From dd34d29a4646586e805c325a8ccad89d95487e9f Mon Sep 17 00:00:00 2001 From: Gary Adams Date: Fri, 4 May 2018 17:52:10 -0400 Subject: [PATCH 01/40] 8202319: Fix compilation warnings in Solaris debug builds for DevStudio 12.6 Disable warnings. Reviewed-by: dholmes, kbarrett --- src/hotspot/share/runtime/frame.cpp | 3 +++ src/hotspot/share/utilities/vmError.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 7a806670f46..6f15e42253b 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -1103,6 +1103,9 @@ void frame::oops_entry_do(OopClosure* f, const RegisterMap* map) { void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) { #ifndef PRODUCT +#if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 +#pragma error_messages(off, SEC_NULL_PTR_DEREF) +#endif // simulate GC crash here to dump java thread in error report if (CrashGCForDumpingJavaThread) { char *t = NULL; diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index ab65ef91431..7a7d240c280 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1620,6 +1620,9 @@ bool VMError::check_timeout() { } #ifndef PRODUCT +#if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 +#pragma error_messages(off, SEC_NULL_PTR_DEREF) +#endif typedef void (*voidfun_t)(); // Crash with an authentic sigfpe static void crash_with_sigfpe() { From 3ecce1fe48bbbb1146c8ae802c00f25466665c49 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 4 May 2018 16:49:22 -0700 Subject: [PATCH 02/40] 8202465: [C1] casts should not be eliminated for interface types Reviewed-by: jrose, thartmann --- src/hotspot/share/c1/c1_Canonicalizer.cpp | 18 ++- test/jdk/java/lang/invoke/I4Special.jcod | 106 ------------------ .../lang/invoke/SpecialInterfaceCall.java | 8 +- .../lang/invoke/SpecialInterfaceCallI4.jasm | 41 +++++++ 4 files changed, 57 insertions(+), 116 deletions(-) delete mode 100644 test/jdk/java/lang/invoke/I4Special.jcod create mode 100644 test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm diff --git a/src/hotspot/share/c1/c1_Canonicalizer.cpp b/src/hotspot/share/c1/c1_Canonicalizer.cpp index 78cf3f4e59c..267d2101386 100644 --- a/src/hotspot/share/c1/c1_Canonicalizer.cpp +++ b/src/hotspot/share/c1/c1_Canonicalizer.cpp @@ -648,13 +648,21 @@ void Canonicalizer::do_NewTypeArray (NewTypeArray* x) {} void Canonicalizer::do_NewObjectArray (NewObjectArray* x) {} void Canonicalizer::do_NewMultiArray (NewMultiArray* x) {} void Canonicalizer::do_CheckCast (CheckCast* x) { - if (x->klass()->is_loaded() && !x->is_invokespecial_receiver_check()) { + if (x->klass()->is_loaded()) { Value obj = x->obj(); ciType* klass = obj->exact_type(); - if (klass == NULL) klass = obj->declared_type(); - if (klass != NULL && klass->is_loaded() && klass->is_subtype_of(x->klass())) { - set_canonical(obj); - return; + if (klass == NULL) { + klass = obj->declared_type(); + } + if (klass != NULL && klass->is_loaded()) { + bool is_interface = klass->is_instance_klass() && + klass->as_instance_klass()->is_interface(); + // Interface casts can't be statically optimized away since verifier doesn't + // enforce interface types in bytecode. + if (!is_interface && klass->is_subtype_of(x->klass())) { + set_canonical(obj); + return; + } } // checkcast of null returns null if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) { diff --git a/test/jdk/java/lang/invoke/I4Special.jcod b/test/jdk/java/lang/invoke/I4Special.jcod deleted file mode 100644 index a54aa5d753f..00000000000 --- a/test/jdk/java/lang/invoke/I4Special.jcod +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2018, 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. - */ - -// invokeDirect is modified to use invokespecial instead of invokevirtual - -class SpecialInterfaceCall$I4 { - 0xCAFEBABE; - 0; // minor version - 55; // version - [] { // Constant Pool - ; // first element is empty - Method #3 #13; // #1 - class #15; // #2 - class #16; // #3 - class #17; // #4 - Utf8 "invokeDirect"; // #5 - Utf8 "I4"; // #6 - Utf8 "InnerClasses"; // #7 - Utf8 "(LSpecialInterfaceCall$I4;)V"; // #8 - Utf8 "Code"; // #9 - Utf8 "LineNumberTable"; // #10 - Utf8 "SourceFile"; // #11 - Utf8 "SpecialInterfaceCall.java"; // #12 - NameAndType #19 #20; // #13 - class #21; // #14 - Utf8 "SpecialInterfaceCall$I4"; // #15 - Utf8 "java/lang/Object"; // #16 - Utf8 "SpecialInterfaceCall$I1"; // #17 - Utf8 "I1"; // #18 - Utf8 "toString"; // #19 - Utf8 "()Ljava/lang/String;"; // #20 - Utf8 "SpecialInterfaceCall"; // #21 - } // Constant Pool - - 0x0600; // access - #2;// this_cpx - #3;// super_cpx - - [] { // Interfaces - #4; - } // Interfaces - - [] { // fields - } // fields - - [] { // methods - { // Member - 0x0009; // access - #5; // name_cpx - #8; // sig_cpx - [] { // Attributes - Attr(#9) { // Code - 1; // max_stack - 2; // max_locals - Bytes[]{ -// 0x2AB600014CB1; - 0x2AB700014CB1; // invokespecial - }; - [] { // Traps - } // end Traps - [] { // Attributes - Attr(#10) { // LineNumberTable - [] { // LineNumberTable - 0 77; - 5 78; - } - } // end LineNumberTable - } // Attributes - } // end Code - } // Attributes - } // Member - } // methods - - [] { // Attributes - Attr(#11) { // SourceFile - #12; - } // end SourceFile - ; - Attr(#7) { // InnerClasses - [] { // InnerClasses - #2 #14 #6 1544; - #4 #14 #18 1544; - } - } // end InnerClasses - } // Attributes -} // end class SpecialInterfaceCall$I4 diff --git a/test/jdk/java/lang/invoke/SpecialInterfaceCall.java b/test/jdk/java/lang/invoke/SpecialInterfaceCall.java index e651845344b..8337aa72a87 100644 --- a/test/jdk/java/lang/invoke/SpecialInterfaceCall.java +++ b/test/jdk/java/lang/invoke/SpecialInterfaceCall.java @@ -26,11 +26,9 @@ * @bug 8200167 * @summary Test direct and MethodHandle access to interface methods using invokespecial semantics * @compile SpecialInterfaceCall.java - * @compile I4Special.jcod + * @compile SpecialInterfaceCallI4.jasm * @run main/othervm -Xint SpecialInterfaceCall * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 SpecialInterfaceCall - * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=2 SpecialInterfaceCall - * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=3 SpecialInterfaceCall * @run main/othervm -Xbatch -XX:-TieredCompilation SpecialInterfaceCall */ @@ -74,9 +72,10 @@ public class SpecialInterfaceCall { } // This interface acts like I2 but we define a directInvoke method // that we will rewrite the bytecode of to use invokespecial + // (see SpecialInterfaceCallI4.jasm). interface I4 extends I1 { static void invokeDirect(I4 i) { - String s = i.toString(); + throw new Error("Class file for I4 is not overwritten"); } } @@ -250,5 +249,4 @@ public class SpecialInterfaceCall { throw new Error(e); } } - } diff --git a/test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm b/test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm new file mode 100644 index 00000000000..87b60307a30 --- /dev/null +++ b/test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, 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. + */ + +// invokeDirect is modified to use invokespecial instead of invokevirtual + +interface SpecialInterfaceCall$I4 implements SpecialInterfaceCall$I1 + version 55:0 +{ + public static Method invokeDirect:"(LSpecialInterfaceCall$I4;)V" + stack 1 locals 2 + { + aload_0; + invokespecial Method java/lang/Object.toString:"()Ljava/lang/String;"; + astore_1; + return; + } + + static abstract interface InnerClass I4=class SpecialInterfaceCall$I4 of class SpecialInterfaceCall; + static abstract interface InnerClass I1=class SpecialInterfaceCall$I1 of class SpecialInterfaceCall; + +} // end Class SpecialInterfaceCall$I4 From 1e0c45b2500cd771b0bd0c777c3b6c9dc1bed564 Mon Sep 17 00:00:00 2001 From: Michal Vala Date: Fri, 4 May 2018 23:19:10 -0700 Subject: [PATCH 03/40] 8199912: jshell tool: /open from URI Reviewed-by: rfield --- .../jdk/internal/jshell/tool/JShellTool.java | 24 +++++++--- test/langtools/jdk/jshell/ToolBasicTest.java | 48 ++++++++++++++++++- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 79e56566a93..4f4bbff438e 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -40,6 +40,9 @@ import java.io.StringReader; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; import java.nio.charset.Charset; import java.nio.file.FileSystems; import java.nio.file.Files; @@ -2999,13 +3002,22 @@ public class JShellTool implements MessageHandler { } else { Path path = toPathResolvingUserHome(filename); String resource; - scanner = new Scanner( - (!Files.exists(path) && (resource = getResource(filename)) != null) - ? new StringReader(resource) // Not found as file, but found as resource - : new FileReader(path.toString()) - ); + if (Files.exists(path)) { + scanner = new Scanner(new FileReader(path.toString())); + } else if ((resource = getResource(filename)) != null) { + scanner = new Scanner(new StringReader(resource)); + } else { + try { + var url = new URL(filename); + scanner = new Scanner(url.openStream()); + } catch (MalformedURLException mue) { + throw new FileNotFoundException(filename); + } + } + } + try (var scannerIOContext = new ScannerIOContext(scanner)) { + run(scannerIOContext); } - run(new ScannerIOContext(scanner)); return true; } catch (FileNotFoundException e) { errormsg("jshell.err.file.not.found", context, filename, e.getMessage()); diff --git a/test/langtools/jdk/jshell/ToolBasicTest.java b/test/langtools/jdk/jshell/ToolBasicTest.java index 096c3c02024..0789e399908 100644 --- a/test/langtools/jdk/jshell/ToolBasicTest.java +++ b/test/langtools/jdk/jshell/ToolBasicTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162 8172102 8165405 8174796 8174797 8175304 8167554 8180508 8166232 8196133 + * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162 8172102 8165405 8174796 8174797 8175304 8167554 8180508 8166232 8196133 8199912 * @summary Tests for Basic tests for REPL tool * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -39,6 +39,8 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -52,6 +54,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.sun.net.httpserver.HttpServer; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; @@ -491,6 +494,49 @@ public class ToolBasicTest extends ReplToolTesting { } } + public void testOpenLocalFileUrl() { + Compiler compiler = new Compiler(); + Path path = compiler.getPath("testOpen.repl"); + compiler.writeToFile(path, "int a = 10;int b = 20;int c = a + b;\n"); + for (String s : new String[]{"/o", "/open"}) { + test( + (a) -> assertCommand(a, s + " file://" + path.toString(), ""), + (a) -> assertCommand(a, "a", "a ==> 10"), + (a) -> assertCommand(a, "b", "b ==> 20"), + (a) -> assertCommand(a, "c", "c ==> 30") + ); + } + } + + public void testOpenFileOverHttp() throws IOException { + var script = "int a = 10;int b = 20;int c = a + b;"; + + var localhostAddress = new InetSocketAddress(InetAddress.getLocalHost().getHostAddress(), 0); + var httpServer = HttpServer.create(localhostAddress, 0); + try { + httpServer.createContext("/script", exchange -> { + exchange.sendResponseHeaders(200, script.length()); + try (var output = exchange.getResponseBody()) { + output.write(script.getBytes()); + } + }); + httpServer.setExecutor(null); + httpServer.start(); + + var urlAddress = "http:/" + httpServer.getAddress().toString() + "/script"; + for (String s : new String[]{"/o", "/open"}) { + test( + (a) -> assertCommand(a, s + " " + urlAddress, ""), + (a) -> assertCommand(a, "a", "a ==> 10"), + (a) -> assertCommand(a, "b", "b ==> 20"), + (a) -> assertCommand(a, "c", "c ==> 30") + ); + } + } finally { + httpServer.stop(0); + } + } + public void testOpenResource() { test( (a) -> assertCommand(a, "/open PRINTING", ""), From e48cfc709dbd811ded123e61fbbb2c74e79a7ca1 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Sat, 5 May 2018 09:24:29 -0700 Subject: [PATCH 04/40] 8199382: [TESTBUG] Open source VM testbase JDI tests Reviewed-by: erikj, kvn, sspitsyn --- make/test/JtregNativeHotspot.gmk | 24 + test/hotspot/jtreg/ProblemList-graal.txt | 51 + test/hotspot/jtreg/ProblemList.txt | 14 + test/hotspot/jtreg/TEST.groups | 561 +++++++++ .../_itself_/awevent001.java | 425 +++++++ .../_itself_/awevent001/TestDescription.java | 73 ++ .../_itself_/awevent001t.java | 114 ++ .../isPackagePrivate/accipp001.java | 180 +++ .../accipp001/TestDescription.java | 68 ++ .../isPackagePrivate/accipp001a.java | 83 ++ .../isPackagePrivate/accipp002.java | 132 ++ .../accipp002/TestDescription.java | 63 + .../isPackagePrivate/accipp002a.java | 105 ++ .../Accessible/isPrivate/isPrivate001.java | 233 ++++ .../isPrivate001/TestDescription.java | 61 + .../Accessible/isPrivate/isPrivate001a.java | 125 ++ .../Accessible/isPrivate/isprivate002.java | 132 ++ .../isprivate002/TestDescription.java | 63 + .../Accessible/isPrivate/isprivate002a.java | 95 ++ .../isProtected/isProtected001.java | 236 ++++ .../isProtected001/TestDescription.java | 60 + .../isProtected/isProtected001a.java | 125 ++ .../isProtected/isprotected002.java | 132 ++ .../isprotected002/TestDescription.java | 63 + .../isProtected/isprotected002a.java | 104 ++ .../jdi/Accessible/isPublic/isPublic001.java | 236 ++++ .../isPublic/isPublic001/TestDescription.java | 60 + .../jdi/Accessible/isPublic/isPublic001a.java | 124 ++ .../jdi/Accessible/isPublic/ispublic002.java | 146 +++ .../isPublic/ispublic002/TestDescription.java | 66 + .../jdi/Accessible/isPublic/ispublic002a.java | 110 ++ .../jdi/Accessible/isPublic/ispublic003.java | 132 ++ .../isPublic/ispublic003/TestDescription.java | 63 + .../jdi/Accessible/isPublic/ispublic003a.java | 105 ++ .../Accessible/modifiers/modifiers001.java | 245 ++++ .../modifiers001/TestDescription.java | 61 + .../Accessible/modifiers/modifiers001a.java | 125 ++ .../Accessible/modifiers/modifiers002.java | 160 +++ .../modifiers002/TestDescription.java | 71 ++ .../Accessible/modifiers/modifiers002a.java | 106 ++ .../Argument/description/description001.java | 105 ++ .../description001/TestDescription.java | 55 + .../nsk/jdi/Argument/isValid/isvalid001.java | 160 +++ .../isValid/isvalid001/TestDescription.java | 78 ++ .../nsk/jdi/Argument/isValid/isvalid002.java | 136 +++ .../isValid/isvalid002/TestDescription.java | 80 ++ .../nsk/jdi/Argument/isValid/isvalid003.java | 150 +++ .../isValid/isvalid003/TestDescription.java | 71 ++ .../nsk/jdi/Argument/isValid/isvalid004.java | 187 +++ .../isValid/isvalid004/TestDescription.java | 91 ++ .../nsk/jdi/Argument/isValid/isvalid005.java | 168 +++ .../isValid/isvalid005/TestDescription.java | 76 ++ .../nsk/jdi/Argument/label/label001.java | 106 ++ .../label/label001/TestDescription.java | 55 + .../Argument/mustSpecify/mustspecify001.java | 132 ++ .../mustspecify001/TestDescription.java | 55 + .../nsk/jdi/Argument/name/name001.java | 115 ++ .../name/name001/TestDescription.java | 54 + .../jdi/Argument/setValue/setvalue001.java | 132 ++ .../setValue/setvalue001/TestDescription.java | 76 ++ .../jdi/Argument/setValue/setvalue002.java | 143 +++ .../setValue/setvalue002/TestDescription.java | 71 ++ .../nsk/jdi/Argument/value/value001.java | 121 ++ .../value/value001/TestDescription.java | 54 + .../nsk/jdi/Argument/value/value002.java | 98 ++ .../value/value002/TestDescription.java | 54 + .../nsk/jdi/Argument/value/value003.java | 214 ++++ .../value/value003/TestDescription.java | 66 + .../nsk/jdi/Argument/value/value003a.java | 33 + .../nsk/jdi/Argument/value/value004.java | 220 ++++ .../value/value004/TestDescription.java | 71 ++ .../nsk/jdi/Argument/value/value004a.java | 57 + .../ArrayReference/getValue/getvalue001.java | 568 +++++++++ .../getValue/getvalue001/TestDescription.java | 71 ++ .../ArrayReference/getValue/getvalue001a.java | 75 ++ .../ArrayReference/getValue/getvalue002.java | 207 ++++ .../getValue/getvalue002/TestDescription.java | 69 ++ .../ArrayReference/getValue/getvalue002a.java | 71 ++ .../ArrayReference/getValue/getvalue003.java | 283 +++++ .../getValue/getvalue003/TestDescription.java | 81 ++ .../ArrayReference/getValue/getvalue003a.java | 101 ++ .../getValues/getvalues001.java | 453 +++++++ .../getvalues001/TestDescription.java | 71 ++ .../getValues/getvalues001a.java | 75 ++ .../getValues/getvalues002.java | 177 +++ .../getvalues002/TestDescription.java | 70 ++ .../getValues/getvalues002a.java | 71 ++ .../getValues/getvalues003.java | 236 ++++ .../getvalues003/TestDescription.java | 71 ++ .../getValues/getvalues003a.java | 87 ++ .../getValues_ii/getvaluesii001.java | 679 +++++++++++ .../getvaluesii001/TestDescription.java | 76 ++ .../getValues_ii/getvaluesii001a.java | 97 ++ .../getValues_ii/getvaluesii002.java | 694 +++++++++++ .../getvaluesii002/TestDescription.java | 77 ++ .../getValues_ii/getvaluesii002a.java | 116 ++ .../getValues_ii/getvaluesii003.java | 209 ++++ .../getvaluesii003/TestDescription.java | 73 ++ .../getValues_ii/getvaluesii003a.java | 71 ++ .../getValues_ii/getvaluesii004.java | 211 ++++ .../getvaluesii004/TestDescription.java | 76 ++ .../getValues_ii/getvaluesii004a.java | 71 ++ .../getValues_ii/getvaluesii005.java | 342 ++++++ .../getvaluesii005/TestDescription.java | 95 ++ .../getValues_ii/getvaluesii005a.java | 110 ++ .../jdi/ArrayReference/length/length001.java | 227 ++++ .../length/length001/TestDescription.java | 71 ++ .../jdi/ArrayReference/length/length001a.java | 103 ++ .../ArrayReference/setValue/setvalue001.java | 589 +++++++++ .../setValue/setvalue001/TestDescription.java | 86 ++ .../ArrayReference/setValue/setvalue001a.java | 109 ++ .../ArrayReference/setValue/setvalue002.java | 362 ++++++ .../setValue/setvalue002/TestDescription.java | 85 ++ .../ArrayReference/setValue/setvalue002a.java | 83 ++ .../ArrayReference/setValue/setvalue003.java | 331 +++++ .../setValue/setvalue003/TestDescription.java | 96 ++ .../ArrayReference/setValue/setvalue003a.java | 117 ++ .../setValues_ilii/setvaluesilii001.java | 874 ++++++++++++++ .../setvaluesilii001/TestDescription.java | 92 ++ .../setValues_ilii/setvaluesilii001a.java | 104 ++ .../setValues_ilii/setvaluesilii002.java | 879 ++++++++++++++ .../setvaluesilii002/TestDescription.java | 91 ++ .../setValues_ilii/setvaluesilii002a.java | 104 ++ .../setValues_ilii/setvaluesilii003.java | 415 +++++++ .../setvaluesilii003/TestDescription.java | 98 ++ .../setValues_ilii/setvaluesilii003a.java | 92 ++ .../setValues_ilii/setvaluesilii004.java | 415 +++++++ .../setvaluesilii004/TestDescription.java | 88 ++ .../setValues_ilii/setvaluesilii004a.java | 90 ++ .../setValues_ilii/setvaluesilii005.java | 416 +++++++ .../setvaluesilii005/TestDescription.java | 89 ++ .../setValues_ilii/setvaluesilii005a.java | 90 ++ .../setValues_l/setvaluesl001.java | 669 ++++++++++ .../setvaluesl001/TestDescription.java | 90 ++ .../setValues_l/setvaluesl001a.java | 91 ++ .../setValues_l/setvaluesl002.java | 669 ++++++++++ .../setvaluesl002/TestDescription.java | 97 ++ .../setValues_l/setvaluesl002a.java | 92 ++ .../setValues_l/setvaluesl003.java | 364 ++++++ .../setvaluesl003/TestDescription.java | 99 ++ .../setValues_l/setvaluesl003a.java | 168 +++ .../componentsignature001.java | 316 +++++ .../TestDescription.java | 77 ++ .../componentsignature001a.java | 122 ++ .../componentsignature002.java | 311 +++++ .../TestDescription.java | 77 ++ .../componentsignature002a.java | 168 +++ .../componentType/componenttype001.java | 296 +++++ .../componenttype001/TestDescription.java | 81 ++ .../componentType/componenttype001a.java | 169 +++ .../componenttypename001.java | 316 +++++ .../componenttypename001/TestDescription.java | 72 ++ .../componenttypename001a.java | 122 ++ .../componenttypename002.java | 303 +++++ .../componenttypename002/TestDescription.java | 73 ++ .../componenttypename002a.java | 169 +++ .../ArrayType/newInstance/newinstance001.java | 381 ++++++ .../newinstance001/TestDescription.java | 78 ++ .../newInstance/newinstance001a.java | 122 ++ .../ArrayType/newInstance/newinstance002.java | 254 ++++ .../newinstance002/TestDescription.java | 78 ++ .../newInstance/newinstance002a.java | 123 ++ .../ArrayType/newInstance/newinstance003.java | 251 ++++ .../newinstance003/TestDescription.java | 78 ++ .../newInstance/newinstance003a.java | 137 +++ .../ArrayType/newInstance/newinstance004.java | 252 ++++ .../newinstance004/TestDescription.java | 78 ++ .../newInstance/newinstance004a.java | 146 +++ .../AttachingConnector/attach/attach001.java | 212 ++++ .../attach/attach001/TestDescription.java | 60 + .../AttachingConnector/attach/attach001t.java | 32 + .../AttachingConnector/attach/attach002.java | 208 ++++ .../attach/attach002/TestDescription.java | 62 + .../AttachingConnector/attach/attach002t.java | 32 + .../AttachingConnector/attach/attach003.java | 144 +++ .../attach/attach003/TestDescription.java | 79 ++ .../attach/attach004/TestDescription.java | 46 + .../attach/attach004/TestDriver.java | 183 +++ .../attach/attach004/attach004.java | 179 +++ .../attach/attach004/attach004t.java | 135 +++ .../attach/attach005/TestDescription.java | 46 + .../attachnosuspend/attachnosuspend001.java | 212 ++++ .../attachnosuspend001/TestDescription.java | 55 + .../attachnosuspend/attachnosuspend001t.java | 39 + .../attachnosuspend002/TestDescription.java | 44 + .../attachnosuspend003/TestDescription.java | 44 + .../nsk/jdi/BScenarios/hotswap/tc01x001.java | 284 +++++ .../hotswap/tc01x001/TestDescription.java | 88 ++ .../hotswap/tc01x001/newclass/tc01x001a.java | 71 ++ .../nsk/jdi/BScenarios/hotswap/tc01x001a.java | 71 ++ .../nsk/jdi/BScenarios/hotswap/tc01x002.java | 295 +++++ .../hotswap/tc01x002/TestDescription.java | 89 ++ .../hotswap/tc01x002/newclass/tc01x002a.java | 71 ++ .../nsk/jdi/BScenarios/hotswap/tc01x002a.java | 71 ++ .../nsk/jdi/BScenarios/hotswap/tc02x001.java | 339 ++++++ .../hotswap/tc02x001/TestDescription.java | 93 ++ .../hotswap/tc02x001/newclass/tc02x001a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc02x001a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc02x002.java | 347 ++++++ .../hotswap/tc02x002/TestDescription.java | 92 ++ .../hotswap/tc02x002/newclass/tc02x002a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc02x002a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc03x001.java | 282 +++++ .../hotswap/tc03x001/TestDescription.java | 80 ++ .../hotswap/tc03x001/newclass/tc03x001a.java | 71 ++ .../nsk/jdi/BScenarios/hotswap/tc03x001a.java | 71 ++ .../nsk/jdi/BScenarios/hotswap/tc04x001.java | 346 ++++++ .../hotswap/tc04x001/TestDescription.java | 93 ++ .../hotswap/tc04x001/newclass/tc04x001a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc04x001a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc04x002.java | 354 ++++++ .../hotswap/tc04x002/TestDescription.java | 92 ++ .../hotswap/tc04x002/newclass/tc04x002a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc04x002a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc05x001.java | 277 +++++ .../hotswap/tc05x001/TestDescription.java | 89 ++ .../hotswap/tc05x001/newclass/tc05x001a.java | 85 ++ .../nsk/jdi/BScenarios/hotswap/tc05x001a.java | 86 ++ .../nsk/jdi/BScenarios/hotswap/tc05x002.java | 317 +++++ .../hotswap/tc05x002/TestDescription.java | 90 ++ .../hotswap/tc05x002/newclass/tc05x002a.java | 73 ++ .../nsk/jdi/BScenarios/hotswap/tc05x002a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc06x001.java | 361 ++++++ .../hotswap/tc06x001/TestDescription.java | 95 ++ .../hotswap/tc06x001/newclass/tc06x001a.java | 73 ++ .../nsk/jdi/BScenarios/hotswap/tc06x001a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc07x001.java | 342 ++++++ .../hotswap/tc07x001/TestDescription.java | 90 ++ .../hotswap/tc07x001/newclass/tc07x001a.java | 73 ++ .../nsk/jdi/BScenarios/hotswap/tc07x001a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc08x001.java | 353 ++++++ .../hotswap/tc08x001/TestDescription.java | 88 ++ .../hotswap/tc08x001/newclass/tc08x001a.java | 73 ++ .../nsk/jdi/BScenarios/hotswap/tc08x001a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc09x001.java | 302 +++++ .../hotswap/tc09x001/TestDescription.java | 88 ++ .../hotswap/tc09x001/newclass/tc09x001a.java | 71 ++ .../nsk/jdi/BScenarios/hotswap/tc09x001a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc09x002.java | 326 +++++ .../hotswap/tc09x002/TestDescription.java | 89 ++ .../hotswap/tc09x002/newclass/tc09x002a.java | 71 ++ .../nsk/jdi/BScenarios/hotswap/tc09x002a.java | 72 ++ .../nsk/jdi/BScenarios/hotswap/tc10x001.java | 305 +++++ .../hotswap/tc10x001/TestDescription.java | 93 ++ .../hotswap/tc10x001/newclass/tc10x001a.java | 73 ++ .../nsk/jdi/BScenarios/hotswap/tc10x001a.java | 74 ++ .../nsk/jdi/BScenarios/hotswap/tc10x002.java | 347 ++++++ .../hotswap/tc10x002/TestDescription.java | 96 ++ .../hotswap/tc10x002/newclass/tc10x002a.java | 78 ++ .../nsk/jdi/BScenarios/hotswap/tc10x002a.java | 78 ++ .../jdi/BScenarios/multithrd/tc01x001.java | 253 ++++ .../multithrd/tc01x001/TestDescription.java | 75 ++ .../jdi/BScenarios/multithrd/tc01x001a.java | 103 ++ .../jdi/BScenarios/multithrd/tc02x001.java | 219 ++++ .../multithrd/tc02x001/TestDescription.java | 82 ++ .../jdi/BScenarios/multithrd/tc02x001a.java | 97 ++ .../jdi/BScenarios/multithrd/tc02x002.java | 237 ++++ .../multithrd/tc02x002/TestDescription.java | 91 ++ .../jdi/BScenarios/multithrd/tc02x002a.java | 102 ++ .../jdi/BScenarios/multithrd/tc02x003.java | 248 ++++ .../multithrd/tc02x003/TestDescription.java | 91 ++ .../jdi/BScenarios/multithrd/tc02x003a.java | 102 ++ .../jdi/BScenarios/multithrd/tc02x004.java | 227 ++++ .../multithrd/tc02x004/TestDescription.java | 84 ++ .../jdi/BScenarios/multithrd/tc02x004a.java | 83 ++ .../jdi/BScenarios/multithrd/tc03x001.java | 233 ++++ .../multithrd/tc03x001/TestDescription.java | 78 ++ .../jdi/BScenarios/multithrd/tc03x001a.java | 100 ++ .../jdi/BScenarios/multithrd/tc04x001.java | 225 ++++ .../multithrd/tc04x001/TestDescription.java | 69 ++ .../jdi/BScenarios/multithrd/tc04x001a.java | 91 ++ .../jdi/BScenarios/singlethrd/tc01x001.java | 240 ++++ .../singlethrd/tc01x001/TestDescription.java | 72 ++ .../jdi/BScenarios/singlethrd/tc01x001a.java | 79 ++ .../jdi/BScenarios/singlethrd/tc01x002.java | 246 ++++ .../singlethrd/tc01x002/TestDescription.java | 68 ++ .../jdi/BScenarios/singlethrd/tc01x002a.java | 79 ++ .../jdi/BScenarios/singlethrd/tc02x001.java | 238 ++++ .../singlethrd/tc02x001/TestDescription.java | 71 ++ .../jdi/BScenarios/singlethrd/tc02x001a.java | 80 ++ .../jdi/BScenarios/singlethrd/tc03x001.java | 222 ++++ .../singlethrd/tc03x001/TestDescription.java | 81 ++ .../jdi/BScenarios/singlethrd/tc03x001a.java | 80 ++ .../jdi/BScenarios/singlethrd/tc03x002.java | 237 ++++ .../singlethrd/tc03x002/TestDescription.java | 89 ++ .../jdi/BScenarios/singlethrd/tc03x002a.java | 81 ++ .../jdi/BScenarios/singlethrd/tc03x003.java | 248 ++++ .../singlethrd/tc03x003/TestDescription.java | 89 ++ .../jdi/BScenarios/singlethrd/tc03x003a.java | 81 ++ .../jdi/BScenarios/singlethrd/tc04x001.java | 238 ++++ .../singlethrd/tc04x001/TestDescription.java | 78 ++ .../jdi/BScenarios/singlethrd/tc04x001a.java | 77 ++ .../jdi/BScenarios/singlethrd/tc05x001.java | 230 ++++ .../singlethrd/tc05x001/TestDescription.java | 81 ++ .../jdi/BScenarios/singlethrd/tc05x001a.java | 85 ++ .../booleanValue/booleanvalue001.java | 200 +++ .../booleanvalue001/TestDescription.java | 95 ++ .../booleanValue/booleanvalue002.java | 211 ++++ .../booleanvalue002/TestDescription.java | 83 ++ .../BooleanArgument/isValid/isvalid001.java | 155 +++ .../isValid/isvalid001/TestDescription.java | 78 ++ .../BooleanArgument/isValid/isvalid002.java | 130 ++ .../isValid/isvalid002/TestDescription.java | 75 ++ .../BooleanArgument/setValue/setvalue001.java | 186 +++ .../setValue/setvalue001/TestDescription.java | 70 ++ .../BooleanArgument/setValue/setvalue002.java | 146 +++ .../setValue/setvalue002/TestDescription.java | 67 ++ .../stringValueOf/stringvalueof001.java | 150 +++ .../stringvalueof001/TestDescription.java | 77 ++ .../stringValueOf/stringvalueof002.java | 167 +++ .../stringvalueof002/TestDescription.java | 89 ++ .../BooleanType/_itself_/booleantype001.java | 455 +++++++ .../booleantype001/TestDescription.java | 66 + .../BooleanType/_itself_/booleantype001a.java | 113 ++ .../jdi/BooleanValue/equals/equals001.java | 265 ++++ .../equals/equals001/TestDescription.java | 75 ++ .../jdi/BooleanValue/equals/equals001a.java | 119 ++ .../jdi/BooleanValue/equals/equals002.java | 213 ++++ .../equals/equals002/TestDescription.java | 66 + .../jdi/BooleanValue/equals/equals002a.java | 102 ++ .../BooleanValue/hashCode/hashcode001.java | 257 ++++ .../hashCode/hashcode001/TestDescription.java | 71 ++ .../BooleanValue/hashCode/hashcode001a.java | 119 ++ .../nsk/jdi/BooleanValue/value/value001.java | 238 ++++ .../value/value001/TestDescription.java | 71 ++ .../nsk/jdi/BooleanValue/value/value001a.java | 122 ++ .../_itself_/breakpoint001.java | 371 ++++++ .../breakpoint001/TestDescription.java | 93 ++ .../_itself_/breakpoint001a.java | 89 ++ .../_itself_/breakpoint002.java | 404 +++++++ .../breakpoint002/TestDescription.java | 67 ++ .../_itself_/breakpoint002t.java | 87 ++ .../_bounds_/filters001.java | 138 +++ .../_bounds_/filters001/TestDescription.java | 60 + .../_bounds_/filters001a.java | 80 ++ .../addInstanceFilter/instancefilter001.java | 204 ++++ .../instancefilter001/TestDescription.java | 83 ++ .../addInstanceFilter/instancefilter001a.java | 196 +++ .../addInstanceFilter/instancefilter002.java | 559 +++++++++ .../instancefilter002/TestDescription.java | 83 ++ .../addInstanceFilter/instancefilter002a.java | 183 +++ .../addInstanceFilter/instancefilter003.java | 526 ++++++++ .../instancefilter003/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter003a.java | 183 +++ .../addInstanceFilter/instancefilter004.java | 210 ++++ .../instancefilter004/TestDescription.java | 92 ++ .../addInstanceFilter/instancefilter004a.java | 196 +++ .../addThreadFilter/threadfilter001.java | 166 +++ .../threadfilter001/TestDescription.java | 76 ++ .../addThreadFilter/threadfilter001a.java | 195 +++ .../addThreadFilter/threadfilter002.java | 545 +++++++++ .../threadfilter002/TestDescription.java | 76 ++ .../addThreadFilter/threadfilter002a.java | 185 +++ .../addThreadFilter/threadfilter003.java | 554 +++++++++ .../threadfilter003/TestDescription.java | 75 ++ .../addThreadFilter/threadfilter003a.java | 188 +++ .../addThreadFilter/threadfilter004.java | 196 +++ .../threadfilter004/TestDescription.java | 84 ++ .../addThreadFilter/threadfilter004a.java | 199 +++ .../location/location001.java | 519 ++++++++ .../location/location001/TestDescription.java | 73 ++ .../location/location001a.java | 185 +++ .../jdi/ByteType/_itself_/bytetype001.java | 456 +++++++ .../_itself_/bytetype001/TestDescription.java | 66 + .../jdi/ByteType/_itself_/bytetype001a.java | 113 ++ .../jdi/ByteValue/compareTo/compareto001.java | 296 +++++ .../compareto001/TestDescription.java | 70 ++ .../ByteValue/compareTo/compareto001a.java | 175 +++ .../nsk/jdi/ByteValue/equals/equals001.java | 247 ++++ .../equals/equals001/TestDescription.java | 73 ++ .../nsk/jdi/ByteValue/equals/equals001a.java | 126 ++ .../nsk/jdi/ByteValue/equals/equals002.java | 212 ++++ .../equals/equals002/TestDescription.java | 66 + .../nsk/jdi/ByteValue/equals/equals002a.java | 142 +++ .../jdi/ByteValue/hashCode/hashcode001.java | 238 ++++ .../hashCode/hashcode001/TestDescription.java | 71 ++ .../jdi/ByteValue/hashCode/hashcode001a.java | 124 ++ .../nsk/jdi/ByteValue/value/value001.java | 243 ++++ .../value/value001/TestDescription.java | 71 ++ .../nsk/jdi/ByteValue/value/value001a.java | 125 ++ .../jdi/CharType/_itself_/chartype001.java | 456 +++++++ .../_itself_/chartype001/TestDescription.java | 66 + .../jdi/CharType/_itself_/chartype001a.java | 113 ++ .../jdi/CharValue/compareTo/compareto001.java | 296 +++++ .../compareto001/TestDescription.java | 70 ++ .../CharValue/compareTo/compareto001a.java | 178 +++ .../nsk/jdi/CharValue/equals/equals001.java | 248 ++++ .../equals/equals001/TestDescription.java | 73 ++ .../nsk/jdi/CharValue/equals/equals001a.java | 123 ++ .../nsk/jdi/CharValue/equals/equals002.java | 212 ++++ .../equals/equals002/TestDescription.java | 66 + .../nsk/jdi/CharValue/equals/equals002a.java | 139 +++ .../jdi/CharValue/hashCode/hashcode001.java | 238 ++++ .../hashCode/hashcode001/TestDescription.java | 71 ++ .../jdi/CharValue/hashCode/hashcode001a.java | 123 ++ .../nsk/jdi/CharValue/value/value001.java | 236 ++++ .../value/value001/TestDescription.java | 71 ++ .../nsk/jdi/CharValue/value/value001a.java | 123 ++ .../definedClasses/definedclasses001.java | 452 +++++++ .../definedclasses001/TestDescription.java | 78 ++ .../definedClasses/definedclasses001a.java | 125 ++ .../definedClasses/definedclasses002.java | 161 +++ .../definedclasses002/TestDescription.java | 66 + .../definedClasses/definedclasses002a.java | 93 ++ .../definedClasses/definedclasses003.java | 174 +++ .../definedclasses003/TestDescription.java | 73 ++ .../loadclass/definedclasses003b.java | 29 + .../loadclass/definedclasses003c.java | 29 + .../definedClasses/definedclasses003a.java | 156 +++ .../definedClasses/definedclasses004.java | 134 +++ .../definedclasses004/TestDescription.java | 66 + .../definedClasses/definedclasses004a.java | 90 ++ .../definedClasses/definedclasses005.java | 164 +++ .../definedclasses005/TestDescription.java | 73 ++ .../loadclass/definedclasses005b.java | 29 + .../definedClasses/definedclasses005a.java | 160 +++ .../visibleClasses/visibleclasses001.java | 499 ++++++++ .../visibleclasses001/TestDescription.java | 100 ++ .../visibleClasses/visibleclasses001a.java | 128 ++ .../visibleClasses/visibleclasses002.java | 161 +++ .../visibleclasses002/TestDescription.java | 66 + .../visibleClasses/visibleclasses002a.java | 93 ++ .../reflectedType/reflectype001.java | 236 ++++ .../reflectype001/TestDescription.java | 64 + .../reflectedType/reflectype001a.java | 117 ++ .../reflectedType/reflectype002.java | 258 ++++ .../reflectype002/TEST.properties | 24 + .../reflectype002/TestDescription.java | 70 ++ .../loadclass/reflectype002b.java | 29 + .../reflectedType/reflectype002a.java | 118 ++ .../toString/tostring001.java | 190 +++ .../toString/tostring001/TestDescription.java | 64 + .../toString/tostring001a.java | 136 +++ .../referenceType/refType001.java | 324 +++++ .../refType001/TestDescription.java | 94 ++ .../referenceType/refType001a.java | 151 +++ .../ClassPrepareEvent/thread/thread001.java | 348 ++++++ .../thread/thread001/TestDescription.java | 91 ++ .../ClassPrepareEvent/thread/thread001a.java | 168 +++ .../_bounds_/filters001.java | 146 +++ .../_bounds_/filters001/TestDescription.java | 57 + .../_bounds_/filters001a.java | 54 + .../addClassExclusionFilter/filter001.java | 149 +++ .../filter001/TestDescription.java | 83 ++ .../addClassExclusionFilter/filter001a.java | 168 +++ .../addClassExclusionFilter/filter002.java | 149 +++ .../filter002/TestDescription.java | 83 ++ .../addClassExclusionFilter/filter002a.java | 168 +++ .../addClassExclusionFilter/filter003.java | 532 ++++++++ .../filter003/TestDescription.java | 80 ++ .../addClassExclusionFilter/filter003a.java | 170 +++ .../addClassFilter_rt/filter_rt001.java | 149 +++ .../filter_rt001/TestDescription.java | 81 ++ .../addClassFilter_rt/filter_rt001a.java | 196 +++ .../addClassFilter_rt/filter_rt002.java | 540 +++++++++ .../filter_rt002/TestDescription.java | 80 ++ .../addClassFilter_rt/filter_rt002a.java | 167 +++ .../addClassFilter_rt/filter_rt003.java | 170 +++ .../filter_rt003/TestDescription.java | 88 ++ .../addClassFilter_rt/filter_rt003a.java | 197 +++ .../addClassFilter_s/filter_s001.java | 189 +++ .../filter_s001/TestDescription.java | 82 ++ .../addClassFilter_s/filter_s001a.java | 192 +++ .../addClassFilter_s/filter_s002.java | 537 +++++++++ .../filter_s002/TestDescription.java | 80 ++ .../addClassFilter_s/filter_s002a.java | 168 +++ .../addSourceNameFilter001/TestClass2.java | 30 + .../addSourceNameFilter001.java | 209 ++++ .../addSourceNameFilter002.java | 245 ++++ .../allInterfaces/allinterfaces001.java | 366 ++++++ .../allinterfaces001/TestDescription.java | 78 ++ .../allInterfaces/allinterfaces001a.java | 265 ++++ .../allInterfaces/allinterfaces002.java | 179 +++ .../allinterfaces002/TestDescription.java | 73 ++ .../allInterfaces/allinterfaces002a.java | 167 +++ .../concreteMethodByName/method001.java | 291 +++++ .../method001/TestDescription.java | 68 ++ .../concreteMethodByName/method001a.java | 238 ++++ .../concreteMethodByName/method002.java | 149 +++ .../method002/TestDescription.java | 54 + .../concreteMethodByName/method002a.java | 54 + .../ClassType/interfaces/interfaces001.java | 287 +++++ .../interfaces001/TestDescription.java | 79 ++ .../ClassType/interfaces/interfaces001a.java | 231 ++++ .../ClassType/interfaces/interfaces002.java | 142 +++ .../interfaces002/TestDescription.java | 67 ++ .../ClassType/interfaces/interfaces002a.java | 106 ++ .../invokeMethod/invokemethod001.java | 577 +++++++++ .../invokemethod001/TestDescription.java | 77 ++ .../invokeMethod/invokemethod001a.java | 276 +++++ .../invokeMethod/invokemethod002.java | 333 +++++ .../invokemethod002/TestDescription.java | 67 ++ .../invokeMethod/invokemethod002a.java | 91 ++ .../invokeMethod/invokemethod003.java | 307 +++++ .../invokemethod003/TestDescription.java | 65 + .../invokeMethod/invokemethod003a.java | 86 ++ .../invokeMethod/invokemethod004.java | 280 +++++ .../invokemethod004/TestDescription.java | 62 + .../invokeMethod/invokemethod004a.java | 71 ++ .../invokeMethod/invokemethod005.java | 258 ++++ .../invokemethod005/TestDescription.java | 61 + .../invokeMethod/invokemethod005a.java | 75 ++ .../invokeMethod/invokemethod006.java | 233 ++++ .../invokemethod006/TestDescription.java | 64 + .../invokeMethod/invokemethod006a.java | 61 + .../invokeMethod/invokemethod007.java | 222 ++++ .../invokemethod007/TestDescription.java | 61 + .../invokeMethod/invokemethod007a.java | 154 +++ .../invokeMethod/invokemethod008.java | 243 ++++ .../invokemethod008/TestDescription.java | 58 + .../invokeMethod/invokemethod008a.java | 78 ++ .../invokeMethod/invokemethod009.java | 303 +++++ .../invokemethod009/TestDescription.java | 59 + .../invokeMethod/invokemethod009t.java | 83 ++ .../invokeMethod/invokemethod010.java | 214 ++++ .../invokemethod010/TestDescription.java | 56 + .../invokeMethod/invokemethod010t.java | 97 ++ .../invokeMethod/invokemethod011.java | 460 +++++++ .../invokemethod011/TestDescription.java | 66 + .../invokeMethod/invokemethod011t.java | 187 +++ .../invokeMethod/invokemethod012.java | 494 ++++++++ .../invokemethod012/TestDescription.java | 64 + .../invokeMethod/invokemethod012t.java | 189 +++ .../invokeMethod/invokemethod013.java | 493 ++++++++ .../invokemethod013/TestDescription.java | 64 + .../invokeMethod/invokemethod013t.java | 189 +++ .../invokeMethod/invokemethod014.java | 292 +++++ .../invokemethod014/TestDescription.java | 54 + .../invokeMethod/invokemethod014t.java | 111 ++ .../invokeMethod/invokemethod015.java | 381 ++++++ .../invokemethod015/TestDescription.java | 70 ++ .../invokeMethod/invokemethod015a.java | 84 ++ .../nsk/jdi/ClassType/isEnum/isenum001.java | 134 +++ .../isEnum/isenum001/TestDescription.java | 65 + .../nsk/jdi/ClassType/isEnum/isenum001a.java | 167 +++ .../ClassType/newInstance/newinstance001.java | 561 +++++++++ .../newinstance001/TestDescription.java | 149 +++ .../newInstance/newinstance001a.java | 236 ++++ .../ClassType/newInstance/newinstance002.java | 550 +++++++++ .../newinstance002/TestDescription.java | 154 +++ .../newInstance/newinstance002a.java | 236 ++++ .../ClassType/newInstance/newinstance003.java | 246 ++++ .../newinstance003/TestDescription.java | 65 + .../newInstance/newinstance003a.java | 74 ++ .../ClassType/newInstance/newinstance004.java | 203 ++++ .../newinstance004/TestDescription.java | 62 + .../newInstance/newinstance004a.java | 71 ++ .../ClassType/newInstance/newinstance005.java | 274 +++++ .../newinstance005/TestDescription.java | 61 + .../newInstance/newinstance005a.java | 79 ++ .../ClassType/newInstance/newinstance006.java | 246 ++++ .../newinstance006/TestDescription.java | 65 + .../newInstance/newinstance006a.java | 61 + .../ClassType/newInstance/newinstance007.java | 233 ++++ .../newinstance007/TestDescription.java | 61 + .../newInstance/newinstance007a.java | 157 +++ .../ClassType/newInstance/newinstance008.java | 294 +++++ .../newinstance008/TestDescription.java | 58 + .../newInstance/newinstance008a.java | 76 ++ .../ClassType/newInstance/newinstance009.java | 201 ++++ .../newinstance009/TestDescription.java | 57 + .../newInstance/newinstance009t.java | 63 + .../jdi/ClassType/setValue/setvalue001.java | 450 +++++++ .../setValue/setvalue001/TestDescription.java | 100 ++ .../jdi/ClassType/setValue/setvalue001a.java | 128 ++ .../jdi/ClassType/setValue/setvalue002.java | 361 ++++++ .../setValue/setvalue002/TestDescription.java | 100 ++ .../jdi/ClassType/setValue/setvalue002a.java | 130 ++ .../jdi/ClassType/setValue/setvalue003.java | 256 ++++ .../setValue/setvalue003/TestDescription.java | 99 ++ .../jdi/ClassType/setValue/setvalue003a.java | 146 +++ .../jdi/ClassType/setValue/setvalue004.java | 281 +++++ .../setValue/setvalue004/TestDescription.java | 100 ++ .../jdi/ClassType/setValue/setvalue004a.java | 124 ++ .../jdi/ClassType/setValue/setvalue005.java | 253 ++++ .../setValue/setvalue005/TestDescription.java | 98 ++ .../jdi/ClassType/setValue/setvalue005a.java | 123 ++ .../jdi/ClassType/setValue/setvalue006.java | 184 +++ .../setValue/setvalue006/TestDescription.java | 64 + .../jdi/ClassType/setValue/setvalue006t.java | 65 + .../jdi/ClassType/setValue/setvalue007.java | 201 ++++ .../setValue/setvalue007/TestDescription.java | 56 + .../jdi/ClassType/setValue/setvalue007t.java | 71 ++ .../jdi/ClassType/setValue/setvalue008.java | 137 +++ .../setValue/setvalue008/TestDescription.java | 64 + .../jdi/ClassType/setValue/setvalue008a.java | 93 ++ .../ClassType/subclasses/subclasses001.java | 280 +++++ .../subclasses001/TestDescription.java | 76 ++ .../ClassType/subclasses/subclasses001a.java | 250 ++++ .../ClassType/subclasses/subclasses002.java | 139 +++ .../subclasses002/TestDescription.java | 69 ++ .../ClassType/subclasses/subclasses002a.java | 113 ++ .../ClassType/superclass/superclass001.java | 280 +++++ .../superclass001/TestDescription.java | 74 ++ .../ClassType/superclass/superclass001a.java | 215 ++++ .../ClassType/superclass/superclass002.java | 133 ++ .../superclass002/TestDescription.java | 66 + .../ClassType/superclass/superclass002a.java | 167 +++ .../className/classname001.java | 325 +++++ .../className/classname001/TEST.properties | 24 + .../classname001/TestDescription.java | 97 ++ .../classname001/loadclass/classname001b.java | 28 + .../className/classname001a.java | 104 ++ .../classSignature/signature001.java | 383 ++++++ .../signature001/TEST.properties | 24 + .../signature001/TestDescription.java | 103 ++ .../signature001/loadclass/signature001b.java | 27 + .../signature001/loadclass/signature001c.java | 32 + .../classSignature/signature001a.java | 152 +++ .../_bounds_/filters001.java | 129 ++ .../_bounds_/filters001/TestDescription.java | 56 + .../_bounds_/filters001a.java | 54 + .../exclfilter001.java | 239 ++++ .../exclfilter001/TEST.properties | 24 + .../exclfilter001/TestDescription.java | 82 ++ .../loadclass/Superexclfilter001b.java | 66 + .../exclfilter001a.java | 119 ++ .../exclfilter002.java | 122 ++ .../exclfilter002/TestDescription.java | 63 + .../exclfilter002a.java | 56 + .../addClassFilter/filter001.java | 238 ++++ .../addClassFilter/filter001/TEST.properties | 24 + .../filter001/TestDescription.java | 80 ++ .../filter001/loadclass/Superfilter001b.java | 66 + .../addClassFilter/filter001a.java | 119 ++ .../addClassFilter/filter002.java | 121 ++ .../filter002/TestDescription.java | 63 + .../addClassFilter/filter002a.java | 56 + .../nsk/jdi/Connector/_bounds_/bounds001.java | 175 +++ .../_bounds_/bounds001/TestDescription.java | 55 + .../jdi/Connector/_bounds_/bounds001a.java | 32 + .../defaultArguments/defaultArguments001.java | 80 ++ .../defaultArguments001/TestDescription.java | 55 + .../defaultArguments/defaultArguments002.java | 113 ++ .../defaultArguments002/TestDescription.java | 55 + .../defaultArguments/defaultArguments003.java | 112 ++ .../defaultArguments003/TestDescription.java | 55 + .../Connector/description/description001.java | 89 ++ .../description001/TestDescription.java | 55 + .../nsk/jdi/Connector/name/name001.java | 86 ++ .../name/name001/TestDescription.java | 54 + .../jdi/Connector/toString/tostring001.java | 112 ++ .../toString/tostring001/TestDescription.java | 56 + .../jdi/Connector/transport/transport001.java | 80 ++ .../transport001/TestDescription.java | 55 + .../nsk/jdi/ConnectorsJarBuilder.java | 116 ++ .../nsk/jdi/ConstantField/values001.java | 220 ++++ .../values001/TestDescription.java | 74 ++ .../DoubleType/_itself_/doubletype001.java | 460 +++++++ .../doubletype001/TestDescription.java | 66 + .../DoubleType/_itself_/doubletype001a.java | 113 ++ .../DoubleValue/compareTo/compareto001.java | 296 +++++ .../compareto001/TestDescription.java | 70 ++ .../DoubleValue/compareTo/compareto001a.java | 175 +++ .../nsk/jdi/DoubleValue/equals/equals001.java | 247 ++++ .../equals/equals001/TestDescription.java | 77 ++ .../jdi/DoubleValue/equals/equals001a.java | 134 +++ .../nsk/jdi/DoubleValue/equals/equals002.java | 212 ++++ .../equals/equals002/TestDescription.java | 66 + .../jdi/DoubleValue/equals/equals002a.java | 142 +++ .../jdi/DoubleValue/hashCode/hashcode001.java | 239 ++++ .../hashCode/hashcode001/TestDescription.java | 75 ++ .../DoubleValue/hashCode/hashcode001a.java | 133 ++ .../nsk/jdi/DoubleValue/value/value001.java | 297 +++++ .../value/value001/TestDescription.java | 75 ++ .../nsk/jdi/DoubleValue/value/value001a.java | 133 ++ .../nsk/jdi/Event/_itself_/event001.java | 385 ++++++ .../_itself_/event001/TestDescription.java | 68 ++ .../nsk/jdi/Event/_itself_/event001t.java | 77 ++ .../nsk/jdi/Event/_itself_/event002.java | 429 +++++++ .../_itself_/event002/TestDescription.java | 69 ++ .../nsk/jdi/Event/_itself_/event002t.java | 107 ++ .../nsk/jdi/Event/equals/equals001.java | 288 +++++ .../equals/equals001/TestDescription.java | 68 ++ .../nsk/jdi/Event/equals/equals001a.java | 153 +++ .../nsk/jdi/Event/hashCode/hashcode001.java | 266 ++++ .../hashCode/hashcode001/TestDescription.java | 75 ++ .../nsk/jdi/Event/hashCode/hashcode001a.java | 153 +++ .../nsk/jdi/Event/request/request001.java | 963 +++++++++++++++ .../request/request001/TestDescription.java | 76 ++ .../nsk/jdi/Event/request/request001a.java | 297 +++++ .../EventIterator/nextEvent/nextevent001.java | 938 +++++++++++++++ .../nextevent001/TestDescription.java | 76 ++ .../nextEvent/nextevent001a.java | 297 +++++ .../jdi/EventQueue/hashCode/hashcode001.java | 139 +++ .../hashCode/hashcode001/TestDescription.java | 64 + .../jdi/EventQueue/hashCode/hashcode001a.java | 87 ++ .../nsk/jdi/EventQueue/remove/remove001.java | 138 +++ .../remove/remove001/TestDescription.java | 54 + .../nsk/jdi/EventQueue/remove/remove001t.java | 45 + .../nsk/jdi/EventQueue/remove/remove002.java | 179 +++ .../remove/remove002/TestDescription.java | 54 + .../nsk/jdi/EventQueue/remove/remove002t.java | 52 + .../nsk/jdi/EventQueue/remove/remove003.java | 179 +++ .../remove/remove003/TestDescription.java | 57 + .../nsk/jdi/EventQueue/remove/remove003t.java | 52 + .../nsk/jdi/EventQueue/remove/remove004.java | 522 ++++++++ .../remove/remove004/TestDescription.java | 78 ++ .../nsk/jdi/EventQueue/remove/remove004a.java | 118 ++ .../jdi/EventQueue/remove_l/remove_l001.java | 142 +++ .../remove_l/remove_l001/TestDescription.java | 56 + .../jdi/EventQueue/remove_l/remove_l001t.java | 45 + .../jdi/EventQueue/remove_l/remove_l002.java | 183 +++ .../remove_l/remove_l002/TestDescription.java | 56 + .../jdi/EventQueue/remove_l/remove_l002t.java | 52 + .../jdi/EventQueue/remove_l/remove_l003.java | 183 +++ .../remove_l/remove_l003/TestDescription.java | 64 + .../jdi/EventQueue/remove_l/remove_l003t.java | 52 + .../jdi/EventQueue/remove_l/remove_l004.java | 453 +++++++ .../remove_l/remove_l004/TestDescription.java | 79 ++ .../jdi/EventQueue/remove_l/remove_l004a.java | 118 ++ .../jdi/EventQueue/remove_l/remove_l005.java | 163 +++ .../remove_l/remove_l005/TestDescription.java | 60 + .../jdi/EventQueue/remove_l/remove_l005a.java | 64 + .../_bounds_/eventrequest001.java | 172 +++ .../eventrequest001/TestDescription.java | 69 ++ .../_bounds_/eventrequest001a.java | 56 + .../addCountFilter/addcountfilter001.java | 590 +++++++++ .../addcountfilter001/TestDescription.java | 89 ++ .../addCountFilter/addcountfilter001a.java | 225 ++++ .../jdi/EventRequest/disable/disable001.java | 548 +++++++++ .../disable/disable001/TestDescription.java | 75 ++ .../jdi/EventRequest/disable/disable001a.java | 225 ++++ .../jdi/EventRequest/disable/disable002.java | 546 +++++++++ .../disable/disable002/TestDescription.java | 76 ++ .../jdi/EventRequest/disable/disable002a.java | 225 ++++ .../jdi/EventRequest/disable/disable003.java | 260 ++++ .../disable/disable003/TestDescription.java | 70 ++ .../disable003/newclass/disable003b.java | 50 + .../jdi/EventRequest/disable/disable003a.java | 52 + .../jdi/EventRequest/disable/disable003b.java | 50 + .../jdi/EventRequest/enable/enable001.java | 544 +++++++++ .../enable/enable001/TestDescription.java | 77 ++ .../jdi/EventRequest/enable/enable001a.java | 225 ++++ .../jdi/EventRequest/enable/enable002.java | 562 +++++++++ .../enable/enable002/TestDescription.java | 80 ++ .../jdi/EventRequest/enable/enable002a.java | 231 ++++ .../getProperty/getproperty001.java | 558 +++++++++ .../getproperty001/TestDescription.java | 78 ++ .../getProperty/getproperty001a.java | 225 ++++ .../EventRequest/hashCode/hashcode001.java | 241 ++++ .../hashCode/hashcode001/TestDescription.java | 61 + .../EventRequest/hashCode/hashcode001a.java | 87 ++ .../EventRequest/isEnabled/isenabled001.java | 552 +++++++++ .../isenabled001/TestDescription.java | 74 ++ .../EventRequest/isEnabled/isenabled001a.java | 225 ++++ .../putProperty/putproperty001.java | 563 +++++++++ .../putproperty001/TestDescription.java | 80 ++ .../putProperty/putproperty001a.java | 225 ++++ .../setEnabled/setenabled001.java | 551 +++++++++ .../setenabled001/TestDescription.java | 83 ++ .../setEnabled/setenabled001a.java | 225 ++++ .../setEnabled/setenabled002.java | 578 +++++++++ .../setenabled002/TestDescription.java | 83 ++ .../setEnabled/setenabled002a.java | 231 ++++ .../setEnabled/setenabled003.java | 527 ++++++++ .../setenabled003/TestDescription.java | 84 ++ .../setEnabled/setenabled003a.java | 180 +++ .../setSuspendPolicy/setsuspendpolicy001.java | 594 +++++++++ .../setsuspendpolicy001/TestDescription.java | 85 ++ .../setsuspendpolicy001a.java | 225 ++++ .../suspendPolicy/suspendpolicy001.java | 567 +++++++++ .../suspendpolicy001/TestDescription.java | 76 ++ .../suspendPolicy/suspendpolicy001a.java | 225 ++++ .../_bounds_/requests001.java | 213 ++++ .../_bounds_/requests001/TestDescription.java | 68 ++ .../_bounds_/requests001a.java | 54 + .../accwtchpreq001.java | 278 +++++ .../accwtchpreq001/TestDescription.java | 65 + .../accwtchpreq001t.java | 69 ++ .../accwtchpreq002.java | 539 +++++++++ .../accwtchpreq002/TestDescription.java | 75 ++ .../accwtchpreq002a.java | 114 ++ .../breakpointRequests/breakpreq001.java | 316 +++++ .../breakpreq001/TestDescription.java | 64 + .../breakpointRequests/breakpreq001t.java | 80 ++ .../breakpointRequests/breakpreq002.java | 533 ++++++++ .../breakpreq002/TestDescription.java | 75 ++ .../breakpointRequests/breakpreq002a.java | 114 ++ .../classPrepareRequests/clsprepreq001.java | 254 ++++ .../clsprepreq001/TestDescription.java | 61 + .../classPrepareRequests/clsprepreq001t.java | 50 + .../classPrepareRequests/clsprepreq002.java | 543 +++++++++ .../clsprepreq002/TestDescription.java | 76 ++ .../classPrepareRequests/clsprepreq002a.java | 114 ++ .../classUnloadRequests/clsunlreq001.java | 261 ++++ .../clsunlreq001/TestDescription.java | 61 + .../classUnloadRequests/clsunlreq001t.java | 50 + .../classUnloadRequests/clsunlreq002.java | 527 ++++++++ .../clsunlreq002/TestDescription.java | 75 ++ .../classUnloadRequests/clsunlreq002a.java | 114 ++ .../craccwtchpreq002.java | 117 ++ .../craccwtchpreq002/TestDescription.java | 55 + .../craccwtchpreq002t.java | 52 + .../craccwtchpreq003.java | 489 ++++++++ .../craccwtchpreq003/TestDescription.java | 84 ++ .../craccwtchpreq003a.java | 114 ++ .../crbreakpreq002.java | 112 ++ .../crbreakpreq002/TestDescription.java | 50 + .../crbreakpreq002t.java | 52 + .../crbreakpreq003.java | 471 ++++++++ .../crbreakpreq003/TestDescription.java | 79 ++ .../crbreakpreq003a.java | 114 ++ .../createClassPrepareRequest/cpreg001.java | 444 +++++++ .../cpreg001/TestDescription.java | 73 ++ .../createClassPrepareRequest/cpreg001a.java | 111 ++ .../createClassUnloadRequest/cureg001.java | 445 +++++++ .../cureg001/TestDescription.java | 73 ++ .../createClassUnloadRequest/cureg001a.java | 111 ++ .../createExceptionRequest/crexreq009.java | 469 ++++++++ .../crexreq009/TestDescription.java | 88 ++ .../createExceptionRequest/crexreq009a.java | 114 ++ .../createExceptionRequest/crexreq010.java | 460 +++++++ .../crexreq010/TestDescription.java | 94 ++ .../createExceptionRequest/crexreq010a.java | 114 ++ .../createMethodEntryRequest/menreg001.java | 445 +++++++ .../menreg001/TestDescription.java | 73 ++ .../createMethodEntryRequest/menreg001a.java | 111 ++ .../createMethodExitRequest/mexreg001.java | 445 +++++++ .../mexreg001/TestDescription.java | 73 ++ .../createMethodExitRequest/mexreg001a.java | 111 ++ .../crmodwtchpreq002.java | 117 ++ .../crmodwtchpreq002/TestDescription.java | 55 + .../crmodwtchpreq002t.java | 52 + .../crmodwtchpreq003.java | 488 ++++++++ .../crmodwtchpreq003/TestDescription.java | 84 ++ .../crmodwtchpreq003a.java | 114 ++ .../createStepRequest/crstepreq001.java | 178 +++ .../crstepreq001/TestDescription.java | 53 + .../createStepRequest/crstepreq001t.java | 52 + .../createStepRequest/crstepreq002.java | 556 +++++++++ .../crstepreq002/TestDescription.java | 92 ++ .../createStepRequest/crstepreq002a.java | 172 +++ .../createStepRequest/crstepreq003.java | 474 ++++++++ .../crstepreq003/TestDescription.java | 85 ++ .../createStepRequest/crstepreq003a.java | 180 +++ .../createStepRequest/crstepreq004.java | 471 ++++++++ .../crstepreq004/TestDescription.java | 87 ++ .../createStepRequest/crstepreq004a.java | 195 +++ .../createStepRequest/crstepreq005.java | 494 ++++++++ .../crstepreq005/TestDescription.java | 81 ++ .../createStepRequest/crstepreq005a.java | 193 +++ .../createStepRequest/crstepreq006.java | 492 ++++++++ .../crstepreq006/TestDescription.java | 81 ++ .../createStepRequest/crstepreq006a.java | 193 +++ .../createStepRequest/crstepreq007.java | 494 ++++++++ .../crstepreq007/TestDescription.java | 79 ++ .../createStepRequest/crstepreq007a.java | 193 +++ .../createStepRequest/crstepreq008.java | 494 ++++++++ .../crstepreq008/TestDescription.java | 81 ++ .../createStepRequest/crstepreq008a.java | 193 +++ .../createStepRequest/crstepreq009.java | 492 ++++++++ .../crstepreq009/TestDescription.java | 81 ++ .../createStepRequest/crstepreq009a.java | 193 +++ .../createStepRequest/crstepreq010.java | 496 ++++++++ .../crstepreq010/TestDescription.java | 80 ++ .../createStepRequest/crstepreq010a.java | 199 +++ .../createThreadDeathRequest/tdreg001.java | 445 +++++++ .../tdreg001/TestDescription.java | 73 ++ .../createThreadDeathRequest/tdreg001a.java | 111 ++ .../createThreadStartRequest/tsreg001.java | 445 +++++++ .../tsreg001/TestDescription.java | 73 ++ .../createThreadStartRequest/tsreg001a.java | 111 ++ .../createVMDeathRequest/vmdreg001.java | 457 +++++++ .../vmdreg001/TestDescription.java | 80 ++ .../createVMDeathRequest/vmdreg001a.java | 111 ++ .../deleteAllBreakpoints/delallbreakp002.java | 457 +++++++ .../delallbreakp002/TestDescription.java | 72 ++ .../delallbreakp002a.java | 114 ++ .../deleteEventRequest/delevtreq002.java | 542 +++++++++ .../delevtreq002/TestDescription.java | 89 ++ .../deleteEventRequest/delevtreq002a.java | 158 +++ .../deleteEventRequest/delevtreq003.java | 252 ++++ .../delevtreq003/TestDescription.java | 69 ++ .../delevtreq003/newclass/delevtreq003b.java | 50 + .../deleteEventRequest/delevtreq003a.java | 52 + .../deleteEventRequest/delevtreq003b.java | 50 + .../deleteEventRequests/delevtreqs002.java | 611 ++++++++++ .../delevtreqs002/TestDescription.java | 75 ++ .../deleteEventRequests/delevtreqs002a.java | 160 +++ .../exceptionRequests/excreq001.java | 291 +++++ .../excreq001/TestDescription.java | 69 ++ .../exceptionRequests/excreq001a.java | 34 + .../exceptionRequests/excreq001b.java | 34 + .../exceptionRequests/excreq001c.java | 34 + .../exceptionRequests/excreq001t.java | 54 + .../exceptionRequests/excreq002.java | 532 ++++++++ .../excreq002/TestDescription.java | 75 ++ .../exceptionRequests/excreq002a.java | 114 ++ .../hashCode/hashcode001.java | 139 +++ .../hashCode/hashcode001/TestDescription.java | 64 + .../hashCode/hashcode001a.java | 87 ++ .../methodEntryRequests/methentreq001.java | 252 ++++ .../methentreq001/TestDescription.java | 61 + .../methodEntryRequests/methentreq001t.java | 50 + .../methodEntryRequests/methentreq002.java | 539 +++++++++ .../methentreq002/TestDescription.java | 76 ++ .../methodEntryRequests/methentreq002a.java | 114 ++ .../methodExitRequests/methexitreq001.java | 252 ++++ .../methexitreq001/TestDescription.java | 61 + .../methodExitRequests/methexitreq001t.java | 50 + .../methodExitRequests/methexitreq002.java | 539 +++++++++ .../methexitreq002/TestDescription.java | 76 ++ .../methodExitRequests/methexitreq002a.java | 114 ++ .../modwtchpreq001.java | 284 +++++ .../modwtchpreq001/TestDescription.java | 65 + .../modwtchpreq001t.java | 69 ++ .../modwtchpreq002.java | 539 +++++++++ .../modwtchpreq002/TestDescription.java | 75 ++ .../modwtchpreq002a.java | 114 ++ .../stepRequests/stepreq001.java | 309 +++++ .../stepreq001/TestDescription.java | 61 + .../stepRequests/stepreq001t.java | 143 +++ .../stepRequests/stepreq002.java | 534 ++++++++ .../stepreq002/TestDescription.java | 75 ++ .../stepRequests/stepreq002a.java | 159 +++ .../threadDeathRequests/thrdeathreq001.java | 238 ++++ .../thrdeathreq001/TestDescription.java | 61 + .../threadDeathRequests/thrdeathreq001t.java | 50 + .../threadDeathRequests/thrdeathreq002.java | 527 ++++++++ .../thrdeathreq002/TestDescription.java | 75 ++ .../threadDeathRequests/thrdeathreq002a.java | 114 ++ .../threadStartRequests/thrstartreq001.java | 237 ++++ .../thrstartreq001/TestDescription.java | 61 + .../threadStartRequests/thrstartreq001t.java | 50 + .../threadStartRequests/thrstartreq002.java | 527 ++++++++ .../thrstartreq002/TestDescription.java | 75 ++ .../threadStartRequests/thrstartreq002a.java | 114 ++ .../vmDeathRequests/vmdeathreq001.java | 527 ++++++++ .../vmdeathreq001/TestDescription.java | 66 + .../vmDeathRequests/vmdeathreq001a.java | 111 ++ .../eventIterator/eventiterator001.java | 499 ++++++++ .../eventiterator001/TestDescription.java | 71 ++ .../eventIterator/eventiterator001a.java | 114 ++ .../eventIterator/eventiterator002.java | 710 +++++++++++ .../eventiterator002/TestDescription.java | 73 ++ .../eventIterator/eventiterator002a.java | 170 +++ .../eventIterator/eventiterator003.java | 521 ++++++++ .../eventiterator003/TestDescription.java | 71 ++ .../eventIterator/eventiterator003a.java | 129 ++ .../eventIterator/eventiterator004.java | 486 ++++++++ .../eventiterator004/TestDescription.java | 75 ++ .../eventIterator/eventiterator004a.java | 106 ++ .../nsk/jdi/EventSet/resume/resume001.java | 265 ++++ .../resume/resume001/TestDescription.java | 76 ++ .../nsk/jdi/EventSet/resume/resume001a.java | 134 +++ .../nsk/jdi/EventSet/resume/resume002.java | 646 ++++++++++ .../resume/resume002/TestDescription.java | 75 ++ .../nsk/jdi/EventSet/resume/resume002a.java | 138 +++ .../nsk/jdi/EventSet/resume/resume003.java | 646 ++++++++++ .../resume/resume003/TestDescription.java | 75 ++ .../nsk/jdi/EventSet/resume/resume003a.java | 138 +++ .../nsk/jdi/EventSet/resume/resume004.java | 642 ++++++++++ .../resume/resume004/TestDescription.java | 75 ++ .../nsk/jdi/EventSet/resume/resume004a.java | 138 +++ .../nsk/jdi/EventSet/resume/resume005.java | 638 ++++++++++ .../resume/resume005/TestDescription.java | 76 ++ .../nsk/jdi/EventSet/resume/resume005a.java | 148 +++ .../nsk/jdi/EventSet/resume/resume006.java | 636 ++++++++++ .../resume/resume006/TestDescription.java | 75 ++ .../nsk/jdi/EventSet/resume/resume006a.java | 139 +++ .../nsk/jdi/EventSet/resume/resume007.java | 635 ++++++++++ .../resume/resume007/TestDescription.java | 75 ++ .../nsk/jdi/EventSet/resume/resume007a.java | 139 +++ .../nsk/jdi/EventSet/resume/resume008.java | 258 ++++ .../resume/resume008/TestDescription.java | 76 ++ .../nsk/jdi/EventSet/resume/resume008a.java | 168 +++ .../nsk/jdi/EventSet/resume/resume009.java | 257 ++++ .../resume/resume009/TestDescription.java | 76 ++ .../nsk/jdi/EventSet/resume/resume009a.java | 175 +++ .../nsk/jdi/EventSet/resume/resume010.java | 631 ++++++++++ .../resume/resume010/TestDescription.java | 75 ++ .../nsk/jdi/EventSet/resume/resume010a.java | 137 +++ .../nsk/jdi/EventSet/resume/resume011.java | 485 ++++++++ .../resume/resume011/TestDescription.java | 74 ++ .../nsk/jdi/EventSet/resume/resume011a.java | 106 ++ .../nsk/jdi/EventSet/resume/resume012.java | 489 ++++++++ .../resume/resume012/TestDescription.java | 79 ++ .../nsk/jdi/EventSet/resume/resume012a.java | 106 ++ .../nsk/jdi/EventSet/resume/resume013.java | 488 ++++++++ .../resume/resume013/TestDescription.java | 74 ++ .../nsk/jdi/EventSet/resume/resume013a.java | 106 ++ .../suspendPolicy/suspendpolicy001.java | 625 ++++++++++ .../suspendpolicy001/TestDescription.java | 83 ++ .../suspendPolicy/suspendpolicy001a.java | 167 +++ .../suspendPolicy/suspendpolicy002.java | 624 ++++++++++ .../suspendpolicy002/TestDescription.java | 83 ++ .../suspendPolicy/suspendpolicy002a.java | 152 +++ .../suspendPolicy/suspendpolicy003.java | 631 ++++++++++ .../suspendpolicy003/TestDescription.java | 83 ++ .../suspendPolicy/suspendpolicy003a.java | 152 +++ .../suspendPolicy/suspendpolicy004.java | 628 ++++++++++ .../suspendpolicy004/TestDescription.java | 83 ++ .../suspendPolicy/suspendpolicy004a.java | 152 +++ .../suspendPolicy/suspendpolicy005.java | 624 ++++++++++ .../suspendpolicy005/TestDescription.java | 84 ++ .../suspendPolicy/suspendpolicy005a.java | 162 +++ .../suspendPolicy/suspendpolicy006.java | 622 ++++++++++ .../suspendpolicy006/TestDescription.java | 83 ++ .../suspendPolicy/suspendpolicy006a.java | 152 +++ .../suspendPolicy/suspendpolicy007.java | 621 ++++++++++ .../suspendpolicy007/TestDescription.java | 83 ++ .../suspendPolicy/suspendpolicy007a.java | 152 +++ .../suspendPolicy/suspendpolicy008.java | 590 +++++++++ .../suspendpolicy008/TestDescription.java | 83 ++ .../suspendPolicy/suspendpolicy008a.java | 202 ++++ .../suspendPolicy/suspendpolicy009.java | 590 +++++++++ .../suspendpolicy009/TestDescription.java | 83 ++ .../suspendPolicy/suspendpolicy009a.java | 223 ++++ .../suspendPolicy/suspendpolicy010.java | 551 +++++++++ .../suspendpolicy010/TestDescription.java | 82 ++ .../suspendPolicy/suspendpolicy010a.java | 144 +++ .../suspendPolicy/suspendpolicy011.java | 507 ++++++++ .../suspendpolicy011/TestDescription.java | 82 ++ .../suspendPolicy/suspendpolicy011a.java | 109 ++ .../suspendPolicy/suspendpolicy012.java | 507 ++++++++ .../suspendpolicy012/TestDescription.java | 82 ++ .../suspendPolicy/suspendpolicy012a.java | 109 ++ .../suspendPolicy/suspendpolicy013.java | 507 ++++++++ .../suspendpolicy013/TestDescription.java | 82 ++ .../suspendPolicy/suspendpolicy013a.java | 109 ++ .../suspendPolicy/suspendpolicy014.java | 510 ++++++++ .../suspendpolicy014/TestDescription.java | 82 ++ .../suspendPolicy/suspendpolicy014a.java | 109 ++ .../suspendPolicy/suspendpolicy015.java | 510 ++++++++ .../suspendpolicy015/TestDescription.java | 82 ++ .../suspendPolicy/suspendpolicy015a.java | 109 ++ .../suspendPolicy/suspendpolicy016.java | 510 ++++++++ .../suspendpolicy016/TestDescription.java | 82 ++ .../suspendPolicy/suspendpolicy016a.java | 109 ++ .../suspendPolicy/suspendpolicy017.java | 512 ++++++++ .../suspendpolicy017/TestDescription.java | 82 ++ .../suspendPolicy/suspendpolicy017a.java | 109 ++ .../suspendPolicy/suspendpolicy018.java | 341 ++++++ .../suspendpolicy018/TestDescription.java | 81 ++ .../suspendPolicy/suspendpolicy018a.java | 109 ++ .../jdi/EventSet/toString/tostring001.java | 198 +++ .../toString/tostring001/TestDescription.java | 65 + .../jdi/EventSet/toString/tostring001a.java | 95 ++ .../virtualMachine/virtualmachine001.java | 189 +++ .../virtualmachine001/TestDescription.java | 67 ++ .../virtualMachine/virtualmachine001a.java | 96 ++ .../ExceptionEvent/_itself_/exevent001.java | 328 +++++ .../_itself_/exevent001/TestDescription.java | 68 ++ .../ExceptionEvent/_itself_/exevent001t.java | 96 ++ .../ExceptionEvent/_itself_/exevent002.java | 245 ++++ .../_itself_/exevent002/TestDescription.java | 64 + .../ExceptionEvent/_itself_/exevent002t.java | 52 + .../ExceptionEvent/_itself_/exevent003.java | 251 ++++ .../_itself_/exevent003/TestDescription.java | 64 + .../ExceptionEvent/_itself_/exevent003t.java | 52 + .../ExceptionEvent/_itself_/exevent004.java | 248 ++++ .../_itself_/exevent004/TestDescription.java | 65 + .../ExceptionEvent/_itself_/exevent004t.java | 55 + .../ExceptionEvent/_itself_/exevent005.java | 247 ++++ .../_itself_/exevent005/TestDescription.java | 65 + .../ExceptionEvent/_itself_/exevent005t.java | 55 + .../ExceptionEvent/_itself_/exevent006.java | 249 ++++ .../_itself_/exevent006/TestDescription.java | 66 + .../ExceptionEvent/_itself_/exevent006t.java | 73 ++ .../ExceptionEvent/_itself_/exevent007.java | 248 ++++ .../_itself_/exevent007/TestDescription.java | 66 + .../ExceptionEvent/_itself_/exevent007t.java | 73 ++ .../ExceptionEvent/_itself_/exevent008.java | 275 +++++ .../_itself_/exevent008/TestDescription.java | 68 ++ .../ExceptionEvent/_itself_/exevent008t.java | 104 ++ .../catchLocation/location001.java | 428 +++++++ .../location001/TestDescription.java | 86 ++ .../catchLocation/location001a.java | 189 +++ .../catchLocation/location002.java | 276 +++++ .../location002/TestDescription.java | 73 ++ .../catchLocation/location002a.java | 76 ++ .../exception/exception001.java | 701 +++++++++++ .../exception001/TestDescription.java | 91 ++ .../exception/exception001a.java | 189 +++ .../ExceptionRequest/_bounds_/filters001.java | 214 ++++ .../_bounds_/filters001/TestDescription.java | 59 + .../_bounds_/filters001a.java | 54 + .../addClassExclusionFilter/filter001.java | 180 +++ .../filter001/TestDescription.java | 82 ++ .../addClassExclusionFilter/filter001a.java | 222 ++++ .../addClassExclusionFilter/filter002.java | 528 ++++++++ .../filter002/TestDescription.java | 80 ++ .../addClassExclusionFilter/filter002a.java | 145 +++ .../addClassFilter_rt/filter_rt001.java | 151 +++ .../filter_rt001/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt001a.java | 219 ++++ .../addClassFilter_rt/filter_rt002.java | 530 ++++++++ .../filter_rt002/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt002a.java | 183 +++ .../addClassFilter_rt/filter_rt003.java | 182 +++ .../filter_rt003/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt003a.java | 225 ++++ .../addClassFilter_s/filter_s001.java | 187 +++ .../filter_s001/TestDescription.java | 81 ++ .../addClassFilter_s/filter_s001a.java | 223 ++++ .../addClassFilter_s/filter_s002.java | 529 ++++++++ .../filter_s002/TestDescription.java | 80 ++ .../addClassFilter_s/filter_s002a.java | 182 +++ .../addInstanceFilter/instancefilter001.java | 191 +++ .../instancefilter001/TestDescription.java | 83 ++ .../addInstanceFilter/instancefilter001a.java | 214 ++++ .../addInstanceFilter/instancefilter002.java | 551 +++++++++ .../instancefilter002/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter002a.java | 195 +++ .../addInstanceFilter/instancefilter003.java | 518 ++++++++ .../instancefilter003/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter003a.java | 195 +++ .../addInstanceFilter/instancefilter004.java | 201 ++++ .../instancefilter004/TestDescription.java | 92 ++ .../addInstanceFilter/instancefilter004a.java | 206 ++++ .../addThreadFilter/threadfilter001.java | 157 +++ .../threadfilter001/TestDescription.java | 76 ++ .../addThreadFilter/threadfilter001a.java | 205 ++++ .../addThreadFilter/threadfilter002.java | 538 +++++++++ .../threadfilter002/TestDescription.java | 76 ++ .../addThreadFilter/threadfilter002a.java | 193 +++ .../addThreadFilter/threadfilter003.java | 543 +++++++++ .../threadfilter003/TestDescription.java | 75 ++ .../addThreadFilter/threadfilter003a.java | 188 +++ .../addThreadFilter/threadfilter004.java | 189 +++ .../threadfilter004/TestDescription.java | 84 ++ .../addThreadFilter/threadfilter004a.java | 208 ++++ .../exception/exception001.java | 509 ++++++++ .../exception001/TestDescription.java | 81 ++ .../exception/exception001a.java | 118 ++ .../notifyCaught/notifycaught001.java | 499 ++++++++ .../notifycaught001/TestDescription.java | 76 ++ .../notifyCaught/notifycaught001a.java | 181 +++ .../notifyUncaught/notifyuncaught001.java | 499 ++++++++ .../notifyuncaught001/TestDescription.java | 76 ++ .../notifyUncaught/notifyuncaught001a.java | 181 +++ .../nsk/jdi/ExtraClassesInstaller.java | 63 + .../nsk/jdi/Field/equals/equals001.java | 233 ++++ .../equals/equals001/TestDescription.java | 58 + .../nsk/jdi/Field/equals/equals001a.java | 111 ++ .../nsk/jdi/Field/equals/equals002.java | 279 +++++ .../equals/equals002/TestDescription.java | 54 + .../nsk/jdi/Field/equals/equals002a.java | 97 ++ .../nsk/jdi/Field/equals/equals003.java | 231 ++++ .../equals/equals003/TestDescription.java | 63 + .../nsk/jdi/Field/equals/equals003a.java | 160 +++ .../nsk/jdi/Field/equals/equals005.java | 145 +++ .../equals/equals005/TestDescription.java | 54 + .../nsk/jdi/Field/equals/equals005a.java | 97 ++ .../nsk/jdi/Field/hashCode/hashcode001.java | 130 ++ .../hashCode/hashcode001/TestDescription.java | 55 + .../nsk/jdi/Field/hashCode/hashcode001a.java | 97 ++ .../isEnumConstant/isenumconstant001.java | 142 +++ .../isenumconstant001/TestDescription.java | 64 + .../isEnumConstant/isenumconstant001a.java | 121 ++ .../nsk/jdi/Field/isTransient/istrans001.java | 389 ++++++ .../istrans001/TestDescription.java | 54 + .../jdi/Field/isTransient/istrans001a.java | 137 +++ .../nsk/jdi/Field/isVolatile/isvol001.java | 379 ++++++ .../isVolatile/isvol001/TestDescription.java | 54 + .../nsk/jdi/Field/isVolatile/isvol001a.java | 134 +++ .../nsk/jdi/Field/type/type001.java | 227 ++++ .../Field/type/type001/TestDescription.java | 56 + .../nsk/jdi/Field/type/type001a.java | 68 ++ .../nsk/jdi/Field/type/type002.java | 249 ++++ .../Field/type/type002/TestDescription.java | 60 + .../nsk/jdi/Field/type/type002a.java | 87 ++ .../nsk/jdi/Field/type/type003.java | 133 ++ .../Field/type/type003/TestDescription.java | 60 + .../nsk/jdi/Field/type/type003a.java | 76 ++ .../nsk/jdi/Field/type/type004.java | 143 +++ .../Field/type/type004/TestDescription.java | 66 + .../nsk/jdi/Field/type/type004a.java | 107 ++ .../nsk/jdi/Field/typeName/typename001.java | 306 +++++ .../typeName/typename001/TestDescription.java | 57 + .../nsk/jdi/Field/typeName/typename001a.java | 97 ++ .../nsk/jdi/Field/typeName/typename002.java | 136 +++ .../typeName/typename002/TestDescription.java | 65 + .../nsk/jdi/Field/typeName/typename002a.java | 106 ++ .../jdi/FloatType/_itself_/floattype001.java | 456 +++++++ .../floattype001/TestDescription.java | 66 + .../jdi/FloatType/_itself_/floattype001a.java | 113 ++ .../FloatValue/compareTo/compareto001.java | 296 +++++ .../compareto001/TestDescription.java | 70 ++ .../FloatValue/compareTo/compareto001a.java | 175 +++ .../nsk/jdi/FloatValue/equals/equals001.java | 246 ++++ .../equals/equals001/TestDescription.java | 73 ++ .../nsk/jdi/FloatValue/equals/equals001a.java | 133 ++ .../nsk/jdi/FloatValue/equals/equals002.java | 212 ++++ .../equals/equals002/TestDescription.java | 66 + .../nsk/jdi/FloatValue/equals/equals002a.java | 142 +++ .../jdi/FloatValue/hashCode/hashcode001.java | 239 ++++ .../hashCode/hashcode001/TestDescription.java | 71 ++ .../jdi/FloatValue/hashCode/hashcode001a.java | 133 ++ .../nsk/jdi/FloatValue/value/value001.java | 297 +++++ .../value/value001/TestDescription.java | 71 ++ .../nsk/jdi/FloatValue/value/value001a.java | 133 ++ .../IntegerArgument/intValue/intvalue001.java | 189 +++ .../intValue/intvalue001/TestDescription.java | 75 ++ .../IntegerArgument/intValue/intvalue002.java | 196 +++ .../intValue/intvalue002/TestDescription.java | 77 ++ .../IntegerArgument/isValid/isvalid001.java | 180 +++ .../isValid/isvalid001/TestDescription.java | 77 ++ .../IntegerArgument/isValid/isvalid002.java | 184 +++ .../isValid/isvalid002/TestDescription.java | 88 ++ .../IntegerArgument/isValid/isvalid003.java | 166 +++ .../isValid/isvalid003/TestDescription.java | 70 ++ .../nsk/jdi/IntegerArgument/max/max001.java | 147 +++ .../max/max001/TestDescription.java | 74 ++ .../nsk/jdi/IntegerArgument/min/min001.java | 139 +++ .../min/min001/TestDescription.java | 70 ++ .../IntegerArgument/setValue/setvalue001.java | 193 +++ .../setValue/setvalue001/TestDescription.java | 83 ++ .../stringValueOf/stringvalueof001.java | 187 +++ .../stringvalueof001/TestDescription.java | 74 ++ .../IntegerType/_itself_/integertype001.java | 456 +++++++ .../integertype001/TestDescription.java | 66 + .../IntegerType/_itself_/integertype001a.java | 113 ++ .../IntegerValue/compareTo/compareto001.java | 296 +++++ .../compareto001/TestDescription.java | 70 ++ .../IntegerValue/compareTo/compareto001a.java | 175 +++ .../jdi/IntegerValue/equals/equals001.java | 247 ++++ .../equals/equals001/TestDescription.java | 73 ++ .../jdi/IntegerValue/equals/equals001a.java | 125 ++ .../jdi/IntegerValue/equals/equals002.java | 212 ++++ .../equals/equals002/TestDescription.java | 66 + .../jdi/IntegerValue/equals/equals002a.java | 142 +++ .../IntegerValue/hashCode/hashcode001.java | 234 ++++ .../hashCode/hashcode001/TestDescription.java | 71 ++ .../IntegerValue/hashCode/hashcode001a.java | 125 ++ .../nsk/jdi/IntegerValue/value/value001.java | 243 ++++ .../value/value001/TestDescription.java | 71 ++ .../nsk/jdi/IntegerValue/value/value001a.java | 125 ++ .../implementors/implementors001.java | 320 +++++ .../implementors001/TestDescription.java | 77 ++ .../implementors/implementors001a.java | 307 +++++ .../subinterfaces/subinterfaces001.java | 311 +++++ .../subinterfaces001/TestDescription.java | 77 ++ .../subinterfaces/subinterfaces001a.java | 305 +++++ .../superinterfaces/superinterfaces001.java | 339 ++++++ .../superinterfaces001/TestDescription.java | 79 ++ .../superinterfaces/superinterfaces001a.java | 304 +++++ .../LaunchingConnector/launch/launch001.java | 193 +++ .../launch/launch001/TestDescription.java | 60 + .../LaunchingConnector/launch/launch001o.java | 33 + .../LaunchingConnector/launch/launch002.java | 192 +++ .../launch/launch002/TestDescription.java | 60 + .../LaunchingConnector/launch/launch002o.java | 33 + .../LaunchingConnector/launch/launch003.java | 198 +++ .../launch/launch003/TestDescription.java | 60 + .../LaunchingConnector/launch/launch003o.java | 33 + .../LaunchingConnector/launch/launch004.java | 197 +++ .../launch/launch004/TestDescription.java | 60 + .../LaunchingConnector/launch/launch004o.java | 30 + .../launchnosuspend/launchnosuspend001.java | 211 ++++ .../launchnosuspend001/TestDescription.java | 52 + .../launchnosuspend/launchnosuspend001o.java | 40 + .../ListeningConnector/accept/accept001.java | 214 ++++ .../accept/accept001/TestDescription.java | 58 + .../ListeningConnector/accept/accept001t.java | 32 + .../ListeningConnector/accept/accept002.java | 214 ++++ .../accept/accept002/TestDescription.java | 58 + .../ListeningConnector/accept/accept002t.java | 32 + .../listennosuspend/listennosuspend001.java | 214 ++++ .../listennosuspend001/TestDescription.java | 52 + .../listennosuspend/listennosuspend001t.java | 39 + .../startListening/startlis001.java | 306 +++++ .../startlis001/TestDescription.java | 65 + .../startListening/startlis001t.java | 30 + .../startListening/startlis002.java | 289 +++++ .../startlis002/TEST.properties | 24 + .../startlis002/TestDescription.java | 67 ++ .../startListening/startlis002t.java | 30 + .../stopListening/stoplis001.java | 219 ++++ .../stopListening/stoplis001/TEST.properties | 24 + .../stoplis001/TestDescription.java | 59 + .../stopListening/stoplis002.java | 219 ++++ .../stopListening/stoplis002/TEST.properties | 24 + .../stoplis002/TestDescription.java | 59 + .../supportsmultipleconnections001.java | 96 ++ .../TestDescription.java | 55 + .../jdi/LocalVariable/equals/equals001.java | 265 ++++ .../equals/equals001/TestDescription.java | 88 ++ .../jdi/LocalVariable/equals/equals001a.java | 206 ++++ .../genericSignature/gensignature001.java | 187 +++ .../gensignature001/TestDescription.java | 71 ++ .../genericSignature/gensignature001a.java | 137 +++ .../LocalVariable/hashCode/hashcode001.java | 264 ++++ .../hashCode/hashcode001/TestDescription.java | 85 ++ .../LocalVariable/hashCode/hashcode001a.java | 206 ++++ .../isArgument/isargument001.java | 340 ++++++ .../isargument001/TestDescription.java | 84 ++ .../isArgument/isargument001a.java | 188 +++ .../LocalVariable/isVisible/isvisible001.java | 632 ++++++++++ .../isvisible001/TestDescription.java | 92 ++ .../isVisible/isvisible001a.java | 197 +++ .../nsk/jdi/LocalVariable/name/name001.java | 335 ++++++ .../name/name001/TestDescription.java | 84 ++ .../nsk/jdi/LocalVariable/name/name001a.java | 187 +++ .../LocalVariable/signature/signature001.java | 336 ++++++ .../signature001/TestDescription.java | 84 ++ .../signature/signature001a.java | 188 +++ .../LocalVariable/toString/tostring001.java | 193 +++ .../toString/tostring001/TestDescription.java | 62 + .../LocalVariable/toString/tostring001a.java | 115 ++ .../nsk/jdi/LocalVariable/type/type001.java | 333 +++++ .../type/type001/TestDescription.java | 92 ++ .../nsk/jdi/LocalVariable/type/type001a.java | 132 ++ .../nsk/jdi/LocalVariable/type/type002.java | 283 +++++ .../type/type002/TestDescription.java | 92 ++ .../nsk/jdi/LocalVariable/type/type002a.java | 174 +++ .../LocalVariable/typeName/typename001.java | 311 +++++ .../typeName/typename001/TestDescription.java | 84 ++ .../LocalVariable/typeName/typename001a.java | 133 ++ .../LocalVariable/typeName/typename002.java | 276 +++++ .../typeName/typename002/TestDescription.java | 84 ++ .../LocalVariable/typeName/typename002a.java | 168 +++ .../jdi/Locatable/location/location001.java | 356 ++++++ .../location/location001/TestDescription.java | 77 ++ .../jdi/Locatable/location/location001a.java | 130 ++ .../jdi/Locatable/location/location002.java | 225 ++++ .../location/location002/TestDescription.java | 76 ++ .../jdi/Locatable/location/location002a.java | 142 +++ .../jdi/Locatable/location/location003.java | 272 +++++ .../location/location003/TestDescription.java | 76 ++ .../jdi/Locatable/location/location003a.java | 181 +++ .../jdi/Locatable/location/location004.java | 512 ++++++++ .../location/location004/TestDescription.java | 77 ++ .../jdi/Locatable/location/location004a.java | 194 +++ .../jdi/Locatable/location/location005.java | 512 ++++++++ .../location/location005/TestDescription.java | 77 ++ .../jdi/Locatable/location/location005a.java | 194 +++ .../jdi/Locatable/location/location006.java | 206 ++++ .../location/location006/TestDescription.java | 78 ++ .../jdi/Locatable/location/location006a.java | 120 ++ .../jdi/LocatableEvent/thread/thread001.java | 809 +++++++++++++ .../thread/thread001/TestDescription.java | 75 ++ .../jdi/LocatableEvent/thread/thread001a.java | 270 +++++ .../jdi/Location/codeIndex/codeindex001.java | 237 ++++ .../codeindex001/TestDescription.java | 84 ++ .../jdi/Location/codeIndex/codeindex001a.java | 134 +++ .../declaringType/declaringtype001.java | 288 +++++ .../declaringtype001/TestDescription.java | 84 ++ .../declaringType/declaringtype001a.java | 133 ++ .../nsk/jdi/Location/equals/equals001.java | 249 ++++ .../equals/equals001/TestDescription.java | 85 ++ .../nsk/jdi/Location/equals/equals001a.java | 134 +++ .../jdi/Location/hashCode/hashcode001.java | 247 ++++ .../hashCode/hashcode001/TestDescription.java | 83 ++ .../jdi/Location/hashCode/hashcode001a.java | 134 +++ .../Location/lineNumber/linenumber001.java | 246 ++++ .../linenumber001/TestDescription.java | 95 ++ .../Location/lineNumber/linenumber001a.java | 142 +++ .../lineNumber_s002/lineNumber_s002.java | 155 +++ .../lineNumber_s/linenumber_s001.java | 243 ++++ .../linenumber_s001/TestDescription.java | 83 ++ .../lineNumber_s/linenumber_s001a.java | 146 +++ .../nsk/jdi/Location/method/method001.java | 246 ++++ .../method/method001/TestDescription.java | 72 ++ .../nsk/jdi/Location/method/method001a.java | 145 +++ .../Location/sourceName/sourcename001.java | 247 ++++ .../sourcename001/TestDescription.java | 89 ++ .../Location/sourceName/sourcename001a.java | 134 +++ .../sourceName_s002/sourceName_s002.java | 156 +++ .../sourceName_s/sourcename_s001.java | 244 ++++ .../sourcename_s001/TestDescription.java | 87 ++ .../sourceName_s/sourcename_s001a.java | 138 +++ .../Location/sourcePath/sourcepath001.java | 247 ++++ .../sourcepath001/TestDescription.java | 85 ++ .../Location/sourcePath/sourcepath001a.java | 133 ++ .../sourcePath_s002/sourcePath_s002.java | 156 +++ .../sourcePath_s/sourcepath_s001.java | 250 ++++ .../sourcepath_s001/TestDescription.java | 96 ++ .../sourcePath_s/sourcepath_s001a.java | 133 ++ .../jdi/LongType/_itself_/longtype001.java | 456 +++++++ .../_itself_/longtype001/TestDescription.java | 66 + .../jdi/LongType/_itself_/longtype001a.java | 113 ++ .../jdi/LongValue/compareTo/compareto001.java | 296 +++++ .../compareto001/TestDescription.java | 70 ++ .../LongValue/compareTo/compareto001a.java | 175 +++ .../nsk/jdi/LongValue/equals/equals001.java | 247 ++++ .../equals/equals001/TestDescription.java | 73 ++ .../nsk/jdi/LongValue/equals/equals001a.java | 125 ++ .../nsk/jdi/LongValue/equals/equals002.java | 212 ++++ .../equals/equals002/TestDescription.java | 66 + .../nsk/jdi/LongValue/equals/equals002a.java | 142 +++ .../jdi/LongValue/hashCode/hashcode001.java | 234 ++++ .../hashCode/hashcode001/TestDescription.java | 71 ++ .../jdi/LongValue/hashCode/hashcode001a.java | 125 ++ .../nsk/jdi/LongValue/value/value001.java | 243 ++++ .../value/value001/TestDescription.java | 71 ++ .../nsk/jdi/LongValue/value/value001a.java | 125 ++ .../nsk/jdi/Method/_bounds_/bounds001.java | 295 +++++ .../_bounds_/bounds001/TestDescription.java | 65 + .../nsk/jdi/Method/_bounds_/bounds001a.java | 54 + .../allLineLocations/alllinelocations001.java | 274 +++++ .../alllinelocations001/TestDescription.java | 102 ++ .../alllinelocations001a.java | 140 +++ .../allLineLocations/alllinelocations002.java | 267 ++++ .../alllinelocations002/TestDescription.java | 102 ++ .../alllinelocations002a.java | 205 ++++ .../allLineLocations_ss002.java | 186 +++ .../allLineLocations_ss003.java | 186 +++ .../alllinelocations_ss001.java | 272 +++++ .../TestDescription.java | 104 ++ .../alllinelocations_ss001a.java | 146 +++ .../argumenttypenames001.java | 307 +++++ .../argumenttypenames001/TestDescription.java | 74 ++ .../argumenttypenames001a.java | 198 +++ .../argumenttypenames002.java | 274 +++++ .../argumenttypenames002/TestDescription.java | 74 ++ .../argumenttypenames002a.java | 199 +++ .../argumenttypenames003.java | 131 ++ .../argumenttypenames003/TestDescription.java | 71 ++ .../argumenttypenames003a.java | 95 ++ .../argumentTypes/argumenttypes001.java | 433 +++++++ .../argumenttypes001/TestDescription.java | 80 ++ .../argumentTypes/argumenttypes001a.java | 202 ++++ .../argumentTypes/argumenttypes002.java | 327 +++++ .../argumenttypes002/TestDescription.java | 80 ++ .../argumentTypes/argumenttypes002a.java | 204 ++++ .../jdi/Method/arguments/arguments001.java | 275 +++++ .../arguments001/TestDescription.java | 98 ++ .../jdi/Method/arguments/arguments001a.java | 143 +++ .../jdi/Method/arguments/arguments002.java | 201 ++++ .../arguments002/TestDescription.java | 80 ++ .../jdi/Method/arguments/arguments002a.java | 143 +++ .../jdi/Method/arguments/arguments003.java | 138 +++ .../arguments003/TestDescription.java | 71 ++ .../jdi/Method/arguments/arguments003a.java | 95 ++ .../jdi/Method/bytecodes/bytecodes001.java | 213 ++++ .../bytecodes001/TestDescription.java | 76 ++ .../jdi/Method/bytecodes/bytecodes001a.java | 207 ++++ .../nsk/jdi/Method/equals/equals001.java | 252 ++++ .../equals/equals001/TestDescription.java | 74 ++ .../nsk/jdi/Method/equals/equals001a.java | 257 ++++ .../nsk/jdi/Method/hashCode/hashcode001.java | 335 ++++++ .../hashCode/hashcode001/TestDescription.java | 74 ++ .../nsk/jdi/Method/hashCode/hashcode001a.java | 258 ++++ .../jdi/Method/isAbstract/isabstract001.java | 215 ++++ .../isabstract001/TestDescription.java | 71 ++ .../jdi/Method/isAbstract/isabstract001a.java | 130 ++ .../nsk/jdi/Method/isBridge/isbridge001.java | 288 +++++ .../isBridge/isbridge001/TestDescription.java | 72 ++ .../nsk/jdi/Method/isBridge/isbridge001t.java | 141 +++ .../isConstructor/isconstructor001.java | 210 ++++ .../isconstructor001/TestDescription.java | 71 ++ .../isConstructor/isconstructor001a.java | 123 ++ .../nsk/jdi/Method/isNative/isnative001.java | 209 ++++ .../isNative/isnative001/TestDescription.java | 71 ++ .../nsk/jdi/Method/isNative/isnative001a.java | 120 ++ .../jdi/Method/isObsolete/isobsolete001.java | 575 +++++++++ .../isobsolete001/TestDescription.java | 94 ++ .../newclass/isobsolete001b.java | 59 + .../jdi/Method/isObsolete/isobsolete001a.java | 115 ++ .../jdi/Method/isObsolete/isobsolete001b.java | 59 + .../jdi/Method/isObsolete/isobsolete002.java | 573 +++++++++ .../isobsolete002/TestDescription.java | 95 ++ .../newclass/isobsolete002b.java | 58 + .../jdi/Method/isObsolete/isobsolete002a.java | 117 ++ .../jdi/Method/isObsolete/isobsolete002b.java | 57 + .../jdi/Method/isObsolete/isobsolete003.java | 460 +++++++ .../isobsolete003/TestDescription.java | 108 ++ .../newclass/isobsolete003b.java | 39 + .../jdi/Method/isObsolete/isobsolete003a.java | 60 + .../jdi/Method/isObsolete/isobsolete003b.java | 35 + .../isstinitializer001.java | 210 ++++ .../isstinitializer001/TestDescription.java | 71 ++ .../isstinitializer001a.java | 123 ++ .../isSynchronized/issynchronized001.java | 209 ++++ .../issynchronized001/TestDescription.java | 71 ++ .../isSynchronized/issynchronized001a.java | 122 ++ .../jdi/Method/isVarArgs/isvarargs001.java | 123 ++ .../isvarargs001/TestDescription.java | 64 + .../jdi/Method/isVarArgs/isvarargs001a.java | 95 ++ .../locationofcodeindex001.java | 260 ++++ .../TestDescription.java | 85 ++ .../locationofcodeindex001a.java | 133 ++ .../locationsOfLine/locationsofline001.java | 273 +++++ .../locationsofline001/TestDescription.java | 101 ++ .../locationsOfLine/locationsofline001a.java | 198 +++ .../locationsOfLine_ssi002.java | 240 ++++ .../locationsOfLine_ssi003.java | 160 +++ .../locationsofline_ssi001.java | 274 +++++ .../TestDescription.java | 99 ++ .../locationsofline_ssi001a.java | 136 +++ .../jdi/Method/returnType/returntype001.java | 362 ++++++ .../returntype001/TestDescription.java | 82 ++ .../jdi/Method/returnType/returntype001a.java | 127 ++ .../jdi/Method/returnType/returntype002.java | 236 ++++ .../returntype002/TestDescription.java | 82 ++ .../jdi/Method/returnType/returntype002a.java | 120 ++ .../jdi/Method/returnType/returntype003.java | 282 +++++ .../returntype003/TestDescription.java | 82 ++ .../jdi/Method/returnType/returntype003a.java | 173 +++ .../returnTypeNames/returntypenames001.java | 332 +++++ .../returntypenames001/TestDescription.java | 72 ++ .../returnTypeNames/returntypenames001a.java | 127 ++ .../returnTypeNames/returntypenames002.java | 233 ++++ .../returntypenames002/TestDescription.java | 72 ++ .../returnTypeNames/returntypenames002a.java | 121 ++ .../returnTypeNames/returntypenames003.java | 275 +++++ .../returntypenames003/TestDescription.java | 72 ++ .../returnTypeNames/returntypenames003a.java | 175 +++ .../jdi/Method/variables/variables001.java | 277 +++++ .../variables001/TestDescription.java | 103 ++ .../jdi/Method/variables/variables001a.java | 153 +++ .../jdi/Method/variables/variables002.java | 202 ++++ .../variables002/TestDescription.java | 85 ++ .../jdi/Method/variables/variables002a.java | 143 +++ .../variablesByName/variablesbyname001.java | 271 +++++ .../variablesbyname001/TestDescription.java | 100 ++ .../variablesByName/variablesbyname001a.java | 154 +++ .../variablesByName/variablesbyname002.java | 202 ++++ .../variablesbyname002/TestDescription.java | 82 ++ .../variablesByName/variablesbyname002a.java | 143 +++ .../MethodEntryEvent/method/method001.java | 381 ++++++ .../method/method001/TestDescription.java | 95 ++ .../MethodEntryEvent/method/method001a.java | 115 ++ .../MethodEntryEvent/method/method002.java | 356 ++++++ .../method/method002/TestDescription.java | 95 ++ .../MethodEntryEvent/method/method002a.java | 114 ++ .../_bounds_/filters001.java | 226 ++++ .../_bounds_/filters001/TestDescription.java | 59 + .../_bounds_/filters001a.java | 54 + .../addClassExclusionFilter/filter001.java | 160 +++ .../filter001/TestDescription.java | 80 ++ .../addClassExclusionFilter/filter001a.java | 178 +++ .../addClassExclusionFilter/filter002.java | 538 +++++++++ .../filter002/TestDescription.java | 79 ++ .../addClassExclusionFilter/filter002a.java | 145 +++ .../addClassFilter_rt/filter_rt001.java | 160 +++ .../filter_rt001/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt001a.java | 191 +++ .../addClassFilter_rt/filter_rt002.java | 530 ++++++++ .../filter_rt002/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt002a.java | 184 +++ .../addClassFilter_rt/filter_rt003.java | 182 +++ .../filter_rt003/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt003a.java | 211 ++++ .../addClassFilter_s/filter_s001.java | 183 +++ .../filter_s001/TestDescription.java | 79 ++ .../addClassFilter_s/filter_s001a.java | 209 ++++ .../addClassFilter_s/filter_s002.java | 525 ++++++++ .../filter_s002/TestDescription.java | 78 ++ .../addClassFilter_s/filter_s002a.java | 145 +++ .../addInstanceFilter/instancefilter001.java | 190 +++ .../instancefilter001/TestDescription.java | 83 ++ .../addInstanceFilter/instancefilter001a.java | 195 +++ .../addInstanceFilter/instancefilter002.java | 556 +++++++++ .../instancefilter002/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter002a.java | 183 +++ .../addInstanceFilter/instancefilter003.java | 523 ++++++++ .../instancefilter003/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter003a.java | 183 +++ .../addInstanceFilter/instancefilter004.java | 202 ++++ .../instancefilter004/TestDescription.java | 92 ++ .../addInstanceFilter/instancefilter004a.java | 194 +++ .../addThreadFilter/threadfilter001.java | 154 +++ .../threadfilter001/TestDescription.java | 76 ++ .../addThreadFilter/threadfilter001a.java | 193 +++ .../addThreadFilter/threadfilter002.java | 538 +++++++++ .../threadfilter002/TestDescription.java | 76 ++ .../addThreadFilter/threadfilter002a.java | 184 +++ .../addThreadFilter/threadfilter003.java | 541 +++++++++ .../threadfilter003/TestDescription.java | 75 ++ .../addThreadFilter/threadfilter003a.java | 187 +++ .../addThreadFilter/threadfilter004.java | 187 +++ .../threadfilter004/TestDescription.java | 84 ++ .../addThreadFilter/threadfilter004a.java | 200 +++ .../_itself_/methodexit001.java | 286 +++++ .../methodexit001/TestDescription.java | 84 ++ .../_itself_/methodexit001a.java | 112 ++ .../jdi/MethodExitEvent/method/method001.java | 374 ++++++ .../method/method001/TestDescription.java | 94 ++ .../MethodExitEvent/method/method001a.java | 115 ++ .../jdi/MethodExitEvent/method/method002.java | 393 ++++++ .../method/method002/TestDescription.java | 95 ++ .../MethodExitEvent/method/method002a.java | 114 ++ .../returnValue001/returnValue001.java | 225 ++++ .../returnValue001/returnValue001a.java | 93 ++ .../returnValue002/returnValue002.java | 167 +++ .../returnValue002/returnValue002a.java | 98 ++ .../returnValue003/returnValue003.java | 284 +++++ .../returnValue003/returnValue003a.java | 116 ++ .../returnValue004/returnValue004.java | 228 ++++ .../returnValue004/returnValue004a.java | 93 ++ .../_bounds_/filters001.java | 226 ++++ .../_bounds_/filters001/TestDescription.java | 59 + .../_bounds_/filters001a.java | 54 + .../addClassExclusionFilter/filter001.java | 160 +++ .../filter001/TestDescription.java | 82 ++ .../addClassExclusionFilter/filter001a.java | 180 +++ .../addClassExclusionFilter/filter002.java | 538 +++++++++ .../filter002/TestDescription.java | 81 ++ .../addClassExclusionFilter/filter002a.java | 145 +++ .../addClassFilter_rt/filter_rt001.java | 160 +++ .../filter_rt001/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt001a.java | 192 +++ .../addClassFilter_rt/filter_rt002.java | 530 ++++++++ .../filter_rt002/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt002a.java | 184 +++ .../addClassFilter_rt/filter_rt003.java | 182 +++ .../filter_rt003/TestDescription.java | 79 ++ .../addClassFilter_rt/filter_rt003a.java | 211 ++++ .../addClassFilter_s/filter_s001.java | 183 +++ .../filter_s001/TestDescription.java | 79 ++ .../addClassFilter_s/filter_s001a.java | 209 ++++ .../addClassFilter_s/filter_s002.java | 525 ++++++++ .../filter_s002/TestDescription.java | 78 ++ .../addClassFilter_s/filter_s002a.java | 145 +++ .../addInstanceFilter/instancefilter001.java | 190 +++ .../instancefilter001/TestDescription.java | 83 ++ .../addInstanceFilter/instancefilter001a.java | 195 +++ .../addInstanceFilter/instancefilter002.java | 556 +++++++++ .../instancefilter002/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter002a.java | 183 +++ .../addInstanceFilter/instancefilter003.java | 523 ++++++++ .../instancefilter003/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter003a.java | 183 +++ .../addInstanceFilter/instancefilter004.java | 202 ++++ .../instancefilter004/TestDescription.java | 92 ++ .../addInstanceFilter/instancefilter004a.java | 194 +++ .../addThreadFilter/threadfilter001.java | 154 +++ .../threadfilter001/TestDescription.java | 76 ++ .../addThreadFilter/threadfilter001a.java | 193 +++ .../addThreadFilter/threadfilter002.java | 538 +++++++++ .../threadfilter002/TestDescription.java | 76 ++ .../addThreadFilter/threadfilter002a.java | 184 +++ .../addThreadFilter/threadfilter003.java | 544 +++++++++ .../threadfilter003/TestDescription.java | 75 ++ .../addThreadFilter/threadfilter003a.java | 187 +++ .../addThreadFilter/threadfilter004.java | 187 +++ .../threadfilter004/TestDescription.java | 84 ++ .../addThreadFilter/threadfilter004a.java | 198 +++ .../nsk/jdi/Mirror/hashCode/hashcode001.java | 139 +++ .../hashCode/hashcode001/TestDescription.java | 64 + .../nsk/jdi/Mirror/hashCode/hashcode001a.java | 87 ++ .../nsk/jdi/Mirror/toString/tostring001.java | 211 ++++ .../toString/tostring001/TestDescription.java | 72 ++ .../nsk/jdi/Mirror/toString/tostring001a.java | 112 ++ .../virtualMachine/virtualmachine001.java | 214 ++++ .../virtualmachine001/TestDescription.java | 72 ++ .../virtualMachine/virtualmachine001a.java | 112 ++ .../_itself_/mwevent001.java | 487 ++++++++ .../_itself_/mwevent001/TestDescription.java | 69 ++ .../_itself_/mwevent001a.java | 307 +++++ .../valueToBe/valuetobe001.java | 279 +++++ .../valuetobe001/TestDescription.java | 89 ++ .../valueToBe/valuetobe001a.java | 279 +++++ .../valueToBe/valuetobe002.java | 279 +++++ .../valuetobe002/TestDescription.java | 90 ++ .../valueToBe/valuetobe002a.java | 268 +++++ .../TestDescription.java | 68 ++ .../TestDescription.java | 69 ++ .../TestDescription.java | 77 ++ .../TestDescription.java | 78 ++ .../TestDescription.java | 76 ++ .../addInstanceFilter/TestDescription.java | 76 ++ .../addThreadFilter/TestDescription.java | 78 ++ .../TestDescription.java | 68 ++ .../TestDescription.java | 69 ++ .../TestDescription.java | 77 ++ .../TestDescription.java | 78 ++ .../TestDescription.java | 76 ++ .../addInstanceFilter/TestDescription.java | 76 ++ .../addThreadFilter/TestDescription.java | 76 ++ .../TestDescription.java | 68 ++ .../TestDescription.java | 69 ++ .../TestDescription.java | 72 ++ .../TestDescription.java | 73 ++ .../TestDescription.java | 71 ++ .../addInstanceFilter/TestDescription.java | 71 ++ .../addThreadFilter/TestDescription.java | 71 ++ .../TestDescription.java | 73 ++ .../TestDescription.java | 74 ++ .../TestDescription.java | 78 ++ .../TestDescription.java | 78 ++ .../TestDescription.java | 76 ++ .../addInstanceFilter/TestDescription.java | 76 ++ .../addThreadFilter/TestDescription.java | 76 ++ .../ObjectReference/_bounds_/bounds001.java | 235 ++++ .../_bounds_/bounds001/TestDescription.java | 65 + .../ObjectReference/_bounds_/bounds001a.java | 67 ++ .../ObjectReference/_bounds_/bounds002.java | 183 +++ .../_bounds_/bounds002/TestDescription.java | 59 + .../ObjectReference/_bounds_/bounds002a.java | 61 + .../ObjectReference/_bounds_/bounds003.java | 233 ++++ .../_bounds_/bounds003/TestDescription.java | 57 + .../ObjectReference/_bounds_/bounds003a.java | 49 + .../disablecollection001.java | 226 ++++ .../disablecollection001/TestDescription.java | 87 ++ .../disablecollection001a.java | 139 +++ .../disablecollection002.java | 491 ++++++++ .../disablecollection002/TestDescription.java | 88 ++ .../disablecollection002a.java | 170 +++ .../dummyPackage/invokemethod014a.java | 182 +++ .../entryCount/entrycount001.java | 229 ++++ .../entrycount001/TestDescription.java | 87 ++ .../entryCount/entrycount001a.java | 139 +++ .../entryCount/entrycount002.java | 317 +++++ .../entrycount002/TestDescription.java | 73 ++ .../entryCount/entrycount002a.java | 125 ++ .../jdi/ObjectReference/equals/equals001.java | 263 ++++ .../equals/equals001/TestDescription.java | 76 ++ .../ObjectReference/equals/equals001a.java | 174 +++ .../ObjectReference/getValue/getvalue001.java | 612 ++++++++++ .../getValue/getvalue001/TestDescription.java | 87 ++ .../getValue/getvalue001a.java | 208 ++++ .../ObjectReference/getValue/getvalue002.java | 664 ++++++++++ .../getValue/getvalue002/TestDescription.java | 90 ++ .../getValue/getvalue002a.java | 223 ++++ .../ObjectReference/getValue/getvalue003.java | 309 +++++ .../getValue/getvalue003/TestDescription.java | 85 ++ .../getValue/getvalue003a.java | 167 +++ .../ObjectReference/getValue/getvalue004.java | 244 ++++ .../getValue/getvalue004/TestDescription.java | 83 ++ .../getValue/getvalue004a.java | 167 +++ .../getValues/getvalues001.java | 298 +++++ .../getvalues001/TestDescription.java | 85 ++ .../getValues/getvalues001a.java | 141 +++ .../getValues/getvalues002.java | 287 +++++ .../getvalues002/TestDescription.java | 86 ++ .../getValues/getvalues002a.java | 172 +++ .../getValues/getvalues003.java | 254 ++++ .../getvalues003/TestDescription.java | 82 ++ .../getValues/getvalues003a.java | 174 +++ .../ObjectReference/hashCode/hashcode001.java | 263 ++++ .../hashCode/hashcode001/TestDescription.java | 73 ++ .../hashCode/hashcode001a.java | 174 +++ .../invokeMethod/invokemethod001.java | 588 +++++++++ .../invokemethod001/TestDescription.java | 72 ++ .../invokeMethod/invokemethod001a.java | 219 ++++ .../invokeMethod/invokemethod002.java | 350 ++++++ .../invokemethod002/TestDescription.java | 60 + .../invokeMethod/invokemethod002t.java | 118 ++ .../invokeMethod/invokemethod003.java | 348 ++++++ .../invokemethod003/TestDescription.java | 60 + .../invokeMethod/invokemethod003t.java | 194 +++ .../invokeMethod/invokemethod004.java | 239 ++++ .../invokemethod004/TestDescription.java | 59 + .../invokeMethod/invokemethod004t.java | 99 ++ .../invokeMethod/invokemethod005.java | 321 +++++ .../invokemethod005/TestDescription.java | 60 + .../invokeMethod/invokemethod005t.java | 101 ++ .../invokeMethod/invokemethod006.java | 329 +++++ .../invokemethod006/TestDescription.java | 60 + .../invokeMethod/invokemethod006t.java | 88 ++ .../invokeMethod/invokemethod007.java | 352 ++++++ .../invokemethod007/TestDescription.java | 59 + .../invokeMethod/invokemethod007t.java | 140 +++ .../invokeMethod/invokemethod008.java | 369 ++++++ .../invokemethod008/TestDescription.java | 63 + .../invokeMethod/invokemethod008t.java | 122 ++ .../invokeMethod/invokemethod009.java | 369 ++++++ .../invokemethod009/TestDescription.java | 67 ++ .../invokeMethod/invokemethod009t.java | 122 ++ .../invokeMethod/invokemethod010.java | 478 ++++++++ .../invokemethod010/TestDescription.java | 71 ++ .../invokeMethod/invokemethod010t.java | 195 +++ .../invokeMethod/invokemethod011.java | 478 ++++++++ .../invokemethod011/TestDescription.java | 75 ++ .../invokeMethod/invokemethod011t.java | 195 +++ .../invokeMethod/invokemethod012.java | 521 ++++++++ .../invokemethod012/TestDescription.java | 68 ++ .../invokeMethod/invokemethod012t.java | 195 +++ .../invokeMethod/invokemethod013.java | 524 ++++++++ .../invokemethod013/TestDescription.java | 68 ++ .../invokeMethod/invokemethod013t.java | 194 +++ .../invokeMethod/invokemethod014.java | 356 ++++++ .../invokemethod014/TestDescription.java | 64 + .../invokeMethod/invokemethod014t.java | 146 +++ .../isCollected/iscollected001.java | 220 ++++ .../iscollected001/TestDescription.java | 73 ++ .../isCollected/iscollected001a.java | 139 +++ .../owningThread/owningthread001.java | 278 +++++ .../owningthread001/TestDescription.java | 83 ++ .../owningThread/owningthread001a.java | 222 ++++ .../owningThread/owningthread002.java | 325 +++++ .../owningthread002/TestDescription.java | 73 ++ .../owningThread/owningthread002a.java | 166 +++ .../referenceType/referencetype001.java | 291 +++++ .../referencetype001/TestDescription.java | 85 ++ .../referenceType/referencetype001a.java | 175 +++ .../referenceType/referencetype002.java | 245 ++++ .../referencetype002/TestDescription.java | 85 ++ .../referenceType/referencetype002a.java | 115 ++ .../referenceType/referencetype003.java | 273 +++++ .../referencetype003/TestDescription.java | 85 ++ .../referenceType/referencetype003a.java | 189 +++ .../referenceType/referencetype004.java | 244 ++++ .../referencetype004/TestDescription.java | 85 ++ .../referenceType/referencetype004a.java | 123 ++ .../referenceType/referencetype005.java | 254 ++++ .../referencetype005/TestDescription.java | 85 ++ .../referenceType/referencetype005a.java | 150 +++ .../referenceType/referencetype006.java | 255 ++++ .../referencetype006/TestDescription.java | 85 ++ .../referenceType/referencetype006a.java | 137 +++ .../referenceType/referencetype007.java | 254 ++++ .../referencetype007/TestDescription.java | 85 ++ .../referenceType/referencetype007a.java | 124 ++ .../referringObjects001.java | 251 ++++ .../referringObjects002.java | 172 +++ .../referringObjects002a.java | 130 ++ .../referringObjects003.java | 235 ++++ .../referringObjects003a.java | 122 ++ .../referringObjects004.java | 144 +++ .../ObjectReference/setValue/setvalue001.java | 458 +++++++ .../setValue/setvalue001/TestDescription.java | 99 ++ .../setValue/setvalue001a.java | 144 +++ .../ObjectReference/setValue/setvalue002.java | 257 ++++ .../setValue/setvalue002/TestDescription.java | 68 ++ .../setValue/setvalue002t.java | 107 ++ .../ObjectReference/setValue/setvalue003.java | 264 ++++ .../setValue/setvalue003/TestDescription.java | 64 + .../setValue/setvalue003t.java | 81 ++ .../ObjectReference/setValue/setvalue004.java | 228 ++++ .../setValue/setvalue004/TestDescription.java | 58 + .../setValue/setvalue004t.java | 69 ++ .../ObjectReference/setValue/setvalue005.java | 251 ++++ .../setValue/setvalue005/TestDescription.java | 61 + .../setValue/setvalue005t.java | 69 ++ .../ObjectReference/uniqueID/uniqueid001.java | 220 ++++ .../uniqueID/uniqueid001/TestDescription.java | 78 ++ .../uniqueID/uniqueid001a.java | 139 +++ .../waitingThreads/waitingthreads001.java | 229 ++++ .../waitingthreads001/TestDescription.java | 88 ++ .../waitingThreads/waitingthreads001a.java | 139 +++ .../waitingThreads/waitingthreads002.java | 196 +++ .../waitingthreads002/TestDescription.java | 72 ++ .../waitingThreads/waitingthreads002a.java | 150 +++ .../waitingThreads/waitingthreads003.java | 196 +++ .../waitingthreads003/TestDescription.java | 72 ++ .../waitingThreads/waitingthreads003a.java | 157 +++ .../waitingThreads/waitingthreads004.java | 196 +++ .../waitingthreads004/TestDescription.java | 72 ++ .../waitingThreads/waitingthreads004a.java | 159 +++ .../baseDirectory/directory001.java | 206 ++++ .../directory001/TestDescription.java | 69 ++ .../baseDirectory/directory001a.java | 111 ++ .../bootClassPath/bootpath001.java | 219 ++++ .../bootpath001/TestDescription.java | 75 ++ .../bootClassPath/bootpath001a.java | 111 ++ .../classPath/classpath001.java | 484 ++++++++ .../classpath001/TestDescription.java | 76 ++ .../classPath/classpath001a.java | 118 ++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugAttachConnector001.java | 52 + .../plugAttachConnect001.java | 243 ++++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugAttachConnector002.java | 104 ++ .../plugAttachConnect002.java | 278 +++++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugAttachConnector003.java | 110 ++ .../plugAttachConnect003.java | 211 ++++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugLaunchConnector001.java | 52 + .../plugLaunchConnect001.java | 245 ++++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugLaunchConnector002.java | 104 ++ .../plugLaunchConnect002.java | 278 +++++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugLaunchConnector003.java | 111 ++ .../plugLaunchConnect003.java | 211 ++++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugListenConnector001.java | 52 + .../plugListenConnect001.java | 245 ++++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugListenConnector002.java | 105 ++ .../plugListenConnect002.java | 278 +++++ .../services/com.sun.jdi.connect.Connector | 23 + .../connectors/PlugListenConnector003.java | 111 ++ .../plugListenConnect003.java | 211 ++++ .../services/com.sun.jdi.connect.Connector | 29 + .../connectors/PlugAttachConnector001_01.java | 56 + .../connectors/PlugAttachConnector001_02.java | 109 ++ .../connectors/PlugLaunchConnector001_01.java | 56 + .../connectors/PlugLaunchConnector001_02.java | 108 ++ .../connectors/PlugListenConnector001_01.java | 56 + .../connectors/PlugListenConnector001_02.java | 108 ++ .../plugMultiConnect001.java | 348 ++++++ .../services/com.sun.jdi.connect.Connector | 32 + .../connectors/PlugAttachConnector002_01.java | 56 + .../connectors/PlugAttachConnector002_02.java | 108 ++ .../connectors/PlugAttachConnector002_03.java | 110 ++ .../connectors/PlugLaunchConnector002_01.java | 56 + .../connectors/PlugLaunchConnector002_02.java | 108 ++ .../connectors/PlugLaunchConnector002_03.java | 111 ++ .../connectors/PlugListenConnector002_01.java | 56 + .../connectors/PlugListenConnector002_02.java | 108 ++ .../connectors/PlugListenConnector002_03.java | 110 ++ .../plugMultiConnect002.java | 488 ++++++++ .../com.sun.jdi.connect.spi.TransportService | 24 + .../PlugTransportService003_01.java | 58 + .../PlugTransportService003_02.java | 58 + .../plugMultiConnect003.java | 496 ++++++++ .../com.sun.jdi.connect.spi.TransportService | 25 + .../PlugTransportService004_01.java | 58 + .../PlugTransportService004_02.java | 58 + .../PlugTransportService004_03.java | 66 + .../plugMultiConnect004.java | 628 ++++++++++ .../services/com.sun.jdi.connect.Connector | 29 + .../com.sun.jdi.connect.spi.TransportService | 24 + .../connectors/PlugAttachConnector005_01.java | 56 + .../connectors/PlugAttachConnector005_02.java | 109 ++ .../connectors/PlugLaunchConnector005_01.java | 56 + .../connectors/PlugLaunchConnector005_02.java | 109 ++ .../connectors/PlugListenConnector005_01.java | 56 + .../connectors/PlugListenConnector005_02.java | 109 ++ .../PlugTransportService005_01.java | 58 + .../PlugTransportService005_02.java | 58 + .../plugMultiConnect005.java | 673 +++++++++++ .../services/com.sun.jdi.connect.Connector | 32 + .../com.sun.jdi.connect.spi.TransportService | 25 + .../connectors/PlugAttachConnector006_01.java | 56 + .../connectors/PlugAttachConnector006_02.java | 109 ++ .../connectors/PlugAttachConnector006_03.java | 111 ++ .../connectors/PlugLaunchConnector006_01.java | 56 + .../connectors/PlugLaunchConnector006_02.java | 109 ++ .../connectors/PlugLaunchConnector006_03.java | 111 ++ .../connectors/PlugListenConnector006_01.java | 56 + .../connectors/PlugListenConnector006_02.java | 109 ++ .../connectors/PlugListenConnector006_03.java | 111 ++ .../PlugTransportService006_01.java | 58 + .../PlugTransportService006_02.java | 58 + .../PlugTransportService006_03.java | 66 + .../plugMultiConnect006.java | 921 ++++++++++++++ .../com.sun.jdi.connect.spi.TransportService | 23 + .../connectors/PlugTransportService001.java | 58 + .../transportService001.java | 396 ++++++ .../com.sun.jdi.connect.spi.TransportService | 23 + .../connectors/PlugTransportService002.java | 58 + .../transportService002.java | 396 ++++++ .../com.sun.jdi.connect.spi.TransportService | 23 + .../connectors/PlugTransportService003.java | 65 + .../transportService003.java | 254 ++++ .../_itself_/primitivetype001.java | 452 +++++++ .../primitivetype001/TestDescription.java | 65 + .../_itself_/primitivetype001a.java | 120 ++ .../booleanValue/booleanvalue001.java | 340 ++++++ .../booleanvalue001/TestDescription.java | 72 ++ .../booleanValue/booleanvalue001a.java | 130 ++ .../byteValue/bytevalue001.java | 344 ++++++ .../bytevalue001/TestDescription.java | 74 ++ .../byteValue/bytevalue001a.java | 130 ++ .../charValue/charvalue001.java | 344 ++++++ .../charvalue001/TestDescription.java | 74 ++ .../charValue/charvalue001a.java | 130 ++ .../doubleValue/doublevalue001.java | 344 ++++++ .../doublevalue001/TestDescription.java | 73 ++ .../doubleValue/doublevalue001a.java | 130 ++ .../doubleValue/doublevalue002.java | 274 +++++ .../doublevalue002/TestDescription.java | 72 ++ .../doubleValue/doublevalue002a.java | 135 +++ .../floatValue/floatvalue001.java | 344 ++++++ .../floatvalue001/TestDescription.java | 74 ++ .../floatValue/floatvalue001a.java | 130 ++ .../PrimitiveValue/intValue/intvalue001.java | 344 ++++++ .../intValue/intvalue001/TestDescription.java | 74 ++ .../PrimitiveValue/intValue/intvalue001a.java | 130 ++ .../longValue/longvalue001.java | 344 ++++++ .../longvalue001/TestDescription.java | 74 ++ .../longValue/longvalue001a.java | 130 ++ .../shortValue/shortvalue001.java | 344 ++++++ .../shortvalue001/TestDescription.java | 74 ++ .../shortValue/shortvalue001a.java | 130 ++ .../jdi/ReferenceType/_bounds_/bounds001.java | 191 +++ .../_bounds_/bounds001/TestDescription.java | 60 + .../ReferenceType/_bounds_/bounds001a.java | 50 + .../jdi/ReferenceType/_bounds_/bounds002.java | 206 ++++ .../_bounds_/bounds002/TestDescription.java | 57 + .../ReferenceType/_bounds_/bounds002a.java | 61 + .../ReferenceType/allFields/allfields001.java | 322 +++++ .../allfields001/TestDescription.java | 59 + .../allFields/allfields001a.java | 162 +++ .../ReferenceType/allFields/allfields002.java | 219 ++++ .../allfields002/TestDescription.java | 67 ++ .../allfields002/loadclass/allfields002b.java | 50 + .../allFields/allfields002a.java | 139 +++ .../ReferenceType/allFields/allfields003.java | 254 ++++ .../allFields/allfields003/TEST.properties | 24 + .../allfields003/TestDescription.java | 70 ++ .../allfields003/loadclass/allfields003b.java | 29 + .../allFields/allfields003a.java | 122 ++ .../ReferenceType/allFields/allfields004.java | 208 ++++ .../allfields004/TestDescription.java | 57 + .../allFields/allfields004a.java | 83 ++ .../ReferenceType/allFields/allfields005.java | 287 +++++ .../allfields005/TestDescription.java | 56 + .../allFields/allfields005t.java | 91 ++ .../ReferenceType/allFields/allfields006.java | 154 +++ .../allfields006/TestDescription.java | 67 ++ .../allFields/allfields006a.java | 98 ++ .../allLineLocations/alllinelocations001.java | 262 ++++ .../alllinelocations001/TestDescription.java | 87 ++ .../alllinelocations001a.java | 146 +++ .../allLineLocations/alllinelocations002.java | 295 +++++ .../alllinelocations002/TestDescription.java | 58 + .../alllinelocations002t.java | 98 ++ .../allLineLocations_ss003.java | 182 +++ .../allLineLocations_ss004.java | 182 +++ .../alllinelocations_ss001.java | 265 ++++ .../TestDescription.java | 106 ++ .../alllinelocations_ss001a.java | 147 +++ .../alllinelocations_ss002.java | 313 +++++ .../TestDescription.java | 58 + .../alllinelocations_ss002t.java | 98 ++ .../allMethods/allmethods001.java | 372 ++++++ .../allmethods001/TestDescription.java | 58 + .../allMethods/allmethods001a.java | 248 ++++ .../allMethods/allmethods002.java | 221 ++++ .../allmethods002/TestDescription.java | 67 ++ .../allmethods002aClassForCheck.java | 69 ++ .../allMethods/allmethods002a.java | 141 +++ .../allMethods/allmethods003.java | 255 ++++ .../allMethods/allmethods003/TEST.properties | 24 + .../allmethods003/TestDescription.java | 70 ++ .../loadclass/allmethods003b.java | 29 + .../allMethods/allmethods003a.java | 118 ++ .../allMethods/allmethods004.java | 205 ++++ .../allmethods004/TestDescription.java | 56 + .../allMethods/allmethods004a.java | 81 ++ .../allMethods/allmethods005.java | 286 +++++ .../allmethods005/TestDescription.java | 55 + .../allMethods/allmethods005t.java | 91 ++ .../allMethods/allmethods006.java | 163 +++ .../allmethods006/TestDescription.java | 78 ++ .../allMethods/allmethods006a.java | 110 ++ .../availableStrata002.java | 111 ++ .../availableStrata/availablestrata001.java | 220 ++++ .../availablestrata001/TestDescription.java | 73 ++ .../availableStrata/availablestrata001a.java | 116 ++ .../classLoader/classloader001.java | 467 +++++++ .../classloader001/TestDescription.java | 78 ++ .../loadclass/classloader001b.java | 28 + .../loadclass1/classloader001c.java | 28 + .../classLoader/classloader001a.java | 154 +++ .../classObject/classobj001.java | 228 ++++ .../classobj001/TestDescription.java | 55 + .../classObject/classobj001a.java | 120 ++ .../classObject/classobj002.java | 254 ++++ .../classObject/classobj002/TEST.properties | 24 + .../classobj002/TestDescription.java | 70 ++ .../classobj002/loadclass/classobj002b.java | 29 + .../classObject/classobj002a.java | 118 ++ .../classObject/classobj003.java | 139 +++ .../classobj003/TestDescription.java | 65 + .../classObject/classobj003a.java | 167 +++ .../defaultStratum002/defaultStratum002.java | 194 +++ .../defaultStratum003/defaultStratum003.java | 188 +++ .../defaultStratum004/TestClass1.java | 40 + .../defaultStratum004/TestClass2.java | 40 + .../defaultStratum004/TestClass3.java | 40 + .../defaultStratum004/defaultStratum004.java | 196 +++ .../defaultStratum004/defaultStratum004a.java | 115 ++ .../defaultStratum/defaultstratum001.java | 204 ++++ .../defaultstratum001/TestDescription.java | 75 ++ .../defaultStratum/defaultstratum001a.java | 116 ++ .../dummyPackage/getvalues003a.java | 66 + .../jdi/ReferenceType/equals/equals001.java | 246 ++++ .../equals/equals001/TestDescription.java | 61 + .../jdi/ReferenceType/equals/equals001a.java | 152 +++ .../jdi/ReferenceType/equals/equals002.java | 251 ++++ .../equals/equals002/TEST.properties | 24 + .../equals/equals002/TestDescription.java | 70 ++ .../equals002/loadclass/equals002b.java | 29 + .../jdi/ReferenceType/equals/equals002a.java | 117 ++ .../failedToInitialize001.java | 202 ++++ .../TestDescription.java | 54 + .../failedToInitialize001a.java | 126 ++ .../failedToInitialize/failedtoinit002.java | 250 ++++ .../failedtoinit002/TEST.properties | 24 + .../failedtoinit002/TestDescription.java | 70 ++ .../loadclass/failedtoinit002b.java | 29 + .../failedToInitialize/failedtoinit002a.java | 117 ++ .../fieldByName/fieldbyname001.java | 349 ++++++ .../fieldbyname001/TestDescription.java | 61 + .../fieldByName/fieldbyname001a.java | 162 +++ .../fieldByName/fieldbyname002.java | 221 ++++ .../fieldbyname002/TestDescription.java | 67 ++ .../fieldbyname002aClassForCheck.java | 51 + .../fieldByName/fieldbyname002a.java | 141 +++ .../fieldByName/fieldbyname003.java | 256 ++++ .../fieldbyname003/TEST.properties | 24 + .../fieldbyname003/TestDescription.java | 70 ++ .../loadclass/fieldbyname003b.java | 29 + .../fieldByName/fieldbyname003a.java | 118 ++ .../jdi/ReferenceType/fields/fields001.java | 284 +++++ .../fields/fields001/TestDescription.java | 59 + .../jdi/ReferenceType/fields/fields001a.java | 162 +++ .../jdi/ReferenceType/fields/fields002.java | 216 ++++ .../fields/fields002/TestDescription.java | 67 ++ .../loadclass/fields002aClassForCheck.java | 51 + .../jdi/ReferenceType/fields/fields002a.java | 141 +++ .../jdi/ReferenceType/fields/fields003.java | 250 ++++ .../fields/fields003/TEST.properties | 24 + .../fields/fields003/TestDescription.java | 70 ++ .../fields003/loadclass/fields003b.java | 29 + .../jdi/ReferenceType/fields/fields003a.java | 117 ++ .../jdi/ReferenceType/fields/fields004.java | 206 ++++ .../fields/fields004/TestDescription.java | 59 + .../jdi/ReferenceType/fields/fields004a.java | 128 ++ .../jdi/ReferenceType/fields/fields005.java | 287 +++++ .../fields/fields005/TestDescription.java | 56 + .../jdi/ReferenceType/fields/fields005t.java | 91 ++ .../jdi/ReferenceType/fields/fields006.java | 156 +++ .../fields/fields006/TestDescription.java | 68 ++ .../jdi/ReferenceType/fields/fields006a.java | 110 ++ .../genericSignature/genericSignature001.java | 263 ++++ .../genericSignature001/TestDescription.java | 62 + .../genericSignature001a.java | 171 +++ .../genericSignature/genericSignature002.java | 241 ++++ .../genericSignature002/TestDescription.java | 60 + .../genericSignature002a.java | 155 +++ .../ReferenceType/getValue/getvalue001.java | 476 ++++++++ .../getValue/getvalue001/TestDescription.java | 76 ++ .../ReferenceType/getValue/getvalue001a.java | 134 +++ .../ReferenceType/getValue/getvalue002.java | 476 ++++++++ .../getValue/getvalue002/TestDescription.java | 76 ++ .../ReferenceType/getValue/getvalue002a.java | 146 +++ .../ReferenceType/getValue/getvalue003.java | 476 ++++++++ .../getValue/getvalue003/TestDescription.java | 78 ++ .../ReferenceType/getValue/getvalue003a.java | 160 +++ .../ReferenceType/getValue/getvalue004.java | 300 +++++ .../getValue/getvalue004/TestDescription.java | 61 + .../ReferenceType/getValue/getvalue004t.java | 92 ++ .../ReferenceType/getValue/getvalue005.java | 299 +++++ .../getValue/getvalue005/TestDescription.java | 56 + .../ReferenceType/getValue/getvalue005t.java | 105 ++ .../ReferenceType/getValues/getvalues001.java | 504 ++++++++ .../getvalues001/TestDescription.java | 79 ++ .../getValues/getvalues001a.java | 134 +++ .../ReferenceType/getValues/getvalues002.java | 309 +++++ .../getvalues002/TestDescription.java | 62 + .../getValues/getvalues002t.java | 101 ++ .../ReferenceType/getValues/getvalues003.java | 318 +++++ .../getvalues003/TestDescription.java | 63 + .../getValues/getvalues003t.java | 66 + .../ReferenceType/hashCode/hashcode001.java | 251 ++++ .../hashCode/hashcode001/TestDescription.java | 58 + .../ReferenceType/hashCode/hashcode001a.java | 150 +++ .../ReferenceType/hashCode/hashcode002.java | 251 ++++ .../hashCode/hashcode002/TEST.properties | 24 + .../hashCode/hashcode002/TestDescription.java | 70 ++ .../hashcode002/loadclass/hashcode002b.java | 29 + .../ReferenceType/hashCode/hashcode002a.java | 117 ++ .../instances/instances001/instances001.java | 207 ++++ .../instances/instances002/instances002.java | 209 ++++ .../instances/instances002/instances002a.java | 39 + .../instances/instances003/instances003.java | 180 +++ .../instances004/TestDescription.java | 60 + .../instances/instances005/instances005.java | 134 +++ .../isAbstract/isAbstract001.java | 199 +++ .../isAbstract001/TestDescription.java | 54 + .../isAbstract/isAbstract001a.java | 110 ++ .../isAbstract/isabstract002.java | 250 ++++ .../isAbstract/isabstract002/TEST.properties | 24 + .../isabstract002/TestDescription.java | 70 ++ .../loadclass/isabstract002b.java | 29 + .../isAbstract/isabstract002a.java | 117 ++ .../isAbstract/isabstract003.java | 131 ++ .../isabstract003/TestDescription.java | 66 + .../isAbstract/isabstract003a.java | 97 ++ .../jdi/ReferenceType/isFinal/isfinal001.java | 553 +++++++++ .../isFinal/isfinal001/TestDescription.java | 71 ++ .../ReferenceType/isFinal/isfinal001a.java | 174 +++ .../jdi/ReferenceType/isFinal/isfinal002.java | 135 +++ .../isFinal/isfinal002/TestDescription.java | 64 + .../ReferenceType/isFinal/isfinal002a.java | 108 ++ .../isInitialized/isinit001.java | 218 ++++ .../isinit001/TestDescription.java | 65 + .../isInitialized/isinit001a.java | 113 ++ .../isInitialized/isinit002.java | 250 ++++ .../isInitialized/isinit002/TEST.properties | 24 + .../isinit002/TestDescription.java | 70 ++ .../isinit002/loadclass/isinit002b.java | 29 + .../isInitialized/isinit002a.java | 117 ++ .../isInitialized/isinit003.java | 131 ++ .../isinit003/TestDescription.java | 65 + .../isInitialized/isinit003a.java | 164 +++ .../isPrepared/isprepared001.java | 216 ++++ .../isprepared001/TestDescription.java | 65 + .../isPrepared/isprepared001a.java | 97 ++ .../isPrepared/isprepared002.java | 251 ++++ .../isPrepared/isprepared002/TEST.properties | 24 + .../isprepared002/TestDescription.java | 70 ++ .../loadclass/isprepared002b.java | 29 + .../isPrepared/isprepared002a.java | 117 ++ .../ReferenceType/isStatic/isstatic001.java | 571 +++++++++ .../isStatic/isstatic001/TestDescription.java | 77 ++ .../ReferenceType/isStatic/isstatic001a.java | 186 +++ .../ReferenceType/isStatic/isstatic002.java | 482 ++++++++ .../isStatic/isstatic002/TestDescription.java | 75 ++ .../ReferenceType/isStatic/isstatic002a.java | 139 +++ .../isVerified/isVerified001.java | 205 ++++ .../isVerified001/TestDescription.java | 60 + .../isVerified/isVerified001a.java | 108 ++ .../isVerified/isverified002.java | 252 ++++ .../isVerified/isverified002/TEST.properties | 24 + .../isverified002/TestDescription.java | 72 ++ .../loadclass/isverified002b.java | 29 + .../isVerified/isverified002a.java | 118 ++ .../isVerified/isverified003.java | 154 +++ .../isverified003/TestDescription.java | 68 ++ .../loadclass/isverified003b.java | 29 + .../loadclass/isverified003c.java | 29 + .../isVerified/isverified003a.java | 165 +++ .../locationsofline_i001.java | 261 ++++ .../locationsofline_i001/TestDescription.java | 94 ++ .../locationsofline_i001a.java | 136 +++ .../locationsofline_i002.java | 295 +++++ .../locationsofline_i002/TestDescription.java | 58 + .../locationsofline_i002t.java | 98 ++ .../locationsOfLine_ssi003.java | 227 ++++ .../locationsOfLine_ssi004.java | 160 +++ .../locationsofline_ssi001.java | 265 ++++ .../TestDescription.java | 101 ++ .../locationsofline_ssi001a.java | 136 +++ .../locationsofline_ssi002.java | 314 +++++ .../TestDescription.java | 58 + .../locationsofline_ssi002t.java | 98 ++ .../jdi/ReferenceType/methods/methods001.java | 328 +++++ .../methods/methods001/TestDescription.java | 58 + .../ReferenceType/methods/methods001a.java | 249 ++++ .../jdi/ReferenceType/methods/methods002.java | 216 ++++ .../methods/methods002/TestDescription.java | 67 ++ .../loadclass/methods002aClassForCheck.java | 68 ++ .../ReferenceType/methods/methods002a.java | 140 +++ .../jdi/ReferenceType/methods/methods003.java | 251 ++++ .../methods/methods003/TEST.properties | 24 + .../methods/methods003/TestDescription.java | 70 ++ .../methods003/loadclass/methods003b.java | 29 + .../ReferenceType/methods/methods003a.java | 117 ++ .../jdi/ReferenceType/methods/methods004.java | 203 ++++ .../methods/methods004/TestDescription.java | 57 + .../ReferenceType/methods/methods004a.java | 90 ++ .../jdi/ReferenceType/methods/methods005.java | 286 +++++ .../methods/methods005/TestDescription.java | 55 + .../ReferenceType/methods/methods005t.java | 91 ++ .../jdi/ReferenceType/methods/methods006.java | 154 +++ .../methods/methods006/TestDescription.java | 67 ++ .../ReferenceType/methods/methods006a.java | 121 ++ .../methodsByName_s/methbyname_s001.java | 420 +++++++ .../methbyname_s001/TestDescription.java | 57 + .../methodsByName_s/methbyname_s001a.java | 249 ++++ .../methodsByName_s/methbyname_s002.java | 222 ++++ .../methbyname_s002/TestDescription.java | 67 ++ .../methbyname_s002aClassForCheck.java | 71 ++ .../methodsByName_s/methbyname_s002a.java | 141 +++ .../methodsByName_s/methbyname_s003.java | 256 ++++ .../methbyname_s003/TEST.properties | 24 + .../methbyname_s003/TestDescription.java | 70 ++ .../loadclass/methbyname_s003b.java | 29 + .../methodsByName_s/methbyname_s003a.java | 117 ++ .../methodsByName_s/methbyname_s004.java | 399 ++++++ .../methbyname_s004/TestDescription.java | 57 + .../methodsByName_s/methbyname_s004a.java | 127 ++ .../methodsByName_ss/methbyname_ss001.java | 444 +++++++ .../methbyname_ss001/TestDescription.java | 57 + .../methodsByName_ss/methbyname_ss001a.java | 272 +++++ .../methodsByName_ss/methbyname_ss002.java | 221 ++++ .../methbyname_ss002/TestDescription.java | 67 ++ .../methbyname_ss002aClassForCheck.java | 71 ++ .../methodsByName_ss/methbyname_ss002a.java | 141 +++ .../methodsByName_ss/methbyname_ss003.java | 252 ++++ .../methbyname_ss003/TEST.properties | 24 + .../methbyname_ss003/TestDescription.java | 70 ++ .../loadclass/methbyname_ss003b.java | 30 + .../methodsByName_ss/methbyname_ss003a.java | 117 ++ .../nsk/jdi/ReferenceType/name/name001.java | 237 ++++ .../name/name001/TestDescription.java | 59 + .../nsk/jdi/ReferenceType/name/name001a.java | 119 ++ .../nsk/jdi/ReferenceType/name/name002.java | 251 ++++ .../name/name002/TEST.properties | 24 + .../name/name002/TestDescription.java | 70 ++ .../name/name002/loadclass/name002b.java | 29 + .../nsk/jdi/ReferenceType/name/name002a.java | 117 ++ .../nestedTypes/nestedtypes001.java | 492 ++++++++ .../nestedtypes001/TestDescription.java | 79 ++ .../nestedTypes/nestedtypes001a.java | 139 +++ .../nestedTypes/nestedtypes002.java | 511 ++++++++ .../nestedtypes002/TestDescription.java | 88 ++ .../nestedTypes/nestedtypes002a.java | 150 +++ .../sourceDebugExtension/srcdebugx001.java | 125 ++ .../srcdebugx001/TestDescription.java | 58 + .../sourceDebugExtension/srcdebugx001t.java | 52 + .../sourceDebugExtension/srcdebugx002.java | 121 ++ .../srcdebugx002/TestDescription.java | 60 + .../srcdebugx002/srcdebugx002x.jcod | 125 ++ .../sourceDebugExtension/srcdebugx002t.java | 63 + .../sourceDebugExtension/srcdebugx002x.java | 34 + .../sourceName/sourcename001.java | 216 ++++ .../sourcename001/TestDescription.java | 59 + .../sourceName/sourcename001a.java | 100 ++ .../sourceName/sourcename002.java | 251 ++++ .../sourceName/sourcename002/TEST.properties | 24 + .../sourcename002/TestDescription.java | 70 ++ .../loadclass/sourcename002b.java | 29 + .../sourceName/sourcename002a.java | 117 ++ .../sourceName/sourcename003.java | 200 +++ .../sourcename003/TestDescription.java | 57 + .../sourceName/sourcename003a.java | 75 ++ .../sourceName/sourcename004.java | 328 +++++ .../sourcename004/TestDescription.java | 60 + .../sourceName/sourcename004t.java | 108 ++ .../sourceNames003/sourceNames003.java | 141 +++ .../sourceNames/sourcenames001.java | 244 ++++ .../sourcenames001/TestDescription.java | 91 ++ .../sourceNames/sourcenames001a.java | 111 ++ .../sourceNames/sourcenames002.java | 342 ++++++ .../sourcenames002/TestDescription.java | 60 + .../sourceNames/sourcenames002t.java | 108 ++ .../sourcePaths003/sourcePaths003.java | 133 ++ .../sourcePaths/sourcepaths001.java | 282 +++++ .../sourcepaths001/TestDescription.java | 92 ++ .../sourcePaths/sourcepaths001a.java | 111 ++ .../sourcePaths/sourcepaths002.java | 304 +++++ .../sourcepaths002/TestDescription.java | 58 + .../sourcePaths/sourcepaths002t.java | 93 ++ .../visibleFields/visibfield001.java | 300 +++++ .../visibfield001/TestDescription.java | 59 + .../visibleFields/visibfield001a.java | 163 +++ .../visibleFields/visibfield002.java | 221 ++++ .../visibfield002/TestDescription.java | 67 ++ .../visibfield002aClassForCheck.java | 52 + .../visibleFields/visibfield002a.java | 141 +++ .../visibleFields/visibfield003.java | 255 ++++ .../visibfield003/TEST.properties | 24 + .../visibfield003/TestDescription.java | 70 ++ .../loadclass/visibfield003b.java | 29 + .../visibleFields/visibfield003a.java | 117 ++ .../visibleFields/visibfield004.java | 208 ++++ .../visibfield004/TestDescription.java | 58 + .../visibleFields/visibfield004a.java | 91 ++ .../visibleFields/visibfield005.java | 287 +++++ .../visibfield005/TestDescription.java | 56 + .../visibleFields/visibfield005t.java | 91 ++ .../visibleFields/visibfield006.java | 161 +++ .../visibfield006/TestDescription.java | 71 ++ .../visibleFields/visibfield006a.java | 115 ++ .../visibleMethods/visibmethod001.java | 350 ++++++ .../visibmethod001/TestDescription.java | 58 + .../visibleMethods/visibmethod001a.java | 249 ++++ .../visibleMethods/visibmethod002.java | 221 ++++ .../visibmethod002/TestDescription.java | 67 ++ .../visibmethod002aClassForCheck.java | 69 ++ .../visibleMethods/visibmethod002a.java | 141 +++ .../visibleMethods/visibmethod003.java | 255 ++++ .../visibmethod003/TEST.properties | 24 + .../visibmethod003/TestDescription.java | 70 ++ .../loadclass/visibmethod003b.java | 29 + .../visibleMethods/visibmethod003a.java | 117 ++ .../visibleMethods/visibmethod004.java | 205 ++++ .../visibmethod004/TestDescription.java | 56 + .../visibleMethods/visibmethod004a.java | 81 ++ .../visibleMethods/visibmethod005.java | 253 ++++ .../visibmethod005/TestDescription.java | 58 + .../visibleMethods/visibmethod005a.java | 105 ++ .../visibleMethods/visibmethod006.java | 287 +++++ .../visibmethod006/TestDescription.java | 56 + .../visibleMethods/visibmethod006t.java | 91 ++ .../visibleMethods/visibmethod007.java | 160 +++ .../visibmethod007/TestDescription.java | 79 ++ .../visibleMethods/visibmethod007a.java | 110 ++ .../Scenarios/invokeMethod/popframes001.java | 324 +++++ .../popframes001/TestDescription.java | 69 ++ .../Scenarios/invokeMethod/popframes001a.java | 78 ++ .../invokeMethod/redefineclasses001.java | 307 +++++ .../redefineclasses001/TestDescription.java | 69 ++ .../newclass/redefineclasses001b.java | 93 ++ .../invokeMethod/redefineclasses001a.java | 87 ++ .../invokeMethod/redefineclasses001b.java | 93 ++ .../SelectedArgument/choices/choices001.java | 155 +++ .../choices/choices001/TestDescription.java | 74 ++ .../SelectedArgument/isValid/isvalid001.java | 158 +++ .../isValid/isvalid001/TestDescription.java | 67 ++ .../SelectedArgument/isValid/isvalid002.java | 166 +++ .../isValid/isvalid002/TestDescription.java | 68 ++ .../jdi/ShortType/_itself_/shorttype001.java | 456 +++++++ .../shorttype001/TestDescription.java | 66 + .../jdi/ShortType/_itself_/shorttype001a.java | 113 ++ .../ShortValue/compareTo/compareto001.java | 296 +++++ .../compareto001/TestDescription.java | 70 ++ .../ShortValue/compareTo/compareto001a.java | 175 +++ .../nsk/jdi/ShortValue/equals/equals001.java | 247 ++++ .../equals/equals001/TestDescription.java | 73 ++ .../nsk/jdi/ShortValue/equals/equals001a.java | 125 ++ .../nsk/jdi/ShortValue/equals/equals002.java | 213 ++++ .../equals/equals002/TestDescription.java | 66 + .../nsk/jdi/ShortValue/equals/equals002a.java | 142 +++ .../jdi/ShortValue/hashCode/hashcode001.java | 234 ++++ .../hashCode/hashcode001/TestDescription.java | 71 ++ .../jdi/ShortValue/hashCode/hashcode001a.java | 125 ++ .../nsk/jdi/ShortValue/value/value001.java | 243 ++++ .../value/value001/TestDescription.java | 71 ++ .../nsk/jdi/ShortValue/value/value001a.java | 125 ++ .../jdi/StackFrame/_bounds_/bounds001.java | 255 ++++ .../_bounds_/bounds001/TestDescription.java | 63 + .../jdi/StackFrame/_bounds_/bounds001a.java | 99 ++ .../jdi/StackFrame/_bounds_/bounds002.java | 232 ++++ .../_bounds_/bounds002/TestDescription.java | 69 ++ .../jdi/StackFrame/_bounds_/bounds002a.java | 55 + .../getArgumentValues001.java | 265 ++++ .../getArgumentValues001a.java | 483 ++++++++ .../getArgumentValues002.java | 138 +++ .../getArgumentValues002a.java | 142 +++ .../getArgumentValues003.java | 114 ++ .../getArgumentValues003a.java | 97 ++ .../jdi/StackFrame/getValue/getvalue001.java | 749 ++++++++++++ .../getValue/getvalue001/TestDescription.java | 97 ++ .../jdi/StackFrame/getValue/getvalue001a.java | 209 ++++ .../jdi/StackFrame/getValue/getvalue002.java | 565 +++++++++ .../getValue/getvalue002/TestDescription.java | 97 ++ .../jdi/StackFrame/getValue/getvalue002a.java | 229 ++++ .../jdi/StackFrame/getValue/getvalue003.java | 312 +++++ .../getValue/getvalue003/TestDescription.java | 63 + .../jdi/StackFrame/getValue/getvalue003t.java | 165 +++ .../StackFrame/getValues/getvalues001.java | 611 ++++++++++ .../getvalues001/TestDescription.java | 89 ++ .../StackFrame/getValues/getvalues001a.java | 210 ++++ .../StackFrame/getValues/getvalues002.java | 562 +++++++++ .../getvalues002/TestDescription.java | 97 ++ .../StackFrame/getValues/getvalues002a.java | 220 ++++ .../StackFrame/getValues/getvalues003.java | 350 ++++++ .../getvalues003/TestDescription.java | 63 + .../StackFrame/getValues/getvalues003t.java | 182 +++ .../jdi/StackFrame/hashCode/hashcode001.java | 183 +++ .../hashCode/hashcode001/TestDescription.java | 70 ++ .../jdi/StackFrame/hashCode/hashcode001a.java | 96 ++ .../jdi/StackFrame/location/location001.java | 537 +++++++++ .../location/location001/TestDescription.java | 87 ++ .../jdi/StackFrame/location/location001a.java | 190 +++ .../setValue/setvalue001/setvalue001.java | 818 +++++++++++++ .../setValue/setvalue001/setvalue001a.java | 209 ++++ .../setValue/setvalue002/setvalue002.java | 682 +++++++++++ .../setValue/setvalue002/setvalue002a.java | 228 ++++ .../setValue/setvalue003/setvalue003.java | 625 ++++++++++ .../setValue/setvalue003/setvalue003a.java | 250 ++++ .../setValue/setvalue004/setvalue004.java | 656 ++++++++++ .../setValue/setvalue004/setvalue004a.java | 222 ++++ .../setValue/setvalue005/setvalue005.java | 379 ++++++ .../setValue/setvalue005/setvalue005t.java | 82 ++ .../setValue/setvalue006/setvalue006.java | 398 ++++++ .../setValue/setvalue006/setvalue006t.java | 85 ++ .../StackFrame/thisObject/thisobject001.java | 536 +++++++++ .../thisobject001/TestDescription.java | 79 ++ .../StackFrame/thisObject/thisobject001a.java | 222 ++++ .../StackFrame/thisObject/thisobject002.java | 531 ++++++++ .../thisobject002/TestDescription.java | 79 ++ .../StackFrame/thisObject/thisobject002a.java | 224 ++++ .../nsk/jdi/StackFrame/thread/thread001.java | 507 ++++++++ .../thread/thread001/TestDescription.java | 75 ++ .../nsk/jdi/StackFrame/thread/thread001a.java | 191 +++ .../jdi/StackFrame/toString/tostring001.java | 170 +++ .../toString/tostring001/TestDescription.java | 64 + .../jdi/StackFrame/toString/tostring001a.java | 96 ++ .../visiblevarbyname001.java | 608 ++++++++++ .../visiblevarbyname001/TestDescription.java | 95 ++ .../visiblevarbyname001a.java | 222 ++++ .../visiblevarbyname002.java | 509 ++++++++ .../visiblevarbyname002/TestDescription.java | 84 ++ .../visiblevarbyname002a.java | 221 ++++ .../visibleVariables/visiblevariables001.java | 559 +++++++++ .../visiblevariables001/TestDescription.java | 109 ++ .../visiblevariables001a.java | 222 ++++ .../visibleVariables/visiblevariables002.java | 532 ++++++++ .../visiblevariables002/TestDescription.java | 98 ++ .../visiblevariables002a.java | 222 ++++ .../_itself_/stepEvent003/stepEvent003.java | 186 +++ .../_itself_/stepEvent004/TestClass1.java | 1072 +++++++++++++++++ .../_itself_/stepEvent004/stepEvent004.java | 265 ++++ .../jdi/StepEvent/_itself_/stepevent001.java | 386 ++++++ .../stepevent001/TestDescription.java | 97 ++ .../jdi/StepEvent/_itself_/stepevent001a.java | 102 ++ .../jdi/StepEvent/_itself_/stepevent002.java | 311 +++++ .../stepevent002/TestDescription.java | 90 ++ .../jdi/StepEvent/_itself_/stepevent002a.java | 164 +++ .../jdi/StepRequest/_bounds_/filters001.java | 200 +++ .../_bounds_/filters001/TestDescription.java | 58 + .../jdi/StepRequest/_bounds_/filters001a.java | 54 + .../addClassExclusionFilter/filter001.java | 196 +++ .../filter001/TestDescription.java | 85 ++ .../addClassExclusionFilter/filter001a.java | 245 ++++ .../addClassExclusionFilter/filter002.java | 533 ++++++++ .../filter002/TestDescription.java | 82 ++ .../addClassExclusionFilter/filter002a.java | 117 ++ .../addClassFilter_rt/filter_rt001.java | 163 +++ .../filter_rt001/TestDescription.java | 82 ++ .../addClassFilter_rt/filter_rt001a.java | 223 ++++ .../addClassFilter_rt/filter_rt002.java | 534 ++++++++ .../filter_rt002/TestDescription.java | 81 ++ .../addClassFilter_rt/filter_rt002a.java | 179 +++ .../addClassFilter_rt/filter_rt003.java | 187 +++ .../filter_rt003/TestDescription.java | 84 ++ .../addClassFilter_rt/filter_rt003a.java | 228 ++++ .../addClassFilter_s/filter_s001.java | 187 +++ .../filter_s001/TestDescription.java | 81 ++ .../addClassFilter_s/filter_s001a.java | 226 ++++ .../addClassFilter_s/filter_s002.java | 527 ++++++++ .../filter_s002/TestDescription.java | 80 ++ .../addClassFilter_s/filter_s002a.java | 194 +++ .../addInstanceFilter/instancefilter001.java | 196 +++ .../instancefilter001/TestDescription.java | 94 ++ .../addInstanceFilter/instancefilter001a.java | 200 +++ .../addInstanceFilter/instancefilter002.java | 552 +++++++++ .../instancefilter002/TestDescription.java | 84 ++ .../addInstanceFilter/instancefilter002a.java | 197 +++ .../addInstanceFilter/instancefilter003.java | 519 ++++++++ .../instancefilter003/TestDescription.java | 84 ++ .../addInstanceFilter/instancefilter003a.java | 197 +++ .../addInstanceFilter/instancefilter004.java | 197 +++ .../instancefilter004/TestDescription.java | 95 ++ .../addInstanceFilter/instancefilter004a.java | 200 +++ .../nsk/jdi/StepRequest/depth/depth001.java | 496 ++++++++ .../depth/depth001/TestDescription.java | 71 ++ .../nsk/jdi/StepRequest/depth/depth001a.java | 179 +++ .../nsk/jdi/StepRequest/depth/depth002.java | 496 ++++++++ .../depth/depth002/TestDescription.java | 71 ++ .../nsk/jdi/StepRequest/depth/depth002a.java | 179 +++ .../nsk/jdi/StepRequest/depth/depth003.java | 496 ++++++++ .../depth/depth003/TestDescription.java | 71 ++ .../nsk/jdi/StepRequest/depth/depth003a.java | 179 +++ .../nsk/jdi/StepRequest/size/size001.java | 496 ++++++++ .../size/size001/TestDescription.java | 71 ++ .../nsk/jdi/StepRequest/size/size001a.java | 179 +++ .../nsk/jdi/StepRequest/size/size002.java | 496 ++++++++ .../size/size002/TestDescription.java | 71 ++ .../nsk/jdi/StepRequest/size/size002a.java | 179 +++ .../nsk/jdi/StepRequest/thread/thread001.java | 497 ++++++++ .../thread/thread001/TestDescription.java | 71 ++ .../jdi/StepRequest/thread/thread001a.java | 179 +++ .../StringArgument/isValid/isvalid001.java | 139 +++ .../isValid/isvalid001/TestDescription.java | 68 ++ .../StringArgument/isValid/isvalid002.java | 140 +++ .../isValid/isvalid002/TestDescription.java | 68 ++ .../StringArgument/isValid/isvalid003.java | 141 +++ .../isValid/isvalid003/TestDescription.java | 69 ++ .../jdi/StringReference/value/value001.java | 271 +++++ .../value/value001/TestDescription.java | 79 ++ .../jdi/StringReference/value/value001a.java | 144 +++ .../ThreadDeathEvent/thread/thread001.java | 285 +++++ .../thread/thread001/TestDescription.java | 95 ++ .../ThreadDeathEvent/thread/thread001a.java | 169 +++ .../addThreadFilter/addthreadfilter001.java | 492 ++++++++ .../addthreadfilter001/TestDescription.java | 74 ++ .../addThreadFilter/addthreadfilter001a.java | 165 +++ .../addThreadFilter/addthreadfilter002.java | 488 ++++++++ .../addthreadfilter002/TestDescription.java | 74 ++ .../addThreadFilter/addthreadfilter002a.java | 113 ++ .../addThreadFilter/addthreadfilter003.java | 528 ++++++++ .../addthreadfilter003/TestDescription.java | 76 ++ .../addThreadFilter/addthreadfilter003a.java | 185 +++ .../addThreadFilter/addthreadfilter004.java | 183 +++ .../addthreadfilter004/TestDescription.java | 81 ++ .../addThreadFilter/addthreadfilter004a.java | 219 ++++ .../addThreadFilter/addthreadfilter005.java | 540 +++++++++ .../addthreadfilter005/TestDescription.java | 75 ++ .../addThreadFilter/addthreadfilter005a.java | 198 +++ .../ThreadGroupReference/name/name001.java | 275 +++++ .../name/name001/TestDescription.java | 75 ++ .../ThreadGroupReference/name/name001a.java | 188 +++ .../parent/parent001.java | 311 +++++ .../parent/parent001/TestDescription.java | 76 ++ .../parent/parent001a.java | 204 ++++ .../resume/resume001.java | 418 +++++++ .../resume/resume001/TestDescription.java | 77 ++ .../resume/resume001a.java | 221 ++++ .../suspend/suspend001.java | 413 +++++++ .../suspend/suspend001/TestDescription.java | 80 ++ .../suspend/suspend001a.java | 221 ++++ .../threadGroups/threadgroups001.java | 321 +++++ .../threadgroups001/TestDescription.java | 78 ++ .../threadGroups/threadgroups001a.java | 222 ++++ .../threads/threads001.java | 302 +++++ .../threads/threads001/TestDescription.java | 84 ++ .../threads/threads001a.java | 212 ++++ .../toString/tostring001.java | 152 +++ .../toString/tostring001/TestDescription.java | 57 + .../toString/tostring001a.java | 126 ++ .../ThreadReference/_bounds_/bounds001.java | 203 ++++ .../_bounds_/bounds001/TestDescription.java | 64 + .../ThreadReference/_bounds_/bounds001a.java | 49 + .../currentContendedMonitor/currentcm001.java | 474 ++++++++ .../currentcm001/TestDescription.java | 89 ++ .../currentcm001a.java | 207 ++++ .../forceEarlyReturn001.java | 333 +++++ .../forceEarlyReturn001a.java | 159 +++ .../forceEarlyReturn002.java | 166 +++ .../forceEarlyReturn002a.java | 100 ++ .../forceEarlyReturn003.java | 120 ++ .../forceEarlyReturn004.java | 99 ++ .../forceEarlyReturn004a.java | 79 ++ .../libforceEarlyReturn004a.c | 71 ++ .../forceEarlyReturn005.java | 122 ++ .../forceEarlyReturn005a.java | 148 +++ .../libforceEarlyReturn005a.c | 60 + .../forceEarlyReturn006/TestDescription.java | 71 ++ .../forceEarlyReturn007/TestDescription.java | 77 ++ .../forceEarlyReturn008.java | 211 ++++ .../forceEarlyReturn008a.java | 89 ++ .../forceEarlyReturn009.java | 179 +++ .../forceEarlyReturn009a.java | 205 ++++ .../forceEarlyReturn010/TestDescription.java | 59 + .../forceEarlyReturn011/TestDescription.java | 59 + .../forceEarlyReturn012/TestDescription.java | 60 + .../forceEarlyReturn013.java | 119 ++ .../forceEarlyReturn013a.java | 144 +++ .../forceEarlyReturn014.java | 134 +++ .../forceEarlyReturn014a.java | 75 ++ .../forceEarlyReturn015.java | 111 ++ .../forceEarlyReturn015a.java | 54 + .../jdi/ThreadReference/frame/frame001.java | 714 +++++++++++ .../frame/frame001/TestDescription.java | 87 ++ .../jdi/ThreadReference/frame/frame001a.java | 207 ++++ .../frameCount/framecount001.java | 612 ++++++++++ .../framecount001/TestDescription.java | 82 ++ .../frameCount/framecount001a.java | 207 ++++ .../jdi/ThreadReference/frames/frames001.java | 712 +++++++++++ .../frames/frames001/TestDescription.java | 82 ++ .../ThreadReference/frames/frames001a.java | 207 ++++ .../frames_ii/frames_ii001.java | 851 +++++++++++++ .../frames_ii001/TestDescription.java | 100 ++ .../frames_ii/frames_ii001a.java | 213 ++++ .../frames_ii/frames_ii002.java | 585 +++++++++ .../frames_ii002/TestDescription.java | 87 ++ .../frames_ii/frames_ii002a.java | 212 ++++ .../interrupt/interrupt001.java | 248 ++++ .../interrupt001/TestDescription.java | 76 ++ .../interrupt/interrupt001a.java | 284 +++++ .../isAtBreakpoint/isatbreakpoint001.java | 516 ++++++++ .../isatbreakpoint001/TestDescription.java | 76 ++ .../isAtBreakpoint/isatbreakpoint001a.java | 208 ++++ .../isSuspended/issuspended001.java | 847 +++++++++++++ .../issuspended001/TestDescription.java | 79 ++ .../isSuspended/issuspended001a.java | 244 ++++ .../isSuspended/issuspended002.java | 643 ++++++++++ .../issuspended002/TestDescription.java | 78 ++ .../isSuspended/issuspended002a.java | 207 ++++ .../isSuspended/issuspended003.java | 654 ++++++++++ .../issuspended003/TestDescription.java | 80 ++ .../isSuspended/issuspended003a.java | 208 ++++ .../isSuspended/issuspended004.java | 654 ++++++++++ .../issuspended004/TestDescription.java | 80 ++ .../isSuspended/issuspended004a.java | 208 ++++ .../nsk/jdi/ThreadReference/name/name001.java | 464 +++++++ .../name/name001/TestDescription.java | 75 ++ .../jdi/ThreadReference/name/name001a.java | 207 ++++ .../ownedMonitors/ownedmonitors001.java | 289 +++++ .../ownedmonitors001/TestDescription.java | 70 ++ .../ownedMonitors/ownedmonitors001a.java | 150 +++ .../ownedMonitors/ownedmonitors002.java | 176 +++ .../ownedmonitors002/TestDescription.java | 54 + .../ownedMonitors/ownedmonitors002t.java | 54 + .../ownedMonitorsAndFrames001.java | 120 ++ .../ownedMonitorsAndFrames002.java | 153 +++ .../ownedMonitorsAndFrames003.java | 174 +++ .../ownedMonitorsAndFrames004.java | 151 +++ .../ownedMonitorsAndFrames004a.java | 119 ++ .../ownedMonitorsAndFrames005.java | 160 +++ .../ownedMonitorsAndFrames006.java | 185 +++ .../ownedMonitorsAndFrames007.java | 197 +++ .../TestDescription.java | 68 ++ .../ownedMonitorsAndFrames009.java | 112 ++ .../ownedMonitorsAndFrames009a.java | 142 +++ .../popFrames/popframes001.java | 551 +++++++++ .../popframes001/TestDescription.java | 122 ++ .../popFrames/popframes001a.java | 188 +++ .../popFrames/popframes002.java | 543 +++++++++ .../popframes002/TestDescription.java | 118 ++ .../popFrames/popframes002a.java | 215 ++++ .../popFrames/popframes003.java | 641 ++++++++++ .../popframes003/TestDescription.java | 118 ++ .../popFrames/popframes003a.java | 231 ++++ .../popFrames/popframes004.java | 549 +++++++++ .../popframes004/TestDescription.java | 117 ++ .../popFrames/popframes004a.java | 197 +++ .../popFrames/popframes005.java | 531 ++++++++ .../popframes005/TestDescription.java | 118 ++ .../popFrames/popframes005a.java | 178 +++ .../popFrames/popframes006.java | 348 ++++++ .../popframes006/TestDescription.java | 61 + .../popFrames/popframes006t.java | 88 ++ .../popFrames/popframes007.java | 334 +++++ .../popframes007/TestDescription.java | 61 + .../popFrames/popframes007t.java | 178 +++ .../jdi/ThreadReference/resume/resume001.java | 576 +++++++++ .../resume/resume001/TestDescription.java | 79 ++ .../ThreadReference/resume/resume001a.java | 208 ++++ .../status/status003/status003.java | 226 ++++ .../status/status003/status003a.java | 151 +++ .../status/status004/status004.java | 257 ++++ .../status/status004/status004a.java | 147 +++ .../status/status005/status005.java | 266 ++++ .../status/status005/status005a.java | 161 +++ .../status/status006/status006.java | 244 ++++ .../status/status006/status006a.java | 149 +++ .../status/status007/status007.java | 215 ++++ .../status/status007/status007a.java | 129 ++ .../status/status008/status008.java | 215 ++++ .../status/status008/status008a.java | 89 ++ .../nsk/jdi/ThreadReference/stop/stop001.java | 302 +++++ .../stop/stop001/TestDescription.java | 85 ++ .../jdi/ThreadReference/stop/stop001a.java | 230 ++++ .../nsk/jdi/ThreadReference/stop/stop002.java | 315 +++++ .../stop/stop002/TestDescription.java | 61 + .../jdi/ThreadReference/stop/stop002t.java | 85 ++ .../ThreadReference/suspend/suspend001.java | 545 +++++++++ .../suspend/suspend001/TestDescription.java | 87 ++ .../ThreadReference/suspend/suspend001a.java | 206 ++++ .../suspendCount/suspendcount001.java | 589 +++++++++ .../suspendcount001/TestDescription.java | 76 ++ .../suspendCount/suspendcount001a.java | 208 ++++ .../threadGroup/threadgroup001.java | 322 +++++ .../threadgroup001/TestDescription.java | 75 ++ .../threadGroup/threadgroup001a.java | 221 ++++ .../ThreadStartEvent/thread/thread001.java | 272 +++++ .../thread/thread001/TestDescription.java | 98 ++ .../ThreadStartEvent/thread/thread001a.java | 120 ++ .../addThreadFilter/addthreadfilter001.java | 491 ++++++++ .../addthreadfilter001/TestDescription.java | 74 ++ .../addThreadFilter/addthreadfilter001a.java | 161 +++ .../addThreadFilter/addthreadfilter002.java | 490 ++++++++ .../addthreadfilter002/TestDescription.java | 74 ++ .../addThreadFilter/addthreadfilter002a.java | 113 ++ .../addThreadFilter/addthreadfilter003.java | 528 ++++++++ .../addthreadfilter003/TestDescription.java | 76 ++ .../addThreadFilter/addthreadfilter003a.java | 185 +++ .../addThreadFilter/addthreadfilter004.java | 183 +++ .../addthreadfilter004/TestDescription.java | 84 ++ .../addThreadFilter/addthreadfilter004a.java | 198 +++ .../addThreadFilter/addthreadfilter005.java | 535 ++++++++ .../addthreadfilter005/TestDescription.java | 75 ++ .../addThreadFilter/addthreadfilter005a.java | 198 +++ .../nsk/jdi/Transport/name/name001.java | 88 ++ .../name/name001/TestDescription.java | 71 ++ .../nsk/jdi/Type/hashCode/hashcode001.java | 232 ++++ .../hashCode/hashcode001/TestDescription.java | 64 + .../nsk/jdi/Type/hashCode/hashcode001a.java | 121 ++ .../vmTestbase/nsk/jdi/Type/name/name001.java | 307 +++++ .../Type/name/name001/TestDescription.java | 71 ++ .../nsk/jdi/Type/name/name001a.java | 122 ++ .../vmTestbase/nsk/jdi/Type/name/name002.java | 297 +++++ .../Type/name/name002/TestDescription.java | 71 ++ .../nsk/jdi/Type/name/name002a.java | 159 +++ .../vmTestbase/nsk/jdi/Type/name/name003.java | 211 ++++ .../Type/name/name003/TestDescription.java | 71 ++ .../nsk/jdi/Type/name/name003a.java | 117 ++ .../nsk/jdi/Type/signature/signature001.java | 314 +++++ .../signature001/TestDescription.java | 76 ++ .../nsk/jdi/Type/signature/signature001a.java | 122 ++ .../nsk/jdi/Type/signature/signature002.java | 308 +++++ .../signature002/TestDescription.java | 76 ++ .../nsk/jdi/Type/signature/signature002a.java | 160 +++ .../nsk/jdi/Type/signature/signature003.java | 211 ++++ .../signature003/TestDescription.java | 76 ++ .../nsk/jdi/Type/signature/signature003a.java | 117 ++ .../declaringType/decltype001.java | 267 ++++ .../decltype001/TestDescription.java | 63 + .../declaringType/decltype001a.java | 127 ++ .../declaringType/decltype002.java | 285 +++++ .../decltype002/TestDescription.java | 66 + .../declaringType/decltype002a.java | 136 +++ .../declaringType/decltype003.java | 270 +++++ .../decltype003/TestDescription.java | 66 + .../declaringType/decltype003a.java | 199 +++ .../declaringType/decltype004.java | 288 +++++ .../decltype004/TestDescription.java | 62 + .../declaringType/decltype004a.java | 283 +++++ .../declaringType/decltype005.java | 306 +++++ .../decltype005/TestDescription.java | 66 + .../declaringType/decltype005a.java | 291 +++++ .../declaringType/decltype006.java | 286 +++++ .../decltype006/TestDescription.java | 66 + .../declaringType/decltype006a.java | 442 +++++++ .../declaringType/decltype007.java | 148 +++ .../decltype007/TestDescription.java | 61 + .../declaringType/decltype007a.java | 71 ++ .../declaringType/decltype008.java | 212 ++++ .../decltype008/TestDescription.java | 66 + .../declaringType/decltype008a.java | 96 ++ .../declaringType/decltype009.java | 143 +++ .../decltype009/TestDescription.java | 66 + .../declaringType/decltype009a.java | 107 ++ .../genericSignature/genericSignature001.java | 300 +++++ .../genericSignature001/TestDescription.java | 62 + .../genericSignature001a.java | 168 +++ .../genericSignature/genericSignature002.java | 298 +++++ .../genericSignature002/TestDescription.java | 60 + .../genericSignature002a.java | 344 ++++++ .../jdi/TypeComponent/isFinal/isfinal001.java | 316 +++++ .../isFinal/isfinal001/TestDescription.java | 61 + .../TypeComponent/isFinal/isfinal001a.java | 124 ++ .../jdi/TypeComponent/isFinal/isfinal002.java | 367 ++++++ .../isFinal/isfinal002/TestDescription.java | 61 + .../TypeComponent/isFinal/isfinal002a.java | 278 +++++ .../jdi/TypeComponent/isFinal/isfinal003.java | 137 +++ .../isFinal/isfinal003/TestDescription.java | 61 + .../TypeComponent/isFinal/isfinal003a.java | 90 ++ .../jdi/TypeComponent/isFinal/isfinal004.java | 146 +++ .../isFinal/isfinal004/TestDescription.java | 65 + .../TypeComponent/isFinal/isfinal004a.java | 110 ++ .../isPackagePrivate/ispackageprivate001.java | 207 ++++ .../ispackageprivate001/TestDescription.java | 69 ++ .../ispackageprivate001a.java | 108 ++ .../isPackagePrivate/ispackageprivate002.java | 368 ++++++ .../ispackageprivate002/TestDescription.java | 69 ++ .../ispackageprivate002a.java | 261 ++++ .../TypeComponent/isPrivate/isprivate001.java | 207 ++++ .../isprivate001/TestDescription.java | 69 ++ .../isPrivate/isprivate001a.java | 108 ++ .../TypeComponent/isPrivate/isprivate002.java | 368 ++++++ .../isprivate002/TestDescription.java | 69 ++ .../isPrivate/isprivate002a.java | 261 ++++ .../isProtected/isprotected001.java | 207 ++++ .../isprotected001/TestDescription.java | 68 ++ .../isProtected/isprotected001a.java | 108 ++ .../isProtected/isprotected002.java | 368 ++++++ .../isprotected002/TestDescription.java | 68 ++ .../isProtected/isprotected002a.java | 261 ++++ .../TypeComponent/isPublic/ispublic001.java | 207 ++++ .../isPublic/ispublic001/TestDescription.java | 68 ++ .../TypeComponent/isPublic/ispublic001a.java | 108 ++ .../TypeComponent/isPublic/ispublic002.java | 368 ++++++ .../isPublic/ispublic002/TestDescription.java | 68 ++ .../TypeComponent/isPublic/ispublic002a.java | 261 ++++ .../TypeComponent/isStatic/isstatic001.java | 325 +++++ .../isStatic/isstatic001/TestDescription.java | 61 + .../TypeComponent/isStatic/isstatic001a.java | 127 ++ .../TypeComponent/isStatic/isstatic002.java | 367 ++++++ .../isStatic/isstatic002/TestDescription.java | 61 + .../TypeComponent/isStatic/isstatic002a.java | 278 +++++ .../TypeComponent/isStatic/isstatic003.java | 137 +++ .../isStatic/isstatic003/TestDescription.java | 61 + .../TypeComponent/isStatic/isstatic003a.java | 90 ++ .../TypeComponent/isStatic/isstatic004.java | 146 +++ .../isStatic/isstatic004/TestDescription.java | 65 + .../TypeComponent/isStatic/isstatic004a.java | 110 ++ .../isSynthetic/issynthetic001.java | 247 ++++ .../issynthetic001/TestDescription.java | 82 ++ .../isSynthetic/issynthetic001a.java | 98 ++ .../isSynthetic/issynthetic002.java | 235 ++++ .../issynthetic002/TestDescription.java | 82 ++ .../isSynthetic/issynthetic002a.java | 203 ++++ .../nsk/jdi/TypeComponent/name/name001.java | 170 +++ .../name/name001/TestDescription.java | 62 + .../nsk/jdi/TypeComponent/name/name001a.java | 96 ++ .../nsk/jdi/TypeComponent/name/name002.java | 183 +++ .../name/name002/TestDescription.java | 62 + .../nsk/jdi/TypeComponent/name/name002a.java | 178 +++ .../nsk/jdi/TypeComponent/name/name003.java | 151 +++ .../name/name003/TestDescription.java | 64 + .../nsk/jdi/TypeComponent/name/name003a.java | 90 ++ .../jdi/TypeComponent/signature/sign001.java | 228 ++++ .../signature/sign001/TestDescription.java | 65 + .../jdi/TypeComponent/signature/sign001a.java | 96 ++ .../jdi/TypeComponent/signature/sign002.java | 255 ++++ .../signature/sign002/TestDescription.java | 65 + .../jdi/TypeComponent/signature/sign002a.java | 178 +++ .../jdi/TypeComponent/signature/sign003.java | 183 +++ .../signature/sign003/TestDescription.java | 70 ++ .../jdi/TypeComponent/signature/sign003a.java | 77 ++ .../_itself_/canntbemod001.java | 113 ++ .../canntbemod001/TestDescription.java | 50 + .../jdi/VMDeathEvent/_itself_/vmdeath001.java | 195 +++ .../_itself_/vmdeath001/TestDescription.java | 74 ++ .../VMDeathEvent/_itself_/vmdeath001a.java | 58 + .../jdi/VMDeathEvent/_itself_/vmdeath002.java | 443 +++++++ .../_itself_/vmdeath002/TestDescription.java | 93 ++ .../VMDeathEvent/_itself_/vmdeath002a.java | 113 ++ .../jdi/VMDeathEvent/_itself_/vmdeath003.java | 441 +++++++ .../_itself_/vmdeath003/TestDescription.java | 92 ++ .../VMDeathEvent/_itself_/vmdeath003a.java | 111 ++ .../_itself_/disconnect001.java | 177 +++ .../disconnect001/TestDescription.java | 74 ++ .../_itself_/disconnect001a.java | 57 + .../_itself_/disconnect002.java | 183 +++ .../disconnect002/TestDescription.java | 73 ++ .../_itself_/disconnect002a.java | 58 + .../_itself_/disconnect003.java | 179 +++ .../disconnect003/TestDescription.java | 73 ++ .../_itself_/disconnect003a.java | 52 + .../VMOutOfMemoryException001.java | 94 ++ .../VMOutOfMemoryException001t.java | 59 + .../jdi/VMStartEvent/thread/thread001.java | 197 +++ .../thread/thread001/TestDescription.java | 73 ++ .../jdi/VMStartEvent/thread/thread001a.java | 61 + .../nsk/jdi/Value/_itself_/value001.java | 706 +++++++++++ .../_itself_/value001/TestDescription.java | 75 ++ .../nsk/jdi/Value/_itself_/value001a.java | 217 ++++ .../nsk/jdi/Value/type/type001.java | 389 ++++++ .../Value/type/type001/TestDescription.java | 70 ++ .../nsk/jdi/Value/type/type001a.java | 122 ++ .../nsk/jdi/Value/type/type002/type002.java | 553 +++++++++ .../nsk/jdi/Value/type/type002/type002a.java | 189 +++ .../nsk/jdi/Value/type/type003.java | 292 +++++ .../Value/type/type003/TestDescription.java | 70 ++ .../nsk/jdi/Value/type/type003a.java | 174 +++ .../allClasses/allclasses001.java | 573 +++++++++ .../allclasses001/TestDescription.java | 80 ++ .../allClasses/allclasses001a.java | 262 ++++ .../allClasses/allclasses002.java | 251 ++++ .../allclasses002/TestDescription.java | 78 ++ .../allClasses/allclasses002a.java | 175 +++ .../allThreads/allthreads001.java | 440 +++++++ .../allthreads001/TestDescription.java | 83 ++ .../allThreads/allthreads001a.java | 192 +++ .../canAddMethod/canaddmethod001.java | 429 +++++++ .../canaddmethod001/TestDescription.java | 70 ++ .../canAddMethod/canaddmethod001a.java | 110 ++ .../canBeModified/canbemodified001.java | 105 ++ .../canbemodified001/TestDescription.java | 54 + .../canBeModified/canbemodified001a.java | 50 + .../canGetBytecodes/cangetbytecodes001.java | 248 ++++ .../cangetbytecodes001/TestDescription.java | 72 ++ .../canGetBytecodes/cangetbytecodes001a.java | 117 ++ .../cangccm001.java | 304 +++++ .../cangccm001/TestDescription.java | 72 ++ .../cangccm001a.java | 193 +++ .../cangetmonitorinfo001.java | 368 ++++++ .../cangetmonitorinfo001/TestDescription.java | 72 ++ .../cangetmonitorinfo001a.java | 199 +++ .../canGetOwnedMonitorInfo/cangetinfo001.java | 304 +++++ .../cangetinfo001/TestDescription.java | 72 ++ .../cangetinfo001a.java | 193 +++ .../cangetsde001.java | 198 +++ .../cangetsde001/TestDescription.java | 72 ++ .../cangetsde001a.java | 111 ++ .../cangetattr001.java | 249 ++++ .../cangetattr001/TestDescription.java | 72 ++ .../cangetattr001a.java | 115 ++ .../canPopFrames/canpopframes001.java | 429 +++++++ .../canpopframes001/TestDescription.java | 69 ++ .../canPopFrames/canpopframes001a.java | 110 ++ .../canredefineclasses001.java | 429 +++++++ .../TestDescription.java | 69 ++ .../canredefineclasses001a.java | 110 ++ .../canreqvmdev001.java | 429 +++++++ .../canreqvmdev001/TestDescription.java | 69 ++ .../canreqvmdev001a.java | 110 ++ .../curc001.java | 429 +++++++ .../curc001/TestDescription.java | 70 ++ .../curc001a.java | 110 ++ .../canusefilters001.java | 429 +++++++ .../canusefilters001/TestDescription.java | 71 ++ .../canusefilters001a.java | 110 ++ .../canwatchaccess001.java | 440 +++++++ .../canwatchaccess001/TestDescription.java | 73 ++ .../canwatchaccess001a.java | 110 ++ .../canwatchmod001.java | 441 +++++++ .../canwatchmod001/TestDescription.java | 73 ++ .../canwatchmod001a.java | 110 ++ .../classesByName/classesbyname001.java | 263 ++++ .../classesbyname001/TestDescription.java | 74 ++ .../classesByName/classesbyname001a.java | 222 ++++ .../description/description001.java | 199 +++ .../description001/TestDescription.java | 77 ++ .../description/description001a.java | 112 ++ .../VirtualMachine/dispose/dispose001.java | 212 ++++ .../dispose/dispose001/TestDescription.java | 87 ++ .../VirtualMachine/dispose/dispose001a.java | 114 ++ .../VirtualMachine/dispose/dispose002.java | 382 ++++++ .../dispose/dispose002/TestDescription.java | 87 ++ .../VirtualMachine/dispose/dispose002a.java | 209 ++++ .../VirtualMachine/dispose/dispose003.java | 290 +++++ .../dispose/dispose003/TestDescription.java | 87 ++ .../VirtualMachine/dispose/dispose003a.java | 209 ++++ .../VirtualMachine/dispose/dispose004.java | 315 +++++ .../dispose/dispose004/TestDescription.java | 87 ++ .../VirtualMachine/dispose/dispose004a.java | 207 ++++ .../VirtualMachine/dispose/dispose005.java | 638 ++++++++++ .../dispose/dispose005/TestDescription.java | 88 ++ .../VirtualMachine/dispose/dispose005a.java | 261 ++++ .../eventQueue/eventqueue001.java | 223 ++++ .../eventqueue001/TestDescription.java | 73 ++ .../eventQueue/eventqueue001a.java | 112 ++ .../eventRequestManager/eventrmanager001.java | 224 ++++ .../eventrmanager001/TestDescription.java | 74 ++ .../eventrmanager001a.java | 112 ++ .../nsk/jdi/VirtualMachine/exit/exit001.java | 176 +++ .../exit/exit001/TestDescription.java | 80 ++ .../nsk/jdi/VirtualMachine/exit/exit001a.java | 62 + .../nsk/jdi/VirtualMachine/exit/exit002.java | 177 +++ .../exit/exit002/TestDescription.java | 81 ++ .../nsk/jdi/VirtualMachine/exit/exit002a.java | 62 + .../getdefaultstratum001.java | 198 +++ .../getdefaultstratum001/TestDescription.java | 75 ++ .../getdefaultstratum001a.java | 116 ++ .../instancecounts001/instancecounts001.java | 143 +++ .../instancecounts002/TestDescription.java | 62 + .../instancecounts003/instancecounts003.java | 105 ++ .../instancecounts004/instancecounts004.java | 152 +++ .../instancecounts004/instancecounts004a.java | 173 +++ .../mirrorOf_bool/mirrorof_bool001.java | 273 +++++ .../mirrorof_bool001/TestDescription.java | 81 ++ .../mirrorOf_bool/mirrorof_bool001a.java | 112 ++ .../mirrorOf_byte/mirrorof_byte001.java | 264 ++++ .../mirrorof_byte001/TestDescription.java | 79 ++ .../mirrorOf_byte/mirrorof_byte001a.java | 118 ++ .../mirrorOf_char/mirrorof_char001.java | 260 ++++ .../mirrorof_char001/TestDescription.java | 79 ++ .../mirrorOf_char/mirrorof_char001a.java | 117 ++ .../mirrorOf_double/mirrorof_double001.java | 314 +++++ .../mirrorof_double001/TestDescription.java | 79 ++ .../mirrorOf_double/mirrorof_double001a.java | 118 ++ .../mirrorOf_float/mirrorof_float001.java | 313 +++++ .../mirrorof_float001/TestDescription.java | 79 ++ .../mirrorOf_float/mirrorof_float001a.java | 117 ++ .../mirrorOf_int/mirrorof_int001.java | 265 ++++ .../mirrorof_int001/TestDescription.java | 79 ++ .../mirrorOf_int/mirrorof_int001a.java | 117 ++ .../mirrorOf_long/mirrorof_long001.java | 265 ++++ .../mirrorof_long001/TestDescription.java | 79 ++ .../mirrorOf_long/mirrorof_long001a.java | 118 ++ .../mirrorOf_short/mirrorof_short001.java | 264 ++++ .../mirrorof_short001/TestDescription.java | 79 ++ .../mirrorOf_short/mirrorof_short001a.java | 119 ++ .../mirrorOf_string/mirrorof_string001.java | 180 +++ .../mirrorof_string001/TestDescription.java | 76 ++ .../mirrorOf_string/mirrorof_string001a.java | 118 ++ .../nsk/jdi/VirtualMachine/name/name001.java | 199 +++ .../name/name001/TestDescription.java | 71 ++ .../nsk/jdi/VirtualMachine/name/name001a.java | 112 ++ .../VirtualMachine/process/process001.java | 202 ++++ .../process/process001/TestDescription.java | 74 ++ .../VirtualMachine/process/process001a.java | 112 ++ .../redefineClasses/redefineclasses001.java | 611 ++++++++++ .../redefineclasses001/TestDescription.java | 139 +++ .../newclass/redefineclasses001b.java | 60 + .../redefineClasses/redefineclasses001a.java | 120 ++ .../redefineClasses/redefineclasses001b.java | 59 + .../redefineClasses/redefineclasses002.java | 322 +++++ .../redefineclasses002/TestDescription.java | 90 ++ .../newclass/redefineclasses002a.java | 82 ++ .../redefineClasses/redefineclasses002a.java | 81 ++ .../redefineClasses/redefineclasses003.java | 263 ++++ .../redefineclasses003/TestDescription.java | 80 ++ .../newclass/redefineclasses003a.java | 100 ++ .../redefineClasses/redefineclasses003a.java | 102 ++ .../redefineClasses/redefineclasses004.java | 251 ++++ .../redefineclasses004/TestDescription.java | 77 ++ .../newclass01/redefineclasses004a.java | 75 ++ .../newclass02/redefineclasses004a.java | 55 + .../newclass03/redefineclasses004a.java | 64 + .../newclass04/redefineclasses004a.java | 64 + .../newclass05/redefineclasses004a.java | 64 + .../newclass06/redefineclasses004a.java | 64 + .../newclass07/redefineclasses004a.java | 64 + .../newclass08/redefineclasses004a.java | 64 + .../newclass09/redefineclasses004a.java | 64 + .../newclass10/redefineclasses004a.java | 64 + .../redefineClasses/redefineclasses004a.java | 63 + .../redefineClasses/redefineclasses005.java | 263 ++++ .../redefineclasses005/TestDescription.java | 74 ++ .../newclass01/redefineclasses005a.java | 79 ++ .../newclass02/redefineclasses005a.java | 79 ++ .../newclass03/redefineclasses005a.java | 79 ++ .../newclass04/redefineclasses005a.java | 79 ++ .../redefineClasses/redefineclasses005a.java | 75 ++ .../redefineClasses/redefineclasses006.java | 265 ++++ .../redefineclasses006/TestDescription.java | 74 ++ .../newclass01/redefineclasses006a.java | 73 ++ .../newclass02/redefineclasses006a.java | 73 ++ .../newclass03/redefineclasses006a.java | 73 ++ .../newclass04/redefineclasses006a.java | 73 ++ .../redefineClasses/redefineclasses006a.java | 75 ++ .../redefineClasses/redefineclasses007.java | 276 +++++ .../redefineclasses007/TestDescription.java | 83 ++ .../newclass01/redefineclasses007a.java | 76 ++ .../newclass02/redefineclasses007a.java | 76 ++ .../newclass03/redefineclasses007a.java | 76 ++ .../newclass04/redefineclasses007a.java | 76 ++ .../newclass05/redefineclasses007a.java | 76 ++ .../newclass06/redefineclasses007a.java | 76 ++ .../newclass07/redefineclasses007a.java | 76 ++ .../newclass08/redefineclasses007a.java | 76 ++ .../redefineClasses/redefineclasses007a.java | 75 ++ .../redefineClasses/redefineclasses008.java | 274 +++++ .../redefineclasses008/TestDescription.java | 85 ++ .../newclass01/redefineclasses008a.java | 73 ++ .../newclass02/redefineclasses008a.java | 73 ++ .../newclass03/redefineclasses008a.java | 73 ++ .../newclass04/redefineclasses008a.java | 73 ++ .../newclass05/redefineclasses008a.java | 73 ++ .../newclass06/redefineclasses008a.java | 73 ++ .../newclass07/redefineclasses008a.java | 73 ++ .../newclass08/redefineclasses008a.java | 73 ++ .../redefineClasses/redefineclasses008a.java | 72 ++ .../redefineClasses/redefineclasses009.java | 262 ++++ .../redefineclasses009/TestDescription.java | 78 ++ .../newclass01/redefineclasses009a.java | 66 + .../newclass02/redefineclasses009a.java | 66 + .../newclass03/redefineclasses009a.java | 66 + .../redefineClasses/redefineclasses009a.java | 66 + .../redefineClasses/redefineclasses010.java | 264 ++++ .../redefineclasses010/TestDescription.java | 75 ++ .../newclass01/redefineclasses010a.java | 72 ++ .../newclass02/redefineclasses010a.java | 72 ++ .../newclass03/redefineclasses010a.java | 72 ++ .../newclass04/redefineclasses010a.java | 72 ++ .../redefineClasses/redefineclasses010a.java | 75 ++ .../redefineClasses/redefineclasses011.java | 300 +++++ .../redefineclasses011/TestDescription.java | 90 ++ .../newclass01/redefineclasses011a.java | 66 + .../newclass02/redefineclasses011a.java | 66 + .../newclass03/redefineclasses011a.java | 66 + .../newclass04/redefineclasses011a.java | 66 + .../redefineClasses/redefineclasses011a.java | 63 + .../redefineClasses/redefineclasses012.java | 247 ++++ .../redefineclasses012/TestDescription.java | 76 ++ .../newclass01/redefineclasses012b.java | 45 + .../newclass02/redefineclasses012b.java | 38 + .../redefineClasses/redefineclasses012a.java | 56 + .../redefineClasses/redefineclasses012b.java | 41 + .../redefineClasses/redefineclasses013.java | 281 +++++ .../redefineclasses013/TestDescription.java | 77 ++ .../newclass01/redefineclasses013b.java | 44 + .../newclass02/redefineclasses013b.java | 44 + .../newclass03/redefineclasses013b.java | 44 + .../redefineClasses/redefineclasses013a.java | 67 ++ .../redefineClasses/redefineclasses013b.java | 41 + .../redefineClasses/redefineclasses014.java | 283 +++++ .../redefineclasses014/TestDescription.java | 75 ++ .../newclass01/redefineclasses014b.java | 40 + .../newclass02/redefineclasses014b.java | 40 + .../newclass03/redefineclasses014b.java | 40 + .../redefineClasses/redefineclasses014a.java | 67 ++ .../redefineClasses/redefineclasses014b.java | 41 + .../redefineClasses/redefineclasses015.java | 281 +++++ .../redefineclasses015/TestDescription.java | 95 ++ .../newclass01/redefineclasses015b.java | 45 + .../newclass02/redefineclasses015b.java | 45 + .../newclass03/redefineclasses015b.java | 45 + .../newclass04/redefineclasses015b.java | 45 + .../newclass05/redefineclasses015b.java | 44 + .../newclass06/redefineclasses015b.java | 45 + .../newclass07/redefineclasses015b.java | 45 + .../newclass08/redefineclasses015b.java | 45 + .../redefineClasses/redefineclasses015a.java | 66 + .../redefineClasses/redefineclasses015b.java | 41 + .../redefineClasses/redefineclasses016.java | 234 ++++ .../redefineclasses016/TestDescription.java | 86 ++ .../newclass01/redefineclasses016b.java | 44 + .../newclass02/redefineclasses016b.java | 44 + .../newclass03/redefineclasses016b.java | 44 + .../newclass04/redefineclasses016b.java | 44 + .../newclass05/redefineclasses016b.java | 44 + .../newclass06/redefineclasses016b.java | 44 + .../redefineClasses/redefineclasses016a.java | 56 + .../redefineClasses/redefineclasses016b.java | 41 + .../redefineClasses/redefineclasses020.java | 247 ++++ .../redefineclasses020/TestDescription.java | 72 ++ .../newclass01/redefineclasses020b.java | 51 + .../newclass02/redefineclasses020b.java | 51 + .../newclass03/redefineclasses020b.java | 51 + .../newclass04/redefineclasses020b.java | 51 + .../redefineClasses/redefineclasses020a.java | 54 + .../redefineClasses/redefineclasses020b.java | 50 + .../redefineClasses/redefineclasses021.java | 267 ++++ .../redefineclasses021/TestDescription.java | 75 ++ .../newclass01/redefineclasses021b.java | 51 + .../newclass02/redefineclasses021b.java | 51 + .../newclass03/redefineclasses021b.java | 51 + .../newclass04/redefineclasses021b.java | 51 + .../redefineClasses/redefineclasses021a.java | 53 + .../redefineClasses/redefineclasses021b.java | 51 + .../redefineClasses/redefineclasses022.java | 245 ++++ .../redefineclasses022/TestDescription.java | 71 ++ .../newclass01/redefineclasses022b.java | 51 + .../newclass02/redefineclasses022b.java | 51 + .../newclass03/redefineclasses022b.java | 51 + .../redefineClasses/redefineclasses022a.java | 53 + .../redefineClasses/redefineclasses022b.java | 50 + .../redefineClasses/redefineclasses023.java | 255 ++++ .../redefineclasses023/TestDescription.java | 72 ++ .../newclass01/redefineclasses023b.java | 52 + .../newclass02/redefineclasses023b.java | 52 + .../newclass03/redefineclasses023b.java | 52 + .../redefineClasses/redefineclasses023a.java | 52 + .../redefineClasses/redefineclasses023b.java | 51 + .../redefineClasses/redefineclasses024.java | 303 +++++ .../redefineclasses024/TestDescription.java | 78 ++ .../newclass01/redefineclasses024b.java | 52 + .../newclass02/redefineclasses024b.java | 52 + .../newclass03/redefineclasses024b.java | 52 + .../newclass04/redefineclasses024b.java | 52 + .../redefineClasses/redefineclasses024a.java | 59 + .../redefineClasses/redefineclasses024b.java | 51 + .../redefineClasses/redefineclasses025.java | 278 +++++ .../redefineclasses025/TestDescription.java | 73 ++ .../newclass01/redefineclasses025b.java | 47 + .../newclass02/redefineclasses025b.java | 47 + .../redefineClasses/redefineclasses025a.java | 63 + .../redefineClasses/redefineclasses025b.java | 47 + .../redefineClasses/redefineclasses026.java | 217 ++++ .../redefineclasses026/TestDescription.java | 70 ++ .../redefineclasses026c_otherName.java | 39 + .../redefineClasses/redefineclasses026a.java | 52 + .../redefineClasses/redefineclasses026c.java | 39 + .../redefineClasses/redefineclasses027.java | 276 +++++ .../redefineclasses027/TestDescription.java | 65 + .../redefineClasses/redefineclasses027a.java | 64 + .../redefineClasses/redefineclasses027c.java | 38 + .../redefineClasses/redefineclasses027i.java | 37 + .../redefineClasses/redefineclasses028.java | 221 ++++ .../redefineclasses028/TestDescription.java | 64 + .../redefineClasses/redefineclasses028a.java | 52 + .../redefineClasses/redefineclasses028b.java | 38 + .../redefineClasses/redefineclasses029.java | 153 +++ .../redefineclasses029/TestDescription.java | 59 + .../redefineClasses/redefineclasses029a.java | 50 + .../redefineClasses/redefineclasses030.java | 278 +++++ .../redefineclasses030/TestDescription.java | 81 ++ .../newclass01/redefineclasses030b.jasm | 52 + .../newclass02/redefineclasses030b.jasm | 53 + .../redefineClasses/redefineclasses030a.java | 52 + .../redefineClasses/redefineclasses030b.java | 42 + .../redefineClasses/redefineclasses031.java | 247 ++++ .../redefineclasses031/TestDescription.java | 66 + .../newclass01/redefineclasses031a.java | 82 ++ .../newclass02/redefineclasses031a.java | 82 ++ .../newclass03/redefineclasses031a.java | 82 ++ .../newclass04/redefineclasses031a.java | 82 ++ .../newclass05/redefineclasses031a.java | 82 ++ .../redefineClasses/redefineclasses031a.java | 82 ++ .../redefineClasses/redefineclasses032.java | 212 ++++ .../redefineclasses032/TestDescription.java | 65 + .../newclass/redefineclasses032a.java | 67 ++ .../redefineClasses/redefineclasses032a.java | 67 ++ .../redefineClasses/redefineclasses034.java | 316 +++++ .../redefineclasses034/TestDescription.java | 84 ++ .../loadclass/redefineclasses034b.java | 40 + .../loadclass/redefineclasses034c.java | 40 + .../newclass/redefineclasses034b.java | 40 + .../newclass/redefineclasses034c.java | 40 + .../redefineClasses/redefineclasses034a.java | 136 +++ .../redefineClasses/redefineclasses035.java | 335 ++++++ .../redefineclasses035/TestDescription.java | 83 ++ .../loadclass/redefineclasses035b.java | 40 + .../loadclass/redefineclasses035c.java | 40 + .../newclass/redefineclasses035b.java | 40 + .../newclass/redefineclasses035c.java | 40 + .../redefineClasses/redefineclasses035a.java | 143 +++ .../jdi/VirtualMachine/resume/resume001.java | 176 +++ .../resume/resume001/TestDescription.java | 56 + .../jdi/VirtualMachine/resume/resume001a.java | 112 ++ .../setDefaultStratum002.java | 167 +++ .../setDefaultStratum003.java | 179 +++ .../setdefaultstratum001.java | 204 ++++ .../setdefaultstratum001/TestDescription.java | 77 ++ .../setdefaultstratum001a.java | 116 ++ .../VirtualMachine/suspend/suspend001.java | 549 +++++++++ .../suspend/suspend001/TestDescription.java | 77 ++ .../VirtualMachine/suspend/suspend001a.java | 225 ++++ .../toplevelgroups001.java | 214 ++++ .../toplevelgroups001/TestDescription.java | 76 ++ .../toplevelgroups001a.java | 116 ++ .../VirtualMachine/version/version001.java | 199 +++ .../version/version001/TestDescription.java | 74 ++ .../VirtualMachine/version/version001a.java | 112 ++ .../allConnectors/allconnectors001.java | 155 +++ .../allconnectors001/TestDescription.java | 59 + .../attachingConnectors/attaching001.java | 153 +++ .../attaching001/TestDescription.java | 61 + .../connectedVirtualMachines/convm001.java | 383 ++++++ .../convm001/TestDescription.java | 80 ++ .../connectedVirtualMachines/convm001a.java | 112 ++ .../connectedVirtualMachines/convm002.java | 375 ++++++ .../convm002/TestDescription.java | 82 ++ .../connectedVirtualMachines/convm002a.java | 62 + .../connectedVirtualMachines/convm003.java | 388 ++++++ .../convm003/TestDescription.java | 82 ++ .../connectedVirtualMachines/convm003a.java | 112 ++ .../CreateVM002_TargetVM.java | 45 + .../CreateVM002_TranspServ.java | 613 ++++++++++ .../CreateVM003_TargetVM.java | 45 + .../CreateVM003_TranspServ.java | 488 ++++++++ .../CreateVM004_TargetVM.java | 45 + .../CreateVM004_TranspServ.java | 489 ++++++++ .../CreateVM005_TargetVM.java | 45 + .../CreateVM005_TranspServ.java | 488 ++++++++ .../createVirtualMachine/createVM001.java | 197 +++ .../createVM001/TestDescription.java | 55 + .../createVirtualMachine/createVM002.java | 260 ++++ .../createVM002/TestDescription.java | 57 + .../createVirtualMachine/createVM003.java | 268 +++++ .../createVM003/TestDescription.java | 61 + .../createVirtualMachine/createVM004.java | 270 +++++ .../createVM004/TestDescription.java | 62 + .../createVirtualMachine/createVM005.java | 265 ++++ .../createVM005/TestDescription.java | 61 + .../defaultConnector/default001.java | 148 +++ .../default001/TestDescription.java | 61 + .../launchingConnectors/launching001.java | 152 +++ .../launching001/TestDescription.java | 61 + .../listeningConnectors/listening001.java | 154 +++ .../listening001/TestDescription.java | 61 + .../majorInterfaceVersion/major001.java | 144 +++ .../major001/TestDescription.java | 61 + .../minorInterfaceVersion/minor001.java | 149 +++ .../minor001/TestDescription.java | 61 + .../jdi/VoidType/_itself_/voidtype001.java | 458 +++++++ .../_itself_/voidtype001/TestDescription.java | 65 + .../jdi/VoidType/_itself_/voidtype001a.java | 115 ++ .../jdi/VoidType/toString/tostring001.java | 179 +++ .../toString/tostring001/TestDescription.java | 64 + .../jdi/VoidType/toString/tostring001a.java | 110 ++ .../VoidValue/equals/equals001/equals001.java | 595 +++++++++ .../equals/equals001/equals001a.java | 189 +++ .../nsk/jdi/VoidValue/equals/equals002.java | 217 ++++ .../equals/equals002/TestDescription.java | 72 ++ .../nsk/jdi/VoidValue/equals/equals002a.java | 97 ++ .../hashCode/hashcode001/hashcode001.java | 609 ++++++++++ .../hashCode/hashcode001/hashcode001a.java | 189 +++ .../jdi/VoidValue/toString/tostring001.java | 183 +++ .../toString/tostring001/TestDescription.java | 65 + .../jdi/VoidValue/toString/tostring001a.java | 108 ++ .../WatchpointEvent/_itself_/wevent001.java | 196 +++ .../_itself_/wevent001/TestDescription.java | 72 ++ .../WatchpointEvent/_itself_/wevent001a.java | 300 +++++ .../jdi/WatchpointEvent/field/field001.java | 327 +++++ .../field/field001/TestDescription.java | 77 ++ .../jdi/WatchpointEvent/field/field001a.java | 219 ++++ .../jdi/WatchpointEvent/object/object001.java | 428 +++++++ .../object/object001/TestDescription.java | 75 ++ .../WatchpointEvent/object/object001a.java | 248 ++++ .../valueCurrent/valuecur001.java | 298 +++++ .../valuecur001/TestDescription.java | 87 ++ .../valueCurrent/valuecur001a.java | 271 +++++ .../_bounds_/filters001.java | 238 ++++ .../_bounds_/filters001/TestDescription.java | 61 + .../_bounds_/filters001a.java | 58 + .../addClassExclusionFilter/filter001.java | 215 ++++ .../filter001/TestDescription.java | 82 ++ .../addClassExclusionFilter/filter001a.java | 259 ++++ .../addClassExclusionFilter/filter002.java | 215 ++++ .../filter002/TestDescription.java | 82 ++ .../addClassExclusionFilter/filter002a.java | 259 ++++ .../addClassExclusionFilter/filter003.java | 538 +++++++++ .../filter003/TestDescription.java | 80 ++ .../addClassExclusionFilter/filter003a.java | 172 +++ .../addClassExclusionFilter/filter004.java | 538 +++++++++ .../filter004/TestDescription.java | 81 ++ .../addClassExclusionFilter/filter004a.java | 172 +++ .../addClassFilter_rt/filter_rt001.java | 172 +++ .../filter_rt001/TestDescription.java | 82 ++ .../addClassFilter_rt/filter_rt001a.java | 254 ++++ .../addClassFilter_rt/filter_rt002.java | 170 +++ .../filter_rt002/TestDescription.java | 82 ++ .../addClassFilter_rt/filter_rt002a.java | 254 ++++ .../addClassFilter_rt/filter_rt003.java | 535 ++++++++ .../filter_rt003/TestDescription.java | 80 ++ .../addClassFilter_rt/filter_rt003a.java | 146 +++ .../addClassFilter_rt/filter_rt004.java | 535 ++++++++ .../filter_rt004/TestDescription.java | 80 ++ .../addClassFilter_rt/filter_rt004a.java | 146 +++ .../addClassFilter_rt/filter_rt005.java | 211 ++++ .../filter_rt005/TestDescription.java | 82 ++ .../addClassFilter_rt/filter_rt005a.java | 254 ++++ .../addClassFilter_rt/filter_rt006.java | 207 ++++ .../filter_rt006/TestDescription.java | 82 ++ .../addClassFilter_rt/filter_rt006a.java | 254 ++++ .../addClassFilter_s/filter_s001.java | 207 ++++ .../filter_s001/TestDescription.java | 82 ++ .../addClassFilter_s/filter_s001a.java | 260 ++++ .../addClassFilter_s/filter_s002.java | 206 ++++ .../filter_s002/TestDescription.java | 82 ++ .../addClassFilter_s/filter_s002a.java | 260 ++++ .../addClassFilter_s/filter_s003.java | 535 ++++++++ .../filter_s003/TestDescription.java | 81 ++ .../addClassFilter_s/filter_s003a.java | 172 +++ .../addClassFilter_s/filter_s004.java | 535 ++++++++ .../filter_s004/TestDescription.java | 81 ++ .../addClassFilter_s/filter_s004a.java | 172 +++ .../addInstanceFilter/instancefilter001.java | 197 +++ .../instancefilter001/TestDescription.java | 84 ++ .../addInstanceFilter/instancefilter001a.java | 196 +++ .../addInstanceFilter/instancefilter002.java | 196 +++ .../instancefilter002/TestDescription.java | 84 ++ .../addInstanceFilter/instancefilter002a.java | 196 +++ .../addInstanceFilter/instancefilter003.java | 562 +++++++++ .../instancefilter003/TestDescription.java | 83 ++ .../addInstanceFilter/instancefilter003a.java | 183 +++ .../addInstanceFilter/instancefilter004.java | 562 +++++++++ .../instancefilter004/TestDescription.java | 83 ++ .../addInstanceFilter/instancefilter004a.java | 183 +++ .../addInstanceFilter/instancefilter005.java | 529 ++++++++ .../instancefilter005/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter005a.java | 183 +++ .../addInstanceFilter/instancefilter006.java | 529 ++++++++ .../instancefilter006/TestDescription.java | 82 ++ .../addInstanceFilter/instancefilter006a.java | 183 +++ .../addInstanceFilter/instancefilter007.java | 212 ++++ .../instancefilter007/TestDescription.java | 92 ++ .../addInstanceFilter/instancefilter007a.java | 196 +++ .../addInstanceFilter/instancefilter008.java | 210 ++++ .../instancefilter008/TestDescription.java | 92 ++ .../addInstanceFilter/instancefilter008a.java | 196 +++ .../addThreadFilter/addthreadfilter001.java | 165 +++ .../addthreadfilter001/TestDescription.java | 77 ++ .../addThreadFilter/addthreadfilter001a.java | 197 +++ .../addThreadFilter/addthreadfilter002.java | 164 +++ .../addthreadfilter002/TestDescription.java | 77 ++ .../addThreadFilter/addthreadfilter002a.java | 197 +++ .../addThreadFilter/addthreadfilter003.java | 552 +++++++++ .../addthreadfilter003/TestDescription.java | 76 ++ .../addThreadFilter/addthreadfilter003a.java | 185 +++ .../addThreadFilter/addthreadfilter004.java | 552 +++++++++ .../addthreadfilter004/TestDescription.java | 76 ++ .../addThreadFilter/addthreadfilter004a.java | 185 +++ .../addThreadFilter/addthreadfilter005.java | 555 +++++++++ .../addthreadfilter005/TestDescription.java | 76 ++ .../addThreadFilter/addthreadfilter005a.java | 188 +++ .../addThreadFilter/addthreadfilter006.java | 555 +++++++++ .../addthreadfilter006/TestDescription.java | 76 ++ .../addThreadFilter/addthreadfilter006a.java | 188 +++ .../addThreadFilter/addthreadfilter007.java | 190 +++ .../addthreadfilter007/TestDescription.java | 85 ++ .../addThreadFilter/addthreadfilter007a.java | 198 +++ .../addThreadFilter/addthreadfilter008.java | 190 +++ .../addthreadfilter008/TestDescription.java | 85 ++ .../addThreadFilter/addthreadfilter008a.java | 198 +++ .../jdi/WatchpointRequest/field/field001.java | 510 ++++++++ .../field/field001/TestDescription.java | 73 ++ .../WatchpointRequest/field/field001a.java | 172 +++ .../jdi/WatchpointRequest/field/field002.java | 511 ++++++++ .../field/field002/TestDescription.java | 73 ++ .../WatchpointRequest/field/field002a.java | 172 +++ .../ClassPrepareEvents001.java | 105 ++ .../MonitorEvents001/TestDescription.java | 77 ++ .../MonitorEvents002/TestDescription.java | 78 ++ .../forceEarlyReturn001/TestDescription.java | 71 ++ .../forceEarlyReturn001.tests | 8 + .../forceEarlyReturn002/TestDescription.java | 74 ++ .../forceEarlyReturn002.tests | 9 + .../heapwalking001/TestDescription.java | 65 + .../heapwalking001/heapwalking001.tests | 5 + .../heapwalking002/TestDescription.java | 68 ++ .../heapwalking002/heapwalking002.tests | 6 + .../serial/mixed001/TestDescription.java | 75 ++ .../jdi/stress/serial/mixed001/mixed001.tests | 15 + .../serial/mixed002/TestDescription.java | 74 ++ .../jdi/stress/serial/mixed002/mixed002.tests | 15 + .../monitorEvents001/TestDescription.java | 60 + .../monitorEvents001/monitorEvents001.tests | 10 + .../monitorEvents002/TestDescription.java | 63 + .../monitorEvents002/monitorEvents002.tests | 11 + .../TestDescription.java | 64 + .../ownedMonitorsAndFrames001.tests | 8 + .../TestDescription.java | 69 ++ .../ownedMonitorsAndFrames002.tests | 9 + .../nsk/share/ExtraClassesBuilder.java | 96 ++ .../nsk/share/jdi/libMonitorEnterExecutor.c | 25 + .../nsk/share/jni/libJNIreferences.c | 25 + .../share/jpda/NativeMethodsTestThread.java | 314 +++++ .../share/jpda/libNativeMethodsTestThread.c | 527 ++++++++ .../nsk/share/locks/libJNIMonitorLocker.c | 25 + .../nsk/share/locks/libLockingThread.c | 25 + 3454 files changed, 577169 insertions(+) create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AccessWatchpointEvent/_itself_/awevent001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AccessWatchpointEvent/_itself_/awevent001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AccessWatchpointEvent/_itself_/awevent001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/description/description001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/description/description001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/label/label001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/label/label001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/TestDriver.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/attach004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/attach004t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/newclass/tc01x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/newclass/tc01x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/newclass/tc02x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/newclass/tc02x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/newclass/tc03x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/newclass/tc04x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/newclass/tc04x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001/newclass/tc05x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/newclass/tc05x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/newclass/tc06x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/newclass/tc07x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/newclass/tc08x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/newclass/tc09x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/newclass/tc09x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/newclass/tc10x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/newclass/tc10x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/loadclass/definedclasses003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/loadclass/definedclasses003c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/loadclass/definedclasses005b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/loadclass/reflectype002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/thread/thread001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/thread/thread001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/thread/thread001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/TestClass2.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/addSourceNameFilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter002/addSourceNameFilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue006t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue007t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/loadclass/classname001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/loadclass/signature001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/loadclass/signature001c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/loadclass/Superexclfilter001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/loadclass/Superfilter001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/description/description001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/description/description001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/transport/transport001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/transport/transport001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ConnectorsJarBuilder.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ConstantField/values001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ConstantField/values001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/_itself_/event001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/_itself_/event001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/_itself_/event001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/_itself_/event002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/_itself_/event002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/_itself_/event002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003/newclass/disable003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/newclass/delevtreq003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ExtraClassesInstaller.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/max/max001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/max/max001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/min/min001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/min/min001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001o.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002o.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003o.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004o.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001o.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/lineNumber_s002/lineNumber_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourceName_s002/sourceName_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcePath_s002/sourcePath_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss002/allLineLocations_ss002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isBridge/isbridge001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isBridge/isbridge001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isBridge/isbridge001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001/newclass/isobsolete001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002/newclass/isobsolete002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/newclass/isobsolete003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi002/locationsOfLine_ssi002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassExclusionFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ClassName/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ReferenceType/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addInstanceFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addThreadFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassExclusionFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ClassName/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ReferenceType/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addInstanceFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addThreadFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/MonitorWaitRequest001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/MonitorWaitRequest002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassExclusionFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ClassName/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ReferenceType/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addInstanceFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addThreadFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassExclusionFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ClassName/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ReferenceType/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addInstanceFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addThreadFilter/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/dummyPackage/invokemethod014a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod009t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects001/referringObjects001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects004/referringObjects004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue003t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/connectors/PlugAttachConnector001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/plugAttachConnect001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/connectors/PlugAttachConnector002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/plugAttachConnect002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/connectors/PlugAttachConnector003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/plugAttachConnect003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/connectors/PlugLaunchConnector001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/plugLaunchConnect001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/connectors/PlugLaunchConnector002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/plugLaunchConnect002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/connectors/PlugLaunchConnector003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/plugLaunchConnect003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/connectors/PlugListenConnector001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/plugListenConnect001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/connectors/PlugListenConnector002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/plugListenConnect002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/connectors/PlugListenConnector003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/plugListenConnect003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugAttachConnector001_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugAttachConnector001_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugLaunchConnector001_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugLaunchConnector001_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugListenConnector001_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugListenConnector001_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/plugMultiConnect001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_03.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_03.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_03.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/plugMultiConnect002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/PlugTransportService003_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/PlugTransportService003_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/plugMultiConnect003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_03.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/plugMultiConnect004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugAttachConnector005_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugAttachConnector005_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugLaunchConnector005_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugLaunchConnector005_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugListenConnector005_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugListenConnector005_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugTransportService005_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugTransportService005_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/plugMultiConnect005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/META-INF/services/com.sun.jdi.connect.Connector create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_03.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_03.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_03.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_01.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_02.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_03.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/plugMultiConnect006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/connectors/PlugTransportService001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/transportService001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/connectors/PlugTransportService002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/transportService002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/connectors/PlugTransportService003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/transportService003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/loadclass/allfields002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/loadclass/allfields003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss004/allLineLocations_ss004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/loadclass/allmethods002aClassForCheck.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/loadclass/allmethods003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availableStrata002/availableStrata002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/loadclass/classloader001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/loadclass1/classloader001c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/loadclass/classobj002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum002/defaultStratum002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum003/defaultStratum003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass1.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass2.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass3.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/defaultStratum004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/defaultStratum004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/dummyPackage/getvalues003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/loadclass/equals002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/loadclass/failedtoinit002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/loadclass/fieldbyname002aClassForCheck.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/loadclass/fieldbyname003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/loadclass/fields002aClassForCheck.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/loadclass/fields003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue004t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/loadclass/hashcode002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances001/instances001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances003/instances003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances005/instances005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/loadclass/isabstract002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/loadclass/isinit002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/loadclass/isprepared002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/loadclass/isverified002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/loadclass/isverified003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/loadclass/isverified003c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi004/locationsOfLine_ssi004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/loadclass/methods002aClassForCheck.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/loadclass/methods003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/loadclass/methbyname_s002aClassForCheck.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/loadclass/methbyname_s003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/loadclass/methbyname_ss002aClassForCheck.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/loadclass/methbyname_ss003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/loadclass/name002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002/srcdebugx002x.jcod create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002x.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/loadclass/sourcename002b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename004t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourceNames003/sourceNames003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcePaths003/sourcePaths003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/loadclass/visibfield002aClassForCheck.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/loadclass/visibfield003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/loadclass/visibmethod002aClassForCheck.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TEST.properties create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/loadclass/visibmethod003b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/newclass/redefineclasses001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/choices/choices001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/choices/choices001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues003t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue001/setvalue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue001/setvalue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue002/setvalue002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue002/setvalue002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue003/setvalue003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue003/setvalue003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue004/setvalue004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue004/setvalue004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue005/setvalue005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue005/setvalue005t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue006/setvalue006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue006/setvalue006t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent003/stepEvent003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/TestClass1.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/stepEvent004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn003/forceEarlyReturn003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/libforceEarlyReturn004a.c create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/libforceEarlyReturn005a.c create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn010/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn011/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn012/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames003/ownedMonitorsAndFrames003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames005/ownedMonitorsAndFrames005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames006/ownedMonitorsAndFrames006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames007/ownedMonitorsAndFrames007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009/ownedMonitorsAndFrames009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009/ownedMonitorsAndFrames009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status003/status003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status003/status003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status004/status004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status004/status004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status005/status005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status005/status005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status006/status006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status006/status006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status007/status007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status007/status007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status008/status008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status008/status008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Transport/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Transport/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001t.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type002/type002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type002/type002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts001/instancecounts001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts003/instancecounts003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/newclass/redefineclasses001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/newclass/redefineclasses002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/newclass/redefineclasses003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass01/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass02/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass03/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass04/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass05/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass06/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass07/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass08/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass09/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass10/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass01/redefineclasses005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass02/redefineclasses005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass03/redefineclasses005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass04/redefineclasses005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass01/redefineclasses006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass02/redefineclasses006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass03/redefineclasses006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass04/redefineclasses006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass01/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass02/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass03/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass04/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass05/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass06/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass07/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass08/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass01/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass02/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass03/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass04/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass05/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass06/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass07/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass08/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass01/redefineclasses009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass02/redefineclasses009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass03/redefineclasses009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass01/redefineclasses010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass02/redefineclasses010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass03/redefineclasses010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass04/redefineclasses010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass01/redefineclasses011a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass02/redefineclasses011a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass03/redefineclasses011a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass04/redefineclasses011a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/newclass01/redefineclasses012b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/newclass02/redefineclasses012b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass01/redefineclasses013b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass02/redefineclasses013b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass03/redefineclasses013b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass01/redefineclasses014b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass02/redefineclasses014b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass03/redefineclasses014b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass01/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass02/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass03/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass04/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass05/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass06/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass07/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass08/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass01/redefineclasses016b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass02/redefineclasses016b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass03/redefineclasses016b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass04/redefineclasses016b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass05/redefineclasses016b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass06/redefineclasses016b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass01/redefineclasses020b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass02/redefineclasses020b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass03/redefineclasses020b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass04/redefineclasses020b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass01/redefineclasses021b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass02/redefineclasses021b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass03/redefineclasses021b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass04/redefineclasses021b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass01/redefineclasses022b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass02/redefineclasses022b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass03/redefineclasses022b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass01/redefineclasses023b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass02/redefineclasses023b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass03/redefineclasses023b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass01/redefineclasses024b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass02/redefineclasses024b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass03/redefineclasses024b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass04/redefineclasses024b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/newclass01/redefineclasses025b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/newclass02/redefineclasses025b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/newclass/redefineclasses026c_otherName.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027i.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/newclass01/redefineclasses030b.jasm create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/newclass02/redefineclasses030b.jasm create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass01/redefineclasses031a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass02/redefineclasses031a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass03/redefineclasses031a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass04/redefineclasses031a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass05/redefineclasses031a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/newclass/redefineclasses032a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/loadclass/redefineclasses034b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/loadclass/redefineclasses034c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/newclass/redefineclasses034b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/newclass/redefineclasses034c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/loadclass/redefineclasses035b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/loadclass/redefineclasses035c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/newclass/redefineclasses035b.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/newclass/redefineclasses035c.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum002/setDefaultStratum002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum003/setDefaultStratum003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/allConnectors/allconnectors001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/allConnectors/allconnectors001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM002_TargetVM.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM002_TranspServ.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM003_TargetVM.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM003_TranspServ.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM004_TargetVM.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM004_TranspServ.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM005_TargetVM.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM005_TranspServ.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002a.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001/ClassPrepareEvents001.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/forceEarlyReturn001.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/forceEarlyReturn002.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/heapwalking001.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/heapwalking002.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/mixed001.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/mixed002.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/monitorEvents001.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/monitorEvents002.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.tests create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/ExtraClassesBuilder.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/jdi/libMonitorEnterExecutor.c create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/jni/libJNIreferences.c create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/jpda/NativeMethodsTestThread.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/jpda/libNativeMethodsTestThread.c create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/locks/libJNIMonitorLocker.c create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/locks/libLockingThread.c diff --git a/make/test/JtregNativeHotspot.gmk b/make/test/JtregNativeHotspot.gmk index 1c4150f7d70..62cca6a433c 100644 --- a/make/test/JtregNativeHotspot.gmk +++ b/make/test/JtregNativeHotspot.gmk @@ -63,6 +63,21 @@ NSK_MONITORING_INCLUDES := \ -I$(VM_TESTBASE_DIR)/nsk/share/native \ -I$(VM_TESTBASE_DIR)/nsk/share/jni +NSK_JDI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native + +NSK_SHARE_JDI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jdi + +NSK_SHARE_JNI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_SHARE_LOCKS_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/locks + BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libThreadController := $(NSK_MONITORING_INCLUDES) @@ -71,6 +86,15 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libRecursiveMonitoringThread := $(NSK_MONIT BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libLockingThreads := $(NSK_MONITORING_INCLUDES) BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libStackTraceController := $(NSK_MONITORING_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libforceEarlyReturn005a := $(NSK_JDI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libMonitorEnterExecutor := $(NSK_SHARE_JDI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIreferences := $(NSK_SHARE_JNI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libLockingThread := $(NSK_SHARE_LOCKS_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIMonitorLocker := $(NSK_SHARE_LOCKS_INCLUDES) + ################################################################################ # Platform specific setup diff --git a/test/hotspot/jtreg/ProblemList-graal.txt b/test/hotspot/jtreg/ProblemList-graal.txt index 6b4700d91f2..bdd9846e286 100644 --- a/test/hotspot/jtreg/ProblemList-graal.txt +++ b/test/hotspot/jtreg/ProblemList-graal.txt @@ -84,3 +84,54 @@ compiler/jvmci/meta/StableFieldTest.java CODETOOLS-790216 compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/HotSpotConstantReflectionProviderTest.java CODETOOLS-7902162 generic-all compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderTest.java CODETOOLS-7902162 generic-all compiler/jvmci/events/JvmciShutdownEventTest.java CODETOOLS-7902162 generic-all + +vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009.java 8191047 generic-all + +vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012/TestDescription.java 8195600 generic-all +vmTestbase/nsk/jdi/ClassType/setValue/setvalue006/TestDescription.java 8195600 generic-all +vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001/TestDescription.java 8195600 generic-all +vmTestbase/nsk/jdi/Location/lineNumber_s/lineNumber_s002/lineNumber_s002.java 8195600 generic-all +vmTestbase/nsk/jdi/Location/sourcePath_s/sourcePath_s002/sourcePath_s002.java 8195600 generic-all +vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java 8195600 generic-all +vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java 8195600 generic-all +vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011/TestDescription.java 8195600 generic-all +vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012/TestDescription.java 8195600 generic-all +vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects001/referringObjects001.java 8195600 generic-all +vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java 8195600 generic-all +vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects004/referringObjects004.java 8195600 generic-all +vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue005/TestDescription.java 8195600 generic-all +vmTestbase/nsk/jdi/ReferenceType/instances/instances001/instances001.java 8195600 generic-all +vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java 8195600 generic-all +vmTestbase/nsk/jdi/ReferenceType/instances/instances005/instances005.java 8195600 generic-all +vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007/TestDescription.java 8195600 generic-all +vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.java 8195600 generic-all +vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java 8195600 generic-all +vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts003/instancecounts003.java 8195600 generic-all +vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java 8195600 generic-all +vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn003/forceEarlyReturn003.java 8195600 generic-all +vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004.java 8195600 generic-all + +vmTestbase/nsk/jdi/Location/sourceName_s/sourceName_s002/sourceName_s002.java 8200387 generic-all +vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss002/allLineLocations_ss002.java 8200387 generic-all +vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi002/locationsOfLine_ssi002.java 8200387 generic-all +vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java 8200387 generic-all +vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java 8200387 generic-all +vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss004/allLineLocations_ss004.java 8200387 generic-all +vmTestbase/nsk/jdi/ReferenceType/availableStrata/availableStrata002/availableStrata002.java 8200387 generic-all +vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum002/defaultStratum002.java 8200387 generic-all +vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java 8200387 generic-all +vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi004/locationsOfLine_ssi004.java 8200387 generic-all +vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourceNames003/sourceNames003.java 8200387 generic-all +vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcePaths003/sourcePaths003.java 8200387 generic-all +vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java 8200387 generic-all +vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java 8200387 generic-all +vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java 8200387 generic-all +vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004.java 8200387 generic-all +vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts001/instancecounts001.java 8200387 generic-all +vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts002/TestDescription.java 8200387 generic-all +vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum002/setDefaultStratum002.java 8200387 generic-all + +vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/TestDescription.java 8195627 generic-all +vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028/TestDescription.java 8195627 generic-all +vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/TestDescription.java 8195627 generic-all + diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 9de4220fd01..2f550390570 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -109,4 +109,18 @@ vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded004 vmTestbase/nsk/monitoring/MemoryPoolMBean/isUsageThresholdExceeded/isexceeded005/TestDescription.java 8153598 generic-all vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Deadlock/JavaDeadlock001/TestDescription.java 8060733 generic-all +vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001/TestDescription.java 8153613 generic-all +vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001/TestDescription.java 6530620 generic-all +vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002/TestDescription.java 4903717 generic-all +vmTestbase/nsk/jdi/ThreadReference/resume/resume001/TestDescription.java 8072701 generic-all +vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java 7034630 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/TestDescription.java 8013728 generic-all +vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004/TestDescription.java 4751860 generic-all +vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003/TestDescription.java 8066993 generic-all +vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001/TestDescription.java 6604963 generic-all +vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java 8065773 generic-all +vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java 8065773 generic-all +vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005/TestDescription.java 8068225 generic-all +vmTestbase/nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001/ClassPrepareEvents001.java 6426321 generic-all + ############################################################################# diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index d6ff348014c..42835663663 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -587,4 +587,565 @@ vmTestbase_nsk_monitoring_quick = \ vmTestbase/nsk/monitoring/ThreadMXBean/GetThreadAllocatedBytes/noAllocationTest_proxy_default/TestDescription.java \ vmTestbase/nsk/monitoring/ThreadMXBean/GetThreadAllocatedBytes/noAllocationTest_proxy_custom/TestDescription.java +# JDI tests +vmTestbase_nsk_jdi = \ + vmTestbase/nsk/jdi + +vmTestbase_nsk_jdi_quick = \ + vmTestbase/nsk/jdi/Argument/description/description001/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/isValid/isvalid001/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/isValid/isvalid002/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/isValid/isvalid003/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/isValid/isvalid004/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/isValid/isvalid005/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/name/name001/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/value/value001/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/value/value002/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/value/value003/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/setValue/setvalue001/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/setValue/setvalue002/TestDescription.java \ + vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001/TestDescription.java \ + vmTestbase/nsk/jdi/AttachingConnector/attach/attach002/TestDescription.java \ + vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001/TestDescription.java \ + vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002/TestDescription.java \ + vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001/TestDescription.java \ + vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002/TestDescription.java \ + vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001/TestDescription.java \ + vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002/TestDescription.java \ + vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001/TestDescription.java \ + vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002/TestDescription.java \ + vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001/TestDescription.java \ + vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002/TestDescription.java \ + vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/TestDescription.java \ + vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004/TestDescription.java \ + vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/TestDescription.java \ + vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002/TestDescription.java \ + vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001/TestDescription.java \ + vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002/TestDescription.java \ + vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003/TestDescription.java \ + vmTestbase/nsk/jdi/Connector/description/description001/TestDescription.java \ + vmTestbase/nsk/jdi/Connector/name/name001/TestDescription.java \ + vmTestbase/nsk/jdi/Connector/transport/transport001/TestDescription.java \ + vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue001/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/max/max001/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/min/min001/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001/TestDescription.java \ + vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001/TestDescription.java \ + vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001/TestDescription.java \ + vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002/TestDescription.java \ + vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004/TestDescription.java \ + vmTestbase/nsk/jdi/ListeningConnector/accept/accept001/TestDescription.java \ + vmTestbase/nsk/jdi/ListeningConnector/accept/accept002/TestDescription.java \ + vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java \ + vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001/TestDescription.java \ + vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001/TestDescription.java \ + vmTestbase/nsk/jdi/LongValue/compareTo/compareto001/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/TestDescription.java \ + vmTestbase/nsk/jdi/SelectedArgument/choices/choices001/TestDescription.java \ + vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001/TestDescription.java \ + vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002/TestDescription.java \ + vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001/TestDescription.java \ + vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/thread/thread001/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002/TestDescription.java \ + vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001/TestDescription.java \ + vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/depth/depth001/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/depth/depth002/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/depth/depth003/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/size/size001/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/size/size002/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/thread/thread001/TestDescription.java \ + vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001/TestDescription.java \ + vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002/TestDescription.java \ + vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003/TestDescription.java \ + vmTestbase/nsk/jdi/StringReference/value/value001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadGroupReference/name/name001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/frame/frame001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/frames/frames001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/name/name001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/resume/resume001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/status/status003/status003.java \ + vmTestbase/nsk/jdi/ThreadReference/status/status004/status004.java \ + vmTestbase/nsk/jdi/ThreadReference/status/status005/status005.java \ + vmTestbase/nsk/jdi/ThreadReference/status/status006/status006.java \ + vmTestbase/nsk/jdi/ThreadReference/status/status007/status007.java \ + vmTestbase/nsk/jdi/ThreadReference/status/status008/status008.java \ + vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005/TestDescription.java \ + vmTestbase/nsk/jdi/Transport/name/name001/TestDescription.java \ + vmTestbase/nsk/jdi/Type/name/name001/TestDescription.java \ + vmTestbase/nsk/jdi/Type/name/name002/TestDescription.java \ + vmTestbase/nsk/jdi/Type/name/name003/TestDescription.java \ + vmTestbase/nsk/jdi/Type/signature/signature001/TestDescription.java \ + vmTestbase/nsk/jdi/Type/signature/signature002/TestDescription.java \ + vmTestbase/nsk/jdi/Type/signature/signature003/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/name/name001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/name/name003/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/signature/sign001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/signature/sign003/TestDescription.java \ + vmTestbase/nsk/jdi/Value/type/type001/TestDescription.java \ + vmTestbase/nsk/jdi/Value/type/type002/type002.java \ + vmTestbase/nsk/jdi/Value/type/type003/TestDescription.java \ + vmTestbase/nsk/jdi/Value/_itself_/value001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/description/description001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/exit/exit001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/exit/exit002/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/name/name001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/process/process001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/version/version001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/allConnectors/allconnectors001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001/TestDescription.java \ + vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001/TestDescription.java \ + vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001.java \ + vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001.java \ + vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001/TestDescription.java \ + vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002/TestDescription.java \ + vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003/TestDescription.java \ + vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001/TestDescription.java \ + vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002/TestDescription.java \ + vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003/TestDescription.java \ + vmTestbase/nsk/jdi/VMStartEvent/thread/thread001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointEvent/object/object001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointEvent/field/field001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/field/field001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/field/field002/TestDescription.java \ + vmTestbase/nsk/jdi/AttachingConnector/attach/attach003/TestDescription.java \ + vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/setValue/setvalue006/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/setValue/setvalue007/TestDescription.java \ + vmTestbase/nsk/jdi/Connector/_bounds_/bounds001/TestDescription.java \ + vmTestbase/nsk/jdi/Connector/toString/tostring001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001/TestDescription.java \ + vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001/TestDescription.java \ + vmTestbase/nsk/jdi/Event/equals/equals001/TestDescription.java \ + vmTestbase/nsk/jdi/Event/hashCode/hashcode001/TestDescription.java \ + vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001/TestDescription.java \ + vmTestbase/nsk/jdi/EventRequest/disable/disable003/TestDescription.java \ + vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001/TestDescription.java \ + vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/TestDescription.java \ + vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001/TestDescription.java \ + vmTestbase/nsk/jdi/EventSet/resume/resume011/TestDescription.java \ + vmTestbase/nsk/jdi/EventSet/toString/tostring001/TestDescription.java \ + vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001/TestDescription.java \ + vmTestbase/nsk/jdi/LocalVariable/toString/tostring001/TestDescription.java \ + vmTestbase/nsk/jdi/Method/_bounds_/bounds001/TestDescription.java \ + vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/TestDescription.java \ + vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001/TestDescription.java \ + vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001/TestDescription.java \ + vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod002/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod009/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue003/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004/TestDescription.java \ + vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue005/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/fields/fields005/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue004/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue005/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/methods/methods005/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename004/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006/TestDescription.java \ + vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001/TestDescription.java \ + vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/getValues/getvalues003/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001/TestDescription.java \ + vmTestbase/nsk/jdi/StackFrame/setValue/setvalue005/setvalue005.java \ + vmTestbase/nsk/jdi/StackFrame/setValue/setvalue006/setvalue006.java \ + vmTestbase/nsk/jdi/StackFrame/toString/tostring001/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003/TestDescription.java \ + vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/stop/stop002/TestDescription.java \ + vmTestbase/nsk/jdi/Type/hashCode/hashcode001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007/TestDescription.java \ + vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001/TestDescription.java \ + vmTestbase/nsk/jdi/VoidType/toString/tostring001/TestDescription.java \ + vmTestbase/nsk/jdi/VoidValue/equals/equals002/TestDescription.java \ + vmTestbase/nsk/jdi/VoidValue/toString/tostring001/TestDescription.java \ + vmTestbase/nsk/jdi/ConstantField/values001/TestDescription.java \ + vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002/TestDescription.java \ + vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002/TestDescription.java \ + vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002/TestDescription.java \ + vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002/TestDescription.java \ + vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003/TestDescription.java \ + vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/isEnum/isenum001/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/setValue/setvalue008/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002/TestDescription.java \ + vmTestbase/nsk/jdi/ClassType/superclass/superclass002/TestDescription.java \ + vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001/TestDescription.java \ + vmTestbase/nsk/jdi/Field/type/type004/TestDescription.java \ + vmTestbase/nsk/jdi/Field/typeName/typename002/TestDescription.java \ + vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001/TestDescription.java \ + vmTestbase/nsk/jdi/Method/arguments/arguments003/TestDescription.java \ + vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003/TestDescription.java \ + vmTestbase/nsk/jdi/Method/isBridge/isbridge001/TestDescription.java \ + vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001/TestDescription.java \ + vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/plugAttachConnect001.java \ + vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/plugAttachConnect002.java \ + vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/plugAttachConnect003.java \ + vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/plugLaunchConnect001.java \ + vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/plugLaunchConnect002.java \ + vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/plugLaunchConnect003.java \ + vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/plugListenConnect001.java \ + vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/plugListenConnect002.java \ + vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/plugListenConnect003.java \ + vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/plugMultiConnect001.java \ + vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/plugMultiConnect002.java \ + vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/plugMultiConnect003.java \ + vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/plugMultiConnect004.java \ + vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/plugMultiConnect005.java \ + vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/plugMultiConnect006.java \ + vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/transportService001.java \ + vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/transportService002.java \ + vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/transportService003.java \ + vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/fields/fields006/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/methods/methods006/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006/TestDescription.java \ + vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004/TestDescription.java \ + vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005/TestDescription.java \ + vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts001/instancecounts001.java \ + vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts002/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts003/instancecounts003.java \ + vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004.java \ + vmTestbase/nsk/jdi/ReferenceType/instances/instances001/instances001.java \ + vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java \ + vmTestbase/nsk/jdi/ReferenceType/instances/instances005/instances005.java \ + vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects001/referringObjects001.java \ + vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java \ + vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java \ + vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects004/referringObjects004.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn003/forceEarlyReturn003.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn006/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007/TestDescription.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014.java \ + vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015.java \ + vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.java \ + vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.java \ + vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames003/ownedMonitorsAndFrames003.java \ + vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004.java \ + vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames005/ownedMonitorsAndFrames005.java \ + vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames008/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassExclusionFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ClassName/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ReferenceType/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addInstanceFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addThreadFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassExclusionFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ClassName/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ReferenceType/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addInstanceFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addThreadFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitRequest/addClassExclusionFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ClassName/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ReferenceType/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitRequest/addInstanceFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitRequest/addThreadFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassExclusionFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ClassName/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ReferenceType/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitedRequest/addInstanceFilter/TestDescription.java \ + vmTestbase/nsk/jdi/MonitorWaitedRequest/addThreadFilter/TestDescription.java \ + vmTestbase/nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001/ClassPrepareEvents001.java \ + vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/addSourceNameFilter001.java \ + vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter002/addSourceNameFilter002.java \ + vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java \ + vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java \ + vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java \ + vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java \ + vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java \ + vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java \ + vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java \ + vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java \ + vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java \ + vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum002/setDefaultStratum002.java \ + vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java \ + vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss004/allLineLocations_ss004.java \ + vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss002/allLineLocations_ss002.java \ + vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java \ + vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java \ + vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi004/locationsOfLine_ssi004.java \ + vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi002/locationsOfLine_ssi002.java \ + vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java \ + vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourceNames003/sourceNames003.java \ + vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcePaths003/sourcePaths003.java \ + vmTestbase/nsk/jdi/ReferenceType/availableStrata/availableStrata002/availableStrata002.java \ + vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum002/defaultStratum002.java \ + vmTestbase/nsk/jdi/Location/lineNumber_s/lineNumber_s002/lineNumber_s002.java \ + vmTestbase/nsk/jdi/Location/sourceName_s/sourceName_s002/sourceName_s002.java \ + vmTestbase/nsk/jdi/Location/sourcePath_s/sourcePath_s002/sourcePath_s002.java \ + vmTestbase/nsk/jdi/AttachingConnector/attach/attach005/TestDescription.java \ + vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend002/TestDescription.java \ + vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend003/TestDescription.java \ + vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001.java \ + vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002.java \ + vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003.java \ + vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004.java \ + vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001.java \ + vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java \ + vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AccessWatchpointEvent/_itself_/awevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AccessWatchpointEvent/_itself_/awevent001.java new file mode 100644 index 00000000000..8ff5df69af0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AccessWatchpointEvent/_itself_/awevent001.java @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.AccessWatchpointEvent._itself_; + +import com.sun.jdi.Field; +import com.sun.jdi.Method; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.AccessWatchpointRequest; +import com.sun.jdi.request.BreakpointRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.VMMismatchException; +import com.sun.jdi.event.*; + +import java.util.Iterator; +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.AccessWatchpointEvent.createAccessWatchpointRequest() + * properly creates new disabled watchpoints which watch accesses to + * the fields of different types. + * A debugger part of the test checks that: + *
  • all created watchpoint requests are disabled + *
  • after the watchpoint requests activation, all events corresponding + * to them, are properly generated. + */ +public class awevent001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.AccessWatchpointEvent._itself_.awevent001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_BREAKPOINT = "breakpoint"; + static final String COMMAND_RUN1 = "run1"; + static final int FLDS_NUM = 9; // number of debuggee's fields + static final String COMMAND_RUN[] = { + "run1", "run2", "run3", "run4", + "run5", "run6", "run7", "run8", "run9" + }; + static final String DEBUGGEE_FLDS[][] = { + {"byte", "byteFld"}, + {"short", "shortFld"}, + {"int", "intFld"}, + {"long", "longFld"}, + {"float", "floatFld"}, + {"double", "doubleFld"}, + {"char", "charFld"}, + {"boolean", "booleanFld"}, + {"java.lang.String", "strFld"} + }; + private volatile int accFCount[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile AccessWatchpointRequest awpRequest[]; + private volatile int tot_res = PASSED; + private volatile boolean breakPointReceived = false; + +// for notification a main thread about received events + private Object gotEvent = new Object(); + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new awevent001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + List fields; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "awevent001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + if ( !vm.canWatchFieldAccess() ) { + log.display(" TEST CANCELLED due to: vm.canWatchFieldAccess() == false"); + return quitDebuggee(); + } + +// Create testing requests + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null"); + tot_res = FAILED; + return quitDebuggee(); + } + try { + fields = rType.allFields(); + } catch (Exception e) { + log.complain("TEST FAILURE: allFields: caught " + e); + tot_res = FAILED; + return quitDebuggee(); + } + if (createRequests(erManager, fields, rType) == FAILED) { + tot_res = FAILED; + return quitDebuggee(); + } + +// Create a thread listening JDI events + elThread = new EventListener(); + elThread.setPriority(Thread.NORM_PRIORITY + 2); + synchronized(gotEvent) { + elThread.start(); + +// Check that all created AccessWatchpointRequests are disabled + log.display("\na) Getting disabled requested AccessWatchpointEvents..."); + if (checkEvents(false) != PASSED) { + return FAILED; + } + +// Stop at the breakpoint so we can verify that there were no AccessWatchPointEvent + if (sendCommand(COMMAND_BREAKPOINT, true) != PASSED) { + return FAILED; + } + if (!breakPointReceived) { + log.display("TEST FAILED: Did not receive the breakpoint event."); + return FAILED; + } + +// Check that no AccessWatchpoint events occurred + for (int i=0; iisPackagePrivate() + * of the JDI interface Accessible works fine with + * the ArrayType sub-interface. + */ +public class accipp001 extends Log { + final static boolean MODE_VERBOSE = false; + + /** The main class names of the debugger & debugee applications. */ + private final static String + thisClassName = "nsk.jdi.Accessible.isPackagePrivate.accipp001", + debugeeName = thisClassName + "a"; + + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** Debugee's classes which status (private or public) is known. */ + private final static String knownClasses[][] = { + {"boolean", "public"}, + {"byte" , "public"}, + {"char" , "public"}, + {"double" , "public"}, + {"float" , "public"}, + {"int" , "public"}, + {"long" , "public"}, + {"short" , "public"}, + + {"java.lang.Boolean" , "public"}, + {"java.lang.Byte" , "public"}, + {"java.lang.Character", "public"}, + {"java.lang.Double" , "public"}, + {"java.lang.Float" , "public"}, + {"java.lang.Integer" , "public"}, + {"java.lang.Long" , "public"}, + {"java.lang.Short" , "public"}, + {"java.lang.String" , "public"}, + {"java.lang.Object" , "public"}, + + {thisClassName+"a", "public" }, + {thisClassName+"e", "package private"}, + + {debugeeName+"$U", "private" }, + {debugeeName+"$V", "protected" }, + {debugeeName+"$W", "public" }, + {debugeeName+"$P", "package private"} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String args[]) { + int exitCode = run(args,System.out); + System.exit(exitCode + 95); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String args[], PrintStream out) { + return new accipp001().runThis(args,out); // incarnate Log + } + + /** + * Non-static variant of the method run(args,out) + * can use Log features. + */ + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + IOPipe pipe = new IOPipe(debugee); + + + debugee.redirectStderr(out); + debugee.resume(); + + String line = pipe.readln(); + if (!line.equals("ready")) { + logHandler.complain("# Cannot recognize debugee's signal: " + line); + return 2; + }; + +// ReferenceType classes[] = debugee.classes(); +// for (int i=0; i 0) { + logHandler.complain("Errors revealed: " + errors); + return 2; + }; + + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 95) { + logHandler.complain("Debugee's exit status=" + status); + return 2; + }; + + logHandler.display("Passed"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001/TestDescription.java new file mode 100644 index 00000000000..ad21279e756 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isPackagePrivate/accipp001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/Accessible/isPackagePrivate/isPackagePrivate001 test + * checks the isPrivatePackage() method of Accessible interface + * of the com.sun.jdi package for ArrayType, ClassType, InterfaceType. + * COMMENTS + * --------- + * The test is updated to use new share classes as follows: + * - two lines, 31 and 32, with argsHandler and logHandler are added + * - statements with definitions, lines 87-100, are added; + * obsolete lines are removed; + * - all "complain" are replaced with "logHandler.complain".. + * - all "display" are replaced with "logHandler.display" + * -------- + * I. To fix the bug 4554254, the following is done: + * file accipp001.java: + * - additional check : !knownClasses[i][1].equals("private") && + * is added to the statement in lines 131-133 + * file accipp001a.java: + * - initialization values are added in variable declarations in lines + * 26-36, 47. + * II. As the test doesn't contain checks on both short and Short (?), + * two lines with variables of both types are added. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isPackagePrivate.accipp001 + * nsk.jdi.Accessible.isPackagePrivate.accipp001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isPackagePrivate.accipp001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001a.java new file mode 100644 index 00000000000..e8eea9f20c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001a.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.isPackagePrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the JDI test. + */ +public class accipp001a { + boolean z0, z1[]={z0}, z2[][]={z1}, z3[][][]={z2}, z4[][][][]={z3}; + byte b0, b1[]={b0}, b2[][]={b1}, b3[][][]={b2}, b4[][][][]={b3}; + char c0, c1[]={c0}, c2[][]={c1}, c3[][][]={c2}, c4[][][][]={c3}; + double d0, d1[]={d0}, d2[][]={d1}, d3[][][]={d2}, d4[][][][]={d3}; + float f0, f1[]={f0}, f2[][]={f1}, f3[][][]={f2}, f4[][][][]={f3}; + int i0, i1[]={i0}, i2[][]={i1}, i3[][][]={i2}, i4[][][][]={i3}; + long l0, l1[]={l0}, l2[][]={l1}, l3[][][]={l2}, l4[][][][]={l3}; + short s0, s1[]={s0}, s2[][]={s1}, s3[][][]={s2}, s4[][][][]={s3}; + + Boolean Z0 = new Boolean(true), Z1[] ={Z0}, Z2[][]={Z1}, Z3[][][]={Z2}, Z4[][][][]={Z3}; + Byte B0 = new Byte("0"), B1[] ={B0}, B2[][]={B1}, B3[][][]={B2}, B4[][][][]={B3}; + Character C0 = new Character('0'), C1[] ={C0}, C2[][]={C1}, C3[][][]={C2}, C4[][][][]={C3}; + Double D0 = new Double(0), D1[] ={D0}, D2[][]={D1}, D3[][][]={D2}, D4[][][][]={D3}; + Float F0 = new Float(0), F1[] ={F0}, F2[][]={F1}, F3[][][]={F2}, F4[][][][]={F3}; + Integer I0 = new Integer(0), I1[] ={I0}, I2[][]={I1}, I3[][][]={I2}, I4[][][][]={I3}; + Long L0 = new Long(0), L1[] ={L0}, L2[][]={L1}, L3[][][]={L2}, L4[][][][]={L3}; + Short Sh0 = new Short("1"), Sh1[]={Sh0}, Sh2[][]={Sh1}, Sh3[][][]={Sh2}, Sh4[][][][]={Sh3}; + String S0 = new String(" "), S1[] ={S0}, S2[][]={S1}, S3[][][]={S2}, S4[][][][]={S3}; + Object O0 = new Object(), O1[] ={O0}, O2[][]={O1}, O3[][][]={O2}, O4[][][][]={O3}; + + private static class U {} // private ==> package private + protected static class V {} + public static class W {} + static class P {} // package private + + U u0=new U(), u1[]={u0}, u2[][]={u1}, u3[][][]={u2}, u4[][][][]={u3}; + V v0=new V(), v1[]={v0}, v2[][]={v1}, v3[][][]={v2}, v4[][][][]={v3}; + W w0=new W(), w1[]={w0}, w2[][]={w1}, w3[][][]={w2}, w4[][][][]={w3}; + P p0=new P(), p1[]={p0}, p2[][]={p1}, p3[][][]={p2}, p4[][][][]={p3}; + + accipp001a a0, a1[]={}, a2[][]={}, a3[][][]={}, a4[][][][]={}; + + accipp001e e0=new accipp001e() , e1[]={e0}, e2[][]={e1}, e3[][][]={e2}, e4[][][][]={e3}; + + public static void main (String args[]) { + accipp001a a = new accipp001a(); + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) + System.exit(95); + System.err.println("# Debugee: unknown instruction: " + instruction); + System.exit(97); + } +} + +/** Sample package-private class. */ +class accipp001e {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002.java new file mode 100644 index 00000000000..e24055f5b55 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isPackagePrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class accipp002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Accessible.isPackagePrivate."; + private final static String className = "accipp002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2", "f3", "f4"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + if (checkedClass.isPackagePrivate()) { + display("Accessible.isPackagePrivate() returned true for " + className); + } else { + complain("Accessible.isPackagePrivate() returned false for " + className); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002/TestDescription.java new file mode 100644 index 00000000000..03da587e75d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isPackagePrivate/accipp002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isPackagePrivate() method of ReferenceType interface. + * The test checks if the method returns true any mirrored + * enum type which has no public, private or protected modifier. + * The test consists of a debugger program (accipp002.java) + * and debuggee application (accipp002a.java). + * Package name is nsk.jdi.Accessible.isPackagePrivate . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isPackagePrivate() method for each field + * of enum type declared in accipp002a class. + * The test fails if false is returned once or more times. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isPackagePrivate.accipp002 + * nsk.jdi.Accessible.isPackagePrivate.accipp002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isPackagePrivate.accipp002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002a.java new file mode 100644 index 00000000000..5485a4d7d17 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp002a.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isPackagePrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class accipp002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum1.Enum1_ f2 = Enum1.Enum1_.e1; + static accipp002Enum2 f3 = accipp002Enum2.e2; + static accipp002Enum2.Enum2_ f4 = accipp002Enum2.Enum2_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(accipp002.SIGNAL_READY); + receiveSignal(accipp002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + enum Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum accipp002Enum2 { + e1, e2; + + enum Enum2_ { + e1, e2; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001.java new file mode 100644 index 00000000000..9e4ba59010e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.isPrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method isPrivate() + * of the JDI interface Accessible of com.sun.jdi package + * for ArrayType, ClassType, InterfaceType + */ + +public class isPrivate001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.Accessible.isPrivate.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "isPrivate001", + debugeeName = thisClassName + "a"; + + + static ArgumentHandler argsHandler; + private static Log logHandler; + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + {"boolean", "public", "primitive_type"}, + {"byte" , "public", "primitive_type"}, + {"char" , "public", "primitive_type"}, + {"double" , "public", "primitive_type"}, + {"float" , "public", "primitive_type"}, + {"int" , "public", "primitive_type"}, + {"long" , "public", "primitive_type"}, + + {"java.lang.Boolean" , "public", "reference_type"}, + {"java.lang.Byte" , "public", "reference_type"}, + {"java.lang.Character", "public", "reference_type"}, + {"java.lang.Double" , "public", "reference_type"}, + {"java.lang.Float" , "public", "reference_type"}, + {"java.lang.Integer" , "public", "reference_type"}, + {"java.lang.Long" , "public", "reference_type"}, + {"java.lang.String" , "public", "reference_type"}, + {"java.lang.Object" , "public", "reference_type"}, + + {thisClassName, "public", "reference_type" }, + {thisClassName+"a", "public", "reference_type" }, + {package_prefix + "pack_priv_cls", "package private", "reference_type"}, // class + {package_prefix + "pack_priv_interf", "package private", "reference_type"}, // interface + + {debugeeName+"$s_interf", "private", "reference_type"}, // static interface + + {debugeeName+"$U", "private", "reference_type" }, + {debugeeName+"$V", "protected", "reference_type" }, + {debugeeName+"$W", "public", "reference_type" }, + {debugeeName+"$P", "package private", "reference_type"} + }; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new isPrivate001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.display("\n==> nsk/jdi/Accessible/isPrivate/isPrivate001 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/Accessible/isPrivate/isPrivate001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + if ( out_stream == null ) { + out_stream = out; + } + + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + IOPipe pipe = new IOPipe(debugee); + + logHandler.display("==> nsk/jdi/Accessible/isPrivate/isPrivate001 test LOG:"); + logHandler.display("==> test checks the isPrivate() method of Accessible interface"); + logHandler.display(" of the com.sun.jdi package for ArrayType, ClassType, InterfaceType\n"); + + debugee.redirectStderr(out); + print_log_on_verbose("--> isPrivate001: isPrivate001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + logHandler.complain("##> isPrivate001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + logHandler.display("##> isPrivate001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isPrivate001: debugee's \"ready\" signal recieved!"); + } + + logHandler.display + ("--> isPrivate001: checking debugee's classes by Accessible.isPrivate() method..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int isPrivate_method_errors = 0; + + + for (int i=0; i isPrivate001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + boolean isPrivate = classes_for_check[i][1].equals("private"); + if (refType.isPrivate() != isPrivate) { + logHandler.complain("##> isPrivate001: UNEXPECTED isPrivate() method result (" + + !isPrivate + ") for class: " + + className + "(" + classes_for_check[i][1] + ")"); + isPrivate_method_errors++; + } + else { + print_log_on_verbose("--> isPrivate001: expected isPrivate() method result (" + + isPrivate + ") for class: " + + className + "(" + classes_for_check[i][1] + ")"); + } + } + } + logHandler.display("--> isPrivate001: checking debugee's classes completed!"); + logHandler.display("--> isPrivate001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + logHandler.complain("##> isPrivate001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + if ( isPrivate_method_errors > 0 ) { + logHandler.complain("##> isPrivate001: isPrivate() method ERRORS counter = " + + isPrivate_method_errors); + } + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + isPrivate_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isPrivate001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + logHandler.complain("##> isPrivate001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isPrivate001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001/TestDescription.java new file mode 100644 index 00000000000..d480ebfb416 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isPrivate/isPrivate001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/Accessible/isPrivate/isPrivate001 test + * checks the isPrivate() method of Accessible interface + * of the com.sun.jdi package for ArrayType, ClassType, InterfaceType. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * --------- + * The test is updated to use new share classes as follows: + * - two lines, 33 and 34, with argsHandler and logHandler are added + * - statements with definitions, lines 110-123, are added; + * obsolete statements are removed; + * - all calls to "println" are replaced with calls to + * "logHandler.complain" or "logHandler.display".. + * - all "display" are replaced with "logHandler.display" + * -------- + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isPrivate.isPrivate001 + * nsk.jdi.Accessible.isPrivate.isPrivate001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isPrivate.isPrivate001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java new file mode 100644 index 00000000000..294937f7d58 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.isPrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isPrivate001 JDI test. + */ + +public class isPrivate001a { + + static boolean verbose_mode = false; + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + private static class U {} + protected static class V {} + public static class W {} + static class P {} // package private + + U u0=new U(), u1[]={u0}, u2[][]={u1}; + V v0=new V(), v1[]={v0}, v2[][]={v1}; + W w0=new W(), w1[]={w0}, w2[][]={w1}; + P p0=new P(), p1[]={p0}, p2[][]={p1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + private static interface s_interf {} + private static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl(); + s_interf s_interf_0, s_interf_1[]={s_interf_0}, s_interf_2[][]={s_interf_1}; + + isPrivate001 a001_0 = new isPrivate001(), a001_1[]={a001_0}, + a001_2[][]={a001_1}; + + // Class isPrivate001a is initialized in method main() + isPrivate001a a0, a1[]={a0}, a2[][]={a1}; + pack_priv_cls ppc0=new pack_priv_cls(), ppc1[]={ppc0}, ppc2[][]={ppc1}; + pack_priv_interf_impl ppii0 = new pack_priv_interf_impl(); + pack_priv_interf ppi0, ppi1[]={ppi0}, ppi2[][]={ppi1}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i isPrivate001a: debugee started!"); + isPrivate001a isPrivate001a_obj = new isPrivate001a(); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + print_log_on_verbose("**> isPrivate001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isPrivate001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isPrivate001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isPrivate001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isPrivate001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** Sample package-private class. */ +class pack_priv_cls {} + +/** Sample package-private interface. */ +interface pack_priv_interf {} + +/** Class that implements package-private interface */ +class pack_priv_interf_impl implements pack_priv_interf {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002.java new file mode 100644 index 00000000000..87ca6dedb27 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isPrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isprivate002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Accessible.isPrivate."; + private final static String className = "isprivate002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + if (checkedClass.isPrivate()) { + display("Accessible.isPrivate() returned true for " + className); + } else { + complain("Accessible.isPrivate() returned false for " + className); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002/TestDescription.java new file mode 100644 index 00000000000..36018424375 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isPrivate/isprivate002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isPrivate() method of ReferenceType interface. + * The test checks if the method returns true any mirrored + * enum type which has private modifier. + * The test consists of a debugger program (isprivate002.java) + * and debuggee application (isprivate002a.java). + * Package name is nsk.jdi.Accessible.isPrivate . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isPrivate() method for each field + * of enum type declared in isprivate002a class. + * The test fails if false is returned once or more times. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isPrivate.isprivate002 + * nsk.jdi.Accessible.isPrivate.isprivate002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isPrivate.isprivate002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002a.java new file mode 100644 index 00000000000..87ed43c82cd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isprivate002a.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isPrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isprivate002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum1.Enum1_ f2 = Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isprivate002.SIGNAL_READY); + receiveSignal(isprivate002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + private enum Enum1 { + e1, e2; + + private enum Enum1_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001.java new file mode 100644 index 00000000000..12e81ca0577 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.isProtected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method isProtected() + * of the JDI interface Accessible of com.sun.jdi package + * for ArrayType, ClassType, InterfaceType + */ + +public class isProtected001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.Accessible.isProtected.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "isProtected001", + debugeeName = thisClassName + "a"; + + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + {"boolean", "public", "primitive_type"}, + {"byte" , "public", "primitive_type"}, + {"char" , "public", "primitive_type"}, + {"double" , "public", "primitive_type"}, + {"float" , "public", "primitive_type"}, + {"int" , "public", "primitive_type"}, + {"long" , "public", "primitive_type"}, + + {"java.lang.Boolean" , "public", "reference_type"}, + {"java.lang.Byte" , "public", "reference_type"}, + {"java.lang.Character", "public", "reference_type"}, + {"java.lang.Double" , "public", "reference_type"}, + {"java.lang.Float" , "public", "reference_type"}, + {"java.lang.Integer" , "public", "reference_type"}, + {"java.lang.Long" , "public", "reference_type"}, + {"java.lang.String" , "public", "reference_type"}, + {"java.lang.Object" , "public", "reference_type"}, + + {thisClassName, "public", "reference_type" }, + {thisClassName+"a", "public", "reference_type" }, + {package_prefix + "pack_priv_cls", "package private", "reference_type"}, // class + {package_prefix + "pack_priv_interf", "package private", "reference_type"}, // interface + + {debugeeName+"$s_interf", "protected", "reference_type"}, // static interface + + {debugeeName+"$U", "private", "reference_type" }, + {debugeeName+"$V", "protected", "reference_type" }, + {debugeeName+"$W", "public", "reference_type" }, + {debugeeName+"$P", "package private", "reference_type"} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new isProtected001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/Accessible/isProtected/isProtected001 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/Accessible/isProtected/isProtected001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + if ( out_stream == null ) { + out_stream = out; + } + + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + IOPipe pipe = new IOPipe(debugee); + + + logHandler.display("==> nsk/jdi/Accessible/isProtected/isProtected001 test LOG:"); + logHandler.display("==> test checks the isProtected() method of Accessible interface"); + logHandler.display(" of the com.sun.jdi package for ArrayType, ClassType, InterfaceType\n"); + + + debugee.redirectStderr(out); + print_log_on_verbose("--> isProtected001: isProtected001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + logHandler.complain("##> isProtected001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + logHandler.complain + ("##> isProtected001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isProtected001: debugee's \"ready\" signal recieved!"); + } + + logHandler.display + ("--> isProtected001: checking debugee's classes by Accessible.isProtected() method..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int isProtected_method_errors = 0; + for (int i=0; i isProtected001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + boolean isProtected = classes_for_check[i][1].equals("protected"); + if (refType.isProtected() != isProtected) { + logHandler.complain("##> isProtected001: UNEXPECTED isProtected() method result (" + + !isProtected + ") for class: " + + className + "(" + classes_for_check[i][1] + ")"); + isProtected_method_errors++; + } + else { + print_log_on_verbose("--> isProtected001: expected isProtected() method result (" + + isProtected + ") for class: " + + className + "(" + classes_for_check[i][1] + ")"); + } + } + } + logHandler.display("--> isProtected001: checking debugee's classes completed!"); + logHandler.display("--> isProtected001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + logHandler.complain("##> isProtected001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + if ( isProtected_method_errors > 0 ) { + logHandler.complain("##> isProtected001: isProtected() method ERRORS counter = " + + isProtected_method_errors); + } + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + isProtected_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isProtected001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + logHandler.complain + ("##> isProtected001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> isProtected001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001/TestDescription.java new file mode 100644 index 00000000000..48f5d730d3f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isProtected/isProtected001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/Accessible/isProtected/isProtected001 test + * checks the isProtected() method of Accessible interface + * of the com.sun.jdi package for ArrayType, ClassType, InterfaceType. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * --------- + * The test is updated to use new share classes as follows: + * - two lines, 33 and 34, with argsHandler and logHandler are added befo + * - statements with definitions, lines 112-123, are added; + * - all calls to "println" are replaced with calls to + * "logHandler.complain" or "logHandler.display".. + * - all "display" are replaced with "logHandler.display" + * -------- + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isProtected.isProtected001 + * nsk.jdi.Accessible.isProtected.isProtected001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isProtected.isProtected001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java new file mode 100644 index 00000000000..9d66c7c6f76 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.isProtected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isProtected001 JDI test. + */ + +public class isProtected001a { + + static boolean verbose_mode = false; + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + private static class U {} + protected static class V {} + public static class W {} + static class P {} // package private + + U u0=new U(), u1[]={u0}, u2[][]={u1}; + V v0=new V(), v1[]={v0}, v2[][]={v1}; + W w0=new W(), w1[]={w0}, w2[][]={w1}; + P p0=new P(), p1[]={p0}, p2[][]={p1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + protected static interface s_interf {} + protected static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl(); + s_interf s_interf_0, s_interf_1[]={s_interf_0}, s_interf_2[][]={s_interf_1}; + + isProtected001 a001_0=new isProtected001(), a001_1[]={a001_0}, + a001_2[][]={a001_1}; + + // Class isPrivate001a is initialized in method main() + isProtected001a a0, a1[]={a0}, a2[][]={a1}; + pack_priv_cls ppc0=new pack_priv_cls(), ppc1[]={ppc0}, ppc2[][]={ppc1}; + pack_priv_interf_impl ppii0 = new pack_priv_interf_impl(); + pack_priv_interf ppi0, ppi1[]={ppi0}, ppi2[][]={ppi1}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i isProtected001a: debugee started!"); + isProtected001a isProtected001a_obj = new isProtected001a(); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + print_log_on_verbose("**> isProtected001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isProtected001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isProtected001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isProtected001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isProtected001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** Sample package-private class. */ +class pack_priv_cls {} + +/** Sample package-private interface. */ +interface pack_priv_interf {} + +/** Class that implements package-private interface */ +class pack_priv_interf_impl implements pack_priv_interf {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002.java new file mode 100644 index 00000000000..1f1cd5944fa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isProtected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isprotected002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Accessible.isProtected."; + private final static String className = "isprotected002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2", "f4"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + if (checkedClass.isProtected()) { + display("Accessible.isProtected() returned true for " + className); + } else { + complain("Accessible.isProtected() returned false for " + className); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002/TestDescription.java new file mode 100644 index 00000000000..23a2dc24e6f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isProtected/isprotected002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isProtected() method of ReferenceType interface. + * The test checks if the method returns true any mirrored + * enum type which has protected modifier. + * The test consists of a debugger program (isprotected002.java) + * and debuggee application (isprotected002a.java). + * Package name is nsk.jdi.Accessible.isProtected . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isProtected() method for each field + * of enum type declared in isprotected002a class. + * The test fails if false is returned once or more times. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isProtected.isprotected002 + * nsk.jdi.Accessible.isProtected.isprotected002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isProtected.isprotected002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002a.java new file mode 100644 index 00000000000..3a7ff10102f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isprotected002a.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isProtected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isprotected002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum1.Enum1_ f2 = Enum1.Enum1_.e1; + static isprotected002Enum2.Enum2_ f4 = isprotected002Enum2.Enum2_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isprotected002.SIGNAL_READY); + receiveSignal(isprotected002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + protected enum Enum1 { + e1, e2; + + protected enum Enum1_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum isprotected002Enum2 { + e1, e2; + + protected enum Enum2_ { + e1, e2; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001.java new file mode 100644 index 00000000000..d4d51966cbb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method isPublic() + * of the JDI interface Accessible of com.sun.jdi package + * for ArrayType, ClassType, InterfaceType + */ + +public class isPublic001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.Accessible.isPublic.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "isPublic001", + debugeeName = thisClassName + "a"; + + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + {"boolean", "public", "primitive_type"}, + {"byte" , "public", "primitive_type"}, + {"char" , "public", "primitive_type"}, + {"double" , "public", "primitive_type"}, + {"float" , "public", "primitive_type"}, + {"int" , "public", "primitive_type"}, + {"long" , "public", "primitive_type"}, + + {"java.lang.Boolean" , "public", "reference_type"}, + {"java.lang.Byte" , "public", "reference_type"}, + {"java.lang.Character", "public", "reference_type"}, + {"java.lang.Double" , "public", "reference_type"}, + {"java.lang.Float" , "public", "reference_type"}, + {"java.lang.Integer" , "public", "reference_type"}, + {"java.lang.Long" , "public", "reference_type"}, + {"java.lang.String" , "public", "reference_type"}, + {"java.lang.Object" , "public", "reference_type"}, + + {thisClassName, "public", "reference_type" }, + {thisClassName+"a", "public", "reference_type" }, + {package_prefix + "pack_priv_cls", "package private", "reference_type"}, // class + {package_prefix + "pack_priv_interf", "package private", "reference_type"}, // interface + + {debugeeName+"$s_interf", "public", "reference_type"}, // interface + + {debugeeName+"$U", "private", "reference_type" }, + {debugeeName+"$V", "protected", "reference_type" }, + {debugeeName+"$W", "public", "reference_type" }, + {debugeeName+"$P", "package private", "reference_type"} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new isPublic001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/Accessible/isPublic/isPublic001 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/Accessible/isPublic/isPublic001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + IOPipe pipe = new IOPipe(debugee); + + logHandler.display("==> nsk/jdi/Accessible/isPublic/isPublic001 test LOG:"); + logHandler.display("==> test checks the isPublic() method of Accessible interface"); + logHandler.display(" of the com.sun.jdi package for ArrayType, ClassType, InterfaceType\n"); + + + debugee.redirectStderr(out); + print_log_on_verbose("--> isPublic001: isPublic001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + logHandler.complain + ("##> isPublic001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + logHandler.complain + ("##> isPublic001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isPublic001: debugee's \"ready\" signal recieved!"); + } + + logHandler.display + ("--> isPublic001: checking debugee's classes by Accessible.isPublic() method..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int isPublic_method_errors = 0; + for (int i=0; i isPublic001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + boolean isPublic = classes_for_check[i][1].equals("public"); + if (refType.isPublic() != isPublic) { + logHandler.complain + ("##> isPublic001: UNEXPECTED isPublic() method result (" + !isPublic + + ") for class: " + className + "(" + classes_for_check[i][1] + ")"); + isPublic_method_errors++; + } + else { + print_log_on_verbose + ("--> isPublic001: expected isPublic() method result (" + isPublic + + ") for class: " + className + "(" + classes_for_check[i][1] + ")"); + } + } + } + logHandler.display("--> isPublic001: checking debugee's classes completed!"); + logHandler.display("--> isPublic001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + logHandler.complain("##> isPublic001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + if ( isPublic_method_errors > 0 ) { + logHandler.complain("##> isPublic001: isPublic() method ERRORS counter = " + + isPublic_method_errors); + } + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + isPublic_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isPublic001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + logHandler.complain + ("##> isPublic001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> isPublic001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001/TestDescription.java new file mode 100644 index 00000000000..2b016ac3706 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isPublic/isPublic001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/Accessible/isPublic/isPublic001 test + * checks the isPublic() method of Accessible interface + * of the com.sun.jdi package for ArrayType, ClassType, InterfaceType. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * --------- + * The test is updated to use new share classes as follows: + * - two lines, 33 and 34, with argsHandler and logHandler are added + * - statements with definitions, lines 110-123, are added; + * - all calls to "println" are replaced with calls to + * "logHandler.complain" or "logHandler.display".. + * - all "display" are replaced with "logHandler.display" + * -------- + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isPublic.isPublic001 + * nsk.jdi.Accessible.isPublic.isPublic001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isPublic.isPublic001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java new file mode 100644 index 00000000000..916795c29e8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isPublic001 JDI test. + */ + +public class isPublic001a { + + static boolean verbose_mode = false; + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + private static class U {} + protected static class V {} + public static class W {} + static class P {} // package private + + U u0=new U(), u1[]={u0}, u2[][]={u1}; + V v0=new V(), v1[]={v0}, v2[][]={v1}; + W w0=new W(), w1[]={w0}, w2[][]={w1}; + P p0=new P(), p1[]={p0}, p2[][]={p1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + public static interface s_interf {} + protected static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl(); + s_interf s_interf_0, s_interf_1[]={s_interf_0}, s_interf_2[][]={s_interf_1}; + + isPublic001 a001_0=new isPublic001(), a001_1[]={a001_0}, a001_2[][]={a001_1}; + + // Class isPrivate001a is initialized in method main() + isPublic001a a0, a1[]={a0}, a2[][]={a1}; + pack_priv_cls ppc0=new pack_priv_cls(), ppc1[]={ppc0}, ppc2[][]={ppc1}; + pack_priv_interf_impl ppii0 = new pack_priv_interf_impl(); + pack_priv_interf ppi0, ppi1[]={ppi0}, ppi2[][]={ppi1}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i isPublic001a: debugee started!"); + isPublic001a isPublic001a_obj = new isPublic001a(); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + print_log_on_verbose("**> isPublic001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isPublic001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isPublic001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isPublic001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isPublic001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** Sample package-private class. */ +class pack_priv_cls {} + +/** Sample package-private interface. */ +interface pack_priv_interf {} + +/** Class that implements package-private interface */ +class pack_priv_interf_impl implements pack_priv_interf {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002.java new file mode 100644 index 00000000000..9495f939a2d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class ispublic002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Accessible.isPublic."; + private final static String className = "ispublic002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] expectedFieldNames = {"f1", "f2", "f3"}; + private final static String[] expectedEnumFieldsNames = { "e1", "e2" }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + Field foundField = checkedClass.fieldByName(expectedEnumFieldsNames[i]); + if (foundField != null) { + if (foundField.isPublic()) { + display("enum " + className + " has public field " + expectedEnumFieldsNames[i]); + display("\t of type " + className); + } else { + complain("enum " + className + " has not-public field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } else { + complain("enum " + className + " does not have field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002/TestDescription.java new file mode 100644 index 00000000000..de1afa5e086 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isPublic/ispublic002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isPublic() method of TypeComponent interface. + * The test checks if the method returns true for each enum + * constant declared in mirrored enum type. All enum constants + * are implicitly public according to enum spec. + * The test consists of a debugger program (ispublic002.java) + * and debuggee application (ispublic002a.java). + * Package name is nsk.jdi.Accessible.isPublic . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger checks result of isPublic() method for each field + * of enum type declared in ispublic002a class. Every of these + * enum types has the same enum constants, i.e fields: e1 and e2. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isPublic.ispublic002 + * nsk.jdi.Accessible.isPublic.ispublic002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isPublic.ispublic002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002a.java new file mode 100644 index 00000000000..3eccc381c0c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic002a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class ispublic002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static ispublic002Enum1 f1 = ispublic002Enum1.e2; + static ispublic002Enum2 f2 = ispublic002Enum2.e1; + static ispublic002Enum1.Enum1_ f3 = ispublic002Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(ispublic002.SIGNAL_READY); + + + //pipe.println(ispublic002.SIGNAL_GO); + receiveSignal(ispublic002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum ispublic002Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum ispublic002Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003.java new file mode 100644 index 00000000000..c1adf733fb3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class ispublic003 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Accessible.isPublic."; + private final static String className = "ispublic003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2", "f4"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + if (checkedClass.isPublic()) { + display("Accessible.isPublic() returned true for " + className); + } else { + complain("Accessible.isPublic() returned false for " + className); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003/TestDescription.java new file mode 100644 index 00000000000..73c327c151e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/isPublic/ispublic003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isPublic() method of ReferenceType interface. + * The test checks if the method returns true any mirrored + * enum type which has public modifier. + * The test consists of a debugger program (ispublic003.java) + * and debuggee application (ispublic003a.java). + * Package name is nsk.jdi.Accessible.isPublic . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isPublic() method for each field + * of enum type declared in ispublic003a class. + * The test fails if false is returned once or more times. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.isPublic.ispublic003 + * nsk.jdi.Accessible.isPublic.ispublic003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.isPublic.ispublic003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003a.java new file mode 100644 index 00000000000..0e67ef54d5e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/ispublic003a.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class ispublic003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum1.Enum1_ f2 = Enum1.Enum1_.e1; + static ispublic003Enum2 f3 = ispublic003Enum2.e2; + static ispublic003Enum2.Enum2_ f4 = ispublic003Enum2.Enum2_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(ispublic003.SIGNAL_READY); + receiveSignal(ispublic003.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + public enum Enum1 { + e1, e2; + + public enum Enum1_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum ispublic003Enum2 { + e1, e2; + + public enum Enum2_ { + e1, e2; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001.java new file mode 100644 index 00000000000..63840b2f428 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.modifiers; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The modifiers001 test checks the method modifiers() + * of the JDI interface Accessible of com.sun.jdi package + * for ClassType, InterfaceType + */ + +public class modifiers001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.Accessible.modifiers.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "modifiers001", + debugeeName = thisClassName + "a"; + + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + + {"java.lang.Boolean" , "public, final", "class"}, + {"java.lang.Byte" , "public, final", "class"}, + {"java.lang.Character", "public, final", "class"}, + {"java.lang.Double" , "public, final", "class"}, + {"java.lang.Float" , "public, final", "class"}, + {"java.lang.Integer" , "public, final", "class"}, + {"java.lang.Long" , "public, final", "class"}, + {"java.lang.String" , "public, final", "class"}, + {"java.lang.Object" , "public ", "class"}, + + {thisClassName, "public", "class"}, + {thisClassName+"a", "public", "class"}, + + {debugeeName+"$fin_s_cls", "final, static", "class"}, + {debugeeName+"$abs_s_cls", "abstract, static", "class"}, + {debugeeName+"$s_interf", "abstract, static, interface", "interface"}, + + {package_prefix + "simple_class", "", "class"}, + {package_prefix + "abstract_class", "abstract", "class"}, + {package_prefix + "final_class", "final", "class"}, + {package_prefix + "interf", "abstract, interface", "interface"} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new modifiers001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/Accessible/modifiers/modifiers001 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/Accessible/modifiers/modifiers001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + IOPipe pipe = new IOPipe(debugee); + + + logHandler.display("==> nsk/jdi/Accessible/modifiers/modifiers001 test LOG:"); + logHandler.display("==> test checks the modifiers() method of Accessible interface"); + logHandler.display(" of the com.sun.jdi package for ClassType, InterfaceType\n"); + + + debugee.redirectStderr(out); + print_log_on_verbose("--> modifiers001: modifiers001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + logHandler.complain + ("##> modifiers001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + logHandler.complain + ("##> modifiers001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> modifiers001: debugee's \"ready\" signal recieved!"); + } + + logHandler.display + ("--> modifiers001: checking debugee's classes by Accessible.modifiers() method...\n"); + int all_classes_count = 0; + int class_not_found_errors = 0; + int class_not_found_exceptions = 0; + int modifiers_method_errors = 0; +// modifiers001a obj = new modifiers001a(); + for (int i=0; i isPublic001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + Class class_obj; + try { + class_obj = Class.forName(className); + } + catch (ClassNotFoundException e) { + logHandler.complain + ("##> modifiers001: Class.forName("+className+") - "+e.toString()); + class_not_found_exceptions++; + continue; + } + int expected_modifiers = class_obj.getModifiers(); + String s_type = classes_for_check[i][2]; + String s_modifiers = classes_for_check[i][1]; + int got_modifiers = refType.modifiers(); + // Class.getModifiers() will never return ACC_SUPER + // but Accessible.modifers() can, so ignore this bit + got_modifiers &= ~0x20; // 0x20 == ACC_SUPER + logHandler.display(""); + if ( got_modifiers != expected_modifiers ) { + logHandler.complain("##> modifiers001: UNEXPECTED modifiers() method result (" + + "0x" + Integer.toHexString(got_modifiers) + ") for " + s_type + ": " + className + + "(" + s_modifiers + ")"); + logHandler.complain("##> expected modifiers() method result = " + + "0x" + Integer.toHexString(expected_modifiers)); + modifiers_method_errors++; + } + else { + print_log_on_verbose("--> modifiers001: expected modifiers() method result (" + + "0x" + Integer.toHexString(got_modifiers) + ") for " + s_type + ": " + className + + "(" + s_modifiers + ")"); + } + } + logHandler.display + ("--> modifiers001: checking debugee's classes completed!"); + logHandler.display + ("--> modifiers001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + logHandler.complain("##> modifiers001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + if ( class_not_found_exceptions > 0 ) { + logHandler.complain("##> modifiers001: \"class not found EXCEPTIONS\" counter = " + + class_not_found_exceptions); + } + logHandler.display("##> modifiers001: modifiers() method ERRORS counter = " + + modifiers_method_errors); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + class_not_found_exceptions + modifiers_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> modifiers001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + logHandler.complain + ("##> modifiers001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> modifiers001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001/TestDescription.java new file mode 100644 index 00000000000..15b8e981051 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/modifiers/modifiers001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/Accessible/modifiers/modifiers001 test + * checks the modifiers() method of Accessible interface + * of the com.sun.jdi package for ClassType, InterfaceType. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * --------- + * The test is updated to use new share classes as follows: + * - two lines, 33 and 34, with argsHandler and logHandler are added befo + * - statements with definitions, lines 102-115, are added; + * - all calls to "println" are replaced with calls to + * "logHandler.complain" or "logHandler.display".. + * - all "display" are replaced with "logHandler.display" + * - one non-used statement, line 148, is commented away. + * -------- + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.modifiers.modifiers001 + * nsk.jdi.Accessible.modifiers.modifiers001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.modifiers.modifiers001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java new file mode 100644 index 00000000000..f9583200353 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Accessible.modifiers; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the modifiers001 JDI test. + */ + +public class modifiers001a { + + static boolean verbose_mode = false; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(false); + Byte B0 = new Byte((byte)1); + Character C0 = new Character('c'); + Double D0 = new Double(1); + Float F0 = new Float(1); + Integer I0 = new Integer(1); + Long L0 = new Long(1); + String S0 = new String("s"); + Object O0 = new Object(); + + modifiers001 m001_0=new modifiers001(); + modifiers001a m001a_0, m001a_1[] = {m001a_0}; + + final static class fin_s_cls {} + abstract static class abs_s_cls {} + static class abs_s_cls_ext extends abs_s_cls {} + static interface s_interf {} + static class s_interf_impl implements s_interf {} + + // Interfaces and abstract classes must be loaded and linked, so classes + // that implement interfaces and extend abstract classes must be + // initialized + fin_s_cls fin_s_cls_0 = new fin_s_cls(); + abs_s_cls_ext abs_s_cls_ext_0 = new abs_s_cls_ext(); + abs_s_cls abs_s_cls_0, abs_s_cls_1[] = {abs_s_cls_0}; + s_interf_impl s_interf_impl_0 = new s_interf_impl(); + s_interf s_interf_0, s_interf_1[] = {s_interf_0}; + + simple_class m_simpleclass_0 = new simple_class(); + abstract_class_ext m_absclass_ext_0 = new abstract_class_ext(); + abstract_class m_absclass_0, m_absclass_1[] = {m_absclass_0}; + final_class m_finclass_0 = new final_class(); + interf_impl m_interf_impl_0 = new interf_impl(); + interf m_interf_0, m_interf_1[] = {m_interf_0}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i modifiers001a: debugee started!"); + modifiers001a obj = new modifiers001a(); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + print_log_on_verbose("**> modifiers001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> modifiers001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> modifiers001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> modifiers001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> modifiers001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** simple class */ +class simple_class {} + +/** abstract class */ +abstract class abstract_class {} + +/** Class that extends abstract class */ +class abstract_class_ext extends abstract_class {} + +/** final class */ +final class final_class {} + +/** simple interface */ +interface interf {} + +/** Class that implements interface */ +class interf_impl implements interf {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002.java new file mode 100644 index 00000000000..137841869c8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.modifiers; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class modifiers002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Accessible.modifiers."; + private final static String className = "modifiers002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2", "f3"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + int modifiers = checkedClass.modifiers(); + if (fieldName.equals("f1") || fieldName.equals("f2")) { + if ((0x0010 & modifiers) == 0x0010 /* ACC_FINAL */) { + display("Accessible.modifiers() returned expected ACC_FINAL flag for type: " + className); + } else { + complain("Accessible.modifiers() did not return ACC_FINAL flag for type: " + className); + exitStatus = Consts.TEST_FAILED; + } + } + + if ((0x0020 & modifiers) == 0x0020 /* ACC_SUPER */) { + display("Accessible.modifiers() returned expected ACC_SUPER flag for type: " + className); + } else { + complain("Accessible.modifiers() did not return ACC_SUPER flag for type: " + className); + exitStatus = Consts.TEST_FAILED; + } + + if (fieldName.equals("f2")) { + if ((0x0001 & modifiers) == 0x0001 /* ACC_PUBLIC */) { + display("Accessible.modifiers() returned expected ACC_PUBLIC flag for type: " + className); + } else { + complain("Accessible.modifiers() did not return ACC_PUBLIC flag for type: " + className); + exitStatus = Consts.TEST_FAILED; + } + } + + if (fieldName.equals("f3")) { + if ((0x0400 & modifiers) == 0x0400 /* ACC_ABSTRACT */) { + display("Accessible.modifiers() returned expected ACC_ABSTRACT flag for type: " + className); + } else { + complain("Accessible.modifiers() did not return ACC_ABSTRACT flag for type: " + className); + exitStatus = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002/TestDescription.java new file mode 100644 index 00000000000..3aa294f2c26 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Accessible/modifiers/modifiers002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isEnum() method of Accessible interface. + * The test checks if the method returns int status combined + * as from following flags for any mirrored enum type: + * - ACC_FINAL (0x0010) for any enum type because each enum types + * is final, + * - ACC_SUPER (0x0020 for any enum type due to + * JVMS 4.1 The ClassFile Structure + * - ACC_PUBLIC (0x0001) if public modifier is declared, + * - ACC_ABSTRACT (0x0400) if abstract modifier is declared. + * The test consists of a debugger program (modifiers002.java) + * and debuggee application (modifiers002a.java). + * Package name is nsk.jdi.Accessible.modifiers . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls modifiers() method for each field + * of enum type declared in modifiers002a class. + * The result is bitwise compared with expected flags. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Accessible.modifiers.modifiers002 + * nsk.jdi.Accessible.modifiers.modifiers002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Accessible.modifiers.modifiers002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002a.java new file mode 100644 index 00000000000..338b8dd7c99 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers002a.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Accessible.modifiers; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class modifiers002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum2 f2 = Enum2.e2; + static Enum3 f3 = Enum3.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(modifiers002.SIGNAL_READY); + receiveSignal(modifiers002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + enum Enum1 { + e1, e2; + } + + public enum Enum2 { + e1, e2; + } + + enum Enum3 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); + } +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/description/description001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/description/description001.java new file mode 100644 index 00000000000..7b4f492cef0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/description/description001.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.description; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.*; +import javax.naming.directory.Attribute; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String description() + * Assertion: "Returns a human-readable description of this + * argument and its purpose." + */ + +public class description001 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + List acl = vmm.allConnectors(); + + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Map cdfltArgmnts = c.defaultArguments(); + Set ks = cdfltArgmnts.keySet(); + + if (ks.isEmpty()) { + log.complain("FAILURE: empty default arguments set is found " + + "for " + c.name() + " connector!"); + return 2; + } + log.display("Looking over " + c.name() + " connector arguments: "); + + Iterator argi = ks.iterator(); + for (int j = 1; argi.hasNext(); j++) { + String argkey = (String) argi.next(); + Connector.Argument argval = + (Connector.Argument)cdfltArgmnts.get((Object) argkey); + String dscrptn = argval.description(); + + if (dscrptn == null) { + log.complain("FAILURE: argument description is null " + + "for " + argkey + " argument of " + c.name() + + " connector!"); + return 2; + } + + if (dscrptn.length() < 1) { + log.complain("FAILURE: empty argument description is found " + + "for " + argkey + " argument of " + c.name() + + " connector!"); + return 2; + } + + log.display(j + "," + argval.name() + ": " + dscrptn); + }; + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/description/description001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/description/description001/TestDescription.java new file mode 100644 index 00000000000..13160956c41 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/description/description001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/description/description001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String description() + * Assertion: "Returns a human-readable description of this + * argument and its purpose." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.description.description001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.description.description001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid001.java new file mode 100644 index 00000000000..78c1b998641 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid001.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; + +/** + * The test for the implementation of an object of the type
    + * Connector.Argument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.Argument.isValid()
    + * complies with its specification, that is,
    + * "Returns: true if the value is valid to be used in setValue(String)"
    + * in case when Argument implements BooleanArgument .
    + *
    + * In case of a wrong boolean value returned,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class isvalid001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.Argument argument = null; + Connector.BooleanArgument booleanArg = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { + argument = (Connector.Argument) + defaultArguments.get(argName); + try { + booleanArg = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (booleanArg != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with BooleanArgument found\n"); + return exitCode0; + } + } + + if (!argument.isValid("true")) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid('true')\n" + + "error: returned value != true\n"); + } + + if (!argument.isValid("false")) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid('false')\n" + + "error: returned value != true\n"); + } + + if (argument.isValid("fals")) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid('fals')\n" + + "error: returned value == true\n"); + } + + if (argument.isValid("")) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid()\n" + + "error: returned value == true\n"); + } + + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid001/TestDescription.java new file mode 100644 index 00000000000..df6ff6f3fad --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/isValid/isvalid001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Argument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.Argument.isValid() + * complies with its specification, that is, + * "Returns: true if the value is valid to be used in setValue(String)" + * in case when Argument implements BooleanArgument . + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.BooleanArgument object is searched among + * Arguments of Connectors. + * If no the object is found out the test exits + * with the return value = 95 and a warning message. + * - To a Connector.Argument argument object + * the following checks are applied: + * IF !argument.isValid("true") + * THEN an error detected + * ELSE the check passed + * IF !argument.isValid("false") + * THEN an error detected + * ELSE the check passed + * IF argument.isValid("fals") + * THEN an error detected + * ELSE the check passed + * IF argument.isValid("") + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.isValid.isvalid001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.isValid.isvalid001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid002.java new file mode 100644 index 00000000000..9b751b240f4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid002.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; + +/** + * The test for the implementation of an object of the type
    + * Connector.Argument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.Argument.isValid()
    + * complies with its specification.
    + * The case for testing includes throwing NullPointerException
    + * if a parameter is a null-string.
    + *
    + */ + + +public class isvalid002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.Argument argument = null; + Connector.BooleanArgument booleanArg = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { + argument = (Connector.Argument) + defaultArguments.get(argName); + try { + booleanArg = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (booleanArg != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with BooleanArgument found\n"); + return exitCode0; + } + } + + String sNull = null; + try { + argument.isValid(sNull); + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(sNull)\n" + + "ERROR: no NullPointerException thrown"); + } catch ( NullPointerException e ) { + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid002/TestDescription.java new file mode 100644 index 00000000000..dc4a629ff74 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/isValid/isvalid002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Argument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.Argument.isValid() + * complies with its specification, that is, + * "Returns: true if the value is valid to be used in setValue(String)" + * in case when Argument implements BooleanArgument + * and its parameter is a null-string . + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.BooleanArgument object is searched among + * Arguments of Connectors. + * If no the object is found out the test exits + * with the return value = 95 and a warning message. + * - To a Connector.Argument argument object + * the following check is applied: + * String sNull = null; + * IF argument.isValid(sNull) + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * To fix the bug 4491137, + * the test is corrected to comply with + * the updated specification in jdi-overview.html: + * Any method which takes a Object as an parameter + * will throw NullPointerException if + * null is passed directly or indirectly -- + * unless null is explicitly mentioned as a valid parameter. + * From now, the test regards throwing NullPointerException + * as the correct reaction to the null-parameter. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.isValid.isvalid002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.isValid.isvalid002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid003.java new file mode 100644 index 00000000000..5ac66a4bc73 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid003.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; + +/** + * The test for the implementation of an object of the type
    + * Connector.Argument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.Argument.isValid()
    + * complies with its specification, that is,
    + * "Returns: true if the value is valid to be used in setValue(String)"
    + * in case when Argument implements StringArgument
    + * and its parameter is a null-string.
    + *
    + * In case of a wrong boolean value returned,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class isvalid003 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.Argument argument = null; + Connector.StringArgument stringArg = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { + argument = (Connector.Argument) + defaultArguments.get(argName); +// + try { + stringArg = (Connector.StringArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } +// + if (stringArg != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with StringArgument found\n"); + return exitCode0; + } + } + + String sNull = null; + try { + if (!argument.isValid(sNull)) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(sNull)\n" + +// + "error: returned value != true\n"); + } + } catch ( NullPointerException e ) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(sNull)\n" + + "error: NullPointerException\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid003/TestDescription.java new file mode 100644 index 00000000000..07730666b65 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid003/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/isValid/isvalid003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Argument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.Argument.isValid() + * complies with its specification, that is, + * "Returns: true if the value is valid to be used in setValue(String)" + * in case when Argument implements StringArgument + * and its parameter is a null-string . + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.StringArgument object is searched among + * Arguments of Connectors. + * If no the object is found out the test exits + * with the return value = 95 and a warning message. + * - To a Connector.Argument (!!!) argument + * the following check is applied: + * String sNull = null; + * IF !argument.isValid(sNull) + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.isValid.isvalid003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.isValid.isvalid003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid004.java new file mode 100644 index 00000000000..b6c8d79ce8f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid004.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.Argument.isValid()
    + * complies with its specification, that is,
    + * "Returns: true if the value is valid to be used in setValue(String)"
    + * in case when Argument implements IntegerArgument
    + * and its parameter is a string representing one of min(), max(),
    + * min()-1, min()+1, max()+1.
    + *
    + * In case of a wrong result returned,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class isvalid004 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.Argument argument = null; + Connector.IntegerArgument intArgument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.IntegerArgument) + defaultArguments.get(argName); + try { + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + Integer intI = null; + + if (argument.isValid(intArgument.stringValueOf(intArgument.min()))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid(stringValueOf(min()))\n" + + "result: false\n"); + } + + if (argument.isValid(intArgument.stringValueOf(intArgument.max()))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid(stringValueOf(max()))\n" + + "result: false\n"); + } + + if (intArgument.min() < intArgument.max()) { + if (argument.isValid( + intArgument.stringValueOf(intArgument.min() + 1))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid(stringValueOf(min()+1))\n" + + "result: false\n"); + } + } + + if (intArgument.min() > intI.MIN_VALUE) { + if (!argument.isValid( + intArgument.stringValueOf(intArgument.min() - 1))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid(stringValueOf(min()-1))\n" + + "result: true\n"); + } + } + + if (intArgument.max() < intI.MAX_VALUE) { + if (!argument.isValid( + intArgument.stringValueOf(intArgument.max() + 1))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid(stringValueOf(max()+1))\n" + + "result: true\n"); + } + } + + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid004/TestDescription.java new file mode 100644 index 00000000000..369fcd148c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid004/TestDescription.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/isValid/isvalid004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Argument. + * The test checks up that results of the method + * Connector.Argument.isValid() + * complies with its specification, that is, + * "Returns: true if the value is valid to be used in setValue(String)" + * in case when Argument implements IntegerArgument + * and parameters are strings representing values min(), max(), + * min()-1, min()+1 and max()+1. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.Argument which implement Connector.IntegerArgument + * object is searched among Arguments of Connectors. + * If no intArgument is found out + * the test exits with the return value = 95 and a warning message. + * - The follwing checks are made: + * argument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.min())) + * expexted result - true + * if (intArgument.min() < intArgument.max()) + * argument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.min() + 1)) + * expected result - true + * argument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.max()) + * expexted result - true + * if (intArgument.min() > INTEGER.MIN_VALUE) + * argument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.min() - 1) + * expected result - false + * if (intArgument.max() < INTEGER.MAX_VALUE) + * argument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.max() + 1) + * expected result - false + * In case of unexpected result + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.isValid.isvalid004 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.isValid.isvalid004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid005.java new file mode 100644 index 00000000000..1add4e1ca37 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid005.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.Argument.isValid()
    + * complies with its specification, that is,
    + * "Returns: true if the value is valid to be used in setValue(String)"
    + * in case when Argument implements IntegerArgument
    + * and its parameter is one of the following: "a", "", null, null-string.

    + *
    + * In case of a wrong result returned,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class isvalid005 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.Argument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.Argument argument = null; + Connector.IntegerArgument intArgument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.IntegerArgument) + defaultArguments.get(argName); + try { + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + if (!argument.isValid("")) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid('')\n" + + "result: true\n"); + } + + if (!argument.isValid("a")) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid('a')\n" + + "result: true\n"); + } + + if (!argument.isValid((String) null)) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid((String) null))\n" + + "result: true\n"); + } + + String s = null; + if (!argument.isValid(s)) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: super.isValid(String s = null)\n" + + "result: true\n"); + } + + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid005/TestDescription.java new file mode 100644 index 00000000000..3b10d1d5e0a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/isValid/isvalid005/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/isValid/isvalid005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Argument. + * The test checks up that results of the method + * Connector.Argument.isValid() + * complies with its specification, that is, + * "Returns: true if the value is valid to be used in setValue(String)" + * in case when Argument implements IntegerArgument + * and parameters are strings "", "a", null, null-string. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.Argument which implement Connector.IntegerArgument + * object is searched among Arguments of Connectors. + * If no intArgument is found out + * the test exits with the return value = 95 and a warning message. + * - The follwing checks are made: + * !argument.isValid("") + * expexted result - true + * !argument.isValid("a") + * expected result - true + * !argument.isValid((String) null) + * expexted result - true + * String s = null; + * !argument.isValid(s) + * expected result - true + * In case of unexpected result + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.isValid.isvalid005 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.isValid.isvalid005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/label/label001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/label/label001.java new file mode 100644 index 00000000000..8d09663ffcc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/label/label001.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.label; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.*; +import javax.naming.directory.Attribute; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String label() + * Assertion: "Returns a short human-readable label for + * this argument." + */ + +public class label001 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Map cdfltArgmnts = c.defaultArguments(); + Set ks = cdfltArgmnts.keySet(); + + if (ks.isEmpty()) { + log.complain("FAILURE: empty default arguments set is found " + + "for " + c.name() + " connector!"); + return 2; + } + + log.display("Looking over " + c.name() + " connector arguments: "); + + Iterator argi = ks.iterator(); + for (int j = 1; argi.hasNext(); j++) { + String argkey = (String) argi.next(); + Connector.Argument argval = + (Connector.Argument)cdfltArgmnts.get((Object) argkey); + String lbl = argval.label(); + + if (lbl == null) { + log.complain("FAILURE: argument label is null " + + "for " + argkey + " argument of " + + c.name() + " connector!"); + return 2; + } + + if (lbl.length() < 1) { + log.complain("FAILURE: empty argument label is found " + + "for " + argkey + " argument of " + + c.name() + " connector!"); + return 2; + } + + log.display("Next (" + j + ") argument's label is: " + lbl); + }; + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/label/label001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/label/label001/TestDescription.java new file mode 100644 index 00000000000..cb8575d435d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/label/label001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/label/label001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String label() + * Assertion: "Returns a short human-readable label for + * this argument." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.label.label001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.label.label001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001.java new file mode 100644 index 00000000000..dadbad24efb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.mustSpecify; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_Argument.
    + *
    + * The test checks up that the method
    + * com.sun.jdi.connect.Connector.Argument.mustSpecify()
    + * complies with its specification.
    + *
    + * In case of Connector has no Argument needed to be specified,
    + * the test prints warning message.
    + * The test is always passed and produces
    + * the return value 95.
    + */ + +// +public class mustspecify001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.intValue\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.intValue()\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.Argument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.Argument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if ((argument != null) && argument.mustSpecify()) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with Argument must be specified, found\n"); + return exitCode0; + } + } +/* + argument.setValue("0"); + if (argument.mustSpecify()) { + out.println("mustSpecify is the same\n"); + } else { + out.println("mustSpecify is changed\n"); + } + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } +*/ + return exitCode0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001/TestDescription.java new file mode 100644 index 00000000000..fd06ac9bc3c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/mustSpecify/mustspecify001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/mustSpecify/mustspecify001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Argument. + * The test checks whether Connector has Argument + * needed to be specified. + * If no such Argument, the test prints warning message; + * otherwise no message. + * The test is always passed and produces + * the return value 95. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.mustSpecify.mustspecify001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.mustSpecify.mustspecify001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/name/name001.java new file mode 100644 index 00000000000..572d8047f57 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/name/name001.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.*; +import javax.naming.directory.Attribute; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String name() + * Assertion: "Returns a short, unique identifier for the argument." + */ + +public class name001 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[],PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Map cdfltArgmnts = c.defaultArguments(); + int ksz = cdfltArgmnts.size(); + String ids[] = new String[ksz + 1]; + Set ks = cdfltArgmnts.keySet(); + if (ks.isEmpty()) { + log.complain("FAILURE: empty default arguments set is found " + + "for " + c.name() + " connector!"); + return 2; + } + + log.display("Looking over " + c.name() + " connector arguments: "); + + Iterator argi = ks.iterator(); + for (int j = 1; argi.hasNext(); j++) { + String argkey = (String) argi.next(); + Connector.Argument argval = + (Connector.Argument)cdfltArgmnts.get((Object) argkey); + String idntfr = argval.name(); + + if (idntfr == null) { + log.complain("FAILURE: argument identifier is null " + + "for " + argkey + " argument of " + c.name() + + " connector!"); + return 2; + } + if (idntfr.length() < 1) { + log.complain("FAILURE: empty argument identifier is found " + + "for " + argkey + " argument of " + c.name() + + " connector!"); + return 2; + } + + for (int k = 1; k < j && j > 1; k++) { + log.display("ids[" + k + "] = " + ids[k]); + if (ids[k].equals(idntfr)) { + log.complain("FAILURE: identifier of argument " + + "value isn't unique ( " + idntfr + ")!"); + return 2; + } + } + ids[j] = idntfr; + log.display("Next (" + j + ") argument's identifier is: " + + argval.name()); + }; + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/name/name001/TestDescription.java new file mode 100644 index 00000000000..1cce6196e22 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/name/name001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/name/name001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String name() + * Assertion: "Returns a short, unique identifier for the argument." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.name.name001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue001.java new file mode 100644 index 00000000000..873b26b8133 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue001.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.setValue; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import java.lang.NullPointerException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; + + +/** + * The test for the implementation of an object of the type
    + * Connector.Argument.
    + * + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.Argument.setValue()
    + * complies with its specification.
    + * The case for testing includes throwing NullPointerException
    + * if a parameter is null-string.
    + *
    + */ + + +public class setvalue001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.Argument.setValue()\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.Argument.setValue()\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.Argument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.Argument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connecter with Argument found\n"); + return exitCode0; + } + } + + try { + argument.setValue(null); + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(null); \n" + + "error: no NullPointerException thrown\n"); + } catch ( java.lang.NullPointerException e ) { + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue001/TestDescription.java new file mode 100644 index 00000000000..659576419bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/setValue/setvalue001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Argument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.Argument.setValue() + * complies with its specification. + * Check: setValue(null) doesn't set NullPointerException. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.Argument object is searched among + * VMM Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * IF argument.setValue(null) results in NullPointerException + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * To fix the bug 4491137, + * the test is corrected to comply with + * the updated specification in jdi-overview.html: + * Any method which takes a Object as an parameter + * will throw NullPointerException if + * null is passed directly or indirectly -- + * unless null is explicitly mentioned as a valid parameter. + * From now, the test regards throwing NullPointerException + * as the correct reaction to the null-parameter. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.setValue.setvalue001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.setValue.setvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue002.java new file mode 100644 index 00000000000..fef74f3db37 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue002.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.setValue; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.LaunchingConnector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.Argument.
    + * + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.Argument.setValue()
    + * complies with its specification, when a string value to be set
    + * is the empty or non-empty string.
    + *
    + * In case of the method Arguemnt.value() returns the value,
    + * not equal to one has been set,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class setvalue002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.max\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.Argument.setValue()\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.Argument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.Argument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connecter with Argument found\n"); + return exitCode0; + } + } + + argument.setValue(""); + if (argument.value() != "") { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue('');\n" + + "result: argument.value != ''\n"); + } + + argument.setValue("a"); + if (argument.value() != "a") { + exitCode = exitCode2; + out.println(sErr2 + + "check: argument.setValue('a');\n" + + "result: argument.value != 'a'\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue002/TestDescription.java new file mode 100644 index 00000000000..53f5aead6e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/setValue/setvalue002/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/setValue/setvalue002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Argument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.Argument.setValue() + * complies with its specification. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.Argument object is searched among + * Connectors. + * If no the argument is found out the test exits + * with the return value = 97 and a error message. + * - The following checks are applied: + * argument.setValue(""); + * IF ( argument.value != "") + * THEN an error detected + * ELSE the check passed + * argument.setValue("a"); + * IF ( argument.value != "a") + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.setValue.setvalue002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.setValue.setvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value001.java new file mode 100644 index 00000000000..6629c3efd26 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value001.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.*; +import javax.naming.directory.Attribute; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String setValue() + * Assertion: "Returns the current value of the argument." + */ + +public class value001 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Map cdfltArgmnts = c.defaultArguments(); + int ksz = cdfltArgmnts.size(); + String av[] = new String[ksz + 1]; + Set ks = cdfltArgmnts.keySet(); + if (ks.isEmpty()) { + log.complain("FAILURE: empty default argument set is found " + + "for " + c.name() + " connector!"); + return 2; + } + + log.display("Looking over " + c.name() + " connector arguments: "); + + Iterator argi = ks.iterator(); + for (int j = 1; argi.hasNext(); j++) { + String argkey = (String) argi.next(); + Connector.Argument argval = + (Connector.Argument)cdfltArgmnts.get((Object) argkey); + + String ovl = argval.value(); + String nvl = null; + try { + argval.setValue(nvl); + nvl = argval.value(); + if (nvl != null) { + log.complain("FAILURE: Can't set up new argument " + + "null-value!"); + return 2; + } + } catch (java.lang.NullPointerException exc) { + log.display("Can't set up new argument null-value."); + } + + argval.setValue("*"); + nvl = argval.value(); + if (!nvl.equals("*")) { + log.complain("FAILURE: Can't set up new argument " + + "'*'"); + return 2; + } + + argval.setValue(ovl); + nvl = argval.value(); + if (nvl != ovl) { + log.complain("FAILURE: Can't reset old argument value!"); + return 2; + } + + log.display("Changed " + argval.name() + " argument's value " + + "is: " + nvl); + }; + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value001/TestDescription.java new file mode 100644 index 00000000000..974fb15c143 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/value/value001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String setValue() + * Assertion: "Returns the current value of the argument." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.value.value001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value002.java new file mode 100644 index 00000000000..6a7c8a585a0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value002.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.*; +import javax.naming.directory.Attribute; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String value() + * Assertion: "Initially, the default value is returned." + */ + +public class value002 { + + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i=1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Map cdfltArgmnts = c.defaultArguments(); + Set ks = cdfltArgmnts.keySet(); + if (ks.isEmpty()) { + log.complain("FAILURE: empty default argument set is found " + + "for " + c.name() + " connector!"); + return 2; + } + + log.display("Looking over " + c.name() + " connector arguments: "); + + Iterator argi = ks.iterator(); + for (int j = 1; argi.hasNext(); j++) { + String argkey = (String) argi.next(); + Connector.Argument argval = + (Connector.Argument)cdfltArgmnts.get((Object) argkey); + String vl = argval.value(); + if (vl == null) { + log.display("The default argument value is null."); + } + if (vl.length() < 1) { + log.display("The default argument value is empty."); + } + log.display("Next (" + j + "," + argval.name() + ") " + + "argument's value is: " + vl); + }; + }; + + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value002/TestDescription.java new file mode 100644 index 00000000000..19d5136871b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value002/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/value/value002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String value() + * Assertion: "Initially, the default value is returned." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.value.value002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.value.value002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003.java new file mode 100644 index 00000000000..e845a809a01 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import javax.naming.directory.Attribute; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String value() + * Assertion: "Returns the current value of the argument." + * + * + * Comments: The test aims on the concrete Sun's JDI + * reference implementations. It uses + * com.sun.jdi.CommandLineLaunch connector and its + * "options" and "main" arguments. + * The test sets up the new "options" and "main" arguments + * values and then checks that new values remain previously + * after connection establishing with debugee VM and + * after debugee VM finishing. + */ + +public class value003 { + private static Log log; + + public static void main(String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + String javaKind = argHandler.getOptions().getProperty("debugee.vmkind"); + boolean java_g = javaKind != null && javaKind.startsWith("java_g"); // ...or java_g.exe + if (java_g) + log.display("Test option: java_g"); + + List lcl = vmm.launchingConnectors(); + if (lcl.size() > 0) { + log.display("Number of all known JDI launching connectors: " + + lcl.size()); + } else { + log.complain("FAILURE: no JDI launching connectors found!"); + return 2; + } + + Iterator lci = lcl.iterator(); + for (int i = 1; lci.hasNext(); i++) { + Connector c = (Connector) lci.next(); + if (c.name().compareTo("com.sun.jdi.CommandLineLaunch") != 0) { + continue; + } + Map cdfltArgmnts = c.defaultArguments(); + int ksz = cdfltArgmnts.size(); + String av[] = new String[ksz + 1]; + Set ks = cdfltArgmnts.keySet(); + if (ks.isEmpty()) { + log.complain("FAILURE: empty default argument set is found " + + "for " + c.name() + " connector!"); + return 2; + } + + log.display("Looking over " + c.name() + " connector arguments: "); + + boolean flg = false; + Iterator argi = ks.iterator(); + String ovl = null; + String nvl = null; + for (int j = 1; argi.hasNext(); j++) { + String argkey = (String)argi.next(); + Connector.Argument argval = + (Connector.Argument)cdfltArgmnts.get((Object) argkey); + + if (java_g && argval.name().equals("vmexec")) { + log.display("Substitute: vmexec --> java_g"); + argval.setValue("java_g"); + }; + + log.display("Connector.Argument argval = "+ argval); + if (argkey.compareTo("options") != 0 && + argkey.compareTo("main") != 0) { + continue; + } + if (argkey.compareTo("main") == 0) { + if (argval.isValid("nsk.jdi.Argument.value.value003a")) { + argval.setValue("nsk.jdi.Argument.value.value003a"); + } else { + log.complain("FAILURE: Can't set up new value for " + + "main-argument"); + return 2; + } + continue; + } + flg = true; + ovl = argval.value(); + if (argval.isValid(ovl + "-verify ")) { + argval.setValue(ovl + "-verify "); + } else { + log.complain("FAILURE: Can't set up new value for " + + "options-argument"); + return 2; + } + + nvl = argval.value(); + if (nvl.compareTo(ovl + "-verify ") != 0) { + log.complain("FAILURE: Can't set up argument value!"); + return 2; + } + log.display("Changed " + argval.name() + " argument's " + + "value is: " + nvl); + }; + + Binder binder = new Binder(argHandler, log); + Debugee debugee = null; + + try { + if (flg) { + flg = false; + VirtualMachine vm = + ((LaunchingConnector) c).launch(cdfltArgmnts); + log.display("VM = (" + vm + ")"); + debugee = binder.enwrapDebugee(vm, vm.process()); + + if (((Connector.Argument)cdfltArgmnts + .get((Object)"options")).value() + .compareTo(ovl + "-verify ") != 0) { + log.complain("FAILURE: Current 'options' argument " + + "value is not coinsides with the last " + + "setted up value."); + return 2; + } + if (((Connector.Argument)c.defaultArguments() + .get((Object) "options")).value() + .compareTo(ovl) != 0) { + log.complain("FAILURE: Default 'options' argument " + + "value can not be changed."); + return 2; + } + + debugee.resume(); + } + } catch ( java.io.IOException exc) { + log.complain("FAILURE: Unable to launch, so " + + "java.io.IOException is arisen."); + log.complain(exc.getMessage()); + return 2; + } catch (com.sun.jdi.connect.IllegalConnectorArgumentsException + exc) { + log.complain("FAILURE: One of the connector arguments is " + + "invalid, so IllegalConnectorArgumentsException " + + "is arisen."); + log.complain(exc.getMessage()); + return 2; + } catch ( com.sun.jdi.connect.VMStartException exc) { + log.complain("FAILURE: VM was terminated with error before " + + "a connection could be established, so " + + "VMStartException is arisen."); + log.complain(exc.getMessage()); + log.complain(Binder.readVMStartExceptionOutput(exc, log.getOutStream())); + return 2; + } finally { + if (debugee != null) { + try { + debugee.dispose(); + } catch (VMDisconnectedException ignore) { + } + + int extcd = debugee.waitFor(); + if (extcd != 95) { + log.complain("FAILURE: Launching VM crushes with " + + extcd + " exit code."); + return 2; + } + } + } + }; + + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003/TestDescription.java new file mode 100644 index 00000000000..1572e15a409 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/value/value003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String value() + * Assertion: "Returns the current value of the argument." + * ================================================ + * COMMENTS: + * The test aims on the concrete Sun's JDI + * reference implementations. It uses + * com.sun.jdi.CommandLineLaunch connector and its + * "options" and "main" arguments. + * The test sets up the new "options" and "main" arguments + * values and then checks that new values remain previously + * after connection establishing with debugee VM and + * after debugee VM finishing. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.value.value003 + * nsk.jdi.Argument.value.value003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.value.value003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003a.java new file mode 100644 index 00000000000..e5268e0d693 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value003a.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.value; + +/** + * Debugee. + */ +public class value003a { + public static void main (String args[]) { + System.exit(95); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004.java new file mode 100644 index 00000000000..f8e0e222692 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import javax.naming.directory.Attribute; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String value() + * Assertion: "Returns the current value of the argument." + * + * + * Comments: The test aims on the concrete Sun's JDI + * reference implementations. It uses + * com.sun.jdi.RawCommandLineLaunch connector and its + * "command" argument. + * The test sets up the new "command" argument + * value and then checks that new value remains previously + * after connection establishing with debugee VM and + * after debugee VM finishing. + * + * Warning: Temporarily the test is prepared only for + * Sparc.Solaris.dt_socket-transport of RawCommandLineLaunch + * connector + */ + +public class value004 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[],PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + String address = argHandler.getTransportPort(); + + List lcl = vmm.launchingConnectors(); + if (lcl.size() > 0) { + log.display("Number of all known JDI launching connectors: " + + lcl.size()); + } else { + log.complain("FAILURE: no JDI launching connectors found!"); + return 2; + } + + Iterator lci = lcl.iterator(); + for (int i = 1; lci.hasNext(); i++) { + Connector c = (Connector) lci.next(); + if (c.name().compareTo("com.sun.jdi.RawCommandLineLaunch") != 0) { + continue; + } + log.display("Connector's transport is: " + c.transport().name()); + if (c.transport().name().compareTo("dt_socket") != 0) { + log.display("WARNING: Temporarily the test is prepared only " + + "for dt_socket-transport of " + + "RawCommandLineLaunch connector!"); + return 0; + } + if (System.getProperties().getProperty("os.arch") + .compareTo("sparc") != 0 || + System.getProperties().getProperty("os.name") + .compareTo("SunOS") != 0) { + log.display("WARNING: Temporarily the test is prepared " + + "only for Sparc.Solaris-transport of " + + "RawCommandLineLaunch connector!"); + return 0; + } + Map cdfltArgmnts = c.defaultArguments(); + int ksz = cdfltArgmnts.size(); + String av[] = new String[ksz + 1]; + Set ks = cdfltArgmnts.keySet(); + if (ks.isEmpty()) { + log.complain("FAILURE: empty default arguments set is " + + "found for " + c.name() + " connector!"); + return 2; + } + + log.display("Looking over " + c.name() + " connector arguments: "); + + boolean flg = false; + Iterator argi = ks.iterator(); + String ovl = null; + String nvl = null; + for (int j = 1; argi.hasNext(); j++) { + String argkey = (String) argi.next(); + Connector.Argument argval = + (Connector.Argument)cdfltArgmnts.get((Object) argkey); + log.display("Connector.Argument argval = "+ argval); + if (argkey.compareTo("command") != 0 && + argkey.compareTo("address") != 0) { + continue; + } + if (argkey.compareTo("address") == 0) { + if (argval.isValid(address)) { + argval.setValue(address); + } else { + log.complain("FAILURE: Can't set up new value " + + "for address-argument"); + return 2; + } + continue; + } + flg = true; + ovl = argHandler.getLaunchExecPath() + " " + + "-Xdebug -Xnoagent -Djava.compiler=NONE " + + "-Xrunjdwp:transport=dt_socket,suspend=y," + + "address=" + address + " nsk.jdi.Argument.value.value004a"; + if (argval.isValid(ovl)) { + argval.setValue(ovl); + } else { + log.complain("FAILURE: Can't set up new value for " + + "command-argument"); + return 2; + } + + nvl = argval.value(); + if (nvl.compareTo(ovl) != 0) { + log.complain("FAILURE: Can't set up argument value!"); + return 2; + } + log.display("Changed " + argval.name() + " argument's " + + "value is: " + nvl); + }; + + Binder binder = new Binder(argHandler, log); + Debugee debugee = null; + + try { + if (flg) { + flg = false; + VirtualMachine vm = + ((LaunchingConnector)c).launch(cdfltArgmnts); + log.display("VM = (" + vm + ")"); + debugee = binder.enwrapDebugee(vm, vm.process()); + + if (((Connector.Argument) cdfltArgmnts + .get((Object) "command")).value() + .compareTo(ovl) != 0) { + log.complain("FAILURE: Current 'command' argument " + + "value is not coinsides with the " + + "last setted up value."); + return 2; + } + + debugee.resume(); + } + } catch ( java.io.IOException exc) { + log.complain("FAILURE: Unable to launch, so " + + "java.io.IOException is arisen."); + log.complain(exc.getMessage()); + return 2; + } catch ( com.sun.jdi.connect.IllegalConnectorArgumentsException + exc) { + log.complain("FAILURE: One of the connector arguments " + + "is invalid, so " + + "IllegalConnectorArgumentsException is arisen."); + log.complain(exc.getMessage()); + return 2; + } catch ( com.sun.jdi.connect.VMStartException exc) { + log.complain("FAILURE: VM was terminated with error before " + + "a connection could be established, so " + + "VMStartException is arisen."); + log.complain(exc.getMessage()); + log.complain(Binder.readVMStartExceptionOutput(exc, log.getOutStream())); + return 2; + } finally { + if (debugee != null) { + try { + debugee.dispose(); + } catch (VMDisconnectedException ignore) { + } + + int extcd = debugee.waitFor(); + if (extcd != 95) { + log.complain("FAILURE: Launching VM crushes " + + "with " + extcd + " exit code."); + return 2; + } + } + } + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004/TestDescription.java new file mode 100644 index 00000000000..6a354665260 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Argument/value/value004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector.Argument + * Method: public java.lang.String value() + * Assertion: "Returns the current value of the argument." + * ================================================ + * COMMENTS: + * The test aims on the concrete Sun's JDI + * reference implementations. It uses + * com.sun.jdi.RawCommandLineLaunch connector and its + * "command" argument. + * The test sets up the new "command" argument + * value and then checks that new value remains previously + * after connection establishing with debugee VM and + * after debugee VM finishing. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * ================================================ + * WARNING: + * Temporarily the test is prepared only for + * Sparc.Solaris.dt_socket-transport of RawCommandLineLaunch + * connector + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Argument.value.value004 + * nsk.jdi.Argument.value.value004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Argument.value.value004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004a.java new file mode 100644 index 00000000000..9431068645d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Argument/value/value004a.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Argument.value; + +//import java.io.*; + +/** + * Debugee. + */ +public class value004a { + public static void main (String args[]) { + +////////////////////////////////////////////////////////////////////////////// +// The following fragment was used only for connection establishing debuging: +// File outputFile = new File("ZSS"); +// FileOutputStream flos = null; +// try { +// flos = new FileOutputStream(outputFile); +// } catch (java.io.FileNotFoundException exc) { +// System.exit(97); +// } +// FilterOutputStream fltros = new FilterOutputStream(flos); +// PrintStream ps = new PrintStream(fltros); +// ps.println("=========== value004a is invoked! =================="); +// ps.close(); +//// Thread.currentThread().suspend(); +// try { +// Thread.currentThread().sleep(5000); +// } catch (java.lang.InterruptedException exc) { +// System.exit(97); +// } +////////////////////////////////////////////////////////////////////////////// + + System.exit(95); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001.java new file mode 100644 index 00000000000..3c4c6da441c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001.java @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class getvalue001 { + final static boolean BOOL[] = {true, false}; + final static byte BYTE[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + final static char CHAR[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE}; + final static double DOUB[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, + -1, -0, 1111111111.0, 1, Double.MAX_VALUE, + Double.POSITIVE_INFINITY, + Double.NaN}; + final static float FLOAT[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, + -1, -0, 0, 1, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, Float.NaN}; + final static int INT[] = {Integer.MIN_VALUE, -1, 0, 1, + Integer.MAX_VALUE}; + final static long LONG[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + final static short SHORT[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE}; + + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long"}, + {"lP1", "long"}, + {"lU1", "long"}, + {"lR1", "long"}, + {"lT1", "long"}, + {"lV1", "long"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.getValue."; + private final static String className = "getvalue001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "getvalue001aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String realType = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // All arrays have different length, so cycle "for (int j..)" + // is inside "if realType.equal(" + + if (realType.equals("boolean")) { + ///////////////////// Check boolean[] ///////////////////// + + for (int j = 0; j < BOOL.length; j++){ + Value arrayValue; + BooleanValue boolValue; + boolean element; + + // Get each element from array + try { + arrayValue = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE Z1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE Z1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + try { + boolValue = (BooleanValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z2> Cannot cast to " + + "boolean " + j + " value of field " + + name); + log.complain("debuger FAILURE Z2> Exception: " + e); + testFailed = true; + continue; + } + element = boolValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BOOL[j]) { + log.complain("debuger FAILURE Z3> " + j + " element of " + + "array " + name + " was expected " + + BOOL[j] + ", but returned " + element); + testFailed = true; + continue; + } + } + } else if (realType.equals("byte")) { + ///////////////////// Check byte[] ///////////////////// + + for (int j = 0; j < BYTE.length; j++){ + Value arrayValue; + ByteValue byteValue; + byte element; + + // Get each element from array + try { + arrayValue = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE B1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE B1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + try { + byteValue = (ByteValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE B2> Cannot cast to " + + "byte " + j + " value of field " + name); + log.complain("debuger FAILURE B2> Exception: " + e); + testFailed = true; + continue; + } + element = byteValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BYTE[j]) { + log.complain("debuger FAILURE B3> " + j + " element of " + + "array " + name + " was expected " + + CHAR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } + } else if (realType.equals("char")) { + ///////////////////// Check char[] ///////////////////// + + for (int j = 0; j < CHAR.length; j++){ + Value arrayValue; + CharValue charValue; + char element; + + // Get each element from array + try { + arrayValue = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE C1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE C1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + try { + charValue = (CharValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE C2> Cannot cast to " + + "char " + j + " value of field " + name); + log.complain("debuger FAILURE C2> Exception: " + e); + testFailed = true; + continue; + } + element = charValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (element != CHAR[j]) { + log.complain("debuger FAILURE C3> " + j + " element of " + + "array " + name + " was expected " + + CHAR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } + } else if (realType.equals("double")) { + ///////////////////// Check double[] ///////////////////// + + for (int j = 0; j < DOUB.length; j++){ + Value arrayValue; + DoubleValue doubleValue; + Double element; + + // Get each element from array + try { + arrayValue = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE D1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE D1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + try { + doubleValue = (DoubleValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE D2> Cannot cast to " + + "double " + j + " value of field " + name); + log.complain("debuger FAILURE D2> Exception: " + e); + testFailed = true; + continue; + } + element = new Double(doubleValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Double(DOUB[j]))) { + log.complain("debuger FAILURE D3> " + j + " element of " + + "array " + name + " was expected " + + DOUB[j] + ", but returned " + element); + testFailed = true; + continue; + } + } + } else if (realType.equals("float")) { + ///////////////////// Check float[] ///////////////////// + + for (int j = 0; j < FLOAT.length; j++){ + Value arrayValue; + FloatValue floatValue; + Float element; + + // Get each element from array + try { + arrayValue = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE F1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE F1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + try { + floatValue = (FloatValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE F2> Cannot cast to " + + "float " + j + " value of field " + name); + log.complain("debuger FAILURE F2> Exception: " + e); + testFailed = true; + continue; + } + element = new Float(floatValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Float(FLOAT[j]))) { + log.complain("debuger FAILURE F3> " + j + " element of " + + "array " + name + " was expected " + + FLOAT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } + } else if (realType.equals("int")) { + ///////////////////// Check int[] ///////////////////// + + for (int j = 0; j < INT.length; j++){ + Value arrayValue; + IntegerValue intValue; + int element; + + // Get each element from array + try { + arrayValue = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE I1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE I1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + try { + intValue = (IntegerValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE I2> Cannot cast to " + + "int " + j + " value of field " + name); + log.complain("debuger FAILURE I2> Exception: " + e); + testFailed = true; + continue; + } + element = intValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element + " (" + + Integer.toHexString(element) + ") "); + + if (element != INT[j]) { + log.complain("debuger FAILURE I3> " + j + " element of " + + "array " + name + " was expected " + INT[j] + + " (" + Integer.toHexString(INT[j]) + "), " + + " but returned " + element); + testFailed = true; + continue; + } + } + } else if (realType.equals("long")) { + ///////////////////// Check long[] ///////////////////// + + for (int j = 0; j < LONG.length; j++){ + Value arrayValue; + LongValue longValue; + long element; + + // Get each element from array + try { + arrayValue = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE L1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE L1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE L2> Cannot cast to " + + "long " + j + " value of field " + name); + log.complain("debuger FAILURE L2> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element + " (" + + Long.toHexString(element) + ") "); + + if (element != LONG[j]) { + log.complain("debuger FAILURE L3> " + j + " element of " + + "array " + name + " was expected " + + LONG[j] + " (" + Long.toHexString(LONG[j]) + + "), but returned " + element); + testFailed = true; + continue; + } + } + } else if (realType.equals("short")) { + ///////////////////// Check short[] ///////////////////// + + for (int j = 0; j < SHORT.length; j++){ + Value arrayValue; + ShortValue shortValue; + short element; + + // Get each element from array + try { + arrayValue = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE R1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE R1> Cannot get " + j + + " value from field " + name); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + try { + shortValue = (ShortValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE R2> Cannot cast to " + + "short " + j + " value of field " + name); + log.complain("debuger FAILURE R2> Exception: " + e); + testFailed = true; + continue; + } + element = shortValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (element != SHORT[j]) { + log.complain("debuger FAILURE R3> " + j + " element of " + + "array " + name + " was expected " + + SHORT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + realType); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001/TestDescription.java new file mode 100644 index 00000000000..a591d37bfa5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValue/getvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the getValue(int) method of ArrayReference interface of + * com.sun.jdi package. + * The method spec: + * public Value getValue(int index) + * Returns an array component value. + * Parameters: index - the index of the component to retrieve + * Returns: the Value at the given index. + * Throws: java.lang.IndexOutOfBoundsException - if the index is beyond the + * end of this array. + * ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/getValue/getvalue001 checks assertion: + * public Value getValue(int index) + * 1. Returns the Value at the given index. Array has components of primitive + * types only, index is in array bounds. + * Debuggee defines a number of array fields with components of primitive types + * only. + * Debugger gets each field from debuggee by name, gets field's value and + * casts it to ArrayReference. Then debugger determines field's type (by + * field's name), gets each element of the array invoking the method + * getValue(int). Returned Value is casted to correspondent PrimitiveType and + * the test gets its primitive value. This value is compared with expected. + * COMMENTS + * 4419982: JDI: two StackFrame methods return incorrect values for double + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValue.getvalue001 + * nsk.jdi.ArrayReference.getValue.getvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValue.getvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001a.java new file mode 100644 index 00000000000..c815efdef8b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvalue001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + getvalue001aClassToCheck classToCheck = new getvalue001aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class getvalue001aClassToCheck { + static boolean z1[] = {true, false}; + static byte b1[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + static char c1[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE}; + static double d1[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 1111111111.0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN}; + static float f1[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + 0, 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN}; + static int i1[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}; + static long l1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static short r1[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE}; + + static final long lF1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static private long lP1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static public long lU1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static protected long lR1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static transient long lT1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static volatile long lV1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002.java new file mode 100644 index 00000000000..f74d25ceae2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class getvalue002 { + final static int MIN_INDEX = -50; + final static int MAX_INDEX = 51; + final static String FIELD_NAME[][] = { + {"z1", "5"}, + {"b1", "5"}, + {"c1", "6"}, + {"d1", "1"}, + {"f1", "1"}, + {"i1", "10"}, + {"l1", "2"}, + {"r1", "5"}, + + {"lF1", "0"}, + {"lP1", "2"}, + {"lU1", "3"}, + {"lR1", "4"}, + {"lT1", "5"}, + {"lV1", "6"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.getValue."; + private final static String className = "getvalue002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "getvalue002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + Integer totalElements = new Integer(FIELD_NAME[i][1]); + int lastElementIndex = totalElements.intValue() - 1; + Value value; + ArrayReference arrayRef; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Try to get value by index from MIN_INDEX to -1 and from + // arrayRef.length() to MAX_INDEX + for (int j = MIN_INDEX; j < MAX_INDEX; j++) { + if ( (j < 0) || (j > lastElementIndex) ) { + Value arrayValue; + + try { + arrayValue = arrayRef.getValue(j); + log.complain("debuger FAILURE 4> Value for " + j + + " element of field " + name + " is " + arrayValue + + ", but IndexOutOfBoundsException expected."); + testFailed = true; + } catch (ObjectCollectedException e) { + log.display("debuger> Cannot get " + j + " value from " + + "field " + name); + log.display("debuger> Exception: " + e); + testFailed = true; + } catch (IndexOutOfBoundsException e) { + // Index is always out of bounds, so + // IndexOutOfBoundsException is expected + log.display("debuger> " + i + " field: cannot get " + + "element with index " + j + ". Expected " + + "exception: " + e); + } + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002/TestDescription.java new file mode 100644 index 00000000000..b4f57ad04b0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValue/getvalue002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the getValue(int) method of ArrayReference interface of + * com.sun.jdi package. + * The method spec: + * public Value getValue(int index) + * Returns an array component value. + * Parameters: index - the index of the component to retrieve + * Returns: the Value at the given index. + * Throws: java.lang.IndexOutOfBoundsException - if the index is beyond the + * end of this array. + * ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/getValue/getvalue002 checks assertion: + * public Value getValue(int index) + * 1. IndexOutOfBoundsException is thrown, if the index is out of range of + * ArrayReference. Array has components of primitive types only. + * Debuggee defines a number of array fields with components of primitive types + * only. The fields have different lengths. + * Debugger gets each field from debuggee by name, gets field's value and + * casts it to ArrayReference. Then debugger tries to invoke the method + * getValue(int) with index from MIN_INDEX to -1 and from last index to + * MAX_INDEX. For each index IndexOutOfBoundsException is expected. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValue.getvalue002 + * nsk.jdi.ArrayReference.getValue.getvalue002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValue.getvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002a.java new file mode 100644 index 00000000000..84671463029 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvalue002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + getvalue002aClassToCheck classToCheck = new getvalue002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class getvalue002aClassToCheck { + static boolean z1[] = {true, false, false, true, true}; + static byte b1[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + static char c1[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + '\u1234', '\u4321', Character.MAX_VALUE}; + static double d1[] = {Double.NEGATIVE_INFINITY}; + static float f1[] = {Float.POSITIVE_INFINITY}; + static int i1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; + static long l1[] = {Long.MIN_VALUE, Long.MAX_VALUE}; + static short r1[] = {-2, -1, 0, 1, 2}; + + static final long lF1[] = {}; + static private long lP1[] = {-1, 0}; + static public long lU1[] = {0, 1, 2}; + static protected long lR1[] = {0, 1, 2, 3}; + static transient long lT1[] = {1, 2, 3, 4, 5}; + static volatile long lV1[] = {1, 2, 3, 4, 5, 6}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003.java new file mode 100644 index 00000000000..aacff00cae4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class getvalue003 { + + // exit code when test failed + public final static int TEST_FAILED = 2; + // exit code when test passed + public final static int TEST_PASSED = 0; + // shift of exit code + public final static int JCK_STATUS_BASE = 95; + + private final static String prefix = "nsk.jdi.ArrayReference.getValue."; + private final static String className = "getvalue003"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String fieldToCheck = "testedObj"; + + private int exitStatus; + private Log log; + private Debugee debugee; + private IOPipe pipe; + + private getvalue003() { + log = null; + debugee = null; + pipe = null; + } + + public static void main(String argv[]) { + System.exit(JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + getvalue003 tstObj = new getvalue003(); + + if ( tstObj.prepareDebugee(argv, out) ) { + tstObj.execTest(); + tstObj.disposeOfDebugee(); + } + + if ( tstObj.exitStatus == TEST_FAILED ) + tstObj.complain("run:: TEST FAILED"); + else + tstObj.display("run:: TEST PASSED"); + return tstObj.exitStatus; + } + + private boolean prepareDebugee(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + display("prepareDebugee:: binder created."); + + debugee = binder.bindToDebugee(debugeeName); + log.display("prepareDebugee:: binded to debugee."); + pipe = debugee.createIOPipe(); + log.display("prepareDebugee:: pipe created."); + + debugee.redirectStderr(out); + debugee.resume(); + + String line = pipe.readln(); + if ( line == null ) { + complain("prepareDebugee:: UNEXPECTED debugee's signal - null"); + return false; + } + if ( !line.equals("ready") ) { + complain("prepareDebugee:: UNEXPECTED debugee's signal - " + + line); + return false; + } + + display("prepareDebugee:: debugee's \"ready\" signal recieved."); + return true; + } + + private boolean disposeOfDebugee() { + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + + if ( status != JCK_STATUS_BASE ) { + complain("disposeOfDebugee:: UNEXPECTED Debugee's exit " + + "status (not " + JCK_STATUS_BASE + ") - " + status); + return false; + } + display("disposeOfDebugee:: expected Debugee's exit " + + "status - " + status); + return true; + } + + private void display(String msg) { + if ( log != null ) + log.display("debugger> " + msg); + } + + private void complain(String msg) { + if ( log != null ) + log.complain("debugger FAILURE> " + msg); + } + + private boolean execTest() { + exitStatus = TEST_FAILED; + + ReferenceType refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("eventHandler:: Class '" + debugeeName + "' not found."); + return false; + } + + Field field = refType.fieldByName(fieldToCheck); + if ( field == null ) { + complain("eventHandler:: Field '" + fieldToCheck + "' not found."); + return false; + } + + Value value = refType.getValue(field); + if ( value == null ) { + complain("eventHandler:: Field '" + fieldToCheck + "' not initialized."); + return false; + } + + return checkObjectFields(value); + } + + public boolean checkObjectFields(Value value) { + List fieldList; + if ( ! (value instanceof ObjectReference) ) + return false; + + fieldList = ((ClassType)value.type()).allFields(); + + // Check all array fields from debugee + Field field; + display("\ncheckObjectFields:: Tests starts >>>"); + for (int i = 0; i < fieldList.size(); i++) { + field = (Field)fieldList.get(i); + + display(""); + display("checkObjectFields:: <" + field.name() + "> field is being " + + " checked."); + + // Check getting of item from field-array + if ( !checkFieldValue((ObjectReference)value, field) ) + return false; + } + exitStatus = TEST_PASSED; + return true; + } + + private boolean checkFieldValue(ObjectReference object, Field field) { + Value value; + ArrayReference arrayRef; + String fieldName = field.name(); + try { + value = object.getValue(field); + } catch (IllegalArgumentException e) { + complain("checkFieldValue:: can not get value for field " + fieldName); + complain("checkFieldValue:: " + e); + return false; + } + + display("checkFieldValue:: ***" + fieldName + " = " + value); + + boolean checkNULL = false; + // scaning of non-initialized arrays + for ( int i = 0; i < getvalue003a.NON_INIT_FIELDS.length; i++ ) + { + if ( fieldName.compareTo(getvalue003a.NON_INIT_FIELDS[i]) == 0 ) { + checkNULL = true; + break; + } + } + + // checking of field value + if ( checkNULL ) { + + // value is not null, but array has not to be initialized. + if ( value != null ) { + complain("checkFieldValue:: Value of '" + fieldName + "' is " + value + + ", but IndexOutOfBoundsException expected."); + return false; + + // array is not initialized. Expected value is null + } else { + display("checkFieldValue:: Expected value is null."); + return true; + } + } else { + + // value is null, but array has to be initialized. + if ( value == null ) { + complain("checkFieldValue:: Unexpected value of '" + fieldName + + "'" + value); + return false; + } + } + + display("checkFieldValue:: *** type of " + fieldName + " = " + value.type()); + + // check up type of value. it has to be ArrayType + if ( ! (value.type() instanceof ArrayType) ) { + display("checkFieldValue:: type of value is not ArrayType."); + return false; + } + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + return checkValue(0, fieldName, (ArrayReference )value, ((ArrayReference )value).length() + 1) && + checkValue(0, fieldName, (ArrayReference )value, Integer.MAX_VALUE) && + checkValue(0, fieldName, (ArrayReference )value, Integer.MAX_VALUE + 1); + } + + private boolean checkValue(int depth, String name, ArrayReference arrayRef, + long itemIndex) { + + Value itemValue; + int length = arrayRef.length(); + try { + itemValue = arrayRef.getValue(0); + if ( itemValue != null ) { + if ( itemValue.type() instanceof ArrayType ) { + + // itemValue has array type, check it by the same way + long index = (length + 1 != itemIndex) ? itemIndex : + ((ArrayReference )itemValue).length() + 1; + if ( !checkValue(depth + 1, name, (ArrayReference )itemValue, index) ) + return false; + } + } + itemValue = arrayRef.getValue((int)itemIndex); + if ( itemIndex > length || itemIndex < 0 ) { + complain("checkValue[" + depth + "]:: " + name + "[" + itemIndex + "] = " + + itemValue + ", but IndexOutOfBoundsException expected."); + return false; + } + + } catch (IndexOutOfBoundsException e) { + /* Index is always out of bounds, so + * IndexOutOfBoundsException is expected + */ + display("checkValue[" + depth + "]:: expected IndexOutOfBoundsException " + + "is thrown for " + itemIndex + " item."); + } catch (Exception e) { + complain("checkValue[" + depth + "]:: Unexpected exception: " + e); + return false; + } + return true; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003/TestDescription.java new file mode 100644 index 00000000000..46db4cbe221 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValue/getvalue003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.ArrayReference.getValue(int) + * correctly works for the boundary value of parameter complies with its spec: + * public Value getValue(int index) + * Returns an array component value. + * Parameters: + * index - the index of the component to retrieve + * Returns: + * the Value at the given index. + * Throws: + * IndexOutOfBoundsException - if index is outside the range of + * this array, that is, if either of the following are true: + * index < 0 + * index >= length() + * The test cases include static and instance fields of int and Object types, + * which are one- and two- dimensional arrays. Values of the method parameter + * are + 1, Integer.MAX_VALUE and Integer.MAX_VALUE + 1. + * IndexOutOfBoundsException is expected or, when array have no initalization, + * value is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayReference.getValue.getvalue003; + * the debuggee program - nsk.jdi.ArrayReference.getValue.getvalue003a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running + * on another JavaVM, establishes a pipe with the debuggee program, + * and then send to the programm commands, to which the debuggee replies + * via the pipe. + * Upon getting reply, the debugger requests fields of checked object + * and trys to read array values or an item of arrays correspondence with + * the test cases above. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValue.getvalue003 + * nsk.jdi.ArrayReference.getValue.getvalue003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValue.getvalue003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003a.java new file mode 100644 index 00000000000..7ecd02fa1bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue003a.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvalue003a { + + public final static String[] NON_INIT_FIELDS = {"staticIntArr2C", + "staticIntArrC", + "staticObjArrC"}; + + static getvalue003aClassToCheck testedObj = new getvalue003aClassToCheck(); + + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(getvalue003.TEST_PASSED + getvalue003.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(getvalue003.TEST_FAILED + getvalue003.JCK_STATUS_BASE); + } +} + +class getvalue003aClassToCheck { + static int[] staticIntArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + static Object[] staticObjArr = {null, null, null, null, null, null, null, null, null, null}; + + static int[][] staticIntArr2 = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}; + + static int[][] staticIntArr2C; // not initialized + + static int[] staticIntArrC; // not initialized + public int[] publicIntArrC; + protected int[] protecIntArrC; + private int[] privatIntArrC; + + static Object[] staticObjArrC; // not initialized + public Object[] publicObjArrC; + protected Object[] protecObjArrC; + private Object[] privatObjArrC; + + public getvalue003aClassToCheck() { + publicIntArrC = createIntArray(); + protecIntArrC = createIntArray(); + privatIntArrC = createIntArray(); + + publicObjArrC = createObjArray(); + protecObjArrC = createObjArray(); + privatObjArrC = createObjArray(); + } + + static private int[] createIntArray() { + int[] array = new int[10]; + for ( int i = 0; i < 10; i++ ) array[i] = i; + return array; + } + + static private Object[] createObjArray() { + Object[] array = new Object[10]; + return array; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001.java new file mode 100644 index 00000000000..0d721b15599 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001.java @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class getvalues001 { + final static boolean BOOL[] = {true, false}; + final static byte BYTE[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + final static char CHAR[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE}; + final static double DOUB[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, + -1, -0, 0, 1, Double.MAX_VALUE, + Double.POSITIVE_INFINITY, + Double.NaN}; + final static float FLOAT[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, + -1, -0, 0, 1, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, Float.NaN}; + final static int INT[] = {Integer.MIN_VALUE, -1, 0, 1, + Integer.MAX_VALUE}; + final static long LONG[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + final static short SHORT[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE}; + + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long"}, + {"lP1", "long"}, + {"lU1", "long"}, + {"lR1", "long"}, + {"lT1", "long"}, + {"lV1", "long"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.getValues."; + private final static String className = "getvalues001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "getvalues001aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String realType = FIELD_NAME[i][1]; + Value value; + Value arrayValue; + ArrayReference arrayRef; + List listOfValues; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Get all components from array + try { + listOfValues = arrayRef.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot get values from field " + + name); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + + // Check each element of the list + for (int j = 0; j < listOfValues.size(); j++) { + try { + arrayValue = (Value)listOfValues.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE 5> Cannot cast to Value " + + j + " element of field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field has " + j + " value " + + arrayValue); + + if (realType.equals("boolean")) { + + ///////////////////// Check boolean[] ///////////////////// + BooleanValue boolValue; + boolean element; + + try { + boolValue = (BooleanValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z1> Cannot cast to " + + "boolean " + j + " value of field " + + name); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + element = boolValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BOOL[j]) { + log.complain("debuger FAILURE Z2> " + j + " element " + + "of array " + name + " was expected " + + BOOL[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("byte")) { + + ///////////////////// Check byte[] ///////////////////// + ByteValue byteValue; + byte element; + + try { + byteValue = (ByteValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE B1> Cannot cast to " + + "byte " + j + " value of field " + + name); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + element = byteValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BYTE[j]) { + log.complain("debuger FAILURE B2> " + j + " element " + + "of array " + name + " was expected " + + BYTE[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("char")) { + + ///////////////////// Check char[] ///////////////////// + CharValue charValue; + char element; + + try { + charValue = (CharValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE C1> Cannot cast to " + + "char " + j + " value of field " + + name); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + element = charValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != CHAR[j]) { + log.complain("debuger FAILURE C2> " + j + " element " + + "of array " + name + " was expected " + + CHAR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("double")) { + + ///////////////////// Check double[] ///////////////////// + DoubleValue doubleValue; + Double element; + + try { + doubleValue = (DoubleValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE D1> Cannot cast to " + + "double " + j + " value of field " + + name); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + element = new Double(doubleValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (!element.equals(new Double(DOUB[j]))) { + log.complain("debuger FAILURE D2> " + j + " element " + + "of array " + name + " was expected " + + DOUB[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("float")) { + + ///////////////////// Check float[] ///////////////////// + FloatValue floatValue; + Float element; + + try { + floatValue = (FloatValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE F1> Cannot cast to " + + "float " + j + " value of field " + + name); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + element = new Float(floatValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (!element.equals(new Float(FLOAT[j]))) { + log.complain("debuger FAILURE F2> " + j + " element " + + "of array " + name + " was expected " + + FLOAT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("int")) { + + ///////////////////// Check int[] ///////////////////// + IntegerValue intValue; + int element; + + try { + intValue = (IntegerValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE I1> Cannot cast to " + + "int " + j + " value of field " + + name); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + element = intValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != INT[j]) { + log.complain("debuger FAILURE I2> " + j + " element " + + "of array " + name + " was expected " + + INT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("long")) { + + ///////////////////// Check long[] ///////////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE L1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONG[j]) { + log.complain("debuger FAILURE L2> " + j + " element " + + "of array " + name + " was expected " + + LONG[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("short")) { + + ///////////////////// Check short[] ///////////////////// + ShortValue shortValue; + short element; + + try { + shortValue = (ShortValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE R1> Cannot cast to " + + "short " + j + " value of field " + + name); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + element = shortValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != SHORT[j]) { + log.complain("debuger FAILURE R2> " + j + " element " + + "of array " + name + " was expected " + + SHORT[j] + ", but returned " + element); + testFailed = true; + continue; + } + + } else { + log.complain("debuger FAILURE 6> Unexpected type: " + + realType); + testFailed = true; + break; + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001/TestDescription.java new file mode 100644 index 00000000000..a299fc158af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValues/getvalues001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the getValues() method of ArrayReference interface of + * com.sun.jdi package. + * The method spec: + * public List getValues() + * Returns all of the components in this array. + * Returns: a list of Value objects, one for each array component ordered by + * array index. + * Throws: ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/getValues/getvalues001 checks assertion: + * public List getValues() + * 1. Returns all of the components in this array with primitive type + * components. + * Debuggee defines a number of array fields which component type is primitive + * type only. + * Debugger gets each field from debuggee by name, gets its value and casts it + * to ArrayReference. Then the test gets all elements of the array invoking the + * method getValues() and then checks each element of the ArrayReference. The + * debugger determines component's type (by field's name), gets each element + * of the list, casts it to correspondent PrimitiveType and then gets its + * primitive value. Then the test compares returned and expected primitive + * values. + * COMMENTS + * 4419982: JDI: two StackFrame methods return incorrect values for double + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValues.getvalues001 + * nsk.jdi.ArrayReference.getValues.getvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValues.getvalues001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001a.java new file mode 100644 index 00000000000..0fcbee7cd35 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvalues001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + getvalues001aClassToCheck classToCheck = new getvalues001aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class getvalues001aClassToCheck { + static boolean z1[] = {true, false}; + static byte b1[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + static char c1[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE}; + static double d1[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN}; + static float f1[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + 0, 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN}; + static int i1[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}; + static long l1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static short r1[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE}; + + static final long lF1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static private long lP1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static public long lU1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static protected long lR1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static transient long lT1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static volatile long lV1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002.java new file mode 100644 index 00000000000..c8d1d291d91 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class getvalues002 { + final static String FIELD_NAME[] = {"z1", "b1", "c1", "d1", "f1", "i1", + "l1", "r1", "lF1", "lP1", "lU1", "lR1", + "lT1", "lV1"}; + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.getValues."; + private final static String className = "getvalues002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "getvalues002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i]; + Value value; + ArrayReference arrayRef; + List listOfValues; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Get all components from array + try { + listOfValues = arrayRef.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot get values from field " + + name); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 4> Cannot get values from field " + + name); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002/TestDescription.java new file mode 100644 index 00000000000..34b586309af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValues/getvalues002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the getValues() method of ArrayReference interface of + * com.sun.jdi package. + * The method spec: + * public List getValues() + * Returns all of the components in this array. + * Returns: a list of Value objects, one for each array component ordered by + * array index. + * Throws: ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/getValues/getvalues002 checks assertion: + * public List getValues() + * 1. Returns all of the components in this empty-array with primitive type + * components. + * Debuggee defines a number of empty-array fields which component type is + * primitive type only. + * Debugger gets each field from debuggee by name, gets its value and casts + * it to ArrayReference. Then the test tries to inkove the method getValues(). + * No exception should be thrown. ObjectCollectedException is declared in the + * spec, but debuggee does not need huge amount of memory, so even + * ObjectCollectedException is treated as failure. + * COMMENTS + * The test shows the bug: + * 4439631 ArrayReference.getValues() throws undeclared IndexOutOfBoundsException + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValues.getvalues002 + * nsk.jdi.ArrayReference.getValues.getvalues002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValues.getvalues002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002a.java new file mode 100644 index 00000000000..5e24cdc74c8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues002a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvalues002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + getvalues002aClassToCheck classToCheck = new getvalues002aClassToCheck(); + + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class getvalues002aClassToCheck { + static boolean z1[] = {}; + static byte b1[] = {}; + static char c1[] = {}; + static double d1[] = {}; + static float f1[] = {}; + static int i1[] = {}; + static long l1[] = {}; + static short r1[] = {}; + + static final long lF1[] = {}; + static private long lP1[] = {}; + static public long lU1[] = {}; + static protected long lR1[] = {}; + static transient long lT1[] = {}; + static volatile long lV1[] = {}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003.java new file mode 100644 index 00000000000..10a6cdf9f66 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class getvalues003 { + + // exit code when test failed + public final static int TEST_FAILED = 2; + // exit code when test passed + public final static int TEST_PASSED = 0; + // shift of exit code + public final static int JCK_STATUS_BASE = 95; + + private final static String prefix = "nsk.jdi.ArrayReference.getValues."; + private final static String className = "getvalues003"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String fieldToCheck = "testedObj"; + + private int exitStatus; + private Log log; + private Debugee debugee; + private IOPipe pipe; + + private getvalues003() { + log = null; + debugee = null; + pipe = null; + } + + public static void main(String argv[]) { + System.exit(JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + getvalues003 tstObj = new getvalues003(); + + if ( tstObj.prepareDebugee(argv, out) ) { + tstObj.execTest(); + tstObj.disposeOfDebugee(); + } + + if ( tstObj.exitStatus == TEST_FAILED ) + tstObj.complain("run:: TEST FAILED"); + else + tstObj.display("run:: TEST PASSED"); + return tstObj.exitStatus; + } + + private boolean prepareDebugee(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + display("prepareDebugee:: binder created."); + + debugee = binder.bindToDebugee(debugeeName); + log.display("prepareDebugee:: binded to debugee."); + pipe = debugee.createIOPipe(); + log.display("prepareDebugee:: pipe created."); + + debugee.redirectStderr(out); + debugee.resume(); + + String line = pipe.readln(); + if ( line == null ) { + complain("prepareDebugee:: UNEXPECTED debugee's signal - null"); + return false; + } + if ( !line.equals("ready") ) { + complain("prepareDebugee:: UNEXPECTED debugee's signal - " + + line); + return false; + } + + display("prepareDebugee:: debugee's \"ready\" signal recieved."); + return true; + } + + private boolean disposeOfDebugee() { + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + + if ( status != JCK_STATUS_BASE ) { + complain("disposeOfDebugee:: UNEXPECTED Debugee's exit " + + "status (not " + JCK_STATUS_BASE + ") - " + status); + return false; + } + display("disposeOfDebugee:: expected Debugee's exit " + + "status - " + status); + return true; + } + + private void display(String msg) { + if ( log != null ) + log.display("debugger> " + msg); + } + + private void complain(String msg) { + if ( log != null ) + log.complain("debugger FAILURE> " + msg); + } + + private boolean execTest() { + exitStatus = TEST_FAILED; + + ReferenceType refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("eventHandler:: Class '" + debugeeName + "' not found."); + return false; + } + + Field field = refType.fieldByName(fieldToCheck); + if ( field == null ) { + complain("eventHandler:: Field '" + fieldToCheck + "' not found."); + return false; + } + + Value value = refType.getValue(field); + if ( value == null ) { + complain("eventHandler:: Field '" + fieldToCheck + "' not initialized."); + return false; + } + + return checkObjectFields(value); + } + + public boolean checkObjectFields(Value value) { + List fieldList; + if ( ! (value instanceof ObjectReference) ) + return false; + + fieldList = ((ClassType)value.type()).allFields(); + + // Check all array fields from debugee + Field field; + display("\ncheckObjectFields:: Tests starts >>>"); + for (int i = 0; i < fieldList.size(); i++) { + field = (Field)fieldList.get(i); + + display(""); + display("checkObjectFields:: <" + field.name() + "> field is being " + + " checked."); + + // Check getting of item from field-array + if ( !checkFieldValue((ObjectReference)value, field) ) + return false; + } + exitStatus = TEST_PASSED; + return true; + } + + private boolean checkFieldValue(ObjectReference object, Field field) { + Value value; + ArrayReference arrayRef; + String name = field.name(); + try { + value = object.getValue(field); + } catch (IllegalArgumentException e) { + complain("checkFieldValue:: can not get value for field " + name); + complain("checkFieldValue:: " + e); + return false; + } + + display("checkFieldValue:: ***" + field.name() + " = " + value); + + // non-initialized fields hav not to be + if ( value == null ) { + complain("checkFieldValue:: value is null."); + return false; + } + display("checkFieldValue:: *** type of " + field.name() + " = " + value.type()); + + // check up type of value. it has to be ArrayType + if ( ! (value.type() instanceof ArrayType) ) { + display("checkFieldValue:: type of value is not ArrayType."); + return true; + } + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + return checkValue(name, (ArrayReference )value); + } + + private boolean checkValue(String name, ArrayReference arrayRef) { + + // Get all components from array + List listOfValues; + try { + listOfValues = arrayRef.getValues(); + } catch (Exception e) { + complain("checkValue:: Unexpected exception: " + e); + return false; + } + display("checkValue:: length of ArrayReference object - " + arrayRef.length()); + display("checkValue:: size of values list - " + listOfValues.size()); + + if ( listOfValues.size() == 0 ) { + display("checkValue:: <" + name + "> field has been checked.\n"); + return true; + } + complain("checkValue:: <" + name + "> field has non-zero length.\n"); + return false; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003/TestDescription.java new file mode 100644 index 00000000000..895c54b5440 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValues/getvalues003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary values. + * The test checks up that the method + * com.sun.jdi.ArrayReference.getValues() + * correctly works for arrays with zero size complies with its spec: + * public List getValues() + * Returns all of the components in this array. + * Returns: + * a list of Value objects, one for each array component ordered by + * array index. For zero length arrays, an empty list is returned. + * The test cases include static and instance fields of int and Object types, + * which are one-dimensional arrays of zero-sizes. An empty list is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayReference.getValues.getvalues003; + * the debuggee program - nsk.jdi.ArrayReference.getValues.getvalues003a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running + * on another JavaVM, establishes a pipe with the debuggee program, + * and then send to the programm commands, to which the debuggee replies + * via the pipe. + * Upon getting reply, the debugger requests fields of checked object + * and trys to read array values correspondence with the test cases above. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValues.getvalues003 + * nsk.jdi.ArrayReference.getValues.getvalues003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValues.getvalues003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003a.java new file mode 100644 index 00000000000..c95c01f9d11 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues003a.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvalues003a { + + static getvalues003aClassToCheck testedObj = new getvalues003aClassToCheck(); + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(getvalues003.TEST_FAILED + getvalues003.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(getvalues003.TEST_FAILED + getvalues003.JCK_STATUS_BASE); + } +} + +class getvalues003aClassToCheck { + static int[] staticIntArr = {}; + static Object[] staticObjArr = {}; + + public int[] publicIntArrC; + protected int[] protecIntArrC; + private int[] privatIntArrC; + + public Object[] publicObjArrC; + protected Object[] protecObjArrC; + private Object[] privatObjArrC; + + public getvalues003aClassToCheck() { + publicIntArrC = createIntArray(); + protecIntArrC = createIntArray(); + privatIntArrC = createIntArray(); + + publicObjArrC = createObjArray(); + protecObjArrC = createObjArray(); + privatObjArrC = createObjArray(); + } + + static private int[] createIntArray() { + return new int[0]; + } + + static private Object[] createObjArray() { + return new Object[0]; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001.java new file mode 100644 index 00000000000..b7052f73007 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001.java @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class getvaluesii001 { + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long_final"}, + {"lP1", "long_private"}, + {"lU1", "long_public"}, + {"lR1", "long_protected"}, + {"lT1", "long_transient"}, + {"lV1", "long_volatile"} + }; + + final static boolean BOOL[] = {true, false, false, false, true, false, + false, true, false, false, false, true, + true}; + final static byte BYTE[] = {0, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + -101, -100, -99, Byte.MIN_VALUE + 1, 99, + Byte.MAX_VALUE - 1, 101, -1}; + final static char CHAR[] = {0, 1, + Character.MIN_VALUE, '\u00ff', '\uff00', + '\uff00', '\uff00', '\u1234', '\u0f0f', + Character.MAX_VALUE, '\u0f0f', + Character.MIN_VALUE, Character.MAX_VALUE, + '\u1234'}; + final static double DOUB[] = {0, 1, 2, + Double.NEGATIVE_INFINITY, Double.MIN_VALUE, + -1, -0, 0, 1, Double.MAX_VALUE, Double.NaN, + Double.NaN, Double.POSITIVE_INFINITY, + Double.NaN}; + final static float FLOAT[] = {0, 1, 2, 3, + Float.NEGATIVE_INFINITY, Float.MIN_VALUE, + -1, -0, 0, 1, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, Float.NaN, + Float.POSITIVE_INFINITY}; + final static int INT[] = {0, 1, 2, 3, 4, + -255, Integer.MIN_VALUE, -1, 0, 1, + Integer.MAX_VALUE, 254, 255, 256}; + final static long LONG[] = {0, 1, 2, 3, 4, 5, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + -1, -2, 0}; + final static short SHORT[] = {0, 1, 2, 3, 4, 5, 6, + Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + -2, 0}; + final static long LONGF[] = {0, 1, 2, 3, 4, 5, 6, 7, + -1, 0, 1, 2, 3, 4}; + final static long LONGP[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + final static long LONGU[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + Long.MAX_VALUE, 10, 0, -10}; + final static long LONGR[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + -1, 0, 1}; + final static long LONGT[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + Long.MAX_VALUE, Long.MIN_VALUE}; + final static long LONGV[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + Long.MAX_VALUE}; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.getValues_ii."; + private final static String className = "getvaluesii001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "getvaluesii001aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String realType = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listOfValues; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Get all components from i to the end of the array. + // Each array has 14 elements, so IndexOutOfBoundsException + // should never be thrown + try { + listOfValues = arrayRef.getValues(i, -1); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot get values from field " + + name); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 4> Cannot get values from field " + + name); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field read: " + listOfValues); + + // Check each element from the list + for (int j = 0; j < listOfValues.size(); j++) { + Value arrayValue; + + try { + arrayValue = (Value)listOfValues.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE 5> Cannot cast to Value " + + j + " element of field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field has " + j + " value " + + arrayValue); + + if (realType.equals("boolean")) { + + ///////////////////// Check boolean[] ///////////////////// + BooleanValue boolValue; + boolean element; + + try { + boolValue = (BooleanValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z1> Cannot cast to " + + "boolean " + j + " value of field " + + name); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + element = boolValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BOOL[j + i]) { + log.complain("debuger FAILURE Z2> " + j + " element " + + "of array " + name + " was expected " + + BOOL[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("byte")) { + + ///////////////////// Check byte[] ///////////////////// + ByteValue byteValue; + byte element; + + try { + byteValue = (ByteValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE B1> Cannot cast to " + + "byte " + j + " value of field " + + name); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + element = byteValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BYTE[j + i]) { + log.complain("debuger FAILURE B2> " + j + " element " + + "of array " + name + " was expected " + + BYTE[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("char")) { + + ///////////////////// Check char[] ///////////////////// + CharValue charValue; + char element; + + try { + charValue = (CharValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE C1> Cannot cast to " + + "char " + j + " value of field " + + name); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + element = charValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != CHAR[j + i]) { + Character c = new Character('c'); + Integer n = new Integer(0); + String sReal = n.toHexString( + c.getNumericValue(CHAR[j + i]) + ); + String sRead = n.toHexString( + c.getNumericValue(element) + ); + + log.complain("debuger FAILURE C2> " + j + " element " + + "of array " + name + " was expected " + + sReal + " but returned " + sRead); + testFailed = true; + continue; + } + } else if (realType.equals("double")) { + + ///////////////////// Check double[] ///////////////////// + DoubleValue doubleValue; + Double element; + + try { + doubleValue = (DoubleValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE D1> Cannot cast to " + + "double " + j + " value of field " + + name); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + element = new Double(doubleValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (!element.equals(new Double(DOUB[j + i]))) { + log.complain("debuger FAILURE D2> " + j + " element " + + "of array " + name + " was expected " + + DOUB[j + i] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("float")) { + + ///////////////////// Check float[] ///////////////////// + FloatValue floatValue; + Float element; + + try { + floatValue = (FloatValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE F1> Cannot cast to " + + "float " + j + " value of field " + + name); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + element = new Float(floatValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (!element.equals(new Float(FLOAT[j + i]))) { + log.complain("debuger FAILURE F2> " + j + " element " + + "of array " + name + " was expected " + + FLOAT[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("int")) { + + ///////////////////// Check int[] ///////////////////// + IntegerValue intValue; + int element; + + try { + intValue = (IntegerValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE I1> Cannot cast to " + + "int " + j + " value of field " + + name); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + element = intValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != INT[j + i]) { + log.complain("debuger FAILURE I2> " + j + " element " + + "of array " + name + " was expected " + + INT[j + i] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("long")) { + + ///////////////////// Check long[] ///////////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE L1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONG[j + i]) { + log.complain("debuger FAILURE L2> " + j + " element " + + "of array " + name + " was expected " + + LONG[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("short")) { + + ///////////////////// Check short[] ///////////////////// + ShortValue shortValue; + short element; + + try { + shortValue = (ShortValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE R1> Cannot cast to " + + "short " + j + " value of field " + + name); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + element = shortValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != SHORT[j + i]) { + log.complain("debuger FAILURE R2> " + j + " element " + + "of array " + name + " was expected " + + SHORT[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_final")) { + + //////////////////// Check final long[] ///////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LF1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LF1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGF[j + i]) { + log.complain("debuger FAILURE LF2> " + j + " element " + + "of array " + name + " was expected " + + LONGF[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_private")) { + + //////////////////// Check private long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LP1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LP1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGP[j + i]) { + log.complain("debuger FAILURE LP2> " + j + " element " + + "of array " + name + " was expected " + + LONGP[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_public")) { + + //////////////////// Check public long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LU1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LU1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGU[j + i]) { + log.complain("debuger FAILURE LU2> " + j + " element " + + "of array " + name + " was expected " + + LONGU[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_protected")) { + + ////////////////// Check protected long[] ////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LR1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LR1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGR[j + i]) { + log.complain("debuger FAILURE LR2> " + j + " element " + + "of array " + name + " was expected " + + LONGR[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_transient")) { + + ////////////////// Check transient long[] ////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LT1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LT1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGT[j + i]) { + log.complain("debuger FAILURE LT2> " + j + " element " + + "of array " + name + " was expected " + + LONGT[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_volatile")) { + + ////////////////// Check volatile long[] ////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LV1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LV1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGV[j + i]) { + log.complain("debuger FAILURE LV2> " + j + " element " + + "of array " + name + " was expected " + + LONGV[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else { + log.complain("debuger FAILURE 6> Unexpected type: " + + realType); + testFailed = true; + break; + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001/TestDescription.java new file mode 100644 index 00000000000..e38c4bbf1ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValues_ii/getvaluesii001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the getValues(int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public List getValues(int index, int length) + * Returns a range of array components. + * Parameters: index - the index of the first component to retrieve + * length - the number of components to retrieve, or -1 to + * retrieve all components to the end of this array. + * Returns: a list of Value objects, one for each requested array component + * ordered by array index. + * Throws: java.lang.IndexOutOfBoundsException - if index + length is an + * index beyond the end of this array. + * ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/getValues_ii/getvaluesii001 checks assertion: + * public Value getValues(int index, int length) + * 1. Returns a list of Value objects -- all components to the end of the + * array. Index is from 0 up to the index of the last element of the + * array; length is always -1. + * Debuggee defines 14 array fields which component type is primitive type + * only. Each field consists of 14 elements. + * Debugger gets each field from debuggee by name, gets its value and casts + * it to ArrayReference. For i field debugger invokes method getValues(i, -1) + * to get all components from i to the end of this array. The debugger + * determines component's type (by field's name), gets each element of the + * list, casts it to correspondent PrimitiveType and then gets its primitive + * value. Then the test compares returned and expected primitive values. + * COMMENTS + * 4419982: JDI: two StackFrame methods return incorrect values for double + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValues_ii.getvaluesii001 + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001a.java new file mode 100644 index 00000000000..39e1ba05658 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvaluesii001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + getvaluesii001aClassToCheck classToCheck = new getvaluesii001aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class getvaluesii001aClassToCheck { + + // Each of 14 array fields has 14 elements + static boolean z1[] = {true, false, false, false, true, + false, false, true, false, false, + false, true, true}; + static byte b1[] = {0, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + -101, -100, -99, Byte.MIN_VALUE + 1, 99, + Byte.MAX_VALUE - 1, 101, -1}; + static char c1[] = {0, 1, + Character.MIN_VALUE, '\u00ff', '\uff00', '\uff00', + '\uff00', '\u1234', '\u0f0f', Character.MAX_VALUE, + '\u0f0f', Character.MIN_VALUE, Character.MAX_VALUE, + '\u1234'}; + static double d1[] = {0, 1, 2, + Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.NaN, Double.NaN, + Double.POSITIVE_INFINITY, Double.NaN}; + static float f1[] = {0, 1, 2, 3, + Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + 0, 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN, Float.POSITIVE_INFINITY}; + static int i1[] = {0, 1, 2, 3, 4, + -255, Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, + 254, 255, 256}; + static long l1[] = {0, 1, 2, 3, 4, 5, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, -1, -2, 0}; + static short r1[] = {0, 1, 2, 3, 4, 5, 6, + Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, -2, 0}; + + static final long lF1[] = {0, 1, 2, 3, 4, 5, 6, 7, + -1, 0, 1, 2, 3, 4}; + static private long lP1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static public long lU1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + Long.MAX_VALUE, 10, 0, -10}; + static protected long lR1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + -1, 0, 1}; + static transient long lT1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + Long.MAX_VALUE, Long.MIN_VALUE}; + static volatile long lV1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + Long.MAX_VALUE}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002.java new file mode 100644 index 00000000000..7ca97a15833 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002.java @@ -0,0 +1,694 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class getvaluesii002 { + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + {"d1", "double"}, + {"f1", "float"}, + + {"lF1", "long_final"}, + {"lP1", "long_private"}, + {"lU1", "long_public"}, + {"lR1", "long_protected"}, + {"lT1", "long_transient"}, + {"lV1", "long_volatile"} + }; + + static boolean BOOL[] = {true}; + static byte BYTE[] = {Byte.MIN_VALUE, 0, Byte.MAX_VALUE}; + static char CHAR[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE, Character.MAX_VALUE}; + static int INT[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, + Integer.MIN_VALUE + 1, Integer.MAX_VALUE - 1}; + static long LONG[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE + 2, -2, 2, Long.MAX_VALUE - 2}; + static short SHORT[] = {Short.MIN_VALUE, -1, 0, 0, 1, Short.MAX_VALUE, + Short.MAX_VALUE - 1, 1, 1, 0, Short.MIN_VALUE}; + static double DOUB[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN, Double.NaN, -0, 0, 1}; + static float FLOAT[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + 0, 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN, Float.NaN, 123456, 0, -123456, + Float.NaN, Float.NEGATIVE_INFINITY}; + + static final long LONGF[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0}; + static private long LONGP[] = {Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE, + Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE, + Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE, + Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE}; + static public long LONGU[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, + Long.MAX_VALUE, Long.MIN_VALUE}; + static protected long LONGR[] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + Long.MAX_VALUE, Long.MIN_VALUE, 0, 0}; + static transient long LONGT[] = {Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE - 1}; + static volatile long LONGV[] = {Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MIN_VALUE}; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.getValues_ii."; + private final static String className = "getvaluesii002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "getvaluesii002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String realType = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listOfValues; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Get i + 1 components from index i. Each array has enough + // elements, so that IndexOutOfBoundsException should never be + // thrown + try { + listOfValues = arrayRef.getValues(i, i + 1); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot get values from field " + + name + " from index " + i); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 4> Cannot get values from field " + + name + " from index " + i); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field read: " + listOfValues); + + // Check each element from the list + for (int j = 0; j < listOfValues.size(); j++) { + Value arrayValue; + + try { + arrayValue = (Value)listOfValues.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE 5> Cannot cast to Value " + + j + " element of field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field has " + j + " value " + + arrayValue); + + if (realType.equals("boolean")) { + + ///////////////////// Check boolean[] ///////////////////// + BooleanValue boolValue; + boolean element; + + try { + boolValue = (BooleanValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z1> Cannot cast to " + + "boolean " + j + " value of field " + + name); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + element = boolValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BOOL[j + i]) { + log.complain("debuger FAILURE Z2> " + j + " element " + + "of array " + name + " was expected " + + BOOL[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("byte")) { + + ///////////////////// Check byte[] ///////////////////// + ByteValue byteValue; + byte element; + + try { + byteValue = (ByteValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE B1> Cannot cast to " + + "byte " + j + " value of field " + + name); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + element = byteValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BYTE[j + i]) { + log.complain("debuger FAILURE B2> " + j + " element " + + "of array " + name + " was expected " + + BYTE[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("char")) { + + ///////////////////// Check char[] ///////////////////// + CharValue charValue; + char element; + + try { + charValue = (CharValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE C1> Cannot cast to " + + "char " + j + " value of field " + + name); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + element = charValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != CHAR[j + i]) { + Character c = new Character('c'); + Integer n = new Integer(0); + String sReal = n.toHexString( + c.getNumericValue(CHAR[j + i]) + ); + String sRead = n.toHexString( + c.getNumericValue(element) + ); + + log.complain("debuger FAILURE C2> " + j + " element " + + "of array " + name + " was expected " + + sReal + " but returned " + sRead); + testFailed = true; + continue; + } + } else if (realType.equals("double")) { + + ///////////////////// Check double[] ///////////////////// + DoubleValue doubleValue; + Double element; + + try { + doubleValue = (DoubleValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE D1> Cannot cast to " + + "double " + j + " value of field " + + name); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + element = new Double(doubleValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (!element.equals(new Double(DOUB[j + i]))) { + log.complain("debuger FAILURE D2> " + j + " element " + + "of array " + name + " was expected " + + DOUB[j + i] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("float")) { + + ///////////////////// Check float[] ///////////////////// + FloatValue floatValue; + Float element; + + try { + floatValue = (FloatValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE F1> Cannot cast to " + + "float " + j + " value of field " + + name); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + element = new Float(floatValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (!element.equals(new Float(FLOAT[j + i]))) { + log.complain("debuger FAILURE F2> " + j + " element " + + "of array " + name + " was expected " + + FLOAT[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("int")) { + + ///////////////////// Check int[] ///////////////////// + IntegerValue intValue; + int element; + + try { + intValue = (IntegerValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE I1> Cannot cast to " + + "int " + j + " value of field " + + name); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + element = intValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != INT[j + i]) { + log.complain("debuger FAILURE I2> " + j + " element " + + "of array " + name + " was expected " + + INT[j + i] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (realType.equals("long")) { + + ///////////////////// Check long[] ///////////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE L1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONG[j + i]) { + log.complain("debuger FAILURE L2> " + j + " element " + + "of array " + name + " was expected " + + LONG[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("short")) { + + ///////////////////// Check short[] ///////////////////// + ShortValue shortValue; + short element; + + try { + shortValue = (ShortValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE R1> Cannot cast to " + + "short " + j + " value of field " + + name); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + element = shortValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != SHORT[j + i]) { + log.complain("debuger FAILURE R2> " + j + " element " + + "of array " + name + " was expected " + + SHORT[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_final")) { + + //////////////////// Check final long[] ///////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LF1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LF1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGF[j + i]) { + log.complain("debuger FAILURE LF2> " + j + " element " + + "of array " + name + " was expected " + + LONGF[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_private")) { + + //////////////////// Check private long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LP1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LP1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGP[j + i]) { + log.complain("debuger FAILURE LP2> " + j + " element " + + "of array " + name + " was expected " + + LONGP[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_public")) { + + //////////////////// Check public long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LU1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LU1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGU[j + i]) { + log.complain("debuger FAILURE LU2> " + j + " element " + + "of array " + name + " was expected " + + LONGU[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_protected")) { + + ////////////////// Check protected long[] ////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LR1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LR1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGR[j + i]) { + log.complain("debuger FAILURE LR2> " + j + " element " + + "of array " + name + " was expected " + + LONGR[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_transient")) { + + ////////////////// Check transient long[] ////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LT1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LT1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGT[j + i]) { + log.complain("debuger FAILURE LT2> " + j + " element " + + "of array " + name + " was expected " + + LONGT[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else if (realType.equals("long_volatile")) { + + ////////////////// Check volatile long[] ////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)arrayValue; + } catch (ClassCastException e) { + log.complain("debuger FAILURE LV1> Cannot cast to " + + "long " + j + " value of field " + + name); + log.complain("debuger FAILURE LV1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGV[j + i]) { + log.complain("debuger FAILURE LV2> " + j + " element " + + "of array " + name + " was expected " + + LONGV[j + i] + ", but returned " + + element); + testFailed = true; + continue; + } + } else { + log.complain("debuger FAILURE 6> Unexpected type: " + + realType); + testFailed = true; + break; + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002/TestDescription.java new file mode 100644 index 00000000000..d885d97fc93 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValues_ii/getvaluesii002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the getValues(int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public List getValues(int index, int length) + * Returns a range of array components. + * Parameters: index - the index of the first component to retrieve + * length - the number of components to retrieve, or -1 to + * retrieve all components to the end of this array. + * Returns: a list of Value objects, one for each requested array component + * ordered by array index. + * Throws: java.lang.IndexOutOfBoundsException - if index + length is an + * index beyond the end of this array. + * ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/getValues_ii/getvaluesii002 checks assertion: + * public Value getValues(int index, int length) + * 1. Returns a range of array components. + * Debuggee defines a number of array fields where component type is primitive + * types only. Each field has two more components then previous one. + * Debugger gets each field from debuggee by name, gets its value and casts + * it to ArrayReference. For i field debugger invokes method + * getValues(i, i + 1), that gets i + 1 components from index i. The debugger + * determines component's type (by field's name), gets each element of the + * list, casts it to correspondent PrimitiveType and then gets its primitive + * value. Then the test compares returned and expected primitive values. + * COMMENTS + * The method getValues(int, int) with length == 0 never invokes, because this + * situation is not clarified in the spec. One more test should cover this + * situation. + * 4419982: JDI: two StackFrame methods return incorrect values for double + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValues_ii.getvaluesii002 + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002a.java new file mode 100644 index 00000000000..6a0bcf0563a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002a.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvaluesii002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + getvaluesii002aClassToCheck classToCheck = new getvaluesii002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class getvaluesii002aClassToCheck { + + // Each field has two more components then previous + static boolean z1[] = {true}; + static byte b1[] = {Byte.MIN_VALUE, 0, Byte.MAX_VALUE}; + static char c1[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE, Character.MAX_VALUE}; + static int i1[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, + Integer.MIN_VALUE + 1, Integer.MAX_VALUE - 1}; + static long l1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE + 2, -2, 2, Long.MAX_VALUE - 2}; + static short r1[] = {Short.MIN_VALUE, -1, 0, 0, 1, Short.MAX_VALUE, + Short.MAX_VALUE - 1, 1, 1, 0, Short.MIN_VALUE}; + static double d1[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN, Double.NaN, -0, 0, 1}; + static float f1[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + 0, 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN, Float.NaN, 123456, 0, -123456, + Float.NaN, Float.NEGATIVE_INFINITY}; + + static final long lF1[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0}; + static private long lP1[] = {Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE, + Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE, + Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE, + Long.MAX_VALUE, -1, 0, 1, Long.MIN_VALUE}; + static public long lU1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, + Long.MAX_VALUE, Long.MIN_VALUE}; + static protected long lR1[] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + Long.MAX_VALUE, Long.MIN_VALUE, 0, 0}; + static transient long lT1[] = {Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MIN_VALUE, Long.MIN_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE - 1}; + static volatile long lV1[] = {Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MAX_VALUE, Long.MAX_VALUE, + Long.MIN_VALUE}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003.java new file mode 100644 index 00000000000..60c83e998b3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class getvaluesii003 { + final static int MIN_INDEX = -50; + final static int MAX_INDEX = 51; + final static String FIELD_NAME[][] = { + {"z1", "5"}, + {"b1", "5"}, + {"c1", "6"}, + {"d1", "1"}, + {"f1", "1"}, + {"i1", "10"}, + {"l1", "2"}, + {"r1", "5"}, + + {"lF1", "1"}, + {"lP1", "1"}, + {"lU1", "2"}, + {"lR1", "3"}, + {"lT1", "4"}, + {"lV1", "5"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.getValues_ii."; + private final static String className = "getvaluesii003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "getvaluesii003aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + Integer totalElements = new Integer(FIELD_NAME[i][1]); + int lastElementIndex = totalElements.intValue() - 1; + Value value; + ArrayReference arrayRef; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Try to get values by index from MIN_INDEX to -1 and from + // arrayRef.length() to MAX_INDEX, while length is 1 + for (int j = MIN_INDEX; j < MAX_INDEX; j++) { + if ( (j < 0) || (j > lastElementIndex) ) { + List listOfValues; + + try { + listOfValues = arrayRef.getValues(j, 1); + log.complain("debuger FAILURE 4> Values for " + j + + " element of field " + name + " is " + + listOfValues + ", but " + + "IndexOutOfBoundsException expected."); + testFailed = true; + } catch (ObjectCollectedException e) { + log.display("debuger> Cannot get " + j + " value from " + + "field " + name); + log.display("debuger> Exception: " + e); + testFailed = true; + } catch (IndexOutOfBoundsException e) { + // Index is always out of bounds, so + // IndexOutOfBoundsException is expected + log.display("debuger> " + i + " field: cannot get " + + "list of components from index " + j + + " with length 1. Expected exception: " + e); + } + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003/TestDescription.java new file mode 100644 index 00000000000..579d2eeea27 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValues_ii/getvaluesii003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the getValues(int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public List getValues(int index, int length) + * Returns a range of array components. + * Parameters: index - the index of the first component to retrieve + * length - the number of components to retrieve, or -1 to + * retrieve all components to the end of this array. + * Returns: a list of Value objects, one for each requested array component + * ordered by array index. + * Throws: java.lang.IndexOutOfBoundsException - if index + length is an + * index beyond the end of this array. + * ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/getValues_ii/getvaluesii003 checks assertion: + * public Value getValues(int index, int length) + * 1. IndexOutOfBoundsException is thrown, if the index is out of range of + * ArrayReference. Array has components of primitive types only. + * Debuggee defines a number of array fields which component type is primitive + * type only. Each array has at least one element. + * Debugger gets each field from debuggee by name, gets its value and casts it + * to ArrayReference. Then debugger tries to invoke the method getValues(j, 1) + * that gets one element forn index j. Index j is form MIN_INDEX to -1 and + * from last index to MAX_INDEX. For each index IndexOutOfBoundsException is + * expected. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValues_ii.getvaluesii003 + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003a.java new file mode 100644 index 00000000000..0c9d4da7e5a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvaluesii003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + getvaluesii003aClassToCheck classToCheck = new getvaluesii003aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class getvaluesii003aClassToCheck { + static boolean z1[] = {true, false, false, true, true}; + static byte b1[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + static char c1[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + '\u1234', '\u4321', Character.MAX_VALUE}; + static double d1[] = {Double.NEGATIVE_INFINITY}; + static float f1[] = {Float.POSITIVE_INFINITY}; + static int i1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; + static long l1[] = {Long.MIN_VALUE, Long.MAX_VALUE}; + static short r1[] = {-2, -1, 0, 1, 2}; + + static final long lF1[] = {Long.MAX_VALUE}; + static private long lP1[] = {0}; + static public long lU1[] = {1, 2}; + static protected long lR1[] = {1, 2, 3}; + static transient long lT1[] = {2, 3, 4, 5}; + static volatile long lV1[] = {2, 3, 4, 5, 6}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004.java new file mode 100644 index 00000000000..b24ffddbf08 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class getvaluesii004 { + final static int MIN_LENGTH = -50; + final static int MAX_LENGTH = 51; + final static String FIELD_NAME[][] = { + {"z1", "5"}, + {"b1", "5"}, + {"c1", "6"}, + {"d1", "1"}, + {"f1", "1"}, + {"i1", "10"}, + {"l1", "2"}, + {"r1", "5"}, + + {"lF1", "1"}, + {"lP1", "1"}, + {"lU1", "2"}, + {"lR1", "3"}, + {"lT1", "4"}, + {"lV1", "5"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.getValues_ii."; + private final static String className = "getvaluesii004"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "getvaluesii004aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + Integer lengthOfArray = new Integer(FIELD_NAME[i][1]); + int length = lengthOfArray.intValue(); + Value value; + ArrayReference arrayRef; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Try to get values from the first element with length + // from MIN_LENGTH to -2 (-1 is legal) and from arrayRef.length() + // to MAX_LENGTH + for (int j = MIN_LENGTH; j < MAX_LENGTH; j++) { + if ( (j < -1) || (j > length) ) { + List listOfValues; + + try { + listOfValues = arrayRef.getValues(0, j); + log.complain("debuger FAILURE 4> List of values of " + + "field " + name + " with length " + j + + " is " + listOfValues + ", but " + + "IndexOutOfBoundsException expected."); + testFailed = true; + } catch (ObjectCollectedException e) { + log.display("debuger FAILURE 5> Cannot get list of " + + "values with length " + j + " from field " + + name); + log.display("debuger FAILURE 5> Exception: " + e); + testFailed = true; + } catch (IndexOutOfBoundsException e) { + // Length is negative or too large, so + // IndexOutOfBoundsException is expected + log.display("debuger> " + i + " field: cannot get " + + "list of components with length " + j + + ". Expected exception: " + e); + } + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004/TestDescription.java new file mode 100644 index 00000000000..2edc4fee5af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValues_ii/getvaluesii004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the getValues(int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public List getValues(int index, int length) + * Returns a range of array components. + * Parameters: index - the index of the first component to retrieve + * length - the number of components to retrieve, or -1 to + * retrieve all components to the end of this array. + * Returns: a list of Value objects, one for each requested array component + * ordered by array index. + * Throws: java.lang.IndexOutOfBoundsException - if index + length is an + * index beyond the end of this array. + * ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/getValues_ii/getvaluesii004 checks assertion: + * public Value getValues(int index, int length) + * 1. IndexOutOfBoundsException is thrown, if the length is negative (except + * -1) or too large. Component type of array in debuggee is primitive. + * Debuggee defines a number of array fields which component type is primitive + * type only. Each array has at least one element. + * Debugger gets each field from debuggee by name, gets its value + * and casts it to ArrayReference. Then debugger tries to invoke the method + * getValues(0, i) that gets i elements form index i. Length is from + * MIN_LENGTH to -2 (-1 is legal) and from arrayRef.length() to MAX_LENGTH. + * IndexOutOfBoundsException is always expected. + * COMMENTS + * The method getValues(int, int) with length == 0 never invokes, because this + * situation is not clarified in the spec. One more test should cover this + * situation. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValues_ii.getvaluesii004 + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004a.java new file mode 100644 index 00000000000..c07b0ae7519 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvaluesii004a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + getvaluesii004aClassToCheck classToCheck = new getvaluesii004aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class getvaluesii004aClassToCheck { + static boolean z1[] = {true, false, false, true, true}; + static byte b1[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + static char c1[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + '\u1234', '\u4321', Character.MAX_VALUE}; + static double d1[] = {Double.NEGATIVE_INFINITY}; + static float f1[] = {Float.POSITIVE_INFINITY}; + static int i1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; + static long l1[] = {Long.MIN_VALUE, Long.MAX_VALUE}; + static short r1[] = {-2, -1, 0, 1, 2}; + + static final long lF1[] = {Long.MIN_VALUE}; + static private long lP1[] = {0}; + static public long lU1[] = {1, 2}; + static protected long lR1[] = {1, 2, 3}; + static transient long lT1[] = {2, 3, 4, 5}; + static volatile long lV1[] = {2, 3, 4, 5, 6}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005.java new file mode 100644 index 00000000000..b0dd52a77a4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005.java @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +/** The test cases include static and instance fields of int and Object types, + * which are one- and two- dimensional arrays (non-initialized arrays are + * considered as well). Values of the method parameter are presented as static + * two-dimensional array onto debuger, which includes the combinations of + * Integer.MAX_VALUE + 1, -1, 0, + * 1, Integer.MAX_VALUE.
    + * + * Expected results:
    + * - when index is 0 and length is -1, + * size of returned list has to be array length;
    + * - when index is 0 and length is 0, + * size if returned list has to be zero;
    + * - otherwise, IndexOutOfBoundsException is expected.
    + */ +public class getvaluesii005 { + + // exit code when test failed + public final static int TEST_FAILED = 2; + // exit code when test passed + public final static int TEST_PASSED = 0; + // shift of exit code + public final static int JCK_STATUS_BASE = 95; + + // parameters array to call com.sum.jdi.ArrayReference.getValues(int, int) + private static long[][] PARAM_ARRS = { + /* index */ /* length */ + {Integer.MAX_VALUE + 1, Integer.MAX_VALUE + 1}, + {Integer.MAX_VALUE + 1, -1}, + {Integer.MAX_VALUE + 1, 0}, + {Integer.MAX_VALUE + 1, 1}, + {Integer.MAX_VALUE + 1, Integer.MAX_VALUE}, + {-1, Integer.MAX_VALUE + 1}, + {-1, -1}, + {-1, 0}, + {-1, Integer.MAX_VALUE}, + {0, Integer.MAX_VALUE + 1}, + {0, -1}, + {0, 0}, + {0, Integer.MAX_VALUE}, + {Integer.MAX_VALUE, Integer.MAX_VALUE + 1}, + {Integer.MAX_VALUE, -1}, + {Integer.MAX_VALUE, 0}, + {Integer.MAX_VALUE, 1}, + {Integer.MAX_VALUE, Integer.MAX_VALUE} + }; + + private final static String prefix = "nsk.jdi.ArrayReference.getValues_ii."; + private final static String className = "getvaluesii005"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + + private int exitStatus; + private Log log; + private Debugee debugee; + private IOPipe pipe; + + public static void main(String argv[]) { + System.exit(JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + getvaluesii005 tstObj = new getvaluesii005(); + + if ( tstObj.prepareDebugee(argv, out) ) { + tstObj.execTest(); + tstObj.disposeOfDebugee(); + } + + if ( tstObj.exitStatus == TEST_FAILED ) + tstObj.complain("run:: TEST FAILED"); + else + tstObj.display("run:: TEST PASSED"); + return tstObj.exitStatus; + } + + private boolean prepareDebugee(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + display("prepareDebugee:: binder created."); + + debugee = binder.bindToDebugee(debugeeName); + log.display("prepareDebugee:: binded to debugee."); + pipe = debugee.createIOPipe(); + log.display("prepareDebugee:: pipe created."); + + debugee.redirectStderr(log,""); + debugee.resume(); + + String line = pipe.readln(); + if ( line == null ) { + complain("prepareDebugee:: UNEXPECTED debugee's signal - null"); + return false; + } + if ( !line.equals("ready") ) { + complain("prepareDebugee:: UNEXPECTED debugee's signal - " + + line); + return false; + } + + display("prepareDebugee:: debugee's \"ready\" signal received."); + return true; + } + + private boolean disposeOfDebugee() { + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + + if ( status != JCK_STATUS_BASE ) { + complain("disposeOfDebugee:: UNEXPECTED Debugee's exit " + + "status (not " + JCK_STATUS_BASE + ") - " + status); + return false; + } + display("disposeOfDebugee:: expected Debugee's exit " + + "status - " + status); + return true; + } + + private void display(String msg) { + if ( log != null ) + log.display("debugger> " + msg); + } + + private void complain(String msg) { + if ( log != null ) + log.complain("debugger FAILURE> " + msg); + } + + private boolean execTest() { + exitStatus = TEST_FAILED; + + ReferenceType refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("eventHandler:: Class '" + debugeeName + "' not found."); + return false; + } + + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("eventHandler:: Field '" + objectToCheck + "' not found."); + return false; + } + + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("eventHandler:: Field '" + objectToCheck + + "' not initialized."); + return false; + } + + return checkObjectFields(objectValue); + } + + public boolean checkObjectFields(Value objectValue) { + List fieldList; + if ( ! (objectValue instanceof ObjectReference) ) + return false; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + // Check all array fields from debugee + display("checkObjectFields:: Tests starts >>>"); + boolean res = true; + for (int i = 0; i < fieldList.size(); i++) { + res = checkFieldValue((ObjectReference )objectValue, + (Field )fieldList.get(i)) && res; + } + + exitStatus = res ? TEST_PASSED : TEST_FAILED; + return res; + } + + private boolean checkFieldValue(ObjectReference object, Field field) { + Value fieldValue; + ArrayReference arrayRef; + String fieldName = field.name(); + log.display(""); + display("checkObjectFields:: <" + fieldName + "> field is being " + + " checked."); + try { + fieldValue = object.getValue(field); + } catch (IllegalArgumentException e) { + complain("checkFieldValue:: can not get value for field " + fieldName); + complain("checkFieldValue:: " + e); + return false; + } + + display("checkFieldValue:: ***" + fieldName + " = " + fieldValue); + + // Tested object doesn't have non-initialized fields! + if ( fieldValue == null ) { + complain("checkFieldValue:: unexpected field value <" + + fieldValue + ">"); + return false; + } + + display("checkFieldValue:: *** type of " + fieldName + " = " + fieldValue.type()); + + // Checking up of value type. + // Tested object doesn't have other fields than be ArrayType + if ( ! (fieldValue.type() instanceof ArrayType) ) { + display("checkFieldValue:: type of value is not ArrayType."); + return false; + } + + boolean res = true; + + // Checking up of test cases. + for ( int i = 0; i < PARAM_ARRS.length; i++ ) { + res = checkValue(0, fieldName, (ArrayReference )fieldValue, + PARAM_ARRS[i][0], PARAM_ARRS[i][1]) && res; + } + return res; + } + + /** The metod returns the first item of the given ArrayReference + * as an array Value; or returns null if that item is + * not an array. + */ + private Value getFirstItemAsArray(ArrayReference arrayRef) { + Value itemValue = null; + try { + itemValue = arrayRef.getValue(0); + if ((itemValue != null) && !(itemValue.type() instanceof ArrayType)) + itemValue = null; + + } catch (IndexOutOfBoundsException e) { + } + return itemValue; + } + + private boolean checkValue(int depth, String name, ArrayReference arrayRef, + long index, long length) { + Value itemValue; + List list; + String il2Str = "for index=" + index + ", length=" + length; + int arrayLength = arrayRef.length(); + + itemValue = getFirstItemAsArray(arrayRef); + + if ( itemValue != null ) { + + // itemValue has array type, check it by the same way + long k = (arrayLength + 1 != index) ? index : + ((ArrayReference )itemValue).length() + 1; + if ( !checkValue(depth + 1, name, (ArrayReference )itemValue, k, length) ) + return false; + } + + try { + list = arrayRef.getValues((int )index, (int )length); + + if ( length == 0 ) { + + // expected list with zero-size + if ( list.size() != 0 ) + complain("checkValue[" + depth + "]:: List size is " + + list.size() + ", but list with zero-size " + + "expected " + il2Str); + else { + display("checkValue[" + depth + "]:: expected list zero-size " + + il2Str); + return true; + } + } else if ( length == -1 && index == 0 ) { + + // expected list size to be equal array length + if ( list.size() != arrayLength ) + complain("checkValue[" + depth + "]:: unexpected list size(" + + list.size() + ") != array length(" + + arrayLength + ") " + il2Str); + else { + display("checkValue[" + depth + "]:: expected list size(" + + list.size() + ") = array length(" + + arrayLength + ") " + il2Str); + return true; + } + } + + // ERR: IndexOutOfBoundsException was expected + complain("checkValue[" + depth + "]:: IndexOutOfBoundsException " + + "expected " + il2Str); + return false; + + } catch (IndexOutOfBoundsException e) { + + // checking specification conditions + if ( (index < 0 || index > arrayLength) || + ( (length != -1) && (length < 0 || index + length > arrayLength) ) ) { + display("checkValue[" + depth + "]:: expected IndexOutOfBoundsException " + + il2Str); + } else { + complain("checkValue[" + depth + "]:: unexpected IndexOutOfBoundsException " + + il2Str); + return false; + } + + } catch (Exception e) { + + complain("checkValue[" + depth + "]:: Unexpected exception: " + e); + return false; + } + return true; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005/TestDescription.java new file mode 100644 index 00000000000..30da601f592 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/getValues_ii/getvaluesii005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.ArrayReference.getValues(int, int) + * correctly works for the boundary value of parameter and complies with its + * spec: + * public List getValues(int index, + * int length) + * Returns a range of array components. + * Parameters: + * index - the index of the first component to retrieve + * length - the number of components to retrieve, or -1 to retrieve + * all components to the end of this array. + * Returns: + * a list of Value objects, one for each requested array component + * ordered by array index. When there are no elements in the specified + * range (e.g. length is zero) an empty list is returned + * Throws: + * IndexOutOfBoundsException - if the range specified with index and + * length is not within the range of the array, that is, if either + * of the following are true: + * index < 0 + * index > length() + * or if length != -1 and either of the following are true: + * length < 0 + * index + length > length() + * The test cases include static and instance fields of int and Object types, + * which are one- and two- dimensional arrays (non-initialized arrays are + * considered too). Values of the method parameter are presented as static + * two-dimensional array into debuger, which includes the combinations of + * Integer.MAX_VALUE + 1, -1, 0, 1, Integer.MAX_VALUE. + * Expected results: + * - when index is 0 and length is -1, size of returned list has to be array + * length; + * - when index is 0 and length is 0, size if returned list has to be zero; + * - otherwise, IndexOutOfBoundsException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayReference.getValues_ii.getvaluesii005; + * the debuggee program - nsk.jdi.ArrayReference.getValues_ii.getvaluesii005a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running on + * another JavaVM, establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies via the pipe. + * Upon getting reply, the debugger requests fields of checked object + * and trys to get a range of arry items correspondence with the test cases + * above. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.getValues_ii.getvaluesii005 + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.getValues_ii.getvaluesii005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005a.java new file mode 100644 index 00000000000..8eed353ca5b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii005a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.getValues_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class getvaluesii005a { + + static getvaluesii005aClassToCheck testedObj = new getvaluesii005aClassToCheck(); + + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(getvaluesii005.TEST_PASSED + getvaluesii005.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(getvaluesii005.TEST_FAILED + getvaluesii005.JCK_STATUS_BASE); + } +} + +class getvaluesii005aClassToCheck { + static int[] staticIntArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + static Object[] staticObjArr = {null, null, null, null, null, null, null, null, null, null}; + + static int[][] staticIntArr2 = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}; + + static int[][] staticIntArr0 = {{},{},{},{},{},{},{}}; + + public int[] publicIntArr0; + protected int[] protecIntArr0; + private int[] privatIntArr0; + + public int[] publicIntArrC; + protected int[] protecIntArrC; + private int[] privatIntArrC; + + public Object[] publicObjArr0; + protected Object[] protecObjArr0; + private Object[] privatObjArr0; + + public Object[] publicObjArrC; + protected Object[] protecObjArrC; + private Object[] privatObjArrC; + + public getvaluesii005aClassToCheck() { + publicIntArr0 = createIntArray(0); + protecIntArr0 = createIntArray(0); + privatIntArr0 = createIntArray(0); + + publicIntArrC = createIntArray(10); + protecIntArrC = createIntArray(10); + privatIntArrC = createIntArray(10); + + publicObjArr0 = createObjArray(0); + protecObjArr0 = createObjArray(0); + privatObjArr0 = createObjArray(0); + + publicObjArrC = createObjArray(10); + protecObjArrC = createObjArray(10); + privatObjArrC = createObjArray(10); + } + + static private int[] createIntArray(int length) { + int[] array = new int[length]; + for ( int i = 0; i < length; i++ ) array[i] = i; + return array; + } + + static private Object[] createObjArray(int length) { + Object[] array = new Object[length]; + return array; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001.java new file mode 100644 index 00000000000..bd714acb6a6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.length; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class length001 { + final static String FIELD_NAME[][] = { + {"z1", "0"}, + {"z2", "7"}, + {"b1", "1"}, + {"b2", "6"}, + {"c1", "2"}, + {"c2", "5"}, + {"d1", "3"}, + {"d2", "4"}, + {"f1", "4"}, + {"f2", "3"}, + {"i1", "5"}, + {"i2", "2"}, + {"l1", "6"}, + {"l2", "1"}, + {"r1", "7"}, + {"r2", "0"}, + + {"lF1", "3"}, + {"lP1", "3"}, + {"lU1", "2"}, + {"lR1", "2"}, + {"lT1", "1"}, + {"lV1", "1"}, + + {"E1", "0"}, + {"E2", "2"}, + {"X1", "1"}, + {"X2", "1"}, + {"O1", "2"}, + {"O2", "0"}, + + {"LF1", "3"}, + {"LP1", "3"}, + {"LU1", "2"}, + {"LR1", "2"}, + {"LT1", "1"}, + {"LV1", "1"}, + + {"EF1", "0"}, + {"EP1", "1"}, + {"EU1", "1"}, + {"ER1", "1"}, + {"ET1", "1"}, + {"EV1", "1"}, + }; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.length."; + private final static String className = "length001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "ClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String realLength = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + int length; + String lengthStr; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Get length of ArrayReference object + try { + length = arrayRef.length(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot get length for array " + + name); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field length is " + length); + lengthStr = realLength.valueOf(length); + + // Check array's length + if (!realLength.equals(lengthStr)) { + log.complain("debuger FAILURE 5> Length of array " + name + + " is " + length + ", but expected " + realLength); + testFailed = true; + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001/TestDescription.java new file mode 100644 index 00000000000..b807c2ffe0d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/length/length001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the length() method of ArrayReference interface of + * com.sun.jdi package. + * The method spec: + * public int length() + * Returns the number of components in this array. + * Returns: the integer count of components in this array. + * Throws: ObjectCollectedException - if this object has been garbage + * collected. + * nsk/jdi/ArrayReference/length/length001 checks assertion: + * public int length() + * 1. Returns the number of components in this array. + * Debuggee defines a number of array fields with component types: + * - primitive types, + * - interface type, + * - classes, + * - array of primitive types, + * - array of component types, + * - array of classes. + * Debugger gets each field from debuggee by name, gets field's value and + * casts it to ArrayReference. Then the test gets length of this object + * invoking the method length(). Debugger already knows the length of the + * array (FIELD_NAME defines it) and compares returned and expected lengths + * of the array. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.length.length001 + * nsk.jdi.ArrayReference.length.length001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.length.length001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001a.java new file mode 100644 index 00000000000..c7cb2f8a570 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001a.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.length; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class length001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + ClassToCheck classToCheck = new ClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class ClassToCheck { + // User class and interface + static class Class {} + static interface Inter {} + + static boolean z1[]={}; + static boolean z2[][]={z1, z1, z1, z1, z1, z1, z1}; + static byte b1[]={0}; + static byte b2[][]={b1, b1, b1, b1, b1, b1}; + static char c1[]={'\u00ff', '\u0f0f'}; + static char c2[][]={c1, c1, c1, c1, c1}; + static double d1[]={0, 1, -2}; + static double d2[][]={d1, d1, d1, d1}; + static float f1[]={0, 1, -2, 3}; + static float f2[][]={f1, f1, f1}; + static int i1[]={0, 1, -2, 3, -4}; + static int i2[][]={i1, i1}; + static long l1[]={0, 1, -2, 3, -4, 5}; + static long l2[][]={l1}; + static short r1[]={0, 1, -2, 3, -4, 5, -6}; + static short r2[][]={}; + + static final long lF1[]={1, -2, 3}; + static private long lP1[][]={{1}, {-2}, {3}}; + static public long lU1[][][]={{{1}}, {{-2}}}; + static protected long lR1[][][][]={{{{1}}}, {{{-2}}}}; + static transient long lT1[][][][][]={{{{{1}}}}}; + static volatile long lV1[][][][][][]={{{{{{1}}}}}}; + + static Inter E1[]={}; + static Inter E2[][]={E1, E1}; + static Class X1[]={new Class()}; + static Class X2[][]={X1}; + static Object O1[]={new Object(), new Object()}; + static Object O2[][]={}; + + static final Long LF1[]={new Long(1), new Long(-2), new Long(3)}; + static private Long LP1[][]={{new Long(1)}, {new Long(2)}, {new Long(3)}}; + static public Long LU1[][][]={{{new Long(1)}}, {{new Long(-2)}}}; + static protected Long LR1[][][][]={{{{new Long(1)}}}, {{{new Long(-2)}}}}; + static transient Long LT1[][][][][]={{{{{new Long(1)}}}}}; + static volatile Long LV1[][][][][][]={{{{{{new Long(1)}}}}}}; + + static final Inter EF1[]={}; + static private Inter EP1[][]={{}}; + static public Inter EU1[][][]={{{}}}; + static protected Inter ER1[][][][]={{{{}}}}; + static transient Inter ET1[][][][][]={{{{{}}}}}; + static volatile Inter EV1[][][][][][]={{{{{{}}}}}}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001.java new file mode 100644 index 00000000000..dac39a77154 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001.java @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class setvalue001 { + final static int HALF = 9; + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long"}, + {"lP1", "long"}, + {"lU1", "long"}, + {"lR1", "long"}, + {"lT1", "long"}, + {"lV1", "long"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.setValue."; + private final static String className = "setvalue001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvalue001aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String realType = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + for (int j = 0; j < HALF; j++) { + int indexSample = j + HALF; + Value sample; + Value valueNew; + + // Get Value from sample-area (9..17 elements) + try { + sample = arrayRef.getValue(indexSample); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot get " + indexSample + + " value from field " + name); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 4> Cannot get " + indexSample + + " value from field " + name); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: sample from index " + + indexSample + " is " + sample); + + // Set the Sample to the correspondent index + // Any exception means that the test fails + try { + arrayRef.setValue(j, sample); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set value " + sample + + " to " + j + " index of field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 5> Cannot set value " + sample + + " to " + j + " index of field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set value " + sample + + " to " + j + " index of field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set value " + sample + + " to " + j + " index of field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set value " + sample + + " to " + j + " index of field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: sample " + sample + + " has been set to index " + j); + + + // Get the Value from the correspondent index + try { + valueNew = arrayRef.getValue(j); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 6> Cannot get " + j + " value" + + " from field " + name); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 6> Cannot get " + j + " value" + + " from field " + name); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: element from index " + j + + " is " + valueNew); + + // Check the Value that has been read with the sample + if (realType.equals("boolean")) { + + ///////////////////// Check boolean[] ///////////////////// + BooleanValue boolValue; + boolean boolSample; + boolean boolNew; + + // Cast sample and read Value to primitive type + try { + boolValue = (BooleanValue)sample; + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z1> Cannot cast to " + + "boolean sample."); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + boolSample = boolValue.value(); + try { + boolValue = (BooleanValue)valueNew; + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z2> Cannot cast to " + + "boolean read value."); + log.complain("debuger FAILURE Z2> Exception: " + e); + testFailed = true; + continue; + } + boolNew = boolValue.value(); + + // Check two primitive values + if (boolNew != boolSample) { + log.complain("debuger FAILURE Z3> " + j + " element " + + "of array " + name + " was expected " + + boolSample + ", but returned " + boolNew); + testFailed = true; + } else { + log.display("debuger> " + i + " field: primitive " + + "sample is " + boolSample + ", primitive " + + " read value is " + boolNew); + } + } else if (realType.equals("byte")) { + + ///////////////////// Check byte[] ///////////////////// + ByteValue byteValue; + byte byteSample; + byte byteNew; + + // Cast sample and read Value to primitive type + try { + byteValue = (ByteValue)sample; + } catch (ClassCastException e) { + log.complain("debuger FAILURE B1> Cannot cast to " + + "byte sample."); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + byteSample = byteValue.value(); + try { + byteValue = (ByteValue)valueNew; + } catch (ClassCastException e) { + log.complain("debuger FAILURE B2> Cannot cast to " + + "byte read value."); + log.complain("debuger FAILURE B2> Exception: " + e); + testFailed = true; + continue; + } + byteNew = byteValue.value(); + + // Check two primitive values + if (byteNew != byteSample) { + log.complain("debuger FAILURE B3> " + j + " element " + + "of array " + name + " was expected " + + byteSample + ", but returned " + byteNew); + testFailed = true; + } else { + log.display("debuger> " + i + " field: primitive " + + "sample is " + byteSample + ", primitive " + + "read value is " + byteNew); + } + } else if (realType.equals("char")) { + + ///////////////////// Check char[] ///////////////////// + CharValue charValue; + char charSample; + char charNew; + + // Cast sample and read Value to primitive type + try { + charValue = (CharValue)sample; + } catch (ClassCastException e) { + log.complain("debuger FAILURE C1> Cannot cast to " + + "char sample."); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + charSample = charValue.value(); + try { + charValue = (CharValue)valueNew; + } catch (ClassCastException e) { + log.complain("debuger FAILURE C2> Cannot cast to " + + "char read value."); + log.complain("debuger FAILURE C2> Exception: " + e); + testFailed = true; + continue; + } + charNew = charValue.value(); + + // Check two primitive values + if (charNew != charSample) { + log.complain("debuger FAILURE C3> " + j + " element " + + "of array " + name + " was expected " + + charSample + ", but returned " + charNew); + testFailed = true; + } else { + log.display("debuger> " + i + " field: primitive " + + "sample is " + charSample + ", primitive " + + "read value is " + charNew); + } + } else if (realType.equals("int")) { + + ///////////////////// Check int[] ///////////////////// + IntegerValue intValue; + int intSample; + int intNew; + + // Cast sample and read Value to primitive type + try { + intValue = (IntegerValue)sample; + } catch (ClassCastException e) { + log.complain("debuger FAILURE I1> Cannot cast to " + + "int sample."); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + intSample = intValue.value(); + try { + intValue = (IntegerValue)valueNew; + } catch (ClassCastException e) { + log.complain("debuger FAILURE I2> Cannot cast to " + + "int read value."); + log.complain("debuger FAILURE I2> Exception: " + e); + testFailed = true; + continue; + } + intNew = intValue.value(); + + // Check two primitive values + if (intNew != intSample) { + log.complain("debuger FAILURE I3> " + j + " element " + + "of array " + name + " was expected " + + intSample + ", but returned " + intNew); + testFailed = true; + } else { + log.display("debuger> " + i + " field: primitive " + + "sample is " + intSample + ", primitive " + + "read value is " + intNew); + } + } else if (realType.equals("long")) { + + ///////////////////// Check long[] ///////////////////// + LongValue longValue; + long longSample; + long longNew; + + // Cast sample and read Value to primitive type + try { + longValue = (LongValue)sample; + } catch (ClassCastException e) { + log.complain("debuger FAILURE L1> Cannot cast to " + + "long sample."); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + longSample = longValue.value(); + try { + longValue = (LongValue)valueNew; + } catch (ClassCastException e) { + log.complain("debuger FAILURE L2> Cannot cast to " + + "long read value."); + log.complain("debuger FAILURE L2> Exception: " + e); + testFailed = true; + continue; + } + longNew = longValue.value(); + + // Check two primitive values + if (longNew != longSample) { + log.complain("debuger FAILURE L3> " + j + " element " + + "of array " + name + " was expected " + + longSample + ", but returned " + longNew); + testFailed = true; + } else { + log.display("debuger> " + i + " field: primitive " + + "sample is " + longSample + ", primitive " + + "read value is " + longNew); + } + } else if (realType.equals("short")) { + + ///////////////////// Check short[] ///////////////////// + ShortValue shortValue; + short shortSample; + short shortNew; + + // Cast sample and read Value to primitive type + try { + shortValue = (ShortValue)sample; + } catch (ClassCastException e) { + log.complain("debuger FAILURE R1> Cannot cast to " + + "short sample."); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + shortSample = shortValue.value(); + try { + shortValue = (ShortValue)valueNew; + } catch (ClassCastException e) { + log.complain("debuger FAILURE R2> Cannot cast to " + + "short read value."); + log.complain("debuger FAILURE R2> Exception: " + e); + testFailed = true; + continue; + } + shortNew = shortValue.value(); + + // Check two primitive values + if (shortNew != shortSample) { + log.complain("debuger FAILURE R3> " + j + " element " + + "of array " + name + " was expected " + + shortSample + ", but returned " + + shortNew); + testFailed = true; + } else { + log.display("debuger> " + i + " field: primitive " + + "sample is " + shortSample + ", primitive " + + "read value is " + shortNew); + } + } else if (realType.equals("double")) { + + ///////////////////// Check double[] ///////////////////// + DoubleValue dblValue; + Double dblSample; + Double dblNew; + + // Cast sample and read Value to primitive type + try { + dblValue = (DoubleValue)sample; + } catch (ClassCastException e) { + log.complain("debuger FAILURE D1> Cannot cast to " + + "double sample."); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + dblSample = new Double(dblValue.value()); + try { + dblValue = (DoubleValue)valueNew; + } catch (ClassCastException e) { + log.complain("debuger FAILURE D2> Cannot cast to " + + "double read value."); + log.complain("debuger FAILURE D2> Exception: " + e); + testFailed = true; + continue; + } + dblNew = new Double(dblValue.value()); + + // Check two primitive values + if (!dblNew.equals(dblSample)) { + log.complain("debuger FAILURE D3> " + j + " element " + + "of array " + name + " was expected " + + dblSample + ", but returned " + dblNew); + testFailed = true; + } else { + log.display("debuger> " + i + " field: primitive " + + "sample is " + dblSample + ", primitive " + + "read value is " + dblNew); + } + } else if (realType.equals("float")) { + + ///////////////////// Check float[] ///////////////////// + FloatValue fltValue; + Float fltSample; + Float fltNew; + + // Cast sample and read Value to primitive type + try { + fltValue = (FloatValue)sample; + } catch (ClassCastException e) { + log.complain("debuger FAILURE F1> Cannot cast to " + + "float sample."); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + fltSample = new Float(fltValue.value()); + try { + fltValue = (FloatValue)valueNew; + } catch (ClassCastException e) { + log.complain("debuger FAILURE F2> Cannot cast to " + + "float read value."); + log.complain("debuger FAILURE F2> Exception: " + e); + testFailed = true; + continue; + } + fltNew = new Float(fltValue.value()); + + // Check two primitive values + if (!fltNew.equals(fltSample)) { + log.complain("debuger FAILURE F3> " + j + " element " + + "of array " + name + " was expected " + + fltSample + ", but returned " + fltNew); + testFailed = true; + } else { + log.display("debuger> " + i + " field: primitive " + + "sample is " + fltSample + ", primitive " + + "read value is " + fltNew); + } + } else { + log.complain("debuger FAILURE 6> Unexpected type: " + + realType); + testFailed = true; + break; + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001/TestDescription.java new file mode 100644 index 00000000000..4628f356f84 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001/TestDescription.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValue/setvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValue(int, Value) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public void setValue(int index, Value value) throws InvalidTypeException, + * ClassNotLoadedException + * Replaces an array component with another value. + * Object values must be assignment compatible with the component type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: value - the new value + * index - the index of the component to set + * Throws: java.lang.IndexOutOfBoundsException - if index is beyond the end of + * this array. + * InvalidTypeException - if the type value is not compatible with the + * declared type of array components. + * ClassNotLoadedException - if the array component type has not yet + * been loaded through the appropriate class loader. + * ObjectCollectedException - if this object or the new value has been + * garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValue/setvalue001 checks assertion: + * public void setValue(int index, Value value) + * 1. Replaces an array component with another value. Array has components of + * primitive types only, index is in array bounds. + * Debuggee defines a number of array fields which component type is primitive + * type only. Each array has 18 components. + * Debugger gets each field from debuggee by name, gets its value and casts it + * to ArrayReference. Then debugger for each field does the following. + * The test gets elements from indexes 8, 9, 10, ..., 17 and sets them to + * 0, 1, 2, ..., 7 indexes of the same ArrayReference. And then checks values + * in the array (0, ..., 7). Debugger gets tested elements from the array, + * casts it to correspondent PrimitiveType and gets its primitive value. This + * value is compared with expected. + * COMMENTS + * 4419982: JDI: two StackFrame methods return incorrect values for double + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValue.setvalue001 + * nsk.jdi.ArrayReference.setValue.setvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValue.setvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001a.java new file mode 100644 index 00000000000..2869f6b04e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvalue001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvalue001aClassToCheck classToCheck = new setvalue001aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvalue001aClassToCheck { + + // Each array has 18 components + // 0..8 are to set and get values, 9..17 are to get sample Value in + // debugger + static boolean z1[] = {false, true, false, true, true, true, false, + false, true, + true, false, true, false, false, false, true, + true, false}; + static byte b1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE + 1, -4, 4, Byte.MAX_VALUE - 1}; + static char c1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE, Character.MIN_VALUE + 1, + '\u1234', '\u4321', '\u8888', + Character.MAX_VALUE - 1}; + static double d1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN}; + static float f1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + 0, 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN}; + static int i1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, + Integer.MIN_VALUE + 1, -2, 2, Integer.MAX_VALUE - 1}; + static long l1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE + 1, -2, 2, Long.MAX_VALUE - 1}; + static short r1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + Short.MIN_VALUE + 1, -3, 3, Short.MAX_VALUE - 1}; + + static final long lF1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, 9}; + static private long lP1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + 100, 101, 102, 103, 104, 105, 106, 107, 108}; + static public long lU1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + -1, -2, -3, -4, -5, -6, -7, -8, -9}; + static protected long lR1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Long.MIN_VALUE, Long.MIN_VALUE + 1, + Long.MIN_VALUE + 2, Long.MIN_VALUE + 3, + Long.MIN_VALUE + 4, Long.MIN_VALUE + 5, + Long.MIN_VALUE + 6, Long.MIN_VALUE + 7, + Long.MIN_VALUE + 8}; + static transient long lT1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + Long.MAX_VALUE, Long.MAX_VALUE - 1, + Long.MAX_VALUE - 2, Long.MAX_VALUE - 3, + Long.MAX_VALUE - 4, Long.MAX_VALUE - 5, + Long.MAX_VALUE - 6, Long.MAX_VALUE - 7, + Long.MAX_VALUE - 8}; + static volatile long lV1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + 1, -1, 1, 0, -1, 1, 0, -1, 1}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002.java new file mode 100644 index 00000000000..66ace08d1c8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class setvalue002 { + final static int MIN_INDEX = -50; + final static int MAX_INDEX = 51; + final static String FIELD_NAME[][] = { + {"z1", "5", "boolean"}, + {"b1", "5", "byte"}, + {"c1", "6", "char"}, + {"d1", "1", "double"}, + {"f1", "1", "float"}, + {"i1", "10", "int"}, + {"l1", "2", "long"}, + {"r1", "5", "short"}, + + {"lF1", "0", "long"}, + {"lP1", "2", "long"}, + {"lU1", "3", "long"}, + {"lR1", "4", "long"}, + {"lT1", "5", "long"}, + {"lV1", "6", "long"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.setValue."; + private final static String className = "setvalue002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvalue002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + Field fieldBoolean = null; + Field fieldByte = null; + Field fieldChar = null; + Field fieldDouble = null; + Field fieldFloat = null; + Field fieldInt = null; + Field fieldLong = null; + Field fieldShort = null; + Value valueBoolean = null; + Value valueByte = null; + Value valueChar = null; + Value valueDouble = null; + Value valueFloat = null; + Value valueInt = null; + Value valueLong = null; + Value valueShort = null; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Get all samples of primitive types Values to set it to the + // ArrayReference + try { + fieldBoolean = refType.fieldByName("z"); + fieldByte = refType.fieldByName("b"); + fieldChar = refType.fieldByName("c"); + fieldDouble = refType.fieldByName("d"); + fieldFloat = refType.fieldByName("f"); + fieldInt = refType.fieldByName("i"); + fieldLong = refType.fieldByName("l"); + fieldShort = refType.fieldByName("r"); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample fields for primitive types."); + log.display("debuger> boolean is " + fieldBoolean); + log.display("debuger> byte is " + fieldByte); + log.display("debuger> char is " + fieldChar); + log.display("debuger> double is " + fieldDouble); + log.display("debuger> float is " + fieldFloat); + log.display("debuger> int is " + fieldInt); + log.display("debuger> long is " + fieldLong); + log.display("debuger> short is " + fieldShort + "\n"); + + if ((fieldBoolean == null) || (fieldByte == null) || + (fieldChar == null) || (fieldDouble == null) || + (fieldFloat == null) || (fieldInt == null) || + (fieldLong == null) || (fieldShort == null)) { + log.complain("debuger FAILURE> Cannot find field in debuggee."); + return 2; + } + + try { + valueBoolean = refType.getValue(fieldBoolean); + valueByte = refType.getValue(fieldByte); + valueChar = refType.getValue(fieldChar); + valueDouble = refType.getValue(fieldDouble); + valueFloat = refType.getValue(fieldFloat); + valueInt = refType.getValue(fieldInt); + valueLong = refType.getValue(fieldLong); + valueShort = refType.getValue(fieldShort); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample values for primitive types."); + log.display("debuger> boolean is " + valueBoolean); + log.display("debuger> byte is " + valueByte); + log.display("debuger> char is " + valueChar); + log.display("debuger> double is " + valueDouble); + log.display("debuger> float is " + valueFloat); + log.display("debuger> int is " + valueInt); + log.display("debuger> long is " + valueLong); + log.display("debuger> short is " + valueShort + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + Integer totalElements = new Integer(FIELD_NAME[i][1]); + String type = FIELD_NAME[i][2]; + int lastElementIndex = totalElements.intValue() - 1; + Value value; + ArrayReference arrayRef; + Value valueToSet; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Prepare Value to set + if (type.equals("boolean")) { + valueToSet = (Value)valueBoolean; + } else if (type.equals("byte")) { + valueToSet = (Value)valueByte; + } else if (type.equals("char")) { + valueToSet = (Value)valueChar; + } else if (type.equals("double")) { + valueToSet = (Value)valueDouble; + } else if (type.equals("float")) { + valueToSet = (Value)valueFloat; + } else if (type.equals("int")) { + valueToSet = (Value)valueInt; + } else if (type.equals("long")) { + valueToSet = (Value)valueLong; + } else if (type.equals("short")) { + valueToSet = (Value)valueShort; + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + type); + testFailed = true; + continue; + } + + // Try to set value by index from MIN_INDEX to -1 and from + // arrayRef.length() to MAX_INDEX + for (int j = MIN_INDEX; j < MAX_INDEX; j++) { + if ( (j < 0) || (j > lastElementIndex) ) { + + // Set the Value, IndexOutOfBoundsException is expected + try { + arrayRef.setValue(j, valueToSet); + log.complain("debuger FAILURE 5> IndexOutOfBoundsException" + + "is not thrown. "); + testFailed = true; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set value " + + valueToSet + " to " + j + " index of " + + "field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + } catch (IndexOutOfBoundsException e) { + log.display("debuger> " + i + " field: cannot set " + + "value " + valueToSet + " with index " + + j + ". Expected exception: " + e); + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set value " + + valueToSet + " to " + j + " index of " + + "field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set value " + + valueToSet + " to " + j + " index of " + + "field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set value " + + valueToSet + " to " + j + " index of " + + "field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + } + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002/TestDescription.java new file mode 100644 index 00000000000..72913a5f525 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValue/setvalue002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValue(int, Value) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public void setValue(int index, Value value) throws InvalidTypeException, + * ClassNotLoadedException + * Replaces an array component with another value. + * Object values must be assignment compatible with the component type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: value - the new value + * index - the index of the component to set + * Throws: java.lang.IndexOutOfBoundsException - if index is beyond the end of + * this array. + * InvalidTypeException - if the type value is not compatible with the + * declared type of array components. + * ClassNotLoadedException - if the array component type has not yet + * been loaded through the appropriate class loader. + * ObjectCollectedException - if this object or the new value has been + * garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValue/setvalue002 checks assertion: + * public void setValue(int index, Value value) + * 1. IndexOutOfBoundsException is thrown if index is out of bounds of this + * array. Array has components of primitive types only. + * Debuggee defines eight sample fields of primitive types. Also it defines + * a number of tested array fields which component type is primitive type only. + * Those arrays have different lengths. + * Debugger gets each sample field from debuggee by name and gets its + * PrimitiveValue. After that the test gets tested array fields by name, gets + * their values, casts to ArrayReference types. And then sets sample values + * to the correspondent tested arrays invoking the method + * setValues(int, Value). Index is from MIN_INDEX to -1 and from + * arrayRef.length() to MAX_INDEX, so IndexOutOfBoundsException is expected. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValue.setvalue002 + * nsk.jdi.ArrayReference.setValue.setvalue002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValue.setvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002a.java new file mode 100644 index 00000000000..8caf2f4db64 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002a.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvalue002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvalue002aClassToCheck classToCheck = new setvalue002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvalue002aClassToCheck { + + // Samples + static boolean z = true; + static byte b = (byte)1; + static char c = '\uff00'; + static double d = -1; + static float f = 2; + static int i = -3; + static long l = 4; + static short r = -5; + + // Arrays + static boolean z1[] = {true, false, false, true, true}; + static byte b1[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + static char c1[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + '\u1234', '\u4321', Character.MAX_VALUE}; + static double d1[] = {Double.NEGATIVE_INFINITY}; + static float f1[] = {Float.POSITIVE_INFINITY}; + static int i1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; + static long l1[] = {Long.MIN_VALUE, Long.MAX_VALUE}; + static short r1[] = {-2, -1, 0, 1, 2}; + + static final long lF1[] = {}; + static private long lP1[] = {-1, 0}; + static public long lU1[] = {0, 1, 2}; + static protected long lR1[] = {0, 1, 2, 3}; + static transient long lT1[] = {1, 2, 3, 4, 5}; + static volatile long lV1[] = {1, 2, 3, 4, 5, 6}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003.java new file mode 100644 index 00000000000..e9a22291b24 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvalue003 { + + // exit code when test failed + public final static int TEST_FAILED = 2; + // exit code when test passed + public final static int TEST_PASSED = 0; + // shift of exit code + public final static int JCK_STATUS_BASE = 95; + + // parameters arrays to call com.sum.jdi.ArrayReference.setValue(int, Value) + private static long[] INDEX_PARAM = { Integer.MAX_VALUE + 1, + -1, + 0, + Integer.MAX_VALUE + }; + private final static String BYTE_VALUES_FIELD = "BYTE_VALUE_PARAM"; + private final static String CHAR_VALUES_FIELD = "CHAR_VALUE_PARAM"; + private final static String DBL_VALUES_FIELD = "DBL_VALUE_PARAM"; + private final static String FLT_VALUES_FIELD = "FLT_VALUE_PARAM"; + private final static String INT_VALUES_FIELD = "INT_VALUE_PARAM"; + private final static String LNG_VALUES_FIELD = "LNG_VALUE_PARAM"; + private final static String SHORT_VALUES_FIELD= "SHORT_VALUE_PARAM"; + + private final static String prefix = "nsk.jdi.ArrayReference.setValue."; + private final static String className = "setvalue003"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + + private int exitStatus; + private Log log; + private Debugee debugee; + private IOPipe pipe; + private ReferenceType refType; + + public static void main(String argv[]) { + System.exit(JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + setvalue003 tstObj = new setvalue003(); + + if ( tstObj.prepareDebugee(argv, out) ) { + tstObj.execTest(); + tstObj.disposeOfDebugee(); + } + + if ( tstObj.exitStatus == TEST_FAILED ) + tstObj.complain("run:: TEST FAILED"); + else + tstObj.display("run:: TEST PASSED"); + return tstObj.exitStatus; + } + + private boolean prepareDebugee(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + display("prepareDebugee:: binder created."); + + debugee = binder.bindToDebugee(debugeeName); + log.display("prepareDebugee:: binded to debugee."); + pipe = debugee.createIOPipe(); + log.display("prepareDebugee:: pipe created."); + + debugee.redirectStderr(out); + debugee.resume(); + + String line = pipe.readln(); + if ( line == null ) { + complain("prepareDebugee:: UNEXPECTED debugee's signal - null"); + return false; + } + if ( !line.equals("ready") ) { + complain("prepareDebugee:: UNEXPECTED debugee's signal - " + + line); + return false; + } + + display("prepareDebugee:: debugee's \"ready\" signal received."); + return true; + } + + private boolean disposeOfDebugee() { + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + + if ( status != JCK_STATUS_BASE ) { + complain("disposeOfDebugee:: UNEXPECTED Debugee's exit " + + "status (not " + JCK_STATUS_BASE + ") - " + status); + return false; + } + display("disposeOfDebugee:: expected Debugee's exit " + + "status - " + status); + return true; + } + + private void display(String msg) { + if ( log != null ) + log.display("debugger> " + msg); + } + + private void complain(String msg) { + if ( log != null ) + log.complain("debugger FAILURE> " + msg); + } + + private boolean execTest() { + exitStatus = TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("eventHandler:: Class '" + debugeeName + "' not found."); + return false; + } + + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("eventHandler:: Field '" + objectToCheck + "' not found."); + return false; + } + + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("eventHandler:: Field '" + objectToCheck + + "' not initialized."); + return false; + } + + return checkObjectFields(objectValue); + } + + public boolean checkObjectFields(Value objectValue) { + List fieldList; + if ( ! (objectValue instanceof ObjectReference) ) + return false; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + // Check all array fields from debugee + display("checkObjectFields:: Tests starts >>>"); + boolean res = true; + for (int i = 0; i < fieldList.size(); i++) { + res = checkFieldValue((ObjectReference )objectValue, + (Field )fieldList.get(i)) && res; + } + + exitStatus = res ? TEST_PASSED : TEST_FAILED; + return res; + } + + private boolean checkFieldValue(ObjectReference object, Field field) { + Value fieldValue; + ArrayReference arrayRef; + String fieldName = field.name(); + log.display(""); + display("<" + fieldName + "> field is being checked."); + try { + fieldValue = object.getValue(field); + } catch (IllegalArgumentException e) { + complain("checkFieldValue:: can not get value for field " + fieldName); + complain("checkFieldValue:: " + e); + return false; + } + + display("***" + fieldName + " = " + fieldValue); + + // Tested object doesn't have non-initialized fields! + if ( fieldValue == null ) { + complain("unexpected field value <" + + fieldValue + ">"); + return false; + } + + display("*** type of " + fieldName + " = " + fieldValue.type()); + + // Checking up of value type. + // Tested object doesn't have other fields than be ArrayType + if ( ! (fieldValue.type() instanceof ArrayType) ) { + display("type of value is not ArrayType."); + return false; + } + + boolean res = true; + + Type itemType; + try { + itemType = ((ArrayType )fieldValue.type()).componentType(); + } catch(Exception e) { + complain("Unexpected " + e.getClass().getName() ); + return false; + } + + // getting value to set from debugee with defined type + Field fieldOfValues = null; + if ( itemType instanceof ByteType ) { + fieldOfValues = refType.fieldByName(BYTE_VALUES_FIELD); + if ( fieldOfValues == null ) { + complain("Field '" + BYTE_VALUES_FIELD + "' not found."); + return false; + } + } else if ( itemType instanceof CharType ) { + fieldOfValues = refType.fieldByName(CHAR_VALUES_FIELD); + if ( fieldOfValues == null ) { + complain("Field '" + CHAR_VALUES_FIELD + "' not found."); + return false; + } + } else if ( itemType instanceof DoubleType ) { + fieldOfValues = refType.fieldByName(DBL_VALUES_FIELD); + if ( fieldOfValues == null ) { + complain("Field '" + DBL_VALUES_FIELD + "' not found."); + return false; + } + } else if ( itemType instanceof FloatType ) { + fieldOfValues = refType.fieldByName(FLT_VALUES_FIELD); + if ( fieldOfValues == null ) { + complain("Field '" + FLT_VALUES_FIELD + "' not found."); + return false; + } + } else if ( itemType instanceof IntegerType ) { + fieldOfValues = refType.fieldByName(INT_VALUES_FIELD); + if ( fieldOfValues == null ) { + complain("Field '" + INT_VALUES_FIELD + "' not found."); + return false; + } + } else if ( itemType instanceof LongType ) { + fieldOfValues = refType.fieldByName(LNG_VALUES_FIELD); + if ( fieldOfValues == null ) { + complain("Field '" + LNG_VALUES_FIELD + "' not found."); + return false; + } + } else if ( itemType instanceof ShortType ) { + fieldOfValues = refType.fieldByName(SHORT_VALUES_FIELD); + if ( fieldOfValues == null ) { + complain("Field '" + SHORT_VALUES_FIELD + "' not found."); + return false; + } + } + + ArrayReference values = (ArrayReference )refType.getValue(fieldOfValues); + + // Checking up of test cases. + for ( int i = 0; i < INDEX_PARAM.length; i++ ) { + for ( int j = 0; j < values.length(); j++ ) { + res = checkValueUpdating(fieldName, + (ArrayReference )fieldValue, INDEX_PARAM[i], + values.getValue(j)) && res; + } + } + return res; + } + + private boolean checkValueUpdating(String name, + ArrayReference arrayRef, long index, Value value) { + Value itemValue; + List list; + String il2Str = "for index=" + index + " value=" + value; + int arrayLength = arrayRef.length(); + + try { + arrayRef.setValue((int )index, value); + Value v1 = arrayRef.getValue((int )index); + + if ( !value.equals(v1) ) { + complain("not correct value " + v1 + + " " + il2Str); + return false; + } + + if ( index < 0 || index >= arrayLength ) { + complain("IndexOutOfBoundsException is expected " + il2Str); + return false; + } else { + display("Value " + v1 + " is set " + il2Str); + } + + } catch (IndexOutOfBoundsException e) { + + // checking specification conditions + if ( index < 0 || index >= arrayLength ) { + display("expected IndexOutOfBoundsException " + + il2Str); + } else { + complain("unexpected IndexOutOfBoundsException " + + il2Str); + return false; + } + + } catch (Exception e) { + complain("Unexpected exception: " + + e + " " + il2Str); + return false; + } + return true; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003/TestDescription.java new file mode 100644 index 00000000000..50fb25695b2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003/TestDescription.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValue/setvalue003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.ArrayReference.setValue(int, Value) + * correctly works for the boundary value of parameter and complies with its + * spec: + * public void setValue(int index, Value value) + * throws InvalidTypeException, + * ClassNotLoadedException + * Replaces an array component with another value. + * Object values must be assignment compatible with the component type + * (This implies that the component type must be loaded through the + * declaring class's class loader). Primitive values must be either + * assignment compatible with the component type or must be + * convertible to the component type without loss of information. See + * JLS section 5.2 for more information on assignment compatibility. + * Parameters: + * value - the new value + * index - the index of the component to set + * Throws: + * IndexOutOfBoundsException - if index is outside the range of this + * array, that is, if either of the following are true: + * index < 0 + * index >= length() + * InvalidTypeException - if the type of value is not compatible with + * the declared type of array components. + * ClassNotLoadedException - if the array component type has not yet + * been loaded through the appropriate class loader. + * The test cases include instance fields of the primitive types, which are + * one-dimensional arrays. Possible values of parameter of the method + * are presented as static array at the debugee part for each primitive types. + * These values include boundary values of each primitive types. Possible + * values of parameter are presented as static array at the debuger + * part. + * Expected results: + * for every values of parameter the method has to work without any + * errors, except of cases when either index < 0 or index >= length(). + * The test works as follows: + * The debugger program - nsk.jdi.ArrayReference.setValue.setvalue003; + * the debuggee program - nsk.jdi.ArrayReference.setValue.setvalue003a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running on + * another JavaVM, establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies via the pipe. + * Upon getting reply, the debugger requests fields of checked object + * and trys to set a value of arry items correspondence with the test cases + * above. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValue.setvalue003 + * nsk.jdi.ArrayReference.setValue.setvalue003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValue.setvalue003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003a.java new file mode 100644 index 00000000000..66d83816ade --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvalue003a { + + static setvalue003aClassToCheck testedObj = new setvalue003aClassToCheck(); + + // Value parameter's array for debugee's int-arrays + public static byte[] BYTE_VALUE_PARAM = { Byte.MIN_VALUE, + Byte.MAX_VALUE + }; + + public static char[] CHAR_VALUE_PARAM = { Character.MIN_VALUE, + Character.MAX_VALUE + }; + + public static double[] DBL_VALUE_PARAM = { Double.MIN_VALUE, + Double.MAX_VALUE, + Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY + }; + + public static float[] FLT_VALUE_PARAM = { Float.MIN_VALUE, + Float.MAX_VALUE, + Float.NEGATIVE_INFINITY, + Float.POSITIVE_INFINITY + }; + + public static int[] INT_VALUE_PARAM = { Integer.MIN_VALUE, + Integer.MAX_VALUE + }; + + public static long[] LNG_VALUE_PARAM = { Long.MIN_VALUE, + Long.MAX_VALUE + }; + + public static short[] SHORT_VALUE_PARAM = { Short.MIN_VALUE, + Short.MAX_VALUE + }; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(setvalue003.TEST_PASSED + setvalue003.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(setvalue003.TEST_FAILED + setvalue003.JCK_STATUS_BASE); + } +} + +class setvalue003aClassToCheck { + public byte[] publicByteArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected byte[] protecByteArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private byte[] privatByteArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public char[] publicCharArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + protected char[] protecCharArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + private char[] privatCharArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + + public double[] publicDoubleArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected double[] protecDoubleArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private double[] privatDoubleArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public float[] publicFloatArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected float[] protecFloatArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private float[] privatFloatArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public int[] publicIntArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected int[] protecIntArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private int[] privatIntArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public long[] publicLongArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected long[] protecLongArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private long[] privatLongArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public short[] publicShortArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected short[] protecShortArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private short[] privatShortArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001.java new file mode 100644 index 00000000000..bd3d891451b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001.java @@ -0,0 +1,874 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvaluesilii001 { + final static int LENGTH = 14; + final static String FIELD_NAME[][] = { + {"d1", "double"}, + {"f1", "float"}, + {"b1", "byte"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + {"c1", "char"}, + {"z1", "boolean"}, + + {"lF1", "long_final"}, + {"lP1", "long_private"}, + {"lU1", "long_public"}, + {"lR1", "long_protected"}, + {"lT1", "long_transient"}, + {"lV1", "long_volatile"} + }; + + final static boolean BOOL[] = {true, false, false, true, true, true, true, + false, false, false, false, false, false, + false}; + final static byte BYTE[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE, -1, + 13, 14}; + + final static char CHAR[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + '\u1234', '\u4321', '\ufedc', '\ucdef', + Character.MAX_VALUE, + 9, 10, 11, 12, 13, 14}; + final static double DOUB[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, + -1, -0, 0, 1, Double.MAX_VALUE, + Double.POSITIVE_INFINITY, Double.NaN, + Double.NaN, -0, 0, 1, -1}; + final static float FLOAT[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, + -1, -0, 0, 1, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, Float.NaN, + Float.NaN, -0, 1, -1, + 14}; + final static int INT[] = {Integer.MIN_VALUE, -1, 0, 1, + Integer.MAX_VALUE, Integer.MIN_VALUE, -1, 0, + 1, Integer.MAX_VALUE, -1, + 12, 13, 14}; + final static long LONG[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + 11, 12, 13, 14}; + final static short SHORT[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + Short.MIN_VALUE, -1, 0, 1, + 10, 11, 12, 13, 14}; + final static long LONGF[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, + 7, 8, 9, 10, 11, 12, 13, 14}; + final static long LONGP[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + 6, 7, 8, 9, 10, 11, 12, 13, 14}; + final static long LONGU[] = {Long.MIN_VALUE, -1, 0, 1, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + final static long LONGR[] = {Long.MIN_VALUE, -1, 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + final static long LONGT[] = {Long.MIN_VALUE, -1, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + final static long LONGV[] = {Long.MIN_VALUE, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + + private static Log log; + private final static String prefix + = "nsk.jdi.ArrayReference.setValues_ilii."; + private final static String className = "setvaluesilii001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvaluesilii001aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + Field fieldBoolean = null; + Field fieldByte = null; + Field fieldChar = null; + Field fieldDouble = null; + Field fieldFloat = null; + Field fieldInt = null; + Field fieldLong = null; + Field fieldShort = null; + ArrayReference arrayBoolean = null; + ArrayReference arrayByte = null; + ArrayReference arrayChar = null; + ArrayReference arrayDouble = null; + ArrayReference arrayFloat = null; + ArrayReference arrayInt = null; + ArrayReference arrayLong = null; + ArrayReference arrayShort = null; + List listBoolean = null; + List listByte = null; + List listChar = null; + List listDouble = null; + List listFloat = null; + List listInt = null; + List listLong = null; + List listShort = null; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Get all array samples of primitive types to set it to the + // ArrayReference + try { + fieldBoolean = refType.fieldByName("z1S"); + fieldByte = refType.fieldByName("b1S"); + fieldChar = refType.fieldByName("c1S"); + fieldDouble = refType.fieldByName("d1S"); + fieldFloat = refType.fieldByName("f1S"); + fieldInt = refType.fieldByName("i1S"); + fieldLong = refType.fieldByName("l1S"); + fieldShort = refType.fieldByName("r1S"); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample fields for primitive types."); + log.display("debuger> boolean is " + fieldBoolean); + log.display("debuger> byte is " + fieldByte); + log.display("debuger> char is " + fieldChar); + log.display("debuger> double is " + fieldDouble); + log.display("debuger> float is " + fieldFloat); + log.display("debuger> int is " + fieldInt); + log.display("debuger> long is " + fieldLong); + log.display("debuger> short is " + fieldShort + "\n"); + + if ((fieldBoolean == null) || (fieldByte == null) || + (fieldChar == null) || (fieldDouble == null) || + (fieldFloat == null) || (fieldInt == null) || + (fieldLong == null) || (fieldShort == null)) { + log.complain("debuger FAILURE> Cannot find field in debuggee."); + return 2; + } + + try { + arrayBoolean = (ArrayReference)refType.getValue(fieldBoolean); + arrayByte = (ArrayReference)refType.getValue(fieldByte); + arrayChar = (ArrayReference)refType.getValue(fieldChar); + arrayDouble = (ArrayReference)refType.getValue(fieldDouble); + arrayFloat = (ArrayReference)refType.getValue(fieldFloat); + arrayInt = (ArrayReference)refType.getValue(fieldInt); + arrayLong = (ArrayReference)refType.getValue(fieldLong); + arrayShort = (ArrayReference)refType.getValue(fieldShort); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ClassCastException e) { + log.complain("debuger FAILURE> Cannot get array reference for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } + log.display("debuger> Got sample array references for primitive " + + "types."); + log.display("debuger> boolean is " + arrayBoolean); + log.display("debuger> byte is " + arrayByte); + log.display("debuger> char is " + arrayChar); + log.display("debuger> double is " + arrayDouble); + log.display("debuger> float is " + arrayFloat); + log.display("debuger> int is " + arrayInt); + log.display("debuger> long is " + arrayLong); + log.display("debuger> short is " + arrayShort + "\n"); + + try { + listBoolean = arrayBoolean.getValues(); + listByte = arrayByte.getValues(); + listChar = arrayChar.getValues(); + listDouble = arrayDouble.getValues(); + listFloat = arrayFloat.getValues(); + listInt = arrayInt.getValues(); + listLong = arrayLong.getValues(); + listShort = arrayShort.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get list of values for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + listBoolean); + log.complain("debuger FAILURE> byte is " + listByte); + log.complain("debuger FAILURE> char is " + listChar); + log.complain("debuger FAILURE> double is " + listDouble); + log.complain("debuger FAILURE> float is " + listFloat); + log.complain("debuger FAILURE> int is " + listInt); + log.complain("debuger FAILURE> long is " + listLong); + log.complain("debuger FAILURE> short is " + listShort); + return 2; + } + log.display("debuger> Got list of values for primitive types."); + log.display("debuger> boolean is " + listBoolean); + log.display("debuger> byte is " + listByte); + log.display("debuger> char is " + listChar); + log.display("debuger> double is " + listDouble); + log.display("debuger> float is " + listFloat); + log.display("debuger> int is " + listInt); + log.display("debuger> long is " + listLong); + log.display("debuger> short is " + listShort + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String type = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listToSet; + List listRead; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Prepare list to set + if (type.equals("boolean")) { + listToSet = listBoolean; + } else if (type.equals("byte")) { + listToSet = listByte; + } else if (type.equals("char")) { + listToSet = listChar; + } else if (type.equals("double")) { + listToSet = listDouble; + } else if (type.equals("float")) { + listToSet = listFloat; + } else if (type.equals("int")) { + listToSet = listInt; + } else if (type.equals("long") || + type.equals("long_final") || + type.equals("long_private") || + type.equals("long_public") || + type.equals("long_protected") || + type.equals("long_transient") || + type.equals("long_volatile") ) { + listToSet = listLong; + } else if (type.equals("short")) { + listToSet = listShort; + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + type); + testFailed = true; + continue; + } + + // Set the sample list of values + try { + arrayRef.setValues(0, listToSet, 0, LENGTH - i); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: sublist of values set " + + listToSet.subList(0, LENGTH - i) + " from index 0."); + + // Get the list of Values and check them + try { + listRead = arrayRef.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 6> Cannot get values from field " + + name); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: list of values read " + + listRead); + + for (int j = 0; j < listRead.size(); j++) { + if (type.equals("boolean")) { + + ///////////////////// Check boolean[] ///////////////////// + BooleanValue boolValue; + boolean element; + + try { + boolValue = (BooleanValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z1> Cannot cast to " + + "boolean " + j + " value of list " + + listRead); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + element = boolValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BOOL[j]) { + log.complain("debuger FAILURE Z2> " + j + " element " + + "of array " + name + " was expected " + + BOOL[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("byte")) { + + ///////////////////// Check byte[] ///////////////////// + ByteValue byteValue; + byte element; + + try { + byteValue = (ByteValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE B1> Cannot cast to " + + "byte " + j + " value of list " + + listRead); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + element = byteValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BYTE[j]) { + log.complain("debuger FAILURE B2> " + j + " element " + + "of array " + name + " was expected " + + BYTE[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("char")) { + + ///////////////////// Check char[] ///////////////////// + CharValue charValue; + char element; + + try { + charValue = (CharValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE C1> Cannot cast to " + + "char " + j + " value of list " + + listRead); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + element = charValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != CHAR[j]) { + log.complain("debuger FAILURE C2> " + j + " element " + + "of array " + name + " was expected " + + CHAR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("int")) { + + ///////////////////// Check int[] ///////////////////// + IntegerValue intValue; + int element; + + try { + intValue = (IntegerValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE I1> Cannot cast to " + + "int " + j + " value of list " + + listRead); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + element = intValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != INT[j]) { + log.complain("debuger FAILURE I2> " + j + " element " + + "of array " + name + " was expected " + + INT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long")) { + + ///////////////////// Check long[] ///////////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE L1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONG[j]) { + log.complain("debuger FAILURE L2> " + j + " element " + + "of array " + name + " was expected " + + LONG[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_final")) { + + ///////////////////// Check final long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LF1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LF1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGF[j]) { + log.complain("debuger FAILURE LF2> " + j + " element " + + "of array " + name + " was expected " + + LONGF[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_private")) { + + ///////////////////// Check private long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LP1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LP1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGP[j]) { + log.complain("debuger FAILURE LP2> " + j + " element " + + "of array " + name + " was expected " + + LONGP[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_public")) { + + ///////////////////// Check public long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LU1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LU1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGU[j]) { + log.complain("debuger FAILURE LU2> " + j + " element " + + "of array " + name + " was expected " + + LONGU[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_protected")) { + + ///////////////////// Check protected long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LR1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LR1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGR[j]) { + log.complain("debuger FAILURE LR2> " + j + " element " + + "of array " + name + " was expected " + + LONGR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_transient")) { + + ///////////////////// Check transient long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LT1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LT1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGT[j]) { + log.complain("debuger FAILURE LT2> " + j + " element " + + "of array " + name + " was expected " + + LONGT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_volatile")) { + + ///////////////////// Check volatile long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LV1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LV1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGV[j]) { + log.complain("debuger FAILURE LV2> " + j + " element " + + "of array " + name + " was expected " + + LONGV[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("short")) { + + ///////////////////// Check short[] ///////////////////// + ShortValue shortValue; + short element; + + try { + shortValue = (ShortValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE R1> Cannot cast to " + + "short " + j + " value of list " + + listRead); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + element = shortValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != SHORT[j]) { + log.complain("debuger FAILURE R2> " + j + " element " + + "of array " + name + " was expected " + + SHORT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("double")) { + + ///////////////////// Check double[] ///////////////////// + DoubleValue doubleValue; + Double element; + + try { + doubleValue = (DoubleValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE D1> Cannot cast to " + + "double " + j + " value of list " + + listRead); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + + element = new Double(doubleValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Double(DOUB[j]))) { + log.complain("debuger FAILURE D3> " + j + " element of " + + "array " + name + " was expected " + + DOUB[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("float")) { + + ///////////////////// Check float[] ///////////////////// + FloatValue floatValue; + Float element; + + try { + floatValue = (FloatValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE F1> Cannot cast to " + + "float " + j + " value of list " + + listRead); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + + element = new Float(floatValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Float(FLOAT[j]))) { + log.complain("debuger FAILURE F3> " + j + " element of " + + "array " + name + " was expected " + + FLOAT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else { + log.complain("debuger FAILURE 6> Unexpected type: " + type); + testFailed = true; + break; + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001/TestDescription.java new file mode 100644 index 00000000000..1a69531b533 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValues(int, List, int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public void setValues(int index, List values, int srcIndex, int length) + * throws InvalidTypeException, ClassNotLoadedException + * Replaces a range of array components with other values. + * Object values must be assignment compatible with the component type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: index - the index of the first component to set. + * values - a list of Value objects to be placed in this array. + * srcIndex - the index of the first source value to to use. + * length - the number of components to set, or -1 to set all + * components to the end of this array. + * Throws: InvalidTypeException - if any element of values is not compatible + * with the declared type of array components. + * java.lang.IndexOutOfBoundsException - if srcIndex + length is beyond + * the end of this array or if values is smaller inside than the + * given range. + * ObjectCollectedException - if this object or any of the new values + * has been garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001 checks assertion: + * public void setValues(int index, List values, int srcIndex, int length) + * 1. Replaces a range of array components with other values. Array has + * components of primitive types only. Index and srcIndex are in array's + * bounds. + * Debuggee defines eight sample array fields. One for each primitive type. + * Also, it defines tested array fields. All arrays have 14 elements. + * Debugger gets each sample field from debuggee by name and gets its + * Value, casts it to ArrayReference and gets list of its Values. After that + * the test gets tested array fields by name, gets their values, casts to + * ArrayReference types. For i field the method + * setValues(0, List, 0, LENGTH - i) is invoked to set LENGTH - i elements of + * sample array from index 0 to ArrayReference from index 0. + * After that the test gets all Values of the array and checks them. Debugger + * determines component's type (by field's name), gets each element of the + * list, casts it to correspondent PrimitiveType and then gets its primitive + * value. Then the test compares returned and expected primitive values. + * COMMENTS + * 4419982: JDI: two StackFrame methods return incorrect values for double + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii001 + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001a.java new file mode 100644 index 00000000000..e67bf80e4ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001a.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvaluesilii001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvaluesilii001aClassToCheck classToCheck = new setvaluesilii001aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvaluesilii001aClassToCheck { + static double d1S[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN, Double.NaN, -0, 0, 1, -1}; + static float f1S[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, 0, + 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN, Float.NaN, -0, 1, -1, + 14}; + static byte b1S[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE, -1, + 13, 14}; + static int i1S[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, + Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, -1, + 12, 13, 14}; + static long l1S[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + 11, 12, 13, 14}; + static short r1S[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + Short.MIN_VALUE, -1, 0, 1, + 10, 11, 12, 13, 14}; + static char c1S[] = {Character.MIN_VALUE, '\u00ff', '\uff00', '\u1234', + '\u4321', '\ufedc', '\ucdef', Character.MAX_VALUE, + 9, 10, 11, 12, 13, 14}; + static boolean z1S[] = {true, false, false, true, true, true, true, + false, true, + false, false, false, false, false, false, false}; + + static boolean z1[] = {false, false, false, false, false, false, false, + false, false, false, false, false, false, false}; + static byte b1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static char c1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static double d1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static float f1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static int i1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static long l1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static short r1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + + static final long lF1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static private long lP1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static public long lU1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static protected long lR1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static transient long lT1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static volatile long lV1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002.java new file mode 100644 index 00000000000..4e44a7de091 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002.java @@ -0,0 +1,879 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvaluesilii002 { + final static String FIELD_NAME[][] = { + {"d1", "double"}, + {"f1", "float"}, + {"b1", "byte"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + {"c1", "char"}, + {"z1", "boolean"}, + + {"lF1", "long_final"}, + {"lP1", "long_private"}, + {"lU1", "long_public"}, + {"lR1", "long_protected"}, + {"lT1", "long_transient"}, + {"lV1", "long_volatile"} + }; + + final static boolean BOOL[] = {false, false, false, false, false, false, + false, true, false, false, true, true, + true, true, false, true}; + final static byte BYTE[] = {1, 2, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE, -1}; + + final static char CHAR[] = {1, 2, 3, 4, 5, 6, + Character.MIN_VALUE, '\u00ff', '\uff00', + '\u1234', '\u4321', '\ufedc', '\ucdef', + Character.MAX_VALUE}; + final static double DOUB[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, + -1, -0, 0, 1, Double.MAX_VALUE, + Double.POSITIVE_INFINITY, Double.NaN, + Double.NaN, -0, 0, 1, -1}; + final static float FLOAT[] = {1, + Float.NEGATIVE_INFINITY, Float.MIN_VALUE, + -1, -0, 0, 1, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, Float.NaN, + Float.NaN, -0, 1, -1}; + final static int INT[] = {1, 2, 3, + Integer.MIN_VALUE, -1, 0, 1, + Integer.MAX_VALUE, Integer.MIN_VALUE, -1, 0, + 1, Integer.MAX_VALUE, -1}; + final static long LONG[] = {1, 2, 3, 4, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + final static short SHORT[] = {1, 2, 3, 4, 5, + Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + Short.MIN_VALUE, -1, 0, 1}; + final static long LONGF[] = {1, 2, 3, 4, 5, 6, 7, 8, + Long.MAX_VALUE, Long.MIN_VALUE, -1, 0, 1, + Long.MAX_VALUE}; + final static long LONGP[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + final static long LONGU[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + -1, 0, 1, Long.MAX_VALUE}; + final static long LONGR[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 0, 1, Long.MAX_VALUE}; + final static long LONGT[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 1, Long.MAX_VALUE}; + final static long LONGV[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + Long.MAX_VALUE}; + + private static Log log; + private final static String prefix + = "nsk.jdi.ArrayReference.setValues_ilii."; + private final static String className = "setvaluesilii002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvaluesilii002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + Field fieldBoolean = null; + Field fieldByte = null; + Field fieldChar = null; + Field fieldDouble = null; + Field fieldFloat = null; + Field fieldInt = null; + Field fieldLong = null; + Field fieldShort = null; + ArrayReference arrayBoolean = null; + ArrayReference arrayByte = null; + ArrayReference arrayChar = null; + ArrayReference arrayDouble = null; + ArrayReference arrayFloat = null; + ArrayReference arrayInt = null; + ArrayReference arrayLong = null; + ArrayReference arrayShort = null; + List listBoolean = null; + List listByte = null; + List listChar = null; + List listDouble = null; + List listFloat = null; + List listInt = null; + List listLong = null; + List listShort = null; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Get all array samples of primitive types to set it to the + // ArrayReference + try { + fieldBoolean = refType.fieldByName("z1S"); + fieldByte = refType.fieldByName("b1S"); + fieldChar = refType.fieldByName("c1S"); + fieldDouble = refType.fieldByName("d1S"); + fieldFloat = refType.fieldByName("f1S"); + fieldInt = refType.fieldByName("i1S"); + fieldLong = refType.fieldByName("l1S"); + fieldShort = refType.fieldByName("r1S"); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample fields for primitive types."); + log.display("debuger> boolean is " + fieldBoolean); + log.display("debuger> byte is " + fieldByte); + log.display("debuger> char is " + fieldChar); + log.display("debuger> double is " + fieldDouble); + log.display("debuger> float is " + fieldFloat); + log.display("debuger> int is " + fieldInt); + log.display("debuger> long is " + fieldLong); + log.display("debuger> short is " + fieldShort + "\n"); + + if ((fieldBoolean == null) || (fieldByte == null) || + (fieldChar == null) || (fieldDouble == null) || + (fieldFloat == null) || (fieldInt == null) || + (fieldLong == null) || (fieldShort == null)) { + log.complain("debuger FAILURE> Cannot find field in debuggee."); + return 2; + } + + try { + arrayBoolean = (ArrayReference)refType.getValue(fieldBoolean); + arrayByte = (ArrayReference)refType.getValue(fieldByte); + arrayChar = (ArrayReference)refType.getValue(fieldChar); + arrayDouble = (ArrayReference)refType.getValue(fieldDouble); + arrayFloat = (ArrayReference)refType.getValue(fieldFloat); + arrayInt = (ArrayReference)refType.getValue(fieldInt); + arrayLong = (ArrayReference)refType.getValue(fieldLong); + arrayShort = (ArrayReference)refType.getValue(fieldShort); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ClassCastException e) { + log.complain("debuger FAILURE> Cannot get array reference for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } + log.display("debuger> Got sample array references for primitive " + + "types."); + log.display("debuger> boolean is " + arrayBoolean); + log.display("debuger> byte is " + arrayByte); + log.display("debuger> char is " + arrayChar); + log.display("debuger> double is " + arrayDouble); + log.display("debuger> float is " + arrayFloat); + log.display("debuger> int is " + arrayInt); + log.display("debuger> long is " + arrayLong); + log.display("debuger> short is " + arrayShort + "\n"); + + try { + listBoolean = arrayBoolean.getValues(); + listByte = arrayByte.getValues(); + listChar = arrayChar.getValues(); + listDouble = arrayDouble.getValues(); + listFloat = arrayFloat.getValues(); + listInt = arrayInt.getValues(); + listLong = arrayLong.getValues(); + listShort = arrayShort.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get list of values for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + listBoolean); + log.complain("debuger FAILURE> byte is " + listByte); + log.complain("debuger FAILURE> char is " + listChar); + log.complain("debuger FAILURE> double is " + listDouble); + log.complain("debuger FAILURE> float is " + listFloat); + log.complain("debuger FAILURE> int is " + listInt); + log.complain("debuger FAILURE> long is " + listLong); + log.complain("debuger FAILURE> short is " + listShort); + return 2; + } + log.display("debuger> Got list of values for primitive types."); + log.display("debuger> boolean is " + listBoolean); + log.display("debuger> byte is " + listByte); + log.display("debuger> char is " + listChar); + log.display("debuger> double is " + listDouble); + log.display("debuger> float is " + listFloat); + log.display("debuger> int is " + listInt); + log.display("debuger> long is " + listLong); + log.display("debuger> short is " + listShort + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String type = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listToSet; + List listRead; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Prepare list to set + if (type.equals("boolean")) { + listToSet = listBoolean; + } else if (type.equals("byte")) { + listToSet = listByte; + } else if (type.equals("char")) { + listToSet = listChar; + } else if (type.equals("double")) { + listToSet = listDouble; + } else if (type.equals("float")) { + listToSet = listFloat; + } else if (type.equals("int")) { + listToSet = listInt; + } else if (type.equals("long") || + type.equals("long_final") || + type.equals("long_private") || + type.equals("long_public") || + type.equals("long_protected") || + type.equals("long_transient") || + type.equals("long_volatile") ) { + listToSet = listLong; + } else if (type.equals("short")) { + listToSet = listShort; + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + type); + testFailed = true; + continue; + } + + // Set the sample list of values + try { + arrayRef.setValues(i, listToSet, i, -1); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: sublist of values set " + + listToSet.subList(i, listToSet.size() - 1) + + " from index " + i); + + // Get the list of Values and check them + try { + listRead = arrayRef.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 6> Cannot get values from field " + + name); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: list of values read " + + listRead); + + for (int j = 0; j < listRead.size(); j++) { + if (type.equals("boolean")) { + + ///////////////////// Check boolean[] ///////////////////// + BooleanValue boolValue; + boolean element; + + try { + boolValue = (BooleanValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z1> Cannot cast to " + + "boolean " + j + " value of list " + + listRead); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + element = boolValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BOOL[j]) { + log.complain("debuger FAILURE Z2> " + j + " element " + + "of array " + name + " was expected " + + BOOL[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("byte")) { + + ///////////////////// Check byte[] ///////////////////// + ByteValue byteValue; + byte element; + + try { + byteValue = (ByteValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE B1> Cannot cast to " + + "byte " + j + " value of list " + + listRead); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + element = byteValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BYTE[j]) { + log.complain("debuger FAILURE B2> " + j + " element " + + "of array " + name + " was expected " + + BYTE[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("char")) { + + ///////////////////// Check char[] ///////////////////// + CharValue charValue; + char element; + + try { + charValue = (CharValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE C1> Cannot cast to " + + "char " + j + " value of list " + + listRead); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + element = charValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != CHAR[j]) { + log.complain("debuger FAILURE C2> " + j + " element " + + "of array " + name + " was expected " + + CHAR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("int")) { + + ///////////////////// Check int[] ///////////////////// + IntegerValue intValue; + int element; + + try { + intValue = (IntegerValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE I1> Cannot cast to " + + "int " + j + " value of list " + + listRead); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + element = intValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != INT[j]) { + log.complain("debuger FAILURE I2> " + j + " element " + + "of array " + name + " was expected " + + INT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long")) { + + ///////////////////// Check long[] ///////////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE L1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONG[j]) { + log.complain("debuger FAILURE L2> " + j + " element " + + "of array " + name + " was expected " + + LONG[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_final")) { + + ///////////////////// Check final long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LF1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LF1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGF[j]) { + log.complain("debuger FAILURE LF2> " + j + " element " + + "of array " + name + " was expected " + + LONGF[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_private")) { + + ///////////////////// Check private long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LP1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LP1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGP[j]) { + log.complain("debuger FAILURE LP2> " + j + " element " + + "of array " + name + " was expected " + + LONGP[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_public")) { + + ///////////////////// Check public long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LU1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LU1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGU[j]) { + log.complain("debuger FAILURE LU2> " + j + " element " + + "of array " + name + " was expected " + + LONGU[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_protected")) { + + ///////////////////// Check protected long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LR1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LR1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGR[j]) { + log.complain("debuger FAILURE LR2> " + j + " element " + + "of array " + name + " was expected " + + LONGR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_transient")) { + + ///////////////////// Check transient long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LT1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LT1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGT[j]) { + log.complain("debuger FAILURE LT2> " + j + " element " + + "of array " + name + " was expected " + + LONGT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long_volatile")) { + + ///////////////////// Check volatile long[] //////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE LV1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE LV1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONGV[j]) { + log.complain("debuger FAILURE LV2> " + j + " element " + + "of array " + name + " was expected " + + LONGV[j] + ", but returned " + element); + testFailed = true; + continue; + } + + + + + + } else if (type.equals("short")) { + + ///////////////////// Check short[] ///////////////////// + ShortValue shortValue; + short element; + + try { + shortValue = (ShortValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE R1> Cannot cast to " + + "short " + j + " value of list " + + listRead); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + element = shortValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != SHORT[j]) { + log.complain("debuger FAILURE R2> " + j + " element " + + "of array " + name + " was expected " + + SHORT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("double")) { + + ///////////////////// Check double[] ///////////////////// + DoubleValue doubleValue; + Double element; + + try { + doubleValue = (DoubleValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE D1> Cannot cast to " + + "double " + j + " value of list " + + listRead); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + + element = new Double(doubleValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Double(DOUB[j]))) { + log.complain("debuger FAILURE D3> " + j + " element of " + + "array " + name + " was expected " + + DOUB[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("float")) { + + ///////////////////// Check float[] ///////////////////// + FloatValue floatValue; + Float element; + + try { + floatValue = (FloatValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE F1> Cannot cast to " + + "float " + j + " value of list " + + listRead); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + + element = new Float(floatValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Float(FLOAT[j]))) { + log.complain("debuger FAILURE F3> " + j + " element of " + + "array " + name + " was expected " + + FLOAT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else { + log.complain("debuger FAILURE 6> Unexpected type: " + type); + testFailed = true; + break; + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.display("debuger FAILURE> TEST FAILED"); + return 0; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002/TestDescription.java new file mode 100644 index 00000000000..23eb5c93894 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002/TestDescription.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValues(int, List, int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public void setValues(int index, List values, int srcIndex, int length) + * throws InvalidTypeException, ClassNotLoadedException + * Replaces a range of array components with other values. + * Object values must be assignment compatible with the component type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: index - the index of the first component to set. + * values - a list of Value objects to be placed in this array. + * srcIndex - the index of the first source value to to use. + * length - the number of components to set, or -1 to set all + * components to the end of this array. + * Throws: InvalidTypeException - if any element of values is not compatible + * with the declared type of array components. + * java.lang.IndexOutOfBoundsException - if srcIndex + length is beyond + * the end of this array or if values is smaller inside than the + * given range. + * ObjectCollectedException - if this object or any of the new values + * has been garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002 checks assertion: + * public void setValues(int index, List values, int srcIndex, int length) + * 1. Replaces all components to the end of this array with other values. Array + * has components of primitive types only. Index and srcIndex are in array's + * bounds. + * Debuggee defines eight sample array fields. One for each primitive type. + * Also, it defines tested array fields. All arrays have 14 elements. + * Debugger gets each sample field from debuggee by name and gets its + * Value, casts it to ArrayReference and gets list of its Values. After that + * the test gets tested array fields by name, gets their values, casts to + * ArrayReference types. For i field the method setValues(0, List, 0, -1) is + * invoked to set all elements of sample array from index 0 to ArrayReference + * from index 0. + * After that the test gets all Values of the array and checks them. Debugger + * determines component's type (by field's name), gets each element of the + * list, casts it to correspondent PrimitiveType and then gets its primitive + * value. Then the test compares returned and expected primitive values. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii002 + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002a.java new file mode 100644 index 00000000000..bfa5e0ecc18 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002a.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvaluesilii002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvaluesilii002aClassToCheck classToCheck = new setvaluesilii002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvaluesilii002aClassToCheck { + static double d1S[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN, Double.NaN, -0, 0, 1, -1}; + static float f1S[] = {0, + Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, 0, + 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN, Float.NaN, -0, 1, -1}; + static byte b1S[] = {0, 1, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, + Byte.MIN_VALUE, -1}; + static int i1S[] = {0, 1, 2, + Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, + Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, -1}; + static long l1S[] = {0, 1, 2, 3, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, + Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + static short r1S[] = {0, 1, 2, 3, 4, + Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + Short.MIN_VALUE, -1, 0, 1}; + static char c1S[] = {0, 1, 2, 3, 4, 5, + Character.MIN_VALUE, '\u00ff', '\uff00', '\u1234', + '\u4321', '\ufedc', '\ucdef', Character.MAX_VALUE}; + static boolean z1S[] = {false, false, false, false, false, false, false, + true, false, false, true, true, true, true, + false, true}; + + static boolean z1[] = {false, false, false, false, false, false, false, + false, false, false, false, false, false, false}; + static byte b1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static char c1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static double d1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static float f1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static int i1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static long l1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + static short r1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; + + static final long lF1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static private long lP1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static public long lU1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static protected long lR1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static transient long lT1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; + static volatile long lV1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003.java new file mode 100644 index 00000000000..7077c381c1d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvaluesilii003 { + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long"}, + {"lP1", "long"}, + {"lU1", "long"}, + {"lR1", "long"}, + {"lT1", "long"}, + {"lV1", "long"} + }; + + private static Log log; + private final static String prefix + = "nsk.jdi.ArrayReference.setValues_ilii."; + private final static String className = "setvaluesilii003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvaluesilii003aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + Field fieldBoolean = null; + Field fieldByte = null; + Field fieldChar = null; + Field fieldDouble = null; + Field fieldFloat = null; + Field fieldInt = null; + Field fieldLong = null; + Field fieldShort = null; + ArrayReference arrayBoolean = null; + ArrayReference arrayByte = null; + ArrayReference arrayChar = null; + ArrayReference arrayDouble = null; + ArrayReference arrayFloat = null; + ArrayReference arrayInt = null; + ArrayReference arrayLong = null; + ArrayReference arrayShort = null; + List listBoolean = null; + List listByte = null; + List listChar = null; + List listDouble = null; + List listFloat = null; + List listInt = null; + List listLong = null; + List listShort = null; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Get all array samples of primitive types to set it to the + // ArrayReference + try { + fieldBoolean = refType.fieldByName("z1S"); + fieldByte = refType.fieldByName("b1S"); + fieldChar = refType.fieldByName("c1S"); + fieldDouble = refType.fieldByName("d1S"); + fieldFloat = refType.fieldByName("f1S"); + fieldInt = refType.fieldByName("i1S"); + fieldLong = refType.fieldByName("l1S"); + fieldShort = refType.fieldByName("r1S"); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample fields for primitive types."); + log.display("debuger> boolean is " + fieldBoolean); + log.display("debuger> byte is " + fieldByte); + log.display("debuger> char is " + fieldChar); + log.display("debuger> double is " + fieldDouble); + log.display("debuger> float is " + fieldFloat); + log.display("debuger> int is " + fieldInt); + log.display("debuger> long is " + fieldLong); + log.display("debuger> short is " + fieldShort + "\n"); + + if ((fieldBoolean == null) || (fieldByte == null) || + (fieldChar == null) || (fieldDouble == null) || + (fieldFloat == null) || (fieldInt == null) || + (fieldLong == null) || (fieldShort == null)) { + log.complain("debuger FAILURE> Cannot find field in debuggee."); + return 2; + } + + try { + arrayBoolean = (ArrayReference)refType.getValue(fieldBoolean); + arrayByte = (ArrayReference)refType.getValue(fieldByte); + arrayChar = (ArrayReference)refType.getValue(fieldChar); + arrayDouble = (ArrayReference)refType.getValue(fieldDouble); + arrayFloat = (ArrayReference)refType.getValue(fieldFloat); + arrayInt = (ArrayReference)refType.getValue(fieldInt); + arrayLong = (ArrayReference)refType.getValue(fieldLong); + arrayShort = (ArrayReference)refType.getValue(fieldShort); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ClassCastException e) { + log.complain("debuger FAILURE> Cannot get array reference for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } + log.display("debuger> Got sample array references for primitive " + + "types."); + log.display("debuger> boolean is " + arrayBoolean); + log.display("debuger> byte is " + arrayByte); + log.display("debuger> char is " + arrayChar); + log.display("debuger> double is " + arrayDouble); + log.display("debuger> float is " + arrayFloat); + log.display("debuger> int is " + arrayInt); + log.display("debuger> long is " + arrayLong); + log.display("debuger> short is " + arrayShort + "\n"); + + try { + listBoolean = arrayBoolean.getValues(); + listByte = arrayByte.getValues(); + listChar = arrayChar.getValues(); + listDouble = arrayDouble.getValues(); + listFloat = arrayFloat.getValues(); + listInt = arrayInt.getValues(); + listLong = arrayLong.getValues(); + listShort = arrayShort.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get list of values for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + listBoolean); + log.complain("debuger FAILURE> byte is " + listByte); + log.complain("debuger FAILURE> char is " + listChar); + log.complain("debuger FAILURE> double is " + listDouble); + log.complain("debuger FAILURE> float is " + listFloat); + log.complain("debuger FAILURE> int is " + listInt); + log.complain("debuger FAILURE> long is " + listLong); + log.complain("debuger FAILURE> short is " + listShort); + return 2; + } + log.display("debuger> Got list of values for primitive types."); + log.display("debuger> boolean is " + listBoolean); + log.display("debuger> byte is " + listByte); + log.display("debuger> char is " + listChar); + log.display("debuger> double is " + listDouble); + log.display("debuger> float is " + listFloat); + log.display("debuger> int is " + listInt); + log.display("debuger> long is " + listLong); + log.display("debuger> short is " + listShort + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String type = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listToSet; + List listRead; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field has length " + + arrayRef.length()); + + // Prepare list to set + if (type.equals("boolean")) { + listToSet = listBoolean; + } else if (type.equals("byte")) { + listToSet = listByte; + } else if (type.equals("char")) { + listToSet = listChar; + } else if (type.equals("double")) { + listToSet = listDouble; + } else if (type.equals("float")) { + listToSet = listFloat; + } else if (type.equals("int")) { + listToSet = listInt; + } else if (type.equals("long") ) { + listToSet = listLong; + } else if (type.equals("short")) { + listToSet = listShort; + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + type); + testFailed = true; + continue; + } + + // Set the sample list of values + try { + arrayRef.setValues(0, listToSet, 0, listToSet.size() + 1 ); + log.complain("debuger FAILURE 5> IndexOutOfBoundsException is " + + "not thrown."); + log.complain("debuger FAILURE 5> " + i + " field: list of " + + "values " + listToSet + " with length " + + listToSet.size() + " set from index 0."); + testFailed = true; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + // List of values is smaller inside than the given range, so + // IndexOutOfBoundsException is expected + log.display("debuger> Cannot set list of values " + listToSet + + " to the field " + name); + log.display("debuger> Exception: " + e); + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003/TestDescription.java new file mode 100644 index 00000000000..a2b97262909 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003/TestDescription.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValues(int, List, int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public void setValues(int index, List values, int srcIndex, int length) + * throws InvalidTypeException, ClassNotLoadedException + * Replaces a range of array components with other values. + * Object values must be assignment compatible with the component type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: index - the index of the first component to set. + * values - a list of Value objects to be placed in this array. + * srcIndex - the index of the first source value to to use. + * length - the number of components to set, or -1 to set all + * components to the end of this array. + * Throws: InvalidTypeException - if any element of values is not compatible + * with the declared type of array components. + * java.lang.IndexOutOfBoundsException - if srcIndex + length is beyond + * the end of this array or if values is smaller inside than the + * given range. + * ObjectCollectedException - if this object or any of the new values + * has been garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003 checks assertion: + * public void setValues(int index, List values, int srcIndex, int length) + * 1. IndexOutOfBoundsException is thrown if the list is smaller then the + * array. Array has components of primitive types only. + * Debuggee defines eight sample array fields. One for each primitive type. + * Also, it defines tested array fields. For each primitive type a sample + * array has at least one element less then correspondent tested array. + * Debugger gets each sample field from debuggee by name and gets its + * Value, casts it to ArrayReference and gets list of its Values. After that + * the test gets tested array fields by name, gets their values, casts to + * ArrayReference types. For i field the method + * setValues(0, List, 0, List.size()) is invoked to set all elements of sample + * array from index 0 to ArrayReference from index 0. Since sample array has + * at least one element less tested array, IndexOutOfBoundsException is + * expected. + * COMMENTS + * The tests shows the bug + * 4448721: ArrayReference.setValues(int, List, int, int) doesn't throw + * IndexOutOfBoundsException + * =========================== + * To fix the bug 4491099, + * the string + * arrayRef.setValues(0, listToSet, 0, listToSet.size()); + * is replaced with + * arrayRef.setValues(0, listToSet, 0, listToSet.size() + 1 ); + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii003 + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003a.java new file mode 100644 index 00000000000..37e472c1ed6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii003a.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvaluesilii003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvaluesilii003aClassToCheck classToCheck = new setvaluesilii003aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvaluesilii003aClassToCheck { + + // For each primitive type a sample array has at least one element less + // then correspondent tested array + static boolean z1[] = {false, false}; + static boolean z1S[] = {true}; + + static byte b1[] = {1, 2, 3}; + static byte b1S[] = {Byte.MIN_VALUE, Byte.MAX_VALUE}; + + static char c1[] = {1, 2, 3, 4}; + static char c1S[] = {Character.MIN_VALUE, '\u00ff', Character.MAX_VALUE}; + + static double d1[] = {1, 2, 3, 4, 5}; + static double d1S[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0}; + + static float f1[] = {1, 2, 3, 4, 5, 6}; + static float f1S[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + Float.NaN}; + + static int i1[] = {1, 2, 3, 4, 5, 6, 7}; + static int i1S[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, -1}; + + static long l1[] = {1, 2, 3, 4, 5, 6, 7, 8}; + static long l1S[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + + static short r1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + static short r1S[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + Short.MIN_VALUE, -1, 0}; + + static final long lF1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + static private long lP1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + static public long lU1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + static protected long lR1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; + static transient long lT1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14}; + static volatile long lV1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004.java new file mode 100644 index 00000000000..ca447ac0d47 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvaluesilii004 { + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long"}, + {"lP1", "long"}, + {"lU1", "long"}, + {"lR1", "long"}, + {"lT1", "long"}, + {"lV1", "long"} + }; + + private static Log log; + private final static String prefix + = "nsk.jdi.ArrayReference.setValues_ilii."; + private final static String className = "setvaluesilii004"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvaluesilii004aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + Field fieldBoolean = null; + Field fieldByte = null; + Field fieldChar = null; + Field fieldDouble = null; + Field fieldFloat = null; + Field fieldInt = null; + Field fieldLong = null; + Field fieldShort = null; + ArrayReference arrayBoolean = null; + ArrayReference arrayByte = null; + ArrayReference arrayChar = null; + ArrayReference arrayDouble = null; + ArrayReference arrayFloat = null; + ArrayReference arrayInt = null; + ArrayReference arrayLong = null; + ArrayReference arrayShort = null; + List listBoolean = null; + List listByte = null; + List listChar = null; + List listDouble = null; + List listFloat = null; + List listInt = null; + List listLong = null; + List listShort = null; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Get all array samples of primitive types to set it to the + // ArrayReference + try { + fieldBoolean = refType.fieldByName("z1S"); + fieldByte = refType.fieldByName("b1S"); + fieldChar = refType.fieldByName("c1S"); + fieldDouble = refType.fieldByName("d1S"); + fieldFloat = refType.fieldByName("f1S"); + fieldInt = refType.fieldByName("i1S"); + fieldLong = refType.fieldByName("l1S"); + fieldShort = refType.fieldByName("r1S"); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample fields for primitive types."); + log.display("debuger> boolean is " + fieldBoolean); + log.display("debuger> byte is " + fieldByte); + log.display("debuger> char is " + fieldChar); + log.display("debuger> double is " + fieldDouble); + log.display("debuger> float is " + fieldFloat); + log.display("debuger> int is " + fieldInt); + log.display("debuger> long is " + fieldLong); + log.display("debuger> short is " + fieldShort + "\n"); + + if ((fieldBoolean == null) || (fieldByte == null) || + (fieldChar == null) || (fieldDouble == null) || + (fieldFloat == null) || (fieldInt == null) || + (fieldLong == null) || (fieldShort == null)) { + log.complain("debuger FAILURE> Cannot find field in debuggee."); + return 2; + } + + try { + arrayBoolean = (ArrayReference)refType.getValue(fieldBoolean); + arrayByte = (ArrayReference)refType.getValue(fieldByte); + arrayChar = (ArrayReference)refType.getValue(fieldChar); + arrayDouble = (ArrayReference)refType.getValue(fieldDouble); + arrayFloat = (ArrayReference)refType.getValue(fieldFloat); + arrayInt = (ArrayReference)refType.getValue(fieldInt); + arrayLong = (ArrayReference)refType.getValue(fieldLong); + arrayShort = (ArrayReference)refType.getValue(fieldShort); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ClassCastException e) { + log.complain("debuger FAILURE> Cannot get array reference for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } + log.display("debuger> Got sample array references for primitive " + + "types."); + log.display("debuger> boolean is " + arrayBoolean); + log.display("debuger> byte is " + arrayByte); + log.display("debuger> char is " + arrayChar); + log.display("debuger> double is " + arrayDouble); + log.display("debuger> float is " + arrayFloat); + log.display("debuger> int is " + arrayInt); + log.display("debuger> long is " + arrayLong); + log.display("debuger> short is " + arrayShort + "\n"); + + try { + listBoolean = arrayBoolean.getValues(); + listByte = arrayByte.getValues(); + listChar = arrayChar.getValues(); + listDouble = arrayDouble.getValues(); + listFloat = arrayFloat.getValues(); + listInt = arrayInt.getValues(); + listLong = arrayLong.getValues(); + listShort = arrayShort.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get list of values for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + listBoolean); + log.complain("debuger FAILURE> byte is " + listByte); + log.complain("debuger FAILURE> char is " + listChar); + log.complain("debuger FAILURE> double is " + listDouble); + log.complain("debuger FAILURE> float is " + listFloat); + log.complain("debuger FAILURE> int is " + listInt); + log.complain("debuger FAILURE> long is " + listLong); + log.complain("debuger FAILURE> short is " + listShort); + return 2; + } + log.display("debuger> Got list of values for primitive types."); + log.display("debuger> boolean is " + listBoolean); + log.display("debuger> byte is " + listByte); + log.display("debuger> char is " + listChar); + log.display("debuger> double is " + listDouble); + log.display("debuger> float is " + listFloat); + log.display("debuger> int is " + listInt); + log.display("debuger> long is " + listLong); + log.display("debuger> short is " + listShort + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String type = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listToSet; + List listRead; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field has length " + + arrayRef.length()); + + // Prepare list to set + if (type.equals("boolean")) { + listToSet = listBoolean; + } else if (type.equals("byte")) { + listToSet = listByte; + } else if (type.equals("char")) { + listToSet = listChar; + } else if (type.equals("double")) { + listToSet = listDouble; + } else if (type.equals("float")) { + listToSet = listFloat; + } else if (type.equals("int")) { + listToSet = listInt; + } else if (type.equals("long") ) { + listToSet = listLong; + } else if (type.equals("short")) { + listToSet = listShort; + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + type); + testFailed = true; + continue; + } + + // Set the sample list of values + try { + arrayRef.setValues(0, listToSet, 1, listToSet.size()); + log.complain("debuger FAILURE 5> IndexOutOfBoundsException is " + + "not thrown."); + log.complain("debuger FAILURE 5> " + i + " field: list of " + + "values " + listToSet + " with length " + + listToSet.size() + " set from index 1."); + testFailed = true; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + // srcIndex + length is out of the range, so + // IndexOutOfBoundsException is expected + log.display("debuger> Cannot set list of values " + listToSet + + " to the field " + name); + log.display("debuger> Exception: " + e); + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004/TestDescription.java new file mode 100644 index 00000000000..6d67705d4cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValues(int, List, int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public void setValues(int index, List values, int srcIndex, int length) + * throws InvalidTypeException, ClassNotLoadedException + * Replaces a range of array components with other values. + * Object values must be assignment compatible with the component type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: index - the index of the first component to set. + * values - a list of Value objects to be placed in this array. + * srcIndex - the index of the first source value to to use. + * length - the number of components to set, or -1 to set all + * components to the end of this array. + * Throws: InvalidTypeException - if any element of values is not compatible + * with the declared type of array components. + * java.lang.IndexOutOfBoundsException - if srcIndex + length is beyond + * the end of this array or if values is smaller inside than the + * given range. + * ObjectCollectedException - if this object or any of the new values + * has been garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004 checks assertion: + * public void setValues(int index, List values, int srcIndex, int length) + * 1. IndexOutOfBoundsException is thrown if srcIndex + length is beyond the + * end of this array. Array has components of primitive types only. + * Debuggee defines eight sample array fields. One for each primitive type. + * Also, it defines tested array fields. Sample and correspondent tested + * arrays have the same lengths. + * Debugger gets each sample field from debuggee by name and gets its + * Value, casts it to ArrayReference and gets list of its Values. After that + * the test gets tested array fields by name, gets their values, casts to + * ArrayReference types. For i field the method + * setValues(0, List, 1, List.size()) is invoked to set all elements of sample + * array from index 0 to ArrayReference from index 1. Since srcIndex + length + * is beyond the end of this array, IndexOutOfBoundsException should be thrown. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii004 + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004a.java new file mode 100644 index 00000000000..19d60cfe25b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii004a.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvaluesilii004a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvaluesilii004aClassToCheck classToCheck = new setvaluesilii004aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvaluesilii004aClassToCheck { + + // For each primitive type a sample array has the same length as + // correspondent tested array + static boolean z1[] = {false}; + static boolean z1S[] = {true}; + + static byte b1[] = {1, 2}; + static byte b1S[] = {Byte.MIN_VALUE, Byte.MAX_VALUE}; + + static char c1[] = {1, 2, 3}; + static char c1S[] = {Character.MIN_VALUE, '\u00ff', Character.MAX_VALUE}; + + static double d1[] = {1, 2, 3, 4}; + static double d1S[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0}; + + static float f1[] = {1, 2, 3, 4, 5}; + static float f1S[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + Float.NaN}; + + static int i1[] = {1, 2, 3, 4, 5, 6}; + static int i1S[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, -1}; + + static long l1[] = {1, 2, 3, 4, 5, 6, 7}; + static long l1S[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + + static short r1[] = {1, 2, 3, 4, 5, 6, 7, 8}; + static short r1S[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + Short.MIN_VALUE, -1, 0}; + + static final long lF1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static private long lP1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static public long lU1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static protected long lR1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static transient long lT1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static volatile long lV1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005.java new file mode 100644 index 00000000000..5422f9deb11 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005.java @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvaluesilii005 { + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long"}, + {"lP1", "long"}, + {"lU1", "long"}, + {"lR1", "long"}, + {"lT1", "long"}, + {"lV1", "long"} + }; + + private static Log log; + private final static String prefix + = "nsk.jdi.ArrayReference.setValues_ilii."; + private final static String className = "setvaluesilii005"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvaluesilii005aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + Field fieldBoolean = null; + Field fieldByte = null; + Field fieldChar = null; + Field fieldDouble = null; + Field fieldFloat = null; + Field fieldInt = null; + Field fieldLong = null; + Field fieldShort = null; + ArrayReference arrayBoolean = null; + ArrayReference arrayByte = null; + ArrayReference arrayChar = null; + ArrayReference arrayDouble = null; + ArrayReference arrayFloat = null; + ArrayReference arrayInt = null; + ArrayReference arrayLong = null; + ArrayReference arrayShort = null; + List listBoolean = null; + List listByte = null; + List listChar = null; + List listDouble = null; + List listFloat = null; + List listInt = null; + List listLong = null; + List listShort = null; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Get all array samples of primitive types to set it to the + // ArrayReference + try { + fieldBoolean = refType.fieldByName("z1S"); + fieldByte = refType.fieldByName("b1S"); + fieldChar = refType.fieldByName("c1S"); + fieldDouble = refType.fieldByName("d1S"); + fieldFloat = refType.fieldByName("f1S"); + fieldInt = refType.fieldByName("i1S"); + fieldLong = refType.fieldByName("l1S"); + fieldShort = refType.fieldByName("r1S"); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample fields for primitive types."); + log.display("debuger> boolean is " + fieldBoolean); + log.display("debuger> byte is " + fieldByte); + log.display("debuger> char is " + fieldChar); + log.display("debuger> double is " + fieldDouble); + log.display("debuger> float is " + fieldFloat); + log.display("debuger> int is " + fieldInt); + log.display("debuger> long is " + fieldLong); + log.display("debuger> short is " + fieldShort + "\n"); + + if ((fieldBoolean == null) || (fieldByte == null) || + (fieldChar == null) || (fieldDouble == null) || + (fieldFloat == null) || (fieldInt == null) || + (fieldLong == null) || (fieldShort == null)) { + log.complain("debuger FAILURE> Cannot find field in debuggee."); + return 2; + } + + try { + arrayBoolean = (ArrayReference)refType.getValue(fieldBoolean); + arrayByte = (ArrayReference)refType.getValue(fieldByte); + arrayChar = (ArrayReference)refType.getValue(fieldChar); + arrayDouble = (ArrayReference)refType.getValue(fieldDouble); + arrayFloat = (ArrayReference)refType.getValue(fieldFloat); + arrayInt = (ArrayReference)refType.getValue(fieldInt); + arrayLong = (ArrayReference)refType.getValue(fieldLong); + arrayShort = (ArrayReference)refType.getValue(fieldShort); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ClassCastException e) { + log.complain("debuger FAILURE> Cannot get array reference for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } + log.display("debuger> Got sample array references for primitive " + + "types."); + log.display("debuger> boolean is " + arrayBoolean); + log.display("debuger> byte is " + arrayByte); + log.display("debuger> char is " + arrayChar); + log.display("debuger> double is " + arrayDouble); + log.display("debuger> float is " + arrayFloat); + log.display("debuger> int is " + arrayInt); + log.display("debuger> long is " + arrayLong); + log.display("debuger> short is " + arrayShort + "\n"); + + try { + listBoolean = arrayBoolean.getValues(); + listByte = arrayByte.getValues(); + listChar = arrayChar.getValues(); + listDouble = arrayDouble.getValues(); + listFloat = arrayFloat.getValues(); + listInt = arrayInt.getValues(); + listLong = arrayLong.getValues(); + listShort = arrayShort.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get list of values for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + listBoolean); + log.complain("debuger FAILURE> byte is " + listByte); + log.complain("debuger FAILURE> char is " + listChar); + log.complain("debuger FAILURE> double is " + listDouble); + log.complain("debuger FAILURE> float is " + listFloat); + log.complain("debuger FAILURE> int is " + listInt); + log.complain("debuger FAILURE> long is " + listLong); + log.complain("debuger FAILURE> short is " + listShort); + return 2; + } + log.display("debuger> Got list of values for primitive types."); + log.display("debuger> boolean is " + listBoolean); + log.display("debuger> byte is " + listByte); + log.display("debuger> char is " + listChar); + log.display("debuger> double is " + listDouble); + log.display("debuger> float is " + listFloat); + log.display("debuger> int is " + listInt); + log.display("debuger> long is " + listLong); + log.display("debuger> short is " + listShort + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String type = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listToSet; + List listRead; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field has length " + + arrayRef.length()); + + // Prepare list to set + if (type.equals("boolean")) { + listToSet = listBoolean; + } else if (type.equals("byte")) { + listToSet = listByte; + } else if (type.equals("char")) { + listToSet = listChar; + } else if (type.equals("double")) { + listToSet = listDouble; + } else if (type.equals("float")) { + listToSet = listFloat; + } else if (type.equals("int")) { + listToSet = listInt; + } else if (type.equals("long") ) { + listToSet = listLong; + } else if (type.equals("short")) { + listToSet = listShort; + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + type); + testFailed = true; + continue; + } + + // Set the sample list of values + try { + arrayRef.setValues(0, listToSet, 0, listToSet.size() + 1); + log.complain("debuger FAILURE 5> IndexOutOfBoundsException is " + + "not thrown."); + log.complain("debuger FAILURE 5> " + i + " field: list of " + + "values " + listToSet + " with length " + + (listToSet.size() + 1) + " set from index 1."); + testFailed = true; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + // srcIndex + length is out of the range, so + // IndexOutOfBoundsException is expected + log.display("debuger> Cannot set list of values " + listToSet + + " with length " + (listToSet.size() + 1) + + " to the field " + name); + log.display("debuger> Exception: " + e); + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005/TestDescription.java new file mode 100644 index 00000000000..15acaa8bcb0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValues(int, List, int, int) method of ArrayReference + * interface of com.sun.jdi package. + * The method spec: + * public void setValues(int index, List values, int srcIndex, int length) + * throws InvalidTypeException, ClassNotLoadedException + * Replaces a range of array components with other values. + * Object values must be assignment compatible with the component type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: index - the index of the first component to set. + * values - a list of Value objects to be placed in this array. + * srcIndex - the index of the first source value to to use. + * length - the number of components to set, or -1 to set all + * components to the end of this array. + * Throws: InvalidTypeException - if any element of values is not compatible + * with the declared type of array components. + * java.lang.IndexOutOfBoundsException - if srcIndex + length is beyond + * the end of this array or if values is smaller inside than the + * given range. + * ObjectCollectedException - if this object or any of the new values + * has been garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005 checks assertion: + * public void setValues(int index, List values, int srcIndex, int length) + * 1. IndexOutOfBoundsException is thrown if srcIndex + length is beyond the + * end of this array. Array has components of primitive types only. + * Debuggee defines eight sample array fields. One for each primitive type. + * Also, it defines tested array fields. Sample and correspondent tested + * arrays have the same lengths. + * Debugger gets each sample field from debuggee by name and gets its + * Value, casts it to ArrayReference and gets list of its Values. After that + * the test gets tested array fields by name, gets their values, casts to + * ArrayReference types. For i field the method + * setValues(0, List, 1, List.size() + 1) is invoked to set all elements of + * sample array from index 0 to ArrayReference from index 1. Since + * srcIndex + length is beyond the end of this array, IndexOutOfBoundsException + * should be thrown. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii005 + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValues_ilii.setvaluesilii005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005a.java new file mode 100644 index 00000000000..5ebfccebe5c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii005a.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_ilii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvaluesilii005a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvaluesilii005aClassToCheck classToCheck = new setvaluesilii005aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvaluesilii005aClassToCheck { + + // For each primitive type a sample array has the same length as + // correspondent tested array + static boolean z1[] = {false}; + static boolean z1S[] = {true}; + + static byte b1[] = {1, 2}; + static byte b1S[] = {Byte.MIN_VALUE, Byte.MAX_VALUE}; + + static char c1[] = {1, 2, 3}; + static char c1S[] = {Character.MIN_VALUE, '\u00ff', Character.MAX_VALUE}; + + static double d1[] = {1, 2, 3, 4}; + static double d1S[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0}; + + static float f1[] = {1, 2, 3, 4, 5}; + static float f1S[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + Float.NaN}; + + static int i1[] = {1, 2, 3, 4, 5, 6}; + static int i1S[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, -1}; + + static long l1[] = {1, 2, 3, 4, 5, 6, 7}; + static long l1S[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + + static short r1[] = {1, 2, 3, 4, 5, 6, 7, 8}; + static short r1S[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, + Short.MIN_VALUE, -1, 0}; + + static final long lF1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static private long lP1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static public long lU1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static protected long lR1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static transient long lT1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; + static volatile long lV1[] = {-2, -1, 0, 1, Long.MAX_VALUE, 0, 1}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001.java new file mode 100644 index 00000000000..323b8b06677 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001.java @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvaluesl001 { + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long"}, + {"lP1", "long"}, + {"lU1", "long"}, + {"lR1", "long"}, + {"lT1", "long"}, + {"lV1", "long"} + }; + + final static boolean BOOL[] = {true, false}; + final static byte BYTE[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + final static char CHAR[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE}; + final static double DOUB[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, + -1, -0, 0, 1, Double.MAX_VALUE, + Double.POSITIVE_INFINITY, Double.NaN}; + final static float FLOAT[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, + -1, -0, 0, 1, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, Float.NaN}; + final static int INT[] = {Integer.MIN_VALUE, -1, 0, 1, + Integer.MAX_VALUE, Integer.MIN_VALUE + 1}; + final static long LONG[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + final static short SHORT[] = {Short.MIN_VALUE, -1, 0, 1, + Short.MAX_VALUE}; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.setValues_l."; + private final static String className = "setvaluesl001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvaluesl001aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + Field fieldBoolean = null; + Field fieldByte = null; + Field fieldChar = null; + Field fieldDouble = null; + Field fieldFloat = null; + Field fieldInt = null; + Field fieldLong = null; + Field fieldShort = null; + ArrayReference arrayBoolean = null; + ArrayReference arrayByte = null; + ArrayReference arrayChar = null; + ArrayReference arrayDouble = null; + ArrayReference arrayFloat = null; + ArrayReference arrayInt = null; + ArrayReference arrayLong = null; + ArrayReference arrayShort = null; + List listBoolean = null; + List listByte = null; + List listChar = null; + List listDouble = null; + List listFloat = null; + List listInt = null; + List listLong = null; + List listShort = null; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Get all array samples of primitive types to set it to the + // ArrayReference + try { + fieldBoolean = refType.fieldByName("z1S"); + fieldByte = refType.fieldByName("b1S"); + fieldChar = refType.fieldByName("c1S"); + fieldDouble = refType.fieldByName("d1S"); + fieldFloat = refType.fieldByName("f1S"); + fieldInt = refType.fieldByName("i1S"); + fieldLong = refType.fieldByName("l1S"); + fieldShort = refType.fieldByName("r1S"); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample fields for primitive types."); + log.display("debuger> boolean is " + fieldBoolean); + log.display("debuger> byte is " + fieldByte); + log.display("debuger> char is " + fieldChar); + log.display("debuger> double is " + fieldDouble); + log.display("debuger> float is " + fieldFloat); + log.display("debuger> int is " + fieldInt); + log.display("debuger> long is " + fieldLong); + log.display("debuger> short is " + fieldShort + "\n"); + + if ((fieldBoolean == null) || (fieldByte == null) || + (fieldChar == null) || (fieldDouble == null) || + (fieldFloat == null) || (fieldInt == null) || + (fieldLong == null) || (fieldShort == null)) { + log.complain("debuger FAILURE> Cannot find field in debuggee."); + return 2; + } + + try { + arrayBoolean = (ArrayReference)refType.getValue(fieldBoolean); + arrayByte = (ArrayReference)refType.getValue(fieldByte); + arrayChar = (ArrayReference)refType.getValue(fieldChar); + arrayDouble = (ArrayReference)refType.getValue(fieldDouble); + arrayFloat = (ArrayReference)refType.getValue(fieldFloat); + arrayInt = (ArrayReference)refType.getValue(fieldInt); + arrayLong = (ArrayReference)refType.getValue(fieldLong); + arrayShort = (ArrayReference)refType.getValue(fieldShort); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ClassCastException e) { + log.complain("debuger FAILURE> Cannot get array reference for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } + log.display("debuger> Got sample array references for primitive " + + "types."); + log.display("debuger> boolean is " + arrayBoolean); + log.display("debuger> byte is " + arrayByte); + log.display("debuger> char is " + arrayChar); + log.display("debuger> double is " + arrayDouble); + log.display("debuger> float is " + arrayFloat); + log.display("debuger> int is " + arrayInt); + log.display("debuger> long is " + arrayLong); + log.display("debuger> short is " + arrayShort + "\n"); + + try { + listBoolean = arrayBoolean.getValues(); + listByte = arrayByte.getValues(); + listChar = arrayChar.getValues(); + listDouble = arrayDouble.getValues(); + listFloat = arrayFloat.getValues(); + listInt = arrayInt.getValues(); + listLong = arrayLong.getValues(); + listShort = arrayShort.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get list of values for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + listBoolean); + log.complain("debuger FAILURE> byte is " + listByte); + log.complain("debuger FAILURE> char is " + listChar); + log.complain("debuger FAILURE> double is " + listDouble); + log.complain("debuger FAILURE> float is " + listFloat); + log.complain("debuger FAILURE> int is " + listInt); + log.complain("debuger FAILURE> long is " + listLong); + log.complain("debuger FAILURE> short is " + listShort); + return 2; + } + log.display("debuger> Got list of values for primitive types."); + log.display("debuger> boolean is " + listBoolean); + log.display("debuger> byte is " + listByte); + log.display("debuger> char is " + listChar); + log.display("debuger> double is " + listDouble); + log.display("debuger> float is " + listFloat); + log.display("debuger> int is " + listInt); + log.display("debuger> long is " + listLong); + log.display("debuger> short is " + listShort + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String type = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listToSet; + List listRead; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Prepare list to set + if (type.equals("boolean")) { + listToSet = listBoolean; + } else if (type.equals("byte")) { + listToSet = listByte; + } else if (type.equals("char")) { + listToSet = listChar; + } else if (type.equals("double")) { + listToSet = listDouble; + } else if (type.equals("float")) { + listToSet = listFloat; + } else if (type.equals("int")) { + listToSet = listInt; + } else if (type.equals("long")) { + listToSet = listLong; + } else if (type.equals("short")) { + listToSet = listShort; + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + type); + testFailed = true; + continue; + } + + // Set the sample list of values + try { + arrayRef.setValues(listToSet); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: list of values set " + + listToSet); + + // Get the list of Values and check them + try { + listRead = arrayRef.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 6> Cannot get values from field " + + name); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: list of values read " + + listRead); + + for (int j = 0; j < listRead.size(); j++) { + if (type.equals("boolean")) { + + ///////////////////// Check boolean[] ///////////////////// + BooleanValue boolValue; + boolean element; + + try { + boolValue = (BooleanValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z1> Cannot cast to " + + "boolean " + j + " value of list " + + listRead); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + element = boolValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BOOL[j]) { + log.complain("debuger FAILURE Z2> " + j + " element " + + "of array " + name + " was expected " + + BOOL[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("byte")) { + + ///////////////////// Check byte[] ///////////////////// + ByteValue byteValue; + byte element; + + try { + byteValue = (ByteValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE B1> Cannot cast to " + + "byte " + j + " value of list " + + listRead); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + element = byteValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BYTE[j]) { + log.complain("debuger FAILURE B2> " + j + " element " + + "of array " + name + " was expected " + + BYTE[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("char")) { + + ///////////////////// Check char[] ///////////////////// + CharValue charValue; + char element; + + try { + charValue = (CharValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE C1> Cannot cast to " + + "char " + j + " value of list " + + listRead); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + element = charValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != CHAR[j]) { + log.complain("debuger FAILURE C2> " + j + " element " + + "of array " + name + " was expected " + + CHAR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("int")) { + + ///////////////////// Check int[] ///////////////////// + IntegerValue intValue; + int element; + + try { + intValue = (IntegerValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE I1> Cannot cast to " + + "int " + j + " value of list " + + listRead); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + element = intValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != INT[j]) { + log.complain("debuger FAILURE I2> " + j + " element " + + "of array " + name + " was expected " + + INT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long")) { + + ///////////////////// Check long[] ///////////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE L1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONG[j]) { + log.complain("debuger FAILURE L2> " + j + " element " + + "of array " + name + " was expected " + + LONG[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("short")) { + + ///////////////////// Check short[] ///////////////////// + ShortValue shortValue; + short element; + + try { + shortValue = (ShortValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE R1> Cannot cast to " + + "short " + j + " value of list " + + listRead); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + element = shortValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != SHORT[j]) { + log.complain("debuger FAILURE R2> " + j + " element " + + "of array " + name + " was expected " + + SHORT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("double")) { + + ///////////////////// Check double[] ///////////////////// + DoubleValue doubleValue; + Double element; + + try { + doubleValue = (DoubleValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE D1> Cannot cast to " + + "double " + j + " value of list " + + listRead); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + + element = new Double(doubleValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Double(DOUB[j]))) { + log.complain("debuger FAILURE D3> " + j + " element of " + + "array " + name + " was expected " + + DOUB[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("float")) { + + ///////////////////// Check float[] ///////////////////// + FloatValue floatValue; + Float element; + + try { + floatValue = (FloatValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE F1> Cannot cast to " + + "float " + j + " value of list " + + listRead); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + + element = new Float(floatValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Float(FLOAT[j]))) { + log.complain("debuger FAILURE F3> " + j + " element of " + + "array " + name + " was expected " + + FLOAT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else { + log.complain("debuger FAILURE 6> Unexpected type: " + type); + testFailed = true; + break; + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001/TestDescription.java new file mode 100644 index 00000000000..c2ccf452b28 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001/TestDescription.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValues_l/setvaluesl001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValues(List) method of ArrayReference interface of + * com.sun.jdi package. + * The method spec: + * public void setValues(List values) throws InvalidTypeException, + * ClassNotLoadedException + * Replaces all array components with other values. If the given list is + * larger is size than the array, the values at the end of the list are + * ignored. + * Object values must be assignment compatible with the element type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: values - a list of Value objects to be placed in this array + * Throws: InvalidTypeException - if any of the values is not compatible with + * the declared type of array components. + * java.lang.IndexOutOfBoundsException - if the size of values is + * larger than the length of this array. + * ClassNotLoadedException - if the array component type has not yet + * been loaded through the appropriate class loader. + * ObjectCollectedException - if this object or any of the new values + * has been garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValue_l/setvaluesl001 checks assertion: + * public Vvoid setValues(List values) + * 1. Replaces all array components with other values. Array has components of + * primitive types only. + * Debuggee defines eight sample array fields. One for each primitive type. + * Also, it defines tested array fields, that have the same length as + * correspondent sample field. + * Debugger gets each sample field from debuggee by name and gets its + * Value, casts it to ArrayReference and gets list of its Values. After that + * the test gets tested array fields by name, gets their values, casts to + * ArrayReference types and invoke the method setValues(List) to set the + * sample list to that ArrayReference. + * After that the test gets all Values of the array and checks them. Debugger + * determines component's type (by field's name), gets each element of the + * list, casts it to correspondent PrimitiveType and then gets its primitive + * value. Then the test compares returned and expected primitive values. + * COMMENTS + * 4419982: JDI: two StackFrame methods return incorrect values for double + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValues_l.setvaluesl001 + * nsk.jdi.ArrayReference.setValues_l.setvaluesl001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValues_l.setvaluesl001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001a.java new file mode 100644 index 00000000000..6aa2b1db051 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001a.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvaluesl001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvaluesl001aClassToCheck classToCheck = new setvaluesl001aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvaluesl001aClassToCheck { + static boolean z1[] = {false, true}; + static boolean z1S[] = {true, false}; + + static byte b1[] = {0, 1, 2, 3, 4}; + static byte b1S[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + + static char c1[] = {0, 1, 2, 3}; + static char c1S[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE}; + + static double d1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + static double d1S[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN}; + + static float f1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + static float f1S[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + 0, 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN}; + + static int i1[] = {0, 1, 2, 3, 4, 5}; + static int i1S[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, + Integer.MIN_VALUE + 1}; + + static long l1[] = {0, 1, 2, 3, 4}; + static long l1S[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + + static short r1[] = {0, 1, 2, 3, 4}; + static short r1S[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE}; + + static final long lF1[] = {0, 1, 2, 3, 4}; + static private long lP1[] = {0, 1, 2, 3, 4}; + static public long lU1[] = {0, 1, 2, 3, 4}; + static protected long lR1[] = {0, 1, 2, 3, 4}; + static transient long lT1[] = {0, 1, 2, 3, 4}; + static volatile long lV1[] = {0, 1, 2, 3, 4}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002.java new file mode 100644 index 00000000000..d4f7f631581 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002.java @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvaluesl002 { + final static String FIELD_NAME[][] = { + {"z1", "boolean"}, + {"b1", "byte"}, + {"c1", "char"}, + {"d1", "double"}, + {"f1", "float"}, + {"i1", "int"}, + {"l1", "long"}, + {"r1", "short"}, + + {"lF1", "long"}, + {"lP1", "long"}, + {"lU1", "long"}, + {"lR1", "long"}, + {"lT1", "long"}, + {"lV1", "long"} + }; + + final static boolean BOOL[] = {true, false}; + final static byte BYTE[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE}; + final static char CHAR[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE}; + final static double DOUB[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, + -1, -0, 0, 1, Double.MAX_VALUE, + Double.POSITIVE_INFINITY, Double.NaN}; + final static float FLOAT[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, + -1, -0, 0, 1, Float.MAX_VALUE, + Float.POSITIVE_INFINITY, Float.NaN}; + final static int INT[] = {Integer.MIN_VALUE, -1, 0, 1, + Integer.MAX_VALUE, Integer.MIN_VALUE + 1}; + final static long LONG[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE}; + final static short SHORT[] = {Short.MIN_VALUE, -1, 0, 1, + Short.MAX_VALUE}; + + private static Log log; + private final static String prefix = "nsk.jdi.ArrayReference.setValues_l."; + private final static String className = "setvaluesl002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "setvaluesl002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debugee.createIOPipe(); + boolean testFailed = false; + Field fieldBoolean = null; + Field fieldByte = null; + Field fieldChar = null; + Field fieldDouble = null; + Field fieldFloat = null; + Field fieldInt = null; + Field fieldLong = null; + Field fieldShort = null; + ArrayReference arrayBoolean = null; + ArrayReference arrayByte = null; + ArrayReference arrayChar = null; + ArrayReference arrayDouble = null; + ArrayReference arrayFloat = null; + ArrayReference arrayInt = null; + ArrayReference arrayLong = null; + ArrayReference arrayShort = null; + List listBoolean = null; + List listByte = null; + List listChar = null; + List listDouble = null; + List listFloat = null; + List listInt = null; + List listLong = null; + List listShort = null; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length + "\n"); + + // Get all array samples of primitive types to set it to the + // ArrayReference + try { + fieldBoolean = refType.fieldByName("z1S"); + fieldByte = refType.fieldByName("b1S"); + fieldChar = refType.fieldByName("c1S"); + fieldDouble = refType.fieldByName("d1S"); + fieldFloat = refType.fieldByName("f1S"); + fieldInt = refType.fieldByName("i1S"); + fieldLong = refType.fieldByName("l1S"); + fieldShort = refType.fieldByName("r1S"); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get field by name."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + fieldBoolean); + log.complain("debuger FAILURE> byte is " + fieldByte); + log.complain("debuger FAILURE> char is " + fieldChar); + log.complain("debuger FAILURE> double is " + fieldDouble); + log.complain("debuger FAILURE> float is " + fieldFloat); + log.complain("debuger FAILURE> int is " + fieldInt); + log.complain("debuger FAILURE> long is " + fieldLong); + log.complain("debuger FAILURE> short is " + fieldShort); + return 2; + } + log.display("debuger> Got sample fields for primitive types."); + log.display("debuger> boolean is " + fieldBoolean); + log.display("debuger> byte is " + fieldByte); + log.display("debuger> char is " + fieldChar); + log.display("debuger> double is " + fieldDouble); + log.display("debuger> float is " + fieldFloat); + log.display("debuger> int is " + fieldInt); + log.display("debuger> long is " + fieldLong); + log.display("debuger> short is " + fieldShort + "\n"); + + if ((fieldBoolean == null) || (fieldByte == null) || + (fieldChar == null) || (fieldDouble == null) || + (fieldFloat == null) || (fieldInt == null) || + (fieldLong == null) || (fieldShort == null)) { + log.complain("debuger FAILURE> Cannot find field in debuggee."); + return 2; + } + + try { + arrayBoolean = (ArrayReference)refType.getValue(fieldBoolean); + arrayByte = (ArrayReference)refType.getValue(fieldByte); + arrayChar = (ArrayReference)refType.getValue(fieldChar); + arrayDouble = (ArrayReference)refType.getValue(fieldDouble); + arrayFloat = (ArrayReference)refType.getValue(fieldFloat); + arrayInt = (ArrayReference)refType.getValue(fieldInt); + arrayLong = (ArrayReference)refType.getValue(fieldLong); + arrayShort = (ArrayReference)refType.getValue(fieldShort); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get values for fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } catch (ClassCastException e) { + log.complain("debuger FAILURE> Cannot get array reference for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + arrayBoolean); + log.complain("debuger FAILURE> byte is " + arrayByte); + log.complain("debuger FAILURE> char is " + arrayChar); + log.complain("debuger FAILURE> double is " + arrayDouble); + log.complain("debuger FAILURE> float is " + arrayFloat); + log.complain("debuger FAILURE> int is " + arrayInt); + log.complain("debuger FAILURE> long is " + arrayLong); + log.complain("debuger FAILURE> short is " + arrayShort); + return 2; + } + log.display("debuger> Got sample array references for primitive " + + "types."); + log.display("debuger> boolean is " + arrayBoolean); + log.display("debuger> byte is " + arrayByte); + log.display("debuger> char is " + arrayChar); + log.display("debuger> double is " + arrayDouble); + log.display("debuger> float is " + arrayFloat); + log.display("debuger> int is " + arrayInt); + log.display("debuger> long is " + arrayLong); + log.display("debuger> short is " + arrayShort + "\n"); + + try { + listBoolean = arrayBoolean.getValues(); + listByte = arrayByte.getValues(); + listChar = arrayChar.getValues(); + listDouble = arrayDouble.getValues(); + listFloat = arrayFloat.getValues(); + listInt = arrayInt.getValues(); + listLong = arrayLong.getValues(); + listShort = arrayShort.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get list of values for " + + "fields."); + log.complain("debuger FAILURE> Exception: " + e); + log.complain("debuger FAILURE> boolean is " + listBoolean); + log.complain("debuger FAILURE> byte is " + listByte); + log.complain("debuger FAILURE> char is " + listChar); + log.complain("debuger FAILURE> double is " + listDouble); + log.complain("debuger FAILURE> float is " + listFloat); + log.complain("debuger FAILURE> int is " + listInt); + log.complain("debuger FAILURE> long is " + listLong); + log.complain("debuger FAILURE> short is " + listShort); + return 2; + } + log.display("debuger> Got list of values for primitive types."); + log.display("debuger> boolean is " + listBoolean); + log.display("debuger> byte is " + listByte); + log.display("debuger> char is " + listChar); + log.display("debuger> double is " + listDouble); + log.display("debuger> float is " + listFloat); + log.display("debuger> int is " + listInt); + log.display("debuger> long is " + listLong); + log.display("debuger> short is " + listShort + "\n"); + + // Check all array fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name = FIELD_NAME[i][0]; + String type = FIELD_NAME[i][1]; + Value value; + ArrayReference arrayRef; + List listToSet; + List listRead; + + // Get field from debuggee by name + try { + field = refType.fieldByName(name); + } catch (ClassNotPreparedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + field + " read."); + + // Get field's value + try { + value = refType.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 2> Cannot get value for field " + + name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field value is " + value); + + // Cast to ArrayReference. All fields in debugee are + // arrays, so ClassCastException should not be thrown + try { + arrayRef = (ArrayReference)value; + } catch (ClassCastException e) { + log.complain("debuger FAILURE 3> Cannot cast value for field " + + name + " to ArrayReference."); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + + // Prepare list to set + if (type.equals("boolean")) { + listToSet = listBoolean; + } else if (type.equals("byte")) { + listToSet = listByte; + } else if (type.equals("char")) { + listToSet = listChar; + } else if (type.equals("double")) { + listToSet = listDouble; + } else if (type.equals("float")) { + listToSet = listFloat; + } else if (type.equals("int")) { + listToSet = listInt; + } else if (type.equals("long")) { + listToSet = listLong; + } else if (type.equals("short")) { + listToSet = listShort; + } else { + log.complain("debuger FAILURE 4> Unexpected type: " + type); + testFailed = true; + continue; + } + + // Set the sample list of values + try { + arrayRef.setValues(listToSet); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (IndexOutOfBoundsException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (InvalidTypeException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } catch (VMMismatchException e) { + log.complain("debuger FAILURE 5> Cannot set list of values " + + listToSet + " to the field " + name); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: list of values set " + + listToSet); + + // Get the list of Values and check them + try { + listRead = arrayRef.getValues(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 6> Cannot get values from field " + + name); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field: list of values read " + + listRead); + + for (int j = 0; j < listRead.size(); j++) { + if (type.equals("boolean")) { + + ///////////////////// Check boolean[] ///////////////////// + BooleanValue boolValue; + boolean element; + + try { + boolValue = (BooleanValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE Z1> Cannot cast to " + + "boolean " + j + " value of list " + + listRead); + log.complain("debuger FAILURE Z1> Exception: " + e); + testFailed = true; + continue; + } + element = boolValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BOOL[j]) { + log.complain("debuger FAILURE Z2> " + j + " element " + + "of array " + name + " was expected " + + BOOL[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("byte")) { + + ///////////////////// Check byte[] ///////////////////// + ByteValue byteValue; + byte element; + + try { + byteValue = (ByteValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE B1> Cannot cast to " + + "byte " + j + " value of list " + + listRead); + log.complain("debuger FAILURE B1> Exception: " + e); + testFailed = true; + continue; + } + element = byteValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != BYTE[j]) { + log.complain("debuger FAILURE B2> " + j + " element " + + "of array " + name + " was expected " + + BYTE[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("char")) { + + ///////////////////// Check char[] ///////////////////// + CharValue charValue; + char element; + + try { + charValue = (CharValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE C1> Cannot cast to " + + "char " + j + " value of list " + + listRead); + log.complain("debuger FAILURE C1> Exception: " + e); + testFailed = true; + continue; + } + element = charValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != CHAR[j]) { + log.complain("debuger FAILURE C2> " + j + " element " + + "of array " + name + " was expected " + + CHAR[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("int")) { + + ///////////////////// Check int[] ///////////////////// + IntegerValue intValue; + int element; + + try { + intValue = (IntegerValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE I1> Cannot cast to " + + "int " + j + " value of list " + + listRead); + log.complain("debuger FAILURE I1> Exception: " + e); + testFailed = true; + continue; + } + element = intValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != INT[j]) { + log.complain("debuger FAILURE I2> " + j + " element " + + "of array " + name + " was expected " + + INT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("long")) { + + ///////////////////// Check long[] ///////////////////// + LongValue longValue; + long element; + + try { + longValue = (LongValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE L1> Cannot cast to " + + "long " + j + " value of list " + + listRead); + log.complain("debuger FAILURE L1> Exception: " + e); + testFailed = true; + continue; + } + element = longValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != LONG[j]) { + log.complain("debuger FAILURE L2> " + j + " element " + + "of array " + name + " was expected " + + LONG[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("short")) { + + ///////////////////// Check short[] ///////////////////// + ShortValue shortValue; + short element; + + try { + shortValue = (ShortValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE R1> Cannot cast to " + + "short " + j + " value of list " + + listRead); + log.complain("debuger FAILURE R1> Exception: " + e); + testFailed = true; + continue; + } + element = shortValue.value(); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + // Check element's value + if (element != SHORT[j]) { + log.complain("debuger FAILURE R2> " + j + " element " + + "of array " + name + " was expected " + + SHORT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("double")) { + + ///////////////////// Check double[] ///////////////////// + DoubleValue doubleValue; + Double element; + + try { + doubleValue = (DoubleValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE D1> Cannot cast to " + + "double " + j + " value of list " + + listRead); + log.complain("debuger FAILURE D1> Exception: " + e); + testFailed = true; + continue; + } + + element = new Double(doubleValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Double(DOUB[j]))) { + log.complain("debuger FAILURE D3> " + j + " element of " + + "array " + name + " was expected " + + DOUB[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else if (type.equals("float")) { + + ///////////////////// Check float[] ///////////////////// + FloatValue floatValue; + Float element; + + try { + floatValue = (FloatValue)listRead.get(j); + } catch (ClassCastException e) { + log.complain("debuger FAILURE F1> Cannot cast to " + + "float " + j + " value of list " + + listRead); + log.complain("debuger FAILURE F1> Exception: " + e); + testFailed = true; + continue; + } + + element = new Float(floatValue.value()); + log.display("debuger> " + i + " field has " + j + + " element " + element); + + if (!element.equals(new Float(FLOAT[j]))) { + log.complain("debuger FAILURE F3> " + j + " element of " + + "array " + name + " was expected " + + FLOAT[j] + ", but returned " + element); + testFailed = true; + continue; + } + } else { + log.complain("debuger FAILURE 6> Unexpected type: " + type); + testFailed = true; + break; + } + } + log.display("debuger> " + i + " field checked.\n"); + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002/TestDescription.java new file mode 100644 index 00000000000..8ba9379c161 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002/TestDescription.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValues_l/setvaluesl002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the setValues(List) method of ArrayReference interface of + * com.sun.jdi package. + * The method spec: + * public void setValues(List values) throws InvalidTypeException, + * ClassNotLoadedException + * Replaces all array components with other values. If the given list is + * larger is size than the array, the values at the end of the list are + * ignored. + * Object values must be assignment compatible with the element type (This + * implies that the component type must be loaded through the enclosing class's + * class loader). Primitive values must be either assignment compatible with + * the component type or must be convertible to the component type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * Parameters: values - a list of Value objects to be placed in this array + * Throws: InvalidTypeException - if any of the values is not compatible with + * the declared type of array components. + * java.lang.IndexOutOfBoundsException - if the size of values is + * larger than the length of this array. + * ClassNotLoadedException - if the array component type has not yet + * been loaded through the appropriate class loader. + * ObjectCollectedException - if this object or any of the new values + * has been garbage collected. + * VMMismatchException - if a Mirror argument and this object do not + * belong to the same VirtualMachine. + * nsk/jdi/ArrayReference/setValue_l/setvaluesl002 checks assertion: + * public void setValues(List values) + * 1. Replaces all array components with other values. Array has components of + * primitive types only. The list is larger than the array, so the values + * at the end of the list is ignored. + * Debuggee defines eight sample array fields. One for each primitive type. + * Also, it defines tested array fields, that have at least one more element + * then correspondent sample field. + * Debugger gets each sample field from debuggee by name and gets its + * Value, casts it to ArrayReference and gets list of its Values. After that + * the test gets tested array fields by name, gets their values, casts to + * ArrayReference types and invoke the method setValues(List) to set the + * sample list to that ArrayReference. The read list of tested array is larger + * than the array, so the values at the end of the list should be ignored. + * After that the test gets all Values of the array and checks them. Debugger + * determines component's type (by field's name), gets each element of the + * list, casts it to correspondent PrimitiveType and then gets its primitive + * value. Then the test compares returned and expected primitive values. + * COMMENTS + * 4448603: JDI spec: ArrayReference.setValues(List) has discrepancy + * Evaluation: + * There is indeed an inconsistency. The safer of the two options should be + * choosen: ignore tail elements in Lists that are too long. This is also what + * the reference implementation does. + * 4419982: JDI: two StackFrame methods return incorrect values for double + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValues_l.setvaluesl002 + * nsk.jdi.ArrayReference.setValues_l.setvaluesl002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValues_l.setvaluesl002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002a.java new file mode 100644 index 00000000000..053c12755c0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002a.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayReference.setValues_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvaluesl002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + setvaluesl002aClassToCheck classToCheck = new setvaluesl002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class setvaluesl002aClassToCheck { + + static boolean z1[] = {false, true}; + static boolean z1S[] = {true, false, true}; + + static byte b1[] = {0, 1, 2, 3, 4}; + static byte b1S[] = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, 0}; + + static char c1[] = {0, 1, 2, 3}; + static char c1S[] = {Character.MIN_VALUE, '\u00ff', '\uff00', + Character.MAX_VALUE, Character.MAX_VALUE}; + + static double d1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + static double d1S[] = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, -1, -0, + 0, 1, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN, -0}; + + static float f1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + static float f1S[] = {Float.NEGATIVE_INFINITY, Float.MIN_VALUE, -1, -0, + 0, 1, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN, -0}; + + static int i1[] = {0, 1, 2, 3, 4, 5}; + static int i1S[] = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE, + Integer.MIN_VALUE + 1, 0}; + + static long l1[] = {0, 1, 2, 3, 4}; + static long l1S[] = {Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE, 0}; + + static short r1[] = {0, 1, 2, 3, 4}; + static short r1S[] = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE, 0}; + + static final long lF1[] = {0, 1, 2, 3, 4}; + static private long lP1[] = {0, 1, 2, 3, 4}; + static public long lU1[] = {0, 1, 2, 3, 4}; + static protected long lR1[] = {0, 1, 2, 3, 4}; + static transient long lT1[] = {0, 1, 2, 3, 4}; + static volatile long lV1[] = {0, 1, 2, 3, 4}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003.java new file mode 100644 index 00000000000..ce3dfd9412b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.setValues_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class setvaluesl003 { + + private int[] failedTypes; + + private final static String prefix = "nsk.jdi.ArrayReference.setValues_l."; + private final static String className = "setvaluesl003"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + + private static Log log; + + private int exitStatus; + private Debugee debugee; + private IOPipe pipe; + private ReferenceType refType; + private ObjectReference testedObject; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + setvaluesl003 tstObj = new setvaluesl003(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + tstObj.debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + tstObj.execTest(); + tstObj.debugee.quit(); + + return tstObj.exitStatus; + } + + private void display(String msg) { + if ( log != null ) + log.display("debugger> " + msg); + } + + private void complain(String msg) { + if ( log != null ) + log.complain("debugger FAILURE> " + msg); + } + + private boolean execTest() { + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("eventHandler:: Class '" + debugeeName + "' not found."); + return false; + } + + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("eventHandler:: Field '" + objectToCheck + "' not found."); + return false; + } + + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("eventHandler:: Field '" + objectToCheck + + "' not initialized."); + return false; + } + + boolean res = checkObjectFields(objectValue); + exitStatus = res ? Consts.TEST_PASSED : Consts.TEST_FAILED; + + if ( exitStatus == Consts.TEST_FAILED ) + complain("run:: TEST FAILED"); + else + display("run:: TEST PASSED"); + + return res; + } + + public boolean checkObjectFields(Value objectValue) { + List fieldList; + if ( ! (objectValue instanceof ObjectReference) ) + return false; + + testedObject = (ObjectReference )objectValue; + fieldList = ((ClassType )testedObject.type()).allFields(); + + // Check all array fields from debugee + display("checkObjectFields:: Tests starts >>>"); + boolean res = true; + failedTypes = new int[7]; + for ( int i = 0; i < fieldList.size(); i++) { + res = checkFieldValue((Field )fieldList.get(i)) && res; + } + + return res; + } + + private boolean checkFieldValue(Field field) { + Value fieldValue; + ArrayReference arrayRef; + String fieldName = field.name(); + log.display(""); +// log.display("<" + fieldName + "> field is being checked."); + try { + fieldValue = testedObject.getValue(field); + } catch (IllegalArgumentException e) { + log.complain("checkFieldValue:: can not get value for field " + fieldName); + log.complain("checkFieldValue:: " + e); + return false; + } + + log.display("***<" + fieldName + "> = " + fieldValue); + log.display("-----------------------------------------------------"); + + // Checking up of value type. + // Tested object doesn't have other fields than be ArrayType + if ( ! (fieldValue.type() instanceof ArrayType) ) { + log.display("type of value is not ArrayType."); + return false; + } + + boolean res = true; + + Type itemType; + try { + itemType = ((ArrayType )fieldValue.type()).componentType(); + } catch(Exception e) { + log.complain("Unexpected " + e.getClass().getName() ); + return false; + } + + // Checking up of test cases. + + for ( int i = 0; i < failedTypes.length; i++ ) failedTypes[i] = i; + + List valuesList; + // for every type + for ( int i = 0; i < failedTypes.length; i++) { + valuesList = generateValuesList(i); + if ( valuesList == null ) { + log.complain("no values list for <" + fieldName + "> " + + setvaluesl003a.COMBINE[i]); + res = false; + continue; + } + res = checkValueUpdating(fieldName, (ArrayReference )fieldValue, + valuesList, i) && res; + } + + // for all passed types + valuesList = generateValuesList(-1); + if ( valuesList == null ) { + log.complain("no values list for <" + fieldName + "> "); + return false; + } + res = checkValueUpdating(fieldName, (ArrayReference )fieldValue, + valuesList, -1) && res; + res = checkValueUpdating(fieldName, (ArrayReference )fieldValue, + null, -1) && res; + log.display(""); + return res; + } + + // when index >= failedTypes.length(), all passed types are added into generated list + private List generateValuesList(int index) { + ArrayReference values; + Field fieldOfValues = null; + if ( index < setvaluesl003a.COMBINE.length && index >= 0 ) { + fieldOfValues = refType.fieldByName(setvaluesl003a.COMBINE[index]); + try { + if ( fieldOfValues == null || + !(fieldOfValues.type() instanceof ArrayType) ) { + log.complain("fieldOfValues " + fieldOfValues + " " + + setvaluesl003a.COMBINE[index]); + return null; + } + } catch (ClassNotLoadedException e) { + log.complain("unexpected exception " + e); + return null; + } + values = (ArrayReference )refType.getValue(fieldOfValues); + return values.getValues(); + } + + List valuesList = new Vector(); + for ( int i = 0; i < failedTypes.length; i++) { + if ( failedTypes[i] < 0 ) continue; + fieldOfValues = refType.fieldByName(setvaluesl003a.COMBINE[i]); + try { + if ( fieldOfValues == null || + !(fieldOfValues.type() instanceof ArrayType) ) { + log.complain("fieldOfValues " + fieldOfValues + " " + + setvaluesl003a.COMBINE[i]); + return null; + } + } catch (ClassNotLoadedException e) { + log.complain("unexpected exception " + e); + return null; + } + values = (ArrayReference )refType.getValue(fieldOfValues); + for ( int j = 0; j < values.length(); j++ ) { + valuesList.add(values.getValue(j)); + } + } + if ( valuesList.size() == 0 ) valuesList = null; + + return valuesList; + } + + private boolean checkValueUpdating(String name, ArrayReference arrayRef, + List values, int index) { + Value itemValue; + List list; + + boolean validConversion = true; + + String valuesStr = ""; + if ( values != null ) { + for ( int i = 0; i < values.size(); i++ ) { + valuesStr = valuesStr + (Value )values.get(i) + "; "; + validConversion = validConversion && + isValidConversion((ArrayType )arrayRef.type(), + ((Value )values.get(i)).type()); + } + } + + if ( index < 0 ) + log.display("values list: (mixed)" + valuesStr); + else + log.display("values list: (" + ((Value )values.get(0)).type() + ")" + valuesStr); + + try { + arrayRef.setValues(values); + + if ( !validConversion ) { + log.complain(" InvalidTypeException is expected"); + log.display("\n"); + return false; + } + + if ( values == null ) { + log.complain(" NullPointerException is expected"); + log.display("\n"); + return false; + } + log.display(" expected NullPointerException"); + + if ( !checkValues(arrayRef, values) ) { + log.complain(" Wrong result of setting"); + log.display("\n"); + return false; + } + + log.display(" Values were correctly set"); + + } catch (InvalidTypeException e) { + + if ( index >= 0 ) failedTypes[index] = -1; + + if ( validConversion ) { + log.complain(" unexpected InvalidTypeException"); + log.display("\n"); + return false; + } + log.display(" expected InvalidTypeException"); + + } catch (ClassNotLoadedException e) { + + log.complain(" unexpected ClassNotLoadedException"); + log.display("\n"); + return false; + } catch (NullPointerException e) { + + if ( values != null ) { + log.complain(" Unexpected NullPointerException"); + return false; + } + log.display(" expected NullPointerException"); + } catch (Exception e) { + log.complain(" Unexpected exception: " + e); + log.display("\n"); + return false; + } + return true; + } + + private boolean isValidConversion(ArrayType arrType, Type valueType) { + String typeSignature = "BCDFIJS"; + Type type = null; + try { + type = arrType.componentType(); + } catch(ClassNotLoadedException e) { + return true; // have to be true always + } + int i = typeSignature.indexOf(type.signature()); + return -1 != setvaluesl003a.VALID_CONVERSIONS[i].indexOf(valueType.signature()); + } + + private boolean checkValues(ArrayReference array, List list) { + if ( list == null ) return true; + int length = array.length() < list.size() ? array.length() + : list.size(); + PrimitiveValue val1, val2; + for ( int i = 0; i < length; i++ ) { + val1 = (PrimitiveValue )array.getValue(i); + val2 = (PrimitiveValue )list.get(i); + if ( !val1.equals(val2) ) { + Type type = val1.type(); + if ( type instanceof ByteType ) + return val1.byteValue() == val2.byteValue(); + else if ( type instanceof CharType ) + return val1.charValue() == val2.charValue(); + else if ( type instanceof DoubleType ) + return val1.doubleValue() == val2.doubleValue(); + else if ( type instanceof FloatType ) + return val1.floatValue() == val2.floatValue(); + else if ( type instanceof IntegerType ) + return val1.intValue() == val2.intValue(); + else if ( type instanceof LongType ) + return val1.longValue() == val2.longValue(); + else if ( type instanceof ShortType ) + return val1.shortValue() == val2.shortValue(); + else + return false; + } + } + return true; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003/TestDescription.java new file mode 100644 index 00000000000..3e881aaad95 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003/TestDescription.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayReference/setValues_l/setvaluesl003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.ArrayReference.setValue(int, Value) + * correctly works for the boundary value of parameter and complies with its + * spec: + * public void setValues(List values) + * throws InvalidTypeException, + * ClassNotLoadedException + * Replaces all array components with other values. If the given list is + * larger in size than the array, the values at the end of the list are + * ignored. + * Object values must be assignment compatible with the element type + * (This implies that the component type must be loaded through the + * enclosing class's class loader). Primitive values must be either + * assignment compatible with the component type or must be convertible + * to the component type without loss of information. See JLS section 5.2 + * for more information on assignment compatibility. + * Parameters: + * values - a list of Value objects to be placed in this array. + * If values.size() is less that the length of the array, the first + * values.size() elements are set. + * Throws: + * InvalidTypeException - if any of the new values is not compatible + * with the declared type of array components. + * ClassNotLoadedException - if the array component type has not yet + * been loaded through the appropriate class loader. + * The test cases include instance fields of the primitive types, which are + * one-dimensional arrays. Possible values of parameter of the method + * are generated from debugee's arrays, which contains boundary values of + * every primitive type. + * Every tested array of primitive type is checked in several steps: + * 1. List parameter consists of values of the same primitive types. + * InvalidTypeException is expected, when primitive values are neither + * assignment compatible with the component type nor are convertible + * to the component type without loss of information. + * 2. List is generated from primitive values passed in first step. + * In this case no exceptions are expected. + * 3. List has null value. In this case NullPointerException is + * excpected. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayReference.setValue.setvalue003; + * the debuggee program - nsk.jdi.ArrayReference.setValue.setvalue003a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running on + * another JavaVM, establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies via the pipe. + * Upon getting reply, the debugger requests fields of checked object + * and trys to set a value of arry items correspondence with the test cases + * above. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayReference.setValues_l.setvaluesl003 + * nsk.jdi.ArrayReference.setValues_l.setvaluesl003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayReference.setValues_l.setvaluesl003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003a.java new file mode 100644 index 00000000000..af7258a5f77 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl003a.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ArrayReference.setValues_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class setvaluesl003a { + + static setvaluesl003aClassToCheck testedObj = new setvaluesl003aClassToCheck(); + + + public static final String[] VALID_CONVERSIONS = { + "B", // primitive types to byte + "C", // primitive types to char + "BCDFIJS", // primitive types to double + "BCFIJS", // primitive types to float + "BCIS", // primitive types to int + "BCIJS", // primitive types to long + "BS" // primitive types to short + }; + + + public final static String[] COMBINE = { + "BYTE_VALUES", + "CHAR_VALUES", + "DBL_VALUES", + "FLT_VALUES", + "INT_VALUES", + "LNG_VALUES", + "SHORT_VALUES" + }; + + // Value parameter's array for debugee's arrays + public static byte[] BYTE_VALUES = { + Byte.MIN_VALUE, + -1, + 0, + 1, + Byte.MAX_VALUE + }; + + public static char[] CHAR_VALUES = { + Character.MIN_VALUE, + 'a', + 'z', + 'A', + 'Z', + Character.MAX_VALUE + }; + + public static double[] DBL_VALUES = { + Double.NEGATIVE_INFINITY, + Double.MIN_VALUE, + -1, + 0, + 1, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY + }; + + public static float[] FLT_VALUES = { + Float.NEGATIVE_INFINITY, + Float.MIN_VALUE, + -1, + 0, + 1, + Float.MAX_VALUE, + Float.POSITIVE_INFINITY + }; + + public static int[] INT_VALUES = { + Integer.MIN_VALUE, + -1, + 0, + 1, + Integer.MAX_VALUE + }; + + public static long[] LNG_VALUES = { + Long.MIN_VALUE, + -1, + 0, + 1, + Long.MAX_VALUE + }; + + public static short[] SHORT_VALUES = { + Short.MIN_VALUE, + -1, + 0, + 1, + Short.MAX_VALUE + }; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class setvaluesl003aClassToCheck { + public byte[] publicByteArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected byte[] protecByteArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private byte[] privatByteArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public char[] publicCharArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + protected char[] protecCharArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + private char[] privatCharArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + + public double[] publicDoubleArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected double[] protecDoubleArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private double[] privatDoubleArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public float[] publicFloatArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected float[] protecFloatArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private float[] privatFloatArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public int[] publicIntArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected int[] protecIntArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private int[] privatIntArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public long[] publicLongArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected long[] protecLongArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private long[] privatLongArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public short[] publicShortArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + protected short[] protecShortArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + private short[] privatShortArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001.java new file mode 100644 index 00000000000..1ae6a0796b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.componentSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.componentSignature()
    + * complies with its spec when a type is one of primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee executes the following :
    + * static boolean bl[] = {true, false};
    + * static byte bt[] = {0, 1};
    + * static char ch[] = {0, 1};
    + * static double db[] = {0.0d, 1.0d};
    + * static float fl[] = {0.0f, 1.0f};
    + * static int in[] = {0, 1};
    + * static long ln[] = {0, 1};
    + * static short sh[] = {0, 1};
    + *
    + * for all of the above primitive type variables,
    + * a debugger forms their corresponding Type objects
    + * from which it forms text representations of
    + * signatures in String variables
    + * named blSignature, btSignature, and etc.
    + *
    + * Then the debugger checks up that
    + * each of the following is true :
    + *
    + * blSignature.equals("Z")
    + * btSignature.equals("B")
    + * chSignature.equals("C")
    + * dbSignature.equals("D")
    + * flSignature.equals("F")
    + * inSignature.equals("I")
    + * lnSignature.equals("J")
    + * shSignature.equals("S")
    + */ + +public class componentsignature001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/componentSignature/componentsignature001", + sHeader2 = "--> componentsignature001: ", + sHeader3 = "##> componentsignature001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new componentsignature001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.componentSignature.componentsignature001a"; + + //String mName = "nsk.jdi.ArrayType.componentSignature"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("componentsignature001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl = execClass.fieldByName("bl"); + Field fsbt = execClass.fieldByName("bt"); + Field fsch = execClass.fieldByName("ch"); + Field fsdb = execClass.fieldByName("db"); + Field fsfl = execClass.fieldByName("fl"); + Field fsin = execClass.fieldByName("in"); + Field fsln = execClass.fieldByName("ln"); + Field fssh = execClass.fieldByName("sh"); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean[] + String blSignature = + ((ArrayType) execClass.getValue(fsbl).type()).componentSignature(); + if (!blSignature.equals("Z")) { + expresult = 1; + log3("ERROR: !blSignature.equals('[Z') " + blSignature); + } + break; + + case 1: // byte[] + String btSignature = + ((ArrayType) execClass.getValue(fsbt).type()).componentSignature(); + if (!btSignature.equals("B")) { + expresult = 1; + log3("ERROR: !btSignature.equals('B')"); + } + break; + + case 2: // char[] + String chSignature = + ((ArrayType) execClass.getValue(fsch).type()).componentSignature(); + if (!chSignature.equals("C")) { + expresult = 1; + log3("ERROR: !chSignature.equals('C')"); + } + break; + + case 3: // double[] + String dbSignature = + ((ArrayType) execClass.getValue(fsdb).type()).componentSignature(); + if (!dbSignature.equals("D")) { + expresult = 1; + log3("ERROR: !dbSignature.equals('D')"); + } + break; + + case 4: // float[] + String flSignature = + ((ArrayType) execClass.getValue(fsfl).type()).componentSignature(); + if (!flSignature.equals("F")) { + expresult = 1; + log3("ERROR: !flSignature.equals('F')"); + } + break; + + case 5: // int[] + String inSignature = + ((ArrayType) execClass.getValue(fsin).type()).componentSignature(); + if (!inSignature.equals("I")) { + expresult = 1; + log3("ERROR: !inSignature.equals('I')"); + } + break; + + case 6: // long[] + String lnSignature = + ((ArrayType) execClass.getValue(fsln).type()).componentSignature(); + if (!lnSignature.equals("J")) { + expresult = 1; + log3("ERROR: !lnSignature.equals('J')"); + } + break; + + case 7: // short[] + String shSignature = + ((ArrayType) execClass.getValue(fssh).type()).componentSignature(); + if (!shSignature.equals("S")) { + expresult = 1; + log3("ERROR: !shSignature.equals('S')"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001/TestDescription.java new file mode 100644 index 00000000000..b1e703883eb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/componentSignature/componentsignature001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.componentSignature() + * complies with its spec: + * public java.lang.String componentSignature() + * Gets the JNI signature of the components of this array class. + * The signature describes the declared type of the components. + * If the components are objects, their actual type in + * a particular run-time context may be a subclass of the declared class. + * Returns: a string containing the JNI signature of array components. + * Throws: ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * when the type is one of the primitive types. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.componentSignature.componentsignature001; + * the debuggee program - nsk.jdi.ArrayType.componentSignature.componentsignature001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.componentSignature.componentsignature001 + * nsk.jdi.ArrayType.componentSignature.componentsignature001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.componentSignature.componentsignature001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001a.java new file mode 100644 index 00000000000..5ea82095a36 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature001a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.componentSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the componentsignature001 JDI test. + */ + +public class componentsignature001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> componentsignature001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> componentsignature001a: " + message); + } + + //====================================================== test program + + static boolean bl[] = {true, false}; + static byte bt[] = {0, 1}; + static char ch[] = {0, 1}; + static double db[] = {0.0d, 1.0d}; + static float fl[] = {0.0f, 1.0f}; + static int in[] = {0, 1}; + static long ln[] = {0, 1}; + static short sh[] = {0, 1}; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.componentSignature()
    + * complies with its spec when a type is one of ReferenceType(s).
    + *
    + * The test checks up that the component signatures of
    + * ArrayType objects, corresponding in a debugger to
    + * the following in a debuggee:
    + *
    + * a class type array - "ClassForCheck_2 class3[]" field,
    + * an interface type array - "InterfaceForCheck iface[]" field,
    + *
    + * are as follows:
    + * "Lnsk/jdi/ArrayType/componentSignature/ClassForCheck_2;"
    + * "Lnsk/jdi/ArrayType/componentSignature/InterfaceForCheck;"
    + *
    + */ + +public class componentsignature002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/componentSignature/componentsignature002", + sHeader2 = "--> componentsignature002: ", + sHeader3 = "##> componentsignature002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new componentsignature002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.componentSignature.componentsignature002a"; + + String mName = "nsk.jdi.ArrayType.componentSignature"; + String signaturePrefix = "nsk/jdi/ArrayType/componentSignature"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("componentsignature002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = null; + ReferenceType reftypeObj = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0 : // ClassType array + + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + log3("ERROR: for ClassType listOfDebuggeeClasses.size() != 1"); + expresult = 1; + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field classField = reftypeObj.fieldByName("class3"); + + Type classfieldType = null; + try { + classfieldType = classField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: classfieldType = classField.type();"); + expresult =1; + break ; + } + + String classtypeComponentSignature = + ((ArrayType) classfieldType).componentSignature(); + if (!classtypeComponentSignature.equals( + "L" + signaturePrefix + "/ClassForCheck_2;")) { + log3("ERROR: !classtypeComponentSignature.equals(namePrefix + " + + "'.ClassForCheck_2')" + " " + classtypeComponentSignature ); + expresult = 1; + break; + } + break; + + case 1 : // InterfaceType array + + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + log3("ERROR: for InterfaceType listOfDebuggeeClasses.size() != 1"); + expresult = 1; + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field ifaceField = reftypeObj.fieldByName("iface"); + + Type ifacefieldType = null; + try { + ifacefieldType = ifaceField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: ifacefieldType = ifaceField.type();"); + expresult =1; + break ; + } + + String interfacetypeComponentSignature = + ((ArrayType) ifacefieldType).componentSignature(); + if (!interfacetypeComponentSignature.equals( + "L" + signaturePrefix + "/InterfaceForCheck;")) { + log3("ERROR: !interfacetypeComponentSignature.equals(namePrefix + " + + "/InterfaceForCheck')" + " " + interfacetypeComponentSignature ); + expresult = 1; + break; + } + break; +/* + case 2 : // PrimitiveType array !!!!! throws ClassNotLoadedException + + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ArrayType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field arrayField = reftypeObj.fieldByName("bl"); + + Type arrayfieldType = null; + try { + arrayfieldType = arrayField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: arrayfieldType = arrayField.type();"); + expresult =1; + break ; + } + + String arrayTypecomponentSignature = + ((ArrayType) arrayfieldType).componentSignature(); + if (!arrayTypecomponentSignature.equals( + "L" + signaturePrefix + "/ClassForCheck_2;")) { + log3("ERROR: !arrayfieldTypeSignature.equals(namePrefix +" + + "'.ClassForCheck_2[]')" + " " + arrayTypecomponentSignature ); + expresult = 1; + break; + } + break; +*/ + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002/TestDescription.java new file mode 100644 index 00000000000..0efa294bda1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/componentSignature/componentsignature002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.componentSignature() + * complies with its spec: + * public java.lang.String componentSignature() + * Gets the JNI signature of the components of this array class. + * The signature describes the declared type of the components. + * If the components are objects, their actual type in + * a particular run-time context may be a subclass of the declared class. + * Returns: a string containing the JNI signature of array components. + * Throws: ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * when the type is one of the ReferenceType(s). + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.componentSignature.componentsignature002; + * the debuggee program - nsk.jdi.ArrayType.componentSignature.componentsignature002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.componentSignature.componentsignature002 + * nsk.jdi.ArrayType.componentSignature.componentsignature002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.componentSignature.componentsignature002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002a.java new file mode 100644 index 00000000000..45a71a1e1fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentSignature/componentsignature002a.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.componentSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the componentsignature002 JDI test. + */ + +public class componentsignature002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> componentsignature002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> componentsignature002a: " + message); + } + + //====================================================== test program + + static ClassForCheck class1 = new ClassForCheck(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.componentType()
    + * complies with its spec when a type is one of ReferenceType(s).
    + *
    + * The test checks up that the component types of
    + * ReferenceType objects, corresponding in a debugger to
    + * the following in a debuggee:
    + *
    + * a class type array - "ClassForCheck_2 class3[]" field,
    + * an interface type array - "InterfaceForCheck iface[]" field,
    + *
    + * are ClassType and InterfaceType accordinly.
    + *
    + */ + +public class componenttype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/componentType/componenttype001", + sHeader2 = "--> componenttype001: ", + sHeader3 = "##> componenttype001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new componenttype001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.componentType.componenttype001a"; + + String mName = "nsk.jdi.ArrayType.componentType"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("componenttype001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = null; + ReferenceType reftypeObj = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0 : // ClassType array + + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ClassType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field classField = reftypeObj.fieldByName("class3"); + + try { + ClassType obj = + (ClassType) ( (ArrayType) classField.type() ).componentType(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: (ClassType) ((ArrayType) classFieldType.type).componentType();"); + expresult =1; + break ; + } catch ( ClassCastException e ) { + log3("ERROR: (ClassType) ((ArrayType) classFieldType.type).componentType();"); + expresult =1; + break ; + } + + break; + + + case 1 : // InterfaceType array + + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for InterfaceType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field ifaceField = reftypeObj.fieldByName("iface"); + + try { + InterfaceType obj = + (InterfaceType) ( (ArrayType) ifaceField.type() ).componentType(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: (InterfaceType) ( (ArrayType) ifaceField.type() ).componentType();"); + expresult =1; + break ; + } catch ( ClassCastException e ) { + log3("ERROR: (InterfaceType) ( (ArrayType) ifaceField.type() ).componentType();"); + expresult =1; + break ; + } + + break; + +/* + + case 2 : // PrimitiveType array !!!!! throws ClassNotLoadedException + + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ArrayType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field arrayField = reftypeObj.fieldByName("bl"); + + try { + ArrayType obj = + (ArrayType) ( (ArrayType) arrayField.type() ).componentType(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: CNLE (ArrayType) ( (ArrayType) arrayField.type() ).componentType();"); + expresult =1; + break ; + } catch ( ClassCastException e ) { + log3("ERROR: CCE (ArrayType) ( (ArrayType) arrayField.type() ).componentType();"); + expresult =1; + break ; + } + + break; +*/ + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001/TestDescription.java new file mode 100644 index 00000000000..3901203b96b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/componentType/componenttype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.componentType() + * complies with its spec: + * public Type componentType() + * throws ClassNotLoadedException + * Returns the type of the array components. + * For primitive arrays, an appropriate PrimitiveType is always returned. + * For object arrays, the appropriate ReferenceType is returned if + * it has been loaded through the enclosing type's class loader. + * Returns: the Type of the array's components. + * Throws: ClassNotLoadedException - + * if the type has not yet been loaded through + * the appropriate class loader. + * ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * when the type is one of the ReferenceType(s). + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.componentType.componenttype001; + * the debuggee program - nsk.jdi.ArrayType.componentType.componenttype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.componentType.componenttype001 + * nsk.jdi.ArrayType.componentType.componenttype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.componentType.componenttype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001a.java new file mode 100644 index 00000000000..08674770539 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentType/componenttype001a.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.componentType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the componenttype001 JDI test. + */ + +public class componenttype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> componenttype001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> componenttype001a: " + message); + } + + //====================================================== test program + + static ClassForCheck class1 = new ClassForCheck(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.componentTypeName()
    + * complies with its spec when a type is one of primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee executes the following :
    + * static boolean bl[] = {true, false};
    + * static byte bt[] = {0, 1};
    + * static char ch[] = {0, 1};
    + * static double db[] = {0.0d, 1.0d};
    + * static float fl[] = {0.0f, 1.0f};
    + * static int in[] = {0, 1};
    + * static long ln[] = {0, 1};
    + * static short sh[] = {0, 1};
    + *
    + * for all of the above primitive type variables,
    + * a debugger forms their corresponding Type objects
    + * from which it forms text representations of
    + * type names in String variables
    + * named blName, btName, and etc.
    + *
    + * Then the debugger checks up that
    + * each of the following is true :
    + *
    + * blName.equals("boolean")
    + * btName.equals("byte")
    + * chName.equals("char")
    + * dbName.equals("double")
    + * flName.equals("float")
    + * inName.equals("int")
    + * lnName.equals("long")
    + * shName.equals("short")
    + */ + +public class componenttypename001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/componentTypeName/componenttypename001", + sHeader2 = "--> componenttypename001: ", + sHeader3 = "##> componenttypename001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new componenttypename001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.componentTypeName.componenttypename001a"; + + //String mName = "nsk.jdi.ArrayType.componentTypeName"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("componenttypename001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl = execClass.fieldByName("bl"); + Field fsbt = execClass.fieldByName("bt"); + Field fsch = execClass.fieldByName("ch"); + Field fsdb = execClass.fieldByName("db"); + Field fsfl = execClass.fieldByName("fl"); + Field fsin = execClass.fieldByName("in"); + Field fsln = execClass.fieldByName("ln"); + Field fssh = execClass.fieldByName("sh"); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean[] + String blName = + ((ArrayType) execClass.getValue(fsbl).type()).componentTypeName(); + if (!blName.equals("boolean")) { + expresult = 1; + log3("ERROR: !blName.equals('boolean') " + blName); + } + break; + + case 1: // byte[] + String btName = + ((ArrayType) execClass.getValue(fsbt).type()).componentTypeName(); + if (!btName.equals("byte")) { + expresult = 1; + log3("ERROR: !btName.equals('byte')"); + } + break; + + case 2: // char[] + String chName = + ((ArrayType) execClass.getValue(fsch).type()).componentTypeName(); + if (!chName.equals("char")) { + expresult = 1; + log3("ERROR: !chName.equals('char')"); + } + break; + + case 3: // double[] + String dbName = + ((ArrayType) execClass.getValue(fsdb).type()).componentTypeName(); + if (!dbName.equals("double")) { + expresult = 1; + log3("ERROR: !dbName.equals('double')"); + } + break; + + case 4: // float[] + String flName = + ((ArrayType) execClass.getValue(fsfl).type()).componentTypeName(); + if (!flName.equals("float")) { + expresult = 1; + log3("ERROR: !flName.equals('float')"); + } + break; + + case 5: // int[] + String inName = + ((ArrayType) execClass.getValue(fsin).type()).componentTypeName(); + if (!inName.equals("int")) { + expresult = 1; + log3("ERROR: !inName.equals('int')"); + } + break; + + case 6: // long[] + String lnName = + ((ArrayType) execClass.getValue(fsln).type()).componentTypeName(); + if (!lnName.equals("long")) { + expresult = 1; + log3("ERROR: !lnName.equals('long')"); + } + break; + + case 7: // short[] + String shName = + ((ArrayType) execClass.getValue(fssh).type()).componentTypeName(); + if (!shName.equals("short")) { + expresult = 1; + log3("ERROR: !shName.equals('short')"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001/TestDescription.java new file mode 100644 index 00000000000..b5a06bf3e55 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/componentTypeName/componenttypename001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.componentTypeName() + * complies with its spec: + * public java.lang.String componentTypeName() + * Returns: a text representation of the component type. + * Throws: ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.componentTypeName001; + * the debuggee program - nsk.jdi.ArrayType.componentTypeName001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.componentTypeName.componenttypename001 + * nsk.jdi.ArrayType.componentTypeName.componenttypename001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.componentTypeName.componenttypename001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001a.java new file mode 100644 index 00000000000..959026a271a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename001a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.componentTypeName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the componenttypename001 JDI test. + */ + +public class componenttypename001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> componenttypename001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> componenttypename001a: " + message); + } + + //====================================================== test program + + static boolean bl[] = {true, false}; + static byte bt[] = {0, 1}; + static char ch[] = {0, 1}; + static double db[] = {0.0d, 1.0d}; + static float fl[] = {0.0f, 1.0f}; + static int in[] = {0, 1}; + static long ln[] = {0, 1}; + static short sh[] = {0, 1}; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.componentTypeName()
    + * complies with its spec when a type is one of ReferenceType(s).
    + *
    + * The test checks up that the component type names of
    + * ArrayType objects, corresponding in a debugger to
    + * the following in a debuggee:
    + *
    + * a class type array - "ClassForCheck_2 class3[]" field,
    + * an interface type array - "InterfaceForCheck iface[]" field,
    + *
    + * are "nsk.jdi.ArrayType.componentTypeName.ClassForCheck_2" and
    + * "nsk.jdi.ArrayType.componentTypeName.InterfaceForCheck"
    + *
    + */ + +public class componenttypename002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/componentTypeName/componenttypename002", + sHeader2 = "--> componenttypename002: ", + sHeader3 = "##> componenttypename002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new componenttypename002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.componentTypeName.componenttypename002a"; + + String mName = "nsk.jdi.ArrayType.componentTypeName"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("componenttypename002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = null; + ReferenceType reftypeObj = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0 : // ClassType array + + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ClassType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field classField = reftypeObj.fieldByName("class3"); + + Type classfieldType = null; + try { + classfieldType = classField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: classfieldType = classField.type();"); + expresult =1; + break ; + } + + String classtypeComponentTypeName = + ((ArrayType) classfieldType).componentTypeName(); + if (!classtypeComponentTypeName.equals(mName + ".ClassForCheck_2")) { + expresult = 1; + log3("ERROR: !classtypeComponentSignature.equals(namePrefix + " + + "'.ClassForCheck_2')" + " " + classtypeComponentTypeName ); + } + break; + + case 1 : // InterfaceType array + + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for InterfaceType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field ifaceField = reftypeObj.fieldByName("iface"); + + Type ifacefieldType = null; + try { + ifacefieldType = ifaceField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: ifacefieldType = ifaceField.type();"); + expresult =1; + break ; + } + + String interfacetypeComponentTypeName = + ((ArrayType) ifacefieldType).componentTypeName(); + if (!interfacetypeComponentTypeName.equals(mName + ".InterfaceForCheck")) { + expresult = 1; + log3("ERROR: !interfacetypeComponentSignature.equals(namePrefix + " + + "/InterfaceForCheck')" + " " + interfacetypeComponentTypeName ); + } + break; + +/* + case 2 : // PrimitiveType array !!!!! throws ClassNotLoadedException + listOfDebuggeeClasses = + vm.classesByName(mName + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ArrayType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field arrayField = reftypeObj.fieldByName("bl"); + + Type arrayfieldType = null; + try { + arrayfieldType = arrayField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: arrayfieldType = arrayField.type();"); + expresult =1; + break ; + } + + String arrayTypecomponentTypeName = + ((ArrayType) arrayfieldType).componentTypeName(); + if (!arrayTypecomponentTypeName.equals(mName + "boolean[]")) { + expresult = 1; + log3("ERROR: !arrayfieldTypeSignature.equals(namePrefix +" + + "'.ClassForCheck_2[]')" + " " + arrayTypecomponentTypeName ); + } + break; +*/ + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002/TestDescription.java new file mode 100644 index 00000000000..55df3bfb1b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/componentTypeName/componenttypename002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.componentTypeName() + * complies with its spec: + * public java.lang.String componentTypeName() + * Returns: a text representation of the component type. + * Throws: ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * when the type is one of the ReferenceType(s). + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.componentTypeName.componenttypename002; + * the debuggee program - nsk.jdi.ArrayType.componentTypeName.componenttypename002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.componentTypeName.componenttypename002 + * nsk.jdi.ArrayType.componentTypeName.componenttypename002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.componentTypeName.componenttypename002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002a.java new file mode 100644 index 00000000000..62e3c830c41 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/componentTypeName/componenttypename002a.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.componentTypeName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the componenttypename002 JDI test. + */ + +public class componenttypename002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> componenttypename002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> componenttypename002a: " + message); + } + + //====================================================== test program + + static ClassForCheck class1 = new ClassForCheck(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.newInstance()
    + * complies with its spec when a type is one of primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee executes the following :
    + * static boolean bl[] = {true};
    + * static byte bt[] = {1};
    + * static char ch[] = {1};
    + * static double db[] = {1.0d};
    + * static float fl[] = {1.0f};
    + * static int in[] = {1};
    + * static long ln[] = {1};
    + * static short sh[] = {1};
    + *
    + * for all of the above primitive type variables,
    + * a debugger creates new instances of
    + * corresponding ReferenceArray objects and checks up
    + * that (1) length of newly created arrays is equal to
    + * a method invocation parameter and (2) initial values
    + * of arrays components are as they are defined in
    + * JLS, section 4.5.5.
    + */ + +public class newinstance001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/newInstance/newinstance001", + sHeader2 = "--> newinstance001: ", + sHeader3 = "##> newinstance001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new newinstance001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.newInstance.newinstance001a"; + + //String mName = "nsk.jdi.ArrayType.newInstance"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("newinstance001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl = execClass.fieldByName("bl"); + Field fsbt = execClass.fieldByName("bt"); + Field fsch = execClass.fieldByName("ch"); + Field fsdb = execClass.fieldByName("db"); + Field fsfl = execClass.fieldByName("fl"); + Field fsin = execClass.fieldByName("in"); + Field fsln = execClass.fieldByName("ln"); + Field fssh = execClass.fieldByName("sh"); + + final int arraylength = 2; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean[] + ArrayType blArray = + (ArrayType) execClass.getValue(fsbl).type(); + ArrayReference newBlArray = blArray.newInstance(arraylength); + + if (newBlArray.length() != arraylength) { + log3("ERROR : newBlArray.length() != arraylength " + newBlArray.length()); + expresult = 1; + break; + } + if ( ((BooleanValue) newBlArray.getValue(0)).value() != false || + ((BooleanValue) newBlArray.getValue(1)).value() != false ) { + log3("ERROR : newBlArray components != false"); + expresult = 1; + break; + } + + break; + + case 1: // byte[] + ArrayType btArray = + (ArrayType) execClass.getValue(fsbt).type(); + ArrayReference newBtArray = btArray.newInstance(arraylength); + + if (newBtArray.length() != arraylength) { + log3("ERROR : newBtArray.length() != arraylength " + newBtArray.length()); + expresult = 1; + break; + } + if ( ((ByteValue) newBtArray.getValue(0)).value() != (byte) 0 || + ((ByteValue) newBtArray.getValue(1)).value() != (byte) 0 ) { + log3("ERROR : newBtArray components != (byte) 0"); + expresult = 1; + break; + } + break; + + case 2: // char[] + ArrayType chArray = + (ArrayType) execClass.getValue(fsch).type(); + ArrayReference newChArray = chArray.newInstance(arraylength); + + if (newChArray.length() != arraylength) { + log3("ERROR : newChArray.length() != arraylength " + newChArray.length()); + expresult = 1; + break; + } + if ( ((CharValue) newChArray.getValue(0)).value() != '\u0000' || + ((CharValue) newChArray.getValue(1)).value() != '\u0000' ) { + log3("ERROR : newChArray components != '\u0000' "); + expresult = 1; + break; + } + break; + + case 3: // double[] + ArrayType dbArray = + (ArrayType) execClass.getValue(fsdb).type(); + ArrayReference newDbArray = dbArray.newInstance(arraylength); + + if (newDbArray.length() != arraylength) { + log3("ERROR : newDBArray.length() != arraylength " + newDbArray.length()); + expresult = 1; + break; + } + if ( ((DoubleValue) newDbArray.getValue(0)).value() != 0.0d || + ((DoubleValue) newDbArray.getValue(1)).value() != 0.0d ) { + log3("ERROR : newDbArray components != 0.0d"); + expresult = 1; + break; + } + break; + + case 4: // float[] + ArrayType flArray = + (ArrayType) execClass.getValue(fsfl).type(); + ArrayReference newFlArray = flArray.newInstance(arraylength); + + if (newFlArray.length() != arraylength) { + log3("ERROR : newFlArray.length() != arraylength " + newFlArray.length()); + expresult = 1; + break; + } + if ( ((FloatValue) newFlArray.getValue(0)).value() != 0.0f || + ((FloatValue) newFlArray.getValue(1)).value() != 0.0f ) { + log3("ERROR : newFlArray components != 0.0f"); + expresult = 1; + break; + } + break; + + case 5: // int[] + ArrayType inArray = + (ArrayType) execClass.getValue(fsin).type(); + ArrayReference newInArray = inArray.newInstance(arraylength); + + if (newInArray.length() != arraylength) { + log3("ERROR : newInArray.length() != arraylength " + newInArray.length()); + expresult = 1; + break; + } + if ( ((IntegerValue) newInArray.getValue(0)).value() != 0 || + ((IntegerValue) newInArray.getValue(1)).value() != 0 ) { + log3("ERROR : newInArray components != 0"); + expresult = 1; + break; + } + break; + + case 6: // long[] + ArrayType lnArray = + (ArrayType) execClass.getValue(fsln).type(); + ArrayReference newLnArray = lnArray.newInstance(arraylength); + + if (newLnArray.length() != arraylength) { + log3("ERROR : newLnArray.length() != arraylength " + newLnArray.length()); + expresult = 1; + break; + } + if ( ((LongValue) newLnArray.getValue(0)).value() != 0L || + ((LongValue) newLnArray.getValue(1)).value() != 0L) { + log3("ERROR : newLnArray components != 0L"); + expresult = 1; + break; + } + break; + + case 7: // short[] + ArrayType shArray = + (ArrayType) execClass.getValue(fssh).type(); + ArrayReference newShArray = shArray.newInstance(arraylength); + + if (newShArray.length() != arraylength) { + log3("ERROR : newShArray.length() != arraylength " + newShArray.length()); + expresult = 1; + break; + } + if ( ((ShortValue) newShArray.getValue(0)).value() != (short) 0 || + ((ShortValue) newShArray.getValue(1)).value() != (short) 0 ) { + log3("ERROR : newShArray components != (short) 0"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001/TestDescription.java new file mode 100644 index 00000000000..b4e8722862b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/newInstance/newinstance001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.newInstance() + * complies with its spec: + * public ArrayReference newInstance(int length) + * Creates a new instance of this array class in the target VM. + * The array is created with the given length and + * each component is initialized to is standard default value. + * Parameters: length - the number of components in the new array + * Returns: the newly created ArrayReference mirroring + * the new object in the target VM. + * Throws: ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * when a type of this array class is one of primitive types. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.newInstance.newinstance001; + * the debuggee program - nsk.jdi.ArrayType.newInstance.newinstance001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.newInstance.newinstance001 + * nsk.jdi.ArrayType.newInstance.newinstance001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.newInstance.newinstance001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001a.java new file mode 100644 index 00000000000..6cfb9979b43 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the newinstance001 JDI test. + */ + +public class newinstance001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> newinstance001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> newinstance001a: " + message); + } + + //====================================================== test program + + static boolean bl[] = {true}; + static byte bt[] = { 1}; + static char ch[] = { 1}; + static double db[] = { 1.0d}; + static float fl[] = { 1.0f}; + static int in[] = { 1}; + static long ln[] = { 1}; + static short sh[] = { 1}; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.newInstance()
    + * complies with its spec when componentType of an ArrayType
    + * object used as original for newInstance() is also ArrayType
    + * whose components are primitive type values.
    + * The test works as follows.
    + *
    + * For given debuggee's array whose components are
    + * a primitive (boolean in this particular case) arrays,
    + * a debugger forms corresponding ArrayType object
    + * to which it applies newInstance() method in order to get
    + * an ArrayReference object, newarray.
    + * Then the debugger checks up that:
    + * - newInstance() method's returned value != null;
    + * - length of newly created array is equal to 'arg' in
    + * newInstance(int arg) method invocation;
    + * - newarray.type().name().equals(array.componentType().name());
    + * - all components of new array are nulls
    + * as its default values at the moment of the array creation.
    + *
    + */ + +public class newinstance002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/newInstance/newinstance002", + sHeader2 = "--> newinstance002: ", + sHeader3 = "##> newinstance002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new newinstance002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.newInstance.newinstance002a"; + + String mName = "nsk.jdi.ArrayType.newInstance"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("newinstance002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOftestedClasses = vm.classesByName(mName + ".newinstance002aTestClass"); + if (listOftestedClasses.size() != 1) { + log3("ERROR: listOftestedClasses.size() != 1"); + testExitCode = FAILED; + continue; + } + ReferenceType testedClass = + (ReferenceType) listOftestedClasses.get(0); + + Field fieldArray = testedClass.fieldByName("a2"); + if (fieldArray == null) { + log3("ERROR: fieldArray == null"); + testExitCode = FAILED; + continue; + } + + final int arraylength = 2; + + log2("1111111111"); + + ArrayType arrayArray = + (ArrayType) testedClass.getValue(fieldArray).type(); + + log2("2222222222"); + + ArrayReference newarrayArray = arrayArray.newInstance(arraylength); + if (newarrayArray == null) { + log3("ERROR: newarrayArray == null"); + testExitCode = FAILED; + continue; + } + log2("3333333333"); + + try { + if ( newarrayArray.type().name().equals(arrayArray.componentType().name()) ) { + log3("ERROR : types are not equal :\n" + + "newarrayArray.type().name() =" + newarrayArray.type().name() + "\n" + + "arrayArray.componentType().name()=" + arrayArray.componentType().name() ); + testExitCode = FAILED; + continue; + } + } catch ( ClassNotLoadedException e ) { + log3("ERROR: ClassNotLoadedException for newarrayArray.type().name().equals(.."); + testExitCode = FAILED; + continue; + } + log2("4444444444"); + + if (newarrayArray.length() != arraylength) { + log3("ERROR : newarrayArray.length() != arraylength " + newarrayArray.length()); + testExitCode = FAILED; + continue; + } + log2("5555555555"); + + if (newarrayArray.getValue(0) != null || + newarrayArray.getValue(1) != null) { + log3("ERROR: newarrayArray.getValue() != null "); + testExitCode = FAILED; + continue; + } + + log2("6666666666"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002/TestDescription.java new file mode 100644 index 00000000000..edf2d9d650c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/newInstance/newinstance002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.newInstance() + * complies with its spec: + * public ArrayReference newInstance(int length) + * Creates a new instance of this array class in the target VM. + * The array is created with the given length and + * each component is initialized to is standard default value. + * Parameters: length - the number of components in the new array + * Returns: the newly created ArrayReference mirroring + * the new object in the target VM. + * Throws: ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * when components of this array class are arrays of primitive type values. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.newInstance.newinstance002; + * the debuggee program - nsk.jdi.ArrayType.newInstance.newinstance002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.newInstance.newinstance002 + * nsk.jdi.ArrayType.newInstance.newinstance002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.newInstance.newinstance002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002a.java new file mode 100644 index 00000000000..a1a68c91102 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002a.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the newinstance002 JDI test. + */ + +public class newinstance002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> newinstance002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> newinstance002a: " + message); + } + + //====================================================== test program + + static newinstance002aTestClass obj = new newinstance002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.newInstance()
    + * complies with its spec when componentType of an ArrayType
    + * object used as original for newInstance() is InterfeaceType.
    + * The test works as follows.
    + *
    + * For given debuggee's array whose components
    + * are objects of a class type implementing the interface,
    + * a debugger forms corresponding ArrayType object
    + * to which it applies newInstance() method in order to get
    + * an ArrayReference object, newarray.
    + * Then the debugger checks up that:
    + * - newInstance() method's returned value != null;
    + * - length of newly created array is equal to 'arg' in
    + * newInstance(int arg) method invocation;
    + * - newarray.type().name().equals(array.componentType().name());
    + * - all components of new array are nulls
    + * as its default values at the moment of the array creation.
    + *
    + */ + +public class newinstance003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/newInstance/newinstance003 ", + sHeader2 = "--> newinstance003: ", + sHeader3 = "##> newinstance003: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new newinstance003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.newInstance.newinstance003a"; + + String mName = "nsk.jdi.ArrayType.newInstance"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("newinstance003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOftestedClasses = vm.classesByName(mName + ".newinstance003aTestClass"); + if (listOftestedClasses.size() != 1) { + log3("ERROR: listOftestedClasses.size() != 1"); + testExitCode = FAILED; + continue; + } + ReferenceType testedClass = + (ReferenceType) listOftestedClasses.get(0); + + Field fieldArray = testedClass.fieldByName("iface"); + if (fieldArray == null) { + log3("ERROR: fieldArray == null"); + testExitCode = FAILED; + continue; + } + + final int arraylength = 2; + + ArrayType ifaceArray = + (ArrayType) testedClass.getValue(fieldArray).type(); + + ArrayReference newifaceArray = null; + try { + newifaceArray = ifaceArray.newInstance(arraylength); + } catch ( Throwable e ) { + log3 ("ERROR: Exception: " + e); + testExitCode = FAILED; + continue; + } + if (newifaceArray == null) { + log3("ERROR: newifaceArray == null"); + testExitCode = FAILED; + continue; + } + + try { + if ( newifaceArray.type().name().equals(ifaceArray.componentType().name()) ) { + log3("ERROR : types are not equal :\n" + + "newifaceArray.type().name() =" + newifaceArray.type().name() + "\n" + + "ifaceArray.componentType().name()=" + ifaceArray.componentType().name() ); + testExitCode = FAILED; + continue; + } + } catch ( ClassNotLoadedException e ) { + log3("ERROR: ClassNotLoadedException for newifaceArray.type().name().equals(.."); + testExitCode = FAILED; + continue; + } + + if (newifaceArray.length() != arraylength) { + log3("ERROR : newifaceArray.length() != arraylength " + newifaceArray.length()); + testExitCode = FAILED; + continue; + } + + if (newifaceArray.getValue(0) != null || + newifaceArray.getValue(1) != null) { + log3("ERROR: newifaceArray.getValue() != null "); + testExitCode = FAILED; + continue; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003/TestDescription.java new file mode 100644 index 00000000000..cd9844c15cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/newInstance/newinstance003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.newInstance() + * complies with its spec: + * public ArrayReference newInstance(int length) + * Creates a new instance of this array class in the target VM. + * The array is created with the given length and + * each component is initialized to is standard default value. + * Parameters: length - the number of components in the new array + * Returns: the newly created ArrayReference mirroring + * the new object in the target VM. + * Throws: ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * when components of this array class are interface type values. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.newInstance.newinstance003; + * the debuggee program - nsk.jdi.ArrayType.newInstance.newinstance003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.newInstance.newinstance003 + * nsk.jdi.ArrayType.newInstance.newinstance003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.newInstance.newinstance003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003a.java new file mode 100644 index 00000000000..0e4e16d9f8f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance003a.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the newinstance003 JDI test. + */ + +public class newinstance003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> newinstance003a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> newinstance003a: " + message); + } + + //====================================================== test program + + static newinstance003aTestClass obj = new newinstance003aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ArrayType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ArrayType.newInstance()
    + * complies with its spec when componentType of an ArrayType
    + * object used as original for newInstance() is ClassType.
    + * The test works as follows.
    + *
    + * For given debuggee's array whose components
    + * are objects of a class type,
    + * a debugger forms corresponding ArrayType object
    + * to which it applies newInstance() method in order to get
    + * an ArrayReference object, newarray.
    + * Then the debugger checks up that:
    + * - newInstance() method's returned value != null;
    + * - length of newly created array is equal to 'arg' in
    + * newInstance(int arg) method invocation;
    + * - newarray.type().name().equals(array.componentType().name());
    + * - all components of new array are nulls
    + * as its default values at the moment of the array creation.
    + *
    + */ + +public class newinstance004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ArrayType/newInstance/newinstance004 ", + sHeader2 = "--> newinstance004: ", + sHeader3 = "##> newinstance004: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new newinstance004().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ArrayType.newInstance.newinstance004a"; + + String mName = "nsk.jdi.ArrayType.newInstance"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("newinstance004a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOftestedClasses = vm.classesByName(mName + ".newinstance004aTestClass"); + if (listOftestedClasses.size() != 1) { + log3("ERROR: listOftestedClasses.size() != 1"); + testExitCode = FAILED; + continue; + } + ReferenceType testedClass = + (ReferenceType) listOftestedClasses.get(0); + + Field fieldArray = testedClass.fieldByName("cfc"); + if (fieldArray == null) { + log3("ERROR: fieldArray == null"); + testExitCode = FAILED; + continue; + } + + final int arraylength = 2; + + ArrayType classArray = + (ArrayType) testedClass.getValue(fieldArray).type(); + + + ArrayReference newclassArray = null; + try { + newclassArray = classArray.newInstance(arraylength); + } catch ( Throwable e ) { + log3 ("ERROR: Exception: " + e); + testExitCode = FAILED; + continue; + } + if (newclassArray == null) { + log3("ERROR: newclassArray == null"); + testExitCode = FAILED; + continue; + } + + try { + if ( newclassArray.type().name().equals(classArray.componentType().name()) ) { + log3("ERROR : types are not equal :\n" + + "newclassArray.type().name() =" + newclassArray.type().name() + "\n" + + "classArray.componentType().name()=" + classArray.componentType().name() ); + testExitCode = FAILED; + continue; + } + } catch ( ClassNotLoadedException e ) { + log3("ERROR: ClassNotLoadedException for newclassArray.type().name().equals(.."); + testExitCode = FAILED; + continue; + } + + if (newclassArray.length() != arraylength) { + log3("ERROR : newclassArray.length() != arraylength " + newclassArray.length()); + testExitCode = FAILED; + continue; + } + + if (newclassArray.getValue(0) != null || + newclassArray.getValue(1) != null) { + log3("ERROR: newclassArray.getValue() != null "); + testExitCode = FAILED; + continue; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004/TestDescription.java new file mode 100644 index 00000000000..ef350a7189e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ArrayType/newInstance/newinstance004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ArrayType. + * The test checks up that a result of the method + * com.sun.jdi.ArrayType.newInstance() + * complies with its spec: + * public ArrayReference newInstance(int length) + * Creates a new instance of this array class in the target VM. + * The array is created with the given length and + * each component is initialized to is standard default value. + * Parameters: length - the number of components in the new array + * Returns: the newly created ArrayReference mirroring + * the new object in the target VM. + * Throws: ObjectCollectedException - + * if this array type has been unloaded and garbage collected. + * when components of this array class are class type values. + * The test works as follows: + * The debugger program - nsk.jdi.ArrayType.newInstance.newinstance004; + * the debuggee program - nsk.jdi.ArrayType.newInstance.newinstance004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ArrayType.newInstance.newinstance004 + * nsk.jdi.ArrayType.newInstance.newinstance004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ArrayType.newInstance.newinstance004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004a.java new file mode 100644 index 00000000000..0902f867053 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance004a.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ArrayType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the newinstance004 JDI test. + */ + +public class newinstance004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> newinstance004a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> newinstance004a: " + message); + } + + //====================================================== test program + + static newinstance004aTestClass obj = new newinstance004aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.SocketAttach connector. + */ +public class attach001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String DEBUGEE_CLASS = + "nsk.jdi.AttachingConnector.attach.attach001t"; + + private Log log; + + private VirtualMachine vm; + + private int attempts; // attempts to connect to the debugee VM + private int delay = 4000; // delay between connection attempts + + IORedirector outRedirector; + IORedirector errRedirector; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new attach001().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + String port; + String listenPort; + Process proc; + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if "com.sun.jdi.SocketAttach" is not implemented +// on this platform + if (argHandler.shouldPass("com.sun.jdi.SocketAttach")) + return PASSED; + + log = new Log(out, argHandler); + + String args[] = argHandler.getArguments(); + + // treat second positional argument as delay between connection attempts + try { + delay = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + log.complain("Incorrect test parameter: timeout value must be an integer"); + return FAILED; + } catch (ArrayIndexOutOfBoundsException e) { + // ignore: default delay will be used if no second argument present + } + // calculate number of connection attempts to not exceed WAITTIME + long timeout = argHandler.getWaitTime() * 60 * 1000; + attempts = (int)(timeout / delay); + + port = argHandler.getTransportPort(); + listenPort = argHandler.getTransportPort(); + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + String cmd = java + + " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=" + + listenPort + " " + DEBUGEE_CLASS; + + Binder binder = new Binder(argHandler, log); + log.display("command: " + cmd); + Debugee debugee = binder.startLocalDebugee(cmd); + debugee.redirectOutput(log); + + if ((vm = attachTarget(argHandler.getTestHost(), port)) == null) { + log.complain("TEST: Unable to attach the debugee VM"); + debugee.close(); + return FAILED; + } + + log.display("debugee VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + debugee.setupVM(vm); + debugee.waitForVMInit(timeout); + + log.display("\nresuming debugee VM"); + debugee.resume(); + + log.display("\nwaiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("Debugee VM has crashed: exit code=" + + code); + return FAILED; + } + log.display("debugee VM: exit code=" + code); + return PASSED; + } + + private VirtualMachine attachTarget(String host, String port) { + Connector.Argument arg; + + if (port == null) { + log.complain("TEST: port number is required!"); + return null; + } + + AttachingConnector connector = + (AttachingConnector) findConnector("com.sun.jdi.SocketAttach"); + + Map cArgs = connector.defaultArguments(); + Iterator cArgsValIter = cArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) cArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + connector.name()); + } + if (arg.name().equals("hostname") && host != null) + arg.setValue(host); + if (arg.name().equals("port")) + arg.setValue(port); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue="+argVal); + else log.display("\t\tvalue=NULL"); + } + + // make several attemts to connect to the debugee VM until WAITTIME exceeds + for (int i = 0; i < attempts; i++) { + try { + return connector.attach(cArgs); + } catch (IOException e) { + // could not connect; sleep a few and make new attempt + log.display("Connection attempt #" + i + " failed: " + e); + try { + Thread.currentThread().sleep(delay); + } catch (InterruptedException ie) { + log.complain("TEST INCOMPLETE: interrupted sleep: " + ie); + } + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return null; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return null; + } + } + // return null after all attempts failed + log.complain("FAILURE: all attempts to connect to the debugee VM failed"); + return null; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001/TestDescription.java new file mode 100644 index 00000000000..3c8f78ecdd3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/AttachingConnector/attach/attach001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that debugger may establish connection with + * a target VM via com.sun.jdi.SocketAttach connector. + * COMMENT + * Test fixed due to bug: + * 4463674 TEST_BUG: some JDI tests are timing dependent + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * Test was fixed to provide early redirecting of debugee output. + * See bug: + * 4905551 shmemBase_listen failed: Cannot create a file when that file already exists + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.AttachingConnector.attach.attach001 + * nsk.jdi.AttachingConnector.attach.attach001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.AttachingConnector.attach.attach001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001t.java new file mode 100644 index 00000000000..2180fd002ef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach001t.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.AttachingConnector.attach; + +import java.io.IOException; + +public class attach001t { + public static void main(String args[]) { + System.exit(attach001.JCK_STATUS_BASE + attach001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java new file mode 100644 index 00000000000..d4092f95bea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.AttachingConnector.attach; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.ReferenceType; + +import java.io.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that debugger may establish connection with + * a target VM via com.sun.jdi.SharedMemoryAttach connector.
    + * The test also analyzes exit code of debugee's process. + */ +public class attach002 extends Log { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String DEBUGEE_CLASS = + "nsk.jdi.AttachingConnector.attach.attach002t"; + + private Log log; + + private VirtualMachine vm; + + private int attempts; // attempts to connect to the debugee VM + private int delay = 4000; // delay between connection attempts + + IORedirector outRedirector; + IORedirector errRedirector; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new attach002().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + String name; + Process proc; + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if "com.sun.jdi.SharedMemoryAttach" is not implemented +// on this platform + if (argHandler.shouldPass("com.sun.jdi.SharedMemoryAttach")) + return PASSED; + + log = new Log(out, argHandler); + + String args[] = argHandler.getArguments(); + + // treat second positional argument as delay between connection attempts + try { + delay = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + log.complain("Incorrect test parameter: timeout value must be an integer"); + return FAILED; + } catch (ArrayIndexOutOfBoundsException e) { + // ignore: default delay will be used if no second argument present + } + + // calculate number of connection attempts to not exceed WAITTIME + long timeout = argHandler.getWaitTime() * 60 * 1000; + attempts = (int)(timeout / delay); + + name = argHandler.getTransportSharedName(); + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + String cmd = java + + " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_shmem,server=y,address=" + + name + " " + DEBUGEE_CLASS; + + Binder binder = new Binder(argHandler, log); + log.display("command: " + cmd); + Debugee debugee = binder.startLocalDebugee(cmd); + debugee.redirectOutput(log); + + if ((vm = attachTarget(name)) == null) { + log.complain("TEST: Unable to attach the debugee VM"); + debugee.close(); + return FAILED; + } + + log.display("target VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + debugee.setupVM(vm); + debugee.waitForVMInit(timeout); + + log.display("\nResuming debugee VM"); + debugee.resume(); + + log.display("\nWaiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("Debugee VM has crashed: exit code=" + code); + return FAILED; + } + log.display("Debugee VM: exit code=" + code); + return PASSED; + } + + private VirtualMachine attachTarget(String name) { + Connector.Argument arg; + + if (name == null) { + log.complain("TEST: shared memory name is required!"); + return null; + } + + AttachingConnector connector = + (AttachingConnector) findConnector("com.sun.jdi.SharedMemoryAttach"); + + Map cArgs = connector.defaultArguments(); + Iterator cArgsValIter = cArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) cArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + connector.name()); + } + if (arg.name().equals("name")) + arg.setValue(name); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue="+argVal); + else log.display("\t\tvalue=NULL"); + } + + // make several attemts to connect to the debugee VM until WAITTIME exceeds + for (int i = 0; i < attempts; i++) { + try { + return connector.attach(cArgs); + } catch (IOException e) { + // could not connect; sleep a few and make new attempt + log.display("Connection attempt #" + i + " failed: " + e); + try { + Thread.currentThread().sleep(delay); + } catch (InterruptedException ie) { + log.complain("TEST INCOMPLETE: interrupted sleep: " + ie); + } + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return null; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return null; + } + } + // return null after all attempts failed + log.complain("FAILURE: all attempts to connect to the debugee VM failed"); + return null; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002/TestDescription.java new file mode 100644 index 00000000000..b945c4a49eb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/AttachingConnector/attach/attach002. + * VM Testbase keywords: [quick, jpda, jdi, quarantine] + * VM Testbase comments: JDK-8054463 + * VM Testbase readme: + * DESCRIPTION + * The test checks that debugger may establish connection with + * a target VM via com.sun.jdi.SharedMemoryAttach connector. + * The test also analyzes exit code of debugee's process. + * COMMENT + * Test fixed due to bug: + * 4463674 TEST_BUG: some JDI tests are timing dependent + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * Test was fixed to provide early redirecting of debugee output. + * See bug: + * 4905551 shmemBase_listen failed: Cannot create a file when that file already exists + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.AttachingConnector.attach.attach002 + * nsk.jdi.AttachingConnector.attach.attach002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.AttachingConnector.attach.attach002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002t.java new file mode 100644 index 00000000000..7837d3d47be --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach002t.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.AttachingConnector.attach; + +import java.io.IOException; + +public class attach002t { + public static void main(String args[]) { + System.exit(attach002.JCK_STATUS_BASE + attach002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach003.java new file mode 100644 index 00000000000..a7b52e9f6b8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach003.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.AttachingConnector.attach; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + + +/** + * The test check up two cases:
    + * 1. Parameter has null value. In this case NullPointerException
    + * is expected.
    + * 2. Parameter has wrong arguments. In this case
    + * IllegalConnectorArgumentsException is expected.
    + * Checking of the each case is executed by performStep method.
    + * Note, this test establishes no connections with debugee, just checks performing of
    + * attach with wrong parameters.
    + */ +public class attach003 { + + private final static String[][] ARGS = { + {"first_key", "first_value"}, + {"second_key","second_value"}, + {"third_key", "third_value"} + }; + + private static Log log; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + return execTest(argv, out); + } + + // this method does bad things + @SuppressWarnings("unchecked") + private static int execTest(String argv[], PrintStream out) { + + int exitCode = Consts.TEST_PASSED; + + log = new Log(out, new ArgumentHandler(argv)); + + List connectors = Bootstrap.virtualMachineManager().attachingConnectors(); + log.display("Getting of " + connectors.size() + " connectors."); + log.display("-----------------------------------------------"); + + Map arguments = null; + log.display("Checking of parameter."); + if (!performStep(connectors, arguments)) + exitCode = Consts.TEST_FAILED; + + log.display("-----------------------------------------------"); + log.display("Checking of parameter with wrong arguments:"); + Attributes amap = new Attributes(); + arguments = (Map)(Map)amap; + + for (int i =0 ; i < ARGS.length; i++) { + log.display(i + ". " + ARGS[i][0] + " , " + ARGS[i][1] ); + amap.putValue(ARGS[i][0], ARGS[i][1]); + } + log.display(""); + if (!performStep(connectors, arguments)) + exitCode = Consts.TEST_FAILED; + + return exitCode; + } + + private static boolean performStep(List connectors, Map arguments) { + boolean res = true; + VirtualMachine vm; + AttachingConnector connector; + for (int i = 0; i < connectors.size(); i++) { + connector = (AttachingConnector )connectors.get(i); + if (connector == null) { + log.complain("Wrong connector " + connector + ": index=" + i + + " size of connectors list=" + + connectors.size()); + res = false; + continue; + } + try { + log.display("Connector " + connector.name() + ":"); + vm = connector.attach(arguments); + if (arguments == null) { + log.complain("\tNullPointerException is not thrown.\n"); + res = false; + } else { + log.complain("\tIllegalConnectorArgumentsException " + + "is not thrown.\n"); + res = false; + } + } catch (NullPointerException e) { + if (arguments != null) { + log.complain("\tunexpected NullPointerException.\n"); + res = false; + continue; + } + log.display("\texpected NullPointerException.\n"); + } catch (IllegalConnectorArgumentsException e) { + if (arguments == null) { + log.complain("\tunexpected IllegalConnectorArgumentsException.\n"); + res = false; + continue; + } + log.display("\texpected IllegalConnectorArgumentsException.\n"); + } catch (Exception e) { + log.complain("\tunexpected " + e ); + res = false; + } + } + return res; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach003/TestDescription.java new file mode 100644 index 00000000000..d41a835ada3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach003/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/AttachingConnector/attach/attach003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.connect.AttachingConnector.attach(Map) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public VirtualMachine attach(Map arguments) + * throws IOException, + * IllegalConnectorArgumentsException + * Attaches to a running application and and returns a mirror of its VM. + * The connector uses the given argument map in attaching the application. + * These arguments will include addressing information that identifies + * the VM. The argument map associates argument name strings to instances + * of Connector.Argument. The default argument map for a connector can be + * obtained through Connector.defaultArguments(). Argument map values can + * be changed, but map entries should not be added or deleted. + * Parameters: + * arguments - the argument map to be used in launching the VM. + * Returns: + * the VirtualMachine mirror of the target VM. + * Throws: + * IOException - when unable to attach. Specific exceptions are + * dependent on the Connector implementation in use. + * IllegalConnectorArgumentsException - when one of the connector + * arguments is invalid. + * The test check up two cases: + * 1. Parameter has value. In this case NullPointerException + * is expected. + * 2. Parameter has wrong arguments. In this case + * IllegalConnectorArgumentsException is expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.AttachingConnector.attach.attach003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.AttachingConnector.attach.attach003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/TestDescription.java new file mode 100644 index 00000000000..11d59a2020b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/TestDescription.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/AttachingConnector/attach/attach004. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that debugger may establish connection with + * a target VM via com.sun.jdi.ProcessAttach connector. + * Target VM is started with option "suspend=y" (VM is to be suspended immediately before the main class is loaded). + * Test uses socket transport for communication between a debugger and the target VM. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.AttachingConnector.attach.attach004.TestDriver + * @run driver PropertyResolvingWrapper + * nsk.jdi.AttachingConnector.attach.attach004.TestDriver + * ${os.family}-${os.simpleArch} dt_socket y + * -waitVMStartEvent + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/TestDriver.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/TestDriver.java new file mode 100644 index 00000000000..7cc94acbf83 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/TestDriver.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2018, 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 nsk.jdi.AttachingConnector.attach.attach004; + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.Utils; +import nsk.share.jdi.ArgumentHandler; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class TestDriver { + public static void main(String[] args) throws InterruptedException { + String arch = args[0]; + String transport = args[1]; + String jdiTransport; + // Need convert transport argument to string recognizable by nsk.share.jdi.ArgumentHandler + switch (transport) { + case "dt_socket": + jdiTransport = "socket"; + break; + case "dt_shmem": + jdiTransport = "shmem"; + break; + default: + throw new Error("Unexpected transport " + args[0] + + ", expected is dt_socket or dt_shmem"); + } + String[] jdiArgs = new String[]{ + "-connector=attaching", + "-transport=" + jdiTransport, + "-verbose", + "-waittime=5", + "-debugee.vmkind=java", + "-transport.address=dynamic", + "-arch=" + arch + }; + + if (isTransportSupported(jdiArgs)) { + System.out.println("Transport is supported on this platform, execute test"); + String suspend = args[2]; + Process debuggee = startDebuggee(jdiArgs, transport, suspend); + Process debugger = startDebugger(jdiArgs, Arrays.copyOfRange(args, 3, args.length), debuggee.pid()); + + int debuggerExit = debugger.waitFor(); + if (debuggerExit != 95) { + throw new Error("debugger exit code is " + debuggerExit); + } + + int debuggeeExit = debuggee.waitFor(); + if (debuggeeExit != 95) { + throw new Error("debuggee exit code is " + debuggeeExit); + } + } else { + System.out.println("SKIPPED: Transport isn't supported on this platform, treat test as passed"); + } + } + + + private static Process startDebuggee(String[] jdiArgs, String transport, String suspend) { + List cmd = new ArrayList<>(); + Class debuggeeClass = attach004t.class; + cmd.add(JDKToolFinder.getJDKTool("java")); + Collections.addAll(cmd, Utils.addTestJavaOpts( + "-cp", + Utils.TEST_CLASS_PATH, + "-Xdebug", + "-agentlib:jdwp=transport=" + transport + ",server=y,suspend=" + suspend, + "-Dmy.little.cookie=" + ProcessHandle.current().pid(), + debuggeeClass.getName())); + Collections.addAll(cmd, jdiArgs); + cmd.add("-testWorkDir"); + cmd.add("."); + + System.out.println("Starting debuggee [" + String.join(",", cmd) + "]"); + Process p; + try { + p = new ProcessBuilder(cmd).redirectErrorStream(true).start(); + } catch (IOException e) { + throw new Error("can't start debuggee"); + } + + Thread t = new Thread(() -> dumpStream("debuggee>> ", p.getInputStream())); + t.setDaemon(true); + t.start(); + + return p; + } + + private static Process startDebugger(String[] jdiArgs, String[] debuggerArgs, long debuggeePid) { + List cmd = new ArrayList<>(); + Class debuggerClass = attach004.class; + cmd.add(JDKToolFinder.getJDKTool("java")); + Collections.addAll(cmd, Utils.addTestJavaOpts( + "-cp", + Utils.TEST_CLASS_PATH, + debuggerClass.getName(), + "-debuggeePID", + "" + debuggeePid)); + Collections.addAll(cmd, debuggerArgs); + Collections.addAll(cmd, jdiArgs); + cmd.add("-testWorkDir"); + cmd.add("."); + + System.out.println("Starting debugger [" + String.join(",", cmd) + "]"); + Process p; + try { + p = new ProcessBuilder(cmd).redirectErrorStream(true).start(); + } catch (IOException e) { + throw new Error("can't start debugger"); + } + + Thread t = new Thread(() -> dumpStream("debugger>> ", p.getInputStream())); + t.setDaemon(true); + t.start(); + + return p; + } + + private static void dumpStream(String prefix, InputStream is) { + + byte[] buffer = new byte[1024]; + int n; + try (BufferedReader r = new BufferedReader(new InputStreamReader(is))) { + String line; + while ((line = r.readLine()) != null) { + System.out.println(prefix + line); + System.out.flush(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static boolean isTransportSupported(String[] jdiArgs) { + ArgumentHandler argHandler = new ArgumentHandler(jdiArgs); + + boolean result; + + if (argHandler.isShmemTransport()) { + result = !argHandler.shouldPass("dt_shmem"); + } else { + result = !argHandler.shouldPass("dt_socket"); + } + + if (result) { + System.out.println("Transport " + argHandler.getTransportType() + + " is result at " + argHandler.getArch()); + } else { + System.out.println("Transport " + argHandler.getTransportType() + + " isn't result at " + argHandler.getArch()); + } + + return result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/attach004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/attach004.java new file mode 100644 index 00000000000..e7346f124c6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/attach004.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.AttachingConnector.attach.attach004; + +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import nsk.share.*; +import nsk.share.ArgumentParser.BadOption; +import nsk.share.jdi.*; +import nsk.share.jdi.ConnectorTest.ArgHandler; +import nsk.share.jpda.SocketIOPipe; + +/* + * The test checks that debugger may establish connection with + * a target VM via 'com.sun.jdi.ProcessAttach' connector. + * + * Test receives target VM PID as parameter and tries to attach + * to target VM using ProcessAttach connector. + * + * To make test reliable following algorithm is used: + * - debugger attaches to the debuggee using ProcessAttach connector + * - debugger creates server socket using free port, saves this port number to the file 'portNumber.txt' and waits + * connection from debuggee process + * - when debuggee is started it waits when file 'portNumber.txt' is created, reads port number from this file and + * sends message to debugger that debuggee is ready to finish execution + * - debugger receives message from debuggee and sends another message which permits debuggee finish execution + */ +public class attach004 extends ConnectorTest { + + static String messageOK = "OK"; + + static String messageQuit = "QUIT"; + + static final String tempFileName = "portNumber.txt"; + + protected String getConnectorName() { + return "com.sun.jdi.ProcessAttach"; + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new attach004().runIt(argv, out); + } + + protected String getDebuggeeClass() { + return attach004t.class.getName(); + } + + static public class ArgHandler extends ConnectorTest.ArgHandler { + public ArgHandler(String[] args) { + super(args); + + } + + protected boolean checkOption(String option, String value) { + if (super.checkOption(option, value)) + return true; + + if (option.equals("debuggeePID")) { + return true; + } + + return false; + } + + protected void checkOptions() { + super.checkOptions(); + + if (!options.containsKey("testWorkDir")) { + throw new TestBug("testWorkDir wasn't specified"); + } + + if (!options.containsKey("debuggeePID")) { + throw new TestBug("debuggeePID wasn't specified"); + } + } + + public String getDebuggeePID() { + return options.getProperty("debuggeePID"); + } + } + + protected ArgHandler createArgumentHandler(String[] args) { + return new ArgHandler(args); + } + + protected void doTest() { + AttachingConnector connector = (AttachingConnector)findConnector(getConnectorName()); + + Map cArgs = connector.defaultArguments(); + + setConnectorArg(cArgs, "pid", ((ArgHandler)argHandler).getDebuggeePID()); + + if ((vm = tryAttach(connector, cArgs)) == null) { + testFailed(); + log.complain("Unable to attach the debugee VM"); + } + + log.display("debugee VM: name=" + vm.name() + " JRE version=" + vm.version() + "\n\tdescription=" + vm.description()); + + if (argHandler.waitVMStartEvent()) { + log.display("\nwaiting for VMStartEvent"); + waitForVMInit(vm); + log.display("\nresuming debugee VM"); + vm.resume(); + } + + SocketIOPipe pipe = null; + + try { + // create server socket on free port + pipe = SocketIOPipe.createServerIOPipe(log, 0, 0); + + // save port number in file + int port = pipe.getPort(); + savePortNumber(port); + + String message = pipe.readln(); + log.display("Received from debuggee: " + message); + + if (!message.equals(messageOK)) { + throw new TestBug("Unexpected debuggee message: " + message); + } + + log.display("Send message to debuggee: " + messageQuit); + pipe.println(messageQuit); + } finally { + if (pipe != null) + pipe.close(); + } + } + + private void savePortNumber(int portNumber) { + try { + File file = new File(argHandler.getTestWorkDir() + File.separator + tempFileName); + file.createNewFile(); + file.deleteOnExit(); + + PrintStream stream = null; + try { + stream = new PrintStream(new FileOutputStream(file)); + // conver portNumber to string + stream.println("" + portNumber); + } finally { + if (stream != null) + stream.close(); + } + + } catch (IOException e) { + log.complain("Unexpected IOException: " + e); + e.printStackTrace(log.getOutStream()); + throw new Failure("Unexpected IOException: " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/attach004t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/attach004t.java new file mode 100644 index 00000000000..342c90c2c72 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach004/attach004t.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.AttachingConnector.attach.attach004; + +import java.io.*; +import java.util.*; +import nsk.share.*; +import nsk.share.jdi.ArgumentHandler; +import nsk.share.jpda.SocketIOPipe; + +public class attach004t { + + static String testWorkDir; + + static String[] parseArgs(String[] args) { + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testWorkDir") && (i < args.length - 1)) { + testWorkDir = args[i + 1]; + + if (testWorkDir.endsWith(File.separator)) { + testWorkDir = testWorkDir.substring(0, testWorkDir.length() - 1); + } + + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + static int readPortNumber(Log log) { + try { + String fileName = testWorkDir + File.separator + attach004.tempFileName; + File file = new File(fileName); + + while (!file.exists()) { + log.display("File '" + file + "' doesn't exists, sleep some"); + Thread.sleep(1000); + } + + LineNumberReader reader = null; + + try { + FileInputStream fileInputStream = new FileInputStream(file); + while (fileInputStream.available() == 0) { + log.display("File '" + file + "' is empty, sleep some"); + Thread.sleep(1000); + } + + reader = new LineNumberReader(new InputStreamReader(fileInputStream)); + String portString = reader.readLine(); + + log.display("Port number was read: " + portString); + + return Integer.parseInt(portString); + } finally { + if (reader != null) + reader.close(); + } + + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + throw new Failure("Unexpected exception: " + e); + } + } + + public static void main(String args[]) throws InterruptedException { + ArgumentHandler argHandler = new ArgumentHandler(parseArgs(args)); + + if (testWorkDir == null) { + throw new TestBug("'testWorkDir' parameter wasn't specified"); + } + + Log log = argHandler.createDebugeeLog(); + + log.display("attach004t was started"); + + SocketIOPipe pipe = null; + try { + int portNumber = readPortNumber(log); + pipe = SocketIOPipe.createClientIOPipe(log, "localhost", portNumber, 0); + log.display("Send message to debugger: " + attach004.messageOK); + pipe.println(attach004.messageOK); + + String message = pipe.readln(); + log.display("Received from debugger: " + message); + if (!message.equals(attach004.messageQuit)) { + throw new TestBug("Unexpected debugger message: " + message); + } + + final long sleepTime = 10000; + + log.display("Sleep for " + sleepTime + "ms"); + try { + // debugee VM should wait here, otherwise test script doesn't have time to obtain debuggee exit code + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + throw new Failure("Unexpected exception: " + e); + } + + log.display("attach004t finished execution"); + } finally { + if (pipe != null) + pipe.close(); + } + + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach005/TestDescription.java new file mode 100644 index 00000000000..9136df49351 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attach/attach005/TestDescription.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/AttachingConnector/attach/attach005. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that debugger may establish connection with + * a target VM via com.sun.jdi.ProcessAttach connector. + * Target VM is started with option "suspend=y" (VM is to be suspended immediately before the main class is loaded). + * Test uses shared memory for communication between a debugger and the target VM. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.AttachingConnector.attach.attach004.TestDriver + * @run driver PropertyResolvingWrapper + * nsk.jdi.AttachingConnector.attach.attach004.TestDriver + * ${os.family}-${os.simpleArch} dt_shmem y + * -waitVMStartEvent + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java new file mode 100644 index 00000000000..a3c5a27178a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.AttachingConnector.attachnosuspend; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.ReferenceType; + +import java.io.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that debugger may establish connection with + * a target VM via com.sun.jdi.SocketAttach connector. + */ +public class attachnosuspend001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String DEBUGEE_CLASS = + "nsk.jdi.AttachingConnector.attachnosuspend.attachnosuspend001t"; + + private Log log; + + private VirtualMachine vm; + + private int attempts; // attempts to connect to the debugee VM + private int delay = 4000; // delay between connection attempts + + IORedirector outRedirector; + IORedirector errRedirector; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new attachnosuspend001().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + String port; + String listenPort; + Process proc; + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if "com.sun.jdi.SocketAttach" is not implemented +// on this platform + if (argHandler.shouldPass("com.sun.jdi.SocketAttach")) + return PASSED; + + log = new Log(out, argHandler); + + String args[] = argHandler.getArguments(); + + // treat second positional argument as delay between connection attempts + try { + delay = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + log.complain("Incorrect test parameter: timeout value must be an integer"); + return FAILED; + } catch (ArrayIndexOutOfBoundsException e) { + // ignore: default delay will be used if no second argument present + } + // calculate number of connection attempts to not exceed WAITTIME + long timeout = argHandler.getWaitTime() * 60 * 1000; + attempts = (int)(timeout / delay); + + port = argHandler.getTransportPort(); + listenPort = argHandler.getTransportPort(); + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + String cmd = java + + " -Xdebug -Xnoagent -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=" + + listenPort + " " + DEBUGEE_CLASS; + + Binder binder = new Binder(argHandler, log); + log.display("command: " + cmd); + Debugee debugee = binder.startLocalDebugee(cmd); + debugee.redirectOutput(log); + + if ((vm = attachTarget(argHandler.getTestHost(), port)) == null) { + log.complain("TEST: Unable to attach the debugee VM"); + debugee.close(); + return FAILED; + } + + log.display("debugee VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + debugee.setupVM(vm); + //debugee.waitForVMInit(timeout); + + //log.display("\nresuming debugee VM"); + //debugee.resume(); + + log.display("\nwaiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("Debugee VM has crashed: exit code=" + + code); + return FAILED; + } + log.display("debugee VM: exit code=" + code); + return PASSED; + } + + private VirtualMachine attachTarget(String host, String port) { + Connector.Argument arg; + + if (port == null) { + log.complain("TEST: port number is required!"); + return null; + } + + AttachingConnector connector = + (AttachingConnector) findConnector("com.sun.jdi.SocketAttach"); + + Map cArgs = connector.defaultArguments(); + Iterator cArgsValIter = cArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) cArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + connector.name()); + } + if (arg.name().equals("hostname") && host != null) + arg.setValue(host); + if (arg.name().equals("port")) + arg.setValue(port); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue="+argVal); + else log.display("\t\tvalue=NULL"); + } + + // make several attemts to connect to the debugee VM until WAITTIME exceeds + for (int i = 0; i < attempts; i++) { + try { + return connector.attach(cArgs); + } catch (IOException e) { + // could not connect; sleep a few and make new attempt + log.display("Connection attempt #" + i + " failed: " + e); + try { + Thread.currentThread().sleep(delay); + } catch (InterruptedException ie) { + log.complain("TEST INCOMPLETE: interrupted sleep: " + ie); + } + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return null; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return null; + } + } + // return null after all attempts failed + log.complain("FAILURE: all attempts to connect to the debugee VM failed"); + return null; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001/TestDescription.java new file mode 100644 index 00000000000..3b04b420e8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001. + * VM Testbase keywords: [quarantine] + * VM Testbase comments: JDK-8153613 + * VM Testbase readme: + * DESCRIPTION + * This test exactly as attach001 except using options: + * -agentlib:jdwb + * suspend=n + * Unfortunately, there is no way to handle VMStartEvent, + * because connection may happens later then event occured. + * COMMENT + * RFE 4920165 + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.AttachingConnector.attachnosuspend.attachnosuspend001 + * nsk.jdi.AttachingConnector.attachnosuspend.attachnosuspend001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.AttachingConnector.attachnosuspend.attachnosuspend001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001t.java new file mode 100644 index 00000000000..cc552a09e00 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend001t.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.AttachingConnector.attachnosuspend; + +import java.io.IOException; + +public class attachnosuspend001t { + public static void main(String args[]) { + try { + Thread.sleep(60000); + } catch (Throwable e) + { + e.printStackTrace(); + System.exit(attachnosuspend001.JCK_STATUS_BASE + attachnosuspend001.FAILED); + } + System.exit(attachnosuspend001.JCK_STATUS_BASE + attachnosuspend001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend002/TestDescription.java new file mode 100644 index 00000000000..df9650ad812 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend002/TestDescription.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that debugger may establish connection with + * a target VM via com.sun.jdi.ProcessAttach connector. + * Test uses socket transport for communication between a debugger and the target VM. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.AttachingConnector.attach.attach004.TestDriver + * @run driver PropertyResolvingWrapper + * nsk.jdi.AttachingConnector.attach.attach004.TestDriver + * ${os.family}-${os.simpleArch} dt_socket n + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend003/TestDescription.java new file mode 100644 index 00000000000..53507ad3bd9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend003/TestDescription.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/AttachingConnector/attachnosuspend/attachnosuspend003. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that debugger may establish connection with + * a target VM via com.sun.jdi.ProcessAttach connector. + * Test uses shared memory transport for communication between a debugger and the target VM. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.AttachingConnector.attach.attach004.TestDriver + * @run driver PropertyResolvingWrapper + * nsk.jdi.AttachingConnector.attach.attach004.TestDriver + * ${os.family}-${os.simpleArch} dt_shmem n + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001.java new file mode 100644 index 00000000000..6aac8fbc989 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC1 + * Description: After point of execution, same method + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as next line after point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Resume + * X. Prints out "foo" after printing the + * numbers + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 37th line (method code>method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into ethod_A and resumes debugee. It is expected + * the added line will be not actual after the redefining according to + * redefineClasses spec: + * "The redefined method will be used on new invokes. If resetting these + * frames is desired, use ThreadReference.popFrames() with + * Method.isObsolete()." + */ + +public class tc01x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc01x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 5; + + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc01x001 thisTest = new tc01x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + int eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc01x001a.brkpMethodName, + tc01x001a.brkpLineNumber); + + debugee.resume(); + eventCount++; + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + display("redefining..."); + redefineDebugee(); + + createMethodExitRequest(debugeeClass); + debugee.resume(); + eventCount++; + + } else if (event instanceof MethodExitEvent) { + display("\n event ===>>> " + event); + Method mthd = ((MethodExitEvent )event).method(); + eventCount++; + display("exiting from \"" + mthd.name() + "\" method"); + if (mthd.isObsolete()) { + Field fld = debugeeClass.fieldByName(tc01x001a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() == tc01x001a.CHANGED_VALUE) { + complain("Unexpected: new code is actual " + + "without resetting frames"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: new code is not actual " + + "without resetting frames!!!"); + } + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private MethodExitRequest createMethodExitRequest(ReferenceType refType) { + EventRequestManager evm = debugee.getEventRequestManager(); + MethodExitRequest request = evm.createMethodExitRequest(); + request.addClassFilter(refType); + request.enable(); + return request; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/TestDescription.java new file mode 100644 index 00000000000..d5fcc116edf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc01x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC1 + * Description: After point of execution, same method + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as next line after point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Resume + * X. Prints out "foo" after printing the + * numbers + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 37th line (method "method_A"). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into "method_A" and resumes debugee. It is expected the + * new code will be NOT actual after the redefining (see COMMENTS) + * COMMENTS: + * Step 5 of Borland's scenario is wrong due to redefineClasses spec says: + * "The redefined method will be used on new invokes. If resetting these + * frames is desired, use ThreadReference.popFrames() with + * Method.isObsolete()." + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc01x001 + * nsk.jdi.BScenarios.hotswap.tc01x001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc01x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/newclass/tc01x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/newclass/tc01x001a.java new file mode 100644 index 00000000000..14269be58d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001/newclass/tc01x001a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc01x001a is deugee's part of the tc01x001. + */ +public class tc01x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 56; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc01x001a obj = new tc01x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { // brkpLineNumber + method_B(); + fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001a.java new file mode 100644 index 00000000000..dee625307a6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x001a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc01x001a is deugee's part of the tc01x001. + */ +public class tc01x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 57; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc01x001a obj = new tc01x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); // brkpLineNumber +// fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002.java new file mode 100644 index 00000000000..48a6411dfe4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002.java @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC1 + * Description: After point of execution, same method + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as next line after point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Resume + * X. Prints out "foo" after printing the + * numbers + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 37th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, pops current frame and resumes debugee. + * It is expected the new code will be actual after the redefining + * + * Step 5 of Borland's scenario is wrong due to redefineClasses spec says: + * "The redefined method will be used on new invokes. If resetting these + * frames is desired, use ThreadReference.popFrames() with + * Method.isObsolete()." + */ + +public class tc01x002 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc01x002"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 5; + + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc01x002 thisTest = new tc01x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + int eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc01x002a.brkpMethodName, + tc01x002a.brkpLineNumber); + + debugee.resume(); + eventCount++; + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + display("redefining..."); + redefineDebugee(); + popFrames(((BreakpointEvent )event).thread()); + + createMethodExitRequest(debugeeClass); + debugee.resume(); + eventCount++; + + } else if (event instanceof MethodExitEvent) { + display("\n event ===>>> " + event); + Method mthd = ((MethodExitEvent )event).method(); + eventCount++; + display("exiting from \"" + mthd.name() + "\" method"); + if (mthd.name().compareTo(tc01x002a.brkpMethodName) == 0) { + Field fld = debugeeClass.fieldByName(tc01x002a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() != tc01x002a.CHANGED_VALUE) { + complain("Unexpected: new code is not actual " + + "after resetting frames"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: new code is actual " + + "after resetting frames!!!"); + } + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private void popFrames(ThreadReference thread) { + try { + StackFrame frame = thread.frame(0); + thread.popFrames(frame); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private MethodExitRequest createMethodExitRequest(ReferenceType refType) { + EventRequestManager evm = debugee.getEventRequestManager(); + MethodExitRequest request = evm.createMethodExitRequest(); + request.addClassFilter(refType); + request.enable(); + return request; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/TestDescription.java new file mode 100644 index 00000000000..519ea3b2c3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc01x002. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC1 + * Description: After point of execution, same method + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as next line after point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Resume + * X. Prints out "foo" after printing the + * numbers + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 37th line (method "method_A"). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into "method_A", pops current frame and resumes debugee. + * It is expected the new code will be actual after the redefining + * (see COMMENTS). + * COMMENTS: + * Step 5 of Borland's scenario is wrong due to redefineClasses spec says: + * "The redefined method will be used on new invokes. If resetting these + * frames is desired, use ThreadReference.popFrames() with + * Method.isObsolete()." + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc01x002 + * nsk.jdi.BScenarios.hotswap.tc01x002a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc01x002 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/newclass/tc01x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/newclass/tc01x002a.java new file mode 100644 index 00000000000..d2447dc10a9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/newclass/tc01x002a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc01x002a is deugee's part of the tc01x002. + */ +public class tc01x002a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 56; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc01x002a obj = new tc01x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { // brkpLineNumber + method_B(); + fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002a.java new file mode 100644 index 00000000000..b52cdd45bd1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc01x002a is deugee's part of the tc01x002. + */ +public class tc01x002a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 57; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc01x002a obj = new tc01x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); // brkpLineNumber +// fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001.java new file mode 100644 index 00000000000..aba42b2ce3c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001.java @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC2 + * Description: Before point of execution, same method + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as line before point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.Resume + * X. Prints out "foo" and hits breakpoint + * on line 24 + * 7.Resume + * X. Prints numbers + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger:
    + * - redefines debugee adding a new line into "method_A",
    + * - pops current frame
    + * and resumes debugee. + * It is expected the new code will be actual after the redefining and + * it doesn't hit breakpoint according to JVMDI Redefine Classes spec : + * "...All breakpoints in the class are cleared." + */ + +public class tc02x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc02x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 5; + private int eventCount = 0; + + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc02x001 thisTest = new tc02x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc02x001a.brkpMethodName, + tc02x001a.brkpLineNumber); + + debugee.resume(); + eventCount++; + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + switch (eventCount) { + case 1: + display("redefining..."); + redefineDebugee(); + popFrames(((BreakpointEvent )event).thread()); + createMethodExitRequest(debugeeClass); + + break; + + default: + complain("Unexpected breakpoint event"); + exitStatus = Consts.TEST_FAILED; + } + eventCount++; + hitBreakpoint((BreakpointEvent )event); + debugee.resume(); + + } else if (event instanceof MethodExitEvent) { + display("\n event ===>>> " + event); + hitMethodExit((MethodExitEvent)event); + eventCount++; + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private void popFrames(ThreadReference thread) { + try { + StackFrame frame = thread.frame(0); + thread.popFrames(frame); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private MethodExitRequest createMethodExitRequest(ReferenceType refType) { + EventRequestManager evm = debugee.getEventRequestManager(); + MethodExitRequest request = evm.createMethodExitRequest(); + request.addClassFilter(refType); + request.enable(); + return request; + } + + private void hitBreakpoint(BreakpointEvent event) { + locationInfo(event); + if (event.location().lineNumber() != tc02x001a.checkLastLine) { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc02x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } + display(""); + } + + private void hitMethodExit(MethodExitEvent event) { + + locationInfo(event); + + Method mthd = ((MethodExitEvent )event).method(); + if (mthd.name().compareTo(tc02x001a.brkpMethodName) == 0) { + Field fld = debugeeClass.fieldByName(tc02x001a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() != tc02x001a.CHANGED_VALUE) { + complain("Unexpected: new code is not actual " + + "after resetting frames"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: new code is actual " + + "after resetting frames!!!"); + } + } + display(""); + } + + private void locationInfo(LocatableEvent event) { + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/TestDescription.java new file mode 100644 index 00000000000..3cf356a3ce4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/TestDescription.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc02x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC2 + * Description: Before point of execution, same method + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as line before point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.Resume + * X. Prints out "foo" and hits breakpoint + * on line 24 + * 7.Resume + * X. Prints numbers + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method "method_A"). + * After the breakpoint is reached, debugger: + * - redefines debugee adding a new line into "method_A", + * - pops current frame + * and resumes debugee. + * It is expected the new code will be actual after the redefining and + * it doesn't hit breakpoint (see COMMENTS). + * COMMENTS: + * In step 6 waiting breakpoint is wrong due to JVMDI Redefine + * Classes spec says:"...All breakpoints in the class are cleared." + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc02x001 + * nsk.jdi.BScenarios.hotswap.tc02x001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc02x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/newclass/tc02x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/newclass/tc02x001a.java new file mode 100644 index 00000000000..922b09247e3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/newclass/tc02x001a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x001a is deugee's part of the tc02x001. + */ +public class tc02x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 57; + public final static int checkLastLine = 57; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc02x001a obj = new tc02x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { // brkpLineNumber // checkLastLine + method_B(); + fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001a.java new file mode 100644 index 00000000000..4c4c2288c5d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x001a is deugee's part of the tc02x001. + */ +public class tc02x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 58; + public final static int checkLastLine = 58; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc02x001a obj = new tc02x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); // brkpLineNumber // checkLastLine +// fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002.java new file mode 100644 index 00000000000..eaeb7cbdc5d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC2 + * Description: Before point of execution, same method + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as line before point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.Resume + * X. Prints out "foo" and hits breakpoint + * on line 24 + * 7.Resume + * X. Prints numbers + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger:
    + * - redefines debugee adding a new line into "method_A",
    + * - pops current frame,
    + * - sets breakpoint at the 38th line again
    + * and resumes debugee. + * It is expected the new code will be actual after the redefining and + * it doesn't hit breakpoint according to JVMDI Redefine Classes spec : + * "...All breakpoints in the class are cleared." + */ + +public class tc02x002 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc02x002"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 6; + private int eventCount = 0; + + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc02x002 thisTest = new tc02x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc02x002a.brkpMethodName, + tc02x002a.brkpLineNumber); + + debugee.resume(); + eventCount++; + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + switch (eventCount) { + case 1: + display("redefining..."); + redefineDebugee(); + popFrames(((BreakpointEvent )event).thread()); + + debugee.setBreakpoint(debugeeClass, + tc02x002a.brkpMethodName, + tc02x002a.brkpLineNumber); + break; + + case 2: + display("!!!Expected second breakpoint event!!!"); + createMethodExitRequest(debugeeClass); + break; + + default: + complain("Unexpected breakpoint event"); + exitStatus = Consts.TEST_FAILED; + } + eventCount++; + hitBreakpoint((BreakpointEvent )event); + debugee.resume(); + + } else if (event instanceof MethodExitEvent) { + display("\n event ===>>> " + event); + hitMethodExit((MethodExitEvent)event); + eventCount++; + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private void popFrames(ThreadReference thread) { + try { + StackFrame frame = thread.frame(0); + thread.popFrames(frame); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private MethodExitRequest createMethodExitRequest(ReferenceType refType) { + EventRequestManager evm = debugee.getEventRequestManager(); + MethodExitRequest request = evm.createMethodExitRequest(); + request.addClassFilter(refType); + request.enable(); + return request; + } + + private void hitBreakpoint(BreakpointEvent event) { + locationInfo(event); + if (event.location().lineNumber() != tc02x002a.checkLastLine) { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc02x002a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } + display(""); + } + + private void hitMethodExit(MethodExitEvent event) { + + locationInfo(event); + + Method mthd = ((MethodExitEvent )event).method(); + if (mthd.name().compareTo(tc02x002a.brkpMethodName) == 0) { + Field fld = debugeeClass.fieldByName(tc02x002a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() != tc02x002a.CHANGED_VALUE) { + complain("Unexpected: new code is not actual " + + "after resetting frames"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: new code is actual " + + "after resetting frames!!!"); + } + } + display(""); + } + + private void locationInfo(LocatableEvent event) { + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/TestDescription.java new file mode 100644 index 00000000000..ac19172c5c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc02x002. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC2 + * Description: Before point of execution, same method + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as line before point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.Resume + * X. Prints out "foo" and hits breakpoint + * on line 24 + * 7.Resume + * X. Prints numbers + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method "method_A"). + * After the breakpoint is reached, debugger: + * - redefines debugee adding a new line into "method_A", + * - pops current frame, + * - sets breakpoint at the 38th line again + * and resumes debugee. + * It is expected the new code will be actual after the redefining and + * it hits breakpoint. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc02x002 + * nsk.jdi.BScenarios.hotswap.tc02x002a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc02x002 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/newclass/tc02x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/newclass/tc02x002a.java new file mode 100644 index 00000000000..738f400eaef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/newclass/tc02x002a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x002a is deugee's part of the tc02x002. + */ +public class tc02x002a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 57; + public final static int checkLastLine = 57; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc02x002a obj = new tc02x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { // brkpLineNumber // checkLastLine + method_B(); + fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002a.java new file mode 100644 index 00000000000..06258a33ff4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x002a is deugee's part of the tc02x002. + */ +public class tc02x002a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 58; + public final static int checkLastLine = 58; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc02x002a obj = new tc02x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); // brkpLineNumber // checkLastLine +// fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001.java new file mode 100644 index 00000000000..16644e8f6e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001.java @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC3 + * Description: After point of execution, different method + * Steps: 1.Set breakpoint at line 24 (call from a() + * to b()) + * 2.Debug Main + * 3.Insert as first line in b(): + * System.err.println("foo"); + * 4.Smart Swap + * 5.Resume + * X. Prints out "foo" before printing the + * numbers + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 37th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * first line into method_B and resumes debugee. It is expected the + * new code will be actual before calling method_C + */ + +public class tc03x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc03x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 4; + private static final String methodNameToCheck = "method_C"; + + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc03x001 thisTest = new tc03x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + int eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc03x001a.brkpMethodName, + tc03x001a.brkpLineNumber); + + debugee.resume(); + eventCount++; + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + display("redefining..."); + redefineDebugee(); + + createMethodEntryRequest(debugeeClass); + debugee.resume(); + eventCount++; + + } else if (event instanceof MethodEntryEvent) { + display("\n event ===>>> " + event); + Method mthd = ((MethodEntryEvent )event).method(); + eventCount++; + display("exiting from \"" + mthd.name() + "\" method"); + if (mthd.name().compareTo(methodNameToCheck) == 0) { + Field fld = debugeeClass.fieldByName(tc03x001a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() == tc03x001a.CHANGED_VALUE) { + display("!!!Expected: new code is actual " + + "before calling " + methodNameToCheck + + "!!!"); + } else { + complain("Unexpected: new code is not actual " + + "before calling " + methodNameToCheck); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private MethodEntryRequest createMethodEntryRequest(ReferenceType refType) { + EventRequestManager evm = debugee.getEventRequestManager(); + MethodEntryRequest request = evm.createMethodEntryRequest(); + request.addClassFilter(refType); + request.enable(); + return request; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/TestDescription.java new file mode 100644 index 00000000000..34aebb7ca07 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc03x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC3 + * Description: After point of execution, different method + * Steps: 1.Set breakpoint at line 24 (call from a() + * to b()) + * 2.Debug Main + * 3.Insert as first line in b(): + * System.err.println("foo"); + * 4.Smart Swap + * 5.Resume + * X. Prints out "foo" before printing the + * numbers + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 37th line (method "method_A"). + * After the breakpoint is reached, debugger redefines debugee adding + * first line into "method_B" and resumes debugee. It is expected the + * new code will be actual before calling "method_C" + * COMMENTS: + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc03x001 + * nsk.jdi.BScenarios.hotswap.tc03x001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc03x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/newclass/tc03x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/newclass/tc03x001a.java new file mode 100644 index 00000000000..0fc784038fb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001/newclass/tc03x001a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc03x001a is deugee's part of the tc03x001. + */ +public class tc03x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 56; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc03x001a obj = new tc03x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { // brkpLineNumber + method_B(); + } + + public void method_B() { + fieldToCheck = CHANGED_VALUE; + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001a.java new file mode 100644 index 00000000000..42665742895 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc03x001a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc03x001a is deugee's part of the tc03x001. + */ +public class tc03x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 57; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc03x001a obj = new tc03x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); // brkpLineNumber + } + + public void method_B() { +// fieldToCheck = CHANGED_VALUE; + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001.java new file mode 100644 index 00000000000..1cc69d32311 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001.java @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC4 + * Description: Before point of execution, different method + * Steps: 1.Set breakpoint at line 30 (call to c() + * from b()) + * 2.Debug Main + * 3.Insert as first line in a(): + * System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.Resume + * X. Prints out "foo" and hits breakpoint + * at line 30 + * 7.Resume + * X. Print numbers + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 43th line (method method_B). + * After the breakpoint is reached, debugger: + * - redefines debugee adding a new line into method_A, + * - pops frames at beginning of method_A + * and resumes debugee. + * It is expected the new code will be actual after the redefining and + * it doesn't hit breakpoint. + */ + +public class tc04x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc04x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 5; + private int eventCount = 0; + + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc04x001 thisTest = new tc04x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc04x001a.brkpMethodName, + tc04x001a.brkpLineNumber); + + debugee.resume(); + eventCount++; + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + switch (eventCount) { + case 1: + display("redefining..."); + redefineDebugee(); + popFrames(((BreakpointEvent )event).thread()); + createMethodExitRequest(debugeeClass); + + break; + + default: + complain("Unexpected breakpoint hitting"); + exitStatus = Consts.TEST_FAILED; + } + eventCount++; + hitBreakpoint((BreakpointEvent )event); + debugee.resume(); + + } else if (event instanceof MethodExitEvent) { + display("\n event ===>>> " + event); + hitMethodExit((MethodExitEvent)event); + eventCount++; + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private void popFrames(ThreadReference thread) { + display("\npop frames..."); + try { + StackFrame frame = thread.frame(0); + Method mthd = frame.location().method(); + do { + thread.popFrames(frame); + display(mthd.name() + " is resetted"); + frame = thread.frame(0); + mthd = frame.location().method(); + } while (mthd.isObsolete()); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + display(""); + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private MethodExitRequest createMethodExitRequest(ReferenceType refType) { + EventRequestManager evm = debugee.getEventRequestManager(); + MethodExitRequest request = evm.createMethodExitRequest(); + request.addClassFilter(refType); + request.enable(); + return request; + } + + private void hitBreakpoint(BreakpointEvent event) { + locationInfo(event); + if (event.location().lineNumber() != tc04x001a.checkLastLine) { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc04x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } + display(""); + } + + private void hitMethodExit(MethodExitEvent event) { + + locationInfo(event); + + Method mthd = ((MethodExitEvent )event).method(); + if (mthd.name().compareTo(tc04x001a.brkpMethodName) == 0) { + Field fld = debugeeClass.fieldByName(tc04x001a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() != tc04x001a.CHANGED_VALUE) { + complain("Unexpected: new code is not actual " + + "after resetting frames"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: new code is actual " + + "after resetting frames!!!"); + } + } + display(""); + } + + private void locationInfo(LocatableEvent event) { + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/TestDescription.java new file mode 100644 index 00000000000..706b5d761c5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/TestDescription.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc04x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC4 + * Description: Before point of execution, different method + * Steps: 1.Set breakpoint at line 30 (call to c() + * from b()) + * 2.Debug Main + * 3.Insert as first line in a(): + * System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.Resume + * X. Prints out "foo" and hits breakpoint + * at line 30 + * 7.Resume + * X. Print numbers + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 43th line (method "method_B"). + * After the breakpoint is reached, debugger: + * - redefines debugee adding a new line into "method_A", + * - pops frames at beginning of "method_A" + * and resumes debugee. + * It is expected the new code will be actual after the redefining and + * it doesn't hit breakpoint (see COMMENTS). + * COMMENTS: + * In step 6 waiting breakpoint is wrong due to JVMDI Redefine + * Classes spec says:"...All breakpoints in the class are cleared." + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc04x001 + * nsk.jdi.BScenarios.hotswap.tc04x001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc04x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/newclass/tc04x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/newclass/tc04x001a.java new file mode 100644 index 00000000000..6f123c9e495 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/newclass/tc04x001a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc04x001a is deugee's part of the tc04x001. + */ +public class tc04x001a { + + public final static String brkpMethodName = "method_B"; + public final static int brkpLineNumber = 62; + public final static int checkLastLine = 62; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc04x001a obj = new tc04x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + fieldToCheck = CHANGED_VALUE; + method_B(); + } + + public void method_B() { // brkpLineNumber // checkLastLine + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001a.java new file mode 100644 index 00000000000..8e4d16dffa6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc04x001a is deugee's part of the tc04x001. + */ +public class tc04x001a { + + public final static String brkpMethodName = "method_B"; + public final static int brkpLineNumber = 63; + public final static int checkLastLine = 63; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc04x001a obj = new tc04x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { +// fieldToCheck = CHANGED_VALUE; + method_B(); + } + + public void method_B() { + method_C(); // checkLastLine // checkLastLine + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002.java new file mode 100644 index 00000000000..467af1742fe --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002.java @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC4 + * Description: Before point of execution, different method + * Steps: 1.Set breakpoint at line 30 (call to c() + * from b()) + * 2.Debug Main + * 3.Insert as first line in a(): + * System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.Resume + * X. Prints out "foo" and hits breakpoint + * at line 30 + * 7.Resume + * X. Print numbers + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 43th line (method method_B). + * After the breakpoint is reached, debugger: + * - redefines debugee adding a new line into method_A, + * - pops frames at beginning of method_A + * - sets breakpoint at the 43th line again + * and resumes debugee. + * It is expected the new code will be actual after the redefining and + * it hits breakpoint. + */ + +public class tc04x002 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc04x002"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 6; + private int eventCount = 0; + + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc04x002 thisTest = new tc04x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc04x002a.brkpMethodName, + tc04x002a.brkpLineNumber); + + debugee.resume(); + eventCount++; + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + switch (eventCount) { + case 1: + display("redefining..."); + redefineDebugee(); + popFrames(((BreakpointEvent )event).thread()); + + debugee.setBreakpoint(debugeeClass, + tc04x002a.brkpMethodName, + tc04x002a.brkpLineNumber); + break; + + case 2: + display("!!!Expected second breakpoint event!!!"); + createMethodExitRequest(debugeeClass); + break; + + default: + complain("Unexpected breakpoint event"); + exitStatus = Consts.TEST_FAILED; + } + eventCount++; + hitBreakpoint((BreakpointEvent )event); + debugee.resume(); + + } else if (event instanceof MethodExitEvent) { + display("\n event ===>>> " + event); + hitMethodExit((MethodExitEvent)event); + eventCount++; + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private void popFrames(ThreadReference thread) { + display("\npop frames..."); + try { + StackFrame frame = thread.frame(0); + Method mthd = frame.location().method(); + do { + thread.popFrames(frame); + display(mthd.name() + " is resetted"); + frame = thread.frame(0); + mthd = frame.location().method(); + } while (mthd.isObsolete()); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + display(""); + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private MethodExitRequest createMethodExitRequest(ReferenceType refType) { + EventRequestManager evm = debugee.getEventRequestManager(); + MethodExitRequest request = evm.createMethodExitRequest(); + request.addClassFilter(refType); + request.enable(); + return request; + } + + private void hitBreakpoint(BreakpointEvent event) { + locationInfo(event); + if (event.location().lineNumber() != tc04x002a.checkLastLine) { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc04x002a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } + display(""); + } + + private void hitMethodExit(MethodExitEvent event) { + + locationInfo(event); + + Method mthd = ((MethodExitEvent )event).method(); + if (mthd.name().compareTo(tc04x002a.brkpMethodName) == 0) { + Field fld = debugeeClass.fieldByName(tc04x002a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() != tc04x002a.CHANGED_VALUE) { + complain("Unexpected: new code is not actual " + + "after resetting frames"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: new code is actual " + + "after resetting frames!!!"); + } + } + display(""); + } + + private void locationInfo(LocatableEvent event) { + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/TestDescription.java new file mode 100644 index 00000000000..640730ed4cd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc04x002. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC4 + * Description: Before point of execution, different method + * Steps: 1.Set breakpoint at line 30 (call to c() + * from b()) + * 2.Debug Main + * 3.Insert as first line in a(): + * System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.Resume + * X. Prints out "foo" and hits breakpoint + * at line 30 + * 7.Resume + * X. Print numbers + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 43th line (method "method_B"). + * After the breakpoint is reached, debugger: + * - redefines debugee adding a new line into "method_A", + * - pops frames at beginning of "method_A" + * - sets breakpoint at the 43th line again + * and resumes debugee. + * It is expected the new code will be actual after the redefining and + * it hits breakpoint. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc04x002 + * nsk.jdi.BScenarios.hotswap.tc04x002a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc04x002 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/newclass/tc04x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/newclass/tc04x002a.java new file mode 100644 index 00000000000..43d0bc0c1ca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/newclass/tc04x002a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc04x002a is deugee's part of the tc04x002. + */ +public class tc04x002a { + + public final static String brkpMethodName = "method_B"; + public final static int brkpLineNumber = 62; + public final static int checkLastLine = 62; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc04x002a obj = new tc04x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + fieldToCheck = CHANGED_VALUE; + method_B(); + } + + public void method_B() { // brkpLineNumber // checkLastLine + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002a.java new file mode 100644 index 00000000000..13632df3ef9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc04x002a is deugee's part of the tc04x002. + */ +public class tc04x002a { + + public final static String brkpMethodName = "method_B"; + public final static int brkpLineNumber = 63; + public final static int checkLastLine = 63; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc04x002a obj = new tc04x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { +// fieldToCheck = CHANGED_VALUE; + method_B(); + } + + public void method_B() { + method_C(); // brkpLineNumber // checkLastLine + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001.java new file mode 100644 index 00000000000..47a49b89bf4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC5
    + * Description: After point of execution, same method - stepping
    + * Steps: 1.Set breakpoint at line 24 (call to b()
    + * from a())
    + * 2.Debug Main
    + * 3.Insert as next line after point of
    + * execution: System.err.println("foo");
    + * 4.Smart Swap
    + * 5.F7 to step into
    + * X. Steps into method b()
    + *
    + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, creates StepRequest and + * resumes debugee. When the location of the current StepEvent is + * in method_B, created StepRequest is disabled. + * Working of debugger and debugee is synchronized via IOPipe channel. + */ + +public class tc05x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc05x001"; + private final static String debugeeName = debuggerName + "a"; + + public final static String PERFORM_SGL = "perform"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + + private static final String firstMethodName = "method_B"; + + private int eventCount; + private int expectedEventCount = 2; + private ClassType debugeeClass; + StepRequest stepRequest = null; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc05x001 thisTest = new tc05x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + debugee.VM().suspend(); + + display("Tested class\t:" + debugeeClass.name()); + + BreakpointRequest brkp = debugee.setBreakpoint(debugeeClass, + tc05x001a.brkpMethodName, + tc05x001a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal(PERFORM_SGL); + + BreakpointEvent brkpEvent = waitBreakpointEvent(brkp, waitTime); + + display("\nredefining..."); + redefineDebugee(); + + ThreadReference thread = brkpEvent.thread(); + + EventRequestManager evm = debugee.getEventRequestManager(); + + display("creating step request INTO..."); + stepRequest = evm.createStepRequest(thread, StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + stepRequest.addClassFilter(debugeeClass); + stepRequest.enable(); + debugee.resume(); + + boolean cmp = false; + StepEvent stepEvent; + Event event; + for (int i = 0; i < 3; i++) { + // waiting the breakpoint event + display("waiting step event..."); + try { + event = debugee.waitingEvent(stepRequest, waitTime); + } catch (Exception e) { + stepRequest.disable(); + throw new Failure(UNEXPECTED_STRING + e); + } + if (!(event instanceof StepEvent )) { + stepRequest.disable(); + throw new Failure("StepEvent didn't arrive"); + } + if (hitStep((StepEvent )event)) { + break; + } + debugee.resume(); + } + evm.deleteEventRequest(stepRequest); + debugee.resume(); + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(testDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new Failure("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } + + private boolean hitStep(StepEvent event) { + locationInfo(event); + String methodName = event.location().method().name(); + boolean ret = methodName.compareTo(firstMethodName) != 0; + if (ret) { + if (!event.location().method().isObsolete()) { + complain("Unexpected event" + event); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected event location at \"" + methodName + "\""); + } + } else { + display("!!!Expected event location at \"" + methodName + "\""); + stepRequest.disable(); + } + display(""); + return !ret; + } + + private void locationInfo(LocatableEvent event) { + eventCount++; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + } catch (AbsentInformationException e) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001/TestDescription.java new file mode 100644 index 00000000000..c253b81c916 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc05x001. + * VM Testbase keywords: [jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC5 + * Description: After point of execution, same method - stepping + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as next line after point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.F7 to step into + * X. Steps into method b() + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, creates StepRequest and resumes debugee. + * When the location of the current StepEvent is in method_B, created + * StepRequest is disabled. + * Working of debugger and debugee is synchronized via IOPipe channel. + * COMMENTS: + * The scenario mentions debugee crashes on 1.4.0-b91. + * The test differs from tc05x002 by that it works via IOPipe + * channel and the crash is reproduced. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc05x001 + * nsk.jdi.BScenarios.hotswap.tc05x001a + * + * @comment make sure tc05x001a is compiled with full debug info + * @clean nsk.jdi.BScenarios.hotswap.tc05x001a + * @compile -g:lines,source,vars ../tc05x001a.java + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc05x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001/newclass/tc05x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001/newclass/tc05x001a.java new file mode 100644 index 00000000000..7219ade28d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001/newclass/tc05x001a.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc05x001a is deugee's part of the tc05x001. + */ +public class tc05x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 69; + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + runIt(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void runIt() { + tc05x001a obj = new tc05x001a(); + obj.method_A(); + } + + public void method_A() { // brkpLineNumber + method_B(); + log.display("new line"); +// ^^^^^^^^^^^^^^^^^^^^^^^^ inserted line + } + + public void method_B() { + method_C(); + } + + public void method_C() { + log.display("method_C:: line 1"); + log.display("method_C:: line 2"); + log.display("method_C:: line 3"); + log.display("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001a.java new file mode 100644 index 00000000000..ca4638fff32 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x001a.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc05x001a is deugee's part of the tc05x001. + */ +public class tc05x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 71; + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + runIt(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void runIt() { + tc05x001a obj = new tc05x001a(); + obj.method_A(); + } + + public void method_A() { + method_B(); // brkpLineNumber +// log.display("new line"); +// try inserting code here + } + + public void method_B() { + method_C(); + } + + public void method_C() { + log.display("method_C:: line 1"); + log.display("method_C:: line 2"); + log.display("method_C:: line 3"); + log.display("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002.java new file mode 100644 index 00000000000..8523866c886 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002.java @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC5
    + * Description: After point of execution, same method - stepping
    + * Steps: 1.Set breakpoint at line 24 (call to b()
    + * from a())
    + * 2.Debug Main
    + * 3.Insert as next line after point of
    + * execution: System.err.println("foo");
    + * 4.Smart Swap
    + * 5.F7 to step into
    + * X. Steps into method b()
    + *
    + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, creates StepRequest and + * resumes debugee. When the location of the current StepEvent is + * in method_B, created StepRequest is disabled. + */ + +public class tc05x002 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc05x002"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private static final String firstMethodName = "method_B"; + + private int eventCount; + private int expectedEventCount = 2; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc05x002 thisTest = new tc05x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc05x002a.brkpMethodName, + tc05x002a.brkpLineNumber); + + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + display("redefining..."); + redefineDebugee(); + createStepRequest(((LocatableEvent )event).thread()); + debugee.resume(); + + } else if (event instanceof StepEvent) { + display("\n event ===>>> " + event); + hitStep((StepEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private StepRequest createStepRequest(ThreadReference thread) { + EventRequestManager evm = debugee.getEventRequestManager(); + StepRequest request = evm.createStepRequest(thread, + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + request.enable(); + return request; + } + + private void hitBreakpoint(BreakpointEvent event) { + locationInfo(event); + if (event.location().lineNumber() != tc05x002a.checkLastLine) { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc05x002a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } + display(""); + } + + private void hitStep(StepEvent event) { + locationInfo(event); + String methodName = event.location().method().name(); + StepRequest request = (StepRequest )event.request(); + if (methodName.compareTo(firstMethodName) != 0) { + if (!event.location().method().isObsolete()) { + complain("Unexpected event" + event); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected step event!!!"); + } + } else { + display("!!!Expected step event!!!"); + request.disable(); + } + display(""); + } + + private void locationInfo(LocatableEvent event) { + if (!event.location().method().isObsolete()) { + eventCount++; + } + String methodName = "<>"; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + try { + methodName = event.location().method().name(); + display("\tsource\t- " + event.location().sourceName()); + display("\tmethod\t- " + methodName); + display("\tline\t- " + event.location().lineNumber()); + } catch (AbsentInformationException e) { + } + if (event.location().method().isObsolete()) { + display(methodName + " method is skipped"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/TestDescription.java new file mode 100644 index 00000000000..e894c9f7aa7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/TestDescription.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc05x002. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC5 + * Description: After point of execution, same method - stepping + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as next line after point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.F7 to step into + * X. Steps into method b() + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, creates StepRequest and resumes debugee. + * When the location of the current StepEvent is in method_B, created + * StepRequest is disabled. + * COMMENTS: + * The scenario mentions debugee crashes on 1.4.0-b91. + * The test differs from tc05x001 by that it works without IOPipe + * channel and instead of the crash unexpected IllegalArgumentException + * is thrown. + * After redefining location of the first step event is expected at the + * redefined method according to #4756474. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc05x002 + * nsk.jdi.BScenarios.hotswap.tc05x002a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc05x002 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/newclass/tc05x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/newclass/tc05x002a.java new file mode 100644 index 00000000000..f4481405830 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002/newclass/tc05x002a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc05x002a is deugee's part of the tc05x002. + */ +public class tc05x002a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 57; + public final static int checkLastLine = 57; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc05x002a obj = new tc05x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { // brkpLineNumber // checkLastLine + method_B(); + fieldToCheck = CHANGED_VALUE; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inserted line + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002a.java new file mode 100644 index 00000000000..bb6c13feab7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc05x002a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc05x002a is deugee's part of the tc05x002. + */ +public class tc05x002a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 58; + public final static int checkLastLine = 58; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc05x002a obj = new tc05x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); // brkpLineNumber // checkLastLine +// fieldToCheck = CHANGED_VALUE; + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001.java new file mode 100644 index 00000000000..8bb869b9ed7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC6
    + * Description: Before point of execution, same method - stepping
    + * Steps: 1.Set breakpoint at line 24 (call to b()
    + * from a())
    + * 2.Debug Main
    + * 3.Insert as line before point of
    + * execution: System.err.println("foo");
    + * 4.Smart Swap
    + * 5.Set Smart PopFrame to beginging of
    + * method a()
    + * 6.F7 to step into
    + * X. Stops on println
    + * 7.F7
    + * X. Prints "foo" and stops on call to b()
    + * 8.F7
    + * X. Steps into b()
    + * 9.Resume
    + * X. Prints numbers
    + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 39th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, pops frames,creates StepRequest + * and resumes debugee. + * When the location of the current StepEvent is in method_B, + * created StepRequest is disabled. The test checks up location of every + * step event and that new code becomes actual. + */ + +public class tc06x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc06x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private static final String firstMethodName = "method_A"; + private static final String lastMethodName = "method_B"; + + private int eventCount; + private int expectedEventCount = 4; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc06x001 thisTest = new tc06x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc06x001a.brkpMethodName, + tc06x001a.brkpLineNumber); + + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + display("redefining..."); + redefineDebugee(); + popFrames(((BreakpointEvent )event).thread()); + createStepRequest(((LocatableEvent )event).thread()); + debugee.resume(); + + } else if (event instanceof StepEvent) { + display("\n event ===>>> " + event); + hitStep((StepEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private void popFrames(ThreadReference thread) { + display("\npop frames..."); + try { + StackFrame frame = thread.frame(0); + Method mthd = frame.location().method(); + do { + thread.popFrames(frame); + display(mthd.name() + " is resetted"); + frame = thread.frame(0); + mthd = frame.location().method(); + } while (mthd.isObsolete()); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + display(""); + } + + private StepRequest createStepRequest(ThreadReference thread) { + EventRequestManager evm = debugee.getEventRequestManager(); + StepRequest request = evm.createStepRequest(thread, + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + request.enable(); + return request; + } + + private void hitBreakpoint(BreakpointEvent event) { + locationInfo(event); + if (event.location().lineNumber() != tc06x001a.checkLastLine) { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc06x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } + display(""); + } + + private void hitStep(StepEvent event) { + locationInfo(event); + String methodName = event.location().method().name(); + StepRequest request = (StepRequest )event.request(); + + switch (eventCount) { + case 2: + checkLocMethod(methodName, firstMethodName); + break; + case 3: + Field fld = debugeeClass.fieldByName(tc06x001a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() != tc06x001a.CHANGED_VALUE) { + complain("Unexpected: new code is not actual"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: Inserted line has worked"); + } + break; + case 4: + checkLocMethod(methodName, lastMethodName); + request.disable(); + break; + default: + complain("Unexpected event" + event); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + private void checkLocMethod(String currentMethodName, String expectedMethodName) { + if (currentMethodName.compareTo(expectedMethodName) != 0) { + complain("Unexpected event location at \"" + currentMethodName + "\""); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected event location at \"" + currentMethodName + "\""); + } + } + + private void locationInfo(LocatableEvent event) { + eventCount++; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + } catch (AbsentInformationException e) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/TestDescription.java new file mode 100644 index 00000000000..4c5dd5a114a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc06x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC6 + * Description: Before point of execution, same method - stepping + * Steps: 1.Set breakpoint at line 24 (call to b() + * from a()) + * 2.Debug Main + * 3.Insert as line before point of + * execution: System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.F7 to step into + * X. Stops on println + * 7.F7 + * X. Prints "foo" and stops on call to b() + * 8.F7 + * X. Steps into b() + * 9.Resume + * X. Prints numbers + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 39th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, pops frames, creates StepRequest and + * resumes debugee. + * When the location of the current StepEvent is in method_B, created + * StepRequest is disabled. + * The test checks up location of every step event and that new code + * becomes actual. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc06x001 + * nsk.jdi.BScenarios.hotswap.tc06x001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc06x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/newclass/tc06x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/newclass/tc06x001a.java new file mode 100644 index 00000000000..95303de89b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/newclass/tc06x001a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc06x001a is deugee's part of the tc06x001. + */ +public class tc06x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 58; + public final static int checkLastLine = 58; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc06x001a obj = new tc06x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + fieldToCheck = CHANGED_VALUE; // brkpLineNumber // checkLastLine +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inserted line + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001a.java new file mode 100644 index 00000000000..0b73833bd4d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc06x001a is deugee's part of the tc06x001. + */ +public class tc06x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 59; + public final static int checkLastLine = 59; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc06x001a obj = new tc06x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { +// fieldToCheck = CHANGED_VALUE; + method_B(); // brkpLineNumber // checkLastLine + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001.java new file mode 100644 index 00000000000..d8bfa5ab6b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001.java @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC7
    + * Description: After point of execution, different method - stepping
    + * Steps: 1.Set breakpoint at line 24 (call from a()
    + * to b())
    + * 2.Debug Main
    + * 3.Insert as first line in b():
    + * System.err.println("foo");
    + * 4.Smart Swap
    + * 5.F7 to step into
    + * X. Steps into b()
    + * 6.F7 to step into
    + * X. Prints "foo"
    + * 7.F7 to step into
    + * X. Steps on to line that prints "1"
    + *
    + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at the 38th + * line (method method_A). After the breakpoint is reached, + * debugger redefines debugee inserting first line into method_B, creates + * StepRequest and resumes debugee. When the location of the + * current StepEvent is in method_C, created + * StepRequest is disabled. + * The test checks up location of every step event and that new code + * becomes actual. + */ + +public class tc07x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc07x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private static final String firstMethodName = "method_B"; + private static final String lastMethodName = "method_C"; + + private int eventCount; + private int expectedEventCount = 4; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc07x001 thisTest = new tc07x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc07x001a.brkpMethodName, + tc07x001a.brkpLineNumber); + + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + display("redefining..."); + redefineDebugee(); + createStepRequest(((LocatableEvent )event).thread()); + debugee.resume(); + + } else if (event instanceof StepEvent) { + display("\n event ===>>> " + event); + hitStep((StepEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private StepRequest createStepRequest(ThreadReference thread) { + EventRequestManager evm = debugee.getEventRequestManager(); + StepRequest request = evm.createStepRequest(thread, + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + request.enable(); + return request; + } + + private void hitBreakpoint(BreakpointEvent event) { + locationInfo(event); + if (event.location().lineNumber() != tc07x001a.checkLastLine) { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc07x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } + display(""); + } + + private void hitStep(StepEvent event) { + locationInfo(event); + String methodName = event.location().method().name(); + StepRequest request = (StepRequest )event.request(); + if (methodName.compareTo(lastMethodName) == 0) { + request.disable(); + } + switch (eventCount) { + case 2: + checkLocMethod(methodName, firstMethodName); + break; + case 3: + checkLocMethod(methodName, firstMethodName); + Field fld = debugeeClass.fieldByName(tc07x001a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() != tc07x001a.CHANGED_VALUE) { + complain("Unexpected: new code is not actual"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: Inserted line has worked"); + } + break; + case 4: + checkLocMethod(methodName, lastMethodName); + break; + default: + complain("Unexpected event" + event); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + private void checkLocMethod(String currentMethodName, String expectedMethodName) { + if (currentMethodName.compareTo(expectedMethodName) != 0) { + complain("Unexpected event location at \"" + currentMethodName + "\""); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected event location at \"" + currentMethodName + "\""); + } + } + + private void locationInfo(LocatableEvent event) { + eventCount++; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + } catch (AbsentInformationException e) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/TestDescription.java new file mode 100644 index 00000000000..39dd08175c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/TestDescription.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc07x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC7 + * Description: After point of execution, different method - stepping + * Steps: 1.Set breakpoint at line 24 (call from a() + * to b()) + * 2.Debug Main + * 3.Insert as first line in b(): + * System.err.println("foo"); + * 4.Smart Swap + * 5.F7 to step into + * X. Steps into b() + * 6.F7 to step into + * X. Prints "foo" + * 7.F7 to step into + * X. Steps on to line that prints "1" + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee inserting + * first line into method_B, creates StepRequest and resumes debugee. + * When the location of the current StepEvent is in method_C, created + * StepRequest is disabled. + * The test checks up location of every step event and that new code + * becomes actual. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc07x001 + * nsk.jdi.BScenarios.hotswap.tc07x001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc07x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/newclass/tc07x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/newclass/tc07x001a.java new file mode 100644 index 00000000000..0db7cda6633 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001/newclass/tc07x001a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc07x001a is deugee's part of the tc07x001. + */ +public class tc07x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 57; + public final static int checkLastLine = 57; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc07x001a obj = new tc07x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { // brkpLineNumber // checkLastLine + method_B(); + } + + public void method_B() { + fieldToCheck = CHANGED_VALUE; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inserted line + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001a.java new file mode 100644 index 00000000000..9a5f1ca78be --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc07x001a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc07x001a is deugee's part of the tc07x001. + */ +public class tc07x001a { + + public final static String brkpMethodName = "method_A"; + public final static int brkpLineNumber = 58; + public final static int checkLastLine = 58; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc07x001a obj = new tc07x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); // brkpLineNumber // checkLastLine + } + + public void method_B() { +// fieldToCheck = CHANGED_VALUE; + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001.java new file mode 100644 index 00000000000..9cbd96a4de2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001.java @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC8
    + * Description: Before point of execution, different method - stepping
    + * Steps: 1.Set breakpoint at line 30 (call to c()
    + * from b())
    + * 2.Debug Main
    + * 3.Insert as first line in a():
    + * System.err.println("foo");
    + * 4.Smart Swap
    + * 5.Set Smart PopFrame to beginging of
    + * method a()
    + * 6.F7 to step into
    + * X. Steps into a()
    + * 7.F7 to step into
    + * X. Prints "foo"
    + *
    + * The description was drown up according to steps under JBuilder.
    + *
    + * Of course, the test has own line numbers and method/class names and
    + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, pops frame, creates StepRequest + * and resumes debugee. When the second StepEvent is reached, created + * StepRequest is disabled. + */ + +public class tc08x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc08x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private static final String firstMethodName = "method_A"; + + private int eventCount; + private int expectedEventCount = 3; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc08x001 thisTest = new tc08x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + debugee.setBreakpoint(debugeeClass, + tc08x001a.brkpMethodName, + tc08x001a.brkpLineNumber); + + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + display("redefining..."); + redefineDebugee(); + popFrames(((BreakpointEvent )event).thread()); + createStepRequest(((LocatableEvent )event).thread()); + debugee.resume(); + + } else if (event instanceof StepEvent) { + display("\n event ===>>> " + event); + hitStep((StepEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private void popFrames(ThreadReference thread) { + display("\npop frames..."); + try { + StackFrame frame = thread.frame(0); + Method mthd = frame.location().method(); + do { + thread.popFrames(frame); + display(mthd.name() + " is resetted"); + frame = thread.frame(0); + mthd = frame.location().method(); + } while (mthd.isObsolete()); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + display(""); + } + + private StepRequest createStepRequest(ThreadReference thread) { + EventRequestManager evm = debugee.getEventRequestManager(); + StepRequest request = evm.createStepRequest(thread, + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + request.enable(); + return request; + } + + private void hitBreakpoint(BreakpointEvent event) { + locationInfo(event); + if (event.location().lineNumber() != tc08x001a.checkLastLine) { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc08x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } + display(""); + } + + private void hitStep(StepEvent event) { + locationInfo(event); + String methodName = event.location().method().name(); + StepRequest request = (StepRequest )event.request(); + + switch (eventCount) { + case 2: + checkLocMethod(methodName, firstMethodName); + break; + case 3: + checkLocMethod(methodName, firstMethodName); + Field fld = debugeeClass.fieldByName(tc08x001a.fieldToCheckName); + Value val = debugeeClass.getValue(fld); + if (((IntegerValue )val).value() != tc08x001a.CHANGED_VALUE) { + complain("Unexpected: new code is not actual"); + complain("Unexpected value of checked field: " + + val); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected: Inserted line has worked"); + } + request.disable(); + break; + default: + complain("Unexpected event" + event); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + private void checkLocMethod(String currentMethodName, String expectedMethodName) { + if (currentMethodName.compareTo(expectedMethodName) != 0) { + complain("Unexpected event location at \"" + currentMethodName + "\""); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected event location at \"" + currentMethodName + "\""); + } + } + + private void locationInfo(LocatableEvent event) { + eventCount++; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + } catch (AbsentInformationException e) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/TestDescription.java new file mode 100644 index 00000000000..2b4c06804f8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc08x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC8 + * Description: Before point of execution, different method - stepping + * Steps: 1.Set breakpoint at line 30 (call to c() + * from b()) + * 2.Debug Main + * 3.Insert as first line in a(): + * System.err.println("foo"); + * 4.Smart Swap + * 5.Set Smart PopFrame to beginging of + * method a() + * 6.F7 to step into + * X. Steps into a() + * 7.F7 to step into + * X. Prints "foo" + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 38th line (method method_A). + * After the breakpoint is reached, debugger redefines debugee adding + * a new line into method_A, pops frame, creates StepRequest and + * resumes debugee. When the second StepEvent is reached, created + * StepRequest is disabled. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc08x001 + * nsk.jdi.BScenarios.hotswap.tc08x001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc08x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/newclass/tc08x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/newclass/tc08x001a.java new file mode 100644 index 00000000000..abe27f4f7d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/newclass/tc08x001a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc08x001a is deugee's part of the tc08x001. + */ +public class tc08x001a { + + public final static String brkpMethodName = "method_B"; + public final static int brkpLineNumber = 62; + public final static int checkLastLine = 62; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc08x001a obj = new tc08x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + fieldToCheck = CHANGED_VALUE; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inserted line + method_B(); + } + // brkpLineNumber // checkLastLine + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001a.java new file mode 100644 index 00000000000..285f0812a84 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc08x001a is deugee's part of the tc08x001. + */ +public class tc08x001a { + + public final static String brkpMethodName = "method_B"; + public final static int brkpLineNumber = 63; + public final static int checkLastLine = 63; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc08x001a obj = new tc08x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { +// fieldToCheck = CHANGED_VALUE; + method_B(); + } + + public void method_B() { + method_C(); // brkpLineNumber // checkLastLine + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001.java new file mode 100644 index 00000000000..283d50bcce4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC9
    + * Description: Breakpoints updated correctly
    + * Steps: 1.Set breakpoint at lines 36 and 39
    + * (printing 1 and 4)
    + * 2.Debug Main
    + * X. Stops on line 36
    + * 3.Delete line 37
    + * 4.Smart Swap
    + * X. Breakpoints still set and valid at 36
    + * and 38
    + * 5.Resume
    + * X. Stops on line 38
    + *
    + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoints at + * the 47th and 49th line (method method_C). + * After the first breakpoint is reached, debugger redefines debugee + * deleting 48th line and resumes debugee. No breakpoints are + * expected anymore. + */ + +public class tc09x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc09x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int eventCount; + private int expectedEventCount = 1; + private ReferenceType debugeeClass; + private BreakpointRequest brkpRequest1 = null, + brkpRequest2 = null; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc09x001 thisTest = new tc09x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + + brkpRequest1 = debugee.setBreakpoint(debugeeClass, + tc09x001a.brkpMethodName, + tc09x001a.brkpLineNumber1); + + brkpRequest2 = debugee.setBreakpoint(debugeeClass, + tc09x001a.brkpMethodName, + tc09x001a.brkpLineNumber2); + + breakpointInfo(brkpRequest1); + breakpointInfo(brkpRequest2); + + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + if (eventCount == 1) { + display("redefining..."); + redefineDebugee(); + breakpointInfo(brkpRequest1); + breakpointInfo(brkpRequest2); + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private void hitBreakpoint(BreakpointEvent event) { + eventInfo(event); + if (event.location().lineNumber() == tc09x001a.checkLastLine && + eventCount == 1) { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } else { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc09x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + private void eventInfo(LocatableEvent event) { + eventCount++; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + locationInfo(event); + } + + private void breakpointInfo(BreakpointRequest request) { + display("breakpoint info: "); + display("\tis enabled - " + request.isEnabled()); + locationInfo(request); + } + + private void locationInfo(Locatable loc) { + try { + display("\tsource\t- " + loc.location().sourceName()); + display("\tmethod\t- " + loc.location().method().name()); + display("\tline\t- " + loc.location().lineNumber()); + } catch (AbsentInformationException e) { + display("***information is not available***"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/TestDescription.java new file mode 100644 index 00000000000..98b85f82b92 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc09x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC9 + * Description: Breakpoints updated correctly + * Steps: 1.Set breakpoint at lines 36 and 39 + * (printing 1 and 4) + * 2.Debug Main + * X. Stops on line 36 + * 3.Delete line 37 + * 4.Smart Swap + * X. Breakpoints still set and valid at 36 + * and 38 + * 5.Resume + * X. Stops on line 38 + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoints at + * the 47th and 49th line (method method_C). + * After the first breakpoint is reached, debugger redefines debugee + * deleting 48th line and resumes debugee. No breakpoints are + * expected anymore. + * COMMENTS: + * Last step from scenarion description (stopping on line 38) is wrong + * of because JVMDI spec (Redefine Classes ) says:"...All breakpoints + * in the class are cleared." + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc09x001 + * nsk.jdi.BScenarios.hotswap.tc09x001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc09x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/newclass/tc09x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/newclass/tc09x001a.java new file mode 100644 index 00000000000..84094a7d107 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001/newclass/tc09x001a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc09x001a is deugee's part of the tc09x001. + */ +public class tc09x001a { + + public final static String brkpMethodName = "method_C"; + public final static int brkpLineNumber1 = 66; + public final static int brkpLineNumber2 = 69; + public final static int checkLastLine = 66; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc09x001a obj = new tc09x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { // brkpLineNumber1 // checkLastLine + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); // brkpLineNumber2 + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001a.java new file mode 100644 index 00000000000..9611a07a0cd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x001a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc09x001a is deugee's part of the tc09x001. + */ +public class tc09x001a { + + public final static String brkpMethodName = "method_C"; + public final static int brkpLineNumber1 = 67; + public final static int brkpLineNumber2 = 70; + public final static int checkLastLine = 67; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc09x001a obj = new tc09x001a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); // brkpLineNumber1 // checkLastLine + System.err.println("method_C:: line 2"); // this line will be removed + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); // brkpLineNumber2 + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002.java new file mode 100644 index 00000000000..5c6308c4a69 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002.java @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC9
    + * Description: Breakpoints updated correctly
    + * Steps: 1.Set breakpoint at lines 36 and 39
    + * (printing 1 and 4)
    + * 2.Debug Main
    + * X. Stops on line 36
    + * 3.Delete line 37
    + * 4.Smart Swap
    + * X. Breakpoints still set and valid at 36
    + * and 38
    + * 5.Resume
    + * X. Stops on line 38
    + *
    + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoints at + * the 47th and 49th line (method method_C). + * After the first breakpoint is reached, debugger redefines debugee + * deleting 48th line and attempts to set another breakpoint at 49th line. + * Because line number info is not available after redefining, it is + * expected IndexOutOfBoundsException will be thrown. + */ + +public class tc09x002 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc09x002"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int eventCount; + private int expectedEventCount = 1; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc09x002 thisTest = new tc09x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + BreakpointRequest brkpRequest1, brkpRequest2; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + + brkpRequest1 = debugee.setBreakpoint(debugeeClass, + tc09x002a.brkpMethodName, + tc09x002a.brkpLineNumber1); + + brkpRequest2 = debugee.setBreakpoint(debugeeClass, + tc09x002a.brkpMethodName, + tc09x002a.brkpLineNumber2); + + breakpointInfo(brkpRequest1); + breakpointInfo(brkpRequest2); + + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + + if (eventCount == 1) { + display("redefining..."); + redefineDebugee(); + Method method = null; + try { + method = ((BreakpointEvent )event).thread().frame(0).location().method(); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + display("\nsetting breakpoint at the redefined method..."); + try { + Location location = debugee.getLineLocation(method, tc09x002a.brkpLineNumber2); + if (location != null) { + brkpRequest2 = evm.createBreakpointRequest(location); + if (method.isObsolete()) { + complain("Locations of the redefined method " + + "should be not available: " + location); + complain("BreakpointRequest for not available location " + + "should be created: " + brkpRequest2); + exitStatus = Consts.TEST_FAILED; + } else { + display("No location found for unavailable line after class redefinition"); + } + } + } catch (Exception e) { + display("Unspecified exception caught while setting breakpoint " + + "to unavailable line after class redefinition:\n\t" + e); + exitStatus = Consts.TEST_FAILED; + } + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private void hitBreakpoint(BreakpointEvent event) { + eventInfo(event); + if (event.location().lineNumber() == tc09x002a.checkLastLine && + eventCount == 1) { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } else { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc09x002a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + private void eventInfo(LocatableEvent event) { + eventCount++; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + locationInfo(event); + } + + private void breakpointInfo(BreakpointRequest request) { + display("breakpoint info: "); + display("\tis enabled - " + request.isEnabled()); + locationInfo(request); + } + + private void locationInfo(Locatable loc) { + try { + display("\tsource\t- " + loc.location().sourceName()); + display("\tmethod\t- " + loc.location().method().name()); + display("\tline\t- " + loc.location().lineNumber()); + } catch (AbsentInformationException e) { + display("***information is not available***"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/TestDescription.java new file mode 100644 index 00000000000..b4e5cd8e7ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc09x002. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC9 + * Description: Breakpoints updated correctly + * Steps: 1.Set breakpoint at lines 36 and 39 + * (printing 1 and 4) + * 2.Debug Main + * X. Stops on line 36 + * 3.Delete line 37 + * 4.Smart Swap + * X. Breakpoints still set and valid at 36 + * and 38 + * 5.Resume + * X. Stops on line 38 + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoints at + * the 47th and 49th line (method method_C). + * After the first breakpoint is reached, debugger redefines debugee + * deleting 48th line and attempts to set another breakpoint at 49th line. + * Because line number info is not available after redefining, it is + * expected IndexOutOfBoundsException will be thrown. + * COMMENTS: + * Last step from scenarion description (stopping on line 38) is wrong + * of because JVMDI spec (Redefine Classes ) says:"...All breakpoints + * in the class are cleared." + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc09x002 + * nsk.jdi.BScenarios.hotswap.tc09x002a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc09x002 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/newclass/tc09x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/newclass/tc09x002a.java new file mode 100644 index 00000000000..ee1c6576a02 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002/newclass/tc09x002a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc09x002a is deugee's part of the tc09x002. + */ +public class tc09x002a { + + public final static String brkpMethodName = "method_C"; + public final static int brkpLineNumber1 = 66; + public final static int brkpLineNumber2 = 69; + public final static int checkLastLine = 66; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc09x002a obj = new tc09x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { // brkpLineNumber1 // checkLastLine + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); // brkpLineNumber2 + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002a.java new file mode 100644 index 00000000000..3da0e071f83 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc09x002a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc09x002a is deugee's part of the tc09x002. + */ +public class tc09x002a { + + public final static String brkpMethodName = "method_C"; + public final static int brkpLineNumber1 = 67; + public final static int brkpLineNumber2 = 70; + public final static int checkLastLine = 67; + public final static String fieldToCheckName = "fieldToCheck"; + public final static int INITIAL_VALUE = 0; + public final static int CHANGED_VALUE = 1; + + private static Log log; + private static int fieldToCheck = INITIAL_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc09x002a obj = new tc09x002a(); + obj.method_A(); + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); // brkpLineNumber1 // checkLastLine + System.err.println("method_C:: line 2"); // this line will be removed + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); // brkpLineNumber2 + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001.java new file mode 100644 index 00000000000..43f4b07719d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC10
    + * Description: Changing data type
    + * Steps: 1.Set breakpoint on line 20
    + * 2.Debug Main
    + * X. Stops on line 20
    + * 3.Change line 16 to boolean i = true;
    + * 4.Smart Swap
    + * 5.Resume
    + * X. Prints "true" as last line of output
    + *
    + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 35th line (method main). + * After the breakpoint is reached, debugger redefines debugee changing + * type of local variable and resumes debugee. + * After resuming debugee sends value of the variable via IOPipe channel, + * debugger reads this value and compares it with expected the one. + * In this case expected value is the value before redefinition. + */ + +public class tc10x001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc10x001"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int eventCount; + private int expectedEventCount = 1; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc10x001 thisTest = new tc10x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.createIOPipe(); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + BreakpointRequest brkpRequest; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + + brkpRequest = debugee.setBreakpoint(debugeeClass, + tc10x001a.brkpMethodName, + tc10x001a.brkpLineNumber); + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + + display("redefining..."); + redefineDebugee(); + + Receiver recv = new Receiver(); + recv.start(); + + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private void hitBreakpoint(BreakpointEvent event) { + eventInfo(event); + if (event.location().lineNumber() == tc10x001a.checkLastLine && + eventCount == 1) { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } else { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc10x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + private void eventInfo(LocatableEvent event) { + eventCount++; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + locationInfo(event); + } + + private void locationInfo(Locatable loc) { + try { + display("\tsource\t- " + loc.location().sourceName()); + display("\tmethod\t- " + loc.location().method().name()); + display("\tline\t- " + loc.location().lineNumber()); + } catch (AbsentInformationException e) { + display("***information is not available***"); + } + } + + class Receiver extends Thread { + public void run() { + try { + String tmp = debugee.receiveSignal(); + display("received value:\t" + tmp); + int actualValue = Integer.parseInt(tmp.substring(1)); + if (actualValue != tc10x001a.INITIAL_INT_VALUE) { + complain("Unexpected value of local variable - " + actualValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("!!!Expected value of local variable - " + actualValue); + } + } catch (Throwable e) { + complain(UNEXPECTED_STRING + e); + exitStatus = Consts.TEST_FAILED; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/TestDescription.java new file mode 100644 index 00000000000..dfe0d342586 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/TestDescription.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc10x001. + * VM Testbase keywords: [quick, jpda, jdi, redefine, quarantine] + * VM Testbase comments: JDK-8013728 + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC10 + * Description: Changing data type + * Steps: 1.Set breakpoint on line 20 + * 2.Debug Main + * X. Stops on line 20 + * 3.Change line 16 to boolean i = true; + * 4.Smart Swap + * 5.Resume + * X. Prints "true" as last line of output + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 35th line (method main). + * After the breakpoint is reached, debugger redefines debugee changing + * type of local variable and resumes debugee. + * After resuming debugee sends value of the variable via IOPipe channel, + * debugger reads this value and compares it with expected the one. + * In this case expected value is the value before redefinition. + * COMMENTS: + * Step 5 of Borland's scenario is wrong due to redefineClasses spec says: + * "The redefined method will be used on new invokes. If resetting these + * frames is desired, use ThreadReference.popFrames() with + * Method.isObsolete()." + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc10x001 + * nsk.jdi.BScenarios.hotswap.tc10x001a + * + * @comment make sure tc10x001a is compiled with full debug info + * @clean nsk.jdi.BScenarios.hotswap.tc10x001a + * @compile -g:lines,source,vars ../tc10x001a.java + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc10x001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/newclass/tc10x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/newclass/tc10x001a.java new file mode 100644 index 00000000000..ad2dabd468a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001/newclass/tc10x001a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc10x001a is deugee's part of the tc10x001. + */ +public class tc10x001a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 54; + public final static int checkLastLine = 54; + public final static int INITIAL_INT_VALUE = 42; + public final static boolean INITIAL_BOOL_VALUE = true; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + boolean i = INITIAL_BOOL_VALUE; +// ^^^^^^^ has been changed + tc10x001a obj = new tc10x001a(); + obj.method_A(); + // brkpLineNumber // checkLastLine + System.err.println("i = " + i); + pipe.println("@" + i); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001a.java new file mode 100644 index 00000000000..e5fe3e4e571 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x001a.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc10x001a is deugee's part of the tc10x001. + */ +public class tc10x001a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 55; + public final static int checkLastLine = 55; + public final static int INITIAL_INT_VALUE = 42; + public final static boolean INITIAL_BOOL_VALUE = true; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + int i = INITIAL_INT_VALUE; +// ^^^ will be changed + tc10x001a obj = new tc10x001a(); + obj.method_A(); + + System.err.println("i = " + i); // brkpLineNumber // checkLastLine + pipe.println("@" + i); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public void method_A() { + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002.java new file mode 100644 index 00000000000..252d8404fe1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 3 - Hot Swap
    + * Test case: TC10
    + * Description: Changing data type
    + * Steps: 1.Set breakpoint on line 20
    + * 2.Debug Main
    + * X. Stops on line 20
    + * 3.Change line 16 to boolean i = true;
    + * 4.Smart Swap
    + * 5.Resume
    + * X. Prints "true" as last line of output
    + *
    + * The description was drown up according to steps under JBuilder. + * + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 40th line (method runIt). + * Note: the runIt method was added into the test, to allow invoking + * ThreadReference.popFrame(). Current frame can not be reset because of + * there is no previous frame. + * After the breakpoint is reached, debugger redefines debugee changing type of + * local variable, pops current frame, sets a new breakpoint at 37th line and + * resumes debugee. + * When the second breakpoint hits, debugger requests value of the local + * variable i and compares got value with expected value. + * In this case expected value is the new value after redefinition. + */ + +public class tc10x002 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.BScenarios.hotswap."; + private final static String debuggerName = prefix + "tc10x002"; + private final static String debugeeName = debuggerName + "a"; + + private final static String newClassFile = "newclass" + File.separator + + debugeeName.replace('.',File.separatorChar) + + ".class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int eventCount; + private int expectedEventCount = 2; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc10x002 thisTest = new tc10x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.createIOPipe(); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + BreakpointRequest brkpRequest; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\n event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\n event ===>>> " + event); + debugeeClass = ((ClassPrepareEvent )event).referenceType(); + display("Tested class\t:" + debugeeClass.name()); + + brkpRequest = debugee.setBreakpoint(debugeeClass, + tc10x002a.brkpMethodName, + tc10x002a.brkpLineNumber1); + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\n event ===>>> " + event); + BreakpointEvent brkpEvent = (BreakpointEvent )event; + + switch (eventCount) { + case 0: + hitBreakpoint(brkpEvent, tc10x002a.checkLastLine1); + display("redefining..."); + redefineDebugee(); + + popFrames(brkpEvent.thread()); + + brkpRequest = debugee.setBreakpoint(debugeeClass, + tc10x002a.brkpMethodName, + tc10x002a.brkpLineNumber2); + break; + case 1: + Value val = null; + hitBreakpoint(brkpEvent, tc10x002a.checkLastLine2); + try { + StackFrame frame = brkpEvent.thread().frame(0); + LocalVariable var = frame.visibleVariableByName("i"); + display("local variable:\t" + var); + val = frame.getValue(var); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + display("\nValue of local variable:\t" + val); + if (((PrimitiveValue)val).booleanValue() == + tc10x002a.INITIAL_BOOL_VALUE) { + display("!!!Expected value of local variable!!!\n"); + } else { + complain("Unexpected value of local variable.\n"); + exitStatus = Consts.TEST_FAILED; + } + break; + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount != expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private void popFrames(ThreadReference thread) { + display("\npop frames..."); + try { + StackFrame frame = thread.frame(0); + Method mthd = frame.location().method(); + do { + thread.popFrames(frame); + display(mthd.name() + " is resetted"); + frame = thread.frame(0); + mthd = frame.location().method(); + } while (mthd.isObsolete()); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + display(""); + } + + private void hitBreakpoint(BreakpointEvent event, int expLine) { + eventInfo(event); + if (event.location().lineNumber() == expLine) { + display("!!!BreakpointEvent steps to the expected line " + + event.location().lineNumber() + "!!!"); + } else { + complain("BreakpointEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + expLine); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + private void eventInfo(LocatableEvent event) { + eventCount++; + display("event info: #" + eventCount); + display("\tthread\t- " + event.thread().name()); + locationInfo(event); + } + + private void breakpointInfo(BreakpointRequest request) { + display("breakpoint info: "); + display("\tis enabled - " + request.isEnabled()); + locationInfo(request); + } + + private void locationInfo(Locatable loc) { + try { + display("\tsource\t- " + loc.location().sourceName()); + display("\tmethod\t- " + loc.location().method().name()); + display("\tline\t- " + loc.location().lineNumber()); + } catch (AbsentInformationException e) { + display("***information is not available***"); + } + } + + private MethodExitRequest createMethodExitRequest(ReferenceType refType) { + EventRequestManager evm = debugee.getEventRequestManager(); + MethodExitRequest request = evm.createMethodExitRequest(); + request.addClassFilter(refType); + request.enable(); + return request; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/TestDescription.java new file mode 100644 index 00000000000..77b32746b3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/TestDescription.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/hotswap/tc10x002. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 3 - Hot Swap + * Test case: TC10 + * Description: Changing data type + * Steps: 1.Set breakpoint on line 20 + * 2.Debug Main + * X. Stops on line 20 + * 3.Change line 16 to boolean i = true; + * 4.Smart Swap + * 5.Resume + * X. Prints "true" as last line of output + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 40th line (method runIt). + * Note: the runIt method was added into the test, to allow invoking + * ThreadReference.popFrame(). Current frame can not be reset because of + * there is no previous frame. + * After the breakpoint is reached, debugger redefines debugee changing + * type of local variable, pops current frame, sets a new breakpoint at + * 37th line and resumes debugee. + * When the second breakpoint hits, debugger requests value of the local + * variable "i" and compares got value with expected value. + * In this case expected value is the new value after redefinition. + * COMMENTS: + * Step 5 of Borland's scenario is wrong due to redefineClasses spec says: + * "The redefined method will be used on new invokes. If resetting these + * frames is desired, use ThreadReference.popFrames() with + * Method.isObsolete()." + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.hotswap.tc10x002 + * nsk.jdi.BScenarios.hotswap.tc10x002a + * + * @comment make sure tc10x002a is compiled with full debug info + * @clean nsk.jdi.BScenarios.hotswap.tc10x002a + * @compile -g:lines,source,vars ../tc10x002a.java + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.hotswap.tc10x002 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/newclass/tc10x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/newclass/tc10x002a.java new file mode 100644 index 00000000000..a36162bbc4b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/newclass/tc10x002a.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc10x002a is deugee's part of the tc10x002. + */ +public class tc10x002a { + + public final static String brkpMethodName = "runIt"; + public final static int brkpLineNumber1 = 60; + public final static int brkpLineNumber2 = 57; + public final static int checkLastLine1 = 60; + public final static int checkLastLine2 = 57; + public final static int INITIAL_INT_VALUE = 42; + public final static boolean INITIAL_BOOL_VALUE = true; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + runIt(); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void runIt() { + boolean i = INITIAL_BOOL_VALUE; +// ^^^^^^^ ^^^^^^^^^^^^^^^^^^ redefined line // brkpLineNumber2 // checkLastLine2 + tc10x002a obj = new tc10x002a(); + obj.method_A(); + // brkpLineNumber1 // checkLastLine1 + System.err.println("i = " + i); + } + + public void method_A() { + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002a.java new file mode 100644 index 00000000000..0827661474f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002a.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.hotswap; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc10x002a is deugee's part of the tc10x002. + */ +public class tc10x002a { + + public final static String brkpMethodName = "runIt"; + public final static int brkpLineNumber1 = 61; + public final static int brkpLineNumber2 = 58; + public final static int checkLastLine1 = 61; + public final static int checkLastLine2 = 58; + public final static int INITIAL_INT_VALUE = 42; + public final static boolean INITIAL_BOOL_VALUE = true; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + runIt(); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void runIt() { + int i = INITIAL_INT_VALUE; +// ^^^ ^^^^^^^^^^^^^^^^^ will be redefined + tc10x002a obj = new tc10x002a(); // brkpLineNumber2 // checkLastLine2 + obj.method_A(); + + System.err.println("i = " + i); // brkpLineNumber1 // checkLastLine1 + } + + public void method_A() { + method_B(); + } + + public void method_B() { + method_C(); + } + + public void method_C() { + System.err.println("method_C:: line 1"); + System.err.println("method_C:: line 2"); + System.err.println("method_C:: line 3"); + System.err.println("method_C:: line 4"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001.java new file mode 100644 index 00000000000..ec720d829ed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001.java @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * TC1
    + * Description: Line breakpoint & step
    + * Steps: 1.Set breakpoint on line 32
    + * 2.Debug Main
    + * X. Stops on line 32
    + * 3.Run | Step over
    + * X. Steps to line 33
    + * + * When the test is starting debugee, debugger sets breakpoint at the 69th + * line (method "foo"). After the breakpoint is reached, debugger creates + * "step over" request and resumes debugee. For every hit event debugger + * checks line number of one's location. It should be 69th line for Breakpoint + * or 70th line for Step. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc01x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.multithrd."; + private final static String debuggerName = prefix + "tc01x001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int brkpEventCount = 0; + private static int stepEventCount = 0; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc01x001 thisTest = new tc01x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + display("Tested class\t:" + debugeeClass.name()); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + debugee.setBreakpoint(debugeeClass, + tc01x001a.brkpMethodName, + tc01x001a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal(SGL_PERFORM); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display(" event ===>>> " + event); + + if (event instanceof BreakpointEvent) { + display(" event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + debugee.resume(); + + } else if (event instanceof StepEvent) { + display(" event ===>>> " + event); + hitStepOver((StepEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + exit = exit || (brkpEventCount == tc01x001a.threadCount && + stepEventCount == tc01x001a.threadCount); + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (brkpEventCount < tc01x001a.threadCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + tc01x001a.threadCount + + " MethodBreakpoint events, but " + + brkpEventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitBreakpoint(BreakpointEvent event) { + EventRequestManager evm = debugee.getEventRequestManager(); + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (event.location().lineNumber() != tc01x001a.checkBrkpLine) { + complain("BreakpointEvent stops on line " + event.location().lineNumber() + + ", expected line number is " + tc01x001a.checkBrkpLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("BreakpointEvent stops on the expected line " + + event.location().lineNumber()); + } + + display(""); + StepRequest step = evm.createStepRequest(thrd, StepRequest.STEP_LINE, + StepRequest.STEP_OVER); + brkpEventCount++; + step.enable(); + } + + private void hitStepOver(StepEvent event) { + EventRequestManager evm = debugee.getEventRequestManager(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (event.location().lineNumber() != tc01x001a.checkStepLine) { + complain("StepEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + tc01x001a.checkStepLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("StepEvent steps to the expected line " + + event.location().lineNumber()); + } + display(""); + + evm.deleteEventRequest(event.request()); + stepEventCount++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001/TestDescription.java new file mode 100644 index 00000000000..366232f1517 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/multithrd/tc01x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC1 + * Description: Line breakpoint & step + * Steps: 1.Set breakpoint on line 32 + * 2.Debug Main + * X. Stops on line 32 + * 3.Run | Step over + * X. Steps to line 33 + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 69th line (method "foo"). + * After the breakpoint is reached, debugger creates "step over" request + * and resumes debugee. For every hit event debugger checks line number + * of one's location. It should be 69th line for Breakpoint or 70th line + * for Step. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * The testcase intermittently hangs under RightCross. It looks like a + * JBuilder bug. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.multithrd.tc01x001 + * nsk.jdi.BScenarios.multithrd.tc01x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.multithrd.tc01x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001a.java new file mode 100644 index 00000000000..154656c263e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc01x001a.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc01x001a is deugee's part of the tc01x001. + */ +public class tc01x001a { + + public final static String brkpMethodName = "bar"; + public final static int brkpLineNumber = 89; + + public final static int checkBrkpLine = 89; + public final static int checkStepLine = 90; + public final static int threadCount = 3; + private static Log log; + + Thready [] thrds = new Thready [threadCount]; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc01x001.SGL_READY); + + tc01x001a obj = null; + String instr; + do { + instr = pipe.readln(); + if (instr.equals(tc01x001.SGL_PERFORM)) { + obj = new tc01x001a(); + } else if (instr.equals(tc01x001.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + try { + for (int i = 0; i < obj.thrds.length; i++ ) { + obj.thrds[i].join(); + } + } catch (InterruptedException e) { + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + tc01x001a() { + for (int i = 0; i < thrds.length; i++ ) { + thrds[i] = new Thready("Thread-" + (i+1)); + thrds[i].start(); + } + } + + public static void foo(String caller) { + log.display(caller + "::foo is called"); + } + + public static void bar(String caller) { + log.display(caller + "::bar is called"); // brkpLineNumber // checkBrkpLine + log.display(caller + "::bar_step"); // checkStepLine + } + + static class Thready extends Thread { + Thready(String name) { + super(name); + } + + public void run() { + tc01x001a.foo(getName()); + tc01x001a.bar(getName()); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001.java new file mode 100644 index 00000000000..6803fd51629 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc02x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc02x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.multithrd."; + private final static String debuggerName = prefix + "tc02x001"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debugeeName + "Class1"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int brkpEventCount = 0; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc02x001 thisTest = new tc02x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + debugeeClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + MethodEntryRequest mthdReq = evm.createMethodEntryRequest(); + mthdReq.addClassFilter(testedClassName); + mthdReq.enable(); + + debugee.resume(); + debugee.sendSignal(SGL_PERFORM); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + + if (event instanceof MethodEntryEvent) { + hitClassBreakpoint((MethodEntryEvent )event); + display(" event ===>>> " + (brkpEventCount+1) + " MethodEntryEvent arrived"); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + exit = exit || (brkpEventCount == tc02x001a.threadCount); + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (brkpEventCount < tc02x001a.threadCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + tc02x001a.threadCount + + " MethodBreakpoint events, but " + + brkpEventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitClassBreakpoint(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (event.location().lineNumber() == tc02x001a.checkClassBrkpLine) { + display("ClassBreakpoint stops on the expected line " + + event.location().lineNumber() + " in method " + + event.method().name()); + } else { + complain("ClassBreakpoint stops on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line number is " + + tc02x001a.checkClassBrkpLine); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + + brkpEventCount++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001/TestDescription.java new file mode 100644 index 00000000000..ff0175af276 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/multithrd/tc02x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC2 + * Description: Class breakpoint + * Steps: 1.Add class breakpoint: singlethread.Class1 + * 2.Debug Main + * X. Stops on line 13 in Class1.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc02x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * The test synchronizes debugger and debugee executing via IOPipe channel. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * There are a doublness of the "class breakpoint" understanding. + * Here is that JBuilder help says: + * 1. "A class breakpoint causes the debugger to stop when any method + * from the specified class is called or when the specified class + * is instantiated." + * So, a class breakpoint is MethodEntryRequest with filtering + * the specified class. + * 2. "A class breakpoint causes the debugger to stop at the location + * when the specified class is loaded or when any method from the + * specified class is called." + * In this case, a class breakpoint is MethodEntryRequest and + * ClassPrepareRequest with filtering the specified class. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.multithrd.tc02x001 + * nsk.jdi.BScenarios.multithrd.tc02x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.multithrd.tc02x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001a.java new file mode 100644 index 00000000000..91a8cb1f08b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x001a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x001a is deugee's part of the tc02x001. + */ +public class tc02x001a { + + public final static int threadCount = 3; + static Log log; + + public final static int checkClassBrkpLine = 93; + Thready [] thrds = new Thready [threadCount]; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc02x001.SGL_READY); + + tc02x001a obj = null; + String instr; + do { + instr = pipe.readln(); + log.display("instr \"" + instr + "\""); + if (instr.equals(tc02x001.SGL_PERFORM)) { + obj = new tc02x001a(); + } else if (instr.equals(tc02x001.SGL_QUIT)) { + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + try { + for (int i = 0; i < obj.thrds.length; i++ ) { + obj.thrds[i].join(); + } + } catch (InterruptedException e) { + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + tc02x001a() { + for (int i = 0; i < thrds.length; i++ ) { + thrds[i] = new Thready("Thread-" + (i+1)); + thrds[i].start(); + } + } + + static class Thready extends Thread { + Thready(String name) { + super(name); + } + + public void run() { + log.display(getName() + ":: creating tc02x001aClass1"); + new tc02x001aClass1(getName()); + } + } +} + +class tc02x001aClass1 { + public tc02x001aClass1(String thrdName) { // checkClassBrkpLine + tc02x001a.log.display("tc02x001aClass1::constructor is called from" + + thrdName); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002.java new file mode 100644 index 00000000000..960ef8ed2ca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 80th or 82th lines, that are static initializer and + * constructor of tc02x001aClass1 class. Every thread must generate + * MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc02x002 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_LOAD = "load"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.multithrd."; + private final static String debuggerName = prefix + "tc02x002"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debugeeName + "Class1"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int eventCount = 0; + + private EventRequestManager evm = null; + private MethodEntryRequest mthdReq = null; + private volatile boolean exit = false; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + tc02x002 thisTest = new tc02x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + IOPipe pipe = debugee.createIOPipe(); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + evm = debugee.getEventRequestManager(); + + ClassPrepareRequest crq = evm.createClassPrepareRequest(); + crq.addClassFilter(testedClassName); + crq.enable(); + + // event handling thread + Thread eventHandler = new Thread() { + public void run() { + EventQueue eventQueue = debugee.VM().eventQueue(); + EventSet eventSet = null; + while (!exit) { + try { + eventSet = eventQueue.remove(1000); + } catch (InterruptedException e) { + new Failure("Event handling thread interrupted:\n\t" + e); + } + if (eventSet == null) { + continue; + } + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + + if (event instanceof ClassPrepareEvent) { + display(" event ===>>> " + event); + mthdReq = evm.createMethodEntryRequest(); + mthdReq.addClassFilter(testedClassName); + mthdReq.enable(); + debugee.resume(); + + } else if (event instanceof MethodEntryEvent) { + display(" event ===>>> " + (eventCount+1) + " MethodEntryEvent arrived"); + hitEvent((MethodEntryEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } else { + throw new Failure("Unexpected event:\n\t" + event); + } // if + exit = exit || (eventCount >= tc02x002a.threadCount + 1); + } // while + } // while + } // run() + }; // eventHadler + + display("Starting handling event"); + eventHandler.start(); + + debugee.resume(); + debugee.receiveExpectedSignal(SGL_READY); + + display("\nTEST BEGINS"); + display("==========="); + debugee.sendSignal(SGL_LOAD); + + display("Waiting for all events received"); + try { + eventHandler.join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Main thread interrupted while waiting for eventHandler:\n\t" + + e); + } finally { + crq.disable(); + mthdReq.disable(); + exit = true; + if (eventHandler.isAlive()) { + display("Interrupting event handling thread"); + eventHandler.interrupt(); + } + } + + if (eventCount < tc02x002a.threadCount) { + complain("expecting " + tc02x002a.threadCount + + " breakpoint events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + debugee.sendSignal(SGL_QUIT); + } + + private void hitEvent(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + if (event.location().lineNumber() == tc02x002a.checkClassBrkpLine1 || + event.location().lineNumber() == tc02x002a.checkClassBrkpLine2) { + display("MethodEntryEvent occurs on the expected line " + + event.location().lineNumber() + " in method " + + event.method().name()); + } else { + complain("MethodEntryEvent occurs on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line numbers are " + + tc02x002a.checkClassBrkpLine1 + ", " + + tc02x002a.checkClassBrkpLine2); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + + eventCount++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002/TestDescription.java new file mode 100644 index 00000000000..800fa741b18 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002/TestDescription.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/multithrd/tc02x002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC2 + * Description: Class breakpoint + * Steps: 1.Add class breakpoint: singlethread.Class1 + * 2.Debug Main + * X. Stops on line 13 in Class1.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates ClassPrepareRequest + * MethodEntryRequest with adding filter via class name. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 80th or 82th lines, that are static initializer + * and constructor of tc02x001aClass1 class. Every thread must generate + * MethodEntryEvent. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * There are a doublness of the "class breakpoint" understanding. + * Here is that JBuilder help says: + * 1. "A class breakpoint causes the debugger to stop when any method + * from the specified class is called or when the specified class + * is instantiated." + * So, a class breakpoint is MethodEntryRequest with filtering + * the specified class. + * 2. "A class breakpoint causes the debugger to stop at the location + * when the specified class is loaded or when any method from the + * specified class is called." + * In this case, a class breakpoint is MethodEntryRequest and + * ClassPrepareRequest with filtering the specified class. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test fixed according to test bug: + * 4804095 TEST_BUG: potential race condition with loading classes in JDI tests + * - launching debuggee by prepareDebugee() replaced with bindToDebugee() + * to exclude first IOPipe communication + * - making ClassPrepareRequest moved to begin (right after debuggee started) + * - making MethodEntryRequest moved to handling ClassPrepareEvent + * - handling events moved to a separate thread + * - removed extra IOPipe communication points to make algorithm more clear + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.multithrd.tc02x002 + * nsk.jdi.BScenarios.multithrd.tc02x002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.multithrd.tc02x002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002a.java new file mode 100644 index 00000000000..a0bf559387d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x002a.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x002a is deugee's part of the tc02x002. + */ +public class tc02x002a { + + public final static int threadCount = 3; + static Log log; + + public final static int checkClassBrkpLine1 = 96; + public final static int checkClassBrkpLine2 = 98; + Thready [] thrds = new Thready [threadCount]; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc02x002.SGL_READY); + + tc02x002a obj = null; + String instr; + do { + instr = pipe.readln(); + if (instr.equals(tc02x002.SGL_LOAD)) { + tc02x002aClass1.loadThis = true; + obj = new tc02x002a(); + } else if (instr.equals(tc02x002.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + try { + for (int i = 0; i < obj.thrds.length; i++ ) { + obj.thrds[i].join(); + } + } catch (InterruptedException e) { + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + tc02x002a() { + for (int i = 0; i < thrds.length; i++ ) { + thrds[i] = new Thready("Thread-" + (i+1)); + thrds[i].start(); + } + } + + static class Thready extends Thread { + Thready(String name) { + super(name); + } + + public void run() { + log.display(getName() + ":: creating tc02x002aClass1"); + new tc02x002aClass1(getName()); + } + } +} + +class tc02x002aClass1 { + + static boolean loadThis = false; // checkClassBrkpLine1 + + public tc02x002aClass1(String thrdName) { // checkClassBrkpLine2 + tc02x002a.log.display("tc02x002aClass1::constructor is called from" + + thrdName); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003.java new file mode 100644 index 00000000000..4fd48e21ff0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 80th or 82th lines, that are static initializer and + * constructor of tc02x001aClass1 class. Every thread must generate + * MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc02x003 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_LOAD = "load"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.multithrd."; + private final static String debuggerName = prefix + "tc02x003"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debugeeName + "Class1"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int eventCount = 0; + + private EventRequestManager evm = null; + private MethodEntryRequest mthdReq = null; + private volatile boolean exit = false; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + tc02x003 thisTest = new tc02x003(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + IOPipe pipe = debugee.createIOPipe(); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + evm = debugee.getEventRequestManager(); + + ClassPrepareRequest crq = evm.createClassPrepareRequest(); + crq.addClassFilter(testedClassName); + crq.enable(); + + // event handling thread + Thread eventHandler = new Thread() { + public void run() { + EventQueue eventQueue = debugee.VM().eventQueue(); + EventSet eventSet = null; + while (!exit) { + try { + eventSet = eventQueue.remove(1000); + } catch (InterruptedException e) { + new Failure("Event handling thread interrupted:\n\t" + e); + } + if (eventSet == null) { + continue; + } + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + + if (event instanceof ClassPrepareEvent) { + display(" event ===>>> " + event); + ClassPrepareEvent clsEvent = (ClassPrepareEvent )event; + hitEvent(clsEvent); + + mthdReq = evm.createMethodEntryRequest(); + ReferenceType testedClass = clsEvent.referenceType();; + mthdReq.addClassFilter(testedClass); + mthdReq.enable(); + + debugee.resume(); + + } else if (event instanceof MethodEntryEvent) { + display(" event ===>>> " + event); + hitEvent((MethodEntryEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } else { + throw new Failure("Unexpected event:\n\t" + event); + } // if + exit = exit || (eventCount >= tc02x003a.threadCount + 2); + } // while + } // while + } // run() + }; // eventHadler + + display("Starting handling event"); + eventHandler.start(); + + debugee.resume(); + debugee.receiveExpectedSignal(SGL_READY); + + display("\nTEST BEGINS"); + display("==========="); + debugee.sendSignal(SGL_LOAD); + + display("Waiting for all events received"); + try { + eventHandler.join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Main thread interrupted while waiting for eventHandler:\n\t" + + e); + } finally { + crq.disable(); + mthdReq.disable(); + exit = true; + if (eventHandler.isAlive()) { + display("Interrupting event handling thread"); + eventHandler.interrupt(); + } + } + + if (eventCount < tc02x003a.threadCount) { + complain("expecting " + tc02x003a.threadCount + + " MethodBreakpoint events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + debugee.sendSignal(SGL_QUIT); + } + + private void hitEvent(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (event.location().lineNumber() == tc02x003a.checkClassBrkpLine1 || + event.location().lineNumber() == tc02x003a.checkClassBrkpLine2) { + display("MethodEntryEvent occurs on the expected line " + + event.location().lineNumber() + " in method " + + event.method().name()); + } else { + complain("MethodEntryEventOccurs on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line numbers are " + + tc02x003a.checkClassBrkpLine1 + ", " + + tc02x003a.checkClassBrkpLine2); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + + eventCount++; + } + + private void hitEvent(ClassPrepareEvent event) { + display("ClassPrepareEvent occursn"); + eventCount++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003/TestDescription.java new file mode 100644 index 00000000000..226c0c2130d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003/TestDescription.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/multithrd/tc02x003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC2 + * Description: Class breakpoint + * Steps: 1.Add class breakpoint: singlethread.Class1 + * 2.Debug Main + * X. Stops on line 13 in Class1.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates ClassPrepareRequest + * MethodEntryRequest with adding filter via reference type. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 80th or 82th lines, that are static initializer + * and constructor of tc02x001aClass1 class. Every thread must generate + * MethodEntryEvent. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * There are a doublness of the "class breakpoint" understanding. + * Here is that JBuilder help says: + * 1. "A class breakpoint causes the debugger to stop when any method + * from the specified class is called or when the specified class + * is instantiated." + * So, a class breakpoint is MethodEntryRequest with filtering + * the specified class. + * 2. "A class breakpoint causes the debugger to stop at the location + * when the specified class is loaded or when any method from the + * specified class is called." + * In this case, a class breakpoint is MethodEntryRequest and + * ClassPrepareRequest with filtering the specified class. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test fixed according to test bug: + * 4804095 TEST_BUG: potential race condition with loading classes in JDI tests + * - launching debuggee by prepareDebugee() replaced with bindToDebugee() + * to exclude first IOPipe communication + * - making ClassPrepareRequest moved to begin (right after debuggee started) + * - making MethodEntryRequest moved to handling ClassPrepareEvent + * - handling events moved to a separate thread + * - removed extra IOPipe communication points to make algorithm more clear + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.multithrd.tc02x003 + * nsk.jdi.BScenarios.multithrd.tc02x003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.multithrd.tc02x003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003a.java new file mode 100644 index 00000000000..2f4957d1fa4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003a.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x003a is deugee's part of the tc02x003. + */ +public class tc02x003a { + + public final static int threadCount = 3; + static Log log; + + public final static int checkClassBrkpLine1 = 96; + public final static int checkClassBrkpLine2 = 98; + Thready [] thrds = new Thready [threadCount]; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc02x003.SGL_READY); + + tc02x003a obj = null; + String instr; + do { + instr = pipe.readln(); + if (instr.equals(tc02x003.SGL_LOAD)) { + tc02x003aClass1.loadThis = true; + obj = new tc02x003a(); + } else if (instr.equals(tc02x003.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + try { + for (int i = 0; i < obj.thrds.length; i++ ) { + obj.thrds[i].join(); + } + } catch (InterruptedException e) { + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + tc02x003a() { + for (int i = 0; i < thrds.length; i++ ) { + thrds[i] = new Thready("Thread-" + (i+1)); + thrds[i].start(); + } + } + + static class Thready extends Thread { + Thready(String name) { + super(name); + } + + public void run() { + log.display(getName() + ":: creating tc02x003aClass1"); + new tc02x003aClass1(getName()); + } + } +} + +class tc02x003aClass1 { + + static boolean loadThis = false; // checkClassBrkpLine1 + + public tc02x003aClass1(String thrdName) { // checkClassBrkpLine2 + tc02x003a.log.display("tc02x003aClass1::constructor is called from" + + thrdName); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004.java new file mode 100644 index 00000000000..9806d30f4da --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc02x004aClass1 + * class. Every thread must generate MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc02x004 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.multithrd."; + private final static String debuggerName = prefix + "tc02x004"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debugeeName + "Class1"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int brkpEventCount = 0; + MethodEntryRequest mthdReq; + EventRequestManager evm; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc02x004 thisTest = new tc02x004(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.redirectStderr(log.getOutStream()); + thisTest.evm = debugee.getEventRequestManager(); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + thisTest.evm.deleteEventRequest(thisTest.mthdReq); + } finally { + debugee.resume(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + display("\nTEST BEGINS"); + display("==========="); + debugee.resume(); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + mthdReq = evm.createMethodEntryRequest(); + mthdReq.addClassFilter(testedClassName); + mthdReq.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + + if (event instanceof MethodEntryEvent) { + display(" event ===>>> " + (brkpEventCount+1) + " MethodEntryEvent arrived"); + hitClassBreakpoint((MethodEntryEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + exit = exit || (brkpEventCount == tc02x004a.threadCount); + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (brkpEventCount < tc02x004a.threadCount) { + complain("expecting " + tc02x004a.threadCount + + " breakpoint events, but " + + brkpEventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitClassBreakpoint(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + display("thread:\t" + event.thread().name()); + try { + display("source:\t" + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("method:\t" + event.location().method().name()); + display("line:\t" + event.location().lineNumber()); + if (event.location().lineNumber() == tc02x004a.checkClassBrkpLine) { + display("ClassBreakpoint stops on the expected line " + + event.location().lineNumber() + " in method " + + event.method().name()); + } else { + complain("ClassBreakpoint stops on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line number is " + + tc02x004a.checkClassBrkpLine); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + + brkpEventCount++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004/TestDescription.java new file mode 100644 index 00000000000..b72c30c7952 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/multithrd/tc02x004. + * VM Testbase keywords: [quick, jpda, jdi, quarantine] + * VM Testbase comments: JDK-4751860 + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC2 + * Description: Class breakpoint + * Steps: 1.Add class breakpoint: singlethread.Class1 + * 2.Debug Main + * X. Stops on line 13 in Class1.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 59th line, that is constructor of tc02x004aClass1 + * class. Every thread must generate MethodEntryEvent. + * The test looks like tc002x001 except that synchronizing debugger and + * debugee is performed without IOPipe channel. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * There are a doublness of the "class breakpoint" understanding. + * Here is that JBuilder help says: + * 1. "A class breakpoint causes the debugger to stop when any method + * from the specified class is called or when the specified class + * is instantiated." + * So, a class breakpoint is MethodEntryRequest with filtering + * the specified class. + * 2. "A class breakpoint causes the debugger to stop at the location + * when the specified class is loaded or when any method from the + * specified class is called." + * In this case, a class breakpoint is MethodEntryRequest and + * ClassPrepareRequest with filtering the specified class. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.multithrd.tc02x004 + * nsk.jdi.BScenarios.multithrd.tc02x004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.multithrd.tc02x004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004a.java new file mode 100644 index 00000000000..f41aed76609 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x004a.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x004a is deugee's part of the tc02x004. + */ +public class tc02x004a { + + public final static int threadCount = 3; + static Log log; + + public final static int checkClassBrkpLine = 79; + Thready [] thrds = new Thready [threadCount]; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + tc02x004a obj = new tc02x004a(); + + try { + for (int i = 0; i < obj.thrds.length; i++ ) { + obj.thrds[i].join(); + } + } catch (InterruptedException e) { + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + tc02x004a() { + for (int i = 0; i < thrds.length; i++ ) { + thrds[i] = new Thready("Thread-" + (i+1)); + thrds[i].start(); + } + } + + static class Thready extends Thread { + Thready(String name) { + super(name); + } + + public void run() { + log.display(getName() + ":: creating tc02x004aClass1"); + new tc02x004aClass1(getName()); + } + } +} + +class tc02x004aClass1 { + public tc02x004aClass1(String thrdName) { // checkClassBrkpLine + tc02x004a.log.display("tc02x004aClass1::constructor is called from" + + thrdName); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001.java new file mode 100644 index 00000000000..986f5549ad2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC3 + * Description: Exception breakpoint + * Steps: 1.Set caught exception breakpoint on class + * javax.sound.midi.MidiUnavailableException + * 2.Debug Main + * X. Stops on line 42 in Main.java + * + * When the test is starting debugee, debugger creates ExceptionRequest. + * After ExceptionEvent arrived, debugger checks line number of one's + * location. It should be 74th line, that is throwing tc03x001aException. + * Every thread must generate ExceptionEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc03x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_LOAD = "load"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.multithrd."; + private final static String debuggerName = prefix + "tc03x001"; + private final static String debugeeName = debuggerName + "a"; + private final static String exceptionName = debugeeName + "Exception"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int eventCount = 0; + + private EventRequestManager evm = null; + private ExceptionRequest exReq = null; + private volatile boolean exit = false; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + tc03x001 thisTest = new tc03x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + IOPipe pipe = debugee.createIOPipe(); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + evm = debugee.getEventRequestManager(); + + ClassPrepareRequest crq = evm.createClassPrepareRequest(); + crq.addClassFilter(exceptionName); + crq.enable(); + + // event handling thread + Thread eventHandler = new Thread() { + public void run() { + EventQueue eventQueue = debugee.VM().eventQueue(); + EventSet eventSet = null; + while (!exit) { + try { + eventSet = eventQueue.remove(1000); + } catch (InterruptedException e) { + new Failure("Event handling thread interrupted:\n\t" + e); + } + if (eventSet == null) { + continue; + } + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + + if (event instanceof ClassPrepareEvent) { + exReq = evm.createExceptionRequest( + ((ClassPrepareEvent )event).referenceType(), + true, false); + exReq.enable(); + debugee.resume(); + + } else if (event instanceof ExceptionEvent) { + hitEvent((ExceptionEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } else { + throw new Failure("Unexpected event:\n\t" + event); + } // if + exit = exit || (eventCount >= tc03x001a.threadCount); + } // while + } // while + } // run() + }; // eventHadler + + display("Starting handling event"); + eventHandler.start(); + + debugee.resume(); + debugee.receiveExpectedSignal(SGL_READY); + + display("\nTEST BEGINS"); + display("==========="); + debugee.sendSignal(SGL_LOAD); + + display("Waiting for all events received"); + try { + eventHandler.join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Main thread interrupted while waiting for eventHandler:\n\t" + + e); + } finally { + crq.disable(); + exReq.disable(); + exit = true; + if (eventHandler.isAlive()) { + display("Interrupting event handling thread"); + eventHandler.interrupt(); + } + } + + if (eventCount < tc03x001a.threadCount) { + complain("expecting " + tc03x001a.threadCount + + " ExceptionEvents, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + display("============="); + display("TEST FINISHES\n"); + debugee.sendSignal(SGL_QUIT); + } + + private void hitEvent(ExceptionEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (event.location().lineNumber() == tc03x001a.checkExBrkpLine) { + display("ExceptionEvent occurs on the expected line " + + event.location().lineNumber() + " in method " + + event.location().method().name()); + } else { + complain("ExceptionEvent occurs stops on line " + event.location().lineNumber() + + " in method " + event.location().method().name() + + ", expected line number is " + + tc03x001a.checkExBrkpLine); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + + eventCount++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001/TestDescription.java new file mode 100644 index 00000000000..0b7eedb0560 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/multithrd/tc03x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC3 + * Description: Exception breakpoint + * Steps: 1.Set caught exception breakpoint on class + * javax.sound.midi.MidiUnavailableException + * 2.Debug Main + * X. Stops on line 42 in Main.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates ExceptionRequest. + * After ExceptionEvent arrived, debugger checks line number of one's + * location. It should be 74th line, that is throwing tc03x001aException. + * Every thread must generate ExceptionEvent. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test fixed according to test bug: + * 4804095 TEST_BUG: potential race condition with loading classes in JDI tests + * - launching debuggee by prepareDebugee() replaced with bindToDebugee() + * to exclude first IOPipe communication + * - making ClassPrepareRequest moved to begin (right after debuggee started) + * - making ExceptionRequest moved to handling ClassPrepareEvent + * - handling events moved to a separate thread + * - removed extra IOPipe communication points to make algorithm more clear + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.multithrd.tc03x001 + * nsk.jdi.BScenarios.multithrd.tc03x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.multithrd.tc03x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001a.java new file mode 100644 index 00000000000..7fffcb24064 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc03x001a.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc03x001a is deugee's part of the tc03x001. + */ +public class tc03x001a { + + public final static int threadCount = 3; + static Log log; + + public final static int checkExBrkpLine = 90; + Thready [] thrds = new Thready [threadCount]; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc03x001.SGL_READY); + + tc03x001a obj = null; + String instr; + do { + instr = pipe.readln(); + + if (instr.equals(tc03x001.SGL_LOAD)) { + tc03x001aException.loadThis = true; + obj = new tc03x001a(); + } else if (instr.equals(tc03x001.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + try { + for (int i = 0; i < obj.thrds.length; i++ ) { + obj.thrds[i].join(); + } + } catch (InterruptedException e) { + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + tc03x001a() { + for (int i = 0; i < thrds.length; i++ ) { + thrds[i] = new Thready("Thread-" + (i+1)); + thrds[i].start(); + } + } + + static class Thready extends Thread { + Thready(String name) { + super(name); + } + + public void run() { + log.display(getName() + ":: throwing tc03x001aException"); + try { + throw new tc03x001aException(); // checkExBrkpLine + } catch (tc03x001aException e) { + } + } + } +} + +class tc03x001aException extends RuntimeException { + + static boolean loadThis = false; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001.java new file mode 100644 index 00000000000..c72ef73a416 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC4 + * Description: Exception breakpoint + * Steps: 1.Set method breakpoint on Main.foo() + * 2.Debug Main + * 3.Stops on line 27 in Main.java + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks method name and if + * the one corresponds to specified name, it checks line number of the + * event location. It should be 64th line, that is method tc04x001a.foo. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc04x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_LOAD = "load"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.multithrd."; + private final static String debuggerName = prefix + "tc04x001"; + private final static String debugeeName = debuggerName + "a"; + private final static String methodName = "foo"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int brkpEventCount = 0; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc04x001 thisTest = new tc04x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + EventRequestManager evm = debugee.getEventRequestManager(); + MethodEntryRequest mthdReq = evm.createMethodEntryRequest(); + display("MethodEntryRequest created, expecting events " + + "from method \"" + methodName + "\""); + display("---------------------------------------------" + + "-----------"); + mthdReq.addClassFilter(debugeeName); + mthdReq.enable(); + + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + + if (event instanceof MethodEntryEvent) { + display(" event ===>>> " + " MethodEntryEvent arrived"); + hitMethodBreakpoint((MethodEntryEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (brkpEventCount < tc04x001a.threadCount) { + complain("expecting " + tc04x001a.threadCount + + " MethodBreakpoint events, but " + + brkpEventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitMethodBreakpoint(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (!event.method().name().equals(methodName)) { + display("the event skipped, method - " + event.method().name() + "\n"); + return; + } + + if (event.location().lineNumber() == tc04x001a.checkMethodBrkpLine) { + display("!!!MethodBreakpoint stops on the expected line " + + event.location().lineNumber() + " in method " + + "\"" + event.method().name() + "\"!!!"); + } else { + complain("MethodBreakpoint stops on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line number is " + + tc04x001a.checkMethodBrkpLine); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + + brkpEventCount++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001/TestDescription.java new file mode 100644 index 00000000000..e196970bf18 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/multithrd/tc04x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC4 + * Description: Exception breakpoint + * Steps: 1.Set method breakpoint on Main.foo() + * 2.Debug Main + * 3.Stops on line 27 in Main.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks method name and if + * the one corresponds to specified name, it checks line number of the + * event location. It should be 64th line, that is method tc04x001a.foo. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.multithrd.tc04x001 + * nsk.jdi.BScenarios.multithrd.tc04x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.multithrd.tc04x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001a.java new file mode 100644 index 00000000000..b7a68c487ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc04x001a.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.multithrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc04x001a is deugee's part of the tc04x001. + */ +public class tc04x001a { + + public final static int threadCount = 3; + static Log log; + + public final static int checkMethodBrkpLine = 74; + Thready [] thrds = new Thready [threadCount]; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.out, argHandler); + + tc04x001a obj = new tc04x001a(); + + for (int i = 0; i < obj.thrds.length; i++ ) { + try { + obj.thrds[i].join(argHandler.getWaitTime() * 60000);//obj.thrds[i].join(); + if (!obj.thrds[i].isAlive()) { + log.display(obj.thrds[i].getName() + " finished"); + } else { + log.display(obj.thrds[i].getName() + " not finished"); + } + } catch (InterruptedException e) { + log.complain("DEBUGEE> " + obj.thrds[i].getName() + " didn't die."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + tc04x001a() { + for (int i = 0; i < thrds.length; i++ ) { + thrds[i] = new Thready("Thread-" + (i+1)); + thrds[i].start(); + } + } + + public static void foo(String caller) { + log.display(caller + "::foo is called"); // checkMethodBrkpLine + } + + public static void bar(String caller) { + log.display(caller + "::bar is called"); + } + + static class Thready extends Thread { + Thready(String name) { + super(name); + } + + public void run() { + tc04x001a.foo(getName()); + tc04x001a.bar(getName()); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001.java new file mode 100644 index 00000000000..337e3654c0f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 1 - Breakpoints (single threads) + * Test case: TC1 + * Description: Line breakpoint & step into + * Steps: 1.Set breakpoint on line 19 + * 2.Debug Main + * X. Stops on line 19 + * 3.Run | Step into three times + * X. Steps into Class1 constructor + * + * When the test is starting debugee, debugger sets breakpoint at + * the 48th line (method performTest). + * After the breakpoint is reached, debugger creates "step into" request + * and resumes debugee. StepRequest is created with specified + * addClassFilter. For the third StepEvent debugger + * checks line number of one's location. It should be 56th line. + * + * In case, when line number of event is wrong, test fails. + */ + +public class tc01x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.singlethrd."; + private final static String debuggerName = prefix + "tc01x001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private final static int expectedStepEventCount = 3; + private static int stepEventCount = 0; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc01x001 thisTest = new tc01x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + display("Tested class\t:" + debugeeClass.name()); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + EventRequestManager evm = debugee.getEventRequestManager(); + StepRequest step = null; + + debugee.setBreakpoint(debugeeClass, + tc01x001a.brkpMethodName, + tc01x001a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal(SGL_PERFORM); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display(" event ===>>> " + event); + + if (event instanceof BreakpointEvent) { + display(" event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + step = evm.createStepRequest(((BreakpointEvent )event).thread(), + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + step.addClassFilter(prefix + "*"); + step.enable(); + debugee.resume(); + + } else if (event instanceof StepEvent) { + display(" event ===>>> " + event); + hitStepInto((StepEvent )event); + if (stepEventCount >= expectedStepEventCount) { + evm.deleteEventRequest(step); + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + exit = exit || (stepEventCount == expectedStepEventCount); + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (stepEventCount < expectedStepEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedStepEventCount + + " step events, but " + + stepEventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitBreakpoint(BreakpointEvent event) { + display("BreakpointEvent arrived. Location - " + + event.location().lineNumber() + " line"); + display(""); + } + + private void hitStepInto(StepEvent event) { + stepEventCount++; + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (stepEventCount == expectedStepEventCount) { + if (event.location().lineNumber() != tc01x001a.checkLastLine) { + complain("StepEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc01x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("StepEvent steps to the expected line " + + event.location().lineNumber()); + } + } + display(""); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001/TestDescription.java new file mode 100644 index 00000000000..57d1b678427 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/singlethrd/tc01x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 1 - Breakpoints (single threads) + * Test case: TC1 + * Description: Line breakpoint & step into + * Steps: 1.Set breakpoint on line 19 + * 2.Debug Main + * X. Stops on line 19 + * 3.Run | Step into three times + * X. Steps into Class1 constructor + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 48th line (method "performTest"). + * After the breakpoint is reached, debugger creates "step into" request + * and resumes debugee. StepRequest is created with specified addClassFilter. + * For the third StepEvent debugger checks line number of one's location. + * It should be 56th line. + * In case, when line number of event is wrong, test fails. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.singlethrd.tc01x001 + * nsk.jdi.BScenarios.singlethrd.tc01x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.singlethrd.tc01x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001a.java new file mode 100644 index 00000000000..79932cc1d46 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x001a.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc01x001a is deugee's part of the tc01x001. + */ +public class tc01x001a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 69; + + public final static int checkLastLine = 76; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc01x001.SGL_READY); + + tc01x001a obj = null; + String instr; + do { + instr = pipe.readln(); + if (instr.equals(tc01x001.SGL_PERFORM)) { + performTest(); + } else if (instr.equals(tc01x001.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void performTest() { + log.display("performTest::line 0"); + log.display("performTest::breakpoint line"); // brkpLineNumber + log.display("performTest::creating tc01x001aClass1 object"); + new tc01x001aClass1(); + } +} + +class tc01x001aClass1 { + tc01x001aClass1() { // checkLastLine + tc01x001a.log.display("tc01x001aClass1::constructor is called"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002.java new file mode 100644 index 00000000000..b5ac0a1590c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 1 - Breakpoints (single threads) + * Test case: TC1 + * Description: Line breakpoint & step into + * Steps: 1.Set breakpoint on line 19 + * 2.Debug Main + * X. Stops on line 19 + * 3.Run | Step into three times + * X. Steps into Class1 constructor + * + * When the test is starting debugee, debugger sets breakpoint at + * the 49th line (method performTest). + * After the breakpoint is reached, debugger creates "step into" request + * and resumes debugee. StepRequest is created with specified + * addClassExclusionFilter. For the third StepEvent + * debugger checks line number of one's location. It should be 56th line. + * + * In case, when line number of event is wrong, test fails. + */ + +public class tc01x002 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.singlethrd."; + private final static String debuggerName = prefix + "tc01x002"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private final static int expectedStepEventCount = 3; + private static int stepEventCount = 0; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc01x002 thisTest = new tc01x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + display("Tested class\t:" + debugeeClass.name()); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + EventRequestManager evm = debugee.getEventRequestManager(); + StepRequest step = null; + + debugee.setBreakpoint(debugeeClass, + tc01x002a.brkpMethodName, + tc01x002a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal(SGL_PERFORM); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display(" event ===>>> " + event); + + if (event instanceof BreakpointEvent) { + display(" event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + step = evm.createStepRequest(((BreakpointEvent )event).thread(), + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + step.addClassExclusionFilter("nsk.share.*"); + step.addClassExclusionFilter("java.*"); + step.addClassExclusionFilter("sun.*"); + step.addClassExclusionFilter("oracle.*"); + step.addClassExclusionFilter("jdk.jfr.*"); + step.addClassExclusionFilter("com.oracle.*"); + step.addClassExclusionFilter("jdk.internal.*"); + step.enable(); + debugee.resume(); + + } else if (event instanceof StepEvent) { + display(" event ===>>> " + event); + hitStepInto((StepEvent )event); + if (stepEventCount >= expectedStepEventCount) { + evm.deleteEventRequest(step); + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + exit = exit || (stepEventCount == expectedStepEventCount); + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (stepEventCount < expectedStepEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedStepEventCount + + " step events, but " + + stepEventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitBreakpoint(BreakpointEvent event) { + display("BreakpointEvent arrived. Location - " + + event.location().lineNumber() + " line"); + display(""); + } + + private void hitStepInto(StepEvent event) { + stepEventCount++; + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (stepEventCount == expectedStepEventCount) { + if (event.location().lineNumber() != tc01x002a.checkLastLine) { + complain("StepEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc01x002a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("StepEvent steps to the expected line " + + event.location().lineNumber()); + } + } + display(""); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002/TestDescription.java new file mode 100644 index 00000000000..830fa9006db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/singlethrd/tc01x002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 1 - Breakpoints (single threads) + * Test case: TC1 + * Description: Line breakpoint & step into + * Steps: 1.Set breakpoint on line 19 + * 2.Debug Main + * X. Stops on line 19 + * 3.Run | Step into three times + * X. Steps into Class1 constructor + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 49th line (method "performTest"). + * After the breakpoint is reached, debugger creates "step into" request + * and resumes debugee. StepRequest is created with specified + * addClassExclusionFilter. For the third StepEvent debugger checks line + * number of one's location. It should be 56th line. + * In case, when line number of event is wrong, test fails. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.singlethrd.tc01x002 + * nsk.jdi.BScenarios.singlethrd.tc01x002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.singlethrd.tc01x002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002a.java new file mode 100644 index 00000000000..6fb97d2d52d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc01x002a.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc01x002a is deugee's part of the tc01x002. + */ +public class tc01x002a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 69; + + public final static int checkLastLine = 76; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc01x002.SGL_READY); + + tc01x002a obj = null; + String instr; + do { + instr = pipe.readln(); + if (instr.equals(tc01x002.SGL_PERFORM)) { + performTest(); + } else if (instr.equals(tc01x002.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void performTest() { + log.display("performTest::line 0"); + log.display("performTest::breakpoint line"); // brkpLineNumber + log.display("performTest::creating tc01x002aClass1 object"); + new tc01x002aClass1(); + } +} + +class tc01x002aClass1 { + tc01x002aClass1() { // checkLastLine + tc01x002a.log.display("tc01x002aClass1::constructor is called"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001.java new file mode 100644 index 00000000000..80e3b1df992 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 1 - Breakpoints (single threads) + * Test case: TC2 + * Description: Line breakpoint & step over + * Steps: 1.Set breakpoint on line 19 + * 2.Debug Main + * X. Stops on line 19 + * 3.Run | Step over three times + * X. Stops on line 22 in Main.java + * + * When the test is starting debugee, debugger sets breakpoint at + * the 49th line (method "performTest"). + * After the breakpoint is reached, debugger creates "step over" request + * and resumes debugee. For the third StepEvent debugger checks line + * number of one's location. It should be 52th line. + * + * In case, when line number of event is wrong, test fails. + */ + +public class tc02x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.singlethrd."; + private final static String debuggerName = prefix + "tc02x001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private final static int expectedStepEventCount = 3; + private static int stepEventCount = 0; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc02x001 thisTest = new tc02x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + display("Tested class\t:" + debugeeClass.name()); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + EventRequestManager evm = debugee.getEventRequestManager(); + StepRequest step = null; + + debugee.setBreakpoint(debugeeClass, + tc02x001a.brkpMethodName, + tc02x001a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal(SGL_PERFORM); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display(" event ===>>> " + event); + + if (event instanceof BreakpointEvent) { + display(" event ===>>> " + event); + hitBreakpoint((BreakpointEvent )event); + step = evm.createStepRequest(((BreakpointEvent )event).thread(), + StepRequest.STEP_LINE, + StepRequest.STEP_OVER); + step.enable(); + debugee.resume(); + + } else if (event instanceof StepEvent) { + display(" event ===>>> " + event); + hitStepOver((StepEvent )event); + if (stepEventCount >= expectedStepEventCount) { + evm.deleteEventRequest(step); + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + exit = exit || (stepEventCount == expectedStepEventCount); + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (stepEventCount < expectedStepEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedStepEventCount + + " step events, but " + + stepEventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitBreakpoint(BreakpointEvent event) { + display("BreakpointEvent arrived. Location - " + + event.location().lineNumber() + " line"); + display(""); + } + + private void hitStepOver(StepEvent event) { + stepEventCount++; + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (stepEventCount == expectedStepEventCount) { + if (event.location().lineNumber() != tc02x001a.checkLastLine) { + complain("StepEvent steps to line " + event.location().lineNumber() + + ", expected line number is " + + tc02x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } else { + display("StepEvent steps to the expected line " + + event.location().lineNumber()); + } + } + display(""); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001/TestDescription.java new file mode 100644 index 00000000000..f791e5192e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/singlethrd/tc02x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 1 - Breakpoints (single threads) + * Test case: TC2 + * Description: Line breakpoint & step over + * Steps: 1.Set breakpoint on line 19 + * 2.Debug Main + * X. Stops on line 19 + * 3.Run | Step over three times + * X. Stops on line 22 in Main.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger sets breakpoint at + * the 49th line (method "performTest"). + * After the breakpoint is reached, debugger creates "step over" request + * and resumes debugee. For the third StepEvent debugger checks line + * number of one's location. It should be 52th line. + * In case, when line number of event is wrong, test fails. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.singlethrd.tc02x001 + * nsk.jdi.BScenarios.singlethrd.tc02x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.singlethrd.tc02x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001a.java new file mode 100644 index 00000000000..6b95d216fd6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc02x001a.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc02x001a is deugee's part of the tc02x001. + */ +public class tc02x001a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 68; + + public final static int checkLastLine = 71; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc02x001.SGL_READY); + + tc02x001a obj = null; + String instr; + do { + instr = pipe.readln(); + if (instr.equals(tc02x001.SGL_PERFORM)) { + performTest(); + } else if (instr.equals(tc02x001.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void performTest() { + log.display("performTest::line 0"); // brkpLineNumber + log.display("performTest::breakpoint line"); + log.display("performTest::creating tc02x001aClass1 object"); + new tc02x001aClass1(); // checkLastLine + log.display("performTest::tc02x001aClass1 object is created"); + } +} + +class tc02x001aClass1 { + tc02x001aClass1() { + tc02x001a.log.display("tc02x001aClass1::constructor is called"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001.java new file mode 100644 index 00000000000..fe2fec7036c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc03x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc03x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.singlethrd."; + private final static String debuggerName = prefix + "tc03x001"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debugeeName + "Class1"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private final static int expectedEventCount = 1; + private static int eventCount = 0; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc03x001 thisTest = new tc03x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + debugeeClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + MethodEntryRequest mthdReq = evm.createMethodEntryRequest(); + mthdReq.addClassFilter(testedClassName); + mthdReq.enable(); + + debugee.resume(); + debugee.sendSignal(SGL_PERFORM); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display(" event ===>>> " + event); + + if (event instanceof MethodEntryEvent) { + display(" event ===>>> " + event); + hitClassBreakpoint((MethodEntryEvent )event); + debugee.resume(); + exit = true; + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (eventCount < expectedEventCount) { + if (totalTime <= 0) { + complain("out of wait time..."); + } + complain("expecting " + expectedEventCount + + " breakpoint events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitClassBreakpoint(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (event.location().lineNumber() == tc03x001a.checkLastLine) { + display("ClassBreakpoint stops on the expected line " + + event.location().lineNumber() + " in method " + + event.method().name()); + } else { + complain("ClassBreakpoint stops on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line number is " + + tc03x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } + + eventCount++; + + display(""); + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001/TestDescription.java new file mode 100644 index 00000000000..1d7ea063201 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/singlethrd/tc03x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC2 + * Description: Class breakpoint + * Steps: 1.Add class breakpoint: singlethread.Class1 + * 2.Debug Main + * X. Stops on line 13 in Class1.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc02x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * There are a doublness of the "class breakpoint" understanding. + * Here is that JBuilder help says: + * 1. "A class breakpoint causes the debugger to stop when any method + * from the specified class is called or when the specified class + * is instantiated." + * So, a class breakpoint is MethodEntryRequest with filtering + * the specified class. + * 2. "A class breakpoint causes the debugger to stop at the location + * when the specified class is loaded or when any method from the + * specified class is called." + * In this case, a class breakpoint is MethodEntryRequest and + * ClassPrepareRequest with filtering the specified class. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.singlethrd.tc03x001 + * nsk.jdi.BScenarios.singlethrd.tc03x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.singlethrd.tc03x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001a.java new file mode 100644 index 00000000000..1469638c84d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x001a.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc03x001a is deugee's part of the tc02x001. + */ +public class tc03x001a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 1; + + public final static int checkLastLine = 77; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc03x001.SGL_READY); + + tc03x001a obj = null; + String instr; + do { + instr = pipe.readln(); + if (instr.equals(tc03x001.SGL_PERFORM)) { + performTest(); + } else if (instr.equals(tc03x001.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void performTest() { + log.display("performTest::line 0"); + log.display("performTest::breakpoint line"); + log.display("performTest::creating tc03x001aClass1 object"); + new tc03x001aClass1(); + log.display("performTest::tc03x001aClass1 object is created"); + } +} + +class tc03x001aClass1 { + tc03x001aClass1() { // checkLastLine + tc03x001a.log.display("tc03x001aClass1::constructor is called"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002.java new file mode 100644 index 00000000000..245d923a4ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc03x002aClass1 + * class. Every thread must generate MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc03x002 { + + public final static String SGL_READY = "ready"; + public final static String SGL_LOAD = "load"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.singlethrd."; + private final static String debuggerName = prefix + "tc03x002"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debugeeName + "Class1"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int eventCount = 0; + private final static int expectedEventCount = 2; + + private EventRequestManager evm = null; + private MethodEntryRequest mthdReq = null; + private volatile boolean exit = false; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + tc03x002 thisTest = new tc03x002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + IOPipe pipe = debugee.createIOPipe(); + + try { + thisTest.execTest(); + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + evm = debugee.getEventRequestManager(); + + ClassPrepareRequest crq = evm.createClassPrepareRequest(); + crq.addClassFilter(testedClassName); + crq.enable(); + + // event handling thread + Thread eventHandler = new Thread() { + public void run() { + EventQueue eventQueue = debugee.VM().eventQueue(); + EventSet eventSet = null; + while (!exit) { + try { + eventSet = eventQueue.remove(1000); + } catch (InterruptedException e) { + new Failure("Event handling thread interrupted:\n\t" + e); + } + if (eventSet == null) { + continue; + } + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + + if (event instanceof ClassPrepareEvent) { + display(" event ===>>> " + event); + mthdReq = evm.createMethodEntryRequest(); + mthdReq.addClassFilter(testedClassName); + mthdReq.enable(); + debugee.resume(); + + } else if (event instanceof MethodEntryEvent) { + display(" event ===>>> " + event); + hitEvent((MethodEntryEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } else { + throw new Failure("Unexpected event:\n\t" + event); + } // if + exit = exit || (eventCount >= expectedEventCount); + } // while + } // while + } // run() + }; // eventHadler + + display("Starting handling event"); + eventHandler.start(); + + debugee.resume(); + debugee.receiveExpectedSignal(SGL_READY); + + display("\nTEST BEGINS"); + display("==========="); + debugee.sendSignal(SGL_LOAD); + + display("Waiting for all events received"); + try { + eventHandler.join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Main thread interrupted while waiting for eventHandler:\n\t" + + e); + } finally { + crq.disable(); + mthdReq.disable(); + exit = true; + if (eventHandler.isAlive()) { + display("Interrupting event handling thread"); + eventHandler.interrupt(); + } + } + + if (eventCount < expectedEventCount) { + complain("Expecting " + expectedEventCount + + " MethodEntryEvents, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + debugee.sendSignal(SGL_QUIT); + } + + private void hitEvent(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + eventCount++; + if (event.location().lineNumber() == tc03x002a.checkLastLine1 || + event.location().lineNumber() == tc03x002a.checkLastLine2) { + display("MethodEntryEvent occurs on the expected line " + + event.location().lineNumber() + " in method " + + event.method().name()); + } else { + complain("MethodEntryEvent occurs on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line numbers are " + + tc03x002a.checkLastLine1 + " or " + + tc03x002a.checkLastLine2); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002/TestDescription.java new file mode 100644 index 00000000000..6cfc53b6c17 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/singlethrd/tc03x002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC2 + * Description: Class breakpoint + * Steps: 1.Add class breakpoint: singlethread.Class1 + * 2.Debug Main + * X. Stops on line 13 in Class1.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc02x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * There are a doublness of the "class breakpoint" understanding. + * Here is that JBuilder help says: + * 1. "A class breakpoint causes the debugger to stop when any method + * from the specified class is called or when the specified class + * is instantiated." + * So, a class breakpoint is MethodEntryRequest with filtering + * the specified class. + * 2. "A class breakpoint causes the debugger to stop at the location + * when the specified class is loaded or when any method from the + * specified class is called." + * In this case, a class breakpoint is MethodEntryRequest and + * ClassPrepareRequest with filtering the specified class. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test fixed according to test bug: + * 4804095 TEST_BUG: potential race condition with loading classes in JDI tests + * - launching debuggee by prepareDebugee() replaced with bindToDebugee() + * to exclude first IOPipe communication + * - making ClassPrepareRequest moved to begin (right after debuggee started) + * - making MethodEntryRequest moved to handling ClassPrepareEvent + * - handling events moved to a separate thread + * - removed extra IOPipe communication points to make algorithm more clear + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.singlethrd.tc03x002 + * nsk.jdi.BScenarios.singlethrd.tc03x002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.singlethrd.tc03x002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002a.java new file mode 100644 index 00000000000..c66b256bd5e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x002a.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc03x002a is deugee's part of the tc02x001. + */ +public class tc03x002a { + + public final static int checkLastLine1 = 76; + public final static int checkLastLine2 = 78; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc03x002.SGL_READY); + + tc03x002a obj = null; + String instr; + do { + instr = pipe.readln(); + log.display("instruction \"" + instr +"\""); + if (instr.equals(tc03x002.SGL_LOAD)) { + tc03x002aClass1.loadThis = true; + performTest(); + } else if (instr.equals(tc03x002.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void performTest() { + log.display("performTest::creating tc03x002aClass1 object"); + new tc03x002aClass1(); + log.display("performTest::tc03x002aClass1 object is created"); + } +} + +class tc03x002aClass1 { + + static boolean loadThis = false; // checkLastLine1 + + tc03x002aClass1() { // checkLastLine2 + tc03x002a.log.display("tc03x002aClass1::constructor is called"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003.java new file mode 100644 index 00000000000..7687f8fdd36 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc03x003aClass1 + * class. Every thread must generate MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc03x003 { + + public final static String SGL_READY = "ready"; + public final static String SGL_LOAD = "load"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.singlethrd."; + private final static String debuggerName = prefix + "tc03x003"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debugeeName + "Class1"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static int eventCount = 0; + private final static int expectedEventCount = 3; + + private EventRequestManager evm = null; + private MethodEntryRequest mthdReq = null; + private volatile boolean exit = false; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + tc03x003 thisTest = new tc03x003(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + IOPipe pipe = debugee.createIOPipe(); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + evm = debugee.getEventRequestManager(); + + ClassPrepareRequest crq = evm.createClassPrepareRequest(); + crq.addClassFilter(testedClassName); + crq.enable(); + + // separate thread to handle event + Thread eventHandler = new Thread() { + public void run() { + EventQueue eventQueue = debugee.VM().eventQueue(); + while (!exit) { + EventSet eventSet = null; + try { + eventSet = eventQueue.remove(1000); + } catch (InterruptedException e) { + new Failure("Event handling thread interrupted:\n\t" + e); + } + if (eventSet == null) { + continue; + } + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + + if (event instanceof ClassPrepareEvent) { + display(" event ===>>> " + event); + ClassPrepareEvent clsEvent = (ClassPrepareEvent)event; + hitEvent(clsEvent); + + mthdReq = evm.createMethodEntryRequest(); + ReferenceType testedClass = clsEvent.referenceType(); + mthdReq.addClassFilter(testedClass); + mthdReq.enable(); + + debugee.resume(); + + } else if (event instanceof MethodEntryEvent) { + display(" event ===>>> " + event); + hitEvent((MethodEntryEvent )event); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } else { + throw new Failure("Unexpected event received:\n\t" + event); + } // if + exit = exit || (eventCount >= expectedEventCount); + } // while + } // while + } // run() + }; // eventHandler + + display("Starting handling event"); + eventHandler.start(); + + debugee.resume(); + debugee.receiveExpectedSignal(SGL_READY); + + display("\nTEST BEGINS"); + display("==========="); + debugee.sendSignal(SGL_LOAD); + + display("Waiting for all events received"); + try { + eventHandler.join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Main thread interrupted while waiting for eventHandler:\n\t" + + e); + } finally { + crq.disable(); + mthdReq.disable(); + exit = true; + if (eventHandler.isAlive()) { + display("Interrupting event handling thread"); + eventHandler.interrupt(); + } + } + + if (eventCount < expectedEventCount) { + complain("Expecting " + expectedEventCount + + " BreakpointEvents, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + debugee.sendSignal(SGL_QUIT); + } + + private void hitEvent(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + eventCount++; + if (event.location().lineNumber() == tc03x003a.checkLastLine1 || + event.location().lineNumber() == tc03x003a.checkLastLine2) { + display("MethodEntryEvent occurs stops on the expected line " + + event.location().lineNumber() + " in method " + + event.method().name()); + } else { + complain("MewthodEntryEvent occurs on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line numbers are " + + tc03x003a.checkLastLine1 + " or " + + tc03x003a.checkLastLine2); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + + } + + private void hitEvent(ClassPrepareEvent event) { + display("ClassPrepareEvent occurs\n"); + eventCount++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003/TestDescription.java new file mode 100644 index 00000000000..7a9f9b16736 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/singlethrd/tc03x003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC2 + * Description: Class breakpoint + * Steps: 1.Add class breakpoint: singlethread.Class1 + * 2.Debug Main + * X. Stops on line 13 in Class1.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc02x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * There are a doublness of the "class breakpoint" understanding. + * Here is that JBuilder help says: + * 1. "A class breakpoint causes the debugger to stop when any method + * from the specified class is called or when the specified class + * is instantiated." + * So, a class breakpoint is MethodEntryRequest with filtering + * the specified class. + * 2. "A class breakpoint causes the debugger to stop at the location + * when the specified class is loaded or when any method from the + * specified class is called." + * In this case, a class breakpoint is MethodEntryRequest and + * ClassPrepareRequest with filtering the specified class. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test fixed according to test bug: + * 4804095 TEST_BUG: potential race condition with loading classes in JDI tests + * - launching debuggee by prepareDebugee() replaced with bindToDebugee() + * to exclude first IOPipe communication + * - making ClassPrepareRequest moved to begin (right after debuggee started) + * - making MethodEntryRequest moved to handling ClassPrepareEvent + * - handling events moved to a separate thread + * - removed extra IOPipe communication points to make algorithm more clear + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.singlethrd.tc03x003 + * nsk.jdi.BScenarios.singlethrd.tc03x003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.singlethrd.tc03x003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003a.java new file mode 100644 index 00000000000..acc5a484c17 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc03x003a.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc03x003a is deugee's part of the tc02x001. + */ +public class tc03x003a { + + public final static int checkLastLine1 = 76; + public final static int checkLastLine2 = 78; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc03x003.SGL_READY); + + tc03x003a obj = null; + String instr; + do { + instr = pipe.readln(); + log.display("instruction \"" + instr +"\""); + if (instr.equals(tc03x003.SGL_LOAD)) { + tc03x003aClass1.loadThis = true; + performTest(); + } else if (instr.equals(tc03x003.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void performTest() { + log.display("performTest::creating tc03x003aClass1 object"); + new tc03x003aClass1(); + log.display("performTest::tc03x003aClass1 object is created"); + } +} + +class tc03x003aClass1 { + + static boolean loadThis = false; // checkLastLine1 + + tc03x003aClass1() { // checkLastLine2 + tc03x003a.log.display("tc03x003aClass1::constructor is called"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001.java new file mode 100644 index 00000000000..4297b956a52 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc04x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc04x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_LOAD = "load"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.singlethrd."; + private final static String debuggerName = prefix + "tc04x001"; + private final static String debugeeName = debuggerName + "a"; + private final static String exceptionName = debugeeName + "Exception"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private final static int expectedEventCount = 1; + private static int eventCount = 0; + + private EventRequestManager evm = null; + private ExceptionRequest exReq = null; + private volatile boolean exit = false; + + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + tc04x001 thisTest = new tc04x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + IOPipe pipe = debugee.createIOPipe(); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + evm = debugee.getEventRequestManager(); + + ClassPrepareRequest crq = evm.createClassPrepareRequest(); + crq.addClassFilter(exceptionName); + crq.enable(); + + // separate thread to handle event + Thread eventHandler = new Thread() { + public void run() { + EventQueue eventQueue = debugee.VM().eventQueue(); + while (!exit) { + EventSet eventSet = null; + try { + eventSet = eventQueue.remove(1000); + } catch (InterruptedException e) { + new Failure("Event handling thread interrupted:\n\t" + e); + } + if (eventSet == null) { + continue; + } + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + + if (event instanceof ClassPrepareEvent) { + display(" event ===>>> " + event); + exReq = evm.createExceptionRequest( + ((ClassPrepareEvent )event).referenceType(), + true, false); + exReq.enable(); + debugee.resume(); + + } else if (event instanceof ExceptionEvent) { + display(" event ===>>> " + event); + hitEvent((ExceptionEvent )event); + exReq.disable(); + debugee.resume(); + exit = true; + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } else { + throw new Failure("Unexpected event received:\n\t" + event); + } // if + } // while + } // while + } // run() + }; // eventHandler + + display("Starting handling event"); + eventHandler.start(); + + debugee.resume(); + debugee.receiveExpectedSignal(SGL_READY); + + display("\nTEST BEGINS"); + display("==========="); + debugee.sendSignal(SGL_LOAD); + + display("Waiting for all events received"); + try { + eventHandler.join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Main thread interrupted while waiting for eventHandler:\n\t" + + e); + } finally { + crq.disable(); + exReq.disable(); + exit = true; + if (eventHandler.isAlive()) { + display("Interrupting event handling thread"); + eventHandler.interrupt(); + } + } + + if (eventCount < expectedEventCount) { + complain("expecting " + expectedEventCount + + " breakpoint events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + debugee.sendSignal(SGL_QUIT); + } + + private void hitEvent(ExceptionEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (event.location().lineNumber() == tc04x001a.checkExBrkpLine) { + display("ExceptionEvent occurs on the expected line " + + event.location().lineNumber() + " in method " + + event.location().method().name()); + } else { + complain("ExceptionEvent occurs on line " + event.location().lineNumber() + + " in method " + event.location().method().name() + + ", expected line number is " + + tc04x001a.checkExBrkpLine); + exitStatus = Consts.TEST_FAILED; + } + + eventCount++; + display(""); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001/TestDescription.java new file mode 100644 index 00000000000..7aafe7a7560 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/singlethrd/tc04x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC3 + * Description: Exception breakpoint + * Steps: 1.Set caught exception breakpoint on class + * javax.sound.midi.MidiUnavailableException + * 2.Debug Main + * X. Stops on line 42 in Main.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates ExceptionRequest. + * After ExceptionEvent arrived, debugger checks line number of one's + * location. It should be 74th line, that is throwing tc03x001aException. + * Every thread must generate ExceptionEvent. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test fixed according to test bug: + * 4804095 TEST_BUG: potential race condition with loading classes in JDI tests + * - launching debuggee by prepareDebugee() replaced with bindToDebugee() + * to exclude first IOPipe communication + * - making ClassPrepareRequest moved to begin (right after debuggee started) + * - making ExceptionRequest moved to handling ClassPrepareEvent + * - handling events moved to a separate thread + * - removed extra IOPipe communication points to make algorithm more clear + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.singlethrd.tc04x001 + * nsk.jdi.BScenarios.singlethrd.tc04x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.singlethrd.tc04x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001a.java new file mode 100644 index 00000000000..5f0ba801666 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc04x001a.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc04x001a is deugee's part of the tc02x001. + */ +public class tc04x001a { + + public final static int checkExBrkpLine = 69; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc04x001.SGL_READY); + + tc04x001a obj = null; + String instr; + do { + instr = pipe.readln(); + log.display("instruction \"" + instr +"\""); + if (instr.equals(tc04x001.SGL_LOAD)) { + tc04x001aException.loadThis = true; + performTest(); + } else if (instr.equals(tc04x001.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void performTest() { + log.display("performTest:: throwing tc04x001aException"); + try { + throw new tc04x001aException(); // checkExBrkpLine + } catch (tc04x001aException e) { + } + } +} + +class tc04x001aException extends RuntimeException { + static boolean loadThis = false; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001.java new file mode 100644 index 00000000000..8a71e950723 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test is from the group of so-called Borland's scenarios and + * implements the following test case:
    + * Suite 2 - Breakpoints (multiple threads)
    + * Test case: TC2
    + * Description: Class breakpoint
    + * Steps: 1.Add class breakpoint: singlethread.Class1
    + * 2.Debug Main
    + * X. Stops on line 13 in Class1.java
    + * + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc05x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + */ + +public class tc05x001 { + + public final static String SGL_READY = "ready"; + public final static String SGL_PERFORM = "perform"; + public final static String SGL_QUIT = "quit"; + + private final static String prefix = "nsk.jdi.BScenarios.singlethrd."; + private final static String debuggerName = prefix + "tc05x001"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debugeeName + "Class1"; + private final static String methodName = "bar"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private final static int expectedEventCount = 1; + private static int eventCount = 0; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + tc05x001 thisTest = new tc05x001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Throwable e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + debugeeClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + EventRequestManager evm = debugee.getEventRequestManager(); + MethodEntryRequest mthdReq = null; + + mthdReq = evm.createMethodEntryRequest(); + mthdReq.addClassFilter(testedClassName); + mthdReq.enable(); + + debugee.resume(); + debugee.sendSignal(SGL_PERFORM); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display(" event ===>>> " + event); + + if (event instanceof MethodEntryEvent) { + display(" event ===>>> " + event); + hitMethodBreakpoint((MethodEntryEvent )event); + if (eventCount > 0) { + exit = true; + evm.deleteEventRequest(mthdReq); + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0 && !exit) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (eventCount < expectedEventCount) { + complain("expecting " + expectedEventCount + + " breakpoint events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitMethodBreakpoint(MethodEntryEvent event) { + ThreadReference thrd = event.thread(); + + display("event info:"); + display("\tthread\t- " + event.thread().name()); + try { + display("\tsource\t- " + event.location().sourceName()); + } catch (AbsentInformationException e) { + } + display("\tmethod\t- " + event.location().method().name()); + display("\tline\t- " + event.location().lineNumber()); + + if (!event.method().name().equals(methodName)) { + display("the event skipped, method - " + event.method().name()); + } else { + if (event.location().lineNumber() == tc05x001a.checkLastLine) { + display("MethodBreakpoint stops on the expected line " + + event.location().lineNumber() + " in method " + + event.method().name()); + } else { + complain("MethodBreakpoint stops on line " + event.location().lineNumber() + + " in method " + event.method().name() + + ", expected line number is " + + tc05x001a.checkLastLine); + exitStatus = Consts.TEST_FAILED; + } + eventCount++; + } + display(""); + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001/TestDescription.java new file mode 100644 index 00000000000..d3eec2e4013 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BScenarios/singlethrd/tc05x001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * This test is from the group of so-called Borland's scenarios and + * implements the following test case: + * Suite 2 - Breakpoints (multiple threads) + * Test case: TC2 + * Description: Class breakpoint + * Steps: 1.Add class breakpoint: singlethread.Class1 + * 2.Debug Main + * X. Stops on line 13 in Class1.java + * The description was drown up according to steps under JBuilder. + * Of course, the test has own line numbers and method/class names and + * works as follow: + * When the test is starting debugee, debugger creates MethodEntryRequest. + * After MethodEntryEvent arrived, debugger checks line number of one's + * location. It should be 73th line, that is constructor of tc02x001aClass1 + * class. Every thread must generate MethodEntryEvent. + * In case, when at least one event doesn't arrive during waittime + * interval or line number of event is wrong, test fails. + * COMMENTS: + * There are a doublness of the "class breakpoint" understanding. + * Here is that JBuilder help says: + * 1. "A class breakpoint causes the debugger to stop when any method + * from the specified class is called or when the specified class + * is instantiated." + * So, a class breakpoint is MethodEntryRequest with filtering + * the specified class. + * 2. "A class breakpoint causes the debugger to stop at the location + * when the specified class is loaded or when any method from the + * specified class is called." + * In this case, a class breakpoint is MethodEntryRequest and + * ClassPrepareRequest with filtering the specified class. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BScenarios.singlethrd.tc05x001 + * nsk.jdi.BScenarios.singlethrd.tc05x001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BScenarios.singlethrd.tc05x001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001a.java new file mode 100644 index 00000000000..534618176a5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/singlethrd/tc05x001a.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BScenarios.singlethrd; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * tc05x001a is deugee's part of the tc02x001. + */ +public class tc05x001a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 1; + + public final static int checkLastLine = 82; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(tc05x001.SGL_READY); + + tc05x001a obj = null; + String instr; + do { + instr = pipe.readln(); + if (instr.equals(tc05x001.SGL_PERFORM)) { + performTest(); + } else if (instr.equals(tc05x001.SGL_QUIT)) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + public static void performTest() { + log.display("performTest::creating tc05x001aClass1 object"); + tc05x001aClass1 obj = new tc05x001aClass1(); + log.display("performTest::invoking tc05x001aClass1.bar()"); + obj.bar(); + } +} + +class tc05x001aClass1 { + + tc05x001aClass1() { + tc05x001a.log.display("tc05x001aClass1::constructor is called"); + } + + public void bar() { + tc05x001a.log.display("tc05x001aClass1.bar::" // checkLastLine + + "method breakpoint should stop here"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001.java new file mode 100644 index 00000000000..abf880997ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanArgument.booleanValue; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; +import com.sun.jdi.connect.LaunchingConnector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.BooleanArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.BooleanArgument.BooleanValue()
    + * complies with its specification in the following cases: + * - a value of the argument is set as a string and read as a boolean;
    + * - a value of the argument is set as a boolean and read as a string.
    + *
    + * In case of the method booleanValue() returns a wrong value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class booleanvalue001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.booleanValue\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.booleanValue\n" ; + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.BooleanArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connecter with needed Argument found\n"); + return exitCode0; + } + } + + + argument.setValue(true); + argument.setValue("true"); + if (!argument.booleanValue()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: 'true' -> true = true \n" + + "result: booleanValue() != true \n"); + } + + argument.setValue(true); + argument.setValue("false"); + if (argument.booleanValue()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: 'false' -> true = false \n" + + "result: booleanValue() != false \n"); + } + + argument.setValue(false); + argument.setValue("true"); + if (!argument.booleanValue()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: 'true' -> false = true \n" + + "result: booleanValue() != true \n"); + } + + argument.setValue(false); + argument.setValue("false"); + if (argument.booleanValue()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: 'false' -> false = false \n" + + "result: booleanValue() != false \n"); + } + + argument.setValue("true"); + argument.setValue(true); + if (!argument.booleanValue()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: true -> 'true' = true \n" + + "result: booleanValue() != true \n"); + } + + argument.setValue("true"); + argument.setValue(false); + if (argument.booleanValue()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: false -> 'true' = false \n" + + "result: booleanValue() != false \n"); + } + + argument.setValue("false"); + argument.setValue(true); + if (!argument.booleanValue()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: true -> 'false' = true \n" + + "result: booleanValue() != true \n"); + } + + argument.setValue("false"); + argument.setValue(false); + if (argument.booleanValue()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: false -> 'false' = false \n" + + "result: booleanValue() != false \n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001/TestDescription.java new file mode 100644 index 00000000000..26ca8dbfc88 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue001/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanArgument/booleanValue/booleanvalue001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.BooleanArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.BooleanArgument.booleanValue() + * complies with its specification. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.BooleanArgument object is searched among + * Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * setValue(true); setValue("true"); + * IF !argument.booleanValue(); + * THEN an error detected + * ELSE the check passed + * setValue(true); setValue("false"); + * IF argument.booleanValue(); + * THEN an error detected + * ELSE the check passed + * setValue(false); setValue("true"); + * IF !argument.booleanValue(); + * THEN an error detected + * ELSE the check passed + * setValue(false); setValue("false"); + * IF argument.booleanValue(); + * THEN an error detected + * ELSE the check passed + * setValue("true"); setValue(true); + * IF !argument.booleanValue() + * THEN an error detected + * ELSE the check passed + * setValue("true"); setValue(false); + * IF argument.booleanValue() + * THEN an error detected + * ELSE the check passed + * setValue("false"); setValue(true); + * IF !argument.booleanValue() + * THEN an error detected + * ELSE the check passed + * setValue("false"); setValue(false); + * IF argument.booleanValue() + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanArgument.booleanValue.booleanvalue001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanArgument.booleanValue.booleanvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002.java new file mode 100644 index 00000000000..e74db7c1390 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanArgument.booleanValue; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; +import com.sun.jdi.connect.LaunchingConnector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.BooleanArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.BooleanArgument.BooleanValue()
    + * complies with its specification in the following cases:
    +
    +
    + *
    + * In case of the method booleanValue() returns a wrong value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class booleanvalue002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING:\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.booleanValue\n" ; +// + String sErr2 = "INFO:\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.booleanValue\n" ; + + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.BooleanArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connecter with needed BooleanArgument found\n"); + return exitCode0; + } + } + + boolean b; + + argument.setValue(true); + argument.setValue(""); + b = argument.booleanValue(); + if (b) { + exitCode = exitCode2; + out.println(sErr2 + + "check: '' -> true = ? \n" + + "result: booleanValue() == " + b + "\n"); + } + + argument.setValue(true); + argument.setValue("tru"); + b = argument.booleanValue(); + if (b) { + exitCode = exitCode2; + out.println(sErr2 + + "check: 'tru' -> true = ? \n" + + "result: booleanValue() == " + b + "\n"); + } + + argument.setValue(false); + argument.setValue(""); + b = argument.booleanValue(); + if (b) { + exitCode = exitCode2; + out.println(sErr2 + + "check: '' -> false = ? \n" + + "result: booleanValue() == " + b + "\n"); + } + + argument.setValue(false); + argument.setValue("fals"); + b = argument.booleanValue(); + if (b) { + exitCode = exitCode2; + out.println(sErr2 + + "check: '' -> false = ? \n" + + "result: booleanValue() == " + b + "\n"); + } + + argument.setValue("true"); + argument.setValue(""); + b = argument.booleanValue(); + if (b) { + exitCode = exitCode2; + out.println(sErr2 + + "check: '' -> 'true' = ? \n" + + "result: booleanValue() == " + b + "\n"); + } + + argument.setValue("true"); + argument.setValue("tru"); + b = argument.booleanValue(); + if (b) { + exitCode = exitCode2; + out.println(sErr2 + + "check: 'tru' -> 'true' = ? \n" + + "result: booleanValue() == " + b + "\n"); + } + + argument.setValue("false"); + argument.setValue(""); + b = argument.booleanValue(); + if (b) { + exitCode = exitCode2; + out.println(sErr2 + + "check: '' -> 'false' = ? \n" + + "result: booleanValue() == " + b + "\n"); + } + + argument.setValue("false"); + argument.setValue("fals"); + b = argument.booleanValue(); + if (b) { + exitCode = exitCode2; + out.println(sErr2 + + "check: 'fals' -> 'false' = ? \n" + + "result: booleanValue() == " + b + "\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002/TestDescription.java new file mode 100644 index 00000000000..15dce51fdb6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/booleanValue/booleanvalue002/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanArgument/booleanValue/booleanvalue002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.BooleanArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.BooleanArgument.booleanValue() + * complies with its specification. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.BooleanArgument object is searched among + * Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - After the following assignments: + * 1) argument.setValue(true); + * argument.setValue("tru"); + * 2) argument.setValue(true); + * argument.setValue(""); + * 3) argument.setValue(false); + * argument.setValue(""); + * 4) argument.setValue(false); + * argument.setValue("fals"); + * 5) argument.setValue("true"); + * argument.setValue("tru"); + * 6) argument.setValue("true"); + * argument.setValue(""); + * 7) argument.setValue("false"); + * argument.setValue(""); + * 8) argument.setValue("false"); + * argument.setValue("fals"); + * the check is performed: + * IF argument.booleanValue(); + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanArgument.booleanValue.booleanvalue002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanArgument.booleanValue.booleanvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001.java new file mode 100644 index 00000000000..b2bae31a334 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.LaunchingConnector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.BooleanArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.BooleanArgument.isValid()
    + * complies with its specification, that is, returns
    + * true for the String values "true" and "false", and
    + * false for another String value which, however, is not null, and
    + * for the empty string.
    + *
    + * In case of a wrong boolean value returned,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class isvalid001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.isValue()\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.BooleanArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connecter with needed Argument found\n"); + return exitCode0; + } + } + + if (!argument.isValid("true")) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid('true')\n" + + "error: returned value != true\n"); + } + + if (!argument.isValid("false")) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid('false')\n" + + "error: returned value != true\n"); + } + + if (argument.isValid("fals")) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid('fals')\n" + + "error: returned value == true\n"); + } + + if (argument.isValid("")) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid()\n" + + "error: returned value == true\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001/TestDescription.java new file mode 100644 index 00000000000..9d224ea009f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanArgument/isValid/isvalid001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.BooleanArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.BooleanArgument.isValid() + * complies with its specification, that is, returns + * true for the String values "true" and "false", and + * false for another String value which, however, is not null, and + * for the empty string. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.BooleanArgument object is searched among + * Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * IF !argument.isValid("true") + * THEN an error detected + * ELSE the check passed + * IF argument.isValid("false") + * THEN an error detected + * ELSE the check passed + * IF argument.isValid("fals") + * THEN an error detected + * ELSE the check passed + * IF argument.isValid("") + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanArgument.isValid.isvalid001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanArgument.isValid.isvalid001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002.java new file mode 100644 index 00000000000..0b0f883aba4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.LaunchingConnector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.BooleanArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.BooleanArgument.isValid()
    + * complies with its specification when its parameter is null-string.
    + *
    + * The case for testing includes throwing NullPointerException as
    + * correct reaction to the null-parameter.
    + */ + + +public class isvalid002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.BooleanArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connecter with BooleanArgument found\n"); + return exitCode0; + } + } + + try { + argument.isValid(null); + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(null)\n" + + "error: no NullPointerException thrown \n"); + } catch (NullPointerException e) { + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002/TestDescription.java new file mode 100644 index 00000000000..e2012bb7be2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/isValid/isvalid002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanArgument/isValid/isvalid002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.BooleanArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.BooleanArgument.isValid() + * complies with its specification when its parameter is null-string. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.BooleanArgument object is searched among + * Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following check is applied: + * IF argument.isValid(null) + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * To fix the bug 4491137, + * the test is corrected to comply with + * the updated specification in jdi-overview.html: + * Any method which takes a Object as an parameter + * will throw NullPointerException if + * null is passed directly or indirectly -- + * unless null is explicitly mentioned as a valid parameter. + * From now, the test regards throwing NullPointerException + * as the correct reaction to the null-parameter. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanArgument.isValid.isvalid002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanArgument.isValid.isvalid002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001.java new file mode 100644 index 00000000000..4850009bc09 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanArgument.setValue; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; + + +/** + * The test for the implementation of a BooleanArgument object.
    + * + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.BooleanArgument.setValue()
    + * complies with specification.
    + * The test works as follows: + *
    + * - Virtual Machine Manager is invoked. + * - First BooleanArgument is searched among Connectors.
    + * If no a BooleanArgument is found out the test exits with
    + * the return value = 95 and a warning message.
    + * - Under the assumption that the method
    + * BooleanArgument.booleanValue() works correctly,
    + * to the value of the BooleanArgument founded,
    + * which may not have been set or may have an invalid value,
    + * the sequence of 5 following checks is applied:
    + *
    + * 1) setValue(true); booleanValue() must return true;
    + * 2) setValue(false); booleanValue() must return false;
    + * 3) setValue(false); booleanValue() must return false;
    + * 4) setValue(true); booleanValue() must return true;
    + * 5) setValue(true); booleanValue() must return true;
    + *
    + * In case of any check results in a wrong value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class setvalue001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.setValue\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.setValue\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.BooleanArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connecter with BooleanArgument found\n"); + return exitCode0; + } + } + + // 1) initial -> true + argument.setValue(true); + if (argument.booleanValue() != true) { + exitCode = 2; + out.println(sErr2 + + "case: unknown -> true\n" + + "error: a returned value != true"); + } + + // 2) true -> false + argument.setValue(false); + if (argument.booleanValue() != false) { + exitCode = 2; + out.println(sErr2 + + "case: true -> false\n" + + "error: a returned value != false\n"); + } + + // 3) false -> false + argument.setValue(false); + if (argument.booleanValue() != false) { + exitCode = 2; + out.println(sErr2 + + "case: false -> false\n" + + "error: a returned value != false"); + } + + // 4) false -> true + argument.setValue(true); + if (argument.booleanValue() != true) { + exitCode = 2; + out.println(sErr2 + + "case: false -> true\n" + + "error: a returned value != true\n"); + } + + // 5) true -> true + argument.setValue(true); + if (argument.booleanValue() != true) { + exitCode = 2; + out.println(sErr2 + + "case: true -> true\n" + + "error: a returned value != true\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001/TestDescription.java new file mode 100644 index 00000000000..99a3d642157 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanArgument/setValue/setvalue001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of a BooleanArgument object. + * The test checks up that results of the method + * com.sun.jdi.connect.Connector.BooleanArgument.setValue() + * complies with specification. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First BooleanArgument is searched among Connectors. + * If no a BooleanArgument is found out the test exits with + * the return value = 95 and a warning message. + * - Under assumption that method booleanValue() works correctly (!!), + * to the value of the BooleanArgument founded, + * which may not have been set or may have an invalid value, + * the sequence of 5 following checks is applied: + * 1) setValue(true); booleanValue() must return true + * 2) setValue(false); booleanValue() must return false + * 3) setValue(false); booleanValue() must return false + * 4) setValue(true); booleanValue() must return true + * 5) setValue(true); booleanValue() must return true + * In case of any check results in a wrong value, + * the test produces the return value 97 and + * a corresponding error message. + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanArgument.setValue.setvalue001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanArgument.setValue.setvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002.java new file mode 100644 index 00000000000..f1bd14421e8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanArgument.setValue; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; + + +/** + * The second test for the implementation of a BooleanArgument object.
    + * + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.BooleanArgument.setValue()
    + * complies with specification.
    + * The test works as follows:
    + *
    + * - Virtual Machine Manager is invoked.
    + * - First BooleanArgument is searched among Connectors.
    + * If no BooleanArgument is found out the test exits with
    + * the return value = 95 and a warning message.
    + * - Under the assumption that the method
    + * BooleanArgument.booleanValue() works correctly (!!),
    + * to the value of the BooleanArgument founded,
    + * which may not have been set or may have an invalid value,
    + * the following check is applied:
    + *
    + * setValue(true); booleanValue() must return true;
    + *
    + * In case of the check results in a wrong value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class setvalue002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.setValue\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.setValue\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.BooleanArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with BooleanArgument found\n"); + return exitCode0; + } + } + + // initial -> false + argument.setValue(false); + if (argument.booleanValue() != false) { + exitCode = 2; + out.println(sErr2 + + "case: initial -> false\n" + + "error: a returned value != false"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002/TestDescription.java new file mode 100644 index 00000000000..960ac3f5917 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/setValue/setvalue002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanArgument/setValue/setvalue002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The second test for the implementation of + * a BooleanArgument object. + * The test checks up that results of the method + * com.sun.jdi.connect.Connector.BooleanArgument.setValue() + * complies with specification. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First BooleanArgument is searched among Connectors. + * If no a BooleanArgument is found out the test exits with + * the return value = 95 and a warning message. + * - Under assumption that method booleanValue() works correctly (!!), + * to the value of the BooleanArgument founded, + * which may not have been set or may have an invalid value, + * the check is applied: + * setValue(false); booleanValue() must return false + * In case of the check results in a wrong value, + * the test produces the return value 97 and + * a corresponding error message. + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanArgument.setValue.setvalue002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanArgument.setValue.setvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001.java new file mode 100644 index 00000000000..853b677db1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanArgument.stringValueOf; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector.BooleanArgument.
    + *
    + * The test checks up that results of the method
    + * Connector.BooleanArgument.stringValueOf(boolean value)
    + * in the package com.sun.jdi.connect
    + * complies with the following statement in its specification:
    + * "Return the string representation of the value parameter."
    + *
    + * In case of the check results in a wrong value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class stringvalueof001 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.stringValueOf\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.stringValueof\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.BooleanArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with BooleanArgument found\n"); + return exitCode0; + } + } + + String sTrue = argument.stringValueOf(true); + String sFalse = argument.stringValueOf(false); + + if (sTrue.equalsIgnoreCase(sFalse)) { + exitCode = 2; + out.println(sErr2 + + "check: stringValueOf(true) != stringValueOf(false)\n" + + "error: strings are equal\n"); + } + + if (sTrue == null) { + exitCode = 2; + out.println(sErr2 + + "check: stringValueOf(true) = 'true'\n" + + "error: a returned value = null\n"); + } + + if (sFalse == null) { + exitCode = 2; + out.println(sErr2 + + "check: stringValueOf(false) = 'false'\n" + + "error: a returned value = null\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001/TestDescription.java new file mode 100644 index 00000000000..3f48a3b7ad8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanArgument/stringValueOf/stringvalueof001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.BooleanArgument. + * The test checks up that results of the method + * Connector.BooleanArgument.stringValueOf(boolean value) + * of the interface com.sun.jdi.connect + * complies with the following statement in its specification: + * "Return the string representation of the value parameter." + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector's argument of the type Connector.BooleanArgument + * is searched among Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - Two String objects are assigned the following values: + * sTrue = argument.stringValueOf(true); + * sFalse = argument.stringValueOf(false); + * - Then the following checks are applied: + * IF sTrue.equalsIgnoreCase(sFalse) + * THEN an error detected + * ELSE the check passed + * IF sTrue == null + * THEN an error detected + * ELSE the check passed + * IF sFalse == null + * THEN an error detected + * ELSE the check passed + * In case of an error the test produces the return value 97 and + * a corresponding error message. + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanArgument.stringValueOf.stringvalueof001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanArgument.stringValueOf.stringvalueof001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002.java new file mode 100644 index 00000000000..8ff262ea8ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanArgument.stringValueOf; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.Argument; +import com.sun.jdi.connect.Connector.BooleanArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector.BooleanArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.BooleanArgument.stringValueOf()
    + * complies with the following statement in its specification:
    + * "Does not set the value of the argument."
    + *
    + * In case of the method does set the value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class stringvalueof002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.stringValueOf\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.BooleanArgument.stringValueOf\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.BooleanArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.BooleanArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with BooleanArgument found\n"); + return exitCode0; + } + } + + String argumentValue; + // 1) + argument.setValue(true); + argumentValue = argument.stringValueOf(true); + if (argument.booleanValue() != true) { + exitCode = 2; + out.println(sErr2 + + "case: stringValueOf(true) doesn't change value true\n" + + "error: argument's value != true\n"); + } + + // 2) + argument.setValue(true); + argumentValue = argument.stringValueOf(false); + if (argument.booleanValue() != true) { + exitCode = 2; + out.println(sErr2 + + "case: stringValueOf(false) doesn't change value true\n" + + "error: argument's value != true\n"); + } + + // 3) + argument.setValue(false); + argumentValue = argument.stringValueOf(true); + if (argument.booleanValue() != false) { + exitCode = 2; + out.println(sErr2 + + "case: stringValueOf(true) doesn't change value false\n" + + "error: a returned value != false\n"); + } + + // 4) + argument.setValue(false); + argumentValue = argument.stringValueOf(false); + if (argument.booleanValue() != false) { + exitCode = 2; + out.println(sErr2 + + "case: stringValueOf(false) doesn't change value false\n" + + "error: a returned value != false\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002/TestDescription.java new file mode 100644 index 00000000000..db7baac54b3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanArgument/stringValueOf/stringvalueof002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.BooleanArgument. + * The test checks up that results of the method + * com.sun.jdi.connect. + * Connector.BooleanArgument.stringValueOf(int value) + * complies with the following statement in its specification: + * "Does not set the value of the argument." + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector's argument of the type Connector.BooleanArgument + * is searched among Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * 1) + * argument.setValue(true); + * argument.stringValueOf(true); + * IF (argument.booleanValue() != true) + * THEN an error detected + * ELSE the check passed + * 2) + * argument.setValue(true); + * argument.stringValueOf(false); + * IF (argument.booleanValue() != true) + * THEN an error detected + * ELSE the check passed + * 3) + * argument.setValue(false); + * argument.stringValueOf(false); + * IF (argument.booleanValue() != false) + * THEN an error detected + * ELSE the check passed + * 4) + * argument.setValue(false); + * argument.stringValueOf(true); + * IF (argument.booleanValue() != false) + * THEN an error detected + * ELSE the check passed + * In case of any error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanArgument.stringValueOf.stringvalueof002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanArgument.stringValueOf.stringvalueof002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java new file mode 100644 index 00000000000..9bedcc54989 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BooleanType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * BooleanType.
    + *
    + * The test checks that for a mirror of a boolean value the casts
    + * from Type to BooleanType and from PrimitiveType to BooleanType
    + * don't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a boolean field and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class booleantype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BooleanType/_itself_/booleantype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new booleantype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BooleanType._itself_.booleantype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......String name = 'bl';"); + String name = "bl"; + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type(); + log2(" PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + + BooleanType booleanType = null; + try { + log2(" checking up on cast: BooleanType booleanType = (BooleanType) type;"); + booleanType = (BooleanType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + try { + log2(" checking up on cast: BooleanType booleanType = (BooleanType) primitiveType;"); + booleanType = (BooleanType) primitiveType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001/TestDescription.java new file mode 100644 index 00000000000..2101fb0aa85 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanType/_itself_/booleantype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BooleanType. + * The test checks that for a mirror of boolean value the casts + * from Type to BooleanType and from PrimitiveType to BooleanType + * don't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.BooleanType._itself_.booleantype001; + * the debuggee program - nsk.jdi.BooleanType._itself_.booleantype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanType._itself_.booleantype001 + * nsk.jdi.BooleanType._itself_.booleantype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanType._itself_.booleantype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001a.java new file mode 100644 index 00000000000..cd2e2fb681e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BooleanType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the booleantype001 JDI test. + */ + +public class booleantype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static boolean bl = false; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001.java new file mode 100644 index 00000000000..75f31d07082 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * BooleanValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.BooleanValue.equals()
    + * complies with its spec.
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static boolean bTrue1 = true;
    + * public static boolean bTrue2 = true;
    + * public static boolean bFalse1 = false;
    + * public static boolean bFalse2 = false;
    + *
    + * which a debugger mirros as :
    + *
    + * BooleanValue bvTrue1;
    + * BooleanValue bvTrue2;
    + * BooleanValue bvFalse1;
    + * BooleanValue bvFalse2;
    + *
    + * the following is true:
    + *
    + * bvTrue1.equals(bvTrue2)
    + * !bvTrue1.equals(bvFalse1)
    + * bvFalse1.equals(bvFalse2)
    + * !bvFalse1.equals(bvTrue1)
    + *
    + * !bvTrue1.equals(IntegerValue i0)
    + * !bvFalse1.equals(IntegerValue i1)
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BooleanValue/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BooleanValue.equals.equals001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("equals001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fTrue1 = execClass.fieldByName("bTrue1"); + Field fTrue2 = execClass.fieldByName("bTrue2"); + Field fFalse1 = execClass.fieldByName("bFalse1"); + Field fFalse2 = execClass.fieldByName("bFalse2"); + + BooleanValue bvTrue1 = (BooleanValue) execClass.getValue(fTrue1); + BooleanValue bvTrue2 = (BooleanValue) execClass.getValue(fTrue2); + BooleanValue bvFalse1 = (BooleanValue) execClass.getValue(fFalse1); + BooleanValue bvFalse2 = (BooleanValue) execClass.getValue(fFalse2); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!bvTrue1.equals(bvTrue2)) + expresult = 1; + break; + + case 1: if (bvTrue1.equals(bvFalse1)) + expresult = 1; + break; + + case 2: if (!bvFalse1.equals(bvFalse2)) + expresult = 1; + break; + + case 3: if (bvFalse1.equals(bvTrue1)) + expresult = 1; + break; + + case 4: IntegerValue i0 = vm.mirrorOf(0); + if (bvTrue1.equals(i0)) + expresult = 1; + break; + + case 5: IntegerValue i1 = vm.mirrorOf(1); + if (bvFalse1.equals(i1)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != 1; check # = " + i2); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..e8bb10d5aa9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanValue/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BooleanValue. + * The test checks up that a result of the method + * com.sun.jdi.BooleanValue.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this BooleanValue + * for equality. + * Returns: + * true if the Object is a BooleanValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.BooleanValue.equals.equals001; + * a debuggee program - nsk.jdi.BooleanValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanValue.equals.equals001 + * nsk.jdi.BooleanValue.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanValue.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001a.java new file mode 100644 index 00000000000..807d6ab82b7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals001a.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the equals001a JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static boolean bTrue1 = true; + public static boolean bTrue2 = true; + public static boolean bFalse1 = false; + public static boolean bFalse2 = false; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * types and when parameter is null.
    + * Analyse of the method executing is performed by PerformComparing + * method.
    + * First parameter of PerformComparing is static field of testedObj,
    + * which is placed onto debugee's side.
    + * + * Second parameter is got from debugee too:
    + * Debugee has array of boundary values of each primitive type, execTest reads
    + * them and calls PerformComparing for each of them.
    + */ +public class equals002 { + + private final static String prefix = "nsk.jdi.BooleanValue.equals."; + private final static String className = "equals002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static ReferenceType refType; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + execTest(); + debugee.quit(); + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + private static void execTest() { + + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("Class '" + debugeeName + "' not found."); + return; + } + + // getting of object to check + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = refType.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = refType.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + List fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + BooleanValue value; + Field fldOtherType; + String msg; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + log.display(""); + msg = "***" + field; + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof BooleanValue) ) { + msg += " is not BooleanValue (skipped)"; + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (BooleanValue )v1; + + // comparing with debugee's fields + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = refType.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = refType.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static boolean PerformComparing(BooleanValue value, Object object ) { + boolean res = true; + String msg = ""; + try { + if ( value.equals(object) ) { + if ( object instanceof BooleanValue ) { + if ( value.value() == ((PrimitiveValue )object).booleanValue() ) { + msg += "--> " + value + " == " + object; + } else { + msg += "##> " + value + " == " + object; + res = false; + } + } + else { + msg += "##> " + value + " == " + object + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if ( object == null ) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if ( object instanceof BooleanValue ) { + if ( value.value() != ((PrimitiveValue )object).booleanValue() ) { + msg += "--> " + value + " != " + object; + } else { + msg += "##> " + value + " != " + object; + res = false; + } + } + else { + msg += "--> " + value + " != " + object; + } + } + + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..25d22e5df5c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanValue/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.BooleanValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this BooleanValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is a BooleanValue and if applying "==" to the + * two mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has boundary values of primitive + * types. Also, case when parameter is considered. + * No exceptions are expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanValue.equals.equals002 + * nsk.jdi.BooleanValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002a.java new file mode 100644 index 00000000000..a579ac6aa81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/equals/equals002a.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BooleanValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * equals002a is deugee's part of the test.
    + * It contains the static fields with boundary values for each primitive type.
    + * ClassToCheck delivers values for first parameter of equals.
    + */ +public class equals002a { + + static ClassToCheck testedObj = new ClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloatMIN", + "cmpIntMAX", + "cmpIntMIN", + "cmpLongMAX", + "cmpLongMIN", + "cmpShortMAX", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class ClassToCheck { + public boolean boolTRUE = true; + public boolean boolFALSE = false; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001.java new file mode 100644 index 00000000000..380c40a30c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * BooleanValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.BooleanValue.hashCode()
    + * complies with its spec.
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static boolean bTrue1 = true;
    + * public static boolean bTrue2 = true;
    + * public static boolean bFalse1 = false;
    + * public static boolean bFalse2 = false;
    + *
    + * which a debugger mirros as :
    + *
    + * BooleanValue bvTrue1;
    + * BooleanValue bvTrue2;
    + * BooleanValue bvFalse1;
    + * BooleanValue bvFalse2;
    + *
    + * the following is true:
    + *
    + * bvTrue1.hashCode() == bvTrue1.hashCode()
    + * bvFalse1.hashCode() == bvFalse1.hashCode()
    + * bvTrue1.hashCode() == bvTrue2.hashCode()
    + * bvFalse1.hashCode() == bvFalse2.hashCode()
    + * bvTrue1.hashCode() != bvFalse1.hashCode()
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BooleanValue/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BooleanValue.hashCode.hashcode001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("hashcode001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fTrue1 = execClass.fieldByName("bTrue1"); + Field fTrue2 = execClass.fieldByName("bTrue2"); + Field fFalse1 = execClass.fieldByName("bFalse1"); + Field fFalse2 = execClass.fieldByName("bFalse2"); + + BooleanValue bvTrue1 = (BooleanValue) execClass.getValue(fTrue1); + BooleanValue bvTrue2 = (BooleanValue) execClass.getValue(fTrue2); + BooleanValue bvFalse1 = (BooleanValue) execClass.getValue(fFalse1); + BooleanValue bvFalse2 = (BooleanValue) execClass.getValue(fFalse2); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (bvTrue1.hashCode() != bvTrue1.hashCode()) + expresult = 1; + break; + + case 1: if (bvFalse1.hashCode() != bvFalse1.hashCode()) + expresult = 1; + break; + + case 2: if (bvTrue1.hashCode() != bvTrue2.hashCode()) + expresult = 1; + break; + + case 3: if (bvFalse1.hashCode() != bvFalse2.hashCode()) + expresult = 1; + break; + + case 4: if (bvTrue1.hashCode() == bvFalse1.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != 1; check # = " + i2); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..e7af7f96e69 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanValue/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BooleanValue. + * The test checks up that a result of the method + * com.sun.jdi.BooleanValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this BooleanValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.BooleanValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.BooleanValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanValue.hashCode.hashcode001 + * nsk.jdi.BooleanValue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanValue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..bf126736629 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/hashCode/hashcode001a.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the hashcode001a JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static boolean bTrue1 = true; + public static boolean bTrue2 = true; + public static boolean bFalse1 = false; + public static boolean bFalse2 = false; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * BooleanValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.BooleanValue.value()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static boolean bTrue1 = true;
    + * public static boolean bFalse1 = false;
    + *
    + * which a debugger mirros as :
    + *
    + * BooleanValue bvTrue1;
    + * BooleanValue bvFalse1;
    + *
    + * the following is true:
    + *
    + * BooleanValue bvTrue.value() == true
    + * BooleanValue bvFalse.value() == false
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BooleanValue/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BooleanValue.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("value001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fTrue1 = execClass.fieldByName("bTrue1"); +// Field fTrue2 = execClass.fieldByName("bTrue2"); + Field fFalse1 = execClass.fieldByName("bFalse1"); +// Field fFalse2 = execClass.fieldByName("bFalse2"); + + BooleanValue bvTrue1 = (BooleanValue) execClass.getValue(fTrue1); +// BooleanValue bvTrue2 = (BooleanValue) execClass.getValue(fTrue2); + BooleanValue bvFalse1 = (BooleanValue) execClass.getValue(fFalse1); +// BooleanValue bvFalse2 = (BooleanValue) execClass.getValue(fFalse2); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (bvTrue1.value() != true) + expresult = 1; + break; + + case 1: if (bvFalse1.value() != false) + expresult = 1; + break; + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != 1; check # = " + i2); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001/TestDescription.java new file mode 100644 index 00000000000..8c2f27c68b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BooleanValue/value/value001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BooleanValue. + * The test checks up that a result of the method + * com.sun.jdi.BooleanValue.value() + * complies with its spec: + * public boolean value() + * Returns this BooleanValue as a boolean. + * Returns: the boolean mirrored by this object. + * The test works as follows: + * A debugger program - nsk.jdi.BooleanValue.value.value001; + * a debuggee program - nsk.jdi.BooleanValue.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BooleanValue.value.value001 + * nsk.jdi.BooleanValue.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BooleanValue.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001a.java new file mode 100644 index 00000000000..e23791558af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanValue/value/value001a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.BooleanValue.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + + //................................................... globals for a debugger + + public static boolean bTrue1 = true; + public static boolean bTrue2 = true; + public static boolean bFalse1 = false; + public static boolean bFalse2 = false; + + //.................................................... + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + debuggee.resume(); + + try { + + // waiting for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // find checked location and create StepEventrequest + EventRequestManager eventRManager = vm.eventRequestManager(); + + log.display("Getting loaded class in debuggee"); + List classes = vm.classesByName(DEBUGGEE_NAME); + checkedClass = (ReferenceType) classes.get(0); + + log.display("Getting reference to main thread"); + Iterator threadIterator = vm.allThreads().iterator(); + while (threadIterator.hasNext()) { + ThreadReference curThread = (ThreadReference) threadIterator.next(); + if (curThread.name().equals("main")) { + checkedThread = curThread; + } + } + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + log.display("Getting reference to method "); + List allMethods = checkedClass.methodsByName("foo"); + try { + checkedMethod = (Method) allMethods.get(0); + } catch (IndexOutOfBoundsException e) { + throw new Failure("No method foo() found for the checked class: " + e); + } + + if (checkedMethod == null) { + throw new Failure("Null reference returned for method foo() of the checked class"); + } + + log.display("Getting reference to field "); + checkedField = checkedClass.fieldByName("counter"); + if (checkedField == null) { + throw new Failure("TEST BUG: unable to find reference to field "); + } + + log.display("Getting all locations"); + List allLineLocations; + try { + allLineLocations = checkedMethod.allLineLocations(); + } catch ( AbsentInformationException e) { + throw new Failure("TEST BUG: caught AbsentInformationException " + e); + } + + log.display("Getting checked location"); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == breakpoint001a.breakpointLineNumber) { + if (checkedLocation != null) { + throw new Failure("TEST BUG: multiple locations on breakpoint line"); + } else { + checkedLocation = curLocation; + } + } + } + if (checkedLocation == null) { + throw new Failure("TEST BUG: incorrect line number of the location in method"); + } + + log.display("Creating BreakpointRequest for the location"); + if ((checkedRequest = eventRManager.createBreakpointRequest(checkedLocation)) == null) { + throw new Failure("TEST BUG: unable to create BreakpointRequest"); + } + + checkedRequest.addThreadFilter(checkedThread); + checkedRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + + switch (checkedRequest.suspendPolicy()) { + case EventRequest.SUSPEND_ALL: + log.display("suspend policy is SUSPEND_ALL"); + break; + case EventRequest.SUSPEND_EVENT_THREAD: + log.display("suspend policy is SUSPEND_EVENT_THREAD"); + break; + case EventRequest.SUSPEND_NONE: + log.display("suspend policy is SUSPEND_NONE"); + break; + default: + log.complain("TEST BUG: Unknown suspend policy!"); + } + + log.display("BreakpointRequest is created for location " + checkedLocation.lineNumber()); + + // define separate thread for handling received events + class EventHandler extends Thread { + public void run() { + // handle events until method invoking completes and all expected events received + while (!methodCompleted || eventsReceived < EXPECTED_EVENTS_COUNT) { + eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (InterruptedException e) { + log.complain("Unexpected InterruptedException while receiving event: " + e); + break; + } + + if (eventSet == null) { + continue; + } + + // handle each event of the event set + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + // handle BreakPointEvent + if (event instanceof BreakpointEvent) { + BreakpointEvent castedEvent = (BreakpointEvent) event; + log.display("Received event is BreakpointEvent:\n " + event); + + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 2: eventRequest is not equal to checked request"); + testFailed = true; + } else { + eventsReceived++; + log.display("Expected BreakpointEvent received: " + eventsReceived + " times"); + } + + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 3: eventThread is not equal to checked thread"); + testFailed = true; + } + + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 4: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + Location eventLocation = castedEvent.location(); + log.display("BreakpointEvent received for location: " + eventLocation.lineNumber()); + + if (!(checkedLocation.equals(eventLocation))) { + log.complain("FAILURE 5: eventLocation is not equal to checked location"); + testFailed = true; + } + + try { + int counterValue = ((IntegerValue)checkedClass.getValue(checkedField)).value(); + log.display("Counter == " + counterValue); + if ( counterValue > oldValue) { + if (!eventThread.isSuspended()) { + log.complain("FAILURE 6: eventThread is not suspended"); + } else { + log.complain("FAILURE 7: BreakpointEvent is generated after code execution"); + + } + testFailed = true; + } + oldValue++; // modify for next event + + } catch (ClassCastException e) { + log.complain("TEST BUG: cannot get value of field"); + testFailed = true; + } + + } + + // ignore each other event + } + + log.display("Resuming event set"); + eventSet.resume(); + } + log.display("eventHandler completed"); + } + } + + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + log.display("Enabling breakpoint request"); + checkedRequest.enable(); + + // force debuggee to invoke method and generate BreakpouintEvents + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // waiting for debuggee finished invoking method + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + methodCompleted = true; + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // Check if all expected BreakpointEvents are received + if (eventsReceived < EXPECTED_EVENTS_COUNT) { + log.display("Too few BreakpointEvents are received: " + eventsReceived); + testFailed = true; + } else if (eventsReceived > EXPECTED_EVENTS_COUNT) { + log.display("Too many BreakpointEvents are received: " + eventsReceived); + testFailed = true; + } else { + log.display("All expected BreakpointEvents are received"); + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + // disable event request to prevent appearance of further events + if (checkedRequest != null && checkedRequest.isEnabled()) { + log.display("Disabling BreakpointEvent request"); + checkedRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint001/TestDescription.java new file mode 100644 index 00000000000..15bc1127b72 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint001/TestDescription.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/BreakpointEvent/_itself_/breakpoint001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises com.sun.jdi.event.BreakpointEvent interface. + * The test checks the following assertions: + * - BreakpointEvent is received by debugger for requested + * location if this location is reached by some executing thread + * in debugged VM; + * - received BreakpointEvent has proper references to: + * debugged VM, + * executed thread, + * related BreakpointRequest, + * checked location. + * - BreakpointEvent is generated before the code at its location + * is executed. + * A debugger class - nsk.jdi.BreakpointEvent._itself_.breakpoint001 ; + * a debuggee class - nsk.jdi.BreakpointEvent._itself_.breakpoint001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger launches and connects to debuggee using the default launching + * connector. Afer command is received from debugge, the debugger + * creates BreakpointRequest on location in method of + * class where field is modified. + * The debugger cleans EventQueue, starts separate thread + * for listening events, enables breakpoint request, sends debuggee command + * and waits for in reply. + * Upon receiving command from debugger, the debuggee invokes + * method. This method updates field of class. + * For each BreakpointEvent received by , all refencies of this + * event ( , , , ) are compared + * with expected values. The current value of field reference + * is compared with expected value. + * After command received from debuggee, debugger notifies + * that method is invoked and waits for + * receives all expected events. If not all events received for + * WAITTIME interval, debugger interrupts thread and + * complains about an error. + * Finally, debugger disables checked request, sends debuggee command from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + // invoke checked method to generate BreakpointEvents + foo(); + + // notify debugger that checked method invoked + pipe.println(COMMAND_DONE); + + // wait for command from debugger and exit + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + return PASSED; + } + + // checked method + static void foo() { + while (counter < LIMIT) { + counter++; // breakpointLineNumber + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint002.java new file mode 100644 index 00000000000..b7d3487f83d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointEvent/_itself_/breakpoint002.java @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointEvent._itself_; + +import com.sun.jdi.AbsentInformationException; +import com.sun.jdi.ClassNotPreparedException; +import com.sun.jdi.ObjectCollectedException; +import com.sun.jdi.Location; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.BreakpointRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.VMMismatchException; +import com.sun.jdi.event.*; + +import java.util.Iterator; +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks up on the JDI interface + * com.sun.jdi.event.BreakpointEvent. + * A debugger + * part of the test creates several BreakpointRequests, + * and then it verifies that appropriate events are generated by + * the target VM. After that the debugger removes the requests by + * deleteAllBreakpoints() call. Finally, the test checks + * that the events corresponding to the deleted requests, are not + * generated by the target VM any more. + */ +public class breakpoint002 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.BreakpointEvent._itself_.breakpoint002t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int BPS_NUM = 4; + static final String COMMAND_RUN[] = { + "run1", "run2", "run3", "run4" + }; + static final int DEBUGGEE_LNS[] = { + 76, 79, 82, 85 + }; + private volatile int eventCount[] = { + 0, 0, 0, 0 + }; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile BreakpointRequest bpRequest[]; + private volatile int tot_res = PASSED; + +// for notification a main thread about received events + private Object gotEvent = new Object(); + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new breakpoint002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "breakpoint002t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + +// Create testing requests + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILED: Method Debugee.classByName() returned null"); + tot_res = FAILED; + return quitDebuggee(); + } + if (createRequests(erManager, rType) == FAILED) { + tot_res = FAILED; + return quitDebuggee(); + } + +// Create a thread listening JDI events + elThread = new EventListener(); + elThread.setPriority(Thread.NORM_PRIORITY + 2); + synchronized(gotEvent) { + elThread.start(); + +// Check all requested BreakpointEvents + for (int i=0; i 0) { + log.complain("TEST FAILED: got more than one breakpoint event for bp "+i); + return FAILED; + } + } + log.display("\nTEST PASSED: no events corresponding to the deleted BreakpointRequests"); + + } + +// Finish the test + return tot_res; + } + + private int createRequests(EventRequestManager erManager, + ReferenceType rType) { + List loctns; + + bpRequest = + new BreakpointRequest[BPS_NUM]; + for (int i=0; i + * - addThreadFilter,
    + * - addInstanceFilter
    + * methods with null argument value. + * In any cases NullPointerException is expected. + */ +public class filters001 { + + private final static String prefix = "nsk.jdi.BreakpointRequest._bounds_."; + private final static String debuggerName = prefix + "filters001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String classToCheck = prefix + filters001a.classToCheck; + private static String indent = " : "; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + filters001 thisTest = new filters001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType debugeeRef = debugee.classByName(debugeeName); + ReferenceType checkedClsRef = debugee.classByName(classToCheck); + + display(""); + display(">>>" + filters001a.objName); + display("----------------------"); + Field field = debugeeRef.fieldByName(filters001a.objName); + Value val = debugeeRef.getValue(field); + + BreakpointRequest request = debugee.setBreakpoint(checkedClsRef, + filters001a.brkptMethodName, + filters001a.brkptLineNumber); + + display(""); + addThreadFilter(request, (ThreadReference )val); + display(""); + addInstanceFilter(request, (ObjectReference )val); + + display(""); + debugee.quit(); + } + + private void addThreadFilter(BreakpointRequest request, ThreadReference thread) { + + display("addThreadFilter :ThreadReference> null"); + try { + request.addThreadFilter(thread); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addInstanceFilter(BreakpointRequest request, + ObjectReference instance) { + + display("addInstanceFilter :ObjectReference> null"); + + try { + request.addInstanceFilter(instance); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001/TestDescription.java new file mode 100644 index 00000000000..cee61e10abf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/_bounds_/filters001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the methods + * com.sun.jdi.request.BreakpointRequest.addThreadFilter(ThreadReference) + * com.sun.jdi.request.BreakpointRequest.addInstanceFilter(ObjectReference) + * correctly work for the boundary value of parameter and throw described + * exceptions. + * The test check up this methods with argument value. In any cases + * NullPointerException is expected. + * COMMENTS: + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest._bounds_.filters001 + * nsk.jdi.BreakpointRequest._bounds_.filters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest._bounds_.filters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001a.java new file mode 100644 index 00000000000..ee4300cfbe7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/_bounds_/filters001a.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.BreakpointRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * filters001a is deugee's part of the test. + */ +public class filters001a { + + static String classToCheck = "filters001b"; + static String objName = "testedObjNULL"; + static filters001b testedObjNULL = null; + + static final String brkptMethodName = "run"; + static final int brkptLineNumber = 75; + + public static void main (String argv[]) { + + // create temporary object to load class + filters001b tmp = new filters001b("tmp"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class filters001b extends Thread { + + static Log log; + filters001b(String nameObj) { + setName(nameObj); + } + + public void run() { + synchronized (log) { // brkptLineNumber + log.display(getName() + "::Breakpoint is reached"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001.java new file mode 100644 index 00000000000..4038829a430 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * BreakpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.BreakpointRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * in which the currently executing instance is + * the object specified. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a special array with three Object instances, + * and two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a BreakpointRequest + * within the method in the class TestClass + * whose array element instances #0 and #1 + * will be calling by the thread1 and the thread2 accordinly, + * - invokes addInstanceFilter() on array element #0 for the thread1 + * and #2 for the thread2, + * thus restricting the breakpoint event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter001a"; + return new instancefilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter001aTestClass"; + + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "BreakpointRequest1"; + String property2 = "BreakpointRequest2"; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2BreakpointRequest (thread1, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_ALL, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + ((BreakpointRequest) eventRequest1).addInstanceFilter(instance); + + eventRequest2 = setting2BreakpointRequest (thread2, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_ALL, property2); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(2); + + ((BreakpointRequest) eventRequest2).addInstanceFilter(instance); + + display("......waiting for BreakpointEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof BreakpointEvent)) { + setFailedStatus("ERROR: new event is not BreakpointEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new BreakpointEvent with propety 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) { + try { + display("......setting up a breakpoint:"); + display(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + display(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001/TestDescription.java new file mode 100644 index 00000000000..f580dae4b92 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter001; + * the debuggee program - nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter001 + * nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001a.java new file mode 100644 index 00000000000..3569a345786 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter001a.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter001 JDI test. + */ + +public class instancefilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter001a thread1 = null; + static Threadinstancefilter001a thread2 = null; + + static instancefilter001aTestClass objTC[] = { new instancefilter001aTestClass(), new instancefilter001aTestClass(), new instancefilter001aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter001a("thread1"); + thread2 = new Threadinstancefilter001a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter001a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter001a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter001aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java new file mode 100644 index 00000000000..cbc2b30f939 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java @@ -0,0 +1,559 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * BreakpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.BreakpointRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a BreakpointRequest and enables it,
    + * - invokes the method addInstanceFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addInstanceFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addInstanceFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter002a"; + + private String testedClassName = + "nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "BreakpointRequest1"; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2BreakpointRequest (null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((BreakpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" no InvalidRequestStateException expected"); + ((BreakpointRequest) eventRequest1).addInstanceFilter(instance); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((BreakpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + log2(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingBreakpointRequest() : " + e); + log3(" BreakpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002/TestDescription.java new file mode 100644 index 00000000000..bc68e5d40a0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter002; + * the debuggee program - nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter002 + * nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002a.java new file mode 100644 index 00000000000..4cdd50a131b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter002 JDI test. + */ + +public class instancefilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter002a thread1 = null; + + static instancefilter002aTestClass objTC[] = { new instancefilter002aTestClass(), new instancefilter002aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter002a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter002a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter002a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter002aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java new file mode 100644 index 00000000000..b7863ebe6e3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * BreakpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.BreakpointRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: UnsupportedOperationException - if the target
    + * virtual machine does not support this operation.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger creates
    + * a BreakpointRequest and if addInstanceFilter() is not supported,
    + * invokes the method on the request expecting
    + * to catch UnsupportedOperationException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter003a"; + + private String testedClassName = + "nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "BreakpointRequest1"; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2BreakpointRequest (null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + if ( vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == true :: test cancelled"); + } else { + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" UnsupportedOperationException expected"); + ((BreakpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no UnsupportedOperationException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" UnsupportedOperationException "); + } + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + log2(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingBreakpointRequest() : " + e); + log3(" BreakpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003/TestDescription.java new file mode 100644 index 00000000000..da42c200065 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter003; + * the debuggee program - nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter003 + * nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003a.java new file mode 100644 index 00000000000..9039c7bb08e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter003 JDI test. + */ + +public class instancefilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter003a thread1 = null; + + static instancefilter003aTestClass objTC[] = { new instancefilter003aTestClass(), new instancefilter003aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter003a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter003a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter003a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter003aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004.java new file mode 100644 index 00000000000..922371eeff0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * BreakpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.BreakpointRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same BreakpointRequest object. + * There are two BreakpointRequests to check as follows: + * (1) For BreakpointRequest2, both invocations are with different + * ObjectReferences restricting one Breakpoint event to two objects. + * The test expects no Breakpoint event will be received. + * (2) For BreakpointRequest1, both invocations are with the same + * ObjectReference restricting one Breakpoint event to one object. + * The test expects this Breakpoint event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, + * an array with three instances of the TestClass containing a method + * calling by both threads, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up BreakpointRequests 1&2 within the method + * in the class TestClass which will be calling by both threads, + * - restricts the BreakpointRequest1 to the tread1 and + * to the array elements #0 & #0 calling only within thread1, + * - restricts the BreakpointRequest2 to the thread2 and + * the array elements #0 & #1 calling within thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter004a"; + return new instancefilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter004aTestClass"; + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "BreakpointRequest1"; + String property2 = "BreakpointRequest2"; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + + ObjectReference instance1 = null; + ObjectReference instance2 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2BreakpointRequest (thread1, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2BreakpointRequest (thread2, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_ALL, property2); + + instance1 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + instance2 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(1); + + ((BreakpointRequest) eventRequest1).addInstanceFilter(instance1); + ((BreakpointRequest) eventRequest1).addInstanceFilter(instance1); + ((BreakpointRequest) eventRequest2).addInstanceFilter(instance1); + ((BreakpointRequest) eventRequest2).addInstanceFilter(instance2); + + display("......waiting for BreakpointEvent in expected thread"); + BreakpointEvent newEvent = (BreakpointEvent)eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + EventRequest newEventRequest = newEvent.request(); + if ( newEventRequest.equals(eventRequest1) ) { + display(" received expected event: " + newEvent); + + ThreadReference newEventThread = newEvent.thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) { + try { + display("......setting up a breakpoint:"); + display(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + display(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up BreakpointRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004/TestDescription.java new file mode 100644 index 00000000000..30615643833 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same BreakpointRequest object. + * There are two BreakpointRequests to check as follows: + * (1) For BreakpointRequest2, both invocations are with different + * ObjectReferences restricting one Breakpoint event to two objects. + * The test expects no Breakpoint event will be received. + * (2) For BreakpointRequest1, both invocations are with the same + * ObjectReference restricting one Breakpoint event to one object. + * The test expects this Breakpoint event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter004; + * the debuggee program - nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter004 + * nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.addInstanceFilter.instancefilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004a.java new file mode 100644 index 00000000000..b30041b0ac1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter004a.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter004 JDI test. + */ + +public class instancefilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter004a thread1 = null; + static Threadinstancefilter004a thread2 = null; + + static instancefilter004aTestClass objTC[] = { new instancefilter004aTestClass(), new instancefilter004aTestClass(), new instancefilter004aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter004a("thread1"); + thread2 = new Threadinstancefilter004a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter004a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter004a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter004aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001.java new file mode 100644 index 00000000000..7205550f17c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * BreakpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.BreakpointRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * + * The test works as follows. + * + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a BreakpointRequest within the method + * in the class TestClass which will be calling by both threads, + * - restricts the breakpoint event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class threadfilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter001a"; + return new threadfilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter001aTestClass"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + ThreadReference thread1 = null; + String thread1Name = "thread1"; + String property1 = "BreakpointRequest1"; + String methodName = "method"; + String bpLineName = "breakpointLine"; + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2BreakpointRequest (thread1, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for BreakpointEvent in tested thread"); + + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + if ( !(newEvent instanceof BreakpointEvent)) { + setFailedStatus("ERROR: new event is not BreakpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new BreakpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ThreadReference thr = ((BreakpointEvent)newEvent).thread(); + if (!thr.equals(thread1)) { + setFailedStatus("The BreakpointEvent occured in unexpected thread: " + thr); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) { + try { + display("......setting up a breakpoint:"); + display(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + display(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001/TestDescription.java new file mode 100644 index 00000000000..54348cd43fd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter001; + * the debuggee program - nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter001 + * nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001a.java new file mode 100644 index 00000000000..81625b6b02f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter001a.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter001 JDI test. + */ + +public class threadfilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadthreadfilter001a thread1 = null; + static Threadthreadfilter001a thread2 = null; + + static threadfilter001aTestClass objTC = new threadfilter001aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadthreadfilter001a("thread1"); + thread2 = new Threadthreadfilter001a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadthreadfilter001a extends Thread { + + String tName = null; + int tNumber; + + public Threadthreadfilter001a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class threadfilter001aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java new file mode 100644 index 00000000000..79ccc79dd38 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * BreakpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.BreakpointRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a BreakpointRequest and enables it,
    + * - invokes the method addThreadFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addThreadFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addThreadFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class threadfilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new threadfilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter002a"; + + private String testedClassName = + "nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "BreakpointRequest1"; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2BreakpointRequest (null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property1); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((BreakpointRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no InvalidRequestStateException expected"); + ((BreakpointRequest)eventRequest1).addThreadFilter(thread1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((BreakpointRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + log2(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingBreakpointRequest() : " + e); + log3(" BreakpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002/TestDescription.java new file mode 100644 index 00000000000..2bc4574d36c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter002; + * the debuggee program - nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter002 + * nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002a.java new file mode 100644 index 00000000000..ed85733431a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002a.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter002 JDI test. + */ + +public class threadfilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadthreadfilter002a thread1 = null; + + static threadfilter002aTestClass objTC = new threadfilter002aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadthreadfilter002a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadthreadfilter002a extends Thread { + + String tName = null; + int tNumber; + + public Threadthreadfilter002a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class threadfilter002aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java new file mode 100644 index 00000000000..6ea1964f821 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java @@ -0,0 +1,554 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * BreakpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.BreakpointRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Restricts the events generated by this request
    + * to those in the given thread.
    + * The cases to test include three thread's states:
    + * not started, running, dead.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a BreakpointRequest1 and
    + * invokes the method addThreadFilter(tread1) on the request1,
    + * - creates a BreakpointRequest2, starts the thread2, and
    + * invokes the method addThreadFilter(thread) on the request2,
    + * - creates a BreakpointRequest3, waits the thread2 to die, and
    + * invokes the method addThreadFilter(thread) on the request3.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class threadfilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new threadfilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter003a"; + + private String testedClassName = + "nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "BreakpointRequest1"; + String property2 = "BreakpointRequest2"; + String property3 = "BreakpointRequest3"; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2BreakpointRequest (null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property1); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((BreakpointRequest)eventRequest1).addThreadFilter(thread1); + log2(" no Exception"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + + break; + + case 1: + eventRequest2 = setting2BreakpointRequest (null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property2); + + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((BreakpointRequest)eventRequest2).addThreadFilter(thread1); + log2(" no Exception"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2BreakpointRequest (null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property3); + + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((BreakpointRequest)eventRequest3).addThreadFilter(thread1); + log2(" no Exception"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + log2(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingBreakpointRequest() : " + e); + log3(" BreakpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003/TestDescription.java new file mode 100644 index 00000000000..4a44c724144 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include three thread's states: not started, running, dead. + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter003; + * the debuggee program - nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter003 + * nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003a.java new file mode 100644 index 00000000000..5246ec81122 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003a.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter003 JDI test. + */ + +public class threadfilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadthreadfilter003a thread1 = null; + + static threadfilter003aTestClass objTC = new threadfilter003aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadthreadfilter003a("thread1"); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();"); + methodForCommunication(); + } + break; + + case 2: + try { + thread1.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class Threadthreadfilter003a extends Thread { + + public Threadthreadfilter003a(String threadName) { + super(threadName); + } + + public void run() { + log1(" 'run': enter "); + + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + log1(" 'run': exit "); + } + return; + } + } + +} + +class threadfilter003aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004.java new file mode 100644 index 00000000000..e4db04d0eb8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * BreakpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.BreakpointRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same BreakpointRequest object. + * There are two BreakpointRequests to check as follows: + * (1) For BreakpointRequest2, both invocations are with different + * ThreadReferences restricting one Breakpoint event to two threads. + * The test expects no Breakpoint event will be received. + * (2) For BreakpointRequest1, both invocations are with the same + * ThreadReference restricting one Breakpoint event to one thread. + * The test expects this Breakpoint event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up BreakpointRequests 1&2 within the method + * in the class TestClass which will be calling by both threads, + * - restricts the BreakpointRequest1 only to thread1, + * - restricts the BreakpointRequest2 to both thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class threadfilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter004a"; + return new threadfilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter004aTestClass"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "BreakpointRequest1"; + String property2 = "BreakpointRequest2"; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2BreakpointRequest (thread1, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2BreakpointRequest (thread1, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_ALL, property2); + + ((BreakpointRequest) eventRequest1).addThreadFilter(thread1); + ((BreakpointRequest) eventRequest2).addThreadFilter(thread2); + + display("......waiting for BreakpointEvent in tested thread1"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof BreakpointEvent)) { + setFailedStatus("ERROR: new event is not BreakpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new BreakpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + EventRequest newEventRequest = newEvent.request(); + if (!newEventRequest.equals(eventRequest1) ) { + setFailedStatus("The BreakpointEvent occured not for eventRequest1"); + } + + ThreadReference thr = ((BreakpointEvent)newEvent).thread(); + if (!thr.equals(thread1)) { + setFailedStatus("The BreakpointEvent occured in unexpected thread: " + thr); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) { + try { + display("......setting up a breakpoint:"); + display(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + display(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up BreakpointRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004/TestDescription.java new file mode 100644 index 00000000000..bab4f929e32 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same BreakpointRequest object. + * There are two BreakpointRequests to check as follows: + * (1) For BreakpointRequest2, both invocations are with different + * ThreadReferences restricting one Breakpoint event to two threads. + * The test expects no Breakpoint event will be received. + * (2) For BreakpointRequest1, both invocations are with the same + * ThreadReference restricting one Breakpoint event to one thread. + * The test expects this Breakpoint event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter004; + * the debuggee program - nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter004 + * nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.addThreadFilter.threadfilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004a.java new file mode 100644 index 00000000000..eee1d5a5cf4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter004a.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter004 JDI test. + */ + +public class threadfilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadthreadfilter004a thread1 = null; + static Threadthreadfilter004a thread2 = null; + + static threadfilter004aTestClass objTC = new threadfilter004aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadthreadfilter004a("thread1"); + thread2 = new Threadthreadfilter004a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadthreadfilter004a extends Thread { + + String tName = null; + int tNumber; + + public Threadthreadfilter004a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class threadfilter004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java new file mode 100644 index 00000000000..df1281910d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * BreakpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.BreakpointRequest.location()
    + * complies with its spec.
    + *
    + * The test checks if a Location object, an argument of the method
    + * EventRequestManager.createBreakpointRequest(Location),
    + * is equal to one returned by the method BreakpointRequest.location()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a BreakpointRequest and gets Location object location1,
    + * - gets Location object location2 with the method
    + * BreakpointRequest.location(),
    + * - compares the Location objects.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class location001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/BreakpointRequest/location/location001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new location001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.BreakpointRequest.location.location001a"; + + private String testedClassName = + "nsk.jdi.BreakpointRequest.location.TestClass"; + + Location location1 = null; + Location location2 = null; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "BreakpointRequest1"; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + log2(".....setting up BreakpointRequest and getting Location object location1"); + eventRequest1 = setting2BreakpointRequest (null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property1); + + log2("......getting: location2 = ((BreakpointRequest) eventRequest1).location();"); + location2 = ((BreakpointRequest) eventRequest1).location(); + + log2(" checking up on equality of location1 and location2"); + if ( !location1.equals(location2) ) { + testExitCode = FAILED; + log3("ERROR: Location objects are not equal"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private BreakpointRequest setting2BreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + location1 = loc; + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + if (thread != null) + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + log2(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingBreakpointRequest() : " + e); + log3(" BreakpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001/TestDescription.java new file mode 100644 index 00000000000..267eaff0b83 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/BreakpointRequest/location/location001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * BreakpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.BreakpointRequest.location() + * complies with its spec: + * public Location location() + * Returns the location of the requested breakpoint. + * Specified by: location in interface Locatable + * Returns: the Location where this breakpoint has been set. + * The test checks if a Location object, + * an argument of the method EventRequestManager.createBreakpointRequest(Location), + * is equal to one returned by the method BreakpointRequest.location() + * The test works as follows: + * The debugger program - nsk.jdi.BreakpointRequest.location.location001; + * the debuggee program - nsk.jdi.BreakpointRequest.location.location001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.BreakpointRequest.location.location001 + * nsk.jdi.BreakpointRequest.location.location001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.BreakpointRequest.location.location001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001a.java new file mode 100644 index 00000000000..e65ddad3066 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001a.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.BreakpointRequest.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the location001 JDI test. + */ + +public class location001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadlocation001a thread1 = null; + + static TestClass objTC = new TestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadlocation001a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadlocation001a extends Thread { + + String tName = null; + int tNumber; + + public Threadlocation001a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class TestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java new file mode 100644 index 00000000000..d1a51c118c4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ByteType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ByteType.
    + *
    + * The test checks that for a mirror of a byte value the casts
    + * from Type to ByteType and from PrimitiveType to ByteType
    + * don't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a byte field and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class bytetype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ByteType/_itself_/bytetype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new bytetype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ByteType._itself_.bytetype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......String name = 'bt';"); + String name = "bt"; + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type(); + log2(" PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + + ByteType byteType = null; + try { + log2(" checking up on cast: ByteType booleanType = (ByteType) type;"); + byteType = (ByteType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + try { + log2(" checking up on cast: ByteType byteType = (ByteType) primitiveType;"); + byteType = (ByteType) primitiveType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001/TestDescription.java new file mode 100644 index 00000000000..8b45ef22042 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ByteType/_itself_/bytetype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ByteType. + * The test checks that for a mirror of byte value the casts + * from Type to ByteType and from PrimitiveType to ByteType + * don't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.ByteType._itself_.bytetype001; + * the debuggee program - nsk.jdi.ByteType._itself_.bytetype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ByteType._itself_.bytetype001 + * nsk.jdi.ByteType._itself_.bytetype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ByteType._itself_.bytetype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001a.java new file mode 100644 index 00000000000..5ec3c1613eb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ByteType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the bytetype001 JDI test. + */ + +public class bytetype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static byte bt = 0; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001.java new file mode 100644 index 00000000000..8c897a85cdd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ByteValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + + +public class compareto001 { + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ByteValue.compareTo"; + private final static String className = ".compareto001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + private static Value objectValue; + private static List fieldList; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return; + } + + // getting of object to check + Field field = debuggeeClass.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + + objectValue = debuggeeClass.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = debuggeeClass.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = debuggeeClass.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitiveValues = (ArrayReference)arrValue; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + ByteValue value; + Field fldOtherType; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof ByteValue) ) { + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (ByteValue )v1; + + // comparing with debuggee's fields + display("Checking compateTo(Object object) method for ByteValue: " + value); + + for (int j = 0; j < primitiveValues.length(); j++) { + arrValue = primitiveValues.getValue(j); + + fldOtherType = debuggeeClass.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = debuggeeClass.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + + } + + //--------------------------------------------------------- test specific methods + + + private static boolean PerformComparing(ByteValue value, Object object ) { + boolean result = true; + + // assertion [ x.compareTo(x) == 0 ] + if (value.compareTo(value) != 0) { + complain("Failed assertion [ x.compareTo(x) == 0 ] for value: " + value.toString()); + result = false; + } + + if (object instanceof ByteValue) { + ByteValue byteObject = (ByteValue)object; + try { + // assertion [ x.compareTo(y) == 0 <==> x.equals(y) ] + if ( ((value.equals(object)) && (value.compareTo(byteObject) != 0)) || + (!(value.equals(object)) && (value.compareTo(byteObject) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (x.equals(y) == true) ] \n\t" + + "where 'x' is ByteValue: " + value + " and 'y' is ByteValue : " + byteObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(byteObject) + "\n\t" + + "result of (x.equals(y)): " + value.equals(object) ); + result = false; + } + + // assertion [ x.compareTo(y) == 0 <==> y.compareTo(x) == 0 ] + if ( ((value.compareTo(byteObject) == 0) && (byteObject.compareTo(value) != 0)) || + ((value.compareTo(byteObject) != 0) && (byteObject.compareTo(value) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0) ] \n\t" + + "where 'x' is ByteValue: " + value + " and 'y' is ByteValue : " + byteObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(byteObject) + "\n\t" + + "result of (y.compareTo(x)): " + byteObject.compareTo(value) ); + result = false; + } + if (value.compareTo(byteObject) != 0) { + // assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] + if (value.compareTo(byteObject) != -(byteObject.compareTo(value))) { + complain("Failed assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] \n\t" + + "where 'x' is ByteValue: " + value + " and 'y' is ByteValue : " + byteObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(byteObject) + "\n\t" + + "result of (y.compareTo(x)): " + byteObject.compareTo(value) ); + result = false; + } + } + + // assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] + if (value.compareTo(byteObject) > 0) { + ByteValue lessValue = FindLessByteValue(byteObject); + if (lessValue != null) { + if (value.compareTo(lessValue) <= 0) { + complain("Failed assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] \n\t" + + "where 'x' is ByteValue: " + value + " , 'y' is ByteValue : " + byteObject + " , 'z' is ByteValue : " + lessValue + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(byteObject) + "\n\t" + + "result of (y.compareTo(z)): " + byteObject.compareTo(lessValue) + "\n\t" + + "result of (x.compareTo(z)): " + value.compareTo(lessValue) ); + result = false; + } + } + } + + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "ByteValue: " + value + " and ByteValue argument: " + object); + result = false; + } + + } else if (object == null) { + try { + value.compareTo(null); + complain("Does not throw expected NullPointerException when comparing \n\t" + + "ByteValue: " + value + " and null argument"); + result = false; + } catch (NullPointerException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "ByteValue: " + value + " and null argument"); + result = false; + } + } else { + try { + value.compareTo((ByteValue)object); + complain("Does not throw expected ClassCastException when comparing \n\t" + + "ByteValue: " + value + " and argument: " + object); + result = false; + } catch (ClassCastException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "ByteValue: " + value + " and argument: " + object); + result = false; + } + } + + return result; + } + + /** + * This function searches the static fieldList - the list of mirrored + * fields of debuggee's compareto001aClassToCheck class. Search is aimed + * to find another ByteValue field which is less then method's argument via + * compareTo method. + */ + + private static ByteValue FindLessByteValue (ByteValue currentValue) { + ByteValue result = null; + + for (int i = 0; i < fieldList.size(); i++ ) { + + Field field = (Field )fieldList.get(i); + ByteValue newValue = (ByteValue)((ObjectReference )objectValue).getValue(field); + + if (currentValue.compareTo(newValue) > 0) { + result = newValue; + break; + } + } + return result; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001/TestDescription.java new file mode 100644 index 00000000000..6a04b76379f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ByteValue/compareTo/compareto001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the compareTo(Object o) method of com.sun.jdi.ByteValue + * interface. This method is inherited from java.lang.Comparable interface. + * The test checks the following assertions which imply from spec for + * Comparable.compareTo(Object o): + * - (x.compareTo(y) == 0) is identical to (x.equals(y) == true); + * - (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0); + * - if (x.compareTo(y) == i) then (y.compareTo(x) == -i); + * - if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0); + * - if an argument is null, then NullPointerException is thrown; + * - if an argument is not of ByteValue type, then a ClassCastException is thrown. + * where 'x', 'y' and 'z' denote ByteValue object. + * The debugger program - nsk.jdi.ByteValue.compareto.compareto001; + * the debuggee program - nsk.jdi.ByteValue.compareto.compareto001a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * Then the debugger gets a list of byte fields of debuggee's object of + * compareto001aClassToCheck type. For every field a mirror of ByteValue type + * is created and the assertions are checked. A various values for comparison + * are got from values of mirrors of debuggee's static fields. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ByteValue.compareTo.compareto001 + * nsk.jdi.ByteValue.compareTo.compareto001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ByteValue.compareTo.compareto001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001a.java new file mode 100644 index 00000000000..83a4a36b51b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/compareTo/compareto001a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ByteValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class compareto001a { + + //----------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + static compareto001aClassToCheck testedObj = new compareto001aClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + pipe.println(compareto001.SIGNAL_READY); +// receiveSignal(compareto001.SIGNAL_GO); + + receiveSignal(compareto001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class compareto001aClassToCheck { + public byte byteMAX = Byte.MAX_VALUE; + public byte byte1 = 1; + public byte byte0 = 0; + public byte byte_1 = -1; + public byte byteMIN = Byte.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001.java new file mode 100644 index 00000000000..fcdd191261c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ByteValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ByteValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ByteValue.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static byte plus1_1 = +1;
    + * public static byte plus1_2 = +1;
    + * public static byte minus1 = -1;
    + * public static short shortplus1 = +1;
    + *
    + * which a debugger mirros as :
    + *
    + * ByteValue bvplus1_1;
    + * ByteValue bvplus1_2;
    + * ByteValue bvminus1;
    + * ShortValue svplus1;
    + *
    + * the following is true:
    + *
    + * bvplus1_1 == bvplus1_2
    + * bvplus1_1 != bvminus1
    + * bvplus1_1 != svplus1
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ByteValue/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ByteValue.equals.equals001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("equals001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fbplus1_1 = execClass.fieldByName("plus1_1"); + Field fbplus1_2 = execClass.fieldByName("plus1_2"); + Field fbminus1 = execClass.fieldByName("minus1"); + Field fsplus1 = execClass.fieldByName("shortplus1"); + + ByteValue bvplus1_1 = (ByteValue) execClass.getValue(fbplus1_1); + ByteValue bvplus1_2 = (ByteValue) execClass.getValue(fbplus1_2); + ByteValue bvminus1 = (ByteValue) execClass.getValue(fbminus1); + ShortValue svplus1 = (ShortValue) execClass.getValue(fsplus1); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!bvplus1_1.equals(bvplus1_2)) + expresult = 1; + break; + + case 1: if (bvplus1_1.equals(bvminus1)) + expresult = 1; + break; + + case 2: if (bvplus1_1.equals(svplus1)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..a24924e809c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ByteValue/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ByteValue. + * The test checks up that a result of the method + * com.sun.jdi.ByteValue.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this ByteValue for equality. + * Returns: true if the Object is a ByteValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.ByteValue.equals.equals001; + * a debuggee program - nsk.jdi.ByteValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ByteValue.equals.equals001 + * nsk.jdi.ByteValue.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ByteValue.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001a.java new file mode 100644 index 00000000000..668c59a5faa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals001a.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ByteValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the equals001a JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static byte smallest = Byte.MIN_VALUE; +// public static byte zero = 0; +// public static byte largest = Byte.MAX_VALUE; + + public static byte plus1_1 = +1; + public static byte plus1_2 = +1; + public static byte minus1 = -1; + + public static short shortplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * types and when parameter is null.
    + * Analyse of the method executing is performed by PerformComparing + * method.
    + * First parameter of PerformComparing is static field of testedObj,
    + * which is placed onto debugee's side.
    + * + * Second parameter is got from debugee too:
    + * Debugee has array of boundary values of each primitive type, execTest reads
    + * them and calls PerformComparing for each of them.
    + */ +public class equals002 { + + private final static String prefix = "nsk.jdi.ByteValue.equals."; + private final static String className = "equals002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static ReferenceType refType; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + execTest(); + debugee.quit(); + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + private static void execTest() { + + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("Class '" + debugeeName + "' not found."); + return; + } + + // getting of object to check + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = refType.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = refType.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + List fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + ByteValue value; + Field fldOtherType; + String msg; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + log.display(""); + msg = "***" + field; + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof ByteValue) ) { + msg += " is not ByteValue (skipped)"; + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (ByteValue )v1; + + // comparing with debugee's fields + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = refType.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = refType.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static boolean PerformComparing(ByteValue value, Object object ) { + boolean res = true; + String msg = ""; + try { + if ( value.equals(object) ) { + if ( object instanceof ByteValue ) { + if ( value.value() == ((PrimitiveValue )object).byteValue() ) { + msg += "--> " + value + " == " + object; + } else { + msg += "##> " + value + " == " + object; + res = false; + } + } + else { + msg += "##> " + value + " == " + object + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if ( object == null ) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if ( object instanceof ByteValue ) { + if ( value.value() != ((PrimitiveValue )object).byteValue() ) { + msg += "--> " + value + " != " + object; + } else { + msg += "##> " + value + " != " + object; + res = false; + } + } + else { + msg += "--> " + value + " != " + object; + } + } + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..79b8d8eaf09 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ByteValue/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.ByteValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this ByteValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is a ByteValue and if applying "==" to the + * two mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has boundary values of primitive + * types. Also, case when parameter is considered. + * No exceptions are expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ByteValue.equals.equals002 + * nsk.jdi.ByteValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ByteValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002a.java new file mode 100644 index 00000000000..76d08d8aead --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/equals/equals002a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ByteValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * equals002a is deugee's part of the test.
    + * It contains the static fields with boundary values for each primitive type.
    + * ClassToCheck delivers values for first parameter of equals.
    + */ +public class equals002a { + + static ClassToCheck testedObj = new ClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class ClassToCheck { + public byte byteMAX = Byte.MAX_VALUE; + public byte byte1 = 1; + public byte byte0 = 0; + public byte byte_1 = -1; + public byte byteMIN = Byte.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001.java new file mode 100644 index 00000000000..5bc3013eb0e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ByteValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ByteValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ByteValue.hashCode()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static byte plus1_1 = +1;
    + * public static byte plus1_2 = +1;
    + *
    + * which a debugger mirros as :
    + *
    + * ByteValue bvplus1_1;
    + * ByteValue bvplus1_2;
    + *
    + * the following is true:
    + *
    + * bvplus1_1.hashCode() == bvplus1_1.hashCode()
    + * bvplus1_1.hashCode() == bvplus1_2.hashCode()
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ByteValue/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ByteValue.hashCode.hashcode001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("hashcode001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fbplus1_1 = execClass.fieldByName("plus1_1"); + Field fbplus1_2 = execClass.fieldByName("plus1_2"); +// Field fbminus1 = execClass.fieldByName("minus1"); +// Field fsplus1 = execClass.fieldByName("shortplus1"); + + ByteValue bvplus1_1 = (ByteValue) execClass.getValue(fbplus1_1); + ByteValue bvplus1_2 = (ByteValue) execClass.getValue(fbplus1_2); +// ByteValue bvminus1 = (ByteValue) execClass.getValue(fbminus1); +// ShortValue svplus1 = (ShortValue) execClass.getValue(fsplus1); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (bvplus1_1.hashCode() != bvplus1_1.hashCode()) + expresult = 1; + break; + + case 1: if (bvplus1_1.hashCode() != bvplus1_2.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..b984a70b85f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ByteValue/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ByteValue. + * The test checks up that a result of the method + * com.sun.jdi.ByteValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this BooleanValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.ByteValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.ByteValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ByteValue.hashCode.hashcode001 + * nsk.jdi.ByteValue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ByteValue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..09ede4f5572 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/hashCode/hashcode001a.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ByteValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the hashcode001a JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static byte smallest = Byte.MIN_VALUE; +// public static byte zero = 0; +// public static byte largest = Byte.MAX_VALUE; + + public static byte plus1_1 = +1; + public static byte plus1_2 = +1; +// public static byte minus1 = -1; + +// public static short shortplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ByteValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ByteValue.value()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static byte smallest = Byte.MIN_VALUE;
    + * public static byte zero = 0;
    + * public static byte largest = Byte.MAX_VALUE;
    + *
    + * which a debugger mirros as :
    + *
    + * ByteValue bvsmallest;
    + * ByteValue bvzero;
    + * ByteValue bvlargest;
    + *
    + * the following is true:
    + *
    + * bvsmallest.value() == Byte.MIN_VALUE
    + * bvzero.value() == 0
    + * bvlargest.value() == Byte.MAX_VALUE
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ByteValue/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ByteValue.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("value001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fbsmallest = execClass.fieldByName("smallest"); + Field fbzero = execClass.fieldByName("zero"); + Field fblargest = execClass.fieldByName("largest"); + + ByteValue bvsmallest = (ByteValue) execClass.getValue(fbsmallest); + ByteValue bvzero = (ByteValue) execClass.getValue(fbzero); + ByteValue bvlargest = (ByteValue) execClass.getValue(fblargest); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (bvsmallest.value() != Byte.MIN_VALUE) + expresult = 1; + break; + + case 1: if (bvzero.value() != 0) + expresult = 1; + break; + + case 2: if (bvlargest.value() != Byte.MAX_VALUE) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001/TestDescription.java new file mode 100644 index 00000000000..3159c31cb55 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ByteValue/value/value001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ByteValue. + * The test checks up that a result of the method + * com.sun.jdi.ByteValue.value() + * complies with its spec: + * public byte value() + * Returns this ByteValue as a boolean. + * Returns: the byte mirrored by this object. + * The test works as follows: + * A debugger program - nsk.jdi.ByteValue.value.value001; + * a debuggee program - nsk.jdi.ByteValue.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ByteValue.value.value001 + * nsk.jdi.ByteValue.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ByteValue.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001a.java new file mode 100644 index 00000000000..746ab944934 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteValue/value/value001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ByteValue.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static byte smallest = Byte.MIN_VALUE; + public static byte zero = 0; + public static byte largest = Byte.MAX_VALUE; + +// public static byte plus1_1 = +1; +// public static byte plus1_2 = +1; +// public static byte minus1 = -1; + +// public static short shortplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * CharType.
    + *
    + * The test checks that for a mirror of a char value the casts
    + * from Type to CharType and from PrimitiveType to CharType
    + * don't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a char field and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class chartype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/CharType/_itself_/chartype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new chartype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.CharType._itself_.chartype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......String name = 'ch';"); + String name = "ch"; + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type(); + log2(" PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + + CharType charType = null; + try { + log2(" checking up on cast: CharType charType = (CharType) type;"); + charType = (CharType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + try { + log2(" checking up on cast: CharType charType = (CharType) primitiveType;"); + charType = (CharType) primitiveType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001/TestDescription.java new file mode 100644 index 00000000000..8940efe6df8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/CharType/_itself_/chartype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * CharType. + * The test checks that for a mirror of char value the casts + * from Type to CharType and from PrimitiveType to CharType + * don't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.CharType._itself_.chartype001; + * the debuggee program - nsk.jdi.CharType._itself_.chartype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.CharType._itself_.chartype001 + * nsk.jdi.CharType._itself_.chartype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.CharType._itself_.chartype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001a.java new file mode 100644 index 00000000000..fee21d2c652 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.CharType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the chartype001 JDI test. + */ + +public class chartype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static char ch = 0; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001.java new file mode 100644 index 00000000000..f78a2b79af8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.CharValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + + +public class compareto001 { + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.CharValue.compareTo"; + private final static String className = ".compareto001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + private static Value objectValue; + private static List fieldList; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return; + } + + // getting of object to check + Field field = debuggeeClass.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + + objectValue = debuggeeClass.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = debuggeeClass.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = debuggeeClass.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitiveValues = (ArrayReference)arrValue; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + CharValue value; + Field fldOtherType; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof CharValue) ) { + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (CharValue)v1; + + // comparing with debuggee's fields + display("Checking compateTo(Object object) method for CharValue: " + value); + + for (int j = 0; j < primitiveValues.length(); j++) { + arrValue = primitiveValues.getValue(j); + + fldOtherType = debuggeeClass.fieldByName(((StringReference)arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = debuggeeClass.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + + } + + //--------------------------------------------------------- test specific methods + + + private static boolean PerformComparing(CharValue value, Object object ) { + boolean result = true; + + // assertion [ x.compareTo(x) == 0 ] + if (value.compareTo(value) != 0) { + complain("Failed assertion [ x.compareTo(x) == 0 ] for value: " + value.toString()); + result = false; + } + + if (object instanceof CharValue) { + CharValue charObject = (CharValue)object; + try { + // assertion [ x.compareTo(y) == 0 <==> x.equals(y) ] + if ( ((value.equals(object)) && (value.compareTo(charObject) != 0)) || + (!(value.equals(object)) && (value.compareTo(charObject) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (x.equals(y) == true) ] \n\t" + + "where 'x' is CharValue: " + value + " and 'y' is CharValue : " + charObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(charObject) + "\n\t" + + "result of (x.equals(y)): " + value.equals(object) ); + result = false; + } + + // assertion [ x.compareTo(y) == 0 <==> y.compareTo(x) == 0 ] + if ( ((value.compareTo(charObject) == 0) && (charObject.compareTo(value) != 0)) || + ((value.compareTo(charObject) != 0) && (charObject.compareTo(value) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0) ] \n\t" + + "where 'x' is CharValue: " + value + " and 'y' is CharValue : " + charObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(charObject) + "\n\t" + + "result of (y.compareTo(x)): " + charObject.compareTo(value) ); + result = false; + } + if (value.compareTo(charObject) != 0) { + // assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] + if (value.compareTo(charObject) != -(charObject.compareTo(value))) { + complain("Failed assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] \n\t" + + "where 'x' is CharValue: " + value + " and 'y' is CharValue : " + charObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(charObject) + "\n\t" + + "result of (y.compareTo(x)): " + charObject.compareTo(value) ); + result = false; + } + } + + // assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] + if (value.compareTo(charObject) > 0) { + CharValue lessValue = FindLessCharValue(charObject); + if (lessValue != null) { + if (value.compareTo(lessValue) <= 0) { + complain("Failed assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] \n\t" + + "where 'x' is CharValue: " + value + " , 'y' is CharValue : " + charObject + " , 'z' is CharValue : " + lessValue + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(charObject) + "\n\t" + + "result of (y.compareTo(z)): " + charObject.compareTo(lessValue) + "\n\t" + + "result of (x.compareTo(z)): " + value.compareTo(lessValue) ); + result = false; + } + } + } + + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "CharValue: " + value + " and CharValue argument: " + object); + result = false; + } + + } else if (object == null) { + try { + value.compareTo(null); + complain("Does not throw expected NullPointerException when comparing \n\t" + + "CharValue: " + value + " and null argument"); + result = false; + } catch (NullPointerException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "CharValue: " + value + " and null argument"); + result = false; + } + } else { + try { + value.compareTo((CharValue)object); + complain("Does not throw expected ClassCastException when comparing \n\t" + + "CharValue: " + value + " and argument: " + object); + result = false; + } catch (ClassCastException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "CharValue: " + value + " and argument: " + object); + result = false; + } + } + + return result; + } + + /** + * This function searches the static fieldList - the list of mirrored + * fields of debuggee's compareto001aClassToCheck class. Search is aimed + * to find another CharValue field which is less then method's argument via + * compareTo method. + */ + + private static CharValue FindLessCharValue (CharValue currentValue) { + CharValue result = null; + + for (int i = 0; i < fieldList.size(); i++ ) { + + Field field = (Field )fieldList.get(i); + CharValue newValue = (CharValue)((ObjectReference )objectValue).getValue(field); + + if (currentValue.compareTo(newValue) > 0) { + result = newValue; + break; + } + } + return result; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001/TestDescription.java new file mode 100644 index 00000000000..0d8a1c093c7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/CharValue/compareTo/compareto001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the compareTo(Object o) method of com.sun.jdi.CharValue + * interface. This method is inherited from java.lang.Comparable interface. + * The test checks the following assertions which imply from spec for + * Comparable.compareTo(Object o): + * - (x.compareTo(y) == 0) is identical to (x.equals(y) == true); + * - (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0); + * - if (x.compareTo(y) == i) then (y.compareTo(x) == -i); + * - if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0); + * - if an argument is null, then NullPointerException is thrown; + * - if an argument is not of CharValue type, then a ClassCastException is thrown. + * where 'x', 'y' and 'z' denote CharValue object. + * The debugger program - nsk.jdi.CharValue.compareto.compareto001; + * the debuggee program - nsk.jdi.CharValue.compareto.compareto001a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * Then the debugger gets a list of char fields of debuggee's object of + * compareto001aClassToCheck type. For every field a mirror of CharValue type + * is created and the assertions are checked. A various values for comparison + * are got from values of mirrors of debuggee's static fields. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.CharValue.compareTo.compareto001 + * nsk.jdi.CharValue.compareTo.compareto001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.CharValue.compareTo.compareto001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001a.java new file mode 100644 index 00000000000..5134b53fb4b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/compareTo/compareto001a.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.CharValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class compareto001a { + + //----------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + static compareto001aClassToCheck testedObj = new compareto001aClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpChar0 = 'a'; + static char cmpChar1 = '%'; + static char cmpChar2 = '\t'; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + pipe.println(compareto001.SIGNAL_READY); +// receiveSignal(compareto001.SIGNAL_GO); + + receiveSignal(compareto001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class compareto001aClassToCheck { + public char charMAX = Character.MAX_VALUE; + public char char0 = 'a'; + public char char1 = '%'; + public char char2 = '\t'; + public char charMIN = Character.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001.java new file mode 100644 index 00000000000..6ce2363cd02 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.CharValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * CharValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.CharValue.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static char char_a_1 = 'a';
    + * public static char char_a_2 = 'a';
    + * public static char char_b = 'b';
    + * public static short shortchar_a_3 = (short) 'a';
    + *
    + * which a debugger mirros as :
    + *
    + * CharValue cvchar_a_1;
    + * CharValue cvchar_a_2;
    + * CharValue cvchar_b;
    + * ShortValue svchar_a_3;
    + *
    + * the following is true:
    + *
    + * cvchar_a_1 == cvchar_a_2
    + * cvchar_a_1 != cvchar_b
    + * cvchar_a_1 != svchar_a_3
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/CharValue/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.CharValue.equals.equals001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("equals001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fcchar_a_1 = execClass.fieldByName("char_a_1"); + Field fcchar_a_2 = execClass.fieldByName("char_a_2"); + Field fcchar_b = execClass.fieldByName("char_b"); + Field fschar_a_3 = execClass.fieldByName("shortchar_a_3"); + + CharValue cvchar_a_1 = (CharValue) execClass.getValue(fcchar_a_1); + CharValue cvchar_a_2 = (CharValue) execClass.getValue(fcchar_a_2); + CharValue cvchar_b = (CharValue) execClass.getValue(fcchar_b); + ShortValue svchar_a_3 = (ShortValue) execClass.getValue(fschar_a_3); + + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!cvchar_a_1.equals(cvchar_a_2)) + expresult = 1; + break; + + case 1: if (cvchar_a_1.equals(cvchar_b)) + expresult = 1; + break; + + case 2: if (cvchar_a_1.equals(svchar_a_3)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..1fb9507dc3c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/CharValue/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * CharValue. + * The test checks up that a result of the method + * com.sun.jdi.CharValue.equals() + * complies with its specification: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this CharValue for equality. + * Returns: true if the Object is a CharValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.CharValue.equals.equals001; + * a debuggee program - nsk.jdi.CharValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.CharValue.equals.equals001 + * nsk.jdi.CharValue.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.CharValue.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001a.java new file mode 100644 index 00000000000..7a6c1d501f9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals001a.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.CharValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001a JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static char smallest = Character.MIN_VALUE; +// public static char largest = Character.MAX_VALUE; + + public static char char_a_1 = 'a'; + public static char char_a_2 = 'a'; + public static char char_b = 'b'; + public static short shortchar_a_3 = (short) 'a'; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * types and when parameter is null.
    + * Analyse of the method executing is performed by PerformComparing + * method.
    + * First parameter of PerformComparing is static field of testedObj,
    + * which is placed onto debugee's side.
    + * + * Second parameter is got from debugee too:
    + * Debugee has array of boundary values of each primitive type, execTest reads
    + * them and calls PerformComparing for each of them.
    + */ +public class equals002 { + + private final static String prefix = "nsk.jdi.CharValue.equals."; + private final static String className = "equals002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static ReferenceType refType; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + execTest(); + debugee.quit(); + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + private static void execTest() { + + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("Class '" + debugeeName + "' not found."); + return; + } + + // getting of object to check + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = refType.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = refType.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + List fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + CharValue value; + Field fldOtherType; + String msg; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + log.display(""); + msg = "***" + field; + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof CharValue) ) { + msg += " is not CharValue (skipped)"; + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (CharValue )v1; + + // comparing with debugee's fields + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = refType.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = refType.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static boolean PerformComparing(CharValue value, Object object ) { + boolean res = true; + String msg = ""; + try { + if ( value.equals(object) ) { + if ( object instanceof CharValue ) { + if ( value.value() == ((PrimitiveValue )object).charValue() ) { + msg += "--> " + value + " == " + object; + } else { + msg += "##> " + value + " == " + object; + res = false; + } + } + else { + msg += "##> " + value + " == " + object + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if ( object == null ) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if ( object instanceof CharValue ) { + if ( value.value() != ((PrimitiveValue )object).charValue() ) { + msg += "--> " + value + " != " + object; + } else { + msg += "##> " + value + " != " + object; + res = false; + } + } + else { + msg += "--> " + value + " != " + object; + } + } + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..7ede6f98428 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/CharValue/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.CharValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this CharValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is a CharValue and if applying "==" to the two + * mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has boundary values of primitive + * types. Also, case when parameter is considered. + * No exceptions are expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.CharValue.equals.equals002 + * nsk.jdi.CharValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.CharValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002a.java new file mode 100644 index 00000000000..91e8a63522c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/equals/equals002a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.CharValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * equals002a is deugee's part of the test.
    + * It contains the static fields with boundary values for each primitive type.
    + * ClassToCheck delivers values for first parameter of equals.
    + */ +public class equals002a { + + static ClassToCheck testedObj = new ClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class ClassToCheck { + public char charMAX = Character.MAX_VALUE; + public char charMIN = Character.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001.java new file mode 100644 index 00000000000..94de260db43 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.CharValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * CharValue.
    + *
    + * The test checks up that results of the method
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static char char_a_1 = 'a';
    + * public static char char_a_2 = 'a';
    + * public static char char_smallest = Character.MIN_VALUE;
    + *
    + * which a debugger mirros as :
    + *
    + * CharValue cvchar_a_1;
    + * CharValue cvchar_a_2;
    + * CharValue cvchar_smallest;
    + *
    + * the following is true:
    + *
    + * cvchar_smallest == cvchar_smallest
    + * cvchar_a_1 == cvchar_a_2
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/CharValue/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.CharValue.hashCode.hashcode001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("hashcode001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fcchar_smallest = execClass.fieldByName("smallest"); + Field fcchar_a_1 = execClass.fieldByName("char_a_1"); + Field fcchar_a_2 = execClass.fieldByName("char_a_2"); + + CharValue cvchar_smallest = (CharValue) execClass.getValue(fcchar_smallest); + CharValue cvchar_a_1 = (CharValue) execClass.getValue(fcchar_a_1); + CharValue cvchar_a_2 = (CharValue) execClass.getValue(fcchar_a_2); + + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!cvchar_smallest.equals(cvchar_smallest)) + expresult = 1; + break; + + case 1: if (!cvchar_a_1.equals(cvchar_a_2)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..132dcaefcb0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/CharValue/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * CharValue. + * The test checks up that a result of the method + * com.sun.jdi.CharValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this CharValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.CharValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.CharValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.CharValue.hashCode.hashcode001 + * nsk.jdi.CharValue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.CharValue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..a31d47bd7df --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/hashCode/hashcode001a.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.CharValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001a JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static char smallest = Character.MIN_VALUE; +// public static char largest = Character.MAX_VALUE; + + public static char char_a_1 = 'a'; + public static char char_a_2 = 'a'; +// public static char char_b = 'b'; +// public static short shortchar_a_3 = (short) 'a'; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * CharValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.CharValue.value()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static char smallest = Character.MIN_VALUE;
    + * public static char largest = Character.MAX_VALUE;
    + *
    + * which a debugger mirros as :
    + *
    + * CharValue cvchar_smallest;
    + * CharValue cvchar_largest;
    + *
    + * the following is true:
    + *
    + * cvchar_smallest.value() == Character.MIN_VALUE
    + * cvchar_largest.value() == Character.MAX_VALUE
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/CharValue/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.CharValue.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("value001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fcchar_smallest = execClass.fieldByName("smallest"); + Field fcchar_largest = execClass.fieldByName("largest"); + + CharValue cvchar_smallest = + (CharValue) execClass.getValue(fcchar_smallest); + CharValue cvchar_largest = + (CharValue) execClass.getValue(fcchar_largest); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (cvchar_smallest.value() != Character.MIN_VALUE) + expresult = 1; + break; + + case 1: if (cvchar_largest.value() != Character.MAX_VALUE) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001/TestDescription.java new file mode 100644 index 00000000000..de6d8a7a2c7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/CharValue/value/value001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * CharValue. + * The test checks up that a result of the method + * com.sun.jdi.CharValue.value() + * complies with its specification: + * public char value() + * Returns this CharValue as a char. + * Returns: the char mirrored by this object. + * The test works as follows: + * A debugger program - nsk.jdi.CharValue.value.value001; + * a debuggee program - nsk.jdi.CharValue.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.CharValue.value.value001 + * nsk.jdi.CharValue.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.CharValue.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001a.java new file mode 100644 index 00000000000..fb386ef3903 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharValue/value/value001a.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.CharValue.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static char smallest = Character.MIN_VALUE; + public static char largest = Character.MAX_VALUE; + +// public static char char_a_1 = 'a'; +// public static char char_a_2 = 'a'; +// public static char char_b = 'b'; +// public static short shortchar_a_3 = (short) 'a'; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ClassLoader.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassLoader.definedClasses()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * The list has length 0 if no types have been defined by
    + * this classloader.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a ClassLoader object and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class definedclasses001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new definedclasses001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassLoaderReference.definedClasses.definedclasses001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String ClassLoaderObjName = "classLoader"; + + log2("......getting: Value val = debuggeeClass.getValue(debuggeeClass.fieldByName(ClassLoaderObjName));"); + Value val = debuggeeClass.getValue(debuggeeClass.fieldByName(ClassLoaderObjName)); + + log2("......getting: ClassLoaderReference clRef = (ClassLoaderReference) val;"); + ClassLoaderReference clRef = (ClassLoaderReference) val; + + log2("......getting: List definedClasses = clRef.definedClasses();"); + List definedClasses = clRef.definedClasses(); + log2("......checking up on definedClasses.size() : 0 is expected"); + if (definedClasses.size() != 0) { + log3("ERROR: definedClasses.size() != 0"); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001/TestDescription.java new file mode 100644 index 00000000000..520e7e5f233 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassLoader. + * The test checks up that a result of the method + * com.sun.jdi.ClassLoaderReference.definedClasses() + * complies with its spec: + * public List definedClasses() + * Returns a list of all loaded classes that were defined by this class loader. + * No ordering of this list guaranteed. + * The returned list will include reference types loaded at least to + * the point of preparation and types (like array) for which preparation is not defined. + * Returns: + * a List of ReferenceType objects mirroring types loaded by this class loader. + * The list has length 0 if no types have been defined by this classloader. + * The test checks up on the assertion: + * The list has length 0 if no types have been defined by this classloader. + * The test works as follows: + * The debugger program - nsk.jdi.ClassLoaderReference.definedClasses.definedclasses001; + * the debuggee program - nsk.jdi.ClassLoaderReference.definedClasses.definedclasses001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test fixed due to test RFE: + * 4842009 TEST_RFE: Incorrect package name in two JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassLoaderReference.definedClasses.definedclasses001 + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001a.java new file mode 100644 index 00000000000..371b489b832 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.net.URLClassLoader; +import java.net.URL; + +/** + * This class is used as debuggee application for the definedclasses001 JDI test. + */ + +public class definedclasses001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static ClassLoader classLoader = null; + + static String urlString = "http://download.java.net/java/jdk10/docs/api/overview-summary.html"; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + try { + URL[] url = { new URL(urlString) } ; + classLoader = new URLClassLoader(url); + } catch ( Exception e ) { + log1("Exception : " + e); + } + + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002.java new file mode 100644 index 00000000000..87d32c47765 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class definedclasses002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ClassLoaderReference.definedClasses."; + private final static String className = "definedclasses002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + display("Getting ClassLoaderReference of debuggee's class."); + ClassLoaderReference classLoader = debuggeeClass.classLoader(); + if (classLoader == null) { + complain("classLoader() method returned null for debuggee's ReferenceType."); + exitStatus = Consts.TEST_FAILED; + } else { + display("Getting definedClasses list."); + Iterator definedClasses = classLoader.definedClasses().iterator(); + boolean found0 = false; + boolean found1 = false; + boolean found2 = false; + display("Searching for debuggee's ReferenceType in the list..."); + while (definedClasses.hasNext()) { + ReferenceType refType = (ReferenceType)definedClasses.next(); + if (refType.equals(debuggeeClass)) { + display("definedclasses002a ClassType is found in definedClasses() list of ClassLoaderReference mirror."); + found0 = true; + } else if (refType instanceof ArrayType) { + Type compType; + try { + compType = ((ArrayType)refType).componentType(); + if (compType instanceof ClassType && ((ReferenceType)compType).equals(debuggeeClass)) { + display("definedclasses002a[] ArrayType is found in definedClasses() list of ClassLoaderReference mirror."); + found1 = true; + } else if (compType instanceof ArrayType) { + compType = ((ArrayType)compType).componentType(); + if (compType instanceof ClassType && ((ReferenceType)compType).equals(debuggeeClass)) { + display("definedclasses002a[][] ArrayType is found in definedClasses() list of ClassLoaderReference mirror."); + found2 = true; + } + } + } catch (ClassNotLoadedException e) { + throw new Failure("Unexpected ClassNotLoadedException while getting componentType() of : " + refType); + } + + } + } + if (!found0) { + complain("definedclasses002a ReferenceType is NOT found in definedClasses() list of ClassLoaderReference mirror."); + exitStatus = Consts.TEST_FAILED; + } + if (!found1) { + complain("definedclasses002a[] ArrayType is NOT found in definedClasses() list of ClassLoaderReference mirror."); + exitStatus = Consts.TEST_FAILED; + } + if (!found2) { + complain("definedclasses002a[][] ArrayType is NOT found in definedClasses() list of ClassLoaderReference mirror."); + exitStatus = Consts.TEST_FAILED; + } + } + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002/TestDescription.java new file mode 100644 index 00000000000..3e7fd78aef0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that an implementation of the + * com.sun.jdi.ClassLoaderReference.definedClasses method conforms + * with its spec. + * The test verifies an assertion: + * public List definedClasses() + * Returns a list of all loaded classes that were defined by this class + * loader. No ordering of this list guaranteed. + * The returned list will include reference types loaded at least to the + * point of preparation and types (like array) for which preparation is + * not defined. + * The test consists of: + * debugger - nsk.jdi.ClassLoaderReference.definedClasses.definedclasses002 + * debuggee - nsk.jdi.ClassLoaderReference.definedClasses.definedclasses002a + * The main method of debuggee class defines local variables of single- and + * two-dimensional array of 'definedclasses002a' type. The debugger gets + * a ClassLoaderReference of debuggee class loader. The tests fails if + * either debuggee class reference or array type references are not found + * in the list returned by definedClasses() method. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassLoaderReference.definedClasses.definedclasses002 + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002a.java new file mode 100644 index 00000000000..3adf36a44f5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses002a.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged applcation of the test. + */ +public class definedclasses002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + definedclasses002a[] arr1 = {}; + definedclasses002a[][] arr2 = {arr1}; + + try { + pipe.println(definedclasses002.SIGNAL_READY); + + receiveSignal(definedclasses002.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(exitStatus + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003.java new file mode 100644 index 00000000000..f9ba74ac466 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class definedclasses003 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ClassLoaderReference.definedClasses."; + private final static String className = "definedclasses003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String classLoaderName = prefix + "fields002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + while (true) { + Field classField = debuggeeClass.fieldByName(classFieldName); + if ( classField == null) { + complain("Checked field is not found in the debuggee: " + classFieldName); + exitStatus = Consts.TEST_FAILED; + break; + } + + Value classValue = debuggeeClass.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + complain("Unexpected exception while getting ClassObjectReference : " + e.getMessage()); + exitStatus = Consts.TEST_FAILED; + break; + } + + ReferenceType refType1 = classObjRef.reflectedType(); + if (!refType1.isPrepared()) { + complain("isPrepared() returned false for " + refType1); + exitStatus = Consts.TEST_FAILED; + break; + } else { + display("isPrepared() returned true for " + refType1); + } + + display("Getting ClassLoaderReference of ReferenceType: " + refType1 ); + ClassLoaderReference classLoader = refType1.classLoader(); + if (classLoader == null) { + complain("classLoader() method returned null for ReferenceType: " + refType1); + exitStatus = Consts.TEST_FAILED; + break; + } + + display("Getting definedClasses list."); + Iterator definedClasses = classLoader.definedClasses().iterator(); + boolean found = false; + display("Searching in the list for ReferenceType : " + refType1); + while (definedClasses.hasNext()) { + ReferenceType refType = (ReferenceType)definedClasses.next(); + if (refType.equals(refType1)) { + found = true; + } else { + complain("Unexpected ReferenceType : " + refType + "\n\t is found in definedClasses() list of " + classLoaderName + " mirror."); + exitStatus = Consts.TEST_FAILED; + } + } + + if (found) { + display("ReferenceType : " + refType1 + "\n\t is found in definedClasses() list of " + classLoaderName + " mirror."); + } else { + complain("ReferenceType : " + refType1 + "\n\t is NOT found in definedClasses() list of " + classLoaderName + " mirror."); + exitStatus = Consts.TEST_FAILED; + } + + break; + } + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/TestDescription.java new file mode 100644 index 00000000000..370e9b29fe5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * COMMENTS: + * The test checks up that an implementation of the + * com.sun.jdi.ClassLoaderReference.definedClasses method conforms + * with its spec. + * The test verifies an assertion: + * public List definedClasses() + * Returns a list of all loaded classes that were defined by this class + * loader. No ordering of this list guaranteed. + * The returned list will include reference types loaded at least to the + * point of preparation and types (like array) for which preparation is + * not defined. + * The test consists of: + * debugger application - definedclasses003, + * debuggee application - definedclasses003a, + * custom-loaded class in the debuggee - definedclasses003b. + * All classes belong to 'nsk.jdi.ClassLoaderReference.definedClasses' package. + * The 'definedclasses003b' class is loaded in debuggee by custom + * 'definedclasses003aClassLoader' loader via invocation of Class.forName method. + * The debugger gets ClassLoaderReference of custom class loader. The test fails if + * reference for 'definedclasses003b' class is not found in list returned by + * definedClasses() method or there is reference to another class in the list. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassLoaderReference.definedClasses.definedclasses003 + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/loadclass/definedclasses003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/loadclass/definedclasses003b.java new file mode 100644 index 00000000000..58a33a4af3c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/loadclass/definedclasses003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +/** + * This class is loaded by definedclasses003aClassLoader . + */ +class definedclasses003b { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/loadclass/definedclasses003c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/loadclass/definedclasses003c.java new file mode 100644 index 00000000000..9b471749433 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003/loadclass/definedclasses003c.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +/** + * This class should not be loaded by definedclasses003aClassLoader . + */ +class definedclasses003c { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003a.java new file mode 100644 index 00000000000..5fd16fd24a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses003a.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * The debugged applcation of the test. + */ +public class definedclasses003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + private final static String prefix = "nsk.jdi.ClassLoaderReference.definedClasses."; + private final static String checkedClassName = prefix + "definedclasses003b"; + static definedclasses003aClassLoader customClassLoader; + static Class loadedClass; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) throws ClassNotFoundException { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + String checkedClassDir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + customClassLoader = new definedclasses003aClassLoader(checkedClassDir); + + loadedClass = Class.forName(checkedClassName, true, customClassLoader); + + // ensure that class was loaded by custom class loader + if (!(loadedClass.getClassLoader() instanceof definedclasses003aClassLoader)) { + throw new Failure("Default system loader was used to load class " + checkedClassName); + } + + display ("Checked class loaded: " + checkedClassName); + + pipe.println(definedclasses003.SIGNAL_READY); + + receiveSignal(definedclasses003.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +/** + * Custom class loader. + */ +class definedclasses003aClassLoader extends ClassLoader { + + private String classPath; + + public definedclasses003aClassLoader(String classPath) { + super(definedclasses003aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + protected synchronized Class findClass(String name) throws ClassNotFoundException { + String classFileName = classPath + "/" + name.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(name, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004.java new file mode 100644 index 00000000000..00b41dc9e51 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class definedclasses004 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ClassLoaderReference.definedClasses."; + private final static String className = "definedclasses004"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + display("Getting ClassLoaderReference of class : " + debuggeeName); + ClassLoaderReference classLoader = debuggeeClass.classLoader(); + if (classLoader == null) { + complain("classLoader() method returned null for ReferenceType mirror of : " + debuggeeName); + exitStatus = Consts.TEST_FAILED; + } else { + display("Getting definedClasses() list of : " + classLoader ); + Iterator definedClasses = classLoader.definedClasses().iterator(); + display("Checking isPrepared() result for ReferenceType's in the list..."); + int count = 0; + while (definedClasses.hasNext()) { + ReferenceType refType = (ReferenceType)definedClasses.next(); + count++; + if (!(refType instanceof ArrayType)) { + if (!refType.isPrepared()) { + complain("isPrepared() returned false for : " + refType); + exitStatus = Consts.TEST_FAILED; + } + } + } + display("Total number of items in definedClasses() list : " + count); + } + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004/TestDescription.java new file mode 100644 index 00000000000..b0717970a36 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that an implementation of the + * com.sun.jdi.ClassLoaderReference.definedClasses method conforms + * with its spec. + * The test verifies an assertion: + * public List definedClasses() + * Returns a list of all loaded classes that were defined by this class + * loader. No ordering of this list guaranteed. + * The returned list will include reference types loaded at least to the + * point of preparation and types (like array) for which preparation is + * not defined. + * The test consists of: + * debugger application - definedclasses004, + * debuggee application - definedclasses004a, + * custom-loaded class in the debuggee - definedclasses004b. + * All classes belong to 'nsk.jdi.ClassLoaderReference.definedClasses' package. + * The debugger gets ClassLoaderReference of debuggee class loader. + * The test fails if isPrepared() method returns false for any + * ReferenceType item in the list returned by definedClasses() method. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassLoaderReference.definedClasses.definedclasses004 + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004a.java new file mode 100644 index 00000000000..cd34e80b536 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses004a.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged applcation of the test. + */ +public class definedclasses004a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + pipe.println(definedclasses004.SIGNAL_READY); + + receiveSignal(definedclasses004.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(exitStatus + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005.java new file mode 100644 index 00000000000..f7f9f84536b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class definedclasses005 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ClassLoaderReference.definedClasses."; + private final static String className = "definedclasses005"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String classLoaderName = prefix + "fields002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + while (true) { + Field classField = debuggeeClass.fieldByName(classFieldName); + if ( classField == null) { + complain("Checked field is not found in the debuggee: " + classFieldName); + exitStatus = Consts.TEST_FAILED; + break; + } + + Value classValue = debuggeeClass.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + complain("Unexpected exception while getting ClassObjectReference : " + e.getMessage()); + exitStatus = Consts.TEST_FAILED; + break; + } + + ReferenceType refType1 = classObjRef.reflectedType(); + display("isPrepared() returned " + refType1.isPrepared() + " for " + refType1); + + display("Getting ClassLoaderReference of ReferenceType: " + refType1 ); + ClassLoaderReference classLoader = refType1.classLoader(); + if (classLoader == null) { + complain("classLoader() method returned null for ReferenceType: " + refType1); + exitStatus = Consts.TEST_FAILED; + break; + } + + display("Getting definedClasses list."); + Iterator definedClasses = classLoader.definedClasses().iterator(); + display("Checking returned list..."); + while (definedClasses.hasNext()) { + ReferenceType refType = (ReferenceType)definedClasses.next(); + if (refType.equals(refType1)) { + if (refType.isPrepared()) { + display("isPrepared() returned true for " + refType); + } else { + complain("Not-prepared ReferenceType : " + refType + "\n\t is found in definedClasses() list of " + classLoaderName + " mirror."); + exitStatus = Consts.TEST_FAILED; + } + } else { + complain("Unexpected ReferenceType : " + refType + "\n\t is found in definedClasses() list of " + classLoaderName + " mirror."); + exitStatus = Consts.TEST_FAILED; + } + } + break; + } + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/TestDescription.java new file mode 100644 index 00000000000..825ae938354 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that an implementation of the + * com.sun.jdi.ClassLoaderReference.definedClasses method conforms + * with its spec. + * The test verifies an assertion: + * public List definedClasses() + * Returns a list of all loaded classes that were defined by this class + * loader. No ordering of this list guaranteed. + * The returned list will include reference types loaded at least to the + * point of preparation and types (like array) for which preparation is + * not defined. + * The test consists of: + * debugger application - definedclasses005, + * debuggee application - definedclasses005a, + * custom-loaded class in the debuggee - definedclasses005b. + * All classes belong to 'nsk.jdi.ClassLoaderReference.definedClasses' package. + * The 'definedclasses005b' class is loaded in debuggee by custom + * 'definedclasses005aClassLoader' loader until a preparation point. + * The debugger gets ClassLoaderReference of custom class loader. The test fails + * if reference for 'definedclasses005b' class is found in list returned by + * definedClasses() method. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassLoaderReference.definedClasses.definedclasses005 + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses005a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassLoaderReference.definedClasses.definedclasses005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/loadclass/definedclasses005b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/loadclass/definedclasses005b.java new file mode 100644 index 00000000000..04ed757e9db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005/loadclass/definedclasses005b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +/** + * This class is loaded by definedclasses005aClassLoader until preparation. + */ +class definedclasses005b { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005a.java new file mode 100644 index 00000000000..65dbc756f1b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses005a.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.definedClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * The debugged applcation of the test. + */ +public class definedclasses005a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + private final static String prefix = "nsk.jdi.ClassLoaderReference.definedClasses."; + private final static String checkedClassName = prefix + "definedclasses005b"; + static definedclasses005aClassLoader customClassLoader; + static Class loadedClass; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) throws ClassNotFoundException { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + String checkedClassDir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + customClassLoader = new definedclasses005aClassLoader(checkedClassDir); + + loadedClass = customClassLoader.preloadClass(checkedClassName); + + // ensure that class was loaded by custom class loader + if (!(loadedClass.getClassLoader() instanceof definedclasses005aClassLoader)) { + throw new Failure("Default system loader was used to load class " + checkedClassName); + } + + display ("Checked class loaded but not prepared: " + checkedClassName); + + pipe.println(definedclasses005.SIGNAL_READY); + + receiveSignal(definedclasses005.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +/** + * Custom class loader. + */ +class definedclasses005aClassLoader extends ClassLoader { + + private String classPath; + + public definedclasses005aClassLoader(String classPath) { + super(definedclasses005aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public Class preloadClass (String className) throws ClassNotFoundException { + return findClass(className); + } + + protected synchronized Class findClass(String name) throws ClassNotFoundException { + String classFileName = classPath + "/" + name.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(name, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java new file mode 100644 index 00000000000..9670dba51e5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassLoaderReference.visibleClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassLoader.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassLoader.visibleClasses()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Returns a list of all classes for which this class loader
    + * has been recorded as the initiating loader in the target VM.
    + * The list contains ReferenceTypes defined directly by
    + * this loader (as returned by definedClasses()) and
    + * any types for which loading was delegated by
    + * this class loader to another class loader.
    + *
    + * The case to check includes a class loader with no
    + * delegated types, that is, the expected returned value should
    + * be equal to one returned by ClassLoader.definedClasses(),
    + * except primitive arrays defined by bootstrap class loader
    + * and visible.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a ClassLoader object and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class visibleclasses001 { + + //----------------------------------------------------- template section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- template parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new visibleclasses001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + static List primitiveArraysNamesPatterns = Arrays.asList(new String[] { + "^boolean(\\[\\])+", "^byte(\\[\\])+", "^char(\\[\\])+", "^int(\\[\\])+", + "^short(\\[\\])+", "^long(\\[\\])+", "^float(\\[\\])+", "^double(\\[\\])+"}); + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # 0"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......getting: List classes = vm.allClasses();"); + List classes = vm.allClasses(); + log2(" classes.size() == " + classes.size()); + + vm.resume(); + breakpointForCommunication(); + + log1(":::::: case: # 1"); + + String ClassLoaderObjName = "classLoader"; + + log2("......getting: Value val = debuggeeClass.getValue(debuggeeClass.fieldByName(ClassLoaderObjName));"); + Value val = debuggeeClass.getValue(debuggeeClass.fieldByName(ClassLoaderObjName)); + + log2("......getting: ClassLoaderReference clRef = (ClassLoaderReference) val;"); + ClassLoaderReference clRef = (ClassLoaderReference) val; + + log2("......getting: List definedClasses = clRef.definedClasses();"); + List definedClasses = clRef.definedClasses(); + + log2("......getting: List visibleClasses = clRef.visibleClasses();"); + List visibleClasses = clRef.visibleClasses(); + + log2("......checking up on: visibleClasses.size() == definedClasses.size()"); + + if (visibleClasses.size() != definedClasses.size()) { + log2(" : visibleClasses.size() != definedClasses.size()"); + log2(" : definedClasses.size() == " + definedClasses.size()); + log2(" : visibleClasses.size() == " + visibleClasses.size()); + + for (ReferenceType vcl : visibleClasses) { + + int vclIndex = visibleClasses.indexOf(vcl); + String vclName = vcl.name(); + + if (primitiveArraysNamesPatterns.stream().anyMatch(vcl.name()::matches)) { + log2(" : visibleClasses[" + vclIndex + "].name() == " + vclName + + " Correct - primitive arrays are visible for class loader"); + } else { + log3(" : visibleClasses[" + vclIndex + "].name() == " + vclName); + + classes.stream().filter(cl -> cl.name().equals(vclName)) + .forEach(cl -> log3(" : List classes contains an object with the name: " + cl.name())); + + testExitCode = FAILED; + } + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001/TestDescription.java new file mode 100644 index 00000000000..6379024e7ef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001/TestDescription.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassLoader. + * The test checks up that a result of the method + * com.sun.jdi.ClassLoaderReference.visibleClasses() + * complies with its spec: + * public List visibleClasses() + * Returns a list of all classes for which this class loader has been recorded + * as the initiating loader in the target VM. The list contains + * ReferenceTypes defined directly by this loader + * (as returned by definedClasses()) and any types for which loading was + * delegated by this class loader to another class loader. + * The visible class list has useful properties with respect to + * the type namespace. A particular type name will occur at most once in + * the list. Each field or variable declared with that type name in + * a class defined by this class loader must be resolved to that single type. + * No ordering of the returned list is guaranteed. + * See the revised Java Virtual Machine Specification section 5.3 + * Creation and Loading for more information on the initiating classloader. + * Note that unlike definedClasses() and VirtualMachine.allClasses(), + * some of the returned reference types may not be prepared. + * Attempts to perform some operations on unprepared reference types + * (e.g. fields()) will throw a ClassNotPreparedException. + * Use ReferenceType.isPrepared() to determine if a reference type is prepared. + * Returns: + * a List of ReferenceType objects mirroring classes initiated by + * this class loader. The list has length 0 if no classes are + * visible to this classloader. + * The test checks up on the following assertion: + * Returns a list of all classes for which this class loader + * has been recorded as the initiating loader in the target VM. + * The list contains ReferenceTypes defined directly by + * this loader (as returned by definedClasses()) and + * any types for which loading was delegated by + * this class loader to another class loader. + * The case to check includes a class loader with no + * delegated types, that is, the expected returned value should + * be equal to one returned by ClassLoaderReference.definedClasses(). + * The test works as follows: + * The debugger program - nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses001; + * the debuggee program - nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test fixed due to test RFE: + * 4842009 TEST_RFE: Incorrect package name in two JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses001 + * nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001a.java new file mode 100644 index 00000000000..3e8c282b9e3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001a.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassLoaderReference.visibleClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.net.URLClassLoader; +import java.net.URL; + +/** + * This class is used as debuggee application for the visibleclasses001 JDI test. + */ + +public class visibleclasses001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static ClassLoader classLoader = null; + + static String urlString = "http://x.y.z/"; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + case 1: + try { + URL[] url = { new URL(urlString) } ; + classLoader = new URLClassLoader(url); + } catch ( Exception e ) { + log1("Exception : " + e); + } + + methodForCommunication(); + break ; + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002.java new file mode 100644 index 00000000000..836b3c1ae5f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.visibleClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class visibleclasses002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ClassLoaderReference.visibleClasses."; + private final static String className = "visibleclasses002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + display("Getting ClassLoaderReference of debuggee's class."); + ClassLoaderReference classLoader = debuggeeClass.classLoader(); + if (classLoader == null) { + complain("classLoader() method returned null for debuggee's ReferenceType."); + exitStatus = Consts.TEST_FAILED; + } else { + display("Getting visibleClasses list."); + Iterator visibleClasses = classLoader.visibleClasses().iterator(); + boolean found0 = false; + boolean found1 = false; + boolean found2 = false; + display("Searching for debuggee's ReferenceType in the list..."); + while (visibleClasses.hasNext()) { + ReferenceType refType = (ReferenceType)visibleClasses.next(); + if (refType.equals(debuggeeClass)) { + display("visibleclasses002a ClassType is found in visibleClasses() list of ClassLoaderReference mirror."); + found0 = true; + } else if (refType instanceof ArrayType) { + Type compType; + try { + compType = ((ArrayType)refType).componentType(); + if (compType instanceof ClassType && ((ReferenceType)compType).equals(debuggeeClass)) { + display("visibleclasses002a[] ArrayType is found in visibleClasses() list of ClassLoaderReference mirror."); + found1 = true; + } else if (compType instanceof ArrayType) { + compType = ((ArrayType)compType).componentType(); + if (compType instanceof ClassType && ((ReferenceType)compType).equals(debuggeeClass)) { + display("visibleclasses002a[][] ArrayType is found in visibleClasses() list of ClassLoaderReference mirror."); + found2 = true; + } + } + } catch (ClassNotLoadedException e) { + throw new Failure("Unexpected ClassNotLoadedException while getting componentType() of : " + refType); + } + + } + } + if (!found0) { + complain("visibleclasses002a ReferenceType is NOT found in visibleClasses() list of ClassLoaderReference mirror."); + exitStatus = Consts.TEST_FAILED; + } + if (!found1) { + complain("visibleclasses002a[] ArrayType is NOT found in visibleClasses() list of ClassLoaderReference mirror."); + exitStatus = Consts.TEST_FAILED; + } + if (!found2) { + complain("visibleclasses002a[][] ArrayType is NOT found in visibleClasses() list of ClassLoaderReference mirror."); + exitStatus = Consts.TEST_FAILED; + } + } + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002/TestDescription.java new file mode 100644 index 00000000000..a3bdb1ebe20 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * COMMENTS: + * The test checks up that an implementation of the + * com.sun.jdi.ClassLoaderReference.visibleClasses method conforms + * with its spec. + * The test verifies an assertion: + * public List visibleClasses() + * Returns a list of all classes for which this class loader has been + * recorded as the initiating loader in the target VM. The list contains + * ReferenceTypes defined directly by this loader (as returned by + * definedClasses()) and any types for which loading was delegated by this + * class loader to another class loader. + * The test consists of: + * debugger - nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses002 + * debuggee - nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses002a + * The main method of debuggee class defines local variables of single- and + * two-dimensional array of 'visibleclasses002a' type. The debugger gets + * a ClassLoaderReference of debuggee class loader. The tests fails if + * either debuggee class reference or array type references are not found + * in the list returned by visibleClasses() method. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses002 + * nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassLoaderReference.visibleClasses.visibleclasses002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002a.java new file mode 100644 index 00000000000..fd8a58e9a63 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses002a.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassLoaderReference.visibleClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged applcation of the test. + */ +public class visibleclasses002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + visibleclasses002a[] arr1 = {}; + visibleclasses002a[][] arr2 = {arr1}; + + try { + pipe.println(visibleclasses002.SIGNAL_READY); + + receiveSignal(visibleclasses002.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(exitStatus + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001.java new file mode 100644 index 00000000000..e807eaa15e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ClassObjectReference.reflectedType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method reflectedType() + * of the JDI interface ClassObjectReference of com.sun.jdi package + */ + +public class reflectype001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ClassObjectReference.reflectedType.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "reflectype001", + debugeeName = thisClassName + "a"; + + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + + {"boolean", "primitive_type", "class"}, + {"byte" , "primitive_type", "class"}, + {"char" , "primitive_type", "class"}, + {"double" , "primitive_type", "class"}, + {"float" , "primitive_type", "class"}, + {"int" , "primitive_type", "class"}, + {"long" , "primitive_type", "class"}, + + {"java.lang.Boolean" , "reference_type", "class"}, + {"java.lang.Byte" , "reference_type", "class"}, + {"java.lang.Character", "reference_type", "class"}, + {"java.lang.Double" , "reference_type", "class"}, + {"java.lang.Float" , "reference_type", "class"}, + {"java.lang.Integer" , "reference_type", "class"}, + {"java.lang.Long" , "reference_type", "class"}, + {"java.lang.String" , "reference_type", "class"}, + {"java.lang.Object" , "reference_type", "class"}, + + {debugeeName+"$s_class", "reference_type", "class"}, // static class + {debugeeName+"$s_interf", "reference_type", "interface"}, // static interface + + {package_prefix + "package_class", "reference_type", "class"}, // class + {package_prefix + "package_interf", "reference_type", "interface"} // interface + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new reflectype001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ClassObjectReference/reflectedType/reflectype001 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ClassObjectReference/reflectedType/reflectype001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + IOPipe pipe = new IOPipe(debugee); + + logHandler.display("==> nsk/jdi/ClassObjectReference/reflectedType/reflectype001 test LOG:"); + logHandler.display("==> test checks reflectedType() method of ClassObjectReference interface "); + logHandler.display(" of the com.sun.jdi package for ArraType, ClassType, InterfaceType\n"); + + + debugee.redirectStderr(out); + print_log_on_verbose("--> reflectype001: reflectype001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + logHandler.complain + ("##> reflectype001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + logHandler.complain + ("##> reflectype001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> reflectype001: debugee's \"ready\" signal recieved!"); + } + + logHandler.display + ("--> reflectype001: check ClassObjectReference.reflectedType() method for debugee's classes..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int classObject_method_errors = 0; + for (int i=0; i reflectype001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + String s_type = classes_for_check[i][2]; + if ( array_measure != 0 ) { // array type + s_type = "class"; + } + ClassObjectReference class_obj_ref = refType.classObject(); + ReferenceType reflected_refType = class_obj_ref.reflectedType(); + if ( ! refType.equals(reflected_refType) ) { + logHandler.complain + ("##> reflectype001: FAILED: source ReferenceType object is NOT equal to reflected object"); + logHandler.complain + ("##> for " + s_type + ": " + className); + classObject_method_errors++; + } + else { + print_log_on_verbose + ("--> reflectype001: PASSED: source ReferenceType object is equal to reflected object"); + print_log_on_verbose + ("--> for " + s_type + ": " + className); + } + } + } + logHandler.display("--> reflectype001: check completed!"); + logHandler.display("--> reflectype001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + logHandler.complain("##> reflectype001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + logHandler.display("##> reflectype001: classObject() method ERRORS counter = " + + classObject_method_errors); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + classObject_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> reflectype001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + logHandler.complain + ("##> reflectype001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> reflectype001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001/TestDescription.java new file mode 100644 index 00000000000..4d107efecb2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassObjectReference/reflectedType/reflectype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ClassObjectReference/reflectedType/reflectype001 test + * checks the reflectedType() method of ClassObjectReference interface + * of the com.sun.jdi package for ArraType, ClassType, InterfaceType: + * The ClassObjectReference.reflectedType() method is checked for debugee's classes + * by comparing source ReferenceType object with reflected ReferenceType object + * returned by ClassObjectReference.reflectedType() method. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * --------- + * To use new share classes, the file reflectype001.java is updated as follows: + * - two lines, 33 and 34, with argsHandler and logHandler are added + * - statements with definitions, lines 105-118, are added; + * obsolete statements are removed; + * - all calls to "println" are replaced with calls to + * "logHandler.complain" or "logHandler.display".. + * - all "display" are replaced with "logHandler.display" + * -------- + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassObjectReference.reflectedType.reflectype001 + * nsk.jdi.ClassObjectReference.reflectedType.reflectype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassObjectReference.reflectedType.reflectype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java new file mode 100644 index 00000000000..6281bfc52af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ClassObjectReference.reflectedType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the reflectype001 JDI test. + */ + +public class reflectype001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + static class s_class {} + static interface s_interf {} + protected static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl(); + + s_class s_class0 = new s_class(), s_class1[]={s_class0}, + s_class2[][]={s_class1}; + s_interf s_interf0, s_interf1[]={s_interf0}, s_interf2[][]={s_interf1}; + + package_class package_class0 = new package_class(), + package_class1[]={package_class0}, + package_class2[][]={package_class1}; + class package_interf_impl implements package_interf {} + package_interf_impl pii0 = new package_interf_impl(); + package_interf package_interf0, package_interf1[]={package_interf0}, + package_interf2[][]={package_interf1}; + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i reflectype001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + reflectype001a reflectype001a_obj = new reflectype001a(); + + print_log_on_verbose("**> reflectype001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> reflectype001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> reflectype001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> reflectype001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> reflectype001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** simple class */ +class package_class {} + +/** simple interface */ +interface package_interf {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002.java new file mode 100644 index 00000000000..da528cee5b3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ClassObjectReference.reflectedType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +/** + * This test checks the method reflectedType() + * of the JDI interface ClassObjectReference of com.sun.jdi package + */ + +public class reflectype002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ClassObjectReference.reflectedType.", + thisClassName = package_prefix + "reflectype002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "reflectype002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new reflectype002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ClassObjectReference/reflectedType/reflectype002 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdiClassObjectReference/reflectedType/reflectype002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + private static void print_log_without_verbose(String message) { + if ( ! verbose_mode ) { + out_stream.println(message); + } + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ClassObjectReference/reflectedType/reflectype002 test LOG:"); + out_stream.println("--> test checks reflectedType() method of ClassObjectReference interface "); + out_stream.println(" of the com.sun.jdi package for UNLOADED class\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + argv = argHandler.getArguments(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> reflectype002: reflectype002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> reflectype002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + out_stream.println + ("##> reflectype002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> reflectype002: debugee's \"ready0\" signal recieved!"); + } + + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> reflectype002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + out_stream.println + ("##> reflectype002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> reflectype002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean reflectedType_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> reflectype002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> reflectype002: getting ReferenceType object for loaded checked class..."); + out_stream.println("##> reflectype002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> reflectype002: checked class FOUND: " + checked_class); + } + + print_log_on_verbose + ("--> reflectype002: getting ClassObjectReference object for loaded checked class..."); + ClassObjectReference class_obj_ref = refType.classObject();; + print_log_on_verbose("--> reflectype002: getting ClassObjectReference object - DONE!"); + + print_log_on_verbose + ("--> reflectype002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> reflectype002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + out_stream.println + ("--> reflectype002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + out_stream.println + ("--> ClassObjectReference.reflectedType() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + out_stream.println + ("##> reflectype002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> reflectype002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> reflectype002: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> reflectype002: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> reflectype002: check that checked class has been unloaded realy..."); + out_stream.println + ("--> reflectype002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + out_stream.println + ("--> ClassObjectReference.reflectedType() method can NOT be checked!"); + break; + } + + out_stream.println + ("--> reflectype002: check ClassObjectReference.reflectedType() method for unloaded class..."); + try { + refType2 = class_obj_ref.reflectedType(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + out_stream.println + ("--> reflectype002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + out_stream.println + ("##> reflectype002: FAILED: unexpected Exception thrown - " + expt.toString()); + out_stream.println + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + reflectedType_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || reflectedType_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> reflectype002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> reflectype002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> reflectype002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of reflectype002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TestDescription.java new file mode 100644 index 00000000000..ab1416ed8d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassObjectReference/reflectedType/reflectype002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ClassObjectReference/reflectedType/reflectype002 test + * checks the reflectedType() method of ClassObjectReference interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then gets a ClassObjectReference instance, then enforces + * the class to be unloaded and calls the reflectedType() method - + * the com.sun.jdi.ObjectCollectedException should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme to have separate +* directory for precompiled classes: + * - reflectype002b class was moved in 'loadclass' subdirectory; + * - package name was added in reflectype002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for reflectype002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassObjectReference.reflectedType.reflectype002 + * nsk.jdi.ClassObjectReference.reflectedType.reflectype002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassObjectReference.reflectedType.reflectype002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/loadclass/reflectype002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/loadclass/reflectype002b.java new file mode 100644 index 00000000000..4df4167218d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002/loadclass/reflectype002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the reflectedType() method of ClassObjectReference interface for UNLOADED class + +package nsk.jdi.ClassObjectReference.reflectedType; + +class reflectype002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002a.java new file mode 100644 index 00000000000..0f5cda75751 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ClassObjectReference.reflectedType; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the reflectype002 JDI test. + */ + +public class reflectype002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ClassObjectReference.reflectedType."; + private final static String checked_class_name = package_prefix + "reflectype002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> reflectype002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + pipe.println("ready0"); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + print_log_on_verbose("**> reflectype002a: waiting for \"checked class dir\" info..."); + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> reflectype002a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> reflectype002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> reflectype002a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> reflectype002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> reflectype002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> reflectype002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("##> reflectype002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("##> reflectype002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> reflectype002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> reflectype002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> reflectype002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> reflectype002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> reflectype002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> reflectype002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> reflectype002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("##> reflectype002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("##> reflectype002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of reflectype002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001.java new file mode 100644 index 00000000000..0f66d1e01bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassObjectReference.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class tostring001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ClassObjectReference.toString."; + private final static String className = "tostring001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + /** debuggee's methods for check **/ + private final static String checkedClasses[] = { + "java.lang.Boolean" , + "java.lang.Byte" , + "java.lang.Character", + "java.lang.Double" , + "java.lang.Float" , + "java.lang.Integer" , + "java.lang.Long" , + "java.lang.Short" , + "java.lang.String" , + "java.lang.Object" , + + debuggeeName + "$innerClass", + debuggeeName + "$innerInterf", + prefix + "tostring001aClass", + prefix + "tostring001aInterf" + }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + BreakpointRequest brkp = debuggee.setBreakpoint(debuggeeClass, + tostring001a.brkpMethodName, + tostring001a.brkpLineNumber); + debuggee.resume(); + + debuggee.sendSignal(SIGNAL_GO); + Event event = null; + + // waiting the breakpoint event + try { + event = debuggee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected InterruptedException while waiting for Breakpoint event"); + } + if (!(event instanceof BreakpointEvent)) { + debuggee.resume(); + throw new Failure("BreakpointEvent didn't arrive"); + } + + ThreadReference thread = ((BreakpointEvent)event).thread(); + List params = new Vector(); + ClassType testedClass = (ClassType)debuggeeClass; + + display("Checking toString() method for ClassObjectReferences of debuggee's fields..."); + String brackets[] = {"", "[]", "[][]"}; + + for (int i=0; i < checkedClasses.length; i++) { + + String basicName = checkedClasses[i]; + + for (int dim = 0; dim<3; dim++) { + + String className = basicName + brackets[dim]; + ReferenceType refType = debuggee.classByName(className); + if (refType == null) { + complain("Could NOT FIND class: " + className); + exitStatus = Consts.TEST_FAILED; + continue; + } + + try { + ClassObjectReference classObjRef = refType.classObject(); + String str = classObjRef.toString(); + if (str == null) { + complain("toString() returns null for ClassObjectReferences of debugges's field: " + className); + exitStatus = Consts.TEST_FAILED; + } else if (str.length() == 0) { + complain("toString() returns empty string for ClassObjectReferences of debugges's field: " + className); + exitStatus = Consts.TEST_FAILED; + } else { + display("toString() method returns for " + className + " : " + str); + } + } catch(Exception e) { + complain("unexpected " + e + " while taking ClassObjectReferences of debugges's field: " + className); + exitStatus = Consts.TEST_FAILED; + } + } + } + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..f2ad8f6687c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassObjectReference/toString/tostring001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public toString() method of an implementing class of + * com.sun.jdi.ClassObjectReference interface. + * The test checks an assertion: + * In conformity with the contract for java.lang.Object.toString(), + * the overrided method returns representing non-empty string for + * for a ClassObjectReference object of a debuggee class's field. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for ClassObjectReference + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassObjectReference.toString.tostring001 + * nsk.jdi.ClassObjectReference.toString.tostring001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassObjectReference.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001a.java new file mode 100644 index 00000000000..7764bff0268 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001a.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassObjectReference.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged applcation of the test. + */ +public class tostring001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 121; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + Short H0 = new Short((short)-1), H1[]={H0}, H2[][]={H1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + static class innerClass {} + static interface innerInterf {} + protected static class innerInterfImpl implements innerInterf {} + innerInterfImpl sii0 = new innerInterfImpl(); + + innerClass innerClass0 = new innerClass(); + innerClass innerClass1[] = {innerClass0}; + innerClass innerClass2[][] = {innerClass1}; + + innerInterf innerInterf0; + innerInterf innerInterf1[] = {innerInterf0}; + innerInterf innerInterf2[][] = {innerInterf1}; + + tostring001aClass tostring001aClass0 = new tostring001aClass(); + tostring001aClass tostring001aClass1[] = {tostring001aClass0}; + tostring001aClass tostring001aClass2[][] = {tostring001aClass1}; + + class tostring001aInterfImpl implements tostring001aInterf {} + tostring001aInterfImpl pii0 = new tostring001aInterfImpl(); + tostring001aInterf tostring001aInterf0; + tostring001aInterf tostring001aInterf1[] = {tostring001aInterf0}; + tostring001aInterf tostring001aInterf2[][] = {tostring001aInterf1}; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + tostring001a dummy = new tostring001a(); + + try { + pipe.println(tostring001.SIGNAL_READY); + receiveSignal(tostring001.SIGNAL_GO); + log.display("breakpoint line"); // brkpLineNumber + receiveSignal(tostring001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods +} + +//--------------------------------------------------------- test specific classes +class tostring001aClass {} +interface tostring001aInterf {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001.java new file mode 100644 index 00000000000..e576e58be4c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareEvent.referenceType; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class refType001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_RUN = "run"; + static final String COMMAND_DONE = "done"; + static final String COMMAND_ERROR = "error"; + + static final String PACKAGE_NAME = "nsk.jdi.ClassPrepareEvent.referenceType"; + static final String DEBUGEE_NAME = PACKAGE_NAME + ".refType001a"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + + static private ClassPrepareRequest checkedRequest; + static private ThreadReference debuggeeThread; + static private volatile String checkedTypes[][] = { + {"main", "refType001a", "0"}, + {"main", "AnotherThread", "0"}, + {"AnotherThread", "ClassForAnotherThread", "0"}, + {"AnotherThread", "Inter", "0"} + }; + + static private volatile boolean testFailed, eventsReceived, threadsStarted; + static private int eventTimeout; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + String command; + + testFailed = false; + eventsReceived = false; + threadsStarted = false; + + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debugee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGEE_NAME); + debuggee.redirectStderr(log, "refType001a >"); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // create request and wait for expected events + try { + + // create request for ClassPrepareEvent + log.display("Creating request for ClassPrepareEvent"); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + if ((checkedRequest = erManager.createClassPrepareRequest()) == null) { + throw new Failure("TEST FAILED: unable to create ClassPrepareRequest"); + } + log.display("ClassPrepareRequest is created"); + + // define separate thread to handle received events + class EventHandler extends Thread { + + public void run() { + + // handle events until all threads started and all expected events received + while (!(threadsStarted && eventsReceived)) { + EventSet eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while receiving events: " + e); + } + + if (eventSet == null) { + continue; + } + + // handle each event + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); +// log.display("\nEvent received:\n " + event); + + // handle ClassPrepareEvent + if (event instanceof ClassPrepareEvent) { + ClassPrepareEvent castedEvent = (ClassPrepareEvent)event; + log.display("\nClassPrepareEvent received:\n " + event); + + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 1: eventRequest is not equal to checked request"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + debuggeeThread = castedEvent.thread(); + String threadName = debuggeeThread.name(); + + // test ClassPrepareEvent.referenceType() method + ReferenceType refType = castedEvent.referenceType(); + if (refType == null) { + log.complain("FAILURE 3: ClassPrepareEvent.referenceType() returns null"); + testFailed = true; + } else { + + String refName = refType.name(); + if ((refName == null) || (refName.equals(""))) { + log.complain("FAILURE 4: Reference has invalid empty name"); + testFailed = true; + } else { + if ( refName.startsWith(PACKAGE_NAME)) { + log.display("Reference " + refName + " prepared in thread " + threadName); + + // Check that all expected debuggee's thread create ClassPrepareEvent only once + for (int i = 0; i < checkedTypes.length; i++) { + if (threadName.equals(checkedTypes[i][0]) && refName.endsWith(checkedTypes[i][1])) { + if (checkedTypes[i][2] == "0") { + checkedTypes[i][2] = "1"; + } else { + log.complain("FAILURE 5: ClassPrepareEvent for " + threadName + " is received more that once"); + testFailed = true; + } + } + } + + // Check that all static fields in reference type are initialized + Iterator fieldsList; + try { + fieldsList = refType.fields().iterator(); + } catch (ClassNotPreparedException e) { + log.complain( "FAILURE 6: " + refName + " is not prepared"); + testFailed = true; + throw new Failure("ClassNotPrepared exception caught: " + e); + } + while (fieldsList.hasNext()) { + Field refField = (Field)fieldsList.next(); + if (refField.isStatic()) { + if (refField.equals(null)) { + log.complain( "FAILURE 7: " + refField.name() + " of " + refName + " is not initialized"); + testFailed = true; + } + } + } + + // Check that all expected ClassPrepareEvent are received + eventsReceived = true; + for (int i = 0; i < checkedTypes.length; i++) { + if (checkedTypes[i][2] == "0") + eventsReceived = false; + } + } + } + + if (!refType.isPrepared()) { + log.complain("FAILURE 8: Reference " + refName + " is not prepared" ); + testFailed = true; + } + } + } + + // ignore each oter event + + } // event handled + +// log.display("Resuming event set"); + eventSet.resume(); + + } // event set handled + + log.display("eventHandler completed"); + + } // for run() + + } // for EventHandler + + // start EventHandler thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // enable event request and resume debugee + log.display("Enabling ClassPrepareEvent request"); + checkedRequest.enable(); + + log.display("Resuming debuggee"); + debuggee.resume(); + + // wait for debugee started + log.display("Waiting for command: " + COMMAND_READY); + command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // force debugee to start another thread + log.display("Sending a command: " + COMMAND_RUN); + pipe.println(COMMAND_RUN); + + // wait for debugee started requested thread + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + log.complain("TEST BUG: unexpected debuggee's command: " + command); + testFailed = true; + } + + // notify EventHandler that all threads started + threadsStarted = true; + + // wait for all expected events received or timeout exceeds + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check that all expected debuggee's threads created ClassPrepareEvent + for (int i = 0; i < checkedTypes.length; i++) { + if (checkedTypes[i][2].equals("0")) { + log.complain("FAILURE 9: ClassPrepareEvent for " + checkedTypes[i][1] + + " in thread " + checkedTypes[i][0] + " is not received"); + testFailed = true; + } + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + // disable event requests to prevent appearance of further events + if (checkedRequest != null && checkedRequest.isEnabled()) { + log.display("Disabling StepEvent request"); + checkedRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001/TestDescription.java new file mode 100644 index 00000000000..11ea84cec54 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/referenceType/refType001/TestDescription.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareEvent/referenceType/refType001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.lassPrepareEvent.referenceType() method. + * The test checks the following assertions: + * - ClassPrepareEvent is always received by debugger + * for all prepared classes and interfaces in target VM, + * - ClassPrepareEvent is received only once for each checked + * class or interface + * - method ClassPrepareEvent.referenceType returns valid + * Reference Type in target VM, + * - all static fields and constants are initialized for checked + * prepared class or interface. + * A debugger class - nsk.jdi.ClassPrepareEvent.referenceType.refType001 ; + * a debuggee class - nsk.jdi.ClassPrepareEvent.referenceType.refType001a . + * The test uses supporting nsk/share/jdi classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates ClassPrepareRequest and starts special thread + * for listening events delivered from debuggee. + * The debuger enables ClassPrepareRequest, resumes debuggee and + * waits for command from it. Next, debuugger sends debuggee + * command to force it to start another thread, and waits + * for confirmation . + * The debuggee starts special thread in which instance of + * with a number of static fields, + * waits for thread started and sends debugger command . + * Each event received by debuger is handled by . + * When event is of ClassPrepareEvent and is for checked threads, + * all assertions are verifieded for this event. + * After debuggee received command from debuggee, if notifies + * that all thread have been started in debuggee, + * and waits for all expected events received and finishes. + * If not all expected events has been received for WAITTIME period, + * debugger complains an error and interrupts . + * Finally, debugger disables event request, sends debuggee command "); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // create request and wait for expected events + try { + + // create request for ClassPrepareEvent + log.display("Creating request for ClassPrepareEvent"); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + if ((checkedRequest = erManager.createClassPrepareRequest()) == null) { + throw new Failure("TEST FAILED: unable to create ClassPrepareRequest"); + } + log.display("ClassPrepareRequest is created"); + + checkedRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); +// checkedRequest.enable(); + + switch (checkedRequest.suspendPolicy()) { + case EventRequest.SUSPEND_NONE: + log.display("Suspend policy is SUSPEND_NONE"); + break; + case EventRequest.SUSPEND_ALL: + log.display("Suspend policy is SUSPEND_ALL"); + break; + case EventRequest.SUSPEND_EVENT_THREAD: + log.display("Suspend policy is SUSPEND_EVENT_THREAD"); + break; + default: + throw new Failure("TEST BUG: Unknown suspend policy: " + checkedRequest.suspendPolicy()); + } + + // define separate thread to handle received events + class EventHandler extends Thread { + + public void run() { + + // handle events until all threads started and all expected events received + while (!(threadsStarted && eventsReceived)) { + EventSet eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while receiving events: " + e); + } + + if (eventSet == null) { + continue; + } + + // handle each event + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); +// log.display("\nEvent received:\n " + event); + + // handle ClassPrepareEvent + if (event instanceof ClassPrepareEvent) { + ClassPrepareEvent castedEvent = (ClassPrepareEvent)event; + log.display("\nClassPrepareEvent received:\n " + event); + + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 1: eventRequest is not equal to checked request"); + testFailed = true; + } + + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + // test method ClassPrepareEvent.thread() + eventThread = castedEvent.thread(); + String threadName = eventThread.name(); + if (eventThread == null) { + log.complain("FAILURE 3: ClassPrepareEvent.thread() returns null"); + testFailed = true; + } else if ((threadName == null) || (threadName.equals(""))) { + log.complain("FAILURE 4: thread reference has invalid empty name"); + testFailed = true; + } + + ReferenceType refType = castedEvent.referenceType(); + if (refType == null) { + log.complain("FAILURE 5: ClassPrepareEvent.referenceType() returns null"); + testFailed = true; + } else { + + String className = refType.name(); + if ( className.startsWith(PACKAGE_NAME)) { + + log.display("Class " + className + " prepared in thread " + threadName); + + // Check that thread is in VirtualMachine.allThreads() list + boolean found = false; + Iterator threadsList = vm.allThreads().iterator(); + while (!found && threadsList.hasNext()) { + found = eventThread.equals((ThreadReference)threadsList.next()); + } + if (!found) { + log.complain("FAILURE 6: " + threadName + " is not in debuggee's allThreads() list"); + testFailed = true; + } + + // Check that all expected debuggee's thread create ClassPrepareEvent only once + for (int i = 0; i < checkedThreads.length; i++) { + if (threadName.equals(checkedThreads[i][0]) && className.endsWith(checkedThreads[i][1])) { + if (checkedThreads[i][2] == "0") { + checkedThreads[i][2] = "1"; + } else { + log.complain("FAILURE 7: ClassPrepareEvent for " + threadName + " is received more that once"); + testFailed = true; + } + } + } + + // check that thread is correctly suspended + if (checkedRequest.suspendPolicy() == EventRequest.SUSPEND_ALL || + checkedRequest.suspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD) { + + if (eventThread.isSuspended()) { + log.display("Thread " + threadName + " is correctly suspended"); + } else { + log.complain("FAILURE 7: Thread " + threadName + " is not suspended"); + testFailed = true; + } + } + + // Check that all expected ClassPrepareEvent are received + eventsReceived = true; + for (int i = 0; i < checkedThreads.length; i++) { + if (checkedThreads[i][2] == "0") { + eventsReceived = false; + } + } + } + } + } + + // ignore each oter event + + } // event handled + +// log.display("Resuming event set"); + eventSet.resume(); + + } // event set handled + + log.display("eventHandler completed"); + + } // for run() + + } // for EventHandler + + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // enable event request and resume debugee + log.display("Enabling ClassPrepareEvent request"); + checkedRequest.enable(); + + log.display("Resuming debuggee"); + debuggee.resume(); + + // wait for debugee started + log.display("Waiting for command: " + COMMAND_READY); + command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // force debugee to start another thread + log.display("Sending a command: " + COMMAND_RUN); + pipe.println(COMMAND_RUN); + + // wait for debugee started requested thread + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + log.complain("TEST BUG: unexpected debuggee's command: " + command); + testFailed = true; + } + + // notify EventHandler that all threads started + threadsStarted = true; + + // wait for all expected events received or timeout exceeds + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check that all expected debuggee's threads created ClassPrepareEvent + for (int i = 0; i < checkedThreads.length; i++) { + if (checkedThreads[i][2].equals("0")) { + log.complain("FAILURE 9: ClassPrepareEvent for " + checkedThreads[i][1] + + " in thread " + checkedThreads[i][0] + " is not received"); + testFailed = true; + } + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + + // disable event requests to prevent appearance of further events + if (checkedRequest != null && checkedRequest.isEnabled()) { + log.display("Disabling StepEvent request"); + checkedRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/thread/thread001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/thread/thread001/TestDescription.java new file mode 100644 index 00000000000..609d193db0e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareEvent/thread/thread001/TestDescription.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareEvent/thread/thread001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.ClassPrepareEvent.thread() method. + * The test checks the following assertions: + * - ClassPrepareEvent is always received by debugger + * for expected classe in proper threads in target VM, + * - ClassPrepareEvent.thread() returns valid ThreadReference + * to checked thread in target VM, + * - ClassPrepareEvent is received only once for each expected class. + * A debugger class - nsk.jdi.ClassPrepareEvent.thread.thread001 ; + * a debuggee class - nsk.jdi.ClassPrepareEvent.thread.thread001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates ClassPrepareRequest and starts special thread + * for listening events delivered from debuggee. + * The debuger enables ClassPrepareRequest, resumes debuggee and + * waits for command from it. Next, debuugger sends debuggee + * command to force it to start another threads, and waits + * for confirmation . + * The debuggee starts inner and outer threads in which instances of + * and created, + * waits for threads started and sends debugger command . + * Each event received by debuger is handled by . + * When event is of ClassPrepareEvent and is for checked threads, + * all assertions are verifieded for this event. + * After debuggee received command from debuggee, if notifies + * that all thread have been started in debuggee, + * and waits for all expected events received and finishes. + * If not all expected events has been received for WAITTIME period, + * debugger complains an error and interrupts . + * Finally, debugger disables event request, sends debuggee command + * - addClassFilter(ReferenceType),
    + * - addClassFilter(String),
    + * - addClassExclusionFilter(String)
    + * methods with null argument value. + * In any cases NullPointerException is expected. + */ +public class filters001 { + + final static String prefix = "nsk.jdi.ClassPrepareRequest._bounds_."; + private final static String className = "filters001"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + filters001 thisTest = new filters001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType debugeeRef = debugee.classByName(debugeeName); + + display(""); + display(">>>creating ClassPrepareRequest"); + ClassPrepareRequest request = + debugee.getEventRequestManager().createClassPrepareRequest(); + + display(""); + addClassFilter(request, (ReferenceType )null); + display(""); + addClassFilter(request, (String )null); + display(""); + addClassExclusionFilter(request, (String )null); + + display(""); + debugee.quit(); + } + + private void addClassFilter(ClassPrepareRequest request, ReferenceType refType) { + + display("addClassFilter :ReferenceType> null"); + try { + request.addClassFilter(refType); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(ClassPrepareRequest request, String classPattern) { + + display("addClassFilter :classPattern> null"); + try { + request.addClassFilter(classPattern); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassExclusionFilter(ClassPrepareRequest request, + String classPattern) { + display("addExclusionClassFilter :classPattern> null"); + try { + request.addClassExclusionFilter(classPattern); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001/TestDescription.java new file mode 100644 index 00000000000..f165155c808 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/_bounds_/filters001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the methods + * com.sun.jdi.request.ClassPrepareRequest.addClassFilter(ReferenceType) + * com.sun.jdi.request.ClassPrepareRequest.addClassFilter(String) + * com.sun.jdi.request.ClassPrepareRequest.addClassExclusionFilter(String) + * correctly work for the boundary value of parameter and throw described + * exceptions. + * The test check up these methods with argument value. In any cases + * NullPointerException is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest._bounds_.filters001 + * nsk.jdi.ClassPrepareRequest._bounds_.filters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest._bounds_.filters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001a.java new file mode 100644 index 00000000000..dfb6d7a4379 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/_bounds_/filters001a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassPrepareRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filters001a is deugee's part of the test. + */ +public class filters001a { + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001.java new file mode 100644 index 00000000000..d684989d4e6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * + * The test checks that results of the method + * com.sun.jdi.ClassPrepareRequest.addClassExclusionFilter(String) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The case to check includes a pattern that begins with '*'. + * + * The test works as follows. + * - The debugger + * - sets up a ClassPrepareRequest, + * - using a string pattern, restricts it with addClassExclusionFilter, + * - resumes the debuggee, and waits for ClassPrepareEvents. + * - The debuggee creates and starts a thread1, + * whose 'run' method creates objects of ClassTypes needed + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs the checks required. + */ + +public class filter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter001a"; + return new filter001().runThis(argv, out); + } + + private String classExclFilter1 = "*TestClass11"; + private String classExclName1 = "nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.Thread1filter001a.TestClass11"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + String property1 = "ClassPrepareRequest1"; + ThreadReference thread1 = null; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + eventRequest1 = setting23ClassPrepareRequest(classExclFilter1, + EventRequest.SUSPEND_NONE, + property1); + eventRequest1.enable(); + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof ClassPrepareEvent) { + String str = ((ClassPrepareEvent)event).referenceType().name(); + if (str.endsWith(classExclName1)) { + setFailedStatus("Received unexpected ClassPrepareEvent for excluded class:" + str); + } else { + display("Received expected ClassPrepareEvent for " + str); + } + return true; + } + return false; + } + } + ); + + display("......waiting for ClassPrepareEvent"); + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ClassPrepareRequest setting23ClassPrepareRequest ( String classExclFilter, + int suspendPolicy, + String property ) + throws Failure { + try { + display("......setting up ClassPrepareRequest:"); + display(" class exclude filter: " + classExclFilter + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.setSuspendPolicy(suspendPolicy); + + cpr.addClassExclusionFilter(classExclFilter); + + display(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ClassPrepareRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001/TestDescription.java new file mode 100644 index 00000000000..9919c145b81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * The test checks up that a result of the method + * com.sun.jdi.ClassPrepareRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name does not match a restricted regular expression. + * Regular expressions are limited to exact matches and patterns that + * begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to test include a pattern that begins with '*'. + * The test works as follows: + * The debugger program - nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter001; + * the debuggee program - nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter001 + * nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001a.java new file mode 100644 index 00000000000..e504ba0131e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter001a.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter001 JDI test. + */ + +public class filter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter001a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter001a("thread1"); + log1("run1(thread1);"); + run1(thread1); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + +class Thread1filter001a extends Thread { + + class TestClass10{ + int var10 = 0; + } + class TestClass11 extends TestClass10{ + int var11 = 0; + } + + String tName = null; + + public Thread1filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter001a.log1(" 'run': enter :: threadName == " + tName); + TestClass11 obj1 = new TestClass11(); + filter001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002.java new file mode 100644 index 00000000000..7c0bdb383cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * + * The test checks that results of the method + * com.sun.jdi.ClassPrepareRequest.addClassExclusionFilter(String) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The case to check includes a pattern that ends with '*'. + * + * The test works as follows. + * - The debugger + * - sets up a ClassPrepareRequest, + * - using a string pattern, restricts it with addClassExclusionFilter, + * - resumes the debuggee, and waits for ClassPrepareEvents. + * - The debuggee creates and starts a thread1 + * whose 'run' method creates objects of ClassTypes needed + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs the checks required. + */ + +public class filter002 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter002a"; + return new filter002().runThis(argv, out); + } + + private String classExclFilter1 = "nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.Thread1filter002a.TestClass11*"; + private String classExclName1 = "nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.Thread1filter002a.TestClass11"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + String property1 = "ClassPrepareRequest1"; + ThreadReference thread1 = null; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + eventRequest1 = setting23ClassPrepareRequest(classExclFilter1, + EventRequest.SUSPEND_NONE, + property1); + eventRequest1.enable(); + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof ClassPrepareEvent) { + String str = ((ClassPrepareEvent)event).referenceType().name(); + if (str.endsWith(classExclName1)) { + setFailedStatus("Received ClassPrepareEvent for excluded class:" + str); + } else { + display("Received expected ClassPrepareEvent for " + str); + } + return true; + } + return false; + } + } + ); + + display("......waiting for ClassPrepareEvent"); + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ClassPrepareRequest setting23ClassPrepareRequest ( String classExclFilter, + int suspendPolicy, + String property ) + throws Failure { + try { + display("......setting up ClassPrepareRequest:"); + display(" class exclude filter: " + classExclFilter + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.setSuspendPolicy(suspendPolicy); + + cpr.addClassExclusionFilter(classExclFilter); + + display(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ClassPrepareRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002/TestDescription.java new file mode 100644 index 00000000000..332ac00462f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * The test checks up that a result of the method + * com.sun.jdi.ClassPrepareRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name does not match a restricted regular expression. + * Regular expressions are limited to exact matches and patterns that + * begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to test include a pattern that ends with '*'. + * The test works as follows: + * The debugger program - nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter002; + * the debuggee program - nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter002 + * nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002a.java new file mode 100644 index 00000000000..b09f2db5490 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter002a.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter002 JDI test. + */ + +public class filter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter002a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter002a("thread1"); + log1("run1(thread1);"); + run1(thread1); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + +class Thread1filter002a extends Thread { + + class TestClass10{ + int var10 = 0; + } + class TestClass11 extends TestClass10{ + int var11 = 0; + } + + String tName = null; + + public Thread1filter002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter002a.log1(" 'run': enter :: threadName == " + tName); + TestClass11 obj1 = new TestClass11(); + filter002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java new file mode 100644 index 00000000000..e852f747349 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassPrepareRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ClassPrepareRequest.addClassExclusionFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger
    + * - creates an ClassPrepareRequest and enables it,
    + * - invokes the method addClassExclusionFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassExclusionFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassExclusionFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter003a"; + + private String testedClassName1 = + "nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "ClassPrepareRequest1"; + + eventRequest1 = setting22ClassPrepareRequest(testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + + for (int i = 0; ; i++) { + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + log2("breakpointForCommunication"); + + do { + getEventSet(); + + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) + return; + + log2(" received: " + event); + + if (EventFilters.filtered(event)) { + eventSet.resume(); + } + else { + break; + } + } while (true); + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ClassPrepareRequest setting22ClassPrepareRequest ( String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ClassPrepareRequest:"); + log2(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.setSuspendPolicy(suspendPolicy); + + log2(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingClassPrepareRequest() : " + e); + log3(" ClassPreparenRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ClassPrepareRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003/TestDescription.java new file mode 100644 index 00000000000..64c0a41a9c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * The test checks up that a result of the method + * com.sun.jdi.ClassPrepareRequest.addClassExclusionFilter(String) + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class whose name does not match this restricted regular expression. + * Regular expressions are limited to exact matches and patterns that + * begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter003; + * the debuggee program - nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter003 + * nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addClassExclusionFilter.filter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003a.java new file mode 100644 index 00000000000..2eed72a2ecf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003a.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter003 JDI test. + */ + +public class filter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + +// static Thread1filter003a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// thread1 = new Thread1filter003a("thread1"); +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +/* + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +*/ + +} + +/* +class Thread1filter003a extends Thread { + + class TestClass10{ + int var10 = 0; + } + class TestClass11 extends TestClass10{ + int var11 = 0; + } + + + String tName = null; + + public Thread1filter003a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter003a.log1(" 'run': enter :: threadName == " + tName); + TestClass11 obj1 = new TestClass11(); + filter003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} +*/ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001.java new file mode 100644 index 00000000000..03075ec0cec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * + * The test checks that results of the method + * com.sun.jdi.ClassPrepareRequest.addClassFilter_rt() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to be + * the preparation of the given reference type and any subtypes. + * An event will be generated for any prepared reference type + * that can be safely cast to the given reference type. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a class filter object, to load the Class to + * filter, and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceType for the Class to filter, + * - sets up a ClassPrepareRequest and, using the ReferenceType, + * restricts it to sub-classes of the Class to filter, + * thus restricting the ClassPrepare event only to the thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - The debuggee creates and starts two threads, thread1 and thread2, + * first of them will create an object of sub-Class to be filtered, + * whereas second will create an object to be not filtered. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class filter_rt001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt001a"; + return new filter_rt001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt001aTestClass10"; + + + protected void testRun() { + EventRequest eventRequest1 = null; + String property1 = "ClassPrepareRequest1"; + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = setting21ClassPrepareRequest(testClassReference, + EventRequest.SUSPEND_NONE, property1); + + display("......waiting for ClassPrepareEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ClassPrepareEvent)) { + setFailedStatus("ERROR: new event is not ClassPrepareEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ClassPrepareEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ClassPrepareRequest setting21ClassPrepareRequest ( ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ClassPrepareRequest:"); + display(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.addClassFilter(testedClass); + cpr.setSuspendPolicy(suspendPolicy); + + display(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ClassPrepareRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001/TestDescription.java new file mode 100644 index 00000000000..dc823fdde8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * The test checks up that a result of the method + * com.sun.jdi.ClassPrepareRequest.addClassFilter_rt() + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to be the preparation + * of the given reference type and any subtypes. + * An event will be generated for any prepared reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to be the preparation + * of the given reference type and any subtypes. + * An event will be generated for any prepared reference type + * that can be safely cast to the given reference type. + * The test works as follows: + * The debugger program - nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt001; + * the debuggee program - nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt001 + * nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001a.java new file mode 100644 index 00000000000..80f3c2d6232 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt001a.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt001 JDI test. + */ + +public class filter_rt001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + filter_rt001aTestClass10 obj = new filter_rt001aTestClass10(); + break; + + + case 1: + filter_rt001aThread1 thread1 = new filter_rt001aThread1("thread1"); + filter_rt001aThread2 thread2 = new filter_rt001aThread2("thread2"); + + log1("new filter_rt001a().run1(thread1);"); + new filter_rt001a().run1(thread1); + + log1("new filter_rt001a().run1(thread2);"); + new filter_rt001a().run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + +class filter_rt001aTestClass10{ + static int var10 = 0; +} +class filter_rt001aTestClass11 extends filter_rt001aTestClass10{ + static int var11 = 0; +} +class filter_rt001aThread1 extends Thread { + + String tName = null; + + public filter_rt001aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + filter_rt001aTestClass11 obj1 = new filter_rt001aTestClass11(); + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt001aTestClass20 { + static int var20 = 0; +} +class filter_rt001aTestClass21 { + static int var21 = 0; +} +class filter_rt001aThread2 extends Thread { + + String tName = null; + + public filter_rt001aThread2(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + filter_rt001aTestClass21 obj2 = new filter_rt001aTestClass21(); + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java new file mode 100644 index 00000000000..49960940b05 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java @@ -0,0 +1,540 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassPrepareRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ClassPrepareRequest.addClassFilter_rt()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a class filter object, to load the Class to
    + * filter, and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ClassPrepareRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_rt002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_rt002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt002a"; + + private String testedClassName = + "nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt002aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "ClassPrepareRequest1"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = setting21ClassPrepareRequest(testClassReference, + EventRequest.SUSPEND_NONE, property1); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" no InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testClassReference); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + log2("breakpointForCommunication"); + + do { + getEventSet(); + + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) + return; + + log2(" received: " + event); + + if (EventFilters.filtered(event)) { + eventSet.resume(); + } + else { + break; + } + } while (true); + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ClassPrepareRequest setting21ClassPrepareRequest ( ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ClassPrepareRequest:"); + log2(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); +// cpr.addClassFilter(testedClass); + cpr.setSuspendPolicy(suspendPolicy); + + log2(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingClassPrepareRequest() : " + e); + log3(" ClassPreparenRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ClassPrepareRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002/TestDescription.java new file mode 100644 index 00000000000..8fbba6c4e12 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * The test checks up that a result of the method + * com.sun.jdi.ClassPrepareRequest.addClassFilter_rt() + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to be the preparation + * of the given reference type and any subtypes. + * An event will be generated for any prepared reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt002; + * the debuggee program - nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt002 + * nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002a.java new file mode 100644 index 00000000000..9641f81ec95 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002a.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt002 JDI test. + */ + +public class filter_rt002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt002aThread1 thread1 = null; + + static filter_rt002aTestClass10 obj = new filter_rt002aTestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new filter_rt002aThread1("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + +class filter_rt002aTestClass10{ + static int var10 = 0; +} +class filter_rt002aTestClass11 extends filter_rt002aTestClass10{ + static int var11 = 0; +} +class filter_rt002aThread1 extends Thread { + + String tName = null; + + public filter_rt002aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt002a.log1(" 'run': enter :: threadName == " + tName); + filter_rt002aTestClass11 obj1 = new filter_rt002aTestClass11(); + filter_rt002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003.java new file mode 100644 index 00000000000..9836e5928bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * + * The test checks that results of the method + * com.sun.jdi.ClassPrepareRequest.addClassFilter_rt() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to be + * the preparation of the given reference type and any subtypes. + * The cases to test include re-invocations of the method + * addClassFilter() on the same ClassPrepareRequest object. + * There are two ClassPrepareRequests to check as follows: + * (1) For ClassPrepareRequest2, both invocations are with different + * ReferenceTypes restricting one ClassPrepare event to two classes. + * The test expects no ClassPrepare event will be received. + * (2) For ClassPrepareRequest1, both invocations are with the same + * ReferenceType restricting one ClassPrepare event to one class. + * The test expects this ClassPrepare event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates class filter objects, to load the Classes to + * filter, and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes 1&2 for the Classes to filter, + * - sets up two ClassPrepareRequests 1&2, + * - double restricts ClassPrepareRequest1 to the RefTypes 1 and 1, + * - double restricts ClassPrepareRequest2 to the RefTypes 1 and 2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - The debuggee creates and starts two threads, thread1 and thread2, + * first of them will create an object of sub-Class to be filtered, + * whereas second will create an object to be not filtered. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class filter_rt003 extends TestDebuggerType1 { + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt003a"; + return new filter_rt003().runThis(argv, out); + } + + private String testedClassName10 = + "nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt003aTestClass10"; + + private String testedClassName20 = + "nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt003aTestClass20"; + + + protected void testRun() { + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "ClassPrepareRequest1"; + String property2 = "ClassPrepareRequest2"; + + ReferenceType testClassReference10 = null; + ReferenceType testClassReference20 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + switch (i) { + + case 0: + testClassReference10 = (ReferenceType) vm.classesByName(testedClassName10).get(0); + testClassReference20 = (ReferenceType) vm.classesByName(testedClassName20).get(0); + + eventRequest1 = setting21ClassPrepareRequest(testClassReference10, + EventRequest.SUSPEND_ALL, property1); + + eventRequest2 = setting21ClassPrepareRequest(testClassReference10, + EventRequest.SUSPEND_ALL, property2); + + ((ClassPrepareRequest) eventRequest1).addClassFilter(testClassReference10); + ((ClassPrepareRequest) eventRequest2).addClassFilter(testClassReference20); + + display("......waiting for ClassPrepareEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ClassPrepareEvent)) { + setFailedStatus("ERROR: new event is not ClassPrepareEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ClassPrepareEvent with propety 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ClassPrepareRequest setting21ClassPrepareRequest ( ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ClassPrepareRequest:"); + display(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.addClassFilter(testedClass); + cpr.setSuspendPolicy(suspendPolicy); + + display(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ClassPrepareRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003/TestDescription.java new file mode 100644 index 00000000000..e6812a43e44 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * The test checks up that a result of the method + * com.sun.jdi.ClassPrepareRequest.addClassFilter_rt() + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to be the preparation + * of the given reference type and any subtypes. + * An event will be generated for any prepared reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to be the preparation + * of the given reference type and any subtypes. + * The cases to test include re-invocations of the method + * addClassFilter() on the same ClassPrepareRequest object. + * There are two ClassPrepareRequests to check as follows: + * (1) For ClassPrepareRequest2, both invocations are with different + * ReferenceTypes restricting one ClassPrepare event to two classes. + * The test expects no ClassPrepare event will be received. + * (2) For ClassPrepareRequest1, both invocations are with the same + * ReferenceType restricting one ClassPrepare event to one class. + * The test expects this ClassPrepare event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt003; + * the debuggee program - nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt003 + * nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addClassFilter_rt.filter_rt003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003a.java new file mode 100644 index 00000000000..291d0a9f075 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt003a.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt003 JDI test. + */ + +public class filter_rt003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + filter_rt003aTestClass10 obj1 = new filter_rt003aTestClass10(); + filter_rt003aTestClass20 obj2 = new filter_rt003aTestClass20(); + break; + + + case 1: + filter_rt003aThread1 thread1 = new filter_rt003aThread1("thread1"); + filter_rt003aThread2 thread2 = new filter_rt003aThread2("thread2"); + + log1("new filter_rt003a().run1(thread1);"); + new filter_rt003a().run1(thread1); + + log1("new filter_rt003a().run1(thread2);"); + new filter_rt003a().run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + +class filter_rt003aTestClass10{ + static int var10 = 0; +} +class filter_rt003aTestClass11 extends filter_rt003aTestClass10{ + static int var11 = 0; +} +class filter_rt003aThread1 extends Thread { + + String tName = null; + + public filter_rt003aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + filter_rt003aTestClass11 obj1 = new filter_rt003aTestClass11(); + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt003aTestClass20 { + static int var20 = 0; +} +class filter_rt003aTestClass21 { + static int var21 = 0; +} +class filter_rt003aThread2 extends Thread { + + String tName = null; + + public filter_rt003aThread2(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + filter_rt003aTestClass21 obj2 = new filter_rt003aTestClass21(); + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001.java new file mode 100644 index 00000000000..937a5ea2531 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * + * The test checks that results of the method + * com.sun.jdi.ClassPrepareRequest.addClassFilter(String) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to check include both a pattern that begin with '*' + * one that end with '*'. + * + * The test works as follows. + * - The debugger + * - creates two class filter objects, + * first one using a pattern that begin with '*', and + * second one using a pattern that end with '*' + * to filter ClassPrepareEvents in two debuggee's tested threads, + * - sets up two ClassPrepareRequests, + * - resumes the debuggee, and + * - waits for expected ClassPrepareEvents. + * - The debuggee creates and starts two threads + * whose 'run' methods create objects of ClassTypes needed + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs the checks required. + */ + +public class filter_s001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s001a"; + return new filter_s001().runThis(argv, out); + } + + private String testedClassName1 = "*TestClass11"; + private String testedClassName2 = + "nsk.jdi.ClassPrepareRequest.addClassFilter_s.Thread2filter_s001a*"; + + private String className1 = "TestClass11"; + private String className2 = + "nsk.jdi.ClassPrepareRequest.addClassFilter_s.Thread2filter_s001a"; + + protected void testRun() { + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "ClassPrepareRequest1"; + String property2 = "ClassPrepareRequest2"; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + eventRequest1 = setting22ClassPrepareRequest(testedClassName1, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for ClassPrepareEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ClassPrepareEvent)) { + setFailedStatus("ERROR: new event is not ClassPrepareEvent"); + } else { + String str = ((ClassPrepareEvent)newEvent).referenceType().name(); + if (!str.endsWith(className1)) { + setFailedStatus("Received ClassPrepareEvent for unexpected class: \n\t" + str); + } else { + display("Received ClassPrepareEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ClassPrepareEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + + vm.resume(); + break; + + case 1: + eventRequest2 = setting22ClassPrepareRequest(testedClassName2, + EventRequest.SUSPEND_ALL, property2); + + display("......waiting for ClassPrepareEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ClassPrepareEvent)) { + setFailedStatus("ERROR: new event is not ClassPrepareEvent"); + } else { + + String str = ((ClassPrepareEvent)newEvent).referenceType().name(); + if (!str.endsWith(className2)) { + setFailedStatus("Received ClassPrepareEvent for unexpected class: \n\t" + str); + } else { + display("Received ClassPrepareEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ClassPrepareEvent with property 'number' == " + property); + + if ( !property.equals(property2) ) { + setFailedStatus("ERROR: property is not : " + property2); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ClassPrepareRequest setting22ClassPrepareRequest ( String testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ClassPrepareRequest:"); + display(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.addClassFilter(testedClass); + cpr.setSuspendPolicy(suspendPolicy); + + display(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ClassPrepareRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001/TestDescription.java new file mode 100644 index 00000000000..c4a052e8bd9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * The test checks up that a result of the method + * com.sun.jdi.ClassPrepareRequest.addClassFilter_s() + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those whose location is in a class + * whose name matches a restricted regular expression. + * Regular expressions are limited to exact matches and patterns that + * begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The test works as follows: + * The debugger program - nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s001; + * the debuggee program - nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was modified to fix the bug: + * 4627990 JDI testcase filter_s001 failing + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s001 + * nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001a.java new file mode 100644 index 00000000000..f96143acfb6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s001a.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s001 JDI test. + */ + +public class filter_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 2; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + Thread1filter_s001a thread1 = new Thread1filter_s001a("thread1"); + log1("new filter_s001a().run1(thread1);"); + new filter_s001a().run1(thread1); + break; + + case 1: + Thread2filter_s001a thread2 = new Thread2filter_s001a("thread2"); + log1("new filter_s001a().run1(thread2);"); + new filter_s001a().run1(thread2); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + +class Thread1filter_s001a extends Thread { + + class TestClass10{ + int var10 = 0; + } + class TestClass11 extends TestClass10{ + int var11 = 0; + } + + String tName = null; + + public Thread1filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + TestClass11 obj1 = new TestClass11(); + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class Thread2filter_s001a extends Thread { + + String tName = null; + + public Thread2filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + filter_s001aTestClass21 obj2 = new filter_s001aTestClass21(); + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_s001aTestClass21 { + int var21 = 0; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java new file mode 100644 index 00000000000..68649fb18e9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java @@ -0,0 +1,537 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassPrepareRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ClassPrepareRequest.addClassFilter_s()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a class filter object,
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ClassPrepareRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_s002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_s002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s002a"; + + private String testedClassName1 = + "nsk.jdi.ClassPrepareRequest.addClassFilter_s.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "ClassPrepareRequest1"; + + eventRequest1 = setting22ClassPrepareRequest(testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ClassPrepareRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + log2("breakpointForCommunication"); + + do { + getEventSet(); + + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) + return; + + log2(" received: " + event); + + if (EventFilters.filtered(event)) { + eventSet.resume(); + } + else { + break; + } + } while (true); + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ClassPrepareRequest setting22ClassPrepareRequest ( String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ClassPrepareRequest:"); + log2(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); +// cpr.addClassFilter(testedClass); + cpr.setSuspendPolicy(suspendPolicy); + + log2(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingClassPrepareRequest() : " + e); + log3(" ClassPreparenRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ClassPrepareRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002/TestDescription.java new file mode 100644 index 00000000000..d131b3de9e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassPrepareRequest. + * The test checks up that a result of the method + * com.sun.jdi.ClassPrepareRequest.addClassFilter(String) + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class whose name matches a restricted regular expression. + * Regular expressions are limited to exact matches and patterns that + * begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s002; + * the debuggee program - nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s002 + * nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addClassFilter_s.filter_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002a.java new file mode 100644 index 00000000000..0395c7fc789 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002a.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassPrepareRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s002 JDI test. + */ + +public class filter_s002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_s002a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_s002a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + + +class Thread1filter_s002a extends Thread { + + class TestClass10{ + int var10 = 0; + } + class TestClass11 extends TestClass10{ + int var11 = 0; + } + + + String tName = null; + + public Thread1filter_s002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s002a.log1(" 'run': enter :: threadName == " + tName); + TestClass11 obj1 = new TestClass11(); + filter_s002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/TestClass2.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/TestClass2.java new file mode 100644 index 00000000000..756e8d96fb4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/TestClass2.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2008, 2018, 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 nsk.jdi.ClassPrepareRequest.addSourceNameFilter.addSourceNameFilter001; + +/* + * Dummy class used for ClassPrepareRequest testing + */ +public class TestClass2 { + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/addSourceNameFilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/addSourceNameFilter001.java new file mode 100644 index 00000000000..65f66e07d97 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001/addSourceNameFilter001.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter001. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.ClassPrepareRequest.addSourceNameFilter(String sourceNamePattern) + * complies with its spec: + * "Restricts the events generated by this request to the preparation of reference types for which the + * restricted regular expression 'sourceNamePattern' matches one of the 'sourceNames' for the reference type + * being prepared." + * Test scenario: + * Debugger VM create ClassPrepareEventRequest, add source name filter and force debuggee load class. When debuggee + * finish class loading debugger checks is ClassPrepareEvent was correct filtered or not. + * Following source name filters are used: + * - exact source name + * - invalid source name (don't expect events with this filter) + * - pattern starting with '*' + * - pattern ending with '*' + * + * @library /vmTestbase + * /test/lib + * + * @build nsk.jdi.ClassPrepareRequest.addSourceNameFilter.addSourceNameFilter001.addSourceNameFilter001 + * nsk.jdi.ClassPrepareRequest.addSourceNameFilter.addSourceNameFilter001.TestClass2 + * nsk.share.jdi.TestClass1 + * @run driver jdk.test.lib.FileInstaller . . + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addSourceNameFilter.addSourceNameFilter001.addSourceNameFilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + */ + +package nsk.jdi.ClassPrepareRequest.addSourceNameFilter.addSourceNameFilter001; + +import java.io.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.*; +import nsk.share.jpda.AbstractDebuggeeTest; +import java.util.*; + +public class addSourceNameFilter001 extends TestDebuggerType2 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new addSourceNameFilter001().runIt(argv, out); + } + + protected boolean canRunTest() { + if (!vm.canUseSourceNameFilters()) { + log.display("TEST CANCELLED due to: vm.canUseSourceNameFilters() = false"); + return false; + } else + return true; + } + + protected String debuggeeClassName() { + if (classpath == null) + throw new TestBug("Debugger requires 'testClassPath' parameter"); + + return AbstractJDIDebuggee.class.getName() + " -testClassPath " + classpath; + } + + // listener counting ClassPrepareEvent + public class ClassPrepareEventListener extends EventHandler.EventListener { + + private boolean eventReceived; + + private String expectedClassName; + + ClassPrepareEventListener(String expectedClassName) { + this.expectedClassName = expectedClassName; + } + + public boolean eventReceived(Event event) { + if (event instanceof ClassPrepareEvent) { + ClassPrepareEvent classPrepareEvent = (ClassPrepareEvent) event; + log.display("Received ClassPrepareEvent: '" + event + "'. Event for class: " + classPrepareEvent.referenceType().name()); + + if (eventReceived) { + setSuccess(false); + log.complain("Only 1 ClassPrepareEvent is expected for tested request"); + } else { + if (!classPrepareEvent.referenceType().name().equals(expectedClassName)) { + setSuccess(false); + log.complain("Received event for wrong class, expected class is " + expectedClassName); + } + eventReceived = true; + } + + vm.resume(); + return true; + } + + return false; + } + } + + private EventHandler eventHandler; + + // force debuggee load class and check is ClassPrepareEvent was generated + private void testSourceFilter(String expectedClassName, + List classesToLoad, + String sourceName, + boolean expectEvent) { + ClassPrepareRequest request; + + // create request with filter + request = debuggee.getEventRequestManager().createClassPrepareRequest(); + request.setSuspendPolicy(EventRequest.SUSPEND_ALL); + request.addSourceNameFilter(sourceName); + request.enable(); + + // this listener waits for ClassPrepareEvent + ClassPrepareEventListener listener = new ClassPrepareEventListener(expectedClassName); + eventHandler.addListener(listener); + + for (String className : classesToLoad) { + log.display("Loading class: " + className + ", using following source filter: " + sourceName); + + // force debuggee load class + pipe.println(AbstractDebuggeeTest.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + } + + request.disable(); + + eventHandler.removeListener(listener); + + // check is event was correctly filtered or not + if (expectEvent) { + if (!listener.eventReceived) { + setSuccess(false); + log.complain("Expected ClassPrepareEvent was not received"); + } + } else { + if (listener.eventReceived) { + setSuccess(false); + log.complain("Unexpected ClassPrepareEvent was received"); + } + } + } + + public void doTest() { + eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + String className = "nsk.share.jdi.TestClass1"; + String sourceName = "TestClass1.java"; + + List classesToLoad = new ArrayList(); + classesToLoad.add(className); + // don't expect events for TestClass2 + classesToLoad.add(TestClass2.class.getName()); + + // set invalid source name, don't expect events + testSourceFilter(className, classesToLoad, sourceName + "_InvalidSourceName", false); + + // set valid source name + testSourceFilter(className, classesToLoad, sourceName, true); + + sourceName = "TestClass1.*"; + // use pattern filter ending with '*' + testSourceFilter(className, classesToLoad, sourceName, true); + + sourceName = "*Class1.java"; + // use pattern filter starting with '*' + testSourceFilter(className, classesToLoad, sourceName, true); + + eventHandler.stopEventHandler(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter002/addSourceNameFilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter002/addSourceNameFilter002.java new file mode 100644 index 00000000000..c9b7616c6cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter002/addSourceNameFilter002.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ClassPrepareRequest/addSourceNameFilter/addSourceNameFilter002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.ClassPrepareRequest.addSourceNameFilter(String sourceNamePattern) + * complies with its spec: + * "Restricts the events generated by this request to the preparation of reference types for which the + * restricted regular expression 'sourceNamePattern' matches one of the 'sourceNames' for the reference type + * being prepared." + * Test scenario: + * Debugger create following class file: + * - class file containing multiple strata + * - SourceDebugExtension's source map refers to multiple sources + * Debugger VM create ClassPrepareEventRequest, add source name filter(use names of all sources which was added to class + * file) and force debuggee load class from generated class file. When debuggee finish class loading debugger check is + * ClassPrepareEvent was correct filtered or not. + * Following source name filters are used: + * - exact source name + * - invalid source name (don't expect events with this filter) + * - pattern starting with '*' + * - pattern ending with '*' + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassPrepareRequest.addSourceNameFilter.addSourceNameFilter002.addSourceNameFilter002 + * nsk.share.jdi.TestClass1 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassPrepareRequest.addSourceNameFilter.addSourceNameFilter002.addSourceNameFilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -sourceCount 2 + */ + +package nsk.jdi.ClassPrepareRequest.addSourceNameFilter.addSourceNameFilter002; + +import java.io.*; +import java.util.ArrayList; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.*; +import nsk.share.jdi.sde.*; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class addSourceNameFilter002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new addSourceNameFilter002().runIt(argv, out); + } + + protected boolean canRunTest() { + if (!vm.canUseSourceNameFilters()) { + log.display("TEST CANCELLED due to: vm.canUseSourceNameFilters() = false"); + return false; + } else + return true; + } + + private int sourceCount; + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-sourceCount") && (i < args.length - 1)) { + sourceCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + if (sourceCount == 0) { + throw new TestBug("Debugger requires 'sourceCount' parameter"); + } + + return standardArgs.toArray(new String[] {}); + } + + protected String debuggeeClassName() { + // debugee should load classes from test work directory + return AbstractJDIDebuggee.class.getName() + " -testClassPath " + testWorkDir; + } + + // listener counting ClassPrepareEvent + public class ClassPrepareEventListener extends EventHandler.EventListener { + public int eventReceived; + + public boolean eventReceived(Event event) { + if (event instanceof ClassPrepareEvent) { + ClassPrepareEvent classPrepareEvent = (ClassPrepareEvent) event; + eventReceived++; + + log.display("Event received: " + event + " Class: " + classPrepareEvent.referenceType().name()); + + vm.resume(); + + return true; + } + + return false; + } + } + + private EventHandler eventHandler; + + private void testSourceFilter(String className, String sourceName, boolean expectEvent) { + ClassPrepareRequest request; + + // create request with filter + request = debuggee.getEventRequestManager().createClassPrepareRequest(); + request.setSuspendPolicy(EventRequest.SUSPEND_ALL); + request.addSourceNameFilter(sourceName); + request.enable(); + + // this listener wait ClassPrepareEvent + ClassPrepareEventListener listener = new ClassPrepareEventListener(); + eventHandler.addListener(listener); + + log.display("Load class: " + className + ", use follows source filter: " + sourceName); + + // force debuggee load class + pipe.println(AbstractDebuggeeTest.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + request.disable(); + + eventHandler.removeListener(listener); + + // check is event was correct filtered or not + if (expectEvent) { + if (listener.eventReceived == 0) { + setSuccess(false); + log.complain("Expected ClassPrepareEvent was not received"); + } + } else { + if (listener.eventReceived > 0) { + setSuccess(false); + log.complain("Unexpected ClassPrepareEvent was received"); + } + } + } + + // create class file with multiple strata + private void preparePathcedClassFile(String className, String testStratumSourceNames[]) { + String smapFileName = "TestSMAP.smap"; + + SmapGenerator smapGenerator = new SmapGenerator(); + + SmapStratum smapStratum = new SmapStratum("TestStratum"); + + for (String testStratumSourceName : testStratumSourceNames) { + smapStratum.addFile(testStratumSourceName); + // add dummy line data + smapStratum.addLineData(1, testStratumSourceName, 1, 1, 1); + smapGenerator.addStratum(smapStratum, true); + } + + savePathcedClassFile(className, smapGenerator, smapFileName); + } + + public void doTest() { + String className = "nsk.share.jdi.TestClass1"; + String sourceName = "TestClass1.java"; + + String testStratumSourceNames[] = new String[sourceCount]; + // {"TestStratum1_Source.tss1", "TestStratum2_Source.tss2"}; + + for (int i = 0; i < testStratumSourceNames.length; i++) + testStratumSourceNames[i] = "TestStratum" + i + "_Source.tss" + i; + + // create class file with multiple strata + preparePathcedClassFile(className, testStratumSourceNames); + + eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + // set valid source name + testSourceFilter(className, sourceName, true); + for (int i = 0; i < testStratumSourceNames.length; i++) { + testSourceFilter(className, testStratumSourceNames[i], true); + } + + // set invalid source name, don't expect events + testSourceFilter(className, sourceName + "_InvalidSourceName", false); + for (int i = 0; i < testStratumSourceNames.length; i++) { + testSourceFilter(className, testStratumSourceNames[i] + "_InvalidSourceName", false); + } + + // use pattern filter + testSourceFilter(className, "TestClass1*", true); + + for (int i = 0; i < testStratumSourceNames.length; i++) + testSourceFilter(className, "TestStratum" + i + "*", true); + + testSourceFilter(className, "*.java", true); + + for (int i = 0; i < testStratumSourceNames.length; i++) + testSourceFilter(className, "*.tss" + i, true); + + eventHandler.stopEventHandler(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001.java new file mode 100644 index 00000000000..8ecef8ec440 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001.java @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.allInterfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.allInterfaces()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * 1) Class0ForCheck doesn't implement interface
    + * 2) Class1ForCheck implements one direct and
    + * one indirect interface
    + * 3) Class2ForCheck implements one direct and
    + * two indirect interfaces
    + * 4) Class3ForCheck extends Class2ForCheck,
    + * hence implements one direct and
    + * two indirect interfaces
    + *
    + */ + +public class allinterfaces001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/allInterfaces/allinterfaces001", + sHeader2 = "--> allinterfaces001: ", + sHeader3 = "##> allinterfaces001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new allinterfaces001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.allInterfaces.allinterfaces001a"; + + String mName = "nsk.jdi.ClassType.allInterfaces"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("allinterfaces001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType classRefType = null; + ReferenceType reftype = null; + List l = null; + Method m = null; + String name = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // Class0ForCheck - 0 interfaces + + List list0 = vm.classesByName(mName + ".Class0ForCheck"); + + classRefType = (ReferenceType) list0.get(0); + + List iface0list = + ((ClassType) classRefType).allInterfaces(); + + if (iface0list.size() != 0) { + log3("ERROR : iface0list.size() != 0 in case: Class0ForCheck"); + expresult = 1; + break; + } + + break ; + + case 1: // Class1forCheck - 1 direct and 1 indirect interfaces + + List list1 = vm.classesByName(mName + ".Class1ForCheck"); + + classRefType = (ReferenceType) list1.get(0); + + List iface1list = + ((ClassType) classRefType).allInterfaces(); + + if (iface1list.size() != 2) { + log3("ERROR : iface1list.size() != 2 in case: Class1forCheck :" + iface1list.size()); + expresult = 1; + break; + } + + reftype = (ReferenceType) iface1list.get(0); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + if (!name.equals(mName + ".Iface2")) { + log3("ERROR : name1: !name.equals('.Iface1' or '.Iface2') in Class1forCheck"); + expresult = 1; + break; + } + } + reftype = (ReferenceType) iface1list.get(1); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + if (!name.equals(mName + ".Iface2")) { + log3("ERROR :name2: !name.equals('.Iface1' or '.Iface2') in Class1forCheck"); + expresult = 1; + break; + } + } + break; + + case 2: // Class2ForCheck - 1 direct and 2 indirect interfaces + + List list2 = vm.classesByName(mName + ".Class2ForCheck"); + + classRefType = (ReferenceType) list2.get(0); + + List iface2list = + ((ClassType) classRefType).allInterfaces(); + + if (iface2list.size() != 3) { + log3("ERROR : iface2list.size() != 3 in case: Class2forCheck"); + expresult = 1; + break; + } + + reftype = (ReferenceType) iface2list.get(0); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface3")) { + log3("ERROR : name1: !name.equals('.Iface1' or '.Iface3' or 'Iface3) in Class2forCheck"); + expresult = 1; + break; + } + } + } + reftype = (ReferenceType) iface2list.get(1); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface3")) { + log3("ERROR : name1: !name.equals('.Iface1' or '.Iface3' or 'Iface3) in Class2forCheck"); + expresult = 1; + break; + } + } + } + reftype = (ReferenceType) iface2list.get(2); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface3")) { + log3("ERROR : name1: !name.equals('.Iface1' or '.Iface3' or 'Iface3) in Class2forCheck"); + expresult = 1; + break; + } + } + } + break; + + case 3: // Class3ForCheck - 1 direct and 2 indirect interfaces + + List list3 = vm.classesByName(mName + ".Class3ForCheck"); + + classRefType = (ReferenceType) list3.get(0); + + List iface3list = + ((ClassType) classRefType).allInterfaces(); + + if (iface3list.size() != 3) { + log3("ERROR : iface3list.size() != 3 in case: Class3forCheck"); + expresult = 1; + break; + } + + reftype = (ReferenceType) iface3list.get(0); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface3")) { + log3("ERROR : name1: !name.equals('.Iface1' or '.Iface3' or 'Iface3) in Class3forCheck"); + expresult = 1; + break; + } + } + } + reftype = (ReferenceType) iface3list.get(1); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface3")) { + log3("ERROR : name1: !name.equals('.Iface1' or '.Iface3' or 'Iface3) in Class3forCheck"); + expresult = 1; + break; + } + } + } + reftype = (ReferenceType) iface3list.get(2); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface3")) { + log3("ERROR : name1: !name.equals('.Iface1' or '.Iface3' or 'Iface3) in Class3forCheck"); + expresult = 1; + break; + } + } + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001/TestDescription.java new file mode 100644 index 00000000000..18f8870a2cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/allInterfaces/allinterfaces001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.allInterfaces() + * complies with its spec: + * public java.util.List allInterfaces() + * Gets the interfaces directly and indirectly implemented by this class. + * Interfaces returned by interfaces() are returned as well all superinterfaces. + * Returns: a List of InterfaceType objects each mirroring an interface of + * this ClassType in the target VM. + * If none exist, returns a zero length List. + * Throws: ClassNotPreparedException - + * if this class not yet been prepared. + * ObjectCollectedException - + * if this class has been unloaded and garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.allInterfaces.allinterfaces001; + * the debuggee program - nsk.jdi.ClassType.allInterfaces.allinterfaces001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.allInterfaces.allinterfaces001 + * nsk.jdi.ClassType.allInterfaces.allinterfaces001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.allInterfaces.allinterfaces001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001a.java new file mode 100644 index 00000000000..87de013a474 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces001a.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.allInterfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the allinterfaces001 JDI test. + */ + +public class allinterfaces001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> allinterfaces001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> allinterfaces001a: " + message); + } + + //====================================================== test program + + static Class0ForCheck class0 = null; + static Class1ForCheck class1 = null; + static Class2ForCheck class2 = null; + static Class3ForCheck class3 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + // check implemented interfaces + boolean isComparable = false; + boolean isSerializable = false; + boolean isCloneable = false; + boolean is_allinterfaces002i = false; + + Iterator it = checkedClass.allInterfaces().iterator(); + while (it.hasNext()) { + InterfaceType i = it.next(); + if (i.name().equals("java.lang.Comparable")) { + isComparable = true; + } else if (i.name().equals("java.io.Serializable")) { + isSerializable = true; + } else if (i.name().equals("java.lang.Cloneable")) { + isCloneable = false; + } else if (i.name().equals("nsk.jdi.ClassType.allInterfaces.allinterfaces002i")) { + is_allinterfaces002i = true; + } + + } + + if (isComparable) { + display("CHECK1 PASSED: " + className + " implements Comparable"); + } else { + complain("CHECK1 FAILED: " + className + " does not implement Comparable"); + exitStatus = Consts.TEST_FAILED; + } + + if (isSerializable) { + display("CHECK2 PASSED: " + className + " implements Serializable"); + } else { + complain("CHECK2 FAILED: " + className + " does not implement Serializable"); + exitStatus = Consts.TEST_FAILED; + } + + if (!isCloneable) { + display("CHECK3 PASSED: " + className + " does not implement Cloneable"); + } else { + complain("CHECK3 FAILED: " + className + " implements Cloneable"); + exitStatus = Consts.TEST_FAILED; + } + + if (fieldName.equals("f3") || fieldName.equals("f7")) { + if (is_allinterfaces002i) { + display("CHECK4 PASSED: " + className + " implements allinterfaces002i"); + } else { + complain("CHECK4 FAILED: " + className + " does not implement allinterfaces002i"); + exitStatus = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002/TestDescription.java new file mode 100644 index 00000000000..eb5be2f7601 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/allInterfaces/allinterfaces002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for allInterfaces() method of ClassType interface. + * The test checks if the method: + * - returns Comparable and Serializable interfaces implemented + * by java.lang.Enum, + * - does not return Cloneable interfaces + * for any mirrored enum type. + * Besides this, the test checks if the method returns expected + * nsk.jdi.ClassType.allInterfaces.allinterfaces002i interface + * for any enum type which implements this interface + * The test consists of a debugger program (allinterfaces002.java) + * and debuggee application (allinterfaces002a.java). + * Package name is nsk.jdi.ClassType.allInterfaces . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls allInterfaces() method for each field + * of enum type declared in allinterfaces002a class. + * The test fails if any of expected interfaces has not been + * returned or Cloneable interface has been returned in the result + * list. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.allInterfaces.allinterfaces002 + * nsk.jdi.ClassType.allInterfaces.allinterfaces002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.allInterfaces.allinterfaces002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002a.java new file mode 100644 index 00000000000..7934282ca64 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/allInterfaces/allinterfaces002a.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.allInterfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class allinterfaces002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum2 f2 = Enum2.e2; + static Enum3 f3 = Enum3.e1; + static Enum4.Enum4_ f4 = Enum4.Enum4_.e1; + static allinterfaces002Enum5 f5 = allinterfaces002Enum5.e2; + static allinterfaces002Enum6 f6 = allinterfaces002Enum6.e1; + static allinterfaces002Enum7 f7 = allinterfaces002Enum7.e2; + static allinterfaces002Enum8.Enum8_ f8 = allinterfaces002Enum8.Enum8_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(allinterfaces002.SIGNAL_READY); + + + //pipe.println(allinterfaces002.SIGNAL_GO); + receiveSignal(allinterfaces002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + enum Enum1 { + e1, e2; + } + + enum Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); + } + + enum Enum3 implements allinterfaces002i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); + } + + enum Enum4 { + e1, e2; + + enum Enum4_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum allinterfaces002Enum5 { + e1, e2; +} + +enum allinterfaces002Enum6 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} + +enum allinterfaces002Enum7 implements allinterfaces002i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); +} + +enum allinterfaces002Enum8 { + e1, e2; + enum Enum8_ { + e1, e2; + } +} + +interface allinterfaces002i { + int i = 1; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001.java new file mode 100644 index 00000000000..0b2d8565017 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.concreteMethodByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.concreteMethodByName()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * 1) 8 methods with return types of
    + * all primitive types (cases 0-7 below)
    + * 2) 1 method with the void type (case 8)
    + * 3) 3 methods with return types of
    + * all reference types (cases 9-11)
    + *
    + */ + +public class method001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/concreteMethodByName/method001", + sHeader2 = "--> method001: ", + sHeader3 = "##> method001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new method001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.concreteMethodByName.method001a"; + + String mName = "nsk.jdi.ClassType.concreteMethodByName"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("method001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType classRefType = null; + + Method m = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // Class1 without abstract methods + + List list1 = vm.classesByName(mName + ".Class1ForCheck"); + + ClassType classType1 = + (ClassType) (ReferenceType) list1.get(0); + if (classType1 == null) { + log3("ERROR : classType1 == null in case: Class1"); + expresult = 1; + break; + } + + int i3; + boolean endFlag = false; + + for (i3 = 0; ; i3++) { + switch (i3) { + + case 0 : m = classType1.concreteMethodByName + ("blValue", "()Z"); + break ; + + case 1 : m = classType1.concreteMethodByName + ("btValue", "()B"); + break ; + + case 2 : m = classType1.concreteMethodByName + ("chValue", "()C"); + break ; + + case 3 : m = classType1.concreteMethodByName + ("dbValue", "()D"); + break ; + + case 4 : m = classType1.concreteMethodByName + ("flValue", "()F"); + break ; + + case 5 : m = classType1.concreteMethodByName + ("inValue", "()I"); + break ; + + case 6 : m = classType1.concreteMethodByName + ("lnValue", "()J"); + break ; + + case 7 : m = classType1.concreteMethodByName + ("shValue", "()S"); + break ; + + + case 8 : m = classType1.concreteMethodByName + ("vdValue", "()V"); + break ; + + + case 9 : m = classType1.concreteMethodByName + ("inArray", "()[I"); + break ; + + case 10 : m = classType1.concreteMethodByName + ("classMethod", "()Lnsk/jdi/ClassType/concreteMethodByName/Class2ForCheck;"); + break ; + + case 11 : m = classType1.concreteMethodByName + ("ifaceMethod", "()Lnsk/jdi/ClassType/concreteMethodByName/IfaceForCheck;"); + break ; + + + default: endFlag = true; + break ; + } + + if (m == null) { + expresult = 1; + log3("ERROR : no methods returned : " + i3); + } + if (endFlag) break ; + } + + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001/TestDescription.java new file mode 100644 index 00000000000..62f9d0053f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/concreteMethodByName/method001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.concreteMethodByName() + * complies with the following requirements: + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.concreteMethodByName.method001; + * the debuggee program - nsk.jdi.ClassType.concreteMethodByName.method001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.concreteMethodByName.method001 + * nsk.jdi.ClassType.concreteMethodByName.method001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.concreteMethodByName.method001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001a.java new file mode 100644 index 00000000000..0e5c9fb6f57 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method001a.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.concreteMethodByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the method001 JDI test. + */ + +public class method001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> method001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> method001a: " + message); + } + + //====================================================== test program + + static Class1ForCheck class1 = null; + static Class2ForCheck class2 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.ClassType.concreteMethodByName(String, String)
    + * for boundary value of parameters.
    + * + * In any cases it is expected, this method will return either the Method + * that matches the given name and signature or null if there is + * no match. No exception is expected. + * All variants of argument values are placed in parameters array. + * Also, this array contains an expected return value for every pair of + * arguments values:
    + * null - return value of concreteMethodByName()
    is + * null + * "T" - return value of concreteMethodByName()
    is not + * null + */ + +public class method002 { + + private final static String prefix = "nsk.jdi.ClassType.concreteMethodByName."; + private final static String debuggerName = prefix + "method002"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private ClassType testedClass; + + private String [][] parameters = { +// methodName signature result + {"justMethod", "(I)I", "T"}, + {"justMethod", null, null}, + {null, "(I)I", null}, + {null, null, null}, + {"", "", null} + }; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + method002 thisTest = new method002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + testedClass = (ClassType )debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + Method method; + for (int i = 0; i < parameters.length; i ++) { + display("invoking concreteMethodByName(\"" + parameters[i][0] + + "\",\"" + parameters[i][1] + "\")"); + try { + method = testedClass.concreteMethodByName(parameters[i][0], + parameters[i][1]); + if (parameters[i][2] != null) { + if (method == null) { + complain("Method : " + method); + exitStatus = Consts.TEST_FAILED; + } else { + display("Method : " + method); + } + } else { + if (method == null) { + display("Method : " + method); + } else { + complain("Method : " + method); + exitStatus = Consts.TEST_FAILED; + } + } + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + display(""); + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002/TestDescription.java new file mode 100644 index 00000000000..88a7b0f333d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/concreteMethodByName/method002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method + * com.sun.jdi.ClassType.concreteMethodByName(String, String) + * for boundary value of parameters. + * In any cases it is expected, this method will return either the method + * that matches the given name and signature or null if there is no match. + * No exception is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.concreteMethodByName.method002 + * nsk.jdi.ClassType.concreteMethodByName.method002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.concreteMethodByName.method002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002a.java new file mode 100644 index 00000000000..b1af468bd5e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/concreteMethodByName/method002a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.concreteMethodByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * method002a is deugee's part of the method002. + */ +public class method002a { + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(method002.SGNL_READY); + String instr = pipe.readln(); + if (instr.equals(method002.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static int justMethod(int val) { + return val; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001.java new file mode 100644 index 00000000000..429556ceffe --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.interfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.interfaces()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * 1) Class0ForCheck doesn't implement interfaces
    + * 2) Class1ForCheck implements one interface
    + * 2) Class2ForCheck implements two interfaces
    + *
    + */ + +public class interfaces001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/interfaces/interfaces001", + sHeader2 = "--> interfaces001: ", + sHeader3 = "##> interfaces001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new interfaces001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.interfaces.interfaces001a"; + + String mName = "nsk.jdi.ClassType.interfaces"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("interfaces001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType classRefType = null; + ReferenceType reftype = null; + List l = null; + Method m = null; + String name = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // Class0ForCheck - 0 interfaces + + List list0 = vm.classesByName(mName + ".Class0ForCheck"); + + classRefType = (ReferenceType) list0.get(0); + + List iface0list = + ((ClassType) classRefType).interfaces(); + + if (iface0list.size() != 0) { + log3("ERROR : iface0list.size() != 0 in case: Class0ForCheck"); + expresult = 1; + break; + } + + break; + + case 1: // Class1forCheck - 1 interface + + List list1 = vm.classesByName(mName + ".Class1ForCheck"); + + classRefType = (ReferenceType) list1.get(0); + + List iface1list = + ((ClassType) classRefType).interfaces(); + + if (iface1list.size() != 1) { + log3("ERROR : iface1list.size() != 1 in case: Class1forCheck"); + expresult = 1; + break; + } + + reftype = (ReferenceType) iface1list.get(0); + name = reftype.name(); + if (!name.equals(mName + ".Iface1")) { + log3("ERROR : !name.equals(mName + '.Iface1') in Class1forCheck"); + expresult = 1; + break; + } + + break; + + case 2: // Class2ForCheck - 2 interfaces + + List list2 = vm.classesByName(mName + ".Class2ForCheck"); + + classRefType = (ReferenceType) list2.get(0); + + List iface2list = + ((ClassType) classRefType).interfaces(); + + if (iface2list.size() != 2) { + log3("ERROR : iface1list.size() != 2 in case: Class2forCheck"); + expresult = 1; + break; + } + + reftype = (ReferenceType) iface2list.get(0); + name = reftype.name(); + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface3")) { + log3("ERROR : name1: !name.equals('.Iface1' or '.Iface3') in Class2forCheck"); + expresult = 1; + break; + } + } + reftype = (ReferenceType) iface2list.get(1); + name = reftype.name(); + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface3")) { + log3("ERROR :name2: !name.equals('.Iface1' or '.Iface3') in Class2forCheck"); + expresult = 1; + break; + } + } + + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001/TestDescription.java new file mode 100644 index 00000000000..177f1e2ed8b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/interfaces/interfaces001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.interfaces() + * complies with its spec: + * public java.util.List interfaces() + * Gets the interfaces directly implemented by this class. + * Only the interfaces that are declared with the "implements" keyword + * in this class are included. + * Returns: a List of InterfaceType objects each mirroring a direct interface + * this ClassType in the target VM. + * If none exist, returns a zero length List. + * Throws: ClassNotPreparedException - + * if this class not yet been prepared. + * ObjectCollectedException - + * if this class has been unloaded and garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.interfacesinterfaces001; + * the debuggee program - nsk.jdi.ClassType.interfaces.interfaces001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.interfaces.interfaces001 + * nsk.jdi.ClassType.interfaces.interfaces001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.interfaces.interfaces001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001a.java new file mode 100644 index 00000000000..dc959a474ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces001a.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.interfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the interfaces001 JDI test. + */ + +public class interfaces001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> interfaces001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> interfaces001a: " + message); + } + + //====================================================== test program + + static Class0ForCheck class0 = null; + static Class1ForCheck class1 = null; + static Class2ForCheck class2 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + List interfaces = checkedClass.interfaces(); + if (interfaces.size() != 1) { + complain("ClassType.interfaces() returned for " + className + " a list of unexpected size:" + interfaces.size()); + complain("\t Expected size: 1"); + exitStatus = Consts.TEST_FAILED; + Iterator it = interfaces.iterator(); + while (it.hasNext()) { + InterfaceType i = it.next(); + complain("\t Interface returned in the list : " + i.name()); + } + } else if (interfaces.get(0).name().equals("nsk.jdi.ClassType.interfaces.interfaces002i")) { + display(className + " implements interfaces002i"); + } else { + complain(className + " does not implement interfaces002i"); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002/TestDescription.java new file mode 100644 index 00000000000..61f9ece0714 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/interfaces/interfaces002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for interfaces() method of ClassType interface. + * The test checks if the method returns expected + * nsk.jdi.ClassType.interfaces.interfaces002i interface + * for any enum type which implements this interface + * The test consists of a debugger program (interfaces002.java) + * and debuggee application (interfaces002a.java). + * Package name is nsk.jdi.ClassType.interfaces . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls interfaces() method for each field + * of enum type declared in interfaces002a class. + * The test fails if the expected interface has not been + * returned in the result list. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.interfaces.interfaces002 + * nsk.jdi.ClassType.interfaces.interfaces002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.interfaces.interfaces002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002a.java new file mode 100644 index 00000000000..66d547ce0f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/interfaces/interfaces002a.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.interfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class interfaces002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static interfaces002Enum1 f1 = interfaces002Enum1.e2; + static interfaces002Enum2 f2 = interfaces002Enum2.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(interfaces002.SIGNAL_READY); + receiveSignal(interfaces002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum interfaces002Enum1 implements interfaces002i { + e1, e2; +} + +enum interfaces002Enum2 implements interfaces002i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); +} + +interface interfaces002i { + int i = 1; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001.java new file mode 100644 index 00000000000..4b5023c92b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001.java @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.invokeMethod()
    + * complies with its spec when invoked methods are of
    + * all primitive types and the void type.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger invokes debuggee's methods:
    + * boolean blValue();
    + * byte btValue();
    + * char chValue();
    + * double dbValue();
    + * float flValue();
    + * int inValue();
    + * long lnValue();
    + * short shValue();
    + * void vdValue();
    + * and checks up that returned Value objects are
    + * corresponding PrimitiveValue objects and
    + * a VoidValue object.
    + *
    + */ + +public class invokemethod001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/invokeMethod/invokemethod001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new invokemethod001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.invokeMethod.invokemethod001a"; + + private String testedClassName = + "nsk.jdi.ClassType.invokeMethod.Threadinvokemethod001a"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("location001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + // BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + ClassType classType = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + classType = (ClassType) testedclass; + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + Value returnValue = null; + + String methodNamnes[] = {"blValue" , "btValue" , + "chValue" , "dbValue" , + "flValue" , "inValue" , + "lnValue" , "shValue" , + "vdValue" }; + + String types[] = { "BooleanValue", "ByteValue", "CharValue", + "DoubleValue", "FloatValue", "IntegerValue", + "LongValue", "ShortValue", "VoidValue" }; + + log2(" beginning of invoking methods"); + label: { + for (int i3 = 0; i3 <= 8; i3++) { + + log2(" checking up " + types[i3] + " method"); + + List invokeMethods = + testedclass.methodsByName(methodNamnes[i3]); + Method invokeMethod = (Method) invokeMethods.get(0); + + List argumentList = Collections.emptyList(); +// List argumentList = +// invokeMethods; +// argumentList.clear(); + + try { + returnValue = + classType.invokeMethod(thread2, + invokeMethod, argumentList, 0); + } catch ( Exception t ) { + log3("ERROR: Exception for classType.invokeMethod :" + t); + expresult = returnCode1; + continue; + } + + try { + switch (i3) { + + case 0: + BooleanValue blValue = (BooleanValue) returnValue; + break; + + case 1: + ByteValue btValue = (ByteValue) returnValue; + break; + + case 2: + CharValue chValue = (CharValue) returnValue; + break; + + case 3: + DoubleValue dbValue = (DoubleValue) returnValue; + break; + + case 4: + FloatValue flValue = (FloatValue) returnValue; + break; + + + case 5: + IntegerValue inValue = (IntegerValue) returnValue; + break; + + case 6: + LongValue lnValue = (LongValue) returnValue; + break; + + case 7: + ShortValue shValue = (ShortValue) returnValue; + break; + + case 8: + VoidValue vdValue = (VoidValue) returnValue; + break; + + default: log3("ERROR : switch (i3) executes 'default:'"); + expresult = returnCode1; + break label; + } + } catch ( ClassCastException e ) { + log3("ERROR : ClassCastException for: " + types[i3] + " 'returnValue'"); + expresult = returnCode1; + break label; + } // try + } // for + } // label: + + log2(" end of checks"); + log2(" resuming VirtualMachine"); + vm.resume(); + + } + vm.resume(); // for case if thread2 was not resumed because of error in a check + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001/TestDescription.java new file mode 100644 index 00000000000..f1fbcfbd131 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.invokeMethod() + * complies with the following requirements in its spec: + * "If the invoked method has a return type other than void, + * a mirror of the return value is returned by this method; + * otherwise, null is returned." + * when an invoked method is one of primitive types or void. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.invokeMethod.invokemethod001; + * the debuggee program - nsk.jdi.ClassType.invokeMethod.invokemethod001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * For a void method return value is the VoidValue. + * fixing #4737294 testbug: + * For a void method return value should be null. + * 4773425 TEST_BUG: invokemethod001 test failing on all platforms + * Previous changes of 4737294 bug fix are deleted. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod001 + * nsk.jdi.ClassType.invokeMethod.invokemethod001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001a.java new file mode 100644 index 00000000000..ce6c285fa07 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod001a.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the invokemethod001 JDI test. + */ + +public class invokemethod001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + // String mName = //!!!!!!!!!!!!!!!!!!!!!! + // "nsk.jdi.ClassType.invokeMethod"; + + //------------------------------------------------------ common section + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * The debugger compares the argument value and the return value and + * it is expected, these values must be equal. + */ + +public class invokemethod002 { + + private final static String prefix = "nsk.jdi.ClassType.invokeMethod."; + private final static String debuggerName = prefix + "invokemethod002"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + public final static String [] methods2Invoke = { + "methodBOOLParam", + "methodBYTEParam", + "methodCHARParam", + "methodDOUBLEParam", + "methodFLOATParam", + "methodINTParam", + "methodLONGParam", + "methodSHORTParam", + "methodOBJParam" + }; + + private static boolean [] boolParamValues = + {true, false}; + private static byte [] byteParamValues = + {Byte.MIN_VALUE,-1,0,1,Byte.MAX_VALUE}; + private static char [] charParamValues = + {Character.MIN_VALUE,Character.MAX_VALUE}; + private static double [] doubleParamValues = + {Double.NEGATIVE_INFINITY, Double.MIN_VALUE,-1.D, + 0.D,1.D,Double.MAX_VALUE,Double.POSITIVE_INFINITY}; + private static float [] floatParamValues = + {Float.NEGATIVE_INFINITY,Float.MIN_VALUE,-1.F, + 0.F,1.F,Float.MAX_VALUE,Float.POSITIVE_INFINITY}; + private static int [] intParamValues = + {Integer.MIN_VALUE,-1,0,1,Integer.MAX_VALUE}; + private static long [] longParamValues = + {Long.MIN_VALUE,-1L,0L,1L,Long.MAX_VALUE}; + private static short [] shortParamValues = + {Short.MIN_VALUE,-1,0,1,Short.MAX_VALUE}; + private static String [] objParamValues = + {"Hello world"}; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + invokemethod002 thisTest = new invokemethod002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + try { + prepareTestCase(); + } catch(InterruptedException e) { + complain("InterruptedException occurs"); + exitStatus = Consts.TEST_FAILED; + return; + } catch(TestRuntimeException e) { + complain(" " + e); + for (int i = 0; i < e.getStackTrace().length; i++) { + display("\t" + e.getStackTrace()[i]); + } + if ( debugee.getIOPipe() == null ) { + debugee.createIOPipe(); + } + debugee.receiveExpectedSignal(SGNL_READY); + debugee.quit(); + exitStatus = Consts.TEST_FAILED; + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + + Value retValue, value = null; + Vector params = new Vector(); + + Method method; + Object arr = null; + for (int j = 0; j < methods2Invoke.length; j++) { + method = debugee.methodByName(testedClass, methods2Invoke[j]); + display(""); + switch (j) { + case 0: + arr = boolParamValues; + display("boolean values"); + break; + case 1: + arr = byteParamValues; + display("byte values"); + break; + case 2: + arr = charParamValues; + display("char values"); + break; + case 3: + arr = doubleParamValues; + display("double values"); + break; + case 4: + arr = floatParamValues; + display("float values"); + break; + case 5: + arr = intParamValues; + display("integer values"); + break; + case 6: + arr = longParamValues; + display("long values"); + break; + case 7: + arr = shortParamValues; + display("short values"); + break; + case 8: + arr = objParamValues; + display("String values"); + break; + default: + complain("***TEST CASE ERROR***"); + exitStatus = Consts.TEST_FAILED; + continue; + } + display("--------------"); + for (int i = 0; i < Array.getLength(arr); i++) { + params.clear(); + if (arr instanceof boolean[]) { + value = debugee.VM().mirrorOf(Array.getBoolean(arr,i)); + } else if (arr instanceof byte[]) { + value = debugee.VM().mirrorOf(Array.getByte(arr,i)); + } else if (arr instanceof char[]) { + value = debugee.VM().mirrorOf(Array.getChar(arr,i)); + } else if (arr instanceof double[]) { + value = debugee.VM().mirrorOf(Array.getDouble(arr,i)); + } else if (arr instanceof float[]) { + value = debugee.VM().mirrorOf(Array.getFloat(arr,i)); + } else if (arr instanceof int[]) { + value = debugee.VM().mirrorOf(Array.getInt(arr,i)); + } else if (arr instanceof long[]) { + value = debugee.VM().mirrorOf(Array.getLong(arr,i)); + } else if (arr instanceof short[]) { + value = debugee.VM().mirrorOf(Array.getShort(arr,i)); + } else if (arr instanceof String[]) { + value = debugee.VM().mirrorOf((String )Array.get(arr,i)); + } else { + complain("***TEST CASE ERROR***"); + exitStatus = Consts.TEST_FAILED; + } + params.add(value); + retValue = invokeMethod(thread, method, params, value); + } + } + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private void prepareTestCase() throws InterruptedException { + Event event = null; + + ClassPrepareRequest cprep + = debugee.getEventRequestManager().createClassPrepareRequest(); + cprep.addClassFilter(debugeeName); + cprep.enable(); + + debugee.resume(); + + // waiting ClassPrepareEvent for debugeeName + event = debugee.waitingEvent(cprep, waitTime); + if (!(event instanceof ClassPrepareEvent)) { + debugee.resume(); + throw new TestRuntimeException("ClassPrepareEvent didn't arrive"); + } + + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + invokemethod002a.brkpMethodName, + invokemethod002a.brkpLineNumber); + debugee.resume(); + + debugee.createIOPipe(); + debugee.redirectStdout(log,""); + debugee.redirectStderr(log,""); + debugee.receiveExpectedSignal(SGNL_READY); + + // waiting the breakpoint event + event = debugee.waitingEvent(brkp, waitTime); + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + if (brkpEvent == null) { + debugee.resume(); + throw new TestRuntimeException("No breakpoint events"); + } + + thread = brkpEvent.thread(); + } + + private Value invokeMethod(ThreadReference thread, Method method, List params, + Value expectedValue) { + Value returnedValue = null, + param; + try { + display("Method : " + method); + for (int i = 0; i < params.size(); i++) { + param = (Value )params.get(i); + display("Parameters : " + param + "(" + param.type() + ")"); + } + returnedValue = testedClass.invokeMethod(thread, method, params, + ClassType.INVOKE_SINGLE_THREADED); + } catch(InvalidTypeException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } catch(ClassNotLoadedException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } catch(IncompatibleThreadStateException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } catch(InvocationException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } + + String retType = returnedValue != null ? returnedValue.type().toString() + : ""; + display("Return value: " + returnedValue + "(" + retType + ")"); + + if (!returnedValue.equals(expectedValue)) { + String expType = expectedValue.type().toString() ; + complain("***wrong the return value***"); + complain("expected value : " + expectedValue + "(" + + expType + ")"); + exitStatus = Consts.TEST_FAILED; + } + display(""); + return returnedValue; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002/TestDescription.java new file mode 100644 index 00000000000..1faa2722e43 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that a result of the method + * com.sun.jdi.ClassType.invokeMethod() + * correctly works for the boundary parameter of the invoked method. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.invokeMethod.invokemethod002; + * The debuggee program - nsk.jdi.ClassType.invokeMethod.invokemethod002a. + * For every primitive value there is the simplest method on the debugee + * side, which has alone argument of this primitive value and returns + * the same value as argument. Such methods are invoked for boundary + * values of the primitive type. + * The debugger compares the argument value and the return value and, + * it is expected, these values must be equal. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod002 + * nsk.jdi.ClassType.invokeMethod.invokemethod002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002a.java new file mode 100644 index 00000000000..9c6bc1fc217 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod002a.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * invokemethod002a is deugee's part of the invokemethod002. + */ +public class invokemethod002a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 45; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(invokemethod002.SGNL_READY); + String instr = pipe.readln(); // brkpLineNumber + if (instr.equals(invokemethod002.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + // methods is invoked by debugger + private static boolean methodBOOLParam(boolean value) { + return value; + } + + private static byte methodBYTEParam(byte value) { + return value; + } + + private static char methodCHARParam(char value) { + return value; + } + + private static double methodDOUBLEParam(double value) { + return value; + } + + private static float methodFLOATParam(float value) { + return value; + } + + private static int methodINTParam(int value) { + return value; + } + + private static long methodLONGParam(long value) { + return value; + } + + private static short methodSHORTParam(short value) { + return value; + } + + private static String methodOBJParam(String value) { + return value; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003.java new file mode 100644 index 00000000000..d51b969e985 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up the following assertions:
    + * 1. The specified method can be defined in this class, or in + * a superclass.
    + * 2. IllegalArgumentException is thrown if
    + * - the method is not a member of this class or a superclass;
    + * - the size of the argument list does not match the number of declared + * arguemnts for the method.
    + * The first case considers the invokations for the private, + * protected and public methods. In this case + * no exceptions are expected.
    + */ + +public class invokemethod003 { + + private final static String prefix = "nsk.jdi.ClassType.invokeMethod."; + private final static String debuggerName = prefix + "invokemethod003"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + private ReferenceType anotherClass; + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + public final static String [] methods2Invoke = { + "publicFromParent", + "protectFromParent", + "privateFromParent", + "fromChild" + }; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + invokemethod003 thisTest = new invokemethod003(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + try { + prepareTestCase(); + } catch(InterruptedException e) { + complain("InterruptedException occurs"); + exitStatus = Consts.TEST_FAILED; + return; + } catch(TestRuntimeException e) { + complain(" " + e); + for (int i = 0; i < e.getStackTrace().length; i++) { + display("\t" + e.getStackTrace()[i]); + } + if ( debugee.getIOPipe() == null ) { + debugee.createIOPipe(); + } + debugee.receiveExpectedSignal(SGNL_READY); + debugee.quit(); + exitStatus = Consts.TEST_FAILED; + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + Value retValue, value = null, + expectedValue = debugee.VM().mirrorOf(6L); + List params = createParams(3), + params4 = createParams(4); + + Method method; + + // checking up IllegalArgumentException, when the method is not a member + // of this class or a superclass + display("\nthe method is not a member of this class or a superclass"); + display("--------------------------------------------------------"); + method = debugee.methodByName(anotherClass, "run"); + try { + retValue = invokeMethod(thread, method, params, expectedValue); + complain("***IllegalArgumentException is not thrown***"); + exitStatus = Consts.TEST_FAILED; + } catch(IllegalArgumentException e) { + display(">expected " + e); + } catch(Exception e) { + complain(" unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + // checking up for public, protected, private methods of the superclass + display("\npublic, protected, private methods of the superclass"); + display("----------------------------------------------------"); + for (int j = 0; j < methods2Invoke.length; j++) { + method = debugee.methodByName(testedClass, methods2Invoke[j]); + try { + retValue = invokeMethod(thread, method, params, expectedValue); + } catch(Exception e) { + complain("***unexpected " + e + "***"); + exitStatus = Consts.TEST_FAILED; + } + } + display(""); + + // checking up IllegalArgumentException, wrong size of the argument list + display("wrong size of the argument list: " + params4.size() + + "(it should be 3)"); + display("--------------------------------------------------"); + method = debugee.methodByName(testedClass, methods2Invoke[0]); + try { + retValue = invokeMethod(thread, method, params4, expectedValue); + complain("***IllegalArgumentException is not thrown***"); + exitStatus = Consts.TEST_FAILED; + } catch(IllegalArgumentException e) { + display(">expected " + e); + } catch(Exception e) { + complain(" unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private void prepareTestCase() throws InterruptedException { + Event event = null; + + ClassPrepareRequest cprep + = debugee.getEventRequestManager().createClassPrepareRequest(); + cprep.addClassFilter(prefix + invokemethod003a.class2Check); + cprep.enable(); + + debugee.resume(); + + // waiting ClassPrepareEvent for debugeeName + event = debugee.waitingEvent(cprep, waitTime); + if (!(event instanceof ClassPrepareEvent)) { + debugee.resume(); + throw new TestRuntimeException("ClassPrepareEvent didn't arrive"); + } + + + testedClass = (ClassType )debugee.classByName(prefix + + invokemethod003a.class2Check); + + ReferenceType debugeeClass = debugee.classByName(debugeeName); + BreakpointRequest brkp = debugee.setBreakpoint(debugeeClass, + invokemethod003a.brkpMethodName, + invokemethod003a.brkpLineNumber); + + debugee.resume(); + + debugee.createIOPipe(); + debugee.redirectStdout(log,""); + debugee.redirectStderr(log,""); + debugee.receiveExpectedSignal(SGNL_READY); + + anotherClass = debugee.classByName(prefix + + invokemethod003a.anotherClassName); + if (anotherClass == null) { + debugee.resume(); + throw new TestRuntimeException(prefix + + invokemethod003a.anotherClassName + + " has not been loaded yet"); + } + + + // waiting the breakpoint event + event = debugee.waitingEvent(brkp, waitTime); + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + if (brkpEvent == null) { + debugee.resume(); + throw new TestRuntimeException("No breakpoint events"); + } + + thread = brkpEvent.thread(); + } + + private Value invokeMethod(ThreadReference thread, Method method, List params, + Value expectedValue) { + Value returnedValue = null, + param; + try { + display("Method : " + method); + for (int i = 0; i < params.size(); i++) { + param = params.get(i); + display("Parameters : " + param + "(" + param.type() + ")"); + } + returnedValue = testedClass.invokeMethod(thread, method, params, + ClassType.INVOKE_SINGLE_THREADED); + } catch(InvalidTypeException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } catch(ClassNotLoadedException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } catch(IncompatibleThreadStateException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } catch(InvocationException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } + + String retType = returnedValue != null ? returnedValue.type().toString() + : ""; + display("Return value: " + returnedValue + "(" + retType + ")"); + + if (!returnedValue.equals(expectedValue)) { + String expType = expectedValue.type().toString() ; + complain("***wrong the return value***"); + complain("expected value : " + expectedValue + "(" + + expType + ")"); + exitStatus = Consts.TEST_FAILED; + } + display(""); + return returnedValue; + } + + private List createParams(int size) { + Vector params = new Vector(); + for (int i = 0; i < size; i++) { + params.add(debugee.VM().mirrorOf(i + 1)); + } + return params; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003/TestDescription.java new file mode 100644 index 00000000000..6d517174467 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that a result of the method + * com.sun.jdi.ClassType.invokeMethod() + * throws IllegalArgumentException according to spec. + * Test checks up the following assertions: + * 1. The specified method can be defined in this class, or in + * a superclass. + * 2. IllegalArgumentException is thrown if + * - the method is not a member of this class or a superclass, + * - the size of the argument list does not match the number of declared + * arguemnts for the method + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod003 + * nsk.jdi.ClassType.invokeMethod.invokemethod003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003a.java new file mode 100644 index 00000000000..1cbab27ab14 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod003a.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * invokemethod003a is deugee's part of the invokemethod003. + */ +public class invokemethod003a { + + public final static String anotherClassName = "invokemethod003b"; + public final static String class2Check = "invokemethod003Child"; + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 50; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + invokemethod003Child child = new invokemethod003Child(); + invokemethod003b imb = new invokemethod003b(); + pipe.println(invokemethod003.SGNL_READY); + + String instr = pipe.readln(); // brkpLineNumber + if (instr.equals(invokemethod003.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static long publicFromParent(int one, int two, int three) { + return one + two + three; + } + + protected static long protectFromParent(int one, int two, int three) { + return one + two + three; + } + + private static long privateFromParent(int one, int two, int three) { + return one + two + three; + } +} + +class invokemethod003Child extends invokemethod003a { + invokemethod003Child() { + } + + public static long fromChild(int one, int two, int three) { + return one + two + three; + } +} + +class invokemethod003b { + public void run() { + int i = 1; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004.java new file mode 100644 index 00000000000..a2bfcffd5aa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004.java @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up the following assertion:
    + * If the invoked method throws an exception, this method will throw + * an InvocationException which contains a mirror to the exception object thrown. + * It is checked for two cases: + * 1. when the invoked method throws uncought NullPointerExection.
    + * For this case, InvocationException is expected, the one
    + * contains a mirror to the NullPointerException object.
    + * 2. when invoked method throws cought exection
    + * For this case, no exceptions are expected
    + */ + +public class invokemethod004 { + + private final static String prefix = "nsk.jdi.ClassType.invokeMethod."; + private final static String debuggerName = prefix + "invokemethod004"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + public final static String [] methods2Invoke = { + "throwNPE", + "throwCaughtNPE" + }; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + invokemethod004 thisTest = new invokemethod004(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + invokemethod004a.brkpMethodName, + invokemethod004a.brkpLineNumber); + debugee.resume(); + + debugee.sendSignal(""); + Event event = null; + + // waiting the breakpoint event + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + + thread = brkpEvent.thread(); + + ReferenceType exceptionRefType = + debugee.classByName(invokemethod004a.testException); + + display("\nTEST BEGINS"); + display("==========="); + + Value retValue; + List params = createParams(0); + + Method method; + + display("\nuncought NullPointerException"); + display("-----------------------------"); + + // uncought NullPointerException + method = debugee.methodByName(testedClass, methods2Invoke[0]); + try { + retValue = invokeMethod(thread, method, params); + complain("InvocationException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(InvocationException e) { + display("!!!expected InvocationException"); + + // cheking of the excpetion type + if (e.exception().referenceType().equals(exceptionRefType)) { + display("!!!expected the exception mirror " + e.exception()); + } else { + complain("Unexpected the exception mirror " + + e.exception().referenceType()); + complain("We are expecting " + exceptionRefType); + exitStatus = Consts.TEST_FAILED; + } + } + display(""); + + display("\ncought NullPointerException"); + display("-----------------------------"); + // cought NullPointerException + method = debugee.methodByName(testedClass, methods2Invoke[1]); + try { + retValue = invokeMethod(thread, method, params); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private void prepareTestCase() throws InterruptedException { + Event event = null; + + // waiting VMStartEvent + event = debugee.waitingEvent(null, waitTime); + if (!(event instanceof VMStartEvent)) { + debugee.resume(); + throw new TestRuntimeException("VMStartEvent didn't arrive"); + } + + ClassPrepareRequest cprep + = debugee.getEventRequestManager().createClassPrepareRequest(); + cprep.addClassFilter(debugeeName); + cprep.enable(); + + debugee.resume(); + + // waiting ClassPrepareEvent for debugeeName + event = debugee.waitingEvent(cprep, waitTime); + if (!(event instanceof ClassPrepareEvent)) { + debugee.resume(); + throw new TestRuntimeException("ClassPrepareEvent didn't arrive"); + } + + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + invokemethod004a.brkpMethodName, + invokemethod004a.brkpLineNumber); + debugee.resume(); + + debugee.createIOPipe(); + debugee.redirectStdout(log,""); + debugee.redirectStderr(log,""); + debugee.receiveExpectedSignal(SGNL_READY); + + // waiting the breakpoint event + event = debugee.waitingEvent(brkp, waitTime); + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + if (brkpEvent == null) { + debugee.resume(); + throw new TestRuntimeException("No breakpoint events"); + } + + thread = brkpEvent.thread(); + } + + private Value invokeMethod(ThreadReference thread, Method method, List params) + throws InvocationException { + Value returnedValue = null, + param; + try { + display("Method : " + method); + for (int i = 0; i < params.size(); i++) { + param = (Value )params.get(i); + display("Parameters : " + param + "(" + param.type() + ")"); + } + returnedValue = testedClass.invokeMethod(thread, method, params, + ClassType.INVOKE_SINGLE_THREADED); + } catch(InvalidTypeException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } catch(ClassNotLoadedException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } catch(IncompatibleThreadStateException e) { + complain("exception: " + e); + exitStatus = Consts.TEST_FAILED; + } + + String retType = returnedValue != null ? returnedValue.type().toString() + : ""; + display("Return value: " + returnedValue + "(" + retType + ")"); + + display(""); + return returnedValue; + } + + private List createParams(int size) { + Vector params = new Vector(); + for (int i = 0; i < size; i++) { + params.add(debugee.VM().mirrorOf(i + 1)); + } + return params; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004/TestDescription.java new file mode 100644 index 00000000000..0016c9c870f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that a result of the method + * com.sun.jdi.ClassType.invokeMethod() + * throws InvocationException according to spec. + * Test checks up the following assertion: + * If the invoked method throws an exception, this method will throw + * an InvocationException which contains a mirror to the exception object + * thrown. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod004 + * nsk.jdi.ClassType.invokeMethod.invokemethod004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004a.java new file mode 100644 index 00000000000..a245829b59c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod004a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * invokemethod004a is deugee's part of the invokemethod004. + */ +public class invokemethod004a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + public final static String testException = "java.lang.NullPointerException"; + + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(invokemethod004.SGNL_READY); + String instr = pipe.readln(); + log.display("breakpoint line"); // brkpLineNumber + instr = pipe.readln(); + if (instr.equals(invokemethod004.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static void throwNPE() { + Object obj = null; + String tmp = obj.toString(); + } + + protected static void throwCaughtNPE() { + Object obj = null; + try { + String tmp = obj.toString(); + } catch (NullPointerException e) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005.java new file mode 100644 index 00000000000..bedc446ec84 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import java.util.*; +import java.io.*; +import java.lang.reflect.Array; + +/** + * Test checks up the following assertion: + * Primitive arguments must be either assignment compatible with + * the argument type or must be convertible to the argument type + * without loss of information. + * for every primitive type + */ + +public class invokemethod005 extends ValueConversionDebugger { + + private static class TestedMethodData { + public String methodName; + public ValueType methodType; + + public TestedMethodData(String methodName, ValueType methodType) { + this.methodName = methodName; + this.methodType = methodType; + } + } + + private ClassType testedClass; + + private ThreadReference thread; + + private final static TestedMethodData [] methods2Invoke = { + new TestedMethodData("methodBYTEParam", BYTE), + new TestedMethodData("methodCHARParam", CHAR), + new TestedMethodData("methodDOUBLEParam", DOUBLE), + new TestedMethodData("methodFLOATParam", FLOAT), + new TestedMethodData("methodINTParam", INT), + new TestedMethodData("methodLONGParam", LONG), + new TestedMethodData("methodSHORTParam", SHORT) + }; + + private static byte [] byteParamValues = + {Byte.MIN_VALUE, + -1, + 0, + 1, + Byte.MAX_VALUE}; + private static char [] charParamValues = + {Character.MIN_VALUE, + Character.MAX_VALUE}; + private static double [] doubleParamValues = + {Double.NEGATIVE_INFINITY, + -1.5D, + -1.0D, + -0.0D, + +0.0D, + Double.MIN_VALUE, + 1.0D, + 1.5D, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY}; + private static float [] floatParamValues = + {Float.NEGATIVE_INFINITY, + -1.5F, + -1.0F, + -0.0F, + +0.0F, + Float.MIN_VALUE, + 1.0F, + 1.5F, + Float.MAX_VALUE, + Float.POSITIVE_INFINITY}; + private static int [] intParamValues = + {Integer.MIN_VALUE, + -1, + 0, + 1, + 1234567890, + Integer.MAX_VALUE}; + private static long [] longParamValues = + {Long.MIN_VALUE, + -1L, + 0L, + 1L, + 1234567890123456789L, + Long.MAX_VALUE}; + private static short [] shortParamValues = + {Short.MIN_VALUE, + -1, + 0, + 1, + Short.MAX_VALUE}; + + protected String debuggeeClassName() { + return invokemethod005a.class.getName(); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod005().runIt(argv, out); + } + + protected void doTest() { + initDefaultBreakpoint(); + + BreakpointEvent brkpEvent = forceBreakpoint(); + + testedClass = (ClassType )debuggee.classByName(debuggeeClassNameWithoutArgs()); + + thread = brkpEvent.thread(); + + display("\nTEST BEGINS"); + display("==========="); + + PrimitiveValue value = null; + List params = new ArrayList(); + Method method; + Object arr = null; + boolean validConversion; + + for (TestedMethodData methodData : methods2Invoke) { + method = debuggee.methodByName(testedClass, methodData.methodName); + display(""); + display("Method : " + method); + display("============="); + for (ValueType type : ValueType.values()) { + switch (type) { + case BYTE: + arr = byteParamValues; + display("\tbyte values"); + break; + case CHAR: + arr = charParamValues; + display("\tchar values"); + break; + case DOUBLE: + arr = doubleParamValues; + display("\tdouble values"); + break; + case FLOAT: + arr = floatParamValues; + display("\tfloat values"); + break; + case INT: + arr = intParamValues; + display("\tinteger values"); + break; + case LONG: + arr = longParamValues; + display("\tlong values"); + break; + case SHORT: + arr = shortParamValues; + display("\tshort values"); + break; + default: + complain("\t***TEST CASE ERROR***"); + setSuccess(false); + continue; + } + display("\t--------------"); + for (int i = 0; i < Array.getLength(arr); i++) { + params.clear(); + value = createValue(arr, i); + params.add(value); + validConversion = isValidConversion(methodData.methodType, value); + try { + invokeMethod(thread, method, params, value); + if (!validConversion) { + complain(lastConversion); + complain("***InvalidTypeException is not thrown***"); + setSuccess(false); + } + } catch(InvalidTypeException e) { + if (validConversion) { + complain(lastConversion); + complain("*** unexpected InvalidTypeException***"); + setSuccess(false); + } else { + display(lastConversion); + display("!!!expected InvalidTypeException"); + } + } + display(""); + } + } + } + + display("============="); + display("TEST FINISHES\n"); + + removeDefaultBreakpoint(); + + debuggee.resume(); + } + + private void invokeMethod(ThreadReference thread, Method method, List params, + PrimitiveValue expectedValue) throws InvalidTypeException { + PrimitiveValue returnedValue = null; + PrimitiveValue param; + try { + for (int i = 0; i < params.size(); i++) { + param = (PrimitiveValue )params.get(i); + if (param instanceof CharValue) { + display("\tParameters : " + Integer.toHexString(param.charValue()) + "(" + param.type() + ")"); + } else { + display("\tParameters : " + param + "(" + param.type() + ")"); + } + } + returnedValue = (PrimitiveValue)testedClass.invokeMethod(thread, method, params, + ClassType.INVOKE_SINGLE_THREADED); + } catch(ClassNotLoadedException e) { + complain("exception: " + e); + setSuccess(false); + } catch(IncompatibleThreadStateException e) { + complain("exception: " + e); + setSuccess(false); + } catch(InvocationException e) { + complain("exception: " + e); + setSuccess(false); + } + + String retType = returnedValue != null ? returnedValue.type().toString() + : ""; + display("\tReturn value: " + returnedValue + "(" + retType + ")"); + + checkValueConversion(expectedValue, returnedValue); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005/TestDescription.java new file mode 100644 index 00000000000..763e75b3a8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ClassType.invokeMethod() + * Test checks up the following assertion: + * Primitive arguments must be either assignment compatible with + * the argument type or must be convertible to the argument type + * without loss of information. + * for every primitive type. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod005 + * nsk.jdi.ClassType.invokeMethod.invokemethod005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005a.java new file mode 100644 index 00000000000..5ca8fc19ec1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod005a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * invokemethod005a is deugee's part of the invokemethod005. + */ +public class invokemethod005a extends AbstractJDIDebuggee { + + public static void main (String args[]) { + new invokemethod005a().doTest(args); + } + + // methods is invoked by debugger + private static boolean methodBOOLParam(boolean value) { + return value; + } + + private static byte methodBYTEParam(byte value) { + return value; + } + + private static char methodCHARParam(char value) { + return value; + } + + private static double methodDOUBLEParam(double value) { + return value; + } + + private static float methodFLOATParam(float value) { + return value; + } + + private static int methodINTParam(int value) { + return value; + } + + private static long methodLONGParam(long value) { + return value; + } + + private static short methodSHORTParam(short value) { + return value; + } + + private static String methodOBJParam(String value) { + return value; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006.java new file mode 100644 index 00000000000..494f54f9de9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up that NullPointerException will be thrown in + * the following cases:
    + * - invokeMethod(null, method, params,ClassType.INVOKE_SINGLE_THREADED)
    + * - invokeMethod(thread, null, params,ClassType.INVOKE_SINGLE_THREADED)
    + * - invokeMethod(thread, method, null,ClassType.INVOKE_SINGLE_THREADED)
    + * In case
    + * invokeMethod(thread, method, params,Integer.MAX_VALUE)
    + * no exception is expected. + */ + +public class invokemethod006 { + + private final static String prefix = "nsk.jdi.ClassType.invokeMethod."; + private final static String debuggerName = prefix + "invokemethod006"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + public final static String method2Invoke = "justMethod"; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + invokemethod006 thisTest = new invokemethod006(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + invokemethod006a.brkpMethodName, + invokemethod006a.brkpLineNumber); + debugee.resume(); + + debugee.sendSignal(""); + Event event = null; + + // waiting the breakpoint event + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + + thread = brkpEvent.thread(); + + display("\nTEST BEGINS"); + display("==========="); + + Value retValue; + List params = createParams(1); + + Method method = debugee.methodByName(testedClass, method2Invoke); + display("Method : " + method); + + display("invokeMethod(null, method, params," + + "ClassType.INVOKE_SINGLE_THREADED)"); + try { + retValue = testedClass.invokeMethod(null, method, params, + ClassType.INVOKE_SINGLE_THREADED); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("invokeMethod(thread, null, params," + + "ClassType.INVOKE_SINGLE_THREADED)"); + try { + retValue = testedClass.invokeMethod(thread, null, params, + ClassType.INVOKE_SINGLE_THREADED); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("invokeMethod(thread, method, null," + + "ClassType.INVOKE_SINGLE_THREADED)"); + try { + retValue = testedClass.invokeMethod(thread, method, null, + ClassType.INVOKE_SINGLE_THREADED); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("invokeMethod(thread, method, params," + + "Integer.MAX_VALUE)"); + try { + retValue = testedClass.invokeMethod(thread, method, params, + Integer.MAX_VALUE); + if (((PrimitiveValue)retValue).intValue() != 1) { + complain("Wrong returned value " + retValue.toString()); + exitStatus = Consts.TEST_FAILED; + } else { + display("returned value is " + retValue.toString()); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("invokeMethod(thread, method, params," + + "Integer.MIN_VALUE)"); + try { + retValue = testedClass.invokeMethod(thread, method, params, + Integer.MIN_VALUE); + if (((PrimitiveValue)retValue).intValue() != 1) { + complain("Wrong returned value " + retValue.toString()); + exitStatus = Consts.TEST_FAILED; + } else { + display("returned value is " + retValue.toString()); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private List createParams(int size) { + Vector params = new Vector(); + for (int i = 0; i < size; i++) { + params.add(debugee.VM().mirrorOf(i + 1)); + } + return params; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006/TestDescription.java new file mode 100644 index 00000000000..e065ec36ca8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ClassType.invokeMethod() + * Test checks up that NullPointerException will be thrown in + * the following cases: + * - invokeMethod(null, method, params,ClassType.INVOKE_SINGLE_THREADED) + * - invokeMethod(thread, null, params,ClassType.INVOKE_SINGLE_THREADED) + * - invokeMethod(thread, method, null,ClassType.INVOKE_SINGLE_THREADED) + * In case + * invokeMethod(thread, method, params,Integer.MAX_VALUE) + * no exception is expected. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod006 + * nsk.jdi.ClassType.invokeMethod.invokemethod006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006a.java new file mode 100644 index 00000000000..a0dfd85898d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod006a.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * invokemethod006a is deugee's part of the invokemethod006. + */ +public class invokemethod006a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 46; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(invokemethod006.SGNL_READY); + String instr = pipe.readln(); + log.display("breakpoint line"); // brkpLineNumber + instr = pipe.readln(); + if (instr.equals(invokemethod006.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static int justMethod(int val) { + return val; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007.java new file mode 100644 index 00000000000..5df33317b94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * + * The test checks up the method com.sun.jdi.ClassType.invokeMethod() + * + * Test checks up the following assertion: + * ...all threads in the target VM are resumed while the method is + * being invoked if they were previously suspended by an event or by + * VirtualMachine.suspend() or ThreadReference.suspend(). + * + * This checking is implemented for three cases: + * - when the tested thread is suspended by ThreadReference.suspend(); + * - when the tested thread is suspended by VirtualMachine.suspend(); + * - when the tested thread is suspended by an event. + */ + +public class invokemethod007 { + + private final static String prefix = "nsk.jdi.ClassType.invokeMethod."; + private final static String debuggerName = prefix + "invokemethod007"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + public final static String SGNL_STRTHRD = "start_thread"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + public final static String method2Invoke = "invokedMethod"; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + invokemethod007 thisTest = new invokemethod007(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.makeBreakpoint(testedClass, + invokemethod007a.brkpMethodName, + invokemethod007a.brkpLineNumber); + brkp.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + brkp.enable(); + + display("\nTEST BEGINS"); + display("==========="); + + Value retValue; + List params = new Vector(); + ThreadReference suspendedThread; + BreakpointEvent brkpEvent; + + Method method = debugee.methodByName(testedClass, method2Invoke); + display("Method : " + method); + + for (int i = 0; i < 3; i++) { + display(""); + switch (i) { + case 0: + display("\nCASE#0 : Thread is suspended by ThreadReference.suspend()"); + break; + case 1: + display("\nCASE#1 : Thread is suspended by VirtualMachine.suspend()"); + break; + case 2: + display("\nCASE#2 : Thread is suspended by BreakPointRequest"); + brkp.disable(); + brkp.setSuspendPolicy(EventRequest.SUSPEND_ALL); + brkp.enable(); + } + + // starting thread + display("sending signal " + SGNL_STRTHRD); + debugee.sendSignal(SGNL_STRTHRD); + debugee.resume(); + display("waiting for signal " + SGNL_READY); + debugee.receiveExpectedSignal(SGNL_READY); + + brkpEvent = waitForBreakpoint(brkp); + + thread = brkpEvent.thread(); + + suspendedThread = debugee.threadByName(invokemethod007a.testedThread); + switch (i) { + case 0: + suspendedThread.suspend(); + break; + case 1: + debugee.VM().suspend(); + break; + } + + if ( !suspendedThread.isSuspended() ) { + complain(suspendedThread.name() + " is not suspended"); + exitStatus = Consts.TEST_FAILED; + } else { + display(suspendedThread.name() + " is suspended"); + } + try { + if (i == 1) { + // for VirtualMachine.suspended() only! + // resume thread for invokedMethod to have suspend count equal to 1. + thread.resume(); + } + display("invoking the method"); + retValue = testedClass.invokeMethod(thread, method, params, 0); + + long resultTime = ((PrimitiveValue)retValue).longValue(); + if ( resultTime >= waitTime) { + complain("CASE #" + i + " FAILED." + + "\n\tTimeout occured while invocation of debugee's method"); + exitStatus = Consts.TEST_FAILED; + } else { + display("CASE #" + i + " PASSED"); + } + } catch(Exception e) { + complain("Unexpected exception while invocation of debugee's method: " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private BreakpointEvent waitForBreakpoint(BreakpointRequest brkp) { + Event event = null; + BreakpointEvent brkpEvent; + + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + brkpEvent = (BreakpointEvent )event; + return brkpEvent; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007/TestDescription.java new file mode 100644 index 00000000000..8628f5f5b89 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod007. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ClassType.invokeMethod() + * Test checks up the following assertion: + * ...all threads in the target VM are resumed while the method is + * being invoked if they were previously suspended by an event or by + * VirtualMachine.suspend() or ThreadReference.suspend(). + * This checking is implemented for three cases: + * - when the tested thread is suspended by ThreadReference.suspend(); + * - when the tested thread is suspended by VirtualMachine.suspend(); + * - when the tested thread is suspended by an event. + * COMMENTS: + * 4786806 TEST_BUG: debugee does not relinquishes lock after notifying + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.makeBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod007 + * nsk.jdi.ClassType.invokeMethod.invokemethod007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007a.java new file mode 100644 index 00000000000..ac5b4f39394 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod007a.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * invokemethod007a is deugee's part of the invokemethod007. + */ +public class invokemethod007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 70; + public final static String testedThread = "im007aThread01"; + + public static Log log; + public static long waitTime; + private static IOPipe pipe; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + pipe = argHandler.createDebugeeIOPipe(log); + im007aThread01 thread = null; + pipe.println(invokemethod007.SGNL_READY); + + String instr = pipe.readln(); + while (!instr.equals(invokemethod007.SGNL_QUIT)) { + + // create new thread and start it + if (instr.equals(invokemethod007.SGNL_STRTHRD)) { + thread = new im007aThread01("im007aThread01"); + synchronized(im007aThread01.waitStarting) { + thread.start(); + try { + im007aThread01.waitStarting.wait(waitTime); + log.display("checked thread started"); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for checked thread start."); + } + } + } + log.display("sending ready signal..."); + pipe.println(invokemethod007.SGNL_READY); + log.display("waiting signal from debugger..."); // brkpLineNumber + instr = pipe.readln(); // this is a line for breakpoint + + if (thread.isAlive()) { + log.display("waiting for join of : " + thread.getName()); + try { + thread.join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for join of " + thread.getName()); + } + if (thread.isAlive()) { + try { + thread.interrupt(); + } catch (SecurityException e) { + throw new Failure("Cannot interrupt checked thread."); + } + } + } + } + + if (instr.equals(invokemethod007.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static long invokedMethod() { + log.display("invokedMethod> starting..."); + try { + synchronized(im007aThread01.waitFinishing) { + synchronized(im007aThread01.waitInvoking) { + log.display("invokedMethod> notifying to thread..."); + im007aThread01.waitInvoking.notifyAll(); + } + + log.display("invokedMethod> waiting for thread's response..."); + long startTime = System.currentTimeMillis(); + im007aThread01.waitFinishing.wait(waitTime); + return System.currentTimeMillis() - startTime; + } + } catch (InterruptedException e) { + log.display("invokedMethod> it was interrupted."); + } + return waitTime + 1; + } +} + +class im007aThread01 extends Thread { + public static Object waitInvoking = new Object(); + public static Object waitStarting = new Object(); + public static Object waitFinishing = new Object(); + + im007aThread01(String threadName) { + super(threadName); + } + + public void run() { + synchronized(waitInvoking) { + synchronized(waitStarting) { + waitStarting.notifyAll(); + } + + invokemethod007a.log.display(getName() + "> waiting for the invoked method..."); + try { + long startTime = System.currentTimeMillis(); + waitInvoking.wait(invokemethod007a.waitTime); + if ((System.currentTimeMillis() - startTime) < invokemethod007a.waitTime) { + invokemethod007a.log.display(getName() + "> got a response from the invoked method"); + } else { + invokemethod007a.log.display(getName() + "*** no response from invoked method"); + } + } catch (Exception e) { + invokemethod007a.log.display(getName() + e); + } + } + synchronized(waitFinishing) { + invokemethod007a.log.display(getName() + "> notifying the invoked method..."); + waitFinishing.notifyAll(); + } + invokemethod007a.log.display(getName() + "> thread finished"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008.java new file mode 100644 index 00000000000..b1125293910 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * + * The test checks up the method com.sun.jdi.ClassType.invokeMethod() + * + * Test checks up the following assertion: + * If the target VM is disconnected during the invoke (for example, + * through VirtualMachine.dispose()) the method invocation continues. + */ + +public class invokemethod008 { + + private final static String prefix = "nsk.jdi.ClassType.invokeMethod."; + private final static String debuggerName = prefix + "invokemethod008"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + public final static String SGNL_FINISH = "finish"; + public final static String SGNL_ABORT = "abort"; + + public static int exitStatus; + public static Log log; + public static Debugee debugee; + public static long waitTime; + private static boolean isAborted = false; + + private ClassType testedClass; + public final static String method2Invoke = "justMethod"; + + public static void display(String msg) { + log.display(msg); + } + + public static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + invokemethod008 thisTest = new invokemethod008(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Failure e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + if (!isAborted) { + debugee.resume(); + debugee.quit(); + } + } + + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure{ + + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + InvokingThread invokeThrd = new InvokingThread(); + invokeThrd.start(); + + // waiting READY signal from invoked method + display("\nwaiting for signal \"" + + SGNL_READY + + "\" from the invoked method"); + debugee.receiveExpectedSignal(SGNL_READY); + + display("\n" + method2Invoke + " has been invoked. Trying to dispose debugee's VM"); + + AbortingThread abortingThrd = new AbortingThread(); + abortingThrd.start(); + + debugee.VM().dispose(); + invokeThrd.waitVMDisconnect(); + + try { + invokeThrd.join(); + } catch(InterruptedException e) { + throw new Failure("unexpected " + e); + } + + if (isAborted) { + complain("Debugee's VM disposing hung. Invoking was aborted!!!"); + exitStatus = Consts.TEST_FAILED; + } else { + display("\nVirtual machine has been disposed"); + display("sending signal \"" + SGNL_FINISH + "\" to the invoked method"); + debugee.sendSignal(SGNL_FINISH); + } + + display("\n============="); + display("TEST FINISHES\n"); + } + + private BreakpointEvent waitForBreakpoint(BreakpointRequest brkp) { + Event event = null; + BreakpointEvent brkpEvent; + + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected " + e); + } + + if (!(event instanceof BreakpointEvent )) { + throw new Failure("BreakpointEvent didn't arrive"); + } + + brkpEvent = (BreakpointEvent )event; + return brkpEvent; + } + + + class InvokingThread extends Thread { + volatile boolean isNotified = false; + + public void run() { + display(""); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + invokemethod008a.brkpMethodName, + invokemethod008a.brkpLineNumber); + debugee.resume(); + + debugee.sendSignal(""); + + BreakpointEvent brkpEvent = waitForBreakpoint(brkp); + ThreadReference thread = brkpEvent.thread(); + + Value retValue; + List params = new Vector(); + + Method method = debugee.methodByName(testedClass, method2Invoke); + display("\nInvoking debugee's method : " + method); + + try { + retValue = testedClass.invokeMethod(thread, method, params, 0); + if ( ((PrimitiveValue )retValue).intValue() == Consts.TEST_FAILED ) { + complain("VMDisconnectException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch(VMDisconnectedException e) { + display("!!!expected VMDisconnectException"); + notifyVMDisconnect(); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + debugee.resume(); + } + + synchronized void notifyVMDisconnect() { + isNotified = true; + notify(); + } + + synchronized void waitVMDisconnect() { + try { + if (!isNotified) { + display("\nwaiting VMDisconnectedException"); + wait(waitTime); + } + } catch (InterruptedException e) { + throw new Failure("unexpected " + e); + } + } + } + + class AbortingThread extends Thread { + + public void run() { + try { + sleep(waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected " + e); + } + + display("\n!!!out of wait time!!!"); + display("sending signal \"" + SGNL_ABORT + "\" to the invoked method"); + isAborted = true; + debugee.sendSignal(SGNL_ABORT); + debugee.resume(); + debugee.quit(); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008/TestDescription.java new file mode 100644 index 00000000000..2df43027be9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod008. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ClassType.invokeMethod() + * Test checks up the following assertion: + * If the target VM is disconnected during the invoke (for example, + * through VirtualMachine.dispose()) the method invocation continues. + * COMMENTS: + * The test was updated to avoid hanging of debugee's VM + * after invoking VirtualMachine.dispose(). + * (see 4471237 VirtualMachine.dispose() hangs on Windows) + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod008 + * nsk.jdi.ClassType.invokeMethod.invokemethod008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008a.java new file mode 100644 index 00000000000..9038940e7c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008a.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * invokemethod008a is deugee's part of the invokemethod008. + */ +public class invokemethod008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 51; + private static Log log; + private static IOPipe pipe; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(invokemethod008.SGNL_READY); + + String instr = pipe.readln(); + // the below line is a breakpoint. + // Debugger will invoke justMethod(). + instr = pipe.readln(); // brkpLineNumber + if (instr.equals(invokemethod008.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static int justMethod() { + try { + pipe.println(invokemethod008.SGNL_READY); + log.display("invoked_method:: waiting response from debugger..."); + String instr = pipe.readln(); + if (instr.equals(invokemethod008.SGNL_FINISH)) { + log.display("invoked_method:: completed succesfully."); + return Consts.TEST_PASSED; + } else if (instr.equals(invokemethod008.SGNL_ABORT)) { + log.display("invoked_method:: aborted."); + } + } catch(Exception e) { + log.display("unexpected exception " + e); + } + return Consts.TEST_FAILED; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009.java new file mode 100644 index 00000000000..802bf810a3e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009.java @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ClassType.invokeMethod() + * properly throws ClassNotLoadedException - if any argument type + * has not yet been loaded through the appropriate class loader.

    + * + * The test works as follows. Debugger part of the test invokes + * debuggee methods dummyMeth, finDummyMeth with arguments of + * non-loaded reference types DummyType, FinDummyType. + * The test makes sure that class has not been loaded by the debuggee + * VM through the JDI method VirtualMachine.classesByName() + * which should return list of loaded classes only. + */ +public class invokemethod009 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.invokeMethod.invokemethod009t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod009tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 57; + + // tested debuggee methods, fields and reference types + static final int METH_NUM = 2; + static final String DEBUGGEE_METHODS[][] = { + {"dummyMeth", "nsk.jdi.ClassType.invokeMethod.invokemethod009tDummyType", + "Lnsk/jdi/ClassType/invokeMethod/invokemethod009tDummyType;" }, + {"finDummyMeth", "nsk.jdi.ClassType.invokeMethod.invokemethod009tFinDummyType", + "Lnsk/jdi/ClassType/invokeMethod/invokemethod009tFinDummyType;"} + }; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod009().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod009t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + +// Check the tested assersion + try { + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + ClassType clsType = (ClassType) rType; + + for (int i=0; i methList = rType.methodsByName(DEBUGGEE_METHODS[i][0]); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHODS[i][0] + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + continue; + } + Method meth = methList.get(0); + LinkedList argList = new LinkedList(); + argList.add(MockReferenceType.createObjectReference(clsType.virtualMachine(), + DEBUGGEE_METHODS[i][2], DEBUGGEE_METHODS[i][1])); + + try { + log.display("\n" + (i+1) + ") Trying to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee class \"" + + clsType + "\" ..."); + + clsType.invokeMethod(thrRef, meth, argList, 0); + + // Make sure that the reference type is not loaded by the debuggee VM + if ((debuggee.classByName(DEBUGGEE_METHODS[i][1])) != null) { + log.display("Skipping the check: the tested reference type\n\t\"" + + DEBUGGEE_METHODS[i][1] + + "\"\n\twas loaded by the debuggee VM, unable to test an assertion"); + continue; + } + else { + log.complain("TEST FAILED: expected ClassNotLoadedException was not thrown" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee class \"" + + clsType + "\""); + tot_res = Consts.TEST_FAILED; + } + } catch (ClassNotLoadedException ce) { + log.display("CHECK PASSED: caught expected " + ce + + "\n\t" + ce.className()); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ClassType.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected ClassNotLoadedException" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee class \"" + + clsType + "\""); + tot_res = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + BPreq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009/TestDescription.java new file mode 100644 index 00000000000..f3a07bac098 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod009. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-4698670 + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ClassType.invokeMethod() + * properly throws ClassNotLoadedException - if any argument type + * has not yet been loaded through the appropriate class loader. + * The test works as follows. Debugger part of the test invokes + * debuggee methods "dummyMeth", "finDummyMeth" with arguments of + * non-loaded reference types "DummyType", "FinDummyType". + * The test makes sure that class has not been loaded by the debuggee + * VM through the JDI method VirtualMachine.classesByName() which + * should return list of loaded classes only. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod009 + * nsk.jdi.ClassType.invokeMethod.invokemethod009t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009t.java new file mode 100644 index 00000000000..9198633a83c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod009t.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class invokemethod009t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod009t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Thread.currentThread().setName(invokemethod009.DEBUGGEE_THRNAME); + + pipe.println(invokemethod009.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod009.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod009.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod009.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } + + // dummy static methods used to provoke ClassNotLoadedException + static void dummyMeth(invokemethod009tDummyType dummyT) { + System.err.println("the method \"dummyMeth\" was invoked!"); + } + + static long finDummyMeth(invokemethod009tFinDummyType finDummyT) { + System.err.println("the method \"finDummyMeth\" was invoked!"); + return 9223372036854775807L; + } +} + +// Dummy reference types used to provoke ClassNotLoadedException +// in the debugger +class invokemethod009tDummyType {} +final class invokemethod009tFinDummyType {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010.java new file mode 100644 index 00000000000..5280d9da008 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ClassType.invokeMethod() + * properly throws IncompatibleThreadStateException - if the + * specified thread has not been suspended by an event.

    + * + * The test works as follows. Debugger part of the test attempts + * to invoke several debuggee methods using main debuggee thread + * invokemethod010tThr has been suspended by the JDI method + * ThreadReference.suspend() instead of by an event. + */ +public class invokemethod010 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.invokeMethod.invokemethod010t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod010tThr"; + + // tested debuggee methods and type reference numbers + static final int METH_NUM = 10; + static final String DEBUGGEE_METHODS[] = { + "byteMeth", + "shortMeth", + "intMeth", + "longMeth", + "floatMeth", + "doubleMeth", + "charMeth", + "booleanMeth", + "strMeth", + "voidMeth" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int ATTEMPTS = 5; + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod010().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod010t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + thrRef.suspend(); + while(!thrRef.isSuspended()) { + num++; + if (num > ATTEMPTS) { + log.complain("TEST FAILED: unable to suspend debuggee thread"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + log.display("Waiting for debuggee thread suspension ..."); + try { + Thread.currentThread().sleep(TIMEOUT_DELTA); + } catch(InterruptedException ie) { + ie.printStackTrace(); + log.complain("TEST FAILED: caught: " + ie); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + ClassType clsType = (ClassType) rType; + + for (int i=0; iemptyList(), 0); + + log.complain("TEST FAILED: expected IncompatibleThreadStateException was not thrown" + + "\n\twhen attempted to invoke the static method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee class \"" + clsType + + "\" and the thread reference which has not been suspended by an event."); + tot_res = Consts.TEST_FAILED; + } catch (IncompatibleThreadStateException is) { + log.display("CHECK PASSED: caught expected " + is); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ClassType.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected IncompatibleThreadStateException" + + "\n\twhen attempted to invoke the static method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee class \"" + clsType + + "\" and the thread reference which has not been suspended by an event."); + tot_res = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private int quitDebuggee() { + log.display("\nFinal resumption of the debuggee thread"); + if (thrRef != null) { + if (thrRef.isSuspended()) + thrRef.resume(); + } + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010/TestDescription.java new file mode 100644 index 00000000000..ddec2742aef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod010. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ClassType.invokeMethod() properly throws + * IncompatibleThreadStateException - if the specified thread has + * not been suspended by an event. + * The test works as follows. Debugger part of the test attempts + * to invoke several debuggee methods using main debuggee thread + * "invokemethod010tThr" suspended by the JDI method + * ThreadReference.suspend() instead of by an event. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod010 + * nsk.jdi.ClassType.invokeMethod.invokemethod010t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod010 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010t.java new file mode 100644 index 00000000000..585c5711664 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod010t.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is debuggee class. + */ +public class invokemethod010t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod010t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Thread.currentThread().setName(invokemethod010.DEBUGGEE_THRNAME); + + pipe.println(invokemethod010.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(invokemethod010.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } + + // dummy static methods used to provoke IncompatibleThreadStateException + // in the debugger + static byte byteMeth() { + return 127; + } + + static short shortMeth() { + return -32768; + } + + static int intMeth() { + return 2147483647; + } + + static long longMeth() { + return 9223372036854775807L; + } + + static float floatMeth() { + return 5.1F; + } + + static double doubleMeth() { + return 6.2D; + } + + static char charMeth() { + return 'a'; + } + + static boolean booleanMeth() { + return false; + } + + static String strMeth() { + return "string method"; + } + + static void voidMeth() {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011.java new file mode 100644 index 00000000000..c72e6bd1dfb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011.java @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that invocation with all threads resumption + * and the single threaded one will be performed properly through + * the JDI method
    + * com.sun.jdi.ClassType.invokeMethod(). + * The following assertions are verified: + *

  • by default, all threads in the target VM are resumed while + * the method is being invoked + *
  • when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation + *
  • only the specified thread will be resumed with the flag + * INVOKE_SINGLE_THREADED + *
  • upon completion of a single threaded invoke, the invoking + * thread will be suspended once again.

    + * + * A debuggee part of the test starts several threads. Then debugger + * calls the JDI method without and with the flag INVOKE_SINGLE_THREADED + * sequentially. During the invocations and after them the threads state + * is expected to be as described above. + */ +public class invokemethod011 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.invokeMethod.invokemethod011t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 66; + + // debuggee thread names to be check + static final int THRDS_NUM = 12; + static final String DEBUGGEE_THRNAMES[] = { + "invokemethod011tMainThr", "invokemethod011tThr1", "invokemethod011tThr2", + "invokemethod011tThr3", "invokemethod011tThr4", "invokemethod011tThr5", + "invokemethod011tThr6", "invokemethod011tThr7", "invokemethod011tThr8", + "invokemethod011tThr9", "invokemethod011tThr10", "invokemethod011tThr11" + }; + + // tested debuggee method + static final String DEBUGGEE_METHOD = + "dummyMeth"; + + // debuggee fields used to operate on an invoked method + static final String DEBUGGEE_FIELDS[] = { + "doExit", "isInvoked" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int ATTEMPTS = 10; + static final int DELAY = 1000; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod011().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod011t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[THRDS_NUM]; + for (int i=0; i methList = rType.methodsByName(DEBUGGEE_METHOD); + + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHOD + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + Method meth = methList.get(0); + LinkedList argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + InvokingThread invThr = null; + Wicket invThrWicket = null; + BooleanValue val = null; + + // Check the tested assersion + for (int i=1; i<=2; i++) + { + invThrWicket = new Wicket(); + + switch(i) { + case 1: // invocation with all threads resumption + invThr = new InvokingThread(clsType, thrRef[0], meth, + argList, 0, invThrWicket); + break; + case 2: // the single threaded invocation + invThr = new InvokingThread(clsType, thrRef[0], meth, + argList, ClassType.INVOKE_SINGLE_THREADED, invThrWicket); + break; + } + invThr.setDaemon(true); + invThr.start(); + + // wait for invThr to be started + log.display("Waiting for invThr thread to be started ..."); + invThrWicket.waitFor(); + + log.display("Waiting for debuggee method invocation ..."); + int tryOns = 0; + do { + if (tryOns > ATTEMPTS) + throw new Failure("unable to continue testing after " + + ATTEMPTS + + " attempts: debuggee method is not invoked yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + val = (BooleanValue) + clsType.getValue(fldToCheck); + tryOns++; + } while (!val.value()); + + // check threads during method invocation + checkThreads(thrRef, i); + + clsType.setValue(fldToExit, vm.mirrorOf(true)); + + invThr.join(argHandler.getWaitTime()*60000); + log.display("Thread \"" + invThr.getName() + "\" done"); + + // check threads status after method invocation + checkThreads(thrRef, 0); + } + + } catch (Exception e) { + e.printStackTrace(); + // force an method to exit if it has been invoked + if (clsType != null && fldToExit != null) { + try { + clsType.setValue(fldToExit, vm.mirrorOf(true)); + } catch(Exception ee) { + ee.printStackTrace(); + } + } + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private void checkThreads(ThreadReference thrRef[], int state) { + switch (state) { + case 0: + log.display("\n\nVerifying threads status after method invocation:"); + break; + case 1: + log.display("\n\nVerifying invocation with all threads resumption:"); + break; + case 2: + log.display("\n\nVerifying the single threaded invocation (INVOKE_SINGLE_THREADED):"); + break; + } + + // check an invoking debuggee thread + if (thrRef[0].isSuspended()) { + if (state == 0) { // after invocation + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis suspended again after invocation as expected"); + } else { + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + "\n\tis still suspended"); + tot_res = Consts.TEST_FAILED; + } + } else { + if (state == 0) { // after invocation + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + + "\n\tis not suspended again after the invocation"); + tot_res = Consts.TEST_FAILED; + } else { + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis resumed as expected"); + } + } + // check other debuggee threads + for (int i=1; i argList; + int bitOpts; + Wicket wicket; + + InvokingThread(ClassType clsRef, ThreadReference thrRef, Method meth, + LinkedList argList, int bitOpts, Wicket wicket) { + this.clsRef = clsRef; + this.thrRef = thrRef; + this.meth = meth; + this.argList = argList; + this.bitOpts = bitOpts; + this.wicket = wicket; + super.setName("InvokingThread"); + } + + public void run() { + wicket.unlock(); + + try { + log.display("\nInvokingThread: trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\twith the arguments: " + argList + + "\"\n\tand " + + new String((bitOpts==ClassType.INVOKE_SINGLE_THREADED)? "with" : "without") + + " the flag INVOKE_SINGLE_THREADED\n\tusing the debuggee class \"" + + clsRef + "\" ..."); + + LongValue retVal = (LongValue) + clsRef.invokeMethod(thrRef, meth, argList, bitOpts); + log.display("InvokingThread: the method returned " + retVal); + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + log.display("InvokingThread: exiting"); + } + } +///////////////////////////////////////////////////////////////////////////// + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011/TestDescription.java new file mode 100644 index 00000000000..f31eba22b76 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod011. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that invocation with all threads resumption + * and the single threaded one will be performed properly through + * the JDI method: + * com.sun.jdi.ClassType.invokeMethod(). + * The following assertions are verified: + * - by default, all threads in the target VM are resumed while + * the method is being invoked; + * - when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation; + * - only the specified thread will be resumed with the flag + * INVOKE_SINGLE_THREADED; + * - upon completion of a single threaded invoke, the invoking + * thread will be suspended once again. + * A debuggee part of the test starts several threads. Then debugger + * calls the JDI method without and with the flag INVOKE_SINGLE_THREADED + * sequentially. During the invocations and after them the threads state + * is expected to be as described above. + * COMMENTS + * Fixed TEST_BUG 6358778. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod011 + * nsk.jdi.ClassType.invokeMethod.invokemethod011t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod011 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011t.java new file mode 100644 index 00000000000..48651dd30f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod011t.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is debuggee class. + */ +public class invokemethod011t { + static Log log; + private invokemethod011Thr thrs[] = + new invokemethod011Thr[invokemethod011.THRDS_NUM-1]; + private IOPipe pipe; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod011t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + pipe = argHandler.createDebugeeIOPipe(); + log = argHandler.createDebugeeLog(); + Thread.currentThread().setName(invokemethod011.DEBUGGEE_THRNAMES[0]); + // start several dummy threads with given names + startThreads(); + + pipe.println(invokemethod011.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod011.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod011.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + killThreads(argHandler.getWaitTime()*60000); + if (!cmd.equals(invokemethod011.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + + return Consts.TEST_PASSED; + } + + /* + * Dummy fields and method used to check the flag INVOKE_SINGLE_THREADED + * in the debugger. + */ + // used by the debugger to let the invoked method exit + static volatile boolean doExit = false; + // indicator of the method invocation + static volatile boolean isInvoked = false; + + static long dummyMeth(long l) throws InterruptedException { + invokemethod011t.log.display("dummyMeth: going to loop"); + isInvoked = true; + while(!doExit) { + l--; l++; + Thread.currentThread().sleep(400); + } + invokemethod011t.log.display("dummyMeth: exiting"); + isInvoked = false; + doExit = false; + return l; + } + + private void startThreads() { + Object readyObj = new Object(); + + for (int i=0; i + * com.sun.jdi.ClassType.invokeMethod(). + * The following assertions are verified: + *

  • only the specified thread will be resumed with the flag + * INVOKE_SINGLE_THREADED + *
  • upon completion of a single threaded invoke, the invoking + * thread will be suspended once again; any threads started during + * the single threaded invocation will not be suspended when the + * invocation completes.

    + * + * A debuggee part of the test starts several threads. The debugger + * calls the JDI method with the flag ClassType.INVOKE_SINGLE_THREADED. + * Then, during the invocation the debugger resumes some threads. + * Upon completing the invocation, these resumed threads are checked + * to be not suspended again. + */ +public class invokemethod012 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.invokeMethod.invokemethod012t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 68; + + // debuggee fields used to operate on an invoked method + static final String DEBUGGEE_FIELDS[] = { + "doExit", "isInvoked" + }; + + // debuggee threads to be check + static final int THRDS_NUM = 12; + static final String DEBUGGEE_THRDS[][] = { + {"invokemethod012tMainThr", "no"}, + {"invokemethod012tThr1", "no"}, + {"invokemethod012tThr2", "resume"}, + {"invokemethod012tThr3", "resume"}, + {"invokemethod012tThr4", "no"}, + {"invokemethod012tThr5", "no"}, + {"invokemethod012tThr6", "no"}, + {"invokemethod012tThr7", "no"}, + {"invokemethod012tThr8", "resume"}, + {"invokemethod012tThr9", "no"}, + {"invokemethod012tThr10", "no"}, + {"invokemethod012tThr11", "resume"} + }; + + // debuggee method to be invoke + static final String DEBUGGEE_METHOD = + "dummyMeth"; + + static final int ATTEMPTS = 10; + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod012().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod012t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[THRDS_NUM]; + for (int i=0; i argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + Wicket invThrWicket = new Wicket(); + + // the single threaded invocation + InvokingThread invThr = new InvokingThread(clsType, thrRef[0], meth, + argList, ClassType.INVOKE_SINGLE_THREADED, invThrWicket); + + invThr.setDaemon(true); + invThr.start(); + + // wait for invThr to be started + log.display("Waiting for invThr thread to be started ..."); + invThrWicket.waitFor(); + + log.display("Waiting for debuggee method invocation ..."); + int tryOns = 0; + BooleanValue val = null; + do { + if (tryOns > ATTEMPTS) + throw new Failure("unable to continue testing after " + + ATTEMPTS + + " attempts: debuggee method is not invoked yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + val = (BooleanValue) + clsType.getValue(fldToCheck); + tryOns++; + } while (!val.value()); + + // check threads during the method invocation + checkThreads(thrRef, 1); + + // resume some threads during the method invocation + resumeSomeThreads(thrRef); + + clsType.setValue(fldToExit, vm.mirrorOf(true)); + invThr.join(argHandler.getWaitTime()*60000); + log.display("Thread \"" + invThr.getName() + "\" done"); + + // check threads status after the method invocation + checkThreads(thrRef, 0); + } catch (Exception e) { + e.printStackTrace(); + // force an method to exit if it has been invoked + if (clsType != null && fldToExit != null) { + try { + clsType.setValue(fldToExit, vm.mirrorOf(true)); + } catch(Exception ee) { + ee.printStackTrace(); + } + } + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private void checkThreads(ThreadReference thrRef[], int state) { + switch (state) { + case 0: + log.display("\nVerifying threads status when the invocation completes:"); + break; + case 1: + log.display("\nVerifying the single threaded invocation:"); + break; + } + + // check an invoking debuggee thread + if (thrRef[0].isSuspended()) { + if (state == 0) { // after invocation + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis suspended again after the invocation as expected"); + } else { + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + "\n\tis still suspended"); + tot_res = Consts.TEST_FAILED; + } + } else { + if (state == 0) { // after invocation + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + + "\n\tis not suspended again after the invocation"); + tot_res = Consts.TEST_FAILED; + } else { + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis resumed as expected"); + } + } + // check other debuggee threads + for (int i=1; i ATTEMPTS) + throw new Failure("unable to continue testing after " + + ATTEMPTS + + " attempts: debuggee thread " + + thrRef[i] + " is not resumed yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + tryOns++; + } while (thrRef[i].isSuspended()); + log.display("The thread " + thrRef[i] + + "\n\tis resumed"); + } + } + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("\nFinal resumption of the debuggee VM"); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + + /** + * A separate thread class used in debuggee method invocation because + * it is synchronous. + */ + class InvokingThread extends Thread { + ClassType clsRef; + ThreadReference thrRef; + Method meth; + LinkedList argList; + int bitOpts; + Wicket wicket; + + InvokingThread(ClassType clsRef, ThreadReference thrRef, Method meth, + LinkedList argList, int bitOpts, Wicket wicket) { + this.clsRef = clsRef; + this.thrRef = thrRef; + this.meth = meth; + this.argList = argList; + this.bitOpts = bitOpts; + this.wicket = wicket; + super.setName("InvokingThread"); + } + + public void run() { + wicket.unlock(); + + try { + log.display("\nInvokingThread: trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\twith the arguments: " + argList + + "\"\n\tand " + + new String((bitOpts==ClassType.INVOKE_SINGLE_THREADED)? "with" : "without") + + " the flag INVOKE_SINGLE_THREADED\n\tusing the debuggee class \"" + + clsRef + "\" ..."); + + LongValue retVal = (LongValue) + clsRef.invokeMethod(thrRef, meth, argList, bitOpts); + log.display("InvokingThread: the method returned " + retVal); + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + log.display("InvokingThread: exiting"); + } + } +///////////////////////////////////////////////////////////////////////////// +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012/TestDescription.java new file mode 100644 index 00000000000..2e1d646a829 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod012. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the single threaded invocation will be + * performed properly through the JDI method: + * com.sun.jdi.ClassType.invokeMethod(). + * The following assertions are verified: + * - only the specified thread will be resumed with the flag + * INVOKE_SINGLE_THREADED; + * - upon completion of a single threaded invoke, the invoking + * thread will be suspended once again; any threads started + * during the single threaded invocation will not be suspended + * when the invocation completes. + * A debuggee part of the test starts several threads. The debugger + * calls the JDI method with the flag ClassType.INVOKE_SINGLE_THREADED. + * Then, during the invocation the debugger resumes some threads. + * Upon completing the invocation, these resumed threads are checked + * to be not suspended again. + * COMMENTS + * Fixed TEST_BUG 6358778. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod012 + * nsk.jdi.ClassType.invokeMethod.invokemethod012t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod012 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012t.java new file mode 100644 index 00000000000..9a93c682f0b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012t.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is main debuggee class. + */ +public class invokemethod012t { + static Log log; + private invokemethod012Thr thrs[] = + new invokemethod012Thr[invokemethod012.THRDS_NUM-1]; + private IOPipe pipe; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod012t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(invokemethod012.DEBUGGEE_THRDS[0][0]); + // Start several dummy threads with given names + startThreads(); + + // Now the debuggee is ready for testing + pipe.println(invokemethod012.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod012.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod012.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + killThreads(argHandler.getWaitTime()*60000); + if (!cmd.equals(invokemethod012.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + + return Consts.TEST_PASSED; + } + + /* + * Dummy fields and method used to check the flag INVOKE_SINGLE_THREADED + * in the debugger. + */ + // used by the debugger to let the invoked method exit + static volatile boolean doExit = false; + // indicator of the method invocation + static volatile boolean isInvoked = false; + + static long dummyMeth(long l) throws InterruptedException { + invokemethod012t.log.display("dummyMeth: going to loop"); + isInvoked = true; + while(!doExit) { + l--; l++; + Thread.currentThread().sleep(400); + } + invokemethod012t.log.display("dummyMeth: exiting"); + isInvoked = false; + doExit = false; + return l; + } + + private void startThreads() { + Object readyObj = new Object(); + + for (int i=0; i < invokemethod012.THRDS_NUM-1; i++) { + thrs[i] = new invokemethod012Thr(readyObj, + invokemethod012.DEBUGGEE_THRDS[i+1][0]); + thrs[i].setDaemon(true); + log.display("Debuggee: starting thread #" + + i + " \"" + thrs[i].getName() + "\" ..."); + synchronized(readyObj) { + thrs[i].start(); + try { + readyObj.wait(); // wait for the thread's readiness + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: waiting for the thread " + + thrs[i].toString() + " start: caught " + e); + pipe.println("failed"); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + } + log.display("Debuggee: the thread #" + + i + " \"" + thrs[i].getName() + "\" started"); + } + } + + private void killThreads(int waitTime) { + for (int i=0; i < invokemethod012.THRDS_NUM-1 ; i++) { + thrs[i].doExit = true; + try { + thrs[i].join(waitTime); + log.display("Debuggee: thread #" + + i + " \"" + thrs[i].getName() + "\" done"); + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: joining the thread #" + + i + " \"" + thrs[i].getName() + "\": caught " + e); + } + } + } + + /** + * This is an auxiliary thread class used to check the flag + * INVOKE_SINGLE_THREADED in the debugger. + */ + class invokemethod012Thr extends Thread { + volatile boolean doExit = false; + private Object readyObj; + + invokemethod012Thr(Object readyObj, String name) { + super(name); + this.readyObj = readyObj; + } + + public void run() { + Thread thr = Thread.currentThread(); + Object waitObj = new Object(); + + synchronized(readyObj) { + readyObj.notify(); // notify the main thread + } + log.display("Debuggee thread \"" + + thr.getName() + "\": going to loop"); + while(!doExit) { + int i = 0; + i++; i--; + + // reliable analogue of Thread.yield() + synchronized(waitObj) { + try { + waitObj.wait(30); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + log.complain("TEST FAILURE: Debuggee thread \"" + + thr.getName() + + "\" interrupted while sleeping:\n\t" + e); + break; + } + } + } + log.display("Debuggee thread \"" + + thr.getName() + "\" exiting ..."); + } + } +///////////////////////////////////////////////////////////////////////////// + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013.java new file mode 100644 index 00000000000..68600892b59 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013.java @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that debuggee method invocation will be + * performed properly through the JDI method
    + * com.sun.jdi.ClassType.invokeMethod().

    + * + * The following assertions are verified: + *

  • all threads in the target VM are resumed while the method is + * being invoked. If the thread's suspend count is greater than 1, + * it will remain in a suspended state during the invocation. + *
  • when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation.

    + * + * A debuggee part of the test starts several threads. The debugger + * suspends all threads by a breakpoint event and then, some + * of them one more time. After that, it calls the JDI method. The + * threads are checked to be resumed or remain suspended during the + * invocation (depending on the suspend count), and, upon completing + * the invocation, to be suspended again. + */ +public class invokemethod013 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.invokeMethod.invokemethod013t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 68; + + // debuggee fields used to operate on invoked method + static final String DEBUGGEE_FIELDS[] = { + "doExit", "isInvoked" + }; + + // debuggee threads to be check and their suspend count + static final int THRDS_NUM = 12; + static final String DEBUGGEE_THRDS[][] = { + {"invokemethod013tThr", "single-suspension"}, + {"invokemethod013tThr1", "single-suspension"}, + {"invokemethod013tThr2", "single-suspension"}, + {"invokemethod013tThr3", "single-suspension"}, + {"invokemethod013tThr4", "double-suspension"}, + {"invokemethod013tThr5", "single-suspension"}, + {"invokemethod013tThr6", "single-suspension"}, + {"invokemethod013tThr7", "single-suspension"}, + {"invokemethod013tThr8", "double-suspension"}, + {"invokemethod013tThr9", "double-suspension"}, + {"invokemethod013tThr10", "single-suspension"}, + {"invokemethod013tThr11", "double-suspension"} + }; + + // debuggee method to be invoke + static final String DEBUGGEE_METHOD = + "dummyMeth"; + + static final int ATTEMPTS = 10; + static final int DELAY = 400; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod013().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod013t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[THRDS_NUM]; + for (int i=0; i methList = rType.methodsByName(DEBUGGEE_METHOD); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHOD + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + Method meth = methList.get(0); + LinkedList argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + Wicket invThrWicket = new Wicket(); + InvokingThread invThr = new InvokingThread(clsRef, thrRef[0], + meth, argList, 0, invThrWicket); + + invThr.setDaemon(true); + + // suspend some threads one more time before the method + // invocation to make the thread's suspend count greater than 1 + suspendSomeThreads(thrRef); + + // perform the invocation + invThr.start(); + + // wait for invThr to be started + log.display("Waiting for invThr thread to be started ..."); + invThrWicket.waitFor(); + + log.display("Waiting for debuggee method invocation ..."); + int tryOns = 0; + BooleanValue val = null; + do { + if (tryOns > ATTEMPTS) + throw new Failure("unable to continue testing after " + + ATTEMPTS + + " attempts: debuggee method is not invoked yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + val = (BooleanValue) + clsRef.getValue(fldToCheck); + tryOns++; + } while (!val.value()); + + // check threads during the method invocation + checkThreads(thrRef, 1); + + // finish the invocation + clsRef.setValue(fldToExit, vm.mirrorOf(true)); + invThr.join(argHandler.getWaitTime()*60000); + log.display("Thread \"" + invThr.getName() + "\" done"); + + // check threads status after the method invocation + checkThreads(thrRef, 0); + } catch (Exception e) { + e.printStackTrace(); + // force an method to exit if it has been invoked + if (clsRef != null && fldToExit != null) { + try { + clsRef.setValue(fldToExit, vm.mirrorOf(true)); + } catch(Exception ee) { + ee.printStackTrace(); + } + } + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private void checkThreads(ThreadReference thrRef[], int state) { + log.display("\nVerifying threads status " + + new String((state==0)? "after" : "during") + + " the invocation:"); + + // check an invoking debuggee thread + if (thrRef[0].isSuspended()) { + if (state == 0) { // after invocation + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis suspended again after the invocation as expected"); + } else { + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + "\n\tis still suspended"); + tot_res = Consts.TEST_FAILED; + } + } else { + if (state == 0) { // after invocation + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + + "\n\tis not suspended again after the invocation"); + tot_res = Consts.TEST_FAILED; + } else { + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis resumed as expected"); + } + } + // check other debuggee threads + for (int i=1; i ATTEMPTS) + throw new Failure("unable to continue testing after " + + ATTEMPTS + + " attempts: debuggee thread " + + thrRef[i] + " is not suspended yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + tryOns++; + } while (thrRef[i].suspendCount() != 2); + log.display("The thread " + thrRef[i] + + "\n\tis suspended one more time: the number of pending suspends = " + + thrRef[i].suspendCount()); + } + } + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("Resuming debuggee VM twice ..."); + vm.resume(); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + + /** + * A separate thread class used in the debuggee method invocation because + * it is synchronous. + */ + class InvokingThread extends Thread { + ClassType clsRef; + ThreadReference thrRef; + Method meth; + LinkedList argList; + int bitOpts; + Wicket wicket; + + InvokingThread(ClassType clsRef, ThreadReference thrRef, Method meth, + LinkedList argList, int bitOpts, Wicket wicket) { + this.clsRef = clsRef; + this.thrRef = thrRef; + this.meth = meth; + this.argList = argList; + this.bitOpts = bitOpts; + this.wicket = wicket; + super.setName("InvokingThread"); + } + + public void run() { + wicket.unlock(); + + try { + log.display("\nInvokingThread: trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\twith the arguments: " + argList + + "\"\n\tusing the debuggee class \"" + + clsRef + "\" ..."); + + LongValue retVal = (LongValue) + clsRef.invokeMethod(thrRef, meth, argList, bitOpts); + log.display("InvokingThread: the method returned " + retVal); + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + log.display("InvokingThread: exiting"); + } + } +///////////////////////////////////////////////////////////////////////////// +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013/TestDescription.java new file mode 100644 index 00000000000..0842b206ad8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod013. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that debuggee method invocation will be + * performed properly through the JDI method: + * com.sun.jdi.ClassType.invokeMethod(). + * The following assertions are verified: + * - all threads in the target VM are resumed while the method is + * being invoked. If the thread's suspend count is greater than 1, + * it will remain in a suspended state during the invocation. + * - when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation. + * A debuggee part of the test starts several threads. The debugger + * suspends all threads by a breakpoint event and then, some + * of them one more time. After that, it calls the JDI method. The + * threads are checked to be resumed or remain suspended during the + * invocation (depending on the suspend count), and, upon completing + * the invocation, to be suspended again. + * COMMENTS + * Fixed TEST_BUG 6358778. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod013 + * nsk.jdi.ClassType.invokeMethod.invokemethod013t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod013 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013t.java new file mode 100644 index 00000000000..8224f26e657 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod013t.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is main debuggee class. + */ +public class invokemethod013t { + static Log log; + private invokemethod013Thr thrs[] = + new invokemethod013Thr[invokemethod013.THRDS_NUM-1]; + private IOPipe pipe; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod013t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(invokemethod013.DEBUGGEE_THRDS[0][0]); + // Start several dummy threads with given names + startThreads(); + + // Now the debuggee is ready for testing + pipe.println(invokemethod013.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod013.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod013.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + killThreads(argHandler.getWaitTime()*60000); + if (!cmd.equals(invokemethod013.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + + return Consts.TEST_PASSED; + } + + /* + * Dummy fields and method used to check method invocation in the debugger. + */ + // used by the debugger to let the invoked method exit + static volatile boolean doExit = false; + // indicator of the method invocation + static volatile boolean isInvoked = false; + + static long dummyMeth(long l) throws InterruptedException { + invokemethod013t.log.display("dummyMeth: going to loop"); + isInvoked = true; + while(!doExit) { + l--; l++; + Thread.currentThread().sleep(400); + } + invokemethod013t.log.display("dummyMeth: exiting"); + isInvoked = false; + doExit = false; + return l; + } + + private void startThreads() { + Object readyObj = new Object(); + + for (int i=0; i < invokemethod013.THRDS_NUM-1; i++) { + thrs[i] = new invokemethod013Thr(readyObj, + invokemethod013.DEBUGGEE_THRDS[i+1][0]); + thrs[i].setDaemon(true); + + log.display("Debuggee: starting thread #" + + i + " \"" + thrs[i].getName() + "\" ..."); + synchronized(readyObj) { + thrs[i].start(); + try { + readyObj.wait(); // wait for the thread's readiness + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: waiting for the thread " + + thrs[i].toString() + " start: caught " + e); + pipe.println("failed"); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + } + log.display("Debuggee: the thread #" + + i + " \"" + thrs[i].getName() + "\" started"); + } + } + + private void killThreads(int waitTime) { + for (int i=0; i < invokemethod013.THRDS_NUM-1 ; i++) { + thrs[i].doExit = true; + try { + thrs[i].join(waitTime); + log.display("Debuggee: thread #" + + i + " \"" + thrs[i].getName() + "\" done"); + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: joining the thread #" + + i + " \"" + thrs[i].getName() + "\": caught " + e); + } + } + } + + /** + * This is an auxiliary thread class used to check method + * invocation in the debugger. + */ + class invokemethod013Thr extends Thread { + volatile boolean doExit = false; + private Object readyObj; + + invokemethod013Thr(Object readyObj, String name) { + super(name); + this.readyObj = readyObj; + } + + public void run() { + Thread thr = Thread.currentThread(); + Object waitObj = new Object(); + + synchronized(readyObj) { + readyObj.notify(); // notify the main thread + } + log.display("Debuggee thread \"" + + thr.getName() + "\": going to loop"); + while(!doExit) { + int i = 0; + i++; i--; + + // reliable analogue of Thread.yield() + synchronized(waitObj) { + try { + waitObj.wait(30); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + log.complain("TEST FAILURE: Debuggee thread \"" + + thr.getName() + + "\" interrupted while sleeping:\n\t" + e); + break; + } + } + } + log.display("Debuggee thread \"" + + thr.getName() + "\" exiting ..."); + } + } +///////////////////////////////////////////////////////////////////////////// + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014.java new file mode 100644 index 00000000000..ab5c0ae798f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014.java @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ClassType.invokeMethod() + * properly throws IllegalArgumentException when + * debugger part of the test attempts to invoke several + * debuggee methods: + *

  • which are constructors or static intializers + *
  • which are instance ones. + */ +public class invokemethod014 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.invokeMethod.invokemethod014t"; + + // tested instance debuggee methods + static final int METH_NUM = 12; + static final String DEBUGGEE_METHODS[] = { + "", + "", + "byteMeth", + "shortMeth", + "intMeth", + "longMeth", + "floatMeth", + "doubleMeth", + "charMeth", + "booleanMeth", + "strMeth", + "voidMeth" + }; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod014tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 61; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod014().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod014t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef = null; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + ClassType clsType = (ClassType) rType; + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; iemptyList(), 0); + + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to invoke instance method/initializer \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee class \"" + clsType + "\""); + tot_res = Consts.TEST_FAILED; + } catch (IllegalArgumentException is) { + log.display("CHECK PASSED: caught expected " + is); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ClassType.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected IllegalArgumentException" + + "\n\twhen attempted to invoke instance method/initializer \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee class \"" + clsType + "\""); + tot_res = Consts.TEST_FAILED; + } + + } + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + BPreq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("Final resuming debuggee VM ..."); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014/TestDescription.java new file mode 100644 index 00000000000..bf89fb63c35 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod014. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ClassType.invokeMethod() + * properly throws IllegalArgumentException when debugger part + * of the test attempts to invoke several debuggee methods: + * - which are constructors or static intializers; + * - which are instance ones. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod014 + * nsk.jdi.ClassType.invokeMethod.invokemethod014t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod014 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014t.java new file mode 100644 index 00000000000..f482c4c396d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod014t.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is debuggee class. + */ +public class invokemethod014t { + static {} // force javac to produce method + + invokemethod014t() {} // force javac to produce method + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod014t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Thread.currentThread().setName(invokemethod014.DEBUGGEE_THRNAME); + + pipe.println(invokemethod014.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod014.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod014.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod014.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } + + // Dummy instance methods used to provoke IllegalArgumentException in the debugger + byte byteMeth() { + return 127; + } + + short shortMeth() { + return -32768; + } + + int intMeth() { + return 2147483647; + } + + long longMeth() { + return 9223372036854775807L; + } + + float floatMeth() { + return 5.1F; + } + + double doubleMeth() { + return 6.2D; + } + + char charMeth() { + return 'a'; + } + + boolean booleanMeth() { + return false; + } + + String strMeth() { + return "string method"; + } + + void voidMeth() {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015.java new file mode 100644 index 00000000000..b96cfe74d68 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015.java @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.io.*; +import java.util.*; + +/** + */ +public class invokemethod015 { + + //----------------------------------------------------- immutable common fields + + private int waitTime; + private static int exitStatus = Consts.TEST_PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.ClassType.invokeMethod"; + private final static String className = ".invokemethod015"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + static final int lineForBreak = 54; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + //------------------------------------------------------ test specific fields + + private static final String fieldName = "f1"; + private static final String methodName = "values"; +// private static final String methodSignature = "()[Lnsk/jdi/ClassType/invokeMethod/invokemethod015aEnum"; + private static final String[] expectedEnumFieldsNames = { "e1", "e2" }; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new invokemethod015().runThis(argv, out); + return exitStatus; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStderr(log, ""); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (Consts.TEST_PASSED + Consts.JCK_STATUS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitStatus = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitStatus = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitStatus; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + BreakpointRequest bpRequest = setBreakpoint( null, + debuggeeClass, + "methodForCommunication", + lineForBreak, + "breakForCommunication"); + bpRequest.enable(); + + display("Wait for initial brakepoint event..."); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + ThreadReference thread = bpEvent.thread(); + + display("TESTING BEGINS"); + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + List l = checkedClass.methods(); + Method checkedMethod = null; + if (l.isEmpty()) { + complain("\t ReferenceType.methods() returned empty list for type: " + className); + exitStatus = Consts.TEST_FAILED; + } else { + Iterator it = l.iterator(); + while (it.hasNext()) { + Method m = it.next(); + if (methodName.equals(m.name())) + checkedMethod = m; + } + if (checkedMethod != null) { + ArrayReference values = (ArrayReference)checkedClass.invokeMethod(thread, checkedMethod , Collections.emptyList(), 0); + if (values.length() == 2) { + List constants = values.getValues(); + Iterator it1 = constants.iterator(); + while (it1.hasNext()) { + ObjectReference checkedField = (ObjectReference)it1.next(); + if (checkedField.type().equals(checkedClass)) { + display("Invoked method " + methodName + " returned expected object " + checkedField.toString()); + } else { + display("Invoked method " + methodName + " returned unexpected object " + checkedField.toString()); + exitStatus = Consts.TEST_FAILED; + } + } + } else { + complain("Invoked method " + methodName + " returned list of unexpected size: " + values.length()); + exitStatus = Consts.TEST_FAILED; + } + } else { + complain("Cannot find in " + className + " the checked method " + methodName); + exitStatus = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methods + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private Event waitForEvent () { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + resultEvent = eventIterator.nextEvent(); + if (resultEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015/TestDescription.java new file mode 100644 index 00000000000..e15d0cf8b15 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/invokeMethod/invokemethod015. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for invokeMethod method of ClassType interface. + * The test checks if static values() method returns mirrors of enum + * constants when it was invoked via checked method for any mirrored + * enum type. The values() method is automatically implemented in any + * enum type. + * The debugger class - nsk.jdi.ClassType.invokeMethod.ivokemethod015; + * the debuggee class - nsk.jdi.ClassType.invokeMethod.ivokemethod015a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's methodForCommunication() method. This breakpoint allows the + * debugger to obtain ThreadReference mirror of debuggee's main thread; + * - after getting the BreakpointEvent, the debugger finds mirrors of + * invokemethod015aEnum enum type and of values() method; + * - then the debugger calls invokeMethod with found mirrors as parameters + * and check if returned list is of correct size and contains ObjectRefences + * for every declared enum constant. + * In case of error the test produces the exit code 97 and a corresponding + * error message(s). Otherwise, the test is passed with exit code 95. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.invokeMethod.invokemethod015 + * nsk.jdi.ClassType.invokeMethod.invokemethod015a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.invokeMethod.invokemethod015 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015a.java new file mode 100644 index 00000000000..fe2050c68a9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015a.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class invokemethod015a { + + //----------------------------------------------------- immutable common fields + + static int exitCode = Consts.TEST_PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + static void methodForCommunication() { + int i = 1; // invokemethod015.lineForBreak + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static invokemethod015aEnum f1 = invokemethod015aEnum.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + display("debuggee started!"); + + methodForCommunication(); + + display("debuggee exits"); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific methodss +} + +//--------------------------------------------------------- test specific classes + +enum invokemethod015aEnum { + e1, e2; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001.java new file mode 100644 index 00000000000..52b9a92241b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.isEnum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isenum001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ClassType.isEnum."; + private final static String className = "isenum001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + if (checkedClass.isEnum()) { + display("CHECK PASSED: ClassType.isEnum() returned expected true for type: " + className); + } else { + complain("ClassType.isEnum() returned unexpected false for type: " + className); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001/TestDescription.java new file mode 100644 index 00000000000..00948ebc9cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/isEnum/isenum001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isEnum() method of ClassType interface. + * The test checks if the method returns true for any + * mirrored enum type + * The test consists of a debugger program (isenum001.java) + * and debuggee application (isenum001a.java). + * Package name is nsk.jdi.ClassType.isEnum . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isEnum() method for each field + * of enum type declared in isenum001a class. + * The test fails if the method returned false once or more. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.isEnum.isenum001 + * nsk.jdi.ClassType.isEnum.isenum001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.isEnum.isenum001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001a.java new file mode 100644 index 00000000000..96639ad0d5b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/isEnum/isenum001a.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.isEnum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isenum001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum2 f2 = Enum2.e2; + static Enum3 f3 = Enum3.e1; + static Enum4.Enum4_ f4 = Enum4.Enum4_.e1; + static isenum001Enum5 f5 = isenum001Enum5.e2; + static isenum001Enum6 f6 = isenum001Enum6.e1; + static isenum001Enum7 f7 = isenum001Enum7.e2; + static isenum001Enum8.Enum8_ f8 = isenum001Enum8.Enum8_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isenum001.SIGNAL_READY); + + + //pipe.println(isenum001.SIGNAL_GO); + receiveSignal(isenum001.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + enum Enum1 { + e1, e2; + } + + enum Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); + } + + enum Enum3 implements isenum001i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); + } + + enum Enum4 { + e1, e2; + + enum Enum4_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum isenum001Enum5 { + e1, e2; +} + +enum isenum001Enum6 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} + +enum isenum001Enum7 implements isenum001i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); +} + +enum isenum001Enum8 { + e1, e2; + enum Enum8_ { + e1, e2; + } +} + +interface isenum001i { + int i = 1; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001.java new file mode 100644 index 00000000000..7121131fb20 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001.java @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.newInstance()
    + * complies with its specification.
    + * The case for testing includes invoking the method to create
    + * new instance of the class TestClass
    + * which is global to a class implementing debuggee's thread
    + * in which instance creation is performed.
    + * No exception is expected to be thrown in response to call
    + * to the method.
    + *
    + * The test works as follows.
    + * A debugger launchs a debuggee which creates new thread, thread2.
    + * The tested class TestClass is specified outside of the class
    + * Threadnewinstance002a extends Thread
    + * After getting thread2 running but locked at a monitor
    + * the debugger informs the debugger of the thread2 creation
    + * and waits for an instruction from it.
    + * Upon receiving the message from the debuggee, the debugger
    + * sets up a breakpoint for the thread2 and instructs the
    + * debuggee to unlock the thread2 and after getting it suspended
    + * at the breakpoint, prepares arguments and invokes the method.
    + * After the method completes, the debugger checks up on
    + * a returned ObjectReference value;
    + * the following is expected to be true:
    + * objRef.referenceType().equals(classType)
    + * where
    + * ObjectReference objRef - is returned value
    + * ClassType classType - is a mirror of the tested class.
    + */ + +public class newinstance001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/newInstance/newinstance001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new newinstance001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.newInstance.newinstance001a"; + + private String testedClassName = + "nsk.jdi.ClassType.newInstance.TestClass"; + + private String threadName = "testedThread"; + + private String threadClassName = + "nsk.jdi.ClassType.newInstance.Threadnewinstance001a"; + + //String mName = "nsk.jdi.ClassType.newInstance"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedClass = null; + + ReferenceType threadClass = null; + + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String breakpointMethod1 = "runt1"; + + String bpLine1 = "breakpointLineNumber1"; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + + ClassType classType = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(threadClassName); + threadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + + log2("......getting Thread thread2 - 1-st argument"); + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + + log2("......getting ClassType classType - an object to apply newInstance()"); + classes = vm.classesByName(testedClassName); + testedClass = (ReferenceType) classes.get(0); + classType = (ClassType) testedClass; + + List invokeMethods = testedClass.methods(); + ListIterator li = invokeMethods.listIterator(); + + Method invokeMethod = null; + + log2("......getting Method invokeMethod - a constructor to invoke; 2-nd argument"); + try { + for (;;) { + invokeMethod = (Method) li.next(); + if (!invokeMethod.isConstructor()) + continue; + if (invokeMethod.arguments().size() == 0) + break; + } + } catch ( AbsentInformationException e1 ) { + log2(" AbsentInformationException "); + break label1; + } catch ( NoSuchElementException e2 ) { + log3("ERROR: NoSuchElementException "); + expresult = returnCode2; + break label1; + } + + + // this is only to get an empty List with JDI methods but not with API List methods + log2("......forming an empty List argumentList for 3-d argument"); + log2(" List argumentList = testedClass.methodsByName('m');"); + List argumentListm = testedClass.methodsByName("m"); + log2(" argumentList.clear();"); + argumentListm.clear(); + List argumentList = Collections.emptyList(); + + ObjectReference objRef = null; + + log2("......ObjectReference objRef = classType.newInstance(thread2, invokeMethod, argumentList, 0);"); + log2(" No Exception is expected"); + try { + objRef = classType.newInstance(thread2, + invokeMethod, argumentList, 0); + if (objRef == null) + log2(" objRe == null"); + + + log2(" ReferenceType refType = objRef.referenceType();"); + ReferenceType refType = objRef.referenceType(); + + log2(" ClassType cType = (ClassType) refType;"); + ClassType cType = (ClassType) refType; + + log2("......checking up on: cType.equals(classType); "); + if (!cType.equals(classType)) { + log3("ERROR: !cType.equals(classType)"); + expresult = returnCode1; + } + + } catch ( Exception e ) { + log3("ERROR: Exception for classType.newInstance() :" + e); + expresult = returnCode1; + } + } + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { +// Method method = (Method) testedclass.methodsByName(methodName).get(0); + Method method = (Method) threadClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = +// ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + ( (IntegerValue) threadClass.getValue(threadClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001/TestDescription.java new file mode 100644 index 00000000000..333a7acf131 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001/TestDescription.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.newInstance() + * complies with its spec: + * public ObjectReference newInstance(ThreadReference thread, + * Method method, + * List arguments, + * int options) + * throws InvalidTypeException, + * ClassNotLoadedException, + * IncompatibleThreadStateException, + * InvocationException + * Constructs a new instance of this type, using the given constructor Method + * in the target VM. The specified constructor must be defined in the this class. + * Instance creation will occur in the specified thread. + * Instance creation can occur only if the specified thread has + * been suspended by an event which occurred in that thread. + * Instance creation is not supported when the target + * VM has been suspended through VirtualMachine.suspend() or + * when the specified thread is suspended through ThreadReference.suspend(). + * The specified constructor is invoked with the arguments in the specified + * argument list. The invocation is synchronous; this method does not return + * until the constructor returns in the target VM. If the invoked method + * throws an exception, this method will throw an InvocationException which + * contains a mirror to the exception object thrown. + * Object arguments must be assignment compatible with the argument type + * (This implies that the argument type must be loaded through the enclosing + * class's class loader). Primitive arguments must be either assignment + * compatible with the argument type or must be convertible to the argument type + * without loss of information. + * See JLS section 5.2 for more information on assignment compatibility. + * By default, all threads in the target VM are resumed while the method is being + * invoked if they were previously suspended by an event or by + * VirtualMachine.suspend() or ThreadReference.suspend(). + * This is done to prevent the deadlocks that will occur if any of the threads own + * monitors that will be needed by the invoked method. + * It is possible that breakpoints or other events might occur during + * the invocation. Note, however, that this implicit resume acts exactly like + * ThreadReference.resume(), so if the thread's suspend count is greater than 1, + * it will remain in a suspended state during the invocation. + * By default, when the invocation completes, + * all threads in the target VM are suspended, + * regardless their state before the invocation. + * The resumption of other threads during the invocation can be prevented by + * specifying the INVOKE_SINGLE_THREADED bit flag in the options argument; + * however, there is no protection against or recovery from the deadlocks + * described above, so this option should be used with great caution. + * Only the specified thread will be resumed (as described for all threads above). + * Upon completion of a single threaded invoke, the invoking thread will be + * suspended once again. Note that any threads started during the single threaded + * invocation will not be suspended when the invocation completes. + * If the target VM is disconnected during the invoke + * (for example, through VirtualMachine.dispose()) + * the method invocation continues. + * Parameters: + * thread - the thread in which to invoke. + * method - the constructor Method to invoke. + * arguments - the list of Value arguments bound to the invoked constructor. + * Values from the list are assigned to arguments in + * the order they appear in the constructor signature. + * options - the integer bit flag options. + * Returns: + * an ObjectReference mirror of the newly created object. + * Throws: + * IllegalArgumentException - + * if the method is not a member of this class, if the size of the + * argument list does not match the number of declared arguments for + * the constructor, or if the method is not a constructor. + * {link - InvalidTypeException} if any argument in the argument list is not + * assignable to the corresponding method argument type. + * ClassNotLoadedException - + * if any argument type has not yet been loaded through the appropriate class loader. + * IncompatibleThreadStateException - + * if the specified thread has not been suspended by an event. + * InvocationException - + * if the method invocation resulted in an exception in the target VM. + * ObjectCollectedException - + * if the given thread or any object argument has been garbage collected. + * Also thrown if this class has been unloaded and garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to the same VirtualMachine. + * The case for testing includes invoking the method on the class TestClass + * which is global to a class implementing debuggee's thread in which + * instance creation is performed. + * No exception is expected to be thrown in response to call to the method. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.newInstance.newinstance001; + * the debuggee program - nsk.jdi.ClassType.newInstance.newinstance001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance001 + * nsk.jdi.ClassType.newInstance.newinstance001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001a.java new file mode 100644 index 00000000000..73f81f2b285 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance001a.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the newinstance001 JDI test. + */ + +public class newinstance001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.newInstance()
    + * complies with its specification.
    + * The case for testing includes invoking the method to create
    + * new instance of an inner class of ClassType extending Thread class.
    + * No exception is expected to be thrown in response to call
    + * to the method.
    + *
    + * The test works as follows.
    + * A debugger launchs a debuggee which creates new thread, thread2
    + * a tested class TestClass1 is specified within a class
    + * Threadnewinstance002a extends Thread
    + * After getting thread2 running but locked at a monitor
    + * the debugger informs the debugger of the thread2 creation
    + * and waits for an instruction from it.
    + * Upon receiving the message from the debuggee, the debugger
    + * sets up a breakpoint for the thread2 and instructs the
    + * debuggee to unlock the thread2 and after getting it suspended
    + * at the breakpoint, prepares arguments and invokes the method.
    + * After the method completes, the debugger checks up on
    + * a returned ObjectReference value; the following is expected
    + * to be true:
    + * objRef.referenceType().equals(classType)
    + * where
    + * ObjectReference objRef - is returned value
    + * ClassType classType - is a mirror of the tested class.
    + */ + +public class newinstance002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/newInstance/newinstance002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new newinstance002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.newInstance.newinstance002a"; + + private String testedClassName = + "nsk.jdi.ClassType.newInstance.Threadnewinstance002a$TestClass1"; + + private String threadName = "testedThread"; + + private String threadClassName = + "nsk.jdi.ClassType.newInstance.Threadnewinstance002a"; + + //String mName = "nsk.jdi.ClassType.newInstance"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedClass = null; + + ReferenceType threadClass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String breakpointMethod1 = "runt1"; + + String bpLine1 = "breakpointLineNumber1"; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + + ClassType classType = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(threadClassName); + threadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + + log2("......getting ClassType classType - an object to apply newInstance()"); + classes = vm.classesByName(testedClassName); + testedClass = (ReferenceType) classes.get(0); + classType = (ClassType) testedClass; + + List invokeMethods = testedClass.methods(); + ListIterator li = invokeMethods.listIterator(); + + Method invokeMethod = null; + + log2("......getting Method invokeMethod - a constructor to invoke; 2-nd argument"); + try { + for (;;) { + invokeMethod = (Method) li.next(); + if (!invokeMethod.isConstructor()) + continue; + if (invokeMethod.arguments().size() == 0) + break; + } + } catch ( AbsentInformationException e1 ) { + log2(" AbsentInformationException "); + break label1; + } catch ( NoSuchElementException e2 ) { + log3("ERROR: NoSuchElementException "); + expresult = returnCode2; + break label1; + } + + + ObjectReference objRef = null; + + log2("......ObjectReference objRef = classType.newInstance(thread2, invokeMethod, Arrays.asList(thread2), 0);"); + log2(" No Exception is expected"); + try { + objRef = classType.newInstance(thread2, + invokeMethod, Arrays.asList(thread2), 0); + if (objRef == null) + log2(" objRe == null"); + + + log2(" ReferenceType refType = objRef.referenceType();"); + ReferenceType refType = objRef.referenceType(); + + log2(" ClassType cType = (ClassType) refType;"); + ClassType cType = (ClassType) refType; + + log2("......checking up on: cType.equals(classType); "); + if (!cType.equals(classType)) { + log3("ERROR: !cType.equals(classType)"); + expresult = returnCode1; + } + + } catch ( Exception e ) { + log3("ERROR: Exception for classType.newInstance() :" + e); + expresult = returnCode1; + } + + } + vm.resume(); // for case if thread2 was not resumed because of error in a check + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { +// Method method = (Method) testedclass.methodsByName(methodName).get(0); + Method method = (Method) threadClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = +// ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + ( (IntegerValue) threadClass.getValue(threadClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002/TestDescription.java new file mode 100644 index 00000000000..947582c18e8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002/TestDescription.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance002. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-4462897 + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.newInstance() + * complies with its spec: + * public ObjectReference newInstance(ThreadReference thread, + * Method method, + * List arguments, + * int options) + * throws InvalidTypeException, + * ClassNotLoadedException, + * IncompatibleThreadStateException, + * InvocationException + * Constructs a new instance of this type, using the given constructor Method + * in the target VM. The specified constructor must be defined in the this class. + * Instance creation will occur in the specified thread. + * Instance creation can occur only if the specified thread has + * been suspended by an event which occurred in that thread. + * Instance creation is not supported when the target + * VM has been suspended through VirtualMachine.suspend() or + * when the specified thread is suspended through ThreadReference.suspend(). + * The specified constructor is invoked with the arguments in the specified + * argument list. The invocation is synchronous; this method does not return + * until the constructor returns in the target VM. If the invoked method + * throws an exception, this method will throw an InvocationException which + * contains a mirror to the exception object thrown. + * Object arguments must be assignment compatible with the argument type + * (This implies that the argument type must be loaded through the enclosing + * class's class loader). Primitive arguments must be either assignment + * compatible with the argument type or must be convertible to the argument type + * without loss of information. + * See JLS section 5.2 for more information on assignment compatibility. + * By default, all threads in the target VM are resumed while the method is being + * invoked if they were previously suspended by an event or by + * VirtualMachine.suspend() or ThreadReference.suspend(). + * This is done to prevent the deadlocks that will occur if any of the threads own + * monitors that will be needed by the invoked method. + * It is possible that breakpoints or other events might occur during + * the invocation. Note, however, that this implicit resume acts exactly like + * ThreadReference.resume(), so if the thread's suspend count is greater than 1, + * it will remain in a suspended state during the invocation. + * By default, when the invocation completes, + * all threads in the target VM are suspended, + * regardless their state before the invocation. + * The resumption of other threads during the invocation can be prevented by + * specifying the INVOKE_SINGLE_THREADED bit flag in the options argument; + * however, there is no protection against or recovery from the deadlocks + * described above, so this option should be used with great caution. + * Only the specified thread will be resumed (as described for all threads above). + * Upon completion of a single threaded invoke, the invoking thread will be + * suspended once again. Note that any threads started during the single threaded + * invocation will not be suspended when the invocation completes. + * If the target VM is disconnected during the invoke + * (for example, through VirtualMachine.dispose()) + * the method invocation continues. + * Parameters: + * thread - the thread in which to invoke. + * method - the constructor Method to invoke. + * arguments - the list of Value arguments bound to the invoked constructor. + * Values from the list are assigned to arguments in + * the order they appear in the constructor signature. + * options - the integer bit flag options. + * Returns: + * an ObjectReference mirror of the newly created object. + * Throws: + * IllegalArgumentException - + * if the method is not a member of this class, if the size of the + * argument list does not match the number of declared arguments for + * the constructor, or if the method is not a constructor. + * {link - InvalidTypeException} if any argument in the argument list is not + * assignable to the corresponding method argument type. + * ClassNotLoadedException - + * if any argument type has not yet been loaded through the appropriate class loader. + * IncompatibleThreadStateException - + * if the specified thread has not been suspended by an event. + * InvocationException - + * if the method invocation resulted in an exception in the target VM. + * ObjectCollectedException - + * if the given thread or any object argument has been garbage collected. + * Also thrown if this class has been unloaded and garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to the same VirtualMachine. + * The case for testing includes invoking the method on an inner class of + * ClassType extending Thread class. + * No exception is expected to be thrown in response to call to the method. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.newInstance.newinstance002; + * the debuggee program - nsk.jdi.ClassType.newInstance.newinstance002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance002 + * nsk.jdi.ClassType.newInstance.newinstance002a + * + * @comment make sure newinstance002a is compiled with full debug info + * @clean nsk.jdi.ClassType.newInstance.newinstance002a + * @compile -g:lines,source,vars ../newinstance002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002a.java new file mode 100644 index 00000000000..4ae343397bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance002a.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the newinstance002 JDI test. + */ + +public class newinstance002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + +// static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * 1. he specified constructor must be defined in this class

    + * 2. IllegalArgumentException is thrown if
    + * - the method is not a member of this class;
    + * - the size of the argument list does not match the number
    + * of declared arguemnts for the constructor, or if the
    + * method is not a constructor.
    + */ + +public class newinstance003 { + + private final static String prefix = "nsk.jdi.ClassType.newInstance."; + private final static String debuggerName = prefix + "newinstance003"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + private ClassType class2Check; + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + newinstance003 thisTest = new newinstance003(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + class2Check = (ClassType )debugee.classByName(prefix + + newinstance003a.class2Check); + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.makeBreakpoint(testedClass, + newinstance003a.brkpMethodName, + newinstance003a.brkpLineNumber); + brkp.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + brkp.enable(); + debugee.resume(); + + debugee.sendSignal(""); + Event event = null; + + // waiting the breakpoint event + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + + thread = brkpEvent.thread(); + + display("\nTEST BEGINS"); + display("==========="); + + ObjectReference obj = null; + Value retValue, value = null, + expectedValue = debugee.VM().mirrorOf(6L); + List params = new Vector(); + + // 1 case--------------------------------------------------------------- + // checking up IllegalArgumentException, the size of the argument list + // does not match the number of declared arguments for the constructor + display("\nthe size of the argument list does not match the number " + + "of declared arguments"); + display("----------------------------------------------------------" + + "-------------------"); + Method method = getConstructor(class2Check); + display("method>" + method); + try { + obj = class2Check.newInstance(thread, method, params, 0); + complain("***IllegalArgumentException is not thrown***"); + exitStatus = Consts.TEST_FAILED; + } catch(IllegalArgumentException e) { + display(">expected " + e); + } catch(Exception e) { + complain(" unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + // 2 case--------------------------------------------------------------- + // checking up IllegalArgumentException, the method is not a constructor + display("\nthe method is not a constructor"); + display("-------------------------------"); + method = debugee.methodByName(class2Check, newinstance003a.method); + display("method>" + method); + try { + obj = class2Check.newInstance(thread, method, params, 0); + complain("***IllegalArgumentException is not thrown***"); + exitStatus = Consts.TEST_FAILED; + } catch(IllegalArgumentException e) { + display(">expected " + e); + } catch(Exception e) { + complain(" unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + // 3 case--------------------------------------------------------------- + // checking up IllegalArgumentException, when constructor is a member + // of superclass + params.add(debugee.VM().mirrorOf(1)); + display("\nconstructor is a member of superclass"); + display("-------------------------------------"); + method = getConstructor(testedClass); + display("method>" + method); + ReferenceType refType; + Field field; + try { + obj = class2Check.newInstance(thread, method, params, 0); + complain("***IllegalArgumentException is not thrown***"); + exitStatus = Consts.TEST_FAILED; + } catch(IllegalArgumentException e) { + display(">expected " + e); + } catch(Exception e) { + complain(" unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + // 4 case--------------------------------------------------------------- + // when constructor is a member of this class + display("\nconstructor is a member of this class"); + display("-------------------------------------"); + method = getConstructor(class2Check); + display("method>" + method); + try { + obj = class2Check.newInstance(thread, method, params, 0); + refType = obj.referenceType(); + field = refType.fieldByName("sum"); + retValue = obj.getValue(field); + if (((PrimitiveValue )retValue).intValue() != 1) { + complain("unexpected value of field: " + retValue); + exitStatus = Consts.TEST_FAILED; + } else { + display(">created instance :" + obj); + } + } catch(Exception e) { + complain(" unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private Method getConstructor(ReferenceType classType) { + List methodList = classType.methods(); + Method method; + for (int i = 0; i < methodList.size(); i++) { + method = (Method )methodList.get(i); + if (method.isConstructor()) { + return method; + } + } + return null; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003/TestDescription.java new file mode 100644 index 00000000000..b384a01392a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that a result of the method + * com.sun.jdi.ClassType.newInstance() + * throws IllegalArgumentException according to spec. + * Test checks up the following assertions: + * 1. The specified constructor must be defined in this class. + * 2. IllegalArgumentException is thrown if + * - the method is not a member of this class, + * - the size of the argument list does not match the number of declared + * arguments for the constructor, or if the method is not + * a constructor. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.makeBreakpoint() method for setting breakpoint + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance003 + * nsk.jdi.ClassType.newInstance.newinstance003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003a.java new file mode 100644 index 00000000000..55f2467cc2b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance003a.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * newinstance003a is deugee's part of the newinstance003. + */ +public class newinstance003a { + + public final static String anotherClassName = "newinstance003b"; + public final static String class2Check = "newinstance003Child"; + public final static String method = "insteadOfConstructor"; + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + newinstance003Child child = new newinstance003Child(1); + pipe.println(newinstance003.SGNL_READY); + String instr = pipe.readln(); + log.display("breakpoint line"); // brkpLineNumber + instr = pipe.readln(); + if (instr.equals(newinstance003.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + + } + + protected static long sum; + newinstance003a(int one) { + sum = one; + } +} + +class newinstance003Child extends newinstance003a { + newinstance003Child(int one) { + super(one); + } + + public static void insteadOfConstructor() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004.java new file mode 100644 index 00000000000..76eb4253c02 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up the following assertion:
    + * If the invoked method throws an exception, this method will throw + * an InvocationException which contains a mirror to the exception object thrown. + * It is checked for two cases: + * 1. when the invoked method throws uncaught NullPointerExection.
    + * For this case, InvocationException is expected, the one
    + * contains a mirror to the NullPointerException object.
    + * 2. when invoked method throws caught exection
    + * For this case, no exceptions are expected
    + */ + +public class newinstance004 { + + private final static String prefix = "nsk.jdi.ClassType.newInstance."; + private final static String debuggerName = prefix + "newinstance004"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + newinstance004 thisTest = new newinstance004(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + newinstance004a.brkpMethodName, + newinstance004a.brkpLineNumber); + debugee.resume(); + + debugee.sendSignal(""); + Event event = null; + + // waiting the breakpoint event + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + + thread = brkpEvent.thread(); + + ReferenceType exceptionRefType = + debugee.classByName(newinstance004a.testException); + + display("\nTEST BEGINS"); + display("==========="); + + Value retValue; + ObjectReference obj = null; + List params = new Vector(); + + display("\nuncaught NullPointerException"); + display("-----------------------------"); + Method method = getConstructor(testedClass); + display("method>" + method); + params.add(debugee.VM().mirrorOf(false)); + try { + obj = testedClass.newInstance(thread, method, params, 0); + complain("***InvocationException is not thrown***"); + exitStatus = Consts.TEST_FAILED; + } catch(InvocationException e) { + display("!!!expected " + e); + if (e.exception().referenceType().equals(exceptionRefType)) { + display("!!!expected the exception mirror " + e.exception()); + } else { + complain("Unexpected the exception mirror " + + e.exception().referenceType()); + complain("We are expecting " + exceptionRefType); + exitStatus = Consts.TEST_FAILED; + } + } catch(Exception e) { + complain(" unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + // caught NullPointerException + display("\ncaught NullPointerException"); + display("-----------------------------"); + method = getConstructor(testedClass); + params.clear(); + params.add(debugee.VM().mirrorOf(true)); + display("method>" + method); + try { + obj = testedClass.newInstance(thread, method, params, 0); + if (!obj.referenceType().equals(testedClass)) { + complain("wrong object type:" + obj.referenceType()); + exitStatus = Consts.TEST_FAILED; + } + } catch(Exception e) { + complain(" unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private Method getConstructor(ReferenceType classType) { + List methodList = classType.methods(); + Method method; + for (int i = 0; i < methodList.size(); i++) { + method = (Method )methodList.get(i); + if (method.isConstructor()) { + return method; + } + } + return null; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004/TestDescription.java new file mode 100644 index 00000000000..155fb60b865 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that a result of the method + * com.sun.jdi.ClassType.newInstance() + * throws InvocationException according to spec. + * Test checks up the following assertion: + * If the invoked method throws an exception, this method will throw + * an InvocationException which contains a mirror to the exception object + * thrown. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance004 + * nsk.jdi.ClassType.newInstance.newinstance004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004a.java new file mode 100644 index 00000000000..cd55ab1c30a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance004a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * newinstance004a is deugee's part of the newinstance004. + */ +public class newinstance004a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + public final static String testException = "java.lang.NullPointerException"; + + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(newinstance004.SGNL_READY); + String instr = pipe.readln(); + log.display("breakpoint line"); // brkpLineNumber + instr = pipe.readln(); + if (instr.equals(newinstance004.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + newinstance004a(boolean caughtException) { + Object obj = null; + String tmp; + if (caughtException) { + try { + tmp = obj.toString(); + } catch (NullPointerException e) { + } + } else { + tmp = obj.toString(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005.java new file mode 100644 index 00000000000..e67364e684c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import java.util.*; +import java.io.*; +import java.lang.reflect.Array; + +/** + * Test checks up the following assertion: + * Primitive arguments must be either assignment compatible with + * the argument type or must be convertible to the argument type + * without loss of information. + * for every primitive type + */ + +public class newinstance005 extends ValueConversionDebugger { + + private ClassType testedClass; + private ThreadReference thread; + + static class TestedConstructorData { + String signature; + String fieldName; + ValueType type; + + TestedConstructorData(String signature, String fieldName, ValueType type) { + this.signature = signature; + this.fieldName = fieldName; + this.type = type; + } + } + + private static final TestedConstructorData [] testedConstructors = { + new TestedConstructorData("(B)V", "byteValue", BYTE), + new TestedConstructorData("(C)V", "charValue", CHAR), + new TestedConstructorData("(D)V", "doubleValue", DOUBLE), + new TestedConstructorData("(F)V", "floatValue", FLOAT), + new TestedConstructorData("(I)V", "intValue", INT), + new TestedConstructorData("(J)V", "longValue", LONG), + new TestedConstructorData("(S)V", "shortValue", SHORT) + }; + + + private Field field; + + private static byte [] byteParamValues = + {Byte.MIN_VALUE, + -1, + 0, + 1, + Byte.MAX_VALUE}; + private static char [] charParamValues = + {Character.MIN_VALUE, + Character.MAX_VALUE}; + private static double [] doubleParamValues = + {Double.NEGATIVE_INFINITY, + -1.5D, + -1.0D, + -0.0D, + +0.0D, + Double.MIN_VALUE, + 1.0D, + 1.5D, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY}; + private static float [] floatParamValues = + {Float.NEGATIVE_INFINITY, + -1.5F, + -1.0F, + -0.0F, + +0.0F, + Float.MIN_VALUE, + 1.0F, + 1.5F, + Float.MAX_VALUE, + Float.POSITIVE_INFINITY}; + private static int [] intParamValues = + {Integer.MIN_VALUE, + -1, + 0, + 1, + 1234567890, + Integer.MAX_VALUE}; + private static long [] longParamValues = + {Long.MIN_VALUE, + -1L, + 0L, + 1L, + 1234567890123456789L, + Long.MAX_VALUE}; + private static short [] shortParamValues = + {Short.MIN_VALUE, + -1, + 0, + 1, + Short.MAX_VALUE}; + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new newinstance005().runIt(argv, out); + } + + protected String debuggeeClassName() { + return newinstance005a.class.getName(); + } + + protected void doTest() { + initDefaultBreakpoint(); + + BreakpointEvent brkpEvent = forceBreakpoint(); + + testedClass = (ClassType )debuggee.classByName(debuggeeClassNameWithoutArgs()); + + thread = brkpEvent.thread(); + + display("\nTEST BEGINS"); + display("==========="); + + + PrimitiveValue value = null; + List params = new ArrayList(); + + Method method; + Object arr = null; + // Type type = null; + boolean validConversion; + for (TestedConstructorData testedConstructor : testedConstructors) { + method = testedClass.concreteMethodByName("", testedConstructor.signature); + if (method == null) { + complain("method :" + testedConstructor.signature + " not found"); + setSuccess(false); + continue; + } + display(""); + field = testedClass.fieldByName(testedConstructor.fieldName); + display("Method : " + method); + display("Field : " + field); + display("============="); + for (ValueType type : ValueType.values()) { + switch (type) { + case BYTE: + arr = byteParamValues; + display("\tbyte values"); + break; + case CHAR: + arr = charParamValues; + display("\tchar values"); + break; + case DOUBLE: + arr = doubleParamValues; + display("\tdouble values"); + break; + case FLOAT: + arr = floatParamValues; + display("\tfloat values"); + break; + case INT: + arr = intParamValues; + display("\tinteger values"); + break; + case LONG: + arr = longParamValues; + display("\tlong values"); + break; + case SHORT: + arr = shortParamValues; + display("\tshort values"); + break; + default: + complain("\t***TEST CASE ERROR***"); + setSuccess(false); + continue; + } + + display("\t--------------"); + for (int i = 0; i < Array.getLength(arr); i++) { + params.clear(); + value = createValue(arr, i); + params.add(value); + validConversion = isValidConversion(testedConstructor.type, value); + try { + newInstance(thread, method, params, value); + if (!validConversion) { + complain(lastConversion); + complain("***InvalidTypeException is not thrown***"); + setSuccess(false); + } + } catch(InvalidTypeException e) { + if (validConversion) { + complain(lastConversion); + complain("*** unexpected InvalidTypeException***"); + setSuccess(false); + } else { + display(lastConversion); + display("!!!expected InvalidTypeException"); + } + } + display(""); + } + } + } + + display("============="); + display("TEST FINISHES\n"); + + removeDefaultBreakpoint(); + + debuggee.resume(); + } + + private void newInstance(ThreadReference thread, Method method, List params, + PrimitiveValue expectedValue) throws InvalidTypeException { + ObjectReference objRef = null; + PrimitiveValue param; + try { + for (int i = 0; i < params.size(); i++) { + param = (PrimitiveValue )params.get(i); + if (param instanceof CharValue) { + display("\tParameters : " + Integer.toHexString(param.charValue()) + "(" + param.type() + ")"); + } else { + display("\tParameters : " + param + "(" + param.type() + ")"); + } + } + objRef = testedClass.newInstance(thread, method, params, + ClassType.INVOKE_SINGLE_THREADED); + } catch(ClassNotLoadedException e) { + complain("exception: " + e); + setSuccess(false); + } catch(IncompatibleThreadStateException e) { + complain("exception: " + e); + setSuccess(false); + } catch(InvocationException e) { + complain("exception: " + e); + setSuccess(false); + } + + PrimitiveValue returnedValue = (PrimitiveValue)objRef.getValue(field); + + String retType = returnedValue != null ? returnedValue.type().toString() + : ""; + display("\tReturn value: " + returnedValue + "(" + retType + ")"); + + checkValueConversion(expectedValue, returnedValue); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005/TestDescription.java new file mode 100644 index 00000000000..2eb275bfed2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ClassType.newInstance() + * Test checks up the following assertion: + * Primitive arguments must be either assignment compatible with + * the argument type or must be convertible to the argument type + * without loss of information. + * for every primitive type. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance005 + * nsk.jdi.ClassType.newInstance.newinstance005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005a.java new file mode 100644 index 00000000000..3d4430556ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance005a.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * newinstance005a is deugee's part of the newinstance005. + */ +public class newinstance005a extends AbstractJDIDebuggee { + + private static byte byteValue; + private static char charValue; + private static double doubleValue; + private static float floatValue; + private static int intValue; + private static long longValue; + private static short shortValue; + + public static void main (String args[]) { + new newinstance005a().doTest(args); + } + + newinstance005a() { + + } + + newinstance005a(byte value) { + byteValue = value; + } + + newinstance005a(char value) { + charValue = value; + } + + newinstance005a(double value) { + doubleValue = value; + } + + newinstance005a(float value) { + floatValue = value; + } + + newinstance005a(int value) { + intValue = value; + } + + newinstance005a(long value) { + longValue = value; + } + + newinstance005a(short value) { + shortValue = value; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006.java new file mode 100644 index 00000000000..80eb364a686 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up that NullPointerException will be thrown in + * the following cases:
    + * - newInstance(null, method, params,ClassType.INVOKE_SINGLE_THREADED)
    + * - newInstance(thread, null, params,ClassType.INVOKE_SINGLE_THREADED)
    + * - newInstance(thread, method, null,ClassType.INVOKE_SINGLE_THREADED)
    + * In case
    + * newInstance(thread, method, params,Integer.MAX_VALUE)
    + * no exception is expected. + */ + +public class newinstance006 { + + private final static String prefix = "nsk.jdi.ClassType.newInstance."; + private final static String debuggerName = prefix + "newinstance006"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + public final static String method2Invoke = "justMethod"; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + newinstance006 thisTest = new newinstance006(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + newinstance006a.brkpMethodName, + newinstance006a.brkpLineNumber); + debugee.resume(); + + debugee.sendSignal(""); + Event event = null; + + // waiting the breakpoint event + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + + thread = brkpEvent.thread(); + + display("\nTEST BEGINS"); + display("==========="); + + ObjectReference objRef; + List params = createParams(1); + + Method method = getConstructor(testedClass); + display("Method : " + method); + + display("newInstance(null, method, params," + + "ClassType.INVOKE_SINGLE_THREADED)"); + try { + objRef = testedClass.newInstance(null, method, params, + ClassType.INVOKE_SINGLE_THREADED); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("newInstance(thread, null, params," + + "ClassType.INVOKE_SINGLE_THREADED)"); + try { + objRef = testedClass.newInstance(thread, null, params, + ClassType.INVOKE_SINGLE_THREADED); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("newInstance(thread, method, null," + + "ClassType.INVOKE_SINGLE_THREADED)"); + try { + objRef = testedClass.newInstance(thread, method, null, + ClassType.INVOKE_SINGLE_THREADED); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("newInstance(thread, method, params," + + "Integer.MAX_VALUE)"); + try { + objRef = testedClass.newInstance(thread, method, params, + Integer.MAX_VALUE); + if (!objRef.referenceType().equals(testedClass)) { + complain("Wrong returned value " + objRef.toString()); + exitStatus = Consts.TEST_FAILED; + } else { + display("returned value is " + objRef.toString()); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("newInstance(thread, method, params," + + "Integer.MIN_VALUE)"); + try { + objRef = testedClass.newInstance(thread, method, params, + Integer.MIN_VALUE); + if (!objRef.referenceType().equals(testedClass)) { + complain("Wrong returned value " + objRef.toString()); + exitStatus = Consts.TEST_FAILED; + } else { + display("returned value is " + objRef.toString()); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private List createParams(int size) { + Vector params = new Vector(); + for (int i = 0; i < size; i++) { + params.add(debugee.VM().mirrorOf(i + 1)); + } + return params; + } + + private Method getConstructor(ReferenceType classType) { + List methodList = classType.methods(); + Method method; + for (int i = 0; i < methodList.size(); i++) { + method = (Method )methodList.get(i); + if (method.isConstructor()) { + return method; + } + } + return null; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006/TestDescription.java new file mode 100644 index 00000000000..16663125ece --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ClassType.newInstance() + * Test checks up that NullPointerException will be thrown in + * the following cases: + * - newInstance(null, method, params,ClassType.INVOKE_SINGLE_THREADED) + * - newInstance(thread, null, params,ClassType.INVOKE_SINGLE_THREADED) + * - newInstance(thread, method, null,ClassType.INVOKE_SINGLE_THREADED) + * In case + * newInstance(thread, method, params,Integer.MAX_VALUE) + * no exception is expected. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance006 + * nsk.jdi.ClassType.newInstance.newinstance006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006a.java new file mode 100644 index 00000000000..98ca9a8c85d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance006a.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * newinstance006a is deugee's part of the newinstance006. + */ +public class newinstance006a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 47; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(newinstance006.SGNL_READY); + String instr = pipe.readln(); + log.display("breakpoint line"); // brkpLineNumber + instr = pipe.readln(); + if (instr.equals(newinstance006.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + newinstance006a(int val) { + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007.java new file mode 100644 index 00000000000..a7421d1d3d1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * + * The test checks up the method com.sun.jdi.ClassType.newInstance() + * + * Test checks up the following assertion: + * ...all threads in the target VM are resumed while the method is + * being invoked if they were previously suspended by an event or by + * VirtualMachine.suspend() or ThreadReference.suspend(). + * + * This checking is implemented for three cases: + * - when the tested thread is suspended by ThreadReference.suspend(); + * - when the tested thread is suspended by VirtualMachine.suspend(); + * - when the tested thread is suspended by an event. + */ + +public class newinstance007 { + + private final static String prefix = "nsk.jdi.ClassType.newInstance."; + private final static String debuggerName = prefix + "newinstance007"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + public final static String SGNL_STRTHRD = "start_thread"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ClassType testedClass; + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + newinstance007 thisTest = new newinstance007(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.makeBreakpoint(testedClass, + newinstance007a.brkpMethodName, + newinstance007a.brkpLineNumber); + brkp.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + brkp.enable(); + + display("\nTEST BEGINS"); + display("==========="); + + ObjectReference objRef = null; + Field field = testedClass.fieldByName("invokingTime"); + List params = new Vector(); + ThreadReference suspendedThread; + BreakpointEvent brkpEvent; + + Method method = getConstructor(testedClass); + display("Method : " + method); + + for (int i = 0; i < 3; i++) { + display(""); + switch (i) { + case 0: + display("\nCASE#0 : Thread is suspended by ThreadReference.suspend()"); + break; + case 1: + display("\nCASE#1 : Thread is suspended by VirtualMachine.suspend()"); + break; + case 2: + display("\nCASE#2 : Thread is suspended by BreakPointRequest"); + brkp.disable(); + brkp.setSuspendPolicy(EventRequest.SUSPEND_ALL); + brkp.enable(); + } + + // starting thread + display("sending signal " + SGNL_STRTHRD); + debugee.sendSignal(SGNL_STRTHRD); + debugee.resume(); + display("waiting for signal " + SGNL_READY); + debugee.receiveExpectedSignal(SGNL_READY); + + brkpEvent = waitForBreakpoint(brkp); + + thread = brkpEvent.thread(); + + suspendedThread = debugee.threadByName(newinstance007a.testedThread); + switch (i) { + case 0: + suspendedThread.suspend(); + break; + case 1: + debugee.VM().suspend(); + break; + } + + if ( !suspendedThread.isSuspended() ) { + complain(suspendedThread.name() + " is not suspended"); + exitStatus = Consts.TEST_FAILED; + } else { + display(suspendedThread.name() + " is suspended"); + } + try { + if (i == 1) { + // for VirtualMachine.suspended() only! + // resume thread for invokedMethod + thread.resume(); + } + display("invoking the constructor"); + objRef = testedClass.newInstance(thread, method, params, 0); + Value retValue = objRef.getValue(field); + suspendedThread = debugee.threadByName("im007aThread01"); + if (((PrimitiveValue)retValue).longValue() >= waitTime) { + complain("CASE #" + i + " FAILED." + + "\n\tTimeout occured while invocation of debugee's constructor"); + exitStatus = Consts.TEST_FAILED; + } else { + display("CASE #" + i + " PASSED"); + } + } catch(Exception e) { + complain("Unexpected exception while invocation of debugee's constructor: " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private BreakpointEvent waitForBreakpoint(BreakpointRequest brkp) { + Event event = null; + BreakpointEvent brkpEvent; + + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + brkpEvent = (BreakpointEvent )event; + return brkpEvent; + } + + private Method getConstructor(ReferenceType classType) { + List methodList = classType.methods(); + Method method; + for (int i = 0; i < methodList.size(); i++) { + method = (Method )methodList.get(i); + if (method.isConstructor()) { + return method; + } + } + return null; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007/TestDescription.java new file mode 100644 index 00000000000..3075d7eacba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance007. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ClassType.newInstance() + * Test checks up the following assertion: + * ...all threads in the target VM are resumed while the method is + * being invoked if they were previously suspended by an event or by + * VirtualMachine.suspend() or ThreadReference.suspend(). + * This checking is implemented for three cases: + * - when the tested thread is suspended by ThreadReference.suspend(); + * - when the tested thread is suspended by VirtualMachine.suspend(); + * - when the tested thread is suspended by an event. + * COMMENTS: + * 4786806 TEST_BUG: debugee does not relinquishes lock after notifying + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.makeBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance007 + * nsk.jdi.ClassType.newInstance.newinstance007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007a.java new file mode 100644 index 00000000000..56b29efa380 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance007a.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * newinstance007a is deugee's part of the newinstance007. + */ +public class newinstance007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 70; + public final static String testedThread = "im007aThread01"; + + public static Log log; + public static long waitTime; + private static IOPipe pipe; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + pipe = argHandler.createDebugeeIOPipe(log); + im007aThread01 thread = null; + pipe.println(newinstance007.SGNL_READY); + + String instr = pipe.readln(); + while (!instr.equals(newinstance007.SGNL_QUIT)) { + + // create new thread and start it + if (instr.equals(newinstance007.SGNL_STRTHRD)) { + thread = new im007aThread01("im007aThread01"); + synchronized(im007aThread01.waitStarting) { + thread.start(); + try { + im007aThread01.waitStarting.wait(waitTime); + log.display("checked thread started"); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for checked thread start."); + } + } + } + log.display("sending ready signal..."); + pipe.println(newinstance007.SGNL_READY); + log.display("waiting signal from debugger..."); // brkpLineNumber + instr = pipe.readln(); // this is a line for breakpoint + + if (thread.isAlive()) { + log.display("waiting for join of : " + thread.getName()); + try { + thread.join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for join of " + thread.getName()); + } + if (thread.isAlive()) { + try { + thread.interrupt(); + } catch (SecurityException e) { + throw new Failure("Cannot interrupt checked thread."); + } + } + } + } + + if (instr.equals(newinstance007.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + private static long invokingTime; + newinstance007a() { + log.display("constructor> starting..."); + invokingTime = 0; + try { + synchronized(im007aThread01.waitFinishing) { + synchronized(im007aThread01.waitInvoking) { + log.display("constructor> notifying to thread..."); + im007aThread01.waitInvoking.notify(); + } + + log.display("constructor> waiting for thread's response..."); + long startTime = System.currentTimeMillis(); + im007aThread01.waitFinishing.wait(waitTime); + invokingTime = System.currentTimeMillis() - startTime; + return; + } + } catch (InterruptedException e) { + log.display("constructor> it was interrupted."); + } + invokingTime = waitTime + 1; + } +} + +class im007aThread01 extends Thread { + public static Object waitInvoking = new Object(); + public static Object waitStarting = new Object(); + public static Object waitFinishing = new Object(); + + im007aThread01(String threadName) { + super(threadName); + } + + public void run() { + synchronized(waitInvoking) { + synchronized(waitStarting) { + waitStarting.notifyAll(); + } + + newinstance007a.log.display(getName() + "> waiting for the invoked method..."); + try { + long startTime = System.currentTimeMillis(); + waitInvoking.wait(newinstance007a.waitTime); + if ((System.currentTimeMillis() - startTime) < newinstance007a.waitTime) { + newinstance007a.log.display(getName() + "> got a response from the invoked method"); + } else { + newinstance007a.log.display(getName() + "*** no response from invoked method"); + } + } catch (Exception e) { + newinstance007a.log.display(getName() + e); + } + } + synchronized(waitFinishing) { + newinstance007a.log.display(getName() + "> notifying to invoked method..."); + waitFinishing.notify(); + } + newinstance007a.log.display(getName() + "> thread finished"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008.java new file mode 100644 index 00000000000..e0a990e7ca4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008.java @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * + * The test checks up the method com.sun.jdi.ClassType.newInstance() + * + * Test checks up the following assertion: + * If the target VM is disconnected during the invoke (for example, + * through VirtualMachine.dispose()) the method invocation continues. + */ + +public class newinstance008 { + + private final static String prefix = "nsk.jdi.ClassType.newInstance."; + private final static String debuggerName = prefix + "newinstance008"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + public final static String SGNL_FINISH = "finish"; + public final static String SGNL_ABORT = "abort"; + + public static int exitStatus; + public static Log log; + public static Debugee debugee; + public static long waitTime; + private static boolean isAborted = false; + + private ClassType testedClass; + + public static void display(String msg) { + log.display(msg); + } + + public static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + newinstance008 thisTest = new newinstance008(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Failure e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + if (!isAborted) { + debugee.resume(); + debugee.quit(); + } + } + + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure{ + + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + InvokingThread invokeThrd = new InvokingThread(); + invokeThrd.start(); + + // waiting READY signal from invoked constructor + display("\nwaiting for signal \"" + + SGNL_READY + + "\" from the invoked constructor"); + debugee.receiveExpectedSignal(SGNL_READY); + + display("\nConstructor has been invoked. Trying to dispose debugee's VM"); + + AbortingThread abortingThrd = new AbortingThread(); + abortingThrd.start(); + + debugee.VM().dispose(); + invokeThrd.waitVMDisconnect(); + + try { + invokeThrd.join(); + } catch(InterruptedException e) { + throw new Failure("unexpected " + e); + } + + if (isAborted) { + complain("Debugee's VM disposing hung. Invoking was aborted!!!"); + exitStatus = Consts.TEST_FAILED; + } else { + display("\nVirtual machine has been disposed"); + display("sending signal \"" + SGNL_FINISH + "\" to the invoked constructor"); + debugee.sendSignal(SGNL_FINISH); + } + + display("\n============="); + display("TEST FINISHES\n"); + } + + private BreakpointEvent waitForBreakpoint(BreakpointRequest brkp) { + Event event = null; + BreakpointEvent brkpEvent; + + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected " + e); + } + + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new Failure("BreakpointEvent didn't arrive"); + } + + brkpEvent = (BreakpointEvent )event; + return brkpEvent; + } + + private Method getConstructor(ReferenceType classType) { + List methodList = classType.methods(); + Method method; + for (int i = 0; i < methodList.size(); i++) { + method = (Method )methodList.get(i); + if (method.isConstructor()) { + return method; + } + } + return null; + } + + class InvokingThread extends Thread { + volatile boolean isNotified = false; + + public void run() { + display(""); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + newinstance008a.brkpMethodName, + newinstance008a.brkpLineNumber); + debugee.resume(); + + debugee.sendSignal(""); + + BreakpointEvent brkpEvent = waitForBreakpoint(brkp); + ThreadReference thread = brkpEvent.thread(); + + Value retValue; + List params = new Vector(); + + Method method = getConstructor(testedClass); + display("\nInvoking debugee's constructor : " + method); + + try { + retValue = testedClass.newInstance(thread, method, params, 0); + if ( ((PrimitiveValue )retValue).intValue() == Consts.TEST_FAILED ) { + complain("VMDisconnectException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch(VMDisconnectedException e) { + display("!!!expected VMDisconnectException"); + notifyVMDisconnect(); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + debugee.resume(); + } + + synchronized void notifyVMDisconnect() { + isNotified = true; + notify(); + } + + synchronized void waitVMDisconnect() { + try { + if (!isNotified) { + display("\nwaiting VMDisconnectedException"); + wait(waitTime); + } + } catch (InterruptedException e) { + throw new Failure("unexpected " + e); + } + } + } + + class AbortingThread extends Thread { + + public void run() { + try { + sleep(waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected " + e); + } + + display("\n!!!out of wait time!!!"); + display("sending signal \"" + SGNL_ABORT + "\" to the invoked method"); + isAborted = true; + debugee.sendSignal(SGNL_ABORT); + debugee.resume(); + debugee.quit(); + } + } +} + +class im008ListeningThread extends Thread { + public static Object waitDisconnecting = new Object(); + public volatile static boolean isNotified = false; + public void run() { + newinstance008.display(""); + newinstance008.display("waiting for signal \"" + + newinstance008.SGNL_READY + + "\" from the constructor"); + newinstance008.debugee.receiveExpectedSignal(newinstance008.SGNL_READY); + + newinstance008.display(""); + newinstance008.display("Virtual machine is disposed"); + newinstance008.debugee.VM().dispose(); + + try { + long startTime = System.currentTimeMillis(); + synchronized (waitDisconnecting) { + if (!isNotified) { + newinstance008.display(""); + newinstance008.display("waiting VMDisconnectedException"); + waitDisconnecting.wait(newinstance008.waitTime); + } else { + newinstance008.display("It doesn't wait VMDisconnectedException"); + } + } + if (System.currentTimeMillis() - startTime >= newinstance008.waitTime) { + newinstance008.complain("VMDisconnectedException is not thrown"); + newinstance008.exitStatus = Consts.TEST_FAILED; + } + } catch (InterruptedException e) { + newinstance008.complain("Unexpected InterruptedException"); + newinstance008.exitStatus = Consts.TEST_FAILED; + } + + newinstance008.display(""); + newinstance008.display("sending signal \"" + newinstance008.SGNL_QUIT + + "\" to the constructor"); + newinstance008.debugee.quit(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008/TestDescription.java new file mode 100644 index 00000000000..e4f5d6a48ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance008. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ClassType.newInstance() + * Test checks up the following assertion: + * If the target VM is disconnected during the invoke (for example, + * through VirtualMachine.dispose()) the method invocation continues. + * COMMENTS: + * The test was updated to avoid hanging of debugee's VM + * after invoking VirtualMachine.dispose(). + * (see 4471237 VirtualMachine.dispose() hangs on Windows) + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance008 + * nsk.jdi.ClassType.newInstance.newinstance008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008a.java new file mode 100644 index 00000000000..cf547790dc0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * newinstance008a is deugee's part of the newinstance008. + */ +public class newinstance008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 51; + private static Log log; + private static IOPipe pipe; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(newinstance008.SGNL_READY); + + String instr = pipe.readln(); + // the below line is a breakpoint. + // Debugger will invoke constructor newinstance008a(). + instr = pipe.readln(); // brkpLineNumber + if (instr.equals(newinstance008.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + newinstance008a() { + try { + pipe.println(newinstance008.SGNL_READY); + log.display("constructor:: waiting response from debugger..."); + String instr = pipe.readln(); + if (instr.equals(newinstance008.SGNL_FINISH)) { + log.display("constructor:: completed succesfully."); + } else if (instr.equals(newinstance008.SGNL_ABORT)) { + log.display("constructor:: aborted."); + } + } catch(Exception e) { + log.display("unexpected exception " + e); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009.java new file mode 100644 index 00000000000..36f24f05fed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ClassType.newInstance() + * properly throws IncompatibleThreadStateException - if the + * specified thread has not been suspended by an event.

    + * + * The test works as follows. Debugger part of the test attempts + * to construct a new instance of main debuggee class newinstance009t + * using thread newinstance009tThr being previously suspended + * by the JDI method ThreadReference.suspend() instead of by + * an event. The exception is expected to be thrown. + */ +public class newinstance009 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.newInstance.newinstance009t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "newinstance009tThr"; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int ATTEMPTS = 5; + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new newinstance009().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "newinstance009t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef = null; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + thrRef.suspend(); + while(!thrRef.isSuspended()) { + num++; + if (num > ATTEMPTS) { + log.complain("TEST FAILED: unable to suspend debuggee thread"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + log.display("Waiting for debuggee thread suspension ..."); + try { + Thread.currentThread().sleep(DELAY); + } catch(InterruptedException ie) { + ie.printStackTrace(); + log.complain("TEST FAILED: caught: " + ie); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + ClassType clsType = (ClassType) rType; + + List methList = rType.methodsByName(""); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected constructor " + + " not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + Method meth = (Method) methList.get(0); + if (!meth.isConstructor()) { + log.complain("TEST FAILURE: found method \"" + + meth.name() + " " + meth.signature() + + "\" is not a constructor: Method.isConstructor()=" + + meth.isConstructor()); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + // Check the tested assersion + try { + log.display("\n Trying to construct a new instance of debuggee class \"" + + clsType + "\"\n\tusing constructor \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\" and thread which has not been suspended by an event ..."); + + clsType.newInstance(thrRef, meth, Collections.emptyList(), 0); + + log.complain("TEST FAILED: expected IncompatibleThreadStateException was not thrown" + + "\n\twhen attempted to construct a new instance of debuggee class \"" + + clsType + "\"\n\tusing constructor \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\" and thread which has not been suspended by an event"); + tot_res = Consts.TEST_FAILED; + } catch (IncompatibleThreadStateException is) { + log.display("CHECK PASSED: caught expected " + is); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ClassType.newInstance(): caught unexpected " + + ee + "\n\tinstead of expected IncompatibleThreadStateException" + + "\n\twhen attempted to construct a new instance of debuggee class \"" + + clsType + "\"\n\tusing constructor \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\" and thread which has not been suspended by an event"); + tot_res = Consts.TEST_FAILED; + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private int quitDebuggee() { + log.display("\nFinal resumption of the debuggee VM"); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009/TestDescription.java new file mode 100644 index 00000000000..1822de400b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/newInstance/newinstance009. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ClassType.newInstance() + * properly throws IncompatibleThreadStateException - if the + * specified thread has not been suspended by an event. + * The test works as follows. Debugger part of the test attempts + * to construct a new instance of main debuggee class "newinstance009t" + * using thread "newinstance009tThr" being previously suspended + * by the JDI method "ThreadReference.suspend()" instead of by + * an event. The exception is expected to be thrown. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.newInstance.newinstance009 + * nsk.jdi.ClassType.newInstance.newinstance009t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.newInstance.newinstance009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009t.java new file mode 100644 index 00000000000..4169ef62e41 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance009t.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassType.newInstance; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is debuggee class. + */ +public class newinstance009t { + // constructor used only to check IncompatibleThreadStateException throwing + // in the debugger + newinstance009t() { + System.err.println("Debuggee: constructor of \"newinstance009t\" was invoked!"); + } + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new newinstance009t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Thread.currentThread().setName(newinstance009.DEBUGGEE_THRNAME); + + pipe.println(newinstance009.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(newinstance009.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001.java new file mode 100644 index 00000000000..50b922da99a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001.java @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.setValue()
    + * complies with its spec.
    + *
    + * The cases for testing include only the primitive types.
    + * After being started up,
    + * a debuggee creates a TestClass object containing fields of each of
    + * the primitive types, and informs a debugger of the object creation.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following for each of the primitive types:
    + * - gets corresponding Value objects using the method
    + * ReferenceType.getValue(Field field2),
    + * - sets corresponding Value objects using the method
    + * ReferenceType.getValue(Field field1),
    + * - gets corresponding Value objects using the method
    + * ReferenceType.getValue(Field field1),
    + * - checks up that field1 holds new value.
    + *
    + */ + +public class setvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/setValue/setvalue001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.setValue.setvalue001a"; + + String mName = "nsk.jdi.ClassType.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedclassName = mName + ".setvalue001aTestClass"; + + ReferenceType testedclass = null; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for setvalue001aTestClass"); + testedclass = (ReferenceType) classes.get(0); + + ClassType tClass = (ClassType) testedclass; + + + String bl1 = "bl1", bl2 = "bl2"; + String bt1 = "bt1", bt2 = "bt2"; + String ch1 = "ch1", ch2 = "ch2"; + String db1 = "db1", db2 = "db2"; + String fl1 = "fl1", fl2 = "fl2"; + String in1 = "in1", in2 = "in2"; + String ln1 = "ln1", ln2 = "ln2"; + String sh1 = "sh1", sh2 = "sh2"; + + Field field1 = null; + Field field2 = null; + + log2(" loop of testing all primitive types"); + for (int i3 = 0; i3 < 8; i3++) { + + try { + + switch (i3) { + + case 0: + log2("...... boolean values"); + BooleanValue blv1 = null; + BooleanValue blv2 = null; + + field1 = testedclass.fieldByName(bl1); + field2 = testedclass.fieldByName(bl2); + if (field1 == null || field2 == null) { + log3("ERROR: 'field1 == null || field2 == null' for Boolean"); + testExitCode = FAILED; + break; + } + + blv2 = (BooleanValue) testedclass.getValue(field2); + tClass.setValue(field1, blv2); + blv1 = (BooleanValue) testedclass.getValue(field1); + if (blv1.value() != false) { + log3("ERROR: blv1 != false : " + blv1.value() ); + testExitCode = FAILED; + } + + break; + + + case 1: + log2("...... byte values"); + ByteValue btv1 = null; + ByteValue btv2 = null; + + field1 = testedclass.fieldByName(bt1); + field2 = testedclass.fieldByName(bt2); + if (field1 == null || field2 == null) { + log3("ERROR: 'field1 == null || field2 == null' for Byte"); + testExitCode = FAILED; + break; + } + + btv2 = (ByteValue) testedclass.getValue(field2); + tClass.setValue(field1, btv2); + btv1 = (ByteValue) testedclass.getValue(field1); + if (btv1.value() != 1) { + log3("ERROR: btv1 != 1 : " + btv1.value() ); + testExitCode = FAILED; + } + + break; + + + case 2: + log2("...... char values"); + CharValue chv1 = null; + CharValue chv2 = null; + + field1 = testedclass.fieldByName(ch1); + field2 = testedclass.fieldByName(ch2); + if (field1 == null || field2 == null) { + log3("ERROR: 'field1 == null || field2 == null' for Char"); + testExitCode = FAILED; + break; + } + + chv2 = (CharValue) testedclass.getValue(field2); + tClass.setValue(field1, chv2); + chv1 = (CharValue) testedclass.getValue(field1); + if (chv1.value() != 1) { + log3("ERROR: chv1 != 1 : " + chv1.value() ); + testExitCode = FAILED; + } + + break; + + + case 3: + log2("...... double values"); + DoubleValue dbv1 = null; + DoubleValue dbv2 = null; + + field1 = testedclass.fieldByName(db1); + field2 = testedclass.fieldByName(db2); + if (field1 == null || field2 == null) { + log3("ERROR: 'field1 == null || field2 == null' for Double"); + testExitCode = FAILED; + break; + } + + dbv2 = (DoubleValue) testedclass.getValue(field2); +// log2("1 : dbv2 = " + Double.doubleToRawLongBits(dbv2.value()) ); + tClass.setValue(field1, dbv2); + dbv1 = (DoubleValue) testedclass.getValue(field1); +// log2("2 : dbv1 = " + Double.doubleToRawLongBits(dbv1.value()) ); + if (dbv1.value() != 1111111111.0d) { + log3("ERROR: dbv1 != 1111111111.0d : " + dbv1.value() ); + testExitCode = FAILED; + } + + break; + + + case 4: + log2("...... float values"); + FloatValue flv1 = null; + FloatValue flv2 = null; + + field1 = testedclass.fieldByName(fl1); + field2 = testedclass.fieldByName(fl2); + if (field1 == null || field2 == null) { + log3("ERROR: 'field1 == null || field2 == null' for Float"); + testExitCode = FAILED; + break; + } + + flv2 = (FloatValue) testedclass.getValue(field2); + tClass.setValue(field1, flv2); + flv1 = (FloatValue) testedclass.getValue(field1); + if (flv1.value() != 1111111111.0f) { + log3("ERROR: flv1 != 1111111111.0f : " + flv1.value() ); + testExitCode = FAILED; + } + + break; + + case 5: + log2("...... int values"); + IntegerValue inv1 = null; + IntegerValue inv2 = null; + + field1 = testedclass.fieldByName(in1); + field2 = testedclass.fieldByName(in2); + if (field1 == null || field2 == null) { + log3("ERROR: 'field1 == null || field2 == null' for Integer"); + testExitCode = FAILED; + break; + } + + inv2 = (IntegerValue) testedclass.getValue(field2); + tClass.setValue(field1, inv2); + inv1 = (IntegerValue) testedclass.getValue(field1); + if (inv1.value() != 1) { + log3("ERROR: inv1 != 1 : " + inv1.value() ); + testExitCode = FAILED; + } + + break; + + + case 6: + log2("...... long values"); + LongValue lnv1 = null; + LongValue lnv2 = null; + + field1 = testedclass.fieldByName(ln1); + field2 = testedclass.fieldByName(ln2); + if (field1 == null || field2 == null) { + log3("ERROR: 'field1 == null || field2 == null' for Long"); + testExitCode = FAILED; + break; + } + + lnv2 = (LongValue) testedclass.getValue(field2); + lnv1 = (LongValue) testedclass.getValue(field1); + tClass.setValue(field1, lnv2); + lnv1 = (LongValue) testedclass.getValue(field1); + if (lnv1.value() != 0x1234567890abcdefL) { + log3("ERROR: lnv1 != 0x1234567890abcdefL : " + + Long.toHexString(lnv1.value()) ); + testExitCode = FAILED; + } + + break; + + + case 7: + log2("...... short values"); + ShortValue shv1 = null; + ShortValue shv2 = null; + + field1 = testedclass.fieldByName(sh1); + field2 = testedclass.fieldByName(sh2); + if (field1 == null || field2 == null) { + log3("ERROR: 'field1 == null || field2 == null' for Short"); + testExitCode = FAILED; + break; + } + + shv2 = (ShortValue) testedclass.getValue(field2); + tClass.setValue(field1, shv2); + shv1 = (ShortValue) testedclass.getValue(field1); + if (shv1.value() != 1) { + log3("ERROR: shv1 != 1 : " + shv1.value() ); + testExitCode = FAILED; + } + + break; + + + default : log3("ERROR: TEST ERROR: case: default:"); + testExitCode = FAILED; + break; + + } // end of switch + + } catch ( Exception e ) { + log3("ERROR: unexpected Exception: " + e); + testExitCode = FAILED; + } // end of try + + } // end of for + + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001/TestDescription.java new file mode 100644 index 00000000000..c3b3a52186a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001/TestDescription.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/setValue/setvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.setValue() + * complies with its spec: + * public void setValue(Field field, Value value) + * throws InvalidTypeException, + * ClassNotLoadedException + * Assigns a value to a static field. + * The Field must be valid for this ObjectReference; that is, there must be + * a widening reference conversion from this object to the field's type. + * The field must not be final. + * Object values must be assignment compatible with the field type + * (This implies that the field type must be loaded through + * the enclosing class's class loader). + * Primitive values must be either assignment compatible with the field type + * or must be convertible to the field type without loss of information. + * See JLS section 5.2 for more information on assignment compatibility. + * Parameters: field - the field to set. + * value - the value to be assigned. + * Throws: IllegalArgumentException - + * if the field is not static, the field is final, or + * the field does not exist in this class. + * ClassNotLoadedException - + * if the field type has not yet been loaded through + * the appropriate class loader. + * InvalidTypeException - + * if the value's type does not match the field's declared type. + * ObjectCollectedException - + * if the given Value is an mirrors an object + * which has been garbage collected. + * Also thrown if this class has been unloaded and garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The cases for testing include only the primitive types + * when non of the Exceptions is expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.setValue.setvalue001; + * the debuggee program - nsk.jdi.ClassType.setValue.setvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.setValue.setvalue001 + * nsk.jdi.ClassType.setValue.setvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.setValue.setvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001a.java new file mode 100644 index 00000000000..16720a55973 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue001a.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the setvalue001 JDI test. + */ + +public class setvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static setvalue001aTestClass obj = new setvalue001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.setValue()
    + * complies with its spec.
    + * The test checks up on throwing IllegalArgumentException and
    + * InvalidTypeException.
    + *
    + * The cases for testing include the primitive types and the array type.
    + * After being started up,
    + * a debuggee creates a TestClass object containing fields of each of
    + * the primitive types and the array type,
    + * and informs a debugger of the object creation.
    + * Upon the receiption a message from the debuggee, the debugger
    + * gets the mirror of the object, ClassType tClass,
    + * and performs the following checks:
    + * - invoking the method
    + * tClass.setValue(Field field1, BooleanValue blv2)
    + * with non-static field1 throws IllegalArgumentException;

    + * - invoking the method
    + * tClass.setValue(Field field1, ByteValue btv2)
    + * with final field1 throws IllegalArgumentException;
    + * - invoking the method
    + * tClass.setValue(Field field1, IntegerValue inv2)
    + * with field1 mirroring an static field within another debuggee's
    + * class throws IllegalArgumentException;
    + * - invoking the method
    + * tClass.setValue(Field field1, ByteValue btv2)
    + * with field1 mirroring not a primitive but an array type
    + * throws InvalidTypeException.
    + *
    + */ + +public class setvalue002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/setValue/setvalue002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.setValue.setvalue002a"; + + String mName = "nsk.jdi.ClassType.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + String testedclassName = mName + ".setvalue002aTestClass"; + + ReferenceType testedclass = null; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for setvalue002aTestClass"); + testedclass = (ReferenceType) classes.get(0); + + ClassType tClass = (ClassType) testedclass; + + + ReferenceType debuggeeclass = null; + + log2(" getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + classes = vm.classesByName(debuggeeName); + size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + debuggeeclass = (ReferenceType) classes.get(0); + + ClassType dClass = (ClassType) debuggeeclass; + + + + + String bl1 = "bl1", bl2 = "bl2"; + String bt1 = "bt1", bt2 = "bt2"; + String ch1 = "ch1", ch2 = "ch2"; + String db1 = "db1", db2 = "db2"; + String fl1 = "fl1", fl2 = "fl2"; + String in1 = "in1", in2 = "in2"; + String ln1 = "ln1", ln2 = "ln2"; + String sh1 = "sh1", sh2 = "sh2"; + + Field field1 = null; + Field field2 = null; + + + + log2("...... checking up: not static field; IllegalArgumentException is expected"); + try { + BooleanValue blv1 = null; + BooleanValue blv2 = null; + + field1 = testedclass.fieldByName(bl1); + field2 = testedclass.fieldByName(bl2); + if (field1 == null || field2 == null) { + log3("ERROR: field1 == null || field2 == null"); + testExitCode = FAILED; + } else { + blv2 = (BooleanValue) testedclass.getValue(field2); + tClass.setValue(field1, blv2); + log3("ERROR: no IllegalArgumentException"); + testExitCode = FAILED; + } + } catch ( IllegalArgumentException e1 ) { + log2(" IllegalArgumentException"); + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception: " + e2); + testExitCode = FAILED; + } + + log2("...... checking up: final field; IllegalArgumentException is expected"); + try { + ByteValue btv1 = null; + ByteValue btv2 = null; + + field1 = testedclass.fieldByName(bt1); + field2 = testedclass.fieldByName(bt2); + if (field1 == null || field2 == null) { + log3("ERROR: field1 == null || field2 == null"); + testExitCode = FAILED; + } else { + btv2 = (ByteValue) testedclass.getValue(field2); + tClass.setValue(field1, btv2); + log3("ERROR: no IllegalArgumentException"); + testExitCode = FAILED; + } + } catch ( IllegalArgumentException e1 ) { + log2(" IllegalArgumentException"); + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception: " + e2); + testExitCode = FAILED; + } + + + log2("...... checking up: field doesn't exist in this class; IllegalArgumentException is expected"); + try { + IntegerValue inv1 = null; + IntegerValue inv2 = null; + + field1 = debuggeeclass.fieldByName(in1); + field2 = testedclass.fieldByName(in2); + if (field1 == null || field2 == null) { + log3("ERROR: field1 == null || field2 == null"); + testExitCode = FAILED; + } else { + inv2 = (IntegerValue) testedclass.getValue(field2); + tClass.setValue(field1, inv2); + log3("ERROR: no IllegalArgumentException"); + testExitCode = FAILED; + } + } catch ( IllegalArgumentException e1 ) { + log2(" IllegalArgumentException"); + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception: " + e2); + testExitCode = FAILED; + } + + + log2("...... checking up: no match the field's declared type; InvalidTypeException is expected"); + try { + ByteValue btv2 = null; + String bta = "bta"; + + field1 = testedclass.fieldByName(bta); + field2 = testedclass.fieldByName(bt2); + if (field1 == null || field2 == null) { + log3("ERROR: field1 == null || field2 == null"); + testExitCode = FAILED; + } else { + btv2 = (ByteValue) testedclass.getValue(field2); + tClass.setValue(field1, btv2); + log3("ERROR: no InvalidTypeException"); + testExitCode = FAILED; + } + } catch ( InvalidTypeException e1 ) { + log2(" InvalidTypeException"); + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception: " + e2); + testExitCode = FAILED; + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002/TestDescription.java new file mode 100644 index 00000000000..43e213d08ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002/TestDescription.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/setValue/setvalue002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.setValue() + * complies with its spec: + * public void setValue(Field field, Value value) + * throws InvalidTypeException, + * ClassNotLoadedException + * Assigns a value to a static field. + * The Field must be valid for this ObjectReference; that is, there must be + * a widening reference conversion from this object to the field's type. + * The field must not be final. + * Object values must be assignment compatible with the field type + * (This implies that the field type must be loaded through + * the enclosing class's class loader). + * Primitive values must be either assignment compatible with the field type + * or must be convertible to the field type without loss of information. + * See JLS section 5.2 for more information on assignment compatibility. + * Parameters: field - the field to set. + * value - the value to be assigned. + * Throws: IllegalArgumentException - + * if the field is not static, the field is final, or + * the field does not exist in this class. + * ClassNotLoadedException - + * if the field type has not yet been loaded through + * the appropriate class loader. + * InvalidTypeException - + * if the value's type does not match the field's declared type. + * ObjectCollectedException - + * if the given Value is an mirrors an object + * which has been garbage collected. + * Also thrown if this class has been unloaded and garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The cases for testing include throwing both IllegalArgumentException and + * InvalidTypeException. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.setValue.setvalue002; + * the debuggee program - nsk.jdi.ClassType.setValue.setvalue002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.setValue.setvalue002 + * nsk.jdi.ClassType.setValue.setvalue002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.setValue.setvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002a.java new file mode 100644 index 00000000000..2955ab331bf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue002a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the setvalue002 JDI test. + */ + +public class setvalue002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static setvalue002aTestClass obj = new setvalue002aTestClass(); + + static int in1; + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.setValue()
    + * complies with its spec in case when
    + * no Exception is expected to be thrown.
    + * The test makes checking up on ReferenceTypes only.
    + *
    + * After being started up, a debuggee creates ReferenceType objects for
    + * testing and informs a debugger of the creation.
    + * Upon the receiption a message from the debuggee, the debugger
    + * gets ReferenceType debuggeeclass and ClassType dClass objects and
    + * checks up that for Fields field1 and field2 the following sequence
    + * Value val1 = debuggeeclass.getValue(field1);
    + * dClass.setValue(field2, val1);
    + * Value val2 = debuggeeclass.getValue(field2);
    + * results in: val1.equals(val2)
    + * for the following tested ReferenceType objects
    + * ClassType
    + * InterfaceType
    + * ClassArray
    + * InterfaceArray
    + * PrimitiveArray
    + *
    + */ + +public class setvalue003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/setValue/setvalue003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.setValue.setvalue003a"; + + String mName = "nsk.jdi.ClassType.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + List classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeclass = (ReferenceType) classes.get(0); + + ClassType dClass = (ClassType) debuggeeclass; + + + String names[][] = { { "class1", "class2" }, + { "class3", "class4" }, + { "iface1", "iface2" }, + { "iface3", "iface4" }, + { "array1", "array2" } }; + + Field field1 = null; + Field field2 = null; + + log2(" checking up variables of ReferenceTypes"); + + for (int i2 = 0; i2 < 5; i2++) { + try { + field1 = debuggeeclass.fieldByName(names[i2][0]); + field2 = debuggeeclass.fieldByName(names[i2][1]); + log2(" : tested type: " + field1.typeName()); + log2(" : tested variables: " + names[i2][0] + " " + names[i2][1]); + if (field1 != null && field2 != null) { + Value val1 = debuggeeclass.getValue(field1); + dClass.setValue(field2, val1); + Value val2 = debuggeeclass.getValue(field2); + if ( !val1.equals(val2)) { + log3("ERROR: !val1.equals(val2)"); + testExitCode = FAILED; + } + } else { + log3("ERROR: field1 != null && field2 != null"); + testExitCode = FAILED; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003/TestDescription.java new file mode 100644 index 00000000000..b6c0fdb4ed5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003/TestDescription.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/setValue/setvalue003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.setValue() + * complies with its spec: + * public void setValue(Field field, Value value) + * throws InvalidTypeException, + * ClassNotLoadedException + * Assigns a value to a static field. + * The Field must be valid for this ObjectReference; that is, there must be + * a widening reference conversion from this object to the field's type. + * The field must not be final. + * Object values must be assignment compatible with the field type + * (This implies that the field type must be loaded through + * the enclosing class's class loader). + * Primitive values must be either assignment compatible with the field type + * or must be convertible to the field type without loss of information. + * See JLS section 5.2 for more information on assignment compatibility. + * Parameters: field - the field to set. + * value - the value to be assigned. + * Throws: IllegalArgumentException - + * if the field is not static, the field is final, or + * the field does not exist in this class. + * ClassNotLoadedException - + * if the field type has not yet been loaded through + * the appropriate class loader. + * InvalidTypeException - + * if the value's type does not match the field's declared type. + * ObjectCollectedException - + * if the given Value is an mirrors an object + * which has been garbage collected. + * Also thrown if this class has been unloaded and garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The cases for testing include ReferenceTypes. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.setValue.setvalue003; + * the debuggee program - nsk.jdi.ClassType.setValue.setvalue003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.setValue.setvalue003 + * nsk.jdi.ClassType.setValue.setvalue003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.setValue.setvalue003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003a.java new file mode 100644 index 00000000000..d92d3eaab2f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue003a.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the setvalue003 JDI test. + */ + +public class setvalue003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + // case 0 + static setvalue003aClassForCheck_2 class1[] = { new setvalue003aClassForCheck_2() }; + static setvalue003aClassForCheck_2 class2[] = null; + static setvalue003aInterfaceForCheck iface1[] = {new setvalue003aClassForCheck_2()}; + static setvalue003aInterfaceForCheck iface2[] = null; + + // case 1 + static setvalue003aClassForCheck_2 class3 = new setvalue003aClassForCheck_2(); + static setvalue003aClassForCheck_2 class4 = null; + static setvalue003aInterfaceForCheck iface3 = new setvalue003aClassForCheck_2(); + static setvalue003aInterfaceForCheck iface4 = null; + + // case 2 + static boolean array1[][] = {{true,false}, {false,true} }; + static boolean array2[][] = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.setValue()
    + * complies with its spec.
    + * The test checks up throwing InvalidTypeException
    + *
    + * After being started up, a debuggee creates all the primitive type
    + * objects and one of the Object type,
    + * and informs a debugger of the creation.
    + * Upon the receiption a message from the debuggee, the debugger
    + * checks up that for each in primitive types
    + * (1) setValue(primitivetype variable, null) does throw whereas
    + * (2) setValue(Object variable, null); does not throw
    + * InvalidTypeException
    + *
    + */ + +public class setvalue004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/setValue/setvalue004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue004().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.display(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.setValue.setvalue004a"; + + String mName = "nsk.jdi.ClassType.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + List classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeclass = (ReferenceType) classes.get(0); + + ClassType dClass = (ClassType) debuggeeclass; + + Field field1 = null; + Field field2 = null; + + + String names[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1" }; + + log2(" checking up on exception for: setValue(primitivetype variable, null);"); + for ( int i2 = 0; i2 < 8; i2++ ) { + + try { + field1 = debuggeeclass.fieldByName(names[i2]); + log2(" checking up on exception for: Field of " + field1.typeName() + " type"); + dClass.setValue(field1, null); + log3("ERROR: no Exception"); + testExitCode = FAILED; + } catch ( java.lang.IllegalArgumentException e1 ) { + log3("ERROR: java.lang.IllegalArgumentException "); + testExitCode = FAILED; + } catch ( InvalidTypeException e2 ) { + log2(" : InvalidTypeException "); + } catch ( ClassNotLoadedException e3 ) { + log3("ERROR: ClassNotLoadedException "); + testExitCode = FAILED; + } catch ( VMMismatchException e4 ) { + log3("ERROR: VMMismatchException "); + testExitCode = FAILED; + } catch ( ObjectCollectedException e5 ) { + log3("ERROR: ObjectCollectedException "); + testExitCode = FAILED; + } catch ( Exception e6 ) { + log3("ERROR: UNSPECIFIED EXCEPTION: " + e6); + testExitCode = FAILED; + } + } + + + String name = "testObj"; + + log2(" checking up on exception for: setValue(Object variable, null);"); + try { + field1 = debuggeeclass.fieldByName(name); + if (field1 != null) { + dClass.setValue(field1, null); + log2(" : no Exception"); + } else { + log3("ERROR: field1 == null after: field1 = debuggeeclass.fieldByName(name);"); + testExitCode = FAILED; + } + } catch ( java.lang.IllegalArgumentException e1 ) { + log3("ERROR: java.lang.IllegalArgumentException "); + testExitCode = FAILED; + } catch ( InvalidTypeException e2 ) { + log3("ERROR: InvalidTypeException "); + testExitCode = FAILED; + } catch ( ClassNotLoadedException e3 ) { + log3("ERROR: ClassNotLoadedException "); + testExitCode = FAILED; + } catch ( ObjectCollectedException e4 ) { + log3("ERROR: ObjectCollectedException "); + testExitCode = FAILED; + } catch ( VMMismatchException e5 ) { + log3("ERROR: VMMismatchException "); + testExitCode = FAILED; + } catch ( Exception e6 ) { + log3("ERROR: UNSPECIFIED EXCEPTION: " + e6); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004/TestDescription.java new file mode 100644 index 00000000000..88f6692fb89 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004/TestDescription.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/setValue/setvalue004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.setValue() + * complies with its spec: + * public void setValue(Field field, Value value) + * throws InvalidTypeException, + * ClassNotLoadedException + * Assigns a value to a static field. + * The Field must be valid for this ObjectReference; that is, there must be + * a widening reference conversion from this object to the field's type. + * The field must not be final. + * Object values must be assignment compatible with the field type + * (This implies that the field type must be loaded through + * the enclosing class's class loader). + * Primitive values must be either assignment compatible with the field type + * or must be convertible to the field type without loss of information. + * See JLS section 5.2 for more information on assignment compatibility. + * Parameters: field - the field to set. + * value - the value to be assigned. + * Throws: IllegalArgumentException - + * if the field is not static, the field is final, or + * the field does not exist in this class. + * ClassNotLoadedException - + * if the field type has not yet been loaded through + * the appropriate class loader. + * InvalidTypeException - + * if the value's type does not match the field's declared type. + * ObjectCollectedException - + * if the given Value is an mirrors an object + * which has been garbage collected. + * Also thrown if this class has been unloaded and garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The case for testing includes checking up on assigning null to + * both PrimitiveType and ReferenceType obects. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.setValue.setvalue004; + * the debuggee program - nsk.jdi.ClassType.setValue.setvalue004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.setValue.setvalue004 + * nsk.jdi.ClassType.setValue.setvalue004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.setValue.setvalue004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004a.java new file mode 100644 index 00000000000..f8d09cf2b5a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue004a.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the setvalue004 JDI test. + */ + +public class setvalue004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static Object testObj = new Object(); + + static boolean bl1 = true, bl2 = false; + static byte bt1 = 0, bt2 = 1; + static char ch1 = 0, ch2 = 1; + static double db1 = 0.0d, db2 = 1.0d; + static float fl1 = 0.0f, fl2 = 1.0f; + static int in1 = 0, in2 = 1; + static long ln1 = 0, ln2 = 1; + static short sh1 = 0, sh2 = 1; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.setValue()
    + * complies with its spec.
    + * The test checks up on throwing IllegalArgumentException
    + * for the method invocation setValue(null, Value value);
    + *
    + * After being started up, a debuggee creates an value used in the test
    + * and informs a debugger of the creation.
    + * Upon the receiption a message from the debuggee, the debugger
    + * checks up that the call setValue.(null, ByteValue byteValue);
    + * throws IllegalArgumentException.
    + *
    + */ + +public class setvalue005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/setValue/setvalue005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue005().runThis(argv, out); + } + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.display(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.setValue.setvalue005a"; + + String mName = "nsk.jdi.ClassType.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + List classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeclass = (ReferenceType) classes.get(0); + + ClassType dClass = (ClassType) debuggeeclass; + + Field field1 = null; + Field field2 = null; + + String bt1 = "bt1"; + + + label1: { + try { + field1 = dClass.fieldByName(bt1); + if (field1 == null) { + log3("ERROR: field1 == null after: field1 = dClass.fieldByName('bt1');"); + testExitCode = FAILED; + break label1; + } + ByteValue byteValue = (ByteValue) debuggeeclass.getValue(field1); + if (byteValue == null) { + log3("ERROR: byteValue == null after: byteValue = (ByteValue) debuggeeclass.getValue(field1);"); + testExitCode = FAILED; + break label1; + } + + log2("......call: dClass.setValue(null, byteValue); IllegalArgumentException expected"); + dClass.setValue(null, byteValue); + log2("ERROR: no any Exception "); + testExitCode = FAILED; + } catch ( IllegalArgumentException e1 ) { + log2(" : IllegalArgumentException "); + } catch ( InvalidTypeException e2 ) { + log3("ERROR: InvalidTypeException "); + testExitCode = FAILED; + } catch ( ClassNotLoadedException e3 ) { + log3("ERROR: ClassNotLoadedException "); + testExitCode = FAILED; + } catch ( ObjectCollectedException e4 ) { + log3("ERROR: ObjectCollectedException "); + testExitCode = FAILED; + } catch ( VMMismatchException e5 ) { + log3("ERROR: VMMismatchException "); + testExitCode = FAILED; + } catch ( Exception e6 ) { + log3("ERROR: UNSPECIFIED EXCEPTION: " + e6); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005/TestDescription.java new file mode 100644 index 00000000000..0ab6555cdc6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005/TestDescription.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/setValue/setvalue005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.setValue() + * complies with its spec: + * public void setValue(Field field, Value value) + * throws InvalidTypeException, + * ClassNotLoadedException + * Assigns a value to a static field. + * The Field must be valid for this ObjectReference; that is, there must be + * a widening reference conversion from this object to the field's type. + * The field must not be final. + * Object values must be assignment compatible with the field type + * (This implies that the field type must be loaded through + * the enclosing class's class loader). + * Primitive values must be either assignment compatible with the field type + * or must be convertible to the field type without loss of information. + * See JLS section 5.2 for more information on assignment compatibility. + * Parameters: field - the field to set. + * value - the value to be assigned. + * Throws: IllegalArgumentException - + * if the field is not static, the field is final, or + * the field does not exist in this class. + * ClassNotLoadedException - + * if the field type has not yet been loaded through + * the appropriate class loader. + * InvalidTypeException - + * if the value's type does not match the field's declared type. + * ObjectCollectedException - + * if the given Value is an mirrors an object + * which has been garbage collected. + * Also thrown if this class has been unloaded and garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.setValue.setvalue005; + * the debuggee program - nsk.jdi.ClassType.setValue.setvalue005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.setValue.setvalue005 + * nsk.jdi.ClassType.setValue.setvalue005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.setValue.setvalue005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005a.java new file mode 100644 index 00000000000..29ac1330d49 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue005a.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the setvalue005 JDI test. + */ + +public class setvalue005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + Object testObj = new Object(); + boolean bl1 = true, bl2 = false; + byte bt1 = 0, bt2 = 1; + char ch1 = 0, ch2 = 1; + double db1 = 0.0d, db2 = 1.0d; + float fl1 = 0.0f, fl2 = 1.0f; + int in1 = 0, in2 = 1; + long ln1 = 0, ln2 = 1; + short sh1 = 0, sh2 = 1; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.ClassType.setValue()
    + * does not throw ClassNotLoadedException - when a debugger + * part of the test attempts to set null value to the debuggee field + * which field type has not yet been loaded through the appropriate + * class loader.

    + * + * The test works as follows. The debuggee part has two static + * fields: dummySFld of non-loaded type setvalue006tDummyType and + * finDummySFld of non-loaded type setvalue006tFinDummyType. + * Debugger part tries to provoke the exception by setting null values to + * these fields. The test makes sure that appropriate class has not + * been loaded by the debuggee VM through the JDI method + * VirtualMachine.classesByName() which should return matching + * list of loaded classes only. + */ +public class setvalue006 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.setValue.setvalue006t"; + + // tested static fields in debuggee class and theirs types + static final int FLD_NUM = 2; + static final String DEBUGGEE_FLDS[][] = { + {"dummySFld", "nsk.jdi.ClassType.setValue.setvalue006tDummyType"}, + {"finDummySFld", "nsk.jdi.ClassType.setValue.setvalue006tFinDummyType"} + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setvalue006().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "setvalue006t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + ClassType clsType = (ClassType) rType; + + for (int i=0; i + * com.sun.jdi.ClassType.setValue()
    + * properly throws InvalidTypeException - if + * the value's type does not match type of the specified field.

    + * + * Debugger part of the test tries to provoke the exception by setting + * values of static fields of different primitive types and own setvalue007tDummyType + * which are not assignment compatible with the field type, and not + * convertible without loss of information as well. + */ +public class setvalue007 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ClassType.setValue.setvalue007t"; + + static final int FLD_NUM = 30; + static final String DEBUGGEE_FLDS[][] = { + // list of debuggee static fields used to set values and ones + // used to get their wrong non-conversionable values, + // see section "5.1.2 Widening Primitive Conversion" in the JLS + {"dummySFld", "doubleSFld"}, + {"byteSFld", "strSFld"}, + {"byteSFld", "shortSFld"}, + {"byteSFld", "intSFld"}, + {"byteSFld", "longSFld"}, + {"byteSFld", "floatSFld"}, + {"byteSFld", "doubleSFld"}, + {"shortSFld", "intSFld"}, + {"shortSFld", "longSFld"}, + {"shortSFld", "floatSFld"}, + {"shortSFld", "doubleSFld"}, + {"intSFld", "longSFld"}, + {"intSFld", "floatSFld"}, + {"intSFld", "doubleSFld"}, + {"longSFld", "floatSFld"}, + {"longSFld", "doubleSFld"}, + {"floatSFld", "doubleSFld"}, + {"doubleSFld", "dummySFld"}, + {"charSFld", "strSFld"}, + {"booleanSFld", "byteSFld"}, + {"strSFld", "charSFld"}, + // see section "5.1.1 Identity Conversions" in the JLS: + // "the only permitted conversion that involves the type boolean is + // the identity conversion from boolean to boolean" + {"byteSFld", "booleanSFld"}, + {"shortSFld", "booleanSFld"}, + {"intSFld", "booleanSFld"}, + {"longSFld", "booleanSFld"}, + {"floatSFld", "booleanSFld"}, + {"doubleSFld", "booleanSFld"}, + {"charSFld", "booleanSFld"}, + {"strSFld", "booleanSFld"}, + {"dummySFld", "booleanSFld"} + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setvalue007().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "setvalue007t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + ClassType clsType = (ClassType) rType; + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + check(); + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check () { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(expectedFieldName).type(); + String className = checkedClass.name(); + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + Field foundField = checkedClass.fieldByName(expectedEnumFieldsNames[i]); + try { + checkedClass.setValue(foundField, null); + complain("Expected IllegalArgumentException was not thrown while trying to set null value for " + foundField.name()); + exitStatus = Consts.TEST_FAILED; + } catch (Exception e) { + if (e instanceof IllegalArgumentException) { + display("Expected IllegalArgumentException was thrown while trying to set null value for " + foundField.name()); + } else { + complain("Unexpected exception while trying to set null value for " + foundField.name() + ": " + e); + exitStatus = Consts.TEST_FAILED; + } + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008/TestDescription.java new file mode 100644 index 00000000000..ef1c89f1dc4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/setValue/setvalue008. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for setValue() method of ClassType interface. + * The test checks if the method throws IllegalArgumentException + * if trying to set new value for anym enum constant field of enum + * type because the field is implicitly final. + * The test consists of a debugger program (setvalue008.java) + * and debuggee application (setvalue008a.java). + * Package name is nsk.jdi.ClassType.setValue . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger finds mirrors enum type and its enum constant fields. + * Then the debugger to set value of these fields to null and + * expects the IllegalArgumentException to be thrown. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.setValue.setvalue008 + * nsk.jdi.ClassType.setValue.setvalue008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.setValue.setvalue008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008a.java new file mode 100644 index 00000000000..db9e6f7b20c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/setValue/setvalue008a.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class setvalue008a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static setvalue008Enum1 f1 = setvalue008Enum1.e2; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(setvalue008.SIGNAL_READY); + + + //pipe.println(setvalue008.SIGNAL_GO); + receiveSignal(setvalue008.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum setvalue008Enum1 { + e1, e2; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001.java new file mode 100644 index 00000000000..6533880fec6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001.java @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.subclasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.subclasses()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * 1) Class2 extends Class1
    + * hence Class1 has only one subclass
    + * 2) Class3 and Class4 extend Class2
    + * hence Class2 has two subclasses
    + * 3) Class3 has no subclasses
    + *
    + */ + +public class subclasses001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/subclasses/subclasses001", + sHeader2 = "--> subclasses001: ", + sHeader3 = "##> subclasses001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new subclasses001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.subclasses.subclasses001a"; + + String mName = "nsk.jdi.ClassType.subclasses"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("subclasses001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType classRefType = null; + List l = null; + String name = null; + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // Class2 extends Class1 + + List list1 = vm.classesByName(mName + ".Class1ForCheck"); + classRefType = (ReferenceType) list1.get(0); + List subClass1list = ((ClassType) classRefType).subclasses(); + + if (subClass1list.size() != 1) { + log3("ERROR : subClass1list.size() != 1 in case: Class2 extends Class1"); + expresult = 1; + break; + } + + ClassType classType2 = + (ClassType) (ReferenceType) subClass1list.get(0); + name = classType2.name(); + if (!name.equals(mName + ".Class2ForCheck")) { + log3("ERROR : !name.equals('.Class2..' in Class2 extends Class1"); + expresult = 1; + break; + } + + break; + + case 1: // Class3, Class4 extend Class2 + + List list2 = vm.classesByName(mName + ".Class2ForCheck"); + classRefType = (ReferenceType) list2.get(0); + List subClass2list = ((ClassType) classRefType).subclasses(); + + if (subClass2list.size() != 2) { + log3("ERROR : subClass2list.size() != 2 in case: Classes 3,4 extend Class2"); + expresult = 1; + break; + } + + ClassType classType3 = + (ClassType) (ReferenceType) subClass2list.get(0); + name = classType3.name(); + if (!name.equals(mName + ".Class3ForCheck")) { + if (!name.equals(mName + ".Class4ForCheck")) { + log3("ERROR : !name.equals('.Class3..' or '.Class4..' in Class3,4 extends Class2"); + expresult = 1; + break; + } + } + classType3 = + (ClassType) (ReferenceType) subClass2list.get(1); + name = classType3.name(); + if (!name.equals(mName + ".Class4ForCheck")) { + if (!name.equals(mName + ".Class3ForCheck")) { + log3("ERROR : !name.equals('.Class4..' or '.Class3..' in Class3,4 extends Class2"); + expresult = 1; + break; + } + } + + break; + + case 2: // Class3 + + List list3 = vm.classesByName(mName + ".Class3ForCheck"); + classRefType = (ReferenceType) list3.get(0); + List subClass3list = ((ClassType) classRefType).subclasses(); + + if (subClass3list.size() != 0) { + log3("ERROR : subClass1list.size() != 0 in case: Class3"); + expresult = 1; + break; + } + + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001/TestDescription.java new file mode 100644 index 00000000000..b362cbe3e31 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/subclasses/subclasses001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.subclasses() + * complies with its spec: + * public java.util.List subclasses() + * Gets the currently loaded, direct subclasses of this class. + * No ordering of this list is guaranteed. + * Returns: a List of ClassType objects each mirroring a loaded subclass + * of this class in the target VM. If no such classes exist, + * this method returns a zero-length list. + * Throws: ObjectCollectedException - + * if this class has been unloaded and garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.subclasses.subclasses001; + * the debuggee program - nsk.jdi.ClassType.subclasses.subclasses001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.subclasses.subclasses001 + * nsk.jdi.ClassType.subclasses.subclasses001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.subclasses.subclasses001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001a.java new file mode 100644 index 00000000000..d5851b34a24 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses001a.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.subclasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the subclasses001 JDI test. + */ + +public class subclasses001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> subclasses001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> subclasses001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + List subclasses = checkedClass.subclasses(); + if (subclasses.size() != 2) { + complain("Size of the list returned by ClassType.subclasses() for " + className + " is not equal 2"); + exitStatus = Consts.TEST_FAILED; + } + Iterator it = checkedClass.subclasses().iterator(); + while (it.hasNext()) { + String subclName = it.next().name(); + if (subclName.indexOf(className) >= 0) { + display(className + " has expected subclass " + subclName); + } else { + complain(className + " has unexpected subclass " + subclName); + exitStatus = Consts.TEST_FAILED; + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002/TestDescription.java new file mode 100644 index 00000000000..bc7383824c7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/subclasses/subclasses002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for subclasses() method of ClassType interface. + * The test checks if the method returns correct list of subclasses + * for any mirrored enum type if it has declared enum constant's + * specific class bodies. + * The test consists of a debugger program (subclasses002.java) + * and debuggee application (subclasses002a.java). + * Package name is nsk.jdi.ClassType.subclasses . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls subclasses() method for two fields + * of enum type declared in fields006a class. + * Each othis enum types has declared enum constant's specific class + * bodies. The test fails if the method returned list of wrong size + * or if any member of the list is not inner class of corresponded + * enum type. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.subclasses.subclasses002 + * nsk.jdi.ClassType.subclasses.subclasses002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.subclasses.subclasses002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002a.java new file mode 100644 index 00000000000..a1fe8bf103e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/subclasses/subclasses002a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.subclasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class subclasses002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static subclasses002Enum1 f1 = subclasses002Enum1.e1; + static subclasses002Enum2 f2 = subclasses002Enum2.e2; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(subclasses002.SIGNAL_READY); + receiveSignal(subclasses002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum subclasses002Enum1 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} + +enum subclasses002Enum2 implements subclasses002i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); +} + +interface subclasses002i { + int i = 1; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001.java new file mode 100644 index 00000000000..d94f8d387a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001.java @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.superclass; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ClassType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ClassType.superclass()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * 1) Class2 extends Class1
    + * hence Class1 is superclass of Class2
    + * 2) Class2 extends Class1
    + * Class3 extends Class2
    + * hence Class2 is superclass of Class3
    + * 3) Class1
    + * hence Object is superclass of Class1
    + *
    + */ + +public class superclass001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ClassType/superclass/superclass001", + sHeader2 = "--> superclass001: ", + sHeader3 = "##> superclass001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new superclass001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ClassType.superclass.superclass001a"; + + String mName = "nsk.jdi.ClassType.superclass"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("superclass001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List list1 = vm.classesByName(mName + ".Class1ForCheck"); + List list2 = vm.classesByName(mName + ".Class2ForCheck"); + List list3 = vm.classesByName(mName + ".Class3ForCheck"); + + ClassType superclass0 = null; + ClassType superclass1 = null; + ClassType superclass2 = null; + + ReferenceType classRefType = null; + + String name = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // Class2 extends Class1 + + classRefType = (ReferenceType) list2.get(0); + superclass1 = ((ClassType) classRefType).superclass(); + + if (superclass1 == null) { + log3("ERROR : superclass1 == null in case: Class2 extends Class1"); + expresult = 1; + break; + } + + name = superclass1.name(); + if (!name.equals(mName + ".Class1ForCheck")) { + log3("ERROR : name != 'Class1ForCheck' in Class2 extends Class1"); + expresult = 1; + break; + } + + break; + + case 1: // Class3 extends Class2 + + classRefType = (ReferenceType) list3.get(0); + superclass2 = ((ClassType) classRefType).superclass(); + + if (superclass2 == null) { + log3("ERROR : superclass2 == null in case: Class3 extends Class2"); + expresult = 1; + break; + } + + name = superclass2.name(); + if (!name.equals(mName + ".Class2ForCheck")) { + log3("ERROR : name != 'Class2ForCheck' in Class3 extends Class2"); + expresult = 1; + break; + } + + break; + + case 2: // Class1 + + classRefType = (ReferenceType) list1.get(0); + + superclass0 = ((ClassType) classRefType).superclass(); + + if (superclass0 == null) { + log3("ERROR : superclass2 == null in case: Class1"); + expresult = 1; + break; + } + + name = superclass0.name(); + if (!name.equals("java.lang.Object")) { + log3("ERROR : name != 'java.lang.Object' in Class1"); + expresult = 1; + break; + } + + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001/TestDescription.java new file mode 100644 index 00000000000..03a2f8db689 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/superclass/superclass001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ClassType. + * The test checks up that a result of the method + * com.sun.jdi.ClassType.superclass() + * complies with its scec: + * public ClassType superclass() + * Gets the superclass of this class. + * Returns: a ClassType that mirrors the superclass of this class in + * the target VM. If no such class exists, returns null + * Throws: ObjectCollectedException - + * if this class has been unloaded and garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.ClassType.superclass001; + * the debuggee program - nsk.jdi.ClassType.superclass001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.superclass.superclass001 + * nsk.jdi.ClassType.superclass.superclass001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.superclass.superclass001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001a.java new file mode 100644 index 00000000000..7b3008028e5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass001a.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassType.superclass; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the superclass001 JDI test. + */ + +public class superclass001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> superclass001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> superclass001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + if (checkedClass.superclass().name().equals("java.lang.Enum")) { + display("ClassType.superclass() returned expected java.lang.Enum for type: " + className); + } else { + complain("ClassType.superclass() returned unexpected type: " + checkedClass.superclass().name()); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002/TestDescription.java new file mode 100644 index 00000000000..85427089149 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassType/superclass/superclass002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for superclass() method of ClassType interface. + * The test checks if the method returns java.lang.Enum reference + * for any mirrored enum type + * The test consists of a debugger program (superclass002.java) + * and debuggee application (superclass002a.java). + * Package name is nsk.jdi.ClassType.superclass . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls superclass() method for each field + * of enum type declared in fields006a class. + * The test fails if the method returned type name other + * than "java.lang.Enum". + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassType.superclass.superclass002 + * nsk.jdi.ClassType.superclass.superclass002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassType.superclass.superclass002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002a.java new file mode 100644 index 00000000000..efa69e88911 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/superclass/superclass002a.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ClassType.superclass; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class superclass002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum2 f2 = Enum2.e2; + static Enum3 f3 = Enum3.e1; + static Enum4.Enum4_ f4 = Enum4.Enum4_.e1; + static superclass002Enum5 f5 = superclass002Enum5.e2; + static superclass002Enum6 f6 = superclass002Enum6.e1; + static superclass002Enum7 f7 = superclass002Enum7.e2; + static superclass002Enum8.Enum8_ f8 = superclass002Enum8.Enum8_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(superclass002.SIGNAL_READY); + + + //pipe.println(superclass002.SIGNAL_GO); + receiveSignal(superclass002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + enum Enum1 { + e1, e2; + } + + enum Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); + } + + enum Enum3 implements superclass002i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); + } + + enum Enum4 { + e1, e2; + + enum Enum4_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum superclass002Enum5 { + e1, e2; +} + +enum superclass002Enum6 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} + +enum superclass002Enum7 implements superclass002i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); +} + +enum superclass002Enum8 { + e1, e2; + enum Enum8_ { + e1, e2; + } +} + +interface superclass002i { + int i = 1; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001.java new file mode 100644 index 00000000000..77ef71d304f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001.java @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassUnloadEvent.className; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger application in the test + +public class classname001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_LOAD = "load"; + static final String COMMAND_LOADED = "loaded"; + static final String COMMAND_UNLOAD = "unload"; + static final String COMMAND_UNLOADED = "unloaded"; + + static final String PREFIX = "nsk.jdi.ClassUnloadEvent.className"; + static final String DEBUGGEE_NAME = PREFIX + ".classname001a"; + static final String CHECKED_CLASS = PREFIX + ".classname001b"; + static final String KLASSLOADER = ClassUnloader.INTERNAL_CLASS_LOADER_NAME; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private ClassUnloadRequest checkedRequest; + + static private long eventTimeout; + static private boolean testFailed; + static private boolean eventReceived; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debugee + + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "classname001a >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // create request and wait for ClassUnloadEvent + + try { + + // resume debugee and wait for it becomes ready + log.display("Resuming debuggee"); + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (command == null || !command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirror of debugee class + ReferenceType rType; + if ((rType = debuggee.classByName(DEBUGGEE_NAME)) == null) { + throw new Failure("TEST BUG: cannot find debuggee's class " + DEBUGGEE_NAME); + } + + // send command to load checked class and waits for a confirmation + pipe.println(COMMAND_LOAD); + log.display("Waiting for checked class is loaded"); + command = pipe.readln(); + + if (command == null || !command.equals(COMMAND_LOADED)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // checked class has been loaded! + log.display("Checked class has been loaded in debuggee!"); + + // check that checked class is loaded in debugee + log.display("Finding checked class in debuggee"); + if ((rType = debuggee.classByName(CHECKED_CLASS)) == null) { + throw new Failure("TEST BUG: cannot find checked class loaded: " + CHECKED_CLASS); + } + rType = null; + + // check that user-defined classloader is also loaded in debuggee + log.display("Finding user-defined class loader in debuggee"); + if ((rType = debuggee.classByName(KLASSLOADER)) == null) { + throw new Failure("TEST BUG: cannot find user-defined classloader loaded: " + KLASSLOADER); + } + rType = null; + + // create request for class unload event + log.display("Creating request for ClassUnloadEvent"); + EventRequestManager erManager = vm.eventRequestManager(); + if ((checkedRequest = erManager.createClassUnloadRequest()) == null) { + throw new Failure("TEST BUG: unable to create ClassUnloadRequest"); + } else { + log.display("ClassUnloadRequest created"); + } +// checkedRequest.addClassFilter("nsk.jdi.ClassUnloadEvent.className.*"); + + // enable event request + log.display("Enabling event request"); + checkedRequest.enable(); + + // turn off pipe pinging + pipe.setPingTimeout(0); + + // force checked class to be unloaded from debuggee + log.display("Waiting for checked class is unloaded"); + pipe.println(COMMAND_UNLOAD); + command = pipe.readln(); + + // end the test if checked class has not been actually unloaded or error occurs + if (command != null && command.equals(COMMAND_LOADED)) { + throw new Warning("TEST INCOMPLETE: unable to unload class"); + } + + if (command == null || !command.equals(COMMAND_UNLOADED)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // checked class has been unloaded + log.display("Checked class forced to be unloaded from debuggee!"); + + // waiting for event until timeout exceeds + log.display("Waiting for ClassUnloadEvent for checked class"); + long timeToFinish = System.currentTimeMillis() + eventTimeout; + while (!eventReceived && System.currentTimeMillis() < timeToFinish) { + + // get next event set + eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (Exception e) { + throw new Failure("TEST INCOMPLETE: Unexpected exception while getting event: " + e); + } + if (eventSet == null) + continue; + + // handle each event from the event set + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + // handle ClassUnloadEvent + if (event instanceof ClassUnloadEvent) { + + ClassUnloadEvent castedEvent = (ClassUnloadEvent)event; + log.display("Received event is ClassUnloadEvent:\n " + castedEvent); + + // check that received event is for checked request + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 1: eventRequest is not equal to checked request"); + testFailed = true; + } + + // check that received event is for checked VM + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + // test the method ClassUnloadEvent.className() + String refName = castedEvent.className(); + + // check that received event is for checked class + log.display("ClassUnloadEvent is received for " + refName); + if ((refName == null) || (refName.equals(""))) { + log.complain("FAILURE 3: ClassUnloadEvent.className() returns null or empty string"); + testFailed = true; + } else if (refName.equals(CHECKED_CLASS)) { + + // mark that ClassUnloadEvent for checked class received + eventReceived = true; + log.display("Expected ClassUnloadEvent for checked class received!"); + +/* + // check that checked class is not included in debuggee's list of loaded classes + List loadedClasses = vm.classesByName(CHECKED_CLASS); + if (loadedClasses != null) { + log.complain("FAILURE 4: ClassUnloadEvent is received for class to be unloaded\n" + + " but class still presents in the list of all debuggee classes"); + testFailed = true; + } +*/ + + } else { + + // ClassUnloadEvent for another class received; just display it + List loadedClasses = vm.classesByName(refName); + if (loadedClasses != null) { + log.display("ClassUnloadEvent was received for loaded class " + refName); + } + } + } + + // ignore all other events + } + + log.display("Resuming event set"); + eventSet.resume(); + } + + log.display(""); + + // check that expected event has been received + log.display("Searching checked class in debuggee"); + rType = debuggee.classByName(CHECKED_CLASS); + if (rType != null) { + if (eventReceived) { + log.complain("FAILURE 4: ClassUnloadEvent is received for class to be unloaded\n" + + " but class still presents in the list of all debuggee classes"); + testFailed = true; + } else { + log.display("WARNING: Unable to test ClassUnloadEvent because checked class\n" + + " was not actually unloaded"); + } + } else { + if (!eventReceived) { + log.complain("FAILURE 6: ClassUnloadEvent was not received for class to be unloaded\n" + + " but class no longe presents in the list of all debuggee classes "); + testFailed = true; + } + } + + } catch (Warning e) { + log.display("WARNING: " + e.getMessage()); + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + // disable event request to prevent appearance of further events + if (checkedRequest != null) { + log.display("Disabling event request"); + checkedRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + return PASSED; + } + + static class Warning extends Failure { + Warning(String msg) { + super(msg); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/TestDescription.java new file mode 100644 index 00000000000..ab7cf2bfb83 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/TestDescription.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassUnloadEvent/className/classname001. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * The test exercises JDI method ClassUnloadEvent.className() . + * The test checks the following assertions: + * - ClassUnloadEvent is always received by debugger + * for unloaded class in target VM, + * - the string returned by className() is not empty. + * A debugger class - nsk.jdi.ClassUnloadEvent.className.classname001 ; + * a debuggee class - nsk.jdi.ClassUnloadEvent.className.classname001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger forces debuggee to load checked class, creates and + * enables ClassUnloadRequest. Next, debugger forces debuggee to + * unload class, using memory stressing techique, and waits for + * ClassUnloadEvent. + * If expected ClassUnloadEvent occurs, debugger tests method + * ClassUnloadEvent.className() and verifies that this event + * is for checked class. + * If no expected ClassUnloadEvent received for WAITTIME period + * but class not found in debuggee, or ClassUnloadEvent received + * but class still in class list, debugger reports an error. + * Test pass even if class leave loaded in debuggee but no + * ClassUnloadEvent received, + * Finally, debugger disables event request to prevent further + * appearing of events, sends debuggee command to quit, clears + * event queue, wait for debugge terminated, and exits. + * The test fails if any of the checks failed. + * PARAMETERS + * 1: String - current test directory. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4463674: TEST_BUG: some JDI tests are timing dependent + * Test fixed due to bug: + * 4419078 HS1.4: class isn't unloaded when its classloader is being finalized + * Test fixed due to bug: + * 4642444 TEST_BUG: tests against ClassUnloadEvent fail due to internal ping timeout + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - classname003b class was moved in 'loadclass' subdirectory; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for classname003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassUnloadEvent.className.classname001 + * nsk.jdi.ClassUnloadEvent.className.classname001a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassUnloadEvent.className.classname001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/loadclass/classname001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/loadclass/classname001b.java new file mode 100644 index 00000000000..9dc56c62681 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001/loadclass/classname001b.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2001, 2018, 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 class will be loaded and then unloaded + +package nsk.jdi.ClassUnloadEvent.className; + +class classname001b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001a.java new file mode 100644 index 00000000000..1415f30a3d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/className/classname001a.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassUnloadEvent.className; + +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class classname001a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final String PREFIX = "nsk.jdi.ClassUnloadEvent.className"; + static final String CHECKED_CLASS = PREFIX + ".classname001b"; + + public static void main(String args[]) { + classname001a _classname001a = new classname001a(); + System.exit(JCK_STATUS_BASE + _classname001a.run(args)); + } + + int run (String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // define directory to class files + String loadClassDir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + // notify debugger that debugee is ready + pipe.println(classname001.COMMAND_READY); + + // wait for a command to load checked class + String command = pipe.readln(); + if (!command.equals(classname001.COMMAND_LOAD)) { + System.err.println("TEST BUG: unexpected command: " + command); + return FAILED; + } + + // load class for further unloading + ClassUnloader classUnloader = new ClassUnloader(); + try { + classUnloader.loadClass(CHECKED_CLASS, loadClassDir); + } catch (Exception ex) { + System.err.println("Unexpected exception while loading classname001b:"); + System.err.println(ex); + return FAILED; + } + + // notify debugger that checked class is loaded + pipe.println(classname001.COMMAND_LOADED); + + // turn off pipe pinging + pipe.setPingTimeout(0); + + // wait for a command to unload checked class + command = pipe.readln(); + if (!command.equals(classname001.COMMAND_UNLOAD)) { + System.err.println("TEST BUG: unexpected command: " + command); + return FAILED; + } + + // try to unload checked class + boolean unloaded = classUnloader.unloadClass(); + + if (!unloaded) { + pipe.println(classname001.COMMAND_LOADED); + } else { + pipe.println(classname001.COMMAND_UNLOADED); + } + + // wait for a command to exit + command = pipe.readln(); + if (!command.equals(classname001.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001.java new file mode 100644 index 00000000000..e3afb2185b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001.java @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassUnloadEvent.classSignature; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.List; +import java.util.Iterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +// NOTE: Test does not check array class because of difficulty of +// providing reliable technique for unloading such class. +// So all these testcases are commented in the test. + +public class signature001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_LOAD = "load"; + static final String COMMAND_LOADED = "loaded"; + static final String COMMAND_UNLOAD = "unload"; + static final String COMMAND_UNLOADED = "unloaded"; + + static final String PREFIX = "nsk.jdi.ClassUnloadEvent.classSignature"; + static final String DEBUGGEE_NAME = PREFIX + ".signature001a"; + static final String CHECKED_CLASS = PREFIX + ".signature001c"; + static final String CHECKED_INTERFACE = PREFIX + ".signature001b"; + static final String CHECKED_ARRAY = PREFIX + ".signature001c[]"; + static final String KLASSLOADER = ClassUnloader.INTERNAL_CLASS_LOADER_NAME; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private ClassUnloadRequest checkedRequest; + + static private long eventTimeout; + static private boolean testFailed; + static private boolean eventsReceived; + static private boolean eventForClass, eventForInterface, eventForArray; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventsReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debugee + + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "signature001a >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // create request and wait for ClassUnloadEvent + + try { + + // resume debugee and wait for it becomes ready + + log.display("Resuming debuggee"); + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (command == null || !command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirror of debugee class + + ReferenceType rType; + if ((rType = debuggee.classByName(DEBUGGEE_NAME)) == null) { + throw new Failure("TEST BUG: cannot find debuggee's class " + DEBUGGEE_NAME); + } + + // send command to load checked class and waits for a confirmation + + pipe.println(COMMAND_LOAD); + log.display("Waiting for checked class is loaded"); + command = pipe.readln(); + + if (command == null || !command.equals(COMMAND_LOADED)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // checked class has been loaded! + log.display("Checked classes have been loaded in debuggee!"); + + // create request for class unload event + + log.display("Creating request for ClassUnloadEvent"); + EventRequestManager erManager = vm.eventRequestManager(); + if ((checkedRequest = erManager.createClassUnloadRequest()) == null) { + throw new Failure("TEST BUG: unable to create ClassUnloadRequest"); + } else { + log.display("ClassUnloadRequest created"); + } +// checkedRequest.addClassFilter("nsk.jdi.ClassUnloadEvent.classSignature.*"); + + log.display("Enabling event request"); + checkedRequest.enable(); + + List unloadRequests = vm.eventRequestManager().classUnloadRequests(); + if (unloadRequests == null) { + throw new Failure("TEST_BUG: ClassUnloadRequest is not created"); + } + + // force checked classes to be unloaded from debuggee + + // turn off pipe pinging + pipe.setPingTimeout(0); + + log.display("Waiting for checked class is unloaded"); + pipe.println(COMMAND_UNLOAD); + command = pipe.readln(); + + // end test if checked classes have not been actually unloaded or error occurs + + if (command != null && command.equals(COMMAND_LOADED)) { +// throw new Failure("TEST INCOMPLETE: unable to unload classes"); + throw new Warning("TEST INCOMPLETE: unable to unload classes"); + } + + if (command == null || !command.equals(COMMAND_UNLOADED)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // checked classes have been unloaded + log.display("Checked classes forced to be unloaded from debuggee!"); + + // waiting for event untill timeout exceeds + log.display("Waiting for ClassUnloadEvent for checked class"); + long timeToFinish = System.currentTimeMillis() + eventTimeout; + while (!eventsReceived && System.currentTimeMillis() < timeToFinish) { + + // get next event set + eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (Exception e) { + throw new Failure("TEST INCOMPLETE: Unexpected exception while getting event: " + e); + } + if (eventSet == null) + continue; + + // handle each event from the event set + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + // handle ClassUnloadEvent + if (event instanceof ClassUnloadEvent) { + + ClassUnloadEvent castedEvent = (ClassUnloadEvent)event; + log.display("Received event is ClassUnloadEvent:\n" + castedEvent); + + // check that received event is for checked request + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 1: eventRequest is not equal to checked request"); + testFailed = true; + } + + // check that received event is for checked VM + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + // test method ClassUnloadEvent. + String refSignature = castedEvent.classSignature(); + log.display("ClassUnloadEvent is received for " + refSignature); + + // check that received event is for checked class + if ((refSignature == null) || (refSignature.equals(""))) { + + log.complain("FAILURE 3: ClassUnloadEvent.classSignature() returns null or empty string"); + testFailed = true; + + } else if (refSignature.equals("L" + CHECKED_CLASS.replace('.','/') + ";")) { + + // mark that ClassUnloadEvent for checked class received + eventForClass = true; + log.display("Expected ClassUnloadEvent for checked class received!"); + +/* + // check that checked class is not included in debuggee's list of loaded classes + List loadedClasses = vm.classesByName(CHECKED_CLASS); + if (loadedClasses != null) { + log.complain("FAILURE 4: Class " + CHECKED_CLASS + + " is not unloaded while ClassUnloadEvent is received"); + testFailed = true; + } +*/ + + } else if (refSignature.equals("L" + CHECKED_INTERFACE.replace('.','/') + ";")) { + + // mark that ClassUnloadEvent for checked interface received + eventForInterface = true; + log.display("Expected ClassUnloadEvent for checked class received!"); + +/* + // check that checked interface is not included in debuggee's list of loaded classes + List loadedClasses = vm.classesByName(CHECKED_INTERFACE); + if (loadedClasses != null) { + log.complain("FAILURE 4: Class " + CHECKED_INTERFACE + + " is not unloaded while ClassUnloadEvent is received"); + testFailed = true; + } +*/ + +/* + } else if (refSignature.equals("L" + CHECKED_ARRAY.replace('.','/') + ";")) { + + // mark that ClassUnloadEvent for checked array class received + eventForArray = true; + log.display("Expected ClassUnloadEvent for checked array class received!"); + + // check that checked array class is not included in debuggee's list of loaded classes + List loadedClasses = vm.classesByName(CHECKED_ARRAY); + if (loadedClasses != null) { + log.complain("FAILURE 4: Class " + CHECKED_ARRAY + + " is not unloaded while ClassUnloadEvent is received"); + testFailed = true; + } + +*/ + } else { + + // ClassUnloadEvent for another class received; just display it + log.display("ClassUnloadEvent was received for loaded class " + refSignature); + } + } + + // ignore all other events + } + + eventSet.resume(); + eventsReceived = eventForClass && eventForInterface /* && eventForArray */; + } + + log.display(""); + + // check that expected event has been received for checked class + log.display("Searching checked class in debuggee"); + rType = debuggee.classByName(CHECKED_CLASS); + if (rType != null) { + if (eventForClass) { + log.complain("FAILURE 4: ClassUnloadEvent is received for class to be unloaded\n" + + " but class still presents in the list of all debuggee classes"); + testFailed = true; + } else { + log.display("WARNING: Unable to test ClassUnloadEvent because checked class\n" + + " was not actually unloaded"); + } + } else { + if (!eventForClass) { + log.complain("FAILURE 5: ClassUnloadEvent was not received for class to be unloaded\n" + + " but class no longe presents in the list of all debuggee classes "); + testFailed = true; + } + } + + // check that expected event has been received for checked interface + log.display("Searching checked interface in debuggee"); + rType = debuggee.classByName(CHECKED_INTERFACE); + if (rType != null) { + if (eventForInterface) { + log.complain("FAILURE 6: ClassUnloadEvent is received for interface to be unloaded\n" + + " but class still presents in the list of all debuggee classes"); + testFailed = true; + } else { + log.display("WARNING: Unable to test ClassUnloadEvent because checked interface\n" + + " was not actually unloaded"); + } + } else { + if (!eventForInterface) { + log.complain("FAILURE 7: ClassUnloadEvent was not received for interface to be unloaded\n" + + " but class no longe presents in the list of all debuggee classes "); + testFailed = true; + } + } + + } catch (Warning e) { + log.display("WARNING: " + e.getMessage()); + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + // disable event request to prevent appearance of further events + if (checkedRequest != null) { + log.display("Disabling event request"); + checkedRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debugee terminates and check its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + return PASSED; + } + + static class Warning extends Failure { + Warning(String msg) { + super(msg); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/TestDescription.java new file mode 100644 index 00000000000..7a8699a2b98 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/TestDescription.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassUnloadEvent/classSignature/signature001. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.ClassUnloadEvent.classSignature() method. + * The test checks the following assertions: + * - ClassUnloadEvent is always received by debugger + * for unloaded class, interface and array type in target VM, + * - the string returned by classSignature() is not empty and comply + * to JNI-style signature. + * A debugger class - nsk.jdi.ClassUnloadEvent.classSignature.signature001 ; + * a debuggee class - nsk.jdi.ClassUnloadEvent.classSignature.signature001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger forces debugge to load checked classes, creates and + * enables ClassUnloadRequest. Next, debugger forces debuggee to + * unload classes, using memory stressing techique, and waits for + * ClassUnloadEvent. + * If each expected ClassUnloadEvent occurs, debugger tests method + * ClassUnloadEvent.classSignature() and verifies that this event + * is for checked class or interface. + * If no expected ClassUnloadEvent received for WAITTIME period + * but class not found in debuggee, or ClassUnloadEvent received + * but class still in class list, debugger reports an error. + * Test pass even if class leave loaded in debuggee but no + * ClassUnloadEvent received, + * Finally, debugger disables event request to prevent further + * appearing of events, sends debuggee command to quit, clears + * event queue, wait for debugge terminated, and exits. + * The test fails if any of the checks failed. + * PARAMETERS + * 1: String - current test directory. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4463674: TEST_BUG: some JDI tests are timing dependent + * NOTE: testcase for array class is excluded from the test (commented out) + * because of difficulty to provide reliable techique to unload + * such a class. + * Test fixed due to bug: + * 4419078 HS1.4: class isn't unloaded when its classloader is being finalized + * Test fixed due to bug: + * 4642444 TEST_BUG: tests against ClassUnloadEvent fail due to internal ping timeout + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - signature003b and signature003c classes were moved in + * 'loadclass' subdirectory; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for classes to load in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassUnloadEvent.classSignature.signature001 + * nsk.jdi.ClassUnloadEvent.classSignature.signature001a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassUnloadEvent.classSignature.signature001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/loadclass/signature001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/loadclass/signature001b.java new file mode 100644 index 00000000000..1535929e1ba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/loadclass/signature001b.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2001, 2018, 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 interface will be loaded and then unloaded +package nsk.jdi.ClassUnloadEvent.classSignature; + +public interface signature001b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/loadclass/signature001c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/loadclass/signature001c.java new file mode 100644 index 00000000000..a2642fc406b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001/loadclass/signature001c.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2001, 2018, 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 class will be loaded and then unloaded +package nsk.jdi.ClassUnloadEvent.classSignature; + +public class signature001c { + private signature001c[] signature001r; + public void initArray() { + signature001r = new signature001c[] {new signature001c()}; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001a.java new file mode 100644 index 00000000000..bb4f8ec10a5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadEvent/classSignature/signature001a.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ClassUnloadEvent.classSignature; + +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.lang.reflect.Method; + +// This class is the debugged application in the test + +// NOTE: Test does not check array class because of difficulty of +// providing reliable technique for unloading such class. +// So all these testcases are commented in the test. + +class signature001a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final String PREFIX = "nsk.jdi.ClassUnloadEvent.classSignature"; + static final String CHECKED_CLASS = PREFIX + ".signature001c"; + static final String CHECKED_INTFACE = PREFIX + ".signature001b"; + static final String CHECKED_ARRAY = PREFIX + ".signature001c[]"; + + public static void main(String args[]) { + signature001a _signature001a = new signature001a(); + System.exit(JCK_STATUS_BASE + _signature001a.run(args)); + } + + int run (String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // define directory to load class files + String loadClassDir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + // notify debugger that debugee is ready + pipe.println(signature001.COMMAND_READY); + + // wait for a command to load checked class + String command = pipe.readln(); + if (!command.equals(signature001.COMMAND_LOAD)) { + System.err.println("TEST BUG: unexpected command: " + command); + return FAILED; + } + + // load checked class for further unloading + ClassUnloader checkedClassUnloader = new ClassUnloader(); + try { + checkedClassUnloader.loadClass(CHECKED_CLASS, loadClassDir); + } catch (Exception ex) { + System.err.println("Unexpected exception while loading " + CHECKED_CLASS + ":"); + System.err.println(ex); + return FAILED; + } + + // load checked interface for further unloading + ClassUnloader checkedInterfaceUnloader = new ClassUnloader(); + try { + checkedInterfaceUnloader.loadClass(CHECKED_INTFACE, loadClassDir); + } catch (Exception ex) { + System.err.println("Unexpected exception while loading " + CHECKED_INTFACE + ":"); + System.err.println(ex); + return FAILED; + } + +/* + // to load array type + Object object1; + try { + object1 = class1.newInstance(); + } catch (Throwable e) { + System.err.println("Cannot create instance of " + CHECKED_CLASS); + System.err.println("Exception/error: " + e.getMessage()); + return FAILED; + } + Method method1; + try { + method1 = class1.getMethod("initArray", null); + method1.invoke(object1, null); + System.out.println("method initArray is invoked"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + try { + if (!(Class.forName(CHECKED_ARRAY).getClassLoader() instanceof KlassLoader)) { + System.err.println("TEST BUG: Incorrect loader of type" + CHECKED_ARRAY); + return FAILED; + } + } catch (Exception e) { + System.out.println(e.getMessage()); + } +*/ + + // notify debugger that checked class is loaded + pipe.println(signature001.COMMAND_LOADED); + + // turn off pipe pinging + pipe.setPingTimeout(0); + + // wait for a command to unload checked class + command = pipe.readln(); + if (!command.equals(signature001.COMMAND_UNLOAD)) { + System.err.println("TEST BUG: unexpected command: " + command); + return FAILED; + } + + // try to unload checked class + boolean classes_unloaded = checkedClassUnloader.unloadClass() + && checkedInterfaceUnloader.unloadClass(); + + if (!classes_unloaded) { + pipe.println(signature001.COMMAND_LOADED); + } else { + pipe.println(signature001.COMMAND_UNLOADED); + } + + // wait for a command to exit + pipe.println(signature001.COMMAND_UNLOAD); + + command = pipe.readln(); + if (!command.equals(signature001.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001.java new file mode 100644 index 00000000000..d95bf7fa8de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest._bounds_; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; + +import java.io.*; + +/** + * The test checks up the
    + * - addClassFilter(ReferenceType),
    + * - addClassFilter(String),
    + * - addClassExclusionFilter(String)
    + * methods with null argument value. + * In any cases NullPointerException is expected. + */ +public class filters001 { + + final static String prefix = "nsk.jdi.ClassUnloadRequest._bounds_."; + private final static String className = "filters001"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + filters001 thisTest = new filters001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType debugeeRef = debugee.classByName(debugeeName); + + display(""); + display(">>>creating ClassUnloadRequest"); + ClassUnloadRequest request = + debugee.getEventRequestManager().createClassUnloadRequest(); + + display(""); + addClassFilter(request, (String )null); + display(""); + addClassExclusionFilter(request, (String )null); + + display(""); + debugee.quit(); + } + + private void addClassFilter(ClassUnloadRequest request, String classPattern) { + + display("addClassFilter :classPattern> null"); + try { + request.addClassFilter(classPattern); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassExclusionFilter(ClassUnloadRequest request, + String classPattern) { + display("addExclusionClassFilter :classPattern> null"); + try { + request.addClassExclusionFilter(classPattern); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001/TestDescription.java new file mode 100644 index 00000000000..c0974086adf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassUnloadRequest/_bounds_/filters001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the methods + * com.sun.jdi.request.ClassUnloadRequest.addClassFilter(String) + * com.sun.jdi.request.ClassUnloadRequest.addClassExclusionFilter(String) + * correctly work for the boundary value of parameter and throw described + * exceptions. + * The test check up these methods with argument value. In any cases + * NullPointerException is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassUnloadRequest._bounds_.filters001 + * nsk.jdi.ClassUnloadRequest._bounds_.filters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassUnloadRequest._bounds_.filters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001a.java new file mode 100644 index 00000000000..50857a06189 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/_bounds_/filters001a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filters001a is deugee's part of the test. + */ +public class filters001a { + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001.java new file mode 100644 index 00000000000..71e1878e3b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import java.io.*; +import java.util.*; + +/** + * Debugger requests ClassUnloadEvent and sets class filter by calling + * addClassExclusionFilter with pattern that begins with '*' and ends + * with '*'. + * + *

    + * To excite a class loading/unloading onto debugee, debugeer uses + * nsk.share.ClassUnloader and performs it twice :
    + * 1. for pattern that ends with '*'
    + * 2. for pattern that begins with '*'
    + * It is expected:
    + * - in case no events occured, test is considered as passed
    + * - in case classunload event occurs, debugger checks class name to do not match to + * pattern. + */ +public class exclfilter001 { + + final static String prefix = "nsk.jdi.ClassUnloadRequest.addClassExclusionFilter."; + private final static String className = "exclfilter001"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + + // signals to control working of debugee + public final static String SGNL_LOAD = "load"; + public final static String SGNL_UNLOAD = "unload"; + public final static String SGNL_BREAK = "break"; + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static int eventWaitTime; + + String[] patterns = { + prefix + "Sub*", + "*.Superexclfilter002b" + }; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exclfilter001 tstObj = new exclfilter001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + eventWaitTime = argHandler.getWaitTime() * 60000; + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + tstObj.execTest(); + + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ClassUnloadRequest request; + + // when there are no class unload events, test should be considered as PASSED + exitStatus = Consts.TEST_PASSED; + + for (int i = 0; i < patterns.length; i++) { + // loading of tested classes + display("sending " + SGNL_LOAD); + debugee.sendSignal(SGNL_LOAD); + debugee.receiveExpectedSignal(SGNL_READY); + + // unloading of tested classes + display("------------------------------------------------"); + request = requestClassUnload(patterns[i]); + display("================================================"); + + display("sending " + SGNL_UNLOAD); + debugee.sendSignal(SGNL_UNLOAD); + debugee.receiveExpectedSignal(SGNL_READY); + + receiveEvents(eventWaitTime, patterns[i]); + + display(""); + debugee.getEventRequestManager().deleteEventRequest(request); + } + + display("sending " + SGNL_BREAK); + debugee.sendSignal(SGNL_BREAK); + debugee.quit(); + + } + + private ClassUnloadRequest requestClassUnload(String filter) { + display(">>>creating ClassUnloadRequest"); + ClassUnloadRequest request = + debugee.getEventRequestManager().createClassUnloadRequest(); + display("adding exclusion filter :"); + display(" <" + filter + ">"); + + request.addClassExclusionFilter(filter); + request.enable(); + + return request; + } + + private void receiveEvents(int waitTime, String pattern) { + EventSet eventSet = null; + Event event; + int totalTime = waitTime; + long begin, delta; + int count = 0; + boolean exit = false; + + try { + begin = System.currentTimeMillis(); + eventSet = debugee.VM().eventQueue().remove(totalTime); + delta = System.currentTimeMillis() - begin; + totalTime -= delta; + while (eventSet != null) { + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + if (event instanceof ClassUnloadEvent) { + if (!analyzeEvents((ClassUnloadEvent )event, pattern)) { + display("exiting..."); + exit = true; + break; + } + count++; + } else if (event instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received"); + } + } + if (totalTime <= 0 || exit) { + break; + } + debugee.resume(); + begin = System.currentTimeMillis(); + eventSet = debugee.VM().eventQueue().remove(totalTime); + delta = System.currentTimeMillis() - begin; + totalTime -= delta; + } + } catch(InterruptedException e) { + throw new Failure(e); + } catch(VMDisconnectedException e) { + throw new Failure(e); + } + + if (count==0) { + display(""); + display("WARNING: No events were arrived"); + display(""); + } + + debugee.resume(); + } + + private boolean analyzeEvents(ClassUnloadEvent event, String pattern) { + String className; + + className = event.className(); + + if (checkMatching(className, pattern)) { + complain("***class was excluded***\n " + className); + display(""); + exitStatus = Consts.TEST_FAILED; + return false; + } + + display("OK--> " + className); + + return true; + } + + private boolean checkMatching(String className, String pattern) { + + String tmp; + int length = pattern.length(); + + // pattern ends with '*' + if (pattern.charAt(length - 1) == '*') { + tmp = pattern.substring(0, length -1); + return className.indexOf(tmp) == 0; + + // pattern begins with '*' + } else if (pattern.charAt(0) == '*') { + tmp = pattern.substring(1); + return className.endsWith(tmp); + + // unsupported pattern + } else new TestBug("Wrong pattern <" + pattern + ">"); + + return false; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/TestDescription.java new file mode 100644 index 00000000000..9cfba1c6dc0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001. + * VM Testbase keywords: [diehard, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method + * com.sun.jdi.ClassUnloadRequest.addClassExclusionFilter(String) + * on the following assertion: + * Restricts the events generated by this request to the unloading + * of reference types whose name does not match a restricted regular + * expression. + * The cases to test include a pattern that begins with '*' and ends with '*'. + * The test works as follows: + * The debugger program - + * nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter001; + * the debuggee program - + * nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter001a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running on + * another JavaVM and controls the classes loading/unloading on debugee. + * Each event is checked class name, which generates this event, to do not + * match to defined filter. + * When class name matches to defined filter, the test fails and produces + * a corresponding error message(s). + * Note: In case no events occured, test is considered as passed. + * COMMENTS: + * Fixed due to the bug 4677256 + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - all classes to be loaded by ClassUnloader were separated and + * moved into 'loadclass' subdirectory; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for classes to load class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - throwing Failure exception on VMDisconnect is used in event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter001 + * nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter001a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm/timeout=420 PropertyResolvingWrapper + * nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/loadclass/Superexclfilter001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/loadclass/Superexclfilter001b.java new file mode 100644 index 00000000000..dc4b986fb14 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001/loadclass/Superexclfilter001b.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassExclusionFilter; + +// These classes will be loaded by ClassUnloader + +class Superexclfilter001b { + static String name = "Superexclfilter001b"; + +} + +class Subexclfilter0011 extends Superexclfilter001b { + static String name = "Subexclfilter0011"; + +} + +class Subexclfilter0021 extends Superexclfilter001b { + static String name = "Subexclfilter0021"; + +} + +class Subexclfilter0031 extends Superexclfilter001b { + static String name = "Subexclfilter0031"; + +} + +class Superexclfilter002b { + static String name = "Superexclfilter002b"; + +} + +class Subexclfilter0012 extends Superexclfilter002b { + static String name = "Subexclfilter0012"; + +} + +class Subexclfilter0022 extends Superexclfilter002b { + static String name = "Subexclfilter0022"; + +} + +class Subexclfilter0032 extends Superexclfilter002b { + static String name = "Subexclfilter0032"; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001a.java new file mode 100644 index 00000000000..77c2ce35969 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter001a.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassExclusionFilter; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * exclfilter001a is deugee's part of the test. + * It contains the descriptions classes, which are used by debugger's part of the test. + */ +public class exclfilter001a { + + static public String[] testedClasses = { + "Superexclfilter001b", + "Subexclfilter0011", + "Subexclfilter0021", + "Subexclfilter0031", + "Superexclfilter002b", + "Subexclfilter0012", + "Subexclfilter0022", + "Subexclfilter0032" + }; + + static public Log log = null; + static public IOPipe pipe = null; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(exclfilter001.SGNL_READY); + + // define directory to class files + String classDir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader unloader = null; + String instr = pipe.readln(); + + while (!instr.equals(exclfilter001.SGNL_BREAK)) { + + log.display("<" + instr + ">" + " arrived"); + if (instr==null) { + break; + } + + // loading of tested classes + if (instr.equals(exclfilter001.SGNL_LOAD)) { + unloader = loadClasses(classDir); + + // unloading of tested classes + } else if (instr.equals(exclfilter001.SGNL_UNLOAD)) { + + unloadClasses(unloader); + } + pipe.println(exclfilter001.SGNL_READY); + + instr = pipe.readln(); + } + + instr = pipe.readln(); + log.display("<" + instr + ">" + " arrived"); + + if (instr != null) { + if (instr.equals(exclfilter001.SGNL_QUIT)) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + private static ClassUnloader loadClasses(String classDir) { + ClassUnloader unloader = new ClassUnloader(); + for (int i = 0; i < testedClasses.length; i++) { + try { + unloader.loadClass(exclfilter001.prefix + testedClasses[i], classDir); + } catch(ClassNotFoundException e) { + log.complain("DEBUGEE> class " + testedClasses[i] + " not found"); + log.complain(" " + e); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + return unloader; + } + + private static void unloadClasses(ClassUnloader unloader) { + unloader.unloadClass(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002.java new file mode 100644 index 00000000000..e4246e271a3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import java.io.*; + +/** + * Debugger checks up assertion:
    + * InvalidRequestStateException - if this request is currently + * enabled or has been deleted.
    + * Debugger performs the following steps:
    + * - creates a ClassUnloadRequests and enables it;
    + * - invokes the method addClassExclusionFilter().
    + * It is expected, InvalidRequestStateException will be thrown;
    + * - deletes this request and invokes the method addClassExclusionFilter()
    + * Once again it is expected, InvalidRequestStateException will be thrown;
    + */ +public class exclfilter002 { + + final static String prefix = "nsk.jdi.ClassUnloadRequest.addClassExclusionFilter."; + private final static String className = "exclfilter002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static String pattern = prefix + "Sub*"; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exclfilter002 tstObj = new exclfilter002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + tstObj.execTest(); + + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + exitStatus = Consts.TEST_PASSED; + + EventRequestManager evm = debugee.getEventRequestManager(); + + display(">>>creating ClassUnloadRequest"); + ClassUnloadRequest request = evm.createClassUnloadRequest(); + + display("enabled request--------------------"); + display(">>>enabling of the created request"); + request.enable(); + addExclusionFilter(request); + + display("deleted request--------------------"); + display(">>>disabling of the created request"); + request.disable(); + display(">>>deleting of the created request"); + evm.deleteEventRequest(request); + addExclusionFilter(request); + + debugee.quit(); + } + + private void addExclusionFilter(ClassUnloadRequest request) { + display(">>>adding an exclusion class filter"); + display(""); + try { + request.addClassExclusionFilter(pattern); + } catch(InvalidRequestStateException e) { + display(">>>>>EXPECTED InvalidRequestStateException"); + } catch(Exception e) { + complain("******UNEXPECTED " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002/TestDescription.java new file mode 100644 index 00000000000..5411f62f904 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method + * com.sun.jdi.ClassUnloadRequest.addClassExclusionFilter(String) + * on the following assertion: + * This method throws InvalidRequestStateException - if this request + * is currently enabled or has been deleted. + * The test works as follows: + * The debugger program - + * nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter002; + * the debuggee program - + * nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter002a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running on + * another JavaVM and attempts to add filter for: + * 1. the disabled request; + * 2. the deleted request. + * When InvalidRequestStateException is not thorwn, the test fails. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter002 + * nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassUnloadRequest.addClassExclusionFilter.exclfilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002a.java new file mode 100644 index 00000000000..c49eaf27a5c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassExclusionFilter/exclfilter002a.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * exclfilter002a is deugee's part of the test. + */ +public class exclfilter002a { + + static public Log log = null; + static public IOPipe pipe = null; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001.java new file mode 100644 index 00000000000..8da9a0ecb14 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassFilter; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import java.io.*; +import java.util.*; + +/** + * Debugger requests ClassUnloadEvent and sets class filter by calling + * addClassFilter with pattern that begins with '*' and ends with '*'. + * + *

    + * To excite a class loading/unloading onto debugee, debugeer uses + * nsk.share.ClassUnloader and performs it twice :
    + * 1. for pattern that ends with '*'
    + * 2. for pattern that begins with '*'
    + * It is expected:
    + * - in case no events occured, test is considered as passed
    + * - in case classunload event occurs, debugger checks class name to match to + * pattern. + */ +public class filter001 { + + final static String prefix = "nsk.jdi.ClassUnloadRequest.addClassFilter."; + private final static String className = "filter001"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + + // signals to control working of debugee + public final static String SGNL_LOAD = "load"; + public final static String SGNL_UNLOAD = "unload"; + public final static String SGNL_BREAK = "break"; + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static int eventWaitTime; + + String[] patterns = { + prefix + "Sub*", + "*.Superfilter002b" + }; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + filter001 tstObj = new filter001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + eventWaitTime = argHandler.getWaitTime() * 60000; + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + tstObj.execTest(); + + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ClassUnloadRequest request; + + // when there are no class unload events, test should be considered as PASSED + exitStatus = Consts.TEST_PASSED; + + for (int i = 0; i < patterns.length; i++) { + // loading of tested classes + display("sending " + SGNL_LOAD); + debugee.sendSignal(SGNL_LOAD); + debugee.receiveExpectedSignal(SGNL_READY); + + // unloading of tested classes + display("------------------------------------------------"); + request = requestClassUnload(patterns[i]); + display("================================================"); + + display("sending " + SGNL_UNLOAD); + debugee.sendSignal(SGNL_UNLOAD); + debugee.receiveExpectedSignal(SGNL_READY); + + receiveEvents(eventWaitTime, patterns[i]); + + display(""); + debugee.getEventRequestManager().deleteEventRequest(request); + } + + display("sending " + SGNL_BREAK); + debugee.sendSignal(SGNL_BREAK); + debugee.quit(); + + } + + private ClassUnloadRequest requestClassUnload(String filter) { + display(">>>creating ClassUnloadRequest"); + ClassUnloadRequest request = + debugee.getEventRequestManager().createClassUnloadRequest(); + display("adding filter :"); + display(" <" + filter + ">"); + + request.addClassFilter(filter); + request.enable(); + + return request; + } + + private void receiveEvents(int waitTime, String pattern) { + EventSet eventSet = null; + Event event; + int totalTime = waitTime; + long begin, delta; + int count = 0; + boolean exit = false; + + try { + begin = System.currentTimeMillis(); + eventSet = debugee.VM().eventQueue().remove(totalTime); + delta = System.currentTimeMillis() - begin; + totalTime -= delta; + while (eventSet != null) { + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + if (event instanceof ClassUnloadEvent) { + if (!analyzeEvents((ClassUnloadEvent )event, pattern)) { + display("exiting..."); + exit = true; + break; + } + count++; + } else if (event instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received"); + } + } + if (totalTime <= 0 || exit) { + break; + } + debugee.resume(); + begin = System.currentTimeMillis(); + eventSet = debugee.VM().eventQueue().remove(totalTime); + delta = System.currentTimeMillis() - begin; + totalTime -= delta; + } + } catch(InterruptedException e) { + throw new Failure(e); + } catch(VMDisconnectedException e) { + throw new Failure(e); + } + + if (count==0) { + display(""); + display("WARNING: No events were arrived"); + display(""); + } + + debugee.resume(); + } + + private boolean analyzeEvents(ClassUnloadEvent event, String pattern) { + String className; + + className = event.className(); + + if (!checkMatching(className, pattern)) { + complain("***no matching***\n " + className); + display(""); + exitStatus = Consts.TEST_FAILED; + return false; + } + + display("OK--> " + className); + + return true; + } + + private boolean checkMatching(String className, String pattern) { + + String tmp; + int length = pattern.length(); + + // pattern ends with '*' + if (pattern.charAt(length - 1) == '*') { + tmp = pattern.substring(0, length -1); + return className.indexOf(tmp) == 0; + + // pattern begins with '*' + } else if (pattern.charAt(0) == '*') { + tmp = pattern.substring(1); + return className.endsWith(tmp); + + // unsupported pattern + } else new TestBug("Wrong pattern <" + pattern + ">"); + + return false; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/TestDescription.java new file mode 100644 index 00000000000..eebba3094bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassUnloadRequest/addClassFilter/filter001. + * VM Testbase keywords: [diehard, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method + * com.sun.jdi.ClassUnloadRequest.addClassFilter(String) + * on the following assertion: + * Restricts the events generated by this request to the unloading + * of reference types whose name does not match a restricted regular + * expression. + * The cases to test include a pattern that begins with '*' and ends with '*'. + * The test works as follows: + * The debugger program - nsk.jdi.ClassUnloadRequest.addClassFilter.filter001; + * the debuggee program - nsk.jdi.ClassUnloadRequest.addClassFilter.filter001a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running on + * another JavaVM and controls the classes loading/unloading on debugee. + * Each event is checked class name, which generates this event, to do + * match to defined filter. + * When class name does not match to defined filter, the test fails and + * produces a corresponding error message(s). + * Note: In case no events occured, test is considered as passed. + * COMMENTS: + * Fixed due to the bug 4677256 + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - all classes to be loaded by ClassUnloader were separated and + * moved into 'loadclass' subdirectory; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for classes to load class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - throwing Failure exception on VMDisconnect is used in event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassUnloadRequest.addClassFilter.filter001 + * nsk.jdi.ClassUnloadRequest.addClassFilter.filter001a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm/timeout=420 PropertyResolvingWrapper + * nsk.jdi.ClassUnloadRequest.addClassFilter.filter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/loadclass/Superfilter001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/loadclass/Superfilter001b.java new file mode 100644 index 00000000000..9f6c574cf26 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001/loadclass/Superfilter001b.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassFilter; + +// These classes will be loaded by ClassUnloader + +class Superfilter001b { + static String name = "Superfilter001b"; + +} + +class Subfilter0011 extends Superfilter001b { + static String name = "Subfilter0011"; + +} + +class Subfilter0021 extends Superfilter001b { + static String name = "Subfilter0021"; + +} + +class Subfilter0031 extends Superfilter001b { + static String name = "Subfilter0031"; + +} + +class Superfilter002b { + static String name = "Superfilter002b"; + +} + +class Subfilter0012 extends Superfilter002b { + static String name = "Subfilter0012"; + +} + +class Subfilter0022 extends Superfilter002b { + static String name = "Subfilter0022"; + +} + +class Subfilter0032 extends Superfilter002b { + static String name = "Subfilter0032"; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001a.java new file mode 100644 index 00000000000..c79bb96c48c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter001a.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassFilter; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filter001a is deugee's part of the test. + * It contains the descriptions classes, which are used by debugger's part of the test. + */ +public class filter001a { + + static public String[] testedClasses = { + "Superfilter001b", + "Subfilter0011", + "Subfilter0021", + "Subfilter0031", + "Superfilter002b", + "Subfilter0012", + "Subfilter0022", + "Subfilter0032" + }; + + static public Log log = null; + static public IOPipe pipe = null; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(filter001.SGNL_READY); + + // define directory to load class files + String classDir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader unloader = null; + String instr = pipe.readln(); + + while (!instr.equals(filter001.SGNL_BREAK)) { + + log.display("<" + instr + ">" + " arrived"); + if (instr==null) { + break; + } + + // loading of tested classes + if (instr.equals(filter001.SGNL_LOAD)) { + unloader = loadClasses(classDir); + + // unloading of tested classes + } else if (instr.equals(filter001.SGNL_UNLOAD)) { + + unloadClasses(unloader); + } + pipe.println(filter001.SGNL_READY); + + instr = pipe.readln(); + } + + instr = pipe.readln(); + log.display("<" + instr + ">" + " arrived"); + + if (instr != null) { + if (instr.equals(filter001.SGNL_QUIT)) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + private static ClassUnloader loadClasses(String classDir) { + ClassUnloader unloader = new ClassUnloader(); + for (int i = 0; i < testedClasses.length; i++) { + try { + unloader.loadClass(filter001.prefix + testedClasses[i], classDir); + } catch(ClassNotFoundException e) { + log.complain("DEBUGEE> class " + testedClasses[i] + " not found"); + log.complain(" " + e); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + return unloader; + } + + private static void unloadClasses(ClassUnloader unloader) { + unloader.unloadClass(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002.java new file mode 100644 index 00000000000..1373239735c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassFilter; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import java.io.*; + +/** + * Debugger checks up assertion:
    + * InvalidRequestStateException - if this request is currently + * enabled or has been deleted.
    + * Debugger performs the following steps:
    + * - creates a ClassUnloadRequests and enables it;
    + * - invokes the method addClassFilter().
    + * It is expected, InvalidRequestStateException will be thrown;
    + * - deletes this request and invokes the method addClassFilter()
    + * Once again it is expected, InvalidRequestStateException will be thrown;
    + */ +public class filter002 { + + final static String prefix = "nsk.jdi.ClassUnloadRequest.addClassFilter."; + private final static String className = "filter002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static String pattern = prefix + "Sub*"; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + filter002 tstObj = new filter002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + tstObj.execTest(); + + display("execTest finished. exitStatus = " + exitStatus); + + return tstObj.exitStatus; + } + + private void execTest() { + + exitStatus = Consts.TEST_PASSED; + + EventRequestManager evm = debugee.getEventRequestManager(); + + display(">>>creating ClassUnloadRequest"); + ClassUnloadRequest request = evm.createClassUnloadRequest(); + + display("enabled request--------------------"); + display(">>>enabling of the created request"); + request.enable(); + addClassFilter(request); + + display("deleted request--------------------"); + display(">>>disabling of the created request"); + request.disable(); + display(">>>deleting of the created request"); + evm.deleteEventRequest(request); + addClassFilter(request); + + debugee.quit(); + } + + private void addClassFilter(ClassUnloadRequest request) { + display(">>>adding a class filter"); + display(""); + try { + request.addClassFilter(pattern); + } catch(InvalidRequestStateException e) { + display(">>>>>EXPECTED InvalidRequestStateException"); + } catch(Exception e) { + complain("******UNEXPECTED " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002/TestDescription.java new file mode 100644 index 00000000000..570d11c0c7e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ClassUnloadRequest/addClassFilter/filter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method + * com.sun.jdi.ClassUnloadRequest.addClassFilter(String) + * on the following assertion: + * This method throws InvalidRequestStateException - if this request + * is currently enabled or has been deleted. + * The test works as follows: + * The debugger program - + * nsk.jdi.ClassUnloadRequest.addClassFilter.filter002; + * the debuggee program - + * nsk.jdi.ClassUnloadRequest.addClassFilter.filter002a. + * Using nsk.jdi.share classes, the debugger gets the debuggee running on + * another JavaVM and attempts to add filter for: + * 1. the disabled request; + * 2. the deleted request. + * When InvalidRequestStateException is not thorwn, the test fails. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ClassUnloadRequest.addClassFilter.filter002 + * nsk.jdi.ClassUnloadRequest.addClassFilter.filter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ClassUnloadRequest.addClassFilter.filter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002a.java new file mode 100644 index 00000000000..9194ad224f3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassUnloadRequest/addClassFilter/filter002a.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ClassUnloadRequest.addClassFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filter002a is deugee's part of the test. + */ +public class filter002a { + + static public Log log = null; + static public IOPipe pipe = null; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001.java new file mode 100644 index 00000000000..f44a4e7fd51 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Connector._bounds_; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jdi.*; + + +/** + * The test checks up the methods:
    + * 1. com.sun.jdi.connect.AttachingConnector.attach(Map)
    + * 2. com.sun.jdi.connect.LaunchingConnector.launch(Map)
    + * 3. com.sun.jdi.connect.ListeningConnector.startListening(Map)
    + * 4. com.sun.jdi.connect.ListeningConnector.stopListening(Map)
    + * 5. com.sun.jdi.connect.ListeningConnector.accept(Map)
    + * to throw NullPointerException for null value of arguments.
    + */ +public class bounds001 { + + public static int exitStatus; + private static Log log; + + public static void display(String msg) { + log.display(msg); + } + + public static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String args[]) { + System.exit(run(args,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[], PrintStream out) { + return new bounds001(args,out).run(); + } + + private bounds001(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + } + + private int run() { + + exitStatus = Consts.TEST_PASSED; + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List attachConnectors; + List launchConnectors; + List listConnectors; + AttachingConnector attachc; + LaunchingConnector launchc; + ListeningConnector listc; + Map arg = null; + for (int j = 0; j < 2; j++) { + if (j == 1 ) { + arg = new HashMap(); + display("arguments - Map of "); + display("-------------------------"); + } else { + display("arguments - "); + display("------------------"); + } + + display("Attaching connectors:"); + attachConnectors = vmm.attachingConnectors(); + for (int i = 0; i < attachConnectors.size(); i++) { + attachc = (AttachingConnector )attachConnectors.get(i); + display("\t" + attachc.name() + ": invoking attach(null)"); + try { + attachc.attach(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("\tExpected " + e); + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + } + + // launching connector + display("Launching connectors:"); + launchConnectors = vmm.launchingConnectors(); + for (int i = 0; i < launchConnectors.size(); i++) { + launchc = (LaunchingConnector )launchConnectors.get(i); + display("\t" + launchc.name() + ": invoking launch(null)"); + try { + launchc.launch(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("\tExpected " + e); + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + } + + display("Listening connectors:"); + listConnectors = vmm.listeningConnectors(); + for (int i = 0; i < listConnectors.size(); i++) { + listc = (ListeningConnector )listConnectors.get(i); + display("\t" + listc.name() + ": invoking startListening(null)"); + try { + listc.startListening(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("\tExpected " + e); + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("\t" + listc.name() + ": invoking stopListening(null)"); + try { + listc.stopListening(null); + } catch (NullPointerException e) { + display("\tExpected " + e); + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("\t" + listc.name() + ": invoking accept(null)"); + try { + listc.accept(null); + } catch (NullPointerException e) { + display("\tExpected " + e); + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + } + + return exitStatus; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001/TestDescription.java new file mode 100644 index 00000000000..468a4d3f10e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Connector/_bounds_/bounds001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the methods: + * 1. com.sun.jdi.connect.AttachingConnector.attach(Map) + * 2. com.sun.jdi.connect.LaunchingConnector.launch(Map) + * 3. com.sun.jdi.connect.ListeningConnector.startListening(Map) + * 4. com.sun.jdi.connect.ListeningConnector.stopListening(Map) + * 5. com.sun.jdi.connect.ListeningConnector.accept(Map) + * to throw NullPointerException for value of arguments. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Connector._bounds_.bounds001 + * nsk.jdi.Connector._bounds_.bounds001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Connector._bounds_.bounds001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001a.java new file mode 100644 index 00000000000..749b598c6ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/_bounds_/bounds001a.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Connector._bounds_; + +import nsk.share.*; + +public class bounds001a { + public static void main(String args[]) { + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001.java new file mode 100644 index 00000000000..d2fc7a93870 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Connector.defaultArguments; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.PrintStream; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector + * Method: public java.util.Map defaultArguments() + * Assertion: "Returns the arguments accepted by this Connector + * and their default values." + */ + +public class defaultArguments001 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[],PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Map cdfltArgmnts = c.defaultArguments(); + if (cdfltArgmnts == null) { + log.complain("FAILURE: connector with empty default " + + "arguments map is found!:"); + log.complain(" Name: " + c.name()); + return 2; + } + log.display("Next (" + i + ") connector's arguments is: " + + cdfltArgmnts); + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001/TestDescription.java new file mode 100644 index 00000000000..20cf04d4237 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Connector/defaultArguments/defaultArguments001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector + * Method: public java.util.Map defaultArguments() + * Assertion: "Returns the arguments accepted by this Connector + * and their default values." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Connector.defaultArguments.defaultArguments001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Connector.defaultArguments.defaultArguments001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002.java new file mode 100644 index 00000000000..1724dc9caa5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Connector.defaultArguments; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.PrintStream; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector + * Method: public java.util.Map defaultArguments() + * Assertion: "The keys of the returned map are string + * argument names." + */ + +public class defaultArguments002 { + + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Map cdfltArgmnts = c.defaultArguments(); + if (cdfltArgmnts.size() < 1) { + log.complain("FAILURE: connector with empty list of " + + "default arguments is found!:"); + log.complain(" Name: " + c.name()); + return 2; + } + + Set ks = cdfltArgmnts.keySet(); + if (ks.isEmpty()) { + log.complain("FAILURE: empty argument name set is found " + + "for " + c.name() + " connector!"); + return 2; + } + + log.display(c.name() + "connector arguments: "); + + Iterator argi = ks.iterator(); + for (int j = 1; argi.hasNext(); j++) { + Object ob = argi.next(); + if (!(ob instanceof String)) { + log.complain("FAILURE: " + j + "-argument key must be " + + "of String type!"); + return 2; + } + String argkey = (String) ob; + + if (argkey == null) { + log.complain("FAILURE: argument name is null " + + "for " + c.name() + " connector."); + return 2; + } + + if (argkey.length() == 0) { + log.complain("FAILURE: empty argument name is found " + + "for " + c.name() + " connector!"); + return 2; + } + + log.display("Next (" + j + ") argument's name is: " + argkey); + }; + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002/TestDescription.java new file mode 100644 index 00000000000..74b5446acc0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments002/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Connector/defaultArguments/defaultArguments002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector + * Method: public java.util.Map defaultArguments() + * Assertion: "The keys of the returned map are string + * argument names." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Connector.defaultArguments.defaultArguments002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Connector.defaultArguments.defaultArguments002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003.java new file mode 100644 index 00000000000..5710f9b5eb6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Connector.defaultArguments; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.PrintStream; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector + * Method: public java.util.Map defaultArguments() + * Assertion: "The values are Connector.Argument containing information + * about the argument and its default value." + */ + +public class defaultArguments003 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[],PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() < 1) { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Map cdfltArgmnts = c.defaultArguments(); + if (cdfltArgmnts.size() < 1) { + log.complain("FAILURE: connector with empty list of " + + "default arguments is found!:"); + log.complain(" Name: " + c.name()); + return 2; + } + + Set ks = cdfltArgmnts.keySet(); + if (ks.isEmpty()) { + log.complain("FAILURE: empty argument name set is found " + + "for " + c.name() + " connector!"); + return 2; + } + + log.display(c.name() + "connector arguments values: "); + + Iterator argi = ks.iterator(); + for (int j = 1; argi.hasNext(); j++) { + String argkey = (String) argi.next(); + Object ob = cdfltArgmnts.get((Object) argkey); + if (!(ob instanceof Connector.Argument)) { + log.complain("FAILURE: " + j + "-argument value " + + "must be of Connector.Argument type!"); + return 2; + } + Connector.Argument argval = + (Connector.Argument)cdfltArgmnts.get((Object) argkey); + if (argval == null) { + log.complain("FAILURE: empty argument value is " + + "found for " + c.name() + " connector!"); + return 2; + } + + if (argval == null) { + log.complain("FAILURE: empty argument value is " + + "found for " + c.name() + " connector!"); + return 2; + } + + log.display("Next (" + j + ") argument's value is: " + + argval); + }; + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003/TestDescription.java new file mode 100644 index 00000000000..63696019e44 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/defaultArguments/defaultArguments003/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Connector/defaultArguments/defaultArguments003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector + * Method: public java.util.Map defaultArguments() + * Assertion: "The keys of the returned map are string + * argument names." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Connector.defaultArguments.defaultArguments003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Connector.defaultArguments.defaultArguments003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/description/description001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/description/description001.java new file mode 100644 index 00000000000..21da4644607 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/description/description001.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Connector.description; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.PrintStream; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector + * Method: public java.lang.String description() + * Assertion: "Returns a human-readable description of this + * connector of this connector and its purpose." + */ + +public class description001 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + String cdsc = c.description(); + + if (cdsc == null) { + log.complain("FAILURE: connector description is null."); + log.complain(" Name: " + c.name()); + log.complain(" Transport: " + c.transport().name()); + return 2; + } + + if (cdsc.length() == 0) { + log.complain("FAILURE: connector with empty-description " + + "is found."); + log.complain(" Name: " + c.name()); + log.complain(" Transport: " + c.transport().name()); + return 2; + } + log.display("Next (" + i + ") connector's description is: " + + cdsc); + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/description/description001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/description/description001/TestDescription.java new file mode 100644 index 00000000000..a9ac5306dc8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/description/description001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Connector/description/description001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector + * Method: public java.lang.String description() + * Assertion: "Returns a human-readable description of this + * connector of this connector and its purpose." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Connector.description.description001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Connector.description.description001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/name/name001.java new file mode 100644 index 00000000000..a8e3cfb8576 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/name/name001.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Connector.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.Connector; +import java.io.PrintStream; +import java.util.*; + +/** + * Test for control of + * + * Interface: com.sun.jdi.connect.Connector + * Method: public java.lang.String name() + * Assertion: "Returns a short identifier for the connector." + */ + +public class name001 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + String cnm = c.name(); + if (cnm == null) { + log.complain("FAILURE: connector name is null."); + log.complain(" Description: " + c.description()); + log.complain(" Transport: " + c.transport().name()); + return 2; + } + + if (cnm.length() == 0) { + log.complain("FAILURE: connector with empty-name is found."); + log.complain(" Description: " + c.description()); + log.complain(" Transport: " + c.transport().name()); + return 2; + } + + log.display("Next (" + i + ") connector's name is: " + cnm); + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/name/name001/TestDescription.java new file mode 100644 index 00000000000..5115c40dfe4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/name/name001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Connector/name/name001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on control of: + * Interface: com.sun.jdi.connect.Connector + * Method: public java.lang.String name() + * Assertion: "Returns a short identifier for the connector." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Connector.name.name001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Connector.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/toString/tostring001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/toString/tostring001.java new file mode 100644 index 00000000000..a1aa360f1e8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/toString/tostring001.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Connector.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class tostring001 { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.dummy.dummy"; + private final static String className = "tostring001"; + private final static String debuggerName = prefix + className; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + + //------------------------------------------------------ mutable common method + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + display("Number of all known JDI connectors: " + acl.size()); + } else { + complain("No JDI connectors found!"); + return Consts.TEST_FAILED; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + String cnm = c.toString(); + if (cnm == null) { + complain("toString() method returns null for Connector #" + i + " : "); + complain(" Description: " + c.description()); + complain(" Transport: " + c.transport().name()); + exitStatus = Consts.TEST_FAILED; + } else if (cnm.length() == 0) { + complain("toString() method returns empty string for Connector #" + i + " : "); + complain(" Description: " + c.description()); + complain(" Transport: " + c.transport().name()); + exitStatus = Consts.TEST_FAILED; + } else { + display("toString() method returns for Connector #" + i + " : " + cnm); + } + }; + + return exitStatus; + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..573afc87cfb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/toString/tostring001/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Connector/toString/tostring001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public toString() method of an implementing class of + * com.sun.jdi.Connector interface. + * The test checks an assertion: + * In conformity with the contract for java.lang.Object.toString(), + * the overrided method returns representing non-empty string for every + * connector returned in the VirtualMachineManager.allConnectors() list. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for Connector + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Connector.toString.tostring001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Connector.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/transport/transport001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/transport/transport001.java new file mode 100644 index 00000000000..49386ec9d92 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/transport/transport001.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Connector.transport; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.PrintStream; +import java.util.*; + +/** + * Test for the control of + * + * Interface: com.sun.jdi.connect.Connector + * Method: public Transport transport() + * Assertion: "Returns the transport mechanism used by this + * connector to establish connections with a target VM." + */ + +public class transport001 { + private static Log log; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List acl = vmm.allConnectors(); + if (acl.size() > 0) { + log.display("Number of all known JDI connectors: " + acl.size()); + } else { + log.complain("FAILURE: no JDI connectors found!"); + return 2; + } + + Iterator aci = acl.iterator(); + for (int i = 1; aci.hasNext(); i++) { + Connector c = (Connector) aci.next(); + Transport ctrnsprt = c.transport(); + if (ctrnsprt == null) { + log.complain("FAILURE: connector with empty-transport " + + "is found!:"); + log.complain(" Name: " + c.name()); + return 2; + } + log.display("Next (" + i + ") connector's transport is: " + + ctrnsprt); + }; + log.display("Test PASSED!"); + return 0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/transport/transport001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/transport/transport001/TestDescription.java new file mode 100644 index 00000000000..3393737f7cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Connector/transport/transport001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Connector/transport/transport001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * ================================================ + * DESCRIPTION: + * The test is aimed on the control of: + * Interface: com.sun.jdi.connect.Connector + * Method: public Transport transport() + * Assertion: "Returns the transport mechanism used by this + * connector to establish connections with a target VM." + * ================================================ + * COMMENTS: + * ================================================ + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Connector.transport.transport001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Connector.transport.transport001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConnectorsJarBuilder.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConnectorsJarBuilder.java new file mode 100644 index 00000000000..d4bd9f1a9bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConnectorsJarBuilder.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2018, 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 nsk.jdi; + +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.Utils; +import jdk.test.lib.process.ProcessTools; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.stream.Stream; + +public class ConnectorsJarBuilder { + public static void main(String[] args) { + Path src = Paths.get(Utils.TEST_SRC) + .resolve("connectors") + .toAbsolutePath(); + if (Files.notExists(src)) { + throw new Error("connectors dir [" + src + "] doesn't exist"); + } + Path classes = Paths.get("connectors","classes") + .toAbsolutePath(); + try { + Files.createDirectories(classes); + } catch (IOException e) { + throw new Error("can't create dir " + classes, e); + } + compile(src, classes); + Path target = Paths.get("jars", "connectors.jar") + .toAbsolutePath(); + buildJar(classes, target); + addMetaInf(src, target); + } + + private static void compile(Path src, Path classes) { + JDKToolLauncher javac = JDKToolLauncher.create("javac") + .addToolArg("-d") + .addToolArg(classes.toString()) + .addToolArg("-cp") + .addToolArg(Utils.TEST_CLASS_PATH); + try (Stream stream = Files.walk(src)) { + stream.map(Path::toAbsolutePath) + .map(Path::toString) + .filter(s -> s.endsWith(".java")) + .forEach(javac::addToolArg); + } catch (IOException e) { + throw new Error("traverse dir " + src, e); + } + + executeTool(javac); + } + + private static void buildJar(Path classes, Path target) { + try { + Files.createDirectories(target.getParent()); + } catch (IOException e) { + throw new Error("can't create dir " + target.getParent(), e); + } + JDKToolLauncher jar = JDKToolLauncher.create("jar") + .addToolArg("cf") + .addToolArg(target.toString()) + .addToolArg("-C") + .addToolArg(classes.toString()) + .addToolArg("."); + executeTool(jar); + } + + private static void addMetaInf(Path src, Path jarFile) { + Path metaInf = src.resolve("META-INF"); + if (Files.exists(metaInf)) { + JDKToolLauncher jar = JDKToolLauncher.create("jar") + .addToolArg("uf") + .addToolArg(jarFile.toString()) + .addToolArg("-C") + .addToolArg(src.toString()) + .addToolArg("META-INF"); + executeTool(jar); + } + } + + private static void executeTool(JDKToolLauncher tool) { + String[] command = tool.getCommand(); + try { + ProcessTools.executeCommand(command) + .shouldHaveExitValue(0); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable e) { + throw new Error("execution of " + Arrays.toString(command) + " failed", e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConstantField/values001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConstantField/values001.java new file mode 100644 index 00000000000..7710337fa9e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConstantField/values001.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ConstantField; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.*; + +/** + * Test checks up static fields of JDI interfaces according to specification + */ +public class values001 { + + private static int exitStatus; + private static Log log; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + execTest(); + + log.display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private static void execTest() { + exitStatus = Consts.TEST_PASSED; + + if (ClassType.INVOKE_SINGLE_THREADED != 1) { + log.complain("***wrong value*** : ClassType.INVOKE_SINGLE_THREADED = " + + ClassType.INVOKE_SINGLE_THREADED); + exitStatus = Consts.TEST_FAILED; + } + + if (ObjectReference.INVOKE_NONVIRTUAL != 2) { + log.complain("***wrong value*** : ObjectReference.INVOKE_NONVIRTUAL = " + + ObjectReference.INVOKE_NONVIRTUAL); + exitStatus = Consts.TEST_FAILED; + } + + if (ObjectReference.INVOKE_SINGLE_THREADED != 1) { + log.complain("***wrong value*** : ObjectReference.INVOKE_SINGLE_THREADED = " + + ObjectReference.INVOKE_SINGLE_THREADED); + exitStatus = Consts.TEST_FAILED; + } + + if (ThreadReference.THREAD_STATUS_MONITOR != 3) { + log.complain("***wrong value*** : ThreadReference.THREAD_STATUS_MONITOR = " + + ThreadReference.THREAD_STATUS_MONITOR); + exitStatus = Consts.TEST_FAILED; + } + + if (ThreadReference.THREAD_STATUS_NOT_STARTED != 5) { + log.complain("***wrong value*** : ThreadReference.THREAD_STATUS_NOT_STARTED = " + + ThreadReference.THREAD_STATUS_NOT_STARTED); + exitStatus = Consts.TEST_FAILED; + } + + if (ThreadReference.THREAD_STATUS_RUNNING != 1) { + log.complain("***wrong value*** : ThreadReference.THREAD_STATUS_RUNNING = " + + ThreadReference.THREAD_STATUS_RUNNING); + exitStatus = Consts.TEST_FAILED; + } + + if (ThreadReference.THREAD_STATUS_SLEEPING != 2) { + log.complain("***wrong value*** : ThreadReference.THREAD_STATUS_SLEEPING = " + + ThreadReference.THREAD_STATUS_SLEEPING); + exitStatus = Consts.TEST_FAILED; + } + + if (ThreadReference.THREAD_STATUS_UNKNOWN != -1) { + log.complain("***wrong value*** : ThreadReference.THREAD_STATUS_UNKNOWN = " + + ThreadReference.THREAD_STATUS_UNKNOWN); + exitStatus = Consts.TEST_FAILED; + } + + if (ThreadReference.THREAD_STATUS_WAIT != 4) { + log.complain("***wrong value*** : ThreadReference.THREAD_STATUS_WAIT = " + + ThreadReference.THREAD_STATUS_WAIT); + exitStatus = Consts.TEST_FAILED; + } + + if (ThreadReference.THREAD_STATUS_ZOMBIE != 0) { + log.complain("***wrong value*** : ThreadReference.THREAD_STATUS_ZOMBIE = " + + ThreadReference.THREAD_STATUS_ZOMBIE); + exitStatus = Consts.TEST_FAILED; + } + + + // VirtualMachine + if (VirtualMachine.TRACE_ALL != 16777215) { + log.complain("***wrong value*** : VirtualMachine.TRACE_ALL = " + + VirtualMachine.TRACE_ALL); + exitStatus = Consts.TEST_FAILED; + } + + if (VirtualMachine.TRACE_EVENTS != 4) { + log.complain("***wrong value*** : VirtualMachine.TRACE_EVENTS = " + + VirtualMachine.TRACE_EVENTS); + exitStatus = Consts.TEST_FAILED; + } + + if (VirtualMachine.TRACE_NONE != 0) { + log.complain("***wrong value*** : VirtualMachine.TRACE_NONE = " + + VirtualMachine.TRACE_NONE); + exitStatus = Consts.TEST_FAILED; + } + + if (VirtualMachine.TRACE_OBJREFS != 16) { + log.complain("***wrong value*** : VirtualMachine.TRACE_OBJREFS = " + + VirtualMachine.TRACE_OBJREFS); + exitStatus = Consts.TEST_FAILED; + } + + if (VirtualMachine.TRACE_RECEIVES != 2) { + log.complain("***wrong value*** : VirtualMachine.TRACE_RECEIVES = " + + VirtualMachine.TRACE_RECEIVES); + exitStatus = Consts.TEST_FAILED; + } + + if (VirtualMachine.TRACE_REFTYPES != 8) { + log.complain("***wrong value*** : VirtualMachine.TRACE_REFTYPES = " + + VirtualMachine.TRACE_REFTYPES); + exitStatus = Consts.TEST_FAILED; + } + + if (VirtualMachine.TRACE_SENDS != 1) { + log.complain("***wrong value*** : VirtualMachine.TRACE_SENDS = " + + VirtualMachine.TRACE_SENDS); + exitStatus = Consts.TEST_FAILED; + } + + + if (EventRequest.SUSPEND_ALL != 2) { + log.complain("***wrong value*** : EventRequest.SUSPEND_ALL = " + + EventRequest.SUSPEND_ALL); + exitStatus = Consts.TEST_FAILED; + } + + if (EventRequest.SUSPEND_EVENT_THREAD != 1) { + log.complain("***wrong value*** : EventRequest.SUSPEND_EVENT_THREAD = " + + EventRequest.SUSPEND_EVENT_THREAD); + exitStatus = Consts.TEST_FAILED; + } + + if (EventRequest.SUSPEND_NONE != 0) { + log.complain("***wrong value*** : EventRequest.SUSPEND_NONE = " + + EventRequest.SUSPEND_NONE); + exitStatus = Consts.TEST_FAILED; + } + + + if (StepRequest.STEP_INTO != 1) { + log.complain("***wrong value*** : StepRequest.STEP_INTO = " + + StepRequest.STEP_INTO); + exitStatus = Consts.TEST_FAILED; + } + + if (StepRequest.STEP_LINE != -2) { + log.complain("***wrong value*** : StepRequest.STEP_LINE = " + + StepRequest.STEP_LINE); + exitStatus = Consts.TEST_FAILED; + } + + if (StepRequest.STEP_MIN != -1) { + log.complain("***wrong value*** : StepRequest.STEP_MIN = " + + StepRequest.STEP_MIN); + exitStatus = Consts.TEST_FAILED; + } + + if (StepRequest.STEP_OUT != 3) { + log.complain("***wrong value*** : StepRequest.STEP_OUT = " + + StepRequest.STEP_OUT); + exitStatus = Consts.TEST_FAILED; + } + + if (StepRequest.STEP_OVER != 2) { + log.complain("***wrong value*** : StepRequest.STEP_OVER = " + + StepRequest.STEP_OVER); + exitStatus = Consts.TEST_FAILED; + } + log.display(""); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConstantField/values001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConstantField/values001/TestDescription.java new file mode 100644 index 00000000000..5308a9564a1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ConstantField/values001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ConstantField/values001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * Test checks up static fields of JDI interfaces according to + * specification of them: + * com.sun.jdi.ClassType + * INVOKE_SINGLE_THREADED = 1 + * com.sun.jdi.ObjectReference + * INVOKE_NONVIRTUAL = 2 + * INVOKE_SINGLE_THREADED = 1 + * com.sun.jdi.ThreadReference + * THREAD_STATUS_MONITOR = 3 + * THREAD_STATUS_NOT_STARTED = 5 + * THREAD_STATUS_RUNNING = 1 + * THREAD_STATUS_SLEEPING = 2 + * THREAD_STATUS_UNKNOWN = -1 + * THREAD_STATUS_WAIT = 4 + * THREAD_STATUS_ZOMBIE = 0 + * com.sun.jdi.VirtualMachine + * TRACE_ALL = 16777215 + * TRACE_EVENTS = 4 + * TRACE_NONE = 0 + * TRACE_OBJREFS = 16 + * TRACE_RECEIVES = 2 + * TRACE_REFTYPES = 8 + * TRACE_SENDS = 1 + * com.sun.jdi.request.EventRequest + * SUSPEND_ALL = 2 + * SUSPEND_EVENT_THREAD = 1 + * SUSPEND_NONE = 0 + * com.sun.jdi.request.StepRequest + * STEP_INTO = 1 + * STEP_LINE = -2 + * STEP_MIN = -1 + * STEP_OUT = 3 + * STEP_OVER = 2 + * COMMENTS: + * This test is valid for jdk 1.4.1 or higher because of that + * there was no specifications for earlier versions. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @run main/othervm nsk.jdi.ConstantField.values001 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java new file mode 100644 index 00000000000..71917626d10 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.DoubleType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * DoubleType.
    + *
    + * The test checks that for a mirror of a double value, the casts
    + * from Type to DoubleType and from PrimitiveType to DoubleType
    + * don't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a double field and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class doubletype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/DoubleType/_itself_/doubletype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new doubletype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.DoubleType._itself_.doubletype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......String name = 'db';"); + String name = "db"; + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type(); + log2(" PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + + DoubleType doubleType = null; + try { + log2(" checking up on cast: DoubleType doubleType = (DoubleType) type;"); + doubleType = (DoubleType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + try { + log2(" checking up on cast: DoubleType doubleType = (DoubleType) primitiveType;"); + doubleType = (DoubleType) primitiveType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001/TestDescription.java new file mode 100644 index 00000000000..6d204c5a952 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/DoubleType/_itself_/doubletype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * DoubleType. + * The test checks that for a mirror of a double value the casts + * from Type to DoubleType and from PrimitiveType to DoubleType + * don't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.DoubleType._itself_.doubletype001; + * the debuggee program - nsk.jdi.DoubleType._itself_.doubletype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.DoubleType._itself_.doubletype001 + * nsk.jdi.DoubleType._itself_.doubletype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.DoubleType._itself_.doubletype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001a.java new file mode 100644 index 00000000000..773f8664a4f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.DoubleType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the doubletype001 JDI test. + */ + +public class doubletype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static double db = 0.0d; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001.java new file mode 100644 index 00000000000..a9e67577690 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.DoubleValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + + +public class compareto001 { + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.DoubleValue.compareTo"; + private final static String className = ".compareto001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + private static Value objectValue; + private static List fieldList; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return; + } + + // getting of object to check + Field field = debuggeeClass.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + + objectValue = debuggeeClass.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = debuggeeClass.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = debuggeeClass.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitiveValues = (ArrayReference)arrValue; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + DoubleValue value; + Field fldOtherType; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof DoubleValue) ) { + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (DoubleValue )v1; + + // comparing with debuggee's fields + display("Checking compateTo(Object object) method for DoubleValue: " + value); + + for (int j = 0; j < primitiveValues.length(); j++) { + arrValue = primitiveValues.getValue(j); + + fldOtherType = debuggeeClass.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = debuggeeClass.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + + } + + //--------------------------------------------------------- test specific methods + + + private static boolean PerformComparing(DoubleValue value, Object object ) { + boolean result = true; + + // assertion [ x.compareTo(x) == 0 ] + if (value.compareTo(value) != 0) { + complain("Failed assertion [ x.compareTo(x) == 0 ] for value: " + value.toString()); + result = false; + } + + if (object instanceof DoubleValue) { + DoubleValue doubleObject = (DoubleValue)object; + try { + // assertion [ x.compareTo(y) == 0 <==> x.equals(y) ] + if ( ((value.equals(object)) && (value.compareTo(doubleObject) != 0)) || + (!(value.equals(object)) && (value.compareTo(doubleObject) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (x.equals(y) == true) ] \n\t" + + "where 'x' is DoubleValue: " + value + " and 'y' is DoubleValue : " + doubleObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(doubleObject) + "\n\t" + + "result of (x.equals(y)): " + value.equals(object) ); + result = false; + } + + // assertion [ x.compareTo(y) == 0 <==> y.compareTo(x) == 0 ] + if ( ((value.compareTo(doubleObject) == 0) && (doubleObject.compareTo(value) != 0)) || + ((value.compareTo(doubleObject) != 0) && (doubleObject.compareTo(value) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0) ] \n\t" + + "where 'x' is DoubleValue: " + value + " and 'y' is DoubleValue : " + doubleObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(doubleObject) + "\n\t" + + "result of (y.compareTo(x)): " + doubleObject.compareTo(value) ); + result = false; + } + if (value.compareTo(doubleObject) != 0) { + // assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] + if (value.compareTo(doubleObject) != -(doubleObject.compareTo(value))) { + complain("Failed assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] \n\t" + + "where 'x' is DoubleValue: " + value + " and 'y' is DoubleValue : " + doubleObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(doubleObject) + "\n\t" + + "result of (y.compareTo(x)): " + doubleObject.compareTo(value) ); + result = false; + } + } + + // assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] + if (value.compareTo(doubleObject) > 0) { + DoubleValue lessValue = FindLessDoubleValue(doubleObject); + if (lessValue != null) { + if (value.compareTo(lessValue) <= 0) { + complain("Failed assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] \n\t" + + "where 'x' is DoubleValue: " + value + " , 'y' is DoubleValue : " + doubleObject + " , 'z' is DoubleValue : " + lessValue + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(doubleObject) + "\n\t" + + "result of (y.compareTo(z)): " + doubleObject.compareTo(lessValue) + "\n\t" + + "result of (x.compareTo(z)): " + value.compareTo(lessValue) ); + result = false; + } + } + } + + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "DoubleValue: " + value + " and DoubleValue argument: " + object); + result = false; + } + + } else if (object == null) { + try { + value.compareTo(null); + complain("Does not throw expected NullPointerException when comparing \n\t" + + "DoubleValue: " + value + " and null argument"); + result = false; + } catch (NullPointerException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "DoubleValue: " + value + " and null argument"); + result = false; + } + } else { + try { + value.compareTo((DoubleValue)object); + complain("Does not throw expected ClassCastException when comparing \n\t" + + "DoubleValue: " + value + " and argument: " + object); + result = false; + } catch (ClassCastException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "DoubleValue: " + value + " and argument: " + object); + result = false; + } + } + + return result; + } + + /** + * This function searches the static fieldList - the list of mirrored + * fields of debuggee's compareto001aClassToCheck class. Search is aimed + * to find another DoubleValue field which is less then method's argument via + * compareTo method. + */ + + private static DoubleValue FindLessDoubleValue (DoubleValue currentValue) { + DoubleValue result = null; + + for (int i = 0; i < fieldList.size(); i++ ) { + + Field field = (Field )fieldList.get(i); + DoubleValue newValue = (DoubleValue)((ObjectReference )objectValue).getValue(field); + + if (currentValue.compareTo(newValue) > 0) { + result = newValue; + break; + } + } + return result; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001/TestDescription.java new file mode 100644 index 00000000000..02c0eb19d81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/DoubleValue/compareTo/compareto001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the compareTo(Object o) method of com.sun.jdi.DoubleValue + * interface. This method is inherited from java.lang.Comparable interface. + * The test checks the following assertions which imply from spec for + * Comparable.compareTo(Object o): + * - (x.compareTo(y) == 0) is identical to (x.equals(y) == true); + * - (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0); + * - if (x.compareTo(y) == i) then (y.compareTo(x) == -i); + * - if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0); + * - if an argument is null, then NullPointerException is thrown; + * - if an argument is not of DoubleValue type, then a ClassCastException is thrown. + * where 'x', 'y' and 'z' denote DoubleValue object. + * The debugger program - nsk.jdi.DoubleValue.compareto.compareto001; + * the debuggee program - nsk.jdi.DoubleValue.compareto.compareto001a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * Then the debugger gets a list of double fields of debuggee's object of + * compareto001aClassToCheck type. For every field a mirror of DoubleValue type + * is created and the assertions are checked. A various values for comparison + * are got from values of mirrors of debuggee's static fields. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.DoubleValue.compareTo.compareto001 + * nsk.jdi.DoubleValue.compareTo.compareto001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.DoubleValue.compareTo.compareto001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001a.java new file mode 100644 index 00000000000..7a01a515e4d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/compareTo/compareto001a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.DoubleValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class compareto001a { + + //----------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + static compareto001aClassToCheck testedObj = new compareto001aClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + pipe.println(compareto001.SIGNAL_READY); +// receiveSignal(compareto001.SIGNAL_GO); + + receiveSignal(compareto001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class compareto001aClassToCheck { + public double doubleMAX = Double.MAX_VALUE; + public double double1 = 1; + public double double0 = 0; + public double double_1 = -1; + public double doubleMIN = Double.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001.java new file mode 100644 index 00000000000..4451d9905d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.DoubleValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * DoubleValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.DoubleValue.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static double plus1_1 = +1d;
    + * public static double plus1_2 = +1d;
    + * public static double minus1 = -1d;
    + * public static float float_plus1 = +1f;
    + *
    + * which a debugger mirros as :
    + *
    + * DoubleValue dvplus1_1;
    + * DoubleValue dvplus1_2;
    + * DoubleValue dvminus1;
    + * FloatValue fvplus1;
    + *
    + * the following is true:
    + *
    + * dvplus1_1 == dvplus1_2
    + * dvplus1_1 != dvminus1
    + * dvplus1_1 != fvplus1
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/DoubleValue/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.DoubleValue.equals.equals001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("equals001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fdplus1_1 = execClass.fieldByName("plus1_1"); + Field fdplus1_2 = execClass.fieldByName("plus1_2"); + Field fdminus1 = execClass.fieldByName("minus1"); + Field ffplus1 = execClass.fieldByName("float_plus1"); + + DoubleValue dvplus1_1 = (DoubleValue) execClass.getValue(fdplus1_1); + DoubleValue dvplus1_2 = (DoubleValue) execClass.getValue(fdplus1_2); + DoubleValue dvminus1 = (DoubleValue) execClass.getValue(fdminus1); + FloatValue fvplus1 = (FloatValue) execClass.getValue(ffplus1); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!dvplus1_1.equals(dvplus1_2)) + expresult = 1; + break; + + case 1: if (dvplus1_1.equals(dvminus1)) + expresult = 1; + break; + + case 2: if (dvplus1_1.equals(fvplus1)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..f61f7d89965 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/DoubleValue/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * DoubleValue. + * The test checks up that a result of the method + * com.sun.jdi.DoubleValue.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this DoubleValue for equality. + * Returns: true if the Object is a DoubleValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.DoubleValue.equals.equals001; + * a debuggee program - nsk.jdi.DoubleValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.DoubleValue.equals.equals001 + * nsk.jdi.DoubleValue.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.DoubleValue.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001a.java new file mode 100644 index 00000000000..360d1e57c78 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.DoubleValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001a JDI test. + + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static double pos_inf = Double.POSITIVE_INFINITY; +// public static double pos_zero = 0.0d; +// public static double neg_zero = -0.0d; +// public static double neg_inf = Double.NEGATIVE_INFINITY; + +// public static double pos_largest = Double.MAX_VALUE; +// public static double pos_smallest = Double.MIN_VALUE; +// public static double neg_largest = -Double.MAX_VALUE; +// public static double neg_smallest = -Double.MIN_VALUE; + +// public static double double_nan = Double.NaN; + + public static double plus1_1 = +1.0d; + public static double plus1_2 = +1.0d; + public static double minus1 = -1.0d; + + public static float float_plus1 = +1.0f; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * types and when parameter is null.
    + * Analyse of the method executing is performed by PerformComparing + * method.
    + * First parameter of PerformComparing is static field of testedObj,
    + * which is placed onto debugee's side.
    + * + * Second parameter is got from debugee too:
    + * Debugee has array of boundary values of each primitive type, execTest reads
    + * them and calls PerformComparing for each of them.
    + */ +public class equals002 { + + private final static String prefix = "nsk.jdi.DoubleValue.equals."; + private final static String className = "equals002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static ReferenceType refType; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + execTest(); + debugee.quit(); + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + private static void execTest() { + + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("Class '" + debugeeName + "' not found."); + return; + } + + // getting of object to check + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = refType.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = refType.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + List fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + DoubleValue value; + Field fldOtherType; + String msg; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + log.display(""); + msg = "***" + field; + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof DoubleValue) ) { + msg += " is not DoubleValue (skipped)"; + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (DoubleValue )v1; + + // comparing with debugee's fields + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = refType.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = refType.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static boolean PerformComparing(DoubleValue value, Object object ) { + boolean res = true; + String msg = ""; + try { + if ( value.equals(object) ) { + if ( object instanceof DoubleValue ) { + if ( value.value() == ((PrimitiveValue )object).doubleValue() ) { + msg += "--> " + value + " == " + object; + } else { + msg += "##> " + value + " == " + object; + res = false; + } + } + else { + msg += "##> " + value + " == " + object + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if ( object == null ) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if ( object instanceof DoubleValue ) { + if ( value.value() != ((PrimitiveValue )object).doubleValue() ) { + msg += "--> " + value + " != " + object; + } else { + msg += "##> " + value + " != " + object; + res = false; + } + } + else { + msg += "--> " + value + " != " + object; + } + } + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..c3c549f1d70 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/DoubleValue/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.DoubleValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this DoubleValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is a DoubleValue and if applying "==" to the + * two mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has boundary values of primitive + * types. Also, case when parameter is considered. + * No exceptions are expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.DoubleValue.equals.equals002 + * nsk.jdi.DoubleValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.DoubleValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002a.java new file mode 100644 index 00000000000..b8103b175fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/equals/equals002a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.DoubleValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * equals002a is deugee's part of the test.
    + * It contains the static fields with boundary values for each primitive type.
    + * ClassToCheck delivers values for first parameter of equals.
    + */ +public class equals002a { + + static ClassToCheck testedObj = new ClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class ClassToCheck { + public double doubleMAX = Double.MAX_VALUE; + public double double1 = 1; + public double double0 = 0; + public double double_1 = -1; + public double doubleMIN = Double.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001.java new file mode 100644 index 00000000000..9b4074dd72f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.DoubleValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * DoubleValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.DoubleValue.hashCode()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static double plus1_1 = +1d;
    + * public static double plus1_2 = +1d;
    + * public static double pos_largest = Double.MAX_VALUE;
    + *
    + * which a debugger mirros as :
    + *
    + * DoubleValue dvplus1_1;
    + * DoubleValue dvplus1_2;
    + * DoubleValue dvpos_largest;
    + *
    + * the following is true:
    + *
    + * dvpos_largest.hashCode() == dvpos_largest.hashCode()
    + * dvplus1_1.hashCode() == dvplus1_2.hashCode()
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/DoubleValue/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.DoubleValue.hashCode.hashcode001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("hashcode001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fdplus1_1 = execClass.fieldByName("plus1_1"); + Field fdplus1_2 = execClass.fieldByName("plus1_2"); + Field fdpos_largest = execClass.fieldByName("pos_largest"); + + DoubleValue dvplus1_1 = (DoubleValue) execClass.getValue(fdplus1_1); + DoubleValue dvplus1_2 = (DoubleValue) execClass.getValue(fdplus1_2); + DoubleValue dvpos_largest = + (DoubleValue) execClass.getValue(fdpos_largest); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (dvpos_largest.hashCode() != dvpos_largest.hashCode()) + expresult = 1; + break; + + case 1: if (dvplus1_1.hashCode() != dvplus1_2.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..231fbfc3227 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/DoubleValue/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * DoubleValue. + * The test checks up that a result of the method + * com.sun.jdi.DoubleValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this DoubleValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.DoubleValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.DoubleValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.DoubleValue.hashCode.hashcode001 + * nsk.jdi.DoubleValue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.DoubleValue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..c4994543ad0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/hashCode/hashcode001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.DoubleValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001a JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static double pos_inf = Double.POSITIVE_INFINITY; +// public static double pos_zero = 0.0d; +// public static double neg_zero = -0.0d; +// public static double neg_inf = Double.NEGATIVE_INFINITY; + + public static double pos_largest = Double.MAX_VALUE; +// public static double pos_smallest = Double.MIN_VALUE; +// public static double neg_largest = -Double.MAX_VALUE; +// public static double neg_smallest = -Double.MIN_VALUE; + +// public static double double_nan = Double.NaN; + + public static double plus1_1 = +1.0d; + public static double plus1_2 = +1.0d; +// public static double minus1 = -1.0d; + +// public static float float_plus1 = +1.0f; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * DoubleValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.DoubleValue.value()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static double pos_inf = Double.POSITIVE_INFINITY;
    + * public static double pos_zero = 0.0d;
    + * public static double neg_zero = -0.0d;
    + * public static double neg_inf = Double.NEGATIVE_INFINITY;
    + * public static double pos_largest = Double.MAX_VALUE;
    + * public static double pos_smallest = Double.MIN_VALUE;
    + * public static double neg_largest = -Double.MAX_VALUE;
    + * public static double neg_smallest = -Double.MIN_VALUE;
    + * public static double double_nan = Double.NaN;
    + *
    + * which a debugger mirros as :
    + *
    + * DoubleValue dvpos_inf;
    + * DoubleValue dvpos_zero;
    + * DoubleValue dvneg_zero;
    + * DoubleValue dvneg_inf;
    + * DoubleValue dvpos_largest;
    + * DoubleValue dvpos_smallest;
    + * DoubleValue dvneg_largest;
    + * DoubleValue dvneg_smallest;
    + * DoubleValue dvdouble_nan;
    + *
    + * the following is true:
    + *
    + * dvneg_inf.value() == Double.NEGATIVE_INFINITY
    + * dvneg_largest.value() == -Double.MAX_VALUE
    + * dvneg_smallest.value() == -Double.MIN_VALUE
    + * dvneg_zero.value() == -0.0d
    + * dvpos_zero.value() == 0.0d
    + * dvpos_smallest.value() == Double.MIN_VALUE
    + * dvpos_largest.value() == Double.MAX_VALUE
    + * dvpos_inf.value() == Double.POSITIVE_INFINITY
    + * dvdouble_nan.value() != dvdouble_nan.value()
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/DoubleValue/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.DoubleValue.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("value001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fdneg_inf = execClass.fieldByName("neg_inf"); + Field fdneg_largest = execClass.fieldByName("neg_largest"); + Field fdneg_smallest = execClass.fieldByName("neg_smallest"); + Field fdneg_zero = execClass.fieldByName("neg_zero"); + Field fdpos_zero = execClass.fieldByName("pos_zero"); + Field fdpos_smallest = execClass.fieldByName("pos_smallest"); + Field fdpos_largest = execClass.fieldByName("pos_largest"); + Field fdpos_inf = execClass.fieldByName("pos_inf"); + Field fddouble_nan = execClass.fieldByName("double_nan"); + + DoubleValue dvneg_inf = (DoubleValue) execClass.getValue(fdneg_inf); + DoubleValue dvneg_largest = (DoubleValue) execClass.getValue(fdneg_largest); + DoubleValue dvneg_smallest = (DoubleValue) execClass.getValue(fdneg_smallest); + DoubleValue dvneg_zero = (DoubleValue) execClass.getValue(fdneg_zero); + DoubleValue dvpos_zero = (DoubleValue) execClass.getValue(fdpos_zero); + DoubleValue dvpos_smallest = (DoubleValue) execClass.getValue(fdpos_smallest); + DoubleValue dvpos_largest = (DoubleValue) execClass.getValue(fdpos_largest); + DoubleValue dvpos_inf = (DoubleValue) execClass.getValue(fdpos_inf); + DoubleValue dvdouble_nan = (DoubleValue) execClass.getValue(fddouble_nan); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (dvneg_inf.value() != Double.NEGATIVE_INFINITY) + expresult = 1; + break; + + case 1: if (dvneg_largest.value() != -Double.MAX_VALUE) + expresult = 1; + break; + + case 2: if (dvneg_smallest.value() != -Double.MIN_VALUE) + expresult = 1; + break; + + case 3: if (dvneg_zero.value() != -0.0d) + expresult = 1; + break; + + case 4: if (dvpos_zero.value() != 0.0d) + expresult = 1; + break; + + case 5: if (dvpos_smallest.value() != Double.MIN_VALUE) + expresult = 1; + break; + + case 6: if (dvpos_largest.value() != Double.MAX_VALUE) + expresult = 1; + break; + + case 7: if (dvpos_inf.value() != Double.POSITIVE_INFINITY) + expresult = 1; + break; + + case 8: if ( !(dvdouble_nan.value() != dvdouble_nan.value()) ) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001/TestDescription.java new file mode 100644 index 00000000000..4081400d13f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/DoubleValue/value/value001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * DoubleValue. + * The test checks up that a result of the method + * com.sun.jdi.DoubleValue.value() + * complies with its spec: + * public double value() + * Returns this DoubleValue as a double. + * Returns: the double mirrored by this object. + * The test works as follows: + * A debugger program - nsk.jdi.DoubleValue.value.value001; + * a debuggee program - nsk.jdi.DoubleValue.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.DoubleValue.value.value001 + * nsk.jdi.DoubleValue.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.DoubleValue.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001a.java new file mode 100644 index 00000000000..4e436a9e231 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleValue/value/value001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.DoubleValue.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static double pos_inf = Double.POSITIVE_INFINITY; + public static double pos_zero = 0.0d; + public static double neg_zero = -0.0d; + public static double neg_inf = Double.NEGATIVE_INFINITY; + + public static double pos_largest = Double.MAX_VALUE; + public static double pos_smallest = Double.MIN_VALUE; + public static double neg_largest = -Double.MAX_VALUE; + public static double neg_smallest = -Double.MIN_VALUE; + + public static double double_nan = Double.NaN; + +// public static double plus1_1 = +1.0d; +// public static double plus1_2 = +1.0d; +// public static double minus1 = -1.0d; + +// public static float float_plus1 = +1.0f; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.event.Event. + * A debugger part of + * the test creates several AccessWatchpointRequests, and + * verifies that all appropriate events have been generated by a target + * VM. Then, the debugger removes one request via + * deleteEventRequest() call. Finally, the test checks + * that the event corresponding to the deleted request, are not generated. + */ +public class event001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.Event._itself_.event001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int FLDS_NUM = 3; + static final String COMMAND_RUN[] = { + "run1", "run2", "run3" + }; + static final String DEBUGGEE_FLDS[][] = { + {"byte", "byteFld"}, + {"short", "shortFld"}, + {"int", "intFld"} + }; + private volatile int accFCount[] = { + 0, 0, 0 + }; + private int DEL_NUM = 1; // deleted request number + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile AccessWatchpointRequest awpRequest[]; + private volatile int tot_res = PASSED; + +// for notification a main thread about received events + private Object gotEvent = new Object(); + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new event001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + List fields; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "event001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + if ( !vm.canWatchFieldAccess() ) { + log.display(" TEST CANCELLED due to: vm.canWatchFieldAccess() == false"); + return quitDebuggee(); + } + +// Create testing requests + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null"); + tot_res = FAILED; + return quitDebuggee(); + } + try { + fields = rType.allFields(); + } catch (Exception e) { + log.complain("TEST FAILURE: allFields: " + e); + tot_res = FAILED; + return quitDebuggee(); + } + if (createRequests(erManager, fields) == FAILED) { + tot_res = FAILED; + return quitDebuggee(); + } + +// Create a thread listening JDI events + elThread = new EventListener(); + elThread.setPriority(Thread.NORM_PRIORITY + 2); + synchronized(gotEvent) { + elThread.start(); + +// Check all requested AccessWatchpointRequest events + for (int i=0; icom.sun.jdi.event.Event. + * A debugger part + * of the test creates several AccessWatchpointRequests, and + * then it verifies that appropriate events will be generated by a target + * VM. After that, the debugger removes the list of the event requests via + * deleteEventRequests() call. Finally, the test checks + * that the events which corresponding requests have been deleted, are + * not generated by the target VM. + */ +public class event002 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.Event._itself_.event002t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int FLDS_NUM = 9; // number of debuggee's fields + static final int DEL_REQS = 5; // number of requests to delete + static final String COMMAND_RUN[] = { + "run1", "run2", "run3", "run4", + "run5", "run6", "run7", "run8", "run9" + }; + static final String DEBUGGEE_FLDS[][] = { + {"byte", "byteFld", "DELETE"}, + {"short", "shortFld", "NO"}, + {"int", "intFld", "DELETE"}, + {"long", "longFld", "NO"}, + {"float", "floatFld", "DELETE"}, + {"double", "doubleFld", "DELETE"}, + {"char", "charFld", "NO"}, + {"boolean", "booleanFld", "NO"}, + {"java.lang.String", "strFld", "DELETE"} + }; + private volatile int accFCount[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile AccessWatchpointRequest awpRequest[]; + private List delRequests; // list of requests to delete + private volatile int tot_res = PASSED; + +// for notification a main thread about received events + private Object gotEvent = new Object(); + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new event002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + List fields; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "event002t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + if ( !vm.canWatchFieldAccess() ) { + log.display(" TEST CANCELLED due to: vm.canWatchFieldAccess() == false"); + return quitDebuggee(); + } + +// Create testing requests + delRequests = new ArrayList(); + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null"); + tot_res = FAILED; + return quitDebuggee(); + } + try { + fields = rType.allFields(); + } catch (Exception e) { + log.complain("TEST FAILURE: allFields: caught " + e); + tot_res = FAILED; + return quitDebuggee(); + } + if (createRequests(erManager, fields) == FAILED) { + tot_res = FAILED; + return quitDebuggee(); + } + +// Create a thread listening JDI events + elThread = new EventListener(); + elThread.setPriority(Thread.NORM_PRIORITY + 2); + synchronized(gotEvent) { + elThread.start(); + +// Check all requested AccessWatchpointRequest events + for (int i=0; i 0 && DEBUGGEE_FLDS[i][2].equals("DELETE")) { + log.complain("TEST FAILED: got AccessWatchpointEvent for disabled field " + + DEBUGGEE_FLDS[i][0]); + return FAILED; + } + } + log.display("TEST PASSED: Got no AccessWatchpointEvents for disabled fields"); + + } + return tot_res; + } + + private int createRequests(EventRequestManager erManager, + List fields) { + Field fld = null; + int i = 0; + + awpRequest = + new AccessWatchpointRequest[FLDS_NUM]; + for (i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } + + execTest(); + + int status = debuggee.endDebugee(); + if ( status != Consts.JCK_STATUS_BASE ) { + throw new Failure("UNEXPECTED Debugee's exit status : " + status); + } + display("expected Debugee's exit status : " + status); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + EventRequestManager eventRequestManager = debuggee.VM().eventRequestManager(); + EventRequest eventRequest; + + ReferenceType testedClass = debuggee.classByName(threadClassName); + if ( testedClass == null ) { + throw new Failure("Class '" + threadClassName + "' not found."); + } + + for (int i = 0; i < 11; i++) { + eventRequest = null; + switch (i) { + + case 0: + ThreadReference thread = debuggee.threadByName(threadName); + + display("setting up StepRequest"); + eventRequest = eventRequestManager.createStepRequest + (thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + display("setting up AccessWatchpointRequest"); + eventRequest = eventRequestManager.createAccessWatchpointRequest + (testedClass.fieldByName(fieldName)); + break; + + case 2: + display("setting up ModificationWatchpointRequest"); + eventRequest = eventRequestManager.createModificationWatchpointRequest + (testedClass.fieldByName(fieldName)); + break; + + case 3: + display("setting up ClassPrepareRequest"); + eventRequest = eventRequestManager.createClassPrepareRequest(); + break; + + case 4: + display("setting up ClassUnloadRequest"); + eventRequest = eventRequestManager.createClassUnloadRequest(); + break; + + case 5: + display("setting up MethodEntryRequest"); + eventRequest = eventRequestManager.createMethodEntryRequest(); + break; + + case 6: + display("setting up MethodExitRequest"); + eventRequest = eventRequestManager.createMethodExitRequest(); + break; + + case 7: + display("setting up ThreadDeathRequest"); + eventRequest = eventRequestManager.createThreadDeathRequest(); + break; + + case 8: + display("setting up ThreadStartRequest"); + eventRequest = eventRequestManager.createThreadStartRequest(); + break; + + case 9: + display("setting up ExceptionRequest"); + eventRequest = eventRequestManager.createExceptionRequest( null, true, true ); + break; + + case 10: + display("setting up BreakpointRequest"); + Method method = methodByName(testedClass, methodName); + List locs = null; + try { + locs = method.allLineLocations(); + } catch(AbsentInformationException e) { + throw new Failure("Unexpected AbsentInformationException while getting "); + } + Location location = (Location)locs.get(0); + eventRequest = eventRequestManager.createBreakpointRequest(location); + break; + + default: + throw new Failure("Wrong test case : " + i); + } + + if (eventRequest == null) { + throw new Failure("Cannot create request case : " + i); + } + eventRequest.addCountFilter(1); + eventRequest.enable(); + } + + debuggee.sendSignal(SIGNAL_GO); + + boolean exit = false; + boolean connected = true; + + Event oldEvent = null; + + while (!exit) { + EventSet eventSet = getEventSet(); + EventIterator eventIterator = eventSet.eventIterator(); + + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + + display("Checking equals() method for Event object : " + event); + + if (!event.equals(event)) { + complain("equals method is not reflexive. x.equals(x) returns false for Event object : " + event); + exitStatus = Consts.TEST_FAILED; + } + + if (event != null && event.equals(null)) { + complain("equals(null) returns true for Event object " + event); + exitStatus = Consts.TEST_FAILED; + } + + if (oldEvent != null) { + boolean eq1 = event.equals(oldEvent); + boolean eq2 = oldEvent.equals(event); + if ((!eq1 && eq2) || (eq1 && !eq2)) { + complain("equals() is not symmetric for Event object : " + event + + "\n\t and another one : " + oldEvent); + + exitStatus = Consts.TEST_FAILED; + } + + eq1 = event.equals(oldEvent); + eq2 = event.equals(oldEvent); + if ((!eq1 && eq2) || (eq1 && !eq2)) { + complain("equals() is not consistent for Event object : " + event + + "\n\t and another one : " + oldEvent); + + exitStatus = Consts.TEST_FAILED; + } + } + + if (event instanceof VMDeathEvent) { + connected = true; + } else if (event instanceof VMDisconnectEvent) { + connected = true; + exit = true; + } + oldEvent = event; + } + if (connected) { + eventSet.resume(); + } + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static Method methodByName(ReferenceType refType, String methodName) { + List methodList = refType.methodsByName(methodName); + if (methodList == null) return null; + + Method method = (Method) methodList.get(0); + return method; + } + + private static EventSet getEventSet() { + EventSet eventSet; + try { + eventSet = debuggee.VM().eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for event"); + } + } catch ( Exception e ) { + throw new Failure("Unexpected exception while waiting for event " + e); + } + return eventSet; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..a73cc845a84 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Event/equals/equals001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public equals() method of an implementing class of + * com.sun.jdi.event.Event interface. + * The test checks an assertion cited from spec for equals() method of + * java.lang.Object class: + * The equals method implements an equivalence relation: + * - It is reflexive: for any reference value x, x.equals(x) should return true. + * - It is symmetric: for any reference values x and y, x.equals(y) should return + * true if and only if y.equals(x) returns true. + * - It is consistent: for any reference values x and y, multiple invocations + * of x.equals(y) consistently return true or consistently return false, + * provided no information used in equals comparisons on the object is modified. + * - For any non-null reference value x, x.equals(null) should return false. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for Event + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - resume for these events is skipped in event handling loop + * - method Debugee.endDebugee() is used instead of Debugee.waitFor() + * Test fixed according to test bug: + * 4854711 TEST_BUG: race condition in threads synchronization + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Event.equals.equals001 + * nsk.jdi.Event.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Event.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001a.java new file mode 100644 index 00000000000..23813795186 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/equals/equals001a.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Event.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class equals001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Object lock = new Object(); + static Object wait = new Object(); + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + Thread thread1 = new equals001aThread("thread1"); + + synchronized (lock) { + synchronized(wait) { + thread1.start(); + try { + wait.wait(); + pipe.println(equals001.SIGNAL_READY); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for notification"); + } + } + receiveSignal(equals001.SIGNAL_GO); + } + try { + thread1.join(); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for thread1 join"); + } + +// receiveSignal(equals001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class equals001aThread extends Thread { + + String name; + + public equals001aThread (String name) { + super(name); + this.name = name; + } + + public void run() { + synchronized (equals001a.wait) { + equals001a.wait.notifyAll(); + } + synchronized (equals001a.lock) { + } + + foo(); + + equals001aThread1 thread2 = new equals001aThread1(); + thread2.start(); + + try { + throw new Exception(); + } catch (Exception e) { + } + + try { + thread2.join(); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for thread2 join"); + } + } + + void foo () { + name = "afterFoo"; + equals001a.display("thread1's name == " + name); + } +} + +class equals001aThread1 extends Thread { + public void run() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001.java new file mode 100644 index 00000000000..06d0ed11f20 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Event.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class hashcode001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Event.hashCode."; + private final static String className = "hashcode001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String threadClassName = prefix + "hashcode001aThread"; + private final static String threadName = "thread1"; + private final static String methodName = "foo"; + private final static String fieldName = "name"; + private final static int brkpLineNumber = 145; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } + + execTest(); + + int status = debuggee.endDebugee(); + if ( status != Consts.JCK_STATUS_BASE ) { + throw new Failure("UNEXPECTED Debugee's exit status : " + status); + } + display("expected Debugee's exit status : " + status); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + EventRequestManager eventRequestManager = debuggee.VM().eventRequestManager(); + EventRequest eventRequest; + + ReferenceType testedClass = debuggee.classByName(threadClassName); + if ( testedClass == null ) { + throw new Failure("Class '" + threadClassName + "' not found."); + } + + for (int i = 0; i < 11; i++) { + eventRequest = null; + switch (i) { + + case 0: + ThreadReference thread = debuggee.threadByName(threadName); + + display(".....setting up StepRequest"); + eventRequest = eventRequestManager.createStepRequest + (thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + display(".....setting up AccessWatchpointRequest"); + eventRequest = eventRequestManager.createAccessWatchpointRequest + (testedClass.fieldByName(fieldName)); + break; + + case 2: + display(".....setting up ModificationWatchpointRequest"); + eventRequest = eventRequestManager.createModificationWatchpointRequest + (testedClass.fieldByName(fieldName)); + break; + + case 3: + display(".....setting up ClassPrepareRequest"); + eventRequest = eventRequestManager.createClassPrepareRequest(); + break; + + case 4: + display(".....setting up ClassUnloadRequest"); + eventRequest = eventRequestManager.createClassUnloadRequest(); + break; + + case 5: + display(".....setting up MethodEntryRequest"); + eventRequest = eventRequestManager.createMethodEntryRequest(); + break; + + case 6: + display(".....setting up MethodExitRequest"); + eventRequest = eventRequestManager.createMethodExitRequest(); + break; + + case 7: + display(".....setting up ThreadDeathRequest"); + eventRequest = eventRequestManager.createThreadDeathRequest(); + break; + + case 8: + display(".....setting up ThreadStartRequest"); + eventRequest = eventRequestManager.createThreadStartRequest(); + break; + + case 9: + display(".....setting up ExceptionRequest"); + eventRequest = eventRequestManager.createExceptionRequest( null, true, true ); + break; + + case 10: + display(".....setting up BreakpointRequest"); + eventRequest = debuggee.makeBreakpoint(testedClass, methodName, brkpLineNumber); + break; + + default: + throw new Failure("Wrong test case : " + i); + } + + if (eventRequest == null) { + throw new Failure("Cannot create request case : " + i); + } + eventRequest.addCountFilter(1); + eventRequest.enable(); + } + + debuggee.sendSignal(SIGNAL_GO); + + display("Checking hashCode() method for Event objects"); + + boolean exit = false; + boolean connected = true; + while (!exit) { + EventSet eventSet = getEventSet(); + EventIterator eventIterator = eventSet.eventIterator(); + + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + String eventName = null; + + if (event instanceof VMDeathEvent) { + eventName = "VMDeathEvent"; + connected = false; + } else if (event instanceof VMDisconnectEvent) { + eventName = "VMDisconnectEvent"; + connected = false; + exit = true; + } else { + eventName = "" + event; + } + + try { + int hCode = event.hashCode(); + display("hashCode() returns " + hCode + " for Event object : " + eventName); + + if (hCode == 0) { + complain("hashCode() returns 0 for Event object " + eventName); + exitStatus = Consts.TEST_FAILED; + } + + int hCode1 = event.hashCode(); + if (hCode != hCode1) { + complain("hashCode() is not consistent for Event object " + eventName + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + } catch (VMDisconnectedException e) { + // skip error message if already disconnected + if (connected) { + throw new Failure("Caught unexpected VMDisconnectedException:\n\t" + e); + } + } + } + if (connected) { + eventSet.resume(); + } + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static EventSet getEventSet() { + EventSet eventSet; + try { + eventSet = debuggee.VM().eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for event"); + } + } catch ( Exception e ) { + throw new Failure("Unexpected exception while waiting for event " + e); + } + return eventSet; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..26a214d859a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Event/hashCode/hashcode001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public hashCode() method of an implementing class of + * com.sun.jdi.event.Event interface. + * The test checks an assertion cited from spec for hashCode() method of + * java.lang.Object class: + * The general contract of hashCode is: + * - Whenever it is invoked on the same object more than once during + * an execution of a Java application, the hashCode method must + * consistently return the same integer, provided no information used + * in equals comparisons on the object is modified. + * ... + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for Event + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - resume for these events is skipped in event handling loop + * - method Debugee.endDebugee() is used instead of Debugee.waitFor() + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * Test fixed according to test bug: + * 4783196 TEST_BUG: hashcode001 incorrectly handles VMDisconnectEvent + * - eliminating printing VMDeathEvent and VMDisconnectEvent + * - ignoring VMDisconnectedException if thrown for these events + * while testinging hashcode() method + * Test fixed according to test bug: + * 4854711 TEST_BUG: race condition in threads synchronization + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Event.hashCode.hashcode001 + * nsk.jdi.Event.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Event.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001a.java new file mode 100644 index 00000000000..4e04d991048 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/hashCode/hashcode001a.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Event.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * The debugged application of the test. + */ +public class hashcode001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Object lock = new Object(); + static Object wait = new Object(); + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + Thread thread1 = new hashcode001aThread("thread1"); + + synchronized (lock) { + synchronized(wait) { + thread1.start(); + try { + wait.wait(); + pipe.println(hashcode001.SIGNAL_READY); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for notification"); + } + } + receiveSignal(hashcode001.SIGNAL_GO); + } + try { + thread1.join(); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for thread1 join"); + } + +// receiveSignal(hashcode001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class hashcode001aThread extends Thread { + + String name; + + public hashcode001aThread (String name) { + super(name); + this.name = name; + } + + public void run() { + synchronized (hashcode001a.wait) { + hashcode001a.wait.notifyAll(); + } + synchronized (hashcode001a.lock) { + } + + foo(); + + hashcode001aThread1 thread2 = new hashcode001aThread1(); + thread2.start(); + + try { + throw new Exception(); + } catch (Exception e) { + } + + try { + thread2.join(); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for thread2 join"); + } + } + + void foo () { + name = "afterFoo"; // hashcode001.brkpLineNumber + hashcode001a.display("thread1's name == " + name); + } +} + +class hashcode001aThread1 extends Thread { + public void run() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java new file mode 100644 index 00000000000..dd484351ccf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java @@ -0,0 +1,963 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Event.request; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Event.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.Event.request()
    + * complies with its spec.
    + *
    + * The test checks that for all Event objects,
    + * except for ClassUnloadEvent, the method returns
    + * either the EventRequest that requested this event
    + * or null if event does not have a corresponding request.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it saves its EventSet into
    + * a special array and makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger saves its EVENTSet into the array and
    + * sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase the debugger and the debuggee perform the following.
    + * - The debugger creates ThreadStartRequest, ThreadDeathRequest, and
    + * an extra VMDeathRequest, resumes the debuggee, and
    + * waits for corresponding ThreadStartEvent and ThreadDeathEvent.
    + * - The debuggee creates new thread, named "thread2",
    + * whose running creates the above events.
    + * - Upon getting the events, the debugger saves their sets in the array,
    + * resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a number of threads, one for each
    + * following event: AccessWatchpoint, ModificationWatchpoint,
    + * MethodEntry, MethodExit, Step, Exception, and Breakpoint,
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointForCommunication, the debugger
    + * gets ThreadReferences mirroring all tested threads in the debuggee,
    + * sets up Requests within them to get EventSETS to check up on,
    + * resumes the debuggee, waits for events, and upon getting them,
    + * saves its EventSets into the array.
    + *
    + * In third phase,at the end
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and ends.
    + * The debugger waits for VMDeathEvents and VMDisconnectEvents, and
    + * upon getting them, saves their EventSets into the array.
    + * Finally, the debugger, using the array of EventSets,
    + * compares Requests from Events to ones set up.
    + * If any mismatch, the test FAILED.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + */ + +public class request001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Event/request/request001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new request001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Event.request.request001a"; + + private String testedClassName = + "nsk.jdi.Event.request.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + + // Event #: + // 0-6 : AccessWatchpoint, ModificationWatchpoint, Breakpoint, Exception, + // MethodEntry, MethodExit, Step + // 7-8 : ClassPrepare, ClassUnload + // 9-10 : ThreadDeath, ThreadStart + // 11-13 : VMDeath, VMDisconnect, VMStart + + EventSet eventSets[] = new EventSet [14]; + EventRequest eRequests[] = new EventRequest[14]; + + int eventFlags[] = { 0,0,0,0, 0,0,0,0, 3,0,0,0, 1,1 }; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugeeNoWait(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugeeNoWait(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + log2("waiting for VMStartEvent"); + getEventSet(); +// + eventSets[13] = eventSet; + if (eventIterator.nextEvent() instanceof VMStartEvent) { + log2("VMStartEvent received; test begins"); + + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + eventSets[11] = eventSet; + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); +// + eventSets[12] = eventSet; + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + check(); + return 0; + } else { + log3("ERROR: first event is not the VMStartEvent"); + return 1; + } + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + log2("......setting up ClassPrepareRequest"); + eRequests[7] = cpRequest; + + cpRequest.enable(); + vm.resume(); + + getEventSet(); + eventSets[7] = eventSet; + + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + { + log2("...... setting up VMDeathRequest"); + if (vm.canRequestVMDeathEvent()) { + VMDeathRequest vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", "VMDeathRequest"); + vmdr.setSuspendPolicy(EventRequest.SUSPEND_NONE); + vmdr.enable(); + eRequests[11] = vmdr; + } else { + eventFlags[11] = 2; + } + + log2("......setting up ThreadStartRequest"); + ThreadStartRequest tsr = eventRManager.createThreadStartRequest(); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tsr.putProperty("number", "ThreadStartRequest"); + tsr.enable(); + + eRequests[10] = tsr; + + log2("......setting up ThreadDeathRequest"); + ThreadDeathRequest tdr = eventRManager.createThreadDeathRequest(); + tdr.addCountFilter(1); + tdr.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tsr.putProperty("number", "ThreadDeathRequest"); + tdr.enable(); + + eRequests[9] = tdr; + + log2("......vm.resume();"); + vm.resume(); + + log2("......waiting for ThreadStartEvent"); + getEventSet(); + eventSets[10] = eventSet; + + Event receivedEvent = eventIterator.nextEvent(); + if ( !(receivedEvent instanceof ThreadStartEvent) ) { + testExitCode = FAILED; + log3("ERROR: new event is not ThreadStartEvent: " + receivedEvent); + return; + } + tsr.disable(); + + log2("......vm.resume();"); + vm.resume(); + + log2("......waiting for ThreadDeathEvent"); + getEventSet(); + eventSets[9] = eventSet; + receivedEvent = eventIterator.nextEvent(); + if ( !(receivedEvent instanceof ThreadDeathEvent) ) { + testExitCode = FAILED; + log3("ERROR: new event is not ThreadDeathEvent: " + receivedEvent); + return; + } + tdr.disable(); + } + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String bpLineName = "breakpointLine"; + String bpMethodName = "method"; + String awFieldName = "awFieldName"; + String mwFieldName = "mwFieldName"; + + String namesArray = "threadNames"; + + String threadNames[] = { + "awThread" , + "mwThread" , + "bpThread" , + "excThread" , + "menThread" , + "mexThread" , + "stThread" + }; + + int flags = 0; + + ThreadReference eventThreads[] = new ThreadReference[threadNames.length]; + + + List allThreads = vm.allThreads(); + + log2("......getting: ArrayReference namesRef = (ArrayReference) debuggeeClass.getValue(debuggeeClass.fieldByName(namesArray));"); + ArrayReference namesRef = (ArrayReference) + debuggeeClass.getValue(debuggeeClass.fieldByName(namesArray)); + log2(" namesRef.length() == " + namesRef.length()); + + log2("......getting and checking up on debuggee threads' names"); + for (int n1 = 0; n1 < namesRef.length(); n1++) { + + log2(" String name = ((StringReference) namesRef.getValue(n1)).value();"); + String name = ((StringReference) namesRef.getValue(n1)).value(); + + label0: { + for (int n2 = 0; n2 < threadNames.length; n2++) { + + if (name.equals(threadNames[n2])) { + ListIterator li = allThreads.listIterator(); + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) { + eventThreads[n1] = thread; + break; + } + } + break label0; + } + } + testExitCode = FAILED; + log3("ERROR: no thread found in the debuggee : " + name); + } + } + if (testExitCode == FAILED) + break; + + + log2("......ReferenceType testClass = (ReferenceType) (vm.classesByName(testedClassName)).get(0);"); + ReferenceType testClass = (ReferenceType) (vm.classesByName(testedClassName)).get(0); + + log2("......setting up Requests"); + for ( int n3 = 0; n3 < namesRef.length(); n3++) { + switch (n3) { + case 0: + if (vm.canWatchFieldAccess()) { + String awName = ( (StringReference) testClass.getValue( + testClass.fieldByName(awFieldName))).value(); + eRequests[n3] = settingAccessWatchpoint(eventThreads[n3], + testClass, awName, threadNames[n3]); + eRequests[n3].enable(); + flags |= 1; + } + break; + + case 1: + if (vm.canWatchFieldModification() ) { + String mwName = ( (StringReference) testClass.getValue( + testClass.fieldByName(mwFieldName))).value(); + eRequests[n3] = settingModificationWatchpoint(eventThreads[n3], + testClass, mwName, threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<1; + } + break; + + case 2: + eRequests[n3] = settingBreakpoint(eventThreads[n3], testClass, + bpMethodName, bpLineName, threadNames[n3]); + eRequests[n3].setSuspendPolicy( EventRequest.SUSPEND_NONE); + eRequests[n3].enable(); + flags |= 1<<2; + break; + + case 3: + eRequests[n3] = settingException(eventThreads[n3], debuggeeClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<3; + break; + + case 4: + eRequests[n3] = settingMethodEntry(eventThreads[n3], testClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<4; + break; + + case 5: + eRequests[n3] = settingMethodExit(eventThreads[n3], testClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<5; + break; + + case 6: + eRequests[n3] = settingStep(eventThreads[n3], threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<6; + break; + + default: + throw new JDITestRuntimeException("** default case while prepareing requests**"); + } + } + + log2(":::::::::vm.resume();"); + vm.resume(); + + Event event1 = null; + int flagsCopy = flags; + String eName = null; + int index = 0; + + log2("......getting and checking up on Events"); + for (int n4 = 0; n4 < namesRef.length(); n4++) { + int flag; + + getEventSet(); + event1 = eventIterator.nextEvent(); + + if (event1 instanceof AccessWatchpointEvent) { + index = 0; + } else if (event1 instanceof ModificationWatchpointEvent ) { + index = 1; + } else if (event1 instanceof BreakpointEvent ) { + index = 2; + } else if (event1 instanceof ExceptionEvent ) { + index = 3; + } else if (event1 instanceof MethodEntryEvent ) { + index = 4; + } else if (event1 instanceof MethodExitEvent ) { + index = 5; + } else if (event1 instanceof StepEvent ) { + index = 6; + } else { + log3("ERROR: else clause in detecting type of event1"); + testExitCode = FAILED; + } + + flag = 1 << index; + if ((flagsCopy & flag) == 0) { + log3("ERROR: event duplication: " + eName); + testExitCode = FAILED; + } else { + flagsCopy ^= flag; + flags |= flag; + } + + eventSets[index] = eventSet; + } + + if (testExitCode == FAILED) + break; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest settingAccessWatchpoint ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + String property) + throws JDITestRuntimeException { + + log2("......setting up AccessWatchpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; fieldName: " + fieldName); + + AccessWatchpointRequest awRequest = null; + try { + Field field = testedClass.fieldByName(fieldName); + awRequest = eventRManager.createAccessWatchpointRequest(field); + awRequest.putProperty("number", property); + awRequest.addThreadFilter(thread); + awRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpoint() : " + e); + log3(" AN ACCESSWATCHPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up an AccessWatchpoint **"); + } + + log2(" an AccessWatchpoint has been set up"); + return awRequest; + } + + private ModificationWatchpointRequest settingModificationWatchpoint ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + String property) + throws JDITestRuntimeException { + + log2("......setting up ModificationWatchpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; fieldName: " + fieldName); + + ModificationWatchpointRequest mwRequest = null; + try { + Field field = testedClass.fieldByName(fieldName); + mwRequest = eventRManager.createModificationWatchpointRequest(field); + mwRequest.putProperty("number", property); + mwRequest.addThreadFilter(thread); + mwRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpoint() : " + e); + log3(" AN ModificationWATCHPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up an AccessWatchpoint **"); + } + + log2(" a ModificationWatchpoint has been set up"); + return mwRequest; + } + + private MethodEntryRequest settingMethodEntry ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up MethodEntry:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + MethodEntryRequest menRequest = null; + try { + menRequest = eventRManager.createMethodEntryRequest(); + menRequest.putProperty("number", property); + menRequest.addThreadFilter(thread); + menRequest.addClassFilter(testedClass); + menRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntry() : " + e); + log3(" A MethodEntry HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a MethodEntry **"); + } + + log2(" a MethodEntry has been set up"); + return menRequest; + } + + private MethodExitRequest settingMethodExit ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up MethodExit:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + MethodExitRequest mexRequest = null; + try { + mexRequest = eventRManager.createMethodExitRequest(); + mexRequest.putProperty("number", property); + mexRequest.addThreadFilter(thread); + mexRequest.addClassFilter(testedClass); + mexRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExit() : " + e); + log3(" A MethodExit HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a MethodExit **"); + } + + log2(" a MethodExit has been set up"); + return mexRequest; + } + + private StepRequest settingStep ( ThreadReference thread, String property) + throws JDITestRuntimeException { + + log2("......setting up Step:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest stRequest = null; + try { + stRequest = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); + stRequest.putProperty("number", property); + stRequest.addCountFilter(1); + stRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStep() : " + e); + log3(" A Step HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a Step **"); + } + + log2(" a Step has been set up"); + return stRequest; + } + + + private ExceptionRequest settingException ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up Exception:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + ExceptionRequest excRequest = null; + try { + excRequest = eventRManager.createExceptionRequest(null, true, true); + excRequest.putProperty("number", property); + excRequest.addThreadFilter(thread); + excRequest.addClassFilter(testedClass); + excRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingException() : " + e); + log3(" A Exception HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a Exception **"); + } + + log2(" a Exception has been set up"); + return excRequest; + } + + private void check() { + + EventSet evSet = null; + EventIterator evI = null; + EventRequest eR = null; + + log2("......performing the check;"); + for (int k = 0; k < eventFlags.length; k++) { + + switch (eventFlags[k]) { + + case 0: + evSet = eventSets[k]; + evI = evSet.eventIterator(); + if (eRequests[k].equals(evI.nextEvent().request())) + break; + testExitCode = FAILED; + log3("ERROR: eventRequest is not equal to event.request() : k == " + k); + break; + + + case 1: + evSet = eventSets[k]; + evI = evSet.eventIterator(); + if (evI.nextEvent().request() == null) + break; + testExitCode = FAILED; + log3("ERROR: event.request() != null : k == " + k); + break; + + case 2: + evSet = eventSets[k]; + evI = evSet.eventIterator(); + try { + eR = evI.nextEvent().request(); + if (eR == null) { + if ( !eRequests[k].equals(evI.nextEvent().request()) ) { + testExitCode = FAILED; + log3("ERROR: eventRequest is not equal to event.request() : k == " + k); + } + } else { + if ( !eRequests[k].equals(eR) ) { + testExitCode = FAILED; + log3("ERROR: eventRequest is not equal to event.request() : k == " + k); + } else if (evI.nextEvent().request() != null) { + testExitCode = FAILED; + log3("ERROR: eventRequest != null : k == " + k); + } + } + } catch ( Exception e ) { + log3("ERROR: Unexpected Exception : " + e + " :: k == " + k); + testExitCode = FAILED; + } + break; + + case 3: + break; + + default: + log3("ERROR: unexpected default case"); + testExitCode = FAILED; + throw new JDITestRuntimeException("** FAILURE within check() **"); + } + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001/TestDescription.java new file mode 100644 index 00000000000..d584f6f72ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Event/request/request001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Event. + * The test checks up that a result of the method + * com.sun.jdi.Event.request() + * complies with its spec: + * public EventRequest request() + * Returns: The EventRequest that requested this event. + * Some events (eg. VMDeathEvent) may not have a corresponding + * request and thus will return null. + * Cases to check don't include only ClassUnloadEvent. + * The test works as follows: + * The debugger program - nsk.jdi.Event.request.request001; + * the debuggee program - nsk.jdi.Event.request.request001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Fixed due to the bug 4528893. + * Test fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - binder.bindToDebugeeNoWait() is used to prevent Binder from + * handling VMStartEvent + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Event.request.request001 + * nsk.jdi.Event.request.request001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Event.request.request001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001a.java new file mode 100644 index 00000000000..ee7ebdac432 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001a.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Event.request; + +import nsk.share.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the request001 JDI test. + */ + +public class request001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass tcObject = new TestClass(); + + static String threadNames[] = { + "awThread", "mwThread", "bpThread", "excThread", + "menThread", "mexThread", "stThread" + }; + + static int threadsN = threadNames.length; + + static Thread threads[] = new Thread[threadsN]; + + static Thread thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread2 = new Thread3request001a("thread2"); + threadStart(thread2); + try { + // we should wait here for thread2 completion (see 6671428) + thread2.join(); + } catch (InterruptedException e) { + logErr("ERROR: unexpected exception: " + e); + exitCode = FAILED; + break ; + } + + for (int n1 = 0; n1 < threadsN; n1++) { + if (n1 < threadsN-1) + threads[n1] = new Thread1request001a(threadNames[n1]); + else + threads[n1] = new Thread2request001a(threadNames[n1]); + } + log1(" threads has been created"); + + synchronized (lockingObject2) { + log1(" loop: threadStart(threads[n2])"); + for (int n2 = 0; n2 < threadsN; n2++) + if ( threadStart(threads[n2]) != PASSED ) + break label0; + + log1(" methodForCommunication();"); + methodForCommunication(); + } + + for (int n2 = 0; n2 < threadsN; n2++) { + synchronized (locks[n2]) { + log1(" synchronized (locks[n2]) : n2 == " + n2); + } + } + + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + public static void nullMethod() { + throw new NullPointerException("test"); + } + + static Object lockingObject2 = new Object(); + static Object locks[] = new Object[threadsN]; + + static volatile int n = 0; + + static class Thread1request001a extends Thread { + + int threadIndex; + + public Thread1request001a(String threadName) { + super(threadName); + threadIndex = n; + locks[threadIndex] = new Object(); + n++; + } + + public void run() { + log3(" 'run': enter :: threadIndex == " + threadIndex); + + synchronized (locks[threadIndex]) { + log3("enter synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log3(" 'run': exit synchronized (waitnotifyObj)"); + + synchronized (lockingObject2) { + TestClass.method(); + } + log3("exit synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + } + return; + } + + } + + static class Thread2request001a extends Thread { + + int threadIndex; + + public Thread2request001a(String threadName) { + super(threadName); + threadIndex = n; + locks[threadIndex] = new Object(); + n++; + } + + public void run() { + log3(" 'run': enter :: threadIndex == " + threadIndex); + + synchronized (locks[threadIndex]) { + log3("enter synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + m1(); + log3("exit synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + } + return; + } + + private void m1() { + synchronized (lockingObject2) { + log3(" 'm1': enter"); + + log3(" 'm1': exit"); + } + } + + } + + static class Thread3request001a extends Thread { + + String tName = null; + + public Thread3request001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log3(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log3(" 'run': exit :: threadName == " + tName); + } + } + + + public static void log3(String str) { + log1(Thread.currentThread().getName() + " : " + str); + } + +} + +class TestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 += 1; + var3 += 1; + var2 = var3; + try { + request001a.nullMethod(); + } catch ( NullPointerException e ) { + request001a.log3(" NullPointerException : " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java new file mode 100644 index 00000000000..d82d4037c56 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java @@ -0,0 +1,938 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventIterator.nextEvent; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventIterator.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventIterator.nextEvent()
    + * complies with its spec.
    + *
    + * For each type of Events except for ClassUnloadEvent,
    + * the cases to check are as follows:
    + * - the method returns Event object if there is an Event to return;
    + * - NoSuchElementException is thrown if no more events to return;
    + * - doesn't throw other Exceptions.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it saves its EventSet into
    + * a special array and makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger saves its EventSet into the array and
    + * sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase the debugger and the debuggee perform the following.
    + * - The debugger creates ThreadStartRequest and ThreadDeathRequest,
    + * resumes the debuggee, and
    + * waits for corresponding ThreadStartEvent and ThreadDeathEvent.
    + * - The debuggee creates new thread, named "thread2",
    + * whose running creates the above events.
    + * - Upon getting the events, the debugger saves their sets in the array,
    + * resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a number of threads, one for each
    + * following event: AccessWatchpoint, ModificationWatchpoint,
    + * MethodEntry, MethodExit, Step, Exception, and Breakpoint,
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointForCommunication, the debugger
    + * gets ThreadReferences mirroring all tested threads in the debuggee,
    + * sets up Requests within them to get EventSets to check up on,
    + * resumes the debuggee, waits for events, and upon getting them,
    + * saves its EventSets into the array.
    + *
    + * In third phase,at the end
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and ends.
    + * The debugger waits for VMDeathEvent and VMDisconnectEvent, and
    + * upon getting them, saves their EventSets into the array.
    + * Finally, the debugger, using the array of EventSets,
    + * checks up on their EventIterators.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + */ + +public class nextevent001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventIterator/nextEvent/nextevent001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new nextevent001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventIterator.nextEvent.nextevent001a"; + + private String testedClassName = + "nsk.jdi.EventIterator.nextEvent.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + // Event #: + // 0-6 : AccessWatchpoint, ModificationWatchpoint, Breakpoint, Exception, + // MethodEntry, MethodExit, Step + // 7-8 : ClassPrepare, ClassUnload + // 9-10 : ThreadDeath, ThreadStart + // 11-13 : VMDeath, VMDisconnect, VMStart + + EventSet eventSets[] = new EventSet [14]; + EventRequest eRequests[] = new EventRequest[14]; + + int eventFlags[] = { 0,0,0,0, 0,0,0,0, 3,0,0,0, 1,1 }; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugeeNoWait(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugeeNoWait(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + log2("waiting for VMStartEvent"); + getEventSet(); +// + eventSets[13] = eventSet; + if (eventIterator.nextEvent() instanceof VMStartEvent) { + log2("VMStartEvent received; test begins"); + + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + eventSets[11] = eventSet; + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); +// + eventSets[12] = eventSet; + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + check(); + return 0; + } else { + log3("ERROR: first event is not the VMStartEvent"); + return 1; + } + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + log2("......setting up ClassPrepareRequest"); + eRequests[7] = cpRequest; + + cpRequest.enable(); + vm.resume(); + + getEventSet(); + eventSets[7] = eventSet; + + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + { + log2("......setting up ThreadStartRequest"); + ThreadStartRequest tsr = eventRManager.createThreadStartRequest(); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tsr.putProperty("number", "ThreadStartRequest"); + tsr.enable(); + + eRequests[10] = tsr; + + log2("......setting up ThreadDeathRequest"); + ThreadDeathRequest tdr = eventRManager.createThreadDeathRequest(); + tdr.addCountFilter(1); + tdr.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tsr.putProperty("number", "ThreadDeathRequest"); + tdr.enable(); + + eRequests[9] = tdr; + + log2("......vm.resume();"); + vm.resume(); + + log2("......waiting for ThreadStartEvent"); + getEventSet(); + eventSets[10] = eventSet; + + Event receivedEvent = eventIterator.nextEvent(); + if ( !(receivedEvent instanceof ThreadStartEvent) ) { + testExitCode = FAILED; + log3("ERROR: new event is not ThreadStartEvent: " + receivedEvent); + return; + } + tsr.disable(); + + log2("......vm.resume();"); + vm.resume(); + + log2("......waiting for ThreadDeathEvent"); + getEventSet(); + eventSets[9] = eventSet; + receivedEvent = eventIterator.nextEvent(); + if ( !(receivedEvent instanceof ThreadDeathEvent) ) { + testExitCode = FAILED; + log3("ERROR: new event is not ThreadDeathEvent: " + receivedEvent); + return; + } + tdr.disable(); + } + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String bpLineName = "breakpointLine"; + String bpMethodName = "method"; + String awFieldName = "awFieldName"; + String mwFieldName = "mwFieldName"; + + String namesArray = "threadNames"; + + String threadNames[] = { + "awThread" , + "mwThread" , + "bpThread" , + "excThread" , + "menThread" , + "mexThread" , + "stThread" + }; + + int flags = 0; + + ThreadReference eventThreads[] = new ThreadReference[threadNames.length]; + + + List allThreads = vm.allThreads(); + + log2("......getting: ArrayReference namesRef = (ArrayReference) debuggeeClass.getValue(debuggeeClass.fieldByName(namesArray));"); + ArrayReference namesRef = (ArrayReference) + debuggeeClass.getValue(debuggeeClass.fieldByName(namesArray)); + log2(" namesRef.length() == " + namesRef.length()); + + log2("......getting and chcking up on debuggee threads' names"); + for (int n1 = 0; n1 < namesRef.length(); n1++) { + + log2(" String name = ((StringReference) namesRef.getValue(n1)).value();"); + String name = ((StringReference) namesRef.getValue(n1)).value(); + + label0: { + for (int n2 = 0; n2 < threadNames.length; n2++) { + + if (name.equals(threadNames[n2])) { + ListIterator li = allThreads.listIterator(); + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) { + eventThreads[n1] = thread; + break; + } + } + break label0; + } + } + testExitCode = FAILED; + log3("ERROR: no thread found in the debuggee : " + name); + } + } + if (testExitCode == FAILED) + break; + + + log2("......ReferenceType testClass = (ReferenceType) (vm.classesByName(testedClassName)).get(0);"); + ReferenceType testClass = (ReferenceType) (vm.classesByName(testedClassName)).get(0); + + log2("......setting up Requests"); + for ( int n3 = 0; n3 < namesRef.length(); n3++) { + switch (n3) { + case 0: + if (vm.canWatchFieldAccess()) { + String awName = ( (StringReference) testClass.getValue( + testClass.fieldByName(awFieldName))).value(); + eRequests[n3] = settingAccessWatchpoint(eventThreads[n3], + testClass, awName, threadNames[n3]); + eRequests[n3].enable(); + flags |= 1; + } + break; + + case 1: + if (vm.canWatchFieldModification() ) { + String mwName = ( (StringReference) testClass.getValue( + testClass.fieldByName(mwFieldName))).value(); + eRequests[n3] = settingModificationWatchpoint(eventThreads[n3], + testClass, mwName, threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<1; + } + break; + + case 2: + eRequests[n3] = settingBreakpoint(eventThreads[n3], testClass, + bpMethodName, bpLineName, threadNames[n3]); + eRequests[n3].setSuspendPolicy( EventRequest.SUSPEND_NONE); + eRequests[n3].enable(); + flags |= 1<<2; + break; + + case 3: + eRequests[n3] = settingException(eventThreads[n3], debuggeeClass, //testClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<3; + break; + + case 4: + eRequests[n3] = settingMethodEntry(eventThreads[n3], testClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<4; + break; + + case 5: + eRequests[n3] = settingMethodExit(eventThreads[n3], testClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<5; + break; + + case 6: + eRequests[n3] = settingStep(eventThreads[n3], threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<6; + break; + + default: + throw new JDITestRuntimeException("** default case while prepareing requests**"); + } + } + + log2(":::::::::vm.resume();"); + vm.resume(); + + Event event1 = null; + int flagsCopy = flags; + String eName = null; + int index = 0; + + log2("......getting and checking up on Events"); + for (int n4 = 0; n4 < namesRef.length(); n4++) { + int flag; + + getEventSet(); + event1 = eventIterator.nextEvent(); + + if (event1 instanceof AccessWatchpointEvent) { + index = 0; + } else if (event1 instanceof ModificationWatchpointEvent ) { + index = 1; + } else if (event1 instanceof BreakpointEvent ) { + index = 2; + } else if (event1 instanceof ExceptionEvent ) { + index = 3; + } else if (event1 instanceof MethodEntryEvent ) { + index = 4; + } else if (event1 instanceof MethodExitEvent ) { + index = 5; + } else if (event1 instanceof StepEvent ) { + index = 6; + } else { + log3("ERROR: else clause in detecting type of event1"); + testExitCode = FAILED; + } + + flag = 1 << index; + if ((flagsCopy & flag) == 0) { + log3("ERROR: event duplication: " + eName); + testExitCode = FAILED; + } else { + flagsCopy ^= flag; + flags |= flag; + } + + eventSets[index] = eventSet; + } + + if (testExitCode == FAILED) + break; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest settingAccessWatchpoint ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + String property) + throws JDITestRuntimeException { + + log2("......setting up AccessWatchpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; fieldName: " + fieldName); + + AccessWatchpointRequest awRequest = null; + try { + Field field = testedClass.fieldByName(fieldName); + awRequest = eventRManager.createAccessWatchpointRequest(field); + awRequest.putProperty("number", property); + awRequest.addThreadFilter(thread); + awRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpoint() : " + e); + log3(" AN ACCESSWATCHPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up an AccessWatchpoint **"); + } + + log2(" an AccessWatchpoint has been set up"); + return awRequest; + } + + private ModificationWatchpointRequest settingModificationWatchpoint ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + String property) + throws JDITestRuntimeException { + + log2("......setting up ModificationWatchpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; fieldName: " + fieldName); + + ModificationWatchpointRequest mwRequest = null; + try { + Field field = testedClass.fieldByName(fieldName); + mwRequest = eventRManager.createModificationWatchpointRequest(field); + mwRequest.putProperty("number", property); + mwRequest.addThreadFilter(thread); + mwRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpoint() : " + e); + log3(" AN ModificationWATCHPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up an AccessWatchpoint **"); + } + + log2(" a ModificationWatchpoint has been set up"); + return mwRequest; + } + + private MethodEntryRequest settingMethodEntry ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up MethodEntry:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + MethodEntryRequest menRequest = null; + try { + menRequest = eventRManager.createMethodEntryRequest(); + menRequest.putProperty("number", property); + menRequest.addThreadFilter(thread); + menRequest.addClassFilter(testedClass); + menRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntry() : " + e); + log3(" A MethodEntry HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a MethodEntry **"); + } + + log2(" a MethodEntry has been set up"); + return menRequest; + } + + private MethodExitRequest settingMethodExit ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up MethodExit:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + MethodExitRequest mexRequest = null; + try { + mexRequest = eventRManager.createMethodExitRequest(); + mexRequest.putProperty("number", property); + mexRequest.addThreadFilter(thread); + mexRequest.addClassFilter(testedClass); + mexRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExit() : " + e); + log3(" A MethodExit HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a MethodExit **"); + } + + log2(" a MethodExit has been set up"); + return mexRequest; + } + + private StepRequest settingStep ( ThreadReference thread, String property) + throws JDITestRuntimeException { + + log2("......setting up Step:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest stRequest = null; + try { + stRequest = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); + stRequest.putProperty("number", property); + stRequest.addCountFilter(1); + stRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStep() : " + e); + log3(" A Step HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a Step **"); + } + + log2(" a Step has been set up"); + return stRequest; + } + + + private ExceptionRequest settingException ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up Exception:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + ExceptionRequest excRequest = null; + try { + excRequest = eventRManager.createExceptionRequest(null, true, true); + excRequest.putProperty("number", property); + excRequest.addThreadFilter(thread); + excRequest.addClassFilter(testedClass); + excRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingException() : " + e); + log3(" A Exception HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a Exception **"); + } + + log2(" a Exception has been set up"); + return excRequest; + } + + private void checkingEventIterator(EventIterator eIterator) { + + log2("......checking up on eIterator.nextEvent()"); + + try { + log2("......first time: Event testedEvent = eIterator.nextEvent();"); + log2(" no Exception to be thrown is expected"); + Event testedEvent = eIterator.nextEvent(); + } catch (Exception e) { + log3("ERROR: Exception while: testedEvent = eIterator.nextEvent(); :: " + e); + testExitCode = FAILED; + } + try { + log2("......second time: Event testedEvent = eIterator.nextEvent();"); + log2(" NoSuchElementException is expected"); + Event testedEvent = eIterator.nextEvent(); + log3("ERROR: no NoSuchElementException while: testedEvent = eIterator.nextEvent();"); + testExitCode = FAILED; + } catch (NoSuchElementException e) { + log2(" NoSuchElementException"); + } catch (Exception e) { + log3("ERROR: unexpected Exception :: " + e); + testExitCode = FAILED; + } + } + + private void check() { + + log2("......performing the check;"); + for (int k = 0; k < eventFlags.length; k++) { + + log2("......new check case :: k == " + k); + switch (eventFlags[k]) { + + case 0: + case 1: + case 2: + checkingEventIterator(eventSets[k].eventIterator()); + break; + + case 3: + break; + + default: + log3("ERROR: unexpected default case"); + testExitCode = FAILED; + throw new JDITestRuntimeException("** FAILURE within check() **"); + } + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001/TestDescription.java new file mode 100644 index 00000000000..88d9134e0c7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventIterator/nextEvent/nextevent001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventIterator. + * The test checks up that a result of the method + * com.sun.jdi.EventIterator.nextEvent() + * complies with its spec: + * public Event nextEvent() + * Returns: + * The next Event in an EventSet. + * The cases to check include normal return and + * throwing no Exceptions but NoSuchElementException. + * The test works as follows: + * The debugger program - nsk.jdi.EventIterator.nextEvent.nextevent001; + * the debuggee program - nsk.jdi.EventIterator.nextEvent.nextevent001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Fixed due to the bug 4528893. + * Test fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - binder.bindToDebugeeNoWait() is used to prevent Binder from + * handling VMStartEvent + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventIterator.nextEvent.nextevent001 + * nsk.jdi.EventIterator.nextEvent.nextevent001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventIterator.nextEvent.nextevent001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001a.java new file mode 100644 index 00000000000..a1bab604101 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001a.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventIterator.nextEvent; + +import nsk.share.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the nextevent001 JDI test. + */ + +public class nextevent001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass tcObject = new TestClass(); + + static String threadNames[] = { + "awThread", "mwThread", "bpThread", "excThread", + "menThread", "mexThread", "stThread" + }; + + static int threadsN = threadNames.length; + + static Thread threads[] = new Thread[threadsN]; + + static Thread thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread2 = new Thread3nextevent001a("thread2"); + threadStart(thread2); + try { + // we should wait here for thread2 completion (see 6671428) + thread2.join(); + } catch (InterruptedException e) { + logErr("ERROR: unexpected exception: " + e); + exitCode = FAILED; + break ; + } + + for (int n1 = 0; n1 < threadsN; n1++) { + if (n1 < threadsN-1) + threads[n1] = new Thread1nextevent001a(threadNames[n1]); + else + threads[n1] = new Thread2nextevent001a(threadNames[n1]); + } + log1(" threads has been created"); + + synchronized (lockingObject2) { + log1(" loop: threadStart(threads[n2])"); + for (int n2 = 0; n2 < threadsN; n2++) + if ( threadStart(threads[n2]) != PASSED ) + break label0; + + log1(" methodForCommunication();"); + methodForCommunication(); + } + + for (int n2 = 0; n2 < threadsN; n2++) { + synchronized (locks[n2]) { + log1(" synchronized (locks[n2]) : n2 == " + n2); + } + } + + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + public static void nullMethod() { + throw new NullPointerException("test"); + } + + static Object lockingObject2 = new Object(); + static Object locks[] = new Object[threadsN]; + + static volatile int n = 0; + + static class Thread1nextevent001a extends Thread { + + int threadIndex; + + public Thread1nextevent001a(String threadName) { + super(threadName); + threadIndex = n; + locks[threadIndex] = new Object(); + n++; + } + + public void run() { + log3(" 'run': enter :: threadIndex == " + threadIndex); + + synchronized (locks[threadIndex]) { + log3("enter synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log3(" 'run': exit synchronized (waitnotifyObj)"); + + synchronized (lockingObject2) { + TestClass.method(); + } + log3("exit synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + } + return; + } + + } + + static class Thread2nextevent001a extends Thread { + + int threadIndex; + + public Thread2nextevent001a(String threadName) { + super(threadName); + threadIndex = n; + locks[threadIndex] = new Object(); + n++; + } + + public void run() { + log3(" 'run': enter :: threadIndex == " + threadIndex); + + synchronized (locks[threadIndex]) { + log3("enter synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + m1(); + log3("exit synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + } + return; + } + + private void m1() { + synchronized (lockingObject2) { + log3(" 'm1': enter"); + + log3(" 'm1': exit"); + } + } + + } + + static class Thread3nextevent001a extends Thread { + + String tName = null; + + public Thread3nextevent001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log3(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log3(" 'run': exit :: threadName == " + tName); + return; + } + } + + + public static void log3(String str) { + log1(Thread.currentThread().getName() + " : " + str); + } + +} + +class TestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 += 1; + var3 += 1; + var2 = var3; + try { + nextevent001a.nullMethod(); + } catch ( NullPointerException e ) { + nextevent001a.log3(" NullPointerException : " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001.java new file mode 100644 index 00000000000..9e066b30998 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventQueue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class hashcode001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.EventQueue.hashCode."; + private final static String className = "hashcode001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + display("Checking hashCode() method for EventQueue object"); + + EventQueue eventQueue = debuggee.VM().eventQueue(); + int hCode = eventQueue.hashCode(); + + if (hCode == 0) { + complain("hashCode() returns 0 for EventQueue object"); + exitStatus = Consts.TEST_FAILED; + } + + int hCode1 = eventQueue.hashCode(); + if (hCode != hCode1) { + complain("hashCode() is not consistent for EventQueue object" + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + // get new reference to the same EventQueue and get hash code. + hCode1 = debuggee.VM().eventQueue().hashCode(); + if (hCode != hCode1) { + complain("hashCode() does not return same value for equal EventQueue object " + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + display("hashCode() returns for EventQueue object : " + hCode); + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..ca9c1a7722b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/hashCode/hashcode001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public hashCode() method of an implementing class of + * com.sun.jdi.event.EventQueue interface. + * The test checks an assertion cited from spec for hashCode() method of + * java.lang.Object class: + * The general contract of hashCode is: + * - Whenever it is invoked on the same object more than once during + * an execution of a Java application, the hashCode method must + * consistently return the same integer, provided no information used + * in equals comparisons on the object is modified. + * ... + * - If two objects are equal according to the equals(Object) method, + * then calling the hashCode method on each of the two objects must + * produce the same integer result. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for EventQueue + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.hashCode.hashcode001 + * nsk.jdi.EventQueue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..f5511cfba25 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/hashCode/hashcode001a.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventQueue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class hashcode001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(hashcode001.SIGNAL_READY); + receiveSignal(hashcode001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001.java new file mode 100644 index 00000000000..182b4723143 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove() + * will always be preceded by a VMDisconnectEvent + * when a debuggee part of the test normally exits. + */ +public class remove001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventQueue.remove.remove001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private int tot_res = FAILED; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new remove001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + debuggee.redirectStderr(log, "remove001t.err> "); +// dummy IOPipe: just to avoid: +// "Pipe server socket listening error: java.net.SocketException" + IOPipe pipe = debuggee.createIOPipe(); + +// Getting JDI events + checkEvents(debuggee.VM().eventQueue()); + + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } + + private void checkEvents(EventQueue eventQ) { + boolean gotVMDisconnect = false; // VMDisconnectEvent is received + boolean gotVMDeath = false; // VMDeathEvent is received + EventSet eventSet = null; + + debuggee.resume(); + while (true) { + try { + eventSet = eventQ.remove(); + EventIterator eventIter = eventSet.eventIterator(); + while (eventIter.hasNext()) { + Event event = eventIter.nextEvent(); + if (event instanceof VMDisconnectEvent) { + gotVMDisconnect = true; + log.display("Got expected VMDisconnectEvent"); + break; + } else if (event instanceof VMStartEvent) { + log.display("Got VMStartEvent"); + } else if (event instanceof VMDeathEvent) { + gotVMDeath = true; + log.display("Got VMDeathEvent"); + } + if (!gotVMDisconnect && !gotVMDeath && + eventSet.suspendPolicy() != + EventRequest.SUSPEND_NONE) { + log.display("Calling EventSet.resume() ..."); + eventSet.resume(); + } + } + } catch(InterruptedException e) { + log.complain("TEST INCOMPLETE: caught " + e); + tot_res = FAILED; + } catch(VMDisconnectedException e) { + if (gotVMDisconnect) { + log.display("\nCHECK PASSED: caught VMDisconnectedException preceded by a VMDisconnectEvent\n"); + tot_res = PASSED; + } else { + log.complain("\nTEST FAILED: caught VMDisconnectedException without preceding VMDisconnectEvent\n"); + e.printStackTrace(); + tot_res = FAILED; + } + break; + } + } + log.display("Stopped JDI events processing"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001/TestDescription.java new file mode 100644 index 00000000000..ed423ccf0c4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove/remove001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove() + * will always be preceded by a VMDisconnectEvent when + * a debuggee part of the test normally exits. + * COMMENTS + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - resume for VMDeathEvent is skipped in event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove.remove001 + * nsk.jdi.EventQueue.remove.remove001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove.remove001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001t.java new file mode 100644 index 00000000000..38d821ea301 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove001t.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee part of the test. + */ +public class remove001t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = argHandler.createDebugeeLog(); +// dummy IOPipe: just to avoid: +// "Pipe server socket listening error: java.net.SocketException" + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + log.display("Debuggee: exiting"); + System.exit(remove001.JCK_STATUS_BASE + + remove001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002.java new file mode 100644 index 00000000000..7ebe2fb8b5d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove() + * will be preceded by a VMDisconnectEvent + * after com.sun.jdi.VirtualMachine.dispose() call. + */ +public class remove002 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventQueue.remove.remove002t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private CheckEvents chkEvents; + private EventQueue eventQ; + private volatile int tot_res = FAILED; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new remove002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + debuggee.redirectStderr(log, "remove002t.err> "); + pipe = debuggee.createIOPipe(); + VirtualMachine vm = debuggee.VM(); + + eventQ = vm.eventQueue(); + chkEvents = new CheckEvents(); + chkEvents.setDaemon(true); + chkEvents.start(); + + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(FAILED); + } + + log.display("Invoking VirtualMachine.dispose() ..."); + vm.dispose(); + + return quitDebuggee(PASSED); + } + + class CheckEvents extends Thread { + public void run() { + boolean gotVMDisconnect = false; // VMDisconnectEvent is received + boolean gotVMDeath = false; // VMDeathEvent is received + EventSet eventSet = null; + + log.display("CheckEvents: starts JDI events processing"); + while (true) { + try { + eventSet = eventQ.remove(); + EventIterator eventIter = eventSet.eventIterator(); + while (eventIter.hasNext()) { + Event event = eventIter.nextEvent(); + if (event instanceof VMDisconnectEvent) { + gotVMDisconnect = true; + log.display("CheckEvents: got expected VMDisconnectEvent"); + break; + } else if (event instanceof VMStartEvent) { + log.display("CheckEvents: got VMStartEvent"); + } else if (event instanceof VMDeathEvent) { + gotVMDeath = true; + log.display("CheckEvents: got VMDeathEvent"); + } + if (!gotVMDisconnect && !gotVMDeath && + eventSet.suspendPolicy() != + EventRequest.SUSPEND_NONE) { + log.display("CheckEvents: calling EventSet.resume() ..."); + eventSet.resume(); + } + } + } catch(InterruptedException e) { + log.complain("TEST INCOMPLETE: caught " + e); + tot_res = FAILED; + } catch(VMDisconnectedException e) { + if (gotVMDisconnect) { + log.display("\nCHECK PASSED: caught expected VMDisconnectedException preceded by a VMDisconnectEvent\n"); + tot_res = PASSED; + } else { + log.complain("\nTEST FAILED: caught VMDisconnectedException without preceding VMDisconnectEvent\n"); + e.printStackTrace(); + tot_res = FAILED; + } + break; + } + } + log.display("CheckEvents: stopped JDI events processing"); + } + } + + private int quitDebuggee(int stat) { + if (chkEvents != null) { + try { + if (chkEvents.isAlive()) + chkEvents.join(argHandler.getWaitTime()*60000); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + if (chkEvents.isAlive()) { + if (stat == PASSED) { + log.complain("TEST FAILED: CheckEvents thread is still alive,\n" + + "\tbut it should stop JDI events processing and exit"); + chkEvents.interrupt(); + tot_res = FAILED; + } + } + } + + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002/TestDescription.java new file mode 100644 index 00000000000..78d4f7b1454 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove/remove002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove() + * will be preceded by a VMDisconnectEvent after + * com.sun.jdi.VirtualMachine.dispose() call. + * COMMENTS + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - resume for VMDeathEvent is skipped in event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove.remove002 + * nsk.jdi.EventQueue.remove.remove002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove.remove002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002t.java new file mode 100644 index 00000000000..5d5e50c080c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove002t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee part of the test. + */ +public class remove002t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + log.display("Debuggee: ready"); + pipe.println(remove002.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(remove002.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd + "\nDebuggee: exiting"); + System.exit(remove002.JCK_STATUS_BASE + + remove002.FAILED); + } + log.display("Debuggee: exiting"); + System.exit(remove002.JCK_STATUS_BASE + + remove002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003.java new file mode 100644 index 00000000000..31fe659acad --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove() + * will be preceded by a VMDisconnectEvent + * after com.sun.jdi.VirtualMachine.exit() call. + */ +public class remove003 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventQueue.remove.remove003t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private CheckEvents chkEvents; + private EventQueue eventQ; + private volatile int tot_res = FAILED; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new remove003().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + debuggee.redirectStderr(log, "remove003t.err> "); + pipe = debuggee.createIOPipe(); + VirtualMachine vm = debuggee.VM(); + + eventQ = vm.eventQueue(); + chkEvents = new CheckEvents(); + chkEvents.setDaemon(true); + chkEvents.start(); + + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(FAILED); + } + + log.display("Invoking VirtualMachine.exit() ..."); + vm.exit(JCK_STATUS_BASE + PASSED); + + return quitDebuggee(PASSED); + } + + class CheckEvents extends Thread { + public void run() { + boolean gotVMDisconnect = false; // VMDisconnectEvent is received + boolean gotVMDeath = false; // VMDeathEvent is received + EventSet eventSet = null; + + log.display("CheckEvents: starts JDI events processing"); + while (true) { + try { + eventSet = eventQ.remove(); + EventIterator eventIter = eventSet.eventIterator(); + while (eventIter.hasNext()) { + Event event = eventIter.nextEvent(); + if (event instanceof VMDisconnectEvent) { + gotVMDisconnect = true; + log.display("CheckEvents: got expected VMDisconnectEvent"); + break; + } else if (event instanceof VMStartEvent) { + log.display("CheckEvents: got VMStartEvent"); + } else if (event instanceof VMDeathEvent) { + gotVMDeath = true; + log.display("CheckEvents: got VMDeathEvent"); + } + if (!gotVMDisconnect && !gotVMDeath && + eventSet.suspendPolicy() != + EventRequest.SUSPEND_NONE) { + log.display("CheckEvents: calling EventSet.resume() ..."); + eventSet.resume(); + } + } + } catch(InterruptedException e) { + log.complain("TEST INCOMPLETE: caught " + e); + tot_res = FAILED; + } catch(VMDisconnectedException e) { + if (gotVMDisconnect) { + log.display("\nCHECK PASSED: caught expected VMDisconnectedException preceded by a VMDisconnectEvent\n"); + tot_res = PASSED; + } else { + log.complain("\nTEST FAILED: caught VMDisconnectedException without preceding VMDisconnectEvent\n"); + e.printStackTrace(); + tot_res = FAILED; + } + break; + } + } + log.display("CheckEvents: stopped JDI events processing"); + } + } + + private int quitDebuggee(int stat) { + if (chkEvents != null) { + try { + if (chkEvents.isAlive()) + chkEvents.join(argHandler.getWaitTime()*60000); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + if (chkEvents.isAlive()) { + if (stat == PASSED) { + log.complain("TEST FAILED: CheckEvents thread is still alive,\n" + + "\tbut it should stop JDI events processing and exit"); + chkEvents.interrupt(); + tot_res = FAILED; + } + } + } + +// pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003/TestDescription.java new file mode 100644 index 00000000000..5ca2acd9784 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove/remove003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove() + * will be preceded by a VMDisconnectEvent after + * com.sun.jdi.VirtualMachine.exit() call. + * COMMENTS + * To fix the bug 4504397, + * the line 148 in the file remove003.java has been commented away. + * --------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - resume on VMDeathEvent is skipped in events handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove.remove003 + * nsk.jdi.EventQueue.remove.remove003t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove.remove003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003t.java new file mode 100644 index 00000000000..daf3f1b645a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove003t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee part of the test. + */ +public class remove003t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + log.display("Debuggee: ready"); + pipe.println(remove003.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(remove003.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd + "\nDebuggee: exiting"); + System.exit(remove003.JCK_STATUS_BASE + + remove003.FAILED); + } + log.display("Debuggee: exiting"); + System.exit(remove003.JCK_STATUS_BASE + + remove003.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java new file mode 100644 index 00000000000..7f58fde7e14 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventQueue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.EventQueue.remove()
    + * complies with its spec.
    + *
    + * Since method's assertion is
    + * "Waits forever for the next available event."
    + * in the condition of a limited time for testing,
    + * the test case limits time for waiting for the next event
    + * to the standard value of WAITTIME set up in the testbase_nsk.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + * The check includes two steps.
    + * In first one, second thread waits for any incoming event from the
    + * debugger which is sleeping for "WAITTIME*90 seconds"; hence,
    + * no events are expected to be received at the debugger end.
    + * In second, second thread is interrupted, and the debugger waits for
    + * a breakpoint event after the debuggee finishes sleeping.
    + */ + +public class remove004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventQueue/remove/remove004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new remove004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventQueue.remove.remove004a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + vm.resume(); + + Threadremove004 thread2 = new Threadremove004("thread2"); + log2(" thread2 is created"); + + synchronized (lockingObject) { + synchronized (waitnotifyObj) { + log2(" before: thread2.start()"); + thread2.start(); + + try { + log2(" before: waitnotifyObj.wait();"); + waitnotifyObj.wait(); + } catch ( Exception e) { + log3("ERROR: Exception : " + e ); + testExitCode = FAILED; + throw new JDITestRuntimeException("** Exception while waiting: notify() **"); + } + } + } + log2("mainThread is out of: synchronized (lockingObject)"); + + Object waitObj = new Object(); + + synchronized (waitObj) { + waitObj.wait(waitTime); + if (!thread2.isAlive()) { + log3("ERROR: thread2 is not alive"); + testExitCode = FAILED; + break; + } + + thread2.interrupt(); + + for (int i2 = 0; i2 < waitTime; ) { + waitObj.wait(10000); + if (!thread2.isAlive()) { + break; + } + i2 += 10000; + } + if (thread2.isAlive()) { + log3("ERROR: thread2 is still alive"); + testExitCode = FAILED; + break; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + + public static Object waitnotifyObj = new Object(); + public static Object lockingObject = new Object(); + + class Threadremove004 extends Thread { + + public Threadremove004(String threadName) { + super(threadName); + } + + public void run() { + log2("-----t2: method 'run' enter"); + synchronized (waitnotifyObj) { + log2("-----t2: entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log2("-----t2: exited from block: synchronized (waitnotifyObj)"); + synchronized (lockingObject) { + log2("-----t2: entered into block: synchronized (lockingObject)"); + } + log2("-----t2: exited from block: synchronized (lockingObject)"); + + try { + log2("-----t2: eventSet = eventQueue.remove(); expects: InterruptedException"); + eventSet = eventQueue.remove(); + throw new JDITestRuntimeException("** return from eventQueue.remove(); **"); + } catch ( InterruptedException e1) { + log2("-----t2: InterruptedException"); + } catch ( Exception e ) { + log3("ERROR: -----t2: Exception : " + e); + testExitCode = FAILED; + } + + log2("-----t2: method 'run' exit"); + return; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004/TestDescription.java new file mode 100644 index 00000000000..e72bbd8b4ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove/remove004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventQueue. + * The test checks up that a result of the method + * com.sun.jdi.EventQueue.remove() + * complies with its spec: + * public EventSet remove() + * throws java.lang.InterruptedException + * Waits forever for the next available event. + * Returns: the next EventSet. + * Throws: java.lang.InterruptedException - + * if another thread has interrupted this thread. + * VMDisconnectedException - + * if the connection to the target VM is no longer available. + * Note this will always be preceded by a VMDisconnectEvent. + * The test checks the assertion + * "Waits forever for the next available event." + * in the condition of a limited time for testing. + * The test works as follows: + * The debugger program - nsk.jdi.EventQueue.remove.remove004; + * the debuggee program - nsk.jdi.EventQueue.remove.remove004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove.remove004 + * nsk.jdi.EventQueue.remove.remove004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove.remove004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004a.java new file mode 100644 index 00000000000..1d5c3d2f1c9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the remove004 JDI test. + */ + +public class remove004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + log1("before: methodForCommunication();"); + methodForCommunication(); + log1("before: Thread.sleep"); + try { + Thread.sleep(argHandler.getWaitTime()*90000); + } catch (InterruptedException e) { + } + log1("after: Thread.sleep"); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001.java new file mode 100644 index 00000000000..9a919ccfb1e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove(long) + * will always be preceded by a VMDisconnectEvent + * when a debuggee part of the test normally exits. + */ +public class remove_l001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventQueue.remove_l.remove_l001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private int tot_res = FAILED; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new remove_l001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + debuggee.redirectStderr(log, "remove_l001t.err> "); +// dummy IOPipe: just to avoid: +// "Pipe server socket listening error: java.net.SocketException" + IOPipe pipe = debuggee.createIOPipe(); + +// Getting JDI events + checkEvents(debuggee.VM().eventQueue()); + + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } + + private void checkEvents(EventQueue eventQ) { + boolean gotVMDisconnect = false; // VMDisconnectEvent is received + boolean gotVMDeath = false; // VMDeathEvent is received + EventSet eventSet = null; + + debuggee.resume(); + while (true) { + try { + eventSet = eventQ.remove(argHandler.getWaitTime()*60000); + if (eventSet == null) { + log.display("Specified time for the next available event has elapsed"); + continue; + } + EventIterator eventIter = eventSet.eventIterator(); + while (eventIter.hasNext()) { + Event event = eventIter.nextEvent(); + if (event instanceof VMDisconnectEvent) { + gotVMDisconnect = true; + log.display("Got expected VMDisconnectEvent"); + break; + } else if (event instanceof VMStartEvent) { + log.display("Got VMStartEvent"); + } else if (event instanceof VMDeathEvent) { + gotVMDeath = true; + log.display("Got VMDeathEvent"); + } + if (!gotVMDisconnect && !gotVMDeath && + eventSet.suspendPolicy() != + EventRequest.SUSPEND_NONE) { + log.display("Calling EventSet.resume() ..."); + eventSet.resume(); + } + } + } catch(InterruptedException e) { + log.complain("TEST INCOMPLETE: caught " + e); + tot_res = FAILED; + } catch(VMDisconnectedException e) { + if (gotVMDisconnect) { + log.display("\nCHECK PASSED: caught VMDisconnectedException preceded by a VMDisconnectEvent\n"); + tot_res = PASSED; + } else { + log.complain("\nTEST FAILED: caught VMDisconnectedException without preceding VMDisconnectEvent\n"); + e.printStackTrace(); + tot_res = FAILED; + } + break; + } + } + log.display("Stopped JDI events processing"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001/TestDescription.java new file mode 100644 index 00000000000..304443ee49a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove_l/remove_l001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove(long) + * will always be preceded by a VMDisconnectEvent when + * a debuggee part of the test normally exits. + * COMMENTS + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - resume for VMDeathEvent is skipped in event handling loop + * Fixed misprint in package name according to test bug: + * 4782469 TEST_RFE: incorrect package name in some JPDA tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove_l.remove_l001 + * nsk.jdi.EventQueue.remove_l.remove_l001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove_l.remove_l001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001t.java new file mode 100644 index 00000000000..7daa68ce2ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l001t.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee part of the test. + */ +public class remove_l001t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = argHandler.createDebugeeLog(); +// dummy IOPipe: just to avoid: +// "Pipe server socket listening error: java.net.SocketException" + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + log.display("Debuggee: exiting"); + System.exit(remove_l001.JCK_STATUS_BASE + + remove_l001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002.java new file mode 100644 index 00000000000..bacc33886d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove(long) + * will be preceded by a VMDisconnectEvent + * after com.sun.jdi.VirtualMachine.dispose() call. + */ +public class remove_l002 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventQueue.remove_l.remove_l002t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private CheckEvents chkEvents; + private EventQueue eventQ; + private volatile int tot_res = FAILED; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new remove_l002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + debuggee.redirectStderr(log, "remove_l002t.err> "); + pipe = debuggee.createIOPipe(); + VirtualMachine vm = debuggee.VM(); + + eventQ = vm.eventQueue(); + chkEvents = new CheckEvents(); + chkEvents.setDaemon(true); + chkEvents.start(); + + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(FAILED); + } + + log.display("Invoking VirtualMachine.dispose() ..."); + vm.dispose(); + + return quitDebuggee(PASSED); + } + + class CheckEvents extends Thread { + public void run() { + boolean gotVMDisconnect = false; // VMDisconnectEvent is received + boolean gotVMDeath = false; // VMDeathEvent is received + EventSet eventSet = null; + + log.display("CheckEvents: starts JDI events processing"); + while (true) { + try { + eventSet = eventQ.remove(argHandler.getWaitTime()*30000); + if (eventSet == null) { + log.display("CheckEvents: specified time for the next available event has elapsed"); + continue; + } + EventIterator eventIter = eventSet.eventIterator(); + while (eventIter.hasNext()) { + Event event = eventIter.nextEvent(); + if (event instanceof VMDisconnectEvent) { + gotVMDisconnect = true; + log.display("CheckEvents: got expected VMDisconnectEvent"); + break; + } else if (event instanceof VMStartEvent) { + log.display("CheckEvents: got VMStartEvent"); + } else if (event instanceof VMDeathEvent) { + log.display("CheckEvents: got VMDeathEvent"); + gotVMDeath = true; + } + if (!gotVMDisconnect && !gotVMDeath && + eventSet.suspendPolicy() != + EventRequest.SUSPEND_NONE) { + log.display("CheckEvents: calling EventSet.resume() ..."); + eventSet.resume(); + } + } + } catch(InterruptedException e) { + log.complain("TEST INCOMPLETE: caught " + e); + tot_res = FAILED; + } catch(VMDisconnectedException e) { + if (gotVMDisconnect) { + log.display("\nCHECK PASSED: caught expected VMDisconnectedException preceded by a VMDisconnectEvent\n"); + tot_res = PASSED; + } else { + log.complain("\nTEST FAILED: caught VMDisconnectedException without preceding VMDisconnectEvent\n"); + e.printStackTrace(); + tot_res = FAILED; + } + break; + } + } + log.display("CheckEvents: stopped JDI events processing"); + } + } + + private int quitDebuggee(int stat) { + if (chkEvents != null) { + try { + if (chkEvents.isAlive()) + chkEvents.join(argHandler.getWaitTime()*60000); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + if (chkEvents.isAlive()) { + if (stat == PASSED) { + log.complain("TEST FAILED: CheckEvents thread is still alive,\n" + + "\tbut it should stop JDI events processing and exit"); + chkEvents.interrupt(); + tot_res = FAILED; + } + } + } + + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002/TestDescription.java new file mode 100644 index 00000000000..18204682e31 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove_l/remove_l002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove(long) + * will be preceded by a VMDisconnectEvent after + * com.sun.jdi.VirtualMachine.dispose() call. + * COMMENTS + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - resume on VMDeathEvent is skipped in events handling loop + * Fixed misprint in package name according to test bug: + * 4782469 TEST_RFE: incorrect package name in some JPDA tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove_l.remove_l002 + * nsk.jdi.EventQueue.remove_l.remove_l002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove_l.remove_l002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002t.java new file mode 100644 index 00000000000..976b29e5ac8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l002t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee part of the test. + */ +public class remove_l002t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + log.display("Debuggee: ready"); + pipe.println(remove_l002.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(remove_l002.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd + "\nDebuggee: exiting"); + System.exit(remove_l002.JCK_STATUS_BASE + + remove_l002.FAILED); + } + log.display("Debuggee: exiting"); + System.exit(remove_l002.JCK_STATUS_BASE + + remove_l002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003.java new file mode 100644 index 00000000000..04d77fe829e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove(int) + * will be preceded by a VMDisconnectEvent + * after com.sun.jdi.VirtualMachine.exit() call. + */ +public class remove_l003 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventQueue.remove_l.remove_l003t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private CheckEvents chkEvents; + private EventQueue eventQ; + private volatile int tot_res = FAILED; + + public static void main(String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new remove_l003().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + debuggee.redirectStderr(log, "remove_l003t.err> "); + pipe = debuggee.createIOPipe(); + VirtualMachine vm = debuggee.VM(); + + eventQ = vm.eventQueue(); + chkEvents = new CheckEvents(); + chkEvents.setDaemon(true); + chkEvents.start(); + + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(FAILED); + } + + log.display("Invoking VirtualMachine.exit() ..."); + vm.exit(JCK_STATUS_BASE + PASSED); + + return quitDebuggee(PASSED); + } + + class CheckEvents extends Thread { + public void run() { + boolean gotVMDisconnect = false; // VMDisconnectEvent is received + boolean gotVMDeath = false; // VMDeathEvent is received + EventSet eventSet = null; + + log.display("CheckEvents: starts JDI events processing"); + while (true) { + try { + eventSet = eventQ.remove(argHandler.getWaitTime()*30000); + if (eventSet == null) { + log.display("CheckEvents: specified time for the next available event has elapsed"); + continue; + } + EventIterator eventIter = eventSet.eventIterator(); + while (eventIter.hasNext()) { + Event event = eventIter.nextEvent(); + if (event instanceof VMDisconnectEvent) { + gotVMDisconnect = true; + log.display("CheckEvents: got expected VMDisconnectEvent"); + break; + } else if (event instanceof VMStartEvent) { + log.display("CheckEvents: got VMStartEvent"); + } else if (event instanceof VMDeathEvent) { + gotVMDeath = true; + log.display("CheckEvents: got VMDeathEvent"); + } + if (!gotVMDisconnect && !gotVMDeath && + eventSet.suspendPolicy() != + EventRequest.SUSPEND_NONE) { + log.display("CheckEvents: calling EventSet.resume() ..."); + eventSet.resume(); + } + } + } catch(InterruptedException e) { + log.complain("TEST INCOMPLETE: caught " + e); + tot_res = FAILED; + } catch(VMDisconnectedException e) { + if (gotVMDisconnect) { + log.display("\nCHECK PASSED: caught expected VMDisconnectedException preceded by a VMDisconnectEvent\n"); + tot_res = PASSED; + } else { + log.complain("\nTEST FAILED: caught VMDisconnectedException without preceding VMDisconnectEvent\n"); + e.printStackTrace(); + tot_res = FAILED; + } + break; + } + } + log.display("CheckEvents: stopped JDI events processing"); + } + } + + private int quitDebuggee(int stat) { + if (chkEvents != null) { + try { + if (chkEvents.isAlive()) + chkEvents.join(argHandler.getWaitTime()*60000); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + if (chkEvents.isAlive()) { + if (stat == PASSED) { + log.complain("TEST FAILED: CheckEvents thread is still alive,\n" + + "\tbut it should stop JDI events processing and exit"); + chkEvents.interrupt(); + tot_res = FAILED; + } + } + } + +// pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003/TestDescription.java new file mode 100644 index 00000000000..9be5d7ca6ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove_l/remove_l003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that a VMDisconnectedException thrown by + * the JDI method com.sun.jdi.request.EventQueue.remove(long) + * will be preceded by a VMDisconnectEvent after + * com.sun.jdi.VirtualMachine.exit() call. + * COMMENTS + * 1) + * To fix the bug 4504397, + * the line 152 in the file remove003.java has been commented away. + * 2) + * To put the name of the package in correspondence with the tesbase_nsk rules, + * EventQueue.remove is replaced with EventQueue.remove_l in the following files: + * - remove_l003.java, lines 5, 32; + * - remove_l003t.java, line 5; + * - remove_l003.cfg, line 4. + * --------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - resume on VMDeathEvent is skipped in events handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove_l.remove_l003 + * nsk.jdi.EventQueue.remove_l.remove_l003t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove_l.remove_l003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003t.java new file mode 100644 index 00000000000..caf8392767c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l003t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee part of the test. + */ +public class remove_l003t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + log.display("Debuggee: ready"); + pipe.println(remove_l003.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(remove_l003.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd + "\nDebuggee: exiting"); + System.exit(remove_l003.JCK_STATUS_BASE + + remove_l003.FAILED); + } + log.display("Debuggee: exiting"); + System.exit(remove_l003.JCK_STATUS_BASE + + remove_l003.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java new file mode 100644 index 00000000000..d924cfe5cb7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventQueue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.EventQueue.remove(int)
    + * complies with its spec.
    + *
    + * The test checks two assertions:
    + * - Returns: null if there is a timeout.
    + * - Returns: the next EventSet if no timeout.
    + * It uses the WAITTINE value which is the standard parameter for
    + * time intervals in the testbase_nsk.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee firstly invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * The case for testing consists of of two steps.
    + * In the first one the first assertion is checked up on as follows:
    + * the debugger sleeps for "WAITTIME * 90 sec";
    + * hence, no event is expected in the debugger within WAITTINE, and
    + * debugger's method breakpointForCommunication() should get null.
    + * After WAITTIME, the debugger just expects to get normal breakpoint event.
    + */ + +public class remove_l004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventQueue/remove_l/remove_l004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new remove_l004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventQueue.remove_l.remove_l004a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction != 1) { + testExitCode = FAILED; + throw new JDITestRuntimeException("** unexpected instruction **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + vm.resume(); + try { + log2("......invoking: getEventSet();"); + getEventSet(); + } catch ( JDITestRuntimeException e ) { + String str = e.getMessage(); + log2(" JDITestRuntimeException : " + str); + if (str.lastIndexOf("TIMEOUT") <0) { + log3("ERROR: no TIMEOUT"); + testExitCode = FAILED; + throw new JDITestRuntimeException("** unexpected Exception **"); + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log2("...... waiting for breakpoint event"); + + breakpointForCommunication(); + + instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction != 0) { + testExitCode = FAILED; + throw new JDITestRuntimeException("** unexpected instruction **"); + } + vm.resume(); + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004/TestDescription.java new file mode 100644 index 00000000000..710059e8351 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove_l/remove_l004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventQueue. + * The test checks up that a result of the method + * com.sun.jdi.EventQueue.remove_l() + * complies with its spec: + * public EventSet remove(long timeout) + * throws java.lang.InterruptedException + * Waits a specified time for the next available event. + * Parameters: timeout - Time in milliseconds to wait for the next event + * Returns: the next EventSet, or null if there is a timeout. + * Throws: java.lang.InterruptedException - + * if another thread has interrupted this thread. + * VMDisconnectedException - + * if the connection to the target VM is no longer available. + * Note this will always be preceded by a VMDisconnectEvent. + * The test checks two assertions: + * - Returns: null if there is a timeout. + * - Returns: the next EventSet if no timeout. + * The test works as follows: + * The debugger program - nsk.jdi.EventQueue.remove_l.remove_l004; + * the debuggee program - nsk.jdi.EventQueue.remove_l.remove_l004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove_l.remove_l004 + * nsk.jdi.EventQueue.remove_l.remove_l004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove_l.remove_l004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004a.java new file mode 100644 index 00000000000..8c0e2c3f032 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the remove_l004 JDI test. + */ + +public class remove_l004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + log1("before: methodForCommunication();"); + methodForCommunication(); + log1("before: Thread.sleep"); + try { + Thread.sleep(argHandler.getWaitTime()*90000); + } catch (InterruptedException e) { + } + log1("after: Thread.sleep"); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005.java new file mode 100644 index 00000000000..2d0ddbfc45d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * Test check up this method for the following values: + * Long.MIN_VALUE, -1 and Long.MAX_VALUE. + * IllegalArgumentException is expected for negative values. + */ +public class remove_l005 { + private final static String prefix = "nsk.jdi.EventQueue.remove_l."; + private final static String debuggerName = prefix + "remove_l005"; + private final static String debugeeName = debuggerName + "a"; + + private final static String brkpMethodName = "run"; + private final static int brkpLineNumber = 61; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + public final static String SGNL_GO = "go"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static long waitTimes[] = { + Long.MIN_VALUE, + -1, + Long.MAX_VALUE + }; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + remove_l005 thisTest = new remove_l005(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType refType = debugee.classByName(debugeeName); + BreakpointRequest brkpReq = debugee.setBreakpoint(refType, brkpMethodName, brkpLineNumber); + + display("\nTEST BEGINS"); + display("==========="); + + Event event = null; + EventSet eventSet = null; + EventIterator eventIterator = null; + + debugee.sendSignal(SGNL_GO); + + for (int i = 0; i < waitTimes.length; i++) { + try { + display("invoking EventQueue.remove(" + waitTimes[i] + ")"); + eventSet = debugee.VM().eventQueue().remove(waitTimes[i]); + if (waitTimes[i] < 0) { + complain("No exception was thrown for negative argument: " + waitTimes[i]); + exitStatus = Consts.TEST_FAILED; + } else { + display("No exception was thrown for not-negative argument: " + waitTimes[i]); + } + if (eventSet != null) { + if (checkBrkpEvent(eventSet, brkpReq)) { + eventSet.resume(); + debugee.sendSignal(SGNL_GO); + } else { + eventSet.resume(); + } + } + } catch (IllegalArgumentException e1) { + if (waitTimes[i] < 0) { + display("Expected IllegalArgumentException was thrown for negative argument: " + waitTimes[i]); + } else { + complain("Unexpected IllegalArgumentException was thrown for not-negative argument: " + waitTimes[i]); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected exception was thrown for argument: " + waitTimes[i] + " :\n\t" + e ); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + display(""); + display("============="); + display("TEST FINISHES\n"); + + brkpReq.disable(); + debugee.resume(); + debugee.quit(); + } + + private boolean checkBrkpEvent(EventSet eventSet, BreakpointRequest brkpReq) { + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) { + EventRequest eventRequest = event.request(); + if (brkpReq.equals(eventRequest)) { + log.display("Got expected BreakpointEvent:\n\t" + event); + return true; + } + } + log.display("Ignore unexpected event:\n\t" + event); + } + return false; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005/TestDescription.java new file mode 100644 index 00000000000..6197ad3a371 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventQueue/remove_l/remove_l005. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-8068225 + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method + * com.sun.jdi.event.EventQueue.remove(long) + * for boundary value of parameters. + * Test check up this method for the following arguments: + * Long.MIN_VALUE, -1 and Long.MAX_VALUE. + * IllegalArgumentException is expected for negative arguments. + * COMMENTS: + * 4777928 TEST_BUG: two jdi tests should expect IllegalArgumentException + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - implicit handling VMStartEvent was removed from the debugger part of the test + * - BreakpointEvent is used instead for testing EventQueue.remove() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventQueue.remove_l.remove_l005 + * nsk.jdi.EventQueue.remove_l.remove_l005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventQueue.remove_l.remove_l005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005a.java new file mode 100644 index 00000000000..d149c74e430 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventQueue.remove_l; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * remove_l005a is deugee's part of the remove_l005. + */ +public class remove_l005a { + private static Log log; + private static IOPipe pipe; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(remove_l005.SGNL_READY); + int status = run(); + System.exit(status + Consts.JCK_STATUS_BASE); + } + + public static int run() { + for (int i = 0; ; i++) { + String instr = pipe.readln(); + if (instr.equals(remove_l005.SGNL_GO)) { + log.display("Go for iteration #" + i); + } else if (instr.equals(remove_l005.SGNL_QUIT)) { + log.display("Quit iterations"); + return Consts.TEST_PASSED; + } else { + log.complain("Unexpected signal received: " + instr); + return Consts.TEST_FAILED; + } + + // next line is for breakpoint + log.display("Breakpoint line reached"); // remove_l005.brkpLineNumber + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001.java new file mode 100644 index 00000000000..4191640334f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * + * The test checks up the methods of com.sun.jdi.EventRequest:
    + * 1. putProperty(Object, Object)
    + * 2. getProperty(Object)
    + * 3. setSuspendPolicy(int)
    + * to correctly work for boundary values of argument.
    + * + * The test performs the next testcases:
    + * 1. putProperty(null, String) - in this case it is + * expected property null with value of + * String will be created.
    + * No exception must be thrown. + * 2. getProperty(null) - value of String from + * the previous case is expected as return value. No exception must + * be thrown.
    + * 3. setSuspendPolicy(int) is checked for the next + * parameters: Integer.MIN_VALUE, -1, + * Integer.MAX_VALUE. IllegalArgumentException is expected.
    + */ + +public class eventrequest001 { + + private final static String prefix = "nsk.jdi.EventRequest._bounds_."; + private final static String debuggerName = prefix + "eventrequest001"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + public static int exitStatus; + public static Log log; + public static Debugee debugee; + + private static String propertyValue = "something"; + private static int policies[] = { + Integer.MIN_VALUE, + -1, + Integer.MAX_VALUE + }; + +//---------------------------------------------------- + + public static void display(String msg) { + log.display(msg); + } + + public static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + eventrequest001 thisTest = new eventrequest001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + ReferenceType testedClass = debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + eventrequest001a.brkpMethodName, + eventrequest001a.brkpLineNumber); + + display("\nTEST BEGINS"); + display("==========="); + + try { + display("setting property : value <" + propertyValue + ">"); + brkp.putProperty(null, propertyValue); + } catch (Exception e) { + complain("Unexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + Object obj = null; + try { + display("reading property :"); + obj = brkp.getProperty(null); + display("\t\t value : <" + obj + ">"); + } catch (Exception e) { + complain("Unexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + if (!obj.equals(propertyValue)) { + complain("Unexpected property value: " + obj); + exitStatus = Consts.TEST_FAILED; + } + + display(""); + for (int i = 0; i < policies.length; i++) { + display("invoking brkp.setSuspendPolicy(" + policies[i] + ")"); + brkp.disable(); + try { + brkp.setSuspendPolicy(policies[i]); + + complain("No exception was thrown for argument: " + policies[i]); + exitStatus = Consts.TEST_FAILED; + } catch (IllegalArgumentException e1) { + display("Expected IllegalArgumentException was thrown for argument: " + policies[i]); + } catch (Exception e) { + complain("Unexpected exception was thrown for argument: " + policies[i] + " :\n\t" + e ); + exitStatus = Consts.TEST_FAILED; + } + brkp.enable(); + display(""); + } + + // breakpoint should be disabled before test finishing + brkp.disable(); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001/TestDescription.java new file mode 100644 index 00000000000..929c94b2846 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/_bounds_/eventrequest001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the methods of com.sun.jdi.EventRequest: + * 1. putProperty(Object, Object) + * 2. getProperty(Object) + * 3. setSuspendPolicy(int) + * to correctly work for boundary values of argument. + * The test performs the next testcases: + * 1. putProperty(null, String) - in this case it is expected + * property with value of will be created. + * No exception must be thrown. + * 2. getProperty(null) - value of from the previous + * case is expected as return value. No exception must be thrown. + * 3. setSuspendPolicy(int) is checked for the next parameters: + * Integer.MIN_VALUE, -1, Integer.MAX_VALUE. IllegalArgumentException + * is expected. + * COMMENTS: + * 4777928 TEST_BUG: two jdi tests should expect IllegalArgumentException + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * Test fixed according to test bug: + * 4862601 TEST_BUG: JDI: Unexpected exception was thrown for argument: -2147483648 + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest._bounds_.eventrequest001 + * nsk.jdi.EventRequest._bounds_.eventrequest001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest._bounds_.eventrequest001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001a.java new file mode 100644 index 00000000000..e672d6b21e5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/_bounds_/eventrequest001a.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * eventrequest001a is deugee's part of the eventrequest001. + */ +public class eventrequest001a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 47; + private static Log log; + private static IOPipe pipe; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(eventrequest001.SGNL_READY); + String instr = pipe.readln(); // brkpLineNumber + if (instr.equals(eventrequest001.SGNL_QUIT)) { + log.display("constructor> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("constructor> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java new file mode 100644 index 00000000000..7ae39143415 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.addCountFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.addCountFilter()
    + * complies with its spec.
    + *
    + * The test checks up on following assertions:
    + * - Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + * - Throws: IllegalArgumentException - if count is less than one.
    + * The cases to check include Requests of all sub-types.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class addcountfilter001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/addCountFilter/addcountfilter001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addcountfilter001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.addCountFilter.addcountfilter001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.addCountFilter.TestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + String propertyName = "name"; + String propertyValue1 = "value1"; + String propertyValue2 = "value2"; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + try { + log2("......eventRequest1.addCountFilter(-1); IllegalArgumentException is expected"); + eventRequest1.addCountFilter(-1); + testExitCode = FAILED; + log3("ERROR: NO IllegalArgumentException"); + } catch ( IllegalArgumentException e ) { + log2(" IllegalArgumentException"); + } + + try { + log2("......eventRequest1.addCountFilter(0); IllegalArgumentException is expected"); + eventRequest1.addCountFilter(0); + testExitCode = FAILED; + log3("ERROR: NO IllegalArgumentException"); + } catch ( IllegalArgumentException e ) { + log2(" IllegalArgumentException"); + } + + try { + log2("......eventRequest1.addCountFilter(1); no IllegalArgumentException is expected"); + eventRequest1.addCountFilter(1); + log2(" no IllegalArgumentException"); + } catch ( IllegalArgumentException e ) { + testExitCode = FAILED; + log3("ERROR: IllegalArgumentException"); + } + + try { + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + log2(" eventRequest1.addCountFilter(1); InvalidRequestStateException is expected"); + eventRequest1.addCountFilter(1); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + try { + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + log2(" eventRequest1.addCountFilter(1); InvalidRequestStateException is expected"); + eventRequest1.addCountFilter(1); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001/TestDescription.java new file mode 100644 index 00000000000..25705171bf2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/addCountFilter/addcountfilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.addCountFilter() + * complies with its spec: + * public void addCountFilter(int count) + * Limit the requested event to be reported at most once + * after a given number of occurrences. + * The event is not reported the first count - 1 times this filter is reached. + * To request a one-off event, call this method with a count of 1. + * Once the count reaches 0, + * any subsequent filters in this request are applied. + * If none of those filters cause the event to be suppressed, + * the event is reported. Otherwise, the event is not reported. + * In either case subsequent events are never reported for this request. + * Parameters: count - the number of ocurrences before generating an event. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * IllegalArgumentException - if count is less than one. + * The test checks up on following assertions: + * - Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * - Throws: IllegalArgumentException - if count is less than one. + * The cases to check include Requests of all sub-types. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.addCountFilter.addcountfilter001; + * the debuggee program - nsk.jdi.EventRequest.addCountFilter.addcountfilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.addCountFilter.addcountfilter001 + * nsk.jdi.EventRequest.addCountFilter.addcountfilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.addCountFilter.addcountfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001a.java new file mode 100644 index 00000000000..ae0ff12fffe --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.addCountFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addcountfilter001 JDI test. + */ + +public class addcountfilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1addcountfilter001a thread1 = null; + + static TestClass11 obj = new TestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1addcountfilter001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + addcountfilter001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class TestClass11 extends TestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + addcountfilter001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1addcountfilter001a extends Thread { + + String tName = null; + + public Thread1addcountfilter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + addcountfilter001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(addcountfilter001a.waitnotifyObj) { + addcountfilter001a.waitnotifyObj.notify(); + } + synchronized(addcountfilter001a.lockObj) { + TestClass11.method11(); + } + addcountfilter001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java new file mode 100644 index 00000000000..d14abb8477e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.disable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.disable()
    + * complies with its spec.
    + *
    + * The test checks up on if a value returned by the method
    + * EventRequest.isEnabled() matchs a value set up with
    + * the method EventRequest.disable().
    + * The cases to test include all sub-types of EventRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class disable001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/disable/disable001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new disable001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.disable.disable001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.disable.disable001aTestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRequest1.setEnabled(true);"); + eventRequest1.setEnabled(true); + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + + log2(" checking up on eventRequest1"); + if ( eventRequest1.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: EventRequest is still enabled"); + } + eventRequest1.setEnabled(false); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001/TestDescription.java new file mode 100644 index 00000000000..37e77793b6a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/disable/disable001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.disable() + * complies with its spec: + * public void disable() + * Same as setEnabled(false). + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * The test checks up on if a value returned by the method EventRequest.isEnabled() + * matchs a value set up with the method EventRequest.disable(), that is, false. + * The cases to test include all sub-types of EventRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.disable.disable001; + * the debuggee program - nsk.jdi.EventRequest.disable.disable001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.disable.disable001 + * nsk.jdi.EventRequest.disable.disable001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.disable.disable001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001a.java new file mode 100644 index 00000000000..d73f0332b86 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.disable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the disable001 JDI test. + */ + +public class disable001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static disable001aThread1 thread1 = null; + + static disable001aTestClass11 obj = new disable001aTestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new disable001aThread1("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class disable001aTestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + disable001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class disable001aTestClass11 extends disable001aTestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + disable001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class disable001aThread1 extends Thread { + + String tName = null; + + public disable001aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + disable001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(disable001a.waitnotifyObj) { + disable001a.waitnotifyObj.notify(); + } + synchronized(disable001a.lockObj) { + disable001aTestClass11.method11(); + } + disable001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java new file mode 100644 index 00000000000..d407d9b45f4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.disable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.disable()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request has been deleted.
    + * The cases to test include all sub-types of EventRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class disable002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/disable/disable002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new disable002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.disable.disable002a"; + + private String testedClassName = + "nsk.jdi.EventRequest.disable.disable002aTestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.enable(); InvalidRequestStateException is expected"); + eventRequest1.disable(); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002/TestDescription.java new file mode 100644 index 00000000000..eab65bc40d1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/disable/disable002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.disable() + * complies with its spec: + * public void disable() + * Same as setEnabled(false). + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * The cases to test include all sub-types of EventRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.disable.disable002; + * the debuggee program - nsk.jdi.EventRequest.disable.disable002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.disable.disable002 + * nsk.jdi.EventRequest.disable.disable002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.disable.disable002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002a.java new file mode 100644 index 00000000000..9f5fa78e44e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.disable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the disable002 JDI test. + */ + +public class disable002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static disable002aThread1 thread1 = null; + + static disable002aTestClass11 obj = new disable002aTestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new disable002aThread1("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----1"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class disable002aTestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + disable002a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class disable002aTestClass11 extends disable002aTestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + disable002a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class disable002aThread1 extends Thread { + + String tName = null; + + public disable002aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + disable002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(disable002a.waitnotifyObj) { + disable002a.waitnotifyObj.notify(); + } + synchronized(disable002a.lockObj) { + disable002aTestClass11.method11(); + } + disable002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003.java new file mode 100644 index 00000000000..c33b23918bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequest.disable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test checks up com.sun.jdi.EventRequest.disable() after + * class file redefinition. + * + * The test performs as follow: + * Debuggee has two classes. Debugger creates a BreakpointRequest + * at the first class and waits a corresponding event. After getting + * BreakpointEvent, debugger redefines the second class, tries to + * disable the set breakpoint and checks status of the BreakpointRequest + * to be disabled. + */ + +public class disable003 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.EventRequest.disable."; + private final static String debuggerName = prefix + "disable003"; + public final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b"; + + private final static String classFileName = "disable003b.class"; + private final static String newClassFile = "newclass" + File.separator + + prefix.replace('.',File.separatorChar) + + classFileName; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + public final static int expectedEventCount = 1; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain(msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + disable003 thisTest = new disable003(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.redirectOutput(log); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + int eventCount = 0; + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\nevent ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\nevent ===>>> " + event); + prepareTestCases(); + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\nevent ===>>> " + event); + ClassType testedClass; + testedClass = (ClassType )debugee.classByName(testedClassName); + + display("\nredefinition of the \"" + + testedClassName + "\" class"); + redefineDebugee(testedClass, newClassFile); + + eventCount++; + boolean isBrkpEnabled = event.request().isEnabled(); + if (!isBrkpEnabled) { + complain("breakpoint was disabled after " + + "the redefinition of an other class"); + exitStatus = Consts.TEST_FAILED; + } else { + display("\nis breakpoint enabled?\t" + isBrkpEnabled); + display("\ndisabling the breakpoint request..."); + event.request().disable(); + if (event.request().isEnabled()) { + complain("breakpoint is not disabled"); + exitStatus = Consts.TEST_FAILED; + } + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (eventCount != expectedEventCount) { + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee(ReferenceType refType, String classFileName) { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(refType, classFileName); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(ReferenceType refType, String fileName) { + display("a new class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(refType, arrayToRedefine); + return mapForClass; + } + + private void prepareTestCases() { + debugeeClass = debugee.classByName(debugeeName); + display("debugeeClass\t\t:" + debugeeClass.name()); + display("setting breakpoint..."); + debugee.setBreakpoint(debugeeClass, + disable003a.brkpMethodName, + disable003a.brkpLineNumber); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003/TestDescription.java new file mode 100644 index 00000000000..6039b23acf5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/disable/disable003. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up com.sun.jdi.EventRequest.disable() after + * class file redefinition. + * The test performs as follow: + * Debuggee has two classes (A and B). Debugger creates a BreakpointRequest + * at the first class A and waits a corresponding event. After getting + * BreakpointEvent, debugger redefines the second class B, tries to disable + * the set breakpoint and checks status of the BreakpointRequest to be + * disabled. + * COMMENTS + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.disable.disable003 + * nsk.jdi.EventRequest.disable.disable003a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.disable.disable003 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003/newclass/disable003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003/newclass/disable003b.java new file mode 100644 index 00000000000..ee99f7ea9f7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003/newclass/disable003b.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequest.disable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * disable003b is deugee's part of the disable003. + */ + +public class disable003b { + public final static int INITIAL_VALUE = 0; + public final static int BEFORE_REDEFINITION = 1; + public final static int AFTER_REDEFINITION = 2; + + public static boolean loadClass = false; + public static int flag = INITIAL_VALUE; + + public static void runIt(boolean doWait) { + + flag = AFTER_REDEFINITION; +// ^^^^^^^^^^^^^^^^^^^ it will be redefined + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003a.java new file mode 100644 index 00000000000..072ed63d857 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003a.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequest.disable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * disable003a is deugee's part of the disable003. + */ +public class disable003a { + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.out, argHandler); + + disable003b.loadClass = true; + + log.display("completed succesfully."); // brkpLineNumber + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003b.java new file mode 100644 index 00000000000..4025db6174c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable003b.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequest.disable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * disable003b is deugee's part of the disable003. + */ + +public class disable003b { + public final static int INITIAL_VALUE = 0; + public final static int BEFORE_REDEFINITION = 1; + public final static int AFTER_REDEFINITION = 2; + + public static boolean loadClass = false; + public static int flag = INITIAL_VALUE; + + public static void runIt(boolean doWait) { + + flag = BEFORE_REDEFINITION; +// ^^^^^^^^^^^^^^^^^^^ it will be redefined + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java new file mode 100644 index 00000000000..96c6ef3200c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.enable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.enable()
    + * complies with its spec.
    + *
    + * The test checks up on if a value returned by the method
    + * EventRequest.isEnabled() matchs a value set up with
    + * the method EventRequest.enable().
    + * The cases to test include all sub-types of EventRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class enable001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/enable/enable001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new enable001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.enable.enable001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.enable.enable001aTestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + log2(" checking up on eventRequest1"); + if ( !eventRequest1.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: EventRequest is not enabled"); + } + eventRequest1.disable(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001/TestDescription.java new file mode 100644 index 00000000000..28b756943be --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/enable/enable001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.enable() + * complies with its spec: + * public void enable() + * Same as setEnabled(true). + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * IllegalThreadStateException - + * if this is a StepRequest and the thread named in the request has died. + * The test checks up on if a value returned by the method EventRequest.isEnabled() + * matchs a value set up with the method EventRequest.enable(), that is, true. + * The cases to test include all sub-types of EventRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.enable.enable001; + * the debuggee program - nsk.jdi.EventRequest.enable.enable001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.enable.enable001 + * nsk.jdi.EventRequest.enable.enable001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.enable.enable001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001a.java new file mode 100644 index 00000000000..d979bf28129 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.enable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the enable001 JDI test. + */ + +public class enable001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static enable001aThread1 thread1 = null; + + static enable001aTestClass11 obj = new enable001aTestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new enable001aThread1("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class enable001aTestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + enable001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class enable001aTestClass11 extends enable001aTestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + enable001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class enable001aThread1 extends Thread { + + String tName = null; + + public enable001aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + enable001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(enable001a.waitnotifyObj) { + enable001a.waitnotifyObj.notify(); + } + synchronized(enable001a.lockObj) { + enable001aTestClass11.method11(); + } + enable001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java new file mode 100644 index 00000000000..fb70ef42655 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.enable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.enable()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request has been deleted.
    + * IllegalThreadStateException -
    + * if this is a StepRequest and
    + * the thread named in the request has died.
    + * The cases to test include all sub-types of EventRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class enable002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/enable/enable002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new enable002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.enable.enable002a"; + + private String testedClassName = + "nsk.jdi.EventRequest.enable.enable002aTestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + vm.resume(); + breakpointForCommunication(); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + if (eventRequest1 instanceof StepRequest) { + try { + log2("......eventRequest1.enable(); IllegalThreadStateException is expected"); + eventRequest1.enable(); + testExitCode = FAILED; + log3("ERROR: NO IllegalThreadStateException for StepRequest"); + } catch ( IllegalThreadStateException e ) { + log2(" IllegalThreadStateException"); + } + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.enable(); InvalidRequestStateException is expected"); + eventRequest1.enable(); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002/TestDescription.java new file mode 100644 index 00000000000..1b172607dac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/enable/enable002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.enable() + * complies with its spec: + * public void enable() + * Same as setEnabled(true). + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * IllegalThreadStateException - + * if this is a StepRequest and the thread named in the request has died. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * IllegalThreadStateException - + * if this is a StepRequest and the thread named in the request has died. + * The cases to test include all sub-types of EventRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.enable.enable002; + * the debuggee program - nsk.jdi.EventRequest.enable.enable002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.enable.enable002 + * nsk.jdi.EventRequest.enable.enable002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.enable.enable002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002a.java new file mode 100644 index 00000000000..1035cad5c5a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002a.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.enable; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the enable002 JDI test. + */ + +public class enable002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static enable002aThread1 thread1 = null; + + static enable002aTestClass11 obj = new enable002aTestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new enable002aThread1("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----1"); + methodForCommunication(); + } + try { + thread1.join(); + log1("methodForCommunication();----2"); + methodForCommunication(); + } catch ( InterruptedException e ) { + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class enable002aTestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + enable002a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class enable002aTestClass11 extends enable002aTestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + enable002a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class enable002aThread1 extends Thread { + + String tName = null; + + public enable002aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + enable002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(enable002a.waitnotifyObj) { + enable002a.waitnotifyObj.notify(); + } + synchronized(enable002a.lockObj) { + enable002aTestClass11.method11(); + } + enable002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java new file mode 100644 index 00000000000..c2901199e37 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java @@ -0,0 +1,558 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.getProperty; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.getProperty()
    + * complies with its spec.
    + *
    + * The test checks up on following assertions:
    + * - a value of property is equal to one assigned with method
    + * putProperty(key, value); + * - the value of the property which is not assign with method
    + * putProperty(key, value), is the null.
    + * The cases to check include Requests of all sub-types.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class getproperty001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/getProperty/getproperty001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new getproperty001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.getProperty.getproperty001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.getProperty.TestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + String propertyName1 = "name1"; + String propertyName2 = "name2"; + String propertyValue1 = "value1"; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRequest1.putProperty(propertyName1, propertyValue1);"); + eventRequest1.putProperty(propertyName1, propertyValue1); + + log2(" checking up on property1"); + if ( !eventRequest1.getProperty(propertyName1).equals(propertyValue1) ) { + testExitCode = FAILED; + log3("ERROR: property is not expected"); + }; + + log2(" checking up on property2"); + if ( eventRequest1.getProperty(propertyName2)!= null ) { + testExitCode = FAILED; + log3("ERROR: property is not the null"); + } + + eventRequest1.setEnabled(false); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001/TestDescription.java new file mode 100644 index 00000000000..3ab89f7b38a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/getProperty/getproperty001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.getProperty() + * complies with its spec: + * public Object getProperty(Object key) + * Returns the value of the property with the specified key. + * Only properties added with putProperty(java.lang.Object, java.lang.Object) + * will return a non-null value. + * Returns: the value of this property or null + * The test checks up on following assertions: + * - a value of property is equal to one assigned with method putProperty(key, value); + * - the value of the property which is not assign with method putProperty(key, value), + * is the null. + * The cases to check include Requests of all sub-types. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.getProperty.getproperty001; + * the debuggee program - nsk.jdi.EventRequest.getProperty.getproperty001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.getProperty.getproperty001 + * nsk.jdi.EventRequest.getProperty.getproperty001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.getProperty.getproperty001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001a.java new file mode 100644 index 00000000000..d8c30f9ba73 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.getProperty; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getproperty001 JDI test. + */ + +public class getproperty001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1getproperty001a thread1 = null; + + static TestClass11 obj = new TestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1getproperty001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + getproperty001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class TestClass11 extends TestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + getproperty001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1getproperty001a extends Thread { + + String tName = null; + + public Thread1getproperty001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + getproperty001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(getproperty001a.waitnotifyObj) { + getproperty001a.waitnotifyObj.notify(); + } + synchronized(getproperty001a.lockObj) { + TestClass11.method11(); + } + getproperty001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001.java new file mode 100644 index 00000000000..9b033475cb2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequest.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class hashcode001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.EventRequest.hashCode."; + private final static String className = "hashcode001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String methodName = "main"; + private final static String fieldName = "exitStatus"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + EventRequestManager eventRequestManager = debuggee.VM().eventRequestManager(); + EventRequest eventRequest; + + display("Checking hashCode() method for EventRequest objects"); + + for (int i = 0; i < 12; i++) { + + switch (i) { + + case 0: + ThreadReference thread = threadByName(methodName); + + display(".....setting up StepRequest"); + eventRequest = eventRequestManager.createStepRequest + (thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + display(".....setting up AccessWatchpointRequest"); + eventRequest = eventRequestManager.createAccessWatchpointRequest + (debuggeeClass.fieldByName(fieldName)); + break; + + case 2: + display(".....setting up ModificationWatchpointRequest"); + eventRequest = eventRequestManager.createModificationWatchpointRequest + (debuggeeClass.fieldByName(fieldName)); + break; + + case 3: + display(".....setting up ClassPrepareRequest"); + eventRequest = eventRequestManager.createClassPrepareRequest(); + break; + + case 4: + display(".....setting up ClassUnloadRequest"); + eventRequest = eventRequestManager.createClassUnloadRequest(); + break; + + case 5: + display(".....setting up MethodEntryRequest"); + eventRequest = eventRequestManager.createMethodEntryRequest(); + break; + + case 6: + display(".....setting up MethodExitRequest"); + eventRequest = eventRequestManager.createMethodExitRequest(); + break; + + case 7: + display(".....setting up ThreadDeathRequest"); + eventRequest = eventRequestManager.createThreadDeathRequest(); + break; + + case 8: + display(".....setting up ThreadStartRequest"); + eventRequest = eventRequestManager.createThreadStartRequest(); + break; + + case 9: + display(".....setting up VMDeathRequest"); + eventRequest = eventRequestManager.createVMDeathRequest(); + break; + + case 10: + display(".....setting up ExceptionRequest"); + eventRequest = eventRequestManager.createExceptionRequest( null, true, true ); + break; + + case 11: + display(".....setting up BreakpointRequest"); + Method method = methodByName(debuggeeClass, methodName); + List locs = null; + try { + locs = method.allLineLocations(); + } catch(AbsentInformationException e) { + throw new Failure("Unexpected AbsentInformationException while getting "); + } + Location location = (Location)locs.get(0); + eventRequest = eventRequestManager.createBreakpointRequest(location); + break; + + default: + throw new Failure("Wrong test case : " + i); + } + + int hCode = eventRequest.hashCode(); + + if (hCode == 0) { + complain("hashCode() returns 0 for EventRequest object " + eventRequest); + exitStatus = Consts.TEST_FAILED; + } + + int hCode1 = eventRequest.hashCode(); + if (hCode != hCode1) { + complain("hashCode() is not consistent for EventRequest object " + eventRequest + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + display("hashCode() returns " + hCode + " for EventRequest object : " + eventRequest); + eventRequestManager.deleteEventRequest(eventRequest); + } + + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + + private static Method methodByName(ReferenceType refType, String methodName) { + List methodList = refType.methodsByName(methodName); + if (methodList == null) return null; + + Method method = (Method) methodList.get(0); + return method; + } + + static private ThreadReference threadByName(String name) { + + List all = debuggee.VM().allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread IS NOT found : " + name); + } + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..d745485ff9f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/hashCode/hashcode001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public hashCode() method of an implementing class of + * com.sun.jdi.request.EventRequest interface. + * The test checks an assertion cited from spec for hashCode() method of + * java.lang.Object class: + * The general contract of hashCode is: + * - Whenever it is invoked on the same object more than once during + * an execution of a Java application, the hashCode method must + * consistently return the same integer, provided no information used + * in equals comparisons on the object is modified. + * ... + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for EventRequest + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.hashCode.hashcode001 + * nsk.jdi.EventRequest.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001a.java new file mode 100644 index 00000000000..a50e56ef161 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001a.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequest.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class hashcode001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(hashcode001.SIGNAL_READY); + receiveSignal(hashcode001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java new file mode 100644 index 00000000000..d6dbbba2bec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.isEnabled; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.isEnabled()
    + * complies with its spec.
    + *
    + * The test checks up on if a value returned by the method
    + * EventRequest.isEnabled() matchs a value set up with
    + * the method EventRequest.setEnabled().
    + * The cases to test include all sub-types of EventRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class isenabled001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/isEnabled/isenabled001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new isenabled001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.isEnabled.isenabled001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.isEnabled.TestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRequest1.setEnabled(true);"); + eventRequest1.setEnabled(true); + log2(" checking up on eventRequest1"); + if ( !eventRequest1.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: EventRequest is not enabled"); + } + + log2("......eventRequest1.setEnabled(false);"); + eventRequest1.setEnabled(false); + log2(" checking up on eventRequest1"); + if ( eventRequest1.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: EventRequest is enabled"); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001/TestDescription.java new file mode 100644 index 00000000000..c5e57b9a9dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/isEnabled/isenabled001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.isEnabled() + * complies with its spec: + * public boolean isEnabled() + * Determines if this event request is currently enabled. + * Returns: true if enabled; false otherwise. + * The test checks up on if a value returned by the method EventRequest.isEnabled() + * matchs a value set up with the method EventRequest.setEnabled(). + * The cases to test include all sub-types of EventRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.isEnabled.isenabled001; + * the debuggee program - nsk.jdi.EventRequest.isEnabled.isenabled001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.isEnabled.isenabled001 + * nsk.jdi.EventRequest.isEnabled.isenabled001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.isEnabled.isenabled001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001a.java new file mode 100644 index 00000000000..f366b25140c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.isEnabled; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the isenabled001 JDI test. + */ + +public class isenabled001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1isenabled001a thread1 = null; + + static TestClass11 obj = new TestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1isenabled001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + isenabled001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class TestClass11 extends TestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + isenabled001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1isenabled001a extends Thread { + + String tName = null; + + public Thread1isenabled001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + isenabled001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(isenabled001a.waitnotifyObj) { + isenabled001a.waitnotifyObj.notify(); + } + synchronized(isenabled001a.lockObj) { + TestClass11.method11(); + } + isenabled001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java new file mode 100644 index 00000000000..2f498c2e457 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.putProperty; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.putProperty()
    + * complies with its spec.
    + *
    + * The test checks up on following assertions:
    + * - a value of property is equal to one assigned by
    + * last method putProperty(key, value);
    + * - after calling putProperty(key, null)
    + * the value of the property 'key' is also null.
    + * The cases to check include Requests of all sub-types.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class putproperty001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/putProperty/putproperty001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new putproperty001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.putProperty.putproperty001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.putProperty.TestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + String propertyName = "name"; + String propertyValue1 = "value1"; + String propertyValue2 = "value2"; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRequest1.putProperty(propertyName, propertyValue1);"); + eventRequest1.putProperty(propertyName, propertyValue1); + log2(" eventRequest1.putProperty(propertyName, propertyValue2);"); + eventRequest1.putProperty(propertyName, propertyValue2); + + log2(" checking up on eventRequest1"); + if ( !eventRequest1.getProperty(propertyName).equals(propertyValue2) ) { + testExitCode = FAILED; + log3("ERROR: property is not expected"); + } + + log2("......eventRequest1.putProperty(propertyName, null);"); + eventRequest1.putProperty(propertyName, null); + + log2(" checking up on eventRequest1"); + if ( eventRequest1.getProperty(propertyName)!= null ) { + testExitCode = FAILED; + log3("ERROR: property is not the null"); + } + + eventRequest1.setEnabled(false); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001/TestDescription.java new file mode 100644 index 00000000000..bdf1970cd11 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/putProperty/putproperty001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.putProperty() + * complies with its spec: + * public void putProperty(Object key, Object value) + * Add an arbitrary key/value "property" to this request. + * The property can be used by a client of the JDI + * to associate application information with the request; + * These client-set properties are not used internally by the JDI. + * The get/putProperty methods provide access to a small per-instance map. + * This is not to be confused with Properties. + * If value is null this method will remove the property. + * The test checks up on following assertions: + * - a value of property is equal to one assigned by last method putProperty(key, value); + * - after calling putProperty(key, null) the value of the property 'key' is also null. + * The cases to check include Requests of all sub-types. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.putProperty.putproperty001; + * the debuggee program - nsk.jdi.EventRequest.putProperty.putproperty001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.putProperty.putproperty001 + * nsk.jdi.EventRequest.putProperty.putproperty001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.putProperty.putproperty001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001a.java new file mode 100644 index 00000000000..6e5b815919a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.putProperty; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the putproperty001 JDI test. + */ + +public class putproperty001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1putproperty001a thread1 = null; + + static TestClass11 obj = new TestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1putproperty001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + putproperty001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class TestClass11 extends TestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + putproperty001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1putproperty001a extends Thread { + + String tName = null; + + public Thread1putproperty001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + putproperty001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(putproperty001a.waitnotifyObj) { + putproperty001a.waitnotifyObj.notify(); + } + synchronized(putproperty001a.lockObj) { + TestClass11.method11(); + } + putproperty001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java new file mode 100644 index 00000000000..26571b466bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.setEnabled; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.setEnabled()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Enables or disables this event request.
    + * The cases to test include all sub-types of EventRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class setenabled001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/setEnabled/setenabled001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new setenabled001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.setEnabled.setenabled001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.setEnabled.setenabled001aTestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRequest1.setEnable(true);"); + eventRequest1.setEnabled(true); + log2(" checking up on eventRequest1"); + if ( !eventRequest1.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: EventRequest is not enabled"); + } + + log2("......eventRequest1.setEnable(false);"); + eventRequest1.setEnabled(false); + log2(" checking up on eventRequest1"); + if ( eventRequest1.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: EventRequest is enabled"); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001/TestDescription.java new file mode 100644 index 00000000000..cd28429b8d4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/setEnabled/setenabled001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.setEnabled() + * complies with its spec: + * public void setEnabled(boolean val) + * Enables or disables this event request. + * While this event request is disabled, the event request will be ignored and + * the target VM will not be stopped if any of its threads reaches the event request. + * Disabled event requests still exist, and are included in event request lists + * such as EventRequestManager.breakpointRequests(). + * Parameters: val - true if the event request is to be enabled; false otherwise. + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * IllegalThreadStateException - + * if this is a StepRequest, val is true, and + * the thread named in the request has died. + * The test checks up on the following assertion: + * Enables or disables this event request. + * The cases to test include all sub-types of EventRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.setEnabled.setenabled001; + * the debuggee program - nsk.jdi.EventRequest.setEnabled.setenabled001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.setEnabled.setenabled001 + * nsk.jdi.EventRequest.setEnabled.setenabled001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.setEnabled.setenabled001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001a.java new file mode 100644 index 00000000000..fb1efae4e4f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.setEnabled; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the setenabled001 JDI test. + */ + +public class setenabled001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static setenabled001aThread1 thread1 = null; + + static setenabled001aTestClass11 obj = new setenabled001aTestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new setenabled001aThread1("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class setenabled001aTestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + setenabled001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class setenabled001aTestClass11 extends setenabled001aTestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + setenabled001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class setenabled001aThread1 extends Thread { + + String tName = null; + + public setenabled001aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + setenabled001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(setenabled001a.waitnotifyObj) { + setenabled001a.waitnotifyObj.notify(); + } + synchronized(setenabled001a.lockObj) { + setenabled001aTestClass11.method11(); + } + setenabled001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java new file mode 100644 index 00000000000..f46aaa16f89 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.setEnabled; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.setEnabled()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - IllegalThreadStateException -
    + * if this is a StepRequest, val is true, and
    + * the thread named in the request has died.
    + * - InvalidRequestStateException -
    + * if this request has been deleted.
    + * The cases to test include all sub-types of EventRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class setenabled002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/setEnabled/setenabled002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new setenabled002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.setEnabled.setenabled002a"; + + private String testedClassName = + "nsk.jdi.EventRequest.setEnabled.setenabled002aTestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + vm.resume(); + breakpointForCommunication(); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + if (eventRequest1 instanceof StepRequest) { + try { + log2("......eventRequest1.setEnabled(true); IllegalThreadStateException is expected"); + eventRequest1.setEnabled(true); + testExitCode = FAILED; + log3("ERROR: NO IllegalThreadStateException for StepRequest"); + } catch ( IllegalThreadStateException e ) { + log2(" IllegalThreadStateException"); + } + try { + log2("......eventRequest1.setEnabled(false); IllegalThreadStateException is not expected"); + eventRequest1.setEnabled(false); + log2(" no IllegalThreadStateException for StepRequest"); + } catch ( IllegalThreadStateException e ) { + testExitCode = FAILED; + log3("ERROR: IllegalThreadStateException"); + } + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.setEnabled(true); InvalidRequestStateException is expected"); + eventRequest1.setEnabled(true); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + try { + log2("......eventRequest1.setEnabled(false); InvalidRequestStateException is expected"); + eventRequest1.setEnabled(false); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002/TestDescription.java new file mode 100644 index 00000000000..7d5d2be4ab8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/setEnabled/setenabled002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.setEnabled() + * complies with its spec: + * public void setEnabled(boolean val) + * Enables or disables this event request. + * While this event request is disabled, the event request will be ignored and + * the target VM will not be stopped if any of its threads reaches the event request. + * Disabled event requests still exist, and are included in event request lists + * such as EventRequestManager.breakpointRequests(). + * Parameters: val - true if the event request is to be enabled; false otherwise. + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * IllegalThreadStateException - + * if this is a StepRequest, val is true, and + * the thread named in the request has died. + * The test checks up on the following assertions: + * - IllegalThreadStateException - if this is a StepRequest, val is true, and + * the thread named in the request has died. + * - InvalidRequestStateException - if this request has been deleted. + * The cases to test include all sub-types of EventRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.setEnabled.setenabled002; + * the debuggee program - nsk.jdi.EventRequest.setEnabled.setenabled002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.setEnabled.setenabled002 + * nsk.jdi.EventRequest.setEnabled.setenabled002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.setEnabled.setenabled002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002a.java new file mode 100644 index 00000000000..73d7954614f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002a.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.setEnabled; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the setenabled002 JDI test. + */ + +public class setenabled002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static setenabled002aThread1 thread1 = null; + + static setenabled002aTestClass11 obj = new setenabled002aTestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new setenabled002aThread1("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + try { + thread1.join(); + log1("methodForCommunication();----2"); + methodForCommunication(); + } catch ( InterruptedException e ) { + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class setenabled002aTestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + setenabled002a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class setenabled002aTestClass11 extends setenabled002aTestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + setenabled002a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class setenabled002aThread1 extends Thread { + + String tName = null; + + public setenabled002aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + setenabled002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(setenabled002a.waitnotifyObj) { + setenabled002a.waitnotifyObj.notify(); + } + synchronized(setenabled002a.lockObj) { + setenabled002aTestClass11.method11(); + } + setenabled002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java new file mode 100644 index 00000000000..e20a786d1c9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.setEnabled; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.setEnabled()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - IllegalThreadStateException -
    + * if this is a StepRequest, val is true, and
    + * the thread named in the request has died.
    + * The cases to test include three states of
    + * the thread named in the request: not started, running, dead.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class setenabled003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/setEnabled/setenabled003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new setenabled003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.setEnabled.setenabled003a"; + + private String testedClassName = + "nsk.jdi.EventRequest.setEnabled.Thread1setenabled003a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = (ThreadReference) + debuggeeClass.getValue(debuggeeClass.fieldByName(threadName1)); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + + try { + log2("......eventRequest1.setEnabled(true); IllegalThreadStateException is expected"); + eventRequest1.setEnabled(true); + log3("ERROR: case 0 : no IllegalThreadStateException"); + testExitCode = FAILED; + } catch ( IllegalThreadStateException e ) { + log2(" not started thread"); + log2(" : IllegalThreadStateException when setEnabled(true)"); + } + try { + log2("......eventRequest1.setEnabled(false); IllegalThreadStateException is not expected"); + eventRequest1.setEnabled(false); + log2(" no IllegalThreadStateException"); + } catch ( IllegalThreadStateException e ) { + testExitCode = FAILED; + log3("ERROR: case 0 : not started thread"); + log3(" : IllegalThreadStateException when setEnabled(false)"); + } + break; + + case 1: + try { + log2("......eventRequest1.setEnabled(true); IllegalThreadStateException is not expected"); + eventRequest1.setEnabled(true); + log2(" no IllegalThreadStateException"); + } catch ( IllegalThreadStateException e ) { + testExitCode = FAILED; + log3("ERROR: case 1 : running thread"); + log3(" : IllegalThreadStateException when setEnabled(true)"); + } + try { + log2("......eventRequest1.setEnabled(false); IllegalThreadStateException is not expected"); + eventRequest1.setEnabled(false); + log2(" no IllegalThreadStateException"); + } catch ( IllegalThreadStateException e ) { + testExitCode = FAILED; + log3("ERROR: case 1 : running thread"); + log3(" : IllegalThreadStateException when setEnabled(false)"); + } + break; + + case 2: + try { + log2("......eventRequest1.setEnabled(true); IllegalThreadStateException is expected"); + eventRequest1.setEnabled(true); + testExitCode = FAILED; + log3("ERROR: case 2 : dead thread"); + log3(" : NO IllegalThreadStateException when setEnabled(true)"); + } catch ( IllegalThreadStateException e ) { + log2(" IllegalThreadStateException"); + } + try { + log2("......eventRequest1.setEnabled(false); IllegalThreadStateException is not expected"); + eventRequest1.setEnabled(false); + log2(" no IllegalThreadStateException"); + } catch ( IllegalThreadStateException e ) { + testExitCode = FAILED; + log3("ERROR: case 2 : dead thread"); + log3(" : IllegalThreadStateException when setEnabled(false)"); + } + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003/TestDescription.java new file mode 100644 index 00000000000..691e7fd51b1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/setEnabled/setenabled003. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-8066993 + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.setEnabled() + * complies with its spec: + * public void setEnabled(boolean val) + * Enables or disables this event request. + * While this event request is disabled, the event request will be ignored and + * the target VM will not be stopped if any of its threads reaches the event request. + * Disabled event requests still exist, and are included in event request lists + * such as EventRequestManager.breakpointRequests(). + * Parameters: val - true if the event request is to be enabled; false otherwise. + * Throws: InvalidRequestStateException - + * if this request has been deleted. + * IllegalThreadStateException - + * if this is a StepRequest, val is true, and + * the thread named in the request has died. + * The test checks up on the following assertion: + * - IllegalThreadStateException - if this is a StepRequest, val is true, and + * the thread named in the request has died. + * The cases to test include three states of the thread named in the request: + * not started, running, dead. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.setEnabled.setenabled003; + * the debuggee program - nsk.jdi.EventRequest.setEnabled.setenabled003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.setEnabled.setenabled003 + * nsk.jdi.EventRequest.setEnabled.setenabled003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.setEnabled.setenabled003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003a.java new file mode 100644 index 00000000000..bc22fdd2846 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003a.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.setEnabled; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the setenabled003 JDI test. + */ + +public class setenabled003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1setenabled003a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1setenabled003a("thread1"); + Thread1setenabled003a.method(); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } +// case 2: + try { + thread1.join(); + log1("methodForCommunication();----2"); + methodForCommunication(); + } catch ( InterruptedException e ) { + } + i++; + + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class Thread1setenabled003a extends Thread { + + String tName = null; + + public Thread1setenabled003a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + setenabled003a.log1(" 'run': enter :: threadName == " + tName); + synchronized(setenabled003a.waitnotifyObj) { + setenabled003a.waitnotifyObj.notify(); + } + + synchronized(setenabled003a.lockObj) { + setenabled003a.log1(" 'run': exit :: threadName == " + tName); + } + return; + } + + static void method() { + setenabled003a.log1(" enetred: method"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java new file mode 100644 index 00000000000..c95834f1f19 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java @@ -0,0 +1,594 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.setSuspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.setSuspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks up on following assertions:
    + * - a value of policy is equal to one assigned by last method
    + * setSuspendPolicy(int);
    + * - InvalidRequestStateException is thrown
    + * if this request is currently enabled;
    + * - InvalidRequestStateException is thrown
    + * if this request has been deleted.
    + * The cases to check include Requests of all sub-types.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class setsuspendpolicy001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new setsuspendpolicy001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.setSuspendPolicy.setsuspendpolicy001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.setSuspendPolicy.TestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + String propertyName = "name"; + String propertyValue1 = "value1"; + String propertyValue2 = "value2"; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_NONE);"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_NONE); + + log2("......eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_ALL);"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_ALL); + + log2(" checking up on eventRequest1"); + if ( eventRequest1.suspendPolicy() != EventRequest.SUSPEND_ALL) { + testExitCode = FAILED; + log3("ERROR: suspendPolicy() != EventRequest.SUSPEND_ALL"); + } + + log2("......eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD );"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD ); + + log2(" checking up on eventRequest1"); + if ( eventRequest1.suspendPolicy() != EventRequest.SUSPEND_EVENT_THREAD ) { + testExitCode = FAILED; + log3("ERROR: suspendPolicy() != EventRequest.SUSPEND_EVENT_THREAD "); + } + + log2("......eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_NONE);"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_NONE); + + log2(" checking up on eventRequest1"); + if ( eventRequest1.suspendPolicy() != EventRequest.SUSPEND_NONE) { + testExitCode = FAILED; + log3("ERROR: suspendPolicy() != EventRequest.SUSPEND_NONE"); + } + + log2("......eventRequest1.setEnabled(true);"); + eventRequest1.setEnabled(true); + try { + log2(" checking up on eventRequest1; InvalidRequestStateException is expected"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_NONE); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2(" checking up on eventRequest1; InvalidRequestStateException is expected"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_NONE); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001/TestDescription.java new file mode 100644 index 00000000000..5bc44da0f0c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.setSuspendPolicy() + * complies with its spec: + * public void setSuspendPolicy(int policy) + * Determines the threads to suspend when the requested event occurs in + * the target VM. + * Use SUSPEND_ALL to suspend all threads in the target VM (the default). + * Use SUSPEND_EVENT_THREAD to suspend only the thread which generated the event. + * Use SUSPEND_NONE to suspend no threads. + * Thread suspensions through events have the same functionality as + * explicitly requested suspensions. + * See ThreadReference.suspend() and VirtualMachine.suspend() for details. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Suspend policy may only be set in disabled requests. + * The test checks up on following assertions: + * - a value of policy is equal to one assigned by last method setSuspendPolicy(int); + * - InvalidRequestStateException is thrown if this request is currently enabled; + * - InvalidRequestStateException is thrown if this request has been deleted. + * The cases to check include Requests of all sub-types. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.setSuspendPolicy.setsuspendpolicy001; + * the debuggee program - nsk.jdi.EventRequest.setSuspendPolicy.setsuspendpolicy001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.setSuspendPolicy.setsuspendpolicy001 + * nsk.jdi.EventRequest.setSuspendPolicy.setsuspendpolicy001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.setSuspendPolicy.setsuspendpolicy001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001a.java new file mode 100644 index 00000000000..56466e106c4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.setSuspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the setsuspendpolicy001 JDI test. + */ + +public class setsuspendpolicy001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1setsuspendpolicy001a thread1 = null; + + static TestClass11 obj = new TestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1setsuspendpolicy001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + setsuspendpolicy001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class TestClass11 extends TestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + setsuspendpolicy001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1setsuspendpolicy001a extends Thread { + + String tName = null; + + public Thread1setsuspendpolicy001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + setsuspendpolicy001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(setsuspendpolicy001a.waitnotifyObj) { + setsuspendpolicy001a.waitnotifyObj.notify(); + } + synchronized(setsuspendpolicy001a.lockObj) { + TestClass11.method11(); + } + setsuspendpolicy001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java new file mode 100644 index 00000000000..3a47f86d3e3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequest.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks up on following assertions:
    + * - Returns: the current suspend mode for this request
    + * The cases to check include Requests of all sub-types.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_ALL
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case (as if) and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class suspendpolicy001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequest.suspendPolicy.suspendpolicy001a"; + + private String testedClassName = + "nsk.jdi.EventRequest.suspendPolicy.TestClass11"; + + Location location = null; // !!!!!!!!!!!!! see settingBreakpoint + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + + EventRequest eventRequest1 = null; + + String fieldName1 = "var101"; + String fieldName2 = "excObj"; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ReferenceType testClassReference = null; + + String propertyName = "name"; + String propertyValue1 = "value1"; + String propertyValue2 = "value2"; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest"); + eventRequest1 = eventRManager.createStepRequest + (thread1, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + break; + + case 1: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); + + log2("......setting up AccessWatchpointRequest"); + eventRequest1 = eventRManager.createAccessWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 2: + log2(".....setting up ModificationWatchpointRequest"); + eventRequest1 = eventRManager.createModificationWatchpointRequest + (testClassReference.fieldByName(fieldName1)); + break; + + case 3: + log2(".....setting up ClassPrepareRequest"); + eventRequest1 = eventRManager.createClassPrepareRequest(); + break; + + case 4: + log2(".....setting up ClassUnloadRequest"); + eventRequest1 = eventRManager.createClassUnloadRequest(); + break; + + case 5: + log2(".....setting up MethodEntryRequest"); + eventRequest1 = eventRManager.createMethodEntryRequest(); + break; + + case 6: + log2(".....setting up MethodExitRequest"); + eventRequest1 = eventRManager.createMethodExitRequest(); + break; + + case 7: + log2(".....setting up ThreadDeathRequest"); + eventRequest1 = eventRManager.createThreadDeathRequest(); + break; + + case 8: + log2(".....setting up ThreadStartRequest"); + eventRequest1 = eventRManager.createThreadStartRequest(); + break; + + case 9: + log2(".....setting up VMDeathRequest"); + eventRequest1 = eventRManager.createVMDeathRequest(); + break; + + case 10: + log2(".....setting up ExceptionRequest"); + eventRequest1 = eventRManager.createExceptionRequest( + (ReferenceType) + (debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2))).type(), + true, true ); + break; + + case 11: + log2(".....setting up BreakpointRequest"); + eventRequest1 = eventRManager.createBreakpointRequest(location); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_ALL);"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_ALL); + + log2(" checking up on eventRequest1"); + if ( eventRequest1.suspendPolicy() != EventRequest.SUSPEND_ALL) { + testExitCode = FAILED; + log3("ERROR: suspendPolicy() != EventRequest.SUSPEND_ALL"); + } + + log2("......eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD );"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD ); + + log2(" checking up on eventRequest1"); + if ( eventRequest1.suspendPolicy() != EventRequest.SUSPEND_EVENT_THREAD ) { + testExitCode = FAILED; + log3("ERROR: suspendPolicy() != EventRequest.SUSPEND_EVENT_THREAD "); + } + + log2("......eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_NONE);"); + eventRequest1.setSuspendPolicy(EventRequest.SUSPEND_NONE); + + log2(" checking up on eventRequest1"); + if ( eventRequest1.suspendPolicy() != EventRequest.SUSPEND_NONE) { + testExitCode = FAILED; + log3("ERROR: suspendPolicy() != EventRequest.SUSPEND_NONE"); + } + + eventRManager.deleteEventRequest(eventRequest1); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + +// this is only for this test to get Location object +location = lineLocation; + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_ALL); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001/TestDescription.java new file mode 100644 index 00000000000..d3b189e744e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequest. + * The test checks up that a result of the method + * com.sun.jdi.EventRequest.suspendPolicy() + * complies with its spec: + * public void suspendPolicy() + * Returns a value which describes the threads to suspend when + * the requested event occurs in the target VM. + * The returned value is SUSPEND_ALL, SUSPEND_EVENT_THREAD, or SUSPEND_NONE. + * Returns: the current suspend mode for this request + * The test checks up on following assertions: + * - Returns: the current suspend mode for this request + * The cases to check include Requests of all sub-types. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequest.suspendPolicy.suspendpolicy001; + * the debuggee program - nsk.jdi.EventRequest.suspendPolicy.suspendpolicy001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Modified due to fix of the bug: + * 4915497 TEST_BUG: wrong synchronization in several JDI tests + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequest.suspendPolicy.suspendpolicy001 + * nsk.jdi.EventRequest.suspendPolicy.suspendpolicy001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequest.suspendPolicy.suspendpolicy001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001a.java new file mode 100644 index 00000000000..62735c77ef8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequest.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy001 JDI test. + */ + +public class suspendpolicy001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1suspendpolicy001a thread1 = null; + + static TestClass11 obj = new TestClass11(); + + static NullPointerException excObj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1suspendpolicy001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + i++; + + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method10 () { + suspendpolicy001a.log1("entered: method10"); + var101 = 1; + var103 = var101; + var102 = var103; + + } +} +class TestClass11 extends TestClass10{ + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method11 () { + suspendpolicy001a.log1("entered: method11"); + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1suspendpolicy001a extends Thread { + + String tName = null; + + public Thread1suspendpolicy001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + suspendpolicy001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(suspendpolicy001a.waitnotifyObj) { + suspendpolicy001a.waitnotifyObj.notify(); + } + synchronized(suspendpolicy001a.lockObj) { + TestClass11.method11(); + } + suspendpolicy001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001.java new file mode 100644 index 00000000000..355ab547747 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager._bounds_; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.*; + +/** + * The test checks up the
    + * a) createStepRequest(ThreadReference, int, int)
    + * this method is invoked 3 times with different arguments:
    + * 1. (null, StepRequest.STEP_LINE, StepRequest.STEP_OVER)
    + * in this case NullPointerException is expected
    + * 2. (thread, Integer.MAX_VALUE, StepRequest.STEP_OVER)
    + * 3. (null, StepRequest.STEP_LINE, Integer.MAX_VALUE)
    + * in 2, 3 cases no exceptions are expected
    + * b) createBreakpointRequest(Location)
    + * c) createAccessWatchpointRequest(Field)
    + * d) createModificationWatchpointRequest(Field)
    + * f) deleteEventRequest(EventRequest)
    + * g) deleteEventRequests(List)
    + * In b)-g) cases NullPointerException is expected. + */ +public class requests001 { + + final static String prefix = "nsk.jdi.EventRequestManager._bounds_."; + private final static String className = "requests001"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + requests001 thisTest = new requests001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + EventRequest request; + EventRequestManager evm = debugee.getEventRequestManager(); + ThreadReference thread = debugee.threadByName("main"); + + display(""); + display("...calling createStepRequest(null, StepRequest.STEP_LINE, " + + "StepRequest.STEP_OVER)"); + display(" ^^^^"); + try { + request = evm.createStepRequest(null, StepRequest.STEP_LINE, + StepRequest.STEP_OVER); + exitStatus = Consts.TEST_FAILED; + complain("NullPointerException is not throw"); + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } + + display(""); + display("...calling createStepRequest(thread, Integer.MAX_VALUE, " + + "StepRequest.STEP_OVER)"); + display(" ^^^^^^^^^^^^^^^^^"); + try { + request = evm.createStepRequest(thread, Integer.MAX_VALUE, + StepRequest.STEP_OVER); + exitStatus = Consts.TEST_FAILED; + complain("IllegalArgumentException is not throw"); + } catch(IllegalArgumentException e) { + display("!!!expected IllegalArgumentException"); + } catch(Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("***unexpected " + e); + } + + display(""); + display("...calling createStepRequest(null, StepRequest.STEP_LINE, " + + "Integer.MAX_VALUE)"); + display(" " + + "^^^^^^^^^^^^^^^^^"); + try { + request = evm.createStepRequest(thread, StepRequest.STEP_LINE, + Integer.MAX_VALUE); + exitStatus = Consts.TEST_FAILED; + complain("IllegalArgumentException is not throw"); + } catch(IllegalArgumentException e) { + display("!!!expected IllegalArgumentException"); + } catch(Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("***unexpected " + e); + } + + display(""); + display("...calling createBreakpointRequest(null)"); + try { + request = evm.createBreakpointRequest(null); + exitStatus = Consts.TEST_FAILED; + complain("NullPointerException is not throw"); + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } + + display(""); + display("...calling createAccessWatchpointRequest(null)"); + try { + request = evm.createAccessWatchpointRequest(null); + exitStatus = Consts.TEST_FAILED; + complain("NullPointerException is not throw"); + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } + + display(""); + display("...calling createModificationWatchpointRequest(null)"); + try { + request = evm.createModificationWatchpointRequest(null); + exitStatus = Consts.TEST_FAILED; + complain("NullPointerException is not throw"); + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } + + display(""); + display("...calling deleteEventRequest(null)"); + try { + evm.deleteEventRequest(null); + exitStatus = Consts.TEST_FAILED; + complain("NullPointerException is not throw"); + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } + + display(""); + display("...calling deleteEventRequests(null)"); + try { + evm.deleteEventRequests(null); + exitStatus = Consts.TEST_FAILED; + complain("NullPointerException is not throw"); + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } + + display(""); + display("...calling deleteEventRequests(list of values)"); + Vector list = new Vector(); + list.add(null); + list.add(null); + list.add(null); + list.add(null); + list.add(null); + list.add(null); + try { + evm.deleteEventRequests(list); + exitStatus = Consts.TEST_FAILED; + complain("NullPointerException is not throw"); + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } + + display(""); + debugee.quit(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001/TestDescription.java new file mode 100644 index 00000000000..0fd582a24e6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/_bounds_/requests001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up the methods + * a) createStepRequest(ThreadReference, int, int) + * this method is invoked 3 times with different arguments: + * 1. (null, StepRequest.STEP_LINE, StepRequest.STEP_OVER) + * in this case NullPointerException is expected + * 2. (thread, Integer.MAX_VALUE, StepRequest.STEP_OVER) + * 3. (null, StepRequest.STEP_LINE, Integer.MAX_VALUE) + * in 2, 3 cases no exceptions are expected + * b) createBreakpointRequest(Location) + * c) createAccessWatchpointRequest(Field) + * d) createModificationWatchpointRequest(Field) + * f) deleteEventRequest(EventRequest) + * g) deleteEventRequests(List) + * In b)-g) cases NullPointerException is expected. + * COMMENTS: + * 10.21.2002 fix for #4764615 + * When calling + * createStepRequest(thread, Integer.MAX_VALUE,StepRequest.STEP_OVER) or + * createStepRequest(null, StepRequest.STEP_LINE,Integer.MAX_VALUE), + * throwing of IllegalArgumentException is expected. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager._bounds_.requests001 + * nsk.jdi.EventRequestManager._bounds_.requests001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager._bounds_.requests001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001a.java new file mode 100644 index 00000000000..66ec7addfb1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/_bounds_/requests001a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * requests001a is deugee's part of the test. + */ +public class requests001a { + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq001.java new file mode 100644 index 00000000000..85d5762e750 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq001.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.accessWatchpointRequests; + +import com.sun.jdi.Field; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.request.AccessWatchpointRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.util.Iterator; +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.accessWatchpointRequests() + * properly returns all AccessWatchpointRequest objects when: + *

  • event requests are disabled + *
  • event requests are enabled
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the debugged VM from potential hangup. + */ +public class accwtchpreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.accessWatchpointRequests.accwtchpreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int FLDS_NUM = 16; + static final String DEBUGGEE_FLDS[][] = { + {"byte", "byteFld"}, + {"short", "shortFld"}, + {"int", "intFld"}, + {"long", "longFld"}, + {"float", "floatFld"}, + {"double", "doubleFld"}, + {"char", "charFld"}, + {"boolean", "booleanFld"}, + {"java.lang.String", "strFld"}, + {"short", "sFld"}, + {"byte", "prFld"}, + {"float", "pubFld"}, + {"double", "protFld"}, + {"int", "tFld"}, + {"long", "vFld"}, + {"char", "fFld"} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new accwtchpreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + List fields; + AccessWatchpointRequest awpRequest[] = + new AccessWatchpointRequest[FLDS_NUM]; + String cmd; + int i = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "accwtchpreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + if ( !vm.canWatchFieldAccess() ) { + log.display(" TEST CANCELLED due to: vm.canWatchFieldAccess() == false"); + return quitDebuggee(); + } + + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null"); + tot_res = FAILED; + return quitDebuggee(); + } + + try { + fields = rType.allFields(); + } catch (Exception e) { + log.complain("TEST FAILURE: allFields: " + e); + tot_res = FAILED; + return quitDebuggee(); + } + Iterator iter = fields.iterator(); + while (iter.hasNext()) { + Field fld = (Field) iter.next(); + log.display("Creating AccessWatchpointRequest for the field " + + fld.typeName() + " " + fld.name()); + try { + awpRequest[i++] = erManager.createAccessWatchpointRequest(fld); + } catch (Exception e) { + log.complain("TEST FAILURE: createAccessWatchpointRequest: " + e); + tot_res = FAILED; + return quitDebuggee(); + } + } + elThread = new EventListener(); + elThread.start(); + +// Check AccessWatchpoint requests when event requests are disabled + log.display("\n1) Getting AccessWatchpointRequest objects with disabled event requests..."); + checkRequests(erManager, 1); + +// Check AccessWatchpoint requests when event requests are enabled + for (i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.accessWatchpointRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled access watchpoint requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class accwtchpreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new accwtchpreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.accessWatchpointRequests.accwtchpreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldAccess() ) { + log2("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + String fieldName = "testField"; + + Field field = null; + + List requests = null; + ListIterator li = null; + + AccessWatchpointRequest request = null; + AccessWatchpointRequest awRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + field = debuggeeClass.fieldByName(fieldName); + + log2("......creating AccessWatchpointRequests"); + for (int i1 = 0; i1 < awRequests.length; i1++) { + awRequests[i1] = eventRManager.createAccessWatchpointRequest(field); + awRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new AccessWatchpointRequest"); + requests = eventRManager.accessWatchpointRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (AccessWatchpointRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created AccessWatchpointRequest"); + awRequests[i1].enable(); + requests = eventRManager.accessWatchpointRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (AccessWatchpointRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting AccessWatchpointRequests"); + for (int i2 = awRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(awRequests[i2]); + requests = eventRManager.accessWatchpointRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002/TestDescription.java new file mode 100644 index 00000000000..ac38ae5af07 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.accessWatchpointRequests() + * complies with its spec: + * public List accessWatchpointRequests() + * Return an unmodifiable list of the enabled and disabled access watchpoint + * requests. This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all AccessWatchpointRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled access watchpoint requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.accessWatchpointRequests.accwtchpreq002; + * the debuggee program - nsk.jdi.EventRequestManager.accessWatchpointRequests.accwtchpreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.accessWatchpointRequests.accwtchpreq002 + * nsk.jdi.EventRequestManager.accessWatchpointRequests.accwtchpreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.accessWatchpointRequests.accwtchpreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002a.java new file mode 100644 index 00000000000..a7c39fc63b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.accessWatchpointRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the accwtchpreq002 JDI test. + */ + +public class accwtchpreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq001.java new file mode 100644 index 00000000000..c22163dbf73 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq001.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.breakpointRequests; + +import com.sun.jdi.AbsentInformationException; +import com.sun.jdi.ClassNotPreparedException; +import com.sun.jdi.ObjectCollectedException; +//import com.sun.jdi.InvalidLineNumberException; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.Location; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.BreakpointRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.event.*; + +import java.util.Iterator; +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.breakpointRequests() + * properly returns all previously created BreakpointRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class breakpreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.breakpointRequests.breakpreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int BPS_NUM = 10; + static final String DEBUGGEE_BPS[][] = { + {"main", "void", "breakpreq001t.java"}, + {"byteMeth", "byte", "breakpreq001t.java"}, + {"shortMeth", "short", "breakpreq001t.java"}, + {"prMeth", "int", "breakpreq001t.java"}, + {"protMeth", "long", "breakpreq001t.java"}, + {"floatMeth", "float", "breakpreq001t.java"}, + {"doubleMeth", "double", "breakpreq001t.java"}, + {"charMeth", "char", "breakpreq001t.java"}, + {"boolMeth", "boolean", "breakpreq001t.java"}, + {"pubMeth", "java.lang.String", "breakpreq001t.java"} + }; + static final int DEBUGGEE_LNS[] = { + 37, 54, 57, 60, 63, 66, 69, 72, 75, 78 + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new breakpreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + List loctns; + BreakpointRequest bpRequest[] = new BreakpointRequest[BPS_NUM]; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "breakpreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null"); + tot_res = FAILED; + return quitDebuggee(); + } + + for (int i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.breakpointRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled breakpoint requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class breakpreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new breakpreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.breakpointRequests.breakpreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + Location breakpLocation = null; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + BreakpointRequest request = null; + BreakpointRequest bpRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating BreakpointRequests"); + for (int i1 = 0; i1 < bpRequests.length; i1++) { + bpRequests[i1] = eventRManager.createBreakpointRequest(breakpLocation); + bpRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new BreakpointRequest"); + requests = eventRManager.breakpointRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 2) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 2)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (BreakpointRequest) li.next(); + if ( request.getProperty("number").equals("zero") ) + continue; + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created BreakpointRequest"); + bpRequests[i1].enable(); + requests = eventRManager.breakpointRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 2) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 2)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (BreakpointRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting BreakpointRequests"); + for (int i2 = bpRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(bpRequests[i2]); + requests = eventRManager.breakpointRequests(); + listSize = requests.size(); + if ( listSize != (i2 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i2 + 1)); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); +breakpLocation = lineLocation; + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002/TestDescription.java new file mode 100644 index 00000000000..8c8b238219b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.breakpointRequests() + * complies with its spec: + * public List breakpointRequests() + * Return an unmodifiable list of the enabled and disabled breakpoint requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all BreakpointRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled breakpoint requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.breakpointRequests.breakpreq002; + * the debuggee program - nsk.jdi.EventRequestManager.breakpointRequests.breakpreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.breakpointRequests.breakpreq002 + * nsk.jdi.EventRequestManager.breakpointRequests.breakpreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.breakpointRequests.breakpreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002a.java new file mode 100644 index 00000000000..55295438568 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.breakpointRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the breakpreq002 JDI test. + */ + +public class breakpreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq001.java new file mode 100644 index 00000000000..888b2f5ee87 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq001.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.classPrepareRequests; + +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.ClassPrepareRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.event.*; + +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.classPrepareRequests() + * properly returns all previously created ClassPrepareRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled.
    + * ClassPrepareRequest objects are distinguished by the different + * EventRequest's properties.
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class clsprepreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.classPrepareRequests.clsprepreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int CLSP_NUM = 7; + static final String PROPS[][] = { + {"first", "a quick"}, + {"second", "brown"}, + {"third", "fox"}, + {"fourth", "jumps"}, + {"fifth", "over"}, + {"sixth", "the lazy"}, + {"seventh", "dog"} + }; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new clsprepreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ClassPrepareRequest clpRequest[] = new ClassPrepareRequest[CLSP_NUM]; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "clsprepreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + for (int i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.classPrepareRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled class prepare requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class clsprepreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new clsprepreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.classPrepareRequests.clsprepreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + ClassPrepareRequest request = null; + ClassPrepareRequest cpRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + cpRequest.putProperty("number", "zero"); + cpRequest.enable(); + + log2("......creating ClassPrepareRequests"); + for (int i1 = 0; i1 < cpRequests.length; i1++) { + cpRequests[i1] = eventRManager.createClassPrepareRequest(); + cpRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new ClassPrepareRequest"); + requests = eventRManager.classPrepareRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 2) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 2)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (ClassPrepareRequest) li.next(); + if ( request.getProperty("number").equals("zero") ) + continue; + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created ClassPrepareRequest"); + cpRequests[i1].enable(); + requests = eventRManager.classPrepareRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 2) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 2)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (ClassPrepareRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting ClassPrepareRequests"); + for (int i2 = cpRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(cpRequests[i2]); + requests = eventRManager.classPrepareRequests(); + listSize = requests.size(); + if ( listSize != (i2 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i2 + 1)); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + log2("breakpointForCommunication"); + + do { + getEventSet(); + + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) + return; + + log2(" received: " + event); + + if (EventFilters.filtered(event)) { + eventSet.resume(); + } + else { + break; + } + } while (true); + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002/TestDescription.java new file mode 100644 index 00000000000..ba92c849d4c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.classPrepareRequests() + * complies with its spec: + * public List classPrepareRequests() + * Return an unmodifiable list of the enabled and disabled class prepare requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all ClassPrepareRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled class prepare requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.classPrepareRequests.clsprepreq002; + * the debuggee program - nsk.jdi.EventRequestManager.classPrepareRequests.clsprepreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.classPrepareRequests.clsprepreq002 + * nsk.jdi.EventRequestManager.classPrepareRequests.clsprepreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.classPrepareRequests.clsprepreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002a.java new file mode 100644 index 00000000000..0496a644c5a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.classPrepareRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the clsprepreq002 JDI test. + */ + +public class clsprepreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq001.java new file mode 100644 index 00000000000..7b72ea4a74c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq001.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.classUnloadRequests; + +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.ClassUnloadRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.event.*; + +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.classUnloadRequests() + * properly returns all previously created ClassUnloadRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled.
    + * ClassUnloadRequest objects are distinguished by the different + * EventRequest's properties.
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class clsunlreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.classUnloadRequests.clsunlreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int CLSUNL_NUM = 7; + static final String PROPS[][] = { + {"first", "a quick"}, + {"second", "brown"}, + {"third", "fox"}, + {"fourth", "jumps"}, + {"fifth", "over"}, + {"sixth", "the lazy"}, + {"seventh", "dog"} + }; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new clsunlreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ClassUnloadRequest clunlRequest[] = new ClassUnloadRequest[CLSUNL_NUM]; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "clsunlreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + for (int i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.classUnloadRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled class unload requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class clsunlreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new clsunlreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.classUnloadRequests.clsunlreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + ClassUnloadRequest request = null; + ClassUnloadRequest cuRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating ClassUnloadRequests"); + for (int i1 = 0; i1 < cuRequests.length; i1++) { + cuRequests[i1] = eventRManager.createClassUnloadRequest(); + cuRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new ClassUnloadRequest"); + requests = eventRManager.classUnloadRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (ClassUnloadRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created ClassUnloadRequest"); + cuRequests[i1].enable(); + requests = eventRManager.classUnloadRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (ClassUnloadRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting ClassUnloadRequests"); + for (int i2 = cuRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(cuRequests[i2]); + requests = eventRManager.classUnloadRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002/TestDescription.java new file mode 100644 index 00000000000..678fd978c2d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.classUnloadRequests() + * complies with its spec: + * public List classUnloadRequests() + * Return an unmodifiable list of the enabled and disabled class unload requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all ClassUnloadRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled class unload requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.classUnloadRequests.clsunlreq002; + * the debuggee program - nsk.jdi.EventRequestManager.classUnloadRequests.clsunlreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.classUnloadRequests.clsunlreq002 + * nsk.jdi.EventRequestManager.classUnloadRequests.clsunlreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.classUnloadRequests.clsunlreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002a.java new file mode 100644 index 00000000000..f6e7aab65bf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.classUnloadRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the clsunlreq002 JDI test. + */ + +public class clsunlreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002.java new file mode 100644 index 00000000000..47df213bf33 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createAccessWatchpointRequest; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.Field; +import com.sun.jdi.request.AccessWatchpointRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VMMismatchException; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.createAccessWatchpointRequest() + * properly throws NullPointerException - if field is null. + */ +public class craccwtchpreq002 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq002t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new craccwtchpreq002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + AccessWatchpointRequest awpRequest; + String cmd; + Field fld = null; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "craccwtchpreq002t.err> "); + VirtualMachine vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + return quitDebuggee(FAILED); + } + + if ( !vm.canWatchFieldAccess() ) { + log.display(" TEST CANCELLED due to: vm.canWatchFieldAccess() == false"); + return quitDebuggee(PASSED); + } + +// Trying to create AccessWatchpointRequest for null Field parameter + try { + awpRequest = + erManager.createAccessWatchpointRequest(fld); + } catch (NullPointerException e) { + log.display("TEST PASSED: EventRequestManager.createAccessWatchpointRequest() throws expected " + + e); + return quitDebuggee(PASSED); + } catch(VMMismatchException e) { + log.complain("TEST FAILED: EventRequestManager.createAccessWatchpointRequest() throws unexpected " + + e + "\n\tbut it should throw NullPointerException for a null field"); + return quitDebuggee(FAILED); + } catch(UnsupportedOperationException e) { // specified only in jdk1.4 + log.complain("WARNING: test has no result. EventRequestManager.createAccessWatchpointRequest() throws " + + e); + return quitDebuggee(PASSED); + } + log.complain("TEST FAILED: EventRequestManager.createAccessWatchpointRequest successfully done,\n\t" + + "but it should throw NullPointerException for a null field"); + return quitDebuggee(FAILED); + } + + private int quitDebuggee(int stat) { + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return stat; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002/TestDescription.java new file mode 100644 index 00000000000..4f1c1f0917c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.createAccessWatchpointRequest() + * properly throws NullPointerException - if field is null. + * COMMENTS + * To fix the bug 4509034, + * the check if + * vm.canWatchFieldAccess() == true + * is added to the beginning of the test. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq002 + * nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002t.java new file mode 100644 index 00000000000..c9c84578ab8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq002t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createAccessWatchpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee class. + */ +public class craccwtchpreq002t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Log log = argHandler.createDebugeeLog(); + + log.display("Debuggee: sending the command: " + + craccwtchpreq002.COMMAND_READY); + pipe.println(craccwtchpreq002.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(craccwtchpreq002.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(craccwtchpreq002.JCK_STATUS_BASE + + craccwtchpreq002.FAILED); + } + System.exit(craccwtchpreq002.JCK_STATUS_BASE + + craccwtchpreq002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java new file mode 100644 index 00000000000..667958795e1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createAccessWatchpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createAccessWatchpointRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Multiple watchpoints on the same field are permitted.
    + * - Creates a new disabled watchpoint.
    + * - The watchpoint watches accesses to the specified field.
    + * - Throws: UnsupportedOperationException -
    + * if the target virtual machine does not support
    + * this operation.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares testcase and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class craccwtchpreq003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new craccwtchpreq003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq003a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + String fieldName = "testField"; + + Field field = null; + + List requests = null; + ListIterator li = null; + + AccessWatchpointRequest awRequest1 = null; + AccessWatchpointRequest awRequest2 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + field = debuggeeClass.fieldByName(fieldName); + + if ( vm.canWatchFieldAccess() ) { + log2("......vm.canWatchFieldAccess == true"); + log2(" creating two AccessWatchpointRequests for 'field': awRequest1 & awRequest2"); + + awRequest1 = eventRManager.createAccessWatchpointRequest(field); + awRequest2 = eventRManager.createAccessWatchpointRequest(field); + + log2(" checking up on: requests are disabled"); + if (awRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: awRequest1 is enabled"); + } + if (awRequest2.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: awRequest2 is enabled"); + } + log2(" compareing field equality"); + if ( !awRequest1.field().equals(field) ) { + testExitCode = FAILED; + log3("ERROR: !awRequest1.field().equals(field)"); + } + if ( !awRequest2.field().equals(field) ) { + testExitCode = FAILED; + log3("ERROR: !awRequest2.field().equals(field)"); + } + + } else { + log2("......vm.canWatchFieldAccess == false"); + log2(" UnsupportedOperationException is expected"); + try { + awRequest1 = eventRManager.createAccessWatchpointRequest(field); + testExitCode = FAILED; + log3("ERROR: NO UnsupportedOperationException"); + } catch ( UnsupportedOperationException e ) { + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003/TestDescription.java new file mode 100644 index 00000000000..b40fc8a8b3d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createAccessWatchpointRequest() + * complies with its spec: + * public AccessWatchpointRequest createAccessWatchpointRequest(Field field) + * Creates a new disabled watchpoint which watches accesses to the specified field. + * The new watchpoint is added to the list managed by this EventRequestManager. + * Multiple watchpoints on the same field are permitted. + * Use EventRequest.enable() to activate this event request. + * Not all target virtual machines support this operation. + * Use VirtualMachine.canWatchFieldAccess() to determine + * if the operation is supported. + * Parameters: field - the field to watch + * Returns: the created watchpoint + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test checks up on the following assertions: + * - Multiple watchpoints on the same field are permitted. + * - Creates a new disabled watchpoint. + * - The watchpoint watches accesses to the specified field. + * - Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq003; + * the debuggee program - nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq003 + * nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createAccessWatchpointRequest.craccwtchpreq003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003a.java new file mode 100644 index 00000000000..4648ccbcf3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createAccessWatchpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the craccwtchpreq003 JDI test. + */ + +public class craccwtchpreq003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002.java new file mode 100644 index 00000000000..98dacc92e17 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createBreakpointRequest; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.Location; +import com.sun.jdi.request.BreakpointRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VMMismatchException; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.createBreakpointRequest() + * properly throws NullPointerException - if location is null. + */ +public class crbreakpreq002 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq002t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new crbreakpreq002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + BreakpointRequest bpRequest; + String cmd; + Location loc = null; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "crbreakpreq002t.err> "); + VirtualMachine vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + return quitDebuggee(FAILED); + } + +// Trying to create BreakpointRequest for a null Location parameter + try { + bpRequest = + erManager.createBreakpointRequest(loc); + } catch (NullPointerException e) { + log.display("TEST PASSED: EventRequestManager.createBreakpointRequest() throws expected " + + e); + return quitDebuggee(PASSED); + } catch(VMMismatchException e) { + log.complain("TEST FAILED: EventRequestManager.createBreakpointRequest() throws unexpected " + + e + "\n\tbut it should throw NullPointerException for a null location"); + return quitDebuggee(FAILED); + } catch(UnsupportedOperationException e) { // specified only in jdk1.4 + log.complain("WARNING: test has no result. EventRequestManager.createBreakpointRequest() throws " + + e); + return quitDebuggee(PASSED); + } + log.complain("TEST FAILED: EventRequestManager.createBreakpointRequest() successfully done,\n\t" + + "but it should throw NullPointerException for a null location"); + return quitDebuggee(FAILED); + } + + private int quitDebuggee(int stat) { + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return stat; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002/TestDescription.java new file mode 100644 index 00000000000..47e6cc2f696 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002/TestDescription.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.createBreakpointRequest() + * properly throws NullPointerException - if location is null. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq002 + * nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002t.java new file mode 100644 index 00000000000..07a98ae25e3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq002t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createBreakpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee class. + */ +public class crbreakpreq002t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Log log = argHandler.createDebugeeLog(); + + log.display("Debuggee: sending the command: " + + crbreakpreq002.COMMAND_READY); + pipe.println(crbreakpreq002.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(crbreakpreq002.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(crbreakpreq002.JCK_STATUS_BASE + + crbreakpreq002.FAILED); + } + System.exit(crbreakpreq002.JCK_STATUS_BASE + + crbreakpreq002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java new file mode 100644 index 00000000000..421eb141e56 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createBreakpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createBreakpointRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Multiple breakpoints at the same location are permitted.
    + * - Creates a new disabled BreakpointRequest.
    + * - The BreakpointRequest is at the specified location.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares testcase and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class crbreakpreq003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new crbreakpreq003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq003a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + Location breakpLocation = null; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + BreakpointRequest bpRequest1 = null; + BreakpointRequest bpRequest2 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" creating two BreakpointRequests for 'breakpLocation': bpRequest1 & bpRequest2"); + + bpRequest1 = eventRManager.createBreakpointRequest(breakpLocation); + bpRequest2 = eventRManager.createBreakpointRequest(breakpLocation); + + log2(" checking up on: requests are disabled"); + if (bpRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: bpRequest1 is enabled"); + } + if (bpRequest2.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: bpRequest2 is enabled"); + } + log2(" compareing locations equality"); + if ( !bpRequest1.location().equals(breakpLocation) ) { + testExitCode = FAILED; + log3("ERROR: !bpRequest1.location().equals(breakpLocation)"); + } + if ( !bpRequest2.location().equals(breakpLocation) ) { + testExitCode = FAILED; + log3("ERROR: !bpRequest2.location().equals(breakpLocation)"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); +breakpLocation = lineLocation; + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003/TestDescription.java new file mode 100644 index 00000000000..c5f1db123f0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createBreakpointRequest() + * complies with its spec: + * public BreakpointRequest createBreakpointRequest(Location location) + * Creates a new disabled BreakpointRequest. + * The given Location must have a valid (that is, non-negative) code index. + * The new breakpoint is added to the list managed by this EventRequestManager. + * Multiple breakpoints at the same location are permitted. + * Use EventRequest.enable() to activate this event request. + * Parameters: location - the location of the new breakpoint. + * Returns: the created BreakpointRequest + * Throws: NativeMethodException - if location is within a native method. + * The test checks up on the following assertions: + * - Multiple breakpoints at the same location are permitted. + * - Creates a new disabled BreakpointRequest. + * - The BreakpointRequest is at the specified location. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq003; + * the debuggee program - nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq003 + * nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createBreakpointRequest.crbreakpreq003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003a.java new file mode 100644 index 00000000000..841eafc3f7b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createBreakpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the crbreakpreq003 JDI test. + */ + +public class crbreakpreq003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java new file mode 100644 index 00000000000..6293bd2d897 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createClassPrepareRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createClassPrepareRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Creates a new disabled ClassPrepareRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class cpreg001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new cpreg001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createClassPrepareRequest.cpreg001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + ClassPrepareRequest cpRequest1 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating: cpRequest1 = eventRManager.createClassPrepareRequest();"); + cpRequest1 = eventRManager.createClassPrepareRequest(); + log2(" checking up on if request is disabled"); + if (cpRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is not disabled"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001/TestDescription.java new file mode 100644 index 00000000000..64e78f14f69 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createClassPrepareRequest() + * complies with its spec: + * public ClassPrepareRequest createClassPrepareRequest() + * Creates a new disabled ClassPrepareRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * Returns: the created ClassPrepareRequest + * The test checks up on the following assertions: + * - Creates a new disabled ClassPrepareRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createClassPrepareRequest.cpreg001; + * the debuggee program - nsk.jdi.EventRequestManager.createClassPrepareRequest.cpreg001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createClassPrepareRequest.cpreg001 + * nsk.jdi.EventRequestManager.createClassPrepareRequest.cpreg001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createClassPrepareRequest.cpreg001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001a.java new file mode 100644 index 00000000000..4263edf664a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createClassPrepareRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the cpreg001 JDI test. + */ + +public class cpreg001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java new file mode 100644 index 00000000000..a8a8d3eb9f9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createClassUnloadRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createClassUnloadRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Creates a new disabled ClassUnloadRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class cureg001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new cureg001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createClassUnloadRequest.cureg001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + ClassUnloadRequest cuRequest1 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating: cuRequest1 = eventRManager.createClassUnloadRequest();"); + cuRequest1 = eventRManager.createClassUnloadRequest(); + log2(" checking up on if request is disabled"); + if (cuRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is not disabled"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001/TestDescription.java new file mode 100644 index 00000000000..7f191547278 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createClassUnloadRequest() + * complies with its spec: + * public ClassUnloadRequest createClassUnloadRequest() + * Creates a new disabled ClassUnloadRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * Returns: the created ClassUnloadRequest + * The test checks up on the following assertions: + * - Creates a new disabled ClassUnloadRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createClassUnloadRequest.cureg001; + * the debuggee program - nsk.jdi.EventRequestManager.createClassUnloadRequest.cureg001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createClassUnloadRequest.cureg001 + * nsk.jdi.EventRequestManager.createClassUnloadRequest.cureg001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createClassUnloadRequest.cureg001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001a.java new file mode 100644 index 00000000000..368daa92a93 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createClassUnloadRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the cureg001 JDI test. + */ + +public class cureg001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java new file mode 100644 index 00000000000..b3a61e6a92e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createExceptionRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createExceptionRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Creates a new disabled ExceptionRequest.
    + * - A specific exception type and its subclasses
    + * can be selected for exception events.
    + * - Caught exceptions, uncaught exceptions, or both can be selected.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new testcase and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class crexreq009 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new crexreq009().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createExceptionRequest.crexreq009a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + String fieldName = "testField"; + + ExceptionRequest exRequest = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType refType = (ReferenceType) + debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)).type(); + + log2("......creating: exRequest = eventRManager.createExceptionRequest(refType, false, true);"); + exRequest = eventRManager.createExceptionRequest(refType, false, true); + log2(" check on if request is disabled"); + if (exRequest.isEnabled()) { + log3("ERROR: request is enabled"); + testExitCode = FAILED; + } + + log2("......creating: exRequest = eventRManager.createExceptionRequest(null, true, false);"); + exRequest = eventRManager.createExceptionRequest(null, true, false); + log2(" check on if request is disabled"); + if (exRequest.isEnabled()) { + log3("ERROR: request is enabled"); + testExitCode = FAILED; + } + + log2("......creating: exRequest = eventRManager.createExceptionRequest(null, true, true);"); + exRequest = eventRManager.createExceptionRequest(null, true, true); + log2(" check on if request is disabled"); + if (exRequest.isEnabled()) { + log3("ERROR: request is enabled"); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009/TestDescription.java new file mode 100644 index 00000000000..1cab2ba5bac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createExceptionRequest() + * complies with its spec: + * public ExceptionRequest createExceptionRequest(ReferenceType refType, + * boolean notifyCaught, + * boolean notifyUncaught) + * Creates a new disabled ExceptionRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * A specific exception type and its subclasses can be selected for exception events. + * Caught exceptions, uncaught exceptions, or both can be selected. + * Note, however, that at the time an exception is thrown, + * it is not always possible to determine whether it is truly caught. + * See ExceptionEvent.catchLocation() for details. + * Parameters: refType - If non-null, specifies that exceptions + * which are instances of refType will be reported. + * Note: this will include instances of sub-types. + * If null, all instances will be reported + * notifyCaught - If true, caught exceptions will be reported. + * notifyUncaught - If true, uncaught exceptions will be reported. + * Returns: the created ExceptionRequest + * The test checks up on the following assertions: + * - Creates a new disabled ExceptionRequest. + * - A specific exception type and its subclasses can be selected for exception events. + * - Caught exceptions, uncaught exceptions, or both can be selected. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createExceptionRequest.crexreq009; + * the debuggee program - nsk.jdi.EventRequestManager.createExceptionRequest.crexreq009a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createExceptionRequest.crexreq009 + * nsk.jdi.EventRequestManager.createExceptionRequest.crexreq009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createExceptionRequest.crexreq009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009a.java new file mode 100644 index 00000000000..78d9fe5cc49 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createExceptionRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the crexreq009 JDI test. + */ + +public class crexreq009a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static NullPointerException testField = new NullPointerException("test"); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java new file mode 100644 index 00000000000..baab21ecd73 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createExceptionRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createExceptionRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - If neither caught exception nor uncaught exception is selected,
    + * that is, both notifyCaught and notifyUncaught arguments are false,
    + * returned value is null.
    + * Note. In condition of no Exception for such testcase is defined in
    + * the spec, null is the only reasonable returned value.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a testcase and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class crexreq010 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new crexreq010().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createExceptionRequest.crexreq010a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + String fieldName = "testField"; + + ExceptionRequest exRequest = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType refType = (ReferenceType) + debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)).type(); + + + try { + log2("......creating: exRequest = eventRManager.createExceptionRequest(refType, false, false);"); + exRequest = eventRManager.createExceptionRequest(refType, false, false); + log2(" check on if returned value is null"); + if (exRequest == null) { + log3("ERROR: returned value is null!"); + testExitCode = FAILED; + } + } catch (Exception e) { + log3("ERROR: exception caught: " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010/TestDescription.java new file mode 100644 index 00000000000..f3db992045a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010/TestDescription.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createExceptionRequest() + * complies with its spec: + * public ExceptionRequest createExceptionRequest(ReferenceType refType, + * boolean notifyCaught, + * boolean notifyUncaught) + * Creates a new disabled ExceptionRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * A specific exception type and its subclasses can be selected for exception events. + * Caught exceptions, uncaught exceptions, or both can be selected. + * Note, however, that at the time an exception is thrown, + * it is not always possible to determine whether it is truly caught. + * See ExceptionEvent.catchLocation() for details. + * Parameters: refType - If non-null, specifies that exceptions + * which are instances of refType will be reported. + * Note: this will include instances of sub-types. + * If null, all instances will be reported + * notifyCaught - If true, caught exceptions will be reported. + * notifyUncaught - If true, uncaught exceptions will be reported. + * Returns: the created ExceptionRequest + * The test checks up on the following assertion: + * - If neither caught exception nor uncaught exception is selected, + * that is, both notifyCaught and notifyUncaught arguments are false, + * returned value is null. + * Note. In condition of no Exception for such testcase is defined in the spec, + * null is the only reasonable returned value. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createExceptionRequest.crexreq010; + * the debuggee program - nsk.jdi.EventRequestManager.createExceptionRequest.crexreq010a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test fixed according to test bug: + * 4615030 crexreq010: method createExceptionRequest() doesn't return expected + * - test now checks that createExceptionRequest() returns non-null object + * and no unspecified exception is thrown + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createExceptionRequest.crexreq010 + * nsk.jdi.EventRequestManager.createExceptionRequest.crexreq010a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createExceptionRequest.crexreq010 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010a.java new file mode 100644 index 00000000000..40db2c30b7e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createExceptionRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the crexreq010 JDI test. + */ + +public class crexreq010a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static NullPointerException testField = new NullPointerException("test"); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java new file mode 100644 index 00000000000..ea0e995c3f9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createMethodEntryRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createMethodEntryRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Creates a new disabled MethodEntryRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class menreg001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new menreg001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createMethodEntryRequest.menreg001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + MethodEntryRequest menRequest1 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating: menRequest1 = eventRManager.createMethodEntryRequest();"); + menRequest1 = eventRManager.createMethodEntryRequest(); + log2(" checking up on if request is disabled"); + if (menRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is not disabled"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001/TestDescription.java new file mode 100644 index 00000000000..904b229cb94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createMethodEntryRequest() + * complies with its spec: + * public MethodEntryRequest createMethodEntryRequest() + * Creates a new disabled MethodEntryRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * Returns: the created MethodEntryRequest + * The test checks up on the following assertions: + * - Creates a new disabled MethodEntryRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createMethodEntryRequest.menreg001; + * the debuggee program - nsk.jdi.EventRequestManager.createMethodEntryRequest.menreg001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createMethodEntryRequest.menreg001 + * nsk.jdi.EventRequestManager.createMethodEntryRequest.menreg001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createMethodEntryRequest.menreg001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001a.java new file mode 100644 index 00000000000..3e45e493dc0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createMethodEntryRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the menreg001 JDI test. + */ + +public class menreg001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java new file mode 100644 index 00000000000..1745d3c968f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createMethodExitRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createMethodExitRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Creates a new disabled MethodExitRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class mexreg001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new mexreg001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createMethodExitRequest.mexreg001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + MethodExitRequest mexRequest1 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating: mexRequest1 = eventRManager.createMethodExitRequest();"); + mexRequest1 = eventRManager.createMethodExitRequest(); + log2(" checking up on if request is disabled"); + if (mexRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is not disabled"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001/TestDescription.java new file mode 100644 index 00000000000..593628da2ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createMethodExitRequest() + * complies with its spec: + * public MethodExitRequest createMethodExitRequest() + * Creates a new disabled MethodExitRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * Returns: the created MethodExitRequest + * The test checks up on the following assertions: + * - Creates a new disabled MethodExitRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createMethodExitRequest.mexreg001; + * the debuggee program - nsk.jdi.EventRequestManager.createMethodExitRequest.mexreg001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createMethodExitRequest.mexreg001 + * nsk.jdi.EventRequestManager.createMethodExitRequest.mexreg001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createMethodExitRequest.mexreg001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001a.java new file mode 100644 index 00000000000..19a781f61a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createMethodExitRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the mexreg001 JDI test. + */ + +public class mexreg001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002.java new file mode 100644 index 00000000000..2a0c4899701 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createModificationWatchpointRequest; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.Field; +import com.sun.jdi.request.ModificationWatchpointRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VMMismatchException; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.createModificationWatchpointRequest() + * properly throws NullPointerException - if field is null. + */ +public class crmodwtchpreq002 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq002t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new crmodwtchpreq002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ModificationWatchpointRequest awpRequest; + String cmd; + Field fld = null; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "crmodwtchpreq002t.err> "); + VirtualMachine vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + return quitDebuggee(FAILED); + } + + if ( !vm.canWatchFieldModification() ) { + log.display(" TEST CANCELLED due to: vm.canWatchFieldModification() == false"); + return quitDebuggee(PASSED); + } + +// Trying to create ModificationWatchpointRequest for a null Field parameter + try { + awpRequest = + erManager.createModificationWatchpointRequest(fld); + } catch (NullPointerException e) { + log.display("TEST PASSED: EventRequestManager.createModificationWatchpointRequest() throws expected " + + e); + return quitDebuggee(PASSED); + } catch(VMMismatchException e) { + log.complain("TEST FAILED: EventRequestManager.createModificationWatchpointRequest() throws unexpected " + + e + "\n\tbut it should throw NullPointerException for a null field"); + return quitDebuggee(FAILED); + } catch(UnsupportedOperationException e) { // specified only in jdk1.4 + log.complain("WARNING: test has no result. EventRequestManager.createModificationWatchpointRequest() throws " + + e); + return quitDebuggee(PASSED); + } + log.complain("TEST FAILED: EventRequestManager.createModificationWatchpointRequest() successfully done,\n\t" + + "but it should throw NullPointerException for a null field"); + return quitDebuggee(FAILED); + } + + private int quitDebuggee(int stat) { + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return stat; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002/TestDescription.java new file mode 100644 index 00000000000..23c91c41492 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.createModificationWatchpointRequest() + * properly throws NullPointerException - if field is null. + * COMMENTS + * To fix the bug 4509034, + * the check if + * vm.canWatchFieldModification() == true + * is added to the beginning of the test. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq002 + * nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002t.java new file mode 100644 index 00000000000..795db253ad1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq002t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createModificationWatchpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee class. + */ +public class crmodwtchpreq002t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Log log = argHandler.createDebugeeLog(); + + log.display("Debuggee: sending the command: " + + crmodwtchpreq002.COMMAND_READY); + pipe.println(crmodwtchpreq002.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(crmodwtchpreq002.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(crmodwtchpreq002.JCK_STATUS_BASE + + crmodwtchpreq002.FAILED); + } + System.exit(crmodwtchpreq002.JCK_STATUS_BASE + + crmodwtchpreq002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java new file mode 100644 index 00000000000..3a074620e87 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createModificationWatchpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createModificationWatchpointRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Multiple watchpoints on the same field are permitted.
    + * - Creates a new disabled watchpoint.
    + * - The watchpoint watches modification of the specified field.
    + * - Throws: UnsupportedOperationException -
    + * if the target virtual machine does not support this operation.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares testcase and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class crmodwtchpreq003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new crmodwtchpreq003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq003a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + String fieldName = "testField"; + + Field field = null; + + List requests = null; + ListIterator li = null; + + ModificationWatchpointRequest mwRequest1 = null; + ModificationWatchpointRequest mwRequest2 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + field = debuggeeClass.fieldByName(fieldName); + + if ( vm.canWatchFieldModification() ) { + log2("......vm.canWatchFieldModification == true"); + log2(" creating two ModificationWatchpointRequests for 'field': mwRequest1 & mwRequest2"); + + mwRequest1 = eventRManager.createModificationWatchpointRequest(field); + mwRequest2 = eventRManager.createModificationWatchpointRequest(field); + + log2(" checking up on: requests are disabled"); + if (mwRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: mwRequest1 is enabled"); + } + if (mwRequest2.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: mwRequest2 is enabled"); + } + log2(" compareing field equality"); + if ( !mwRequest1.field().equals(field) ) { + testExitCode = FAILED; + log3("ERROR: !mwRequest1.field().equals(field)"); + } + if ( !mwRequest2.field().equals(field) ) { + testExitCode = FAILED; + log3("ERROR: !mwRequest2.field().equals(field)"); + } + + } else { + log2("......vm.canWatchFieldModification == false"); + log2(" UnsupportedOperationException is expected"); + try { + mwRequest1 = eventRManager.createModificationWatchpointRequest(field); + testExitCode = FAILED; + log3("ERROR: NO UnsupportedOperationException"); + } catch ( UnsupportedOperationException e ) { + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003/TestDescription.java new file mode 100644 index 00000000000..36377d73a12 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createModificationWatchpointRequest() + * complies with its spec: + * public ModificationWatchpointRequest createModificationWatchpointRequest(Field field) + * Creates a new disabled watchpoint which watches accesses to the specified field. + * The new watchpoint is added to the list managed by this EventRequestManager. + * Multiple watchpoints on the same field are permitted. + * Use EventRequest.enable() to activate this event request. + * Not all target virtual machines support this operation. + * Use VirtualMachine.canWatchFieldModification() to determine + * if the operation is supported. + * Parameters: field - the field to watch + * Returns: the created watchpoint + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test checks up on the following assertions: + * - Multiple watchpoints on the same field are permitted. + * - Creates a new disabled watchpoint. + * - The watchpoint watches accesses to the specified field. + * - Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq003; + * the debuggee program - nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq003 + * nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createModificationWatchpointRequest.crmodwtchpreq003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003a.java new file mode 100644 index 00000000000..1771ab415c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createModificationWatchpointRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the crmodwtchpreq003 JDI test. + */ + +public class crmodwtchpreq003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001.java new file mode 100644 index 00000000000..0e0e1b64ebf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import com.sun.jdi.ThreadReference; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.StepRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.DuplicateRequestException; +import com.sun.jdi.ObjectCollectedException; +import com.sun.jdi.VMMismatchException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that only one pending JDI step request is + * allowed per thread, i.e. the JDI method + * com.sun.jdi.request.EventRequestManager.createStepRequest() + * properly throws a DuplicateRequestException if there + * is already a pending step request for the specified thread. + */ +public class crstepreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.createStepRequest.crstepreq001t"; + static final String DEBUGGEE_THRD = "debuggee_thr"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int RSTS_NUM = 6; + static final int RESTRICTIONS[][] = { + {StepRequest.STEP_MIN, StepRequest.STEP_INTO}, + {StepRequest.STEP_MIN, StepRequest.STEP_OVER}, + {StepRequest.STEP_MIN, StepRequest.STEP_OUT}, + {StepRequest.STEP_LINE, StepRequest.STEP_INTO}, + {StepRequest.STEP_LINE, StepRequest.STEP_OVER}, + {StepRequest.STEP_LINE, StepRequest.STEP_OUT} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new crstepreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ThreadReference thR = null; + List threads; + List enabledStepRequests = new LinkedList<>(); + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "crstepreq001t.err> "); + VirtualMachine vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + return quitDebuggee(FAILED); + } + + try { + threads = vm.allThreads(); + } catch (Exception e) { + log.complain("TEST FAILURE: allThreads: " + e); + return quitDebuggee(FAILED); + } + Iterator iter = threads.iterator(); + while (iter.hasNext()) { + thR = (ThreadReference) iter.next(); + if (thR.name().equals(DEBUGGEE_THRD)) { + log.display("\nCreating StepRequest for the debuggee's thread \"" + + thR.name() + "\""); + try { + StepRequest sReq = erManager.createStepRequest(thR, + RESTRICTIONS[0][0],RESTRICTIONS[0][1]); + sReq.enable(); + enabledStepRequests.add(sReq); + } catch (DuplicateRequestException e) { + log.complain("TEST FAILURE: createStepRequest: caught " + e); + return quitDebuggee(FAILED); + } catch (ObjectCollectedException e) { + log.complain("TEST FAILURE: createStepRequest: caught " + e); + return quitDebuggee(FAILED); + } catch (VMMismatchException e) { + log.complain("TEST FAILURE: createStepRequest: caught " + e); + return quitDebuggee(FAILED); + } + break; + } + } + +// Check that createStepRequest() throws DuplicateRequestException +// to indicate a duplicate event request per thread + for(int i=0; i erManager.deleteEventRequest(s)); + + return quitDebuggee(tot_res); + } + + private int quitDebuggee(int stat) { + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return stat; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001/TestDescription.java new file mode 100644 index 00000000000..7d48ae61e15 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001/TestDescription.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq001. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-4447344 + * VM Testbase readme: + * DESCRIPTION + * This test checks that only one pending JDI step request is + * allowed per thread, i.e. the JDI method + * com.sun.jdi.request.EventRequestManager.createStepRequest() + * properly throws a DuplicateRequestException if there + * is already a pending step request for the specified thread. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq001 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001t.java new file mode 100644 index 00000000000..ec910b298a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq001t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This is a debuggee class. + */ +public class crstepreq001t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Thread thr = Thread.currentThread(); + + thr.setName(crstepreq001.DEBUGGEE_THRD); + pipe.println(crstepreq001.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(crstepreq001.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(crstepreq001.JCK_STATUS_BASE + + crstepreq001.FAILED); + } + System.exit(crstepreq001.JCK_STATUS_BASE + + crstepreq001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java new file mode 100644 index 00000000000..2571289065d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createStepRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Creates a new disabled StepRequest.
    + * - STEP_MIN, STEP_LINE, STEP_INTO, STEP_OVER, STEP_OUT are valid
    + * arguments, that is, they don't throw IllegalArgumentException.
    + * - Values larger and lesser corresponding above are invalid arguments,
    + * that is, they do throw IllegalArgumentException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertions,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new testcase and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class crstepreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createStepRequest/crstepreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new crstepreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createStepRequest.crstepreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + ThreadReference thread = null; + String threadName = "thread1"; + + StepRequest stRequest = null; + + int minDepth, maxDepth; + int minSize, maxSize; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + thread = threadByName(threadName); + + if (StepRequest.STEP_MIN > StepRequest.STEP_LINE) { + maxSize = StepRequest.STEP_MIN; + minSize = StepRequest.STEP_LINE; + } else { + minSize = StepRequest.STEP_MIN; + maxSize = StepRequest.STEP_LINE; + } + + if ( (StepRequest.STEP_INTO > StepRequest.STEP_OVER) && + (StepRequest.STEP_INTO > StepRequest.STEP_OUT) ) + maxDepth = StepRequest.STEP_INTO; + + if ( (StepRequest.STEP_OVER > StepRequest.STEP_INTO) && + (StepRequest.STEP_OVER > StepRequest.STEP_OUT) ) + maxDepth = StepRequest.STEP_OVER; + + if ( (StepRequest.STEP_OUT > StepRequest.STEP_OVER) && + (StepRequest.STEP_OUT > StepRequest.STEP_INTO) ) + maxDepth = StepRequest.STEP_OUT; + + if ( (StepRequest.STEP_INTO < StepRequest.STEP_OVER) && + (StepRequest.STEP_INTO < StepRequest.STEP_OUT) ) + minDepth = StepRequest.STEP_INTO; + + if ( (StepRequest.STEP_OVER < StepRequest.STEP_INTO) && + (StepRequest.STEP_OVER < StepRequest.STEP_OUT) ) + minDepth = StepRequest.STEP_OVER; + + if ( (StepRequest.STEP_OUT < StepRequest.STEP_OVER) && + (StepRequest.STEP_OUT < StepRequest.STEP_INTO) ) + minDepth = StepRequest.STEP_OUT; + + try { + log2("......creating: eventRManager.createStepRequest(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO);"); + stRequest = eventRManager.createStepRequest(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO); + log2(" checking up on if request is disabled"); + if (stRequest.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is enabled"); + } + } catch ( IllegalArgumentException e ) { + testExitCode = FAILED; + log3("ERROR: IllegalArgumentException for STEP_MIN - STEP_INTO"); + } + eventRManager.deleteEventRequest(stRequest); + try { + log2("......creating: eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER);"); + stRequest = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); + log2(" checking up on if request is disabled"); + if (stRequest.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is enabled"); + } + } catch ( IllegalArgumentException e ) { + testExitCode = FAILED; + log3("ERROR: IllegalArgumentException for STEP_LINE - STEP_OVER"); + } + eventRManager.deleteEventRequest(stRequest); + try { + log2("......creating: eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OUT);"); + stRequest = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OUT); + log2(" checking up on if request is disabled"); + if (stRequest.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is enabled"); + } + } catch ( IllegalArgumentException e ) { + testExitCode = FAILED; + log3("ERROR: IllegalArgumentException for STEP_LINE - STEP_OUT"); + } + eventRManager.deleteEventRequest(stRequest); + log2("......creating: eventRManager.createStepRequest(thread, minSize -1, StepRequest.STEP_OUT);"); + log2(" IllegalArgumentException is expected"); + try { + stRequest = eventRManager.createStepRequest(thread, minSize -1, StepRequest.STEP_OUT); + testExitCode = FAILED; + log3("ERROR: no IllegalArgumentException thrown"); + } catch ( IllegalArgumentException e ) { + } + eventRManager.deleteEventRequest(stRequest); + log2("......creating: eventRManager.createStepRequest(thread, maxSize +1, StepRequest.STEP_OUT);"); + log2(" IllegalArgumentException is expected"); + try { + stRequest = eventRManager.createStepRequest(thread, maxSize +1, StepRequest.STEP_OUT); + testExitCode = FAILED; + log3("ERROR: no IllegalArgumentException thrown"); + } catch ( IllegalArgumentException e ) { + } + eventRManager.deleteEventRequest(stRequest); + log2("......creating: eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, minDepth -1);"); + log2(" IllegalArgumentException is expected"); + try { + stRequest = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, minDepth -1); + testExitCode = FAILED; + log3("ERROR: no IllegalArgumentException thrown"); + } catch ( IllegalArgumentException e ) { + } + eventRManager.deleteEventRequest(stRequest); + log2("......creating: eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, maxDepth +1);"); + log2(" IllegalArgumentException is expected"); + try { + stRequest = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, maxDepth +1); + testExitCode = FAILED; + log3("ERROR: no IllegalArgumentException thrown"); + } catch ( IllegalArgumentException e ) { + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002/TestDescription.java new file mode 100644 index 00000000000..3b52b200119 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createStepRequest() + * complies with its spec: + * public StepRequest createStepRequest(ThreadReference thread, int size, int depth) + * Creates a new disabled StepRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * The returned request will control stepping only in the specified thread; + * all other threads will be unaffected. + * A sizevalue of StepRequest.STEP_MIN will generate a step event each time the code index changes. + * It represents the smallest step size available and often maps to the instruction level. + * A size value of StepRequest.STEP_LINE will generate a step event each time the source line changes. + * A depth value of StepRequest.STEP_INTO will generate step events in any called methods. + * A depth value of StepRequest.STEP_OVER restricts step events to the current frame or caller frames. + * A depth value of StepRequest.STEP_OUT restricts step events to caller frames only. + * All depth restrictions are relative to the call stack immediately before the step takes place. + * Only one pending step request is allowed per thread. + * Parameters: thread - the thread in which to step + * depth - the step depth + * size - the step size + * Returns: the created StepRequest + * Throws: DuplicateRequestException - + * if there is already a pending step request for the specified thread. + * The test checks up on the following assertions: + * - Creates a new disabled StepRequest. + * - STEP_MIN, STEP_LINE, STEP_INTO, STEP_OVER, STEP_OUT are valid arguments, + * that is, they don't throw IllegalArgumentException. + * - Values larger and lesser corresponding above are invalid arguments, that is, + * they do throw IllegalArgumentException. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createStepRequest.crstepreq002; + * the debuggee program - nsk.jdi.EventRequestManager.createStepRequest.crstepreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq002 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002a.java new file mode 100644 index 00000000000..150e41fbd36 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002a.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the crstepreq002 JDI test. + */ + +public class crstepreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1crstepreq002a thread1 = null; + + static TestClass10 obj = new TestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1crstepreq002a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + static void m10() { + crstepreq002a.log1("entered: m10"); + } +} +class TestClass11 extends TestClass10{ + static void m11() { + crstepreq002a.log1("entered: m11"); + TestClass10.m10(); + } +} + +class Thread1crstepreq002a extends Thread { + + String tName = null; + + public Thread1crstepreq002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + crstepreq002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(crstepreq002a.waitnotifyObj) { + crstepreq002a.waitnotifyObj.notify(); + } + synchronized(crstepreq002a.lockObj) { + TestClass11.m11(); + } + crstepreq002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java new file mode 100644 index 00000000000..72ad344cad6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class crstepreq003 { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + private int instruction = 1; + private int waitTime; + private static int exitCode = PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.createStepRequest"; + private final static String className = ".crstepreq003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + PASS_BASE); + } + + //------------------------------------------------------ test specific fields + + static final int lineForBreakInThread = 137; + static final int[] checkedLines = { 138, 138, 178 }; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new crstepreq003().runThis(argv, out); + System.out.println (exitStatus == PASSED ? "TEST PASSED" : "TEST FAILED"); + return exitCode; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStdout(log, "debuggee stdout> "); + debuggee.redirectStderr(log, "debuggee stderr> "); + debuggee.createIOPipe(); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (PASSED + PASS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitCode = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitCode = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitCode = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(PASSED + PASS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitCode; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + ThreadReference mainThread = threadByName("main"); +/* + BreakpointRequest bpRequest = setBreakpoint( mainThread, + debuggeeClass, + "methodForCommunication", + 2, + "breakpointForCommunication"); +*/ + BreakpointRequest bpRequest = setBreakpoint( null, + debuggeeClass, + "breakInThread", + lineForBreakInThread, + "breakInThread"); + bpRequest.enable(); + + display("TESTING BEGINS"); + + label0: + for (int testCase = 0; instruction != quit; testCase++) { + +// waitForEvent(bpRequest); + instruction = getInstruction(); + if (instruction == quit) { + vm.resume(); + break; + } + + display(":: case: # " + testCase); + + switch (testCase) { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test case section + case 0: + display("Step request will be created with size == StepRequest.STEP_LINE, depth == StepRequest.STEP_INTO"); + setAndCheckStepEvent ( bpRequest, + "StepRequest0", + "thread0", + checkedLines[testCase], + StepRequest.STEP_INTO); + break; + + case 1: + display("Step request will be created with size == StepRequest.STEP_LINE, depth == StepRequest.STEP_OVER"); + setAndCheckStepEvent ( bpRequest, + "StepRequest1", + "thread1", + checkedLines[testCase], + StepRequest.STEP_OVER); + break; + case 2: + display("Step request will be created with size == StepRequest.STEP_LINE, depth == StepRequest.STEP_OUT"); + setAndCheckStepEvent ( bpRequest, + "StepRequest2", + "thread2", + checkedLines[testCase], + StepRequest.STEP_OUT); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end of section + default: + instruction = quit; + setInstruction("quit"); + } + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methodss + + private StepRequest setStepRequest ( ThreadReference thread, int size, int depth, String property ) { + display("Setting a step request in thread: " + thread); + StepRequest stepRequest = null; + + try { + stepRequest = eventRManager.createStepRequest(thread, size, depth); + stepRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setStepRequest(): unexpected Exception while creating StepRequest: " + e1); + throw new Failure("setStep(): A StepRequest has not been set up."); + } + + display("setStepRequest(): A StepRequest has been set up."); + return stepRequest; + } + + private void setAndCheckStepEvent ( BreakpointRequest bpRequest, + String caseProperty, + String threadName, + int lineOfStepEvent, + int stepDepth ) { + display("Wait for brakepoint event in " + threadName); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + + // check location of breakpoint event + int lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != lineForBreakInThread) { + complain("Wrong line number of BreakpointEvent for " + threadName); + complain("\texpected value : " + lineForBreakInThread + "; got one : " + lineOfEvent); + exitCode = FAILED; + } + + ThreadReference thread = threadByName(threadName); + StepRequest stepRequest = setStepRequest( thread, + StepRequest.STEP_LINE, + stepDepth, + caseProperty); + stepRequest.enable(); + + display("waiting for StepEvent in " + threadName); + Event newEvent = waitForEvent(stepRequest); + if (newEvent instanceof StepEvent) { + String property = (String) newEvent.request().getProperty("number"); + display("got new StepEvent with property 'number' == " + property); + + if ( !property.equals(caseProperty) ) { + complain("property is not : " + caseProperty); + exitCode = FAILED; + } + // check location of step event + lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != lineOfStepEvent) { + switch (stepDepth) { + case StepRequest.STEP_INTO: + complain("Wrong line number of StepEvent for request with depth == StepRequest.STEP_INTO:" ); + break; + case StepRequest.STEP_OVER: + complain("Wrong line number of StepEvent for request with depth == StepRequest.STEP_OVER:" ); + break; + case StepRequest.STEP_OUT: + complain("Wrong line number of StepEvent for request with depth == StepRequest.STEP_OUT:" ); + break; + } + complain("\texpected value : " + lineOfStepEvent + "; got one : " + lineOfEvent); + exitCode = FAILED; + } + + } else if (newEvent instanceof BreakpointEvent) { + vm.resume(); + exitCode = FAILED; + complain("got unexpected BreakpointEvent, but StepEvent is not received"); + } else if (newEvent instanceof VMDeathEvent) { + exitCode = FAILED; + throw new Failure("got unexpected VMDeathtEvent, but StepEvent is not received"); + } + + stepRequest.disable(); + eventRManager.deleteEventRequest(stepRequest); + stepRequest = null; + display("request for StepEvent in " + threadName + " is deleted"); + } + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003/TestDescription.java new file mode 100644 index 00000000000..1529e5b8cef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks whether an implementation of + * EventRequestManager.createStepRequest (ThreadReference thread, int size, int depth) + * method complies with its spec. + * The test checks the following assertions: + * A size value of StepRequest.STEP_LINE will generate a step event each time + * the source line changes. A depth value of StepRequest.STEP_INTO will generate + * step events in any called methods. A depth value of StepRequest.STEP_OVER + * restricts step events to the current frame or caller frames. A depth value + * of StepRequest.STEP_OUT restricts step events to caller frames only. + * The debugger class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq003; + * the debuggee class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq003a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's breakInThread() method at the beginning of synchronized block; + * - the debuggee starts additional thread with 'thread1' name and it gets + * suspended at breakpoint; + * - After getting BreakpointEvent, the debugger sets StepRequest for thread1 and + * resumes debuggee; + * - after getting StepEvent, the debugger checks its location by comparing with + * expected line number value. + * There are three cases in the test: + * - step request is created with STEP_LINE size and STEP_INTO depth, + * - step request is created with STEP_LINE size and STEP_OVER depth, + * - step request is created with STEP_LINE size and STEP_OUT depth. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * This test is developed basing on analysis of 4628003 bug. The test is aimed + * to check to the case when debuggee's thread in step request does not wait + * for lock in syncronized block. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq003 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003a.java new file mode 100644 index 00000000000..e00752db4fb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003a.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class crstepreq003a { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Object waitnotifyObj = new Object(); + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = new Log(System.out, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + display("debuggee started!"); + + label0: + for (int testCase = 0; instruction != quit; testCase++) { + + switch (testCase) { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test case section + case 0: + + Thread thread0 = new Thread0crstepreq003a("thread0"); + threadStart(thread0); + threadJoin (thread0, "0"); + break; + + case 1: + + Thread thread1 = new Thread0crstepreq003a("thread1"); + threadStart(thread1); + threadJoin (thread1, "1"); + break; + + case 2: + + Thread thread2 = new Thread0crstepreq003a("thread2"); + threadStart(thread2); + threadJoin (thread2, "2"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end of section + + default: + instruction = quit; + break; + } + +// display("call methodForCommunication() #0"); +// methodForCommunication(); + if (instruction == quit) + break; + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + + static void threadJoin (Thread t, String number) { + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + complain("Case #" + number + ": caught unexpected InterruptedException while waiting for thread finish" ); + } + } + + static int threadStart (Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + exitCode = FAILED; + complain("Caught unexpected InterruptedException while waiting for thread start" ); + return FAILED; + } + } + return PASSED; + } + + static void breakInThread() { + Object dummy = new Object(); + synchronized(dummy) { // crstepreq003.lineForBreakInThread + int i = 1; // This is line of step event's location for STEP_OVER and STEP_INTO -- crstepreq003.checkedLines[0-1] + } + } + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + private static void methodForCommunication() { + int i = instruction; + int curInstruction = i; + } +} + +//--------------------------------------------------------- test specific classes + +/** + * This thread will be suspended on breakpoint. No locks are used. + */ +class Thread0crstepreq003a extends Thread { + public Thread0crstepreq003a (String name) { + super(name); + } + + public void run() { + crstepreq003a.display("enter thread " + getName()); + + synchronized(crstepreq003a.waitnotifyObj) { + crstepreq003a.waitnotifyObj.notifyAll(); + } + + crstepreq003a.display("call breakInThread()"); + crstepreq003a.breakInThread(); + + crstepreq003a.display("exit thread " + getName()); // This is line of step event's location for STEP_OUT -- crstepreq003.checkedLines[2] + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java new file mode 100644 index 00000000000..f2dba0bdd1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class crstepreq004 { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + private int instruction = 1; + private int waitTime; + private static int exitCode = PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.createStepRequest"; + private final static String className = ".crstepreq004"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + PASS_BASE); + } + + //------------------------------------------------------ test specific fields + + static final int lineForBreakInThread = 146; + static final int[] checkedLines = { 160, 160, 193 }; + static final int[] checkedLinesAlt = { 161, 161, 193 }; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new crstepreq004().runThis(argv, out); + System.out.println (exitStatus == PASSED ? "TEST PASSED" : "TEST FAILED"); + return exitCode; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStdout(log, "debuggee stdout> "); + debuggee.redirectStderr(log, "debuggee stderr> "); + debuggee.createIOPipe(); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (PASSED + PASS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitCode = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitCode = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitCode = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(PASSED + PASS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitCode; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = setBreakpoint( mainThread, + debuggeeClass, + "methodForCommunication", + lineForBreakInThread, + "breakpointForCommunication"); + bpRequest.enable(); + + display("TESTING BEGINS"); + + label0: + for (int testCase = 0; instruction != quit; testCase++) { + +// waitForEvent(bpRequest); + instruction = getInstruction(); + if (instruction == quit) { + vm.resume(); + break; + } + + display(":: case: # " + testCase); + + switch (testCase) { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test case section + case 0: + display("Step request will be created with size == StepRequest.STEP_LINE, depth == StepRequest.STEP_INTO"); + setAndCheckStepEvent ( bpRequest, + "StepRequest0", + "thread2", + testCase, + StepRequest.STEP_INTO); + break; + + case 1: + display("Step request will be created with size == StepRequest.STEP_LINE, depth == StepRequest.STEP_OVER"); + setAndCheckStepEvent ( bpRequest, + "StepRequest1", + "thread2", + testCase, + StepRequest.STEP_OVER); + break; + case 2: + display("Step request will be created with size == StepRequest.STEP_LINE, depth == StepRequest.STEP_OUT"); + setAndCheckStepEvent ( bpRequest, + "StepRequest2", + "thread2", + testCase, + StepRequest.STEP_OUT); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end of section + default: + instruction = quit; + setInstruction("quit"); + } + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methodss + + private StepRequest setStepRequest ( ThreadReference thread, int size, int depth, String property ) { + display("Setting a step request in thread: " + thread); + StepRequest stepRequest = null; + + try { + stepRequest = eventRManager.createStepRequest(thread, size, depth); + stepRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setStepRequest(): unexpected Exception while creating StepRequest: " + e1); + throw new Failure("setStep(): A StepRequest has not been set up."); + } + + display("setStepRequest(): A StepRequest has been set up."); + return stepRequest; + } + + private void setAndCheckStepEvent ( BreakpointRequest bpRequest, + String caseProperty, + String threadName, + int testCaseIndex, + int stepDepth) { + display("Wait for brakepoint event in " + threadName); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + + // check location of breakpoint event + int lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != lineForBreakInThread) { + complain("Wrong line number of BreakpointEvent for " + threadName); + complain("\texpected value : " + lineForBreakInThread + "; got one : " + lineOfEvent); + exitCode = FAILED; + } + + ThreadReference thread = threadByName(threadName); + StepRequest stepRequest = setStepRequest( thread, + StepRequest.STEP_LINE, + stepDepth, + caseProperty); + stepRequest.enable(); + + display("waiting for StepEvent in " + threadName); + Event newEvent = waitForEvent(stepRequest); + if (newEvent instanceof StepEvent) { + String property = (String) newEvent.request().getProperty("number"); + display("got new StepEvent with property 'number' == " + property); + + if ( !property.equals(caseProperty) ) { + complain("property is not : " + caseProperty); + exitCode = FAILED; + } + // check location of step event + lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + boolean isCorrectLine = lineOfEvent == checkedLines[testCaseIndex] || lineOfEvent == checkedLinesAlt[testCaseIndex]; + if (!isCorrectLine) { + switch (stepDepth) { + case StepRequest.STEP_INTO: + complain("Wrong line number of StepEvent for request with depth == StepRequest.STEP_INTO:" ); + break; + case StepRequest.STEP_OVER: + complain("Wrong line number of StepEvent for request with depth == StepRequest.STEP_OVER:" ); + break; + case StepRequest.STEP_OUT: + complain("Wrong line number of StepEvent for request with depth == StepRequest.STEP_OUT:" ); + break; + } + String msg = "\texpected line %d or %d; got %d"; + complain(String.format(msg, checkedLines[testCaseIndex], checkedLinesAlt[testCaseIndex], lineOfEvent)); + exitCode = FAILED; + } + + } else if (newEvent instanceof BreakpointEvent) { + vm.resume(); + exitCode = FAILED; + complain("got unexpected BreakpointEvent, but StepEvent is not received"); + } else if (newEvent instanceof VMDeathEvent) { + exitCode = FAILED; + throw new Failure("got unexpected VMDeathtEvent, but StepEvent is not received"); + } + + stepRequest.disable(); + eventRManager.deleteEventRequest(stepRequest); + stepRequest = null; + display("request for StepEvent in " + threadName + " is deleted"); + } + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004/TestDescription.java new file mode 100644 index 00000000000..c09187b7687 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks whether an implementation of + * EventRequestManager.createStepRequest (ThreadReference thread, int size, int depth) + * method complies with its spec. + * The test checks the following assertions: + * A size value of StepRequest.STEP_LINE will generate a step event each time + * the source line changes. A depth value of StepRequest.STEP_INTO will generate + * step events in any called methods. A depth value of StepRequest.STEP_OVER + * restricts step events to the current frame or caller frames. A depth value + * of StepRequest.STEP_OUT restricts step events to caller frames only. + * The debugger class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq004; + * the debuggee class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq004a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's methodForCommunication() method; + * - the debuggee starts two threads, thread1 and thread2. Each of them must hold + * the lock of lockObj1 object inside its run() method.Thread1 is first one who + * captures the lock, thread2 waits at beginning of synchronized block. + * The debuggee's main thread invokes methodForCommunication() method at this moment; + * - After getting BreakpointEvent, the debugger sets StepRequest for thread2 and + * resumes debuggee; + * - after getting StepEvent, the debugger checks its location by comparing with + * expected line number value. + * There are three cases in the test: + * - step request is created with STEP_LINE size and STEP_INTO depth, + * - step request is created with STEP_LINE size and STEP_OVER depth, + * - step request is created with STEP_LINE size and STEP_OUT depth. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * This test is developed basing on analysis of 4628003 bug. The test is aimed + * to check to the case when debuggee's thread in step request is waiting for + * lock release in syncronized block which is held by another thread. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq004 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004a.java new file mode 100644 index 00000000000..2f760c4dad2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004a.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class crstepreq004a { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Object lockObj = new Object(); + static Object lockObj1 = new Object(); + private static volatile boolean isFirstThreadReady = false; + private static volatile boolean isSecondThreadReady = false; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = new Log(System.out, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + display("debuggee started!"); + + label0: + for (int testCase = 0; instruction != quit; testCase++) { + + switch (testCase) { + case 0: + case 1: + case 2: + runTestCase(testCase); + break; + default: + instruction = quit; + break; + } + + if (instruction == quit) + break; + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + + private static void runTestCase(int testCaseId) { + isFirstThreadReady = false; + isSecondThreadReady = false; + Thread thread1 = new Thread1crstepreq004a("thread1"); + Thread thread2 = new Thread2crstepreq004a("thread2"); + synchronized (lockObj) { + thread1.start(); + while (!isFirstThreadReady) { + shortSleep(); + } + thread2.start(); + while (!isSecondThreadReady) { + shortSleep(); + } + + display("call methodForCommunication() #" + testCaseId); + methodForCommunication(); + } + threadJoin(thread1, "1"); + threadJoin(thread2, "2"); + } + + static void threadJoin (Thread t, String number) { + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + complain("Case #" + number + ": caught unexpected InterruptedException while waiting for thread finish" ); + } + } + + //---------------------------------------------------------- immutable common methods + + static void shortSleep() { + try { + Thread.currentThread().sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + private static void methodForCommunication() { + int i = instruction; + int curInstruction = i; // crstepreq004.lineForBreakInThread + } + + static void lockAndNotify1() { + synchronized(lockObj1) { + isFirstThreadReady = true; + synchronized(lockObj) { + } + } + } + + static void lockAndNotify2() { + isSecondThreadReady = true; + synchronized(lockObj1) { // thread is waiting here the lock when step request is created. + int i = 1; // This is line of step event for STEP_INTO and STEP_OVER -- crstepreq004.checkedLines[0-1] + } // crstepreq004.checkedLinesAlt[0-1] + } +} + +//--------------------------------------------------------- test specific classes + +/** + * First thread which owns and locks the crstepreq004a.lockObj1 monitor . + */ +class Thread1crstepreq004a extends Thread { + public Thread1crstepreq004a (String name) { + super(name); + } + + public void run() { + crstepreq004a.display("enter thread " + getName()); + crstepreq004a.lockAndNotify1(); + crstepreq004a.display("exit thread " + getName()); + } +} + +/** + * Second thread which who owns the crstepreq004a.lockObj1 monitor . + */ +class Thread2crstepreq004a extends Thread { + public Thread2crstepreq004a (String name) { + super(name); + } + + public void run() { + crstepreq004a.display("enter thread " + getName()); + crstepreq004a.lockAndNotify2(); + crstepreq004a.display("exit thread " + getName()); // This is line of step event for STEP_OUT -- crstepreq004.checkedLines[2] checkedLinesAlt[2]. + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005.java new file mode 100644 index 00000000000..c8dc5397924 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005.java @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class crstepreq005 { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + private int instruction = 1; + private int waitTime; + private static int exitCode = PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.createStepRequest"; + private final static String className = ".crstepreq005"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + static final int lineForBreak = 62; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + PASS_BASE); + } + + //------------------------------------------------------ test specific fields + + static final int maxCase = 4; + static final String[] brakeMethods = { + "caseRun", + "m00", + "m02", + "m02" + }; + static final int[][] checkedLines = { + { 152, 153, 154}, + { 174, 178, 157}, + { 182, 183, 168}, + { 183, 168, 169} + }; + + static final String debuggeeThreadName = prefix + ".Thread0crstepreq005a"; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new crstepreq005().runThis(argv, out); + System.out.println (exitStatus == PASSED ? "TEST PASSED" : "TEST FAILED"); + return exitCode; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStderr(log, ""); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (PASSED + PASS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitCode = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitCode = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitCode = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(PASSED + PASS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitCode; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + BreakpointRequest bpRequest = setBreakpoint( null, + debuggeeClass, + "methodForCommunication", + lineForBreak, + "breakForCommunication"); + bpRequest.enable(); + + StepRequest stepRequest = null; + + display("TESTING BEGINS"); + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + instruction = getInstruction(); + if (instruction == quit) { + vm.resume(); + break; + } + + display(":: CASE # " + testCase); + stepRequest = setStepRequest( bpRequest, + "thread" + testCase, + testCase, + "stepRequest" + testCase ); + + checkStepEvent( stepRequest, + "thread" + testCase, + testCase ); + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methods + + private StepRequest setStepRequest ( BreakpointRequest bpRequest, + String threadName, + int testCase, + String property ) { + StepRequest stepRequest = null; + for (;;) { + display("Wait for initial brakepoint event in " + threadName); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + + // check location of breakpoint event + int lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != lineForBreak) { + complain("Wrong line number of initial brakepoint event for " + threadName); + complain("\texpected value : " + lineForBreak + "; got one : " + lineOfEvent); + break; + } + + display("Getting mirror of thread: " + threadName); + ThreadReference thread = threadByName(threadName); + + display("Getting ReferenceType of thread: " + threadName); + ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); + + // set second breakpoint to suspend checked thread at the right location before + // setting step request + BreakpointRequest bpRequest1 = setBreakpoint( thread, + debuggeeThread, + brakeMethods[testCase], + checkedLines[testCase][0], + ""); + bpRequest1.addCountFilter(1); + bpRequest1.enable(); + + display("Wait for additional brakepoint event in " + threadName); + bpEvent = (BreakpointEvent)waitForEvent(bpRequest1); + + // check location of breakpoint event + lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][0]) { + complain("Wrong line number of additional brakepoint event for " + threadName); + complain("\texpected value : " + checkedLines[testCase][0] + "; got one : " + lineOfEvent); + break; + } + + display("Setting a step request in thread: " + thread); + try { + stepRequest = eventRManager.createStepRequest ( thread, + StepRequest.STEP_LINE, + StepRequest.STEP_OVER ); + stepRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setStepRequest(): unexpected Exception while creating StepRequest: " + e1); + break; + } + break; + } + if (stepRequest == null) { + throw new Failure("setStepRequest(): StepRequest has not been set up."); + } + display("setStepRequest(): StepRequest has been set up."); + return stepRequest; + } + + private void checkStepEvent ( StepRequest stepRequest, + String threadName, + int testCase ) { + stepRequest.enable(); + + display("waiting for first StepEvent in " + threadName); + Event newEvent = waitForEvent(stepRequest); + display("got first StepEvent"); + + display("CHECK1 for line location of first StepEvent."); + int lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][1]) { + complain("CHECK1 for line location of first StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][1] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK1 PASSED"); + } + + display("waiting for second StepEvent in " + threadName); + newEvent = waitForEvent(stepRequest); + display("got second StepEvent"); + + display("CHECK2 for line location of second StepEvent."); + lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][2]) { + complain("CHECK2 for line location of second StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][2] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK2 PASSED"); + } + + stepRequest.disable(); + eventRManager.deleteEventRequest(stepRequest); + stepRequest = null; + display("request for StepEvent in " + threadName + " is deleted"); + } + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private Event waitForEvent () { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + resultEvent = eventIterator.nextEvent(); + if (resultEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005/TestDescription.java new file mode 100644 index 00000000000..ae522252d81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks whether an implementation of + * EventRequestManager.createStepRequest (ThreadReference thread, int size, int depth) + * method complies with its spec. + * The test checks the following assertions: + * A size value of StepRequest.STEP_LINE will generate a step event each time + * the source line changes... + * A depth value of StepRequest.STEP_OVER restricts step events to the current + * frame or caller frames. + * The debugger class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq005; + * the debuggee class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq005a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's methodForCommunication() method. This method is invoked in + * additional 'thread1' started in debuggee. First breakpoint allows the debugger + * to obtain ThreadReference mirror of debuggee's 'thread1'; + * - after getting first BreakpointEvent, the debugger sets second BreakpointRequest + * to suspend 'thread1 at the right location before setting step request; + * - after getting second BreakpointEvent, the debugger sets StepRequest + * with STEP_LINE size and STEP_OVER depth, resumes the debuggee and + * waits for two consecutive StepEvents; + * - upon getting StepEvents, the debugger checks their locations by comparing with + * expected line number values. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * 4767945 TEST_BUG: crstepreq005 test fails in Mantis + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq005 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005a.java new file mode 100644 index 00000000000..10edb3d96a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class crstepreq005a { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + static void methodForCommunication() { + int i = instruction; // crstepreq005.lineForBreak + int curInstruction = i; + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static final int maxCase = 4; + static Object waitnotifyObj = new Object(); + static Thread thread1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + display("debuggee started!"); + + label0: + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + thread1 = new Thread0crstepreq005a(testCase); + threadStart(thread1); + threadJoin (thread1, testCase); + + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + + static void threadJoin (Thread t, int number) { + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + complain("Case #" + number + ": caught unexpected InterruptedException while waiting for thread finish" ); + } + } + + static int threadStart (Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + exitCode = FAILED; + complain("Caught unexpected InterruptedException while waiting for thread start" ); + return FAILED; + } + } + return PASSED; + } + +} + +//--------------------------------------------------------- test specific classes + +/** + * This thread will be suspended on breakpoint. No locks are used. + */ +class Thread0crstepreq005a extends Thread { + int testCase; + + public Thread0crstepreq005a (int testCase) { + super("thread" + testCase); + this.testCase = testCase; + } + + public void run() { + crstepreq005a.display("enter thread " + getName()); + synchronized(crstepreq005a.waitnotifyObj) { + crstepreq005a.waitnotifyObj.notifyAll(); + } + + crstepreq005a.methodForCommunication(); + caseRun(); + crstepreq005a.display("exit thread " + getName()); + } + + void caseRun() { + int i; + try { + switch (testCase) { + case 0: + i = m00(1); // crstepreq005.checkedLines[0][1] + i = m00(2); i = m00(3); // crstepreq005.checkedLines[0][2] + break; // crstepreq005.checkedLines[0][3] + + case 1: + i = m01(1); i = m01(2); // crstepreq005.checkedLines[1][2] + break; + + case 2: + i = m02(-1); + break; + + case 3: + i = m03(-1); + break; + } + } catch (DummyException e) { // crstepreq005.checkedLines[2][2] // crstepreq005.checkedLines[3][1] + crstepreq005a.display("DummyException was caught for testCase # " + testCase); // crstepreq005.checkedLines[3][2] + } + } + + int m00 (int arg) { + return arg++; // crstepreq005.checkedLines[1][0] + } + + int m01 (int arg) { + return m00(arg); // crstepreq005.checkedLines[1][1] + } + + int m02 (int arg) throws DummyException { + if (arg < 0) { // crstepreq005.checkedLines[2][0] + throw new DummyException(); // crstepreq005.checkedLines[2][1] // crstepreq005.checkedLines[3][0] + } + return arg++; + } + + int m03 (int arg) throws DummyException { + return m02(arg); + } + + class DummyException extends Exception {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006.java new file mode 100644 index 00000000000..2fdd39ab107 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006.java @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class crstepreq006 { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + private int instruction = 1; + private int waitTime; + private static int exitCode = PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.createStepRequest"; + private final static String className = ".crstepreq006"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + static final int lineForBreak = 62; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + PASS_BASE); + } + + //------------------------------------------------------ test specific fields + + static final int maxCase = 3; + static final String[] brakeMethods = { + "m00", + "m00", + "m00" + }; + static final int[][] checkedLines = { + { 167, 171, 151}, + { 167, 175, 156}, + { 167, 178, 187} + }; + + static final String debuggeeThreadName = prefix + ".Thread0crstepreq006a"; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new crstepreq006().runThis(argv, out); + System.out.println (exitStatus == PASSED ? "TEST PASSED" : "TEST FAILED"); + return exitCode; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStderr(log, ""); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (PASSED + PASS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitCode = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitCode = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitCode = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(PASSED + PASS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitCode; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + BreakpointRequest bpRequest = setBreakpoint( null, + debuggeeClass, + "methodForCommunication", + lineForBreak, + "breakForCommunication"); + bpRequest.enable(); + + StepRequest stepRequest = null; + + display("TESTING BEGINS"); + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + instruction = getInstruction(); + if (instruction == quit) { + vm.resume(); + break; + } + + display(":: CASE # " + testCase); + stepRequest = setStepRequest( bpRequest, + "thread" + testCase, + testCase, + "stepRequest" + testCase ); + + checkStepEvent( stepRequest, + "thread" + testCase, + testCase ); + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methods + + private StepRequest setStepRequest ( BreakpointRequest bpRequest, + String threadName, + int testCase, + String property ) { + StepRequest stepRequest = null; + for (;;) { + display("Wait for initial brakepoint event in " + threadName); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + + // check location of breakpoint event + int lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != lineForBreak) { + complain("Wrong line number of initial brakepoint event for " + threadName); + complain("\texpected value : " + lineForBreak + "; got one : " + lineOfEvent); + break; + } + + display("Getting mirror of thread: " + threadName); + ThreadReference thread = threadByName(threadName); + + display("Getting ReferenceType of thread: " + threadName); + ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); + + // set second breakpoint to suspend checked thread at the right location before + // setting step request + BreakpointRequest bpRequest1 = setBreakpoint( thread, + debuggeeThread, + brakeMethods[testCase], + checkedLines[testCase][0], + ""); + bpRequest1.addCountFilter(1); + bpRequest1.enable(); + + display("Wait for additional brakepoint event in " + threadName); + bpEvent = (BreakpointEvent)waitForEvent(bpRequest1); + + // check location of breakpoint event + lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][0]) { + complain("Wrong line number of additional brakepoint event for " + threadName); + complain("\texpected value : " + checkedLines[testCase][0] + "; got one : " + lineOfEvent); + break; + } + + display("Setting a step request in thread: " + thread); + try { + stepRequest = eventRManager.createStepRequest ( thread, + StepRequest.STEP_LINE, + StepRequest.STEP_OUT ); + stepRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setStepRequest(): unexpected Exception while creating StepRequest: " + e1); + break; + } + break; + } + if (stepRequest == null) { + throw new Failure("setStepRequest(): StepRequest has not been set up."); + } + display("setStepRequest(): StepRequest has been set up."); + return stepRequest; + } + + private void checkStepEvent ( StepRequest stepRequest, + String threadName, + int testCase ) { + stepRequest.enable(); + + display("waiting for first StepEvent in " + threadName); + Event newEvent = waitForEvent(stepRequest); + display("got first StepEvent"); + + display("CHECK1 for line location of first StepEvent."); + int lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][1]) { + complain("CHECK1 for line location of first StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][1] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK1 PASSED"); + } + + display("waiting for second StepEvent in " + threadName); + newEvent = waitForEvent(stepRequest); + display("got second StepEvent"); + + display("CHECK2 for line location of second StepEvent."); + lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][2]) { + complain("CHECK2 for line location of second StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][2] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK2 PASSED"); + } + + stepRequest.disable(); + eventRManager.deleteEventRequest(stepRequest); + stepRequest = null; + display("request for StepEvent in " + threadName + " is deleted"); + } + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private Event waitForEvent () { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + resultEvent = eventIterator.nextEvent(); + if (resultEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006/TestDescription.java new file mode 100644 index 00000000000..a238e9cdf63 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks whether an implementation of + * EventRequestManager.createStepRequest (ThreadReference thread, int size, int depth) + * method complies with its spec. + * The test checks the following assertions: + * A size value of StepRequest.STEP_LINE will generate a step event each time + * the source line changes... + * A depth value of StepRequest.STEP_OUT restricts step events to caller frames + * only. + * The debugger class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq006; + * the debuggee class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq006a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's methodForCommunication() method. This method is invoked in + * additional 'thread1' started in debuggee. First breakpoint allows the debugger + * to obtain ThreadReference mirror of debuggee's 'thread1'; + * - after getting first BreakpointEvent, the debugger sets second BreakpointRequest + * to suspend 'thread1 at the right location before setting step request; + * - after getting second BreakpointEvent, the debugger sets StepRequest + * with STEP_LINE size and STEP_OUT depth, resumes the debuggee and + * waits for two consecutive StepEvents; + * - upon getting StepEvents, the debugger checks their locations by comparing with + * expected line number values. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * 4767945 TEST_BUG: crstepreq005 test fails in Mantis + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq006 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006a.java new file mode 100644 index 00000000000..26f0681064f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class crstepreq006a { + + //------------------------------------------------------ immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //----------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + static void methodForCommunication() { + int i = instruction; // crstepreq006.lineForBreak + int curInstruction = i; + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static final int maxCase = 3; + static Object waitnotifyObj = new Object(); + static Thread thread1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + display("debuggee started!"); + + label0: + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + thread1 = new Thread0crstepreq006a(testCase); + threadStart(thread1); + threadJoin (thread1, testCase); + + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + + static void threadJoin (Thread t, int number) { + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + complain("Case #" + number + ": caught unexpected InterruptedException while waiting for thread finish" ); + } + } + + static int threadStart (Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + exitCode = FAILED; + complain("Caught unexpected InterruptedException while waiting for thread start" ); + return FAILED; + } + } + return PASSED; + } + +} + +//--------------------------------------------------------- test specific classes + +/** + * This thread will be suspended on breakpoint. No locks are used. + */ +class Thread0crstepreq006a extends Thread { + int testCase; + + public Thread0crstepreq006a (int testCase) { + super("thread" + testCase); + this.testCase = testCase; + } + + public void run() { + crstepreq006a.display("enter thread " + getName()); + synchronized(crstepreq006a.waitnotifyObj) { + crstepreq006a.waitnotifyObj.notifyAll(); + } + + crstepreq006a.methodForCommunication(); + caseRun(); + crstepreq006a.display("exit thread " + getName()); + } + + void caseRun() { + int i; + switch (testCase) { + case 0: + i = m01(1); // crstepreq006.checkedLines[0][2] + i = m01(2); + break; + + case 1: + i = m02(1); // crstepreq006.checkedLines[1][2] + break; + + case 2: + i = m04(-2); + break; + + } + } + + int m00 (int arg) { + return arg++; // crstepreq006.checkedLines[0-2][0] + } + + int m01 (int arg) { + return m00(arg); // crstepreq006.checkedLines[0][1] + } + + int m02 (int arg) { + int j = m00(arg); return m00(arg); } // crstepreq006.checkedLines[1][1] + + int m03 (int arg) throws DummyException { + arg = m00(arg); if (arg < 0) { throw new DummyException(); }; // crstepreq006.checkedLines[2][1] + return arg++; + } + + int m04 (int arg) { + int j = 0; + try { + j = m03(arg) + 1; + } catch (DummyException e) { + crstepreq006a.display("DummyException was caught for testCase # " + testCase); // // crstepreq006.checkedLines[2][2] + } + return j; + } + + class DummyException extends Exception {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007.java new file mode 100644 index 00000000000..7927dccddef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007.java @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class crstepreq007 { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + private int instruction = 1; + private int waitTime; + private static int exitCode = PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.createStepRequest"; + private final static String className = ".crstepreq007"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + static final int lineForBreak = 62; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + PASS_BASE); + } + + //------------------------------------------------------ test specific fields + + static final int maxCase = 4; + static final String[] brakeMethods = { + "caseRun", + "m00", + "caseRun", + "caseRun" + }; + static final int[][] checkedLines = { + { 152, 174, 152}, + { 174, 157, 178}, + { 161, 178, 174}, + { 165, 182, 185} + }; + + static final String debuggeeThreadName = prefix + ".Thread0crstepreq007a"; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new crstepreq007().runThis(argv, out); + System.out.println (exitStatus == PASSED ? "TEST PASSED" : "TEST FAILED"); + return exitCode; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStderr(log, ""); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (PASSED + PASS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitCode = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitCode = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitCode = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(PASSED + PASS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitCode; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + BreakpointRequest bpRequest = setBreakpoint( null, + debuggeeClass, + "methodForCommunication", + lineForBreak, + "breakForCommunication"); + bpRequest.enable(); + + StepRequest stepRequest = null; + + display("TESTING BEGINS"); + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + instruction = getInstruction(); + if (instruction == quit) { + vm.resume(); + break; + } + + display(":: CASE # " + testCase); + stepRequest = setStepRequest( bpRequest, + "thread" + testCase, + testCase, + "stepRequest" + testCase ); + + checkStepEvent( stepRequest, + "thread" + testCase, + testCase ); + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methods + + private StepRequest setStepRequest ( BreakpointRequest bpRequest, + String threadName, + int testCase, + String property ) { + StepRequest stepRequest = null; + for (;;) { + display("Wait for initial brakepoint event in " + threadName); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + + // check location of breakpoint event + int lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != lineForBreak) { + complain("Wrong line number of initial brakepoint event for " + threadName); + complain("\texpected value : " + lineForBreak + "; got one : " + lineOfEvent); + break; + } + + display("Getting mirror of thread: " + threadName); + ThreadReference thread = threadByName(threadName); + + display("Getting ReferenceType of thread: " + threadName); + ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); + + // set second breakpoint to suspend checked thread at the right location before + // setting step request + BreakpointRequest bpRequest1 = setBreakpoint( thread, + debuggeeThread, + brakeMethods[testCase], + checkedLines[testCase][0], + ""); + bpRequest1.addCountFilter(1); + bpRequest1.enable(); + + display("Wait for additional brakepoint event in " + threadName); + bpEvent = (BreakpointEvent)waitForEvent(bpRequest1); + + // check location of breakpoint event + lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][0]) { + complain("Wrong line number of additional brakepoint event for " + threadName); + complain("\texpected value : " + checkedLines[testCase][0] + "; got one : " + lineOfEvent); + break; + } + + display("Setting a step request in thread: " + thread); + try { + stepRequest = eventRManager.createStepRequest ( thread, + StepRequest.STEP_LINE, + StepRequest.STEP_INTO ); + stepRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setStepRequest(): unexpected Exception while creating StepRequest: " + e1); + break; + } + break; + } + if (stepRequest == null) { + throw new Failure("setStepRequest(): StepRequest has not been set up."); + } + display("setStepRequest(): StepRequest has been set up."); + return stepRequest; + } + + private void checkStepEvent ( StepRequest stepRequest, + String threadName, + int testCase ) { + stepRequest.enable(); + + display("waiting for first StepEvent in " + threadName); + Event newEvent = waitForEvent(stepRequest); + display("got first StepEvent"); + + display("CHECK1 for line location of first StepEvent."); + int lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][1]) { + complain("CHECK1 for line location of first StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][1] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK1 PASSED"); + } + + display("waiting for second StepEvent in " + threadName); + newEvent = waitForEvent(stepRequest); + display("got second StepEvent"); + + display("CHECK2 for line location of second StepEvent."); + lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][2]) { + complain("CHECK2 for line location of second StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][2] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK2 PASSED"); + } + + stepRequest.disable(); + eventRManager.deleteEventRequest(stepRequest); + stepRequest = null; + display("request for StepEvent in " + threadName + " is deleted"); + } + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private Event waitForEvent () { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + resultEvent = eventIterator.nextEvent(); + if (resultEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007/TestDescription.java new file mode 100644 index 00000000000..8455ca2c852 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq007. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks whether an implementation of + * EventRequestManager.createStepRequest (ThreadReference thread, int size, int depth) + * method complies with its spec. + * The test checks the following assertions: + * A size value of StepRequest.STEP_LINE will generate a step event each time + * the source line changes. A depth value of StepRequest.STEP_INTO will generate + * step events in any called methods. + * The debugger class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq007; + * the debuggee class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq007a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's methodForCommunication() method. This method is invoked in + * additional 'thread1' started in debuggee. First breakpoint allows the debugger + * to obtain ThreadReference mirror of debuggee's 'thread1'; + * - after getting first BreakpointEvent, the debugger sets second BreakpointRequest + * to suspend 'thread1 at the right location before setting step request; + * - after getting second BreakpointEvent, the debugger sets StepRequest + * with STEP_LINE size and STEP_INTO depth, resumes the debuggee and + * waits for two consecutive StepEvents; + * - upon getting StepEvents, the debugger checks their locations by comparing with + * expected line number values. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq007 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007a.java new file mode 100644 index 00000000000..5000cf0c7e6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class crstepreq007a { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + static void methodForCommunication() { + int i = instruction; // crstepreq007.lineForBreak + int curInstruction = i; + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static final int maxCase = 4; + static Object waitnotifyObj = new Object(); + static Thread thread1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + display("debuggee started!"); + + label0: + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + thread1 = new Thread0crstepreq007a(testCase); + threadStart(thread1); + threadJoin (thread1, testCase); + + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + + static void threadJoin (Thread t, int number) { + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + complain("Case #" + number + ": caught unexpected InterruptedException while waiting for thread finish" ); + } + } + + static int threadStart (Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + exitCode = FAILED; + complain("Caught unexpected InterruptedException while waiting for thread start" ); + return FAILED; + } + } + return PASSED; + } + +} + +//--------------------------------------------------------- test specific classes + +/** + * This thread will be suspended on breakpoint. No locks are used. + */ +class Thread0crstepreq007a extends Thread { + int testCase; + + public Thread0crstepreq007a (int testCase) { + super("thread" + testCase); + this.testCase = testCase; + } + + public void run() { + crstepreq007a.display("enter thread " + getName()); + synchronized(crstepreq007a.waitnotifyObj) { + crstepreq007a.waitnotifyObj.notifyAll(); + } + + crstepreq007a.methodForCommunication(); + caseRun(); + crstepreq007a.display("exit thread " + getName()); + } + + void caseRun() { + int i; + try { + switch (testCase) { + case 0: + i = m00(1); // crstepreq007.checkedLines[0][0,2] + i = m00(2); + break; + + case 1: + i = m00(1); i = m01(2); // crstepreq007.checkedLines[1][1] + break; + + case 2: + i = m01(1); // crstepreq007.checkedLines[2][0] + break; + + case 3: + i = m02(1); // crstepreq007.checkedLines[3][0] + break; + } + } catch (DummyException e) { + crstepreq007a.display("DummyException was caught for testCase # " + testCase); + } + } + + int m00 (int arg) { + return arg++; // crstepreq007.checkedLines[0][1] // crstepreq007.checkedLines[1][0] // crstepreq007.checkedLines[2][2] + } + + int m01 (int arg) { + return m00(arg); // crstepreq007.checkedLines[1][2] // crstepreq007.checkedLines[2][1] + } + + int m02 (int arg) throws DummyException { + if (arg < 0) { // crstepreq007.checkedLines[2][1] + throw new DummyException(); + } + return arg++; // crstepreq007.checkedLines[2][2] + } + + int m03 (int arg) throws DummyException { + return m02(arg); + } + + class DummyException extends Exception {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008.java new file mode 100644 index 00000000000..317027a846d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008.java @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class crstepreq008 { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + private int instruction = 1; + private int waitTime; + private static int exitCode = PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.createStepRequest"; + private final static String className = ".crstepreq008"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + static final int lineForBreak = 62; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + PASS_BASE); + } + + //------------------------------------------------------ test specific fields + + static final int maxCase = 4; + static final String[] brakeMethods = { + "caseRun", + "m00", + "m02", + "m02" + }; + static final int[][] checkedLines = { + { 152, 152, 152}, + { 174, 174, 174}, + { 182, 182, 183}, + { 183, 183, 183} + }; + + static final String debuggeeThreadName = prefix + ".Thread0crstepreq008a"; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new crstepreq008().runThis(argv, out); + System.out.println (exitStatus == PASSED ? "TEST PASSED" : "TEST FAILED"); + return exitCode; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStderr(log, ""); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (PASSED + PASS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitCode = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitCode = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitCode = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(PASSED + PASS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitCode; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + BreakpointRequest bpRequest = setBreakpoint( null, + debuggeeClass, + "methodForCommunication", + lineForBreak, + "breakForCommunication"); + bpRequest.enable(); + + StepRequest stepRequest = null; + + display("TESTING BEGINS"); + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + instruction = getInstruction(); + if (instruction == quit) { + vm.resume(); + break; + } + + display(":: CASE # " + testCase); + stepRequest = setStepRequest( bpRequest, + "thread" + testCase, + testCase, + "stepRequest" + testCase ); + + checkStepEvent( stepRequest, + "thread" + testCase, + testCase ); + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methods + + private StepRequest setStepRequest ( BreakpointRequest bpRequest, + String threadName, + int testCase, + String property ) { + StepRequest stepRequest = null; + for (;;) { + display("Wait for initial brakepoint event in " + threadName); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + + // check location of breakpoint event + int lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != lineForBreak) { + complain("Wrong line number of initial brakepoint event for " + threadName); + complain("\texpected value : " + lineForBreak + "; got one : " + lineOfEvent); + break; + } + + display("Getting mirror of thread: " + threadName); + ThreadReference thread = threadByName(threadName); + + display("Getting ReferenceType of thread: " + threadName); + ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); + + // set second breakpoint to suspend checked thread at the right location before + // setting step request + BreakpointRequest bpRequest1 = setBreakpoint( thread, + debuggeeThread, + brakeMethods[testCase], + checkedLines[testCase][0], + ""); + bpRequest1.addCountFilter(1); + bpRequest1.enable(); + + display("Wait for additional brakepoint event in " + threadName); + bpEvent = (BreakpointEvent)waitForEvent(bpRequest1); + + // check location of breakpoint event + lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][0]) { + complain("Wrong line number of additional brakepoint event for " + threadName); + complain("\texpected value : " + checkedLines[testCase][0] + "; got one : " + lineOfEvent); + break; + } + + display("Setting a step request in thread: " + thread); + try { + stepRequest = eventRManager.createStepRequest ( thread, + StepRequest.STEP_MIN, + StepRequest.STEP_OVER ); + stepRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setStepRequest(): unexpected Exception while creating StepRequest: " + e1); + break; + } + break; + } + if (stepRequest == null) { + throw new Failure("setStepRequest(): StepRequest has not been set up."); + } + display("setStepRequest(): StepRequest has been set up."); + return stepRequest; + } + + private void checkStepEvent ( StepRequest stepRequest, + String threadName, + int testCase ) { + stepRequest.enable(); + + display("waiting for first StepEvent in " + threadName); + Event newEvent = waitForEvent(stepRequest); + display("got first StepEvent"); + + display("CHECK1 for line location of first StepEvent."); + int lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][1]) { + complain("CHECK1 for line location of first StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][1] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK1 PASSED"); + } + + display("waiting for second StepEvent in " + threadName); + newEvent = waitForEvent(stepRequest); + display("got second StepEvent"); + + display("CHECK2 for line location of second StepEvent."); + lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][2]) { + complain("CHECK2 for line location of second StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][2] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK2 PASSED"); + } + + stepRequest.disable(); + eventRManager.deleteEventRequest(stepRequest); + stepRequest = null; + display("request for StepEvent in " + threadName + " is deleted"); + } + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private Event waitForEvent () { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + resultEvent = eventIterator.nextEvent(); + if (resultEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008/TestDescription.java new file mode 100644 index 00000000000..f509a823b66 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq008. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks whether an implementation of + * EventRequestManager.createStepRequest (ThreadReference thread, int size, int depth) + * method complies with its spec. + * The test checks the following assertions: + * A sizevalue of StepRequest.STEP_MIN will generate a step event each time + * the code index changes. It represents the smallest step size available and + * often maps to the instruction level.... + * A depth value of StepRequest.STEP_OVER restricts step events to the current + * frame or caller frames. + * The debugger class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq008; + * the debuggee class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq008a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's methodForCommunication() method. This method is invoked in + * additional 'thread1' started in debuggee. First breakpoint allows the debugger + * to obtain ThreadReference mirror of debuggee's 'thread1'; + * - after getting first BreakpointEvent, the debugger sets second BreakpointRequest + * to suspend 'thread1 at the right location before setting step request; + * - after getting second BreakpointEvent, the debugger sets StepRequest + * with STEP_MIN size and STEP_OVER depth, resumes the debuggee and + * waits for two consecutive StepEvents; + * - upon getting StepEvents, the debugger checks their locations by comparing with + * expected line number values. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq008 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008a.java new file mode 100644 index 00000000000..64f20c1fe26 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class crstepreq008a { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + static void methodForCommunication() { + int i = instruction; // crstepreq008.lineForBreak + int curInstruction = i; + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static final int maxCase = 4; + static Object waitnotifyObj = new Object(); + static Thread thread1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + display("debuggee started!"); + + label0: + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + thread1 = new Thread0crstepreq008a(testCase); + threadStart(thread1); + threadJoin (thread1, testCase); + + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + + static void threadJoin (Thread t, int number) { + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + complain("Case #" + number + ": caught unexpected InterruptedException while waiting for thread finish" ); + } + } + + static int threadStart (Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + exitCode = FAILED; + complain("Caught unexpected InterruptedException while waiting for thread start" ); + return FAILED; + } + } + return PASSED; + } + +} + +//--------------------------------------------------------- test specific classes + +/** + * This thread will be suspended on breakpoint. No locks are used. + */ +class Thread0crstepreq008a extends Thread { + int testCase; + + public Thread0crstepreq008a (int testCase) { + super("thread" + testCase); + this.testCase = testCase; + } + + public void run() { + crstepreq008a.display("enter thread " + getName()); + synchronized(crstepreq008a.waitnotifyObj) { + crstepreq008a.waitnotifyObj.notifyAll(); + } + + crstepreq008a.methodForCommunication(); + caseRun(); + crstepreq008a.display("exit thread " + getName()); + } + + void caseRun() { + int i; + try { + switch (testCase) { + case 0: + i = m00(1); // crstepreq008.checkedLines[0][0-2] + i = m00(2); i = m00(3); + break; + + case 1: + i = m01(1); i = m01(2); + break; + + case 2: + i = m02(-1); + break; + + case 3: + i = m03(-1); + break; + } + } catch (DummyException e) { + crstepreq008a.display("DummyException was caught for testCase # " + testCase); + } + } + + int m00 (int arg) { + return arg++; // crstepreq008.checkedLines[1][0-2] + } + + int m01 (int arg) { + return m00(arg); + } + + int m02 (int arg) throws DummyException { + if (arg < 0) { // crstepreq008.checkedLines[2][0-1] + throw new DummyException(); // crstepreq008.checkedLines[2][2]// crstepreq008.checkedLines[3][0-2] + } + return arg++; + } + + int m03 (int arg) throws DummyException { + return m02(arg); + } + + class DummyException extends Exception {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009.java new file mode 100644 index 00000000000..fb89b818947 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009.java @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class crstepreq009 { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + private int instruction = 1; + private int waitTime; + private static int exitCode = PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.createStepRequest"; + private final static String className = ".crstepreq009"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + static final int lineForBreak = 62; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + PASS_BASE); + } + + //------------------------------------------------------ test specific fields + + static final int maxCase = 3; + static final String[] brakeMethods = { + "m00", + "m00", + "m00" + }; + static final int[][] checkedLines = { + { 167, 171, 151}, + { 167, 175, 175}, + { 167, 178, 178} + }; + + static final String debuggeeThreadName = prefix + ".Thread0crstepreq009a"; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new crstepreq009().runThis(argv, out); + System.out.println (exitStatus == PASSED ? "TEST PASSED" : "TEST FAILED"); + return exitCode; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStderr(log, ""); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (PASSED + PASS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitCode = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitCode = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitCode = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(PASSED + PASS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitCode; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + BreakpointRequest bpRequest = setBreakpoint( null, + debuggeeClass, + "methodForCommunication", + lineForBreak, + "breakForCommunication"); + bpRequest.enable(); + + StepRequest stepRequest = null; + + display("TESTING BEGINS"); + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + instruction = getInstruction(); + if (instruction == quit) { + vm.resume(); + break; + } + + display(":: CASE # " + testCase); + stepRequest = setStepRequest( bpRequest, + "thread" + testCase, + testCase, + "stepRequest" + testCase ); + + checkStepEvent( stepRequest, + "thread" + testCase, + testCase ); + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methods + + private StepRequest setStepRequest ( BreakpointRequest bpRequest, + String threadName, + int testCase, + String property ) { + StepRequest stepRequest = null; + for (;;) { + display("Wait for initial brakepoint event in " + threadName); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + + // check location of breakpoint event + int lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != lineForBreak) { + complain("Wrong line number of initial brakepoint event for " + threadName); + complain("\texpected value : " + lineForBreak + "; got one : " + lineOfEvent); + break; + } + + display("Getting mirror of thread: " + threadName); + ThreadReference thread = threadByName(threadName); + + display("Getting ReferenceType of thread: " + threadName); + ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); + + // set second breakpoint to suspend checked thread at the right location before + // setting step request + BreakpointRequest bpRequest1 = setBreakpoint( thread, + debuggeeThread, + brakeMethods[testCase], + checkedLines[testCase][0], + ""); + bpRequest1.addCountFilter(1); + bpRequest1.enable(); + + display("Wait for additional brakepoint event in " + threadName); + bpEvent = (BreakpointEvent)waitForEvent(bpRequest1); + + // check location of breakpoint event + lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][0]) { + complain("Wrong line number of additional brakepoint event for " + threadName); + complain("\texpected value : " + checkedLines[testCase][0] + "; got one : " + lineOfEvent); + break; + } + + display("Setting a step request in thread: " + thread); + try { + stepRequest = eventRManager.createStepRequest ( thread, + StepRequest.STEP_MIN, + StepRequest.STEP_OUT ); + stepRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setStepRequest(): unexpected Exception while creating StepRequest: " + e1); + break; + } + break; + } + if (stepRequest == null) { + throw new Failure("setStepRequest(): StepRequest has not been set up."); + } + display("setStepRequest(): StepRequest has been set up."); + return stepRequest; + } + + private void checkStepEvent ( StepRequest stepRequest, + String threadName, + int testCase ) { + stepRequest.enable(); + + display("waiting for first StepEvent in " + threadName); + Event newEvent = waitForEvent(stepRequest); + display("got first StepEvent"); + + display("CHECK1 for line location of first StepEvent."); + int lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][1]) { + complain("CHECK1 for line location of first StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][1] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK1 PASSED"); + } + + display("waiting for second StepEvent in " + threadName); + newEvent = waitForEvent(stepRequest); + display("got second StepEvent"); + + display("CHECK2 for line location of second StepEvent."); + lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][2]) { + complain("CHECK2 for line location of second StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][2] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK2 PASSED"); + } + + stepRequest.disable(); + eventRManager.deleteEventRequest(stepRequest); + stepRequest = null; + display("request for StepEvent in " + threadName + " is deleted"); + } + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private Event waitForEvent () { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + resultEvent = eventIterator.nextEvent(); + if (resultEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009/TestDescription.java new file mode 100644 index 00000000000..35049f97640 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq009. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks whether an implementation of + * EventRequestManager.createStepRequest (ThreadReference thread, int size, int depth) + * method complies with its spec. + * The test checks the following assertions: + * A sizevalue of StepRequest.STEP_MIN will generate a step event each time the code + * index changes. It represents the smallest step size available and often maps to + * the instruction level.... + * A depth value of StepRequest.STEP_OUT restricts step events to caller frames + * only. + * The debugger class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq009; + * the debuggee class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq009a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's methodForCommunication() method. This method is invoked in + * additional 'thread1' started in debuggee. First breakpoint allows the debugger + * to obtain ThreadReference mirror of debuggee's 'thread1'; + * - after getting first BreakpointEvent, the debugger sets second BreakpointRequest + * to suspend 'thread1 at the right location before setting step request; + * - after getting second BreakpointEvent, the debugger sets StepRequest + * with STEP_MIN size and STEP_OUT depth, resumes the debuggee and + * waits for two consecutive StepEvents; + * - upon getting StepEvents, the debugger checks their locations by comparing with + * expected line number values. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq009 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009a.java new file mode 100644 index 00000000000..8df51baa8b2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class crstepreq009a { + + //------------------------------------------------------ immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //----------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + static void methodForCommunication() { + int i = instruction; // crstepreq009.lineForBreak + int curInstruction = i; + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static final int maxCase = 3; + static Object waitnotifyObj = new Object(); + static Thread thread1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + display("debuggee started!"); + + label0: + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + thread1 = new Thread0crstepreq009a(testCase); + threadStart(thread1); + threadJoin (thread1, testCase); + + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + + static void threadJoin (Thread t, int number) { + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + complain("Case #" + number + ": caught unexpected InterruptedException while waiting for thread finish" ); + } + } + + static int threadStart (Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + exitCode = FAILED; + complain("Caught unexpected InterruptedException while waiting for thread start" ); + return FAILED; + } + } + return PASSED; + } + +} + +//--------------------------------------------------------- test specific classes + +/** + * This thread will be suspended on breakpoint. No locks are used. + */ +class Thread0crstepreq009a extends Thread { + int testCase; + + public Thread0crstepreq009a (int testCase) { + super("thread" + testCase); + this.testCase = testCase; + } + + public void run() { + crstepreq009a.display("enter thread " + getName()); + synchronized(crstepreq009a.waitnotifyObj) { + crstepreq009a.waitnotifyObj.notifyAll(); + } + + crstepreq009a.methodForCommunication(); + caseRun(); + crstepreq009a.display("exit thread " + getName()); + } + + void caseRun() { + int i; + switch (testCase) { + case 0: + i = m01(1); // crstepreq009.checkedLines[0][2] + i = m01(2); + break; + + case 1: + i = m02(1); + break; + + case 2: + i = m04(-2); + break; + + } + } + + int m00 (int arg) { + return arg++; // crstepreq009.checkedLines[0-2][0] + } + + int m01 (int arg) { + return m00(arg); // crstepreq009.checkedLines[0][1] + } + + int m02 (int arg) { + int j = m00(arg); return m00(arg); } // crstepreq009.checkedLines[1][1-2] + + int m03 (int arg) throws DummyException { + arg = m00(arg); if (arg < 0) { throw new DummyException(); }; // crstepreq009.checkedLines[2][1-2] + return arg++; + } + + int m04 (int arg) { + int j = 0; + try { + j = m03(arg) + 1; + } catch (DummyException e) { + crstepreq009a.display("DummyException was caught for testCase # " + testCase); + } + return j; + } + + class DummyException extends Exception {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010.java new file mode 100644 index 00000000000..c615b430a2c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class crstepreq010 { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + private int instruction = 1; + private int waitTime; + private static int exitCode = PASSED; + + private ArgumentHandler argHandler; + private Log log; + private Debugee debuggee; + private VirtualMachine vm; + private ReferenceType debuggeeClass; + + private EventRequestManager eventRManager; + private EventSet eventSet; + private EventIterator eventIterator; + + //------------------------------------------------------ mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.createStepRequest"; + private final static String className = ".crstepreq010"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + static final int lineForBreak = 62; + + //------------------------------------------------------ immutable common methods + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + PASS_BASE); + } + + //------------------------------------------------------ test specific fields + + static final int maxCase = 5; + static final String[] brakeMethods = { + "caseRun", + "m01", + "m02", + "m03", + "caseRun" + }; + static final int[][] checkedLines = { + { 152, 152, 152}, + { 182, 182, 182}, + { 187, 187, 187}, + { 193, 193, 193}, + { 169, 169, 196} + }; + + static final String debuggeeThreadName = prefix + ".Thread0crstepreq010a"; + + //------------------------------------------------------ mutable common methods + + public static int run (String argv[], PrintStream out) { + + int exitStatus = new crstepreq010().runThis(argv, out); + System.out.println (exitStatus == PASSED ? "TEST PASSED" : "TEST FAILED"); + return exitCode; + } + + private int runThis(String argv[], PrintStream out) { + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStderr(log, ""); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + debuggeeClass = waitForDebuggeeClassPrepared(); + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (PASSED + PASS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitCode = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } catch (VMDisconnectedException e) { + exitCode = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitCode = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(PASSED + PASS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitCode; + } + + //--------------------------------------------------------- mutable common methods + + private void execTest() { + BreakpointRequest bpRequest = setBreakpoint( null, + debuggeeClass, + "methodForCommunication", + lineForBreak, + "breakForCommunication"); + bpRequest.enable(); + + StepRequest stepRequest = null; + + display("TESTING BEGINS"); + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + instruction = getInstruction(); + if (instruction == quit) { + vm.resume(); + break; + } + + display(":: CASE # " + testCase); + stepRequest = setStepRequest( bpRequest, + "thread" + testCase, + testCase, + "stepRequest" + testCase ); + + checkStepEvent( stepRequest, + "thread" + testCase, + testCase ); + } + display("TESTING ENDS"); + } + + //--------------------------------------------------------- test specific methods + + private StepRequest setStepRequest ( BreakpointRequest bpRequest, + String threadName, + int testCase, + String property ) { + StepRequest stepRequest = null; + for (;;) { + display("Wait for initial brakepoint event in " + threadName); + BreakpointEvent bpEvent = (BreakpointEvent)waitForEvent(bpRequest); + + // check location of breakpoint event + int lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != lineForBreak) { + complain("Wrong line number of initial brakepoint event for " + threadName); + complain("\texpected value : " + lineForBreak + "; got one : " + lineOfEvent); + break; + } + + display("Getting mirror of thread: " + threadName); + ThreadReference thread = threadByName(threadName); + + display("Getting ReferenceType of thread: " + threadName); + ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); + + // set second breakpoint to suspend checked thread at the right location before + // setting step request + BreakpointRequest bpRequest1 = setBreakpoint( thread, + debuggeeThread, + brakeMethods[testCase], + checkedLines[testCase][0], + ""); + bpRequest1.addCountFilter(1); + bpRequest1.enable(); + + display("Wait for additional brakepoint event in " + threadName); + bpEvent = (BreakpointEvent)waitForEvent(bpRequest1); + + // check location of breakpoint event + lineOfEvent = ((LocatableEvent)bpEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][0]) { + complain("Wrong line number of additional brakepoint event for " + threadName); + complain("\texpected value : " + checkedLines[testCase][0] + "; got one : " + lineOfEvent); + break; + } + + display("Setting a step request in thread: " + thread); + try { + stepRequest = eventRManager.createStepRequest ( thread, + StepRequest.STEP_MIN, + StepRequest.STEP_INTO ); + stepRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setStepRequest(): unexpected Exception while creating StepRequest: " + e1); + break; + } + break; + } + if (stepRequest == null) { + throw new Failure("setStepRequest(): StepRequest has not been set up."); + } + display("setStepRequest(): StepRequest has been set up."); + return stepRequest; + } + + private void checkStepEvent ( StepRequest stepRequest, + String threadName, + int testCase ) { + stepRequest.enable(); + + display("waiting for first StepEvent in " + threadName); + Event newEvent = waitForEvent(stepRequest); + display("got first StepEvent"); + + display("CHECK1 for line location of first StepEvent."); + int lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][1]) { + complain("CHECK1 for line location of first StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][1] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK1 PASSED"); + } + + display("waiting for second StepEvent in " + threadName); + newEvent = waitForEvent(stepRequest); + display("got second StepEvent"); + + display("CHECK2 for line location of second StepEvent."); + lineOfEvent = ((LocatableEvent)newEvent).location().lineNumber(); + if (lineOfEvent != checkedLines[testCase][2]) { + complain("CHECK2 for line location of second StepEvent FAILED for CASE # " + testCase); + complain("\texpected value : " + checkedLines[testCase][2] + "; got one : " + lineOfEvent); + exitCode = FAILED; + } else { + display("CHECK2 PASSED"); + } + + stepRequest.disable(); + eventRManager.deleteEventRequest(stepRequest); + stepRequest = null; + display("request for StepEvent in " + threadName + " is deleted"); + } + + //--------------------------------------------------------- immutable common methods + + void display(String msg) { + log.display("debugger > " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Returns a BreakpointRequest object in case of success, otherwise throws Failure. + */ + private BreakpointRequest setBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + int bpLine, + String property) { + + display("Setting a breakpoint in :"); + display(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine + "; property: " + property); + + List allLineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + allLineLocations = method.allLineLocations(); + + display("Getting location for breakpoint..."); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == bpLine) { + lineLocation = curLocation; + break; + } + } + if (lineLocation == null) { + throw new TestBug("Incorrect line number of methods' location"); + } + + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } + breakpRequest.putProperty("number", property); + } catch ( Exception e1 ) { + complain("setBreakpoint(): unexpected Exception while creating BreakpointRequest: " + e1); + breakpRequest = null; + } + } catch ( Exception e2 ) { + complain("setBreakpoint(): unexpected Exception while getting locations: " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + throw new Failure("setBreakpoint(): A breakpoint has not been set up."); + } + + display("setBreakpoint(): A breakpoint has been set up."); + return breakpRequest; + } + + private Event waitForEvent (EventRequest eventRequest) { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private Event waitForEvent () { + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + resultEvent = eventIterator.nextEvent(); + if (resultEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ThreadReference threadByName(String name) throws Failure{ + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + while (li.hasNext()) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new Failure("Thread with searching for name is not found: " + name); + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010/TestDescription.java new file mode 100644 index 00000000000..a2cddfd5d2c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createStepRequest/crstepreq010. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks whether an implementation of + * EventRequestManager.createStepRequest (ThreadReference thread, int size, int depth) + * method complies with its spec. + * The test checks the following assertions: + * A sizevalue of StepRequest.STEP_MIN will generate a step event each time the code + * index changes. It represents the smallest step size available and often maps to + * the instruction level... + * A depth value of StepRequest.STEP_INTO will generate step events in any called methods. + * The debugger class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq010; + * the debuggee class - nsk.jdi.EventRequestManager.createStepRequest.crstepreq010a; + * The test works as follows. At first, preliminary phase: + * - the debugger connects to the debuggee using nsk.jdi.share classes; + * - the debugger waits for the VMStartEvent and requested ClassPrepareEvent for + * debuggee class. + * At second, test specific phase, each action is performed for every test case: + * - the debugger waits for requested BreakpointEvent which is set on a line + * of debuggee's methodForCommunication() method. This method is invoked in + * additional 'thread1' started in debuggee. First breakpoint allows the debugger + * to obtain ThreadReference mirror of debuggee's 'thread1'; + * - after getting first BreakpointEvent, the debugger sets second BreakpointRequest + * to suspend 'thread1 at the right location before setting step request; + * - after getting second BreakpointEvent, the debugger sets StepRequest + * with STEP_MIN size and STEP_INTO depth, resumes the debuggee and + * waits for two consecutive StepEvents; + * - upon getting StepEvents, the debugger checks their locations by comparing with + * expected line number values. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createStepRequest.crstepreq010 + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq010a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createStepRequest.crstepreq010 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010a.java new file mode 100644 index 00000000000..2b9d71c0d69 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010a.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.createStepRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class crstepreq010a { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + static void methodForCommunication() { + int i = instruction; // crstepreq010.lineForBreak + int curInstruction = i; + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static final int maxCase = 5; + static Object waitnotifyObj = new Object(); + static Thread thread1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + display("debuggee started!"); + + label0: + for (int testCase = 0; testCase < maxCase && instruction != quit; testCase++) { + + thread1 = new Thread0crstepreq010a(testCase); + threadStart(thread1); + threadJoin (thread1, testCase); + + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + + static void threadJoin (Thread t, int number) { + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + complain("Case #" + number + ": caught unexpected InterruptedException while waiting for thread finish" ); + } + } + + static int threadStart (Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + exitCode = FAILED; + complain("Caught unexpected InterruptedException while waiting for thread start" ); + return FAILED; + } + } + return PASSED; + } + +} + +//--------------------------------------------------------- test specific classes + +/** + * This thread will be suspended on breakpoint. No locks are used. + */ +class Thread0crstepreq010a extends Thread { + int testCase; + + public Thread0crstepreq010a (int testCase) { + super("thread" + testCase); + this.testCase = testCase; + } + + public void run() { + crstepreq010a.display("enter thread " + getName()); + synchronized(crstepreq010a.waitnotifyObj) { + crstepreq010a.waitnotifyObj.notifyAll(); + } + + crstepreq010a.methodForCommunication(); + caseRun(); + crstepreq010a.display("exit thread " + getName()); + } + + void caseRun() { + int i; + try { + switch (testCase) { + case 0: + i = m00(1); // crstepreq010.checkedLines[0][0-2] + i = m00(2); + break; + + case 1: + i = m00(1); i = m01(2); + break; + + case 2: + i = m02(-1); + break; + + case 3: + i = m03(1); + break; + + case 4: + m04(); // crstepreq010.checkedLines[4][0-2] + break; + } + } catch (DummyException e) { + crstepreq010a.display("DummyException was caught for testCase # " + testCase); + } + } + + int m00 (int arg) { + return arg++; + } + + int m01 (int arg) { + return m00(arg); // crstepreq010.checkedLines[1][0-2] + } + + int m02 (int arg) throws DummyException { + if (arg < 0) { + throw new DummyException(); // crstepreq010.checkedLines[2][0-2] + } + return arg++; + } + + int m03 (int arg) throws DummyException { + return m02(arg); // crstepreq010.checkedLines[3][0-2] + } + + void m04 () {} // crstepreq010.checkedLines[4][2] + + class DummyException extends Exception {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java new file mode 100644 index 00000000000..4ce208821dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createThreadDeathRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createThreadDeathRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Creates a new disabled ThreadDeathRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class tdreg001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new tdreg001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createThreadDeathRequest.tdreg001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + ThreadDeathRequest tdRequest1 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating: tdRequest1 = eventRManager.createThreadDeathRequest();"); + tdRequest1 = eventRManager.createThreadDeathRequest(); + log2(" checking up on if request is disabled"); + if (tdRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is not disabled"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001/TestDescription.java new file mode 100644 index 00000000000..b48ea188dc9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createThreadDeathRequest() + * complies with its spec: + * public ThreadDeathRequest createThreadDeathRequest() + * Creates a new disabled ThreadDeathRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * Returns: the created ThreadDeathRequest + * The test checks up on the following assertions: + * - Creates a new disabled ThreadDeathRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createThreadDeathRequest.tdreg001; + * the debuggee program - nsk.jdi.EventRequestManager.createThreadDeathRequest.tdreg001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createThreadDeathRequest.tdreg001 + * nsk.jdi.EventRequestManager.createThreadDeathRequest.tdreg001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createThreadDeathRequest.tdreg001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001a.java new file mode 100644 index 00000000000..716a1a6ef89 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createThreadDeathRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the tdreg001 JDI test. + */ + +public class tdreg001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java new file mode 100644 index 00000000000..8c081f2bb22 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createThreadStartRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createThreadStartRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - Creates a new disabled ThreadDeathRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class tsreg001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new tsreg001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createThreadStartRequest.tsreg001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + ThreadStartRequest tsRequest1 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating: tsRequest1 = eventRManager.createThreadStartRequest();"); + tsRequest1 = eventRManager.createThreadStartRequest(); + log2(" checking up on if request is disabled"); + if (tsRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is not disabled"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001/TestDescription.java new file mode 100644 index 00000000000..ea419899416 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createThreadStartRequest() + * complies with its spec: + * public ThreadDeathRequest createThreadStartRequest() + * Creates a new disabled ThreadDeathRequest. + * The new event request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * Returns: the created ThreadDeathRequest + * The test checks up on the following assertions: + * - Creates a new disabled ThreadDeathRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createThreadStartRequest.tsreg001; + * the debuggee program - nsk.jdi.EventRequestManager.createThreadStartRequest.tsreg001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createThreadStartRequest.tsreg001 + * nsk.jdi.EventRequestManager.createThreadStartRequest.tsreg001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createThreadStartRequest.tsreg001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001a.java new file mode 100644 index 00000000000..86892712abd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createThreadStartRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the tsreg001 JDI test. + */ + +public class tsreg001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java new file mode 100644 index 00000000000..1885e595acb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createVMDeathRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.createVMDeathRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertions:
    + * - Creates a new disabled VMDeathRequest.
    + * - Throws: UnsupportedOperationException -
    + * if the target VM does not support this operation.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class vmdreg001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new vmdreg001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.createVMDeathRequest.vmdreg001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + VMDeathRequest vmdRequest1 = null; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + if (vm.canRequestVMDeathEvent()) { + log2("......creating: vmdRequest1 = eventRManager.createVMDeathRequest();"); + vmdRequest1 = eventRManager.createVMDeathRequest(); + log2(" checking up on if request is disabled"); + if (vmdRequest1.isEnabled()) { + testExitCode = FAILED; + log3("ERROR: request is not disabled"); + } + } else { + try { + log2("......creating: vmdRequest1 = eventRManager.createVMDeathRequest();"); + vmdRequest1 = eventRManager.createVMDeathRequest(); + testExitCode = FAILED; + log3("ERROR: no UnsupportedOperationException thrown"); + } catch ( UnsupportedOperationException e ) { + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001/TestDescription.java new file mode 100644 index 00000000000..1361d306f7c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.createVMDeathRequest() + * complies with its spec: + * public VMDeathRequest createVMDeathRequest() + * Creates a new disabled VMDeathRequest. + * The new request is added to the list managed by this EventRequestManager. + * Use EventRequest.enable() to activate this event request. + * Not all target virtual machines support this operation. + * Use VirtualMachine.canRequestVMDeathEvent() to determine + * if the operation is supported. + * Returns: the created request + * Throws: UnsupportedOperationException - + * if the target VM does not support this operation. + * The test checks up on the following assertions: + * - Creates a new disabled VMDeathRequest. + * - Throws: UnsupportedOperationException - + * if the target VM does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.createVMDeathRequest.vmdreg001; + * the debuggee program - nsk.jdi.EventRequestManager.createVMDeathRequest.vmdreg001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.createVMDeathRequest.vmdreg001 + * nsk.jdi.EventRequestManager.createVMDeathRequest.vmdreg001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.createVMDeathRequest.vmdreg001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001a.java new file mode 100644 index 00000000000..303fe67dd3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.createVMDeathRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the vmdreg001 JDI test. + */ + +public class vmdreg001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java new file mode 100644 index 00000000000..5c9275617d4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.deleteAllBreakpoints; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.deleteAllBreakpoints()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - All breakpoints are deleted, that is, following call to
    + * EventRequestManager.breakpointRequests()
    + * returns empty list.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debugger resumes
    + * the debuggee, and both end.
    + *
    + */ + +public class delallbreakp002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new delallbreakp002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.deleteAllBreakpoints.delallbreakp002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + Location breakpLocation = null; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + BreakpointRequest request = null; + BreakpointRequest bpRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + vm.resume(); + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating BreakpointRequests"); + for (int i1 = 0; i1 < bpRequests.length; i1++) { + bpRequests[i1] = eventRManager.createBreakpointRequest(breakpLocation); + bpRequests[i1].putProperty("number", String.valueOf(i1)); + } + + log2("......deleting all BreakpointRequests"); + eventRManager.deleteAllBreakpoints(); + log2("...... getting new list of BreakpointRequests"); + requests = eventRManager.breakpointRequests(); + + log2("...... checking up on size of the list; 0 is expected"); + listSize = requests.size(); + if ( listSize != 0 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected 0 "); + } + + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); +breakpLocation = lineLocation; + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002/TestDescription.java new file mode 100644 index 00000000000..b6ba0f21783 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.deleteAllBreakpoints() + * complies with its spec: + * public void deleteAllBreakpoints() + * Remove all breakpoints managed by this EventRequestManager. + * The test checks up on the following assertion: + * - All breakpoints are deleted, that is, following call to + * EventRequestManager.breakpointRequests() + * returns empty list. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.deleteAllBreakpoints.delallbreakp002; + * the debuggee program - nsk.jdi.EventRequestManager.deleteAllBreakpoints.delallbreakp002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.deleteAllBreakpoints.delallbreakp002 + * nsk.jdi.EventRequestManager.deleteAllBreakpoints.delallbreakp002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.deleteAllBreakpoints.delallbreakp002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002a.java new file mode 100644 index 00000000000..77a0aa35a8b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.deleteAllBreakpoints; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the delallbreakp002 JDI test. + */ + +public class delallbreakp002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested +/* + case 0: + methodForCommunication(); + break ; + */ + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java new file mode 100644 index 00000000000..fdd49ac9c3b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.deleteEventRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.deleteEventRequest()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Once the eventRequest is deleted, no operations
    + * (for example, EventRequest.setEnabled(boolean)) are permitted -
    + * attempts to do so will generally cause
    + * an InvalidRequestStateException.
    + * Note: only operations specified to throw InvalidRequestStateException
    + * are not permitted.
    + * Testcases unclude all 12 subclasses of EventRequest created by
    + * EventRequestManager.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares testcases and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class delevtreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new delevtreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + Location breakpLocation = null; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + EventRequest requestArray[] = new EventRequest[12]; + + String fieldName1 = "testField1"; + String fieldName2 = "testField2"; + String fieldName3 = "testField3"; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + Field field1 = debuggeeClass.fieldByName(fieldName1); + + ReferenceType refType = (ReferenceType) + debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2)).type(); + + ThreadReference threadRef = (ThreadReference) + debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName3)); + + String requests[] = { "AccessWatchpoint", "ModificationWatchpoint", + "Breakpoint", "ClassPrepare", + "ClassUnload", "Exception", + "MethodEntry", "MethodExit", + "Step", "ThreadDeath", + "ThreadStart", "VMDeath" }; + + requestArray[0] = eventRManager.createAccessWatchpointRequest(field1); + requestArray[1] = eventRManager.createModificationWatchpointRequest(field1); + requestArray[2] = eventRManager.createBreakpointRequest(breakpLocation); + requestArray[3] = eventRManager.createClassPrepareRequest(); + requestArray[4] = eventRManager.createClassUnloadRequest(); + requestArray[5] = eventRManager.createExceptionRequest(refType, false, false); + requestArray[6] = eventRManager.createMethodEntryRequest(); + requestArray[7] = eventRManager.createMethodExitRequest(); + requestArray[8] = eventRManager.createStepRequest(threadRef, StepRequest.STEP_MIN, StepRequest.STEP_OUT); + requestArray[9] = eventRManager.createThreadDeathRequest(); + requestArray[10] = eventRManager.createThreadStartRequest(); + requestArray[11] = eventRManager.createVMDeathRequest(); + + for (int i1 = 0; i1 < requestArray.length; i1++) { + + log2("......eventRManager.deleteEventRequest(requestArray[i1]); :: " + requests[i1]); + eventRManager.deleteEventRequest(requestArray[i1]); + + try { + requestArray[i1].addCountFilter(1); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException for addCountFilter(1);"); + } catch ( InvalidRequestStateException e ) { + } + try { + requestArray[i1].disable(); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException for disable();"); + } catch ( InvalidRequestStateException e ) { + } + try { + requestArray[i1].enable(); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException for enable();"); + } catch ( InvalidRequestStateException e ) { + } + try { + requestArray[i1].getProperty("number"); + } catch ( InvalidRequestStateException e ) { + testExitCode = FAILED; + log3("ERROR: InvalidRequestStateException for getProperty('number');"); + } + try { + requestArray[i1].isEnabled(); + } catch ( InvalidRequestStateException e ) { + testExitCode = FAILED; + log3("ERROR: InvalidRequestStateException for isEnabled();"); + } + try { + requestArray[i1].putProperty("number", "request" + i1); + } catch ( InvalidRequestStateException e ) { + testExitCode = FAILED; + log3("ERROR: InvalidRequestStateException for putProperty('number', 'request' + i1);"); + } + try { + requestArray[i1].setEnabled(true); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException for setEnabled(true);"); + } catch ( InvalidRequestStateException e ) { + } + try { + requestArray[i1].setSuspendPolicy(EventRequest.SUSPEND_NONE); + testExitCode = FAILED; + log3("ERROR: NO InvalidRequestStateException for setSuspendPolicy(EventRequest.SUSPEND_NONE);"); + } catch ( InvalidRequestStateException e ) { + } + try { + requestArray[i1].suspendPolicy(); + } catch ( InvalidRequestStateException e ) { + testExitCode = FAILED; + log3("ERROR: InvalidRequestStateException for suspendPolicy();"); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); +breakpLocation = lineLocation; + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002/TestDescription.java new file mode 100644 index 00000000000..4391085dbe1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-4613913 + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.deleteEventRequest() + * complies with its spec: + * public void deleteEventRequest(EventRequest eventRequest) + * Removes an eventRequest. The eventRequest is disabled and the removed from the + * requests managed by this EventRequestManager. + * Once the eventRequest is deleted, no operations + * (for example, EventRequest.setEnabled(boolean)) are permitted - + * attempts to do so will generally cause an InvalidRequestStateException. + * No other eventRequests are effected. + * Because this method changes the underlying lists of event requests, + * attempting to directly delete from a list returned by a request accessor + * (e.g. below): + * Iterator iter = requestManager.stepRequests().iterator(); + * while (iter.hasNext()) { + * requestManager.deleteEventRequest(iter.next()); + * } + * may cause a ConcurrentModificationException. + * Instead use deleteEventRequests(List) or copy the list before iterating. + * Parameters: eventRequest - the eventRequest to remove + * The test checks up on the following assertion: + * Once the eventRequest is deleted, no operations + * (for example, EventRequest.setEnabled(boolean)) are permitted - + * attempts to do so will generally cause an InvalidRequestStateException. + * Testcases unclude all 12 sublcasses of EventRequest created by EventRequestManager. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq002; + * the debuggee program - nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq002 + * nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002a.java new file mode 100644 index 00000000000..519654834df --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002a.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.deleteEventRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the delevtreq002 JDI test. + */ + +public class delevtreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static int testField1 = 0; + static NullPointerException testField2 = new NullPointerException("test"); + static Thread1delevtreq002a testField3 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + synchronized (lockObj1) { + testField3 = new Thread1delevtreq002a("thread1"); + threadStart(testField3); + methodForCommunication(); + } + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj1 = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class Thread1delevtreq002a extends Thread { + + String tName = null; + + public Thread1delevtreq002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + delevtreq002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(delevtreq002a.waitnotifyObj) { + delevtreq002a.waitnotifyObj.notify(); + } + synchronized(delevtreq002a.lockObj1) { + delevtreq002a.log1(" 'run': exit :: threadName == " + tName); + } + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003.java new file mode 100644 index 00000000000..ec150daeada --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.deleteEventRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test checks up com.sun.jdi.EventRequestManager.deleteEventRequest() + * after class file redefinition. + * + * The test performs as follow: + * Debuggee has two classes. Debugger creates a BreakpointRequest at the + * first class and waits a corresponding event. After getting BreakpointEvent, + * debugger redefines the second class and tries to delete BreakpointRequest. + */ + +public class delevtreq003 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.EventRequestManager.deleteEventRequest."; + private final static String debuggerName = prefix + "delevtreq003"; + public final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b"; + + private final static String classFileName = "delevtreq003b.class"; + private final static String newClassFile = "newclass" + File.separator + + prefix.replace('.',File.separatorChar) + + classFileName; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + public final static int expectedEventCount = 1; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain(msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + delevtreq003 thisTest = new delevtreq003(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.redirectOutput(log); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + int eventCount = 0; + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\nevent ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\nevent ===>>> " + event); + prepareTestCases(); + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\nevent ===>>> " + event); + ClassType testedClass; + testedClass = (ClassType )debugee.classByName(testedClassName); + + display("\nredefining..."); + redefineDebugee(testedClass, newClassFile); + + eventCount++; + boolean isBrkpEnabled = event.request().isEnabled(); + if (!isBrkpEnabled) { + complain("breakpoint was disabled after " + + "the redefinition of an other class"); + exitStatus = Consts.TEST_FAILED; + } else { + display("\nis breakpoint enabled?\t" + isBrkpEnabled); + display("\ndeleting the breakpoint request..."); + evm.deleteEventRequest(event.request()); + } + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (eventCount != expectedEventCount) { + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee(ReferenceType refType, String classFileName) { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(refType, classFileName); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(ReferenceType refType, String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(classDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(refType, arrayToRedefine); + return mapForClass; + } + + private void prepareTestCases() { + debugeeClass = debugee.classByName(debugeeName); + display("debugeeClass\t\t:" + debugeeClass.name()); + display("setting breakpoint..."); + debugee.setBreakpoint(debugeeClass, + delevtreq003a.brkpMethodName, + delevtreq003a.brkpLineNumber); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/TestDescription.java new file mode 100644 index 00000000000..6468af3e6f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up com.sun.jdi.EventRequestManager.deleteEventRequest() + * after class file redefinition. + * The test performs as follow: + * Debuggee has two classes (A and B). Debugger creates a BreakpointRequest + * at the first class A and waits a corresponding event. After getting + * BreakpointEvent, debugger redefines the second class B and tries to + * delete BreakpointRequest. + * COMMENTS + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq003 + * nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq003a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.deleteEventRequest.delevtreq003 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/newclass/delevtreq003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/newclass/delevtreq003b.java new file mode 100644 index 00000000000..6decdcb6475 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003/newclass/delevtreq003b.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.deleteEventRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * delevtreq003b is deugee's part of the delevtreq003. + */ + +public class delevtreq003b { + public final static int INITIAL_VALUE = 0; + public final static int BEFORE_REDEFINITION = 1; + public final static int AFTER_REDEFINITION = 2; + + public static boolean loadClass = false; + public static int flag = INITIAL_VALUE; + + public static void runIt(boolean doWait) { + + flag = AFTER_REDEFINITION; +// ^^^^^^^^^^^^^^^^^^^ it will be redefined + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003a.java new file mode 100644 index 00000000000..7c474a87b83 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003a.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.deleteEventRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * delevtreq003a is deugee's part of the delevtreq003. + */ +public class delevtreq003a { + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 50; + + private static Log log = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.out, argHandler); + + delevtreq003b.loadClass = true; + + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003b.java new file mode 100644 index 00000000000..a14ba1a9acc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq003b.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.deleteEventRequest; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * delevtreq003b is deugee's part of the delevtreq003. + */ + +public class delevtreq003b { + public final static int INITIAL_VALUE = 0; + public final static int BEFORE_REDEFINITION = 1; + public final static int AFTER_REDEFINITION = 2; + + public static boolean loadClass = false; + public static int flag = INITIAL_VALUE; + + public static void runIt(boolean doWait) { + + flag = BEFORE_REDEFINITION; +// ^^^^^^^^^^^^^^^^^^^ it will be redefined + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java new file mode 100644 index 00000000000..43e423d399e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.deleteEventRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.deleteEventRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * After invoking the tested method,
    + * the methods returning Lists of requests,
    + * such as EventRequestManager.accessWatchpointRequests(),
    + * return a List containing no eventRequests
    + * deleted by the tested method.
    + * Testcases include all subclasses of EventRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares testcases and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks required.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class delevtreqs002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new delevtreqs002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.deleteEventRequests.delevtreqs002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + Location breakpLocation = null; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + final int length1 = 10; + final int length2 = 12; + EventRequest requestArray[][] = new EventRequest[length1][length2]; + + String fieldName1 = "testField1"; + String fieldName2 = "testField2"; + String fieldName3 = "testField3"; + + List requests = null; + ListIterator li = null; + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + Field field1 = debuggeeClass.fieldByName(fieldName1); + + ReferenceType refType = (ReferenceType) + debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName2)).type(); + + + log2("......creating EventRequests"); + for (int i1 = 0; i1 < length1; i1++) { + + ThreadReference threadRef = (ThreadReference) + ( (ArrayReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName3)) + ).getValue(i1); + + requestArray[i1][0] = eventRManager.createAccessWatchpointRequest(field1); + requestArray[i1][1] = eventRManager.createModificationWatchpointRequest(field1); + requestArray[i1][2] = eventRManager.createBreakpointRequest(breakpLocation); + requestArray[i1][3] = eventRManager.createClassPrepareRequest(); + requestArray[i1][4] = eventRManager.createClassUnloadRequest(); + requestArray[i1][5] = eventRManager.createExceptionRequest(refType, false, false); + requestArray[i1][6] = eventRManager.createMethodEntryRequest(); + requestArray[i1][7] = eventRManager.createMethodExitRequest(); + requestArray[i1][8] = eventRManager.createStepRequest(threadRef, StepRequest.STEP_MIN, StepRequest.STEP_OUT); + requestArray[i1][9] = eventRManager.createThreadDeathRequest(); + requestArray[i1][10] = eventRManager.createThreadStartRequest(); + requestArray[i1][11] = eventRManager.createVMDeathRequest(); + } + for ( int ii1 = 0; ii1 < length1; ii1++) { + for ( int ii2 = 0; ii2 < length2; ii2++) { + requestArray[ii1][ii2].putProperty("number", "request " + ii1 + " " + ii2); + } + } + + + log2("......deleting Requests and checking up on Lists"); + for (int i2 = 0; i2 < length1; i2++) { + + EventRequest awRequest = requestArray[i2][0]; + EventRequest mwRequest = requestArray[i2][1]; + EventRequest bp1Request = requestArray[i2][2]; + EventRequest cp1Request = requestArray[i2][3]; + EventRequest cuRequest = requestArray[i2][4]; + EventRequest exRequest = requestArray[i2][5]; + EventRequest menRequest = requestArray[i2][6]; + EventRequest mexRequest = requestArray[i2][7]; + EventRequest stRequest = requestArray[i2][8]; + EventRequest tdRequest = requestArray[i2][9]; + EventRequest tsRequest = requestArray[i2][10]; + EventRequest vmdRequest = requestArray[i2][11]; + + requests = new LinkedList(); + + try { + requests.add(awRequest); + requests.add(mwRequest); + requests.add(bp1Request); + requests.add(cp1Request); + requests.add(cuRequest); + requests.add(exRequest); + requests.add(menRequest); + requests.add(mexRequest); + requests.add(stRequest); + requests.add(tdRequest); + requests.add(tsRequest); + requests.add(vmdRequest); + } catch ( UnsupportedOperationException e ) { + testExitCode = FAILED; + log3("ERROR: unexpected UnsupportedOperationException"); + break; + } + + eventRManager.deleteEventRequests(requests); + + for (EventRequest er : eventRManager.accessWatchpointRequests()) { + if ( er.equals(awRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted AccessWatchpointRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.modificationWatchpointRequests()) { + if ( er.equals(mwRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted ModificationWatchpointRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.breakpointRequests()) { + if ( er.equals(bp1Request) ) { + testExitCode = FAILED; + log3("ERROR: deleted BreakpointRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.classPrepareRequests()) { + if ( er.equals(cp1Request) ) { + testExitCode = FAILED; + log3("ERROR: deleted ClassPrepareRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.classUnloadRequests()) { + if ( er.equals(cuRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted ClassUnloadRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.exceptionRequests()) { + if ( er.equals(exRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted ExceptionRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.methodEntryRequests()) { + if ( er.equals(menRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted MethodEntryRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.methodExitRequests()) { + if ( er.equals(mexRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted MethodExitRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.stepRequests()) { + if ( er.equals(stRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted StepRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.threadDeathRequests()) { + if ( er.equals(tdRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted ThreadDeathRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.threadStartRequests()) { + if ( er.equals(tsRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted ThreadStartRequest is in the List :: " + er.getProperty("number") ); + } + } + + for (EventRequest er : eventRManager.vmDeathRequests()) { + if ( er.equals(vmdRequest) ) { + testExitCode = FAILED; + log3("ERROR: deleted VMDeathRequest is in the List :: " + er.getProperty("number") ); + } + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); +breakpLocation = lineLocation; + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002/TestDescription.java new file mode 100644 index 00000000000..c77afc1e606 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.deleteEventRequests() + * complies with its spec: + * public void deleteEventRequests(List eventRequests) + * Removes a list of EventRequests. + * Parameters: eventRequests - the list of eventRequests to remove + * The test checks up on the following assertion: + * After invoking the tested method, + * the methods returning Lists of requests, + * such as EventRequestManager.accessWatchpointRequests(), + * return a List containing no eventRequests deleted by the tested method. + * Testcases include all subclasses of EventRequest. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.deleteEventRequests.delevtreqs002; + * the debuggee program - nsk.jdi.EventRequestManager.deleteEventRequests.delevtreqs002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.deleteEventRequests.delevtreqs002 + * nsk.jdi.EventRequestManager.deleteEventRequests.delevtreqs002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.deleteEventRequests.delevtreqs002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002a.java new file mode 100644 index 00000000000..7ade8be26c4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002a.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.deleteEventRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the delevtreqs002 JDI test. + */ + +public class delevtreqs002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static int testField1 = 0; + static NullPointerException testField2 = new NullPointerException("test"); + static Thread1delevtreqs002a testField3[] = new Thread1delevtreqs002a[10]; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + synchronized (lockObj1) { + for (int ii = 0; ii < 10; ii++) { + testField3[ii] = new Thread1delevtreqs002a("thread" + ii); + threadStart(testField3[ii]); + } + methodForCommunication(); + } + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + static Object lockObj1 = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + +} + +class Thread1delevtreqs002a extends Thread { + + String tName = null; + + public Thread1delevtreqs002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + delevtreqs002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(delevtreqs002a.waitnotifyObj) { + delevtreqs002a.waitnotifyObj.notify(); + } + synchronized(delevtreqs002a.lockObj1) { + delevtreqs002a.log1(" 'run': exit :: threadName == " + tName); + } + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001.java new file mode 100644 index 00000000000..c0916034e80 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq001.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.exceptionRequests; + +import com.sun.jdi.ReferenceType; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; +import com.sun.jdi.AbsentInformationException; +import com.sun.jdi.ObjectCollectedException; + +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.exceptionRequests() + * properly returns all previously created ExceptionRequest objects for the + * different kinds of methods in two debuggee's classes when: + *
  • event requests are disabled + *
  • event requests are enabled
    + * The debuggee loads several dummy classes which ReferenceType + * objects are obtained by the debugger for exercising + * the exceptionRequests().
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class excreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String PACK = + "nsk.jdi.EventRequestManager.exceptionRequests"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int EXC_NUM = 4; +// list of debuggee's loaded classes + static final String DEBUGGEE_CLS[][] = { + {PACK + ".excreq001t", "excreq001t.java"}, + {PACK + ".excreq001a", "excreq001a.java"}, + {PACK + ".excreq001b", "excreq001b.java"}, + {PACK + ".excreq001c", "excreq001c.java"}, + }; +// caught/uncaught exception notifications + static final boolean DEBUGGEE_NTFS[][] = { + {true, true}, + {true, false}, + {false, false}, + {false, true} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new excreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + ExceptionRequest excRequest[] = new ExceptionRequest[EXC_NUM]; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLS[0][0]); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "excreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + for (int i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.exceptionRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled exception requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class excreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/exceptionRequests/excreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new excreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.exceptionRequests.excreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + String fieldName = "testField"; + + List requests = null; + ListIterator li = null; + + ExceptionRequest request = null; + ExceptionRequest cuRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType refType = (ReferenceType) + debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)).type(); + + log2("......creating ExceptionRequests"); + for (int i1 = 0; i1 < cuRequests.length; i1++) { + cuRequests[i1] = eventRManager.createExceptionRequest(refType, false, false); + cuRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new ExceptionRequest"); + requests = eventRManager.exceptionRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (ExceptionRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created ExceptionRequest"); + cuRequests[i1].enable(); + requests = eventRManager.exceptionRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (ExceptionRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting ExceptionRequests"); + for (int i2 = cuRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(cuRequests[i2]); + requests = eventRManager.exceptionRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002/TestDescription.java new file mode 100644 index 00000000000..d504c67f653 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/exceptionRequests/excreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.exceptionRequests() + * complies with its spec: + * public List exceptionRequests() + * Return an unmodifiable list of the enabled and disabled exception requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all ExceptionRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled exception requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.exceptionRequests.excreq002; + * the debuggee program - nsk.jdi.EventRequestManager.exceptionRequests.excreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.exceptionRequests.excreq002 + * nsk.jdi.EventRequestManager.exceptionRequests.excreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.exceptionRequests.excreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002a.java new file mode 100644 index 00000000000..c7a3ed9c802 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.exceptionRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the excreq002 JDI test. + */ + +public class excreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static NullPointerException testField = new NullPointerException("test"); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001.java new file mode 100644 index 00000000000..dbbb475b031 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class hashcode001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.EventRequestManager.hashCode."; + private final static String className = "hashcode001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + display("Checking hashCode() method for EventRequestManager object"); + + EventRequestManager eventRequestManager = debuggee.VM().eventRequestManager(); + int hCode = eventRequestManager.hashCode(); + + if (hCode == 0) { + complain("hashCode() returns 0 for EventRequestManager object"); + exitStatus = Consts.TEST_FAILED; + } + + int hCode1 = eventRequestManager.hashCode(); + if (hCode != hCode1) { + complain("hashCode() is not consistent for EventRequestManager object" + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + // get new reference to the same EventRequestManager and get hash code. + hCode1 = debuggee.VM().eventRequestManager().hashCode(); + if (hCode != hCode1) { + complain("hashCode() does not return same value for equal EventRequestManager object " + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + display("hashCode() returns for EventRequestManager object : " + hCode); + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..46a617824f4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/hashCode/hashcode001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public hashCode() method of an implementing class of + * com.sun.jdi.request.EventRequestManager interface. + * The test checks an assertion cited from spec for hashCode() method of + * java.lang.Object class: + * The general contract of hashCode is: + * - Whenever it is invoked on the same object more than once during + * an execution of a Java application, the hashCode method must + * consistently return the same integer, provided no information used + * in equals comparisons on the object is modified. + * ... + * - If two objects are equal according to the equals(Object) method, + * then calling the hashCode method on each of the two objects must + * produce the same integer result. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for EventRequestManager + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.hashCode.hashcode001 + * nsk.jdi.EventRequestManager.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001a.java new file mode 100644 index 00000000000..dc8c10753d8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/hashCode/hashcode001a.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventRequestManager.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class hashcode001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(hashcode001.SIGNAL_READY); + receiveSignal(hashcode001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq001.java new file mode 100644 index 00000000000..ca8c0e1fbe7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq001.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.methodEntryRequests; + +import com.sun.jdi.request.MethodEntryRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.methodEntryRequests() + * properly returns all MethodEntryRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled.
    + * The MethodEntryRequest objects are distinguished by the different + * EventRequest's properties.
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class methentreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final int TIMEOUT_DELTA = 1000; // in milliseconds + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.methodEntryRequests.methentreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int MENTRS_NUM = 7; + static final String PROPS[][] = { + {"first", "a quick"}, + {"second", "brown"}, + {"third", "fox"}, + {"fourth", "jumps"}, + {"fifth", "over"}, + {"sixth", "the lazy"}, + {"seventh", "dog"} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new methentreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + MethodEntryRequest mentrRequest[] = new MethodEntryRequest[MENTRS_NUM]; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "methentreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + for (int i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.methodEntryRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled method entry requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class methentreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new methentreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.methodEntryRequests.methentreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + MethodEntryRequest request = null; + MethodEntryRequest meRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating MethodEntryRequests"); + for (int i1 = 0; i1 < meRequests.length; i1++) { + meRequests[i1] = eventRManager.createMethodEntryRequest(); + meRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new MethodEntryRequest"); + requests = eventRManager.methodEntryRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (MethodEntryRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created MethodEntryRequest"); + meRequests[i1].enable(); + requests = eventRManager.methodEntryRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (MethodEntryRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting MethodEntryRequests"); + for (int i2 = meRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(meRequests[i2]); + requests = eventRManager.methodEntryRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + log2("breakpointForCommunication"); + + do { + getEventSet(); + + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) + return; + + log2(" received: " + event); + + if (EventFilters.filtered(event)) { + eventSet.resume(); + } + else { + break; + } + } while (true); + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002/TestDescription.java new file mode 100644 index 00000000000..ba80356ead5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.methodEntryRequests() + * complies with its spec: + * public List methodEntryRequests() + * Return an unmodifiable list of the enabled and disabled method entry requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all MethodEntryRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled method entry requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.methodEntryRequests.methentreq002; + * the debuggee program - nsk.jdi.EventRequestManager.methodEntryRequests.methentreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.methodEntryRequests.methentreq002 + * nsk.jdi.EventRequestManager.methodEntryRequests.methentreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.methodEntryRequests.methentreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002a.java new file mode 100644 index 00000000000..9f55b029901 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.methodEntryRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the methentreq002 JDI test. + */ + +public class methentreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq001.java new file mode 100644 index 00000000000..d6852a0b5cb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq001.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.methodExitRequests; + +import com.sun.jdi.request.MethodExitRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.event.*; + +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.methodExitRequests() + * properly returns all MethodExitRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled.
    + * The MethodExitRequest objects are distinguished by the different + * EventRequest's properties.
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class methexitreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final int TIMEOUT_DELTA = 1000; // in milliseconds + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.methodExitRequests.methexitreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int MEXIT_NUM = 7; + static final String PROPS[][] = { + {"first", "a quick"}, + {"second", "brown"}, + {"third", "fox"}, + {"fourth", "jumps"}, + {"fifth", "over"}, + {"sixth", "the lazy"}, + {"seventh", "dog"} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new methexitreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + MethodExitRequest mentrRequest[] = new MethodExitRequest[MEXIT_NUM]; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "methexitreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + for (int i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.methodExitRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled method exit requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class methexitreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new methexitreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.methodExitRequests.methexitreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + MethodExitRequest request = null; + MethodExitRequest meRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating MethodExitRequests"); + for (int i1 = 0; i1 < meRequests.length; i1++) { + meRequests[i1] = eventRManager.createMethodExitRequest(); + meRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new MethodExitRequest"); + requests = eventRManager.methodExitRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (MethodExitRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created MethodExitRequest"); + meRequests[i1].enable(); + requests = eventRManager.methodExitRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (MethodExitRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting MethodExitRequests"); + for (int i2 = meRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(meRequests[i2]); + requests = eventRManager.methodExitRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + log2("breakpointForCommunication"); + + do { + getEventSet(); + + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) + return; + + log2(" received: " + event); + + if (EventFilters.filtered(event)) { + eventSet.resume(); + } + else { + break; + } + } while (true); + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002/TestDescription.java new file mode 100644 index 00000000000..fde5f6dc7dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.methodExitRequests() + * complies with its spec: + * public List methodExitRequests() + * Return an unmodifiable list of the enabled and disabled method exit requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all MethodExitRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled method exit requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.methodExitRequests.methexitreq002; + * the debuggee program - nsk.jdi.EventRequestManager.methodExitRequests.methexitreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.methodExitRequests.methexitreq002 + * nsk.jdi.EventRequestManager.methodExitRequests.methexitreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.methodExitRequests.methexitreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002a.java new file mode 100644 index 00000000000..4c1b902c477 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.methodExitRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the methexitreq002 JDI test. + */ + +public class methexitreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq001.java new file mode 100644 index 00000000000..0fe9d65972e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq001.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.modificationWatchpointRequests; + +import com.sun.jdi.Field; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.request.ModificationWatchpointRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.event.*; + +import java.util.Iterator; +import java.util.List; + +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.modificationWatchpointRequests() + * properly returns all ModificationWatchpointRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class modwtchpreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.modificationWatchpointRequests.modwtchpreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int FLDS_NUM = 16; + static final String DEBUGGEE_FLDS[][] = { + {"byte", "byteFld", "B"}, + {"short", "shortFld", "S"}, + {"int", "intFld", "I"}, + {"long", "longFld", "J"}, + {"float", "floatFld", "F"}, + {"double", "doubleFld", "D"}, + {"char", "charFld", "C"}, + {"boolean", "booleanFld", "Z"}, + {"java.lang.String", "strFld", "Ljava/lang/String;"}, + {"short", "sFld", "S"}, + {"byte", "prFld", "B"}, + {"float", "pubFld", "F"}, + {"double", "protFld", "D"}, + {"int", "tFld", "I"}, + {"long", "vFld", "J"}, + {"char", "fFld", "C"} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new modwtchpreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + List fields; + ModificationWatchpointRequest mwpRequest[] = + new ModificationWatchpointRequest[FLDS_NUM]; + String cmd; + int i = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "modwtchpreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + if ( !vm.canWatchFieldModification() ) { + log.display(" TEST CANCELLED due to: vm.canWatchFieldModification() == false"); + return quitDebuggee(); + } + + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null"); + tot_res = FAILED; + return quitDebuggee(); + } + + try { + fields = rType.allFields(); + } catch (Exception e) { + log.complain("TEST FAILURE: allFields: " + e); + tot_res = FAILED; + return quitDebuggee(); + } + Iterator iter = fields.iterator(); + while (iter.hasNext()) { + Field fld = (Field) iter.next(); + log.display("\nCreating ModificationWatchpointRequest for the field:\n\t" + + fld.typeName() + " " + fld.name() + + " type_signature=" + fld.signature()); + try { + mwpRequest[i++] = erManager.createModificationWatchpointRequest(fld); + } catch (Exception e) { + log.complain("TEST FAILURE: createModificationWatchpointRequest: " + e); + tot_res = FAILED; + return quitDebuggee(); + } + } + elThread = new EventListener(); + elThread.start(); + +// Check ModificationWatchpoint requests when event requests are disabled + log.display("\n1) Getting ModificationWatchpointRequest objects with disabled event requests..."); + checkRequests(erManager, 1); + +// Check ModificationWatchpoint requests when event requests are enabled + for (i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.modificationWatchpointRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled access watchpoint requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checks up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class modwtchpreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new modwtchpreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.modificationWatchpointRequests.modwtchpreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldAccess() ) { + log2("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + String fieldName = "testField"; + + Field field = null; + + List requests = null; + ListIterator li = null; + + ModificationWatchpointRequest request = null; + ModificationWatchpointRequest awRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + field = debuggeeClass.fieldByName(fieldName); + + log2("......creating ModificationWatchpointRequests"); + for (int i1 = 0; i1 < awRequests.length; i1++) { + awRequests[i1] = eventRManager.createModificationWatchpointRequest(field); + awRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new ModificationWatchpointRequest"); + requests = eventRManager.modificationWatchpointRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (ModificationWatchpointRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created ModificationWatchpointRequest"); + awRequests[i1].enable(); + requests = eventRManager.modificationWatchpointRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (ModificationWatchpointRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting ModificationWatchpointRequests"); + for (int i2 = awRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(awRequests[i2]); + requests = eventRManager.modificationWatchpointRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002/TestDescription.java new file mode 100644 index 00000000000..b0039c4a072 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.modificationWatchpointRequests() + * complies with its spec: + * public List modificationWatchpointRequests() + * Return an unmodifiable list of the enabled and disabled modificaton watchpoint + * requests. This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all ModificationWatchpointRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled modification watchpoint requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.modificationWatchpointRequests.modwtchpreq002; + * the debuggee program - nsk.jdi.EventRequestManager.modificationWatchpointRequests.modwtchpreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.modificationWatchpointRequests.modwtchpreq002 + * nsk.jdi.EventRequestManager.modificationWatchpointRequests.modwtchpreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.modificationWatchpointRequests.modwtchpreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002a.java new file mode 100644 index 00000000000..833f2a61eed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.modificationWatchpointRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the modwtchpreq002 JDI test. + */ + +public class modwtchpreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq001.java new file mode 100644 index 00000000000..d7993362074 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq001.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.stepRequests; + +import com.sun.jdi.ThreadReference; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.StepRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.DuplicateRequestException; +import com.sun.jdi.ObjectCollectedException; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.VMMismatchException; +import com.sun.jdi.event.*; + +import java.util.Iterator; +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.stepRequests() + * properly returns all StepRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled
    + * A debuggee part of the test creates several dummy user and daemon + * threads with own names.
    + * EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class stepreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.stepRequests.stepreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int THRDS_NUM = 8; + static final String DEBUGGEE_THRDS[] = { + "main_thr", "thr1", "thr2", "thr3", + "thr4", "thr5", "thr6", "thr7" + }; + static final boolean DAEMON_THRDS[] = { + false, true, false, true, + true, false, true, false + }; + static final int RESTRICTIONS[][] = { + {StepRequest.STEP_MIN, StepRequest.STEP_INTO}, + {StepRequest.STEP_LINE, StepRequest.STEP_OVER}, + {StepRequest.STEP_MIN, StepRequest.STEP_OUT}, + {StepRequest.STEP_LINE, StepRequest.STEP_INTO}, + {StepRequest.STEP_LINE, StepRequest.STEP_INTO}, + {StepRequest.STEP_MIN, StepRequest.STEP_OUT}, + {StepRequest.STEP_LINE, StepRequest.STEP_INTO}, + {StepRequest.STEP_MIN, StepRequest.STEP_OUT} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new stepreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ThreadReference thR; + List threads; + StepRequest sRequest[] = new StepRequest[THRDS_NUM]; + String cmd; + int i = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "stepreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + try { + threads = vm.allThreads(); + } catch (Exception e) { + log.complain("TEST FAILURE: allThreads: " + e); + tot_res = FAILED; + return quitDebuggee(); + } + + Iterator iter = threads.iterator(); + while (iter.hasNext()) { + thR = (ThreadReference) iter.next(); + for (int j=0; j + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.stepRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled step requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class stepreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/stepRequests/stepreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new stepreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.stepRequests.stepreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + String fieldName = "testField"; + + List requests = null; + ListIterator li = null; + + StepRequest request = null; + StepRequest stRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ArrayReference threads = (ArrayReference) + debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); + + + log2("......creating StepRequests"); + for (int i1 = 0; i1 < stRequests.length; i1++) { + stRequests[i1] = eventRManager.createStepRequest( (ThreadReference) threads.getValue(i1), + StepRequest.STEP_MIN, StepRequest.STEP_OUT); + stRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new StepRequest"); + requests = eventRManager.stepRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (StepRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created StepRequest"); + stRequests[i1].enable(); + requests = eventRManager.stepRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (StepRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting StepRequests"); + for (int i2 = stRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(stRequests[i2]); + requests = eventRManager.stepRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002/TestDescription.java new file mode 100644 index 00000000000..0d4ad10738f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/stepRequests/stepreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.stepRequests() + * complies with its spec: + * public List stepRequests() + * Return an unmodifiable list of the enabled and disabled step requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all StepRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled step requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.stepRequests.stepreq002; + * the debuggee program - nsk.jdi.EventRequestManager.stepRequests.stepreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.stepRequests.stepreq002 + * nsk.jdi.EventRequestManager.stepRequests.stepreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.stepRequests.stepreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002a.java new file mode 100644 index 00000000000..d0ade995f6f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002a.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.stepRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the stepreq002 JDI test. + */ + +public class stepreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1stepreq002a testField[] = new Thread1stepreq002a[10]; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + synchronized (lockObj1) { + for (int ii = 0; ii < 10; ii++) { + testField[ii] = new Thread1stepreq002a("thread" + ii); + threadStart(testField[ii]); + } + methodForCommunication(); + } + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj1 = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + +} + +class Thread1stepreq002a extends Thread { + + String tName = null; + + public Thread1stepreq002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + stepreq002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(stepreq002a.waitnotifyObj) { + stepreq002a.waitnotifyObj.notify(); + } + synchronized(stepreq002a.lockObj1) { + stepreq002a.log1(" 'run': exit :: threadName == " + tName); + } + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq001.java new file mode 100644 index 00000000000..7b0c0095b03 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq001.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.threadDeathRequests; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.request.ThreadDeathRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.event.*; + +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.threadDeathRequests() + * properly returns all ThreadDeathRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled.
    + * ThreadDeathRequest objects are distinguished by the different + * EventRequest's properties.
    + * JDI EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class thrdeathreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.threadDeathRequests.thrdeathreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int THR_NUM = 7; + static final String PROPS[][] = { + {"first", "a quick"}, + {"second", "brown"}, + {"third", "fox"}, + {"fourth", "jumps"}, + {"fifth", "over"}, + {"sixth", "the lazy"}, + {"seventh", "dog"} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new thrdeathreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ThreadDeathRequest thrdeathRequest[] = + new ThreadDeathRequest[THR_NUM]; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "thrdeathreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + for (int i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.threadDeathRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled thread death requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class thrdeathreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new thrdeathreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.threadDeathRequests.thrdeathreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + ThreadDeathRequest request = null; + ThreadDeathRequest tdRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating ThreadDeathRequests"); + for (int i1 = 0; i1 < tdRequests.length; i1++) { + tdRequests[i1] = eventRManager.createThreadDeathRequest(); + tdRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new ThreadDeathRequest"); + requests = eventRManager.threadDeathRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (ThreadDeathRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created ThreadDeathRequest"); + tdRequests[i1].enable(); + requests = eventRManager.threadDeathRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (ThreadDeathRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting ThreadDeathRequests"); + for (int i2 = tdRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(tdRequests[i2]); + requests = eventRManager.threadDeathRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002/TestDescription.java new file mode 100644 index 00000000000..708b07cfe0d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.threadDeathRequests() + * complies with its spec: + * public List threadDeathRequests() + * Return an unmodifiable list of the enabled and disabled thread death requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all ThreadDeathRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled thread death requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.threadDeathRequests.thrdeathreq002; + * the debuggee program - nsk.jdi.EventRequestManager.threadDeathRequests.thrdeathreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.threadDeathRequests.thrdeathreq002 + * nsk.jdi.EventRequestManager.threadDeathRequests.thrdeathreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.threadDeathRequests.thrdeathreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002a.java new file mode 100644 index 00000000000..c6cb2d0455a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.threadDeathRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the thrdeathreq002 JDI test. + */ + +public class thrdeathreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq001.java new file mode 100644 index 00000000000..c76b805bea9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq001.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.threadStartRequests; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.request.ThreadStartRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.event.*; + +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.request.EventRequestManager.threadStartRequests() + * properly returns all ThreadStartRequest objects when: + *
  • event requests are disabled + *
  • event requests are enabled.
    + * ThreadStartRequest objects are distinguished by the different + * EventRequest's properties.
    + * JDI EventHandler was added as workaround for the bug 4430096. + * This prevents the target VM from potential hangup. + */ +public class thrstartreq001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.EventRequestManager.threadStartRequests.thrstartreq001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int THR_NUM = 7; + static final String PROPS[][] = { + {"first", "a quick"}, + {"second", "brown"}, + {"third", "fox"}, + {"fourth", "jumps"}, + {"fifth", "over"}, + {"sixth", "the lazy"}, + {"seventh", "dog"} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private EventListener elThread; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new thrstartreq001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ThreadStartRequest thrstartRequest[] = new ThreadStartRequest[THR_NUM]; + String cmd; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "thrstartreq001t.err> "); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + + for (int i=0; i + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.threadStartRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled thread start requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class thrstartreq002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new thrstartreq002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.threadStartRequests.thrstartreq002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + ThreadStartRequest request = null; + ThreadStartRequest tsRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating ThreadStartRequests"); + for (int i1 = 0; i1 < tsRequests.length; i1++) { + tsRequests[i1] = eventRManager.createThreadStartRequest(); + tsRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new ThreadStartRequest"); + requests = eventRManager.threadStartRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (ThreadStartRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created ThreadStartRequest"); + tsRequests[i1].enable(); + requests = eventRManager.threadStartRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (ThreadStartRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting ThreadStartRequests"); + for (int i2 = tsRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(tsRequests[i2]); + requests = eventRManager.threadStartRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002/TestDescription.java new file mode 100644 index 00000000000..48631305820 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.threadStartRequests() + * complies with its spec: + * public List threadStartRequests() + * Return an unmodifiable list of the enabled and disabled thread start requests. + * This list is a live view of these requests and thus changes + * as requests are added and deleted. + * Returns: the all ThreadStartRequest objects. + * The test checks up on the following assertions: + * - The list is unmodifiable. + * - The list of the enabled and disabled thread start requests. + * - This list is changes as requests are added and deleted. + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.threadStartRequests.thrstartreq002; + * the debuggee program - nsk.jdi.EventRequestManager.threadStartRequests.thrstartreq002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.threadStartRequests.thrstartreq002 + * nsk.jdi.EventRequestManager.threadStartRequests.thrstartreq002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.threadStartRequests.thrstartreq002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002a.java new file mode 100644 index 00000000000..13a115c53fd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.threadStartRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the thrstartreq002 JDI test. + */ + +public class thrstartreq002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //static int testField = 0; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java new file mode 100644 index 00000000000..b6fce04d6ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.vmDeathRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventRequestManager.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventRequestManager.vmDeathRequests()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * - The list is unmodifiable.
    + * - The list of the enabled and disabled VM death requests.
    + * - This list is changes as requests are added and deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger checking up on assertions.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class vmdeathreq001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new vmdeathreq001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventRequestManager.vmDeathRequests.vmdeathreq001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + List requests = null; + ListIterator li = null; + + VMDeathRequest request = null; + VMDeathRequest vmRequests[] = { null, null, null, null, null, + null, null, null, null, null }; + int listSize; + int flag; + + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......creating VMDeathRequests"); + for (int i1 = 0; i1 < vmRequests.length; i1++) { + vmRequests[i1] = eventRManager.createVMDeathRequest(); + vmRequests[i1].putProperty("number", String.valueOf(i1)); + + log2("......checking up on returned List after creating new VMDeathRequest"); + requests = eventRManager.vmDeathRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + flag = 0; + li = requests.listIterator(); + while (li.hasNext()) { + request = (VMDeathRequest) li.next(); + if ( !request.isEnabled() ) { + flag++; + if (flag > 1) { + testExitCode = FAILED; + log3("ERROR: # of disabled requests > 1 : " + flag); + } + if ( !request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, disabled is request expected to be enabled : # == " + i1); + } + } else { + if ( request.getProperty("number").equals(String.valueOf(i1)) ) { + testExitCode = FAILED; + log3("ERROR: in the List, enabled is newly created disabled request : # == " + i1); + } + } + } + + log2(" enabling created VMDeathRequest"); + vmRequests[i1].enable(); + requests = eventRManager.vmDeathRequests(); + listSize = requests.size(); + if ( listSize != (i1 + 1) ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + (i1 + 1)); + } + + li = requests.listIterator(); + while (li.hasNext()) { + request = (VMDeathRequest) li.next(); + if ( !request.isEnabled() ) { + testExitCode = FAILED; + log3("ERROR: returned List contains disabled request : " + request); + } + } + + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i1); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + log2("......deleting VMDeathRequests"); + for (int i2 = vmRequests.length -1; i2 >= 0; i2--) { + eventRManager.deleteEventRequest(vmRequests[i2]); + requests = eventRManager.vmDeathRequests(); + listSize = requests.size(); + if ( listSize != i2 ) { + testExitCode = FAILED; + log3("ERROR: size of returned List is not equal to expected : " + listSize + " != " + i2); + } + log2(" removing item from the List; UnsupportedOperationException is expected"); + try { + requests.remove(i2); + testExitCode = FAILED; + log3("ERROR: NO exception"); + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException "); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001/TestDescription.java new file mode 100644 index 00000000000..74b16c92364 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventRequestManager. + * The test checks up that a result of the method + * com.sun.jdi.EventRequestManager.vmDeathRequests() + * complies with its spec: + * The test works as follows: + * The debugger program - nsk.jdi.EventRequestManager.vmDeathRequests.vmdeathreq001; + * the debuggee program - nsk.jdi.EventRequestManager.vmDeathRequests.vmdeathreq001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventRequestManager.vmDeathRequests.vmdeathreq001 + * nsk.jdi.EventRequestManager.vmDeathRequests.vmdeathreq001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventRequestManager.vmDeathRequests.vmdeathreq001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001a.java new file mode 100644 index 00000000000..7095403ef4b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventRequestManager.vmDeathRequests; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the vmdeathreq001 JDI test. + */ + +public class vmdeathreq001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java new file mode 100644 index 00000000000..a336bf093b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.eventIterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.eventIterator()
    + * complies with its spec.
    + *
    + * The test checks that for ClassPrepareEvent set
    + * - the method returns a non-null object, and
    + * - object's class is the subclass of class Iterator.
    + *
    + * The test works as follows.
    + *
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent,
    + * the debugger sets up two requests, both with SUSPEND_EVENT_THREAD,
    + * one for debuggee's ClassPrepareEvent,
    + * another one for a special TestClass, resumes the VM,
    + * and waits for the events within the predefined time interval.
    + * If no the events received, the test is FAILED.
    + * Upon getting the debuggeeClass's ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + * Upon getting TestClass's ClassPrepareEvent,
    + * the debugger performs the check.
    + *
    + * At the end the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both ends.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + */ + +public class eventiterator001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/eventIterator/eventiterator001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new eventiterator001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.eventIterator.eventiterator001a"; + + private String testedClassName = + "nsk.jdi.EventSet.eventIterator.eventiterator001aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.putProperty("number", "debuggeeClass"); + cpRequest.enable(); + + ClassPrepareRequest tcRequest = settingClassPrepareRequest(testedClassName, + EventRequest.SUSPEND_EVENT_THREAD, + "TestClassPrepareRequest"); + tcRequest.enable(); + + int nn1 = 0; + int nn2 = 0; + for (int nn = 0; nn < 2; nn++) { + + vm.resume(); + getEventSet(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + + log2("String property = (String) event.request().getProperty('number');"); + String property = (String) event.request().getProperty("number"); + + if (property.equals("debuggeeClass")) { + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + nn1++; + if (nn1 > 1) + throw new JDITestRuntimeException("** 2-nd event for debuggeeClass **"); + + cpRequest.disable(); + debuggeeClass = event.referenceType(); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + } else if (property.equals("TestClassPrepareRequest")) { + nn2++; + if (nn2 > 1) + throw new JDITestRuntimeException("** 2-nd event for TestClass **"); + + if (eventIterator == null) { + testExitCode = FAILED; + log3("ERROR: eventIterator == null"); + } + if ( !(eventIterator instanceof Iterator) ) { + testExitCode = FAILED; + log3("ERROR: eventIterator is NOT instanceof Iterator"); + } + } else { + log3("ERROR: unexpected Event : property == " + property); + throw new JDITestRuntimeException("** UNEXPECTED Event **"); + } + } + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction != 0) { + throw new JDITestRuntimeException("** instruction != 0 **"); + } + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ClassPrepareRequest settingClassPrepareRequest ( String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ClassPrepareRequest:"); + log2(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.addClassFilter(testedClass); + cpr.setSuspendPolicy(suspendPolicy); + + log2(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingClassPrepareRequest() : " + e); + log3(" ClassPreparenRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ClassPrepareRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001/TestDescription.java new file mode 100644 index 00000000000..c86c1fc924a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/eventIterator/eventiterator001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.eventIterator() + * complies with its spec: + * public EventIterator eventIterator() + * Return an iterator specific to Event objects. + * The test checks that for ClassPrepareEvent set + * - the method returns a non-null object, and + * - object's class is the subclass of class Iterator. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.eventIterator.eventiterator001; + * the debuggee program - nsk.jdi.EventSet.eventIterator.eventiterator001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.eventIterator.eventiterator001 + * nsk.jdi.EventSet.eventIterator.eventiterator001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.eventIterator.eventiterator001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001a.java new file mode 100644 index 00000000000..eb54181d51d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.eventIterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the eventiterator001 JDI test. + */ + +public class eventiterator001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + eventiterator001aTestClass tcObject = new eventiterator001aTestClass(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} + +class eventiterator001aTestClass { + static int var1 = 0; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java new file mode 100644 index 00000000000..1a4c36be045 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java @@ -0,0 +1,710 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.eventIterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.eventIterator()
    + * complies with its spec.
    + *
    + * The test checks that for each type of the following Events:
    + * AccessWatchpoint, ModificationWatchpoint, Breakpoint,
    + * Exception, MethodEntry, MethodExit, and Step,
    + * - the method returns non-null object, and
    + * - object's class is subclass of class Iterator.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase the debugger and debuggee perform the following loop.
    + * - The debugger creates new Request, resumes the debuggee, and
    + * waits for corresponding Event.
    + * - The debuggee performes an action resulting in Event required.
    + * - Upon getting the Event, the debugger checks up on EventSet.
    + *
    + * In third phase, at the end
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + */ + +public class eventiterator002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/eventIterator/eventiterator002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new eventiterator002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.eventIterator.eventiterator002a"; + + private String testedClassName = + "nsk.jdi.EventSet.eventIterator.eventiterator002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + String accWatchpointName = "var1"; + String modWatchpointName = "var2"; + String bpLineName = "breakpointLine"; + String bpMethodName = "method"; + String awFieldName = "awFieldName"; + String mwFieldName = "mwFieldName"; + String excName = "method"; + String menName = "method"; + String mexName = "method"; + + EventRequest eRequest = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......ReferenceType testClass = (ReferenceType) (vm.classesByName(testedClassName)).get(0);"); + ReferenceType testClass = (ReferenceType) (vm.classesByName(testedClassName)).get(0); + + switch (i) { + + case 0: + eRequest = null; + if (vm.canWatchFieldAccess()) { + String awName = ( (StringReference) testClass.getValue( + testClass.fieldByName(awFieldName))).value(); + eRequest = settingAccessWatchpointRequest(mainThread, + testClass, awName, "AccessWatchpointRequest"); + eRequest.enable(); + } + break; + + case 1: + eRequest = null; + if (vm.canWatchFieldModification() ) { + String mwName = ( (StringReference) testClass.getValue( + testClass.fieldByName(mwFieldName))).value(); + eRequest = settingModificationWatchpointRequest(mainThread, + testClass, mwName, "ModificationWatchpointRequest"); + eRequest.enable(); + } + break; + + case 2: + eRequest = settingBreakpointRequest(mainThread, testClass, + bpMethodName, bpLineName, + EventRequest.SUSPEND_EVENT_THREAD, "BreakpointRequest"); + eRequest.enable(); + break; + + case 3: + eRequest = settingExceptionRequest(mainThread, testClass, + "ExceptionRequest"); + eRequest.enable(); + break; + + case 4: + eRequest = settingMethodEntryRequest(mainThread, testClass, + "MethodEntryRequest"); + eRequest.enable(); + break; + + case 5: + eRequest = settingMethodExitRequest(mainThread, testClass, + "MethodExitRequest"); + eRequest.enable(); + break; + + case 6: + eRequest = settingStepRequest(mainThread, "StepRequest"); + eRequest.enable(); + break; + } + + // see setting up Acceess&Modification requests above + if (eRequest == null) + continue; + + log2("......getting new Event and checking up on EventIterator"); + vm.resume(); + getEventSet(); + eRequest.disable(); + + if (eventIterator == null) { + testExitCode = FAILED; + log3("ERROR: eventIterator == null"); + } + if ( !(eventIterator instanceof Iterator) ) { + testExitCode = FAILED; + log3("ERROR: eventIterator is NOT instanceof Iterator"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest settingAccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + awr.addThreadFilter(thread); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + + private ModificationWatchpointRequest settingModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + mwr = eventRManager.createModificationWatchpointRequest(field); + mwr.putProperty("number", property); + mwr.addThreadFilter(thread); + + log2(" ModificationWatchpointRequest has been set up"); + return mwr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + + private BreakpointRequest settingBreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + log2(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingBreakpointRequest() : " + e); + log3(" BreakpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up BreakpointRequest **"); + } + } + + private MethodEntryRequest settingMethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + + private MethodExitRequest settingMethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + mexr = eventRManager.createMethodExitRequest(); + mexr.putProperty("number", property); + mexr.addThreadFilter(thread); + mexr.addClassFilter(testedClass); + + log2(" MethodExitRequest has been set up"); + return mexr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + + private StepRequest settingStepRequest ( ThreadReference thread, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); + str.putProperty("number", property); + str.addCountFilter(1); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + + private ExceptionRequest settingExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002/TestDescription.java new file mode 100644 index 00000000000..f314b65fd2c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/eventIterator/eventiterator002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.eventIterator() + * complies with its spec: + * public EventIterator eventIterator() + * Return an iterator specific to Event objects. + * The test checks that for each type of the following Events: + * AccessWatchpoint, ModificationWatchpoint, Breakpoint, + * Exception, MethodEntry, MethodExit, and Step, + * - the method returns non-null object, and + * - object's class is subclass of class Iterator. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.eventIterator.eventiterator002; + * the debuggee program - nsk.jdi.EventSet.eventIterator.eventiterator002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.eventIterator.eventiterator002 + * nsk.jdi.EventSet.eventIterator.eventiterator002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.eventIterator.eventiterator002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002a.java new file mode 100644 index 00000000000..e1879b5b621 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002a.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.eventIterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the eventiterator002 JDI test. + */ + +public class eventiterator002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static eventiterator002aTestClass tcObject = new eventiterator002aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); // TestClass is already prepared + + eventiterator002aTestClass.method(); + methodForCommunication(); + break; + + case 1: + eventiterator002aTestClass.method(); + methodForCommunication(); + break; + + case 2: + eventiterator002aTestClass.method(); + methodForCommunication(); + break; + + case 3: + eventiterator002aTestClass.method(); + methodForCommunication(); + break; + + case 4: + eventiterator002aTestClass.method(); + methodForCommunication(); + break; + + case 5: + eventiterator002aTestClass.method(); + methodForCommunication(); + break; + + case 6: + eventiterator002aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits!"); + System.exit(exitCode + PASS_BASE); + } +} + +class eventiterator002aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void nullMethod() { + throw new NullPointerException("++ nullMethod ++"); + } + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + nullMethod(); + } catch ( NullPointerException e ) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java new file mode 100644 index 00000000000..7dd013c5bb1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.eventIterator; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.eventIterator()
    + * complies with its spec.
    + *
    + * The test checks that for ThreadStartEvent and
    + * ThreadDeathEvent sets:
    + * - the method returns non-null object;
    + * - object's class is subclass of class Iterator.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase the debugger and the debuggee perform the following.
    + * - The debugger creates ThreadStartRequest,resumes the debuggee, and
    + * waits for corresponding ThreadStartEvent.
    + * - The debuggee starts new thread, named "thread2",
    + * whose running creates the needed events.
    + * - Upon getting the ThreadStartEvent, the debugger checks up on it,
    + * creates ThreadDeathRequest, resumes the debuggee, and
    + * waits for corresponding ThreadDeathEvent.
    + * Upon getting the ThreadDeathEvent, the debugger checks up on it.
    + *
    + * In third phase, the debugger and the debuggee end.
    + *
    + */ + +public class eventiterator003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + + static final int FAILED = 2; + + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String sHeader1 = "\n==> nsk/jdi/EventSet/eventIterator/eventiterator003 ", + sHeader2 = "--> debugger: ", sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main(String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = new eventiterator003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = "nsk.jdi.EventSet.eventIterator.eventiterator003a"; + + private String testedClassName = "nsk.jdi.EventSet.eventIterator.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static EventRequestManager eventRManager = null; + + static EventQueue eventQueue = null; + + static EventSet eventSet = null; + + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis(String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch (Exception e) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0: + log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + status + " == PASS_BASE"); + } + break; + + default: + log3("ERROR: runTest() returned unexpected value"); + + case 1: + log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch (Exception e) { + log3("ERROR: Exception : e"); + } + break; + + case 2: + log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch (Exception e) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + + if (!(eventIterator.nextEvent() instanceof VMDeathEvent)) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + + if (!(eventIterator.nextEvent() instanceof VMDisconnectEvent)) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch (VMDisconnectedException e) { + log3("ERROR: VMDisconnectedException : " + e); + e.printStackTrace(logHandler.getOutStream()); + return 2; + } catch (Exception e) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + String thread2Name = "thread2"; + + EventRequest eRequest = null; + + label0: { + + vm.resume(); + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ThreadReference tr = (ThreadReference) debuggeeClass.getValue(debuggeeClass.fieldByName(thread2Name)); + + log2("......setting up ThreadStartRequest"); + eRequest = settingThreadStartRequest(tr, EventRequest.SUSPEND_EVENT_THREAD, "ThreadStartRequest"); + eRequest.enable(); + vm.resume(); + log2("......getting EventSet"); + getEventSet(); + eRequest.disable(); + + String str = (String) eventIterator.nextEvent().request().getProperty("number"); + if (!str.equals("ThreadStartRequest")) { + testExitCode = FAILED; + log3("ERROR: new event doesn't corresponds to ThreadStartRequest required"); + break label0; + } + + log2("......checking up on EventIterator"); + if (eventIterator == null) { + testExitCode = FAILED; + log3("ERROR: eventIterator == null"); + } + if (!(eventIterator instanceof Iterator)) { + testExitCode = FAILED; + log3("ERROR: eventIterator is NOT instanceof Iterator"); + } + + log2("......setting up ThreadDeathRequest"); + // suspend policy 'SUSPEND_ALL' should be used for ThreadDeathRequest (see 6609499) + eRequest = settingThreadDeathRequest(tr, EventRequest.SUSPEND_ALL, "ThreadDeathRequest"); + eRequest.enable(); + eventSet.resume(); + log2("......getting EventSet"); + getEventSet(); + eRequest.disable(); + + str = (String) eventIterator.nextEvent().request().getProperty("number"); + if (!str.equals("ThreadDeathRequest")) { + testExitCode = FAILED; + log3("ERROR: new event doesn't corresponds to ThreadDeathRequest required"); + break label0; + } + + log2("......checking up on EventIterator"); + if (eventIterator == null) { + testExitCode = FAILED; + log3("ERROR: eventIterator == null"); + } + if (!(eventIterator instanceof Iterator)) { + testExitCode = FAILED; + log3("ERROR: eventIterator is NOT instanceof Iterator"); + } + + eventSet.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext();) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint(ThreadReference thread, ReferenceType testedClass, String methodName, + String bpLine, String property) throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = ((IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine))).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + } catch (Exception e1) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch (Exception e2) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + private void getEventSet() throws JDITestRuntimeException { + try { + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + private void breakpointForCommunication() throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ThreadStartRequest settingThreadStartRequest(ThreadReference thread, int suspendPolicy, String property) + throws JDITestRuntimeException { + try { + ThreadStartRequest tsr = eventRManager.createThreadStartRequest(); + tsr.addThreadFilter(thread); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch (Exception e) { + log3("ERROR: ATTENTION: Exception within settingThreadStartRequest() : " + e); + log3(" ThreadStartRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ThreadStartRequest **"); + } + } + + private ThreadDeathRequest settingThreadDeathRequest(ThreadReference thread, int suspendPolicy, String property) + throws JDITestRuntimeException { + try { + ThreadDeathRequest tdr = eventRManager.createThreadDeathRequest(); + tdr.addThreadFilter(thread); + tdr.addCountFilter(1); + tdr.setSuspendPolicy(suspendPolicy); + tdr.putProperty("number", property); + return tdr; + } catch (Exception e) { + log3("ERROR: ATTENTION: Exception within settingThreadDeathRequest() : " + e); + log3(" ThreadDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ThreadDeathRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003/TestDescription.java new file mode 100644 index 00000000000..36747b69c1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/eventIterator/eventiterator003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.eventIterator() + * complies with its spec: + * public EventIterator eventIterator() + * Return an iterator specific to Event objects. + * The test checks that for ThreadStartEvent and ThreadDeathEvent sets: + * - the method returns non-null object, and + * - object's class is subclass of class Iterator. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.eventIterator.eventiterator003; + * the debuggee program - nsk.jdi.EventSet.eventIterator.eventiterator003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.eventIterator.eventiterator003 + * nsk.jdi.EventSet.eventIterator.eventiterator003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.eventIterator.eventiterator003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003a.java new file mode 100644 index 00000000000..5dbdfb5e23c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003a.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.eventIterator; + +import nsk.share.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the eventiterator003 JDI test. + */ + +public class eventiterator003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + + static final int FAILED = 2; + + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + + static int end = 0; + + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + + //---------------------------------------------------- main method + + public static void main(String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + thread2 = new Thread2eventiterator003a("thread2"); + methodForCommunication(); + + threadStart(thread2); + try { + thread2.join(); + } catch (InterruptedException e) { + } + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch (Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e); + return FAILED; + } + } + return PASSED; + } + + static class Thread2eventiterator003a extends Thread { + + public Thread2eventiterator003a(String threadName) { + super(threadName); + } + + public void run() { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java new file mode 100644 index 00000000000..ac9476da7c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.eventIterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.eventIterator()
    + * complies with its spec.
    + *
    + * The test checks that for VMStart, VMDeath, and
    + * VMDisconnect Events:
    + * - the method returns non-null object, and
    + * - object's class is subclass of class Iterator.
    + *
    + * The test works as follows.
    + *
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it checks up on the method and
    + * sets up the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + *
    + * The debugger then resumes the debuggee which will normally end
    + * that will result in VMDeathEvent and waits for the event.
    + * Upon getting the VMDeathEvent, it checks up on the method and
    + * waits for VMDisconnectEvent, and upon getting it, checks up on this.
    + *
    + */ + +public class eventiterator004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/eventIterator/eventiterator004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new eventiterator004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.eventIterator.eventiterator004a"; + + private String testedClassName = + "nsk.jdi.EventSet.eventIterator.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + // Event #: + // 0-6 : AccessWatchpoint, ModificationWatchpoint, Breakpoint, Exception, + // MethodEntry, MethodExit, Step + // 7-8 : ClassPrepare, ClassUnload + // 9-10 : ThreadDeath, ThreadStart + // 11-13 : VMDeath, VMDisconnect, VMStart + + EventSet eventSets[] = new EventSet [14]; + EventRequest eRequests[] = new EventRequest[14]; + + int eventFlags[] = { 0,0,0,0, 0,0,0,0, 3,0,0,0, 1,1 }; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugeeNoWait(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugeeNoWait(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + log2("waiting for VMStartEvent"); + getEventSet(); + check(); + + + if (eventIterator.nextEvent() instanceof VMStartEvent) { + log2("VMStartEvent received; test begins"); + + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + check(); + + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + check(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + } else { + log3("ERROR: first event is not the VMStartEvent"); + return 1; + } + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + log2("......setting up ClassPrepareRequest"); + eRequests[7] = cpRequest; + + cpRequest.enable(); + vm.resume(); + + getEventSet(); + eventSets[7] = eventSet; + + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private void check() { + + log2("......checking up on EventIterator"); + if (eventIterator == null) { + testExitCode = FAILED; + log3("ERROR: eventIterator == null"); + } + if ( !(eventIterator instanceof Iterator) ) { + testExitCode = FAILED; + log3("ERROR: eventIterator is NOT instanceof Iterator"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004/TestDescription.java new file mode 100644 index 00000000000..ed73879b4ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/eventIterator/eventiterator004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.eventIterator() + * complies with its spec: + * public EventIterator eventIterator() + * Return an iterator specific to Event objects. + * The test checks that for VMStart, VMDeath, and VMDisconnect Events: + * - the method returns non-null object, and + * - object's class is subclass of class Iterator. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.eventIterator.eventiterator004; + * the debuggee program - nsk.jdi.EventSet.eventIterator.eventiterator004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - binder.bindToDebugeeNoWait() is used to prevent Binder from + * handling VMStartEvent + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.eventIterator.eventiterator004 + * nsk.jdi.EventSet.eventIterator.eventiterator004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.eventIterator.eventiterator004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004a.java new file mode 100644 index 00000000000..e6646966593 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004a.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.eventIterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the eventiterator004 JDI test. + */ + +public class eventiterator004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001.java new file mode 100644 index 00000000000..45cad0aaef4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import static nsk.share.Consts.TEST_FAILED; + +/** + * The test for the implementation of an object of the type + * EventSet. + * + * The test checks that results of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec. + * + * Test cases include all three possible suspensions, NONE, + * EVENT_THREAD, and ALL, for ClassPrepareEvent sets. + * + * To check up on the method, a debugger, + * upon getting new set for ClassPrepareEvent, + * suspends VM with the method VirtualMachine.suspend(), + * gets the List of geduggee's threads calling VM.allThreads(), + * invokes the method EventSet.resume(), and + * gets another List of geduggee's threads. + * The debugger then compares values of + * each thread's suspendCount from first and second Lists. + * + * The test works as follows. + * - The debugger resumes the debuggee and + * waits for the ClassPrepareEvents. + * - The debuggee creates three threads, running one by one and + * making special clases loaded and prepared to create the Events + * - Upon getting the Events, + * the debugger performs the check required. + */ + +public class resume001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.EventSet.resume.resume001a"; + return new resume001().runThis(argv, out); + } + + protected void testRun() { + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + String classNames[] = { + "nsk.jdi.EventSet.resume.TestClass2", + "nsk.jdi.EventSet.resume.TestClass3", + "nsk.jdi.EventSet.resume.TestClass4", + }; + + EventRequest eventRequest; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + eventRequest = settingClassPrepareRequest(classNames[0], + SUSPEND_NONE, "ClassPrepareRequest0"); + break; + + case 1: + eventRequest = settingClassPrepareRequest(classNames[1], + SUSPEND_THREAD, "ClassPrepareRequest1"); + break; + + case 2: + eventRequest = settingClassPrepareRequest(classNames[2], + SUSPEND_ALL, "ClassPrepareRequest2"); + break; + + + default: + throw new Failure("** default case 2 **"); + } + + display("......waiting for new ClassPrepareEvent : " + i); + EventSet eventSet = eventHandler.waitForRequestedEventSet(new EventRequest[]{eventRequest}, waitTime, true); + + EventIterator eventIterator = eventSet.eventIterator(); + Event newEvent = eventIterator.nextEvent(); + + if ( !(newEvent instanceof ClassPrepareEvent)) { + setFailedStatus("ERROR: new event is not ClassPreparedEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ClassPrepareEvent with propety 'number' == " + property); + + display("......checking up on EventSet.resume()"); + display("......--> vm.suspend();"); + vm.suspend(); + + display(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + display(suspendsCounts1.toString()); + + display(" eventSet.resume;"); + eventSet.resume(); + + display(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + display(suspendsCounts2.toString()); + + display(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE : + display(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + display(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + case SUSPEND_THREAD : + display(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + display("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = ((ClassPrepareEvent)newEvent).thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + case SUSPEND_ALL : + + display(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + display("checking " + threadName); + + if (!newEvent.request().equals(eventRequest)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + default: throw new Failure("** default case 1 **"); + } + } + + display("......--> vm.resume()"); + vm.resume(); + } + return; + } + + private ClassPrepareRequest settingClassPrepareRequest ( String testedClass, + int suspendPolicy, + String property ) + throws Failure { + try { + display("......setting up ClassPrepareRequest:"); + display(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.addClassFilter(testedClass); + cpr.setSuspendPolicy(suspendPolicy); + + display(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ClassPrepareRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001/TestDescription.java new file mode 100644 index 00000000000..15c2750af4b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three ClassPrepareEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume001; + * the debuggee program - nsk.jdi.EventSet.resume.resume001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume001 + * nsk.jdi.EventSet.resume.resume001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001a.java new file mode 100644 index 00000000000..da96c913ec3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume001 JDI test. + */ + +public class resume001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + TestClass2 obj2 = new TestClass2(); + break; + + case 1: + TestClass3 obj3 = new TestClass3(); + break; + + case 2: + TestClass4 obj4 = new TestClass4(); +//------------------------------------------------- standard end section + + default: + instruction = end; + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} + +class TestClass2 { + static int var1 = 0; +} + +class TestClass3 { + static int var1 = 0; +} + +class TestClass4 { + static int var1 = 0; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java new file mode 100644 index 00000000000..fe456247eca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test cases include all three possible suspensions, NONE,
    + * EVENT_THREAD, and ALL, for AccessWatchpointEvent sets.
    + *
    + * To check up on the method, a debugger,
    + * upon getting new set for the EventSet,
    + * suspends VM with the method VirtualMachine.suspend(),
    + * gets the List of geduggee's threads calling VM.allThreads(),
    + * invokes the method EventSet.resume(), and
    + * gets another List of geduggee's threads.
    + * The debugger then compares values of
    + * each thread's suspendCount from first and second Lists.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a AccessWatchpointRequest, resumes
    + * the debuggee, and waits for the AccessWatchpointEvent.
    + * - The debuggee invokes the special method which makes access to
    + * a predefined variable to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class resume002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume002a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.resume002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldAccess() ) { + log2("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "AccessWatchpointRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "AccessWatchpointRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "AccessWatchpointRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new AccessWatchpointEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + if ( !(newEvent instanceof AccessWatchpointEvent)) { + log3("ERROR: new event is not AccessWatchpointEvent"); + testExitCode = FAILED; + } else { + + String property = (String) newEvent.request().getProperty("number"); + log2(" got new AccessWatchpointEvent with propety 'number' == " + property); + + log2("......checking up on EventSet.resume()"); + log2("......--> vm.suspend();"); + vm.suspend(); + + log2(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(" eventSet.resume;"); + eventSet.resume(); + + log2(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(suspendsCounts1.toString()); + log2(suspendsCounts2.toString()); + + log2(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE : + log2(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + log2(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest1.disable(); + break; + + case SUSPEND_THREAD : + log2(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = ((AccessWatchpointEvent)newEvent).thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest2.disable(); + break; + + case SUSPEND_ALL : + + log2(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!event.request().equals(eventRequest3)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest3.disable(); + break; + + default: throw new JDITestRuntimeException("** default case 1 **"); + } + } + + log2("......--> vm.resume()"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest settingAccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002/TestDescription.java new file mode 100644 index 00000000000..08e73ba6c9a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three AccessWatchpointEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume002; + * the debuggee program - nsk.jdi.EventSet.resume.resume002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume002 + * nsk.jdi.EventSet.resume.resume002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002a.java new file mode 100644 index 00000000000..fe219b453a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002a.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume002 JDI test. + */ + +public class resume002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static resume002aTestClass tcObject = new resume002aTestClass(); + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: resume002aTestClass.method(); + break; + + case 1: resume002aTestClass.method(); + break; + + case 2: resume002aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} + +class resume002aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java new file mode 100644 index 00000000000..0b985421c6f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test cases include all three possible suspensions, NONE,
    + * EVENT_THREAD, and ALL, for ModificationWatchpointEvent sets.
    + *
    + * To check up on the method, a debugger,
    + * upon getting new set for the EventSet,
    + * suspends VM with the method VirtualMachine.suspend(),
    + * gets the List of geduggee's threads calling VM.allThreads(),
    + * invokes the method EventSet.resume(), and
    + * gets another List of geduggee's threads.
    + * The debugger then compares values of
    + * each thread's suspendCount from first and second Lists.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a ModificationWatchpointRequest, resumes
    + * the debuggee, and waits for the ModificationWatchpointEvent.
    + * - The debuggee invokes the special method which makes access to
    + * a predefined variable to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class resume003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume003a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.resume003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldModification() ) { + log2("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "ModificationWatchpointRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "ModificationWatchpointRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "ModificationWatchpointRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new ModificationWatchpointEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + if ( !(newEvent instanceof ModificationWatchpointEvent)) { + log3("ERROR: new event is not ModificationWatchpointEvent"); + testExitCode = FAILED; + } else { + + String property = (String) newEvent.request().getProperty("number"); + log2(" got new ModificationWatchpointEvent with propety 'number' == " + property); + + log2("......checking up on EventSet.resume()"); + log2("......--> vm.suspend();"); + vm.suspend(); + + log2(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(" eventSet.resume;"); + eventSet.resume(); + + log2(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(suspendsCounts1.toString()); + log2(suspendsCounts2.toString()); + + log2(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE : + log2(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + log2(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest1.disable(); + break; + + case SUSPEND_THREAD : + log2(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = ((ModificationWatchpointEvent)newEvent).thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest2.disable(); + break; + + case SUSPEND_ALL : + + log2(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!event.request().equals(eventRequest3)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest3.disable(); + break; + + default: throw new JDITestRuntimeException("** default case 1 **"); + } + } + + log2("......--> vm.resume()"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest settingModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003/TestDescription.java new file mode 100644 index 00000000000..b5b7404cedb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three ModificationWatchpointEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume003; + * the debuggee program - nsk.jdi.EventSet.resume.resume003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume003 + * nsk.jdi.EventSet.resume.resume003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003a.java new file mode 100644 index 00000000000..2bb0df34fc1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003a.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume003 JDI test. + */ + +public class resume003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static resume003aTestClass tcObject = new resume003aTestClass(); + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: resume003aTestClass.method(); + break; + + case 1: resume003aTestClass.method(); + break; + + case 2: resume003aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} + +class resume003aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java new file mode 100644 index 00000000000..3f185107ea7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test cases include all three possible suspensions, NONE,
    + * EVENT_THREAD, and ALL, for BreakpointEvent sets.
    + *
    + * To check up on the method, a debugger,
    + * upon getting new set for the EventSet,
    + * suspends VM with the method VirtualMachine.suspend(),
    + * gets the List of geduggee's threads calling VM.allThreads(),
    + * invokes the method EventSet.resume(), and
    + * gets another List of geduggee's threads.
    + * The debugger then compares values of
    + * each thread's suspendCount from first and second Lists.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a BreakpointRequest, resumes
    + * the debuggee, and waits for the BreakpointEvent.
    + * - The debuggee invokes the special method which makes access to
    + * a predefined variable to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class resume004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume004a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.resume004aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_NONE, "BreakpointRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_THREAD, "BreakpointRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_ALL, "BreakpointRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new BreakpointEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + if ( !(newEvent instanceof BreakpointEvent)) { + log3("ERROR: new event is not BreakpointEvent"); + testExitCode = FAILED; + } else { + + String property = (String) newEvent.request().getProperty("number"); + log2(" got new BreakpointEvent with propety 'number' == " + property); + + log2("......checking up on EventSet.resume()"); + log2("......--> vm.suspend();"); + vm.suspend(); + + log2(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(" eventSet.resume;"); + eventSet.resume(); + + log2(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(suspendsCounts1.toString()); + log2(suspendsCounts2.toString()); + + log2(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE : + log2(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + log2(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest1.disable(); + break; + + case SUSPEND_THREAD : + log2(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = ((BreakpointEvent)newEvent).thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest2.disable(); + break; + + case SUSPEND_ALL : + + log2(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!event.request().equals(eventRequest3)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest3.disable(); + break; + + default: throw new JDITestRuntimeException("** default case 1 **"); + } + } + + log2("......--> vm.resume()"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private BreakpointRequest settingBreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + log2(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingBreakpointRequest() : " + e); + log3(" BreakpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004/TestDescription.java new file mode 100644 index 00000000000..f0dba7f7836 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three BreakpointEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume004; + * the debuggee program - nsk.jdi.EventSet.resume.resume004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume004 + * nsk.jdi.EventSet.resume.resume004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004a.java new file mode 100644 index 00000000000..56712b489b7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004a.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume004 JDI test. + */ + +public class resume004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static resume004aTestClass tcObject = new resume004aTestClass(); + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: resume004aTestClass.method(); + break; + + case 1: resume004aTestClass.method(); + break; + + case 2: resume004aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} + +class resume004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java new file mode 100644 index 00000000000..0705c3929ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test cases include all three possible suspensions, NONE,
    + * EVENT_THREAD, and ALL, for ExceptionEvent sets.
    + *
    + * To check up on the method, a debugger,
    + * upon getting new set for the EventSet,
    + * suspends VM with the method VirtualMachine.suspend(),
    + * gets the List of geduggee's threads calling VM.allThreads(),
    + * invokes the method EventSet.resume(), and
    + * gets another List of geduggee's threads.
    + * The debugger then compares values of
    + * each thread's suspendCount from first and second Lists.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a ExceptionRequest, resumes
    + * the debuggee, and waits for the ExceptionEvent.
    + * - The debuggee invokes the special method which makes access to
    + * a predefined variable to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class resume005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume005().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume005a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.resume005aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingExceptionRequest (mainThread, + debuggeeClass, // testClassReference, + SUSPEND_NONE, "ExceptionRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingExceptionRequest (mainThread, + debuggeeClass, // testClassReference, + SUSPEND_THREAD, "ExceptionRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingExceptionRequest (mainThread, + debuggeeClass, // testClassReference, + SUSPEND_ALL, "ExceptionRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new ExceptionEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + if ( !(newEvent instanceof ExceptionEvent)) { + log3("ERROR: new event is not ExceptionEvent"); + testExitCode = FAILED; + } else { + + String property = (String) newEvent.request().getProperty("number"); + log2(" got new ExceptionEvent with propety 'number' == " + property); + + log2("......checking up on EventSet.resume()"); + log2("......--> vm.suspend();"); + vm.suspend(); + + log2(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(" eventSet.resume;"); + eventSet.resume(); + + log2(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(suspendsCounts1.toString()); + log2(suspendsCounts2.toString()); + + log2(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE : + log2(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + log2(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest1.disable(); + break; + + case SUSPEND_THREAD : + log2(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = ((ExceptionEvent)newEvent).thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest2.disable(); + break; + + case SUSPEND_ALL : + + log2(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!event.request().equals(eventRequest3)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest3.disable(); + break; + + default: throw new JDITestRuntimeException("** default case 1 **"); + } + } + + log2("......--> vm.resume()"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest settingExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005/TestDescription.java new file mode 100644 index 00000000000..fb4c682b8a1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three ExceptionEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume005; + * the debuggee program - nsk.jdi.EventSet.resume.resume005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Fixed due to the bug 4528893. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume005 + * nsk.jdi.EventSet.resume.resume005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005a.java new file mode 100644 index 00000000000..bdd8b54d1b7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005a.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume005 JDI test. + */ + +public class resume005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static resume005aTestClass tcObject = new resume005aTestClass(); + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: resume005aTestClass.method(); + break; + + case 1: resume005aTestClass.method(); + break; + + case 2: resume005aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + public static void nullMethod() { + throw new NullPointerException("test"); + } + +} + +class resume005aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + resume005a.nullMethod(); + } catch ( NullPointerException e ) { +// suspendpolicy005a.log3(" NullPointerException : " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java new file mode 100644 index 00000000000..ba2b22abaa0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test cases include all three possible suspensions, NONE,
    + * EVENT_THREAD, and ALL, for MethodEntryEvent sets.
    + *
    + * To check up on the method, a debugger,
    + * upon getting new set for the EventSet,
    + * suspends VM with the method VirtualMachine.suspend(),
    + * gets the List of geduggee's threads calling VM.allThreads(),
    + * invokes the method EventSet.resume(), and
    + * gets another List of geduggee's threads.
    + * The debugger then compares values of
    + * each thread's suspendCount from first and second Lists.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a MethodEntryRequest, resumes
    + * the debuggee, and waits for the MethodEntryEvent.
    + * - The debuggee invokes the special method which makes access to
    + * a predefined variable to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class resume006 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume006 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume006().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume006a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.resume006aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodEntryRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodEntryRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodEntryRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new MethodEntryEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + if ( !(newEvent instanceof MethodEntryEvent)) { + log3("ERROR: new event is not MethodEntryEvent"); + testExitCode = FAILED; + } else { + + String property = (String) newEvent.request().getProperty("number"); + log2(" got new MethodEntryEvent with propety 'number' == " + property); + + log2("......checking up on EventSet.resume()"); + log2("......--> vm.suspend();"); + vm.suspend(); + + log2(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(" eventSet.resume;"); + eventSet.resume(); + + log2(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(suspendsCounts1.toString()); + log2(suspendsCounts2.toString()); + + log2(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE : + log2(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + log2(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest1.disable(); + break; + + case SUSPEND_THREAD : + log2(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = event.thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest2.disable(); + break; + + case SUSPEND_ALL : + + log2(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!event.request().equals(eventRequest3)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest3.disable(); + break; + + + default: throw new JDITestRuntimeException("** default case 1 **"); + } + } + + log2("......--> vm.resume()"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest settingMethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006/TestDescription.java new file mode 100644 index 00000000000..c6e5bdbb365 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three MethodEntryEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume006; + * the debuggee program - nsk.jdi.EventSet.resume.resume006a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume006 + * nsk.jdi.EventSet.resume.resume006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006a.java new file mode 100644 index 00000000000..ab7677e13fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume006 JDI test. + */ + +public class resume006a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static resume006aTestClass tcObject = new resume006aTestClass(); + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: resume006aTestClass.method(); + break; + + case 1: resume006aTestClass.method(); + break; + + case 2: resume006aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + +} + +class resume006aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java new file mode 100644 index 00000000000..ced07a24a09 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java @@ -0,0 +1,635 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test cases include all three possible suspensions, NONE,
    + * EVENT_THREAD, and ALL, for MethodExitEvent sets.
    + *
    + * To check up on the method, a debugger,
    + * upon getting new set for the EventSet,
    + * suspends VM with the method VirtualMachine.suspend(),
    + * gets the List of geduggee's threads calling VM.allThreads(),
    + * invokes the method EventSet.resume(), and
    + * gets another List of geduggee's threads.
    + * The debugger then compares values of
    + * each thread's suspendCount from first and second Lists.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a MethodExitRequest, resumes
    + * the debuggee, and waits for the MethodExitEvent.
    + * - The debuggee invokes the special method which makes access to
    + * a predefined variable to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class resume007 { + + //----------------------------------------------------- templete section + static final int PASSED = Consts.TEST_PASSED; + static final int FAILED = Consts.TEST_FAILED; + static final int PASS_BASE = Consts.JCK_STATUS_BASE; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume007 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume007().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume007a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.resume007aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodExitRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodExitRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodExitRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new MethodExitEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + if ( !(newEvent instanceof MethodExitEvent)) { + log3("ERROR: new event is not MethodExitEvent"); + testExitCode = FAILED; + } else { + + String property = (String) newEvent.request().getProperty("number"); + log2(" got new MethodExitEvent with propety 'number' == " + property); + + log2("......checking up on EventSet.resume()"); + log2("......--> vm.suspend();"); + vm.suspend(); + + log2(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(" eventSet.resume;"); + eventSet.resume(); + + log2(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(suspendsCounts1.toString()); + log2(suspendsCounts2.toString()); + + log2(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE : + log2(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + log2(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest1.disable(); + break; + + case SUSPEND_THREAD : + log2(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = event.thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest2.disable(); + break; + + case SUSPEND_ALL : + + log2(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!event.request().equals(eventRequest3)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest3.disable(); + break; + + default: throw new JDITestRuntimeException("** default case 1 **"); + } + } + + log2("......--> vm.resume()"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest settingMethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + mexr = eventRManager.createMethodExitRequest(); + mexr.putProperty("number", property); + mexr.addThreadFilter(thread); + mexr.addClassFilter(testedClass); + mexr.setSuspendPolicy(suspendPolicy); + + log2(" MethodExitRequest has been set up"); + return mexr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007/TestDescription.java new file mode 100644 index 00000000000..793b1a457c0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume007. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three MethodExitEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume007; + * the debuggee program - nsk.jdi.EventSet.resume.resume007a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume007 + * nsk.jdi.EventSet.resume.resume007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007a.java new file mode 100644 index 00000000000..a70a4e80246 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume007 JDI test. + */ + +public class resume007a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static resume007aTestClass tcObject = new resume007aTestClass(); + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: resume007aTestClass.method(); + break; + + case 1: resume007aTestClass.method(); + break; + + case 2: resume007aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + +} + +class resume007aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java new file mode 100644 index 00000000000..c011dcd7974 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import static nsk.share.Consts.TEST_FAILED; + +/** + * The test for the implementation of an object of the type + * EventSet. + * + * The test checks that results of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec. + * + * Test cases include all three possible suspensions, NONE, + * EVENT_THREAD, and ALL, for ThreadStartEvent sets. + * + * To check up on the method, a debugger, + * upon getting new set for the EventSet, + * suspends VM with the method VirtualMachine.suspend(), + * gets the List of geduggee's threads calling VM.allThreads(), + * invokes the method EventSet.resume(), and + * gets another List of geduggee's threads. + * The debugger then compares values of + * each thread's suspendCount from first and second Lists. + * + * The test works as follows. + * - The debugger sets up a ThreadStartRequest, resumes + * the debuggee, and waits for the ThreadStartEvent. + * - The debuggee creates and starts new thread + * to be resulting in the event. + * - Upon getting new event, the debugger + * performs the check corresponding to the event. + */ + +public class resume008 extends TestDebuggerType1 { + + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.EventSet.resume.resume008a"; + return new resume008().runThis(argv, out); + } + + private String testedClassName = "nsk.jdi.EventSet.resume.TestClass"; + + + protected void testRun() { + + EventRequest eventRequest = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + eventRequest = settingThreadStartRequest ( + SUSPEND_NONE, "ThreadStartRequest1"); + break; + + case 1: + eventRequest = settingThreadStartRequest ( + SUSPEND_THREAD, "ThreadStartRequest2"); + break; + + case 2: + eventRequest = settingThreadStartRequest ( + SUSPEND_ALL, "ThreadStartRequest3"); + break; + + + default: + throw new Failure("** default case 2 **"); + } + + display("......waiting for new ThreadStartEvent : " + i); + EventSet eventSet = eventHandler.waitForRequestedEventSet(new EventRequest[]{eventRequest}, waitTime, true); + + EventIterator eventIterator = eventSet.eventIterator(); + Event newEvent = eventIterator.nextEvent(); + + if ( !(newEvent instanceof ThreadStartEvent)) { + setFailedStatus("ERROR: new event is not ThreadStartEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ThreadStartEvent with propety 'number' == " + property); + + display("......checking up on EventSet.resume()"); + display("......--> vm.suspend();"); + vm.suspend(); + + display(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + display(suspendsCounts1.toString()); + + display(" eventSet.resume;"); + eventSet.resume(); + + display(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + display(suspendsCounts2.toString()); + + display(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE : + display(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + display(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + case SUSPEND_THREAD : + display(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + display("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = ((ThreadStartEvent)newEvent).thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + case SUSPEND_ALL : + + display(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + display("checking " + threadName); + + if (!newEvent.request().equals(eventRequest)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + default: throw new Failure("** default case 1 **"); + } + } + + display("......--> vm.resume()"); + vm.resume(); + } + return; + } + + private ThreadStartRequest settingThreadStartRequest(int suspendPolicy, + String property) { + try { + ThreadStartRequest tsr = eventRManager.createThreadStartRequest(); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ThreadStartRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008/TestDescription.java new file mode 100644 index 00000000000..91cde13bbb2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume008. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three ThreadStartEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume008; + * the debuggee program - nsk.jdi.EventSet.resume.resume008a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume008 + * nsk.jdi.EventSet.resume.resume008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008a.java new file mode 100644 index 00000000000..8f0790dfef7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume008a.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume008 JDI test. + */ + +public class resume008a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadresume008a thread0 = null; + static Threadresume008a thread1 = null; + static Threadresume008a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread0 = new Threadresume008a("thread0"); + methodForCommunication(); + + threadStart(thread0); + + thread1 = new Threadresume008a("thread1"); + methodForCommunication(); + break; + + case 1: + threadStart(thread1); + + thread2 = new Threadresume008a("thread2"); + methodForCommunication(); + break; + + case 2: + threadStart(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class Threadresume008a extends Thread { + + String tName = null; + + public Threadresume008a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009.java new file mode 100644 index 00000000000..5fbee4c1a35 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import static nsk.share.Consts.TEST_FAILED; + +/** + * The test for the implementation of an object of the type + * EventSet. + * + * The test checks that results of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec. + * + * Test cases include all three possible suspensions, NONE, + * EVENT_THREAD, and ALL, for ThreadDeathEvent sets. + * + * To check up on the method, a debugger, + * upon getting new set for the EventSet, + * suspends VM with the method VirtualMachine.suspend(), + * gets the List of geduggee's threads calling VM.allThreads(), + * invokes the method EventSet.resume(), and + * gets another List of geduggee's threads. + * The debugger then compares values of + * each thread's suspendCount from first and second Lists. + * + * The test works as follows. + * - The debugger sets up a ThreadDeathRequest, resumes + * the debuggee, and waits for the ThreadDeathEvent. + * - The debuggee creates and starts new thread + * to be resulting in the event. + * - Upon getting new event, the debugger + * performs the check corresponding to the event. + */ + +public class resume009 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.EventSet.resume.resume009a"; + return new resume009().runThis(argv, out); + } + + private String testedClassName = "nsk.jdi.EventSet.resume.TestClass"; + + + protected void testRun() { + + EventRequest eventRequest = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + eventRequest = settingThreadDeathRequest ( + SUSPEND_NONE, "ThreadDeathRequest1"); + break; + + case 1: + eventRequest = settingThreadDeathRequest ( + SUSPEND_THREAD, "ThreadDeathRequest2"); + break; + + case 2: + eventRequest = settingThreadDeathRequest ( + SUSPEND_ALL, "ThreadDeathRequest3"); + break; + + + default: + throw new Failure("** default case 2 **"); + } + + display("......waiting for new ThreadDeathEvent : " + i); + EventSet eventSet = eventHandler.waitForRequestedEventSet(new EventRequest[]{eventRequest}, waitTime, true); + + EventIterator eventIterator = eventSet.eventIterator(); + Event newEvent = eventIterator.nextEvent(); + + if ( !(newEvent instanceof ThreadDeathEvent)) { + setFailedStatus("ERROR: new event is not ThreadDeathEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ThreadDeathEvent with propety 'number' == " + property); + + display("......checking up on EventSet.resume()"); + display("......--> vm.suspend();"); + vm.suspend(); + + display(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + display(suspendsCounts1.toString()); + + display(" eventSet.resume;"); + eventSet.resume(); + + display(" getting : Map suspendsCounts2"); + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + + display(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + display(suspendsCounts2.toString()); + + switch (policy) { + + case SUSPEND_NONE : + display(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + display(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + case SUSPEND_THREAD : + display(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + display("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = ((ThreadDeathEvent)newEvent).thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + case SUSPEND_ALL : + + display(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + display("checking " + threadName); + + if (!newEvent.request().equals(eventRequest)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + complain("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = TEST_FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + complain("ERROR: suspendCounts don't match for : " + threadName); + complain("before resuming : " + count1); + complain("after resuming : " + count2); + testExitCode = TEST_FAILED; + break; + } + } + break; + + default: throw new Failure("** default case 1 **"); + } + } + + display("......--> vm.resume()"); + vm.resume(); + } + return; + } + + private ThreadDeathRequest settingThreadDeathRequest(int suspendPolicy, + String property) { + try { + ThreadDeathRequest tsr = eventRManager.createThreadDeathRequest(); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ThreadDeathRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009/TestDescription.java new file mode 100644 index 00000000000..3fd35380f9e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume009. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three ThreadDeathEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume009; + * the debuggee program - nsk.jdi.EventSet.resume.resume009a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume009 + * nsk.jdi.EventSet.resume.resume009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009a.java new file mode 100644 index 00000000000..8b93e8a079f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume009a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume009 JDI test. + */ + +public class resume009a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadresume009a thread0 = null; + static Threadresume009a thread1 = null; + static Threadresume009a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread0 = new Threadresume009a("thread0"); + methodForCommunication(); + + threadRun(thread0); + + thread1 = new Threadresume009a("thread1"); + methodForCommunication(); + break; + + case 1: + threadRun(thread1); + + thread2 = new Threadresume009a("thread2"); + methodForCommunication(); + break; + + case 2: + threadRun(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadRun(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr("Exception in threadRun : " + e ); + return FAILED; + } + } + try { + t.join(); + } catch ( InterruptedException e ) { + exitCode = FAILED; + logErr("InterruptedException in threadRun : " + e ); + return FAILED; + } + return PASSED; + } + + static class Threadresume009a extends Thread { + + String tName = null; + + public Threadresume009a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java new file mode 100644 index 00000000000..5940e5e9a4e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java @@ -0,0 +1,631 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test cases include all three possible suspensions, NONE,
    + * EVENT_THREAD, and ALL, for StepEvent sets.
    + *
    + * To check up on the method, a debugger,
    + * upon getting new set for the EventSet,
    + * suspends VM with the method VirtualMachine.suspend(),
    + * gets the List of geduggee's threads calling VM.allThreads(),
    + * invokes the method EventSet.resume(), and
    + * gets another List of geduggee's threads.
    + * The debugger then compares values of
    + * each thread's suspendCount from first and second Lists.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a StepRequest, resumes
    + * the debuggee, and waits for the StepEvent.
    + * - The debuggee invokes the special method
    + * to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class resume010 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume010 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume010().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume010a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.resume010aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = settingStepRequest (mainThread, + SUSPEND_NONE, "StepRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingStepRequest (mainThread, + SUSPEND_THREAD, "StepRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingStepRequest (mainThread, + + SUSPEND_ALL, "StepRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new StepEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + if ( !(newEvent instanceof StepEvent)) { + log3("ERROR: new event is not StepEvent"); + testExitCode = FAILED; + } else { + + String property = (String) newEvent.request().getProperty("number"); + log2(" got new StepEvent with propety 'number' == " + property); + + log2("......checking up on EventSet.resume()"); + log2("......--> vm.suspend();"); + vm.suspend(); + + log2(" getting : Map suspendsCounts1"); + + Map suspendsCounts1 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts1.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(" eventSet.resume;"); + eventSet.resume(); + + log2(" getting : Map suspendsCounts2"); + + Map suspendsCounts2 = new HashMap(); + for (ThreadReference threadReference : vm.allThreads()) { + suspendsCounts2.put(threadReference.name(), threadReference.suspendCount()); + } + + log2(suspendsCounts1.toString()); + log2(suspendsCounts2.toString()); + + log2(" getting : int policy = eventSet.suspendPolicy();"); + int policy = eventSet.suspendPolicy(); + + switch (policy) { + + case SUSPEND_NONE: + + log2(" case SUSPEND_NONE"); + for (String threadName : suspendsCounts1.keySet()) { + log2(" checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest1.disable(); + break; + + case SUSPEND_THREAD: + + log2(" case SUSPEND_THREAD"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + String eventThreadName = ((StepEvent) newEvent).thread().name(); + int expectedValue = count2 + (eventThreadName.equals(threadName) ? 1 : 0); + if (count1 != expectedValue) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest2.disable(); + break; + + case SUSPEND_ALL: + + log2(" case SUSPEND_ALL"); + for (String threadName : suspendsCounts1.keySet()) { + log2("checking " + threadName); + if (!event.request().equals(eventRequest3)) + break; + if (!suspendsCounts2.containsKey(threadName)) { + log3("ERROR: couldn't get ThreadReference for " + threadName); + testExitCode = FAILED; + break; + } + int count1 = suspendsCounts1.get(threadName); + int count2 = suspendsCounts2.get(threadName); + if (count1 != count2 + 1) { + log3("ERROR: suspendCounts don't match for : " + threadName); + log3("before resuming : " + count1); + log3("after resuming : " + count2); + testExitCode = FAILED; + break; + } + } + eventRequest3.disable(); + break; + + default: + throw new JDITestRuntimeException("** default case 1 **"); + } + } + + log2("......--> vm.resume()"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest settingStepRequest ( ThreadReference thread, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); + str.putProperty("number", property); + str.addCountFilter(1); + str.setSuspendPolicy(suspendPolicy); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010/TestDescription.java new file mode 100644 index 00000000000..0d8894fd02b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume010. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on three StepEvent sets with suspendPolicy() + * NONE, EVENT_THREAD, and ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume010; + * the debuggee program - nsk.jdi.EventSet.resume.resume010a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume010 + * nsk.jdi.EventSet.resume.resume010a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume010 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010a.java new file mode 100644 index 00000000000..d3a6a084fee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010a.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume010 JDI test. + */ + +public class resume010a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static resume010aTestClass tcObject = new resume010aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: resume010aTestClass.method(); + break; + + case 1: resume010aTestClass.method(); + break; + + case 2: resume010aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} +class resume010aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java new file mode 100644 index 00000000000..4bbee554d30 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test case includes SUSPEND_NONE for a VMDeathEvent set.
    + *
    + * The test has three phases and works as follows.
    + *
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * Then to check the above,
    + * the debugger and the debuggee perform the following.
    + * - The debugger sets up a VMDeathRequest, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the VMDeathEvent.
    + * - Upon getting the event, the debugger performs the check.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + */ + +public class resume011 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume011 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume011().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume011a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; +// EventRequest eventRequest2 = null; +// EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest1 = settingVMDeathRequest ( SUSPEND_NONE, "VMDeathRequest1"); + eventRequest1.enable(); + + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + log2("......checking up on eventSet.resume()"); + try { + log2(" eventSet.resume(); :: no Exception expected"); + eventSet.resume(); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011/TestDescription.java new file mode 100644 index 00000000000..7d8c1cbd122 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume011. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on VMDeathEvent set with suspendPolicy() NONE. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume011; + * the debuggee program - nsk.jdi.EventSet.resume.resume011a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume011 + * nsk.jdi.EventSet.resume.resume011a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume011 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011a.java new file mode 100644 index 00000000000..9cff7f41054 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011a.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume011 JDI test. + */ + +public class resume011a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java new file mode 100644 index 00000000000..01aa01ccf23 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test case includes SUSPEND_THREAD for a VMDeathEvent set.
    + *
    + * The test works as follows.
    + *
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * Then to check the above,
    + * the debugger and the debuggee perform the following.
    + * - The debugger sets up a VMDeathRequest, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the VMDeathEvent.
    + * - Upon getting the event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + */ + +public class resume012 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume012 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume012().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume012a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + +// EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; +// EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest2 = settingVMDeathRequest ( SUSPEND_THREAD, "VMDeathRequest2"); + eventRequest2.enable(); + + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + + log2("......checking up on EventSet.resume()"); + try { + log2(" eventSet.resume(); :: Exception expected: com.sun.jdi.InternalException: Inconsistent suspend policy"); + eventSet.resume(); + testExitCode = FAILED; + } catch ( Exception e ) { + log3("Expected exception : " + e); + log2(" vm.resume;"); + vm.resume(); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012/TestDescription.java new file mode 100644 index 00000000000..cedc665813b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume012. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on VMDeathEvent set with suspendPolicy() EVENT_THREAD. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume012; + * the debuggee program - nsk.jdi.EventSet.resume.resume012a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * nsk/jdi/EventSet/resume/resume012 fails intermittently on all platforms + * In case of this test when we force VMDeathEvent with suspend policy set to EVENT_THREAD + * eventSet.resume() produces an exception (com.sun.jdi.InternalException: Inconsistent suspend policy) + * while trying to resume some thread associated with this event. But VMDeathEvent doesn't have any + * associated thread. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume012 + * nsk.jdi.EventSet.resume.resume012a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume012 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012a.java new file mode 100644 index 00000000000..93a23d8d659 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012a.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume012 JDI test. + */ + +public class resume012a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java new file mode 100644 index 00000000000..502b9da8cf5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.resume()
    + * complies with its spec.
    + *
    + * Test case includes SUSPEND_ALL for VMDeathEvent set.
    + *
    + * The test works as follows.
    + *
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * Then to check the above,
    + * the debugger and the debuggee perform the following.
    + * - The debugger sets up a VMDeathRequest, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the VMDeathEvent.
    + * - Upon getting the event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + */ + +public class resume013 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/resume/resume013 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new resume013().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.resume.resume013a"; + + private String testedClassName = + "nsk.jdi.EventSet.resume.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + +// EventRequest eventRequest1 = null; +// EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest3 = settingVMDeathRequest ( SUSPEND_ALL, "VMDeathRequest3"); + eventRequest3.enable(); + + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + + log2("......checking up on EventSet.resume()"); + try { + log2(" eventSet.resume(); :: no Exception expected"); + eventSet.resume(); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + log2(" vm.resume;"); + vm.resume(); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013/TestDescription.java new file mode 100644 index 00000000000..ef01c8c15a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/resume/resume013. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.resume() + * complies with its spec: + * public void resume() + * Resumes threads suspended by this event set. + * If the suspendPolicy() is EventRequest.SUSPEND_ALL, + * a call to this method is equivalent to VirtualMachine.resume(). + * If the suspend policy is EventRequest.SUSPEND_EVENT_THREAD, + * a call to this method is equivalent to ThreadReference.resume() + * for the event thread. Otherwise, a call to this method is a no-op. + * The test checks up on VMDeathEvent set with suspendPolicy() ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.resume.resume013; + * the debuggee program - nsk.jdi.EventSet.resume.resume013a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.resume.resume013 + * nsk.jdi.EventSet.resume.resume013a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.resume.resume013 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013a.java new file mode 100644 index 00000000000..478e33f639c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013a.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the resume013 JDI test. + */ + +public class resume013a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java new file mode 100644 index 00000000000..0d075163fd1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a ClassPrepareEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + * The debugger then prepares an array containing sets of
    + * enabled requests for each combination to check.
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for ClassPrepareEvents.
    + * - The debuggee makes new checked classes prepared and invokes then
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the ClassPrepareEvents,
    + * the debugger performs the check required.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + int classFlags = 0; + + String classNames[] = { + "nsk.jdi.EventSet.suspendPolicy.TestClass0", + "nsk.jdi.EventSet.suspendPolicy.TestClass1", + "nsk.jdi.EventSet.suspendPolicy.TestClass2", + "nsk.jdi.EventSet.suspendPolicy.TestClass3", + "nsk.jdi.EventSet.suspendPolicy.TestClass4", + "nsk.jdi.EventSet.suspendPolicy.TestClass5", + "nsk.jdi.EventSet.suspendPolicy.TestClass6" + }; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + EventRequest eventRequests[][] = new EventRequest[classNames.length][3]; + + for ( int nr = 0; nr < eventRequests.length; nr++) { + log2("......setting up ClassPrepareRequest for TestClass" + nr); + switch (nr) { + + case 0: + eventRequests[nr][0] = settingClassPrepareRequest(classNames[nr], + SUSPEND_NONE, "ClassPrepareRequest" + nr); + eventRequests[nr][0].enable(); + break; + + case 1: + eventRequests[nr][1] = settingClassPrepareRequest(classNames[nr], + SUSPEND_THREAD, "ClassPrepareRequest" + nr); + eventRequests[nr][1].enable(); + break; + + case 2: + eventRequests[nr][2] = settingClassPrepareRequest(classNames[nr], + SUSPEND_ALL, "ClassPrepareRequest" + nr); + eventRequests[nr][2].enable(); + break; + + case 3: + eventRequests[nr][0] = settingClassPrepareRequest(classNames[nr], + SUSPEND_NONE, "ClassPrepareRequest" + nr); + eventRequests[nr][0].enable(); + eventRequests[nr][1] = settingClassPrepareRequest(classNames[nr], + SUSPEND_THREAD, "ClassPrepareRequest" + nr); + eventRequests[nr][1].enable(); + break; + + case 4: + eventRequests[nr][0] = settingClassPrepareRequest(classNames[nr], + SUSPEND_NONE, "ClassPrepareRequest" + nr); + eventRequests[nr][0].enable(); + eventRequests[nr][2] = settingClassPrepareRequest(classNames[nr], + SUSPEND_ALL, "ClassPrepareRequest" + nr); + eventRequests[nr][2].enable(); + break; + + case 5: + eventRequests[nr][1] = settingClassPrepareRequest(classNames[nr], + SUSPEND_THREAD, "ClassPrepareRequest" + nr); + eventRequests[nr][1].enable(); + eventRequests[nr][2] = settingClassPrepareRequest(classNames[nr], + SUSPEND_ALL, "ClassPrepareRequest" + nr); + eventRequests[nr][2].enable(); + break; + + case 6: + eventRequests[nr][0] = settingClassPrepareRequest(classNames[nr], + SUSPEND_NONE, "ClassPrepareRequest" + nr); + eventRequests[nr][0].enable(); + eventRequests[nr][1] = settingClassPrepareRequest(classNames[nr], + SUSPEND_THREAD, "ClassPrepareRequest" + nr); + eventRequests[nr][1].enable(); + eventRequests[nr][2] = settingClassPrepareRequest(classNames[nr], + SUSPEND_ALL, "ClassPrepareRequest" + nr); + eventRequests[nr][2].enable(); + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + classFlags |= 1 << nr; + } + + log2("......checking up on eventSets"); + + vm.resume(); + + for (int ne = 0; ne < eventRequests.length; ne++) { + + getEventSet(); + + Event ev = eventIterator.nextEvent(); + if ( !( ev instanceof ClassPrepareEvent)) { + log3("ERROR: new event is not ClassPrepareEvent"); + testExitCode = FAILED; + break; + } + + String property = (String) ev.request().getProperty("number"); + + int np = 0; + for (; np < eventRequests.length; np++) { + if (property.equals("ClassPrepareRequest" + np)) + break; + } + + policy = eventSet.suspendPolicy(); + + if (policy != policyExpected[np]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[np]); + testExitCode = FAILED; + } + + switch (np) { + case 0: eventRequests[np][0].disable(); break; + case 1: eventRequests[np][1].disable(); break; + case 2: eventRequests[np][2].disable(); break; + case 3: eventRequests[np][0].disable(); eventRequests[np][1].disable(); break; + case 4: eventRequests[np][0].disable(); eventRequests[np][2].disable(); break; + case 5: eventRequests[np][1].disable(); eventRequests[np][2].disable(); break; + case 6: eventRequests[np][0].disable(); eventRequests[np][1].disable(); + eventRequests[np][2].disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : mainThread.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 1 **"); + } + classFlags &= 1 << ne; + } + if (classFlags != 0) { + log3("ERROR: not all events received : " + classFlags); + testExitCode = FAILED; + } + + for (int i = 0; ; i++) { + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ClassPrepareRequest settingClassPrepareRequest ( String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ClassPrepareRequest:"); + log2(" class: " + testedClass + "; property: " + property); + + ClassPrepareRequest + cpr = eventRManager.createClassPrepareRequest(); + cpr.putProperty("number", property); + cpr.addClassFilter(testedClass); + cpr.setSuspendPolicy(suspendPolicy); + + log2(" ClassPrepareRequest has been set up"); + return cpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingClassPrepareRequest() : " + e); + log3(" ClassPreparenRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ClassPrepareRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001/TestDescription.java new file mode 100644 index 00000000000..5b87848d7d1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a ClassPrepareEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy001; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy001 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001a.java new file mode 100644 index 00000000000..df038132104 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001a.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy001 JDI test. + */ + +public class suspendpolicy001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + +// Below, there is no the loop of interaction with the debugger for each Event +// because JVMS doesn't guaranties ordering ClassPrepareEvents. +// Therefore the debugger doesn't rely on the event order. + + case 0: + TestClass0 tcObject0 = new TestClass0(); +// methodForCommunication(); +// break; + + case 1: + TestClass1 tcObject1 = new TestClass1(); +// methodForCommunication(); +// break; + case 2: + TestClass2 tcObject2 = new TestClass2(); +// methodForCommunication(); +// break; + + case 3: + TestClass3 tcObject3 = new TestClass3(); +// methodForCommunication(); +// break; + + case 4: + TestClass4 tcObject4 = new TestClass4(); +// methodForCommunication(); +// break; + + case 5: + TestClass5 tcObject5 = new TestClass5(); +// methodForCommunication(); +// break; + + case 6: + TestClass6 tcObject6 = new TestClass6(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} +class TestClass0 { + static int var1 = 0; +} +class TestClass1 { + static int var1 = 0; +} +class TestClass2 { + static int var1 = 0; +} +class TestClass3 { + static int var1 = 0; +} +class TestClass4 { + static int var1 = 0; +} +class TestClass5 { + static int var1 = 0; +} +class TestClass6 { + static int var1 = 0; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java new file mode 100644 index 00000000000..cdff2ce99db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java @@ -0,0 +1,624 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for an AccessWatchpointEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a AccessWatchpointRequest, resumes
    + * the debuggee, and waits for the AccessWatchpointEvent.
    + * - The debuggee invokes the special method which makes access to
    + * a predefined variable to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy002a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldAccess() ) { + log2("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + ReferenceType testClassReference = null; + + String fieldName = "var1"; + + + for (int i = 0; ; i++) { + + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "AccessWatchpointRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "AccessWatchpointRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "AccessWatchpointRequest3"); + eventRequest3.enable(); + break; + + case 3: + eventRequest1 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "AccessWatchpointRequest4"); + eventRequest1.enable(); + eventRequest2 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "AccessWatchpointRequest5"); + eventRequest2.enable(); + break; + + case 4: + eventRequest1 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "AccessWatchpointRequest6"); + eventRequest1.enable(); + eventRequest3 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "AccessWatchpointRequest7"); + eventRequest3.enable(); + break; + + case 5: + eventRequest2 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "AccessWatchpointRequest8"); + eventRequest2.enable(); + eventRequest3 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "AccessWatchpointRequest9"); + eventRequest3.enable(); + break; + + case 6: + eventRequest1 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "AccessWatchpointRequest10"); + eventRequest1.enable(); + eventRequest2 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "AccessWatchpointRequest11"); + eventRequest2.enable(); + eventRequest3 = settingAccessWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "AccessWatchpointRequest12"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new AccessWatchpointEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + log2(" got new Event with propety 'number' == " + newEvent.request().getProperty("number")); + if ( !( newEvent instanceof AccessWatchpointEvent)) { + log3("ERROR: new event is not AccessWatchpointEvent"); + testExitCode = FAILED; + } else { + log2(" Event is instanceof AccessWatchpointEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + case 3: eventRequest1.disable(); eventRequest2.disable(); break; + case 4: eventRequest1.disable(); eventRequest3.disable(); break; + case 5: eventRequest2.disable(); eventRequest3.disable(); break; + case 6: eventRequest1.disable(); eventRequest2.disable(); + eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : mainThread.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest settingAccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002/TestDescription.java new file mode 100644 index 00000000000..bafe08662d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for an AccessWatchpointEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy002; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy002 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002a.java new file mode 100644 index 00000000000..e8a9a0088cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002a.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy002 JDI test. + */ + +public class suspendpolicy002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static suspendpolicy002aTestClass tcObject = new suspendpolicy002aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: suspendpolicy002aTestClass.method(); + break; + + case 1: suspendpolicy002aTestClass.method(); + break; + + case 2: suspendpolicy002aTestClass.method(); + break; + + case 3: suspendpolicy002aTestClass.method(); + break; + + case 4: suspendpolicy002aTestClass.method(); + break; + + case 5: suspendpolicy002aTestClass.method(); + break; + + case 6: suspendpolicy002aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} +class suspendpolicy002aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java new file mode 100644 index 00000000000..6988f530043 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java @@ -0,0 +1,631 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a ModificationWatchpointEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a ModificationWatchpointRequest, resumes
    + * the debuggee, and waits for the ModificationWatchpointEvent.
    + * - The debuggee invokes the special method which makes modification
    + * of a predefined variable to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy003a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldModification() ) { + log2("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + + ReferenceType testClassReference = null; + + String fieldName = "var2"; + + + for (int i = 0; ; i++) { + + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "ModificationWatchpointRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "ModificationWatchpointRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "ModificationWatchpointRequest3"); + eventRequest3.enable(); + break; + + case 3: + eventRequest1 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "ModificationWatchpointRequest4"); + eventRequest1.enable(); + eventRequest2 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "ModificationWatchpointRequest5"); + eventRequest2.enable(); + break; + + case 4: + eventRequest1 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "ModificationWatchpointRequest6"); + eventRequest1.enable(); + eventRequest3 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "ModificationWatchpointRequest7"); + eventRequest3.enable(); + break; + + case 5: + eventRequest2 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "ModificationWatchpointRequest8"); + eventRequest2.enable(); + eventRequest3 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "ModificationWatchpointRequest9"); + eventRequest3.enable(); + break; + + case 6: + eventRequest1 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_NONE, "ModificationWatchpointRequest10"); + eventRequest1.enable(); + eventRequest2 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_THREAD, "ModificationWatchpointRequest11"); + eventRequest2.enable(); + eventRequest3 = settingModificationWatchpointRequest (mainThread, + testClassReference, fieldName, + SUSPEND_ALL, "ModificationWatchpointRequest12"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new AccessWatchpointEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + log2(" got new Event with propety 'number' == " + newEvent.request().getProperty("number")); + if ( !( newEvent instanceof ModificationWatchpointEvent)) { + log3("ERROR: new event is not ModificationWatchpointEvent"); + testExitCode = FAILED; + } else { + log2(" Event is instanceof ModificationWatchpointEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + case 3: eventRequest1.disable(); eventRequest2.disable(); break; + case 4: eventRequest1.disable(); eventRequest3.disable(); break; + case 5: eventRequest2.disable(); eventRequest3.disable(); break; + case 6: eventRequest1.disable(); eventRequest2.disable(); + eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : mainThread.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest settingModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003/TestDescription.java new file mode 100644 index 00000000000..c01a28bdf50 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a ModificationWatchpointEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy003; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy003 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003a.java new file mode 100644 index 00000000000..08cdc4b885f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003a.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy003 JDI test. + */ + +public class suspendpolicy003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static suspendpolicy003aTestClass tcObject = new suspendpolicy003aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: suspendpolicy003aTestClass.method(); + break; + + case 1: suspendpolicy003aTestClass.method(); + break; + + case 2: suspendpolicy003aTestClass.method(); + break; + + case 3: suspendpolicy003aTestClass.method(); + break; + + case 4: suspendpolicy003aTestClass.method(); + break; + + case 5: suspendpolicy003aTestClass.method(); + break; + + case 6: suspendpolicy003aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} +class suspendpolicy003aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java new file mode 100644 index 00000000000..56719aeac70 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a BreakpointEvent set,
    + * the method returns a value corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a BreakpointRequest,
    + * resumes the debuggee, and waits for the BreakpointEvent.
    + * - The debuggee invokes the special method in which control passes
    + * through a predefined line to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy004a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy004aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + + ReferenceType testClassReference = null; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + + for (int i = 0; ; i++) { + + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_NONE, "BreakpointRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_THREAD, "BreakpointRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_ALL, "BreakpointRequest3"); + eventRequest3.enable(); + break; + + case 3: + eventRequest1 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_NONE, "BreakpointRequest4"); + eventRequest1.enable(); + eventRequest2 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_THREAD, "BreakpointRequest5"); + eventRequest2.enable(); + break; + + case 4: + eventRequest1 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_NONE, "BreakpointRequest6"); + eventRequest1.enable(); + eventRequest3 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_ALL, "BreakpointRequest7"); + eventRequest3.enable(); + break; + + case 5: + eventRequest2 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_THREAD, "BreakpointRequest8"); + eventRequest2.enable(); + eventRequest3 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_ALL, "BreakpointRequest9"); + eventRequest3.enable(); + break; + + case 6: + eventRequest1 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_NONE, "BreakpointRequest10"); + eventRequest1.enable(); + eventRequest2 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_THREAD, "BreakpointRequest11"); + eventRequest2.enable(); + eventRequest3 = settingBreakpointRequest (mainThread, + testClassReference, methodName, bpLineName, + SUSPEND_ALL, "BreakpointRequest12"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new BreakpointEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + log2(" got new Event with propety 'number' == " + newEvent.request().getProperty("number")); + if ( !( newEvent instanceof BreakpointEvent)) { + log3("ERROR: new event is not BreakpointEvent"); + testExitCode = FAILED; + } else { + log2(" Event is instanceof BreakpointEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + case 3: eventRequest1.disable(); eventRequest2.disable(); break; + case 4: eventRequest1.disable(); eventRequest3.disable(); break; + case 5: eventRequest2.disable(); eventRequest3.disable(); break; + case 6: eventRequest1.disable(); eventRequest2.disable(); + eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : mainThread.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private BreakpointRequest settingBreakpointRequest ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + "; method: " + methodName + "; line: " + bpLine); + + int n = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + Location loc = (Location) ((Method) testedClass.methodsByName(methodName).get(0)).allLineLocations().get(n); + + BreakpointRequest + bpr = eventRManager.createBreakpointRequest(loc); + bpr.putProperty("number", property); + bpr.addThreadFilter(thread); + bpr.setSuspendPolicy(suspendPolicy); + + log2(" a breakpoint has been set up"); + return bpr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingBreakpointRequest() : " + e); + log3(" BreakpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up BreakpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004/TestDescription.java new file mode 100644 index 00000000000..286ff0c817b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a BreakpointEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy004; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy004 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004a.java new file mode 100644 index 00000000000..8621fb0c9e8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004a.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy004 JDI test. + */ + +public class suspendpolicy004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static suspendpolicy004aTestClass tcObject = new suspendpolicy004aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: suspendpolicy004aTestClass.method(); + break; + + case 1: suspendpolicy004aTestClass.method(); + break; + + case 2: suspendpolicy004aTestClass.method(); + break; + + case 3: suspendpolicy004aTestClass.method(); + break; + + case 4: suspendpolicy004aTestClass.method(); + break; + + case 5: suspendpolicy004aTestClass.method(); + break; + + case 6: suspendpolicy004aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} +class suspendpolicy004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java new file mode 100644 index 00000000000..9009f7402ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java @@ -0,0 +1,624 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for an ExceptionEvent set,
    + * the method returns a value corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a ExceptionRequest,
    + * resumes the debuggee, and waits for the ExceptionEvent.
    + * - The debuggee invokes the special method in which
    + * NullPointerException is thrown to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy005().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy005a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy005aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + + ReferenceType testClassReference = null; + + String methodName = "method"; + String bpLineName = "breakpointLine"; + + + for (int i = 0; ; i++) { + + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_NONE, "ExceptionRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_THREAD, "ExceptionRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_ALL, "ExceptionRequest3"); + eventRequest3.enable(); + break; + + case 3: + eventRequest1 = settingExceptionRequest (mainThread, + debuggeeClass, // testClassReference, + SUSPEND_NONE, "ExceptionRequest4"); + eventRequest1.enable(); + eventRequest2 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_THREAD, "ExceptionRequest5"); + eventRequest2.enable(); + break; + + case 4: + eventRequest1 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_NONE, "ExceptionRequest6"); + eventRequest1.enable(); + eventRequest3 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_ALL, "ExceptionRequest7"); + eventRequest3.enable(); + break; + + case 5: + eventRequest2 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_THREAD, "ExceptionRequest8"); + eventRequest2.enable(); + eventRequest3 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_ALL, "ExceptionRequest9"); + eventRequest3.enable(); + break; + + case 6: + eventRequest1 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_NONE, "ExceptionRequest10"); + eventRequest1.enable(); + eventRequest2 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_THREAD, "ExceptionRequest11"); + eventRequest2.enable(); + eventRequest3 = settingExceptionRequest (mainThread, + debuggeeClass, //testClassReference, + SUSPEND_ALL, "ExceptionRequest12"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new ExceptionEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + log2(" got new Event with propety 'number' == " + newEvent.request().getProperty("number")); + if ( !( newEvent instanceof ExceptionEvent)) { + log3("ERROR: new event is not ExceptionEvent"); + testExitCode = FAILED; + } else { + log2(" Event is instanceof ExceptionEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + case 3: eventRequest1.disable(); eventRequest2.disable(); break; + case 4: eventRequest1.disable(); eventRequest3.disable(); break; + case 5: eventRequest2.disable(); eventRequest3.disable(); break; + case 6: eventRequest1.disable(); eventRequest2.disable(); + eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : mainThread.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest settingExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005/TestDescription.java new file mode 100644 index 00000000000..8ef7e8ee156 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for an ExceptionEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy005; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Fixed due to the bug 4528893. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy005 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005a.java new file mode 100644 index 00000000000..685202cf1e5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005a.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy005 JDI test. + */ + +public class suspendpolicy005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static suspendpolicy005aTestClass tcObject = new suspendpolicy005aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: suspendpolicy005aTestClass.method(); + break; + + case 1: suspendpolicy005aTestClass.method(); + break; + + case 2: suspendpolicy005aTestClass.method(); + break; + + case 3: suspendpolicy005aTestClass.method(); + break; + + case 4: suspendpolicy005aTestClass.method(); + break; + + case 5: suspendpolicy005aTestClass.method(); + break; + + case 6: suspendpolicy005aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + public static void nullMethod() { + throw new NullPointerException("test"); + } + +} + +class suspendpolicy005aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 += 1; + var3 += 1; + var2 = var3; + try { + suspendpolicy005a.nullMethod(); + } catch ( NullPointerException e ) { +// suspendpolicy005a.log3(" NullPointerException : " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java new file mode 100644 index 00000000000..6d9a450317b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java @@ -0,0 +1,622 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a MethodEntryEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a MethodEntryRequest, resumes
    + * the debuggee, and waits for the MethodEntryEvent.
    + * - The debuggee invokes the special method to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy006 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy006 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy006().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy006a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy006aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + + ReferenceType testClassReference = null; + + String fieldName = "var1"; + + + for (int i = 0; ; i++) { + + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodEntryRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodEntryRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodEntryRequest3"); + eventRequest3.enable(); + break; + + case 3: + eventRequest1 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodEntryRequest4"); + eventRequest1.enable(); + eventRequest2 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodEntryRequest5"); + eventRequest2.enable(); + break; + + case 4: + eventRequest1 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodEntryRequest6"); + eventRequest1.enable(); + eventRequest3 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodEntryRequest7"); + eventRequest3.enable(); + break; + + case 5: + eventRequest2 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodEntryRequest8"); + eventRequest2.enable(); + eventRequest3 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodEntryRequest9"); + eventRequest3.enable(); + break; + + case 6: + eventRequest1 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodEntryRequest10"); + eventRequest1.enable(); + eventRequest2 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodEntryRequest11"); + eventRequest2.enable(); + eventRequest3 = settingMethodEntryRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodEntryRequest12"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new MethodEntryEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + log2(" got new Event with propety 'number' == " + newEvent.request().getProperty("number")); + if ( !( newEvent instanceof MethodEntryEvent)) { + log3("ERROR: new event is not MethodEntryEvent"); + testExitCode = FAILED; + } else { + log2(" Event is instanceof MethodEntryEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + case 3: eventRequest1.disable(); eventRequest2.disable(); break; + case 4: eventRequest1.disable(); eventRequest3.disable(); break; + case 5: eventRequest2.disable(); eventRequest3.disable(); break; + case 6: eventRequest1.disable(); eventRequest2.disable(); + eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : mainThread.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest settingMethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006/TestDescription.java new file mode 100644 index 00000000000..bfdd2e4ef8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a MethodEntryEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy006; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy006a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy006 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006a.java new file mode 100644 index 00000000000..ed90bbdef5c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006a.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy006 JDI test. + */ + +public class suspendpolicy006a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static suspendpolicy006aTestClass tcObject = new suspendpolicy006aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: suspendpolicy006aTestClass.method(); + break; + + case 1: suspendpolicy006aTestClass.method(); + break; + + case 2: suspendpolicy006aTestClass.method(); + break; + + case 3: suspendpolicy006aTestClass.method(); + break; + + case 4: suspendpolicy006aTestClass.method(); + break; + + case 5: suspendpolicy006aTestClass.method(); + break; + + case 6: suspendpolicy006aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} +class suspendpolicy006aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java new file mode 100644 index 00000000000..da114123eac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a MethodExitEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a MethodExitRequest, resumes
    + * the debuggee, and waits for the MethodExitEvent.
    + * - The debuggee invokes the special method to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy007 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy007 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy007().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy007a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy007aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + ReferenceType testClassReference = null; + + String fieldName = "var1"; + + + for (int i = 0; ; i++) { + + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodExitRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodExitRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodExitRequest3"); + eventRequest3.enable(); + break; + + case 3: + eventRequest1 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodExitRequest4"); + eventRequest1.enable(); + eventRequest2 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodExitRequest5"); + eventRequest2.enable(); + break; + + case 4: + eventRequest1 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodExitRequest6"); + eventRequest1.enable(); + eventRequest3 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodExitRequest7"); + eventRequest3.enable(); + break; + + case 5: + eventRequest2 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodExitRequest8"); + eventRequest2.enable(); + eventRequest3 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodExitRequest9"); + eventRequest3.enable(); + break; + + case 6: + eventRequest1 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_NONE, "MethodExitRequest10"); + eventRequest1.enable(); + eventRequest2 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_THREAD, "MethodExitRequest11"); + eventRequest2.enable(); + eventRequest3 = settingMethodExitRequest (mainThread, + testClassReference, + SUSPEND_ALL, "MethodExitRequest12"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + log2("......waiting for new MethodExitEvent : " + i); + mainThread.resume(); + getEventSet(); + + Event newEvent = eventIterator.nextEvent(); + log2(" got new Event with propety 'number' == " + newEvent.request().getProperty("number")); + if ( !( newEvent instanceof MethodExitEvent)) { + log3("ERROR: new event is not MethodExitEvent"); + testExitCode = FAILED; + } else { + log2(" Event is instanceof MethodExitEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + case 3: eventRequest1.disable(); eventRequest2.disable(); break; + case 4: eventRequest1.disable(); eventRequest3.disable(); break; + case 5: eventRequest2.disable(); eventRequest3.disable(); break; + case 6: eventRequest1.disable(); eventRequest2.disable(); + eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : mainThread.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest settingMethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + mexr = eventRManager.createMethodExitRequest(); + mexr.putProperty("number", property); + mexr.addThreadFilter(thread); + mexr.addClassFilter(testedClass); + mexr.setSuspendPolicy(suspendPolicy); + + log2(" MethodExitRequest has been set up"); + return mexr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007/TestDescription.java new file mode 100644 index 00000000000..17299d99526 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy007. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a MethodExitEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy007; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy007a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy007 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007a.java new file mode 100644 index 00000000000..af03cedceb4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007a.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy007 JDI test. + */ + +public class suspendpolicy007a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static suspendpolicy007aTestClass tcObject = new suspendpolicy007aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + log1("methodForCommunication(); : " + i); + methodForCommunication(); + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: suspendpolicy007aTestClass.method(); + break; + + case 1: suspendpolicy007aTestClass.method(); + break; + + case 2: suspendpolicy007aTestClass.method(); + break; + + case 3: suspendpolicy007aTestClass.method(); + break; + + case 4: suspendpolicy007aTestClass.method(); + break; + + case 5: suspendpolicy007aTestClass.method(); + break; + + case 6: suspendpolicy007aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} +class suspendpolicy007aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java new file mode 100644 index 00000000000..8c3788b4d3f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a ThreadStartEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up one to three new ThreadStartRequests,
    + * resumes the debuggee, and waits for the ThreadStartEvents.
    + * - The debuggee starts new thread to be resulting in the events.
    + * - Upon getting new ThreadStartEvent,
    + * the debugger performs the check corresponding to the EventSet.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy008 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy008 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy008().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy008a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = settingThreadStartRequest ( + SUSPEND_NONE, "ThreadStartRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingThreadStartRequest ( + SUSPEND_THREAD, "ThreadStartRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingThreadStartRequest ( + SUSPEND_ALL, "ThreadStartRequest3"); + eventRequest3.enable(); + break; + + case 3: + eventRequest1 = settingThreadStartRequest ( + SUSPEND_NONE, "ThreadStartRequest1"); + eventRequest1.enable(); + eventRequest2 = settingThreadStartRequest ( + SUSPEND_THREAD, "ThreadStartRequest2"); + eventRequest2.enable(); + break; + + case 4: + eventRequest1 = settingThreadStartRequest ( + SUSPEND_NONE, "ThreadStartRequest1"); + eventRequest1.enable(); + eventRequest3 = settingThreadStartRequest ( + SUSPEND_ALL, "ThreadStartRequest3"); + eventRequest3.enable(); + break; + + case 5: + eventRequest2 = settingThreadStartRequest ( + SUSPEND_THREAD, "ThreadStartRequest2"); + eventRequest2.enable(); + eventRequest3 = settingThreadStartRequest ( + SUSPEND_ALL, "ThreadStartRequest3"); + eventRequest3.enable(); + break; + + case 6: + eventRequest1 = settingThreadStartRequest ( + SUSPEND_NONE, "ThreadStartRequest1"); + eventRequest1.enable(); + eventRequest2 = settingThreadStartRequest ( + SUSPEND_THREAD, "ThreadStartRequest2"); + eventRequest2.enable(); + eventRequest3 = settingThreadStartRequest ( + SUSPEND_ALL, "ThreadStartRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + mainThread.resume(); + getEventSet(); + + if ( !(eventIterator.nextEvent() instanceof ThreadStartEvent)) { + log3("ERROR: new event is not ThreadStartEvent"); + testExitCode = FAILED; + } else { + log2("......got : instanceof ThreadStartEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + case 3: eventRequest1.disable(); eventRequest2.disable(); break; + case 4: eventRequest1.disable(); eventRequest3.disable(); break; + case 5: eventRequest2.disable(); eventRequest3.disable(); break; + case 6: eventRequest1.disable(); eventRequest2.disable(); + eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : vm.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ThreadStartRequest settingThreadStartRequest(int suspendPolicy, + String property) + throws JDITestRuntimeException { + try { + ThreadStartRequest tsr = eventRManager.createThreadStartRequest(); +// tsr.addThreadFilter(mainThread); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingThreadStartRequest() : " + e); + log3(" ThreadStartRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ThreadStartRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008/TestDescription.java new file mode 100644 index 00000000000..f71380e33f5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy008. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a ThreadStartEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy008; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy008a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy008 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008a.java new file mode 100644 index 00000000000..9906cc3aaa4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008a.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy008 JDI test. + */ + +public class suspendpolicy008a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadsuspendpolicy008a thread0 = null; + static Threadsuspendpolicy008a thread1 = null; + static Threadsuspendpolicy008a thread2 = null; + static Threadsuspendpolicy008a thread3 = null; + static Threadsuspendpolicy008a thread4 = null; + static Threadsuspendpolicy008a thread5 = null; + static Threadsuspendpolicy008a thread6 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread0 = new Threadsuspendpolicy008a("thread0"); + methodForCommunication(); + + threadStart(thread0); + + thread1 = new Threadsuspendpolicy008a("thread1"); + methodForCommunication(); + break; + + case 1: + threadStart(thread1); + + thread2 = new Threadsuspendpolicy008a("thread2"); + methodForCommunication(); + break; + + case 2: + threadStart(thread2); + + thread3 = new Threadsuspendpolicy008a("thread3"); + methodForCommunication(); + break; + + case 3: + threadStart(thread3); + + thread4 = new Threadsuspendpolicy008a("thread4"); + methodForCommunication(); + break; + + case 4: + threadStart(thread4); + + thread5 = new Threadsuspendpolicy008a("thread5"); + methodForCommunication(); + break; + + case 5: + threadStart(thread5); + + thread6 = new Threadsuspendpolicy008a("thread6"); + methodForCommunication(); + break; + + case 6: + threadStart(thread6); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class Threadsuspendpolicy008a extends Thread { + + String tName = null; + + public Threadsuspendpolicy008a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java new file mode 100644 index 00000000000..878c35b9563 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a ThreadDeathEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one to three threads with all possible combinations:
    + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL,
    + * THREAD+ALL, NONE+THREAD+ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up one to three new ThreadDeathRequests,
    + * resumes the debuggee, and waits for the ThreadDeathEvents.
    + * - The debuggee starts new thread to be resulting in the events.
    + * - Upon getting new ThreadDeathEvent,
    + * the debugger performs the check corresponding to the EventSet.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy009 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy009 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy009().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy009a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = settingThreadDeathRequest ( + SUSPEND_NONE, "ThreadDeathRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingThreadDeathRequest ( + SUSPEND_THREAD, "ThreadDeathRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingThreadDeathRequest ( + SUSPEND_ALL, "ThreadDeathRequest3"); + eventRequest3.enable(); + break; + + case 3: + eventRequest1 = settingThreadDeathRequest ( + SUSPEND_NONE, "ThreadDeathRequest1"); + eventRequest1.enable(); + eventRequest2 = settingThreadDeathRequest ( + SUSPEND_THREAD, "ThreadDeathRequest2"); + eventRequest2.enable(); + break; + + case 4: + eventRequest1 = settingThreadDeathRequest ( + SUSPEND_NONE, "ThreadDeathRequest1"); + eventRequest1.enable(); + eventRequest3 = settingThreadDeathRequest ( + SUSPEND_ALL, "ThreadDeathRequest3"); + eventRequest3.enable(); + break; + + case 5: + eventRequest2 = settingThreadDeathRequest ( + SUSPEND_THREAD, "ThreadDeathRequest2"); + eventRequest2.enable(); + eventRequest3 = settingThreadDeathRequest ( + SUSPEND_ALL, "ThreadDeathRequest3"); + eventRequest3.enable(); + break; + + case 6: + eventRequest1 = settingThreadDeathRequest ( + SUSPEND_NONE, "ThreadDeathRequest1"); + eventRequest1.enable(); + eventRequest2 = settingThreadDeathRequest ( + SUSPEND_THREAD, "ThreadDeathRequest2"); + eventRequest2.enable(); + eventRequest3 = settingThreadDeathRequest ( + SUSPEND_ALL, "ThreadDeathRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + mainThread.resume(); + getEventSet(); + + if ( !(eventIterator.nextEvent() instanceof ThreadDeathEvent)) { + log3("ERROR: new event is not ThreadDeathEvent"); + testExitCode = FAILED; + } else { + log2("......got : instanceof ThreadDeathEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + case 3: eventRequest1.disable(); eventRequest2.disable(); break; + case 4: eventRequest1.disable(); eventRequest3.disable(); break; + case 5: eventRequest2.disable(); eventRequest3.disable(); break; + case 6: eventRequest1.disable(); eventRequest2.disable(); + eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : vm.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ThreadDeathRequest settingThreadDeathRequest(int suspendPolicy, + String property) + throws JDITestRuntimeException { + try { + ThreadDeathRequest tsr = eventRManager.createThreadDeathRequest(); +// tsr.addThreadFilter(mainThread); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingThreadDeathRequest() : " + e); + log3(" ThreadDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ThreadDeathRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009/TestDescription.java new file mode 100644 index 00000000000..216d181e0e1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy009. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a ThreadDeathEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one to three threads + * with all possible combinations: + * NONE, THREAD, ALL, NONE+THREAD, NONE+ALL, THREAD+ALL, NONE+THREAD+ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy009; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy009a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy009 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009a.java new file mode 100644 index 00000000000..10e7464620d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009a.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy009 JDI test. + */ + +public class suspendpolicy009a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadsuspendpolicy009a thread0 = null; + static Threadsuspendpolicy009a thread1 = null; + static Threadsuspendpolicy009a thread2 = null; + static Threadsuspendpolicy009a thread3 = null; + static Threadsuspendpolicy009a thread4 = null; + static Threadsuspendpolicy009a thread5 = null; + static Threadsuspendpolicy009a thread6 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread0 = new Threadsuspendpolicy009a("thread0"); + methodForCommunication(); + + threadStart(thread0); + try { + thread0.join(); + } catch (InterruptedException e) { + } + thread1 = new Threadsuspendpolicy009a("thread1"); + methodForCommunication(); + break; + + case 1: + threadStart(thread1); + try { + thread1.join(); + } catch (InterruptedException e) { + } + thread2 = new Threadsuspendpolicy009a("thread2"); + methodForCommunication(); + break; + + case 2: + threadStart(thread2); + try { + thread2.join(); + } catch (InterruptedException e) { + } + thread3 = new Threadsuspendpolicy009a("thread3"); + methodForCommunication(); + break; + + case 3: + threadStart(thread3); + try { + thread3.join(); + } catch (InterruptedException e) { + } + thread4 = new Threadsuspendpolicy009a("thread4"); + methodForCommunication(); + break; + + case 4: + threadStart(thread4); + try { + thread4.join(); + } catch (InterruptedException e) { + } + thread5 = new Threadsuspendpolicy009a("thread5"); + methodForCommunication(); + break; + + case 5: + threadStart(thread5); + try { + thread5.join(); + } catch (InterruptedException e) { + } + thread6 = new Threadsuspendpolicy009a("thread6"); + methodForCommunication(); + break; + + case 6: + threadStart(thread6); + try { + thread6.join(); + } catch (InterruptedException e) { + } + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class Threadsuspendpolicy009a extends Thread { + + String tName = null; + + public Threadsuspendpolicy009a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java new file mode 100644 index 00000000000..ee733d43817 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a StepEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event sets containing
    + * one thread with all possible combinations:
    + * NONE, THREAD, ALL
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a StepRequest, resumes
    + * the debuggee, and waits for the StepEvent.
    + * - The debuggee invokes the special method to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy010 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy010 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy010().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy010a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy010aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = settingStepRequest (mainThread, + SUSPEND_NONE, "StepRequest1"); + eventRequest1.enable(); + break; + + case 1: + eventRequest2 = settingStepRequest (mainThread, + SUSPEND_THREAD, "StepRequest2"); + eventRequest2.enable(); + break; + + case 2: + eventRequest3 = settingStepRequest (mainThread, + + SUSPEND_ALL, "StepRequest3"); + eventRequest3.enable(); + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + mainThread.resume(); + getEventSet(); + + if ( !(eventIterator.nextEvent() instanceof StepEvent)) { + log3("ERROR: new event is not StepEvent"); + testExitCode = FAILED; + } else { + log2("......got : instanceof StepEvent"); + policy = eventSet.suspendPolicy(); + if (policy != policyExpected[i]) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyExpected[i]); + testExitCode = FAILED; + } + } + + switch (i) { + case 0: eventRequest1.disable(); break; + case 1: eventRequest2.disable(); break; + case 2: eventRequest3.disable(); break; + } + + switch (policy) { + case SUSPEND_NONE : break; + case SUSPEND_THREAD : mainThread.resume(); break; + case SUSPEND_ALL : vm.resume(); break; + default: throw new JDITestRuntimeException("** default case 3 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest settingStepRequest ( ThreadReference thread, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); + str.putProperty("number", property); + str.addCountFilter(1); + str.setSuspendPolicy(suspendPolicy); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010/TestDescription.java new file mode 100644 index 00000000000..132179cb198 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy010. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a StepEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event sets containing one thread + * with all possible combinations: NONE, THREAD, ALL + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy010; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy010a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy010 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy010a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy010 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010a.java new file mode 100644 index 00000000000..b21776ff955 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010a.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy010 JDI test. + */ + +public class suspendpolicy010a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static suspendpolicy010aTestClass tcObject = new suspendpolicy010aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); // suspendpolicy010aTestClass is already prepared + + suspendpolicy010aTestClass.method(); + methodForCommunication(); + break; + + case 1: + suspendpolicy010aTestClass.method(); + methodForCommunication(); + break; + + case 2: + suspendpolicy010aTestClass.method(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} +class suspendpolicy010aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java new file mode 100644 index 00000000000..a6e48edc65a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a VMDeathEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event set containing
    + * one more VMDeathRequest with suspendPolicy SUSPEND_NONE.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a VMDeathRequest, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy011 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy011 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy011().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy011a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + int policyToCheck = 0; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest1 = settingVMDeathRequest ( SUSPEND_NONE, "VMDeathRequest1"); + eventRequest1.enable(); + + policyToCheck = policyExpected[0]; + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + log2("......checking up on eventSet.suspendPolicy()"); + int policy = eventSet.suspendPolicy(); + if (policy != policyToCheck) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyToCheck); + testExitCode = FAILED; + } + vm.resume(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011/TestDescription.java new file mode 100644 index 00000000000..b15f5dd942c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy011. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a VMDeathEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event set containing + * one more VMDeathRequest with suspendPolicy SUSPEND_NONE. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy011; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy011a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy011 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy011a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy011 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011a.java new file mode 100644 index 00000000000..ec23ecf49f5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy011 JDI test. + */ + +public class suspendpolicy011a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java new file mode 100644 index 00000000000..18e34f6ece8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a VMDeathEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event set containing one more
    + * VMDeathRequest with suspendPolicy SUSPEND_EVENT_THREAD.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a VMDeathRequest, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy012 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy012 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy012().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy012a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + int policyToCheck = 0; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest2 = settingVMDeathRequest ( SUSPEND_THREAD, "VMDeathRequest2"); + eventRequest2.enable(); + + policyToCheck = policyExpected[1]; + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + log2("......checking up on eventSet.suspendPolicy()"); + int policy = eventSet.suspendPolicy(); + if (policy != policyToCheck) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyToCheck); + testExitCode = FAILED; + } + vm.resume(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012/TestDescription.java new file mode 100644 index 00000000000..d4638896ad5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy012. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a VMDeathEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event set containing + * one more VMDeathRequest with suspendPolicy SUSPEND_EVENT_THREAD. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy012; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy012a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy012 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy012a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy012 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012a.java new file mode 100644 index 00000000000..a9489971213 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy012 JDI test. + */ + +public class suspendpolicy012a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java new file mode 100644 index 00000000000..33dfb24e9e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a VMDeathEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event set containing one more
    + * VMDeathRequest with suspendPolicy SUSPEND_ALL.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up a VMDeathRequest, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy013 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy013 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy013().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy013a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + int policyToCheck = 0; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest3 = settingVMDeathRequest ( SUSPEND_ALL, "VMDeathRequest3"); + eventRequest3.enable(); + + policyToCheck = policyExpected[2]; + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + log2("......checking up on eventSet.suspendPolicy()"); + int policy = eventSet.suspendPolicy(); + if (policy != policyToCheck) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyToCheck); + testExitCode = FAILED; + } + vm.resume(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013/TestDescription.java new file mode 100644 index 00000000000..46517636bb9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy013. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a VMDeathEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event set containing + * one more VMDeathRequest with suspendPolicy SUSPEND_ALL. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy013; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy013a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy013 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy013a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy013 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013a.java new file mode 100644 index 00000000000..a0494e2b066 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy013 JDI test. + */ + +public class suspendpolicy013a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java new file mode 100644 index 00000000000..716d3c21c0d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a VMDeathEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event set containing two more
    + * VMDeathRequests with suspendPolicies
    + * SUSPEND_EVENT_THREAD and SUSPEND_NONE.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up VMDeathRequests, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy014 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy014 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy014().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy014a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + int policyToCheck = 0; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest1 = settingVMDeathRequest (SUSPEND_NONE, "VMDeathRequest1"); + eventRequest1.enable(); + eventRequest2 = settingVMDeathRequest (SUSPEND_THREAD, "VMDeathRequest2"); + eventRequest2.enable(); + + policyToCheck = policyExpected[3]; + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + log2("......checking up on eventSet.suspendPolicy()"); + int policy = eventSet.suspendPolicy(); + if (policy != policyToCheck) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyToCheck); + testExitCode = FAILED; + } + vm.resume(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014/TestDescription.java new file mode 100644 index 00000000000..c7984a61b8d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy014. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a VMDeathEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event set containing two more VMDeathRequests + * with suspendPolicies SUSPEND_EVENT_THREAD and SUSPEND_NONE. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy014; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy014a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy014 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy014a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy014 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014a.java new file mode 100644 index 00000000000..dfdb560e1d4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy014 JDI test. + */ + +public class suspendpolicy014a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java new file mode 100644 index 00000000000..e3cafdf6357 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a VMDeathEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event set containing two more
    + * VMDeathRequests with suspendPolicies
    + * SUSPEND_ALL and SUSPEND_NONE.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up VMDeathRequests, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy015 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy015 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy015().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy015a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + int policyToCheck = 0; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest1 = settingVMDeathRequest (SUSPEND_NONE, "VMDeathRequest1"); + eventRequest1.enable(); + eventRequest3 = settingVMDeathRequest (SUSPEND_ALL, "VMDeathRequest3"); + eventRequest3.enable(); + + policyToCheck = policyExpected[4]; + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + log2("......checking up on eventSet.suspendPolicy()"); + int policy = eventSet.suspendPolicy(); + if (policy != policyToCheck) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyToCheck); + testExitCode = FAILED; + } + vm.resume(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015/TestDescription.java new file mode 100644 index 00000000000..9f485777109 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy015. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a VMDeathEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event set containing two more VMDeathRequests + * with suspendPolicies SUSPEND_ALL and SUSPEND_NONE. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy015; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy015a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy015 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy015a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy015 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015a.java new file mode 100644 index 00000000000..7209c6b160c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy015 JDI test. + */ + +public class suspendpolicy015a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java new file mode 100644 index 00000000000..e8f7c03581a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a VMDeathEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event set containing two more
    + * VMDeathRequests with suspendPolicies
    + * SUSPEND_ALL and SUSPEND_EVENT_THREAD.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up VMDeathRequests, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy016 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy016 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy016().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy016a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + int policyToCheck = 0; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest2 = settingVMDeathRequest (SUSPEND_THREAD, "VMDeathRequest2"); + eventRequest2.enable(); + eventRequest3 = settingVMDeathRequest (SUSPEND_ALL, "VMDeathRequest3"); + eventRequest3.enable(); + + policyToCheck = policyExpected[5]; + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + log2("......checking up on eventSet.suspendPolicy()"); + int policy = eventSet.suspendPolicy(); + if (policy != policyToCheck) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyToCheck); + testExitCode = FAILED; + } + vm.resume(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016/TestDescription.java new file mode 100644 index 00000000000..97a5ddd9063 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy016. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a VMDeathEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event set containing two more VMDeathRequests + * with suspendPolicies SUSPEND_ALL and SUSPEND_EVENT_THREAD. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy016; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy016a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy016 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy016a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy016 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016a.java new file mode 100644 index 00000000000..32e6b43748b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy016 JDI test. + */ + +public class suspendpolicy016a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java new file mode 100644 index 00000000000..c2bf7bfae31 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for a VMDeathEvent set,
    + * the method returns values corresponding to one
    + * which suspends the most threads.
    + * The cases to check include event set containing three more
    + * VMDeathRequests with suspendPolicies
    + * SUSPEND_ALL, SUSPEND_NONE, and SUSPEND_EVENT_THREAD.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the above,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger sets up VMDeathRequests, resumes
    + * the debuggee, and waits for the VMDeathEvent.
    + * - The debuggee ends to be resulting in the event.
    + * - Upon getting new event, the debugger
    + * performs the check corresponding to the event.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + * In third phase, at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class suspendpolicy017 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy017 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy017().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy017a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + int policyToCheck = 0; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + check(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + + return 0; + + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canRequestVMDeathEvent() ) { + log2("......vm.canRequestVMDeathEvent == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + log2("......setting up ClassPrepareEvent for breakpointForCommunication"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = threadByName("main"); + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + final int SUSPEND_POLICY = EventRequest.SUSPEND_NONE; + final int SUSPEND_NONE = EventRequest.SUSPEND_NONE; + final int SUSPEND_THREAD = EventRequest.SUSPEND_EVENT_THREAD; + final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; + + int policyExpected[] = { SUSPEND_NONE, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_THREAD, + SUSPEND_ALL, + SUSPEND_ALL, + SUSPEND_ALL }; + int policy = 0; + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRequest1 = settingVMDeathRequest (SUSPEND_NONE, "VMDeathRequest1"); + eventRequest1.enable(); + eventRequest2 = settingVMDeathRequest (SUSPEND_THREAD, "VMDeathRequest2"); + eventRequest2.enable(); + eventRequest3 = settingVMDeathRequest (SUSPEND_ALL, "VMDeathRequest3"); + eventRequest3.enable(); + + policyToCheck = policyExpected[6]; + mainThread.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private VMDeathRequest settingVMDeathRequest( int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up VMDeathRequest:"); + log2(" suspendPolicy: " + suspendPolicy + "; property: " + property); + + VMDeathRequest + vmdr = eventRManager.createVMDeathRequest(); + vmdr.putProperty("number", property); + vmdr.setSuspendPolicy(suspendPolicy); + + return vmdr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingVMDeathRequest() : " + e); + log3(" VMDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a VMDeathRequest **"); + } + } + + void check() { + log2("......checking up on eventSet.suspendPolicy()"); + int policy = eventSet.suspendPolicy(); + if (policy != policyToCheck) { + log3("ERROR: eventSet.suspendPolicy() != policyExpected"); + log3(" eventSet.suspendPolicy() == " + policy); + log3(" policyExpected == " + policyToCheck); + testExitCode = FAILED; + } + vm.resume(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017/TestDescription.java new file mode 100644 index 00000000000..8a211ce5d3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy017. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for a VMDeathEvent set, + * the method returns values corresponding to one which suspends the most threads. + * The cases to check include event set containing three more VMDeathRequests + * with suspendPoliy SUSPEND_ALL, SUSPEND_NONE, and SUSPEND_EVENT_THREAD. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy017; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy017a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy017 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy017a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy017 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017a.java new file mode 100644 index 00000000000..7632c1f2b86 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy017 JDI test. + */ + +public class suspendpolicy017a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018.java new file mode 100644 index 00000000000..e2d4d7da79a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018.java @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * EventSet.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.EventSet.suspendPolicy()
    + * complies with its spec.
    + *
    + * The test checks that for Event sets,
    + * corresponding to VMStart, VMDeath, and VMDisconnect Events,
    + * the method returns
    + * SUSPEND_ALL, SUSPEND_NONE, and SUSPEND_NONE.
    + *
    + * The test works as follows.
    + *
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent,
    + * it checks up on the value returned by the method suspendPolicy(),
    + * resumes the VM, and waits for VMDeathEvent within
    + * the predefined time interval.
    + * If no the event received, the test is FAILED.
    + * Upon getting the VMDeathEvent, the debugger
    + * checks up on the value returned by the method suspendPolicy() and
    + * waits for VMDisconnectEvent within the predefined time interval.
    + * If no the event received, the test is FAILED.
    + * Upon getting the VMDisconnectEvent, the debugger
    + * checks up on the value returned by the method suspendPolicy().
    + *
    + */ + +public class suspendpolicy018 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/EventSet/suspendPolicy/suspendpolicy018 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new suspendpolicy018().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.EventSet.suspendPolicy.suspendpolicy018a"; + + private String testedClassName = + "nsk.jdi.EventSet.suspendPolicy.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + int policyToCheck = 0; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugeeNoWait(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugeeNoWait(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + log2("waiting for VMStartEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMStartEvent) { + log2("VMStartEvent received; test begins"); + int sp1 = eventSet.suspendPolicy(); + if (sp1 != EventRequest.SUSPEND_ALL) { + log3("ERROR: eventSet.suspendPolicy() != EventRequest.SUSPEND_ALL but : " + sp1); + testExitCode = FAILED; + } + + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDeathEvent) ) { + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } + sp1 = eventSet.suspendPolicy(); + if (sp1 != EventRequest.SUSPEND_NONE) { + log3("ERROR: eventSet.suspendPolicy() != EventRequest.SUSPEND_NONE but : " + sp1); + testExitCode = FAILED; + } + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + if ( !(eventIterator.nextEvent() instanceof VMDisconnectEvent) ) { + log3("ERROR: last event is not the VMDisconnectEvent"); + return 1; + } + sp1 = eventSet.suspendPolicy(); + if (sp1 != EventRequest.SUSPEND_NONE) { + log3("ERROR: eventSet.suspendPolicy() != EventRequest.SUSPEND_NONE but : " + sp1); + testExitCode = FAILED; + } + + return 0; + } else { + log3("ERROR: first event is not the VMStartEvent"); + return 1; + } + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + log2("......getting ClassPrepareEvent for debuggee's class"); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + log2(" received: ClassPrepareEvent for debuggeeClass"); + + vm.resume(); + + log1(" TESTING ENDS"); + return; + } + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018/TestDescription.java new file mode 100644 index 00000000000..14e47c1a3ba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/suspendPolicy/suspendpolicy018. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * EventSet. + * The test checks up that a result of the method + * com.sun.jdi.EventSet.suspendPolicy() + * complies with its spec: + * public int suspendPolicy() + * Returns the policy used to suspend threads in the target VM for this event set. + * This policy is selected from the suspend policies for each event's request; + * the target VM chooses the policy which suspends the most threads. + * The target VM suspends threads according to that policy and + * that policy is returned here. + * See EventRequest for the possible policy values. + * In rare cases, the suspend policy may differ from the requested value if + * a ClassPrepareEvent has occurred in a debugger system thread. + * See ClassPrepareEvent.thread() for details. + * Returns: the suspendPolicy which is either SUSPEND_ALL, + * SUSPEND_EVENT_THREAD or SUSPEND_NONE. + * The test checks that for Event sets, + * corresponding to VMStart, VMDeath, and VMDisconnect Events, + * the method returns SUSPEND_ALL, SUSPEND_NONE, and SUSPEND_NONE. + * The test works as follows: + * The debugger program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy018; + * the debuggee program - nsk.jdi.EventSet.suspendPolicy.suspendpolicy018a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.suspendPolicy.suspendpolicy018 + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy018a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.suspendPolicy.suspendpolicy018 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018a.java new file mode 100644 index 00000000000..6f7404205ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018a.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.EventSet.suspendPolicy; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspendpolicy018 JDI test. + */ + +public class suspendpolicy018a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001.java new file mode 100644 index 00000000000..f5a56217b9f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventSet.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class tostring001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.EventSet.toString."; + private final static String className = "tostring001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + BreakpointRequest brkp = debuggee.setBreakpoint(debuggeeClass, + tostring001a.brkpMethodName, + tostring001a.brkpLineNumber); + debuggee.resume(); + + debuggee.sendSignal(SIGNAL_GO); + EventSet eventSet = null; + +/* + // waiting for VMStartEvent event + try { + eventSet = waitEventSet(null, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected InterruptedException while waiting for VMStartEvent event"); + } + + display("Checking toString() method for eventSet of VMStartEvent event"); + checkToString (eventSet); +*/ + + // waiting the breakpoint event + try { + eventSet = waitEventSet(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected InterruptedException while waiting for Breakpoint event"); + } + if (!(eventSet.eventIterator().nextEvent() instanceof BreakpointEvent)) { + debuggee.resume(); + throw new Failure("BreakpointEvent didn't arrive"); + } + + display("Checking toString() method for eventSet of Breakpoint event"); + checkToString (eventSet); + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + + private static EventSet waitEventSet(EventRequest request, long timeout) + throws InterruptedException { + Event event; + long totalTime = timeout; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + EventIterator eventIterator = null; + EventSet eventSet = null; + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + eventSet = debuggee.VM().eventQueue().remove(totalTime); + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + display(" event ===>>> " + event); + if (event.request() != null && event.request().equals(request)) { + return eventSet; + } else if (request == null && event instanceof VMStartEvent) { + return eventSet; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + return null; + } + + private static void checkToString (EventSet eventSet) { + String str = eventSet.toString(); + if (str == null) { + complain("toString() returns null for event set"); + exitStatus = Consts.TEST_FAILED; + } else if (str.length() == 0) { + complain("toString() returns empty string for event set"); + exitStatus = Consts.TEST_FAILED; + } else { + display("toString() returns for event set : " + str); + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..172c46fc1d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/toString/tostring001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public toString() method of an implementing class of + * com.sun.jdi.EventSet interface. This method is inherited from + * com.sun.jdi.Mirror interface. + * The test checks an assertion: + * In conformity with the contract for java.lang.Object.toString(), + * the overrided method returns representing non-empty string for + * a given EventSet. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for EventSet + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers for setting breakpoints + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.toString.tostring001 + * nsk.jdi.EventSet.toString.tostring001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001a.java new file mode 100644 index 00000000000..63d8e4114d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/toString/tostring001a.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventSet.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class tostring001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + public final static String brkpMethodName = "breakHere"; + public final static int brkpLineNumber = 91; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(tostring001.SIGNAL_READY); + breakHere(); + receiveSignal(tostring001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + public static void breakHere () { + receiveSignal(tostring001.SIGNAL_GO); + log.display("breakpoint line"); // brkpLineNumber + } +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001.java new file mode 100644 index 00000000000..3b60be91ee9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventSet.virtualMachine; + +import nsk.share.*; +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; + +/** + * The debugger application of the test. + */ +public class virtualmachine001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.EventSet.virtualMachine."; + private final static String className = "virtualmachine001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private static VirtualMachine vm; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + BreakpointRequest brkp = debuggee.setBreakpoint(debuggeeClass, + virtualmachine001a.brkpMethodName, + virtualmachine001a.brkpLineNumber); + debuggee.resume(); + + // get expected reference for comparison. + vm = debuggee.VM(); + + debuggee.sendSignal(SIGNAL_GO); + EventSet eventSet = null; + + // waiting the breakpoint event + try { + eventSet = waitEventSet(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected InterruptedException while waiting for Breakpoint event"); + } + if (eventSet == null) + throw new Failure("Expected EventSet didn't arrive"); + + if (!(eventSet.eventIterator().nextEvent() instanceof BreakpointEvent)) { + debuggee.resume(); + throw new Failure("BreakpointEvent didn't arrive"); + } + + display("Checking virtualMachine() method for eventSet of Breakpoint event"); + checkVM (eventSet); + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + + private static EventSet waitEventSet(EventRequest request, long timeout) + throws InterruptedException { + Event event; + long totalTime = timeout; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + EventIterator eventIterator = null; + EventSet eventSet = null; + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + eventSet = debuggee.VM().eventQueue().remove(totalTime); + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + display(" event ===>>> " + event); + if (event.request() != null && event.request().equals(request)) { + return eventSet; + } else if (request == null && event instanceof VMStartEvent) { + return eventSet; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + return null; + } + + private static void checkVM (EventSet eventSet) { + VirtualMachine vm1 = eventSet.virtualMachine(); + if (vm1 == null) { + complain("virtualMachine() returns null for event set"); + exitStatus = Consts.TEST_FAILED; + } else if (vm1 != vm) { + complain("virtualMachine() returns different VirtualMachine object"); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001/TestDescription.java new file mode 100644 index 00000000000..4982a4fe940 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/EventSet/virtualMachine/virtualmachine001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public virtualMachine() method of an implementing class of + * com.sun.jdi.EventSet interface. This method is inherited from + * com.sun.jdi.Mirror interface. + * The test checks an assertion : + * public VirtualMachine virtualMachine() + * Gets the VirtualMachine to which this Mirror belongs. + * A Mirror must be associated with a VirtualMachine to have any meaning. + * Returns: + * the VirtualMachine for which this mirror is a proxy. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for EventSet + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers for setting breakpoints + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.EventSet.virtualMachine.virtualmachine001 + * nsk.jdi.EventSet.virtualMachine.virtualmachine001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.EventSet.virtualMachine.virtualmachine001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001a.java new file mode 100644 index 00000000000..47b03191535 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/virtualMachine/virtualmachine001a.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.EventSet.virtualMachine; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class virtualmachine001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + public final static String brkpMethodName = "breakHere"; + public final static int brkpLineNumber = 92; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(virtualmachine001.SIGNAL_READY); + breakHere(); + receiveSignal(virtualmachine001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + public static void breakHere () { + receiveSignal(virtualmachine001.SIGNAL_GO); + log.display("breakpoint line"); // brkpLineNumber + } +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001.java new file mode 100644 index 00000000000..80e261b45c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001.java @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.EventIterator; +import com.sun.jdi.event.ExceptionEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.VMDisconnectedException; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that caught exception events are properly reported + * or not reported by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with two combinations of boolean parameter notifyCaught. + * The debuggee part of the test raises three caught exceptions: + *
  • own exevent001tException + *
  • IllegalMonitorStateException + *
  • NumberFormatException in another class + */ +public class exevent001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; //milliseconds + + static final String DEBUGGEE_CLASS = + "nsk.jdi.ExceptionEvent._itself_.exevent001t"; + static final String DEBUGGEE_EXCEPTION1 = DEBUGGEE_CLASS + "Exception"; + static final String DEBUGGEE_EXCEPTION2 = "java.lang.IllegalMonitorStateException"; + static final String DEBUGGEE_EXCEPTION3 = "java.lang.NumberFormatException"; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_TEST1 = "test1"; + static final String COMMAND_TEST2 = "test2"; + static final String COMMAND_TEST3 = "test3"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private EventListener elThread; + private EventRequestManager erManager; + private VirtualMachine vm; + private ReferenceType rType; + private volatile ExceptionRequest eRequest; + private volatile int t_case = 0; // testing debuggee's exception + private volatile int exc1Count = 0; + private volatile int exc2Count = 0; + private volatile int exc3Count = 0; + private volatile int totalRes = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); // JCK-style exit status. + } + + public static int run(String argv[], PrintStream out) { + return new exevent001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "exevent001t.err> "); + vm = debuggee.VM(); + erManager = vm.eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + String token = pipe.readln(); + + if (!token.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + token); + return quitDebuggee(FAILED); + } + + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST BUG: cannot find class " + + DEBUGGEE_CLASS); + return quitDebuggee(FAILED); + } + + log.display("Starting events listener"); + EventListener elThread = new EventListener(); + elThread.start(); + +/* Create a new ExceptionRequest with false notifyCaught parameter + so caught exceptions should not be reported. */ + log.display("\nCreating ExceptionEvent request that not reports caught events"); + if ((eRequest = createExReq(false, false)) == null) + return FAILED; + + if (runTestCase(1, COMMAND_TEST1) == FAILED) + return quitDebuggee(FAILED); + + if (runTestCase(2, COMMAND_TEST2) == FAILED) + return quitDebuggee(FAILED); + + if (runTestCase(3, COMMAND_TEST3) == FAILED) + return quitDebuggee(FAILED); + + eRequest.disable(); + +// check results for caught exceptions + if (exc1Count != 0) { + log.complain("TEST FAILED: caught exception " + + DEBUGGEE_EXCEPTION1 + + " was reported by the debugger"); + totalRes = FAILED; + } + exc1Count = 0; + if (exc2Count != 0) { + log.complain("TEST FAILED: caught exception " + + DEBUGGEE_EXCEPTION2 + + " was reported by the debugger"); + totalRes = FAILED; + } + exc2Count = 0; + if (exc3Count != 0) { + log.complain("TEST FAILED: caught exception " + + DEBUGGEE_EXCEPTION3 + + " was reported by the debugger"); + totalRes = FAILED; + } + exc3Count = 0; + +/* Create a new ExceptionRequest with true notifyCaught parameter + so caught exceptions should be reported. */ + log.display("\nCreating ExceptionEvent request that reports caught events"); + if ((eRequest = createExReq(true, false)) == null) + return FAILED; + + if (runTestCase(1, COMMAND_TEST1) == FAILED) + return quitDebuggee(FAILED); + + if (runTestCase(2, COMMAND_TEST2) == FAILED) + return quitDebuggee(FAILED); + + if (runTestCase(3, COMMAND_TEST3) == FAILED) + return quitDebuggee(FAILED); + + eRequest.disable(); + +// check results for caught exceptions + if (exc1Count == 0) { + log.complain("TEST FAILED: caught exception " + + DEBUGGEE_EXCEPTION1 + + " was not reported by the debugger"); + totalRes = FAILED; + } + if (exc2Count == 0) { + log.complain("TEST FAILED: caught exception " + + DEBUGGEE_EXCEPTION2 + + " was not reported by the debugger"); + totalRes = FAILED; + } + if (exc3Count == 0) { + log.complain("TEST FAILED: caught exception " + + DEBUGGEE_EXCEPTION3 + + " was not reported by the debugger"); + totalRes = FAILED; + } + + return quitDebuggee(totalRes); + } + + private int runTestCase(int tNum, String command) { + t_case = tNum; + pipe.println(command); + String token = pipe.readln(); + if (token == null || !token.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + token); + return FAILED; + } + return PASSED; + } + + private ExceptionRequest createExReq(boolean notifyC, boolean notifyUnc) { + ExceptionRequest eRequest; + try { + eRequest = erManager.createExceptionRequest(null, notifyC, notifyUnc); + } catch (Exception e) { + log.complain("createExceptionRequest: " + e); + return null; + } + eRequest.enable(); + return eRequest; + } + + private int quitDebuggee(int stat) { + if (eRequest != null) { + eRequest.disable(); + } + + if (elThread != null) { + elThread.isConnected = false; + try { + if (elThread.isAlive()) + elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught " + e); + stat = FAILED; + } + } + + pipe.println(COMMAND_QUIT); + + int debStat = debuggee.endDebugee(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + debStat); + stat = FAILED; + } else + log.display("Debuggee's process finished with status: " + debStat); + + return stat; + } + + class EventListener extends Thread { + public volatile boolean isConnected = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // there is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDeathEvent) { + isConnected = false; + } else if (event instanceof VMDisconnectEvent) { + isConnected = false; + } else if (event instanceof ExceptionEvent) { + ExceptionEvent exEvent = (ExceptionEvent) event; + log.display("EventListener: following ExceptionEvent occured: \n\t" + + exEvent); + + if (eRequest.equals(event.request())) { + switch (t_case) { + case 1: + if (exEvent.exception().referenceType().name().equals( + DEBUGGEE_EXCEPTION1)) { + log.display(">> Exception event equals to expected " + + exEvent.exception().referenceType().name()); + exc1Count += 1; + } + break; + case 2: + if (exEvent.exception().referenceType().name().equals( + DEBUGGEE_EXCEPTION2)) { + log.display(">> Exception event equals to expected " + + exEvent.exception().referenceType().name()); + exc2Count += 1; + } + break; + case 3: + if (exEvent.exception().referenceType().name().equals( + DEBUGGEE_EXCEPTION3)) { + log.display(">> Exception event equals to expected " + + exEvent.exception().referenceType().name()); + exc3Count += 1; + } + break; + } + } + } else { + log.display("EventListener: following JDI event occured: \n\t" + + event); + } + } + if (isConnected) { + eventSet.resume(); + } + } + } while (isConnected); + } catch (InterruptedException e) { + totalRes = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + } catch (VMDisconnectedException e) { + totalRes = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + e.printStackTrace(); + } + log.display("EventListener: exiting"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001/TestDescription.java new file mode 100644 index 00000000000..3590fd21bf5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/_itself_/exevent001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that caught exception events are properly reported + * or not reported by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with two combinations of boolean parameter notifyCaught. + * The debuggee part of the test raises three caught exceptions: + * - own exevent001tException; + * - IllegalMonitorStateException; + * - NumberFormatException in another class + * COMMENTS + * See also a product bug 4323439. The test was fixed due to + * the bug 4434819. + * -------------------------------- + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * -------------------------------- + * To fix 4615225, + * the test suite was moved here. + * -------------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - quit on VMDeathEvent is added to event handling loop + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent._itself_.exevent001 + * nsk.jdi.ExceptionEvent._itself_.exevent001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent._itself_.exevent001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001t.java new file mode 100644 index 00000000000..895dd5a46e6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent001t.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class exevent001t { + static ArgumentHandler argHandler; + + public static void main(String args[]) { + exevent001t _exevent001t = new exevent001t(); + System.exit(exevent001.JCK_STATUS_BASE + + _exevent001t.communication(args)); + } + + private static void raiseEx() throws exevent001tException { + throw new exevent001tException(); + } + + static void raiseException(int testCase) { + switch(testCase) { + case 1: // raise own Exception then catch it + try { + raiseEx(); + } catch (exevent001tException e) {} + break; + case 2: // raise IllegalMonitorStateException then catch it + Object obj = new Object(); + try { + obj.notify(); + } catch (IllegalMonitorStateException e) {} + break; + case 3: // raise NumberFormatException in another class + new exevent001tNFException("oops!"); + break; + } + } + + int communication(String args[]) { + String command; + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + do { + pipe.println(exevent001.COMMAND_READY); + command = pipe.readln(); + if (command.equals(exevent001.COMMAND_TEST1)) { + raiseException(1); + } else if (command.equals(exevent001.COMMAND_TEST2)) { + raiseException(2); + } else if (command.equals(exevent001.COMMAND_TEST3)) { + raiseException(3); + } else if (command.equals(exevent001.COMMAND_QUIT)) { + break; + } else { + System.err.println("TEST BUG: Debuggee: unknown command: " + + command); + return exevent001.FAILED; + } + } while(true); + return exevent001.PASSED; + } +} + +class exevent001tException extends Exception {} + +class exevent001tNFException { + exevent001tNFException(String arg) { + try { + int i = Integer.parseInt(arg); + } catch (NumberFormatException e) {} + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002.java new file mode 100644 index 00000000000..add38110b0c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.EventIterator; +import com.sun.jdi.event.ExceptionEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.VMDisconnectedException; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that uncaught exception event is properly reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with true value of boolean parameter notifyUncaught. + * The debuggee part of the test raises own uncaught exevent002tException. + */ + +public class exevent002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; //milliseconds + + static final String DEBUGGEE_CLASS = "nsk.jdi.ExceptionEvent._itself_.exevent002t"; + static final String DEBUGGEE_EXCEPTION = DEBUGGEE_CLASS + "Exception"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_RUN = "run"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private EventListener elThread; + private VirtualMachine vm; + private static EventRequestManager erManager; + private ExceptionRequest eRequest; + private static ReferenceType rType, rTypeEx; + private int counter = 0; + private String cmd; + private volatile int totalRes = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); // JCK-style exit status. + } + + public static int run(String argv[], PrintStream out) { + return new exevent002().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "exevent002t.err> "); + vm = debuggee.VM(); + erManager = vm.eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + cmd = pipe.readln(); + + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + return quitDebuggee(FAILED); + } + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_CLASS); + return quitDebuggee(FAILED); + } + if ((rTypeEx = debuggee.classByName(DEBUGGEE_EXCEPTION)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_EXCEPTION); + return quitDebuggee(FAILED); + } + +/* Create a new ExceptionRequest with true notifyUncaught parameter + so uncaught exceptions should be reported. */ + log.display("Creating ExceptionEvent request"); + if ((eRequest = createExReq(false, true)) == null) { + return quitDebuggee(FAILED); + } + + log.display("Starting events listener"); + EventListener elThread = new EventListener(); + elThread.start(); + + log.display("Forcing debuggee to generate uncaught exception"); + counter = 0; + pipe.println(COMMAND_RUN); + + log.display("Waiting for debuggee exits due to uncaught exception"); + debuggee.waitFor(); + + log.display("Waiting for all events recieved"); + try { + if (elThread.isAlive()) elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + e); + return quitDebuggee(FAILED); + } + + if (counter == 0) { + log.complain("TEST FAILED: uncaught exception " + rTypeEx.name() + + " was not reported by the debugger"); + return FAILED; + } + return PASSED; + } + + private ExceptionRequest createExReq(boolean notifyC, boolean notifyUnc) { + ExceptionRequest eRequest; + try { + eRequest = erManager.createExceptionRequest(rTypeEx, notifyC, notifyUnc); + } catch (Exception e) { + log.complain("createExceptionRequest: " + e); + return null; + } + eRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + eRequest.enable(); + return eRequest; + } + + private int quitDebuggee(int stat) { + if (eRequest != null) { + eRequest.disable(); + } + + pipe.println(COMMAND_QUIT); + + if (elThread != null) { + elThread.isConnected = false; + try { + if (elThread.isAlive()) + elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + stat = FAILED; + } + } + + int debStat = debuggee.endDebugee(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + stat = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return stat; + } + class EventListener extends Thread { + public volatile boolean isConnected = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // there is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDeathEvent) { + isConnected = false; + } else if (event instanceof VMDisconnectEvent) { + isConnected = false; + } else if (event instanceof ExceptionEvent) { + ExceptionEvent exEvent = (ExceptionEvent) event; + log.display("EventListener: following ExceptionEvent occured: \n\t" + + exEvent); + + if (eRequest.equals(event.request())) { + if (exEvent.exception().referenceType().equals(rTypeEx)) { + log.display("Exception event equals to expected \n\t" + + exEvent.exception().referenceType().name()); + counter++; + log.display("\t" + "counter = " + counter); + } + } + } else { + log.display("EventListener: following JDI event occured: \n\t" + + event); + } + } + if (isConnected) { + eventSet.resume(); + } + } + } while (isConnected); + } catch (InterruptedException e) { + totalRes = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + } catch (VMDisconnectedException e) { + totalRes = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + e.printStackTrace(); + } + log.display("EventListener: exiting"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002/TestDescription.java new file mode 100644 index 00000000000..1276093c2cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/_itself_/exevent002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that uncaught exception event is properly reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with true value of boolean parameter notifyUncaught. + * The debugee part of the test raises own uncaught crexreq002tException. + * COMMENTS + * See also bug 4323439 + * -------------------------------- + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * -------------------------------- + * To fix 4615225, + * the test suite was moved here. + * -------------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - quit on VMDeathEvent is added to event handling loop + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent._itself_.exevent002 + * nsk.jdi.ExceptionEvent._itself_.exevent002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent._itself_.exevent002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002t.java new file mode 100644 index 00000000000..6b8be28361e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent002t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class exevent002t { + public static void main(String args[]) throws exevent002tException { + exevent002t _exevent002t = new exevent002t(); + System.exit(exevent002.JCK_STATUS_BASE + _exevent002t.communication(args)); + } + + int communication(String args[]) throws exevent002tException { + String command; + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + exevent002tException userException = new exevent002tException(); + + pipe.println(exevent002.COMMAND_READY); + command = pipe.readln(); + if (command.equals(exevent002.COMMAND_RUN)) + throw userException; + else + return exevent002.FAILED; + } +} + +class exevent002tException extends Exception {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003.java new file mode 100644 index 00000000000..cc38cd69580 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.EventIterator; +import com.sun.jdi.event.ExceptionEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.VMDisconnectedException; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that uncaught exception event is not reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with false value of boolean parameter notifyUncaught. + * The debugee part of the test raises own uncaught exevent003tException. + */ + +public class exevent003 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; //milliseconds + + static final String DEBUGGEE_CLASS = "nsk.jdi.ExceptionEvent._itself_.exevent003t"; + static final String DEBUGGEE_EXCEPTION = DEBUGGEE_CLASS + "Exception"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_RUN = "run"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private EventListener elThread; + private VirtualMachine vm; + private static EventRequestManager erManager; + private ExceptionRequest eRequest; + private static ReferenceType rType, rTypeEx; + private int counter = 0; + private String cmd; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); // JCK-style exit status. + } + + public static int run(String argv[], PrintStream out) { + return new exevent003().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "exevent003t.err> "); + vm = debuggee.VM(); + erManager = vm.eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + cmd = pipe.readln(); + + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_CLASS); + tot_res = FAILED; + return quitDebuggee(); + } + if ((rTypeEx = debuggee.classByName(DEBUGGEE_EXCEPTION)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_EXCEPTION); + tot_res = FAILED; + return quitDebuggee(); + } + +/* Create a new ExceptionRequest with false notifyUncaught parameter + so uncaught exceptions should not be reported. */ + log.display("Creating ExceptionEvent request"); + if ((eRequest = createExReq(false, false)) == null) { + tot_res = FAILED; + return quitDebuggee(); + } + + log.display("Starting events listener"); + EventListener elThread = new EventListener(); + elThread.start(); + + log.display("Forcing debuggee to generate uncaught exception"); + counter = 0; + pipe.println(COMMAND_RUN); + + log.display("Waiting for debuggee exits due to uncaught exception"); + debuggee.waitFor(); + + log.display("Waiting for all events recieved"); + try { + if (elThread.isAlive()) elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + e); + tot_res = FAILED; + return quitDebuggee(); + } + + if (counter != 0) { + log. complain("TEST FAILED: uncaught exception " + rTypeEx.name() + + " was reported by the debugger"); + return FAILED; + } + else return PASSED; + } + + private ExceptionRequest createExReq(boolean notifyC, boolean notifyUnc) { + ExceptionRequest eRequest; + try { + eRequest = erManager.createExceptionRequest(rType, notifyC, notifyUnc); + } catch (Exception e) { + log.complain("createExceptionRequest: " + e); + return null; + } + eRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + eRequest.enable(); + return eRequest; + } + + private int quitDebuggee() { + if (eRequest != null) { + eRequest.disable(); + } + + pipe.println(COMMAND_QUIT); + + if (elThread != null) { + elThread.isConnected = false; + try { + if (elThread.isAlive()) + elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + } + + int debStat = debuggee.endDebugee(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } + class EventListener extends Thread { + public volatile boolean isConnected = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // there is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDeathEvent) { + isConnected = false; + } else if (event instanceof VMDisconnectEvent) { + isConnected = false; + } else if (event instanceof ExceptionEvent) { + ExceptionEvent exEvent = (ExceptionEvent) event; + log.display("EventListener: following ExceptionEvent occured: \n\t" + + exEvent.toString()); + + if (eRequest.equals(event.request())) { + if (exEvent.exception().referenceType().equals(rTypeEx)) { + log.display("Exception event equals to expected \n\t" + + exEvent.exception().referenceType().name()); + counter++; + log.display("\t" + "counter = " + counter); + } + } + } else { + log.display("EventListener: following JDI event occured: \n\t" + + event.toString()); + } + } + if (isConnected) { + eventSet.resume(); + } + } + } while (isConnected); + } catch (InterruptedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + } catch (VMDisconnectedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + e.printStackTrace(); + } + log.display("EventListener: exiting"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003/TestDescription.java new file mode 100644 index 00000000000..af76f1ee1f7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/_itself_/exevent003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that uncaught exception event is not reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with false value of boolean parameter notifyUncaught. + * The debugee part of the test raises own uncaught crexreq003tException. + * COMMENTS + * See also bug 4323439 + * -------------------------------- + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * -------------------------------- + * To fix 4615225, + * the test suite was moved here. + * -------------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - quit on VMDeathEvent is added to event handling loop + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent._itself_.exevent003 + * nsk.jdi.ExceptionEvent._itself_.exevent003t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent._itself_.exevent003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003t.java new file mode 100644 index 00000000000..6ede86d2cfa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent003t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class exevent003t { + public static void main(String args[]) throws exevent003tException { + exevent003t _exevent003t = new exevent003t(); + System.exit(exevent003.JCK_STATUS_BASE + _exevent003t.communication(args)); + } + + int communication(String args[]) throws exevent003tException { + String command; + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + exevent003tException userException = new exevent003tException(); + + pipe.println(exevent003.COMMAND_READY); + command = pipe.readln(); + if (command.equals(exevent003.COMMAND_RUN)) + throw userException; + else + return exevent003.FAILED; + } +} + +class exevent003tException extends Exception {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004.java new file mode 100644 index 00000000000..85d0e31982d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.EventIterator; +import com.sun.jdi.event.ExceptionEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.VMDisconnectedException; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that uncaught exception event is properly reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with true value of boolean parameter notifyUncaught. + * The debugee part of the test raises uncaught StackOverflowException by + * recursion calls of the same method. + */ + +public class exevent004 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; //milliseconds + + static final String DEBUGGEE_CLASS = "nsk.jdi.ExceptionEvent._itself_.exevent004t"; + static final String DEBUGGEE_EXCEPTION = "java.lang.ArithmeticException"; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_RUN = "run"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private EventListener elThread; + private VirtualMachine vm; + private EventRequestManager erManager; + private ExceptionRequest eRequest; + private ReferenceType rType; + private int counter = 0; + private String cmd; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); // JCK-style exit status. + } + + public static int run(String argv[], PrintStream out) { + return new exevent004().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "exevent004t.err> "); + vm = debuggee.VM(); + erManager = vm.eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + cmd = pipe.readln(); + + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_CLASS); + tot_res = FAILED; + return quitDebuggee(); + } + +/* Create a new ExceptionRequest with true notifyUncaught parameter + so uncaught exceptions should be reported. */ + log.display("Creating ExceptionEvent request"); + if ((eRequest = createExReq(false, true)) == null) { + tot_res = FAILED; + return quitDebuggee(); + } + + log.display("Starting events listener"); + EventListener elThread = new EventListener(); + elThread.start(); + + log.display("Forcing debuggee to generate uncaught exception"); + counter = 0; + pipe.println(COMMAND_RUN); + + log.display("Waiting for debuggee exits due to uncaught exception"); + debuggee.waitFor(); + + log.display("Waiting for all events recieved"); + try { + if (elThread.isAlive()) elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + e); + tot_res = FAILED; + return quitDebuggee(); + } + + if (counter == 0) { + log.complain("TEST FAILED: uncaught exception " + DEBUGGEE_EXCEPTION + + " was not reported by the debugger"); + return FAILED; + } + else return PASSED; + } + + private ExceptionRequest createExReq(boolean notifyC, boolean notifyUnc) { + ExceptionRequest eRequest; + try { + eRequest = erManager.createExceptionRequest(null, notifyC, notifyUnc); + } catch (Exception e) { + log.complain("createExceptionRequest: " + e); + return null; + } + eRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + eRequest.enable(); + return eRequest; + } + + private int quitDebuggee() { + if (eRequest != null) { + eRequest.disable(); + } + + if (elThread != null) { + elThread.isConnected = false; + try { + if (elThread.isAlive()) + elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + } + + pipe.println(COMMAND_QUIT); + + int debStat = debuggee.endDebugee(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } + + class EventListener extends Thread { + public volatile boolean isConnected = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // there is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDeathEvent) { + isConnected = false; + } else if (event instanceof VMDisconnectEvent) { + isConnected = false; + } else if (event instanceof ExceptionEvent) { + ExceptionEvent exEvent = (ExceptionEvent) event; + log.display("EventListener: following ExceptionEvent occured: \n\t" + + exEvent.toString()); + + if (eRequest.equals(event.request())) { + if (exEvent.exception().referenceType().name().equals(DEBUGGEE_EXCEPTION)) { + log.display("Exception event equals to expected \n\t" + + exEvent.exception().referenceType().name()); + counter++; + log.display("\t" + "counter = " + counter); + } + } + } else { + log.display("EventListener: following JDI event occured: \n\t" + + event.toString()); + } + } + if (isConnected) { + eventSet.resume(); + } + } + } while (isConnected); + } catch (InterruptedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + } catch (VMDisconnectedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + e.printStackTrace(); + } + log.display("EventListener: exiting"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004/TestDescription.java new file mode 100644 index 00000000000..56bd168d280 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/_itself_/exevent004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that uncaught exception event is properly reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with true value of boolean parameter notifyUncaught. + * The debugee part of the test rai7~ses uncaught ArithmeticException by + * deviding integer by zero + * COMMENTS + * See also bug 4323439 + * -------------------------------- + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * -------------------------------- + * To fix 4615225, + * the test suite was moved here. + * -------------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - quit on VMDeathEvent is added to event handling loop + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent._itself_.exevent004 + * nsk.jdi.ExceptionEvent._itself_.exevent004t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent._itself_.exevent004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004t.java new file mode 100644 index 00000000000..d6901be9191 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent004t.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class exevent004t { + public static void main(String args[]) { + exevent004t _exevent004t = new exevent004t(); + System.exit(exevent004.JCK_STATUS_BASE + _exevent004t.communication(args)); + } + + private static void raiseArithmeticException() { + int foo = 10; + foo = foo / 0; + } + + int communication(String args[]) throws ArithmeticException { + String command; + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(exevent004.COMMAND_READY); + command = pipe.readln(); + if (command.equals(exevent004.COMMAND_RUN)) { + raiseArithmeticException(); + return exevent004.PASSED; + } else + return exevent004.FAILED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005.java new file mode 100644 index 00000000000..12087f79495 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.EventIterator; +import com.sun.jdi.event.ExceptionEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.VMDisconnectedException; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that uncaught exception event is not reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with false value of boolean parameter notifyUncaught. + * The debugee part of the test raises uncaught StackOverflowException + * by recursion calls of the same method. + */ + +public class exevent005 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; //milliseconds + + static final String DEBUGGEE_CLASS = "nsk.jdi.ExceptionEvent._itself_.exevent005t"; + static final String DEBUGGEE_EXCEPTION = "java.lang.ArithmeticException"; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_RUN = "run"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private EventListener elThread; + private VirtualMachine vm; + private EventRequestManager erManager; + private ExceptionRequest eRequest; + private ReferenceType rType; + private int counter = 0; + private String cmd; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); // JCK-style exit status. + } + + public static int run(String argv[], PrintStream out) { + return new exevent005().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "exevent005t.err> "); + vm = debuggee.VM(); + erManager = vm.eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + cmd = pipe.readln(); + + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_CLASS); + tot_res = FAILED; + return quitDebuggee(); + } + +/* Create a new ExceptionRequest with false notifyUncaught parameter + so uncaught exceptions should not be reported. */ + log.display("Creating ExceptionEvent request"); + if ((eRequest = createExReq(false, false)) == null) { + tot_res = FAILED; + return quitDebuggee(); + } + + log.display("Starting events listener"); + EventListener elThread = new EventListener(); + elThread.start(); + + log.display("Forcing debuggee to generate uncaught exception"); + counter = 0; + pipe.println(COMMAND_RUN); + + log.display("Waiting for debuggee exits due to uncaught exception"); + debuggee.waitFor(); + + log.display("Waiting for all events recieved"); + try { + if (elThread.isAlive()) elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + e); + tot_res = FAILED; + return quitDebuggee(); + } + + if (counter != 0) { + log.complain("TEST FAILED: uncaught exception " + DEBUGGEE_EXCEPTION + + " was reported by the debugger"); + return FAILED; + } + else return PASSED; + } + + private ExceptionRequest createExReq(boolean notifyC, boolean notifyUnc) { + ExceptionRequest eRequest; + try { + eRequest = erManager.createExceptionRequest(null, notifyC, notifyUnc); + } catch (Exception e) { + log.complain("createExceptionRequest: " + e); + return null; + } + eRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + eRequest.enable(); + return eRequest; + } + + private int quitDebuggee() { + if (eRequest != null) { + eRequest.disable(); + } + + if (elThread != null) { + elThread.isConnected = false; + try { + if (elThread.isAlive()) + elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + } + + pipe.println(COMMAND_QUIT); + + int debStat = debuggee.endDebugee(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } + + class EventListener extends Thread { + public volatile boolean isConnected = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // there is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDeathEvent) { + isConnected = false; + } else if (event instanceof VMDisconnectEvent) { + isConnected = false; + } else if (event instanceof ExceptionEvent) { + ExceptionEvent exEvent = (ExceptionEvent) event; + log.display("EventListener: following ExceptionEvent occured: \n\t" + + exEvent.toString()); + + if (eRequest.equals(event.request())) { + if (exEvent.exception().referenceType().name().equals(DEBUGGEE_EXCEPTION)) { + log.display("Exception event equals to expected \n\t" + + exEvent.exception().referenceType().name()); + counter++; + log.display("\t" + "counter = " + counter); + } + } + } else { + log.display("EventListener: following JDI event occured: \n\t" + + event.toString()); + } + } + if (isConnected) { + eventSet.resume(); + } + } + } while (isConnected); + } catch (InterruptedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + } catch (VMDisconnectedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + e.printStackTrace(); + } + log.display("EventListener: exiting"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005/TestDescription.java new file mode 100644 index 00000000000..85bcc6d6091 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/_itself_/exevent005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that uncaught exception event is not reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with false value of boolean parameter notifyUncaught. + * The debugee part of the test rai7~ses uncaught ArithmeticException by + * deviding integer by zero + * COMMENTS + * See also bug 4323439 + * -------------------------------- + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * -------------------------------- + * To fix 4615225, + * the test suite was moved here. + * -------------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - quit on VMDeathEvent is added to event handling loop + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent._itself_.exevent005 + * nsk.jdi.ExceptionEvent._itself_.exevent005t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent._itself_.exevent005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005t.java new file mode 100644 index 00000000000..2360b1dd963 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent005t.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class exevent005t { + public static void main(String args[]) { + exevent005t _exevent005t = new exevent005t(); + System.exit(exevent005.JCK_STATUS_BASE + _exevent005t.communication(args)); + } + + private static void raiseArithmeticException() { + int foo = 10; + foo = foo / 0; + } + + int communication(String args[]) throws ArithmeticException { + String command; + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(exevent005.COMMAND_READY); + command = pipe.readln(); + if (command.equals(exevent005.COMMAND_RUN)) { + raiseArithmeticException(); + return exevent005.PASSED; + } else + return exevent005.FAILED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006.java new file mode 100644 index 00000000000..9ead1af3517 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.EventIterator; +import com.sun.jdi.event.ExceptionEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.VMDisconnectedException; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that uncaught exception event is properly reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with true value of boolean parameter notifyUncaught. + * The debugee part of the test raises uncaught NumberFormatException + * in another class. + */ + +public class exevent006 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; //milliseconds + + static final String DEBUGGEE_CLASS = "nsk.jdi.ExceptionEvent._itself_.exevent006t"; +// static final String DEBUGGEE_EXCEPTION = "java.lang.NumberFormatException"; + static final String DEBUGGEE_EXCEPTION = "java.lang.reflect.InvocationTargetException"; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_RUN = "run"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private EventListener elThread; + private VirtualMachine vm; + private EventRequestManager erManager; + private ExceptionRequest eRequest; + private ReferenceType rType; + private int counter = 0; + private String cmd; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); // JCK-style exit status. + } + + public static int run(String argv[], PrintStream out) { + return new exevent006().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "exevent006t.err> "); + vm = debuggee.VM(); + erManager = vm.eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + cmd = pipe.readln(); + + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_CLASS); + tot_res = FAILED; + return quitDebuggee(); + } + +/* Create a new ExceptionRequest with true notifyUncaught parameter + so uncaught exceptions should be reported. */ + log.display("Creating ExceptionEvent request"); + if ((eRequest = createExReq(false, true)) == null) { + tot_res = FAILED; + return quitDebuggee(); + } + + log.display("Starting events listener"); + EventListener elThread = new EventListener(); + elThread.start(); + + log.display("Forcing debuggee to generate uncaught exception"); + counter = 0; + pipe.println(COMMAND_RUN); + + log.display("Waiting for debuggee exits due to uncaught exception"); + debuggee.waitFor(); + + log.display("Waiting for all events recieved"); + try { + if (elThread.isAlive()) elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + e); + tot_res = FAILED; + return quitDebuggee(); + } + + if (counter == 0) { + log.complain("TEST FAILED: uncaught exception " + DEBUGGEE_EXCEPTION + + " was not reported by the debugger"); + return FAILED; + } + else return PASSED; + } + + private ExceptionRequest createExReq(boolean notifyC, boolean notifyUnc) { + ExceptionRequest eRequest; + try { + eRequest = erManager.createExceptionRequest(null, notifyC, notifyUnc); + } catch (Exception e) { + log.complain("createExceptionRequest: " + e); + return null; + } + eRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + eRequest.enable(); + return eRequest; + } + + private int quitDebuggee() { + if (eRequest != null) { + eRequest.disable(); + } + + if (elThread != null) { + elThread.isConnected = false; + try { + if (elThread.isAlive()) + elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + } + + pipe.println(COMMAND_QUIT); + + int debStat = debuggee.endDebugee(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } + + class EventListener extends Thread { + public volatile boolean isConnected = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // there is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDeathEvent) { + isConnected = false; + } else if (event instanceof VMDisconnectEvent) { + isConnected = false; + } else if (event instanceof ExceptionEvent) { + ExceptionEvent exEvent = (ExceptionEvent) event; + log.display("EventListener: following ExceptionEvent occured: \n\t" + + exEvent.toString()); + + if (eRequest.equals(event.request())) { + if (exEvent.exception().referenceType().name().equals(DEBUGGEE_EXCEPTION)) { + log.display("Exception event equals to expected \n\t" + + exEvent.exception().referenceType().name()); + counter++; + log.display("\t" + "counter = " + counter); + } + } + } else { + log.display("EventListener: following JDI event occured: \n\t" + + event.toString()); + } + } + if (isConnected) { + eventSet.resume(); + } + } + } while (isConnected); + } catch (InterruptedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + } catch (VMDisconnectedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + e.printStackTrace(); + } + log.display("EventListener: exiting"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006/TestDescription.java new file mode 100644 index 00000000000..40365a0bed6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/_itself_/exevent006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that uncaught exception event is properly reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with true value of boolean parameter notifyUncaught. + * The debugee part of the test raises NumberFormatException in + * another class, which is caught by Method.invoke() and enveloped + * into uncaught InvokationTargetException. + * COMMENTS + * See also bug 4323439 + * -------------------------------- + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * -------------------------------- + * To fix 4615225, + * the test suite was moved here. + * -------------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - quit on VMDeathEvent is added to event handling loop + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent._itself_.exevent006 + * nsk.jdi.ExceptionEvent._itself_.exevent006t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent._itself_.exevent006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006t.java new file mode 100644 index 00000000000..ca08aa0fe3e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent006t.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class exevent006t { + public static void main(String args[]) throws ClassNotFoundException, + NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + exevent006t _exevent006t = new exevent006t(); + System.exit(exevent006.JCK_STATUS_BASE + _exevent006t.communication(args)); + } + + int communication(String args[]) throws ClassNotFoundException, + NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + String command; + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(exevent006.COMMAND_READY); + command = pipe.readln(); + if (command.equals(exevent006.COMMAND_RUN)) { + Class testClass = Class.forName(exevent006.DEBUGGEE_CLASS+"Exception"); + Class methodArgs[] = { String.class }; + Method testMeth = testClass.getMethod("exevent006traiseEx", methodArgs); + Object testInstance = testClass.newInstance(); + Object parameters[] = { "oops!" }; + Object result = testMeth.invoke(testInstance, parameters); + + return exevent006.PASSED; + } else + return exevent006.FAILED; + } +} + +class exevent006tException { + public void exevent006traiseEx(String arg) { + int i = Integer.parseInt(arg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007.java new file mode 100644 index 00000000000..06f2b698e7d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.EventIterator; +import com.sun.jdi.event.ExceptionEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.VMDisconnectedException; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that uncaught exception event is not reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with false value of boolean parameter notifyUncaught. + * The debugee part of the test raises uncaught NumberFormatException + * in another class. + */ + +public class exevent007 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; //milliseconds + + static final String DEBUGGEE_CLASS = "nsk.jdi.ExceptionEvent._itself_.exevent007t"; +// static final String DEBUGGEE_EXCEPTION = "java.lang.NumberFormatException"; + static final String DEBUGGEE_EXCEPTION = "java.lang.reflect.InvocationTargetException"; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_RUN = "run"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private EventListener elThread; + private VirtualMachine vm; + private EventRequestManager erManager; + private ExceptionRequest eRequest; + private ReferenceType rType; + private int counter = 0; + private String cmd; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); // JCK-style exit status. + } + + public static int run(String argv[], PrintStream out) { + return new exevent007().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "crexreq006t.err> "); + vm = debuggee.VM(); + erManager = vm.eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + cmd = pipe.readln(); + + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_CLASS); + tot_res = FAILED; + return quitDebuggee(); + } + +/* Create a new ExceptionRequest with false notifyUncaught parameter + so uncaught exceptions should not be reported. */ + log.display("Creating ExceptionEvent request"); + if ((eRequest = createExReq(false, false)) == null) { + tot_res = FAILED; + return quitDebuggee(); + } + + log.display("Starting events listener"); + EventListener elThread = new EventListener(); + elThread.start(); + + log.display("Forcing debuggee to generate uncaught exception"); + counter = 0; + pipe.println(COMMAND_RUN); + + log.display("Waiting for debuggee exits due to uncaught exception"); + debuggee.waitFor(); + + log.display("Waiting for all events recieved"); + try { + if (elThread.isAlive()) elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + e); + tot_res = FAILED; + return quitDebuggee(); + } + + if (counter != 0) { + log.complain("TEST FAILED: uncaught exception " + DEBUGGEE_EXCEPTION + + " was reported by the debugger"); + return FAILED; + } + else return PASSED; + } + + private ExceptionRequest createExReq(boolean notifyC, boolean notifyUnc) { + ExceptionRequest eRequest; + try { + eRequest = erManager.createExceptionRequest(null, notifyC, notifyUnc); + } catch (Exception e) { + log.complain("createExceptionRequest: " + e); + return null; + } + eRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + eRequest.enable(); + return eRequest; + } + + private int quitDebuggee() { + if (eRequest != null) { + eRequest.disable(); + } + + if (elThread != null) { + elThread.isConnected = false; + try { + if (elThread.isAlive()) + elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + } + + pipe.println(COMMAND_QUIT); + + int debStat = debuggee.endDebugee(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } + + class EventListener extends Thread { + public volatile boolean isConnected = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // there is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDeathEvent) { + isConnected = false; + } else if (event instanceof VMDisconnectEvent) { + isConnected = false; + } else if (event instanceof ExceptionEvent) { + ExceptionEvent exEvent = (ExceptionEvent) event; + log.display("EventListener: following ExceptionEvent occured: \n\t" + + exEvent.toString()); + + if (eRequest.equals(event.request())) { + if (exEvent.exception().referenceType().name().equals(DEBUGGEE_EXCEPTION)) { + log.display("Exception event equals to expected \n\t" + + exEvent.exception().referenceType().name()); + counter++; + log.display("\t" + "counter = " + counter); + } + } + } else { + log.display("EventListener: following JDI event occured: \n\t" + + event.toString()); + } + } + if (isConnected) { + eventSet.resume(); + } + } + } while (isConnected); + } catch (InterruptedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + } catch (VMDisconnectedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + e.printStackTrace(); + } + log.display("EventListener: exiting"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007/TestDescription.java new file mode 100644 index 00000000000..64c33265734 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/_itself_/exevent007. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that uncaught exception event is not reported + * by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with false value of boolean parameter notifyUncaught. + * The debugee part of the test raises NumberFormatException in + * another class, which is caught by Method.invoke() and enveloped + * into uncaught InvokationTargetException. + * COMMENTS + * See also bug 4323439 + * -------------------------------- + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * -------------------------------- + * To fix 4615225, + * the test suite was moved here. + * -------------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - quit on VMDeathEvent is added to event handling loop + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent._itself_.exevent007 + * nsk.jdi.ExceptionEvent._itself_.exevent007t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent._itself_.exevent007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007t.java new file mode 100644 index 00000000000..1978c74e054 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent007t.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class exevent007t { + public static void main(String args[]) throws ClassNotFoundException, + NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + exevent007t _exevent007t = new exevent007t(); + System.exit(exevent007.JCK_STATUS_BASE + _exevent007t.communication(args)); + } + + int communication(String args[]) throws ClassNotFoundException, + NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + String command; + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(exevent007.COMMAND_READY); + command = pipe.readln(); + if (command.equals(exevent007.COMMAND_RUN)) { + Class testClass = Class.forName(exevent007.DEBUGGEE_CLASS+"Exception"); + Class methodArgs[] = { String.class }; + Method testMeth = testClass.getMethod("exevent007traiseEx", methodArgs); + Object testInstance = testClass.newInstance(); + Object parameters[] = { "oops!" }; + Object result = testMeth.invoke(testInstance, parameters); + + return exevent007.PASSED; + } else + return exevent007.FAILED; + } +} + +class exevent007tException { + public void exevent007traiseEx(String arg) { + int i = Integer.parseInt(arg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008.java new file mode 100644 index 00000000000..51ea853676a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ExceptionRequest; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.EventIterator; +import com.sun.jdi.event.ExceptionEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.VMDisconnectedException; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that both caught and uncaught exception events + * are properly reported by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with true values of boolean parameters notifyCaught + * and notifyUncaught. + * The debugee part of the test raises two exceptions: + *
  • own caught exevent008tException + *
  • uncaught NumberFormatException in another class + */ + +public class exevent008 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; //milliseconds + + static final String DEBUGGEE_CLASS = "nsk.jdi.ExceptionEvent._itself_.exevent008t"; + static final String DEBUGGEE_EXCEPTION1 = DEBUGGEE_CLASS + "Exception"; +// static final String DEBUGGEE_EXCEPTION2 = "java.lang.NumberFormatException"; + static final String DEBUGGEE_EXCEPTION2 = "java.lang.reflect.InvocationTargetException"; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_TEST1 = "test1"; + static final String COMMAND_TEST2 = "test2"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private EventListener elThread; + private VirtualMachine vm; + private EventRequestManager erManager; + private ExceptionRequest eRequest; + private ReferenceType rType, rTypeEx; + private String cmd; + private int counter1 = 0, counter2 = 0; + private volatile int tot_res = PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); // JCK-style exit status. + } + + public static int run(String argv[], PrintStream out) { + return new exevent008().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "crexreq006t.err> "); + vm = debuggee.VM(); + erManager = vm.eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + cmd = pipe.readln(); + + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + DEBUGGEE_CLASS); + tot_res = FAILED; + return quitDebuggee(); + } + +/* Create a new ExceptionRequest with true notifyCaught and notifyUncaught + parameters so all exceptions should be reported */ + log.display("Creating ExceptionEvent request"); + if ((eRequest = createExReq(true, true)) == null) { + tot_res = FAILED; + return quitDebuggee(); + } + + log.display("Starting events listener"); + EventListener elThread = new EventListener(); + elThread.start(); + + log.display("Forcing debuggee to generate caught exception"); + counter1 = 0; + pipe.println(COMMAND_TEST1); + + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = FAILED; + return quitDebuggee(); + } + log.display("Exception caught"); + + log.display("Forcing debuggee to generate uncaught exception"); + counter1 = 0; + pipe.println(COMMAND_TEST2); + + log.display("Waiting for debuggee exits due to uncaught exception"); + debuggee.waitFor(); + log.display("Debuggee exited"); + + log.display("Waiting for all events recieved"); + try { + if (elThread.isAlive()) elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + e); + tot_res = FAILED; + return quitDebuggee(); + } + + if (counter1 == 0) { + log.complain("TEST FAILED: caught exception " + DEBUGGEE_EXCEPTION1 + + " was not reported by the debugger"); + tot_res = FAILED; + } + if (counter2 == 0) { + log.complain("TEST FAILED: uncaught exception " + DEBUGGEE_EXCEPTION2 + + " was not reported by the debugger"); + tot_res = FAILED; + } + + return tot_res; + } + + private ExceptionRequest createExReq(boolean notifyC, boolean notifyUnc) { + ExceptionRequest eRequest; + try { + eRequest = erManager.createExceptionRequest(null, notifyC, notifyUnc); + } catch (Exception e) { + log.complain("createExceptionRequest: " + e); + return null; + } + eRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + eRequest.enable(); + return eRequest; + } + + private int quitDebuggee() { + if (eRequest != null) { + eRequest.disable(); + } + + if (elThread != null) { + elThread.isConnected = false; + try { + if (elThread.isAlive()) + elThread.join(); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException " + + e); + tot_res = FAILED; + } + } + + pipe.println(COMMAND_QUIT); + + int debStat = debuggee.endDebugee(); + if (debStat != (JCK_STATUS_BASE + PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = FAILED; + } else + log.display("Debuggee's process finished with status: " + + debStat); + + return tot_res; + } + + class EventListener extends Thread { + public volatile boolean isConnected = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // there is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDeathEvent) { + isConnected = false; + } else if (event instanceof VMDisconnectEvent) { + isConnected = false; + } else if (event instanceof ExceptionEvent) { + ExceptionEvent exEvent = (ExceptionEvent) event; + log.display("EventListener: following ExceptionEvent occured: \n\t" + + exEvent.toString()); + + if (eRequest.equals(event.request())) { + if (exEvent.exception().referenceType().name().equals(DEBUGGEE_EXCEPTION1)) { + log.display("CException event equals to expected for caught exception\n\t" + + exEvent.exception().referenceType().name()); + counter1++; + log.display("\t" + "counter1 = " + counter1); + } else if (exEvent.exception().referenceType().name().equals(DEBUGGEE_EXCEPTION2)) { + log.display("Exception event equals to expected for uncaught exception\n\t" + + exEvent.exception().referenceType().name()); + counter2++; + log.display("\t" + "counter2 = " + counter2); + } + } + } else { + log.display("EventListener: following JDI event occured: \n\t" + + event.toString()); + } + } + if (isConnected) { + eventSet.resume(); + } + } + } while (isConnected); + } catch (InterruptedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + } catch (VMDisconnectedException e) { + tot_res = FAILED; + log.complain("FAILURE in EventListener: caught unexpected " + + e); + e.printStackTrace(); + } + log.display("EventListener: exiting"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008/TestDescription.java new file mode 100644 index 00000000000..d47cecc3e18 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/_itself_/exevent008. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that both caught and uncaught exception events + * are properly reported by the debugger. It calls + * com.sun.jdi.request.EventRequestManager.createExceptionRequest() + * method with true values of boolean parameters notifyCaught and + * notifyUncaught. + * The debugee part of the test raises two exceptions: + * - caught own exevent008tException; + * - uncaught InvokationTargetException with enveloped NumberFormatException + * in another class + * COMMENTS + * See also bug 4323439 + * -------------------------------- + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * -------------------------------- + * To fix 4615225, + * the test suite was moved here. + * -------------------------------- + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - quit on VMDeathEvent is added to event handling loop + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent._itself_.exevent008 + * nsk.jdi.ExceptionEvent._itself_.exevent008t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent._itself_.exevent008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008t.java new file mode 100644 index 00000000000..72b3bbcf129 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/_itself_/exevent008t.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ExceptionEvent._itself_; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class exevent008t { + public static void main(String args[]) throws ClassNotFoundException, + NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + exevent008t _exevent008t = new exevent008t(); + System.exit(exevent008.JCK_STATUS_BASE + _exevent008t.communication(args)); + } + + private static void raiseEx() throws exevent008tException { + throw new exevent008tException(); + } + + static void raiseException(int testCase) throws ClassNotFoundException, + NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + switch(testCase) { + case 1: // raise own Exception then catch it + try { + raiseEx(); + } catch (exevent008tException e) {} + break; + case 2: // raise uncaught InvokationTargerexception with enveloped + // NumberFormatException in another class + Class testClass = Class.forName(exevent008.DEBUGGEE_CLASS+"NFException"); + Class args[] = { String.class }; + Method testMeth = testClass.getMethod("exevent008traiseEx", args); + Object testInstance = testClass.newInstance(); + Object parameters[] = { "oops!" }; + Object result = testMeth.invoke(testInstance, parameters); + break; + } + } + + int communication(String args[]) throws ClassNotFoundException, + NoSuchMethodException, + InstantiationException, + IllegalAccessException, + InvocationTargetException { + String command; + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + do { + pipe.println(exevent008.COMMAND_READY); + command = pipe.readln(); + if (command.equals(exevent008.COMMAND_TEST1)) { + raiseException(1); + } else if (command.equals(exevent008.COMMAND_TEST2)) { + raiseException(2); + } else if (command.equals(exevent008.COMMAND_QUIT)) { + break; + } else { + System.err.println("TEST BUG: Debugee: unknown command: " + + command); + return exevent008.FAILED; + } + } while(true); + return exevent008.PASSED; + } +} + +class exevent008tException extends Exception {} + +class exevent008tNFException { + public void exevent008traiseEx(String arg) { + int i = Integer.parseInt(arg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001.java new file mode 100644 index 00000000000..1d18901dcda --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001.java @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionEvent.catchLocation; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class location001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // time interval to wait for events + static final int TIMEOUT_DELTA = 1000; // milliseconds + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + static final String COMMAND_ERROR = "error"; + + // checked classes names + static final String DEBUGGEE_NAME = "nsk.jdi.ExceptionEvent.catchLocation.location001a"; + + static final String USER_EXCEPTION = DEBUGGEE_NAME + "Exception"; + static final String USER_ERROR = DEBUGGEE_NAME + "Error"; + static final String USER_THROWABLE = DEBUGGEE_NAME + "Throwable"; + static final String JAVA_EXCEPTION = "java.lang.NumberFormatException"; + static final String JAVA_ERROR = "java.lang.StackOverflowError"; + + // scaffold objects + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + // timeout for waiting events + static private long eventTimeout; + + // mirrors for checked classes and threads in debuggee + static private ExceptionRequest checkedRequest; + static private ReferenceType checkedClass; + static private ThreadReference checkedThread; + + static private ReferenceType userException; + static private ReferenceType userError; + static private ReferenceType userThrowable; + + + // results of receiving particular events + static private boolean userExceptionReceived; + static private boolean userErrorReceived; + static private boolean userThrowableReceived; + static private boolean javaExceptionReceived; + static private boolean javaErrorReceived; + + // results of test execution + static private boolean eventsReceived; + static private boolean testFailed; + + // flag for EventHandler thread + static private volatile boolean exceptionsThrown; + + // execute test from command line + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + // execute test from JCK-compatible harness + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + userExceptionReceived = false; + userErrorReceived = false; + userThrowableReceived = false; + javaExceptionReceived = false; + javaErrorReceived = false; + eventsReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "location001a >"); + + // create synchronization channel with debuggee + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + // catch exceptions while testing and finally quit debuggee + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirrors of checked classes in debuggee + log.display("Getting loaded classes in debuggee"); + if ((checkedClass = debuggee.classByName(DEBUGGEE_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + DEBUGGEE_NAME); + } + + if ((userException = debuggee.classByName(USER_EXCEPTION)) == null) { + throw new Failure("TEST BUG: cannot find " + USER_EXCEPTION); + } + + if ((userError = debuggee.classByName(USER_ERROR)) == null) { + throw new Failure("TEST BUG: cannot find " + USER_ERROR); + } + + if ((userThrowable = debuggee.classByName(USER_THROWABLE)) == null) { + throw new Failure("TEST BUG: cannot find " + USER_THROWABLE); + } + + // get mirror of main thread in debuggee + log.display("Getting reference to main thread"); + Iterator threadIterator = vm.allThreads().iterator(); + while (threadIterator.hasNext()) { + ThreadReference curThread = (ThreadReference) threadIterator.next(); + if (curThread.name().equals("main")) { + checkedThread = curThread; + } + } + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + // create ExceptionRequest for all throwable classes (initially disabled) + log.display("Creating ExceptionRequest"); + boolean notifyCaught = true; + boolean notifyUncaught = true; + if ((checkedRequest = erManager.createExceptionRequest(null, notifyCaught, notifyUncaught)) == null) { + throw new Failure("TEST BUG: unable to create ExceptionRequest"); + } + + // define separate thread for handling received events + class EventHandler extends Thread { + public void run() { + // handle events until all exceptions thrown and + // all expected events received + while (!(exceptionsThrown && eventsReceived)) { + eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (InterruptedException e) { + log.complain("Unexpected InterruptedException while receiving event: " + e); + break; + } + + if (eventSet == null) { + continue; + } + + // handle each event from event set + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + if (EventFilters.filtered(event)) + continue; + + // handle ExceptionEvent + if (event instanceof ExceptionEvent) { + + ExceptionEvent castedEvent = (ExceptionEvent)event; + ReferenceType eventRefType = castedEvent.exception().referenceType(); + Location eventLocation = castedEvent.location(); + Location eventCatchLocation = castedEvent.catchLocation(); + + if (eventRefType.equals(userException)) { + log.display("ExceptionEvent for " + USER_EXCEPTION + " is received"); + userExceptionReceived = true; + if (eventLocation.lineNumber() != location001a.userExceptionLocation) { + log.complain("FAILURE 1: incorrect location for " + USER_EXCEPTION + + "\nexpected: " + location001a.userExceptionLocation + ", got: " + eventLocation.lineNumber()); + testFailed = true; + } + if (eventCatchLocation.lineNumber() != location001a.userExceptionCatchLocation) { + log.complain("FAILURE 1: incorrect catchLocation for " + USER_EXCEPTION + + "\nexpected: " + location001a.userExceptionCatchLocation + ", got: " + eventCatchLocation.lineNumber()); + testFailed = true; + } + if (!(eventLocation.declaringType().equals(checkedClass))) { + log.complain("FAILURE 2: catchLocation.declaringType() does not equal to debuggee class:"); + testFailed = true; + log.complain(eventLocation.declaringType().name()); + } + + } else if (eventRefType.equals(userError)) { + log.display("ExceptionEvent for " + USER_ERROR + " is received"); + userErrorReceived = true; + if (eventLocation.lineNumber() != location001a.userErrorLocation) { + log.complain("FAILURE 3: incorrect location for " + USER_ERROR + + "\nexpected: " + location001a.userErrorLocation + ", got: " + eventLocation.lineNumber()); + testFailed = true; + } + if (eventCatchLocation.lineNumber() != location001a.userErrorCatchLocation) { + log.complain("FAILURE 3: incorrect catchLocation for " + USER_ERROR + + "\nexpected: " + location001a.userErrorCatchLocation + ", got: " + eventCatchLocation.lineNumber()); + testFailed = true; + } + if (!(eventLocation.declaringType().equals(checkedClass))) { + log.complain("FAILURE 4: catchLocation.declaringType() does not equal to debuggee class:"); + testFailed = true; + log.complain(eventLocation.declaringType().name()); + } + + } else if (eventRefType.equals(userThrowable)) { + log.display("ExceptionEvent for " + USER_THROWABLE + " is received"); + userThrowableReceived = true; + if (eventLocation.lineNumber() != location001a.userThrowableLocation) { + log.complain("FAILURE 5: incorrect location for " + USER_THROWABLE + + "\nexpected: " + location001a.userThrowableLocation + ", got: " + eventLocation.lineNumber()); + testFailed = true; + } + if (eventCatchLocation.lineNumber() != location001a.userThrowableCatchLocation) { + log.complain("FAILURE 5: incorrect catchLocation for " + USER_THROWABLE + + "\nexpected: " + location001a.userThrowableCatchLocation + ", got: " + eventCatchLocation.lineNumber()); + testFailed = true; + } + if (!(eventLocation.declaringType().equals(checkedClass))) { + log.complain("FAILURE 6: catchLocation.declaringType() does not equal to debuggee class:"); + testFailed = true; + log.complain(eventLocation.declaringType().name()); + } + } else { + String eventTypeName = eventRefType.name(); + if (eventTypeName.equals(JAVA_EXCEPTION)) { + log.display("ExceptionEvent for " + JAVA_EXCEPTION + " is received"); + javaExceptionReceived = true; + if (eventCatchLocation.lineNumber() != location001a.javaExceptionCatchLocation) { + log.complain("FAILURE 7: incorrect catchLocation for " + JAVA_EXCEPTION + + "\nexpected: " + location001a.javaExceptionCatchLocation + ", got: " + eventCatchLocation.lineNumber()); + testFailed = true; + } + + } else if (eventTypeName.equals(JAVA_ERROR)) { + log.display("ExceptionEvent for " + JAVA_ERROR + " is received"); + javaErrorReceived = true; + if (eventCatchLocation.lineNumber() != location001a.javaErrorCatchLocation) { + log.complain("FAILURE 8: incorrect catchLocation for " + JAVA_ERROR + + "\nexpected: " + location001a.javaErrorCatchLocation + ", got: " + eventCatchLocation.lineNumber()); + testFailed = true; + } + } + } + } + + // ignore each other events + + } // end of event handling loop + + log.display("Resuming event set"); + eventSet.resume(); + + // check if all expected events received + eventsReceived = userExceptionReceived && userErrorReceived + && userThrowableReceived && javaExceptionReceived + && javaErrorReceived; + + } // end of event set handling loop + + log.display("eventHandler completed"); + + } // end of run() + + } // end of EventHandler + + // start EventHandler thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // enable event request + log.display("Enabling ExceptionRequest"); + checkedRequest.enable(); + + // force debuggee to throw exceptions and generate events + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // wait for debuggee completed test case + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (command.equals(COMMAND_ERROR)) { + throw new Failure("TEST BUG: Unable to thrown all exceptions in debuggee"); + } + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // notify EventHandler that all checked exceptions thrown in debuggee + exceptionsThrown = true; + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // complain if not all expected events received + if (!userExceptionReceived) { + log.complain("FAILURE 9: " + USER_EXCEPTION + " was not received received"); + testFailed= true; + } + if (!userErrorReceived) { + log.complain("FAILURE 10: " + USER_ERROR + " was not received received"); + testFailed= true; + } + if (!userThrowableReceived) { + log.complain("FAILURE 11: " + USER_THROWABLE + " was not received received"); + testFailed= true; + } + if (!javaExceptionReceived) { + log.complain("FAILURE 12: " + JAVA_EXCEPTION + " was not received received"); + testFailed= true; + } + if (!javaErrorReceived) { + log.complain("FAILURE 13: " + JAVA_ERROR + " was not received received"); + testFailed= true; + } + + // end testing + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // disable event request to prevent appearance of further events + if (checkedRequest != null && checkedRequest.isEnabled()) { + log.display("Disabling event request"); + checkedRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001/TestDescription.java new file mode 100644 index 00000000000..2335be6dd6f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location001/TestDescription.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/catchLocation/location001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exercises + * com.sun.jdi.event.ExceptionEvent.catchLocation() method. + * The test checks the following assertion: + * - method ExceptionEvent.catchLocation() returns for the caught + * Throwable object a correct Location reference to the first code + * index in the appropriate catch clause of enclosing try statement. + * A debugger class - nsk.jdi.ExceptionEvent.catchLocation.location001 ; + * a debuggee class - nsk.jdi.ExceptionEvent.catchLocation.location001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger launches and connects to debuggee, waits for it started, and + * creates the ExceptionRequest with true and + * parameters, which is disabled by default. + * The debugger defines separate thread for listening received + * events, cleans EventQueue, starts , enables ExceptionRequest, + * sends debuggee command to force it to throw exception, and waits for + * notification that all exceptions are thrown. + * Upon receiving command from debugger, the debuggee raises several + * exceptions and errors. All these exceptions and errors are enclosed in + * separate try-catch blocks. Debuggee verifies that all exceptions are + * really thrown and notifies debugger by sending command or . + * Each received event is handled by separate thread. + * For each ExceptionEvent assertions of the test are verified. + * After command received from debuggee, debugger notifies + * that all checked exceptions have been thrown and waits for + * receives all expected events. If not all events received for WAITIME interval, + * debugger interrupts thread and complains about an error. + * Finally, debugger disables event request, sends debuggee command from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: unknown command: " + command); + return FAILED; + } + + // throw checked exceptions + try { + try { + throw new location001aException(); // userExceptionLocation + } catch (location001aException e) { // <= expected catch location due to evaluation of 4740123. // userExceptionLocation + log.display("location001aException is thrown"); + userExceptionThrown = true; + } + + try { + throw new location001aError(); // userErrorLocation + } catch (location001aError e) { // <= expected catch location due to evaluation of 4740123. // userErrorCatchLocation + log.display("location001aError is thrown"); + userErrorThrown = true; + } + + try { + throw new location001aThrowable(); // userThrowableLocation + } catch (location001aThrowable e) { // <= expected catch location due to evaluation of 4740123. // userThrowableCatchLocation + log.display("location001aThrowable is thrown"); + userThrowableThrown = true; + } + + try { + int i = Integer.parseInt("foo"); + } catch (NumberFormatException e) { // <= expected catch location due to evaluation of 4740123. // userThrowableCatchLocation + log.display("NumberFormatException is thrown"); + javaExceptionThrown = true; + } + + try { + raiseStackOverflow(); + } catch (StackOverflowError e) { // <= expected catch location due to evaluation of 4740123. // javaErrorCatchLocation + log.display("StackOverflowError is thrown"); + javaErrorThrown = true; + } + + } catch (Throwable e) { + log.complain("Unexpected Throwable: " + e.getMessage()); + e.printStackTrace(); + if (e instanceof ThreadDeath) { + throw e; + } + } + + // check that all exceptions are thrown + boolean thrown = true; + if (!userExceptionThrown) { + log.complain("TEST BUG: user exception NOT thrown"); + thrown = false; + } + if (!userErrorThrown) { + log.complain("TEST BUG: user error NOT thrown"); + thrown = false; + } + if (!userThrowableThrown) { + log.complain("TEST BUG: user Throwable NOT thrown"); + thrown = false; + } + if (!javaExceptionThrown) { + log.complain("TEST BUG: java exception NOT thrown"); + thrown = false; + } + if (!javaErrorThrown) { + log.complain("TEST BUG: java error NOT thrown"); + thrown = false; + } + + // notify debugger whether all exceptions thrown or not + if (thrown) { + pipe.println(COMMAND_DONE); + } else { + pipe.println(COMMAND_ERROR); + } + + // wait for command from debugger and exit + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + log.complain("TEST BUG: unknown command: " + command); + return FAILED; + } + + return PASSED; + } + + private void raiseStackOverflow () { + raiseStackOverflow(); + } +} + +class location001aException extends Exception {} + +class location001aError extends Error {} + +class location001aThrowable extends Throwable {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002.java new file mode 100644 index 00000000000..e73874989bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionEvent.catchLocation; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class location002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // time interval to wait for events + static final int TIMEOUT_DELTA = 1000; // milliseconds + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + static final String COMMAND_ERROR = "error"; + + // checked classes names + static final String DEBUGGEE_NAME = "nsk.jdi.ExceptionEvent.catchLocation.location002a"; + static final String JAVA_EXCEPTION = "java.lang.NumberFormatException"; + + // scaffold objects + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + // timeout for waiting events + static private long eventTimeout; + + // mirrors for checked classes and threads in debuggee + static private ExceptionRequest checkedRequest; + static private ReferenceType checkedClass; + static private ThreadReference checkedThread; + + // results of test execution + static private boolean eventsReceived; + static private boolean testFailed; + + // execute test from command line + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + // execute test from JCK-compatible harness + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "location001a >"); + + // create synchronization channel with debuggee + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + // catch exceptions while testing and finally quit debuggee + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirrors of checked classes in debuggee + log.display("Getting loaded classes in debuggee"); + if ((checkedClass = debuggee.classByName(DEBUGGEE_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + DEBUGGEE_NAME); + } + + // get mirror of main thread in debuggee + log.display("Getting reference to main thread"); + Iterator threadIterator = vm.allThreads().iterator(); + while (threadIterator.hasNext()) { + ThreadReference curThread = (ThreadReference) threadIterator.next(); + if (curThread.name().equals("main")) { + checkedThread = curThread; + } + } + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + // create ExceptionRequest for all throwable classes (initially disabled) + log.display("Creating ExceptionRequest"); + boolean notifyCaught = true; + boolean notifyUncaught = true; + if ((checkedRequest = erManager.createExceptionRequest(null, notifyCaught, notifyUncaught)) == null) { + throw new Failure("TEST BUG: unable to create ExceptionRequest"); + } + + // define separate thread for handling received events + class EventHandler extends Thread { + public void run() { + // handle events until expected event received + eventHandlingLoop: + while (!eventsReceived) { + eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (InterruptedException e) { + log.complain("Unexpected InterruptedException while receiving event: " + e); + break; + } + + if (eventSet == null) { + continue; + } + + // handle each event from event set + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); +// log.display("Event received:\n " + event); + + // break event handling loop if VMDisconnectEvent received + if (event instanceof VMDisconnectEvent) { + log.display("VMDisconnectEvent received"); + break eventHandlingLoop; + } + + // handle ExceptionEvent + if (event instanceof ExceptionEvent) { + log.display("ExceptionEvent received"); + + ExceptionEvent castedEvent = (ExceptionEvent)event; + ReferenceType eventRefType = castedEvent.exception().referenceType(); + + String eventTypeName = eventRefType.name(); + if (eventTypeName.equals(JAVA_EXCEPTION)) { + log.display("Expected ExceptionEvent for " + JAVA_EXCEPTION + " is received"); + eventsReceived = true; + + Location catchLocation = castedEvent.catchLocation(); + if (catchLocation != null) { + log.complain("FAILURE 1: catchLocation for uncaught " + JAVA_EXCEPTION + + " is not null :"); + log.complain("declaring type: " + catchLocation.declaringType().name()); + log.complain("line number : " + catchLocation.lineNumber()); + } + + } + } + + // ignore each other events + + } // end of event handling loop + +// log.display("Resuming event set"); + eventSet.resume(); + + } // end of event set handling loop + + log.display("eventHandler completed"); + + } // end of run() + + } // end of EventHandler + + // start EventHandler thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // enable event request + log.display("Enabling ExceptionRequest"); + checkedRequest.enable(); + + // force debuggee to throw exceptions and generate events + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // complain if not all expected events received + if (!eventsReceived) { + log.complain("FAILURE 2: " + JAVA_EXCEPTION + " was not received"); + testFailed= true; + } + + // end testing + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + log.display("Debuggee terminated with exit code: " + debuggeeStatus); + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002/TestDescription.java new file mode 100644 index 00000000000..14111b15adf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/catchLocation/location002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exercises + * com.sun.jdi.event.ExceptionEvent.catchLocation() method. + * The test checks the following assertion: + * - method ExceptionEvent.catchLocation() returns null for + * uncaught exception. + * A debugger class - nsk.jdi.ExceptionEvent.catchLocation.location002 ; + * a debuggee class - nsk.jdi.ExceptionEvent.catchLocation.location002a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates and enables the ExceptionRequest with true + * and parameters. + * The debugger starts thread for listening events delivered + * from the debuggee. + * Upon receiving command from debugger, the debuggee raises uncaught + * NumberFormatException. + * The debugger switches to to listen the event during the + * time specified by parameter. If debugger receives + * ExceptionEvent, it checks the assertion of the test. The test fails + * if this check fails or no expected ExceptionEvent received. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionEvent.catchLocation.location002 + * nsk.jdi.ExceptionEvent.catchLocation.location002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionEvent.catchLocation.location002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002a.java new file mode 100644 index 00000000000..a0c21394079 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionEvent.catchLocation; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; +import java.lang.Integer.*; + +// This class is the debugged application in the test + +class location002a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + static final String COMMAND_ERROR = "error"; + + // start debuggee + public static void main(String args[]) throws Throwable { + location002a _location002a = new location002a(); + System.exit(JCK_STATUS_BASE + _location002a.runIt(args, System.err)); + } + + // perform debugee execution + int runIt(String args[], PrintStream out) throws Throwable { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Log log = new Log(out, argHandler); + + // notify debuggeer that debuggee started + pipe.println(COMMAND_READY); + + // wait for command from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: unknown command: " + command); + return FAILED; + } + + // throw uncaught exception, which should terminate debuggee + System.err.println("Raising NumberFormatException"); + int i = Integer.parseInt("foo"); + + // return FAILED if not terminated by uncaught exception + return FAILED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001.java new file mode 100644 index 00000000000..f2730bdac18 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001.java @@ -0,0 +1,701 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionEvent.exception; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class exception001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // time interval to wait for events + static final int TIMEOUT_DELTA = 1000; // milliseconds + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + static final String COMMAND_ERROR = "error"; + + // checked classes names + static final String DEBUGGEE_NAME = "nsk.jdi.ExceptionEvent.exception.exception001a"; + + static final String USER_EXCEPTION = DEBUGGEE_NAME + "Exception"; + static final String USER_ERROR = DEBUGGEE_NAME + "Error"; + static final String USER_THROWABLE = DEBUGGEE_NAME + "Throwable"; + static final String JAVA_EXCEPTION = "java.lang.NumberFormatException"; + static final String JAVA_ERROR = "java.lang.StackOverflowError"; + + // scaffold objects + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + // timeout for waiting events + static private long eventTimeout; + + // mirrors for checked classes and threads in debuggee + static private ExceptionRequest checkedRequest; + static private ReferenceType checkedClass; + static private ThreadReference checkedThread; + + static private ReferenceType userException; + static private ReferenceType userError; + static private ReferenceType userThrowable; + + + // results of receiving particular events + static private boolean userExceptionReceived; + static private boolean userErrorReceived; + static private boolean userThrowableReceived; + static private boolean javaExceptionReceived; + static private boolean javaErrorReceived; + + // results of test execution + static private boolean eventsReceived; + static private boolean testFailed; + + // flag for EventHandler thread + static private volatile boolean exceptionsThrown; + + // execute test from command line + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + // execute test from JCK-compatible harness + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + userExceptionReceived = false; + userErrorReceived = false; + userThrowableReceived = false; + javaExceptionReceived = false; + javaErrorReceived = false; + eventsReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "exception001a >"); + + // create synchronization channel with debuggee + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + EventRequestManager erManager = vm.eventRequestManager(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + // catch exceptions while testing and finally quit debuggee + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirrors of checked classes in debuggee + log.display("Getting loaded classes in debuggee"); + if ((checkedClass = debuggee.classByName(DEBUGGEE_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + DEBUGGEE_NAME); + } + + if ((userException = debuggee.classByName(USER_EXCEPTION)) == null) { + throw new Failure("TEST BUG: cannot find " + USER_EXCEPTION); + } + + if ((userError = debuggee.classByName(USER_ERROR)) == null) { + throw new Failure("TEST BUG: cannot find " + USER_ERROR); + } + + if ((userThrowable = debuggee.classByName(USER_THROWABLE)) == null) { + throw new Failure("TEST BUG: cannot find " + USER_THROWABLE); + } + + // get mirror of main thread in debuggee + log.display("Getting reference to main thread"); + Iterator threadIterator = vm.allThreads().iterator(); + while (threadIterator.hasNext()) { + ThreadReference curThread = (ThreadReference) threadIterator.next(); + if (curThread.name().equals("main")) { + checkedThread = curThread; + } + } + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + // create ExceptionRequest for all throwable classes (initially disabled) + log.display("Creating ExceptionRequest"); + boolean notifyCaught = true; + boolean notifyUncaught = true; + if ((checkedRequest = erManager.createExceptionRequest(null, notifyCaught, notifyUncaught)) == null) { + throw new Failure("TEST BUG: unable to create ExceptionRequest"); + } + + // define separate thread for handling received events + class EventHandler extends Thread { + public void run() { + // handle events until all exceptions thrown and + // all expected events received + while (!(exceptionsThrown && eventsReceived)) { + eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (InterruptedException e) { + log.complain("Unexpected InterruptedException while receiving event: " + e); + break; + } + + if (eventSet == null) { + continue; + } + + // handle each event from event set + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + if (EventFilters.filtered(event)) + continue; + + // handle ExceptionEvent + if (event instanceof ExceptionEvent) { + + ExceptionEvent castedEvent = (ExceptionEvent)event; + + ObjectReference eventThrowable = castedEvent.exception(); + if (eventThrowable == null) { + log.complain("FAILURE 1: ExceptionEvent.exception() returns null"); + testFailed = true; + } else { + ReferenceType eventRefType = castedEvent.exception().referenceType(); + if (eventRefType.equals(userException)) { + log.display("ExceptionEvent for " + USER_EXCEPTION + " is received"); + userExceptionReceived = true; + + Location eventLocation = castedEvent.location(); + if (!(eventLocation.declaringType().name().equals(DEBUGGEE_NAME))) { + log.complain("FAILURE 2: eventLocation.declaringType() does not equal to debuggee class"); + testFailed = true; + } + + } else if (eventRefType.equals(userError)) { + log.display("ExceptionEvent for " + USER_ERROR + " is received"); + userErrorReceived = true; + + Location eventLocation = castedEvent.location(); + if (!(eventLocation.declaringType().name().equals(DEBUGGEE_NAME))) { + log.complain("FAILURE 2: eventLocation.declaringType() does not equal to debuggee class"); + testFailed = true; + } + + } else if (eventRefType.equals(userThrowable)) { + log.display("ExceptionEvent for " + USER_THROWABLE + " is received"); + userThrowableReceived = true; + + Location eventLocation = castedEvent.location(); + if (!(eventLocation.declaringType().name().equals(DEBUGGEE_NAME))) { + log.complain("FAILURE 2: eventLocation.declaringType() does not equal to debuggee class"); + testFailed = true; + } + + } else { + String eventTypeName = eventRefType.name(); + if (eventTypeName.equals(JAVA_EXCEPTION)) { + log.display("ExceptionEvent for " + JAVA_EXCEPTION + " is received"); + javaExceptionReceived = true; + } else if (eventTypeName.equals(JAVA_ERROR)) { + log.display("ExceptionEvent for " + JAVA_ERROR + " is received"); + javaErrorReceived = true; + } + } + } + + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 4: eventRequest does not equal to checked request"); + testFailed = true; + } + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 5: eventThread does not equal to checked thread"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 6: eventVirtualMachine does not equal to checked vm"); + testFailed = true; + } + } + + // ignore each other events + + } // end of event handling loop + + log.display("Resuming event set"); + eventSet.resume(); + + // check if all expected events received + eventsReceived = userExceptionReceived && userErrorReceived + && userThrowableReceived && javaExceptionReceived + && javaErrorReceived; + + } // end of event set handling loop + + log.display("eventHandler completed"); + + } // end of run() + + } // end of EventHandler + + // start EventHandler thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // enable event request + log.display("Enabling ExceptionRequest"); + checkedRequest.enable(); + + // force debuggee to throw exceptions and generate events + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // wait for debuggee completed test case + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (command.equals(COMMAND_ERROR)) { + throw new Failure("TEST BUG: Unable to thrown all exceptions in debuggee"); + } + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // notify EventHandler that all checked exceptions thrown in debuggee + exceptionsThrown = true; + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // complain if not all expected events received + if (!userExceptionReceived) { + log.complain("FAILURE 9: " + USER_EXCEPTION + " was not received received"); + testFailed= true; + } + if (!userErrorReceived) { + log.complain("FAILURE 10: " + USER_ERROR + " was not received received"); + testFailed= true; + } + if (!userThrowableReceived) { + log.complain("FAILURE 11: " + USER_THROWABLE + " was not received received"); + testFailed= true; + } + if (!javaExceptionReceived) { + log.complain("FAILURE 12: " + JAVA_EXCEPTION + " was not received received"); + testFailed= true; + } + if (!javaErrorReceived) { + log.complain("FAILURE 13: " + JAVA_ERROR + " was not received received"); + testFailed= true; + } + + // end testing + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // disable event request to prevent appearance of further events + if (checkedRequest != null && checkedRequest.isEnabled()) { + log.display("Disabling event request"); + checkedRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} + + +/* +// This class is the debugger in the test + +public class exception001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String DEBUGGEE_NAME = "nsk.jdi.ExceptionEvent.exception.exception001a"; + static final String USER_EXCEPTION = DEBUGGEE_NAME + "Exception"; + static final String USER_ERROR = DEBUGGEE_NAME + "Error"; + static final String USER_THROWABLE = DEBUGGEE_NAME + "Throwable"; + static final String JAVA_EXCEPTION = "java.lang.NumberFormatException"; + static final String JAVA_ERROR = "java.lang.StackOverflowError"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private ExceptionRequest checkedRequest; + static private ReferenceType checkedClass; + static private ThreadReference checkedThread; + + static private ReferenceType userException; + static private ReferenceType userError; + static private ReferenceType userThrowable; + static private boolean userExceptionReceived; + static private boolean userErrorReceived; + static private boolean userThrowableReceived; + static private boolean javaExceptionReceived; + static private boolean javaErrorReceived; + + static private boolean testFailed; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + userExceptionReceived = false; + userErrorReceived = false; + userThrowableReceived = false; + javaExceptionReceived = false; + javaErrorReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "exception001a >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + + log.display("Resuming debuggee"); + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + + while (true) { + + if (!command.equals(COMMAND_READY)) { + log.complain("TEST BUG: unexpected debuggee's command: " + command); + testFailed = true; + break; + } + + log.display("Getting loaded classes in debuggee"); + if ((checkedClass = debuggee.classByName(DEBUGGEE_NAME)) == null) { + log.complain("TEST BUG: cannot find " + DEBUGGEE_NAME); + testFailed = true; + break; + } + + if ((userException = debuggee.classByName(USER_EXCEPTION)) == null) { + log.complain("TEST BUG: cannot find " + USER_EXCEPTION); + testFailed = true; + break; + } + + if ((userError = debuggee.classByName(USER_ERROR)) == null) { + log.complain("TEST BUG: cannot find " + USER_ERROR); + testFailed = true; + break; + } + + if ((userThrowable = debuggee.classByName(USER_THROWABLE)) == null) { + log.complain("TEST BUG: cannot find " + USER_THROWABLE); + testFailed = true; + break; + } + + log.display("Getting reference to main thread"); + Iterator threadIterator = vm.allThreads().iterator(); + while (threadIterator.hasNext()) { + ThreadReference curThread = (ThreadReference) threadIterator.next(); + if (curThread.name().equals("main")) { + checkedThread = curThread; + } + } + if (checkedThread == null) { + log.complain("TEST BUG: unable to find reference to main thread"); + testFailed = true; + break; + } + + log.display("Creating ExceptionRequest"); + boolean notifyCaught = true; + boolean notifyUncaught = true; + if ((checkedRequest = erManager.createExceptionRequest(null, notifyCaught, notifyUncaught)) == null) { + log.complain("TEST BUG: unable to create ExceptionRequest"); + testFailed = true; + break; + } + + //checkedRequest.addClassFilter(checkedClass); + checkedRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + checkedRequest.enable(); + log.display("ExceptionRequest is created"); + + break; + } + if (testFailed) { + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + log.display("Waiting for debuggee terminating"); + debuggee.waitFor(); + return FAILED; + } + + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + isConnected: + while (true) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + if (event instanceof VMDisconnectEvent) { + break isConnected; + } + + if (event instanceof ExceptionEvent) { + + ExceptionEvent castedEvent = (ExceptionEvent)event; + + ObjectReference eventThrowable = castedEvent.exception(); + if (eventThrowable == null) { + log.complain("FAILURE 1: ExceptionEvent.exception() returns null"); + testFailed = true; + } else { + ReferenceType eventRefType = castedEvent.exception().referenceType(); + if (eventRefType.equals(userException)) { + log.display("ExceptionEvent for " + USER_EXCEPTION + " is received"); + userExceptionReceived = true; + + Location eventLocation = castedEvent.location(); + if (!(eventLocation.declaringType().name().equals(DEBUGGEE_NAME))) { + log.complain("FAILURE 2: eventLocation.declaringType() does not equal to debuggee class"); + testFailed = true; + } + + } else if (eventRefType.equals(userError)) { + log.display("ExceptionEvent for " + USER_ERROR + " is received"); + userErrorReceived = true; + + Location eventLocation = castedEvent.location(); + if (!(eventLocation.declaringType().name().equals(DEBUGGEE_NAME))) { + log.complain("FAILURE 2: eventLocation.declaringType() does not equal to debuggee class"); + testFailed = true; + } + + } else if (eventRefType.equals(userThrowable)) { + log.display("ExceptionEvent for " + USER_THROWABLE + " is received"); + userThrowableReceived = true; + + Location eventLocation = castedEvent.location(); + if (!(eventLocation.declaringType().name().equals(DEBUGGEE_NAME))) { + log.complain("FAILURE 2: eventLocation.declaringType() does not equal to debuggee class"); + testFailed = true; + } + + } else { + String eventTypeName = eventRefType.name(); + if (eventTypeName.equals(JAVA_EXCEPTION)) { + log.display("ExceptionEvent for " + JAVA_EXCEPTION + " is received"); + javaExceptionReceived = true; + } else if (eventTypeName.equals(JAVA_ERROR)) { + log.display("ExceptionEvent for " + JAVA_ERROR + " is received"); + javaErrorReceived = true; + } + } + } + + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 4: eventRequest does not equal to checked request"); + testFailed = true; + } + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 5: eventThread does not equal to checked thread"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 6: eventVirtualMachine does not equal to checked vm"); + testFailed = true; + } + } + } + eventSet.resume(); + } + } catch (InterruptedException e) { + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + log.display("Waiting for debuggee terminating"); + debuggee.waitFor(); + + if (!userExceptionReceived) { + log.complain("FAILURE 7: " + USER_EXCEPTION + " was not received received"); + testFailed= true; + } + if (!userErrorReceived) { + log.complain("FAILURE 8: " + USER_ERROR + " was not received received"); + testFailed= true; + } + if (!userThrowableReceived) { + log.complain("FAILURE 9: " + USER_THROWABLE + " was not received received"); + testFailed= true; + } + if (!javaExceptionReceived) { + log.complain("FAILURE 10: " + JAVA_EXCEPTION + " was not received received"); + testFailed= true; + } + if (!javaErrorReceived) { + log.complain("FAILURE 11: " + JAVA_ERROR + " was not received received"); + testFailed= true; + } + + if (testFailed) return FAILED; + return PASSED; + } + +} + +*/ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001/TestDescription.java new file mode 100644 index 00000000000..8cf5ac3621b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionEvent/exception/exception001/TestDescription.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ExceptionEvent/exception/exception001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exercises + * com.sun.jdi.event.ExceptionEvent.exception() method. + * The test checks the following assertion: + * - the ExceptionEvent is received by the debugger for every runtime + * exception or error occured in the debuggee if debugger creates + * and enables the ExceptionRequest; + * - the received ExceptionEvent has proper references to: + * debugged VM, + * executed thread, + * related ExceptionRequest, + * checked location. + * - method ExceptionEvent.exception() returns correct ObjectReference + * to objects of Throwable class or its subclasses. + * A debugger class - nsk.jdi.ExceptionEvent.exception.exception001 ; + * a debuggee class - nsk.jdi.ExceptionEvent.exception.exception001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger launches and connects to debuggee, waits for it started, and + * creates the ExceptionRequest with true and + * parameters, which is disabled by default. + * The debugger defines separate thread for listening received + * events, cleans EventQueue, starts , enables ExceptionRequest, + * sends debuggee command to force it to throw exception, and waits for + * notification that all exceptions are thrown. + * Upon receiving command from debugger, the debuggee raises several + * exception and errors. All these exceptions and errors are enclosed in + * separate try-catch blocks. The debuggee verifies that all exceptions + * are actually thrown and notifies debugger by command or . + * Each received event is handled by separate thread. + * For each ExceptionEvent assertions of the test are verified. + * After command received from debuggee, debugger notifies + * that all checked exceptions have been thrown and waits for + * receives all expected events. If not all events received for WAITIME interval, + * debugger interrupts thread and complains about an error. + * Finally, debugger disables event request, sends debuggee command from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: unknown command: " + command); + return FAILED; + } + + // throw checked exceptions + try { + try { + throw new exception001aException(); + } catch (exception001aException e) { + log.display("exception001aException is thrown"); + userExceptionThrown = true; + } + + try { + throw new exception001aError(); + } catch (exception001aError e) { + log.display("exception001aError is thrown"); + userErrorThrown = true; + } + + try { + throw new exception001aThrowable(); + } catch (exception001aThrowable e) { + log.display("exception001aThrowable is thrown"); + userThrowableThrown = true; + } + + try { + int i = Integer.parseInt("foo"); + } catch (NumberFormatException e) { + log.display("NumberFormatException is thrown"); + javaExceptionThrown = true; + } + + try { + raiseStackOverflow(); + } catch (StackOverflowError e) { + log.display("StackOverflowError is thrown"); + javaErrorThrown = true; + } + + } catch (Throwable e) { + log.complain("Unexpected Throwable: " + e.getMessage()); + e.printStackTrace(); + if (e instanceof ThreadDeath) { + throw e; + } + } + + // check that all exceptions are thrown + boolean thrown = true; + if (!userExceptionThrown) { + log.complain("TEST BUG: user exception NOT thrown"); + thrown = false; + } + if (!userErrorThrown) { + log.complain("TEST BUG: user error NOT thrown"); + thrown = false; + } + if (!userThrowableThrown) { + log.complain("TEST BUG: user Throwable NOT thrown"); + thrown = false; + } + if (!javaExceptionThrown) { + log.complain("TEST BUG: java exception NOT thrown"); + thrown = false; + } + if (!javaErrorThrown) { + log.complain("TEST BUG: java error NOT thrown"); + thrown = false; + } + + // notify debugger whether all exceptions thrown or not + if (thrown) { + pipe.println(COMMAND_DONE); + } else { + pipe.println(COMMAND_ERROR); + } + + // wait for command from debugger and exit + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + log.complain("TEST BUG: unknown command: " + command); + return FAILED; + } + + return PASSED; + } + + private void raiseStackOverflow () { + raiseStackOverflow(); + } +} + +class exception001aException extends Exception {} + +class exception001aError extends Error {} + +class exception001aThrowable extends Throwable {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001.java new file mode 100644 index 00000000000..e1dfd61b3d8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ExceptionRequest._bounds_; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; + +import java.io.*; + +/** + * The test checks up the
    + * - addThreadFilter(ThreadReference)
    + * - addInstanceFilter(ObjectReference)
    + * - addClassFilter(ReferenceType)
    + * - addClassFilter(String)
    + * - addClassExclusionFilter(String)
    + * methods with null argument value. + * In any cases NullPointerException is expected. + */ +/** + com.sun.jdi.request.ExceptionRequest.addThreadFilter(ThreadReference) + com.sun.jdi.request.ExceptionRequest.addInstanceFilter(ObjectReference) + com.sun.jdi.request.ExceptionRequest.addClassFilter(ReferenceType) + com.sun.jdi.request.ExceptionRequest.addClassFilter(String) + com.sun.jdi.request.ExceptionRequest.addClassExclusionFilter(String) + */ +public class filters001 { + + private final static String prefix = "nsk.jdi.ExceptionRequest._bounds_."; + private final static String debuggerName = prefix + "filters001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + filters001 thisTest = new filters001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + display(""); + display(">>>creating ExceptionRequest"); + + ExceptionRequest request = + debugee.getEventRequestManager().createExceptionRequest(null, true, true); + + display(""); + addThreadFilter(request, null); + + display(""); + addInstanceFilter(request, null); + + display(""); + addClassFilter(request, (ReferenceType )null); + + display(""); + addClassFilter(request, (String )null); + + display(""); + addClassExclusionFilter(request, (String )null); + + display(""); + debugee.quit(); + } + + private void addThreadFilter(ExceptionRequest request, ThreadReference thread) { + String tmp = "addThreadFilter :thread name> "; + tmp += (thread == null) ? "" : thread.name(); + display("----------------------"); + display(tmp); + + try { + request.addThreadFilter(thread); + if (thread==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (thread == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addInstanceFilter(ExceptionRequest request, + ObjectReference instance) { + String tmp = "addInstanceFilter :object value> "; + tmp += (instance == null) ? "" : instance.toString(); + display("----------------------"); + display(tmp); + + try { + request.addInstanceFilter(instance); + if (instance==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (instance == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(ExceptionRequest request, ReferenceType refType) { + + display("addClassFilter :ReferenceType> null"); + + try { + request.addClassFilter(refType); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(ExceptionRequest request, String classPattern) { + + display("addClassFilter :classPattern> null"); + try { + request.addClassFilter(classPattern); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassExclusionFilter(ExceptionRequest request, + String classPattern) { + display("addExclusionClassFilter :classPattern> null"); + try { + request.addClassExclusionFilter(classPattern); + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch (NullPointerException e) { + display("!!!Expected " + e); + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001/TestDescription.java new file mode 100644 index 00000000000..3e0649c7a08 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/_bounds_/filters001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the methods + * com.sun.jdi.request.ExceptionRequest.addThreadFilter(ThreadReference) + * com.sun.jdi.request.ExceptionRequest.addInstanceFilter(ObjectReference) + * com.sun.jdi.request.ExceptionRequest.addClassFilter(ReferenceType) + * com.sun.jdi.request.ExceptionRequest.addClassFilter(String) + * com.sun.jdi.request.ExceptionRequest.addClassExclusionFilter(String) + * correctly work for the boundary value of parameter and throw described + * exceptions. + * The test check up this methods with argument value. In any cases + * NullPointerException is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest._bounds_.filters001 + * nsk.jdi.ExceptionRequest._bounds_.filters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest._bounds_.filters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001a.java new file mode 100644 index 00000000000..ed85865b83a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/_bounds_/filters001a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ExceptionRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filters001a is deugee's part of the test. + */ +public class filters001a { + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001.java new file mode 100644 index 00000000000..37de70bd64c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ExceptionRequest. + * + * The test checks that results of the method + * com.sun.jdi.ExceptionRequest.addClassExclusionFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class whose name does not match a + * restricted regular expression. + * The cases to check include both a pattern that begins with '*' and + * one that end with '*'. + * + * The test works as follows. + * - The debugger + * - sets up two ExceptionRequests, + * - restricts the Requests using patterns that begins with '*' and + * ends with *, so that, events will be filtered only from thread1, + * - resumes the debuggee, and + * - waits for expected ExceptionEvents. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, throw NullPointerExceptions used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter001a"; + return new filter001().runThis(argv, out); + } + + private String testedClassName1 = "TestClass11"; + private String testedClassName2 = "nsk.jdi.ExceptionRequest.addClassExclusionFilter.Thread2filter001a"; + + protected void testRun() { + + String property1 = "ExceptionRequest1"; + String property2 = "ExceptionRequest2"; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + final EventRequest eventRequest1 = setting23ExceptionRequest( null, + "*" + testedClassName1, + EventRequest.SUSPEND_NONE, + property1); + eventRequest1.enable(); + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof ExceptionEvent && event.request().equals(eventRequest1)) { + String str = ((ExceptionEvent)event).location().declaringType().name(); + if (str.endsWith(testedClassName1)) { + setFailedStatus("eventRequest1: Received unexpected ExceptionEvent for excluded class:" + str); + } else { + display("eventRequest1: Received expected ExceptionEvent for " + str); + } + return true; + } + return false; + } + } + ); + + display("......waiting1 for ExceptionEvent in expected thread"); + vm.resume(); + break; + + case 1: + final EventRequest eventRequest2 = setting23ExceptionRequest( null, + testedClassName2 + "*", + EventRequest.SUSPEND_NONE, + property2); + eventRequest2.enable(); + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof ExceptionEvent && event.request().equals(eventRequest2)) { + String str = ((ExceptionEvent)event).location().declaringType().name(); + if (str.endsWith(testedClassName2)) { + setFailedStatus("eventRequest2: Received ExceptionEvent for excluded class:" + str); + } else { + display("eventRequest2: Received expected ExceptionEvent for " + str); + } + return true; + } + return false; + } + } + ); + + display("......waiting for ExceptionEvent in expected thread"); + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ExceptionRequest setting23ExceptionRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ExceptionRequest:"); + display(" thread: " + thread + "; class exclude filter: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassExclusionFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + display(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ExceptionRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001/TestDescription.java new file mode 100644 index 00000000000..2c3fb042c28 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name does not match a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter001; + * the debuggee program - nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter001 + * nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001a.java new file mode 100644 index 00000000000..e0e4ad50eea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter001a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter001 JDI test. + */ + +public class filter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter001a thread1 = null; + static Thread2filter001a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 2; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter001a("thread1"); + log1("new filter001a().run1(thread1);"); + new filter001a().run1(thread1); + break; + + case 1: + thread2 = new Thread2filter001a("thread2"); + log1("new filter001a().run1(thread2);"); + new filter001a().run1(thread2); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class Thread1filter001a extends Thread { + + class TestClass10{ + void m10() { + throw new NullPointerException("m10"); + } + } + class TestClass11 extends TestClass10{ + void m11() { + + try { + (new TestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } + } + + + String tName = null; + + public Thread1filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new TestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class Thread2filter001a extends Thread { + + class TestClass20{ + void m20() { + throw new NullPointerException("m20"); + } + } + class TestClass21 extends TestClass20{ + void m21() { + + try { + (new TestClass20()).m20(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } + } + + String tName = null; + + public Thread2filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new TestClass21()).m21(); + } catch ( NullPointerException e) { + } + filter001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java new file mode 100644 index 00000000000..42f24fb625f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.addClassExclusionFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ExceptionRequest and enables it,
    + * - invokes the method addClassExclusionFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassExclusionFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassExclusionFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter002a"; + + private String testedClassName1 = + "nsk.jdi.ExceptionRequest.addClassExclusionFilter.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "ExceptionRequest1"; + + + + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = setting23ExceptionRequest(null, testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting23ExceptionRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassExclusionFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002/TestDescription.java new file mode 100644 index 00000000000..c7a8b7f9e9f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name does not match a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter002; + * the debuggee program - nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter002 + * nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addClassExclusionFilter.filter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002a.java new file mode 100644 index 00000000000..6ff25e86501 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002a.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter002 JDI test. + */ + +public class filter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + +// static Thread1filter002a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// thread1 = new Thread1filter002a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001.java new file mode 100644 index 00000000000..74d658008e1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ExceptionRequest. + * + * The test checks that results of the method + * com.sun.jdi.ExceptionRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or + * any of its subtypes. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2 + * (thread1 will invoke methods throwing NullPointerException in + * the super-class TestClass10 and its sub-class TestClass11), + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes to use to filter ExceptionEvents, + * - sets up ExceptionRequest for the events, + * - restricts the events to those in thread1, + * - and resumes the debuggee and waits for the events. + * - The debuggee starts threads. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_rt001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt001a"; + return new filter_rt001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt001aTestClass11"; + + protected void testRun() { + EventRequest eventRequest1 = null; + String property1 = "ExceptionRequest1"; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + final ReferenceType testClassReference = (ReferenceType)debuggee.classByName(testedClassName); + + eventRequest1 = setting21ExceptionRequest( null, testClassReference, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for ExceptionEvent in expected class"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ExceptionEvent)) { + setFailedStatus("New event is not ExceptionEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property1) ) + setFailedStatus("Received ExceptionEvent with unexpected property: " + property1); + + ReferenceType eventDeclType = ((ExceptionEvent)newEvent).location().declaringType(); + if (!eventDeclType.equals(testClassReference)) { + setFailedStatus("Received unexpected ExceptionEvent for class:" + eventDeclType.name()); + } else { + display("Received expected ExceptionEvent for " + eventDeclType.name()); + } + } + + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ExceptionRequest setting21ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ExceptionRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + display(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ExceptionRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001/TestDescription.java new file mode 100644 index 00000000000..07a9697475a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt001; + * the debuggee program - nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt001 + * nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001a.java new file mode 100644 index 00000000000..4c9ec6cb049 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt001a.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt001 JDI test. + */ + +public class filter_rt001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt001aThread1 thread1 = new filter_rt001aThread1("thread1"); + static filter_rt001aThread2 thread2 = new filter_rt001aThread2("thread2"); + + static filter_rt001aTestClass11 obj = new filter_rt001aTestClass11(); + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + log1("new filter_rt001a().run1(thread1);"); + new filter_rt001a().run1(thread1); + + log1("new filter_rt001a().run1(thread2);"); + new filter_rt001a().run1(thread2); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt001aTestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class filter_rt001aTestClass11 extends filter_rt001aTestClass10{ + void m11() { + + try { + (new filter_rt001aTestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class filter_rt001aThread1 extends Thread { + + String tName = null; + + public filter_rt001aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_rt001aTestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt001aThread2 extends Thread { + + class filter_rt001aTestClass20{ + void m20() { + throw new NullPointerException("m20"); + } + } + class filter_rt001aTestClass21 extends filter_rt001aTestClass20{ + void m21() { + + try { + (new filter_rt001aTestClass20()).m20(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } + } + + String tName = null; + + public filter_rt001aThread2(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_rt001aTestClass21()).m21(); + } catch ( NullPointerException e) { + } + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java new file mode 100644 index 00000000000..ad90bc53d25 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.addClassFilter(ReferenceType)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a TestClass10 object, to use as filter,
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ExceptionRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_rt002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_rt002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt002a"; + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt002aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "ExceptionRequest1"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = setting21ExceptionRequest(null, testClassReference, + EventRequest.SUSPEND_NONE, property1); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" no InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testClassReference); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting21ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002/TestDescription.java new file mode 100644 index 00000000000..a7811270711 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt002; + * the debuggee program - nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt002 + * nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002a.java new file mode 100644 index 00000000000..2917317648b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt002 JDI test. + */ + +public class filter_rt002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt002aThread1 thread1 = null; + + static filter_rt002aTestClass10 obj = new filter_rt002aTestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new filter_rt002aThread1("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt002aTestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class filter_rt002aTestClass11 extends filter_rt002aTestClass10{ + void m11() { + try { + (new filter_rt002aTestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class filter_rt002aThread1 extends Thread { + + String tName = null; + + public filter_rt002aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt002a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_rt002aTestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter_rt002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003.java new file mode 100644 index 00000000000..7d2966f93fb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ExceptionRequest. + * + * The test checks that results of the method + * com.sun.jdi.ExceptionRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to be + * the preparation of the given reference type and any subtypes. + * The cases to test include re-invocations of the method + * addClassFilter() on the same ExceptionRequest object. + * There are two ExceptionRequests to check as follows: + * (1) For ExceptionRequest2, both invocations are with different + * ReferenceTypes restricting one Exception event to two classes. + * The test expects no Exception event will be received. + * (2) For ExceptionRequest1, both invocations are with the same + * ReferenceType restricting one Exception event to one class. + * The test expects this Exception event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2 + * (thread1 will invoke methods throwing NullPointerException in + * the super-class TestClass10 and its sub-class TestClass11), + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes 1&2 for the Classes to filter, + * - sets up two ExceptionRequests 1&2, + * - double restricts ExceptionRequest1 to the RefTypes 1 and 1, + * - double restricts ExceptionRequest2 to the RefTypes 1 and 2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - The debuggee starts thread1 and thread2, one by one, + * to generate the events to be filtered. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_rt003 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt003a"; + return new filter_rt003().runThis(argv, out); + } + + private String testedClassName11 = + "nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt003aTestClass11"; + private String testedClassName21 = + "nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt003aTestClass21"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "ExceptionRequest1"; + String property2 = "ExceptionRequest2"; + + ReferenceType testClassReference11 = null; + ReferenceType testClassReference21 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference11 = (ReferenceType)debuggee.classByName(testedClassName11); + testClassReference21 = (ReferenceType)debuggee.classByName(testedClassName21); + + eventRequest1 = setting21ExceptionRequest(null, testClassReference11, + EventRequest.SUSPEND_ALL, property1); + + eventRequest2 = setting21ExceptionRequest(null, testClassReference11, + EventRequest.SUSPEND_ALL, property2); + + ((ExceptionRequest) eventRequest1).addClassFilter(testClassReference11); + ((ExceptionRequest) eventRequest2).addClassFilter(testClassReference21); + display("......waiting for MethodEntryEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, false); + + if ( !(newEvent instanceof ExceptionEvent)) { + setFailedStatus("ERROR: new event is not ExceptionEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ExceptionEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ReferenceType refType = ((ExceptionEvent)newEvent).location().declaringType(); + if (!refType.equals(testClassReference11)) { + setFailedStatus("Received unexpected declaring type of the event: " + refType.name() + + "\n\texpected one: " + testClassReference11.name()); + } + } + vm.resume(); + break; + + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + + private ExceptionRequest setting21ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ExceptionRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + display(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003/TestDescription.java new file mode 100644 index 00000000000..76123cbc4fb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt003; + * the debuggee program - nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt003 + * nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addClassFilter_rt.filter_rt003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003a.java new file mode 100644 index 00000000000..810185d1d2c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt003a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt003 JDI test. + */ + +public class filter_rt003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt003aThread1 thread1 = null; + static filter_rt003aThread2 thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + filter_rt003aTestClass11 obj1 = new filter_rt003aTestClass11(); + filter_rt003aTestClass21 obj2 = new filter_rt003aTestClass21(); + + thread1 = new filter_rt003aThread1("thread1"); + thread2 = new filter_rt003aThread2("thread2"); + + log1("debuggee started!"); + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + log1("new filter_rt003a().run1(thread1);"); + new filter_rt003a().run1(thread1); + + log1("new filter_rt003a().run1(thread2);"); + new filter_rt003a().run1(thread2); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt003aTestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class filter_rt003aTestClass11 extends filter_rt003aTestClass10{ + void m11() { + + try { + (new filter_rt003aTestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class filter_rt003aThread1 extends Thread { + + String tName = null; + + public filter_rt003aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_rt003aTestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + + +class filter_rt003aTestClass20{ + void m20() { + throw new NullPointerException("m20"); + } +} +class filter_rt003aTestClass21 extends filter_rt003aTestClass20{ + void m21() { + + try { + (new filter_rt003aTestClass20()).m20(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class filter_rt003aThread2 extends Thread { + + String tName = null; + + public filter_rt003aThread2(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_rt003aTestClass21()).m21(); + } catch ( NullPointerException e) { + } + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001.java new file mode 100644 index 00000000000..e3c48517983 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ExceptionRequest. + * + * The test checks that results of the method + * com.sun.jdi.ExceptionRequest.addClassFilter(String) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to check include both a pattern that begin with '*' + * one that end with '*'. + * + * The test works as follows. + * - The debugger + * - creates two class filter objects, + * first one using a pattern that begin with '*', and + * second one using a pattern that end with '*' + * to filter ExceptionEvents in two debuggee's tested threads, + * - sets up two ExceptionRequests, + * - resumes the debuggee, and + * - waits for expected ExceptionEvents. + * - The debuggee creates and starts two threads + * whose 'run' methods create objects of ClassTypes needed + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_s001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s001a"; + return new filter_s001().runThis(argv, out); + } + + private String testedClassName1 = "*TestClass11"; + private String testedClassName2 = + "nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s001aThread2$filter_s001aTestClass20*"; + + private String className1 = "TestClass11"; + private String className2 = + "nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s001aThread2$filter_s001aTestClass20"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "ExceptionRequest1"; + String property2 = "ExceptionRequest2"; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + eventRequest1 = setting22ExceptionRequest(null, testedClassName1, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for ExceptionEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ExceptionEvent)) { + setFailedStatus("ERROR: new event is not ExceptionEvent"); + } else { + String str = ((ExceptionEvent)newEvent).location().declaringType().name(); + if (!str.endsWith(className1)) { + setFailedStatus("Received ExceptionEvent for unexpected class: \n\t" + str); + } else { + display("Received ExceptionEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property1) ) { + setFailedStatus("event has unexpected property: " + property1); + } + } + + vm.resume(); + break; + + case 1: + eventRequest2 = setting22ExceptionRequest(null, testedClassName2, + EventRequest.SUSPEND_ALL, property2); + + display("......waiting for ExceptionEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ExceptionEvent)) { + setFailedStatus("ERROR: new event is not ExceptionEvent"); + } else { + String str = ((ExceptionEvent)newEvent).location().declaringType().name(); + if (!str.endsWith(className2)) { + setFailedStatus("Received ExceptionEvent for unexpected class: \n\t" + str); + } else { + display("Received ExceptionEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property2) ) { + setFailedStatus("event has unexpected property: " + property2); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ExceptionRequest setting22ExceptionRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ExceptionRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + display(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ExceptionRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001/TestDescription.java new file mode 100644 index 00000000000..4c89daedbe3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addClassFilter(String classPattern) + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s001; + * the debuggee program - nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s001 + * nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001a.java new file mode 100644 index 00000000000..f4196029e28 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s001a.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s001 JDI test. + */ + +public class filter_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_s001aThread1 thread1 = null; + static filter_s001aThread2 thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + //------------------------------------------------------ section tested + + case 0: + thread1 = new filter_s001aThread1("thread1"); + log1("new filter_s001a().run1(thread1);"); + new filter_s001a().run1(thread1); + + break; + + case 1: + thread2 = new filter_s001aThread2("thread2"); + log1("new filter_s001a().run1(thread2);"); + new filter_s001a().run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_s001aTestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class filter_s001aTestClass11 extends filter_s001aTestClass10{ + void m11() { + + try { + (new filter_s001aTestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class filter_s001aThread1 extends Thread { + + String tName = null; + + public filter_s001aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_s001aTestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_s001aThread2 extends Thread { + + class filter_s001aTestClass20{ + void m20() { + throw new NullPointerException("m20"); + } + } + class filter_s001aTestClass21 extends filter_s001aTestClass20{ + void m21() { + + try { + (new filter_s001aTestClass20()).m20(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } + } + + String tName = null; + + public filter_s001aThread2(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_s001aTestClass21()).m21(); + } catch ( NullPointerException e) { + } + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java new file mode 100644 index 00000000000..bf5a544fa43 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.addClassFilter(String)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a TestClass10 object, to use as filter,
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ExceptionRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_s002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_s002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s002a"; + + private String testedClassName1 = + "nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s002aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "ExceptionRequest1"; + + + + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = setting22ExceptionRequest(null, testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting22ExceptionRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002/TestDescription.java new file mode 100644 index 00000000000..d0450dbf8d4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addClassFilter(String classPattern) + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s002; + * the debuggee program - nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s002 + * nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addClassFilter_s.filter_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002a.java new file mode 100644 index 00000000000..4945fa054d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002a.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s002 JDI test. + */ + +public class filter_s002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_s002aThread1 thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new filter_s002aThread1("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_s002aTestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class filter_s002aTestClass11 extends filter_s002aTestClass10{ + void m11() { + + try { + (new filter_s002aTestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class filter_s002aThread1 extends Thread { + + String tName = null; + + public filter_s002aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s002a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_s002aTestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter_s002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001.java new file mode 100644 index 00000000000..6f0f3b08d3b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ExceptionRequest. + * + * The test checks that results of the method + * com.sun.jdi.ExceptionRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * in which the currently executing instance is + * the object specified. + * + * The test has works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a special array with three Object instances, + * and two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a BreakpointRequest + * within the method in the class TestClass + * whose array element instances #0 and #1 + * will be calling by the thread1 and the thread2 accordinly, + * - invokes addInstanceFilter() on array element #0 for the thread1 + * and #2 for the thread2, + * thus restricting the breakpoint event only to thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter001a"; + return new instancefilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter001aTestClass"; + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ExceptionRequest1"; + String property2 = "ExceptionRequest2"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + eventRequest1 = setting2ExceptionRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + ((ExceptionRequest) eventRequest1).addInstanceFilter(instance); + + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + eventRequest2 = setting2ExceptionRequest (thread2, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(2); + ((ExceptionRequest) eventRequest2).addInstanceFilter(instance); + + display("......waiting for ExceptionEvent in expected thread"); + + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ExceptionEvent)) { + setFailedStatus("ERROR: new event is not ExceptionEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new ExceptionEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ExceptionRequest setting2ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ExceptionRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + display(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ExceptionRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001/TestDescription.java new file mode 100644 index 00000000000..90de625a39d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter001; + * the debuggee program - nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter001 + * nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001a.java new file mode 100644 index 00000000000..2641d513521 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001a.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter001 JDI test. + */ + +public class instancefilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter001aThread thread1 = null; + static instancefilter001aThread thread2 = null; + + static instancefilter001aTestClass objTC[] = { new instancefilter001aTestClass(), new instancefilter001aTestClass(), new instancefilter001aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + + case 0: + thread1 = new instancefilter001aThread("thread1"); + thread2 = new instancefilter001aThread("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter001aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter001aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } +/* + public static void nullMethod() { + throw new NullPointerException("test"); + } +*/ +} + +class instancefilter001aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void nullMethod() { + throw new NullPointerException("test"); + } + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + instancefilter001a.log1("instancefilter001aTestClass.method() : " + Thread.currentThread().getName()); +// instancefilter001a.nullMethod(); + nullMethod(); + } catch ( NullPointerException e ) { +// instancefilter001a.log1(" NullPointerException : " + e); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java new file mode 100644 index 00000000000..2dc18e5cb47 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ExceptionRequest and enables it,
    + * - invokes the method addInstanceFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addInstanceFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addInstanceFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter002a"; + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "ExceptionRequest1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ExceptionRequest (thread1, + testClassReference, + EventRequest.SUSPEND_NONE, "ExceptionRequest1"); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" no InvalidRequestStateException expected"); + ((ExceptionRequest) eventRequest1).addInstanceFilter(instance); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting2ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002/TestDescription.java new file mode 100644 index 00000000000..532b566aa5d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter002; + * the debuggee program - nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter002 + * nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002a.java new file mode 100644 index 00000000000..015677438aa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002a.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter002 JDI test. + */ + +public class instancefilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter002aThread thread1 = null; + + static instancefilter002aTestClass objTC[] = { new instancefilter002aTestClass(), new instancefilter002aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + + case 0: + thread1 = new instancefilter002aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter002aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter002aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + + public static void nullMethod() { + throw new NullPointerException("test"); + } + +} + +class instancefilter002aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + instancefilter002a.nullMethod(); + } catch ( NullPointerException e ) { +// instancefilter002a.log(" NullPointerException : " + e); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java new file mode 100644 index 00000000000..66dd7161aa3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java @@ -0,0 +1,518 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: UnsupportedOperationException - if the target
    + * virtual machine does not support this operation.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger creates
    + * an ExceptionRequest and if addInstanceFilter() is not supported,
    + * invokes the method on the request expecting
    + * to catch UnsupportedOperationException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter003a"; + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "ExceptionRequest1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ExceptionRequest (thread1, + testClassReference, + EventRequest.SUSPEND_NONE, "ExceptionRequest1"); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + if ( vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == true :: test cancelled"); + } else { + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" UnsupportedOperationException expected"); + ((ExceptionRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no UnsupportedOperationException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" UnsupportedOperationException "); + } + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting2ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003/TestDescription.java new file mode 100644 index 00000000000..3b08aef51d1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter003; + * the debuggee program - nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter003 + * nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003a.java new file mode 100644 index 00000000000..54365c3e44b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003a.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter003 JDI test. + */ + +public class instancefilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter003aThread thread1 = null; + + static instancefilter003aTestClass objTC[] = { new instancefilter003aTestClass(), new instancefilter003aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + + case 0: + thread1 = new instancefilter003aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter003aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter003aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + + public static void nullMethod() { + throw new NullPointerException("test"); + } + +} + +class instancefilter003aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + instancefilter003a.nullMethod(); + } catch ( NullPointerException e ) { +// instancefilter003a.log(" NullPointerException : " + e); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004.java new file mode 100644 index 00000000000..c8d5e44b26b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ExceptionRequest. + * + * The test checks that results of the method + * com.sun.jdi.ExceptionRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same ExceptionRequest object. + * There are two BreakpointRequests to check as follows: + * (1) For ExceptionRequest2, both invocations are with different + * ObjectReferences restricting one Exception event to two objects. + * The test expects no Exception event will be received. + * (2) For ExceptionRequest1, both invocations are with the same + * ObjectReference restricting one Exception event to one object. + * The test expects this Exception event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up ExceptionRequests 1&2 within the method + * in the class TestClass which will be calling by both threads, + * - restricts the ExceptionRequest1 to the tread1 and + * to the array elements #0 & #0 calling only within thread1, + * - restricts the ExceptionRequest2 to the thread2 and + * the array elements #0 & #1 calling within thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter004a"; + return new instancefilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter004aTestClass"; + + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ExceptionRequest1"; + String property2 = "ExceptionRequest2"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + + ObjectReference instance1 = null; + ObjectReference instance2 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2ExceptionRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2ExceptionRequest (thread2, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + + instance1 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + instance2 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(1); + + ((ExceptionRequest) eventRequest1).addInstanceFilter(instance1); + ((ExceptionRequest) eventRequest1).addInstanceFilter(instance1); + ((ExceptionRequest) eventRequest2).addInstanceFilter(instance1); + ((ExceptionRequest) eventRequest2).addInstanceFilter(instance2); + + display("......waiting for ExceptionEvent in expected thread"); + ExceptionEvent newEvent = (ExceptionEvent)eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + EventRequest newEventRequest = newEvent.request(); + if ( newEventRequest.equals(eventRequest1) ) { + display(" received expected event: " + newEvent); + + ThreadReference newEventThread = newEvent.thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ExceptionRequest setting2ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ExceptionRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.setSuspendPolicy(suspendPolicy); + + display(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ExceptionRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004/TestDescription.java new file mode 100644 index 00000000000..56ca45d14f8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same ExceptionRequest object. + * There are two ExceptionRequests to check as follows: + * (1) For ExceptionRequest2, both invocations are with different + * ObjectReferences restricting one Exception event to two objects. + * The test expects no Exception event will be received. + * (2) For ExceptiontRequest1, both invocations are with the same + * ObjectReference restricting one Exception event to one object. + * The test expects this Exception event will be received + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter004; + * the debuggee program - nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter004 + * nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addInstanceFilter.instancefilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004a.java new file mode 100644 index 00000000000..54397f99636 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004a.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter004 JDI test. + */ + +public class instancefilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter004aThread thread1 = null; + static instancefilter004aThread thread2 = null; + + static instancefilter004aTestClass objTC[] = { new instancefilter004aTestClass(), new instancefilter004aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new instancefilter004aThread("thread1"); + thread2 = new instancefilter004aThread("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter004aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter004aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter004aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + nullMethod(); + } catch ( NullPointerException e ) { +// instancefilter004a.log(" NullPointerException : " + e); + } + } + + void nullMethod() { + throw new NullPointerException("test"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001.java new file mode 100644 index 00000000000..36fa79961a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ExceptionRequest. + * + * The test checks that results of the method + * com.sun.jdi.ExceptionRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up an ExceptionRequest within the method + * in the class TestClass which will be calling by both threads, + * - restricts the exception event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class threadfilter001 extends TestDebuggerType1 { + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter001a"; + return new threadfilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter001aTestClass"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + ThreadReference thread1 = null; + String thread1Name = "thread1"; + String property1 = "ExceptionRequest1"; + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ExceptionRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, "ExceptionRequest1"); + + display("......waiting for ExceptionEvent in tested thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ExceptionEvent)) { + setFailedStatus("ERROR: new event is not ExceptionEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ExceptionEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ThreadReference thr = ((ExceptionEvent)newEvent).thread(); + if (!thr.equals(thread1)) { + setFailedStatus("The ExceptionEvent occured in unexpected thread: " + thr); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ExceptionRequest setting2ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ExceptionRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + + excr.setSuspendPolicy(suspendPolicy); + + display(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ExceptionRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001/TestDescription.java new file mode 100644 index 00000000000..47a1eff09d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter001; + * the debuggee program - nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter001 + * nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001a.java new file mode 100644 index 00000000000..dfbb7c71b9c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter001a.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter001 JDI test. + */ + +public class threadfilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter001aThread thread1 = null; + static threadfilter001aThread thread2 = null; + + static threadfilter001aTestClass objTC = new threadfilter001aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new threadfilter001aThread("thread1"); + thread2 = new threadfilter001aThread("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter001aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter001aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + + public static void nullMethod() { + throw new NullPointerException("test"); + } + +} + +class threadfilter001aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + threadfilter001a.nullMethod(); + } catch ( NullPointerException e ) { +// threadfilter001a.log(" NullPointerException : " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java new file mode 100644 index 00000000000..eb710144d51 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ExceptionRequest and enables it,
    + * - invokes the method addThreadFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addThreadFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addThreadFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class threadfilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new threadfilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter002a"; + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "ExceptionRequest1"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ExceptionRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addThreadFilter(thread1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((ExceptionRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting2ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002/TestDescription.java new file mode 100644 index 00000000000..63f455d63e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter002; + * the debuggee program - nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter002 + * nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002a.java new file mode 100644 index 00000000000..83e96c629ba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter002 JDI test. + */ + +public class threadfilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter002aThread thread1 = null; + + static threadfilter002aTestClass objTC = new threadfilter002aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new threadfilter002aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter002aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter002aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + + public static void nullMethod() { + throw new NullPointerException("test"); + } + +} + +class threadfilter002aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + threadfilter002a.nullMethod(); + } catch ( NullPointerException e ) { +// threadfilter002a.log(" NullPointerException : " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java new file mode 100644 index 00000000000..4f1e046660d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java @@ -0,0 +1,543 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Restricts the events generated by this request
    + * to those in the given thread.
    + * The cases to test include three thread's states:
    + * not started, running, dead.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates ExceptionRequest1 and
    + * invokes the method addThreadFilter(tread1) on the request1,
    + * - creates ExceptiontRequest2,
    + * resumes the debuggee to get the thread1 started, and
    + * invokes the method addThreadFilter(thread) on the request2,
    + * - creates ExceptiontRequest3, waits the thread1 to die, and
    + * invokes the method addThreadFilter(thread) on the request3.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class threadfilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new threadfilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter003a"; + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "ExceptionRequest1"; + String property2 = "ExceptionRequest2"; + String property3 = "ExceptionRequest3"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ExceptionRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ExceptionRequest)eventRequest1).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception :: " + e); + testExitCode = FAILED; + } + break; + + case 1: + eventRequest2 = setting2ExceptionRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property2); + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ExceptionRequest)eventRequest2).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception :: " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2ExceptionRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property3); + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ExceptionRequest)eventRequest3).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception :: " + e); + testExitCode = FAILED; + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting2ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.addClassFilter(testedClass); + excr.setSuspendPolicy(suspendPolicy); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003/TestDescription.java new file mode 100644 index 00000000000..2409613aeef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include three thread's states: not started, running, dead. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter003; + * the debuggee program - nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter003 + * nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003a.java new file mode 100644 index 00000000000..0e77c0c03b2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003a.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter003 JDI test. + */ + +public class threadfilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter003aThread thread1 = null; + + static threadfilter003aTestClass objTC = new threadfilter003aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new threadfilter003aThread("thread1"); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();"); + methodForCommunication(); + } + break; + + case 2: + try { + thread1.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class threadfilter003aThread extends Thread { + + public threadfilter003aThread(String threadName) { + super(threadName); + } + + public void run() { + log1(" 'run': enter "); + + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + log1(" 'run': exit "); + } + return; + } + } + +} + +class threadfilter003aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004.java new file mode 100644 index 00000000000..3b84c265867 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ExceptionRequest. + * + * The test checks that results of the method + * com.sun.jdi.ExceptionRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same ExceptionRequest object. + * There are two ExceptionRequests to check as follows: + * (1) For ExceptionRequest2, both invocations are with different + * ThreadReferences restricting one Exception event to two threads. + * The test expects no Exception event will be received. + * (2) For ExceptionRequest1, both invocations are with the same + * ThreadReference restricting one Exception event to one thread. + * The test expects this Exception event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up ExceptionRequests 1&2 within the method + * in the class TestClass which will be calling by both threads, + * - restricts the ExceptionRequest1 only to thread1, + * - restricts the ExceptionRequest2 to both thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class threadfilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter004a"; + return new threadfilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter004aTestClass"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ExceptionRequest1"; + String property2 = "ExceptionRequest2"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2ExceptionRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2ExceptionRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + + ((ExceptionRequest) eventRequest1).addThreadFilter(thread1); + ((ExceptionRequest) eventRequest2).addThreadFilter(thread2); + + display("......waiting for ExceptionEvent in tested thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ExceptionEvent)) { + setFailedStatus("ERROR: new event is not ExceptionEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ExceptionEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + EventRequest newEventRequest = newEvent.request(); + if (!newEventRequest.equals(eventRequest1) ) { + setFailedStatus("The ExceptionEvent occured not for eventRequest1"); + } + + ThreadReference thr = ((ExceptionEvent)newEvent).thread(); + if (!thr.equals(thread1)) { + setFailedStatus("The ExceptionEvent occured in unexpected thread: " + thr); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + + private ExceptionRequest setting2ExceptionRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up ExceptionRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, true, true); + excr.putProperty("number", property); + if (thread != null) + excr.addThreadFilter(thread); + excr.setSuspendPolicy(suspendPolicy); + + display(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ExceptionRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004/TestDescription.java new file mode 100644 index 00000000000..282c3f4ec1f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same ExceptionRequest object. + * There are two ExceptionRequests to check as follows: + * (1) For ExceptionRequest2, both invocations are with different + * ThreadReferences restricting one Exception event to two threads. + * The test expects no Exception event will be received. + * (2) For ExceptionRequest1, both invocations are with the same + * ThreadReference restricting one Exception event to one thread. + * The test expects this Exception event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter004; + * the debuggee program - nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter004 + * nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.addThreadFilter.threadfilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004a.java new file mode 100644 index 00000000000..59850277e3f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter004a.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter004 JDI test. + */ + +public class threadfilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter004aThread thread1 = null; + static threadfilter004aThread thread2 = null; + + static threadfilter004aTestClass objTC = new threadfilter004aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new threadfilter004aThread("thread1"); + thread2 = new threadfilter004aThread("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter004aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter004aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + + public static void nullMethod() { + throw new NullPointerException("test"); + } + +} + +class threadfilter004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + try { + threadfilter004a.nullMethod(); + } catch ( NullPointerException e ) { +// threadfilter004a.log(" NullPointerException : " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java new file mode 100644 index 00000000000..72a4e40d243 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.exception; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.exception()
    + * complies with its spec.
    + *
    + * The test checks if a boolean value, an argument of the method
    + * EventRequestManager.createExceptionRequest(),
    + * is equal to one returned by the method
    + * ExceptionRequest.exception()
    + * The cases to test include a ReferenceType
    + * mirroring NullPointerException, and null.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger
    + * - gets ReferenceType value mirroring NullPointerException,
    + * - sets up two ExceptionRequests with the ReferenceType and null
    + * values of the exception arguments,
    + * - gets the values of the Request with the method
    + * StepRequest.exception(), and
    + * - compares the values.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class exception001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/exception/exception001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new exception001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.exception.exception001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + vm.resume(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String fieldName = "obj"; + Value value = null; + + ReferenceType refObject = null; + ReferenceType exception = null; + + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + log2("......vm.resume();"); + vm.resume(); + + log2("......getting: refObject = debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName));"); + value = debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); + log2(" getting: refObject = (ReferenceType) value.type();"); + refObject = (ReferenceType) value.type(); + + log2("......setting up: eventRequest1 = setting25ExceptionRequest(refObject);"); + eventRequest1 = setting25ExceptionRequest(refObject); + + log2("......getting: exception = ((ExceptionRequest) eventRequest1).exception();"); + exception = ((ExceptionRequest) eventRequest1).exception(); + + log2(" comparing ReferenceType objects"); + if ( !exception.equals(refObject) ) { + testExitCode = FAILED; + log3("ERROR: objects are not equal : " + exception); + } + + log2("......setting up: eventRequest2 = setting25ExceptionRequest(null);"); + eventRequest2 = setting25ExceptionRequest(null); + + log2("......getting: exception = ((ExceptionRequest) eventRequest2).exception();"); + exception = ((ExceptionRequest) eventRequest2).exception(); + + log2(" comparing to null"); + if ( exception != null ) { + testExitCode = FAILED; + log3("ERROR: exception is not the null : " + exception); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting25ExceptionRequest ( ReferenceType refType ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(refType, true, true); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001/TestDescription.java new file mode 100644 index 00000000000..58f006cebe4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/exception/exception001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.exception() + * complies with its spec: + * public ReferenceType exception() + * Returns exception type for which exception events are requested. + * Returns: The exception (and its subclasses) requested with + * EventRequestManager.createExceptionRequest(com.sun.jdi.ReferenceType, + * boolean, boolean), or null if, as by default, + * all exceptions are requested. + * The test checks if a ReferenceType object, + * an argument of the method EventRequestManager.createExceptionRequest(), + * is equal to one returned by the method ExceptionRequest.exception() + * The cases to test include ReferenceType mirroring NullPointerException + * and null. + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.exception.exception001; + * the debuggee program - nsk.jdi.ExceptionRequest.exception.exception001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test was fixed due to bug: + * 4637824 TEST_BUG: race condition in exception001 + * Test was fixed due to bug: + * 4915479 TEST_BUG: race in nsk/jdi/ExceptionRequest/exception/exception001 + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.exception.exception001 + * nsk.jdi.ExceptionRequest.exception.exception001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.exception.exception001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001a.java new file mode 100644 index 00000000000..4344bbd24dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.exception; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the exception001 JDI test. + */ + +public class exception001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static NullPointerException obj = new NullPointerException(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + // continue + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java new file mode 100644 index 00000000000..da7c5022533 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.notifyCaught; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.notifyCaught()
    + * complies with its spec.
    + *
    + * The test checks if a boolean value, an argument of the method
    + * EventRequestManager.createExceptionRequest(),
    + * is equal to one returned by the method
    + * ExceptionRequest.notifyCaught()
    + * The cases to check include both true and false.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger
    + * - sets up two ExceptionRequests with true and false values of
    + * the notifyCaught argument,
    + * - gets the values of the Request with the method
    + * StepRequest.notifyCaught(), and
    + * - compares the values.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class notifycaught001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new notifycaught001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.notifyCaught.notifycaught001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + boolean bool; + + + for (int i = 0; ; i++) { + + vm.resume(); + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + + + log2("......setting up: eventRequest1 = setting24ExceptionRequest(true, true);"); + eventRequest1 = setting24ExceptionRequest(true, true); + + log2("......getting: bool = ((ExceptionRequest) eventRequest1).notifyCaught();"); + bool = ((ExceptionRequest) eventRequest1).notifyCaught(); + + log2(" compareing boolean values"); + if (bool != true) { + testExitCode = FAILED; + log3("ERROR: values are not equal : true and false"); + } + + log2("......setting up: eventRequest2 = setting24ExceptionRequest(false, true);"); + eventRequest2 = setting24ExceptionRequest(false, true); + + log2("......getting: bool = ((ExceptionRequest) eventRequest2).notifyCaught();"); + bool = ((ExceptionRequest) eventRequest2).notifyCaught(); + + log2(" compareing boolean values"); + if (bool != false) { + testExitCode = FAILED; + log3("ERROR: values are not equal : true and false"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting24ExceptionRequest ( boolean notifyCaught, + boolean notifyUnaught ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, notifyCaught, notifyUnaught); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001/TestDescription.java new file mode 100644 index 00000000000..be9faadbfe6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.notifyCaught() + * complies with its spec: + * public boolean notifyCaught() + * Returns whether caught exceptions of the requested type + * will generate events when they are thrown. + * Note that at the time an exception is thrown, + * it is not always possible to determine whether it is truly caught. + * See ExceptionEvent.catchLocation() for details. + * Returns: boolean true if caught exceptions will be reported, false otherwise. + * The test checks if a boolean value, + * an argument of the method EventRequestManager.createExceptionRequest(), + * is equal to one returned by the method ExceptionRequest.notifyCaught() + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.notifyCaught.notifycaught001; + * the debuggee program - nsk.jdi.ExceptionRequest.notifyCaught.notifycaught001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.notifyCaught.notifycaught001 + * nsk.jdi.ExceptionRequest.notifyCaught.notifycaught001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.notifyCaught.notifycaught001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001a.java new file mode 100644 index 00000000000..351804d6ef1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001a.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.notifyCaught; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the notifycaught001 JDI test. + */ + +public class notifycaught001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1notifycaught001a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1notifycaught001a("thread1"); + log1("new notifycaught001a().run1(thread1);"); + new notifycaught001a().run1(thread1); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class TestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class TestClass11 extends TestClass10{ + void m11() { + + try { + (new TestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class Thread1notifycaught001a extends Thread { + + String tName = null; + + public Thread1notifycaught001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + notifycaught001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new TestClass11()).m11(); + } catch ( NullPointerException e) { + } + notifycaught001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java new file mode 100644 index 00000000000..8f02f3fa4dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.notifyUncaught; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ExceptionRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ExceptionRequest.notifyUncaught()
    + * complies with its spec.
    + *
    + * The test checks if a boolean value, an argument of the method
    + * EventRequestManager.createExceptionRequest(),
    + * is equal to one returned by the method
    + * ExceptionRequest.notifyUncaught()
    + * The cases to check include both true and false.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger
    + * - sets up two ExceptionRequests with true and false values of
    + * the notifyUncaught argument,
    + * - gets the values of the Request with the method
    + * StepRequest.notifyUncaught(), and
    + * - compares the values.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class notifyuncaught001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new notifyuncaught001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ExceptionRequest.notifyUncaught.notifyuncaught001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + boolean bool; + + + for (int i = 0; ; i++) { + + vm.resume(); + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + + + log2("......setting up: eventRequest1 = setting24ExceptionRequest(true, true);"); + eventRequest1 = setting24ExceptionRequest(true, true); + + log2("......getting: bool = ((ExceptionRequest) eventRequest1).notifyUncaught();"); + bool = ((ExceptionRequest) eventRequest1).notifyUncaught(); + + log2(" compareing boolean values"); + if (bool != true) { + testExitCode = FAILED; + log3("ERROR: values are not equal : false and true"); + } + + log2("......setting up: eventRequest2 = setting24ExceptionRequest(true, false);"); + eventRequest2 = setting24ExceptionRequest(true, false); + + log2("......getting: bool = ((ExceptionRequest) eventRequest2).notifyUncaught();"); + bool = ((ExceptionRequest) eventRequest2).notifyUncaught(); + + log2(" compareing boolean values"); + if (bool != false) { + testExitCode = FAILED; + log3("ERROR: values are not equal : true and false"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ExceptionRequest setting24ExceptionRequest ( boolean notifyCaught, + boolean notifyUnaught ) + throws JDITestRuntimeException { + try { + log2("......setting up ExceptionRequest:"); + + ExceptionRequest + excr = eventRManager.createExceptionRequest(null, notifyCaught, notifyUnaught); + + log2(" ExceptionRequest has been set up"); + return excr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingExceptionRequest() : " + e); + log3(" ExceptionRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ExceptionRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001/TestDescription.java new file mode 100644 index 00000000000..1a26cbb5b0e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ExceptionRequest. + * The test checks up that a result of the method + * com.sun.jdi.ExceptionRequest.notifyUncaught() + * complies with its spec: + * public boolean notifyUncaught() + * Returns whether uncaught exceptions of the requested type + * will generate events when they are thrown. + * Note that at the time an exception is thrown, + * it is not always possible to determine whether it is truly caught. + * See ExceptionEvent.catchLocation() for details. + * Returns: boolean true if uncaught exceptions will be reported, false otherwise. + * The test checks if a boolean value, + * an argument of the method EventRequestManager.createExceptionRequest(), + * is equal to one returned by the method ExceptionRequest.notifyUncaught() + * The test works as follows: + * The debugger program - nsk.jdi.ExceptionRequest.notifyUncaught.notifyuncaught001; + * the debuggee program - nsk.jdi.ExceptionRequest.notifyUncaught.notifyuncaught001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ExceptionRequest.notifyUncaught.notifyuncaught001 + * nsk.jdi.ExceptionRequest.notifyUncaught.notifyuncaught001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ExceptionRequest.notifyUncaught.notifyuncaught001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001a.java new file mode 100644 index 00000000000..99100baf3af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001a.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ExceptionRequest.notifyUncaught; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the notifyuncaught001 JDI test. + */ + +public class notifyuncaught001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1notifyuncaught001a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1notifyuncaught001a("thread1"); + log1("new notifyuncaught001a().run1(thread1);"); + new notifyuncaught001a().run1(thread1); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class TestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class TestClass11 extends TestClass10{ + void m11() { + + try { + (new TestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class Thread1notifyuncaught001a extends Thread { + + String tName = null; + + public Thread1notifyuncaught001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + notifyuncaught001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new TestClass11()).m11(); + } catch ( NullPointerException e) { + } + notifyuncaught001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExtraClassesInstaller.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExtraClassesInstaller.java new file mode 100644 index 00000000000..f4f98043547 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExtraClassesInstaller.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 nsk.jdi; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ExtraClassesInstaller { + public static void main(String[] args) { + Path target = Paths.get("bin") + .resolve(args[0]); + ClassLoader cl = ExtraClassesInstaller.class.getClassLoader(); + for (int i = 1; i < args.length; ++i) { + + String pathName = args[i]; + try { + try (InputStream is = cl.getResourceAsStream(pathName)) { + if (is == null) { + throw new Error("can't find " + pathName); + } + Path file = target.resolve(pathName); + Path dir = file.getParent(); + try { + Files.createDirectories(dir); + } catch (IOException e) { + throw new Error("can't create dir " + dir, e); + } + try { + Files.copy(is, file); + } catch (IOException e) { + throw new Error("can't write to " + file, e); + } + } + } catch (IOException e) { + throw new Error("IOE on closing " + pathName + " resource stream", e); + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001.java new file mode 100644 index 00000000000..3622fc90743 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class equals001 { + private static Log log; + private final static String prefix = "nsk.jdi.Field.equals."; + private final static String className = "equals001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "ClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fieldsDebugee; + List methods; + Iterator methodsIterator; + java.lang.reflect.Field[] fieldsDebuger; + ClassOfFields classOfFields = new ClassOfFields(); + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + try { + fieldsDebugee = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fieldsDebugee.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + + // Compare each Field and Method from debugee + try { + methods = refType.allMethods(); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get methods from class"); + log.complain("debuger FAILURE 1> Exception: " + e); + return 2; + } + log.display("debuger> Total methods found: " + methods.size()); + Iterator fieldsIterator = fieldsDebugee.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field fieldDebugee = (Field)fieldsIterator.next(); + String name = fieldDebugee.name(); + methodsIterator = methods.iterator(); + + for (int j = 0; methodsIterator.hasNext(); j++) { + Method method = (Method)methodsIterator.next(); + String methodName = method.name(); + + log.display("debuger> Field " + name + " and method " + + methodName + " read from debugee."); + if (fieldDebugee.equals(method)) { + // Field is not equal to any Object which type is not Field + log.complain("debuger FAILURE 2> Field " + name + + " and method " + methodName + " are equal. " + + "Expected result: not equal."); + testFailed = true; + continue; + } + } + } + + // Compare Field (com.sun.jdi.Field) from debugee and Field + // from debuger (java.lang.reflect.Field) + Class classDebuger = classOfFields.getClass(); + try { + fieldsDebuger = classDebuger.getDeclaredFields(); + } catch (SecurityException e) { + log.complain("debuger FAILURE 3> Can't get fields from debuger's" + + " class"); + log.complain("debuger FAILURE 3> Exception: " + e); + return 2; + } + int totalDebugerFields = fieldsDebuger.length; + log.display("debuger> Total fields in debuger found: " + + totalDebugerFields); + fieldsIterator = fieldsDebugee.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field fieldDebugee = (Field)fieldsIterator.next(); + String name = fieldDebugee.name(); + + for (int j = 1; j < totalDebugerFields; j++) { + java.lang.reflect.Field fieldDebuger = fieldsDebuger[j]; + String nameDebuger = fieldDebuger.getName(); + + log.display("debuger> Field from debugee " + name + " and " + + "field from debuger " + nameDebuger + " read."); + if (fieldDebugee.equals(fieldDebuger)) { + // Field is not equal to any Object which type + // is not not com.sun.jdi.Field + log.complain("debuger FAILURE 4> Field from debugee " + + name + " and field from debuger " + + nameDebuger + " are equal. Expected " + + "result: not equal."); + testFailed = true; + continue; + } + } + } + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} + +class ClassOfFields { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..2b946ea6750 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the equals() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/equals001 checks assertion: + * public boolean equals(java.lang.Object obj) + * 1. Returns false if the Object is not a Field. + * Each method from debugee is not a Field, so equals() returns + * false if to compare fields and methods from debugee. + * Each Object from debuger (any field of type java.lang.reflect.Field) + * is not a Field, so equals() returns false if to compare fields from + * debugee and debuger. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.equals.equals001 + * nsk.jdi.Field.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001a.java new file mode 100644 index 00000000000..8b16e12fa67 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class equals001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + ClassToCheck check = new ClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class ClassToCheck { + // Fields + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + class Class {} + Class X0, X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + + // Methods + void v_m() {} + boolean z_m() { return true; } + byte b_m() { return (byte)1; } + char c_m() { return (char)1; } + double d_m() { return (double)1; } + float f_m() { return (float)1; } + int i_m() { return (int)1; } + long l_m() { return (long)1; } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002.java new file mode 100644 index 00000000000..0979c7db846 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002.java @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class equals002 { + final static int TOTAL_FIELDS = 117; + final static String FIELDS_TYPE_NAME[][] = { + {"boolean", "z0"}, + {"boolean", "z1"}, + {"boolean", "z2"}, + {"byte", "b0"}, + {"byte", "b1"}, + {"byte", "b2"}, + {"char", "c0"}, + {"char", "c1"}, + {"char", "c2"}, + {"double", "d0"}, + {"double", "d1"}, + {"double", "d2"}, + {"float", "f0"}, + {"float", "f1"}, + {"float", "f2"}, + {"int", "i0"}, + {"int", "i1"}, + {"int", "i2"}, + {"long", "l0"}, + {"long", "l1"}, + {"long", "l2"}, + + {"long", "lS0"}, + {"long", "lS1"}, + {"long", "lS2"}, + {"long", "lP0"}, + {"long", "lP1"}, + {"long", "lP2"}, + {"long", "lU0"}, + {"long", "lU1"}, + {"long", "lU2"}, + {"long", "lR0"}, + {"long", "lR1"}, + {"long", "lR2"}, + {"long", "lT0"}, + {"long", "lT1"}, + {"long", "lT2"}, + {"long", "lV0"}, + {"long", "lV1"}, + {"long", "lV2"}, + {"long", "lF0"}, + {"long", "lF1"}, + {"long", "lF2"}, + + {"Class", "X0"}, + {"Class", "X1"}, + {"Class", "X2"}, + {"Boolean", "Z0"}, + {"Boolean", "Z1"}, + {"Boolean", "Z2"}, + {"Byte", "B0"}, + {"Byte", "B1"}, + {"Byte", "B2"}, + {"Char", "C0"}, + {"Char", "C1"}, + {"Char", "C2"}, + {"Double", "D0"}, + {"Double", "D1"}, + {"Double", "D2"}, + {"Float", "F0"}, + {"Float", "F1"}, + {"Float", "F2"}, + {"Int", "I0"}, + {"Int", "I1"}, + {"Int", "I2"}, + {"Long", "L0"}, + {"Long", "L1"}, + {"Long", "L2"}, + {"String", "S0"}, + {"String", "S1"}, + {"String", "S2"}, + {"Object", "O0"}, + {"Object", "O1"}, + {"Object", "O2"}, + + {"Long", "LS0"}, + {"Long", "LS1"}, + {"Long", "LS2"}, + {"Long", "LP0"}, + {"Long", "LP1"}, + {"Long", "LP2"}, + {"Long", "LU0"}, + {"Long", "LU1"}, + {"Long", "LU2"}, + {"Long", "LR0"}, + {"Long", "LR1"}, + {"Long", "LR2"}, + {"Long", "LT0"}, + {"Long", "LT1"}, + {"Long", "LT2"}, + {"Long", "LV0"}, + {"Long", "LV1"}, + {"Long", "LV2"}, + {"Long", "LF0"}, + {"Long", "LF1"}, + {"Long", "LF2"}, + + {"Inter", "E0"}, + {"Inter", "E1"}, + {"Inter", "E2"}, + {"Inter", "ES0"}, + {"Inter", "ES1"}, + {"Inter", "ES2"}, + {"Inter", "EP0"}, + {"Inter", "EP1"}, + {"Inter", "EP2"}, + {"Inter", "EU0"}, + {"Inter", "EU1"}, + {"Inter", "EU2"}, + {"Inter", "ER0"}, + {"Inter", "ER1"}, + {"Inter", "ER2"}, + {"Inter", "ET0"}, + {"Inter", "ET1"}, + {"Inter", "ET2"}, + {"Inter", "EV0"}, + {"Inter", "EV1"}, + {"Inter", "EV2"}, + {"Inter", "EF0"}, + {"Inter", "EF1"}, + {"Inter", "EF2"} + }; + private static Log log; + private final static String prefix = "nsk.jdi.Field.equals."; + private final static String className = "equals002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(debugeeName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + debugeeName + + " not found."); + return 2; + } + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields + ", should be " + TOTAL_FIELDS); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + Iterator fieldsIterator = fields.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field srcField = (Field)fieldsIterator.next(); + String name = srcField.name(); + + // Compare all fields with each other but srcField + if (name == null) { + log.complain("debuger FAILURE 1> Name is null for " + i + + " field"); + testFailed = true; + continue; + } + for (int j = 0; j < TOTAL_FIELDS; j++) { + String checkFieldName = FIELDS_TYPE_NAME[j][1]; + Field checkField; + + if (!name.equals(checkFieldName)) { + try { + checkField = refType.fieldByName(checkFieldName); + } catch (Exception e) { + log.complain("debuger FAILURE 2> Can't get field " + + "by name " + checkFieldName); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + + // Compare two different Fields, result should be false + boolean fieldsEqual = srcField.equals(checkField); + log.display("debuger> Compared fields " + name + " and " + + checkFieldName + ", result is " + fieldsEqual); + if (fieldsEqual) { + // Fields in the same class that mirror different + // fields are not equal + log.complain("debuger FAILURE 3> Different fields " + + "(" + name + " and " + checkFieldName + ")" + + " are equal. Expected result: not equal."); + testFailed = true; + continue; + } + } + } + } + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..67f3051e3b2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the equals() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/equals002 checks assertion: + * public boolean equals(java.lang.Object obj) + * 1. Returns false if the Object and Field are in the same class but + * mirror different fields. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.equals.equals002 + * nsk.jdi.Field.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002a.java new file mode 100644 index 00000000000..1c17943fa6b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class equals002a { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + class Class {} + Class X0, X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003.java new file mode 100644 index 00000000000..fe1bbd5bd76 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class equals003 { + private static Log log; + private final static String prefix = "nsk.jdi.Field.equals."; + private final static String className = "equals003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String mainClassName = prefix + "MainClass"; + private final static String sameClass1Name = prefix + "SameClass1"; + private final static String sameClass2Name = prefix + "SameClass2"; + private final static String overridenClassName = prefix + "OverridenClass"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List mainFields; + Field mainField; + Field same1Field; + Field same2Field; + Field overridenField; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from all classes + ReferenceType mainClassRefType = debugee.classByName(mainClassName); + if (mainClassRefType == null) { + log.complain("debuger FAILURE> Class " + mainClassName + " not " + + "found."); + return 2; + } + ReferenceType sameClass1RefType = debugee.classByName(sameClass1Name); + if (sameClass1RefType == null) { + log.complain("debuger FAILURE> Class " + sameClass1Name + " not " + + "found."); + return 2; + } + ReferenceType sameClass2RefType = debugee.classByName(sameClass2Name); + if (sameClass2RefType == null) { + log.complain("debuger FAILURE> Class " + sameClass2Name + " not " + + "found."); + return 2; + } + ReferenceType overridenClassRefType = + debugee.classByName(overridenClassName); + if (overridenClassRefType == null) { + log.complain("debuger FAILURE> Class " + overridenClassName + + " not found."); + return 2; + } + + try { + mainFields = mainClassRefType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class " + + mainClassName); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = mainFields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields in class " + + mainClassName + " read: " + totalFields); + return 2; + } + log.display("debuger> Total number of fields in class " + + mainClassName + " read: " + totalFields); + Iterator fieldsIterator = mainFields.iterator(); + + // Check each field of MainClass with fields from classes + // SameClass1, SameClass2, OverridenClass + for (int i = 0; fieldsIterator.hasNext(); i++) { + mainField = (Field)fieldsIterator.next(); + String name = mainField.name(); + + if (name == null) { + log.complain("debuger FAILURE 1> Name is null for " + i + + " field"); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + name + " from class " + + mainClassName + " read."); + + // Compare fields from classes MainClass and SameClass1 + log.display("debuger> Compare classes " + mainClassName + " and " + + sameClass1Name); + try { + same1Field = sameClass1RefType.fieldByName(name); + } catch (Exception e) { + log.complain("debuger FAILURE 2> Can't get field by name " + + name + " in class " + sameClass1Name); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> Field " + name + " from class " + + sameClass1Name + " read."); + // Fields in different classes but defined in same class are equal + if (! mainField.equals(same1Field)) { + log.complain("debuger FAILURE 3> Fields " + name + " from " + + "classes " + mainClassName + " and " + + sameClass1Name + " are not equal. Expected " + + "result: equal."); + testFailed = true; + continue; + } + + // Compare fields from classes MainClass and OverridenClass + log.display("debuger> Compare classes " + mainClassName + + " and " + overridenClassName); + try { + overridenField = overridenClassRefType.fieldByName(name); + } catch (Exception e) { + log.complain("debuger FAILURE 4> Can't get field by name " + + name + " in class " + overridenClassName); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> Field " + name + " from class " + + overridenClassName + " read."); + // Fields in different classes are not equal + if (mainField.equals(overridenField)) { + log.complain("debuger FAILURE 5> Fields " + name + + " from classes " + mainClassName + " and " + + overridenClassName + " are equal. Expected " + + "result: not equal."); + testFailed = true; + continue; + } + + // Compare fields from classes SameClass1 and SameClass2 + log.display("debuger> Compare classes " + sameClass1Name + + " and " + sameClass2Name); + try { + same2Field = sameClass2RefType.fieldByName(name); + } catch (Exception e) { + log.complain("debuger FAILURE 6> Can't get field by name " + + name + " in class " + sameClass2Name); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + log.display("debuger> Field " + name + " from class " + + sameClass2Name + " read."); + // Fields in different classes but defined in same class are equal + if (!same1Field.equals(same2Field)) { + log.complain("debuger FAILURE 7> Fields " + name + + " from classes " + sameClass1Name + " and " + + sameClass2Name + " are not equal. Expected " + + "result: equal."); + testFailed = true; + continue; + } + } + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003/TestDescription.java new file mode 100644 index 00000000000..aa08dbd8616 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/equals/equals003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the equals() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/equals003 checks assertion: + * public boolean equals(java.lang.Object obj) + * 1. Returns false if the Object and Field are in different classes + * but mirror the same field. + * There are MainClass, two classes (SameClass1, SameClass2) that extends + * it and do not override fields from super class, OverridenClass that + * extends MainClass and overrides all fields. Three comparisons are made: + * - Two fields from MainClass and SameClass1, that mirror the same field + * are compared. Expected result - true. + * - Two fields from MainClass and OverridenClass, that mirror the same field + * are compared. Expected result - false. + * - Two fields from SameClass1 and SameClass2, that mirror the same field + * are compared. Expected result - true. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.equals.equals003 + * nsk.jdi.Field.equals.equals003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.equals.equals003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003a.java new file mode 100644 index 00000000000..289fc8a03d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003a.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class equals003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + SameClass1 sc1 = new SameClass1(); + SameClass2 sc2 = new SameClass2(); + OverridenClass rc = new OverridenClass(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class SameClass1 extends MainClass { + // All fields are the same as in MainClass +} + +class SameClass2 extends MainClass { + // All fields are the same as in MainClass +} + +class OverridenClass extends MainClass { + // All fields are redefined + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + class Class {} + Class X0, X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; +} + +class MainClass { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + class Class {} + Class X0, X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005.java new file mode 100644 index 00000000000..f2f92335ca5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class equals005 { + private static Log log; + private final static String prefix = "nsk.jdi.Field.equals."; + private final static String className = "equals005"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(debugeeName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + debugeeName + + " not found."); + return 2; + } + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + Iterator fieldsIterator = fields.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field srcField = (Field)fieldsIterator.next(); + String name = srcField.name(); + Field checkField; + boolean fieldsEqual; + + if (name == null) { + log.complain("debuger FAILURE 1> Name is null for " + i + + " field"); + testFailed = true; + continue; + } + try { + checkField = refType.fieldByName(name); + } catch (Exception e) { + log.complain("debuger FAILURE 2> Can't create field to check " + + "for field " + name); + testFailed = true; + continue; + } + fieldsEqual = srcField.equals(checkField); + log.display("debuger> Fields " + name + " and " + checkField.name() + + " compared, result " + fieldsEqual); + if (!fieldsEqual) { + // Fields declared in the same class and mirror the same + // fields are equal + log.complain("debuger FAILURE 3> Same fields with name " + name + + " are not equal. Expected result: equal."); + testFailed = true; + continue; + } + } + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005/TestDescription.java new file mode 100644 index 00000000000..88a837e492b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/equals/equals005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the equals() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/equals005 checks assertion: + * public boolean equals(java.lang.Object obj) + * 1. Returns true if the Object and Field are declared in the same class + * or interface, in the same VM. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.equals.equals005 + * nsk.jdi.Field.equals.equals005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.equals.equals005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005a.java new file mode 100644 index 00000000000..9758af546f0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class equals005a { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + class Class {} + Class X0, X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001.java new file mode 100644 index 00000000000..3f5d99ddaa9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class hashcode001 { + private static Log log; + private final static String prefix = "nsk.jdi.Field.hashCode."; + private final static String className = "hashcode001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(debugeeName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + debugeeName + + " not found."); + return 2; + } + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields); + return 2; + } + log.display("debuger> Total fields found: " + fields.size()); + Iterator fieldsIterator = fields.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field field = (Field)fieldsIterator.next(); + int hash1 = field.hashCode(); + int hash2 = field.hashCode(); + // hashCode() returns int value and always should be the same + // for one field + log.display("debuger> " + i + " field " + field.name() + + "(" + field.typeName() + ") has hashCode = " + hash1); + if (hash1 != hash2) { + log.complain("debuger FAILURE> Two different hash codes for " + + "field " + field.name() + " (" + field.typeName() + + "): " + hash1 + " and " + hash2 + ". Should be " + + "the same"); + testFailed = true; + } + } + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..3aa7cad3029 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the hashCode() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/hashcode001 checks assertion: + * public int hashCode() + * Returns: the integer code + * Whenever hashCode() invoked on the same Field more then once during + * an execution, it must consistently return the same integer. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.hashCode.hashcode001 + * nsk.jdi.Field.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001a.java new file mode 100644 index 00000000000..722dcbc1128 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class hashcode001a { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + class Class {} + Class X0, X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + + log.display("DEBUGEE> debugee started."); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001.java new file mode 100644 index 00000000000..9218197eab0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Field.isEnumConstant; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isenumconstant001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Field.isEnumConstant."; + private final static String className = "isenumconstant001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] expectedFieldNames = {"f1", "f2", "f3", "f4"}; + private final static String[] expectedEnumFieldsNames = { "e1", "e2" }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + + Field checkedField = checkedClass.fieldByName(expectedEnumFieldsNames[i]); + if (checkedField.isEnumConstant()) { + display("Field.isEnumConstant() returned expected true for"); + display("\t" + expectedEnumFieldsNames[i] + " field of enum " + className ); + } else { + display("Field.isEnumConstant() returned unexpected false for"); + display("\t" + expectedEnumFieldsNames[i] + " field of enum " + className ); + exitStatus = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001/TestDescription.java new file mode 100644 index 00000000000..c281ea919b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/isEnumConstant/isenumconstant001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isEnumConstant() method of Field interface. + * The test checks if the method returns true for each enum + * constant declared in mirrored enum type. + * The test consists of a debugger program (isenumconstant001.java) + * and debuggee application (isenumconstant001a.java). + * Package name is nsk.jdi.Field.isEnumConstant . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isEnumConstant() method for each + * expected enum constant field of mirrrored enum types. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.isEnumConstant.isenumconstant001 + * nsk.jdi.Field.isEnumConstant.isenumconstant001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.isEnumConstant.isenumconstant001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001a.java new file mode 100644 index 00000000000..4c4471acca6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isEnumConstant/isenumconstant001a.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Field.isEnumConstant; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isenumconstant001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static isenumconstant001Enum1 f1 = isenumconstant001Enum1.e2; + static isenumconstant001Enum2 f2 = isenumconstant001Enum2.e1; + static isenumconstant001Enum3 f3 = isenumconstant001Enum3.e1; + static isenumconstant001Enum1.Enum1_ f4 = isenumconstant001Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isenumconstant001.SIGNAL_READY); + + + //pipe.println(isenumconstant001.SIGNAL_GO); + receiveSignal(isenumconstant001.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum isenumconstant001Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum isenumconstant001Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} + +enum isenumconstant001Enum3 { + e1(1), e2(2); + + int ii; + + isenumconstant001Enum3 (int i) { + ii = i; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001.java new file mode 100644 index 00000000000..ca1fc0aabd7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001.java @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.isTransient; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class istrans001 { + final static String IS_TRANS = "transient"; + final static String NOT_TRANS = ""; + final static int TOTAL_FIELDS = 216; + final static String FIELDS_TYPE_NAME[][] = { + {"z0", NOT_TRANS}, + {"z1", NOT_TRANS}, + {"z2", NOT_TRANS}, + {"b0", NOT_TRANS}, + {"b1", NOT_TRANS}, + {"b2", NOT_TRANS}, + {"c0", NOT_TRANS}, + {"c1", NOT_TRANS}, + {"c2", NOT_TRANS}, + {"d0", NOT_TRANS}, + {"d1", NOT_TRANS}, + {"d2", NOT_TRANS}, + {"f0", NOT_TRANS}, + {"f1", NOT_TRANS}, + {"f2", NOT_TRANS}, + {"i0", NOT_TRANS}, + {"i1", NOT_TRANS}, + {"i2", NOT_TRANS}, + {"l0", NOT_TRANS}, + {"l1", NOT_TRANS}, + {"l2", NOT_TRANS}, + + {"z0T", IS_TRANS}, + {"z1T", IS_TRANS}, + {"z2T", IS_TRANS}, + {"b0T", IS_TRANS}, + {"b1T", IS_TRANS}, + {"b2T", IS_TRANS}, + {"c0T", IS_TRANS}, + {"c1T", IS_TRANS}, + {"c2T", IS_TRANS}, + {"d0T", IS_TRANS}, + {"d1T", IS_TRANS}, + {"d2T", IS_TRANS}, + {"f0T", IS_TRANS}, + {"f1T", IS_TRANS}, + {"f2T", IS_TRANS}, + {"i0T", IS_TRANS}, + {"i1T", IS_TRANS}, + {"i2T", IS_TRANS}, + {"l0T", IS_TRANS}, + {"l1T", IS_TRANS}, + {"l2T", IS_TRANS}, + + {"lS0", NOT_TRANS}, + {"lS1", NOT_TRANS}, + {"lS2", NOT_TRANS}, + {"lP0", NOT_TRANS}, + {"lP1", NOT_TRANS}, + {"lP2", NOT_TRANS}, + {"lU0", NOT_TRANS}, + {"lU1", NOT_TRANS}, + {"lU2", NOT_TRANS}, + {"lR0", NOT_TRANS}, + {"lR1", NOT_TRANS}, + {"lR2", NOT_TRANS}, + {"lV0", NOT_TRANS}, + {"lV1", NOT_TRANS}, + {"lV2", NOT_TRANS}, + {"lF0", NOT_TRANS}, + {"lF1", NOT_TRANS}, + {"lF2", NOT_TRANS}, + + {"lS0T", IS_TRANS}, + {"lS1T", IS_TRANS}, + {"lS2T", IS_TRANS}, + {"lP0T", IS_TRANS}, + {"lP1T", IS_TRANS}, + {"lP2T", IS_TRANS}, + {"lU0T", IS_TRANS}, + {"lU1T", IS_TRANS}, + {"lU2T", IS_TRANS}, + {"lR0T", IS_TRANS}, + {"lR1T", IS_TRANS}, + {"lR2T", IS_TRANS}, + {"lV0T", IS_TRANS}, + {"lV1T", IS_TRANS}, + {"lV2T", IS_TRANS}, + {"lF0T", IS_TRANS}, + {"lF1T", IS_TRANS}, + {"lF2T", IS_TRANS}, + + {"X0", NOT_TRANS}, + {"X1", NOT_TRANS}, + {"X2", NOT_TRANS}, + {"Z0", NOT_TRANS}, + {"Z1", NOT_TRANS}, + {"Z2", NOT_TRANS}, + {"B0", NOT_TRANS}, + {"B1", NOT_TRANS}, + {"B2", NOT_TRANS}, + {"C0", NOT_TRANS}, + {"C1", NOT_TRANS}, + {"C2", NOT_TRANS}, + {"D0", NOT_TRANS}, + {"D1", NOT_TRANS}, + {"D2", NOT_TRANS}, + {"F0", NOT_TRANS}, + {"F1", NOT_TRANS}, + {"F2", NOT_TRANS}, + {"I0", NOT_TRANS}, + {"I1", NOT_TRANS}, + {"I2", NOT_TRANS}, + {"L0", NOT_TRANS}, + {"L1", NOT_TRANS}, + {"L2", NOT_TRANS}, + {"S0", NOT_TRANS}, + {"S1", NOT_TRANS}, + {"S2", NOT_TRANS}, + {"O0", NOT_TRANS}, + {"O1", NOT_TRANS}, + {"O2", NOT_TRANS}, + + {"X0T", IS_TRANS}, + {"X1T", IS_TRANS}, + {"X2T", IS_TRANS}, + {"Z0T", IS_TRANS}, + {"Z1T", IS_TRANS}, + {"Z2T", IS_TRANS}, + {"B0T", IS_TRANS}, + {"B1T", IS_TRANS}, + {"B2T", IS_TRANS}, + {"C0T", IS_TRANS}, + {"C1T", IS_TRANS}, + {"C2T", IS_TRANS}, + {"D0T", IS_TRANS}, + {"D1T", IS_TRANS}, + {"D2T", IS_TRANS}, + {"F0T", IS_TRANS}, + {"F1T", IS_TRANS}, + {"F2T", IS_TRANS}, + {"I0T", IS_TRANS}, + {"I1T", IS_TRANS}, + {"I2T", IS_TRANS}, + {"L0T", IS_TRANS}, + {"L1T", IS_TRANS}, + {"L2T", IS_TRANS}, + {"S0T", IS_TRANS}, + {"S1T", IS_TRANS}, + {"S2T", IS_TRANS}, + {"O0T", IS_TRANS}, + {"O1T", IS_TRANS}, + {"O2T", IS_TRANS}, + + {"LS0", NOT_TRANS}, + {"LS1", NOT_TRANS}, + {"LS2", NOT_TRANS}, + {"LP0", NOT_TRANS}, + {"LP1", NOT_TRANS}, + {"LP2", NOT_TRANS}, + {"LU0", NOT_TRANS}, + {"LU1", NOT_TRANS}, + {"LU2", NOT_TRANS}, + {"LR0", NOT_TRANS}, + {"LR1", NOT_TRANS}, + {"LR2", NOT_TRANS}, + {"LV0", NOT_TRANS}, + {"LV1", NOT_TRANS}, + {"LV2", NOT_TRANS}, + {"LF0", NOT_TRANS}, + {"LF1", NOT_TRANS}, + {"LF2", NOT_TRANS}, + + {"LS0T", IS_TRANS}, + {"LS1T", IS_TRANS}, + {"LS2T", IS_TRANS}, + {"LP0T", IS_TRANS}, + {"LP1T", IS_TRANS}, + {"LP2T", IS_TRANS}, + {"LU0T", IS_TRANS}, + {"LU1T", IS_TRANS}, + {"LU2T", IS_TRANS}, + {"LR0T", IS_TRANS}, + {"LR1T", IS_TRANS}, + {"LR2T", IS_TRANS}, + {"LV0T", IS_TRANS}, + {"LV1T", IS_TRANS}, + {"LV2T", IS_TRANS}, + {"LF0T", IS_TRANS}, + {"LF1T", IS_TRANS}, + {"LF2T", IS_TRANS}, + + {"E0", NOT_TRANS}, + {"E1", NOT_TRANS}, + {"E2", NOT_TRANS}, + + {"E0T", IS_TRANS}, + {"E1T", IS_TRANS}, + {"E2T", IS_TRANS}, + + {"ES0", NOT_TRANS}, + {"ES1", NOT_TRANS}, + {"ES2", NOT_TRANS}, + {"EP0", NOT_TRANS}, + {"EP1", NOT_TRANS}, + {"EP2", NOT_TRANS}, + {"EU0", NOT_TRANS}, + {"EU1", NOT_TRANS}, + {"EU2", NOT_TRANS}, + {"ER0", NOT_TRANS}, + {"ER1", NOT_TRANS}, + {"ER2", NOT_TRANS}, + {"EV0", NOT_TRANS}, + {"EV1", NOT_TRANS}, + {"EV2", NOT_TRANS}, + {"EF0", NOT_TRANS}, + {"EF1", NOT_TRANS}, + {"EF2", NOT_TRANS}, + + {"ES0T", IS_TRANS}, + {"ES1T", IS_TRANS}, + {"ES2T", IS_TRANS}, + {"EP0T", IS_TRANS}, + {"EP1T", IS_TRANS}, + {"EP2T", IS_TRANS}, + {"EU0T", IS_TRANS}, + {"EU1T", IS_TRANS}, + {"EU2T", IS_TRANS}, + {"ER0T", IS_TRANS}, + {"ER1T", IS_TRANS}, + {"ER2T", IS_TRANS}, + {"EV0T", IS_TRANS}, + {"EV1T", IS_TRANS}, + {"EV2T", IS_TRANS}, + {"EF0T", IS_TRANS}, + {"EF1T", IS_TRANS}, + {"EF2T", IS_TRANS} + }; + private static Log log; + private final static String prefix = "nsk.jdi.Field.isTransient."; + private final static String className = "istrans001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(debugeeName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + debugeeName + + " not found."); + return 2; + } + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields + ", should be " + TOTAL_FIELDS); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + Iterator fieldsIterator = fields.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field field = (Field)fieldsIterator.next(); + boolean isTrans = field.isTransient(); + String name = field.name(); + String realIsTrans; + + if (name == null) { + log.complain("debuger FAILURE 1> Name is null for " + i + + " field"); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field (" + name + "), " + + "isTransient = " + isTrans + " read."); + try { + realIsTrans = getTransByName(name); + } catch (Error e) { + log.complain("debuger FAILURE 2> Unexpected Error " + e); + return 2; + } + // isTransient() returns true if the field is transient, + // returns false if the field is not transient + if ((isTrans && !realIsTrans.equals(IS_TRANS)) || + (!isTrans && realIsTrans.equals(IS_TRANS)) + ) { + log.complain("debuger FAILURE 3> " + i + " field " + name + + ": read field.isTransient() = " + isTrans + + " real isTransient should be " + realIsTrans); + testFailed = true; + } + } + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } + + private static String getTransByName(String name) + throws Error + { + for (int i = 0; i < TOTAL_FIELDS; i++) { + String fieldName = FIELDS_TYPE_NAME[i][0]; + if (fieldName.equals(name)) { + return FIELDS_TYPE_NAME[i][1]; + } + } + throw new Error("Error in test. Unknown field " + name); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001/TestDescription.java new file mode 100644 index 00000000000..bdbda687c0c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/isTransient/istrans001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isTransient() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/istrans001 checks assertions: + * public boolean isTransient() + * 1. Returns true if this field is transient. + * 2. Returns false if this field is not transient. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.isTransient.istrans001 + * nsk.jdi.Field.isTransient.istrans001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.isTransient.istrans001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001a.java new file mode 100644 index 00000000000..225ae95ac25 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001a.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.isTransient; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class istrans001a { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + transient boolean z0T, z1T[]={z0T}, z2T[][]={z1T}; + transient byte b0T, b1T[]={b0T}, b2T[][]={b1T}; + transient char c0T, c1T[]={c0T}, c2T[][]={c1T}; + transient double d0T, d1T[]={d0T}, d2T[][]={d1T}; + transient float f0T, f1T[]={f0T}, f2T[][]={f1T}; + transient int i0T, i1T[]={i0T}, i2T[][]={i1T}; + transient long l0T, l1T[]={l0T}, l2T[][]={l1T}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + transient static long lS0T, lS1T[]={lS0T}, lS2T[][]={lS1T}; + transient private long lP0T, lP1T[]={lP0T}, lP2T[][]={lP1T}; + transient public long lU0T, lU1T[]={lU0T}, lU2T[][]={lU1T}; + transient protected long lR0T, lR1T[]={lR0T}, lR2T[][]={lR1T}; + transient volatile long lV0T, lV1T[]={lV0T}, lV2T[][]={lV1T}; + transient final long lF0T = 999, lF1T[]={lF0T}, lF2T[][]={lF1T}; + + class Class {} + Class X0 = new Class(), X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + transient Class X0T, X1T[]={X0T}, X2T[][]={X1T}; + transient Boolean Z0T, Z1T[]={Z0T}, Z2T[][]={Z1T}; + transient Byte B0T, B1T[]={B0T}, B2T[][]={B1T}; + transient Character C0T, C1T[]={C0T}, C2T[][]={C1T}; + transient Double D0T, D1T[]={D0T}, D2T[][]={D1T}; + transient Float F0T, F1T[]={F0T}, F2T[][]={F1T}; + transient Integer I0T, I1T[]={I0T}, I2T[][]={I1T}; + transient Long L0T, L1T[]={L0T}, L2T[][]={L1T}; + transient String S0T, S1T[]={S0T}, S2T[][]={S1T}; + transient Object O0T, O1T[]={O0T}, O2T[][]={O1T}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + transient static Long LS0T, LS1T[]={LS0T}, LS2T[][]={LS1T}; + transient private Long LP0T, LP1T[]={LP0T}, LP2T[][]={LP1T}; + transient public Long LU0T, LU1T[]={LU0T}, LU2T[][]={LU1T}; + transient protected Long LR0T, LR1T[]={LR0T}, LR2T[][]={LR1T}; + transient volatile Long LV0T, LV1T[]={LV0T}, LV2T[][]={LV1T}; + transient final Long LF0T = new Long(999), LF1T[]={LF0T}, + LF2T[][]={LF1T}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + transient Inter E0T, E1T[]={E0T}, E2T[][]={E1T}; + + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + + transient static Inter ES0T, ES1T[]={ES0T}, ES2T[][]={ES1T}; + transient private Inter EP0T, EP1T[]={EP0T}, EP2T[][]={EP1T}; + transient public Inter EU0T, EU1T[]={EU0T}, EU2T[][]={EU1T}; + transient protected Inter ER0T, ER1T[]={ER0T}, ER2T[][]={ER1T}; + transient volatile Inter EV0T, EV1T[]={EV0T}, EV2T[][]={EV1T}; + transient final Inter EF0T = null, EF1T[]={EF0T}, EF2T[][]={EF1T}; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001.java new file mode 100644 index 00000000000..10834197c9b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001.java @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.isVolatile; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class isvol001 { + final static String IS_VOL = "volatile"; + final static String NOT_VOL = ""; + final static int TOTAL_FIELDS = 207; + final static String FIELDS_TYPE_NAME[][] = { + {"z0", NOT_VOL}, + {"z1", NOT_VOL}, + {"z2", NOT_VOL}, + {"b0", NOT_VOL}, + {"b1", NOT_VOL}, + {"b2", NOT_VOL}, + {"c0", NOT_VOL}, + {"c1", NOT_VOL}, + {"c2", NOT_VOL}, + {"d0", NOT_VOL}, + {"d1", NOT_VOL}, + {"d2", NOT_VOL}, + {"f0", NOT_VOL}, + {"f1", NOT_VOL}, + {"f2", NOT_VOL}, + {"i0", NOT_VOL}, + {"i1", NOT_VOL}, + {"i2", NOT_VOL}, + {"l0", NOT_VOL}, + {"l1", NOT_VOL}, + {"l2", NOT_VOL}, + + {"z0V", IS_VOL}, + {"z1V", IS_VOL}, + {"z2V", IS_VOL}, + {"b0V", IS_VOL}, + {"b1V", IS_VOL}, + {"b2V", IS_VOL}, + {"c0V", IS_VOL}, + {"c1V", IS_VOL}, + {"c2V", IS_VOL}, + {"d0V", IS_VOL}, + {"d1V", IS_VOL}, + {"d2V", IS_VOL}, + {"f0V", IS_VOL}, + {"f1V", IS_VOL}, + {"f2V", IS_VOL}, + {"i0V", IS_VOL}, + {"i1V", IS_VOL}, + {"i2V", IS_VOL}, + {"l0V", IS_VOL}, + {"l1V", IS_VOL}, + {"l2V", IS_VOL}, + + {"lS0", NOT_VOL}, + {"lS1", NOT_VOL}, + {"lS2", NOT_VOL}, + {"lP0", NOT_VOL}, + {"lP1", NOT_VOL}, + {"lP2", NOT_VOL}, + {"lU0", NOT_VOL}, + {"lU1", NOT_VOL}, + {"lU2", NOT_VOL}, + {"lR0", NOT_VOL}, + {"lR1", NOT_VOL}, + {"lR2", NOT_VOL}, + {"lT0", NOT_VOL}, + {"lT1", NOT_VOL}, + {"lT2", NOT_VOL}, + {"lF0", NOT_VOL}, + {"lF1", NOT_VOL}, + {"lF2", NOT_VOL}, + + {"lS0V", IS_VOL}, + {"lS1V", IS_VOL}, + {"lS2V", IS_VOL}, + {"lP0V", IS_VOL}, + {"lP1V", IS_VOL}, + {"lP2V", IS_VOL}, + {"lU0V", IS_VOL}, + {"lU1V", IS_VOL}, + {"lU2V", IS_VOL}, + {"lR0V", IS_VOL}, + {"lR1V", IS_VOL}, + {"lR2V", IS_VOL}, + {"lT0V", IS_VOL}, + {"lT1V", IS_VOL}, + {"lT2V", IS_VOL}, + + {"X0", NOT_VOL}, + {"X1", NOT_VOL}, + {"X2", NOT_VOL}, + {"Z0", NOT_VOL}, + {"Z1", NOT_VOL}, + {"Z2", NOT_VOL}, + {"B0", NOT_VOL}, + {"B1", NOT_VOL}, + {"B2", NOT_VOL}, + {"C0", NOT_VOL}, + {"C1", NOT_VOL}, + {"C2", NOT_VOL}, + {"D0", NOT_VOL}, + {"D1", NOT_VOL}, + {"D2", NOT_VOL}, + {"F0", NOT_VOL}, + {"F1", NOT_VOL}, + {"F2", NOT_VOL}, + {"I0", NOT_VOL}, + {"I1", NOT_VOL}, + {"I2", NOT_VOL}, + {"L0", NOT_VOL}, + {"L1", NOT_VOL}, + {"L2", NOT_VOL}, + {"S0", NOT_VOL}, + {"S1", NOT_VOL}, + {"S2", NOT_VOL}, + {"O0", NOT_VOL}, + {"O1", NOT_VOL}, + {"O2", NOT_VOL}, + + {"X0V", IS_VOL}, + {"X1V", IS_VOL}, + {"X2V", IS_VOL}, + {"Z0V", IS_VOL}, + {"Z1V", IS_VOL}, + {"Z2V", IS_VOL}, + {"B0V", IS_VOL}, + {"B1V", IS_VOL}, + {"B2V", IS_VOL}, + {"C0V", IS_VOL}, + {"C1V", IS_VOL}, + {"C2V", IS_VOL}, + {"D0V", IS_VOL}, + {"D1V", IS_VOL}, + {"D2V", IS_VOL}, + {"F0V", IS_VOL}, + {"F1V", IS_VOL}, + {"F2V", IS_VOL}, + {"I0V", IS_VOL}, + {"I1V", IS_VOL}, + {"I2V", IS_VOL}, + {"L0V", IS_VOL}, + {"L1V", IS_VOL}, + {"L2V", IS_VOL}, + {"S0V", IS_VOL}, + {"S1V", IS_VOL}, + {"S2V", IS_VOL}, + {"O0V", IS_VOL}, + {"O1V", IS_VOL}, + {"O2V", IS_VOL}, + + {"LS0", NOT_VOL}, + {"LS1", NOT_VOL}, + {"LS2", NOT_VOL}, + {"LP0", NOT_VOL}, + {"LP1", NOT_VOL}, + {"LP2", NOT_VOL}, + {"LU0", NOT_VOL}, + {"LU1", NOT_VOL}, + {"LU2", NOT_VOL}, + {"LR0", NOT_VOL}, + {"LR1", NOT_VOL}, + {"LR2", NOT_VOL}, + {"LT0", NOT_VOL}, + {"LT1", NOT_VOL}, + {"LT2", NOT_VOL}, + {"LF0", NOT_VOL}, + {"LF1", NOT_VOL}, + {"LF2", NOT_VOL}, + + {"LS0V", IS_VOL}, + {"LS1V", IS_VOL}, + {"LS2V", IS_VOL}, + {"LP0V", IS_VOL}, + {"LP1V", IS_VOL}, + {"LP2V", IS_VOL}, + {"LU0V", IS_VOL}, + {"LU1V", IS_VOL}, + {"LU2V", IS_VOL}, + {"LR0V", IS_VOL}, + {"LR1V", IS_VOL}, + {"LR2V", IS_VOL}, + {"LT0V", IS_VOL}, + {"LT1V", IS_VOL}, + {"LT2V", IS_VOL}, + + {"E0", NOT_VOL}, + {"E1", NOT_VOL}, + {"E2", NOT_VOL}, + + {"E0V", IS_VOL}, + {"E1V", IS_VOL}, + {"E2V", IS_VOL}, + + {"ES0", NOT_VOL}, + {"ES1", NOT_VOL}, + {"ES2", NOT_VOL}, + {"EP0", NOT_VOL}, + {"EP1", NOT_VOL}, + {"EP2", NOT_VOL}, + {"EU0", NOT_VOL}, + {"EU1", NOT_VOL}, + {"EU2", NOT_VOL}, + {"ER0", NOT_VOL}, + {"ER1", NOT_VOL}, + {"ER2", NOT_VOL}, + {"ET0", NOT_VOL}, + {"ET1", NOT_VOL}, + {"ET2", NOT_VOL}, + {"EF0", NOT_VOL}, + {"EF1", NOT_VOL}, + {"EF2", NOT_VOL}, + + {"ES0V", IS_VOL}, + {"ES1V", IS_VOL}, + {"ES2V", IS_VOL}, + {"EP0V", IS_VOL}, + {"EP1V", IS_VOL}, + {"EP2V", IS_VOL}, + {"EU0V", IS_VOL}, + {"EU1V", IS_VOL}, + {"EU2V", IS_VOL}, + {"ER0V", IS_VOL}, + {"ER1V", IS_VOL}, + {"ER2V", IS_VOL}, + {"ET0V", IS_VOL}, + {"ET1V", IS_VOL}, + {"ET2V", IS_VOL} + }; + private static Log log; + private final static String prefix = "nsk.jdi.Field.isVolatile."; + private final static String className = "isvol001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(debugeeName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + debugeeName + + " not found."); + return 2; + } + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields + ", should be " + TOTAL_FIELDS); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + Iterator fieldsIterator = fields.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field field = (Field)fieldsIterator.next(); + boolean isVol = field.isVolatile(); + String name = field.name(); + String realIsVol; + + if (name == null) { + log.complain("debuger FAILURE 1> Name is null for " + i + + " field"); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field (" + name + "), " + + "isVolatile = " + isVol + " read."); + try { + realIsVol = getVolByName(name); + } catch (Error e) { + log.complain("debuger FAILURE 2> Unexpected Error " + e); + return 2; + } + // isVolatile() returns true if the field is volatile, + // returns false if the field is not volatile + if ((isVol && !realIsVol.equals(IS_VOL)) || + (!isVol && realIsVol.equals(IS_VOL)) + ) { + log.complain("debuger FAILURE> " + i + " field " + name + + ": read field.isVolatile() = " + isVol + + " real isVolatile should be " + realIsVol); + testFailed = true; + } + } + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } + + private static String getVolByName(String name) + throws Error + { + for (int i = 0; i < TOTAL_FIELDS; i++) { + String fieldName = FIELDS_TYPE_NAME[i][0]; + if (fieldName.equals(name)) { + return FIELDS_TYPE_NAME[i][1]; + } + } + throw new Error("Error in test. Unknown field " + name); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001/TestDescription.java new file mode 100644 index 00000000000..939938b28dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/isVolatile/isvol001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isVolatile() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/isvol001 checks assertions: + * public boolean isVolatile() + * 1. Returns true if this field is volatile. + * 2. Returns false if this field is not volatile. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.isVolatile.isvol001 + * nsk.jdi.Field.isVolatile.isvol001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.isVolatile.isvol001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001a.java new file mode 100644 index 00000000000..1fb0d769f40 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.isVolatile; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isvol001a { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + volatile boolean z0V, z1V[]={z0V}, z2V[][]={z1V}; + volatile byte b0V, b1V[]={b0V}, b2V[][]={b1V}; + volatile char c0V, c1V[]={c0V}, c2V[][]={c1V}; + volatile double d0V, d1V[]={d0V}, d2V[][]={d1V}; + volatile float f0V, f1V[]={f0V}, f2V[][]={f1V}; + volatile int i0V, i1V[]={i0V}, i2V[][]={i1V}; + volatile long l0V, l1V[]={l0V}, l2V[][]={l1V}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + volatile static long lS0V, lS1V[]={lS0V}, lS2V[][]={lS1V}; + volatile private long lP0V, lP1V[]={lP0V}, lP2V[][]={lP1V}; + volatile public long lU0V, lU1V[]={lU0V}, lU2V[][]={lU1V}; + volatile protected long lR0V, lR1V[]={lR0V}, lR2V[][]={lR1V}; + volatile transient long lT0V, lT1V[]={lT0V}, lT2V[][]={lT1V}; + + class Class {} + Class X0, X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + volatile Class X0V, X1V[]={X0V}, X2V[][]={X1V}; + volatile Boolean Z0V, Z1V[]={Z0V}, Z2V[][]={Z1V}; + volatile Byte B0V, B1V[]={B0V}, B2V[][]={B1V}; + volatile Character C0V, C1V[]={C0V}, C2V[][]={C1V}; + volatile Double D0V, D1V[]={D0V}, D2V[][]={D1V}; + volatile Float F0V, F1V[]={F0V}, F2V[][]={F1V}; + volatile Integer I0V, I1V[]={I0V}, I2V[][]={I1V}; + volatile Long L0V, L1V[]={L0V}, L2V[][]={L1V}; + volatile String S0V, S1V[]={S0V}, S2V[][]={S1V}; + volatile Object O0V, O1V[]={O0V}, O2V[][]={O1V}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + volatile static Long LS0V, LS1V[]={LS0V}, LS2V[][]={LS1V}; + volatile private Long LP0V, LP1V[]={LP0V}, LP2V[][]={LP1V}; + volatile public Long LU0V, LU1V[]={LU0V}, LU2V[][]={LU1V}; + volatile protected Long LR0V, LR1V[]={LR0V}, LR2V[][]={LR1V}; + volatile transient Long LT0V, LT1V[]={LT0V}, LT2V[][]={LT1V}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + + volatile Inter E0V, E1V[]={E0V}, E2V[][]={E1V}; + + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + + volatile static Inter ES0V, ES1V[]={ES0V}, ES2V[][]={ES1V}; + volatile private Inter EP0V, EP1V[]={EP0V}, EP2V[][]={EP1V}; + volatile public Inter EU0V, EU1V[]={EU0V}, EU2V[][]={EU1V}; + volatile protected Inter ER0V, ER1V[]={ER0V}, ER2V[][]={ER1V}; + volatile transient Inter ET0V, ET1V[]={ET0V}, ET2V[][]={ET1V}; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001.java new file mode 100644 index 00000000000..536289d2a4a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class type001 { + final static int TOTAL_FIELDS = 15; + final static String FIELDS_TYPE_NAME[][] = { + {"boolean", "z0", "Z"}, + {"byte", "b0", "B"}, + {"char", "c0", "C"}, + {"double", "d0", "D"}, + {"float", "f0", "F"}, + {"int", "i0", "I"}, + {"long", "l0", "J"}, + {"short", "r0", "S"}, + + {"long", "lS0", "J"}, + {"long", "lP0", "J"}, + {"long", "lU0", "J"}, + {"long", "lR0", "J"}, + {"long", "lT0", "J"}, + {"long", "lV0", "J"}, + {"long", "lF0", "J"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.Field.type."; + private final static String className = "type001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(debugeeName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + debugeeName + + " not found."); + return 2; + } + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields + ", should be " + TOTAL_FIELDS); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + Iterator fieldsIterator = fields.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field field = (Field)fieldsIterator.next(); + String name = field.name(); + Type type; + String realType; + + try { + type = field.type(); + } catch (ClassNotLoadedException e) { + log.complain("debuger FAILURE 1> Can't get primitive type of " + + "field " + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + if (type == null) { + log.complain("debuger FAILURE 2> Type is null for " + i + + " field " + name); + testFailed = true; + continue; + } + if (name == null) { + log.complain("debuger FAILURE 3> Name is null for " + i + + " field"); + testFailed = true; + continue; + } + try { + realType = getStatByName(name, 2); + } catch (Error e) { + log.complain("debuger FAILURE 4> Unexpected Error " + e); + return 2; + } + String signature = type.signature(); + log.display("debuger> " + i + " field (" + name + ") of type " + + type + " signature " + signature + " read."); + char signJNI = realType.charAt(0); + try { + switch (signJNI) { + case 'Z': + BooleanType typeBoolean = (BooleanType)type; + break; + case 'B': + ByteType typeByte = (ByteType)type; + break; + case 'C': + CharType typeChar = (CharType)type; + break; + case 'D': + DoubleType typeDouble = (DoubleType)type; + break; + case 'F': + FloatType typeFloat = (FloatType)type; + break; + case 'I': + IntegerType typeInteger = (IntegerType)type; + break; + case 'J': + LongType typeLong = (LongType)type; + break; + case 'S': + ShortType typeShort = (ShortType)type; + break; + default: + log.complain("debuger FAILURE 5> Error in test. " + + "Unknown JNI signature " + signJNI); + return 2; + } + } catch (ClassCastException e) { + log.complain("debuger FAILURE 6> Can't convert field " + name + + " to PrimitiveType"); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + } + + if (!realType.equals(signature)) { + log.complain("debuger FAILURE 7> Signature of field " + name + + " is " + signature + ", but should be " + + realType); + testFailed = true; + } + } + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } + + private static String getStatByName(String name, int field) + throws Error + { + for (int i = 0; i < TOTAL_FIELDS; i++) { + String fieldName = FIELDS_TYPE_NAME[i][1]; + if (fieldName.equals(name)) { + return FIELDS_TYPE_NAME[i][field]; + } + } + throw new Error("Error in test. Unknown field " + name); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001/TestDescription.java new file mode 100644 index 00000000000..e7b90b955e8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/type/type001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the type() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/type001 checks assertion: + * public Type type() throws ClassNotLoadedException + * 1. For primitive fields an apropriate PrimitiveType is returned. + * Each field of primitive type of debugee should be casted to apropriate + * PrimitiveType in debuger without exceptions. Also, each signature of + * returned Type of a field should agree with JDI Type Signatures. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.type.type001 + * nsk.jdi.Field.type.type001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.type.type001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001a.java new file mode 100644 index 00000000000..d16f3e49f1a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type001a.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class type001a { + boolean z0; + byte b0; + char c0; + double d0; + float f0; + int i0; + long l0; + short r0; + + static long lS0; + private long lP0; + public long lU0; + protected long lR0; + transient long lT0; + volatile long lV0; + final long lF0 = 999; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002.java new file mode 100644 index 00000000000..ae816148f29 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class type002 { + final static int TOTAL_FIELDS = 25; + // final static String ARRAY_TYPE = "A"; + // Not used yet because of bug + // 4404195: JDI: spec: Field.type() is undefined for array fields + final static String CLASS_TYPE = "C"; + final static String INTERFACE_TYPE = "I"; + + final static String FIELDS_TYPE_NAME[][] = { + {"Class", "X0", CLASS_TYPE}, + {"Boolean", "Z0", CLASS_TYPE}, + {"Byte", "B0", CLASS_TYPE}, + {"Character", "C0", CLASS_TYPE}, + {"Double", "D0", CLASS_TYPE}, + {"Float", "F0", CLASS_TYPE}, + {"Integer", "I0", CLASS_TYPE}, + {"Long", "L0", CLASS_TYPE}, + {"String", "S0", CLASS_TYPE}, + {"Object", "O0", CLASS_TYPE}, + + {"Long", "LS0", CLASS_TYPE}, + {"Long", "LP0", CLASS_TYPE}, + {"Long", "LU0", CLASS_TYPE}, + {"Long", "LR0", CLASS_TYPE}, + {"Long", "LT0", CLASS_TYPE}, + {"Long", "LV0", CLASS_TYPE}, + {"Long", "LF0", CLASS_TYPE}, + + {"Inter", "E0", INTERFACE_TYPE}, + {"Inter", "ES0", INTERFACE_TYPE}, + {"Inter", "EP0", INTERFACE_TYPE}, + {"Inter", "EU0", INTERFACE_TYPE}, + {"Inter", "ER0", INTERFACE_TYPE}, + {"Inter", "ET0", INTERFACE_TYPE}, + {"Inter", "EV0", INTERFACE_TYPE}, + {"Inter", "EF0", INTERFACE_TYPE}, + }; + + private static Log log; + private final static String prefix = "nsk.jdi.Field.type."; + private final static String className = "type002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToChekName = prefix + "type002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(classToChekName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToChekName + + " not found."); + return 2; + } + log.display("debuger> Class loaded with loader " + + refType.classLoader()); + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields + ", should be " + TOTAL_FIELDS); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + Iterator fieldsIterator = fields.iterator(); + + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field field = (Field)fieldsIterator.next(); + String name = field.name(); + String realType; + String realSign; + Type type; + ArrayType typeArray; + ClassType typeClass; + InterfaceType typeInterface; + + try { + type = field.type(); + } catch (ClassNotLoadedException e) { + // All classes are loaded, so ClassNotLoadedException is + // not expected + log.complain("debuger FAILURE 1> Can't get type of field " + + name); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + if (type == null) { + log.complain("debuger FAILURE 2> Type is null for " + i + + " field " + name); + testFailed = true; + continue; + } + if (name == null) { + log.display("debuger FAILURE 3> Name is null for " + i + + " field"); + testFailed = true; + continue; + } + try { + realType = getStatByName(name, 0); + } catch (Error e) { + log.complain("debuger FAILURE 4> Unexpected Error " + e); + return 2; + } + try { + realSign = getStatByName(name, 2); + } catch (Error e) { + log.complain("debuger FAILURE 5> Unexpected Error " + e); + return 2; + } + String signature = type.signature(); + log.display("debuger> " + i + " field (" + name + ") of type " + + type + " signature " + signature + " read."); + + char signJNI = realSign.charAt(0); + try { + switch (signJNI) { +// case 'A': +// typeArray = (ArrayType)type; +// break; +// Not used yet because of bug +// 4404195: JDI: spec: Field.type() is undefined for array fields + case 'C': + typeClass = (ClassType)type; + break; + case 'I': + typeInterface = (InterfaceType)type; + break; + default: + log.complain("debuger FAILURE 6> Error in test. " + + "Unknown JNI signature " + signJNI); + return 2; + } + } catch (ClassCastException e) { + log.complain("debuger FAILURE 7> Can't convert field " + name + + " to ReferenceType"); + log.complain("debuger FAILURE 7> Exception: " + e); + testFailed = true; + } + + if (signature.indexOf(realType) == -1) { + // field.signature() does not exist in realType + log.complain("debuger FAILURE 8> Signature of field " + name + + " is " + signature + ", but " + "should be " + + realType); + testFailed = true; + } + } + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } + + private static String getStatByName(String name, int field) + throws Error + { + for (int i = 0; i < TOTAL_FIELDS; i++) { + String fieldName = FIELDS_TYPE_NAME[i][1]; + if (fieldName.equals(name)) { + return FIELDS_TYPE_NAME[i][field]; + } + } + throw new Error("Error in test. Unknown field " + name); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002/TestDescription.java new file mode 100644 index 00000000000..2e77d51123a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/type/type002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the type() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/type002 checks assertion: + * public Type type() throws ClassNotLoadedException + * 1. For object fields, the appropriate ReferenceType is returned if it + * has been loaded through the enclosing type's class loader. + * Constructor for each class and interface are triggered, so all + * classes are loaded in debugee and ClassNotLoadedException are not + * thrown. Each field of reference type of debugee should be casted + * to apropriate ReferenceType (ArrayType, ClassType, InterfaceType) + * in debuger without exceptions. Also, each component type name should + * exist in signature of the Type. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.type.type002 + * nsk.jdi.Field.type.type002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.type.type002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002a.java new file mode 100644 index 00000000000..f06289d6038 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002a.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.type; + +import com.sun.jdi.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class type002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + type002aClassToCheck check = new type002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class type002aClassToCheck { + // No array fields + class Class {} + Class X0 = new Class(); + Boolean Z0 = new Boolean(true); + Byte B0 = new Byte(Byte.MIN_VALUE); + Character C0 = new Character('\u00ff'); + Double D0 = new Double(1); + Float F0 = new Float(1f); + Integer I0 = new Integer(1); + Long L0 = new Long(1l); + String S0 = new String(); + Object O0 = new Object(); + + static Long LS0 = new Long(1l); + private Long LP0 = new Long(1l); + public Long LU0 = new Long(1l); + protected Long LR0 = new Long(1l); + transient Long LT0 = new Long(1l); + volatile Long LV0 = new Long(1l); + final Long LF0 = new Long(1l); + + interface Inter {} + static class InterClass implements Inter {} + Inter E0 = new InterClass(); + static Inter ES0 = new InterClass(); + private Inter EP0 = new InterClass(); + public Inter EU0 = new InterClass(); + protected Inter ER0 = new InterClass(); + transient Inter ET0 = new InterClass(); + volatile Inter EV0 = new InterClass(); + final Inter EF0 = new InterClass(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003.java new file mode 100644 index 00000000000..bab1315ba61 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class type003 { + private static Log log; + private final static String prefix = "nsk.jdi.Field.type."; + private final static String className = "type003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToChekName = prefix + "type003aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(classToChekName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToChekName + + " not found."); + return 2; + } + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + Iterator fieldsIterator = fields.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field field = (Field)fieldsIterator.next(); + String name = field.name(); + Type type; + + // All fields are not initalized in debugee, so all types are not + // loaded. ClassNotLoadedException; should be thrown + try { + type = field.type(); + log.complain("debuger FAILURE 1> Got type for field " + name + + " : " + type + ". Expected Exception " + + "ClassNotLoadedException"); + testFailed = true; + } catch (ClassNotLoadedException e) { + log.display("debuger> Can't get type of field " + name); + log.display("debuger> Exception: " + e); + } + } + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003/TestDescription.java new file mode 100644 index 00000000000..9ce8002fb33 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/type/type003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the type() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/type003 checks assertion: + * public Type type() throws ClassNotLoadedException + * 1. Throws ClassNotLoadedException for object fields, if it + * has not been loaded through the enclosing type's class loader. + * Constructor for each class and interface are not triggered, so all + * classes are not loaded in debugee and ClassNotLoadedException should be + * thrown in debuger VM. + * COMMENTS + * To fix the bug 4423695, all previous classes are replaced with only three basic, + * - Class, Interface, and Array, - + * applied to inner and outer class types. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.type.type003 + * nsk.jdi.Field.type.type003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.type.type003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003a.java new file mode 100644 index 00000000000..fb66b3804e3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type003a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +public class type003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + type003aClassToCheck check = new type003aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class type003aClassToCheck { + class InnerClass {} + InnerClass ic0; + InnerClass aic0[]; + + interface InnerIface {} + InnerIface ii0; + InnerIface aii0[]; + + type003aTestClass tc; + type003aTestClass tcA[]; + type003aIface iface; + type003aIface ifaceA[]; +} + +interface type003aIface { + static boolean b1 = false; +} + +class type003aTestClass implements type003aIface { + static final boolean b2 = true; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004.java new file mode 100644 index 00000000000..47336bb3b65 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Field.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class type004 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Field.type."; + private final static String className = "type004"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] expectedFieldNames = {"f1", "f2", "f3"}; + private final static String[] expectedEnumFieldsNames = { "e1", "e2" }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + Field foundField = checkedClass.fieldByName(expectedEnumFieldsNames[i]); + if (foundField != null) { + if (foundField.type().equals(checkedClass)) { + display("enum " + className + " has field " + expectedEnumFieldsNames[i]); + display("\t of expected type " + className); + } else { + complain("enum " + className + " has field " + expectedEnumFieldsNames[i]); + complain("\t of unexpected type " + foundField.type().name()); + exitStatus = Consts.TEST_FAILED; + } + } else { + complain("enum " + className + " does not have field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004/TestDescription.java new file mode 100644 index 00000000000..02083132ac4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/type/type004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for type() method of Field interface. + * The test checks if the method returns correct result for + * each enum constant field declared in mirrored enum type. + * The test consists of a debugger program (type004.java) + * and debuggee application (type004a.java). + * Package name is nsk.jdi.Field.type . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger finds mirrors of enum types. Every of these + * enum types has the same enum constant fields: e1 and e2. + * The debugger checks if each field is "self-typed", i.e. + * of declaring enum type. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.type.type004 + * nsk.jdi.Field.type.type004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.type.type004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004a.java new file mode 100644 index 00000000000..92d568d7333 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type004a.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Field.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class type004a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static type004Enum1 f1 = type004Enum1.e2; + static type004Enum2 f2 = type004Enum2.e1; + static type004Enum1.Enum1_ f3 = type004Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(type004.SIGNAL_READY); + receiveSignal(type004.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum type004Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum type004Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001.java new file mode 100644 index 00000000000..32d6f6654f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.typeName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class typename001 { + final static String PRIM_CODE = "primitive"; + final static String REF_CODE = "reference"; + final static int TOTAL_FIELDS = 117; + final static String FIELDS_TYPE_NAME[][] = { + {"boolean", "z0", PRIM_CODE}, + {"boolean", "z1", REF_CODE}, + {"boolean", "z2", REF_CODE}, + {"byte", "b0", PRIM_CODE}, + {"byte", "b1", REF_CODE}, + {"byte", "b2", REF_CODE}, + {"char", "c0", PRIM_CODE}, + {"char", "c1", REF_CODE}, + {"char", "c2", REF_CODE}, + {"double", "d0", PRIM_CODE}, + {"double", "d1", REF_CODE}, + {"double", "d2", REF_CODE}, + {"float", "f0", PRIM_CODE}, + {"float", "f1", REF_CODE}, + {"float", "f2", REF_CODE}, + {"int", "i0", PRIM_CODE}, + {"int", "i1", REF_CODE}, + {"int", "i2", REF_CODE}, + {"long", "l0", PRIM_CODE}, + {"long", "l1", REF_CODE}, + {"long", "l2", REF_CODE}, + + {"long", "lS0", PRIM_CODE}, + {"long", "lS1", REF_CODE}, + {"long", "lS2", REF_CODE}, + {"long", "lP0", PRIM_CODE}, + {"long", "lP1", REF_CODE}, + {"long", "lP2", REF_CODE}, + {"long", "lU0", PRIM_CODE}, + {"long", "lU1", REF_CODE}, + {"long", "lU2", REF_CODE}, + {"long", "lR0", PRIM_CODE}, + {"long", "lR1", REF_CODE}, + {"long", "lR2", REF_CODE}, + {"long", "lT0", PRIM_CODE}, + {"long", "lT1", REF_CODE}, + {"long", "lT2", REF_CODE}, + {"long", "lV0", PRIM_CODE}, + {"long", "lV1", REF_CODE}, + {"long", "lV2", REF_CODE}, + {"long", "lF0", PRIM_CODE}, + {"long", "lF1", REF_CODE}, + {"long", "lF2", REF_CODE}, + + {"Class", "X0", REF_CODE}, + {"Class", "X1", REF_CODE}, + {"Class", "X2", REF_CODE}, + {"Boolean", "Z0", REF_CODE}, + {"Boolean", "Z1", REF_CODE}, + {"Boolean", "Z2", REF_CODE}, + {"Byte", "B0", REF_CODE}, + {"Byte", "B1", REF_CODE}, + {"Byte", "B2", REF_CODE}, + {"Char", "C0", REF_CODE}, + {"Char", "C1", REF_CODE}, + {"Char", "C2", REF_CODE}, + {"Double", "D0", REF_CODE}, + {"Double", "D1", REF_CODE}, + {"Double", "D2", REF_CODE}, + {"Float", "F0", REF_CODE}, + {"Float", "F1", REF_CODE}, + {"Float", "F2", REF_CODE}, + {"Int", "I0", REF_CODE}, + {"Int", "I1", REF_CODE}, + {"Int", "I2", REF_CODE}, + {"Long", "L0", REF_CODE}, + {"Long", "L1", REF_CODE}, + {"Long", "L2", REF_CODE}, + {"String", "S0", REF_CODE}, + {"String", "S1", REF_CODE}, + {"String", "S2", REF_CODE}, + {"Object", "O0", REF_CODE}, + {"Object", "O1", REF_CODE}, + {"Object", "O2", REF_CODE}, + + {"Long", "LS0", REF_CODE}, + {"Long", "LS1", REF_CODE}, + {"Long", "LS2", REF_CODE}, + {"Long", "LP0", REF_CODE}, + {"Long", "LP1", REF_CODE}, + {"Long", "LP2", REF_CODE}, + {"Long", "LU0", REF_CODE}, + {"Long", "LU1", REF_CODE}, + {"Long", "LU2", REF_CODE}, + {"Long", "LR0", REF_CODE}, + {"Long", "LR1", REF_CODE}, + {"Long", "LR2", REF_CODE}, + {"Long", "LT0", REF_CODE}, + {"Long", "LT1", REF_CODE}, + {"Long", "LT2", REF_CODE}, + {"Long", "LV0", REF_CODE}, + {"Long", "LV1", REF_CODE}, + {"Long", "LV2", REF_CODE}, + {"Long", "LF0", REF_CODE}, + {"Long", "LF1", REF_CODE}, + {"Long", "LF2", REF_CODE}, + + {"Inter", "E0", REF_CODE}, + {"Inter", "E1", REF_CODE}, + {"Inter", "E2", REF_CODE}, + {"Inter", "ES0", REF_CODE}, + {"Inter", "ES1", REF_CODE}, + {"Inter", "ES2", REF_CODE}, + {"Inter", "EP0", REF_CODE}, + {"Inter", "EP1", REF_CODE}, + {"Inter", "EP2", REF_CODE}, + {"Inter", "EU0", REF_CODE}, + {"Inter", "EU1", REF_CODE}, + {"Inter", "EU2", REF_CODE}, + {"Inter", "ER0", REF_CODE}, + {"Inter", "ER1", REF_CODE}, + {"Inter", "ER2", REF_CODE}, + {"Inter", "ET0", REF_CODE}, + {"Inter", "ET1", REF_CODE}, + {"Inter", "ET2", REF_CODE}, + {"Inter", "EV0", REF_CODE}, + {"Inter", "EV1", REF_CODE}, + {"Inter", "EV2", REF_CODE}, + {"Inter", "EF0", REF_CODE}, + {"Inter", "EF1", REF_CODE}, + {"Inter", "EF2", REF_CODE} + }; + private static Log log; + private final static String prefix = "nsk.jdi.Field.typeName."; + private final static String className = "typename001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get all fields from debugee + ReferenceType refType = debugee.classByName(debugeeName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + debugeeName + + " not found."); + return 2; + } + try { + fields = refType.allFields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields + ", should be " + TOTAL_FIELDS); + return 2; + } + log.display("debuger> Total fields found: " + totalFields); + Iterator fieldsIterator = fields.iterator(); + for (int i = 0; fieldsIterator.hasNext(); i++) { + Field field = (Field)fieldsIterator.next(); + String typeName = field.typeName(); + String name = field.name(); + String nameStat; + + if (typeName == null) { + log.complain("debuger FAILURE 1> typeName is null for " + + i + " field " + name); + testFailed = true; + continue; + } + if (name == null) { + log.complain("debuger FAILURE 2> Name is null for " + i + + " field"); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field (" + name + ") of " + "type " + + typeName + " read."); + try { + nameStat = getStatByName(name, 2); + } catch (Error e) { + log.complain("debuger FAILURE 3> Unexpected Error " + e); + return 2; + } + if (nameStat.equals(REF_CODE)) { + // ReferenceType - name of the type should exist in + // field.typeName() string + String realTypeName; + try { + realTypeName = getStatByName(name, 0); + } catch (Error e) { + log.complain("debuger FAILURE 4> Unexpected Error " + e); + return 2; + } + log.display("debuger> ReferenceType = " + name + "; " + + "typeName = " + typeName + "; " + + "realTypeName = " + realTypeName); + if (typeName.indexOf(realTypeName) == -1) { + log.complain("debuger FAILURE> Type of field " + name + + " is " + typeName + ", but " + "should be " + + realTypeName); + testFailed = true; + } + } else { + // PrimitiveType - name of the type should not be empty + if (typeName.length() == 0) { + log.complain("debuger FAILURE> Empty typeName for " + i + + " field " + name); + testFailed = true; + } + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } + + private static String getStatByName(String name, int field) + throws Error + { + for (int i = 0; i < TOTAL_FIELDS; i++) { + String fieldName = FIELDS_TYPE_NAME[i][1]; + if (fieldName.equals(name)) { + return FIELDS_TYPE_NAME[i][field]; + } + } + throw new Error("Error in test. Unknown field " + name); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001/TestDescription.java new file mode 100644 index 00000000000..74433feee60 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/typeName/typename001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the typeName() method of Field interface of + * com.sun.jdi package. + * nsk/jdi/Field/typename001 checks assertions: + * public java.lang.String typeName() + * 1. Returns: a string + * 2. Returns: a string containing the type name. + * For PrimitiveTypes typeName() should not be null or empty. + * For ReferenceTypes typeName() should not be null and contain name + * of the type. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.typeName.typename001 + * nsk.jdi.Field.typeName.typename001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.typeName.typename001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001a.java new file mode 100644 index 00000000000..3b29fc68206 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Field.typeName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class typename001a { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + final long lF0 = 999, lF1[]={lF0}, lF2[][]={lF1}; + + class Class {} + Class X0 = new Class(), X1[]={X0}, X2[][]={X1}; + Boolean Z0, Z1[]={Z0}, Z2[][]={Z1}; + Byte B0, B1[]={B0}, B2[][]={B1}; + Character C0, C1[]={C0}, C2[][]={C1}; + Double D0, D1[]={D0}, D2[][]={D1}; + Float F0, F1[]={F0}, F2[][]={F1}; + Integer I0, I1[]={I0}, I2[][]={I1}; + Long L0, L1[]={L0}, L2[][]={L1}; + String S0, S1[]={S0}, S2[][]={S1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + + interface Inter {} + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002.java new file mode 100644 index 00000000000..8f3d13b4241 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Field.typeName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class typename002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Field.typeName."; + private final static String className = "typename002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] expectedFieldNames = {"f1", "f2"}; + private final static String[] expectedTypeNames = { "nsk.jdi.Field.typeName.typename002Enum1", + "nsk.jdi.Field.typeName.typename002Enum2" }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i], expectedTypeNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName, String typeName) { + try { + Field foundField = debuggeeClass.fieldByName(fieldName); + if (foundField != null) { + if (foundField.typeName().equals(typeName)) { + display("Field " + fieldName + " is of expected type " + typeName); + } else { + complain("Field " + fieldName + " is of unexpected type " + foundField.typeName()); + exitStatus = Consts.TEST_FAILED; + } + } else { + complain(" Cannot find field " + fieldName); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected exception while checking of field " + fieldName + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002/TestDescription.java new file mode 100644 index 00000000000..c2dd8a5b17b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Field/typeName/typename002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for typeName() method of Field interface. + * The test checks if the method returns correct type name of enum + * constants declared in mirrored enum type. + * The test consists of a debugger program (typename002.java) + * and debuggee application (typename002a.java). + * Package name is nsk.jdi.Field.typeName . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls typeName() method for each constant field + * in mirrored enum types. The returned name must equal to name of + * declaring enum type. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Field.typeName.typename002 + * nsk.jdi.Field.typeName.typename002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Field.typeName.typename002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002a.java new file mode 100644 index 00000000000..f7cdeb9e6b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename002a.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Field.typeName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class typename002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static typename002Enum1 f1; + static typename002Enum2 f2; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(typename002.SIGNAL_READY); + receiveSignal(typename002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum typename002Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum typename002Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java new file mode 100644 index 00000000000..61a10039052 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.FloatType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * FloatType.
    + *
    + * The test checks that for a mirror of a float value the casts
    + * from Type to FloatType and from PrimitiveType to FloatType
    + * don't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a float field and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class floattype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/FloatType/_itself_/floattype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new floattype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.FloatType._itself_.floattype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......String name = 'fl';"); + String name = "fl"; + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type(); + log2(" PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + + FloatType floatType = null; + try { + log2(" checking up on cast: FloatType floatType = (FloatType) type;"); + floatType = (FloatType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + try { + log2(" checking up on cast: FloatType floatType = (FloatType) primitiveType;"); + floatType = (FloatType) primitiveType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001/TestDescription.java new file mode 100644 index 00000000000..fe39c5c4555 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/FloatType/_itself_/floattype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * FloatType. + * The test checks that for a mirror of float value, the casts + * from Type to FloatType and from PrimitiveType to FloatType + * don't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.FloatType._itself_.floattype001; + * the debuggee program - nsk.jdi.FloatType._itself_.floattype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.FloatType._itself_.floattype001 + * nsk.jdi.FloatType._itself_.floattype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.FloatType._itself_.floattype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001a.java new file mode 100644 index 00000000000..9c6b7c6d5b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.FloatType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the floattype001 JDI test. + */ + +public class floattype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static float fl = 0.0f; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001.java new file mode 100644 index 00000000000..7294d37450d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.FloatValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + + +public class compareto001 { + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.FloatValue.compareTo"; + private final static String className = ".compareto001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + private static Value objectValue; + private static List fieldList; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return; + } + + // getting of object to check + Field field = debuggeeClass.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + + objectValue = debuggeeClass.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = debuggeeClass.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = debuggeeClass.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitiveValues = (ArrayReference)arrValue; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + FloatValue value; + Field fldOtherType; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof FloatValue) ) { + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (FloatValue )v1; + + // comparing with debuggee's fields + display("Checking compateTo(Object object) method for FloatValue: " + value); + + for (int j = 0; j < primitiveValues.length(); j++) { + arrValue = primitiveValues.getValue(j); + + fldOtherType = debuggeeClass.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = debuggeeClass.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + + } + + //--------------------------------------------------------- test specific methods + + + private static boolean PerformComparing(FloatValue value, Object object ) { + boolean result = true; + + // assertion [ x.compareTo(x) == 0 ] + if (value.compareTo(value) != 0) { + complain("Failed assertion [ x.compareTo(x) == 0 ] for value: " + value.toString()); + result = false; + } + + if (object instanceof FloatValue) { + FloatValue floatObject = (FloatValue)object; + try { + // assertion [ x.compareTo(y) == 0 <==> x.equals(y) ] + if ( ((value.equals(object)) && (value.compareTo(floatObject) != 0)) || + (!(value.equals(object)) && (value.compareTo(floatObject) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (x.equals(y) == true) ] \n\t" + + "where 'x' is FloatValue: " + value + " and 'y' is FloatValue : " + floatObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(floatObject) + "\n\t" + + "result of (x.equals(y)): " + value.equals(object) ); + result = false; + } + + // assertion [ x.compareTo(y) == 0 <==> y.compareTo(x) == 0 ] + if ( ((value.compareTo(floatObject) == 0) && (floatObject.compareTo(value) != 0)) || + ((value.compareTo(floatObject) != 0) && (floatObject.compareTo(value) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0) ] \n\t" + + "where 'x' is FloatValue: " + value + " and 'y' is FloatValue : " + floatObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(floatObject) + "\n\t" + + "result of (y.compareTo(x)): " + floatObject.compareTo(value) ); + result = false; + } + if (value.compareTo(floatObject) != 0) { + // assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] + if (value.compareTo(floatObject) != -(floatObject.compareTo(value))) { + complain("Failed assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] \n\t" + + "where 'x' is FloatValue: " + value + " and 'y' is FloatValue : " + floatObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(floatObject) + "\n\t" + + "result of (y.compareTo(x)): " + floatObject.compareTo(value) ); + result = false; + } + } + + // assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] + if (value.compareTo(floatObject) > 0) { + FloatValue lessValue = FindLessFloatValue(floatObject); + if (lessValue != null) { + if (value.compareTo(lessValue) <= 0) { + complain("Failed assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] \n\t" + + "where 'x' is FloatValue: " + value + " , 'y' is FloatValue : " + floatObject + " , 'z' is FloatValue : " + lessValue + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(floatObject) + "\n\t" + + "result of (y.compareTo(z)): " + floatObject.compareTo(lessValue) + "\n\t" + + "result of (x.compareTo(z)): " + value.compareTo(lessValue) ); + result = false; + } + } + } + + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "FloatValue: " + value + " and FloatValue argument: " + object); + result = false; + } + + } else if (object == null) { + try { + value.compareTo(null); + complain("Does not throw expected NullPointerException when comparing \n\t" + + "FloatValue: " + value + " and null argument"); + result = false; + } catch (NullPointerException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "FloatValue: " + value + " and null argument"); + result = false; + } + } else { + try { + value.compareTo((FloatValue)object); + complain("Does not throw expected ClassCastException when comparing \n\t" + + "FloatValue: " + value + " and argument: " + object); + result = false; + } catch (ClassCastException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "FloatValue: " + value + " and argument: " + object); + result = false; + } + } + + return result; + } + + /** + * This function searches the static fieldList - the list of mirrored + * fields of debuggee's compareto001aClassToCheck class. Search is aimed + * to find another FloatValue field which is less then method's argument via + * compareTo method. + */ + + private static FloatValue FindLessFloatValue (FloatValue currentValue) { + FloatValue result = null; + + for (int i = 0; i < fieldList.size(); i++ ) { + + Field field = (Field )fieldList.get(i); + FloatValue newValue = (FloatValue)((ObjectReference )objectValue).getValue(field); + + if (currentValue.compareTo(newValue) > 0) { + result = newValue; + break; + } + } + return result; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001/TestDescription.java new file mode 100644 index 00000000000..68975481c20 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/FloatValue/compareTo/compareto001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the compareTo(Object o) method of com.sun.jdi.FloatValue + * interface. This method is inherited from java.lang.Comparable interface. + * The test checks the following assertions which imply from spec for + * Comparable.compareTo(Object o): + * - (x.compareTo(y) == 0) is identical to (x.equals(y) == true); + * - (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0); + * - if (x.compareTo(y) == i) then (y.compareTo(x) == -i); + * - if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0); + * - if an argument is null, then NullPointerException is thrown; + * - if an argument is not of FloatValue type, then a ClassCastException is thrown. + * where 'x', 'y' and 'z' denote FloatValue object. + * The debugger program - nsk.jdi.FloatValue.compareto.compareto001; + * the debuggee program - nsk.jdi.FloatValue.compareto.compareto001a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * Then the debugger gets a list of float fields of debuggee's object of + * compareto001aClassToCheck type. For every field a mirror of FloatValue type + * is created and the assertions are checked. A various values for comparison + * are got from values of mirrors of debuggee's static fields. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.FloatValue.compareTo.compareto001 + * nsk.jdi.FloatValue.compareTo.compareto001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.FloatValue.compareTo.compareto001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001a.java new file mode 100644 index 00000000000..113eca3fbf3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/compareTo/compareto001a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.FloatValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class compareto001a { + + //----------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + static compareto001aClassToCheck testedObj = new compareto001aClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + pipe.println(compareto001.SIGNAL_READY); +// receiveSignal(compareto001.SIGNAL_GO); + + receiveSignal(compareto001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class compareto001aClassToCheck { + public float floatMAX = Float.MAX_VALUE; + public float float1 = 1; + public float float0 = 0; + public float float_1 = -1; + public float floatMIN = Float.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001.java new file mode 100644 index 00000000000..6ed5a5a7569 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.FloatValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * FloatValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.FloatValue.equals()
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static float plus1_1 = +1f;
    + * public static float plus1_2 = +1f;
    + * public static float minus1 = -1f;
    + * public static double double_plus1 = +1d;
    + *
    + * which a debugger mirros as :
    + *
    + * FloatValue fvplus1_1;
    + * FloatValue fvplus1_2;
    + * FloatValue fvminus1;
    + * DoubleValue dvplus1;
    + *
    + * the following is true:
    + *
    + * fvplus1_1 == fvplus1_2
    + * fvplus1_1 != fvminus1
    + * fvplus1_1 != dvplus1
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/FloatValue/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.FloatValue.equals.equals001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("equals001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field ffplus1_1 = execClass.fieldByName("plus1_1"); + Field ffplus1_2 = execClass.fieldByName("plus1_2"); + Field ffminus1 = execClass.fieldByName("minus1"); + Field fdplus1 = execClass.fieldByName("double_plus1"); + + FloatValue fvplus1_1 = (FloatValue) execClass.getValue(ffplus1_1); + FloatValue fvplus1_2 = (FloatValue) execClass.getValue(ffplus1_2); + FloatValue fvminus1 = (FloatValue) execClass.getValue(ffminus1); + DoubleValue dvplus1 = (DoubleValue) execClass.getValue(fdplus1); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!fvplus1_1.equals(fvplus1_2)) + expresult = 1; + break; + + case 1: if (fvplus1_1.equals(fvminus1)) + expresult = 1; + break; + + case 2: if (fvplus1_1.equals(dvplus1)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..e89f3e4eddd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/FloatValue/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * FloatValue. + * The test checks up that a result of the method + * com.sun.jdi.FloatValue.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this FloatValue for equality. + * Returns: true if the Object is a FloatValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.FloatValue.equals.equals001; + * a debuggee program - nsk.jdi.FloatValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.FloatValue.equals.equals001 + * nsk.jdi.FloatValue.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.FloatValue.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001a.java new file mode 100644 index 00000000000..836c459e50a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.FloatValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001a JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static float pos_inf = Float.POSITIVE_INFINITY; +// public static float pos_zero = 0.0f; +// public static float neg_zero = -0.0f; +// public static float neg_inf = Float.NEGATIVE_INFINITY; + +// public static float pos_largest = Float.MAX_VALUE; +// public static float pos_smallest = Float.MIN_VALUE; +// public static float neg_largest = -Float.MAX_VALUE; +// public static float neg_smallest = -Float.MIN_VALUE; + +// public static float flo_nan = Float.NaN; + + public static float plus1_1 = +1.0f; + public static float plus1_2 = +1.0f; + public static float minus1 = -1.0f; + + public static double double_plus1 = +1.0d; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * types and when parameter is null.
    + * Analyse of the method executing is performed by PerformComparing + * method.
    + * First parameter of PerformComparing is static field of testedObj,
    + * which is placed onto debugee's side.
    + * + * Second parameter is got from debugee too:
    + * Debugee has array of boundary values of each primitive type, execTest reads
    + * them and calls PerformComparing for each of them.
    + */ +public class equals002 { + + private final static String prefix = "nsk.jdi.FloatValue.equals."; + private final static String className = "equals002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static ReferenceType refType; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + execTest(); + debugee.quit(); + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + private static void execTest() { + + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("Class '" + debugeeName + "' not found."); + return; + } + + // getting of object to check + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = refType.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = refType.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + List fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + FloatValue value; + Field fldOtherType; + String msg; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + log.display(""); + msg = "***" + field; + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof FloatValue) ) { + msg += " is not FloatValue (skipped)"; + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (FloatValue )v1; + + // comparing with debugee's fields + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = refType.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = refType.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static boolean PerformComparing(FloatValue value, Object object ) { + boolean res = true; + String msg = ""; + try { + if ( value.equals(object) ) { + if ( object instanceof FloatValue ) { + if ( value.value() == ((PrimitiveValue )object).floatValue() ) { + msg += "--> " + value + " == " + object; + } else { + msg += "##> " + value + " == " + object; + res = false; + } + } + else { + msg += "##> " + value + " == " + object + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if ( object == null ) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if ( object instanceof FloatValue ) { + if ( value.value() != ((PrimitiveValue )object).floatValue() ) { + msg += "--> " + value + " != " + object; + } else { + msg += "##> " + value + " != " + object; + res = false; + } + } + else { + msg += "--> " + value + " != " + object; + } + } + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..d70a83a82ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/FloatValue/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.FloatValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this FloatValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is a FloatValue and if applying "==" to the two + * mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has boundary values of primitive + * types. Also, case when parameter is considered. + * No exceptions are expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.FloatValue.equals.equals002 + * nsk.jdi.FloatValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.FloatValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002a.java new file mode 100644 index 00000000000..7b1de2a72da --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/equals/equals002a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.FloatValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * equals002a is deugee's part of the test.
    + * It contains the static fields with boundary values for each primitive type.
    + * ClassToCheck delivers values for first parameter of equals.
    + */ +public class equals002a { + + static ClassToCheck testedObj = new ClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class ClassToCheck { + public float floatMAX = Float.MAX_VALUE; + public float float1 = 1; + public float float0 = 0; + public float float_1 = -1; + public float floatMIN = Float.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001.java new file mode 100644 index 00000000000..846e7168174 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.FloatValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * FloatValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.FloatValue.hashCode()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static float plus1_1 = +1f;
    + * public static float plus1_2 = +1f;
    + * public static float pos_largest = Float.MAX_VALUE;
    + *
    + * which a debugger mirros as :
    + *
    + * FloatValue fvplus1_1;
    + * FloatValue fvplus1_2;
    + * FloatValue fvpos_largest;
    + *
    + * the following is true:
    + *
    + * fvpos_largest.hashCode() == fvpos_largest.hashCode()
    + * fvplus1_1.hashCode() == fvplus1_2.hashCode()
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/FloatValue/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.FloatValue.hashCode.hashcode001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("hashcode001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field ffplus1_1 = execClass.fieldByName("plus1_1"); + Field ffplus1_2 = execClass.fieldByName("plus1_2"); + Field ffpos_largest = execClass.fieldByName("pos_largest"); + + FloatValue fvplus1_1 = (FloatValue) execClass.getValue(ffplus1_1); + FloatValue fvplus1_2 = (FloatValue) execClass.getValue(ffplus1_2); + FloatValue fvpos_largest = + (FloatValue) execClass.getValue(ffpos_largest); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (fvpos_largest.hashCode() != fvpos_largest.hashCode()) + expresult = 1; + break; + + case 1: if (fvplus1_1.hashCode() != fvplus1_2.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..cf130bd54af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/FloatValue/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * FloatValue. + * The test checks up that a result of the method + * com.sun.jdi.FloatValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this FloatValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.FloatValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.FloatValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.FloatValue.hashCode.hashcode001 + * nsk.jdi.FloatValue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.FloatValue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..5ca688013b7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/hashCode/hashcode001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.FloatValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001a JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static float pos_inf = Float.POSITIVE_INFINITY; +// public static float pos_zero = 0.0f; +// public static float neg_zero = -0.0f; +// public static float neg_inf = Float.NEGATIVE_INFINITY; + + public static float pos_largest = Float.MAX_VALUE; +// public static float pos_smallest = Float.MIN_VALUE; +// public static float neg_largest = -Float.MAX_VALUE; +// public static float neg_smallest = -Float.MIN_VALUE; + +// public static float flo_nan = Float.NaN; + + public static float plus1_1 = +1.0f; + public static float plus1_2 = +1.0f; +// public static float minus1 = -1.0f; + +// public static double double_plus1 = +1.0d; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * FloatValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.FloatValue.value()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static float pos_inf = Float.POSITIVE_INFINITY;
    + * public static float pos_zero = 0.0d;
    + * public static float neg_zero = -0.0d;
    + * public static float neg_inf = Float.NEGATIVE_INFINITY;
    + * public static float pos_largest = Float.MAX_VALUE;
    + * public static float pos_smallest = Float.MIN_VALUE;
    + * public static float neg_largest = -Float.MAX_VALUE;
    + * public static float neg_smallest = -Float.MIN_VALUE;
    + * public static float float_nan = Float.NaN;
    + *
    + * which a debugger mirros as :
    + *
    + * FloatValue fvpos_inf;
    + * FloatValue fvpos_zero;
    + * FloatValue fvneg_zero;
    + * FloatValue fvneg_inf;
    + * FloatValue fvpos_largest;
    + * FloatValue fvpos_smallest;
    + * FloatValue fvneg_largest;
    + * FloatValue fvneg_smallest;
    + * FloatValue fvdouble_nan;
    + *
    + * the following is true:
    + *
    + * fvneg_inf.value() == Floate.NEGATIVE_INFINITY
    + * fvneg_largest.value() == -Float.MAX_VALUE
    + * fvneg_smallest.value() == -Double.MIN_VALUE
    + * fvneg_zero.value() == -0.0d
    + * fvpos_zero.value() == 0.0d
    + * fvpos_smallest.value() == Float.MIN_VALUE
    + * fvpos_largest.value() == Float.MAX_VALUE
    + * fvpos_inf.value() == Float.POSITIVE_INFINITY
    + * fvfloat_nan.value() != fvfloat_nan.value()
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/FloatValue/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.FloatValue.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("value001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field ffneg_inf = execClass.fieldByName("neg_inf"); + Field ffneg_largest = execClass.fieldByName("neg_largest"); + Field ffneg_smallest = execClass.fieldByName("neg_smallest"); + Field ffneg_zero = execClass.fieldByName("neg_zero"); + Field ffpos_zero = execClass.fieldByName("pos_zero"); + Field ffpos_smallest = execClass.fieldByName("pos_smallest"); + Field ffpos_largest = execClass.fieldByName("pos_largest"); + Field ffpos_inf = execClass.fieldByName("pos_inf"); + Field ffloat_nan = execClass.fieldByName("float_nan"); + + FloatValue fvneg_inf = (FloatValue) execClass.getValue(ffneg_inf); + FloatValue fvneg_largest = (FloatValue) execClass.getValue(ffneg_largest); + FloatValue fvneg_smallest = (FloatValue) execClass.getValue(ffneg_smallest); + FloatValue fvneg_zero = (FloatValue) execClass.getValue(ffneg_zero); + FloatValue fvpos_zero = (FloatValue) execClass.getValue(ffpos_zero); + FloatValue fvpos_smallest = (FloatValue) execClass.getValue(ffpos_smallest); + FloatValue fvpos_largest = (FloatValue) execClass.getValue(ffpos_largest); + FloatValue fvpos_inf = (FloatValue) execClass.getValue(ffpos_inf); + FloatValue fvfloat_nan = (FloatValue) execClass.getValue(ffloat_nan); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (fvneg_inf.value() != Float.NEGATIVE_INFINITY) + expresult = 1; + break; + + case 1: if (fvneg_largest.value() != -Float.MAX_VALUE) + expresult = 1; + break; + + case 2: if (fvneg_smallest.value() != -Float.MIN_VALUE) + expresult = 1; + break; + + case 3: if (fvneg_zero.value() != -0.0d) + expresult = 1; + break; + + case 4: if (fvpos_zero.value() != 0.0d) + expresult = 1; + break; + + case 5: if (fvpos_smallest.value() != Float.MIN_VALUE) + expresult = 1; + break; + + case 6: if (fvpos_largest.value() != Float.MAX_VALUE) + expresult = 1; + break; + + case 7: if (fvpos_inf.value() != Float.POSITIVE_INFINITY) + expresult = 1; + break; + + case 8: if ( !(fvfloat_nan.value() != fvfloat_nan.value()) ) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001/TestDescription.java new file mode 100644 index 00000000000..6205b5e39da --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/FloatValue/value/value001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * FloatValue. + * The test checks up that a result of the method + * com.sun.jdi.FloatValue.value() + * complies with its spec: + * public float value() + * Returns this FloatValue as a float. + * Returns: the float mirrored by this object. + * The test works as follows: + * A debugger program - nsk.jdi.FloatValue.value.value001; + * a debuggee program - nsk.jdi.FloatValue.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.FloatValue.value.value001 + * nsk.jdi.FloatValue.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.FloatValue.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001a.java new file mode 100644 index 00000000000..53b7b9f8ab1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatValue/value/value001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.FloatValue.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static float pos_inf = Float.POSITIVE_INFINITY; + public static float pos_zero = 0.0f; + public static float neg_zero = -0.0f; + public static float neg_inf = Float.NEGATIVE_INFINITY; + + public static float pos_largest = Float.MAX_VALUE; + public static float pos_smallest = Float.MIN_VALUE; + public static float neg_largest = -Float.MAX_VALUE; + public static float neg_smallest = -Float.MIN_VALUE; + + public static float float_nan = Float.NaN; + +// public static float plus1_1 = +1.0f; +// public static float plus1_2 = +1.0f; +// public static float minus1 = -1.0f; + +// public static double double_plus1 = +1.0d; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.IntegerArgument.intValue()
    + * complies with the following requirements in its specification:
    + * "Returns the value of the argument as a int."
    + * when the value of IntegerArgument is set
    + * with the method setValue(int value);
    + * The checking values are as follows:
    + * min()
    + * max()
    + * min()+1
    + * min()-1
    + * max()+1
    + *
    + * In case of a value set with setValue()
    + * doesn't match a value get with the following intValue(),
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class intvalue001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.intValue\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.intValue()\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.IntegerArgument intArgument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + Integer intI = null; + int i; + + i = intArgument.min(); + intArgument.setValue(i); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(min()); intValue() == min()\n" + + "result: false\n"); + } + + i = intArgument.max(); + intArgument.setValue(i); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(max()); intValue() == max()\n" + + "result: false\n"); + } + + if (intArgument.min() < intArgument.max()) { + i = intArgument.min() + 1; + intArgument.setValue(i); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(min()+1); intValue() == min()+1\n" + + "result: false\n"); + } + } + + if (intArgument.min() > intI.MIN_VALUE) { + i = intArgument.min() - 1; + intArgument.setValue(i); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(min()-1); intValue() == min()-1\n" + + "result: false\n"); + } + } + + if (intArgument.max() < intI.MAX_VALUE) { + i = intArgument.max() + 1; + intArgument.setValue(i); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(max()+1); intValue() == max()+1\n" + + "result: false\n"); + } + } + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue001/TestDescription.java new file mode 100644 index 00000000000..7e53758b366 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/intValue/intvalue001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the method + * IntegerArgument.intValue() + * complies with the following requirements: + * "Returns the value of the argument as a int." + * when the value of the argument is set + * with the method setValue(int value). + * The cases tested are as follows: + * min() + * max() + * min()+1 + * min()-1> + * max()+1 + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Arguments of Connectors. + * If no the intArgument is found out the test exits + * with the return value = 95 and a warning message. + * - To the above values the following check is applied: + * int value set with intArgument.setValue() + * must be equal to int value get with intArguemnt.intValue() + * In case of inequality of the values + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.intValue.intvalue001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.intValue.intvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002.java new file mode 100644 index 00000000000..e78982a4463 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerArgument.intValue; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.IntegerArgument.intValue()
    + * complies with the following requirements in its specification:
    + * "Sets the value of the argument."
    + * when the value of the IntegerArgument is set
    + * the super.method setValue(String value).
    + * The checking values are as follows:
    + * min()
    + * max()
    + * min()+1
    + * min()-1
    + * max()+1
    + *
    + * In case of int value i1 set with
    + * setValue(stringValueOf(i1));
    + * doesn't match int value i2 get with
    + * i2 = intValue();
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class intvalue002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.intValue\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.intValue()\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.IntegerArgument intArgument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + Integer intI = null; + int i; + + i = intArgument.min(); + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(stringValueOf(min()); " + + "intValue() == min()\n" + + "result: false\n"); + } + + i = intArgument.max(); + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(stringValueOf(max)); " + + "intValue() == max()\n" + + "result: false\n"); + } + + if (intArgument.min() < intArgument.max()) { + i = intArgument.min() + 1; + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(stringValueOf(min()+1); " + + "intValue() == min()+1\n" + + "result: false\n"); + } + } + + if (intArgument.min() > intI.MIN_VALUE) { + i = intArgument.min() - 1; + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(stringValueOf(min()-1); " + + "intValue() == min()-1\n" + + "result: false\n"); + } + } + + if (intArgument.max() < intI.MAX_VALUE) { + i = intArgument.max() + 1; + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(stringValueOf(max()+1); " + + "intValue() == max()+1\n" + + "result: false\n"); + } + } + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002/TestDescription.java new file mode 100644 index 00000000000..f546414576b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/intValue/intvalue002/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/intValue/intvalue002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the method + * IntegerArgument.intValue(int value) + * complies with the following requirements: + * "Returns the value of the argument as a int." + * when the value of the argument was set + * with the super.method setValue(String value). + * The cases tested are as follows: + * min() + * max() + * min()+1 + * min()-1> + * max()+1 + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Arguments of Connectors. + * If no the intArgument is found out the test exits + * with the return value = 95 and a warning message. + * - To the above values the following check is applied: + * int value i1 set with the super.method + * intArgument.setValue(stringValueOf(i1)); + * must be equal to int value i2 get with + * i2 = intArgument.intValue(); + * In case of inequality of the values + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.intValue.intvalue002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.intValue.intvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001.java new file mode 100644 index 00000000000..dc108516356 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * Connector.IntegerArgument.isValid(int value)
    + * complies with the following requirements:
    + * "true if min() <= value <= max()"
    + * when the value is one of the following:
    + * min()
    + * max()
    + * min()+1
    + * min()-1
    + * max()+1
    + *
    + * In case of a wrong result returned,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class isvalid001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.IntegerArgument intArgument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + Integer intI = null; + + if (intArgument.isValid(intArgument.min())) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(min())\n" + + "result: false\n"); + } + + if (intArgument.isValid(intArgument.max())) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(max())\n" + + "result: false\n"); + } + + if (intArgument.min() < intArgument.max()) { + if (intArgument.isValid(intArgument.min() + 1)) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(min()+1)\n" + + "result: false\n"); + } + } + + if (intArgument.min() > intI.MIN_VALUE) { + if (!intArgument.isValid(intArgument.min() - 1)) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(min()-1)\n" + + "result: true\n"); + } + } + + if (intArgument.max() < intI.MAX_VALUE) { + if (!intArgument.isValid(intArgument.max() + 1)) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(max()+1)\n" + + "result: true\n"); + } + } + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001/TestDescription.java new file mode 100644 index 00000000000..ef5b8a1de3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/isValid/isvalid001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the method + * IntegerArgument.isValid(int value) + * complies with the following requirements: + * "true if min() <= value <= max()" + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Arguments of Connectors. If no intArgument is found out + * the test exits with the return value = 95 and a warning message. + * - The follwing checks are made: + * intArgument.isValid(int.Argument.min()) + * expexted result - true + * if (intArgument.min() < intArgument.max()) + * intArgument.isValid(int.Argument.min() + 1) + * expected result - true + * intArgument.isValid(int.Argument.max()) + * expexted result - true + * if (intArgument.min() > INTEGER.MIN_VALUE) + * intArgument.isValid(int.Argument.min() - 1) + * expected result - false + * if (intArgument.max() < INTEGER.MAX_VALUE) + * intArgument.isValid(int.Argument.max() + 1) + * expected result - false + * In case of unexpected result + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.isValid.isvalid001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.isValid.isvalid001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002.java new file mode 100644 index 00000000000..7c9669a1da8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * Connector.IntegerArgument.isValid(String value)
    + * complies with the following requirements:
    + * "true if value represents an int that is
    + * min() <= value <= max()"
    + * when the value is one of the following:
    + * stringValueOf(min())
    + * stringValueOf(max())
    + * stringValueOf(min()+1)
    + * stringValueOf(min()-1)
    + * stringValueOf(max()+1)
    + *
    + * In case of a wrong result returned,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class isvalid002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.IntegerArgument intArgument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + Integer intI = null; + + if (intArgument.isValid(intArgument.stringValueOf(intArgument.min()))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(stringValueOf(min()))\n" + + "result: false\n"); + } + + if (intArgument.isValid(intArgument.stringValueOf(intArgument.max()))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(stringValueOf(max()))\n" + + "result: false\n"); + } + + if (intArgument.min() < intArgument.max()) { + if (intArgument.isValid( + intArgument.stringValueOf(intArgument.min() + 1))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(stringValueOf(min()+1))\n" + + "result: false\n"); + } + } + + if (intArgument.min() > intI.MIN_VALUE) { + if (!intArgument.isValid( + intArgument.stringValueOf(intArgument.min() - 1))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(stringValueOf(min()-1))\n" + + "result: true\n"); + } + } + + if (intArgument.max() < intI.MAX_VALUE) { + if (!intArgument.isValid( + intArgument.stringValueOf(intArgument.max() + 1))) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(stringValueOf(max()+1))\n" + + "result: true\n"); + } + } + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002/TestDescription.java new file mode 100644 index 00000000000..13331fa82d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid002/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/isValid/isvalid002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the method + * IntegerArgument.isValid(String value) + * complies with the following requirements: + * "true if value represents an int that is + * min() <= value <= max()" + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Arguments of Connectors. If no intArgument is found out + * the test exits with the return value = 95 and a warning message. + * - The follwing checks are made: + * intArgument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.min())) + * expexted result - true + * if (intArgument.min() < intArgument.max()) + * intArgument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.min() + 1)) + * expected result - true + * intArgument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.max()) + * expexted result - true + * if (intArgument.min() > INTEGER.MIN_VALUE) + * intArgument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.min() - 1) + * expected result - false + * if (intArgument.max() < INTEGER.MAX_VALUE) + * intArgument.isValid( + * intArgurmnt.stringValueOf( + * int.Argument.max() + 1) + * expected result - false + * In case of unexpected result + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.isValid.isvalid002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.isValid.isvalid002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003.java new file mode 100644 index 00000000000..75600cdc3b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * Connector.IntegerArgument.isValid(String value)
    + * complies with the following requirements:
    + * "true if value represents an int that is
    + * min() <= value <= max()"
    + * when the value is one of the following strings:
    + * "a"
    + * ""
    + * (String) null
    + * a null-string
    + * to which expected results are false.
    + *
    + * In case of a wrong result returned,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class isvalid003 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.IntegerArgument intArgument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + if (!intArgument.isValid("")) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid('')\n" + + "result: true\n"); + } + + if (!intArgument.isValid("a")) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid('a')\n" + + "result: true\n"); + } + + if (!intArgument.isValid((String) null)) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid((String) null))\n" + + "result: true\n"); + } + + String s = null; + if (!intArgument.isValid(s)) { + } else { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(String s = null)\n" + + "result: true\n"); + } + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003/TestDescription.java new file mode 100644 index 00000000000..2e1a1fdd946 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/isValid/isvalid003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/isValid/isvalid003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the method + * IntegerArgument.isValid(String value) + * complies with the following requirements: + * "true if value represents an int that is + * min() <= value <= max()" + * in case when parameter is one of "", "a", null, null-string. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Arguments of Connectors. If no intArgument is found out + * the test exits with the return value = 95 and a warning message. + * - The follwing checks are made: + * !intArgument.isValid("") + * expected result - true + * !intArgument.isValid("a") + * expected result - true + * In case of unexpected result + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.isValid.isvalid003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.isValid.isvalid003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/max/max001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/max/max001.java new file mode 100644 index 00000000000..27efbe9e777 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/max/max001.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerArgument.max; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.IntegerArgument.max()
    + * complies with the following requirements:
    + * -2147483648 <= max() <= 2147483647
    + * min() <= max()
    + *
    + * In case of wrong values,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class max001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.max\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.max\n" ; + + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.IntegerArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + int iMax = argument.max(); + + if (iMax < -2147483648) { + exitCode = exitCode2; + out.println(sErr2 + + "check: argument.max() >= -2147483648\n"); + } + + if (iMax > 2147483647) { + exitCode = exitCode2; + out.println(sErr2 + + "check: argument.max <= 2147483647\n"); + } + + if (iMax < argument.min()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: argument.max >= argument.min\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/max/max001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/max/max001/TestDescription.java new file mode 100644 index 00000000000..d500425da46 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/max/max001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/max/max001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.IntegerArgument.max() + * complies with the following requirements: + * -2147483648 <= max() <= 2147483647 + * min() <= max() + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Arguments of Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * IF -2147483648 > argument.max() + * THEN an error detected + * ELSE the check passed + * IF argument.max() > 2147483647 + * THEN an error detected + * ELSE the check passed + * IF argument.max() < argument.min() + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.max.max001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.max.max001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/min/min001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/min/min001.java new file mode 100644 index 00000000000..aff2f5a73bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/min/min001.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerArgument.min; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.IntegerArgument.min()
    + * complies with the following requirement:
    + * -2147483648 <= min() <= 2147483647
    + *
    + * In case of wrong values,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class min001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.min\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.min\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.IntegerArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + int iMin = argument.min(); + + if (iMin < -2147483648) { + exitCode = exitCode2; + out.println(sErr2 + + "check: iMin < -2147483648\n"); + } + + if (iMin > 2147483647) { + exitCode = exitCode2; + out.println(sErr2 + + "check: iMin > 2147483647\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/min/min001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/min/min001/TestDescription.java new file mode 100644 index 00000000000..3fc5ffafb1d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/min/min001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/min/min001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.IntegerArgument.min() + * complies with the following requirement: + * -2147483648 <= min() <= 2147483647 + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * IF -2147483648 > argument.min() + * THEN an error detected + * ELSE the check passed + * IF argument.min() > 2147483647 + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.min.min001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.min.min001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001.java new file mode 100644 index 00000000000..39a00aab3bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerArgument.setValue; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.IntegerArgument.setValue()
    + * complies with the following requirements in its specification:
    + * "Sets the value of the argument."
    + *
    + * If after two following one by one methods, in all four possible cases,
    + * setValue(int) and super.setValue(String)
    + * with different values to set, the value returned by intValue()
    + * isn't equal to the second value set
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class setvalue001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + static int exitCode = 0; + static int exitCode0 = 0; + static int exitCode2 = 2; + +// + static Connector.IntegerArgument intArgument = null; + static int i; + + private static void check(int i1, PrintStream out) { + +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.setValue()\n" ; + + + intArgument.setValue(i); + intArgument.setValue(i1); + if (intArgument.intValue() != i1) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(int); setValue(int)\n" + + "result: no equality\n"); + } + + intArgument.setValue(i); + intArgument.setValue(intArgument.stringValueOf(i1)); + if (intArgument.intValue() != i1) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(int); setValue(String)\n" + + "result: no equality\n"); + } + + intArgument.setValue(intArgument.stringValueOf(i)); + intArgument.setValue(i1); + if (intArgument.intValue() != i1) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(String); setValue(int)\n" + + "result: no equality\n"); + } + + intArgument.setValue(intArgument.stringValueOf(i)); + intArgument.setValue(intArgument.stringValueOf(i1)); + if (intArgument.intValue() != i1) { + exitCode = exitCode2; + out.println(sErr2 + + "check: setValue(String); setValue(String)\n" + + "result: no equality\n"); + } + } + + public static int run(String argv[], PrintStream out) { + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.setValue\n" ; + + Integer intI = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + + if (intArgument.min() >= 0) { + i = -1; + } else { + i = 1; + } + + check(intArgument.min(), out); + check(intArgument.max(), out); + if (intArgument.min() < intArgument.max()) { + check(intArgument.min() + 1, out); + } + if (intArgument.min() > intI.MIN_VALUE) { + check(intArgument.min() - 1, out); + } + if (intArgument.max() < intI.MAX_VALUE) { + check(intArgument.max() + 1, out); + } + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001/TestDescription.java new file mode 100644 index 00000000000..8b838932362 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/setValue/setvalue001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/setValue/setvalue001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the methods + * IntegerArgument.setValue(int value) and + * Argument.setValue(String value) + * complies with the following requirements: + * "Sets the value of the argument." + * when Argument is IntegerArgument. + * The testing values are as follows: + * min() + * max() + * min()+1 + * min()-1> + * max()+1 + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Arguments of Connectors. + * If no the intArgument is found out the test exits + * with the return value = 95 and a warning message. + * - To the above values the following check is applied: + * intArgument.setValue(int i); + * intArgument.setValue(int i1); + * intArgument.setValue(int i); + * intArgument.setValue(intArgument.stringValueOf(i1)); + * intArgument.setValue(intArgument.stringValueOf(i)); + * intArgument.setValue(int i1); + * intArgument.setValue(intArgument.stringValueOf(i)); + * intArgument.setValue(intArgument.stringValueOf(i1)); + * In all checks the value returned by followed intArgument.intValue() + * must be equal to int i1. + * In case of inequality of the values + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.setValue.setvalue001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.setValue.setvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001.java new file mode 100644 index 00000000000..34ba655155d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerArgument.stringValueOf; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.IntegerArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector_IntegerArgument.
    + *
    + * The test checks up that results of the method
    + * Connector.IntegerArgument.stringValueOf()
    + * complies with the following requirements in its specification:
    + * "Returns the String representation of the value parameter."
    + * The checking values are as follows:
    + * min()
    + * max()
    + * min()+1
    + * min()-1
    + * max()+1
    + *
    + * In case of a value set with setValue(stringValueOf(value))
    + * is not equal to a value returned by the following intValue(),
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + +// +public class stringvalueof001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.intValue\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.IntegerArgument.intValue()\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.IntegerArgument intArgument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + intArgument = (Connector.IntegerArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (intArgument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + +// + "no Connector with IntegerArgument found\n"); + return exitCode0; + } + } + + Integer intI = null; + int i; + + i = intArgument.min(); + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: stringValueOf(min())\n" + + "result: inequality\n"); + } + + i = intArgument.max(); + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: stringValueOf(max())\n" + + "result: inequality\n"); + } + + if (intArgument.min() < intArgument.max()) { + i = intArgument.min() + 1; + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: stringValueOf(min()+1)\n" + + "result: inequality\n"); + } + } + + if (intArgument.min() > intI.MIN_VALUE) { + i = intArgument.min() - 1; + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: stringValueOf(min()-1)\n" + + "result: inequality\n"); + } + } + + if (intArgument.max() < intI.MAX_VALUE) { + i = intArgument.max() + 1; + intArgument.setValue(intArgument.stringValueOf(i)); + if (intArgument.intValue() != i) { + exitCode = exitCode2; + out.println(sErr2 + + "check: stringValueOf(max()+1)\n" + + "result: inequality\n"); + } + } + + if (exitCode != exitCode0) { + out.println("TEST FAILED"); + } + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001/TestDescription.java new file mode 100644 index 00000000000..e6c9fb4a3b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerArgument/stringValueOf/stringvalueof001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.IntegerArgument. + * The test checks up that a result of the method + * IntegerArgument.stringValueOf() + * complies with the following requirements: + * "Returns the String representation of the value parameter." + * The cases tested are as follows: + * min() + * max() + * min()+1 + * min()-1> + * max()+1 + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.IntegerArgument object is searched among + * Arguments of Connectors. + * If no the intArgument is found out the test exits + * with the return value = 95 and a warning message. + * - To the above values the following check is applied: + * int value i used as parameter in + * intArgument.setValue(intArgument.stringValueOf(i)) + * must be equal to int value returned by intArgument.intValue() + * In case of inequality of the values + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerArgument.stringValueOf.stringvalueof001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerArgument.stringValueOf.stringvalueof001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java new file mode 100644 index 00000000000..2b7d8255ab0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.IntegerType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * IntegerType.
    + *
    + * The test checks that for a mirror of an integer value the casts
    + * from Type to IntegerType and from PrimitiveType to IntegerType
    + * don't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares an integer field and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class integertype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/IntegerType/_itself_/integertype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new integertype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.IntegerType._itself_.integertype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......String name = 'in';"); + String name = "in"; + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type(); + log2(" PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + + IntegerType integerType = null; + try { + log2(" checking up on cast: IntegerType integerType = (IntegerType) type;"); + integerType = (IntegerType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + try { + log2(" checking up on cast: IntegerType integerType = (IntegerType) primitiveType;"); + integerType = (IntegerType) primitiveType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001/TestDescription.java new file mode 100644 index 00000000000..33d94667c8b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerType/_itself_/integertype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * IntegerType. + * The test checks that for a mirror of an integer value the casts + * from Type to IntegerType and from PrimitiveType to IntegerType + * don't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.IntegerType._itself_.integertype001; + * the debuggee program - nsk.jdi.IntegerType._itself_.integertype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerType._itself_.integertype001 + * nsk.jdi.IntegerType._itself_.integertype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerType._itself_.integertype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001a.java new file mode 100644 index 00000000000..8208ff837c8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.IntegerType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the integertype001 JDI test. + */ + +public class integertype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static int in = 0; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001.java new file mode 100644 index 00000000000..ae2411b1853 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.IntegerValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + + +public class compareto001 { + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.IntegerValue.compareTo"; + private final static String className = ".compareto001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + private static Value objectValue; + private static List fieldList; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return; + } + + // getting of object to check + Field field = debuggeeClass.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + + objectValue = debuggeeClass.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = debuggeeClass.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = debuggeeClass.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitiveValues = (ArrayReference)arrValue; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + IntegerValue value; + Field fldOtherType; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof IntegerValue) ) { + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (IntegerValue )v1; + + // comparing with debuggee's fields + display("Checking compateTo(Object object) method for IntegerValue: " + value); + + for (int j = 0; j < primitiveValues.length(); j++) { + arrValue = primitiveValues.getValue(j); + + fldOtherType = debuggeeClass.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = debuggeeClass.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + + } + + //--------------------------------------------------------- test specific methods + + + private static boolean PerformComparing(IntegerValue value, Object object ) { + boolean result = true; + + // assertion [ x.compareTo(x) == 0 ] + if (value.compareTo(value) != 0) { + complain("Failed assertion [ x.compareTo(x) == 0 ] for value: " + value.toString()); + result = false; + } + + if (object instanceof IntegerValue) { + IntegerValue intObject = (IntegerValue)object; + try { + // assertion [ x.compareTo(y) == 0 <==> x.equals(y) ] + if ( ((value.equals(object)) && (value.compareTo(intObject) != 0)) || + (!(value.equals(object)) && (value.compareTo(intObject) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (x.equals(y) == true) ] \n\t" + + "where 'x' is IntegerValue: " + value + " and 'y' is IntegerValue : " + intObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(intObject) + "\n\t" + + "result of (x.equals(y)): " + value.equals(object) ); + result = false; + } + + // assertion [ x.compareTo(y) == 0 <==> y.compareTo(x) == 0 ] + if ( ((value.compareTo(intObject) == 0) && (intObject.compareTo(value) != 0)) || + ((value.compareTo(intObject) != 0) && (intObject.compareTo(value) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0) ] \n\t" + + "where 'x' is IntegerValue: " + value + " and 'y' is IntegerValue : " + intObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(intObject) + "\n\t" + + "result of (y.compareTo(x)): " + intObject.compareTo(value) ); + result = false; + } + if (value.compareTo(intObject) != 0) { + // assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] + if (value.compareTo(intObject) != -(intObject.compareTo(value))) { + complain("Failed assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] \n\t" + + "where 'x' is IntegerValue: " + value + " and 'y' is IntegerValue : " + intObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(intObject) + "\n\t" + + "result of (y.compareTo(x)): " + intObject.compareTo(value) ); + result = false; + } + } + + // assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] + if (value.compareTo(intObject) > 0) { + IntegerValue lessValue = FindLessIntegerValue(intObject); + if (lessValue != null) { + if (value.compareTo(lessValue) <= 0) { + complain("Failed assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] \n\t" + + "where 'x' is IntegerValue: " + value + " , 'y' is IntegerValue : " + intObject + " , 'z' is IntegerValue : " + lessValue + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(intObject) + "\n\t" + + "result of (y.compareTo(z)): " + intObject.compareTo(lessValue) + "\n\t" + + "result of (x.compareTo(z)): " + value.compareTo(lessValue) ); + result = false; + } + } + } + + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "IntegerValue: " + value + " and IntegerValue argument: " + object); + result = false; + } + + } else if (object == null) { + try { + value.compareTo(null); + complain("Does not throw expected NullPointerException when comparing \n\t" + + "IntegerValue: " + value + " and null argument"); + result = false; + } catch (NullPointerException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "IntegerValue: " + value + " and null argument"); + result = false; + } + } else { + try { + value.compareTo((IntegerValue)object); + complain("Does not throw expected ClassCastException when comparing \n\t" + + "IntegerValue: " + value + " and argument: " + object); + result = false; + } catch (ClassCastException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "IntegerValue: " + value + " and argument: " + object); + result = false; + } + } + + return result; + } + + /** + * This function searches the static fieldList - the list of mirrored + * fields of debuggee's compareto001aClassToCheck class. Search is aimed + * to find another IntegerValue field which is less then method's argument via + * compareTo method. + */ + + private static IntegerValue FindLessIntegerValue (IntegerValue currentValue) { + IntegerValue result = null; + + for (int i = 0; i < fieldList.size(); i++ ) { + + Field field = (Field )fieldList.get(i); + IntegerValue newValue = (IntegerValue)((ObjectReference )objectValue).getValue(field); + + if (currentValue.compareTo(newValue) > 0) { + result = newValue; + break; + } + } + return result; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001/TestDescription.java new file mode 100644 index 00000000000..af0c4278bca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerValue/compareTo/compareto001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the compareTo(Object o) method of com.sun.jdi.IntegerValue + * interface. This method is inherited from java.lang.Comparable interface. + * The test checks the following assertions which imply from spec for + * Comparable.compareTo(Object o): + * - (x.compareTo(y) == 0) is identical to (x.equals(y) == true); + * - (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0); + * - if (x.compareTo(y) == i) then (y.compareTo(x) == -i); + * - if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0); + * - if an argument is null, then NullPointerException is thrown; + * - if an argument is not of IntegerValue type, then a ClassCastException is thrown. + * where 'x', 'y' and 'z' denote IntegerValue object. + * The debugger program - nsk.jdi.IntegerValue.compareto.compareto001; + * the debuggee program - nsk.jdi.IntegerValue.compareto.compareto001a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * Then the debugger gets a list of integer fields of debuggee's object of + * compareto001aClassToCheck type. For every field a mirror of IntegerValue type + * is created and the assertions are checked. A various values for comparison + * are got from values of mirrors of debuggee's static fields. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerValue.compareTo.compareto001 + * nsk.jdi.IntegerValue.compareTo.compareto001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerValue.compareTo.compareto001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001a.java new file mode 100644 index 00000000000..6dca61da1c7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/compareTo/compareto001a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.IntegerValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class compareto001a { + + //----------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + static compareto001aClassToCheck testedObj = new compareto001aClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + pipe.println(compareto001.SIGNAL_READY); +// receiveSignal(compareto001.SIGNAL_GO); + + receiveSignal(compareto001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class compareto001aClassToCheck { + public int intMAX = Integer.MAX_VALUE; + public int int1 = 1; + public int int0 = 0; + public int int_1 = -1; + public int intMIN = Integer.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001.java new file mode 100644 index 00000000000..68dea3ff71e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * IntegerValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.IntegerValue.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static integer plus1_1 = +1;
    + * public static integer plus1_2 = +1;
    + * public static integer minus1 = -1;
    + * public static long longplus1 = +1;
    + *
    + * which a debugger mirros as :
    + *
    + * IntegerValue ivplus1_1;
    + * IntegerValue ivplus1_2;
    + * IntegerValue ivminus1;
    + * LongValue lvplus1;
    + *
    + * the following is true:
    + *
    + * ivplus1_1 == ivplus1_2
    + * ivplus1_1 != ivminus1
    + * ivplus1_1 != lvplus1
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/IntegerValue/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.IntegerValue.equals.equals001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("equals001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fiplus1_1 = execClass.fieldByName("plus1_1"); + Field fiplus1_2 = execClass.fieldByName("plus1_2"); + Field fiminus1 = execClass.fieldByName("minus1"); + Field flplus1 = execClass.fieldByName("longplus1"); + + IntegerValue ivplus1_1 = (IntegerValue) execClass.getValue(fiplus1_1); + IntegerValue ivplus1_2 = (IntegerValue) execClass.getValue(fiplus1_2); + IntegerValue ivminus1 = (IntegerValue) execClass.getValue(fiminus1); + LongValue lvplus1 = (LongValue) execClass.getValue(flplus1); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!ivplus1_1.equals(ivplus1_2)) + expresult = 1; + break; + + case 1: if (ivplus1_1.equals(ivminus1)) + expresult = 1; + break; + + case 2: if (ivplus1_1.equals(lvplus1)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..22410cfc414 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerValue/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * IntValue. + * The test checks up that a result of the method + * com.sun.jdi.IntegerValue.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this IntegerValue for equality. + * Returns: true if the Object is an IntegerValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.IntegerValue.equals.equals001; + * a debuggee program - nsk.jdi.IntegerValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerValue.equals.equals001 + * nsk.jdi.IntegerValue.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerValue.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001a.java new file mode 100644 index 00000000000..75e475ced99 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001a JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static int smallest = Integer.MIN_VALUE; +// public static int zero = 0; +// public static int largest = Integer.MAX_VALUE; + + public static int plus1_1 = +1; + public static int plus1_2 = +1; + public static int minus1 = -1; + + public static long longplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * types and when parameter is null.
    + * Analyse of the method executing is performed by PerformComparing + * method.
    + * First parameter of PerformComparing is static field of testedObj,
    + * which is placed onto debugee's side.
    + * + * Second parameter is got from debugee too:
    + * Debugee has array of boundary values of each primitive type, execTest reads
    + * them and calls PerformComparing for each of them.
    + */ +public class equals002 { + + private final static String prefix = "nsk.jdi.IntegerValue.equals."; + private final static String className = "equals002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static ReferenceType refType; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + execTest(); + debugee.quit(); + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + private static void execTest() { + + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("Class '" + debugeeName + "' not found."); + return; + } + + // getting of object to check + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = refType.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = refType.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + List fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + IntegerValue value; + Field fldOtherType; + String msg; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + log.display(""); + msg = "***" + field; + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof IntegerValue) ) { + msg += " is not IntegerValue (skipped)"; + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (IntegerValue )v1; + + // comparing with debugee's fields + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = refType.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = refType.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static boolean PerformComparing(IntegerValue value, Object object ) { + boolean res = true; + String msg = ""; + try { + if ( value.equals(object) ) { + if ( object instanceof IntegerValue ) { + if ( value.value() == ((PrimitiveValue )object).intValue() ) { + msg += "--> " + value + " == " + object; + } else { + msg += "##> " + value + " == " + object; + res = false; + } + } + else { + msg += "##> " + value + " == " + object + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if ( object == null ) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if ( object instanceof IntegerValue ) { + if ( value.value() != ((PrimitiveValue )object).intValue() ) { + msg += "--> " + value + " != " + object; + } else { + msg += "##> " + value + " != " + object; + res = false; + } + } + else { + msg += "--> " + value + " != " + object; + } + } + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..87763456777 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerValue/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.IntegerValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this IntegerValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is an IntegerValue and if applying "==" to the + * two mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has boundary values of primitive + * types. Also, case when parameter is considered. + * No exceptions are expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerValue.equals.equals002 + * nsk.jdi.IntegerValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002a.java new file mode 100644 index 00000000000..93549edbf21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/equals/equals002a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.IntegerValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * equals002a is deugee's part of the test.
    + * It contains the static fields with boundary values for each primitive type.
    + * ClassToCheck delivers values for first parameter of equals.
    + */ +public class equals002a { + + static ClassToCheck testedObj = new ClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class ClassToCheck { + public int integerMAX = Integer.MAX_VALUE; + public int int1 = 1; + public int int0 = 0; + public int int_1 = -1; + public int integerMIN = Integer.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001.java new file mode 100644 index 00000000000..5d730e3baf5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * IntegerValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.IntegerValue.hashCode()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static integer plus1_1 = +1;
    + * public static integer plus1_2 = +1;
    + *
    + * which a debugger mirros as :
    + *
    + * IntegerValue ivplus1_1;
    + * IntegerValue ivplus1_2;
    + *
    + * the following is true:
    + *
    + * ivplus1_1.hashCode() == ivplus1_1.hashCode()
    + * ivplus1_1.hashCode() == ivplus1_2.hashCode()
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/IntegerValue/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.IntegerValue.hashCode.hashcode001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("hashcode001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fiplus1_1 = execClass.fieldByName("plus1_1"); + Field fiplus1_2 = execClass.fieldByName("plus1_2"); + + IntegerValue ivplus1_1 = (IntegerValue) execClass.getValue(fiplus1_1); + IntegerValue ivplus1_2 = (IntegerValue) execClass.getValue(fiplus1_2); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (ivplus1_1.hashCode() != ivplus1_1.hashCode()) + expresult = 1; + break; + + case 1: if (ivplus1_1.hashCode() != ivplus1_2.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..79a9b9a7194 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerValue/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * IntValue. + * The test checks up that a result of the method + * com.sun.jdi.IntValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this IntegerValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.IntegerValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.IntegerValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerValue.hashCode.hashcode001 + * nsk.jdi.IntegerValue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerValue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..2fab00809bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/hashCode/hashcode001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001a JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static int smallest = Integer.MIN_VALUE; +// public static int zero = 0; +// public static int largest = Integer.MAX_VALUE; + + public static int plus1_1 = +1; + public static int plus1_2 = +1; +// public static int minus1 = -1; + +// public static long longplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * IntegerValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.IntegerValue.value()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static integer smallest = Integer.MIN_VALUE;
    + * public static integer zero = 0;
    + * public static integer largest = Integer.MAX_VALUE;
    + *
    + * which a debugger mirros as :
    + *
    + * IntegerValue ivsmallest;
    + * IntegerValue ivzero;
    + * IntegerValue ivlargest;
    + *
    + * the following is true:
    + *
    + * ivsmallest == Integer.MIN_VALUE
    + * ivzero == 0
    + * ivlargest == Integer.MAX_VALUE
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/IntegerValue/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.IntegerValue.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("value001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fismallest = execClass.fieldByName("smallest"); + Field fizero = execClass.fieldByName("zero"); + Field filargest = execClass.fieldByName("largest"); + + IntegerValue ivsmallest = (IntegerValue) execClass.getValue(fismallest); + IntegerValue ivzero = (IntegerValue) execClass.getValue(fizero); + IntegerValue ivlargest = (IntegerValue) execClass.getValue(filargest); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (ivsmallest.value() != Integer.MIN_VALUE) + expresult = 1; + break; + + case 1: if (ivzero.value() != 0) + expresult = 1; + break; + + case 2: if (ivlargest.value() != Integer.MAX_VALUE) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001/TestDescription.java new file mode 100644 index 00000000000..8b69eb255ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/IntegerValue/value/value001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * IntegerValue. + * The test checks up that a result of the method + * com.sun.jdi.IntegerValue.value() + * complies with its spec: + * public int value() + * Returns this IntegerValue as an int. + * Returns: the int mirrored by this object. + * The test works as follows: + * A debugger program - nsk.jdi.IntegerValue.value.value001; + * a debuggee program - nsk.jdi.IntegerValue.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.IntegerValue.value.value001 + * nsk.jdi.IntegerValue.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.IntegerValue.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001a.java new file mode 100644 index 00000000000..d9052833c8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerValue/value/value001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.IntegerValue.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static int smallest = Integer.MIN_VALUE; + public static int zero = 0; + public static int largest = Integer.MAX_VALUE; + +// public static int plus1_1 = +1; +// public static int plus1_2 = +1; +// public static int minus1 = -1; + +// public static long longplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * InterfaceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.InterfaceType.implementors()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * 1) Iface1 has two implementors, Class0 and Class1
    + * 2) Iface2 has one implementor, Class2
    + * 3) Iface0 has no direct implementors
    + *
    + */ + +public class implementors001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/InterfaceType/implementors/implementors001", + sHeader2 = "--> implementors001: ", + sHeader3 = "##> implementors001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new implementors001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.InterfaceType.implementors.implementors001a"; + + String mName = "nsk.jdi.InterfaceType.implementors"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("implementors001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType classRefType = null; + ClassType ctype = null; +// ReferenceType reftype = null; + List l = null; + String name = null; + InterfaceType ifaceType = null; + InterfaceType itype = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // Iface1 - 2 direct implementors, Class0 and Class1 + + List list0 = vm.classesByName(mName + ".Class1ForCheck"); + + classRefType = (ReferenceType) list0.get(0); + + List iface0list = + ((ClassType) classRefType).interfaces(); + + if (iface0list.size() != 1) { + log3("ERROR : iface0list.size() != 1 in case: Iface1"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface0list.get(0); + l = ifaceType.implementors(); + if (l.size() != 2) { + log3("ERROR : l.size() != 2 in case: Iface1"); + expresult = 1; + break; + } + + ctype = (ClassType) l.get(0); + name = ctype.name(); + if (!name.equals(mName + ".Class0ForCheck")) { + if (!name.equals(mName + ".Class1ForCheck")) { + log3("ERROR : !name.equals('.Class0..' or '.Class1..') in case: Iface1"); + expresult = 1; + break; + } + } + ctype = (ClassType) l.get(1); + name = ctype.name(); + if (!name.equals(mName + ".Class0ForCheck")) { + if (!name.equals(mName + ".Class1ForCheck")) { + log3("ERROR : !name.equals('.Class1..' or '.Class0..') in case: Iface1"); + expresult = 1; + break; + } + } + + break; + + case 1: // Iface2 - 1 direct implementor, Class2 + + List list1 = vm.classesByName(mName + ".Class2ForCheck"); + + classRefType = (ReferenceType) list1.get(0); + + List iface1list = + ((ClassType) classRefType).interfaces(); + + if (iface1list.size() != 1) { + log3("ERROR : iface1list.size() != 1 in case: Iface2"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface1list.get(0); + l = ifaceType.implementors(); + if (l.size() != 1) { + log3("ERROR : l.size() != 1 in case: Iface2"); + expresult = 1; + break; + } + + ctype = (ClassType) l.get(0); + name = ctype.name(); + if (!name.equals(mName + ".Class2ForCheck")) { + log3("ERROR : !name.equals('.Class2..') in case: Iface2"); + expresult = 1; + break; + } + + break; + + case 2: // Iface0 - 0 direct implementors + + List list3 = vm.classesByName(mName + ".Class4ForCheck"); + + classRefType = (ReferenceType) list3.get(0); + + List iface3list = + ((ClassType) classRefType).interfaces(); + + if (iface3list.size() != 1) { + log3("ERROR : iface3list.size() != 1 in case: Iface3"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface3list.get(0); + l = ifaceType.superinterfaces(); + if (l.size() != 1) { + log3("ERROR : ifaceType.superinterfaces().size() != 1 in case: Iface0 " + l.size()); + expresult = 1; + break; + } + itype = (InterfaceType) l.get(0); + l = itype.implementors(); + if (l.size() != 0) { + log3("ERROR : l.get(0).size() != 0 in case: Iface0"); + expresult = 1; + break; + } + + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001/TestDescription.java new file mode 100644 index 00000000000..e9da4aa74d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/InterfaceType/implementors/implementors001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * InterfaceType. + * The test checks up that a result of the method + * com.sun.jdi.InterfaceType.implementors() + * complies with tits spec: + * public java.util.List implementors() + * Gets the currently prepared classes which directly implement this interface. + * The returned list contains only those classes that declared this interface + * in their "implements" clause. + * Returns: a List of ClassType objects each mirroring a class + * implementing this interface. + * If none exist, returns a zero length List. + * Throws: ObjectCollectedException - + * if this interface has been unloaded and garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.InterfaceType.implementors.implementors001; + * the debuggee program - nsk.jdi.InterfaceType.implementors.implementors001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.InterfaceType.implementors.implementors001 + * nsk.jdi.InterfaceType.implementors.implementors001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.InterfaceType.implementors.implementors001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001a.java new file mode 100644 index 00000000000..17d35f74159 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/implementors/implementors001a.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.InterfaceType.implementors; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the implementors001 JDI test. + */ + +public class implementors001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> implementors001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> implementors001a: " + message); + } + + //====================================================== test program + + static Class0ForCheck class0 = null; + static Class1ForCheck class1 = null; + static Class2ForCheck class2 = null; + static Class3ForCheck class3 = null; + static Class4ForCheck class4 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * InterfaceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.InterfaceType.subinterfaces()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * 1) Iface3 has no a subinterface
    + * 2) Iface2 has the subinterface Iface3
    + * 3) Iface1 has the subinterfaces Iface2 and Iface4
    + *
    + */ + +public class subinterfaces001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/InterfaceType/subinterfaces/subinterfaces001", + sHeader2 = "--> subinterfaces001: ", + sHeader3 = "##> subinterfaces001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new subinterfaces001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.InterfaceType.subinterfaces.subinterfaces001a"; + + String mName = "nsk.jdi.InterfaceType.subinterfaces"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("subinterfaces001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType classRefType = null; + ReferenceType reftype = null; + List l = null; + String name = null; + InterfaceType ifaceType = null; + InterfaceType itype = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // Iface3 - 0 subinterfaces + + List list0 = vm.classesByName(mName + ".Class3ForCheck"); + + classRefType = (ReferenceType) list0.get(0); + + List iface0list = + ((ClassType) classRefType).interfaces(); + + if (iface0list.size() != 1) { + log3("ERROR : iface0list.size() != 1 in case: Iface3"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface0list.get(0); + if (ifaceType.subinterfaces().size() != 0) { + log3("ERROR : ifaceType.subinterfaces().size() != 0 in case: Iface3"); + expresult = 1; + break; + } + + break; + + case 1: // Iface2 - 1 subinterfaces + + List list1 = vm.classesByName(mName + ".Class2ForCheck"); + + classRefType = (ReferenceType) list1.get(0); + + List iface1list = + ((ClassType) classRefType).interfaces(); + + if (iface1list.size() != 1) { + log3("ERROR : iface1list.size() != 1 in case: Iface2"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface1list.get(0); + l = ifaceType.subinterfaces(); + if (l.size() != 1) { + log3("ERROR : ifaceType.subinterfaces().size() != 1 in case: Iface2"); + expresult = 1; + break; + } + + itype = (InterfaceType) l.get(0); + name = itype.name(); + if (!name.equals(mName + ".Iface3")) { + log3("ERROR : !name.equals(mName + '.Iface3') in case: Iface2"); + expresult = 1; + break; + } + + break; + + case 2: // Iface1 - 2 subinterfaces + + List list3 = vm.classesByName(mName + ".Class1ForCheck"); + + classRefType = (ReferenceType) list3.get(0); + + List iface3list = + ((ClassType) classRefType).interfaces(); + + if (iface3list.size() != 1) { + log3("ERROR : iface3list.size() != 1 in case: Iface1"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface3list.get(0); + l = ifaceType.subinterfaces(); + if (l.size() != 2) { + log3("ERROR : ifaceType.subinterfaces().size() != 1 in case: Iface1"); + expresult = 1; + break; + } + + itype = (InterfaceType) l.get(0); + name = itype.name(); + if (!name.equals(mName + ".Iface2")) { + if (!name.equals(mName + ".Iface4")) { + log3("ERROR : !name.equals('.Iface2' or '.Iface4') in case: Iface1"); + expresult = 1; + break; + } + } + itype = (InterfaceType) l.get(1); + name = itype.name(); + if (!name.equals(mName + ".Iface4")) { + if (!name.equals(mName + ".Iface2")) { + log3("ERROR : !name.equals('.Iface4' or '.Iface2') in case: Iface1"); + expresult = 1; + break; + } + } + + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001/TestDescription.java new file mode 100644 index 00000000000..7deecd14086 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/InterfaceType/subinterfaces/subinterfaces001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * InterfaceType. + * The test checks up that a result of the method + * com.sun.jdi.InterfaceType.subinterfaces() + * complies with tits spec: + * public java.util.List subinterfaces() + * Gets the currently prepared interfaces which directly extend this interface. + * The returned list contains only those interfaces + * that declared this interface in their "extends" clause. + * Returns: a List of InterfaceType objects each mirroring an interface + * extending this interface. + * If none exist, returns a zero length List. + * Throws: ObjectCollectedException - + * if this interface has been unloaded and garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.InterfaceType.subinterfaces.subinterfaces001; + * the debuggee program - nsk.jdi.InterfaceType.subinterfaces.subinterfaces001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.InterfaceType.subinterfaces.subinterfaces001 + * nsk.jdi.InterfaceType.subinterfaces.subinterfaces001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.InterfaceType.subinterfaces.subinterfaces001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001a.java new file mode 100644 index 00000000000..ffc07fcdfa3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/subinterfaces/subinterfaces001a.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.InterfaceType.subinterfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the subinterfaces001 JDI test. + */ + +public class subinterfaces001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> subinterfaces001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> subinterfaces001a: " + message); + } + + //====================================================== test program + + static Class1ForCheck class1 = null; + static Class2ForCheck class2 = null; + static Class3ForCheck class3 = null; + static Class4ForCheck class4 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * InterfaceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.InterfaceType.superinterfaces()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * 1) Iface1 has no a superinterface
    + * 2) Iface2 has the superinterface Iface1 and
    + * no indirect interfaces
    + * 3) Iface3 has the superinterface Iface2 and
    + * the indirect interface Iface1
    + * 4) Iface4 has the superinterfaces Iface0 and Iface1
    + *
    + */ + +public class superinterfaces001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/InterfaceType/superinterfaces/superinterfaces001", + sHeader2 = "--> superinterfaces001: ", + sHeader3 = "##> superinterfaces001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new superinterfaces001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.InterfaceType.superinterfaces.superinterfaces001a"; + + String mName = "nsk.jdi.InterfaceType.superinterfaces"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("superinterfaces001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType classRefType = null; + ReferenceType reftype = null; + List l = null; + String name = null; + InterfaceType ifaceType = null; + InterfaceType itype = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // Iface1 - 0 superinterfaces + + List list0 = vm.classesByName(mName + ".Class1ForCheck"); + + classRefType = (ReferenceType) list0.get(0); + + List iface0list = + ((ClassType) classRefType).interfaces(); + + if (iface0list.size() != 1) { + log3("ERROR : iface0list.size() != 1 in case: Iface1"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface0list.get(0); + if (ifaceType.superinterfaces().size() != 0) { + log3("ERROR : ifaceType.superinterfaces().size() != 0 in case: Iface1"); + expresult = 1; + break; + } + + break; + + case 1: // Iface2 - 1 superifaces, 0 indirect ifaces + + List list1 = vm.classesByName(mName + ".Class2ForCheck"); + + classRefType = (ReferenceType) list1.get(0); + + List iface1list = + ((ClassType) classRefType).interfaces(); + + if (iface1list.size() != 1) { + log3("ERROR : iface1list.size() != 1 in case: Iface2"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface1list.get(0); + l = ifaceType.superinterfaces(); + if (l.size() != 1) { + log3("ERROR : ifaceType.superinterfaces().size() != 1 in case: Iface2"); + expresult = 1; + break; + } + + itype = (InterfaceType) l.get(0); + name = itype.name(); + if (!name.equals(mName + ".Iface1")) { + log3("ERROR : !name.equals(mName + '.Iface1') in case: Iface2"); + expresult = 1; + break; + } + + break; + + case 2: // Iface3 - 1 superifaces, 1 indirect ifaces + + List list3 = vm.classesByName(mName + ".Class3ForCheck"); + + classRefType = (ReferenceType) list3.get(0); + + List iface3list = + ((ClassType) classRefType).interfaces(); + + if (iface3list.size() != 1) { + log3("ERROR : iface3list.size() != 1 in case: Iface3"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface3list.get(0); + l = ifaceType.superinterfaces(); + if (l.size() != 1) { + log3("ERROR : ifaceType.superinterfaces().size() != 1 in case: Iface3"); + expresult = 1; + break; + } + + break; + + case 3: // Iface4 - 2 superifaces, 0 indirect ifaces + + List list4 = vm.classesByName(mName + ".Class4ForCheck"); + + classRefType = (ReferenceType) list4.get(0); + + List iface4list = + ((ClassType) classRefType).interfaces(); + + if (iface4list.size() != 1) { + log3("ERROR : iface4list.size() != 1 in case: Iface4"); + expresult = 1; + break; + } + + ifaceType = (InterfaceType) iface4list.get(0); + l = ifaceType.superinterfaces(); + if (l.size() != 2) { + log3("ERROR : ifaceType.superinterfaces().size() != 2 in case: Iface4"); + expresult = 1; + break; + } + + itype = (InterfaceType) l.get(0); + name = itype.name(); + if (!name.equals(mName + ".Iface0")) { + if (!name.equals(mName + ".Iface1")) { + log3("ERROR : !name.equals('.Iface0' or '.Iface1') in case: Iface4"); + expresult = 1; + break; + } + } + itype = (InterfaceType) l.get(1); + name = itype.name(); + if (!name.equals(mName + ".Iface0")) { + if (!name.equals(mName + ".Iface1")) { + log3("ERROR : !name.equals('.Iface1' or '.Iface0') in case: Iface4"); + expresult = 1; + break; + } + } + + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001/TestDescription.java new file mode 100644 index 00000000000..10b3f987ac3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/InterfaceType/superinterfaces/superinterfaces001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * InterfaceType. + * The test checks up that a result of the method + * com.sun.jdi.InterfaceType.superinterfaces() + * complies with tits spec: + * public java.util.List superinterfaces() + * Gets the interfaces directly extended by this interface. + * The returned list contains only those interfaces + * this interface has declared to be extended. + * Returns: a List of InterfaceType objects each mirroring + * an interface extended by this interface. + * If none exist, returns a zero length List. + * Throws: ClassNotPreparedException - + * if this class not yet been prepared. + * ObjectCollectedException - + * if this interface has been unloaded and garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.InterfaceType.superinterfaces.superinterfaces001; + * the debuggee program - nsk.jdi.InterfaceType.superinterfaces.superinterfaces001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.InterfaceType.superinterfaces.superinterfaces001 + * nsk.jdi.InterfaceType.superinterfaces.superinterfaces001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.InterfaceType.superinterfaces.superinterfaces001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001a.java new file mode 100644 index 00000000000..433e005efa3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/InterfaceType/superinterfaces/superinterfaces001a.java @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.InterfaceType.superinterfaces; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the superinterfaces001 JDI test. + */ + +public class superinterfaces001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> superinterfaces001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> superinterfaces001a: " + message); + } + + //====================================================== test program + + static Class1ForCheck class1 = null; + static Class2ForCheck class2 = null; + static Class3ForCheck class3 = null; + static Class4ForCheck class4 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.CommandLineLaunch + * and dt_socket transport. + * + *

    Note, that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + */ +public class launch001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + private final static String CONNECTOR_NAME = + "com.sun.jdi.CommandLineLaunch"; + private final static String TRANSPORT_NAME = "dt_socket"; + + private final static String DEBUGEE_CLASS = + "nsk.jdi.LaunchingConnector.launch.launch001o"; + + public static void main (String args[]) { + System.exit(run(args,System.out) + JCK_STATUS_BASE); + // JCK-style exit status. + } + + public static int run (String args[], PrintStream out) { + return new launch001(args,out).run(); + } + + private launch001 (String args[], PrintStream out) { + this.out = out; + + argHandler = new ArgumentHandler(args); + log = new Log(this.out, argHandler); + } + + private PrintStream out; + private ArgumentHandler argHandler; + private Log log; + + private int run () { +// pass if CONNECTOR_NAME with TRANSPORT_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME, TRANSPORT_NAME)) + return PASSED; + + LaunchingConnector lc = + getLaunchingConnector(CONNECTOR_NAME, TRANSPORT_NAME); + if (lc == null) { + log.complain("FAILURE: cannot get LaunchingConnector"); + return FAILED; + }; + Map carg = setupConnectorArguments(lc); + + log.display("Starting debugee VM"); + VirtualMachine vm; + try { + vm = lc.launch(carg); + } catch (Exception e) { + log.complain("FAILURE: cannot launch debugee VM: " + + e.getMessage()); + e.printStackTrace(out); + return FAILED; + } + + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.enwrapDebugee(vm, vm.process()); + + log.display("Resuming debugee VM"); + debugee.resume(); + + log.display("Waiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("FAILURE: debugee VM exitCode=" + code); + return FAILED; + }; + log.display("Debugee VM exitCode=" + code); + return PASSED; + } + + private Map setupConnectorArguments (LaunchingConnector lc) { + Map carg = lc.defaultArguments(); + + log.display("Connector's arguments:"); + Object cava[] = carg.values().toArray(); + for (int i=0; i 0) + log.display("Launching connectors available:"); + + int found = 0; + LaunchingConnector lc = null; + + Iterator lci = lcl.iterator(); + for (int i=1; lci.hasNext(); i++) { + LaunchingConnector c = (LaunchingConnector) lci.next(); + log.display(" Launching connector #" + i + ":"); + log.display(" Name: " + c.name()); + log.display(" Description: " + c.description()); + log.display(" Transport: " + c.transport().name()); + if (!c.name().equals(connectorName)) + continue; + if (c.transport().name().equals(transportName)) { + log.display(" -- This connector is appropriate. --"); + if (lc == null) + lc = c; + found++; + } + }; + + if (lc == null) { + log.complain("FAILURE: no " + + connectorName + " connector found for " + + transportName + " transport!"); + return null; + }; + if (found > 1) { + log.complain("TEST_BUG: more than one " + + connectorName + " connector found for " + + transportName + " transport!"); + return null; + }; + return lc; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001/TestDescription.java new file mode 100644 index 00000000000..51a5990df62 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LaunchingConnector/launch/launch001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This tiny debugger-like application starts debugee VM + * so that debugger/debugee connection be correctly + * established via connector com.sun.jdi.CommandLineLaunch + * and dt_socket transport. + * Note, that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + * COMMENTS + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LaunchingConnector.launch.launch001 + * nsk.jdi.LaunchingConnector.launch.launch001o + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LaunchingConnector.launch.launch001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001o.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001o.java new file mode 100644 index 00000000000..9356dcd32fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001o.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LaunchingConnector.launch; + +/** + * Dummy debugee application used to test JDI connection. + */ +public class launch001o { + public static void main (String args[]) { + System.exit(launch001.JCK_STATUS_BASE + launch001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002.java new file mode 100644 index 00000000000..e2eb8168f2a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LaunchingConnector.launch; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This tiny debugger-like application starts debugee VM + * so that debugger/debugee connection be correctly + * established via connector com.sun.jdi.CommandLineLaunch + * and dt_shmem transport. + * + *

    Note, that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + */ +public class launch002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + private final static String CONNECTOR_NAME = + "com.sun.jdi.CommandLineLaunch"; + private final static String TRANSPORT_NAME = "dt_shmem"; + + private final static String DEBUGEE_CLASS = + "nsk.jdi.LaunchingConnector.launch.launch002o"; + + public static void main (String args[]) { + System.exit(run(args,System.out) + JCK_STATUS_BASE); + // JCK-style exit status. + } + + public static int run (String args[], PrintStream out) { + return new launch002(args,out).run(); + } + + private launch002 (String args[], PrintStream out) { + this.out = out; + argHandler = new ArgumentHandler(args); + log = new Log(this.out, argHandler); + } + + private PrintStream out; + private ArgumentHandler argHandler; + private Log log; + + private int run () { +// pass if CONNECTOR_NAME with TRANSPORT_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME, TRANSPORT_NAME)) + return PASSED; + + LaunchingConnector lc = + getLaunchingConnector(CONNECTOR_NAME, TRANSPORT_NAME); + if (lc == null) { + log.complain("FAILURE: cannot get LaunchingConnector"); + return FAILED; + }; + Map carg = setupConnectorArguments(lc); + + log.display("Starting debugee VM"); + VirtualMachine vm; + try { + vm = lc.launch(carg); + } catch (Exception e) { + log.complain("FAILURE: cannot launch debugee VM: " + + e.getMessage()); + e.printStackTrace(out); + return FAILED; + }; + + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.enwrapDebugee(vm, vm.process()); + + log.display("Resuming debugee VM"); + debugee.resume(); + + log.display("Waiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("FAILURE: debugee VM exitCode=" + code); + return FAILED; + }; + log.display("Debugee VM exitCode=" + code); + log.display("Test PASSED!"); + return PASSED; + } + + private Map setupConnectorArguments(LaunchingConnector lc) { + Map carg = lc.defaultArguments(); + + log.display("Connector's arguments:"); + Object cava[] = carg.values().toArray(); + for (int i=0; i 0) + log.display("Launching connectors available:"); + + int found = 0; + LaunchingConnector lc = null; + + Iterator lci = lcl.iterator(); + for (int i=1; lci.hasNext(); i++) { + LaunchingConnector c = (LaunchingConnector) lci.next(); + log.display(" Launching connector #" + i + ":"); + log.display(" Name: " + c.name()); + log.display(" Description: " + c.description()); + log.display(" Transport: " + c.transport().name()); + if (!c.name().equals(connectorName)) + continue; + if (c.transport().name().equals(transportName)) { + log.display(" -- This connector is appropriate. --"); + if (lc == null) + lc = c; + found++; + } + }; + + if (lc == null) { + log.complain("FAILURE: no " + + connectorName + " connector found for " + + transportName + " transport!"); + return null; + }; + if (found > 1) { + log.complain("TEST_BUG: more than one " + + connectorName + " connector found for " + + transportName + " transport!"); + return null; + }; + return lc; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002/TestDescription.java new file mode 100644 index 00000000000..4a4afa9c9f5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LaunchingConnector/launch/launch002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This tiny debugger-like application starts debugee VM + * so that debugger/debugee connection be correctly + * established via connector com.sun.jdi.CommandLineLaunch + * and dt_shmem transport. + * Note, that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + * COMMENTS + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LaunchingConnector.launch.launch002 + * nsk.jdi.LaunchingConnector.launch.launch002o + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LaunchingConnector.launch.launch002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002o.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002o.java new file mode 100644 index 00000000000..2ab2ac9391c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch002o.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LaunchingConnector.launch; + +/** + * Dummy debugee application used to test JDI connection. + */ +public class launch002o { + public static void main (String args[]) { + System.exit(launch002.JCK_STATUS_BASE + launch002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003.java new file mode 100644 index 00000000000..05d1dffeadb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LaunchingConnector.launch; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This tiny debugger-like application starts debugee VM + * so that debugger/debugee connection be correctly + * established via connector com.sun.jdi.RawCommandLineLaunch + * and dt_socket transport. + * + *

    Note, that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + */ +public class launch003 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + private final static String CONNECTOR_NAME = + "com.sun.jdi.RawCommandLineLaunch"; + private final static String TRANSPORT_NAME = "dt_socket"; + + private final static String DEBUGEE_CLASS = + "nsk.jdi.LaunchingConnector.launch.launch003o"; + + public static void main(String args[]) { + System.exit(run(args,System.out) + JCK_STATUS_BASE); + // JCK-style exit status. + } + + public static int run(String args[], PrintStream out) { + return new launch003(args,out).run(); + } + + private launch003(String args[], PrintStream out) { + this.out = out; + argHandler = new ArgumentHandler(args); + log = new Log(this.out, argHandler); + } + + private PrintStream out; + private ArgumentHandler argHandler; + private Log log; + + private int run() { + +// pass if CONNECTOR_NAME with TRANSPORT_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME, TRANSPORT_NAME)) + return PASSED; + + LaunchingConnector lc = + getLaunchingConnector(CONNECTOR_NAME, TRANSPORT_NAME); + if (lc == null) { + log.complain("FAILURE: cannot get LaunchingConnector"); + return FAILED; + }; + Map carg = + setupConnectorArguments(lc, argHandler.getTestHost(), + argHandler.getTransportPort()); + log.display("Starting debugee VM"); + VirtualMachine vm; + try { + vm = lc.launch(carg); + } catch (Exception e) { + log.complain("FAILURE: cannot launch debugee VM: " + + e.getMessage()); + e.printStackTrace(out); + return FAILED; + }; + + log.display("target VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.enwrapDebugee(vm, vm.process()); + + log.display("Resuming debugee VM"); + debugee.resume(); + + log.display("Waiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("FAILURE: debugee VM exitCode=" + code); + return FAILED; + }; + log.display("Debugee VM exitCode=" + code); + log.display("Test PASSED!"); + return PASSED; + } + + private Map setupConnectorArguments( + LaunchingConnector lc, String host, String port) { + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + Map carg = lc.defaultArguments(); + log.display("Connector's arguments:"); + Object cava[] = carg.values().toArray(); + for (int i=0; i 1) { + log.complain("TEST_BUG: more than one " + + connectorName + " connector found for " + + transportName + " transport!"); + return null; + }; + return lc; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003/TestDescription.java new file mode 100644 index 00000000000..1f3f3dcd59a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LaunchingConnector/launch/launch003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This tiny debugger-like application starts debugee VM + * so that debugger/debugee connection be correctly + * established via connector com.sun.jdi.RawCommandLineLaunch + * and dt_socket transport. + * Note, that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + * COMMENTS + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LaunchingConnector.launch.launch003 + * nsk.jdi.LaunchingConnector.launch.launch003o + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LaunchingConnector.launch.launch003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003o.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003o.java new file mode 100644 index 00000000000..8d3c8e01aa0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003o.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LaunchingConnector.launch; + +/** + * Dummy debugee application used to test JDI connection. + */ +public class launch003o { + public static void main (String args[]) { + System.exit(launch003.JCK_STATUS_BASE + launch003.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004.java new file mode 100644 index 00000000000..7822023ac94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LaunchingConnector.launch; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This test is debugger-like application. It starts debugee VM + * so that debugger/debugee connection be correctly + * established via connector com.sun.jdi.RawCommandLineLaunch + * and dt_shmem transport. + * + *

    Note that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + */ +public class launch004 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + private final static String CONNECTOR_NAME = + "com.sun.jdi.RawCommandLineLaunch"; + private final static String TRANSPORT_NAME = "dt_shmem"; + + private final static String DEBUGEE_CLASS = + "nsk.jdi.LaunchingConnector.launch.launch004o"; + + public static void main(String args[]) { + System.exit(run(args,System.out) + JCK_STATUS_BASE); + // JCK-style exit status. + } + + public static int run(String args[], PrintStream out) { + return new launch004(args,out).run(); + } + + private launch004(String args[], PrintStream out) { + this.out = out; + argHandler = new ArgumentHandler(args); + log = new Log(this.out, argHandler); + } + + private PrintStream out; + private ArgumentHandler argHandler; + private Log log; + + private int run() { + +// pass if CONNECTOR_NAME with TRANSPORT_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME, TRANSPORT_NAME)) + return PASSED; + + LaunchingConnector lc = + getLaunchingConnector(CONNECTOR_NAME, TRANSPORT_NAME); + if (lc == null) { + log.complain("FAILURE: cannot get LaunchingConnector"); + return FAILED; + }; + Map carg = + setupConnectorArguments(lc, argHandler.getTransportSharedName()); + log.display("Starting debugee VM"); + VirtualMachine vm; + try { + vm = lc.launch(carg); + } catch (Exception e) { + log.complain("FAILURE: cannot launch debugee VM: " + + e.getMessage()); + e.printStackTrace(out); + return FAILED; + }; + + log.display("target VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.enwrapDebugee(vm, vm.process()); + + log.display("Resuming debugee VM"); + debugee.resume(); + + log.display("Waiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("FAILURE: debugee VM exitCode=" + code); + return FAILED; + }; + log.display("Debugee VM exitCode=" + code); + log.display("Test PASSED!"); + return PASSED; + } + + private Map setupConnectorArguments( + LaunchingConnector lc, String name) { + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + Map carg = lc.defaultArguments(); + log.display("Connector's arguments:"); + Object cava[] = carg.values().toArray(); + for (int i=0; i 1) { + log.complain("TEST_BUG: more than one " + + connectorName + " connector found for " + + transportName + " transport!"); + return null; + }; + return lc; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004/TestDescription.java new file mode 100644 index 00000000000..20f185eaf34 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LaunchingConnector/launch/launch004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test is debugger-like application. It starts + * debugee VM so that debugger/debugee connection be correctly + * established via connector com.sun.jdi.RawCommandLineLaunch + * and dt_shmem transport. + * Note that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + * COMMENTS + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LaunchingConnector.launch.launch004 + * nsk.jdi.LaunchingConnector.launch.launch004o + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LaunchingConnector.launch.launch004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004o.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004o.java new file mode 100644 index 00000000000..5e075d231b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launch/launch004o.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LaunchingConnector.launch; + +public class launch004o { + public static void main(String args[]) { + System.exit(launch004.JCK_STATUS_BASE + launch004.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001.java new file mode 100644 index 00000000000..9c03396d67f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.LaunchingConnector.launchnosuspend; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.event.*; + +import java.io.*; +import java.util.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This tiny debugger-like application starts debugee VM + * so that debugger/debugee connection be correctly + * established via connector com.sun.jdi.CommandLineLaunch + * and dt_socket transport. + * + *

    Note, that unlike most of JDI tests, this test + * will always fail if launching of other JVM is prohibited + * by security restrictions. + */ +public class launchnosuspend001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + private final static String CONNECTOR_NAME = + "com.sun.jdi.RawCommandLineLaunch"; + private final static String TRANSPORT_NAME = "dt_socket"; + + private final static String DEBUGEE_CLASS = + "nsk.jdi.LaunchingConnector.launchnosuspend.launchnosuspend001o"; + + public static void main (String args[]) { + System.exit(run(args,System.out) + JCK_STATUS_BASE); + // JCK-style exit status. + } + + public static int run (String args[], PrintStream out) { + return new launchnosuspend001(args,out).run(); + } + + private launchnosuspend001 (String args[], PrintStream out) { + this.out = out; + + argHandler = new ArgumentHandler(args); + log = new Log(this.out, argHandler); + //log.enableVerbose(true); + } + + private PrintStream out; + private ArgumentHandler argHandler; + private Log log; + + private int run() { + +// pass if CONNECTOR_NAME with TRANSPORT_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME, TRANSPORT_NAME)) + return PASSED; + + LaunchingConnector lc = + getLaunchingConnector(CONNECTOR_NAME, TRANSPORT_NAME); + if (lc == null) { + log.complain("FAILURE: cannot get LaunchingConnector"); + return FAILED; + }; + Map carg = + setupConnectorArguments(lc, argHandler.getTestHost(), + argHandler.getTransportPort()); + log.display("Starting debugee VM"); + VirtualMachine vm; + try { + vm = lc.launch(carg); + } catch (Exception e) { + log.complain("FAILURE: cannot launch debugee VM: " + + e.getMessage()); + e.printStackTrace(out); + return FAILED; + }; + + log.display("target VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + //try {EventSet set = vm.eventQueue().remove(); + //for(Event event : set) + // System.out.println("==DEFSTAN: " + event.toString()); + //} catch (Throwable e) {} + + //vm.setDebugTraceMode(VirtualMachine.TRACE_ALL); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.makeLocalDebugee(vm.process()); + debugee.redirectOutput(log); + debugee.setupVM(vm); + //debugee.waitForVMInit(1000); + + //log.display("Resuming debugee VM"); + //debugee.resume(); + + log.display("Waiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("FAILURE: debugee VM exitCode=" + code); + return FAILED; + }; + log.display("Debugee VM exitCode=" + code); + log.display("Test PASSED!"); + return PASSED; + } + + private Map setupConnectorArguments( + LaunchingConnector lc, String host, String port) { + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + Map carg = lc.defaultArguments(); + log.display("Connector's arguments:"); + Object cava[] = carg.values().toArray(); + for (int i=0; i 1) { + log.complain("TEST_BUG: more than one " + + connectorName + " connector found for " + + transportName + " transport!"); + return null; + }; + return lc; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001/TestDescription.java new file mode 100644 index 00000000000..b1bcb4764b1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001/TestDescription.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exactly as launch003 except using options: + * -agentlib:jdwb + * suspend=n + * COMMENT + * RFE 4920165 + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LaunchingConnector.launchnosuspend.launchnosuspend001 + * nsk.jdi.LaunchingConnector.launchnosuspend.launchnosuspend001o + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LaunchingConnector.launchnosuspend.launchnosuspend001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001o.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001o.java new file mode 100644 index 00000000000..5b55267b923 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001o.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.LaunchingConnector.launchnosuspend; + +/** + * Dummy debugee application used to test JDI connection. + */ +public class launchnosuspend001o { + public static void main (String args[]) { + try { + Thread.sleep(60000); + } catch (Throwable e) + { + e.printStackTrace(); + System.exit(launchnosuspend001.JCK_STATUS_BASE + launchnosuspend001.FAILED); + } + System.exit(launchnosuspend001.JCK_STATUS_BASE + launchnosuspend001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java new file mode 100644 index 00000000000..450ad57f8e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.accept; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; +import com.sun.jdi.VirtualMachine; + +import java.io.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that debugger may establish connection with + * a debugee VM via com.sun.jdi.SocketListen connector. + */ +public class accept001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String DEBUGEE_CLASS = "nsk.jdi.ListeningConnector.accept.accept001t"; + + private Log log; + + private VirtualMachine vm; + private ListeningConnector connector; + private Map connArgs; + + IORedirector outRedirector; + IORedirector errRedirector; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new accept001().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if "com.sun.jdi.SocketListen" is not implemented +// on this platform + if (argHandler.shouldPass("com.sun.jdi.SocketListen")) + return PASSED; + + long timeout = argHandler.getWaitTime() * 60 * 1000; + log = new Log(out, argHandler); + + String connAddr = startListen(argHandler.getTransportPortIfNotDynamic()); + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + String cmd = java + + " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,address=" + + connAddr + " " + DEBUGEE_CLASS; + + Binder binder = new Binder(argHandler, log); + log.display("command: " + cmd); + Debugee debugee = binder.startLocalDebugee(cmd); + debugee.redirectOutput(log); + + if ((vm = attachTarget()) == null) { + log.complain("TEST: Unable to attach the debugee VM"); + debugee.close(); + return FAILED; + } + + if (!stopListen()) { + log.complain("TEST: Unable to stop listen"); + debugee.close(); + return FAILED; + } + + log.display("Debugee VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + debugee.setupVM(vm); + debugee.waitForVMInit(timeout); + + log.display("\nResuming debugee VM"); + debugee.resume(); + + log.display("\nWaiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("Debugee VM has crashed: exit code=" + + code); + return FAILED; + } + log.display("Debugee VM: exit code=" + code); + return PASSED; + } + + private VirtualMachine attachTarget() { + try { + return connector.accept(connArgs); + } catch (IOException e) { + log.complain("TEST: caught IOException: " + + e.getMessage()); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return null; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return null; + } + } + + private String startListen(String port) { + Connector.Argument arg; + + connector = (ListeningConnector) + findConnector("com.sun.jdi.SocketListen"); + + connArgs = connector.defaultArguments(); + Iterator cArgsValIter = connArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) connArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + + connector.name()); + } + if (arg.name().equals("port") && port != null) + arg.setValue(port); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue=" + argVal); + else log.display("\t\tvalue=NULL"); + } + + try { + return connector.startListening(connArgs); + } catch (IOException e) { + throw new Error("TEST: Unable to start listening to the debugee VM: " + + e.getMessage()); + } catch (IllegalConnectorArgumentsException e) { + throw new Error("TEST: Illegal connector arguments: " + + e.getMessage()); + } catch (Exception e) { + throw new Error("TEST: Internal error: " + e.getMessage()); + } + } + + private boolean stopListen() { + try { + connector.stopListening(connArgs); + } catch (IOException e) { + log.complain("TEST: Unable to stop listening to the debugee VM: " + + e.getMessage()); + return false; + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return false; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return false; + } + + return true; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001/TestDescription.java new file mode 100644 index 00000000000..26f7949f5cd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ListeningConnector/accept/accept001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that debugger may establish connection with + * a debugee VM via com.sun.jdi.SocketListen connector. + * COMMENTS + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * Test was fixed to provide early redirecting of debugee output. + * See bug: + * 4905551 shmemBase_listen failed: Cannot create a file when that file already exists + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ListeningConnector.accept.accept001 + * nsk.jdi.ListeningConnector.accept.accept001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ListeningConnector.accept.accept001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001t.java new file mode 100644 index 00000000000..c29f7284af4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept001t.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.accept; + +import java.io.IOException; + +public class accept001t { + public static void main(String args[]) { + System.exit(accept001.JCK_STATUS_BASE + accept001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java new file mode 100644 index 00000000000..5eeabb30a97 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.accept; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; +import com.sun.jdi.VirtualMachine; + +import java.io.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that debugger may establish connection with + * a debugee VM via com.sun.jdi.SharedMemoryListen connector. + */ +public class accept002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String DEBUGEE_CLASS = + "nsk.jdi.ListeningConnector.accept.accept002t"; + + private Log log; + + private VirtualMachine vm; + private ListeningConnector connector; + private Map connArgs; + + IORedirector outRedirector; + IORedirector errRedirector; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new accept002().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if "com.sun.jdi.SharedMemoryListen" is not implemented +// on this platform + if (argHandler.shouldPass("com.sun.jdi.SharedMemoryListen")) + return PASSED; + + long timeout = argHandler.getWaitTime() * 60 * 1000; + log = new Log(out, argHandler); + + String connAddr = startListen(argHandler.getTransportSharedName()); + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + String cmd = java + + " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_shmem,server=n,address=" + + connAddr + " " + DEBUGEE_CLASS; + + Binder binder = new Binder(argHandler, log); + log.display("command: " + cmd); + Debugee debugee = binder.startLocalDebugee(cmd); + debugee.redirectOutput(log); + + if ((vm = attachTarget()) == null) { + log.complain("TEST: Unable to attach the debugee VM"); + debugee.close(); + return FAILED; + } + if (!stopListen()) { + log.complain("TEST: Unable to stop listen"); + debugee.close(); + return FAILED; + } + + log.display("Debugee VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + debugee.setupVM(vm); + debugee.waitForVMInit(timeout); + + log.display("\nResuming debugee VM"); + debugee.resume(); + + log.display("\nWaiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("Debugee VM has crashed: exit code=" + + code); + return FAILED; + } + log.display("Debugee VM: exit code=" + code); + return PASSED; + } + + private VirtualMachine attachTarget() { + try { + return connector.accept(connArgs); + } catch (IOException e) { + log.complain("TEST: caught IOException: " + + e.getMessage()); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return null; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return null; + } + } + + private String startListen(String name) { + Connector.Argument arg; + + connector = (ListeningConnector) + findConnector("com.sun.jdi.SharedMemoryListen"); + + connArgs = connector.defaultArguments(); + Iterator cArgsValIter = connArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) connArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + + connector.name()); + } + if (arg.name().equals("name") && name != null) + arg.setValue(name); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue=" + argVal); + else log.display("\t\tvalue=NULL"); + } + + try { + return connector.startListening(connArgs); + } catch (IOException e) { + throw new Error("TEST: Unable to start listening to the debugee VM: " + + e.getMessage()); + } catch (IllegalConnectorArgumentsException e) { + throw new Error("TEST: Illegal connector arguments: " + + e.getMessage()); + } catch (Exception e) { + throw new Error("TEST: Internal error: " + e.getMessage()); + } + } + + private boolean stopListen() { + try { + connector.stopListening(connArgs); + } catch (IOException e) { + log.complain("TEST: Unable to stop listening to the debugee VM: " + + e.getMessage()); + return false; + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return false; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return false; + } + + return true; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002/TestDescription.java new file mode 100644 index 00000000000..3c0fabf4e24 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ListeningConnector/accept/accept002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that debugger may establish connection with + * a debugee VM via com.sun.jdi.SharedMemoryListen connector. + * COMMENTS + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * Test was fixed to provide early redirecting of debugee output. + * See bug: + * 4905551 shmemBase_listen failed: Cannot create a file when that file already exists + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ListeningConnector.accept.accept002 + * nsk.jdi.ListeningConnector.accept.accept002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ListeningConnector.accept.accept002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002t.java new file mode 100644 index 00000000000..21ee1e2faf7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/accept/accept002t.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.accept; + +import java.io.IOException; + +public class accept002t { + public static void main(String args[]) { + System.exit(accept002.JCK_STATUS_BASE + accept002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java new file mode 100644 index 00000000000..cff662f9296 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ListeningConnector.listennosuspend; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; +import com.sun.jdi.VirtualMachine; + +import java.io.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that debugger may establish connection with + * a debugee VM via com.sun.jdi.SocketListen connector. + */ +public class listennosuspend001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String DEBUGEE_CLASS = "nsk.jdi.ListeningConnector.listennosuspend.listennosuspend001t"; + + private Log log; + + private VirtualMachine vm; + private ListeningConnector connector; + private Map connArgs; + + IORedirector outRedirector; + IORedirector errRedirector; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new listennosuspend001().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if "com.sun.jdi.SocketListen" is not implemented +// on this platform + if (argHandler.shouldPass("com.sun.jdi.SocketListen")) + return PASSED; + + long timeout = argHandler.getWaitTime() * 60 * 1000; + log = new Log(out, argHandler); + + String connAddr = startListen(argHandler.getTransportPortIfNotDynamic()); + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + String cmd = java + + " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,suspend=n,address=" + + connAddr + " " + DEBUGEE_CLASS; + + Binder binder = new Binder(argHandler, log); + log.display("command: " + cmd); + Debugee debugee = binder.startLocalDebugee(cmd); + debugee.redirectOutput(log); + + if ((vm = attachTarget()) == null) { + log.complain("TEST: Unable to attach the debugee VM"); + debugee.close(); + return FAILED; + } + + if (!stopListen()) { + log.complain("TEST: Unable to stop listen"); + debugee.close(); + return FAILED; + } + + log.display("Debugee VM: name=" + vm.name() + " JRE version=" + + vm.version() + "\n\tdescription=" + vm.description()); + + debugee.setupVM(vm); + //debugee.waitForVMInit(timeout); + + //log.display("\nResuming debugee VM"); + //debugee.resume(); + + log.display("\nWaiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("Debugee VM has crashed: exit code=" + + code); + return FAILED; + } + log.display("Debugee VM: exit code=" + code); + return PASSED; + } + + private VirtualMachine attachTarget() { + try { + return connector.accept(connArgs); + } catch (IOException e) { + log.complain("TEST: caught IOException: " + + e.getMessage()); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return null; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return null; + } + } + + private String startListen(String port) { + Connector.Argument arg; + + connector = (ListeningConnector) + findConnector("com.sun.jdi.SocketListen"); + + connArgs = connector.defaultArguments(); + Iterator cArgsValIter = connArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) connArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + + connector.name()); + } + if (arg.name().equals("port") && port != null) + arg.setValue(port); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue=" + argVal); + else log.display("\t\tvalue=NULL"); + } + + try { + return connector.startListening(connArgs); + } catch (IOException e) { + throw new Error("TEST: Unable to start listening to the debugee VM: " + + e.getMessage()); + } catch (IllegalConnectorArgumentsException e) { + throw new Error("TEST: Illegal connector arguments: " + + e.getMessage()); + } catch (Exception e) { + throw new Error("TEST: Internal error: " + e.getMessage()); + } + } + + private boolean stopListen() { + try { + connector.stopListening(connArgs); + } catch (IOException e) { + log.complain("TEST: Unable to stop listening to the debugee VM: " + + e.getMessage()); + return false; + } catch (IllegalConnectorArgumentsException e) { + log.complain("TEST: Illegal connector arguments: " + + e.getMessage()); + return false; + } catch (Exception e) { + log.complain("TEST: Internal error: " + e.getMessage()); + return false; + } + + return true; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001/TestDescription.java new file mode 100644 index 00000000000..8a3c75b2116 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001/TestDescription.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exactly as accept001 except using options: + * -agentlib:jdwb + * suspend=n + * COMMENT + * RFE 4920165 + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ListeningConnector.listennosuspend.listennosuspend001 + * nsk.jdi.ListeningConnector.listennosuspend.listennosuspend001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ListeningConnector.listennosuspend.listennosuspend001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001t.java new file mode 100644 index 00000000000..85a025954d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001t.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ListeningConnector.listennosuspend; + +import java.io.IOException; + +public class listennosuspend001t { + public static void main(String args[]) { + try { + Thread.sleep(60000); + } catch (Throwable e) + { + e.printStackTrace(); + System.exit(listennosuspend001.JCK_STATUS_BASE + listennosuspend001.FAILED); + } + System.exit(listennosuspend001.JCK_STATUS_BASE + listennosuspend001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java new file mode 100644 index 00000000000..3efc60b46e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.startListening; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; +import com.sun.jdi.VirtualMachine; + +import java.io.*; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test exercises JDI function ListeningConnector.startListening. + * The Socket Listening Connector is using as listening + * connector.
    + * The test cases include: + *

  • checking that listening address returned by + * ListeningConnector.startListening() matches the address + * which was set via connector's arguments; + *
  • checking that address generated by + * ListeningConnector.startListening() is valid i.e. + * debugee VM is accessible via this address. + */ +public class startlis001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String CONNECTOR_NAME = + "com.sun.jdi.SocketListen"; + static final String DEBUGEE_CLASS = + "nsk.jdi.ListeningConnector.startListening.startlis001t"; + + private Log log; + + private VirtualMachine vm; + private ListeningConnector connector; + private Map connArgs; + private PrintStream out; + + IORedirector outRedirector; + IORedirector errRedirector; + + boolean totalRes = true; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new startlis001().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + String port; + String addr; + InetAddress inetAddr = null; + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if CONNECTOR_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME)) + return PASSED; + this.out = out; + log = new Log(out, argHandler); + + long timeout = argHandler.getWaitTime() * 60 * 1000; + +/* Check that listening address returned by ListeningConnector.startListening() + matches the address which was set via connector's arguments */ + try { + inetAddr = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + log.complain("FAILURE: caught UnknownHostException " + + e.getMessage()); + totalRes = false; + } + String hostname = inetAddr.getHostName(); + String ip = inetAddr.getHostAddress(); + port = argHandler.getTransportPortIfNotDynamic(); + + initConnector(port); + if ((addr = startListen()) == null) { + log.complain("Test case #1 FAILED: unable to start listening"); + totalRes = false; + } + else { + log.display("Test case #1: start listening the address " + addr); + log.display("Expected address: "+ hostname + ":" + port + + "\n\tor "+ ip + ":" + port); + if ( (!addr.startsWith(hostname) && !addr.startsWith(ip)) || + (port != null && !addr.endsWith(port)) ) { + log.complain("Test case #1 FAILED: listening address " + addr + + "\ndoes not match expected address:\n" + + hostname + ":" + port + " or " + + ip + ":" + port); + totalRes = false; + } + if (!stopListen()) { + log.complain("TEST: unable to stop listening #1"); + totalRes = false; + } + else + log.display("Test case #1 PASSED: listening address matches expected address"); + } + +/* Check that an address generated by ListeningConnector.startListening() + is valid i.e. debugee VM is accessible via this address */ + initConnector(null); + if ((addr = startListen()) == null) { + log.complain("Test case #2 FAILED: unable to start listening"); + return FAILED; + } + else + log.display("Test case #2: start listening the address " + addr); + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + + String cmd = java + + " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,address=" + + addr + " " + DEBUGEE_CLASS; + + Binder binder = new Binder(argHandler, log); + Debugee debugee = null; + + log.display("command: " + cmd); + try { + debugee = binder.startLocalDebugee(cmd); + debugee.redirectOutput(log); + } catch (Exception e) { + stopListen(); + throw new Failure(e); + } + + if ((vm = attachTarget()) == null) { + log.complain("Test case #2 FAILED: unable to attach the debugee VM"); + debugee.close(); + stopListen(); + return FAILED; + } + else + log.display("Test case #2 PASSED: successfully attach the debugee VM"); + + if (!stopListen()) { + log.complain("TEST: unable to stop listening #2"); + debugee.close(); + return FAILED; + } + + debugee.setupVM(vm); + debugee.waitForVMInit(timeout); + + log.display("\nResuming debugee VM"); + debugee.resume(); + + log.display("\nWaiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("Debugee VM has crashed: exit code=" + + code); + return FAILED; + } + log.display("Debugee VM: exit code=" + code); + + if (totalRes) return PASSED; + else return FAILED; + } + + private VirtualMachine attachTarget() { + try { + return connector.accept(connArgs); + } catch (IOException e) { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (Exception e) { + log.complain("FAILURE: Exception: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } + } + + private void initConnector(String port) { + Connector.Argument arg; + + connector = (ListeningConnector) + findConnector(CONNECTOR_NAME); + + connArgs = connector.defaultArguments(); + Iterator cArgsValIter = connArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) connArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + + connector.name()); + } + if (arg.name().equals("port") && port != null) + arg.setValue(port); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue=" + argVal); + else log.display("\t\tvalue=NULL"); + } + } + + private String startListen() { + try { + return connector.startListening(connArgs); + } catch (IOException e) { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (Exception e) { + log.complain("FAILURE: Exception: " + e.getMessage()); + e.printStackTrace(out); + return null; + } + } + + private boolean stopListen() { + try { + connector.stopListening(connArgs); + } catch (IOException e) { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + return false; + } catch (IllegalConnectorArgumentsException e) { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + return false; + } catch (Exception e) { + log.complain("FAILURE: Exception: " + e.getMessage()); + e.printStackTrace(out); + return false; + } + + return true; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001/TestDescription.java new file mode 100644 index 00000000000..6257609a4d0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ListeningConnector/startListening/startlis001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises JDI function ListeningConnector.startListening. + * The Socket Listening Connector is using as listening connector. + * The test cases include: + * - checking that listening address returned by + * ListeningConnector.startListening() matches the address + * which was set via connector's arguments; + * - checking that address generated by + * ListeningConnector.startListening() is valid i.e. + * debugee VM is accessible via this address. + * COMMENTS + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * Test was fixed to provide early redirecting of debugee output. + * See bug: + * 4905551 shmemBase_listen failed: Cannot create a file when that file already exists + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ListeningConnector.startListening.startlis001 + * nsk.jdi.ListeningConnector.startListening.startlis001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ListeningConnector.startListening.startlis001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001t.java new file mode 100644 index 00000000000..bb8d483ba6d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis001t.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.startListening; + +public class startlis001t { + public static void main(String args[]) { + System.exit(startlis001.JCK_STATUS_BASE + startlis001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java new file mode 100644 index 00000000000..0b3eb3656af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002.java @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.startListening; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; +import com.sun.jdi.VirtualMachine; + +import java.io.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test exercises JDI function ListeningConnector.startListening. + * The Shared Memory Connector is using as listening + * connector.
    + * The test cases include: + *
  • checking that listening address returned by + * ListeningConnector.startListening() matches the address + * which was set via connector's arguments; + *
  • checking that address generated by + * ListeningConnector.startListening() is valid i.e. + * debugee VM is accessible via this address. + */ +public class startlis002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String DEBUGEE_CLASS = + "nsk.jdi.ListeningConnector.startListening.startlis002t"; + static final String CONNECTOR_NAME = + "com.sun.jdi.SharedMemoryListen"; + + private Log log; + + private VirtualMachine vm; + private ListeningConnector connector; + private Map connArgs; + private PrintStream out; + + IORedirector outRedirector; + IORedirector errRedirector; + + boolean totalRes = true; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new startlis002().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + String addr; + ArgumentHandler argHandler = new ArgumentHandler(argv); + String shmemName = argHandler.getTransportSharedName(); + +// pass if CONNECTOR_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME)) + return PASSED; + this.out = out; + log = new Log(out, argHandler); + + long timeout = argHandler.getWaitTime() * 60 * 1000; + +/* Check that listening address returned by ListeningConnector.startListening() + matches the address which was set via connector's arguments */ + initConnector(shmemName); + if ((addr = startListen()) == null) { + log.complain("Test case #1 FAILED: unable to start listening"); + totalRes = false; + } + else { + log.display("Test case #1: start listen the address " + addr); + log.display("Expected address: "+ shmemName); + if (!addr.equals(shmemName)) { + log.complain("Test case #1 FAILED: listening address " + + addr + + "\ndoes not match expected address: " + + shmemName); + totalRes = false; + } + if (!stopListen()) { + log.complain("TEST: unable to stop listening #1"); + totalRes = false; + } + else + log.display("Test case #1 PASSED: listening address matches expected address"); + } + +/* Check that an address generated by ListeningConnector.startListening() + is valid i.e. debugee VM is accessible via this address */ + initConnector(null); + if ((addr = startListen()) == null) { + log.complain("Test case #2 FAILED: unable to start listening"); + return FAILED; + } + else + log.display("Test case #2: start listening the address " + addr); + + String java = argHandler.getLaunchExecPath() + + " " + argHandler.getLaunchOptions(); + + String cmd = java + + " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_shmem,server=n,address=" + + addr + " " + DEBUGEE_CLASS; + + Binder binder = new Binder(argHandler, log); + Debugee debugee = null; + + log.display("command: " + cmd); + try { + debugee = binder.startLocalDebugee(cmd); + debugee.redirectOutput(log); + } catch (Exception e) { + stopListen(); + throw new Failure(e); + } + + if ((vm = attachTarget()) == null) { + log.complain("Test case #2 FAILED: unable to attach the debugee VM"); + debugee.close(); + stopListen(); + return FAILED; + } + else + log.display("Test case #2 PASSED: successfully attach the debugee VM"); + + if (!stopListen()) { + log.complain("TEST: unable to stop listening #2"); + debugee.close(); + return FAILED; + } + + debugee.setupVM(vm); + debugee.waitForVMInit(timeout); + + log.display("\nResuming debugee VM"); + debugee.resume(); + + log.display("\nWaiting for debugee VM exit"); + int code = debugee.waitFor(); + if (code != (JCK_STATUS_BASE+PASSED)) { + log.complain("Debugee VM has crashed: exit code=" + + code); + return FAILED; + } + log.display("Debugee VM: exit code=" + code); + + if (totalRes) return PASSED; + else return FAILED; + } + + private VirtualMachine attachTarget() { + try { + return connector.accept(connArgs); + } catch (IOException e) { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (Exception e) { + log.complain("FAILURE: Exception: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } + } + + private void initConnector(String name) { + Connector.Argument arg; + + connector = (ListeningConnector) + findConnector(CONNECTOR_NAME); + + connArgs = connector.defaultArguments(); + Iterator cArgsValIter = connArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) connArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + + connector.name()); + } + if (arg.name().equals("name") && name != null) + arg.setValue(name); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue=" + argVal); + else log.display("\t\tvalue=NULL"); + } + } + + private String startListen() { + try { + return connector.startListening(connArgs); + } catch (IOException e) { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (Exception e) { + log.complain("FAILURE: Exception: " + e.getMessage()); + e.printStackTrace(out); + return null; + } + } + + private boolean stopListen() { + try { + connector.stopListening(connArgs); + } catch (IOException e) { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + return false; + } catch (IllegalConnectorArgumentsException e) { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + return false; + } catch (Exception e) { + log.complain("FAILURE: Exception: " + e.getMessage()); + e.printStackTrace(out); + return false; + } + + return true; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002/TestDescription.java new file mode 100644 index 00000000000..767b44bf92f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ListeningConnector/startListening/startlis002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * The test exercises JDI function ListeningConnector.startListening. + * The Shared Memory Listening Connector is using as listening connector. + * The test cases include: + * - checking that listening address returned by + * ListeningConnector.startListening() matches the address + * which was set via connector's arguments; + * - checking that address generated by + * ListeningConnector.startListening() is valid i.e. + * debugee VM is accessible via this address. + * NOTE: this test is tagged "nonconcurrent" because it uses the default + * "javadebug" shmem file, as do some other tests. + * COMMENTS + * Test updated to support launching debuggee VM from another JDK + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - debuggee wrapper is used to handle VMStartEvent + * - output redirectors are incapsulated in the wrapper + * Test was fixed to provide early redirecting of debugee output. + * See bug: + * 4905551 shmemBase_listen failed: Cannot create a file when that file already exists + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ListeningConnector.startListening.startlis002 + * nsk.jdi.ListeningConnector.startListening.startlis002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ListeningConnector.startListening.startlis002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002t.java new file mode 100644 index 00000000000..06a6d266c99 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/startListening/startlis002t.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.startListening; + +public class startlis002t { + public static void main(String args[]) { + System.exit(startlis002.JCK_STATUS_BASE + startlis002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001.java new file mode 100644 index 00000000000..340c70a2ad1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.stopListening; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; + +import java.io.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test exercises JDI function ListeningConnector.stopListening. + * The Socket Connector is using as listening + * connector.
    + * The test cases include: + *
  • checking that ListeningConnector.stopListening throws + * an Exception if it has been invoked with argument map different from + * the one given for a previous ListeningConnector.startListening() + * invocation; + *
  • checking that listening can be successfully stopped if given + * argument map is the same with the one given for the previous + * ListeningConnector.startListening() invocation. + */ +public class stoplis001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String CONNECTOR_NAME = + "com.sun.jdi.SocketListen"; + + private Log log; + + private ListeningConnector connector; + private PrintStream out; + + boolean totalRes = true; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new stoplis001().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + String addr; + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if CONNECTOR_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME)) + return PASSED; + this.out = out; + log = new Log(out, argHandler); + + Map cArgs1 = initConnector(argHandler.getTransportPort()); + Map cArgs2 = initConnector(null); + if ((addr = startListen(cArgs2)) == null) { + log.complain("FAILURE: unable to start listening the address " + + addr); + return FAILED; + } + else + log.display("TEST: start listening the address " + addr); + +/* Check that an Exception is thrown if ListeningConnector.stopListening + has been invoked with argument map different from the one given for + a previous ListeningConnector.startListening() invocation */ + if (!stopListen(cArgs1, true)) + log.display("Test case #1 PASSED: unable to stop listening"); + else { + log.complain("Test case #1 FAILED: listening is successfully stopped without starting listening"); + totalRes = false; + } + +/* Check that listening can be successfully stopped if given argument map + is the same with the one given for ListeningConnector.startListening() */ + if (!stopListen(cArgs2, false)) { + log.complain("Test case #2 FAILED: unable to stop listening"); + return FAILED; + } + else + log.display("Test case #2 PASSED: listening is successfully stopped"); + + if (totalRes) return PASSED; + else return FAILED; + } + + private Map initConnector(String port) { + Connector.Argument arg; + + connector = (ListeningConnector) + findConnector(CONNECTOR_NAME); + Map connArgs = connector.defaultArguments(); + Iterator cArgsValIter = connArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) connArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + + connector.name()); + } + if (arg.name().equals("port") && port != null) + arg.setValue(port); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue=" + argVal); + else log.display("\t\tvalue=NULL"); + } + + return connArgs; + } + + private String startListen(Map cArgs) { + try { + return connector.startListening(cArgs); + } catch (IOException e) { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (Exception e) { + log.complain("FAILURE: Exception: " + e.getMessage()); + e.printStackTrace(out); + return null; + } + } + + private boolean stopListen(Map cArgs, boolean negative) { + try { + connector.stopListening(cArgs); + } catch (IOException e) { + if (negative) + log.display("stopListen: caught IOException: " + + e.getMessage()); + else { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + } + return false; + } catch (IllegalConnectorArgumentsException e) { + if (negative) + log.display("stopListen: caught IllegalConnectorArgumentsException: " + + e.getMessage()); + else { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + } + return false; + } catch (Exception e) { + if (negative) + log.display("stopListen: caught Exception: " + + e.getMessage()); + else { + log.complain("FAILURE: Exception: " + e.getMessage()); + e.printStackTrace(out); + } + return false; + } + + return true; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java new file mode 100644 index 00000000000..568e3e82633 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ListeningConnector/stopListening/stoplis001. + * VM Testbase keywords: [quick, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * The test exercises JDI function ListeningConnector.stopListening. + * The Socket Connector is using as listening connector. + * The test cases include: + * - checking that ListeningConnector.stopListening throws + * an Exception if it has been invoked with argument map different + * from the one given for a previous ListeningConnector.startListening() + * invocation; + * - checking that listening can be successfully stopped if given + * argument map is the same with the one given for the previous + * ListeningConnector.startListening() invocation. + * + * NOTE: this test is tagged "nonconcurrent" because it uses the default + * "javadebug" shmem file, as do some other tests. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ListeningConnector.stopListening.stoplis001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ListeningConnector.stopListening.stoplis001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002.java new file mode 100644 index 00000000000..68aa0ba92dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.stopListening; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.*; + +import java.io.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test exercises JDI function ListeningConnector.stopListening. + * The Shared Memory Connector is using as listening + * connector.
    + * The test cases include: + *
  • checking that ListeningConnector.stopListening throws + * an Exception if it has been invoked with argument map different from + * the one given for a previous ListeningConnector.startListening() + * invocation; + *
  • checking that listening can be successfully stopped if given + * argument map is the same with the one given for the previous + * ListeningConnector.startListening() invocation. + */ +public class stoplis002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String CONNECTOR_NAME = + "com.sun.jdi.SharedMemoryListen"; + + private Log log; + + private ListeningConnector connector; + private PrintStream out; + + boolean totalRes = true; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new stoplis002().runIt(argv, out); + } + + private int runIt(String argv[], PrintStream out) { + String addr; + ArgumentHandler argHandler = new ArgumentHandler(argv); + +// pass if CONNECTOR_NAME is not implemented +// on this platform + if (argHandler.shouldPass(CONNECTOR_NAME)) + return PASSED; + this.out = out; + log = new Log(out, argHandler); + + Map cArgs1 = initConnector(argHandler.getTransportSharedName()); + Map cArgs2 = initConnector(null); + if ((addr = startListen(cArgs2)) == null) { + log.complain("FAILURE: unable to start listening the address " + + addr); + return FAILED; + } + else + log.display("TEST: start listening the address " + addr); + +/* Check that an Exception is thrown if ListeningConnector.stopListening + has been invoked with argument map different from the one given for + a previous ListeningConnector.startListening() invocation */ + if (!stopListen(cArgs1, true)) + log.display("Test case #1 PASSED: unable to stop listening"); + else { + log.complain("Test case #1 FAILED: listening is successfully stopped without starting listening"); + totalRes = false; + } + +/* Check that listening can be successfully stopped if given argument map + is the same with the one given for ListeningConnector.startListening() */ + if (!stopListen(cArgs2, false)) { + log.complain("Test case #2 FAILED: unable to stop listening"); + return FAILED; + } + else + log.display("Test case #2 PASSED: listening is successfully stopped"); + + if (totalRes) return PASSED; + else return FAILED; + } + + private Map initConnector(String name) { + Connector.Argument arg; + + connector = (ListeningConnector) + findConnector(CONNECTOR_NAME); + Map connArgs = connector.defaultArguments(); + Iterator cArgsValIter = connArgs.keySet().iterator(); + while (cArgsValIter.hasNext()) { + String argKey = (String) cArgsValIter.next(); + String argVal = null; + + if ((arg = (Connector.Argument) connArgs.get(argKey)) == null) { + log.complain("Argument " + argKey.toString() + + "is not defined for the connector: " + + connector.name()); + } + if (arg.name().equals("name") && name != null) + arg.setValue(name); + + log.display("\targument name=" + arg.name()); + if ((argVal = arg.value()) != null) + log.display("\t\tvalue=" + argVal); + else log.display("\t\tvalue=NULL"); + } + + return connArgs; + } + + private String startListen(Map cArgs) { + try { + return connector.startListening(cArgs); + } catch (IOException e) { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (IllegalConnectorArgumentsException e) { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + return null; + } catch (Exception e) { + log.complain("FAILURE: Exception: " + e.getMessage()); + e.printStackTrace(out); + return null; + } + } + + private boolean stopListen(Map cArgs, boolean negative) { + try { + connector.stopListening(cArgs); + } catch (IOException e) { + if (negative) + log.display("stopListen: caught IOException: " + + e.getMessage()); + else { + log.complain("FAILURE: caught IOException: " + + e.getMessage()); + e.printStackTrace(out); + } + return false; + } catch (IllegalConnectorArgumentsException e) { + if (negative) + log.display("stopListen: caught IllegalConnectorArgumentsException: " + + e.getMessage()); + else { + log.complain("FAILURE: Illegal connector arguments: " + + e.getMessage()); + e.printStackTrace(out); + } + return false; + } catch (Exception e) { + if (negative) + log.display("stopListen: caught Exception: " + + e.getMessage()); + else { + log.complain("FAILURE: Exception: " + e.getMessage()); + e.printStackTrace(out); + } + return false; + } + + return true; + } + + private Connector findConnector(String connectorName) { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + + while (iter.hasNext()) { + Connector connector = (Connector) iter.next(); + if (connector.name().equals(connectorName)) { + log.display("Connector name=" + connector.name() + + "\n\tdescription=" + connector.description() + + "\n\ttransport=" + connector.transport().name()); + return connector; + } + } + throw new Error("No appropriate connector"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002/TestDescription.java new file mode 100644 index 00000000000..eb2dc321764 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis002/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ListeningConnector/stopListening/stoplis002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * The test exercises JDI function ListeningConnector.stopListening. + * The Shared Memory Connector is using as listening connector. + * The test cases include: + * - checking that ListeningConnector.stopListening throws + * an Exception if it has been invoked with argument map different + * from the one given for a previous ListeningConnector.startListening() + * invocation; + * - checking that listening can be successfully stopped if given + * argument map is the same with the one given for the previous + * ListeningConnector.startListening() invocation. + * + * NOTE: this test is tagged "nonconcurrent" because it uses the default + * "javadebug" shmem file, as do some other tests. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ListeningConnector.stopListening.stoplis002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ListeningConnector.stopListening.stoplis002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001.java new file mode 100644 index 00000000000..2f668865620 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ListeningConnector.supportsMultipleConnections; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.ListeningConnector; + + +/** + * The test for the implementation of an object of the type
    + * ListeningConnector.
    + *
    + * The test checks up that the method
    + * com.sun.jdi.connect.ListeningConnector.supportMultipleConnections()
    + * complies with its specification.
    + *
    + * In case of VMM doesn't have ListeningConnector
    + * supporting multiple connections,
    + * the test prints warning message.
    + * The test is always passed and produces
    + * the return value 95.
    + */ + +// +public class supportsmultipleconnections001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 1; + int exitCode0 = 0; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.ListeningConnector.supportsMultipleConnections()\n" + + "no ListeningConnector supporting multiconnections\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); + + for ( ; ; ) { + try { + ListeningConnector connector = + (ListeningConnector) connectorsListIterator.next(); + if (connector.supportsMultipleConnections()) { + exitCode = exitCode0; + } + } catch ( ClassCastException e) { + } catch ( NoSuchElementException e) { + break ; + } + } + + if (exitCode != exitCode0) { + out.println(sErr1); + } + return exitCode0; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001/TestDescription.java new file mode 100644 index 00000000000..7a29380ff07 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ListeningConnector/supportsMultipleConnections/supportsmultipleconnections001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ListeningConnector.Argument + * The test checks whether VMM has ListeningConnector supporting + * multiple connections. + * If no such ListeningConnector, the test prints warning message; + * otherwise no message. + * The test is always passed and produces + * the return value 95. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ListeningConnector.supportsMultipleConnections.supportsmultipleconnections001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ListeningConnector.supportsMultipleConnections.supportsmultipleconnections001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001.java new file mode 100644 index 00000000000..7ab3d6d3b17 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing two
    + * methods with equal sets of variables and arguments,
    + * a debugger creates following LocalVariable objects:
    + * - two for the same variable in the debuggee;
    + * - for "the same type - different name" variable in
    + * the same method in the debuggee;
    + * - for "same name-type - different methods" variable;
    + *
    + * and applies the method LocalVariable.equals()
    + * to pairs of the above Localvariables to
    + * check up that the method returns the follwing values:
    + * - true if two LocalVariable mirror the same variable
    + * or argument in the same method in the debuggee;
    + * - false otherwise.
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/equals/equals001 ", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.equals.equals001a"; + + String mName = "nsk.jdi.LocalVariable.equals"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("equals001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".TestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods1 = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod1"); + List methods2 = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod2"); + + Method testMethod1 = (Method) methods1.get(0); + Method testMethod2 = (Method) methods2.get(0); + + String names1[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1", + "class2_1", "iface_1", "cfc_1", "param1" }; + String names2[] = { "bl2", "bt2", "ch2", "db2", + "fl2", "in2", "ln2", "sh2", + "class2_2", "iface_2", "cfc_2", "param2" }; + + int i2; + + for (i2 = 0; i2 < names1.length; i2++) { + + log2("new check: #" + i2); + + List lVars1 = null; + List lVars2 = null; + List lVars3 = null; + List lVars4 = null; + + try { + lVars1 = testMethod1.variablesByName(names1[i2]); + lVars2 = testMethod1.variablesByName(names1[i2]); + lVars3 = testMethod1.variablesByName(names2[i2]); + lVars4 = testMethod2.variablesByName(names1[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod_i.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars1.size() != 1 || lVars2.size() != 1 || + lVars3.size() != 1 || lVars4.size() != 1 ) { + testExitCode = FAILED; + log3("ERROR: lVars-i.size() != 1 for i2= " + i2); + continue; + } + + LocalVariable lVar1 = (LocalVariable) lVars1.get(0); + LocalVariable lVar2 = (LocalVariable) lVars2.get(0); + LocalVariable lVar3 = (LocalVariable) lVars3.get(0); + LocalVariable lVar4 = (LocalVariable) lVars4.get(0); + + + if (!lVar1.equals(lVar2)) { + testExitCode = FAILED; + log3("ERROR: !lVar1.equals(lvar2) for check# " + i2); + } + if (lVar1.equals(lVar3)) { + testExitCode = FAILED; + log3("ERROR: lVar1.equals(lvar3) for check# " + i2); + } + if (lVar1.equals(lVar4)) { + testExitCode = FAILED; + log3("ERROR: lVar1.equals(lvar4) for check# " + i2); + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..69d3cef9ebd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this LocalVariable for equality. + * Returns: true if the Object is a LocalVariable, + * if both LocalVariables are contained in the same method + * (as determined by Method.equals(java.lang.Object)), and if both + * LocalVariables mirror the same declaration within that method. + * Overrides: equals in class java.lang.Object + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.equals.equals001; + * the debuggee program - nsk.jdi.LocalVariable.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.equals.equals001 + * nsk.jdi.LocalVariable.equals.equals001a + * + * @comment make sure equals001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.equals.equals001a + * @compile -g:lines,source,vars ../equals001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001a.java new file mode 100644 index 00000000000..ac42451ae65 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/equals/equals001a.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001 JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i" + ";"; + + // tested method name constant + static final String TESTED_METHOD_NAME = "testedMethod"; + + private static Debugee debugee; + private static ReferenceType debugeeClass; + + // list of tested variables names and signatures + static final String varsList[][] = { + + // not generic arguments + {"arg11PrimBoolean", null}, + {"arg12PrimInt", null}, + {"arg13Object", null}, + {"arg14String", null}, + {"arg15PrimArrShort", null}, + {"arg16ObjArrObject", null}, + + // generic arguments + {"arg21GenObject", "TT;"}, + {"arg22GenNumber", "TN;"}, + {"arg23GenObjectArr", "[TT;"}, + {"arg24GenNumberArr", "[TN;"}, + {"arg25GenObjectList", "Ljava/util/List;"}, + {"arg26GenNumberList", "Ljava/util/List;"}, + {"arg27GenObjectDerivedList", "Ljava/util/List<+TT;>;"}, + {"arg28GenNumberDerivedList", "Ljava/util/List<+TN;>;"}, + + // not generic variables + {"var11PrimBoolean", null}, + {"var12PrimInt", null}, + {"var13Object", null}, + {"var14String", null}, + {"var15PrimArrShort", null}, + {"var16ObjArrObject", null}, + + // generic variables + {"var21GenObject", "TT;"}, + {"var22GenNumber", "TN;"}, + {"var23GenObjectArr", "[TT;"}, + {"var24GenNumberArr", "[TN;"}, + {"var25GenObjectList", "Ljava/util/List;"}, + {"var26GenNumberList", "Ljava/util/List;"}, + {"var27GenObjectDerivedList", "Ljava/util/List<+TT;>;"}, + {"var28GenNumberDerivedList", "Ljava/util/List<+TN;>;"}, + + + }; + + static ArgumentHandler argHandler; + static Log log; + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new gensignature001().runThis(argv, out); + } + + private int runThis (String argv[], PrintStream out) { + + int testResult = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, DEBUGEE_CLASS_NAME); + + debugeeClass = debugee.classByName(DEBUGEE_CLASS_NAME); + if ( debugeeClass == null ) { + log.complain("Class '" + DEBUGEE_CLASS_NAME + "' not found."); + testResult = Consts.TEST_FAILED; + } + + + log.display("Checking started."); + do { + ReferenceType testedClass = debugee.classByName(TESTED_CLASS_NAME); + log.display("Found tested class: " + testedClass.name()); + + Method testedMethod = debugee.methodByName(testedClass, TESTED_METHOD_NAME); + log.display("Found tested method: " + testedMethod.name()); + + for (int i = 0; i < varsList.length; i++) { + + List localVars = null; + try { + localVars = testedMethod.variablesByName(varsList[i][0]); + } catch (AbsentInformationException e) { + log.complain("Unexpected AbsentInformationException while calling variablesByName() for " + + varsList[i][0]); + testResult = Consts.TEST_FAILED; + continue; + } + if (localVars.size() != 1) { + log.complain("Not unique local variable '" + varsList[i][0] + "' : " + localVars.size()); + testResult = Consts.TEST_FAILED; + continue; + } + log.display("Found local variable: " + varsList[i][0]); + + LocalVariable var = (LocalVariable)localVars.get(0); + String expSignature = varsList[i][1]; + log.display("Getting generic signature for local variable: " + varsList[i][0]); + + String actSignature = ""; + try { + actSignature = var.genericSignature(); + } catch (Exception e) { + log.complain("Unexpected exception while calling genericSignature() for " + + varsList[i][0] + " : " + e.getMessage()); + e.printStackTrace(out); + testResult = Consts.TEST_FAILED; + continue; + } + + if ((expSignature == null && actSignature != null) || + (expSignature != null && !expSignature.equals(actSignature))) { + log.complain("Unexpected generic signature for local variable '" + varsList[i][0] + "': " + + actSignature + "\n\tExpected generic signature: " + expSignature); + testResult = Consts.TEST_FAILED; + } else { + log.display("\tgot expected generic signature: " + actSignature); + } + } + + } while (false); + log.display("All checking completed."); + + debugee.quit(); + return testResult; + } +} // end of gensignature001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001/TestDescription.java new file mode 100644 index 00000000000..703d8ac6397 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/genericSignature/gensignature001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test for genericSignature() method of LocalVariable + * interface. + * The test checks that names and generic signatures of returned + * arguments and local variables are equal to expected ones. + * Test consists of two compoments: + * debugger application: gensignature001 + * debugged application: gensignature001a + * First, the debugger uses nsk.share support classes to launch + * debuggee and obtain Debugee object that represents debugged + * application. Also communication channel (IOPipe) is established + * between debugger and debuggee to exchange with synchronization + * signals. + * Next, the debugger obtains JDI mirrors for the tested class + * and method from the debuggee. + * Then, the debugger gets a mirror of every known local variable + * of the tested method, including arguments; gets its generic + * signature using genericSignature() call and compares returned + * character string with expected one. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.genericSignature.gensignature001 + * nsk.jdi.LocalVariable.genericSignature.gensignature001a + * + * @comment make sure gensignature001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.genericSignature.gensignature001a + * @compile -g:lines,source,vars ../gensignature001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.genericSignature.gensignature001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001a.java new file mode 100644 index 00000000000..fdf6b97fab3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/genericSignature/gensignature001a.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2004, 2018, 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 nsk.jdi.LocalVariable.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.util.*; +import java.io.*; + +/** + * This class is used as debugee part of the test. + */ + +public class gensignature001a { + + private static ArgumentHandler argsHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + public static void main(String args[]) { + gensignature001a _gensignature001a = new gensignature001a(); + System.exit(Consts.JCK_STATUS_BASE + _gensignature001a.runThis(args, System.err)); + } + + public int runThis(String args[], PrintStream out) { + + argsHandler = new ArgumentHandler(args); + log = new Log(out, argsHandler); + pipe = argsHandler.createDebugeeIOPipe(log); + + display("Debugee started!"); + + // ensure tested class loaded + display("Creating object of tested class"); + TestedClass foo = new TestedClass(); + + // send debugger signal READY + display("Sending signal to debugger: " + gensignature001.READY); + pipe.println(gensignature001.READY); + + // wait for signal QUIT from debugeer + display("Wait for '" + gensignature001.QUIT + "' signal from debugger..."); + receiveSignal(gensignature001.QUIT); + + display("Debugee PASSED"); + return Consts.TEST_PASSED; + } + + // tested class + public static class TestedClass { + int foo = 0; + + // tested method + public void testedMethod( + // not generic argumments + boolean arg11PrimBoolean, + int arg12PrimInt, + Object arg13Object, + String arg14String, + short[] arg15PrimArrShort, + Object[] arg16ObjArrObject, + + // generic arguments + T arg21GenObject, + N arg22GenNumber, + T[] arg23GenObjectArr, + N[] arg24GenNumberArr, + List arg25GenObjectList, + List arg26GenNumberList, + List arg27GenObjectDerivedList, + List arg28GenNumberDerivedList + ) { + + // not generic variables + boolean var11PrimBoolean = arg11PrimBoolean; + int var12PrimInt = arg12PrimInt; + Object var13Object = arg13Object; + String var14String = arg14String; + short[] var15PrimArrShort = arg15PrimArrShort; + Object[] var16ObjArrObject = arg16ObjArrObject; + + // generic variables + T var21GenObject = arg21GenObject; + N var22GenNumber = arg22GenNumber; + T[] var23GenObjectArr = arg23GenObjectArr; + N[] var24GenNumberArr = arg24GenNumberArr; + List var25GenObjectList = arg25GenObjectList; + List var26GenNumberList = arg26GenNumberList; + List var27GenObjectDerivedList = arg27GenObjectDerivedList; + List var28GenNumberDerivedList = arg28GenNumberDerivedList; + } + } +} // end of gensignature001a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001.java new file mode 100644 index 00000000000..af651f7010a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing two
    + * methods with equal sets of variables and arguments,
    + * a debugger creates following LocalVariable objects:
    + * - two for the same variable in the debuggee;
    + * - for "the same type - different name" variable in
    + * the same method in the debuggee;
    + * - for "same name-type - different methods" variable;
    + *
    + * applies the method LocalVariable.hashCode() and
    + * compares pairs of hashCodes to check up that
    + * - hashCodes are equal if two LocalVariable mirror
    + * the same variable or argument
    + * in the same method in the debuggee;
    + * - hashCodes are not equal otherwise.
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/hashCode/hashcode001 ", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.hashCode.hashcode001a"; + + String mName = "nsk.jdi.LocalVariable.hashCode"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("hashcode001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".TestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods1 = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod1"); + List methods2 = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod2"); + + Method testMethod1 = (Method) methods1.get(0); + Method testMethod2 = (Method) methods2.get(0); + + String names1[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1", + "class2_1", "iface_1", "cfc_1", "param1" }; + String names2[] = { "bl2", "bt2", "ch2", "db2", + "fl2", "in2", "ln2", "sh2", + "class2_2", "iface_2", "cfc_2", "param2" }; + + int i2; + + for (i2 = 0; i2 < names1.length; i2++) { + + log2("new check: #" + i2); + + List lVars1 = null; + List lVars2 = null; + List lVars3 = null; + List lVars4 = null; + + try { + lVars1 = testMethod1.variablesByName(names1[i2]); + lVars2 = testMethod1.variablesByName(names1[i2]); + lVars3 = testMethod1.variablesByName(names2[i2]); + lVars4 = testMethod2.variablesByName(names1[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod_i.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars1.size() != 1 || lVars2.size() != 1 || + lVars3.size() != 1 || lVars4.size() != 1 ) { + testExitCode = FAILED; + log3("ERROR: lVars-i.size() != 1 for i2= " + i2); + continue; + } + + LocalVariable lVar1 = (LocalVariable) lVars1.get(0); + LocalVariable lVar2 = (LocalVariable) lVars2.get(0); + LocalVariable lVar3 = (LocalVariable) lVars3.get(0); + LocalVariable lVar4 = (LocalVariable) lVars4.get(0); + + + if (lVar1.hashCode() != lVar2.hashCode()) { + testExitCode = FAILED; + log3("ERROR: lVar1.hashCode() != lVar2.hashCode() for check# " + i2); + } + if (lVar1.hashCode() == lVar3.hashCode()) { + testExitCode = FAILED; + log3("ERROR: lVar1.hashCode() == lVar3.hashCode()) for check# " + i2); + } + if (lVar1.hashCode() == lVar4.hashCode()) { + testExitCode = FAILED; + log3("ERROR: lVar1.hashCode() == lVar4.hashCode() for check# " + i2); + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..71a54bafc88 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this LocalVariable. + * Returns: the integer hash code + * Overrides: hashCode in class java.lang.Object + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.hashCode.hashcode001; + * the debuggee program - nsk.jdi.LocalVariable.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.hashCode.hashcode001 + * nsk.jdi.LocalVariable.hashCode.hashcode001a + * + * @comment make sure hashcode001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.hashCode.hashcode001a + * @compile -g:lines,source,vars ../hashcode001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001a.java new file mode 100644 index 00000000000..a7978e73619 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/hashCode/hashcode001a.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001 JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.isArgument()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing
    + * the following method:
    + * public void testmethod (int param) {
    + * boolean bl1 = false, bl2 = true;
    + * byte bt1 = 0, bt2 = 1;
    + * char ch1 = 0, ch2 = 1;
    + * double db1 = 0.0d, db2 = 1.0d;
    + * float fl1 = 0.0f, fl2 = 1.0f;
    + * int in1 = 0, in2 = 1;
    + * long ln1 = 0, ln2 = 1;
    + * short sh1 = 0, sh2 = 1;
    + * ClassForCheck_2 class2 = new ClassForCheck_2();
    + * InterfaceForCheck iface = class2;
    + * ClassForCheck cfc[] = { new ClassForCheck(),
    + * new ClassForCheck() };
    + * return;
    + * }
    + * a debugger checks up that the method
    + * LocalVariable.isArgument() applied to each of
    + * method variable returns false for all the tested
    + * local variables and true for the argument "param".
    + *
    + */ + +public class isargument001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/isArgument/isargument001 ", + sHeader2 = "--> isargument001: ", + sHeader3 = "##> isargument001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new isargument001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.isArgument.isargument001a"; + + String mName = "nsk.jdi.LocalVariable.isArgument"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("isargument001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".TestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod"); + + Method testMethod = (Method) methods.get(0); + + + String names[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1", + "class2", "iface", "cfc", "param" }; + + int i2; + int expresult = 0; + + for (i2 = 0; i2 < names.length; i2++) { + + log2("new check: #" + i2); + + List lVars = null; + try { + lVars = testMethod.variablesByName(names[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars.size() != 1) { + testExitCode = FAILED; + log3("ERROR: lVars.size() != 1 for i2=" + i2 + " : " + lVars.size()); + continue; + } + + LocalVariable lVar = (LocalVariable) lVars.get(0); + + switch (i2) { + + case 0: // BooleanType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'bl1'"); + } + break; + + case 1: // ByteType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'bt1'"); + } + break; + + case 2: // CharType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'ch1'"); + } + break; + + case 3: // DoubleType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'db1'"); + } + break; + + case 4: // FloatType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'fl1'"); + } + break; + + case 5: // IntegerType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'in1'"); + } + break; + + case 6: // LongType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'ln1'"); + } + break; + + case 7: // ShortType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'sh1'"); + } + break; + + + case 8: // ClassType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'class2'"); + } + break; + + case 9: // InterfaceType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'iface'"); + } + break; + + case 10: // ArrayType + if (lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: lVar.isArgument for 'cfc'"); + } + break; + + + case 11: // argument + if (!lVar.isArgument()) { + testExitCode = FAILED; + log3("ERROR: !lVar.isArgument for 'param'"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001/TestDescription.java new file mode 100644 index 00000000000..c75177e470c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/isArgument/isargument001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.isArgument() + * complies with its spec: + * public boolean isArgument() + * Determines if this variable is an argument to its method. + * Returns: true if this variable is argument; false otherwise. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.isArgument.isargument001; + * the debuggee program - nsk.jdi.LocalVariable.isArgument.isargument001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.isArgument.isargument001 + * nsk.jdi.LocalVariable.isArgument.isargument001a + * + * @comment make sure isargument001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.isArgument.isargument001a + * @compile -g:lines,source,vars ../isargument001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.isArgument.isargument001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001a.java new file mode 100644 index 00000000000..62cc1f2356a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isArgument/isargument001a.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.isArgument; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the isargument001 JDI test. + */ + +public class isargument001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> isargument001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> isargument001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.isVisible()
    + * complies with its spec in case when a tested program
    + * is prepared with full information,
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, instructs the debuggee to leave synchronized
    + * block, and after getting the thread2 suspended at breakpoint,
    + * StackFrame.variablesByName() is used to form LocalVariable
    + * objects for the following method variables:
    + * - visible i0 and invisible i2 within the method run
    + * whose StackFrame # = 1;
    + * - visible i2 and invisible i3 within the method runt
    + * whose StackFrame # = 0.
    + * Then a debugger checks up whether the LocalVariable objects
    + * are visible or not for corresponding StackFrames.
    + *
    + */ + +public class isvisible001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/isVisible/isvisible001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new isvisible001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.isVisible.isvisible001a"; + + private String testedClassName = + "nsk.jdi.LocalVariable.isVisible.Threadisvisible001a"; + + String mName = "nsk.jdi.LocalVariable.isVisible"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "Thread2"; + + String breakpointMethod1 = "runt1"; + String bpLine1 = "breakpointLineNumber1"; + + BreakpointRequest breakpRequest1 = null; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + StackFrame stackFrame = null; + StackFrame stackFrame1 = null; + + List methods = null; + + Method runmethod = null; + Method runt1method = null; + + List lVars = null; + + LocalVariable l_i0 = null; + LocalVariable l_i1 = null; + LocalVariable l_i2 = null; + LocalVariable l_i3 = null; + + int expresult = returnCode0; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting a breakpoint event"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + stackFrame1 = thread2.frame(1); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + } + + label2: { + + if (expresult != returnCode0) + break label2; + + methods = ((ReferenceType) classes.get(0)).methodsByName("run"); + runmethod = (Method) methods.get(0); + + methods = ((ReferenceType) classes.get(0)).methodsByName("runt1"); + runt1method = (Method) methods.get(0); + + try { + log2(" lVars = runmethod.variablesByName('i0');"); + lVars = runmethod.variablesByName("i0"); + if (lVars.size() != 1) { + log3("ERROR: lVars.size() != 1"); + expresult = returnCode1; + } + l_i0 = (LocalVariable) lVars.get(0); + + log2(" lVars = runmethod.variablesByName('i1');"); + lVars = runmethod.variablesByName("i1"); + if (lVars.size() != 1) { + log3("ERROR: lVars.size() != 1"); + expresult = returnCode1; + } + l_i1 = (LocalVariable) lVars.get(0); + + log2(" lVars = runmethod.variablesByName('i2');"); + lVars = runt1method.variablesByName("i2"); + if (lVars.size() != 1) { + log3("ERROR: lVars.size() != 1"); + expresult = returnCode1; + } + l_i2 = (LocalVariable) lVars.get(0); + + log2(" lVars = runmethod.variablesByName('i3');"); + lVars = runt1method.variablesByName("i3"); + if (lVars.size() != 1) { + log3("ERROR: lVars.size() != 1"); + expresult = returnCode1; + } + l_i3 = (LocalVariable) lVars.get(0); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException"); + expresult = returnCode1; + } + if (expresult != returnCode0) + break label2; + + + log2(" checkin up: l_i0.isVisible(stackFrame1); expected: true"); + try { + if (!l_i0.isVisible(stackFrame1)) { + log3("ERROR: !l_i0.isVisible(stackFrame1)"); + expresult = returnCode1; + } + } catch ( IllegalArgumentException e ) { + log3("ERROR: IllegalArgumentException"); + expresult = returnCode1; + } + + log2(" checkin up: l_i1.isVisible(stackFrame1); expected: false"); + try { + if (l_i1.isVisible(stackFrame1)) { + log3("ERROR: l_i1.isVisible(stackFrame1)"); + expresult = returnCode1; + } + } catch ( IllegalArgumentException e ) { + log3("ERROR: IllegalArgumentException"); + expresult = returnCode1; + } + + log2(" checkin up: l_i2.isVisible(stackFrame1); expected: IllegalArgumentException"); + try { + if (l_i2.isVisible(stackFrame1)) { + log3("ERROR: no IllegalArgumentException"); + expresult = returnCode1; + } + } catch ( IllegalArgumentException e ) { + log2(" : IllegalArgumentException"); + } + + log2(" checkin up: l_i3.isVisible(stackFrame1); expected: IllegalArgumentException"); + try { + if (l_i3.isVisible(stackFrame1)) { + log3("ERROR: no IllegalArgumentException"); + expresult = returnCode1; + } + } catch ( IllegalArgumentException e ) { + log2(" : IllegalArgumentException"); + } + + log2(" checkin up: l_i1.isVisible(stackFrame); expected: IllegalArgumentException"); + try { + if (l_i1.isVisible(stackFrame)) { + log3("ERROR: no IllegalArgumentException"); + expresult = returnCode1; + } + } catch ( IllegalArgumentException e ) { + log2(" : IllegalArgumentException"); + } + + log2(" checkin up: l_i2.isVisible(stackFrame); expected: true"); + try { + if (!l_i2.isVisible(stackFrame)) { + log3("ERROR: !l_i2.isVisible(stackFrame)"); + expresult = returnCode1; + } + } catch ( IllegalArgumentException e ) { + log3("ERROR: IllegalArgumentException for i2 in stackFrame"); + expresult = returnCode1; + } + log2(" checkin up: l_i3.isVisible(stackFrame); expected: false"); + try { + if (l_i3.isVisible(stackFrame)) { + log3("ERROR: l_i3.isVisible(stackFrame)"); + expresult = returnCode1; + } + } catch ( IllegalArgumentException e ) { + log3("ERROR: IllegalArgumentException for i3 in stackFrame");; + expresult = returnCode1; + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001/TestDescription.java new file mode 100644 index 00000000000..ab2189a5f3c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/isVisible/isvisible001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.isVisible() + * complies with its spec: + * public boolean isVisible(StackFrame frame) + * Determines whether this variable can be accessed from the given StackFrame. + * See StackFrame.visibleVariables() for + * a complete description variable visibility in this interface. + * Parameters: frame - the StackFrame querying visibility + * Returns: true if this variable is visible; false otherwise. + * Throws: java.lang.IllegalArgumentException - + * if the stack frame's method does not match this variable's method. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.isVisible.isvisible001; + * the debuggee program - nsk.jdi.LocalVariable.isVisible.isvisible001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.isVisible.isvisible001 + * nsk.jdi.LocalVariable.isVisible.isvisible001a + * + * @comment make sure isvisible001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.isVisible.isvisible001a + * @compile -g:lines,source,vars ../isvisible001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.isVisible.isvisible001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001a.java new file mode 100644 index 00000000000..72253f9d39d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001a.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.isVisible; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the isvisible001 JDI test. + */ + +public class isvisible001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.name()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing
    + * the following method:
    + * public void testmethod (int param) {
    + * boolean bl1 = false, bl2 = true;
    + * byte bt1 = 0, bt2 = 1;
    + * char ch1 = 0, ch2 = 1;
    + * double db1 = 0.0d, db2 = 1.0d;
    + * float fl1 = 0.0f, fl2 = 1.0f;
    + * int in1 = 0, in2 = 1;
    + * long ln1 = 0, ln2 = 1;
    + * short sh1 = 0, sh2 = 1;
    + * ClassForCheck_2 class2 = new ClassForCheck_2();
    + * InterfaceForCheck iface = class2;
    + * ClassForCheck cfc[] = { new ClassForCheck(),
    + * new ClassForCheck() };
    + * return;
    + * }
    + * a debugger checks up that the method
    + * LocalVariable.name() applied to each of
    + * method variable returns its name.
    + *
    + */ + +public class name001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/name/name001 ", + sHeader2 = "--> name001: ", + sHeader3 = "##> name001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new name001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.name.name001a"; + + String mName = "nsk.jdi.LocalVariable.name"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("name001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".TestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod"); + + Method testMethod = (Method) methods.get(0); + + + String names[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1", + "class2", "iface", "cfc" }; + + int i2; + int expresult = 0; + + for (i2 = 0; i2 < names.length; i2++) { + + log2("new check: #" + i2); + + List lVars = null; + try { + lVars = testMethod.variablesByName(names[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars.size() != 1) { + testExitCode = FAILED; + log3("ERROR: lVars.size() != 1 for i2=" + i2 + " : " + lVars.size()); + continue; + } + + LocalVariable lVar = (LocalVariable) lVars.get(0); + + String lVarName = lVar.name(); + + switch (i2) { + + case 0: // BooleanType + if (!lVarName.equals("bl1")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('bl1')"); + } + + break; + + case 1: // ByteType + + if (!lVarName.equals("bt1")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('bt1')"); + } + break; + + case 2: // CharType + if (!lVarName.equals("ch1")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('ch1')"); + } + break; + + case 3: // DoubleType + if (!lVarName.equals("db1")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('db1')"); + } + break; + + case 4: // FloatType + if (!lVarName.equals("fl1")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('fl1')"); + } + break; + + case 5: // IntegerType + if (!lVarName.equals("in1")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('in1')"); + } + break; + + case 6: // LongType + if (!lVarName.equals("ln1")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('ln1')"); + } + break; + + case 7: // ShortType + if (!lVarName.equals("sh1")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('sh1')"); + } + break; + + + case 8: // ClassType + if (!lVarName.equals("class2")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('class2')"); + } + break; + + case 9: // InterfaceType + if (!lVarName.equals("iface")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('iface')"); + } + break; + + case 10: // ArrayType + if (!lVarName.equals("cfc")) { + testExitCode = FAILED; + log3("ERROR: !lVarName.equals('cfc')"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001/TestDescription.java new file mode 100644 index 00000000000..f7dbe7d9834 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/name/name001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.name() + * complies with its spec: + * public java.lang.String name() + * Gets the name of the local variable. + * Returns: a string containing the name. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.name.name001; + * the debuggee program - nsk.jdi.LocalVariable.name.name001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.name.name001 + * nsk.jdi.LocalVariable.name.name001a + * + * @comment make sure name001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.name.name001a + * @compile -g:lines,source,vars ../name001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001a.java new file mode 100644 index 00000000000..ad73c392175 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/name/name001a.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the name001 JDI test. + */ + +public class name001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> name001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> name001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.signature()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing
    + * the following method:
    + * public void testmethod (int param) {
    + * boolean bl1 = false, bl2 = true;
    + * byte bt1 = 0, bt2 = 1;
    + * char ch1 = 0, ch2 = 1;
    + * double db1 = 0.0d, db2 = 1.0d;
    + * float fl1 = 0.0f, fl2 = 1.0f;
    + * int in1 = 0, in2 = 1;
    + * long ln1 = 0, ln2 = 1;
    + * short sh1 = 0, sh2 = 1;
    + * ClassForCheck_2 class2 = new ClassForCheck_2();
    + * InterfaceForCheck iface = class2;
    + * ClassForCheck cfc[] = { new ClassForCheck(),
    + * new ClassForCheck() };
    + * return;
    + * }
    + * a debugger checks up that the method
    + * LocalVariable.signature() applied to each of
    + * method variable returns its JNI-style signature.
    + *
    + */ + +public class signature001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/signature/signature001 ", + sHeader2 = "--> signature001: ", + sHeader3 = "##> signature001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new signature001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.signature.signature001a"; + + String mName = "nsk.jdi.LocalVariable.signature"; + + String mSignature = "nsk/jdi/LocalVariable/signature"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("signature001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".TestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod"); + + Method testMethod = (Method) methods.get(0); + + + String names[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1", + "class2", "iface", "cfc" }; + + int i2; + int expresult = 0; + + for (i2 = 0; i2 < names.length; i2++) { + + log2("new check: #" + i2); + + List lVars = null; + try { + lVars = testMethod.variablesByName(names[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars.size() != 1) { + testExitCode = FAILED; + log3("ERROR: lVars.size() != 1 for i2=" + i2 + " : " + lVars.size()); + continue; + } + + LocalVariable lVar = (LocalVariable) lVars.get(0); + + String lVarSignature = lVar.signature(); + + switch (i2) { + + case 0: // BooleanType + if (!lVarSignature.equals("Z")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals('Z')"); + } + break; + + case 1: // ByteType + + if (!lVarSignature.equals("B")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals('B')"); + } + break; + + case 2: // CharType + if (!lVarSignature.equals("C")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals('C')"); + } + break; + + case 3: // DoubleType + if (!lVarSignature.equals("D")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals('D')"); + } + break; + + case 4: // FloatType + if (!lVarSignature.equals("F")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals('F')"); + } + break; + + case 5: // IntegerType + if (!lVarSignature.equals("I")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals('I')"); + } + break; + + case 6: // LongType + if (!lVarSignature.equals("J")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals('J')"); + } + break; + + case 7: // ShortType + if (!lVarSignature.equals("S")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals('S')"); + } + break; + + + case 8: // ClassType + if (!lVarSignature.equals("L" + mSignature + "/ClassForCheck_2;")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals() : " + lVarSignature); + } + break; + + case 9: // InterfaceType + if (!lVarSignature.equals("L" + mSignature + "/InterfaceForCheck;")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals() : " + lVarSignature); + } + break; + + case 10: // ArrayType + if (!lVarSignature.equals("[L" + mSignature + "/ClassForCheck;")) { + testExitCode = FAILED; + log3("ERROR: !lVarSignature.equals() : " + lVarSignature); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001/TestDescription.java new file mode 100644 index 00000000000..0a236ed5651 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/signature/signature001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.signature() + * complies with its spec: + * public java.lang.String signature() + * Gets the JNI signature of the local variable. + * Returns: a string containing the signature. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.signature.signature001; + * the debuggee program - nsk.jdi.LocalVariable.signature.signature001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.signature.signature001 + * nsk.jdi.LocalVariable.signature.signature001a + * + * @comment make sure signature001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.signature.signature001a + * @compile -g:lines,source,vars ../signature001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.signature.signature001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001a.java new file mode 100644 index 00000000000..837976672b1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/signature/signature001a.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the signature001 JDI test. + */ + +public class signature001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> signature001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> signature001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + // Finding of debuggee's main method + Method mainMethod = methodByName(debuggeeClass, "main"); + + display("Checking toString() method for local variables of debuggee's main method..."); + + // Check all methods from debuggee + for (int i = 0; i < checkedVars.length; i++) { + + LocalVariable localVar = variableByName(mainMethod, checkedVars[i]); + + try { + String str = localVar.toString(); + if (str == null) { + complain("toString() returns null for LocalVariable of debuggee's local variable: " + checkedVars[i]); + exitStatus = Consts.TEST_FAILED; + } else if (str.length() == 0) { + complain("toString() returns empty string for LocalVariable of debuggee's local variable: " + checkedVars[i]); + exitStatus = Consts.TEST_FAILED; + } else { + display("toString() returns for debuggee's local variable " + checkedVars[i] + " : " + str); + } + } catch(Exception e) { + complain("Unexpected " + e + " when getting LocalVariable of debuggee's local variable: " + checkedVars[i]); + exitStatus = Consts.TEST_FAILED; + } + + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static Method methodByName(ReferenceType refType, String methodName) { + List methodList = refType.methodsByName(methodName); + if (methodList == null) { + throw new Failure("Can not find method: " + methodName); + } + if (methodList.size() > 1) { + throw new Failure("Found more than one method with name : " + methodName); + } + + Method method = (Method) methodList.get(0); + return method; + } + + private static LocalVariable variableByName(Method method, String varName) { + List varList = null; + try { + varList = method.variablesByName(varName); + } catch (AbsentInformationException e) { + throw new Failure("Unexpected AbsentInformationException while getting variable: " + varName); + } + if (varList == null) { + throw new Failure("Can not find variable: " + varName); + } + if (varList.size() > 1) { + throw new Failure("Found more than one variable with name : " + varName); + } + + LocalVariable var = (LocalVariable) varList.get(0); + return var; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..56c86ce8676 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/toString/tostring001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public toString() method of an implementing class of + * com.sun.jdi.LocalVariable interface. + * The test checks an assertion: + * In conformity with the contract for java.lang.Object.toString(), + * the overrided method returns representing non-empty string for + * a LocalVariable object of a debuggee's local variable. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for LocalVariable + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.toString.tostring001 + * nsk.jdi.LocalVariable.toString.tostring001a + * + * @comment make sure tostring001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.toString.tostring001a + * @compile -g:lines,source,vars ../tostring001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001a.java new file mode 100644 index 00000000000..a551705a311 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.LocalVariable.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class tostring001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + // Tested local variables -------------------- + boolean z0 = true, z1[] = {z0}, z2[][] = {z1}; + byte b0 = (byte)-1, b1[] = {b0}, b2[][] = {b1}; + char c0 = '\n', c1[] = {c0}, c2[][] = {c1}; + double d0 = (double)-1, d1[] = {d0}, d2[][] = {d1}; + float f0 = (float)-1, f1[] = {f0}, f2[][] = {f1}; + int i0 = -1, i1[] = {i0}, i2[][] = {i1}; + long l0 = (long)-1, l1[] = {l0}, l2[][] = {l1}; + short r0 = (short)-1, r1[] = {r0}, r2[][] = {r1}; + + Boolean Z0 = new Boolean(false), Z1[] = {Z0}, Z2[][] = {Z1}; + Byte B0 = new Byte((byte)1), B1[] = {B0}, B2[][] = {B1}; + Character C0 = new Character('z'), C1[] = {C0}, C2[][] = {C1}; + Double D0 = new Double((double)1), D1[] = {D0}, D2[][] = {D1}; + Float F0 = new Float((float)1), F1[] = {F0}, F2[][] = {F1}; + Integer I0 = new Integer(1), I1[] = {I0}, I2[][] = {I1}; + Long L0 = new Long((long)1), L1[] = {L0}, L2[][] = {L1}; + Short R0 = new Short((short)1), R1[] = {R0}, R2[][] = {R1}; + + String s0 = "string", s1[] = {s0}, s2[][] = {s1}; + Object o0 = new Object(), o1[] = {o0}, o2[][] = {o1}; + tostring001aP p0 = new tostring001aP(), p1[] = {p0}, p2[][] = {p1}; + tostring001aM m0 = new tostring001aP(), m1[] = {m0}, m2[][] = {m1}; + //-------------------------------------------- + + try { + pipe.println(tostring001.SIGNAL_READY); + + receiveSignal(tostring001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods +} + +//--------------------------------------------------------- test specific classes +class tostring001aP implements tostring001aM {} +interface tostring001aM {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001.java new file mode 100644 index 00000000000..5f215bcbf21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001.java @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.type()
    + * complies with its spec when LocalVariable is one of
    + * primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing
    + * the following method:
    + * public void testmethod (int param) {
    + * boolean bl1 = false, bl2 = true;
    + * byte bt1 = 0, bt2 = 1;
    + * char ch1 = 0, ch2 = 1;
    + * double db1 = 0.0d, db2 = 1.0d;
    + * float fl1 = 0.0f, fl2 = 1.0f;
    + * int in1 = 0, in2 = 1;
    + * long ln1 = 0, ln2 = 1;
    + * short sh1 = 0, sh2 = 1;
    + * return;
    + * }
    + * a debugger checks up that the method
    + * LocalVariable.type() applied to each of primitive
    + * type method variable returns a Type object casted to
    + * a corresponding primitive type.
    + *
    + */ + +public class type001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/type/type001 ", + sHeader2 = "--> type001: ", + sHeader3 = "##> type001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new type001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.type.type001a"; + + String mName = "nsk.jdi.LocalVariable.type"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("type001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".type001aTestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod"); + + Method testMethod = (Method) methods.get(0); + + + String names[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1" }; + + int i2; + int expresult = 0; + + for (i2 = 0; i2 < names.length; i2++) { + + log2("new check: #" + i2); + + List lVars = null; + try { + lVars = testMethod.variablesByName(names[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars.size() != 1) { + testExitCode = FAILED; + log3("ERROR: lVars.size() != 1 for i2=" + i2 + " : " + lVars.size()); + continue; + } + + LocalVariable lVar = (LocalVariable) lVars.get(0); + + Type lVarType = null; + try { + lVarType = lVar.type(); + } catch ( ClassNotLoadedException e) { + log3("ERROR : ClassNotLoadedExc for lVarType = lVar.type();"); + testExitCode = FAILED; + continue; + } + + switch (i2) { + + case 0: // BooleanType + try { + BooleanType bl = (BooleanType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: BooleanType blt = (BooleanType) lVarType;"); + } + + break; + + case 1: // ByteType + + try { + ByteType bt = (ByteType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ByteType bt = (ByteType) lVarType;"); + } + break; + + case 2: // CharType + try { + CharType ch = (CharType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: CharType ch = (CharType) lVarType;"); + } + break; + + case 3: // DoubleType + try { + DoubleType db = (DoubleType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: DoubleType db = (DoubleType) lVarType;"); + } + break; + + case 4: // FloatType + try { + FloatType fl = (FloatType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: FloatType fl = (FloatType) lVarType;"); + } + break; + + case 5: // IntegerType + try { + IntegerType in = (IntegerType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: IntegerType in = (IntegerType) lVarType;"); + } + break; + + case 6: // LongType + try { + LongType ln = (LongType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: LongType ln = (LongType) lVarType;"); + } + break; + + case 7: // ShortType + try { + ShortType sh = (ShortType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ShortType sh = (ShortType) lVarType;"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001/TestDescription.java new file mode 100644 index 00000000000..359372ecc81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/type/type001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.type() + * complies with its spec: + * public Type type() + * throws ClassNotLoadedException + * Returns the type of the this LocalVariable. + * For primitive variables, an appropriate PrimitiveType is always returned. + * For object variables, the appropriate ReferenceType is returned if + * it has been loaded through the enclosing type's class loader. + * Returns: the Type of this local variable. + * Throws: ClassNotLoadedException - + * if the type has not yet been loaded through + * the appropriate class loader. + * when the type is one of primitive types and + * a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.type.type001; + * the debuggee program - nsk.jdi.LocalVariable.type.type001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.type.type001 + * nsk.jdi.LocalVariable.type.type001a + * + * @comment make sure type001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.type.type001a + * @compile -g:lines,source,vars ../type001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.type.type001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001a.java new file mode 100644 index 00000000000..c4eb836d2c5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type001a.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the type001 JDI test. + */ + +public class type001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> type001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> type001a: " + message); + } + + //====================================================== test program + + static type001aTestClass obj = new type001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.type()
    + * complies with its spec when LocalVariable is one of
    + * ReferenceTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing
    + * the following method:
    + * public void testmethod (int param) {
    + * ClassForCheck_2 class2 = new ClassForCheck_2();
    + * InterfaceForCheck iface = class2;
    + * ClassForCheck cfc[] = { new ClassForCheck(),
    + * new ClassForCheck() };
    + * return;
    + * }
    + * a debugger checks up that the method
    + * LocalVariable.type() applied to each of ReferenceType
    + * method variable returns a Type object casted to
    + * a corresponding ReferenceType.
    + *
    + */ + +public class type002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/type/type002 ", + sHeader2 = "--> type002: ", + sHeader3 = "##> type002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new type002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.type.type002a"; + + String mName = "nsk.jdi.LocalVariable.type"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("type002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".type002aTestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod"); + + Method testMethod = (Method) methods.get(0); + + + String names[] = { "class2", "iface", "cfc" }; + + int i2; + int expresult = 0; + + for (i2 = 0; i2 < names.length; i2++) { + + log2("new check: #" + i2); + + List lVars = null; + try { + lVars = testMethod.variablesByName(names[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars.size() != 1) { + testExitCode = FAILED; + log3("ERROR: lVars.size() != 1 for i2=" + i2 + " : " + lVars.size()); + continue; + } + + LocalVariable lVar = (LocalVariable) lVars.get(0); + + Type lVarType = null; + try { + lVarType = lVar.type(); + } catch ( ClassNotLoadedException e) { + log3("ERROR : ClassNotLoadedExc for lVarType = lVar.type();"); + testExitCode = FAILED; + continue; + } + + switch (i2) { + + case 0: // ClassType + try { + ClassType ct = (ClassType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassType ct = (ClassType) lVarType;"); + } + + break; + + case 1: // InterfaceType + + try { + InterfaceType it = (InterfaceType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: InterfaceType it = (InterfaceType) lVarType;"); + } + break; + + case 2: // ArrayType + try { + ArrayType at = (ArrayType) lVarType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ArrayType at = (ArrayType) lVarType;"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002/TestDescription.java new file mode 100644 index 00000000000..a42450a6b79 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/type/type002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.type() + * complies with its spec: + * public Type type() + * throws ClassNotLoadedException + * Returns the type of the this LocalVariable. + * For primitive variables, an appropriate PrimitiveType is always returned. + * For object variables, the appropriate ReferenceType is returned if + * it has been loaded through the enclosing type's class loader. + * Returns: the Type of this local variable. + * Throws: ClassNotLoadedException - + * if the type has not yet been loaded through + * the appropriate class loader. + * when the type is one of ReferenceTypes and + * a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.typetype002; + * the debuggee program - nsk.jdi.LocalVariable.type.type002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.type.type002 + * nsk.jdi.LocalVariable.type.type002a + * + * @comment make sure type002a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.type.type002a + * @compile -g:lines,source,vars ../type002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.type.type002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002a.java new file mode 100644 index 00000000000..aea6a4bccca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/type/type002a.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the type002 JDI test. + */ + +public class type002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> type002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> type002a: " + message); + } + + //====================================================== test program + + static type002aTestClass obj = new type002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.typeName()
    + * complies with its spec when LocalVariable is one of
    + * primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing
    + * the following method:
    + * public void testmethod (int param) {
    + * boolean bl1 = false, bl2 = true;
    + * byte bt1 = 0, bt2 = 1;
    + * char ch1 = 0, ch2 = 1;
    + * double db1 = 0.0d, db2 = 1.0d;
    + * float fl1 = 0.0f, fl2 = 1.0f;
    + * int in1 = 0, in2 = 1;
    + * long ln1 = 0, ln2 = 1;
    + * short sh1 = 0, sh2 = 1;
    + * return;
    + * }
    + * a debugger checks up that the method
    + * LocalVariable.typeName() applied to each of
    + * primitive type method variable returns a name of
    + * a corresponding primitive type.
    + *
    + */ + +public class typename001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/typeName/typename001 ", + sHeader2 = "--> typename001: ", + sHeader3 = "##> typename001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new typename001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.typeName.typename001a"; + + String mName = "nsk.jdi.LocalVariable.typeName"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("typename001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".typename001aTestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod"); + + Method testMethod = (Method) methods.get(0); + + + String names[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1" }; + + int i2; + int expresult = 0; + + for (i2 = 0; i2 < names.length; i2++) { + + log2("new check: #" + i2); + + List lVars = null; + try { + lVars = testMethod.variablesByName(names[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars.size() != 1) { + testExitCode = FAILED; + log3("ERROR: lVars.size() != 1 for i2=" + i2 + " : " + lVars.size()); + continue; + } + + LocalVariable lVar = (LocalVariable) lVars.get(0); + + String lVarTypeName = null; + lVarTypeName = lVar.typeName(); + + switch (i2) { + + case 0: // BooleanType + if (!lVarTypeName.equals("boolean")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals('boolean')"); + } + + break; + + case 1: // ByteType + + if (!lVarTypeName.equals("byte")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals('byte')"); + } + break; + + case 2: // CharType + if (!lVarTypeName.equals("char")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals('char')"); + } + break; + + case 3: // DoubleType + if (!lVarTypeName.equals("double")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals('double')"); + } + break; + + case 4: // FloatType + if (!lVarTypeName.equals("float")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals('float')"); + } + break; + + case 5: // IntegerType + if (!lVarTypeName.equals("int")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals('int')"); + } + break; + + case 6: // LongType + if (!lVarTypeName.equals("long")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals('long')"); + } + break; + + case 7: // ShortType + if (!lVarTypeName.equals("short")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals('short')"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001/TestDescription.java new file mode 100644 index 00000000000..6bbdeec97b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/typeName/typename001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.typeName() + * complies with its spec: + * public java.lang.String typeName() + * Returns: a text representation of the declared type of this variable. + * when the declared type is one of primitive types and + * a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.typeName.typename001; + * the debuggee program - nsk.jdi.LocalVariable.typeName.typename001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.typeName.typename001 + * nsk.jdi.LocalVariable.typeName.typename001a + * + * @comment make sure typename001a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.typeName.typename001a + * @compile -g:lines,source,vars ../typename001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.typeName.typename001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001a.java new file mode 100644 index 00000000000..da4b5d49f64 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.typeName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the typename001 JDI test. + */ + +public class typename001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> typename001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> typename001a: " + message); + } + + //====================================================== test program + + static typename001aTestClass obj = new typename001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LocalVariable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LocalVariable.typeName()
    + * complies with its spec when LocalVariable is one of
    + * ReferenceTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object containing
    + * the following method:
    + * public void testmethod (int param) {
    + * typename002aClassForCheck_2 class2 = new typename002aClassForCheck_2();
    + * typename002atypename002aInterfaceForCheck iface = class2;
    + * typename002aClassForCheck cfc[] = { new typename002aClassForCheck(),
    + * new typename002aClassForCheck() };
    + * return;
    + * }
    + * a debugger checks up that the method
    + * LocalVariable.typeName() applied to each of
    + * ReferenceType method variable returns
    + * a name of a corresponding ReferenecType.
    + *
    + */ + +public class typename002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocalVariable/typeName/typename002 ", + sHeader2 = "--> typename002: ", + sHeader3 = "##> typename002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new typename002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocalVariable.typeName.typename002a"; + + String mName = "nsk.jdi.LocalVariable.typeName"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("typename002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".typename002aTestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + List methods = + ((ReferenceType) listOfLoadedClasses.get(0)). + methodsByName("testmethod"); + + Method testMethod = (Method) methods.get(0); + + + String names[] = { "class2", "iface", "cfc" }; + + int i2; + int expresult = 0; + + for (i2 = 0; i2 < names.length; i2++) { + + log2("new check: #" + i2); + + List lVars = null; + try { + lVars = testMethod.variablesByName(names[i2]); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for " + + "lVars = testMethod.variablesByName(names[i2])" ); + testExitCode = FAILED; + continue; + } + if (lVars.size() != 1) { + testExitCode = FAILED; + log3("ERROR: lVars.size() != 1 for i2=" + i2 + " : " + lVars.size()); + continue; + } + + LocalVariable lVar = (LocalVariable) lVars.get(0); + + String lVarTypeName = null; + lVarTypeName = lVar.typeName(); + + switch (i2) { + + case 0: // ClassType + + if (!lVarTypeName.equals(mName + ".typename002aClassForCheck_2")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals(mName + '.typename002aClassForCheck_2') : " + + lVarTypeName); + } + + break; + + case 1: // InterfaceType + + if (!lVarTypeName.equals(mName + ".typename002aInterfaceForCheck")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals(mName + '.typename002aInterfaceForCheck') : " + + lVarTypeName); + } + break; + + case 2: // ArrayType + + if (!lVarTypeName.equals(mName + ".typename002aClassForCheck[]")) { + testExitCode = FAILED; + log3("ERROR: !lVarTypeName.equals(mName + '.typename002aClassForCheck[]') : " + + lVarTypeName); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002/TestDescription.java new file mode 100644 index 00000000000..5442089ec79 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocalVariable/typeName/typename002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocalVariable. + * The test checks up that a result of the method + * com.sun.jdi.LocalVariable.typeName() + * complies with its spec: + * public java.lang.String typeName() + * Returns: a text representation of the declared type of this variable. + * when the declared type is one of ReferenceTypes and + * a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.LocalVariable.typeName.typename002; + * the debuggee program - nsk.jdi.LocalVariable.typeName.typename002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocalVariable.typeName.typename002 + * nsk.jdi.LocalVariable.typeName.typename002a + * + * @comment make sure typename002a is compiled with full debug info + * @clean nsk.jdi.LocalVariable.typeName.typename002a + * @compile -g:lines,source,vars ../typename002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocalVariable.typeName.typename002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002a.java new file mode 100644 index 00000000000..dff4bf00c14 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/typeName/typename002a.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocalVariable.typeName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the typename002 JDI test. + */ + +public class typename002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> typename002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> typename002a: " + message); + } + + //====================================================== test program + + static typename002aTestClass obj = new typename002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Locatable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Locatable.location()
    + * complies with its spec when a tested method
    + * is one of PrimitiveTypes, void or native.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class TestClass {
    + * public static boolean bl () { return false; }
    + * public static byte bt () { return 0; }
    + * private static char ch () { return 0; }
    + * protected static double db () { return 0.0d; }
    + * public float fl () { return 0.0f; }
    + * public int in () { return 0; }
    + * private long ln () { return 0; }
    + * protected short sh () { return 0; }
    + * public void vd () { return ; }
    + * }
    + * a debugger checks up that for all of the above methods,
    + * the invocation of the method Locatable.location()
    + * returns non-null values.
    + *
    + */ + +public class location001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Locatable/location/location001 ", + sHeader2 = "--> location001: ", + sHeader3 = "##> location001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new location001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Locatable.location.location001a"; + + String mName = "nsk.jdi.Locatable.location"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("location001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".location001aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + Location mLocation = null; + + String bl = "bl"; + String bt = "bt"; + String ch = "ch"; + String db = "db"; + String fl = "fl"; + String in = "in"; + String ln = "ln"; + String sh = "sh"; + String vd = "vd"; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(bl); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a boolean method"); + expresult = 1; + break; + } + break; + + case 1: // byte method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(bt); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a byte method"); + expresult = 1; + break; + } + break; + + case 2: // char method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(ch); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a char method"); + expresult = 1; + break; + } + break; + + case 3: // double method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(db); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a double method"); + expresult = 1; + break; + } + break; + + case 4: // float method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(fl); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a float method"); + expresult = 1; + break; + } + break; + + case 5: // int method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(in); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for an int method"); + expresult = 1; + break; + } + break; + + case 6: // long method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(ln); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a long method"); + expresult = 1; + break; + } + break; + + case 7: // short method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(sh); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a short method"); + expresult = 1; + break; + } + break; + + case 8: // void method + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(vd); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a void method"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001/TestDescription.java new file mode 100644 index 00000000000..40fe6437b0f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Locatable/location/location001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Locatable. + * The test checks up that a result of the method + * com.sun.jdi.Locatable.location() + * complies with its spec: + * public Location location() + * Returns the Location of this mirror, + * if there is executable Java language code associated with it. + * Returns: the Location of this mirror, or + * null if there is no executable code associated with it. + * For example, abstract and native Methods will return null when + * their location method is called. + * when it is applied to public, private, protected, and static methods + * returning primitive type values, and void methods. + * The test works as follows: + * The debugger program - nsk.jdi.Locatable.location.location001; + * the debuggee program - nsk.jdi.Locatable.location.location001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Locatable.location.location001 + * nsk.jdi.Locatable.location.location001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Locatable.location.location001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001a.java new file mode 100644 index 00000000000..24fb704d5b2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Locatable.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the location001 JDI test. + */ + +public class location001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> location001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> location001a: " + message); + } + + //====================================================== test program + + static location001aTestClass obj = new location001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Locatable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Locatable.location()
    + * complies with its spec when a tested method is an abstract.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of TestClass
    + * which contains an instance of class ClassForCheck
    + * implementing, directly and indirectly, two abstract
    + * methods from its super-class and super-interface,
    + * a debugger invokes the method Locatable.location()
    + * with these two abstract methods as arguments and
    + * checks up returned values.
    + *
    + */ + +public class location002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Locatable/location/location002 ", + sHeader2 = "--> location002: ", + sHeader3 = "##> location002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new location002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Locatable.location.location002a"; + + String mName = "nsk.jdi.Locatable.location"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("location002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = null; + List methods = null; + Method m = null; + Location mLocation = null; + + String testedMethod1 = "abstractMethod1"; + String testedMethod2 = "abstractMethod2"; + + listOfDebuggeeClasses = vm.classesByName(mName + ".location002aInterfaceForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(testedMethod1); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation != null) { + log3("ERROR: mLocation != null for an abstract method in location002aInterfaceForCheck"); + testExitCode = FAILED; + } + + listOfDebuggeeClasses = vm.classesByName(mName + ".location002aClassForCheck2"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(testedMethod2); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation != null) { + log3("ERROR: mLocation != null for an abstract method in location002aClassForCheck2"); + testExitCode = FAILED; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002/TestDescription.java new file mode 100644 index 00000000000..cfe0c928c94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Locatable/location/location002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Locatable. + * The test checks up that a result of the method + * com.sun.jdi.Locatable.location() + * complies with its spec: + * public Location location() + * Returns the Location of this mirror, + * if there is executable Java language code associated with it. + * Returns: the Location of this mirror, or + * null if there is no executable code associated with it. + * For example, abstract and native Methods will return null when + * their location method is called. + * in case of the method Locatable.location() is invoked on an abstract method. + * The test works as follows: + * The debugger program - nsk.jdi.Locatable.location.location002; + * the debuggee program - nsk.jdi.Locatable.location.location002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Locatable.location.location002 + * nsk.jdi.Locatable.location.location002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Locatable.location.location002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002a.java new file mode 100644 index 00000000000..bddfb78bc92 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location002a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Locatable.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the location002 JDI test. + */ + +public class location002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> location002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> location002a: " + message); + } + + //====================================================== test program + + static location002aTestClass obj = new location002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Locatable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Locatable.location()
    + * complies with its spec when a tested method
    + * is one of ReferenceTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of the following
    + * class type with methods returning ReferenceType objects:
    + *
    + * class TestClass {
    + * .
    + * .
    + * public ClassForCheck[] arraymethod () {
    + * return cfc;
    + * }
    + * public ClassForCheck classmethod () {
    + * return classFC;
    + * }
    + * public InterfaceForCheck ifacemethod () {
    + * return iface;
    + * }
    + * }
    + * a debugger checks up that for all of the above + * methods returning ReferenceType objects,
    + * the invocation of the method Locatable.location()
    + * returns non-null value.
    + *
    + */ + +public class location003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Locatable/location/location003 ", + sHeader2 = "--> location003: ", + sHeader3 = "##> location003: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new location003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Locatable.location.location003a"; + + String mName = "nsk.jdi.Locatable.location"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("location003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".location003aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + Location mLocation = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // ArrayType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("arraymethod"); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for 'arraymethod'"); + testExitCode = FAILED; + } + break; + + case 1: // ClassType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("classmethod"); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for 'classmethod'"); + testExitCode = FAILED; + } + break; + + case 2: // InterfaceType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ifacemethod"); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for 'ifacemethod'"); + testExitCode = FAILED; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003/TestDescription.java new file mode 100644 index 00000000000..3ad08939522 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Locatable/location/location003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Locatable. + * The test checks up that a result of the method + * com.sun.jdi.Locatable.location() + * complies with its spec: + * public Location location() + * Returns the Location of this mirror, + * if there is executable Java language code associated with it. + * Returns: the Location of this mirror, or + * null if there is no executable code associated with it. + * For example, abstract and native Methods will return null when + * their location method is called. + * when it is applied to methods returning ReferenceType objects. + * The test works as follows: + * The debugger program - nsk.jdi.Locatable.location.location003; + * the debuggee program - nsk.jdi.Locatable.location.location003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Locatable.location.location003 + * nsk.jdi.Locatable.location.location003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Locatable.location.location003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003a.java new file mode 100644 index 00000000000..92e6573baec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location003a.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Locatable.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the location003 JDI test. + */ + +public class location003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> location003a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> location003a: " + message); + } + + //====================================================== test program + + static location003aTestClass obj = new location003aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Locatable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Locatable.location()
    + * complies with its spec when applied to a static method.
    + *
    + * The cases for testing are as follows.
    + * 1) After getting a thread suspended but before to resume it,
    + * StackFrame.location() is invoked and its returned value
    + * must not be null.
    + * Since the thread is not resumed yet,
    + * InvalidStackFrameException must not be throw.
    + * 2) After resuming the thread, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class location004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Locatable/location/location004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new location004().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Locatable.location.location004a"; + + private String testedClassName = + "nsk.jdi.Locatable.location.Threadlocation004a"; + + String mName = "nsk.jdi.Locatable.location"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "Thread2"; + String breakpointMethod = "runt1"; + String bpLine1 = "breakpointLineNumber1"; + String breakpointMethod1 = "runt1"; + + BreakpointRequest breakpRequest1 = null; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + StackFrame stackFrame = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + + log2(" stackFrame = thread2.frame(0);"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + expresult = returnCode1; + break label1; + } + + + Location stackLocation = null; + + log2(" checking up: no InvalidStackFrameException when the thread2 is suspended"); + try { + log2(" before: stackLocation = stackFrame.location();"); + stackLocation = stackFrame.location(); + if (stackLocation == null) { + log3("ERROR: stackLocation == null"); + expresult = returnCode1; + } + } catch ( InvalidStackFrameException e ) { + log2("ERROR: InvalidStackFrameExceprtion"); + } + + log2(" resuming the thread2"); + eventSet.resume(); + + if (expresult == returnCode1) + break label1; + + log2(" checking up InvalidStackFrameException after resuming the thread2"); + try { + log2(" before: stackLocation = stackFrame.location();"); + stackLocation = stackFrame.location(); + expresult = returnCode1; + log3("ERROR: no InvalidStackFrameExceprtion"); + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameExceprtion"); + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004/TestDescription.java new file mode 100644 index 00000000000..1f966343f70 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Locatable/location/location004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Locatable. + * The test checks up that a result of the method + * com.sun.jdi.Locatable.location() + * complies with its spec: + * public Location location() + * Returns the Location of this mirror, + * if there is executable Java language code associated with it. + * Returns: the Location of this mirror, or + * null if there is no executable code associated with it. + * For example, abstract and native Methods will return null + * when their location method is called. + * when applied to a static method. + * The test works as follows: + * The debugger program - nsk.jdi.Locatable.location.location00; + * the debuggee program - nsk.jdi.Locatable.location.location00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * See: StackFrame.thisObject.thosobject002 + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Locatable.location.location004 + * nsk.jdi.Locatable.location.location004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Locatable.location.location004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004a.java new file mode 100644 index 00000000000..69907d62009 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location004a.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Locatable.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the location004 JDI test. + */ + +public class location004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Locatable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Locatable.location()
    + * complies with its spec when applied to an instance method.
    + *
    + * The cases for testing are as follows.
    + * 1) After getting a thread suspended but before to resume it,
    + * StackFrame.location() is invoked and its returned value
    + * must not be null.
    + * Since the thread is not resumed yet,
    + * InvalidStackFrameException must not be throw.
    + * 2) After resuming the thread, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class location005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Locatable/location/location005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new location005().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Locatable.location.location005a"; + + private String testedClassName = + "nsk.jdi.Locatable.location.Threadlocation005a"; + + String mName = "nsk.jdi.Locatable.location"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "Thread2"; + String breakpointMethod = "runt1"; + String bpLine1 = "breakpointLineNumber1"; + String breakpointMethod1 = "runt1"; + + BreakpointRequest breakpRequest1 = null; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + StackFrame stackFrame = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + + log2(" stackFrame = thread2.frame(0);"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + expresult = returnCode1; + break label1; + } + + + Location stackLocation = null; + + log2(" checking up: no InvalidStackFrameException when the thread2 is suspended"); + try { + log2(" before: stackLocation = stackFrame.location();"); + stackLocation = stackFrame.location(); + if (stackLocation == null) { + log3("ERROR: stackLocation == null"); + expresult = returnCode1; + } + } catch ( InvalidStackFrameException e ) { + log2("ERROR: InvalidStackFrameExceprtion"); + } + + log2(" resuming the thread2"); + eventSet.resume(); + + if (expresult == returnCode1) + break label1; + + log2(" checking up InvalidStackFrameException after resuming the thread2"); + try { + log2(" before: stackLocation = stackFrame.location();"); + stackLocation = stackFrame.location(); + expresult = returnCode1; + log3("ERROR: no InvalidStackFrameExceprtion"); + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameExceprtion"); + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005/TestDescription.java new file mode 100644 index 00000000000..adf235f6d14 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Locatable/location/location005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Locatable. + * The test checks up that a result of the method + * com.sun.jdi.Locatable.location() + * complies with its spec: + * public Location location() + * Returns the Location of this mirror, + * if there is executable Java language code associated with it. + * Returns: the Location of this mirror, or + * null if there is no executable code associated with it. + * For example, abstract and native Methods will return null + * when their location method is called. + * when applied to an instance method. + * The test works as follows: + * The debugger program - nsk.jdi.Locatable.location.location005; + * the debuggee program - nsk.jdi.Locatable.location.location005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * See StackFrame.thisObject.thisobject001 + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Locatable.location.location005 + * nsk.jdi.Locatable.location.location005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Locatable.location.location005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005a.java new file mode 100644 index 00000000000..6e89a20087c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location005a.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Locatable.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the location005 JDI test. + */ + +public class location005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Locatable.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Locatable.location()
    + * complies with its spec when a tested method is native.
    + *
    + * The case for testing is as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class TestClass {
    + * public native void nativeMethod ();
    + * }
    + * a debugger checks up that the invocation of
    + * the method Locatable.location() on the nativeMethod
    + * returns not the null.
    + *
    + */ + +public class location006 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Locatable/location/location006 ", + sHeader2 = "--> location006: ", + sHeader3 = "##> location006: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new location006().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Locatable.location.location006a"; + + String mName = "nsk.jdi.Locatable.location"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("location006a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".location006aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + Location mLocation = null; + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("nativeMethod"); + m = (Method) methods.get(0); + mLocation = m.location(); + + if (mLocation == null) { + log3("ERROR: mLocation == null for a native method"); + testExitCode = FAILED; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006/TestDescription.java new file mode 100644 index 00000000000..d440ff32f31 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Locatable/location/location006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Locatable. + * The test checks up that a result of the method + * com.sun.jdi.Locatable.location() + * complies with its spec: + * public Location location() + * Returns the Location of this mirror, + * if there is executable Java language code associated with it. + * Returns: the Location of this mirror, or + * null if there is no executable code associated with it. + * For example, abstract and native Methods will return null when + * their location method is called. + * when it is applied to a native method. + * The test works as follows: + * The debugger program - nsk.jdi.Locatable.location.location006; + * the debuggee program - nsk.jdi.Locatable.location.location006a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test is corrected to comply with latest Merlin specification + * which states that for a native method, a returned value is not the null. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Locatable.location.location006 + * nsk.jdi.Locatable.location.location006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Locatable.location.location006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006a.java new file mode 100644 index 00000000000..57b44e2d9e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Locatable/location/location006a.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Locatable.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the location006 JDI test. + */ + +public class location006a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> location006a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> location006a: " + message); + } + + //====================================================== test program + + static location006aTestClass obj = new location006aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LocatableEvent.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.LocatableEvent.thread()
    + * complies with its spec.
    + *
    + * The cases for testing include all Locatable events.
    + * The test checks that
    + * for each type of LocatableEvent received in a debugger,
    + * a value returned by the method invoked on
    + * a Event object corresponds to a thread
    + * which debuggee's counterpart event was generated in.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check Locatable events,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a number of threads, one for each check case
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * gets ThreadReferences mirroring all tested threads in the debuggee,
    + * sets up Requests within them to get Events to check up on,
    + * resumes the debuggee, waits for events, and upon getting them,
    + * compares ThreadReferences put into Requests to ones from Events;
    + * if any mismatch, the test FAILED.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class thread001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LocatableEvent/thread/thread001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new thread001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LocatableEvent.thread.thread001a"; + + private String testedClassName = + "nsk.jdi.LocatableEvent.thread.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String accWatchpointName = "var1"; + String modWatchpointName = "var2"; + String bpLineName = "breakpointLine"; + String bpMethodName = "method"; + String awFieldName = "awFieldName"; + String mwFieldName = "mwFieldName"; + String excName = "method"; + String menName = "method"; + String mexName = "method"; + + String namesArray = "threadNames"; + + String threadNames[] = { + "awThread" , + "mwThread" , + "bpThread" , + "excThread" , + "menThread" , + "mexThread" , + "stThread" + }; + + + EventRequest eRequests[] = new EventRequest[threadNames.length]; + int flags = 0; + + ThreadReference eventThreads[] = new ThreadReference[threadNames.length]; + + + List allThreads = vm.allThreads(); + + log2("......getting: ArrayReference namesRef = (ArrayReference) debuggeeClass.getValue(debuggeeClass.fieldByName(namesArray));"); + ArrayReference namesRef = (ArrayReference) + debuggeeClass.getValue(debuggeeClass.fieldByName(namesArray)); + log2(" namesRef.length() == " + namesRef.length()); + + log2("......getting and chcking up on debuggee threads' names"); + for (int n1 = 0; n1 < namesRef.length(); n1++) { + + log2(" String name = ((StringReference) namesRef.getValue(n1)).value();"); + String name = ((StringReference) namesRef.getValue(n1)).value(); + + label0: { + for (int n2 = 0; n2 < threadNames.length; n2++) { + + if (name.equals(threadNames[n2])) { + ListIterator li = allThreads.listIterator(); + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) { + eventThreads[n1] = thread; + break; + } + } + break label0; + } + } + testExitCode = FAILED; + log3("ERROR: no thread found in the debuggee : " + name); + } + } + if (testExitCode == FAILED) + break; + + + log2("......ReferenceType testClass = (ReferenceType) (vm.classesByName(testedClassName)).get(0);"); + ReferenceType testClass = (ReferenceType) (vm.classesByName(testedClassName)).get(0); + + log2("......setting up Requests"); + for ( int n3 = 0; n3 < namesRef.length(); n3++) { + switch (n3) { + case 0: + if (vm.canWatchFieldAccess()) { + String awName = ( (StringReference) testClass.getValue( + testClass.fieldByName(awFieldName))).value(); + eRequests[n3] = settingAccessWatchpoint(eventThreads[n3], + testClass, awName, threadNames[n3]); + eRequests[n3].enable(); + flags |= 1; + } + break; + + case 1: + if (vm.canWatchFieldModification() ) { + String mwName = ( (StringReference) testClass.getValue( + testClass.fieldByName(mwFieldName))).value(); + eRequests[n3] = settingModificationWatchpoint(eventThreads[n3], + testClass, mwName, threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<1; + } + break; + + case 2: + eRequests[n3] = settingBreakpoint(eventThreads[n3], testClass, + bpMethodName, bpLineName, threadNames[n3]); + eRequests[n3].setSuspendPolicy( EventRequest.SUSPEND_NONE); + eRequests[n3].enable(); + flags |= 1<<2; + break; + + case 3: + eRequests[n3] = settingException(eventThreads[n3], debuggeeClass, //testClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<3; + break; + + case 4: + eRequests[n3] = settingMethodEntry(eventThreads[n3], testClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<4; + break; + + case 5: + eRequests[n3] = settingMethodExit(eventThreads[n3], testClass, + threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<5; + break; + + case 6: + eRequests[n3] = settingStep(eventThreads[n3], threadNames[n3]); + eRequests[n3].enable(); + flags |= 1<<6; + break; + + default: + throw new JDITestRuntimeException("** default case while prepareing requests**"); + } + } + + log2(":::::::::vm.resume();"); + vm.resume(); + + Event event1 = null; + String threadName = null; + int flagsCopy = flags; + String eName = null; + + log2("......getting and checking up on Events"); + for (int n4 = 0; n4 < namesRef.length(); n4++) { + int flag; + int index; + getEventSet(); + event1 = eventIterator.nextEvent(); + + if (event1 instanceof AccessWatchpointEvent) { + eName = "AccessWatchpointEvent"; + index = 0; + } else if (event1 instanceof ModificationWatchpointEvent ) { + eName = "ModificationWatchpointEvent"; + index = 1; + } else if (event1 instanceof BreakpointEvent ) { + eName = "BreakpointEvent"; + index = 2; + } else if (event1 instanceof ExceptionEvent ) { + eName = "ExceptionEvent"; + index = 3; + } else if (event1 instanceof MethodEntryEvent ) { + eName = "MethodEntryEvent"; + index = 4; + } else if (event1 instanceof MethodExitEvent ) { + eName = "MethodExitEvent"; + index = 5; + } else if (event1 instanceof StepEvent ) { + eName = "StepEvent"; + index = 6; + } else { + log3("ERROR: else clause in detecting type of event1"); + testExitCode = FAILED; + throw new JDITestRuntimeException("** unexpected event **"); + } + log2("--------> got: " + eName); + + ThreadReference threadRef = ((LocatableEvent) event1).thread(); + + label0: { + for (int n5 = 0; n5 < namesRef.length(); n5++) { + if (threadRef.equals(eventThreads[n5])) { + eventThreads[n5] = null; + threadName = threadNames[index]; + break label0; + } + } + testExitCode = FAILED; + log3("ERROR: event's thread is not equal to any tested"); + log3(" thread's name == " + threadRef.name()); + } + + flag = 1 << index; + if ((flagsCopy & flag) == 0) { + log3("ERROR: event duplication: " + eName); + testExitCode = FAILED; + } else { + flagsCopy ^= flag; + flags |= flag; + } + } + + breakpointForCommunication(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest settingAccessWatchpoint ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + String property) + throws JDITestRuntimeException { + + log2("......setting up AccessWatchpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; fieldName: " + fieldName); + + AccessWatchpointRequest awRequest = null; + try { + Field field = testedClass.fieldByName(fieldName); + awRequest = eventRManager.createAccessWatchpointRequest(field); + awRequest.putProperty("number", property); + awRequest.addThreadFilter(thread); + awRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpoint() : " + e); + log3(" AN ACCESSWATCHPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up an AccessWatchpoint **"); + } + + log2(" an AccessWatchpoint has been set up"); + return awRequest; + } + + private ModificationWatchpointRequest settingModificationWatchpoint ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + String property) + throws JDITestRuntimeException { + + log2("......setting up ModificationWatchpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; fieldName: " + fieldName); + + ModificationWatchpointRequest mwRequest = null; + try { + Field field = testedClass.fieldByName(fieldName); + mwRequest = eventRManager.createModificationWatchpointRequest(field); + mwRequest.putProperty("number", property); + mwRequest.addThreadFilter(thread); + mwRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpoint() : " + e); + log3(" AN ModificationWATCHPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up an AccessWatchpoint **"); + } + + log2(" a ModificationWatchpoint has been set up"); + return mwRequest; + } + + private MethodEntryRequest settingMethodEntry ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up MethodEntry:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + MethodEntryRequest menRequest = null; + try { + menRequest = eventRManager.createMethodEntryRequest(); + menRequest.putProperty("number", property); + menRequest.addThreadFilter(thread); + menRequest.addClassFilter(testedClass); + menRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntry() : " + e); + log3(" A MethodEntry HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a MethodEntry **"); + } + + log2(" a MethodEntry has been set up"); + return menRequest; + } + + private MethodExitRequest settingMethodExit ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up MethodExit:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + MethodExitRequest mexRequest = null; + try { + mexRequest = eventRManager.createMethodExitRequest(); + mexRequest.putProperty("number", property); + mexRequest.addThreadFilter(thread); + mexRequest.addClassFilter(testedClass); + mexRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExit() : " + e); + log3(" A MethodExit HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a MethodExit **"); + } + + log2(" a MethodExit has been set up"); + return mexRequest; + } + + private StepRequest settingStep ( ThreadReference thread, String property) + throws JDITestRuntimeException { + + log2("......setting up Step:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest stRequest = null; + try { + stRequest = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); + stRequest.putProperty("number", property); + stRequest.addCountFilter(1); + stRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStep() : " + e); + log3(" A Step HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a Step **"); + } + + log2(" a Step has been set up"); + return stRequest; + } + + + private ExceptionRequest settingException ( ThreadReference thread, + ReferenceType testedClass, + String property) + throws JDITestRuntimeException { + + log2("......setting up Exception:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; property: " + property); + + ExceptionRequest excRequest = null; + try { + excRequest = eventRManager.createExceptionRequest(null, true, true); + excRequest.putProperty("number", property); + excRequest.addThreadFilter(thread); + excRequest.addClassFilter(testedClass); + excRequest.setSuspendPolicy( EventRequest.SUSPEND_NONE); + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingException() : " + e); + log3(" A Exception HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up a Exception **"); + } + + log2(" a Exception has been set up"); + return excRequest; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001/TestDescription.java new file mode 100644 index 00000000000..adef1bd98b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LocatableEvent/thread/thread001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LocatableEvent. + * The test checks up that a result of the method + * com.sun.jdi.LocatableEvent.thread() + * complies with its spec: + * public ThreadReference thread() + * Returns the thread in which this event has occurred. + * Returns: a ThreadReference which mirrors the event's thread in the target VM. + * The cases for testing include all Locatable events. + * The test checks that + * for each type of LocatableEvent received in a debugger, + * a value returned by the method invoked on a Event object + * corresponds to a thread which debuggee's counterpart event was generated in. + * The test works as follows: + * The debugger program - nsk.jdi.LocatableEvent.thread.thread001; + * the debuggee program - nsk.jdi.LocatableEvent.thread.thread001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Fixed due to the bug 4528893. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LocatableEvent.thread.thread001 + * nsk.jdi.LocatableEvent.thread.thread001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LocatableEvent.thread.thread001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001a.java new file mode 100644 index 00000000000..c32450a147c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001a.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LocatableEvent.thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the thread001 JDI test. + */ + +public class thread001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass tcObject = new TestClass(); + + static String threadNames[] = { + "awThread", "mwThread", "bpThread", "excThread", + "menThread", "mexThread", "stThread" + }; + + static int threadsN = threadNames.length; + + static Thread threads[] = new Thread[threadsN]; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + for (int n1 = 0; n1 < threadsN; n1++) { + if (n1 < threadsN-1) + threads[n1] = new Thread1thread001a(threadNames[n1]); + else + threads[n1] = new Thread2thread001a(threadNames[n1]); + } + log1(" threads has been created"); + + synchronized (lockingObject2) { + log1(" loop: threadStart(threads[n2])"); + for (int n2 = 0; n2 < threadsN; n2++) + if ( threadStart(threads[n2]) != PASSED ) + break label0; + + log1(" methodForCommunication();"); + methodForCommunication(); + } + + for (int n2 = 0; n2 < threadsN; n2++) { + synchronized (locks[n2]) { + log1(" synchronized (locks[n2]) : n2 == " + n2); + } + } + + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { +// log3("threadStart before: waitnotifyObj.wait();"); + waitnotifyObj.wait(); +// log3("threadStart after: waitnotifyObj.wait();"); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + public static void nullMethod() { + throw new NullPointerException("test"); + } + + static Object lockingObject2 = new Object(); + static Object locks[] = new Object[threadsN]; + + static volatile int n = 0; + + static class Thread1thread001a extends Thread { + + int threadIndex; + + public Thread1thread001a(String threadName) { + super(threadName); + threadIndex = n; + locks[threadIndex] = new Object(); + n++; + } + + public void run() { + log3(" 'run': enter :: threadIndex == " + threadIndex); + + synchronized (locks[threadIndex]) { + log3("enter synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log3(" 'run': exit synchronized (waitnotifyObj)"); + + synchronized (lockingObject2) { + TestClass.method(); + } + log3("exit synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + } + return; + } + + } + + static class Thread2thread001a extends Thread { + + int threadIndex; + + public Thread2thread001a(String threadName) { + super(threadName); + threadIndex = n; + locks[threadIndex] = new Object(); + n++; + } + + public void run() { + log3(" 'run': enter :: threadIndex == " + threadIndex); + + synchronized (locks[threadIndex]) { + log3("enter synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + m1(); + log3("exit synchronized (locks[threadIndex]) :: threadIndex == " + threadIndex); + } + return; + } + + private void m1() { + synchronized (lockingObject2) { + log3(" 'm1': enter"); + + log3(" 'm1': exit"); + } + } + + } + + + public static void log3(String str) { + log1(Thread.currentThread().getName() + " : " + str); + } + +} + +class TestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 += 1; + var3 += 1; + var2 = var3; + try { + thread001a.nullMethod(); + } catch ( NullPointerException e ) { + thread001a.log3(" NullPointerException : " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001.java new file mode 100644 index 00000000000..45496e2d35e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.codeIndex; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.codeIndex()
    + * complies with its spec.
    + *
    + * The test checks up that a List of allLineLocations in
    + * a ReferenceType object mirroring debuggee's class TestClass
    + * containing no native methods, contains only Location objects
    + * whose codeIndexes are >= 0.
    + */ + +public class codeindex001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/codeIndex/codeindex001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new codeindex001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.codeIndex.codeindex001a"; + + String mName = "nsk.jdi.Location.codeIndex"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = ((ReferenceType) classes.get(0)).allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + ListIterator li = lineLocations.listIterator(); + + log2("......checking up codeIndexes in all Locations"); + log2(" neither -1 nor <0 are expected"); + for (int ifor = 0; li.hasNext(); ifor++) { + Location loc = (Location) li.next(); + long codei = loc.codeIndex(); + if (codei == -1) { + log3("ERROR: codei == -1 ; index in List : " + ifor); + testExitCode = FAILED; + } else if (codei < 0) { + log3("ERROR: codei <0 : " + codei + "; index in List : " + ifor); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001/TestDescription.java new file mode 100644 index 00000000000..83f0a461dc8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/codeIndex/codeindex001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.codeIndex() + * complies with its spec: + * public long codeIndex() + * Gets the code position within this location's method. + * Returns: the long representing the position within the method or -1 + * if location is within a native method. + * when no native methods are tested. + * The test works as follows: + * The debugger program - nsk.jdi.Location.codeIndex.codeindex 00; + * the debuggee program - nsk.jdi.Location.codeIndex.codeindex 00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.codeIndex.codeindex001 + * nsk.jdi.Location.codeIndex.codeindex001a + * + * @comment make sure codeindex001a is compiled with full debug info + * @clean nsk.jdi.Location.codeIndex.codeindex001a + * @compile -g:lines,source,vars ../codeindex001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.codeIndex.codeindex001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001a.java new file mode 100644 index 00000000000..7c71b25e2af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/codeIndex/codeindex001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.codeIndex; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the codeindex001 JDI test. + */ + +public class codeindex001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.declaringType()
    + * complie with its specification.
    + *
    + * The case for testing includes two types in a debuggee,
    + * an Interface type and a Class type implementing it.
    + * The Class contains a method, the Interface static initialize.
    + * A debugger gets two ReferenceType objects,
    + * a testedclass and a testediface mirroring the types,
    + * and for each tested type, performs the following:
    + * - gets a List returned by the methods testedclass.allLineLocations();
    + * - perform a loop to check up that for each Location in the List,
    + * call to the method Location.declaringType() returns ReferenceType
    + * object equal to one got at the beginning of the test.
    + */ + +public class declaringtype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/declaringType/declaringtype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new declaringtype001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.declaringType.declaringtype001a"; + + String mName = "nsk.jdi.Location.declaringType"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......testing Class ReferenceType"); + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" ReferenceType testedclass = (ReferenceType) classes.get(0)"); + ReferenceType testedclass = (ReferenceType) classes.get(0); + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = testedclass.allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + ListIterator li = lineLocations.listIterator(); + + log2("......checking equality: location.declareingType().equals(testedclass)"); + for (int ifor = 0; li.hasNext(); ifor++) { + Location loc = (Location) li.next(); + + if (!loc.declaringType().equals(testedclass)) { + log3("ERROR: !loc.declareingType().equals(testedclass); index in List : " + ifor); + testExitCode = FAILED; + } + } + + + log2("......testing Interface ReferenceType"); + + String testedifaceName = mName + ".TestIface"; + + log2(" getting: List ifaces = vm.classesByName(testedifaceName); expected size == 1"); + List ifaces = vm.classesByName(testedifaceName); + size = ifaces.size(); + if (size != 1) { + log3("ERROR: ifaces.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" ReferenceType testediface = (ReferenceType) classes.get(0)"); + ReferenceType testediface = (ReferenceType) ifaces.get(0); + + log2(" getting: TestIface.allLineLocations(); no AbsentInformationException expected"); + try { + lineLocations = testediface.allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + li = lineLocations.listIterator(); + + log2("......checking equality: location.declareingType().equals(testediface)"); + for (int ifor = 0; li.hasNext(); ifor++) { + Location loc = (Location) li.next(); + + if (!loc.declaringType().equals(testediface)) { + log3("ERROR: !loc.declareingType().equals(testediface); index in List : " + ifor); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001/TestDescription.java new file mode 100644 index 00000000000..33e2c1005f9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/declaringType/declaringtype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.declaringType() + * complies with its spec: + * public ReferenceType declaringType() + * Gets the type to which this Location belongs. + * Normally the declaring type is a ClassType, but executable locations + * also may exist within the static initializer of an InterfaceType. + * Returns: the ReferenceType containing this Location. + * The test works as follows: + * The debugger program - nsk.jdi.Location.declaringType.declaringtype001 + * the debuggee program - nsk.jdi.Location.declaringType.declaringtype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.declaringType.declaringtype001 + * nsk.jdi.Location.declaringType.declaringtype001a + * + * @comment make sure declaringtype001a is compiled with full debug info + * @clean nsk.jdi.Location.declaringType.declaringtype001a + * @compile -g:lines,source,vars ../declaringtype001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.declaringType.declaringtype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001a.java new file mode 100644 index 00000000000..80c4e099637 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/declaringType/declaringtype001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the declaringtype001 JDI test. + */ + +public class declaringtype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.equals()
    + * complie with its specification.
    + *
    + * The case for testing includes a Class type in a debuggee.
    + * A debugger gets a ReferenceType objects, mirroring tested Class,
    + * then gets a List returned by the methods
    + * testedclass.allLineLocations() and performs a loop in which
    + * for each Location in the List, it checks up that :
    + * - two invocations of the method hashCode() on the same Location
    + * return Objects equal to each other;
    + * - two invocations on different Locations return Objects
    + * not equal to each other.
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/equals/equals001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.equals.equals001a"; + + String mName = "nsk.jdi.Location.equals"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = ((ReferenceType) classes.get(0)).allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + + log2("......checking up Locations equality"); + + ListIterator li = lineLocations.listIterator(); + Location loc1 = (Location) li.next(); + + for (int ifor = 0; li.hasNext(); ifor++) { + + Location loc2 = (Location) lineLocations.get(ifor); + Location loc3 = (Location) li.next(); + + if (!loc2.equals(loc1)) { + log3("ERROR: !loc2.equals(loc1); ifor : " + ifor); + testExitCode = FAILED; + } + if (loc2.equals(loc3)) { + log3("ERROR: loc2.equals(loc3); ifor : " + ifor); + testExitCode = FAILED; + } + loc1 = loc3; + + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..9e2bffb24be --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this Location for equality. + * Returns: true if the Object is a Location and if + * it refers to the same point in the same VM as this Location. + * Overrides: equals in class java.lang.Object + * when only one VM runs a debugged program. + * The test works as follows: + * The debugger program - nsk.jdi.Location.equals.equals001; + * the debuggee program - nsk.jdi.Location.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.equals.equals001 + * nsk.jdi.Location.equals.equals001a + * + * @comment make sure equals001a is compiled with full debug info + * @clean nsk.jdi.Location.equals.equals001a + * @compile -g:lines,source,vars ../equals001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001a.java new file mode 100644 index 00000000000..e342a38ccfc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/equals/equals001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001 JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.hashCode()
    + * complie with its specification.
    + *
    + * The case for testing includes a Class type in a debuggee.
    + * A debugger gets a ReferenceType objects, mirroring tested Class,
    + * then gets a List returned by the methods
    + * testedclass.allLineLocations() and performs a loop in which
    + * for each Location in the List, it checks up that :
    + * - two invocations of the method hashCode() on the same Location
    + * return ints equal to each other;
    + * - two invocations on different Locations return ints
    + * not equal to each other.
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/hashCode/hashcode001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.hashCode.hashcode001a"; + + String mName = "nsk.jdi.Location.hashCode"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = ((ReferenceType) classes.get(0)).allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + log2("......checking up Location's hashCodes"); + + ListIterator li = lineLocations.listIterator(); + Location loc1 = (Location) li.next(); + + for (int ifor = 0; li.hasNext(); ifor++) { + + Location loc2 = (Location) lineLocations.get(ifor); + Location loc3 = (Location) li.next(); + + int hcode1 = loc1.hashCode(); + int hcode2 = loc2.hashCode(); + int hcode3 = loc3.hashCode(); + + if (hcode1 != hcode2) { + log3("ERROR: loc1.hashCode() != loc2.hashCode() ifor : " + ifor); + testExitCode = FAILED; + } + loc1 = loc3; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..1560c1c1110 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this Location. + * Returns: the integer hash code + * Overrides: hashCode in class java.lang.Object + * The test works as follows: + * The debugger program - nsk.jdi.Location.hashCode.hashcode001; + * the debuggee program - nsk.jdi.Location.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.hashCode.hashcode001 + * nsk.jdi.Location.hashCode.hashcode001a + * + * @comment make sure hashcode001a is compiled with full debug info + * @clean nsk.jdi.Location.hashCode.hashcode001a + * @compile -g:lines,source,vars ../hashcode001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001a.java new file mode 100644 index 00000000000..8ed785a7066 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/hashCode/hashcode001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001 JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.lineNumber()
    + * complies with its spec.
    + * Case for testing includes only a List of locations returned
    + * by the method ReferenceType.allLineLocations(), hence
    + * no -1 returned by Location.lineNumber() is expected.
    + */ + +public class linenumber001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/lineNumber/linenumber001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new linenumber001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.lineNumber.linenumber001a"; + + String mName = "nsk.jdi.Location.lineNumber"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String className = mName + ".TestClass"; + + log2(" getting: List of loaded 'TestClass' classes; only one element is expected"); + List listOfLoadedClasses = vm.classesByName(className); + + int size = listOfLoadedClasses.size(); + if (size != 1) { + log3("ERROR: listOfLoadedClasses.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + ReferenceType testedClass = (ReferenceType) listOfLoadedClasses.get(0); + + log2(" getting: List of TestClass lineLocations; AbsentInformationException is not expected"); + List lineLocations = null; + try { + lineLocations = testedClass.allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: min and max line numbers of TestClass"); + int minLine; + int maxLine; + try { + minLine = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName("minLine")) ).value(); + maxLine = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName("maxLine")) ).value(); + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + break; + } + + log2(" loop for checking up lineNumbers in each element in lineLocations"); + ListIterator li = lineLocations.listIterator(); + + for (int ifor = 0; li.hasNext(); ifor++) { + int lineNumber = ((Location) li.next()).lineNumber(); + if ( lineNumber < minLine || lineNumber > maxLine ) { + log3("ERROR: lineNumber is out of range minLine-maxLine: "); + log2(" minLine == " + minLine + "; lineNumber == " + lineNumber + "; maxLine == " + maxLine); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001/TestDescription.java new file mode 100644 index 00000000000..e9558102635 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/lineNumber/linenumber001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.lineNumber() + * complies with its spec: + * public int lineNumber() + * The line number of this Location. + * The line number is relative to the source specified by sourceName(). + * Returns: an int specifying the line in the source, + * return -1 if the information is not available. + * when a tested method is not native. + * The test works as follows: + * The debugger program - nsk.jdi.Location.lineNumber.linenumber001; + * the debuggee program - nsk.jdi.Location.lineNumber.linenumber001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 1) + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * 2) The spec in Merlin: + * public int lineNumber() + * The line number of this Location. + * The line number is relative to the source specified by sourceName(). + * Returns: an int specifying the line in the source, + * returns -1 if the information is not available; + * specifically, always returns -1 for native methods. + * In my opinion the Merlin spec doesn't change the semantic in the Kectrel spec + * but only clarifies one particular case. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.lineNumber.linenumber001 + * nsk.jdi.Location.lineNumber.linenumber001a + * + * @comment make sure linenumber001a is compiled with full debug info + * @clean nsk.jdi.Location.lineNumber.linenumber001a + * @compile -g:lines,source,vars ../linenumber001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.lineNumber.linenumber001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001a.java new file mode 100644 index 00000000000..b0edb5510a6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber/linenumber001a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.lineNumber; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This class is used as debuggee application for the linenumber001 JDI test. + */ + +public class linenumber001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * 9 --> 1000 + * ... ... + * 16 --> 1007 + * sde_testMethod1 + * 20 --> 1100 + * ... ... + * 27 --> 1107 + * sde_testMethod2 + * 31 --> 1200 + * ... ... + * 38 --> 1207 + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that all locations obtained for one the 'TestStratumXXX' returns -1 as line number for all others 'TestStratumXXX'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.lineNumber_s.lineNumber_s002.lineNumber_s002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.lineNumber_s.lineNumber_s002.lineNumber_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + */ + +package nsk.jdi.Location.lineNumber_s.lineNumber_s002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class lineNumber_s002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new lineNumber_s002().runIt(argv, out); + } + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type4(className); + /* + * Method 'prepareDefaultPatchedClassFile_Type4' creates class file with + * following line mapping: "Java" "TestStratum1" "TestStratum2" + * "TestStratum3" + * + * + * 9 --> 1000 + * ... + * ... + * 16 --> 1007 + * + * sde_testMethod1 + * 20 --> 1100 + * ... + * ... + * 27 --> 1107 + * + * sde_testMethod2 + * 31 --> 1200 + * ... + * ... + * 38 --> 1207 + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName1 : testStratumData.keySet()) { + log.display("Check locations for stratum: " + stratumName1); + + List allLocations; + + try { + allLocations = referenceType.allLineLocations(stratumName1, null); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + + continue; + } + + for (Location location : allLocations) { + // check that for all stratums other than stratumName1 + // Location.lineNumber() returns -1 + for (String stratumName2 : testStratumData.keySet()) { + if (!stratumName2.equals(stratumName1)) { + log.display("Try get line number for stratum: " + stratumName2); + + int lineNumber = location.lineNumber(stratumName2); + + if (lineNumber != -1) { + setSuccess(false); + log.complain("Location.lineNumber returns unexpected value: " + lineNumber + + ", expected is " + -1); + } + } + } + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001.java new file mode 100644 index 00000000000..ede865ba146 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.lineNumber_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.lineNumber(String stratum)
    + * complies with its spec.
    + * Case for testing includes only a List of locations returned
    + * by the method ReferenceType.allLineLocations() applied to
    + * a class with the "Java" stratum which is the default one.
    + */ + +public class linenumber_s001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/lineNumber_s/linenumber_s001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new linenumber_s001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.lineNumber_s.linenumber_s001a"; + + String mName = "nsk.jdi.Location.lineNumber_s"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null;; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String className = mName + ".TestClass"; + + log2(" getting: List of loaded 'TestClass' classes; only one element is expected"); + List listOfLoadedClasses = vm.classesByName(className); + + int size = listOfLoadedClasses.size(); + if (size != 1) { + log3("ERROR: listOfLoadedClasses.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + ReferenceType testedClass = (ReferenceType) listOfLoadedClasses.get(0); + + log2(" getting: List of TestClass lineLocations; AbsentInformationException is not expected"); + List lineLocations = null; + try { + lineLocations = testedClass.allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: min and max line numbers of TestClass"); + int minLine; + int maxLine; + try { + minLine = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName("minLine")) ).value(); + maxLine = ( (IntegerValue) testedClass.getValue(testedClass.fieldByName("maxLine")) ).value(); + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + break; + } + + String defaultStratum = vm.getDefaultStratum(); + + log2(" loop for checking up lineNumbers in each element in lineLocations"); + ListIterator li = lineLocations.listIterator(); + + for (int ifor = 0; li.hasNext(); ifor++) { + int lineNumber = ((Location) li.next()).lineNumber(defaultStratum); + if ( lineNumber < minLine || lineNumber > maxLine ) { + log3("ERROR: lineNumber is out of range minLine-maxLine: "); + log2(" minLine == " + minLine + "; lineNumber == " + lineNumber + "; maxLine == " + maxLine); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001/TestDescription.java new file mode 100644 index 00000000000..a7671921a72 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/lineNumber_s/linenumber_s001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.lineNumber(String) + * complies with its spec: + * Public int lineNumber(String stratum) + * The line number of this Location. + * The line number is relative to the source specified by sourceName(stratum). + * Returned line number is for the specified stratum + * (see the class comment for a description of strata). + * Parameters: stratum - The stratum to retrieve information from or + * null for the declaring type's default stratum. + * Returns: an int specifying the line in the source, + * returns -1 if the information is not available; + * specifically, always returns -1 for native methods. + * The test works as follows: + * The debugger program - nsk.jdi.Location.lineNumber_s.linenumber_s001; + * the debuggee program - nsk.jdi.Location.lineNumber_s.linenumber_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.lineNumber_s.linenumber_s001 + * nsk.jdi.Location.lineNumber_s.linenumber_s001a + * + * @comment make sure linenumber_s001a is compiled with full debug info + * @clean nsk.jdi.Location.lineNumber_s.linenumber_s001a + * @compile -g:lines,source,vars ../linenumber_s001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.lineNumber_s.linenumber_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001a.java new file mode 100644 index 00000000000..65203fcc6e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/lineNumber_s/linenumber_s001a.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.lineNumber_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This class is used as debuggee application for the linenumber_s001 JDI test. + */ +public class linenumber_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } +/* + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } +*/ + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.method()
    + * complies with its spec.
    + *
    + * The test checks up that method's returned value is Method
    + * for both method and initializer in debuggee's class object.
    + *
    + */ + +public class method001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/method/method001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new method001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.method.method001a"; + + String mName = "nsk.jdi.Location.method"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("method001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = ((ReferenceType) classes.get(0)).allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + int flag = 0; + + ListIterator li = lineLocations.listIterator(); + + log2("......checking up methods in all Locations"); + log2(" expected methods: Constructor, StaticInitializer, user defined"); + log2(" neither abstract no native expected"); + for (int ifor = 0; li.hasNext(); ifor++) { + Location loc = (Location) li.next(); + Method m = loc.method(); + + if (m.isConstructor()) + flag |= 1; + else if (m.isStaticInitializer()) + flag |= 2; + if (m.isNative()) + flag |= 8; + else if (m.isAbstract()) + flag |= 16; + else + flag |= 4; + + } + if ( (flag & 1) == 0) { + log3("ERROR: no Constructor found"); + testExitCode = FAILED; + } else if ( (flag & 2) == 0) { + log3("ERROR: no StaticInitializer found"); + testExitCode = FAILED; + } else if ( (flag & 4) == 0) { + log3("ERROR: no user defined method found"); + testExitCode = FAILED; + } else if ( (flag & 8) != 0) { + log3("ERROR: native method found"); + testExitCode = FAILED; + } else if ( (flag & 16) != 0) { + log3("ERROR: abstract method found"); + testExitCode = FAILED; + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001/TestDescription.java new file mode 100644 index 00000000000..44d69a7bef5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/method/method001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.method() + * complies with its spec: + * public Method method() + * Gets the method, if any, containing this Location. + * Returns: the Method if this location is in a method, otherwise null. + * when tested objects are a method and a initializer. + * The test works as follows: + * The debugger program - nsk.jdi.Location.method.method001; + * the debuggee program - nsk.jdi.Location.method.method001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.method.method001 + * nsk.jdi.Location.method.method001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.method.method001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001a.java new file mode 100644 index 00000000000..082bb82489f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/method/method001a.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.method; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the method001 JDI test. + */ + +public class method001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> method001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> method001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.sourceName()
    + * complie with its specification.
    + *
    + * The case for testing includes a Class type in a debuggee, and
    + * debuggee's sourcecode file with a predefined name.
    + * A debugger gets aReferenceType objects, mirroring tested Class and
    + * performs the following:
    + * - gets a List returned by the methods testedclass.allLineLocations();
    + * - perform a loop to check up that for each Location in the List,
    + * call to the method Location.sourceName() returns String equal to
    + * the predefined one.
    + */ + +public class sourcename001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/sourceName/sourcename001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new sourcename001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.sourceName.sourcename001a"; + + String mName = "nsk.jdi.Location.sourceName"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = ((ReferenceType) classes.get(0)).allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + ListIterator li = lineLocations.listIterator(); + + log2("......checking up sourceName strings in all Locations"); + log2(" only 'sourcename001a.java' is expected"); + + label0: + for (int ifor = 0; li.hasNext(); ifor++) { + Location loc = (Location) li.next(); + + try { + String str = loc.sourceName(); + if (!str.equals("sourcename001a.java")) { + log3("ERROR: !str.equals('sourcename001a.java') : " + str); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break label0; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001/TestDescription.java new file mode 100644 index 00000000000..6c042b13f5a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/sourceName/sourcename001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.sourceName() + * complies with its spec: + * public String sourceName() + * throws AbsentInformationException + * Gets an identifing name for the source corresponding to this location. + * Interpretation of this string is the responsibility of + * the source repository mechanism. + * In the reference implementation, the returned string is + * the unqualified name of the source file for this Location. + * Returns: a string specifying the source + * Throws: AbsentInformationException - + * if the source name is not known + * The test works as follows: + * The debugger program - nsk.jdi.Location.sourceName.sourcename001; + * the debuggee program - nsk.jdi.Location.sourceName.sourcename001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.sourceName.sourcename001 + * nsk.jdi.Location.sourceName.sourcename001a + * + * @comment make sure sourcename001a is compiled with full debug info + * @clean nsk.jdi.Location.sourceName.sourcename001a + * @compile -g:lines,source,vars ../sourcename001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.sourceName.sourcename001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001a.java new file mode 100644 index 00000000000..1c2c60d345a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName/sourcename001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.sourceName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the sourcename001 JDI test. + */ + +public class sourcename001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * 9 --> 1000, source1, path1 + * ... ... + * 16 --> 1007, source1, path1 + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * ... ... + * 27 --> 1107, source1, path1 + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * ... ... + * 38 --> 1207, source1, path1 + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that for all locations obtained for one the 'TestStratumXXX' method 'sourceName(String stratum)' throws AbsentInformationException + * when try to get source name for all others 'TestStratumXXX'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.sourceName_s.sourceName_s002.sourceName_s002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.sourceName_s.sourceName_s002.sourceName_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + */ + +package nsk.jdi.Location.sourceName_s.sourceName_s002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class sourceName_s002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new sourceName_s002().runIt(argv, out); + } + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type4(className); + /* + * Method 'prepareDefaultPatchedClassFile_Type4' creates class file with + * following line mapping: "Java" "TestStratum1" "TestStratum2" + * "TestStratum3" + * + * + * 9 --> 1000 + * ... + * ... + * 16 --> 1007 + * + * sde_testMethod1 + * 20 --> 1100 + * ... + * ... + * 27 --> 1107 + * + * sde_testMethod2 + * 31 --> 1200 + * ... + * ... + * 38 --> 1207 + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName1 : testStratumData.keySet()) { + log.display("Check locations for stratum: " + stratumName1); + + List allLocations; + + try { + allLocations = referenceType.allLineLocations(stratumName1, null); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + + continue; + } + + for (Location location : allLocations) { + // check that for all stratums other than stratumName1 + // Location.sourceName() throws AbsentInformationException + for (String stratumName2 : testStratumData.keySet()) { + if (!stratumName2.equals(stratumName1)) { + log.display("Try get source name for stratum: " + stratumName2); + + try { + location.sourceName(stratumName2); + setSuccess(false); + log.complain("Expected AbsentInformationException was not thrown"); + } catch (AbsentInformationException e) { + // expected exception + } + } + } + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001.java new file mode 100644 index 00000000000..0146c1608fd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.sourceName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.sourceName(String stratum)
    + * complies with its specification.
    + *
    + * The case for testing includes a Class type in a debuggee, and
    + * debuggee's sourcecode file with a predefined name.
    + * A debugger gets ReferenceType objects, mirroring tested Class and
    + * performs the following:
    + * - gets a List returned by the method testedClass.allLineLocations();
    + * - perform a loop to check up that for each Location in the List,
    + * the method Location.sourceName(defaultStratum)
    + * returns String equal to the predefined one.
    + */ + +public class sourcename_s001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/sourceName_s/sourcename_s001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new sourcename_s001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.sourceName_s.sourcename_s001a"; + + String mName = "nsk.jdi.Location.sourceName_s"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = ((ReferenceType) classes.get(0)).allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + String defaultStratum = vm.getDefaultStratum(); + + ListIterator li = lineLocations.listIterator(); + + log2("......checking up on sourceName strings in all Locations"); + log2(" only 'sourcename_s001a.java' is expected"); + + label0: + for (int ifor = 0; li.hasNext(); ifor++) { + Location loc = (Location) li.next(); + + try { + String str = loc.sourceName(defaultStratum); + if (!str.equals("sourcename_s001a.java")) { + log3("ERROR: !str.equals('sourcename_s001a.java') : " + str); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break label0; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001/TestDescription.java new file mode 100644 index 00000000000..047a091f253 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/sourceName_s/sourcename_s001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.sourceName(String) + * complies with its spec: + * public String sourceName(String stratum) + * throws AbsentInformationException + * Gets an identifing name for the source corresponding to this location. + * Interpretation of this string is the responsibility of the source + * repository mechanism. + * Returned name is for the specified stratum + * (see the class comment for a description of strata). + * The returned string is the unqualified name of the source file for + * this Location. For example, java.lang.Thread would return "Thread.java". + * Parameters: stratum - The stratum to retrieve information from or + * null for the declaring type's default stratum. + * Returns: a string specifying the source + * Throws: AbsentInformationException - + * if the source name is not known + * The test works as follows: + * The debugger program - nsk.jdi.Location.sourceName_s.sourcename_s001; + * the debuggee program - nsk.jdi.Location.sourceName_s.sourcename_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.sourceName_s.sourcename_s001 + * nsk.jdi.Location.sourceName_s.sourcename_s001a + * + * @comment make sure sourcename_s001a is compiled with full debug info + * @clean nsk.jdi.Location.sourceName_s.sourcename_s001a + * @compile -g:lines,source,vars ../sourcename_s001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.sourceName_s.sourcename_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001a.java new file mode 100644 index 00000000000..a4c543a2b21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourceName_s/sourcename_s001a.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.sourceName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the sourcename_s001 JDI test. + */ + +public class sourcename_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } +/* + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } +*/ + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.sourcePath()
    + * complies with its specification.
    + *
    + * The test checks that
    + * - invocation of the method doesn't throw
    + * an error or unspecified exception;
    + * - returned value is debuggee's
    + * "unqualified name of the source file for this Location".
    + *
    + */ + +public class sourcepath001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/sourcePath/sourcepath001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new sourcepath001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.sourcePath.sourcepath001a"; + + String mName = "nsk.jdi.Location.sourcePath"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = ((ReferenceType) classes.get(0)).allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + log2("...... getting : ListIterator li = lineLocations.listIterator();"); + ListIterator li = lineLocations.listIterator(); + + log2("...... getting : Location loc = (Location) li.next();"); + Location loc = (Location) li.next(); + + String sep = System.getProperty("file.separator"); + String debuggeeUnqualifiedSourcePath = "nsk" + sep + "jdi" +sep + "Location" + sep + + "sourcePath" + sep + "sourcepath001a.java"; + + log2("......getting: String str = loc.sourcePath()"); + try { + String str = loc.sourcePath(); + + log2("......compareing: loc.sourcePath() to debuggeeUnqualifiedSourcePath"); + if (!str.equals(debuggeeUnqualifiedSourcePath)) { + log3("ERROR: loc.sourcePath() != debuggeeUnqualifiedSourcePath"); + log2(" loc.sourcePath() == " + str); + log2(" debuggeeUnqualifiedSourcePath == " + debuggeeUnqualifiedSourcePath); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + } catch ( Throwable err ) { + log3("ERROR: Throwable : " + err); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001/TestDescription.java new file mode 100644 index 00000000000..24caea48a74 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/sourcePath/sourcepath001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.sourcePath() + * complies with its spec: + * public String sourcePath() + * throws AbsentInformationException + * Gets the path to the source corresponding to this location. + * This method is equivalent to sourcePath(vm.getDefaultStratum()) - see + * sourcePath(String) for more information. + * Returns: a string specifying the source + * Throws: AbsentInformationException - + * if the source name is not known + * The test checks that + * - invocation of the method doesn't throw an error or unspecified exception;
    + * - returned value is debuggee's + * "unqualified name of the source file for this Location". + * The test works as follows: + * The debugger program - nsk.jdi.Location.sourcePath.sourcepath001; + * the debuggee program - nsk.jdi.Location.sourcePath.sourcepath001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and performes the testing call. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.sourcePath.sourcepath001 + * nsk.jdi.Location.sourcePath.sourcepath001a + * + * @comment make sure sourcepath001a is compiled with full debug info + * @clean nsk.jdi.Location.sourcePath.sourcepath001a + * @compile -g:lines,source,vars ../sourcepath001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.sourcePath.sourcepath001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001a.java new file mode 100644 index 00000000000..6e8f209b719 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath/sourcepath001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.sourcePath; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the sourcepath001 JDI test. + */ + +public class sourcepath001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * 9 --> 1000, source1, path1 + * ... ... + * 16 --> 1007, source1, path1 + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * ... ... + * 27 --> 1107, source1, path1 + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * ... ... + * 38 --> 1207, source1, path1 + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that for all locations obtained for one the 'TestStratumXXX' method 'sourcePath(String stratum)' throws AbsentInformationException + * when try to get source path for all others 'TestStratumXXX'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.sourcePath_s.sourcePath_s002.sourcePath_s002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.sourcePath_s.sourcePath_s002.sourcePath_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + */ + +package nsk.jdi.Location.sourcePath_s.sourcePath_s002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class sourcePath_s002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new sourcePath_s002().runIt(argv, out); + } + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type4(className); + /* + * Method 'prepareDefaultPatchedClassFile_Type4' creates class file with + * following line mapping: "Java" "TestStratum1" "TestStratum2" + * "TestStratum3" + * + * + * 9 --> 1000 + * ... + * ... + * 16 --> 1007 + * + * sde_testMethod1 + * 20 --> 1100 + * ... + * ... + * 27 --> 1107 + * + * sde_testMethod2 + * 31 --> 1200 + * ... + * ... + * 38 --> 1207 + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName1 : testStratumData.keySet()) { + log.display("Check locations for stratum: " + stratumName1); + + List allLocations; + + try { + allLocations = referenceType.allLineLocations(stratumName1, null); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + + continue; + } + + for (Location location : allLocations) { + // check that for all stratums other than stratumName1 + // Location.sourcePath() throws AbsentInformationException + for (String stratumName2 : testStratumData.keySet()) { + if (!stratumName2.equals(stratumName1)) { + log.display("Try get source path for stratum: " + stratumName2); + + try { + location.sourcePath(stratumName2); + setSuccess(false); + log.complain("Expected AbsentInformationException was not thrown"); + } catch (AbsentInformationException e) { + // expected exception + } + } + } + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001.java new file mode 100644 index 00000000000..c118d88e325 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.sourcePath_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Location.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Location.sourcePath(String stratum)
    + * complies with its specification.
    + *
    + * The test checks that
    + * - invocation of the method doesn't throw
    + * an error or unspecified exception;
    + * - returned value is debuggee's
    + * "unqualified name of the source file for this Location".
    + *
    + */ + +public class sourcepath_s001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Location/sourcePath_s/sourcepath_s001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new sourcepath_s001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Location.sourcePath_s.sourcepath_s001a"; + + String mName = "nsk.jdi.Location.sourcePath_s"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedclassName = mName + ".TestClass"; + + log2(" getting: List classes = vm.classesByName(testedclassName); expected size == 1"); + List classes = vm.classesByName(testedclassName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting: TestClass.allLineLocations(); no AbsentInformationException expected"); + List lineLocations = null; + try { + lineLocations = ((ReferenceType) classes.get(0)).allLineLocations(); + } catch ( AbsentInformationException e) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + break; + } + size = lineLocations.size(); + if (size == 0) { + log3("ERROR: lineLocations.size() == 0"); + testExitCode = FAILED; + break; + } + + log2("...... getting : String defaultStratum = vm.getDefaultStratum();"); + String defaultStratum = vm.getDefaultStratum(); + + log2("...... getting : ListIterator li = lineLocations.listIterator();"); + ListIterator li = lineLocations.listIterator(); + + log2("...... getting : Location loc = (Location) li.next();"); + Location loc = (Location) li.next(); + + String sep = System.getProperty("file.separator"); + String debuggeeUnqualifiedSourcePath = "nsk" + sep + "jdi" +sep + "Location" + sep + + "sourcePath_s" + sep + "sourcepath_s001a.java"; + + log2("......getting: String str = loc.sourcePath(defaultStratum)"); + try { + String str = loc.sourcePath(defaultStratum); + + log2("......compareing: loc.sourcePath(defaultStratum) to debuggeeUnqualifiedSourcePath"); + if (!str.equals(debuggeeUnqualifiedSourcePath)) { + log3("ERROR: loc.sourcePath(defaultStratum) != debuggeeUnqualifiedSourcePath"); + log2(" loc.sourcePath(defaultStratum) == " + str); + log2(" debuggeeUnqualifiedSourcePath == " + debuggeeUnqualifiedSourcePath); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException"); + testExitCode = FAILED; + } catch ( Throwable err ) { + log3("ERROR: Throwable : " + err); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001/TestDescription.java new file mode 100644 index 00000000000..e5e64859e9c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001/TestDescription.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Location/sourcePath_s/sourcepath_s001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Location. + * The test checks up that a result of the method + * com.sun.jdi.Location.sourcePath(String) + * complies with its spec: + * public String sourcePath(String stratum) + * throws AbsentInformationException + * Gets the path to the source corresponding to this location. + * Interpretation of this string is the responsibility of + * the source repository mechanism. + * Returned path is for the specified stratum + * (see the class comment for a description of strata). + * In the reference implementation, for strata which do not explicitly specify + * source path (the Java programming language stratum never does), + * the returned string is the package name of declaringType() converted to + * a platform dependent path followed by the unqualified name of + * the source file for this Location (sourceName(stratum)). + * For example, on a Windows platform, + * java.lang.Thread would return "java\lang\Thread.java". + * Parameters: stratum - The stratum to retrieve information from or + * null for the declaring type's default stratum. + * Returns: a string specifying the source + * Throws: AbsentInformationException - + * if the source name is not known + * The test checks that + * - invocation of the method doesn't throw an error or unspecified exception;
    + * - returned value is debuggee's + * "unqualified name of the source file for this Location". + * The test works as follows: + * The debugger program - nsk.jdi.Location.sourcePath_s.sourcepath_s001; + * the debuggee program - nsk.jdi.Location.sourcePath_s.sourcepath_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and performes the testing call. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Location.sourcePath_s.sourcepath_s001 + * nsk.jdi.Location.sourcePath_s.sourcepath_s001a + * + * @comment make sure sourcepath_s001a is compiled with full debug info + * @clean nsk.jdi.Location.sourcePath_s.sourcepath_s001a + * @compile -g:lines,source,vars ../sourcepath_s001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Location.sourcePath_s.sourcepath_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001a.java new file mode 100644 index 00000000000..26ad8ad3e5b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Location/sourcePath_s/sourcepath_s001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Location.sourcePath_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the sourcepath_s001 JDI test. + */ + +public class sourcepath_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LongType.
    + *
    + * The test checks that for a mirror of a long value, the casts
    + * from Type to LongType and from PrimitiveType to LongType
    + * don't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a long field and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class longtype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LongType/_itself_/longtype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new longtype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LongType._itself_.longtype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......String name = 'ln';"); + String name = "ln"; + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type(); + log2(" PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + + LongType longType = null; + try { + log2(" checking up on cast: LongType longType = (LongType) type;"); + longType = (LongType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + try { + log2(" checking up on cast: LongType longType = (LongType) primitiveType;"); + longType = (LongType) primitiveType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001/TestDescription.java new file mode 100644 index 00000000000..24e7653a3a2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LongType/_itself_/longtype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LongType. + * The test checks that for a mirror of a long value the casts + * from Type to LongType and from PrimitiveType to LongType + * don't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.LongType._itself_.longtype001; + * the debuggee program - nsk.jdi.LongType._itself_.longtype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LongType._itself_.longtype001 + * nsk.jdi.LongType._itself_.longtype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LongType._itself_.longtype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001a.java new file mode 100644 index 00000000000..cd8417db8a4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.LongType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the longtype001 JDI test. + */ + +public class longtype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static long ln = 0; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001.java new file mode 100644 index 00000000000..2a1e00012b2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.LongValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + + +public class compareto001 { + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.LongValue.compareTo"; + private final static String className = ".compareto001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + private static Value objectValue; + private static List fieldList; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return; + } + + // getting of object to check + Field field = debuggeeClass.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + + objectValue = debuggeeClass.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = debuggeeClass.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = debuggeeClass.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitiveValues = (ArrayReference)arrValue; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + LongValue value; + Field fldOtherType; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof LongValue) ) { + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (LongValue )v1; + + // comparing with debuggee's fields + display("Checking compateTo(Object object) method for LongValue: " + value); + + for (int j = 0; j < primitiveValues.length(); j++) { + arrValue = primitiveValues.getValue(j); + + fldOtherType = debuggeeClass.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = debuggeeClass.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + + } + + //--------------------------------------------------------- test specific methods + + + private static boolean PerformComparing(LongValue value, Object object ) { + boolean result = true; + + // assertion [ x.compareTo(x) == 0 ] + if (value.compareTo(value) != 0) { + complain("Failed assertion [ x.compareTo(x) == 0 ] for value: " + value.toString()); + result = false; + } + + if (object instanceof LongValue) { + LongValue longObject = (LongValue)object; + try { + // assertion [ x.compareTo(y) == 0 <==> x.equals(y) ] + if ( ((value.equals(object)) && (value.compareTo(longObject) != 0)) || + (!(value.equals(object)) && (value.compareTo(longObject) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (x.equals(y) == true) ] \n\t" + + "where 'x' is LongValue: " + value + " and 'y' is LongValue : " + longObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(longObject) + "\n\t" + + "result of (x.equals(y)): " + value.equals(object) ); + result = false; + } + + // assertion [ x.compareTo(y) == 0 <==> y.compareTo(x) == 0 ] + if ( ((value.compareTo(longObject) == 0) && (longObject.compareTo(value) != 0)) || + ((value.compareTo(longObject) != 0) && (longObject.compareTo(value) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0) ] \n\t" + + "where 'x' is LongValue: " + value + " and 'y' is LongValue : " + longObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(longObject) + "\n\t" + + "result of (y.compareTo(x)): " + longObject.compareTo(value) ); + result = false; + } + if (value.compareTo(longObject) != 0) { + // assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] + if (value.compareTo(longObject) != -(longObject.compareTo(value))) { + complain("Failed assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] \n\t" + + "where 'x' is LongValue: " + value + " and 'y' is LongValue : " + longObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(longObject) + "\n\t" + + "result of (y.compareTo(x)): " + longObject.compareTo(value) ); + result = false; + } + } + + // assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] + if (value.compareTo(longObject) > 0) { + LongValue lessValue = FindLessLongValue(longObject); + if (lessValue != null) { + if (value.compareTo(lessValue) <= 0) { + complain("Failed assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] \n\t" + + "where 'x' is LongValue: " + value + " , 'y' is LongValue : " + longObject + " , 'z' is LongValue : " + lessValue + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(longObject) + "\n\t" + + "result of (y.compareTo(z)): " + longObject.compareTo(lessValue) + "\n\t" + + "result of (x.compareTo(z)): " + value.compareTo(lessValue) ); + result = false; + } + } + } + + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "LongValue: " + value + " and LongValue argument: " + object); + result = false; + } + + } else if (object == null) { + try { + value.compareTo(null); + complain("Does not throw expected NullPointerException when comparing \n\t" + + "LongValue: " + value + " and null argument"); + result = false; + } catch (NullPointerException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "LongValue: " + value + " and null argument"); + result = false; + } + } else { + try { + value.compareTo((LongValue)object); + complain("Does not throw expected ClassCastException when comparing \n\t" + + "LongValue: " + value + " and argument: " + object); + result = false; + } catch (ClassCastException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "LongValue: " + value + " and argument: " + object); + result = false; + } + } + + return result; + } + + /** + * This function searches the static fieldList - the list of mirrored + * fields of debuggee's compareto001aClassToCheck class. Search is aimed + * to find another LongValue field which is less then method's argument via + * compareTo method. + */ + + private static LongValue FindLessLongValue (LongValue currentValue) { + LongValue result = null; + + for (int i = 0; i < fieldList.size(); i++ ) { + + Field field = (Field )fieldList.get(i); + LongValue newValue = (LongValue)((ObjectReference )objectValue).getValue(field); + + if (currentValue.compareTo(newValue) > 0) { + result = newValue; + break; + } + } + return result; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001/TestDescription.java new file mode 100644 index 00000000000..919673a8906 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LongValue/compareTo/compareto001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the compareTo(Object o) method of com.sun.jdi.LongValue + * interface. This method is inherited from java.lang.Comparable interface. + * The test checks the following assertions which imply from spec for + * Comparable.compareTo(Object o): + * - (x.compareTo(y) == 0) is identical to (x.equals(y) == true); + * - (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0); + * - if (x.compareTo(y) == i) then (y.compareTo(x) == -i); + * - if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0); + * - if an argument is null, then NullPointerException is thrown; + * - if an argument is not of LongValue type, then a ClassCastException is thrown. + * where 'x', 'y' and 'z' denote LongValue object. + * The debugger program - nsk.jdi.LongValue.compareto.compareto001; + * the debuggee program - nsk.jdi.LongValue.compareto.compareto001a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * Then the debugger gets a list of long fields of debuggee's object of + * compareto001aClassToCheck type. For every field a mirror of LongValue type + * is created and the assertions are checked. A various values for comparison + * are got from values of mirrors of debuggee's static fields. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LongValue.compareTo.compareto001 + * nsk.jdi.LongValue.compareTo.compareto001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LongValue.compareTo.compareto001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001a.java new file mode 100644 index 00000000000..5ad9da953f3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/compareTo/compareto001a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.LongValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class compareto001a { + + //----------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + static compareto001aClassToCheck testedObj = new compareto001aClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + pipe.println(compareto001.SIGNAL_READY); +// receiveSignal(compareto001.SIGNAL_GO); + + receiveSignal(compareto001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class compareto001aClassToCheck { + public long longMAX = Long.MAX_VALUE; + public long long1 = 1; + public long long0 = 0; + public long long_1 = -1; + public long longMIN = Long.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001.java new file mode 100644 index 00000000000..897b15e3487 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LongValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * LongValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LongValue.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static long plus1_1 = +1;
    + * public static long plus1_2 = +1;
    + * public static long minus1 = -1;
    + * public static float floatplus1 = +1;
    + *
    + * which a debugger mirros as :
    + *
    + * LongValue lvplus1_1;
    + * LongValue lvplus1_2;
    + * LongValue lvminus1;
    + * FloatValue fvplus1;
    + *
    + * the following is true:
    + *
    + * lvplus1_1 == lvplus1_2
    + * lvplus1_1 != lvminus1
    + * lvplus1_1 != fvplus1
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LongValue/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LongValue.equals.equals001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("equals001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field flplus1_1 = execClass.fieldByName("plus1_1"); + Field flplus1_2 = execClass.fieldByName("plus1_2"); + Field flminus1 = execClass.fieldByName("minus1"); + Field ffplus1 = execClass.fieldByName("floatplus1"); + + LongValue lvplus1_1 = (LongValue) execClass.getValue(flplus1_1); + LongValue lvplus1_2 = (LongValue) execClass.getValue(flplus1_2); + LongValue lvminus1 = (LongValue) execClass.getValue(flminus1); + FloatValue fvplus1 = (FloatValue) execClass.getValue(ffplus1); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!lvplus1_1.equals(lvplus1_2)) + expresult = 1; + break; + + case 1: if (lvplus1_1.equals(lvminus1)) + expresult = 1; + break; + + case 2: if (lvplus1_1.equals(fvplus1)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..a79d3666841 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LongValue/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LongValue. + * The test checks up that a result of the method + * com.sun.jdi.LongValue.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this LongValue for equality. + * Returns: true if the Object is a LongValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.LongValue.equals.equals001; + * a debuggee program - nsk.jdi.LongValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LongValue.equals.equals001 + * nsk.jdi.LongValue.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LongValue.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001a.java new file mode 100644 index 00000000000..8a0e6e46877 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LongValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001a JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static long smallest = Long.MIN_VALUE; +// public static long zero = 0; +// public static long largest = Long.MAX_VALUE; + + public static long plus1_1 = +1; + public static long plus1_2 = +1; + public static long minus1 = -1; + + public static float floatplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * types and when parameter is null.
    + * Analyse of the method executing is performed by PerformComparing + * method.
    + * First parameter of PerformComparing is static field of testedObj,
    + * which is placed onto debugee's side.
    + * + * Second parameter is got from debugee too:
    + * Debugee has array of boundary values of each primitive type, execTest reads
    + * them and calls PerformComparing for each of them.
    + */ +public class equals002 { + + private final static String prefix = "nsk.jdi.LongValue.equals."; + private final static String className = "equals002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static ReferenceType refType; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + execTest(); + debugee.quit(); + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + private static void execTest() { + + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("Class '" + debugeeName + "' not found."); + return; + } + + // getting of object to check + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = refType.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = refType.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + List fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + LongValue value; + Field fldOtherType; + String msg; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + log.display(""); + msg = "***" + field; + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof LongValue) ) { + msg += " is not LongValue (skipped)"; + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (LongValue )v1; + + // comparing with debugee's fields + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = refType.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = refType.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static boolean PerformComparing(LongValue value, Object object ) { + boolean res = true; + String msg = ""; + try { + if ( value.equals(object) ) { + if ( object instanceof LongValue ) { + if ( value.value() == ((PrimitiveValue )object).longValue() ) { + msg += "--> " + value + " == " + object; + } else { + msg += "##> " + value + " == " + object; + res = false; + } + } + else { + msg += "##> " + value + " == " + object + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if ( object == null ) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if ( object instanceof LongValue ) { + if ( value.value() != ((PrimitiveValue )object).longValue() ) { + msg += "--> " + value + " != " + object; + } else { + msg += "##> " + value + " != " + object; + res = false; + } + } + else { + msg += "--> " + value + " != " + object; + } + } + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..301ffc4fdc4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LongValue/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.LongValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this LongValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is a LongValue and if applying "==" to the + * two mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has boundary values of primitive + * types. Also, case when parameter is considered. + * No exceptions are expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LongValue.equals.equals002 + * nsk.jdi.LongValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LongValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002a.java new file mode 100644 index 00000000000..6883bba8ca6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/equals/equals002a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.LongValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * equals002a is deugee's part of the test.
    + * It contains the static fields with boundary values for each primitive type.
    + * ClassToCheck delivers values for first parameter of equals.
    + */ +public class equals002a { + + static ClassToCheck testedObj = new ClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class ClassToCheck { + public long longMAX = Long.MAX_VALUE; + public long long1 = 1; + public long long0 = 0; + public long long_1 = -1; + public long longMIN = Long.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001.java new file mode 100644 index 00000000000..7719789504f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LongValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * LongValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LongValue.hashCode()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static long plus1_1 = +1;
    + * public static long plus1_2 = +1;
    + *
    + * which a debugger mirros as :
    + *
    + * LongValue lvplus1_1;
    + * LongValue lvplus1_2;
    + *
    + * the following is true:
    + *
    + * lvplus1_1.hashCode() == lvplus1_1.hashCode()
    + * lvplus1_1.hashCode() == lvplus1_2.hashCode()
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LongValue/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LongValue.hashCode.hashcode001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("hashcode001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field flplus1_1 = execClass.fieldByName("plus1_1"); + Field flplus1_2 = execClass.fieldByName("plus1_2"); + + LongValue lvplus1_1 = (LongValue) execClass.getValue(flplus1_1); + LongValue lvplus1_2 = (LongValue) execClass.getValue(flplus1_2); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (lvplus1_1.hashCode() != lvplus1_1.hashCode()) + expresult = 1; + break; + + case 1: if (lvplus1_1.hashCode() != lvplus1_2.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..1db82d67f0e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LongValue/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LongValue. + * The test checks up that a result of the method + * com.sun.jdi.LongValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this LongValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.LongValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.LongValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LongValue.hashCode.hashcode001 + * nsk.jdi.LongValue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LongValue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..56fb512d5b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/hashCode/hashcode001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LongValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001a JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static long smallest = Long.MIN_VALUE; +// public static long zero = 0; +// public static long largest = Long.MAX_VALUE; + + public static long plus1_1 = +1; + public static long plus1_2 = +1; +// public static long minus1 = -1; + +// public static float floatplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * LongValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.LongValue.value()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static long smallest = Long.MIN_VALUE;
    + * public static long zero = 0;
    + * public static long largest = Long.MAX_VALUE;
    + *
    + * which a debugger mirros as :
    + *
    + * LongValue lvsmallest;
    + * LongValue lvzero;
    + * LongValue lvlargest;
    + *
    + * the following is true:
    + *
    + * lvsmallest == Long.MIN_VALUE
    + * lvzero == 0
    + * lvlargest == Long.MAX_VALUE
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/LongValue/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.LongValue.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("value001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field flsmallest = execClass.fieldByName("smallest"); + Field flzero = execClass.fieldByName("zero"); + Field fllargest = execClass.fieldByName("largest"); + + LongValue lvsmallest = (LongValue) execClass.getValue(flsmallest); + LongValue lvzero = (LongValue) execClass.getValue(flzero); + LongValue lvlargest = (LongValue) execClass.getValue(fllargest); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (lvsmallest.value() != Long.MIN_VALUE) + expresult = 1; + break; + + case 1: if (lvzero.value() != 0) + expresult = 1; + break; + + case 2: if (lvlargest.value() != Long.MAX_VALUE) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001/TestDescription.java new file mode 100644 index 00000000000..d8721aab0a5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/LongValue/value/value001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * LongValue. + * The test checks up that a result of the method + * com.sun.jdi.LongValue.value() + * complies with its spec: + * public long value() + * Returns this LongValue as a long. + * Returns: the long mirrored by this object. + * The test works as follows: + * A debugger program - nsk.jdi.LongValue.value.value001; + * a debuggee program - nsk.jdi.LongValue.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.LongValue.value.value001 + * nsk.jdi.LongValue.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.LongValue.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001a.java new file mode 100644 index 00000000000..1806e42a84c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongValue/value/value001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.LongValue.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static long smallest = Long.MIN_VALUE; + public static long zero = 0; + public static long largest = Long.MAX_VALUE; + +// public static long plus1_1 = +1; +// public static long plus1_2 = +1; +// public static long minus1 = -1; + +// public static float floatplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.Method:
    + * + * - locationsOfLine(int) for boundary values of Integer
    + * + * - locationsOfLine(String, String, int) for boundary values of + * Integer and various combinations of value of String arguments + * such as (null, "", ), where + * means the some names of nonexisting object.
    + * + * - variablesByName(String) for various combinations of value + * of String arguments (see the notes above)
    + * + * - locationOfCodeIndex(long) for boundary values + * of Long
    + * + * - equals(Object) for null value
    + * + * - bytecodes() is checked on length of return array
    + * + * These checking are performed for native and non-native methods. + */ +public class bounds001 { + + private final static String prefix = "nsk.jdi.Method._bounds_."; + private final static String debuggerName = prefix + "bounds001"; + private final static String debugeeName = debuggerName + "a"; + private final static String classWithNativeMethod = "java.lang.System"; + private final static String nativeMethod = "currentTimeMillis"; + + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + public static int exitStatus; + public static Log log; + public static Debugee debugee; + + private static String propertyValue = "something"; + private static int lineNumbers[] = { + Integer.MIN_VALUE, + -1, + Integer.MAX_VALUE + }; + + private static long codeIndexes[] = { + Long.MIN_VALUE, + -1, + Long.MAX_VALUE + }; + + private static String[][] strParams = { + {null, null }, + {null, "" }, + {null, "bounds001_hotchpotch"}, + {"", null }, + {"", "" }, + {"", "bounds001_hotchpotch"}, + {"bounds001_jumble", null }, + {"bounds001_jumble", "" }, + {"bounds001_jumble", "bounds001_hotchpotch"} + }; + +//---------------------------------------------------- + + public static void display(String msg) { + log.display(msg); + } + + public static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + bounds001 thisTest = new bounds001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType testedClass = debugee.classByName(debugeeName); + Method method = methodByName(testedClass, bounds001a.justMethod); + + ReferenceType classNM = debugee.classByName(classWithNativeMethod); + Method nativeM = methodByName(classNM, nativeMethod); + + display("\nTEST BEGINS"); + display("==========="); + + checkMethod(method); + + display("============="); + + checkMethod(nativeM); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private void checkMethod(Method method) { + List list = null; + display(""); + display(">checking method: " + method); + display(">is native? " + method.isNative()); + + display("invoking locationsOfLine(int):"); + display("------------------------------"); + for (int i = 0; i < lineNumbers.length; i++) { + display("\tparameter: " + lineNumbers[i]); + try { + list = method.locationsOfLine(lineNumbers[i]); + display("\tsize of locations list: " + list.size()); + if (list.size() > 0) { + complain("\twrong size"); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + display("invoking locationsOfLine(String, String, int):"); + display("----------------------------------------------"); + for (int i = 0; i < lineNumbers.length; i++) { + for (int j = 0; j < strParams.length; j++) { + display("\tparameters: \"" + strParams[j][0] + "\", \"" + + strParams[j][1] + "\", " + lineNumbers[i]); + try { + list = method.locationsOfLine(strParams[j][0], strParams[j][1], + lineNumbers[i]); + display("\tsize of locations list: " + list.size()); + if (list.size() > 0) { + complain("\twrong size"); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + } + + display("invoking variablesByName(String):"); + display("---------------------------------"); + for (int j = 0; j < strParams.length; j++) { + display("\tparameter: \"" + strParams[j][0] + "\""); + try { + list = method.variablesByName(strParams[j][0]); + display("\tsize of variables list: " + list.size()); + if (list.size() > 0) { + complain("\twrong size"); + exitStatus = Consts.TEST_FAILED; + } + } catch (AbsentInformationException e) { + if (method.isNative()) { + display("\tExpected: " + e); + } else { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + j += 2; + } + + + Location loc; + display("invoking locationOfCodeIndex(long):"); + display("-----------------------------------"); + for (int i = 0; i < codeIndexes.length; i++) { + display("\tparameter: " + codeIndexes[i]); + try { + loc = method.locationOfCodeIndex(codeIndexes[i]); + display("\tlocation: " + loc); + if (loc != null) { + complain("\twrong location"); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + display("invoking equals(Object):"); + display("----------------------"); + display("\tparameter: "); + try { + if (!method.equals(null)) { + display("\tis not equal to "); + } else { + complain("\tis equal to "); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + + byte[] bytes; + display("invoking bytecodes():"); + display("---------------------"); + try { + bytes = method.bytecodes(); + display("\tsize of byte codes: " + bytes.length); + if (method.isNative()) { + if (bytes.length > 0) { + complain("\twrong size"); + exitStatus = Consts.TEST_FAILED; + } + } else { + if (bytes.length == 0) { + complain("\twrong size"); + exitStatus = Consts.TEST_FAILED; + } + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + private Method methodByName(ReferenceType refType, String methodName) { + List methodList = refType.methodsByName(methodName); + if (methodList == null) return null; + Method method = (Method )methodList.get(0); + return method; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001/TestDescription.java new file mode 100644 index 00000000000..92a86e9a630 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/_bounds_/bounds001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the following methods of com.sun.jdi.Method: + * - locationsOfLine(int) for boundary values of Integer + * - locationsOfLine(String, String, int) for boundary values of + * Integer and various combinations of value of String arguments + * such as null, "", , where means the some + * names of nonexisting object. + * - variablesByName(String) for various combinations of value of + * String arguments (see the notes above) + * - locationOfCodeIndex(long) for boundary values of Long + * - equals(Object) for null-value + * - bytecodes() is checked on length of return array + * These checking are performed for native and non-native methods. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method._bounds_.bounds001 + * nsk.jdi.Method._bounds_.bounds001a + * + * @comment make sure bounds001a is compiled with full debug info + * @clean nsk.jdi.Method._bounds_.bounds001a + * @compile -g:lines,source,vars ../bounds001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method._bounds_.bounds001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001a.java new file mode 100644 index 00000000000..1006da9cf48 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/_bounds_/bounds001a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Method._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * bounds001a is deugee's part of the bounds001. + */ +public class bounds001a { + + public final static String justMethod = "justMethod"; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(bounds001.SGNL_READY); + String instr = pipe.readln(); + if (instr.equals(bounds001.SGNL_QUIT)) { + log.display("constructor> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("constructor> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + void justMethod() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001.java new file mode 100644 index 00000000000..fb414a818c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.allLineLocations; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.allLineLocations()
    + * complies with its spec and returns an empty list
    + * when invoked on abstract and native methods.
    + */ + +public class alllinelocations001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/allLineLocations/alllinelocations001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new alllinelocations001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.allLineLocations.alllinelocations001a"; + + String mName = "nsk.jdi.Method.allLineLocations"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + List methods = null; + Method m = null; + List locations = null; + + + log2("----testing case: abstract method"); + + log2(" List classes = vm.classesByName(mName + '.AClass');"); + classes = vm.classesByName(mName + ".AClass"); + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1 for abstract class"); + break ; + } + log2(" methods = ((ReferenceType) classes.get(0)).methodsByName('atest');"); + methods = ((ReferenceType) classes.get(0)).methodsByName("atest"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 : " + methods.size()); + testExitCode = FAILED; + break; + } + + log2(" Method m = (Method) methods.get(0);"); + m = (Method) methods.get(0); + log2(" if (!m.isAbstract())"); + if (!m.isAbstract()) { + log3("ERROR : method 'atest' is not an abstract as expected"); + testExitCode = FAILED; + break; + } + + log2("......locations = m.allLineLocations(); AbsentInformationException is not expected"); + try { + locations = m.allLineLocations(); + } catch ( AbsentInformationException e ) { + log3("ERROR : AbsentInformationException for abstract method"); + testExitCode = FAILED; + break; + } + if (locations.size() != 0) { + log3("ERROR : locations.size() != 0 for abstract method"); + testExitCode = FAILED; + break; + } + + + log2("----testing case: native method"); + + log2(" List classes = vm.classesByName(mName + '.TestClass1');"); + classes = vm.classesByName(mName + ".TestClass1"); + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1 for native method"); + break ; + } + log2(" List methods = ((ReferenceType) classes.get(0)).methodsByName('test1');"); + methods = ((ReferenceType) classes.get(0)).methodsByName("test1"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 for test1 :" + methods.size()); + testExitCode = FAILED; + break; + } + log2(" Method m = (Method) methods.get(0);"); + m = (Method) methods.get(0); + log2(" if (!m.isNative())"); + if (!m.isNative()) { + log3("ERROR : 'test1' is not a native method as expected"); + testExitCode = FAILED; + break; + } + + log2("......locations = m.allLineLocations(); AbsentInformationException is not expected"); + try { + locations = m.allLineLocations(); + } catch ( AbsentInformationException e ) { + log3("ERROR : AbsentInformationException for abstract method"); + testExitCode = FAILED; + break; + } + if (locations.size() != 0) { + log3("ERROR : locations.size() != 0 for abstract method"); + testExitCode = FAILED; + break; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001/TestDescription.java new file mode 100644 index 00000000000..2a9cb2abfdb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001/TestDescription.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/allLineLocations/alllinelocations001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.allLineLocations() + * complies with its spec: + * public java.util.List allLineLocations() + * throws AbsentInformationException + * Returns the beginning Location objects for each executable source line in + * this method. Each location maps a source line to a range of code indices. + * The beginning of the range can be determined through Location.codeIndex(). + * The returned list is ordered by code index (from low to high). + * The returned list may contain multiple locations for + * a particular line number, if the compiler and/or VM has mapped that line to + * two or more disjoint code index ranges. + * If the method is native or abstract, an empty list is returned. + * Returns: a List of all source line Location objects. + * Throws: AbsentInformationException - + * if there is no line number information for this + * (non-native, non-abstract) method. + * when a tested method is native or abstract and + * when no AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.allLineLocations.alllinelocations001; + * the debuggee program - nsk.jdi.Method.allLineLocations.alllinelocations001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * In general, this test is potentially option depended + * since its spec states: + * Throws: AbsentInformationException - + * if there is no line number information for this + * (non-native, non-abstract) method. + * However, unlike some tests that need to be compiled with the option + * JAVAC_OPTS=-g + * (method.arguments(), method.variables() and method.variablesByName) + * at the date of implementing the test, + * javac prepares full information for the test without the option. + * Nonetheless, the alllinelocations002.cfg file contains the option + * in order to avoid possible failures in future in case of any changes + * in javac. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.allLineLocations.alllinelocations001 + * nsk.jdi.Method.allLineLocations.alllinelocations001a + * + * @comment make sure alllinelocations001a is compiled with full debug info + * @clean nsk.jdi.Method.allLineLocations.alllinelocations001a + * @compile -g:lines,source,vars ../alllinelocations001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.allLineLocations.alllinelocations001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001a.java new file mode 100644 index 00000000000..2fad5ec76e9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations001a.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.allLineLocations; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the alllinelocations001 JDI test. + */ + +public class alllinelocations001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> alllinelocations001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> alllinelocations001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.allLineLocations()
    + * complies with its spec for non-abstract, non-native method.
    + * The test checks up that a list of locations for the method
    + * - is not empty and
    + * - is ordered in a proper, from low to high, sequence.
    + */ + +public class alllinelocations002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/allLineLocations/alllinelocations002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new alllinelocations002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.display(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.allLineLocations.alllinelocations002a"; + + String mName = "nsk.jdi.Method.allLineLocations"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List methods = null; + Method m = null; + List locations = null; + + + log2(" getting: List classes = vm.classesByName(mName + '.TestClass');"); + List classes = vm.classesByName(mName + ".TestClass"); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2(" getting a tested method object 'm'"); + methods = ((ReferenceType) classes.get(0)).methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + log2("......locations = m.allLineLocations(); no AbsentInformationException is expected"); + try { + locations = m.allLineLocations(); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + + log2("......checking up on a value of locations.size(); 0 is not expected"); + if (locations.size() == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + log2("......checking up element order in the List"); + + ListIterator listIterator = locations.listIterator(); + + Location location1 = null; + Location location2 = null; + + int i2; + + for (i2 = 0; listIterator.hasNext(); i2++) { + + long codeIndex1 = 0l; + long codeIndex2 = 0l; + + try { + location2 = (Location) listIterator.next(); + } catch ( ClassCastException e) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + break ; + } + codeIndex2 = location2.codeIndex(); + if (i2 == 0) { + continue; + } + + if (codeIndex2 < codeIndex1) { + testExitCode = FAILED; + log3("ERROR: codeIndex disorder: codeIndex2 < codeIndex1"); + break ; + } + + codeIndex1 = codeIndex2; + } + + log2("......compareing locations.size() to a processed number of elements in the list"); + if (locations.size() != i2) { + testExitCode = FAILED; + log3("ERROR: locations.size() != the processed number"); + break ; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002/TestDescription.java new file mode 100644 index 00000000000..ec92566c07e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002/TestDescription.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/allLineLocations/alllinelocations002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.allLineLocations() + * complies with its spec: + * public java.util.List allLineLocations() + * throws AbsentInformationException + * Returns the beginning Location objects for each executable source line in + * this method. Each location maps a source line to a range of code indices. + * The beginning of the range can be determined through Location.codeIndex(). + * The returned list is ordered by code index (from low to high). + * The returned list may contain multiple locations for + * a particular line number, if the compiler and/or VM has mapped that line to + * two or more disjoint code index ranges. + * If the method is native or abstract, an empty list is returned. + * Returns: a List of all source line Location objects. + * Throws: AbsentInformationException - + * if there is no line number information for this + * (non-native, non-abstract) method. + * when a tested method is non-native, non-abstract and + * when no AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.allLineLocations.alllinelocations002; + * the debuggee program - nsk.jdi.Method.allLineLocations.alllinelocations002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * In general, this test is potentially option depended + * since its spec states: + * Throws: AbsentInformationException - + * if there is no line number information for this + * (non-native, non-abstract) method. + * However, unlike some tests that need to be compiled with the option + * JAVAC_OPTS=-g + * (method.arguments(), method.variables() and method.variablesByName) + * at the date of implementing the test, + * javac prepares full information for the test without the option. + * Nonetheless, the alllinelocations002.cfg file contains the option + * in order to avoid possible failures in future in case of any changes + * in javac. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.allLineLocations.alllinelocations002 + * nsk.jdi.Method.allLineLocations.alllinelocations002a + * + * @comment make sure alllinelocations002a is compiled with full debug info + * @clean nsk.jdi.Method.allLineLocations.alllinelocations002a + * @compile -g:lines,source,vars ../alllinelocations002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.allLineLocations.alllinelocations002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002a.java new file mode 100644 index 00000000000..96fdd8ba985 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations/alllinelocations002a.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.allLineLocations; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the alllinelocations002JDI test. + */ + +public class alllinelocations002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> alllinelocations002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> alllinelocations002a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * 9 --> 1000, source1 + * 10 --> 1001, source1 + * ... ... + * 16 --> 1007, source1 + * sde_testMethod1 + * 20 --> 1100, source1 + * 21 --> 1101, source1 + * ... ... + * 27 --> 1107, source1 + * sde_testMethod1 + * 31 --> 1200, source1 + * 32 --> 1201, source1 + * ... ... + * 38 --> 1207, source1 + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that for all methods defined in this class method 'com.sun.jdi.Method.allLineLocations(String stratum, String sourceName)' + * returns only expected locations for all stratums: for 'Java' stratum, and for stratums 'TestStratum1'-'TestStratum3'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.allLineLocations_ss.allLineLocations_ss002.allLineLocations_ss002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.allLineLocations_ss.allLineLocations_ss002.allLineLocations_ss002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.Method.allLineLocations_ss.allLineLocations_ss002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class allLineLocations_ss002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allLineLocations_ss002().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData; + + testStratumData = prepareDefaultPatchedClassFile_Type1(className, testStratumCount, true); + + /* + * Method 'prepareDefaultPatchedClassFile_Type1' creates class file with + * following line mapping for each TestStratum: "Java" "TestStratum" + * + * + * 9 --> 1000, source1 + * 10 --> 1001, source1 + * ... + * ... + * 16 --> 1007, source1 + * + * sde_testMethod1 + * 20 --> 1100, source1 + * 21 --> 1101, source1 + * ... + * ... + * 27 --> 1107, source1 + * + * sde_testMethod1 + * 31 --> 1200, source1 + * 32 --> 1201, source1 + * ... + * ... + * 38 --> 1207, source1 + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName : testStratumData.keySet()) { + for (Method method : referenceType.methods()) { + List expectedLocations = testStratumData.get(stratumName).allLocations; + + // all locations has the same source + String locationsSource = expectedLocations.get(0).sourceName; + + log.display("Check locations for method '" + method.name() + "': stratum: " + stratumName + ", source " + + locationsSource); + + try { + compareLocations(method.allLineLocations(stratumName, locationsSource), locationsOfMethod( + expectedLocations, + method.name()), stratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + + log.display("Check locations for method '" + method.name() + "': stratum: " + stratumName + ", source " + + null); + + try { + compareLocations(method.allLineLocations(stratumName, null), locationsOfMethod( + expectedLocations, + method.name()), stratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + } + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java new file mode 100644 index 00000000000..fc2f4e540bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss003. + * VM Testbase keywords: [quick, jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that method 'com.sun.jdi.Method.allLineLocations(String stratum, String sourceName)' returns + * correct values for all stratums available for class and if sourceName == null locaitions for all sources are returned. + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3') and for each of this stratums following line mapping + * is defined (each method has locations in 3 different sources): + * "Java" "TestStratum" + * + * 9 --> 1000, source1, path1 + * 10 --> 1000, source2, path2 + * 11 --> 1000, source3, path3 + * ... ... + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1100, source2, path2 + * 22 --> 1100, source3, path3 + * ... ... + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1200, source2, path2 + * 33 --> 1200, source3, path3 + * ... ... + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that for all methods defined in this class method 'com.sun.jdi.Method.allLineLocations(String stratum, String sourceName)' + * returns only expected locations for all stratums(for 'Java' stratum, and for stratums 'TestStratum1'-'TestStratum3') depending on given source name, + * and if source name is null locations for all sources are returned. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.allLineLocations_ss.allLineLocations_ss003.allLineLocations_ss003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.allLineLocations_ss.allLineLocations_ss003.allLineLocations_ss003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.Method.allLineLocations_ss.allLineLocations_ss003; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class allLineLocations_ss003 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allLineLocations_ss003().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type2(className, testStratumCount); + /* + * Method 'prepareDefaultPatchedClassFile_Type2' creates class file with + * following line mapping for each test stratum: "Java" "TestStratum" + * + * + * 9 --> 1000, source1, path1 + * 10 --> 1001, source2, path2 + * 11 --> 1002, source3, path3 + * ... + * ... + * + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1101, source2, path2 + * 22 --> 1102, source3, path3 + * ... + * ... + * + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1201, source2, path2 + * 33 --> 1207, source3, path3 + * ... + * ... + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName : testStratumData.keySet()) { + LocationsData locationsData = testStratumData.get(stratumName); + + for (Method method : referenceType.methods()) { + // for all available sources names + for (String sourceName : locationsData.sourceLocations.keySet()) { + List expectedLocations = locationsData.sourceLocations.get(sourceName); + + log.display("Check locations for method '" + method.name() + "': stratum: " + stratumName + + ", source " + sourceName); + + try { + compareLocations(method.allLineLocations(stratumName, sourceName), locationsOfMethod( + expectedLocations, + method.name()), stratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + } + + // check case when sourceName is null + log.display("Check locations for method '" + method.name() + "': stratum: " + stratumName + ", source " + + null); + + try { + compareLocations(method.allLineLocations(stratumName, null), locationsOfMethod( + locationsData.allLocations, + method.name()), stratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001.java new file mode 100644 index 00000000000..fb1704acf15 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.allLineLocations_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.allLineLocations(String,String)
    + * complies with its spec.
    + *
    + * The case for testing includes only non-abstract, non-native
    + * method and defaultStratum.
    + * The test checks up that a list of locations for the method
    + * - is not empty and
    + * - is ordered in a proper, from low to high, sequence.
    + */ + +public class alllinelocations_ss001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new alllinelocations_ss001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.allLineLocations_ss.alllinelocations_ss001a"; + + String mName = "nsk.jdi.Method.allLineLocations_ss"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List methods = null; + Method m = null; + List locations = null; + + + log2(" getting: List classes = vm.classesByName(mName + '.TestClass');"); + List classes = vm.classesByName(mName + ".TestClass"); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2("...... getting : String defaultStratum = vm.getDefaultStratum();"); + String defaultStratum = vm.getDefaultStratum(); + + + log2(" getting a tested Method object 'm'"); + methods = ((ReferenceType) classes.get(0)).methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + log2("......locations = m.allLineLocations(defaultStratum, null);"); + log2(" no AbsentInformationException is expected"); + try { + locations = m.allLineLocations(defaultStratum, null); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + + log2("......checking up on a value of locations.size(); 0 is not expected"); + if (locations.size() == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + log2("......checking up on element order in the List"); + + ListIterator listIterator = locations.listIterator(); + + Location location1 = null; + Location location2 = null; + + int i2; + + for (i2 = 0; listIterator.hasNext(); i2++) { + + long codeIndex1 = 0l; + long codeIndex2 = 0l; + + try { + location2 = (Location) listIterator.next(); + } catch ( ClassCastException e) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + break ; + } + codeIndex2 = location2.codeIndex(); + if (i2 == 0) { + continue; + } + + if (codeIndex2 < codeIndex1) { + testExitCode = FAILED; + log3("ERROR: codeIndex disorder: codeIndex2 < codeIndex1"); + break ; + } + + codeIndex1 = codeIndex2; + } + + log2("......compareing locations.size() to a processed number of elements in the list"); + if (locations.size() != i2) { + testExitCode = FAILED; + log3("ERROR: locations.size() != the processed number"); + break ; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001/TestDescription.java new file mode 100644 index 00000000000..84f588dbda8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001/TestDescription.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001. + * VM Testbase keywords: [jpda, jdi, feature_sde] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.allLineLocations(String,String) + * complies with its spec: + * public List allLineLocations(String stratum, String sourceName) + * throws AbsentInformationException + * Returns a list containing a Location object for + * each executable source line in this method. + * Each location maps a source line to a range of code indices. + * The beginning of the range can be determined through Location.codeIndex(). + * The returned list is ordered by code index (from low to high). + * The returned list may contain multiple locations for + * a particular line number, if the compiler and/or VM has mapped that line + * to two or more disjoint code index ranges. + * If the method is native or abstract, an empty list is returned. + * Returned list is for the specified stratum + * (see Location for a description of strata). + * Parameters: stratum - The stratum to retrieve information from or + * null for the #defaultStratum() + * sourceName - Return locations only within this source file or + * null to return locations. + * Returns: a List of all source line Location objects. + * Throws: AbsentInformationException - + * if there is no line number information for this + * (non-native, non-abstract) method. + * Or if sourceName is non-null and + * source name information is not present. + * The case for testing includes only non-abstract, + * non-native method and defaultStratum. + * The test checks up that a list of locations for the method + * - is not empty and + * - is ordered in a proper, from low to high, sequence. + * The test works as follows: + * The debugger program - nsk.jdi.Method.allLineLocations_ss.alllinelocations_ss001; + * the debuggee program - nsk.jdi.Method.allLineLocations_ss.alllinelocations_ss001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The option + * JAVAC_OPTS=-g + * is put in the locationsofline002.cfg file. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.allLineLocations_ss.alllinelocations_ss001 + * nsk.jdi.Method.allLineLocations_ss.alllinelocations_ss001a + * + * @comment make sure alllinelocations_ss001a is compiled with full debug info + * @clean nsk.jdi.Method.allLineLocations_ss.alllinelocations_ss001a + * @compile -g:lines,source,vars ../alllinelocations_ss001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.allLineLocations_ss.alllinelocations_ss001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001a.java new file mode 100644 index 00000000000..9d493684186 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/allLineLocations_ss/alllinelocations_ss001a.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.allLineLocations_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the alllinelocations_ss001 JDI test. + */ + +public class alllinelocations_ss001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.argumentTypeNames()
    + * complies with its spec when a type is one of PrimitiveTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class TestClass {
    + * public void primitiveargsmethod (
    + * boolean bl,
    + * byte bt,
    + * char ch,
    + * double db,
    + * float fl,
    + * int in,
    + * long l,
    + * short sh ) {
    + * return ;
    + * }
    + * }
    + * for all of the above primitive type arguments,
    + * a debugger forms text strings with corresponding
    + * types, that is 'boolean', 'byte', 'char', and etc.
    + *
    + */ + +public class argumenttypenames001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/argumentTypeNames/argumenttypenames001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new argumenttypenames001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.argumentTypeNames.argumenttypenames001a"; + + String mName = "nsk.jdi.Method.argumentTypeNames"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("argumenttypenames001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".argumenttypenames001aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + + List argTypeNames = null; + + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + argTypeNames = m.argumentTypeNames(); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean arg + + if (!argTypeNames.contains("boolean")) { + log3("ERROR: !argTypes.contains('boolean')"); + expresult = 1; + break; + } + break; + + case 1: // byte arg + + if (!argTypeNames.contains("byte")) { + log3("ERROR: !argTypes.contains('byte')"); + expresult = 1; + break; + } + break; + + case 2: // char arg + + if (!argTypeNames.contains("char")) { + log3("ERROR: !argTypes.contains('char')"); + expresult = 1; + break; + } + break; + + case 3: // double arg + + if (!argTypeNames.contains("double")) { + log3("ERROR: !argTypes.contains('double')"); + expresult = 1; + break; + } + break; + + case 4: // float arg + + if (!argTypeNames.contains("float")) { + log3("ERROR: !argTypes.contains('float')"); + expresult = 1; + break; + } + break; + case 5: // int arg + + if (!argTypeNames.contains("int")) { + log3("ERROR: !argTypes.contains('int')"); + expresult = 1; + break; + } + break; + + case 6: // long arg + + if (!argTypeNames.contains("long")) { + log3("ERROR: !argTypes.contains('long')"); + expresult = 1; + break; + } + break; + + case 7: // short arg + + if (!argTypeNames.contains("short")) { + log3("ERROR: !argTypes.contains('short')"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001/TestDescription.java new file mode 100644 index 00000000000..20966f2daad --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/argumentTypeNames/argumenttypenames001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.argumentTypeNames() + * complies with its spec: + * public java.util.List argumentTypeNames() + * Returns a text representation of all declared argument types of this method. + * This list is always available even if + * argument variables are unavailable due to absent debug information. + * Returns: a List of strings containing the return type name. + * when methods' arguments are of PrimitiveTypes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.argumentTypeNames.argumenttypenames001; + * the debuggee program - nsk.jdi.Method.argumentTypeNames.argumenttypenames001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.argumentTypeNames.argumenttypenames001 + * nsk.jdi.Method.argumentTypeNames.argumenttypenames001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.argumentTypeNames.argumenttypenames001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001a.java new file mode 100644 index 00000000000..84ed0043c59 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames001a.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.argumentTypeNames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the argumenttypenames001 JDI test. + */ + +public class argumenttypenames001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> argumenttypenames001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> argumenttypenames001a: " + message); + } + + //====================================================== test program + + static argumenttypenames001aTestClass obj = new argumenttypenames001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.argumentTypeNames()
    + * complies with its spec when a type is one of PrimitiveTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class TestClass {
    + * .
    + * .
    + * public ClassForCheck[] arrayargmethod (ClassForCheck[] cfc) {
    + * return cfc;
    + * }
    + * public ClassForCheck classargmethod (ClassForCheck classFC) {
    + * return classFC;
    + * }
    + * public InterfaceForCheck ifaceargmethod (InterfaceForCheck iface) {
    + * return iface;
    + * }
    + * }

    + * for all of the above ReferenceType arguments,
    + * a debugger forms text strings with corresponding
    + * types, that is "ClassForCheck[]", "ClassForCheck",
    + * and "InterfaceForCheck".
    + *
    + */ + +public class argumenttypenames002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/argumentTypeNames/argumenttypenames002", + sHeader2 = "--> argumenttypenames002: ", + sHeader3 = "##> argumenttypenames002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new argumenttypenames002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.argumentTypeNames.argumenttypenames002a"; + + String mName = "nsk.jdi.Method.argumentTypeNames"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("argumenttypenames002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".argumenttypenames002aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + + List argTypeNames = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // array arg + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("arrayargmethod"); + m = (Method) methods.get(0); + argTypeNames = m.argumentTypeNames(); + + if (!argTypeNames.contains(mName + ".argumenttypenames002aClassForCheck1[]")) { + log3("ERROR: !argTypeNames.contains(mName + '.argumenttypenames002aClassForCheck1[]'"); + expresult = 1; + break; + } + break; + + + case 1: // class arg + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("classargmethod"); + m = (Method) methods.get(0); + argTypeNames = m.argumentTypeNames(); + + if (!argTypeNames.contains(mName + ".argumenttypenames002aClassForCheck1")) { + log3("ERROR: !argTypeNames.contains(mName + '.argumenttypenames002aClassForCheck1'"); + expresult = 1; + break; + } + break; + + case 2: // interface arg + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ifaceargmethod"); + m = (Method) methods.get(0); + argTypeNames = m.argumentTypeNames(); + + if (!argTypeNames.contains(mName + ".argumenttypenames002aIntfForCheck")) { + log3("ERROR: !argTypeNames.contains(mName + '.argumenttypenames002aIntfForCheck'"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002/TestDescription.java new file mode 100644 index 00000000000..e4b0a9fc161 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/argumentTypeNames/argumenttypenames002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.argumentTypeNames() + * complies with its spec: + * public java.util.List argumentTypeNames() + * Returns a text representation of all declared argument types of this method. + * This list is always available even if + * argument variables are unavailable due to absent debug information. + * Returns: a List of strings containing the return type name. + * when methods' arguments are of ReferenceTypes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.argumentTypeNames.argumenttypenames002; + * the debuggee program - nsk.jdi.Method.argumentTypeNames.argumenttypenames002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.argumentTypeNames.argumenttypenames002 + * nsk.jdi.Method.argumentTypeNames.argumenttypenames002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.argumentTypeNames.argumenttypenames002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002a.java new file mode 100644 index 00000000000..8f0ff321da0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames002a.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.argumentTypeNames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the argumenttypenames002 JDI test. + */ + +public class argumenttypenames002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> argumenttypenames002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> argumenttypenames002a: " + message); + } + + //====================================================== test program + + static argumenttypenames002aTestClass obj = new argumenttypenames002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + private static void failure(String msg) { + complain(msg); + exitStatus = Consts.TEST_FAILED; + } + + public static int run(String argv[], PrintStream out) { + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + failure("Class '" + debuggeeName + "' not found."); + } + + execTest(); + debuggee.quit(); + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + String expMethodName = "foo"; + String[][] expSignatures = { /* signature of method varargs type name */ + {"([I)Ljava/lang/String;", "int[]"}, + {"([Ljava/lang/Integer;)Ljava/lang/String;", "java.lang.Integer[]"}, + {"(Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/String;", "java.lang.String[]"} + }; + + for (int i = 0; i < expSignatures.length; i++) { + List methods = debuggeeClass.methodsByName(expMethodName); + Method method = ((ClassType)debuggeeClass).concreteMethodByName(expMethodName, expSignatures[i][0]); + if (method != null) { + try { + List typeNames = method.argumentTypeNames(); + if (typeNames.contains(expSignatures[i][1])) { + display("Method.argumentTypeNames() returned expected varargs type name " + expSignatures[i][1]); + } else { + failure("Method.argumentTypeNames() did not return expected varargs type name " + expSignatures[i][1]); + } + + } catch (Exception e) { + failure("Unexpected exception: " + e); + e.printStackTrace(System.out); + } + } else { + failure("Cannot find method with signature: " + expSignatures[i][0]); + } + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003/TestDescription.java new file mode 100644 index 00000000000..90b895f2f11 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/argumentTypeNames/argumenttypenames003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for argumentTypeNames() method of Method interface. + * The test checks if the method returns string representing array + * of the type before the ellipsis for any mirrored method which has + * varargs argument. + * The test consists of a debugger program (argumenttypenames003.java) + * and debuggee application (argumenttypenames003a.java). + * Package name is nsk.jdi.Method.argumentTypeNames . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger finds mirrors of debuggee's methods 'foo' + * which have varargs arguments and calls argumentTypeNames() method + * for each found method mirror. The test checks if returned + * list contains a string representing expected array type + * of vararg argument. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.argumentTypeNames.argumenttypenames003 + * nsk.jdi.Method.argumentTypeNames.argumenttypenames003a + * + * @comment make sure argumenttypenames003a is compiled with full debug info + * @clean nsk.jdi.Method.argumentTypeNames.argumenttypenames003a + * @compile -g:lines,source,vars ../argumenttypenames003a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.argumentTypeNames.argumenttypenames003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003a.java new file mode 100644 index 00000000000..a51fa9b18e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypeNames/argumenttypenames003a.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Method.argumentTypeNames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class argumenttypenames003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(argumenttypenames003.SIGNAL_READY); + receiveSignal(argumenttypenames003.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific methods + + static String foo (int... args) { + return "1"; + } + + static String foo (Integer... args) { + return "2"; + } + + static String foo (String s, String... args) { + return "3"; + } +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001.java new file mode 100644 index 00000000000..e9882b87efa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001.java @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.argumentTypes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.argumentTypes()
    + * complies with its spec when a type is one of PrimitiveTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class argumenttypes001aTestClass {
    + * public void primitiveargsmethod (
    + * boolean bl,
    + * byte bt,
    + * char ch,
    + * double db,
    + * float fl,
    + * int in,
    + * long l,
    + * short sh ) {
    + * return ;
    + * }
    + * }
    + * for all of the above primitive type arguments,
    + * a debugger forms their corresponding Type objects
    + * BooleanType, ByteType, CharType, etc.
    + *
    + */ + +public class argumenttypes001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/argumentTypes/argumenttypes001", + sHeader2 = "--> argumenttypes001: ", + sHeader3 = "##> argumenttypes001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new argumenttypes001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.argumentTypes.argumenttypes001a"; + + String mName = "nsk.jdi.Method.argumentTypes"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("argumenttypes001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".argumenttypes001aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + Method m1 = null; + List argTypes = null; + + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + try { + argTypes = m.argumentTypes(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: CNLE: argTypes = m.argumentTypes();"); + testExitCode = FAILED; + break; + } + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean arg + BooleanType blType = null; + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("bl"); + m1 = (Method) methods.get(0); + try { + blType = (BooleanType) m1.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (BooleanType) m1.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (BooleanType) m1.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(blType)) { + log3("ERROR: !argTypes.contains(blType)"); + expresult = 1; + break; + } + break; + + case 1: // byte arg + ByteType btType = null; + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("bt"); + m1 = (Method) methods.get(0); + try { + btType = (ByteType) m1.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (ByteType) m1.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (ByteType) m1.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(btType)) { + log3("ERROR: !argTypes.contains(btType)"); + expresult = 1; + break; + } + break; + + case 2: // char arg + CharType chType = null; + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ch"); + m1 = (Method) methods.get(0); + try { + chType = (CharType) m1.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (CharType) m1.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: CharType) m1.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(chType)) { + log3("ERROR: !argTypes.contains(chType)"); + expresult = 1; + break; + } + break; + + case 3: // double arg + DoubleType dbType = null; + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("db"); + m1 = (Method) methods.get(0); + try { + dbType = (DoubleType) m1.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (DoubleType) m1.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (DoubleType) m1.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(dbType)) { + log3("ERROR: !argTypes.contains(dbType)"); + expresult = 1; + break; + } + break; + + case 4: // float arg + FloatType flType = null; + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("fl"); + m1 = (Method) methods.get(0); + try { + flType = (FloatType) m1.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (FloatType) m1.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (FloatType) m1.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(flType)) { + log3("ERROR: !argTypes.contains(flType)"); + expresult = 1; + break; + } + break; + case 5: // int arg + IntegerType inType = null; + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("in"); + m1 = (Method) methods.get(0); + try { + inType = (IntegerType) m1.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (IntegerType) m1.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (IntegerType) m1.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(inType)) { + log3("ERROR: !argTypes.contains(inType)"); + expresult = 1; + break; + } + break; + + case 6: // long arg + LongType lnType = null; + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ln"); + m1 = (Method) methods.get(0); + try { + lnType = (LongType) m1.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (LongType) m1.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (LongType) m1.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(lnType)) { + log3("ERROR: !argTypes.contains(lnType)"); + expresult = 1; + break; + } + break; + + case 7: // short arg + ShortType shType = null; + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("sh"); + m1 = (Method) methods.get(0); + try { + shType = (ShortType) m1.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (ShortType) m1.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (ShortType) m1.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(shType)) { + log3("ERROR: !argTypes.contains(shType)"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001/TestDescription.java new file mode 100644 index 00000000000..09ee5295c25 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/argumentTypes/argumenttypes001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.argumentTypes() + * complies with its spec: + * public java.util.List argumentTypes() + * throws ClassNotLoadedException + * Returns the list containing the type of each argument. + * For primitive arguments, an appropriate PrimitiveType is always returned. + * For object arguments, the appropriate ReferenceType is returned if + * it has been loaded through the enclosing type's + * (that is, the type returned by TypeComponent#enclosingType) class loader. + * Returns: the list of argument types for this method. + * Throws: ClassNotLoadedException - + * if the type has not yet been loaded through + * the appropriate class loader. + * when methods' arguments are of PrimitiveTypes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.argumentTypes.argumenttypes001; + * the debuggee program - nsk.jdi.Method.argumentTypes.argumenttypes001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.argumentTypes.argumenttypes001 + * nsk.jdi.Method.argumentTypes.argumenttypes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.argumentTypes.argumenttypes001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001a.java new file mode 100644 index 00000000000..f56f5285c75 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes001a.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.argumentTypes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the argumenttypes001 JDI test. + */ + +public class argumenttypes001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> argumenttypes001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> argumenttypes001a: " + message); + } + + //====================================================== test program + + static argumenttypes001aTestClass obj = new argumenttypes001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.argumentTypes()
    + * complies with its spec when a type is one of PrimitiveTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class argumenttypes002aTestClass {
    + * .
    + * .
    + * public ClassForCheck[] arrayargmethod (ClassForCheck[] cfc) {
    + * return cfc;
    + * }
    + * public ClassForCheck classargmethod (ClassForCheck classFC) {
    + * return classFC;
    + * }
    + * public InterfaceForCheck ifaceargmethod (InterfaceForCheck iface) {
    + * return iface;
    + * }
    + * }

    + * for all of the above ReferenceType arguments,
    + * a debugger forms their corresponding Type objects:
    + * ClassForCheck[], ClassForCheck, and InterfaceForCheck.
    + *
    + */ + +public class argumenttypes002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/argumentTypes/argumenttypes002", + sHeader2 = "--> argumenttypes002: ", + sHeader3 = "##> argumenttypes002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new argumenttypes002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.argumentTypes.argumenttypes002a"; + + String mName = "nsk.jdi.Method.argumentTypes"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("argumenttypes002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".argumenttypes002aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + ReferenceType testClass = (ReferenceType) listOfDebuggeeClasses.get(0); + + List methods = null; + Method m = null; + List argTypes = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // array arg + + methods = testClass.methodsByName("arrayargmethod"); + m = (Method) methods.get(0); + try { + argTypes = m.argumentTypes(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: CNLE: argTypes = m.argumentTypes(); for arrayargmethod"); + testExitCode = FAILED; + break; + } + + ArrayType aType = null; + try { + aType = (ArrayType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (ArrayType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (ArrayType) m.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(aType)) { + log3("ERROR: !argTypes.contains(aType)"); + expresult = 1; + break; + } + break; + + case 1: // class arg + + methods = testClass.methodsByName("classargmethod"); + m = (Method) methods.get(0); + try { + argTypes = m.argumentTypes(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: CNLE: argTypes = m.argumentTypes(); for classargmethod"); + testExitCode = FAILED; + break; + } + + ClassType cType = null; + try { + cType = (ClassType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (ClassType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (ClassType) m.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(cType)) { + log3("ERROR: !argTypes.contains(cType)"); + expresult = 1; + break; + } + break; + + + case 2: // interface arg + + methods = testClass.methodsByName("ifaceargmethod"); + m = (Method) methods.get(0); + try { + argTypes = m.argumentTypes(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: CNLE: argTypes = m.argumentTypes(); for ifaceargmethod"); + testExitCode = FAILED; + break; + } + + InterfaceType iType = null; + try { + iType = (InterfaceType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (InterfaceType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (InterfaceType) m.returnType();"); + expresult = 1; + break; + } + + if (!argTypes.contains(iType)) { + log3("ERROR: !argTypes.contains(iType)"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002/TestDescription.java new file mode 100644 index 00000000000..d9d7a4e54f5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/argumentTypes/argumenttypes002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.argumentTypes() + * complies with its spec: + * public java.util.List argumentTypes() + * throws ClassNotLoadedException + * Returns the list containing the type of each argument. + * For primitive arguments, an appropriate PrimitiveType is always returned. + * For object arguments, the appropriate ReferenceType is returned if + * it has been loaded through the enclosing type's + * (that is, the type returned by TypeComponent#enclosingType) class loader. + * Returns: the list of argument types for this method. + * Throws: ClassNotLoadedException - + * if the type has not yet been loaded through + * the appropriate class loader. + * when methods' arguments are of ReferenceTypes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.argumentTypes.argumenttypes002; + * the debuggee program - nsk.jdi.Method.argumentTypes.argumenttypes002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.argumentTypes.argumenttypes002 + * nsk.jdi.Method.argumentTypes.argumenttypes002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.argumentTypes.argumenttypes002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002a.java new file mode 100644 index 00000000000..7ef8c8d4d54 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/argumentTypes/argumenttypes002a.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.argumentTypes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the argumenttypes002 JDI test. + */ + +public class argumenttypes002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> argumenttypes002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> argumenttypes002a: " + message); + } + + //====================================================== test program + + static argumenttypes002aTestClass obj = new argumenttypes002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.arguments()
    + * complies with its spec if a debugged program is compiled with
    + * "-g" option, hence no exception AbsentInformationException
    + * is expected.
    + *
    + * Cases for testing are as follows:
    + * - non-native method with arguments
    + * - non-native method without arguments
    + * - native method
    + */ + +public class arguments001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/arguments/arguments001", + sHeader2 = "--> arguments001: ", + sHeader3 = "##> arguments001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new arguments001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.arguments.arguments001a"; + + String mName = "nsk.jdi.Method.arguments"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("arguments001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + + ".arguments001aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + List argsList = null; + + + // method with arguments + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + check: { + try { + argsList = m.arguments(); + if (argsList.size() != 8) { + log3("ERROR: for method with arguments: argsList# != 8 :" + + argsList.size() ); + testExitCode = FAILED; + } + try { + for (int i2 = 0; i2 < argsList.size(); i2++) { + LocalVariable lv = (LocalVariable) argsList.get(i2); + int n = 0; + String names[] = { "bl", "bt", "ch", "db", + "fl", "in", "ln", "sh" }; + String name = lv.name(); + + for (int i3 = 0; i3 < 8; i3++) { + if (names[i3].equals(name)) { + if (n == 1) { + log3("ERROR: method with args: multiple arg names " + + name); + testExitCode = FAILED; + } + n++; + } + } + if (n == 0) { + log3("ERROR: method with args: no name in list: " + + name); + testExitCode = FAILED; + } + } + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException for lv = (LocalVariable) arglist.get(0);"); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for method with arguments"); + testExitCode = FAILED; + } + } //check: + + + // method without arguments + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("vd"); + m = (Method) methods.get(0); + + try { + argsList = m.arguments(); + if (argsList.size() != 0) { + log3("ERROR: for method without arguments: argsList# != 0 :" + + argsList.size() ); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for method without arguments"); + testExitCode = FAILED; + } + + + // native method + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("nvd"); + m = (Method) methods.get(0); + + try { + argsList = m.arguments(); + log3("ERROR: no AbsentInformationException for native method"); + testExitCode = FAILED; + } catch ( AbsentInformationException e ) { + log2(" AbsentInformationException for native method"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001/TestDescription.java new file mode 100644 index 00000000000..b49b15ee4dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001/TestDescription.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/arguments/arguments001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.arguments() + * complies with its spec: + * public java.util.List arguments() + * throws AbsentInformationException + * Returns a list containing each LocalVariable that is declared as + * an argument of this method. + * Returns: the list of LocalVariable arguments. + * If there are no arguments, a zero-length list is returned. + * Throws: AbsentInformationException - + * if there is no variable information for this method. + * NativeMethodException - + * if this operation is attempted for a native method. + * when a debugged program is compiled with the '-g' option, + * hence, no AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.arguments.arguments001; + * the debuggee program - nsk.jdi.Method.arguments.arguments001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * -------------- + * Fixing bug 4453137: + * To comply with the latest Merlin specification + * which differs the Ladybird and early Merlin specifications, + * the test is corrected as follows: + * - for native method, + * the check on throwing AbsentInformationException is performed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.arguments.arguments001 + * nsk.jdi.Method.arguments.arguments001a + * + * @comment make sure arguments001a is compiled with full debug info + * @clean nsk.jdi.Method.arguments.arguments001a + * @compile -g:lines,source,vars ../arguments001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.arguments.arguments001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001a.java new file mode 100644 index 00000000000..5cffeef950b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments001a.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.arguments; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the arguments001 JDI test. + */ + +public class arguments001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> arguments001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> arguments001a: " + message); + } + + //====================================================== test program + + static arguments001aTestClass obj = new arguments001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.arguments()
    + * complies with its spec if a debugged program is compiled
    + * without "-g" option,
    + * hence, the exception AbsentInformationException is expected.

    + *
    + */ + +public class arguments002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/arguments/arguments002", + sHeader2 = "--> arguments002: ", + sHeader3 = "##> arguments002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new arguments002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.arguments.arguments002a"; + + String mName = "nsk.jdi.Method.arguments"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("arguments002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".arguments002aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + List argsList = null; + + + // method with arguments + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + try { + argsList = m.arguments(); + log3(" no AbsentInformationException"); + testExitCode = FAILED; + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002/TestDescription.java new file mode 100644 index 00000000000..7ad9e2014b1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/arguments/arguments002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.arguments() + * complies with its spec: + * public java.util.List arguments() + * throws AbsentInformationException + * Returns a list containing each LocalVariable that is declared as + * an argument of this method. + * Returns: the list of LocalVariable arguments. + * If there are no arguments, a zero-length list is returned. + * Throws: AbsentInformationException - + * if there is no variable information for this method. + * NativeMethodException - + * if this operation is attempted for a native method. + * when a debugged program is compiled without the '-g' option, + * hence, AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.arguments.arguments002; + * the debuggee program - nsk.jdi.Method.arguments.arguments002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.arguments.arguments002 + * nsk.jdi.Method.arguments.arguments002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.arguments.arguments002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002a.java new file mode 100644 index 00000000000..9e246754639 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments002a.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.arguments; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the arguments002 JDI test. + */ + +public class arguments002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> arguments002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> arguments002a: " + message); + } + + //====================================================== test program + + static arguments002aTestClass obj = new arguments002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + private static void failure(String msg) { + complain(msg); + exitStatus = Consts.TEST_FAILED; + } + + public static int run(String argv[], PrintStream out) { + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + failure("Class '" + debuggeeName + "' not found."); + } + + execTest(); + debuggee.quit(); + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + String expMethodName = "foo"; + String[][] expSignatures = { /* signature of method varargs type name */ + {"([I)Ljava/lang/String;", "int[]"}, + {"([Ljava/lang/Integer;)Ljava/lang/String;", "java.lang.Integer[]"}, + {"(Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/String;", "java.lang.String[]"} + }; + + for (int i = 0; i < expSignatures.length; i++) { + List methods = debuggeeClass.methodsByName(expMethodName); + Method method = ((ClassType)debuggeeClass).concreteMethodByName(expMethodName, expSignatures[i][0]); + if (method != null) { + try { + Iterator arguments = method.arguments().iterator(); + boolean found = false; + while (arguments.hasNext()) { + LocalVariable argument = arguments.next(); + if (argument.typeName().equals(expSignatures[i][1])) { + found = true; + } + } + if (found) { + display("Method.arguments() returned expected varargs argument of type: " + expSignatures[i][1]); + } else { + failure("Method.arguments() did not return expected varargsvarargs argument of type: " + expSignatures[i][1]); + } + + } catch (Exception e) { + failure("Unexpected exception: " + e); + e.printStackTrace(System.out); + } + } else { + failure("Cannot find method with signature: " + expSignatures[i][0]); + } + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003/TestDescription.java new file mode 100644 index 00000000000..f6bc95093e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/arguments/arguments003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for arguments() method of Method interface. + * The test checks if the method returns list of LocalVariable + * references which contains array type local variable for any + * mirrored method which has varargs argument. + * The test consists of a debugger program (arguments003.java) + * and debuggee application (arguments003a.java). + * Package name is nsk.jdi.Method.arguments . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger finds mirrors of debuggee's methods 'foo' + * which have varargs arguments and calls arguments() method + * for each found method mirror. The test checks if returned + * list contains a LocalVariable reference representing expected + * array type of vararg argument. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.arguments.arguments003 + * nsk.jdi.Method.arguments.arguments003a + * + * @comment make sure arguments003a is compiled with full debug info + * @clean nsk.jdi.Method.arguments.arguments003a + * @compile -g:lines,source,vars ../arguments003a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.arguments.arguments003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003a.java new file mode 100644 index 00000000000..48911a40f0d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/arguments/arguments003a.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Method.arguments; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class arguments003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(arguments003.SIGNAL_READY); + receiveSignal(arguments003.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific methods + + static String foo (int... args) { + return "1"; + } + + static String foo (Integer... args) { + return "2"; + } + + static String foo (String s, String... args) { + return "3"; + } +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001.java new file mode 100644 index 00000000000..84b0bf465e5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.bytecodes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.bytecodes()
    + * complies with its spec.
    + *
    + * If VirtualMachine supports this method the test checks up
    + * that the method invokation doesn't throw
    + * UnsupportedOperationException and a returned value is not null.
    + */ + +public class bytecodes001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/bytecodes/bytecodes001", + sHeader2 = "--> bytecodes001: ", + sHeader3 = "##> bytecodes001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new bytecodes001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.bytecodes.bytecodes001a"; + + String mName = "nsk.jdi.Method.bytecodes"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("bytecodes001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + if (!vm.canGetBytecodes()) { + log2(" : !vm.canGetBytecodes()"); + break ; + } + + List listOfDebuggeeClasses = vm.classesByName(mName + + ".TestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + + List argTypeNames = null; + + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + byte[] mBytecode = null; + try { + mBytecode = m.bytecodes(); + } catch ( UnsupportedOperationException e ) { + log3("ERROR: UnsupportedOperationException for vm.canGetBytecodes()"); + testExitCode = FAILED; + break; + } + if (mBytecode == null) { + log3("ERROR: mBytecode == null"); + testExitCode = FAILED; + break; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001/TestDescription.java new file mode 100644 index 00000000000..92017b7704a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/bytecodes/bytecodes001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.bytecodes() + * complies with its spec: + * public byte[] bytecodes() + * Returns an array containing the bytecodes for this method. + * Not all target VMs support this query. + * See VirtualMachine#canGetBytecodes to determine if + * the operation is supported. + * Returns: the array of bytecodes. + * Throws: java.lang.UnsupportedOperationException - + * if the target VM does not support the retrieval of bytecodes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.bytecodes.bytecodes001; + * the debuggee program - nsk.jdi.Method.bytecodes.bytecodes001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.bytecodes.bytecodes001 + * nsk.jdi.Method.bytecodes.bytecodes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.bytecodes.bytecodes001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001a.java new file mode 100644 index 00000000000..13ef8aeef9c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/bytecodes/bytecodes001a.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.bytecodes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the bytecodes001 JDI test. + */ + +public class bytecodes001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> bytecodes001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> bytecodes001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows:
    + * two objects mirror the same method on the same VM
    + * two objects mirror different methods on the same VM
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.equals.equals001a"; + + String mName = "nsk.jdi.Method.equals"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("equals001a debuggees launched"); + debuggee.resume(); + log2("equals001a debuggees resumed"); + + String line = pipe.readln(); + + if ((line == null) || !line.equals("ready")) { + log3("line: signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("line: 'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + log2("line: 'newcheck' sent"); + + line = pipe.readln(); + if (line.equals("checkend")) { + log2(" : line: returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: line: returned string is not 'checkready'"); + testExitCode = FAILED; +// break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses1 = vm.classesByName(mName + ".TestClass1"); + if (listOfDebuggeeClasses1.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses1.size() != 1"); + break ; + } + List listOfDebuggeeClasses2 = vm.classesByName(mName + ".TestClass2"); + if (listOfDebuggeeClasses2.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses2.size() != 1"); + break ; + } + + List methods = null; + Method m1 = null; + Method m2 = null; + Method m3 = null; + + methods = ((ReferenceType) listOfDebuggeeClasses1.get(0)). + methodsByName("primitiveargsmethod"); + m1 = (Method) methods.get(0); + + methods = ((ReferenceType) listOfDebuggeeClasses1.get(0)). + methodsByName("primitiveargsmethod"); + m2 = (Method) methods.get(0); + + methods = ((ReferenceType) listOfDebuggeeClasses2.get(0)). + methodsByName("arrayargmethod"); + m3 = (Method) methods.get(0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // both m1 and m2 mirror the same method + + if (!m1.equals(m2)) { + log3("ERROR: !m1.equals(m2)"); + expresult = 1; + break; + } + break; + + case 1: // different classes on the same VM + + if (m1.equals(m3)) { + log3("ERROR: m1.equals(m3)"); + expresult = 1; + break; + } + break; + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..fad91b8f4ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this method for equality. + * Returns: true if the Object is a method and if both mirror the same method + * (declared in the same class or interface, in the same VM). + * Overrides: equals in class java.lang.Object + * The test works as follows: + * The debugger program - nsk.jdi.Method.equals.equals001; + * the debuggee program - nsk.jdi.Method.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4791232 TEST_BUG: some JDI tests start two instances of debuggee VM + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.equals.equals001 + * nsk.jdi.Method.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001a.java new file mode 100644 index 00000000000..30df66a081f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/equals/equals001a.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001 JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + + static TestClass1 obj1 = new TestClass1(); + static TestClass2 obj2 = new TestClass2(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.hashCode()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows:
    + * two objects mirror the same method on the same VM
    + * two objects mirror different methods on the same VM
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.hashCode.hashcode001a"; + + String mName = "nsk.jdi.Method.hashCode"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee1; +// Debugee debuggee2; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee1 = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp +// debuggee2 = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee1 = binder.bindToDebugee(debuggeeName); // *** tp +// debuggee2 = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe1 = new IOPipe(debuggee1); +// IOPipe pipe2 = new IOPipe(debuggee2); + + debuggee1.redirectStderr(out); +// debuggee2.redirectStderr(out); + log2("equals001a debuggees launched"); + debuggee1.resume(); +// debuggee2.resume(); +// log2("equals001a debuggees resumed"); + + String line1 = pipe1.readln(); +// String line2 = pipe2.readln(); + + + if ((line1 == null) || !line1.equals("ready")) { + log3("line1: signal received is not 'ready' but: " + line1); + return FAILED; + } else { + log2("line1: 'ready' recieved"); + } +/* + if ((line2 == null) || !line2.equals("ready")) { + log3("line2: signal received is not 'ready' but: " + line2); + return FAILED; + } else { + log2("line2: 'ready' recieved"); + } +*/ + VirtualMachine vm1 = debuggee1.VM(); +// VirtualMachine vm2 = debuggee2.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + +// for (int i = 0; ; i++) { + + check: + { + pipe1.println("newcheck"); + log2("line1: 'newcheck' sent"); + line1 = pipe1.readln(); + +// if (line1.equals("checkend")) { +// log2(" : line1: returned string is 'checkend'"); +// } else { + + if (!line1.equals("checkready")) { + log3("ERROR: line1: returned string is not 'checkready'"); + testExitCode = FAILED; + break check; + } + +/* + pipe2.println("newcheck"); + log2("line2: 'newcheck' sent"); + line2 = pipe2.readln(); + +// if (line2.equals("checkend")) { +// log2(" : line2: returned string is 'checkend'"); +// break ; +// } else { + + if (!line2.equals("checkready")) { + log3("ERROR: line2: returned string is not 'checkready'"); + testExitCode = FAILED; + break check; + } +*/ + + + log1("check begins: "); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses1 = vm1.classesByName(mName + ".TestClass1"); + if (listOfDebuggeeClasses1.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses1.size() != 1"); + break check; + } + List listOfDebuggeeClasses2 = vm1.classesByName(mName + ".TestClass2"); + if (listOfDebuggeeClasses2.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses2.size() != 1"); + break check; + } +/* + List listOfDebuggeeClasses3 = vm2.classesByName(mName + ".TestClass1"); + if (listOfDebuggeeClasses3.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses3.size() != 1"); + break check; + } +*/ + List methods = null; + Method m1 = null; + Method m2 = null; + Method m3 = null; +// Method m4 = null; + + methods = ((ReferenceType) listOfDebuggeeClasses1.get(0)). + methodsByName("primitiveargsmethod"); + m1 = (Method) methods.get(0); + + methods = ((ReferenceType) listOfDebuggeeClasses1.get(0)). + methodsByName("primitiveargsmethod"); + m2 = (Method) methods.get(0); + + methods = ((ReferenceType) listOfDebuggeeClasses2.get(0)). + methodsByName("arrayargmethod"); + m3 = (Method) methods.get(0); + +/* + methods = ((ReferenceType) listOfDebuggeeClasses3.get(0)). + methodsByName("primitiveargsmethod"); + m4 = (Method) methods.get(0); +*/ + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // both m1 and m2 mirror the same method + + if ( m1.hashCode() != m2.hashCode() ) { + log3("ERROR: m1.hashCode() != m2.hashCode()"); + expresult = 1; + break; + } + break; + + case 1: // different classes on the same VM + + if ( m1.hashCode() == m3.hashCode() ) { + log3("ERROR: m1.hashCode() == m3.hashCode()"); + expresult = 1; + break; + } + break; +/* + case 2: // different VMs + + if ( m1.hashCode() != m4.hashCode() ) { + log3("ERROR: m1.hashCode() != m4.hashCode()"); + expresult = 1; + break; + } + break; +*/ + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; " ); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + } // check: + + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + if (line1.equals("checkready")) { + pipe1.println("quit"); + log2("waiting for the debuggee1 to finish ..."); + debuggee1.waitFor(); + + int status1 = debuggee1.getStatus(); + if (status1 != PASSED + PASS_BASE) { + log3("debuggee1 returned UNEXPECTED exit status: " + + status1 + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee1 returned expected exit status: " + + status1 + " == PASS_BASE"); + } + } +/* + else { + if (line2.equals("checkready")) { + pipe2.println("quit"); + log2("waiting for the debuggee2 to finish ..."); + debuggee2.waitFor(); + + int status2 = debuggee2.getStatus(); + if (status2 != PASSED + PASS_BASE) { + log3("debuggee2 returned UNEXPECTED exit status: " + + status2 + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee2 returned expected exit status: " + + status2 + " == PASS_BASE"); + } + } + } +*/ + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..f9d4e477222 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this Method. + * Returns: the integer hash code + * Overrides: hashCode in class java.lang.Object + * when both mirrored Method objects are on the same VM. + * The test works as follows: + * The debugger program - nsk.jdi.Method.hashCode.hashcode001; + * the debuggee program - nsk.jdi.Method.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.hashCode.hashcode001 + * nsk.jdi.Method.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001a.java new file mode 100644 index 00000000000..a86576b33d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/hashCode/hashcode001a.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001 JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + + static TestClass1 obj1 = new TestClass1(); + static TestClass2 obj2 = new TestClass2(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.isAbstract()
    + * true for a class method declared as abstract and
    + * to false otherwise.
    + */ + +public class isabstract001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/isAbstract/isabstract001", + sHeader2 = "--> isabstract001: ", + sHeader3 = "##> isabstract001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new isabstract001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.isAbstract.isabstract001a"; + + String mName = "nsk.jdi.Method.isAbstract"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("isabstract001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".AClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("atest"); + if (methods.size() <= 0) { + log3("ERROR : methods.size() <= 0 for 'atest' " + methods.size()); + testExitCode = FAILED; + break; + } + + Method testMethod = (Method) methods.get(0); + if (!testMethod.isAbstract()) { + log3("ERROR : method 'atest' is not an abstract"); + testExitCode = FAILED; + break; + } + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("test"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 for test"); + testExitCode = FAILED; + break; + } + testMethod = (Method) methods.get(0); + if (testMethod.isAbstract()) { + log3("ERROR : test is an abstract"); + testExitCode = FAILED; + break; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001/TestDescription.java new file mode 100644 index 00000000000..84eaa7f869c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isAbstract/isabstract001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.isAbstract() + * complies with its spec: + * public boolean isAbstract() + * Determine if this method is abstract. + * Returns: true if the method is declared abstract; false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.Method.isAbstract.isabstract001; + * the debuggee program - nsk.jdi.Method.isAbstract.isabstract001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isAbstract.isabstract001 + * nsk.jdi.Method.isAbstract.isabstract001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isAbstract.isabstract001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001a.java new file mode 100644 index 00000000000..788af87f4b7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isAbstract/isabstract001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isAbstract; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the isabstract001 JDI test. + */ + +public class isabstract001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> isabstract001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> isabstract001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.Method.isBridge()
    + * It verifies that 'bridge methods' generated during translation of + * generic classes are determinated properly by the method. + * Here are the rules from the spec "Adding Generics to the Java + * Programming Language: Public Draft Specification, Version 2.0" + * followed by the test:
    + *
    + *     6.2 Translation of Methods
    + *     ...
    + *     
  • If C.m is directly overridden by a method D.m in D, and the + * erasure of the return type or argument types of D.m differs from + * the erasure of the corresponding types in C.m, a bridge method + * needs to be generated. + * + *
  • A bridge method also needs to be generated if C.m is not + * directly overridden in D, unless C.m is abstract. + *

  • + * The test works as follows. Debuggee contains several dummy superclasses + * and subclasses. Some of their methods fall under the rules above. + * Debugger verifies that the JDI Method.isBridge() returns true for all + * generated bridge methods and false for the non-bridge ones. + * The list of the class methods is obtained through the JDI + * ReferenceType.methods() which must return each method declared directly + * in this type including any synthetic methods created by the compiler. + */ +public class isbridge001 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.Method.isBridge.isbridge001t"; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final String[][][] methods = { +// nsk.jdi.Method.isBridge.isbridge001aa + {{"", + "()V", + "false", + "0"}, + {"isbridge001aMeth", + "(Ljava/lang/Double;)V", + "false", + "0"}}, + +// nsk.jdi.Method.isBridge.isbridge001bb + {{"", + "()V", + "false", + "0"}, + {"isbridge001bMeth", + "(Ljava/lang/Number;)Ljava/lang/Number;", + "false", + "0"}, + {"isbridge001bMeth2", + "(Ljava/lang/Number;I)V", + "false", + "0"}}, + +// nsk.jdi.Method.isBridge.isbridge001bb2 + {{"", + "()V", + "false", + "0"}, + {"isbridge001bMeth", + "(Ljava/lang/Byte;)Ljava/lang/Byte;", + "false", + "0"}, + {"isbridge001bMeth2", + "(Ljava/lang/Byte;I)V", + "false", + "0"}, + {"isbridge001bMeth", + "(Ljava/lang/Number;)Ljava/lang/Number;", + "true", + "0"}, + {"isbridge001bMeth2", + "(Ljava/lang/Number;I)V", + "true", + "0"}}, + +// nsk.jdi.Method.isBridge.isbridge001dd + {{"", + "()V", + "false", + "0"}}, + +// nsk.jdi.Method.isBridge.isbridge001dd2 + {{"", + "()V", + "false", + "0"}, + {"isbridge001dMeth", + "(Ljava/lang/Boolean;Ljava/lang/Character;)Ljava/lang/String;", + "false", + "0"}, + {"isbridge001dMeth", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + "true", + "0"}} + }; + + static final String[] classes = { + "nsk.jdi.Method.isBridge.isbridge001aa", + "nsk.jdi.Method.isBridge.isbridge001bb", + "nsk.jdi.Method.isBridge.isbridge001bb2", + "nsk.jdi.Method.isBridge.isbridge001dd", + "nsk.jdi.Method.isBridge.isbridge001dd2", + }; + + static final int CLS_NUM = classes.length; + + private IOPipe pipe; + private Log log; + private Debugee debuggee; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new isbridge001().runThis(argv, out); + } + + private int runThis(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "isbridge001t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + tot_res = Consts.TEST_FAILED; + log.complain("TEST BUG: unknown debuggee's command: " + + cmd); + return quitDebuggee(); + } + + for (int i=0; i>>>>> Class " + classes[i]); + if ((rType = debuggee.classByName(classes[i])) == null) { + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILURE: Method Debugee.classByName() returned null for " + + classes[i] + "\n"); + return quitDebuggee(); + } + try { + clsMethods = rType.methods(); + } catch (Exception e) { + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILURE: ReferenceType.methods: caught " + e + + "\n"); + return quitDebuggee(); + } + + Iterator iterator = clsMethods.iterator(); + while(iterator.hasNext()) { + Method meth = (Method) iterator.next(); + log.display("\t--> method " + meth + + "\n\t\tname " + meth.name() + + "\n\t\treturn type " + meth.returnTypeName() + + "\n\t\tsignature " + meth.signature()); + + int idx = findMethod(i, meth.signature()); + if (idx != -1) { + try { + int methCounter = Integer.parseInt(methods[i][idx][3]); + methCounter++; + methods[i][idx][3] = String.valueOf(methCounter); + } catch (NumberFormatException e) { + tot_res = Consts.TEST_FAILED; + log.complain("TEST BUG: Integer.parseInt: caught " + e); + return quitDebuggee(); + } + boolean bridge = new Boolean(methods[i][idx][2]); + if (bridge == meth.isBridge()) + log.display("\tCHECK PASSED: Method.isBridge() returns " + + meth.isBridge() + " as expected\n"); + else { + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: Method.isBridge() returns " + + meth.isBridge() + + "\n\tfor the method: " + meth.name() + + " " + meth.signature() + + "\n\tExpected: "+ methods[i][idx][2] + "\n"); + } + } + } + + log.display("<<<<<<"); + } + + for (int i=0; i { + T isbridge001bMeth(T a) { + return a; + } + + void isbridge001bMeth2(T b, int i) {} +} + +/* Test case 2: no bridge methods: the erasure of the return type/arguments + types of overridding methods are the same with the original ones. */ +class isbridge001bb extends isbridge001b { + Number isbridge001bMeth(Number a) { + return a; + } + + void isbridge001bMeth2(Number b, int i) {} +} + +/* Test case 3: bridge methods: the erasure of the return type/arguments + types of overridding methods are differ from the original ones. */ +class isbridge001bb2 extends isbridge001b { + Byte isbridge001bMeth(Byte a) { + return a; + } + + void isbridge001bMeth2(Byte b, int i) {} +} + +/* Test case 4 and classes isbridge001c/cc were removed. Bug id: 5083386 */ + +abstract class isbridge001d { + abstract C isbridge001dMeth(A a, B b); +} + +/* Test case 5: no bridge methods: non-overridden method of superclass + is abstract. */ +abstract class isbridge001dd extends isbridge001d {} + +/* Test case 6: bridge methods: overridden method of superclass + is abstract. */ +class isbridge001dd2 extends isbridge001d { + String isbridge001dMeth(Boolean a, Character b) { + return (String) "bridge"; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001.java new file mode 100644 index 00000000000..002947a1c4a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isConstructor; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.isConstructor()
    + * complies with its spec and its returned value is equal to
    + * true for a Method object returned by methodsByName("");
    + * and to false for other name.
    + */ + +public class isconstructor001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/isConstructor/isconstructor001", + sHeader2 = "--> isconstructor001: ", + sHeader3 = "##> isconstructor001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new isconstructor001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.isConstructor.isconstructor001a"; + + String mName = "nsk.jdi.Method.isConstructor"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("isconstructor001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".TestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(""); + if (methods.size() <= 0) { + log3("ERROR : methods.size() <= 0 for '' " + methods.size()); + testExitCode = FAILED; + break; + } + + Method testMethod = (Method) methods.get(0); + if (!testMethod.isConstructor()) { + log3("ERROR : method is not a constructor"); + testExitCode = FAILED; + break; + } + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("test2"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 for test2"); + testExitCode = FAILED; + break; + } + testMethod = (Method) methods.get(0); + if (testMethod.isConstructor()) { + log3("ERROR : test2 is a constructor"); + testExitCode = FAILED; + break; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001/TestDescription.java new file mode 100644 index 00000000000..9f010909138 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isConstructor/isconstructor001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.isConstructor() + * complies with its spec: + * public boolean isConstructor() + * Determine if this method is a constructor. + * Returns: true if the method is a constructor; false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.Method.isConstructor.isconstructor001; + * the debuggee program - nsk.jdi.Method.isConstructor.isconstructor001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isConstructor.isconstructor001 + * nsk.jdi.Method.isConstructor.isconstructor001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isConstructor.isconstructor001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001a.java new file mode 100644 index 00000000000..6e17ec9ffda --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isConstructor/isconstructor001a.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isConstructor; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the isconstructor001 JDI test. + */ + +public class isconstructor001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> isconstructor001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> isconstructor001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.isNative()
    + * complies with its spec and its returned value is equal to
    + * true for a class method declared as native and
    + * to false otherwise.
    + */ + +public class isnative001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/isNative/isnative001", + sHeader2 = "--> isnative001: ", + sHeader3 = "##> isnative001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new isnative001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.isNative.isnative001a"; + + String mName = "nsk.jdi.Method.isNative"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("isnative001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".TestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("test1"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 for test1"); + testExitCode = FAILED; + break; + } + Method testMethod = (Method) methods.get(0); + if (!testMethod.isNative()) { + log3("ERROR : test1 is not a native method"); + testExitCode = FAILED; + break; + } + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("test2"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 for test2"); + testExitCode = FAILED; + break; + } + testMethod = (Method) methods.get(0); + if (testMethod.isNative()) { + log3("ERROR : test2 is a native method"); + testExitCode = FAILED; + break; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001/TestDescription.java new file mode 100644 index 00000000000..2604ebf0467 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isNative/isnative001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * isNative. + * The test checks up that a result of the method + * com.sun.jdi.Method.isNative() + * complies with its spec: + * public boolean isNative() + * Determine if this method is native. + * Returns: true if the method is declared native; false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.Method.isNative.isnative001; + * the debuggee program - nsk.jdi.Method.isNative.isnative001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isNative.isnative001 + * nsk.jdi.Method.isNative.isnative001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isNative.isnative001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001a.java new file mode 100644 index 00000000000..e36d47b2b1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isNative/isnative001a.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isNative; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the isnative001 JDI test. + */ + +public class isnative001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> isnative001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> isnative001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.isObsolete()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * true if this method has been replaced by a non-equivalent
    + * method using VirtualMachine.redefineClasses(java.util.Map).
    + * The test checks that isObsolete() returns false if
    + * the tested method was redefined with itself
    + * which is certainly equivalent.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following .
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee loads the class to be redefined and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger + * - gets a Method object mirroring a method in the class,
    + * - checks that isObsolete() invoked on the object, returns false;
    + * - redefines the class;
    + * - checks again that isObsolete() invoked on the object,
    + * returns false.
    + *
    + * In third phase the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class isobsolete001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/isObsolete/isobsolete001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new isobsolete001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.isObsolete.isobsolete001a"; + + private static final int brkpLineNumber = 49; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + + debuggee = binder.bindToDebugee(debuggeeName); + + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + + if ( !vm.canRedefineClasses() ) { + log2("......vm.canRedefineClasses() == false : test is cancelled"); + vm.resume(); + return; + } + + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = debuggee.threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + + String className = "nsk.jdi.Method.isObsolete.isobsolete001b"; + String methodName = "m2"; + + ReferenceType redefClass = null; + + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + + redefClass = debuggee.classByName(className); + Method method = debuggee.methodByName(redefClass, methodName); + boolean isObs = method.isObsolete(); + + if (isObs) { + log3("ERROR: isObsolete() == true for m2 method before redefineClasses() invocation"); + testExitCode = FAILED; + } else + log2(" : isObsolete() == false for m2 method before redefineClasses() invocation "); + + // Create breakpoint request to have isobsolete002b.m2 on the top of the stack. + bpRequest = debuggee.makeBreakpoint(redefClass, methodName, brkpLineNumber); + bpRequest.addThreadFilter(mainThread); + bpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + bpRequest.putProperty("number", "one"); + bpRequest.enable(); + + // resuming after breakpoint for communication + vm.resume(); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) { + log2("......requested BreakpointEvent received;"); + if (mainThread.frame(0).location().method() == method) { + log2("......m2 method is on the top of the main thread stack;"); + } else { + log3("TEST ERROR: m2 method is not on the top of the main thread stack"); + testExitCode = FAILED; + } + } else { + log3("TEST ERROR: expected BreakpointEvent is not receieved"); + testExitCode = FAILED; + } + + try { + log2("......vm.redefineClasses(mapClassToBytes());"); + vm.redefineClasses(mapClassToBytes()); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + testExitCode = FAILED; + throw e; + } catch ( Error e ) { + log3("ERROR: Error: " + e); + testExitCode = FAILED; + throw e; + } + + log2("......getting: method = mainThread.frame(0).location().method();"); + method = mainThread.frame(0).location().method(); + log2("......getting: isObs = method.isObsolete();"); + isObs = method.isObsolete(); + if (isObs) { + log3("ERROR: method.isObsolete() == true for m2 method after redefineClasses() invocation"); + testExitCode = FAILED; + } else + log2(" : method.isObsolete() == false for m2 method after redefineClasses() invocation;"); + + break; + + default: + throw new JDITestRuntimeException ("** default case **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + + vm.resume(); + log1(" TESTING ENDS"); + return; + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + + private Map mapClassToBytes() + throws JDITestRuntimeException { + + byte []arrayToRedefine; + + log2("......getting: String[] args = argsHandler.getArguments();"); + String[] args = argsHandler.getArguments(); + if (args.length <= 0) { + log3("ERROR: args.length <= 0"); + testExitCode = FAILED; + throw new JDITestRuntimeException("** args.length <= 0 **"); + } + String testDir = args[0]; + log2("...... testDir = " + testDir); + + + String filePrefix = File.separator + "nsk" + + File.separator + "jdi" + + File.separator + "Method" + + File.separator + "isObsolete"; + + String fileToRedefineName = testDir + + File.separator + "newclass" + filePrefix + + File.separator + "isobsolete001b.class"; + + log2("...... fileToRedefineName=" + fileToRedefineName); + + try { + log2("......File fileToRedefine = new File(fileToRedefineName);"); + File fileToRedefine = new File(fileToRedefineName); + if (fileToRedefine.exists()) + log2(" fileToRedefine.exists()"); + else { + log3("ERROR: fileToRedefine doesn't exist"); + testExitCode = FAILED; + } + + if (testExitCode == FAILED) + throw new JDITestRuntimeException("** testExitCode == FAILED **"); + + int fileToRedefineLength = (int) fileToRedefine.length(); + log2(" fileToRedefineLength == " + fileToRedefineLength); + + FileInputStream inputFile = new FileInputStream(fileToRedefine); + arrayToRedefine = new byte[fileToRedefineLength]; + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch ( IOException e ) { + log3("ERROR: IOException: " + e); + throw new JDITestRuntimeException("** IOException **"); + } + + String testClassName = "nsk.jdi.Method.isObsolete.isobsolete001b"; + List classes = vm.classesByName(testClassName); + ReferenceType testClass = (ReferenceType) classes.get(0); + + HashMap mapForClass = new HashMap(); + mapForClass.put(testClass, arrayToRedefine); + + return mapForClass; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001/TestDescription.java new file mode 100644 index 00000000000..146d766c4b3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001/TestDescription.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isObsolete/isobsolete001. + * VM Testbase keywords: [jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.isObsolete() + * complies with its spec: + * public boolean isObsolete() + * Determine if this method is obsolete. + * Returns: true if this method has been replaced by + * a non-equivalent method using + * VirtualMachine.redefineClasses(java.util.Map). + * The test checks that isObsolete() returns false if + * the tested method was redefined with itself which is certainly equivalent. + * The test works as follows: + * The debugger program - nsk.jdi.Method.isObsolete.isobsolete001; + * the debuggee program - nsk.jdi.Method.isObsolete.isobsolete001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test suite contains + * the precompiled class file isobsolete001b.klass . + * Its source file is isobsolete001b.java . + * The test was modified die to fix of the bug: + * 4514956 Method.isObsolete() returns false for redefined method + * Test was updated according to rfe: + * 4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS. + * isobsolete001b.java was copied into newclass directory and the precompiled + * class file is created during test base build process. + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.makeBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isObsolete.isobsolete001 + * nsk.jdi.Method.isObsolete.isobsolete001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isObsolete.isobsolete001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001/newclass/isobsolete001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001/newclass/isobsolete001b.java new file mode 100644 index 00000000000..eeebf5b21ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001/newclass/isobsolete001b.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * This is the redefined class for the isobsolete001 JDI test. + */ +public class isobsolete001b { + + static final String prefix = "**> debuggee: "; + static Log log; + + isobsolete001b(Log log) { + this.log = log; + log.display(prefix + " This is the class to be redefined"); + } + + static int i1 = 0; + static int i2 = 0; + + static void m2() { + i1 = 1; + i2 = 1; // isobsolete001.brkpLineNumber + } + + static void m1() { + log.display(prefix + "redefined method: before: m2()"); + m2(); + log.display(prefix + "redefined method: after: m2()"); + log.display(prefix + "redefined method: value of i1 == " + i1); + log.display(prefix + "redefined method: value of i2 == " + i2); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001a.java new file mode 100644 index 00000000000..c2559e7a5d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the isobsolete001 JDI test. + */ + +public class isobsolete001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static isobsolete001b objRF1; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + objRF1 = new isobsolete001b(log); + methodForCommunication(); + objRF1.m1(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001b.java new file mode 100644 index 00000000000..aa1a150abb5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001b.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * This is the redefined class for the isobsolete001 JDI test. + */ +public class isobsolete001b { + + static final String prefix = "**> debuggee: "; + static Log log; + + isobsolete001b(Log log) { + this.log = log; + log.display(prefix + " This is the class to be redefined"); + } + + static int i1 = 0; + static int i2 = 0; + + static void m2() { + i1 = 1; + i2 = 1; // isobsolete001.brkpLineNumber + } + + static void m1() { + log.display(prefix + "redefined method: before: m2()"); + m2(); + log.display(prefix + "redefined method: after: m2()"); + log.display(prefix + "redefined method: value of i1 == " + i1); + log.display(prefix + "redefined method: value of i2 == " + i2); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java new file mode 100644 index 00000000000..9ccedf98133 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.isObsolete()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * true if this method has been replaced by a non-equivalent
    + * method using VirtualMachine.redefineClasses(java.util.Map).
    + * The test checks that isObsolete() returns true if
    + * the body of the tested method was fully replaced.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * the debugger and the debuggee perform the following .
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee loads the class to be redefined and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger + * - gets a Method object mirroring a method in the class,
    + * - checks that isObsolete() invoked on the object, returns false;
    + * - redefines the class;
    + * - checks again that isObsolete() invoked on the object,
    + * returns true.
    + *
    + * In third phase the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class isobsolete002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/isObsolete/isobsolete002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new isobsolete002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.isObsolete.isobsolete002a"; + + private static final int brkpLineNumber = 49; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + + debuggee = binder.bindToDebugee(debuggeeName); + + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + + if ( !vm.canRedefineClasses() ) { + log2("......vm.canRedefineClasses() == false : test is cancelled"); + vm.resume(); + return; + } + + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + ThreadReference mainThread = debuggee.threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + + String className = "nsk.jdi.Method.isObsolete.isobsolete002b"; + String methodName = "m2"; + + ReferenceType redefClass = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + + log2("......getting: redefClass = debuggee.classByName(className);"); + redefClass = debuggee.classByName(className); + + log2("......getting: Method method = debuggee.methodByName(redefClass, methodName);"); + Method method = debuggee.methodByName(redefClass, methodName); + log2("......getting: boolean isObs = method.isObsolete();"); + boolean isObs = method.isObsolete(); + + if (isObs) { + log3("ERROR: isObsolete() == true for m2 method before redefineClasses() invocation"); + testExitCode = FAILED; + } else + log2(" : isObsolete() == false for m2 method before redefineClasses() invocation"); + + // Create breakpoint request to have isobsolete002b.m2 on the top of the stack. + bpRequest = debuggee.makeBreakpoint(redefClass, methodName, brkpLineNumber); + bpRequest.addThreadFilter(mainThread); + bpRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + bpRequest.putProperty("number", "one"); + bpRequest.enable(); + + // resuming after breakpoint for communication + vm.resume(); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) { + log2("......requested BreakpointEvent received;"); + if (mainThread.frame(0).location().method() == method) { + log2("......m2 method is on the top of the main thread stack;"); + } else { + log3("TEST ERROR: m2 method is not on the top of the main thread stack"); + testExitCode = FAILED; + } + } else { + log3("TEST ERROR: expected BreakpointEvent is not receieved"); + testExitCode = FAILED; + } + + try { + log2("......vm.redefineClasses(mapClassToBytes());"); + vm.redefineClasses(mapClassToBytes()); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + testExitCode = FAILED; + throw e; + } catch ( Error e ) { + log3("ERROR: Error: " + e); + testExitCode = FAILED; + throw e; + } + + log2("......getting: method = mainThread.frame(0).location().method();"); + method = mainThread.frame(0).location().method(); + log2("......getting: isObs = method.isObsolete();"); + isObs = method.isObsolete(); + if (isObs) { + log2(" : isObsolete() == true for m2 method after redefineClasses() invocation;"); + } else { + log3("ERROR: isObsolete() == false for m2 method after redefineClasses() invocation"); + testExitCode = FAILED; + } + break; + + default: + throw new JDITestRuntimeException ("** default case **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + + vm.resume(); + log1(" TESTING ENDS"); + return; + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + + private Map mapClassToBytes() + throws JDITestRuntimeException { + + byte []arrayToRedefine; + + log2("......getting: String[] args = argsHandler.getArguments();"); + String[] args = argsHandler.getArguments(); + if (args.length <= 0) { + log3("ERROR: args.length <= 0"); + testExitCode = FAILED; + throw new JDITestRuntimeException("** args.length <= 0 **"); + } + String testDir = args[0]; + log2("...... testDir = " + testDir); + + + String filePrefix = File.separator + "nsk" + + File.separator + "jdi" + + File.separator + "Method" + + File.separator + "isObsolete"; + + String fileToRedefineName = testDir + + File.separator + "newclass" + filePrefix + + File.separator + "isobsolete002b.class"; + + log2("...... fileToRedefineName=" + fileToRedefineName); + + try { + log2("......File fileToRedefine = new File(fileToRedefineName);"); + File fileToRedefine = new File(fileToRedefineName); + if (fileToRedefine.exists()) + log2(" fileToRedefine.exists(); length == " + fileToRedefine.length()); + else { + log3("ERROR: fileToRedefine doesn't exist"); + testExitCode = FAILED; + } + + if (testExitCode == FAILED) + throw new JDITestRuntimeException("** testExitCode == FAILED **"); + + FileInputStream inputFile = new FileInputStream(fileToRedefine); + arrayToRedefine = new byte[(int) fileToRedefine.length()]; + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch ( IOException e ) { + log3("ERROR: IOException: " + e); + throw new JDITestRuntimeException("** IOException **"); + } + + String testClassName = "nsk.jdi.Method.isObsolete.isobsolete002b"; + List classes = vm.classesByName(testClassName); + ReferenceType testClass = (ReferenceType) classes.get(0); + + HashMap mapForClass = new HashMap(); + mapForClass.put(testClass, arrayToRedefine); + + return mapForClass; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002/TestDescription.java new file mode 100644 index 00000000000..7e9e242e8c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isObsolete/isobsolete002. + * VM Testbase keywords: [jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.isObsolete() + * complies with its spec: + * public boolean isObsolete() + * Determine if this method is obsolete. + * Returns: true if this method has been replaced by + * a non-equivalent method using + * VirtualMachine.redefineClasses(java.util.Map). + * The test checks that isObsolete() returns true if + * the body of the tested method has been fully replaced. + * The test works as follows: + * The debugger program - nsk.jdi.Method.isObsolete.isobsolete002; + * the debuggee program - nsk.jdi.Method.isObsolete.isobsolete002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test suite contains + * the precompiled class file isobsolete002b.klass . + * Its source file is isobsolete002b.ja . + * The test was modified die to fix of the bug: + * 4514956 Method.isObsolete() returns false for redefined method + * Test was updated according to rfe: + * 4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS. + * isobsolete002b.ja was moved into newclass directory and renamed + * to isobsolete002b.java. + * The precompiled class file is created during test base build process. + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.makeBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isObsolete.isobsolete002 + * nsk.jdi.Method.isObsolete.isobsolete002a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isObsolete.isobsolete002 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002/newclass/isobsolete002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002/newclass/isobsolete002b.java new file mode 100644 index 00000000000..7cb9493d8a3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002/newclass/isobsolete002b.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * This is the redefining class for the isobsolete002 JDI test. + */ +public class isobsolete002b { + + static final String prefix = "**> debuggee: "; + static Log log; + + isobsolete002b(Log log) { + this.log = log; + log.display(prefix + " This is the class to redefine"); + } + + static int i1 = 0; + static int i2 = 0; + + static void m2() { + boolean b1 = true; + log.display(prefix + "redefining method: b1 " + b1); // isobsolete001.brkpLineNumber + } + + static void m1() { + log.display(prefix + "method m1: before m2()"); + m2(); + log.display(prefix + "method m1: after m2()"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002a.java new file mode 100644 index 00000000000..753b9911335 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the isobsolete002 JDI test. + */ + +public class isobsolete002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static isobsolete002b objRF1; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + objRF1 = new isobsolete002b(log); + methodForCommunication(); + objRF1.m1(); + break ; + + //------------------------------------------------- standard end section + + default: + log1("Call m1 method again to show that class is redefined."); + objRF1.m1(); + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002b.java new file mode 100644 index 00000000000..f3968ca1fab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002b.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * This is the redefined class for the isobsolete002 JDI test. + */ +public class isobsolete002b { + + static final String prefix = "**> debuggee: "; + static Log log; + + isobsolete002b(Log log) { + this.log = log; + log.display(prefix + " This is the class to be redefined"); + } + + static int i1 = 0; + static int i2 = 0; + + static void m2() { + i1 = 1; + i2 = 1; // isobsolete001.brkpLineNumber + } + + static void m1() { + log.display(prefix + "method m1: before m2()"); + m2(); + log.display(prefix + "method m1: after m2()"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003.java new file mode 100644 index 00000000000..c6328ad8a3d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003.java @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import java.io.*; +import java.util.*; + +/** + */ +public class isobsolete003 { + + private final static String prefix = "nsk.jdi.Method.isObsolete"; + private final static String className = ".isobsolete003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + private final static int brkpMainLineNumber = 48; + private final static int brkpFooLineNumber = 33; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static VirtualMachine vm; + private static ReferenceType debuggeeClass; + + private static EventRequestManager eventRManager; + private static EventSet eventSet; + private static EventIterator eventIterator; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + + Binder binder = new Binder(argHandler, log); + debuggee = binder.bindToDebugee(debuggeeName); + debuggee.redirectStderr(log, "debuggee > "); + debuggee.createIOPipe(); + eventRManager = debuggee.getEventRequestManager(); + + vm = debuggee.VM(); + eventRManager = vm.eventRequestManager(); + + waitForDebuggeeClassPrepared(); + + if (vm.canRedefineClasses()) { + + execTest(); + + debuggee.resume(); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) { + display("Waiting for the debuggee's finish..."); + debuggee.waitFor(); + + display("Getting the debuggee's exit status."); + int status = debuggee.getStatus(); + if (status != (Consts.TEST_PASSED + Consts.JCK_STATUS_BASE)) { + complain("Debuggee returned UNEXPECTED exit status: " + status); + exitStatus = Consts.TEST_FAILED; + } + } else { + throw new TestBug("Last event is not the VMDeathEvent"); + } + + } else { + display("vm.canRedefineClasses() == false : test is cancelled"); + vm.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } catch (VMDisconnectedException e) { + exitStatus = Consts.TEST_FAILED; + complain("The test cancelled due to VMDisconnectedException."); + e.printStackTrace(out); + display("Trying: vm.process().destroy();"); + if (vm != null) { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } + + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + complain("The test has not finished normally. Forcing: vm.exit()."); + if (vm != null) { + vm.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + debuggee.resume(); + getEventSet(); + } + + return exitStatus; + } + + + private static void execTest() { + + ThreadReference mainThread = debuggee.threadByName("main"); + + // Set first breakpoint to have isobsolete003b class loaded. + BreakpointRequest bpRequest = debuggee.makeBreakpoint(debuggeeClass, "main", brkpMainLineNumber); + bpRequest.addThreadFilter(mainThread); + bpRequest.addCountFilter(1); + bpRequest.enable(); + + waitForEvent(bpRequest); + bpRequest.disable(); + + // At this point isobsolete003b class should be loaded in debuggee. + String redefName = prefix + ".isobsolete003b"; + + ReferenceType redefClass = debuggee.classByName(redefName); + if (redefClass == null) { + throw new TestBug(redefName + "is not found in debuggee."); + } + + String methodName = "foo"; + Method method = (Method) redefClass.methodsByName(methodName).get(0); + + // save some values for check in future + Method oldMethod = method; + Location oldLocation = method.location(); + long oldCodeIndex = oldLocation.codeIndex(); + String oldRetTypeName = method.returnTypeName(); + int oldHashCode = method.hashCode(); + + // Set new breakpoint to have isobsolete003b.foo() method on stack before redefinition. + bpRequest = debuggee.makeBreakpoint(redefClass, methodName, brkpFooLineNumber); + bpRequest.addThreadFilter(mainThread); + bpRequest.addCountFilter(1); + bpRequest.enable(); + + waitForEvent(bpRequest); + bpRequest.disable(); + + display("requested BreakpointEvent for foo() method received;"); + try { + if (!mainThread.frame(0).location().method().equals(method)) { + throw new TestBug("foo() method is not on the top of the main thread stack"); + } + } catch (IncompatibleThreadStateException e) { + throw new Failure("Unexpected IncompatibleThreadStateException while comparing mainThread.frame(0).location().method(): " + e.getMessage()); + } + + display("Making redefineClasses(mapClassToBytes())."); + vm.redefineClasses(mapClassToBytes()); + + // Check isObsolete after redefinition + try { + method = mainThread.frame(0).location().method(); + } catch (IncompatibleThreadStateException e) { + throw new Failure("Unexpected IncompatibleThreadStateException while getting mainThread.frame(0).location().method(): " + e.getMessage()); + } + if (!method.isObsolete()) { + complain("method.isObsolete() == true for foo() method after redefineClasses()"); + exitStatus = Consts.TEST_FAILED; + } else { + // Do other checks for obsolete method. + + if (method.equals(oldMethod)) { + complain("equals(oldMethod) returned true for obsolete method."); + exitStatus = Consts.TEST_FAILED; + } + + List l = null; + Location loc = null; + try { + l = method.allLineLocations(); + if (l.size() > 0) { + complain("allLineLocations() returned a list with non-zero size for obsolete method." + + "Number of Locations :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + } catch (AbsentInformationException e) { + // it is expected + } + + try { + l = method.allLineLocations(vm.getDefaultStratum(), null); + if (l.size() > 0) { + complain("allLineLocations(vm.getDefaultStratum(), null) returned a list with non-zero size for obsolete method." + + "Number of Locations :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + } catch (AbsentInformationException e) { + // it is expected + } + + try { + l = method.locationsOfLine(1); + if (l.size() > 0) { + complain("locationsOfLine(1) returned a list with non-zero size for obsolete method." + + "Number of Locations :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + } catch (AbsentInformationException e) { + // it is expected + } + + try { + l = method.locationsOfLine(vm.getDefaultStratum(), null, 1); + if (l.size() > 0) { + complain("locationsOfLine(vm.getDefaultStratum(), null, 1) returned a list with non-zero size for obsolete method." + + "Number of Locations :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + } catch (AbsentInformationException e) { + // it is expected + } + + try { + l = method.arguments(); + if (l.size() > 0) { + complain("arguments() returned a list with non-zero size for obsolete method." + + "Size of list :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + } catch (AbsentInformationException e) { + // it is expected + } + + l = method.argumentTypeNames(); + if (l.size() > 0) { + complain("argumentTypeNames() returned a list with non-zero size for obsolete method." + + "Size of list :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + + try { + l = method.argumentTypes(); + if (l.size() > 0) { + complain("argumentsTypes() returned a list with non-zero size for obsolete method." + + "Size of list :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + } catch (ClassNotLoadedException e) { + // it is expected + } + + try { + l = method.variables(); + if (l.size() > 0) { + complain("variables() returned a list with non-zero size for obsolete method." + + "Size of list :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + } catch (AbsentInformationException e) { + // it is expected + } + + try { + l = method.variablesByName("dummyInt"); + if (l.size() > 0) { + complain("variablesByName(oldVar.name()) returned a list with non-zero size for obsolete method." + + "Size of list :" + l.size()); + exitStatus = Consts.TEST_FAILED; + } + } catch (AbsentInformationException e) { + // it is expected + } + + byte[] b = method.bytecodes(); + if (b.length > 0) { + complain("bytecodes() returned an array with non-zero length for obsolete method." + + "Number of bytes :" + b.length); + exitStatus = Consts.TEST_FAILED; + } + + loc = method.location(); + if (loc != null && loc == oldLocation) { + complain("location() returned old location for obsolete method."); + exitStatus = Consts.TEST_FAILED; + } + + loc = method.locationOfCodeIndex(oldCodeIndex); + if (loc != null) { + complain("locationOfCodeIndex(oldCodeIndex) returned not-null location for obsolete method."); + exitStatus = Consts.TEST_FAILED; + } + + String rtName = method.returnTypeName(); + if (rtName.equals(oldRetTypeName)) { + complain("returnTypeName() returned an old string for obsolete method: " + rtName); + exitStatus = Consts.TEST_FAILED; + } + + try { + Type rType = method.returnType(); + if (rType != null) { + complain("returnType() returned not-null Type for obsolete method: " + rType.name()); + exitStatus = Consts.TEST_FAILED; + } + } catch (ClassNotLoadedException e) { + // it is expected + } + + int hashCode = method.hashCode(); + if (hashCode == oldHashCode) { + complain("hashCode() returned old value for obsolete method: " + hashCode); + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + /** + * Returns Map object for redefinition. + * + */ + private static Map mapClassToBytes() { + String[] args = argHandler.getArguments(); + if (args.length <= 0) { + throw new Failure("mapClassToBytes(): Test arguments are not found."); + } + + String testDir = args[0]; + display("Test current dir = " + testDir); + + String filePrefix = File.separator + "nsk" + + File.separator + "jdi" + + File.separator + "Method" + + File.separator + "isObsolete"; + + String fileToRedefineName = testDir + + File.separator + "newclass" + filePrefix + + File.separator + "isobsolete003b.class"; + + display("fileToRedefineName : " + fileToRedefineName); + + byte[] arrayToRedefine; + try { + File fileToRedefine = new File(fileToRedefineName); + if (!fileToRedefine.exists()) { + throw new Failure("mapClassToBytes(): fileToRedefine does not exist"); + } + + FileInputStream inputFile = new FileInputStream(fileToRedefine); + arrayToRedefine = new byte [(int) fileToRedefine.length()]; + inputFile.read(arrayToRedefine); + inputFile.close(); + + } catch (IOException e) { + complain("unexpected IOException: " + e); + throw new Failure(e); + } + + String testClassName = prefix + ".isobsolete003b"; + ReferenceType testClass = debuggee.classByName(testClassName); + + HashMap mapForClass = new HashMap(); + mapForClass.put(testClass, arrayToRedefine); + + return mapForClass; + } + + private static Event waitForEvent (EventRequest evRequest) { + + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else if (curEvent.request().equals(evRequest)) { + display("Requested event received."); + resultEvent = curEvent; + break; + } else { + throw new TestBug("Unexpected Event received: " + curEvent.toString()); + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + private static void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + private static void waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + debuggeeClass = event.referenceType(); + if (!debuggeeClass.name().equals(debuggeeName)) + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/TestDescription.java new file mode 100644 index 00000000000..492609bc797 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/TestDescription.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isObsolete/isobsolete003. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks the following assertions: + * if Method object is obsolete, then + * - all method of Method class which are specified to return the List, + * must return zero size list or throw AbsentInformationException, + * - bytecodes() method must return empty array, + * - location() method can not return Location equal to one + * before redefinition, + * - locationOfCodeIndex(long codeIndex) method must return null, + * - returnTypeName() method can not return String equal to one + * before redefinition, + * - returnType() method must return null or throw ClassNotLoadedException, + * - hashCode() method can not return int value equal to one before + * redefinition. + * The debugger program - nsk.jdi.Method.isObsolete.isobsolete003; + * the debuggee program - nsk.jdi.Method.isObsolete.isobsolete003a; + * the class to be redefined - nsk.jdi.Method.isObsolete.isobsolete003b. + * The test contains the precompiled class file isobsolete003b.klass . + * Its source file is isobsolete003b.java.rdf and presents class which + * redefines isobsolete003b class. + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * Upon getting the debuggee VM started, the debugger creates the special + * requests for event when isobsolete003a class is prepared and for event + * when isobsolete003b is load into debuggee VM. This actions are needed + * to take return values on some methods for further comparisons. + * Then debugger creates breakpoint request at line of 'isobsolete003b.foo()' + * method and resumes debuggee. After receiving of requested breakpoint event, + * the debuggee's main thread is suspended and 'foo()' method is at its top + * frame.. At this moment, the debugger redefines isobsolete003b class. + * The isobsolete003b.klass which redefines isobsolete003b class, contains + * non-equivalent version of 'foo()' method. Thus, after redefinition, + * new mirror of 'foo()' method is obsolete. After this, the debugger performs + * the checks of assertions listed above. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the method which were not yet covered by previous tests for isObsolete() + * method. The coverage analysis was done for jdk1.4.0-b92 build. + * Test was updated according to rfe: + * 4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS. + * isobsolete003b.java.rdf was moved into newclass directory and renamed + * to isobsolete003b.java. + * The precompiled class file is created during test base build process. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.makeBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isObsolete.isobsolete003 + * nsk.jdi.Method.isObsolete.isobsolete003a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isObsolete.isobsolete003 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/newclass/isobsolete003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/newclass/isobsolete003b.java new file mode 100644 index 00000000000..935c873cea3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/newclass/isobsolete003b.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Method.isObsolete; + +/** + * This is the redefining class for isobsolete003 JDI test. + */ +public class isobsolete003b { + + static Integer foo(int i) { + Integer j = null; + try { + j = new Integer(new String(String.valueOf(i))); + } catch (NumberFormatException e) { + } + return j; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003a.java new file mode 100644 index 00000000000..be4a6004411 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003a.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Method.isObsolete; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * The debugged application of the test. + */ +public class isobsolete003a { + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + isobsolete003b.foo(1); + isobsolete003b.foo(2); // isobsolete003.brkpMainLineNumber + + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003b.java new file mode 100644 index 00000000000..33145ec4c48 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003b.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Method.isObsolete; + +// THIS TEST IS LINE NUMBER SENSITIVE +/** + * This is the class to be redefined for isobsolete003 JDI test. + */ +public class isobsolete003b { + + static Integer foo(int i) { + int dummyInt = i; + return new Integer(i); // isobsolete003.brkpFooLineNumber + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001.java new file mode 100644 index 00000000000..5b062b0f217 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isStaticInitializer; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.isStaticInitializer()
    + * complies with its spec and its returned value is equal to
    + * true for a Method object returned by methodsByName("");
    + * and to false for other name.
    + */ + +public class isstinitializer001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/isStaticInitializer/isstinitializer001", + sHeader2 = "--> isstinitializer001: ", + sHeader3 = "##> isstinitializer001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new isstinitializer001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.isStaticInitializer.isstinitializer001a"; + + String mName = "nsk.jdi.Method.isStaticInitializer"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("isstinitializer001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".TestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName(""); + if (methods.size() <= 0) { + log3("ERROR : methods.size() <= 0 for '' " + methods.size()); + testExitCode = FAILED; + break; + } + + Method testMethod = (Method) methods.get(0); + if (!testMethod.isStaticInitializer()) { + log3("ERROR : method is not an initializer"); + testExitCode = FAILED; + break; + } + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("test2"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 for test2"); + testExitCode = FAILED; + break; + } + testMethod = (Method) methods.get(0); + if (testMethod.isStaticInitializer()) { + log3("ERROR : test2 is an initializer"); + testExitCode = FAILED; + break; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001/TestDescription.java new file mode 100644 index 00000000000..9f275d1ab48 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isStaticInitializer/isstinitializer001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.isStaticInitializer() + * complies with its spec: + * public boolean isStaticInitializer() + * Determine if this method is a static initializer. + * Returns: true if the method is a static initializer; false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.Method.isStaticInitializer.isstinitializer001; + * the debuggee program - nsk.jdi.Method.isStaticInitializer.isstinitializer001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isStaticInitializer.isstinitializer001 + * nsk.jdi.Method.isStaticInitializer.isstinitializer001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isStaticInitializer.isstinitializer001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001a.java new file mode 100644 index 00000000000..6cc5df63ccc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isStaticInitializer/isstinitializer001a.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isStaticInitializer; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the isstinitializer001 JDI test. + */ + +public class isstinitializer001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> isstinitializer001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> isstinitializer001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.isSynchronized()
    + * complies with its spec and its returned value is equal to
    + * true for a class method declared as synchronized and to
    + * false otherwise.
    + */ + +public class issynchronized001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/isSynchronized/issynchronized001", + sHeader2 = "--> issynchronized001: ", + sHeader3 = "##> issynchronized001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new issynchronized001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.isSynchronized.issynchronized001a"; + + String mName = "nsk.jdi.Method.isSynchronized"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issynchronized001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".TestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("test1"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 for test1"); + testExitCode = FAILED; + break; + } + Method testMethod = (Method) methods.get(0); + if (!testMethod.isSynchronized()) { + log3("ERROR : test1 is not a synchronized method"); + testExitCode = FAILED; + break; + } + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("test2"); + if (methods.size() != 1) { + log3("ERROR : methods.size() != 1 for test2"); + testExitCode = FAILED; + break; + } + testMethod = (Method) methods.get(0); + if (testMethod.isSynchronized()) { + log3("ERROR : test2 is a synchronized method"); + testExitCode = FAILED; + break; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001/TestDescription.java new file mode 100644 index 00000000000..3e8f9d36eb4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isSynchronized/issynchronized001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.isSynchronized() + * complies with its spec: + * public boolean isSynchronized() + * Determine if this method is synchronized. + * Returns: true if the method is declared synchronized; false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.Method.isSynchronized.issynchronized001; + * the debuggee program - nsk.jdi.Method.isSynchronized.issynchronized001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isSynchronized.issynchronized001 + * nsk.jdi.Method.isSynchronized.issynchronized001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isSynchronized.issynchronized001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001a.java new file mode 100644 index 00000000000..83d7ff8f19c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isSynchronized/issynchronized001a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.isSynchronized; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the isSynchronized001 JDI test. + */ + +public class issynchronized001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> issynchronized001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> issynchronized001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + private static void failure(String msg) { + complain(msg); + exitStatus = Consts.TEST_FAILED; + } + + public static int run(String argv[], PrintStream out) { + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + failure("Class '" + debuggeeName + "' not found."); + } + + execTest(); + debuggee.quit(); + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + String expMethodName = "foo"; + + List methods = debuggeeClass.methodsByName(expMethodName); + if (methods.size() != 3) { + failure("Found unexpected number of method " + expMethodName + " : " + methods.size()); + } + Iterator it = methods.iterator(); + while (it.hasNext()) { + Method method = it.next(); + if (method.isVarArgs()) { + display("Method.isVarArgs() returned expected true for method " + expMethodName); + display("\t signature:" + method.signature()); + } else { + complain("Method.isVarArgs() returned unexpected false for method " + expMethodName); + complain("\t signature:" + method.signature()); + exitStatus = Consts.TEST_FAILED; + } + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001/TestDescription.java new file mode 100644 index 00000000000..77491f47832 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/isVarArgs/isvarargs001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isVarArgs() method of Method interface. + * The test checks if the method returns true for any + * mirrored method which has varargs argument. + * The test consists of a debugger program (isvarargs001.java) + * and debuggee application (isvarargs001a.java). + * Package name is nsk.jdi.Method.isVarArgs . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger finds mirrors of debuggee's methods 'foo' + * which have varargs argument and calls isVarArgs() method + * for each found method mirror. The test fails if false is + * returned once or more. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.isVarArgs.isvarargs001 + * nsk.jdi.Method.isVarArgs.isvarargs001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.isVarArgs.isvarargs001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001a.java new file mode 100644 index 00000000000..2b43abe0dda --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isVarArgs/isvarargs001a.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.Method.isVarArgs; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isvarargs001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isvarargs001.SIGNAL_READY); + receiveSignal(isvarargs001.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific methods + + static String foo (int... args) { + return "1"; + } + + static String foo (Integer... args) { + return "2"; + } + + static String foo (String s, String... args) { + return "3"; + } +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001.java new file mode 100644 index 00000000000..94a9e7f4c57 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.locationOfCodeIndex; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.locationOfCodeIndex()
    + * complies with its spec for non-abstract, non-native method.
    + * The test works as follows.
    + * In a debuggee, a TestClass contains a "testedmethod".
    + * After getting a mirror of the testedmethod, a debugger gets
    + * a List allLineLocations containing executable lines of
    + * the method, and performs a loop on the List, in which it
    + * each element in the List is equal to a Location object
    + * getting with call to the method locationOfCodeIndex().
    + * Since the method allLineLocations returnes a list of executable
    + * lines the check that the method locationOfCodeIndex()
    + * doesn't return null is also perfomed.
    + */ + +public class locationofcodeindex001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new locationofcodeindex001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.locationOfCodeIndex.locationofcodeindex001a"; + + private String testedClassName = + "nsk.jdi.Method.locationOfCodeIndex.TestClass"; + + //String mName = "nsk.jdi.Method.locationOfCodeIndex"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testedMethod = "testedmethod"; + + List methods = null; + Method m = null; + List locations = null; + + log2(" getting: List classes = vm.classesByName(testedClassName);"); + List classes = vm.classesByName(testedClassName); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2(" getting a tested method object 'm'"); + methods = ((ReferenceType) classes.get(0)).methodsByName(testedMethod); + m = (Method) methods.get(0); + + log2("......locations = m.allLineLocations(); no AbsentInformationException is expected"); + try { + locations = m.allLineLocations(); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + log2("......checking up on a value of locations.size(); 0 is not expected"); + if (locations.size() == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + log2(" getting: ListIterator li = locations.listIterator();"); + ListIterator li = locations.listIterator(); + + Location loc1 = null; + Location loc2 = null; + long codeIndex; + + log2("......loop of testing elements in allLineLocations"); + for (int ifor = 1; li.hasNext(); ifor++) { + loc1 = (Location) li.next(); + codeIndex = loc1.codeIndex(); + loc2 = m.locationOfCodeIndex(codeIndex); + if (loc2 == null) { + log3("ERROR: a location in allLineLocations == null; element in List: " + ifor); + testExitCode = FAILED; + } else { + if (!loc2.equals(loc1)) { + log3("ERROR: !loc2.equals(loc1); element in List: " + ifor); + testExitCode = FAILED; + } + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001/TestDescription.java new file mode 100644 index 00000000000..369c7017b06 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.locationOfCodeIndex() + * complies with its spec: + * public Location locationOfCodeIndex(long codeIndex) + * Returns a Location for the given code index. + * Returns: the Location corresponding to the given code index or null if + * the specified code index is not a valid code index for this method + * (native and abstract methods will always return null). + * when a tested method is not a native or abstract. + * The test works as follows: + * The debugger program - nsk.jdi.Method.locationOfCodeIndex.locationofcodeindex001; + * the debuggee program - nsk.jdi.Method.locationOfCodeIndex.locationofcodeindex001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * In general, this test is potentially option depended + * since its spec states since it uses the method + * Method.allLineLocations. + * Hence it also needs to be compiled with the option + * JAVAC_OPTS=-g + * in the locationofcodeindex001.cfg file. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.locationOfCodeIndex.locationofcodeindex001 + * nsk.jdi.Method.locationOfCodeIndex.locationofcodeindex001a + * + * @comment make sure locationofcodeindex001a is compiled with full debug info + * @clean nsk.jdi.Method.locationOfCodeIndex.locationofcodeindex001a + * @compile -g:lines,source,vars ../locationofcodeindex001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.locationOfCodeIndex.locationofcodeindex001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001a.java new file mode 100644 index 00000000000..c3fa374b746 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationOfCodeIndex/locationofcodeindex001a.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.locationOfCodeIndex; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the locationofcodeindex001 JDI test. + */ + +public class locationofcodeindex001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> locationofcodeindex001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> locationofcodeindex001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.locationsOfLine()
    + * complies with its spec for non-abstract, non-native method.
    + * The test checks up that for each line in the List returned
    + * by the method Method.allLineLocations(), call to the method
    + * Method.locationsOfLine(lineNumber) returns
    + * non-empty List object in which
    + * each object is a Location object.
    + * Not throwing AbsentInformationException or
    + * InvalidLineNumberException
    + * is checked up as well.
    + */ + +public class locationsofline001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/locationsOfLine/locationsofline001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new locationsofline001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.locationsOfLine.locationsofline001a"; + + String mName = "nsk.jdi.Method.locationsOfLine"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List methods = null; + Method m = null; + List locations = null; + + + log2(" getting: List classes = vm.classesByName(mName + '.TestClass');"); + List classes = vm.classesByName(mName + ".TestClass"); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2(" getting a tested method object 'm'"); + methods = ((ReferenceType) classes.get(0)).methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + + log2("......locations = m.allLineLocations(); no AbsentInformationException is expected"); + try { + locations = m.allLineLocations(); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + + log2("......checking up on a value of locations.size(); 0 is not expected"); + int size = locations.size(); + if (size == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + ListIterator li1 = locations.listIterator(); + + log2(" the loop of checking locations in the returned list; neither AbsentInformationException no InvalidLineNumberException is expected"); + + label1: + for (int ifor1 = 0; ifor1 < size; ifor1++) { + + int lineNumber = ((Location) li1.next()).lineNumber(); + + try { + log2("......List lineLocations = m.locationsOfLine(" + lineNumber + ");"); + List lineLocations = m.locationsOfLine(lineNumber); + int size1 = lineLocations.size(); + if (size1 == 0) { + testExitCode = FAILED; + log3("ERROR: lineLocations.size() == 0"); + break label1; + } + ListIterator li2 = lineLocations.listIterator(); + try { + for (; li2.hasNext(); ) { + Location loc = (Location) li2.next(); + } + } catch ( ClassCastException e) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + break label1; + } + + } catch ( InvalidLineNumberException e1 ) { + testExitCode = FAILED; + log3("ERROR: InvalidLineNumberException"); + break label1; + } catch ( AbsentInformationException e2 ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break label1; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001/TestDescription.java new file mode 100644 index 00000000000..1f649e3c15b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001/TestDescription.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/locationsOfLine/locationsofline001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.locationsOfLine() + * complies with its spec: + * public java.util.List locationsOfLine(int lineNumber) + * throws AbsentInformationException + * Returns a list containing each Location that maps to the given line. + * The returned list will contain a location for each disjoint range of code + * indices that have been assigned to the given line by the compiler and/or VM. + * Each returned location corresponds to the beginning of this range. + * Parameters: lineNumber - the line number + * Returns: a List of Location objects that map to the given line number. + * Throws: AbsentInformationException - + * if there is no line number information for this method. + * InvalidLineNumberException - + * if there is no executable code in this method associated with + * the given line. + * when a tested method is non-native, non-abstract and + * when neither InvalidLineNumberException + * no AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.locationsOfLine.locationsofline001; + * the debuggee program - nsk.jdi.Method.locationsOfLine.locationsofline001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * In general, this test is potentially option depended + * since its spec states: + * Throws: AbsentInformationException - + * if there is no line number information for this method. + * However, unlike some tests that need to be compiled with the option + * JAVAC_OPTS=-g + * (method.arguments(), method.variables() and method.variablesByName) + * at the date of implementing the test, + * javac prepares full information for the test without the option. + * Nonetheless, the locationsofline002.cfg file contains the option + * in order to avoid possible failures in future in case of any changes + * in javac. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.locationsOfLine.locationsofline001 + * nsk.jdi.Method.locationsOfLine.locationsofline001a + * + * @comment make sure locationsofline001a is compiled with full debug info + * @clean nsk.jdi.Method.locationsOfLine.locationsofline001a + * @compile -g:lines,source,vars ../locationsofline001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.locationsOfLine.locationsofline001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001a.java new file mode 100644 index 00000000000..6402eb1b046 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine/locationsofline001a.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.locationsOfLine; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the locationsofline001 JDI test. + */ + +public class locationsofline001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> locationsofline001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> locationsofline001a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * 32 --> 1001 + * 32 --> 1002 + * 32 --> 1003 + * 32 --> 1004 + * For this case locationsOfLine('TestStratum', null, 1001) should return single location for java line 32, + * and for lines 1002, 1003, 1004 should return empty list. + * 33 --> 1005 + * 34 --> 1005 + * 35 --> 1005 + * 36 --> 1005 + * For this case locationsOfLine('TestStratum', null, 1005) should return 4 locations for java lines 33 - 36, + * 37 --> 1006 + * 38 --> 1007 + * 39 --> 1008 + * For this case locationsOfLine for lines 1006-1007 should return single corresponding java line. + * Debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that for method '' method 'com.sun.jdi.Method.locationsOfLine(String stratum, String sourceName, int lineNumber)' + * returns correct values for 3 cases described above. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.locationsOfLine_ssi.locationsOfLine_ssi002.locationsOfLine_ssi002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.locationsOfLine_ssi.locationsOfLine_ssi002.locationsOfLine_ssi002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + */ + +package nsk.jdi.Method.locationsOfLine_ssi.locationsOfLine_ssi002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.sde.*; + +public class locationsOfLine_ssi002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new locationsOfLine_ssi002().runIt(argv, out); + } + + protected void preparePatchedClassFile(String className) { + String smapFileName = "TestSMAP.smap"; + SmapGenerator smapGenerator = new SmapGenerator(); + + SmapStratum smapStratum = new SmapStratum(testStratumName); + smapStratum.addFile(testStratumSourceName, testStratumSourcePath); + + // single output line is mapped to the multiple input lines + // 1001 -> 32 + // 1002 -> 32 + // 1003 -> 32 + // 1004 -> 32 + smapStratum.addLineData(1001, testStratumSourceName, 1, INIT_LINE, 1); + smapStratum.addLineData(1002, testStratumSourceName, 1, INIT_LINE, 1); + smapStratum.addLineData(1003, testStratumSourceName, 1, INIT_LINE, 1); + smapStratum.addLineData(1004, testStratumSourceName, 1, INIT_LINE, 1); + + // multiple output lines are mapped to the single input line + // 1005 -> 33 + // 1005 -> 34 + // 1005 -> 35 + // 1005 -> 36 + smapStratum.addLineData(1005, testStratumSourceName, 1, INIT_LINE + 1, 1); + smapStratum.addLineData(1005, testStratumSourceName, 1, INIT_LINE + 2, 1); + smapStratum.addLineData(1005, testStratumSourceName, 1, INIT_LINE + 3, 1); + smapStratum.addLineData(1005, testStratumSourceName, 1, INIT_LINE + 4, 1); + + // single output line is mapped to the single input line + // 1006 -> 37 + // 1007 -> 38 + // 1008 -> 39 + smapStratum.addLineData(1006, testStratumSourceName, 1, INIT_LINE + 5, 1); + smapStratum.addLineData(1007, testStratumSourceName, 1, INIT_LINE + 6, 1); + smapStratum.addLineData(1008, testStratumSourceName, 1, INIT_LINE + 7, 1); + + smapGenerator.addStratum(smapStratum, false); + + savePathcedClassFile(className, smapGenerator, smapFileName); + } + + public void doTest() { + String className = TestClass1.class.getName(); + + preparePatchedClassFile(className); + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + String methodName = ""; + + Method methodToTest = null; + + for (Method method : debuggee.classByName(className).methods()) { + if (method.name().equals(methodName)) { + methodToTest = method; + break; + } + } + + if (methodToTest == null) { + throw new TestBug("Method with name '' was not found in ReferenceType for class " + className); + } + + List expectedLocations = new ArrayList(); + + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1001, INIT_LINE)); + log.display("Check case when single output line is mapped to the multiple input lines"); + // single output line is mapped to the multiple input lines + // 1001 -> 32 + // 1002 -> 32 + // 1003 -> 32 + // 1004 -> 32 + try { + // locationsOfLine.(testStratum, testStratumSource, 1001) should + // return single java location + compareLocations( + methodToTest.locationsOfLine(testStratumName, testStratumSourceName, 1001), + expectedLocations, + testStratumName); + + // locationsOfLine.(testStratum, testStratumSource, [1002, 1003, + // 1004]) should return empty list + expectedLocations.clear(); + for (int i = 1002; i <= 1004; i++) + compareLocations( + methodToTest.locationsOfLine(testStratumName, testStratumSourceName, i), + expectedLocations, + testStratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1005, INIT_LINE + 1)); + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1005, INIT_LINE + 2)); + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1005, INIT_LINE + 3)); + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1005, INIT_LINE + 4)); + + log.display("Check case when multiple output lines are mapped to the single input line"); + // multiple output lines are mapped to the single input line + // 1005 -> 33 + // 1005 -> 34 + // 1005 -> 35 + // 1005 -> 36 + try { + // locationsOfLine.(testStratum, testStratumSource, 1005) should + // return 4 java locations + compareLocations( + methodToTest.locationsOfLine(testStratumName, testStratumSourceName, 1005), + expectedLocations, + testStratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + + log.display("Check case when single output line is mapped to the single input line"); + // single output line is mapped to the single input line + // 1006 -> 37 + // 1007 -> 38 + // 1008 -> 39 + try { + for (int i = 0; i < 3; i++) { + // locationsOfLine.(testStratum, testStratumSource, line) should + // return 1 java locations + expectedLocations.clear(); + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1006 + i, INIT_LINE + 5 + i)); + compareLocations( + methodToTest.locationsOfLine(testStratumName, testStratumSourceName, 1006 + i), + expectedLocations, + testStratumName); + } + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java new file mode 100644 index 00000000000..eed8d4daeb0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi003. + * VM Testbase keywords: [quick, jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that method 'com.sun.jdi.Method.locationsOfLine(String stratum, String sourceName, int lineNumber)' returns + * correct values for all stratums available for class and if sourceName == null locaitions for all sources are returned. + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3') and for each of this stratums following line mapping + * is defined (each method has locations in 3 different sources): + * "Java" "TestStratum" + * + * 9 --> 1000, source1, path1 + * 10 --> 1000, source2, path2 + * 11 --> 1000, source3, path3 + * ... ... + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1100, source2, path2 + * 22 --> 1100, source3, path3 + * ... ... + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1200, source2, path2 + * 33 --> 1200, source3, path3 + * ... ... + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that for all methods defined in this class method 'com.sun.jdi.Method.locationsOfLine(String stratum, String sourceName, int lineNumber)' + * for all test stratums('TestStratum1'-'TestStratum3') returns only expected locations depending on given line number and source name, + * and if source name is null locations for all sources are returned. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.locationsOfLine_ssi.locationsOfLine_ssi003.locationsOfLine_ssi003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.locationsOfLine_ssi.locationsOfLine_ssi003.locationsOfLine_ssi003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.Method.locationsOfLine_ssi.locationsOfLine_ssi003; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class locationsOfLine_ssi003 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new locationsOfLine_ssi003().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type5(className, testStratumCount); + /* + * Method 'prepareDefaultPatchedClassFile_Type5' creates class file with + * following line mapping for each TestStratum: "Java" "TestStratum" + * + * + * 9 --> 1000, source1, path1 + * 10 --> 1000, source2, path2 + * 11 --> 1000, source3, path3 ... ... + * + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1100, source2, path2 + * 22 --> 1100, source3, path3 ... ... + * + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1200, source2, path2 + * 33 --> 1200, source3, path3 ... ... + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName : testStratumData.keySet()) { + log.display("Check stratum: " + stratumName); + + for (Method method : referenceType.methods()) { + log.display("Check method '" + method.name() + "'"); + List locationsOfMethod = locationsOfMethod( + testStratumData.get(stratumName).allLocations, + method.name()); + + log.display("Check locations with specified source name"); + check_Method_locationsOfLine(method, stratumName, false, locationsOfMethod); + + log.display("Check locations for all sources"); + check_Method_locationsOfLine(method, stratumName, true, locationsOfMethod); + } + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001.java new file mode 100644 index 00000000000..96d54ca02d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.locationsOfLine_ssi; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.locationsOfLine(String, String, int)
    + * complies with its spec.
    + *
    + * The test checks up that for each line in the List returned
    + * by the method Method.allLineLocations(), the method
    + * locationsOfLine(defaultStratum, null, lineNumber) returns
    + * non-empty List object in which
    + * each object is a Location object.
    + * Not throwing AbsentInformationException
    + * is checked up as well.
    + *
    + */ + +public class locationsofline_ssi001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new locationsofline_ssi001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.locationsOfLine_ssi.locationsofline_ssi001a"; + + String mName = "nsk.jdi.Method.locationsOfLine_ssi"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List methods = null; + Method m = null; + List locations = null; + + + log2(" getting: List classes = vm.classesByName(mName + '.TestClass');"); + List classes = vm.classesByName(mName + ".TestClass"); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2("...... getting : String defaultStratum = vm.getDefaultStratum();"); + String defaultStratum = vm.getDefaultStratum(); + + log2(" getting a tested method object 'm'"); + methods = ((ReferenceType) classes.get(0)).methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + + log2("......locations = m.allLineLocations(); no AbsentInformationException is expected"); + try { + locations = m.allLineLocations(); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + + log2("......checking up on a value of locations.size(); 0 is not expected"); + int size = locations.size(); + if (size == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + ListIterator li1 = locations.listIterator(); + + log2("......the loop of checking locations in the returned list;"); + log2(" neither AbsentInformationException no InvalidLineNumberException is expected"); + + label1: + for (int ifor1 = 0; ifor1 < size; ifor1++) { + + int lineNumber = ((Location) li1.next()).lineNumber(); + + try { + log2("......List lineLocations = m.locationsOfLine(defaultStratum, null, " + lineNumber + ");"); + List lineLocations = m.locationsOfLine(defaultStratum, null, lineNumber); + int size1 = lineLocations.size(); + if (size1 == 0) { + testExitCode = FAILED; + log3("ERROR: lineLocations.size() == 0"); + break label1; + } + ListIterator li2 = lineLocations.listIterator(); + try { + for (; li2.hasNext(); ) { + Location loc = (Location) li2.next(); + } + } catch ( ClassCastException e) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + break label1; + } + } catch ( InvalidLineNumberException e1 ) { + testExitCode = FAILED; + log3("ERROR: InvalidLineNumberException"); + break label1; + } catch ( AbsentInformationException e2 ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break label1; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001/TestDescription.java new file mode 100644 index 00000000000..124556bee7e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001/TestDescription.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.locationsOfLine(String,String,int) + * complies with its spec: + * public List locationsOfLine(String stratum, String sourceName, int lineNumber) + * throws AbsentInformationException + * Returns a List containing all Location objects that map to + * the given line number and source name. + * Returns a list containing each Location that maps to the given line. + * The returned list will contain a location for each disjoint range of + * code indices that have been assigned to the given line by the compiler + * and/or VM. Each returned location corresponds to the beginning of + * this range. An empty list will be returned if + * there is no executable code at the specified line number; + * specifically, native and abstract methods will always return an empty list. + * Returned list is for the specified stratum + * (see Location for a description of strata). + * Parameters: stratum - the stratum to use for comparing line number and + * source name, or null to use the default stratum + * sourceName - the source name containing the line number, or + * null to match all source names + * lineNumber - the line number + * Returns: a List of Location objects that map to the given line number. + * Throws: AbsentInformationException - + * if there is no line number information for this method. + * Or if sourceName is non-null + * and source name information is not present. + * The test works as follows: + * The debugger program - nsk.jdi.Method.locationsOfLine_ssi.locationsofline_ssi001; + * the debuggee program - nsk.jdi.Method.locationsOfLine_ssi.locationsofline_ssi001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The option + * JAVAC_OPTS=-g + * is put in the locationsofline002.cfg file. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.locationsOfLine_ssi.locationsofline_ssi001 + * nsk.jdi.Method.locationsOfLine_ssi.locationsofline_ssi001a + * + * @comment make sure locationsofline_ssi001a is compiled with full debug info + * @clean nsk.jdi.Method.locationsOfLine_ssi.locationsofline_ssi001a + * @compile -g:lines,source,vars ../locationsofline_ssi001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.locationsOfLine_ssi.locationsofline_ssi001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001a.java new file mode 100644 index 00000000000..24d9ee5ac7f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsofline_ssi001a.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.locationsOfLine_ssi; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the locationsofline_ssi001 JDI test. + */ + +public class locationsofline_ssi001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.returnType()
    + * complies with its spec when a type is one of PrimitiveTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class returntype001aTestClass {
    + * public boolean bl () { return false; }
    + * public byte bt () { return 0; }
    + * public char ch () { return 0; }
    + * public double db () { return 0.0d; }
    + * public float fl () { return 0.0f; }
    + * public int in () { return 0; }
    + * public long ln () { return 0; }
    + * public short sh () { return 0; }
    + * }
    + *
    + * for all of the above primitive type return methods,
    + * a debugger forms their corresponding Type objects.
    + *
    + */ + +public class returntype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/returnType/returntype001", + sHeader2 = "--> returntype001: ", + sHeader3 = "##> returntype001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new returntype001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.returnType.returntype001a"; + + String mName = "nsk.jdi.Method.returnType"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("returntype001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".returntype001aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("bl"); + m = (Method) methods.get(0); + try { + BooleanType blType = (BooleanType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (BooleanType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (BooleanType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 1: // byte + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("bt"); + m = (Method) methods.get(0); + try { + ByteType btType = (ByteType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (ByteType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (ByteType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 2: // char + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ch"); + m = (Method) methods.get(0); + try { + CharType chType = (CharType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (CharType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (CharType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 3: // double + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("db"); + m = (Method) methods.get(0); + try { + DoubleType dbType = (DoubleType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (DoublerType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (DoubleType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 4: // float + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("fl"); + m = (Method) methods.get(0); + try { + FloatType flType = (FloatType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (FloatType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (FloatType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 5: // int + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("in"); + m = (Method) methods.get(0); + try { + IntegerType inType = (IntegerType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (IntegerType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (IntegerType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 6: // long + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ln"); + m = (Method) methods.get(0); + try { + LongType lnType = (LongType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (LongType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (LongType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 7: // short + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("sh"); + m = (Method) methods.get(0); + try { + ShortType shType = (ShortType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (ShortType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (ShortType) m.returnType();"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001/TestDescription.java new file mode 100644 index 00000000000..e768300f117 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/returnType/returntype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.returnType() + * complies with its spec: + * public Type returnType() + * throws ClassNotLoadedException + * Returns the return type of the this Method. + * For methods returning primitive values, + * an appropriate PrimitiveType is always returned. + * For methods returning object values, + * the appropriate ReferenceType is returned if + * it has been loaded through the enclosing type's + * (that is, the type returned by TypeComponent#enclosingType) class loader. + * Returns: the return Type of this method. + * Throws: ClassNotLoadedException - + * if the type has not yet been loaded through + * the appropriate class loader. + * when methods' returnTypes are PrimitiveTypes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.returnType.returntype001; + * the debuggee program - nsk.jdi.Method.returnType.returntype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.returnType.returntype001 + * nsk.jdi.Method.returnType.returntype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.returnType.returntype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001a.java new file mode 100644 index 00000000000..cc60cf3099b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype001a.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.returnType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the returntype001 JDI test. + */ + +public class returntype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> returntype001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> returntype001a: " + message); + } + + //====================================================== test program + + static returntype001aTestClass obj = new returntype001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.returnType()
    + * complies with its spec when a type is one of primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class returntype002aTestClass {
    + * public void vd () { return ; }
    + * }
    + *
    + * for the above void method vd,
    + * a debugger forms its corresponding Type object.
    + *
    + */ + +public class returntype002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/returnType/returntype002", + sHeader2 = "--> returntype002: ", + sHeader3 = "##> returntype002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new returntype002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.returnType.returntype002a"; + + String mName = "nsk.jdi.Method.returnType"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("returntype002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".returntype002aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // void + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("vd"); + m = (Method) methods.get(0); + try { + VoidType vdType = (VoidType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (VoidType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (VoidType) m.returnType();"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002/TestDescription.java new file mode 100644 index 00000000000..a1f0548330b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/returnType/returntype002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.returnType() + * complies with its spec: + * public Type returnType() + * throws ClassNotLoadedException + * Returns the return type of the this Method. + * For methods returning primitive values, + * an appropriate PrimitiveType is always returned. + * For methods returning object values, + * the appropriate ReferenceType is returned if + * it has been loaded through the enclosing type's + * (that is, the type returned by TypeComponent#enclosingType) class loader. + * Returns: the return Type of this method. + * Throws: ClassNotLoadedException - + * if the type has not yet been loaded through + * the appropriate class loader. + * when method's returnType is VoidType. + * The test works as follows: + * The debugger program - nsk.jdi.Method.returnType.returntype002; + * the debuggee program - nsk.jdi.Method.returnType.returntype002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.returnType.returntype002 + * nsk.jdi.Method.returnType.returntype002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.returnType.returntype002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002a.java new file mode 100644 index 00000000000..6f5813d1475 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype002a.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.returnType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the returntype002 JDI test. + */ + +public class returntype002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> returntype002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> returntype002a: " + message); + } + + //====================================================== test program + + static returntype002aTestClass obj = new returntype002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.returnType()
    + * complies with its spec when a type is one of ReferenceTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of the following
    + * class type with methods of ReferenceType return values:
    + *
    + * class returntype003aTestClass {
    + * .
    + * .
    + * public ClassForCheck[] arraymethod () {
    + * return cfc;
    + * }
    + * public ClassForCheck classmethod () {
    + * return classFC;
    + * }
    + * public InterfaceForCheck ifacemethod () {
    + * return iface;
    + * }
    + * }
    + *
    + * a debugger forms their corresponding Type objects.
    + *
    + */ + +public class returntype003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/returnType/returntype003", + sHeader2 = "--> returntype003: ", + sHeader3 = "##> returntype003: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new returntype003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.returnType.returntype003a"; + + String mName = "nsk.jdi.Method.returnType"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("returntype003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".returntype003aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // ArrayType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("arraymethod"); + m = (Method) methods.get(0); + try { + ArrayType aType = (ArrayType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (ArrayType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (ArrayType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 1: // ClassType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("classmethod"); + m = (Method) methods.get(0); + try { + ClassType cType = (ClassType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (ClassType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (ClassType) m.returnType();"); + expresult = 1; + break; + } + break; + + case 2: // InterfaceType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ifacemethod"); + m = (Method) methods.get(0); + try { + InterfaceType iType = (InterfaceType) m.returnType(); + } catch ( ClassCastException e1 ) { + log3("ERROR: CCE: (InterfaceType) m.returnType();"); + expresult = 1; + break; + } catch ( ClassNotLoadedException e2 ) { + log3("ERROR: CNLE: (InterfaceType) m.returnType();"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003/TestDescription.java new file mode 100644 index 00000000000..1bf496f6848 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/returnType/returntype003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.returnType() + * complies with its spec: + * public Type returnType() + * throws ClassNotLoadedException + * Returns the return type of the this Method. + * For methods returning primitive values, + * an appropriate PrimitiveType is always returned. + * For methods returning object values, + * the appropriate ReferenceType is returned if + * it has been loaded through the enclosing type's + * (that is, the type returned by TypeComponent#enclosingType) class loader. + * Returns: the return Type of this method. + * Throws: ClassNotLoadedException - + * if the type has not yet been loaded through + * the appropriate class loader. + * when methods' returnTypes are ReferenceTypes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.returnType.returntype003; + * the debuggee program - nsk.jdi.Method.returnType.returntype003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.returnType.returntype003 + * nsk.jdi.Method.returnType.returntype003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.returnType.returntype003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003a.java new file mode 100644 index 00000000000..217c93c5c85 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnType/returntype003a.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.returnType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the returntype003 JDI test. + */ + +public class returntype003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> returntype003a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> returntype003a: " + message); + } + + //====================================================== test program + + static returntype003aTestClass obj = new returntype003aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.returnTypeNames()
    + * complies with its spec when a type is one of PrimitiveTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class returntypenames001aTestClass {
    + * public boolean bl () { return false; }
    + * public byte bt () { return 0; }
    + * public char ch () { return 0; }
    + * public double db () { return 0.0d; }
    + * public float fl () { return 0.0f; }
    + * public int in () { return 0; }
    + * public long ln () { return 0; }
    + * public short sh () { return 0; }
    + * }
    + *
    + * for all of the above primitive type return methods,
    + * the debugger forms text representations of their
    + * corresponding types that is boolean, byte, char, and etc.
    + *
    + */ + +public class returntypenames001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/returnTypeNames/returntypenames001", + sHeader2 = "--> returntypenames001: ", + sHeader3 = "##> returntypenames001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new returntypenames001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.returnTypeNames.returntypenames001a"; + + String mName = "nsk.jdi.Method.returnTypeNames"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("returntypenames001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".returntypenames001aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + String name = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("bl"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("boolean")) { + log3("ERROR: !name.equals('boolean')"); + expresult = 1; + break; + } + break; + + case 1: // byte + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("bt"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("byte")) { + log3("ERROR: !name.equals('byte')"); + expresult = 1; + break; + } + break; + + case 2: // char + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ch"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("char")) { + log3("ERROR: !name.equals(char')"); + expresult = 1; + break; + } + break; + + case 3: // double + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("db"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("double")) { + log3("ERROR: !name.equals('double')"); + expresult = 1; + break; + } + break; + + case 4: // float + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("fl"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("float")) { + log3("ERROR: !name.equals('float')"); + expresult = 1; + break; + } + break; + + case 5: // int + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("in"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("int")) { + log3("ERROR: !name.equals('int')"); + expresult = 1; + break; + } + break; + + case 6: // long + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ln"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("long")) { + log3("ERROR: !name.equals('long')"); + expresult = 1; + break; + } + break; + + case 7: // short + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("sh"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("short")) { + log3("ERROR: !name.equals('short')"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001/TestDescription.java new file mode 100644 index 00000000000..37661340741 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/returnTypeNames/returntypenames001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.returnTypeNames() + * complies with its spec: + * public java.lang.String returnTypeName() + * Returns a text representation of the declared return type of this method. + * Returns: a string containing the return type name. + * when methods' returnTypes are PrimitiveTypes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.returnTypeNames.returntypenames001; + * the debuggee program - nsk.jdi.Method.returnTypeNames.returntypenames001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.returnTypeNames.returntypenames001 + * nsk.jdi.Method.returnTypeNames.returntypenames001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.returnTypeNames.returntypenames001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001a.java new file mode 100644 index 00000000000..784cef2ccd0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames001a.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.returnTypeNames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the returntypenames001 JDI test. + */ + +public class returntypenames001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> returntypenames001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> returntypenames001a: " + message); + } + + //====================================================== test program + + static returntypenames001aTestClass obj = new returntypenames001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.returnTypeNames()
    + * complies with its spec when a type is one of primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of
    + * the following class type:
    + * class returntypenames002aTestClass {
    + * public void vd () { return ; }
    + * }
    + *
    + * for the above void method vd, a debugger forms
    + * text representation of return type as void.
    + *
    + */ + +public class returntypenames002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/returnTypeNames/returntypenames002", + sHeader2 = "--> returntypenames002: ", + sHeader3 = "##> returntypenames002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new returntypenames002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.returnTypeNames.returntypenames002a"; + + String mName = "nsk.jdi.Method.returnTypeNames"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("returntypenames002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".returntypenames002aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + String name = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // void + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("vd"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals("void")) { + log3("ERROR: !name.equals('void')"); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002/TestDescription.java new file mode 100644 index 00000000000..b5d06a4d412 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/returnTypeNames/returntypenames002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.returnTypeNames() + * complies with its spec: + * public java.lang.String returnTypeName() + * Returns a text representation of the declared return type of this method. + * Returns: a string containing the return type name. + * when method's returnType is VoidType. + * The test works as follows: + * The debugger program - nsk.jdi.Method.returnTypeNames.returntypenames002; + * the debuggee program - nsk.jdi.Method.returnTypeNames.returntypenames002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.returnTypeNames.returntypenames002 + * nsk.jdi.Method.returnTypeNames.returntypenames002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.returnTypeNames.returntypenames002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002a.java new file mode 100644 index 00000000000..c1519d589a9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames002a.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.returnTypeNames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the returntypenames002 JDI test. + */ + +public class returntypenames002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> returntypenames002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> returntypenames002a: " + message); + } + + //====================================================== test program + + static returntypenames002aTestClass obj = new returntypenames002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.returnTypeNames()
    + * complies with its spec when a type is one of ReferenceTypes.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee creates an object of the following
    + * class type with methods of ReferenceType return values:
    + *
    + * class returntypenames003aTestClass {
    + * .
    + * .
    + * public returntypenames003aClassForCheck1[] arraymethod () {
    + * return cfc;
    + * }
    + * public returntypenames003aClassForCheck1 classmethod () {
    + * return classFC;
    + * }
    + * public returntypenames003aIntfForCheck ifacemethod () {
    + * return iface;
    + * }
    + * }
    + *
    + * a debugger forms text representations of their types
    + * as follows:
    + * nsk.jdi.Method.returnTypeNames.returntypenames003aClassForCheck1[]
    + * nsk.jdi.Method.returnTypeNames.returntypenames003aClassForCheck1
    + * nsk.jdi.Method.returnTypeNames.returntypenames003aIntfForCheck
    + *
    + */ + +public class returntypenames003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/returnTypeNames/returntypenames003", + sHeader2 = "--> returntypenames003: ", + sHeader3 = "##> returntypenames003: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new returntypenames003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.returnTypeNames.returntypenames003a"; + + String mName = "nsk.jdi.Method.returnTypeNames"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("returntypenames003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".returntypenames003aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + String name = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // ArrayType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("arraymethod"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals(mName + ".returntypenames003aClassForCheck1[]")) { + log3("ERROR: !name.equals(mName + '.returntypenames003aClassForCheck1[]') " + name); + expresult = 1; + break; + } + break; + + case 1: // ClassType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("classmethod"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals(mName + ".returntypenames003aClassForCheck1")) { + log3("ERROR: !name.equals(mName + '.returntypenames003aClassForCheck1') " + name); + expresult = 1; + break; + } + break; + + case 2: // InterfaceType + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("ifacemethod"); + m = (Method) methods.get(0); + name = m.returnTypeName(); + + if (!name.equals(mName + ".returntypenames003aIntfForCheck")) { + log3("ERROR: !name.equals(mName + '.returntypenames003aIntfForCheck') " + name); + expresult = 1; + break; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003/TestDescription.java new file mode 100644 index 00000000000..d6292e90679 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/returnTypeNames/returntypenames003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.returnTypeNames() + * complies with its spec: + * public java.lang.String returnTypeName() + * Returns a text representation of the declared return type of this method. + * Returns: a string containing the return type name. + * when methods' returnTypes are ReferenceTypes. + * The test works as follows: + * The debugger program - nsk.jdi.Method.returnTypeNames.returntypenames003; + * the debuggee program - nsk.jdi.Method.returnTypeNames.returntypenames003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.returnTypeNames.returntypenames003 + * nsk.jdi.Method.returnTypeNames.returntypenames003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.returnTypeNames.returntypenames003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003a.java new file mode 100644 index 00000000000..34801b9a3d4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/returnTypeNames/returntypenames003a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.returnTypeNames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the returntypenames003 JDI test. + */ + +public class returntypenames003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> returntypenames003a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> returntypenames003a: " + message); + } + + //====================================================== test program + + static returntypenames003aTestClass obj = new returntypenames003aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.variables()
    + * complies with its spec if a debugged program is compiled with
    + * "-g" option, hence, no exception AbsentInformationException
    + * is expected.
    + *
    + * Cases for testing are as follows:
    + * - non-native method with arguments and variables
    + * - non-native method without arguments and variables
    + * - native method
    + */ + +public class variables001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/variables/variables001", + sHeader2 = "--> variables001: ", + sHeader3 = "##> variables001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new variables001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.variables.variables001a"; + + String mName = "nsk.jdi.Method.variables"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("variables001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".variables001aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + List argsList = null; + + + // method with arguments and variables + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + check:{ + try { + argsList = m.variables(); + if (argsList.size() != 12) { + log3("ERROR: for method with args and vars: argsList# != 12 :" + + argsList.size() ); + testExitCode = FAILED; + break check; + } + try { + int i1names = 0; + int i2names = 0; + int i3names = 0; + + for (int i2 = 0; i2 < argsList.size(); i2++) { + LocalVariable lv = (LocalVariable) argsList.get(i2); + if (lv.name().equals("i1")) i1names++; + if (lv.name().equals("i2")) i2names++; + if (lv.name().equals("i3")) i3names++; + } + if (i1names != 1) { + log3("ERROR: for method with args and vars: mirrors of 'i1' != 1 :" + + i1names); + testExitCode = FAILED; + } + if (i2names != 2) { + log3("ERROR: for method with args and vars: mirrors of 'i2' != 2 :" + + i2names); + testExitCode = FAILED; + } + if (i3names != 1) { + log3("ERROR: for method with args and vars: mirrors of 'i3' != 1 :" + + i3names); + testExitCode = FAILED; + } + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException for lv = (LocalVariable) arglist.get(0);"); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException for method with arguments"); + testExitCode = FAILED; + } + } // check: + + + // method without arguments and variables + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("vd"); + m = (Method) methods.get(0); + + try { + argsList = m.variables(); + if (argsList.size() != 0) { + log3("ERROR: for method without args and vars: argsList# != 0 :" + + argsList.size() ); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException for method without arguments"); + testExitCode = FAILED; + } + + + // native method + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("nvd"); + m = (Method) methods.get(0); + + try { + log2("......testing native method; AbsentInformationException is expected"); + argsList = m.variables(); + log3("ERROR: no AbsentInformationException"); + testExitCode = FAILED; + } catch ( AbsentInformationException e ) { + log2(" AbsentInformationException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001/TestDescription.java new file mode 100644 index 00000000000..8e1686881e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001/TestDescription.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/variables/variables001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.variables() + * complies with its spec: + * public java.util.List variables() + * throws AbsentInformationException + * Returns a list containing each LocalVariable declared in this method. + * The list includes any variable declared in any scope within the method. + * It may contain multiple variables of the same name declared within + * disjoint scopes. + * Arguments are considered local variables and will be present in + * the returned list. + * Returns: the list of LocalVariable objects which mirror local variables + * declared in this method in the target VM. + * If there are no local variables, a zero-length list is returned. + * Throws: AbsentInformationException - + * if there is no variable information for this method. + * NativeMethodException - + * if this operation is attempted for a native method. + * when a debugged program is compiled with the '-g' option, + * hence, no AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.variables.variables 00; + * the debuggee program - nsk.jdi.Method.variables.variables 00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * -------------- + * Fixing bug 4453137: + * To comply with the latest Merlin specification + * which differs the Ladybird and early Merlin specifications, + * the test is corrected as follows: + * - for native method, + * the check on throwing AbsentInformationException is performed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.variables.variables001 + * nsk.jdi.Method.variables.variables001a + * + * @comment make sure variables001a is compiled with full debug info + * @clean nsk.jdi.Method.variables.variables001a + * @compile -g:lines,source,vars ../variables001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.variables.variables001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001a.java new file mode 100644 index 00000000000..c0fd6144bab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables001a.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.variables; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the variables001 JDI test. + */ + +public class variables001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> variables001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> variables001a: " + message); + } + + //====================================================== test program + + static variables001aTestClass obj = new variables001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.variables()
    + * complies with its spec if a debugged program is compiled
    + * without "-g" option,
    + * hence, the exception AbsentInformationException is expected.

    + *
    + */ + +public class variables002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/variables/variables002", + sHeader2 = "--> variables002: ", + sHeader3 = "##> variables002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new variables002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.variables.variables002a"; + + String mName = "nsk.jdi.Method.variables"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("variables002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".variables002aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + List argsList = null; + + + // method with arguments + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + try { + argsList = m.variables(); + log3(" no AbsentInformationException"); + testExitCode = FAILED; + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002/TestDescription.java new file mode 100644 index 00000000000..34ee0591209 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/variables/variables002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.variables() + * complies with its spec: + * public java.util.List variables() + * throws AbsentInformationException + * Returns a list containing each LocalVariable declared in this method. + * The list includes any variable declared in any scope within the method. + * It may contain multiple variables of the same name declared within + * disjoint scopes. + * Arguments are considered local variables and will be present in + * the returned list. + * Returns: the list of LocalVariable objects which mirror local variables + * declared in this method in the target VM. + * If there are no local variables, a zero-length list is returned. + * Throws: AbsentInformationException - + * if there is no variable information for this method. + * NativeMethodException - + * if this operation is attempted for a native method. + * when a debugged program is compiled without the '-g' option, + * hence, AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.variables.variables002; + * the debuggee program - nsk.jdi.Method.variables.variables002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.variables.variables002 + * nsk.jdi.Method.variables.variables002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.variables.variables002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002a.java new file mode 100644 index 00000000000..53973dcb1a4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variables/variables002a.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.variables; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the variables002 JDI test. + */ + +public class variables002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> variables002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> variables002a: " + message); + } + + //====================================================== test program + + static variables002aTestClass obj = new variables002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.variablesByName()
    + * complies with its spec if a debugged program is compiled with
    + * "-g" option, hence, no exception AbsentInformationException
    + * is expected.
    + *
    + * Cases for testing are as follows:
    + * - non-native method with arguments and variables
    + * - non-native method without arguments and variables
    + * - native method + */ + +public class variablesbyname001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/variablesByName/variablesbyname001", + sHeader2 = "--> variablesbyname001: ", + sHeader3 = "##> variablesbyname001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new variablesbyname001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.variablesByName.variablesbyname001a"; + + String mName = "nsk.jdi.Method.variablesByName"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("variablesbyname001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".variablesbyname001aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + List argsList = null; + + + // method with arguments and variables + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + check:{ + try { + argsList = m.variablesByName("in"); + if (argsList.size() != 1) { + log3("ERROR: for method with args and vars: argsList# != 1 for 'in' :" + + argsList.size() ); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException for method with arguments"); + testExitCode = FAILED; + } + + try { + argsList = m.variablesByName("i1"); + if (argsList.size() != 1) { + log3("ERROR: for method with args and vars: argsList# != 1 for 'i1' :" + + argsList.size() ); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException for method with arguments"); + testExitCode = FAILED; + } + + try { + argsList = m.variablesByName("i2"); + if (argsList.size() != 2) { + log3("ERROR: for method with args and vars: argsList# != 2 for 'i2' :" + + argsList.size() ); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException for method with arguments"); + testExitCode = FAILED; + } + } // check: + + + // method without arguments and variables + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("vd"); + m = (Method) methods.get(0); + + try { + argsList = m.variablesByName("in"); + if (argsList.size() != 0) { + log3("ERROR: for method without args and vars: argsList# != 0 :" + + argsList.size() ); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException for method without arguments"); + testExitCode = FAILED; + } + + + // native method + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("nvd"); + m = (Method) methods.get(0); + + try { + log2("......testing native method; AbsentInformationException is expected"); + argsList = m.variablesByName("in"); + log3("ERROR: no AbsentInformationException"); + testExitCode = FAILED; + } catch ( AbsentInformationException e ) { + log2(" AbsentInformationException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001/TestDescription.java new file mode 100644 index 00000000000..ecc2d2185b0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001/TestDescription.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/variablesByName/variablesbyname001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.variablesByName() + * complies with its spec: + * public java.util.List variablesByName(java.lang.String name) + * throws AbsentInformationException + * Returns a list containing each LocalVariable of a given name in this method. + * Multiple variables can be returned if the same variable name is used + * in disjoint scopes within the method. + * Returns: the list of LocalVariable objects of the given name. + * If there are no matching local variables, + * a zero-length list is returned. + * Throws: AbsentInformationException - + * if there is no variable information for this method. + * NativeMethodException - + * if this operation is attempted for a native method. + * when a debugged program is compiled with the '-g' option, + * hence, no AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.variablesByName.variablesbyname001; + * the debuggee program - nsk.jdi.Method.variablesByName.variablesbyname001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * -------------- + * Fixing bug 4453137: + * To comply with the latest Merlin specification + * which differs the Ladybird and early Merlin specifications, + * the test is corrected as follows: + * - for native method, + * the check on throwing AbsentInformationException is performed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.variablesByName.variablesbyname001 + * nsk.jdi.Method.variablesByName.variablesbyname001a + * + * @comment make sure variablesbyname001a is compiled with full debug info + * @clean nsk.jdi.Method.variablesByName.variablesbyname001a + * @compile -g:lines,source,vars ../variablesbyname001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.variablesByName.variablesbyname001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001a.java new file mode 100644 index 00000000000..d5cbfa56416 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname001a.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.variablesByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the variablesbyname001 JDI test. + */ + +public class variablesbyname001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> variablesbyname001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> variablesbyname001a: " + message); + } + + //====================================================== test program + + static variablesbyname001aTestClass obj = new variablesbyname001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Method.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Method.variablesByName()
    + * complies with its spec if a debugged program is compiled
    + * without "-g" option,
    + * hence, the exception AbsentInformationException is expected.

    + *
    + */ + +public class variablesbyname002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Method/variablesByName/variablesbyname002", + sHeader2 = "--> variablesbyname002: ", + sHeader3 = "##> variablesbyname002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new variablesbyname002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Method.variablesByName.variablesbyname002a"; + + String mName = "nsk.jdi.Method.variablesByName"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("variablesbyname002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeClasses = vm.classesByName(mName + ".variablesbyname002aTestClass"); + if (listOfDebuggeeClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeClasses.size() != 1"); + break ; + } + + List methods = null; + Method m = null; + List argsList = null; + + + // method with arguments + + methods = ((ReferenceType) listOfDebuggeeClasses.get(0)). + methodsByName("primitiveargsmethod"); + m = (Method) methods.get(0); + + try { + argsList = m.variablesByName("in2"); + log3(" no AbsentInformationException"); + testExitCode = FAILED; + } catch ( AbsentInformationException e ) { + log3(" AbsentInformationException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002/TestDescription.java new file mode 100644 index 00000000000..5d8d998499f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Method/variablesByName/variablesbyname002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Method. + * The test checks up that a result of the method + * com.sun.jdi.Method.variablesByName() + * complies with its spec: + * public java.util.List variablesByName(java.lang.String name) + * throws AbsentInformationException + * Returns a list containing each LocalVariable of a given name in this method. + * Multiple variables can be returned if the same variable name is used + * in disjoint scopes within the method. + * Returns: the list of LocalVariable objects of the given name. + * If there are no matching local variables, + * a zero-length list is returned. + * Throws: AbsentInformationException - + * if there is no variable information for this method. + * NativeMethodException - + * if this operation is attempted for a native method. + * when a debugged program is compiled without the '-g' option, + * hence, AbsentInformationException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.Method.variablesByName.variablesbyname002; + * the debuggee program - nsk.jdi.Method.variablesByName.variablesbyname002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Method.variablesByName.variablesbyname002 + * nsk.jdi.Method.variablesByName.variablesbyname002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Method.variablesByName.variablesbyname002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002a.java new file mode 100644 index 00000000000..7f9202a9402 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/variablesByName/variablesbyname002a.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Method.variablesByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the variablesbyname002 JDI test. + */ + +public class variablesbyname002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> variablesbyname002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> variablesbyname002a: " + message); + } + + //====================================================== test program + + static variablesbyname002aTestClass obj = new variablesbyname002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i"); + + pipe = debuggee.createIOPipe(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + try { + + // wait for debugee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // get mirrors for checked class, thread, and method + + vm = debuggee.VM(); + + log.display("Getting loaded class in debuggee"); + checkedClass = debuggee.classByName(DEBUGGEE_NAME); + + Iterator threadIterator = vm.allThreads().iterator(); + while (threadIterator.hasNext()) { + ThreadReference curThread = (ThreadReference) threadIterator.next(); + if (curThread.name().equals("main")) { + checkedThread = curThread; + } + } + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + log.display("Getting reference to method "); + checkedMethod = debuggee.methodByName(checkedClass, "foo"); + if (checkedMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + + log.display("Getting reference to field "); + checkedField = checkedClass.fieldByName("flag"); + if (checkedField == null) { + throw new Failure("TEST BUG: unable to find reference to field "); + } + + log.display("Getting reference to field "); + depthField = checkedClass.fieldByName("depth"); + if (depthField == null) { + throw new Failure("TEST BUG: unable to find reference to field "); + } + + log.display("Getting value of field "); + try { + depthVal = ((IntegerValue)checkedClass.getValue(depthField)).value(); + log.display("depth == " + depthVal); + } catch (ClassCastException e) { + throw new Failure("TEST BUG: cannot get value of field"); + } + + // create event request (initially disabled) + + EventRequestManager eventRManager = vm.eventRequestManager(); + log.display("Creating MethodEntryRequest"); + if ((checkedRequest = eventRManager.createMethodEntryRequest()) == null) { + throw new Failure("TEST BUG: unable to create MethodEntryRequest"); + } + + checkedRequest.addThreadFilter(checkedThread); + checkedRequest.addClassFilter(checkedClass); + checkedRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + + switch (checkedRequest.suspendPolicy()) { + case EventRequest.SUSPEND_ALL: + log.display(" suspend policy is SUSPEND_ALL"); + break; + case EventRequest.SUSPEND_EVENT_THREAD: + log.display(" suspend policy is SUSPEND_EVENT_THREAD"); + break; + case EventRequest.SUSPEND_NONE: + log.display(" suspend policy is SUSPEND_NONE"); + break; + default: + log.complain("TEST BUG: Unknown suspend policy!"); + } + + log.display("MethodEntryRequest is created"); + + // create two auxilary breakpoints + + log.display("Getting reference to method "); + runMethod = debuggee.methodByName(checkedClass, "run"); + if (runMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + + log.display("Creating two auxilary breakpoints into method "); + startingBreakpointRequest = debuggee.setBreakpoint(runMethod, method001a.STARTING_BREAKPOINT_LINE); + endingBreakpointRequest = debuggee.setBreakpoint(runMethod, method001a.ENDING_BREAKPOINT_LINE); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + while (!eventReceived) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + // enable or disable checked event request at BreakpointEvent + if (event instanceof BreakpointEvent) { + Location eventLocation = ((BreakpointEvent)event).location(); + int lineNumber = eventLocation.lineNumber(); + log.display("BreakpointEvent received for location " + lineNumber); + if (lineNumber == method001a.STARTING_BREAKPOINT_LINE) { + log.display("Enabling MethodEntryRequest at breakpoint before invoking method"); + checkedRequest.enable(); + } else if (lineNumber == method001a.ENDING_BREAKPOINT_LINE) { + log.display("Disabling MethodEntryRequest at breakpoint after invoking method"); + checkedRequest.disable(); + eventReceived = true; + } else { + testFailed = true; + throw new Failure("TEST BUG: Unknown location of breakpoint event: " + lineNumber); + } + } + + // handle checked MethodEntryEvent + if (event instanceof MethodEntryEvent) { + MethodEntryEvent castedEvent = (MethodEntryEvent) event; + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 2: eventRequest is not equal to checked request"); + testFailed = true; + } + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 3: eventThread is not equal to checked thread"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 4: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + Method method1 = castedEvent.method(); + Method method2 = castedEvent.method(); + if (!method1.equals(method2)) { + log.complain("FAILURE 7: return of MethodEntryEvent.method() is inconsistent"); + testFailed = true; + } + + if (castedEvent.method().equals(checkedMethod)) { + eventsCounter++; + log.display("MethodEntryEvent is received for method " + checkedMethod.name() + ", counter = " + eventsCounter); + try { + int flagVal = ((IntegerValue)checkedClass.getValue(checkedField)).value(); + log.display("flag == " + flagVal); + if ( flagVal > 0) { + if (!eventThread.isSuspended()) { + log.complain("FAILURE 5: eventThread is not suspended"); + } else { + log.complain("FAILURE 6: MethodEntryEvent is generated after code execution"); + } + testFailed = true; + } + } catch (ClassCastException e) { + log.complain("TEST BUG: cannot get value of field"); + testFailed = true; + } + } + } + } + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to invoke method + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // waiting for debuggee comfirms method invoked + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check whether all expected events received or not + if (eventsCounter == 0) { + log.complain("FAILURE 1: No any MethodEntryEvent received"); + testFailed = true; + } else if (eventsCounter < depthVal) { + log.complain("FAILURE 1: Some " + (depthVal - eventsCounter) + " MethodEntryEvent NOT received (too few)"); + testFailed = true; + } else if (eventsCounter > depthVal) { + log.complain("FAILURE 1: Extra " + (eventsCounter - depthVal) + " MethodEntryEvent received (too many)"); + testFailed = true; + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debuggee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analyze its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001/TestDescription.java new file mode 100644 index 00000000000..7247800ee3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryEvent/method/method001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.MethodEntryEvent.method() method. + * The test checks the following assertions: + * - MethodEntryEvent is received by debugger for requested + * method if this method is invoked by some executing + * thread in debugged VM; + * - received MethodEntryEvent has proper references to: + * method, + * debugged VM, + * executed thread, + * related MethodEntryRequest. + * - MethodEntryEvent is produced before any code of the + * method is executed. + * A debugger class - nsk.jdi.MethodEntryEvent.method.method001 ; + * a debuggee class - nsk.jdi.MethodEntryEvent.method.method001a . + * The test uses supporting nsk/share/jdi classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates MethodEntryRequest filtered to class. + * Also it sets two breakpoint in debuggee before and after invoking + * checked method . + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee recurcively + * invokes method. This method updates field of + * class. + * The debugger switches to to listen the event during the + * time specified by parameter. When BreakpointEvent for the first + * breakpoint is received, MethodEntryRequest becomes enabled. + * checks all received MetodEntryEvents until second breakpoint is reached + * and MethodEntryRequest becomes disabled. + * Each time the debugger receives MethodEntryEvent, it compares all refencies + * of this event ( , , , ) + * with expected values. If the event belongs to method, value + * of field is checked. + * Finally, debugger sends debuggee command QUIT and checks number of recieved + * events. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4433805 EventSet.resume() for VMStartEvent resumes thread suspended by breakpoint request + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryEvent.method.method001 + * nsk.jdi.MethodEntryEvent.method.method001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryEvent.method.method001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001a.java new file mode 100644 index 00000000000..3a2ec46ebb7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method001a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryEvent.method; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +// This class is the debugged application in the test +public class method001a { + + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // line numbers for auxilary breakpoints + public static final int STARTING_BREAKPOINT_LINE = 86; + public static final int ENDING_BREAKPOINT_LINE = 91; + + // scaffold objects + static private ArgumentHandler argHandler; + static private Log log; + static private IOPipe pipe; + + // flags and counters + static private int flag; + static private int depth; + static private boolean methodInvoked; + + // start debuggee + public static void main(String args[]) { + method001a _method001a = new method001a(); + System.exit(JCK_STATUS_BASE + _method001a.run(args, System.err)); + } + + // perform the test + int run(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + pipe = argHandler.createDebugeeIOPipe(); + + depth = 10; + flag = 0; + + // notify debugger that debuggee has been started + pipe.println(COMMAND_READY); + + // wait for GO commnad from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + methodInvoked = false; // STARTING_BREAKPOINT_LINE + + // invoke checked method + foo(); + + methodInvoked = true; // ENDING_BREAKPOINT_LINE + + // notify debugger that checked method has been invoked + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + return PASSED; + } + + // checked method + void foo() { + flag++; + if (depth > 1) { + depth--; + flag--; + foo(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002.java new file mode 100644 index 00000000000..2d67b0b95e8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002.java @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryEvent.method; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.List; +import java.util.Iterator; +import java.lang.Thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test +public class method002 { + + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // timeout interval for waiting events in a loop + static final int TIMEOUT_DELTA = 1000; // milliseconds + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // class names + static final String TEST_NAME = "nsk.jdi.MethodEntryEvent.method.method002"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + static final String CHILD_NAME = TEST_NAME + "child"; + + // JDI scaffold objects + static private Debugee debuggee; + static private IOPipe pipe; + static private VirtualMachine vm; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + // mirrors for tested debuggee entities + static private MethodEntryRequest checkedRequest; + static private ThreadReference checkedThread; + static private Method checkedMethod; + static private Field checkedField; + static private ReferenceType checkedClass; + static private ReferenceType debuggeeClass; + + // auxilary breakpoints + static private BreakpointRequest startingBreakpointRequest; + static private BreakpointRequest endingBreakpointRequest; + static private Method runMethod; + + // flags and counters + static private long eventTimeout; + static private boolean testFailed; + static private boolean eventReceived; + static private int eventsCount; + + // start test from command line + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + // start test from JCK-compatible environment + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + eventsCount = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + try { + + // wait for debugee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // get mirrors for checked class, thread, and method + + vm = debuggee.VM(); + + log.display("Getting loaded classes in debuggee"); + debuggeeClass = debuggee.classByName(DEBUGGEE_NAME); + checkedClass = debuggee.classByName(CHILD_NAME); + + log.display("Getting
    thread in debuggee"); + checkedThread = debuggee.threadByName("main"); + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + log.display("Getting reference to method "); + checkedMethod = debuggee.methodByName(checkedClass, "foo"); + if (checkedMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + if (checkedMethod.isAbstract()) { + throw new Failure("TEST BUG: found method is abstract"); + } + + log.display("Getting reference to field "); + checkedField = checkedClass.fieldByName("counter"); + if (checkedField == null) { + throw new Failure("TEST BUG: unable to find reference to field "); + } + + // create event request (initially disabled) + + log.display("Creating MethodEntryRequest"); + if ((checkedRequest = vm.eventRequestManager().createMethodEntryRequest()) == null) { + throw new Failure("TEST BUG: unable to create MethodEntryRequest"); + } + + checkedRequest.addThreadFilter(checkedThread); + checkedRequest.addClassFilter(checkedClass); + checkedRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + + switch (checkedRequest.suspendPolicy()) { + case EventRequest.SUSPEND_ALL: + log.display(" suspend policy is SUSPEND_ALL"); + break; + case EventRequest.SUSPEND_EVENT_THREAD: + log.display(" suspend policy is SUSPEND_EVENT_THREAD"); + break; + case EventRequest.SUSPEND_NONE: + log.display(" suspend policy is SUSPEND_NONE"); + break; + default: + log.complain("TEST BUG: Unknown suspend policy!"); + } + + log.display("MethodEntryRequest is created"); + + // create two auxilary breakpoints + + log.display("Getting reference to method "); + runMethod = debuggee.methodByName(debuggeeClass, "run"); + if (runMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + + log.display("Creating two auxilary breakpoints into method "); + startingBreakpointRequest = debuggee.setBreakpoint(runMethod, method002a.STARTING_BREAKPOINT_LINE); + endingBreakpointRequest = debuggee.setBreakpoint(runMethod, method002a.ENDING_BREAKPOINT_LINE); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + while (!eventReceived) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + // enable or disable checked event request at BreakpointEvent + if (event instanceof BreakpointEvent) { + Location eventLocation = ((BreakpointEvent)event).location(); + int lineNumber = eventLocation.lineNumber(); + log.display("BreakpointEvent received for location " + lineNumber); + if (lineNumber == method002a.STARTING_BREAKPOINT_LINE) { + log.display("Enabling MethodEntryRequest at breakpoint before invoking method"); + checkedRequest.enable(); + } else if (lineNumber == method002a.ENDING_BREAKPOINT_LINE) { + log.display("Disabling MethodEntryRequest at breakpoint after invoking method"); + checkedRequest.disable(); + eventReceived = true; + } else { + testFailed = true; + throw new Failure("TEST BUG: Unknown location of breakpoint event: " + lineNumber); + } + } + + // handle checked MethodEntryEvent + if (event instanceof MethodEntryEvent) { + MethodEntryEvent castedEvent = (MethodEntryEvent) event; + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 2: eventRequest is not equal to checked request"); + testFailed = true; + } + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 3: eventThread is not equal to checked thread"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 4: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + if (castedEvent.method().equals(checkedMethod)) { + eventsCount++; + log.display("MethodEntryEvent is received for method " + checkedMethod.name()); + try { + int counterVal = ((IntegerValue)checkedClass.getValue(checkedField)).value(); + log.display("Counter == " + counterVal); + if ( counterVal > 0) { + if (!eventThread.isSuspended()) { + log.complain("FAILURE 5: eventThread is not suspended"); + } else { + log.complain("FAILURE 6: MethodEntryEvent is generated after code execution"); + } + testFailed = true; + } + } catch (ClassCastException e) { + log.complain("TEST BUG: cannot get value of field"); + testFailed = true; + } + } + } + } + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to invoke method + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // waiting for debuggee comfirms method invoked + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check whether all expected events received or not + if (eventsCount < 1) { + log.complain("FAILURE 1: No any MethodEntryEvent received: " + eventsCount); + testFailed = true; + } else if (eventsCount > 1) { + log.complain("FAILURE 1: Too many MethodEntryEvent received: " + eventsCount); + testFailed = true; + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debuggee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analyze its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002/TestDescription.java new file mode 100644 index 00000000000..6fcead6f690 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryEvent/method/method002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.MethodEntryEvent.method() method. + * The test checks the following assertions: + * - MethodEntryEvent is received by debugger for requested + * method if this method is invoked by some executing thread + * in debugged VM; + * - received MethodEntryEvent has proper references to: + * method, + * debugged VM, + * executed thread, + * related MethodEntryRequest. + * - MethodEntryEvent is produced before any code of the + * method is executed. + * A debugger class - nsk.jdi.MethodEntryEvent.method.method002 ; + * a debuggee class - nsk.jdi.MethodEntryEvent.method.method002a . + * The test uses supporting nsk/share/jdi classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates MethodEntryRequest filtered to class. + * Also it sets two breakpoint in debuggee before and after invoking + * checked method . + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee creates variable + * of class. This class implements abstract method + * of class. The method is invoked. The + * implementing method updates field of class. + * The debugger switches to to listen the event during the + * time specified by parameter. When BreakpointEvent for the first + * breakpoint is received, MethodEntryRequest becomes enabled. + * checks all received MetodEntryEvents until second breakpoint is reached + * and MethodEntryRequest becomes disabled. + * Each time the debugger receives MethodEntryEvent, it compares all refencies + * of this event ( , , , ) + * with expected values. If the event belongs to method, value + * of field is checked. + * Finally, debugger sends debuggee command QUIT and checks number of recieved + * events. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4433805 EventSet.resume() for VMStartEvent resumes thread suspended by breakpoint request + * Standard method Debugee.endDebugee() is used instead of cleaning event queue on debuggee VM exit. + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryEvent.method.method002 + * nsk.jdi.MethodEntryEvent.method.method002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryEvent.method.method002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002a.java new file mode 100644 index 00000000000..16a16e0304d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryEvent/method/method002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryEvent.method; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +// This class is the debugged application in the test +public class method002a { + + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // line numbers for auxilary breakpoints + public static final int STARTING_BREAKPOINT_LINE = 83; + public static final int ENDING_BREAKPOINT_LINE = 88; + + // scaffold objects + static private ArgumentHandler argHandler; + static private Log log; + static private IOPipe pipe; + + // flags and counters + static private boolean methodInvoked; + + // start debuggee + public static void main(String args[]) { + method002a _method002a = new method002a(); + System.exit(JCK_STATUS_BASE + _method002a.run(args, System.err)); + } + + // perform the test + static int run(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + pipe = argHandler.createDebugeeIOPipe(); + + method002parent a = new method002child(); + + // notify debugger that debuggee has been started + pipe.println(COMMAND_READY); + + // wait for GO commnad from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + methodInvoked = false; // STARTING_BREAKPOINT_LINE + + // invoke checked method + a.foo(); + + methodInvoked = true; // ENDING_BREAKPOINT_LINE + + // notify debugger that checked method has been invoked + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + return PASSED; + } +} + +abstract class method002parent { + abstract void foo(); +} + +class method002child extends method002parent { + static private int counter = 0; + + void foo() { + counter++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001.java new file mode 100644 index 00000000000..6cdca54c742 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.MethodEntryRequest._bounds_; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; + +import java.io.*; + +/** + * The test checks up the
    + * - addThreadFilter(ThreadReference)
    + * - addInstanceFilter(ObjectReference)
    + * - addClassFilter(ReferenceType)
    + * - addClassFilter(String)
    + * - addClassExclusionFilter(String)
    + * methods with null argument value. + * In any cases NullPointerException is expected. + */ +public class filters001 { + + private final static String prefix = "nsk.jdi.MethodEntryRequest._bounds_."; + private final static String debuggerName = prefix + "filters001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + filters001 thisTest = new filters001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + display(""); + display(">>>creating MethodEntryRequest"); + + MethodEntryRequest request = + debugee.getEventRequestManager().createMethodEntryRequest(); + + display(""); + addThreadFilter(request, null); + + display(""); + addInstanceFilter(request, null); + + display(""); + addClassFilter(request, (ReferenceType )null); + + display(""); + addClassFilter(request, (String )null); + + display(""); + addClassExclusionFilter(request, (String )null); + + display(""); + debugee.quit(); + } + + private void addThreadFilter(MethodEntryRequest request, ThreadReference thread) { + String tmp = "addThreadFilter :thread name> "; + tmp += (thread == null) ? "" : thread.name(); + display(tmp); + + try { + request.addThreadFilter(thread); + if (thread==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (thread == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addInstanceFilter(MethodEntryRequest request, + ObjectReference instance) { + String tmp = "addInstanceFilter :object value> "; + tmp += (instance == null) ? "" : instance.toString(); + display(tmp); + + try { + request.addInstanceFilter(instance); + if (instance==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (instance == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(MethodEntryRequest request, ReferenceType refType) { + + display("addClassFilter :ReferenceType> <" + refType + ">"); + + try { + request.addClassFilter(refType); + if (refType==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (refType==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(MethodEntryRequest request, String classPattern) { + + display("addClassFilter :classPattern> <" + classPattern + ">"); + try { + request.addClassFilter(classPattern); + if (classPattern==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (classPattern==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassExclusionFilter(MethodEntryRequest request, + String classPattern) { + display("addExclusionClassFilter :classPattern> <" + classPattern + ">"); + try { + request.addClassExclusionFilter(classPattern); + if (classPattern==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (classPattern==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001/TestDescription.java new file mode 100644 index 00000000000..fbcfb57c21b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/_bounds_/filters001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the methods + * com.sun.jdi.request.MethodEntryRequest.addThreadFilter(ThreadReference) + * com.sun.jdi.request.MethodEntryRequest.addInstanceFilter(ObjectReference) + * com.sun.jdi.request.MethodEntryRequest.addClassFilter(ReferenceType) + * com.sun.jdi.request.MethodEntryRequest.addClassFilter(String) + * com.sun.jdi.request.MethodEntryRequest.addClassExclusionFilter(String) + * correctly work for the boundary value of parameter and throw described + * exceptions. + * The test check up this methods with argument value. In any cases + * NullPointerException is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest._bounds_.filters001 + * nsk.jdi.MethodEntryRequest._bounds_.filters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest._bounds_.filters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001a.java new file mode 100644 index 00000000000..507a34ff72e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/_bounds_/filters001a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.MethodEntryRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filters001a is deugee's part of the test. + */ +public class filters001a { + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001.java new file mode 100644 index 00000000000..8e87e5049fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodEntryRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodEntryRequest.addClassExclusionFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The case to checks a pattern that ends with '*'. + * + * The test works as follows. + * - The debugger + * - sets up two MethodEntryRequests, + * - restricts the Requests using patterns 'java*' and 'sun*', + * so that events will be filtered only from test classes, + * - resumes the debuggee, and + * - waits for expected MethodEntryEvents. + * - The debuggee creates and starts thread1, which being run, + * invoke methods used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter001a"; + return new filter001().runThis(argv, out); + } + + private String classExclName1 = "java"; + private String classExclName2 = "sun"; + private boolean methodEntryReceived = false; + + protected void testRun() { + + MethodEntryRequest eventRequest1 = null; + String thread1Name = "thread1"; + String property1 = "MethodEntryRequest1"; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + ThreadReference thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting23MethodEntryRequest( thread1, + EventRequest.SUSPEND_NONE, + property1); + + eventRequest1.addClassExclusionFilter(classExclName1 + "*"); + eventRequest1.addClassExclusionFilter(classExclName2 + "*"); + eventRequest1.enable(); + + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof MethodEntryEvent) { + methodEntryReceived = true; + String str = ((MethodEntryEvent)event).location().declaringType().name(); + if (str.indexOf(classExclName1) == 0 || str.indexOf(classExclName2) == 0) { + setFailedStatus("Received unexpected MethodEntryEvent for excluded class:" + str); + } else { + display("Received expected MethodEntryEvent for " + str); + } + return true; + } + return false; + } + } + ); + + display("......waiting for MethodEntryEvent in expected thread"); + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + if (!methodEntryReceived) { + setFailedStatus("No MethodEntryEvent was received."); + } + return; + } + + private MethodEntryRequest setting23MethodEntryRequest ( ThreadReference thread, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodEntryRequest:"); + display(" thread: " + thread + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodEntryRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001/TestDescription.java new file mode 100644 index 00000000000..17d13398f21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateMethodEntry - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter001; + * the debuggee program - nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter001 + * nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001a.java new file mode 100644 index 00000000000..1fea7a9a757 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter001a.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter001 JDI test. + */ + +public class filter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter001a thread1 = new Thread1filter001a("thread1"); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + log1("new filter001a().run1(thread1);"); + new filter001a().run1(thread1); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class Thread1filter001a extends Thread { + + class TestClass10{ + void m10() { + throw new NullPointerException("m10"); + } + } + class TestClass11 extends TestClass10{ + void m11() { + + try { + (new TestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } + } + + + String tName = null; + + public Thread1filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new TestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java new file mode 100644 index 00000000000..a75f4873d5e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodEntryRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodEntryRequest.addClassExclusionFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an MethodEntryRequest and enables it,
    + * - invokes the method addClassExclusionFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassExclusionFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassExclusionFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter002a"; + + private String testedClassName1 = + "nsk.jdi.MethodEntryRequest.addClassExclusionFilter.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "MethodEntryRequest1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = setting23MethodEntryRequest(null, testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + log2("breakpointForCommunication"); + + do { + getEventSet(); + + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) + return; + + log2(" received: " + event); + + if (EventFilters.filtered(event)) { + eventSet.resume(); + } + else { + break; + } + } while (true); + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest setting23MethodEntryRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassExclusionFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + menr.addCountFilter(1); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002/TestDescription.java new file mode 100644 index 00000000000..cc5d535c435 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateMethodEntry - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateMethodEntry - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter002; + * the debuggee program - nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter002 + * nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addClassExclusionFilter.filter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002a.java new file mode 100644 index 00000000000..74a2b8577bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002a.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter002 JDI test. + */ + +public class filter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + +// static Thread1filter002a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// thread1 = new Thread1filter002a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001.java new file mode 100644 index 00000000000..e25b0b202e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodEntryRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodEntryRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or + * any of its subtypes. + * The cases to check include entering methods in four types, + * two in super-class filter_rt001aTestClass10 and its sub-class filter_rt001aTestClass11, and + * two in super-class filter_rt001aTestClass20 and its sub-class filter_rt001aTestClass21. + * A filter used restricts events only to methods in first pair. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a thread, thread1, invoking methods + * in the super-class filter_rt001aTestClass10 and its sub-class filter_rt001aTestClass11 and + * in the super-class filter_rt001aTestClass20 and its sub-class filter_rt001aTestClass21 + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes to use to filter MethodEntryEvents, + * - sets up MethodEntryRequest for the events, + * - restricts the events to those in filter_rt001aTestClass11, + * - and resumes the debuggee and waits for the events. + * - The debuggee starts the thread1. + * - Upon getting the events, the debugger performs checks required. + * + * In third phase, at the end of the test, the debuggee changes + * the value of the "instruction" which the debugger and debuggee + * use to inform each other of needed actions, and both end. + */ + +public class filter_rt001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt001a"; + return new filter_rt001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt001aTestClass11"; + + protected void testRun() { + EventRequest eventRequest1 = null; + String property1 = "MethodEntryRequest1"; + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = (ReferenceType) debuggee.classByName(testedClassName); + + eventRequest1 = setting21MethodEntryRequest(null, testClassReference, + EventRequest.SUSPEND_NONE, property1); + + display("......waiting for MethodEntryEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, false); + + if ( !(newEvent instanceof MethodEntryEvent)) { + setFailedStatus("ERROR: new event is not MethodEntryEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodEntryEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ReferenceType refType = ((MethodEntryEvent)newEvent).location().declaringType(); + if (!refType.equals(testClassReference)) { + setFailedStatus("Received unexpected declaring type of the event: " + refType.name() + + "\n\texpected one: " + testClassReference.name()); + } + } + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodEntryRequest setting21MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodEntryRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodEntryRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001/TestDescription.java new file mode 100644 index 00000000000..f384c53118b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt001; + * the debuggee program - nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt001 + * nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001a.java new file mode 100644 index 00000000000..5d50bd9363c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt001a.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt001 JDI test. + */ + +public class filter_rt001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt001aThread1 thread1 = null; + + static filter_rt001aTestClass10 obj10 = new filter_rt001aTestClass10(); + static filter_rt001aTestClass11 obj11 = new filter_rt001aTestClass11(); + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + thread1 = new filter_rt001aThread1("thread1"); + + log1("new filter_rt001a().run1(thread1);"); + new filter_rt001a().run1(thread1); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt001aTestClass10{ + static void m10() { + filter_rt001a.log1("entered: m10()"); + } +} +class filter_rt001aTestClass11 extends filter_rt001aTestClass10{ + static void m11() { + filter_rt001a.log1("entered: m11()"); + filter_rt001aTestClass10.m10(); + } +} + +class filter_rt001aThread1 extends Thread { + + String tName = null; + + public filter_rt001aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + filter_rt001aTestClass21.m21(); + filter_rt001aTestClass11.m11(); + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt001aTestClass20{ + static void m20() { + filter_rt001a.log1("entered: m20()"); + } +} + +class filter_rt001aTestClass21 extends filter_rt001aTestClass20{ + static void m21() { + filter_rt001a.log1("entered: m21()"); + filter_rt001aTestClass20.m20(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java new file mode 100644 index 00000000000..9cbb56bc192 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodEntryRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodEntryRequest.addClassFilter(ReferenceType)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a filter_rt002aTestClass10 object, to use as filter,
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an MethodEntryRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_rt002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_rt002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt002a"; + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt002aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "MethodEntryRequest1"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = setting21MethodEntryRequest(null, testClassReference, + EventRequest.SUSPEND_NONE, property1); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" no InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testClassReference); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest setting21MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002/TestDescription.java new file mode 100644 index 00000000000..65759c1d8cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt002; + * the debuggee program - nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt002 + * nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002a.java new file mode 100644 index 00000000000..9dc407e5415 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002a.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt002 JDI test. + */ + +public class filter_rt002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt002aThread1 thread1 = null; + + static filter_rt002aTestClass10 obj = new filter_rt002aTestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new filter_rt002aThread1("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt002aTestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class filter_rt002aTestClass11 extends filter_rt002aTestClass10{ + void m11() { + + try { + (new filter_rt002aTestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class filter_rt002aThread1 extends Thread { + + String tName = null; + + public filter_rt002aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt002a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_rt002aTestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter_rt002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003.java new file mode 100644 index 00000000000..0b7eee0174f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodEntryRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodEntryRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to be + * the preparation of the given reference type and any subtypes. + * The cases to test include re-invocations of the method + * addClassFilter() on the same MethodEntryRequest object. + * There are two MethodEntryRequests to check as follows: + * (1) For MethodEntryRequest2, both invocations are with different + * ReferenceTypes restricting one MethodEntry event to two classes. + * The test expects no MethodEntry event will be received. + * (2) For MethodEntryRequest1, both invocations are with the same + * ReferenceType restricting one MethodEntry event to one class. + * The test expects this MethodEntry event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, + * invoking methods correspondingly + * in the super-class filter_rt003aTestClass10 and its sub-class filter_rt003aTestClass11 and + * in the super-class filter_rt003aTestClass20 and its sub-class filter_rt003aTestClass21, + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes 1&2 for the Classes to filter, + * - sets up two MethodEntryRequests 1&2, + * - double restricts MethodEntryRequest1 to the RefTypes 1 and 1, + * - double restricts MethodEntryRequest2 to the RefTypes 1 and 2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - The debuggee creates and starts two threads, thread1 and thread2, + * generating the events to be filtered. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_rt003 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt003a"; + return new filter_rt003().runThis(argv, out); + } + + private String testedClassName11 = + "nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt003aTestClass11"; + + private String testedClassName21 = + "nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt003aTestClass21"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "MethodEntryRequest1"; + String property2 = "MethodEntryRequest2"; + + ReferenceType testClassReference11 = null; + ReferenceType testClassReference21 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference11 = (ReferenceType) debuggee.classByName(testedClassName11); + testClassReference21 = (ReferenceType) debuggee.classByName(testedClassName21); + + eventRequest1 = setting21MethodEntryRequest(null, testClassReference11, + EventRequest.SUSPEND_ALL, property1); + + eventRequest2 = setting21MethodEntryRequest(null, testClassReference11, + EventRequest.SUSPEND_ALL, property2); + + ((MethodEntryRequest) eventRequest1).addClassFilter(testClassReference11); + ((MethodEntryRequest) eventRequest2).addClassFilter(testClassReference21); + + display("......waiting for MethodEntryEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, false); + + if ( !(newEvent instanceof MethodEntryEvent)) { + setFailedStatus("ERROR: new event is not MethodEntryEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodEntryEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ReferenceType refType = ((MethodEntryEvent)newEvent).location().declaringType(); + if (!refType.equals(testClassReference11)) { + setFailedStatus("Received unexpected declaring type of the event: " + refType.name() + + "\n\texpected one: " + testClassReference11.name()); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodEntryRequest setting21MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodEntryRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodEntryRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003/TestDescription.java new file mode 100644 index 00000000000..dfb4f300e3f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt003; + * the debuggee program - nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt003 + * nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addClassFilter_rt.filter_rt003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003a.java new file mode 100644 index 00000000000..82b3eabfcec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt003a.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt003 JDI test. + */ + +public class filter_rt003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt003aThread1 thread1 = null; + static filter_rt003aThread2 thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + filter_rt003aTestClass11 obj1 = new filter_rt003aTestClass11(); + filter_rt003aTestClass21 obj2 = new filter_rt003aTestClass21(); + + thread1 = new filter_rt003aThread1("thread1"); + thread2 = new filter_rt003aThread2("thread2"); + + log1("debuggee started!"); + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + log1("new filter_rt003a().run1(thread1);"); + new filter_rt003a().run1(thread1); + + log1("new filter_rt003a().run1(thread2);"); + new filter_rt003a().run1(thread2); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt003aTestClass10{ + static void m10() { + filter_rt003a.log1("entered: m10()"); + } +} +class filter_rt003aTestClass11 extends filter_rt003aTestClass10{ + static void m11() { + filter_rt003a.log1("entered: m11()"); + filter_rt003aTestClass10.m10(); + } +} + +class filter_rt003aThread1 extends Thread { + + String tName = null; + + public filter_rt003aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + filter_rt003aTestClass11.m11(); + filter_rt003aTestClass21.m21(); + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt003aTestClass20{ + static void m20() { + filter_rt003a.log1("entered: m20()"); + } +} +class filter_rt003aTestClass21 extends filter_rt003aTestClass20{ + static void m21() { + filter_rt003a.log1("entered: m21()"); + filter_rt003aTestClass20.m20(); + } +} + +class filter_rt003aThread2 extends Thread { + + String tName = null; + + public filter_rt003aThread2(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + filter_rt003aTestClass21.m21(); + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001.java new file mode 100644 index 00000000000..79032f1e334 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodEntryRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodEntryRequest.addClassFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The cases to check include both a pattern that begin with '*' and + * one that end with '*'. + * + * The test works as follows. + * - The debugger + * - sets up two MethodEntryRequests, + * - restricts the Requests using patterns that begins with '*' and + * ends with *, + * - resumes the debuggee, and + * - waits for expected MethodEntryEvents. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, invoke methods used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_s001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s001a"; + return new filter_s001().runThis(argv, out); + } + + private String testedClassName1 = "TestClass11"; + private String testedClassName2 = + "nsk.jdi.MethodEntryRequest.addClassFilter_s.Thread2filter_s001a"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "MethodEntryRequest1"; + String property2 = "MethodEntryRequest2"; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + + eventRequest1 = setting22MethodEntryRequest(null, "*" + testedClassName1, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for MethodEntryEvent in expected class"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof MethodEntryEvent)) { + setFailedStatus("ERROR: new event is not MethodEntryEvent"); + } else { + String str = ((MethodEntryEvent)newEvent).location().declaringType().name(); + if (!str.endsWith(testedClassName1)) { + setFailedStatus("Received MethodEntryEvent for unexpected class: \n\t" + str); + } else { + display("Received MethodEntryEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + + vm.resume(); + break; + + case 1: + eventRequest2 = setting22MethodEntryRequest(null, testedClassName2 + "*", + EventRequest.SUSPEND_ALL, property2); + + display("......waiting for MethodEntryEvent in expected class"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof MethodEntryEvent)) { + setFailedStatus("ERROR: new event is not MethodEntryEvent"); + } else { + + String str = ((MethodEntryEvent)newEvent).location().declaringType().name(); + if (!str.endsWith(testedClassName2)) { + setFailedStatus("Received MethodEntryEvent for unexpected class: \n\t" + str); + } else { + display("Received MethodEntryEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property2) ) { + setFailedStatus("ERROR: property is not : " + property2); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodEntryRequest setting22MethodEntryRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodEntryRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodEntryRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001/TestDescription.java new file mode 100644 index 00000000000..6b87bfb6a19 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addClassFilter() + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateMethodEntry - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s001; + * the debuggee program - nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s001 + * nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001a.java new file mode 100644 index 00000000000..6af8df133e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s001a.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s001 JDI test. + */ + +public class filter_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_s001a thread1 = null; + static Thread2filter_s001a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_s001a("thread1"); + log1("new filter_s001a().run1(thread1);"); + new filter_s001a().run1(thread1); + + break; + + case 1: + thread2 = new Thread2filter_s001a("thread2"); + log1("new filter_s001a().run1(thread2);"); + new filter_s001a().run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class TestClass10{ + static void m10() { + filter_s001a.log1(" entered: m10()"); + } +} +class TestClass11 extends TestClass10{ + static void m11() { + filter_s001a.log1(" entered: m11()"); + TestClass10.m10(); + } +} + +class Thread1filter_s001a extends Thread { + + String tName = null; + + public Thread1filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + TestClass11.m11(); + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class Thread2filter_s001a extends Thread { + + String tName = null; + + public Thread2filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + TestClass21.m21(); + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } + + static class TestClass20{ + static void m20() { + filter_s001a.log1(" entered: m20()"); + } + } + static class TestClass21 extends TestClass20{ + static void m21() { + filter_s001a.log1(" entered: m21()"); + TestClass20.m20(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java new file mode 100644 index 00000000000..1d2225b0f3d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java @@ -0,0 +1,525 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodEntryRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodEntryRequest.addClassFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an MethodEntryRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_s002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_s002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s002a"; + + private String testedClassName1 = + "nsk.jdi.MethodEntryRequest.addClassFilter_s.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "MethodEntryRequest1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = setting22MethodEntryRequest(null, testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest setting22MethodEntryRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002/TestDescription.java new file mode 100644 index 00000000000..d9be1a6e2f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addClassFilter() + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateMethodEntry - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateMethodEntry - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addClassFilter.filter_s002; + * the debuggee program - nsk.jdi.MethodEntryRequest.addClassFilter.filter_s002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s002 + * nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addClassFilter_s.filter_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002a.java new file mode 100644 index 00000000000..e857d52c2cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002a.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s002 JDI test. + */ + +public class filter_s002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + +// static Thread1filter_s002a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// thread1 = new Thread1filter_s002a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001.java new file mode 100644 index 00000000000..20dd47dc62f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodEntryRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodEntryRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * in which the currently executing instance is + * the object specified. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a special array with three Object instances, + * and two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a MethodEntryRequest + * within the method in the class instancefilter001aTestClass + * whose array element instances #0 and #1 + * will be calling by the thread1 and the thread2 accordinly, + * - invokes addInstanceFilter() on array element #0 for the thread1 + * and #2 for the thread2, + * thus restricting the MethodEntry event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter001a"; + return new instancefilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter001aTestClass"; + + protected void testRun() { + + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodEntryRequest1"; + String property2 = "MethodEntryRequest2"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) debuggee.classByName(testedClassName); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + eventRequest1 = setting2MethodEntryRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + ((MethodEntryRequest) eventRequest1).addInstanceFilter(instance); + + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + eventRequest2 = setting2MethodEntryRequest (thread2, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(2); + ((MethodEntryRequest) eventRequest2).addInstanceFilter(instance); + + display("......waiting for MethodEntryEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof MethodEntryEvent)) { + setFailedStatus("ERROR: new event is not MethodEntryEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodEntryEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodEntryRequest setting2MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodEntryRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodEntryRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001/TestDescription.java new file mode 100644 index 00000000000..62f41a796cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter001; + * the debuggee program - nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter001 + * nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001a.java new file mode 100644 index 00000000000..623f88ac8bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter001a.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter001 JDI test. + */ + +public class instancefilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter001aThread thread1 = null; + static instancefilter001aThread thread2 = null; + + static instancefilter001aTestClass objTC[] = { new instancefilter001aTestClass(), new instancefilter001aTestClass(), new instancefilter001aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1 = new instancefilter001aThread("thread1"); + thread2 = new instancefilter001aThread("thread2"); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter001aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter001aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter001aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java new file mode 100644 index 00000000000..4a6f4893a1b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodEntryRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodEntryRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a MethodEntryRequest and enables it,
    + * - invokes the method addInstanceFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addInstanceFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addInstanceFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter002a"; + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodEntryRequest1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodEntryRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + ((MethodEntryRequest) eventRequest1).addInstanceFilter(instance); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" no InvalidRequestStateException expected"); + ((MethodEntryRequest) eventRequest1).addInstanceFilter(instance); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest setting2MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002/TestDescription.java new file mode 100644 index 00000000000..87e81c3cedd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter002; + * the debuggee program - nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter002 + * nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002a.java new file mode 100644 index 00000000000..f2a1c21f988 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter002 JDI test. + */ + +public class instancefilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter002aThread thread1 = null; + + static instancefilter002aTestClass objTC[] = { new instancefilter002aTestClass(), new instancefilter002aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new instancefilter002aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter002aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter002aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter002aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java new file mode 100644 index 00000000000..0a6936b397b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodEntryRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodEntryRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: UnsupportedOperationException -
    + * if the target virtual machine
    + * does not support this operation.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger creates
    + * a MethodEntryRequest and if addInstanceFilter() is not supported,
    + * invokes the method on the request expecting
    + * to catch UnsupportedOperationException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter003a"; + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodEntryRequest1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodEntryRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + if ( vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == true :: test cancelled"); + } else { + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" UnsupportedOperationException expected"); + ((MethodEntryRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no UnsupportedOperationException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" UnsupportedOperationException "); + } + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest setting2MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003/TestDescription.java new file mode 100644 index 00000000000..116e4fac9a1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter003; + * the debuggee program - nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter003 + * nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003a.java new file mode 100644 index 00000000000..8076232ebaf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter003 JDI test. + */ + +public class instancefilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter003aThread thread1 = null; + + static instancefilter003aTestClass objTC[] = { new instancefilter003aTestClass(), new instancefilter003aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new instancefilter003aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter003aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter003aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter003aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004.java new file mode 100644 index 00000000000..247e96ea1b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodEntryRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodEntryRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same MethodEntryRequest object. + * There are two BreakpointRequests to check as follows: + * (1) For MethodEntryRequest2, both invocations are with different + * ObjectReferences restricting one MethodEntry event to two objects. + * The test expects no MethodEntry event will be received. + * (2) For MethodEntryRequest1, both invocations are with the same + * ObjectReference restricting one MethodEntry event to one object. + * The test expects this MethodEntry event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up MethodEntryRequests 1&2 within the method + * in the class TestClass which will be calling by both threads, + * - restricts the MethodEntryRequest1 to the tread1 and + * to the array elements #0 & #0 calling only within thread1, + * - restricts the MethodEntryRequest2 to the thread2 and + * the array elements #0 & #1 calling within thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter004a"; + return new instancefilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter004aTestClass"; + + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodEntryRequest1"; + String property2 = "MethodEntryRequest2"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + + ObjectReference instance1 = null; + ObjectReference instance2 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2MethodEntryRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2MethodEntryRequest (thread2, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + + instance1 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + instance2 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(1); + + ((MethodEntryRequest) eventRequest1).addInstanceFilter(instance1); + ((MethodEntryRequest) eventRequest1).addInstanceFilter(instance1); + ((MethodEntryRequest) eventRequest2).addInstanceFilter(instance1); + ((MethodEntryRequest) eventRequest2).addInstanceFilter(instance2); + + display("......waiting for MethodEntryEvent in expected thread"); + MethodEntryEvent newEvent = (MethodEntryEvent)eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + EventRequest newEventRequest = newEvent.request(); + if ( newEventRequest.equals(eventRequest1) ) { + display(" received expected event: " + newEvent); + + ThreadReference newEventThread = newEvent.thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodEntryRequest setting2MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodEntryRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodEntryRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004/TestDescription.java new file mode 100644 index 00000000000..c177ac20b85 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same MethodEntryRequest object. + * There are two MethodEntryRequests to check as follows: + * (1) For MethodEntryRequest2, both invocations are with different + * ObjectReferences restricting one MethodEntry event to two objects. + * The test expects no MethodEntry event will be received. + * (2) For MethodEntryRequest1, both invocations are with the same + * ObjectReference restricting one MethodEntry event to one object. + * The test expects this MethodEntry event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter004; + * the debuggee program - nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter004 + * nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addInstanceFilter.instancefilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004a.java new file mode 100644 index 00000000000..bd03f15a0ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter004a.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter004 JDI test. + */ + +public class instancefilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter004aThread thread1 = null; + static instancefilter004aThread thread2 = null; + + static instancefilter004aTestClass objTC[] = { new instancefilter004aTestClass(), new instancefilter004aTestClass(), new instancefilter004aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1 = new instancefilter004aThread("thread1"); + thread2 = new instancefilter004aThread("thread2"); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter004aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter004aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter004aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001.java new file mode 100644 index 00000000000..1b98c9ff6bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodEntryRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodEntryRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a MethodEntryRequest within the method + * in the class threadfilter001aTestClass which will be calling by both threads, + * - restricts the method entry event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class threadfilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter001a"; + return new threadfilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter001aTestClass"; + + protected void testRun() { + EventRequest eventRequest1 = null; + ThreadReference thread1 = null; + String thread1Name = "thread1"; + String property1 = "MethodEntryRequest1"; + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodEntryRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for MethodEntryEvent in tested thread"); + + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof MethodEntryEvent)) { + setFailedStatus("ERROR: new event is not MethodEntryEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodEntryEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + + } + return; + } + + private MethodEntryRequest setting2MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodEntryRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodEntryRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001/TestDescription.java new file mode 100644 index 00000000000..c8adc9bf511 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter001; + * the debuggee program - nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter001 + * nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001a.java new file mode 100644 index 00000000000..e84543404d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter001a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter001 JDI test. + */ + +public class threadfilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter001aThread thread1 = null; + static threadfilter001aThread thread2 = null; + + static threadfilter001aTestClass objTC = new threadfilter001aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1 = new threadfilter001aThread("thread1"); + thread2 = new threadfilter001aThread("thread2"); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter001aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter001aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class threadfilter001aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java new file mode 100644 index 00000000000..eafa4730ddf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodEntryRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodEntryRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a MethodEntryRequest and enables it,
    + * - invokes the method addThreadFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addThreadFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addThreadFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class threadfilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new threadfilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter002a"; + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "MethodEntryRequest1"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodEntryRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addThreadFilter(thread1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((MethodEntryRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest setting2MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002/TestDescription.java new file mode 100644 index 00000000000..37f2a05e3ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter002; + * the debuggee program - nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter002 + * nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002a.java new file mode 100644 index 00000000000..31e19b85360 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002a.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter002 JDI test. + */ + +public class threadfilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter002aThread thread1 = null; + + static threadfilter002aTestClass objTC = new threadfilter002aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new threadfilter002aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter002aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter002aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class threadfilter002aTestClass { + + static int breakpointLine = 3; + + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java new file mode 100644 index 00000000000..afb5cd8d24a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodEntryRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodEntryRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Restricts the events generated by this request
    + * to those in the given thread.
    + * The cases to test include three thread's states:
    + * not started, running, dead.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates MethodEntryRequest1 and
    + * invokes the method addThreadFilter(tread1) on the request1,
    + * - creates MethodEntryRequest2,
    + * resumes the debuggee to get the thread1 started, and
    + * invokes the method addThreadFilter(thread) on the request2,
    + * - creates MethodEntryRequest3, waits the thread1 to die, and
    + * invokes the method addThreadFilter(thread) on the request3.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class threadfilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new threadfilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter003a"; + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "MethodEntryRequest1"; + String property2 = "MethodEntryRequest2"; + String property3 = "MethodEntryRequest3"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodEntryRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((MethodEntryRequest)eventRequest1).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 1: + eventRequest2 = setting2MethodEntryRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property2); + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((MethodEntryRequest)eventRequest2).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2MethodEntryRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property3); + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((MethodEntryRequest)eventRequest3).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodEntryRequest setting2MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodEntryRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + menr = eventRManager.createMethodEntryRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodEntryRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodEntryRequest() : " + e); + log3(" MethodEntryRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodEntryRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003/TestDescription.java new file mode 100644 index 00000000000..18b275cdfed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include three thread's states: not started, running, dead. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter003; + * the debuggee program - nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter003 + * nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003a.java new file mode 100644 index 00000000000..574638e1544 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003a.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter003 JDI test. + */ + +public class threadfilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter003aThread thread1 = null; + + static threadfilter003aTestClass objTC = new threadfilter003aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new threadfilter003aThread("thread1"); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();"); + methodForCommunication(); + } + break; + + case 2: + try { + thread1.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class threadfilter003aThread extends Thread { + + public threadfilter003aThread(String threadName) { + super(threadName); + } + + public void run() { + log1(" 'run': enter "); + + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + log1(" 'run': exit "); + } + return; + } + } + +} + +class threadfilter003aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004.java new file mode 100644 index 00000000000..78483dd5219 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodEntryRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodEntryRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same MethodEntryRequest object. + * There are two MethodEntryRequests to check as follows: + * (1) For MethodEntryRequest2, both invocations are with different + * ThreadReferences restricting one MethodEntry event to two threads. + * The test expects no MethodEntry event will be received. + * (2) For MethodEntryRequest1, both invocations are with the same + * ThreadReference restricting one MethodEntry event to one thread. + * The test expects this MethodEntry event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up MethodEntryRequests 1&2 within the method + * in the class threadfilter004aTestClass which will be calling by both threads, + * - restricts the MethodEntryRequest1 only to thread1, + * - restricts the MethodEntryRequest2 to both thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class threadfilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter004a"; + return new threadfilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter004aTestClass"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodEntryRequest1"; + String property2 = "MethodEntryRequest2"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) debuggee.classByName(testedClassName); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2MethodEntryRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2MethodEntryRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + + ((MethodEntryRequest) eventRequest1).addThreadFilter(thread1); + ((MethodEntryRequest) eventRequest2).addThreadFilter(thread2); + + display("......waiting for MethodEntryEvent in tested thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof MethodEntryEvent)) { + setFailedStatus("ERROR: new event is not MethodEntryEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodEntryEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + EventRequest newEventRequest = newEvent.request(); + if (!newEventRequest.equals(eventRequest1) ) { + setFailedStatus("The MethodEntryEvent occured not for eventRequest1"); + } + + ThreadReference thr = ((MethodEntryEvent)newEvent).thread(); + if (!thr.equals(thread1)) { + setFailedStatus("The MethodEntryEvent occured in unexpected thread: " + thr); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodEntryRequest setting2MethodEntryRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodEntryRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodEntryRequest + mexr = eventRManager.createMethodEntryRequest(); + mexr.putProperty("number", property); + if (thread != null) + mexr.addThreadFilter(thread); + mexr.addClassFilter(testedClass); + mexr.setSuspendPolicy(suspendPolicy); + + display(" MethodEntryRequest has been set up"); + return mexr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodEntryRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004/TestDescription.java new file mode 100644 index 00000000000..7ffe3d410d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodEntryRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodEntryRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same MethodEntryRequest object. + * There are two MethodEntryRequests to check as follows: + * (1) For MethodEntryRequest2, both invocations are with different + * ThreadReferences restricting one MethodEntry event to two threads. + * The test expects no MethodEntry event will be received. + * (2) For MethodEntryRequest1, both invocations are with the same + * ThreadReference restricting one MethodEntry event to one thread. + * The test expects this MethodEntry event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter004; + * the debuggee program - nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter004 + * nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodEntryRequest.addThreadFilter.threadfilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004a.java new file mode 100644 index 00000000000..46800b5d554 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter004a.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodEntryRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter004 JDI test. + */ + +public class threadfilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter004aThread thread1 = null; + static threadfilter004aThread thread2 = null; + + static threadfilter004aTestClass objTC = new threadfilter004aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1 = new threadfilter004aThread("thread1"); + thread2 = new threadfilter004aThread("thread2"); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter004aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter004aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + + public static void nullMethod() { + throw new NullPointerException("test"); + } + +} + +class threadfilter004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001.java new file mode 100644 index 00000000000..874c930d646 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitEvent._itself_; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.List; +import java.util.Iterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger application in the test + +public class methodexit001 { + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // timeout interval for waiting events in a loop + static final int TIMEOUT_DELTA = 1000; // milliseconds + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // class names + static final String TEST_NAME = "nsk.jdi.MethodExitEvent._itself_.methodexit001"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + + // JDI scaffold objects + static private Debugee debuggee; + static private IOPipe pipe; + static private VirtualMachine vm; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + // mirrors for tested debuggee entities + static private MethodExitRequest checkedRequest; + static private Method checkedMethod; + static private ReferenceType checkedClass; + + // auxilary breakpoints + static private BreakpointRequest startingBreakpointRequest; + static private BreakpointRequest endingBreakpointRequest; + static private Method runMethod; + + // flags and counters + static private long eventTimeout; + static private int depthVal, eventsCounter; + static private volatile boolean testFailed, eventReceived; + + // start test from command line + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + // start test from JCK-compatible environment + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + eventsCounter = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + try { + + // wait for debugee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // get mirrors for checked class, thread, and method + + vm = debuggee.VM(); + + log.display("Getting loaded class in debuggee"); + checkedClass = debuggee.classByName(DEBUGGEE_NAME); + + log.display("Getting reference to method 'foo'"); + checkedMethod = debuggee.methodByName(checkedClass, "foo"); + + // create event request (initially disabled) + + EventRequestManager eventRManager = vm.eventRequestManager(); + + log.display("Creating MethodExitRequest"); + if ((checkedRequest = eventRManager.createMethodExitRequest()) == null) { + throw new Failure("TEST BUG: unable to create MethodExitRequest"); + } + + checkedRequest.addClassFilter(checkedClass); + log.display("MethodExitRequest is created"); + + // create two auxilary breakpoints + + log.display("Getting reference to method "); + runMethod = debuggee.methodByName(checkedClass, "run"); + if (runMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + + log.display("Creating two auxilary breakpoints into method "); + startingBreakpointRequest = debuggee.setBreakpoint(runMethod, methodexit001a.STARTING_BREAKPOINT_LINE); + endingBreakpointRequest = debuggee.setBreakpoint(runMethod, methodexit001a.ENDING_BREAKPOINT_LINE); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + while (!eventReceived) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + // enable or disable checked event request at BreakpointEvent + if (event instanceof BreakpointEvent) { + Location eventLocation = ((BreakpointEvent)event).location(); + int lineNumber = eventLocation.lineNumber(); + log.display("BreakpointEvent received for location " + lineNumber); + if (lineNumber == methodexit001a.STARTING_BREAKPOINT_LINE) { + log.display("Enabling MethodExitRequest at breakpoint before invoking method"); + checkedRequest.enable(); + } else if (lineNumber == methodexit001a.ENDING_BREAKPOINT_LINE) { + log.display("Disabling MethodExitRequest at breakpoint after invoking method"); + checkedRequest.disable(); + eventReceived = true; + } else { + testFailed = true; + throw new Failure("TEST BUG: Unknown location of breakpoint event: " + lineNumber); + } + } + + // handle checked MethodEntryEvent + if (event instanceof MethodExitEvent) { + MethodExitEvent castedEvent = (MethodExitEvent) event; + EventRequest eventRequest = castedEvent.request(); + + if (castedEvent.method().equals(checkedMethod)) { + eventsCounter++; + log.display("FAILURE 1: MethodExitEvent is received for method " + + checkedMethod.name() + " at location " + castedEvent.location().lineNumber()); + testFailed = true; + } + } + } + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to invoke method + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // waiting for debuggee comfirms method invoked + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check whether all expected events received or not + if (eventsCounter == 0) { + log.display("No any MethodExitEvent received for checked method as expected"); + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debuggee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analyze its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001/TestDescription.java new file mode 100644 index 00000000000..67d08ab7c7b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodExitEvent/_itself_/methodexit001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.MethodExitEvent.method() method. + * The test checks the following assertions: + * - MethodExitEvent is not received by debugger if the method + * terminated with thrown exception in debugged VM; + * A debugger class - nsk.jdi.MethodExitEvent._itself_.methodexit001 ; + * a debuggee class - nsk.jdi.MethodExitEvent._itself_.methodexit001a . + * The test uses supporting nsk/share/jdi classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates MethodEntryRequest filtered to class. + * Also it sets two breakpoint in debuggee before and after invoking + * checked method . + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee recurcively + * invokes method. This method throws user-defined uncatched exception + * . + * The debugger switches to to listen the event during the + * time specified by parameter. When BreakpointEvent for the first + * breakpoint is received, MethodEntryRequest becomes enabled. + * checks all received MetodEntryEvents until second breakpoint is reached + * and MethodEntryRequest becomes disabled. + * If debugger receives MethodEntryEvent for the checked method it + * complains an error message. + * Finally, debugger sends debuggee command QUIT and checks number of recieved + * events. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4433805 EventSet.resume() for VMStartEvent resumes thread suspended by breakpoint request + * Standard method Debugee.endDebugee() is used instead of cleaning event queue on debuggee VM exit. + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitEvent._itself_.methodexit001 + * nsk.jdi.MethodExitEvent._itself_.methodexit001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitEvent._itself_.methodexit001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001a.java new file mode 100644 index 00000000000..681926b4c7e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/_itself_/methodexit001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +// This class is the debugged application in the test +public class methodexit001a { + + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // line numbers for auxilary breakpoints + public static final int STARTING_BREAKPOINT_LINE = 81; + public static final int ENDING_BREAKPOINT_LINE = 90; + + // scaffold objects + static private ArgumentHandler argHandler; + static private Log log; + static private IOPipe pipe; + + // flags and counters + static private boolean methodInvoked; + + // start debuggee + public static void main(String args[]) { + methodexit001a _methodexit001a = new methodexit001a(); + System.exit(JCK_STATUS_BASE + _methodexit001a.run(args, System.err)); + } + + // perform the test + static int run(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + pipe = argHandler.createDebugeeIOPipe(); + + // notify debugger that debuggee has been started + pipe.println(COMMAND_READY); + + // wait for GO commnad from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + methodInvoked = false; // STARTING_BREAKPOINT_LINE + + // invoke checked method with exception caught + try { + foo(); + } catch (methodexit001e e) { + // do not invoke any methods here to prevent from generation of events + } + + methodInvoked = true; // ENDING_BREAKPOINT_LINE + + // notify debugger that checked method has been invoked + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + return PASSED; + } + + // checked method + static void foo() throws methodexit001e { + throw new methodexit001e(); + } +} + +// checked exception +class methodexit001e extends Exception {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001.java new file mode 100644 index 00000000000..510965ac480 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001.java @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitEvent.method; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.List; +import java.util.Iterator; +import java.lang.Thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// This class is the debugger application in the test +public class method001 { + + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // timeout interval for waiting events in a loop + static final int TIMEOUT_DELTA = 1000; // milliseconds + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // class names + static final String TEST_NAME = "nsk.jdi.MethodExitEvent.method.method001"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + + // JDI scaffold objects + static private Debugee debuggee; + static private IOPipe pipe; + static private VirtualMachine vm; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + // mirrors for tested debuggee entities + static private MethodExitRequest checkedRequest; + static private ThreadReference checkedThread; + static private Method checkedMethod; + static private Field checkedField; + static private ReferenceType checkedClass; + static private Field depthField; + + // auxilary breakpoints + static private BreakpointRequest startingBreakpointRequest; + static private BreakpointRequest endingBreakpointRequest; + static private Method runMethod; + + // flags and counters + static private long eventTimeout; + static private int depthVal, eventsCounter; + static private volatile boolean testFailed, eventReceived; + + // start test from command line + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + // start test from JCK-compatible environment + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + eventsCounter = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + try { + + // wait for debugee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // get mirrors for checked class, thread, and method + + vm = debuggee.VM(); + + log.display("Getting loaded class in debuggee"); + checkedClass = debuggee.classByName(DEBUGGEE_NAME); + + log.display("Getting reference to thread
    "); + checkedThread = debuggee.threadByName("main"); + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + log.display("Getting reference to method "); + checkedMethod = debuggee.methodByName(checkedClass, "foo"); + if (checkedMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + + log.display("Getting reference to field "); + checkedField = checkedClass.fieldByName("flag"); + if (checkedField == null) { + throw new Failure("TEST BUG: unable to find reference to field "); + } + + log.display("Getting reference to field "); + depthField = checkedClass.fieldByName("depth"); + if (depthField == null) { + throw new Failure("TEST BUG: unable to find reference to field "); + } + + log.display("Getting value of field "); + try { + depthVal = ((IntegerValue)checkedClass.getValue(depthField)).value(); + log.display("depth == " + depthVal); + } catch (ClassCastException e) { + throw new Failure("TEST BUG: cannot get value of field"); + } + + // create event request (initially disabled) + + EventRequestManager eventRManager = vm.eventRequestManager(); + log.display("Creating MethodExitRequest"); + if ((checkedRequest = eventRManager.createMethodExitRequest()) == null) { + throw new Failure("TEST BUG: unable to create MethodExitRequest"); + } + + checkedRequest.addThreadFilter(checkedThread); + checkedRequest.addClassFilter(checkedClass); + checkedRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + + switch (checkedRequest.suspendPolicy()) { + case EventRequest.SUSPEND_ALL: + log.display(" suspend policy is SUSPEND_ALL"); + break; + case EventRequest.SUSPEND_EVENT_THREAD: + log.display(" suspend policy is SUSPEND_EVENT_THREAD"); + break; + case EventRequest.SUSPEND_NONE: + log.display(" suspend policy is SUSPEND_NONE"); + break; + default: + log.complain("TEST BUG: Unknown suspend policy!"); + } + + log.display("MethodExitRequest is created"); + + // create two auxilary breakpoints + + log.display("Getting reference to method "); + runMethod = debuggee.methodByName(checkedClass, "run"); + if (runMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + + log.display("Creating two auxilary breakpoints into method "); + startingBreakpointRequest = debuggee.setBreakpoint(runMethod, method001a.STARTING_BREAKPOINT_LINE); + endingBreakpointRequest = debuggee.setBreakpoint(runMethod, method001a.ENDING_BREAKPOINT_LINE); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + while (!eventReceived) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + // enable or disable checked event request at BreakpointEvent + if (event instanceof BreakpointEvent) { + Location eventLocation = ((BreakpointEvent)event).location(); + int lineNumber = eventLocation.lineNumber(); + log.display("BreakpointEvent received for location " + lineNumber); + if (lineNumber == method001a.STARTING_BREAKPOINT_LINE) { + log.display("Enabling MethodExitRequest at breakpoint before invoking method"); + checkedRequest.enable(); + } else if (lineNumber == method001a.ENDING_BREAKPOINT_LINE) { + log.display("Disabling MethodExitRequest at breakpoint after invoking method"); + checkedRequest.disable(); + eventReceived = true; + } else { + testFailed = true; + throw new Failure("TEST BUG: Unknown location of breakpoint event: " + lineNumber); + } + } + + if (event instanceof MethodExitEvent) { + MethodExitEvent castedEvent = (MethodExitEvent) event; + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 2: eventRequest is not equal to checked request"); + testFailed = true; + } + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 3: eventThread is not equal to checked thread"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 4: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + Method method1 = castedEvent.method(); + Method method2 = castedEvent.method(); + if (!method1.equals(method2)) { + log.complain("FAILURE 7: return of MethodExitEvent.method() is inconsistent"); + testFailed = true; + } + + if (castedEvent.method().equals(checkedMethod)) { + eventsCounter++; + log.display("MethodExitEvent is received for method " + checkedMethod.name() + ", counter = " + eventsCounter); + try { + int flagVal = ((IntegerValue)checkedClass.getValue(checkedField)).value(); + log.display("flag == " + flagVal); + if ( flagVal != 3) { + if (!eventThread.isSuspended()) { + log.complain("FAILURE 5: eventThread is not suspended"); + } else { + log.complain("FAILURE 6: last execution code of the method is not yet executed"); + } + testFailed = true; + } + } catch (ClassCastException e) { + log.complain("TEST BUG: cannot get value of field"); + testFailed = true; + } + } + } + } + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to invoke method + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // waiting for debuggee comfirms method invoked + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check whether all expected events received or not + if (eventsCounter == 0) { + log.complain("FAILURE 1: No any MethodExitEvent received"); + testFailed = true; + } else if (eventsCounter < depthVal) { + log.complain("FAILURE 1: Some " + (depthVal - eventsCounter) + " MethodExitEvent NOT received (too few)"); + testFailed = true; + } else if (eventsCounter > depthVal) { + log.complain("FAILURE 1: Extra " + (eventsCounter - depthVal) + " MethodExitEvent received (too many)"); + testFailed = true; + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debuggee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analyze its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001/TestDescription.java new file mode 100644 index 00000000000..0ca6a2d5215 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001/TestDescription.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodExitEvent/method/method001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.MethodExitEvent.method() method. + * The test checks the following assertions: + * - MethodExitEvent is received by debugger for requested + * method if this method is normally exited by some + * executing thread in debugged VM; + * - received MethodExitEvent has proper references to: + * method, + * debugged VM, + * executed thread, + * related MethodExitRequest. + * - MethodExitEvent is emitted after last executed code of the + * method. + * A debugger class - nsk.jdi.MethodExitEvent.method.method001 ; + * a debuggee class - nsk.jdi.MethodExitEvent.method.method001a . + * The test uses supporting nsk/share/jdi classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates MethodEntryRequest filtered to class. + * Also it sets two breakpoint in debuggee before and after invoking + * checked method . + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee recurcively + * invokes method. This method updates field of + * class. + * The debugger switches to to listen the event during the + * time specified by parameter. When BreakpointEvent for the first + * breakpoint is received, MethodExitRequest becomes enabled. + * checks all received MetodExitEvents until second breakpoint is reached + * and MethodExitRequest becomes disabled. + * Each time the debugger receives MethodExitEvent, it compares all refencies + * of this event ( , , , ) + * with expected values. If the event belongs to method, value + * of field is checked. + * Finally, debugger sends debuggee command and checks number of recieved + * events. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4433805 EventSet.resume() for VMStartEvent resumes thread suspended by breakpoint request + * Standard method Debugee.endDebugee() is used instead of cleaning event queue on debuggee VM exit. + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitEvent.method.method001 + * nsk.jdi.MethodExitEvent.method.method001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitEvent.method.method001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001a.java new file mode 100644 index 00000000000..0463c80d3a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method001a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitEvent.method; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +// This class is the debugged application in the test +public class method001a { + + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // line numbers for auxilary breakpoints + public static final int STARTING_BREAKPOINT_LINE = 86; + public static final int ENDING_BREAKPOINT_LINE = 91; + + // scaffold objects + static private ArgumentHandler argHandler; + static private Log log; + static private IOPipe pipe; + + // flags and counters + static private int flag; + static private int depth; + static private boolean methodInvoked; + + // start debuggee + public static void main(String args[]) { + method001a _method001a = new method001a(); + System.exit(JCK_STATUS_BASE + _method001a.run(args, System.err)); + } + + // perform the test + int run(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + pipe = argHandler.createDebugeeIOPipe(); + + depth = 10; + flag = 0; + + // notify debugger that debuggee has been started + pipe.println(COMMAND_READY); + + // wait for GO commnad from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + methodInvoked = false; // STARTING_BREAKPOINT_LINE + + // invoke checked method + foo(); + + methodInvoked = true; // ENDING_BREAKPOINT_LINE + + // notify debugger that checked method has been invoked + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + return PASSED; + } + + // checked method + void foo() { + flag = 1; + if (depth > 1) { + depth--; + foo(); + } + flag = 3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002.java new file mode 100644 index 00000000000..f6b61c1e872 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002.java @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitEvent.method; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.List; +import java.util.Iterator; +import java.lang.Thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class method002 { + + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // timeout interval for waiting events in a loop + static final int TIMEOUT_DELTA = 1000; // milliseconds + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // class names + static final String TEST_NAME = "nsk.jdi.MethodExitEvent.method.method002"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + static final String CHILD_NAME = TEST_NAME + "child"; + + // JDI scaffold objects + static private Debugee debuggee; + static private IOPipe pipe; + static private VirtualMachine vm; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + // mirrors for tested debuggee entities + static private MethodExitRequest checkedRequest; + static private ThreadReference checkedThread; + static private Method checkedMethod; + static private Field checkedField; + static private ReferenceType checkedClass; + static private ReferenceType debuggeeClass; + + // auxilary breakpoints + static private BreakpointRequest startingBreakpointRequest; + static private BreakpointRequest endingBreakpointRequest; + static private Method runMethod; + + // flags and counters + static private long eventTimeout; + static private boolean testFailed; + static private boolean eventReceived; + static private int eventsCount; + + // start test from command line + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + // start test from JCK-compatible environment + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + eventsCount = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + try { + + // wait for debugee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // get mirrors for checked class, thread, and method + + vm = debuggee.VM(); + + log.display("Getting loaded classes in debuggee"); + debuggeeClass = debuggee.classByName(DEBUGGEE_NAME); + checkedClass = debuggee.classByName(CHILD_NAME); + + log.display("Getting reference to thread
    "); + checkedThread = debuggee.threadByName("main"); + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + log.display("Getting reference to method "); + checkedMethod = debuggee.methodByName(checkedClass, "foo"); + if (checkedMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + if (checkedMethod.isAbstract()) { + throw new Failure("TEST BUG: found method is abstract"); + } + + log.display("Getting reference to field "); + checkedField = checkedClass.fieldByName("counter"); + if (checkedField == null) { + throw new Failure("TEST BUG: unable to find reference to field "); + } + + // create event request (initially disabled) + + log.display("Creating MethodExitRequest"); + if ((checkedRequest = vm.eventRequestManager().createMethodExitRequest()) == null) { + throw new Failure("TEST BUG: unable to create MethodExitRequest"); + } + + checkedRequest.addThreadFilter(checkedThread); + checkedRequest.addClassFilter(checkedClass); + checkedRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + + switch (checkedRequest.suspendPolicy()) { + case EventRequest.SUSPEND_ALL: + log.display(" suspend policy is SUSPEND_ALL"); + break; + case EventRequest.SUSPEND_EVENT_THREAD: + log.display(" suspend policy is SUSPEND_EVENT_THREAD"); + break; + case EventRequest.SUSPEND_NONE: + log.display(" suspend policy is SUSPEND_NONE"); + break; + default: + log.complain("TEST BUG: Unknown suspend policy!"); + } + + log.display("MethodExitRequest is created"); + + // create two auxilary breakpoints + + log.display("Getting reference to method "); + runMethod = debuggee.methodByName(debuggeeClass, "run"); + if (runMethod == null) { + throw new Failure("TEST BUG: returned null reference to method "); + } + + log.display("Creating two auxilary breakpoints into method "); + startingBreakpointRequest = debuggee.setBreakpoint(runMethod, method002a.STARTING_BREAKPOINT_LINE); + endingBreakpointRequest = debuggee.setBreakpoint(runMethod, method002a.ENDING_BREAKPOINT_LINE); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + while (!eventReceived) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + // enable or disable checked event request at BreakpointEvent + if (event instanceof BreakpointEvent) { + Location eventLocation = ((BreakpointEvent)event).location(); + int lineNumber = eventLocation.lineNumber(); + log.display("BreakpointEvent received for location " + lineNumber); + if (lineNumber == method002a.STARTING_BREAKPOINT_LINE) { + log.display("Enabling MethodExitRequest at breakpoint before invoking method"); + checkedRequest.enable(); + } else if (lineNumber == method002a.ENDING_BREAKPOINT_LINE) { + log.display("Disabling MethodExitRequest at breakpoint after invoking method"); + checkedRequest.disable(); + eventReceived = true; + } else { + testFailed = true; + throw new Failure("TEST BUG: Unknown location of breakpoint event: " + lineNumber); + } + } + + // handle checked MethodExitEvent + if (event instanceof MethodExitEvent) { + MethodExitEvent castedEvent = (MethodExitEvent) event; + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 2: eventRequest is not equal to checked request"); + testFailed = true; + } + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 3: eventThread is not equal to checked thread"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 4: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + if (castedEvent.method().equals(checkedMethod)) { + eventsCount++; + log.display("MethodExitEvent is received for method " + checkedMethod.name()); + try { + int counterVal = ((IntegerValue)checkedClass.getValue(checkedField)).value(); + log.display("Counter == " + counterVal); + if ( counterVal != 3) { + if (!eventThread.isSuspended()) { + log.complain("FAILURE 5: eventThread is not suspended"); + } else { + log.complain("FAILURE 6: last execution code of the method is not yet executed"); + } + testFailed = true; + } + } catch (ClassCastException e) { + log.complain("TEST BUG: cannot get value of field"); + testFailed = true; + } + } + } + } + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to invoke method + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // waiting for debuggee comfirms method invoked + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check whether all expected events received or not + if (eventsCount < 1) { + log.complain("FAILURE 1: No any MethodExitEvent received"); + testFailed = true; + } else if (eventsCount > 1) { + log.complain("FAILURE 1: Too many MethodExitEvent received: " + eventsCount); + testFailed = true; + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debuggee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analyze its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + + } + + // create breakpoint request for given method and line number + private static BreakpointRequest setBreakpoint(Method method, int line) { + + // find location for the given line + List allLineLocations = null; + try { + allLineLocations = method.allLineLocations(); + } catch ( AbsentInformationException e) { + throw new Failure("TEST BUG: caught AbsentInformationException " + e); + } + + Location foundLocation = null; + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location location = (Location)locIterator.next(); + if (location.lineNumber() == line) { + foundLocation = location; + break; + } + } + if (foundLocation == null) { + throw new Failure("TEST BUG: unable to find breakpoint location for line number " + line); + } + + // create and enable breakpoint request + log.display("Setting breakpoint at location: " + foundLocation); + BreakpointRequest breakpointRequest = vm.eventRequestManager().createBreakpointRequest(foundLocation); + if (breakpointRequest == null) { + throw new Failure("TEST BUG: unable to create BreakpointRequest"); + } + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + breakpointRequest.enable(); + + return breakpointRequest; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002/TestDescription.java new file mode 100644 index 00000000000..a424c05e417 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodExitEvent/method/method002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.MethodExitEvent.method() method. + * The test checks the following assertions: + * - MethodExitEvent is received by debugger for requested + * method if this method is invoked by some executing thread + * in debugged VM; + * - received MethodExitEvent has proper references to: + * method, + * debugged VM, + * executed thread, + * related MethodExitRequest. + * - MethodExitEvent is generated after last executed code of the + * method. + * A debugger class - nsk.jdi.MethodExitEvent.method.method002 ; + * a debuggee class - nsk.jdi.MethodExitEvent.method.method002a . + * The test uses supporting nsk/share/jdi classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates MethodEntryRequest filtered to class. + * Also it sets two breakpoint in debuggee before and after invoking + * checked method . + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee creates variable + * of class. This class implements abstract method + * of class. The method is invoked. The + * implementing method updates field of class. + * The debugger switches to to listen the event during the + * time specified by parameter. When BreakpointEvent for the first + * breakpoint is received, MethodEntryRequest becomes enabled. + * checks all received MetodEntryEvents until second breakpoint is reached + * and MethodEntryRequest becomes disabled. + * Each time the debugger receives MethodEntryEvent, it compares all refencies + * of this event ( , , , ) + * with expected values. If the event belongs to method, value + * of field is checked. + * Finally, debugger sends debuggee command QUIT and checks number of recieved + * events. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4433805 EventSet.resume() for VMStartEvent resumes thread suspended by breakpoint request + * Standard method Debugee.endDebugee() is used instead of cleaning event queue on debuggee VM exit. + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method for setting breapoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitEvent.method.method002 + * nsk.jdi.MethodExitEvent.method.method002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitEvent.method.method002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002a.java new file mode 100644 index 00000000000..5f23f9b3070 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/method/method002a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitEvent.method; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +// This class is the debugged application in the test +public class method002a { + + // exit status constants + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // synchronization commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // line numbers for auxilary breakpoints + public static final int STARTING_BREAKPOINT_LINE = 83; + public static final int ENDING_BREAKPOINT_LINE = 88; + + // scaffold objects + static private ArgumentHandler argHandler; + static private Log log; + static private IOPipe pipe; + + // flags and counters + static private boolean methodInvoked; + + // start debuggee + public static void main(String args[]) { + method002a _method002a = new method002a(); + System.exit(JCK_STATUS_BASE + _method002a.run(args, System.err)); + } + + // perform the test + static int run(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + pipe = argHandler.createDebugeeIOPipe(); + + method002parent a = new method002child(); + + // notify debugger that debuggee has been started + pipe.println(COMMAND_READY); + + // wait for GO commnad from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + methodInvoked = false; // STARTING_BREAKPOINT_LINE + + // invoke checked method + a.foo(); + + methodInvoked = true; // ENDING_BREAKPOINT_LINE + + // notify debugger that checked method has been invoked + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + return PASSED; + } +} + +abstract class method002parent { + abstract void foo(); +} + +class method002child extends method002parent { + static private int counter = 0; + + void foo() { + counter++; counter *= 3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001.java new file mode 100644 index 00000000000..9cc8f688eb2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodExitEvent/returnValue/returnValue001. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that method 'MethodExitEvent.returnValue()' returns the value that the method will return. + * Test generates MethodExitEvents for methods with following return types: + * - void + * - all primitive types + * - array of objects + * - String + * - Thread + * - ThreadGroup + * - Class + * - ClassLoader + * - Object + * - wrappers for all primitive types + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitEvent.returnValue.returnValue001.returnValue001 + * nsk.jdi.MethodExitEvent.returnValue.returnValue001.returnValue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitEvent.returnValue.returnValue001.returnValue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.MethodExitEvent.returnValue.returnValue001; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.*; +import nsk.share.jdi.*; +import nsk.share.jpda.ForceEarlyReturnTestThread; + +/* + * Test checks that method 'MethodExitEvent.returnValue()' returns the value that the method will return. + * For generation MethodExitEvent for methods with different return types class ForceEarlyReturnTestThread is used. + * This test thread executes in loop methods with following return types: + * - void + * - all primitive types + * - array of objects + * - String + * - Thread + * - ThreadGroup + * - Class + * - ClassLoader + * - Object + * - wrappers for all primitive types + * + * Returned values are stored in ForceEarlyReturnTestThread's static fields. Test receives MethodExitEvent, obtains value + * of corresponding static field and compares this value with result of 'MethodExitEvent.returnValue()'. + */ +public class returnValue001 extends TestDebuggerType2 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new returnValue001().runIt(argv, out); + } + + protected String debuggeeClassName() { + return returnValue001a.class.getName(); + } + + protected boolean canRunTest() { + return vm.canGetMethodReturnValues(); + } + + // event listener handles MethodExitEvents + class EventListener extends EventHandler.EventListener { + private int eventCounter; + + private int expectedEventNumber; + + volatile boolean allEventsWereReceived; + + private List expectedTypes = new ArrayList(); + + public EventListener() { + for (String typeName : ForceEarlyReturnTestThread.testedTypesNames) + expectedTypes.add(typeName); + expectedEventNumber = expectedTypes.size(); + } + + public boolean eventReceived(Event event) { + if (event instanceof MethodExitEvent) { + + /* + * ForceEarlyReturnTestThread has several methods with different return types which are called + * in special manner: "Method", for example BooleanMethod. Return values for this methods + * are stored in ForceEarlyReturnTestThread's static fields which are named "unexpectedValue", + * for example "unexpectedBooleanValue". + * When MethodExitEvent is received EventListener finds method name for received MethodExitEvent and if + * method's name has form "Method" EventListener constructs static field name for corresponding + * type, obtains static field value and compares this value with result of MethodExitEvent.returnValue(). + */ + MethodExitEvent methodExitEvent = (MethodExitEvent) event; + String methodName = methodExitEvent.method().name(); + + int index = methodName.indexOf("Method"); + + if (index > 0) { + + String typeName = methodName.substring(0, index); + + if (expectedTypes.contains(typeName)) { + log.display("Received event for method: " + methodExitEvent.method()); + expectedTypes.remove(typeName); + + Value expectedReturnValue; + + if (typeName.equals("Void")) { + expectedReturnValue = vm.mirrorOfVoid(); + } else { + ReferenceType referenceType = debuggee.classByName(ForceEarlyReturnTestThread.class.getName()); + expectedReturnValue = referenceType.getValue(referenceType.fieldByName("unexpected" + typeName + "Value")); + } + + Value returnValue = methodExitEvent.returnValue(); + + if (!returnValue.equals(expectedReturnValue)) { + setSuccess(false); + log.complain("Unexpected return value: " + returnValue + ", expected is " + expectedReturnValue); + } else { + log.display("Return value for method '" + methodName + "': " + returnValue); + } + + eventCounter++; + + if (eventCounter == expectedEventNumber) { + allEventsWereReceived = true; + log.display("All expected events were received"); + methodExitEvent.request().disable(); + testStopWicket.unlock(); + } + } + } + + methodExitEvent.thread().resume(); + + return true; + } + + return false; + } + } + + private Wicket testStopWicket = new Wicket(); + + public void doTest() { + // create request for MethodExitEvents generated by ForceEarlyReturnTestThread + MethodExitRequest request = debuggee.getEventRequestManager().createMethodExitRequest(); + ReferenceType referenceType = debuggee.classByName(ForceEarlyReturnTestThread.class.getName()); + request.addClassFilter(referenceType); + request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + request.enable(); + + // start event handler + EventHandler eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + // add event listener which handles MethodExit events + EventListener listener = new EventListener(); + eventHandler.addListener(listener); + + // start thread generating MethodExitEvent + pipe.println(returnValue001a.COMMAND_START_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + // EventListener should notify main thread when all event are received + testStopWicket.waitFor(argHandler.getWaitTime() * 60000); + + if (!listener.allEventsWereReceived) { + setSuccess(false); + log.complain("ERROR: not all events were received"); + } + + pipe.println(returnValue001a.COMMAND_STOP_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + eventHandler.stopEventHandler(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001a.java new file mode 100644 index 00000000000..6ef859c90c9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue001/returnValue001a.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.MethodExitEvent.returnValue.returnValue001; + +import nsk.share.TestBug; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/* + * Debuggee class, handles commands for starting and stoping ForceEarlyReturnTestThread. + */ +public class returnValue001a extends AbstractJDIDebuggee { + + public static void main(String args[]) { + new returnValue001a().doTest(args); + } + + public static final String COMMAND_START_TEST_THREAD = "COMMAND_START_TEST_THREAD"; + + public static final String COMMAND_STOP_TEST_THREAD = "COMMAND_STOP_TEST_THREAD"; + + public String[] doInit(String args[]) { + args = super.doInit(args); + + try { + // load ForceEarlyReturnTestThread class to let debugger get instance of ReferenceType for this class + Class.forName(ForceEarlyReturnTestThread.class.getName()); + } catch (Throwable t) { + setSuccess(false); + System.out.println("Unexpected exception during initialization: " + t); + t.printStackTrace(); + throw new TestBug("Unexpected exception during initialization: " + t); + } + + return args; + } + + private ForceEarlyReturnTestThread testThread; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_TEST_THREAD)) { + + if (testThread != null) + throw new TestBug("Thread is already created"); + + testThread = new ForceEarlyReturnTestThread(log, false, 1); + testThread.start(); + testThread.startExecuion(); + + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREAD)) { + + if (testThread == null) + throw new TestBug("Thread isn't created"); + + testThread.stopExecution(); + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + return true; + } + + return false; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002.java new file mode 100644 index 00000000000..c4c48f27541 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodExitEvent/returnValue/returnValue002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test checks that method 'MethodExitEvent.returnValue()' returns VoidValue when event is generated + * for static initializer, constructor and static method. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitEvent.returnValue.returnValue002.returnValue002 + * nsk.jdi.MethodExitEvent.returnValue.returnValue002.returnValue002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitEvent.returnValue.returnValue002.returnValue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.MethodExitEvent.returnValue.returnValue002; + +import java.io.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.*; +import nsk.share.jdi.*; + +/* + * Test checks that method 'MethodExitEvent.returnValue()' returns VoidValue for static initializer, class constructor + * and static method. + */ +public class returnValue002 extends TestDebuggerType2 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new returnValue002().runIt(argv, out); + } + + protected String debuggeeClassName() { + return returnValue002a.class.getName(); + } + + protected boolean canRunTest() { + return vm.canGetMethodReturnValues(); + } + + class EventListener extends EventHandler.EventListener { + + private volatile boolean allEventsWereReceived; + + private boolean staticInitializerEventReceived; + private boolean constructorEventReceived; + private boolean staticMethodEventReceived; + + public boolean eventReceived(Event event) { + if (event instanceof MethodExitEvent) { + MethodExitEvent methodExitEvent = (MethodExitEvent) event; + + log.display("Received event for method: " + methodExitEvent.method()); + + if (methodExitEvent.method().name().equals("")) { + log.display("Static initializer event received"); + staticInitializerEventReceived = true; + } + + if (methodExitEvent.method().name().equals("")) { + log.display("Constructor event received"); + constructorEventReceived = true; + } + + if (methodExitEvent.method().name().equals("staticMethod")) { + log.display("Static method event received"); + staticMethodEventReceived = true; + } + + if (!methodExitEvent.returnValue().equals(vm.mirrorOfVoid())) { + setSuccess(false); + log.complain("Unexpected return value: " + methodExitEvent.returnValue() + ", expected is " + vm.mirrorOfVoid()); + } + + // expect events for static initializer, constructor, static method + if (staticInitializerEventReceived && constructorEventReceived && staticMethodEventReceived) { + allEventsWereReceived = true; + log.display("All expected events were received"); + methodExitEvent.request().disable(); + testStopWicket.unlock(); + } + + methodExitEvent.thread().resume(); + + return true; + } + + return false; + } + } + + private Wicket testStopWicket = new Wicket(); + + public void doTest() { + // create MethodExitRequest for events generated for returnValue002a.TestClass methods + MethodExitRequest request = debuggee.getEventRequestManager().createMethodExitRequest(); + request.addClassFilter(returnValue002a.TestClass.class.getName()); + request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + request.enable(); + + // start event handler + EventHandler eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + // add event listener which handles MethodExitEvents + EventListener listener = new EventListener(); + eventHandler.addListener(listener); + + pipe.println(returnValue002a.COMMAND_START_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + // EventListener should notify main thread when all event are received + testStopWicket.waitFor(argHandler.getWaitTime() * 60000); + + if (!listener.allEventsWereReceived) { + setSuccess(false); + log.complain("ERROR: not all events were received, possible there is error in test logic"); + } + + pipe.println(returnValue002a.COMMAND_STOP_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + eventHandler.stopEventHandler(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002a.java new file mode 100644 index 00000000000..35af72be4ea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue002/returnValue002a.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.MethodExitEvent.returnValue.returnValue002; + +import nsk.share.TestBug; +import nsk.share.jdi.*; + +/* + * Debuggee class, handles command for starting test thread which creates instance + * of returnValue002a.TestClass. + */ +public class returnValue002a extends AbstractJDIDebuggee { + + public static void main(String args[]) { + new returnValue002a().doTest(args); + } + + // test class containig static initializer, constructor and static method + static class TestClass { + static { + System.out.println("TestClass static initializer"); + } + + public TestClass() { + System.out.println("TestClass constructor"); + } + + static void staticMethod() { + System.out.println("TestClass static method"); + } + } + + public static final String COMMAND_START_TEST_THREAD = "COMMAND_START_TEST_THREAD"; + + public static final String COMMAND_STOP_TEST_THREAD = "COMMAND_STOP_TEST_THREAD"; + + static class TestThread extends Thread { + public void run() { + // static initializer and constructor for class 'TestClass' are called here + new TestClass(); + TestClass.staticMethod(); + } + } + + private TestThread testThread; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_TEST_THREAD)) { + + if (testThread != null) + throw new TestBug("Thread is already created"); + + testThread = new TestThread(); + testThread.start(); + + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREAD)) { + + if (testThread == null) + throw new TestBug("Thread isn't created"); + + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + return true; + } + + return false; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003.java new file mode 100644 index 00000000000..4ea32650b4d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitEvent/returnValue/returnValue003. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that method 'MethodExitEvent.returnValue()' returns the value that the method will return. + * Test generates MethodExitEvents for methods with following return types: + * - void + * - all primitive types + * - array of objects + * - String + * - Thread + * - ThreadGroup + * - Class + * - ClassLoader + * - Object + * - wrappers for all primitive types + * Test checks case when MethodExitEvent is generated when method completes because of debugger calls method + * ThreadReference.forceEarlyReturn(). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitEvent.returnValue.returnValue003.returnValue003 + * nsk.jdi.MethodExitEvent.returnValue.returnValue003.returnValue003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitEvent.returnValue.returnValue003.returnValue003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.MethodExitEvent.returnValue.returnValue003; + +import java.io.PrintStream; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.jdi.TestDebuggerType2; +import nsk.share.jpda.ForceEarlyReturnTestThread; + +/* + * Test checks that method 'MethodExitEvent.returnValue()' returns the value that the method will return. + * Test checks case when MethodExitEvent is generated when method completes because of debugger calls method + * ThreadReference.forceEarlyReturn(). + * + * For generation MethodExitEvent for methods with different return types class ForceEarlyReturnTestThread is used. + * Values intended to return through ThreadReference.ForceEarlyReturn are stored in ForceEarlyReturnTestThread's static + * fields. + * + * This test thread executes methods with following return types: + * - void + * - all primitive types + * - array of objects + * - String + * - Thread + * - ThreadGroup + * - Class + * - ClassLoader + * - Object + * - wrappers for all primitive types + * + * Debugger sets breakpoints in all this methods and waits while BreakpointEvent occurs. When debuggee's + * test thread stops at breakpoint debugger calls forceEarlyReturn() with corresponding value, creates MethodExitEvent + * for test thread and resumes test thread. When MethodExitEvent is received debugger checks that + * MethodExitEvent.returnValue() returns the same value which was passed to the ThreadReference,forceEarlyReturn(). + */ +public class returnValue003 extends TestDebuggerType2 { + // Data for testing forceEarlyReturn for single method + // Contains following data: + // - tested method's name + // - breakpoint request for location in tested method + // InvalidTypeException is thrown + // - correct value to pass in forceEarlyReturn() + class TestData { + public TestData(ReferenceType referenceType, String methodName, int lineNumber, ThreadReference thread, Value returnValue) { + breakpointRequest = debuggee.makeBreakpoint(referenceType, methodName, lineNumber); + + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + breakpointRequest.addThreadFilter(thread); + breakpointRequest.enable(); + + this.returnValue = returnValue; + this.methodName = methodName; + } + + String methodName; + + BreakpointRequest breakpointRequest; + + Value returnValue; + } + + protected boolean canRunTest() { + return vm.canGetMethodReturnValues(); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new returnValue003().runIt(argv, out); + } + + protected String debuggeeClassName() { + return returnValue003a.class.getName(); + } + + private TestExecutorThread testThread; + + // predefined in TestThread values to pass in forceEarlyReturn() + private Value testValues[]; + + class TestExecutorThread extends Thread { + TestData testData[]; + + private ThreadReference thread; + + public TestExecutorThread(ReferenceType testedThreadReferenceType, String threadName) { + thread = debuggee.threadByName(threadName); + + testData = new TestData[ForceEarlyReturnTestThread.testedTypesNames.length]; + + for (int i = 0; i < testData.length; i++) { + testData[i] = new TestData(testedThreadReferenceType, ForceEarlyReturnTestThread.testedTypesNames[i] + "Method", + ForceEarlyReturnTestThread.breakpointLines[i], thread, testValues[i]); + } + } + + public void run() { + for (int i = 0; i < testData.length; i++) + test(testData[i]); + + log.display("Test executor thread exit"); + } + + public void test(TestData testData) { + BreakpointEvent breakPointEvent = waitForBreakpoint(testData.breakpointRequest); + + try { + log.display("Call forceEarlyReturn with value: " + testData.returnValue); + breakPointEvent.thread().forceEarlyReturn(testData.returnValue); + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e + ", method: " + testData.methodName); + e.printStackTrace(System.out); + } + + testMethodExitEvent(thread, testData.methodName, testData.returnValue); + } + } + + protected void testMethodExitEvent(ThreadReference thread, String methodName, Value expectedValue) { + MethodExitRequest methodExitRequest; + methodExitRequest = debuggee.getEventRequestManager().createMethodExitRequest(); + methodExitRequest.addThreadFilter(thread); + methodExitRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + methodExitRequest.enable(); + + EventListenerThread listenerThread = new EventListenerThread(methodExitRequest); + listenerThread.start(); + listenerThread.waitStartListen(); + + thread.resume(); + + Event event = listenerThread.getEvent(); + + if (event == null) { + setSuccess(false); + log.complain("MethodExitEvent was not generated " + ", method: " + methodName); + } else { + MethodExitEvent methodExitEvent = (MethodExitEvent) event; + if (!methodExitEvent.method().name().equals(methodName)) { + setSuccess(false); + log.complain("Invalid MethodExitEvent: expected method - " + methodName + ", actually - " + + methodExitEvent.method().name()); + } else { + Value returnValue = methodExitEvent.returnValue(); + + if (!returnValue.equals(expectedValue)) { + setSuccess(false); + log.complain("Unexpected result of MethodExitEvent.returnValue(): " + returnValue + ", expected is " + expectedValue); + } else { + log.display("Result of MethodExitEvent.returnValue():" + returnValue); + } + } + } + + methodExitRequest.disable(); + + thread.resume(); + } + + // initialize Values objects to pass in forceEarlyReturn() + protected void initTestValues() { + ReferenceType referenceType = debuggee.classByName(ForceEarlyReturnTestThread.class.getName()); + + Value voidValue = createVoidValue(); + + if (voidValue == null) { + setSuccess(false); + log.complain("Can't create void value"); + return; + } + + testValues = new Value[ForceEarlyReturnTestThread.testedTypesNames.length + 1]; + + testValues[0] = voidValue; + + for (int i = 1; i < ForceEarlyReturnTestThread.testedTypesNames.length; i++) + testValues[i] = referenceType.getValue(referenceType.fieldByName("expected" + ForceEarlyReturnTestThread.testedTypesNames[i] + "Value")); + } + + private void startTestThread() { + ReferenceType referenceType = debuggee.classByName(ForceEarlyReturnTestThread.class.getName()); + + testThread = new TestExecutorThread(referenceType, returnValue003a.testThreadName); + testThread.start(); + } + + private void waitTestEnd() { + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + initTestValues(); + + // start ForceEarlyReturnThread to let create breakpoints for this thread + pipe.println(returnValue003a.COMMAND_START_AND_SUSPEND_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + startTestThread(); + + pipe.println(returnValue003a.COMMAND_START_TEST_THREAD_EXECUTION); + + if (!isDebuggeeReady()) + return; + + waitTestEnd(); + + pipe.println(returnValue003a.COMMAND_STOP_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003a.java new file mode 100644 index 00000000000..a37475ecc32 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003a.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.MethodExitEvent.returnValue.returnValue003; + +import nsk.share.*; +import nsk.share.jpda.ForceEarlyReturnTestThread; +import nsk.share.jdi.*; + +/* + * Debuggee class, handles commands for starting and stoping ForceEarlyReturnTestThread. + */ +public class returnValue003a extends AbstractJDIDebuggee { + static { + try { + // load thread class to let debugger get ReferenceType for TestThread class + Class.forName(ForceEarlyReturnTestThread.class.getName()); + } catch (ClassNotFoundException e) { + System.out.println("ClassNotFoundException while loading test thread class: " + e); + e.printStackTrace(System.out); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + } + + public static void main(String args[]) { + new returnValue003a().doTest(args); + } + + // start and suspend test threads to let debugger initialize breakpoints (debugger should obtain ThreadReference) + // command:threadsNumber:iterationsNumber + public static final String COMMAND_START_AND_SUSPEND_TEST_THREAD = "startAndSuspendTestThread"; + + // let test threads continue execution + public static final String COMMAND_START_TEST_THREAD_EXECUTION = "startTestThreadExecution"; + + // stop test threads + public static final String COMMAND_STOP_TEST_THREAD = "stopTestThread"; + + public static final String testThreadName = "returnValue03_TestThread"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_AND_SUSPEND_TEST_THREAD)) { + startTestThread(); + return true; + } else if (command.equals(COMMAND_START_TEST_THREAD_EXECUTION)) { + startTestThreadsExecution(); + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREAD)) { + stopTestThreads(); + return true; + } + + return false; + } + + private ForceEarlyReturnTestThread testThread; + + private void startTestThread() { + testThread = new ForceEarlyReturnTestThread(log, true, 1); + testThread.setName(testThreadName); + testThread.start(); + } + + private void startTestThreadsExecution() { + if (testThread == null) { + throw new TestBug("Test threads wasn't started"); + } + testThread.startExecuion(); + } + + private void stopTestThreads() { + if (testThread == null) { + throw new TestBug("Test threads wasn't started"); + } + + testThread.stopExecution(); + + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + if (!testThread.getSuccess()) + setSuccess(false); + } + + // access to success status for TestThread + public void setSuccess(boolean value) { + super.setSuccess(value); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004.java new file mode 100644 index 00000000000..bda5f045d32 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodExitEvent/returnValue/returnValue004. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that method 'MethodExitEvent.returnValue()' returns the value that the method will return. + * Test checks case when MethodExitEvent are generated for native methods. + * Test generates MethodExitEvents for native methods with following return types: + * - void + * - all primitive types + * - array of objects + * - String + * - Thread + * - ThreadGroup + * - Class + * - ClassLoader + * - Object + * - wrappers for all primitive types + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitEvent.returnValue.returnValue004.returnValue004 + * nsk.jdi.MethodExitEvent.returnValue.returnValue004.returnValue004a + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.MethodExitEvent.returnValue.returnValue004.returnValue004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.MethodExitEvent.returnValue.returnValue004; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.*; +import nsk.share.jdi.*; +import nsk.share.jpda.NativeMethodsTestThread; + +/* + * Test checks that method 'MethodExitEvent.returnValue()' returns the value that the method will return + * (test checks case when events are generated for native methods). + * + * For generation MethodExitEvent for methods with different return types class NativeMethodsTestThread is used. + * This test thread executes native methods with following return types: + * - void + * - all primitive types + * - array of objects + * - String + * - Thread + * - ThreadGroup + * - Class + * - ClassLoader + * - Object + * - wrappers for all primitive types + * + * Returned values are stored in NativeMethodsTestThread's static fields. Test receives MethodExitEvent, obtains value + * of corresponding static field and compares this value with result of 'MethodExitEvent.returnValue()'. + */ +public class returnValue004 extends TestDebuggerType2 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new returnValue004().runIt(argv, out); + } + + protected String debuggeeClassName() { + return returnValue004a.class.getName(); + } + + protected boolean canRunTest() { + return vm.canGetMethodReturnValues(); + } + + // event listener handles MethodExitEvents + class EventListener extends EventHandler.EventListener { + private int eventCounter; + + private int expectedEventNumber; + + volatile boolean allEventsWereReceived; + + private List expectedTypes = new ArrayList(); + + public EventListener() { + for (String typeName : NativeMethodsTestThread.testedTypesNames) + expectedTypes.add(typeName); + expectedEventNumber = expectedTypes.size(); + } + + public boolean eventReceived(Event event) { + if (event instanceof MethodExitEvent) { + + /* + * NativeMethodsTestThread has several methods with different return types which are called + * in special manner: "Method", for example BooleanMethod. Return values for this methods + * are stored in NativeMethodsTestThread's static fields which are named "expectedValue", + * for example "expectedBooleanValue". + * When MethodExitEvent is received EventListener finds method name for received MethodExitEvent and if + * method's name has form "Method" EventListener constructs static field name for corresponding + * type, obtains static field value and compares this value with result of MethodExitEvent.returnValue(). + */ + MethodExitEvent methodExitEvent = (MethodExitEvent) event; + String methodName = methodExitEvent.method().name(); + + int index = methodName.indexOf("Method"); + + if (index > 0) { + + String typeName = methodName.substring(0, index); + + if (expectedTypes.contains(typeName)) { + log.display("Received event for method: " + methodExitEvent.method()); + expectedTypes.remove(typeName); + + Value expectedReturnValue; + + if (typeName.equals("Void")) { + expectedReturnValue = vm.mirrorOfVoid(); + } else { + ReferenceType referenceType = debuggee.classByName(NativeMethodsTestThread.class.getName()); + expectedReturnValue = referenceType.getValue(referenceType.fieldByName("expected" + typeName + "Value")); + } + + Value returnValue = methodExitEvent.returnValue(); + + if (!returnValue.equals(expectedReturnValue)) { + setSuccess(false); + log.complain("Unexpected return value: " + returnValue + ", expected is " + expectedReturnValue); + } else { + log.display("Return value for method '" + methodName + "': " + returnValue); + } + + eventCounter++; + + if (eventCounter == expectedEventNumber) { + allEventsWereReceived = true; + log.display("All expected events were received"); + methodExitEvent.request().disable(); + testStopWicket.unlock(); + } + } + } + + methodExitEvent.thread().resume(); + + return true; + } + + return false; + } + } + + private Wicket testStopWicket = new Wicket(); + + public void doTest() { + // create request for MethodExitEvents generated by NativeMethodsTestThread + MethodExitRequest request = debuggee.getEventRequestManager().createMethodExitRequest(); + ReferenceType referenceType = debuggee.classByName(NativeMethodsTestThread.class.getName()); + request.addClassFilter(referenceType); + request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + request.enable(); + + // start event handler + EventHandler eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + // add event listener which handles MethodExit events + EventListener listener = new EventListener(); + eventHandler.addListener(listener); + + // start thread generating MethodExitEvent + pipe.println(returnValue004a.COMMAND_START_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + // EventListener should notify main thread when all event are received + testStopWicket.waitFor(argHandler.getWaitTime() * 60000); + + if (!listener.allEventsWereReceived) { + setSuccess(false); + log.complain("ERROR: not all events were received"); + } + + pipe.println(returnValue004a.COMMAND_STOP_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + eventHandler.stopEventHandler(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004a.java new file mode 100644 index 00000000000..7f5beb285f5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue004/returnValue004a.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.MethodExitEvent.returnValue.returnValue004; + +import nsk.share.TestBug; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/* + * Debuggee class, handles commands for starting and stoping ForceEarlyReturnTestThread. + */ +public class returnValue004a extends AbstractJDIDebuggee { + + public static void main(String args[]) { + new returnValue004a().doTest(args); + } + + public static final String COMMAND_START_TEST_THREAD = "COMMAND_START_TEST_THREAD"; + + public static final String COMMAND_STOP_TEST_THREAD = "COMMAND_STOP_TEST_THREAD"; + + public String[] doInit(String args[]) { + args = super.doInit(args); + + try { + // load ForceEarlyReturnTestThread class to let debugger get instance of ReferenceType for this class + Class.forName(NativeMethodsTestThread.class.getName()); + } catch (Throwable t) { + setSuccess(false); + System.out.println("Unexpected exception during initialization: " + t); + t.printStackTrace(); + throw new TestBug("Unexpected exception during initialization: " + t); + } + + return args; + } + + private NativeMethodsTestThread testThread; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_TEST_THREAD)) { + + if (testThread != null) + throw new TestBug("Thread is already created"); + + testThread = new NativeMethodsTestThread(log, false, 1); + testThread.start(); + testThread.startExecuion(); + + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREAD)) { + + if (testThread == null) + throw new TestBug("Thread isn't created"); + + testThread.stopExecution(); + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + return true; + } + + return false; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001.java new file mode 100644 index 00000000000..5a663348ae0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.MethodExitRequest._bounds_; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; + +import java.io.*; + +/** + * The test checks up the
    + * - addThreadFilter(ThreadReference)
    + * - addInstanceFilter(ObjectReference)
    + * - addClassFilter(ReferenceType)
    + * - addClassFilter(String)
    + * - addClassExclusionFilter(String)
    + * methods with null argument value. + * In any cases NullPointerException is expected. + */ +public class filters001 { + + private final static String prefix = "nsk.jdi.MethodExitRequest._bounds_."; + private final static String debuggerName = prefix + "filters001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + filters001 thisTest = new filters001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + display(""); + display(">>>creating MethodExitRequest"); + + MethodExitRequest request = + debugee.getEventRequestManager().createMethodExitRequest(); + + display(""); + addThreadFilter(request, null); + + display(""); + addInstanceFilter(request, null); + + display(""); + addClassFilter(request, (ReferenceType )null); + + display(""); + addClassFilter(request, (String )null); + + display(""); + addClassExclusionFilter(request, (String )null); + + display(""); + debugee.quit(); + } + + private void addThreadFilter(MethodExitRequest request, ThreadReference thread) { + String tmp = "addThreadFilter :thread name> "; + tmp += (thread == null) ? "" : thread.name(); + display(tmp); + + try { + request.addThreadFilter(thread); + if (thread==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (thread == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addInstanceFilter(MethodExitRequest request, + ObjectReference instance) { + String tmp = "addInstanceFilter :object value> "; + tmp += (instance == null) ? "" : instance.toString(); + display(tmp); + + try { + request.addInstanceFilter(instance); + if (instance==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (instance == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(MethodExitRequest request, ReferenceType refType) { + + display("addClassFilter :ReferenceType> <" + refType + ">"); + + try { + request.addClassFilter(refType); + if (refType==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (refType==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(MethodExitRequest request, String classPattern) { + + display("addClassFilter :classPattern> <" + classPattern + ">"); + try { + request.addClassFilter(classPattern); + if (classPattern==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (classPattern==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassExclusionFilter(MethodExitRequest request, + String classPattern) { + display("addExclusionClassFilter :classPattern> <" + classPattern + ">"); + try { + request.addClassExclusionFilter(classPattern); + if (classPattern==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (classPattern==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001/TestDescription.java new file mode 100644 index 00000000000..d2b20b92321 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/_bounds_/filters001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the methods + * com.sun.jdi.request.MethodExitRequest.addThreadFilter(ThreadReference) + * com.sun.jdi.request.MethodExitRequest.addInstanceFilter(ObjectReference) + * com.sun.jdi.request.MethodExitRequest.addClassFilter(ReferenceType) + * com.sun.jdi.request.MethodExitRequest.addClassFilter(String) + * com.sun.jdi.request.MethodExitRequest.addClassExclusionFilter(String) + * correctly work for the boundary value of parameter and throw described + * exceptions. + * The test check up this methods with argument value. In any cases + * NullPointerException is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest._bounds_.filters001 + * nsk.jdi.MethodExitRequest._bounds_.filters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest._bounds_.filters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001a.java new file mode 100644 index 00000000000..45dbb03d998 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/_bounds_/filters001a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.MethodExitRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filters001a is deugee's part of the test. + */ +public class filters001a { + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001.java new file mode 100644 index 00000000000..18684b56027 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodExitRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodExitRequest.addClassExclusionFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The case to checks a pattern that ends with '*'. + * + * The test works as follows. + * - The debugger + * - sets up two MethodExitRequests, + * - restricts the Requests using patterns 'java*' and 'sun*', + * so that events will be filtered only from test classes, + * - resumes the debuggee, and + * - waits for expected MethodExitEvents. + * - The debuggee creates and starts thread1, which being run, + * invoke methods used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter001a"; + return new filter001().runThis(argv, out); + } + + private String classExclName1 = "java"; + private String classExclName2 = "sun"; + private boolean methodExitReceived = false; + + protected void testRun() { + + MethodExitRequest eventRequest1 = null; + String thread1Name = "thread1"; + String property1 = "MethodExitRequest1"; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + ThreadReference thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting23MethodExitRequest( thread1, + EventRequest.SUSPEND_NONE, + property1); + + eventRequest1.addClassExclusionFilter(classExclName1 + "*"); + eventRequest1.addClassExclusionFilter(classExclName2 + "*"); + eventRequest1.enable(); + + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof MethodExitEvent) { + methodExitReceived = true; + String str = ((MethodExitEvent)event).location().declaringType().name(); + if (str.indexOf(classExclName1) == 0 || str.indexOf(classExclName2) == 0) { + setFailedStatus("Received unexpected MethodExitEvent for excluded class:" + str); + } else { + display("Received expected MethodExitEvent for " + str); + } + return true; + } + return false; + } + } + ); + + display("......waiting for MethodExitEvent in expected thread"); + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + if (!methodExitReceived) { + setFailedStatus("No MethodExitEvent was received."); + } + return; + } + + private MethodExitRequest setting23MethodExitRequest ( ThreadReference thread, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodExitRequest:"); + display(" thread: " + thread + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodExitRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001/TestDescription.java new file mode 100644 index 00000000000..b4fdf076ebb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateMethodExit - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter001; + * the debuggee program - nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter001 + * nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001a.java new file mode 100644 index 00000000000..ced41a717de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter001a.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter001 JDI test. + */ + +public class filter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter001a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter001a("thread1"); + log1("new filter001a().run1(thread1);"); + new filter001a().run1(thread1); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class Thread1filter001a extends Thread { + + class TestClass10{ + void m10() { + throw new NullPointerException("m10"); + } + } + class TestClass11 extends TestClass10{ + void m11() { + + try { + (new TestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } + } + + + String tName = null; + + public Thread1filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter001a.log1(" 'run': enter :: threadName == " + tName); + try { + (new TestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java new file mode 100644 index 00000000000..aabe8851b6b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodExitRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodExitRequest.addClassExclusionFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an MethodExitRequest and enables it,
    + * - invokes the method addClassExclusionFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassExclusionFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassExclusionFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter002a"; + + private String testedClassName1 = + "nsk.jdi.MethodExitRequest.addClassExclusionFilter.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "MethodExitRequest1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = setting23MethodExitRequest(null, testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + log2("breakpointForCommunication"); + + do { + getEventSet(); + + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) + return; + + log2(" received: " + event); + + if (EventFilters.filtered(event)) { + eventSet.resume(); + } + else { + break; + } + } while (true); + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest setting23MethodExitRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassExclusionFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + menr.addCountFilter(1); + + log2(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002/TestDescription.java new file mode 100644 index 00000000000..f2a8fc161af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateMethodExit - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateMethodExit - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter002; + * the debuggee program - nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter002 + * nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addClassExclusionFilter.filter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002a.java new file mode 100644 index 00000000000..4c4d4a8c3f3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002a.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter002 JDI test. + */ + +public class filter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + +// static Thread1filter002a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// thread1 = new Thread1filter002a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001.java new file mode 100644 index 00000000000..59e4f1d2ff7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodExitRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodExitRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or + * any of its subtypes. + * The cases to check include entering methods in four types, + * two in super-class filter_rt001aTestClass10 and its sub-class filter_rt001aTestClass11, and + * two in super-class filter_rt001aTestClass20 and its sub-class filter_rt001aTestClass21. + * A filter used restricts events only to methods in first pair. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a thread, thread1, invoking methods + * in the super-class filter_rt001aTestClass10 and its sub-class filter_rt001aTestClass11 and + * in the super-class filter_rt001aTestClass20 and its sub-class filter_rt001aTestClass21 + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes to use to filter MethodExitEvents, + * - sets up MethodExitRequest for the events, + * - restricts the events to those in filter_rt001aTestClass11, + * - and resumes the debuggee and waits for the events. + * - The debuggee starts the thread1. + * - Upon getting the events, the debugger performs checks required. + * + * In third phase, at the end of the test, the debuggee changes + * the value of the "instruction" which the debugger and debuggee + * use to inform each other of needed actions, and both end. + */ + +public class filter_rt001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt001a"; + return new filter_rt001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt001aTestClass11"; + + protected void testRun() { + EventRequest eventRequest1 = null; + String property1 = "MethodExitRequest1"; + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = (ReferenceType) debuggee.classByName(testedClassName); + + eventRequest1 = setting21MethodExitRequest(null, testClassReference, + EventRequest.SUSPEND_NONE, property1); + + display("......waiting for MethodExitEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, false); + + if ( !(newEvent instanceof MethodExitEvent)) { + setFailedStatus("ERROR: new event is not MethodExitEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodExitEvent with propety 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ReferenceType refType = ((MethodExitEvent)newEvent).location().declaringType(); + if (!refType.equals(testClassReference)) { + setFailedStatus("Received unexpected declaring type of the event: " + refType.name() + + "\n\texpected one: " + testClassReference.name()); + } + } + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodExitRequest setting21MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodExitRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodExitRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001/TestDescription.java new file mode 100644 index 00000000000..1c982f9a78f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt001; + * the debuggee program - nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt001 + * nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001a.java new file mode 100644 index 00000000000..5268ec4400a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001a.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt001 JDI test. + */ + +public class filter_rt001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt001aThread1 thread1 = null; +// static Thread2filter_rt001a thread2 = null; + + static filter_rt001aTestClass10 obj10 = new filter_rt001aTestClass10(); + static filter_rt001aTestClass11 obj11 = new filter_rt001aTestClass11(); + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new filter_rt001aThread1("thread1"); + + log1("new filter_rt001a().run1(thread1);"); + new filter_rt001a().run1(thread1); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt001aTestClass10{ + static void m10() { + filter_rt001a.log1("entered: m10()"); + } +} +class filter_rt001aTestClass11 extends filter_rt001aTestClass10{ + static void m11() { + filter_rt001a.log1("entered: m11()"); + filter_rt001aTestClass10.m10(); + } +} + +class filter_rt001aThread1 extends Thread { + + String tName = null; + + public filter_rt001aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + filter_rt001aTestClass21.m21(); + filter_rt001aTestClass11.m11(); + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt001aTestClass20{ + static void m20() { + filter_rt001a.log1("entered: m20()"); + } +} + +class filter_rt001aTestClass21 extends filter_rt001aTestClass20{ + static void m21() { + filter_rt001a.log1("entered: m21()"); + filter_rt001aTestClass20.m20(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java new file mode 100644 index 00000000000..2d66add566d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodExitRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodExitRequest.addClassFilter(ReferenceType)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a filter_rt002aTestClass10 object, to use as filter,
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an MethodExitRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_rt002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_rt002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt002a"; + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt002aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "MethodExitRequest1"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + eventRequest1 = setting21MethodExitRequest(null, testClassReference, + EventRequest.SUSPEND_NONE, property1); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" no InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testClassReference); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest setting21MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002/TestDescription.java new file mode 100644 index 00000000000..f306f68a81d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt002; + * the debuggee program - nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt002 + * nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002a.java new file mode 100644 index 00000000000..8f2de3ca6c5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002a.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt002 JDI test. + */ + +public class filter_rt002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt002aThread1 thread1 = null; + + static filter_rt002aTestClass10 obj = new filter_rt002aTestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new filter_rt002aThread1("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt002aTestClass10{ + void m10() { + throw new NullPointerException("m10"); + } +} +class filter_rt002aTestClass11 extends filter_rt002aTestClass10{ + void m11() { + + try { + (new filter_rt002aTestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } +} + +class filter_rt002aThread1 extends Thread { + + String tName = null; + + public filter_rt002aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt002a.log1(" 'run': enter :: threadName == " + tName); + try { + (new filter_rt002aTestClass11()).m11(); + } catch ( NullPointerException e) { + } + filter_rt002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003.java new file mode 100644 index 00000000000..c9247f89651 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodExitRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodExitRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to be + * the preparation of the given reference type and any subtypes. + * The cases to test include re-invocations of the method + * addClassFilter() on the same MethodExitRequest object. + * There are two MethodExitRequests to check as follows: + * (1) For MethodExitRequest2, both invocations are with different + * ReferenceTypes restricting one MethodExit event to two classes. + * The test expects no MethodExit event will be received. + * (2) For MethodExitRequest1, both invocations are with the same + * ReferenceType restricting one MethodExit event to one class. + * The test expects this MethodExit event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, + * invoking methods correspondingly + * in the super-class filter_rt003aTestClass10 and its sub-class filter_rt003aTestClass11 and + * in the super-class filter_rt003aTestClass20 and its sub-class filter_rt003aTestClass21, + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes 1&2 for the Classes to filter, + * - sets up two MethodExitRequests 1&2, + * - double restricts MethodExitRequest1 to the RefTypes 1 and 1, + * - double restricts MethodExitRequest2 to the RefTypes 1 and 2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - The debuggee creates and starts two threads, thread1 and thread2, + * generating the events to be filtered. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_rt003 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt003a"; + return new filter_rt003().runThis(argv, out); + } + + private String testedClassName11 = + "nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt003aTestClass11"; + + private String testedClassName21 = + "nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt003aTestClass21"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "MethodExitRequest1"; + String property2 = "MethodExitRequest2"; + + ReferenceType testClassReference11 = null; + ReferenceType testClassReference21 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference11 = (ReferenceType) debuggee.classByName(testedClassName11); + testClassReference21 = (ReferenceType) debuggee.classByName(testedClassName21); + + eventRequest1 = setting21MethodExitRequest(null, testClassReference11, + EventRequest.SUSPEND_ALL, property1); + + eventRequest2 = setting21MethodExitRequest(null, testClassReference11, + EventRequest.SUSPEND_ALL, property2); + + ((MethodExitRequest) eventRequest1).addClassFilter(testClassReference11); + ((MethodExitRequest) eventRequest2).addClassFilter(testClassReference21); + + display("......waiting for MethodExitEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, false); + + if ( !(newEvent instanceof MethodExitEvent)) { + setFailedStatus("ERROR: new event is not MethodExitEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodExitEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ReferenceType refType = ((MethodExitEvent)newEvent).location().declaringType(); + if (!refType.equals(testClassReference11)) { + setFailedStatus("Received unexpected declaring type of the event: " + refType.name() + + "\n\texpected one: " + testClassReference11.name()); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodExitRequest setting21MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodExitRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodExitRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003/TestDescription.java new file mode 100644 index 00000000000..15be6901d6e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt003; + * the debuggee program - nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt003 + * nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addClassFilter_rt.filter_rt003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003a.java new file mode 100644 index 00000000000..77c8e6fd1ef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt003a.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt003 JDI test. + */ + +public class filter_rt003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt003aThread1 thread1 = null; + static filter_rt003aThread2 thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + filter_rt003aTestClass11 obj1 = new filter_rt003aTestClass11(); + filter_rt003aTestClass21 obj2 = new filter_rt003aTestClass21(); + + thread1 = new filter_rt003aThread1("thread1"); + thread2 = new filter_rt003aThread2("thread2"); + + log1("debuggee started!"); + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + log1("new filter_rt003a().run1(thread1);"); + new filter_rt003a().run1(thread1); + + log1("new filter_rt003a().run1(thread2);"); + new filter_rt003a().run1(thread2); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + + +class filter_rt003aTestClass10{ + static void m10() { + filter_rt003a.log1("entered: m10()"); + } +} +class filter_rt003aTestClass11 extends filter_rt003aTestClass10{ + static void m11() { + filter_rt003a.log1("entered: m11()"); + filter_rt003aTestClass10.m10(); + } +} + +class filter_rt003aThread1 extends Thread { + + String tName = null; + + public filter_rt003aThread1(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + filter_rt003aTestClass11.m11(); + filter_rt003aTestClass21.m21(); + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt003aTestClass20{ + static void m20() { + filter_rt003a.log1("entered: m20()"); + } +} +class filter_rt003aTestClass21 extends filter_rt003aTestClass20{ + static void m21() { + filter_rt003a.log1("entered: m21()"); + filter_rt003aTestClass20.m20(); + } +} + +class filter_rt003aThread2 extends Thread { + + String tName = null; + + public filter_rt003aThread2(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + filter_rt003aTestClass21.m21(); + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001.java new file mode 100644 index 00000000000..a3cee6877eb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodExitRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodExitRequest.addClassFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The cases to check include both a pattern that begin with '*' and + * one that end with '*'. + * + * The test works as follows. + * - The debugger + * - sets up two MethodExitRequests, + * - restricts the Requests using patterns that begins with '*' and + * ends with *, + * - resumes the debuggee, and + * - waits for expected MethodExitEvents. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, invoke methods used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_s001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s001a"; + return new filter_s001().runThis(argv, out); + } + + private String testedClassName1 = "TestClass11"; + private String testedClassName2 = + "nsk.jdi.MethodExitRequest.addClassFilter_s.Thread2filter_s001a"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "MethodExitRequest1"; + String property2 = "MethodExitRequest2"; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + + eventRequest1 = setting22MethodExitRequest(null, "*" + testedClassName1, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for MethodExitEvent in expected class"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof MethodExitEvent)) { + setFailedStatus("ERROR: new event is not MethodExitEvent"); + } else { + String str = ((MethodExitEvent)newEvent).location().declaringType().name(); + if (!str.endsWith(testedClassName1)) { + setFailedStatus("Received MethodExitEvent for unexpected class: \n\t" + str); + } else { + display("Received MethodExitEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + + vm.resume(); + break; + + case 1: + eventRequest2 = setting22MethodExitRequest(null, testedClassName2 + "*", + EventRequest.SUSPEND_ALL, property2); + + display("......waiting for MethodExitEvent in expected class"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof MethodExitEvent)) { + setFailedStatus("ERROR: new event is not MethodExitEvent"); + } else { + + String str = ((MethodExitEvent)newEvent).location().declaringType().name(); + if (!str.endsWith(testedClassName2)) { + setFailedStatus("Received MethodExitEvent for unexpected class: \n\t" + str); + } else { + display("Received MethodExitEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property2) ) { + setFailedStatus("ERROR: property is not : " + property2); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodExitRequest setting22MethodExitRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodExitRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodExitRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001/TestDescription.java new file mode 100644 index 00000000000..43fc975b5d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addClassFilter() + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateMethodExit - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s001; + * the debuggee program - nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s001 + * nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001a.java new file mode 100644 index 00000000000..98064792489 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s001a.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s001 JDI test. + */ + +public class filter_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_s001a thread1 = null; + static Thread2filter_s001a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_s001a("thread1"); + log1("new filter_s001a().run1(thread1);"); + new filter_s001a().run1(thread1); + + break; + + case 1: + thread2 = new Thread2filter_s001a("thread2"); + log1("new filter_s001a().run1(thread2);"); + new filter_s001a().run1(thread2); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class TestClass10{ + static void m10() { + filter_s001a.log1(" entered: m10()"); + } +} +class TestClass11 extends TestClass10{ + static void m11() { + filter_s001a.log1(" entered: m11()"); + TestClass10.m10(); + } +} + +class Thread1filter_s001a extends Thread { + + String tName = null; + + public Thread1filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + TestClass11.m11(); + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class Thread2filter_s001a extends Thread { + + String tName = null; + + public Thread2filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + TestClass21.m21(); + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } + + static class TestClass20{ + static void m20() { + filter_s001a.log1(" entered: m20()"); + } + } + static class TestClass21 extends TestClass20{ + static void m21() { + filter_s001a.log1(" entered: m21()"); + TestClass20.m20(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java new file mode 100644 index 00000000000..ca18acbdec8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java @@ -0,0 +1,525 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodExitRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodExitRequest.addClassFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an MethodExitRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_s002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_s002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s002a"; + + private String testedClassName1 = + "nsk.jdi.MethodExitRequest.addClassFilter_s.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "MethodExitRequest1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + eventRequest1 = setting22MethodExitRequest(null, testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest setting22MethodExitRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002/TestDescription.java new file mode 100644 index 00000000000..6081a9081f9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addClassFilter() + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateMethodExit - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateMethodExit - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addClassFilter.filter_s002; + * the debuggee program - nsk.jdi.MethodExitRequest.addClassFilter.filter_s002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s002 + * nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addClassFilter_s.filter_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002a.java new file mode 100644 index 00000000000..730ffd2d567 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002a.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s002 JDI test. + */ + +public class filter_s002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + +// static Thread1filter_s002a thread1 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// thread1 = new Thread1filter_s002a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001.java new file mode 100644 index 00000000000..6cd7455ec8d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodExitRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodExitRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * in which the currently executing instance is + * the object specified. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a special array with three Object instances, + * and two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a MethodExitRequest + * within the method in the class instancefilter001aTestClass + * whose array element instances #0 and #1 + * will be calling by the thread1 and the thread2 accordinly, + * - invokes addInstanceFilter() on array element #0 for the thread1 + * and #2 for the thread2, + * thus restricting the MethodExit event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter001a"; + return new instancefilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter001aTestClass"; + + protected void testRun() { + + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodExitRequest1"; + String property2 = "MethodExitRequest2"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) debuggee.classByName(testedClassName); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + eventRequest1 = setting2MethodExitRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + ((MethodExitRequest) eventRequest1).addInstanceFilter(instance); + + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + eventRequest2 = setting2MethodExitRequest (thread2, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(2); + ((MethodExitRequest) eventRequest2).addInstanceFilter(instance); + + display("......waiting for MethodExitEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof MethodExitEvent)) { + setFailedStatus("ERROR: new event is not MethodExitEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodExitEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodExitRequest setting2MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodExitRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodExitRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001/TestDescription.java new file mode 100644 index 00000000000..7fce1e89b96 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter001; + * the debuggee program - nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter001 + * nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001a.java new file mode 100644 index 00000000000..1f6fdb36c6d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter001a.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter001 JDI test. + */ + +public class instancefilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter001aThread thread1 = null; + static instancefilter001aThread thread2 = null; + + static instancefilter001aTestClass objTC[] = { new instancefilter001aTestClass(), new instancefilter001aTestClass(), new instancefilter001aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1 = new instancefilter001aThread("thread1"); + thread2 = new instancefilter001aThread("thread2"); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter001aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter001aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter001aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java new file mode 100644 index 00000000000..2701981c4fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodExitRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodExitRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a MethodExitRequest and enables it,
    + * - invokes the method addInstanceFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addInstanceFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addInstanceFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter002a"; + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodExitRequest1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodExitRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + ((MethodExitRequest) eventRequest1).addInstanceFilter(instance); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" no InvalidRequestStateException expected"); + ((MethodExitRequest) eventRequest1).addInstanceFilter(instance); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest setting2MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002/TestDescription.java new file mode 100644 index 00000000000..de290d9c81f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter002; + * the debuggee program - nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter002 + * nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002a.java new file mode 100644 index 00000000000..65e0d85d8d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter002 JDI test. + */ + +public class instancefilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter002aThread thread1 = null; + + static instancefilter002aTestClass objTC[] = { new instancefilter002aTestClass(), new instancefilter002aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new instancefilter002aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter002aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter002aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter002aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java new file mode 100644 index 00000000000..6c2ad1daf54 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodExitRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodExitRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: UnsupportedOperationException -
    + * if the target virtual machine
    + * does not support this operation.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger creates
    + * a MethodExitRequest and if addInstanceFilter() is not supported,
    + * invokes the method on the request expecting
    + * to catch UnsupportedOperationException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter003a"; + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodExitRequest1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodExitRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + if ( vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == true :: test cancelled"); + } else { + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" UnsupportedOperationException expected"); + ((MethodExitRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no UnsupportedOperationException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" UnsupportedOperationException "); + } + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest setting2MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + log2(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003/TestDescription.java new file mode 100644 index 00000000000..3508c4144db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter003; + * the debuggee program - nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter003 + * nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003a.java new file mode 100644 index 00000000000..bf39e958e0a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter003 JDI test. + */ + +public class instancefilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter003aThread thread1 = null; + + static instancefilter003aTestClass objTC[] = { new instancefilter003aTestClass(), new instancefilter003aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new instancefilter003aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter003aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter003aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter003aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004.java new file mode 100644 index 00000000000..9c2a497b1e1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodExitRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodExitRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same MethodExitRequest object. + * There are two BreakpointRequests to check as follows: + * (1) For MethodExitRequest2, both invocations are with different + * ObjectReferences restricting one MethodExit event to two objects. + * The test expects no MethodExit event will be received. + * (2) For MethodExitRequest1, both invocations are with the same + * ObjectReference restricting one MethodExit event to one object. + * The test expects this MethodExit event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up MethodExitRequests 1&2 within the method + * in the class TestClass which will be calling by both threads, + * - restricts the MethodExitRequest1 to the tread1 and + * to the array elements #0 & #0 calling only within thread1, + * - restricts the MethodExitRequest2 to the thread2 and + * the array elements #0 & #1 calling within thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter004a"; + return new instancefilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter004aTestClass"; + + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodExitRequest1"; + String property2 = "MethodExitRequest2"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + + ObjectReference instance1 = null; + ObjectReference instance2 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2MethodExitRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2MethodExitRequest (thread2, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + + instance1 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + instance2 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(1); + + ((MethodExitRequest) eventRequest1).addInstanceFilter(instance1); + ((MethodExitRequest) eventRequest1).addInstanceFilter(instance1); + ((MethodExitRequest) eventRequest2).addInstanceFilter(instance1); + ((MethodExitRequest) eventRequest2).addInstanceFilter(instance2); + + display("......waiting for MethodExitEvent in expected thread"); + MethodExitEvent newEvent = (MethodExitEvent)eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + EventRequest newEventRequest = newEvent.request(); + if ( newEventRequest.equals(eventRequest1) ) { + display(" received expected event: " + newEvent); + + ThreadReference newEventThread = newEvent.thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodExitRequest setting2MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodExitRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodExitRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004/TestDescription.java new file mode 100644 index 00000000000..31b3a5c5435 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same MethodExitRequest object. + * There are two MethodExitRequests to check as follows: + * (1) For MethodExitRequest2, both invocations are with different + * ObjectReferences restricting one MethodExit event to two objects. + * The test expects no MethodExit event will be received. + * (2) For MethodExitRequest1, both invocations are with the same + * ObjectReference restricting one MethodExit event to one object. + * The test expects this MethodExit event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter004; + * the debuggee program - nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter004 + * nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addInstanceFilter.instancefilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004a.java new file mode 100644 index 00000000000..74483c7f4ab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter004a.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter004 JDI test. + */ + +public class instancefilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static instancefilter004aThread thread1 = null; + static instancefilter004aThread thread2 = null; + + static instancefilter004aTestClass objTC[] = { new instancefilter004aTestClass(), new instancefilter004aTestClass(), new instancefilter004aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1 = new instancefilter004aThread("thread1"); + thread2 = new instancefilter004aThread("thread2"); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class instancefilter004aThread extends Thread { + + String tName = null; + int tNumber; + + public instancefilter004aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter004aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001.java new file mode 100644 index 00000000000..84a1fac28d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodExitRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodExitRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a MethodExitRequest within the method + * in the class threadfilter001aTestClass which will be calling by both threads, + * - restricts the method entry event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class threadfilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter001a"; + return new threadfilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter001aTestClass"; + + protected void testRun() { + EventRequest eventRequest1 = null; + ThreadReference thread1 = null; + String thread1Name = "thread1"; + String property1 = "MethodExitRequest1"; + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodExitRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for MethodExitEvent in tested thread"); + + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof MethodExitEvent)) { + setFailedStatus("ERROR: new event is not MethodExitEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodExitEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + + } + return; + } + + private MethodExitRequest setting2MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodExitRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + menr = eventRManager.createMethodExitRequest(); + menr.putProperty("number", property); + if (thread != null) + menr.addThreadFilter(thread); + menr.addClassFilter(testedClass); + menr.setSuspendPolicy(suspendPolicy); + + display(" a MethodExitRequest has been set up"); + return menr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodExitRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001/TestDescription.java new file mode 100644 index 00000000000..9bac1b8193c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter001; + * the debuggee program - nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter001 + * nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001a.java new file mode 100644 index 00000000000..f52c54210b3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter001a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter001 JDI test. + */ + +public class threadfilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter001aThread thread1 = null; + static threadfilter001aThread thread2 = null; + + static threadfilter001aTestClass objTC = new threadfilter001aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1 = new threadfilter001aThread("thread1"); + thread2 = new threadfilter001aThread("thread2"); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter001aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter001aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class threadfilter001aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java new file mode 100644 index 00000000000..42ed26ca153 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodExitRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodExitRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an MethodExitRequest and enables it,
    + * - invokes the method addThreadFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addThreadFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addThreadFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class threadfilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new threadfilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter002a"; + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "MethodExitRequest1"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodExitRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addThreadFilter(thread1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((MethodExitRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest setting2MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + mexr = eventRManager.createMethodExitRequest(); + mexr.putProperty("number", property); + if (thread != null) + mexr.addThreadFilter(thread); + mexr.addClassFilter(testedClass); + mexr.setSuspendPolicy(suspendPolicy); + + log2(" MethodExitRequest has been set up"); + return mexr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002/TestDescription.java new file mode 100644 index 00000000000..f081f9aee4a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter002; + * the debuggee program - nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter002 + * nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002a.java new file mode 100644 index 00000000000..d403dc963ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002a.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter002 JDI test. + */ + +public class threadfilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter002aThread thread1 = null; + + static threadfilter002aTestClass objTC = new threadfilter002aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new threadfilter002aThread("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter002aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter002aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class threadfilter002aTestClass { + + static int breakpointLine = 3; + + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java new file mode 100644 index 00000000000..37b9c31a1eb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * MethodExitRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.MethodExitRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Restricts the events generated by this request
    + * to those in the given thread.
    + * The cases to test include three thread's states:
    + * not started, running, dead.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates MethodExitRequest1 and
    + * invokes the method addThreadFilter(tread1) on the request1,
    + * - creates MethodExitRequest2,
    + * resumes the debuggee to get the thread1 started, and
    + * invokes the method addThreadFilter(thread) on the request2,
    + * - creates MethodExitRequest3, waits the thread1 to die, and
    + * invokes the method addThreadFilter(thread) on the request3.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class threadfilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new threadfilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter003a"; + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "MethodExitRequest1"; + String property2 = "MethodExitRequest2"; + String property3 = "MethodExitRequest3"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2MethodExitRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property1); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((MethodExitRequest)eventRequest1).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 1: + eventRequest2 = setting2MethodExitRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property2); + + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((MethodExitRequest)eventRequest2).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2MethodExitRequest (null, + testClassReference, + EventRequest.SUSPEND_NONE, property3); + + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((MethodExitRequest)eventRequest3).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private MethodExitRequest setting2MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up MethodExitRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + mexr = eventRManager.createMethodExitRequest(); + mexr.putProperty("number", property); + if (thread != null) + mexr.addThreadFilter(thread); + mexr.addClassFilter(testedClass); + mexr.setSuspendPolicy(suspendPolicy); + + log2(" MethodExitRequest has been set up"); + return mexr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingMethodExitRequest() : " + e); + log3(" MethodExitRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up MethodExitRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003/TestDescription.java new file mode 100644 index 00000000000..b054bc5b849 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include three thread's states: not started, running, dead. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter003; + * the debuggee program - nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter003 + * nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003a.java new file mode 100644 index 00000000000..33ca73d6690 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003a.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter003 JDI test. + */ + +public class threadfilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter003aThread thread1 = null; + + static threadfilter003aTestClass objTC = new threadfilter003aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new threadfilter003aThread("thread1"); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();"); + methodForCommunication(); + } + break; + + case 2: + try { + thread1.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class threadfilter003aThread extends Thread { + + public threadfilter003aThread(String threadName) { + super(threadName); + } + + public void run() { + log1(" 'run': enter "); + + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + log1(" 'run': exit "); + } + return; + } + } + +} + +class threadfilter003aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004.java new file mode 100644 index 00000000000..133470ce684 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * MethodExitRequest. + * + * The test checks that results of the method + * com.sun.jdi.MethodExitRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same MethodExitRequest object. + * There are two MethodExitRequests to check as follows: + * (1) For MethodExitRequest2, both invocations are with different + * ThreadReferences restricting one MethodExit event to two threads. + * The test expects no MethodExit event will be received. + * (2) For MethodExitRequest1, both invocations are with the same + * ThreadReference restricting one MethodExit event to one thread. + * The test expects this MethodExit event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up MethodExitRequests 1&2 within the method + * in the class threadfilter004aTestClass which will be calling by both threads, + * - restricts the MethodExitRequest1 only to thread1, + * - restricts the MethodExitRequest2 to both thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class threadfilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter004a"; + return new threadfilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter004aTestClass"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "MethodExitRequest1"; + String property2 = "MethodExitRequest2"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) debuggee.classByName(testedClassName); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2MethodExitRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2MethodExitRequest (thread1, + testClassReference, + EventRequest.SUSPEND_ALL, property2); + + ((MethodExitRequest) eventRequest1).addThreadFilter(thread1); + ((MethodExitRequest) eventRequest2).addThreadFilter(thread2); + + display("......waiting for MethodExitEvent in tested thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof MethodExitEvent)) { + setFailedStatus("ERROR: new event is not MethodExitEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new MethodExitEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + EventRequest newEventRequest = newEvent.request(); + if (!newEventRequest.equals(eventRequest1) ) { + setFailedStatus("The MethodExitEvent occured not for eventRequest1"); + } + + ThreadReference thr = ((MethodExitEvent)newEvent).thread(); + if (!thr.equals(thread1)) { + setFailedStatus("The MethodExitEvent occured in unexpected thread: " + thr); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private MethodExitRequest setting2MethodExitRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up MethodExitRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; property: " + property); + + MethodExitRequest + mexr = eventRManager.createMethodExitRequest(); + mexr.putProperty("number", property); + if (thread != null) + mexr.addThreadFilter(thread); + mexr.addClassFilter(testedClass); + mexr.setSuspendPolicy(suspendPolicy); + + display(" MethodExitRequest has been set up"); + return mexr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up MethodExitRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004/TestDescription.java new file mode 100644 index 00000000000..761b44f8d28 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * MethodExitRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same MethodExitRequest object. + * There are two MethodExitRequests to check as follows: + * (1) For MethodExitRequest2, both invocations are with different + * ThreadReferences restricting one MethodExit event to two threads. + * The test expects no MethodExit event will be received. + * (2) For MethodExitRequest1, both invocations are with the same + * ThreadReference restricting one MethodExit event to one thread. + * The test expects this MethodExit event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter004; + * the debuggee program - nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter004 + * nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.MethodExitRequest.addThreadFilter.threadfilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004a.java new file mode 100644 index 00000000000..c5612ccf39d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter004a.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.MethodExitRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the threadfilter004 JDI test. + */ + +public class threadfilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static threadfilter004aThread thread1 = null; + static threadfilter004aThread thread2 = null; + + static threadfilter004aTestClass objTC = new threadfilter004aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1 = new threadfilter004aThread("thread1"); + thread2 = new threadfilter004aThread("thread2"); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class threadfilter004aThread extends Thread { + + String tName = null; + int tNumber; + + public threadfilter004aThread(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class threadfilter004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001.java new file mode 100644 index 00000000000..332203964dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Mirror.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class hashcode001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Mirror.hashCode."; + private final static String className = "hashcode001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + display("Checking hashCode() method for Mirror object"); + + Mirror mirror = (Mirror)debuggeeClass; + int hCode = mirror.hashCode(); + + if (hCode == 0) { + complain("hashCode() returns 0 for Mirror object : " + mirror); + exitStatus = Consts.TEST_FAILED; + } + + int hCode1 = mirror.hashCode(); + if (hCode != hCode1) { + complain("hashCode() is not consistent for Mirror object" + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + // get new reference to the same Mirror and get hash code. + hCode1 = ((Mirror)debuggee.classByName(debuggeeName)).hashCode(); + if (hCode != hCode1) { + complain("hashCode() does not return same value for equal Mirror object " + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + display("hashCode() returns for Mirror object : " + hCode); + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..2d20b515c2d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Mirror/hashCode/hashcode001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public hashCode() method of an implementing class of + * com.sun.jdi.Mirror interface. + * The test checks an assertion cited from spec for hashCode() method of + * java.lang.Object class: + * The general contract of hashCode is: + * - Whenever it is invoked on the same object more than once during + * an execution of a Java application, the hashCode method must + * consistently return the same integer, provided no information used + * in equals comparisons on the object is modified. + * ... + * - If two objects are equal according to the equals(Object) method, + * then calling the hashCode method on each of the two objects must + * produce the same integer result. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for Mirror + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Mirror.hashCode.hashcode001 + * nsk.jdi.Mirror.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Mirror.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001a.java new file mode 100644 index 00000000000..d3589c293c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/hashCode/hashcode001a.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Mirror.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class hashcode001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(hashcode001.SIGNAL_READY); + receiveSignal(hashcode001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001.java new file mode 100644 index 00000000000..d30aa02dcc0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Mirror.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Mirror.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Mirror.toString()
    + * complies with its specification.
    + *
    + * The test works as follows.
    + * A debugger, using shared classses, creates and launches
    + * a debuggee, establishes a pipe to comminicate with the it,
    + * and upon receiption a message from the debuggee, gets
    + * a ReferenceType object mirroring debuggee's class, and
    + * applies the method Mirror.toString() to the object.
    + * Then the debugger checks up that a value returned by
    + * the method is not a null-string.
    + */ + +public class tostring001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Mirror/toString/tostring001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new tostring001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Mirror.toString.tostring001a"; + + //String mName = "nsk.jdi.Mirror.toString"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" ReferenceType testClass = (ReferenceType) (vm.classesByName(debuggeeName)).get(0);"); + ReferenceType testClass = (ReferenceType) (vm.classesByName(debuggeeName)).get(0); + + log2(" String str = testClass.toString();"); + String str = testClass.toString(); + + log2(" checking up on 'str' value; null is not expected"); + if (str == null) { + log3("ERROR: str == null"); + testExitCode = FAILED; + } else { + int lenght = str.length(); + log2(" str.length() == " + lenght); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..ea492190ca0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Mirror/toString/tostring001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Mirror. + * The test checks up that a result of the method + * com.sun.jdi.Mirror.toString() + * complies with its spec: + * public java.lang.String toString() + * Returns a String describing this mirror + * Returns: a string describing this mirror. + * Overrides: toString in class java.lang.Object + * The test works as follows: + * The debugger program - nsk.jdi.Mirror.toString.tostring001; + * the debuggee program - nsk.jdi.Mirror.toString.tostring001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Mirror.toString.tostring001 + * nsk.jdi.Mirror.toString.tostring001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Mirror.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001a.java new file mode 100644 index 00000000000..e6d42829fd2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/toString/tostring001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Mirror.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the tostring001 JDI test. + */ + +public class tostring001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> tostring001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> tostring001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Mirror.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Mirror.virtualMachine()
    + * complies with its specification.
    + *
    + * The test works as follows.
    + * A debugger, using shared classses, creates and launches
    + * a debuggee, establishes a pipe to comminicate with the it,
    + * and upon receiption a message from the debuggee, gets
    + * a ReferenceType object mirroring debuggee's class, and
    + * applies the method Mirror.virtualMachine() to the object.
    + * Then the debugger checks up that a value returned by
    + * the method is not a null-string.
    + */ + +public class virtualmachine001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Mirror/virtualMachine/virtualmachine001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new virtualmachine001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Mirror.virtualMachine.virtualmachine001a"; + + //String mName = "nsk.jdi.Mirror.virtualMachine"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" ReferenceType testClass = (ReferenceType) (vm.classesByName(debuggeeName)).get(0);"); + ReferenceType testClass = (ReferenceType) (vm.classesByName(debuggeeName)).get(0); + + log2(" VirtualMachine vm1 = testClass.virtualMachine();"); + VirtualMachine vm1 = testClass.virtualMachine(); + + log2(" checking up on 'vm1' value; null is not expected"); + if (vm1 == null) { + log3("ERROR: vm1 == null"); + testExitCode = FAILED; + } else { + log2(" checking up equality of vm1 and vm; must be equal"); + if (!vm.equals(vm1)) { + log3("ERROR: !vm.equals(vm1)"); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001/TestDescription.java new file mode 100644 index 00000000000..5f61e97c8e9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Mirror/virtualMachine/virtualmachine001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Mirror. + * The test checks up that a result of the method + * com.sun.jdi.Mirror.virtualMachine() + * complies with its spec: + * public VirtualMachine virtualMachine() + * Gets the VirtualMachine to which this Mirror belongs. + * A Mirror must be associated with a VirtualMachine to have any meaning. + * Returns: the VirtualMachine for which this mirror is a proxy. + * The test works as follows: + * The debugger program - nsk.jdi.Mirror.virtualMachine.virtualmachine001; + * the debuggee program - nsk.jdi.Mirror.virtualMachine.virtualmachine001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Mirror.virtualMachine.virtualmachine001 + * nsk.jdi.Mirror.virtualMachine.virtualmachine001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Mirror.virtualMachine.virtualmachine001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001a.java new file mode 100644 index 00000000000..25003a56967 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Mirror/virtualMachine/virtualmachine001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Mirror.virtualMachine; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the virtualmachine001 JDI test. + */ + +public class virtualmachine001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> virtualmachine001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> virtualmachine001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ModificationWatchpointEvent.
    + *
    + * The test checks that results of methods in the interface
    + * com.sun.jdi.ModificationWatchpointEvent
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * The number of ModificationWatchpointEvents received is
    + * equal to the number of ModificationWatchpointRequests
    + * set up by a debugger.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates an object foo of CheckedClass and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger:
    + * - set up enabled ModificationWatchpointRequests for all fields,
    + * - resumes the debuggee, and
    + * - waiting for all expected events to receive.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class mwevent001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new mwevent001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ModificationWatchpointEvent._itself_.mwevent001a"; + + private String testedClassName = + "nsk.jdi.ModificationWatchpointEvent._itself_.CheckedClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldModification() ) { + log2("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + ReferenceType refType = null; + List fields = null; + ListIterator li = null; + Field field = null; + + ModificationWatchpointRequest mwRequest = null; + + int requestsCount = 0; + int mwEventsCount = 0; + + + vm.resume(); // !!!!! + for (int i = 0; ; i++) { + + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + refType = (ReferenceType) vm.classesByName(testedClassName).get(0); + fields = refType.fields(); + li = fields.listIterator(); + + log2("......setting up ModificationWatchpointRequests"); + while (li.hasNext()) { + field = (Field) li.next(); + mwRequest = eventRManager.createModificationWatchpointRequest(field); + mwRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); + mwRequest.enable(); + requestsCount++; + } + log2(" # mwRequests set up : " + requestsCount); + + log2("......vm.resume();"); + vm.resume(); + + log2("......waiting for ModificationWatchpointEvents"); + while ( mwEventsCount < requestsCount ) { + getEventSet(); + Event newEvent = eventIterator.nextEvent(); + if ( !( newEvent instanceof ModificationWatchpointEvent)) { + testExitCode = FAILED; + log3("ERROR: new event is not ModificationWatchpointEvent"); + break; + } + mwEventsCount++; + } + log2(" # mwEventsCount == " + mwEventsCount); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001/TestDescription.java new file mode 100644 index 00000000000..4e27dd7c028 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ModificationWatchpointEvent. + * The test checks up on the following assertion: + * The number of ModificationWatchpointEvents received is equal to + * the number of ModificationWatchpointRequests set up by a debugger. + * The test works as follows: + * The debugger program - nsk.jdi.ModificationWatchpointEvent._itself_.mwevent001; + * the debuggee program - nsk.jdi.ModificationWatchpointEvent._itself_.mwevent001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * class CheckedClass being used in the debuggee + * has been taken from the test + * nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001 + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ModificationWatchpointEvent._itself_.mwevent001 + * nsk.jdi.ModificationWatchpointEvent._itself_.mwevent001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ModificationWatchpointEvent._itself_.mwevent001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001a.java new file mode 100644 index 00000000000..acd9d43ee0c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001a.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ModificationWatchpointEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the mwevent001 JDI test. + */ + +public class mwevent001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + CheckedClass foo = new CheckedClass(); + foo.init(); + methodForCommunication(); + foo.run(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} + +// class for checking +class CheckedClass { + + boolean z0, z1[], z2[][]; + byte b0, b1[], b2[][]; + char c0, c1[], c2[][]; + double d0, d1[], d2[][]; + float f0, f1[], f2[][]; + int i0, i1[], i2[][]; + long l0, l1[], l2[][]; + short s0, s1[], s2[][]; + + static long lS0, lS1[], lS2[][]; + private long lP0, lP1[], lP2[][]; + public long lU0, lU1[], lU2[][]; + protected long lR0, lR1[], lR2[][]; + transient long lT0, lT1[], lT2[][]; + volatile long lV0, lV1[], lV2[][]; + + Boolean Z0, Z1[], Z2[][]; + Byte B0, B1[], B2[][]; + Character C0, C1[], C2[][]; + Double D0, D1[], D2[][]; + Float F0, F1[], F2[][]; + Integer I0, I1[], I2[][]; + Long L0, L1[], L2[][]; + String W0, W1[], W2[][]; + Short S0, S1[], S2[][]; + Object O0, O1[], O2[][]; + + static Long LS0, LS1[], LS2[][]; + private Long LP0, LP1[], LP2[][]; + public Long LU0, LU1[], LU2[][]; + protected Long LR0, LR1[], LR2[][]; + transient Long LT0, LT1[], LT2[][]; + volatile Long LV0, LV1[], LV2[][]; + + interface Inter {} + class Class implements Inter {} + Class X0, X1[], X2[][]; + Inter E0, E1[], E2[][]; + static Inter ES0, ES1[], ES2[][]; + private Inter EP0, EP1[], EP2[][]; + public Inter EU0, EU1[], EU2[][]; + protected Inter ER0, ER1[], ER2[][]; + transient Inter ET0, ET1[], ET2[][]; + volatile Inter EV0, EV1[], EV2[][]; + + // initializa fields values + void init() { + z0 = false; + b0 = java.lang.Byte.MIN_VALUE; + c0 = java.lang.Character.MIN_VALUE; + d0 = java.lang.Double.MIN_VALUE; + f0 = java.lang.Float.MIN_VALUE; + i0 = java.lang.Integer.MIN_VALUE; + l0 = java.lang.Long.MIN_VALUE; + s0 = java.lang.Short.MIN_VALUE; + + initFields(); + } + + // change fields values + void run() { + z0 = true; + b0 = java.lang.Byte.MAX_VALUE; + c0 = java.lang.Character.MAX_VALUE; + d0 = java.lang.Double.MAX_VALUE; + f0 = java.lang.Float.MAX_VALUE; + i0 = java.lang.Integer.MAX_VALUE; + l0 = java.lang.Long.MAX_VALUE; + s0 = java.lang.Short.MAX_VALUE; + + initFields(); + } + + // calculate new fields values + void initFields() { + + z1 = new boolean[] {z0}; + z2 = new boolean[][] {z1}; + b1 = new byte[] {b0}; + b2 = new byte[][] {b1}; + c1 = new char[] {c0}; + c2 = new char[][] {c1}; + d1 = new double[] {d0}; + d2 = new double[][] {d1}; + f1 = new float[] {f0}; + f2 = new float[][] {f1}; + i1 = new int[] {i0}; + i2 = new int[][] {i1}; + l1 = new long[] {l0}; + l2 = new long[][] {l1}; + s1 = new short[] {s0}; + s2 = new short[][] {s1}; + + lS0 = l0; + lP0 = l0; + lU0 = l0; + lR0 = l0; + lT0 = l0; + lV0 = l0; + + lS1 = new long[] {lS0}; + lS2 = new long[][] {lS1}; + lP1 = new long[] {lP0}; + lP2 = new long[][] {lP1}; + lU1 = new long[] {lU0}; + lU2 = new long[][] {lU1}; + lR1 = new long[] {lR0}; + lR2 = new long[][] {lR1}; + lT1 = new long[] {lT0}; + lT2 = new long[][] {lT1}; + lV1 = new long[] {lV0}; + lV2 = new long[][] {lV1}; + + X0 = new Class(); + X1 = new Class[] {X0}; + X2 = new Class[][] {X1}; + Z0 = new Boolean(true); + Z1 = new Boolean[] {Z0}; + Z2 = new Boolean[][] {Z1}; + B0 = new Byte(java.lang.Byte.MIN_VALUE); + B1 = new Byte[] {B0}; + B2 = new Byte[][] {B1}; + C0 = new Character(java.lang.Character.MIN_VALUE); + C1 = new Character[] {C0}; + C2 = new Character[][]{C1}; + D0 = new Double(java.lang.Double.MIN_VALUE); + D1 = new Double[] {D0}; + D2 = new Double[][] {D1}; + F0 = new Float(java.lang.Float.MIN_VALUE); + F1 = new Float[] {F0}; + F2 = new Float[][] {F1}; + I0 = new Integer(java.lang.Integer.MIN_VALUE); + I1 = new Integer[] {I0}; + I2 = new Integer[][] {I1}; + L0 = new Long(java.lang.Long.MIN_VALUE); + L1 = new Long[] {L0}; + L2 = new Long[][] {L1}; + S0 = new Short(java.lang.Short.MIN_VALUE); + S1 = new Short[] {S0}; + S2 = new Short[][] {S1}; + W0 = new String(); + W1 = new String[] {W0}; + W2 = new String[][] {W1}; + O0 = new Object(); + O1 = new Object[] {O0}; + O2 = new Object[][] {O1}; + + LS0 = new Long(java.lang.Long.MAX_VALUE); + LS1 = new Long[] {LS0}; + LS2 = new Long[][] {LS1}; + LP0 = new Long(java.lang.Long.MAX_VALUE); + LP1 = new Long[] {LP0}; + LP2 = new Long[][] {LP1}; + LU0 = new Long(java.lang.Long.MAX_VALUE); + LU1 = new Long[] {LU0}; + LU2 = new Long[][] {LU1}; + LR0 = new Long(java.lang.Long.MAX_VALUE); + LR1 = new Long[] {LR0}; + LR2 = new Long[][] {LR1}; + LT0 = new Long(java.lang.Long.MAX_VALUE); + LT1 = new Long[] {LT0}; + LT2 = new Long[][] {LT1}; + LV0 = new Long(java.lang.Long.MAX_VALUE); + LV1 = new Long[] {LV0}; + LV2 = new Long[][] {LV1}; + + E0 = new Class(); + E1 = new Inter[] {E0}; + E2 = new Inter[][] {E1}; + ES0 = new Class(); + ES1 = new Inter[] {ES0}; + ES2 = new Inter[][] {ES1}; + EP0 = new Class(); + EP1 = new Inter[] {EP0}; + EP2 = new Inter[][] {EP1}; + EU0 = new Class(); + EU1 = new Inter[] {EU0}; + EU2 = new Inter[][] {EU1}; + ER0 = new Class(); + ER1 = new Inter[] {ER0}; + ER2 = new Inter[][] {ER1}; + ET0 = new Class(); + ET1 = new Inter[] {ET0}; + ET2 = new Inter[][] {ET1}; + EV0 = new Class(); + EV1 = new Inter[] {EV0}; + EV2 = new Inter[][] {EV1}; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001.java new file mode 100644 index 00000000000..0fe8b7904bf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001.java @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ModificationWatchpointEvent.valueToBe; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class valuetobe001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static final String DEBUGEE_NAME = "nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001a"; + static final String CHECKED_CLASS_NAME = "nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001aCheckedClass"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private ReferenceType rType; + static private ModificationWatchpointRequest wpRequest; + static private List fieldsList; + + static private volatile boolean testFailed; + static private volatile boolean done; + static private volatile int requestsCount, mwpEventsCount; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + requestsCount = 0; + mwpEventsCount = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGEE_NAME); + debuggee.redirectStderr(log, "valuetobe001a >"); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // check for debuggee's capabilities + if (!debuggee.VM().canWatchFieldModification()) { + log.display("TEST WARNING: test passed because JDI implementation does not support " + + "watchpoints for field modification"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return PASSED; + } + + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirrors + if ((rType = debuggee.classByName(CHECKED_CLASS_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + CHECKED_CLASS_NAME); + } + + // create events requests + log.display("Creating requests for WatchpointEvent"); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + Iterator fieldsIter; + try { + fieldsList = rType.fields(); + fieldsIter = fieldsList.iterator(); + } catch (ClassNotPreparedException e) { + throw new Failure( "TEST_BUG: " + rType.name() + " is not prepared"); + } + while (fieldsIter.hasNext()) { + Field refField = (Field)fieldsIter.next(); + if ((wpRequest = erManager.createModificationWatchpointRequest(refField)) == null) { + throw new Failure("TEST BUG: unable to create ModificationWatchpointRequest"); + } else { + log.display("ModificationWatchpointRequest for field " + refField.name() + " created"); + wpRequest.enable(); + } + requestsCount++; + } + log.display("Created total " + requestsCount + " ModificationWatchpointRequests"); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + // handle events until all events generated and received + while ( mwpEventsCount != requestsCount ) { + eventSet = null; + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + + if (eventSet == null) + continue; + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + // handle ModificationWatchpointEvent + if (event instanceof ModificationWatchpointEvent) { + mwpEventsCount++; + ModificationWatchpointEvent castedEvent = (ModificationWatchpointEvent)event; + Value evValue = castedEvent.valueToBe(); + Field evField = castedEvent.field(); + log.display("ModificationWatchpointEvent received for " + evField.name()); + if (evValue == null) { + log.complain("FAILURE 1: ModificationWatchpointEvent.valueToBe() returns null for " + evField.name()); + testFailed = true; + } else { + int ind = fieldsList.indexOf(evField); + if (ind == -1) { + log.complain("FAILURE 2: ModificationWatchpoint.field() returns unknown field"); + testFailed = true; + } else { + Value valueNew = castedEvent.valueToBe(); + Value valueNew1= castedEvent.valueToBe(); + + if (!valueNew.equals(valueNew1)) { + log.complain("FAILURE 3: method valueToBe() returns inconsistent results for " + + evField.name() + "\nvalueNew: " + valueNew + " ; valueNew1: " + valueNew1); + testFailed = true; + } + + Value valueFld = castedEvent.valueCurrent(); + + if (valueFld.equals(valueNew)) { + log.complain("FAILURE 4: method valueToBe() returns incorrect equal value for " + + evField.name() + "\nvaluetoBe(): " + valueNew + " ; valueCurrent(): " + valueFld); + testFailed = true; + } else { + log.display(evField.name() + " is assigned to " + castedEvent.valueToBe().toString()); + } + } + } + } + } + // resume each handled event set + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to generate events + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + // wait for confirmation from debugee + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (command == null || !command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // notify EventHandler that all events generated + done = true; + + // wait for all expected events received + log.display("Waiting for all expected events received"); + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001/TestDescription.java new file mode 100644 index 00000000000..389f9c07069 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exercises the + * com.sun.jdi.event.ModificationWatchpointEvent.valueToBe() method. + * The test checks the following assertion: + * If any field of loaded class of target VM is assigned to new value + * which is not equal to previous value, then Value reference + * returned by ModificationWatchpointEvent.valueToBe() is not equal + * to one returned by Watchpoint.valueCurrent(). + * A debugger class - nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001 ; + * a debuggee class - nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates ModificationWatchpointRequests to the fields defined + * in debuggee class. + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee initializes its + * fields and sends command . + * The debugger switches to to listen the event during the + * time specified by parameter. Then debugger shuts down debuggee + * by command. + * If debugger receives ModificationWatchpointEvent, it compares old and new + * values of field referenced in the event. The test fails if any of this + * these values are equal. + * The test also fails if no ModificationWatchpointEvent was received. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * ---------- + * I. To fix the bug 4505870, the following is done in file valuetobe001a.java: + * - assignments values to the fields lS0, lP0, lU0, lR0, lT0, and lV0 + * are added (new lines 164-169). + * II. Several improvments: + * debugger: + * - line 129: check value is in requestsCount; + * - old line 39 removed; + * - check for all expected events received (lines 233-248) removed. + * debuggee: + * - line 25 removed. + * ---------- + * Standard method Debugee.endDebugee() is used instead of cleaning event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001 + * nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001a.java new file mode 100644 index 00000000000..507bc3ab934 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001a.java @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ModificationWatchpointEvent.valueToBe; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class valuetobe001a { + + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + + public static void main(String args[]) { + System.exit(JCK_STATUS_BASE + run(args)); + } + + static int run( String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // create instance of checked class + valuetobe001aCheckedClass foo = new valuetobe001aCheckedClass(); + // initialize fields values + foo.init(); + + // notify debugger that debuggee started + pipe.println(COMMAND_READY); + + // wait for command GO from debugger + String command = pipe.readln(); + if (command.equals(COMMAND_QUIT)) { + return PASSED; + } + if (!command.equals(COMMAND_GO)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + + // perform actions + foo.run(); + + // notify debugger that the command done + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger and exit + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + return PASSED; + } +} + +// class for checking +class valuetobe001aCheckedClass { + + boolean z0, z1[], z2[][]; + byte b0, b1[], b2[][]; + char c0, c1[], c2[][]; + double d0, d1[], d2[][]; + float f0, f1[], f2[][]; + int i0, i1[], i2[][]; + long l0, l1[], l2[][]; + short s0, s1[], s2[][]; + + static long lS0, lS1[], lS2[][]; + private long lP0, lP1[], lP2[][]; + public long lU0, lU1[], lU2[][]; + protected long lR0, lR1[], lR2[][]; + transient long lT0, lT1[], lT2[][]; + volatile long lV0, lV1[], lV2[][]; + + Boolean Z0, Z1[], Z2[][]; + Byte B0, B1[], B2[][]; + Character C0, C1[], C2[][]; + Double D0, D1[], D2[][]; + Float F0, F1[], F2[][]; + Integer I0, I1[], I2[][]; + Long L0, L1[], L2[][]; + String W0, W1[], W2[][]; + Short S0, S1[], S2[][]; + Object O0, O1[], O2[][]; + + static Long LS0, LS1[], LS2[][]; + private Long LP0, LP1[], LP2[][]; + public Long LU0, LU1[], LU2[][]; + protected Long LR0, LR1[], LR2[][]; + transient Long LT0, LT1[], LT2[][]; + volatile Long LV0, LV1[], LV2[][]; + + interface Inter {} + class Class implements Inter {} + Class X0, X1[], X2[][]; + Inter E0, E1[], E2[][]; + static Inter ES0, ES1[], ES2[][]; + private Inter EP0, EP1[], EP2[][]; + public Inter EU0, EU1[], EU2[][]; + protected Inter ER0, ER1[], ER2[][]; + transient Inter ET0, ET1[], ET2[][]; + volatile Inter EV0, EV1[], EV2[][]; + + // initializa fields values + void init() { + z0 = false; + b0 = java.lang.Byte.MIN_VALUE; + c0 = java.lang.Character.MIN_VALUE; + d0 = java.lang.Double.MIN_VALUE; + f0 = java.lang.Float.MIN_VALUE; + i0 = java.lang.Integer.MIN_VALUE; + l0 = java.lang.Long.MIN_VALUE; + s0 = java.lang.Short.MIN_VALUE; + + initFields(); + } + + // change fields values + void run() { + z0 = true; + b0 = java.lang.Byte.MAX_VALUE; + c0 = java.lang.Character.MAX_VALUE; + d0 = java.lang.Double.MAX_VALUE; + f0 = java.lang.Float.MAX_VALUE; + i0 = java.lang.Integer.MAX_VALUE; + l0 = java.lang.Long.MAX_VALUE; + s0 = java.lang.Short.MAX_VALUE; + + initFields(); + } + + // calculate new fields values + void initFields() { + + z1 = new boolean[] {z0}; + z2 = new boolean[][] {z1}; + b1 = new byte[] {b0}; + b2 = new byte[][] {b1}; + c1 = new char[] {c0}; + c2 = new char[][] {c1}; + d1 = new double[] {d0}; + d2 = new double[][] {d1}; + f1 = new float[] {f0}; + f2 = new float[][] {f1}; + i1 = new int[] {i0}; + i2 = new int[][] {i1}; + l1 = new long[] {l0}; + l2 = new long[][] {l1}; + s1 = new short[] {s0}; + s2 = new short[][] {s1}; + + lS0 = l0; + lP0 = l0; + lU0 = l0; + lR0 = l0; + lT0 = l0; + lV0 = l0; + + lS1 = new long[] {lS0}; + lS2 = new long[][] {lS1}; + lP1 = new long[] {lP0}; + lP2 = new long[][] {lP1}; + lU1 = new long[] {lU0}; + lU2 = new long[][] {lU1}; + lR1 = new long[] {lR0}; + lR2 = new long[][] {lR1}; + lT1 = new long[] {lT0}; + lT2 = new long[][] {lT1}; + lV1 = new long[] {lV0}; + lV2 = new long[][] {lV1}; + + X0 = new Class(); + X1 = new Class[] {X0}; + X2 = new Class[][] {X1}; + Z0 = new Boolean(true); + Z1 = new Boolean[] {Z0}; + Z2 = new Boolean[][] {Z1}; + B0 = new Byte(java.lang.Byte.MIN_VALUE); + B1 = new Byte[] {B0}; + B2 = new Byte[][] {B1}; + C0 = new Character(java.lang.Character.MIN_VALUE); + C1 = new Character[] {C0}; + C2 = new Character[][]{C1}; + D0 = new Double(java.lang.Double.MIN_VALUE); + D1 = new Double[] {D0}; + D2 = new Double[][] {D1}; + F0 = new Float(java.lang.Float.MIN_VALUE); + F1 = new Float[] {F0}; + F2 = new Float[][] {F1}; + I0 = new Integer(java.lang.Integer.MIN_VALUE); + I1 = new Integer[] {I0}; + I2 = new Integer[][] {I1}; + L0 = new Long(java.lang.Long.MIN_VALUE); + L1 = new Long[] {L0}; + L2 = new Long[][] {L1}; + S0 = new Short(java.lang.Short.MIN_VALUE); + S1 = new Short[] {S0}; + S2 = new Short[][] {S1}; + W0 = new String(); + W1 = new String[] {W0}; + W2 = new String[][] {W1}; + O0 = new Object(); + O1 = new Object[] {O0}; + O2 = new Object[][] {O1}; + + LS0 = new Long(java.lang.Long.MAX_VALUE); + LS1 = new Long[] {LS0}; + LS2 = new Long[][] {LS1}; + LP0 = new Long(java.lang.Long.MAX_VALUE); + LP1 = new Long[] {LP0}; + LP2 = new Long[][] {LP1}; + LU0 = new Long(java.lang.Long.MAX_VALUE); + LU1 = new Long[] {LU0}; + LU2 = new Long[][] {LU1}; + LR0 = new Long(java.lang.Long.MAX_VALUE); + LR1 = new Long[] {LR0}; + LR2 = new Long[][] {LR1}; + LT0 = new Long(java.lang.Long.MAX_VALUE); + LT1 = new Long[] {LT0}; + LT2 = new Long[][] {LT1}; + LV0 = new Long(java.lang.Long.MAX_VALUE); + LV1 = new Long[] {LV0}; + LV2 = new Long[][] {LV1}; + + E0 = new Class(); + E1 = new Inter[] {E0}; + E2 = new Inter[][] {E1}; + ES0 = new Class(); + ES1 = new Inter[] {ES0}; + ES2 = new Inter[][] {ES1}; + EP0 = new Class(); + EP1 = new Inter[] {EP0}; + EP2 = new Inter[][] {EP1}; + EU0 = new Class(); + EU1 = new Inter[] {EU0}; + EU2 = new Inter[][] {EU1}; + ER0 = new Class(); + ER1 = new Inter[] {ER0}; + ER2 = new Inter[][] {ER1}; + ET0 = new Class(); + ET1 = new Inter[] {ET0}; + ET2 = new Inter[][] {ET1}; + EV0 = new Class(); + EV1 = new Inter[] {EV0}; + EV2 = new Inter[][] {EV1}; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002.java new file mode 100644 index 00000000000..230277030c5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002.java @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ModificationWatchpointEvent.valueToBe; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class valuetobe002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static final String DEBUGEE_NAME = "nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe002a"; + static final String CHECKED_CLASS_NAME = "nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe002aCheckedClass"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private ReferenceType rType; + static private ModificationWatchpointRequest wpRequest; + static private List fieldsList; + + static private volatile boolean testFailed; + static private volatile boolean done; + static private volatile int requestsCount, mwpEventsCount; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + requestsCount = 0; + mwpEventsCount = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGEE_NAME); + debuggee.redirectStderr(log, "valuetobe001a >"); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // check for debuggee's capabilities + if (!debuggee.VM().canWatchFieldModification()) { + log.display("TEST WARNING: test passed because JDI implementation does not support " + + "watchpoints for field modification"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return PASSED; + } + + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirrors + if ((rType = debuggee.classByName(CHECKED_CLASS_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + CHECKED_CLASS_NAME); + } + + // create events requests + log.display("Creating requests for WatchpointEvent"); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + Iterator fieldsIter; + try { + fieldsList = rType.fields(); + fieldsIter = fieldsList.iterator(); + } catch (ClassNotPreparedException e) { + throw new Failure( "TEST_BUG: " + rType.name() + " is not prepared"); + } + while (fieldsIter.hasNext()) { + Field refField = (Field)fieldsIter.next(); + if ((wpRequest = erManager.createModificationWatchpointRequest(refField)) == null) { + throw new Failure("TEST BUG: unable to create ModificationWatchpointRequest"); + } else { + log.display("ModificationWatchpointRequest for field " + refField.name() + " created"); + wpRequest.enable(); + } + requestsCount++; + } + log.display("Created total " + requestsCount + " ModificationWatchpointRequests"); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + // handle events until all events generated and received + while (mwpEventsCount < requestsCount) { + eventSet = null; + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + + if (eventSet == null) + continue; + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + // handle ModificationWatchpointEvent + if (event instanceof ModificationWatchpointEvent) { + mwpEventsCount++; + ModificationWatchpointEvent castedEvent = (ModificationWatchpointEvent)event; + Value evValue = castedEvent.valueToBe(); + Field evField = castedEvent.field(); + log.display("ModificationWatchpointEvent received for " + evField.name()); + if (evValue == null) { + log.complain("FAILURE 3: ModificationWatchpointEvent.valueToBe() returns null for " + evField.name()); + testFailed = true; + } else { + int ind = fieldsList.indexOf(evField); + if (ind == -1) { + log.complain("FAILURE 2: ModificationWatchpoint.field() returns unknown field"); + testFailed = true; + } else { + Value valueNew = castedEvent.valueToBe(); + Value valueNew1= castedEvent.valueToBe(); + + if (!valueNew.equals(valueNew1)) { + log.complain("FAILURE 3: method valueToBe() returns inconsistent results for " + + evField.name() + "\nvalueNew: " + valueNew + " ; valueNew1: " + valueNew1); + testFailed = true; + } + + Value valueFld = castedEvent.valueCurrent(); + + if (!valueFld.equals(valueNew)) { + log.complain("FAILURE 4: method valueToBe() returns incorrect equal value for " + + evField.name() + "\nvaluetoBe(): " + valueNew + " ; valueCurrent(): " + valueFld); + testFailed = true; + } else { + log.display(evField.name() + " is assigned to " + castedEvent.valueToBe().toString()); + } + } + } + } + } + // resume each handled event set + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to generate events + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + // wait for confirmation from debugee + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (command == null || !command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // notify EventHandler that all events generated + done = true; + + // wait for all expected events received + log.display("Waiting for all expected events received"); + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002/TestDescription.java new file mode 100644 index 00000000000..f014d42c4fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002/TestDescription.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exercises + * com.sun.jdi.event.ModificationWatchpointEvent.valueToBe() method. + * The test checks the following assertion: + * If any field of loaded class of target VM is assigned to new value + * which is equal to previous value, then Value reference returned + * by ModificationWatchpointEvent.valueToBe() is equal to one + * returned by Watchpoint.valueCurrent(). + * A debugger class - nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001 ; + * a debuggee class - nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates ModificationWatchpointRequests to the fields defined + * in debuggee class. + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee assignes every field + * to itself (i.e. the old and new values of the field are equal) and sends + * command . + * The debugger switches to to listen the event during the + * time specified by parameter. Then debugger shuts down debuggee + * by command. + * If debugger receives ModificationWatchpointEvent, it compares old and new + * values of field referenced in the event. The test fails if any of this + * these values are not equal. The test also fails if no + * ModificationWatchpointEvent was received. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * ---------- + * I. To fix the bug 4505870, the following is done in file valuetobe001a.java: + * - assignments values to the fields lS0, lP0, lU0, lR0, lT0, and lV0 + * are added (new lines 153-158). + * II. Several improvments: + * debugger: + * - line 129: check value is in requestsCount; + * - old line 37 removed; + * - check for all expected events received (lines 233-248) removed. + * debuggee: + * - line 25 removed. + * ---------- + * Standard method Debugee.endDebugee() is used instead of cleaning event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe002 + * nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ModificationWatchpointEvent.valueToBe.valuetobe002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002a.java new file mode 100644 index 00000000000..78fdd9a550e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002a.java @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ModificationWatchpointEvent.valueToBe; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class valuetobe002a { + + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + public static void main(String args[]) { + System.exit(JCK_STATUS_BASE + run(args)); + } + + static int run( String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // create instance of checked class + valuetobe002aCheckedClass foo = new valuetobe002aCheckedClass(); + // initialize fields values + foo.init(); + + // notify debugger that debuggee started + pipe.println(COMMAND_READY); + + // wait for command GO from debugger + String command = pipe.readln(); + if (command.equals(COMMAND_QUIT)) { + return PASSED; + } + if (!command.equals(COMMAND_GO)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + + // perform actions + foo.run(); + + // notify debugger that the command done + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger and exit + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + return PASSED; + } +} + +// class for checking +class valuetobe002aCheckedClass { + + boolean z0, z1[], z2[][]; + byte b0, b1[], b2[][]; + char c0, c1[], c2[][]; + double d0, d1[], d2[][]; + float f0, f1[], f2[][]; + int i0, i1[], i2[][]; + long l0, l1[], l2[][]; + short s0, s1[], s2[][]; + + static long lS0, lS1[], lS2[][]; + private long lP0, lP1[], lP2[][]; + public long lU0, lU1[], lU2[][]; + protected long lR0, lR1[], lR2[][]; + transient long lT0, lT1[], lT2[][]; + volatile long lV0, lV1[], lV2[][]; + + Boolean Z0, Z1[], Z2[][]; + Byte B0, B1[], B2[][]; + Character C0, C1[], C2[][]; + Double D0, D1[], D2[][]; + Float F0, F1[], F2[][]; + Integer I0, I1[], I2[][]; + Long L0, L1[], L2[][]; + String W0, W1[], W2[][]; + Short S0, S1[], S2[][]; + Object O0, O1[], O2[][]; + + static Long LS0, LS1[], LS2[][]; + private Long LP0, LP1[], LP2[][]; + public Long LU0, LU1[], LU2[][]; + protected Long LR0, LR1[], LR2[][]; + transient Long LT0, LT1[], LT2[][]; + volatile Long LV0, LV1[], LV2[][]; + + interface Inter {} + class Class implements Inter {} + Class X0, X1[], X2[][]; + Inter E0, E1[], E2[][]; + static Inter ES0, ES1[], ES2[][]; + private Inter EP0, EP1[], EP2[][]; + public Inter EU0, EU1[], EU2[][]; + protected Inter ER0, ER1[], ER2[][]; + transient Inter ET0, ET1[], ET2[][]; + volatile Inter EV0, EV1[], EV2[][]; + + // initialize fields values + void init() { + initFields(false); + } + + // change fields values + void run() { + initFields(true); + } + + // calculate new fields values + void initFields(boolean flag) { + z0 = true; + b0 = java.lang.Byte.MAX_VALUE; + c0 = java.lang.Character.MAX_VALUE; + d0 = java.lang.Double.MAX_VALUE; + f0 = java.lang.Float.MAX_VALUE; + i0 = java.lang.Integer.MAX_VALUE; + l0 = java.lang.Long.MAX_VALUE; + s0 = java.lang.Short.MAX_VALUE; + + z1 = flag ? z1 : new boolean[] {z0}; + z2 = flag ? z2 : new boolean[][] {z1}; + b1 = flag ? b1 : new byte[] {b0}; + b2 = flag ? b2 : new byte[][] {b1}; + c1 = flag ? c1 : new char[] {c0}; + c2 = flag ? c2 : new char[][] {c1}; + d1 = flag ? d1 : new double[] {d0}; + d2 = flag ? d2 : new double[][] {d1}; + f1 = flag ? f1 : new float[] {f0}; + f2 = flag ? f2 : new float[][] {f1}; + i1 = flag ? i1 : new int[] {i0}; + i2 = flag ? i2 : new int[][] {i1}; + l1 = flag ? l1 : new long[] {l0}; + l2 = flag ? l2 : new long[][] {l1}; + s1 = flag ? s1 : new short[] {s0}; + s2 = flag ? s2 : new short[][] {s1}; + + lS0 = l0; + lP0 = l0; + lU0 = l0; + lR0 = l0; + lT0 = l0; + lV0 = l0; + + lS1 = flag ? lS1 : new long[] {lS0}; + lS2 = flag ? lS2 : new long[][] {lS1}; + lP1 = flag ? lP1 : new long[] {lP0}; + lP2 = flag ? lP2 : new long[][] {lP1}; + lU1 = flag ? lU1 : new long[] {lU0}; + lU2 = flag ? lU2 : new long[][] {lU1}; + lR1 = flag ? lR1 : new long[] {lR0}; + lR2 = flag ? lR2 : new long[][] {lR1}; + lT1 = flag ? lT1 : new long[] {lT0}; + lT2 = flag ? lT2 : new long[][] {lT1}; + lV1 = flag ? lV1 : new long[] {lV0}; + lV2 = flag ? lV2 : new long[][] {lV1}; + + X0 = flag ? X0 : new Class(); + X1 = flag ? X1 : new Class[] {X0}; + X2 = flag ? X2 : new Class[][] {X1}; + Z0 = flag ? Z0 : new Boolean(true); + Z1 = flag ? Z1 : new Boolean[] {Z0}; + Z2 = flag ? Z2 : new Boolean[][] {Z1}; + B0 = flag ? B0 : new Byte(java.lang.Byte.MIN_VALUE); + B1 = flag ? B1 : new Byte[] {B0}; + B2 = flag ? B2 : new Byte[][] {B1}; + C0 = flag ? C0 : new Character(java.lang.Character.MIN_VALUE); + C1 = flag ? C1 : new Character[] {C0}; + C2 = flag ? C2 : new Character[][]{C1}; + D0 = flag ? D0 : new Double(java.lang.Double.MIN_VALUE); + D1 = flag ? D1 : new Double[] {D0}; + D2 = flag ? D2 : new Double[][] {D1}; + F0 = flag ? F0 : new Float(java.lang.Float.MIN_VALUE); + F1 = flag ? F1 : new Float[] {F0}; + F2 = flag ? F2 : new Float[][] {F1}; + I0 = flag ? I0 : new Integer(java.lang.Integer.MIN_VALUE); + I1 = flag ? I1 : new Integer[] {I0}; + I2 = flag ? I2 : new Integer[][] {I1}; + L0 = flag ? L0 : new Long(java.lang.Long.MIN_VALUE); + L1 = flag ? L1 : new Long[] {L0}; + L2 = flag ? L2 : new Long[][] {L1}; + S0 = flag ? S0 : new Short(java.lang.Short.MIN_VALUE); + S1 = flag ? S1 : new Short[] {S0}; + S2 = flag ? S2 : new Short[][] {S1}; + W0 = flag ? W0 : new String(); + W1 = flag ? W1 : new String[] {W0}; + W2 = flag ? W2 : new String[][] {W1}; + O0 = flag ? O0 : new Object(); + O1 = flag ? O1 : new Object[] {O0}; + O2 = flag ? O2 : new Object[][] {O1}; + + LS0 = flag ? LS0 : new Long(java.lang.Long.MAX_VALUE); + LS1 = flag ? LS1 : new Long[] {LS0}; + LS2 = flag ? LS2 : new Long[][] {LS1}; + LP0 = flag ? LP0 : new Long(java.lang.Long.MAX_VALUE); + LP1 = flag ? LP1 : new Long[] {LP0}; + LP2 = flag ? LP2 : new Long[][] {LP1}; + LU0 = flag ? LU0 : new Long(java.lang.Long.MAX_VALUE); + LU1 = flag ? LU1 : new Long[] {LU0}; + LU2 = flag ? LU2 : new Long[][] {LU1}; + LR0 = flag ? LR0 : new Long(java.lang.Long.MAX_VALUE); + LR1 = flag ? LR1 : new Long[] {LR0}; + LR2 = flag ? LR2 : new Long[][] {LR1}; + LT0 = flag ? LT0 : new Long(java.lang.Long.MAX_VALUE); + LT1 = flag ? LT1 : new Long[] {LT0}; + LT2 = flag ? LT2 : new Long[][] {LT1}; + LV0 = flag ? LV0 : new Long(java.lang.Long.MAX_VALUE); + LV1 = flag ? LV1 : new Long[] {LV0}; + LV2 = flag ? LV2 : new Long[][] {LV1}; + + E0 = flag ? E0 : new Class(); + E1 = flag ? E1 : new Inter[] {E0}; + E2 = flag ? E2 : new Inter[][] {E1}; + ES0 = flag ? ES0 : new Class(); + ES1 = flag ? ES1 : new Inter[] {ES0}; + ES2 = flag ? ES2 : new Inter[][] {ES1}; + EP0 = flag ? EP0 : new Class(); + EP1 = flag ? EP1 : new Inter[] {EP0}; + EP2 = flag ? EP2 : new Inter[][] {EP1}; + EU0 = flag ? EU0 : new Class(); + EU1 = flag ? EU1 : new Inter[] {EU0}; + EU2 = flag ? EU2 : new Inter[][] {EU1}; + ER0 = flag ? ER0 : new Class(); + ER1 = flag ? ER1 : new Inter[] {ER0}; + ER2 = flag ? ER2 : new Inter[][] {ER1}; + ET0 = flag ? ET0 : new Class(); + ET1 = flag ? ET1 : new Inter[] {ET0}; + ET2 = flag ? ET2 : new Inter[][] {ET1}; + EV0 = flag ? EV0 : new Class(); + EV1 = flag ? EV1 : new Inter[] {EV0}; + EV2 = flag ? EV2 : new Inter[][] {EV1}; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest001/TestDescription.java new file mode 100644 index 00000000000..cf11d277c63 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest001. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for MonitorContendedEnterRequest and MonitorContendedEnterEvent, debugger force + * debuggee generate several thousands of MonitorContendedEnteredEvents and check that all events was received and contains + * correct information. + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debuggee VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 250 and threadsNumber to 1, but because of framework design each requested event should + * be generated in 3 different way(through synchronized block, synchronized method and JNI MonitorEnter) and + * by 3 different threads, so actual number of generated events is (eventsNumber * 9), and actual number of threads generating + * events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTER + * -eventTypes MONITOR_CONTENTED_ENTER + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 100 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest002/TestDescription.java new file mode 100644 index 00000000000..4f83a7a988c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnterRequest/MonitorContendedEnterRequest002. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for MonitorContendedEnterRequest and MonitorContendedEnterEvent, debugger force + * debuggee start several threads which simultaneously generate MonitorContendedEnteredEvents and checks that + * all events was received and contain correct information. + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debuggee VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 25 and threadsNumber to 3, but because of framework design each requested event should + * be generated in 3 different way(through synchronized block, synchronized method and JNI MonitorEnter) and + * by 3 different threads, so actual number of generated events is (eventsNumber * 9), and actual number of threads generating + * events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTER + * -eventTypes MONITOR_CONTENTED_ENTER + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 10 + * -threadsNumber 2 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassExclusionFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassExclusionFilter/TestDescription.java new file mode 100644 index 00000000000..869ef79e9de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassExclusionFilter/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnterRequest/addClassExclusionFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnterRequest.addClassExclusionFilter(String classPattern) + * complies with its spec: + * "Restricts the events generated by this request to those whose method is in a class whose name does not match + * this restricted regular expression, e.g. "java.*" or "*.Foo"." + * Test also checks that received com.sun.jdi.MonitorContendedEnterEvent complies with its spec and contains correct data. + * Test uses 3 different class exclusion patterns: + * - begins with '*' ('*Subclass') + * - ending with '*' ('nsk.share.jdi.MonitorEnterExecutor_*') + * - class name ('nsk.share.jdi.MonitorEnterExecutor_1Subclass') + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor enter events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTER + * -eventType MONITOR_CONTENTED_ENTER + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorEnterExecutor_'*':'*'Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ClassName/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ClassName/TestDescription.java new file mode 100644 index 00000000000..1b4d3f7df73 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ClassName/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ClassName. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnterRequest.addClassFilter(String classPattern) + * complies with its spec: + * "Restricts the events generated by this request to the preparation of reference types whose name matches this + * restricted regular expression. Regular expressions are limited to exact matches and patterns that begin + * with '*' or end with '*'; for example, "*.Foo" or "java.*"." + * Test also checks that received com.sun.jdi.MonitorContendedEnterEvent complies with its spec and contains correct data. + * Test uses 3 different class patterns: + * - begins with '*' ('*Subclass') + * - ending with '*' ('nsk.share.jdi.MonitorEnterExecutor_*') + * - class name ('nsk.share.jdi.MonitorEnterExecutor_1Subclass') + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor enter events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassFilterTest_ClassName + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTER + * -eventType MONITOR_CONTENTED_ENTER + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorEnterExecutor_'*':'*'Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ReferenceType/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ReferenceType/TestDescription.java new file mode 100644 index 00000000000..d31fe007efd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ReferenceType/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnterRequest/addClassFilter_ReferenceType. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnterRequest.addClassFilter(ReferenceType referenceType) + * complies with its spec: + * "Restricts the events generated by this request to be the preparation of the given reference type and any subtypes. + * An event will be generated for any prepared reference type that can be safely cast to the given reference type." + * Test also checks that received com.sun.jdi.MonitorContendedEnterEvent complies with its spec and contains correct data. + * Test uses 2 event filters: + * - add to request filter for class which has subclass (expect events for class and its subclasses) + * - add to request filter for class without subclasses + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor enter events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassFilterTest_ReferenceType + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTER + * -eventType MONITOR_CONTENTED_ENTER + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorEnterExecutor_1Subclass:nsk.share.jdi.MonitorEnterExecutor_2Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addInstanceFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addInstanceFilter/TestDescription.java new file mode 100644 index 00000000000..9b30671d1b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addInstanceFilter/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnterRequest/addInstanceFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnterRequest.addInstanceFilter(ObjectReference instance) + * complies with its spec: + * "Restricts the events generated by this request to those in which the currently executing instance ("this") is + * the object specified." + * Test also checks that received com.sun.jdi.MonitorContendedEnterEvent complies with its spec and contains correct data. + * Test uses following instances filters: + * - add to request filter for single object + * - add to request filter for the same object 2 times, expect behavior such as in previous case + * - add to request filter for 2 different objects, so events shouldn't be received + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor enter events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$InstanceFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTER + * -eventType MONITOR_CONTENTED_ENTER + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addThreadFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addThreadFilter/TestDescription.java new file mode 100644 index 00000000000..add52592e1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnterRequest/addThreadFilter/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnterRequest/addThreadFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnterRequest.addThreadFilter(ThreadReference thread) + * complies with its spec: + * "Restricts the events generated by this request to those in which the currently executing instance ("this") is + * the object specified." + * Test also checks that received com.sun.jdi.MonitorContendedEnterEvent complies with its spec and contains correct data. + * Test uses following thread filters: + * - add to request filter for single thread + * - add to request filter for the same thread 2 times, expect behavior such as in previous case + * - add to request filter for 2 different threads, so events shouldn't be received + * Test execute class nsk.share.jdi.EventTestTemplates$ThreadFilterTest which use JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor enter events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ThreadFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTER + * -eventType MONITOR_CONTENTED_ENTER + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest001/TestDescription.java new file mode 100644 index 00000000000..48e2c7c9aec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest001. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for MonitorContendedEnteredRequest and MonitorContendedEnteredEvent, debugger force + * debuggee generate several thousands of MonitorContendedEnteredEvents and checks that all events was received and contains + * correct information. + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 250 and threadsNumber to 1, but because of framework design each requested event should + * be generated in 3 different way(through synchronized block, synchronized method and JNI MonitorEnter) and + * by 3 different threads, so actual number of generated events is (eventsNumber * 9), and actual number of threads generating + * events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED + * -eventTypes MONITOR_CONTENTED_ENTERED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 100 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest002/TestDescription.java new file mode 100644 index 00000000000..40f79f602a9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnteredRequest/MonitorContendedEnteredRequest002. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for MonitorContendedEnteredRequest and MonitorContendedEnteredEvent, debugger forces + * debuggee start several threads which simultaneously generate MonitorContendedEnteredEvents and checks that + * all events was received and contains correct information. + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 25 and threadsNumber to 3, but because of framework design each requested event should + * be generated in 3 different way(through synchronized block, synchronized method and JNI MonitorEnter) and + * by 3 different threads, so actual number of generated events is (eventsNumber * 9), and actual number of threads generating + * events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED + * -eventTypes MONITOR_CONTENTED_ENTERED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 10 + * -threadsNumber 2 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassExclusionFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassExclusionFilter/TestDescription.java new file mode 100644 index 00000000000..5ebb02ba864 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassExclusionFilter/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnteredRequest/addClassExclusionFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnteredRequest.addClassExclusionFilter(String classPattern) + * complies with its spec: + * "Restricts the events generated by this request to those whose method is in a class whose name does not match + * this restricted regular expression, e.g. "java.*" or "*.Foo"." + * Test also checks that received com.sun.jdi.MonitorContendedEnteredEvent complies with its spec and contains correct data. + * Test uses 3 different class exclusion patterns: + * - begins with '*' ('*Subclass') + * - ending with '*' ('nsk.share.jdi.MonitorEnterExecutor_*') + * - class name ('nsk.share.jdi.MonitorEnterExecutor_1Subclass') + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor entered events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED + * -eventType MONITOR_CONTENTED_ENTERED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorEnterExecutor_'*':'*'Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ClassName/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ClassName/TestDescription.java new file mode 100644 index 00000000000..acee5e56f30 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ClassName/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ClassName. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnteredRequest.addClassFilter(String classPattern) + * complies with its spec: + * "Restricts the events generated by this request to the preparation of reference types whose name matches this + * restricted regular expression. Regular expressions are limited to exact matches and patterns that begin + * with '*' or end with '*'; for example, "*.Foo" or "java.*"." + * Test also checks that received com.sun.jdi.MonitorContendedEnteredEvent complies with its spec and contains correct data. + * Test uses 3 different class patterns: + * - begins with '*' ('*Subclass') + * - ending with '*' ('nsk.share.jdi.MonitorEnterExecutor_*') + * - class name ('nsk.share.jdi.MonitorEnterExecutor_1Subclass') + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor entered events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassFilterTest_ClassName + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED + * -eventType MONITOR_CONTENTED_ENTERED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorEnterExecutor_'*':'*'Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ReferenceType/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ReferenceType/TestDescription.java new file mode 100644 index 00000000000..56332be7c90 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ReferenceType/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnteredRequest/addClassFilter_ReferenceType. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnteredRequest.addClassFilter(ReferenceType referenceType) + * complies with its spec: + * "Restricts the events generated by this request to be the preparation of the given reference type and any subtypes. + * An event will be generated for any prepared reference type that can be safely cast to the given reference type." + * Test also checks that received com.sun.jdi.MonitorContendedEnteredEvent complies with its spec and contains correct data. + * Test uses 2 event filters: + * - add to request filter for class which has subclass (expect events for class and its subclasses) + * - add to request filter for class without subclasses + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor entered events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassFilterTest_ReferenceType + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED + * -eventType MONITOR_CONTENTED_ENTERED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorEnterExecutor_1Subclass:nsk.share.jdi.MonitorEnterExecutor_2Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addInstanceFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addInstanceFilter/TestDescription.java new file mode 100644 index 00000000000..eed3043adf1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addInstanceFilter/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnteredRequest/addInstanceFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnteredRequest.addInstanceFilter(ObjectReference instance) + * complies with its spec: + * "Restricts the events generated by this request to those in which the currently executing instance ("this") is + * the object specified." + * Test also checks that received com.sun.jdi.MonitorContendedEnteredEvent complies with its spec and contains correct data. + * Test uses following instances filters: + * - add to request filter for single object + * - add to request filter for the same object 2 times, expect behavior such as in previous case + * - add to request filter for 2 different objects, so events shouldn't be received + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor entered events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$InstanceFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED + * -eventType MONITOR_CONTENTED_ENTERED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addThreadFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addThreadFilter/TestDescription.java new file mode 100644 index 00000000000..b9d33103468 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorContendedEnteredRequest/addThreadFilter/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorContendedEnteredRequest/addThreadFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorContendedEnteredRequest.addThreadFilter(ThreadReference thread) + * complies with its spec: + * "Restricts the events generated by this request to those in which the currently executing instance ("this") is + * the object specified." + * Test also checks that received com.sun.jdi.MonitorContendedEnteredEvent complies with its spec and contains correct data. + * Test uses following thread filters: + * - add to request filter for single thread + * - add to request filter for the same thread 2 times, expect behavior such as in previous case + * - add to request filter for 2 different threads, so events shouldn't be received + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Monitor entered events are generated in 3 different ways: + * - through synchronized block + * - through synchronized method + * - through JNI MonitorEnter + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ThreadFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED + * -eventType MONITOR_CONTENTED_ENTERED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/MonitorWaitRequest001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/MonitorWaitRequest001/TestDescription.java new file mode 100644 index 00000000000..d473c5bd759 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/MonitorWaitRequest001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitRequest/MonitorWaitRequest001. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for MonitorWaitRequest and MonitorWaitEvent, debugger force + * debuggee generate several thousands of MonitorWaitEvents and checks that all events was received and contain + * correct information. + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debuggee VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 500 and threadsNumber to 1, but because of framework design generation of MonitorWait + * and MonitorWaited events is performed for 4 cases: thread exits from wait() after timeout, waiting thread is waked up with + * notify() or notifyAll(), or waiting thread is interrupted with interrupt(). + * Also events are generated by 3 different threads, so actual number of generated events is (eventsNumber * 12), + * and actual number of threads generating events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventTypes MONITOR_WAIT + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 100 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/MonitorWaitRequest002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/MonitorWaitRequest002/TestDescription.java new file mode 100644 index 00000000000..909ac3d3722 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/MonitorWaitRequest002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitRequest/MonitorWaitRequest002. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for MonitorWaitRequest and MonitorWaitEvent, debugger force + * debuggee start several threads which simultaneously generate MonitorWaitEvents and checks that + * all events was received and contain correct information. + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debuggee VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 25 and threadsNumber to 5, but because of framework design generation of MonitorWait + * and MonitorWaited events is performed for 4 cases: thread exits from wait() after timeout, waiting thread is waked up with + * notify() or notifyAll(), or waiting thread is interrupted with interrupt(). + * Also events are generated by 3 different threads, so actual number of generated events is (eventsNumber * 12), + * and actual number of threads generating events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventTypes MONITOR_WAIT + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 10 + * -threadsNumber 2 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassExclusionFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassExclusionFilter/TestDescription.java new file mode 100644 index 00000000000..e4481bc19f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassExclusionFilter/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitRequest/addClassExclusionFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitRequest.addClassExclusionFilter(String classPattern) + * complies with its spec: + * "Restricts the events generated by this request to those whose method is in a class whose name does not match + * this restricted regular expression, e.g. "java.*" or "*.Foo"." + * Test also checks that received com.sun.jdi.MonitorWaitEvent complies with its spec and contains correct data. + * Test uses 3 different class exclusion patterns: + * - begins with '*' ('*Subclass') + * - ending with '*' ('nsk.share.jdi.MonitorWaitExecutor_*') + * - class name ('nsk.share.jdi.MonitorWaitExecutor_1Subclass') + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAIT + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorWaitExecutor_'*':'*'Subclass:nsk.share.jdi.MonitorWaitExecutor_1Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ClassName/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ClassName/TestDescription.java new file mode 100644 index 00000000000..e842cfc4ac8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ClassName/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitRequest/addClassFilter_ClassName. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitRequest.addClassFilter(String classPattern) + * complies with its spec: + * "Restricts the events generated by this request to the preparation of reference types whose name matches this + * restricted regular expression. Regular expressions are limited to exact matches and patterns that begin + * with '*' or end with '*'; for example, "*.Foo" or "java.*"." + * Test also checks that received com.sun.jdi.MonitorWaitEvent complies with its spec and containc correct data. + * Test uses 3 different class patterns: + * - begins with '*' ('*Subclass') + * - ending with '*' ('nsk.share.jdi.MonitorWaitExecutor_*') + * - class name ('nsk.share.jdi.MonitorWaitExecutor_1Subclass') + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassFilterTest_ClassName + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAIT + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorWaitExecutor_'*':'*'Subclass:nsk.share.jdi.MonitorWaitExecutor_1Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ReferenceType/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ReferenceType/TestDescription.java new file mode 100644 index 00000000000..dba00008f11 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addClassFilter_ReferenceType/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitRequest/addClassFilter_ReferenceType. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitRequest.addClassFilter(ReferenceType referenceType) + * complies with its spec: + * "Restricts the events generated by this request to be the preparation of the given reference type and any subtypes. + * An event will be generated for any prepared reference type that can be safely cast to the given reference type." + * Test also checks that received com.sun.jdi.MonitorWaitEvent complies with its spec and contains correct data. + * Test uses 2 event filters: + * - add to request filter for class which has subclass (expect events for class and its subclasses) + * - add to request filter for class without subclasses + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassFilterTest_ReferenceType + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAIT + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorWaitExecutor_1Subclass:nsk.share.jdi.MonitorWaitExecutor_2Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addInstanceFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addInstanceFilter/TestDescription.java new file mode 100644 index 00000000000..f4f563d1664 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addInstanceFilter/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitRequest/addInstanceFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitRequest.addInstanceFilter(ObjectReference instance) + * complies with its spec: + * "Restricts the events generated by this request to those in which the currently executing instance ("this") is + * the object specified." + * Test also checks that received com.sun.jdi.MonitorWaitEvent complies with its spec and contains correct data. + * Test use following instances filters: + * - add to request filter for single object + * - add to request filter for the same object 2 times, expect behavior such as in previous case + * - add to request filter for 2 different objects, so events shouldn't be received + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$InstanceFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAIT + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addThreadFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addThreadFilter/TestDescription.java new file mode 100644 index 00000000000..82ad25df977 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitRequest/addThreadFilter/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitRequest/addThreadFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitRequest.addThreadFilter(ThreadReference thread) + * complies with its spec: + * "Restricts the events generated by this request to those in which the currently executing instance ("this") is + * the object specified." + * Test also checks that received com.sun.jdi.MonitorWaitEvent complies with its spec and contains correct data. + * Test use following thread filters: + * - add to request filter for single thread + * - add to request filter for the same thread 2 times, expect behavior such as in previous case + * - add to request filter for 2 different threads, so events shouldn't be received + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ThreadFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAIT + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest001/TestDescription.java new file mode 100644 index 00000000000..f4e14c8d471 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest001. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for MonitorWaitedRequest and MonitorWaitedEvent, debugger forces + * debuggee generate several thousands of MonitorWaitedEvents and checks that all events was received and contains + * correct information. + * MonitorWaited events are generated for 4 cases: + * - waiting thread exits from wait() after timeout + * - another thread wakes up waiting thread using notify() method + * - another thread wakes up waiting thread using notifyAll() method + * - another thread interrupts waiting thread using interrupt() method + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debuggee VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 500 and threadsNumber to 1, but because of framework design generation of MonitorWait + * and MonitorWaited events is performed for 4 cases: thread exits from wait() after timeout, waiting thread is waked up with + * notify() or notifyAll(), or waiting thread is interrupted with interrupt(). + * Also events are generated by 3 different threads, so actual number of generated events is (eventsNumber * 12), + * and actual number of threads generating events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventTypes MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 100 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest002/TestDescription.java new file mode 100644 index 00000000000..e82c3404459 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest002/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitedRequest/MonitorWaitedRequest002. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for MonitorWaitedRequest and MonitorWaitedEvent, debugger forces + * debuggee start several threads which simultaneously generate MonitorWaitedEvents and checks that + * all events was received and contains correct information. + * MonitorWaited events are generated for 4 cases: + * - waiting thread exits from wait() after timeout + * - another thread wakes up waiting thread using notify() method + * - another thread wakes up waiting thread using notifyAll() method + * - another thread interrupts waiting thread using interrupt() method + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 25 and threadsNumber to 5, but because of framework design generation of MonitorWait + * and MonitorWaited events is performed for 4 cases: thread exits from wait() after timeout, waiting thread is waked up with + * notify() or notifyAll(), or waiting thread is interrupted with interrupt(). + * Also events are generated by 3 different threads, so actual number of generated events is (eventsNumber * 12), + * and actual number of threads generating events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventTypes MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 10 + * -threadsNumber 2 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassExclusionFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassExclusionFilter/TestDescription.java new file mode 100644 index 00000000000..adcc36367c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassExclusionFilter/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open jdk.jdi/com.sun.tools.jdi:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitedRequest/addClassExclusionFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitedRequest.addClassExclusionFilter(String classPattern) + * complies with its spec: + * "Restricts the events generated by this request to those whose method is in a class whose name does not match + * this restricted regular expression, e.g. "java.*" or "*.Foo"." + * Test also checks that received com.sun.jdi.MonitorWaitedEvent complies with its spec and contain correct data. + * Test uses 3 different class exclusion patterns: + * - begins with '*' ('*Subclass') + * - ending with '*' ('nsk.share.jdi.MonitorWaitExecutor_*') + * - class name ('nsk.share.jdi.MonitorWaitExecutor_1Subclass') + * MonitorWaited events are generated for 4 cases: + * - waiting thread exits from wait() after timeout + * - another thread wakes up waiting thread using notify() method + * - another thread wakes up waiting thread using notifyAll() method + * - another thread interrupts waiting thread using interrupt() method + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm + * PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorWaitExecutor_'*':'*'Subclass:nsk.share.jdi.MonitorWaitExecutor_1Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ClassName/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ClassName/TestDescription.java new file mode 100644 index 00000000000..887786e8de6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ClassName/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitedRequest/addClassFilter_ClassName. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitedRequest.addClassFilter(String classPattern) + * complies with its spec: + * "Restricts the events generated by this request to the preparation of reference types whose name matches this + * restricted regular expression. Regular expressions are limited to exact matches and patterns that begin + * with '*' or end with '*'; for example, "*.Foo" or "java.*"." + * Test also checks that received com.sun.jdi.MonitorWaitedEvent complies with its spec and contain correct data. + * Test uses 3 different class patterns: + * - begins with '*' ('*Subclass') + * - ending with '*' ('nsk.share.jdi.MonitorWaitExecutor_*') + * - class name ('nsk.share.jdi.MonitorWaitExecutor_1Subclass') + * MonitorWaited events are generated for 4 cases: + * - waiting thread exits from wait() after timeout + * - another thread wakes up waiting thread using notify() method + * - another thread wakes up waiting thread using notifyAll() method + * - another thread interrupts waiting thread using interrupt() method + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassFilterTest_ClassName + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorWaitExecutor_'*':'*'Subclass:nsk.share.jdi.MonitorWaitExecutor_1Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ReferenceType/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ReferenceType/TestDescription.java new file mode 100644 index 00000000000..fab801125a3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addClassFilter_ReferenceType/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitedRequest/addClassFilter_ReferenceType. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitedRequest.addClassFilter(ReferenceType referenceType) + * complies with its spec: + * "Restricts the events generated by this request to be the preparation of the given reference type and any subtypes. + * An event will be generated for any prepared reference type that can be safely cast to the given reference type." + * Test also checks that received com.sun.jdi.MonitorWaitedEvent complies with its spec and contain correct data. + * Test uses 2 event filters: + * - add to request filter for class which has subclass (expect events for class and its subclasses) + * - add to request filter for class whiteout subclasses + * MonitorWaited events are generated for 4 cases: + * - waiting thread exits from wait() after timeout + * - another thread wakes up waiting thread using notify() method + * - another thread wakes up waiting thread using notifyAll() method + * - another thread interrupts waiting thread using interrupt() method + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ClassFilterTest_ReferenceType + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -classPatterns nsk.share.jdi.MonitorWaitExecutor_1Subclass:nsk.share.jdi.MonitorWaitExecutor_2Subclass + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addInstanceFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addInstanceFilter/TestDescription.java new file mode 100644 index 00000000000..badd630eab2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addInstanceFilter/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitedRequest/addInstanceFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitedRequest.addInstanceFilter(ObjectReference instance) + * complies with its spec: + * "Restricts the events generated by this request to those in which the currently executing instance ("this") is + * the object specified." + * Test also checks that received com.sun.jdi.MonitorWaitedEvent complies with its spec and contain correct data. + * Test use following instances filters: + * - add to request filter for single object + * - add to request filter for the same object 2 times, expect behavior such as in previous case + * - add to request filter for 2 different objects, so events shouldn't be received + * MonitorWaited events are generated for 4 cases: + * - waiting thread exits from wait() after timeout + * - another thread wakes up waiting thread using notify() method + * - another thread wakes up waiting thread using notifyAll() method + * - another thread interrupts waiting thread using interrupt() method + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$InstanceFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addThreadFilter/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addThreadFilter/TestDescription.java new file mode 100644 index 00000000000..f5f2727a35e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MonitorWaitedRequest/addThreadFilter/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/MonitorWaitedRequest/addThreadFilter. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that a result of the method com.sun.jdi.MonitorWaitedRequest.addThreadFilter(ThreadReference thread) + * complies with its spec: + * "Restricts the events generated by this request to those in which the currently executing instance ("this") is + * the object specified." + * Test also checks that received com.sun.jdi.MonitorWaitedEvent complies with its spec and contain correct data. + * Test uses following thread filters: + * - add to request filter for single thread + * - add to request filter for the same thread 2 times, expect behavior such as in previous case + * - add to request filter for 2 different threads, so events shouldn't be received + * MonitorWaited events are generated for 4 cases: + * - waiting thread exits from wait() after timeout + * - another thread wakes up waiting thread using notify() method + * - another thread wakes up waiting thread using notifyAll() method + * - another thread interrupts waiting thread using interrupt() method + * Test executes class nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debugge VM to create number of objects which should generate events during test + * - if any event filters are used each generating event object is checked is this object accepted by all filters, + * if object was accepted it should save information about all generated events and this information is available for debugger + * - debuggee performs event generation and stop at breakpoint + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * In addition to the main scenario tests using event filters also check following cases: + * - attempt to add filter to enabled or deleted request throws 'InvalidRequestStateException' + * - corresponding method EventRequestManager.xxxRequests() returns created event request + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$ThreadFilterTest + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -eventType MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001.java new file mode 100644 index 00000000000..595d52e167d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up that NullPointerException will be thrown in + * the following cases:
    + * - invokeMethod(null, method, params,ObjectReference.INVOKE_SINGLE_THREADED)
    + * - invokeMethod(thread, null, params,ObjectReference.INVOKE_SINGLE_THREADED)
    + * - invokeMethod(thread, method, null,ObjectReference.INVOKE_SINGLE_THREADED)
    + * In case
    + * invokeMethod(thread, method, params,Integer.MAX_VALUE)
    + * invokeMethod(thread, method, params,Integer.MIN_VALUE)
    + * no exception is expected. + */ + +public class bounds001 { + + private final static String prefix = "nsk.jdi.ObjectReference._bounds_."; + private final static String debuggerName = prefix + "bounds001"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private ThreadReference thread; + + class TestRuntimeException extends RuntimeException { + TestRuntimeException(String msg) { + super("TestRuntimeException: " + msg); + } + } + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + bounds001 thisTest = new bounds001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + ReferenceType debugeeClass = debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(debugeeClass, + bounds001a.brkpMethodName, + bounds001a.brkpLineNumber); + debugee.resume(); + + debugee.sendSignal(""); + Event event = null; + + // waiting the breakpoint event + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + + thread = brkpEvent.thread(); + + Field field = debugeeClass.fieldByName(bounds001a.testedFieldName); + ObjectReference objRef = (ObjectReference )debugeeClass.getValue(field); + ReferenceType testedClass = objRef.referenceType(); + + Method method = debugee.methodByName(testedClass, bounds001a.testedMethod); + + display("\nTEST BEGINS"); + display("==========="); + + List params = createParams(1); + Value retValue; + display("Method : " + method); + + display("invokeMethod(null, method, params," + + "ObjectReference.INVOKE_NONVIRTUAL)"); + try { + retValue = objRef.invokeMethod(null, method, params, + ObjectReference.INVOKE_NONVIRTUAL); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("invokeMethod(thread, null, params," + + "ObjectReference.INVOKE_NONVIRTUAL)"); + try { + retValue = objRef.invokeMethod(thread, null, params, + ObjectReference.INVOKE_NONVIRTUAL); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("invokeMethod(thread, method, null," + + "ObjectReference.INVOKE_NONVIRTUAL)"); + try { + retValue = objRef.invokeMethod(thread, method, null, + ObjectReference.INVOKE_NONVIRTUAL); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("invokeMethod(thread, method, params," + + "Integer.MAX_VALUE)"); + try { + retValue = objRef.invokeMethod(thread, method, params, + Integer.MAX_VALUE); + if (((PrimitiveValue)retValue).intValue() != 1) { + complain("Wrong returned value " + retValue.toString()); + exitStatus = Consts.TEST_FAILED; + } else { + display("returned value is " + retValue.toString()); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("invokeMethod(thread, method, params," + + "Integer.MIN_VALUE)"); + try { + retValue = objRef.invokeMethod(thread, method, params, + Integer.MIN_VALUE); + if (((PrimitiveValue)retValue).intValue() != 1) { + complain("Wrong returned value " + retValue.toString()); + exitStatus = Consts.TEST_FAILED; + } else { + display("returned value is " + retValue.toString()); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private List createParams(int size) { + Vector params = new Vector(); + for (int i = 0; i < size; i++) { + params.add(debugee.VM().mirrorOf(i + 1)); + } + return params; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001/TestDescription.java new file mode 100644 index 00000000000..33de989cf1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/_bounds_/bounds001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the method com.sun.jdi.ObjectReference.invokeMethod() + * Test checks up that NullPointerException will be thrown in + * the following cases: + * - invokeMethod(null, method, params,ObjectReference.INVOKE_NONVIRTUAL) + * - invokeMethod(thread, null, params,ObjectReference.INVOKE_NONVIRTUAL) + * - invokeMethod(thread, method, null,ObjectReference.INVOKE_NONVIRTUAL) + * In case + * invokeMethod(thread, method, params,Integer.MAX_VALUE) + * invokeMethod(thread, method, params,Integer.MIN_VALUE) + * no exception is expected. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference._bounds_.bounds001 + * nsk.jdi.ObjectReference._bounds_.bounds001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference._bounds_.bounds001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001a.java new file mode 100644 index 00000000000..ba5f0880bab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds001a.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * bounds001a is deugee's part of the bounds001. + */ +public class bounds001a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 51; + + public final static String testedFieldName = "testedObj"; + public final static String testedMethod = "justMethod"; + + private static bounds001b testedObj = new bounds001b(); + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(bounds001.SGNL_READY); + String instr = pipe.readln(); + log.display("breakpoint line"); // brkpLineNumber + instr = pipe.readln(); + if (instr.equals(bounds001.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class bounds001b { + public static int justMethod(int val) { + return val; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002.java new file mode 100644 index 00000000000..5ea2cb6e3f0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up ObjectReference methods for the following cases:
    + * - getValue(null)
    + * - getValues(null)
    + * - getValues(list with size = 0)
    + * - setValue(null, null)
    + * - setValue(field, null)
    + * NullPointerException is expected for every test case + * except for the last. + */ + +public class bounds002 { + + private final static String prefix = "nsk.jdi.ObjectReference._bounds_."; + private final static String debuggerName = prefix + "bounds002"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + bounds002 thisTest = new bounds002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType debugeeClass = debugee.classByName(debugeeName); + + Field field = debugeeClass.fieldByName(bounds002a.testedFieldName); + ObjectReference objRef = (ObjectReference )debugeeClass.getValue(field); + ReferenceType testedClass = objRef.referenceType(); + + display("\nTEST BEGINS"); + display("==========="); + + Value retValue; + + display("getValue(null)"); + try { + retValue = objRef.getValue(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("getValues(null)"); + try { + objRef.getValues(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + List lst = null; + display("getValues(list with size = 0)"); + try { + objRef.getValues(lst); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("setValue(null, null)"); + try { + objRef.setValue(null, null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + Field fld = objRef.referenceType().fieldByName(bounds002a.testedFieldName); + display("setValue(field, null)"); + try { + objRef.setValue(fld, null); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("equals(null)"); + try { + if (objRef.equals(null)) { + complain("is equal to "); + exitStatus = Consts.TEST_FAILED; + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002/TestDescription.java new file mode 100644 index 00000000000..da950db3f88 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/_bounds_/bounds002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the methods com.sun.jdi.ObjectReference + * for the following cases: + * - getValue(null) + * - getValues(null) + * - getValues(list with size = 0) + * - setValue(null, null) + * - setValue(field, null) + * NullPointerException is expected for every test case except for the last. + * In case + * setValue(field, null), where field is mirror of Object + * no exception is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference._bounds_.bounds002 + * nsk.jdi.ObjectReference._bounds_.bounds002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference._bounds_.bounds002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002a.java new file mode 100644 index 00000000000..0dee72712e9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds002a.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * bounds002a is deugee's part of the bounds002. + */ +public class bounds002a { + + public final static String testedFieldName = "testedObj"; + public final static String testedMethod = "justMethod"; + + private static bounds002b testedObj = new bounds002b(); + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(bounds002.SGNL_READY); + String instr = pipe.readln(); + if (instr.equals(bounds002.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class bounds002b { + private static Object testedObj; + public static int justMethod(int val) { + return val; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003.java new file mode 100644 index 00000000000..e209ffee69c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference._bounds_; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.lang.reflect.Array; + +/** + * The test checks up the methods:
    + * com.sun.jdi.ObjectReference.setValue(Field, Object)
    + * com.sun.jdi.ObjectReference.getValue(Field)
    + * for boundary values of primitive types
    + * + * Test checks up the following assertion:
    + * Primitive arguments must be either assignment compatible with
    + * the field type or must be convertible to the field type
    + * without loss of information.
    + * for every primitive type.
    + */ + +public class bounds003 extends ValueConversionDebugger { + + private static class TestedFieldData { + public String fieldName; + public ValueType fieldType; + + public TestedFieldData(String fieldName, ValueType fieldType) { + this.fieldName = fieldName; + this.fieldType = fieldType; + } + } + + private static TestedFieldData[] testedFields = { + new TestedFieldData("byteField", BYTE), + new TestedFieldData("charField", CHAR), + new TestedFieldData("doubleField", DOUBLE), + new TestedFieldData("floatField", FLOAT), + new TestedFieldData("intField", INT), + new TestedFieldData("longField", LONG), + new TestedFieldData("shortField", SHORT) + }; + + private static byte [] byteFieldValues = + {Byte.MIN_VALUE, + -1, + 0, + 1, + Byte.MAX_VALUE}; + private static char [] charFieldValues = + {Character.MIN_VALUE, + Character.MAX_VALUE}; + private static double [] doubleFieldValues = + {Double.NEGATIVE_INFINITY, + -1.5D, + -1.0D, + -0.0D, + +0.0D, + Double.MIN_VALUE, + 1.0D, + 1.5D, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY}; + private static float [] floatFieldValues = + {Float.NEGATIVE_INFINITY, + -1.5F, + -1.0F, + -0.0F, + +0.0F, + Float.MIN_VALUE, + 1.0F, + 1.5F, + Float.MAX_VALUE, + Float.POSITIVE_INFINITY}; + private static int [] intFieldValues = + {Integer.MIN_VALUE, + -1, + 0, + 1, + 1234567890, + Integer.MAX_VALUE}; + private static long [] longFieldValues = + {Long.MIN_VALUE, + -1L, + 0L, + 1L, + 1234567890123456789L, + Long.MAX_VALUE}; + private static short [] shortFieldValues = + {Short.MIN_VALUE, + -1, + 0, + 1, + Short.MAX_VALUE}; + + protected String debuggeeClassName() { + return bounds003a.class.getName(); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + return new bounds003().runIt(argv, out); + } + + protected void doTest() { + debuggee.suspend(); + + ReferenceType debugeeClass = debuggee.classByName(debuggeeClassNameWithoutArgs()); + + Field field = debugeeClass.fieldByName(bounds003a.testedFieldName); + ObjectReference objRef = (ObjectReference )debugeeClass.getValue(field); + ReferenceType testedClass = objRef.referenceType(); + + display("\nTEST BEGINS"); + display("==========="); + + PrimitiveValue retValue, value; + Object arr = null; + boolean validConversion; + + for (TestedFieldData testedField : testedFields) { + field = testedClass.fieldByName(testedField.fieldName); + display("Field : " + field); + display("======================"); + for (ValueType type : ValueType.values()) { + switch (type) { + case BYTE: + arr = byteFieldValues; + display("byte values"); + break; + case CHAR: + arr = charFieldValues; + display("char values"); + break; + case DOUBLE: + arr = doubleFieldValues; + display("double values"); + break; + case FLOAT: + arr = floatFieldValues; + display("float values"); + break; + case INT: + arr = intFieldValues; + display("integer values"); + break; + case LONG: + arr = longFieldValues; + display("long values"); + break; + case SHORT: + arr = shortFieldValues; + display("short values"); + break; + default: + complain("***TEST CASE ERROR***"); + setSuccess(false); + continue; + } + display("-----------------"); + for (int i = 0; i < Array.getLength(arr); i++) { + value = createValue(arr, i); + validConversion = isValidConversion(testedField.fieldType, value); + display(">value = " + value.toString()); + try { + objRef.setValue(field, value); + if (!validConversion) { + complain(lastConversion); + complain("***InvalidTypeException is not thrown***"); + display(""); + setSuccess(false); + continue; + } + + retValue = (PrimitiveValue) objRef.getValue(field); + + checkValueConversion(value, retValue); + + } catch(InvalidTypeException e) { + if (validConversion) { + complain(lastConversion); + complain("*** unexpected InvalidTypeException***"); + display(""); + setSuccess(false); + } else { + display(lastConversion); + display("!!!expected InvalidTypeException"); + display(""); + } + } catch(Exception e) { + complain("unexpected " + e); + display(""); + setSuccess(false); + } + } + display(""); + } + } + + display("============="); + display("TEST FINISHES\n"); + + debuggee.resume(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003/TestDescription.java new file mode 100644 index 00000000000..6cc8a38ac3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/_bounds_/bounds003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the methods: + * com.sun.jdi.ObjectReference.setValue(Field, Object) + * com.sun.jdi.ObjectReference.getValue(Field) + * for boundry values of primitive types + * Test checks up the following assertion: + * Primitive arguments must be either assignment compatible with + * the field type or must be convertible to the field type + * without loss of information. + * for every primitive type. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference._bounds_.bounds003 + * nsk.jdi.ObjectReference._bounds_.bounds003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference._bounds_.bounds003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003a.java new file mode 100644 index 00000000000..ee7663e9443 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/_bounds_/bounds003a.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference._bounds_; + + +import nsk.share.jdi.*; + +/** + * bounds003a is debuggee's part of the bounds003. + */ +public class bounds003a extends AbstractJDIDebuggee { + + public static String testedFieldName = "fieldObj"; + + private byte byteField; + private char charField; + private double doubleField; + private float floatField; + private int intField; + private long longField; + private short shortField; + + static bounds003a fieldObj = new bounds003a(); + + public static void main (String args[]) { + new bounds003a().doTest(args); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001.java new file mode 100644 index 00000000000..6b39a826dc7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.disableCollection; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.disableCollection()
    + * complies with its specification.
    + *
    + * The case for testing includes not throwing
    + * ObjectCollectedException
    + * provided a mirrored object is not collected.
    + */ + +public class disablecollection001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/disableCollection/disablecollection001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new disablecollection001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.disableCollection.disablecollection001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.disableCollection.TestClass"; + + //String mName = "nsk.jdi.ObjectReference.disableCollection"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String objName = "testObj"; + + log2("getting testedClass object"); + try { + + testedClass = (ReferenceType) + vm.classesByName(debuggeeName).get(0); + + ObjectReference objRef = (ObjectReference) + testedClass.getValue(testedClass.fieldByName(objName)); + + + log2(".......checking up on not throwing ObjectCollectedException "); + + try { + objRef.disableCollection(); + log2(" ObjectCollectedException is not thrown"); + } catch ( UnsupportedOperationException e1 ) { + log3("ERROR: ObjectCollectedException"); + testExitCode = FAILED; + } catch ( Exception e2 ) { + testExitCode = FAILED; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001/TestDescription.java new file mode 100644 index 00000000000..76b5636d651 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/disableCollection/disablecollection001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.disableCollection() + * complies with its spec: + * public void disableCollection() + * Prevents garbage collection for this object. + * By default all ObjectReference values returned by JDI may be + * collected at any time the target VM is running. + * A call to this method guarantees that the object will not be collected. + * enableCollection() can be used to allow collection once again. + * Calls to this method are counted. + * Every call to this method requires a corresponding call to + * enableCollection() before garbage collection is re-enabled. + * Note that while the target VM is suspended, + * no garbage collection will occur because all threads are suspended. + * The typical examination of variables, fields, and arrays during + * the suspension is safe without explicitly disabling garbage collection. + * This method should be used sparingly, as + * it alters the pattern of garbage collection in the target VM and, + * consequently, may result in application behavior under the debugger that + * differs from its non-debugged behavior. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.disableCollection.disablecollection001; + * the debuggee program - nsk.jdi.ObjectReference.disableCollection.disablecollection001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.disableCollection.disablecollection001 + * nsk.jdi.ObjectReference.disableCollection.disablecollection001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.disableCollection.disablecollection001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001a.java new file mode 100644 index 00000000000..72b3e794efa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection001a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.disableCollection; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the disablecollection001 JDI test. + */ + +public class disablecollection001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass testObj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ObjectReference.disableCollection()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Prevents garbage collection for this object.
    + * By default all ObjectReference values returned by JDI
    + * may be collected at any time the target VM is running.
    + * A call to this method guarantees that
    + * the object will not be collected.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new array object "arr1" to be tested on
    + * collection and invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger gets ObjectReference mirroring arr1,
    + * disables collecting "arr1" resumes the debuggee and waits for new
    + * BreakpointEvent.
    + * - The debuggee assigns null to arr1 to make object's memory available
    + * to be collected and pertforms a loop in which it creates new
    + * objects until VM throws OutOfMemoryError. Then it informs the
    + * debugger of the ERROR with new BreakPoint event.
    + * - Upon getting the event,
    + * the debugger gets new ObjectReference mirroring arr1,
    + * resumes the debuggee, and waits for new breakpoint.
    + * - The debuggee invokes a garbage collector and informs the debugger
    + * with new breakpoint event.
    + * - Upon getting the event,
    + * the debugger gets new ObjectReference mirroring arr1 once again.
    + *
    + * If no ObjectCollectedexception is thrown during the above cooperation
    + * the test is PASSED, othewise, FAILED.
    + *
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class disablecollection002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/disableCollection/disablecollection002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new disablecollection002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.disableCollection.disablecollection002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String name = "arr1"; + + ReferenceType arr1RefType = null; + ObjectReference arr1ObjRef = null; + + try { + log2("......getting: arr1ObjRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(name));"); + arr1ObjRef = (ObjectReference) + debuggeeClass.getValue(debuggeeClass.fieldByName(name)); + + log2("...... arr1ObjRef.disableCollection();"); + arr1ObjRef.disableCollection(); + + log2("......vm.resume();"); + vm.resume(); + breakpointForCommunication(); + log2(" after breakpointForCommunication();"); + + log2("......getting: arr1RefType = arr1ObjRef.referenceType();"); + arr1RefType = arr1ObjRef.referenceType(); + + log2("......vm.resume();"); + vm.resume(); + breakpointForCommunication(); + log2(" after breakpointForCommunication();"); + + log2("......after debuggee invoked runTime.gc() :"); + log2(" getting: arr1RefType = arr1ObjRef.referenceType();"); + arr1RefType = arr1ObjRef.referenceType(); + + } catch ( ObjectCollectedException e ) { + log3("ERROR: caught ObjectCollectedException"); + throw new JDITestRuntimeException("** unexpected ObjectCollectedException **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002/TestDescription.java new file mode 100644 index 00000000000..de92a5943ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/disableCollection/disablecollection002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.disableCollection() + * complies with its spec: + * public void disableCollection() + * Prevents garbage collection for this object. + * By default all ObjectReference values returned by JDI may be collected at any + * time the target VM is running. A call to this method guarantees that + * the object will not be collected. + * enableCollection() can be used to allow collection once again. + * Calls to this method are counted. + * Every call to this method requires a corresponding call to enableCollection() + * before garbage collection is re-enabled. + * Note that while the target VM is suspended, no garbage collection will occur + * because all threads are suspended. The typical examination of variables, fields, + * and arrays during the suspension is safe without + * explicitly disabling garbage collection. + * This method should be used sparingly, + * as it alters the pattern of garbage collection in the target VM and, consequently, + * may result in application behavior under the debugger that + * differs from its non-debugged behavior. + * The test checks up on the following assertion: + * Prevents garbage collection for this object. + * By default all ObjectReference values returned by JDI may be collected at + * any time the target VM is running. A call to this method guarantees that + * the object will not be collected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.disableCollection.disablecollection002; + * the debuggee program - nsk.jdi.ObjectReference.disableCollection.disablecollection002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.disableCollection.disablecollection002 + * nsk.jdi.ObjectReference.disableCollection.disablecollection002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.disableCollection.disablecollection002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002a.java new file mode 100644 index 00000000000..7c45352c7d1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002a.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.disableCollection; + +import nsk.share.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the disablecollection002 JDI test. + */ + +public class disablecollection002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Runtime runTime = Runtime.getRuntime(); + + static array1 arr1 = null; + static array2 arr2[] = null; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + log1("runTime.maxMemory() == " + runTime.maxMemory()); + log1("runTime.totalMemory() == " + runTime.totalMemory()); + log1("runTime.freeMemory() == " + runTime.freeMemory()); + + try { + arr1 = new array1(); + arr2 = new array2[100]; + } catch (OutOfMemoryError e) { + log1("caught: OutOfMemoryError while creating objects"); + instruction = end; + methodForCommunication(); + break label0; + } + + methodForCommunication(); + break ; + + case 1: + log1("arr1 = null;"); + arr1 = null; + try { + for (int k = 0; k < 100; k++) { + log1("> " + k + " runTime.maxMemory() == " + runTime.maxMemory()); + log1(" " + k + " runTime.totalMemory() == " + runTime.totalMemory()); + log1(" " + k + " runTime.freeMemory() == " + runTime.freeMemory()); + arr2[k] = new array2(); + } + } catch (OutOfMemoryError e) { + log1("caught: OutOfMemoryError"); + } + methodForCommunication(); + break ; + + case 2: + log1("runTime.gc();"); + runTime.gc(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + static int getArraySize(long longValue) { + int arraySize; + if (longValue > Integer.MAX_VALUE) + arraySize = Integer.MAX_VALUE; + else + arraySize = (int)longValue; + + return arraySize; + } + + static class array1 { + int a1[] = new int[getArraySize(runTime.maxMemory() / 10)]; + } + + static class array2 { + int a2[] = new int[getArraySize(runTime.maxMemory() / 100)]; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/dummyPackage/invokemethod014a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/dummyPackage/invokemethod014a.java new file mode 100644 index 00000000000..a860460713e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/dummyPackage/invokemethod014a.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2002, 2018, 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. + */ + +// dummy package +package nsk.jdi.ObjectReference.dummyPackage; + +/** + * This is an auxiliary class outside a main debuggee package. It's + * used to provoke IllegalArgumentException in the debugger: + * non-public methods cannot be accessed from outside the package. + */ +public class invokemethod014a { + // methods with default access are below + byte byteMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"byteMeth\" was invoked from outside package!"); + return 127; + } + + short shortMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"shortMeth\" was invoked from outside not public!"); + return -32768; + } + + int intMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"intMeth\" was invoked from outside not public!"); + return 2147483647; + } + + long longMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"longMeth\" was invoked from outside not public!"); + return 9223372036854775807L; + } + + float floatMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"floatMeth\" was invoked from outside not public!"); + return 5.1F; + } + + double doubleMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"doubleMeth\" was invoked from outside not public!"); + return 6.2D; + } + + char charMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"charMeth\" was invoked from outside not public!"); + return 'a'; + } + + boolean booleanMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"booleanMeth\" was invoked from outside not public!"); + return false; + } + + String strMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"strMeth\" was invoked from outside not public!"); + return "string method"; + } + + void voidMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod14a: non-public method \"voidMeth\" was invoked from outside not public!"); + } + + // protected methods are below + protected byte protByteMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protByteMeth\" was invoked!"); + return 127; + } + + protected short protShortMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protShortMeth\" was invoked!"); + return -32768; + } + + protected int protIntMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protIntMeth\" was invoked!"); + return 2147483647; + } + + protected long protLongMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protLongMeth\" was invoked!"); + return 9223372036854775807L; + } + + protected float protFloatMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protFloatMeth\" was invoked!"); + return 5.1F; + } + + protected double protDoubleMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protDoubleMeth\" was invoked!"); + return 6.2D; + } + + protected char protCharMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protCharMeth\" was invoked!"); + return 'a'; + } + + protected boolean protBooleanMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protBooleanMeth\" was invoked!"); + return false; + } + + protected String protStrMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protStrMeth\" was invoked!"); + return "string method"; + } + + protected void protVoidMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: protected method \"protVoidMeth\" was invoked!"); + } + + // private methods are below + private byte privByteMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privByteMeth\" was invoked!"); + return 127; + } + + private short privShortMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privShortMeth\" was invoked!"); + return -32768; + } + + private int privIntMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privIntMeth\" was invoked!"); + return 2147483647; + } + + private long privLongMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privLongMeth\" was invoked!"); + return 9223372036854775807L; + } + + private float privFloatMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privFloatMeth\" was invoked!"); + return 5.1F; + } + + private double privDoubleMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privDoubleMeth\" was invoked!"); + return 6.2D; + } + + private char privCharMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privCharMeth\" was invoked!"); + return 'a'; + } + + private boolean privBooleanMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privBooleanMeth\" was invoked!"); + return false; + } + + private String privStrMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privStrMeth\" was invoked!"); + return "string method"; + } + + private void privVoidMeth() { + nsk.jdi.ObjectReference.invokeMethod.invokemethod014t.log.complain("invokemethod014a: private method \"privVoidMeth\" was invoked!"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001.java new file mode 100644 index 00000000000..d0611900c49 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.entryCount; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.entryCount()
    + * complies with its specification.
    + *
    + * The case for testing includes throwing
    + * UnsupportedOperationException
    + * provided
    + * VirtualMachine.canGetMonitorInfo() == false
    + */ + +public class entrycount001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/entryCount/entrycount001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new entrycount001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.entryCount.entrycount001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.entryCount.TestClass"; + + //String mName = "nsk.jdi.ObjectReference.entryCount"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String objName = "testObj"; + + log2("getting testedClass object"); + try { + + testedClass = (ReferenceType) + vm.classesByName(debuggeeName).get(0); + + ObjectReference objRef = (ObjectReference) + testedClass.getValue(testedClass.fieldByName(objName)); + + if (!vm.canGetMonitorInfo()) { + + log2(".......vm.canGetMonitorInfo() == false"); + log2(".......checking up on throwing UnsupportedOperationException"); + + try { + int count = objRef.entryCount(); + log3("ERROR: UnsupportedOperationException is not thrown"); + testExitCode = FAILED; + } catch ( UnsupportedOperationException e1 ) { + log2(" UnsupportedOperationException"); + } catch ( Exception e2 ) { + testExitCode = FAILED; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + } + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001/TestDescription.java new file mode 100644 index 00000000000..ec8f33ffbde --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/entryCount/entrycount001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.entryCount() + * complies with its spec: + * public int entryCount() + * throws IncompatibleThreadStateException + * Returns the number times this object's monitor has been entered + * by the current owning thread. See ThreadReference.ownedMonitors() for + * a definition of ownership. + * Not all target VMs support this operation. + * See VirtualMachine#canGetMonitorInfo to determine + * if the operation is supported. + * Returns: the integer count of the number of entries. + * Throws: java.lang.UnsupportedOperationException - + * if the target target VM does not support this operation. + * IncompatibleThreadStateException - + * if the owning thread is not suspended in the target VM + * ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes throwing + * UnsupportedOperationException + * provided + * VirtualMachine.canGetMonitorInfo() == false + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.entryCount.entrycount 00; + * the debuggee program - nsk.jdi.ObjectReference.entryCount.entrycount 00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.entryCount.entrycount001 + * nsk.jdi.ObjectReference.entryCount.entrycount001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.entryCount.entrycount001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001a.java new file mode 100644 index 00000000000..b8f1c4bdfd0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount001a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.entryCount; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the entrycount001 JDI test. + */ + +public class entrycount001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass testObj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + private Event waitForEvent (EventRequest eventRequest) { + + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002/TestDescription.java new file mode 100644 index 00000000000..8af1f3823d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/entryCount/entrycount002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks the following assertion of + * com.sun.jdi.ObjectReference.entryCount method spec: + * Returns the number times this object's monitor has been entered + * by the current owning thread. + * The debugger program - nsk.jdi.ObjectReference.entryCount.entrycount002; + * the debuggee program - nsk.jdi.ObjectReference.entryCount.entrycount002a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * The debuggee invokes syncronized foo method of entrycount002aLock class. + * The foo method is recursive : invokes itself with the argument substracted 1 + * until 0 is reached. The debugger creates MethodEntryRequest filtered + * to class of foo method. Each time the foo is invoked, the debuggee is + * suspended. Upon receiving next MethodEntryEvent, the debugger calls + * entryCount method for the debuggee's field of entrycount002aLock type. + * The returned value must be equal to the expected one - the level of + * recursion. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.makeBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.entryCount.entrycount002 + * nsk.jdi.ObjectReference.entryCount.entrycount002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.entryCount.entrycount002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002a.java new file mode 100644 index 00000000000..a2fe3a78c3b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.entryCount; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class entrycount002a { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + private static void methodForCommunication() { + int i = instruction; // entrycount002.lineForBreak + int curInstruction = i; + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static entrycount002aLock lockObj = new entrycount002aLock(); + static int levelMax = 10; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + display("debuggee started!"); + + label0: + for (int testCase = 0; instruction != quit; testCase++) { + + switch (testCase) { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test case section + case 0: + display("call methodForCommunication() #0"); + methodForCommunication(); + + lockObj.foo(levelMax); + break; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end of section + + default: + instruction = quit; + break; + } + + display("call methodForCommunication() #1"); + methodForCommunication(); + if (instruction == quit) + break; + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + +} + +//--------------------------------------------------------- test specific classes + +class entrycount002aLock { + synchronized void foo (int level) { + if (level <= 0) { + return; + } + level--; + entrycount002a.display("Calling foo with level : " + level); + foo(level); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001.java new file mode 100644 index 00000000000..17114974c6b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.equals()
    + * complies with its specification.
    + * The case for testing incliudes two ObjectReference objects
    + * beloning to the same VM.
    + *
    + * The test works as follows.
    + * Upon launch, a debuggee infroms a debugger of creating
    + * tested objects.
    + * The debuggee gets two ObjectReference objRef1 and objRef2
    + * mirroring the same object in the debuggee, and
    + * ObjectReference objRef3 mirroring another object.
    + * Then it checks up that
    + * - objRef1.equals(objRef2) returns true and
    + * - objRef1.equals(objRef3) returns false.
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/equals/equals001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.equals.equals001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValues.TestClass"; + + private String testedClass1Name = + "nsk.jdi.ObjectReference.getValues.TestClass1"; + + //String mName = "nsk.jdi.ObjectReference.equals"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + log2("......getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeClass = (ReferenceType) classes.get(0); + + + Field field1 = null; + Value val1 = null; + List fields = null; + + String objName = "testObj"; + String obj1Name = "testObj1"; + + ObjectReference objRef1 = null; + ObjectReference objRef2 = null; + ObjectReference objRef3 = null; + + + log2("......getting first mirror of tested TestClass obj : ObjectReference objRef1"); + + field1 = debuggeeClass.fieldByName(objName); + val1 = debuggeeClass.getValue(field1); + objRef1 = (ObjectReference) val1; + + + log2("......getting second mirror of tested TestClass obj : ObjectReference objRef2"); + + objRef2 = (ObjectReference) val1; + + + log2("......getting amirror of tested TestClass1 obj : ObjectReference objRef3"); + + field1 = debuggeeClass.fieldByName(obj1Name); + val1 = debuggeeClass.getValue(field1); + objRef3 = (ObjectReference) val1; + + + log2("......testing equality of objRef1 and objRef2"); + if (!objRef1.equals(objRef2)) { + log3("ERROR: objRef1 is not equal to objRef2"); + testExitCode = FAILED; + } + + log2("......testing inequality of objRef1 and objRef3"); + if (objRef1.equals(objRef3)) { + log3("ERROR: objRef1 is equal to objRef3"); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..ddd77b2a1d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this ObjectReference for equality. + * Returns: true if the Object is an ObjectReference, + * if the ObjectReferences belong to the same VM, and + * if applying the "==" operator on the mirrored objects in that VM + * evaluates to true. + * Overrides: equals in class java.lang.Object + * The case for testing includes objects beloning to the same VM. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.equals.equals001; + * the debuggee program - nsk.jdi.ObjectReference.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.equals.equals001 + * nsk.jdi.ObjectReference.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001a.java new file mode 100644 index 00000000000..01a6b5a3625 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/equals/equals001a.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the equals001 JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass testObj = new TestClass(); + static TestClass1 testObj1 = new TestClass1(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.getValue()
    + * complies with its specification.
    + *
    + * The cases for testing include
    + * static and instance fields of primitive types created in
    + * debuggee's second thread.
    + *
    + * The test works as follows.
    + * Upon launch, a debuggee creates second thread, thread2 and
    + * informs a debugger of its creation.
    + * The debugger :
    + * gets a mirror of current Stackframe object
    + * gets mirrors of fields to test, and
    + * performs casts from Value to corresponding PrimitiveValue
    + * for each of the tested types.
    + */ + +public class getvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/getValue/getvalue001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.getValue.getvalue001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValue.Threadgetvalue001a"; + + //String mName = "nsk.jdi.ObjectReference.getValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedClass = null; + + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + String breakpointMethod1 = "runt1"; + String bpLine1 = "breakpointLineNumber1"; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + + StackFrame stackFrame = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + ObjectReference thisobj = null; + thisobj = stackFrame.thisObject(); + + String bl1 = "bl1", bl2 = "bl2"; + String bt1 = "bt1", bt2 = "bt2"; + String ch1 = "ch1", ch2 = "ch2"; + String db1 = "db1", db2 = "db2"; + String fl1 = "fl1", fl2 = "fl2"; + String in1 = "in1", in2 = "in2"; + String ln1 = "ln1", ln2 = "ln2"; + String sh1 = "sh1", sh2 = "sh2"; + + Field fsbl1 = testedClass.fieldByName("bl1"); + Field fsbt1 = testedClass.fieldByName("bt1"); + Field fsch1 = testedClass.fieldByName("ch1"); + Field fsdb1 = testedClass.fieldByName("db1"); + Field fsfl1 = testedClass.fieldByName("fl1"); + Field fsin1 = testedClass.fieldByName("in1"); + Field fsln1 = testedClass.fieldByName("ln1"); + Field fssh1 = testedClass.fieldByName("sh1"); + + Field fsbl2 = testedClass.fieldByName("bl2"); + Field fsbt2 = testedClass.fieldByName("bt2"); + Field fsch2 = testedClass.fieldByName("ch2"); + Field fsdb2 = testedClass.fieldByName("db2"); + Field fsfl2 = testedClass.fieldByName("fl2"); + Field fsin2 = testedClass.fieldByName("in2"); + Field fsln2 = testedClass.fieldByName("ln2"); + Field fssh2 = testedClass.fieldByName("sh2"); + + + log2("......loop of checks on each primitive type by performing statements like first one:"); + log2(" BooleanValue blv = (BooleanValue) thisobj.getValue(fsbl1);"); + for ( int i3 = 0; i3 < 8; i3++) { + + try { + + switch (i3) { + + case 0: + log2(" checking up on boolean"); + BooleanValue blv = (BooleanValue) thisobj.getValue(fsbl1); + + blv = (BooleanValue) thisobj.getValue(fsbl2); + break; + + case 1: + log2(" checking up on byte"); + ByteValue btv = (ByteValue) thisobj.getValue(fsbt1); + + btv = (ByteValue) thisobj.getValue(fsbt2); + break; + + case 2: + log2(" checking up on char"); + CharValue chv = (CharValue) thisobj.getValue(fsch1); + + chv = (CharValue) thisobj.getValue(fsch2); + break; + + case 3: + log2(" checking up on double"); + DoubleValue dbv = (DoubleValue) thisobj.getValue(fsdb1); + + dbv = (DoubleValue) thisobj.getValue(fsdb2); + break; + + case 4: + log2(" checking up on float"); + FloatValue flv = (FloatValue) thisobj.getValue(fsfl1); + + flv = (FloatValue) thisobj.getValue(fsfl2); + break; + + case 5: + log2(" checking up on int"); + IntegerValue inv = (IntegerValue) thisobj.getValue(fsin1); + + inv = (IntegerValue) thisobj.getValue(fsin2); + break; + + case 6: + log2(" checking up on long"); + LongValue lnv = (LongValue) thisobj.getValue(fsln1); + + lnv = (LongValue) thisobj.getValue(fsln2); + break; + + case 7: + log2(" checking up on short"); + ShortValue shv = (ShortValue) thisobj.getValue(fssh1); + + shv = (ShortValue) thisobj.getValue(fssh2); + break; + + + default : log3("ERROR: TEST ERROR: case: default:"); + expresult = returnCode1; + break; + + } // end of switch + + } catch ( IllegalArgumentException e ) { + log3("ERROR: IllegalArgumentException"); + expresult = returnCode1; + } catch ( ObjectCollectedException e ) { + log3("ERROR: ObjectCollectedException"); + expresult = 1; + } catch ( VMMismatchException e ) { + log3("ERROR: VMMismatchException"); + expresult = 1; + } catch ( Exception e ) { + log3("ERROR: unexpected exception: " + e); + expresult = returnCode1; + } // end of try + + } // end of for + } + + if (thread2 != null) { + thread2.resume(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { +// Method method = (Method) testedclass.methodsByName(methodName).get(0); + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = +// ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001/TestDescription.java new file mode 100644 index 00000000000..e4872f8f31d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/getValue/getvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.getValue() + * complies with its spec: + * public Value getValue(Field sig) + * Gets the value of a given instance or static field in this object. + * The Field must be valid for this ObjectReference; + * that is, it must be from the mirrored object's class or + * a superclass of that class. + * Parameters: sig - the field containing the requested value + * Returns: the Value of the instance field. + * Throws: IllegalArgumentException - + * if the field is not valid for this object's class. + * ObjectCollectedException - + * if this object has been garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The cases for testing include static and instance fields of primitive types + * created in debuggee's second thread. + * No exception is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.getValue.getvalue001; + * the debuggee program - nsk.jdi.ObjectReference.getValue.getvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test fixed according to test bug: + * 4955084 TEST_BUG: JDI test does not resume suspended thread + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.getValue.getvalue001 + * nsk.jdi.ObjectReference.getValue.getvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.getValue.getvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001a.java new file mode 100644 index 00000000000..53f34af9f49 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue001a.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalue001 JDI test. + */ + +public class getvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.getValue()
    + * complies with its specification.
    + *
    + * The cases for testing include
    + * static and instance fields of primitive types created in
    + * debuggee's second thread with the method ClassType.newInstance().
    + *
    + * The test works as follows.
    + * Upon launch, a debuggee creates second thread, thread2 and
    + * informs a debugger of its creation.
    + * The debugger :
    + * creates in the thread2
    + * new object with static and instace fields,
    + * gets mirrors of fields to test, and
    + * performs casts from Value to corresponding PrimitiveValue
    + * for each of the tested types.
    + */ + +public class getvalue002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/getValue/getvalue002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalue002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.getValue.getvalue002a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValue.getvalue002aTestClass"; + + private String threadName = "testedThread"; + + private String threadClassName = + "nsk.jdi.ObjectReference.getValue.getvalue002aThread"; + + //String mName = "nsk.jdi.ObjectReference.getValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedClass = null; + ReferenceType threadClass = null; + + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String breakpointMethod1 = "runt1"; + + String bpLine1 = "breakpointLineNumber1"; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + + ClassType classType = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(threadClassName); + threadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + + log2("......getting Thread thread2 - 1-st argument"); + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + + log2("......getting ClassType classType - an object to apply newInstance()"); + classes = vm.classesByName(testedClassName); + testedClass = (ReferenceType) classes.get(0); + classType = (ClassType) testedClass; + + List invokeMethods = testedClass.methods(); + ListIterator li = invokeMethods.listIterator(); + + Method invokeMethod = null; + + log2("......getting Method invokeMethod - a constructor to invoke; 2-nd argument"); + try { + for (;;) { + invokeMethod = (Method) li.next(); + if (!invokeMethod.isConstructor()) + continue; + if (invokeMethod.arguments().size() == 0) + break; + } + } catch ( AbsentInformationException e1 ) { + log2(" AbsentInformationException "); + break label1; + } catch ( NoSuchElementException e2 ) { + log3("ERROR: NoSuchElementException "); + expresult = returnCode2; + break label1; + } + + + // this is only to get an empty List with JDI methods but not with API List methods + log2("......forming an empty List argumentList for 3-d argument"); + log2(" List argumentList = testedClass.methodsByName('m');"); + List argumentList = testedClass.methodsByName("m"); + log2(" argumentList.clear();"); + argumentList.clear(); + + + ObjectReference objRef = null; + + log2("......ObjectReference objRef = classType.newInstance(thread2, invokeMethod, argumentList, 0);"); + log2(" No Exception is expected"); + try { + objRef = classType.newInstance(thread2, + invokeMethod, Collections.emptyList(), 0); + if (objRef == null) + log2(" objRe == null"); + + + log2(" ReferenceType refType = objRef.referenceType();"); + ReferenceType refType = objRef.referenceType(); + + log2(" ClassType cType = (ClassType) refType;"); + ClassType cType = (ClassType) refType; + + log2("......checking up on: cType.equals(classType); "); + if (!cType.equals(classType)) { + log3("ERROR: !cType.equals(classType)"); + expresult = returnCode1; + } + + } catch ( Exception e ) { + log3("ERROR: Exception for classType.newInstance() :" + e); + expresult = returnCode1; + } + + ObjectReference thisobj = objRef; + + String bl1 = "bl1", bl2 = "bl2"; + String bt1 = "bt1", bt2 = "bt2"; + String ch1 = "ch1", ch2 = "ch2"; + String db1 = "db1", db2 = "db2"; + String fl1 = "fl1", fl2 = "fl2"; + String in1 = "in1", in2 = "in2"; + String ln1 = "ln1", ln2 = "ln2"; + String sh1 = "sh1", sh2 = "sh2"; + + Field fsbl1 = testedClass.fieldByName("bl1"); + Field fsbt1 = testedClass.fieldByName("bt1"); + Field fsch1 = testedClass.fieldByName("ch1"); + Field fsdb1 = testedClass.fieldByName("db1"); + Field fsfl1 = testedClass.fieldByName("fl1"); + Field fsin1 = testedClass.fieldByName("in1"); + Field fsln1 = testedClass.fieldByName("ln1"); + Field fssh1 = testedClass.fieldByName("sh1"); + + Field fsbl2 = testedClass.fieldByName("bl2"); + Field fsbt2 = testedClass.fieldByName("bt2"); + Field fsch2 = testedClass.fieldByName("ch2"); + Field fsdb2 = testedClass.fieldByName("db2"); + Field fsfl2 = testedClass.fieldByName("fl2"); + Field fsin2 = testedClass.fieldByName("in2"); + Field fsln2 = testedClass.fieldByName("ln2"); + Field fssh2 = testedClass.fieldByName("sh2"); + + + log2("......loop of checks on each primitive type by performing statements like first one:"); + log2(" BooleanValue blv = (BooleanValue) thisobj.getValue(fsbl1);"); + for ( int i3 = 0; i3 < 8; i3++) { + + try { + + switch (i3) { + + case 0: + log2(" checking up on boolean"); + BooleanValue blv = (BooleanValue) thisobj.getValue(fsbl1); + + blv = (BooleanValue) thisobj.getValue(fsbl2); + break; + + case 1: + log2(" checking up on byte"); + ByteValue btv = (ByteValue) thisobj.getValue(fsbt1); + + btv = (ByteValue) thisobj.getValue(fsbt2); + break; + + case 2: + log2(" checking up on char"); + CharValue chv = (CharValue) thisobj.getValue(fsch1); + + chv = (CharValue) thisobj.getValue(fsch2); + break; + + case 3: + log2(" checking up on double"); + DoubleValue dbv = (DoubleValue) thisobj.getValue(fsdb1); + + dbv = (DoubleValue) thisobj.getValue(fsdb2); + break; + + case 4: + log2(" checking up on float"); + FloatValue flv = (FloatValue) thisobj.getValue(fsfl1); + + flv = (FloatValue) thisobj.getValue(fsfl2); + break; + + case 5: + log2(" checking up on int"); + IntegerValue inv = (IntegerValue) thisobj.getValue(fsin1); + + inv = (IntegerValue) thisobj.getValue(fsin2); + break; + + case 6: + log2(" checking up on long"); + LongValue lnv = (LongValue) thisobj.getValue(fsln1); + + lnv = (LongValue) thisobj.getValue(fsln2); + break; + + case 7: + log2(" checking up on short"); + ShortValue shv = (ShortValue) thisobj.getValue(fssh1); + + shv = (ShortValue) thisobj.getValue(fssh2); + break; + + + default : log3("ERROR: TEST ERROR: case: default:"); + expresult = returnCode1; + break; + + } // end of switch + + } catch ( IllegalArgumentException e ) { + log3("ERROR: IllegalArgumentException"); + expresult = returnCode1; + } catch ( ObjectCollectedException e ) { + log3("ERROR: ObjectCollectedException"); + expresult = returnCode1; + } catch ( VMMismatchException e ) { + log3("ERROR: VMMismatchException"); + expresult = returnCode1; + } catch ( Exception e ) { + log3("ERROR: unexpected exception: " + e); + expresult = returnCode1; + } // end of try + + } // end of for + + + } + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { +// Method method = (Method) testedclass.methodsByName(methodName).get(0); + Method method = (Method) threadClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = +// ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + ( (IntegerValue) threadClass.getValue(threadClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002/TestDescription.java new file mode 100644 index 00000000000..a67ce38b5a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002/TestDescription.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/getValue/getvalue002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.getValue() + * complies with its spec: + * public Value getValue(Field sig) + * Gets the value of a given instance or static field in this object. + * The Field must be valid for this ObjectReference; + * that is, it must be from the mirrored object's class or + * a superclass of that class. + * Parameters: sig - the field containing the requested value + * Returns: the Value of the instance field. + * Throws: IllegalArgumentException - + * if the field is not valid for this object's class. + * ObjectCollectedException - + * if this object has been garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The cases for testing include static and instance fields of primitive types + * created in debuggee's second thread with the method ClassType.newInstance(). + * No exception is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.getValue.getvalue002; + * the debuggee program - nsk.jdi.ObjectReference.getValue.getvalue002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.getValue.getvalue002 + * nsk.jdi.ObjectReference.getValue.getvalue002a + * + * @comment make sure getvalue002a is compiled with full debug info + * @clean nsk.jdi.ObjectReference.getValue.getvalue002a + * @compile -g:lines,source,vars ../getvalue002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.getValue.getvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002a.java new file mode 100644 index 00000000000..6e47f790924 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue002a.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalue002 JDI test. + */ + +public class getvalue002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static getvalue002aTestClass obj = new getvalue002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.getValue()
    + * complies with its specification.
    + *
    + * The cases for testing include fields of following ClassTypes:
    + * Class type, Interface type, Class Array type, and
    + * primitive Array type
    + * The test works as follows.
    + * Upon launch, a debuggee informs a debugger of creating
    + * a tested object. The debugger gets mirrors of fields to test
    + * and compares types of returned Value object to expected ones.
    + */ + +public class getvalue003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/getValue/getvalue003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalue003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.getValue.getvalue003a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValue.getvalue003aTestClass"; + + //String mName = "nsk.jdi.ObjectReference.getValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + log2("......getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeClass = (ReferenceType) classes.get(0); + + + String objName = "testObj"; + + String tClassObjName = "class2_0"; + String tClassArrayObjName = "cfc_0"; + String tIfaceObjName = "iface_0"; + String tPrimArrayObjName = "bl1"; + + + String className = "nsk.jdi.ObjectReference.getValue.getvalue003aTestClass"; + + String tClassTypeName = "nsk.jdi.ObjectReference.getValue.getvalue003aClassForCheck_2"; + String tClassArrayTypeName = "nsk.jdi.ObjectReference.getValue.getvalue003aClassForCheck[]"; + String tIfaceTypeName = "nsk.jdi.ObjectReference.getValue.getvalue003aClassForCheck_2"; + String tPrimArrayTypeName = "boolean[][][][]"; + + + Field field1 = null; + Field field2 = null; + Value val1 = null; + Value val2 = null; + Type type1 = null; + String str = null; + + ObjectReference objRef = null; + + ReferenceType classRef = null; + + + log2("......getting the mirror of tested getvalue003aTestClass obj : ObjectReference objRef"); + + field1 = debuggeeClass.fieldByName(objName); + val1 = debuggeeClass.getValue(field1); + objRef = (ObjectReference) val1; + + log2("......getting the mirror of tested getvalue003aTestClass : ReferenceType classRef"); + + classes = vm.classesByName(testedClassName); + classRef = (ReferenceType) classes.get(0); + + + log2("......checking up on class ClassType Field: getvalue003aClassForCheck_2 class2_0"); + + field2 = classRef.fieldByName(tClassObjName); + val2 = objRef.getValue(field2); + type1 = val2.type(); + str = type1.name(); + + if (!str.equals(tClassTypeName)) { + log3("ERROR: type of Value != nsk.jdi.ObjectReference.getValue.getvalue003aClassForCheck_2"); + log3("ERROR: type of Value == " + str); + testExitCode = FAILED; + } + + + log2("......checking up on class ArrayType Field: getvalue003aClassForCheck[] cfc_0"); + + field2 = classRef.fieldByName(tClassArrayObjName); + val2 = objRef.getValue(field2); + type1 = val2.type(); + str = type1.name(); + + if (!str.equals(tClassArrayTypeName)) { + log3("ERROR: type of Value != nsk.jdi.ObjectReference.getValue.getvalue003aClassForCheck[]"); + log3("ERROR: type of Value == " + str); + testExitCode = FAILED; + } + + + log2("......checking up on class InterfaceType Field: getvalue003aInterfaceForCheck iface_0"); + + field2 = classRef.fieldByName(tIfaceObjName); + val2 = objRef.getValue(field2); + type1 = val2.type(); + str = type1.name(); + + if (!str.equals(tIfaceTypeName)) { + log3("ERROR: type of Value != nsk.jdi.ObjectReference.getValue.getvalue003aClassForCheck_2"); + log3("ERROR: type of Value == " + str); + testExitCode = FAILED; + } + + + log2("......checking up on class PrimitiveArrayType Field: boolean[][][][] bl1"); + + field2 = classRef.fieldByName(tPrimArrayObjName); + val2 = objRef.getValue(field2); + type1 = val2.type(); + str = type1.name(); + + if (!str.equals(tPrimArrayTypeName)) { + log3("ERROR: type of Value != boolean[][][][]"); + log3("ERROR: type of Value == " + str); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003/TestDescription.java new file mode 100644 index 00000000000..54218cd2e57 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/getValue/getvalue003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.getValue() + * complies with its spec: + * public Value getValue(Field sig) + * Gets the value of a given instance or static field in this object. + * The Field must be valid for this ObjectReference; + * that is, it must be from the mirrored object's class or + * a superclass of that class. + * Parameters: sig - the field containing the requested value + * Returns: the Value of the instance field. + * Throws: IllegalArgumentException - + * if the field is not valid for this object's class. + * ObjectCollectedException - + * if this object has been garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The cases for testing include Class type, Interface type, Class Array type, + * and primitive Array type objects. + * No exception is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.getValue.getvalue003; + * the debuggee program - nsk.jdi.ObjectReference.getValue.getvalue003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.getValue.getvalue003 + * nsk.jdi.ObjectReference.getValue.getvalue003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.getValue.getvalue003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003a.java new file mode 100644 index 00000000000..daa53efc19d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue003a.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalue003 JDI test. + */ + +public class getvalue003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static getvalue003aTestClass testObj = new getvalue003aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.getValue()
    + * complies with its specification.
    + *
    + * The case for testing includes throwing IllegalArgumentException
    + *
    + * The test works as follows.
    + * Upon launch, a debuggee informs a debugger of creating
    + * a tested object. The debugger gets mirror of a field
    + * in another class type object and uses it as an argument.
    + * The expected result of invoking the method is the Exception.
    + */ + +public class getvalue004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/getValue/getvalue004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalue004().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.getValue.getvalue004a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValue.getvalue004aTestClass"; + + //String mName = "nsk.jdi.ObjectReference.getValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + log2("......getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeClass = (ReferenceType) classes.get(0); + + String tClassObjName = "class2_0"; + String objName = "testObj"; + String obj1Name = "PASSED"; + + Field field1 = null; + Field field2 = null; + Value val1 = null; + Value val2 = null; + + ObjectReference objRef = null; + + + log2("......getting the mirror of tested getvalue004aTestClass obj : ObjectReference objRef"); + + field1 = debuggeeClass.fieldByName(objName); + val1 = debuggeeClass.getValue(field1); + objRef = (ObjectReference) val1; + + log2("......getting the mirror of a field in another class"); + field1 = debuggeeClass.fieldByName(obj1Name); + + log2("......performing the check; IllegalArgumentException is expected"); + try { + val2 = objRef.getValue(field1); + log3("ERROR: no IllegalArgumentException"); + testExitCode = FAILED; + } catch ( IllegalArgumentException e ) { + log2(" IllegalArgumentException"); + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004/TestDescription.java new file mode 100644 index 00000000000..c5762cf87b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/getValue/getvalue004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.getValue() + * complies with its spec: + * public Value getValue(Field sig) + * Gets the value of a given instance or static field in this object. + * The Field must be valid for this ObjectReference; + * that is, it must be from the mirrored object's class or + * a superclass of that class. + * Parameters: sig - the field containing the requested value + * Returns: the Value of the instance field. + * Throws: IllegalArgumentException - + * if the field is not valid for this object's class. + * ObjectCollectedException - + * if this object has been garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The case for testing includes throwing IllegalArgumentException. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.getValue.getvalue004; + * the debuggee program - nsk.jdi.ObjectReference.getValue.getvalue004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.getValue.getvalue004 + * nsk.jdi.ObjectReference.getValue.getvalue004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.getValue.getvalue004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004a.java new file mode 100644 index 00000000000..e480ac4c9b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValue/getvalue004a.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalue004 JDI test. + */ + +public class getvalue004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static getvalue004aTestClass testObj = new getvalue004aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.getValues()
    + * complies with its specification.
    + *

    + * The case for tesing includes fields in the following object:
    + * class getvalues001aTestClass extends getvalues001aTestClass1
    + * when both classes contain class and instance fields of
    + * primitive types.
    + *
    + * The test works as follows:
    + * Upon launch, a debuggee informs a debuggee of creating
    + * the tested object.
    + * The debugger gets a Map of objects and checks up that:
    + * - the Map contains the tested number of elements and
    + * - the Map doesn't contain duplications.
    + */ + +public class getvalues001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/getValues/getvalues001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalues001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.getValues.getvalues001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValues.getvalues001aTestClass"; + + //String mName = "nsk.jdi.ObjectReference.getValues"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + log2("......getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeClass = (ReferenceType) classes.get(0); + + + Field field1 = null; + Value val1 = null; + List fields = null; + + String objName = "testObj"; + + ObjectReference objRef = null; + + ReferenceType testedClass = null; + + + log2("......getting the mirror of tested getvalues001aTestClass obj : ObjectReference objRef"); + + field1 = debuggeeClass.fieldByName(objName); + val1 = debuggeeClass.getValue(field1); + objRef = (ObjectReference) val1; + + log2("......getting the mirror of tested getvalues001aTestClass : ReferenceType classRef"); + + classes = vm.classesByName(testedClassName); + testedClass = (ReferenceType) classes.get(0); + fields = testedClass.visibleFields(); + + + String [] names = { "bl1", "bl2", + "bt1", "bt2", + "ch1", "ch2", + "db1", "db2", + "fl1", "fl2", + "in1", "in2", + "ln1", "ln2", + "sh1", "sh2" }; + + Field [] fArray = { + testedClass.fieldByName(names[ 0]), testedClass.fieldByName(names[ 1]), + testedClass.fieldByName(names[ 2]), testedClass.fieldByName(names[ 3]), + testedClass.fieldByName(names[ 4]), testedClass.fieldByName(names[ 5]), + testedClass.fieldByName(names[ 6]), testedClass.fieldByName(names[ 7]), + testedClass.fieldByName(names[ 8]), testedClass.fieldByName(names[ 9]), + testedClass.fieldByName(names[10]), testedClass.fieldByName(names[11]), + testedClass.fieldByName(names[12]), testedClass.fieldByName(names[13]), + testedClass.fieldByName(names[14]), testedClass.fieldByName(names[15]) }; + + + log2("......getting the Map of tested fields : Map vMap = objRef.getValues(fields);"); + + Map vMap = objRef.getValues(fields); + Set keySet = vMap.keySet(); + Iterator si = keySet.iterator(); + + Field f1 = null; + + int flag = 0; + int controlFlag = 0xFFFF; + + log2("......loop of testing the Map"); + + for (int ifor = 0; si.hasNext(); ifor++) { + + f1 = si.next(); + + int flag1 = 0; + for (int ifor1 = 0; ifor1 < 16; ifor1++) { + + if (f1.equals(fArray[ifor1])) { + if (flag1 == 0) { + flag1++; + flag |= 1 << ifor1; + break; + } else { + log3("ERROR: duplication in the Map; ifor = " + ifor + " ifor1 = " + ifor1); + testExitCode = FAILED; + } + } + } + } + if (flag != controlFlag) { + log3("ERROR: returned Map object doesn't contain all tested fields"); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001/TestDescription.java new file mode 100644 index 00000000000..157e11b5d07 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/getValues/getvalues001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.getValues() + * complies with its spec: + * public Map getValues(List fields) + * Gets the value of multiple instance and/or static fields in this object. + * The Fields must be valid for this ObjectReference; that is, + * they must be from the mirrored object's class or a superclass of that class. + * Parameters: fields - a list of Field objects containing the requested values. + * Returns: a Map of the requested Field objects with their Value. + * Throws: IllegalArgumentException - + * if any field is not valid for this object's class. + * ObjectCollectedException - + * if this object has been garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The case for tesing includes fields in the following object: + * class TestClass extends TestClass1 + * when both classes contain class and instance fields of primitive types. + * IllegalArgumentException is not expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.getValues.getvalues001; + * the debuggee program - nsk.jdi.ObjectReference.getValues.getvalues001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.getValues.getvalues001 + * nsk.jdi.ObjectReference.getValues.getvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.getValues.getvalues001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001a.java new file mode 100644 index 00000000000..730367cde8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues001a.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalues001 JDI test. + */ + +public class getvalues001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static getvalues001aTestClass testObj = new getvalues001aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.getValues()
    + * complies with its specification.
    + *

    + * The case for tesing includes fields in the following object:
    + * class getvalues002aTestClass extends getvalues002aTestClass1
    + * when both classes contain class and instance fields of
    + * Class Interface and Array types.
    + *
    + * The test works as follows:
    + * Upon launch, a debuggee informs a debuggee of creating
    + * the tested object.
    + * The debugger gets a Map of objects and checks up that:
    + * - the Map contains the tested number of elements and
    + * - the Map doesn't contain duplications.
    + */ + +public class getvalues002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/getValues/getvalues002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalues002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.getValues.getvalues002a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValues.getvalues002aTestClass"; + + //String mName = "nsk.jdi.ObjectReference.getValues"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + log2("......getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeClass = (ReferenceType) classes.get(0); + + + Field field1 = null; + Value val1 = null; + List fields = null; + + String objName = "testObj"; + + ObjectReference objRef = null; + + ReferenceType testedClass = null; + + + log2("......getting the mirror of tested getvalues002aTestClass obj : ObjectReference objRef"); + + field1 = debuggeeClass.fieldByName(objName); + val1 = debuggeeClass.getValue(field1); + objRef = (ObjectReference) val1; + + log2("......getting the mirror of tested getvalues002aTestClass : ReferenceType classRef"); + + classes = vm.classesByName(testedClassName); + testedClass = (ReferenceType) classes.get(0); + fields = testedClass.visibleFields(); + + + String [] names = { "class2_0", "iface_0", + "cfc_0", "bl0" }; + + Field [] fArray = { + testedClass.fieldByName(names[ 0]), testedClass.fieldByName(names[ 1]), + testedClass.fieldByName(names[ 2]), testedClass.fieldByName(names[ 3]) }; + + + + log2("......getting the Map of tested fields : Map vMap = objRef.getValues(fields);"); + + Map vMap = objRef.getValues(fields); + Set keySet = vMap.keySet(); + Iterator si = keySet.iterator(); + + Field f1 = null; + + int flag = 0; + int controlFlag = 0xF; + + log2("......loop of testing the Map"); + + for (int ifor = 0; si.hasNext(); ifor++) { + + f1 = si.next(); + + int flag1 = 0; + for (int ifor1 = 0; ifor1 < 4; ifor1++) { + + if (f1.equals(fArray[ifor1])) { + if (flag1 == 0) { + flag1++; + flag |= 1 << ifor1; + break; + } else { + log3("ERROR: duplication in the Map; ifor = " + ifor + " ifor1 = " + ifor1); + testExitCode = FAILED; + } + } + } + } + if (flag != controlFlag) { + log3("ERROR: returned Map object doesn't contain all tested fields"); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002/TestDescription.java new file mode 100644 index 00000000000..0a29af3cbcf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002/TestDescription.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/getValues/getvalues002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.getValues() + * complies with its spec: + * public Map getValues(List fields) + * Gets the value of multiple instance and/or static fields in this object. + * The Fields must be valid for this ObjectReference; that is, + * they must be from the mirrored object's class or a superclass of that class. + * Parameters: fields - a list of Field objects containing the requested values. + * Returns: a Map of the requested Field objects with their Value. + * Throws: IllegalArgumentException - + * if any field is not valid for this object's class. + * ObjectCollectedException - + * if this object has been garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The case for tesing includes fields in the following object: + * class TestClass extends TestClass1 + * when both classes contain class and instance fields of + * Class Interface and Array types. + * IllegalArgumentException is not expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.getValues.getvalues002; + * the debuggee program - nsk.jdi.ObjectReference.getValues.getvalues002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.getValues.getvalues002 + * nsk.jdi.ObjectReference.getValues.getvalues002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.getValues.getvalues002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002a.java new file mode 100644 index 00000000000..e57ef7567da --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues002a.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalues002 JDI test. + */ + +public class getvalues002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static getvalues002aTestClass testObj = new getvalues002aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.getValues()
    + * complies with its specification.
    + *

    + * The case for tesing includes fields in two objects of two
    + * different classes: getvalues003aTestClass and getvalues003aTestClass1
    + * As List of arguments contains Fileds defined in another class
    + * throwing IllegalArgumentException is expected.
    + *
    + * The test works as follows:
    + * Upon launch, a debuggee informs a debuggee of creating
    + * the tested object.
    + * The debugger gets a List of fields from the getvalues003aTestClass1 object1
    + * and uses it as the argument for get.Values() invoked on
    + * getvalues003aTestClass object.
    + */ + +public class getvalues003{ + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/getValues/getvalues003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalues003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.getValues.getvalues003a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValues.getvalues003aTestClass"; + + private String testedClass1Name = + "nsk.jdi.ObjectReference.getValues.getvalues003aTestClass1"; + + //String mName = "nsk.jdi.ObjectReference.getValues"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + log2("......getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeClass = (ReferenceType) classes.get(0); + + + Field field1 = null; + Value val1 = null; + List fields = null; + + String objName = "testObj"; + String obj1Name = "testObj1"; + + ObjectReference objRef = null; + + ReferenceType testedClass = null; + + + log2("......getting the mirror of tested getvalues003aTestClass obj : ObjectReference objRef"); + + field1 = debuggeeClass.fieldByName(objName); + val1 = debuggeeClass.getValue(field1); + objRef = (ObjectReference) val1; + + log2("......getting the mirror of tested getvalues003aTestClass : ReferenceType classRef"); + + classes = vm.classesByName(testedClass1Name); + testedClass = (ReferenceType) classes.get(0); + fields = testedClass.visibleFields(); + + + log2("......performing the check; IllegalArgumentException is expected"); + try { + Map vMap = objRef.getValues(fields); + log3("ERROR: no IllegalArgumentException"); + testExitCode = FAILED; + } catch ( IllegalArgumentException e ) { + log2(" IllegalArgumentException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003/TestDescription.java new file mode 100644 index 00000000000..30b88917f7d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/getValues/getvalues003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.getValues() + * complies with its spec: + * public Map getValues(List fields) + * Gets the value of multiple instance and/or static fields in this object. + * The Fields must be valid for this ObjectReference; that is, + * they must be from the mirrored object's class or a superclass of that class. + * Parameters: fields - a list of Field objects containing the requested values. + * Returns: a Map of the requested Field objects with their Value. + * Throws: IllegalArgumentException - + * if any field is not valid for this object's class. + * ObjectCollectedException - + * if this object has been garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The case for testing includes throwing IllegalArgumentException . + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.getValues.getvalues003; + * the debuggee program - nsk.jdi.ObjectReference.getValues.getvalues003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.getValues.getvalues003 + * nsk.jdi.ObjectReference.getValues.getvalues003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.getValues.getvalues003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003a.java new file mode 100644 index 00000000000..be643a6e3ed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/getValues/getvalues003a.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalues003 JDI test. + */ + +public class getvalues003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static getvalues003aTestClass testObj = new getvalues003aTestClass(); + static getvalues003aTestClass1 testObj1 = new getvalues003aTestClass1(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.hashCode()
    + * complies with its specification.
    + * The case for testing incliudes two ObjectReference objects
    + * beloning to the same VM.
    + *
    + * The test works as follows.
    + * Upon launch, a debuggee infroms a debugger of creating
    + * tested objects.
    + * The debuggee gets two ObjectReference objRef1 and objRef2
    + * mirroring the same object in the debuggee, and
    + * ObjectReference objRef3 mirroring another object.
    + * Then it checks up that
    + * - objRef1.hashCode() == objRef2.hashCode()
    + * - objRef1.hashCode() != objRef3.hashCode()
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/hashCode/hashcode001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.hashCode.hashcode001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.getValues.TestClass"; + + private String testedClass1Name = + "nsk.jdi.ObjectReference.getValues.TestClass1"; + + //String mName = "nsk.jdi.ObjectReference.hashCode"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + log2("......getting: List classes = vm.classesByName(debuggeeName); expected size == 1"); + classes = vm.classesByName(debuggeeName); + int size = classes.size(); + if (size != 1) { + log3("ERROR: classes.size() != 1 : " + size); + testExitCode = FAILED; + break ; + } + + log2(" getting ReferenceType and ClassType objects for debuggeeClass"); + ReferenceType debuggeeClass = (ReferenceType) classes.get(0); + + + Field field1 = null; + Value val1 = null; + List fields = null; + + String objName = "testObj"; + String obj1Name = "testObj1"; + + ObjectReference objRef1 = null; + ObjectReference objRef2 = null; + ObjectReference objRef3 = null; + + + log2("......getting first mirror of tested TestClass obj : ObjectReference objRef1"); + + field1 = debuggeeClass.fieldByName(objName); + val1 = debuggeeClass.getValue(field1); + objRef1 = (ObjectReference) val1; + + + log2("......getting second mirror of tested TestClass obj : ObjectReference objRef2"); + + objRef2 = (ObjectReference) val1; + + + log2("......getting amirror of tested TestClass1 obj : ObjectReference objRef3"); + + field1 = debuggeeClass.fieldByName(obj1Name); + val1 = debuggeeClass.getValue(field1); + objRef3 = (ObjectReference) val1; + + + log2("......testing equality of hashCodes of objRef1 and objRef2"); + if (objRef1.hashCode() != objRef2.hashCode()) { + log3("ERROR: objRef1.hashCode() is not equal to objRef2.hashCode()"); + testExitCode = FAILED; + } + + log2("......testing inequality of hashCodes of objRef1 and objRef3"); + if (objRef1.hashCode() == objRef3.hashCode()) { + log3("ERROR: objRef1.hashCode() is equal to objRef3.hashCode()"); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..35b554bfad8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this ObjectReference. + * Returns: the integer hash code + * Overrides: hashCode in class java.lang.Object + * The case for testing includes objects beloning to the same VM. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.hashCode.hashcode001; + * the debuggee program - nsk.jdi.ObjectReference.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.hashCode.hashcode001 + * nsk.jdi.ObjectReference.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001a.java new file mode 100644 index 00000000000..302d020ed48 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/hashCode/hashcode001a.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the hashcode001 JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass testObj = new TestClass(); + static TestClass1 testObj1 = new TestClass1(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.invokeMethod()
    + * complies with its spec when invoked methods are of
    + * all primitive types and the void type.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger invokes debuggee's methods:
    + * boolean blValue();
    + * byte btValue();
    + * char chValue();
    + * double dbValue();
    + * float flValue();
    + * int inValue();
    + * long lnValue();
    + * short shValue();
    + * void vdValue();
    + * and checks up that returned Value objects are
    + * corresponding PrimitiveValue objects and
    + * a VoidValue object.
    + *
    + */ + +public class invokemethod001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/invokeMethod/invokemethod001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new invokemethod001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.invokeMethod.Threadinvokemethod001a"; + + //String mName = "nsk.jdi.ObjectReference.invokeMethod"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + ObjectReference threadObjRef = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + if (thread2 == null) { + log3("ERROR: didn't find thread '" + threadName + "'"); + expresult = returnCode1; + break label0; + } + + threadObjRef = thread2; + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + Value returnValue = null; + + String methodNamnes[] = {"blValue" , "btValue" , + "chValue" , "dbValue" , + "flValue" , "inValue" , + "lnValue" , "shValue" , + "vdValue" }; + + String types[] = { "BooleanValue", "ByteValue", "CharValue", + "DoubleValue", "FloatValue", "IntegerValue", + "LongValue", "ShortValue", "VoidValue" }; + + log2(" beginning of invoking methods"); + label: { + for (int i3 = 0; i3 <= 8; i3++) { + + log2(" checking up " + types[i3] + " method"); + + List invokeMethods = + testedclass.methodsByName(methodNamnes[i3]); + Method invokeMethod = (Method) invokeMethods.get(0); + + List argumentList = invokeMethods; + argumentList.clear(); + + try { + returnValue = + threadObjRef.invokeMethod(thread2, + invokeMethod, Collections.emptyList(), 0); + } catch ( Exception t ) { + log3("ERROR: Exception for classType.invokeMethod :" + t); + expresult = returnCode1; + continue; + } + + try { + switch (i3) { + + case 0: + BooleanValue blValue = (BooleanValue) returnValue; + break; + + case 1: + ByteValue btValue = (ByteValue) returnValue; + break; + + case 2: + CharValue chValue = (CharValue) returnValue; + break; + + case 3: + DoubleValue dbValue = (DoubleValue) returnValue; + break; + + case 4: + FloatValue flValue = (FloatValue) returnValue; + break; + + + case 5: + IntegerValue inValue = (IntegerValue) returnValue; + break; + + case 6: + LongValue lnValue = (LongValue) returnValue; + break; + + case 7: + ShortValue shValue = (ShortValue) returnValue; + break; + + case 8: + VoidValue vdValue = (VoidValue) returnValue; + break; + + default: log3("ERROR : switch (i3) executes 'default:'"); + expresult = returnCode1; + break label; + } + } catch ( ClassCastException e ) { + log3("ERROR : ClassCastException for: " + types[i3] + " 'returnValue'"); + expresult = returnCode1; + break label; + } // try + } // for + } // label: + + log2(" end of checks"); + log2(" resuming VirtualMachine"); + vm.resume(); + + } + vm.resume(); // for case if thread2 was not resumed because of error in a check + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001/TestDescription.java new file mode 100644 index 00000000000..590bff95904 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.invokeMethod() + * complies with its spec: + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.invokeMethod.invokemethod 00; + * the debuggee program - nsk.jdi.ObjectReference.invokeMethod.invokemethod 00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * #4737294 testbug: + * For a void method return value should be null. + * 4773425 TEST_BUG: invokemethod001 test failing on all platforms + * Previous changes of 4737294 bug fix are deleted. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod001 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001a.java new file mode 100644 index 00000000000..d0bca2b31d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod001a.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the invokemethod001 JDI test. + */ + +public class invokemethod001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ObjectReference.invokeMethod() + * properly throws IllegalArgumentException when + * debugger part of the test attempts to invoke several + * debuggee methods: + *
  • which are not members of an object's class + *
  • which are constructors or static intializers + *
  • with the size mismatch of an argument list. + */ +public class invokemethod002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod002t"; + + // tested debuggee methods and type/object reference numbers + static final int METH_NUM = 14; + static final String DEBUGGEE_METHODS[][] = { + {"", "0", "0"}, + {"", "0", "0"}, + {"", "1", "0"}, + {"", "1", "0"}, + {"byteMeth", "1", "0"}, + {"shortMeth", "1", "0"}, + {"intMeth", "1", "0"}, + {"longMeth", "1", "0"}, + {"floatMeth", "1", "0"}, + {"doubleMeth", "1", "0"}, + {"charMeth", "1", "0"}, + {"booleanMeth", "1", "0"}, + {"strMeth", "1", "0"}, + {"voidMeth", "1", "0"} + }; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod002tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 62; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = "invokemethod002tdummyCls"; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private ObjectReference[] objRef = new ObjectReference[2]; + private ReferenceType[] rType = new ReferenceType[2]; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod002t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + rType[0] = debuggee.classByName(DEBUGGEE_CLASS); // debuggee main class + +// Check the tested assersion + try { + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + findObjRef(DEBUGGEE_LOCALVAR); + rType[1] = objRef[1].referenceType(); // debuggee dummy class + + // provoke the IllegalArgumentException with the wrong methods + provokeException(Collections.emptyList(), true); + + // provoke the IllegalArgumentException with the wrong argument list + provokeException( + Collections.singletonList(vm.mirrorOf(9223372036854775807L)), + false); + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private void provokeException(List argList, boolean use3rdIndex) { + int objIndex; + + for (int i=0; i method + + invokemethod002t() {} // force javac to produce method + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod002t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + invokemethod002tDummyClass invokemethod002tdummyCls = new invokemethod002tDummyClass(); + + Thread.currentThread().setName(invokemethod002.DEBUGGEE_THRNAME); + + pipe.println(invokemethod002.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod002.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod002.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod002.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} + +// Dummy class used to provoke IllegalArgumentException in the debugger +class invokemethod002tDummyClass { + static {} // force javac to produce method + + invokemethod002tDummyClass() {} // force javac to produce method + + byte byteMeth() { + return 127; + } + + short shortMeth() { + return -32768; + } + + int intMeth() { + return 2147483647; + } + + long longMeth() { + return 9223372036854775807L; + } + + float floatMeth() { + return 5.1F; + } + + double doubleMeth() { + return 6.2D; + } + + char charMeth() { + return 'a'; + } + + boolean booleanMeth() { + return false; + } + + String strMeth() { + return "string method"; + } + + void voidMeth() {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003.java new file mode 100644 index 00000000000..366434f5c8d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003.java @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() + * properly throws IllegalArgumentException when + * debugger part of the test attempts to invoke several + * debuggee methods with the flag ObjectReference.INVOKE_NONVIRTUAL + * and these methods: + *
  • belong to an interface + *
  • are abstract ones + */ +public class invokemethod003 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod003t"; + + static final String DEBUGGEE_INTERFACE = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod003tDummyInterface"; + + static final String DEBUGGEE_ABSTRACTCLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod003tDummyAbstractCls"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod003tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 59; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod003tdummyCls"; + + // tested debuggee methods and type reference numbers + static final int METH_NUM = 20; + static final String DEBUGGEE_METHODS[][] = { + {"byteMeth", "1"}, + {"shortMeth", "1"}, + {"intMeth", "1"}, + {"longMeth", "1"}, + {"floatMeth", "1"}, + {"doubleMeth", "1"}, + {"charMeth", "1"}, + {"booleanMeth", "1"}, + {"strMeth", "1"}, + {"voidMeth", "1"}, + {"absByteMeth", "2"}, + {"absShortMeth", "2"}, + {"absIntMeth", "2"}, + {"absLongMeth", "2"}, + {"absFloatMeth", "2"}, + {"absDoubleMeth", "2"}, + {"absCharMeth", "2"}, + {"absBooleanMeth", "2"}, + {"absStrMeth", "2"}, + {"absVoidMeth", "2"} + }; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod003().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod003t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + ReferenceType[] rType = new ReferenceType[3]; + // debuggee main class + rType[0] = debuggee.classByName(DEBUGGEE_CLASS); + // debuggee dummy interface + rType[1] = debuggee.classByName(DEBUGGEE_INTERFACE); + // debuggee dummy abstract class + rType[2] = debuggee.classByName(DEBUGGEE_ABSTRACTCLASS); + +// Check the tested assersion + try { + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + ObjectReference objRef = findObjRef(DEBUGGEE_LOCALVAR); + + for (int i=0; iemptyList(), ObjectReference.INVOKE_NONVIRTUAL); + + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\" and the flag ObjectReference.INVOKE_NONVIRTUAL"); + tot_res = Consts.TEST_FAILED; + } catch (IllegalArgumentException ia) { + log.display("CHECK PASSED: caught expected " + ia); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ObjectReference.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected llegalArgumentException" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\" and the flag ObjectReference.INVOKE_NONVIRTUAL"); + tot_res = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private ObjectReference findObjRef(String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + + if (locVar == null) continue; + + // dummy debuggee class + return (ObjectReference)stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + BPreq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003/TestDescription.java new file mode 100644 index 00000000000..aa4929a277a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() properly throws + * IllegalArgumentException when debugger part of the test + * attempts to invoke several debuggee methods with the flag + * ObjectReference.INVOKE_NONVIRTUAL and these methods: + * - belong to an interface; + * - are abstract ones. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod003 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod003t + * + * @comment make sure invokemethod003t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod003t + * @compile -g:lines,source,vars ../invokemethod003t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003t.java new file mode 100644 index 00000000000..be465b61070 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod003t.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class invokemethod003t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod003t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + invokemethod003tDummyClass invokemethod003tdummyCls = new invokemethod003tDummyClass(); + + Thread.currentThread().setName(invokemethod003.DEBUGGEE_THRNAME); + + pipe.println(invokemethod003.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod003.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod003.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod003.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} + +// Dummy interface & abstract class used to provoke +// IllegalArgumentException in the debugger +interface invokemethod003tDummyInterface { + byte byteMeth(); + + short shortMeth(); + + int intMeth(); + + long longMeth(); + + float floatMeth(); + + double doubleMeth(); + + char charMeth(); + + boolean booleanMeth(); + + String strMeth(); + + void voidMeth(); +} + +abstract class invokemethod003tDummyAbstractCls { + abstract byte absByteMeth(); + + abstract short absShortMeth(); + + abstract int absIntMeth(); + + abstract long absLongMeth(); + + abstract float absFloatMeth(); + + abstract double absDoubleMeth(); + + abstract char absCharMeth(); + + abstract boolean absBooleanMeth(); + + abstract String absStrMeth(); + + abstract void absVoidMeth(); +} + +class invokemethod003tDummyClass extends invokemethod003tDummyAbstractCls implements invokemethod003tDummyInterface { + public byte byteMeth() { + return 127; + } + + public short shortMeth() { + return -32768; + } + + public int intMeth() { + return 2147483647; + } + + public long longMeth() { + return 9223372036854775807L; + } + + public float floatMeth() { + return 5.1F; + } + + public double doubleMeth() { + return 6.2D; + } + + public char charMeth() { + return 'a'; + } + + public boolean booleanMeth() { + return false; + } + + public String strMeth() { + return "string method"; + } + + public void voidMeth() {} + + byte absByteMeth() { + return 127; + } + + public short absShortMeth() { + return 32767; + } + + public int absIntMeth() { + return 2147483647; + } + + public long absLongMeth() { + return 9223372036854775807L; + } + + public float absFloatMeth() { + return 5.1F; + } + + public double absDoubleMeth() { + return 6.2D; + } + + public char absCharMeth() { + return 'a'; + } + + public boolean absBooleanMeth() { + return true; + } + + public String absStrMeth() { + return "string method"; + } + + public void absVoidMeth() {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004.java new file mode 100644 index 00000000000..0b815182252 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() + * properly throws IncompatibleThreadStateException when + * debugger part of the test attempts to invoke several + * debuggee methods when the debuggee thread has been suspended + * by the ThreadReference.suspend() instead of by an event. + */ +public class invokemethod004 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod004t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod004tThr"; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod004tdummyCls"; + + // tested debuggee methods and type reference numbers + static final int METH_NUM = 10; + static final String DEBUGGEE_METHODS[] = { + "byteMeth", + "shortMeth", + "intMeth", + "longMeth", + "floatMeth", + "doubleMeth", + "charMeth", + "booleanMeth", + "strMeth", + "voidMeth" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int ATTEMPTS = 5; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod004().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod004t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + thrRef.suspend(); + while(!thrRef.isSuspended()) { + num++; + if (num > ATTEMPTS) { + log.complain("TEST FAILED: unable to suspend debuggee thread"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + log.display("Waiting for debuggee thread suspension ..."); + try { + Thread.currentThread().sleep(1000); + } catch(InterruptedException ie) { + ie.printStackTrace(); + log.complain("TEST FAILED: caught: " + ie); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + } + +// Check the tested assersion + try { + ObjectReference objRef = findObjRef(DEBUGGEE_LOCALVAR); + ReferenceType rType = objRef.referenceType(); // debuggee dummy class + + for (int i=0; i methList = rType.methodsByName(DEBUGGEE_METHODS[i]); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHODS[i] + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + continue; + } + Method meth = methList.get(0); + + try { + log.display("\nTrying to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\" and the thread reference which has not been suspended by an event ..."); + + objRef.invokeMethod(thrRef, meth, Collections.emptyList(), 0); + + log.complain("TEST FAILED: expected IncompatibleThreadStateException was not thrown" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\" and the thread reference which has not been suspended by an event."); + tot_res = Consts.TEST_FAILED; + } catch (IncompatibleThreadStateException is) { + log.display("CHECK PASSED: caught expected " + is); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ObjectReference.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected IncompatibleThreadStateException" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\" and the thread reference which has not been suspended by an event."); + tot_res = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private ObjectReference findObjRef(String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) continue; + + // dummy debuggee class + return (ObjectReference)stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private int quitDebuggee() { + if (thrRef != null) { + if (thrRef.isSuspended()) + thrRef.resume(); + } + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004/TestDescription.java new file mode 100644 index 00000000000..174544fcd97 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() properly throws + * IncompatibleThreadStateException when debugger part of the test + * attempts to invoke several debuggee methods when the debuggee + * thread has been suspended by the ThreadReference.suspend() + * instead of by an event. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod004 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod004t + * + * @comment make sure invokemethod004t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod004t + * @compile -g:lines,source,vars ../invokemethod004t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004t.java new file mode 100644 index 00000000000..2e90c83caad --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod004t.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee class. + */ +public class invokemethod004t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod004t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + invokemethod004tDummyClass invokemethod004tdummyCls = new invokemethod004tDummyClass(); + Thread.currentThread().setName(invokemethod004.DEBUGGEE_THRNAME); + + pipe.println(invokemethod004.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(invokemethod004.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} + +// Dummy class used to provoke IncompatibleThreadStateException in the debugger +class invokemethod004tDummyClass { + byte byteMeth() { + return 127; + } + + short shortMeth() { + return -32768; + } + + int intMeth() { + return 2147483647; + } + + long longMeth() { + return 9223372036854775807L; + } + + float floatMeth() { + return 5.1F; + } + + double doubleMeth() { + return 6.2D; + } + + char charMeth() { + return 'a'; + } + + boolean booleanMeth() { + return false; + } + + String strMeth() { + return "string method"; + } + + void voidMeth() {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005.java new file mode 100644 index 00000000000..c6cb2c1aa88 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005.java @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() + * properly throws InvocationException when + * debugger part of the test invokes several debuggee methods + * which throw runtime ArithmeticException, + * NumberFormatException, IllegalMonitorStateException, + * own "Failure", and finally the Error instance. + */ +public class invokemethod005 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod005t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod005tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 58; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod005tdummyCls"; + + // tested debuggee methods and type reference numbers + static final int METH_NUM = 5; + static final String DEBUGGEE_METHODS[] = { + "arithmeticMeth", + "numberFormatMeth", + "illegalMonitorMeth", + "failureMeth", + "errorMeth" + }; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod005t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + ReferenceType[] rType = new ReferenceType[2]; + // debuggee main class + rType[0] = debuggee.classByName(DEBUGGEE_CLASS); + +// Check the tested assersion + try { + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + ObjectReference objRef = findObjRef(DEBUGGEE_LOCALVAR); + rType[1] = objRef.referenceType(); // debuggee dummy class + + for (int i=0; i methList = rType[1].methodsByName(DEBUGGEE_METHODS[i]); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHODS[i] + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + continue; + } + Method meth = methList.get(0); + + try { + log.display("\nTrying to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[1] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + + objRef.invokeMethod(thrRef, meth, Collections.emptyList(), 0); + + log.complain("TEST FAILED: expected InvocationException was not thrown" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[1] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } catch (InvocationException ie) { + log.display("CHECK PASSED: caught expected " + ie + + "\n\t" + ie.exception()); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ObjectReference.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected InvocationException" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[1] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private ObjectReference findObjRef(String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) continue; + + // dummy debuggee class + return (ObjectReference)stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + BPreq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005/TestDescription.java new file mode 100644 index 00000000000..1f5ea6f5b0c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() properly throws + * InvocationException when debugger part of the test + * invokes several debuggee methods which throw runtime + * ArithmeticException, NumberFormatException, + * IllegalMonitorStateException, own "Failure" exception, and + * finally the Error instance. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod005 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod005t + * + * @comment make sure invokemethod005t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod005t + * @compile -g:lines,source,vars ../invokemethod005t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005t.java new file mode 100644 index 00000000000..4e512eaecc5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod005t.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class invokemethod005t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod005t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + invokemethod005tDummyClass invokemethod005tdummyCls = new invokemethod005tDummyClass(); + Thread.currentThread().setName(invokemethod005.DEBUGGEE_THRNAME); + + pipe.println(invokemethod005.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod005.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod005.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod005.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} + +// Dummy class used to provoke InvocationException in the debugger +class invokemethod005tDummyClass { + // provoke runtime ArithmeticException + boolean arithmeticMeth() { + int i = 10 / Integer.parseInt("0"); + return true; + } + + // provoke runtime NumberFormatException + int numberFormatMeth() { + int i = Integer.parseInt("oops!"); + return 2147483647; + } + + // provoke runtime IllegalMonitorStateException + long illegalMonitorMeth() { + Object obj = new Object(); + obj.notify(); + return 9223372036854775807L; + } + + // throw own runtime exception Failure + void failureMeth() { + throw new Failure("Catch me!"); + } + + // throw error exception + void errorMeth() { + throw new Error("Throw Error!"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006.java new file mode 100644 index 00000000000..90c324a99ea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006.java @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() + * properly throws ClassNotLoadedException when + * a debugger part of the test invokes several debuggee methods + * with arguments which reference types have not been loaded + * through the appropriate class loader. + */ +public class invokemethod006 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod006t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod006tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 58; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod006tdummyCls"; + + // tested debuggee methods, fields and reference types + static final int METH_NUM = 2; + static final String DEBUGGEE_METHODS[][] = { + {"dummyMeth", "nsk.jdi.ObjectReference.invokeMethod.invokemethod006tDummyType", + "Lnsk/jdi/ObjectReference/invokeMethod/invokemethod006tDummyType;"}, + {"finDummyMeth", "nsk.jdi.ObjectReference.invokeMethod.invokemethod006tFinDummyType", + "Lnsk/jdi/ObjectReference/invokeMethod/invokemethod006tFinDummyType;"} + }; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod006().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod006t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + ReferenceType[] rType = new ReferenceType[2]; + // debuggee main class + rType[0] = debuggee.classByName(DEBUGGEE_CLASS); + +// Check the tested assersion + try { + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + ObjectReference objRef = findObjRef(DEBUGGEE_LOCALVAR); + rType[1] = objRef.referenceType(); // debuggee dummy class + + for (int i=0; i methList = rType[1].methodsByName(DEBUGGEE_METHODS[i][0]); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHODS[i][0] + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + continue; + } + Method meth = methList.get(0); + LinkedList argList = new LinkedList(); + argList.add(MockReferenceType.createObjectReference(objRef.virtualMachine(), + DEBUGGEE_METHODS[i][2], DEBUGGEE_METHODS[i][1])); + + try { + log.display("\nTrying to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[1] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + + objRef.invokeMethod(thrRef, meth, argList, 0); + + // Make sure that the reference type is not loaded by the debuggee VM + if ((debuggee.classByName(DEBUGGEE_METHODS[i][2])) != null) { + log.display("Skipping the check: the tested reference type\n\t\"" + + DEBUGGEE_METHODS[i][1] + + "\"\n\twas loaded by the debuggee VM, unable to test an assertion"); + continue; + } + else { + log.complain("TEST FAILED: expected ClassNotLoadedException was not thrown" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[1] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } + } catch (ClassNotLoadedException ce) { + log.display("CHECK PASSED: caught expected " + ce + + "\n\t" + ce.className()); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ObjectReference.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected ClassNotLoadedException" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[1] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private ObjectReference findObjRef(String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) continue; + // dummy debuggee class + return (ObjectReference)stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + BPreq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006/TestDescription.java new file mode 100644 index 00000000000..a5fab53e40e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod006. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-4698670 + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() properly throws + * ClassNotLoadedException when a debugger part of the test + * invokes several debuggee methods with arguments which + * reference types have not been loaded through the appropriate + * class loader. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod006 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod006t + * + * @comment make sure invokemethod006t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod006t + * @compile -g:lines,source,vars ../invokemethod006t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006t.java new file mode 100644 index 00000000000..625f6ead77c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod006t.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class invokemethod006t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod006t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + invokemethod006tDummyClass invokemethod006tdummyCls = new invokemethod006tDummyClass(); + Thread.currentThread().setName(invokemethod006.DEBUGGEE_THRNAME); + + pipe.println(invokemethod006.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod006.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod006.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod006.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} + +// Dummy reference types used to provoke ClassNotLoadedException +// in the debugger +class invokemethod006tDummyType {} +final class invokemethod006tFinDummyType {} + +// Dummy class used to provoke ClassNotLoadedException +// in the debugger +class invokemethod006tDummyClass { + + void dummyMeth(invokemethod006tDummyType dummyT) { + System.err.println("the method \"dummyMeth\" was invoked!"); + } + + long finDummyMeth(invokemethod006tFinDummyType finDummyT) { + System.err.println("the method \"finDummyMeth\" was invoked!"); + return 9223372036854775807L; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007.java new file mode 100644 index 00000000000..327c69d82d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() + * properly throws InvalidTypeException when + * a debugger part of the test invokes several debuggee methods + * with different kinds of arguments which are not assignment + * compatible with the argument type and not convertible without + * loss of information as well. + */ +public class invokemethod007 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod007t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod007tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 58; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod007tdummyCls"; + + // tested debuggee methods and fields used only to obtian their values + static final int METH_NUM = 19; + static final String DEBUGGEE_METHODS[][] = { + {"byteMeth", "sStrFld"}, + {"shortMeth", "intFld"}, + {"intMeth", "sLongFld"}, + {"longMeth", "floatFld"}, + {"floatMeth", "sDoubleFld"}, + {"doubleMeth", "sBooleanFld"}, + {"charMeth", "sStrFld"}, + {"booleanMeth", "sByteFld"}, + {"strMeth", "sCharFld"}, + {"dummyTMeth", "sByteFld"}, + {"dummyTMeth", "sShortFld"}, + {"dummyTMeth", "intFld"}, + {"dummyTMeth", "sLongFld"}, + {"dummyTMeth", "floatFld"}, + {"dummyTMeth", "sDoubleFld"}, + {"dummyTMeth", "sCharFld"}, + {"dummyTMeth", "sBooleanFld"}, + {"dummyTMeth", "sStrFld"}, + {"dummyTMeth", "wrongDummyType"} + }; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod007().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod007t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + ReferenceType[] rType = new ReferenceType[2]; + // debuggee main class + rType[0] = debuggee.classByName(DEBUGGEE_CLASS); + +// Check the tested assersion + try { + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + ObjectReference objRef = findObjRef(DEBUGGEE_LOCALVAR); + rType[1] = objRef.referenceType(); // debuggee dummy class + + for (int i=0; i argList = new LinkedList(); + argList.add(objRef.getValue( + rType[1].fieldByName(DEBUGGEE_METHODS[i][1]))); + + try { + log.display("\nTrying to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[1] + + "\"\n\twith the arguments: " + + rType[1].fieldByName(DEBUGGEE_METHODS[i][1]) + " " + argList + + "\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + + objRef.invokeMethod(thrRef, meth, argList, 0); + + log.complain("TEST FAILED: expected InvalidTypeException was not thrown" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \""+ rType[1].fieldByName(DEBUGGEE_METHODS[i][1]) + " " + rType[1] + + "\"\n\twith the arguments: " + + rType[1].fieldByName(DEBUGGEE_METHODS[i][1]) + " " + argList + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } catch (InvalidTypeException ie) { + log.display("CHECK PASSED: caught expected " + ie); + } catch (Exception ee) { + // Make sure that the reference type is really loaded by the debuggee VM + if ((debuggee.classByName(DEBUGGEE_METHODS[i][1])) == null) { + log.display("Skipping the check: the tested reference type\n\t\"" + + DEBUGGEE_METHODS[i][2] + + "\"\n\twas not loaded by the debuggee VM, unable to test an assertion"); + continue; + } + else { + ee.printStackTrace(); + log.complain("TEST FAILED: ObjectReference.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected InvalidTypeException" + + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[1] + + "\"\n\twith the arguments: " + + rType[1].fieldByName(DEBUGGEE_METHODS[i][1]) + " " + argList + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private ObjectReference findObjRef(String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) continue; + + // dummy debuggee class + return (ObjectReference)stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + BPreq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007/TestDescription.java new file mode 100644 index 00000000000..e1b96d9b18f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod007. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ObjectReference.invokeMethod() properly throws + * InvalidTypeException when a debugger part of the test + * invokes several debuggee methods with different kinds of + * arguments which are not assignment compatible with the argument + * type and not convertible without loss of information as well. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod007 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod007t + * + * @comment make sure invokemethod007t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod007t + * @compile -g:lines,source,vars ../invokemethod007t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007t.java new file mode 100644 index 00000000000..1e249de4083 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod007t.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class invokemethod007t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod007t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + invokemethod007tDummyClass invokemethod007tdummyCls = new invokemethod007tDummyClass(); + Thread.currentThread().setName(invokemethod007.DEBUGGEE_THRNAME); + + pipe.println(invokemethod007.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod007.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod007.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod007.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} + +// Dummy reference types used to provoke InvalidTypeException +// in the debugger +class invokemethod007tDummyType {} +class invokemethod007tWrongDummyType {} + +// Dummy class used to provoke InvalidTypeException +// in the debugger +class invokemethod007tDummyClass { + // dummy fields used to obtain their values for method invocation + static byte sByteFld = 127; + static short sShortFld = -32768; + int intFld = 2147483647; + static long sLongFld = 9223372036854775807L; + float floatFld = 5.1F; + static double sDoubleFld = 6.2D; + static char sCharFld = 'a'; + static boolean sBooleanFld = true; + static String sStrFld = "static field"; + static invokemethod007tDummyType dummyType = new invokemethod007tDummyType(); + static invokemethod007tWrongDummyType wrongDummyType = new invokemethod007tWrongDummyType(); + + byte byteMeth(byte b) { + System.err.println("the method \"byteMeth\" was invoked!"); + return b; + } + + short shortMeth(short sh) { + System.err.println("the method \"shortMeth\" was invoked!"); + return sh; + } + + int intMeth(int i) { + System.err.println("the method \"intMeth\" was invoked!"); + return i; + } + + long longMeth(long l) { + System.err.println("the method \"longMeth\" was invoked!"); + return l; + } + + float floatMeth(float f) { + System.err.println("the method \"floatMeth\" was invoked!"); + return f; + } + + double doubleMeth(double d) { + System.err.println("the method \"doubleMeth\" was invoked!"); + return d; + } + + char charMeth(char c) { + System.err.println("the method \"charMeth\" was invoked!"); + return c; + } + + boolean booleanMeth(boolean bool) { + System.err.println("the method \"booleanMeth\" was invoked!"); + return bool; + } + + String strMeth(String str) { + System.err.println("the method \"strMeth\" was invoked!"); + return str; + } + + void dummyTMeth(invokemethod007tDummyType dummyT) { + System.err.println("the method \"dummyTMeth\" was invoked!"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008.java new file mode 100644 index 00000000000..3e0236c4f56 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008.java @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that virtual and non-virtual method invocation + * will be performed properly through the JDI method + * com.sun.jdi.ObjectReference.invokeMethod().
    + * A debugger part of the test invokes several debuggee methods, + * overriden in an object reference class, but obtained from + * a reference type of its superclass. The debugger calls the + * JDI method without and with the flag ObjectReference.INVOKE_NONVIRTUAL + * sequentially. It is expected, that methods from the object reference + * class instead of from the superclass will be invoked without + * the flag INVOKE_NONVIRTUAL and vise versa otherwise. + */ +public class invokemethod008 { + // debuggee classes + static final String DEBUGGEE_CLASSES[] = { + "nsk.jdi.ObjectReference.invokeMethod.invokemethod008t", + "nsk.jdi.ObjectReference.invokeMethod.invokemethod008tDummySuperClass", + "nsk.jdi.ObjectReference.invokeMethod.invokemethod008tDummySuperSuperClass" + }; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod008tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 69; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod008tdummyCls"; + + // tested debuggee methods to be invoked, reference type numbers + // and expected return values + static final int METH_NUM = 4; + static final String DEBUGGEE_METHODS[][] = { + {"longProtMeth", "1", "9223372036854775806"}, + {"longMeth", "1", "9223372036854775806"}, + {"longProtMeth", "2", "9223372036854775805"}, + {"longMeth", "2", "9223372036854775805"} + }; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod008().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASSES[0]); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod008t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + ReferenceType[] rType = new ReferenceType[3]; + // reference types of debuggee main & dummy classes + rType[0] = debuggee.classByName(DEBUGGEE_CLASSES[0]); + rType[1] = debuggee.classByName(DEBUGGEE_CLASSES[1]); + rType[2] = debuggee.classByName(DEBUGGEE_CLASSES[2]); + +// Check the tested assersion + try { + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + ObjectReference objRef = findObjRef(DEBUGGEE_LOCALVAR); + + for (int i=0; i argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + try { + log.display("\n\n1) Trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\twith the arguments: " + argList + + " and without the flag ObjectReference.INVOKE_NONVIRTUAL" + + "\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + + LongValue retVal = (LongValue) + objRef.invokeMethod(thrRef, meth, argList, 0); + if (retVal.value() == 9223372036854775807L) { + log.display("CHECK PASSED: the invoked method returns: " + retVal.value() + + " as expected"); + } + else { + log.complain("TEST FAILED: wrong virtual invocation: the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\tinvoked with the arguments: " + argList + + " and without the flag ObjectReference.INVOKE_NONVIRTUAL" + + "\"\n\tusing the debuggee object reference \"" + objRef + + "\" returned: " + retVal.value() + + " instead of 9223372036854775807L as expected"); + tot_res = Consts.TEST_FAILED; + } + + log.display("\n2) Trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\twith the arguments: " + argList + + " and with the flag ObjectReference.INVOKE_NONVIRTUAL" + + "\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + LongValue retVal2 = (LongValue) + objRef.invokeMethod(thrRef, meth, argList, + ObjectReference.INVOKE_NONVIRTUAL); + if (retVal2.value() != expValue) { + log.complain("TEST FAILED: wrong non-virtual invocation: the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\tinvoked with the arguments: " + argList + + " and with the flag ObjectReference.INVOKE_NONVIRTUAL" + + "\"\n\tusing the debuggee object reference \"" + objRef + + "\",\n\treturns: " + retVal2.value() + + " instead of " + expValue + " as expected"); + tot_res = Consts.TEST_FAILED; + } + else + log.display("CHECK PASSED: the method invoked with ObjectReference.INVOKE_NONVIRTUAL returns: " + + retVal2.value() + " as expected"); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ObjectReference.invokeMethod(): caught unexpected " + + ee + "\n\twhen attempted to invoke the method \"" + + meth.name() + " " + meth.signature() + + "\"\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\twith the arguments: " + argList + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private ObjectReference findObjRef(String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) continue; + + // dummy debuggee class + return (ObjectReference)stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008/TestDescription.java new file mode 100644 index 00000000000..3767883a5ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod008. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test checks that virtual and non-virtual method invocation + * will be performed properly through the JDI method: + * com.sun.jdi.ObjectReference.invokeMethod(). + * A debugger part of the test invokes several debuggee methods, + * overriden in an object reference class, but obtained from + * a reference type of its superclass. The debugger calls the + * JDI method without and with the flag ObjectReference.INVOKE_NONVIRTUAL + * sequentially. It is expected, that methods from the object reference + * class instead of from the superclass will be invoked without + * the flag INVOKE_NONVIRTUAL and vise versa otherwise. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod008 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod008t + * + * @comment make sure invokemethod008t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod008t + * @compile -g:lines,source,vars ../invokemethod008t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008t.java new file mode 100644 index 00000000000..9ccff1fa714 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod008t.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class invokemethod008t { + static Log log; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod008t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + log = argHandler.createDebugeeLog(); + + // force debuggee VM to load dummy classes + invokemethod008tDummyClass invokemethod008tdummyCls = + new invokemethod008tDummyClass(); + invokemethod008tDummySuperClass invokemethod008tdummySCls = + new invokemethod008tDummySuperClass(); + invokemethod008tDummySuperSuperClass invokemethod008tdummySSCls = + new invokemethod008tDummySuperSuperClass(); + + Thread.currentThread().setName(invokemethod008.DEBUGGEE_THRNAME); + + pipe.println(invokemethod008.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod008.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod008.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod008.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} + +// Dummy super super class used to check the flag +// ObjectReference.INVOKE_NONVIRTUAL in the debugger +class invokemethod008tDummySuperSuperClass { + protected long longProtMeth(long l) { + invokemethod008t.log.display("invokemethod008tDummySuperSuperClass: longProtMeth invoked"); + return (l - 2); + } + + long longMeth(long l) { + invokemethod008t.log.display("invokemethod008tDummySuperSuperClass: longMeth invoked"); + return (l - 2); + } +} + +// Dummy super class used to check the flag +// ObjectReference.INVOKE_NONVIRTUAL in the debugger +class invokemethod008tDummySuperClass extends invokemethod008tDummySuperSuperClass { + protected long longProtMeth(long l) { + invokemethod008t.log.display("invokemethod008tDummySuperClass: longProtMeth invoked"); + return (l - 1); + } + + long longMeth(long l) { + invokemethod008t.log.display("invokemethod008tDummySuperClass: longMeth invoked"); + return (l - 1); + } +} + +// Dummy class used to check the flag +// ObjectReference.INVOKE_NONVIRTUAL in the debugger +class invokemethod008tDummyClass extends invokemethod008tDummySuperClass { + protected long longProtMeth(long l) { + invokemethod008t.log.display("invokemethod008tDummyClass: longProtMeth invoked"); + return l; + } + + long longMeth(long l) { + invokemethod008t.log.display("invokemethod008tDummyClass: longMeth invoked"); + return l; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod009.java new file mode 100644 index 00000000000..ca4394d3682 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod009.java @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that virtual and non-virtual method invocation + * will be performed properly through the JDI method + * com.sun.jdi.ObjectReference.invokeMethod().
    + * A debugger part of the test invokes several debuggee methods, + * overriden in an object reference class, but obtained from + * a reference type of its superclass. The debugger calls the + * JDI method with and without the flag ObjectReference.INVOKE_NONVIRTUAL + * sequentially. It is expected, that methods from the superclass + * instead of from the object reference class will be invoked with + * the flag and vise versa otherwise. + */ +public class invokemethod009 { + // debuggee classes + static final String DEBUGGEE_CLASSES[] = { + "nsk.jdi.ObjectReference.invokeMethod.invokemethod009t", + "nsk.jdi.ObjectReference.invokeMethod.invokemethod009tDummySuperClass", + "nsk.jdi.ObjectReference.invokeMethod.invokemethod009tDummySuperSuperClass" + }; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod009tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 69; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod009tdummyCls"; + + // tested debuggee methods to be invoked, reference type numbers + // and expected return values + static final int METH_NUM = 4; + static final String DEBUGGEE_METHODS[][] = { + {"longProtMeth", "1", "9223372036854775806"}, + {"longMeth", "1", "9223372036854775806"}, + {"longProtMeth", "2", "9223372036854775805"}, + {"longMeth", "2", "9223372036854775805"} + }; + + static final int TIMEOUT_DELTA = 1000; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private ThreadReference thrRef = null; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod009().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASSES[0]); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod009t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + ReferenceType[] rType = new ReferenceType[3]; + // reference types of debuggee main & dummy classes + rType[0] = debuggee.classByName(DEBUGGEE_CLASSES[0]); + rType[1] = debuggee.classByName(DEBUGGEE_CLASSES[1]); + rType[2] = debuggee.classByName(DEBUGGEE_CLASSES[2]); + +// Check the tested assersion + try { + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + ObjectReference objRef = findObjRef(DEBUGGEE_LOCALVAR); + LinkedList argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + for (int i=0; i + * com.sun.jdi.ObjectReference.invokeMethod(). + * The following assertions are verified: + *
  • by default, all threads in the target VM are resumed while + * the method is being invoked + *
  • when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation + *
  • only the specified thread will be resumed with the + * INVOKE_SINGLE_THREADED + *
  • upon completion of a single threaded invoke, the invoking + * thread will be suspended once again.
    + * + * A debuggee part of the test starts several threads. Then debugger + * calls the JDI method without and with the flag + * ObjectReference.INVOKE_SINGLE_THREADED sequentially. During + * the invocations and after them the threads state is expected to be as + * described above. + */ +public class invokemethod010 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod010t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 71; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod010tdummyCls"; + + // debuggee fields used to operate on an invoked method + static final String DEBUGGEE_FIELDS[] = { + "doExit", "isInvoked" + }; + + // debuggee thread names to be check + static final int THRDS_NUM = 12; + static final String DEBUGGEE_THRDS[] = { + "invokemethod010tThr", "invokemethod010tThr1", "invokemethod010tThr2", + "invokemethod010tThr3", "invokemethod010tThr4", "invokemethod010tThr5", + "invokemethod010tThr6", "invokemethod010tThr7", "invokemethod010tThr8", + "invokemethod010tThr9", "invokemethod010tThr10", "invokemethod010tThr11" + }; + + // debuggee method to be invoke + static final String DEBUGGEE_METHOD = + "longMeth"; + + static final int DELAY = 400; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod010().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + ObjectReference objRef = null; + Field fldToExit = null; + BooleanValue val = null; + InvokingThread invThr = null; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod010t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[THRDS_NUM]; + for (int i=0; i argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + for (int i=1; i<=2; i++) { + switch(i) { + case 1: // invocation with all threads resumption + invThr = new InvokingThread(objRef, thrRef[0], + meth, argList, 0); + break; + case 2: // the single threaded invocation + invThr = new InvokingThread(objRef, thrRef[0], meth, + argList, ObjectReference.INVOKE_SINGLE_THREADED); + break; + } + invThr.setDaemon(true); + invThr.start(); + + log.display("Waiting for debuggee method invocation ..."); + int tryOns = 0; + int attempts = (argHandler.getWaitTime() * 60000) / DELAY; + + do { + if (tryOns > attempts) + throw new Failure("unable to continue testing after " + + attempts + + " attempts: debuggee method is not invoked yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + val = (BooleanValue) + objRef.getValue(fldToCheck); + tryOns++; + } while (!val.value()); + + // check threads during method invocation + checkThreads(thrRef, i); + + objRef.setValue(fldToExit, vm.mirrorOf(true)); + + invThr.join(argHandler.getWaitTime()*60000); + log.display("Thread \"" + invThr.getName() + "\" done"); + + // check threads status after method invocation + checkThreads(thrRef, 0); + } + } catch (Exception e) { + e.printStackTrace(); + // force an method to exit if it has been invoked + if (objRef != null && fldToExit != null) { + try { + objRef.setValue(fldToExit, vm.mirrorOf(true)); + } catch(Exception ee) { + ee.printStackTrace(); + } + } + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private void checkThreads(ThreadReference thrRef[], int state) { + switch (state) { + case 0: + log.display("\n\nVerifying threads status after method invocation:"); + break; + case 1: + log.display("\n\nVerifying invocation with all threads resumption:"); + break; + case 2: + log.display("\n\nVerifying the single threaded invocation (INVOKE_SINGLE_THREADED):"); + break; + } + + // check an invoking debuggee thread + if (thrRef[0].isSuspended()) { + if (state == 0) { // after invocation + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis suspended again after invocation as expected"); + } else { + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + "\n\tis still suspended"); + tot_res = Consts.TEST_FAILED; + } + } else { + if (state == 0) { // after invocation + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + + "\n\tis not suspended again after the invocation"); + tot_res = Consts.TEST_FAILED; + } else { + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis resumed as expected"); + } + } + // check other debuggee threads + for (int i=1; i argList; + int bitOpts; + + InvokingThread(ObjectReference objRef, ThreadReference thrRef, Method meth, LinkedList argList, int bitOpts) { + this.objRef = objRef; + this.thrRef = thrRef; + this.meth = meth; + this.argList = argList; + this.bitOpts = bitOpts; + super.setName("InvokingThread"); + } + + public void run() { + try { + log.display("\nInvokingThread: trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\twith the arguments: " + argList + + "\"\n\tand " + + new String((bitOpts==ObjectReference.INVOKE_SINGLE_THREADED)? "with" : "without") + + " the flag ObjectReference.INVOKE_SINGLE_THREADED\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + + LongValue retVal = (LongValue) + objRef.invokeMethod(thrRef, meth, argList, bitOpts); + log.display("InvokingThread: the method returned " + retVal); + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + log.display("InvokingThread: exiting"); + } + } +///////////////////////////////////////////////////////////////////////////// +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010/TestDescription.java new file mode 100644 index 00000000000..6bad2838d67 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod010. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that invocation with all threads resumption + * and the single threaded one will be performed properly through + * the JDI method: + * com.sun.jdi.ObjectReference.invokeMethod(). + * The following assertions are verified: + * - by default, all threads in the target VM are resumed while + * the method is being invoked; + * - when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation; + * - only the specified thread will be resumed with the + * INVOKE_SINGLE_THREADED; + * - upon completion of a single threaded invoke, the invoking + * thread will be suspended once again. + * A debuggee part of the test starts several threads. Then debugger + * calls the JDI method without and with the flag + * ObjectReference.INVOKE_SINGLE_THREADED sequentially. During + * the invocations and after them the threads state is expected to be as + * described above. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod010 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod010t + * + * @comment make sure invokemethod010t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod010t + * @compile -g:lines,source,vars ../invokemethod010t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod010 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010t.java new file mode 100644 index 00000000000..2dae569f1fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod010t.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a main debuggee class. + */ +public class invokemethod010t { + static Log log; + private invokemethod010Thr thrs[] = + new invokemethod010Thr[invokemethod010.THRDS_NUM-1]; + private IOPipe pipe; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod010t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + invokemethod010tDummyClass invokemethod010tdummyCls = + new invokemethod010tDummyClass(); + + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(invokemethod010.DEBUGGEE_THRDS[0]); + // Start several dummy threads with given names + startThreads(); + + // Now the debuggee is ready for testing + pipe.println(invokemethod010.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod010.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod010.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod010.COMMAND_QUIT)) { + killThreads(argHandler.getWaitTime()*60000); + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + private void startThreads() { + Object readyObj = new Object(); + + for (int i=0; i < invokemethod010.THRDS_NUM-1; i++) { + thrs[i] = new invokemethod010Thr(readyObj, + invokemethod010.DEBUGGEE_THRDS[i+1]); + thrs[i].setDaemon(true); + log.display("Debuggee: starting thread #" + + i + " \"" + thrs[i].getName() + "\" ..."); + synchronized(readyObj) { + thrs[i].start(); + try { + readyObj.wait(); // wait for the thread's readiness + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: waiting for the thread " + + thrs[i].toString() + " start: caught " + e); + pipe.println("failed"); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + } + log.display("Debuggee: the thread #" + + i + " \"" + thrs[i].getName() + "\" started"); + } + } + + private void killThreads(int waitTime) { + for (int i=0; i < invokemethod010.THRDS_NUM-1 ; i++) { + thrs[i].doExit = true; + try { + thrs[i].join(waitTime); + log.display("Debuggee: thread #" + + i + " \"" + thrs[i].getName() + "\" done"); + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: joining the thread #" + + i + " \"" + thrs[i].getName() + "\": caught " + e); + } + } + } + + /** + * This is an auxiliary thread class used to check the flag + * ObjectReference.INVOKE_SINGLE_THREADED in the debugger. + */ + class invokemethod010Thr extends Thread { + volatile boolean doExit = false; + private Object readyObj; + + invokemethod010Thr(Object readyObj, String name) { + super(name); + this.readyObj = readyObj; + } + + public void run() { + Thread thr = Thread.currentThread(); + Object waitObj = new Object(); + + synchronized(readyObj) { + readyObj.notify(); // notify the main thread + } + log.display("Debuggee thread \"" + + thr.getName() + "\": going to loop"); + while(!doExit) { + int i = 0; + i++; i--; + + // reliable analogue of Thread.yield() + synchronized(waitObj) { + try { + waitObj.wait(30); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + log.complain("TEST FAILURE: Debuggee thread \"" + + thr.getName() + + "\" interrupted while sleeping:\n\t" + e); + break; + } + } + } + log.display("Debuggee thread \"" + + thr.getName() + "\" exiting ..."); + } + } +///////////////////////////////////////////////////////////////////////////// + +} + +/** + * Dummy class used to check the flag ObjectReference.INVOKE_SINGLE_THREADED + * in the debugger. + */ +class invokemethod010tDummyClass { + // used by the debugger to let the invoked method return + volatile boolean doExit = false; + // indicator that the method has been really invoked + volatile boolean isInvoked = false; + + long longMeth(long l) throws InterruptedException { + invokemethod010t.log.display("invokemethod010tDummyClass: longMeth: going to loop"); + isInvoked = true; + while(!doExit) { + l--; l++; + Thread.currentThread().sleep(400); + } + invokemethod010t.log.display("invokemethod010tDummyClass: longMeth: exiting"); + isInvoked = false; + doExit = false; + return l; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011.java new file mode 100644 index 00000000000..090546a2226 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011.java @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that invocation with all threads resumption + * and the single threaded one will be performed properly through + * the JDI method
    + * com.sun.jdi.ObjectReference.invokeMethod(). + * The following assertions are verified: + *
  • by default, all threads in the target VM are resumed while + * the method is being invoked + *
  • when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation + *
  • only the specified thread will be resumed with the + * INVOKE_SINGLE_THREADED + *
  • upon completion of a single threaded invoke, the invoking + * thread will be suspended once again.
    + * + * A debuggee part of the test starts several threads. Then debugger + * calls the JDI method with and without the flag + * ObjectReference.INVOKE_SINGLE_THREADED sequentially. During + * the invocation and after it the threads state is expected to be as + * described above. + */ +public class invokemethod011 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod011t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 71; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod011tdummyCls"; + + // debuggee fields used to operate on an invoked method + static final String DEBUGGEE_FIELDS[] = { + "doExit", "isInvoked" + }; + + // debuggee thread names to be check + static final int THRDS_NUM = 12; + static final String DEBUGGEE_THRDS[] = { + "invokemethod011tThr", "invokemethod011tThr1", "invokemethod011tThr2", + "invokemethod011tThr3", "invokemethod011tThr4", "invokemethod011tThr5", + "invokemethod011tThr6", "invokemethod011tThr7", "invokemethod011tThr8", + "invokemethod011tThr9", "invokemethod011tThr10", "invokemethod011tThr11" + }; + + // debuggee method to be invoke + static final String DEBUGGEE_METHOD = + "longMeth"; + + static final int DELAY = 400; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod011().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + ObjectReference objRef = null; + Field fldToExit = null; + BooleanValue val = null; + InvokingThread invThr = null; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod011t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[THRDS_NUM]; + for (int i=0; i methList = rType[1].methodsByName(DEBUGGEE_METHOD); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHOD + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + Method meth = methList.get(0); + LinkedList argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + for (int i=2; i>=1; i--) { + switch(i) { + case 1: // invocation with all threads resumption + invThr = new InvokingThread(objRef, thrRef[0], + meth, argList, 0); + break; + case 2: // the single threaded invocation + invThr = new InvokingThread(objRef, thrRef[0], meth, + argList, ObjectReference.INVOKE_SINGLE_THREADED); + break; + } + invThr.setDaemon(true); + invThr.start(); + + log.display("Waiting for debuggee method invocation ..."); + int tryOns = 0; + int attempts = (argHandler.getWaitTime() * 60000) / DELAY; + + do { + if (tryOns > attempts) + throw new Failure("unable to continue testing after " + + attempts + + " attempts: debuggee method is not invoked yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + val = (BooleanValue) + objRef.getValue(fldToCheck); + tryOns++; + } while (!val.value()); + + // check threads during method invocation + checkThreads(thrRef, i); + + objRef.setValue(fldToExit, vm.mirrorOf(true)); + + invThr.join(argHandler.getWaitTime()*60000); + log.display("Thread \"" + invThr.getName() + "\" done"); + + // check threads status after method invocation + checkThreads(thrRef, 0); + } + } catch (Exception e) { + e.printStackTrace(); + // force an method to exit if it has been invoked + if (objRef != null && fldToExit != null) { + try { + objRef.setValue(fldToExit, vm.mirrorOf(true)); + } catch(Exception ee) { + ee.printStackTrace(); + } + } + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private void checkThreads(ThreadReference thrRef[], int state) { + switch (state) { + case 0: + log.display("\n\nVerifying threads status after the method invocation:"); + break; + case 1: + log.display("\n\nVerifying invocation with all threads resumption:"); + break; + case 2: + log.display("\n\nVerifying the single threaded invocation (INVOKE_SINGLE_THREADED):"); + break; + } + + // check an invoking debuggee thread + if (thrRef[0].isSuspended()) { + if (state == 0) { // after invocation + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis suspended again after the invocation as expected"); + } else { + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + "\n\tis still suspended"); + tot_res = Consts.TEST_FAILED; + } + } else { + if (state == 0) { // after invocation + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + + "\n\tis not suspended again after the invocation"); + tot_res = Consts.TEST_FAILED; + } else { + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis resumed as expected"); + } + } + // check other debuggee threads + for (int i=1; i argList; + int bitOpts; + + InvokingThread(ObjectReference objRef, ThreadReference thrRef, Method meth, LinkedList argList, int bitOpts) { + this.objRef = objRef; + this.thrRef = thrRef; + this.meth = meth; + this.argList = argList; + this.bitOpts = bitOpts; + super.setName("InvokingThread"); + } + + public void run() { + try { + log.display("\nInvokingThread: trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\twith the arguments: " + argList + + "\"\n\tand " + + new String((bitOpts==ObjectReference.INVOKE_SINGLE_THREADED)? "with" : "without") + + " the flag ObjectReference.INVOKE_SINGLE_THREADED\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + + LongValue retVal = (LongValue) + objRef.invokeMethod(thrRef, meth, argList, bitOpts); + log.display("InvokingThread: the method returned " + retVal); + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + log.display("InvokingThread: exiting"); + } + } +///////////////////////////////////////////////////////////////////////////// +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011/TestDescription.java new file mode 100644 index 00000000000..1ddc164cbf7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod011. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that invocation with all threads resumption + * and the single threaded one will be performed properly through + * the JDI method: + * com.sun.jdi.ObjectReference.invokeMethod(). + * The following assertions are verified: + * - by default, all threads in the target VM are resumed while + * the method is being invoked; + * - when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation; + * - only the specified thread will be resumed with the + * INVOKE_SINGLE_THREADED; + * - upon completion of a single threaded invoke, the invoking + * thread will be suspended once again. + * A debuggee part of the test starts several threads. Then debugger + * calls the JDI method with and without the flag + * ObjectReference.INVOKE_SINGLE_THREADED sequentially. During + * the invocation and after it the threads state is expected to be as + * described above. + * COMMENTS + * This test is similar to the following one: + * nsk/jdi/ObjectReference/invokeMethod/invokemethod010 + * except the order of single threaded and non single threaded + * invocations. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod011 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod011t + * + * @comment make sure invokemethod011t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod011t + * @compile -g:lines,source,vars ../invokemethod011t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod011 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011t.java new file mode 100644 index 00000000000..fadc1ab0030 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011t.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a main debuggee class. + */ +public class invokemethod011t { + static Log log; + private invokemethod011Thr thrs[] = + new invokemethod011Thr[invokemethod011.THRDS_NUM-1]; + private IOPipe pipe; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod011t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + invokemethod011tDummyClass invokemethod011tdummyCls = + new invokemethod011tDummyClass(); + + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(invokemethod011.DEBUGGEE_THRDS[0]); + // Start several dummy threads with given names + startThreads(); + + // Now the debuggee is ready for testing + pipe.println(invokemethod011.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod011.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod011.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod011.COMMAND_QUIT)) { + killThreads(argHandler.getWaitTime()*60000); + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + private void startThreads() { + Object readyObj = new Object(); + + for (int i=0; i < invokemethod011.THRDS_NUM-1; i++) { + thrs[i] = new invokemethod011Thr(readyObj, + invokemethod011.DEBUGGEE_THRDS[i+1]); + thrs[i].setDaemon(true); + log.display("Debuggee: starting thread #" + + i + " \"" + thrs[i].getName() + "\" ..."); + synchronized(readyObj) { + thrs[i].start(); + try { + readyObj.wait(); // wait for the thread's readiness + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: waiting for the thread " + + thrs[i].toString() + " start: caught " + e); + pipe.println("failed"); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + } + log.display("Debuggee: the thread #" + + i + " \"" + thrs[i].getName() + "\" started"); + } + } + + private void killThreads(int waitTime) { + for (int i=0; i < invokemethod011.THRDS_NUM-1 ; i++) { + thrs[i].doExit = true; + try { + thrs[i].join(waitTime); + log.display("Debuggee: thread #" + + i + " \"" + thrs[i].getName() + "\" done"); + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: joining the thread #" + + i + " \"" + thrs[i].getName() + "\": caught " + e); + } + } + } + + /** + * This is an auxiliary thread class used to check the flag + * ObjectReference.INVOKE_SINGLE_THREADED in the debugger. + */ + class invokemethod011Thr extends Thread { + volatile boolean doExit = false; + private Object readyObj; + + invokemethod011Thr(Object readyObj, String name) { + super(name); + this.readyObj = readyObj; + } + + public void run() { + Thread thr = Thread.currentThread(); + Object waitObj = new Object(); + + synchronized(readyObj) { + readyObj.notify(); // notify the main thread + } + log.display("Debuggee thread \"" + + thr.getName() + "\": going to loop"); + while(!doExit) { + int i = 0; + i++; i--; + + // reliable analogue of Thread.yield() + synchronized(waitObj) { + try { + waitObj.wait(30); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + log.complain("TEST FAILURE: Debuggee thread \"" + + thr.getName() + + "\" interrupted while sleeping:\n\t" + e); + break; + } + } + } + log.display("Debuggee thread \"" + + thr.getName() + "\" exiting ..."); + } + } +///////////////////////////////////////////////////////////////////////////// + +} + +/** + * Dummy class used to check the flag ObjectReference.INVOKE_SINGLE_THREADED + * in the debugger. + */ +class invokemethod011tDummyClass { + // used by the debugger to let the invoked method return + volatile boolean doExit = false; + // indicator that the method has been really invoked + volatile boolean isInvoked = false; + + long longMeth(long l) throws InterruptedException { + invokemethod011t.log.display("invokemethod011tDummyClass: longMeth: going to loop"); + isInvoked = true; + while(!doExit) { + l--; l++; + Thread.currentThread().sleep(400); + } + invokemethod011t.log.display("invokemethod011tDummyClass: longMeth: exiting"); + isInvoked = false; + doExit = false; + return l; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012.java new file mode 100644 index 00000000000..7e83e5a3fdc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012.java @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the single threaded invocation will be + * performed properly through the JDI method
    + * com.sun.jdi.ObjectReference.invokeMethod(). + * The following assertions are verified: + *
  • only the specified thread will be resumed with the + * INVOKE_SINGLE_THREADED + *
  • upon completion of a single threaded invoke, the invoking + * thread will be suspended once again. + *
  • any threads started during the single threaded invocation + * will not be suspended when the invocation completes.

    + * + * A debuggee part of the test starts several threads. The debugger + * calls the JDI method with the flag + * ObjectReference.INVOKE_SINGLE_THREADED. + * Then, during the invocation the debugger resumes some of the + * threads. Finally, these threads are checked to be not suspended + * when the invocation completes. + */ +public class invokemethod012 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod012t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 71; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod012tdummyCls"; + + // debuggee fields used to operate on an invoked method + static final String DEBUGGEE_FIELDS[] = { + "doExit", "isInvoked" + }; + + // debuggee threads to be check + static final int THRDS_NUM = 12; + static final String DEBUGGEE_THRDS[][] = { + {"invokemethod012tThr", "no"}, + {"invokemethod012tThr1", "no"}, + {"invokemethod012tThr2", "resume"}, + {"invokemethod012tThr3", "resume"}, + {"invokemethod012tThr4", "no"}, + {"invokemethod012tThr5", "no"}, + {"invokemethod012tThr6", "no"}, + {"invokemethod012tThr7", "no"}, + {"invokemethod012tThr8", "resume"}, + {"invokemethod012tThr9", "no"}, + {"invokemethod012tThr10", "no"}, + {"invokemethod012tThr11", "resume"} + }; + + // debuggee method to be invoke + static final String DEBUGGEE_METHOD = + "longMeth"; + + static final int DELAY = 400; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod012().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + ObjectReference objRef = null; + Field fldToExit = null; + BooleanValue val = null; + InvokingThread invThr = null; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod012t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[THRDS_NUM]; + for (int i=0; i methList = rType[1].methodsByName(DEBUGGEE_METHOD); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHOD + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + Method meth = methList.get(0); + LinkedList argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + // the single threaded invocation + invThr = new InvokingThread(objRef, thrRef[0], meth, + argList, ObjectReference.INVOKE_SINGLE_THREADED); + invThr.setDaemon(true); + invThr.start(); + + log.display("Waiting for debuggee method invocation ..."); + int tryOns = 0; + int attempts = (argHandler.getWaitTime() * 60000) / DELAY; + + do { + if (tryOns > attempts) + throw new Failure("unable to continue testing after " + + attempts + + " attempts: debuggee method is not invoked yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + val = (BooleanValue) + objRef.getValue(fldToCheck); + tryOns++; + } while (!val.value()); + + // check threads during the method invocation + checkThreads(thrRef, 1); + + // resume some threads during the method invocation + resumeSomeThreads(thrRef); + + objRef.setValue(fldToExit, vm.mirrorOf(true)); + invThr.join(argHandler.getWaitTime()*60000); + log.display("Thread \"" + invThr.getName() + "\" done"); + + // check threads status after the method invocation + checkThreads(thrRef, 0); + } catch (Exception e) { + e.printStackTrace(); + // force an method to exit if it has been invoked + if (objRef != null && fldToExit != null) { + try { + objRef.setValue(fldToExit, vm.mirrorOf(true)); + } catch(Exception ee) { + ee.printStackTrace(); + } + } + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private void checkThreads(ThreadReference thrRef[], int state) { + switch (state) { + case 0: + log.display("\nVerifying threads status when the invocation completes:"); + break; + case 1: + log.display("\nVerifying the single threaded invocation:"); + break; + } + + // check an invoking debuggee thread + if (thrRef[0].isSuspended()) { + if (state == 0) { // after invocation + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis suspended again after the invocation as expected"); + } else { + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + "\n\tis still suspended"); + tot_res = Consts.TEST_FAILED; + } + } else { + if (state == 0) { // after invocation + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + + "\n\tis not suspended again after the invocation"); + tot_res = Consts.TEST_FAILED; + } else { + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis resumed as expected"); + } + } + // check other debuggee threads + for (int i=1; i attempts) + throw new Failure("unable to continue testing after " + + attempts + + " attempts: debuggee thread " + + thrRef[i] + " is not resumed yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + tryOns++; + } while (thrRef[i].isSuspended()); + log.display("The thread " + thrRef[i] + + "\n\tis resumed"); + } + } + } + + private ObjectReference findObjRef(ThreadReference thrRef, String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) continue; + + // dummy debuggee class + return (ObjectReference) + stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + + /** + * A separate thread class used in debuggee method invocation because + * it is synchronous. + */ + class InvokingThread extends Thread { + ObjectReference objRef; + ThreadReference thrRef; + Method meth; + LinkedList argList; + int bitOpts; + + InvokingThread(ObjectReference objRef, ThreadReference thrRef, Method meth, LinkedList argList, int bitOpts) { + this.objRef = objRef; + this.thrRef = thrRef; + this.meth = meth; + this.argList = argList; + this.bitOpts = bitOpts; + super.setName("InvokingThread"); + } + + public void run() { + try { + log.display("\nInvokingThread: trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\twith the arguments: " + argList + + "\"\n\tand " + + new String((bitOpts==ObjectReference.INVOKE_SINGLE_THREADED)? "with" : "without") + + " the flag ObjectReference.INVOKE_SINGLE_THREADED\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + + LongValue retVal = (LongValue) + objRef.invokeMethod(thrRef, meth, argList, bitOpts); + log.display("InvokingThread: the method returned " + retVal); + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + log.display("InvokingThread: exiting"); + } + } +///////////////////////////////////////////////////////////////////////////// +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012/TestDescription.java new file mode 100644 index 00000000000..ae25a93fa66 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod012. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the single threaded invocation will be + * performed properly through the JDI method: + * com.sun.jdi.ObjectReference.invokeMethod(). + * The following assertions are verified: + * - only the specified thread will be resumed with the + * INVOKE_SINGLE_THREADED; + * - upon completion of a single threaded invoke, the invoking + * thread will be suspended once again; + * - any threads started during the single threaded invocation + * will not be suspended when the invocation completes. + * A debuggee part of the test starts several threads. The debugger + * calls the JDI method with the flag ObjectReference.INVOKE_SINGLE_THREADED. + * Then, during the invocation the debugger resumes some of the + * threads. Finally, these threads are checked to be not suspended + * when the invocation completes. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod012 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod012t + * + * @comment make sure invokemethod012t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod012t + * @compile -g:lines,source,vars ../invokemethod012t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod012 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012t.java new file mode 100644 index 00000000000..3f4aab830ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012t.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a main debuggee class. + */ +public class invokemethod012t { + static Log log; + private invokemethod012Thr thrs[] = + new invokemethod012Thr[invokemethod012.THRDS_NUM-1]; + private IOPipe pipe; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod012t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + invokemethod012tDummyClass invokemethod012tdummyCls = + new invokemethod012tDummyClass(); + + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(invokemethod012.DEBUGGEE_THRDS[0][0]); + // Start several dummy threads with given names + startThreads(); + + // Now the debuggee is ready for testing + pipe.println(invokemethod012.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod012.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod012.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod012.COMMAND_QUIT)) { + killThreads(argHandler.getWaitTime()*60000); + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + private void startThreads() { + Object readyObj = new Object(); + + for (int i=0; i < invokemethod012.THRDS_NUM-1; i++) { + thrs[i] = new invokemethod012Thr(readyObj, + invokemethod012.DEBUGGEE_THRDS[i+1][0]); + thrs[i].setDaemon(true); + log.display("Debuggee: starting thread #" + + i + " \"" + thrs[i].getName() + "\" ..."); + synchronized(readyObj) { + thrs[i].start(); + try { + readyObj.wait(); // wait for the thread's readiness + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: waiting for the thread " + + thrs[i].toString() + " start: caught " + e); + pipe.println("failed"); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + } + log.display("Debuggee: the thread #" + + i + " \"" + thrs[i].getName() + "\" started"); + } + } + + private void killThreads(int waitTime) { + for (int i=0; i < invokemethod012.THRDS_NUM-1 ; i++) { + thrs[i].doExit = true; + try { + thrs[i].join(waitTime); + log.display("Debuggee: thread #" + + i + " \"" + thrs[i].getName() + "\" done"); + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: joining the thread #" + + i + " \"" + thrs[i].getName() + "\": caught " + e); + } + } + } + + /** + * This is an auxiliary thread class used to check the flag + * ObjectReference.INVOKE_SINGLE_THREADED in the debugger. + */ + class invokemethod012Thr extends Thread { + volatile boolean doExit = false; + private Object readyObj; + + invokemethod012Thr(Object readyObj, String name) { + super(name); + this.readyObj = readyObj; + } + + public void run() { + Thread thr = Thread.currentThread(); + Object waitObj = new Object(); + + synchronized(readyObj) { + readyObj.notify(); // notify the main thread + } + log.display("Debuggee thread \"" + + thr.getName() + "\": going to loop"); + while(!doExit) { + int i = 0; + i++; i--; + + // reliable analogue of Thread.yield() + synchronized(waitObj) { + try { + waitObj.wait(30); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + log.complain("TEST FAILURE: Debuggee thread \"" + + thr.getName() + + "\" interrupted while sleeping:\n\t" + e); + break; + } + } + } + log.display("Debuggee thread \"" + + thr.getName() + "\" exiting ..."); + } + } +///////////////////////////////////////////////////////////////////////////// + +} + +/** + * Dummy class used to check the flag ObjectReference.INVOKE_SINGLE_THREADED + * in the debugger. + */ +class invokemethod012tDummyClass { + // used by the debugger to let the invoked method return + volatile boolean doExit = false; + // indicator that the method has been really invoked + volatile boolean isInvoked = false; + + long longMeth(long l) throws InterruptedException { + invokemethod012t.log.display("invokemethod012tDummyClass: longMeth: going to loop"); + isInvoked = true; + while(!doExit) { + l--; l++; + Thread.currentThread().sleep(400); + } + invokemethod012t.log.display("invokemethod012tDummyClass: longMeth: exiting"); + isInvoked = false; + doExit = false; + return l; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013.java new file mode 100644 index 00000000000..9685e515eda --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013.java @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that debuggee method invocation will be + * performed properly through the JDI method
    + * com.sun.jdi.ObjectReference.invokeMethod(). + * The following assertions are verified: + *

  • all threads in the target VM are resumed while the method is + * being invoked. If the thread's suspend count is greater than 1, + * it will remain in a suspended state during the invocation. + *
  • when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation.

    + * + * A debuggee part of the test starts several threads. The debugger + * suspends all of the threads by a breakpoint event and then, some + * of them one more time. After that, it calls the JDI method. + * Then, the threads are checked to be resumed or remain suspended + * during the invocation depending on the suspend count, and finally, + * to be suspended when it completes. + */ +public class invokemethod013 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.invokeMethod.invokemethod013t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 71; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod013tdummyCls"; + + // debuggee fields used to operate on an invoked method + static final String DEBUGGEE_FIELDS[] = { + "doExit", "isInvoked" + }; + + // debuggee threads to be check + static final int THRDS_NUM = 12; + static final String DEBUGGEE_THRDS[][] = { + {"invokemethod013tThr", "no"}, + {"invokemethod013tThr1", "no"}, + {"invokemethod013tThr2", "no"}, + {"invokemethod013tThr3", "no"}, + {"invokemethod013tThr4", "double-suspension"}, + {"invokemethod013tThr5", "no"}, + {"invokemethod013tThr6", "no"}, + {"invokemethod013tThr7", "no"}, + {"invokemethod013tThr8", "double-suspension"}, + {"invokemethod013tThr9", "double-suspension"}, + {"invokemethod013tThr10", "no"}, + {"invokemethod013tThr11", "double-suspension"} + }; + + // debuggee method to be invoke + static final String DEBUGGEE_METHOD = + "longMeth"; + + static final int DELAY = 400; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod013().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + ObjectReference objRef = null; + Field fldToExit = null; + BooleanValue val = null; + InvokingThread invThr = null; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod013t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[THRDS_NUM]; + for (int i=0; i methList = rType[1].methodsByName(DEBUGGEE_METHOD); + if (methList.isEmpty()) { + log.complain("TEST FAILURE: the expected debuggee method \"" + + DEBUGGEE_METHOD + + "\" not found through the JDI method ReferenceType.methodsByName()"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + Method meth = methList.get(0); + LinkedList argList = new LinkedList(); + argList.add(vm.mirrorOf(9223372036854775807L)); + + invThr = new InvokingThread(objRef, thrRef[0], meth, + argList, 0); + invThr.setDaemon(true); + + // suspend some threads one more time before the method + // invocation in order to make the thread's suspend count + // greater than 1 + suspendSomeThreads(thrRef); + + // perform the invocation + invThr.start(); + log.display("Waiting for debuggee method invocation ..."); + int tryOns = 0; + int attempts = (argHandler.getWaitTime() * 60000) / DELAY; + + do { + if (tryOns > attempts) + throw new Failure("unable to continue testing after " + + attempts + + " attempts: debuggee method is not invoked yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + val = (BooleanValue) + objRef.getValue(fldToCheck); + tryOns++; + } while (!val.value()); + + // check threads during the method invocation + checkThreads(thrRef, 1); + + objRef.setValue(fldToExit, vm.mirrorOf(true)); + invThr.join(argHandler.getWaitTime()*60000); + log.display("Thread \"" + invThr.getName() + "\" done"); + + // check threads status after the method invocation + checkThreads(thrRef, 0); + } catch (Exception e) { + e.printStackTrace(); + // force an method to exit if it has been invoked + if (objRef != null && fldToExit != null) { + try { + objRef.setValue(fldToExit, vm.mirrorOf(true)); + } catch(Exception ee) { + ee.printStackTrace(); + } + } + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private void checkThreads(ThreadReference thrRef[], int state) { + switch (state) { + case 0: + log.display("\nVerifying threads status when the invocation completes:"); + break; + case 1: + log.display("\nVerifying threads status during the invocation:"); + break; + } + + // check an invoking debuggee thread + if (thrRef[0].isSuspended()) { + if (state == 0) { // after invocation + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis suspended again after the invocation as expected"); + } else { + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + "\n\tis still suspended"); + tot_res = Consts.TEST_FAILED; + } + } else { + if (state == 0) { // after invocation + log.complain("TEST FAILED: wrong invocation: " + + "\n\tinvoking debuggee thread " + thrRef[0] + + "\n\tis not suspended again after the invocation"); + tot_res = Consts.TEST_FAILED; + } else { + log.display("CHECK PASSED: invoking debuggee thread " + thrRef[0] + + "\n\tis resumed as expected"); + } + } + // check other debuggee threads + for (int i=1; i attempts) + throw new Failure("unable to continue testing after " + + attempts + + " attempts: debuggee thread " + + thrRef[i] + " is not suspended yet"); + + // reliable analogue of Thread.yield() + synchronized(this) { + this.wait(DELAY); + } + tryOns++; + } while (thrRef[i].suspendCount() != 2); + log.display("The thread " + thrRef[i] + + "\n\tis suspended one more time: the number of pending suspends = " + + thrRef[i].suspendCount()); + } + } + } + + private ObjectReference findObjRef(ThreadReference thrRef, String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) continue; + + // dummy debuggee class + return (ObjectReference)stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("Resuming debuggee twice ..."); + vm.resume(); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } + + /** + * A separate thread class used in the debuggee method invocation because + * it is synchronous. + */ + class InvokingThread extends Thread { + ObjectReference objRef; + ThreadReference thrRef; + Method meth; + LinkedList argList; + int bitOpts; + + InvokingThread(ObjectReference objRef, ThreadReference thrRef, Method meth, LinkedList argList, int bitOpts) { + this.objRef = objRef; + this.thrRef = thrRef; + this.meth = meth; + this.argList = argList; + this.bitOpts = bitOpts; + super.setName("InvokingThread"); + } + + public void run() { + try { + log.display("\nInvokingThread: trying to invoke the method \"" + + meth.name() + " " + meth.signature() + " " + meth + + "\"\n\twith the arguments: " + argList + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\" ..."); + + LongValue retVal = (LongValue) + objRef.invokeMethod(thrRef, meth, argList, bitOpts); + log.display("InvokingThread: the method returned " + retVal); + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + log.display("InvokingThread: exiting"); + } + } +///////////////////////////////////////////////////////////////////////////// +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013/TestDescription.java new file mode 100644 index 00000000000..780316eaaa2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod013. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that debuggee method invocation will be + * performed properly through the JDI method: + * com.sun.jdi.ObjectReference.invokeMethod(). + * The following assertions are verified: + * - all threads in the target VM are resumed while the method is + * being invoked. If the thread's suspend count is greater than 1, + * it will remain in a suspended state during the invocation; + * - when the invocation completes, all threads in the target VM + * are suspended, regardless their state before the invocation. + * A debuggee part of the test starts several threads. The debugger + * suspends all of the threads by a breakpoint event and then, some + * of them one more time. After that, it calls the JDI method. + * Then, the threads are checked to be resumed or remain suspended + * during the invocation depending on the suspend count, and finally, + * to be suspended when it completes. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod013 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod013t + * + * @comment make sure invokemethod013t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod013t + * @compile -g:lines,source,vars ../invokemethod013t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod013 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013t.java new file mode 100644 index 00000000000..7b309f07d19 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod013t.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a main debuggee class. + */ +public class invokemethod013t { + static Log log; + private invokemethod013Thr thrs[] = + new invokemethod013Thr[invokemethod013.THRDS_NUM-1]; + private IOPipe pipe; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod013t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + invokemethod013tDummyClass invokemethod013tdummyCls = + new invokemethod013tDummyClass(); + + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(invokemethod013.DEBUGGEE_THRDS[0][0]); + // Start several dummy threads with given names + startThreads(); + + // Now the debuggee is ready for testing + pipe.println(invokemethod013.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod013.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // invokemethod013.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod013.COMMAND_QUIT)) { + killThreads(argHandler.getWaitTime()*60000); + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + + killThreads(argHandler.getWaitTime()*60000); + return Consts.TEST_PASSED; + } + + private void startThreads() { + Object readyObj = new Object(); + + for (int i=0; i < invokemethod013.THRDS_NUM-1; i++) { + thrs[i] = new invokemethod013Thr(readyObj, + invokemethod013.DEBUGGEE_THRDS[i+1][0]); + thrs[i].setDaemon(true); + log.display("Debuggee: starting thread #" + + i + " \"" + thrs[i].getName() + "\" ..."); + synchronized(readyObj) { + thrs[i].start(); + try { + readyObj.wait(); // wait for the thread's readiness + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: waiting for the thread " + + thrs[i].toString() + " start: caught " + e); + pipe.println("failed"); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + } + log.display("Debuggee: the thread #" + + i + " \"" + thrs[i].getName() + "\" started"); + } + } + + private void killThreads(int waitTime) { + for (int i=0; i < invokemethod013.THRDS_NUM-1 ; i++) { + thrs[i].doExit = true; + try { + thrs[i].join(waitTime); + log.display("Debuggee: thread #" + + i + " \"" + thrs[i].getName() + "\" done"); + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: joining the thread #" + + i + " \"" + thrs[i].getName() + "\": caught " + e); + } + } + } + + /** + * This is an auxiliary thread class used to check method + * invocation in the debugger. + */ + class invokemethod013Thr extends Thread { + volatile boolean doExit = false; + private Object readyObj; + + invokemethod013Thr(Object readyObj, String name) { + super(name); + this.readyObj = readyObj; + } + + public void run() { + Thread thr = Thread.currentThread(); + Object waitObj = new Object(); + + synchronized(readyObj) { + readyObj.notify(); // notify the main thread + } + log.display("Debuggee thread \"" + + thr.getName() + "\": going to loop"); + while(!doExit) { + int i = 0; + i++; i--; + + // reliable analogue of Thread.yield() + synchronized(waitObj) { + try { + waitObj.wait(30); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + log.complain("TEST FAILURE: Debuggee thread \"" + + thr.getName() + + "\" interrupted while sleeping:\n\t" + e); + break; + } + } + } + log.display("Debuggee thread \"" + + thr.getName() + "\" exiting ..."); + } + } +///////////////////////////////////////////////////////////////////////////// + +} + +/** + * Dummy class used to check method invocation in the debugger. + */ +class invokemethod013tDummyClass { + // used by the debugger to let the invoked method return + volatile boolean doExit = false; + // indicator that the method has been really invoked + volatile boolean isInvoked = false; + + long longMeth(long l) throws InterruptedException { + invokemethod013t.log.display("invokemethod013tDummyClass: longMeth: going to loop"); + isInvoked = true; + while(!doExit) { + l--; l++; + Thread.currentThread().sleep(400); + } + invokemethod013t.log.display("invokemethod013tDummyClass: longMeth: exiting"); + isInvoked = false; + doExit = false; + return l; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014.java new file mode 100644 index 00000000000..01e3fe6f950 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014.java @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method:
    + * com.sun.jdi.ObjectReference.invokeMethod() + * properly throws IllegalArgumentException, when debugger + * part of the test attempts to invoke several debuggee methods + * which are not members of an object's class and: + *

  • declared non-public (access by default) from outside the package + *
  • declared protected from outside the package + *
  • finally, declared private from outside the package. + */ +public class invokemethod014 { + static final String DEBUGGEE_CLASSES[] = { + "nsk.jdi.ObjectReference.invokeMethod.invokemethod014t", + "nsk.jdi.ObjectReference.invokeMethod.invokemethod014tDummySuperClass", + "nsk.jdi.ObjectReference.dummyPackage.invokemethod014a" + }; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "invokemethod014tThr"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 72; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = + "invokemethod014tdummyCls"; + + // tested debuggee methods with different kind of access, + // and their type reference numbers + static final int METH_NUM = 30; + static final String DEBUGGEE_METHODS[][] = { + {"byteMeth", "2", "non-public"}, + {"shortMeth", "2", "non-public"}, + {"intMeth", "2", "non-public"}, + {"longMeth", "2", "non-public"}, + {"floatMeth", "2", "non-public"}, + {"doubleMeth", "2", "non-public"}, + {"charMeth", "2", "non-public"}, + {"booleanMeth", "2", "non-public"}, + {"strMeth", "2", "non-public"}, + {"voidMeth", "2", "non-public"}, + {"protByteMeth", "2", "protected"}, + {"protShortMeth", "2", "protected"}, + {"protIntMeth", "2", "protected"}, + {"protLongMeth", "2", "protected"}, + {"protFloatMeth", "2", "protected"}, + {"protDoubleMeth", "2", "protected"}, + {"protCharMeth", "2", "protected"}, + {"protBooleanMeth", "2", "protected"}, + {"protStrMeth", "2", "protected"}, + {"protVoidMeth", "2", "protected"}, + {"privByteMeth", "2", "private"}, + {"privShortMeth", "2", "private"}, + {"privIntMeth", "2", "private"}, + {"privLongMeth", "2", "private"}, + {"privFloatMeth", "2", "private"}, + {"privDoubleMeth", "2", "private"}, + {"privCharMeth", "2", "private"}, + {"privBooleanMeth", "2", "private"}, + {"privStrMeth", "2", "private"}, + {"privVoidMeth", "2", "private"} + }; + + static final int ATTEMPTS = 5; + static final int DELAY = 400; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new invokemethod014().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + String cmd; + ObjectReference objRef = null; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASSES[0]); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "invokemethod014t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + ReferenceType[] rType = new ReferenceType[3]; + // debuggee main & dummy classes + rType[0] = debuggee.classByName(DEBUGGEE_CLASSES[0]); + rType[1] = debuggee.classByName(DEBUGGEE_CLASSES[1]); + rType[2] = debuggee.classByName(DEBUGGEE_CLASSES[2]); + +// Check the tested assersion + try { + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + objRef = findObjRef(thrRef, DEBUGGEE_LOCALVAR); + + for (int i=0; iemptyList(), 0); + + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to invoke " + methInfo + + "\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } catch (IllegalArgumentException ia) { + log.display("CHECK PASSED: caught expected " + ia); + } catch (Exception ee) { + ee.printStackTrace(); + log.complain("TEST FAILED: ObjectReference.invokeMethod(): caught unexpected " + + ee + "\n\tinstead of expected llegalArgumentException" + + "\n\twhen attempted to invoke " + methInfo + + "\n\tgot from reference type \"" + rType[typeIndex] + + "\"\n\tusing the debuggee object reference \"" + + objRef + "\""); + tot_res = Consts.TEST_FAILED; + } + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private ObjectReference findObjRef(ThreadReference thrRef, String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) continue; + + // dummy debuggee class + return (ObjectReference)stackFr.getValue(locVar); + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("Resuming debuggee ..."); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014/TestDescription.java new file mode 100644 index 00000000000..179edd23e71 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/invokeMethod/invokemethod014. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method: + * com.sun.jdi.ObjectReference.invokeMethod() + * properly throws IllegalArgumentException, when debugger + * part of the test attempts to invoke several debuggee methods + * which are not members of an object's class and: + * - declared non-public (access by default) from outside + * the package; + * - declared protected from outside the package; + * - finally, declared private from outside the package. + * COMMENTS + * Modified due to fix of the bug: + * 4716226 JDI: ObjectReference.invokeMethod() allows to invoke private methods + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.invokeMethod.invokemethod014 + * nsk.jdi.ObjectReference.invokeMethod.invokemethod014t + * + * @comment make sure invokemethod014t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.invokeMethod.invokemethod014t + * @compile -g:lines,source,vars ../invokemethod014t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.invokeMethod.invokemethod014 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014t.java new file mode 100644 index 00000000000..2196a976b69 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod014t.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a main debuggee class. + */ +public class invokemethod014t { + public static Log log; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new invokemethod014t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // force debuggee VM to load dummy classes + invokemethod014tDummyClass invokemethod014tdummyCls = + new invokemethod014tDummyClass(); + invokemethod014tDummySuperClass invokemethod014tdummySCls = + new invokemethod014tDummySuperClass(); + nsk.jdi.ObjectReference.dummyPackage.invokemethod014a + invokemethod014adummyCls = + new nsk.jdi.ObjectReference.dummyPackage.invokemethod014a(); + + log = argHandler.createDebugeeLog(); + + Thread.currentThread().setName(invokemethod014.DEBUGGEE_THRNAME); + + // Now the debuggee is ready for testing + pipe.println(invokemethod014.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(invokemethod014.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0;// invokemethod014.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(invokemethod014.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } + +} + +/** + * Dummy superclass used to provoke IllegalArgumentException + * in the debugger: private methods cannot be accessed from + * other classes. + */ +class invokemethod014tDummySuperClass { + private byte prByteMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prByteMeth\" was invoked!"); + return 127; + } + + private short prShortMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prShortMeth\" was invoked!"); + return -32768; + } + + private int prIntMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prIntMeth\" was invoked!"); + return 2147483647; + } + + private long prLongMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prLongMeth\" was invoked!"); + return 9223372036854775807L; + } + + private float prFloatMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prFloatMeth\" was invoked!"); + return 5.1F; + } + + private double prDoubleMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prDoubleMeth\" was invoked!"); + return 6.2D; + } + + private char prCharMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prCharMeth\" was invoked!"); + return 'a'; + } + + private boolean prBooleanMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prBooleanMeth\" was invoked!"); + return false; + } + + private String prStrMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prStrMeth\" was invoked!"); + return "string method"; + } + + private void prVoidMeth() { + invokemethod014t.log.complain("invokemethod014tDummySuperClass: private method \"prVoidMeth\" was invoked!"); + } +} + +/** + * Dummy subclass used to provoke IllegalArgumentException + * in the debugger. + */ +class invokemethod014tDummyClass extends invokemethod014tDummySuperClass {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001.java new file mode 100644 index 00000000000..2463fbfa27f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.isCollected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.isCollected()
    + * complies with its specification.
    + *
    + * The test checks up that a value returned by the method is
    + * "false" provided a testing object is not garbage collected.
    + */ + +public class iscollected001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/isCollected/iscollected001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new iscollected001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.isCollected.iscollected001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.isCollected.TestClass"; + + //String mName = "nsk.jdi.ObjectReference.isCollected"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String objName = "testObj"; + + log2("......getting ObjectReference objRef object"); + try { + + testedClass = (ReferenceType) + vm.classesByName(debuggeeName).get(0); + + ObjectReference objRef = (ObjectReference) + testedClass.getValue(testedClass.fieldByName(objName)); + + log2("......performing the check : objRef.isCollected();"); + log2(" ERROR if returned value is 'true'"); + if (objRef.isCollected()) { + log3("ERROR: objRef.isCollected() == true"); + testExitCode = FAILED; + } else { + log2(" objRef.isCollected() == false"); + } + + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001/TestDescription.java new file mode 100644 index 00000000000..324c69df88f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/isCollected/iscollected001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.isCollected() + * complies with its spec: + * public boolean isCollected() + * Determines if this object has been garbage collected in the target VM. + * Returns: true if this ObjectReference has been collected; false otherwise. + * The case for testing includes testing an object that + * is not garbage collected, hence, a returned value == false. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.isCollected.iscollected001; + * the debuggee program - nsk.jdi.ObjectReference.isCollected.iscollected001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.isCollected.iscollected001 + * nsk.jdi.ObjectReference.isCollected.iscollected001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.isCollected.iscollected001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001a.java new file mode 100644 index 00000000000..6c96007c1ad --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/isCollected/iscollected001a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.isCollected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the iscollected001 JDI test. + */ + +public class iscollected001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass testObj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.owningThread()
    + * complies with its specification.
    + *
    + * The case for testing includes throwing
    + * UnsupportedOperationException
    + * provided
    + * VirtualMachine.canGetOwnedMonitorInfo() == false
    + */ + +public class owningthread001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/owningThread/owningthread001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new owningthread001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.owningThread.owningthread001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.owningThread.TestClass"; + + //String mName = "nsk.jdi.ObjectReference.owningThread"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + List allThreads = null; + List monitors = null; + ListIterator listIterator = null; + List classes = null; + ObjectReference objRef = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO 'main' thread ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + + label1: { + if (expresult != returnCode0) + break label1; + + + log2(" suspending the main thread"); + mainThread.suspend(); + + objRef = (ObjectReference) testedClass.getValue(testedClass.fieldByName("bl")); + + + if (!vm.canGetOwnedMonitorInfo()) { + + log2(".......vm.canGetOwnedMonitorInfo() == false"); + log2(".......checking up on throwing UnsupportedOperationException"); + try { + ThreadReference tr = objRef.owningThread(); + log3("ERROR: UnsupportedOperationException is not thrown"); + expresult = returnCode1; + } catch ( UnsupportedOperationException e1 ) { + log2(" UnsupportedOperationException"); + } catch ( Exception e2 ) { + expresult = returnCode1; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + } + + log2(" resuming the main thread"); + mainThread.resume(); + } + + log2("......instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001/TestDescription.java new file mode 100644 index 00000000000..1ce3ad1ae90 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/owningThread/owningthread001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.owningThread() + * complies with its spec: + * public ThreadReference owningThread() + * throws IncompatibleThreadStateException + * Returns an ThreadReference for the thread, if any, + * which currently owns this object's monitor. + * See ThreadReference.ownedMonitors() for a definition of ownership. + * Not all target VMs support this operation. + * See VirtualMachine#canGetMonitorInfo to determine if the operation is supported. + * Returns: the ThreadReference which currently owns the monitor, or + * null if it is unowned. + * Throws: java.lang.UnsupportedOperationException - + * if the target target VM does not support this operation. + * IncompatibleThreadStateException - + * if the owning thread is not suspended in the target VM + * ObjectCollectedException - + * if this object has been garbage collected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.owningThread.owningthread 00; + * the debuggee program - nsk.jdi.ObjectReference.owningThread.owningthread 00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.owningThread.owningthread001 + * nsk.jdi.ObjectReference.owningThread.owningthread001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.owningThread.owningthread001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001a.java new file mode 100644 index 00000000000..82466190ba2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread001a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.owningThread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the owningthread001 JDI test. + */ + +public class owningthread001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + private static Threadowningthread001a thread2 = null; + + static TestClass testObj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + private Event waitForEvent (EventRequest eventRequest) { + + vm.resume(); + Event resultEvent = null; + try { + eventSet = null; + eventIterator = null; + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event curEvent = eventIterator.nextEvent(); + if (curEvent instanceof VMDisconnectEvent) { + throw new Failure("Unexpected VMDisconnectEvent received."); + } else { + EventRequest evRequest = curEvent.request(); + if (evRequest != null && evRequest.equals(eventRequest)) { + display("Requested event received: " + curEvent.toString() + + "; request property: " + (String) curEvent.request().getProperty("number")); + resultEvent = curEvent; + break; + } else { + throw new Failure("Unexpected event received: " + curEvent.toString()); + } + } + } + } catch (Exception e) { + throw new Failure("Unexpected exception while waiting for an event: " + e); + } + return resultEvent; + } + + + private void getEventSet() { + try { + eventSet = vm.eventQueue().remove(waitTime); + if (eventSet == null) { + throw new Failure("TIMEOUT while waiting for an event"); + } + eventIterator = eventSet.eventIterator(); + } catch (Exception e) { + throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); + } + } + + private ReferenceType waitForDebuggeeClassPrepared () { + display("Creating request for ClassPrepareEvent for debuggee."); + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.addClassFilter(debuggeeName); + cpRequest.addCountFilter(1); + cpRequest.enable(); + + ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); + cpRequest.disable(); + + if (!event.referenceType().name().equals(debuggeeName)) { + throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); + } + return event.referenceType(); + } + + private int getInstruction () { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + return ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } + + private void setInstruction (String instructionField) { + if (debuggeeClass == null) { + throw new Failure("getInstruction() :: debuggeeClass reference is null"); + } + Field instrField = debuggeeClass.fieldByName("instruction"); + IntegerValue instrValue = (IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName(instructionField))); + try { + ((ClassType)debuggeeClass).setValue(instrField, instrValue ); + } catch (InvalidTypeException e1) { + throw new Failure("Caught unexpected InvalidTypeException while setting value '" + instructionField + "' for instruction field"); + } catch (ClassNotLoadedException e2) { + throw new Failure("Caught unexpected ClassNotLoadedException while setting value '" + instructionField + "' for instruction field"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002/TestDescription.java new file mode 100644 index 00000000000..118ee585dba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/owningThread/owningthread002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks the following assertion of + * com.sun.jdi.ObjectReference.owningThread method spec: + * Returns an ThreadReference for the thread, if any, + * which currently owns this object's monitor. + * The debugger program - nsk.jdi.ObjectReference.owningThread.owningthread002; + * the debuggee program - nsk.jdi.ObjectReference.owningThread.owningthread002a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * The debuggee's main threads starts a number of auxiliary threads. + * Each of them invokes syncronized foo method of owningthread002aLock class. + * The debugger creates MethodEntryRequest filtered to class of foo method. + * Each time the foo is invoked, the debuggee is suspended. Upon receiving next + * MethodEntryEvent, the debugger calls owningThread method for the debuggee's field + * of owningthread002aLock type. The returned ThreadReference must have expected name + * and be equal to the thread reference returned by thread method of received + * MethodEntryEvent . + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - remove waiting for VMStartEvent after launching debuggee VM + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.makeBreakpoint() method for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.owningThread.owningthread002 + * nsk.jdi.ObjectReference.owningThread.owningthread002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.owningThread.owningthread002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002a.java new file mode 100644 index 00000000000..b3472b24b5c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002a.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.owningThread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class owningthread002a { + + //----------------------------------------------------- immutable common fields + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + static final int quit = -1; + + static int instruction = 1; + static int lineForComm = 2; + static int exitCode = PASSED; + + private static ArgumentHandler argHandler; + private static Log log; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + private static void methodForCommunication() { + int i = instruction; // owningthread002.lineForBreak + int curInstruction = i; + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static owningthread002aLock lockObj = new owningthread002aLock(); +// static Object waitnotifyObj = new Object(); + static final int threadCount = 5; + static final String threadNamePrefix = "MyThread-"; + static owningthread002aThread[] threads = new owningthread002aThread[threadCount]; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + long waitTime = argHandler.getWaitTime() * 60000; + + display("debuggee started!"); + + label0: + for (int testCase = 0; instruction != quit; testCase++) { + + switch (testCase) { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test case section + case 0: + display("call methodForCommunication() #0"); + methodForCommunication(); + + for (int i = 0; i < threadCount; i++) { + threads[i] = new owningthread002aThread(threadNamePrefix + i); + threads[i].start(); +/* + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for " + threadNamePrefix + i + " start"); + } +*/ + } + + for (int i = 0; i < threadCount; i++) { + if (threads[i].isAlive()) { + try { + threads[i].join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for " + threadNamePrefix + i + " join"); + } + } + } + + break; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end of section + + default: + instruction = quit; + break; + } + + display("call methodForCommunication() #1"); + methodForCommunication(); + if (instruction == quit) + break; + } + + display("debuggee exits"); + System.exit(PASSED + PASS_BASE); + } + + //--------------------------------------------------------- test specific methodss + +} + +//--------------------------------------------------------- test specific classes + +class owningthread002aLock { + synchronized void foo () { + } +} + +class owningthread002aThread extends Thread { + public owningthread002aThread(String threadName) { + super(threadName); + } + + public void run() { +/* + synchronized (owningthread002a.waitnotifyObj) { + display("entered: synchronized (waitnotifyObj)"); + owningthread002a.waitnotifyObj.notifyAll(); + } + display("exited: synchronized (waitnotifyObj)"); +*/ + owningthread002a.lockObj.foo(); + display("exited: synchronized method foo"); + } + + private void display (String str) { + owningthread002a.display(Thread.currentThread().getName() + " : " + str); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001.java new file mode 100644 index 00000000000..7ce032b664d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.referenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.referenceType()
    + * complies with its spec when ObjectReference is ThreadReference.
    + *
    + * The test consequently checks up the following assersions:
    + * - the type may be a subclass or implementor of the declared type
    + * of any field or variable which currently holds it;
    + * - the returned ReferenceType will be a ClassType or ArrayType
    + * and never an InterfaceType;
    + * - the type of an object never changes, so this method will
    + * always return the same ReferenceType over the lifetime
    + * of the mirrored object.
    + */ + +public class referencetype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/referenceType/referencetype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new referencetype001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.referenceType.referencetype001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.referenceType.Threadreferencetype001a"; + + //String mName = "nsk.jdi.ObjectReference.referenceType"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + + List allThreads = null; + ListIterator listIterator = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + + log2("......ReferenceType testedClass = thread2.referenceType();"); + testedClass = thread2.referenceType(); + + log2("...... check up on equality testedClass.name() to String testedClassName"); + if (!testedClass.name().equals(testedClassName)) { + log3("ERROR: check that the type may be a subclass or implementor of the declared type FAILED"); + log3("ERROR: String testedClassName : " + testedClassName); + log3("ERROR: performing statement : !testedClass.name().equals(testedClassName)"); + log3("ERROR: testedClass.name() : " + testedClass.name()); + expresult = returnCode1; + } + + try { + log2(".......check up on cast to ClassType; no Exception expected"); + ClassType ct = (ClassType) testedClass; + } catch ( Exception e ) { + log3("ERROR: check that ReferenceType will be a ClassType FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: ClassType ct = (ClassType) testedClass;"); + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + + log2(".......check up on equality ReferenceType thread2.referenceType() to testedClass"); + ReferenceType testedClass1 = thread2.referenceType(); + if (!testedClass1.equals(testedClass)) { + log3("ERROR: check that the method always return the same RefereneceType object FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: !thread2.referenceType().equals(testedClass)"); + log3("ERROR: returned ReferenceType : " + testedClass1); + expresult = returnCode1; + } + + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001/TestDescription.java new file mode 100644 index 00000000000..5337a88cab2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referenceType/referencetype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.referenceType() + * complies with its spec: + * public ReferenceType referenceType() + * Gets the ReferenceType that mirrors the type of this object. + * The type may be a subclass or implementor of the declared type of + * any field or variable which currently holds it. + * For example, right after the following statement. + * Object obj = new String("Hello, world!"); + * The ReferenceType of obj will mirror java.lang.String and + * not java.lang.Object. + * The type of an object never changes, so this method will always return + * the same ReferenceType over the lifetime of the mirrored object. + * The returned ReferenceType will be a ClassType or ArrayType and never + * an InterfaceType. + * Returns: the ReferenceType for this object. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes ThreadReference object, + * and no ObjectCollectedException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.referenceType.referencetype001; + * the debuggee program - nsk.jdi.ObjectReference.referenceType.referencetype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referenceType.referencetype001 + * nsk.jdi.ObjectReference.referenceType.referencetype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referenceType.referencetype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001a.java new file mode 100644 index 00000000000..471c13c44e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype001a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.referenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the referencetype001 JDI test. + */ + +public class referencetype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.referenceType()
    + * complies with its spec when ObjectReference is StringReference.
    + *
    + * The test consequently checks up the following assersions:
    + * - the type may be a subclass or implementor of the declared type
    + * of any field or variable which currently holds it;
    + * - the returned ReferenceType will be a ClassType or ArrayType
    + * and never an InterfaceType;
    + * - the type of an object never changes, so this method will
    + * always return the same ReferenceType over the lifetime
    + * of the mirrored object.
    + */ + +public class referencetype002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/referenceType/referencetype002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new referencetype002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.referenceType.referencetype002a"; + + private String testedClassName = "java.lang.String"; + + //String mName = "nsk.jdi.ObjectReference.referenceType"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + classes = vm.classesByName(debuggeeName); + testedClass = (ReferenceType) classes.get(0); + + StringReference str = (StringReference) testedClass.getValue( + testedClass.fieldByName("str")); + + + log2("......ReferenceType testedClass = str.referenceType();"); + testedClass = str.referenceType(); + + + log2("...... check up on equality testedClass.name() to String testedClassName"); + if (!testedClass.name().equals(testedClassName)) { + log3("ERROR: check that the type may be a subclass or implementor of the declared type FAILED"); + log3("ERROR: String testedClassName : " + testedClassName); + log3("ERROR: performing statement : !testedClass.name().equals(testedClassName)"); + log3("ERROR: testedClass.name() : " + testedClass.name()); + testExitCode = FAILED; + } + + try { + log2(".......check up on cast to ClassType; no Exception expected"); + ClassType ct = (ClassType) testedClass; + } catch ( Exception e ) { + log3("ERROR: check that ReferenceType will be a ClassType FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: ClassType ct = (ClassType) testedClass;"); + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + + + log2(".......check up on equality ReferenceType str.referenceType() to testedClass"); + ReferenceType testedClass1 = str.referenceType(); + if (!testedClass1.equals(testedClass)) { + log3("ERROR: check that the method always return the same RefereneceType object FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: !str.referenceType().equals(testedClass)"); + log3("ERROR: returned ReferenceType : " + testedClass1); + testExitCode = FAILED; + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002/TestDescription.java new file mode 100644 index 00000000000..a99bb0e6c34 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referenceType/referencetype002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.referenceType() + * complies with its spec: + * public ReferenceType referenceType() + * Gets the ReferenceType that mirrors the type of this object. + * The type may be a subclass or implementor of the declared type of + * any field or variable which currently holds it. + * For example, right after the following statement. + * Object obj = new String("Hello, world!"); + * The ReferenceType of obj will mirror java.lang.String and + * not java.lang.Object. + * The type of an object never changes, so this method will always return + * the same ReferenceType over the lifetime of the mirrored object. + * The returned ReferenceType will be a ClassType or ArrayType and never + * an InterfaceType. + * Returns: the ReferenceType for this object. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes StringReference object, + * and no ObjectCollectedException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.referenceType.referencetype002; + * the debuggee program - nsk.jdi.ObjectReference.referenceType.referencetype002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referenceType.referencetype002 + * nsk.jdi.ObjectReference.referenceType.referencetype002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referenceType.referencetype002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002a.java new file mode 100644 index 00000000000..f3ee2d17204 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype002a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.referenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the referencetype002 JDI test. + */ + +public class referencetype002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static String str = "Hello, world!"; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.referenceType()
    + * complies with its spec when ObjectReference is ThreadGroupReference.
    + *
    + * The test consequently checks up the following assersions:
    + * - the type may be a subclass or implementor of the declared type
    + * of any field or variable which currently holds it;
    + * - the returned ReferenceType will be a ClassType or ArrayType
    + * and never an InterfaceType;
    + * - the type of an object never changes, so this method will
    + * always return the same ReferenceType over the lifetime
    + * of the mirrored object.
    + */ + +public class referencetype003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/referenceType/referencetype003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new referencetype003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.referenceType.referencetype003a"; + + private String testedClassName = "java.lang.ThreadGroup"; + + //String mName = "nsk.jdi.ObjectReference.referenceType"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + ReferenceType testedClass = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + String mainGroupObj = "mainGroupObj"; + String mainGroupName = "mainthreadGroupName"; + + List classes = null; + + ReferenceType mainThreadClass = null; + + label0: { + + log2("getting ThreadReference objects"); + try { + classes = vm.classesByName(debuggeeName); + mainThreadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + + log2(" getting: ThreadGroupReference mainThreadGroup"); + ThreadGroupReference mainThreadGroup = (ThreadGroupReference) + mainThreadClass.getValue(mainThreadClass.fieldByName(mainGroupObj) ); + + log2("......ReferenceType testedClass = mainThreadGroup.referenceType();"); + testedClass = mainThreadGroup.referenceType(); + + + log2("...... check up on equality testedClass.name() to String testedClassName"); + if (!testedClass.name().equals(testedClassName)) { + log3("ERROR: check that the type may be a subclass or implementor of the declared type FAILED"); + log3("ERROR: String testedClassName : " + testedClassName); + log3("ERROR: performing statement : !testedClass.name().equals(testedClassName)"); + log3("ERROR: testedClass.name() : " + testedClass.name()); + expresult = returnCode1; + } + + try { + log2(".......check up on cast to ClassType; no Exception expected"); + ClassType ct = (ClassType) testedClass; + } catch ( Exception e ) { + log3("ERROR: check that ReferenceType will be a ClassType FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: ClassType ct = (ClassType) testedClass;"); + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + + log2(".......check up on equality ReferenceType mainThreadGroup.referenceType() to testedClass"); + ReferenceType testedClass1 = mainThreadGroup.referenceType(); + if (!testedClass1.equals(testedClass)) { + log3("ERROR: check that the method always return the same RefereneceType object FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: !mainThreadGroup.referenceType().equals(testedClass)"); + log3("ERROR: returned ReferenceType : " + testedClass1); + expresult = returnCode1; + } + + + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003/TestDescription.java new file mode 100644 index 00000000000..56ab485830a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referenceType/referencetype003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.referenceType() + * complies with its spec: + * public ReferenceType referenceType() + * Gets the ReferenceType that mirrors the type of this object. + * The type may be a subclass or implementor of the declared type of + * any field or variable which currently holds it. + * For example, right after the following statement. + * Object obj = new String("Hello, world!"); + * The ReferenceType of obj will mirror java.lang.String and + * not java.lang.Object. + * The type of an object never changes, so this method will always return + * the same ReferenceType over the lifetime of the mirrored object. + * The returned ReferenceType will be a ClassType or ArrayType and never + * an InterfaceType. + * Returns: the ReferenceType for this object. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes ThreadGroupReference object, + * and no ObjectCollectedException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.referenceType.referencetype003; + * the debuggee program - nsk.jdi.ObjectReference.referenceType.referencetype003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referenceType.referencetype003 + * nsk.jdi.ObjectReference.referenceType.referencetype003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referenceType.referencetype003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003a.java new file mode 100644 index 00000000000..3228256c39d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype003a.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.referenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the referencetype003 JDI test. + */ + +public class referencetype003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + private static ThreadGroup mainGroupObj = new ThreadGroup("mainthreadGroupName"); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.referenceType()
    + * complies with its spec when ObjectReference is ClassObjectReference.
    + *
    + * The test consequently checks up the following assersions:
    + * - the type may be a subclass or implementor of the declared type
    + * of any field or variable which currently holds it;
    + * - the returned ReferenceType will be a ClassType or ArrayType
    + * and never an InterfaceType;
    + * - the type of an object never changes, so this method will
    + * always return the same ReferenceType over the lifetime
    + * of the mirrored object.
    + */ + +public class referencetype004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/referenceType/referencetype004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new referencetype004().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.referenceType.referencetype004a"; + + private String className = + "nsk.jdi.ObjectReference.referenceType.referencetype004aTestClass"; + + private String testedClassName = "java.lang.Class"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = null; + + + classes = vm.classesByName(className); + testedClass = (ReferenceType) classes.get(0); + + ClassObjectReference classObjRef = testedClass.classObject(); + + log2("......ReferenceType testedClass = classObjRef.referenceType();"); + testedClass = classObjRef.referenceType(); + + + log2(".......check up on equality testedClass.name() to String testedClassName"); + if (!testedClass.name().equals(testedClassName)) { + log3("ERROR: check that the type may be a subclass or implementor of the declared type FAILED"); + log3("ERROR: String testedClassName : " + testedClassName); + log3("ERROR: performing statement : !testedClass.name().equals(testedClassName)"); + log3("ERROR: testedClass.name() : " + testedClass.name()); + testExitCode = FAILED; + } + + try { + log2(".......check up on cast to ClassType; no Exception expected"); + ClassType ct = (ClassType) testedClass; + } catch ( Exception e ) { + log3("ERROR: check that ReferenceType will be a ClassType FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: ClassType ct = (ClassType) testedClass;"); + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + + + log2(".......check up on equality ReferenceType classObjRef.referenceType() to testedClass"); + ReferenceType testedClass1 = classObjRef.referenceType(); + if (!testedClass1.equals(testedClass)) { + log3("ERROR: check that the method always return the same RefereneceType object FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: !classObjRef.referenceType().equals(testedClass)"); + log3("ERROR: returned ReferenceType : " + testedClass1); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004/TestDescription.java new file mode 100644 index 00000000000..7f3bcc418d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referenceType/referencetype004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.referenceType() + * complies with its spec: + * public ReferenceType referenceType() + * Gets the ReferenceType that mirrors the type of this object. + * The type may be a subclass or implementor of the declared type of + * any field or variable which currently holds it. + * For example, right after the following statement. + * Object obj = new String("Hello, world!"); + * The ReferenceType of obj will mirror java.lang.String and + * not java.lang.Object. + * The type of an object never changes, so this method will always return + * the same ReferenceType over the lifetime of the mirrored object. + * The returned ReferenceType will be a ClassType or ArrayType and never + * an InterfaceType. + * Returns: the ReferenceType for this object. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes ClassObjectReference object, + * and no ObjectCollectedException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.referenceType.referencetype004; + * the debuggee program - nsk.jdi.ObjectReference.referenceType.referencetype004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referenceType.referencetype004 + * nsk.jdi.ObjectReference.referenceType.referencetype004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referenceType.referencetype004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004a.java new file mode 100644 index 00000000000..f0886eac3a1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype004a.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.referenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the referencetype004 JDI test. + */ + +public class referencetype004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static referencetype004aTestClass obj = new referencetype004aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.referenceType()
    + * complies with its spec when ObjectReference is ArrayReference
    + * of ClassType.
    + *
    + * The test consequently checks up the following assersions:
    + * - the type may be a subclass or implementor of the declared type
    + * of any field or variable which currently holds it;
    + * - the returned ReferenceType will be a ClassType or ArrayType
    + * and never an InterfaceType;
    + * - the type of an object never changes, so this method will
    + * always return the same ReferenceType over the lifetime
    + * of the mirrored object.
    + */ + +public class referencetype005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/referenceType/referencetype005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new referencetype005().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.referenceType.referencetype005a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.referenceType.referencetype005aClassForCheck[]"; + + String mName = "nsk.jdi.ObjectReference.referenceType"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOftestedClasses = vm.classesByName(mName + ".referencetype005aTestClass"); + if (listOftestedClasses.size() != 1) { + log3("ERROR: listOftestedClasses.size() != 1"); + testExitCode = FAILED; + continue; + } + ReferenceType testedClass = + (ReferenceType) listOftestedClasses.get(0); + + Field fieldArray = testedClass.fieldByName("cfc"); + if (fieldArray == null) { + log3("ERROR: fieldArray == null"); + testExitCode = FAILED; + continue; + } + + ArrayReference arrayRef = (ArrayReference) testedClass.getValue(fieldArray); + + log2("......ReferenceType testedClass = arrayRef.referenceType();"); + testedClass = arrayRef.referenceType(); + + log2("...... check up on equality testedClass.name() to String testedClassName"); + if (!testedClass.name().equals(testedClassName)) { + log3("ERROR: check that the type may be a subclass or implementor of the declared type FAILED"); + log3("ERROR: String testedClassName : " + testedClassName); + log3("ERROR: performing statement : !testedClass.name().equals(testedClassName)"); + log3("ERROR: testedClass.name() : " + testedClass.name()); + testExitCode = FAILED; + } + + try { + log2(".......check up on cast to ArrayType; no Exception expected"); + ArrayType ct = (ArrayType) testedClass; + } catch ( Exception e ) { + log3("ERROR: check that ReferenceType will be a ArrayType FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: ArrayType ct = (ArrayType) testedClass;"); + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + + + log2(".......check up on equality ReferenceType arrayRef.referenceType() to testedClass"); + ReferenceType testedClass1 = arrayRef.referenceType(); + if (!testedClass1.equals(testedClass)) { + log3("ERROR: check that the method always return the same RefereneceType object FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: !arrayRef.referenceType().equals(testedClass)"); + log3("ERROR: returned ReferenceType : " + testedClass1); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005/TestDescription.java new file mode 100644 index 00000000000..5f9dbd373d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referenceType/referencetype005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.referenceType() + * complies with its spec: + * public ReferenceType referenceType() + * Gets the ReferenceType that mirrors the type of this object. + * The type may be a subclass or implementor of the declared type of + * any field or variable which currently holds it. + * For example, right after the following statement. + * Object obj = new String("Hello, world!"); + * The ReferenceType of obj will mirror java.lang.String and + * not java.lang.Object. + * The type of an object never changes, so this method will always return + * the same ReferenceType over the lifetime of the mirrored object. + * The returned ReferenceType will be a ClassType or ArrayType and never + * an InterfaceType. + * Returns: the ReferenceType for this object. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes Class type Array object, + * and no ObjectCollectedException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.referenceType.referencetype005; + * the debuggee program - nsk.jdi.ObjectReference.referenceType.referencetype005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referenceType.referencetype005 + * nsk.jdi.ObjectReference.referenceType.referencetype005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referenceType.referencetype005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005a.java new file mode 100644 index 00000000000..9f017011f75 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype005a.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2001, 2018, 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. + */ +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! templete parameters !!!! +// ObjectReference InterfaceName ObjectReference +// referenceType MethodName referenceType +// referencetype005 TestName referencetype005a +// ------------------------------------------------------ + +package nsk.jdi.ObjectReference.referenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the referencetype005 JDI test. + */ + +public class referencetype005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static referencetype005aTestClass obj = new referencetype005aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.referenceType()
    + * complies with its spec when ObjectReference is ArrayReference
    + * of InterfaceType.
    + *
    + * The test consequently checks up the following assersions:
    + * - the type may be a subclass or implementor of the declared type
    + * of any field or variable which currently holds it;
    + * - the returned ReferenceType will be a ClassType or ArrayType
    + * and never an InterfaceType;
    + * - the type of an object never changes, so this method will
    + * always return the same ReferenceType over the lifetime
    + * of the mirrored object.
    + */ + +public class referencetype006 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/referenceType/referencetype006 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new referencetype006().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.referenceType.referencetype006a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.referenceType.referencetype006aInterfaceForCheck[]"; + + String mName = "nsk.jdi.ObjectReference.referenceType"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOftestedClasses = vm.classesByName(mName + ".referencetype006aTestClass"); + if (listOftestedClasses.size() != 1) { + log3("ERROR: listOftestedClasses.size() != 1"); + testExitCode = FAILED; + continue; + } + ReferenceType testedClass = + (ReferenceType) listOftestedClasses.get(0); + + Field fieldArray = testedClass.fieldByName("iface"); + if (fieldArray == null) { + log3("ERROR: fieldArray == null"); + testExitCode = FAILED; + continue; + } + + ArrayReference arrayRef = (ArrayReference) testedClass.getValue(fieldArray); + + log2("......ReferenceType testedClass = arrayRef.referenceType();"); + testedClass = arrayRef.referenceType(); + + + log2("...... check up on equality testedClass.name() to String testedClassName"); + if (!testedClass.name().equals(testedClassName)) { + log3("ERROR: check that the type may be a subclass or implementor of the declared type FAILED"); + log3("ERROR: String testedClassName : " + testedClassName); + log3("ERROR: performing statement : !testedClass.name().equals(testedClassName)"); + log3("ERROR: testedClass.name() : " + testedClass.name()); + testExitCode = FAILED; + } + + try { + log2(".......check up on cast to ArrayType; no Exception expected"); + ArrayType ct = (ArrayType) testedClass; + } catch ( Exception e ) { + log3("ERROR: check that ReferenceType will be a ArrayType FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: ArrayType ct = (ArrayType) testedClass;"); + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + + + log2(".......check up on equality ReferenceType arrayRef.referenceType() to testedClass"); + ReferenceType testedClass1 = arrayRef.referenceType(); + if (!testedClass1.equals(testedClass)) { + log3("ERROR: check that the method always return the same RefereneceType object FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: !arrayRef.referenceType().equals(testedClass)"); + log3("ERROR: returned ReferenceType : " + testedClass1); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006/TestDescription.java new file mode 100644 index 00000000000..95d1241011a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referenceType/referencetype006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.referenceType() + * complies with its spec: + * public ReferenceType referenceType() + * Gets the ReferenceType that mirrors the type of this object. + * The type may be a subclass or implementor of the declared type of + * any field or variable which currently holds it. + * For example, right after the following statement. + * Object obj = new String("Hello, world!"); + * The ReferenceType of obj will mirror java.lang.String and + * not java.lang.Object. + * The type of an object never changes, so this method will always return + * the same ReferenceType over the lifetime of the mirrored object. + * The returned ReferenceType will be a ClassType or ArrayType and never + * an InterfaceType. + * Returns: the ReferenceType for this object. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes Interface type Array object, + * and no ObjectCollectedException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.referenceType.referencetype006; + * the debuggee program - nsk.jdi.ObjectReference.referenceType.referencetype006a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referenceType.referencetype006 + * nsk.jdi.ObjectReference.referenceType.referencetype006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referenceType.referencetype006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006a.java new file mode 100644 index 00000000000..33225a0bdba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype006a.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.referenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the referencetype006 JDI test. + */ + +public class referencetype006a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static referencetype006aTestClass obj = new referencetype006aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.referenceType()
    + * complies with its spec when ObjectReference is ArrayReference
    + * of primitive type.
    + *
    + * The test consequently checks up the following assersions:
    + * - the type may be a subclass or implementor of the declared type
    + * of any field or variable which currently holds it;
    + * - the returned ReferenceType will be a ClassType or ArrayType
    + * and never an InterfaceType;
    + * - the type of an object never changes, so this method will
    + * always return the same ReferenceType over the lifetime
    + * of the mirrored object.
    + */ + +public class referencetype007 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/referenceType/referencetype007 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new referencetype007().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.referenceType.referencetype007a"; + + private String testedClassName = "boolean[][]"; + + String mName = "nsk.jdi.ObjectReference.referenceType"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOftestedClasses = vm.classesByName(mName + ".referencetype007aTestClass"); + if (listOftestedClasses.size() != 1) { + log3("ERROR: listOftestedClasses.size() != 1"); + testExitCode = FAILED; + continue; + } + ReferenceType testedClass = + (ReferenceType) listOftestedClasses.get(0); + + Field fieldArray = testedClass.fieldByName("a2"); + if (fieldArray == null) { + log3("ERROR: fieldArray == null"); + testExitCode = FAILED; + continue; + } + + + ArrayReference arrayRef = (ArrayReference) testedClass.getValue(fieldArray); + + log2("......ReferenceType testedClass = arrayRef.referenceType();"); + testedClass = arrayRef.referenceType(); + + log2("...... check up on equality testedClass.name() to String testedClassName"); + if (!testedClass.name().equals(testedClassName)) { + log3("ERROR: check that the type may be a subclass or implementor of the declared type FAILED"); + log3("ERROR: String testedClassName : " + testedClassName); + log3("ERROR: performing statement : !testedClass.name().equals(testedClassName)"); + log3("ERROR: testedClass.name() : " + testedClass.name()); + testExitCode = FAILED; + } + + try { + log2(".......check up on cast to ArrayType; no Exception expected"); + ArrayType ct = (ArrayType) testedClass; + } catch ( Exception e ) { + log3("ERROR: check that ReferenceType will be a ArrayType FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: ArrayType ct = (ArrayType) testedClass;"); + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + + + log2(".......check up on equality ReferenceType arrayRef.referenceType() to testedClass"); + ReferenceType testedClass1 = arrayRef.referenceType(); + if (!testedClass1.equals(testedClass)) { + log3("ERROR: check that the method always return the same RefereneceType object FAILED"); + log3("ERROR: ReferenceType testedClass is of the type : " + testedClass); + log3("ERROR: performing statement: !arrayRef.referenceType().equals(testedClass)"); + log3("ERROR: returned ReferenceType : " + testedClass1); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007/TestDescription.java new file mode 100644 index 00000000000..1f81fde500a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referenceType/referencetype007. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.referenceType() + * complies with its spec: + * public ReferenceType referenceType() + * Gets the ReferenceType that mirrors the type of this object. + * The type may be a subclass or implementor of the declared type of + * any field or variable which currently holds it. + * For example, right after the following statement. + * Object obj = new String("Hello, world!"); + * The ReferenceType of obj will mirror java.lang.String and + * not java.lang.Object. + * The type of an object never changes, so this method will always return + * the same ReferenceType over the lifetime of the mirrored object. + * The returned ReferenceType will be a ClassType or ArrayType and never + * an InterfaceType. + * Returns: the ReferenceType for this object. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes primitive type Array object, + * and no ObjectCollectedException is expected. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.referenceType.referencetype007; + * the debuggee program - nsk.jdi.ObjectReference.referenceType.referencetype007a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referenceType.referencetype007 + * nsk.jdi.ObjectReference.referenceType.referencetype007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referenceType.referencetype007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007a.java new file mode 100644 index 00000000000..658247403cd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referenceType/referencetype007a.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.referenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the referencetype007 JDI test. + */ + +public class referencetype007a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static referencetype007aTestClass obj = new referencetype007aTestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * do + * - initiate creation of referring objects of type 'refererence_type' + * - check the number of referrers and instances is correct + * - initiate deletion of some referreres(making them unreachable) + * - check the number of referrers and instances is correct + * done + * - Debugger VM + * create references of all possible types to single object, ObjectReference.referringObjects should return only + * referrers with supported type(Strong, PhantomReference, SoftReference, WeakReference) + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referringObjects.referringObjects001.referringObjects001 + * nsk.share.jdi.TestClass1 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referringObjects.referringObjects001.referringObjects001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ObjectReference.referringObjects.referringObjects001; + +import java.io.PrintStream; +import java.util.*; + +import nsk.share.*; +import nsk.share.jdi.*; + + +import com.sun.jdi.*; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class referringObjects001 extends HeapwalkingDebugger { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new referringObjects001().runIt(argv, out); + } + + protected String debuggeeClassName() { + return nsk.share.jdi.HeapwalkingDebuggee.class.getName(); + } + + // test given class with all references types + protected void testClass(String className) { + log.display("Test ObjectReference for class: " + className); + + // force GC in debuggee VM to avoid collection of weak references during test execution + forceGC(); + + for (String referrerType : ObjectInstancesManager.allReferenceTypes) { + testReferrerType(referrerType, className); + if (ObjectInstancesManager.isWeak(referrerType)) { + resetStatusIfGC(); + } + } + + int createInstanceCount = 10; + List objectsToFilter = getObjectReferences(className, vm); + + // create instances reachable via all types of references + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_ALL_TYPE_REFERENCES + ":" + className + ":" + createInstanceCount); + + if (!isDebuggeeReady()) + return; + + // ObjectReference.referringObjects should include only supported types of references + checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, createInstanceCount, true, + HeapwalkingDebuggee.includedIntoReferrersCountTypes.size()); + + for (int i = 0; i < ObjectInstancesManager.allReferenceTypes.size(); i++) { + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_REFERRERS + ":" + className + ":" + 1); + + if (!isDebuggeeReady()) + return; + } + } + + + protected void testReferrerType(String referrerType, String className) { + // can't check number of referrers for objects that was created in debugee VM + // before debugger command (for example primitive type arrays), so we should filter such objects + List objectsToFilter = HeapwalkingDebugger.getObjectReferences(className, vm); + + boolean includedInReferrersCount = HeapwalkingDebuggee.isIncludedIntoReferrersCount(referrerType); + boolean includedInInstancesCount = HeapwalkingDebuggee.isIncludedIntoInstancesCount(referrerType); + + int createInstanceCount = 4; + int referrerCount = 10; + + // create 'createInstanceCount' instances with 'referrerCount' referrers + + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + className + ":" + createInstanceCount + ":" + referrerCount + ":" + + referrerType); + + int expectedInstanceCount; + + if (includedInInstancesCount) + expectedInstanceCount = createInstanceCount; + else + expectedInstanceCount = 0; + + checkDebugeeAnswer_instanceCounts(className, expectedInstanceCount, objectsToFilter); + checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, expectedInstanceCount, includedInReferrersCount, referrerCount); + + // delete half of referrers + + int deleteCount = referrerCount / 2; + + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_REFERRERS + ":" + className + ":" + deleteCount); + + referrerCount -= deleteCount; + + if (includedInInstancesCount) + expectedInstanceCount = createInstanceCount; + else + expectedInstanceCount = 0; + + checkDebugeeAnswer_instanceCounts(className, expectedInstanceCount, objectsToFilter); + checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, expectedInstanceCount, includedInReferrersCount, referrerCount); + + // delete half of instances + + deleteCount = createInstanceCount / 2; + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + className + ":" + deleteCount); + + createInstanceCount -= deleteCount; + + if (includedInInstancesCount) + expectedInstanceCount = createInstanceCount; + else + expectedInstanceCount = 0; + + checkDebugeeAnswer_instanceCounts(className, expectedInstanceCount, objectsToFilter); + checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, expectedInstanceCount, includedInReferrersCount, referrerCount); + + // delete all referrers (make object unreachable) + + deleteCount = referrerCount; + + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_REFERRERS + ":" + className + ":" + deleteCount); + + referrerCount = 0; + createInstanceCount = 0; + + expectedInstanceCount = 0; + + checkDebugeeAnswer_instanceCounts(className, expectedInstanceCount, objectsToFilter); + checkDebugeeAnswer_instances_referringObjects(objectsToFilter, className, expectedInstanceCount, includedInReferrersCount, referrerCount); + } + + protected void checkDebugeeAnswer_instances_referringObjects(List objectsToFilter, String className, int expectedInstances, + boolean checkReferrers, int expectedReferrers) { + try { + ReferenceType referenceType = debuggee.classByName(className); + + if (checkReferrers) { + List objectReferrences = HeapwalkingDebugger.filterObjectReferrence(objectsToFilter, referenceType.instances(0)); + + // used for non-strict check + int correctObjectsFound = 0; + + for (ObjectReference objectReference : objectReferrences) { + int referrerCount = objectReference.referringObjects(0).size(); + + if (strictCheck(className)) { + if (referrerCount != expectedReferrers) { + setSuccess(false); + log.complain("List with wrong size was returned by ObjectReference.referringObjects: " + referrerCount + ", expected: " + + expectedReferrers); + } + } else { + if (referrerCount == expectedReferrers) { + correctObjectsFound++; + } + } + } + + if (!strictCheck(className)) { + if (correctObjectsFound != expectedInstances) { + setSuccess(false); + log.complain("List with wrong size was returned by ObjectReference.referringObjects, expected: " + expectedReferrers); + } + } + } + } catch (Throwable t) { + log.complain("Unexpected exception:"); + t.printStackTrace(log.getOutStream()); + } + } + + protected void doTest() { + String[] testClassNames = { "java.lang.String", "nsk.share.jdi.TestClass1", "boolean[]", + "float[]" }; + + for (String className : testClassNames) { + testClass(className); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java new file mode 100644 index 00000000000..df9d745d8cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referringObjects/referringObjects002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test check behaviour of ObjectReference.referringObjects, ObjectReference.disableCollection and + * ObjectReference.enableCollection for ClassObjectReference + * The test scenario is following: + * - Debugger VM + * - initiate in target VM loading of test class: + * - Debugee VM + * - create several instances of loaded class + * - create references of all possible types to loaded class + * - Debugger VM + * - check test class have correct number of referrers + * (class object referrers should include class instances and references with supported types: Strong, PhantomReference, SoftReference, WeakReference) + * - Debugger VM + * - initiate in debuggee removing of class instances and class object references + * - check test class have correct number of referrers + * - Debugger VM + * - prevent collection of class object using ObjectReference.disableCollection + * - initiate test class unloading in debugee VM + * - check class object was not collected + * - enable collection of class object using ObjectReference.enableCollection + * - check class object was collected + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referringObjects.referringObjects002.referringObjects002 + * nsk.jdi.ObjectReference.referringObjects.referringObjects002.referringObjects002a + * nsk.share.jdi.TestClass1 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referringObjects.referringObjects002.referringObjects002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + */ + +package nsk.jdi.ObjectReference.referringObjects.referringObjects002; + +import java.io.PrintStream; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdi.HeapwalkingDebugger; + +public class referringObjects002 extends HeapwalkingDebugger { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new referringObjects002().runIt(argv, out); + } + + protected String debuggeeClassName() { + if (classpath == null) { + throw new TestBug("Debugger requires 'testClassPath' parameter"); + } + + return nsk.jdi.ObjectReference.referringObjects.referringObjects002.referringObjects002a.class.getName() + + " -testClassPath " + classpath; + } + + public void checkClassObjectReferrersCount(ClassObjectReference classObjectReference, int expectedCount) { + int referrersCount = classObjectReference.referringObjects(0).size(); + + if (referrersCount != expectedCount) { + setSuccess(false); + log.complain("Unexpected size of ClassLoaderReference.referringObjects: " + referrersCount + ", expected: " + expectedCount); + } + } + + protected void doTest() { + String className = "nsk.share.jdi.TestClass1"; + + int createInstances = 10; + + pipe.println(HeapwalkingDebuggee.COMMAND_LOAD_CLASS + ":" + className + ":" + createInstances); + + if (!isDebuggeeReady()) + return; + + // each class instances has reference to class object + + // + 'includedIntoReferrersCountTypes.size()' referrers was additionally created + // +1 referrer is classloader + // +1 referrer is debugee class unloader + int expectedReferrersCount = createInstances + HeapwalkingDebuggee.includedIntoReferrersCountTypes.size() + 2; + + ClassObjectReference classObjectReference = debuggee.classByName(className).classObject(); + + checkClassObjectReferrersCount(classObjectReference, expectedReferrersCount); + + pipe.println(referringObjects002a.COMMAND_DELETE_CLASS_OBJECT_REFERRERS); + + if (!isDebuggeeReady()) + return; + + // Only this referrers should left: + // 1 referrer is classloader + // 1 referrer is debugee class unloader + expectedReferrersCount = 2; + + checkClassObjectReferrersCount(classObjectReference, expectedReferrersCount); + + // disable collection and try unload class object + classObjectReference.disableCollection(); + + pipe.println(HeapwalkingDebuggee.COMMAND_UNLOAD_CLASS + ":" + className + ":" + HeapwalkingDebuggee.UNLOAD_RESULT_FALSE); + + if (!isDebuggeeReady()) + return; + + try { + classObjectReference.referringObjects(0); + } catch (ObjectCollectedException e) { + setSuccess(false); + log.complain("Class object was collected after disableCollection"); + return; + } + + // enable collection and try unload class object + classObjectReference.enableCollection(); + + pipe.println(HeapwalkingDebuggee.COMMAND_UNLOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + try { + classObjectReference.referringObjects(0); + } catch (ObjectCollectedException expectedException) { + // expected exception + return; + } + + setSuccess(false); + log.complain("Class object was not collected after enableCollection"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002a.java new file mode 100644 index 00000000000..1e90e159b58 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ObjectReference.referringObjects.referringObjects002; + +import nsk.share.ClassUnloader; +import nsk.share.ObjectInstancesManager; +import nsk.share.ReferringObject; +import nsk.share.TestBug; +import nsk.share.jdi.HeapwalkingDebuggee; +import java.io.*; +import java.util.*; + +/* + * Class create and save given number of class instances + */ +class Instances { + Instances(Class klass, int instanceCount) { + try { + for (int i = 0; i < instanceCount; i++) + instances.add(klass.newInstance()); + } catch (Throwable t) { + throw new TestBug("Unexpected error during test class instantiation: " + t); + } + } + + private List instances = new ArrayList(); +} + +/* + * Debuggee class handle request for loading classes with custom classloader and creating class instances + */ +public class referringObjects002a extends HeapwalkingDebuggee { + private Map classesInstances = new HashMap(); + + private List classReferrers = new ArrayList(); + + final static public String COMMAND_DELETE_CLASS_OBJECT_REFERRERS = "deleteClassObjectReferrers"; + + public static void main(String args[]) { + new referringObjects002a().doTest(args); + } + + // create references of all possible types to class object + public void createClassObjectReferrers(String className, int instanceCount) { + ClassUnloader unloader = loadedClasses.get(className); + + if (unloader == null) + throw new TestBug("Unloader is null for class: " + className); + + Class klass = unloader.getLoadedClass(); + + if (klass == null) + throw new TestBug("Unloader return null class object, for classname: " + className); + + classesInstances.put(className, new Instances(klass, instanceCount)); + + for (String referenceType : ObjectInstancesManager.allReferenceTypes) + classReferrers.add(new ReferringObject(klass, referenceType)); + } + + // delete all created references to class object + public void deleteClassObjectReferrers() { + classesInstances = null; + + for (ReferringObject referrer : classReferrers) + referrer.delete(); + + classReferrers.clear(); + } + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) { + // need do some additional actions for COMMAND_LOAD_CLASS + if (!command.startsWith(COMMAND_LOAD_CLASS)) + return true; + } + + try { + StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command)); + tokenizer.whitespaceChars(':', ':'); + + if (command.startsWith(COMMAND_LOAD_CLASS)) { + tokenizer.nextToken(); + + if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) + throw new IllegalArgumentException("Invalid command format"); + + String className = tokenizer.sval; + + if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) + throw new IllegalArgumentException("Invalid command format"); + + int instanceCount = (int) tokenizer.nval; + + createClassObjectReferrers(className, instanceCount); + + return true; + } else if (command.equals(COMMAND_DELETE_CLASS_OBJECT_REFERRERS)) { + deleteClassObjectReferrers(); + + return true; + } + } catch (IOException e) { + throw new TestBug("Invalid command format: " + command); + } + + return false; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java new file mode 100644 index 00000000000..dcced7f9a6d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referringObjects/referringObjects003. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test check behaviour of ObjectReference.referringObjects for ThreadReference and ThreadGroupReference + * and ObjectReference.disableCollection/ObjectReference.enableCollection for ThreadGroupReference + * The test scenario is following: + * - Debugger VM + * - initiate in target VM thread execution: + * - Debugee VM + * - start several threads included in thread group + * - create references of all possible types to all started threads and thread group + * - Debugger VM + * - check that threads and thread group have correct number of referrers: + * (thread referrers should include thread group and references with supported types, + * thread group referrers should include group's threads, parent thread group and references with supported types) + * - Debugger VM + * - initiate in target VM thread stop: + * - Debugee VM + * - stop all threads and remove all references to threads and thread group + * - Debugger VM + * - check that thread group have only 1 referrer: parent thread group + * - check that threre are no references to test threads in target VM + * - Debugger VM + * - test ObjectReference.disableCollection, ObjectReference.enableCollection for ThreadGroupReference: + * can't force collection of thread group because of thread group always has 1 referrer - parent thread group, so + * just test disableCollection/enableCollection don't throw any unexpected exceptions + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 + * nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003a + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ObjectReference.referringObjects.referringObjects003; + +import java.io.PrintStream; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdi.HeapwalkingDebugger; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class referringObjects003 extends HeapwalkingDebugger { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new referringObjects003().runIt(argv, out); + } + + protected String debuggeeClassName() { + return "nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003a"; + } + + // check ObjectReference type and number of referrers + public void checkThreadGroupReferrersCount(List objectReferences, int expectedCount) { + for (ObjectReference objectReference : objectReferences) { + if (!(objectReference instanceof ThreadGroupReference)) { + setSuccess(false); + log.complain("Unexpected type of ObjectReference: " + objectReference.getClass().getName() + + ", expected ThreadGroupReference"); + } + + int referrerCount = objectReference.referringObjects(0).size(); + + if (referrerCount != expectedCount) { + setSuccess(false); + log + .complain("List with wrong size was returned by ObjectReference.referringObjects(ThreadGroupReference): " + + referrerCount + ", expected: " + expectedCount); + } + } + } + + // check ObjectReference type and number of referrers + public void checkThreadReferrersCount(List objectReferences, int expectedCount) { + for (ObjectReference objectReference : objectReferences) { + if (!(objectReference instanceof ThreadReference)) { + setSuccess(false); + log.complain("Unexpected type of ObjectReference: " + objectReference.getClass().getName() + + ", expected ThreadReference"); + } + + if (((ThreadReference)objectReference).name().contains("Test thread") == false) + continue; + + int referrerCount = objectReference.referringObjects(0).size(); + + if (referrerCount != expectedCount) { + setSuccess(false); + log.complain("List with wrong size was returned by ObjectReference.referringObjects(ThreadReferrence): " + + referrerCount + ", expected: " + expectedCount); + } + } + } + + public void doTest() { + int threadCount = 15; + + // threads and thread groups loaded before debugger command should be + // filtered + List threadGroupsToFilter = HeapwalkingDebugger.getObjectReferences( + "java.lang.ThreadGroup", + vm); + List threadsToFilter = HeapwalkingDebugger.getObjectReferences("java.lang.Thread", vm); + + pipe.println(referringObjects003a.COMMAND_START_THREADS + ":" + threadCount); + + if (!isDebuggeeReady()) + return; + + // check instance count + checkDebugeeAnswer_instances("java.lang.ThreadGroup", threadGroupsToFilter.size() + 1); + checkDebugeeAnswer_instances("java.lang.Thread", threadsToFilter.size() + threadCount); + + List threadGroups = HeapwalkingDebugger.filterObjectReferrence( + threadGroupsToFilter, + HeapwalkingDebugger.getObjectReferences("java.lang.ThreadGroup", vm)); + + // thread group has 'threadCount' referrers + 1 referrer is parent + // thread group + // + 'includedIntoReferrersCountTypes.size()' referrers was additionally + // created + int expectedCount = threadCount + 1 + HeapwalkingDebuggee.includedIntoReferrersCountTypes.size(); + + checkThreadGroupReferrersCount(threadGroups, expectedCount); + + List threads = HeapwalkingDebugger.filterObjectReferrence(threadsToFilter, HeapwalkingDebugger + .getObjectReferences("java.lang.Thread", vm)); + + expectedCount = 2 + HeapwalkingDebuggee.includedIntoReferrersCountTypes.size(); + + // 1 referrer is debugee object + 1 referrer is thread group + // + 'includedIntoReferrersCountTypes.size()' referrers was additionally + // created + checkThreadReferrersCount(threads, expectedCount); + + pipe.println(referringObjects003a.COMMAND_STOP_THREADS); + + if (!isDebuggeeReady()) + return; + + checkDebugeeAnswer_instances("java.lang.ThreadGroup", threadGroupsToFilter.size() + 1); + checkDebugeeAnswer_instances("java.lang.Thread", threadsToFilter.size()); + + threadGroups = HeapwalkingDebugger.filterObjectReferrence(threadGroupsToFilter, HeapwalkingDebugger + .getObjectReferences("java.lang.ThreadGroup", vm)); + + // 1 referrer(parent thread group) is left + checkThreadGroupReferrersCount(threadGroups, 1); + + threads = HeapwalkingDebugger.filterObjectReferrence(threadsToFilter, HeapwalkingDebugger.getObjectReferences( + "java.lang.Thread", + vm)); + + if (threads.size() != 0) { + log.complain("All test threads should be removed"); + log.complain("Unexpected threads:"); + for (ObjectReference objectReference : threads) { + log.complain(objectReference.toString()); + } + } + + checkThreadGroupDisableCollection(threadGroups); + } + + // can't force collection of thread group because of 1 reference is always + // left in parent tread group + public void checkThreadGroupDisableCollection(List objectReferences) { + try { + for (ObjectReference objectReference : objectReferences) + objectReference.disableCollection(); + } catch (Throwable t) { + log.complain("Unexpected exception: " + t); + t.printStackTrace(log.getOutStream()); + } + + forceGC(); + try { + for (ObjectReference objectReference : objectReferences) + objectReference.enableCollection(); + } catch (Throwable t) { + log.complain("Unexpected exception: " + t); + t.printStackTrace(log.getOutStream()); + } + + forceGC(); + try { + for (ObjectReference objectReference : objectReferences) + objectReference.referringObjects(0); + } catch (Throwable t) { + log.complain("Unexpected exception: " + t); + t.printStackTrace(log.getOutStream()); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003a.java new file mode 100644 index 00000000000..694bf62ee4b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ObjectReference.referringObjects.referringObjects003; + +import java.io.*; +import java.util.*; +import nsk.share.*; +import nsk.share.jdi.HeapwalkingDebuggee; + +/* + * Test class handle request for start/stop test threads(threads are included in special thread group) + */ +public class referringObjects003a extends HeapwalkingDebuggee { + class TestThread implements Runnable { + public void run() { + wicket.waitFor(); + } + } + + private Wicket wicket = new Wicket(); + + private List threads = new ArrayList(); + + private List referrers; + + public static final String COMMAND_START_THREADS = "startThreads"; + + public static final String COMMAND_STOP_THREADS = "stopThreads"; + + public static void main(String args[]) { + new referringObjects003a().doTest(args); + } + + private void addAllTypeReferernces(Object object) { + for (String referenceType : ObjectInstancesManager.allReferenceTypes) + referrers.add(new ReferringObject(object, referenceType)); + } + + public void startThreads(int threadCount) { + referrers = new ArrayList(); + + ThreadGroup threadGroup = new ThreadGroup("Test thread group"); + addAllTypeReferernces(threadGroup); + + for (int i = 0; i < threadCount; i++) { + Thread testThread = new Thread(threadGroup, new TestThread(), "Test thread " + i); + threads.add(testThread); + addAllTypeReferernces(testThread); + testThread.start(); + } + } + + public void stopThreads() { + wicket.unlockAll(); + + for (Thread testThread : threads) { + try { + testThread.join(); + } catch (InterruptedException e) { + log.display("Main thread was unexpected interrupted"); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + } + + for (ReferringObject referringObject : referrers) + referringObject.delete(); + + threads = null; + } + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + try { + StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command)); + tokenizer.whitespaceChars(':', ':'); + + if (command.startsWith(COMMAND_START_THREADS)) { + tokenizer.nextToken(); + + if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) + throw new IllegalArgumentException("Invalid command format"); + + int threadCount = (int) tokenizer.nval; + + startThreads(threadCount); + + return true; + } else if (command.equals(COMMAND_STOP_THREADS)) { + stopThreads(); + + return true; + } + + } catch (IOException e) { + throw new TestBug("Invalid command format: " + command); + } + + return false; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects004/referringObjects004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects004/referringObjects004.java new file mode 100644 index 00000000000..24b4d6e0d35 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects004/referringObjects004.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/referringObjects/referringObjects004. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test checks behavior of ObjectReference.referringObjects() in case when there are + * many (several thousands) referring objects for corresponding ObjectReference. + * Debugger forces debuggee create instance of 'nsk.share.jdi.TestClass1' with 100000 (this value can be changed through parameter -referrerCount) + * referrers, obtains ObjectReference for this instance and checks that ObjectReference.referringObjects() + * returns collection with correct size and returned instances doesn't throw any exception when call following methods: + * referenceType() + * isCollected() + * uniqueID() + * hashCode() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.referringObjects.referringObjects004.referringObjects004 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ObjectReference.referringObjects.referringObjects004.referringObjects004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ObjectReference.referringObjects.referringObjects004; + +import java.io.PrintStream; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.ObjectInstancesManager; +import nsk.share.ReferringObject; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdi.HeapwalkingDebugger; +import nsk.share.jdi.TestClass1; + +public class referringObjects004 extends HeapwalkingDebugger { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new referringObjects004().runIt(argv, out); + } + + protected String debuggeeClassName() { + return HeapwalkingDebuggee.class.getName(); + } + + private int referrerCount = 100000; + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-referrerCount") && (i < args.length - 1)) { + referrerCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + public void doTest() { + String className = TestClass1.class.getName(); + + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + className + ":" + 1 + ":" + referrerCount + + ":" + ObjectInstancesManager.STRONG_REFERENCE); + + if (!isDebuggeeReady()) + return; + + ObjectReference objectReference = findSingleObjectReference(className); + + if (objectReference.referringObjects(0).size() != referrerCount) { + setSuccess(false); + log.complain("List with wrong size was returned by ObjectReference.referringObjects: " + + objectReference.referringObjects(0).size() + ", expected: " + referrerCount); + } + + List referrers = objectReference.referringObjects(0); + + ReferenceType referrerReferenceType = debuggee.classByName(ReferringObject.class.getName()); + + vm.suspend(); + + for (ObjectReference referrer : referrers) { + try { + if (!referrerReferenceType.equals(referrer.referenceType())) { + setSuccess(false); + log.complain("Referrer's ReferenceType " + referrer.referenceType() + " doesn't equal " + + referrerReferenceType); + } + if (referrer.isCollected()) { + setSuccess(false); + log.complain("isCollected() returns 'true' for " + referrer); + } + referrer.uniqueID(); + referrer.hashCode(); + } catch (Throwable t) { + setSuccess(false); + t.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + t); + } + } + + vm.resume(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001.java new file mode 100644 index 00000000000..a8d975b14b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001.java @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.setValue()
    + * complies with its specification.
    + * The cases for testing include values of class and instance
    + * variables of primitive types each.
    + * No Exception is expected to be thrown.
    + */ + +public class setvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/setValue/setvalue001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.setValue.setvalue001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.setValue.TestClass"; + + //String mName = "nsk.jdi.ObjectReference.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String testObjName = "obj"; + + ReferenceType testedClass = null; + ReferenceType debuggeeClass = null; + ObjectReference objRef = null; + + List classes = null; + + classes = vm.classesByName(debuggeeName); + debuggeeClass = (ReferenceType) classes.get(0); + + objRef = (ObjectReference) + debuggeeClass.getValue(debuggeeClass.fieldByName(testObjName)); + + classes = vm.classesByName(testedClassName); + testedClass = (ReferenceType) classes.get(0); + + + Field fsbl1 = testedClass.fieldByName("bl1"); + Field fsbt1 = testedClass.fieldByName("bt1"); + Field fsch1 = testedClass.fieldByName("ch1"); + Field fsdb1 = testedClass.fieldByName("db1"); + Field fsfl1 = testedClass.fieldByName("fl1"); + Field fsin1 = testedClass.fieldByName("in1"); + Field fsln1 = testedClass.fieldByName("ln1"); + Field fssh1 = testedClass.fieldByName("sh1"); + + Field fsbl2 = testedClass.fieldByName("bl2"); + Field fsbt2 = testedClass.fieldByName("bt2"); + Field fsch2 = testedClass.fieldByName("ch2"); + Field fsdb2 = testedClass.fieldByName("db2"); + Field fsfl2 = testedClass.fieldByName("fl2"); + Field fsin2 = testedClass.fieldByName("in2"); + Field fsln2 = testedClass.fieldByName("ln2"); + Field fssh2 = testedClass.fieldByName("sh2"); + + + log2("......loop of checks on each primitive type by performing statements like first ones:"); + log2(" BooleanValue blv1 = (BooleanValue) objRef.getValue(fsbl1);"); + log2(" BooleanValue blv2 = (BooleanValue) objRef.getValue(fsbl2);"); + log2(" boolean bl1 = blv1.value();"); + log2(" boolean bl2 = blv2.value();"); + log2(" objRef.setValue(fsbl1, blv2);"); + log2(" objRef.setValue(fsbl2, blv1);"); + log2(" blv1 = (BooleanValue) objRef.getValue(fsbl1);"); + log2(" if (blv1.value() != false) {"); + log2(" log3('ERROR: getValue(fsbl1) != false');"); + log2(" }"); + log2(" blv2 = (BooleanValue) objRef.getValue(fsbl2);"); + log2(" if (blv2.value() != true) {"); + log2(" log3('ERROR: getValue(fsbl2) != true');"); + log2(" }"); + + for ( int i3 = 0; i3 < 8; i3++) { + + try { + + switch (i3) { + + case 0: + log2(" checking up on boolean"); + + BooleanValue blv1 = (BooleanValue) objRef.getValue(fsbl1); + BooleanValue blv2 = (BooleanValue) objRef.getValue(fsbl2); + + boolean bl1 = blv1.value(); + boolean bl2 = blv2.value(); + + objRef.setValue(fsbl1, blv2); + objRef.setValue(fsbl2, blv1); + + blv1 = (BooleanValue) objRef.getValue(fsbl1); + if (blv1.value() != bl2) { + log3("ERROR: getValue(fsbl1) != bl2"); + testExitCode = FAILED; + } + blv2 = (BooleanValue) objRef.getValue(fsbl2); + if (blv2.value() != bl1) { + log3("ERROR: getValue(fsbl2) != bl1"); + testExitCode = FAILED; + } + break; + + case 1: + log2(" checking up on byte"); + + ByteValue btv1 = (ByteValue) objRef.getValue(fsbt1); + ByteValue btv2 = (ByteValue) objRef.getValue(fsbt2); + + byte bt1 = btv1.value(); + byte bt2 = btv2.value(); + + objRef.setValue(fsbt1, btv2); + objRef.setValue(fsbt2, btv1); + + btv1 = (ByteValue) objRef.getValue(fsbt1); + if (btv1.value() != bt2) { + log3("ERROR: getValue(fsbt1) != bt2"); + testExitCode = FAILED; + } + btv2 = (ByteValue) objRef.getValue(fsbt2); + if (btv2.value() != bt1) { + log3("ERROR: getValue(fsbt2) != bt1"); + testExitCode = FAILED; + } + break; + + case 2: + log2(" checking up on char"); + + CharValue chv1 = (CharValue) objRef.getValue(fsch1); + CharValue chv2 = (CharValue) objRef.getValue(fsch2); + + char ch1 = chv1.value(); + char ch2 = chv2.value(); + + objRef.setValue(fsch1, chv2); + objRef.setValue(fsch2, chv1); + + chv1 = (CharValue) objRef.getValue(fsch1); + if (chv1.value() != ch2) { + log3("ERROR: getValue(fsch1) != ch2"); + testExitCode = FAILED; + } + chv2 = (CharValue) objRef.getValue(fsch2); + if (chv2.value() != ch1) { + log3("ERROR: getValue(fsch2) != ch1"); + testExitCode = FAILED; + } + break; + + case 3: + log2(" checking up on double"); + + DoubleValue dbv1 = (DoubleValue) objRef.getValue(fsdb1); + DoubleValue dbv2 = (DoubleValue) objRef.getValue(fsdb2); + + double db1 = dbv1.value(); + double db2 = dbv2.value(); + + objRef.setValue(fsdb1, dbv2); + objRef.setValue(fsdb2, dbv1); + + dbv1 = (DoubleValue) objRef.getValue(fsdb1); + if (dbv1.value() != db2) { + log3("ERROR: getValue(fsdb1) != db2"); + testExitCode = FAILED; + } + dbv2 = (DoubleValue) objRef.getValue(fsdb2); + if (dbv2.value() != db1) { + log3("ERROR: getValue(fsdb2) != db1"); + testExitCode = FAILED; + } + break; + + case 4: + log2(" checking up on float"); + + FloatValue flv1 = (FloatValue) objRef.getValue(fsfl1); + FloatValue flv2 = (FloatValue) objRef.getValue(fsfl2); + + float fl1 = flv1.value(); + float fl2 = flv2.value(); + + objRef.setValue(fsfl1, flv2); + objRef.setValue(fsfl2, flv1); + + flv1 = (FloatValue) objRef.getValue(fsfl1); + if (flv1.value() != fl2) { + log3("ERROR: getValue(fsfl1) != fl2"); + testExitCode = FAILED; + } + flv2 = (FloatValue) objRef.getValue(fsfl2); + if (flv2.value() != fl1) { + log3("ERROR: getValue(fsfl2) != fl1"); + testExitCode = FAILED; + } + break; + + case 5: + log2(" checking up on int"); + + IntegerValue inv1 = (IntegerValue) objRef.getValue(fsin1); + IntegerValue inv2 = (IntegerValue) objRef.getValue(fsin2); + + int in1 = inv1.value(); + int in2 = inv2.value(); + + objRef.setValue(fsin1, inv2); + objRef.setValue(fsin2, inv1); + + inv1 = (IntegerValue) objRef.getValue(fsin1); + if (inv1.value() != in2) { + log3("ERROR: getValue(fsin1) != in2"); + testExitCode = FAILED; + } + inv2 = (IntegerValue) objRef.getValue(fsin2); + if (inv2.value() != in1) { + log3("ERROR: getValue(fsin2) != in1"); + testExitCode = FAILED; + } + break; + + case 6: + log2(" checking up on long"); + + LongValue lnv1 = (LongValue) objRef.getValue(fsln1); + LongValue lnv2 = (LongValue) objRef.getValue(fsln2); + + long ln1 = lnv1.value(); + long ln2 = lnv2.value(); + + objRef.setValue(fsln1, lnv2); + objRef.setValue(fsln2, lnv1); + + lnv1 = (LongValue) objRef.getValue(fsln1); + if (lnv1.value() != ln2) { + log3("ERROR: getValue(fsln1) != ln2"); + testExitCode = FAILED; + } + lnv2 = (LongValue) objRef.getValue(fsln2); + if (lnv2.value() != ln1) { + log3("ERROR: getValue(fsln2) != ln1"); + testExitCode = FAILED; + } + break; + + case 7: + log2(" checking up on short"); + + ShortValue shv1 = (ShortValue) objRef.getValue(fssh1); + ShortValue shv2 = (ShortValue) objRef.getValue(fssh2); + + short sh1 = shv1.value(); + short sh2 = shv2.value(); + + objRef.setValue(fssh1, shv2); + objRef.setValue(fssh2, shv1); + + shv1 = (ShortValue) objRef.getValue(fssh1); + if (shv1.value() != sh2) { + log3("ERROR: getValue(fssh1) != sh2"); + testExitCode = FAILED; + } + shv2 = (ShortValue) objRef.getValue(fssh2); + if (shv2.value() != sh1) { + log3("ERROR: getValue(fssh2) != sh1"); + testExitCode = FAILED; + } + break; + + + default : log3("ERROR: TEST ERROR: case: default:"); + testExitCode = FAILED; + break; + + } // end of switch + + } catch ( Exception e ) { + log3("ERROR: unexpected exception: " + e); + testExitCode = FAILED; + } // end of try + + } // end of for + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001/TestDescription.java new file mode 100644 index 00000000000..93d77facee2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001/TestDescription.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/setValue/setvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.setValue() + * complies with its spec: + * public void setValue(Field field, Value value) + * throws InvalidTypeException, ClassNotLoadedException + * Sets the value of a given instance or static field in this object. + * The Field must be valid for this ObjectReference; + * that is, there must be a widening reference conversion from this object + * to the field's type. If static, the field must not be final. + * Object values must be assignment compatible with the field type + * (This implies that the field type must be loaded through + * the enclosing class's class loader). + * Primitive values must be either assignment compatible with the field type or + * must be convertible to the field type without loss of information. + * See the JavaTM Language Specification.section 5.2 for more information on + * assignment compatibility. + * Parameters: field - the field containing the requested value + * value - the new value to assign + * Throws: IllegalArgumentException - + * if the field is not valid for this object's class. + * InvalidTypeException - + * if the value's type does not match the field's type. + * ClassNotLoadedException - + * if the field type has not yet been loaded through + * the appropriate class loader. + * ObjectCollectedException - + * if this object or the new value (if an ObjectReference) has been + * garbage collected. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The cases for testing include values of class and instance + * variables of primitive types each. + * No Exception is expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.setValue.setvalue 00; + * the debuggee program - nsk.jdi.ObjectReference.setValue.setvalue 00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.setValue.setvalue001 + * nsk.jdi.ObjectReference.setValue.setvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.setValue.setvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001a.java new file mode 100644 index 00000000000..af98b9b9609 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue001a.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the setvalue001 JDI test. + */ + +public class setvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ObjectReference.setValue() + * properly throws IllegalArgumentException - if the + * field is not valid for this object's class.
    + * The debuggee part of the test contains two classes: the main one + * setvalue002t and the dummy one DummyClass. Each of + * them has the same set of static and instance fields.
    + * The debugger part provokes the IllegalArgumentException trying to + * set value of: + *
  • an object reference to the debuggee's class setvalue002t + * and Field's value from an object reference to the debuggee's class + * DummyClass + *
  • an object reference to the debuggee's class DummyClass + * and Field's value from an object reference to the debuggee's class + * setvalue002t.
    + */ +public class setvalue002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.setValue.setvalue002t"; + + // name of debuggee's main thread + static final String DEBUGGEE_THRNAME = "setvalue002tThr"; + + // debuggee's local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = "dummyCls"; + + static final int ATTEMPTS = 5; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private ThreadReference thrRef = null; + private ObjectReference[] objRef = new ObjectReference[2]; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setvalue002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType[] rType = new ReferenceType[2]; + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "setvalue002t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee's thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + thrRef.suspend(); + while(!thrRef.isSuspended()) { + num++; + if (num > ATTEMPTS) { + log.complain("TEST FAILED: Unable to suspend debuggee's thread"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + log.display("Waiting for debuggee's thread suspension ..."); + try { + Thread.currentThread().sleep(1000); + } catch(InterruptedException ie) { + log.complain("TEST FAILED: caught: " + ie); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + } + +// Check the tested assersion + try { + findObjRefs(DEBUGGEE_LOCALVAR); + rType[0] = objRef[0].referenceType(); + rType[1] = objRef[1].referenceType(); + + // provoke the IllegalArgumentException using an object reference + // to debuggee's main class "setvalue002t" and Field's value from + // an object reference to debuggee's dummy class "DummyClass" + provokeException(objRef[0], rType[0], objRef[1], rType[1]); + + // provoke the IllegalArgumentException using an object reference + // to debuggee's dummy class "DummyClass" and Field's value from + // an object reference to debuggee's main class "setvalue002t" + provokeException(objRef[1], rType[1], objRef[0], rType[0]); + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + +// Finish the test + thrRef.resume(); + return quitDebuggee(); + } + + private void findObjRefs(String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = stackFr.visibleVariableByName(varName); + if (locVar == null) + continue; + // main debuggee class + objRef[0] = stackFr.thisObject(); + // dummy debuggee class + objRef[1] = (ObjectReference)stackFr.getValue(locVar); + return; + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee's stack frame not found"); + } + + private void provokeException(ObjectReference objRef, + ReferenceType refType, + ObjectReference fldObjRef, ReferenceType fldRefType) { + List fields; + + try { + fields = fldRefType.allFields(); + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: allFields for " + + fldObjRef + ": caught: " + e); + tot_res = Consts.TEST_FAILED; + throw new Failure("provokeException: caught unexpected exception"); + } + + Iterator iter = fields.iterator(); + while (iter.hasNext()) { + Field fld = (Field) iter.next(); + try { + log.display("\nTrying to set value for the field \"" + + fld.name() + "\"\n\tfrom the debuggee's object reference \"" + + objRef + + "\"\n\tusing not valid Field's value from the other object reference \"" + + fldObjRef + "\" ..."); + objRef.setValue(fld, objRef.getValue(refType.fieldByName(fld.name()))); + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to set value for the field \"" + + fld.name() + "\"\n\tfrom the debuggee's object reference \"" + + objRef + + "\n\tusing not valid Field's value from the other object reference \"" + + fldObjRef + "\""); + tot_res = Consts.TEST_FAILED; + } catch (IllegalArgumentException ee) { + log.display("CHECK PASSED: caught expected " + ee); + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILED: ObjectReference.setValue(): caught unexpected " + + e + "\n\tinstead of expected IllegalArgumentException" + + "\n\twhen attempted to set value for the field \"" + + fld.name() + "\"\n\tfrom the debuggee's object reference \"" + + objRef + + "\n\tusing not valid Field's value from the other object reference \"" + + fldObjRef + "\""); + tot_res = Consts.TEST_FAILED; + } + } + } + + private int quitDebuggee() { + if (thrRef != null) { + if (thrRef.isSuspended()) + thrRef.resume(); + } + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee's process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("Debuggee's process finished with the status: " + + debStat); + + return tot_res; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002/TestDescription.java new file mode 100644 index 00000000000..3769c021718 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/setValue/setvalue002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ObjectReference.setValue() properly throws + * IllegalArgumentException - if the field is not valid for this + * object's class. + * The debuggee part of the test contains two classes: the main one + * "setvalue002t" and the dummy one "DummyClass". Each of them has + * the same set of static and instance fields. + * The debugger part provokes the IllegalArgumentException trying to + * set value of: + * - an object reference to the debuggee's class "setvalue002t" + * and Field's value from an object reference to the debuggee's class + * "DummyClass"; + * - an object reference to the debuggee's class "DummyClass" and + * Field's value from an object reference to the debuggee's class + * "setvalue002t". + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.setValue.setvalue002 + * nsk.jdi.ObjectReference.setValue.setvalue002t + * + * @comment make sure setvalue002t is compiled with full debug info + * @clean nsk.jdi.ObjectReference.setValue.setvalue002t + * @compile -g:lines,source,vars ../setvalue002t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.setValue.setvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002t.java new file mode 100644 index 00000000000..9737c6bcfbc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue002t.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.setValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee class. + */ +public class setvalue002t { + // tested static fields + static byte sByteFld = 127; + static short sShortFld = -32768; + static int sIntFld = 2147483647; + static long sLongFld = 9223372036854775807L; + static float sFloatFld = 5.1F; + static double sDoubleFld = 6.2D; + static char sCharFld = 'a'; + static boolean sBooleanFld = false; + static String sStrFld = "instance field"; + + // tested instance fields + byte byteFld = 127; + short shortFld = -32768; + int intFld = 2147483647; + long longFld = 9223372036854775807L; + float floatFld = 5.1F; + double doubleFld = 6.2D; + char charFld = 'a'; + boolean booleanFld = false; + String strFld = "instance field"; + + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new setvalue002t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + setvalue002tDummyClass dummyCls = new setvalue002tDummyClass(); + + Thread.currentThread().setName(setvalue002.DEBUGGEE_THRNAME); + + pipe.println(setvalue002.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(setvalue002.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + return Consts.TEST_PASSED; + } +} + +// Dummy class used to provoke IllegalArgumentException in debugger +class setvalue002tDummyClass { + // tested static fields + static byte sByteFld = 127; + static short sShortFld = -32768; + static int sIntFld = 2147483647; + static long sLongFld = 9223372036854775807L; + static float sFloatFld = 5.1F; + static double sDoubleFld = 6.2D; + static char sCharFld = 'a'; + static boolean sBooleanFld = false; + static String sStrFld = "instance field"; + + // tested instance fields + byte byteFld = 127; + short shortFld = -32768; + int intFld = 2147483647; + long longFld = 9223372036854775807L; + float floatFld = 5.1F; + double doubleFld = 6.2D; + char charFld = 'a'; + boolean booleanFld = false; + String strFld = "instance field"; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue003.java new file mode 100644 index 00000000000..e922d6e8466 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue003.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.setValue; + +import com.sun.jdi.*; + +import java.util.Iterator; +import java.util.List; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ObjectReference.setValue() + * properly throws InvalidTypeException - if the Field is valid + * for this ObjectReference, but there is no a widening reference + * conversion from this object to the field's type.
    + * The debuggee part of the test has set of static and instance fields + * of different types. The debugger part provokes the InvalidTypeException + * trying to set value of: + *
  • type not matched with the field's one, and without the widening + * reference conversion as well + *
  • boolean type which can be converted only to boolean.
    + */ +public class setvalue003 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.setValue.setvalue003t"; + + // name of debuggee's main thread + static final String DEBUGGEE_THRNAME = "setvalue003tThr"; + + // debuggee's local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = "setvalue003tPipe"; + + static final int ATTEMPTS = 5; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int FLDS_NUM = 34; + // list of debuggee's fields used to set values and ones + // used only to get their wrong non-conversionable values, + // see section "5.1.2 Widening Primitive Conversion" in the JLS + static final String DEBUGGEE_FLDS[][] = { + {"byteFld", "sStrFld"}, + {"shortFld", "intFld"}, + {"intFld", "longFld"}, + {"longFld", "floatFld"}, + {"floatFld", "doubleFld"}, + {"doubleFld", "sBooleanFld"}, + {"charFld", "strFld"}, + {"booleanFld", "byteFld"}, + {"strFld", "sCharFld"}, + {"sByteFld", "sIntFld"}, + {"sShortFld", "doubleFld"}, + {"sIntFld", "sStrFld"}, + {"sLongFld", "sFloatFld"}, + {"sFloatFld", "sDoubleFld"}, + {"sDoubleFld", "strFld"}, + {"sCharFld", "sDoubleFld"}, + {"sBooleanFld", "doubleFld"}, + {"sStrFld", "sDoubleFld"}, + // see section "5.1.1 Identity Conversions" in the JLS: + // "the only permitted conversion that involves the type boolean is + // the identity conversion from boolean to boolean" + {"byteFld", "booleanFld"}, + {"shortFld", "booleanFld"}, + {"intFld", "booleanFld"}, + {"longFld", "booleanFld"}, + {"floatFld", "booleanFld"}, + {"doubleFld", "booleanFld"}, + {"charFld", "booleanFld"}, + {"strFld", "booleanFld"}, + {"sByteFld", "booleanFld"}, + {"sShortFld", "booleanFld"}, + {"sIntFld", "booleanFld"}, + {"sLongFld", "booleanFld"}, + {"sFloatFld", "booleanFld"}, + {"sDoubleFld", "booleanFld"}, + {"sCharFld", "booleanFld"}, + {"sStrFld", "booleanFld"} + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private ThreadReference thrRef = null; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setvalue003().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ObjectReference objRef; + ReferenceType rType; + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "setvalue003t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee's thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + thrRef.suspend(); + while(!thrRef.isSuspended()) { + num++; + if (num > ATTEMPTS) { + log.complain("TEST FAILED: Unable to suspend debuggee's thread"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + log.display("Waiting for debuggee's thread suspension ..."); + try { + Thread.sleep(1000); + } catch(InterruptedException ie) { + ie.printStackTrace(); + log.complain("TEST FAILED: caught: " + ie); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + } + +// Check the tested assertion + try { + objRef = findObjRef(DEBUGGEE_LOCALVAR); + rType = objRef.referenceType(); + + // provoke the InvalidTypeException + for (int i=0; icom.sun.jdi.ObjectReference.setValue() + * properly throws IllegalArgumentException when a + * debugger part of the test attempts to set value of + * debuggee's static field which is declared as final.
    + */ +public class setvalue004 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.setValue.setvalue004t"; + + // name of debuggee's main thread + static final String DEBUGGEE_THRNAME = "setvalue004tThr"; + + // debuggee's local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = "setvalue004tPipe"; + + static final int ATTEMPTS = 5; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final int FLDS_NUM = 9; + static final String DEBUGGEE_FLDS[] = { + "sByteFld", + "sShortFld", + "sIntFld", + "sLongFld", + "sFloatFld", + "sDoubleFld", + "sCharFld", + "sBooleanFld", + "sStrFld" + }; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private ThreadReference thrRef = null; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setvalue004().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ObjectReference objRef; + ReferenceType rType; + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "setvalue004t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee's thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + thrRef.suspend(); + while(!thrRef.isSuspended()) { + num++; + if (num > ATTEMPTS) { + log.complain("TEST FAILED: Unable to suspend debuggee's thread"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + log.display("Waiting for debuggee's thread suspension ..."); + try { + Thread.currentThread().sleep(1000); + } catch(InterruptedException ie) { + ie.printStackTrace(); + log.complain("TEST FAILED: caught: " + ie); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + } + +// Check the tested assersion + try { + objRef = findObjRef(DEBUGGEE_LOCALVAR); + rType = objRef.referenceType(); + + // provoke the IllegalArgumentException + for (int i=0; icom.sun.jdi.ObjectReference.setValue() + * does not throw ClassNotLoadedException when a + * debugger part of the test attempts to set null value of + * a debuggee field of reference type which has not been loaded + * through the appropriate class loader.
    + */ +public class setvalue005 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ObjectReference.setValue.setvalue005t"; + + // tested debuggee reference types + static final int REFTYPES_NUM = 3; + static final String DEBUGGEE_REFTYPES[][] = { + {"nsk.jdi.ObjectReference.setValue.setvalue005tDummyType", "dummyType"}, + {"nsk.jdi.ObjectReference.setValue.setvalue005tAbsDummyType", "absDummyType"}, + {"nsk.jdi.ObjectReference.setValue.setvalue005tFinDummyType", "finDummyType"} + }; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "setvalue005tThr"; + + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = "setvalue005tPipe"; + + static final int ATTEMPTS = 5; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private ThreadReference thrRef = null; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setvalue005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ObjectReference objRef; + ReferenceType rType; + String cmd; + int num = 0; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "setvalue005t.err> "); + debuggee.resume(); + cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: Method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + thrRef.suspend(); + while(!thrRef.isSuspended()) { + num++; + if (num > ATTEMPTS) { + log.complain("TEST FAILED: Unable to suspend debuggee thread after " + + ATTEMPTS + " attempts"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + log.display("Waiting for debuggee thread suspension ..."); + try { + Thread.currentThread().sleep(1000); + } catch(InterruptedException ie) { + ie.printStackTrace(); + log.complain("TEST FAILED: caught: " + ie); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + } + +// Check the tested assersion + try { + objRef = findObjRef(DEBUGGEE_LOCALVAR); + rType = objRef.referenceType(); + + // provoke the ClassNotLoadedException + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.uniqueID()
    + * complies with its specification.
    + *
    + * The test checks up that the method returns a long value.
    + */ + +public class uniqueid001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/uniqueID/uniqueid001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new uniqueid001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.uniqueID.uniqueid001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.uniqueID.TestClass"; + + //String mName = "nsk.jdi.ObjectReference.uniqueID"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String objName = "testObj"; + + log2(".......getting ObjectReference objRef object"); + try { + + testedClass = (ReferenceType) + vm.classesByName(debuggeeName).get(0); + + ObjectReference objRef = (ObjectReference) + testedClass.getValue(testedClass.fieldByName(objName)); + + log2(".......checking up on throwing Exception by objRef.uniqueID()"); + + try { + long id = objRef.uniqueID(); + log2(" uniqueID value == " + id); + } catch ( Exception e2 ) { + testExitCode = FAILED; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001/TestDescription.java new file mode 100644 index 00000000000..91d89ed8013 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/uniqueID/uniqueid001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.uniqueID() + * complies with its spec: + * public long uniqueID() + * Returns a unique identifier for this ObjectReference. + * It is guaranteed to be unique among all ObjectReferences + * from the same VM that have not yet been disposed. + * The guarantee applies as long as this ObjectReference has + * not yet been disposed. + * Returns: a long unique ID + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The test checks up that a returned value is "long". + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.uniqueID.uniqueid 00; + * the debuggee program - nsk.jdi.ObjectReference.uniqueID.uniqueid 00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.uniqueID.uniqueid001 + * nsk.jdi.ObjectReference.uniqueID.uniqueid001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.uniqueID.uniqueid001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001a.java new file mode 100644 index 00000000000..d20da8e6290 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/uniqueID/uniqueid001a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.uniqueID; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the uniqueid001 JDI test. + */ + +public class uniqueid001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass testObj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ObjectReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ObjectReference.waitingThreads()
    + * complies with its specification.
    + *
    + * The case for testing includes throwing
    + * UnsupportedOperationException
    + * provided
    + * VirtualMachine.canGetMonitorInfo() == false
    + */ + +public class waitingthreads001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ObjectReference/waitingThreads/waitingthreads001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new waitingthreads001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ObjectReference.waitingThreads.waitingthreads001a"; + + private String testedClassName = + "nsk.jdi.ObjectReference.waitingThreads.TestClass"; + + //String mName = "nsk.jdi.ObjectReference.waitingThreads"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String objName = "testObj"; + + log2("getting testedClass object"); + try { + + testedClass = (ReferenceType) + vm.classesByName(debuggeeName).get(0); + + ObjectReference objRef = (ObjectReference) + testedClass.getValue(testedClass.fieldByName(objName)); + + if (!vm.canGetMonitorInfo()) { + + log2(".......vm.canGetMonitorInfo() == false"); + log2(".......checking up on throwing UnsupportedOperationException"); + + try { + List waitingThreads = objRef.waitingThreads(); + log3("ERROR: UnsupportedOperationException is not thrown"); + testExitCode = FAILED; + } catch ( UnsupportedOperationException e1 ) { + log2(" expected UnsupportedOperationException is thrown"); + } catch ( Exception e2 ) { + testExitCode = FAILED; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + } + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001/TestDescription.java new file mode 100644 index 00000000000..c7af5d87720 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/waitingThreads/waitingthreads001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ObjectReference. + * The test checks up that a result of the method + * com.sun.jdi.ObjectReference.waitingThreads() + * complies with its spec: + * public List waitingThreads() + * throws IncompatibleThreadStateException + * Returns a List containing a ThreadReference for each thread + * currently waiting for this object's monitor. + * See ThreadReference.currentContendedMonitor() for information about + * when a thread is considered to be waiting for a monitor. + * Not all target VMs support this operation. + * See VirtualMachine#canGetMonitorInfo to determine if the operation is supported. + * Returns: a List of ThreadReference objects. + * The list has zero length if no threads are waiting for the monitor. + * Throws: UnsupportedOperationException - + * if the target VM does not support this operation. + * IncompatibleThreadStateException - + * if any waiting thread is not suspended in the target VM + * ObjectCollectedException - + * if this object has been garbage collected. + * The case for testing includes throwing + * UnsupportedOperationException + * provided + * VirtualMachine.canGetMonitorInfo() == false + * The test works as follows: + * The debugger program - nsk.jdi.ObjectReference.waitingThreads.waitingthreads 00; + * the debuggee program - nsk.jdi.ObjectReference.waitingThreads.waitingthreads 00a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.waitingThreads.waitingthreads001 + * nsk.jdi.ObjectReference.waitingThreads.waitingthreads001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.waitingThreads.waitingthreads001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001a.java new file mode 100644 index 00000000000..0780d6753ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads001a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ObjectReference.waitingThreads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the waitingthreads001 JDI test. + */ + +public class waitingthreads001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass testObj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + debuggee.receiveExpectedSignal(SIGNAL_GO); + + if (debuggee.VM().canGetMonitorInfo()) { + + // Wait up to waitTime until all MyThreads will be blocked on entering in monitor + int waitingCount = 0; + long oldTime = System.currentTimeMillis(); + while ((System.currentTimeMillis() - oldTime) <= waitTime && waitingCount < waitingthreads002a.threadCount) { + Iterator threads = debuggee.VM().allThreads().iterator(); + waitingCount = 0; + while (threads.hasNext()) { + ThreadReference thread = (ThreadReference)threads.next(); + if (thread.name().indexOf(waitingthreads002a.threadNamePrefix) >= 0 && + thread.status() == ThreadReference.THREAD_STATUS_MONITOR ) { + waitingCount++; + } + } + } + + if (waitingCount < waitingthreads002a.threadCount) { + exitStatus = Consts.TEST_FAILED; + complain("After " + waitTime + " ms only " + waitingCount + " of " + waitingthreads002a.threadNamePrefix + "s " + + "\n\t are blocked on entering monitor. Expected count: " + waitingthreads002a.threadCount); + } else { + try { + debuggee.VM().suspend(); + + // check for waitingthreads002a.waitnotifyObj - no waiting threads expected + String fieldName = "waitnotifyObj"; + display("CHECK1 : checking waitingThreads method for ObjectReference of waitingthreads002a." + fieldName); + ObjectReference objRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); + try { + List waitingThreads = objRef.waitingThreads(); + if (waitingThreads.size() != 0) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads method returned non-zero size list for " + fieldName); + } else { + display("waitingThreads method returned expected list of zero size for " + fieldName); + } + if (exitStatus == Consts.TEST_PASSED) { + display("CHECK1 PASSED"); + } + } catch (Exception e) { + throw new Failure("Unexpected exception while getting waitingThreads method's result for " + fieldName + " : " + e); + } + + // check for waitingthreads002a.lockingObject - waiting threads expected + fieldName = "lockingObject"; + display("CHECK2: checking waitingThreads method for ObjectReference of waitingthreads002a." + fieldName); + objRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); + try { + List waitingThreads = objRef.waitingThreads(); + if (waitingThreads.size() != waitingthreads002a.threadCount) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads method returned list with unexpected size for " + fieldName + + "\n\t expected value : " + waitingthreads002a.threadCount + "; got one : " + waitingThreads.size()); + } else { + // check waitingThreads list + Iterator itr = waitingThreads.iterator(); + while (itr.hasNext()) { + ThreadReference thread = (ThreadReference)itr.next(); + if (thread.name().indexOf(waitingthreads002a.threadNamePrefix) < 0) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads returned list containing ThreadReference with unexpected name: " + thread.name()); + } else { + display("Expected ThreadReference is found in the returned list: " + thread.name()); + } + if (!thread.currentContendedMonitor().equals(objRef)) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads returned list contained ThreadReference with unexpected monitor: " + thread.currentContendedMonitor()); + } + } + } + if (exitStatus == Consts.TEST_PASSED) { + display("CHECK2 PASSED"); + } + } catch (Exception e) { + throw new Failure("Unexpected exception while getting waitingThreads method's result for " + fieldName + " : " + e); + } + } finally { + debuggee.VM().resume(); + } + } + } + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002/TestDescription.java new file mode 100644 index 00000000000..44b4640640a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/waitingThreads/waitingthreads002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks an following assertion of + * com.sun.jdi.ObjectReference.waitingThreads method spec: + * Returns a List containing a ThreadReference for each thread currently + * waiting for this object's monitor. + * There are two test cases: + * - An object with no waiting threads. + * A list with zero size is expected to be returned by the method. + * - An object with threads waiting to lock monitor in a synchronized statement. + * The debugger checks with expected results: + * - a size of returned list of ThreadReferences, + * - the names of thread references, + * - whether the thread reference has the same contented monitor object + * as checked one. + * The debugger program - nsk.jdi.ObjectReference.waitingThreads.waitingthreads004; + * the debuggee program - nsk.jdi.ObjectReference.waitingThreads.waitingthreads004a. + * Communication details between the debugger and the debuggee: + * Using nsk.jdi.share classes, the debugger connects to debuggee program running + * on another VM and establishes a communication pipe with the debuggee. The pipe + * is used in bi-directional way by sending and receiving special commands between + * the debugger and debuggee for synchronization + * In case of error the test produces the exit code 97 and a corresponding error + * message(s). Otherwise, the test is passed and produces the exit code 95 and + * no message. + * COMMENTS: + * 4883502 TEST_BUG: waiting Threads testcases not predictable + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.waitingThreads.waitingthreads002 + * nsk.jdi.ObjectReference.waitingThreads.waitingthreads002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.waitingThreads.waitingthreads002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002a.java new file mode 100644 index 00000000000..eb718935f2a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002a.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.waitingThreads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged applcation of the test. + */ +public class waitingthreads002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + static final int threadCount = 5; + static final String threadNamePrefix = "MyThread-"; + static waitingthreads002aThread[] threads = new waitingthreads002aThread[threadCount]; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + long waitTime = argHandler.getWaitTime() * 60000; + + pipe.println(waitingthreads002.SIGNAL_READY); + + try { + synchronized (lockingObject) { + display("entered: synchronized (lockingObject) {}"); + synchronized (waitnotifyObj) { + display("entered: synchronized (waitnotifyObj) {}"); + + for (int i = 0; i < threadCount; i++) { + threads[i] = new waitingthreads002aThread(threadNamePrefix + i); + threads[i].start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for " + threadNamePrefix + i + " start"); + } + } + + pipe.println(waitingthreads002.SIGNAL_GO); + receiveSignal(waitingthreads002.SIGNAL_QUIT); + } + display("exited: synchronized (waitnotifyObj) {}"); + } + display("exited: synchronized (lockingObject) {}"); + + for (int i = 0; i < threadCount; i++) { + if (threads[i].isAlive()) { + try { + threads[i].join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for " + threadNamePrefix + i + " join"); + } + } + } + +// receiveSignal(waitingthreads002.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(exitStatus + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class waitingthreads002aThread extends Thread { + public waitingthreads002aThread(String threadName) { + super(threadName); + } + + public void run() { + synchronized (waitingthreads002a.waitnotifyObj) { + waitingthreads002a.waitnotifyObj.notifyAll(); + } + + synchronized (waitingthreads002a.lockingObject) { + display("entered: synchronized (lockingObject)"); + } + display("exited: synchronized (lockingObject)"); + } + + private void display (String str) { + waitingthreads002a.display(Thread.currentThread().getName() + " : " + str); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003.java new file mode 100644 index 00000000000..832b3521e95 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.waitingThreads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class waitingthreads003 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ObjectReference.waitingThreads."; + private final static String className = "waitingthreads003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + debuggee.receiveExpectedSignal(SIGNAL_GO); + + if (debuggee.VM().canGetMonitorInfo()) { + + // Wait up to waitTime until all MyThreads will be blocked on entering in monitor + int waitingCount = 0; + long oldTime = System.currentTimeMillis(); + while ((System.currentTimeMillis() - oldTime) <= waitTime && waitingCount < waitingthreads003a.threadCount) { + Iterator threads = debuggee.VM().allThreads().iterator(); + waitingCount = 0; + while (threads.hasNext()) { + ThreadReference thread = (ThreadReference)threads.next(); + if (thread.name().indexOf(waitingthreads003a.threadNamePrefix) >= 0 && + thread.status() == ThreadReference.THREAD_STATUS_MONITOR ) { + waitingCount++; + } + } + } + + if (waitingCount < waitingthreads003a.threadCount) { + exitStatus = Consts.TEST_FAILED; + complain("After " + waitTime + " ms only " + waitingCount + " of " + waitingthreads003a.threadNamePrefix + "s " + + "\n\t are blocked on entering monitor. Expected count: " + waitingthreads003a.threadCount); + } else { + try { + debuggee.VM().suspend(); + + // check for waitingthreads003a.waitnotifyObj - no waiting threads expected + String fieldName = "waitnotifyObj"; + display("CHECK1 : checking waitingThreads method for ObjectReference of waitingthreads003a." + fieldName); + ObjectReference objRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); + try { + List waitingThreads = objRef.waitingThreads(); + if (waitingThreads.size() != 0) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads method returned non-zero size list for " + fieldName); + } else { + display("waitingThreads method returned expected list of zero size for " + fieldName); + } + if (exitStatus == Consts.TEST_PASSED) { + display("CHECK1 PASSED"); + } + } catch (Exception e) { + throw new Failure("Unexpected exception while getting waitingThreads method's result for " + fieldName + " : " + e); + } + + // check for waitingthreads003a.lockingObject - waiting threads expected + fieldName = "lockingObject"; + display("CHECK2: checking waitingThreads method for ObjectReference of waitingthreads003a." + fieldName); + objRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); + try { + List waitingThreads = objRef.waitingThreads(); + if (waitingThreads.size() != waitingthreads003a.threadCount) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads method returned list with unexpected size for " + fieldName + + "\n\t expected value : " + waitingthreads003a.threadCount + "; got one : " + waitingThreads.size()); + } else { + // check waitingThreads list + Iterator itr = waitingThreads.iterator(); + while (itr.hasNext()) { + ThreadReference thread = (ThreadReference)itr.next(); + if (thread.name().indexOf(waitingthreads003a.threadNamePrefix) < 0) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads returned list containing ThreadReference with unexpected name: " + thread.name()); + } else { + display("Expected ThreadReference is found in the returned list: " + thread.name()); + } + if (!thread.currentContendedMonitor().equals(objRef)) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads returned list contained ThreadReference with unexpected monitor: " + thread.currentContendedMonitor()); + } + } + } + if (exitStatus == Consts.TEST_PASSED) { + display("CHECK2 PASSED"); + } + } catch (Exception e) { + throw new Failure("Unexpected exception while getting waitingThreads method's result for " + fieldName + " : " + e); + } + } finally { + debuggee.VM().resume(); + } + } + } + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003/TestDescription.java new file mode 100644 index 00000000000..5b370f257de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/waitingThreads/waitingthreads003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks an following assertion of + * com.sun.jdi.ObjectReference.waitingThreads method spec: + * Returns a List containing a ThreadReference for each thread currently + * waiting for this object's monitor. + * There are two test cases: + * - An object with no waiting threads. + * A list with zero size is expected to be returned by the method. + * - An object with threads waiting to lock monitor in a synchronized method. + * The debugger checks with expected results: + * - a size of returned list of ThreadReferences, + * - the names of thread references, + * - whether the thread reference has the same contented monitor object + * as checked one. + * The debugger program - nsk.jdi.ObjectReference.waitingThreads.waitingthreads004; + * the debuggee program - nsk.jdi.ObjectReference.waitingThreads.waitingthreads004a. + * Communication details between the debugger and the debuggee: + * Using nsk.jdi.share classes, the debugger connects to debuggee program running + * on another VM and establishes a communication pipe with the debuggee. The pipe + * is used in bi-directional way by sending and receiving special commands between + * the debugger and debuggee for synchronization + * In case of error the test produces the exit code 97 and a corresponding error + * message(s). Otherwise, the test is passed and produces the exit code 95 and + * no message. + * COMMENTS: + * 4883502 TEST_BUG: waiting Threads testcases not predictable + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.waitingThreads.waitingthreads003 + * nsk.jdi.ObjectReference.waitingThreads.waitingthreads003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.waitingThreads.waitingthreads003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003a.java new file mode 100644 index 00000000000..5109849e03b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads003a.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.waitingThreads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged applcation of the test. + */ +public class waitingthreads003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Object waitnotifyObj = new Object(); + static waitingthreads003aLock lockingObject = new waitingthreads003aLock(); + static final int threadCount = 5; + static final String threadNamePrefix = "MyThread-"; + static waitingthreads003aThread[] threads = new waitingthreads003aThread[threadCount]; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + long waitTime = argHandler.getWaitTime() * 60000; + + pipe.println(waitingthreads003.SIGNAL_READY); + + try { + synchronized (lockingObject) { + display("entered: synchronized (lockingObject) {}"); + synchronized (waitnotifyObj) { + display("entered: synchronized (waitnotifyObj) {}"); + + for (int i = 0; i < threadCount; i++) { + threads[i] = new waitingthreads003aThread(threadNamePrefix + i); + threads[i].start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for " + threadNamePrefix + i + " start"); + } + } + + pipe.println(waitingthreads003.SIGNAL_GO); + receiveSignal(waitingthreads003.SIGNAL_QUIT); + } + display("exited: synchronized (waitnotifyObj) {}"); + } + display("exited: synchronized (lockingObject) {}"); + + for (int i = 0; i < threadCount; i++) { + if (threads[i].isAlive()) { + try { + threads[i].join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for " + threadNamePrefix + i + " join"); + } + } + } + +// receiveSignal(waitingthreads003.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(exitStatus + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class waitingthreads003aThread extends Thread { + public waitingthreads003aThread(String threadName) { + super(threadName); + } + + public void run() { + synchronized (waitingthreads003a.waitnotifyObj) { + waitingthreads003a.waitnotifyObj.notifyAll(); + } + waitingthreads003a.lockingObject.foo(); + display("exited: synchronized method foo"); + } + + private void display (String str) { + waitingthreads003a.display(Thread.currentThread().getName() + " : " + str); + } +} + +class waitingthreads003aLock { + synchronized void foo() { + display("entered: synchronized method foo"); + } + + private void display (String str) { + waitingthreads003a.display(Thread.currentThread().getName() + " : " + str); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004.java new file mode 100644 index 00000000000..769a7de625b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.waitingThreads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class waitingthreads004 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ObjectReference.waitingThreads."; + private final static String className = "waitingthreads004"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + debuggee.receiveExpectedSignal(SIGNAL_GO); + + if (debuggee.VM().canGetMonitorInfo()) { + + // Wait up to waitTime until all MyThreads will be waiting + int waitingCount = 0; + long oldTime = System.currentTimeMillis(); + while ((System.currentTimeMillis() - oldTime) <= waitTime && waitingCount < waitingthreads004a.threadCount) { + Iterator threads = debuggee.VM().allThreads().iterator(); + waitingCount = 0; + while (threads.hasNext()) { + ThreadReference thread = (ThreadReference)threads.next(); + if (thread.name().indexOf(waitingthreads004a.threadNamePrefix) >= 0 && + thread.status() == ThreadReference.THREAD_STATUS_WAIT ) { + waitingCount++; + } + } + } + + if (waitingCount < waitingthreads004a.threadCount) { + exitStatus = Consts.TEST_FAILED; + complain("After " + waitTime + " ms only " + waitingCount + " of " + waitingthreads004a.threadNamePrefix + "s " + + "\n\t are waiting. Expected count: " + waitingthreads004a.threadCount); + } else { + try { + debuggee.VM().suspend(); + + // check for waitingthreads004a.waitnotifyObj - no waiting threads expected + String fieldName = "waitnotifyObj"; + display("CHECK1 : checking waitingThreads method for ObjectReference of waitingthreads004a." + fieldName); + ObjectReference objRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); + try { + List waitingThreads = objRef.waitingThreads(); + if (waitingThreads.size() != 0) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads method returned non-zero size list for " + fieldName); + } else { + display("waitingThreads method returned expected list of zero size for " + fieldName); + } + if (exitStatus == Consts.TEST_PASSED) { + display("CHECK1 PASSED"); + } + } catch (Exception e) { + throw new Failure("Unexpected exception while getting waitingThreads method's result for " + fieldName + " : " + e); + } + + // check for waitingthreads004a.lockingObject - waiting threads expected + fieldName = "lockingObject"; + display("CHECK2: checking waitingThreads method for ObjectReference of waitingthreads004a." + fieldName); + objRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); + try { + List waitingThreads = objRef.waitingThreads(); + if (waitingThreads.size() != waitingthreads004a.threadCount) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads method returned list with unexpected size for " + fieldName + + "\n\t expected value : " + waitingthreads004a.threadCount + "; got one : " + waitingThreads.size()); + } else { + // check waitingThreads list + Iterator itr = waitingThreads.iterator(); + while (itr.hasNext()) { + ThreadReference thread = (ThreadReference)itr.next(); + if (thread.name().indexOf(waitingthreads004a.threadNamePrefix) < 0) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads returned list containing ThreadReference with unexpected name: " + thread.name()); + } else { + display("Expected ThreadReference is found in the returned list: " + thread.name()); + } + if (!thread.currentContendedMonitor().equals(objRef)) { + exitStatus = Consts.TEST_FAILED; + complain("waitingThreads returned list contained ThreadReference with unexpected monitor: " + thread.currentContendedMonitor()); + } + } + } + if (exitStatus == Consts.TEST_PASSED) { + display("CHECK2 PASSED"); + } + } catch (Exception e) { + throw new Failure("Unexpected exception while getting waitingThreads method's result for " + fieldName + " : " + e); + } + } finally { + debuggee.VM().resume(); + } + } + } + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004/TestDescription.java new file mode 100644 index 00000000000..73d3f0af2fd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ObjectReference/waitingThreads/waitingthreads004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks an following assertion of + * com.sun.jdi.ObjectReference.waitingThreads method spec: + * Returns a List containing a ThreadReference for each thread currently + * waiting for this object's monitor. + * There are two test cases: + * - An object with no waiting threads. + * A list with zero size is expected to be returned by the method. + * - An object with threads waiting in Object.wait(long) method. + * The debugger checks with expected results: + * - a size of returned list of ThreadReferences, + * - the names of thread references, + * - whether the thread reference has the same contented monitor object + * as checked one. + * The debugger program - nsk.jdi.ObjectReference.waitingThreads.waitingthreads004; + * the debuggee program - nsk.jdi.ObjectReference.waitingThreads.waitingthreads004a. + * Communication details between the debugger and the debuggee: + * Using nsk.jdi.share classes, the debugger connects to debuggee program running + * on another VM and establishes a communication pipe with the debuggee. The pipe + * is used in bi-directional way by sending and receiving special commands between + * the debugger and debuggee for synchronization + * In case of error the test produces the exit code 97 and a corresponding error + * message(s). Otherwise, the test is passed and produces the exit code 95 and + * no message. + * COMMENTS: + * 4883502 TEST_BUG: waiting Threads testcases not predictable + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ObjectReference.waitingThreads.waitingthreads004 + * nsk.jdi.ObjectReference.waitingThreads.waitingthreads004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ObjectReference.waitingThreads.waitingthreads004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004a.java new file mode 100644 index 00000000000..2b2e9a0ffda --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads004a.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ObjectReference.waitingThreads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged applcation of the test. + */ +public class waitingthreads004a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + static final int threadCount = 5; + static final String threadNamePrefix = "MyThread-"; + static waitingthreads004aThread[] threads = new waitingthreads004aThread[threadCount]; + static long waitTime; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + waitTime = argHandler.getWaitTime() * 60000; + + pipe.println(waitingthreads004.SIGNAL_READY); + + try { + synchronized (waitnotifyObj) { + display("entered: synchronized (waitnotifyObj) {}"); + + for (int i = 0; i < threadCount; i++) { + threads[i] = new waitingthreads004aThread(threadNamePrefix + i); + threads[i].start(); + try { + waitnotifyObj.wait(); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for " + threadNamePrefix + i + " start"); + } + } + + pipe.println(waitingthreads004.SIGNAL_GO); + receiveSignal(waitingthreads004.SIGNAL_QUIT); + } + display("exited: synchronized (waitnotifyObj) {}"); + + synchronized (lockingObject) { + display("entered and notifyAll: synchronized (lockingObject) {}"); + lockingObject.notifyAll(); + } + display("exited: synchronized (lockingObject) {}"); + + for (int i = 0; i < threadCount; i++) { + if (threads[i].isAlive()) { + try { + threads[i].join(waitTime); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for " + threadNamePrefix + i + " join"); + } + } + } + +// receiveSignal(waitingthreads004.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(exitStatus + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class waitingthreads004aThread extends Thread { + public waitingthreads004aThread(String threadName) { + super(threadName); + } + + public void run() { + synchronized (waitingthreads004a.lockingObject) { + display("entered and waiting: synchronized (lockingObject)"); + + synchronized (waitingthreads004a.waitnotifyObj) { + waitingthreads004a.waitnotifyObj.notifyAll(); + } + + try { + waitingthreads004a.lockingObject.wait(waitingthreads004a.waitTime); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting in " + Thread.currentThread().getName()); + } + } + display("exited: synchronized (lockingObject)"); + } + + private void display (String str) { + waitingthreads004a.display(Thread.currentThread().getName() + " : " + str); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001.java new file mode 100644 index 00000000000..e9f45a67b32 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PathSearchingVirtualMachine.baseDirectory; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * PathSearchingVirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PathSearchingVirtualMachine.baseDirectory()
    + * complies with its spec.
    + *
    + * The test checks up that a returned value is not null-string
    + * and no Exception is thrown when the method is invoked.
    + */ + +public class directory001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new directory001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PathSearchingVirtualMachine.baseDirectory.directory001a"; + + //String mName = "nsk.jdi.PathSearchingVirtualMachine.baseDirectory"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + PathSearchingVirtualMachine pvm; + + try { + log2("......getting: pvm = (PathSearchingVirtualMachine) vm;"); + pvm = (PathSearchingVirtualMachine) vm; + + log2("......getting: String baseDirectory = pvm.baseDirectory();"); + String baseDirectory = pvm.baseDirectory(); + log2(" baseDirectory == " + baseDirectory); + + if (baseDirectory == null) { + log3("ERROR: baseDirectory == null"); + testExitCode = FAILED; + } + } catch ( Exception e) { + log3("ERROR: unspecified exception thrown: " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001/TestDescription.java new file mode 100644 index 00000000000..521033c2e63 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PathSearchingVirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.PathSearchingVirtualMachine.baseDirectory() + * complies with its spec: + * public String baseDirectory() + * The test works as follows: + * The debugger program - nsk.jdi.PathSearchingVirtualMachine.baseDirectory.directory001; + * the debuggee program - nsk.jdi.PathSearchingVirtualMachine.baseDirectory.directory001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PathSearchingVirtualMachine.baseDirectory.directory001 + * nsk.jdi.PathSearchingVirtualMachine.baseDirectory.directory001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PathSearchingVirtualMachine.baseDirectory.directory001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001a.java new file mode 100644 index 00000000000..ee97b4079a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/baseDirectory/directory001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PathSearchingVirtualMachine.baseDirectory; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the directory001 JDI test. + */ + +public class directory001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PathSearchingVirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PathSearchingVirtualMachine.bootClassPath()
    + * complies with its spec.
    + *
    + * The test checks up that a returned value is not null-List
    + * containing String elements,
    + * and no Exception is thrown when the method is invoked.
    + */ + +public class bootpath001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new bootpath001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PathSearchingVirtualMachine.bootClassPath.bootpath001a"; + + //String mName = "nsk.jdi.PathSearchingVirtualMachine.bootClassPath"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + PathSearchingVirtualMachine pvm; + + try { + log2("......getting: pvm = (PathSearchingVirtualMachine) vm;"); + pvm = (PathSearchingVirtualMachine) vm; + + log2("......getting: List bootClassPath = pvm.bootClassPath();"); + List bootClassPath = pvm.bootClassPath(); + + if (bootClassPath == null) { + log3("ERROR: classPath == null"); + testExitCode = FAILED; + break; + } + + log2("......getting: ListIterator li = bootClassPath.listIterator();"); + ListIterator li = bootClassPath.listIterator(); + + log2("......loop of checking up on ListIterator elements; no Exception is expected"); + String str; + for (; li.hasNext(); ) { + + str = (String) li.next(); + log2(" element == " + str); + } + + } catch ( Exception e) { + log3("ERROR: unspecified exception thrown: " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001/TestDescription.java new file mode 100644 index 00000000000..899557ebe88 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PathSearchingVirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.PathSearchingVirtualMachine.bootClassPath() + * complies with its spec: + * public List bootClassPath() + * Get the boot class path for this virtual machine. + * Returns: List of components of the boot class path, + * each represented by a String. + * The test checks up that a returned value is not null-List + * containing String elements, + * and no Exception is thrown when the method is invoked. + * The test works as follows: + * The debugger program - nsk.jdi.PathSearchingVirtualMachine.bootClassPath.bootpath001; + * the debuggee program - nsk.jdi.PathSearchingVirtualMachine.bootClassPath.bootpath001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PathSearchingVirtualMachine.bootClassPath.bootpath001 + * nsk.jdi.PathSearchingVirtualMachine.bootClassPath.bootpath001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PathSearchingVirtualMachine.bootClassPath.bootpath001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001a.java new file mode 100644 index 00000000000..be685a7affd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/bootClassPath/bootpath001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PathSearchingVirtualMachine.bootClassPath; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the bootpath001 JDI test. + */ + +public class bootpath001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PathSearchingVirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PathSearchingVirtualMachine.classPath()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * A List returned by the method contains only String elements
    + * and each element is a substring of String returned by
    + * the method System.getProperty("java.class.path")
    + * invoked in a debuggee.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares the check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class classpath001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new classpath001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PathSearchingVirtualMachine.classPath.classpath001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + try { + PathSearchingVirtualMachine pvm; + + String debuggeeClassPathName = "javaClassPath"; + + String debuggeeClassPath = ((StringReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(debuggeeClassPathName)) + ).value(); + + log2("......getting: pvm = (PathSearchingVirtualMachine) vm;"); + pvm = (PathSearchingVirtualMachine) vm; + + log2("......getting: List classPath = pvm.classPath();"); + List classPath = pvm.classPath(); + + if (classPath == null) { + log3("ERROR: classPath == null"); + testExitCode = FAILED; + } + + log2("......getting: ListIterator li = classPath.listIterator();"); + ListIterator li = classPath.listIterator(); + + log2("......loop of checking up on ListIterator elements; no Exception is expected"); + String str; + for (; li.hasNext(); ) { + + str = (String) li.next(); + log2(" : " + str); + + if (debuggeeClassPath.indexOf(str) == -1) { + log3("ERROR: element is not a substring of debuggeeClassPath"); + log2(" element == " + str); + testExitCode = FAILED; + } + } + + } catch ( Exception e) { + log3("ERROR: unspecified exception thrown: " + e); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001/TestDescription.java new file mode 100644 index 00000000000..64c8119953f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PathSearchingVirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.PathSearchingVirtualMachine.classPath() + * complies with its spec: + * public List classPath() + * Get the class path for this virtual machine. + * Returns: List of components of the classpath, each represented by a String. + * The test checks that a List returned by the method contains + * only String elements and each element is a substring of String + * returned by the method System.getProperty("java.class.path") . + * The test works as follows: + * The debugger program - nsk.jdi.PathSearchingVirtualMachine.classPath.classpath001; + * the debuggee program - nsk.jdi.PathSearchingVirtualMachine.classPath.classpath001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * To fix the bug 4509548 and + * to eliminate the possibility of the bug 4482592 in the test, + * the test is re-implemented on the base of new interaction mechanism + * for communication between a debugger and debuggee. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PathSearchingVirtualMachine.classPath.classpath001 + * nsk.jdi.PathSearchingVirtualMachine.classPath.classpath001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PathSearchingVirtualMachine.classPath.classpath001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001a.java new file mode 100644 index 00000000000..1d5b8e721ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PathSearchingVirtualMachine.classPath; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the classpath001 JDI test. + */ + +public class classpath001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static String javaClassPath = null; + + //------------------------------------------------------ common section + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + log1("......javaClassPath = System.getProperty('java.class.path');"); + javaClassPath = System.getProperty("java.class.path"); + log1(" java.class.path == " + javaClassPath); + + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..eb20e1bbfa9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001 test +nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect001.connectors.PlugAttachConnector001 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/connectors/PlugAttachConnector001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/connectors/PlugAttachConnector001.java new file mode 100644 index 00000000000..108227ed666 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/connectors/PlugAttachConnector001.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector used by + * nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001 test + */ + +package nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector001 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName = "PlugAttachConnector001_Name"; + static String plugAttachConnectorDescription = "PlugAttachConnector001_Description"; + static Transport plugAttachConnectorTransport = new PlugConnectorsTransport("PlugAttachConnector001_Transport"); + static Map plugAttachConnectorDefaultArguments = new HashMap(); + + + public PlugAttachConnector001() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + plugAttachConnectorDefaultArguments); + } + +} // end of PlugAttachConnector001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/plugAttachConnect001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/plugAttachConnect001.java new file mode 100644 index 00000000000..3c1999d31e6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001/plugAttachConnect001.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the pluggable + * connector named "PlugAttachConnector001_Name" is created on base + * of PlugAttachConnector001 class which implements + * com.sun.jdi.connect.AttachingConnector interface. + * This pluggable connector has to be contained in lists returned + * by VirtualMachineManager.attachingConnectors() and + * by VirtualMachineManager.allConnectors() methods. + * This pluggable connector has to have: + * Connector.description() = "PlugAttachConnector001_Description"; + * Connector.transport().name() = "PlugAttachConnector001_Transport"; + * Connector.defaultArguments() = , i.e without arguments; + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect001.plugAttachConnect001 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect001.plugAttachConnect001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect001; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the pluggable
    + * connector named "PlugAttachConnector001_Name" is created on base
    + * of PlugAttachConnector001 class which implements
    + * com.sun.jdi.connect.AttachingConnector interface.
    + *
    + * This pluggable connector has to be contained in lists returned
    + * by VirtualMachineManager.attachingConnectors() and
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * This pluggable connector has to have:
    + * Connector.description() = "PlugAttachConnector001_Description";
    + * Connector.transport().name() = "PlugAttachConnector001_Transport";
    + * Connector.defaultArguments() = , i.e without arguments;
    + *
    + */ + +public class plugAttachConnect001 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugAttachConnect001: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugAttachConnect001: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugAttachConnect001().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + String expectedPlugAttachConnectorName = "PlugAttachConnector001_Name"; + String expectedPlugAttachConnectorDescription = "PlugAttachConnector001_Description"; + String expectedPlugAttachConnectorTransportName = "PlugAttachConnector001_Transport"; + + logAlways("==> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect001 test..."); + logOnVerbose + ("==> Test checks that expected pluggable attaching connector is created properly."); + + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that expected pluggable attaching connector is found out in attachingConnectors() List + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector expectedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( expectedPlugAttachConnectorName.equals(attachConnectorName) ) { + expectedPlugAttachConnector = attachingConnector; + break; + } + } + + if ( expectedPlugAttachConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable attaching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + expectedPlugAttachConnectorName + "'"); + return STATUS_FAILED; + } + + // check that expected pluggable attaching connector has expected description + String actualDescription = expectedPlugAttachConnector.description(); + if ( ! expectedPlugAttachConnectorDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Expected descripton = '" + expectedPlugAttachConnectorDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has expected transport name + String actualTransportName = expectedPlugAttachConnector.transport().name(); + if ( ! expectedPlugAttachConnectorTransportName.equals(actualTransportName) ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected Transport:"); + logOnError + (errorLogPrefix + "Expected Transport name = '" + expectedPlugAttachConnectorTransportName + "'"); + logOnError(errorLogPrefix + "Actual Transport name = '" + actualTransportName + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has not defaultArguments + Map actualDefaultArguments = expectedPlugAttachConnector.defaultArguments(); + int actualDefaultArgumentsNumber = actualDefaultArguments.size(); + if ( actualDefaultArgumentsNumber != 0 ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected defaultArguments:"); + logOnError(errorLogPrefix + "Expected defaultArguments Map - "); + logOnError(errorLogPrefix + "Actual defaultArguments Map size = " + actualDefaultArgumentsNumber); + testResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean expectedPlugAttachConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof AttachingConnector ) { + AttachingConnector foundAttachingConnector = (AttachingConnector)foundConnector; + if ( expectedPlugAttachConnector.equals(foundAttachingConnector) ) { + expectedPlugAttachConnectorFound = true; + break; + } + } + } + + if ( ! expectedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable attaching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + expectedPlugAttachConnector); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of plugAttachConnect001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..5a12fcbc8aa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002 test +nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect002.connectors.PlugAttachConnector002 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/connectors/PlugAttachConnector002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/connectors/PlugAttachConnector002.java new file mode 100644 index 00000000000..aa7fbac65ca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/connectors/PlugAttachConnector002.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector used by + * nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002 test + */ + +package nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector002 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName = "PlugAttachConnector002_Name"; + static String plugAttachConnectorDescription = "PlugAttachConnector002_Description"; + static Transport plugAttachConnectorTransport = new PlugConnectorsTransport("PlugAttachConnector002_Transport"); + static Map plugAttachConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugAttachConnectorStringArgumentKey = "PlugAttachConnector002_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugAttachConnector002_StringArgument_Name", + "PlugAttachConnector002_StringArgument_Label", + "PlugAttachConnector002_StringArgument_Description", + "PlugAttachConnector002_StringArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorStringArgumentKey, testStringArgument); + + String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector002_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugAttachConnector002_IntegerArgument_Name", + "PlugAttachConnector002_IntegerArgument_Label", + "PlugAttachConnector002_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorIntegerArgumentKey, testIntegerArgument); + + String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector002_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugAttachConnector002_BooleanArgument_Name", + "PlugAttachConnector002_BooleanArgument_Label", + "PlugAttachConnector002_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorBooleanArgumentKey, testBooleanArgument); + + String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector002_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugAttachConnector002_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugAttachConnector002_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugAttachConnector002_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugAttachConnector002_SelectedArgument_Name", + "PlugAttachConnector002_SelectedArgument_Label", + "PlugAttachConnector002_SelectedArgument_Description", + "PlugAttachConnector002_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorSelectedArgumentKey, testSelectedArgument); + + return plugAttachConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugAttachConnector002() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugAttachConnector002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/plugAttachConnect002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/plugAttachConnect002.java new file mode 100644 index 00000000000..069a12aa7e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002/plugAttachConnect002.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the pluggable + * connector named "PlugAttachConnector002_Name" is created on base + * of PlugAttachConnector002 class which implements + * com.sun.jdi.connect.AttachingConnector interface. + * This pluggable connector has to be contained in lists returned + * by VirtualMachineManager.attachingConnectors() and + * by VirtualMachineManager.allConnectors() methods. + * This pluggable connector has to have: + * Connector.description() = "PlugAttachConnector002_Description"; + * Connector.transport().name() = "PlugAttachConnector002_Transport"; + * Connector.defaultArguments() = List of 4 Connector.Argument: + * Connector.StringArgument named + * 'PlugAttachConnector002_StringArgument_Name' + * Connector.IntegerArgument named + * 'PlugAttachConnector002_IntegerArgument_Name' + * Connector.BooleanArgument named + * 'PlugAttachConnector002_BooleanArgument_Name' + * Connector.SelectedArgument named + * 'PlugAttachConnector002_SelectedArgument_Name' + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect002.plugAttachConnect002 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect002.plugAttachConnect002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect002; + +import nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect002.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the pluggable
    + * connector named "PlugAttachConnector002_Name" is created on base
    + * of PlugAttachConnector002 class which implements
    + * com.sun.jdi.connect.AttachingConnector interface.
    + *
    + * This pluggable connector has to be contained in lists returned
    + * by VirtualMachineManager.attachingConnectors() and
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * This pluggable connector has to have:
    + * Connector.description() = "PlugAttachConnector002_Description";
    + * Connector.transport().name() = "PlugAttachConnector002_Transport";
    + * Connector.defaultArguments() = List of 4 Connector.Argument:
    + * Connector.StringArgument named
    + * 'PlugAttachConnector002_StringArgument_Name'
    + * Connector.IntegerArgument named
    + * 'PlugAttachConnector002_IntegerArgument_Name'
    + * Connector.BooleanArgument named
    + * 'PlugAttachConnector002_BooleanArgument_Name'
    + * Connector.SelectedArgument named
    + * 'PlugAttachConnector002_SelectedArgument_Name'
    + *
    + */ + +public class plugAttachConnect002 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugAttachConnect002: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugAttachConnect002: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugAttachConnect002().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + String checkedPlugAttachConnectorName = "PlugAttachConnector002_Name"; + String checkedPlugAttachConnectorDescription = "PlugAttachConnector002_Description"; + String checkedPlugAttachConnectorTransportName = "PlugAttachConnector002_Transport"; + + logAlways("==> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect002 test..."); + logOnVerbose + ("==> Test checks that expected pluggable attaching connector is created properly."); + + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that expected pluggable attaching connector is found out in attachingConnectors() List + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + checkedPlugAttachConnector = attachingConnector; + break; + } + } + + if ( checkedPlugAttachConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable attaching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugAttachConnectorName + "'"); + return STATUS_FAILED; + } + + // check that expected pluggable attaching connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean checkedPlugAttachConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof AttachingConnector ) { + AttachingConnector foundAttachingConnector = (AttachingConnector)foundConnector; + if ( checkedPlugAttachConnector.equals(foundAttachingConnector) ) { + checkedPlugAttachConnectorFound = true; + break; + } + } + } + + if ( ! checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable attaching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugAttachConnector); + testResult = STATUS_FAILED; + } + + + AttachingConnector referencePlugAttachConnector = new PlugAttachConnector002(); + + String emptyString = ""; + String errorMessage = PlugConnectors.compareConnectors( + errorLogPrefixHead, + errorLogPrefix, + referencePlugAttachConnector, + checkedPlugAttachConnector); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + return STATUS_FAILED; + } + + // check default Arguments of checked pluggable connector + + // strings below are for info only +// String plugAttachConnectorStringArgumentKey = "PlugAttachConnector002_StringArgument_Key"; +// String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector002_IntegerArgument_Key"; +// String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector002_BooleanArgument_Key"; +// String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector002_SelectedArgument_Key"; + + Map referenceDefaultArguments = referencePlugAttachConnector.defaultArguments(); + Map checkedDefaultArguments = checkedPlugAttachConnector.defaultArguments(); + + int referenceDefaultArgumentsNumber = referenceDefaultArguments.size(); + Object[] referenceDefaultArgumentsKeys = referenceDefaultArguments.keySet().toArray(); + for (int i=0; i < referenceDefaultArgumentsNumber; i++) { + String referenceKey = (String)referenceDefaultArgumentsKeys[i]; + Connector.Argument referenceArgument = + (Connector.Argument)(referenceDefaultArguments.get(referenceKey)); + Connector.Argument checkedArgument = + (Connector.Argument)(checkedDefaultArguments.get(referenceKey)); + errorMessage = PlugConnectors.compareConnectorArguments( + errorLogPrefixHead, + errorLogPrefix, + referenceArgument, + checkedArgument); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + testResult = STATUS_FAILED; + } + } + + return testResult; + } +} // end of plugAttachConnect002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..7c5e0289f98 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003 test +nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect003.connectors.PlugAttachConnector003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/connectors/PlugAttachConnector003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/connectors/PlugAttachConnector003.java new file mode 100644 index 00000000000..7a9d285cc74 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/connectors/PlugAttachConnector003.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector used by + * nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003 test + */ + +package nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect003.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector003 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName = "PlugAttachConnector003_Name"; + static String plugAttachConnectorDescription = "PlugAttachConnector003_Description"; + static Transport plugAttachConnectorTransport = new PlugConnectorsTransport("PlugAttachConnector003_Transport"); + static Map plugAttachConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugAttachConnectorStringArgumentKey = "PlugAttachConnector003_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugAttachConnector003_StringArgument_Name", + "PlugAttachConnector003_StringArgument_Label", + "PlugAttachConnector003_StringArgument_Description", + "PlugAttachConnector003_StringArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorStringArgumentKey, testStringArgument); + + String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector003_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugAttachConnector003_IntegerArgument_Name", + "PlugAttachConnector003_IntegerArgument_Label", + "PlugAttachConnector003_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorIntegerArgumentKey, testIntegerArgument); + + String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector003_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugAttachConnector003_BooleanArgument_Name", + "PlugAttachConnector003_BooleanArgument_Label", + "PlugAttachConnector003_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorBooleanArgumentKey, testBooleanArgument); + + String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector003_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugAttachConnector003_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugAttachConnector003_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugAttachConnector003_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugAttachConnector003_SelectedArgument_Name", + "PlugAttachConnector003_SelectedArgument_Label", + "PlugAttachConnector003_SelectedArgument_Description", + "PlugAttachConnector003_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorSelectedArgumentKey, testSelectedArgument); + + return plugAttachConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugAttachConnector003() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugAttachConnector003: This RuntimeException is thrown intentionally by AttachingConnector " + + "constructor to check creating of pluggable connectors on base of such AttachingConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugAttachConnector003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/plugAttachConnect003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/plugAttachConnect003.java new file mode 100644 index 00000000000..86e5db26754 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003/plugAttachConnect003.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked a pluggable + * connector is NOT created on base of PlugAttachConnector003 class + * which implements com.sun.jdi.connect.AttachingConnector interface, + * but constructor of PlugAttachConnector003 throws Exception. + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect003.plugAttachConnect003 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect003.plugAttachConnect003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect003; + +import nsk.jdi.PlugConnectors.AttachConnector.plugAttachConnect003.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked a pluggable
    + * connector is NOT created on base of PlugAttachConnector003 class
    + * which implements com.sun.jdi.connect.AttachingConnector interface,
    + * but constructor of PlugAttachConnector003 throws Exception.
    + *
    + */ + +public class plugAttachConnect003 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugAttachConnect003: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugAttachConnect003: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugAttachConnect003().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/AttachConnector/plugAttachConnect003 test..."); + logOnVerbose + ("==> Test checks that pluggable attaching connector is NOT created."); + logOnVerbose + (" for AttachingConnector implementation for which instance can not be created."); + + + VirtualMachineManager virtualMachineManager = null; + try { + virtualMachineManager = Bootstrap.virtualMachineManager(); + } catch (Throwable thrown) { + // OK: Bootstrap.virtualMachineManager() may throw an unspecified error + // if initialization of the VirtualMachineManager fails or if the virtual + // machine manager is unable to locate or create any Connectors. + logOnVerbose + (infoLogPrefixNead + "Bootstrap.virtualMachineManager() throws:\n" + thrown); + return STATUS_PASSED; + } + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that pluggable attaching connector is NOT created on base of AttachingConnector + // implementation (PlugAttachConnector003 class) for which instance can not be created + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + if ( attachingConnector instanceof PlugAttachConnector003 ) { + checkedPlugAttachConnector = attachingConnector; + break; + } + } + + if ( checkedPlugAttachConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector is created on base of AttachingConnector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in attachingConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnector.name() + "'"); + testResult = STATUS_FAILED; + } + + + // check that pluggable connectors are NOT contained in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + Connector foundAttachConnector = null; + for (int i=0; i < allConnectorsNumber; i++ ){ + Connector connector = (Connector)allConnectorsList.get(i); + if ( connector instanceof PlugAttachConnector003 ) { + foundAttachConnector = connector; + break; + } + } + + if ( foundAttachConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector is created on base of AttachingConnector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + foundAttachConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + foundAttachConnector.name() + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of plugAttachConnect003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..e047eb85641 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001 test +nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect001.connectors.PlugLaunchConnector001 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/connectors/PlugLaunchConnector001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/connectors/PlugLaunchConnector001.java new file mode 100644 index 00000000000..1ecc906747d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/connectors/PlugLaunchConnector001.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector used by + * nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001 test + */ + +package nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugLaunchConnector001 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName = "PlugLaunchConnector001_Name"; + static String plugLaunchConnectorDescription = "PlugLaunchConnector001_Description"; + static Transport plugLaunchConnectorTransport = new PlugConnectorsTransport("PlugLaunchConnector001_Transport"); + static Map plugLaunchConnectorDefaultArguments = new HashMap(); + + + public PlugLaunchConnector001() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + plugLaunchConnectorDefaultArguments); + } + +} // end of PlugLaunchConnector001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/plugLaunchConnect001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/plugLaunchConnect001.java new file mode 100644 index 00000000000..6a14a703b51 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001/plugLaunchConnect001.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the pluggable + * connector named "PlugLaunchConnector001_Name" is created on base + * of PlugLaunchConnector001 class which implements + * com.sun.jdi.connect.LaunchingConnector interface. + * This pluggable connector has to be contained in lists returned + * by VirtualMachineManager.launchingConnectors() and + * by VirtualMachineManager.allConnectors() methods. + * This pluggable connector has to have: + * Connector.description() = "PlugLaunchConnector001_Description"; + * Connector.transport().name() = "PlugLaunchConnector001_Transport"; + * Connector.defaultArguments() = , i.e without arguments; + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect001.plugLaunchConnect001 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect001.plugLaunchConnect001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect001; + +import nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect001.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the pluggable
    + * connector named "PlugLaunchConnector001_Name" is created on base
    + * of PlugLaunchConnector001 class which implements
    + * com.sun.jdi.connect.LaunchingConnector interface.
    + *
    + * This pluggable connector has to be contained in lists returned
    + * by VirtualMachineManager.launchingConnectors() and
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * This pluggable connector has to have:
    + * Connector.description() = "PlugLaunchConnector001_Description";
    + * Connector.transport().name() = "PlugLaunchConnector001_Transport";
    + * Connector.defaultArguments() = , i.e without arguments;
    + *
    + */ + +public class plugLaunchConnect001 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugLaunchConnect001: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugLaunchConnect001: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugLaunchConnect001().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + String expectedPlugLaunchConnectorName = "PlugLaunchConnector001_Name"; + String expectedPlugLaunchConnectorDescription = "PlugLaunchConnector001_Description"; + String expectedPlugLaunchConnectorTransportName = "PlugLaunchConnector001_Transport"; + + logAlways("==> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect001 test..."); + logOnVerbose + ("==> Test checks that expected pluggable launching connector is created properly."); + + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that expected pluggable launching connector is found out in launchingConnectors() List + List launchingConnectorsList = virtualMachineManager.launchingConnectors(); + int launchingConnectorsNumber = launchingConnectorsList.size(); + LaunchingConnector expectedPlugLaunchConnector = null; + + for (int i=0; i < launchingConnectorsNumber; i++ ) { + LaunchingConnector launchingConnector = (LaunchingConnector)launchingConnectorsList.get(i); + String launchConnectorName = launchingConnector.name(); + if ( expectedPlugLaunchConnectorName.equals(launchConnectorName) ) { + expectedPlugLaunchConnector = launchingConnector; + break; + } + } + + if ( expectedPlugLaunchConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable launching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + expectedPlugLaunchConnectorName + "'"); + return STATUS_FAILED; + } + + // check that expected pluggable launching connector has expected description + String actualDescription = expectedPlugLaunchConnector.description(); + if ( ! expectedPlugLaunchConnectorDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable launching connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Expected descripton = '" + expectedPlugLaunchConnectorDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable launching connector has expected transport name + String actualTransportName = expectedPlugLaunchConnector.transport().name(); + if ( ! expectedPlugLaunchConnectorTransportName.equals(actualTransportName) ) { + logOnError(errorLogPrefixHead + "Pluggable launching connector has unexpected Transport:"); + logOnError + (errorLogPrefix + "Expected Transport name = '" + expectedPlugLaunchConnectorTransportName + "'"); + logOnError(errorLogPrefix + "Actual Transport name = '" + actualTransportName + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable launching connector has not defaultArguments + Map actualDefaultArguments = expectedPlugLaunchConnector.defaultArguments(); + int actualDefaultArgumentsNumber = actualDefaultArguments.size(); + if ( actualDefaultArgumentsNumber != 0 ) { + logOnError(errorLogPrefixHead + "Pluggable launching connector has unexpected defaultArguments:"); + logOnError(errorLogPrefix + "Expected defaultArguments Map - "); + logOnError(errorLogPrefix + "Actual defaultArguments Map size = " + actualDefaultArgumentsNumber); + testResult = STATUS_FAILED; + } + + // check that expected pluggable launching connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean expectedPlugLaunchConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof LaunchingConnector ) { + LaunchingConnector foundLaunchingConnector = (LaunchingConnector)foundConnector; + if ( expectedPlugLaunchConnector.equals(foundLaunchingConnector) ) { + expectedPlugLaunchConnectorFound = true; + break; + } + } + } + + if ( ! expectedPlugLaunchConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable launching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + expectedPlugLaunchConnector); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of plugLaunchConnect001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..6a22ad45034 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002 test +nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect002.connectors.PlugLaunchConnector002 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/connectors/PlugLaunchConnector002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/connectors/PlugLaunchConnector002.java new file mode 100644 index 00000000000..e286eaed3cb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/connectors/PlugLaunchConnector002.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector used by + * nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002 test + */ + +package nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugLaunchConnector002 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName = "PlugLaunchConnector002_Name"; + static String plugLaunchConnectorDescription = "PlugLaunchConnector002_Description"; + static Transport plugLaunchConnectorTransport = new PlugConnectorsTransport("PlugLaunchConnector002_Transport"); + static Map plugLaunchConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector002_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugLaunchConnector002_StringArgument_Name", + "PlugLaunchConnector002_StringArgument_Label", + "PlugLaunchConnector002_StringArgument_Description", + "PlugLaunchConnector002_StringArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorStringArgumentKey, testStringArgument); + + String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector002_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugLaunchConnector002_IntegerArgument_Name", + "PlugLaunchConnector002_IntegerArgument_Label", + "PlugLaunchConnector002_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorIntegerArgumentKey, testIntegerArgument); + + String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector002_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugLaunchConnector002_BooleanArgument_Name", + "PlugLaunchConnector002_BooleanArgument_Label", + "PlugLaunchConnector002_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorBooleanArgumentKey, testBooleanArgument); + + String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector002_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugLaunchConnector002_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugLaunchConnector002_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugLaunchConnector002_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugLaunchConnector002_SelectedArgument_Name", + "PlugLaunchConnector002_SelectedArgument_Label", + "PlugLaunchConnector002_SelectedArgument_Description", + "PlugLaunchConnector002_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorSelectedArgumentKey, testSelectedArgument); + + return plugLaunchConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugLaunchConnector002() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugLaunchConnector002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/plugLaunchConnect002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/plugLaunchConnect002.java new file mode 100644 index 00000000000..d1857f44d6c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002/plugLaunchConnect002.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the pluggable + * connector named "PlugLaunchConnector002_Name" is created on base + * of PlugLaunchConnector002 class which implements + * com.sun.jdi.connect.LaunchingConnector interface. + * This pluggable connector has to be contained in lists returned + * by VirtualMachineManager.launchingConnectors() and + * by VirtualMachineManager.allConnectors() methods. + * This pluggable connector has to have: + * Connector.description() = "PlugLaunchConnector002_Description"; + * Connector.transport().name() = "PlugLaunchConnector002_Transport"; + * Connector.defaultArguments() = List of 4 Connector.Argument: + * Connector.StringArgument named + * 'PlugLaunchConnector002_StringArgument_Name' + * Connector.IntegerArgument named + * 'PlugLaunchConnector002_IntegerArgument_Name' + * Connector.BooleanArgument named + * 'PlugLaunchConnector002_BooleanArgument_Name' + * Connector.SelectedArgument named + * 'PlugLaunchConnector002_SelectedArgument_Name' + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect002.plugLaunchConnect002 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect002.plugLaunchConnect002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect002; + +import nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect002.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the pluggable
    + * connector named "PlugLaunchConnector002_Name" is created on base
    + * of PlugLaunchConnector002 class which implements
    + * com.sun.jdi.connect.LaunchingConnector interface.
    + *
    + * This pluggable connector has to be contained in lists returned
    + * by VirtualMachineManager.launchingConnectors() and
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * This pluggable connector has to have:
    + * Connector.description() = "PlugLaunchConnector002_Description";
    + * Connector.transport().name() = "PlugLaunchConnector002_Transport";
    + * Connector.defaultArguments() = List of 4 Connector.Argument:
    + * Connector.StringArgument named
    + * 'PlugLaunchConnector002_StringArgument_Name'
    + * Connector.IntegerArgument named
    + * 'PlugLaunchConnector002_IntegerArgument_Name'
    + * Connector.BooleanArgument named
    + * 'PlugLaunchConnector002_BooleanArgument_Name'
    + * Connector.SelectedArgument named
    + * 'PlugLaunchConnector002_SelectedArgument_Name'
    + *
    + */ + +public class plugLaunchConnect002 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugLaunchConnect002: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugLaunchConnect002: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugLaunchConnect002().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + String checkedPlugLaunchConnectorName = "PlugLaunchConnector002_Name"; + String checkedPlugLaunchConnectorDescription = "PlugLaunchConnector002_Description"; + String checkedPlugLaunchConnectorTransportName = "PlugLaunchConnector002_Transport"; + + logAlways("==> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect002 test..."); + logOnVerbose + ("==> Test checks that expected pluggable launching connector is created properly."); + + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that expected pluggable launching connector is found out in launchingConnectors() List + List launchingConnectorsList = virtualMachineManager.launchingConnectors(); + int launchingConnectorsNumber = launchingConnectorsList.size(); + LaunchingConnector checkedPlugLaunchConnector = null; + + for (int i=0; i < launchingConnectorsNumber; i++ ) { + LaunchingConnector launchingConnector = (LaunchingConnector)launchingConnectorsList.get(i); + String launchConnectorName = launchingConnector.name(); + if ( checkedPlugLaunchConnectorName.equals(launchConnectorName) ) { + checkedPlugLaunchConnector = launchingConnector; + break; + } + } + + if ( checkedPlugLaunchConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable launching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugLaunchConnectorName + "'"); + return STATUS_FAILED; + } + + // check that expected pluggable launching connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean checkedPlugLaunchConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof LaunchingConnector ) { + LaunchingConnector foundLaunchingConnector = (LaunchingConnector)foundConnector; + if ( checkedPlugLaunchConnector.equals(foundLaunchingConnector) ) { + checkedPlugLaunchConnectorFound = true; + break; + } + } + } + + if ( ! checkedPlugLaunchConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable launching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugLaunchConnector); + testResult = STATUS_FAILED; + } + + + LaunchingConnector referencePlugLaunchConnector = new PlugLaunchConnector002(); + + String emptyString = ""; + String errorMessage = PlugConnectors.compareConnectors( + errorLogPrefixHead, + errorLogPrefix, + referencePlugLaunchConnector, + checkedPlugLaunchConnector); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + return STATUS_FAILED; + } + + // check default Arguments of checked pluggable connector + + // strings below are for info only +// String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector002_StringArgument_Key"; +// String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector002_IntegerArgument_Key"; +// String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector002_BooleanArgument_Key"; +// String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector002_SelectedArgument_Key"; + + Map referenceDefaultArguments = referencePlugLaunchConnector.defaultArguments(); + Map checkedDefaultArguments = checkedPlugLaunchConnector.defaultArguments(); + + int referenceDefaultArgumentsNumber = referenceDefaultArguments.size(); + Object[] referenceDefaultArgumentsKeys = referenceDefaultArguments.keySet().toArray(); + for (int i=0; i < referenceDefaultArgumentsNumber; i++) { + String referenceKey = (String)referenceDefaultArgumentsKeys[i]; + Connector.Argument referenceArgument = + (Connector.Argument)(referenceDefaultArguments.get(referenceKey)); + Connector.Argument checkedArgument = + (Connector.Argument)(checkedDefaultArguments.get(referenceKey)); + errorMessage = PlugConnectors.compareConnectorArguments( + errorLogPrefixHead, + errorLogPrefix, + referenceArgument, + checkedArgument); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + testResult = STATUS_FAILED; + } + } + + return testResult; + } +} // end of plugLaunchConnect002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..9818c34574a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003 test +nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect003.connectors.PlugLaunchConnector003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/connectors/PlugLaunchConnector003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/connectors/PlugLaunchConnector003.java new file mode 100644 index 00000000000..972ef8be85a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/connectors/PlugLaunchConnector003.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector used by + * nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003 test + */ + +package nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect003.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugLaunchConnector003 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName = "PlugLaunchConnector003_Name"; + static String plugLaunchConnectorDescription = "PlugLaunchConnector003_Description"; + static Transport plugLaunchConnectorTransport = new PlugConnectorsTransport("PlugLaunchConnector003_Transport"); + static Map plugLaunchConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector003_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugLaunchConnector003_StringArgument_Name", + "PlugLaunchConnector003_StringArgument_Label", + "PlugLaunchConnector003_StringArgument_Description", + "PlugLaunchConnector003_StringArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorStringArgumentKey, testStringArgument); + + String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector003_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugLaunchConnector003_IntegerArgument_Name", + "PlugLaunchConnector003_IntegerArgument_Label", + "PlugLaunchConnector003_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorIntegerArgumentKey, testIntegerArgument); + + String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector003_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugLaunchConnector003_BooleanArgument_Name", + "PlugLaunchConnector003_BooleanArgument_Label", + "PlugLaunchConnector003_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorBooleanArgumentKey, testBooleanArgument); + + String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector003_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugLaunchConnector003_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugLaunchConnector003_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugLaunchConnector003_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugLaunchConnector003_SelectedArgument_Name", + "PlugLaunchConnector003_SelectedArgument_Label", + "PlugLaunchConnector003_SelectedArgument_Description", + "PlugLaunchConnector003_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorSelectedArgumentKey, testSelectedArgument); + + return plugLaunchConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugLaunchConnector003() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugLaunchConnector003: This RuntimeException is thrown intentionally by LaunchingConnector " + + "constructor to check creating of pluggable connectors on base of such LaunchingConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugLaunchConnector003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/plugLaunchConnect003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/plugLaunchConnect003.java new file mode 100644 index 00000000000..d709b531b70 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003/plugLaunchConnect003.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked a pluggable + * connector is NOT created on base of PlugLaunchConnector003 class + * which implements com.sun.jdi.connect.LaunchingConnector interface, + * but constructor of PlugLaunchConnector003 throws Exception. + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect003.plugLaunchConnect003 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect003.plugLaunchConnect003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect003; + +import nsk.jdi.PlugConnectors.LaunchConnector.plugLaunchConnect003.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked a pluggable
    + * connector is NOT created on base of PlugLaunchConnector003 class
    + * which implements com.sun.jdi.connect.LaunchingConnector interface,
    + * but constructor of PlugLaunchConnector003 throws Exception.
    + *
    + */ + +public class plugLaunchConnect003 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugLaunchConnect003: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugLaunchConnect003: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugLaunchConnect003().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/LaunchConnector/plugLaunchConnect003 test..."); + logOnVerbose + ("==> Test checks that pluggable launching connector is NOT created."); + logOnVerbose + (" for LaunchingConnector implementation for which instance can not be created."); + + + VirtualMachineManager virtualMachineManager = null; + try { + virtualMachineManager = Bootstrap.virtualMachineManager(); + } catch (Throwable thrown) { + // OK: Bootstrap.virtualMachineManager() may throw an unspecified error + // if initialization of the VirtualMachineManager fails or if the virtual + // machine manager is unable to locate or create any Connectors. + logOnVerbose + (infoLogPrefixNead + "Bootstrap.virtualMachineManager() throws:\n" + thrown); + return STATUS_PASSED; + } + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that pluggable launching connector is NOT created on base of LaunchingConnector + // implementation (PlugLaunchConnector003 class) for which instance can not be created + List launchingConnectorsList = virtualMachineManager.launchingConnectors(); + int launchingConnectorsNumber = launchingConnectorsList.size(); + LaunchingConnector checkedPlugLaunchConnector = null; + + for (int i=0; i < launchingConnectorsNumber; i++ ) { + LaunchingConnector launchingConnector = (LaunchingConnector)launchingConnectorsList.get(i); + if ( launchingConnector instanceof PlugLaunchConnector003 ) { + checkedPlugLaunchConnector = launchingConnector; + break; + } + } + + if ( checkedPlugLaunchConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable launching connector is created on base of LaunchingConnector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in launchingConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugLaunchConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugLaunchConnector.name() + "'"); + testResult = STATUS_FAILED; + } + + + // check that pluggable connectors are NOT contained in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + Connector foundLaunchConnector = null; + for (int i=0; i < allConnectorsNumber; i++ ){ + Connector connector = (Connector)allConnectorsList.get(i); + if ( connector instanceof PlugLaunchConnector003 ) { + foundLaunchConnector = connector; + break; + } + } + + if ( foundLaunchConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable launching connector is created on base of LaunchingConnector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + foundLaunchConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + foundLaunchConnector.name() + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of plugLaunchConnect003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..87c1c464d68 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001 test +nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect001.connectors.PlugListenConnector001 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/connectors/PlugListenConnector001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/connectors/PlugListenConnector001.java new file mode 100644 index 00000000000..7e5b7634306 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/connectors/PlugListenConnector001.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector used by + * nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001 test + */ + +package nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugListenConnector001 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName = "PlugListenConnector001_Name"; + static String plugListenConnectorDescription = "PlugListenConnector001_Description"; + static Transport plugListenConnectorTransport = new PlugConnectorsTransport("PlugListenConnector001_Transport"); + static Map plugListenConnectorDefaultArguments = new HashMap(); + + + public PlugListenConnector001() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + plugListenConnectorDefaultArguments); + } + +} // end of PlugListenConnector001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/plugListenConnect001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/plugListenConnect001.java new file mode 100644 index 00000000000..8042bf4e752 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001/plugListenConnect001.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LauWnchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the pluggable + * connector named "PlugListenConnector001_Name" is created on base + * of PlugListenConnector001 class which implements + * com.sun.jdi.connect.ListeningConnector interface. + * This pluggable connector has to be contained in lists returned + * by VirtualMachineManager.listeningConnectors() and + * by VirtualMachineManager.allConnectors() methods. + * This pluggable connector has to have: + * Connector.description() = "PlugListenConnector001_Description"; + * Connector.transport().name() = "PlugListenConnector001_Transport"; + * Connector.defaultArguments() = , i.e without arguments; + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect001.plugListenConnect001 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect001.plugListenConnect001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect001; + +import nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect001.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the pluggable
    + * connector named "PlugListenConnector001_Name" is created on base
    + * of PlugListenConnector001 class which implements
    + * com.sun.jdi.connect.ListeningConnector interface.
    + *
    + * This pluggable connector has to be contained in lists returned
    + * by VirtualMachineManager.listeningConnectors() and
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * This pluggable connector has to have:
    + * Connector.description() = "PlugListenConnector001_Description";
    + * Connector.transport().name() = "PlugListenConnector001_Transport";
    + * Connector.defaultArguments() = , i.e without arguments;
    + *
    + */ + +public class plugListenConnect001 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugListenConnect001: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugListenConnect001: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugListenConnect001().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + String expectedPlugListenConnectorName = "PlugListenConnector001_Name"; + String expectedPlugListenConnectorDescription = "PlugListenConnector001_Description"; + String expectedPlugListenConnectorTransportName = "PlugListenConnector001_Transport"; + + logAlways("==> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect001 test..."); + logOnVerbose + ("==> Test checks that expected pluggable listening connector is created properly."); + + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in listeningConnectors() List + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector expectedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( expectedPlugListenConnectorName.equals(listenConnectorName) ) { + expectedPlugListenConnector = listeningConnector; + break; + } + } + + if ( expectedPlugListenConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable listening connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + expectedPlugListenConnectorName + "'"); + return STATUS_FAILED; + } + + // check that expected pluggable listening connector has expected description + String actualDescription = expectedPlugListenConnector.description(); + if ( ! expectedPlugListenConnectorDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Expected descripton = '" + expectedPlugListenConnectorDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector has expected transport name + String actualTransportName = expectedPlugListenConnector.transport().name(); + if ( ! expectedPlugListenConnectorTransportName.equals(actualTransportName) ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected Transport:"); + logOnError + (errorLogPrefix + "Expected Transport name = '" + expectedPlugListenConnectorTransportName + "'"); + logOnError(errorLogPrefix + "Actual Transport name = '" + actualTransportName + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector has not defaultArguments + Map actualDefaultArguments = expectedPlugListenConnector.defaultArguments(); + int actualDefaultArgumentsNumber = actualDefaultArguments.size(); + if ( actualDefaultArgumentsNumber != 0 ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected defaultArguments:"); + logOnError(errorLogPrefix + "Expected defaultArguments Map - "); + logOnError(errorLogPrefix + "Actual defaultArguments Map size = " + actualDefaultArgumentsNumber); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean expectedPlugListenConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof ListeningConnector ) { + ListeningConnector foundListeningConnector = (ListeningConnector)foundConnector; + if ( expectedPlugListenConnector.equals(foundListeningConnector) ) { + expectedPlugListenConnectorFound = true; + break; + } + } + } + + if ( ! expectedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable listening connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + expectedPlugListenConnector); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of plugListenConnect001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..c02f00c5b3f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002 test +nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect002.connectors.PlugListenConnector002 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/connectors/PlugListenConnector002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/connectors/PlugListenConnector002.java new file mode 100644 index 00000000000..b4c5cdfde17 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/connectors/PlugListenConnector002.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector used by + * nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002 test + */ + +package nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugListenConnector002 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName = "PlugListenConnector002_Name"; + static String plugListenConnectorDescription = "PlugListenConnector002_Description"; + static Transport plugListenConnectorTransport = new PlugConnectorsTransport("PlugListenConnector002_Transport"); + static Map plugListenConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugListenConnectorStringArgumentKey = "PlugListenConnector002_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugListenConnector002_StringArgument_Name", + "PlugListenConnector002_StringArgument_Label", + "PlugListenConnector002_StringArgument_Description", + "PlugListenConnector002_StringArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorStringArgumentKey, testStringArgument); + + String plugListenConnectorIntegerArgumentKey = "PlugListenConnector002_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugListenConnector002_IntegerArgument_Name", + "PlugListenConnector002_IntegerArgument_Label", + "PlugListenConnector002_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorIntegerArgumentKey, testIntegerArgument); + + String plugListenConnectorBooleanArgumentKey = "PlugListenConnector002_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugListenConnector002_BooleanArgument_Name", + "PlugListenConnector002_BooleanArgument_Label", + "PlugListenConnector002_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorBooleanArgumentKey, testBooleanArgument); + + String plugListenConnectorSelectedArgumentKey = "PlugListenConnector002_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugListenConnector002_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugListenConnector002_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugListenConnector002_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugListenConnector002_SelectedArgument_Name", + "PlugListenConnector002_SelectedArgument_Label", + "PlugListenConnector002_SelectedArgument_Description", + "PlugListenConnector002_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorSelectedArgumentKey, testSelectedArgument); + + return plugListenConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugListenConnector002() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugListenConnector002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/plugListenConnect002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/plugListenConnect002.java new file mode 100644 index 00000000000..342fc7e3e74 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002/plugListenConnect002.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the pluggable + * connector named "PlugListenConnector002_Name" is created on base + * of PlugListenConnector002 class which implements + * com.sun.jdi.connect.ListeningConnector interface. + * This pluggable connector has to be contained in lists returned + * by VirtualMachineManager.listeningConnectors() and + * by VirtualMachineManager.allConnectors() methods. + * This pluggable connector has to have: + * Connector.description() = "PlugListenConnector002_Description"; + * Connector.transport().name() = "PlugListenConnector002_Transport"; + * Connector.defaultArguments() = List of 4 Connector.Argument: + * Connector.StringArgument named + * 'PlugListenConnector002_StringArgument_Name' + * Connector.IntegerArgument named + * 'PlugListenConnector002_IntegerArgument_Name' + * Connector.BooleanArgument named + * 'PlugListenConnector002_BooleanArgument_Name' + * Connector.SelectedArgument named + * 'PlugListenConnector002_SelectedArgument_Name' + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect002.plugListenConnect002 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect002.plugListenConnect002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect002; + +import nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect002.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the pluggable
    + * connector named "PlugListenConnector002_Name" is created on base
    + * of PlugListenConnector002 class which implements
    + * com.sun.jdi.connect.ListeningConnector interface.
    + *
    + * This pluggable connector has to be contained in lists returned
    + * by VirtualMachineManager.listeningConnectors() and
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * This pluggable connector has to have:
    + * Connector.description() = "PlugListenConnector002_Description";
    + * Connector.transport().name() = "PlugListenConnector002_Transport";
    + * Connector.defaultArguments() = List of 4 Connector.Argument:
    + * Connector.StringArgument named
    + * 'PlugListenConnector002_StringArgument_Name'
    + * Connector.IntegerArgument named
    + * 'PlugListenConnector002_IntegerArgument_Name'
    + * Connector.BooleanArgument named
    + * 'PlugListenConnector002_BooleanArgument_Name'
    + * Connector.SelectedArgument named
    + * 'PlugListenConnector002_SelectedArgument_Name'
    + *
    + */ + +public class plugListenConnect002 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugListenConnect002: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugListenConnect002: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugListenConnect002().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + String checkedPlugListenConnectorName = "PlugListenConnector002_Name"; + String checkedPlugListenConnectorDescription = "PlugListenConnector002_Description"; + String checkedPlugListenConnectorTransportName = "PlugListenConnector002_Transport"; + + logAlways("==> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect002 test..."); + logOnVerbose + ("==> Test checks that expected pluggable listening connector is created properly."); + + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in listeningConnectors() List + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + checkedPlugListenConnector = listeningConnector; + break; + } + } + + if ( checkedPlugListenConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable listening connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugListenConnectorName + "'"); + return STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean checkedPlugListenConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof ListeningConnector ) { + ListeningConnector foundListeningConnector = (ListeningConnector)foundConnector; + if ( checkedPlugListenConnector.equals(foundListeningConnector) ) { + checkedPlugListenConnectorFound = true; + break; + } + } + } + + if ( ! checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable listening connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugListenConnector); + testResult = STATUS_FAILED; + } + + + ListeningConnector referencePlugListenConnector = new PlugListenConnector002(); + + String emptyString = ""; + String errorMessage = PlugConnectors.compareConnectors( + errorLogPrefixHead, + errorLogPrefix, + referencePlugListenConnector, + checkedPlugListenConnector); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + return STATUS_FAILED; + } + + // check default Arguments of checked pluggable connector + + // strings below are for info only +// String plugListenConnectorStringArgumentKey = "PlugListenConnector002_StringArgument_Key"; +// String plugListenConnectorIntegerArgumentKey = "PlugListenConnector002_IntegerArgument_Key"; +// String plugListenConnectorBooleanArgumentKey = "PlugListenConnector002_BooleanArgument_Key"; +// String plugListenConnectorSelectedArgumentKey = "PlugListenConnector002_SelectedArgument_Key"; + + Map referenceDefaultArguments = referencePlugListenConnector.defaultArguments(); + Map checkedDefaultArguments = checkedPlugListenConnector.defaultArguments(); + + int referenceDefaultArgumentsNumber = referenceDefaultArguments.size(); + Object[] referenceDefaultArgumentsKeys = referenceDefaultArguments.keySet().toArray(); + for (int i=0; i < referenceDefaultArgumentsNumber; i++) { + String referenceKey = (String)referenceDefaultArgumentsKeys[i]; + Connector.Argument referenceArgument = + (Connector.Argument)(referenceDefaultArguments.get(referenceKey)); + Connector.Argument checkedArgument = + (Connector.Argument)(checkedDefaultArguments.get(referenceKey)); + errorMessage = PlugConnectors.compareConnectorArguments( + errorLogPrefixHead, + errorLogPrefix, + referenceArgument, + checkedArgument); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + testResult = STATUS_FAILED; + } + } + + return testResult; + } +} // end of plugListenConnect002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..559cb0022b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003 test +nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect003.connectors.PlugListenConnector003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/connectors/PlugListenConnector003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/connectors/PlugListenConnector003.java new file mode 100644 index 00000000000..264f60d0f7c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/connectors/PlugListenConnector003.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector used by + * nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003 test + */ + +package nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect003.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugListenConnector003 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName = "PlugListenConnector003_Name"; + static String plugListenConnectorDescription = "PlugListenConnector003_Description"; + static Transport plugListenConnectorTransport = new PlugConnectorsTransport("PlugListenConnector003_Transport"); + static Map plugListenConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugListenConnectorStringArgumentKey = "PlugListenConnector003_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugListenConnector003_StringArgument_Name", + "PlugListenConnector003_StringArgument_Label", + "PlugListenConnector003_StringArgument_Description", + "PlugListenConnector003_StringArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorStringArgumentKey, testStringArgument); + + String plugListenConnectorIntegerArgumentKey = "PlugListenConnector003_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugListenConnector003_IntegerArgument_Name", + "PlugListenConnector003_IntegerArgument_Label", + "PlugListenConnector003_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorIntegerArgumentKey, testIntegerArgument); + + String plugListenConnectorBooleanArgumentKey = "PlugListenConnector003_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugListenConnector003_BooleanArgument_Name", + "PlugListenConnector003_BooleanArgument_Label", + "PlugListenConnector003_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorBooleanArgumentKey, testBooleanArgument); + + String plugListenConnectorSelectedArgumentKey = "PlugListenConnector003_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugListenConnector003_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugListenConnector003_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugListenConnector003_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugListenConnector003_SelectedArgument_Name", + "PlugListenConnector003_SelectedArgument_Label", + "PlugListenConnector003_SelectedArgument_Description", + "PlugListenConnector003_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorSelectedArgumentKey, testSelectedArgument); + + return plugListenConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugListenConnector003() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugListenConnector003: This RuntimeException is thrown intentionally by ListeningConnector " + + "constructor to check creating of pluggable connectors on base of such ListeningConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugListenConnector003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/plugListenConnect003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/plugListenConnect003.java new file mode 100644 index 00000000000..4977185d81a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003/plugListenConnect003.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked a pluggable + * connector is NOT created on base of PlugListenConnector003 class + * which implements com.sun.jdi.connect.ListeningConnector interface, + * but constructor of PlugListenConnector003 throws Exception. + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect003.plugListenConnect003 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect003.plugListenConnect003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect003; + +import nsk.jdi.PlugConnectors.ListenConnector.plugListenConnect003.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked a pluggable
    + * connector is NOT created on base of PlugListenConnector003 class
    + * which implements com.sun.jdi.connect.ListeningConnector interface,
    + * but constructor of PlugListenConnector003 throws Exception.
    + *
    + */ + +public class plugListenConnect003 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugListenConnect003: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugListenConnect003: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugListenConnect003().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/ListenConnector/plugListenConnect003 test..."); + logOnVerbose + ("==> Test checks that pluggable listening connector is NOT created."); + logOnVerbose + (" for ListeningConnector implementation for which instance can not be created."); + + + VirtualMachineManager virtualMachineManager = null; + try { + virtualMachineManager = Bootstrap.virtualMachineManager(); + } catch (Throwable thrown) { + // OK: Bootstrap.virtualMachineManager() may throw an unspecified error + // if initialization of the VirtualMachineManager fails or if the virtual + // machine manager is unable to locate or create any Connectors. + logOnVerbose + (infoLogPrefixNead + "Bootstrap.virtualMachineManager() throws:\n" + thrown); + return STATUS_PASSED; + } + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check that pluggable listening connector is NOT created on base of ListeningConnector + // implementation (PlugListenConnector003 class) for which instance can not be created + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + if ( listeningConnector instanceof PlugListenConnector003 ) { + checkedPlugListenConnector = listeningConnector; + break; + } + } + + if ( checkedPlugListenConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector is created on base of ListeningConnector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in listeningConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnector.name() + "'"); + testResult = STATUS_FAILED; + } + + + // check that pluggable connectors are NOT contained in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + Connector foundListenConnector = null; + for (int i=0; i < allConnectorsNumber; i++ ){ + Connector connector = (Connector)allConnectorsList.get(i); + if ( connector instanceof PlugListenConnector003 ) { + foundListenConnector = connector; + break; + } + } + + if ( foundListenConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector is created on base of ListeningConnector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + foundListenConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + foundListenConnector.name() + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of plugListenConnect003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..3cd901c22bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,29 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors.PlugAttachConnector001_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors.PlugAttachConnector001_02 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors.PlugLaunchConnector001_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors.PlugLaunchConnector001_02 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors.PlugListenConnector001_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors.PlugListenConnector001_02 + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugAttachConnector001_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugAttachConnector001_01.java new file mode 100644 index 00000000000..156cc5737ea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugAttachConnector001_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector001_01 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName + = "PlugAttachConnector001_01_Name"; + static String plugAttachConnectorDescription + = "PlugAttachConnector001_01_Description"; + static Transport plugAttachConnectorTransport + = new PlugConnectorsTransport("PlugAttachConnector001_01_Transport"); + static Map plugAttachConnectorDefaultArguments + = new HashMap(); + + + public PlugAttachConnector001_01() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + plugAttachConnectorDefaultArguments); + } + +} // end of PlugAttachConnector001_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugAttachConnector001_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugAttachConnector001_02.java new file mode 100644 index 00000000000..28d0fba8c5f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugAttachConnector001_02.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugAttachConnector001_02 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName + = "PlugAttachConnector001_02_Name"; + static String plugAttachConnectorDescription + = "PlugAttachConnector001_02_Description"; + static Transport plugAttachConnectorTransport + = new PlugConnectorsTransport("PlugAttachConnector001_02_Transport"); + static Map plugAttachConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugAttachConnectorStringArgumentKey = "PlugAttachConnector001_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugAttachConnector001_02_StringArgument_Name", + "PlugAttachConnector001_02_StringArgument_Label", + "PlugAttachConnector001_02_StringArgument_Description", + "PlugAttachConnector001_02_StringArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorStringArgumentKey, testStringArgument); + + String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector001_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugAttachConnector001_02_IntegerArgument_Name", + "PlugAttachConnector001_02_IntegerArgument_Label", + "PlugAttachConnector001_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorIntegerArgumentKey, testIntegerArgument); + + String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector001_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugAttachConnector001_02_BooleanArgument_Name", + "PlugAttachConnector001_02_BooleanArgument_Label", + "PlugAttachConnector001_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorBooleanArgumentKey, testBooleanArgument); + + String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector001_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugAttachConnector001_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugAttachConnector001_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugAttachConnector001_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugAttachConnector001_02_SelectedArgument_Name", + "PlugAttachConnector001_02_SelectedArgument_Label", + "PlugAttachConnector001_02_SelectedArgument_Description", + "PlugAttachConnector001_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorSelectedArgumentKey, testSelectedArgument); + + return plugAttachConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugAttachConnector001_02() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugAttachConnector001_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugLaunchConnector001_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugLaunchConnector001_01.java new file mode 100644 index 00000000000..8c93829e805 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugLaunchConnector001_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugLaunchConnector001_01 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName + = "PlugLaunchConnector001_01_Name"; + static String plugLaunchConnectorDescription + = "PlugLaunchConnector001_01_Description"; + static Transport plugLaunchConnectorTransport + = new PlugConnectorsTransport("PlugLaunchConnector001_01_Transport"); + static Map plugLaunchConnectorDefaultArguments + = new HashMap(); + + + public PlugLaunchConnector001_01() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + plugLaunchConnectorDefaultArguments); + } + +} // end of PlugLaunchConnector001_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugLaunchConnector001_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugLaunchConnector001_02.java new file mode 100644 index 00000000000..bfc1b25d584 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugLaunchConnector001_02.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugLaunchConnector001_02 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName + = "PlugLaunchConnector001_02_Name"; + static String plugLaunchConnectorDescription + = "PlugLaunchConnector001_02_Description"; + static Transport plugLaunchConnectorTransport + = new PlugConnectorsTransport("PlugLaunchConnector001_02_Transport"); + static Map plugLaunchConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector001_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugLaunchConnector001_02_StringArgument_Name", + "PlugLaunchConnector001_02_StringArgument_Label", + "PlugLaunchConnector001_02_StringArgument_Description", + "PlugLaunchConnector001_02_StringArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorStringArgumentKey, testStringArgument); + + String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector001_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugLaunchConnector001_02_IntegerArgument_Name", + "PlugLaunchConnector001_02_IntegerArgument_Label", + "PlugLaunchConnector001_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorIntegerArgumentKey, testIntegerArgument); + + String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector001_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugLaunchConnector001_02_BooleanArgument_Name", + "PlugLaunchConnector001_02_BooleanArgument_Label", + "PlugLaunchConnector001_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorBooleanArgumentKey, testBooleanArgument); + + String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector001_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugLaunchConnector001_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugLaunchConnector001_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugLaunchConnector001_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugLaunchConnector001_02_SelectedArgument_Name", + "PlugLaunchConnector001_02_SelectedArgument_Label", + "PlugLaunchConnector001_02_SelectedArgument_Description", + "PlugLaunchConnector001_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorSelectedArgumentKey, testSelectedArgument); + + return plugLaunchConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugLaunchConnector001_02() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugLaunchConnector001_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugListenConnector001_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugListenConnector001_01.java new file mode 100644 index 00000000000..6ba12b50f91 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugListenConnector001_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugListenConnector001_01 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName + = "PlugListenConnector001_01_Name"; + static String plugListenConnectorDescription + = "PlugListenConnector001_01_Description"; + static Transport plugListenConnectorTransport + = new PlugConnectorsTransport("PlugListenConnector001_01_Transport"); + static Map plugListenConnectorDefaultArguments + = new HashMap(); + + + public PlugListenConnector001_01() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + plugListenConnectorDefaultArguments); + } + +} // end of PlugListenConnector001_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugListenConnector001_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugListenConnector001_02.java new file mode 100644 index 00000000000..4526294967c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/connectors/PlugListenConnector001_02.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugListenConnector001_02 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName + = "PlugListenConnector001_02_Name"; + static String plugListenConnectorDescription + = "PlugListenConnector001_02_Description"; + static Transport plugListenConnectorTransport + = new PlugConnectorsTransport("PlugListenConnector001_02_Transport"); + static Map plugListenConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugListenConnectorStringArgumentKey = "PlugListenConnector001_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugListenConnector001_02_StringArgument_Name", + "PlugListenConnector001_02_StringArgument_Label", + "PlugListenConnector001_02_StringArgument_Description", + "PlugListenConnector001_02_StringArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorStringArgumentKey, testStringArgument); + + String plugListenConnectorIntegerArgumentKey = "PlugListenConnector001_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugListenConnector001_02_IntegerArgument_Name", + "PlugListenConnector001_02_IntegerArgument_Label", + "PlugListenConnector001_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorIntegerArgumentKey, testIntegerArgument); + + String plugListenConnectorBooleanArgumentKey = "PlugListenConnector001_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugListenConnector001_02_BooleanArgument_Name", + "PlugListenConnector001_02_BooleanArgument_Label", + "PlugListenConnector001_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorBooleanArgumentKey, testBooleanArgument); + + String plugListenConnectorSelectedArgumentKey = "PlugListenConnector001_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugListenConnector001_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugListenConnector001_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugListenConnector001_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugListenConnector001_02_SelectedArgument_Name", + "PlugListenConnector001_02_SelectedArgument_Label", + "PlugListenConnector001_02_SelectedArgument_Description", + "PlugListenConnector001_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorSelectedArgumentKey, testSelectedArgument); + + return plugListenConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugListenConnector001_02() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugListenConnector001_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/plugMultiConnect001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/plugMultiConnect001.java new file mode 100644 index 00000000000..fc596d20273 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001/plugMultiConnect001.java @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the 6 expected + * pluggable connectors are created properly on base of 6 differen + * Connector implementations of different types. + * The test expects that 2 pluggable connectors should be + * of AttachingConnector type, other 2 connectors - + * of ListeningConnector type, and last 2 coonectors - + * of LaunchingConnector type + * Each pluggable connector has to be contained in corresponding list: + * VirtualMachineManager.attachingConnectors(), + * VirtualMachineManager.launchingConnectors() or + * VirtualMachineManager.listeningConnectors(). + * All 6 pluggable connectors have to be contained in + * VirtualMachineManager.allConnectors() list. + * Each pluggable connector is checked for the certain expected + * description and for the certain expected transport. + * For each connector type one pluggable connector should have the + * empty Map of default arguments, and other pluggable connector + * should have 4 default arguments of all types: + * Connector.StringArgument; + * Connector.IntegerArgument; + * Connector.BooleanArgument; + * Connector.SelectedArgument; + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.plugMultiConnect001 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.plugMultiConnect001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001; + +import nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect001.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the 6 expected
    + * pluggable connectors are created properly on base of 6 different
    + * Connector implementations of different types.
    + *
    + * The test expects that 2 pluggable connectors should be
    + * of AttachingConnector type, other 2 connectors -
    + * of ListeningConnector type, and last 2 coonectors -
    + * of LaunchingConnector type
    + *
    + * Each pluggable connector has to be contained in corresponding list:
    + * VirtualMachineManager.attachingConnectors(),
    + * VirtualMachineManager.launchingConnectors() or
    + * VirtualMachineManager.listeningConnectors().
    + *
    + * All 6 pluggable connectors have to be contained in
    + * VirtualMachineManager.allConnectors() list.
    + *
    + * Each pluggable connector is checked for the certain expected
    + * description and for the certain expected transport.
    + *
    + * For each connector type one pluggable connector should have the
    + * empty Map of default arguments, and other pluggable connector
    + * should have 4 default arguments of all types:
    + * Connector.StringArgument;
    + * Connector.IntegerArgument;
    + * Connector.BooleanArgument;
    + * Connector.SelectedArgument;
    + *
    + */ + +public class plugMultiConnect001 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugMultiConnect001: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugMultiConnect001: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugMultiConnect001().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect001 test..."); + logOnVerbose + ("==> Test checks that expected pluggable connectors are created properly"); + logOnVerbose + ("==> on base of 6 different Connector implementations."); + int expectedConnectorsNumber = 6; + + String[] checkedPlugConnectorNames = new String[expectedConnectorsNumber]; + checkedPlugConnectorNames[0] = "PlugAttachConnector001_01_Name"; + checkedPlugConnectorNames[1] = "PlugAttachConnector001_02_Name"; + checkedPlugConnectorNames[2] = "PlugLaunchConnector001_01_Name"; + checkedPlugConnectorNames[3] = "PlugLaunchConnector001_02_Name"; + checkedPlugConnectorNames[4] = "PlugListenConnector001_01_Name"; + checkedPlugConnectorNames[5] = "PlugListenConnector001_02_Name"; + + Connector[] referencePlugConnectors = new Connector[expectedConnectorsNumber]; + referencePlugConnectors[0] = new PlugAttachConnector001_01(); + referencePlugConnectors[1] = new PlugAttachConnector001_02(); + referencePlugConnectors[2] = new PlugLaunchConnector001_01(); + referencePlugConnectors[3] = new PlugLaunchConnector001_02(); + referencePlugConnectors[4] = new PlugListenConnector001_01(); + referencePlugConnectors[5] = new PlugListenConnector001_02(); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + for (int i=0; i < expectedConnectorsNumber; i++ ) { + int checkResult = checkConnector(virtualMachineManager, + checkedPlugConnectorNames[i], + referencePlugConnectors[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + return testResult; + } + + private int checkConnector (VirtualMachineManager virtualMachineManager, + String checkedPlugConnectorName, + Connector referencePlugConnector) { + int checkResult = STATUS_PASSED; + + // check that checked pluggable connector is found out + // in attaching/launching/listeningConnectors() List + List connectorsList = null; + if ( referencePlugConnector instanceof AttachingConnector) { + connectorsList = virtualMachineManager.attachingConnectors(); + } + if ( referencePlugConnector instanceof LaunchingConnector) { + connectorsList = virtualMachineManager.launchingConnectors(); + } + if ( referencePlugConnector instanceof ListeningConnector) { + connectorsList = virtualMachineManager.listeningConnectors(); + } + + int connectorsNumber = connectorsList.size(); + Connector checkedPlugConnector = null; + + for (int i=0; i < connectorsNumber; i++ ) { + Connector connector = (Connector)connectorsList.get(i); + String connectorName = connector.name(); + if ( checkedPlugConnectorName.equals(connectorName) ) { + if ( checkedPlugConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + connector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugConnector = connector; + } + } + } + + if ( checkedPlugConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugConnectorName + "'"); + return STATUS_FAILED; + } + + // check that checked pluggable connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean checkedPlugConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( checkedPlugConnector.equals(foundConnector) ) { + if ( checkedPlugConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable connector with the same name is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugConnectorFound = true; + } + } + } + + if ( ! checkedPlugConnectorFound ) { + logOnError(errorLogPrefixHead + + "Checked pluggable connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Checked connector = " + checkedPlugConnector); + checkResult = STATUS_FAILED; + } + + // check that checked pluggable connector matches corresponding reference connector + String errorMessage = PlugConnectors.compareConnectors( + errorLogPrefixHead, + errorLogPrefix, + referencePlugConnector, + checkedPlugConnector); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + return STATUS_FAILED; + } + + // check default Arguments of checked pluggable connector + + Map referenceDefaultArguments = referencePlugConnector.defaultArguments(); + Map checkedDefaultArguments = checkedPlugConnector.defaultArguments(); + + int referenceDefaultArgumentsNumber = referenceDefaultArguments.size(); + int checkedDefaultArgumentsNumber = checkedDefaultArguments.size(); + + if ( referenceDefaultArgumentsNumber != checkedDefaultArgumentsNumber ) { + logOnError(errorLogPrefixHead + + "Checked pluggable connector contains unexpected number of default arguments"); + logOnError(errorLogPrefix + "Checked connector = " + checkedPlugConnector); + logOnError(errorLogPrefix + "Expected number of default arguments = " + + referenceDefaultArgumentsNumber); + logOnError(errorLogPrefix + "Actual number of default arguments = " + + checkedDefaultArgumentsNumber); + return STATUS_FAILED; + } + + Object[] referenceDefaultArgumentsKeys = referenceDefaultArguments.keySet().toArray(); + for (int i=0; i < referenceDefaultArgumentsNumber; i++) { + String referenceKey = (String)referenceDefaultArgumentsKeys[i]; + Connector.Argument referenceArgument = + (Connector.Argument)(referenceDefaultArguments.get(referenceKey)); + Connector.Argument checkedArgument = + (Connector.Argument)(checkedDefaultArguments.get(referenceKey)); + errorMessage = PlugConnectors.compareConnectorArguments( + errorLogPrefixHead, + errorLogPrefix, + referenceArgument, + checkedArgument); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + checkResult = STATUS_FAILED; + } + } + + return checkResult; + } +} // end of plugMultiConnect001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..b381bb66021 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,32 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugAttachConnector002_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugAttachConnector002_03 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugAttachConnector002_02 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugLaunchConnector002_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugLaunchConnector002_03 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugLaunchConnector002_02 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugListenConnector002_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugListenConnector002_03 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.PlugListenConnector002_02 + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_01.java new file mode 100644 index 00000000000..b8eadd6d9b8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector002_01 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName + = "PlugAttachConnector002_01_Name"; + static String plugAttachConnectorDescription + = "PlugAttachConnector002_01_Description"; + static Transport plugAttachConnectorTransport + = new PlugConnectorsTransport("PlugAttachConnector002_01_Transport"); + static Map plugAttachConnectorDefaultArguments + = new HashMap(); + + + public PlugAttachConnector002_01() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + plugAttachConnectorDefaultArguments); + } + +} // end of PlugAttachConnector002_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_02.java new file mode 100644 index 00000000000..1d31c426e40 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_02.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector002_02 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName + = "PlugAttachConnector002_02_Name"; + static String plugAttachConnectorDescription + = "PlugAttachConnector002_02_Description"; + static Transport plugAttachConnectorTransport + = new PlugConnectorsTransport("PlugAttachConnector002_02_Transport"); + static Map plugAttachConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugAttachConnectorStringArgumentKey = "PlugAttachConnector002_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugAttachConnector002_02_StringArgument_Name", + "PlugAttachConnector002_02_StringArgument_Label", + "PlugAttachConnector002_02_StringArgument_Description", + "PlugAttachConnector002_02_StringArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorStringArgumentKey, testStringArgument); + + String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector002_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugAttachConnector002_02_IntegerArgument_Name", + "PlugAttachConnector002_02_IntegerArgument_Label", + "PlugAttachConnector002_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorIntegerArgumentKey, testIntegerArgument); + + String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector002_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugAttachConnector002_02_BooleanArgument_Name", + "PlugAttachConnector002_02_BooleanArgument_Label", + "PlugAttachConnector002_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorBooleanArgumentKey, testBooleanArgument); + + String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector002_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugAttachConnector002_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugAttachConnector002_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugAttachConnector002_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugAttachConnector002_02_SelectedArgument_Name", + "PlugAttachConnector002_02_SelectedArgument_Label", + "PlugAttachConnector002_02_SelectedArgument_Description", + "PlugAttachConnector002_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorSelectedArgumentKey, testSelectedArgument); + + return plugAttachConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugAttachConnector002_02() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugAttachConnector002_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_03.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_03.java new file mode 100644 index 00000000000..8cc6061945c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugAttachConnector002_03.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector throwing RuntimeException during instantiating used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector002_03 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName = "PlugAttachConnector002_03_Name"; + static String plugAttachConnectorDescription = "PlugAttachConnector002_03_Description"; + static Transport plugAttachConnectorTransport = new PlugConnectorsTransport("PlugAttachConnector002_03_Transport"); + static Map plugAttachConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugAttachConnectorStringArgumentKey = "PlugAttachConnector002_03_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugAttachConnector002_03_StringArgument_Name", + "PlugAttachConnector002_03_StringArgument_Label", + "PlugAttachConnector002_03_StringArgument_Description", + "PlugAttachConnector002_03_StringArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorStringArgumentKey, testStringArgument); + + String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector002_03_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugAttachConnector002_03_IntegerArgument_Name", + "PlugAttachConnector002_03_IntegerArgument_Label", + "PlugAttachConnector002_03_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorIntegerArgumentKey, testIntegerArgument); + + String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector002_03_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugAttachConnector002_03_BooleanArgument_Name", + "PlugAttachConnector002_03_BooleanArgument_Label", + "PlugAttachConnector002_03_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorBooleanArgumentKey, testBooleanArgument); + + String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector002_03_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugAttachConnector002_03_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugAttachConnector002_03_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugAttachConnector002_03_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugAttachConnector002_03_SelectedArgument_Name", + "PlugAttachConnector002_03_SelectedArgument_Label", + "PlugAttachConnector002_03_SelectedArgument_Description", + "PlugAttachConnector002_03_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorSelectedArgumentKey, testSelectedArgument); + + return plugAttachConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugAttachConnector002_03() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugAttachConnector002_03: This RuntimeException is thrown intentionally by AttachingConnector " + + "constructor to check creating of pluggable connectors on base of such AttachingConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugAttachConnector002_03 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_01.java new file mode 100644 index 00000000000..c9c0f70c27f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugLaunchConnector002_01 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName + = "PlugLaunchConnector002_01_Name"; + static String plugLaunchConnectorDescription + = "PlugLaunchConnector002_01_Description"; + static Transport plugLaunchConnectorTransport + = new PlugConnectorsTransport("PlugLaunchConnector002_01_Transport"); + static Map plugLaunchConnectorDefaultArguments + = new HashMap(); + + + public PlugLaunchConnector002_01() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + plugLaunchConnectorDefaultArguments); + } + +} // end of PlugLaunchConnector002_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_02.java new file mode 100644 index 00000000000..be2c85513a6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_02.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugLaunchConnector002_02 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName + = "PlugLaunchConnector002_02_Name"; + static String plugLaunchConnectorDescription + = "PlugLaunchConnector002_02_Description"; + static Transport plugLaunchConnectorTransport + = new PlugConnectorsTransport("PlugLaunchConnector002_02_Transport"); + static Map plugLaunchConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector002_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugLaunchConnector002_02_StringArgument_Name", + "PlugLaunchConnector002_02_StringArgument_Label", + "PlugLaunchConnector002_02_StringArgument_Description", + "PlugLaunchConnector002_02_StringArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorStringArgumentKey, testStringArgument); + + String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector002_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugLaunchConnector002_02_IntegerArgument_Name", + "PlugLaunchConnector002_02_IntegerArgument_Label", + "PlugLaunchConnector002_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorIntegerArgumentKey, testIntegerArgument); + + String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector002_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugLaunchConnector002_02_BooleanArgument_Name", + "PlugLaunchConnector002_02_BooleanArgument_Label", + "PlugLaunchConnector002_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorBooleanArgumentKey, testBooleanArgument); + + String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector002_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugLaunchConnector002_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugLaunchConnector002_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugLaunchConnector002_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugLaunchConnector002_02_SelectedArgument_Name", + "PlugLaunchConnector002_02_SelectedArgument_Label", + "PlugLaunchConnector002_02_SelectedArgument_Description", + "PlugLaunchConnector002_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorSelectedArgumentKey, testSelectedArgument); + + return plugLaunchConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugLaunchConnector002_02() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugLaunchConnector002_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_03.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_03.java new file mode 100644 index 00000000000..f3a8391b8d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugLaunchConnector002_03.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector throwing RuntimeException during instantiating used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugLaunchConnector002_03 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName = "PlugLaunchConnector002_03_Name"; + static String plugLaunchConnectorDescription = "PlugLaunchConnector002_03_Description"; + static Transport plugLaunchConnectorTransport = new PlugConnectorsTransport("PlugLaunchConnector002_03_Transport"); + static Map plugLaunchConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector002_03_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugLaunchConnector002_03_StringArgument_Name", + "PlugLaunchConnector002_03_StringArgument_Label", + "PlugLaunchConnector002_03_StringArgument_Description", + "PlugLaunchConnector002_03_StringArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorStringArgumentKey, testStringArgument); + + String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector002_03_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugLaunchConnector002_03_IntegerArgument_Name", + "PlugLaunchConnector002_03_IntegerArgument_Label", + "PlugLaunchConnector002_03_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorIntegerArgumentKey, testIntegerArgument); + + String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector002_03_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugLaunchConnector002_03_BooleanArgument_Name", + "PlugLaunchConnector002_03_BooleanArgument_Label", + "PlugLaunchConnector002_03_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorBooleanArgumentKey, testBooleanArgument); + + String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector002_03_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugLaunchConnector002_03_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugLaunchConnector002_03_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugLaunchConnector002_03_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugLaunchConnector002_03_SelectedArgument_Name", + "PlugLaunchConnector002_03_SelectedArgument_Label", + "PlugLaunchConnector002_03_SelectedArgument_Description", + "PlugLaunchConnector002_03_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorSelectedArgumentKey, testSelectedArgument); + + return plugLaunchConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugLaunchConnector002_03() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugLaunchConnector002_03: This RuntimeException is thrown intentionally by LaunchingConnector " + + "constructor to check creating of pluggable connectors on base of such LaunchingConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugLaunchConnector002_03 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_01.java new file mode 100644 index 00000000000..189d4ca6a78 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugListenConnector002_01 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName + = "PlugListenConnector002_01_Name"; + static String plugListenConnectorDescription + = "PlugListenConnector002_01_Description"; + static Transport plugListenConnectorTransport + = new PlugConnectorsTransport("PlugListenConnector002_01_Transport"); + static Map plugListenConnectorDefaultArguments + = new HashMap(); + + + public PlugListenConnector002_01() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + plugListenConnectorDefaultArguments); + } + +} // end of PlugListenConnector002_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_02.java new file mode 100644 index 00000000000..ca8bcda833a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_02.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugListenConnector002_02 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName + = "PlugListenConnector002_02_Name"; + static String plugListenConnectorDescription + = "PlugListenConnector002_02_Description"; + static Transport plugListenConnectorTransport + = new PlugConnectorsTransport("PlugListenConnector002_02_Transport"); + static Map plugListenConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugListenConnectorStringArgumentKey = "PlugListenConnector002_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugListenConnector002_02_StringArgument_Name", + "PlugListenConnector002_02_StringArgument_Label", + "PlugListenConnector002_02_StringArgument_Description", + "PlugListenConnector002_02_StringArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorStringArgumentKey, testStringArgument); + + String plugListenConnectorIntegerArgumentKey = "PlugListenConnector002_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugListenConnector002_02_IntegerArgument_Name", + "PlugListenConnector002_02_IntegerArgument_Label", + "PlugListenConnector002_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorIntegerArgumentKey, testIntegerArgument); + + String plugListenConnectorBooleanArgumentKey = "PlugListenConnector002_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugListenConnector002_02_BooleanArgument_Name", + "PlugListenConnector002_02_BooleanArgument_Label", + "PlugListenConnector002_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorBooleanArgumentKey, testBooleanArgument); + + String plugListenConnectorSelectedArgumentKey = "PlugListenConnector002_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugListenConnector002_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugListenConnector002_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugListenConnector002_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugListenConnector002_02_SelectedArgument_Name", + "PlugListenConnector002_02_SelectedArgument_Label", + "PlugListenConnector002_02_SelectedArgument_Description", + "PlugListenConnector002_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorSelectedArgumentKey, testSelectedArgument); + + return plugListenConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugListenConnector002_02() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugListenConnector002_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_03.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_03.java new file mode 100644 index 00000000000..8ef7897d15c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/connectors/PlugListenConnector002_03.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector throwing RuntimeException during instantiating used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugListenConnector002_03 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName = "PlugListenConnector002_03_Name"; + static String plugListenConnectorDescription = "PlugListenConnector002_03_Description"; + static Transport plugListenConnectorTransport = new PlugConnectorsTransport("PlugListenConnector002_03_Transport"); + static Map plugListenConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugListenConnectorStringArgumentKey = "PlugListenConnector002_03_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugListenConnector002_03_StringArgument_Name", + "PlugListenConnector002_03_StringArgument_Label", + "PlugListenConnector002_03_StringArgument_Description", + "PlugListenConnector002_03_StringArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorStringArgumentKey, testStringArgument); + + String plugListenConnectorIntegerArgumentKey = "PlugListenConnector002_03_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugListenConnector002_03_IntegerArgument_Name", + "PlugListenConnector002_03_IntegerArgument_Label", + "PlugListenConnector002_03_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorIntegerArgumentKey, testIntegerArgument); + + String plugListenConnectorBooleanArgumentKey = "PlugListenConnector002_03_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugListenConnector002_03_BooleanArgument_Name", + "PlugListenConnector002_03_BooleanArgument_Label", + "PlugListenConnector002_03_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorBooleanArgumentKey, testBooleanArgument); + + String plugListenConnectorSelectedArgumentKey = "PlugListenConnector002_03_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugListenConnector002_03_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugListenConnector002_03_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugListenConnector002_03_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugListenConnector002_03_SelectedArgument_Name", + "PlugListenConnector002_03_SelectedArgument_Label", + "PlugListenConnector002_03_SelectedArgument_Description", + "PlugListenConnector002_03_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorSelectedArgumentKey, testSelectedArgument); + + return plugListenConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugListenConnector002_03() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugListenConnector002_03: This RuntimeException is thrown intentionally by ListeningConnector " + + "constructor to check creating of pluggable connectors on base of such ListeningConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugListenConnector002_03 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/plugMultiConnect002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/plugMultiConnect002.java new file mode 100644 index 00000000000..1991b01d9cb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002/plugMultiConnect002.java @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test: + * This test is the test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the 6 expected + * pluggable connectors are created properly on base of 6 different + * Connector implementations of different types, but 3 other pluggable + * connectors are NOT created for Connector implementations for which + * instances can not be created. + * The test expects that 2 created pluggable connectors should be + * of AttachingConnector type, other 2 connectors - + * of ListeningConnector type, and last 2 coonectors - + * of LaunchingConnector type + * Each pluggable connector has to be contained in corresponding list: + * VirtualMachineManager.attachingConnectors(), + * VirtualMachineManager.launchingConnectors() or + * VirtualMachineManager.listeningConnectors(). + * All 6 pluggable connectors have to be contained in + * VirtualMachineManager.allConnectors() list. + * Each pluggable connector is checked for the certain expected + * description and for the certain expected transport. + * For each connector type one pluggable connector should have the + * empty Map of default arguments, and other pluggable connector + * should have 4 default arguments of all types: + * Connector.StringArgument; + * Connector.IntegerArgument; + * Connector.BooleanArgument; + * Connector.SelectedArgument; + * Also the test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the 3 pluggable + * connectors are NOT created as they are based on classes which + * implement the Connector interfaces + * (AttachingConnector, ListeningConnector, and LaunchingConnector), + * but constructors of these classes throw Exception. + * These "invalid" Connector implementations are: + * PlugAttachConnector002_03 class; + * PlugLaunchConnector002_03 class; + * PlugListenConnector002_03 class; + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.plugMultiConnect002 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.plugMultiConnect002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002; + +import nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect002.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the 6 expected
    + * pluggable connectors are created properly on base of 6 different
    + * Connector implementations of different types, but 3 other pluggable
    + * connectors are NOT created for Connector implementations for which
    + * instances can not be created.
    + *
    + * The test expects that 2 created pluggable connectors should be
    + * of AttachingConnector type, other 2 connectors -
    + * of ListeningConnector type, and last 2 coonectors -
    + * of LaunchingConnector type
    + *
    + * Each pluggable connector has to be contained in corresponding list:
    + * VirtualMachineManager.attachingConnectors(),
    + * VirtualMachineManager.launchingConnectors() or
    + * VirtualMachineManager.listeningConnectors().
    + *
    + * All 6 pluggable connectors have to be contained in
    + * VirtualMachineManager.allConnectors() list.
    + *
    + * Each pluggable connector is checked for the certain expected
    + * description and for the certain expected transport.
    + *
    + * For each connector type one pluggable connector should have the
    + * empty Map of default arguments, and other pluggable connector
    + * should have 4 default arguments of all types:
    + * Connector.StringArgument;
    + * Connector.IntegerArgument;
    + * Connector.BooleanArgument;
    + * Connector.SelectedArgument;
    + *
    + * Also the test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the 3 pluggable
    + * connectors are NOT created as they are based on classes which
    + * implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, and LaunchingConnector),
    + * but constructors of these classes throw Exception.
    + * These "invalid" Connector implementations are:
    + * PlugAttachConnector002_03 class;
    + * PlugLaunchConnector002_03 class;
    + * PlugListenConnector002_03 class;
    + *
    + */ + +public class plugMultiConnect002 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugMultiConnect002: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugMultiConnect002: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugMultiConnect002().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect002 test..."); + logOnVerbose + ("==> Test checks that expected pluggable connectors are created properly"); + logOnVerbose + ("==> on base of 6 different Connector implementations,"); + logOnVerbose + ("==> but other pluggable connectors are NOT created"); + logOnVerbose + ("==> for Connector implementations for which instances can not be created.\n"); + int expectedConnectorsNumber = 6; + + String[] checkedPlugConnectorNames = new String[expectedConnectorsNumber]; + checkedPlugConnectorNames[0] = "PlugAttachConnector002_01_Name"; + checkedPlugConnectorNames[1] = "PlugAttachConnector002_02_Name"; + checkedPlugConnectorNames[2] = "PlugLaunchConnector002_01_Name"; + checkedPlugConnectorNames[3] = "PlugLaunchConnector002_02_Name"; + checkedPlugConnectorNames[4] = "PlugListenConnector002_01_Name"; + checkedPlugConnectorNames[5] = "PlugListenConnector002_02_Name"; + + Connector[] referencePlugConnectors = new Connector[expectedConnectorsNumber]; + referencePlugConnectors[0] = new PlugAttachConnector002_01(); + referencePlugConnectors[1] = new PlugAttachConnector002_02(); + referencePlugConnectors[2] = new PlugLaunchConnector002_01(); + referencePlugConnectors[3] = new PlugLaunchConnector002_02(); + referencePlugConnectors[4] = new PlugListenConnector002_01(); + referencePlugConnectors[5] = new PlugListenConnector002_02(); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + for (int i=0; i < expectedConnectorsNumber; i++ ) { + int checkResult = checkForValidConnector(virtualMachineManager, + checkedPlugConnectorNames[i], + referencePlugConnectors[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + int invalidConnectorsNumber = 3; + + String[] invalidPlugConnectorClassesNames = new String[invalidConnectorsNumber]; + invalidPlugConnectorClassesNames[0] = "PlugAttachConnector002_03"; + invalidPlugConnectorClassesNames[1] = "PlugLaunchConnector002_03"; + invalidPlugConnectorClassesNames[2] = "PlugListenConnector002_03"; + + for (int i=0; i < invalidConnectorsNumber; i++ ) { + int checkResult = checkForInvalidConnector(virtualMachineManager, + invalidPlugConnectorClassesNames[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + return testResult; + } + + private int checkForValidConnector (VirtualMachineManager virtualMachineManager, + String checkedPlugConnectorName, + Connector referencePlugConnector) { + int checkResult = STATUS_PASSED; + + // check that checked pluggable connector is found out + // in attaching/launching/listeningConnectors() List + List connectorsList = null; + if ( referencePlugConnector instanceof AttachingConnector) { + connectorsList = virtualMachineManager.attachingConnectors(); + } + if ( referencePlugConnector instanceof LaunchingConnector) { + connectorsList = virtualMachineManager.launchingConnectors(); + } + if ( referencePlugConnector instanceof ListeningConnector) { + connectorsList = virtualMachineManager.listeningConnectors(); + } + + int connectorsNumber = connectorsList.size(); + Connector checkedPlugConnector = null; + + for (int i=0; i < connectorsNumber; i++ ) { + Connector connector = (Connector)connectorsList.get(i); + String connectorName = connector.name(); + if ( checkedPlugConnectorName.equals(connectorName) ) { + if ( checkedPlugConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + connector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugConnector = connector; + } + } + } + + if ( checkedPlugConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugConnectorName + "'"); + return STATUS_FAILED; + } + + // check that checked pluggable connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean checkedPlugConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( checkedPlugConnector.equals(foundConnector) ) { + if ( checkedPlugConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable connector with the same name is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugConnectorFound = true; + } + } + } + + if ( ! checkedPlugConnectorFound ) { + logOnError(errorLogPrefixHead + + "Checked pluggable connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Checked connector = " + checkedPlugConnector); + checkResult = STATUS_FAILED; + } + + // check that checked pluggable connector matches corresponding reference connector + String errorMessage = PlugConnectors.compareConnectors( + errorLogPrefixHead, + errorLogPrefix, + referencePlugConnector, + checkedPlugConnector); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + return STATUS_FAILED; + } + + // check default Arguments of checked pluggable connector + + Map referenceDefaultArguments = referencePlugConnector.defaultArguments(); + Map checkedDefaultArguments = checkedPlugConnector.defaultArguments(); + + int referenceDefaultArgumentsNumber = referenceDefaultArguments.size(); + int checkedDefaultArgumentsNumber = checkedDefaultArguments.size(); + + if ( referenceDefaultArgumentsNumber != checkedDefaultArgumentsNumber ) { + logOnError(errorLogPrefixHead + + "Checked pluggable connector contains unexpected number of default arguments"); + logOnError(errorLogPrefix + "Checked connector = " + checkedPlugConnector); + logOnError(errorLogPrefix + "Expected number of default arguments = " + + referenceDefaultArgumentsNumber); + logOnError(errorLogPrefix + "Actual number of default arguments = " + + checkedDefaultArgumentsNumber); + return STATUS_FAILED; + } + + Object[] referenceDefaultArgumentsKeys = referenceDefaultArguments.keySet().toArray(); + for (int i=0; i < referenceDefaultArgumentsNumber; i++) { + String referenceKey = (String)referenceDefaultArgumentsKeys[i]; + Connector.Argument referenceArgument = + (Connector.Argument)(referenceDefaultArguments.get(referenceKey)); + Connector.Argument checkedArgument = + (Connector.Argument)(checkedDefaultArguments.get(referenceKey)); + errorMessage = PlugConnectors.compareConnectorArguments( + errorLogPrefixHead, + errorLogPrefix, + referenceArgument, + checkedArgument); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + checkResult = STATUS_FAILED; + } + } + + return checkResult; + } + + private int checkForInvalidConnector (VirtualMachineManager virtualMachineManager, + String invalidPlugConnectorClassName) { + int checkResult = STATUS_PASSED; + + List connectorsList = null; + String connectorsListName = null; + if ( invalidPlugConnectorClassName.equals("PlugAttachConnector002_03") ) { + connectorsList = virtualMachineManager.attachingConnectors(); + connectorsListName = "attachingConnectors() List"; + } + if ( invalidPlugConnectorClassName.equals("PlugLaunchConnector002_03") ) { + connectorsList = virtualMachineManager.launchingConnectors(); + connectorsListName = "launchingConnectors() List"; + } + if ( invalidPlugConnectorClassName.equals("PlugListenConnector002_03") ) { + connectorsList = virtualMachineManager.listeningConnectors(); + connectorsListName = "listeningConnectors() List"; + } + int connectorsNumber = connectorsList.size(); + + // check that pluggable connector is NOT created on base of Connector + // implementation for which instance can not be created + Connector invalidPlugConnector = null; + + for (int i=0; i < connectorsNumber; i++ ) { + Connector foundConnector = (Connector)connectorsList.get(i); + if ( invalidPlugConnectorClassName.equals("PlugAttachConnector002_03") ) { + if ( foundConnector instanceof PlugAttachConnector002_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + if ( invalidPlugConnectorClassName.equals("PlugLaunchConnector002_03") ) { + if ( foundConnector instanceof PlugLaunchConnector002_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + if ( invalidPlugConnectorClassName.equals("PlugListenConnector002_03") ) { + if ( foundConnector instanceof PlugListenConnector002_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + } + + if ( invalidPlugConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable connector is created on base of Connector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in " + connectorsListName); + logOnError(errorLogPrefix + "Connector instance = '" + invalidPlugConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + invalidPlugConnector.name() + "'"); + checkResult = STATUS_FAILED; + } + + + // check that invalid pluggable connector is NOT contained in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + invalidPlugConnector = null; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( invalidPlugConnectorClassName.equals("PlugAttachConnector002_03") ) { + if ( foundConnector instanceof PlugAttachConnector002_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + if ( invalidPlugConnectorClassName.equals("PlugLaunchConnector002_03") ) { + if ( foundConnector instanceof PlugLaunchConnector002_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + if ( invalidPlugConnectorClassName.equals("PlugListenConnector002_03") ) { + if ( foundConnector instanceof PlugListenConnector002_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + } + + if ( invalidPlugConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable connector is created on base of Connector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() List"); + logOnError(errorLogPrefix + "Connector instance = '" + invalidPlugConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + invalidPlugConnector.name() + "'"); + checkResult = STATUS_FAILED; + } + + return checkResult; + } + +} // end of plugMultiConnect002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService new file mode 100644 index 00000000000..3f005ba4c82 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService @@ -0,0 +1,24 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003 test +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect003.connectors.PlugTransportService003_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect003.connectors.PlugTransportService003_02 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/PlugTransportService003_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/PlugTransportService003_01.java new file mode 100644 index 00000000000..bc565ade6a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/PlugTransportService003_01.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect003.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService003_01 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService003_01_Name"; + static String plugTransportServiceDescription = "PlugTransportService003_01_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + true, // supportsAcceptTimeout + true, // supportsAttachTimeout + true, // supportsHandshakeTimeout + true // supportsMultipleConnections + ); + + public PlugTransportService003_01() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService003_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/PlugTransportService003_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/PlugTransportService003_02.java new file mode 100644 index 00000000000..0f1ddca72b0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/connectors/PlugTransportService003_02.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect003.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService003_02 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService003_02_Name"; + static String plugTransportServiceDescription = "PlugTransportService003_02_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + false, // supportsAcceptTimeout + false, // supportsAttachTimeout + false, // supportsHandshakeTimeout + false // supportsMultipleConnections + ); + + public PlugTransportService003_02() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService003_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/plugMultiConnect003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/plugMultiConnect003.java new file mode 100644 index 00000000000..e8cffb3db36 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003/plugMultiConnect003.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003 test: + * The test for the mechanism for creating pluggable Connectors + * on base of classes which implement the TransportService abstract + * class (com.sun.jdi.connect.spi.TransportService). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked four expected pluggable + * connectors (two AttachingConnectors and two ListeningConnectors) are + * created properly on base of two different TransportService + * implementations. + * The created attaching pluggable connectors have to be contained in Lis + * returned by VirtualMachineManager.attachingConnectors(). + * The created listening pluggable connectors have to be contained in Lis + * returned by VirtualMachineManager.listeningConnectors(). + * And all four connectors have to be contained in List returned + * by VirtualMachineManager.allConnectors() methods. + * The attaching pluggable connectors should have names based on the names + * of the corresponding base transport services concatenated with the + * string "Attach", i.e. + * TransportService.name() + "Attach" + * Similarly, the listening pluggable connectors names are formed of names + * of transport services with string "Listen": + * TransportService.name() + "Listen"; + * All pluggable connectors should have the description conterminous with + * the description of the corresponding base transport service + * (TransportService001.description()). + * All pluggable connectors should have two default arguments named + * "address" and "timeout". + * In addition the listening pluggable connectorsshould have + * 'supportsMultipleConnections' capability matching the same base + * TransportService capability. + * The baee TransportServices are: + * PlugTransportService003_01 class which has: + * name() = "PlugTransportService003_01_Name" + * description() = "PlugTransportService003_01_Description" + * capabilities().supportsAcceptTimeout = true + * capabilities().supportsAttachTimeout = true + * capabilities().supportsHandshakeTimeout = true + * capabilities().supportsMultipleConnections = true + * PlugTransportService003_02 class which has: + * name() = "PlugTransportService003_02_Name" + * description() = "PlugTransportService003_02_Description" + * capabilities().supportsAcceptTimeout = false + * capabilities().supportsAttachTimeout = false + * capabilities().supportsHandshakeTimeout = false + * capabilities().supportsMultipleConnections = false + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect003.plugMultiConnect003 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect003.plugMultiConnect003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect003; + +import nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect003.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the TransportService abstract
    + * class (com.sun.jdi.connect.spi.TransportService).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked four expected pluggable
    + * connectors (two AttachingConnectors and two ListeningConnectors) are
    + * created properly on base of two different TransportService
    + * implementations.
    + *
    + * The created attaching pluggable connectors have to be contained in List
    + * returned by VirtualMachineManager.attachingConnectors().
    + * The created listening pluggable connectors have to be contained in List
    + * returned by VirtualMachineManager.listeningConnectors().
    + * And all four connectors have to be contained in List returned
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * The attaching pluggable connectors should have names based on the names
    + * of the corresponding base transport services concatenated with the
    + * string "Attach", i.e.
    + * TransportService.name() + "Attach"
    + * Similarly, the listening pluggable connectors names are formed of names
    + * of transport services with string "Listen":
    + * TransportService.name() + "Listen";
    + *
    + * All pluggable connectors should have the description conterminous with
    + * the description of the corresponding base transport service
    + * (TransportService001.description()).
    + *
    + * All pluggable connectors should have two default arguments named
    + * "address" and "timeout".
    + *
    + * In addition the listening pluggable connectorsshould have
    + * 'supportsMultipleConnections' capability matching the same base
    + * TransportService capability.
    + *
    + * The baee TransportServices are:
    + * PlugTransportService003_01 class which has:
    + * name() = "PlugTransportService003_01_Name"
    + * description() = "PlugTransportService003_01_Description"
    + * capabilities().supportsAcceptTimeout = true
    + * capabilities().supportsAttachTimeout = true
    + * capabilities().supportsHandshakeTimeout = true
    + * capabilities().supportsMultipleConnections = true
    + * PlugTransportService003_02 class which has:
    + * name() = "PlugTransportService003_02_Name"
    + * description() = "PlugTransportService003_02_Description"
    + * capabilities().supportsAcceptTimeout = false
    + * capabilities().supportsAttachTimeout = false
    + * capabilities().supportsHandshakeTimeout = false
    + * capabilities().supportsMultipleConnections = false
    + *
    + */ + +public class plugMultiConnect003 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugMultiConnect003: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugMultiConnect003: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugMultiConnect003().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect003 test..."); + logOnVerbose + ("==> Test checks that expected pluggable connectors are created properly"); + logOnVerbose + ("==> on base of two different TransportService implementations."); + + int referenceTransportServicesNumber = 2; + + TransportService[] referenceTransportServices + = new TransportService[referenceTransportServicesNumber]; + referenceTransportServices[0] = new PlugTransportService003_01(); + referenceTransportServices[1] = new PlugTransportService003_02(); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + for (int i=0; i < referenceTransportServicesNumber; i++ ) { + int checkResult = checkConnectorsForTransportService(virtualMachineManager, + referenceTransportServices[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + return testResult; + } + + private int checkConnectorsForTransportService + (VirtualMachineManager virtualMachineManager, + TransportService referenceTransportService) { + + int checkResult = STATUS_PASSED; + + String checkedPlugAttachConnectorName = referenceTransportService.name() + "Attach"; + String checkedPlugListenConnectorName = referenceTransportService.name() + "Listen"; + String checkedPlugConnectorsDescription = referenceTransportService.description(); + String addressArgumentName = "address"; + String timeoutArgumentName = "timeout"; + boolean expectedMultipleConnectionsCapability + = referenceTransportService.capabilities().supportsMultipleConnections(); + + // check that expected pluggable attaching connector is found out in attachingConnectors() List + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + if ( checkedPlugAttachConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable attaching connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + attachingConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugAttachConnector = attachingConnector; + } + } + } + + if ( checkedPlugAttachConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable attaching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugAttachConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in listeningConnectors() List + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + if ( checkedPlugListenConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable listening connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + listeningConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugListenConnector = listeningConnector; + } + } + } + + if ( checkedPlugListenConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable listening connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugListenConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + if ( checkedPlugAttachConnector != null ) { + // check that expected pluggable attaching connector is found out in allConnectors() List too + boolean checkedPlugAttachConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof AttachingConnector ) { + AttachingConnector foundAttachingConnector = (AttachingConnector)foundConnector; + if ( checkedPlugAttachConnector.equals(foundAttachingConnector) ) { + if ( checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable attaching connector with the same name " + + "is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundAttachingConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugAttachConnectorFound = true; + } + } + } + } + + if ( ! checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable attaching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugAttachConnector); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has expected description + String actualDescription = checkedPlugAttachConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT address argument:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable attaching connector is NOT of Connector.StringArgument type"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable attaching connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable attaching connector is NOT of Connector.IntegerArgument type"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + } + + if ( checkedPlugListenConnector != null ) { + // check that expected pluggable listening connector is found out in allConnectors() List too + boolean checkedPlugListenConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof ListeningConnector ) { + ListeningConnector foundListeningConnector = (ListeningConnector)foundConnector; + if ( checkedPlugListenConnector.equals(foundListeningConnector) ) { + if ( checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable listening connector with the same name " + + "is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundListeningConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugListenConnectorFound = true; + } + } + } + } + + if ( ! checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable listening connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugListenConnector); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listenhing connector has expected description + String actualDescription = checkedPlugListenConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT address argument:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable listening connector is NOT of Connector.StringArgument type"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable listening connector is NOT of Connector.IntegerArgument type"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has 'supportsMultipleConnections' + // capability matching the same base TransportService capability + boolean actualMultipleConnectionsCapability = checkedPlugListenConnector.supportsMultipleConnections(); + if ( actualMultipleConnectionsCapability != expectedMultipleConnectionsCapability ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has 'supportsMultipleConnections'"); + logOnError(errorLogPrefix + "capability NOT matching the same base TransportService capability:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected 'supportsMultipleConnections' capability = " + + expectedMultipleConnectionsCapability); + logOnError(errorLogPrefix + "Actual 'supportsMultipleConnections' capability = " + + actualMultipleConnectionsCapability); + checkResult = STATUS_FAILED; + } + + } + + return checkResult; + } + +} // end of plugMultiConnect003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService new file mode 100644 index 00000000000..ea81c975df5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService @@ -0,0 +1,25 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004 test +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.connectors.PlugTransportService004_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.connectors.PlugTransportService004_03 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.connectors.PlugTransportService004_02 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_01.java new file mode 100644 index 00000000000..f3b43e35691 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_01.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService004_01 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService004_01_Name"; + static String plugTransportServiceDescription = "PlugTransportService004_01_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + true, // supportsAcceptTimeout + true, // supportsAttachTimeout + true, // supportsHandshakeTimeout + true // supportsMultipleConnections + ); + + public PlugTransportService004_01() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService004_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_02.java new file mode 100644 index 00000000000..effe7440030 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_02.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService004_02 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService004_02_Name"; + static String plugTransportServiceDescription = "PlugTransportService004_02_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + false, // supportsAcceptTimeout + false, // supportsAttachTimeout + false, // supportsHandshakeTimeout + false // supportsMultipleConnections + ); + + public PlugTransportService004_02() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService004_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_03.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_03.java new file mode 100644 index 00000000000..ddcb0e3cd89 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/connectors/PlugTransportService004_03.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService implementatiopn with constructor throwing + * Exception. Used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService004_03 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService004_03_Name"; + static String plugTransportServiceDescription = "PlugTransportService004_03_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + true, // supportsAcceptTimeout + true, // supportsAttachTimeout + true, // supportsHandshakeTimeout + true // supportsMultipleConnections + ); + + public PlugTransportService004_03() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + + String exceptionMessage = + "<## PlugTransportService004_03: This RuntimeException is thrown intentionally by TransportService " + + "constructor to check creating of pluggable connectors on base of such TransportService. ##>"; + + throw new RuntimeException(exceptionMessage); + + } + +} // end of PlugTransportService004_03 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/plugMultiConnect004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/plugMultiConnect004.java new file mode 100644 index 00000000000..ef25a332f80 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004/plugMultiConnect004.java @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004 test: + * The test for the mechanism for creating pluggable Connectors + * on base of classes which implement the TransportService abstract + * class (com.sun.jdi.connect.spi.TransportService). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked four expected pluggable + * connectors (two AttachingConnectors and two ListeningConnectors) are + * created properly on base of two different TransportService + * implementations, but 2 other pluggable connectors (AttachingConnector + * and ListeningConnector) are NOT created for TransportService + * implementation for which instances can not be created. + * The created attaching pluggable connectors have to be contained in List + * returned by VirtualMachineManager.attachingConnectors(). + * The created listening pluggable connectors have to be contained in List + * returned by VirtualMachineManager.listeningConnectors(). + * And all four connectors have to be contained in List returned + * by VirtualMachineManager.allConnectors() methods. + * The attaching pluggable connectors should have names based on the names + * of the corresponding base transport services concatenated with the + * string "Attach", i.e. + * TransportService.name() + "Attach" + * Similarly, the listening pluggable connectors names are formed of names + * of transport services with string "Listen": + * TransportService.name() + "Listen"; + * All pluggable connectors should have the description conterminous with + * the description of the corresponding base transport service + * (TransportService001.description()). + * All pluggable connectors should have two default arguments named + * "address" and "timeout". + * In addition the listening pluggable connectorsshould have + * 'supportsMultipleConnections' capability matching the same base + * TransportService capability. + * The baee TransportServices are: + * PlugTransportService004_01 class which has: + * name() = "PlugTransportService004_01_Name" + * description() = "PlugTransportService004_01_Description" + * capabilities().supportsAcceptTimeout = true + * capabilities().supportsAttachTimeout = true + * capabilities().supportsHandshakeTimeout = true + * capabilities().supportsMultipleConnections = true + * PlugTransportService004_02 class which has: + * name() = "PlugTransportService004_02_Name" + * description() = "PlugTransportService004_02_Description" + * capabilities().supportsAcceptTimeout = false + * capabilities().supportsAttachTimeout = false + * capabilities().supportsHandshakeTimeout = false + * capabilities().supportsMultipleConnections = false + * Also the test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the 2 pluggable connectors + * (AttachingConnector and ListeningConnector) are NOT created as they are + * based on class which extends the TransportService abstract class but + * constructors of this class throws Exception. + * This "invalid" TransportService implementations is: + * PlugTransportService004_03 class; + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.plugMultiConnect004 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.plugMultiConnect004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004; + +import nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect004.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the TransportService abstract
    + * class (com.sun.jdi.connect.spi.TransportService).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked four expected pluggable
    + * connectors (two AttachingConnectors and two ListeningConnectors) are
    + * created properly on base of two different TransportService
    + * implementations, but 2 other pluggable connectors (AttachingConnector
    + * and ListeningConnector) are NOT created for TransportService
    + * implementation for which instances can not be created.
    + *
    + * The created attaching pluggable connectors have to be contained in List
    + * returned by VirtualMachineManager.attachingConnectors().
    + * The created listening pluggable connectors have to be contained in List
    + * returned by VirtualMachineManager.listeningConnectors().
    + * And all four connectors have to be contained in List returned
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * The attaching pluggable connectors should have names based on the names
    + * of the corresponding base transport services concatenated with the
    + * string "Attach", i.e.
    + * TransportService.name() + "Attach"
    + * Similarly, the listening pluggable connectors names are formed of names
    + * of transport services with string "Listen":
    + * TransportService.name() + "Listen";
    + *
    + * All pluggable connectors should have the description conterminous with
    + * the description of the corresponding base transport service
    + * (TransportService001.description()).
    + *
    + * All pluggable connectors should have two default arguments named
    + * "address" and "timeout".
    + *
    + * In addition the listening pluggable connectorsshould have
    + * 'supportsMultipleConnections' capability matching the same base
    + * TransportService capability.
    + *
    + * The baee TransportServices are:
    + * PlugTransportService004_01 class which has:
    + * name() = "PlugTransportService004_01_Name"
    + * description() = "PlugTransportService004_01_Description"
    + * capabilities().supportsAcceptTimeout = true
    + * capabilities().supportsAttachTimeout = true
    + * capabilities().supportsHandshakeTimeout = true
    + * capabilities().supportsMultipleConnections = true
    + * PlugTransportService004_02 class which has:
    + * name() = "PlugTransportService004_02_Name"
    + * description() = "PlugTransportService004_02_Description"
    + * capabilities().supportsAcceptTimeout = false
    + * capabilities().supportsAttachTimeout = false
    + * capabilities().supportsHandshakeTimeout = false
    + * capabilities().supportsMultipleConnections = false
    + *
    + * Also the test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the 2 pluggable connectors
    + * (AttachingConnector and ListeningConnector) are NOT created as they are
    + * based on class which extends the TransportService abstract class but
    + * constructors of this class throws Exception.
    + * This "invalid" TransportService implementations is:
    + * PlugTransportService004_03 class;
    + *
    + */ + +public class plugMultiConnect004 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugMultiConnect004: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugMultiConnect004: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugMultiConnect004().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect004 test..."); + logOnVerbose + ("==> Test checks that expected pluggable connectors are created properly"); + logOnVerbose + ("==> on base of two different TransportService implementations,"); + logOnVerbose + ("==> but other pluggable connectors are NOT created"); + logOnVerbose + ("==> for TransportService implementation for which instance can not be created.\n"); + + int referenceTransportServicesNumber = 2; + + TransportService[] referenceTransportServices + = new TransportService[referenceTransportServicesNumber]; + referenceTransportServices[0] = new PlugTransportService004_01(); + referenceTransportServices[1] = new PlugTransportService004_02(); + + int invalidTransportServicesNumber = 1; + + String[] invalidTransportServicesNames + = new String[invalidTransportServicesNumber]; + invalidTransportServicesNames[0] = "PlugTransportService004_03_Name"; + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + for (int i=0; i < referenceTransportServicesNumber; i++ ) { + int checkResult = checkConnectorsForValidTransportService(virtualMachineManager, + referenceTransportServices[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + for (int i=0; i < invalidTransportServicesNumber; i++ ) { + int checkResult = checkConnectorsForInvalidTransportService(virtualMachineManager, + invalidTransportServicesNames[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + return testResult; + } + + private int checkConnectorsForValidTransportService + (VirtualMachineManager virtualMachineManager, + TransportService referenceTransportService) { + + int checkResult = STATUS_PASSED; + + String checkedPlugAttachConnectorName = referenceTransportService.name() + "Attach"; + String checkedPlugListenConnectorName = referenceTransportService.name() + "Listen"; + String checkedPlugConnectorsDescription = referenceTransportService.description(); + String addressArgumentName = "address"; + String timeoutArgumentName = "timeout"; + boolean expectedMultipleConnectionsCapability + = referenceTransportService.capabilities().supportsMultipleConnections(); + + // check that expected pluggable attaching connector is found out in attachingConnectors() List + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + if ( checkedPlugAttachConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable attaching connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + attachingConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugAttachConnector = attachingConnector; + } + } + } + + if ( checkedPlugAttachConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable attaching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugAttachConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in listeningConnectors() List + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + if ( checkedPlugListenConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable listening connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + listeningConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugListenConnector = listeningConnector; + } + } + } + + if ( checkedPlugListenConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable listening connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugListenConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + if ( checkedPlugAttachConnector != null ) { + // check that expected pluggable attaching connector is found out in allConnectors() List too + boolean checkedPlugAttachConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof AttachingConnector ) { + AttachingConnector foundAttachingConnector = (AttachingConnector)foundConnector; + if ( checkedPlugAttachConnector.equals(foundAttachingConnector) ) { + if ( checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable attaching connector with the same name " + + "is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundAttachingConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugAttachConnectorFound = true; + } + } + } + } + + if ( ! checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable attaching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugAttachConnector); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has expected description + String actualDescription = checkedPlugAttachConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT address argument:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable attaching connector is NOT of Connector.StringArgument type"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable attaching connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable attaching connector is NOT of Connector.IntegerArgument type"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + } + + if ( checkedPlugListenConnector != null ) { + // check that expected pluggable listening connector is found out in allConnectors() List too + boolean checkedPlugListenConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof ListeningConnector ) { + ListeningConnector foundListeningConnector = (ListeningConnector)foundConnector; + if ( checkedPlugListenConnector.equals(foundListeningConnector) ) { + if ( checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable listening connector with the same name " + + "is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundListeningConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugListenConnectorFound = true; + } + } + } + } + + if ( ! checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable listening connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugListenConnector); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listenhing connector has expected description + String actualDescription = checkedPlugListenConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT address argument:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable listening connector is NOT of Connector.StringArgument type"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable listening connector is NOT of Connector.IntegerArgument type"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has 'supportsMultipleConnections' + // capability matching the same base TransportService capability + boolean actualMultipleConnectionsCapability = checkedPlugListenConnector.supportsMultipleConnections(); + if ( actualMultipleConnectionsCapability != expectedMultipleConnectionsCapability ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has 'supportsMultipleConnections'"); + logOnError(errorLogPrefix + "capability NOT matching the same base TransportService capability:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected 'supportsMultipleConnections' capability = " + + expectedMultipleConnectionsCapability); + logOnError(errorLogPrefix + "Actual 'supportsMultipleConnections' capability = " + + actualMultipleConnectionsCapability); + checkResult = STATUS_FAILED; + } + + } + + return checkResult; + } + + private int checkConnectorsForInvalidTransportService + (VirtualMachineManager virtualMachineManager, + String invalidTransportServiceName) { + + int checkResult = STATUS_PASSED; + + String checkedPlugAttachConnectorName = invalidTransportServiceName + "Attach"; + String checkedPlugListenConnectorName = invalidTransportServiceName + "Listen"; + + // check that pluggable attaching connector is NOT created on base of TransportService + // implementation for which instance can not be created + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + checkedPlugAttachConnector = attachingConnector; + break; + } + } + + if ( checkedPlugAttachConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in attachingConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + // check that pluggable listening connector is NOT created on base of TransportService + // implementation for which instance can not be created + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + checkedPlugListenConnector = listeningConnector; + break; + } + } + + if ( checkedPlugListenConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in listeningConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + // check that pluggable connectors are NOT contained in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + Connector attachConnector = null; + Connector listenConnector = null; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector connector = (Connector)allConnectorsList.get(i); + String connectorName = connector.name(); + if ( checkedPlugAttachConnectorName.equals(connectorName) ) { + attachConnector = connector; + } + if ( checkedPlugListenConnectorName.equals(connectorName) ) { + listenConnector = connector; + } + } + + if ( attachConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + attachConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + if ( listenConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + listenConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + return checkResult; + } + +} // end of plugMultiConnect004 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..6616295f5c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,29 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.PlugAttachConnector005_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.PlugAttachConnector005_02 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.PlugLaunchConnector005_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.PlugLaunchConnector005_02 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.PlugListenConnector005_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.PlugListenConnector005_02 + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService new file mode 100644 index 00000000000..4ab0a5cbafa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService @@ -0,0 +1,24 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.PlugTransportService005_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.PlugTransportService005_02 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugAttachConnector005_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugAttachConnector005_01.java new file mode 100644 index 00000000000..289bfe491c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugAttachConnector005_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector005_01 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName + = "PlugAttachConnector005_01_Name"; + static String plugAttachConnectorDescription + = "PlugAttachConnector005_01_Description"; + static Transport plugAttachConnectorTransport + = new PlugConnectorsTransport("PlugAttachConnector005_01_Transport"); + static Map plugAttachConnectorDefaultArguments + = new HashMap(); + + + public PlugAttachConnector005_01() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + plugAttachConnectorDefaultArguments); + } + +} // end of PlugAttachConnector005_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugAttachConnector005_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugAttachConnector005_02.java new file mode 100644 index 00000000000..bcac43e29a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugAttachConnector005_02.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugAttachConnector005_02 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName + = "PlugAttachConnector005_02_Name"; + static String plugAttachConnectorDescription + = "PlugAttachConnector005_02_Description"; + static Transport plugAttachConnectorTransport + = new PlugConnectorsTransport("PlugAttachConnector005_02_Transport"); + static Map plugAttachConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugAttachConnectorStringArgumentKey = "PlugAttachConnector005_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugAttachConnector005_02_StringArgument_Name", + "PlugAttachConnector005_02_StringArgument_Label", + "PlugAttachConnector005_02_StringArgument_Description", + "PlugAttachConnector005_02_StringArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorStringArgumentKey, testStringArgument); + + String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector005_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugAttachConnector005_02_IntegerArgument_Name", + "PlugAttachConnector005_02_IntegerArgument_Label", + "PlugAttachConnector005_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorIntegerArgumentKey, testIntegerArgument); + + String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector005_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugAttachConnector005_02_BooleanArgument_Name", + "PlugAttachConnector005_02_BooleanArgument_Label", + "PlugAttachConnector005_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorBooleanArgumentKey, testBooleanArgument); + + String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector005_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugAttachConnector005_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugAttachConnector005_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugAttachConnector005_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugAttachConnector005_02_SelectedArgument_Name", + "PlugAttachConnector005_02_SelectedArgument_Label", + "PlugAttachConnector005_02_SelectedArgument_Description", + "PlugAttachConnector005_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorSelectedArgumentKey, testSelectedArgument); + + return plugAttachConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugAttachConnector005_02() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugAttachConnector005_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugLaunchConnector005_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugLaunchConnector005_01.java new file mode 100644 index 00000000000..9b4384038f3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugLaunchConnector005_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugLaunchConnector005_01 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName + = "PlugLaunchConnector005_01_Name"; + static String plugLaunchConnectorDescription + = "PlugLaunchConnector005_01_Description"; + static Transport plugLaunchConnectorTransport + = new PlugConnectorsTransport("PlugLaunchConnector005_01_Transport"); + static Map plugLaunchConnectorDefaultArguments + = new HashMap(); + + + public PlugLaunchConnector005_01() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + plugLaunchConnectorDefaultArguments); + } + +} // end of PlugLaunchConnector005_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugLaunchConnector005_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugLaunchConnector005_02.java new file mode 100644 index 00000000000..c4d44b934f4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugLaunchConnector005_02.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugLaunchConnector005_02 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName + = "PlugLaunchConnector005_02_Name"; + static String plugLaunchConnectorDescription + = "PlugLaunchConnector005_02_Description"; + static Transport plugLaunchConnectorTransport + = new PlugConnectorsTransport("PlugLaunchConnector005_02_Transport"); + static Map plugLaunchConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector005_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugLaunchConnector005_02_StringArgument_Name", + "PlugLaunchConnector005_02_StringArgument_Label", + "PlugLaunchConnector005_02_StringArgument_Description", + "PlugLaunchConnector005_02_StringArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorStringArgumentKey, testStringArgument); + + String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector005_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugLaunchConnector005_02_IntegerArgument_Name", + "PlugLaunchConnector005_02_IntegerArgument_Label", + "PlugLaunchConnector005_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorIntegerArgumentKey, testIntegerArgument); + + String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector005_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugLaunchConnector005_02_BooleanArgument_Name", + "PlugLaunchConnector005_02_BooleanArgument_Label", + "PlugLaunchConnector005_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorBooleanArgumentKey, testBooleanArgument); + + String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector005_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugLaunchConnector005_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugLaunchConnector005_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugLaunchConnector005_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugLaunchConnector005_02_SelectedArgument_Name", + "PlugLaunchConnector005_02_SelectedArgument_Label", + "PlugLaunchConnector005_02_SelectedArgument_Description", + "PlugLaunchConnector005_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorSelectedArgumentKey, testSelectedArgument); + + return plugLaunchConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugLaunchConnector005_02() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugLaunchConnector005_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugListenConnector005_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugListenConnector005_01.java new file mode 100644 index 00000000000..ef7a34aa64a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugListenConnector005_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugListenConnector005_01 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName + = "PlugListenConnector005_01_Name"; + static String plugListenConnectorDescription + = "PlugListenConnector005_01_Description"; + static Transport plugListenConnectorTransport + = new PlugConnectorsTransport("PlugListenConnector005_01_Transport"); + static Map plugListenConnectorDefaultArguments + = new HashMap(); + + + public PlugListenConnector005_01() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + plugListenConnectorDefaultArguments); + } + +} // end of PlugListenConnector005_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugListenConnector005_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugListenConnector005_02.java new file mode 100644 index 00000000000..6a0e5e418e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugListenConnector005_02.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugListenConnector005_02 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName + = "PlugListenConnector005_02_Name"; + static String plugListenConnectorDescription + = "PlugListenConnector005_02_Description"; + static Transport plugListenConnectorTransport + = new PlugConnectorsTransport("PlugListenConnector005_02_Transport"); + static Map plugListenConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugListenConnectorStringArgumentKey = "PlugListenConnector005_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugListenConnector005_02_StringArgument_Name", + "PlugListenConnector005_02_StringArgument_Label", + "PlugListenConnector005_02_StringArgument_Description", + "PlugListenConnector005_02_StringArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorStringArgumentKey, testStringArgument); + + String plugListenConnectorIntegerArgumentKey = "PlugListenConnector005_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugListenConnector005_02_IntegerArgument_Name", + "PlugListenConnector005_02_IntegerArgument_Label", + "PlugListenConnector005_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorIntegerArgumentKey, testIntegerArgument); + + String plugListenConnectorBooleanArgumentKey = "PlugListenConnector005_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugListenConnector005_02_BooleanArgument_Name", + "PlugListenConnector005_02_BooleanArgument_Label", + "PlugListenConnector005_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorBooleanArgumentKey, testBooleanArgument); + + String plugListenConnectorSelectedArgumentKey = "PlugListenConnector005_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugListenConnector005_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugListenConnector005_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugListenConnector005_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugListenConnector005_02_SelectedArgument_Name", + "PlugListenConnector005_02_SelectedArgument_Label", + "PlugListenConnector005_02_SelectedArgument_Description", + "PlugListenConnector005_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorSelectedArgumentKey, testSelectedArgument); + + return plugListenConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugListenConnector005_02() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugListenConnector005_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugTransportService005_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugTransportService005_01.java new file mode 100644 index 00000000000..7c01367eeb4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugTransportService005_01.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService005_01 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService005_01_Name"; + static String plugTransportServiceDescription = "PlugTransportService005_01_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + true, // supportsAcceptTimeout + true, // supportsAttachTimeout + true, // supportsHandshakeTimeout + true // supportsMultipleConnections + ); + + public PlugTransportService005_01() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService005_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugTransportService005_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugTransportService005_02.java new file mode 100644 index 00000000000..e8e14a69d23 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/connectors/PlugTransportService005_02.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService005_02 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService005_02_Name"; + static String plugTransportServiceDescription = "PlugTransportService005_02_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + false, // supportsAcceptTimeout + false, // supportsAttachTimeout + false, // supportsHandshakeTimeout + false // supportsMultipleConnections + ); + + public PlugTransportService005_02() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService005_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/plugMultiConnect005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/plugMultiConnect005.java new file mode 100644 index 00000000000..a4c6c480e5f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005/plugMultiConnect005.java @@ -0,0 +1,673 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test: + * The test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * and the TransportService abstract class. + * The test checks up that at start-up time when > + * Bootstrap.virtualMachineManager() is invoked the 6 expected + * pluggable connectors are created properly on base of 6 different + * Connector implementations of different types and four expected + * pluggable connectors (two AttachingConnectors and two + * ListeningConnectors) are created properly on base of two different + * TransportService implementations. + * For connectors created on base of Connector implementations the + * test expects that 2 pluggable connectors should be + * of AttachingConnector type, other 2 connectors - + * of ListeningConnector type, and last 2 coonectors - + * of LaunchingConnector type + * Each pluggable connector has to be contained in corresponding list: + * VirtualMachineManager.attachingConnectors(), + * VirtualMachineManager.launchingConnectors() or> + * VirtualMachineManager.listeningConnectors(). + * All 6 pluggable connectors have to be contained in + * VirtualMachineManager.allConnectors() list. + * Each pluggable connector is checked for the certain expected + * description and for the certain expected transport. + * For each connector type one pluggable connector should have the + * empty Map of default arguments, and other pluggable connector + * should have 4 default arguments of all types: > + * Connector.StringArgument; + * Connector.IntegerArgument; + * Connector.BooleanArgument; + * Connector.SelectedArgument; + * For connectors created on base of TransportService implementations + * the test expects that the created attaching pluggable connectors have + * to be contained in List returned by + * VirtualMachineManager.attachingConnectors(). + * The created listening pluggable connectors have to be contained in List + * returned by VirtualMachineManager.listeningConnectors(). + * And all four connectors have to be contained in List returned + * by VirtualMachineManager.allConnectors() methods. + * The attaching pluggable connectors should have names based on the names + * of the corresponding base transport services concatenated with the + * string "Attach", i.e. + * TransportService.name() + "Attach" + * Similarly, the listening pluggable connectors names are formed of names + * of transport services with string "Listen": + * TransportService.name() + "Listen"; + * All pluggable connectors should have the description conterminous with + * the description of the corresponding base transport service + * (TransportService001.description()). + * All pluggable connectors should have two default arguments named + * "address" and "timeout". + * In addition the listening pluggable connectorsshould have + * 'supportsMultipleConnections' capability matching the same base + * TransportService capability. + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.plugMultiConnect005 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.plugMultiConnect005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005; + +import nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect005.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + * and the TransportService abstract class.
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the 6 expected
    + * pluggable connectors are created properly on base of 6 different
    + * Connector implementations of different types and four expected
    + * pluggable connectors (two AttachingConnectors and two
    + * ListeningConnectors) are created properly on base of two different
    + * TransportService implementations.
    + *
    + * For connectors created on base of Connector implementations the
    + * test expects that 2 pluggable connectors should be
    + * of AttachingConnector type, other 2 connectors -
    + * of ListeningConnector type, and last 2 coonectors -
    + * of LaunchingConnector type
    + *
    + * Each pluggable connector has to be contained in corresponding list:
    + * VirtualMachineManager.attachingConnectors(),
    + * VirtualMachineManager.launchingConnectors() or
    + * VirtualMachineManager.listeningConnectors().
    + *
    + * All 6 pluggable connectors have to be contained in
    + * VirtualMachineManager.allConnectors() list.
    + *
    + * Each pluggable connector is checked for the certain expected
    + * description and for the certain expected transport.
    + *
    + * For each connector type one pluggable connector should have the
    + * empty Map of default arguments, and other pluggable connector
    + * should have 4 default arguments of all types:
    + * Connector.StringArgument;
    + * Connector.IntegerArgument;
    + * Connector.BooleanArgument;
    + * Connector.SelectedArgument;
    + *
    + * For connectors created on base of TransportService implementations
    + * the test expects that the created attaching pluggable connectors have
    + * to be contained in List returned by
    + * VirtualMachineManager.attachingConnectors().
    + * The created listening pluggable connectors have to be contained in List
    + * returned by VirtualMachineManager.listeningConnectors().
    + * And all four connectors have to be contained in List returned
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * The attaching pluggable connectors should have names based on the names
    + * of the corresponding base transport services concatenated with the
    + * string "Attach", i.e.
    + * TransportService.name() + "Attach"
    + * Similarly, the listening pluggable connectors names are formed of names
    + * of transport services with string "Listen":
    + * TransportService.name() + "Listen";
    + *
    + * All pluggable connectors should have the description conterminous with
    + * the description of the corresponding base transport service
    + * (TransportService001.description()).
    + *
    + * All pluggable connectors should have two default arguments named
    + * "address" and "timeout".
    + *
    + * In addition the listening pluggable connectorsshould have
    + * 'supportsMultipleConnections' capability matching the same base
    + * TransportService capability.
    + *
    + */ + +public class plugMultiConnect005 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugMultiConnect005: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugMultiConnect005: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugMultiConnect005().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test..."); + logOnVerbose + ("==> Test checks that expected pluggable connectors are created properly"); + logOnVerbose + ("==> on base of 6 different Connector implementations and of 2 different"); + logOnVerbose + ("==> TransportService implementations."); + int expectedConnectorsNumber = 6; + + String[] checkedPlugConnectorNames = new String[expectedConnectorsNumber]; + checkedPlugConnectorNames[0] = "PlugAttachConnector005_01_Name"; + checkedPlugConnectorNames[1] = "PlugAttachConnector005_02_Name"; + checkedPlugConnectorNames[2] = "PlugLaunchConnector005_01_Name"; + checkedPlugConnectorNames[3] = "PlugLaunchConnector005_02_Name"; + checkedPlugConnectorNames[4] = "PlugListenConnector005_01_Name"; + checkedPlugConnectorNames[5] = "PlugListenConnector005_02_Name"; + + Connector[] referencePlugConnectors = new Connector[expectedConnectorsNumber]; + referencePlugConnectors[0] = new PlugAttachConnector005_01(); + referencePlugConnectors[1] = new PlugAttachConnector005_02(); + referencePlugConnectors[2] = new PlugLaunchConnector005_01(); + referencePlugConnectors[3] = new PlugLaunchConnector005_02(); + referencePlugConnectors[4] = new PlugListenConnector005_01(); + referencePlugConnectors[5] = new PlugListenConnector005_02(); + + int referenceTransportServicesNumber = 2; + + TransportService[] referenceTransportServices + = new TransportService[referenceTransportServicesNumber]; + referenceTransportServices[0] = new PlugTransportService005_01(); + referenceTransportServices[1] = new PlugTransportService005_02(); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + for (int i=0; i < expectedConnectorsNumber; i++ ) { + int checkResult = checkConnector(virtualMachineManager, + checkedPlugConnectorNames[i], + referencePlugConnectors[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + for (int i=0; i < referenceTransportServicesNumber; i++ ) { + int checkResult = checkConnectorsForTransportService(virtualMachineManager, + referenceTransportServices[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + return testResult; + } + + private int checkConnector (VirtualMachineManager virtualMachineManager, + String checkedPlugConnectorName, + Connector referencePlugConnector) { + int checkResult = STATUS_PASSED; + + // check that checked pluggable connector is found out + // in attaching/launching/listeningConnectors() List + List connectorsList = null; + if ( referencePlugConnector instanceof AttachingConnector) { + connectorsList = virtualMachineManager.attachingConnectors(); + } + if ( referencePlugConnector instanceof LaunchingConnector) { + connectorsList = virtualMachineManager.launchingConnectors(); + } + if ( referencePlugConnector instanceof ListeningConnector) { + connectorsList = virtualMachineManager.listeningConnectors(); + } + + int connectorsNumber = connectorsList.size(); + Connector checkedPlugConnector = null; + + for (int i=0; i < connectorsNumber; i++ ) { + Connector connector = (Connector)connectorsList.get(i); + String connectorName = connector.name(); + if ( checkedPlugConnectorName.equals(connectorName) ) { + if ( checkedPlugConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + connector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugConnector = connector; + } + } + } + + if ( checkedPlugConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugConnectorName + "'"); + return STATUS_FAILED; + } + + // check that checked pluggable connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean checkedPlugConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( checkedPlugConnector.equals(foundConnector) ) { + if ( checkedPlugConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable connector with the same name is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugConnectorFound = true; + } + } + } + + if ( ! checkedPlugConnectorFound ) { + logOnError(errorLogPrefixHead + + "Checked pluggable connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Checked connector = " + checkedPlugConnector); + checkResult = STATUS_FAILED; + } + + // check that checked pluggable connector matches corresponding reference connector + String errorMessage = PlugConnectors.compareConnectors( + errorLogPrefixHead, + errorLogPrefix, + referencePlugConnector, + checkedPlugConnector); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + return STATUS_FAILED; + } + + // check default Arguments of checked pluggable connector + + Map referenceDefaultArguments = referencePlugConnector.defaultArguments(); + Map checkedDefaultArguments = checkedPlugConnector.defaultArguments(); + + int referenceDefaultArgumentsNumber = referenceDefaultArguments.size(); + int checkedDefaultArgumentsNumber = checkedDefaultArguments.size(); + + if ( referenceDefaultArgumentsNumber != checkedDefaultArgumentsNumber ) { + logOnError(errorLogPrefixHead + + "Checked pluggable connector contains unexpected number of default arguments"); + logOnError(errorLogPrefix + "Checked connector = " + checkedPlugConnector); + logOnError(errorLogPrefix + "Expected number of default arguments = " + + referenceDefaultArgumentsNumber); + logOnError(errorLogPrefix + "Actual number of default arguments = " + + checkedDefaultArgumentsNumber); + return STATUS_FAILED; + } + + Object[] referenceDefaultArgumentsKeys = referenceDefaultArguments.keySet().toArray(); + for (int i=0; i < referenceDefaultArgumentsNumber; i++) { + String referenceKey = (String)referenceDefaultArgumentsKeys[i]; + Connector.Argument referenceArgument = + (Connector.Argument)(referenceDefaultArguments.get(referenceKey)); + Connector.Argument checkedArgument = + (Connector.Argument)(checkedDefaultArguments.get(referenceKey)); + errorMessage = PlugConnectors.compareConnectorArguments( + errorLogPrefixHead, + errorLogPrefix, + referenceArgument, + checkedArgument); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + checkResult = STATUS_FAILED; + } + } + + return checkResult; + } + + private int checkConnectorsForTransportService + (VirtualMachineManager virtualMachineManager, + TransportService referenceTransportService) { + + int checkResult = STATUS_PASSED; + + String checkedPlugAttachConnectorName = referenceTransportService.name() + "Attach"; + String checkedPlugListenConnectorName = referenceTransportService.name() + "Listen"; + String checkedPlugConnectorsDescription = referenceTransportService.description(); + String addressArgumentName = "address"; + String timeoutArgumentName = "timeout"; + boolean expectedMultipleConnectionsCapability + = referenceTransportService.capabilities().supportsMultipleConnections(); + + // check that expected pluggable attaching connector is found out in attachingConnectors() List + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + if ( checkedPlugAttachConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable attaching connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + attachingConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugAttachConnector = attachingConnector; + } + } + } + + if ( checkedPlugAttachConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable attaching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugAttachConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in listeningConnectors() List + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + if ( checkedPlugListenConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable listening connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + listeningConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugListenConnector = listeningConnector; + } + } + } + + if ( checkedPlugListenConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable listening connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugListenConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + if ( checkedPlugAttachConnector != null ) { + // check that expected pluggable attaching connector is found out in allConnectors() List too + boolean checkedPlugAttachConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof AttachingConnector ) { + AttachingConnector foundAttachingConnector = (AttachingConnector)foundConnector; + if ( checkedPlugAttachConnector.equals(foundAttachingConnector) ) { + if ( checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable attaching connector with the same name " + + "is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundAttachingConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugAttachConnectorFound = true; + } + } + } + } + + if ( ! checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable attaching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugAttachConnector); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has expected description + String actualDescription = checkedPlugAttachConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT address argument:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable attaching connector is NOT of Connector.StringArgument type"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable attaching connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable attaching connector is NOT of Connector.IntegerArgument type"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + } + + if ( checkedPlugListenConnector != null ) { + // check that expected pluggable listening connector is found out in allConnectors() List too + boolean checkedPlugListenConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof ListeningConnector ) { + ListeningConnector foundListeningConnector = (ListeningConnector)foundConnector; + if ( checkedPlugListenConnector.equals(foundListeningConnector) ) { + if ( checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable listening connector with the same name " + + "is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundListeningConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugListenConnectorFound = true; + } + } + } + } + + if ( ! checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable listening connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugListenConnector); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listenhing connector has expected description + String actualDescription = checkedPlugListenConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT address argument:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable listening connector is NOT of Connector.StringArgument type"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable listening connector is NOT of Connector.IntegerArgument type"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has 'supportsMultipleConnections' + // capability matching the same base TransportService capability + boolean actualMultipleConnectionsCapability = checkedPlugListenConnector.supportsMultipleConnections(); + if ( actualMultipleConnectionsCapability != expectedMultipleConnectionsCapability ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has 'supportsMultipleConnections'"); + logOnError(errorLogPrefix + "capability NOT matching the same base TransportService capability:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected 'supportsMultipleConnections' capability = " + + expectedMultipleConnectionsCapability); + logOnError(errorLogPrefix + "Actual 'supportsMultipleConnections' capability = " + + actualMultipleConnectionsCapability); + checkResult = STATUS_FAILED; + } + + } + + return checkResult; + } + +} // end of plugMultiConnect005 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/META-INF/services/com.sun.jdi.connect.Connector b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/META-INF/services/com.sun.jdi.connect.Connector new file mode 100644 index 00000000000..0992bbee0fb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/META-INF/services/com.sun.jdi.connect.Connector @@ -0,0 +1,32 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugAttachConnector006_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugAttachConnector006_03 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugAttachConnector006_02 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugLaunchConnector006_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugLaunchConnector006_03 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugLaunchConnector006_02 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugListenConnector006_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugListenConnector006_03 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugListenConnector006_02 + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService new file mode 100644 index 00000000000..e6cf20b7756 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService @@ -0,0 +1,25 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect005 test +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugTransportService006_01 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugTransportService006_03 +nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.PlugTransportService006_02 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_01.java new file mode 100644 index 00000000000..e2db22c2d32 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugAttachConnector006_01 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName + = "PlugAttachConnector006_01_Name"; + static String plugAttachConnectorDescription + = "PlugAttachConnector006_01_Description"; + static Transport plugAttachConnectorTransport + = new PlugConnectorsTransport("PlugAttachConnector006_01_Transport"); + static Map plugAttachConnectorDefaultArguments + = new HashMap(); + + + public PlugAttachConnector006_01() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + plugAttachConnectorDefaultArguments); + } + +} // end of PlugAttachConnector006_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_02.java new file mode 100644 index 00000000000..f0615d1af28 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_02.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugAttachConnector006_02 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName + = "PlugAttachConnector006_02_Name"; + static String plugAttachConnectorDescription + = "PlugAttachConnector006_02_Description"; + static Transport plugAttachConnectorTransport + = new PlugConnectorsTransport("PlugAttachConnector006_02_Transport"); + static Map plugAttachConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugAttachConnectorStringArgumentKey = "PlugAttachConnector006_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugAttachConnector006_02_StringArgument_Name", + "PlugAttachConnector006_02_StringArgument_Label", + "PlugAttachConnector006_02_StringArgument_Description", + "PlugAttachConnector006_02_StringArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorStringArgumentKey, testStringArgument); + + String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector006_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugAttachConnector006_02_IntegerArgument_Name", + "PlugAttachConnector006_02_IntegerArgument_Label", + "PlugAttachConnector006_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorIntegerArgumentKey, testIntegerArgument); + + String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector006_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugAttachConnector006_02_BooleanArgument_Name", + "PlugAttachConnector006_02_BooleanArgument_Label", + "PlugAttachConnector006_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorBooleanArgumentKey, testBooleanArgument); + + String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector006_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugAttachConnector006_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugAttachConnector006_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugAttachConnector006_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugAttachConnector006_02_SelectedArgument_Name", + "PlugAttachConnector006_02_SelectedArgument_Label", + "PlugAttachConnector006_02_SelectedArgument_Description", + "PlugAttachConnector006_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorSelectedArgumentKey, testSelectedArgument); + + return plugAttachConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugAttachConnector006_02() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugAttachConnector006_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_03.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_03.java new file mode 100644 index 00000000000..bf7481d95ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugAttachConnector006_03.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple AttachingConnector throwing RuntimeException during instantiating used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugAttachConnector006_03 extends PlugConnectors implements AttachingConnector { + + static String plugAttachConnectorName = "PlugAttachConnector006_03_Name"; + static String plugAttachConnectorDescription = "PlugAttachConnector006_03_Description"; + static Transport plugAttachConnectorTransport = new PlugConnectorsTransport("PlugAttachConnector006_03_Transport"); + static Map plugAttachConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugAttachConnectorStringArgumentKey = "PlugAttachConnector006_03_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugAttachConnector006_03_StringArgument_Name", + "PlugAttachConnector006_03_StringArgument_Label", + "PlugAttachConnector006_03_StringArgument_Description", + "PlugAttachConnector006_03_StringArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorStringArgumentKey, testStringArgument); + + String plugAttachConnectorIntegerArgumentKey = "PlugAttachConnector006_03_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugAttachConnector006_03_IntegerArgument_Name", + "PlugAttachConnector006_03_IntegerArgument_Label", + "PlugAttachConnector006_03_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorIntegerArgumentKey, testIntegerArgument); + + String plugAttachConnectorBooleanArgumentKey = "PlugAttachConnector006_03_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugAttachConnector006_03_BooleanArgument_Name", + "PlugAttachConnector006_03_BooleanArgument_Label", + "PlugAttachConnector006_03_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorBooleanArgumentKey, testBooleanArgument); + + String plugAttachConnectorSelectedArgumentKey = "PlugAttachConnector006_03_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugAttachConnector006_03_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugAttachConnector006_03_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugAttachConnector006_03_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugAttachConnector006_03_SelectedArgument_Name", + "PlugAttachConnector006_03_SelectedArgument_Label", + "PlugAttachConnector006_03_SelectedArgument_Description", + "PlugAttachConnector006_03_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugAttachConnectorDefaultArguments.put(plugAttachConnectorSelectedArgumentKey, testSelectedArgument); + + return plugAttachConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugAttachConnector006_03() { + + super(plugAttachConnectorName, + plugAttachConnectorDescription, + plugAttachConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugAttachConnector006_03: This RuntimeException is thrown intentionally by AttachingConnector " + + "constructor to check creating of pluggable connectors on base of such AttachingConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugAttachConnector006_03 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_01.java new file mode 100644 index 00000000000..124826411c4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugLaunchConnector006_01 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName + = "PlugLaunchConnector006_01_Name"; + static String plugLaunchConnectorDescription + = "PlugLaunchConnector006_01_Description"; + static Transport plugLaunchConnectorTransport + = new PlugConnectorsTransport("PlugLaunchConnector006_01_Transport"); + static Map plugLaunchConnectorDefaultArguments + = new HashMap(); + + + public PlugLaunchConnector006_01() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + plugLaunchConnectorDefaultArguments); + } + +} // end of PlugLaunchConnector006_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_02.java new file mode 100644 index 00000000000..40e45c4519c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_02.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugLaunchConnector006_02 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName + = "PlugLaunchConnector006_02_Name"; + static String plugLaunchConnectorDescription + = "PlugLaunchConnector006_02_Description"; + static Transport plugLaunchConnectorTransport + = new PlugConnectorsTransport("PlugLaunchConnector006_02_Transport"); + static Map plugLaunchConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector006_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugLaunchConnector006_02_StringArgument_Name", + "PlugLaunchConnector006_02_StringArgument_Label", + "PlugLaunchConnector006_02_StringArgument_Description", + "PlugLaunchConnector006_02_StringArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorStringArgumentKey, testStringArgument); + + String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector006_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugLaunchConnector006_02_IntegerArgument_Name", + "PlugLaunchConnector006_02_IntegerArgument_Label", + "PlugLaunchConnector006_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorIntegerArgumentKey, testIntegerArgument); + + String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector006_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugLaunchConnector006_02_BooleanArgument_Name", + "PlugLaunchConnector006_02_BooleanArgument_Label", + "PlugLaunchConnector006_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorBooleanArgumentKey, testBooleanArgument); + + String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector006_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugLaunchConnector006_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugLaunchConnector006_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugLaunchConnector006_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugLaunchConnector006_02_SelectedArgument_Name", + "PlugLaunchConnector006_02_SelectedArgument_Label", + "PlugLaunchConnector006_02_SelectedArgument_Description", + "PlugLaunchConnector006_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorSelectedArgumentKey, testSelectedArgument); + + return plugLaunchConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugLaunchConnector006_02() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugLaunchConnector006_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_03.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_03.java new file mode 100644 index 00000000000..5489fc6a349 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugLaunchConnector006_03.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple LaunchingConnector throwing RuntimeException during instantiating used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugLaunchConnector006_03 extends PlugConnectors implements LaunchingConnector { + + static String plugLaunchConnectorName = "PlugLaunchConnector006_03_Name"; + static String plugLaunchConnectorDescription = "PlugLaunchConnector006_03_Description"; + static Transport plugLaunchConnectorTransport = new PlugConnectorsTransport("PlugLaunchConnector006_03_Transport"); + static Map plugLaunchConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugLaunchConnectorStringArgumentKey = "PlugLaunchConnector006_03_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugLaunchConnector006_03_StringArgument_Name", + "PlugLaunchConnector006_03_StringArgument_Label", + "PlugLaunchConnector006_03_StringArgument_Description", + "PlugLaunchConnector006_03_StringArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorStringArgumentKey, testStringArgument); + + String plugLaunchConnectorIntegerArgumentKey = "PlugLaunchConnector006_03_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugLaunchConnector006_03_IntegerArgument_Name", + "PlugLaunchConnector006_03_IntegerArgument_Label", + "PlugLaunchConnector006_03_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorIntegerArgumentKey, testIntegerArgument); + + String plugLaunchConnectorBooleanArgumentKey = "PlugLaunchConnector006_03_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugLaunchConnector006_03_BooleanArgument_Name", + "PlugLaunchConnector006_03_BooleanArgument_Label", + "PlugLaunchConnector006_03_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorBooleanArgumentKey, testBooleanArgument); + + String plugLaunchConnectorSelectedArgumentKey = "PlugLaunchConnector006_03_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugLaunchConnector006_03_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugLaunchConnector006_03_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugLaunchConnector006_03_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugLaunchConnector006_03_SelectedArgument_Name", + "PlugLaunchConnector006_03_SelectedArgument_Label", + "PlugLaunchConnector006_03_SelectedArgument_Description", + "PlugLaunchConnector006_03_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugLaunchConnectorDefaultArguments.put(plugLaunchConnectorSelectedArgumentKey, testSelectedArgument); + + return plugLaunchConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugLaunchConnector006_03() { + + super(plugLaunchConnectorName, + plugLaunchConnectorDescription, + plugLaunchConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugLaunchConnector006_03: This RuntimeException is thrown intentionally by LaunchingConnector " + + "constructor to check creating of pluggable connectors on base of such LaunchingConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugLaunchConnector006_03 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_01.java new file mode 100644 index 00000000000..f8470957eb6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_01.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector without default arguments used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; + +public class PlugListenConnector006_01 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName + = "PlugListenConnector006_01_Name"; + static String plugListenConnectorDescription + = "PlugListenConnector006_01_Description"; + static Transport plugListenConnectorTransport + = new PlugConnectorsTransport("PlugListenConnector006_01_Transport"); + static Map plugListenConnectorDefaultArguments + = new HashMap(); + + + public PlugListenConnector006_01() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + plugListenConnectorDefaultArguments); + } + +} // end of PlugListenConnector006_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_02.java new file mode 100644 index 00000000000..2a2946fd9cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_02.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector with default arguments of all types used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugListenConnector006_02 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName + = "PlugListenConnector006_02_Name"; + static String plugListenConnectorDescription + = "PlugListenConnector006_02_Description"; + static Transport plugListenConnectorTransport + = new PlugConnectorsTransport("PlugListenConnector006_02_Transport"); + static Map plugListenConnectorDefaultArguments + = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugListenConnectorStringArgumentKey = "PlugListenConnector006_02_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugListenConnector006_02_StringArgument_Name", + "PlugListenConnector006_02_StringArgument_Label", + "PlugListenConnector006_02_StringArgument_Description", + "PlugListenConnector006_02_StringArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorStringArgumentKey, testStringArgument); + + String plugListenConnectorIntegerArgumentKey = "PlugListenConnector006_02_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugListenConnector006_02_IntegerArgument_Name", + "PlugListenConnector006_02_IntegerArgument_Label", + "PlugListenConnector006_02_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorIntegerArgumentKey, testIntegerArgument); + + String plugListenConnectorBooleanArgumentKey = "PlugListenConnector006_02_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugListenConnector006_02_BooleanArgument_Name", + "PlugListenConnector006_02_BooleanArgument_Label", + "PlugListenConnector006_02_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorBooleanArgumentKey, testBooleanArgument); + + String plugListenConnectorSelectedArgumentKey = "PlugListenConnector006_02_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugListenConnector006_02_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugListenConnector006_02_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugListenConnector006_02_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugListenConnector006_02_SelectedArgument_Name", + "PlugListenConnector006_02_SelectedArgument_Label", + "PlugListenConnector006_02_SelectedArgument_Description", + "PlugListenConnector006_02_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorSelectedArgumentKey, testSelectedArgument); + + return plugListenConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugListenConnector006_02() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + prepareConnectorDefaultArguments()); + } + +} // end of PlugListenConnector006_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_03.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_03.java new file mode 100644 index 00000000000..2f00b8c5242 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugListenConnector006_03.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple ListeningConnector throwing RuntimeException during instantiating used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.util.ArrayList; + +public class PlugListenConnector006_03 extends PlugConnectors implements ListeningConnector { + + static String plugListenConnectorName = "PlugListenConnector006_03_Name"; + static String plugListenConnectorDescription = "PlugListenConnector006_03_Description"; + static Transport plugListenConnectorTransport = new PlugConnectorsTransport("PlugListenConnector006_03_Transport"); + static Map plugListenConnectorDefaultArguments = new HashMap(); + + static Map prepareConnectorDefaultArguments() { + String plugListenConnectorStringArgumentKey = "PlugListenConnector006_03_StringArgument_Key"; + Connector.StringArgument testStringArgument = new TestStringArgument( + "PlugListenConnector006_03_StringArgument_Name", + "PlugListenConnector006_03_StringArgument_Label", + "PlugListenConnector006_03_StringArgument_Description", + "PlugListenConnector006_03_StringArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorStringArgumentKey, testStringArgument); + + String plugListenConnectorIntegerArgumentKey = "PlugListenConnector006_03_IntegerArgument_Key"; + Connector.IntegerArgument testIntegerArgument = new TestIntegerArgument( + "PlugListenConnector006_03_IntegerArgument_Name", + "PlugListenConnector006_03_IntegerArgument_Label", + "PlugListenConnector006_03_IntegerArgument_Description", + 555555, // IntegerArgument_Value", + 111111, // IntegerArgument_Min", + 999999, // IntegerArgument_Max", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorIntegerArgumentKey, testIntegerArgument); + + String plugListenConnectorBooleanArgumentKey = "PlugListenConnector006_03_BooleanArgument_Key"; + Connector.BooleanArgument testBooleanArgument = new TestBooleanArgument( + "PlugListenConnector006_03_BooleanArgument_Name", + "PlugListenConnector006_03_BooleanArgument_Label", + "PlugListenConnector006_03_BooleanArgument_Description", + true, // BooleanArgument_Value", + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorBooleanArgumentKey, testBooleanArgument); + + String plugListenConnectorSelectedArgumentKey = "PlugListenConnector006_03_SelectedArgument_Key"; + List selectedArgumentChoices = new ArrayList(); + selectedArgumentChoices.add("PlugListenConnector006_03_SelectedArgument_Value_0"); + selectedArgumentChoices.add("PlugListenConnector006_03_SelectedArgument_Value"); + selectedArgumentChoices.add("PlugListenConnector006_03_SelectedArgument_Value_1"); + + Connector.SelectedArgument testSelectedArgument = new TestSelectedArgument( + "PlugListenConnector006_03_SelectedArgument_Name", + "PlugListenConnector006_03_SelectedArgument_Label", + "PlugListenConnector006_03_SelectedArgument_Description", + "PlugListenConnector006_03_SelectedArgument_Value", + selectedArgumentChoices, // List of choices, + true // mustSpecify + ); + plugListenConnectorDefaultArguments.put(plugListenConnectorSelectedArgumentKey, testSelectedArgument); + + return plugListenConnectorDefaultArguments; + } // end of prepareConnectorDefaultArguments() method + + + public PlugListenConnector006_03() { + + super(plugListenConnectorName, + plugListenConnectorDescription, + plugListenConnectorTransport, + prepareConnectorDefaultArguments()); + + String exceptionMessage = + "<## PlugListenConnector006_03: This RuntimeException is thrown intentionally by ListeningConnector " + + "constructor to check creating of pluggable connectors on base of such ListeningConnector. ##>"; + + throw new RuntimeException(exceptionMessage); + } + +} // end of PlugListenConnector006_03 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_01.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_01.java new file mode 100644 index 00000000000..30b54fa3a90 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_01.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService006_01 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService006_01_Name"; + static String plugTransportServiceDescription = "PlugTransportService006_01_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + true, // supportsAcceptTimeout + true, // supportsAttachTimeout + true, // supportsHandshakeTimeout + true // supportsMultipleConnections + ); + + public PlugTransportService006_01() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService006_01 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_02.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_02.java new file mode 100644 index 00000000000..d47f5834540 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_02.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService006_02 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService006_02_Name"; + static String plugTransportServiceDescription = "PlugTransportService006_02_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + false, // supportsAcceptTimeout + false, // supportsAttachTimeout + false, // supportsHandshakeTimeout + false // supportsMultipleConnections + ); + + public PlugTransportService006_02() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService006_02 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_03.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_03.java new file mode 100644 index 00000000000..11ccaf8975e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/connectors/PlugTransportService006_03.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService implementatiopn with constructor throwing + * Exception. Used by + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService006_03 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService006_03_Name"; + static String plugTransportServiceDescription = "PlugTransportService006_03_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + true, // supportsAcceptTimeout + true, // supportsAttachTimeout + true, // supportsHandshakeTimeout + true // supportsMultipleConnections + ); + + public PlugTransportService006_03() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + + String exceptionMessage = + "<## PlugTransportService006_03: This RuntimeException is thrown intentionally by TransportService " + + "constructor to check creating of pluggable connectors on base of such TransportService. ##>"; + + throw new RuntimeException(exceptionMessage); + + } + +} // end of PlugTransportService006_03 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/plugMultiConnect006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/plugMultiConnect006.java new file mode 100644 index 00000000000..a203a2e51e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006/plugMultiConnect006.java @@ -0,0 +1,921 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test: + * The test for the mechanism for creating pluggable Connectors + * on base of classes which implement the Connector interfaces + * (AttachingConnector, ListeningConnector, or LaunchingConnector). + * and the TransportService abstract class. + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the 6 expected + * pluggable connectors are created properly on base of 6 different + * Connector implementations of different types and four expected + * pluggable connectors (two AttachingConnectors and two + * ListeningConnectors) are created properly on base of two different + * TransportService implementations. + * Also the test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked the 3 pluggable connectors + * are NOT created for Connector implementations for which instances can + * not be created and 2 pluggable connectors (AttachingConnector and + * ListeningConnector) are NOT created for TransportService implementation + * for which instances can not be created. + * These "invalid" Connector implementations are: + * PlugAttachConnector006_03 class; + * PlugLaunchConnector006_03 class; + * PlugListenConnector006_03 class; + * and "invalid" TransportService implementations is: + * PlugTransportService006_03 class; + * For connectors created on base of Connector implementations the + * test expects that 2 pluggable connectors should be + * of AttachingConnector type, other 2 connectors - + * of ListeningConnector type, and last 2 coonectors - + * of LaunchingConnector type + * Each pluggable connector has to be contained in corresponding list: + * VirtualMachineManager.attachingConnectors(), + * VirtualMachineManager.launchingConnectors() or + * VirtualMachineManager.listeningConnectors(). + * All 6 pluggable connectors have to be contained in + * VirtualMachineManager.allConnectors() list. + * Each pluggable connector is checked for the certain expected + * description and for the certain expected transport. + * For each connector type one pluggable connector should have the + * empty Map of default arguments, and other pluggable connector + * should have 4 default arguments of all types: + * Connector.StringArgument; + * Connector.IntegerArgument; + * Connector.BooleanArgument; + * Connector.SelectedArgument; + * For connectors created on base of TransportService implementations + * the test expects that the created attaching pluggable connectors have + * to be contained in List returned by + * VirtualMachineManager.attachingConnectors(). + * The created listening pluggable connectors have to be contained in List + * returned by VirtualMachineManager.listeningConnectors(). + * And all four connectors have to be contained in List returned + * by VirtualMachineManager.allConnectors() methods. + * The attaching pluggable connectors should have names based on the names + * of the corresponding base transport services concatenated with the + * string "Attach", i.e. + * TransportService.name() + "Attach" + * Similarly, the listening pluggable connectors names are formed of names + * of transport services with string "Listen": + * TransportService.name() + "Listen"; + * All pluggable connectors should have the description conterminous with + * the description of the corresponding base transport service + * (TransportService001.description()). + * All pluggable connectors should have two default arguments named + * "address" and "timeout". + * In addition the listening pluggable connectorsshould have + * 'supportsMultipleConnections' capability matching the same base + * TransportService capability. + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.plugMultiConnect006 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.plugMultiConnect006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006; + +import nsk.jdi.PlugConnectors.MultiConnectors.plugMultiConnect006.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the Connector interfaces
    + * (AttachingConnector, ListeningConnector, or LaunchingConnector).
    + * and the TransportService abstract class.
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the 6 expected
    + * pluggable connectors are created properly on base of 6 different
    + * Connector implementations of different types and four expected
    + * pluggable connectors (two AttachingConnectors and two
    + * ListeningConnectors) are created properly on base of two different
    + * TransportService implementations.
    + *
    + * Also the test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked the 3 pluggable connectors
    + * are NOT created for Connector implementations for which instances can
    + * not be created and 2 pluggable connectors (AttachingConnector and
    + * ListeningConnector) are NOT created for TransportService implementation
    + * for which instances can not be created.
    + * These "invalid" Connector implementations are:
    + * PlugAttachConnector006_03 class;
    + * PlugLaunchConnector006_03 class;
    + * PlugListenConnector006_03 class;
    + * and "invalid" TransportService implementations is:
    + * PlugTransportService006_03 class;
    + *
    + * For connectors created on base of Connector implementations the
    + * test expects that 2 pluggable connectors should be
    + * of AttachingConnector type, other 2 connectors -
    + * of ListeningConnector type, and last 2 coonectors -
    + * of LaunchingConnector type
    + *
    + * Each pluggable connector has to be contained in corresponding list:
    + * VirtualMachineManager.attachingConnectors(),
    + * VirtualMachineManager.launchingConnectors() or
    + * VirtualMachineManager.listeningConnectors().
    + *
    + * All 6 pluggable connectors have to be contained in
    + * VirtualMachineManager.allConnectors() list.
    + *
    + * Each pluggable connector is checked for the certain expected
    + * description and for the certain expected transport.
    + *
    + * For each connector type one pluggable connector should have the
    + * empty Map of default arguments, and other pluggable connector
    + * should have 4 default arguments of all types:
    + * Connector.StringArgument;
    + * Connector.IntegerArgument;
    + * Connector.BooleanArgument;
    + * Connector.SelectedArgument;
    + *
    + * For connectors created on base of TransportService implementations
    + * the test expects that the created attaching pluggable connectors have
    + * to be contained in List returned by
    + * VirtualMachineManager.attachingConnectors().
    + * The created listening pluggable connectors have to be contained in List
    + * returned by VirtualMachineManager.listeningConnectors().
    + * And all four connectors have to be contained in List returned
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * The attaching pluggable connectors should have names based on the names
    + * of the corresponding base transport services concatenated with the
    + * string "Attach", i.e.
    + * TransportService.name() + "Attach"
    + * Similarly, the listening pluggable connectors names are formed of names
    + * of transport services with string "Listen":
    + * TransportService.name() + "Listen";
    + *
    + * All pluggable connectors should have the description conterminous with
    + * the description of the corresponding base transport service
    + * (TransportService001.description()).
    + *
    + * All pluggable connectors should have two default arguments named
    + * "address" and "timeout".
    + *
    + * In addition the listening pluggable connectorsshould have
    + * 'supportsMultipleConnections' capability matching the same base
    + * TransportService capability.
    + *
    + */ + +public class plugMultiConnect006 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "plugMultiConnect006: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> plugMultiConnect006: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new plugMultiConnect006().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/MultiConnectors/plugMultiConnect006 test..."); + logOnVerbose + ("==> Test checks that expected pluggable connectors are created properly"); + logOnVerbose + ("==> on base of 6 different Connector implementations and of 2 different"); + logOnVerbose + ("==> TransportService implementations."); + logOnVerbose + ("==> But other pluggable connectors are NOT created for Connector and "); + logOnVerbose + ("==> TransportService implementations for which instances can not be created.\n"); + int expectedConnectorsNumber = 6; + + String[] checkedPlugConnectorNames = new String[expectedConnectorsNumber]; + checkedPlugConnectorNames[0] = "PlugAttachConnector006_01_Name"; + checkedPlugConnectorNames[1] = "PlugAttachConnector006_02_Name"; + checkedPlugConnectorNames[2] = "PlugLaunchConnector006_01_Name"; + checkedPlugConnectorNames[3] = "PlugLaunchConnector006_02_Name"; + checkedPlugConnectorNames[4] = "PlugListenConnector006_01_Name"; + checkedPlugConnectorNames[5] = "PlugListenConnector006_02_Name"; + + Connector[] referencePlugConnectors = new Connector[expectedConnectorsNumber]; + referencePlugConnectors[0] = new PlugAttachConnector006_01(); + referencePlugConnectors[1] = new PlugAttachConnector006_02(); + referencePlugConnectors[2] = new PlugLaunchConnector006_01(); + referencePlugConnectors[3] = new PlugLaunchConnector006_02(); + referencePlugConnectors[4] = new PlugListenConnector006_01(); + referencePlugConnectors[5] = new PlugListenConnector006_02(); + + int referenceTransportServicesNumber = 2; + + TransportService[] referenceTransportServices + = new TransportService[referenceTransportServicesNumber]; + referenceTransportServices[0] = new PlugTransportService006_01(); + referenceTransportServices[1] = new PlugTransportService006_02(); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + for (int i=0; i < expectedConnectorsNumber; i++ ) { + int checkResult = checkValidConnector(virtualMachineManager, + checkedPlugConnectorNames[i], + referencePlugConnectors[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + for (int i=0; i < referenceTransportServicesNumber; i++ ) { + int checkResult = checkConnectorsForValidTransportService(virtualMachineManager, + referenceTransportServices[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + int invalidConnectorsNumber = 3; + + String[] invalidPlugConnectorClassesNames = new String[invalidConnectorsNumber]; + invalidPlugConnectorClassesNames[0] = "PlugAttachConnector006_03"; + invalidPlugConnectorClassesNames[1] = "PlugLaunchConnector006_03"; + invalidPlugConnectorClassesNames[2] = "PlugListenConnector006_03"; + + int invalidTransportServicesNumber = 1; + + String[] invalidTransportServicesNames + = new String[invalidTransportServicesNumber]; + invalidTransportServicesNames[0] = "PlugTransportService006_03_Name"; + + for (int i=0; i < invalidConnectorsNumber; i++ ) { + int checkResult = checkForInvalidConnector(virtualMachineManager, + invalidPlugConnectorClassesNames[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + for (int i=0; i < invalidTransportServicesNumber; i++ ) { + int checkResult = checkConnectorsForInvalidTransportService(virtualMachineManager, + invalidTransportServicesNames[i]); + if ( testResult == STATUS_PASSED ) { + testResult = checkResult; + } + } + + return testResult; + } + + private int checkValidConnector (VirtualMachineManager virtualMachineManager, + String checkedPlugConnectorName, + Connector referencePlugConnector) { + int checkResult = STATUS_PASSED; + + // check that checked pluggable connector is found out + // in attaching/launching/listeningConnectors() List + List connectorsList = null; + if ( referencePlugConnector instanceof AttachingConnector) { + connectorsList = virtualMachineManager.attachingConnectors(); + } + if ( referencePlugConnector instanceof LaunchingConnector) { + connectorsList = virtualMachineManager.launchingConnectors(); + } + if ( referencePlugConnector instanceof ListeningConnector) { + connectorsList = virtualMachineManager.listeningConnectors(); + } + + int connectorsNumber = connectorsList.size(); + Connector checkedPlugConnector = null; + + for (int i=0; i < connectorsNumber; i++ ) { + Connector connector = (Connector)connectorsList.get(i); + String connectorName = connector.name(); + if ( checkedPlugConnectorName.equals(connectorName) ) { + if ( checkedPlugConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + connector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugConnector = connector; + } + } + } + + if ( checkedPlugConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugConnectorName + "'"); + return STATUS_FAILED; + } + + // check that checked pluggable connector is found out in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + boolean checkedPlugConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( checkedPlugConnector.equals(foundConnector) ) { + if ( checkedPlugConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable connector with the same name is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugConnectorFound = true; + } + } + } + + if ( ! checkedPlugConnectorFound ) { + logOnError(errorLogPrefixHead + + "Checked pluggable connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Checked connector = " + checkedPlugConnector); + checkResult = STATUS_FAILED; + } + + // check that checked pluggable connector matches corresponding reference connector + String errorMessage = PlugConnectors.compareConnectors( + errorLogPrefixHead, + errorLogPrefix, + referencePlugConnector, + checkedPlugConnector); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + return STATUS_FAILED; + } + + // check default Arguments of checked pluggable connector + + Map referenceDefaultArguments = referencePlugConnector.defaultArguments(); + Map checkedDefaultArguments = checkedPlugConnector.defaultArguments(); + + int referenceDefaultArgumentsNumber = referenceDefaultArguments.size(); + int checkedDefaultArgumentsNumber = checkedDefaultArguments.size(); + + if ( referenceDefaultArgumentsNumber != checkedDefaultArgumentsNumber ) { + logOnError(errorLogPrefixHead + + "Checked pluggable connector contains unexpected number of default arguments"); + logOnError(errorLogPrefix + "Checked connector = " + checkedPlugConnector); + logOnError(errorLogPrefix + "Expected number of default arguments = " + + referenceDefaultArgumentsNumber); + logOnError(errorLogPrefix + "Actual number of default arguments = " + + checkedDefaultArgumentsNumber); + return STATUS_FAILED; + } + + Object[] referenceDefaultArgumentsKeys = referenceDefaultArguments.keySet().toArray(); + for (int i=0; i < referenceDefaultArgumentsNumber; i++) { + String referenceKey = (String)referenceDefaultArgumentsKeys[i]; + Connector.Argument referenceArgument = + (Connector.Argument)(referenceDefaultArguments.get(referenceKey)); + Connector.Argument checkedArgument = + (Connector.Argument)(checkedDefaultArguments.get(referenceKey)); + errorMessage = PlugConnectors.compareConnectorArguments( + errorLogPrefixHead, + errorLogPrefix, + referenceArgument, + checkedArgument); + + if ( ! emptyString.equals(errorMessage) ) { + logOnError(errorMessage); + checkResult = STATUS_FAILED; + } + } + + return checkResult; + } + + private int checkConnectorsForValidTransportService + (VirtualMachineManager virtualMachineManager, + TransportService referenceTransportService) { + + int checkResult = STATUS_PASSED; + + String checkedPlugAttachConnectorName = referenceTransportService.name() + "Attach"; + String checkedPlugListenConnectorName = referenceTransportService.name() + "Listen"; + String checkedPlugConnectorsDescription = referenceTransportService.description(); + String addressArgumentName = "address"; + String timeoutArgumentName = "timeout"; + boolean expectedMultipleConnectionsCapability + = referenceTransportService.capabilities().supportsMultipleConnections(); + + // check that expected pluggable attaching connector is found out in attachingConnectors() List + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + if ( checkedPlugAttachConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable attaching connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + attachingConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugAttachConnector = attachingConnector; + } + } + } + + if ( checkedPlugAttachConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable attaching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugAttachConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in listeningConnectors() List + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + if ( checkedPlugListenConnector != null ) { + logOnError(errorLogPrefixHead + + "One more pluggable listening connector with the same name is found out."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + listeningConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugListenConnector = listeningConnector; + } + } + } + + if ( checkedPlugListenConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable listening connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugListenConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + if ( checkedPlugAttachConnector != null ) { + // check that expected pluggable attaching connector is found out in allConnectors() List too + boolean checkedPlugAttachConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof AttachingConnector ) { + AttachingConnector foundAttachingConnector = (AttachingConnector)foundConnector; + if ( checkedPlugAttachConnector.equals(foundAttachingConnector) ) { + if ( checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable attaching connector with the same name " + + "is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundAttachingConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugAttachConnectorFound = true; + } + } + } + } + + if ( ! checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable attaching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugAttachConnector); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has expected description + String actualDescription = checkedPlugAttachConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT address argument:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable attaching connector is NOT of Connector.StringArgument type"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable attaching connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable attaching connector is NOT of Connector.IntegerArgument type"); + logOnError(errorLogPrefix + "Attaching connector = '" + checkedPlugAttachConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + } + + if ( checkedPlugListenConnector != null ) { + // check that expected pluggable listening connector is found out in allConnectors() List too + boolean checkedPlugListenConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof ListeningConnector ) { + ListeningConnector foundListeningConnector = (ListeningConnector)foundConnector; + if ( checkedPlugListenConnector.equals(foundListeningConnector) ) { + if ( checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "One more pluggable listening connector with the same name " + + "is found out in allConnectors() List."); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + logOnError(errorLogPrefix + "First Connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Found Connector = '" + foundListeningConnector + "'"); + checkResult = STATUS_FAILED; + } else { + checkedPlugListenConnectorFound = true; + } + } + } + } + + if ( ! checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable listening connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugListenConnector); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listenhing connector has expected description + String actualDescription = checkedPlugListenConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + checkResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT address argument:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable listening connector is NOT of Connector.StringArgument type"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + checkResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable listening connector is NOT of Connector.IntegerArgument type"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + checkResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has 'supportsMultipleConnections' + // capability matching the same base TransportService capability + boolean actualMultipleConnectionsCapability = checkedPlugListenConnector.supportsMultipleConnections(); + if ( actualMultipleConnectionsCapability != expectedMultipleConnectionsCapability ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has 'supportsMultipleConnections'"); + logOnError(errorLogPrefix + "capability NOT matching the same base TransportService capability:"); + logOnError(errorLogPrefix + "Listening connector = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Expected 'supportsMultipleConnections' capability = " + + expectedMultipleConnectionsCapability); + logOnError(errorLogPrefix + "Actual 'supportsMultipleConnections' capability = " + + actualMultipleConnectionsCapability); + checkResult = STATUS_FAILED; + } + + } + + return checkResult; + } + + private int checkForInvalidConnector (VirtualMachineManager virtualMachineManager, + String invalidPlugConnectorClassName) { + int checkResult = STATUS_PASSED; + + List connectorsList = null; + String connectorsListName = null; + if ( invalidPlugConnectorClassName.equals("PlugAttachConnector006_03") ) { + connectorsList = virtualMachineManager.attachingConnectors(); + connectorsListName = "attachingConnectors() List"; + } + if ( invalidPlugConnectorClassName.equals("PlugLaunchConnector006_03") ) { + connectorsList = virtualMachineManager.launchingConnectors(); + connectorsListName = "launchingConnectors() List"; + } + if ( invalidPlugConnectorClassName.equals("PlugListenConnector006_03") ) { + connectorsList = virtualMachineManager.listeningConnectors(); + connectorsListName = "listeningConnectors() List"; + } + int connectorsNumber = connectorsList.size(); + + // check that pluggable connector is NOT created on base of Connector + // implementation for which instance can not be created + Connector invalidPlugConnector = null; + + for (int i=0; i < connectorsNumber; i++ ) { + Connector foundConnector = (Connector)connectorsList.get(i); + if ( invalidPlugConnectorClassName.equals("PlugAttachConnector006_03") ) { + if ( foundConnector instanceof PlugAttachConnector006_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + if ( invalidPlugConnectorClassName.equals("PlugLaunchConnector006_03") ) { + if ( foundConnector instanceof PlugLaunchConnector006_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + if ( invalidPlugConnectorClassName.equals("PlugListenConnector006_03") ) { + if ( foundConnector instanceof PlugListenConnector006_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + } + + if ( invalidPlugConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable connector is created on base of Connector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in " + connectorsListName); + logOnError(errorLogPrefix + "Connector instance = '" + invalidPlugConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + invalidPlugConnector.name() + "'"); + checkResult = STATUS_FAILED; + } + + + // check that invalid pluggable connector is NOT contained in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + invalidPlugConnector = null; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( invalidPlugConnectorClassName.equals("PlugAttachConnector006_03") ) { + if ( foundConnector instanceof PlugAttachConnector006_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + if ( invalidPlugConnectorClassName.equals("PlugLaunchConnector006_03") ) { + if ( foundConnector instanceof PlugLaunchConnector006_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + if ( invalidPlugConnectorClassName.equals("PlugListenConnector006_03") ) { + if ( foundConnector instanceof PlugListenConnector006_03 ) { + invalidPlugConnector = foundConnector; + break; + } + } + } + + if ( invalidPlugConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable connector is created on base of Connector"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() List"); + logOnError(errorLogPrefix + "Connector instance = '" + invalidPlugConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + invalidPlugConnector.name() + "'"); + checkResult = STATUS_FAILED; + } + + return checkResult; + } + + private int checkConnectorsForInvalidTransportService + (VirtualMachineManager virtualMachineManager, + String invalidTransportServiceName) { + + int checkResult = STATUS_PASSED; + + String checkedPlugAttachConnectorName = invalidTransportServiceName + "Attach"; + String checkedPlugListenConnectorName = invalidTransportServiceName + "Listen"; + + // check that pluggable attaching connector is NOT created on base of TransportService + // implementation for which instance can not be created + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + checkedPlugAttachConnector = attachingConnector; + break; + } + } + + if ( checkedPlugAttachConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in attachingConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + // check that pluggable listening connector is NOT created on base of TransportService + // implementation for which instance can not be created + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + checkedPlugListenConnector = listeningConnector; + break; + } + } + + if ( checkedPlugListenConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in listeningConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + // check that pluggable connectors are NOT contained in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + Connector attachConnector = null; + Connector listenConnector = null; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector connector = (Connector)allConnectorsList.get(i); + String connectorName = connector.name(); + if ( checkedPlugAttachConnectorName.equals(connectorName) ) { + attachConnector = connector; + } + if ( checkedPlugListenConnectorName.equals(connectorName) ) { + listenConnector = connector; + } + } + + if ( attachConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + attachConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + if ( listenConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + listenConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + checkResult = STATUS_FAILED; + } + + return checkResult; + } + +} // end of plugMultiConnect006 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService new file mode 100644 index 00000000000..d655e28e692 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/TransportService/transportService001 test +nsk.jdi.PlugConnectors.TransportService.transportService001.connectors.PlugTransportService001 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/connectors/PlugTransportService001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/connectors/PlugTransportService001.java new file mode 100644 index 00000000000..096dc37b363 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/connectors/PlugTransportService001.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/TransportService/transportService001 test + */ + +package nsk.jdi.PlugConnectors.TransportService.transportService001.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService001 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService001_Name"; + static String plugTransportServiceDescription = "PlugTransportService001_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + true, // supportsAcceptTimeout + true, // supportsAttachTimeout + true, // supportsHandshakeTimeout + true // supportsMultipleConnections + ); + + public PlugTransportService001() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/transportService001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/transportService001.java new file mode 100644 index 00000000000..e1d197a5841 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService001/transportService001.java @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/TransportService/transportService001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/TransportService/transportService001 test: + * The test for the mechanism for creating pluggable Connectors + * on base of classes which implement the TransportService abstract + * class (com.sun.jdi.connect.spi.TransportService). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked two pluggable + * connectors (AttachingConnector and ListeningConnector) are created + * on base of PlugTransportService001 class which extends + * com.sun.jdi.connect.spi.TransportService abstract class + * Base PlugTransportService001 has: + * TransportService.name() = "PlugTransportService001_Name" + * TransportService.description() = "PlugTransportService001_Description" + * TransportService.capabilities().supportsAcceptTimeout = true + * TransportService.capabilities().supportsAttachTimeout = true + * TransportService.capabilities().supportsHandshakeTimeout = true + * TransportService.capabilities().supportsMultipleConnections = true + * The created attaching pluggable connector has to be contained in list + * returned by VirtualMachineManager.attachingConnectors(). + * The created listening pluggable connector has to be contained in list + * returned by VirtualMachineManager.listeningConnectors(). + * And both connectors have to be contained in list returned + * by VirtualMachineManager.allConnectors() methods. + * The attaching pluggable connector has to have name + * PlugTransportService001.name() + "Attach"; + * The listening pluggable connector has to have name + * PlugTransportService001.name() + "Listen"; + * Both pluggable connectors have to have description + * PlugTransportService001.description(); + * Both pluggable connectors have to have two default arguments named + * "address" and "timeout". + * In addition the listening pluggable connector has to have + * 'supportsMultipleConnections' capability matching the same base + * PlugTransportService001 capability, i.e. = true. + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.TransportService.transportService001.transportService001 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.TransportService.transportService001.transportService001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.TransportService.transportService001; + +import nsk.jdi.PlugConnectors.TransportService.transportService001.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the TransportService abstract
    + * class (com.sun.jdi.connect.spi.TransportService).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked two pluggable
    + * connectors (AttachingConnector and ListeningConnector) are created
    + * on base of PlugTransportService001 class which extends
    + * com.sun.jdi.connect.spi.TransportService abstract class
    + *
    + * Base PlugTransportService001 has:
    + * TransportService.name() = "PlugTransportService001_Name"
    + * TransportService.description() = "PlugTransportService001_Description"
    + * TransportService.capabilities().supportsAcceptTimeout = true
    + * TransportService.capabilities().supportsAttachTimeout = true
    + * TransportService.capabilities().supportsHandshakeTimeout = true
    + * TransportService.capabilities().supportsMultipleConnections = true
    + *
    + * The created attaching pluggable connector has to be contained in list
    + * returned by VirtualMachineManager.attachingConnectors().
    + * The created listening pluggable connector has to be contained in list
    + * returned by VirtualMachineManager.listeningConnectors().
    + * And both connectors have to be contained in list returned
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * The attaching pluggable connector has to have name
    + * PlugTransportService001.name() + "Attach";
    + * The listening pluggable connector has to have name
    + * PlugTransportService001.name() + "Listen";
    + * Both pluggable connectors have to have description
    + * PlugTransportService001.description();
    + * Both pluggable connectors have to have two default arguments named
    + * "address" and "timeout".
    + * In addition the listening pluggable connector has to have
    + * 'supportsMultipleConnections' capability matching the same base
    + * PlugTransportService001 capability, i.e. = true.
    + *
    + */ + +public class transportService001 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "transportService001: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> transportService001: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new transportService001().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/TransportService/transportService001 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/TransportService/transportService001 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/TransportService/transportService001 test..."); + logOnVerbose + ("==> Test checks that expected pluggable attaching and listening connectors are created properly."); + + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + TransportService referenceTransportService = new PlugTransportService001(); + String checkedPlugAttachConnectorName = referenceTransportService.name() + "Attach"; + String checkedPlugListenConnectorName = referenceTransportService.name() + "Listen"; + String checkedPlugConnectorsDescription = referenceTransportService.description(); + String addressArgumentName = "address"; + String timeoutArgumentName = "timeout"; + boolean expectedMultipleConnectionsCapability + = referenceTransportService.capabilities().supportsMultipleConnections(); + + // check that expected pluggable attaching connector is found out in attachingConnectors() List + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + checkedPlugAttachConnector = attachingConnector; + break; + } + } + + if ( checkedPlugAttachConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable attaching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugAttachConnectorName + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in listeningConnectors() List + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + checkedPlugListenConnector = listeningConnector; + break; + } + } + + if ( checkedPlugListenConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable listening connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugListenConnectorName + "'"); + testResult = STATUS_FAILED; + } + + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + if ( checkedPlugAttachConnector != null ) { + // check that expected pluggable attaching connector is found out in allConnectors() List too + boolean checkedPlugAttachConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof AttachingConnector ) { + AttachingConnector foundAttachingConnector = (AttachingConnector)foundConnector; + if ( checkedPlugAttachConnector.equals(foundAttachingConnector) ) { + checkedPlugAttachConnectorFound = true; + break; + } + } + } + + if ( ! checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable attaching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugAttachConnector); + testResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has expected description + String actualDescription = checkedPlugAttachConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT address argument:"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + testResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable attaching connector is NOT of Connector.StringArgument type"); + testResult = STATUS_FAILED; + } + } + + // check that expected pluggable attaching connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + testResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable attaching connector is NOT of Connector.IntegerArgument type"); + testResult = STATUS_FAILED; + } + } + + } + + if ( checkedPlugListenConnector != null ) { + // check that expected pluggable listening connector is found out in allConnectors() List too + boolean checkedPlugListenConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof ListeningConnector ) { + ListeningConnector foundListeningConnector = (ListeningConnector)foundConnector; + if ( checkedPlugListenConnector.equals(foundListeningConnector) ) { + checkedPlugListenConnectorFound = true; + break; + } + } + } + + if ( ! checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable listening connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugListenConnector); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listenhing connector has expected description + String actualDescription = checkedPlugListenConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT address argument:"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + testResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable listening connector is NOT of Connector.StringArgument type"); + testResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + testResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable listening connector is NOT of Connector.IntegerArgument type"); + testResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has 'supportsMultipleConnections' + // capability matching the same base TransportService capability, i.e. = true + boolean actualMultipleConnectionsCapability = checkedPlugListenConnector.supportsMultipleConnections(); + if ( actualMultipleConnectionsCapability != expectedMultipleConnectionsCapability ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has 'supportsMultipleConnections'"); + logOnError(errorLogPrefix + "capability NOT matching the same base TransportService capability:"); + logOnError(errorLogPrefix + "Expected 'supportsMultipleConnections' capability = " + + expectedMultipleConnectionsCapability); + logOnError(errorLogPrefix + "Actual 'supportsMultipleConnections' capability = " + + actualMultipleConnectionsCapability); + testResult = STATUS_FAILED; + } + + } + return testResult; + } +} // end of transportService001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService new file mode 100644 index 00000000000..2bb0ccf5673 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/TransportService/transportService002 test +nsk.jdi.PlugConnectors.TransportService.transportService002.connectors.PlugTransportService002 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/connectors/PlugTransportService002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/connectors/PlugTransportService002.java new file mode 100644 index 00000000000..9fabc481234 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/connectors/PlugTransportService002.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/TransportService/transportService002 test + */ + +package nsk.jdi.PlugConnectors.TransportService.transportService002.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService002 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService002_Name"; + static String plugTransportServiceDescription = "PlugTransportService002_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + false, // supportsAcceptTimeout + false, // supportsAttachTimeout + false, // supportsHandshakeTimeout + false // supportsMultipleConnections + ); + + public PlugTransportService002() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + } + +} // end of PlugTransportService002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/transportService002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/transportService002.java new file mode 100644 index 00000000000..2f0d06baa29 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService002/transportService002.java @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/TransportService/transportService002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/TransportService/transportService002 test: + * The test for the mechanism for creating pluggable Connectors + * on base of classes which implement the TransportService abstract + * class (com.sun.jdi.connect.spi.TransportService). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked two pluggable + * connectors (AttachingConnector and ListeningConnector) are created + * on base of PlugTransportService002 class which extends + * com.sun.jdi.connect.spi.TransportService abstract class + * Base PlugTransportService002 has: + * TransportService.name() = "PlugTransportService002_Name" + * TransportService.description() = "PlugTransportService002_Description" + * TransportService.capabilities().supportsAcceptTimeout = false + * TransportService.capabilities().supportsAttachTimeout = false + * TransportService.capabilities().supportsHandshakeTimeout = false + * TransportService.capabilities().supportsMultipleConnections = false + * The created attaching pluggable connector has to be contained in list + * returned by VirtualMachineManager.attachingConnectors(). + * The created listening pluggable connector has to be contained in list + * returned by VirtualMachineManager.listeningConnectors(). + * And both connectors have to be contained in list returned + * by VirtualMachineManager.allConnectors() methods. + * The attaching pluggable connector has to have name + * PlugTransportService002.name() + "Attach"; + * The listening pluggable connector has to have name + * PlugTransportService002.name() + "Listen"; + * Both pluggable connectors have to have description + * PlugTransportService002.description(); + * Both pluggable connectors have to have two default arguments named + * "address" and "timeout". + * In addition the listening pluggable connector has to have + * 'supportsMultipleConnections' capability matching the same base + * PlugTransportService002 capability, i.e. = false. + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.TransportService.transportService002.transportService002 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugConnectors + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.TransportService.transportService002.transportService002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.TransportService.transportService002; + +import nsk.jdi.PlugConnectors.TransportService.transportService002.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the TransportService abstract
    + * class (com.sun.jdi.connect.spi.TransportService).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked two pluggable
    + * connectors (AttachingConnector and ListeningConnector) are created
    + * on base of PlugTransportService002 class which extends
    + * com.sun.jdi.connect.spi.TransportService abstract class
    + *
    + * Base PlugTransportService002 has:
    + * TransportService.name() = "PlugTransportService002_Name"
    + * TransportService.description() = "PlugTransportService002_Description"
    + * TransportService.capabilities().supportsAcceptTimeout = false
    + * TransportService.capabilities().supportsAttachTimeout = false
    + * TransportService.capabilities().supportsHandshakeTimeout = false
    + * TransportService.capabilities().supportsMultipleConnections = false
    + *
    + * The created attaching pluggable connector has to be contained in list
    + * returned by VirtualMachineManager.attachingConnectors().
    + * The created listening pluggable connector has to be contained in list
    + * returned by VirtualMachineManager.listeningConnectors().
    + * And both connectors have to be contained in list returned
    + * by VirtualMachineManager.allConnectors() methods.
    + *
    + * The attaching pluggable connector has to have name
    + * PlugTransportService002.name() + "Attach";
    + * The listening pluggable connector has to have name
    + * PlugTransportService002.name() + "Listen";
    + * Both pluggable connectors have to have description
    + * PlugTransportService002.description();
    + * Both pluggable connectors have to have two default arguments named
    + * "address" and "timeout".
    + * In addition the listening pluggable connector has to have
    + * 'supportsMultipleConnections' capability matching the same base
    + * PlugTransportService002 capability, i.e. = false.
    + *
    + */ + +public class transportService002 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "transportService002: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> transportService002: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new transportService002().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/TransportService/transportService002 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/TransportService/transportService002 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/TransportService/transportService002 test..."); + logOnVerbose + ("==> Test checks that expected pluggable attaching and listening connectors are created properly."); + + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + TransportService referenceTransportService = new PlugTransportService002(); + String checkedPlugAttachConnectorName = referenceTransportService.name() + "Attach"; + String checkedPlugListenConnectorName = referenceTransportService.name() + "Listen"; + String checkedPlugConnectorsDescription = referenceTransportService.description(); + String addressArgumentName = "address"; + String timeoutArgumentName = "timeout"; + boolean expectedMultipleConnectionsCapability + = referenceTransportService.capabilities().supportsMultipleConnections(); + + // check that expected pluggable attaching connector is found out in attachingConnectors() List + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + checkedPlugAttachConnector = attachingConnector; + break; + } + } + + if ( checkedPlugAttachConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable attaching connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugAttachConnectorName + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector is found out in listeningConnectors() List + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + checkedPlugListenConnector = listeningConnector; + break; + } + } + + if ( checkedPlugListenConnector == null ) { + logOnError(errorLogPrefixHead + "Expected pluggable listening connector is NOT found out."); + logOnError(errorLogPrefix + "Expected connector name = '" + checkedPlugListenConnectorName + "'"); + testResult = STATUS_FAILED; + } + + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + if ( checkedPlugAttachConnector != null ) { + // check that expected pluggable attaching connector is found out in allConnectors() List too + boolean checkedPlugAttachConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof AttachingConnector ) { + AttachingConnector foundAttachingConnector = (AttachingConnector)foundConnector; + if ( checkedPlugAttachConnector.equals(foundAttachingConnector) ) { + checkedPlugAttachConnectorFound = true; + break; + } + } + } + + if ( ! checkedPlugAttachConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable attaching connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugAttachConnector); + testResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has expected description + String actualDescription = checkedPlugAttachConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable attaching connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT address argument:"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + testResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable attaching connector is NOT of Connector.StringArgument type"); + testResult = STATUS_FAILED; + } + } + + // check that expected pluggable attaching connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugAttachConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + testResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable attaching connector is NOT of Connector.IntegerArgument type"); + testResult = STATUS_FAILED; + } + } + + } + + if ( checkedPlugListenConnector != null ) { + // check that expected pluggable listening connector is found out in allConnectors() List too + boolean checkedPlugListenConnectorFound = false; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector foundConnector = (Connector)allConnectorsList.get(i); + if ( foundConnector instanceof ListeningConnector ) { + ListeningConnector foundListeningConnector = (ListeningConnector)foundConnector; + if ( checkedPlugListenConnector.equals(foundListeningConnector) ) { + checkedPlugListenConnectorFound = true; + break; + } + } + } + + if ( ! checkedPlugListenConnectorFound ) { + logOnError(errorLogPrefixHead + + "Expected pluggable listening connector is NOT found out in allConnectors() List"); + logOnError(errorLogPrefix + "Expected connector = " + checkedPlugListenConnector); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listenhing connector has expected description + String actualDescription = checkedPlugListenConnector.description(); + if ( ! checkedPlugConnectorsDescription.equals(actualDescription) ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has unexpected descripton:"); + logOnError(errorLogPrefix + "Expected descripton = '" + checkedPlugConnectorsDescription + "'"); + logOnError(errorLogPrefix + "Actual descripton = '" + actualDescription + "'"); + testResult = STATUS_FAILED; + } + + // check that expected pluggable listening connector has default argument 'address' + // and this argument is of Connector.StringArgument type + Connector.Argument addressArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, addressArgumentName); + if ( addressArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT address argument:"); + logOnError(errorLogPrefix + "Expected argument name = '" + addressArgumentName + "'"); + testResult = STATUS_FAILED; + } else { + if ( ! (addressArgument instanceof Connector.StringArgument) ) { + logOnError(errorLogPrefixHead + + "Address argument of Pluggable listening connector is NOT of Connector.StringArgument type"); + testResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has default argument 'timeout' + // and this argument is of Connector.IntegerArgument type + Connector.Argument timeoutArgument = PlugConnectors.getConnectorDefaultArgument + (checkedPlugListenConnector, timeoutArgumentName); + if ( timeoutArgument == null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has NOT timeout argument:"); + logOnError(errorLogPrefix + "Expected argument name = '" + timeoutArgumentName + "'"); + testResult = STATUS_FAILED; + } else { + if ( ! (timeoutArgument instanceof Connector.IntegerArgument) ) { + logOnError(errorLogPrefixHead + + "Timeout argument of Pluggable listening connector is NOT of Connector.IntegerArgument type"); + testResult = STATUS_FAILED; + } + } + + // check that expected pluggable listening connector has 'supportsMultipleConnections' + // capability matching the same base TransportService capability, i.e. = false + boolean actualMultipleConnectionsCapability = checkedPlugListenConnector.supportsMultipleConnections(); + if ( actualMultipleConnectionsCapability != expectedMultipleConnectionsCapability ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector has 'supportsMultipleConnections'"); + logOnError(errorLogPrefix + "capability NOT matching the same base TransportService capability:"); + logOnError(errorLogPrefix + "Expected 'supportsMultipleConnections' capability = " + + expectedMultipleConnectionsCapability); + logOnError(errorLogPrefix + "Actual 'supportsMultipleConnections' capability = " + + actualMultipleConnectionsCapability); + testResult = STATUS_FAILED; + } + + } + return testResult; + } +} // end of transportService002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService new file mode 100644 index 00000000000..0a8a3c11694 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/connectors/META-INF/services/com.sun.jdi.connect.spi.TransportService @@ -0,0 +1,23 @@ +# Copyright (c) 2007, 2018, 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. + +# -- used by nsk/jdi/PlugConnectors/TransportService/transportService003 test +nsk.jdi.PlugConnectors.TransportService.transportService003.connectors.PlugTransportService003 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/connectors/PlugTransportService003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/connectors/PlugTransportService003.java new file mode 100644 index 00000000000..af614827e33 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/connectors/PlugTransportService003.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +/* + * A Simple TransportService used by + * nsk/jdi/PlugConnectors/TransportService/transportService003 test + */ + +package nsk.jdi.PlugConnectors.TransportService.transportService003.connectors; + +import nsk.share.jdi.*; +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; + +public class PlugTransportService003 extends PlugTransportService { + + static String plugTransportServiceName = "PlugTransportService003_Name"; + static String plugTransportServiceDescription = "PlugTransportService003_Description"; + static TransportService.Capabilities plugTransportServiceCapabilities = + new TestCapabilities( + true, // supportsAcceptTimeout + true, // supportsAttachTimeout + true, // supportsHandshakeTimeout + true // supportsMultipleConnections + ); + + public PlugTransportService003() { + + super( + plugTransportServiceName, + plugTransportServiceDescription, + plugTransportServiceCapabilities + ); + + String exceptionMessage = + "<## PlugTransportService003: This RuntimeException is thrown intentionally by TransportService " + + "constructor to check creating of pluggable connectors on base of such TransportService. ##>"; + + throw new RuntimeException(exceptionMessage); + + } + +} // end of PlugTransportService003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/transportService003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/transportService003.java new file mode 100644 index 00000000000..18efd2f49a5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PlugConnectors/TransportService/transportService003/transportService003.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PlugConnectors/TransportService/transportService003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/PlugConnectors/TransportService/transportService003 test: + * The test for the mechanism for creating pluggable Connectors + * on base of classes which implement the TransportService abstract + * class (com.sun.jdi.connect.spi.TransportService). + * The test checks up that at start-up time when + * Bootstrap.virtualMachineManager() is invoked pluggable + * connectors (AttachingConnector and ListeningConnector) are NOT created + * on base of PlugTransportService003 class which extends + * com.sun.jdi.connect.spi.TransportService abstract class + * but constructor of PlugTransportService003 throws Exception. + * COMMENTS: + * Fixed bug 6426609: nsk/share/jdi/plug_connectors_jar_file.pl should use + * "system" instead of back-quotes + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PlugConnectors.TransportService.transportService003.transportService003 + * + * @comment build connectors.jar to jars + * @build nsk.share.jdi.PlugTransportService + * @run driver nsk.jdi.ConnectorsJarBuilder + * + * @build ExecDriver + * @run driver PropertyResolvingWrapper ExecDriver --java + * -cp jars${file.separator}connectors.jar${path.separator}${test.class.path} + * nsk.jdi.PlugConnectors.TransportService.transportService003.transportService003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + */ + +package nsk.jdi.PlugConnectors.TransportService.transportService003; + +import nsk.jdi.PlugConnectors.TransportService.transportService003.connectors.*; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the mechanism for creating pluggable Connectors
    + * on base of classes which implement the TransportService abstract
    + * class (com.sun.jdi.connect.spi.TransportService).
    + *
    + * The test checks up that at start-up time when
    + * Bootstrap.virtualMachineManager() is invoked pluggable
    + * connectors (AttachingConnector and ListeningConnector) are NOT created
    + * on base of PlugTransportService003 class which extends
    + * com.sun.jdi.connect.spi.TransportService abstract class
    + * but constructor of PlugTransportService003 throws Exception.
    + *
    + */ + +public class transportService003 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "transportService003: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixNead = "--> transportService003: "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new transportService003().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/PlugConnectors/TransportService/transportService003 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/PlugConnectors/TransportService/transportService003 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/PlugConnectors/TransportService/transportService003 test..."); + logOnVerbose + ("==> Test checks that pluggable attaching and listening connectors are NOT created"); + logOnVerbose + (" for TransportService implementation for which instance can not be created."); + + VirtualMachineManager virtualMachineManager = null; + try { + virtualMachineManager = Bootstrap.virtualMachineManager(); + } catch (Throwable thrown) { + // OK: Bootstrap.virtualMachineManager() may throw an unspecified error + // if initialization of the VirtualMachineManager fails or if the virtual + // machine manager is unable to locate or create any Connectors. + logOnVerbose + (infoLogPrefixNead + "Bootstrap.virtualMachineManager() throws:\n" + thrown); + return STATUS_PASSED; + } + + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + String checkedPlugAttachConnectorName = "PlugTransportService003_Name" + "Attach"; + String checkedPlugListenConnectorName = "PlugTransportService003_Name" + "Listen"; + + // check that pluggable attaching connector is NOT created on base of TransportService + // implementation (PlugTransportService003 class) for which instance can not be created + List attachingConnectorsList = virtualMachineManager.attachingConnectors(); + int attachingConnectorsNumber = attachingConnectorsList.size(); + AttachingConnector checkedPlugAttachConnector = null; + + for (int i=0; i < attachingConnectorsNumber; i++ ) { + AttachingConnector attachingConnector = (AttachingConnector)attachingConnectorsList.get(i); + String attachConnectorName = attachingConnector.name(); + if ( checkedPlugAttachConnectorName.equals(attachConnectorName) ) { + checkedPlugAttachConnector = attachingConnector; + break; + } + } + + if ( checkedPlugAttachConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in attachingConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugAttachConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + testResult = STATUS_FAILED; + } + + // check that pluggable listening connector is NOT created on base of TransportService + // implementation (PlugTransportService003 class) for which instance can not be created + List listeningConnectorsList = virtualMachineManager.listeningConnectors(); + int listeningConnectorsNumber = listeningConnectorsList.size(); + ListeningConnector checkedPlugListenConnector = null; + + for (int i=0; i < listeningConnectorsNumber; i++ ) { + ListeningConnector listeningConnector = (ListeningConnector)listeningConnectorsList.get(i); + String listenConnectorName = listeningConnector.name(); + if ( checkedPlugListenConnectorName.equals(listenConnectorName) ) { + checkedPlugListenConnector = listeningConnector; + break; + } + } + + if ( checkedPlugListenConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in listeningConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + checkedPlugListenConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + testResult = STATUS_FAILED; + } + + // check that pluggable connectors are NOT contained in allConnectors() List too + List allConnectorsList = virtualMachineManager.allConnectors(); + int allConnectorsNumber = allConnectorsList.size(); + + Connector attachConnector = null; + Connector listenConnector = null; + for (int i=0; i < allConnectorsNumber; i++ ) { + Connector connector = (Connector)allConnectorsList.get(i); + String connectorName = connector.name(); + if ( checkedPlugAttachConnectorName.equals(connectorName) ) { + attachConnector = connector; + } + if ( checkedPlugListenConnectorName.equals(connectorName) ) { + listenConnector = connector; + } + } + + if ( attachConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable attaching connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + attachConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugAttachConnectorName + "'"); + testResult = STATUS_FAILED; + } + + if ( listenConnector != null ) { + logOnError(errorLogPrefixHead + "Pluggable listening connector is created for TransportService"); + logOnError(errorLogPrefix + "implementation for which instance can not be created."); + logOnError(errorLogPrefix + "This connector is found out in allConnectors() list"); + logOnError(errorLogPrefix + "Connector instance = '" + listenConnector + "'"); + logOnError(errorLogPrefix + "Connector name = '" + checkedPlugListenConnectorName + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of transportService003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java new file mode 100644 index 00000000000..6954b2d390e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java @@ -0,0 +1,452 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * PrimitiveType.
    + *
    + * The test checks up that for each PrimitiveType value the cast
    + * from Type to PrimitiveType doesn't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares objects of all PrimitiveTypes and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks required.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class primitivetype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveType/_itself_/primitivetype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new primitivetype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveType._itself_.primitivetype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String types[] = { "BooleanType", "ByteType", "CharType", "DoubleType", + "FloatType", "IntegerType", "LongType", "ShortType" }; + + String names[] = { "bl", "bt", "ch", "db", "fl", "in", "ln", "sh" }; + + for (int i2 = 0; i2 < names.length; i2++) { + + log2("......PrimitiveType to test: " + types[i2]); + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(names[i2])).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(names[i2])).type(); + + try { + log2(" checking up on cast: PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001/TestDescription.java new file mode 100644 index 00000000000..813907006d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveType/_itself_/primitivetype001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveType. + * The test checks up that for each PrimitiveType value the cast + * from Type to PrimitiveType doesn't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.PrimitiveType._itself_.primitivetype001; + * the debuggee program - nsk.jdi.PrimitiveType._itself_.primitivetype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveType._itself_.primitivetype001 + * nsk.jdi.PrimitiveType._itself_.primitivetype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveType._itself_.primitivetype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001a.java new file mode 100644 index 00000000000..44977d44984 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001a.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the primitivetype001 JDI test. + */ + +public class primitivetype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static boolean bl = false; + static byte bt = 0; + static char ch = 0; + static double db = 0.0d; + static float fl = 0.0f; + static int in = 0; + static long ln = 0; + static short sh = 0; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001.java new file mode 100644 index 00000000000..62131e5b1f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001.java @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.booleanValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.booleanValue()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl1 = true;
    + * static boolean bl0 = false;
    + * static byte bt1 = Byte.MAX_VALUE;
    + * static byte bt0 = 0;
    + * static char ch1 = Character.MAX_VALUE;
    + * static char ch0 = 0;
    + * static double db1 = Double.MAX_VALUE;
    + * static double db0 = 0.0d;
    + * static float fl1 = Float.MAX_VALUE;
    + * static float fl0 = 0.0f;
    + * static int in1 = Integer.MAX_VALUE;
    + * static int in0 = 0;
    + * static long ln1 = Long.MAX_VALUE;
    + * static long ln0 = 0;
    + * static short sh1 = Short.MAX_VALUE;
    + * static short sh0 = 0;
    + *
    + * which a debugger mirrors as :
    + *
    + * PrimitiveValue pvbl1, pvbl0, pvbt1, pvbt0,
    + * pvch1, pvch0, pvdb1, pvdb0,
    + * pvfl1, pvfl0, pvin1, pvin0,
    + * pvln1, pvln0, pvsh1, pvsh0;
    + *
    + * each of the following is true:
    + *
    + * pvbl1.booleanValue(), !pvbl0.booleanValue(),
    + * pvbt1.booleanValue(), !pvbt0.booleanValue(),
    + * pvch1.booleanValue(), !pvch0.booleanValue(),
    + * pvdb1.booleanValue(), !pvdb0.booleanValue(),
    + * pvfl1.booleanValue(), !pvfl0.booleanValue(),
    + * pvin1.booleanValue(), !pvin0.booleanValue(),
    + * pvln1.booleanValue(), !pvln0.booleanValue(),
    + * pvsh1.booleanValue(), !pvsh0.booleanValue()
    + *
    + */ + +public class booleanvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new booleanvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.booleanValue.booleanvalue001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("booleanvalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl1 = execClass.fieldByName("bl1"); + Field fsbl0 = execClass.fieldByName("bl0"); + Field fsbt1 = execClass.fieldByName("bt1"); + Field fsbt0 = execClass.fieldByName("bt0"); + Field fsch1 = execClass.fieldByName("ch1"); + Field fsch0 = execClass.fieldByName("ch0"); + Field fsdb1 = execClass.fieldByName("db1"); + Field fsdb0 = execClass.fieldByName("db0"); + Field fsfl1 = execClass.fieldByName("fl1"); + Field fsfl0 = execClass.fieldByName("fl0"); + Field fsin1 = execClass.fieldByName("in1"); + Field fsin0 = execClass.fieldByName("in0"); + Field fsln1 = execClass.fieldByName("ln1"); + Field fsln0 = execClass.fieldByName("ln0"); + Field fssh1 = execClass.fieldByName("sh1"); + Field fssh0 = execClass.fieldByName("sh0"); + + PrimitiveValue pvbl1 = (PrimitiveValue) execClass.getValue(fsbl1); + PrimitiveValue pvbl0 = (PrimitiveValue) execClass.getValue(fsbl0); + PrimitiveValue pvbt1 = (PrimitiveValue) execClass.getValue(fsbt1); + PrimitiveValue pvbt0 = (PrimitiveValue) execClass.getValue(fsbt0); + PrimitiveValue pvch1 = (PrimitiveValue) execClass.getValue(fsch1); + PrimitiveValue pvch0 = (PrimitiveValue) execClass.getValue(fsch0); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + PrimitiveValue pvdb0 = (PrimitiveValue) execClass.getValue(fsdb0); + PrimitiveValue pvfl1 = (PrimitiveValue) execClass.getValue(fsfl1); + PrimitiveValue pvfl0 = (PrimitiveValue) execClass.getValue(fsfl0); + PrimitiveValue pvin1 = (PrimitiveValue) execClass.getValue(fsin1); + PrimitiveValue pvin0 = (PrimitiveValue) execClass.getValue(fsin0); + PrimitiveValue pvln1 = (PrimitiveValue) execClass.getValue(fsln1); + PrimitiveValue pvln0 = (PrimitiveValue) execClass.getValue(fsln0); + PrimitiveValue pvsh1 = (PrimitiveValue) execClass.getValue(fssh1); + PrimitiveValue pvsh0 = (PrimitiveValue) execClass.getValue(fssh0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + log2("...... checks for: pvbl1.booleanValue() and pvbl0.booleanValue()"); + if (!pvbl1.booleanValue() || pvbl0.booleanValue()) { + log3("ERROR: !pvbl1.booleanValue() || pvbl0.booleanValue()"); + expresult = 1; + } + break; + + case 1: + log2("...... checks for: pvbt1.booleanValue() and pvbt0.booleanValue()"); + if (!pvbt1.booleanValue() || pvbt0.booleanValue()) { + log3("ERROR: !pvbt1.booleanValue() || pvbt0.booleanValue()"); + expresult = 1; + } + break; + + case 2: + log2("...... checks for: pvch1.booleanValue() and pvch0.booleanValue()"); + if (!pvch1.booleanValue() || pvch0.booleanValue()) { + log3("ERROR: !pvch1.booleanValue() || pvch0.booleanValue()"); + expresult = 1; + } + break; + + case 3: + log2("...... checks for: pvdb1.booleanValue() and pvdb0.booleanValue()"); + if (!pvdb1.booleanValue() || pvdb0.booleanValue()) { + log3("ERROR: !pvdb1.booleanValue() || pvdb0.booleanValue()"); + expresult = 1; + } + break; + + case 4: + log2("...... checks for: pvfl1.booleanValue() and pvfl0.booleanValue()"); + if (!pvfl1.booleanValue() || pvfl0.booleanValue()) { + log3("ERROR: !pvfl1.booleanValue() || pvfl0.booleanValue()"); + expresult = 1; + } + break; + + case 5: + log2("...... checks for: pvin1.booleanValue() and pvin0.booleanValue()"); + if (!pvin1.booleanValue() || pvin0.booleanValue()) { + log3("ERROR: !pvin1.booleanValue() || pvin0.booleanValue()"); + expresult = 1; + } + break; + + case 6: + log2("...... checks for: pvln1.booleanValue() and pvln0.booleanValue()"); + if (!pvln1.booleanValue() || pvln0.booleanValue()) { + log3("ERROR: !pvln1.booleanValue() || pvln0.booleanValue()"); + expresult = 1; + } + break; + + case 7: + log2("...... checks for: pvsh1.booleanValue() and pvsh0.booleanValue()"); + if (!pvsh1.booleanValue() || pvsh0.booleanValue()) { + log3("ERROR: !pvsh1.booleanValue() || pvsh0.booleanValue()"); + expresult = 1; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { +// log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001/TestDescription.java new file mode 100644 index 00000000000..a126046dac8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.booleanValue() + * complies with its spec: + * public boolean booleanValue() + * Converts this value to a BooleanValue and returns the result as a boolean. + * Returns: true if this value is non-zero (or true if already a BooleanValue); + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.PrimitiveValue.booleanValue.booleanvalue001; + * a debuggee program - nsk.jdi.PrimitiveValue.booleanValue.booleanvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.booleanValue.booleanvalue001 + * nsk.jdi.PrimitiveValue.booleanValue.booleanvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.booleanValue.booleanvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001a.java new file mode 100644 index 00000000000..9bc0e6413d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/booleanValue/booleanvalue001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.booleanValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the booleanvalue001 JDI test. + */ + +public class booleanvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> booleanvalue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> booleanvalue001a: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.byteValue()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl1 = true;
    + * static boolean bl0 = false;
    + * static byte bt1 = Byte.MAX_VALUE;
    + * static byte bt0 = 0;
    + * static char ch1 = Character.MAX_VALUE;
    + * static char ch0 = 0;
    + * static double db1 = Double.MAX_VALUE;
    + * static double db0 = 0.0d;
    + * static float fl1 = Float.MAX_VALUE;
    + * static float fl0 = 0.0f;
    + * static int in1 = Integer.MAX_VALUE;
    + * static int in0 = 0;
    + * static long ln1 = Long.MAX_VALUE;
    + * static long ln0 = 0;
    + * static short sh1 = Short.MAX_VALUE;
    + * static short sh0 = 0;
    + *
    + * which a debugger mirrors as :
    + *
    + * PrimitiveValue pvbl1, pvbl0, pvbt1, pvbt0,
    + * pvch1, pvch0, pvdb1, pvdb0,
    + * pvfl1, pvfl0, pvin1, pvin0,
    + * pvln1, pvln0, pvsh1, pvsh0;
    + *
    + * each of the following is true:
    + *
    + * pvbl1.byteValue() == 1
    + * pvbl0.byteValue() == 0
    + * pvbt1.byteValue() == Byte.MAX_VALUE
    + * pvbt0.byteValue() == 0
    + * pvch1.byteValue() == (byte) Character.MAX_VALUE
    + * pvch0.byteValue() == 0
    + *
    + *
    + * pvfl1.byteValue() == (byte) Float.MAX_VALUE
    + * pvfl0.byteValue() == 0
    + * pvin1.byteValue() == (byte) Integer.MAX_VALUE
    + * pvin0.byteValue() == 0
    + * pvln1.byteValue() == (byte) Long.MAX_VALUE
    + * pvln0.byteValue() == 0
    + * pvsh1.byteValue() == (byte) Short.MAX_VALUE
    + * pvsh0.byteValue() == 0
    + *
    + */ + +public class bytevalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/byteValue/bytevalue001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new bytevalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.byteValue.bytevalue001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("bytevalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl1 = execClass.fieldByName("bl1"); + Field fsbl0 = execClass.fieldByName("bl0"); + Field fsbt1 = execClass.fieldByName("bt1"); + Field fsbt0 = execClass.fieldByName("bt0"); + Field fsch1 = execClass.fieldByName("ch1"); + Field fsch0 = execClass.fieldByName("ch0"); + Field fsdb1 = execClass.fieldByName("db1"); + Field fsdb0 = execClass.fieldByName("db0"); + Field fsfl1 = execClass.fieldByName("fl1"); + Field fsfl0 = execClass.fieldByName("fl0"); + Field fsin1 = execClass.fieldByName("in1"); + Field fsin0 = execClass.fieldByName("in0"); + Field fsln1 = execClass.fieldByName("ln1"); + Field fsln0 = execClass.fieldByName("ln0"); + Field fssh1 = execClass.fieldByName("sh1"); + Field fssh0 = execClass.fieldByName("sh0"); + + PrimitiveValue pvbl1 = (PrimitiveValue) execClass.getValue(fsbl1); + PrimitiveValue pvbl0 = (PrimitiveValue) execClass.getValue(fsbl0); + PrimitiveValue pvbt1 = (PrimitiveValue) execClass.getValue(fsbt1); + PrimitiveValue pvbt0 = (PrimitiveValue) execClass.getValue(fsbt0); + PrimitiveValue pvch1 = (PrimitiveValue) execClass.getValue(fsch1); + PrimitiveValue pvch0 = (PrimitiveValue) execClass.getValue(fsch0); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + PrimitiveValue pvdb0 = (PrimitiveValue) execClass.getValue(fsdb0); + PrimitiveValue pvfl1 = (PrimitiveValue) execClass.getValue(fsfl1); + PrimitiveValue pvfl0 = (PrimitiveValue) execClass.getValue(fsfl0); + PrimitiveValue pvin1 = (PrimitiveValue) execClass.getValue(fsin1); + PrimitiveValue pvin0 = (PrimitiveValue) execClass.getValue(fsin0); + PrimitiveValue pvln1 = (PrimitiveValue) execClass.getValue(fsln1); + PrimitiveValue pvln0 = (PrimitiveValue) execClass.getValue(fsln0); + PrimitiveValue pvsh1 = (PrimitiveValue) execClass.getValue(fssh1); + PrimitiveValue pvsh0 = (PrimitiveValue) execClass.getValue(fssh0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + log2("......checks for: pvbl1.byteValue() == 1 && pvbl0.byteValue() == 0"); + if (pvbl1.byteValue() != 1 || pvbl0.byteValue() != 0) { + log3("ERROR: pvbl1.byteValue() != 1 || pvbl0.byteValue() != 0"); + expresult = 1; + } + break; + + case 1: + log2("......checks for: pvbt1.byteValue() == Byte.MAX_VALUE && pvbt0.byteValue() == 0"); + if (pvbt1.byteValue() != Byte.MAX_VALUE || pvbt0.byteValue() != 0) { + log3("ERROR: pvbt1.byteValue() != Byte.MAX_VALUE || pvbt0.byteValue() != 0"); + expresult = 1; + } + break; + + case 2: + log2("......checks for: pvch1.byteValue() == (byte) Character.MAX_VALUE && pvch0.byteValue() == 0"); + if (pvch1.byteValue() != (byte) Character.MAX_VALUE || pvch0.byteValue() != 0) { + log3("ERROR: pvch1.byteValue() != (byte) Character.MAX_VALUE || pvch0.byteValue() != 0"); + expresult = 1; + } + break; + + case 3: + log2("......checks for: no checks"); + break; + + case 4: + log2("......checks for: pvfl1.byteValue() == (byte) Float.MAX_VALUE && pvfl0.byteValue() ==0"); + if (pvfl1.byteValue() != (byte) Float.MAX_VALUE || pvfl0.byteValue() !=0 ) { + log3("ERROR: pvfl1.byteValue() != (byte) Float.MAX_VALUE || pvfl0.byteValue() !=0"); + expresult = 1; + } + break; + + case 5: + log2("......checks for: pvin1.byteValue() == (byte) Integer.MAX_VALUE && pvin0.byteValue() == 0"); + if (pvin1.byteValue() != (byte) Integer.MAX_VALUE || pvin0.byteValue() != 0) { + log3("ERROR: pvin1.byteValue() != (byte) Integer.MAX_VALUE || pvin0.byteValue() != 0"); + expresult = 1; + } + break; + + case 6: + log2("......checks for: pvln1.byteValue() == (byte) Long.MAX_VALUE && pvln0.byteValue() == 0"); + if (pvln1.byteValue() != (byte) Long.MAX_VALUE || pvln0.byteValue() != 0) { + log3("ERROR: pvln1.byteValue() != (byte) Long.MAX_VALUE || pvln0.byteValue() != 0"); + expresult = 1; + } + break; + + case 7: + log2("......checks for: pvsh1.byteValue() == (byte) Short.MAX_VALUE && pvsh0.byteValue() == 0"); + if (pvsh1.byteValue() != (byte) Short.MAX_VALUE || pvsh0.byteValue() != 0) { + log3("ERROR: pvsh1.byteValue() != (byte) Short.MAX_VALUE || pvsh0.byteValue() != 0"); + expresult = 1; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { +// log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001/TestDescription.java new file mode 100644 index 00000000000..5bab73bcaf7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/byteValue/bytevalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.byteValue() + * complies with its spec: + * public byte byteValue() + * Converts this value to a ByteValue and returns the result as a byte. + * The value will be narrowed as necessary, and magnitude or + * precision information may be lost + * (as if the primitive had been cast to a byte). + * Returns: the value, converted to byte + * The test works as follows: + * A debugger program - nsk.jdi.PrimitiveValue.byteValue.bytevalue001; + * a debuggee program - nsk.jdi.PrimitiveValue.byteValue.bytevalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.byteValue.bytevalue001 + * nsk.jdi.PrimitiveValue.byteValue.bytevalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.byteValue.bytevalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001a.java new file mode 100644 index 00000000000..4743fca06d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/byteValue/bytevalue001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.byteValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the bytevalue001 JDI test. + */ + +public class bytevalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> bytevalue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> bytevalue001a: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.charValue()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl1 = true;
    + * static boolean bl0 = false;
    + * static byte bt1 = Byte.MAX_VALUE;
    + * static byte bt0 = 0;
    + * static char ch1 = Character.MAX_VALUE;
    + * static char ch0 = 0;
    + * static double db1 = Double.MAX_VALUE;
    + * static double db0 = 0.0d;
    + * static float fl1 = Float.MAX_VALUE;
    + * static float fl0 = 0.0f;
    + * static int in1 = Integer.MAX_VALUE;
    + * static int in0 = 0;
    + * static long ln1 = Long.MAX_VALUE;
    + * static long ln0 = 0;
    + * static short sh1 = Short.MAX_VALUE;
    + * static short sh0 = 0;
    + *
    + * which a debugger mirrors as :
    + *
    + * PrimitiveValue pvbl1, pvbl0, pvbt1, pvbt0,
    + * pvch1, pvch0, pvdb1, pvdb0,
    + * pvfl1, pvfl0, pvin1, pvin0,
    + * pvln1, pvln0, pvsh1, pvsh0;
    + *
    + * each of the following is true:
    + *
    + * pvbl1.charValue() == 1
    + * pvbl0.charValue() == 0
    + * pvbt1.charValue() == (char) Byte.MAX_VALUE
    + * pvbt0.charValue() == 0
    + * pvch1.charValue() == Character.MAX_VALUE
    + * pvch0.charValue() == 0
    + *
    + *
    + * pvfl1.charValue() == (char) Float.MAX_VALUE
    + * pvfl0.charValue() == 0
    + * pvin1.charValue() == (char) Integer.MAX_VALUE
    + * pvin0.charValue() == 0
    + * pvln1.charValue() == (char) Long.MAX_VALUE
    + * pvln0.charValue() == 0
    + * pvsh1.charValue() == (char) Short.MAX_VALUE
    + * pvsh0.charValue() == 0
    + *
    + */ + +public class charvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/charValue/charvalue001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new charvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.charValue.charvalue001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("charvalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl1 = execClass.fieldByName("bl1"); + Field fsbl0 = execClass.fieldByName("bl0"); + Field fsbt1 = execClass.fieldByName("bt1"); + Field fsbt0 = execClass.fieldByName("bt0"); + Field fsch1 = execClass.fieldByName("ch1"); + Field fsch0 = execClass.fieldByName("ch0"); + Field fsdb1 = execClass.fieldByName("db1"); + Field fsdb0 = execClass.fieldByName("db0"); + Field fsfl1 = execClass.fieldByName("fl1"); + Field fsfl0 = execClass.fieldByName("fl0"); + Field fsin1 = execClass.fieldByName("in1"); + Field fsin0 = execClass.fieldByName("in0"); + Field fsln1 = execClass.fieldByName("ln1"); + Field fsln0 = execClass.fieldByName("ln0"); + Field fssh1 = execClass.fieldByName("sh1"); + Field fssh0 = execClass.fieldByName("sh0"); + + PrimitiveValue pvbl1 = (PrimitiveValue) execClass.getValue(fsbl1); + PrimitiveValue pvbl0 = (PrimitiveValue) execClass.getValue(fsbl0); + PrimitiveValue pvbt1 = (PrimitiveValue) execClass.getValue(fsbt1); + PrimitiveValue pvbt0 = (PrimitiveValue) execClass.getValue(fsbt0); + PrimitiveValue pvch1 = (PrimitiveValue) execClass.getValue(fsch1); + PrimitiveValue pvch0 = (PrimitiveValue) execClass.getValue(fsch0); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + PrimitiveValue pvdb0 = (PrimitiveValue) execClass.getValue(fsdb0); + PrimitiveValue pvfl1 = (PrimitiveValue) execClass.getValue(fsfl1); + PrimitiveValue pvfl0 = (PrimitiveValue) execClass.getValue(fsfl0); + PrimitiveValue pvin1 = (PrimitiveValue) execClass.getValue(fsin1); + PrimitiveValue pvin0 = (PrimitiveValue) execClass.getValue(fsin0); + PrimitiveValue pvln1 = (PrimitiveValue) execClass.getValue(fsln1); + PrimitiveValue pvln0 = (PrimitiveValue) execClass.getValue(fsln0); + PrimitiveValue pvsh1 = (PrimitiveValue) execClass.getValue(fssh1); + PrimitiveValue pvsh0 = (PrimitiveValue) execClass.getValue(fssh0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + log2("......checks for: pvbl1.charValue() == 1 and pvbl0.charValue() != 0"); + if (pvbl1.charValue() != 1 || pvbl0.charValue() != 0) { + log3("ERROR: pvbl1.charValue() != 1 || pvbl0.charValue() != 0"); + expresult = 1; + } + break; + + case 1: + log2("......checks for: pvbt1.charValue() != (char) Byte.MAX_VALUE and pvbt0.charValue() != 0"); + if (pvbt1.charValue() != (char) Byte.MAX_VALUE || pvbt0.charValue() != 0) { + log3("ERROR: pvbt1.charValue() != (char) Byte.MAX_VALUE || pvbt0.charValue() != 0"); + expresult = 1; + } + break; + + case 2: + log2("......checks for: pvch1.charValue() != Character.MAX_VALUE and pvch0.charValue() != 0"); + if (pvch1.charValue() != Character.MAX_VALUE || pvch0.charValue() != 0) { + log3("ERROR: pvch1.charValue() != Character.MAX_VALUE || pvch0.charValue() != 0"); + expresult = 1; + } + break; + + case 3: + log2("......checks for: no checks"); + break; + + case 4: + log2("......checks for: pvfl1.charValue() != (char) Float.MAX_VALUE and pvfl0.charValue() !=0"); + if (pvfl1.charValue() != (char) Float.MAX_VALUE || pvfl0.charValue() !=0 ) { + log3("ERROR: pvfl1.charValue() != (char) Float.MAX_VALUE || pvfl0.charValue() !=0"); + expresult = 1; + } + break; + + case 5: + log2("......checks for: pvin1.charValue() != (char) Integer.MAX_VALUE and pvin0.charValue() != 0"); + if (pvin1.charValue() != (char) Integer.MAX_VALUE || pvin0.charValue() != 0) { + log3("ERROR: pvin1.charValue() != (char) Integer.MAX_VALUE || pvin0.charValue() != 0"); + expresult = 1; + } + break; + + case 6: + log2("......checks for: pvln1.charValue() != (char) Long.MAX_VALUE and pvln0.charValue() != 0"); + if (pvln1.charValue() != (char) Long.MAX_VALUE || pvln0.charValue() != 0) { + log3("ERROR: pvln1.charValue() != (char) Long.MAX_VALUE || pvln0.charValue() != 0"); + expresult = 1; + } + break; + + case 7: + log2("......checks for: pvsh1.charValue() != (char) Short.MAX_VALUE and pvsh0.charValue() != 0"); + if (pvsh1.charValue() != (char) Short.MAX_VALUE || pvsh0.charValue() != 0) { + log3("ERROR: pvsh1.charValue() != (char) Short.MAX_VALUE || pvsh0.charValue() != 0"); + expresult = 1; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { +// log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001/TestDescription.java new file mode 100644 index 00000000000..ad5c01a3acf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/charValue/charvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.charValue() + * complies with its spec: + * public char charValue() + * Converts this value to a CharValue and returns the result as a char. + * The value will be narrowed or widened as necessary, and + * magnitude or precision information may be lost + * (as if the primitive had been cast to a char, in the narrowing case). + * Returns: the value, converted to char + * The test works as follows: + * A debugger program - nsk.jdi.PrimitiveValue.charValue.charvalue001; + * a debuggee program - nsk.jdi.PrimitiveValue.charValue.charvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.charValue.charvalue001 + * nsk.jdi.PrimitiveValue.charValue.charvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.charValue.charvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001a.java new file mode 100644 index 00000000000..35814431b03 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/charValue/charvalue001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.charValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the charvalue001 JDI test. + */ + +public class charvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> charvalue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> charvalue001a: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.doubleValue()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl1 = true;
    + * static boolean bl0 = false;
    + * static byte bt1 = Byte.MAX_VALUE;
    + * static byte bt0 = 0;
    + * static char ch1 = Character.MAX_VALUE;
    + * static char ch0 = 0;
    + * static double db1 = Double.MAX_VALUE;
    + * static double db0 = 0.0d;
    + * static float fl1 = Float.MAX_VALUE;
    + * static float fl0 = 0.0f;
    + * static int in1 = Integer.MAX_VALUE;
    + * static int in0 = 0;
    + * static long ln1 = Long.MAX_VALUE;
    + * static long ln0 = 0;
    + * static short sh1 = Short.MAX_VALUE;
    + * static short sh0 = 0;
    + *
    + * which a debugger mirrors as :
    + *
    + * PrimitiveValue pvbl1, pvbl0, pvbt1, pvbt0,
    + * pvch1, pvch0, pvdb1, pvdb0,
    + * pvfl1, pvfl0, pvin1, pvin0,
    + * pvln1, pvln0, pvsh1, pvsh0;
    + *
    + * each of the following is true:
    + *
    + * pvbl1.doubleValue() == 1
    + * pvbl0.doubleValue() == 0
    + * pvbt1.doubleValue() == (double) Byte.MAX_VALUE
    + * pvbt0.doubleValue() == 0
    + * pvch1.doubleValue() == (double) Character.MAX_VALUE
    + * pvch0.doubleValue() == 0
    + *
    + *
    + * pvfl1.doubleValue() == (double) Float.MAX_VALUE
    + * pvfl0.doubleValue() == 0
    + * pvin1.doubleValue() == (double) Integer.MAX_VALUE
    + * pvin0.doubleValue() == 0
    + * pvln1.doubleValue() == (double) Long.MAX_VALUE
    + * pvln0.doubleValue() == 0
    + * pvsh1.doubleValue() == (double) Short.MAX_VALUE
    + * pvsh0.doubleValue() == 0
    + *
    + */ + +public class doublevalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/doubleValue/doublevalue001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new doublevalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.doubleValue.doublevalue001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("doublevalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl1 = execClass.fieldByName("bl1"); + Field fsbl0 = execClass.fieldByName("bl0"); + Field fsbt1 = execClass.fieldByName("bt1"); + Field fsbt0 = execClass.fieldByName("bt0"); + Field fsch1 = execClass.fieldByName("ch1"); + Field fsch0 = execClass.fieldByName("ch0"); + Field fsdb1 = execClass.fieldByName("db1"); + Field fsdb0 = execClass.fieldByName("db0"); + Field fsfl1 = execClass.fieldByName("fl1"); + Field fsfl0 = execClass.fieldByName("fl0"); + Field fsin1 = execClass.fieldByName("in1"); + Field fsin0 = execClass.fieldByName("in0"); + Field fsln1 = execClass.fieldByName("ln1"); + Field fsln0 = execClass.fieldByName("ln0"); + Field fssh1 = execClass.fieldByName("sh1"); + Field fssh0 = execClass.fieldByName("sh0"); + + PrimitiveValue pvbl1 = (PrimitiveValue) execClass.getValue(fsbl1); + PrimitiveValue pvbl0 = (PrimitiveValue) execClass.getValue(fsbl0); + PrimitiveValue pvbt1 = (PrimitiveValue) execClass.getValue(fsbt1); + PrimitiveValue pvbt0 = (PrimitiveValue) execClass.getValue(fsbt0); + PrimitiveValue pvch1 = (PrimitiveValue) execClass.getValue(fsch1); + PrimitiveValue pvch0 = (PrimitiveValue) execClass.getValue(fsch0); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + PrimitiveValue pvdb0 = (PrimitiveValue) execClass.getValue(fsdb0); + PrimitiveValue pvfl1 = (PrimitiveValue) execClass.getValue(fsfl1); + PrimitiveValue pvfl0 = (PrimitiveValue) execClass.getValue(fsfl0); + PrimitiveValue pvin1 = (PrimitiveValue) execClass.getValue(fsin1); + PrimitiveValue pvin0 = (PrimitiveValue) execClass.getValue(fsin0); + PrimitiveValue pvln1 = (PrimitiveValue) execClass.getValue(fsln1); + PrimitiveValue pvln0 = (PrimitiveValue) execClass.getValue(fsln0); + PrimitiveValue pvsh1 = (PrimitiveValue) execClass.getValue(fssh1); + PrimitiveValue pvsh0 = (PrimitiveValue) execClass.getValue(fssh0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + log2("......check: pvbl1.doubleValue() == 1 && pvbl0.doubleValue() == 0"); + if (pvbl1.doubleValue() != 1 || pvbl0.doubleValue() != 0) { + log3("ERROR: pvbl1.doubleValue() != 1 || pvbl0.doubleValue() != 0"); + expresult = 1; + } + break; + + case 1: + log2("......check: pvbt1.doubleValue() == (double) Byte.MAX_VALUE && pvbt0.doubleValue() == 0"); + if (pvbt1.doubleValue() != (double) Byte.MAX_VALUE || pvbt0.doubleValue() != 0) { + log3("ERROR: pvbt1.doubleValue() != (double) Byte.MAX_VALUE || pvbt0.doubleValue() != 0"); + expresult = 1; + } + break; + + case 2: + log2("......check: pvch1.doubleValue() == (double) Character.MAX_VALUE && pvch0.doubleValue() == 0"); + if (pvch1.doubleValue() != (double) Character.MAX_VALUE || pvch0.doubleValue() != 0) { + log3("ERROR: pvch1.doubleValue() != (double) Character.MAX_VALUE || pvch0.doubleValue() != 0"); + expresult = 1; + } + break; + + case 3: + log2("......check: no checks"); + break; + + case 4: + log2("......check: pvfl1.doubleValue() == (double) Float.MAX_VALUE && pvfl0.doubleValue() ==0"); + if (pvfl1.doubleValue() != (double) Float.MAX_VALUE || pvfl0.doubleValue() !=0 ) { + log3("ERROR: pvfl1.doubleValue() != (double) Float.MAX_VALUE || pvfl0.doubleValue() !=0"); + expresult = 1; + } + break; + + case 5: + log2("......check: pvin1.doubleValue() == (double) Integer.MAX_VALUE && pvin0.doubleValue() == 0"); + if (pvin1.doubleValue() != (double) Integer.MAX_VALUE || pvin0.doubleValue() != 0) { + log3("ERROR: pvin1.doubleValue() != (double) Integer.MAX_VALUE || pvin0.doubleValue() != 0"); + expresult = 1; + } + break; + + case 6: + log2("......check: pvln1.doubleValue() == (double) Long.MAX_VALUE && pvln0.doubleValue() == 0"); + if (pvln1.doubleValue() != (double) Long.MAX_VALUE || pvln0.doubleValue() != 0) { + log3("ERROR: pvln1.doubleValue() != (double) Long.MAX_VALUE || pvln0.doubleValue() != 0"); + expresult = 1; + } + break; + + case 7: + log2("......check: pvsh1.doubleValue() == (double) Short.MAX_VALUE && pvsh0.doubleValue() == 0"); + if (pvsh1.doubleValue() != (double) Short.MAX_VALUE || pvsh0.doubleValue() != 0) { + log3("ERROR: pvsh1.doubleValue() != (double) Short.MAX_VALUE || pvsh0.doubleValue() != 0"); + expresult = 1; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { +// log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001/TestDescription.java new file mode 100644 index 00000000000..40f6c794c4c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/doubleValue/doublevalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.doubleValue() + * complies with its spec: + * public double doubleValue() + * Converts this value to a DoubleValue and returns the result as a double. + * The value will be widened as necessary, and + * precision information may be lost. + * Returns: the value, converted to double + * The test works as follows: + * A debugger program - nsk.jdi.PrimitiveValue.doubleValue.doublevalue001; + * a debuggee program - nsk.jdi.PrimitiveValue.doubleValue.doublevalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.doubleValue.doublevalue001 + * nsk.jdi.PrimitiveValue.doubleValue.doublevalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.doubleValue.doublevalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001a.java new file mode 100644 index 00000000000..e93a15b2988 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.doubleValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the doublevalue001 JDI test. + */ + +public class doublevalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> doublevalue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> doublevalue001a: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.doubleValue()
    + * complies with its spec.
    + *
    + * The case for testing is as follows.
    + *
    + * when a gebugger mirrors debuggee's field:
    + * static double db1 = Double.MAX_VALUE;
    + * as PrimitiveValue pvdb1;
    + *
    + * each of the following is true:
    + *
    + * pvdb1.byteValue() == (byte) Double.MAX_VALUE
    + * pvdb1.charValue() == (char) Double.MAX_VALUE
    + * pvdb1.doubleValue() == (double) Double.MAX_VALUE
    + * pvdb1.floatValue() == (float) Double.MAX_VALUE
    + * pvdb1.intValue() == (int) Double.MAX_VALUE
    + * pvdb1.longValue() == (long) Double.MAX_VALUE
    + * pvdb1.shortValue() == (short) Double.MAX_VALUE
    + *
    + */ + +public class doublevalue002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/doubleValue/doublevalue002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new doublevalue002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.doubleValue.doublevalue002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + log2("......Field fsdb1 = execClass.fieldByName('db1');"); + Field fsdb1 = execClass.fieldByName("db1"); + + log2("......PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1);"); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + + + log2("......check: pvdb1.byteValue() == (byte) Double.MAX_VALUE"); + if (pvdb1.byteValue() != (byte) Double.MAX_VALUE) { + testExitCode = FAILED; + log3("ERROR: pvdb1.byteValue() != (byte) Double.MAX_VALUE"); + log2(" pvdb1.byteValue() == " + pvdb1.byteValue() ); + log2(" (byte) Double.MAX_VALUE == " + ((byte) Double.MAX_VALUE) ); + } + + log2("......check: pvdb1.charValue() == (char) Double.MAX_VALUE"); + if (pvdb1.charValue() != (char) Double.MAX_VALUE) { + testExitCode = FAILED; + log3("ERROR: pvdb1.charValue() != (char) Double.MAX_VALUE"); + log2(" pvdb1.charValue() == " + pvdb1.charValue() ); + log2(" (char) Double.MAX_VALUE == " + ((char) Double.MAX_VALUE) ); + } + + log2("......check: pvdb1.doubleValue() == (double) Double.MAX_VALUE"); + if (pvdb1.doubleValue() != (double) Double.MAX_VALUE) { + testExitCode = FAILED; + log3("ERROR: pvdb1.doubleValue() != (double) Double.MAX_VALUE"); + log2(" pvdb1.doubleValue() == " + pvdb1.doubleValue() ); + log2(" (double) Double.MAX_VALUE == " + ((double) Double.MAX_VALUE) ); + } + + log2("......check: pvdb1.floatValue() == (float) Double.MAX_VALUE"); + if (pvdb1.floatValue() != (float) Double.MAX_VALUE) { + testExitCode = FAILED; + log3("ERROR: pvdb1.floatValue() != (float) Double.MAX_VALUE"); + log2(" pvdb1.floatValue() == " + pvdb1.floatValue() ); + log2(" (float) Double.MAX_VALUE == " + ((float) Double.MAX_VALUE) ); + } + + log2("......check: pvdb1.intValue() == (int) Double.MAX_VALUE"); + if (pvdb1.intValue() != (int) Double.MAX_VALUE) { + testExitCode = FAILED; + log3("ERROR: pvdb1.intValue() != (int) Double.MAX_VALUE"); + log2(" pvdb1.intValue() == " + pvdb1.intValue() ); + log2(" (int) Double.MAX_VALUE == " + ((int) Double.MAX_VALUE) ); + } + + log2("......check: pvdb1.longValue() == (long) Double.MAX_VALUE"); + if (pvdb1.longValue() != (long) Double.MAX_VALUE) { + testExitCode = FAILED; + log3("ERROR: pvdb1.longValue() != (long) Double.MAX_VALUE"); + log2(" pvdb1.longValue() == " + pvdb1.longValue() ); + log2(" (long) Double.MAX_VALUE == " + ((long) Double.MAX_VALUE) ); + } + + log2("......check: pvdb1.shortValue() == (short) Double.MAX_VALUE"); + if (pvdb1.shortValue() != (short) Double.MAX_VALUE) { + testExitCode = FAILED; + log3("ERROR: pvdb1.shortValue() != (short) Double.MAX_VALUE"); + log2(" pvdb1.shortValue() == " + pvdb1.shortValue() ); + log2(" (short) Double.MAX_VALUE == " + ((short) Double.MAX_VALUE) ); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002/TestDescription.java new file mode 100644 index 00000000000..d6d89194195 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/doubleValue/doublevalue002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.doubleValue() + * complies with its spec: + * public double doubleValue() + * Converts this value to a DoubleValue and returns the result as a double. + * The value will be widened as necessary, and precision information may be lost. + * Returns: the value, converted to double + * The test works as follows: + * The debugger program - nsk.jdi.PrimitiveValue.doubleValue.doublevalue002; + * the debuggee program - nsk.jdi.PrimitiveValue.doubleValue.doublevalue002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.doubleValue.doublevalue002 + * nsk.jdi.PrimitiveValue.doubleValue.doublevalue002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.doubleValue.doublevalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002a.java new file mode 100644 index 00000000000..1f1cf9bc09c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/doubleValue/doublevalue002a.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2001, 2018, 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. + */ +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! templete parameters !!!! +// PrimitiveValue InterfaceName PrimitiveValue +// doubleValue MethodName doubleValue +// doublevalue002 TestName doublevalue002a +// ------------------------------------------------------ + +package nsk.jdi.PrimitiveValue.doubleValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the doublevalue002 JDI test. + */ + +public class doublevalue002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.floatValue()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl1 = true;
    + * static boolean bl0 = false;
    + * static byte bt1 = Byte.MAX_VALUE;
    + * static byte bt0 = 0;
    + * static char ch1 = Character.MAX_VALUE;
    + * static char ch0 = 0;
    + * static double db1 = Double.MAX_VALUE;
    + * static double db0 = 0.0d;
    + * static float fl1 = Float.MAX_VALUE;
    + * static float fl0 = 0.0f;
    + * static int in1 = Integer.MAX_VALUE;
    + * static int in0 = 0;
    + * static long ln1 = Long.MAX_VALUE;
    + * static long ln0 = 0;
    + * static short sh1 = Short.MAX_VALUE;
    + * static short sh0 = 0;
    + *
    + * which a debugger mirrors as :
    + *
    + * PrimitiveValue pvbl1, pvbl0, pvbt1, pvbt0,
    + * pvch1, pvch0, pvdb1, pvdb0,
    + * pvfl1, pvfl0, pvin1, pvin0,
    + * pvln1, pvln0, pvsh1, pvsh0;
    + *
    + * each of the following is true:
    + *
    + * pvbl1.floatValue() == 1
    + * pvbl0.floatValue() == 0
    + * pvbt1.floatValue() == (float) Byte.MAX_VALUE
    + * pvbt0.floatValue() == 0
    + * pvch1.floatValue() == (float) Character.MAX_VALUE
    + * pvch0.floatValue() == 0
    + *
    + *
    + * pvfl1.floatValue() == Float.MAX_VALUE
    + * pvfl0.floatValue() == 0
    + * pvin1.floatValue() == (float) Integer.MAX_VALUE
    + * pvin0.floatValue() == 0
    + * pvln1.floatValue() == (float) Long.MAX_VALUE
    + * pvln0.floatValue() == 0
    + * pvsh1.floatValue() == (float) Short.MAX_VALUE
    + * pvsh0.floatValue() == 0
    + *
    + */ + +public class floatvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/floatValue/floatvalue001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new floatvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.floatValue.floatvalue001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("floatvalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl1 = execClass.fieldByName("bl1"); + Field fsbl0 = execClass.fieldByName("bl0"); + Field fsbt1 = execClass.fieldByName("bt1"); + Field fsbt0 = execClass.fieldByName("bt0"); + Field fsch1 = execClass.fieldByName("ch1"); + Field fsch0 = execClass.fieldByName("ch0"); + Field fsdb1 = execClass.fieldByName("db1"); + Field fsdb0 = execClass.fieldByName("db0"); + Field fsfl1 = execClass.fieldByName("fl1"); + Field fsfl0 = execClass.fieldByName("fl0"); + Field fsin1 = execClass.fieldByName("in1"); + Field fsin0 = execClass.fieldByName("in0"); + Field fsln1 = execClass.fieldByName("ln1"); + Field fsln0 = execClass.fieldByName("ln0"); + Field fssh1 = execClass.fieldByName("sh1"); + Field fssh0 = execClass.fieldByName("sh0"); + + PrimitiveValue pvbl1 = (PrimitiveValue) execClass.getValue(fsbl1); + PrimitiveValue pvbl0 = (PrimitiveValue) execClass.getValue(fsbl0); + PrimitiveValue pvbt1 = (PrimitiveValue) execClass.getValue(fsbt1); + PrimitiveValue pvbt0 = (PrimitiveValue) execClass.getValue(fsbt0); + PrimitiveValue pvch1 = (PrimitiveValue) execClass.getValue(fsch1); + PrimitiveValue pvch0 = (PrimitiveValue) execClass.getValue(fsch0); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + PrimitiveValue pvdb0 = (PrimitiveValue) execClass.getValue(fsdb0); + PrimitiveValue pvfl1 = (PrimitiveValue) execClass.getValue(fsfl1); + PrimitiveValue pvfl0 = (PrimitiveValue) execClass.getValue(fsfl0); + PrimitiveValue pvin1 = (PrimitiveValue) execClass.getValue(fsin1); + PrimitiveValue pvin0 = (PrimitiveValue) execClass.getValue(fsin0); + PrimitiveValue pvln1 = (PrimitiveValue) execClass.getValue(fsln1); + PrimitiveValue pvln0 = (PrimitiveValue) execClass.getValue(fsln0); + PrimitiveValue pvsh1 = (PrimitiveValue) execClass.getValue(fssh1); + PrimitiveValue pvsh0 = (PrimitiveValue) execClass.getValue(fssh0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + log2("......checks for: pvbl1.floatValue() == 1 and pvbl0.floatValue() == 0"); + if (pvbl1.floatValue() != 1 || pvbl0.floatValue() != 0) { + log3("ERROR: pvbl1.floatValue() != 1 || pvbl0.floatValue() != 0"); + expresult = 1; + } + break; + + case 1: + log2("......checks for: pvbt1.floatValue() == (float) Byte.MAX_VALUE and pvbt0.floatValue() == 0"); + if (pvbt1.floatValue() != (float) Byte.MAX_VALUE || pvbt0.floatValue() != 0) { + log3("ERROR: pvbt1.floatValue() != (float) Byte.MAX_VALUE || pvbt0.floatValue() != 0"); + expresult = 1; + } + break; + + case 2: + log2("......checks for: pvch1.floatValue() == (float) Character.MAX_VALUE and pvch0.floatValue() == 0"); + if (pvch1.floatValue() != (float) Character.MAX_VALUE || pvch0.floatValue() != 0) { + log3("ERROR: pvch1.floatValue() != (float) Character.MAX_VALUE || pvch0.floatValue() != 0"); + expresult = 1; + } + break; + + case 3: + log2("......checks for: no checks"); + break; + + case 4: + log2("......checks for: pvfl1.floatValue() == Float.MAX_VALUE and pvfl0.floatValue() ==0"); + if (pvfl1.floatValue() != Float.MAX_VALUE || pvfl0.floatValue() !=0 ) { + log3("ERROR: pvfl1.floatValue() != Float.MAX_VALUE || pvfl0.floatValue() !=0"); + expresult = 1; + } + break; + + case 5: + log2("......checks for: pvin1.floatValue() == (float) Integer.MAX_VALUE and pvin0.floatValue() == 0"); + if (pvin1.floatValue() != (float) Integer.MAX_VALUE || pvin0.floatValue() != 0) { + log3("ERROR: pvin1.floatValue() != (float) Integer.MAX_VALUE || pvin0.floatValue() != 0"); + expresult = 1; + } + break; + + case 6: + log2("......checks for: pvln1.floatValue() == (float) Long.MAX_VALUE and pvln0.floatValue() == 0"); + if (pvln1.floatValue() != (float) Long.MAX_VALUE || pvln0.floatValue() != 0) { + log3("ERROR: pvln1.floatValue() != (float) Long.MAX_VALUE || pvln0.floatValue() != 0"); + expresult = 1; + } + break; + + case 7: + log2("......checks for: pvsh1.floatValue() == (float) Short.MAX_VALUE and pvsh0.floatValue() == 0"); + if (pvsh1.floatValue() != (float) Short.MAX_VALUE || pvsh0.floatValue() != 0) { + log3("ERROR: pvsh1.floatValue() != (float) Short.MAX_VALUE || pvsh0.floatValue() != 0"); + expresult = 1; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { +// log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001/TestDescription.java new file mode 100644 index 00000000000..096e6703b96 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/floatValue/floatvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.floatValue() + * complies with its spec: + * public float floatValue() + * Converts this value to a FloatValue and returns the result as a float. + * The value will be narrowed or widened as necessary, and + * magnitude or precision information may be lost ( + * as if the primitive had been cast to a float, in the narrowing case). + * Returns: the value, converted to float + * The test works as follows: + * A debugger program - nsk.jdi.PrimitiveValue.floatValue.floatvalue001; + * a debuggee program - nsk.jdi.PrimitiveValue.floatValue.floatvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.floatValue.floatvalue001 + * nsk.jdi.PrimitiveValue.floatValue.floatvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.floatValue.floatvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001a.java new file mode 100644 index 00000000000..784e7f8b885 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/floatValue/floatvalue001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.floatValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the floatvalue001 JDI test. + */ + +public class floatvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> floatvalue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> floatvalue001a: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.intValue()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl1 = true;
    + * static boolean bl0 = false;
    + * static byte bt1 = Byte.MAX_VALUE;
    + * static byte bt0 = 0;
    + * static char ch1 = Character.MAX_VALUE;
    + * static char ch0 = 0;
    + * static double db1 = Double.MAX_VALUE;
    + * static double db0 = 0.0d;
    + * static float fl1 = Float.MAX_VALUE;
    + * static float fl0 = 0.0f;
    + * static int in1 = Integer.MAX_VALUE;
    + * static int in0 = 0;
    + * static long ln1 = Long.MAX_VALUE;
    + * static long ln0 = 0;
    + * static short sh1 = Short.MAX_VALUE;
    + * static short sh0 = 0;
    + *
    + * which a debugger mirrors as :
    + *
    + * PrimitiveValue pvbl1, pvbl0, pvbt1, pvbt0,
    + * pvch1, pvch0, pvdb1, pvdb0,
    + * pvfl1, pvfl0, pvin1, pvin0,
    + * pvln1, pvln0, pvsh1, pvsh0;
    + *
    + * each of the following is true:
    + *
    + * pvbl1.intValue() == 1
    + * pvbl0.intValue() == 0
    + * pvbt1.intValue() == (int) Byte.MAX_VALUE
    + * pvbt0.intValue() == 0
    + * pvch1.intValue() == (int) Character.MAX_VALUE
    + * pvch0.intValue() == 0
    + *
    + *
    + * pvfl1.intValue() == (int) Float.MAX_VALUE
    + * pvfl0.intValue() == 0
    + * pvin1.intValue() == Integer.MAX_VALUE
    + * pvin0.intValue() == 0
    + * pvln1.intValue() == (int) Long.MAX_VALUE
    + * pvln0.intValue() == 0
    + * pvsh1.intValue() == (int) Short.MAX_VALUE
    + * pvsh0.intValue() == 0
    + *
    + */ + +public class intvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/intValue/intvalue001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new intvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.intValue.intvalue001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("intvalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl1 = execClass.fieldByName("bl1"); + Field fsbl0 = execClass.fieldByName("bl0"); + Field fsbt1 = execClass.fieldByName("bt1"); + Field fsbt0 = execClass.fieldByName("bt0"); + Field fsch1 = execClass.fieldByName("ch1"); + Field fsch0 = execClass.fieldByName("ch0"); + Field fsdb1 = execClass.fieldByName("db1"); + Field fsdb0 = execClass.fieldByName("db0"); + Field fsfl1 = execClass.fieldByName("fl1"); + Field fsfl0 = execClass.fieldByName("fl0"); + Field fsin1 = execClass.fieldByName("in1"); + Field fsin0 = execClass.fieldByName("in0"); + Field fsln1 = execClass.fieldByName("ln1"); + Field fsln0 = execClass.fieldByName("ln0"); + Field fssh1 = execClass.fieldByName("sh1"); + Field fssh0 = execClass.fieldByName("sh0"); + + PrimitiveValue pvbl1 = (PrimitiveValue) execClass.getValue(fsbl1); + PrimitiveValue pvbl0 = (PrimitiveValue) execClass.getValue(fsbl0); + PrimitiveValue pvbt1 = (PrimitiveValue) execClass.getValue(fsbt1); + PrimitiveValue pvbt0 = (PrimitiveValue) execClass.getValue(fsbt0); + PrimitiveValue pvch1 = (PrimitiveValue) execClass.getValue(fsch1); + PrimitiveValue pvch0 = (PrimitiveValue) execClass.getValue(fsch0); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + PrimitiveValue pvdb0 = (PrimitiveValue) execClass.getValue(fsdb0); + PrimitiveValue pvfl1 = (PrimitiveValue) execClass.getValue(fsfl1); + PrimitiveValue pvfl0 = (PrimitiveValue) execClass.getValue(fsfl0); + PrimitiveValue pvin1 = (PrimitiveValue) execClass.getValue(fsin1); + PrimitiveValue pvin0 = (PrimitiveValue) execClass.getValue(fsin0); + PrimitiveValue pvln1 = (PrimitiveValue) execClass.getValue(fsln1); + PrimitiveValue pvln0 = (PrimitiveValue) execClass.getValue(fsln0); + PrimitiveValue pvsh1 = (PrimitiveValue) execClass.getValue(fssh1); + PrimitiveValue pvsh0 = (PrimitiveValue) execClass.getValue(fssh0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + log2("......checks for: pvbl1.intValue() == 1 and pvbl0.intValue() == 0"); + if (pvbl1.intValue() != 1 || pvbl0.intValue() != 0) { + log3("ERROR: pvbl1.intValue() != 1 || pvbl0.intValue() != 0"); + expresult = 1; + } + break; + + case 1: + log2("......checks for: pvbt1.intValue() == (int) Byte.MAX_VALUE and pvbt0.intValue() == 0"); + if (pvbt1.intValue() != (int) Byte.MAX_VALUE || pvbt0.intValue() != 0) { + log3("ERROR: pvbt1.intValue() != (int) Byte.MAX_VALUE || pvbt0.intValue() != 0"); + expresult = 1; + } + break; + + case 2: + log2("......checks for: pvch1.intValue() == (int) Character.MAX_VALUE and pvch0.intValue() == 0"); + if (pvch1.intValue() != (int) Character.MAX_VALUE || pvch0.intValue() != 0) { + log3("ERROR: pvch1.intValue() != (int) Character.MAX_VALUE || pvch0.intValue() != 0"); + expresult = 1; + } + break; + + case 3: + log2("......checks for: no checks"); + break; + + case 4: + log2("......checks for: pvfl1.intValue() == (int) Float.MAX_VALUE and pvfl0.intValue() ==0"); + if (pvfl1.intValue() != (int) Float.MAX_VALUE || pvfl0.intValue() !=0 ) { + log3("ERROR: pvfl1.intValue() != (int) Float.MAX_VALUE || pvfl0.intValue() !=0"); + expresult = 1; + } + break; + + case 5: + log2("......checks for: pvin1.intValue() == Integer.MAX_VALUE and pvin0.intValue() == 0"); + if (pvin1.intValue() != Integer.MAX_VALUE || pvin0.intValue() != 0) { + log3("ERROR: pvin1.intValue() != Integer.MAX_VALUE || pvin0.intValue() != 0"); + expresult = 1; + } + break; + + case 6: + log2("......checks for: pvln1.intValue() == (int) Long.MAX_VALUE and pvln0.intValue() == 0"); + if (pvln1.intValue() != (int) Long.MAX_VALUE || pvln0.intValue() != 0) { + log3("ERROR: pvln1.intValue() != (int) Long.MAX_VALUE || pvln0.intValue() != 0"); + expresult = 1; + } + break; + + case 7: + log2("......checks for: pvsh1.intValue() == (int) Short.MAX_VALUE and pvsh0.intValue() == 0"); + if (pvsh1.intValue() != (int) Short.MAX_VALUE || pvsh0.intValue() != 0) { + log3("ERROR: pvsh1.intValue() != (int) Short.MAX_VALUE || pvsh0.intValue() != 0"); + expresult = 1; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { +// log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001/TestDescription.java new file mode 100644 index 00000000000..1b615978966 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/intValue/intvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.intValue() + * complies with its spec: + * public int intValue() + * Converts this value to an IntegerValue and returns the result as an int. + * The value will be narrowed or widened as necessary, and + * magnitude or precision information may be lost + * (as if the primitive had been cast to an int, in the narrowing case). + * Returns: the value, converted to int + * The test works as follows: + * A debugger program - nsk.jdi.PrimitiveValue.intValue.intvalue001; + * a debuggee program - nsk.jdi.PrimitiveValue.intValue.intvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.intValue.intvalue001 + * nsk.jdi.PrimitiveValue.intValue.intvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.intValue.intvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001a.java new file mode 100644 index 00000000000..0bf522dc4a0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/intValue/intvalue001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.intValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the intvalue001 JDI test. + */ + +public class intvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> intvalue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> intvalue001a: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.longValue()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl1 = true;
    + * static boolean bl0 = false;
    + * static byte bt1 = Byte.MAX_VALUE;
    + * static byte bt0 = 0;
    + * static char ch1 = Character.MAX_VALUE;
    + * static char ch0 = 0;
    + * static double db1 = Double.MAX_VALUE;
    + * static double db0 = 0.0d;
    + * static float fl1 = Float.MAX_VALUE;
    + * static float fl0 = 0.0f;
    + * static int in1 = Integer.MAX_VALUE;
    + * static int in0 = 0;
    + * static long ln1 = Long.MAX_VALUE;
    + * static long ln0 = 0;
    + * static short sh1 = Short.MAX_VALUE;
    + * static short sh0 = 0;
    + *
    + * which a debugger mirrors as :
    + *
    + * PrimitiveValue pvbl1, pvbl0, pvbt1, pvbt0,
    + * pvch1, pvch0, pvdb1, pvdb0,
    + * pvfl1, pvfl0, pvin1, pvin0,
    + * pvln1, pvln0, pvsh1, pvsh0;
    + *
    + * each of the following is true:
    + *
    + * pvbl1.longValue() == 1
    + * pvbl0.longValue() == 0
    + * pvbt1.longValue() == (long) Byte.MAX_VALUE
    + * pvbt0.longValue() == 0
    + * pvch1.longValue() == (long) Character.MAX_VALUE
    + * pvch0.longValue() == 0
    + *
    + *
    + * pvfl1.longValue() == (long) Float.MAX_VALUE
    + * pvfl0.longValue() == 0
    + * pvin1.longValue() == (long) Integer.MAX_VALUE
    + * pvin0.longValue() == 0
    + * pvln1.longValue() == Long.MAX_VALUE
    + * pvln0.longValue() == 0
    + * pvsh1.longValue() == (long) Short.MAX_VALUE
    + * pvsh0.longValue() == 0
    + *
    + */ + +public class longvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/longValue/longvalue001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new longvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.longValue.longvalue001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("longvalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl1 = execClass.fieldByName("bl1"); + Field fsbl0 = execClass.fieldByName("bl0"); + Field fsbt1 = execClass.fieldByName("bt1"); + Field fsbt0 = execClass.fieldByName("bt0"); + Field fsch1 = execClass.fieldByName("ch1"); + Field fsch0 = execClass.fieldByName("ch0"); + Field fsdb1 = execClass.fieldByName("db1"); + Field fsdb0 = execClass.fieldByName("db0"); + Field fsfl1 = execClass.fieldByName("fl1"); + Field fsfl0 = execClass.fieldByName("fl0"); + Field fsin1 = execClass.fieldByName("in1"); + Field fsin0 = execClass.fieldByName("in0"); + Field fsln1 = execClass.fieldByName("ln1"); + Field fsln0 = execClass.fieldByName("ln0"); + Field fssh1 = execClass.fieldByName("sh1"); + Field fssh0 = execClass.fieldByName("sh0"); + + PrimitiveValue pvbl1 = (PrimitiveValue) execClass.getValue(fsbl1); + PrimitiveValue pvbl0 = (PrimitiveValue) execClass.getValue(fsbl0); + PrimitiveValue pvbt1 = (PrimitiveValue) execClass.getValue(fsbt1); + PrimitiveValue pvbt0 = (PrimitiveValue) execClass.getValue(fsbt0); + PrimitiveValue pvch1 = (PrimitiveValue) execClass.getValue(fsch1); + PrimitiveValue pvch0 = (PrimitiveValue) execClass.getValue(fsch0); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + PrimitiveValue pvdb0 = (PrimitiveValue) execClass.getValue(fsdb0); + PrimitiveValue pvfl1 = (PrimitiveValue) execClass.getValue(fsfl1); + PrimitiveValue pvfl0 = (PrimitiveValue) execClass.getValue(fsfl0); + PrimitiveValue pvin1 = (PrimitiveValue) execClass.getValue(fsin1); + PrimitiveValue pvin0 = (PrimitiveValue) execClass.getValue(fsin0); + PrimitiveValue pvln1 = (PrimitiveValue) execClass.getValue(fsln1); + PrimitiveValue pvln0 = (PrimitiveValue) execClass.getValue(fsln0); + PrimitiveValue pvsh1 = (PrimitiveValue) execClass.getValue(fssh1); + PrimitiveValue pvsh0 = (PrimitiveValue) execClass.getValue(fssh0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + log2("......checks for: pvbl1.longValue() == 1 and pvbl0.longValue() == 0"); + if (pvbl1.longValue() != 1 || pvbl0.longValue() != 0) { + log3("ERROR: pvbl1.longValue() != 1 || pvbl0.longValue() != 0"); + expresult = 1; + } + break; + + case 1: + log2("......checks for: pvbt1.longValue() == (long) Byte.MAX_VALUE and pvbt0.longValue() == 0"); + if (pvbt1.longValue() != (long) Byte.MAX_VALUE || pvbt0.longValue() != 0) { + log3("ERROR: pvbt1.longValue() != (long) Byte.MAX_VALUE || pvbt0.longValue() != 0"); + expresult = 1; + } + break; + + case 2: + log2("......checks for: pvch1.longValue() == (long) Character.MAX_VALUE and pvch0.longValue() == 0"); + if (pvch1.longValue() != (long) Character.MAX_VALUE || pvch0.longValue() != 0) { + log3("ERROR: pvch1.longValue() != (long) Character.MAX_VALUE || pvch0.longValue() != 0"); + expresult = 1; + } + break; + + case 3: + log2("......checks for: no checks"); + break; + + case 4: + log2("......checks for: pvfl1.longValue() == (long) Float.MAX_VALUE and pvfl0.longValue() ==0"); + if (pvfl1.longValue() != (long) Float.MAX_VALUE || pvfl0.longValue() !=0 ) { + log3("ERROR: pvfl1.longValue() != (long) Float.MAX_VALUE || pvfl0.longValue() !=0"); + expresult = 1; + } + break; + + case 5: + log2("......checks for: pvin1.longValue() == (long) Integer.MAX_VALUE and pvin0.longValue() == 0"); + if (pvin1.longValue() != (long) Integer.MAX_VALUE || pvin0.longValue() != 0) { + log3("ERROR: pvin1.longValue() != (long) Integer.MAX_VALUE || pvin0.longValue() != 0"); + expresult = 1; + } + break; + + case 6: + log2("......checks for: pvln1.longValue() == Long.MAX_VALUE and pvln0.longValue() == 0"); + if (pvln1.longValue() != Long.MAX_VALUE || pvln0.longValue() != 0) { + log3("ERROR: pvln1.longValue() != Long.MAX_VALUE || pvln0.longValue() != 0"); + expresult = 1; + } + break; + + case 7: + log2("......checks for: pvsh1.longValue() == (long) Short.MAX_VALUE and pvsh0.longValue() == 0"); + if (pvsh1.longValue() != (long) Short.MAX_VALUE || pvsh0.longValue() != 0) { + log3("ERROR: pvsh1.longValue() != (long) Short.MAX_VALUE || pvsh0.longValue() != 0"); + expresult = 1; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { +// log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001/TestDescription.java new file mode 100644 index 00000000000..55cfeaab5b2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/longValue/longvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.longValue() + * complies with its spec: + * public long longValue() + * Converts this value to a LongValue and returns the result as a long. + * The value will be narrowed or widened as necessary, and + * magnitude or precision information may be lost + * (as if the primitive had been cast to a long, in the narrowing case). + * Returns: the value, converted to long + * The test works as follows: + * A debugger program - nsk.jdi.PrimitiveValue.longValue.longvalue001; + * a debuggee program - nsk.jdi.PrimitiveValue.longValue.longvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.longValue.longvalue001 + * nsk.jdi.PrimitiveValue.longValue.longvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.longValue.longvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001a.java new file mode 100644 index 00000000000..2970752b731 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/longValue/longvalue001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.longValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the longvalue001a JDI test. + */ + +public class longvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> longvalue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> longvalue001a: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * PrimitiveValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.PrimitiveValue.shortValue()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl1 = true;
    + * static boolean bl0 = false;
    + * static byte bt1 = Byte.MAX_VALUE;
    + * static byte bt0 = 0;
    + * static char ch1 = Character.MAX_VALUE;
    + * static char ch0 = 0;
    + * static double db1 = Double.MAX_VALUE;
    + * static double db0 = 0.0d;
    + * static float fl1 = Float.MAX_VALUE;
    + * static float fl0 = 0.0f;
    + * static int in1 = Integer.MAX_VALUE;
    + * static int in0 = 0;
    + * static long ln1 = Long.MAX_VALUE;
    + * static long ln0 = 0;
    + * static short sh1 = Short.MAX_VALUE;
    + * static short sh0 = 0;
    + *
    + * which a debugger mirrors as :
    + *
    + * PrimitiveValue pvbl1, pvbl0, pvbt1, pvbt0,
    + * pvch1, pvch0, pvdb1, pvdb0,
    + * pvfl1, pvfl0, pvin1, pvin0,
    + * pvln1, pvln0, pvsh1, pvsh0;
    + *
    + * each of the following is true:
    + *
    + * pvbl1.shortValue() == 1
    + * pvbl0.shortValue() == 0
    + * pvbt1.shortValue() == (short) Byte.MAX_VALUE
    + * pvbt0.shortValue() == 0
    + * pvch1.shortValue() == (short) Character.MAX_VALUE
    + * pvch0.shortValue() == 0
    + *
    + *
    + * pvfl1.shortValue() == (short) Float.MAX_VALUE
    + * pvfl0.shortValue() == 0
    + * pvin1.shortValue() == (short) Integer.MAX_VALUE
    + * pvin0.shortValue() == 0
    + * pvln1.shortValue() == (short) Long.MAX_VALUE
    + * pvln0.shortValue() == 0
    + * pvsh1.shortValue() == Short.MAX_VALUE
    + * pvsh0.shortValue() == 0
    + *
    + */ + +public class shortvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/PrimitiveValue/shortValue/shortvalue001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new shortvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.PrimitiveValue.shortValue.shortvalue001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("shortvalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl1 = execClass.fieldByName("bl1"); + Field fsbl0 = execClass.fieldByName("bl0"); + Field fsbt1 = execClass.fieldByName("bt1"); + Field fsbt0 = execClass.fieldByName("bt0"); + Field fsch1 = execClass.fieldByName("ch1"); + Field fsch0 = execClass.fieldByName("ch0"); + Field fsdb1 = execClass.fieldByName("db1"); + Field fsdb0 = execClass.fieldByName("db0"); + Field fsfl1 = execClass.fieldByName("fl1"); + Field fsfl0 = execClass.fieldByName("fl0"); + Field fsin1 = execClass.fieldByName("in1"); + Field fsin0 = execClass.fieldByName("in0"); + Field fsln1 = execClass.fieldByName("ln1"); + Field fsln0 = execClass.fieldByName("ln0"); + Field fssh1 = execClass.fieldByName("sh1"); + Field fssh0 = execClass.fieldByName("sh0"); + + PrimitiveValue pvbl1 = (PrimitiveValue) execClass.getValue(fsbl1); + PrimitiveValue pvbl0 = (PrimitiveValue) execClass.getValue(fsbl0); + PrimitiveValue pvbt1 = (PrimitiveValue) execClass.getValue(fsbt1); + PrimitiveValue pvbt0 = (PrimitiveValue) execClass.getValue(fsbt0); + PrimitiveValue pvch1 = (PrimitiveValue) execClass.getValue(fsch1); + PrimitiveValue pvch0 = (PrimitiveValue) execClass.getValue(fsch0); + PrimitiveValue pvdb1 = (PrimitiveValue) execClass.getValue(fsdb1); + PrimitiveValue pvdb0 = (PrimitiveValue) execClass.getValue(fsdb0); + PrimitiveValue pvfl1 = (PrimitiveValue) execClass.getValue(fsfl1); + PrimitiveValue pvfl0 = (PrimitiveValue) execClass.getValue(fsfl0); + PrimitiveValue pvin1 = (PrimitiveValue) execClass.getValue(fsin1); + PrimitiveValue pvin0 = (PrimitiveValue) execClass.getValue(fsin0); + PrimitiveValue pvln1 = (PrimitiveValue) execClass.getValue(fsln1); + PrimitiveValue pvln0 = (PrimitiveValue) execClass.getValue(fsln0); + PrimitiveValue pvsh1 = (PrimitiveValue) execClass.getValue(fssh1); + PrimitiveValue pvsh0 = (PrimitiveValue) execClass.getValue(fssh0); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + log2("......checks for: pvbl1.shortValue() == 1 and pvbl0.shortValue() == 0"); + if (pvbl1.shortValue() != 1 || pvbl0.shortValue() != 0) { + log3("ERROR: pvbl1.shortValue() != 1 || pvbl0.shortValue() != 0"); + expresult = 1; + } + break; + + case 1: + log2("......checks for: pvbt1.shortValue() == (short) Byte.MAX_VALUE and pvbt0.shortValue() == 0"); + if (pvbt1.shortValue() != (short) Byte.MAX_VALUE || pvbt0.shortValue() != 0) { + log3("ERROR: pvbt1.shortValue() != (short) Byte.MAX_VALUE || pvbt0.shortValue() != 0"); + expresult = 1; + } + break; + + case 2: + log2("......checks for: pvch1.shortValue() == (short) Character.MAX_VALUE and pvch0.shortValue() == 0"); + if (pvch1.shortValue() != (short) Character.MAX_VALUE || pvch0.shortValue() != 0) { + log3("ERROR: pvch1.shortValue() != (short) Character.MAX_VALUE || pvch0.shortValue() != 0"); + expresult = 1; + } + break; + + case 3: + log2("......checks for: no checks"); + break; + + case 4: + log2("......checks for: pvfl1.shortValue() == (short) Float.MAX_VALUE and pvfl0.shortValue() ==0"); + if (pvfl1.shortValue() != (short) Float.MAX_VALUE || pvfl0.shortValue() !=0 ) { + log3("ERROR: pvfl1.shortValue() != (short) Float.MAX_VALUE || pvfl0.shortValue() !=0"); + expresult = 1; + } + break; + + case 5: + log2("......checks for: pvin1.shortValue() == (short) Integer.MAX_VALUE and pvin0.shortValue() == 0"); + if (pvin1.shortValue() != (short) Integer.MAX_VALUE || pvin0.shortValue() != 0) { + log3("ERROR: pvin1.shortValue() != (short) Integer.MAX_VALUE || pvin0.shortValue() != 0"); + expresult = 1; + } + break; + + case 6: + log2("......checks for: pvln1.shortValue() == (short) Long.MAX_VALUE and pvln0.shortValue() == 0"); + if (pvln1.shortValue() != (short) Long.MAX_VALUE || pvln0.shortValue() != 0) { + log3("ERROR: pvln1.shortValue() != (short) Long.MAX_VALUE || pvln0.shortValue() != 0"); + expresult = 1; + } + break; + + case 7: + log2("......checks for: pvsh1.shortValue() == Short.MAX_VALUE and pvsh0.shortValue() == 0"); + if (pvsh1.shortValue() != Short.MAX_VALUE || pvsh0.shortValue() != 0) { + log3("ERROR: pvsh1.shortValue() != Short.MAX_VALUE || pvsh0.shortValue() != 0"); + expresult = 1; + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { +// log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001/TestDescription.java new file mode 100644 index 00000000000..5e704d5c639 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/PrimitiveValue/shortValue/shortvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * PrimitiveValue. + * The test checks up that a result of the method + * com.sun.jdi.PrimitiveValue.shortValue() + * complies with its spec: + * public short shortValue() + * Converts this value to a ShortValue and returns the result as a short. + * The value will be narrowed or widened as necessary, and + * magnitude or precision information may be lost + * (as if the primitive had been cast to a short, in the narrowing case). + * Returns: the value, converted to short + * The test works as follows: + * A debugger program - nsk.jdi.PrimitiveValue.shortValue.shortvalue001; + * a debuggee program - nsk.jdi.PrimitiveValue.shortValue.shortvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.PrimitiveValue.shortValue.shortvalue001 + * nsk.jdi.PrimitiveValue.shortValue.shortvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.PrimitiveValue.shortValue.shortvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001a.java new file mode 100644 index 00000000000..89bd687d366 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveValue/shortValue/shortvalue001a.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.PrimitiveValue.shortValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the shortvalue001 JDI test. + */ + +public class shortvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> shortvalue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> shortvalue001a: " + message); + } + + //====================================================== test program + + static boolean bl1 = true; + static boolean bl0 = false; + static byte bt1 = Byte.MAX_VALUE; + static byte bt0 = 0; + static char ch1 = Character.MAX_VALUE; + static char ch0 = 0; + static double db1 = Double.MAX_VALUE; + static double db0 = 0.0d; + static float fl1 = Float.MAX_VALUE; + static float fl0 = 0.0f; + static int in1 = Integer.MAX_VALUE; + static int in0 = 0; + static long ln1 = Long.MAX_VALUE; + static long ln0 = 0; + static short sh1 = Short.MAX_VALUE; + static short sh0 = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ReferenceType: + + * - locationsOfLine(int) for boundary values of Integer + + * - locationsOfLine(String, String, int) for boundary values of + * Integer and various combinations of value of String arguments such as + * null, "", , where means the some + * names of nonexisting object. + * + * - equals(Object) for null-value + */ +public class bounds001 { + + private final static String prefix = "nsk.jdi.ReferenceType._bounds_."; + private final static String debuggerName = prefix + "bounds001"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + public static int exitStatus; + public static Log log; + public static Debugee debugee; + + private static String propertyValue = "something"; + private static int lineNumbers[] = { + Integer.MIN_VALUE, + -1, + Integer.MAX_VALUE + }; + + private static long codeIndexes[] = { + Long.MIN_VALUE, + -1, + Long.MAX_VALUE + }; + + private static String[][] strParams = { + {null, null }, + {null, "" }, + {null, "bounds001_hotchpotch"}, + {"", null }, + {"", "" }, + {"", "bounds001_hotchpotch"}, + {"bounds001_jumble", null }, + {"bounds001_jumble", "" }, + {"bounds001_jumble", "bounds001_hotchpotch"} + }; + +//---------------------------------------------------- + + public static void display(String msg) { + log.display(msg); + } + + public static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + bounds001 thisTest = new bounds001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType testedClass = debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + List list = null; + + display(""); + display("invoking locationsOfLine(int):"); + display("------------------------------"); + for (int i = 0; i < lineNumbers.length; i++) { + display("\tparameter: " + lineNumbers[i]); + try { + list = testedClass.locationsOfLine(lineNumbers[i]); + display("\tsize of locations list: " + list.size()); + if (list.size() > 0) { + complain("\twrong size"); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + display("invoking locationsOfLine(String, String, int):"); + display("----------------------------------------------"); + for (int i = 0; i < lineNumbers.length; i++) { + for (int j = 0; j < strParams.length; j++) { + display("\tparameters: \"" + strParams[j][0] + "\", \"" + + strParams[j][1] + "\", " + lineNumbers[i]); + try { + list = testedClass.locationsOfLine(strParams[j][0], + strParams[j][1], lineNumbers[i]); + display("\tsize of locations list: " + list.size()); + if (list.size() > 0) { + complain("\twrong size"); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + } + + display("invoking equals(Object):"); + display("----------------------"); + display("\tparameter: "); + try { + if (!testedClass.equals(null)) { + display("\tis not equal to "); + } else { + complain("\tis equal to "); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("\tUnexpected: " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001/TestDescription.java new file mode 100644 index 00000000000..1f838b5a864 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/_bounds_/bounds001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the following methods of com.sun.jdi.Method: + * - locationsOfLine(int) for boundary values of Integer + * - locationsOfLine(String, String, int) for boundary values of + * Integer and various combinations of value of String arguments + * such as null, "", , where means the some + * names of nonexisting object. + * - equals(Object) for null-value + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType._bounds_.bounds001 + * nsk.jdi.ReferenceType._bounds_.bounds001a + * + * @comment make sure bounds001a is compiled with full debug info + * @clean nsk.jdi.ReferenceType._bounds_.bounds001a + * @compile -g:lines,source,vars ../bounds001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType._bounds_.bounds001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001a.java new file mode 100644 index 00000000000..925925c7a68 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds001a.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * bounds001a is deugee's part of the bounds001. + */ +public class bounds001a { + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(bounds001.SGNL_READY); + String instr = pipe.readln(); + if (instr.equals(bounds001.SGNL_QUIT)) { + log.display("constructor> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("constructor> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002.java new file mode 100644 index 00000000000..f8eeed59262 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.util.*; +import java.io.*; + +/** + * The test checks up the methods of com.sun.jdi.ReferenceType: + * - fieldByName(String) + * - methodsByName(String) + * - methodsByName(String, String) + * - getValue(Field) + * - getValues(List) + * - equals(Object) + * These methods are invoked with null-value of parameter. + * getValues(List) is invoked with List of zero-size too. + */ + +public class bounds002 { + + private final static String prefix = "nsk.jdi.ReferenceType._bounds_."; + private final static String debuggerName = prefix + "bounds002"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + bounds002 thisTest = new bounds002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType testedClass = debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + Value retValue; + + Field field; + display("fieldByName(null)"); + try { + field = testedClass.fieldByName(null); + if (field != null) { + complain("wrong field: " + field); + exitStatus = Consts.TEST_FAILED; + } else { + display("field: " + field); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + List methodList; + display("methodsByName(null)"); + try { + methodList = testedClass.methodsByName(null); + if (methodList.size() != 0) { + complain("wrong size of method list: " + methodList.size()); + exitStatus = Consts.TEST_FAILED; + } else { + display("size of method list: " + methodList.size()); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("methodsByName(null, null)"); + try { + methodList = testedClass.methodsByName(null, null); + if (methodList.size() != 0) { + complain("wrong size of method list: " + methodList.size()); + exitStatus = Consts.TEST_FAILED; + } else { + display("size of method list: " + methodList.size()); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("getValue(null)"); + try { + retValue = testedClass.getValue(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("getValues(null)"); + try { + testedClass.getValues(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + List lst = null; + display("getValues(list with size = 0)"); + try { + testedClass.getValues(lst); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("equals(null)"); + try { + if (testedClass.equals(null)) { + complain("is equal to "); + exitStatus = Consts.TEST_FAILED; + } else { + display("is not equal to "); + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002/TestDescription.java new file mode 100644 index 00000000000..8710dda7622 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/_bounds_/bounds002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the methods of com.sun.jdi.ReferenceType: + * - fieldByName(String) + * - methodsByName(String) + * - methodsByName(String, String) + * - getValue(Field) + * - getValues(List) + * - equals(Object) + * These methods are invoked with null-value of parameter. + * getValues(List) is invoked with List of zero-size too. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType._bounds_.bounds002 + * nsk.jdi.ReferenceType._bounds_.bounds002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType._bounds_.bounds002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002a.java new file mode 100644 index 00000000000..bcb40c05197 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/_bounds_/bounds002a.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * bounds002a is deugee's part of the bounds002. + */ +public class bounds002a { + + public final static String testedFieldName = "testedObj"; + public final static String testedMethod = "justMethod"; + + private static bounds002b testedObj = new bounds002b(); + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(bounds002.SGNL_READY); + String instr = pipe.readln(); + if (instr.equals(bounds002.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class bounds002b { + private static Object testedObj; + public static int justMethod(int val) { + return val; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001.java new file mode 100644 index 00000000000..f6bf66908a9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001.java @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method allFields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class allfields001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.allFields.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "allfields001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "allfields001aClassForCheck"; + private final static String super_class_for_check = package_prefix + "allfields001aSuperClassForCheck"; + private final static String interf_for_check = package_prefix + "allfields001aInterfaceForCheck"; + private final static String not_found_sign = "NOT FOUND"; + private final static String passed_sign = "PASSED"; + private static String fields_for_check[][] = { + +// field name type name static declaring class check result + + {"s_boolean_field", "boolean", " static", class_for_check, not_found_sign }, + {"s_byte_field", "byte", " static", class_for_check, not_found_sign }, + {"s_char_field", "char", " static", class_for_check, not_found_sign }, + {"s_double_field", "double", " static", class_for_check, not_found_sign }, + {"s_float_field", "float", " static", class_for_check, not_found_sign }, + {"s_int_field", "int", " static", class_for_check, not_found_sign }, + {"s_long_field", "long", " static", class_for_check, not_found_sign }, + {"s_object_field", "java.lang.Object", " static", class_for_check, not_found_sign }, + {"s_prim_array_field", "long[]", " static", class_for_check, not_found_sign }, + {"s_ref_array_field", "java.lang.Object[]", " static", class_for_check, not_found_sign }, + {"i_boolean_field", "boolean", "", class_for_check, not_found_sign }, + {"i_byte_field", "byte", "", class_for_check, not_found_sign }, + {"i_char_field", "char", "", class_for_check, not_found_sign }, + {"i_double_field", "double", "", class_for_check, not_found_sign }, + {"i_float_field", "float", "", class_for_check, not_found_sign }, + {"i_int_field", "int", "", class_for_check, not_found_sign }, + {"i_long_field", "long", "", class_for_check, not_found_sign }, + {"i_object_field", "java.lang.Object", "", class_for_check, not_found_sign }, + {"i_prim_array_field", "long[]", "", class_for_check, not_found_sign }, + {"i_ref_array_field", "java.lang.Object[]", "", class_for_check, not_found_sign }, + {"s_super_hidden_prim_field", "long", " static", class_for_check, not_found_sign }, + {"s_super_hidden_ref_field", "java.lang.Object", " static", class_for_check, not_found_sign }, + {"i_super_hidden_prim_field", "long", " static", class_for_check, not_found_sign }, + {"i_super_hidden_ref_field", "java.lang.Object", " static", class_for_check, not_found_sign }, + {"s_interf_hidden_prim_field", "long", " static", class_for_check, not_found_sign }, + {"s_interf_hidden_ref_field", "java.lang.Object", " static", class_for_check, not_found_sign }, + {"s_super_boolean_field", "boolean", " static", super_class_for_check, not_found_sign }, + {"s_super_byte_field", "byte", " static", super_class_for_check, not_found_sign }, + {"s_super_char_field", "char", " static", super_class_for_check, not_found_sign }, + {"s_super_double_field", "double", " static", super_class_for_check, not_found_sign }, + {"s_super_float_field", "float", " static", super_class_for_check, not_found_sign }, + {"s_super_int_field", "int", " static", super_class_for_check, not_found_sign }, + {"s_super_long_field", "long", " static", super_class_for_check, not_found_sign }, + {"s_super_object_field", "java.lang.Object", " static", super_class_for_check, not_found_sign }, + {"s_super_hidden_prim_field", "long", " static", super_class_for_check, not_found_sign }, + {"s_super_hidden_ref_field", "java.lang.Object", " static", super_class_for_check, not_found_sign }, + {"i_super_boolean_field", "boolean", "", super_class_for_check, not_found_sign }, + {"i_super_byte_field", "byte", "", super_class_for_check, not_found_sign }, + {"i_super_char_field", "char", "", super_class_for_check, not_found_sign }, + {"i_super_double_field", "double", "", super_class_for_check, not_found_sign }, + {"i_super_float_field", "float", "", super_class_for_check, not_found_sign }, + {"i_super_int_field", "int", "", super_class_for_check, not_found_sign }, + {"i_super_long_field", "long", "", super_class_for_check, not_found_sign }, + {"i_super_object_field", "java.lang.Object", "", super_class_for_check, not_found_sign }, + {"i_super_hidden_prim_field", "long", "", super_class_for_check, not_found_sign }, + {"i_super_hidden_ref_field", "java.lang.Object", "", super_class_for_check, not_found_sign }, + {"ambiguous_prim_field", "long", "", super_class_for_check, not_found_sign }, + {"ambiguous_ref_field", "java.lang.Object", "", super_class_for_check, not_found_sign }, + {"s_interf_boolean_field", "boolean", " static", interf_for_check, not_found_sign }, + {"s_interf_byte_field", "byte", " static", interf_for_check, not_found_sign }, + {"s_interf_char_field", "char", " static", interf_for_check, not_found_sign }, + {"s_interf_double_field", "double", " static", interf_for_check, not_found_sign }, + {"s_interf_float_field", "float", " static", interf_for_check, not_found_sign }, + {"s_interf_int_field", "int", " static", interf_for_check, not_found_sign }, + {"s_interf_long_field", "long", " static", interf_for_check, not_found_sign }, + {"s_interf_object_field", "java.lang.Object", " static", interf_for_check, not_found_sign }, + {"s_interf_hidden_prim_field", "long", " static", interf_for_check, not_found_sign }, + {"s_interf_hidden_ref_field", "java.lang.Object", " static", interf_for_check, not_found_sign }, + {"ambiguous_prim_field", "long", " static", interf_for_check, not_found_sign }, + {"ambiguous_ref_field", "java.lang.Object", " static", interf_for_check, not_found_sign } + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new allfields001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/allFields/allfields001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/allFields/allfields001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/allFields/allfields001 test LOG:"); + out_stream.println("==> test checks allFields() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> allfields001: allfields001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> allfields001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> allfields001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allfields001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> allfields001: check ReferenceType.allFields() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean allFields_method_error = false; + int fields_for_check_number = fields_for_check.length; + int not_found_fields_number = 0; + int all_fields_number = 0; + int unexpected_found_fields_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> allfields001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List all_fields_list = null; + try { + all_fields_list = refType.allFields(); + } + catch (Throwable thrown) { + out_stream.println("##> allfields001: FAILED: ReferenceType.allFields() throws unexpected " + + thrown); + allFields_method_error = true; + break; + } + all_fields_number = all_fields_list.size(); + Field all_fields[] = new Field[all_fields_number]; + String unexpected_all_fields[] = new String[all_fields_number]; + all_fields_list.toArray(all_fields); + for (int i=0; i allfields001: FAILED: field is NOT found: " + current_field_for_check); + not_found_fields_number++; + } + else { + print_log_on_verbose + ("--> allfields001: PASSED for field: " + current_field_for_check); + } + } + for (int i=0; i allfields001: FAILED: unexpected found field: " + unexpected_all_fields[i]); + } + break; + } + + out_stream.println("--> allfields001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || allFields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println("--> allfields001: expected found fields number = " + fields_for_check_number); + out_stream.println("--> allfields001: in fact found fields number = " + all_fields_number); + out_stream.println("--> allfields001: expected and in fact found fields number = " + + (fields_for_check_number - not_found_fields_number)); + out_stream.println + ("##> allfields001: NOT found fields number = " + not_found_fields_number); + out_stream.println + ("##> allfields001: UNEXPECTED found fields number = " + unexpected_found_fields_number); + } + if ( not_found_fields_number + unexpected_found_fields_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> allfields001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> allfields001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> allfields001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001/TestDescription.java new file mode 100644 index 00000000000..502dcfd2184 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allFields/allfields001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/allFields/allfields001 test + * checks the allFields() method of ReferenceType interface + * of the com.sun.jdi package : + * the ReferenceType.allFields() method is checked for fields of + * debugee's class which extends super class and implements interface. + * Debugee's class has both hidden and ambiguous fields which should + * present in Field list returned by the allFields() method. + * Each field is checked for field name, field type, static modifier + * and declaring class. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allFields.allfields001 + * nsk.jdi.ReferenceType.allFields.allfields001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allFields.allfields001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001a.java new file mode 100644 index 00000000000..8fa0790cc71 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields001a.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the allfields001 JDI test. + */ + +public class allfields001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i allfields001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + allfields001aClassForCheck class_for_check = new allfields001aClassForCheck(); + + print_log_on_verbose("**> allfields001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allfields001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allfields001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> allfields001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> allfields001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class allfields001aClassForCheck extends allfields001aSuperClassForCheck implements allfields001aInterfaceForCheck { + + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + static long[] s_prim_array_field; + static Object[] s_ref_array_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + long[] i_prim_array_field; + Object[] i_ref_array_field; + + static long s_super_hidden_prim_field; + static Object s_super_hidden_ref_field; + + static long i_super_hidden_prim_field; + static Object i_super_hidden_ref_field; + + static long s_interf_hidden_prim_field; + static Object s_interf_hidden_ref_field; + +} + +class allfields001aSuperClassForCheck { + + static boolean s_super_boolean_field; + static byte s_super_byte_field; + static char s_super_char_field; + static double s_super_double_field; + static float s_super_float_field; + static int s_super_int_field; + static long s_super_long_field; + static Object s_super_object_field; + + static long s_super_hidden_prim_field; + static Object s_super_hidden_ref_field; + + boolean i_super_boolean_field; + byte i_super_byte_field; + char i_super_char_field; + double i_super_double_field; + float i_super_float_field; + int i_super_int_field; + long i_super_long_field; + Object i_super_object_field; + + long i_super_hidden_prim_field; + Object i_super_hidden_ref_field; + + long ambiguous_prim_field; + Object ambiguous_ref_field; + +} + +interface allfields001aInterfaceForCheck { + + static final boolean s_interf_boolean_field = true; + static final byte s_interf_byte_field = (byte)1; + static final char s_interf_char_field = '1'; + static final double s_interf_double_field = 999; + static final float s_interf_float_field = 99; + static final int s_interf_int_field = 100; + static final long s_interf_long_field = 1000; + static final Object s_interf_object_field = new Object(); + + static final long s_interf_hidden_prim_field = 1; + static final Object s_interf_hidden_ref_field = new Object(); + + static final long ambiguous_prim_field = 1; + static final Object ambiguous_ref_field = new Object(); + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002.java new file mode 100644 index 00000000000..5ff2b6b4928 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method allFields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class allfields002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String package_prefix = "nsk.jdi.ReferenceType.allFields."; + private final static String thisClassName = package_prefix + "allfields002"; + private final static String debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "allfields002b"; + + private final static String classLoaderName = package_prefix + "allfields002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + static ArgumentHandler argsHandler; + private static Log logHandler; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new allfields002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ReferenceType/allFields/allfields002 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ReferenceType/allFields/allfields002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + private void print_log_anyway(String message) { + logHandler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + Debugee debugee; + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + print_log_on_verbose("==> nsk/jdi/ReferenceType/allFields/allfields002 test LOG:"); + print_log_on_verbose("==> test checks allFields() method of ReferenceType interface "); + print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> allfields002: allfields002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> allfields002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> allfields002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allfields002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> allfields002: check ReferenceType.allFields() method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean allFields_method_error = false; + + while ( true ) { // test body + + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> allfields002: Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> allfields002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> allfields002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + List all_fields_list = null; + try { + all_fields_list = refType.allFields(); + print_log_anyway + ("##> allfields002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + allFields_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> allfields002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> allfields002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + allFields_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || allFields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> allfields002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> allfields002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> allfields002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/TestDescription.java new file mode 100644 index 00000000000..5131effb152 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allFields/allfields002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/allFields/allfields002 test + * checks the allFields() method of ReferenceType interface + * of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.allFields() method is called for + * this class - ClassNotPreparedException should be thrown + * in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "out_stream.println" are replaced with + * "print_log_on_verbose" and "print_log_anyway". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allFields.allfields002 + * nsk.jdi.ReferenceType.allFields.allfields002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allFields.allfields002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/loadclass/allfields002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/loadclass/allfields002b.java new file mode 100644 index 00000000000..98d244b3b17 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002/loadclass/allfields002b.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.allFields; + +/** + * This class is loaded by allfields002aClassLoader . + */ +class allfields002b { + + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002a.java new file mode 100644 index 00000000000..eb4e99cd953 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields002a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + + +/** + * This class is used as debugee application for the allfields002 JDI test. + */ + +public class allfields002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.allFields."; + private final static String checked_class_name = package_prefix + "allfields002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i allfields002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + allfields002aClassLoader customClassLoader = new allfields002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> allfields002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> allfields002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> allfields002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allfields002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allfields002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> allfields002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> allfields002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class allfields002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public allfields002aClassLoader(String classPath, String className) { + super(allfields002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003.java new file mode 100644 index 00000000000..1b70ed4a82c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method allFields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class allfields003 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.allFields.", + thisClassName = package_prefix + "allfields003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "allfields003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new allfields003().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/allFields/allfields003 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/allFields/allfields003 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + private static void print_log_without_verbose(String message) { + if ( ! verbose_mode ) { + out_stream.println(message); + } + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/allFields/allfields003 test LOG:"); + out_stream.println("--> test checks allFields() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for UNLOADED class\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> allfields003: allfields003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> allfields003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + out_stream.println + ("##> allfields003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allfields003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> allfields003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + out_stream.println + ("##> allfields003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allfields003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean allFields_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> allfields003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> allfields003: getting ReferenceType object for loaded checked class..."); + out_stream.println("##> allfields003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> allfields003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> allfields003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> allfields003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + out_stream.println + ("--> allfields003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + out_stream.println + ("--> ReferenceType.allFields() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + out_stream.println + ("##> allfields003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allfields003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> allfields003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> allfields003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> allfields003: check that checked class has been unloaded realy..."); + out_stream.println + ("--> allfields003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + out_stream.println + ("--> ReferenceType.allFields() method can NOT be checked!"); + break; + } + + out_stream.println + ("--> allfields003: check ReferenceType.allFields() method for unloaded class..."); + List all_fields_list = null; + try { + all_fields_list = refType.allFields(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + out_stream.println + ("--> allfields003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + out_stream.println + ("##> allfields003: FAILED: unexpected Exception thrown - " + expt.toString()); + out_stream.println + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + allFields_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || allFields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> allfields003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> allfields003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> allfields003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of allfields003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TestDescription.java new file mode 100644 index 00000000000..f58719a9ee8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allFields/allfields003. + * VM Testbase keywords: [diehard, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/allFields/allfields003 test + * checks the allFields() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * allFields() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - allfields003b class was moved in 'loadclass' subdirectory; + * - package name was added in allfields003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for allfields003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allFields.allfields003 + * nsk.jdi.ReferenceType.allFields.allfields003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allFields.allfields003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/loadclass/allfields003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/loadclass/allfields003b.java new file mode 100644 index 00000000000..4c17fbe2051 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003/loadclass/allfields003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the allFields() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.allFields; + +class allfields003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003a.java new file mode 100644 index 00000000000..68b88e0af6c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields003a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the allfields003 JDI test. + */ + +public class allfields003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + static String package_prefix = "nsk.jdi.ReferenceType.allFields."; + static String checked_class_name = package_prefix + "allfields003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> allfields003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> allfields003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + print_log_on_verbose + ("--> allfields003a: checked class dir:" + checked_class_dir); + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> allfields003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + print_log_on_verbose + ("**> allfields003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> allfields003a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> allfields003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allfields003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allfields003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> allfields003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> allfields003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> allfields003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> allfields003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> allfields003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> allfields003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> allfields003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allfields003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allfields003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> allfields003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> allfields003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of allfields003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004.java new file mode 100644 index 00000000000..03634e108f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method allFields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class allfields004 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.allFields.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "allfields004", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "allfields004aClassForCheck"; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new allfields004().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/allFields/allfields004 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/allFields/allfields004 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/allFields/allfields004 test LOG:"); + out_stream.println("==> test checks allFields() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for class without any declarated fields\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> allfields004: allfields004a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> allfields004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> allfields004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allfields004: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> allfields004: check ReferenceType.allFields() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean allFields_method_error = false; + int all_fields_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> allfields004: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List all_fields_list = null; + try { + all_fields_list = refType.allFields(); + } + catch (Throwable thrown) { + out_stream.println("##> allfields004: FAILED: ReferenceType.allFields() throws unexpected " + + thrown); + allFields_method_error = true; + break; + } + all_fields_number = all_fields_list.size(); + if ( all_fields_number == 0 ) { + break; + } + Field all_fields[] = new Field[all_fields_number]; + all_fields_list.toArray(all_fields); + for (int i=0; i allfields004: FAILED: unexpected found field: " + full_checked_field); + } + break; + } + + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || allFields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + if ( all_fields_number > 0 ) { + out_stream.println + ("##> allfields004: UNEXPECTED found fields number = " + all_fields_number); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println + ("--> allfields004: PASSED: returned list of fields is empty!"); + } + + print_log_on_verbose("--> allfields004: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> allfields004: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> allfields004: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004/TestDescription.java new file mode 100644 index 00000000000..f924e11aab5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allFields/allfields004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/allFields/allfields004 test + * checks the allFields() method of ReferenceType interface + * of the com.sun.jdi package for class without any declarated fields: + * the ReferenceType.allFields() method is checked for + * debugee's class which extends super class and implements interface. + * All these classes do not contain any declarated fields. + * The test expects the returned list of fields to be empty. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allFields.allfields004 + * nsk.jdi.ReferenceType.allFields.allfields004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allFields.allfields004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004a.java new file mode 100644 index 00000000000..2384484e59c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields004a.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the allfields004 JDI test. + */ + +public class allfields004a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i allfields004a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + allfields004aClassForCheck class_for_check = new allfields004aClassForCheck(); + + print_log_on_verbose("**> allfields004a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allfields004a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allfields004a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("##> allfields004a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("##> allfields004a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class allfields004aClassForCheck extends allfields004aSuperClassForCheck implements allfields004aInterfaceForCheck { +} + +class allfields004aSuperClassForCheck { +} + +interface allfields004aInterfaceForCheck { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005.java new file mode 100644 index 00000000000..ea2957dfa70 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.allFields() + * properly returns an empty field list for arrays (ArrayType) and primitive + * classes.

    + * + * Debugger part of it attempts to get a list of all fields declared + * and inherited in several reference types corresponding to debuggee field + * values, which themselves are:
    + * primitive classes, and arrays of primitive types and classes. + */ +public class allfields005 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.allFields.allfields005t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 24; + // tested allfields used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allfields005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "allfields005t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + check(); + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check () { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName("f1").type(); + String className = checkedClass.name(); + + List l = checkedClass.allFields(); + if (l.isEmpty()) { + complain("\t ReferenceType.allFields() returned empty list for type: " + className); + exitStatus = Consts.TEST_FAILED; + } else { + + for (int i = 0; i < expectedEnumFields.length; i++) { + Iterator it = l.iterator(); + while (it.hasNext()) { + Field checkedField = it.next(); + if (expectedEnumFields[i][0].equals(checkedField.name()) && + checkedField.declaringType().name().equals(expectedEnumFields[i][1]) ) + + expectedEnumFields[i][2] = "found"; + } + } + + for (int i = 0; i < expectedEnumFields.length; i++) { + if (expectedEnumFields[i][2] != null) { + display("enum " + className + " has field " + expectedEnumFields[i][0]); + display("\t of type " + expectedEnumFields[i][1]); + } else { + complain("enum " + className + " does not have field " + expectedEnumFields[i][0]); + complain("\t of type " + expectedEnumFields[i][1]); + exitStatus = Consts.TEST_FAILED; + } + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006/TestDescription.java new file mode 100644 index 00000000000..903476d2ec6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allFields/allfields006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for allFields() method of ReferenceType interface. + * The test checks if the method returns all enum constants + * declared in mirrored enum type and all inherited fields + * regardless if they are ambigous or not. + * The test consists of a debugger program (allfields006.java) + * and debuggee application (allfields006a.java). + * Package name is nsk.jdi.ReferenceType.allFields . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls allFields() method for field f1 + * of enum type declared in allfields006a class. + * The result list must include enum constant fields e1 and e2, + * and two inherited fields with same name i1. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allFields.allfields006 + * nsk.jdi.ReferenceType.allFields.allfields006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allFields.allfields006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006a.java new file mode 100644 index 00000000000..1f5e452e417 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields006a.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.allFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class allfields006a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static allfields006Enum1 f1 = allfields006Enum1.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(allfields006.SIGNAL_READY); + receiveSignal(allfields006.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum allfields006Enum1 implements allfields006i1, allfields006i2 { + e1, e2; +} + +interface allfields006i1 { + public final int i1 = 1; +} + +interface allfields006i2 { + public final int i1 = 2; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001.java new file mode 100644 index 00000000000..f38a6b23fdd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001.java @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.allLineLocations; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.allLineLocations()
    + * complies with its spec.
    + * The test checks up that a list of locations for
    + * a tested ReferenceType object
    + * - is not empty and
    + * - is ordered in a proper, from low to high, sequence.
    + */ + +public class alllinelocations001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/allLineLocations/alllinelocations001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new alllinelocations001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.allLineLocations.alllinelocations001a"; + + String mName = "nsk.jdi.ReferenceType.allLineLocations"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List locations = null; + ReferenceType refType = null; + + log2(" getting: List classes = vm.classesByName(mName + '.TestClass');"); + List classes = vm.classesByName(mName + ".TestClass"); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2(" getting a tested ReferenceType object 'refType'"); + refType = (ReferenceType) classes.get(0); + + log2("......locations = refType.allLineLocations(); no AbsentInformationException is expected"); + try { + locations = refType.allLineLocations(); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + + log2("......checking up on a value of locations.size(); 0 is not expected"); + if (locations.size() == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + log2("......checking up element order in the List"); + + ListIterator listIterator = locations.listIterator(); + + Location location1 = null; + Location location2 = null; + + int i2; + + for (i2 = 0; listIterator.hasNext(); i2++) { + + long codeIndex1 = 0l; + long codeIndex2 = 0l; + + try { + location2 = (Location) listIterator.next(); + } catch ( ClassCastException e) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + break ; + } + codeIndex2 = location2.codeIndex(); + if (i2 == 0) { + continue; + } + + if (codeIndex2 < codeIndex1) { + testExitCode = FAILED; + log3("ERROR: codeIndex disorder: codeIndex2 < codeIndex1"); + break ; + } + + codeIndex1 = codeIndex2; + } + + log2("......compareing locations.size() to a processed number of elements in the list"); + if (locations.size() != i2) { + testExitCode = FAILED; + log3("ERROR: locations.size() != the processed number"); + break ; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001/TestDescription.java new file mode 100644 index 00000000000..729b38148f7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allLineLocations/alllinelocations001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.allLineLocations() + * complies with its spec: + * public List allLineLocations() + * throws AbsentInformationException + * Returns a list containing a Location object for + * each executable source line in this reference type. + * This method is equivalent to allLineLocations(vm.getDefaultStratum(),null) - + * see allLineLocations(String,String) for more information. + * Throws: AbsentInformationException - + * if there is no line number information for this class and + * there are non-native, non-abstract executable members of this class. + * ClassNotPreparedException - + * if this class not yet been prepared. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.allLineLocations.alllinelocations001; + * the debuggee program - nsk.jdi.ReferenceType.allLineLocations.alllinelocations001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The option + * JAVAC_OPTS=-g + * is put into the locationsofline002.cfg file. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allLineLocations.alllinelocations001 + * nsk.jdi.ReferenceType.allLineLocations.alllinelocations001a + * + * @comment make sure alllinelocations001a is compiled with full debug info + * @clean nsk.jdi.ReferenceType.allLineLocations.alllinelocations001a + * @compile -g:lines,source,vars ../alllinelocations001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allLineLocations.alllinelocations001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001a.java new file mode 100644 index 00000000000..1c9c6b01d2f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations001a.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.allLineLocations; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the alllinelocations001 JDI test. + */ + +public class alllinelocations001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ReferenceType.allLineLocations() + * properly returns an empty list for arrays (ArrayType), primitive + * classes, and for interfaces (InterfaceType) if the interface has + * no executable code in its class initialization at the specified line + * number.

    + * + * Debugger part of it attempts to get all locations that map to the debuggee + * field values/type declaration, which themselves are:
    + * primitive classes, arrays of primitive types and classes, and finally, + * an interface type. + */ +public class alllinelocations002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.allLineLocations.alllinelocations002t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 25; + // tested fields and used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr", + "dummyIf" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new alllinelocations002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "alllinelocations002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; i + * 9 --> 1000, source1 + * 10 --> 1001, source1 + * ... ... + * 16 --> 1007, source1 + * sde_testMethod1 + * 20 --> 1100, source1 + * 21 --> 1101, source1 + * ... ... + * 27 --> 1107, source1 + * sde_testMethod1 + * 31 --> 1200, source1 + * 32 --> 1201, source1 + * ... ... + * 38 --> 1207, source1 + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that method 'com.sun.jdi.ReferenceType.allLineLocations(String stratum, String sourceName)' + * returns only expected locations for all stratums: for 'Java' stratum, and for stratums 'TestStratum1'-'TestStratum3'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allLineLocations_ss.allLineLocations_ss003.allLineLocations_ss003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allLineLocations_ss.allLineLocations_ss003.allLineLocations_ss003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.ReferenceType.allLineLocations_ss.allLineLocations_ss003; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class allLineLocations_ss003 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allLineLocations_ss003().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type1( + className, + testStratumCount, + true); + + /* + * Method 'prepareDefaultPatchedClassFile_Type1' creates class file with + * following line mapping for each TestStratum: "Java" "TestStratum" + * + * + * 9 --> 1000, source1 + * 10 --> 1001, source1 + * ... + * ... + * 16 --> 1007, source1 + * + * sde_testMethod1 + * 20 --> 1100, source1 + * 21 --> 1101, source1 + * ... + * ... + * 27 --> 1107, source1 + * + * sde_testMethod1 + * 31 --> 1200, source1 + * 32 --> 1201, source1 + * ... + * ... + * 38 --> 1207, source1 + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName : testStratumData.keySet()) { + List expectedLocations = testStratumData.get(stratumName).allLocations; + + // all locations has the same source + String locationsSource = expectedLocations.get(0).sourceName; + + log.display("Check locations for stratum: " + stratumName + ", source " + locationsSource); + + try { + compareLocations( + referenceType.allLineLocations(stratumName, locationsSource), + expectedLocations, + stratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + + log.display("Check locations for stratum: " + stratumName + ", source " + null); + + try { + compareLocations(referenceType.allLineLocations(stratumName, null), expectedLocations, stratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss004/allLineLocations_ss004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss004/allLineLocations_ss004.java new file mode 100644 index 00000000000..1df8bd172fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss004/allLineLocations_ss004.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss004. + * VM Testbase keywords: [quick, jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that method 'com.sun.jdi.Method.allLineLocations(String stratum, String sourceName)' returns + * correct values for all stratums available for class and if sourceName == null locaitions for all sources are returned. + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3') and for each of this stratums following line mapping + * is defined (each method has locations in 3 different sources): + * "Java" "TestStratum" + * + * 9 --> 1000, source1, path1 + * 10 --> 1000, source2, path2 + * 11 --> 1000, source3, path3 + * ... ... + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1100, source2, path2 + * 22 --> 1100, source3, path3 + * ... ... + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1200, source2, path2 + * 33 --> 1200, source3, path3 + * ... ... + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that method 'com.sun.jdi.ReferenceType.allLineLocations(String stratum, String sourceName)' + * returns only expected locations for all test stratums('TestStratum1'-'TestStratum3') depending on given source name, + * and if source name is null locations for all sources are returned. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allLineLocations_ss.allLineLocations_ss004.allLineLocations_ss004 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allLineLocations_ss.allLineLocations_ss004.allLineLocations_ss004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.ReferenceType.allLineLocations_ss.allLineLocations_ss004; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class allLineLocations_ss004 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allLineLocations_ss004().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type2(className, testStratumCount); + /* + * Method 'prepareDefaultPatchedClassFile_Type2' creates class file with + * following line mapping for each test stratum: "Java" "TestStratum" + * + * + * 9 --> 1000, source1, path1 + * 10 --> 1001, source2, path2 + * 11 --> 1002, source3, path3 + * ... + * ... + * + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1101, source2, path2 + * 22 --> 1102, source3, path3 + * ... + * ... + * + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1201, source2, path2 + * 33 --> 1207, source3, path3 ... ... + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName : testStratumData.keySet()) { + LocationsData locationsData = testStratumData.get(stratumName); + + // for all available sources names + for (String sourceName : locationsData.sourceLocations.keySet()) { + List expectedLocations = locationsData.sourceLocations.get(sourceName); + + log.display("Check locations for stratum: '" + stratumName + "', source '" + sourceName + "'"); + + try { + compareLocations( + referenceType.allLineLocations(stratumName, sourceName), + expectedLocations, + stratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + } + + // check case when sourceName is null + log.display("Check locations for stratum: '" + stratumName + "', source " + null); + try { + compareLocations( + referenceType.allLineLocations(stratumName, null), + locationsData.allLocations, + stratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001.java new file mode 100644 index 00000000000..9672ba1f813 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.allLineLocations_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.allLineLocations(String,String)
    + * The test checks up that a list of locations for
    + * a tested ReferenceType object
    + * - is not empty and
    + * - is ordered in a proper, from low to high, sequence.
    + */ + +public class alllinelocations_ss001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new alllinelocations_ss001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.allLineLocations_ss.alllinelocations_ss001a"; + + String mName = "nsk.jdi.ReferenceType.allLineLocations_ss"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List locations = null; + ReferenceType refType = null; + + log2(" getting: List classes = vm.classesByName(mName + '.TestClass');"); + List classes = vm.classesByName(mName + ".TestClass"); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2(" getting a tested ReferenceType object 'refType'"); + refType = (ReferenceType) classes.get(0); + + log2("...... getting : String defaultStratum = vm.getDefaultStratum();"); + String defaultStratum = vm.getDefaultStratum(); + + log2("......locations = refType.allLineLocations(defaultStratum, null);"); + log2(" no AbsentInformationException is expected"); + try { + locations = refType.allLineLocations(defaultStratum, null); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + + log2("......checking up on a value of locations.size(); 0 is not expected"); + if (locations.size() == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + log2("......checking up element order in the List"); + + ListIterator listIterator = locations.listIterator(); + + Location location1 = null; + Location location2 = null; + + int i2; + + for (i2 = 0; listIterator.hasNext(); i2++) { + + long codeIndex1 = 0l; + long codeIndex2 = 0l; + + try { + location2 = (Location) listIterator.next(); + } catch ( ClassCastException e) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + break ; + } + codeIndex2 = location2.codeIndex(); + if (i2 == 0) { + continue; + } + + if (codeIndex2 < codeIndex1) { + testExitCode = FAILED; + log3("ERROR: codeIndex disorder: codeIndex2 < codeIndex1"); + break ; + } + + codeIndex1 = codeIndex2; + } + + log2("......compareing locations.size() to a processed number of elements in the list"); + if (locations.size() != i2) { + testExitCode = FAILED; + log3("ERROR: locations.size() != the processed number"); + break ; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001/TestDescription.java new file mode 100644 index 00000000000..bfc3acbb311 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001/TestDescription.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.allLineLocations(String, String) + * complies with its spec: + * public List allLineLocations(String stratum, String sourceName) + * throws AbsentInformationException + * Returns a list containing a Location object for + * each executable source line in this reference type. + * Each location maps a source line to a range of code indices. + * The beginning of the range can be determined through Location.codeIndex(). + * The returned list may contain multiple locations for + * a particular line number, if the compiler and/or VM has mapped that line + * to two or more disjoint code index ranges. + * Note that it is possible for the same source line + * to represent different code index ranges in different methods. + * For arrays (ArrayType) and primitive classes, + * the returned list is always empty. + * For interfaces (InterfaceType), the returned list will be non-empty + * only if the interface has executable code in its class initialization. + * Returned list is for the specified stratum + * (see Location for a description of strata). + * Parameters: stratum - The stratum to retrieve information from or + * null for the defaultStratum(). + * sourceName - Return locations only within this source file or + * null to return locations. + * Returns: a List of all source line Location objects. + * Throws: AbsentInformationException - + * if there is no line number information for this class and + * there are non-native, non-abstract executable members of + * this class. + * Or if sourceName is non-null and + * source name information is not present. + * ClassNotPreparedException - + * if this class not yet been prepared. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.allLineLocations_ss.alllinelocations_ss001; + * the debuggee program - nsk.jdi.ReferenceType.allLineLocations_ss.alllinelocations_ss001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The option + * JAVAC_OPTS=-g + * is put into the locationsofline002.cfg file. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allLineLocations_ss.alllinelocations_ss001 + * nsk.jdi.ReferenceType.allLineLocations_ss.alllinelocations_ss001a + * + * @comment make sure alllinelocations_ss001a is compiled with full debug info + * @clean nsk.jdi.ReferenceType.allLineLocations_ss.alllinelocations_ss001a + * @compile -g:lines,source,vars ../alllinelocations_ss001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allLineLocations_ss.alllinelocations_ss001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001a.java new file mode 100644 index 00000000000..6482b4a5db5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss001a.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.allLineLocations_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the alllinelocations_ss001 JDI test. + */ + +public class alllinelocations_ss001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ReferenceType.allLineLocations(String,String) + * properly returns an empty list for arrays (ArrayType), primitive + * classes, and for interfaces (InterfaceType) if the interface has + * no executable code in its class initialization at the specified line + * number.

    + * + * Debugger part of it attempts to get all locations that map to the debuggee + * field values/type declaration, which themselves are:
    + * primitive classes, arrays of primitive types and classes, and finally, + * an interface type. + */ +public class alllinelocations_ss002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.allLineLocations_ss.alllinelocations_ss002t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 25; + // tested fields and used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr", + "dummyIf" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new alllinelocations_ss002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "alllinelocations_ss002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; iallMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class allmethods001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.allMethods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "allmethods001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "allmethods001aClassForCheck"; + private final static String super_class_for_check = package_prefix + "allmethods001aSuperClassForCheck"; + private final static String interf_for_check = package_prefix + "allmethods001aInterfaceForCheck"; + private final static String not_found_sign = "NOT FOUND"; + private final static String passed_sign = "PASSED"; + private final static String Object_class_name = "java.lang.Object"; + private static String methods_for_check[][] = { + +// method name declaring class check result + + {"", class_for_check, not_found_sign}, + {"ClassForCheck", class_for_check, not_found_sign}, + {"s_void_method", class_for_check, not_found_sign}, + {"s_boolean_method", class_for_check, not_found_sign}, + {"s_byte_method", class_for_check, not_found_sign}, + {"s_char_method", class_for_check, not_found_sign}, + {"s_double_method", class_for_check, not_found_sign}, + {"s_float_method", class_for_check, not_found_sign}, + {"s_int_method", class_for_check, not_found_sign}, + {"s_long_method", class_for_check, not_found_sign}, + {"s_string_method", class_for_check, not_found_sign}, + {"s_object_method", class_for_check, not_found_sign}, + {"s_prim_array_method", class_for_check, not_found_sign}, + {"s_ref_array_method", class_for_check, not_found_sign}, + {"s_super_hidden_void_method", class_for_check, not_found_sign}, + {"s_super_hidden_prim_method", class_for_check, not_found_sign}, + {"s_super_hidden_ref_method", class_for_check, not_found_sign}, + {"s_void_par_method", class_for_check, not_found_sign}, + {"s_boolean_par_method", class_for_check, not_found_sign}, + {"s_byte_par_method", class_for_check, not_found_sign}, + {"s_char_par_method", class_for_check, not_found_sign}, + {"s_double_par_method", class_for_check, not_found_sign}, + {"s_float_par_method", class_for_check, not_found_sign}, + {"s_int_par_method", class_for_check, not_found_sign}, + {"s_long_par_method", class_for_check, not_found_sign}, + {"s_string_par_method", class_for_check, not_found_sign}, + {"s_object_par_method", class_for_check, not_found_sign}, + {"s_prim_array_par_method", class_for_check, not_found_sign}, + {"s_ref_array_par_method", class_for_check, not_found_sign}, + {"s_super_hidden_void_par_method", class_for_check, not_found_sign}, + {"s_super_hidden_prim_par_method", class_for_check, not_found_sign}, + {"s_super_hidden_ref_par_method", class_for_check, not_found_sign}, + {"s_native_method", class_for_check, not_found_sign}, + {"s_synchr_method", class_for_check, not_found_sign}, + {"s_final_method", class_for_check, not_found_sign}, + {"s_private_method", class_for_check, not_found_sign}, + {"s_protected_method", class_for_check, not_found_sign}, + {"s_public_method", class_for_check, not_found_sign}, + {"i_void_method", class_for_check, not_found_sign}, + {"i_boolean_method", class_for_check, not_found_sign}, + {"i_byte_method", class_for_check, not_found_sign}, + {"i_char_method", class_for_check, not_found_sign}, + {"i_double_method", class_for_check, not_found_sign}, + {"i_float_method", class_for_check, not_found_sign}, + {"i_int_method", class_for_check, not_found_sign}, + {"i_long_method", class_for_check, not_found_sign}, + {"i_string_method", class_for_check, not_found_sign}, + {"i_object_method", class_for_check, not_found_sign}, + {"i_prim_array_method", class_for_check, not_found_sign}, + {"i_ref_array_method", class_for_check, not_found_sign}, + {"i_super_overridden_void_method", class_for_check, not_found_sign}, + {"i_super_overridden_prim_method", class_for_check, not_found_sign}, + {"i_super_overridden_ref_method", class_for_check, not_found_sign}, + {"i_interf_overridden_void_method", class_for_check, not_found_sign}, + {"i_interf_overridden_prim_method", class_for_check, not_found_sign}, + {"i_interf_overridden_ref_method", class_for_check, not_found_sign}, + {"i_void_par_method", class_for_check, not_found_sign}, + {"i_boolean_par_method", class_for_check, not_found_sign}, + {"i_byte_par_method", class_for_check, not_found_sign}, + {"i_char_par_method", class_for_check, not_found_sign}, + {"i_double_par_method", class_for_check, not_found_sign}, + {"i_float_par_method", class_for_check, not_found_sign}, + {"i_int_par_method", class_for_check, not_found_sign}, + {"i_long_par_method", class_for_check, not_found_sign}, + {"i_string_par_method", class_for_check, not_found_sign}, + {"i_object_par_method", class_for_check, not_found_sign}, + {"i_prim_array_par_method", class_for_check, not_found_sign}, + {"i_ref_array_par_method", class_for_check, not_found_sign}, + {"i_super_overridden_void_par_method", class_for_check, not_found_sign}, + {"i_super_overridden_prim_par_method", class_for_check, not_found_sign}, + {"i_super_overridden_ref_par_method", class_for_check, not_found_sign}, + {"i_interf_overridden_void_par_method", class_for_check, not_found_sign}, + {"i_interf_overridden_prim_par_method", class_for_check, not_found_sign}, + {"i_interf_overridden_ref_par_method", class_for_check, not_found_sign}, + {"i_abstract_method", class_for_check, not_found_sign}, + {"i_native_method", class_for_check, not_found_sign}, + {"i_synchr_method", class_for_check, not_found_sign}, + {"i_final_method", class_for_check, not_found_sign}, + {"i_private_method", class_for_check, not_found_sign}, + {"i_protected_method", class_for_check, not_found_sign}, + {"i_public_method", class_for_check, not_found_sign}, + {"", class_for_check, not_found_sign}, + + {"", super_class_for_check, not_found_sign}, + {"s_super_void_method", super_class_for_check, not_found_sign}, + {"s_super_prim_method", super_class_for_check, not_found_sign}, + {"s_super_ref_method", super_class_for_check, not_found_sign}, + {"i_super_void_method", super_class_for_check, not_found_sign}, + {"i_super_prim_method", super_class_for_check, not_found_sign}, + {"i_super_ref_method", super_class_for_check, not_found_sign}, + {"s_super_hidden_void_method", super_class_for_check, not_found_sign}, + {"s_super_hidden_prim_method", super_class_for_check, not_found_sign}, + {"s_super_hidden_ref_method", super_class_for_check, not_found_sign}, + {"s_super_hidden_void_par_method", super_class_for_check, not_found_sign}, + {"s_super_hidden_prim_par_method", super_class_for_check, not_found_sign}, + {"s_super_hidden_ref_par_method", super_class_for_check, not_found_sign}, + {"i_super_overridden_void_method", super_class_for_check, not_found_sign}, + {"i_super_overridden_prim_method", super_class_for_check, not_found_sign}, + {"i_super_overridden_ref_method", super_class_for_check, not_found_sign}, + {"i_super_overridden_void_par_method", super_class_for_check, not_found_sign}, + {"i_super_overridden_prim_par_method", super_class_for_check, not_found_sign}, + {"i_super_overridden_ref_par_method", super_class_for_check, not_found_sign}, + {"i_multiple_inherited_method", super_class_for_check, not_found_sign}, + + {"i_interf_ref_method", interf_for_check, not_found_sign}, + {"i_interf_prim_method", interf_for_check, not_found_sign}, + {"i_interf_void_method", interf_for_check, not_found_sign}, + {"i_interf_overridden_void_method", interf_for_check, not_found_sign}, + {"i_interf_overridden_prim_method", interf_for_check, not_found_sign}, + {"i_interf_overridden_ref_method", interf_for_check, not_found_sign}, + {"i_interf_overridden_void_par_method", interf_for_check, not_found_sign}, + {"i_interf_overridden_prim_par_method", interf_for_check, not_found_sign}, + {"i_interf_overridden_ref_par_method", interf_for_check, not_found_sign}, + {"i_multiple_inherited_method", interf_for_check, not_found_sign} + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new allmethods001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/allMethods/allmethods001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/allMethods/allmethods001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/allMethods/allmethods001 test LOG:"); + out_stream.println("==> test checks allMethods() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> allmethods001: allmethods001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> allmethods001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> allmethods001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allmethods001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> allmethods001: check ReferenceType.allMethods() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean allMethods_method_error = false; + int methods_for_check_number = methods_for_check.length; + int not_found_methods_number = 0; + int all_methods_number = 0; + int unexpected_found_methods_number = 0; + int disregarded_all_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> allmethods001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List all_methods_list = null; + try { + all_methods_list = refType.allMethods(); + } + catch (Throwable thrown) { + out_stream.println("##> allmethods001: FAILED: ReferenceType.allMethods() throws unexpected " + + thrown); + allMethods_method_error = true; + break; + } + all_methods_number = all_methods_list.size(); + Method all_methods[] = new Method[all_methods_number]; + String unexpected_all_methods[] = new String[all_methods_number]; + all_methods_list.toArray(all_methods); + for (int i=0; i allmethods001: FAILED: method is NOT found: " + current_method_for_check); + not_found_methods_number++; + } + else { + print_log_on_verbose + ("--> allmethods001: PASSED for method: " + current_method_for_check); + } + } + for (int i=0; i allmethods001: FAILED: unexpected found method: " + unexpected_all_methods[i]); + } + break; + } + + out_stream.println("--> allmethods001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || allMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println("--> allmethods001: expected found methods number = " + methods_for_check_number); + out_stream.println("--> allmethods001: in fact found methods number = " + + (all_methods_number - disregarded_all_methods_number)); + out_stream.println("--> allmethods001: expected and in fact found methods number = " + + (methods_for_check_number - not_found_methods_number)); + out_stream.println + ("##> allmethods001: NOT found methods number = " + not_found_methods_number); + out_stream.println + ("##> allmethods001: UNEXPECTED found methods number = " + unexpected_found_methods_number); + } + if ( not_found_methods_number + unexpected_found_methods_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> allmethods001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> allmethods001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> allmethods001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001/TestDescription.java new file mode 100644 index 00000000000..75ee3609d46 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allMethods/allmethods001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/allMethods/allmethods001 test + * checks the allMethods() method of ReferenceType interface + * of the com.sun.jdi package : + * the ReferenceType.allMethods() method is checked for methods of + * debugee's class which extends super class and implements interface. + * Debugee's class has both hidden and overridden methods which should + * present in Method list returned by the allMethods() method.. + * Each method is checked for method name and declaring class name. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allMethods.allmethods001 + * nsk.jdi.ReferenceType.allMethods.allmethods001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allMethods.allmethods001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001a.java new file mode 100644 index 00000000000..963609fa7df --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods001a.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the allmethods001 JDI test. + */ + +public class allmethods001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + private final static String + package_prefix = "nsk.jdi.ReferenceType.allMethods."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "allmethods001aClassForCheck"; + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i allmethods001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + Class checked_class_classobj = null; + try { + checked_class_classobj = + Class.forName(checked_class_name, true, allmethods001a.class.getClassLoader()); + print_log_on_verbose + ("--> allmethods001a: checked class loaded:" + checked_class_name); + } + catch ( Throwable thrown ) { // ClassNotFoundException +// System.err.println +// ("**> allmethods001a: load class: Throwable thrown = " + thrown.toString()); + print_log_on_verbose + ("--> allmethods001a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> allmethods001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allmethods001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allmethods001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> allmethods001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> allmethods001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +abstract class allmethods001aClassForCheck extends allmethods001aSuperClassForCheck implements allmethods001aInterfaceForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods without params + static void s_void_method() {} + static boolean s_boolean_method() {return true;} + static byte s_byte_method() {return (byte)1;} + static char s_char_method() {return (char)1;} + static double s_double_method() {return (double)100.99;} + static float s_float_method() {return (float)100.88;} + static int s_int_method() {return 100;} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + // static methods with params + static void s_void_par_method(boolean z) {} + static boolean s_boolean_par_method(boolean z) {return true;} + static byte s_byte_par_method(byte b) {return (byte)1;} + static char s_char_par_method(char ch) {return (char)1;} + static double s_double_par_method(double d) {return (double)100.99;} + static float s_float_par_method(float f) {return (float)100.88;} + static int s_int_par_method(int i) {return 100;} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + // other static methods + native static Object s_native_method(Object obj); + static synchronized Object s_synchr_method(Object obj) {return new Object();} + final static Object s_final_method(Object obj) {return new Object();} + private static Object s_private_method(Object obj) {return new Object();} + protected static Object s_protected_method(Object obj) {return new Object();} + public static Object s_public_method(Object obj) {return new Object();} + + // instance methods without params + void i_void_method() {} + boolean i_boolean_method() {return true;} + byte i_byte_method() {return (byte)1;} + char i_char_method() {return (char)1;} + double i_double_method() {return (double)100.99;} + float i_float_method() {return (float)100.88;} + int i_int_method() {return 100;} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + public void i_interf_overridden_void_method() {} + public int i_interf_overridden_prim_method() {return 100;} + public Object i_interf_overridden_ref_method() {return new Object();} + + // instance methods with params + void i_void_par_method(boolean z) {} + boolean i_boolean_par_method(boolean z) {return true;} + byte i_byte_par_method(byte b) {return (byte)1;} + char i_char_par_method(char ch) {return (char)1;} + double i_double_par_method(double d) {return (double)100.99;} + float i_float_par_method(float f) {return (float)100.88;} + int i_int_par_method(int i) {return 100;} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public void i_interf_overridden_void_par_method(int i) {} + public int i_interf_overridden_prim_par_method(int i) {return 100;} + public Object i_interf_overridden_ref_par_method(Object obj) {return new Object();} + + // other instance methods + abstract Object i_abstract_method(Object obj); + native Object i_native_method(Object obj); + synchronized Object i_synchr_method(Object obj) {return new Object();} + final Object i_final_method(Object obj) {return new Object();} + private Object i_private_method(Object obj) {return new Object();} + protected Object i_protected_method(Object obj) {return new Object();} + public Object i_public_method(Object obj) {return new Object();} + + // static initializer + static {} + + +} + +abstract class allmethods001aSuperClassForCheck { + + static void s_super_void_method(long l) {} + static long s_super_prim_method(long l) {return 100;} + static Object s_super_ref_method(Object obj) {return new Object();} + + void i_super_void_method(long l) {} + long i_super_prim_method(long l) {return 100;} + Object i_super_ref_method(Object obj) {return new Object();} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public Object i_multiple_inherited_method(Object obj) {return new Object();} + +} + +interface allmethods001aInterfaceForCheck { + + void i_interf_void_method(long l); + long i_interf_prim_method(long l); + Object i_interf_ref_method(Object obj); + + void i_interf_overridden_void_method(); + int i_interf_overridden_prim_method(); + Object i_interf_overridden_ref_method(); + + void i_interf_overridden_void_par_method(int i); + int i_interf_overridden_prim_par_method(int i); + Object i_interf_overridden_ref_par_method(Object obj); + + public Object i_multiple_inherited_method(Object obj); + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002.java new file mode 100644 index 00000000000..27c6fc80138 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method allMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class allmethods002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.allMethods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "allmethods002", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "allmethods002aClassForCheck"; + + private final static String classLoaderName = package_prefix + "allmethods002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new allmethods002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ReferenceType/allMethods/allmethods002 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ReferenceType/allMethods/allmethods002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + private void print_log_anyway(String message) { + logHandler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + Debugee debugee; + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + print_log_on_verbose("==> nsk/jdi/ReferenceType/allMethods/allmethods002 test LOG:"); + print_log_on_verbose("==> test checks allMethods() method of ReferenceType interface "); + print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> allmethods002: allmethods002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> allmethods002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> allmethods002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allmethods002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> allmethods002: check ReferenceType.allMethods() method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean allMethods_method_error = false; + + while ( true ) { // test body + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> allmethods002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> allmethods002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + List all_methods_list = null; + try { + all_methods_list = refType.allMethods(); + print_log_anyway + ("##> allmethods002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + allMethods_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> allmethods002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> allmethods002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + allMethods_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || allMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> allmethods002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> allmethods002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> allmethods002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/TestDescription.java new file mode 100644 index 00000000000..33e41215d2b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allMethods/allmethods002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/allMethods/allmethods002 test + * checks the allMethods() method of ReferenceType interface + * of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.allMethods() method is called for + * this class - ClassNotPreparedException should be thrown + * in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "out_stream.println" are replaced with + * "print_log_on_verbose" and "print_log_anyway". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allMethods.allmethods002 + * nsk.jdi.ReferenceType.allMethods.allmethods002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allMethods.allmethods002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/loadclass/allmethods002aClassForCheck.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/loadclass/allmethods002aClassForCheck.java new file mode 100644 index 00000000000..f03c7101136 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002/loadclass/allmethods002aClassForCheck.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +/** + * This class is loaded by allmethods002aClassLoader . + */ + +class allmethods002aClassForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods + static void s_void_method() {} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_void_par_method(boolean z) {} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + + // instance methods + void i_void_method() {} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_void_par_method(boolean z) {} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + // static initializer + static {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002a.java new file mode 100644 index 00000000000..0ea324a2aa5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods002a.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + + +/** + * This class is used as debugee application for the allmethods002 JDI test. + */ + +public class allmethods002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String + package_prefix = "nsk.jdi.ReferenceType.allMethods."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "allmethods002aClassForCheck"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i allmethods002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + allmethods002aClassLoader customClassLoader = new allmethods002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> allmethods002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> allmethods002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> allmethods002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allmethods002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allmethods002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> allmethods002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> allmethods002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class allmethods002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public allmethods002aClassLoader(String classPath, String className) { + super(allmethods002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003.java new file mode 100644 index 00000000000..7a9f4159396 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method allMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class allmethods003 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.allMethods.", + thisClassName = package_prefix + "allmethods003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "allmethods003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new allmethods003().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/allMethods/allmethods003 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/allMethods/allmethods003 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + private static void print_log_without_verbose(String message) { + if ( ! verbose_mode ) { + out_stream.println(message); + } + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/allMethods/allmethods003 test LOG:"); + out_stream.println("--> test checks allMethods() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for UNLOADED class\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + argv = argHandler.getArguments(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> allmethods003: allmethods003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> allmethods003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + out_stream.println + ("##> allmethods003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allmethods003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> allmethods003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + out_stream.println + ("##> allmethods003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allmethods003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean allMethods_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> allmethods003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> allmethods003: getting ReferenceType object for loaded checked class..."); + out_stream.println("##> allmethods003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> allmethods003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> allmethods003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> allmethods003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + out_stream.println + ("--> allmethods003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + out_stream.println + ("--> ReferenceType.allMethods() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + out_stream.println + ("##> allmethods003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allmethods003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> allmethods003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> allmethods003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> allmethods003: check that checked class has been unloaded realy..."); + out_stream.println + ("--> allmethods003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + out_stream.println + ("--> ReferenceType.allMethods() method can NOT be checked!"); + break; + } + + out_stream.println + ("--> allmethods003: check ReferenceType.allMethods() method for unloaded class..."); + List all_methods_list = null; + try { + all_methods_list = refType.allMethods(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + out_stream.println + ("--> allmethods003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + out_stream.println + ("##> allmethods003: FAILED: unexpected Exception thrown - " + expt.toString()); + out_stream.println + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + allMethods_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || allMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> allmethods003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> allmethods003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> allmethods003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of allmethods003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TestDescription.java new file mode 100644 index 00000000000..bf5af306fa7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allMethods/allmethods003. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/allMethods/allmethods003 test + * checks the allMethods() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * allMethods() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - allmethods003b class was moved in 'loadclass' subdirectory; + * - package name was added in allmethods003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for allmethods003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allMethods.allmethods003 + * nsk.jdi.ReferenceType.allMethods.allmethods003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allMethods.allmethods003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/loadclass/allmethods003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/loadclass/allmethods003b.java new file mode 100644 index 00000000000..7bfae1c30fa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003/loadclass/allmethods003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the allMethods() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.allMethods; + +class allmethods003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003a.java new file mode 100644 index 00000000000..f8a7af6b717 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods003a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the allmethods003 JDI test. + */ + +public class allmethods003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + static String package_prefix = "nsk.jdi.ReferenceType.allMethods."; + static String checked_class_name = package_prefix + "allmethods003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> allmethods003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> allmethods003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> allmethods003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> allmethods003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> allmethods003a: checked class NOT loaded:" + checked_class_name); + // Debugger finds this fact itself + } + + print_log_on_verbose("**> allmethods003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allmethods003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allmethods003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> allmethods003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> allmethods003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> allmethods003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> allmethods003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> allmethods003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> allmethods003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> allmethods003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allmethods003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allmethods003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> allmethods003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> allmethods003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of allmethods003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004.java new file mode 100644 index 00000000000..bd654bd8585 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method allMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class allmethods004 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.allMethods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "allmethods004", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "allmethods004aInterfaceForCheck"; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new allmethods004().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/allMethods/allmethods004 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/allMethods/allmethods004 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/allMethods/allmethods004 test LOG:"); + out_stream.println("==> test checks allMethods() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for class without any methods\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> allmethods004: allmethods004a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> allmethods004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> allmethods004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> allmethods004: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> allmethods004: check ReferenceType.allMethods() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean allMethods_method_error = false; + int all_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> allmethods004: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List all_methods_list = null; + try { + all_methods_list = refType.allMethods(); + } + catch (Throwable thrown) { + out_stream.println("##> allmethods004: FAILED: ReferenceType.allMethods() throws unexpected " + + thrown); + allMethods_method_error = true; + break; + } + all_methods_number = all_methods_list.size(); + if ( all_methods_number == 0 ) { + break; + } + Method all_methods[] = new Method[all_methods_number]; + all_methods_list.toArray(all_methods); + for (int i=0; i allmethods004: FAILED: unexpected found method: " + full_checked_method_info); + } + break; + } + + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || allMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + if ( all_methods_number > 0 ) { + out_stream.println + ("##> allmethods004: UNEXPECTED all methods number = " + all_methods_number); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println + ("--> allmethods004: PASSED: returned list of methods is empty!"); + } + + print_log_on_verbose("--> allmethods004: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> allmethods004: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> allmethods004: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004/TestDescription.java new file mode 100644 index 00000000000..08b899b7ed3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allMethods/allmethods004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/allMethods/allmethods004 test + * checks the allMethods() method of ReferenceType interface + * of the com.sun.jdi package for class without any methods: + * the ReferenceType.allMethods() method is checked for + * debugee's interface which does not contain any methods. + * The test expects the returned list of methods to be empty. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allMethods.allmethods004 + * nsk.jdi.ReferenceType.allMethods.allmethods004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allMethods.allmethods004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004a.java new file mode 100644 index 00000000000..c7d94273b10 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods004a.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the allmethods004 JDI test. + */ + +public class allmethods004a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i allmethods004a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + allmethods004aClassForCheck class_for_check = new allmethods004aClassForCheck(); + + print_log_on_verbose("**> allmethods004a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> allmethods004a: \"quit\" signal recieved!"); + print_log_on_verbose("**> allmethods004a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("##> allmethods004a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("##> allmethods004a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class allmethods004aClassForCheck implements allmethods004aInterfaceForCheck { + +} + +interface allmethods004aInterfaceForCheck { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005.java new file mode 100644 index 00000000000..667cfb939e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.allMethod() + * properly returns an empty list for arrays (ArrayType) and primitive + * classes.

    + * + * Debugger part of it attempts to get a list of all methods in several + * reference types corresponding to debuggee field values, which are:
    + * primitive classes themselves, and arrays of primitive types and classes. + */ +public class allmethods005 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.allMethods.allmethods005t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 24; + // tested fields used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new allmethods005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "allmethods005t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + // check existence of inherited methods for this enum type + List l = checkedClass.allMethods(); + if (l.isEmpty()) { + complain("\t ReferenceType.allMethods() returned empty list for type: " + className); + exitStatus = Consts.TEST_FAILED; + } else { + Vector methodNames = new Vector(); + Iterator it = l.iterator(); + while (it.hasNext()) { + methodNames.add(it.next().name()); + } + + for (int i = 0; i < testedMethodNames.length; i++) { + String methodName = testedMethodNames[i]; + if (methodNames.contains(methodName)) { + display("CHECK" + (i+1) + " PASSED: " + className + " has method " + methodName); + } else { + complain("CHECK" + (i+1) + " FAILED: " + className + " does not have method " + methodName); + exitStatus = Consts.TEST_FAILED; + } + } + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006/TestDescription.java new file mode 100644 index 00000000000..59c881b5bba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/allMethods/allmethods006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for allMethods() method of ReferenceType interface. + * The test checks if this method returns all methods declared + * in java.lang.Enum for any mirrored enum type. + * The java.lang.Enum class is superclass for each enum type. + * The test checks existence of methods with following names in + * returned List: + * clone(), + * compareTo(E o), + * equals(Object o), + * getDeclaringClass(), + * hashCode(), + * name(), + * ordinal(), + * toString() + * The test consists of a debugger program (allmethods006.java) + * and debugged application (allmethods006a.java). + * Package name is nsk.jdi.ReferenceType.allMethods . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls allMethods() method for each field + * of enum type declared in allmethods006a class. + * The debugger checks if each of expected method name exists + * in returned list. The test fails if any of expected method + * names has not been met. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.allMethods.allmethods006 + * nsk.jdi.ReferenceType.allMethods.allmethods006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.allMethods.allmethods006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006a.java new file mode 100644 index 00000000000..e88f3619749 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods006a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.allMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class allmethods006a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static allmethods006Enum1 f1 = allmethods006Enum1.e2; + static allmethods006Enum2 f2 = allmethods006Enum2.e1; + static allmethods006Enum1.Enum1_ f3 = allmethods006Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(allmethods006.SIGNAL_READY); + + + //pipe.println(allmethods006.SIGNAL_GO); + receiveSignal(allmethods006.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum allmethods006Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum allmethods006Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availableStrata002/availableStrata002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availableStrata002/availableStrata002.java new file mode 100644 index 00000000000..e3082692338 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availableStrata002/availableStrata002.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/availableStrata/availableStrata002. + * VM Testbase keywords: [quick, jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that method 'com.sun.jdi.ReferenceType.availableStrata()' returns all available stratums defined for class. + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3'). Then debugger forces debuggee to load 'TestClass1' from updated class file, + * obtains ReferenceType for this class and checks up that method 'com.sun.jdi.ReferenceType.availableStrata()' returns all following stratums: + * 'Java', 'TestStratum1', 'TestStratum2', 'TestStratum3'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.availableStrata.availableStrata002.availableStrata002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.availableStrata.availableStrata002.availableStrata002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.ReferenceType.availableStrata.availableStrata002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class availableStrata002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new availableStrata002().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type1( + className, + testStratumCount, + true); + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + List expectedStratums = new ArrayList(); + expectedStratums.addAll(testStratumData.keySet()); + + check_ReferenceType_availableStrata(referenceType, expectedStratums); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001.java new file mode 100644 index 00000000000..ff5c08b2614 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.availableStrata; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.availableStrata()
    + * complies with its specification.
    + *
    + * The case for testing includes a class file with the base
    + * startum. The test checks that List returned by the method
    + * availableStrata():
    + * - contains only one String element;
    + * - the element is equal to one returned by the method
    + * ReferenceType.defaultStratum()
    + *
    + */ + +public class availablestrata001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/availableStrata/availablestrata001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new availablestrata001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.availableStrata.availablestrata001a"; + + //String mName = "nsk.jdi.ReferenceType.availableStrata"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = vm.classesByName(debuggeeName); + + testedClass = (ReferenceType) classes.get(0); + + log2("......getting List of availableStrata"); + List availableStrata = testedClass.availableStrata(); + int size = availableStrata.size(); + + log2(" checking up on size of List availableStrata; 1 is expected"); + if (size != 1) { + log3("ERROR: availableStrata.size() != 1 : " + size); + testExitCode = FAILED; + } else { + + String stratum = (String) availableStrata.get(0); + String defaultStratum = testedClass.defaultStratum(); + + log2("...... compareing stratum from the List to defaultStratum"); + if (!stratum.equals(defaultStratum)) { + log3("ERROR: stratum is not equal to defaultStratum()"); + log3(" stratum == " + stratum); + log3(" defaultStratum == " + defaultStratum); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001/TestDescription.java new file mode 100644 index 00000000000..46071c73951 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/availableStrata/availablestrata001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.availableStrata() + * complies with its spec: + * public List availableStrata() + * Return the available strata for this reference type. + * See the Location for a description of strata. + * Returns: List of java.lang.String, each representing a stratum + * The case for testing includes List containing only defaultStratum. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.availableStrata.availablestrata001; + * the debuggee program - nsk.jdi.ReferenceType.availableStrata.availablestrata001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.availableStrata.availablestrata001 + * nsk.jdi.ReferenceType.availableStrata.availablestrata001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.availableStrata.availablestrata001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001a.java new file mode 100644 index 00000000000..1675964cafc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/availableStrata/availablestrata001a.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.availableStrata; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the availablestrata001 JDI test. + */ + +public class availablestrata001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } +/* + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } +*/ + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.classLoader()
    + * complies with its spec.
    + *
    + * The case for testing includes a classLoader object for type
    + * loaded through the bootstrap class loader.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class classloader001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/classLoader/classloader001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new classloader001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private final static String packagePrefix = "nsk.jdi.ReferenceType.classLoader."; + private final static String debuggeeName = packagePrefix + "classloader001a"; + private final static String testedClassName0 = packagePrefix + "classloader001b"; + private final static String testedClassName1 = packagePrefix + "classloader001c"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + checkClassLoader (testedClassName0, false); + break; + + case 1: + checkClassLoader (testedClassName1, true); + break; + + default : + throw new JDITestRuntimeException("Wrong test case :" + i); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private void checkClassLoader (String testedClassName, boolean nullExpected) { + log2(" name of tested class : " + testedClassName); + List classes = vm.classesByName(testedClassName); + if (classes.size() != 1) { + log3("ERROR: classes.size() != 1 : " + classes.size()); + testExitCode = FAILED; + return; + } + ReferenceType testedClass = (ReferenceType) classes.get(0); + if (testedClass == null) { + log3("ERROR: testedClass == null"); + testExitCode = FAILED; + } + if (nullExpected) { + log2(" checking: testedClass.classLoader(); expected result is null"); + if (testedClass.classLoader() != null) { + log3("ERROR: method classLoader() returns not null for " + testedClass.name()); + testExitCode = FAILED; + } + } else { + log2(" checking: testedClass.classLoader(); expected result is not null"); + if (testedClass.classLoader() == null) { + log3("ERROR: method classLoader() returns null for " + testedClass.name()); + testExitCode = FAILED; + } + } + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/TestDescription.java new file mode 100644 index 00000000000..6383b112fdc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/classLoader/classloader001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.classLoader() + * complies with its spec: + * public ClassLoaderReference classLoader() + * Gets the classloader object which loaded the class corresponding to this type. + * Returns: a ClassLoaderReference which mirrors the classloader, or null + * if the class was loaded through the bootstrap class loader. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.classLoader.classloader001; + * the debuggee program - nsk.jdi.ReferenceType.classLoader.classloader001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was modified due to fix of the bug: + * 4499917 ReferenceType.classLoader() returns non-null for the bootstrap CL + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.classLoader.classloader001 + * nsk.jdi.ReferenceType.classLoader.classloader001a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass loadclass1 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.classLoader.classloader001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts} + * -Xbootclasspath/a:./bin/loadclass1" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/loadclass/classloader001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/loadclass/classloader001b.java new file mode 100644 index 00000000000..3f0a90fbdc1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/loadclass/classloader001b.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2002, 2018, 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 class will be loaded by bootstarp class loader + +package nsk.jdi.ReferenceType.classLoader; + +class classloader001b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/loadclass1/classloader001c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/loadclass1/classloader001c.java new file mode 100644 index 00000000000..8aaad149b83 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001/loadclass1/classloader001c.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2002, 2018, 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 class will be loaded by bootstrap class loader + +package nsk.jdi.ReferenceType.classLoader; + +class classloader001c {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001a.java new file mode 100644 index 00000000000..44a9a877cae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001a.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.classLoader; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * This class is used as debuggee application for the classloader001 JDI test. + */ + +public class classloader001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 2; // 1; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + private final static String packagePrefix = "nsk.jdi.ReferenceType.classLoader."; + private final static String testedClassName0 = packagePrefix + "classloader001b"; + private final static String testedClassName1 = packagePrefix + "classloader001c"; + + public static void main (String argv[]) { + + for (int i=0; i maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + ArgumentHandler argHandler = new ArgumentHandler(argv); + String checkedClassDir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + // Load class by custom class loader + ClassUnloader classUnloader = new ClassUnloader(); + try { + classUnloader.loadClass(testedClassName0, checkedClassDir); + Class loadedClass = classUnloader.getLoadedClass(); + if (loadedClass == null) { + throw new Failure("classUnloader.getLoadedClass() returned null"); + } + if (loadedClass.getClassLoader() == null) { + throw new Failure("loadedClass.getClassLoader() returned null"); + } + log1("checked class : " + loadedClass.toString() + " loaded by custom class loader"); + } catch ( Exception e ) { // ClassNotFoundException + logErr("Unexpected exception thrown while trying to load " + testedClassName0 + " : " + e); + exitCode = FAILED; + } + methodForCommunication(); + break ; + + case 1: + + Class testClass = null; + // Load class by bootstrap class loader + try { + testClass = Class.forName(testedClassName1, true, null); + if (testClass.getClassLoader() != null) { + logErr(testedClassName1 + " is not loaded by bootstrap class loader"); + exitCode = FAILED; + } + } catch (Exception e) { + logErr("Unexpected exception while trying to load " + testedClassName1 + " : " + e); + exitCode = FAILED; + } + methodForCommunication(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001.java new file mode 100644 index 00000000000..2052b5aaa3d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.classObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method classObject() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class classobj001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.classObject.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "classobj001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + + {"boolean", "primitive_type", "class"}, + {"byte" , "primitive_type", "class"}, + {"char" , "primitive_type", "class"}, + {"double" , "primitive_type", "class"}, + {"float" , "primitive_type", "class"}, + {"int" , "primitive_type", "class"}, + {"long" , "primitive_type", "class"}, + + {"java.lang.Boolean" , "reference_type", "class"}, + {"java.lang.Byte" , "reference_type", "class"}, + {"java.lang.Character", "reference_type", "class"}, + {"java.lang.Double" , "reference_type", "class"}, + {"java.lang.Float" , "reference_type", "class"}, + {"java.lang.Integer" , "reference_type", "class"}, + {"java.lang.Long" , "reference_type", "class"}, + {"java.lang.String" , "reference_type", "class"}, + {"java.lang.Object" , "reference_type", "class"}, + + {debugeeName+"$s_class", "reference_type", "class"}, // static class + {debugeeName+"$s_interf", "reference_type", "interface"}, // static interface + + {package_prefix + "package_class", "reference_type", "class"}, // class + {package_prefix + "package_interf", "reference_type", "interface"} // interface + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new classobj001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/classObject/classobj001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/classObject/classobj001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/classObject/classobj001 test LOG:"); + out_stream.println("==> test checks classObject() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for ArraType, ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> classobj001: classobj001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> classobj001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> classobj001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> classobj001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> classobj001: check ReferenceType.classObject() method for debugee's classes"); + out_stream.println + (" with help of ClassObjectReference.reflectedType() method..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int classObject_method_errors = 0; + for (int i=0; i classobj001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + String s_type = classes_for_check[i][2]; + if ( array_measure != 0 ) { // array type + s_type = "class"; + } + ClassObjectReference class_obj_ref = refType.classObject(); + ReferenceType reflected_refType = class_obj_ref.reflectedType(); + if ( ! refType.equals(reflected_refType) ) { + out_stream.println + ("##> classobj001: FAILED: source ReferenceType object is NOT equal to reflected object"); + out_stream.println + ("##> for " + s_type + ": " + className); + classObject_method_errors++; + } + else { + print_log_on_verbose + ("--> classobj001: PASSED: source ReferenceType object is equal to reflected object"); + print_log_on_verbose + ("--> for " + s_type + ": " + className); + } + } + } + out_stream.println("--> classobj001: check completed!"); + out_stream.println("--> classobj001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + out_stream.println("##> classobj001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + out_stream.println("##> classobj001: classObject() method ERRORS counter = " + + classObject_method_errors); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + classObject_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> classobj001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> classobj001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> classobj001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001/TestDescription.java new file mode 100644 index 00000000000..2eb623dea91 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/classObject/classobj001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/classObject/classobj001 test + * checks the classObject() method of ReferenceType interface + * of the com.sun.jdi package for ArraType, ClassType, InterfaceType: + * The ReferenceType.classObject() method is checked for debugee's classes + * with help of ClassObjectReference.reflectedType() method by comparing + * source ReferenceType object with reflected ReferenceType object. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.classObject.classobj001 + * nsk.jdi.ReferenceType.classObject.classobj001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.classObject.classobj001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java new file mode 100644 index 00000000000..baac6343384 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.classObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the classobj001 JDI test. + */ + +public class classobj001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + static class s_class {} + static interface s_interf {} + static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl(); + + s_class s_class0 = new s_class(), s_class1[]={s_class0}, + s_class2[][]={s_class1}; + s_interf s_interf0, s_interf1[]={s_interf0}, s_interf2[][]={s_interf1}; + + package_class package_class0 = new package_class(), + package_class1[]={package_class0}, + package_class2[][]={package_class1}; + package_interf_impl pii0 = new package_interf_impl(); + package_interf package_interf0, package_interf1[]={package_interf0}, + package_interf2[][]={package_interf1}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i classobj001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + classobj001a classobj001a_obj = new classobj001a(); + + print_log_on_verbose("**> classobj001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> classobj001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> classobj001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> classobj001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> classobj001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** simple class */ +class package_class {} + +/** simple interface */ +interface package_interf {} + +/** Class that implements simple interface */ +class package_interf_impl implements package_interf {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002.java new file mode 100644 index 00000000000..8154c448fbc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.classObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +/** + * This test checks the method classObject() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class classobj002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.classObject.", + thisClassName = package_prefix + "classobj002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "classobj002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new classobj002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/classObject/classobj002 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/classObject/classobj002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + private static void print_log_without_verbose(String message) { + if ( ! verbose_mode ) { + out_stream.println(message); + } + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/classObject/classobj002 test LOG:"); + out_stream.println("--> test checks classObject() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for UNLOADED class\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + argv = argHandler.getArguments(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> classobj002: classobj002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> classobj002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + out_stream.println + ("##> classobj002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> classobj002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> classobj002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + out_stream.println + ("##> classobj002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> classobj002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean classObject_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> classobj002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> classobj002: getting ReferenceType object for loaded checked class..."); + out_stream.println("##> classobj002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> classobj002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> classobj002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> classobj002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + out_stream.println + ("--> classobj002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + out_stream.println + ("--> ReferenceType.classObject() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + out_stream.println + ("##> classobj002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> classobj002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> classobj002: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> classobj002: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> classobj002: check that checked class has been unloaded realy..."); + out_stream.println + ("--> classobj002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + out_stream.println + ("--> ReferenceType.classObject() method can NOT be checked!"); + break; + } + + out_stream.println + ("--> classobj002: check ReferenceType.classObject() method for unloaded class..."); + ClassObjectReference class_obj_ref = null; + try { + class_obj_ref = refType.classObject(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + out_stream.println + ("--> classobj002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + out_stream.println + ("##> classobj002: FAILED: unexpected Exception thrown - " + expt.toString()); + out_stream.println + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + classObject_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || classObject_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> classobj002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> classobj002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> classobj002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of classobj002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TestDescription.java new file mode 100644 index 00000000000..ede39567c3f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/classObject/classobj002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/classObject/classobj002 test + * checks the classObject() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * classObject() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - classobj002b class was moved in 'loadclass' subdirectory; + * - package name was added in classobj002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for classobj002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.classObject.classobj002 + * nsk.jdi.ReferenceType.classObject.classobj002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.classObject.classobj002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/loadclass/classobj002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/loadclass/classobj002b.java new file mode 100644 index 00000000000..60eb6fb6b94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002/loadclass/classobj002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the classObject() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.classObject; + +class classobj002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002a.java new file mode 100644 index 00000000000..2d9b1bce94d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj002a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.classObject; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the classobj002 JDI test. + */ + +public class classobj002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.classObject."; + private final static String checked_class_name = package_prefix + "classobj002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> classobj002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> classobj002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> classobj002a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> classobj002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> classobj002a: checked class NOT loaded:" + checked_class_name); + // Debugger finds this fact itself + } + + print_log_on_verbose("**> classobj002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> classobj002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> classobj002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("##> classobj002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("##> classobj002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> classobj002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> classobj002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> classobj002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> classobj002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> classobj002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> classobj002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> classobj002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("##> classobj002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("##> classobj002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of classobj002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003.java new file mode 100644 index 00000000000..facbe38b780 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.classObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class classobj003 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ReferenceType.classObject."; + private final static String className = "classobj003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + ClassObjectReference checkedClassObject = checkedClass.classObject(); + String className = checkedClass.name(); + if (checkedClassObject == null) { + complain("ReferenceType.classObject() returned null for type: " + className); + exitStatus = Consts.TEST_FAILED; + } else if (checkedClass.equals(checkedClassObject.reflectedType())) { + display("ReferenceType.classObject() returned expected object for type: " + className); + } else { + complain("CHECK FAILED for " + className); + complain("\t ReferenceType.classObject() returned unexpected object : " + checkedClassObject.toString()); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003/TestDescription.java new file mode 100644 index 00000000000..38a811f7472 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/classObject/classobj003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test checks classObject() method of ReferenceType interface + * for mirrored enum types + * The test consists of a debugger program (classObject001.java) + * and debuggee application (classObject001a.java). + * Package name is nsk.jdi.ReferenceType.classObject . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls classObject() method for each field + * of enum type declared in isfinal002a class. + * The test fails if source ReferenceType object is not equal + * to reflected ReferenceType object. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.classObject.classobj003 + * nsk.jdi.ReferenceType.classObject.classobj003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.classObject.classobj003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003a.java new file mode 100644 index 00000000000..ab7e743d581 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj003a.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.classObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class classobj003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum2 f2 = Enum2.e2; + static Enum3 f3 = Enum3.e1; + static Enum4.Enum4_ f4 = Enum4.Enum4_.e1; + static classobj003Enum5 f5 = classobj003Enum5.e2; + static classobj003Enum6 f6 = classobj003Enum6.e1; + static classobj003Enum7 f7 = classobj003Enum7.e2; + static classobj003Enum8.Enum8_ f8 = classobj003Enum8.Enum8_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(classobj003.SIGNAL_READY); + + + //pipe.println(classobj003.SIGNAL_GO); + receiveSignal(classobj003.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + enum Enum1 { + e1, e2; + } + + enum Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); + } + + enum Enum3 implements classobj003i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); + } + + enum Enum4 { + e1, e2; + + enum Enum4_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum classobj003Enum5 { + e1, e2; +} + +enum classobj003Enum6 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} + +enum classobj003Enum7 implements classobj003i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); +} + +enum classobj003Enum8 { + e1, e2; + enum Enum8_ { + e1, e2; + } +} + +interface classobj003i { + int i = 1; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum002/defaultStratum002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum002/defaultStratum002.java new file mode 100644 index 00000000000..a113464e364 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum002/defaultStratum002.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/defaultStratum/defaultStratum002. + * VM Testbase keywords: [quick, jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that default stratum specified in class file affects result of following methods: + * - ReferenceType.defaultStratum() + * - ReferenceType.sourceName() + * - ReferenceType.allLineLocations() + * - ReferenceType.locationsOfLine(int lineNumber) + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3') and for each of this stratums following line mapping + * is defined: + * "Java" "TestStratum" + * + * 9 --> 1000, source1 + * 10 --> 1001, source1 + * ... ... + * 16 --> 1007, source1 + * sde_testMethod1 + * 20 --> 1100, source1 + * 21 --> 1101, source1 + * ... ... + * 27 --> 1107, source1 + * sde_testMethod1 + * 31 --> 1200, source1 + * 32 --> 1201, source1 + * ... ... + * 38 --> 1207, source1 + * Stratum 'TestStratum1' is specified as default for 'TestClass1'. + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that following methods: + * - ReferenceType.defaultStratum() + * - ReferenceType.sourceName() + * - ReferenceType.allLineLocations() + * - ReferenceType.locationsOfLine(int lineNumber) + * returns information for 'TestStratum1'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.defaultStratum.defaultStratum002.defaultStratum002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.defaultStratum.defaultStratum002.defaultStratum002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.ReferenceType.defaultStratum.defaultStratum002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.sde.*; + +public class defaultStratum002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new defaultStratum002().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type1( + className, + testStratumCount, + false); + /* + * Method 'prepareDefaultPatchedClassFile_Type1' creates class file with + * following line mapping: "Java" "TestStratum" + * + * + * 9 --> 1000, source1 + * 10 --> 1001, source1 + * ... + * ... + * 16 --> 1007, source1 + * + * sde_testMethod1 + * 20 --> 1100, source1 + * 21 --> 1101, source1 + * ... + * ... + * 27 --> 1107, source1 + * + * sde_testMethod1 + * 31 --> 1200, source1 + * 32 --> 1201, source1 + * ... + * ... + * 38 --> 1207, source1 + */ + + String defaultStratum = null; + + // find wich stratum was set default + // (prepareDefaultPatchedClassFile_Type1 should set default first + // not-java stratum) + for (LocationsData locationsData : testStratumData.values()) { + if (locationsData.isDefault) { + defaultStratum = locationsData.stratumName; + break; + } + } + + if (defaultStratum == null || defaultStratum.equals(javaStratumName)) { + throw new TestBug("Class file with default not-java stratum was not generated"); + } + + log.display("Default stratum for '" + className + "' is '" + defaultStratum + "'"); + log.display("Result of VirtualMachine.getDefaultStratum() is '" + vm.getDefaultStratum() + "'"); + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + String actualDefaultStratum = referenceType.defaultStratum(); + + if (!actualDefaultStratum.equals(defaultStratum)) { + setSuccess(false); + log.complain("ReferenceType.defaultStratum() returns unexpected value: " + actualDefaultStratum + + ", expected is " + defaultStratum); + } + + LocationsData locationsData = testStratumData.get(defaultStratum); + checkReferenceType( + null, + referenceType, + locationsData.sourceNames(), + locationsData.paths, + locationsData.allLocations); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum003/defaultStratum003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum003/defaultStratum003.java new file mode 100644 index 00000000000..9b2d3a8172d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum003/defaultStratum003.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/defaultStratum/defaultStratum003. + * VM Testbase keywords: [jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that default stratum specified in class file affects StepEvents generation. + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3') and for each of this stratums following line mapping + * is defined: + * "Java" "TestStratum" + * + * 9 --> 1000, source1 + * 11 --> 1002, source1 + * ... ... + * sde_testMethod1 + * 20 --> 1100, source1 + * 22 --> 1101, source1 + * ... ... + * sde_testMethod1 + * 31 --> 1200, source1 + * 33 --> 1201, source1 + * ... ... + * Stratum 'TestStratum1' is specified as default for 'TestClass1'. + * Then debugger forces debuggee to load 'TestClass1' from updated class file, starts event listener thread which saves all received StepEvents, + * enables StepEvent request(class filter is used to receive events only for 'TestClass1') and forces debuggee to execute all methods defined in 'TestClass1'. + * When all methods was executed debugger checks up that StepEvents was generated for all locations specified for 'TestStratum1'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.defaultStratum.defaultStratum003.defaultStratum003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.defaultStratum.defaultStratum003.defaultStratum003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.ReferenceType.defaultStratum.defaultStratum003; + +import java.io.*; +import java.util.*; +import com.sun.jdi.request.StepRequest; +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.EventHandler; +import nsk.share.jdi.sde.*; + +public class defaultStratum003 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new defaultStratum003().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + private EventHandler eventHandler; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type3( + className, + testStratumCount, + false); + /* + * Method 'prepareDefaultPatchedClassFile_Type3' creates class file with + * following line mapping for each test stratum: + * + * "Java" "TestStratum" + * + * + * 9 --> 1001, source1 + * 11 --> 1002, source1 + * 14 --> 1003, source1 + * 16 --> 1004, source1 + * + * sde_testMethod1 + * 20 --> 1101, source1 + * 22 --> 1102, source1 + * 24 --> 1103, source1 + * 26 --> 1104, source1 + * + * sde_testMethod2 + * 31 --> 1201, source1 + * 33 --> 1202, source1 + * 35 --> 1203, source1 + * 37 --> 1204, source1 + */ + + String defaultStratum = null; + + // find wich stratum was set default + // (prepareDefaultPatchedClassFile_Type3 should set default first + // not-java stratum) + for (LocationsData locationsData : testStratumData.values()) { + if (locationsData.isDefault) { + defaultStratum = locationsData.stratumName; + break; + } + } + + if (defaultStratum == null || defaultStratum.equals(javaStratumName)) { + throw new TestBug("Class file with default not-java stratum was not generated"); + } + + initDefaultBreakpoint(); + + // check that events are generated for default stratum + eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + StepEventListener stepEventListener = new StepEventListener(); + eventHandler.addListener(stepEventListener); + + StepRequest stepRequest = debuggee.getEventRequestManager().createStepRequest( + debuggee.threadByName(SDEDebuggee.mainThreadName), + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + + stepRequest.setSuspendPolicy(StepRequest.SUSPEND_EVENT_THREAD); + stepRequest.addClassFilter(TestClass1.class.getName()); + stepRequest.enable(); + + pipe.println(SDEDebuggee.COMMAND_EXECUTE_TEST_METHODS + ":" + className); + + if (!isDebuggeeReady()) + return; + + stepEventListener.waitBreakpointEvent(); + + compareLocations( + stepEventListener.stepLocations(), + testStratumData.get(defaultStratum).allLocations, + defaultStratum); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass1.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass1.java new file mode 100644 index 00000000000..032bd0d094c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass1.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ReferenceType.defaultStratum.defaultStratum004; + +// THIS TEST IS LINE NUMBER SENSITIVE + +// Class contains method with several locations, do not edit this file because of line numbers are hardcoded in tests +public class TestClass1 +{ + public TestClass1() + { + super(); // testStratumData::doTest()::testStratumData->at(0) + int i = 0; + i++; // testStratumData::doTest()::testStratumData->at(1) + i++; + i++; + i++; // testStratumData::doTest()::testStratumData->at(2) + i++; + } // testStratumData::doTest()::testStratumData->at(3) +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass2.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass2.java new file mode 100644 index 00000000000..3586101ef00 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass2.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ReferenceType.defaultStratum.defaultStratum004; + +// THIS TEST IS LINE NUMBER SENSITIVE + +// Class contains method with several locations, do not edit this file because of line numbers are hardcoded in tests +public class TestClass2 +{ + public TestClass2() + { + super(); // testStratumData::doTest()::testStratumData->at(0) + int i = 0; // testStratumData::doTest()::testStratumData->at(1) + i++; // testStratumData::doTest()::testStratumData->at(2) + i++; // testStratumData::doTest()::testStratumData->at(3) + i++; // testStratumData::doTest()::testStratumData->at(4) + i++; // testStratumData::doTest()::testStratumData->at(5) + i++; // testStratumData::doTest()::testStratumData->at(6) + } // testStratumData::doTest()::testStratumData->at(7) +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass3.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass3.java new file mode 100644 index 00000000000..32c7e31bf15 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/TestClass3.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ReferenceType.defaultStratum.defaultStratum004; + +// THIS TEST IS LINE NUMBER SENSITIVE + +// Class contains method with several locations, do not edit this file because of line numbers are hardcoded in tests +public class TestClass3 +{ + public TestClass3() + { + super(); // testStratumData::doTest()::testStratumData->at(0) + int i = 0; + i++; + i++; + i++; + i++; + i++; + } // testStratumData::doTest()::testStratumData->at(1) +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/defaultStratum004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/defaultStratum004.java new file mode 100644 index 00000000000..9c49323d794 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/defaultStratum004.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/defaultStratum/defaultStratum004. + * VM Testbase keywords: [jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test scenario: + * Debugger creates copies of 3 class files for classes defined in test's package: 'TestClass1'-'TestClass3'. + * SourceDebugExtension attribute is added for all this classes, for all classes different line mapping is defined + * add different default stratums are specified. + * Then debugger forces debuggee to load 'TestClass1'-'TestClass3' from updated class files and starts event listener thread which saves all received StepEvents. + * Then for TestedClass in 'TestClass1'-'TestClass3': + * - enables StepEvent request(class filter is used to receive events only for TestedClass) + * - forces debuggee to execute constructor of TestedClass + * - when constructor was executed debugger checks up that StepEvents was generated for all locations specified for stratum specified as default in TestedClass + * done + * Described event generation is performed 3 times. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.defaultStratum.defaultStratum004.defaultStratum004 + * nsk.jdi.ReferenceType.defaultStratum.defaultStratum004.defaultStratum004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.defaultStratum.defaultStratum004.defaultStratum004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + */ + +package nsk.jdi.ReferenceType.defaultStratum.defaultStratum004; + +import java.io.*; +import java.util.*; +import com.sun.jdi.request.StepRequest; +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.EventHandler; +import nsk.share.jdi.sde.*; + +public class defaultStratum004 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new defaultStratum004().runIt(argv, out); + } + + protected String debuggeeClassName() { + if (classpath == null) { + throw new TestBug("Debugger requires 'testClassPath' parameter"); + } + + return defaultStratum004a.class.getName() + " -testClassPath " + testWorkDir; + } + + private EventHandler eventHandler; + + protected List preparePatchedClassFile(String className, String stratumName, String sourceName, + String sourcePath, List testStratumData) { + String smapFileName = "TestSMAP.smap"; + SmapGenerator smapGenerator = new SmapGenerator(); + + SmapStratum smapStratum = new SmapStratum(stratumName); + + smapStratum.addFile(sourceName, sourcePath); + + for (DebugLocation debugLocation : testStratumData) { + smapStratum.addLineData(debugLocation.inputLine, sourceName, 1, debugLocation.outputLine, 1); + } + + // set as default stratum + smapGenerator.addStratum(smapStratum, true); + + savePathcedClassFile(className, smapGenerator, smapFileName); + + return testStratumData; + } + + Map> classLocations = new TreeMap>(); + + public void doTest() { + String sourceName = testStratumSourceName; + String sourcePath = testStratumSourcePath; + String methodName = ""; + + String className = TestClass1.class.getName(); + String stratumName = className + "_Stratum"; + List testStratumData = new ArrayList(); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1001, 32)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1002, 34)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1003, 37)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1004, 39)); + preparePatchedClassFile(className, stratumName, sourceName, sourcePath, testStratumData); + classLocations.put(className, testStratumData); + + className = TestClass2.class.getName(); + stratumName = className + "_Stratum"; + testStratumData = new ArrayList(); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1001, 32)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1002, 33)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1003, 34)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1004, 35)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1005, 36)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1006, 37)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1007, 38)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1008, 39)); + preparePatchedClassFile(className, stratumName, sourceName, sourcePath, testStratumData); + classLocations.put(className, testStratumData); + + className = TestClass3.class.getName(); + stratumName = className + "_Stratum"; + testStratumData = new ArrayList(); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1001, 32)); + testStratumData.add(new DebugLocation(sourceName, sourcePath, methodName, 1008, 39)); + preparePatchedClassFile(className, stratumName, sourceName, sourcePath, testStratumData); + classLocations.put(className, testStratumData); + + initDefaultBreakpoint(); + + String command = defaultStratum004a.COMMAND_LOAD_TEST_CLASSES + ":" + TestClass1.class.getName() + " " + + TestClass2.class.getName() + " " + TestClass3.class.getName(); + + pipe.println(command); + + if (!isDebuggeeReady()) + return; + + eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + StepEventListener stepEventListener = new StepEventListener(); + eventHandler.addListener(stepEventListener); + + // perform step events generation 3 times + for (int i = 0; i < 3; i++) { + for (String testedClassName : classLocations.keySet()) { + StepRequest stepRequest = debuggee.getEventRequestManager().createStepRequest( + debuggee.threadByName(SDEDebuggee.mainThreadName), + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + + stepRequest.addClassFilter(testedClassName); + stepRequest.setSuspendPolicy(StepRequest.SUSPEND_EVENT_THREAD); + stepRequest.enable(); + + stepEventListener.clearLocations(); + + pipe.println(defaultStratum004a.COMMAND_INSTANTIATE_TEST_CLASS + ":" + testedClassName); + + if (!isDebuggeeReady()) + return; + + stepEventListener.waitBreakpointEvent(); + + compareLocations( + stepEventListener.stepLocations(), + classLocations.get(testedClassName), + testedClassName + "_Stratum"); + + stepRequest.disable(); + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/defaultStratum004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/defaultStratum004a.java new file mode 100644 index 00000000000..e6b243a7dd3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum004/defaultStratum004a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ReferenceType.defaultStratum.defaultStratum004; + +import java.util.*; +import nsk.share.TestBug; +import nsk.share.jdi.sde.SDEDebuggee; + +public class defaultStratum004a extends SDEDebuggee { + public static void main(String[] args) { + new defaultStratum004a().doTest(args); + } + + // command:class_name class_name ... + public static final String COMMAND_LOAD_TEST_CLASSES = "loadTestClasses"; + + // command:class_name + public static final String COMMAND_INSTANTIATE_TEST_CLASS = "instantiateTestClasses"; + + List testClasses = new ArrayList(); + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.startsWith(COMMAND_LOAD_TEST_CLASSES)) { + String classNamesString[] = command.split(":"); + + if ((classNamesString.length != 2) || (classNamesString[1].length() == 0)) + throw new TestBug("Invalid command format, class names was not specified"); + + String classNames[] = classNamesString[1].split(" "); + + if (classNames.length == 0) + throw new TestBug("Class names was not specified"); + + loadTestClasses(classNames); + + return true; + } else if (command.startsWith(COMMAND_INSTANTIATE_TEST_CLASS)) { + String classNamesString[] = command.split(":"); + + if ((classNamesString.length == 0) || (classNamesString[1].length() == 0)) + throw new TestBug("Class name was not specified"); + + instantiateTestClass(classNamesString[1]); + breakpointMethod(); + + return true; + } + + return false; + } + + public void loadTestClasses(String classNames[]) { + TestClassLoader classLoader = new TestClassLoader(); + classLoader.setClassPath(classpath); + + try { + for (String className : classNames) { + Class klass = classLoader.loadClass(className); + testClasses.add(klass); + + log.display("Class '" + klass.getName() + "' was loaded"); + } + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + + throw new TestBug("Unexpected exception: " + e); + } + } + + public void instantiateTestClass(String className) { + for (Class klass : testClasses) { + if (klass.getName().equals(className)) { + try { + log.display("Create instance of '" + klass.getName() + "'"); + klass.newInstance(); + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + + throw new TestBug("Unexpected exception: " + e); + } + + return; + } + } + + throw new TestBug("Class '" + className + "' was not loaded"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001.java new file mode 100644 index 00000000000..68be4efc6d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.defaultStratum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.defaultStratum()
    + * complies with its specification.
    + *
    + * The case for testing includes a class file with the base
    + * startum. The test checks that String returned by the method
    + * ReferenceType.defaultStratum() is "Java".
    + *
    + */ + +public class defaultstratum001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/defaultStratum/defaultstratum001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new defaultstratum001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.defaultStratum.defaultstratum001a"; + + //String mName = "nsk.jdi.ReferenceType.defaultStratum"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List classes = vm.classesByName(debuggeeName); + + testedClass = (ReferenceType) classes.get(0); + + String defaultStratum = testedClass.defaultStratum(); + + log2("...... compareing defaultStratum to 'Java'"); + if (!defaultStratum.equals("Java")) { + log3("ERROR: defaultStratum is not equal to 'Java'"); + log3(" defaultStratum == " + defaultStratum); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001/TestDescription.java new file mode 100644 index 00000000000..fbfdf9f77e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/defaultStratum/defaultstratum001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.defaultStratum() + * complies with its spec: + * public String defaultStratum() + * Returns the default stratum for this reference type. + * This value is specified in the class file and cannot be set by the user. + * If the class file does not specify a default stratum the base stratum + * ("Java") will be returned. + * See the Location for a description of strata. + * The case for testing includes only a class file with the base stratum. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.defaultStratum.defaultstratum001; + * the debuggee program - nsk.jdi.ReferenceType.defaultStratum.defaultstratum001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.defaultStratum.defaultstratum001 + * nsk.jdi.ReferenceType.defaultStratum.defaultstratum001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.defaultStratum.defaultstratum001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001a.java new file mode 100644 index 00000000000..d93c6883171 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultstratum001a.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.defaultStratum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the defaultstratum001 JDI test. + */ + +public class defaultstratum001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } +/* + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } +*/ + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; iequals() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class equals001 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.equals.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "equals001", + debugeeName = thisClassName + "a"; + + private final static String primitive_type_sign = "aprimitive_type"; + private final static String reference_type_sign = "areference_type"; + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + {"boolean", primitive_type_sign}, + {"byte" , primitive_type_sign}, + {"char" , primitive_type_sign}, + {"double" , primitive_type_sign}, + {"float" , primitive_type_sign}, + {"int" , primitive_type_sign}, + {"long" , primitive_type_sign}, + + {"java.lang.Boolean" , reference_type_sign}, + {"java.lang.Byte" , reference_type_sign}, + {"java.lang.Character", reference_type_sign}, + {"java.lang.Double" , reference_type_sign}, + {"java.lang.Float" , reference_type_sign}, + {"java.lang.Integer" , reference_type_sign}, + {"java.lang.Long" , reference_type_sign}, + {"java.lang.String" , reference_type_sign}, + {"java.lang.Object" , reference_type_sign}, + + {package_prefix + "ClassForCheck", reference_type_sign}, + {package_prefix + "InterfaceForCheck", reference_type_sign}, + + {debugeeName+"$s_class", reference_type_sign}, + {debugeeName+"$s_interf", reference_type_sign} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new equals001().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/equals/equals001 test FAILED"); + } + else { + print_log_anyway("\n==> nsk/jdi/ReferenceType/equals/equals001 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/equals/equals001 test LOG:"); + print_log_anyway("==> test checks the equals() method of ReferenceType interface"); + print_log_anyway(" of the com.sun.jdi package for ArrayType, ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> equals001: equals001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway("##> equals001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway("##> equals001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> equals001: debugee's \"ready\" signal recieved!"); + } + + print_log_anyway + ("--> equals001: checking debugee's classes by ReferenceType.equals() method..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int equals_method_errors_for_equal_objects = 0; + int equals_method_errors_for_unequal_objects = 0; + ReferenceType unequal_refType = null; + for (int i=0; i equals001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + ReferenceType refType_2 = debugee.classByName(className); + if ( ! refType_1.equals(refType_2) ) { + print_log_anyway("##> equals001: FAILED: refType_1.equals(refType_2) returned FALSE"); + print_log_anyway("##> refType_1 = " + refType_1); + print_log_anyway("##> refType_2 = " + refType_2); + equals_method_errors_for_equal_objects++; + } + else { + + print_log_on_verbose("--> equals001: PASSED: refType_1.equals(refType_2) returned TRUE"); + print_log_on_verbose("--> refType_1 = " + refType_1); + print_log_on_verbose("--> refType_2 = " + refType_2); + + } + boolean is_equal = true; + String unequal_refType_str = null; + if ( unequal_refType == null ) { + Object object_for_compare = new Object(); + is_equal = refType_1.equals(object_for_compare); + unequal_refType_str = object_for_compare.toString(); + } + else { + is_equal = refType_1.equals(unequal_refType); + unequal_refType_str = unequal_refType.toString(); + } + if ( is_equal ) { + print_log_anyway("##> equals001: FAILED: refType_1.equals(unequal_refType) returned TRUE"); + print_log_anyway("##> refType_1 = " + refType_1); + print_log_anyway("##> unequal_refType = " + unequal_refType_str); + equals_method_errors_for_unequal_objects++; + } + else { + + print_log_on_verbose("--> equals001: PASSED: refType_1.equals(unequal_refType) returned FALSE"); + print_log_on_verbose("--> refType_1 = " + refType_1); + print_log_on_verbose("--> unequal_refType = " + unequal_refType_str); + + } + unequal_refType = refType_1; + } + } + print_log_anyway("--> equals001: checking debugee's classes completed!"); + print_log_anyway("--> equals001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + print_log_anyway("##> equals001: \"class not found ERRORS\" number = " + + class_not_found_errors); + } + print_log_anyway("##> equals001: errors number of equals() method for equal objects = " + + equals_method_errors_for_equal_objects); + print_log_anyway("##> equals001: errors number of equals() method for unequal objects = " + + equals_method_errors_for_unequal_objects); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + equals_method_errors_for_equal_objects + + equals_method_errors_for_unequal_objects > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> equals001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway("##> equals001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> equals001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..6a224401634 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/equals/equals001 test + * checks the equals() method of ReferenceType interface + * of the com.sun.jdi package for ArrayType, ClassType, InterfaceType: + * For each checked debugee's class the test gets two ReferenceType + * instances for this class and compares these ReferenceType instances + * by equals() method - true is expected to be return. + * Then the test compares two ReferenceType instances for different + * debugee's classes - false is expected to be return. + * Also the test compares ReferenceType instance with Object instance + * - false is expected to be return. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.equals.equals001 + * nsk.jdi.ReferenceType.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java new file mode 100644 index 00000000000..bc74f002d8c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the equals001 JDI test. + */ + +public class equals001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + static class s_class {} + s_class s_class_0 = new s_class(), s_class_1[]={s_class_0}, + s_class_2[][]={s_class_1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + static interface s_interf {} + static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl(); + s_interf s_interf_0, s_interf_1[]={s_interf_0}, s_interf_2[][]={s_interf_1}; + + ClassForCheck class_for_check0 = new ClassForCheck(), + class_for_check1[]={class_for_check0}, + class_for_check2[][]={class_for_check1}; + InterfaceForCheck_impl interf_for_check_impl0 = new InterfaceForCheck_impl(); + InterfaceForCheck interf_for_check0, + interf_for_check1[]={interf_for_check0}, + interf_for_check2[][]={interf_for_check1}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i equals001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + equals001a equals001a_obj = new equals001a(); + + print_log_on_verbose("**> equals001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> equals001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> equals001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> equals001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> equals001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class ClassForCheck { + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + static long[] s_prim_array_field; + static Object[] s_ref_array_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + long[] i_prim_array_field; + Object[] i_ref_array_field; +} + +interface InterfaceForCheck { + static final boolean s_interf_boolean_field = true; + static final byte s_interf_byte_field = (byte)1; + static final char s_interf_char_field = '1'; + static final double s_interf_double_field = 999; + static final float s_interf_float_field = 99; + static final int s_interf_int_field = 100; + static final long s_interf_long_field = 1000; + static final Object s_interf_object_field = new Object(); +} + +class InterfaceForCheck_impl implements InterfaceForCheck {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002.java new file mode 100644 index 00000000000..1e210565466 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method equals() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class equals002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.equals.", + thisClassName = package_prefix + "equals002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "equals002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new equals002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/equals/equals002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/equals/equals002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/equals/equals002 test LOG:"); + print_log_anyway("--> test checks equals() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> equals002: equals002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> equals002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> equals002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> equals002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> equals002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> equals002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> equals002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean equals_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> equals002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> equals002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> equals002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> equals002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> equals002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> equals002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> equals002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.equals() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> equals002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> equals002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> equals002: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> equals002: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> equals002: check that checked class has been unloaded realy..."); + print_log_anyway + ("--> equals002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.equals() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> equals002: check ReferenceType.equals() method for unloaded class..."); + boolean equals_sign = false; + try { + equals_sign = refType.equals(refType); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> equals002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> equals002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + equals_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || equals_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> equals002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> equals002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> equals002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of equals002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..278ce65f282 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/equals/equals002. + * VM Testbase keywords: [diehard, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/equals/equals002 test + * checks the equals() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * equals() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - equals002b class was moved in 'loadclass' subdirectory; + * - package name was added in equals002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for equals002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.equals.equals002 + * nsk.jdi.ReferenceType.equals.equals002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/loadclass/equals002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/loadclass/equals002b.java new file mode 100644 index 00000000000..ee2fbb03967 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002/loadclass/equals002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the equals() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.equals; + +class equals002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002a.java new file mode 100644 index 00000000000..0fc1f3a2818 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.equals; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the equals002 JDI test. + */ + +public class equals002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.equals."; + private final static String checked_class_name = package_prefix + "equals002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> equals002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> equals002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> equals002a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> equals002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> equals002a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> equals002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> equals002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> equals002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> equals002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> equals002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> equals002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> equals002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> equals002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> equals002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> equals002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> equals002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> equals002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> equals002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> equals002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of equals002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001.java new file mode 100644 index 00000000000..e35a80b9db3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.failedToInitialize; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method failedToInitialize() + * of the JDI interface ReferenceType of com.sun.jdi package + * for ClassType, InterfaceType + */ + +public class failedToInitialize001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.failedToInitialize.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "failedToInitialize001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + + {thisClassName, "no failed init", "class"}, + {thisClassName+"a", "no failed init", "class"}, + + {package_prefix + "fail_init_class", "failed init", "class"}, + + {package_prefix + "interf", "no failed init", "interface"}, + + {package_prefix + "fail_init_interf", "failed init", "interface"}, + + {package_prefix + "fail_init_subcl", "failed init", "class"} + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new failedToInitialize001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001 test LOG:"); + out_stream.println("==> test checks failedToInitialize() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> failedToInitialize001: failedToInitialize001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> failedToInitialize001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> failedToInitialize001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> failedToInitialize001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> failedToInitialize001: checking debugee's classes by ReferenceType.failedToInitialize() method..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int failedToInitialize_method_errors = 0; + for (int i=0; i failedToInitialize001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + String s_failed_sign = classes_for_check[i][1]; + String s_type = classes_for_check[i][2]; + boolean failedToInitialize = s_failed_sign.equals("failed init"); + if (refType.failedToInitialize() != failedToInitialize) { + out_stream.println("##> failedToInitialize001: UNEXPECTED failedToInitialize() method result (" + + !failedToInitialize + ") for " + s_type + ": " + + className + "(" + s_failed_sign + ")"); + failedToInitialize_method_errors++; + } + else { + print_log_on_verbose("--> failedToInitialize001: expected failedToInitialize() method result (" + + failedToInitialize + ") for " + s_type + ": " + + className + "(" + s_failed_sign + ")"); + } + } + out_stream.println("--> failedToInitialize001: checking debugee's classes completed!"); + out_stream.println("--> failedToInitialize001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + out_stream.println("##> failedToInitialize001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + out_stream.println("##> failedToInitialize001: failedToInitialize() method ERRORS counter = " + + failedToInitialize_method_errors); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + failedToInitialize_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> failedToInitialize001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> failedToInitialize001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> failedToInitialize001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001/TestDescription.java new file mode 100644 index 00000000000..8a59348a7a6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001 test + * checks the failedToInitialize() method of ReferenceType interface + * of the com.sun.jdi package for ClassType, InterfaceType. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.failedToInitialize.failedToInitialize001 + * nsk.jdi.ReferenceType.failedToInitialize.failedToInitialize001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.failedToInitialize.failedToInitialize001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001a.java new file mode 100644 index 00000000000..f8c801e881c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedToInitialize001a.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.failedToInitialize; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the failedToInitialize001 JDI test. + */ + +public class failedToInitialize001a { + + static boolean verbose_mode = false; + + failedToInitialize001 a001_0=new failedToInitialize001(); + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + interf_impl interf_impl_0 = new interf_impl(); + interf interf_0, interf_1[]={interf_0}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i failedToInitialize001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + failedToInitialize001a failedToInitialize001a_obj = new failedToInitialize001a(); + try { + fail_init_class fail_init_class_var = new fail_init_class(); + System.err.println + ("!!**> failedToInitialize001a: FAILED - NO ExceptionInInitializerError (fail_init_class)!"); + pipe.println("failedToInitialize001a FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + catch (ExceptionInInitializerError e) { + print_log_on_verbose + ("**> failedToInitialize001a: ExceptionInInitializerError caught (fail_init_class)!"); + } + + try { + fail_init_subcl fail_init_subcl_var = new fail_init_subcl(); + System.err.println + ("!!**> failedToInitialize001a: FAILED - NO ExceptionInInitializerError (fail_init_subcl)!"); + pipe.println("failedToInitialize001a FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + catch (ExceptionInInitializerError e) { + print_log_on_verbose + ("**> failedToInitialize001a: ExceptionInInitializerError caught (fail_init_subcl)!"); + } + + print_log_on_verbose("**> failedToInitialize001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> failedToInitialize001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> failedToInitialize001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> failedToInitialize001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> failedToInitialize001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** failed to initialize class */ +class fail_init_class { + + static { + int int_var = 1/0; + } + +} + +/** interface */ +interface interf {} + +class interf_impl implements interf {} + +/** failed to initialize interface */ +interface fail_init_interf { + static final int int_var = 1/0; +} + +/** failed to initialize subclass */ +class fail_init_subcl implements fail_init_interf { + static int my_int_var = int_var; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002.java new file mode 100644 index 00000000000..0d0726e5686 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.failedToInitialize; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +/** + * This test checks the method failedToInitialize() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class failedtoinit002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class failedToInitializes of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.failedToInitialize.", + thisClassName = package_prefix + "failedtoinit002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "failedtoinit002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new failedtoinit002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002 test LOG:"); + print_log_anyway("--> test checks failedToInitialize() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> failedtoinit002: failedtoinit002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> failedtoinit002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> failedtoinit002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> failedtoinit002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> failedtoinit002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> failedtoinit002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> failedtoinit002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean failedToInitialize_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> failedtoinit002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> failedtoinit002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> failedtoinit002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> failedtoinit002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> failedtoinit002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> failedtoinit002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> failedtoinit002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.failedToInitialize() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> failedtoinit002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> failedtoinit002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> failedtoinit002: check that checked class has been unloaded really..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> failedtoinit002: checked class has been unloaded really: " + checked_class); + } + else { + print_log_without_verbose + ("--> failedtoinit002: check that checked class has been unloaded really..."); + print_log_anyway + ("--> failedtoinit002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.failedToInitialize() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> failedtoinit002: check ReferenceType.failedToInitialize() method for unloaded class..."); + boolean ref_type_failed_to_initialize = true; + try { + ref_type_failed_to_initialize = refType.failedToInitialize(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> failedtoinit002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> failedtoinit002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + failedToInitialize_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || failedToInitialize_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> failedtoinit002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> failedtoinit002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> failedtoinit002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of failedtoinit002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TestDescription.java new file mode 100644 index 00000000000..b28533b7d39 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002 test + * checks the failedToInitialize() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * failedToInitialize() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - failedtoinit002b class was moved in 'loadclass' subdirectory; + * - package name was added in failedtoinit002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for failedtoinit002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.failedToInitialize.failedtoinit002 + * nsk.jdi.ReferenceType.failedToInitialize.failedtoinit002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.failedToInitialize.failedtoinit002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/loadclass/failedtoinit002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/loadclass/failedtoinit002b.java new file mode 100644 index 00000000000..91898de306d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002/loadclass/failedtoinit002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the failedToInitialize() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.failedToInitialize; + +class failedtoinit002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002a.java new file mode 100644 index 00000000000..cbd88e24236 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/failedToInitialize/failedtoinit002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.failedToInitialize; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the failedtoinit002 JDI test. + */ + +public class failedtoinit002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.failedToInitialize."; + private final static String checked_class_name = package_prefix + "failedtoinit002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> failedtoinit002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> failedtoinit002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> failedtoinit002a: checked class loaded: " + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> failedtoinit002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> failedtoinit002a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> failedtoinit002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> failedtoinit002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> failedtoinit002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> failedtoinit002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> failedtoinit002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> failedtoinit002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> failedtoinit002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> failedtoinit002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> failedtoinit002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> failedtoinit002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> failedtoinit002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> failedtoinit002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> failedtoinit002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> failedtoinit002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of failedtoinit002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001.java new file mode 100644 index 00000000000..b037ae45de0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001.java @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fieldByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method fieldByName() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class fieldbyname001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.fieldByName.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "fieldbyname001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "fieldbyname001aClassForCheck"; + private final static String super_class_for_check = package_prefix + "fieldbyname001aSuperClassForCheck"; + private final static String interf_for_check = package_prefix + "fieldbyname001aInterfaceForCheck"; + private final static String ambiguous_class = "ambiguous_class"; + private final static String not_existing_class = "not_existing_class"; + private static String fields_for_check[][] = { + +// field name type name static declaring class + + {"s_boolean_field", "boolean", " static", class_for_check, }, + {"s_byte_field", "byte", " static", class_for_check, }, + {"s_char_field", "char", " static", class_for_check, }, + {"s_double_field", "double", " static", class_for_check, }, + {"s_float_field", "float", " static", class_for_check, }, + {"s_int_field", "int", " static", class_for_check, }, + {"s_long_field", "long", " static", class_for_check, }, + {"s_object_field", "java.lang.Object", " static", class_for_check, }, + {"s_prim_array_field", "long[]", " static", class_for_check, }, + {"s_ref_array_field", "java.lang.Object[]", " static", class_for_check, }, + {"i_boolean_field", "boolean", "", class_for_check, }, + {"i_byte_field", "byte", "", class_for_check, }, + {"i_char_field", "char", "", class_for_check, }, + {"i_double_field", "double", "", class_for_check, }, + {"i_float_field", "float", "", class_for_check, }, + {"i_int_field", "int", "", class_for_check, }, + {"i_long_field", "long", "", class_for_check, }, + {"i_object_field", "java.lang.Object", "", class_for_check, }, + {"i_prim_array_field", "long[]", "", class_for_check, }, + {"i_ref_array_field", "java.lang.Object[]", "", class_for_check, }, + {"s_super_hidden_prim_field", "long", " static", class_for_check, }, + {"s_super_hidden_ref_field", "java.lang.Object", " static", class_for_check, }, + {"i_super_hidden_prim_field", "long", " static", class_for_check, }, + {"i_super_hidden_ref_field", "java.lang.Object", " static", class_for_check, }, + {"s_interf_hidden_prim_field", "long", " static", class_for_check, }, + {"s_interf_hidden_ref_field", "java.lang.Object", " static", class_for_check, }, + {"s_super_boolean_field", "boolean", " static", super_class_for_check }, + {"s_super_byte_field", "byte", " static", super_class_for_check }, + {"s_super_char_field", "char", " static", super_class_for_check }, + {"s_super_double_field", "double", " static", super_class_for_check }, + {"s_super_float_field", "float", " static", super_class_for_check }, + {"s_super_int_field", "int", " static", super_class_for_check }, + {"s_super_long_field", "long", " static", super_class_for_check }, + {"s_super_object_field", "java.lang.Object", " static", super_class_for_check }, + {"i_super_boolean_field", "boolean", "", super_class_for_check }, + {"i_super_byte_field", "byte", "", super_class_for_check }, + {"i_super_char_field", "char", "", super_class_for_check }, + {"i_super_double_field", "double", "", super_class_for_check }, + {"i_super_float_field", "float", "", super_class_for_check }, + {"i_super_int_field", "int", "", super_class_for_check }, + {"i_super_long_field", "long", "", super_class_for_check }, + {"i_super_object_field", "java.lang.Object", "", super_class_for_check }, + {"s_interf_boolean_field", "boolean", " static", interf_for_check, }, + {"s_interf_byte_field", "byte", " static", interf_for_check, }, + {"s_interf_char_field", "char", " static", interf_for_check, }, + {"s_interf_double_field", "double", " static", interf_for_check, }, + {"s_interf_float_field", "float", " static", interf_for_check, }, + {"s_interf_int_field", "int", " static", interf_for_check, }, + {"s_interf_long_field", "long", " static", interf_for_check, }, + {"s_interf_object_field", "java.lang.Object", " static", interf_for_check, }, + {"ambiguous_prim_field", "long", " static", ambiguous_class, }, + {"ambiguous_ref_field", "java.lang.Object", " static", ambiguous_class, }, + {"non_existing_field", "not_defined_type", "non_def", not_existing_class, } + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new fieldbyname001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/fieldByName/fieldbyname001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/fieldByName/fieldbyname001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/fieldByName/fieldbyname001 test LOG:"); + out_stream.println("==> test checks fieldByName(...) method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> fieldbyname001: fieldbyname001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> fieldbyname001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> fieldbyname001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fieldbyname001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> fieldbyname001: check ReferenceType.fieldByName(...) method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + int fields_for_check_number = fields_for_check.length; + int fieldByName_exceptions = 0; + int not_found_fields_number = 0; + int unexpected_found_fields_number = 0; + int not_corresponded_fields_number = 0; + int all_field_errors_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> fieldbyname001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + for (int i=0; i fieldbyname001: FAILED: fieldByName() throws unexpected " + + thrown); + out_stream.println("##> requested field: " + current_field_for_check); + fieldByName_exceptions++; + all_field_errors_number++; + continue; + } + if ( field_by_name == null ) { + if ( existing_field ) { + out_stream.println("##> fieldbyname001: FAILED: fieldByName() returned null!"); + out_stream.println("##> requested field: " + current_field_for_check); + not_found_fields_number++; + all_field_errors_number++; + } + else { + print_log_on_verbose + ("--> fieldbyname001: PASSED for field: " + current_field_for_check); + print_log_on_verbose + ("--> expected result: null Field"); + } + continue; + } + String field_by_name_name = field_by_name.name(); + String field_by_name_typename = field_by_name.typeName(); + String field_by_name_static; + if ( field_by_name.isStatic() ) { + field_by_name_static = " static"; + } + else { + field_by_name_static = ""; + } + String declaring_class_name = "declaring class NOT defined"; + try { + declaring_class_name = field_by_name.declaringType().name(); + } + catch (Throwable thrown) { + } + String full_field_by_name = field_by_name_static + + " " + field_by_name_typename + " " + field_by_name_name + + " (" + declaring_class_name + ")"; + if ( ! existing_field ) { + out_stream.println("##> fieldbyname001: FAILED: fieldByName() returned unexpected field: " + + full_field_by_name); + out_stream.println("##> requested field: " + current_field_for_check); + out_stream.println("##> expected result: null Field"); + unexpected_found_fields_number++; + all_field_errors_number++; + continue; + } + if ( (field_by_name_name.equals(fields_for_check[i][0])) + && (field_by_name_typename.equals(fields_for_check[i][1])) + && (field_by_name_static.equals(fields_for_check[i][2])) + && (declaring_class_name.equals(fields_for_check[i][3])) ) { + print_log_on_verbose + ("--> fieldbyname001: PASSED for field: " + current_field_for_check); + } + else { + out_stream.println + ("##> fieldbyname001: FAILED: fieldByName() returned field not corresponded to requested field!"); + out_stream.println + ("##> returned field: " + full_field_by_name); + out_stream.println + ("##> requested field: " + current_field_for_check); + not_corresponded_fields_number++; + all_field_errors_number++; + } + } + break; + } + + out_stream.println("--> fieldbyname001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println + ("--> fieldbyname001: number of checked fields = " + fields_for_check_number); + if ( fieldByName_exceptions > 0 ) { + out_stream.println + ("--> fieldbyname001: number of unexpected exceptions thrown by fieldByName() = " + + fieldByName_exceptions); + } + if ( not_found_fields_number > 0 ) { + out_stream.println + ("--> fieldbyname001: number of fields not found by fieldByName() (null returned) = " + + not_found_fields_number); + } + if ( unexpected_found_fields_number > 0 ) { + out_stream.println + ("--> fieldbyname001: number of unexpected fields found by fieldByName() (not null returned) = " + + unexpected_found_fields_number); + } + if ( not_corresponded_fields_number > 0 ) { + out_stream.println + ("--> fieldbyname001: number of returned by fieldByName() fields not corresponded to requested field = " + + not_corresponded_fields_number); + } + out_stream.println + ("--> fieldbyname001: number of fields for which fieldByName() returned expected result = " + + (fields_for_check_number - all_field_errors_number)); + } + if ( all_field_errors_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> fieldbyname001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> fieldbyname001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> fieldbyname001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001/TestDescription.java new file mode 100644 index 00000000000..4e96ca54cb9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/fieldByName/fieldbyname001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/fieldByName/fieldbyname001 test + * checks the fieldByName(...) method of ReferenceType interface + * of the com.sun.jdi package : + * the ReferenceType.fieldByName(...) method is checked for fields of + * debugee's class which extends super class and implements interface. + * Debugee's classes have both hidden and ambiguous fields which should + * be not found by the fieldByName(...) method. + * Each visible field is checked for field name, field type, + * static modifier and declaring class. + * Also fieldByName(...) method is checked for nonexisting field - null + * Field should be returned. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.fieldByName.fieldbyname001 + * nsk.jdi.ReferenceType.fieldByName.fieldbyname001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.fieldByName.fieldbyname001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001a.java new file mode 100644 index 00000000000..a08cb86538a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname001a.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fieldByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the fieldbyname001 JDI test. + */ + +public class fieldbyname001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i fieldbyname001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + fieldbyname001aClassForCheck class_for_check = new fieldbyname001aClassForCheck(); + + print_log_on_verbose("**> fieldbyname001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fieldbyname001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fieldbyname001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> fieldbyname001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> fieldbyname001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class fieldbyname001aClassForCheck extends fieldbyname001aSuperClassForCheck implements fieldbyname001aInterfaceForCheck { + + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + static long[] s_prim_array_field; + static Object[] s_ref_array_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + long[] i_prim_array_field; + Object[] i_ref_array_field; + + static long s_super_hidden_prim_field; + static Object s_super_hidden_ref_field; + + static long i_super_hidden_prim_field; + static Object i_super_hidden_ref_field; + + static long s_interf_hidden_prim_field; + static Object s_interf_hidden_ref_field; + +} + +class fieldbyname001aSuperClassForCheck { + + static boolean s_super_boolean_field; + static byte s_super_byte_field; + static char s_super_char_field; + static double s_super_double_field; + static float s_super_float_field; + static int s_super_int_field; + static long s_super_long_field; + static Object s_super_object_field; + + static long s_super_hidden_prim_field; + static Object s_super_hidden_ref_field; + + boolean i_super_boolean_field; + byte i_super_byte_field; + char i_super_char_field; + double i_super_double_field; + float i_super_float_field; + int i_super_int_field; + long i_super_long_field; + Object i_super_object_field; + + long i_super_hidden_prim_field; + Object i_super_hidden_ref_field; + + int ambiguous_prim_field; + Class ambiguous_ref_field; + +} + +interface fieldbyname001aInterfaceForCheck { + + static final boolean s_interf_boolean_field = true; + static final byte s_interf_byte_field = (byte)1; + static final char s_interf_char_field = '1'; + static final double s_interf_double_field = 999; + static final float s_interf_float_field = 99; + static final int s_interf_int_field = 100; + static final long s_interf_long_field = 1000; + static final Object s_interf_object_field = new Object(); + + static final long s_interf_hidden_prim_field = 1; + static final Object s_interf_hidden_ref_field = new Object(); + + static final long ambiguous_prim_field = 1; + static final Object ambiguous_ref_field = new Object(); + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002.java new file mode 100644 index 00000000000..bcbb8846e72 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fieldByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method fieldByName() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class fieldbyname002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.fieldByName.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "fieldbyname002", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "fieldbyname002aClassForCheck"; + + private final static String classLoaderName = package_prefix + "fieldbyname002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new fieldbyname002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ReferenceType/fieldByName/fieldbyname002 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ReferenceType/fieldByName/fieldbyname002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + private void print_log_anyway(String message) { + logHandler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + Debugee debugee; + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + print_log_on_verbose("==> nsk/jdi/ReferenceType/fieldByName/fieldbyname002 test LOG:"); + print_log_on_verbose("==> test checks fieldByName(...) method of ReferenceType interface "); + print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> fieldbyname002: fieldbyname002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> fieldbyname002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> fieldbyname002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fieldbyname002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> fieldbyname002: check ReferenceType.fieldByName(...) method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean fieldByName_method_error = false; + + while ( true ) { // test body + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> fieldbyname002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> fieldbyname002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + Field field_by_name = null; + try { + field_by_name = refType.fieldByName("dummy_field"); + print_log_anyway + ("##> fieldbyname002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + fieldByName_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> fieldbyname002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> fieldbyname002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + fieldByName_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || fieldByName_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> fieldbyname002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> fieldbyname002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> fieldbyname002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/TestDescription.java new file mode 100644 index 00000000000..9f2809dfbbc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/fieldByName/fieldbyname002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/fieldByName/fieldbyname002 test + * checks the fieldByName(...) method of ReferenceType interface + * of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.fieldByName(...) method is called for + * dummy field of this class - ClassNotPreparedException should be thrown + * in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "out_stream.println" are replaced with + * "print_log_on_verbose" and "print_log_anyway". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.fieldByName.fieldbyname002 + * nsk.jdi.ReferenceType.fieldByName.fieldbyname002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.fieldByName.fieldbyname002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/loadclass/fieldbyname002aClassForCheck.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/loadclass/fieldbyname002aClassForCheck.java new file mode 100644 index 00000000000..988bbcbd5d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002/loadclass/fieldbyname002aClassForCheck.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.fieldByName; + +/** + * This class is loaded by fieldbyname002aClassLoader . + */ +class fieldbyname002aClassForCheck { + + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002a.java new file mode 100644 index 00000000000..84d51fc58f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname002a.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fieldByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + + +/** + * This class is used as debugee application for the fieldbyname002 JDI test. + */ + +public class fieldbyname002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String + package_prefix = "nsk.jdi.ReferenceType.fieldByName."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "fieldbyname002aClassForCheck"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i fieldbyname002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + fieldbyname002aClassLoader customClassLoader = new fieldbyname002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> fieldbyname002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> fieldbyname002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> fieldbyname002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fieldbyname002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fieldbyname002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> fieldbyname002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> fieldbyname002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class fieldbyname002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public fieldbyname002aClassLoader(String classPath, String className) { + super(fieldbyname002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003.java new file mode 100644 index 00000000000..184cf3e865c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fieldByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method fieldByName() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class fieldbyname003 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.fieldByName.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "fieldbyname003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "fieldbyname003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new fieldbyname003().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/fieldByName/fieldbyname003 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/fieldByName/fieldbyname003 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + private static void print_log_without_verbose(String message) { + if ( ! verbose_mode ) { + out_stream.println(message); + } + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/fieldByName/fieldbyname003 test LOG:"); + out_stream.println("--> test checks fieldByName(...) method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for UNLOADED class\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + argv = argHandler.getArguments(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> fieldbyname003: fieldbyname003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> fieldbyname003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + out_stream.println + ("##> fieldbyname003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fieldbyname003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> fieldbyname003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + out_stream.println + ("##> fieldbyname003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fieldbyname003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean fieldByName_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> fieldbyname003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> fieldbyname003: getting ReferenceType object for loaded checked class..."); + out_stream.println("##> fieldbyname003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> fieldbyname003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> fieldbyname003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> fieldbyname003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + out_stream.println + ("--> fieldbyname003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + out_stream.println + ("--> ReferenceType.fieldByName() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + out_stream.println + ("##> fieldbyname003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fieldbyname003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> fieldbyname003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> fieldbyname003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> fieldbyname003: check that checked class has been unloaded realy..."); + out_stream.println + ("--> fieldbyname003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + out_stream.println + ("--> ReferenceType.fieldByName() method can NOT be checked!"); + break; + } + + out_stream.println + ("--> fieldbyname003: check ReferenceType.fieldByName(...) method for unloaded class..."); + Field field_by_name = null; + try { + field_by_name = refType.fieldByName("dummy_field"); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + out_stream.println + ("--> fieldbyname003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + out_stream.println + ("##> fieldbyname003: FAILED: unexpected Exception thrown - " + expt.toString()); + out_stream.println + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + fieldByName_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || fieldByName_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> fieldbyname003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> fieldbyname003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> fieldbyname003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of fieldbyname003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TestDescription.java new file mode 100644 index 00000000000..5e299f27b3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/fieldByName/fieldbyname003. + * VM Testbase keywords: [diehard, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/fieldByName/fieldbyname003 test + * checks the fieldByName(...) method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * fieldByName(...) method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - fieldbyname003b class was moved in 'loadclass' subdirectory; + * - package name was added in fieldbyname003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for fieldbyname003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.fieldByName.fieldbyname003 + * nsk.jdi.ReferenceType.fieldByName.fieldbyname003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.fieldByName.fieldbyname003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/loadclass/fieldbyname003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/loadclass/fieldbyname003b.java new file mode 100644 index 00000000000..bf827f494b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003/loadclass/fieldbyname003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the fieldByName(...) method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.fieldByName; + +class fieldbyname003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003a.java new file mode 100644 index 00000000000..8d2cb87f239 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fieldByName/fieldbyname003a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fieldByName; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the fieldbyname003 JDI test. + */ + +public class fieldbyname003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + static String package_prefix = "nsk.jdi.ReferenceType.fieldByName."; + static String checked_class_name = package_prefix + "fieldbyname003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> fieldbyname003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> fieldbyname003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> fieldbyname003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> fieldbyname003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> fieldbyname003a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> fieldbyname003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fieldbyname003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fieldbyname003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> fieldbyname003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> fieldbyname003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> fieldbyname003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> fieldbyname003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> fieldbyname003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> fieldbyname003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> fieldbyname003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fieldbyname003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fieldbyname003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> fieldbyname003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> fieldbyname003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of fieldbyname003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001.java new file mode 100644 index 00000000000..3b2fb2c6e3f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method fields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class fields001 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.fields.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "fields001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "fields001aClassForCheck"; + private final static String not_found_sign = "NOT FOUND"; + private final static String passed_sign = "PASSED"; + private static String fields_for_check[][] = { + +// field name type name static declaring class check result + + {"s_boolean_field", "boolean", " static", class_for_check, not_found_sign }, + {"s_byte_field", "byte", " static", class_for_check, not_found_sign }, + {"s_char_field", "char", " static", class_for_check, not_found_sign }, + {"s_double_field", "double", " static", class_for_check, not_found_sign }, + {"s_float_field", "float", " static", class_for_check, not_found_sign }, + {"s_int_field", "int", " static", class_for_check, not_found_sign }, + {"s_long_field", "long", " static", class_for_check, not_found_sign }, + {"s_object_field", "java.lang.Object", " static", class_for_check, not_found_sign }, + {"s_prim_array_field", "long[]", " static", class_for_check, not_found_sign }, + {"s_ref_array_field", "java.lang.Object[]", " static", class_for_check, not_found_sign }, + {"i_boolean_field", "boolean", "", class_for_check, not_found_sign }, + {"i_byte_field", "byte", "", class_for_check, not_found_sign }, + {"i_char_field", "char", "", class_for_check, not_found_sign }, + {"i_double_field", "double", "", class_for_check, not_found_sign }, + {"i_float_field", "float", "", class_for_check, not_found_sign }, + {"i_int_field", "int", "", class_for_check, not_found_sign }, + {"i_long_field", "long", "", class_for_check, not_found_sign }, + {"i_object_field", "java.lang.Object", "", class_for_check, not_found_sign }, + {"i_prim_array_field", "long[]", "", class_for_check, not_found_sign }, + {"i_ref_array_field", "java.lang.Object[]", "", class_for_check, not_found_sign }, + {"s_super_hidden_prim_field", "long", " static", class_for_check, not_found_sign }, + {"s_super_hidden_ref_field", "java.lang.Object", " static", class_for_check, not_found_sign }, + {"i_super_hidden_prim_field", "long", " static", class_for_check, not_found_sign }, + {"i_super_hidden_ref_field", "java.lang.Object", " static", class_for_check, not_found_sign }, + {"s_interf_hidden_prim_field", "long", " static", class_for_check, not_found_sign }, + {"s_interf_hidden_ref_field", "java.lang.Object", " static", class_for_check, not_found_sign } + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new fields001().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/fields/fields001 test FAILED"); + } + else { + print_log_anyway("\n==> nsk/jdi/ReferenceType/fields/fields001 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/fields/fields001 test LOG:"); + print_log_anyway("==> test checks fields() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> fields001: fields001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> fields001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> fields001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fields001: debugee's \"ready\" signal recieved!"); + } + + print_log_anyway + ("--> fields001: check ReferenceType.fields() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean fields_method_error = false; + int fields_for_check_number = fields_for_check.length; + int not_found_fields_number = 0; + int returned_fields_number = 0; + int unexpected_found_fields_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + print_log_anyway("##> fields001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List returned_fields_list = null; + try { + returned_fields_list = refType.fields(); + } + catch (Throwable thrown) { + print_log_anyway("##> fields001: FAILED: ReferenceType.fields() throws unexpected " + + thrown); + fields_method_error = true; + break; + } + returned_fields_number = returned_fields_list.size(); + Field returned_fields_array[] = new Field[returned_fields_number]; + String unexpected_returned_fields_array[] = new String[returned_fields_number]; + returned_fields_list.toArray(returned_fields_array); + for (int i=0; i fields001: FAILED: field is NOT found: " + field_for_check_info); + not_found_fields_number++; + } + else { + print_log_on_verbose + ("--> fields001: PASSED for field: " + field_for_check_info); + } + } + for (int i=0; i fields001: FAILED: unexpected found field: " + unexpected_returned_fields_array[i]); + } + break; + } + + print_log_anyway("--> fields001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || fields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_anyway("--> fields001: expected found fields number = " + fields_for_check_number); + print_log_anyway("--> fields001: in fact found fields number = " + returned_fields_number); + print_log_anyway("--> fields001: expected and in fact found fields number = " + + (fields_for_check_number - not_found_fields_number)); + print_log_anyway + ("##> fields001: NOT found fields number = " + not_found_fields_number); + print_log_anyway + ("##> fields001: UNEXPECTED found fields number = " + unexpected_found_fields_number); + } + if ( not_found_fields_number + unexpected_found_fields_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> fields001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> fields001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> fields001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001/TestDescription.java new file mode 100644 index 00000000000..c4d99fe44df --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/fields/fields001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/fields/fields001 test + * checks the fields() method of ReferenceType interface + * of the com.sun.jdi package : + * the ReferenceType.fields() method is checked for fields of + * debugee's class which extends super class and implements interface. + * The test expects that only declared directly in the checked class + * fields should be included in Field list returned by the fields() method. + * Each field is checked for field name, field type, static modifier + * and declaring class. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.fields.fields001 + * nsk.jdi.ReferenceType.fields.fields001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.fields.fields001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001a.java new file mode 100644 index 00000000000..d72fb7c5124 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields001a.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the fields001 JDI test. + */ + +public class fields001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i fields001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + fields001aClassForCheck class_for_check = new fields001aClassForCheck(); + + print_log_on_verbose("**> fields001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fields001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fields001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> fields001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> fields001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class fields001aClassForCheck extends fields001aSuperClassForCheck implements fields001aInterfaceForCheck { + + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + static long[] s_prim_array_field; + static Object[] s_ref_array_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + long[] i_prim_array_field; + Object[] i_ref_array_field; + + static long s_super_hidden_prim_field; + static Object s_super_hidden_ref_field; + + static long i_super_hidden_prim_field; + static Object i_super_hidden_ref_field; + + static long s_interf_hidden_prim_field; + static Object s_interf_hidden_ref_field; + +} + +class fields001aSuperClassForCheck { + + static boolean s_super_boolean_field; + static byte s_super_byte_field; + static char s_super_char_field; + static double s_super_double_field; + static float s_super_float_field; + static int s_super_int_field; + static long s_super_long_field; + static Object s_super_object_field; + + static long s_super_hidden_prim_field; + static Object s_super_hidden_ref_field; + + boolean i_super_boolean_field; + byte i_super_byte_field; + char i_super_char_field; + double i_super_double_field; + float i_super_float_field; + int i_super_int_field; + long i_super_long_field; + Object i_super_object_field; + + long i_super_hidden_prim_field; + Object i_super_hidden_ref_field; + + long ambiguous_prim_field; + Object ambiguous_ref_field; + +} + +interface fields001aInterfaceForCheck { + + static final boolean s_interf_boolean_field = true; + static final byte s_interf_byte_field = (byte)1; + static final char s_interf_char_field = '1'; + static final double s_interf_double_field = 999; + static final float s_interf_float_field = 99; + static final int s_interf_int_field = 100; + static final long s_interf_long_field = 1000; + static final Object s_interf_object_field = new Object(); + + static final long s_interf_hidden_prim_field = 1; + static final Object s_interf_hidden_ref_field = new Object(); + + static final long ambiguous_prim_field = 1; + static final Object ambiguous_ref_field = new Object(); + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002.java new file mode 100644 index 00000000000..63eb6e6ea15 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method fields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class fields002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.fields.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "fields002", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "fields002aClassForCheck"; + + private final static String classLoaderName = package_prefix + "fields002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new fields002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/fields/fields002 test FAILED"); + } + else { + print_log_on_verbose("\n==> nsk/jdi/ReferenceType/fields/fields002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + test_log_handler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, test_log_handler); + + print_log_on_verbose("==> nsk/jdi/ReferenceType/fields/fields002 test LOG:"); + print_log_on_verbose("==> test checks fields() method of ReferenceType interface "); + print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + debugee_launch_command = debugeeName + " -vbs"; + } + + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + + debugee.redirectStderr(out); + print_log_on_verbose("--> fields002: fields002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> fields002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> fields002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fields002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> fields002: check ReferenceType.fields() method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean fields_method_error = false; + + while ( true ) { // test body + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> fields002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> fields002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + List fields_list = null; + try { + fields_list = refType.fields(); + print_log_anyway + ("##> fields002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + fields_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> fields002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> fields002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + fields_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || fields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> fields002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> fields002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> fields002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/TestDescription.java new file mode 100644 index 00000000000..645963209e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/fields/fields002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/fields/fields002 test + * checks the fields() method of ReferenceType interface + * of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.fields() method is called for + * this class - ClassNotPreparedException should be thrown + * in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements ""print_log_anyway"" are replaced with + * "print_log_on_verbose". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.fields.fields002 + * nsk.jdi.ReferenceType.fields.fields002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.fields.fields002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/loadclass/fields002aClassForCheck.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/loadclass/fields002aClassForCheck.java new file mode 100644 index 00000000000..826cf2e1565 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002/loadclass/fields002aClassForCheck.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.fields; + +/** + * This class is loaded by fields002aClassLoader . + */ +class fields002aClassForCheck { + + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002a.java new file mode 100644 index 00000000000..5f0501c794e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields002a.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + + +/** + * This class is used as debugee application for the fields002 JDI test. + */ + +public class fields002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String + package_prefix = "nsk.jdi.ReferenceType.fields."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "fields002aClassForCheck"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i fields002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + fields002aClassLoader customClassLoader = new fields002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> fields002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> fields002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> fields002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fields002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fields002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> fields002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> fields002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class fields002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public fields002aClassLoader(String classPath, String className) { + super(fields002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003.java new file mode 100644 index 00000000000..48807fdda96 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method fields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class fields003 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private static final String package_prefix = "nsk.jdi.ReferenceType.fields."; + private static final String thisClassName = package_prefix + "fields003"; + private static final String debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "fields003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new fields003().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/fields/fields003 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/fields/fields003 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/fields/fields003 test LOG:"); + print_log_anyway("--> test checks fields() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> fields003: fields003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> fields003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> fields003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fields003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> fields003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> fields003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fields003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean fields_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> fields003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> fields003: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> fields003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> fields003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> fields003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> fields003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> fields003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.fields() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> fields003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fields003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> fields003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> fields003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> fields003: check that checked class has been unloaded realy..."); + print_log_anyway + ("--> fields003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.fields() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> fields003: check ReferenceType.fields() method for unloaded class..."); + List fields_list = null; + try { + fields_list = refType.fields(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> fields003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> fields003: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + fields_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || fields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> fields003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> fields003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> fields003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of fields003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TestDescription.java new file mode 100644 index 00000000000..1f71c07a218 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/fields/fields003. + * VM Testbase keywords: [diehard, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/fields/fields003 test + * checks the fields() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * fields() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - fields003b class was moved in 'loadclass' subdirectory; + * - package name was added in fields003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for fields003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.fields.fields003 + * nsk.jdi.ReferenceType.fields.fields003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.fields.fields003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/loadclass/fields003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/loadclass/fields003b.java new file mode 100644 index 00000000000..fbe6ddee028 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003/loadclass/fields003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the fields() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.fields; + +class fields003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003a.java new file mode 100644 index 00000000000..f808a057799 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fields; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the fields003 JDI test. + */ + +public class fields003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private static final String package_prefix = "nsk.jdi.ReferenceType.fields."; + private static final String checked_class_name = package_prefix + "fields003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> fields003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> fields003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> fields003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> fields003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> fields003a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> fields003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fields003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fields003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> fields003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> fields003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> fields003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> fields003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> fields003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> fields003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> fields003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fields003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fields003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> fields003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> fields003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of fields003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004.java new file mode 100644 index 00000000000..f796027328d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method fields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class fields004 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.fields.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "fields004", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "fields004aClassForCheck"; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new fields004().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/fields/fields004 test FAILED"); + } + else { + print_log_anyway("\n==> nsk/jdi/ReferenceType/fields/fields004 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/fields/fields004 test LOG:"); + print_log_anyway("==> test checks fields() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for class without any declarated fields\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> fields004: fields004a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> fields004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> fields004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> fields004: debugee's \"ready\" signal recieved!"); + } + + print_log_anyway + ("--> fields004: check ReferenceType.fields() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean fields_method_error = false; + int returned_fields_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + print_log_anyway("##> fields004: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List returned_fields_list = null; + try { + returned_fields_list = refType.fields(); + } + catch (Throwable thrown) { + print_log_anyway("##> fields004: FAILED: ReferenceType.fields() throws unexpected " + + thrown); + fields_method_error = true; + break; + } + returned_fields_number = returned_fields_list.size(); + if ( returned_fields_number == 0 ) { + break; + } + Field returned_fields[] = new Field[returned_fields_number]; + returned_fields_list.toArray(returned_fields); + for (int i=0; i fields004: FAILED: unexpected found field: " + returned_field_info); + } + break; + } + + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || fields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + if ( returned_fields_number > 0 ) { + print_log_anyway + ("##> fields004: UNEXPECTED found fields number = " + returned_fields_number); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_anyway + ("--> fields004: PASSED: returned list of fields is empty!"); + } + + print_log_on_verbose("--> fields004: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> fields004: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> fields004: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004/TestDescription.java new file mode 100644 index 00000000000..e8e2a672c23 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/fields/fields004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/fields/fields004 test + * checks the fields() method of ReferenceType interface + * of the com.sun.jdi package for class without any declarated fields: + * the ReferenceType.fields() method is checked for + * debugee's class which extends super class and implements interface. + * The checked class does not contain any declarated fields + * but extended super class and implemented interface have + * declarated fields. + * The test expects the returned list of fields to be empty. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.fields.fields004 + * nsk.jdi.ReferenceType.fields.fields004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.fields.fields004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004a.java new file mode 100644 index 00000000000..9dc8565cfe4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields004a.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the fields004 JDI test. + */ + +public class fields004a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i fields004a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + fields004aClassForCheck class_for_check = new fields004aClassForCheck(); + + print_log_on_verbose("**> fields004a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> fields004a: \"quit\" signal recieved!"); + print_log_on_verbose("**> fields004a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("##> fields004a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("##> fields004a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class fields004aClassForCheck extends fields004aSuperClassForCheck implements fields004aInterfaceForCheck { + +} + +class fields004aSuperClassForCheck { + + static boolean s_super_boolean_field; + static byte s_super_byte_field; + static char s_super_char_field; + static double s_super_double_field; + static float s_super_float_field; + static int s_super_int_field; + static long s_super_long_field; + static Object s_super_object_field; + + static long s_super_hidden_prim_field; + static Object s_super_hidden_ref_field; + + boolean i_super_boolean_field; + byte i_super_byte_field; + char i_super_char_field; + double i_super_double_field; + float i_super_float_field; + int i_super_int_field; + long i_super_long_field; + Object i_super_object_field; + + long i_super_hidden_prim_field; + Object i_super_hidden_ref_field; + + long ambiguous_prim_field; + Object ambiguous_ref_field; + +} + +interface fields004aInterfaceForCheck { + + static final boolean s_interf_boolean_field = true; + static final byte s_interf_byte_field = (byte)1; + static final char s_interf_char_field = '1'; + static final double s_interf_double_field = 999; + static final float s_interf_float_field = 99; + static final int s_interf_int_field = 100; + static final long s_interf_long_field = 1000; + static final Object s_interf_object_field = new Object(); + + static final long s_interf_hidden_prim_field = 1; + static final Object s_interf_hidden_ref_field = new Object(); + + static final long ambiguous_prim_field = 1; + static final Object ambiguous_ref_field = new Object(); + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005.java new file mode 100644 index 00000000000..625e7ade016 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.fields; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.fields() + * properly returns an empty field list for arrays (ArrayType) and primitive + * classes.

    + * + * Debugger part of it attempts to get a list of fields declared in several + * reference types corresponding to debuggee field values, which themselves + * are:
    + * primitive classes, and arrays of primitive types and classes. + */ +public class fields005 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.fields.fields005t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 24; + // tested fields used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new fields005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "fields005t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + // check there are enum constant fields + List l = checkedClass.fields(); + if (l.isEmpty()) { + complain("\t ReferenceType.fields() returned empty list for type: " + className); + exitStatus = Consts.TEST_FAILED; + } else { + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + boolean hasField = false; + + Iterator it = l.iterator(); + while (it.hasNext()) { + Field checkedField = it.next(); + if (expectedEnumFieldsNames[i].equals(checkedField.name()) && + checkedField.type().equals(checkedClass) ) + + hasField = true; + } + if (hasField) { + display("enum " + className + " has field " + expectedEnumFieldsNames[i]); + display("\t of type " + className); + } else { + complain("enum " + className + " does not have field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006/TestDescription.java new file mode 100644 index 00000000000..99d4c68c9a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/fields/fields006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for fields() method of ReferenceType interface. + * The test checks if the method returns each enum constants + * declared in mirrored enum type. + * The test consists of a debugger program (fields006.java) + * and debuggee application (fields006a.java). + * Package name is nsk.jdi.ReferenceType.fields . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls fields() method for each field + * of enum type declared in fields006a class. Every of these + * enum types has the same enum constants, i.e fields: e1 and e2. + * The debugger checks if each field of expected name and type + * (it must be "self-typed") exists in returned list. + * The test fails if any of expected fields has not been met. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.fields.fields006 + * nsk.jdi.ReferenceType.fields.fields006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.fields.fields006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006a.java new file mode 100644 index 00000000000..e97c7ece505 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields006a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.fields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class fields006a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static fields006Enum1 f1 = fields006Enum1.e2; + static fields006Enum2 f2 = fields006Enum2.e1; + static fields006Enum1.Enum1_ f3 = fields006Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(fields006.SIGNAL_READY); + + + //pipe.println(fields006.SIGNAL_GO); + receiveSignal(fields006.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum fields006Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum fields006Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001.java new file mode 100644 index 00000000000..ceb9b6286c4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the ReferenceType.genericSignature() method.
    + *
    + * The test checks up ReferenceType.genericSignature() method
    + * for ArrayType and ClassType objects.
    + *
    + * The first: the test checks that genericSignature() method returns
    + * null for arrays of all primitive types.
    + *
    + * The second: the test checks that genericSignature() method returns
    + * null for arrays of reference types which have a ClassType as its
    + * type.
    + *
    + * The third: the test checks that genericSignature() method returns
    + * null for ClassType types which are not generic types.
    + *
    + * At last: the test checks that genericSignature() method returns
    + * a corresponding signature string for ClassType types which are
    + * generic types.
    + *
    + */ + +public class genericSignature001 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "genericSignature001: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> genericSignature001: "; + static final String infoLogPrefix = "--> "; + static final String packagePrefix = "nsk.jdi.ReferenceType.genericSignature."; + static final String targetVMClassName = packagePrefix + "genericSignature001a"; + + static ArgumentHandler argsHandler; + static Log logHandler; + static boolean verboseMode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + + private final static String primitiveTypeSign = "primitiveType"; + private final static String referenceTypeSign = "referenceType"; + + /** + * Debugee's classes for check: + * classesForCheck[i][0] - basic class name (without arrays' brackets) + * classesForCheck[i][1] - type sign: primitive or reference) + * classesForCheck[i][2] - expected string returned by genericSignature() + */ + private final static String classesForCheck[][] = { + {"boolean", primitiveTypeSign, null}, + {"byte" , primitiveTypeSign, null}, + {"char" , primitiveTypeSign, null}, + {"double" , primitiveTypeSign, null}, + {"float" , primitiveTypeSign, null}, + {"int" , primitiveTypeSign, null}, + {"long" , primitiveTypeSign, null}, + + {packagePrefix + "GS001_Class01", referenceTypeSign, null}, + {packagePrefix + "GS001_Class02", referenceTypeSign, null}, + {packagePrefix + "GS001_Class03", referenceTypeSign, null}, + {packagePrefix + "GS001_Class04", referenceTypeSign, null}, + {packagePrefix + "GS001_Class05", referenceTypeSign, null}, + + {packagePrefix + "GS001_Class06", referenceTypeSign, + "Ljava/lang/Object;"}, + {packagePrefix + "GS001_Class07", referenceTypeSign, + "Ljava/lang/Object;"}, + {packagePrefix + "GS001_Class08", referenceTypeSign, + "Ljava/lang/Object;"}, + {packagePrefix + "GS001_Class09", referenceTypeSign, + "Ljava/lang/Object;"}, + {packagePrefix + "GS001_Class10", referenceTypeSign, + "Ljava/lang/Object;"}, + {packagePrefix + "GS001_Class11", referenceTypeSign, + "Lnsk/jdi/ReferenceType/genericSignature/GS001_Class06;"}, + + }; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int result = new genericSignature001().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/ReferenceType/genericSignature/genericSignature001 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/ReferenceType/genericSignature/genericSignature001 test PASSED"); + } + return result; + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + verboseMode = argsHandler.verbose(); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/ReferenceType/genericSignature/genericSignature001 test..."); + logOnVerbose + ("==> Test checks the genericSignature() method of ReferenceType interface"); + logOnVerbose + ("==> of the com.sun.jdi package for ArrayType, ClassType, InterfaceType."); + + Binder binder = new Binder(argsHandler,logHandler); + Debugee debugee = binder.bindToDebugee(targetVMClassName); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + logOnVerbose(infoLogPrefixHead + "Debugee (" + targetVMClassName + ") launched..."); + debugee.resume(); + + String readySignal = "ready"; + String signalFromDebugee = pipe.readln(); + if ( ! readySignal.equals(signalFromDebugee) ) { + logOnError(errorLogPrefixHead + "Uexpected debugee's signal:"); + logOnError(errorLogPrefix + "Expected signal = '" + readySignal + "'"); + logOnError(errorLogPrefix + "Actual signal = '" + signalFromDebugee + "'"); + return STATUS_FAILED; + } + logOnVerbose(infoLogPrefixHead + "Debugee's signal recieved = '" + readySignal + "'"); + + logOnVerbose(infoLogPrefixHead + "check ReferenceType.genericSignature() method for debugee's classes..."); + String brackets[] = {"", "[]", "[][]"}; + for (int i=0; i 0 ) { + expectedGenericSignature = null; + } + String actualGenericSignature = null; + try { + actualGenericSignature = referenceType.genericSignature(); + } catch (Throwable thrown) { + logOnError(errorLogPrefixHead + "ReferenceType.genericSignature() throws unexpected exception: "); + logOnError(errorLogPrefix + "ReferenceType = '" + referenceType + "'"); + logOnError(errorLogPrefix + "Class name for this ReferenceType = '" + className + "'"); + logOnError(errorLogPrefix + "Exception = '" + thrown + "'"); + testResult = STATUS_FAILED; + continue; + } + boolean isFailure = false; + if ( expectedGenericSignature == null ) { + if ( actualGenericSignature != null ) { + isFailure = true; + } + } else { + if ( ! expectedGenericSignature.equals(actualGenericSignature) ) { + isFailure = true; + } + } + if ( isFailure ) { + logOnError(errorLogPrefixHead + "ReferenceType.genericSignature() returns unexpected signature: "); + logOnError(errorLogPrefix + "ReferenceType = '" + referenceType + "'"); + logOnError(errorLogPrefix + "Class name for this ReferenceType = '" + className + "'"); + logOnError(errorLogPrefix + "Expected generic signature = '" + expectedGenericSignature + "'"); + logOnError(errorLogPrefix + "Actual generic signature = '" + actualGenericSignature + "'"); + testResult = STATUS_FAILED; + } + } + } + logOnVerbose(infoLogPrefixHead + + "Check ReferenceType.genericSignature() method for debugee's classes completed."); + + logOnVerbose(infoLogPrefixHead + "Waiting for debugee finish..."); + String quitSignal = "quit"; + pipe.println(quitSignal); + debugee.waitFor(); + + int debugeeExitStatus = debugee.getStatus(); + if (debugeeExitStatus != (STATUS_PASSED + STATUS_TEMP) ) { + logOnError(errorLogPrefixHead + "Unexpected Debugee's exit status: "); + logOnError(errorLogPrefix + "Expected status = '" + (STATUS_PASSED + STATUS_TEMP) + "'"); + logOnError(errorLogPrefix + "Actual status = '" + debugeeExitStatus + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of genericSignature001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001/TestDescription.java new file mode 100644 index 00000000000..e336e3540d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/genericSignature/genericSignature001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/genericSignature/genericSignature001 test: + * The test for the ReferenceType.genericSignature() method. + * The test checks up ReferenceType.genericSignature() method + * for ArrayType and ClassType objects. + * The first: the test checks that genericSignature() method returns + * null for arrays of all primitive types. + * The second: the test checks that genericSignature() method returns + * null for arrays of reference types which have a ClassType as its + * type. + * The third: the test checks that genericSignature() method returns + * null for ClassType types which are not generic types. + * At last: the test checks that genericSignature() method returns + * a corresponding signature string for ClassType types which are + * generic types. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.genericSignature.genericSignature001 + * nsk.jdi.ReferenceType.genericSignature.genericSignature001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.genericSignature.genericSignature001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001a.java new file mode 100644 index 00000000000..dd41eab3ddc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature001a.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for + * the nsk/jdi/ReferenceType/genericSignature/genericSignature001 JDI test. + */ + +public class genericSignature001a { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "genericSignature001(Debugee): "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> genericSignature001(Debugee): "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + // instantiating of arrays of primitive types for check ReferenceType.genericSignature() method + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // instantiating of non-generic reference types and arrays of non-generic reference types + // for check ReferenceType.genericSignature() method + + GS001_Class01 GS001_Class01_Obj0 = new GS001_Class01(), + GS001_Class01_Obj1[]={GS001_Class01_Obj0}, + GS001_Class01_Obj2[][]={GS001_Class01_Obj1}; + + GS001_Class02 GS001_Class02_Obj0 = new GS001_Class02(), + GS001_Class02_Obj1[]={GS001_Class02_Obj0}, + GS001_Class02_Obj2[][]={GS001_Class02_Obj1}; + + GS001_Class03 GS001_Class03_Obj0 = new GS001_Class03(), + GS001_Class03_Obj1[]={GS001_Class03_Obj0}, + GS001_Class03_Obj2[][]={GS001_Class03_Obj1}; + + GS001_Class04 GS001_Class04_Obj0 = new GS001_Class04(), + GS001_Class04_Obj1[]={GS001_Class04_Obj0}, + GS001_Class04_Obj2[][]={GS001_Class04_Obj1}; + + GS001_Class05 GS001_Class05_Obj0 = new GS001_Class05(), + GS001_Class05_Obj1[]={GS001_Class05_Obj0}, + GS001_Class05_Obj2[][]={GS001_Class05_Obj1}; + + // instantiating of generic types for check ReferenceType.genericSignature() method + + GS001_Class06 GS001_Class06_Obj = new GS001_Class06(); + + GS001_Class07 GS001_Class07_Obj = + new GS001_Class07(); + + GS001_Class08 GS001_Class08_Obj = new GS001_Class08(); + + GS001_Class09 GS001_Class09_Obj = new GS001_Class09(); + + GS001_Class10 GS001_Class10_Obj = + new GS001_Class10(); + + GS001_Class11 GS001_Class11_Obj = new GS001_Class11(); + + + public static void main (String argv[]) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(System.err, argsHandler); + logHandler.enableErrorsSummary(false); + IOPipe pipe = argsHandler.createDebugeeIOPipe(); + + logOnVerbose(infoLogPrefixHead + "Debugee started!"); + + genericSignature001a genericSignature001aDebugee = new genericSignature001a(); + + String readySignal = "ready"; + pipe.println(readySignal); + String quitSignal = "quit"; + logOnVerbose(infoLogPrefixHead + "Wait for '" + quitSignal + "' signal..."); + String signalFromDebugger = pipe.readln(); + if ( ! (quitSignal.equals(signalFromDebugger)) ) { + logOnError(errorLogPrefixHead + "UNEXPECTED debugger's signal:"); + logOnError(errorLogPrefix + "Expected signal = '" + quitSignal + "'"); + logOnError(errorLogPrefix + "Actual signal = '" + signalFromDebugger + "'"); + logOnError(errorLogPrefix + "Exiting with Exit Status = '" + (STATUS_FAILED + STATUS_TEMP) + "'"); + System.exit(STATUS_FAILED + STATUS_TEMP); + } + logOnVerbose(infoLogPrefixHead + "'" + quitSignal + "' signal from debugger is received."); + logOnVerbose(infoLogPrefix + "Exiting with Exit Status = '" + (STATUS_PASSED + STATUS_TEMP) + "'"); + System.exit(STATUS_PASSED + STATUS_TEMP); + } +} // end of genericSignature001a class + + +// non generic classes: + +class GS001_Class01 {} + +class GS001_Class02 {} + +interface GS001_Interf01 {} + +interface GS001_Interf02 {} + +class GS001_Class03 extends GS001_Class01 {} + +class GS001_Class04 extends GS001_Class01 implements GS001_Interf01 {} + +class GS001_Class05 extends GS001_Class02 implements GS001_Interf02 {} + + +// generic classes: + +class GS001_Class06 {} + +class GS001_Class07 {} + +class GS001_Class08 {} + +class GS001_Class09 {} + +class GS001_Class10 {} + +class GS001_Class11 extends GS001_Class06 {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002.java new file mode 100644 index 00000000000..86262573aae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the ReferenceType.genericSignature() method.
    + *
    + * The test checks up ReferenceType.genericSignature() method
    + * for InterfaceType objects.
    + *
    + * The first: the test checks that genericSignature() method returns
    + * null for arrays of reference types which have a InterfaceType as
    + * its type.
    + *
    + * The second: the test checks that genericSignature() method returns
    + * null for InterfaceType types which are not generic types.
    + *
    + * At last: the test checks that genericSignature() method returns
    + * a corresponding signature string for InterfaceType types which are
    + * generic types.
    + *
    + */ + +public class genericSignature002 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "genericSignature002: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> genericSignature002: "; + static final String infoLogPrefix = "--> "; + static final String packagePrefix = "nsk.jdi.ReferenceType.genericSignature."; + static final String targetVMClassName = packagePrefix + "genericSignature002a"; + + static ArgumentHandler argsHandler; + static Log logHandler; + static boolean verboseMode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + + /** + * Debugee's classes for check: + * classesForCheck[i][0] - basic interface name (without arrays' brackets) + * classesForCheck[i][1] - expected string returned by genericSignature() + */ + /** Debugee's classes for check **/ + private final static String classesForCheck[][] = { + + {packagePrefix + "GS002_Interf01", null}, + {packagePrefix + "GS002_Interf02", null}, + + {packagePrefix + "GS002_Interf03", "Ljava/lang/Object;"}, + {packagePrefix + "GS002_Interf04", "Ljava/lang/Object;"}, + {packagePrefix + "GS002_Interf05", + "Ljava/lang/Object;"}, + {packagePrefix + "GS002_Interf06", + "Ljava/lang/Object;"}, + {packagePrefix + "GS002_Interf07", + "Ljava/lang/Object;"}, + {packagePrefix + "GS002_Interf08", + "Ljava/lang/Object;Lnsk/jdi/ReferenceType/genericSignature/GS002_Interf03;"} + + }; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int result = new genericSignature002().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/ReferenceType/genericSignature/genericSignature002 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/ReferenceType/genericSignature/genericSignature002 test PASSED"); + } + return result; + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + verboseMode = argsHandler.verbose(); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/ReferenceType/genericSignature/genericSignature002 test..."); + logOnVerbose + ("==> Test checks the genericSignature() method of ReferenceType interface"); + logOnVerbose + ("==> of the com.sun.jdi package for InterfaceType."); + + Binder binder = new Binder(argsHandler,logHandler); + Debugee debugee = binder.bindToDebugee(targetVMClassName); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + logOnVerbose(infoLogPrefixHead + "Debugee (" + targetVMClassName + ") launched..."); + debugee.resume(); + + String readySignal = "ready"; + String signalFromDebugee = pipe.readln(); + if ( ! readySignal.equals(signalFromDebugee) ) { + logOnError(errorLogPrefixHead + "Uexpected debugee's signal:"); + logOnError(errorLogPrefix + "Expected signal = '" + readySignal + "'"); + logOnError(errorLogPrefix + "Actual signal = '" + signalFromDebugee + "'"); + return STATUS_FAILED; + } + logOnVerbose(infoLogPrefixHead + "Debugee's signal recieved = '" + readySignal + "'"); + + logOnVerbose(infoLogPrefixHead + "check ReferenceType.genericSignature() method for debugee's classes..."); + String brackets[] = {"", "[]", "[][]"}; + for (int i=0; i 0 ) { // array type + if ( classesForCheck[i][1] != null ) { // it is generic type + continue; // arrays of generic types are not allowed + } + } + String className = basicName + brackets[arrayDimension]; + ReferenceType referenceType = debugee.classByName(className); + if (referenceType == null) { + logOnError(errorLogPrefixHead + "Could NOT find ReferenceType object for debugee's class: "); + logOnError(errorLogPrefix + "Requested class name = '" + className + "'"); + testResult = STATUS_FAILED; + continue; + } + String expectedGenericSignature = classesForCheck[i][1]; + if ( arrayDimension > 0 ) { + expectedGenericSignature = null; + } + String actualGenericSignature = null; + try { + actualGenericSignature = referenceType.genericSignature(); + } catch (Throwable thrown) { + logOnError(errorLogPrefixHead + "ReferenceType.genericSignature() throws unexpected exception: "); + logOnError(errorLogPrefix + "ReferenceType = '" + referenceType + "'"); + logOnError(errorLogPrefix + "Class name for this ReferenceType = '" + className + "'"); + logOnError(errorLogPrefix + "Exception = '" + thrown + "'"); + testResult = STATUS_FAILED; + continue; + } + boolean isFailure = false; + if ( expectedGenericSignature == null ) { + if ( actualGenericSignature != null ) { + isFailure = true; + } + } else { + if ( ! expectedGenericSignature.equals(actualGenericSignature) ) { + isFailure = true; + } + } + if ( isFailure ) { + logOnError(errorLogPrefixHead + "ReferenceType.genericSignature() returns unexpected signature: "); + logOnError(errorLogPrefix + "ReferenceType = '" + referenceType + "'"); + logOnError(errorLogPrefix + "Class name for this ReferenceType = '" + className + "'"); + logOnError(errorLogPrefix + "Expected generic signature = '" + expectedGenericSignature + "'"); + logOnError(errorLogPrefix + "Actual generic signature = '" + actualGenericSignature + "'"); + testResult = STATUS_FAILED; + } + } + } + logOnVerbose(infoLogPrefixHead + + "Check ReferenceType.genericSignature() method for debugee's classes completed."); + + logOnVerbose(infoLogPrefixHead + "Waiting for debugee finish..."); + String quitSignal = "quit"; + pipe.println(quitSignal); + debugee.waitFor(); + + int debugeeExitStatus = debugee.getStatus(); + if (debugeeExitStatus != (STATUS_PASSED + STATUS_TEMP) ) { + logOnError(errorLogPrefixHead + "Unexpected Debugee's exit status: "); + logOnError(errorLogPrefix + "Expected status = '" + (STATUS_PASSED + STATUS_TEMP) + "'"); + logOnError(errorLogPrefix + "Actual status = '" + debugeeExitStatus + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of genericSignature002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002/TestDescription.java new file mode 100644 index 00000000000..ef37114b303 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/genericSignature/genericSignature002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/genericSignature/genericSignature002 test: + * The test for the ReferenceType.genericSignature() method. + * The test checks up ReferenceType.genericSignature() method + * for InterfaceType objects. + * The first: the test checks that genericSignature() method returns + * null for arrays of reference types which have a InterfaceType as + * its type. + * The second: the test checks that genericSignature() method returns + * null for InterfaceType types which are not generic types. + * At last: the test checks that genericSignature() method returns + * a corresponding signature string for InterfaceType types which are + * generic types. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.genericSignature.genericSignature002 + * nsk.jdi.ReferenceType.genericSignature.genericSignature002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.genericSignature.genericSignature002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002a.java new file mode 100644 index 00000000000..9be56cd362f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/genericSignature/genericSignature002a.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for + * the nsk/jdi/ReferenceType/genericSignature/genericSignature002 JDI test. + */ + +public class genericSignature002a { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "genericSignature002(Debugee): "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> genericSignature002(Debugee): "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + // instantiating of non-generic interface types and arrays of non-generic interface types + // for check ReferenceType.genericSignature() method + + GS002_Class00 GS002_Class00_Obj = new GS002_Class00(); + + GS002_Interf01 GS002_Interf01_Obj0 = new GS002_Class01(); + GS002_Interf01[] GS002_Interf01_Obj1 = {GS002_Interf01_Obj0}; + GS002_Interf01[][] GS002_Interf01_Obj2 = {GS002_Interf01_Obj1}; + + GS002_Interf02 GS002_Interf02_Obj0 = new GS002_Class02(); + GS002_Interf02[] GS002_Interf02_Obj1 = {GS002_Interf02_Obj0}; + GS002_Interf02[][] GS002_Interf02_Obj2 = {GS002_Interf02_Obj1}; + + // instantiating of generic interface types for check ReferenceType.genericSignature() method + + GS002_Interf03 GS002_Interf03_Obj = new GS002_Class03(); + GS002_Interf04 GS002_Interf04_Obj = new GS002_Class04(); + GS002_Interf05 GS002_Interf05_Obj = new GS002_Class05(); + GS002_Interf06 GS002_Interf06_Obj = new GS002_Class06(); + GS002_Interf07 GS002_Interf07_Obj = new GS002_Class07(); + GS002_Interf08 GS002_Interf08_Obj = new GS002_Class08(); + + + public static void main (String argv[]) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(System.err, argsHandler); + logHandler.enableErrorsSummary(false); + IOPipe pipe = argsHandler.createDebugeeIOPipe(); + + logOnVerbose(infoLogPrefixHead + "Debugee started!"); + + genericSignature002a genericSignature002aDrbugee = new genericSignature002a(); + + String readySignal = "ready"; + pipe.println(readySignal); + String quitSignal = "quit"; + logOnVerbose(infoLogPrefixHead + "Wait for '" + quitSignal + "' signal..."); + String signalFromDebugger = pipe.readln(); + if ( ! (quitSignal.equals(signalFromDebugger)) ) { + logOnError(errorLogPrefixHead + "UNEXPECTED debugger's signal:"); + logOnError(errorLogPrefix + "Expected signal = '" + quitSignal + "'"); + logOnError(errorLogPrefix + "Actual signal = '" + signalFromDebugger + "'"); + logOnError(errorLogPrefix + "Exiting with Exit Status = '" + (STATUS_FAILED + STATUS_TEMP) + "'"); + System.exit(STATUS_FAILED + STATUS_TEMP); + } + logOnVerbose(infoLogPrefixHead + "'" + quitSignal + "' signal from debugger is received."); + logOnVerbose(infoLogPrefix + "Exiting with Exit Status = '" + (STATUS_PASSED + STATUS_TEMP) + "'"); + System.exit(STATUS_PASSED + STATUS_TEMP); + } +} // end of genericSignature002a class + + +// non generic interfaces: + +interface GS002_Interf01 {} + +interface GS002_Interf02 {} + +// generic interfaces: + +interface GS002_Interf03 {} + +interface GS002_Interf04 {} + +interface GS002_Interf05 {} + +interface GS002_Interf06 {} + +interface GS002_Interf07 {} + +interface GS002_Interf08 extends GS002_Interf03 {} + + + +// Auxiliary classes + +class GS002_Class00 implements GS002_Interf02 {} + +class GS002_Class01 implements GS002_Interf01 {} + +class GS002_Class02 implements GS002_Interf02 {} + +class GS002_Class03 implements GS002_Interf03 {} + +class GS002_Class04 implements GS002_Interf04 {} + +class GS002_Class05 implements GS002_Interf05 {} + +class GS002_Class06 implements GS002_Interf06 {} + +class GS002_Class07 implements GS002_Interf07 {} + +class GS002_Class08 implements GS002_Interf08 {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java new file mode 100644 index 00000000000..a8bbadaf602 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.getValue()
    + * complies with its spec.
    + * Case for testing includes fields mirroring primitive type values.
    + * The test checks that Values returned by the method,
    + * are casted to PrimitiveValue(s).
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class getvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/getValue/getvalue001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new getvalue001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.getValue.getvalue001a"; + + private String testedClassName = + "nsk.jdi.ReferenceType.getValue.getvalue001aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" name of tested class : " + testedClassName); + log2(" getting: List classes = vm.classByName(testedClassName);"); + List classes = vm.classesByName(testedClassName); + if (classes.size() != 1) { + log3("ERROR: classes.size() != 1 : " + classes.size()); + testExitCode = FAILED; + break; + } + log2(" getting: ReferenceType testedClass = (ReferenceType) classes.get(0);"); + ReferenceType testedClass = (ReferenceType) classes.get(0); + + log2("------case for testing: primitive values"); + + String fieldNames0[] = { + "bl0", + "bt0", + "ch0", + "db0", + "fl0", + "in0", + "ln0", + "sh0" }; + + for (int i1 = 0; i1 < 8; i1++) { + + log2("......field tested : " + fieldNames0[i1]); + log2(" getting: Field field = testedClass.fieldByName(fieldNames0[i1]);"); + Field field = testedClass.fieldByName(fieldNames0[i1]); + if (field == null) { + log3("ERROR: field == null"); + testExitCode = FAILED; + continue; + } + log2(" getting: Value value = testedClass.getValue(field);"); + Value value = testedClass.getValue(field); + if (value == null) { + log3("ERROR: value == null"); + testExitCode = FAILED; + continue; + } + try { + log2(" getting Class cast: PrimitiveValue primitiveValue = (PrimitiveValue) value;"); + PrimitiveValue primitiveValue = (PrimitiveValue) value; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001/TestDescription.java new file mode 100644 index 00000000000..0c503afd2d8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/getValue/getvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.getValue() + * complies with its spec: + * public Value getValue(Field field) + * Gets the Value of a given static Field in this type. + * The Field must be valid for this type; that is, it must be declared + * in this type, a superclass, a superinterface, or an implemented interface. + * Parameters: field - the field containing the requested value + * Returns: the Value of the instance field. + * Throws: IllegalArgumentException - + * if the field is not valid for this object's class. + * Case for testing includes fields mirroring primitive type values + * in this type, a superclass, a superinterface, and an implemented interface. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.getValue.getvalue001; + * the debuggee program - nsk.jdi.ReferenceType.getValue.getvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.getValue.getvalue001 + * nsk.jdi.ReferenceType.getValue.getvalue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.getValue.getvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001a.java new file mode 100644 index 00000000000..6404f56ed2a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalue001 JDI test. + */ + +public class getvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + getvalue001aTestClass testObj = new getvalue001aTestClass(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + +interface getvalue001aInterface1 { + char ch0 = 0; + double db0 = 0.0d; +} +interface getvalue001aInterface0 extends getvalue001aInterface1 { + boolean bl0 = false; + byte bt0 = 0; +} +interface getvalue001aInterface2 { + long ln0 = 0; +} +class getvalue001aClass1 implements getvalue001aInterface2 { + static short sh0 = 0; +} +class getvalue001aTestClass extends getvalue001aClass1 implements getvalue001aInterface0 { + static float fl0 = 0.0f; + static int in0 = 0; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java new file mode 100644 index 00000000000..eb701855946 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.getValue()
    + * complies with its spec.
    + * Case for testing includes arrays of primitive types declared
    + * in this type and its superclass.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class getvalue002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/getValue/getvalue002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new getvalue002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.getValue.getvalue002a"; + + private String testedClassName = + "nsk.jdi.ReferenceType.getValue.getvalue002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" name of tested class : " + testedClassName); + log2(" getting: List classes = vm.classByName(testedClassName);"); + List classes = vm.classesByName(testedClassName); + if (classes.size() != 1) { + log3("ERROR: classes.size() != 1 : " + classes.size()); + testExitCode = FAILED; + break; + } + log2(" getting: ReferenceType testedClass = (ReferenceType) classes.get(0);"); + ReferenceType testedClass = (ReferenceType) classes.get(0); + + + log2("------case for testing: arrays of primitive values"); + + String fieldNames[] = { + // "fl1", + // "in1", + // "ln1", + // "sh1" + // "fl1", + "in1", + "ln1", + "sh1" + }; + + for (int i1 = 0; i1 < fieldNames.length; i1++) { + + log2("......field tested : " + fieldNames[i1]); + log2(" getting: Field field = testedClass.fieldByName(fieldNames[i1]);"); + Field field = testedClass.fieldByName(fieldNames[i1]); + if (field == null) { + log3("ERROR: field == null"); + testExitCode = FAILED; + continue; + } + log2(" getting: Value value = testedClass.getValue(field);"); + Value value = testedClass.getValue(field); + if (value == null) { + log3("ERROR: value == null"); + testExitCode = FAILED; + continue; + } + try { + log2(" getting Class cast: ObjectReference objectReferenceValue = (ObjectReference) value;"); + ObjectReference objectReferenceValue = (ObjectReference) value; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002/TestDescription.java new file mode 100644 index 00000000000..5510da282e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/getValue/getvalue002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.getValue() + * complies with its spec: + * public Value getValue(Field field) + * Gets the Value of a given static Field in this type. + * The Field must be valid for this type; that is, it must be declared + * in this type, a superclass, a superinterface, or an implemented interface. + * Parameters: field - the field containing the requested value + * Returns: the Value of the instance field. + * Throws: IllegalArgumentException - + * if the field is not valid for this object's class. + * Case for testing includes arrays of primitive types declared + * in this type, a superclass, a superinterface, and an implemented interface. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.getValue.getvalue002; + * the debuggee program - nsk.jdi.ReferenceType.getValue.getvalue002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.getValue.getvalue002 + * nsk.jdi.ReferenceType.getValue.getvalue002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.getValue.getvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002a.java new file mode 100644 index 00000000000..88d45ac47e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002a.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalue002 JDI test. + */ + +public class getvalue002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + getvalue002aTestClass testObj = new getvalue002aTestClass(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + +interface getvalue002aInterface1 { + boolean[][][][] bl1 = { {{{true, false}, {true, false}}, {{true, false}, {true, false}} }, + {{{true, false}, {true, false}}, {{true, false}, {true, false}} } }; + byte [][][][] bt1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; +} + +interface getvalue002aInterface0 extends getvalue002aInterface1 { + char [][][][] ch1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; + double [][][][] db1 = { {{{0.0d, 1.0d},{0.0d, 1.0d}}, {{0.0d, 1.0d},{0.0d, 1.0d}}}, + {{{0.0d, 1.0d},{0.0d, 1.0d}}, {{0.0d, 1.0d},{0.0d, 1.0d}}} }; +} + +interface getvalue002aInterface2 { + float [][][][] fl1 = { {{{0.0f, 1.0f},{0.0f, 1.0f}}, {{0.0f, 1.0f},{0.0f, 1.0f}}}, + {{{0.0f, 1.0f},{0.0f, 1.0f}}, {{0.0f, 1.0f},{0.0f, 1.0f}}} }; +} + +class getvalue002aClass1 implements getvalue002aInterface2 { + static int [][][][] in1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; +} + +class getvalue002aTestClass extends getvalue002aClass1 implements getvalue002aInterface0 { + static long [][][][] ln1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; + static short [][][][] sh1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java new file mode 100644 index 00000000000..1130fbc2f30 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.getValue()
    + * complies with its spec.
    + * Case for testing includes arrays of primitive types declared
    + * in a superinterface and an implemented interface.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class getvalue003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/getValue/getvalue003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new getvalue003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.getValue.getvalue003a"; + + private String testedClassName = + "nsk.jdi.ReferenceType.getValue.getvalue003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" name of tested class : " + testedClassName); + log2(" getting: List classes = vm.classByName(testedClassName);"); + List classes = vm.classesByName(testedClassName); + if (classes.size() != 1) { + log3("ERROR: classes.size() != 1 : " + classes.size()); + testExitCode = FAILED; + break; + } + log2(" getting: ReferenceType testedClass = (ReferenceType) classes.get(0);"); + ReferenceType testedClass = (ReferenceType) classes.get(0); + + + log2("------case for testing: arrays of primitive values"); + + String fieldNames[] = { + "bl1", + "bt1", + "ch1", + "db1", + "fl1" + //"in1", + //"ln1", + //"sh1" + }; + + for (int i1 = 0; i1 < fieldNames.length; i1++) { + + log2("......field tested : " + fieldNames[i1]); + log2(" getting: Field field = testedClass.fieldByName(fieldNames[i1]);"); + Field field = testedClass.fieldByName(fieldNames[i1]); + if (field == null) { + log3("ERROR: field == null"); + testExitCode = FAILED; + continue; + } + log2(" getting: Value value = testedClass.getValue(field);"); + Value value = testedClass.getValue(field); + if (value == null) { + log3("ERROR: value == null"); + testExitCode = FAILED; + continue; + } + try { + log2(" getting Class cast: ObjectReference objectReferenceValue = (ObjectReference) value;"); + ObjectReference objectReferenceValue = (ObjectReference) value; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003/TestDescription.java new file mode 100644 index 00000000000..d2a22dfc0d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/getValue/getvalue003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.getValue() + * complies with its spec: + * public Value getValue(Field field) + * Gets the Value of a given static Field in this type. + * The Field must be valid for this type; that is, it must be declared + * in this type, a superclass, a superinterface, or an implemented interface. + * Parameters: field - the field containing the requested value + * Returns: the Value of the instance field. + * Throws: IllegalArgumentException - + * if the field is not valid for this object's class. + * Case for testing includes arrays of primitive types declared + * in this type, a superclass, a superinterface, and an implemented interface. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.getValue.getvalue003; + * the debuggee program - nsk.jdi.ReferenceType.getValue.getvalue003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test modified due to fix of the bug: + * 4499876 TEST_BUG: ReferenceType.getValue() returns null for ArrayType in interface + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.getValue.getvalue003 + * nsk.jdi.ReferenceType.getValue.getvalue003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.getValue.getvalue003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003a.java new file mode 100644 index 00000000000..1da67aae691 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003a.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalue003 JDI test. + */ + +public class getvalue003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + getvalue003aTestClass testObj = new getvalue003aTestClass(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + +interface getvalue003aInterface1 { + boolean[][][][] bl1 = { {{{true, false}, {true, false}}, {{true, false}, {true, false}} }, + {{{true, false}, {true, false}}, {{true, false}, {true, false}} } }; + byte [][][][] bt1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; +} + +interface getvalue003aInterface0 extends getvalue003aInterface1 { + char [][][][] ch1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; + double [][][][] db1 = { {{{0.0d, 1.0d},{0.0d, 1.0d}}, {{0.0d, 1.0d},{0.0d, 1.0d}}}, + {{{0.0d, 1.0d},{0.0d, 1.0d}}, {{0.0d, 1.0d},{0.0d, 1.0d}}} }; +} + +interface getvalue003aInterface2 { + float [][][][] fl1 = { {{{0.0f, 1.0f},{0.0f, 1.0f}}, {{0.0f, 1.0f},{0.0f, 1.0f}}}, + {{{0.0f, 1.0f},{0.0f, 1.0f}}, {{0.0f, 1.0f},{0.0f, 1.0f}}} }; +} + +class getvalue003aClass1 implements getvalue003aInterface2 { + static int [][][][] in1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; +} + +class getvalue003aTestClass extends getvalue003aClass1 implements getvalue003aInterface0 { + static final long [][][][] ln1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; + static final short [][][][] sh1 = { {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}}, + {{{0, 1},{0, 1}}, {{0, 1},{0, 1}}} }; + + boolean[][][][] bl0; + byte [][][][] bt0; + char [][][][] ch0; + double [][][][] db0; + float [][][][] fl0; + + public getvalue003aTestClass () { + bl0 = bl1; + bt0 = bt1; + ch0 = ch1; + db0 = db1; + fl0 = fl1; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue004.java new file mode 100644 index 00000000000..e02927bdee2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue004.java @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.getValue; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.getValue() + * properly throws IllegalArgumentException - if the field + * is not valid for this object's class.

    + * + * Debuggee part of the test consists of the following classes: + * getvalue004t, getvalue004tDummySuperCls, and + * getvalue004tDummyCls which extends getvalue004tDummySuperCls.
    + * The exception is provoked to be thrown by getting a Value of:
    + *

  • field obtained from the getvalue004tDummyCls but applied to + * reference type of the getvalue004t + *
  • private field obtained from the getvalue004tDummySuperCls + * but applied to reference type of the getvalue004t + */ +public class getvalue004 { + static final String DEBUGGEE_CLASSES[] = { + "nsk.jdi.ReferenceType.getValue.getvalue004t", + "nsk.jdi.ReferenceType.getValue.getvalue004tDummyCls", + "nsk.jdi.ReferenceType.getValue.getvalue004tDummySuperCls" + }; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 58; + + static final int FLD_NUM = 16; + // tested fields used to provoke the exception and + // type reference numbers for obtaining/applying a Field + static final String DEBUGGEE_FLDS[][] = { + {"boolFld", "0", "1"}, + {"byteFld", "0", "1"}, + {"charFld", "0", "1"}, + {"doubleFld", "0", "1"}, + {"floatFld", "0", "1"}, + {"intFld", "0", "1"}, + {"longFld", "0", "1"}, + {"shortFld", "0", "1"}, + {"boolPrFld", "0", "2"}, + {"bytePrFld", "0", "2"}, + {"charPrFld", "0", "2"}, + {"doublePrFld", "0", "2"}, + {"floatPrFld", "0", "2"}, + {"intPrFld", "0", "2"}, + {"longPrFld", "0", "2"}, + {"shortPrFld", "0", "2"} + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getvalue004().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASSES[0]); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "getvalue004t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + ReferenceType[] rType = new ReferenceType[3]; + // debuggee main & dummy classes + rType[0] = debuggee.classByName(DEBUGGEE_CLASSES[0]); + rType[1] = debuggee.classByName(DEBUGGEE_CLASSES[1]); + rType[2] = debuggee.classByName(DEBUGGEE_CLASSES[2]); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + + for (int i=0; icom.sun.jdi.ReferenceType.getValue() + * properly throws IllegalArgumentException for non-static field.

    + * + * The exception is provoked to be thrown by getting a Value of:
    + *

  • protected non-static field + *
  • private non-static field + *
  • package non-static field (default access) + *
  • public non-static field. + */ +public class getvalue005 { + static final String DEBUGGEE_CLASSES[] = { + "nsk.jdi.ReferenceType.getValue.getvalue005t", + "nsk.jdi.ReferenceType.getValue.getvalue005tDummyCls" + }; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 56; + + static final int FLD_NUM = 32; + // tested non-static fields used to provoke the exception + static final String DEBUGGEE_FLDS[] = { + "boolProtFld", + "byteProtFld", + "charProtFld", + "doubleProtFld", + "floatProtFld", + "intProtFld", + "longProtFld", + "shortProtFld", + "boolPrFld", + "bytePrFld", + "charPrFld", + "doublePrFld", + "floatPrFld", + "intPrFld", + "longPrFld", + "shortPrFld", + "boolPubFld", + "bytePubFld", + "charPubFld", + "doublePubFld", + "floatPubFld", + "intPubFld", + "longPubFld", + "shortPubFld", + "boolFld", + "byteFld", + "charFld", + "doubleFld", + "floatFld", + "intFld", + "longFld", + "shortFld" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getvalue005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASSES[0]); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "getvalue005t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + ReferenceType[] rType = new ReferenceType[2]; + // debuggee main & dummy classes + rType[0] = debuggee.classByName(DEBUGGEE_CLASSES[0]); + rType[1] = debuggee.classByName(DEBUGGEE_CLASSES[1]); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + + for (int i=0; i + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.getValues()
    + * complies with its spec.
    + *
    + * Case for testing includes fields mirroring primitive type values
    + * declared in this type, a superclass, a superinterface, and
    + * an implemented interface.
    + * The test checks that Map returned by the method,
    + * contains all the tested variables.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class getvalues001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/getValues/getvalues001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new getvalues001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.getValues.getvalues001a"; + + private String testedClassName = + "nsk.jdi.ReferenceType.getValues.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2(" name of tested class : " + testedClassName); + log2(" getting: List classes = vm.classByName(testedClassName);"); + List classes = vm.classesByName(testedClassName); + if (classes.size() != 1) { + log3("ERROR: classes.size() != 1 : " + classes.size()); + testExitCode = FAILED; + break; + } + log2(" getting: ReferenceType testedClass = (ReferenceType) classes.get(0);"); + ReferenceType testedClass = (ReferenceType) classes.get(0); + + log2("------case for testing: primitive values"); + + String fieldNames[] = { + "bl0", + "bt0", + "ch0", + "db0", + "fl0", + "in0", + "ln0", + "sh0" + }; + + Field [] fArray = { + testedClass.fieldByName(fieldNames[0]), + testedClass.fieldByName(fieldNames[1]), + testedClass.fieldByName(fieldNames[2]), + testedClass.fieldByName(fieldNames[3]), + testedClass.fieldByName(fieldNames[4]), + testedClass.fieldByName(fieldNames[5]), + testedClass.fieldByName(fieldNames[6]), + testedClass.fieldByName(fieldNames[7]), + }; + + log2(" getting: List fields = testedClass.visibleFields();"); + List fields = testedClass.visibleFields(); + + log2(" getting: Map valuesMap = testedClass.getValues(fields);"); + Map valuesMap = testedClass.getValues(fields); + Set keySet = valuesMap.keySet(); + Iterator setIterator = keySet.iterator(); + + int flag = 0; + int controlFlag = 0xFF; + + Field f1 = null; + + log2(" loop of testing the Map"); + + for (int ifor = 0; setIterator.hasNext(); ifor++) { + + f1 = setIterator.next(); + + int flag1 = 0; + for (int ifor1 = 0; ifor1 < fieldNames.length; ifor1++) { + + if (f1.equals(fArray[ifor1])) { + if (flag1 == 0) { + flag1++; + flag |= 1 << ifor1; + break; + } else { + log3("ERROR: duplication in the Map; ifor = " + ifor + " ifor1 = " + ifor1); + testExitCode = FAILED; + } + } + } + } + if (flag != controlFlag) { + log3("ERROR: returned Map object doesn't contain all tested fields"); + testExitCode = FAILED; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001/TestDescription.java new file mode 100644 index 00000000000..50487616499 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/getValues/getvalues001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.getValues() + * complies with its spec: + * public Map getValues(List fields) + * Returns a map containing the Value of each static Field in the given list. + * The Fields must be valid for this type; that is, + * they must be declared in this type, a superclass, a superinterface, or + * an implemented interface. + * Parameters: fields - a list of Field objects containing the requested values. + * Returns: a Map of the requested Field objects with their Value. + * Throws: IllegalArgumentException - + * if any field is not valid for this object's class. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to the same VirtualMachine. + * Case for testing includes fields mirroring primitive type values + * declared in this type, a superclass, a superinterface, and an implemented interface. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.getValues.getvalues001; + * the debuggee program - nsk.jdi.ReferenceType.getValues.getvalues001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.getValues.getvalues001 + * nsk.jdi.ReferenceType.getValues.getvalues001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.getValues.getvalues001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001a.java new file mode 100644 index 00000000000..496d838083e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001a.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getvalues001 JDI test. + */ + +public class getvalues001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + TestClass testObj = new TestClass(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + +interface Interface1 { + char ch0 = 0; + double db0 = 0.0d; +} +interface Interface0 extends Interface1 { + boolean bl0 = false; + byte bt0 = 0; +} +interface Interface2 { + long ln0 = 0; +} +class Class1 implements Interface2 { + static short sh0 = 0; +} +class TestClass extends Class1 implements Interface0 { + static float fl0 = 0.0f; + static int in0 = 0; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002.java new file mode 100644 index 00000000000..d0370d4ca34 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.getValues; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.getValues() + * properly throws IllegalArgumentException - if any field is + * not valid for this object's class.

    + * + * Debuggee part of the test consists of the following classes: + * getvalues002t, getvalues002tDummySuperCls, and + * getvalues002tDummyCls which extends getvalues002tDummySuperCls.
    + * The exception is provoked to be thrown by getting a Map of values + * which correspond to a list containing some wrong fields such as:
    + *

  • fields obtained from the getvalues002tDummyCls but applied to + * reference type of the getvalues002t + *
  • some non-static fields from the getvalues002tDummyCls applied to + * its reference type. + */ +public class getvalues002 { + static final String DEBUGGEE_CLASSES[] = { + "nsk.jdi.ReferenceType.getValues.getvalues002t", + "nsk.jdi.ReferenceType.getValues.getvalues002tDummyCls", + "nsk.jdi.ReferenceType.getValues.getvalues002tDummySuperCls" + }; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 58; + + static final int LST_NUM = 2; // number of lists + static final int FLD_NUM = 8; // number of fields in particular list + // tested fields used to provoke the exception and + // type reference numbers for applying/obtaining a Field + static final String DEBUGGEE_FLDS[][][] = { + {{"boolFld", "0", "1", "static"}, + {"byteFld", "0", "1", "static"}, + {"charFld", "0", "1", "static"}, + {"doubleFld", "0", "1", "static"}, + {"floatFld", "0", "1", "static"}, + {"intFld", "0", "1", "static"}, + {"longFld", "0", "1", "static"}, + {"shortFld", "0", "1", "static"}}, + + {{"boolMiscFld", "1", "1", "static"}, + {"byteMiscFld", "1", "1", "static"}, + {"charMiscFld", "1", "1", "wrong non-static"}, + {"doubleMiscFld", "1", "1", "static"}, + {"floatMiscFld", "1", "1", "static"}, + {"intMiscFld", "1", "1", "static"}, + {"longMiscFld", "1", "1", "wrong non-static"}, + {"shortMiscFld", "1", "1", "static"}} + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getvalues002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASSES[0]); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "getvalues002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + ReferenceType[] rType = new ReferenceType[3]; + // debuggee main & dummy classes + rType[0] = debuggee.classByName(DEBUGGEE_CLASSES[0]); + rType[1] = debuggee.classByName(DEBUGGEE_CLASSES[1]); + rType[2] = debuggee.classByName(DEBUGGEE_CLASSES[2]); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + + for (int l=0; l flds = new ArrayList(); + int appIx = 0; + int obtIx = 0; + + + for (int i=0; i valMap = rType[appIx].getValues(flds); + + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to get a Map containing Value of each field in the list" + + "\n\t\tusing reference type \"" + + rType[appIx] + "\",\n\t\tand some of the fields are not valid"); + tot_res = Consts.TEST_FAILED; + } catch (IllegalArgumentException ee) { + log.display("CHECK PASSED: caught expected " + ee); + } catch (Exception ue) { + ue.printStackTrace(); + log.complain("TEST FAILED: caught unexpected " + + ue + "\n\tinstead of expected IllegalArgumentException" + + "\n\twhen attempted to get a Map containing Value of each field in the list" + + "\"\n\t\tusing reference type \"" + + rType[appIx] + "\",\n\t\tand some of the fields are not valid"); + tot_res = Consts.TEST_FAILED; + } + + } + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + BPreq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("\nFinal resumption of the debuggee VM"); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002/TestDescription.java new file mode 100644 index 00000000000..a50dcc4adc9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/getValues/getvalues002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ReferenceType.getValues() + * properly throws IllegalArgumentException - if any field is + * not valid for this object's class. + * Debuggee part of the test consists of the following classes: + * "getvalues002t", "getvalues002tDummySuperCls", and "getvalues002tDummyCls" + * which extends getvalues002tDummySuperCls. + * The exception is provoked to be thrown by getting a Map of values + * which correspond to a list containing some wrong fields such as: + * - fields obtained from the getvalues002tDummyCls but applied to + * reference type of the getvalues002t; + * - some non-static fields from the getvalues002tDummyCls applied to + * its reference type. + * COMMENTS + * 4772094 JDI: ReferenceType.getValue() allows to get value of a private field + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.getValues.getvalues002 + * nsk.jdi.ReferenceType.getValues.getvalues002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.getValues.getvalues002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002t.java new file mode 100644 index 00000000000..f174f6cf241 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues002t.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is debuggee class. + */ +public class getvalues002t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // force debuggee VM to load dummy classes + getvalues002tDummySuperCls dummySuperCls = + new getvalues002tDummySuperCls(); + getvalues002tDummyCls dummyCls = + new getvalues002tDummyCls(); + + pipe.println(getvalues002.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(getvalues002.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command: " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // getvalues002.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(getvalues002.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + return Consts.TEST_FAILED; + } + return Consts.TEST_PASSED; + } +} + +// dummy super class used for provoking IllegalArgumentException in debugger +class getvalues002tDummySuperCls { + private static boolean boolPrFld = false; + private static byte bytePrFld = 127; + private static char charPrFld = 'b'; + private static double doublePrFld = 6.2D; + private static float floatPrFld = 5.1F; + private static int intPrFld = 2147483647; + private static long longPrFld = 9223372036854775807L; + private static short shortPrFld = -32768; +} + +// dummy class used for provoking IllegalArgumentException in debugger +class getvalues002tDummyCls extends getvalues002tDummySuperCls { + static boolean boolFld = false; + static byte byteFld = 127; + static char charFld = 'a'; + static double doubleFld = 6.2D; + static float floatFld = 5.1F; + static int intFld = 2147483647; + static long longFld = 9223372036854775807L; + static short shortFld = -32768; + + static boolean boolMiscFld = true; + static byte byteMiscFld = Byte.MIN_VALUE; + protected char charMiscFld = 'c'; + static double doubleMiscFld = Double.MAX_VALUE; + static float floatMiscFld = Float.MAX_VALUE; + static int intMiscFld = Integer.MIN_VALUE; + long longMiscFld = Long.MIN_VALUE; + static short shortMiscFld = Short.MAX_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003.java new file mode 100644 index 00000000000..c93be1803a5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003.java @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.getValues; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.getValues() + * properly throws IllegalArgumentException - if any field is + * not valid for this object's class.

    + * + * Debuggee part of the test consists of the following classes: + * getvalues003t inside a main package, and getvalues003ta + * outside the package.
    + * The exception is provoked to be thrown by getting a Map of values + * which correspond to a list containing wrong fields such as:
    + *

  • private fields obtained from the getvalues003ta but applied to + * reference type of the getvalues003t + *
  • default-access fields from the getvalues003ta but applied to + * reference type of the getvalues003t + *
  • protected fields from the getvalues003ta but applied to reference + * type of the getvalues003t. + */ +public class getvalues003 { + static final String DEBUGGEE_CLASSES[] = { + "nsk.jdi.ReferenceType.getValues.getvalues003t", + "nsk.jdi.ReferenceType.dummyPackage.getvalues003a" + }; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 56; + + static final int LST_NUM = 3; // number of lists + static final int FLD_NUM = 8; // number of fields in particular list + // tested fields used to provoke the exception and + // type reference numbers for applying/obtaining a Field + static final String DEBUGGEE_FLDS[][][] = { + {{"boolFld", "0", "1", "default-access"}, + {"byteFld", "0", "1", "default-access"}, + {"charFld", "0", "1", "default-access"}, + {"doubleFld", "0", "1", "default-access"}, + {"floatFld", "0", "1", "default-access"}, + {"intFld", "0", "1", "default-access"}, + {"longFld", "0", "1", "default-access"}, + {"shortFld", "0", "1", "default-access"}}, + + {{"boolPrFld", "0", "1", "private"}, + {"bytePrFld", "0", "1", "private"}, + {"charPrFld", "0", "1", "private"}, + {"doublePrFld", "0", "1", "private"}, + {"floatPrFld", "0", "1", "private"}, + {"intPrFld", "0", "1", "private"}, + {"longPrFld", "0", "1", "private"}, + {"shortPrFld", "0", "1", "private"}}, + + {{"boolProtFld", "0", "1", "protected"}, + {"byteProtFld", "0", "1", "protected"}, + {"charProtFld", "0", "1", "protected"}, + {"doubleProtFld", "0", "1", "protected"}, + {"floatProtFld", "0", "1", "protected"}, + {"intProtFld", "0", "1", "protected"}, + {"longProtFld", "0", "1", "protected"}, + {"shortProtFld", "0", "1", "protected"}} + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getvalues003().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASSES[0]); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "getvalues003t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + ReferenceType[] rType = new ReferenceType[2]; + // debuggee main & dummy classes + rType[0] = debuggee.classByName(DEBUGGEE_CLASSES[0]); + rType[1] = debuggee.classByName(DEBUGGEE_CLASSES[1]); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType[0], DEBUGGEE_STOPATLINE); + + for (int l=0; l flds = new ArrayList(); + int appIx = 0; + int obtIx = 0; + + + for (int i=0; i valMap = rType[appIx].getValues(flds); + + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to get a Map containing Value of each field in the list" + + "\n\t\tusing reference type \"" + + rType[appIx] + "\",\n\t\tand the fields are not valid"); + tot_res = Consts.TEST_FAILED; + } catch (IllegalArgumentException ee) { + log.display("CHECK PASSED: caught expected " + ee); + } catch (Exception ue) { + ue.printStackTrace(); + log.complain("TEST FAILED: caught unexpected " + + ue + "\n\tinstead of expected IllegalArgumentException" + + "\n\twhen attempted to get a Map containing Value of each field in the list" + + "\"\n\t\tusing reference type \"" + + rType[appIx] + "\",\n\t\tand the fields are not valid"); + tot_res = Consts.TEST_FAILED; + } + + } + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + BPreq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + +// Class containing a critical section which may lead to time out of the test + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("\nFinal resumption of the debuggee VM"); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003/TestDescription.java new file mode 100644 index 00000000000..d21d135747a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/getValues/getvalues003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method + * com.sun.jdi.ReferenceType.getValues() + * properly throws IllegalArgumentException - if any field is + * not valid for this object's class. + * Debuggee part of the test consists of the following classes: + * "getvalues003t" inside a main package, and "getvalues003a" outside + * the package. + * The exception is provoked to be thrown by getting a Map of values + * which correspond to a list containing wrong fields such as: + * - private fields obtained from the getvalues003ta + * but applied to reference type of the getvalues003t; + * - default-access fields from the getvalues003ta + * but applied to reference type of the getvalues003t; + * - protected fields from the getvalues003ta + * but applied to reference type of the getvalues003t. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.getValues.getvalues003 + * nsk.jdi.ReferenceType.getValues.getvalues003t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.getValues.getvalues003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003t.java new file mode 100644 index 00000000000..2def2d53993 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues003t.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is debuggee class. + */ +public class getvalues003t { + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // force debuggee VM to load dummy class + nsk.jdi.ReferenceType.dummyPackage.getvalues003a dummyCls = + new nsk.jdi.ReferenceType.dummyPackage.getvalues003a(); + + pipe.println(getvalues003.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(getvalues003.COMMAND_QUIT)) { + System.err.println("Debuggee: exiting due to the command: " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // getvalues003.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + if (!cmd.equals(getvalues003.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + return Consts.TEST_FAILED; + } + return Consts.TEST_PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001.java new file mode 100644 index 00000000000..558d081fafc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method hashCode() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class hashcode001 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.hashCode.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "hashcode001", + debugeeName = thisClassName + "a"; + + private final static String primitive_type_sign = "primitive_type"; + private final static String reference_type_sign = "reference_type"; + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + {"boolean", primitive_type_sign}, + {"byte" , primitive_type_sign}, + {"char" , primitive_type_sign}, + {"double" , primitive_type_sign}, + {"float" , primitive_type_sign}, + {"int" , primitive_type_sign}, + {"long" , primitive_type_sign}, + + {"java.lang.Boolean" , reference_type_sign}, + {"java.lang.Byte" , reference_type_sign}, + {"java.lang.Character", reference_type_sign}, + {"java.lang.Double" , reference_type_sign}, + {"java.lang.Float" , reference_type_sign}, + {"java.lang.Integer" , reference_type_sign}, + {"java.lang.Long" , reference_type_sign}, + {"java.lang.String" , reference_type_sign}, + {"java.lang.Object" , reference_type_sign}, + + {package_prefix + "ClassForCheck", reference_type_sign}, + {package_prefix + "InterfaceForCheck", reference_type_sign}, + + {debugeeName+"$s_class", reference_type_sign}, + {debugeeName+"$s_interf", reference_type_sign} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new hashcode001().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/hashCode/hashcode001 test FAILED"); + } + else { + print_log_anyway("\n==> nsk/jdi/ReferenceType/hashCode/hashcode001 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/hashCode/hashcode001 test LOG:"); + print_log_anyway("==> test checks the hashCode() method of ReferenceType interface"); + print_log_anyway(" of the com.sun.jdi package for ArrayType, ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> hashcode001: hashcode001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway("##> hashcode001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway("##> hashcode001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> hashcode001: debugee's \"ready\" signal recieved!"); + } + + print_log_anyway + ("--> hashcode001: check ReferenceType.hashCode() method for debugee's classes..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int hashCode_method_exceptions = 0; + int hashCode_method_errors = 0; + for (int i=0; i hashcode001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + int hash_code_1 = 0; + try { + hash_code_1 = refType_1.hashCode(); + } + catch (Throwable thrown) { + print_log_anyway + ("##> hashcode001: FAILED: refType_1.hashCode() threw unexpected exception - " + + thrown); + print_log_anyway + ("##> refType_1 = " + refType_1); + hashCode_method_exceptions++; + continue; + } + ReferenceType refType_2 = debugee.classByName(className); + int hash_code_2 = 0; + try { + hash_code_2 = refType_2.hashCode(); + } + catch (Throwable thrown) { + print_log_anyway + ("##> hashcode001: FAILED: refType_2.hashCode() threw unexpected exception - " + + thrown); + print_log_anyway + ("##> refType_2 = " + refType_2); + hashCode_method_exceptions++; + continue; + } + if ( hash_code_1 != hash_code_2 ) { + print_log_anyway + ("##> hashcode001: FAILED: hashCode() returned unequals values for equals ReferenceType instances:"); + print_log_anyway + ("##> refType_1 = " + refType_1 + "#" + hash_code_1); + print_log_anyway + ("##> refType_2 = " + refType_2 + "#" + hash_code_2); + hashCode_method_errors++; + } + else { + print_log_on_verbose + ("--> hashcode001: PASSED: hashCode() returned equals values for equals ReferenceType instances:"); + print_log_on_verbose + ("--> refType_1 = " + refType_1 + "#" + hash_code_1); + print_log_on_verbose + ("--> refType_2 = " + refType_2 + "#" + hash_code_2); + } + } + } + print_log_anyway("--> hashcode001: check completed!"); + print_log_anyway("--> hashcode001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + print_log_anyway("##> hashcode001: \"class not found ERRORS\" number = " + + class_not_found_errors); + } + if ( hashCode_method_exceptions > 0 ) { + print_log_anyway("##> hashcode001: number of unexpected hashCode() methods exceptions = " + + hashCode_method_exceptions); + } + print_log_anyway("##> hashcode001: hashCode() method errors number = " + + hashCode_method_errors); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + hashCode_method_errors + hashCode_method_exceptions > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> hashcode001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway("##> hashcode001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> hashcode001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..319e9c1d340 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/hashCode/hashcode001 test + * checks the hashCode() method of ReferenceType interface + * of the com.sun.jdi package for ArrayType, ClassType, InterfaceType: + * For each checked debugee's class the test gets two ReferenceType + * instances for this class and gets the hash code values for these + * ReferenceType instances by hashCode() method. + * The test expects that returned hash code values should be equal. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.hashCode.hashcode001 + * nsk.jdi.ReferenceType.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java new file mode 100644 index 00000000000..4b402d515bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the hashcode001 JDI test. + */ + +public class hashcode001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + static class s_class {} + s_class s_class_0 = new s_class(), s_class_1[]={s_class_0}, + s_class_2[][]={s_class_1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + static interface s_interf {} + static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl(); + s_interf s_interf_0, s_interf_1[]={s_interf_0}, s_interf_2[][]={s_interf_1}; + + ClassForCheck class_for_check0 = new ClassForCheck(), + class_for_check1[]={class_for_check0}, + class_for_check2[][]={class_for_check1}; + InterfaceForCheck_impl interf_for_check_impl0 = new InterfaceForCheck_impl(); + InterfaceForCheck interf_for_check0,interf_for_check1[]={interf_for_check0}, interf_for_check2[][]={interf_for_check1}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i hashcode001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + hashcode001a hashcode001a_obj = new hashcode001a(); + + print_log_on_verbose("**> hashcode001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> hashcode001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> hashcode001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> hashcode001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> hashcode001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class ClassForCheck { + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + static long[] s_prim_array_field; + static Object[] s_ref_array_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + long[] i_prim_array_field; + Object[] i_ref_array_field; +} + +interface InterfaceForCheck { + static final boolean s_interf_boolean_field = true; + static final byte s_interf_byte_field = (byte)1; + static final char s_interf_char_field = '1'; + static final double s_interf_double_field = 999; + static final float s_interf_float_field = 99; + static final int s_interf_int_field = 100; + static final long s_interf_long_field = 1000; + static final Object s_interf_object_field = new Object(); +} + +class InterfaceForCheck_impl implements InterfaceForCheck {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002.java new file mode 100644 index 00000000000..d1c4b24a5ca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method hashCode() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class hashcode002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.hashCode.", + thisClassName = package_prefix + "hashcode002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "hashcode002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new hashcode002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/hashCode/hashcode002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/hashCode/hashcode002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/hashCode/hashcode002 test LOG:"); + print_log_anyway("--> test checks hashCode() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> hashcode002: hashcode002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> hashcode002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> hashcode002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> hashcode002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> hashcode002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> hashcode002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> hashcode002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean hashCode_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> hashcode002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> hashcode002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> hashcode002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> hashcode002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> hashcode002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> hashcode002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> hashcode002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.hashCode() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> hashcode002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> hashcode002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> hashcode002: check that checked class has been unloaded really..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> hashcode002: checked class has been unloaded really: " + checked_class); + } + else { + print_log_without_verbose + ("--> hashcode002: check that checked class has been unloaded really..."); + print_log_anyway + ("--> hashcode002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.hashCode() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> hashcode002: check ReferenceType.hashCode() method for unloaded class..."); + int hash_code = 0; + try { + hash_code = refType.hashCode(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> hashcode002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> hashcode002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + hashCode_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || hashCode_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> hashcode002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> hashcode002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> hashcode002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of hashcode002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TestDescription.java new file mode 100644 index 00000000000..fc31d0724c0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/hashCode/hashcode002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/hashCode/hashcode002 test + * checks the hashCode() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * hashCode() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - hashcode002b class was moved in 'loadclass' subdirectory; + * - package name was added in hashcode002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for hashcode002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.hashCode.hashcode002 + * nsk.jdi.ReferenceType.hashCode.hashcode002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.hashCode.hashcode002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/loadclass/hashcode002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/loadclass/hashcode002b.java new file mode 100644 index 00000000000..dc350ca791b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002/loadclass/hashcode002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the hashCode() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.hashCode; + +class hashcode002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002a.java new file mode 100644 index 00000000000..f72a629b8a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.hashCode; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the hashcode002 JDI test. + */ + +public class hashcode002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.hashCode."; + private final static String checked_class_name = package_prefix + "hashcode002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> hashcode002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> hashcode002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> hashcode002a: checked class loaded: " + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> hashcode002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> hashcode002a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> hashcode002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> hashcode002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> hashcode002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> hashcode002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> hashcode002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> hashcode002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> hashcode002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> hashcode002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> hashcode002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> hashcode002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> hashcode002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> hashcode002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> hashcode002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> hashcode002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of hashcode002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances001/instances001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances001/instances001.java new file mode 100644 index 00000000000..d7d166e2898 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances001/instances001.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/instances/instances001. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test checks behaviour of ReferenceType.instances, VirtualMachine.instanceCounts + * in cases when object is reacheable via following types of references: + * - strong + * - soft + * - weak + * - phantom + * - jni local + * - jni global + * - jni weak + * Test is executed for following subclasses of ReferenceType: + * - ArrayType + * - InterfaceType(for InterfaceType methof instances() should always return empty list) + * The test scenario is following: + * - Debugger VM + * - inititate creation instances of sublcass of tested class to ensure that instances of subclasses are not returned by ReferenceType.instances() + * - Debugger VM + * for refererence_type in + * do + * - initiate creation test class instances of type 'refererence_type' + * - check the number of instances is correct + * - initiate deletion of some referreres(making them unreachable) + * - check the number of instances is correct + * done + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.instances.instances001.instances001 + * nsk.share.jdi.TestClass1 + * nsk.share.jdi.TestClass2 + * nsk.share.jdi.TestInterfaceImplementer1 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ReferenceType.instances.instances001.instances001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ReferenceType.instances.instances001; + +import java.io.PrintStream; +import java.util.*; +import com.sun.jdi.*; + +import nsk.share.Consts; +import nsk.share.ObjectInstancesManager; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdi.HeapwalkingDebugger; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class instances001 extends HeapwalkingDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new instances001().runIt(argv, out); + } + + protected String debuggeeClassName() { + return nsk.share.jdi.HeapwalkingDebuggee.class.getName(); + } + + // test given class with all references types + protected void testClass(String className) { + // force GC in debugee VM to avoid collection of weak references during test execution + forceGC(); + + for (String referrerType : ObjectInstancesManager.allReferenceTypes) { + testReferrerType(referrerType, className); + if (ObjectInstancesManager.isWeak(referrerType)) { + // if GC occurs during test the results should be ignored + resetStatusIfGC(); + } + } + } + + protected void testReferrerType(String referrerType, String className) { + int createInstanceCount = 50; + int baseCount = 0; + + ReferenceType referenceType = debuggee.classByName(className); + + // object number created in target VM before debugger command should be filtered + if (referenceType != null) { + List objectReferences = referenceType.instances(0); + + // disable GC because of uncontrolled object deletion may break test checks + for (ObjectReference objectReference : objectReferences) + objectReference.disableCollection(); + + baseCount = objectReferences.size(); + } + + boolean isIncludedIntoInstancesCount = HeapwalkingDebuggee.isIncludedIntoInstancesCount(referrerType); + + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + className + ":" + createInstanceCount + ":" + 1 + ":" + referrerType); + + int expectedCount; + + if (isIncludedIntoInstancesCount) + expectedCount = baseCount + createInstanceCount; + else + expectedCount = baseCount; + + checkDebugeeAnswer_instanceCounts(className, expectedCount); + checkDebugeeAnswer_instances(className, expectedCount); + + //delete half of instances + + int deleteCount = createInstanceCount / 2; + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + className + ":" + deleteCount); + + createInstanceCount -= deleteCount; + + if (isIncludedIntoInstancesCount) + expectedCount = baseCount + createInstanceCount; + else + expectedCount = baseCount; + + checkDebugeeAnswer_instanceCounts(className, expectedCount); + checkDebugeeAnswer_instances(className, expectedCount); + + //delete all instances + + deleteCount = createInstanceCount; + + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + className + ":" + deleteCount); + + if (isIncludedIntoInstancesCount) + expectedCount = baseCount; + else + expectedCount = baseCount; + + checkDebugeeAnswer_instanceCounts(className, expectedCount); + checkDebugeeAnswer_instances(className, expectedCount); + } + + // also check number of instanes for InterfaceType + protected void checkDebugeeAnswer_instances(String className, int expectedInstances) { + super.checkDebugeeAnswer_instances(className, expectedInstances); + + ReferenceType referenceType = debuggee.classByName(className); + + // check number of instances for InterfaceType(should be 0) + if (referenceType instanceof ClassType) { + ClassType classType = (ClassType) referenceType; + + for (InterfaceType interfaceType : classType.interfaces()) { + checkDebugeeAnswer_InterfaceType_instances(interfaceType, 0); + } + } + } + + // ArrayType, ClassType and InterfaceType are tested here + protected void doTest() { + String testClassName = "nsk.share.jdi.TestClass1"; + String testClassSubclassName = "nsk.share.jdi.TestClass2"; + + int subclassInstanceCount = 10; + + String testClasses[] = { testClassName, "nsk.share.jdi.TestInterfaceImplementer1", "boolean[]", "float[]" }; + + // create instances of 'nsk.share.jdi.TestClass1' subclass to ensure that instances of subclasses are not returned by ReferenceType.instances() + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + testClassSubclassName + ":" + subclassInstanceCount); + + checkDebugeeAnswer_instanceCounts(testClassSubclassName, subclassInstanceCount); + checkDebugeeAnswer_instances(testClassSubclassName, subclassInstanceCount); + + for (String className : testClasses) { + testClass(className); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java new file mode 100644 index 00000000000..adf38b27e38 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/instances/instances002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test scenario is following: + * - Debugger VM + * - initiate creation a number of instances in debuggee VM using ClassType.newInstance + * - check the number of instances is correct + * - initiate creation a number of instances in debuggee VM using ArrayType.newInstance + * - check the number of instances is correct + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.instances.instances002.instances002 + * nsk.jdi.ReferenceType.instances.instances002.instances002a + * nsk.share.jdi.TestClass1 + * nsk.share.jdi.TestInterfaceImplementer1 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ReferenceType.instances.instances002.instances002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ReferenceType.instances.instances002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import nsk.share.Consts; +import nsk.share.ObjectInstancesManager; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdi.HeapwalkingDebugger; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class instances002 extends HeapwalkingDebugger { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new instances002().runIt(argv, out); + } + + protected boolean canRunTest() { + return super.canRunTest() || (!vm.canBeModified()); + } + + protected String debuggeeClassName() { + return nsk.jdi.ReferenceType.instances.instances002.instances002a.class.getName(); + } + + // create instance of ReferenceType + public ReferenceType prepareReferenceType(String className, int instanceCount) { + String referrerType = ObjectInstancesManager.STRONG_REFERENCE; + + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + className + ":" + instanceCount + ":" + "1" + ":" + referrerType); + + if (!isDebuggeeReady()) + return null; + + return debuggee.classByName(className); + } + + // test method ArrayType.newInstance + public void testArrayType(String className) { + // create some instances in target VM, just to get ReferenceType object + int baseInstances = 10; + + ReferenceType referenceType = prepareReferenceType(className, baseInstances); + + if (referenceType == null) + return; + + if (!(referenceType instanceof ArrayType)) { + setSuccess(false); + log.complain("Unexpected reference type: " + referenceType.getClass().getName() + ", expected is ArrayType"); + return; + } + + baseInstances = referenceType.instances(0).size(); + + int createInstanceCount = 100; + int arraySize = 1; + + ArrayType arrayType = (ArrayType) referenceType; + List objectReferences = new ArrayList(); + + for (int i = 0; i < createInstanceCount; i++) { + // instances created in this way aren't reachable for the purposes of garbage collection, + // to make it reachable call disableCollection() for this objects + ArrayReference arrayReference = arrayType.newInstance(arraySize); + arrayReference.disableCollection(); + + objectReferences.add(arrayReference); + } + + checkDebugeeAnswer_instances(className, createInstanceCount + baseInstances); + + for (ArrayReference arrayReference : objectReferences) + arrayReference.enableCollection(); + } + + // test method ClassType.newInstance + public void testClassType(String className) { + // create some instances in target VM, just to get ReferenceType object + int baseInstances = 10; + + ReferenceType referenceType = prepareReferenceType(className, baseInstances); + + if (referenceType == null) + return; + + if (!(referenceType instanceof ClassType)) { + setSuccess(false); + log.display("Unexpected reference type: " + referenceType.getClass().getName() + ", expected is ClassType"); + return; + } + + baseInstances = referenceType.instances(0).size(); + + ClassType classType = (ClassType) referenceType; + + pipe.println(AbstractDebuggeeTest.COMMAND_FORCE_BREAKPOINT); + + BreakpointEvent breakpointEvent = waitForBreakpoint(defaultBreakpointRequest); + + List methods = referenceType.allMethods(); + List objectReferences = new ArrayList(); + + int createInstanceCount = 100; + + try { + for (Method method : methods) { + if (method.isConstructor()) { + for (int i = 0; i < createInstanceCount; i++) { + objectReferences.add(classType.newInstance(breakpointEvent.thread(), method, new ArrayList(), 0)); + } + + checkDebugeeAnswer_instances(className, baseInstances); + + break; + } + } + } catch (Exception e) { + setSuccess(false); + log.display("Unexpected exception: "); + e.printStackTrace(log.getOutStream()); + } + + debuggee.resume(); + + // wait response for command 'COMMAND_FORCE_BREAKPOINT' + if (!isDebuggeeReady()) + return; + + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + className + ":" + baseInstances); + + if (!isDebuggeeReady()) + return; + + checkDebugeeAnswer_instances(className, 0); + } + + protected void doTest() { + initDefaultBreakpoint(); + + String[] testClasses = { "nsk.share.jdi.TestClass1", "nsk.share.jdi.TestInterfaceImplementer1" }; + + for (String className : testClasses) + testClassType(className); + + for (String className : ObjectInstancesManager.primitiveArrayClassNames) + testArrayType(className); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002a.java new file mode 100644 index 00000000000..6a4643dce9a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002a.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ReferenceType.instances.instances002; + +import nsk.share.jdi.*; + +public class instances002a extends HeapwalkingDebuggee { + public final static String MAIN_THREAD_NAME = "instances002a_MainThread"; + + protected String[] doInit(String args[]) { + Thread.currentThread().setName(MAIN_THREAD_NAME); + + return args; + } + + public static void main(String args[]) { + new instances002a().doTest(args); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances003/instances003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances003/instances003.java new file mode 100644 index 00000000000..fdb07c6c85c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances003/instances003.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/instances/instances003. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test scenario is following: + * - Debugger VM + * for refererence_type in + * - initiate creation test class instances of type 'refererence_type' in debuggee VM + * - prevent some instances from being garbage collected using ObjectReference.disableCollection + * - initiate GarbageCollection in Debuggee VM + * - check the number of instances is left is correct + * - enables Garbage Collection for instances for which it were previously disabled using ObjectReference.enableCollection + * - initiate GarbageCollection in Debuggee VM + * - check the number of instances is 0 + * done + * Test is executed for following sublcasses of ObjectReference: StringReference, ThreadReference, ClassLoaderReference + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.instances.instances003.instances003 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ReferenceType.instances.instances003.instances003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + * -testClassNames nsk.jdi.ReferenceType.instances.instances003.instances003$TestClassLoader:java.lang.String:java.lang.Thread + */ + +package nsk.jdi.ReferenceType.instances.instances003; + +import java.io.PrintStream; +import java.util.*; + +import com.sun.jdi.ObjectReference; +import com.sun.jdi.ReferenceType; + +import nsk.share.Consts; +import nsk.share.ObjectInstancesManager; +import nsk.share.TestBug; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdi.HeapwalkingDebugger; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class instances003 extends HeapwalkingDebugger { + // use subclass of java.lang.ClassLoader to be sure that there are no its instances in debuggee VM + public static class TestClassLoader extends ClassLoader { + + } + + private String testClasses[]; + + protected String[] doInit(String[] args, PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testClassNames") && (i < args.length - 1)) { + testClasses = args[i + 1].split(":"); + + i++; + } else + standardArgs.add(args[i]); + } + + if ((testClasses == null) || (testClasses.length == 0)) + throw new TestBug("Test class names was not specified, use test parameter '-testClassNames'"); + + return standardArgs.toArray(new String[] {}); + } + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new instances003().runIt(argv, out); + } + + protected String debuggeeClassName() { + return nsk.share.jdi.HeapwalkingDebuggee.class.getName(); + } + + protected void testClass(String className, String referrerType) { + final int createInstanceCount = 50; + final int referrerCount = 1; + + List objectsToFilter = HeapwalkingDebugger.getObjectReferences(className, vm); + + // create 'createInstanceCount' instances of test class + + // create temporary strong references to prevent the weakly referred instances being GCed + // during the time between creating them and disabling collection on them + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + className + ":" + createInstanceCount + + ":" + referrerCount + ":" + referrerType + + (referrerType.equals(ObjectInstancesManager.WEAK_REFERENCE) ? "|" + ObjectInstancesManager.STRONG_REFERENCE : "")); + + // the instance counts should not be affected by creating multiple references + checkDebugeeAnswer_instanceCounts(className, createInstanceCount, objectsToFilter); + + ReferenceType referenceType = debuggee.classByName(className); + List instances = HeapwalkingDebugger.filterObjectReferrence(objectsToFilter, referenceType.instances(0)); + + for (ObjectReference or : instances) { + or.disableCollection(); + } + + // remove the temporary strong references so the weak references can be properly tested + if (referrerType.equals(ObjectInstancesManager.WEAK_REFERENCE)) { + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_REFERRERS + ":" + className + ":" + referrerCount + ":" + ObjectInstancesManager.STRONG_REFERENCE); + if (!isDebuggeeReady()) { + return; + } + } + + // prevent half of instances from GC, delete references and force GC + + int preventGCCount = createInstanceCount / 2; + + for (int i = 0; i < preventGCCount; i++) { + instances.get(i).enableCollection(); + } + + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + className + ":" + createInstanceCount); + + if (!isDebuggeeReady()) + return; + + pipe.println(AbstractDebuggeeTest.COMMAND_FORCE_GC); + + checkDebugeeAnswer_instanceCounts(className, createInstanceCount - preventGCCount, objectsToFilter); + + // enable garbage collection for all instances and force GC + + for (ObjectReference reference : referenceType.instances(0)) { + reference.enableCollection(); + } + + pipe.println(AbstractDebuggeeTest.COMMAND_FORCE_GC); + + checkDebugeeAnswer_instanceCounts(className, 0, objectsToFilter); + } + + protected void doTest() { + for (String referenceType : HeapwalkingDebuggee.includedIntoInstancesCountTypes) { + for (String className : testClasses) + testClass(className, referenceType); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances004/TestDescription.java new file mode 100644 index 00000000000..a642a73d031 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances004/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/instances/instances004. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test scenario is following: + * - Debugger VM + * for refererence_type in + * - initiate creation test class instances of type 'refererence_type' in debuggee VM + * - prevent some instances from being garbage collected using ObjectReference.disableCollection + * - initiate GarbageCollection in Debuggee VM + * - check the number of instances is left is correct + * - enables Garbage Collection for instances for which it were previously disabled using ObjectReference.enableCollection + * - initiate GarbageCollection in Debuggee VM + * - check the number of instances is 0 + * done + * Test is executed for following sublcass of ObjectReference: ArrayReference + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.instances.instances003.instances003 + * nsk.share.jdi.TestClass1 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ReferenceType.instances.instances003.instances003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + * -testClassNames nsk.share.jdi.TestClass1:boolean[]:float[] + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances005/instances005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances005/instances005.java new file mode 100644 index 00000000000..254d7da40c6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/instances/instances005/instances005.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/instances/instances005. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test checks behavior of ReferenceType.instances() in case when there are many + * instances (several thousands) of corresponding ReferenceType in debuggee VM. + * Debugger forces debuggee VM create 100000 (this value can be changed through parameter -instanceCount) instances + * of 'nsk.share.jdi.TestClass1', obtains ReferenceType for 'nsk.share.jdi.TestClass1' and checks that ReferenceType.instances() + * returns collection with correct size and returned instances doesn't throw any exception when call following methods: + * referenceType() + * isCollected() + * uniqueID() + * hashCode() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.instances.instances005.instances005 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ReferenceType.instances.instances005.instances005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ReferenceType.instances.instances005; + +import java.io.PrintStream; +import java.util.*; +import com.sun.jdi.*; + +import nsk.share.Consts; +import nsk.share.ObjectInstancesManager; +import nsk.share.jdi.HeapwalkingDebuggee; +import nsk.share.jdi.HeapwalkingDebugger; +import nsk.share.jdi.TestClass1; + +public class instances005 extends HeapwalkingDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + private int instanceCount = 100000; + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-instanceCount") && (i < args.length - 1)) { + instanceCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + public static int run(String argv[], PrintStream out) { + return new instances005().runIt(argv, out); + } + + protected String debuggeeClassName() { + return HeapwalkingDebuggee.class.getName(); + } + + protected void doTest() { + String className = TestClass1.class.getName(); + + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + className + ":" + instanceCount + ":" + 1 + + ":" + ObjectInstancesManager.STRONG_REFERENCE); + + checkDebugeeAnswer_instanceCounts(className, instanceCount); + checkDebugeeAnswer_instances(className, instanceCount); + + ReferenceType referenceType = debuggee.classByName(className); + List instances = referenceType.instances(0); + + vm.suspend(); + + for (ObjectReference instance : instances) { + try { + if (!referenceType.equals(instance.referenceType())) { + setSuccess(false); + log.complain("Instance's ReferenceType " + instance.referenceType() + " doesn't equal " + + referenceType); + } + if (instance.isCollected()) { + setSuccess(false); + log.complain("isCollected() returns 'true' for " + instance); + } + instance.uniqueID(); + instance.hashCode(); + } catch (Throwable t) { + setSuccess(false); + t.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + t); + } + } + + vm.resume(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001.java new file mode 100644 index 00000000000..1be2afea3da --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isAbstract; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method isAbstract() + * of the JDI interface ReferenceType of com.sun.jdi package + * for ClassType, InterfaceType + */ + +public class isAbstract001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.isAbstract.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "isAbstract001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + + {thisClassName, "no abstract", "class"}, + {thisClassName+"a", "no abstract", "class"}, + + {debugeeName+"$s_cls", "no abstract", "class"}, + {debugeeName+"$abs_s_cls", "abstract", "class"}, + {debugeeName+"$s_interf", "abstract", "interface"}, + + {package_prefix + "simple_cls", "no abstract", "class"}, + {package_prefix + "abstr_cls", "abstract", "class"}, + {package_prefix + "interf", "abstract", "interface"}, + {package_prefix + "abstr_interf", "abstract", "interface"} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new isAbstract001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/isAbstract/isAbstract001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/isAbstract/isAbstract001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/isAbstract/isAbstract001 test LOG:"); + out_stream.println("==> test checks isAbstract() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for ClassType, InterfaceType\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> isAbstract001: isAbstract001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> isAbstract001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> isAbstract001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isAbstract001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> isAbstract001: checking debugee's classes by ReferenceType.isAbstract() method..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int isAbstract_method_errors = 0; + for (int i=0; i isAbstract001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + String s_type = classes_for_check[i][2]; + String s_abstract_sign = classes_for_check[i][1]; + boolean isAbstract = s_abstract_sign.equals("abstract"); + if (refType.isAbstract() != isAbstract) { + out_stream.println("##> isAbstract001: UNEXPECTED isAbstract() method result (" + + !isAbstract + ") for " + s_type + ": " + + className + "(" + s_abstract_sign + ")"); + isAbstract_method_errors++; + } + else { + print_log_on_verbose("--> isAbstract001: expected isAbstract() method result (" + + isAbstract + ") for " + s_type + ": " + + className + "(" + s_abstract_sign + ")"); + } + } + out_stream.println("--> isAbstract001: checking debugee's classes completed!"); + out_stream.println("--> isAbstract001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + out_stream.println("##> isAbstract001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + out_stream.println("##> isAbstract001: isAbstract() method ERRORS counter = " + + isAbstract_method_errors); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + isAbstract_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isAbstract001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> isAbstract001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> isAbstract001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001/TestDescription.java new file mode 100644 index 00000000000..e13b3eb03ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isAbstract/isAbstract001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/isAbstract/isAbstract001 test + * checks the isAbstract() method of ReferenceType interface + * of the com.sun.jdi package for ClassType, InterfaceType. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isAbstract.isAbstract001 + * nsk.jdi.ReferenceType.isAbstract.isAbstract001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isAbstract.isAbstract001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001a.java new file mode 100644 index 00000000000..464162b9edb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isAbstract001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isAbstract; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isAbstract001 JDI test. + */ + +public class isAbstract001a { + + static boolean verbose_mode = false; + + // Abstract classes must be extended by a class and that class must be + // initialized, so that abstract classes could be returnedin debugger + + static class s_cls {} + abstract static class abs_s_cls {} + static class abs_s_cls_ext extends abs_s_cls {} + abs_s_cls_ext abs_s_cls_ext_0 = new abs_s_cls_ext(); + static interface s_interf {} + static class s_interf_impl implements s_interf {} + s_interf_impl s_interf_impl_0 = new s_interf_impl(); + + s_cls s_cls_0=new s_cls(); + abs_s_cls abs_s_cls_0, abs_s_cls_1[]={abs_s_cls_0}; + s_interf s_interf_0, s_interf_1[]={s_interf_0}; + + isAbstract001 a001_0=new isAbstract001(); + + simple_cls simple_cls_0=new simple_cls(); + abstr_cls_ext abstr_cls_ext_0= new abstr_cls_ext(); + abstr_cls abstr_cls_0, abstr_cls_1[]={abstr_cls_0}; + interf_impl interf_impl_0= new interf_impl(); + interf interf_0, interf_1[]={interf_0}; + abstr_interf abstr_interf_0, abstr_interf_1[]={abstr_interf_0}; + abstr_interf_impl abstr_interf_impl_0= new abstr_interf_impl(); + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i isAbstract001a: debugee started!"); + isAbstract001a isAbstract001a_obj = new isAbstract001a(); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + print_log_on_verbose("**> isAbstract001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isAbstract001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isAbstract001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isAbstract001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isAbstract001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** simple class */ +class simple_cls {} + +/** abstract class */ +abstract class abstr_cls {} +class abstr_cls_ext extends abstr_cls {} + +/** interface */ +interface interf {} +class interf_impl implements interf {} + +/** abstract interface */ +abstract interface abstr_interf {} +class abstr_interf_impl implements abstr_interf {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002.java new file mode 100644 index 00000000000..5bec6ff24fd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isAbstract; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +/** + * This test checks the method isAbstract() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class isabstract002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class isAbstracts of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.isAbstract.", + thisClassName = package_prefix + "isabstract002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "isabstract002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new isabstract002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/isAbstract/isabstract002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/isAbstract/isabstract002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/isAbstract/isabstract002 test LOG:"); + print_log_anyway("--> test checks isAbstract() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> isabstract002: isabstract002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isabstract002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> isabstract002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isabstract002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isabstract002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> isabstract002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isabstract002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean isAbstract_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> isabstract002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> isabstract002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> isabstract002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> isabstract002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> isabstract002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isabstract002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> isabstract002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.isAbstract() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> isabstract002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isabstract002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> isabstract002: check that checked class has been unloaded really..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> isabstract002: checked class has been unloaded really: " + checked_class); + } + else { + print_log_without_verbose + ("--> isabstract002: check that checked class has been unloaded really..."); + print_log_anyway + ("--> isabstract002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.isAbstract() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> isabstract002: check ReferenceType.isAbstract() method for unloaded class..."); + boolean ref_type_is_abstract = false; + try { + ref_type_is_abstract = refType.isAbstract(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> isabstract002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> isabstract002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + isAbstract_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || isAbstract_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isabstract002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> isabstract002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> isabstract002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of isabstract002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TestDescription.java new file mode 100644 index 00000000000..15a77258e00 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isAbstract/isabstract002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/isAbstract/isabstract002 test + * checks the isAbstract() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * isAbstract() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - isabstract002b class was moved in 'loadclass' subdirectory; + * - package name was added in isabstract002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for isabstract002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isAbstract.isabstract002 + * nsk.jdi.ReferenceType.isAbstract.isabstract002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isAbstract.isabstract002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/loadclass/isabstract002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/loadclass/isabstract002b.java new file mode 100644 index 00000000000..b3fa480d5ab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002/loadclass/isabstract002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the isAbstract() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.isAbstract; + +abstract class isabstract002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002a.java new file mode 100644 index 00000000000..af85baf3d4d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isAbstract; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isabstract002 JDI test. + */ + +public class isabstract002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.isAbstract."; + static String checked_class_name = package_prefix + "isabstract002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> isabstract002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> isabstract002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> isabstract002a: checked class loaded: " + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> isabstract002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> isabstract002a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> isabstract002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isabstract002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isabstract002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> isabstract002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> isabstract002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> isabstract002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> isabstract002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> isabstract002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> isabstract002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> isabstract002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isabstract002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isabstract002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isabstract002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isabstract002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of isabstract002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003.java new file mode 100644 index 00000000000..43496804edb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.isAbstract; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isabstract003 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ReferenceType.isAbstract."; + private final static String className = "isabstract003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + if (checkedClass.isEnum()) { + display("ReferenceType.isAbstract() returned expected true for type: " + className); + } else { + complain("ReferenceType.isAbstract() returned unexpected false for type: " + className); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003/TestDescription.java new file mode 100644 index 00000000000..91a409c3b74 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isAbstract/isabstract003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isEnum() method of ReferenceType interface. + * The test checks if the method returns true for any + * mirrored abstract enum type which has enum constant-specific + * class bodies. + * The test consists of a debugger program (isabstract003.java) + * and debuggee application (isabstract003a.java). + * Package name is nsk.jdi.ReferenceType.isAbstract . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isAbstract() method for field of enum type + * declared in isabstract003a class. The test fails if the method + * returned false. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isAbstract.isabstract003 + * nsk.jdi.ReferenceType.isAbstract.isabstract003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isAbstract.isabstract003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003a.java new file mode 100644 index 00000000000..557943d95e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isAbstract/isabstract003a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.isAbstract; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isabstract003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static isabstract003Enum f1 = isabstract003Enum.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isabstract003.SIGNAL_READY); + receiveSignal(isabstract003.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum isabstract003Enum { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java new file mode 100644 index 00000000000..7153e138fb4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.isFinal()
    + * complies with its spec.
    + *
    + * Cases for testing include :
    + * - inner and outer ClassTypes, InterfaceTypes, and ArrayTypes;
    + * - arrays of primitive values;
    + * - primitive classes.
    + */ + +public class isfinal001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/isFinal/isfinal001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new isfinal001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return exitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.isFinal.isfinal001a"; + + private String testedClassName = + "nsk.jdi.ReferenceType.isFinal.ClassToCheck"; + + String mName = "nsk.jdi.ReferenceType.isFinal"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String names1[] = { + + ".TestClass$InnerClass", "f", + ".TestClass$InnerClass[]", "t", + + ".TestClass$FinalInnerClass", "t", + ".TestClass$FinalInnerClass[]", "t", + + ".TestClass$NestedIface", "f", + ".TestClass$NestedIface[]", "t", + + ".OuterClass", "f", + ".OuterClass[]", "t", + ".OuterIface", "f", + ".OuterIface[]", "t", + + ".FinalOuterClass", "t", + ".FinalOuterClass[]", "t" + + }; + + String names2[] = { + + "boolean[][][][]", "t", + "byte[][][][]", "t", + "char[][][][]", "t", + "double[][][][]", "t", + "float[][][][]", "t", + "int[][][][]", "t", + "long[][][][]", "t", + "short[][][][]", "t" + + }; + + String names3[] = { + + "java.lang.Boolean", "t", + "java.lang.Byte", "t", + "java.lang.Character", "t", + "java.lang.Double", "t", + "java.lang.Float", "t", + "java.lang.Integer", "t", + "java.lang.Long", "t", + "java.lang.Short", "t" + + }; + + log2("----- Cases for testing: ReferenceTypes"); + for (int i1 = 0; i1 < names1.length; i1 += 2) { + + String typeForCheck = mName + names1[i1]; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + + List classList = vm.classesByName(typeForCheck); + if (classList.size() != 1) { + log3("ERROR: classList.size() != 1 : " + classList.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType referenceType = (ReferenceType) classList.get(0);"); + ReferenceType referenceType = (ReferenceType) classList.get(0); + + log2(" getting: boolean isFinal = referenceType.isfinal();"); + boolean isFinal = referenceType.isFinal(); + + if ( names1[i1+1].equals("t") ) { + log2(" expected value of isFinal is 'true'"); + if (!isFinal) { + log3("ERROR: isfinal != true for: " + typeForCheck); + testExitCode = FAILED; + } + } else { + log2(" expected value of isFinal is 'false'"); + if (isFinal) { + log3("ERROR: isfinal != false for: " + typeForCheck); + testExitCode = FAILED; + } + } + } + + log2("----- Cases for testing: primitive type arrays"); + for (int i1 = 0; i1 < names2.length; i1 += 2) { + + String typeForCheck = names2[i1]; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classList = vm.classesByName(typeForCheck); + if (classList.size() != 1) { + log3("ERROR: classList.size() != 1 : " + classList.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType referenceType = (ReferenceType) classList.get(0);"); + ReferenceType referenceType = (ReferenceType) classList.get(0); + + log2(" getting: boolean isFinal = referenceType.isfinal();"); + boolean isFinal = referenceType.isFinal(); + + log2(" expected value of isFinal is 'true'"); + if (!isFinal) { + log3("ERROR: isfinal != true for: " + typeForCheck); + testExitCode = FAILED; + } + + } + + log2("----- Cases for testing: primitive classes"); + for (int i1 = 0; i1 < names3.length; i1 += 2) { + + String typeForCheck = names3[i1]; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classList = vm.classesByName(typeForCheck); + if (classList.size() != 1) { + log3("ERROR: classList.size() != 1 : " + classList.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType referenceType = (ReferenceType) classList.get(0);"); + ReferenceType referenceType = (ReferenceType) classList.get(0); + + log2(" getting: boolean isFinal = referenceType.isfinal();"); + boolean isFinal = referenceType.isFinal(); + + log2(" expected value of isFinal is 'true'"); + if (!isFinal) { + log3("ERROR: isfinal != true for: " + typeForCheck); + testExitCode = FAILED; + } + + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001/TestDescription.java new file mode 100644 index 00000000000..5c67dac8a05 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isFinal/isfinal001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.isFinal() + * complies with its spec: + * public boolean isFinal() + * Determines if this type was declared final. + * For arrays (ArrayType) and primitive classes, + * the return value is always true. + * Returns: true if this type is final; false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.isFinal.isfinal001; + * the debuggee program - nsk.jdi.ReferenceType.isFinal.isfinal001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isFinal.isfinal001 + * nsk.jdi.ReferenceType.isFinal.isfinal001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isFinal.isfinal001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001a.java new file mode 100644 index 00000000000..7c9dc66003c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001a.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the isfinal001 JDI test. + */ + +public class isfinal001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + TestClass check = new TestClass(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + +class TestClass { + + class InnerClass implements NestedIface { + boolean bic = true; + } + InnerClass innerClass = new InnerClass(); + InnerClass innerClassArray[] = { new InnerClass() }; + + final class FinalInnerClass { + boolean bfic = true; + } + FinalInnerClass finalInnerClass = new FinalInnerClass(); + FinalInnerClass finalInnerClassArray[] = { new FinalInnerClass() }; + + interface NestedIface { + boolean bif = true; + } + NestedIface nestedIface = new InnerClass(); + NestedIface nestedIfaceArray[] = { new InnerClass() }; + + static OuterClass outerClass = new OuterClass(); + static OuterClass outerClassArray[] = { new OuterClass() }; + static OuterIface outerIface = new OuterClass(); + static OuterIface outerIfaceArray[] = { new OuterClass() }; + + static FinalOuterClass finalOuterClass = new FinalOuterClass(); + static FinalOuterClass finalOuterClassArray[] = { new FinalOuterClass() }; + + boolean bl[][][][] = {{{{true}}}}; + byte bt[][][][] = {{{{0}}}}; + char ch[][][][] = {{{{0}}}}; + double db[][][][] = {{{{0.0}}}}; + float fl[][][][] = {{{{0.0f}}}}; + int in[][][][] = {{{{0}}}}; + long ln[][][][] = {{{{0}}}}; + short sh[][][][] = {{{{0}}}}; + + Boolean blBl = new Boolean(true); + Byte btBt = new Byte((byte)1); + Character chCh = new Character('c'); + Double dbDb = new Double(0); + Float flFl = new Float(0.0f); + Integer inIn = new Integer(0); + Long lnLn = new Long(0); + Short shSh = new Short((short)1); +} + +interface OuterIface { + static boolean b1 = false; +} + +class OuterClass implements OuterIface { + static final boolean b2 = true; +} + +final class FinalOuterClass implements OuterIface { + static final boolean b3 = true; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002.java new file mode 100644 index 00000000000..d0c76736d69 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isfinal002 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ReferenceType.isFinal."; + private final static String className = "isfinal002"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2", "f3", "f4"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + if (checkedClass.isFinal()) { + display("ReferenceType.isFinal() returned true for " + className); + } else { + complain("ReferenceType.isFinal() returned false for " + className); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002/TestDescription.java new file mode 100644 index 00000000000..31c664cfc46 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isFinal/isfinal002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isFinal() method of ReferenceType interface. + * The test checks if the method returns true any mirrored + * enum type which does not have enum constant's specific + * class bodies. This kind of enum types are implicitly final. + * The test consists of a debugger program (isfinal002.java) + * and debuggee application (isfinal002a.java). + * Package name is nsk.jdi.ReferenceType.isFinal . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isFinal() method for each field + * of enum type declared in isfinal002a class. + * The test fails if false is returned once or more times. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isFinal.isfinal002 + * nsk.jdi.ReferenceType.isFinal.isfinal002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isFinal.isfinal002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002a.java new file mode 100644 index 00000000000..84bad1943f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal002a.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isfinal002a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum1.Enum1_ f2 = Enum1.Enum1_.e1; + static isfinal002Enum2 f3 = isfinal002Enum2.e2; + static isfinal002Enum2.Enum2_ f4 = isfinal002Enum2.Enum2_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isfinal002.SIGNAL_READY); + + + //pipe.println(isfinal002.SIGNAL_GO); + receiveSignal(isfinal002.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + enum Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum isfinal002Enum2 { + e1, e2; + + enum Enum2_ { + e1, e2; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001.java new file mode 100644 index 00000000000..6efaa399b89 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isInitialized; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +/** + * This test checks the method isInitialized() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class isinit001 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class isInitializeds of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.isInitialized.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "isinit001", + debugeeName = thisClassName + "a"; + + static String is_initialized_sign = "is_initialized"; + static String not_initialized_sign = "not_initialized"; + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + +// {package_prefix + "NotInitializedClass", not_initialized_sign}, +// {package_prefix + "NotInitializedInterface", not_initialized_sign}, + + {package_prefix + "InitializedSuperClass", is_initialized_sign}, + + {package_prefix + "InitializedClass", is_initialized_sign}, + {package_prefix + "InitializedInterface", is_initialized_sign} + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new isinit001().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/isInitialized/isinit001 test FAILED"); + } + else { + print_log_on_verbose("\n==> nsk/jdi/ReferenceType/isInitialized/isinit001 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + test_log_handler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, test_log_handler); + + print_log_on_verbose("==> nsk/jdi/ReferenceType/isInitialized/isinit001 test LOG:"); + print_log_on_verbose("==> test checks the isInitialized() method of ReferenceType interface"); + print_log_on_verbose(" of the com.sun.jdi package for ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + debugee_launch_command = debugeeName + " -vbs"; + } + + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + + debugee.redirectStderr(out); + print_log_on_verbose("--> isinit001: isinit001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway("##> isinit001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway("##> isinit001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isinit001: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> isinit001: check ReferenceType.isInitialized() method for debugee's classes..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int isInitialized_method_exceptions = 0; + int isInitialized_method_errors = 0; + for (int i=0; i isinit001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + boolean expected_is_initialized_result = classes_for_check[i][1].equals(is_initialized_sign); + boolean returned_is_initialized_result = false; + try { + returned_is_initialized_result = refType.isInitialized(); + } + catch (Throwable thrown) { + print_log_anyway + ("##> isinit001: FAILED: refType.isInitialized() threw unexpected exception - " + + thrown); + print_log_anyway + ("##> refType = " + refType); + isInitialized_method_exceptions++; + continue; + } + if ( returned_is_initialized_result != expected_is_initialized_result ) { + print_log_anyway + ("##> isinit001: FAILED: ReferenceType.isInitialized() returned unexpected result = " + + returned_is_initialized_result); + print_log_anyway + ("##> checked class = " + className); + isInitialized_method_errors++; + } + else { + print_log_on_verbose + ("--> isinit001: PASSED: ReferenceType.isInitialized() returned expected result = " + + returned_is_initialized_result); + print_log_on_verbose + ("--> checked class = " + className); + } + } + print_log_on_verbose("--> isinit001: check completed!"); + print_log_on_verbose("--> isinit001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + print_log_anyway("##> isinit001: \"class not found ERRORS\" number = " + + class_not_found_errors); + } + if ( isInitialized_method_exceptions > 0 ) { + print_log_anyway("##> isinit001: number of unexpected isInitialized() methods exceptions = " + + isInitialized_method_exceptions); + } + if (isInitialized_method_errors > 0) { + print_log_anyway("##> isinit001: isInitialized() method errors number = " + + isInitialized_method_errors); + } + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + isInitialized_method_errors + isInitialized_method_exceptions > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isinit001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway("##> isinit001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isinit001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001/TestDescription.java new file mode 100644 index 00000000000..8883ec0f669 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isInitialized/isinit001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/isInitialized/isinit001 test + * checks the isInitialized() method of ReferenceType interface + * of the com.sun.jdi package for ClassType, InterfaceType: + * For each checked debugee's class the test gets ReferenceType + * instance for this class and then calls the isInitialized() + * method for this ReferenceType instance. + * Some checked debugee's classes have been initialized but other have not. + * The test expects that returned boolean value should be equal to the + * expected boolean value. + * COMMENTS + * The test is corrected and updated as follows: + * - the checks for NotInitializedClass and NotInitializedInterface are removed + * because the logic of other checks doesn't allow to get + * corresponding objects in the debuggee; + * - statements for establishing LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "print_log_anyway" are replaced with "print_log_on_verbose". + * ------------------------------------------------------- + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isInitialized.isinit001 + * nsk.jdi.ReferenceType.isInitialized.isinit001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isInitialized.isinit001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001a.java new file mode 100644 index 00000000000..91b035ccc29 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isInitialized; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isinit001 JDI test. + */ + +public class isinit001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + NotInitializedClass not_initialized_class_0, + not_initialized_class_1[] = {not_initialized_class_0}; + + NotInitializedInterface not_initialized_interface_0, + not_initialized_interface_1[] = {not_initialized_interface_0}; + + InitializedClass initialized_class_0 = new InitializedClass(); + + int copy_super_class_int_var = SubClass.super_class_int_var; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i isinit001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + isinit001a isinit001a_obj = new isinit001a(); + + print_log_on_verbose("**> isinit001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isinit001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isinit001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isinit001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isinit001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +// not initialized class +class NotInitializedClass {} + +// not initialized interface +interface NotInitializedInterface {} + + +// initialized interface +interface InitializedInterface { + static final int int_var = 1; +} + +// initialized class +class InitializedClass implements InitializedInterface { + static int my_int_var = int_var; + +} + +// initialized super class +class InitializedSuperClass { + static int super_class_int_var = 999; + +} + +// subclass +class SubClass extends InitializedSuperClass { + static String dummy_string; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002.java new file mode 100644 index 00000000000..658ed8ad4ba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isInitialized; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +/** + * This test checks the method isInitialized() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class isinit002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class isInitializeds of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.isInitialized.", + thisClassName = package_prefix + "isinit002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "isinit002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new isinit002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/isInitialized/isinit002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/isInitialized/isinit002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/isInitialized/isinit002 test LOG:"); + print_log_anyway("--> test checks isInitialized() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> isinit002: isinit002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isinit002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> isinit002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isinit002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isinit002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> isinit002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isinit002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean isInitialized_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> isinit002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> isinit002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> isinit002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> isinit002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> isinit002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isinit002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> isinit002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.isInitialized() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> isinit002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isinit002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> isinit002: check that checked class has been unloaded really..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> isinit002: checked class has been unloaded really: " + checked_class); + } + else { + print_log_without_verbose + ("--> isinit002: check that checked class has been unloaded really..."); + print_log_anyway + ("--> isinit002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.isInitialized() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> isinit002: check ReferenceType.isInitialized() method for unloaded class..."); + boolean ref_type_is_initialized = false; + try { + ref_type_is_initialized = refType.isInitialized(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> isinit002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> isinit002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + isInitialized_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || isInitialized_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isinit002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> isinit002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> isinit002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of isinit002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TestDescription.java new file mode 100644 index 00000000000..6132e17e001 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isInitialized/isinit002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/isInitialized/isinit002 test + * checks the isInitialized() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * isInitialized() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - isinit002b class was moved in 'loadclass' subdirectory; + * - package name was added in isinit002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for isinit002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isInitialized.isinit002 + * nsk.jdi.ReferenceType.isInitialized.isinit002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isInitialized.isinit002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/loadclass/isinit002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/loadclass/isinit002b.java new file mode 100644 index 00000000000..9cfc23c4615 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002/loadclass/isinit002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the isInitialized() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.isInitialized; + +class isinit002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002a.java new file mode 100644 index 00000000000..80a766dc2ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isInitialized; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isinit002 JDI test. + */ + +public class isinit002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.isInitialized."; + private final static String checked_class_name = package_prefix + "isinit002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> isinit002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> isinit002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> isinit002a: checked class loaded: " + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + print_log_on_verbose + ("**> isinit002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> isinit002a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> isinit002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isinit002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isinit002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> isinit002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> isinit002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> isinit002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> isinit002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> isinit002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> isinit002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> isinit002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isinit002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isinit002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isinit002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isinit002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of isinit002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003.java new file mode 100644 index 00000000000..0f6d0716e1d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.isInitialized; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isinit003 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ReferenceType.isInitialized."; + private final static String className = "isinit003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] testedFieldNames = {"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"}; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + if (checkedClass.isInitialized()) { + display("ReferenceType.isInitialized() returned expected true for type: " + className); + } else { + complain("ReferenceType.isInitialized() returned unexpected false for type: " + className); + exitStatus = Consts.TEST_FAILED; + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003/TestDescription.java new file mode 100644 index 00000000000..17cb719451e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isInitialized/isinit003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isInitialized() method of ReferenceType interface. + * The test checks if the method returns true for any + * mirrored enum type + * The test consists of a debugger program (isinit003.java) + * and debuggee application (isinit003a.java). + * Package name is nsk.jdi.ReferenceType.isInitialized . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls isInitialized() method for each mirorred + * enum type. The test fails if the method returned false once + * or more. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isInitialized.isinit003 + * nsk.jdi.ReferenceType.isInitialized.isinit003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isInitialized.isinit003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003a.java new file mode 100644 index 00000000000..59a53e5335c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isInitialized/isinit003a.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.isInitialized; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isinit003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static Enum1 f1 = Enum1.e1; + static Enum2 f2 = Enum2.e2; + static Enum3 f3 = Enum3.e1; + static Enum4.Enum4_ f4 = Enum4.Enum4_.e1; + static isinit003Enum5 f5 = isinit003Enum5.e2; + static isinit003Enum6 f6 = isinit003Enum6.e1; + static isinit003Enum7 f7 = isinit003Enum7.e2; + static isinit003Enum8.Enum8_ f8 = isinit003Enum8.Enum8_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isinit003.SIGNAL_READY); + receiveSignal(isinit003.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + + enum Enum1 { + e1, e2; + } + + enum Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); + } + + enum Enum3 implements isinit003i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); + } + + enum Enum4 { + e1, e2; + + enum Enum4_ { + e1, e2; + } + } + +} + +//--------------------------------------------------------- test specific classes + +enum isinit003Enum5 { + e1, e2; +} + +enum isinit003Enum6 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} + +enum isinit003Enum7 implements isinit003i { + e1 { + int val() {return i+1;} + }, + + e2 { + int val() {return i+2;} + }; + abstract int val(); +} + +enum isinit003Enum8 { + e1, e2; + enum Enum8_ { + e1, e2; + } +} + +interface isinit003i { + int i = 1; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001.java new file mode 100644 index 00000000000..1f79a950faa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isPrepared; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method isPrepared() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class isprepared001 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class isPrepareds of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.isPrepared.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "isprepared001", + debugeeName = thisClassName + "a"; + + static String is_prepared_sign = "is_prepared"; + static String not_prepared_sign = "not_prepared"; + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + +// {package_prefix + "NotPreparedClass", not_prepared_sign}, +// {package_prefix + "NotPreparedInterface", not_prepared_sign}, + + {package_prefix + "PreparedClass", is_prepared_sign}, + {package_prefix + "PreparedInterface", is_prepared_sign} + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new isprepared001().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/isPrepared/isprepared001 test FAILED"); + } + else { + print_log_on_verbose("\n==> nsk/jdi/ReferenceType/isPrepared/isprepared001 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + test_log_handler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, test_log_handler); + + print_log_on_verbose("==> nsk/jdi/ReferenceType/isInitialized/isinit001 test LOG:"); + print_log_on_verbose("==> test checks the isInitialized() method of ReferenceType interface"); + print_log_on_verbose(" of the com.sun.jdi package for ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + debugee_launch_command = debugeeName + " -vbs"; + } + + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> isprepared001: isprepared001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway("##> isprepared001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway("##> isprepared001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isprepared001: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> isprepared001: check ReferenceType.isPrepared() method for debugee's classes..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int isPrepared_method_exceptions = 0; + int isPrepared_method_errors = 0; + for (int i=0; i isprepared001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + boolean expected_is_prepared_result = classes_for_check[i][1].equals(is_prepared_sign); + boolean returned_is_prepared_result = false; + try { + returned_is_prepared_result = refType.isPrepared(); + } + catch (Throwable thrown) { + print_log_anyway + ("##> isprepared001: FAILED: refType.isPrepared() threw unexpected exception - " + + thrown); + print_log_anyway + ("##> refType = " + refType); + isPrepared_method_exceptions++; + continue; + } + if ( returned_is_prepared_result != expected_is_prepared_result ) { + print_log_anyway + ("##> isprepared001: FAILED: ReferenceType.isPrepared() returned unexpected result = " + + returned_is_prepared_result); + print_log_anyway + ("##> checked class = " + className); + isPrepared_method_errors++; + } + else { + print_log_on_verbose + ("--> isprepared001: PASSED: ReferenceType.isPrepared() returned expected result = " + + returned_is_prepared_result); + print_log_on_verbose + ("--> checked class = " + className); + } + } + print_log_on_verbose("--> isprepared001: check completed!"); + print_log_on_verbose("--> isprepared001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + print_log_anyway("##> isprepared001: \"class not found ERRORS\" number = " + + class_not_found_errors); + } + if ( isPrepared_method_exceptions > 0 ) { + print_log_anyway("##> isprepared001: number of unexpected isPrepared() methods exceptions = " + + isPrepared_method_exceptions); + } + if (isPrepared_method_errors > 0) { + print_log_anyway("##> isprepared001: isPrepared() method errors number = " + + isPrepared_method_errors); + } + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + isPrepared_method_errors + isPrepared_method_exceptions > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isprepared001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway("##> isprepared001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isprepared001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001/TestDescription.java new file mode 100644 index 00000000000..9531602aef3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isPrepared/isprepared001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/isPrepared/isprepared001 test + * checks the isPrepared() method of ReferenceType interface + * of the com.sun.jdi package for ClassType, InterfaceType: + * For each checked debugee's class the test gets ReferenceType + * instance for this class and then calls the isPrepared() + * method for this ReferenceType instance. + * Some checked debugee's classes have been prepared but other have not. + * The test expects that returned boolean value should be equal to the + * expected boolean value. + * COMMENTS + * The test is corrected and updated as follows: + * - the checks for NotPreparedClass and NotPreparedInterface are removed + * because the logic of other checks doesn't allow to get + * corresponding objects in the debuggee; + * - statements for establishing LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "print_log_anyway" are replaced with "print_log_on_verbose". + * ------------------------------------------------------- + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isPrepared.isprepared001 + * nsk.jdi.ReferenceType.isPrepared.isprepared001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isPrepared.isprepared001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001a.java new file mode 100644 index 00000000000..c43f9ae033c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared001a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isPrepared; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isprepared001 JDI test. + */ + +public class isprepared001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + NotPreparedClass not_prepared_class_0, not_prepared_class_1[] = {not_prepared_class_0}; + + NotPreparedInterface not_prepared_interface_0, not_prepared_interface_1[] = {not_prepared_interface_0}; + + PreparedClass prepared_class_0 = new PreparedClass(); + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i isprepared001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + isprepared001a isprepared001a_obj = new isprepared001a(); + + print_log_on_verbose("**> isprepared001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isprepared001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isprepared001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isprepared001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isprepared001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +// not prepared class +class NotPreparedClass {} + +// not prepared interface +interface NotPreparedInterface {} + + +// prepared interface +interface PreparedInterface { + static final int int_var = 1; +} + +// prepared class +class PreparedClass implements PreparedInterface { + static int my_int_var = int_var; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002.java new file mode 100644 index 00000000000..d160d257434 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isPrepared; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method isPrepared() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class isprepared002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class isPrepareds of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.isPrepared.", + thisClassName = package_prefix + "isprepared002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "isprepared002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new isprepared002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/isPrepared/isprepared002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/isPrepared/isprepared002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/isPrepared/isprepared002 test LOG:"); + print_log_anyway("--> test checks isPrepared() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> isprepared002: isprepared002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isprepared002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> isprepared002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isprepared002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isprepared002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> isprepared002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isprepared002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean isPrepared_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> isprepared002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> isprepared002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> isprepared002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> isprepared002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> isprepared002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isprepared002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> isprepared002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.isPrepared() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> isprepared002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isprepared002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> isprepared002: check that checked class has been unloaded really..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> isprepared002: checked class has been unloaded really: " + checked_class); + } + else { + print_log_without_verbose + ("--> isprepared002: check that checked class has been unloaded really..."); + print_log_anyway + ("--> isprepared002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.isPrepared() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> isprepared002: check ReferenceType.isPrepared() method for unloaded class..."); + boolean ref_type_is_prepared = false; + try { + ref_type_is_prepared = refType.isPrepared(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> isprepared002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> isprepared002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + isPrepared_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || isPrepared_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isprepared002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> isprepared002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> isprepared002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of isprepared002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TestDescription.java new file mode 100644 index 00000000000..48f1942e4fb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isPrepared/isprepared002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/isPrepared/isprepared002 test + * checks the isPrepared() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * isPrepared() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - isprepared002b class was moved in 'loadclass' subdirectory; + * - package name was added in isprepared002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for isprepared002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isPrepared.isprepared002 + * nsk.jdi.ReferenceType.isPrepared.isprepared002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isPrepared.isprepared002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/loadclass/isprepared002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/loadclass/isprepared002b.java new file mode 100644 index 00000000000..cb6dae35958 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002/loadclass/isprepared002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the isPrepared() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.isPrepared; + +class isprepared002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002a.java new file mode 100644 index 00000000000..b005131cc4c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isPrepared/isprepared002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isPrepared; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isprepared002 JDI test. + */ + +public class isprepared002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.isPrepared."; + private final static String checked_class_name = package_prefix + "isprepared002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> isprepared002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> isprepared002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> isprepared002a: checked class loaded: " + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> isprepared002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> isprepared002a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> isprepared002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isprepared002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isprepared002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> isprepared002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> isprepared002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> isprepared002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> isprepared002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> isprepared002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> isprepared002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> isprepared002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isprepared002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isprepared002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isprepared002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isprepared002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of isprepared002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java new file mode 100644 index 00000000000..f4a8ebbd44d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.isStatic()
    + * complies with its spec.
    + *
    + * Cases for testing include :
    + * - nested and outer ClassTypes and InterfaceTypes,
    + * and nested ArrayTypes;
    + * - arrays of primitive values;
    + * - primitive classes.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class isstatic001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/isStatic/isstatic001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new isstatic001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.isStatic.isstatic001a"; + + String mName = "nsk.jdi.ReferenceType.isStatic"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String names1[] = { + + ".isstatic001aTestClass$NestedClass", "f", + ".isstatic001aTestClass$NestedClass[]", "f", + ".isstatic001aTestClass$NestedIface", "t", + ".isstatic001aTestClass$StaticNestedClass", "t", + ".isstatic001aOuterClass", "f", + ".isstatic001aOuterClass[]", "f", + ".isstatic001aOuterIface", "f", + ".isstatic001aOuterIface[]", "f", + ".isstatic001aOuterIface$InnerIface", "t", + ".isstatic001aOuterIface$StaticInnerIface", "t" + + }; + + String names2[] = { + + "boolean[][][][]", "f", + "byte[][][][]", "f", + "char[][][][]", "f", + "double[][][][]", "f", + "float[][][][]", "f", + "int[][][][]", "f", + "long[][][][]", "f", + "short[][][][]", "f" + + }; + + String names3[] = { + + "java.lang.Boolean", "f", + "java.lang.Byte", "f", + "java.lang.Character", "f", + "java.lang.Double", "f", + "java.lang.Float", "f", + "java.lang.Integer", "f", + "java.lang.Long", "f", + "java.lang.Short", "f" + + }; + + log2("----- Cases for testing: ReferenceTypes"); + for (int i1 = 0; i1 < names1.length; i1 += 2) { + + String typeForCheck = mName + names1[i1]; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classList = vm.classesByName(typeForCheck); + if (classList.size() != 1) { + log3("ERROR: classList.size() != 1 : " + classList.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType referenceType = (ReferenceType) classList.get(0);"); + ReferenceType referenceType = (ReferenceType) classList.get(0); + + log2(" getting: boolean isStatic = referenceType.isStatic();"); + boolean isStatic = referenceType.isStatic(); + + if ( names1[i1+1].equals("t") ) { + log2(" expected value of isStatic is 'true'"); + if (!isStatic) { + log3("ERROR: isStatic != true for: " + typeForCheck); + testExitCode = FAILED; + } + } else { + log2(" expected value of isStatic is 'false'"); + if (isStatic) { + log3("ERROR: isStatic != false for: " + typeForCheck); + testExitCode = FAILED; + } + } + } + + log2("----- Cases for testing: primitive type arrays"); + for (int i1 = 0; i1 < names2.length; i1 += 2) { + + String typeForCheck = names2[i1]; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classList = vm.classesByName(typeForCheck); + if (classList.size() != 1) { + log3("ERROR: classList.size() != 1 : " + classList.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType referenceType = (ReferenceType) classList.get(0);"); + ReferenceType referenceType = (ReferenceType) classList.get(0); + + log2(" getting: boolean isStatic = referenceType.isStatic();"); + boolean isStatic = referenceType.isStatic(); + + log2(" expected value of isStatic is 'false'"); + if (isStatic) { + log3("ERROR: isStatic != false for: " + typeForCheck); + testExitCode = FAILED; + } + + } + + log2("----- Cases for testing: primitive classes"); + for (int i1 = 0; i1 < names3.length; i1 += 2) { + + String typeForCheck = names3[i1]; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classList = vm.classesByName(typeForCheck); + if (classList.size() != 1) { + log3("ERROR: classList.size() != 1 : " + classList.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType referenceType = (ReferenceType) classList.get(0);"); + ReferenceType referenceType = (ReferenceType) classList.get(0); + + log2(" getting: boolean isStatic = referenceType.isStatic();"); + boolean isStatic = referenceType.isStatic(); + + log2(" expected value of isStatic is 'false'"); + if (isStatic) { + log3("ERROR: isStatic != false for: " + typeForCheck); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001/TestDescription.java new file mode 100644 index 00000000000..aaa68a69c12 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isStatic/isstatic001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.isStatic() + * complies with its spec: + * public boolean isStatic() + * Determines if this type was declared static. + * Only nested types, can be declared static, + * so false is returned for any + * package-level type, array type, or primitive class. + * Returns: + * true if this type is static; false otherwise. + * Cases for testing include : + * - nested and outer ClassTypes and InterfaceTypes, and nested ArrayTypes;
    + * - arrays of primitive values; + * - primitive classes. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.isStatic.isstatic001; + * the debuggee program - nsk.jdi.ReferenceType.isStatic.isstatic001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isStatic.isstatic001 + * nsk.jdi.ReferenceType.isStatic.isstatic001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isStatic.isstatic001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001a.java new file mode 100644 index 00000000000..2065d1f7e5f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001a.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the isstatic001 JDI test. + */ + +public class isstatic001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + isstatic001aTestClass check = new isstatic001aTestClass(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + + +class isstatic001aTestClass { + + class NestedClass implements NestedIface { + boolean bnc = true; + } + NestedClass nestedClass = new NestedClass(); + NestedClass nestedClassArray[] = { new NestedClass() }; + + interface NestedIface { + boolean bnf = true; + } + NestedIface nestedIface = new NestedClass(); +// NestedIface nestedIfaceArray[] = { new NestedClass() }; + + + static class StaticNestedClass { + boolean bsnc = true; + } + StaticNestedClass staticNestedClass = new StaticNestedClass(); +// StaticNestedClass staticNestedClassArray[] = { new StaticNestedClass() }; + + + static isstatic001aOuterClass outerClass = new isstatic001aOuterClass(); + static isstatic001aOuterClass outerClassArray[] = { new isstatic001aOuterClass() }; + static isstatic001aOuterIface outerIface = new isstatic001aOuterClass(); + static isstatic001aOuterIface outerIfaceArray[] = { new isstatic001aOuterClass() }; + + + boolean bl[][][][] = {{{{true}}}}; + byte bt[][][][] = {{{{0}}}}; + char ch[][][][] = {{{{0}}}}; + double db[][][][] = {{{{0.0}}}}; + float fl[][][][] = {{{{0.0f}}}}; + int in[][][][] = {{{{0}}}}; + long ln[][][][] = {{{{0}}}}; + short sh[][][][] = {{{{0}}}}; + + + Boolean blBl = new Boolean(true); + Byte btBt = new Byte((byte)1); + Character chCh = new Character('c'); + Double dbDb = new Double(0); + Float flFl = new Float(0.0f); + Integer inIn = new Integer(0); + Long lnLn = new Long(0); + Short shSh = new Short((short)1); +} + +interface isstatic001aOuterIface { + static boolean b1 = false; + + interface InnerIface {} + + static interface StaticInnerIface {} +} + +class isstatic001aOuterClass implements isstatic001aOuterIface { + static final boolean b2 = true; + + class InnerClass implements isstatic001aOuterIface.InnerIface { + boolean bOiIi = true; + } + InnerClass innerClass = new InnerClass(); + + class StaticInnerClass implements isstatic001aOuterIface.StaticInnerIface { + boolean bOiSii = true; + } + StaticInnerClass staticInnerClass = new StaticInnerClass(); +} + +final class isstatic001aFinalOuterClass implements isstatic001aOuterIface { + static final boolean b3 = true; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java new file mode 100644 index 00000000000..16ce817ed5d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.isStatic()
    + * complies with its spec.
    + *
    + * Cases for testing include :
    + * - nested and outer ClassTypes and InterfaceTypes,
    + * and nested ArrayTypes;
    + * - arrays of primitive values;
    + * - primitive classes.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class isstatic002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/isStatic/isstatic002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new isstatic002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.isStatic.isstatic002a"; + + String mName = "nsk.jdi.ReferenceType.isStatic"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String names1[] = { + + ".isstatic002aTestClass$NestedIface1[]", "f", + ".isstatic002aTestClass$NestedIface2[]", "f", + ".isstatic002aTestClass$StaticNestedClass[]", "f" + }; + + log2("----- Cases for testing: ReferenceTypes"); + for (int i1 = 0; i1 < names1.length; i1 += 2) { + + String typeForCheck = mName + names1[i1]; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classList = vm.classesByName(typeForCheck); + if (classList.size() != 1) { + log3("ERROR: classList.size() != 1 : " + classList.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType referenceType = (ReferenceType) classList.get(0);"); + ReferenceType referenceType = (ReferenceType) classList.get(0); + + log2(" getting: boolean isStatic = referenceType.isStatic();"); + boolean isStatic = referenceType.isStatic(); + + if ( names1[i1+1].equals("t") ) { + log2(" expected value of isStatic is 'true'"); + if (!isStatic) { + log3("ERROR: isStatic != true for: " + typeForCheck); + testExitCode = FAILED; + } + } else { + log2(" expected value of isStatic is 'false'"); + if (isStatic) { + log3("ERROR: isStatic != false for: " + typeForCheck); + testExitCode = FAILED; + } + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002/TestDescription.java new file mode 100644 index 00000000000..8743a535b71 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isStatic/isstatic002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.isStatic() + * complies with its spec: + * public boolean isStatic() + * Determines if this type was declared static. + * Only nested types, can be declared static, + * so false is returned for any + * package-level type, array type, or primitive class. + * Returns: + * true if this type is static; false otherwise. + * Cases for testing include : + * - nested package-level ClassTypes and InterfaceTypes. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.isStatic.isstatic002; + * the debuggee program - nsk.jdi.ReferenceType.isStatic.isstatic002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isStatic.isstatic002 + * nsk.jdi.ReferenceType.isStatic.isstatic002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isStatic.isstatic002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002a.java new file mode 100644 index 00000000000..2cf2f97dbb9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the isstatic002 JDI test. + */ + +public class isstatic002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + isstatic002aTestClass check = new isstatic002aTestClass(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + + +class isstatic002aTestClass { + + interface NestedIface1 { + boolean bnf = true; + } + static class NestedClass1 implements NestedIface1 { + boolean bnc = true; + } + NestedIface1 nestedIfaceArray1[] = { new NestedClass1() }; + + + interface NestedIface2 { + boolean bnf = true; + } + class NestedClass2 implements NestedIface2 { + boolean bnc = true; + } + NestedIface2 nestedIfaceArray2[] = { new NestedClass2() }; + + + static class StaticNestedClass { + boolean bsnc = true; + } + StaticNestedClass staticNestedClassArray[] = { new StaticNestedClass() }; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001.java new file mode 100644 index 00000000000..6f920e5417b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isVerified; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method isVerified() + * of the JDI interface ReferenceType of com.sun.jdi package + * for ClassType, InterfaceType + */ + +public class isVerified001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.isVerified.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "isVerified001", + debugeeName = thisClassName + "a"; + + + static ArgumentHandler argsHandler; + private static Log logHandler; + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + + {thisClassName, "verified", "class"}, + {thisClassName+"a", "verified", "class"}, + +// {package_prefix + "not_verif_cls", "not verified", "class"}, + +// {package_prefix + "not_verif_interf", "not verified", "interface"}, + + {package_prefix + "verif_class", "verified", "class"}, + + {package_prefix + "verif_interf", "verified", "interface"}, + + {package_prefix + "verif_subcl", "verified", "class"} + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new isVerified001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ReferenceType/isVerified/isVerified001 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ReferenceType/isVerified/isVerified001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + print_log_on_verbose("==> nsk/jdi/ReferenceType/isInitialized/isinit001 test LOG:"); + print_log_on_verbose("==> test checks the isInitialized() method of ReferenceType interface"); + print_log_on_verbose(" of the com.sun.jdi package for ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + debugee_launch_command = debugeeName + " -vbs"; + } + + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + + debugee.redirectStderr(out); + print_log_on_verbose("--> isVerified001: isVerified001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + logHandler.complain + ("##> isVerified001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + logHandler.complain + ("##> isVerified001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isVerified001: debugee's \"ready\" signal recieved!"); + } + + logHandler.display + ("--> isVerified001: checking debugee's classes by ReferenceType.isVerified() method..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int isVerified_method_errors = 0; + for (int i=0; i isVerified001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + String s_type = classes_for_check[i][2]; + String s_verified_sign = classes_for_check[i][1]; + boolean isVerified = s_verified_sign.equals("verified"); + if (refType.isVerified() != isVerified) { + logHandler.complain("##> isVerified001: UNEXPECTED isVerified() method result (" + + !isVerified + ") for " + s_type + ": " + + className + "(" + s_verified_sign + ")"); + isVerified_method_errors++; + } + else { + print_log_on_verbose("--> isVerified001: expected isVerified() method result (" + + isVerified + ") for " + s_type + ": " + + className + "(" + s_verified_sign + ")"); + } + } + logHandler.display("--> isVerified001: checking debugee's classes completed!"); + logHandler.display("--> isVerified001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + logHandler.complain("##> isVerified001: \"class not found ERRORS\" counter = " + + class_not_found_errors); + } + if (isVerified_method_errors > 0) { + logHandler.complain("##> isVerified001: isVerified() method ERRORS counter = " + + isVerified_method_errors); + } + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + isVerified_method_errors > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isVerified001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + logHandler.complain + ("##> isVerified001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> isVerified001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001/TestDescription.java new file mode 100644 index 00000000000..8b89469aad9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isVerified/isVerified001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/isVerified/isVerified001 test + * checks the isVerified() method of ReferenceType interface + * of the com.sun.jdi package for ClassType, InterfaceType. + * COMMENTS + * The test is corrected and updated as follows: + * - the checks for "not_verif_cls" and "not_verif_interf" are removed + * because the logic of other checks doesn't allow to get + * corresponding objects in the debuggee; + * - statements for establishing LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "out_stream.println" are replaced with + * "logHandler.display" or "logHandler.complain". + * ------------------------------------------------------- + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isVerified.isVerified001 + * nsk.jdi.ReferenceType.isVerified.isVerified001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isVerified.isVerified001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001a.java new file mode 100644 index 00000000000..4f4649dd033 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isVerified001a.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isVerified; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isVerified001 JDI test. + */ + +public class isVerified001a { + + static boolean verbose_mode = false; + + isVerified001 a001_0 = new isVerified001(); + + not_verif_cls not_verif_cls_0, not_verif_cls_1[] = {not_verif_cls_0}; + + not_verif_interf not_verif_interf_0, not_verif_interf_1[] = {not_verif_interf_0}; + + verif_class verif_class_0 = new verif_class(); + + verif_subcl verif_subcl_0 = new verif_subcl(); + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i isVerified001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + isVerified001a isVerified001a_obj = new isVerified001a(); + + print_log_on_verbose("**> isVerified001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isVerified001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isVerified001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isVerified001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isVerified001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** not verified class */ +class not_verif_cls {} + +/** not verified interface */ +interface not_verif_interf {} + +/** verified class */ +class verif_class { + + static { + int int_var = 1; + } + +} + +/** verified interface */ +interface verif_interf { + static final int int_var = 1; +} + +/** verified subclass */ +class verif_subcl implements verif_interf { + static int my_int_var = int_var; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002.java new file mode 100644 index 00000000000..b5fe3449d68 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isVerified; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method isVerified() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class isverified002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class isVerifieds of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.isVerified.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "isverified002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "isverified002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new isverified002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/isVerified/isverified002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/isVerified/isverified002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/isVerified/isverified002 test LOG:"); + print_log_anyway("--> test checks isVerified() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> isverified002: isverified002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isverified002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> isverified002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isverified002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isverified002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> isverified002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isverified002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean isVerified_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> isverified002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> isverified002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> isverified002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> isverified002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> isverified002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> isverified002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> isverified002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.isVerified() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> isverified002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> isverified002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> isverified002: check that checked class has been unloaded really..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> isverified002: checked class has been unloaded really: " + checked_class); + } + else { + print_log_without_verbose + ("--> isverified002: check that checked class has been unloaded really..."); + print_log_anyway + ("--> isverified002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.isVerified() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> isverified002: check ReferenceType.isVerified() method for unloaded class..."); + boolean ref_type_is_verified = false; + try { + ref_type_is_verified = refType.isVerified(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> isverified002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> isverified002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + isVerified_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || isVerified_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> isverified002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> isverified002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> isverified002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of isverified002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TestDescription.java new file mode 100644 index 00000000000..388038571ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isVerified/isverified002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/isVerified/isverified002 test + * checks the isVerified() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * isVerified() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - isverified002b class was moved in 'loadclass' subdirectory; + * - package name was added in isverified002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for isverified002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isVerified.isverified002 + * nsk.jdi.ReferenceType.isVerified.isverified002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isVerified.isverified002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/loadclass/isverified002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/loadclass/isverified002b.java new file mode 100644 index 00000000000..3862effdd30 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002/loadclass/isverified002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the isVerified() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.isVerified; + +class isverified002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002a.java new file mode 100644 index 00000000000..6a769b9c78b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified002a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.isVerified; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the isverified002 JDI test. + */ + +public class isverified002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + static String package_prefix = "nsk.jdi.ReferenceType.isVerified."; + static String checked_class_name = package_prefix + "isverified002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> isverified002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> isverified002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> isverified002a: checked class loaded: " + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> isverified002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> isverified002a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> isverified002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isverified002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isverified002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> isverified002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> isverified002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> isverified002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> isverified002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> isverified002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> isverified002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> isverified002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> isverified002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> isverified002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> isverified002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> isverified002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of isverified002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003.java new file mode 100644 index 00000000000..47e594e51b7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.isVerified; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; +import java.util.jar.*; + +/** + */ +public class isverified003 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ReferenceType.isVerified."; + private final static String className = "isverified003"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String classLoaderName = prefix + "fields002aClassLoader"; + private final static String classFieldName1 = "loadedClass1"; + private final static String classFieldName2 = "loadedClass2"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + try { + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + throw new Failure("Class '" + debuggeeName + "' not found."); + } else { + execTest(); + } + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain("Unexpected Exception: " + e.getMessage()); + e.printStackTrace(out); + } finally { + debuggee.quit(); + } + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + ReferenceType refType1 = getFieldType(classFieldName1); + ReferenceType refType2 = getFieldType(classFieldName2); + + display("isPrepared() returned " + refType1.isPrepared() + " for " + refType1); +// display("isPrepared() returned " + refType2.isPrepared() + " for " + refType2); + boolean result1 = refType1.isVerified(); + boolean result2 = refType2.isVerified(); + if (result1 != result2) { + complain("isVerified() returned different results :" + + "\n\t '" + result1 + "' for " + refType1 + "\n\t '" + result2 + "' for " + refType2); + exitStatus = Consts.TEST_FAILED; + } + } + + //--------------------------------------------------------- test specific methods + + private static ReferenceType getFieldType (String fieldName) { + ReferenceType refType = null; + while (true) { + Field classField = debuggeeClass.fieldByName(fieldName); + if ( classField == null) { + complain("Checked field is not found in the debuggee: " + fieldName); + break; + } + + Value classValue = debuggeeClass.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + complain("Unexpected exception while getting ClassObjectReference : " + e.getMessage()); + break; + } + + refType = classObjRef.reflectedType(); + break; + } + if (refType == null) { + throw new Failure("Cannot find ReferenceType for : " + fieldName); + } + return refType; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/TestDescription.java new file mode 100644 index 00000000000..24cf76e1a3b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/isVerified/isverified003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that an implementation of the + * com.sun.jdi.ReferenceType.isVerified() method conforms + * with its spec. + * The test verifies an assertion: + * public boolean isVerified() + * Determines if this type has been verified. + * The test consists of: + * debugger application - nsk.jdi.ReferenceType.isVerified.isverified003, + * debuggee application - nsk.jdi.ReferenceType.isVerified.isverified003a, + * custom-loaded classes - nsk.jdi.ReferenceType.isVerified.isverified003b, + * nsk.jdi.ReferenceType.isVerified.isverified003c + * The test checks up results of the method for two classes loaded by + * custom isverified003aClassLoader loader. The custom loader loads + * auxuliary classes until preparation point exclusively. The test fails + * if isVerified() method returns diffrent results for custom-loaded classes + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.isVerified.isverified003 + * nsk.jdi.ReferenceType.isVerified.isverified003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.isVerified.isverified003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/loadclass/isverified003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/loadclass/isverified003b.java new file mode 100644 index 00000000000..42fe42f76ab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/loadclass/isverified003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.isVerified; + +/** + * This class is loaded by isverified003aClassLoader until preparation. + */ +class isverified003b { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/loadclass/isverified003c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/loadclass/isverified003c.java new file mode 100644 index 00000000000..75e4abab846 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003/loadclass/isverified003c.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.isVerified; + +/** + * This class is loaded by isverified003aClassLoader until preparation. + */ +class isverified003c { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003a.java new file mode 100644 index 00000000000..229c0840e31 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isVerified/isverified003a.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.isVerified; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * The debugged applcation of the test. + */ +public class isverified003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + private final static String prefix = "nsk.jdi.ReferenceType.isVerified."; + private final static String checkedClassName1 = prefix + "isverified003b"; + private final static String checkedClassName2 = prefix + "isverified003c"; + static isverified003aClassLoader customClassLoader; + static Class loadedClass1; + static Class loadedClass2; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) throws ClassNotFoundException { + + exitStatus = Consts.TEST_PASSED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + String checkedClassDir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + customClassLoader = new isverified003aClassLoader(checkedClassDir); + + loadedClass1 = loadUntilPreparation (checkedClassName1); + loadedClass2 = loadUntilPreparation (checkedClassName2); + + pipe.println(isverified003.SIGNAL_READY); + + receiveSignal(isverified003.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + + private static Class loadUntilPreparation (String className) throws ClassNotFoundException { + Class loadedClass = customClassLoader.preloadClass(className); + // ensure that class was loaded by custom class loader + if (!(loadedClass.getClassLoader() instanceof isverified003aClassLoader)) { + throw new Failure("Default system loader was used to load class " + className); + } + display ("Checked class loaded but not prepared: " + className); + return loadedClass; + } +} + +//--------------------------------------------------------- test specific classes + +/** + * Custom class loader. + */ +class isverified003aClassLoader extends ClassLoader { + + private String classPath; + + public isverified003aClassLoader(String classPath) { + super(isverified003aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public Class preloadClass (String className) throws ClassNotFoundException { + return findClass(className); + } + + protected synchronized Class findClass(String name) throws ClassNotFoundException { + String classFileName = classPath + "/" + name.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(name, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001.java new file mode 100644 index 00000000000..356d1c0ee5b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.locationsOfLine_i; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.locationsOfLine(int)
    + * complies with its specification.
    + *
    + * The test checks up that for each line in the List returned
    + * by the method ReferenceType.allLineLocations(),
    + * the method locationsOfLine(lineNumber) returns
    + * non-empty List object in which each object is a Location object.
    + * Not throwing AbsentInformationException is checked up as well.
    + */ + +public class locationsofline_i001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new locationsofline_i001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.locationsOfLine_i.locationsofline_i001a"; + + String mName = "nsk.jdi.ReferenceType.locationsOfLine_i"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List locations = null; + ReferenceType refType = null; + + + log2(" getting: List classes = vm.classesByName(mName + '.TestClass');"); + List classes = vm.classesByName(mName + ".TestClass"); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2(" getting a tested ReferenceType object 'refType'"); + refType = (ReferenceType) classes.get(0); + + log2("......locations = refType.allLineLocations(); no AbsentInformationException is expected"); + try { + locations = refType.allLineLocations(); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + + log2("......checking up on a value of locations.size(); 0 is not expected"); + int size = locations.size(); + if (size == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + ListIterator li1 = locations.listIterator(); + + log2("......the loop of checking locations in the returned list;"); + log2(" AbsentInformationException is not expected"); + + label1: + for (int ifor1 = 0; ifor1 < size; ifor1++) { + + int lineNumber = ((Location) li1.next()).lineNumber(); + + try { + log2("......List lineLocations = refType.locationsOfLine(" + lineNumber + ");"); + List lineLocations = refType.locationsOfLine(lineNumber); + int size1 = lineLocations.size(); + if (size1 == 0) { + testExitCode = FAILED; + log3("ERROR: lineLocations.size() == 0"); + break label1; + } + ListIterator li2 = lineLocations.listIterator(); + try { + for (; li2.hasNext(); ) { + Location loc = (Location) li2.next(); + } + } catch ( ClassCastException e) { + testExitCode = FAILED; + log3("ERROR: ClassCastException, that is, element is not Location"); + break label1; + } + } catch ( AbsentInformationException e2 ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break label1; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001/TestDescription.java new file mode 100644 index 00000000000..40ec864d198 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001/TestDescription.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.locationsOfLine_i() + * complies with its spec: + * public List locationsOfLine(int lineNumber) + * throws AbsentInformationException + * Returns a List containing all Location objects that + * map to the given line number. + * This method is equivalent to + * locationsOfLine(vm.getDefaultStratum(), null, lineNumber) - + * see locationsOfLine(java.lang.String,java.lang.String,int) + * for more information. + * Parameters: lineNumber - the line number + * Returns: a List of all Location objects that map to the given line. + * Throws: AbsentInformationException - + * if there is no line number information for this class. + * ClassNotPreparedException - + * if this class not yet been prepared. + * The test checks up that for each line in the List returned by the method + * ReferenceType.allLineLocations(), the method locationsOfLine(lineNumber) + * returns non-empty List object in which each object is a Location object. + * Not throwing AbsentInformationException is checked up as well. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.locationsOfLine_i.locationsofline_i001; + * the debuggee program - nsk.jdi.ReferenceType.locationsOfLine_i.locationsofline_i001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The option + * JAVAC_OPTS=-g + * is put into the locationsofline002.cfg file. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.locationsOfLine_i.locationsofline_i001 + * nsk.jdi.ReferenceType.locationsOfLine_i.locationsofline_i001a + * + * @comment make sure locationsofline_i001a is compiled with full debug info + * @clean nsk.jdi.ReferenceType.locationsOfLine_i.locationsofline_i001a + * @compile -g:lines,source,vars ../locationsofline_i001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.locationsOfLine_i.locationsofline_i001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001a.java new file mode 100644 index 00000000000..d5e4ca9a40c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i001a.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.locationsOfLine_i; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the locationsofline_i001 JDI test. + */ + +public class locationsofline_i001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ReferenceType.locationsOfLine(int) + * properly returns an empty list for arrays (ArrayType), primitive + * classes, and for interfaces (InterfaceType) if the interface has + * no executable code in its class initialization at the specified line + * number.

    + * + * Debugger part of it attempts to get locations that map to the debuggee + * field values/type declaration, which themselves are:
    + * primitive classes, arrays of primitive types and classes, and finally, + * an interface type. + */ +public class locationsofline_i002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.locationsOfLine_i.locationsofline_i002t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 25; + // tested fields and used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr", + "dummyIf" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new locationsofline_i002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "locationsofline_i002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; i + * 32 --> 1001 + * 32 --> 1002 + * 32 --> 1003 + * 32 --> 1004 + * For this case locationsOfLine('TestStratum', null, 1001) should return single location for java line 32, + * and for lines 1002, 1003, 1004 should return empty list. + * 33 --> 1005 + * 36 --> 1005 + * 37 --> 1005 + * 38 --> 1005 + * For this case locationsOfLine('TestStratum', null, 1005) should return 4 locations for java lines 33 - 36, + * 39 --> 1006 + * 40 --> 1007 + * 41 --> 1008 + * For this case locationsOfLine for lines 1006-1007 should return single corresponding java line. + * Debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that for obtained ReferenceType method 'com.sun.jdi.Method.locationsOfLine(String stratum, String sourceName, int lineNumber)' + * returns correct values for 3 cases described above. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsOfLine_ssi003.locationsOfLine_ssi003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsOfLine_ssi003.locationsOfLine_ssi003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + */ + +package nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsOfLine_ssi003; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class locationsOfLine_ssi003 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new locationsOfLine_ssi003().runIt(argv, out); + } + + protected void preparePatchedClassFile(String className) { + String smapFileName = "TestSMAP.smap"; + SmapGenerator smapGenerator = new SmapGenerator(); + + SmapStratum smapStratum = new SmapStratum(testStratumName); + smapStratum.addFile(testStratumSourceName, testStratumSourcePath); + + // single output line is mapped to the multiple input lines + // 1001 -> 32 + // 1002 -> 32 + // 1003 -> 32 + // 1004 -> 32 + smapStratum.addLineData(1001, testStratumSourceName, 1, INIT_LINE, 1); + smapStratum.addLineData(1002, testStratumSourceName, 1, INIT_LINE, 1); + smapStratum.addLineData(1003, testStratumSourceName, 1, INIT_LINE, 1); + smapStratum.addLineData(1004, testStratumSourceName, 1, INIT_LINE, 1); + + // multiple output lines are mapped to the single input line + // 1005 -> 10 + // 1005 -> 11 + // 1005 -> 12 + // 1005 -> 13 + smapStratum.addLineData(1005, testStratumSourceName, 1, INIT_LINE + 1, 1); + smapStratum.addLineData(1005, testStratumSourceName, 1, INIT_LINE + 2, 1); + smapStratum.addLineData(1005, testStratumSourceName, 1, INIT_LINE + 3, 1); + smapStratum.addLineData(1005, testStratumSourceName, 1, INIT_LINE + 4, 1); + + // single output line is mapped to the single input line + // 1006 -> 14 + // 1007 -> 15 + // 1008 -> 16 + smapStratum.addLineData(1006, testStratumSourceName, 1, INIT_LINE + 5, 1); + smapStratum.addLineData(1007, testStratumSourceName, 1, INIT_LINE + 6, 1); + smapStratum.addLineData(1008, testStratumSourceName, 1, INIT_LINE + 7, 1); + + smapGenerator.addStratum(smapStratum, false); + + savePathcedClassFile(className, smapGenerator, smapFileName); + } + + public void doTest() { + String className = TestClass1.class.getName(); + + preparePatchedClassFile(className); + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + List expectedLocations = new ArrayList(); + + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1001, INIT_LINE)); + log.display("Check case when single output line is mapped to the multiple input lines"); + // single output line is mapped to the multiple input lines + // 1001 -> 32 + // 1002 -> 32 + // 1003 -> 32 + // 1004 -> 32 + try { + // locationsOfLine.(testStratum, testStratumSource, 1001) should + // return single java location + compareLocations( + referenceType.locationsOfLine(testStratumName, testStratumSourceName, 1001), + expectedLocations, + testStratumName); + + // locationsOfLine.(testStratum, testStratumSource, [1002, 1003, + // 1004]) should return empty list + expectedLocations.clear(); + for (int i = 1002; i <= 1004; i++) + compareLocations( + referenceType.locationsOfLine(testStratumName, testStratumSourceName, i), + expectedLocations, + testStratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1005, INIT_LINE + 1)); + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1005, INIT_LINE + 2)); + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1005, INIT_LINE + 3)); + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1005, INIT_LINE + 4)); + + log.display("Check case when multiple output lines are mapped to the single input line"); + // multiple output lines are mapped to the single input line + // 1005 -> 33 + // 1005 -> 34 + // 1005 -> 35 + // 1005 -> 36 + try { + // locationsOfLine.(testStratum, testStratumSource, 1005) should + // return 4 java locations + compareLocations( + referenceType.locationsOfLine(testStratumName, testStratumSourceName, 1005), + expectedLocations, + testStratumName); + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + + log.display("Check case when single output line is mapped to the single input line"); + // single output line is mapped to the single input line + // 1006 -> 37 + // 1007 -> 38 + // 1008 -> 39 + try { + for (int i = 0; i < 3; i++) { + // locationsOfLine.(testStratum, testStratumSource, line) should + // return 1 java locations + expectedLocations.clear(); + expectedLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath, + "", 1006 + i, INIT_LINE + 5 + i)); + compareLocations( + referenceType.locationsOfLine(testStratumName, testStratumSourceName, 1006 + i), + expectedLocations, + testStratumName); + } + } catch (AbsentInformationException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi004/locationsOfLine_ssi004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi004/locationsOfLine_ssi004.java new file mode 100644 index 00000000000..b684cdac6f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi004/locationsOfLine_ssi004.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi004. + * VM Testbase keywords: [quick, jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that method 'com.sun.jdi.ReferenceType.locationsOfLine(String stratum, String sourceName, int lineNumber)' returns + * correct values for all stratums available for class and if sourceName == null locaitions for all sources are returned. + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3') and for each of this stratums following line mapping + * is defined (each method has locations in 3 different sources): + * "Java" "TestStratum" + * + * 9 --> 1000, source1, path1 + * 10 --> 1000, source2, path2 + * 11 --> 1000, source3, path3 + * ... ... + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1100, source2, path2 + * 22 --> 1100, source3, path3 + * ... ... + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1200, source2, path2 + * 33 --> 1200, source3, path3 + * ... ... + * Then debugger forces debuggee to load 'TestClass1' from updated class file, obtains ReferenceType for this class + * and checks up that method 'com.sun.jdi.ReferenceType.locationsOfLine(String stratum, String sourceName, int lineNumber)' + * for all test stratums('TestStratum1'-'TestStratum3') returns only expected locations depending on given line number and source name, + * and if source name is null locations for all sources are returned. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsOfLine_ssi004.locationsOfLine_ssi004 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsOfLine_ssi004.locationsOfLine_ssi004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsOfLine_ssi004; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class locationsOfLine_ssi004 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new locationsOfLine_ssi004().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type5(className, testStratumCount); + /* + * Method 'prepareDefaultPatchedClassFile_Type5' creates class file with + * following line mapping for each TestStratum: "Java" "TestStratum" + * + * + * 9 --> 1000, source1, path1 + * 10 --> 1000, source2, path2 + * 11 --> 1000, source3, path3 + * ... + * ... + * + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1100, source2, path2 + * 22 --> 1100, source3, path3 + * ... + * ... + * + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1200, source2, path2 + * 33 --> 1200, source3, path3 ... ... + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName : testStratumData.keySet()) { + check_ReferenceType_locationsOfLine( + referenceType, + stratumName, + false, + testStratumData.get(stratumName).allLocations); + check_ReferenceType_locationsOfLine( + referenceType, + stratumName, + true, + testStratumData.get(stratumName).allLocations); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001.java new file mode 100644 index 00000000000..849b6d50777 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.locationsOfLine_ssi; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.locationsOfLine(String,String,int)
    + * complies with its specification.
    + *
    + * The test checks up that for each line in the List returned
    + * by the method ReferenceType.allLineLocations(),
    + * the method locationsOfLine(defaultStratum,null,lineNumber)
    + * returns non-empty List object
    + * in which each object is a Location object.
    + * Not throwing AbsentInformationException is checked up as well.
    + */ + +public class locationsofline_ssi001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new locationsofline_ssi001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsofline_ssi001a"; + + String mName = "nsk.jdi.ReferenceType.locationsOfLine_ssi"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List locations = null; + ReferenceType refType = null; + + + log2(" getting: List classes = vm.classesByName(mName + '.TestClass');"); + List classes = vm.classesByName(mName + ".TestClass"); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2("...... getting : String defaultStratum = vm.getDefaultStratum();"); + String defaultStratum = vm.getDefaultStratum(); + + log2(" getting a tested ReferenceType object 'refType'"); + refType = (ReferenceType) classes.get(0); + + log2("......locations = refType.allLineLocations(); no AbsentInformationException is expected"); + try { + locations = refType.allLineLocations(); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break ; + } + + log2("......checking up on a value of locations.size(); 0 is not expected"); + int size = locations.size(); + if (size == 0) { + testExitCode = FAILED; + log3("ERROR: locations.size() == 0"); + break ; + } + + ListIterator li1 = locations.listIterator(); + + log2("......the loop of checking locations in the returned list;"); + log2(" AbsentInformationException is not expected"); + + label1: + for (int ifor1 = 0; ifor1 < size; ifor1++) { + + int lineNumber = ((Location) li1.next()).lineNumber(); + + try { + log2("......List lineLocations = refType.locationsOfLine(defaultStratum, null, " + lineNumber + ");"); + List lineLocations = refType.locationsOfLine(defaultStratum, null, lineNumber); + int size1 = lineLocations.size(); + if (size1 == 0) { + testExitCode = FAILED; + log3("ERROR: lineLocations.size() == 0"); + break label1; + } + ListIterator li2 = lineLocations.listIterator(); + try { + for (; li2.hasNext(); ) { + Location loc = (Location) li2.next(); + } + } catch ( ClassCastException e) { + testExitCode = FAILED; + log3("ERROR: ClassCastException, that is, element is not Location"); + break label1; + } + } catch ( AbsentInformationException e2 ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + log3(" ATTENTION: see the README file to this test"); + break label1; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001/TestDescription.java new file mode 100644 index 00000000000..e3a62d9f6dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001/TestDescription.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.locationsOfLine(String,String,int) + * complies with its spec: + * public List locationsOfLine(String stratum, String sourceName, int lineNumber) + * throws AbsentInformationException + * Returns a List containing all Location objects that + * map to the given line number. + * For arrays (ArrayType) and primitive classes, + * the returned list is always empty. + * For interfaces (InterfaceType), the returned list will be non-empty only + * if the interface has executable code in its class initialization + * at the specified line number. An empty list will be returned + * if there is no executable code at the specified line number. + * Returned list is for the specified stratum + * (see Location for a description of strata). + * Parameters: stratum - the stratum to use for comparing line number and + * source name, or null to use the defaultStratum(). + * sourceName - the source name containing the line number, or + * null to match all source names + * lineNumber - the line number + * Returns: a List of all Location objects that map to the given line. + * Throws: AbsentInformationException - + * if there is no line number information for this class. + * Or if sourceName is non-null and source name information is not present. + * ClassNotPreparedException - + * if this class not yet been prepared. + * The test checks up that for each line in the List returned + * by the method ReferenceType.allLineLocations(), + * the method locationsOfLine(defaultStratum,null,lineNumber) + * returns non-empty List object in which each object is a Location object. + * Not throwing AbsentInformationException is checked up as well. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsofline_ssi001; + * the debuggee program - nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsofline_ssi001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsofline_ssi001 + * nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsofline_ssi001a + * + * @comment make sure locationsofline_ssi001a is compiled with full debug info + * @clean nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsofline_ssi001a + * @compile -g:lines,source,vars ../locationsofline_ssi001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsofline_ssi001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001a.java new file mode 100644 index 00000000000..a054dcf3da7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi001a.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.locationsOfLine_ssi; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the locationsofline_ssi001 JDI test. + */ + +public class locationsofline_ssi001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ReferenceType.locationsOfLine(String,String,int) + * properly returns an empty list for arrays (ArrayType), primitive + * classes, and for interfaces (InterfaceType) if the interface has + * no executable code in its class initialization at the specified line + * number.

    + * + * Debugger part of it attempts to get locations that map to the debuggee + * field values/type declaration, which themselves are:
    + * primitive classes, arrays of primitive types and classes, and finally, + * an interface type. + */ +public class locationsofline_ssi002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.locationsOfLine_ssi.locationsofline_ssi002t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 25; + // tested fields and used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr", + "dummyIf" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new locationsofline_ssi002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "locationsofline_ssi002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; imethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methods001 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methods001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "methods001aClassForCheck"; + private final static String not_found_sign = "NOT FOUND"; + private final static String passed_sign = "PASSED"; + private static String methods_for_check[][] = { + +// method name declaring class check result + + {"", class_for_check, not_found_sign}, + {"ClassForCheck", class_for_check, not_found_sign}, + {"s_void_method", class_for_check, not_found_sign}, + {"s_boolean_method", class_for_check, not_found_sign}, + {"s_byte_method", class_for_check, not_found_sign}, + {"s_char_method", class_for_check, not_found_sign}, + {"s_double_method", class_for_check, not_found_sign}, + {"s_float_method", class_for_check, not_found_sign}, + {"s_int_method", class_for_check, not_found_sign}, + {"s_long_method", class_for_check, not_found_sign}, + {"s_string_method", class_for_check, not_found_sign}, + {"s_object_method", class_for_check, not_found_sign}, + {"s_prim_array_method", class_for_check, not_found_sign}, + {"s_ref_array_method", class_for_check, not_found_sign}, + {"s_super_hidden_void_method", class_for_check, not_found_sign}, + {"s_super_hidden_prim_method", class_for_check, not_found_sign}, + {"s_super_hidden_ref_method", class_for_check, not_found_sign}, + {"s_void_par_method", class_for_check, not_found_sign}, + {"s_boolean_par_method", class_for_check, not_found_sign}, + {"s_byte_par_method", class_for_check, not_found_sign}, + {"s_char_par_method", class_for_check, not_found_sign}, + {"s_double_par_method", class_for_check, not_found_sign}, + {"s_float_par_method", class_for_check, not_found_sign}, + {"s_int_par_method", class_for_check, not_found_sign}, + {"s_long_par_method", class_for_check, not_found_sign}, + {"s_string_par_method", class_for_check, not_found_sign}, + {"s_object_par_method", class_for_check, not_found_sign}, + {"s_prim_array_par_method", class_for_check, not_found_sign}, + {"s_ref_array_par_method", class_for_check, not_found_sign}, + {"s_super_hidden_void_par_method", class_for_check, not_found_sign}, + {"s_super_hidden_prim_par_method", class_for_check, not_found_sign}, + {"s_super_hidden_ref_par_method", class_for_check, not_found_sign}, + {"s_native_method", class_for_check, not_found_sign}, + {"s_synchr_method", class_for_check, not_found_sign}, + {"s_final_method", class_for_check, not_found_sign}, + {"s_private_method", class_for_check, not_found_sign}, + {"s_protected_method", class_for_check, not_found_sign}, + {"s_public_method", class_for_check, not_found_sign}, + {"i_void_method", class_for_check, not_found_sign}, + {"i_boolean_method", class_for_check, not_found_sign}, + {"i_byte_method", class_for_check, not_found_sign}, + {"i_char_method", class_for_check, not_found_sign}, + {"i_double_method", class_for_check, not_found_sign}, + {"i_float_method", class_for_check, not_found_sign}, + {"i_int_method", class_for_check, not_found_sign}, + {"i_long_method", class_for_check, not_found_sign}, + {"i_string_method", class_for_check, not_found_sign}, + {"i_object_method", class_for_check, not_found_sign}, + {"i_prim_array_method", class_for_check, not_found_sign}, + {"i_ref_array_method", class_for_check, not_found_sign}, + {"i_super_overridden_void_method", class_for_check, not_found_sign}, + {"i_super_overridden_prim_method", class_for_check, not_found_sign}, + {"i_super_overridden_ref_method", class_for_check, not_found_sign}, + {"i_interf_overridden_void_method", class_for_check, not_found_sign}, + {"i_interf_overridden_prim_method", class_for_check, not_found_sign}, + {"i_interf_overridden_ref_method", class_for_check, not_found_sign}, + {"i_void_par_method", class_for_check, not_found_sign}, + {"i_boolean_par_method", class_for_check, not_found_sign}, + {"i_byte_par_method", class_for_check, not_found_sign}, + {"i_char_par_method", class_for_check, not_found_sign}, + {"i_double_par_method", class_for_check, not_found_sign}, + {"i_float_par_method", class_for_check, not_found_sign}, + {"i_int_par_method", class_for_check, not_found_sign}, + {"i_long_par_method", class_for_check, not_found_sign}, + {"i_string_par_method", class_for_check, not_found_sign}, + {"i_object_par_method", class_for_check, not_found_sign}, + {"i_prim_array_par_method", class_for_check, not_found_sign}, + {"i_ref_array_par_method", class_for_check, not_found_sign}, + {"i_super_overridden_void_par_method", class_for_check, not_found_sign}, + {"i_super_overridden_prim_par_method", class_for_check, not_found_sign}, + {"i_super_overridden_ref_par_method", class_for_check, not_found_sign}, + {"i_interf_overridden_void_par_method", class_for_check, not_found_sign}, + {"i_interf_overridden_prim_par_method", class_for_check, not_found_sign}, + {"i_interf_overridden_ref_par_method", class_for_check, not_found_sign}, + {"i_abstract_method", class_for_check, not_found_sign}, + {"i_native_method", class_for_check, not_found_sign}, + {"i_synchr_method", class_for_check, not_found_sign}, + {"i_final_method", class_for_check, not_found_sign}, + {"i_private_method", class_for_check, not_found_sign}, + {"i_protected_method", class_for_check, not_found_sign}, + {"i_public_method", class_for_check, not_found_sign}, + {"", class_for_check, not_found_sign} + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new methods001().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/methods/methods001 test FAILED"); + } + else { + print_log_anyway("\n==> nsk/jdi/ReferenceType/methods/methods001 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/methods/methods001 test LOG:"); + print_log_anyway("==> test checks methods() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methods001: methods001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> methods001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> methods001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methods001: debugee's \"ready\" signal recieved!"); + } + + print_log_anyway + ("--> methods001: check ReferenceType.methods() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean methods_exception_thrown = false; + int methods_for_check_number = methods_for_check.length; + int not_found_methods_number = 0; + int found_methods_number = 0; + int unexpected_found_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + print_log_anyway("##> methods001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List found_methods_list = null; + try { + found_methods_list = refType.methods(); + } + catch (Throwable thrown) { + print_log_anyway("##> methods001: FAILED: ReferenceType.methods() throws unexpected " + + thrown); + methods_exception_thrown = true; + break; + } + found_methods_number = found_methods_list.size(); + Method found_methods[] = new Method[found_methods_number]; + String unexpected_found_methods[] = new String[found_methods_number]; + found_methods_list.toArray(found_methods); + for (int i=0; i methods001: FAILED: method is NOT found: " + current_method_for_check); + not_found_methods_number++; + } + else { + print_log_on_verbose + ("--> methods001: PASSED for method: " + current_method_for_check); + } + } + for (int i=0; i methods001: FAILED: unexpected found method: " + unexpected_found_methods[i]); + } + break; + } + + print_log_anyway("--> methods001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || methods_exception_thrown ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_anyway("--> methods001: expected found methods number = " + methods_for_check_number); + print_log_anyway("--> methods001: in fact found methods number = " + + found_methods_number); + print_log_anyway("--> methods001: expected and in fact found methods number = " + + (methods_for_check_number - not_found_methods_number)); + print_log_anyway + ("##> methods001: NOT found methods number = " + not_found_methods_number); + print_log_anyway + ("##> methods001: UNEXPECTED found methods number = " + unexpected_found_methods_number); + } + if ( not_found_methods_number + unexpected_found_methods_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methods001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> methods001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methods001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001/TestDescription.java new file mode 100644 index 00000000000..c9772fbbb0f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methods/methods001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methods/methods001 test + * checks the methods() method of ReferenceType interface + * of the com.sun.jdi package : + * the ReferenceType.methods() method is checked for methods of + * debugee's class which extends super class and implements interface. + * The test expects that only declared directly in the checked class + * methods should be included in Method list returned by the methods() method. + * Each method is checked for method name and declaring class name. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methods.methods001 + * nsk.jdi.ReferenceType.methods.methods001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methods.methods001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001a.java new file mode 100644 index 00000000000..1055d9f0607 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods001a.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the methods001 JDI test. + */ + +public class methods001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + private final static String + package_prefix = "nsk.jdi.ReferenceType.methods."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "methods001aClassForCheck"; + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i methods001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + Class checked_class_classobj = null; + try { + checked_class_classobj = + Class.forName(checked_class_name, true, methods001a.class.getClassLoader()); + print_log_on_verbose + ("--> methods001a: checked class loaded:" + checked_class_name); + } + catch ( Throwable thrown ) { // ClassNotFoundException +// System.err.println +// ("**> methods001a: load class: Throwable thrown = " + thrown.toString()); + print_log_on_verbose + ("--> methods001a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> methods001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methods001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methods001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methods001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methods001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +abstract class methods001aClassForCheck extends methods001aSuperClassForCheck + implements methods001aInterfaceForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods without params + static void s_void_method() {} + static boolean s_boolean_method() {return true;} + static byte s_byte_method() {return (byte)1;} + static char s_char_method() {return (char)1;} + static double s_double_method() {return (double)100.99;} + static float s_float_method() {return (float)100.88;} + static int s_int_method() {return 100;} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + // static methods with params + static void s_void_par_method(boolean z) {} + static boolean s_boolean_par_method(boolean z) {return true;} + static byte s_byte_par_method(byte b) {return (byte)1;} + static char s_char_par_method(char ch) {return (char)1;} + static double s_double_par_method(double d) {return (double)100.99;} + static float s_float_par_method(float f) {return (float)100.88;} + static int s_int_par_method(int i) {return 100;} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + // other static methods + native static Object s_native_method(Object obj); + static synchronized Object s_synchr_method(Object obj) {return new Object();} + final static Object s_final_method(Object obj) {return new Object();} + private static Object s_private_method(Object obj) {return new Object();} + protected static Object s_protected_method(Object obj) {return new Object();} + public static Object s_public_method(Object obj) {return new Object();} + + // instance methods without params + void i_void_method() {} + boolean i_boolean_method() {return true;} + byte i_byte_method() {return (byte)1;} + char i_char_method() {return (char)1;} + double i_double_method() {return (double)100.99;} + float i_float_method() {return (float)100.88;} + int i_int_method() {return 100;} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + public void i_interf_overridden_void_method() {} + public int i_interf_overridden_prim_method() {return 100;} + public Object i_interf_overridden_ref_method() {return new Object();} + + // instance methods with params + void i_void_par_method(boolean z) {} + boolean i_boolean_par_method(boolean z) {return true;} + byte i_byte_par_method(byte b) {return (byte)1;} + char i_char_par_method(char ch) {return (char)1;} + double i_double_par_method(double d) {return (double)100.99;} + float i_float_par_method(float f) {return (float)100.88;} + int i_int_par_method(int i) {return 100;} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public void i_interf_overridden_void_par_method(int i) {} + public int i_interf_overridden_prim_par_method(int i) {return 100;} + public Object i_interf_overridden_ref_par_method(Object obj) {return new Object();} + + // other instance methods + abstract Object i_abstract_method(Object obj); + native Object i_native_method(Object obj); + synchronized Object i_synchr_method(Object obj) {return new Object();} + final Object i_final_method(Object obj) {return new Object();} + private Object i_private_method(Object obj) {return new Object();} + protected Object i_protected_method(Object obj) {return new Object();} + public Object i_public_method(Object obj) {return new Object();} + + // static initializer + static {} + + +} + +abstract class methods001aSuperClassForCheck { + + static void s_super_void_method(long l) {} + static long s_super_prim_method(long l) {return 100;} + static Object s_super_ref_method(Object obj) {return new Object();} + + void i_super_void_method(long l) {} + long i_super_prim_method(long l) {return 100;} + Object i_super_ref_method(Object obj) {return new Object();} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public Object i_multiple_inherited_method(Object obj) {return new Object();} + +} + +interface methods001aInterfaceForCheck { + + void i_interf_void_method(long l); + long i_interf_prim_method(long l); + Object i_interf_ref_method(Object obj); + + void i_interf_overridden_void_method(); + int i_interf_overridden_prim_method(); + Object i_interf_overridden_ref_method(); + + void i_interf_overridden_void_par_method(int i); + int i_interf_overridden_prim_par_method(int i); + Object i_interf_overridden_ref_par_method(Object obj); + + public Object i_multiple_inherited_method(Object obj); + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002.java new file mode 100644 index 00000000000..b8bf39e1842 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methods002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methods002", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "methods002aClassForCheck"; + + private final static String classLoaderName = package_prefix + "methods002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new methods002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/methods/methods002 test FAILED"); + } + else { + print_log_on_verbose("\n==> nsk/jdi/ReferenceType/methods/methods002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + test_log_handler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, test_log_handler); + + print_log_on_verbose("==> nsk/jdi/ReferenceType/methods/methods002 test LOG:"); + print_log_on_verbose("==> test checks methods() method of ReferenceType interface "); + print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + debugee_launch_command = debugeeName + " -vbs"; + } + + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + + debugee.redirectStderr(out); + print_log_on_verbose("--> methods002: methods002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> methods002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> methods002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methods002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> methods002: check ReferenceType.methods() method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean methods_method_error = false; + + while ( true ) { // test body + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> methods002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> methods002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + List methods_list = null; + try { + methods_list = refType.methods(); + print_log_anyway + ("##> methods002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + methods_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> methods002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> methods002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + methods_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || methods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methods002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> methods002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methods002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/TestDescription.java new file mode 100644 index 00000000000..cb1c5027693 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methods/methods002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methods/methods002 test + * checks the methods() method of ReferenceType interface + * of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.methods() method is called for + * this class - ClassNotPreparedException should be thrown + * in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements ""print_log_anyway"" are replaced with + * "print_log_on_verbose". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methods.methods002 + * nsk.jdi.ReferenceType.methods.methods002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methods.methods002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/loadclass/methods002aClassForCheck.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/loadclass/methods002aClassForCheck.java new file mode 100644 index 00000000000..99934901d2e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002/loadclass/methods002aClassForCheck.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.methods; + +/** + * This class is loaded by methods002aClassLoader . + */ +class methods002aClassForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods + static void s_void_method() {} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_void_par_method(boolean z) {} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + + // instance methods + void i_void_method() {} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_void_par_method(boolean z) {} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + // static initializer + static {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002a.java new file mode 100644 index 00000000000..8ac4f767fe1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods002a.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + +/** + * This class is used as debugee application for the methods002 JDI test. + */ + +public class methods002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String + package_prefix = "nsk.jdi.ReferenceType.methods."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "methods002aClassForCheck"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i methods002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + methods002aClassLoader customClassLoader = new methods002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> methods002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> methods002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> methods002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methods002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methods002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methods002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methods002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class methods002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public methods002aClassLoader(String classPath, String className) { + super(methods002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003.java new file mode 100644 index 00000000000..e878fae9e39 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methods003 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methods.", + thisClassName = package_prefix + "methods003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "methods003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new methods003().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/methods/methods003 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/methods/methods003 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/methods/methods003 test LOG:"); + print_log_anyway("--> test checks methods() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methods003: methods003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> methods003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> methods003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methods003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> methods003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> methods003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methods003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean methods_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> methods003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> methods003: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> methods003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> methods003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> methods003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> methods003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> methods003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.methods() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> methods003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methods003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> methods003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> methods003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> methods003: check that checked class has been unloaded realy..."); + print_log_anyway + ("--> methods003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.methods() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> methods003: check ReferenceType.methods() method for unloaded class..."); + List methods_list = null; + try { + methods_list = refType.methods(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> methods003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> methods003: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + methods_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || methods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methods003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> methods003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methods003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of methods003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TestDescription.java new file mode 100644 index 00000000000..64efccc93a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methods/methods003. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methods/methods003 test + * checks the methods() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * methods() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - methods003b class was moved in 'loadclass' subdirectory; + * - package name was added in methods003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for methods003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methods.methods003 + * nsk.jdi.ReferenceType.methods.methods003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methods.methods003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/loadclass/methods003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/loadclass/methods003b.java new file mode 100644 index 00000000000..fb3220723b0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003/loadclass/methods003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the methods() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.methods; + +class methods003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003a.java new file mode 100644 index 00000000000..0e8c2e3399c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methods; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the methods003 JDI test. + */ + +public class methods003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.methods."; + private final static String checked_class_name = package_prefix + "methods003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> methods003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> methods003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> methods003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> methods003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> methods003a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> methods003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methods003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methods003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> methods003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> methods003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> methods003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> methods003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> methods003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> methods003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> methods003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methods003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methods003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methods003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methods003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of methods003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004.java new file mode 100644 index 00000000000..952c5e1515a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methods004 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methods004", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "methods004aInterfaceForCheck"; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new methods004().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/methods/methods004 test FAILED"); + } + else { + print_log_anyway("\n==> nsk/jdi/ReferenceType/methods/methods004 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/methods/methods004 test LOG:"); + print_log_anyway("==> test checks methods() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for class without any methods\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methods004: methods004a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> methods004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> methods004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methods004: debugee's \"ready\" signal recieved!"); + } + + print_log_anyway + ("--> methods004: check ReferenceType.methods() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean methods_method_error = false; + int returned_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + print_log_anyway("##> methods004: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List methods_list = null; + try { + methods_list = refType.methods(); + } + catch (Throwable thrown) { + print_log_anyway("##> methods004: FAILED: ReferenceType.methods() throws unexpected " + + thrown); + methods_method_error = true; + break; + } + returned_methods_number = methods_list.size(); + if ( returned_methods_number == 0 ) { + break; + } + Method returned_methods[] = new Method[returned_methods_number]; + methods_list.toArray(returned_methods); + for (int i=0; i methods004: FAILED: unexpected found method: " + returned_method_info); + } + break; + } + + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || methods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + if ( returned_methods_number > 0 ) { + print_log_anyway + ("##> methods004: UNEXPECTED all methods number = " + returned_methods_number); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_anyway + ("--> methods004: PASSED: returned list of methods is empty!"); + } + + print_log_on_verbose("--> methods004: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> methods004: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methods004: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004/TestDescription.java new file mode 100644 index 00000000000..604af2f7ce3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methods/methods004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methods/methods004 test + * checks the methods() method of ReferenceType interface + * of the com.sun.jdi package for class without any methods: + * the ReferenceType.methods() method is checked for + * debugee's interface which does not contain any methods + * but extends a super interface with declared methods. + * The test expects the returned list of methods to be empty. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methods.methods004 + * nsk.jdi.ReferenceType.methods.methods004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methods.methods004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004a.java new file mode 100644 index 00000000000..41c1dec7e5e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods004a.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the methods004 JDI test. + */ + +public class methods004a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i methods004a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + methods004aClassForCheck class_for_check = new methods004aClassForCheck(); + + print_log_on_verbose("**> methods004a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methods004a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methods004a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("##> methods004a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("##> methods004a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class methods004aClassForCheck implements methods004aInterfaceForCheck { + + public void i_interf_void_method(long l) {} + public long i_interf_prim_method(long l) {return l;} + public Object i_interf_ref_method(Object obj) {return obj;} +} + +interface methods004aInterfaceForCheck extends methods004aSuperInterfaceForCheck{ +} + +interface methods004aSuperInterfaceForCheck { + void i_interf_void_method(long l); + long i_interf_prim_method(long l); + Object i_interf_ref_method(Object obj); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005.java new file mode 100644 index 00000000000..9e048f477f8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.methods; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.methods() + * properly returns an empty list for arrays (ArrayType) and primitive + * classes.

    + * + * Debugger part of it attempts to get a list of methods in several + * reference types corresponding to debuggee field values, which are:
    + * primitive classes themselves, and arrays of primitive types and classes. + */ +public class methods005 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.methods.methods005t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 24; + // tested fields used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new methods005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "methods005t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; i", null }, + {"values", null }, + {"valueOf", null }, + {"foo", null} }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + // check there are enum methods + List l = checkedClass.methods(); + if (l.isEmpty()) { + complain("\t ReferenceType.methods() returned empty list for type: " + className); + exitStatus = Consts.TEST_FAILED; + } else { + for (int i = 0; i < expectedEnumMethods.length; i++) { + Iterator it = l.iterator(); + while (it.hasNext()) { + Method checkedMethod = it.next(); + if (expectedEnumMethods[i][0].equals(checkedMethod.name()) ) + + expectedEnumMethods[i][1] = "found"; + } + } + + for (int i = 0; i < expectedEnumMethods.length; i++) { + if (expectedEnumMethods[i][1] != null) { + display("enum " + className + " has Method " + expectedEnumMethods[i][0]); + } else { + complain("enum " + className + " does not have Method " + expectedEnumMethods[i][0]); + exitStatus = Consts.TEST_FAILED; + } + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006/TestDescription.java new file mode 100644 index 00000000000..7a8b5932e64 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methods/methods006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for methods() method of ReferenceType interface. + * The test checks if the method returns methods declared in + * mirrored enum type, methods automatically generated + * by javac for enums, i.e. values, valueOf and default + * constructor. + * The test consists of a debugger program (methods006.java) + * and debuggee application (methods006a.java). + * Package name is nsk.jdi.ReferenceType.methods . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls methods() method for each field + * of enum type declared in methods006a class. The result list + * list must contain all expected methods. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methods.methods006 + * nsk.jdi.ReferenceType.methods.methods006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methods.methods006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006a.java new file mode 100644 index 00000000000..365e2306dea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods006a.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.methods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class methods006a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static methods006Enum1 f1 = methods006Enum1.e2; + static methods006Enum2 f2 = methods006Enum2.e1; + static methods006Enum1.Enum1_ f3 = methods006Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(methods006.SIGNAL_READY); + receiveSignal(methods006.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum methods006Enum1 implements methods006i1, methods006i2 { + e1, e2; + public int foo() {return 1;} + + enum Enum1_ implements methods006i1, methods006i2 { + e1, e2; + public int foo() {return 3;} + } +} + +enum methods006Enum2 implements methods006i1, methods006i2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + + abstract int val(); + public int foo() {return 2;} +} + +interface methods006i1 { + public final int i1 = 1; + public abstract int foo(); +} + +interface methods006i2 { + public final int i1 = 1; + public abstract int foo(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001.java new file mode 100644 index 00000000000..1b17c1e1919 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001.java @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methodsByName(String name) + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methbyname_s001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_s.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methbyname_s001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "methbyname_s001aClassForCheck"; + private final static String super_class_for_check = package_prefix + "methbyname_s001aSuperClassForCheck"; + private final static String interface_for_check = package_prefix + "methbyname_s001aInterfaceForCheck"; + private final static String not_existing_class = "not_existing_class"; + private static String methods_for_check[][] = { + +// method name declaring class + + {"", class_for_check }, + {"ClassForCheck", class_for_check }, + {"s_void_method", class_for_check }, + {"s_boolean_method", class_for_check }, + {"s_byte_method", class_for_check }, + {"s_char_method", class_for_check }, + {"s_double_method", class_for_check }, + {"s_float_method", class_for_check }, + {"s_int_method", class_for_check }, + {"s_long_method", class_for_check }, + {"s_string_method", class_for_check }, + {"s_object_method", class_for_check }, + {"s_prim_array_method", class_for_check }, + {"s_ref_array_method", class_for_check }, + {"s_super_hidden_void_method", class_for_check }, + {"s_super_hidden_prim_method", class_for_check }, + {"s_super_hidden_ref_method", class_for_check }, + {"s_void_par_method", class_for_check }, + {"s_boolean_par_method", class_for_check }, + {"s_byte_par_method", class_for_check }, + {"s_char_par_method", class_for_check }, + {"s_double_par_method", class_for_check }, + {"s_float_par_method", class_for_check }, + {"s_int_par_method", class_for_check }, + {"s_long_par_method", class_for_check }, + {"s_string_par_method", class_for_check }, + {"s_object_par_method", class_for_check }, + {"s_prim_array_par_method", class_for_check }, + {"s_ref_array_par_method", class_for_check }, + {"s_super_hidden_void_par_method", class_for_check }, + {"s_super_hidden_prim_par_method", class_for_check }, + {"s_super_hidden_ref_par_method", class_for_check }, + {"s_native_method", class_for_check }, + {"s_synchr_method", class_for_check }, + {"s_final_method", class_for_check }, + {"s_private_method", class_for_check }, + {"s_protected_method", class_for_check }, + {"s_public_method", class_for_check }, + {"i_void_method", class_for_check }, + {"i_boolean_method", class_for_check }, + {"i_byte_method", class_for_check }, + {"i_char_method", class_for_check }, + {"i_double_method", class_for_check }, + {"i_float_method", class_for_check }, + {"i_int_method", class_for_check }, + {"i_long_method", class_for_check }, + {"i_string_method", class_for_check }, + {"i_object_method", class_for_check }, + {"i_prim_array_method", class_for_check }, + {"i_ref_array_method", class_for_check }, + {"i_super_overridden_void_method", class_for_check }, + {"i_super_overridden_prim_method", class_for_check }, + {"i_super_overridden_ref_method", class_for_check }, + {"i_interf_overridden_void_method", class_for_check }, + {"i_interf_overridden_prim_method", class_for_check }, + {"i_interf_overridden_ref_method", class_for_check }, + {"i_void_par_method", class_for_check }, + {"i_boolean_par_method", class_for_check }, + {"i_byte_par_method", class_for_check }, + {"i_char_par_method", class_for_check }, + {"i_double_par_method", class_for_check }, + {"i_float_par_method", class_for_check }, + {"i_int_par_method", class_for_check }, + {"i_long_par_method", class_for_check }, + {"i_string_par_method", class_for_check }, + {"i_object_par_method", class_for_check }, + {"i_prim_array_par_method", class_for_check }, + {"i_ref_array_par_method", class_for_check }, + {"i_super_overridden_void_par_method", class_for_check }, + {"i_super_overridden_prim_par_method", class_for_check }, + {"i_super_overridden_ref_par_method", class_for_check }, + {"i_interf_overridden_void_par_method", class_for_check }, + {"i_interf_overridden_prim_par_method", class_for_check }, + {"i_interf_overridden_ref_par_method", class_for_check }, + {"i_abstract_method", class_for_check }, + {"i_native_method", class_for_check }, + {"i_synchr_method", class_for_check }, + {"i_final_method", class_for_check }, + {"i_private_method", class_for_check }, + {"i_protected_method", class_for_check }, + {"i_public_method", class_for_check }, + {"", class_for_check }, + + {"s_super_void_method", super_class_for_check}, + {"s_super_prim_method", super_class_for_check}, + {"s_super_ref_method", super_class_for_check}, + {"i_super_void_method", super_class_for_check}, + {"i_super_prim_method", super_class_for_check}, + {"i_super_ref_method", super_class_for_check}, + {"i_multiple_inherited_method", super_class_for_check}, + + {"i_interf_ref_method", interface_for_check }, + {"i_interf_prim_method", interface_for_check }, + {"i_interf_void_method", interface_for_check }, + + {"non_existing_method", not_existing_class } + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new methbyname_s001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001 test LOG:"); + out_stream.println("==> test checks methodsByName(String name) method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methbyname_s001: methbyname_s001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> methbyname_s001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> methbyname_s001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_s001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> methbyname_s001: check ReferenceType.methodsByName(...) method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + int methods_for_check_number = methods_for_check.length; + int methodsByName_exceptions = 0; + int not_found_methods_number = 0; + int unexpected_found_methods_number = 0; + int not_matched_methods_number = 0; + int all_method_errors_number = 0; + int passed_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> methbyname_s001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + for (int i=0; i methods_byname_list = null; + try { + methods_byname_list = refType.methodsByName(methods_for_check[i][0]); + } + catch (Throwable thrown) { + out_stream.println + ("##> methbyname_s001: FAILED: methodsByName(...) throws unexpected " + + thrown); + out_stream.println + ("##> requested method: " + current_method_for_check); + methodsByName_exceptions++; + all_method_errors_number++; + continue; + } + int methods_byname_number = methods_byname_list.size(); + if ( methods_byname_number == 0 ) { + if ( existing_method ) { + out_stream.println + ("##> methbyname_s001: FAILED: methodsByName(...) returned empty List of methods!"); + out_stream.println + ("##> requested method: " + current_method_for_check); + not_found_methods_number++; + all_method_errors_number++; + } + else { + print_log_on_verbose + ("--> methbyname_s001: PASSED for method: " + current_method_for_check); + print_log_on_verbose + ("--> expected result: empty List of methods"); + passed_methods_number++; + } + continue; + } + Method methods_byname_array[] = new Method[methods_byname_number]; + methods_byname_list.toArray(methods_byname_array); + if ( (! existing_method) || (methods_byname_number > 1) ) { + out_stream.println + ("##> methbyname_s001: FAILED: methodsByName(...) returned unexpected methods - " + + methods_byname_number + " method(s)"); + out_stream.println + ("##> requested method: " + current_method_for_check); + if ( ! existing_method ) { + out_stream.println + ("##> expected result: empty List of methods"); + unexpected_found_methods_number++; + } + else { + out_stream.println + ("##> expected result: List of requested method"); + not_matched_methods_number++; + } + out_stream.println + ("##> returned methods:"); + for (int k=0; k returned method[" + k +"] - " + found_method_info); + } + all_method_errors_number++; + continue; + } + +// The beginning of the patch to fix the test failure. + /* + Method found_method = methods_byname_array[0]; + String found_method_name = found_method.name(); + String declaring_class_name = "declaring class NOT defined"; + try { + declaring_class_name = found_method.declaringType().name(); + } + catch (Throwable thrown) { + } + String found_method_info = found_method_name + " (" + declaring_class_name + ")"; + if ( ! methods_for_check[i][1].equals(declaring_class_name) ) { + out_stream.println + ("##> methbyname_s001: FAILED: methodsByName(...) returned not matched method - " + + found_method_info); + out_stream.println + ("##> requested method: " + current_method_for_check); + not_matched_methods_number++; + all_method_errors_number++; + } + else { + print_log_on_verbose + ("--> methbyname_s001: PASSED for method: " + current_method_for_check); + passed_methods_number++; + } + */ + // the string below replaces the above code fragment + passed_methods_number++; + +// The end of the patch. + + } + break; + } + + out_stream.println("--> methbyname_s001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println + ("--> methbyname_s001: number of checked methods = " + methods_for_check_number); + if ( methodsByName_exceptions > 0 ) { + out_stream.println + ("--> methbyname_s001: number of unexpected exceptions thrown by methodsByName(...) = " + + methodsByName_exceptions); + } + if ( not_found_methods_number > 0 ) { + out_stream.println + ("--> methbyname_s001: number of methods not found by methodsByName(...) (empty List returned) = " + + not_found_methods_number); + } + if ( unexpected_found_methods_number > 0 ) { + out_stream.println + ("--> methbyname_s001: number of unexpected methods found by methodsByName(...) (not empty List returned) = " + + unexpected_found_methods_number); + } + if ( not_matched_methods_number > 0 ) { + out_stream.println + ("--> methbyname_s001: number of returned by methodsByName(...) methods not matched to requested method = " + + not_matched_methods_number); + } + out_stream.println + ("--> methbyname_s001: number of methods for which methodsByName(...) returned expected result = " + + passed_methods_number); + } + if ( all_method_errors_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methbyname_s001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> methbyname_s001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methbyname_s001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001/TestDescription.java new file mode 100644 index 00000000000..76860a8d3da --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001 test + * checks the methodsByName(String name) method of ReferenceType interface + * of the com.sun.jdi package : + * the ReferenceType.methodsByName(String name) method is checked for methods of + * debugee's class which extends super class and implements interface. + * Debugee's class has not overloaded methods. + * Each method is checked for method's name. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methodsByName_s.methbyname_s001 + * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001a.java new file mode 100644 index 00000000000..54290e72945 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s001a.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the methbyname_s001 JDI test. + */ + +public class methbyname_s001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_s."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "methbyname_s001aClassForCheck"; + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i methbyname_s001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + Class checked_class_classobj = null; + try { + checked_class_classobj = + Class.forName(checked_class_name, true, methbyname_s001a.class.getClassLoader()); + print_log_on_verbose + ("--> methbyname_s001a: checked class loaded:" + checked_class_name); + } + catch ( Throwable thrown ) { // ClassNotFoundException +// System.err.println +// ("**> methbyname_s001a: load class: Throwable thrown = " + thrown.toString()); + print_log_on_verbose + ("--> methbyname_s001a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> methbyname_s001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_s001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_s001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methbyname_s001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methbyname_s001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +abstract class methbyname_s001aClassForCheck extends methbyname_s001aSuperClassForCheck implements methbyname_s001aInterfaceForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods without params + static void s_void_method() {} + static boolean s_boolean_method() {return true;} + static byte s_byte_method() {return (byte)1;} + static char s_char_method() {return (char)1;} + static double s_double_method() {return (double)100.99;} + static float s_float_method() {return (float)100.88;} + static int s_int_method() {return 100;} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + // static methods with params + static void s_void_par_method(boolean z) {} + static boolean s_boolean_par_method(boolean z) {return true;} + static byte s_byte_par_method(byte b) {return (byte)1;} + static char s_char_par_method(char ch) {return (char)1;} + static double s_double_par_method(double d) {return (double)100.99;} + static float s_float_par_method(float f) {return (float)100.88;} + static int s_int_par_method(int i) {return 100;} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + // other static methods + native static Object s_native_method(Object obj); + static synchronized Object s_synchr_method(Object obj) {return new Object();} + final static Object s_final_method(Object obj) {return new Object();} + private static Object s_private_method(Object obj) {return new Object();} + protected static Object s_protected_method(Object obj) {return new Object();} + public static Object s_public_method(Object obj) {return new Object();} + + // instance methods without params + void i_void_method() {} + boolean i_boolean_method() {return true;} + byte i_byte_method() {return (byte)1;} + char i_char_method() {return (char)1;} + double i_double_method() {return (double)100.99;} + float i_float_method() {return (float)100.88;} + int i_int_method() {return 100;} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + public void i_interf_overridden_void_method() {} + public int i_interf_overridden_prim_method() {return 100;} + public Object i_interf_overridden_ref_method() {return new Object();} + + // instance methods with params + void i_void_par_method(boolean z) {} + boolean i_boolean_par_method(boolean z) {return true;} + byte i_byte_par_method(byte b) {return (byte)1;} + char i_char_par_method(char ch) {return (char)1;} + double i_double_par_method(double d) {return (double)100.99;} + float i_float_par_method(float f) {return (float)100.88;} + int i_int_par_method(int i) {return 100;} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public void i_interf_overridden_void_par_method(int i) {} + public int i_interf_overridden_prim_par_method(int i) {return 100;} + public Object i_interf_overridden_ref_par_method(Object obj) {return new Object();} + + // other instance methods + abstract Object i_abstract_method(Object obj); + native Object i_native_method(Object obj); + synchronized Object i_synchr_method(Object obj) {return new Object();} + final Object i_final_method(Object obj) {return new Object();} + private Object i_private_method(Object obj) {return new Object();} + protected Object i_protected_method(Object obj) {return new Object();} + public Object i_public_method(Object obj) {return new Object();} + + + // static initializer + static {} + + +} + +abstract class methbyname_s001aSuperClassForCheck { + + static void s_super_void_method(long l) {} + static long s_super_prim_method(long l) {return 100;} + static Object s_super_ref_method(Object obj) {return new Object();} + + void i_super_void_method(long l) {} + long i_super_prim_method(long l) {return 100;} + Object i_super_ref_method(Object obj) {return new Object();} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public Object i_multiple_inherited_method(Object obj) {return new Object();} + +} + +interface methbyname_s001aInterfaceForCheck { + + void i_interf_void_method(long l); + long i_interf_prim_method(long l); + Object i_interf_ref_method(Object obj); + + void i_interf_overridden_void_method(); + int i_interf_overridden_prim_method(); + Object i_interf_overridden_ref_method(); + + void i_interf_overridden_void_par_method(int i); + int i_interf_overridden_prim_par_method(int i); + Object i_interf_overridden_ref_par_method(Object obj); + + public Object i_multiple_inherited_method(Object obj); + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002.java new file mode 100644 index 00000000000..6a2951c8e4e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methodsByName(String name) + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methbyname_s002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_s.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methbyname_s002", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "methbyname_s002aClassForCheck"; + + private final static String classLoaderName = package_prefix + "methbyname_s002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new methbyname_s002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + private void print_log_anyway(String message) { + logHandler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + Debugee debugee; + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + print_log_on_verbose("==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002 test LOG:"); + print_log_on_verbose("==> test checks methodsByName(String name) method of ReferenceType interface "); + print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methbyname_s002: methbyname_s002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> methbyname_s002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> methbyname_s002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_s002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> methbyname_s002: check ReferenceType.methodsByName(...) method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean methodsByName_method_error = false; + + while ( true ) { // test body + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> methbyname_s002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> methbyname_s002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + List methodsByName_methods_list = null; + try { + methodsByName_methods_list = refType.methodsByName("dummy_method_name"); + print_log_anyway + ("##> methbyname_s002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + methodsByName_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> methbyname_s002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> methbyname_s002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + methodsByName_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || methodsByName_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methbyname_s002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> methbyname_s002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methbyname_s002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/TestDescription.java new file mode 100644 index 00000000000..6abe10bc7ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002 test + * checks the methodsByName(String name) method of ReferenceType interface + * of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.methodsByName(String name) method is called for + * this class - ClassNotPreparedException should be thrown + * in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "out_stream.println" are replaced with + * "print_log_on_verbose" and "print_log_anyway". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methodsByName_s.methbyname_s002 + * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/loadclass/methbyname_s002aClassForCheck.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/loadclass/methbyname_s002aClassForCheck.java new file mode 100644 index 00000000000..b0796137fd9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002/loadclass/methbyname_s002aClassForCheck.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +/** + * This class is loaded by methbyname_s002aClassLoader . + */ + +class methbyname_s002aClassForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods + static void s_void_method() {} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_void_par_method(boolean z) {} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + + // instance methods + void i_void_method() {} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_void_par_method(boolean z) {} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + // static initializer + static {} + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002a.java new file mode 100644 index 00000000000..fd2377ccb7d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s002a.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + + +/** + * This class is used as debugee application for the methbyname_s002 JDI test. + */ + +public class methbyname_s002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_s."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "methbyname_s002aClassForCheck"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i methbyname_s002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + methbyname_s002aClassLoader customClassLoader = new methbyname_s002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> methbyname_s002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> methbyname_s002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> methbyname_s002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_s002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_s002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methbyname_s002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methbyname_s002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class methbyname_s002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public methbyname_s002aClassLoader(String classPath, String className) { + super(methbyname_s002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003.java new file mode 100644 index 00000000000..92aca680933 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methodsByName(String name) + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methbyname_s003 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_s.", + thisClassName = package_prefix + "methbyname_s003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "methbyname_s003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new methbyname_s003().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + private static void print_log_without_verbose(String message) { + if ( ! verbose_mode ) { + out_stream.println(message); + } + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003 test LOG:"); + out_stream.println("--> test checks methodsByName(String name) method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for UNLOADED class\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + argv = argHandler.getArguments(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methbyname_s003: methbyname_s003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> methbyname_s003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + out_stream.println + ("##> methbyname_s003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_s003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> methbyname_s003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + out_stream.println + ("##> methbyname_s003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_s003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean methodsByName_s_method_error = false; + + while ( true ) { + print_log_on_verbose + ("--> methbyname_s003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> methbyname_s003: getting ReferenceType object for loaded checked class..."); + out_stream.println("##> methbyname_s003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> methbyname_s003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> methbyname_s003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> methbyname_s003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + out_stream.println + ("--> methbyname_s003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + out_stream.println + ("--> ReferenceType.methodsByName_s() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + out_stream.println + ("##> methbyname_s003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_s003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> methbyname_s003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> methbyname_s003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> methbyname_s003: check that checked class has been unloaded realy..."); + out_stream.println + ("--> methbyname_s003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + out_stream.println + ("--> ReferenceType.methodsByName_s() method can NOT be checked!"); + break; + } + + out_stream.println + ("--> methbyname_s003: check ReferenceType.methodsByName(...) method for unloaded class..."); + List methods_byname_list = null; + try { + methods_byname_list = refType.methodsByName("dummy_method_name"); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + out_stream.println + ("--> methbyname_s003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + out_stream.println + ("##> methbyname_s003: FAILED: unexpected Exception thrown - " + expt.toString()); + out_stream.println + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + methodsByName_s_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || methodsByName_s_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methbyname_s003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> methbyname_s003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methbyname_s003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of methbyname_s003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TestDescription.java new file mode 100644 index 00000000000..5a3c44f9808 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003 test + * checks the methodsByName(String name) method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * methodsByName(String name) method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - methodsByName_s003b class was moved in 'loadclass' subdirectory; + * - package name was added in methodsByName_s003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for methodsByName_s003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methodsByName_s.methbyname_s003 + * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/loadclass/methbyname_s003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/loadclass/methbyname_s003b.java new file mode 100644 index 00000000000..677d4540700 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003/loadclass/methbyname_s003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the methodsByName(String name) method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.methodsByName_s; + +class methbyname_s003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003a.java new file mode 100644 index 00000000000..5ef8e69611e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the methbyname_s003 JDI test. + */ + +public class methbyname_s003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_s."; + private final static String checked_class_name = package_prefix + "methbyname_s003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> methbyname_s003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> methbyname_s003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> methbyname_s003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> methbyname_s003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> methbyname_s003a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> methbyname_s003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_s003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_s003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> methbyname_s003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> methbyname_s003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> methbyname_s003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> methbyname_s003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> methbyname_s003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> methbyname_s003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> methbyname_s003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_s003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_s003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methbyname_s003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methbyname_s003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of methbyname_s003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004.java new file mode 100644 index 00000000000..aeacb65598f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004.java @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methodsByName(String name) + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methbyname_s004 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_s.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methbyname_s004", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "methbyname_s004aClassForCheck"; + private final static String super_class_for_check = package_prefix + "methbyname_s004aSuperClassForCheck"; + private final static String interface_for_check = package_prefix + "methbyname_s004aInterfaceForCheck"; + private static String methods_for_check[][] = { + +// method name returned methods expected number + + {"s_overloaded_method", "4" }, + {"i_overloaded_method", "4" }, + {"i_super_overloaded_method", "2" }, + {"i_interf_overloaded_method", "2" } + + }; + + private static String expected_methods_full_list[][] = { + +// method name declaring class signature + + {"s_overloaded_method", class_for_check, "()V" }, + {"s_overloaded_method", class_for_check, "(Ljava/lang/String;)Ljava/lang/String;" }, + {"s_overloaded_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_overloaded_method", class_for_check, "(JLjava/lang/String;)Ljava/lang/Object;" }, + {"i_overloaded_method", class_for_check, "()V" }, + {"i_overloaded_method", class_for_check, "(Ljava/lang/Object;)J" }, + {"i_overloaded_method", class_for_check, "(Ljava/lang/String;)Ljava/lang/String;" }, + {"i_overloaded_method", class_for_check, "(JLjava/lang/String;)Ljava/lang/Object;" }, + {"i_super_overloaded_method", class_for_check, "(JLjava/lang/String;)Ljava/lang/Object;" }, + {"i_super_overloaded_method", super_class_for_check, "(J)Ljava/lang/Object;" }, + {"i_interf_overloaded_method", class_for_check, "(JLjava/lang/String;)Ljava/lang/Object;" }, + {"i_interf_overloaded_method", interface_for_check, "(J)Ljava/lang/Object;" } + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new methbyname_s004().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004 test LOG:"); + out_stream.println("==> test checks methodsByName(String name) method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for overloaded methods\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methbyname_s004: methbyname_s004a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> methbyname_s004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> methbyname_s004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_s004: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> methbyname_s004: check ReferenceType.methodsByName(String name) method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + int methods_for_check_number = methods_for_check.length; + int methodsByName_exceptions = 0; + int not_found_methods_number = 0; + int not_matched_methods_number = 0; + int all_method_errors_number = 0; + int passed_methods_number = 0; + + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> methbyname_s004: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + for (int i=0; i methods_byname_list = null; + try { + methods_byname_list = refType.methodsByName(methods_for_check[i][0]); + } + catch (Throwable thrown) { + out_stream.println + ("##> methbyname_s004: FAILED: methodsByName(...) throws unexpected " + + thrown); + out_stream.println + ("##> requested method: " + methods_for_check[i][0]); + methodsByName_exceptions++; + all_method_errors_number++; + continue; + } + int methods_byname_number = methods_byname_list.size(); + if ( methods_byname_number == 0 ) { + out_stream.println + ("##> methbyname_s004: FAILED: methodsByName(...) returned empty List of methods!"); + out_stream.println + ("##> requested method: " + methods_for_check[i][0]); + out_stream.println + ("##> expected number of returned methods = " + expected_methods_number); + not_found_methods_number++; + all_method_errors_number++; + continue; + } + Method methods_byname_array[] = new Method[methods_byname_number]; + methods_byname_list.toArray(methods_byname_array); + if ( methods_byname_number != expected_methods_number ) { + out_stream.println + ("##> methbyname_s004: FAILED: methodsByName(...) returned unexpected methods number = " + + methods_byname_number); + out_stream.println + ("##> requested method: " + methods_for_check[i][0]); + out_stream.println + ("##> expected number of returned methods = " + expected_methods_number); + out_stream.println + ("##> expected methods:"); + int counter = 0; + for (int k=0; k returned method[" + counter +"] - " + expected_method_info); + counter++; + } + out_stream.println + ("##> returned methods:"); + for (int k=0; k expected method[" + k +"] - " + found_method_info); + } + not_matched_methods_number++; + all_method_errors_number++; + continue; + } + int matched_methods_number = 0; + for (int k=0; k methbyname_s004: FAILED: methodsByName(...) returned unexpected List of methods!"); + out_stream.println + ("##> requested method: " + methods_for_check[i][0]); + out_stream.println + ("##> expected number of returned methods = " + expected_methods_number); + out_stream.println + ("##> expected methods:"); + int counter = 0; + for (int k=0; k expected[" + counter +"] - " + expected_method_info); + counter++; + } + out_stream.println + ("##> in fact number of returned methods = " + expected_methods_number); + out_stream.println + ("##> returned methods:"); + for (int k=0; k returned method[" + k +"] - " + found_method_info); + } + not_matched_methods_number++; + all_method_errors_number++; + } + else { + print_log_on_verbose + ("--> methbyname_s004: PASSED for method: " + methods_for_check[i][0]); + passed_methods_number++; + } + } + break; + } + + out_stream.println("--> methbyname_s004: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println + ("--> methbyname_s004: number of checked methods = " + methods_for_check_number); + if ( methodsByName_exceptions > 0 ) { + out_stream.println + ("--> methbyname_s004: number of unexpected exceptions thrown by methodsByName(...) = " + + methodsByName_exceptions); + } + if ( not_found_methods_number > 0 ) { + out_stream.println + ("--> methbyname_s004: number of methods not found by methodsByName(...) (empty List returned) = " + + not_found_methods_number); + } + if ( not_matched_methods_number > 0 ) { + out_stream.println + ("--> methbyname_s004: number of returned by methodsByName(...) methods not matched to requested method = " + + not_matched_methods_number); + } + out_stream.println + ("--> methbyname_s004: number of methods for which methodsByName(...) returned expected result = " + + passed_methods_number); + } + if ( all_method_errors_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methbyname_s004: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> methbyname_s004: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methbyname_s004: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004/TestDescription.java new file mode 100644 index 00000000000..6cb60aa15dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004 test + * checks the methodsByName(String name) method of ReferenceType interface + * of the com.sun.jdi package for overloaded methods: + * the ReferenceType.methodsByName(String name) method is checked for methods of + * debugee's class which extends super class and implements interface. + * Debugee's class has only overloaded methods. + * Each returned method is checked for its name and signature. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methodsByName_s.methbyname_s004 + * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methodsByName_s.methbyname_s004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004a.java new file mode 100644 index 00000000000..24ea124d6c4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_s/methbyname_s004a.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the methbyname_s004 JDI test. + */ + +public class methbyname_s004a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_s."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "methbyname_s004aClassForCheck"; + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i methbyname_s004a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + Class checked_class_classobj = null; + try { + checked_class_classobj = + Class.forName(checked_class_name, true, methbyname_s004a.class.getClassLoader()); + print_log_on_verbose + ("--> methbyname_s004a: checked class loaded:" + checked_class_name); + } + catch ( Throwable thrown ) { // ClassNotFoundException +// System.err.println +// ("**> methbyname_s004a: load class: Throwable thrown = " + thrown.toString()); + print_log_on_verbose + ("--> methbyname_s004a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> methbyname_s004a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_s004a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_s004a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methbyname_s004a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methbyname_s004a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +abstract class methbyname_s004aClassForCheck extends methbyname_s004aSuperClassForCheck implements methbyname_s004aInterfaceForCheck { + + + // overloaded static methods + static void s_overloaded_method() {} + static String s_overloaded_method(String s) {return "string";} + static Object s_overloaded_method(Object obj) {return new Object();} + static Object s_overloaded_method(long l, String s) {return new Object();} + + static Object s_super_overloaded_method(long l, String s) {return new Object();} + + // overloaded instance methods + void i_overloaded_method() {} + long i_overloaded_method(Object obj) {return (long)1;} + String i_overloaded_method(String s) {return "string";} + Object i_overloaded_method(long l, String s) {return new Object();} + + Object i_super_overloaded_method(long l, String s) {return new Object();} + Object i_interf_overloaded_method(long l, String s) {return new Object();} + + +} + +abstract class methbyname_s004aSuperClassForCheck { + + static Object s_super_overloaded_method(long l) {return new Object();} + Object i_super_overloaded_method(long l) {return new Object();} + +} + +interface methbyname_s004aInterfaceForCheck { + + Object i_interf_overloaded_method(long l); + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001.java new file mode 100644 index 00000000000..e316d96ea4f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001.java @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methodsByName(String name, String signature) + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methbyname_ss001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methbyname_ss001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "methbyname_ss001aClassForCheck"; + private final static String super_class_for_check = package_prefix + "methbyname_ss001aSuperClassForCheck"; + private final static String interface_for_check = package_prefix + "methbyname_ss001aInterfaceForCheck"; + private final static String not_existing_class = "not_existing_class"; + private static String methods_for_check[][] = { + +// method name declaring class signature + + {"", class_for_check, "()V" }, + {"ClassForCheck", class_for_check, "()V" }, + {"s_void_method", class_for_check, "()V" }, + {"s_boolean_method", class_for_check, "()Z" }, + {"s_byte_method", class_for_check, "()B" }, + {"s_char_method", class_for_check, "()C" }, + {"s_double_method", class_for_check, "()D" }, + {"s_float_method", class_for_check, "()F" }, + {"s_int_method", class_for_check, "()I" }, + {"s_long_method", class_for_check, "()J" }, + {"s_string_method", class_for_check, "()Ljava/lang/String;" }, + {"s_object_method", class_for_check, "()Ljava/lang/Object;" }, + {"s_prim_array_method", class_for_check, "()[J" }, + {"s_ref_array_method", class_for_check, "()[Ljava/lang/Object;" }, + {"s_super_hidden_void_method", class_for_check, "()V" }, + {"s_super_hidden_prim_method", class_for_check, "()I" }, + {"s_super_hidden_ref_method", class_for_check, "()Ljava/lang/Object;" }, + {"s_void_par_method", class_for_check, "(Z)V" }, + {"s_boolean_par_method", class_for_check, "(Z)Z" }, + {"s_byte_par_method", class_for_check, "(B)B" }, + {"s_char_par_method", class_for_check, "(C)C" }, + {"s_double_par_method", class_for_check, "(D)D" }, + {"s_float_par_method", class_for_check, "(F)F" }, + {"s_int_par_method", class_for_check, "(I)I" }, + {"s_long_par_method", class_for_check, "(J)J" }, + {"s_string_par_method", class_for_check, "(Ljava/lang/String;)Ljava/lang/String;" }, + {"s_object_par_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_prim_array_par_method", class_for_check, "([J)[J" }, + {"s_ref_array_par_method", class_for_check, "([Ljava/lang/Object;)[Ljava/lang/Object;" }, + {"s_super_hidden_void_par_method", class_for_check, "(I)V" }, + {"s_super_hidden_prim_par_method", class_for_check, "(I)I" }, + {"s_super_hidden_ref_par_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_native_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_synchr_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_final_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_private_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_protected_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_public_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_void_method", class_for_check, "()V" }, + {"i_boolean_method", class_for_check, "()Z" }, + {"i_byte_method", class_for_check, "()B" }, + {"i_char_method", class_for_check, "()C" }, + {"i_double_method", class_for_check, "()D" }, + {"i_float_method", class_for_check, "()F" }, + {"i_int_method", class_for_check, "()I" }, + {"i_long_method", class_for_check, "()J" }, + {"i_string_method", class_for_check, "()Ljava/lang/String;" }, + {"i_object_method", class_for_check, "()Ljava/lang/Object;" }, + {"i_prim_array_method", class_for_check, "()[J" }, + {"i_ref_array_method", class_for_check, "()[Ljava/lang/Object;" }, + {"i_super_overridden_void_method", class_for_check, "()V" }, + {"i_super_overridden_prim_method", class_for_check, "()I" }, + {"i_super_overridden_ref_method", class_for_check, "()Ljava/lang/Object;" }, + {"i_interf_overridden_void_method", class_for_check, "()V" }, + {"i_interf_overridden_prim_method", class_for_check, "()I" }, + {"i_interf_overridden_ref_method", class_for_check, "()Ljava/lang/Object;" }, + {"i_void_par_method", class_for_check, "(Z)V" }, + {"i_boolean_par_method", class_for_check, "(Z)Z" }, + {"i_byte_par_method", class_for_check, "(B)B" }, + {"i_char_par_method", class_for_check, "(C)C" }, + {"i_double_par_method", class_for_check, "(D)D" }, + {"i_float_par_method", class_for_check, "(F)F" }, + {"i_int_par_method", class_for_check, "(I)I" }, + {"i_long_par_method", class_for_check, "(J)J" }, + {"i_string_par_method", class_for_check, "(Ljava/lang/String;)Ljava/lang/String;" }, + {"i_object_par_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_prim_array_par_method", class_for_check, "([J)[J" }, + {"i_ref_array_par_method", class_for_check, "([Ljava/lang/Object;)[Ljava/lang/Object;" }, + {"i_super_overridden_void_par_method", class_for_check, "(I)V" }, + {"i_super_overridden_prim_par_method", class_for_check, "(I)I" }, + {"i_super_overridden_ref_par_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_interf_overridden_void_par_method", class_for_check, "(I)V" }, + {"i_interf_overridden_prim_par_method", class_for_check, "(I)I" }, + {"i_interf_overridden_ref_par_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_abstract_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_native_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_synchr_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_final_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_private_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_protected_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_public_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"", class_for_check, "()V" }, + + {"s_super_void_method", super_class_for_check, "(J)V" }, + {"s_super_prim_method", super_class_for_check, "(J)J" }, + {"s_super_ref_method", super_class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_super_void_method", super_class_for_check, "(J)V" }, + {"i_super_prim_method", super_class_for_check, "(J)J" }, + {"i_super_ref_method", super_class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_multiple_inherited_method", super_class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + + {"i_interf_ref_method", interface_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"i_interf_prim_method", interface_for_check, "(J)J" }, + {"i_interf_void_method", interface_for_check, "(J)V" }, + + {"s_overloaded_method", class_for_check, "()V" }, + {"s_overloaded_method", class_for_check, "(Ljava/lang/String;)Ljava/lang/String;" }, + {"s_overloaded_method", class_for_check, "(Ljava/lang/Object;)Ljava/lang/Object;" }, + {"s_overloaded_method", class_for_check, "(JLjava/lang/String;)Ljava/lang/Object;" }, + {"i_overloaded_method", class_for_check, "()V" }, + {"i_overloaded_method", class_for_check, "(Ljava/lang/Object;)J" }, + {"i_overloaded_method", class_for_check, "(Ljava/lang/String;)Ljava/lang/String;" }, + {"i_overloaded_method", class_for_check, "(JLjava/lang/String;)Ljava/lang/Object;" }, + {"i_super_overloaded_method", class_for_check, "(JLjava/lang/String;)Ljava/lang/Object;" }, + {"i_super_overloaded_method", super_class_for_check, "(J)Ljava/lang/Object;" }, + {"i_interf_overloaded_method", class_for_check, "(JLjava/lang/String;)Ljava/lang/Object;" }, + {"i_interf_overloaded_method", interface_for_check, "(J)Ljava/lang/Object;" }, + + {"non_existing_method", not_existing_class, "non_existing_signature" } + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new methbyname_ss001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001 test LOG:"); + out_stream.println("==> test checks methodsByName(String name, String signature) method of "); + out_stream.println(" ReferenceType interface of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out_stream); + print_log_on_verbose("--> methbyname_ss001: methbyname_ss001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> methbyname_ss001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> methbyname_ss001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_ss001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> methbyname_ss001: check ReferenceType.methodsByName(...) method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + int methods_for_check_number = methods_for_check.length; + int methodsByName_exceptions = 0; + int not_found_methods_number = 0; + int unexpected_found_methods_number = 0; + int not_matched_methods_number = 0; + int all_method_errors_number = 0; + int passed_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> methbyname_ss001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + for (int i=0; i methods_byname_list = null; + try { + methods_byname_list = refType.methodsByName(expected_method_name, expected_method_signature); + } + catch (Throwable thrown) { + out_stream.println + ("##> methbyname_ss001: FAILED: methodsByName(...) throws unexpected " + + thrown); + out_stream.println + ("##> requested method: " + expected_method_info); + methodsByName_exceptions++; + all_method_errors_number++; + continue; + } + int methods_byname_number = methods_byname_list.size(); + if ( methods_byname_number == 0 ) { + if ( existing_method ) { + out_stream.println + ("##> methbyname_ss001: FAILED: methodsByName(...) returned empty List of methods!"); + out_stream.println + ("##> requested method: " + expected_method_info); + not_found_methods_number++; + all_method_errors_number++; + } + else { + print_log_on_verbose + ("--> methbyname_ss001: PASSED for method: " + expected_method_info); + print_log_on_verbose + ("--> expected result: empty List of methods"); + passed_methods_number++; + } + continue; + } + Method methods_byname_array[] = new Method[methods_byname_number]; + methods_byname_list.toArray(methods_byname_array); + + if ( (! existing_method) || (methods_byname_number > 1) ) { + out_stream.println + ("##> methbyname_ss001: FAILED: methodsByName(...) returned unexpected number of methods - " + + methods_byname_number + " method(s)"); + out_stream.println + ("##> requested method: " + expected_method_info); + if ( ! existing_method ) { + out_stream.println + ("##> expected result: empty List of methods"); + unexpected_found_methods_number++; + } + else { + out_stream.println + ("##> expected result: List of requested method"); + not_matched_methods_number++; + } + out_stream.println + ("##> returned methods:"); + for (int k=0; k returned method[" + k +"] - " + found_method_info); + } + all_method_errors_number++; + continue; + } + Method found_method = methods_byname_array[0]; + String found_method_name = found_method.name(); + String found_method_signature = found_method.signature(); + String found_declaring_class = "declaring class NOT defined"; + try { + found_declaring_class = found_method.declaringType().name(); + } + catch (Throwable thrown) { + } + +// 'found_method_info' is changed to fix the test failure. +// See also: 'expected_method_info' above. +// String found_method_info = found_method_name + " (\"" +// + found_method_signature + "\", " + found_declaring_class + ")"; + String found_method_info = found_method_name + " (\"" + + found_method_signature + "\", )"; + + if ( ! found_method_info.equals(expected_method_info) ) { + out_stream.println + ("##> methbyname_ss001: FAILED: methodsByName(...) returned not matched method - " + + found_method_info); + out_stream.println + ("##> requested method: " + expected_method_info); + not_matched_methods_number++; + all_method_errors_number++; + } + else { + print_log_on_verbose + ("--> methbyname_ss001: PASSED for method: " + expected_method_info); + passed_methods_number++; + } + } + break; + } + out_stream.println("--> methbyname_ss001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println + ("--> methbyname_ss001: number of checked methods = " + methods_for_check_number); + if ( methodsByName_exceptions > 0 ) { + out_stream.println + ("--> methbyname_ss001: number of unexpected exceptions thrown by methodsByName(...) = " + + methodsByName_exceptions); + } + if ( not_found_methods_number > 0 ) { + out_stream.println + ("--> methbyname_ss001: number of methods not found by methodsByName(...) (empty List returned) = " + + not_found_methods_number); + } + if ( unexpected_found_methods_number > 0 ) { + out_stream.println + ("--> methbyname_ss001: number of unexpected methods found by methodsByName(...) (not empty List returned) = " + + unexpected_found_methods_number); + } + if ( not_matched_methods_number > 0 ) { + out_stream.println + ("--> methbyname_ss001: number of returned by methodsByName(...) methods not matched to requested method = " + + not_matched_methods_number); + } + out_stream.println + ("--> methbyname_ss001: number of methods for which methodsByName(...) returned expected result = " + + passed_methods_number); + } + if ( all_method_errors_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methbyname_ss001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> methbyname_ss001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methbyname_ss001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001/TestDescription.java new file mode 100644 index 00000000000..d0d2131647d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001 test + * checks the methodsByName(String name, String signature) method + * of ReferenceType interface of the com.sun.jdi package : + * the ReferenceType.methodsByName(String name, String signature) method + * is checked for methods of debugee's class which extends super class and + * implements interface. + * Each method is checked for its name and signature. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss001 + * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001a.java new file mode 100644 index 00000000000..13cfdf25901 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss001a.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the methbyname_ss001 JDI test. + */ + +public class methbyname_ss001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "methbyname_ss001aClassForCheck"; + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i methbyname_ss001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + Class checked_class_classobj = null; + try { + checked_class_classobj = + Class.forName(checked_class_name, true, methbyname_ss001a.class.getClassLoader()); + print_log_on_verbose + ("--> methbyname_ss001a: checked class loaded:" + checked_class_name); + } + catch ( Throwable thrown ) { // ClassNotFoundException +// System.err.println +// ("**> methbyname_ss001a: load class: Throwable thrown = " + thrown.toString()); + print_log_on_verbose + ("--> methbyname_ss001a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> methbyname_ss001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_ss001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_ss001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methbyname_ss001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methbyname_ss001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +abstract class methbyname_ss001aClassForCheck extends methbyname_ss001aSuperClassForCheck + implements methbyname_ss001aInterfaceForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods without params + static void s_void_method() {} + static boolean s_boolean_method() {return true;} + static byte s_byte_method() {return (byte)1;} + static char s_char_method() {return (char)1;} + static double s_double_method() {return (double)100.99;} + static float s_float_method() {return (float)100.88;} + static int s_int_method() {return 100;} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + // static methods with params + static void s_void_par_method(boolean z) {} + static boolean s_boolean_par_method(boolean z) {return true;} + static byte s_byte_par_method(byte b) {return (byte)1;} + static char s_char_par_method(char ch) {return (char)1;} + static double s_double_par_method(double d) {return (double)100.99;} + static float s_float_par_method(float f) {return (float)100.88;} + static int s_int_par_method(int i) {return 100;} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + // other static methods + native static Object s_native_method(Object obj); + static synchronized Object s_synchr_method(Object obj) {return new Object();} + final static Object s_final_method(Object obj) {return new Object();} + private static Object s_private_method(Object obj) {return new Object();} + protected static Object s_protected_method(Object obj) {return new Object();} + public static Object s_public_method(Object obj) {return new Object();} + + // instance methods without params + void i_void_method() {} + boolean i_boolean_method() {return true;} + byte i_byte_method() {return (byte)1;} + char i_char_method() {return (char)1;} + double i_double_method() {return (double)100.99;} + float i_float_method() {return (float)100.88;} + int i_int_method() {return 100;} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + public void i_interf_overridden_void_method() {} + public int i_interf_overridden_prim_method() {return 100;} + public Object i_interf_overridden_ref_method() {return new Object();} + + // instance methods with params + void i_void_par_method(boolean z) {} + boolean i_boolean_par_method(boolean z) {return true;} + byte i_byte_par_method(byte b) {return (byte)1;} + char i_char_par_method(char ch) {return (char)1;} + double i_double_par_method(double d) {return (double)100.99;} + float i_float_par_method(float f) {return (float)100.88;} + int i_int_par_method(int i) {return 100;} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public void i_interf_overridden_void_par_method(int i) {} + public int i_interf_overridden_prim_par_method(int i) {return 100;} + public Object i_interf_overridden_ref_par_method(Object obj) {return new Object();} + + // other instance methods + abstract Object i_abstract_method(Object obj); + native Object i_native_method(Object obj); + synchronized Object i_synchr_method(Object obj) {return new Object();} + final Object i_final_method(Object obj) {return new Object();} + private Object i_private_method(Object obj) {return new Object();} + protected Object i_protected_method(Object obj) {return new Object();} + public Object i_public_method(Object obj) {return new Object();} + + + // static initializer + static {} + + // overloaded static methods + static void s_overloaded_method() {} + static String s_overloaded_method(String s) {return "string";} + static Object s_overloaded_method(Object obj) {return new Object();} + static Object s_overloaded_method(long l, String s) {return new Object();} + + static Object s_super_overloaded_method(long l, String s) {return new Object();} + + // overloaded instance methods + void i_overloaded_method() {} + long i_overloaded_method(Object obj) {return (long)1;} + String i_overloaded_method(String s) {return "string";} + Object i_overloaded_method(long l, String s) {return new Object();} + + Object i_super_overloaded_method(long l, String s) {return new Object();} + Object i_interf_overloaded_method(long l, String s) {return new Object();} + + +} + +abstract class methbyname_ss001aSuperClassForCheck { + + static void s_super_void_method(long l) {} + static long s_super_prim_method(long l) {return 100;} + static Object s_super_ref_method(Object obj) {return new Object();} + + void i_super_void_method(long l) {} + long i_super_prim_method(long l) {return 100;} + Object i_super_ref_method(Object obj) {return new Object();} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public Object i_multiple_inherited_method(Object obj) {return new Object();} + + static Object s_super_overloaded_method(long l) {return new Object();} + Object i_super_overloaded_method(long l) {return new Object();} + +} + +interface methbyname_ss001aInterfaceForCheck { + + void i_interf_void_method(long l); + long i_interf_prim_method(long l); + Object i_interf_ref_method(Object obj); + + void i_interf_overridden_void_method(); + int i_interf_overridden_prim_method(); + Object i_interf_overridden_ref_method(); + + void i_interf_overridden_void_par_method(int i); + int i_interf_overridden_prim_par_method(int i); + Object i_interf_overridden_ref_par_method(Object obj); + + public Object i_multiple_inherited_method(Object obj); + + Object i_interf_overloaded_method(long l); + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002.java new file mode 100644 index 00000000000..d66e8f35e64 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methodsByName(String name, String signature) + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methbyname_ss002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methbyname_ss002", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "methbyname_ss002aClassForCheck"; + + private final static String classLoaderName = package_prefix + "methbyname_ss002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new methbyname_ss002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + private void print_log_anyway(String message) { + logHandler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + Debugee debugee; + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + print_log_on_verbose("==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002 test LOG:"); + print_log_on_verbose("==> test checks methodsByName(String name, String signature) method of ReferenceType "); + print_log_on_verbose(" interface of the com.sun.jdi package for not prepared class\n"); + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methbyname_ss002: methbyname_ss002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> methbyname_ss002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> methbyname_ss002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_ss002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> methbyname_ss002: check ReferenceType.methodsByName(...) method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean methodsByName_method_error = false; + + while ( true ) { // test body + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> methbyname_ss002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> methbyname_ss002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + List methodsByName_methods_list = null; + try { + methodsByName_methods_list = refType.methodsByName("dummy_method_name", "dummy_method_signature"); + print_log_anyway + ("##> methbyname_ss002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + methodsByName_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> methbyname_ss002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> methbyname_ss002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + methodsByName_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || methodsByName_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methbyname_ss002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> methbyname_ss002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methbyname_ss002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/TestDescription.java new file mode 100644 index 00000000000..304d73e4797 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002 test + * checks the methodsByName(String name, String signature) method of ReferenceType + * interface of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.methodsByName(String name, String signature) + * method is called for this class - ClassNotPreparedException + * should be thrown in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "out_stream.println" are replaced with + * "print_log_on_verbose" and "print_log_anyway". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss002 + * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/loadclass/methbyname_ss002aClassForCheck.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/loadclass/methbyname_ss002aClassForCheck.java new file mode 100644 index 00000000000..656d9678976 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002/loadclass/methbyname_ss002aClassForCheck.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.methodsByName_ss; + +/** + * This class is loaded by methbyname_ss002aClassLoader . + */ + +class methbyname_ss002aClassForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods + static void s_void_method() {} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_void_par_method(boolean z) {} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + + // instance methods + void i_void_method() {} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_void_par_method(boolean z) {} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + // static initializer + static {} + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002a.java new file mode 100644 index 00000000000..88dbe5521ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss002a.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + + +/** + * This class is used as debugee application for the methbyname_ss002 JDI test. + */ + +public class methbyname_ss002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "methbyname_ss002aClassForCheck"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i methbyname_ss002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + methbyname_ss002aClassLoader customClassLoader = new methbyname_ss002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> methbyname_ss002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> methbyname_ss002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> methbyname_ss002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_ss002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_ss002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methbyname_ss002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methbyname_ss002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class methbyname_ss002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public methbyname_ss002aClassLoader(String classPath, String className) { + super(methbyname_ss002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003.java new file mode 100644 index 00000000000..d8c87906b36 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_ss; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method methodsByName(String name, String signature) + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class methbyname_ss003 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "methbyname_ss003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "methbyname_ss003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new methbyname_ss003().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003 test LOG:"); + print_log_anyway("--> test checks methodsByName(String name, String signature) method of ReferenceType "); + print_log_anyway(" interface of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> methbyname_ss003: methbyname_ss003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> methbyname_ss003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> methbyname_ss003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_ss003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> methbyname_ss003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> methbyname_ss003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_ss003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean methodsByName_ss_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> methbyname_ss003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> methbyname_ss003: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> methbyname_ss003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> methbyname_ss003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> methbyname_ss003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> methbyname_ss003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> methbyname_ss003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.methodsByName_ss() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> methbyname_ss003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> methbyname_ss003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> methbyname_ss003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> methbyname_ss003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> methbyname_ss003: check that checked class has been unloaded realy..."); + print_log_anyway + ("--> methbyname_ss003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.methodsByName_ss() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> methbyname_ss003: check ReferenceType.methodsByName(...) method for unloaded class..."); + List methods_byname_list = null; + try { + methods_byname_list = refType.methodsByName("dummy_method_name", "dummy_method_signature"); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> methbyname_ss003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> methbyname_ss003: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + methodsByName_ss_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || methodsByName_ss_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> methbyname_ss003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> methbyname_ss003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> methbyname_ss003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of methbyname_ss003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TestDescription.java new file mode 100644 index 00000000000..6aabb1ef753 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003. + * VM Testbase keywords: [diehard, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003 test + * checks the methodsByName(String name, String signature) method of + * ReferenceType interface of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * methodsByName(String name, String signature) method - the + * com.sun.jdi.ObjectCollectedException should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - methodsByName_ss003b class was moved in 'loadclass' subdirectory; + * - package name was added in methodsByName_ss003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for methodsByName_ss003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss003 + * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.methodsByName_ss.methbyname_ss003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/loadclass/methbyname_ss003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/loadclass/methbyname_ss003b.java new file mode 100644 index 00000000000..dbef4b6a91b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003/loadclass/methbyname_ss003b.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the methodsByName(String name, String signature) method +//of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.methodsByName_ss; + +class methbyname_ss003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003a.java new file mode 100644 index 00000000000..57906353d8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methodsByName_ss/methbyname_ss003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.methodsByName_ss; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the methbyname_ss003 JDI test. + */ + +public class methbyname_ss003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.methodsByName_ss."; + private final static String checked_class_name = package_prefix + "methbyname_ss003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> methbyname_ss003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> methbyname_ss003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> methbyname_ss003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> methbyname_ss003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> methbyname_ss003a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> methbyname_ss003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_ss003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_ss003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> methbyname_ss003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> methbyname_ss003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> methbyname_ss003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> methbyname_ss003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> methbyname_ss003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> methbyname_ss003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> methbyname_ss003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> methbyname_ss003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> methbyname_ss003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> methbyname_ss003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> methbyname_ss003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of methbyname_ss003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001.java new file mode 100644 index 00000000000..1b5d3c7e39d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method name() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class name001 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.name.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "name001", + debugeeName = thisClassName + "a"; + + private final static String primitive_type_sign = "primitive_type"; + private final static String reference_type_sign = "reference_type"; + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + {"boolean", primitive_type_sign}, + {"byte" , primitive_type_sign}, + {"char" , primitive_type_sign}, + {"double" , primitive_type_sign}, + {"float" , primitive_type_sign}, + {"int" , primitive_type_sign}, + {"long" , primitive_type_sign}, + + {"java.lang.Boolean" , reference_type_sign}, + {"java.lang.Byte" , reference_type_sign}, + {"java.lang.Character", reference_type_sign}, + {"java.lang.Double" , reference_type_sign}, + {"java.lang.Float" , reference_type_sign}, + {"java.lang.Integer" , reference_type_sign}, + {"java.lang.Long" , reference_type_sign}, + {"java.lang.String" , reference_type_sign}, + {"java.lang.Object" , reference_type_sign}, + + {package_prefix + "ClassForCheck", reference_type_sign}, + {package_prefix + "InterfaceForCheck", reference_type_sign}, + + {debugeeName+"$s_class", reference_type_sign}, + {debugeeName+"$s_interf", reference_type_sign} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new name001().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/name/name001 test FAILED"); + } + else { + print_log_anyway("\n==> nsk/jdi/ReferenceType/name/name001 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/name/name001 test LOG:"); + print_log_anyway("==> test checks the name() method of ReferenceType interface"); + print_log_anyway(" of the com.sun.jdi package for ArrayType, ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> name001: name001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway("##> name001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway("##> name001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> name001: debugee's \"ready\" signal recieved!"); + } + + print_log_anyway + ("--> name001: check ReferenceType.name() method for debugee's classes..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int name_method_exceptions = 0; + int name_method_errors = 0; + for (int i=0; i name001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + String ref_type_name = null; + try { + ref_type_name = refType.name(); + } + catch (Throwable thrown) { + print_log_anyway + ("##> name001: FAILED: refType.name() threw unexpected exception - " + + thrown); + print_log_anyway + ("##> refType = " + refType); + name_method_exceptions++; + continue; + } + if ( ! ref_type_name.equals(className) ) { + print_log_anyway + ("##> name001: FAILED: ReferenceType.name() returned unexpected name:"); + print_log_anyway + ("##> expected name = " + className); + print_log_anyway + ("##> returned name = " + ref_type_name); + name_method_errors++; + } + else { + print_log_on_verbose + ("--> name001: PASSED: ReferenceType.name() returned expected name:"); + print_log_on_verbose + ("--> checked class name = " + className); + print_log_on_verbose + ("--> returned name = " + ref_type_name); + } + } + } + print_log_anyway("--> name001: check completed!"); + print_log_anyway("--> name001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + print_log_anyway("##> name001: \"class not found ERRORS\" number = " + + class_not_found_errors); + } + if ( name_method_exceptions > 0 ) { + print_log_anyway("##> name001: number of unexpected name() methods exceptions = " + + name_method_exceptions); + } + print_log_anyway("##> name001: name() method errors number = " + + name_method_errors); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + name_method_errors + name_method_exceptions > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> name001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway("##> name001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> name001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001/TestDescription.java new file mode 100644 index 00000000000..600154862b7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/name/name001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/name/name001 test + * checks the name() method of ReferenceType interface + * of the com.sun.jdi package for ArrayType, ClassType, InterfaceType: + * For each checked debugee's class the test gets ReferenceType + * instance for this class and then gets the name by name() method + * for this ReferenceType instance. + * The test expects that returned name should be equal to the + * checked debugee's class name. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.name.name001 + * nsk.jdi.ReferenceType.name.name001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java new file mode 100644 index 00000000000..c547460c0ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the name001 JDI test. + */ + +public class name001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // Classes must be loaded and linked, so all fields must be + // initialized + Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + static class s_class {} + s_class s_class_0 = new s_class(), s_class_1[]={s_class_0}, + s_class_2[][]={s_class_1}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + static interface s_interf {} + static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl(); + s_interf s_interf_0, s_interf_1[]={s_interf_0}, s_interf_2[][]={s_interf_1}; + + ClassForCheck class_for_check0 = new ClassForCheck(), + class_for_check1[]={class_for_check0}, + class_for_check2[][]={class_for_check1}; + InterfaceForCheck_impl interf_for_check_impl0 = new InterfaceForCheck_impl(); + InterfaceForCheck interf_for_check0, + interf_for_check1[]={interf_for_check0}, + interf_for_check2[][]={interf_for_check1}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i name001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + name001a name001a_obj = new name001a(); + + print_log_on_verbose("**> name001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> name001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> name001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> name001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> name001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class ClassForCheck {} + +interface InterfaceForCheck {} + +class InterfaceForCheck_impl implements InterfaceForCheck{} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002.java new file mode 100644 index 00000000000..8f69320a06d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method name() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class name002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.name.", + thisClassName = package_prefix + "name002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "name002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new name002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/name/name002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/name/name002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/name/name002 test LOG:"); + print_log_anyway("--> test checks name() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> name002: name002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> name002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> name002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> name002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> name002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> name002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> name002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean name_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> name002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> name002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> name002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> name002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> name002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> name002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> name002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.name() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> name002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> name002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> name002: check that checked class has been unloaded really..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> name002: checked class has been unloaded really: " + checked_class); + } + else { + print_log_without_verbose + ("--> name002: check that checked class has been unloaded really..."); + print_log_anyway + ("--> name002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.name() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> name002: check ReferenceType.name() method for unloaded class..."); + String ref_type_name = null; + try { + ref_type_name = refType.name(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> name002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> name002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + name_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || name_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> name002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> name002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> name002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of name002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TestDescription.java new file mode 100644 index 00000000000..f9be40307cd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/name/name002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/name/name002 test + * checks the name() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * name() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - name002b class was moved in 'loadclass' subdirectory; + * - package name was added in name002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for name002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.name.name002 + * nsk.jdi.ReferenceType.name.name002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.name.name002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/loadclass/name002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/loadclass/name002b.java new file mode 100644 index 00000000000..956970997e1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002/loadclass/name002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the name() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.name; + +class name002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002a.java new file mode 100644 index 00000000000..385056310fb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.name; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the name002 JDI test. + */ + +public class name002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.name."; + private final static String checked_class_name = package_prefix + "name002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> name002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> name002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> name002a: checked class loaded: " + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> name002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> name002a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> name002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> name002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> name002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> name002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> name002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> name002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> name002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> name002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> name002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> name002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> name002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> name002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> name002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> name002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of name002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java new file mode 100644 index 00000000000..bea80620850 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.nestedTypes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.nestedTypes()
    + * complies with its spec.
    + *
    + * Cases for testing include only ClassTypes and InterfaceTypes.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class nestedtypes001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/nestedTypes/nestedtypes001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new nestedtypes001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.nestedTypes.nestedtypes001a"; + + String mName = "nsk.jdi.ReferenceType.nestedTypes"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + + String names1[] = { + + ".nestedtypes001aTestClass$NestedClass", + ".nestedtypes001aTestClass$NestedClass[]", + + ".nestedtypes001aTestClass$NestedIface", + ".nestedtypes001aTestClass$NestedIface[]", + + + ".nestedtypes001aTestClass$StaticNestedClass", + ".nestedtypes001aTestClass$StaticNestedClass[]" + + }; + + String typeForCheck = mName + ".nestedtypes001aTestClass"; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classes = vm.classesByName(typeForCheck); + if (classes.size() != 1) { + log3("ERROR: classes.size() != 1 : " + classes.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType testedType = (ReferenceType) classList.get(0);"); + ReferenceType testedType = (ReferenceType) classes.get(0); + + log2(" getting: List netsedTypes = testedType.nestedTypes();"); + List nestedTypes = testedType.nestedTypes(); + if (nestedTypes.size() != names1.length) { + log3("ERROR: nestedTypes.size() != names1.length : " + nestedTypes.size()); + testExitCode = FAILED; + continue; + } + + + log2("----- Cases for testing: ReferenceTypes"); + for (int i1 = 0; i1 < names1.length; i1++) { + + typeForCheck = mName + names1[i1]; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classList = vm.classesByName(typeForCheck); + if (classList.size() != 1) { + log3("ERROR: classList.size() != 1 : " + classList.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType referenceType = (ReferenceType) classList.get(0);"); + ReferenceType referenceType = (ReferenceType) classList.get(0); + + boolean equals = false; + + ListIterator li = nestedTypes.listIterator(); + for (; li.hasNext(); ) { + if (li.next().equals(referenceType)) { + equals = true; + break; + } + } + + if (!equals) { + log3("ERROR: referenceType is not in the List: " + typeForCheck); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001/TestDescription.java new file mode 100644 index 00000000000..0dbd66697cc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/nestedTypes/nestedtypes001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.nestedTypes() + * complies with its spec: + * public List nestedTypes() + * Returns a List containing ReferenceType objects that + * are declared within this type and + * are currently loaded into the Virtual Machine. + * Both static nested types and non-static nested types (that is, inner types) + * are included. Local inner types + * (declared within a code block somewhere in this reference type) + * are also included in the returned list. + * For arrays (ArrayType) and primitive classes, + * the returned list is always empty. + * Returns: a List of nested ReferenceType objects; + * the list has 0 length if there are no nested types. + * Cases for testing include only ClassTypes and InterfaceTypes. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.nestedTypes.nestedtypes001; + * the debuggee program - nsk.jdi.ReferenceType.nestedTypes.nestedtypes001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.nestedTypes.nestedtypes001 + * nsk.jdi.ReferenceType.nestedTypes.nestedtypes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.nestedTypes.nestedtypes001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001a.java new file mode 100644 index 00000000000..44619a5a9d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001a.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.nestedTypes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the nestedtypes001 JDI test. + */ + +public class nestedtypes001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + nestedtypes001aTestClass check = new nestedtypes001aTestClass(); + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + +class nestedtypes001aTestClass { + + + class NestedClass implements NestedIface { + boolean bnc = true; + } + NestedClass nestedClass = new NestedClass(); + NestedClass nestedClassArray[] = { new NestedClass() }; + + interface NestedIface { + boolean bsnf = true; + } + NestedIface nestedIface = new NestedClass(); + NestedIface nestedIfaceArray[] = { new NestedClass() }; + + + static class StaticNestedClass { + boolean bsnc = true; + } + StaticNestedClass staticNestedClass = new StaticNestedClass(); + StaticNestedClass staticNestedClassArray[] = { new StaticNestedClass() }; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java new file mode 100644 index 00000000000..559fc020922 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.nestedTypes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.nestedTypes()
    + * complies with its spec.
    + *
    + * Cases for testing include ArrayType and primitive classes.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class nestedtypes002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/nestedTypes/nestedtypes002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new nestedtypes002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.nestedTypes.nestedtypes002a"; + + String mName = "nsk.jdi.ReferenceType.nestedTypes"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private static BreakpointEvent bpEvent; + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ReferenceType testedType = null; + List nestedTypes = null; + String typeForCheck; + + + log2("----- Case for testing: ArrayType"); + + typeForCheck = mName + ".nestedtypes002aTestClass[]"; + log2("......typeForCheck: " + typeForCheck); + + log2(" getting: List classList = vm.classesByName(typeForCheck);"); + List classes = vm.classesByName(typeForCheck); + if (classes.size() != 1) { + log3("ERROR: classes.size() != 1 : " + classes.size()); + testExitCode = FAILED; + continue; + } + + log2(" getting: ReferenceType testedType = (ReferenceType) classList.get(0);"); + testedType = (ReferenceType) classes.get(0); + + log2(" getting: List nestedTypes = testedType.nestedTypes();"); + nestedTypes = testedType.nestedTypes(); + if (nestedTypes.size() != 0) { + log3("ERROR: nestedTypes.size() != 0 : " + nestedTypes.size()); + testExitCode = FAILED; + continue; + } + + log2("----- Cases for testing: primitive classes"); + + String names[] = { + "bl", + "bt", + "ch", + "db", + "fl", + "in", + "ln", + "sh" + }; + + Method testMethod = (Method)debuggeeClass.methodsByName("main").get(0); + // bpEvent should be assigned while getting of BreakpointEvent + if (bpEvent == null) { + throw new JDITestRuntimeException("bpEvent is null"); + } + + // get stack farme with main method + StackFrame frame = null; + try { + frame = bpEvent.thread().frame(1); + } catch (Exception e) { + throw new JDITestRuntimeException("Unexpected exception while getting stack frame: " + e ); + } + if (frame.location().method() != testMethod) { + throw new JDITestRuntimeException("Cannot take frame of main method"); + } + + for (int i1 = 0; i1 < names.length; i1++) { + + log2("......check for field : " + names[i]); + LocalVariable lVar = null; + try { + lVar = frame.visibleVariableByName(names[i1]); + } catch (Exception e ) { + throw new JDITestRuntimeException("Unexpected exception while searching for field " + names[i1] + " : " + e ); + } + Value val = null; + try { + val = frame.getValue(lVar); + } catch (Exception e ) { + throw new JDITestRuntimeException("Unexpected exception while getting value of field " + names[i1] + " : " + e ); + } + + testedType = ((ClassObjectReference)val).reflectedType(); + + log2(" checking nestedTypes() for ClassObjectReference of : " + testedType.name()); + nestedTypes = testedType.nestedTypes(); + if (nestedTypes.size() != 0) { + log3("ERROR: nestedTypes.size() != 0 : " + nestedTypes.size()); + testExitCode = FAILED; + continue; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + Event event = eventIterator.nextEvent(); + if ( event instanceof BreakpointEvent) { + bpEvent = (BreakpointEvent)event; + return; + } + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002/TestDescription.java new file mode 100644 index 00000000000..ba442df440e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/nestedTypes/nestedtypes002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.nestedTypes() + * complies with its spec: + * public List nestedTypes() + * Returns a List containing ReferenceType objects that + * are declared within this type and + * are currently loaded into the Virtual Machine. + * Both static nested types and non-static nested types (that is, inner types) + * are included. Local inner types + * (declared within a code block somewhere in this reference type) + * are also included in the returned list. + * For arrays (ArrayType) and primitive classes, + * the returned list is always empty. + * Returns: a List of nested ReferenceType objects; + * the list has 0 length if there are no nested types. + * Cases for testing include ArrayType and primitive classes. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.nestedTypes.nestedtypes002; + * the debuggee program - nsk.jdi.ReferenceType.nestedTypes.nestedtypes002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was modified to fix of the bug: + * 4740126 TEST_BUG: ReferenceType.nestedTypes() returns wrong number of nested types + * Please, see an evaluation of the bug for details. + * 4773489 TEST_BUG nestedtypes002 failing + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.nestedTypes.nestedtypes002 + * nsk.jdi.ReferenceType.nestedTypes.nestedtypes002a + * + * @comment make sure nestedtypes002a is compiled with full debug info + * @clean nsk.jdi.ReferenceType.nestedTypes.nestedtypes002a + * @compile -g:lines,source,vars ../nestedtypes002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.nestedTypes.nestedtypes002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002a.java new file mode 100644 index 00000000000..f486ca5bc26 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002a.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.nestedTypes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the nestedtypes002 JDI test. + */ + +public class nestedtypes002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + nestedtypes002aTestClass testArray[] = { new nestedtypes002aTestClass() }; + + Class bl = Boolean.TYPE; + Class bt = Byte.TYPE; + Class ch = Character.TYPE; + Class db = Double.TYPE; + Class fl = Float.TYPE; + Class in = Integer.TYPE; + Class ln = Long.TYPE; + Class sh = Short.TYPE; + + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + +class nestedtypes002aTestClass { + + class NestedClass implements NestedIface { + boolean bnc = true; + } + NestedClass nestedClass = new NestedClass(); + NestedClass nestedClassArray[] = { new NestedClass() }; + + interface NestedIface { + boolean bsnf = true; + } + NestedIface nestedIface = new NestedClass(); + NestedIface nestedIfaceArray[] = { new NestedClass() }; + + + + static class StaticNestedClass { + boolean bsnc = true; + } + StaticNestedClass staticNestedClass = new StaticNestedClass(); + StaticNestedClass staticNestedClassArray[] = { new StaticNestedClass() }; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001.java new file mode 100644 index 00000000000..3db76e18d38 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourceDebugExtension; + +import com.sun.jdi.ReferenceType; +import com.sun.jdi.ObjectCollectedException; +import com.sun.jdi.AbsentInformationException; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that the SourceDebugExtension class file + * attribute can be obtained by the JDI method + * ReferenceType.sourceDebugExtension(), + * otherwise the method should throw the AbsentInformationException. + */ +public class srcdebugx001 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx001t"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private IOPipe pipe; + private Debugee debuggee; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new srcdebugx001().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "srcdebugx001t.err> "); + debuggee.resume(); + + log.display("Waiting for debuggee readiness..."); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + return quitDebuggee(FAILED); + } + + if ((rType = debuggee.classByName(DEBUGGEE_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null"); + return quitDebuggee(FAILED); + } + + if (!debuggee.VM().canGetSourceDebugExtension()) { + + log.display(" VirtualMachine.canGetSourceDebugExtension() == false"); + log.display(" UnsupportedOperationException is expected"); + try { + String debugX = rType.sourceDebugExtension(); + log.complain("TEST FAILED: no UnsupportedOperationException thrown"); + return quitDebuggee(FAILED); + } catch ( UnsupportedOperationException e1 ) { + log.display(" UnsupportedOperationException thrown"); + return quitDebuggee(PASSED); + } catch ( Exception e2) { + log.complain("TEST FAILED: unexpected Exception thrown : " + e2); + return quitDebuggee(FAILED); + } + + } else { + + log.display(" VirtualMachine.canGetSourceDebugExtension() == true"); + log.display(" UnsupportedOperationException is not expected"); + + try { + String debugX = rType.sourceDebugExtension(); + log.display("TEST PASSED: successfully obtained the SourceDebugExtension attribute: \"" + + debugX + "\""); + return quitDebuggee(PASSED); + } catch(AbsentInformationException e) { + log.display("TEST PASSED: caught the expected exception: " + e); + return quitDebuggee(PASSED); + } catch (Exception e) { + log.complain("TEST FAILED: caught " + e); + return quitDebuggee(FAILED); + } + } + } + + private int quitDebuggee(int stat) { + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return stat; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001/TestDescription.java new file mode 100644 index 00000000000..8466eab558b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the SourceDebugExtension class file + * attribute can be obtained by the JDI method + * ReferenceType.sourceDebugExtension(), otherwise the method + * should throw the AbsentInformationException + * COMMENTS + * To fix the bug 4493107, a corresponding check is added. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx001 + * nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx001t + * + * @comment make sure srcdebugx001t is compiled with full debug info + * @clean nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx001t + * @compile -g:lines,source,vars ../srcdebugx001t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001t.java new file mode 100644 index 00000000000..eb249a13a07 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx001t.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourceDebugExtension; + +import com.sun.jdi.ReferenceType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This is dummy debuggee class + */ +public class srcdebugx001t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(srcdebugx001.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(srcdebugx001.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(srcdebugx001.JCK_STATUS_BASE + + srcdebugx001.FAILED); + } + System.exit(srcdebugx001.JCK_STATUS_BASE + + srcdebugx001.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002.java new file mode 100644 index 00000000000..710f530d97d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourceDebugExtension; + +import com.sun.jdi.ReferenceType; +import com.sun.jdi.AbsentInformationException; +import com.sun.jdi.ObjectCollectedException; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * The test checks that the JDI method + * ReferenceType.sourceDebugExtension() properly returns + * the SourceDebugExtension Class File attribute. String obtained from + * the sourceDebugExtension() is compared with the expected + * attribute string. + */ +public class srcdebugx002 { + public static final int PASSED = 0; + public static final int FAILED = 2; + public static final int JCK_STATUS_BASE = 95; + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx002t"; + static final String SRCDEBUGX_CLASS = + "nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx002x"; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String SRCDEBUGXSTR = "Hello world!"; + + private IOPipe pipe; + private Debugee debuggee; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new srcdebugx002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + Log log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + ReferenceType rType; + String debugX = null; + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "srcdebugx002t.err> "); + debuggee.resume(); + + log.display("Waiting for debuggee readiness..."); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + cmd); + return quitDebuggee(FAILED); + } + + if ((rType = debuggee.classByName(SRCDEBUGX_CLASS)) == null) { + log.complain("TEST FAILURE: Method Debugee.classByName() returned null"); + return quitDebuggee(FAILED); + } + + if (!debuggee.VM().canGetSourceDebugExtension()) { + log.display("TEST CANCELLED: VirtualMachine.canGetSourceDebugExtension() == false"); + return quitDebuggee(PASSED); + } + + try { + debugX = rType.sourceDebugExtension(); + log.display("Check #1 PASSED: successfully obtained the SourceDebugExtension attribute"); + } catch(AbsentInformationException e) { + log.display("TEST FAILED: caught the exception: " + e); + return quitDebuggee(FAILED); + } catch (ObjectCollectedException e) { + log.complain("TEST FAILED: caught the exception: " + e); + return quitDebuggee(FAILED); + } + + if (debugX.equals(SRCDEBUGXSTR)) { + log.display("Check #2 PASSED: obtained the expected SourceDebugExtension attribute \"" + + debugX + "\""); + return quitDebuggee(PASSED); + } else { + log.complain("TEST FAILED: the SourceDebugExtension attribute is \"" + + debugX + "\",\n\texpected: \"" + SRCDEBUGXSTR + "\""); + return quitDebuggee(FAILED); + } + } + + private int quitDebuggee(int stat) { + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return stat; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002/TestDescription.java new file mode 100644 index 00000000000..5aa7a1ddef6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method ReferenceType.sourceDebugExtension() + * properly returns the SourceDebugExtension Class File attribute. + * String obtained from the sourceDebugExtension() is compared with + * the expected attribute string. + * COMMENTS + * The file srcdebugx002x.jcod has been generated by the JCK's SQE tool Jdec + * for the class file compiled by Javac from a source file srcdebugx002x.java + * which is located at the directory srcdebugx.jdec. Please note that only + * the Jcoder tool implemented the RFE 4460411, must be used. + * The test was updated due to the bug 4422724. + * To fix the bug 4493107, a corresponding check is added. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx002 + * nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx002t + * @compile srcdebugx002x.jcod + * @build ExecDriver + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.sourceDebugExtension.srcdebugx002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002/srcdebugx002x.jcod b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002/srcdebugx002x.jcod new file mode 100644 index 00000000000..ce8fc1c9aab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002/srcdebugx002x.jcod @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001, 2018, 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. + */ + +class nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002x { + 0xCAFEBABE; + 3; // minor version + 45; // version + [] { // Constant Pool + ; // first element is empty + Method #3 #15; // #1 + class #16; // #2 + class #17; // #3 + Utf8 ""; // #4 + Utf8 "()V"; // #5 + Utf8 "Code"; // #6 + Utf8 "LineNumberTable"; // #7 + Utf8 "LocalVariableTable"; // #8 + Utf8 "this"; // #9 + Utf8 "Lnsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002x;"; // #10 + Utf8 "readiness"; // #11 + Utf8 "()I"; // #12 + Utf8 "SourceFile"; // #13 + Utf8 "srcdebugx002x.java"; // #14 + NameAndType #4 #5; // #15 + Utf8 "nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002x"; // #16 + Utf8 "java/lang/Object"; // #17 + Utf8 "SourceDebugExtension"; // #18 + } // Constant Pool + + 0x0021; // access + #2;// this_cpx + #3;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // fields + } // fields + + [] { // methods + { // Member + 0x0001; // access + #4; // name_cpx + #5; // sig_cpx + [] { // Attributes + Attr(#6) { // Code + 1; // max_stack + 1; // max_locals + Bytes[] { + 0x2AB70001B1; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#7) { // LineNumberTable + [] { // LineNumberTable + 0 11; + } + } // end LineNumberTable + ; + Attr(#8) { // LocalVariableTable + [] { // LocalVariableTable + 0 5 9 10 0; + } + } // end LocalVariableTable + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member + 0x0008; // access + #11; // name_cpx + #12; // sig_cpx + [] { // Attributes + Attr(#6) { // Code + 1; // max_stack + 0; // max_locals + Bytes[] { + 0x1107D1AC; + }; + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#7) { // LineNumberTable + [] { // LineNumberTable + 0 13; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + Attr(#13) { // SourceFile + #14; + } // end SourceFile + ; + Attr(#18) { // SourceDebugExtension + 'Hello world!'; // an UTF string without prepended length + } // end SourceDebugExtension + } // Attributes +} // end class nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002x diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002t.java new file mode 100644 index 00000000000..f6ac5ccd209 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002t.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourceDebugExtension; + +import com.sun.jdi.ReferenceType; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This debuggee class gets the Class object associated with the class + * srcdebugx002x containing the SourceDebugExtension attribute. + */ +public class srcdebugx002t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + Class srcdebX; + +// get auxiliary class containing the SourceDebugExtension attribute + try { + srcdebX = Class.forName(srcdebugx002.SRCDEBUGX_CLASS); + } catch(Exception e) { + System.err.println("TEST BUG: caught in debuggee: " + + e); + System.exit(srcdebugx002.JCK_STATUS_BASE + + srcdebugx002.FAILED); + } + + pipe.println(srcdebugx002.COMMAND_READY); + String cmd = pipe.readln(); + if (!cmd.equals(srcdebugx002.COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown debugger command: " + + cmd); + System.exit(srcdebugx002.JCK_STATUS_BASE + + srcdebugx002.FAILED); + } + System.exit(srcdebugx002.JCK_STATUS_BASE + + srcdebugx002.PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002x.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002x.java new file mode 100644 index 00000000000..f78fa86f046 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceDebugExtension/srcdebugx002x.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourceDebugExtension; + +/** + * This is dummy auxiliary class used only in process of generation + * a source file *.jcod for the JCK's SQE tool Jcoder. + */ +public class srcdebugx002x { + static int readiness() { + return 2001; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001.java new file mode 100644 index 00000000000..cf2f6a74260 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.sourceName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method sourceName() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class sourcename001 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class sourceNames of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.sourceName.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "sourcename001", + debugeeName = thisClassName + "a"; + + static String this_class_source_name = "sourcename001.java"; + static String debugee_source_name = "sourcename001a.java"; + + /** Debugee's classes for check **/ + private final static String classes_for_check[][] = { + + {thisClassName, this_class_source_name}, + {debugeeName, debugee_source_name}, + + {package_prefix + "ClassForCheck", debugee_source_name}, + {package_prefix + "InterfaceForCheck", debugee_source_name}, + + {debugeeName+"$s_class", debugee_source_name}, + {debugeeName+"$s_interf", debugee_source_name} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new sourcename001().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway("\n==> nsk/jdi/ReferenceType/sourceName/sourcename001 test FAILED"); + } + else { + print_log_anyway("\n==> nsk/jdi/ReferenceType/sourceName/sourcename001 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/sourceName/sourcename001 test LOG:"); + print_log_anyway("==> test checks the sourceName() method of ReferenceType interface"); + print_log_anyway(" of the com.sun.jdi package for ClassType, InterfaceType\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> sourcename001: sourcename001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway("##> sourcename001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway("##> sourcename001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> sourcename001: debugee's \"ready\" signal recieved!"); + } + + print_log_anyway + ("--> sourcename001: check ReferenceType.sourceName() method for debugee's classes..."); + int all_classes_count = 0; + int class_not_found_errors = 0; + int sourceName_method_exceptions = 0; + int sourceName_method_errors = 0; + for (int i=0; i sourcename001: Could NOT FIND class: " + className); + class_not_found_errors++; + continue; + } + String ref_type_source_name = null; + try { + ref_type_source_name = refType.sourceName(); + } + catch (Throwable thrown) { + print_log_anyway + ("##> sourcename001: FAILED: refType.sourceName() threw unexpected exception - " + + thrown); + print_log_anyway + ("##> refType = " + refType); + sourceName_method_exceptions++; + continue; + } + if ( ! ref_type_source_name.equals(source_class_name) ) { + print_log_anyway + ("##> sourcename001: FAILED: ReferenceType.sourceName() returned unexpected source name:"); + print_log_anyway + ("##> expected source name = " + source_class_name); + print_log_anyway + ("##> returned source name = " + ref_type_source_name); + sourceName_method_errors++; + } + else { + print_log_on_verbose + ("--> sourcename001: PASSED: ReferenceType.sourceName() returned expected source name:"); + print_log_on_verbose + ("--> checked class source name = " + source_class_name); + print_log_on_verbose + ("--> returned source name = " + ref_type_source_name); + } + } + print_log_anyway("--> sourcename001: check completed!"); + print_log_anyway("--> sourcename001: number of checked classes = " + all_classes_count); + if ( class_not_found_errors > 0 ) { + print_log_anyway("##> sourcename001: \"class not found ERRORS\" number = " + + class_not_found_errors); + } + if ( sourceName_method_exceptions > 0 ) { + print_log_anyway("##> sourcename001: number of unexpected sourceName() methods exceptions = " + + sourceName_method_exceptions); + } + print_log_anyway("##> sourcename001: sourceName() method errors number = " + + sourceName_method_errors); + int v_test_result = 0/*STATUS_PASSED*/; + if (class_not_found_errors + sourceName_method_errors + sourceName_method_exceptions > 0) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> sourcename001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway("##> sourcename001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> sourcename001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001/TestDescription.java new file mode 100644 index 00000000000..65463387a15 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/sourceName/sourcename001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/sourceName/sourcename001 test + * checks the sourceName() method of ReferenceType interface + * of the com.sun.jdi package for ClassType, InterfaceType: + * For each checked debugee's class the test gets ReferenceType + * instance for this class and then gets the source name by sourceName() + * method for this ReferenceType instance. + * The test expects that returned source name should be equal to the + * file name which declarates the checked debugee's class. + * COMMENTS + * Bug fixed: 4434819: TEST_BUG: wrongly believe that classes are loaded + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.sourceName.sourcename001 + * nsk.jdi.ReferenceType.sourceName.sourcename001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.sourceName.sourcename001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001a.java new file mode 100644 index 00000000000..b6d6e49b9ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename001a.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.sourceName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the sourcename001 JDI test. + */ + +public class sourcename001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + // Classes must be loaded and linked, so all fields must be + // initialized + static class s_class {} + s_class s_class_0 = new s_class(), s_class_1[]={s_class_0}; + + // Interfaces must be loaded and linked, so classes that implement + // interfaces must be initialized. + static interface s_interf {} + static class s_interf_impl implements s_interf {} + s_interf_impl sii0 = new s_interf_impl (); + s_interf s_interf_0, s_interf_1[]={s_interf_0}; + + ClassForCheck class_for_check0 = new ClassForCheck(), + class_for_check1[]={class_for_check0}; + InterfaceForCheck_impl interf_for_check_impl0 = new InterfaceForCheck_impl(); + InterfaceForCheck interf_for_check0, + interf_for_check1[]={interf_for_check0}; + + sourcename001 sourcename001_0 = new sourcename001(), + sourcename001_1[]={sourcename001_0}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i sourcename001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + sourcename001a sourcename001a_obj = new sourcename001a(); + + print_log_on_verbose("**> sourcename001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> sourcename001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> sourcename001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> sourcename001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> sourcename001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class ClassForCheck {} + +interface InterfaceForCheck {} + +class InterfaceForCheck_impl implements InterfaceForCheck{} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002.java new file mode 100644 index 00000000000..ff5f2a9caf8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.sourceName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method sourceName() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class sourcename002 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class sourceNames of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.sourceName.", + thisClassName = package_prefix + "sourcename002", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "sourcename002b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new sourcename002().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/sourceName/sourcename002 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/sourceName/sourcename002 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + argv = argsHandler.getArguments(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/sourceName/sourcename002 test LOG:"); + print_log_anyway("--> test checks sourceName() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for UNLOADED class\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> sourcename002: sourcename002a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> sourcename002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + print_log_anyway + ("##> sourcename002: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> sourcename002: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> sourcename002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + print_log_anyway + ("##> sourcename002: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> sourcename002: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean sourceName_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> sourcename002: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> sourcename002: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> sourcename002: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> sourcename002: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> sourcename002: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> sourcename002: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + print_log_anyway + ("--> sourcename002: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + print_log_anyway + ("--> ReferenceType.sourceName() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + print_log_anyway + ("##> sourcename002: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> sourcename002: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> sourcename002: check that checked class has been unloaded really..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> sourcename002: checked class has been unloaded really: " + checked_class); + } + else { + print_log_without_verbose + ("--> sourcename002: check that checked class has been unloaded really..."); + print_log_anyway + ("--> sourcename002: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + print_log_anyway + ("--> ReferenceType.sourceName() method can NOT be checked!"); + break; + } + + print_log_anyway + ("--> sourcename002: check ReferenceType.sourceName() method for unloaded class..."); + String ref_type_sourceName = null; + try { + ref_type_sourceName = refType.sourceName(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + print_log_anyway + ("--> sourcename002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> sourcename002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + sourceName_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || sourceName_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> sourcename002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> sourcename002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> sourcename002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of sourcename002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TestDescription.java new file mode 100644 index 00000000000..2ef7a03aff6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/sourceName/sourcename002. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/sourceName/sourcename002 test + * checks the sourceName() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * sourceName() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - sourcename002b class was moved in 'loadclass' subdirectory; + * - package name was added in sourcename002b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for sourcename002b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.sourceName.sourcename002 + * nsk.jdi.ReferenceType.sourceName.sourcename002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.sourceName.sourcename002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/loadclass/sourcename002b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/loadclass/sourcename002b.java new file mode 100644 index 00000000000..77582aaba72 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002/loadclass/sourcename002b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the sourceName() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.sourceName; + +class sourcename002b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002a.java new file mode 100644 index 00000000000..dcb2f8ec75f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.sourceName; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the sourcename002 JDI test. + */ + +public class sourcename002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.sourceName."; + private final static String checked_class_name = package_prefix + "sourcename002b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> sourcename002a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> sourcename002a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> sourcename002a: checked class loaded: " + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + print_log_on_verbose + ("**> sourcename002a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> sourcename002a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> sourcename002a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> sourcename002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> sourcename002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> sourcename002a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> sourcename002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> sourcename002a: \"continue\" signal recieved!"); + print_log_on_verbose("**> sourcename002a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> sourcename002a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> sourcename002a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> sourcename002a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> sourcename002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> sourcename002a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> sourcename002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> sourcename002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of sourcename002a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003.java new file mode 100644 index 00000000000..ac91b7dc2de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.sourceName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method sourceName() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class sourcename003 { + static ArgumentHandler argsHandler; + static Log test_log_handler; + static boolean verbose_mode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + /** The main class sourceNames of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.sourceName.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "sourcename003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = thisClassName + "[]"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int v_test_result = new sourcename003().runThis(argv,out); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/sourceName/sourcename003 test FAILED"); + } + else { + print_log_anyway + ("\n==> nsk/jdi/ReferenceType/sourceName/sourcename003 test PASSED"); + } + return v_test_result; + } + + private static void print_log_on_verbose(String message) { + test_log_handler.display(message); + } + + private static void print_log_without_verbose(String message) { + test_log_handler.comment(message); + } + + private static void print_log_anyway(String message) { + test_log_handler.println(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + argsHandler = new ArgumentHandler(argv); + verbose_mode = argsHandler.verbose(); + test_log_handler = new Log(out, argsHandler); + + print_log_anyway("==> nsk/jdi/ReferenceType/sourceName/sourcename003 test LOG:"); + print_log_anyway("--> test checks sourceName() method of ReferenceType interface "); + print_log_anyway(" of the com.sun.jdi package for class with unknown source name\n"); + + String debugee_launch_command = debugeeName; + + Binder binder = new Binder(argsHandler,test_log_handler); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> sourcename003: sourcename003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + print_log_anyway + ("##> sourcename003: UNEXPECTED debugee's signal (not \"ready\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready")) { + print_log_anyway + ("##> sourcename003: UNEXPECTED debugee's signal (not \"ready\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> sourcename003: debugee's \"ready\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean sourceName_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> sourcename003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> sourcename003: getting ReferenceType object for loaded checked class..."); + print_log_anyway("##> sourcename003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> sourcename003: checked class FOUND: " + checked_class); + } + print_log_anyway + ("--> sourcename003: check ReferenceType.sourceName() method for class with unknown source name..."); + print_log_anyway + ("--> checked class - " + checked_class); + String ref_type_sourceName = null; + try { + ref_type_sourceName = refType.sourceName(); + print_log_anyway + ("##> sourcename003: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> returned sourceName = " + ref_type_sourceName); + print_log_anyway + ("##> expected Exception - com.sun.jdi.AbsentInformationException"); + sourceName_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.AbsentInformationException) { + print_log_anyway + ("--> sourcename003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> sourcename003: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.AbsentInformationException"); + sourceName_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || sourceName_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> sourcename003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> sourcename003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> sourcename003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of sourcename003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003/TestDescription.java new file mode 100644 index 00000000000..a243d9ef162 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/sourceName/sourcename003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/sourceName/sourcename003 test + * checks the sourceName() method of ReferenceType interface + * of the com.sun.jdi package for class with unknown source name: + * the test loads a class with unknown source name, gets + * a ReferenceType instance for this class and calls the + * sourceName() method - the com.sun.jdi.AbsentInformationException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.sourceName.sourcename003 + * nsk.jdi.ReferenceType.sourceName.sourcename003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.sourceName.sourcename003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003a.java new file mode 100644 index 00000000000..3bdeddb3ec3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename003a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.sourceName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the sourcename003 JDI test. + */ + +public class sourcename003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + sourcename003 sourcename003_0, sourcename003_1[]={sourcename003_0}; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i sourcename003a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + sourcename003a sourcename003a_obj = new sourcename003a(); + + print_log_on_verbose("**> sourcename003a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> sourcename003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> sourcename003a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> sourcename003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> sourcename003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename004.java new file mode 100644 index 00000000000..ff54267302b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceName/sourcename004.java @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.sourceName; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.sourceName() + * properly throws AbsentInformationException - if the source + * name is not known.

    + * + * The test exercises the following assertion:
    + * "For arrays (ArrayType) and primitive classes, + * AbsentInformationException is always thrown".
    + * It works as follows. Debugger part attempts to get an identifying + * source name of reference types corresponding to several debuggee fields + * by calling the JDI method. These fields have types of different + * kinds: primitive classes themselves, and arrays of primitive types + * and classes. The exception is expected to be thrown. + */ +public class sourcename004 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.sourceName.sourcename004t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "sourcename004tThr"; + + // name of debuggee method used to find needed stack frame + static final String DEBUGGEE_METHOD = "sourcename004trunIt"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 57; + + static final int FLD_NUM = 24; + // tested fields used to provoke the exception + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new sourcename004().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "sourcename004t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main thread + ThreadReference thrRef = null; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) + throw new Failure("method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + Method meth = debuggee.methodByName(rType, DEBUGGEE_METHOD); + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + ObjectReference objRef = findObjRef(thrRef, meth); + + for (int i=0; i standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type2(className, testStratumCount); + /* + * Method 'prepareDefaultPathcedClassFile_Type2' creates class file with + * following line mapping for each TestStratum: "Java" "TestStratum" + * + * + * 9 --> 1000, source1, path1 + * 10 --> 1001, source2, path2 + * 11 --> 1002, source3, path3 + * ... + * ... + * + * sde_testMethod1 + * 20 --> 1100, source1, path1 + * 21 --> 1101, source2, path2 + * 22 --> 1102, source3, path3 + * ... + * ... + * + * sde_testMethod2 + * 31 --> 1200, source1, path1 + * 32 --> 1201, source2, path2 + * 33 --> 1207, source3, path3 + * ... + * ... + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName : testStratumData.keySet()) { + log.display("Check sources for stratum: '" + stratumName + "'"); + + LocationsData locationsData = testStratumData.get(stratumName); + + // create list with expected sources + List sourceNames = new ArrayList(); + sourceNames.addAll(locationsData.sourceLocations.keySet()); + + check_ReferenceType_sourceNames(referenceType, stratumName, sourceNames); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001.java new file mode 100644 index 00000000000..2871d7134c5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourceNames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.sourceNames(String)
    + * complies with its specification.
    + *
    + * The case for testing includes a Class type in a debuggee, and
    + * debuggee's sourcecode file with a predefined name.
    + * A debugger gets ReferenceType object, mirroring tested Class and
    + * performs the following:
    + * - gets a List returned by the method
    + * ReferenceType.sourceNames(defaultStratum);
    + * - checks that the List contains only one String element which,
    + * is equal to the predefined one.
    + */ + +public class sourcenames001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/sourceNames/sourcenames001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new sourcenames001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.sourceNames.sourcenames001a"; + + //String mName = "nsk.jdi.ReferenceType.sourceNames"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List sourceNames = null; + ReferenceType refType = null; + + log2(" getting: List classes = vm.classesByName(debuggeeName);"); + List classes = vm.classesByName(debuggeeName); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2(" getting a tested ReferenceType object 'refType'"); + refType = (ReferenceType) classes.get(0); + + log2("...... getting : String defaultStratum = vm.getDefaultStratum();"); + String defaultStratum = vm.getDefaultStratum(); + + log2("......sourceNames = refType.sourceNames(defaultStratum);"); + log2(" no AbsentInformationException is expected"); + try { + sourceNames = refType.sourceNames(defaultStratum); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + break ; + } + + log2("......checking up on a value of sourceNames.size(); 1 is expected"); + if (sourceNames.size() != 1) { + testExitCode = FAILED; + log3("ERROR: sourceNames.size() != 1"); + break ; + } + + log2("......getting: String sourceName = sourceNames.get(0);"); + String sourceName; + try { + sourceName = (String) sourceNames.get(0); + log2(" sourceName == " + sourceName); + } catch ( Exception e ) { + log3("ERROR: exception thrown : " + e); + testExitCode = FAILED; + break ; + } + log2("......checking up on equality: sourceName.equals('sourcenames001a.java')"); + if (!sourceName.equals("sourcenames001a.java")) { + log3("ERROR: sourceName is not equal to 'sourcenames001a.java' : " + sourceName); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001/TestDescription.java new file mode 100644 index 00000000000..45b53cbf670 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001/TestDescription.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/sourceNames/sourcenames001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.sourceNames() + * complies with its spec: + * public List sourceNames(String stratum) + * throws AbsentInformationException + * Gets the identifying names for all the source corresponding to + * the declaration of this type. Interpretation of these names is the + * responsibility of the source repository mechanism. + * The returned names are for the specified stratum + * (see Location for a description of strata). + * In the reference implementation, when using the Java programming language stratum, + * the returned List contains one element: + * a String which is the unqualified name of the source file + * containing the declaration of this type. + * In other strata the returned source names are + * all the source names defined for that stratum. + * Parameters: stratum - The stratum to retrieve information from or + * null for the declaring type's default stratum. + * Returns: a List of String objects each representing a source name + * Throws: AbsentInformationException - + * if the source names are not known. + * For arrays (ArrayType) and primitive classes, + * AbsentInformationException is always thrown. + * The case for testing includes a Class type in a debuggee, and + * debuggee's sourcecode file with a predefined name. + * No AbsentInformationException is expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.sourceNames.sourcenames001; + * the debuggee program - nsk.jdi.ReferenceType.sourceNames.sourcenames001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.sourceNames.sourcenames001 + * nsk.jdi.ReferenceType.sourceNames.sourcenames001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.sourceNames.sourcenames001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001a.java new file mode 100644 index 00000000000..7cb91e2ffe2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourceNames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the sourcenames001 JDI test. + */ + +public class sourcenames001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ReferenceType.sourceNames() + * properly throws AbsentInformationException - if the source + * names are not known.

    + * + * The test exercises the following assertion:
    + * "For arrays (ArrayType) and primitive classes, + * AbsentInformationException is always thrown".
    + * It works as follows. Debugger part attempts to get identifying + * source names of reference types corresponding to several debuggee + * fields by calling the JDI method. These fields have types of + * different kinds: primitive classes themselves, and arrays of + * primitive types and classes. The exception is expected to be thrown. + */ +public class sourcenames002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.sourceNames.sourcenames002t"; + + // name of debuggee main thread + static final String DEBUGGEE_THRNAME = "sourcenames002tThr"; + + // name of debuggee method used to find needed stack frame + static final String DEBUGGEE_METHOD = "sourcenames002trunIt"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 57; + + static final int FLD_NUM = 24; + // tested fields used to provoke the exception + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new sourcenames002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "sourcenames002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main thread + ThreadReference thrRef = null; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) + throw new Failure("method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + Method meth = debuggee.methodByName(rType, DEBUGGEE_METHOD); + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + ObjectReference objRef = findObjRef(thrRef, meth); + + for (int i=0; i standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type2(className, testStratumCount); + /* + * Method 'prepareDefaultPathcedClassFile_Type2' creates SDE with + * following source map: "Java" "TestStratum" + * + * + * 9 --> 1000, source1, path1 + * 10 --> 1001, source1, path1 + * ... + * 16 --> 1007, source1, path1 + * + * testMethod1 + * 20 --> 1100, source2, path2 + * 21 --> 1101, source2, path2 + * ... + * 27 --> 1107, source2, path2 + * + * testMethod1 + * 31 --> 1200, source3, path3 + * 32 --> 1201, source3, path3 + * ... + * 38 --> 1207, source3, path3 + */ + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + for (String stratumName : testStratumData.keySet()) { + log.display("Check paths for stratum: '" + stratumName + "'"); + + LocationsData locationsData = testStratumData.get(stratumName); + check_ReferenceType_sourcePaths(referenceType, stratumName, locationsData.paths); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001.java new file mode 100644 index 00000000000..7961d33699e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001.java @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourcePaths; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ReferenceType.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ReferenceType.sourcePaths()
    + * complies with its specification.
    + *
    + * The case for testing debuggee's sourcecode file with a predefined name
    + * and a predefined package name.
    + * A debugger gets ReferenceType object, mirroring debuggee's Class and
    + * performs the following:
    + * - gets a List returned by the method
    + * ReferenceType.sourcePaths(defaultStratum);
    + * - checks that the List contains only one String element which,
    + * is equal to the String which is concatenation of the package name
    + * and the sourceName.
    + */ + +public class sourcepaths001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ReferenceType/sourcePaths/sourcepaths001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new sourcepaths001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ReferenceType.sourcePaths.sourcepaths001a"; + + //String mName = "nsk.jdi.ReferenceType.sourcePaths"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List sourcePaths = null; + List sourceNames = null; + ReferenceType refType = null; + + log2(" getting: List classes = vm.classesByName(debuggeeName);"); + List classes = vm.classesByName(debuggeeName); + + if (classes.size() != 1) { + testExitCode = FAILED; + log3("ERROR: classes.size() != 1"); + break ; + } + + log2(" getting a tested ReferenceType object 'refType'"); + refType = (ReferenceType) classes.get(0); + + log2("...... getting : String defaultStratum = vm.getDefaultStratum();"); + String defaultStratum = vm.getDefaultStratum(); + + log2("......sourcePaths = refType.sourcePaths(defaultStratum);"); + log2(" no AbsentInformationException is expected"); + try { + sourcePaths = refType.sourcePaths(defaultStratum); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + break ; + } + + log2("......checking up on a value of sourcePaths.size(); 1 is expected"); + if (sourcePaths.size() != 1) { + testExitCode = FAILED; + log3("ERROR: sourcePaths.size() != 1"); + break ; + } + + log2("......getting: String sourcePath = sourcePaths.get(0);"); + String sourcePath; + try { + sourcePath = (String) sourcePaths.get(0); + log2(" sourcePath == " + sourcePath); + } catch ( Exception e ) { + log3("ERROR: exception thrown : " + e); + testExitCode = FAILED; + break ; + } + + log2("......sourceNames = refType.sourceNames(defaultStratum);"); + log2(" no AbsentInformationException is expected"); + try { + sourceNames = refType.sourceNames(defaultStratum); + } catch ( AbsentInformationException e ) { + testExitCode = FAILED; + log3("ERROR: AbsentInformationException"); + break ; + } + + log2("......checking up on a value of sourceNames.size(); 1 is expected"); + if (sourceNames.size() != 1) { + testExitCode = FAILED; + log3("ERROR: sourceNames.size() != 1"); + break ; + } + + log2("......getting: String sourceName = sourceNames.get(0);"); + String sourceName; + try { + sourceName = (String) sourceNames.get(0); + log2(" sourceName == " + sourceName); + } catch ( Exception e ) { + log3("ERROR: exception thrown : " + e); + testExitCode = FAILED; + break ; + } + + log2("......forming String debuggeeSourcePath : package name + sourceName"); + String sep = System.getProperty("file.separator"); + String debuggeeSourcePath = "nsk" + sep + "jdi" + sep + "ReferenceType" + sep + + "sourcePaths" + sep + sourceName; + + log2("......compareing: sourcePath to debuggeeSourcePath"); + if (!sourcePath.equals(debuggeeSourcePath)) { + log3("ERROR: sourcePath != debuggeeSourcePath"); + log3(" sourcePath == " + sourcePath); + log3(" debuggeeSourcePath == " + debuggeeSourcePath); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001/TestDescription.java new file mode 100644 index 00000000000..4d9514eae1b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/sourcePaths/sourcepaths001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ReferenceType. + * The test checks up that a result of the method + * com.sun.jdi.ReferenceType.sourcePaths() + * complies with its spec: + * public List sourcePaths(String stratum) + * throws AbsentInformationException + * Gets the paths to the source corresponding to the declaration of this type. + * Interpretation of these paths is the responsibility of + * the source repository mechanism. + * The returned paths are for the specified stratum + * (see Location for a description of strata). + * In the reference implementation, for strata + * which do not explicitly specify source path + * (the Java programming language stratum never does), + * the returned strings are the sourceNames(String) prefixed by + * the package name of this ReferenceType converted to + * a platform dependent path. For example, on a Windows platform, + * java.lang.Thread would return a List containing one element: + * "java\lang\Thread.java". + * Parameters: stratum - The stratum to retrieve information from or + * null for the declaring type's default stratum. + * Returns: a List of String objects each representing a source path + * Throws: AbsentInformationException - + * if the source names are not known. + * For arrays (ArrayType) and primitive classes, + * AbsentInformationException is always thrown. + * The case for testing debuggee's sourcecode file with a predefined name + * and a predefined package name. + * The test works as follows: + * The debugger program - nsk.jdi.ReferenceType.sourcePaths.sourcepaths001; + * the debuggee program - nsk.jdi.ReferenceType.sourcePaths.sourcepaths001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.sourcePaths.sourcepaths001 + * nsk.jdi.ReferenceType.sourcePaths.sourcepaths001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.sourcePaths.sourcepaths001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001a.java new file mode 100644 index 00000000000..074b833f3e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ReferenceType.sourcePaths; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the sourcepaths001 JDI test. + */ + +public class sourcepaths001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; icom.sun.jdi.ReferenceType.sourcePaths() + * properly throws AbsentInformationException - if the source + * paths are not known.

    + * + * The test exercises the following assertion:
    + * "For arrays (ArrayType) and primitive classes, + * AbsentInformationException is always thrown".
    + * Debugger part attempts to get paths to the sources corresponding + * to the declaration types of several debuggee fields, which are:
    + * primitive classes themselves, and arrays of primitive types and classes. + */ +public class sourcepaths002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.sourcePaths.sourcepaths002t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 24; + // tested fields used to provoke the exception + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new sourcepaths002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "sourcepaths002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; ivisibleFields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibfield001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleFields.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "visibfield001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "visibfield001aClassForCheck"; + private final static String not_visible_sign = "NOT VISIBLE"; + private final static String passed_sign = "PASSED"; + private static String fields_for_check[][] = { + +// field name type name static check result + {"s_boolean_field", "boolean", " static", not_visible_sign }, + {"s_byte_field", "byte", " static", not_visible_sign }, + {"s_char_field", "char", " static", not_visible_sign }, + {"s_double_field", "double", " static", not_visible_sign }, + {"s_float_field", "float", " static", not_visible_sign }, + {"s_int_field", "int", " static", not_visible_sign }, + {"s_long_field", "long", " static", not_visible_sign }, + {"s_object_field", "java.lang.Object", " static", not_visible_sign }, + {"s_prim_array_field", "long[]", " static", not_visible_sign }, + {"s_ref_array_field", "java.lang.Object[]", " static", not_visible_sign }, + {"i_boolean_field", "boolean", "", not_visible_sign }, + {"i_byte_field", "byte", "", not_visible_sign }, + {"i_char_field", "char", "", not_visible_sign }, + {"i_double_field", "double", "", not_visible_sign }, + {"i_float_field", "float", "", not_visible_sign }, + {"i_int_field", "int", "", not_visible_sign }, + {"i_long_field", "long", "", not_visible_sign }, + {"i_object_field", "java.lang.Object", "", not_visible_sign }, + {"i_prim_array_field", "long[]", "", not_visible_sign }, + {"i_ref_array_field", "java.lang.Object[]", "", not_visible_sign }, + {"s_super_hidden_prim_field", "int", " static", not_visible_sign }, + {"s_super_hidden_ref_field", "java.lang.Class", " static", not_visible_sign }, + {"i_super_hidden_prim_field", "int", " static", not_visible_sign }, + {"i_super_hidden_ref_field", "java.lang.Class", " static", not_visible_sign }, + {"s_interf_hidden_prim_field", "int", " static", not_visible_sign }, + {"s_interf_hidden_ref_field", "java.lang.Class", " static", not_visible_sign }, + {"s_super_boolean_field", "boolean", " static", not_visible_sign }, + {"s_super_byte_field", "byte", " static", not_visible_sign }, + {"s_super_char_field", "char", " static", not_visible_sign }, + {"s_super_double_field", "double", " static", not_visible_sign }, + {"s_super_float_field", "float", " static", not_visible_sign }, + {"s_super_int_field", "int", " static", not_visible_sign }, + {"s_super_long_field", "long", " static", not_visible_sign }, + {"s_super_object_field", "java.lang.Object", " static", not_visible_sign }, + {"i_super_boolean_field", "boolean", "", not_visible_sign }, + {"i_super_byte_field", "byte", "", not_visible_sign }, + {"i_super_char_field", "char", "", not_visible_sign }, + {"i_super_double_field", "double", "", not_visible_sign }, + {"i_super_float_field", "float", "", not_visible_sign }, + {"i_super_int_field", "int", "", not_visible_sign }, + {"i_super_long_field", "long", "", not_visible_sign }, + {"i_super_object_field", "java.lang.Object", "", not_visible_sign }, + {"s_interf_boolean_field", "boolean", " static", not_visible_sign }, + {"s_interf_byte_field", "byte", " static", not_visible_sign }, + {"s_interf_char_field", "char", " static", not_visible_sign }, + {"s_interf_double_field", "double", " static", not_visible_sign }, + {"s_interf_float_field", "float", " static", not_visible_sign }, + {"s_interf_int_field", "int", " static", not_visible_sign }, + {"s_interf_long_field", "long", " static", not_visible_sign }, + {"s_interf_object_field", "java.lang.Object", " static", not_visible_sign } + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibfield001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleFields/visibfield001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleFields/visibfield001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/visibleFields/visibfield001 test LOG:"); + out_stream.println("==> test checks visibleFields() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibfield001: visibfield001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> visibfield001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> visibfield001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibfield001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> visibfield001: check ReferenceType.visibleFields() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean visibleFields_method_error = false; + int fields_for_check_number = fields_for_check.length; + int not_visible_fields_number = 0; + int visible_fields_number = 0; + int unexpected_visible_fields_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> visibfield001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List visible_fields_list = null; + try { + visible_fields_list = refType.visibleFields(); + } + catch (Throwable thrown) { + out_stream.println("##> visibfield001: FAILED: ReferenceType.visibleFields() throws unexpected " + + thrown); + visibleFields_method_error = true; + break; + } + visible_fields_number = visible_fields_list.size(); + Field visible_fields[] = new Field[visible_fields_number]; + String unexpected_visible_fields[] = new String[visible_fields_number]; + visible_fields_list.toArray(visible_fields); + for (int i=0; i visibfield001: FAILED: field is NOT visible: " + current_field_for_check); + not_visible_fields_number++; + } + else { + print_log_on_verbose + ("--> visibfield001: PASSED for field: " + current_field_for_check); + } + } + for (int i=0; i visibfield001: FAILED: unexpected visible field: " + unexpected_visible_fields[i]); + } + break; + } + + out_stream.println("--> visibfield001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleFields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println("--> visibfield001: expected visible fields number = " + fields_for_check_number); + out_stream.println("--> visibfield001: in fact visible fields number = " + visible_fields_number); + out_stream.println("--> visibfield001: expected and in fact visible fields number = " + + (fields_for_check_number - not_visible_fields_number)); + out_stream.println + ("##> visibfield001: NOT visible fields number = " + not_visible_fields_number); + out_stream.println + ("##> visibfield001: UNEXPECTED visible fields number = " + unexpected_visible_fields_number); + } + if ( not_visible_fields_number + unexpected_visible_fields_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> visibfield001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> visibfield001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibfield001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001/TestDescription.java new file mode 100644 index 00000000000..8c80682a2a1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleFields/visibfield001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleFields/visibfield001 test + * checks the visibleFields() method of ReferenceType interface + * of the com.sun.jdi package : + * the ReferenceType.visibleFields() method is checked for fields of + * debugee's class which extends super class and implements interface. + * Debugee's class has both hidden and ambiguous fields which should + * be not visible. + * Each visible field is checked for field name, field type and + * static modifier. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleFields.visibfield001 + * nsk.jdi.ReferenceType.visibleFields.visibfield001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleFields.visibfield001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001a.java new file mode 100644 index 00000000000..208a73ad90a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield001a.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the visibfield001 JDI test. + */ + +public class visibfield001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i visibfield001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + visibfield001aClassForCheck class_for_check = new visibfield001aClassForCheck(); + + print_log_on_verbose("**> visibfield001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibfield001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibfield001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> visibfield001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> visibfield001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class visibfield001aClassForCheck extends visibfield001aSuperClassForCheck + implements visibfield001aInterfaceForCheck { + + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + static long[] s_prim_array_field; + static Object[] s_ref_array_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + long[] i_prim_array_field; + Object[] i_ref_array_field; + + static int s_super_hidden_prim_field; + static Class s_super_hidden_ref_field; + + static int i_super_hidden_prim_field; + static Class i_super_hidden_ref_field; + + static int s_interf_hidden_prim_field; + static Class s_interf_hidden_ref_field; + +} + +class visibfield001aSuperClassForCheck { + + static boolean s_super_boolean_field; + static byte s_super_byte_field; + static char s_super_char_field; + static double s_super_double_field; + static float s_super_float_field; + static int s_super_int_field; + static long s_super_long_field; + static Object s_super_object_field; + + static long s_super_hidden_prim_field; + static Object s_super_hidden_ref_field; + + boolean i_super_boolean_field; + byte i_super_byte_field; + char i_super_char_field; + double i_super_double_field; + float i_super_float_field; + int i_super_int_field; + long i_super_long_field; + Object i_super_object_field; + + long i_super_hidden_prim_field; + Object i_super_hidden_ref_field; + + int ambiguous_prim_field; + Class ambiguous_ref_field; + +} + +interface visibfield001aInterfaceForCheck { + + static final boolean s_interf_boolean_field = true; + static final byte s_interf_byte_field = (byte)1; + static final char s_interf_char_field = '1'; + static final double s_interf_double_field = 999; + static final float s_interf_float_field = 99; + static final int s_interf_int_field = 100; + static final long s_interf_long_field = 1000; + static final Object s_interf_object_field = new Object(); + + static final long s_interf_hidden_prim_field = 1; + static final Object s_interf_hidden_ref_field = new Object(); + + static final long ambiguous_prim_field = 1; + static final Object ambiguous_ref_field = new Object(); + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002.java new file mode 100644 index 00000000000..d001e50c141 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method visibleFields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibfield002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleFields.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "visibfield002", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "visibfield002aClassForCheck"; + + private final static String classLoaderName = package_prefix + "visibfield002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibfield002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ReferenceType/visibleFields/visibfield002 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ReferenceType/visibleFields/visibfield002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + private void print_log_anyway(String message) { + logHandler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + Debugee debugee; + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + print_log_on_verbose("==> nsk/jdi/ReferenceType/visibleFields/visibfield002 test LOG:"); + print_log_on_verbose("==> test checks visibleFields() method of ReferenceType interface "); + print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibfield002: visibfield002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> visibfield002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> visibfield002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibfield002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> visibfield002: check ReferenceType.visibleFields() method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean visibleFields_method_error = false; + + while ( true ) { // test body + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> visibfield002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> visibfield002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + List visible_fields_list = null; + try { + visible_fields_list = refType.visibleFields(); + print_log_anyway + ("##> visibfield002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + visibleFields_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> visibfield002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> visibfield002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + visibleFields_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleFields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> visibfield002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> visibfield002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibfield002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/TestDescription.java new file mode 100644 index 00000000000..14e44821539 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleFields/visibfield002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleFields/visibfield002 test + * checks the visibleFields() method of ReferenceType interface + * of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.visibleFields() method is called for + * this class - ClassNotPreparedException should be thrown + * in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "out_stream.println" are replaced with + * "print_log_on_verbose" and "print_log_anyway". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleFields.visibfield002 + * nsk.jdi.ReferenceType.visibleFields.visibfield002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleFields.visibfield002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/loadclass/visibfield002aClassForCheck.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/loadclass/visibfield002aClassForCheck.java new file mode 100644 index 00000000000..574d2b694bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002/loadclass/visibfield002aClassForCheck.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +/** + * This class is loaded by visibfield002aClassLoader . + */ + +class visibfield002aClassForCheck { + + // static fields + static boolean s_boolean_field; + static byte s_byte_field; + static char s_char_field; + static double s_double_field; + static float s_float_field; + static int s_int_field; + static long s_long_field; + static Object s_object_field; + + // instance fields + boolean i_boolean_field; + byte i_byte_field; + char i_char_field; + double i_double_field; + float i_float_field; + int i_int_field; + long i_long_field; + Object i_object_field; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002a.java new file mode 100644 index 00000000000..b8b7ac9f591 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield002a.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + + +/** + * This class is used as debugee application for the visibfield002 JDI test. + */ + +public class visibfield002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleFields."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "visibfield002aClassForCheck"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i visibfield002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + visibfield002aClassLoader customClassLoader = new visibfield002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> visibfield002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> visibfield002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> visibfield002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibfield002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibfield002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> visibfield002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> visibfield002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class visibfield002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public visibfield002aClassLoader(String classPath, String className) { + super(visibfield002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003.java new file mode 100644 index 00000000000..8c452d84e89 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method visibleFields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibfield003 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleFields.", + thisClassName = package_prefix + "visibfield003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "visibfield003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibfield003().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/visibleFields/visibfield003 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/visibleFields/visibfield003 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + private static void print_log_without_verbose(String message) { + if ( ! verbose_mode ) { + out_stream.println(message); + } + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/visibleFields/visibfield003 test LOG:"); + out_stream.println("--> test checks visibleFields() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for UNLOADED class\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + argv = argHandler.getArguments(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibfield003: visibfield003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> visibfield003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + out_stream.println + ("##> visibfield003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibfield003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> visibfield003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + out_stream.println + ("##> visibfield003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibfield003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean visibleFields_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> visibfield003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> visibfield003: getting ReferenceType object for loaded checked class..."); + out_stream.println("##> visibfield003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> visibfield003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> visibfield003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> visibfield003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + out_stream.println + ("--> visibfield003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + out_stream.println + ("--> ReferenceType.visibleFields() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + out_stream.println + ("##> visibfield003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibfield003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> visibfield003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> visibfield003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> visibfield003: check that checked class has been unloaded realy..."); + out_stream.println + ("--> visibfield003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + out_stream.println + ("--> ReferenceType.visibleFields() method can NOT be checked!"); + break; + } + + out_stream.println + ("--> visibfield003: check ReferenceType.visibleFields() method for unloaded class..."); + List visible_fields_list = null; + try { + visible_fields_list = refType.visibleFields(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + out_stream.println + ("--> visibfield003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + out_stream.println + ("##> visibfield003: FAILED: unexpected Exception thrown - " + expt.toString()); + out_stream.println + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + visibleFields_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleFields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> visibfield003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> visibfield003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibfield003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of visibfield003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TestDescription.java new file mode 100644 index 00000000000..95b570009e9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleFields/visibfield003. + * VM Testbase keywords: [jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleFields/visibfield003 test + * checks the visibleFields() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * visibleFields() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - visibfield003b class was moved in 'loadclass' subdirectory; + * - package name was added in visibfield003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for visibfield003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleFields.visibfield003 + * nsk.jdi.ReferenceType.visibleFields.visibfield003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleFields.visibfield003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/loadclass/visibfield003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/loadclass/visibfield003b.java new file mode 100644 index 00000000000..ccbdfcf8dfd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003/loadclass/visibfield003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the visibleFields() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.visibleFields; + +class visibfield003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003a.java new file mode 100644 index 00000000000..56be764f85b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the visibfield003 JDI test. + */ + +public class visibfield003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.visibleFields."; + private final static String checked_class_name = package_prefix + "visibfield003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> visibfield003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> visibfield003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> visibfield003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> visibfield003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> visibfield003a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> visibfield003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibfield003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibfield003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> visibfield003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> visibfield003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> visibfield003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> visibfield003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> visibfield003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> visibfield003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> visibfield003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibfield003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibfield003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> visibfield003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> visibfield003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of visibfield003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004.java new file mode 100644 index 00000000000..7c9b4e7c34d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method visibleFields() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibfield004 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleFields.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "visibfield004", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "visibfield004aClassForCheck"; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibfield004().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleFields/visibfield004 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleFields/visibfield004 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/visibleFields/visibfield004 test LOG:"); + out_stream.println("==> test checks visibleFields() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for class without visible fields\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibfield004: visibfield004a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> visibfield004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> visibfield004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibfield004: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> visibfield004: check ReferenceType.visibleFields() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean visibleFields_method_error = false; + int visible_fields_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> visibfield004: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List visible_fields_list = null; + try { + visible_fields_list = refType.visibleFields(); + } + catch (Throwable thrown) { + out_stream.println("##> visibfield004: FAILED: ReferenceType.visibleFields() throws unexpected " + + thrown); + visibleFields_method_error = true; + break; + } + visible_fields_number = visible_fields_list.size(); + if ( visible_fields_number == 0 ) { + break; + } + Field visible_fields[] = new Field[visible_fields_number]; + visible_fields_list.toArray(visible_fields); + for (int i=0; i visibfield004: FAILED: unexpected visible field: " + full_checked_field); + } + break; + } + + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleFields_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + if ( visible_fields_number > 0 ) { + out_stream.println + ("##> visibfield004: UNEXPECTED visible fields number = " + visible_fields_number); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println + ("--> visibfield004: PASSED: returned list of fields is empty!"); + } + + print_log_on_verbose("--> visibfield004: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> visibfield004: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibfield004: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004/TestDescription.java new file mode 100644 index 00000000000..af1420fb44f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleFields/visibfield004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleFields/visibfield004 test + * checks the visibleFields() method of ReferenceType interface + * of the com.sun.jdi package for class without visible fields: + * the ReferenceType.visibleFields() method is checked for fields of + * debugee's class which extends super class and implements interface. + * Debugee's class has only ambiguous fields which should + * be not visible. + * The test expects the returned list of fields to be empty. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleFields.visibfield004 + * nsk.jdi.ReferenceType.visibleFields.visibfield004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleFields.visibfield004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004a.java new file mode 100644 index 00000000000..acca91d0c43 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield004a.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the visibfield004 JDI test. + */ + +public class visibfield004a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i visibfield004a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + visibfield004aClassForCheck class_for_check = new visibfield004aClassForCheck(); + + print_log_on_verbose("**> visibfield004a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibfield004a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibfield004a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("##> visibfield004a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("##> visibfield004a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class visibfield004aClassForCheck extends visibfield004aSuperClassForCheck + implements visibfield004aInterfaceForCheck {} + +class visibfield004aSuperClassForCheck { + + int ambiguous_prim_field; + Class ambiguous_ref_field; + +} + +interface visibfield004aInterfaceForCheck { + + static final long ambiguous_prim_field = 1; + static final Object ambiguous_ref_field = new Object(); + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005.java new file mode 100644 index 00000000000..f13995bd242 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.visibleFields() + * properly returns an empty field list for arrays (ArrayType) and primitive + * classes.

    + * + * Debugger part of it attempts to get a list of visible fields in several + * reference types corresponding to debuggee field values, which themselves + * are:
    + * primitive classes, and arrays of primitive types and classes. + */ +public class visibfield005 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.visibleFields.visibfield005t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 24; + // tested fields used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new visibfield005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "visibfield005t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + // check there are enum constant fields + List l = checkedClass.visibleFields(); + if (l.isEmpty()) { + complain("\t ReferenceType.visibleFields() returned empty list for type: " + className); + exitStatus = Consts.TEST_FAILED; + } else { + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + boolean hasField = false; + + Iterator it = l.iterator(); + while (it.hasNext()) { + Field checkedField = it.next(); + if (expectedEnumFieldsNames[i].equals(checkedField.name()) && + checkedField.type().equals(checkedClass) ) + + hasField = true; + } + if (hasField) { + display("enum " + className + " has field " + expectedEnumFieldsNames[i]); + display("\t of type " + className); + } else { + complain("enum " + className + " does not have field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } + // check that ambiguous field in not returned + Iterator it = l.iterator(); + while (it.hasNext()) { + Field field = it.next(); + if (field.name().equals("i1")) { + complain("enum " + className + " has ambigous field i1 "); + exitStatus = Consts.TEST_FAILED; + } + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006/TestDescription.java new file mode 100644 index 00000000000..66fd45ba19c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleFields/visibfield006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for visibleFields() method of ReferenceType interface. + * The test checks if the method returns all enum constants + * declared in mirrored enum type and does not return any + * ambiguous inherited field. + * The test consists of a debugger program (visibfield006.java) + * and debuggee application (visibfield006a.java). + * Package name is nsk.jdi.ReferenceType.visibleFields . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls visibleFields() method for each field + * of enum type declared in visibfield006a class. Every of these + * enum types has the same enum constants, i.e fields: e1 and e2, + * which must be included in result list. Some of checked enum + * types implement visibfield006i1 and visibfield006i2 interfaces. + * These interfaces have int field of same name i1. These fields + * are ambigous in enum types and should not be returned by + * visibleFields() method. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleFields.visibfield006 + * nsk.jdi.ReferenceType.visibleFields.visibfield006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleFields.visibfield006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006a.java new file mode 100644 index 00000000000..cf14b56585c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield006a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.visibleFields; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class visibfield006a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static visibfield006Enum1 f1 = visibfield006Enum1.e2; + static visibfield006Enum2 f2 = visibfield006Enum2.e1; + static visibfield006Enum1.Enum1_ f3 = visibfield006Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(visibfield006.SIGNAL_READY); + receiveSignal(visibfield006.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum visibfield006Enum1 implements visibfield006i1, visibfield006i2 { + e1, e2; + + enum Enum1_ implements visibfield006i1, visibfield006i2 { + e1, e2; + } +} + +enum visibfield006Enum2 implements visibfield006i1, visibfield006i2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} + +interface visibfield006i1 { + public final int i1 = 1; +} + +interface visibfield006i2 { + public final int i1 = 1; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001.java new file mode 100644 index 00000000000..e4912181f04 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001.java @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method visibleMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibmethod001 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleMethods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "visibmethod001", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "visibmethod001aClassForCheck"; + private final static String super_class_for_check = package_prefix + "visibmethod001aSuperClassForCheck"; + private final static String interface_for_check = package_prefix + "visibmethod001aInterfaceForCheck"; + private final static String not_visible_sign = "NOT VISIBLE"; + private final static String passed_sign = "PASSED"; + private final static String Object_class_name = "java.lang.Object"; + private static String methods_for_check[][] = { + +// method name declaring class check result + + {"", class_for_check, not_visible_sign}, + {"ClassForCheck", class_for_check, not_visible_sign}, + {"s_void_method", class_for_check, not_visible_sign}, + {"s_boolean_method", class_for_check, not_visible_sign}, + {"s_byte_method", class_for_check, not_visible_sign}, + {"s_char_method", class_for_check, not_visible_sign}, + {"s_double_method", class_for_check, not_visible_sign}, + {"s_float_method", class_for_check, not_visible_sign}, + {"s_int_method", class_for_check, not_visible_sign}, + {"s_long_method", class_for_check, not_visible_sign}, + {"s_string_method", class_for_check, not_visible_sign}, + {"s_object_method", class_for_check, not_visible_sign}, + {"s_prim_array_method", class_for_check, not_visible_sign}, + {"s_ref_array_method", class_for_check, not_visible_sign}, + {"s_super_hidden_void_method", class_for_check, not_visible_sign}, + {"s_super_hidden_prim_method", class_for_check, not_visible_sign}, + {"s_super_hidden_ref_method", class_for_check, not_visible_sign}, + {"s_void_par_method", class_for_check, not_visible_sign}, + {"s_boolean_par_method", class_for_check, not_visible_sign}, + {"s_byte_par_method", class_for_check, not_visible_sign}, + {"s_char_par_method", class_for_check, not_visible_sign}, + {"s_double_par_method", class_for_check, not_visible_sign}, + {"s_float_par_method", class_for_check, not_visible_sign}, + {"s_int_par_method", class_for_check, not_visible_sign}, + {"s_long_par_method", class_for_check, not_visible_sign}, + {"s_string_par_method", class_for_check, not_visible_sign}, + {"s_object_par_method", class_for_check, not_visible_sign}, + {"s_prim_array_par_method", class_for_check, not_visible_sign}, + {"s_ref_array_par_method", class_for_check, not_visible_sign}, + {"s_super_hidden_void_par_method", class_for_check, not_visible_sign}, + {"s_super_hidden_prim_par_method", class_for_check, not_visible_sign}, + {"s_super_hidden_ref_par_method", class_for_check, not_visible_sign}, + {"s_native_method", class_for_check, not_visible_sign}, + {"s_synchr_method", class_for_check, not_visible_sign}, + {"s_final_method", class_for_check, not_visible_sign}, + {"s_private_method", class_for_check, not_visible_sign}, + {"s_protected_method", class_for_check, not_visible_sign}, + {"s_public_method", class_for_check, not_visible_sign}, + {"i_void_method", class_for_check, not_visible_sign}, + {"i_boolean_method", class_for_check, not_visible_sign}, + {"i_byte_method", class_for_check, not_visible_sign}, + {"i_char_method", class_for_check, not_visible_sign}, + {"i_double_method", class_for_check, not_visible_sign}, + {"i_float_method", class_for_check, not_visible_sign}, + {"i_int_method", class_for_check, not_visible_sign}, + {"i_long_method", class_for_check, not_visible_sign}, + {"i_string_method", class_for_check, not_visible_sign}, + {"i_object_method", class_for_check, not_visible_sign}, + {"i_prim_array_method", class_for_check, not_visible_sign}, + {"i_ref_array_method", class_for_check, not_visible_sign}, + {"i_super_overridden_void_method", class_for_check, not_visible_sign}, + {"i_super_overridden_prim_method", class_for_check, not_visible_sign}, + {"i_super_overridden_ref_method", class_for_check, not_visible_sign}, + {"i_interf_overridden_void_method", class_for_check, not_visible_sign}, + {"i_interf_overridden_prim_method", class_for_check, not_visible_sign}, + {"i_interf_overridden_ref_method", class_for_check, not_visible_sign}, + {"i_void_par_method", class_for_check, not_visible_sign}, + {"i_boolean_par_method", class_for_check, not_visible_sign}, + {"i_byte_par_method", class_for_check, not_visible_sign}, + {"i_char_par_method", class_for_check, not_visible_sign}, + {"i_double_par_method", class_for_check, not_visible_sign}, + {"i_float_par_method", class_for_check, not_visible_sign}, + {"i_int_par_method", class_for_check, not_visible_sign}, + {"i_long_par_method", class_for_check, not_visible_sign}, + {"i_string_par_method", class_for_check, not_visible_sign}, + {"i_object_par_method", class_for_check, not_visible_sign}, + {"i_prim_array_par_method", class_for_check, not_visible_sign}, + {"i_ref_array_par_method", class_for_check, not_visible_sign}, + {"i_super_overridden_void_par_method", class_for_check, not_visible_sign}, + {"i_super_overridden_prim_par_method", class_for_check, not_visible_sign}, + {"i_super_overridden_ref_par_method", class_for_check, not_visible_sign}, + {"i_interf_overridden_void_par_method", class_for_check, not_visible_sign}, + {"i_interf_overridden_prim_par_method", class_for_check, not_visible_sign}, + {"i_interf_overridden_ref_par_method", class_for_check, not_visible_sign}, + {"i_abstract_method", class_for_check, not_visible_sign}, + {"i_native_method", class_for_check, not_visible_sign}, + {"i_synchr_method", class_for_check, not_visible_sign}, + {"i_final_method", class_for_check, not_visible_sign}, + {"i_private_method", class_for_check, not_visible_sign}, + {"i_protected_method", class_for_check, not_visible_sign}, + {"i_public_method", class_for_check, not_visible_sign}, + {"", class_for_check, not_visible_sign}, + {"s_super_void_method", super_class_for_check, not_visible_sign}, + {"s_super_prim_method", super_class_for_check, not_visible_sign}, + {"s_super_ref_method", super_class_for_check, not_visible_sign}, + {"i_super_void_method", super_class_for_check, not_visible_sign}, + {"i_super_prim_method", super_class_for_check, not_visible_sign}, + {"i_super_ref_method", super_class_for_check, not_visible_sign}, + {"i_multiple_inherited_method", super_class_for_check, not_visible_sign}, + {"i_interf_ref_method", interface_for_check, not_visible_sign}, + {"i_interf_prim_method", interface_for_check, not_visible_sign}, + {"i_interf_void_method", interface_for_check, not_visible_sign} + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibmethod001().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod001 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod001 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/visibleMethods/visibmethod001 test LOG:"); + out_stream.println("==> test checks visibleMethods() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibmethod001: visibmethod001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> visibmethod001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> visibmethod001: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibmethod001: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> visibmethod001: check ReferenceType.visibleMethods() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean visibleMethods_method_error = false; + int methods_for_check_number = methods_for_check.length; + int not_visible_methods_number = 0; + int visible_methods_number = 0; + int unexpected_visible_methods_number = 0; + int disregarded_visible_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> visibmethod001: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List visible_methods_list = null; + try { + visible_methods_list = refType.visibleMethods(); + } + catch (Throwable thrown) { + out_stream.println("##> visibmethod001: FAILED: ReferenceType.visibleMethods() throws unexpected " + + thrown); + visibleMethods_method_error = true; + break; + } + visible_methods_number = visible_methods_list.size(); + Method visible_methods[] = new Method[visible_methods_number]; + String unexpected_visible_methods[] = new String[visible_methods_number]; + visible_methods_list.toArray(visible_methods); + for (int i=0; i visibmethod001: FAILED: method is NOT visible: " + current_method_for_check); + not_visible_methods_number++; + } + else { + print_log_on_verbose + ("--> visibmethod001: PASSED for method: " + current_method_for_check); + } + } + for (int i=0; i visibmethod001: FAILED: unexpected visible method: " + unexpected_visible_methods[i]); + } + break; + } + + out_stream.println("--> visibmethod001: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println("--> visibmethod001: expected visible methods number = " + methods_for_check_number); + out_stream.println("--> visibmethod001: in fact visible methods number = " + + (visible_methods_number - disregarded_visible_methods_number)); + out_stream.println("--> visibmethod001: expected and in fact visible methods number = " + + (methods_for_check_number - not_visible_methods_number)); + out_stream.println + ("##> visibmethod001: NOT visible methods number = " + not_visible_methods_number); + out_stream.println + ("##> visibmethod001: UNEXPECTED visible methods number = " + unexpected_visible_methods_number); + } + if ( not_visible_methods_number + unexpected_visible_methods_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> visibmethod001: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> visibmethod001: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibmethod001: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001/TestDescription.java new file mode 100644 index 00000000000..8cc73d470a4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleMethods/visibmethod001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleMethods/visibmethod001 test + * checks the visibleMethods() method of ReferenceType interface + * of the com.sun.jdi package : + * the ReferenceType.visibleMethods() method is checked for methods of + * debugee's class which extends super class and implements interface. + * Debugee's class has both hidden and overridden methods which should + * be not visible. + * Each visible method is checked for method name and declaring class name. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleMethods.visibmethod001 + * nsk.jdi.ReferenceType.visibleMethods.visibmethod001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleMethods.visibmethod001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001a.java new file mode 100644 index 00000000000..723b65577c7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod001a.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the visibmethod001 JDI test. + */ + +public class visibmethod001a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleMethods."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "visibmethod001aClassForCheck"; + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i visibmethod001a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + Class checked_class_classobj = null; + try { + checked_class_classobj = + Class.forName(checked_class_name, true, visibmethod001a.class.getClassLoader()); + print_log_on_verbose + ("--> visibmethod001a: checked class loaded:" + checked_class_name); + } + catch ( Throwable thrown ) { // ClassNotFoundException +// System.err.println +// ("**> visibmethod001a: load class: Throwable thrown = " + thrown.toString()); + print_log_on_verbose + ("--> visibmethod001a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> visibmethod001a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibmethod001a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibmethod001a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> visibmethod001a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> visibmethod001a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +abstract class visibmethod001aClassForCheck extends visibmethod001aSuperClassForCheck + implements visibmethod001aInterfaceForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods without params + static void s_void_method() {} + static boolean s_boolean_method() {return true;} + static byte s_byte_method() {return (byte)1;} + static char s_char_method() {return (char)1;} + static double s_double_method() {return (double)100.99;} + static float s_float_method() {return (float)100.88;} + static int s_int_method() {return 100;} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + // static methods with params + static void s_void_par_method(boolean z) {} + static boolean s_boolean_par_method(boolean z) {return true;} + static byte s_byte_par_method(byte b) {return (byte)1;} + static char s_char_par_method(char ch) {return (char)1;} + static double s_double_par_method(double d) {return (double)100.99;} + static float s_float_par_method(float f) {return (float)100.88;} + static int s_int_par_method(int i) {return 100;} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + // other static methods + native static Object s_native_method(Object obj); + static synchronized Object s_synchr_method(Object obj) {return new Object();} + final static Object s_final_method(Object obj) {return new Object();} + private static Object s_private_method(Object obj) {return new Object();} + protected static Object s_protected_method(Object obj) {return new Object();} + public static Object s_public_method(Object obj) {return new Object();} + + // instance methods without params + void i_void_method() {} + boolean i_boolean_method() {return true;} + byte i_byte_method() {return (byte)1;} + char i_char_method() {return (char)1;} + double i_double_method() {return (double)100.99;} + float i_float_method() {return (float)100.88;} + int i_int_method() {return 100;} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + public void i_interf_overridden_void_method() {} + public int i_interf_overridden_prim_method() {return 100;} + public Object i_interf_overridden_ref_method() {return new Object();} + + // instance methods with params + void i_void_par_method(boolean z) {} + boolean i_boolean_par_method(boolean z) {return true;} + byte i_byte_par_method(byte b) {return (byte)1;} + char i_char_par_method(char ch) {return (char)1;} + double i_double_par_method(double d) {return (double)100.99;} + float i_float_par_method(float f) {return (float)100.88;} + int i_int_par_method(int i) {return 100;} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public void i_interf_overridden_void_par_method(int i) {} + public int i_interf_overridden_prim_par_method(int i) {return 100;} + public Object i_interf_overridden_ref_par_method(Object obj) {return new Object();} + + // other instance methods + abstract Object i_abstract_method(Object obj); + native Object i_native_method(Object obj); + synchronized Object i_synchr_method(Object obj) {return new Object();} + final Object i_final_method(Object obj) {return new Object();} + private Object i_private_method(Object obj) {return new Object();} + protected Object i_protected_method(Object obj) {return new Object();} + public Object i_public_method(Object obj) {return new Object();} + + // static initializer + static {} + + +} + +abstract class visibmethod001aSuperClassForCheck { + + static void s_super_void_method(long l) {} + static long s_super_prim_method(long l) {return 100;} + static Object s_super_ref_method(Object obj) {return new Object();} + + void i_super_void_method(long l) {} + long i_super_prim_method(long l) {return 100;} + Object i_super_ref_method(Object obj) {return new Object();} + + static void s_super_hidden_void_method() {} + static int s_super_hidden_prim_method() {return 100;} + static Object s_super_hidden_ref_method() {return new Object();} + + static void s_super_hidden_void_par_method(int i) {} + static int s_super_hidden_prim_par_method(int i) {return 100;} + static Object s_super_hidden_ref_par_method(Object obj) {return new Object();} + + void i_super_overridden_void_method() {} + int i_super_overridden_prim_method() {return 100;} + Object i_super_overridden_ref_method() {return new Object();} + + void i_super_overridden_void_par_method(int i) {} + int i_super_overridden_prim_par_method(int i) {return 100;} + Object i_super_overridden_ref_par_method(Object obj) {return new Object();} + + public Object i_multiple_inherited_method(Object obj) {return new Object();} + +} + +interface visibmethod001aInterfaceForCheck { + + void i_interf_void_method(long l); + long i_interf_prim_method(long l); + Object i_interf_ref_method(Object obj); + + void i_interf_overridden_void_method(); + int i_interf_overridden_prim_method(); + Object i_interf_overridden_ref_method(); + + void i_interf_overridden_void_par_method(int i); + int i_interf_overridden_prim_par_method(int i); + Object i_interf_overridden_ref_par_method(Object obj); + + public Object i_multiple_inherited_method(Object obj); + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002.java new file mode 100644 index 00000000000..4bddea133c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method visibleMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibmethod002 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleMethods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "visibmethod002", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "visibmethod002aClassForCheck"; + + private final static String classLoaderName = package_prefix + "visibmethod002aClassLoader"; + private final static String classFieldName = "loadedClass"; + + static ArgumentHandler argsHandler; + private static Log logHandler; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibmethod002().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + logHandler.complain("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod002 test FAILED"); + } + else { + logHandler.display("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod002 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + logHandler.display(message); + } + + private void print_log_anyway(String message) { + logHandler.complain(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + Debugee debugee; + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); + } else { + debugee = binder.bindToDebugee(debugeeName); + } + + print_log_on_verbose("==> nsk/jdi/ReferenceType/visibleMethods/visibmethod002 test LOG:"); + print_log_on_verbose("==> test checks visibleMethods() method of ReferenceType interface "); + print_log_on_verbose(" of the com.sun.jdi package for not prepared class\n"); + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibmethod002: visibmethod002a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + print_log_anyway + ("##> visibmethod002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + print_log_anyway + ("##> visibmethod002: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibmethod002: debugee's \"ready\" signal recieved!"); + } + + print_log_on_verbose + ("--> visibmethod002: check ReferenceType.visibleMethods() method for not prepared " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean visibleMethods_method_error = false; + + while ( true ) { // test body + ReferenceType loaderRefType = debugee.classByName(classLoaderName); + if (loaderRefType == null) { + print_log_anyway("##> Could NOT FIND custom class loader: " + classLoaderName); + class_not_found_error = true; + break; + } + + Field classField = loaderRefType.fieldByName(classFieldName); + Value classValue = loaderRefType.getValue(classField); + + ClassObjectReference classObjRef = null; + try { + classObjRef = (ClassObjectReference)classValue; + } catch (Exception e) { + print_log_anyway ("##> Unexpected exception while getting ClassObjectReference : " + e); + class_not_found_error = true; + break; + } + + ReferenceType refType = classObjRef.reflectedType(); + boolean isPrep = refType.isPrepared(); + if (isPrep) { + print_log_anyway + ("##> visibmethod002: FAILED: isPrepared() returns for " + class_for_check + " : " + isPrep); + class_not_found_error = true; + break; + } else { + print_log_on_verbose + ("--> visibmethod002: isPrepared() returns for " + class_for_check + " : " + isPrep); + } + + List visible_methods_list = null; + try { + visible_methods_list = refType.visibleMethods(); + print_log_anyway + ("##> visibmethod002: FAILED: NO any Exception thrown!"); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + visibleMethods_method_error = true; + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ClassNotPreparedException) { + print_log_on_verbose + ("--> visibmethod002: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + print_log_anyway + ("##> visibmethod002: FAILED: unexpected Exception thrown - " + expt.toString()); + print_log_anyway + ("##> expected Exception - com.sun.jdi.ClassNotPreparedException"); + visibleMethods_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> visibmethod002: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + print_log_anyway + ("##> visibmethod002: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibmethod002: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/TestDescription.java new file mode 100644 index 00000000000..348df411f67 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleMethods/visibmethod002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleMethods/visibmethod002 test + * checks the visibleMethods() method of ReferenceType interface + * of the com.sun.jdi package for not prepared class: + * the checked class is loaded but is not prepared. + * The ReferenceType.visibleMethods() method is called for + * this class - ClassNotPreparedException should be thrown + * in this case. + * COMMENTS + * The test is updated as follows: + * - statements for establishing ArgumentHandler, LogHandler and Binder are updated + * to comply with new version of the shared classes; + * - a number of statements "out_stream.println" are replaced with + * "print_log_on_verbose" and "print_log_anyway". + * ------------------------------------------------------- + * 4477989 TEST_BUG: some nine ReferenceType tests use wrong assumption + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleMethods.visibmethod002 + * nsk.jdi.ReferenceType.visibleMethods.visibmethod002a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleMethods.visibmethod002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/loadclass/visibmethod002aClassForCheck.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/loadclass/visibmethod002aClassForCheck.java new file mode 100644 index 00000000000..9c0efc40787 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002/loadclass/visibmethod002aClassForCheck.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +/** + * This class is loaded by visibmethod002aClassLoader . + */ + +class visibmethod002aClassForCheck { + + // constructor + public void ClassForCheck() { + } + + // static methods + static void s_void_method() {} + static long s_long_method() {return 100;} + static String s_string_method() {return "return";} + static Object s_object_method() {return new Object();} + static long[] s_prim_array_method() {return new long[100];} + static Object[] s_ref_array_method() {return new Object[100];} + + static void s_void_par_method(boolean z) {} + static long s_long_par_method(long l) {return 100;} + static String s_string_par_method(String s) {return "return";} + static Object s_object_par_method(Object obj) {return new Object();} + static long[] s_prim_array_par_method(long[] la) {return new long[100];} + static Object[] s_ref_array_par_method(Object[] obja) {return new Object[100];} + + + // instance methods + void i_void_method() {} + long i_long_method() {return 100;} + String i_string_method() {return "return";} + Object i_object_method() {return new Object();} + long[] i_prim_array_method() {return new long[100];} + Object[] i_ref_array_method() {return new Object[100];} + + void i_void_par_method(boolean z) {} + long i_long_par_method(long l) {return 100;} + String i_string_par_method(String s) {return "return";} + Object i_object_par_method(Object obj) {return new Object();} + long[] i_prim_array_par_method(long[] la) {return new long[100];} + Object[] i_ref_array_par_method(Object[] obja) {return new Object[100];} + + // static initializer + static {} +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002a.java new file mode 100644 index 00000000000..4f219b75cf1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod002a.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.io.*; + + +/** + * This class is used as debugee application for the visibmethod002 JDI test. + */ + +public class visibmethod002a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleMethods."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "visibmethod002aClassForCheck"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i visibmethod002a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + visibmethod002aClassLoader customClassLoader = new visibmethod002aClassLoader(checked_class_dir, checked_class_name); + try { + customClassLoader.preloadClass(checked_class_name); + print_log_on_verbose + ("--> visibmethod002a: checked class loaded but not prepared: " + checked_class_name); + } catch (Throwable e) { // ClassNotFoundException + print_log_on_verbose + ("--> visibmethod002a: checked class NOT loaded: " + e); + } + + print_log_on_verbose("**> visibmethod002a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibmethod002a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibmethod002a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> visibmethod002a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> visibmethod002a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +/** + * Custom class loader to load class without preparation. + */ +class visibmethod002aClassLoader extends ClassLoader { + + private String classPath; + public static Class loadedClass; + + public visibmethod002aClassLoader(String classPath, String className) { + super(visibmethod002aClassLoader.class.getClassLoader()); + this.classPath = classPath; + } + + public void preloadClass (String className) throws ClassNotFoundException { + loadedClass = findClass(className); + } + + protected synchronized Class findClass(String className) throws ClassNotFoundException { + String classFileName = classPath + "/" + className.replace('.', '/') + ".class"; + + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + int len; + byte data[]; + try { + len = in.available(); + data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } + } + + return defineClass(className, data, 0, data.length); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003.java new file mode 100644 index 00000000000..70e68d57e34 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method visibleMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibmethod003 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to true + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleMethods.", + thisClassName = package_prefix + "visibmethod003", + debugeeName = thisClassName + "a"; + + /** Debugee's class for check **/ + private final static String checked_class = package_prefix + "visibmethod003b"; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibmethod003().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod003 test FAILED"); + } + else { + out_stream.println + ("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod003 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + private static void print_log_without_verbose(String message) { + if ( ! verbose_mode ) { + out_stream.println(message); + } + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/visibleMethods/visibmethod003 test LOG:"); + out_stream.println("--> test checks visibleMethods() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for UNLOADED class\n"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + argv = argHandler.getArguments(); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = debugee.createIOPipe(); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibmethod003: visibmethod003a debugee launched"); + debugee.resume(); + + String debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> visibmethod003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready0")) { + out_stream.println + ("##> visibmethod003: UNEXPECTED debugee's signal (not \"ready0\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibmethod003: debugee's \"ready0\" signal recieved!"); + } + + // pass to debugee checked_class_dir... + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> visibmethod003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if (!debugee_signal.equals("ready1")) { + out_stream.println + ("##> visibmethod003: UNEXPECTED debugee's signal (not \"ready1\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibmethod003: debugee's \"ready1\" signal recieved!"); + } + + boolean class_not_found_error = false; + boolean visibleMethods_method_error = false; + while ( true ) { + print_log_on_verbose + ("--> visibmethod003: getting ReferenceType object for loaded checked class..."); + ReferenceType refType = debugee.classByName(checked_class); + if (refType == null) { + print_log_without_verbose + ("--> visibmethod003: getting ReferenceType object for loaded checked class..."); + out_stream.println("##> visibmethod003: FAILED: Could NOT FIND checked class: " + checked_class); + class_not_found_error = true; + break; + } + else { + print_log_on_verbose("--> visibmethod003: checked class FOUND: " + checked_class); + } + print_log_on_verbose + ("--> visibmethod003: waiting for \"ready2\" or \"not_unloaded\" signal from debugee..."); + pipe.println("continue"); + debugee_signal = pipe.readln(); + if (debugee_signal == null) { + out_stream.println + ("##> visibmethod003: UNEXPECTED debugee's signal - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + if ( debugee_signal.equals("not_unloaded")) { + out_stream.println + ("--> visibmethod003: debugee's \"not_unloaded\" signal recieved!"); + print_log_without_verbose + ("--> checked class may be NOT unloaded!"); + out_stream.println + ("--> ReferenceType.visibleMethods() method can NOT be checked!"); + break; + } + if (!debugee_signal.equals("ready2")) { + out_stream.println + ("##> visibmethod003: UNEXPECTED debugee's signal (not \"ready2\") - " + debugee_signal); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibmethod003: debugee's \"ready2\" signal recieved!"); + } + print_log_on_verbose + ("--> visibmethod003: check that checked class has been unloaded realy..."); + ReferenceType refType2 = debugee.classByName(checked_class); + if (refType2 == null) { + print_log_on_verbose + ("--> visibmethod003: checked class has been unloaded realy: " + checked_class); + } + else { + print_log_without_verbose + ("--> visibmethod003: check that checked class has been unloaded realy..."); + out_stream.println + ("--> visibmethod003: checked class FOUND: " + checked_class + + " => it has NOT been unloaded!"); + out_stream.println + ("--> ReferenceType.visibleMethods() method can NOT be checked!"); + break; + } + + out_stream.println + ("--> visibmethod003: check ReferenceType.visibleMethods() method for unloaded class..."); + List visible_methods_list = null; + try { + visible_methods_list = refType.visibleMethods(); + } + catch (Exception expt) { + if (expt instanceof com.sun.jdi.ObjectCollectedException) { + out_stream.println + ("--> visibmethod003: PASSED: expected Exception thrown - " + expt.toString()); + } + else { + out_stream.println + ("##> visibmethod003: FAILED: unexpected Exception thrown - " + expt.toString()); + out_stream.println + ("##> expected Exception - com.sun.jdi.ObjectCollectedException"); + visibleMethods_method_error = true; + } + } + break; + } + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> visibmethod003: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> visibmethod003: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibmethod003: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} // end of visibmethod003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TEST.properties new file mode 100644 index 00000000000..8b51b2a9115 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2018, 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. +# + +exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TestDescription.java new file mode 100644 index 00000000000..af7544c42a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleMethods/visibmethod003. + * VM Testbase keywords: [diehard, jpda, jdi, nonconcurrent] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleMethods/visibmethod003 test + * checks the visibleMethods() method of ReferenceType interface + * of the com.sun.jdi package for UNLOADED class: + * the test loads a class, gets a ReferenceType instance for this + * class, then enforces the class to be unloaded and calls the + * visibleMethods() method - the com.sun.jdi.ObjectCollectedException + * should be thrown in this case. + * COMMENTS + * Fixed test due to bug + * 4463674: TEST_BUG: some JDI tests are timing dependent + * The test was modified to comply with new execution scheme + * to have separate directory for precompiled classes: + * - visibmethod003b class was moved in 'loadclass' subdirectory; + * - package name was added in visibmethod003b class; + * - ${COMMON_CLASSES_LOCATION} instead of ${TESTDIR} in .cfg file; + * - ClassUnloader seekes for visibmethod003b class in + * ${COMMON_CLASSES_LOCATION}/loadclass directory. + * 4505735 equals002 and other tests fail with merlin + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleMethods.visibmethod003 + * nsk.jdi.ReferenceType.visibleMethods.visibmethod003a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleMethods.visibmethod003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" ./bin + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/loadclass/visibmethod003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/loadclass/visibmethod003b.java new file mode 100644 index 00000000000..d154a3e8236 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003/loadclass/visibmethod003b.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000, 2018, 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 class will be loaded and then onloaded to check +// the visibleMethods() method of ReferenceType interface for UNLOADED class + +package nsk.jdi.ReferenceType.visibleMethods; + +class visibmethod003b {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003a.java new file mode 100644 index 00000000000..b04195f51d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import java.lang.reflect.*; +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the visibmethod003 JDI test. + */ + +public class visibmethod003a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + private final static String package_prefix = "nsk.jdi.ReferenceType.visibleMethods."; + private final static String checked_class_name = package_prefix + "visibmethod003b"; + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + print_log_on_verbose("**> visibmethod003a: debugee started!"); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + print_log_on_verbose("**> visibmethod003a: waiting for \"checked class dir\" info..."); + pipe.println("ready0"); + String checked_class_dir = (argHandler.getArguments())[0] + File.separator + "loadclass"; + + ClassUnloader classUnloader = new ClassUnloader(); + + try { + classUnloader.loadClass(checked_class_name, checked_class_dir); + print_log_on_verbose + ("--> visibmethod003a: checked class loaded:" + checked_class_name); + } + catch ( Exception e ) { // ClassNotFoundException + System.err.println + ("**> visibmethod003a: load class: exception thrown = " + e.toString()); + print_log_on_verbose + ("--> visibmethod003a: checked class NOT loaded:" + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> visibmethod003a: waiting for \"continue\" or \"quit\" signal..."); + pipe.println("ready1"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibmethod003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibmethod003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + if ( ! instruction.equals("continue")) { + System.err.println + ("!!**> visibmethod003a: unexpected signal (no \"continue\" or \"quit\") - " + instruction); + System.err.println("!!**> visibmethod003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } + + print_log_on_verbose("**> visibmethod003a: \"continue\" signal recieved!"); + print_log_on_verbose("**> visibmethod003a: enforce to unload checked class..."); + + boolean test_class_loader_finalized = classUnloader.unloadClass(); + + if ( ! test_class_loader_finalized ) { + print_log_on_verbose("**> visibmethod003a: checked class may be NOT unloaded!"); + pipe.println("not_unloaded"); + } + else { + print_log_on_verbose("**> visibmethod003a: checked class unloaded!"); + pipe.println("ready2"); + } + print_log_on_verbose("**> visibmethod003a: waiting for \"quit\" signal..."); + instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibmethod003a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibmethod003a: completed!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> visibmethod003a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> visibmethod003a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} // end of visibmethod003a class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004.java new file mode 100644 index 00000000000..63a859c6c61 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method visibleMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibmethod004 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleMethods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "visibmethod004", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "visibmethod004aInterfaceForCheck"; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibmethod004().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod004 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod004 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/visibleMethods/visibmethod004 test LOG:"); + out_stream.println("==> test checks visibleMethods() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for class without visible methods\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibmethod004: visibmethod004a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> visibmethod004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> visibmethod004: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibmethod004: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> visibmethod004: check ReferenceType.visibleMethods() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean visibleMethods_method_error = false; + int visible_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> visibmethod004: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List visible_methods_list = null; + try { + visible_methods_list = refType.visibleMethods(); + } + catch (Throwable thrown) { + out_stream.println("##> visibmethod004: FAILED: ReferenceType.visibleMethods() throws unexpected " + + thrown); + visibleMethods_method_error = true; + break; + } + visible_methods_number = visible_methods_list.size(); + if ( visible_methods_number == 0 ) { + break; + } + Method visible_methods[] = new Method[visible_methods_number]; + visible_methods_list.toArray(visible_methods); + for (int i=0; i visibmethod004: FAILED: unexpected visible method: " + full_visible_method_info); + } + break; + } + + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + if ( visible_methods_number > 0 ) { + out_stream.println + ("##> visibmethod004: UNEXPECTED visible methods number = " + visible_methods_number); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println + ("--> visibmethod004: PASSED: returned list of methods is empty!"); + } + + print_log_on_verbose("--> visibmethod004: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> visibmethod004: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibmethod004: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004/TestDescription.java new file mode 100644 index 00000000000..ebba6e0bf39 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleMethods/visibmethod004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleMethods/visibmethod004 test + * checks the visibleMethods() method of ReferenceType interface + * of the com.sun.jdi package for class without visible methods: + * the ReferenceType.visibleMethods() method is checked for + * debugee's interface which does not contain any methods. + * The test expects the returned list of methods to be empty. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleMethods.visibmethod004 + * nsk.jdi.ReferenceType.visibleMethods.visibmethod004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleMethods.visibmethod004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004a.java new file mode 100644 index 00000000000..61c2160f794 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod004a.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the visibmethod004 JDI test. + */ + +public class visibmethod004a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i visibmethod004a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + visibmethod004aClassForCheck class_for_check = new visibmethod004aClassForCheck(); + + print_log_on_verbose("**> visibmethod004a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibmethod004a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibmethod004a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("##> visibmethod004a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("##> visibmethod004a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +class visibmethod004aClassForCheck implements visibmethod004aInterfaceForCheck { + +} + +interface visibmethod004aInterfaceForCheck { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005.java new file mode 100644 index 00000000000..ab11e7300d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005.java @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * This test checks the method visibleMethods() + * of the JDI interface ReferenceType of com.sun.jdi package + */ + +public class visibmethod005 extends Log { + static java.io.PrintStream out_stream; + static boolean verbose_mode = false; // test argument -vbs or -verbose switches to static + // - for more easy failure evaluation + + /** The main class names of the debugger & debugee applications. */ + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleMethods.", +// package_prefix = "", // for DEBUG without package + thisClassName = package_prefix + "visibmethod005", + debugeeName = thisClassName + "a"; + + /** Debugee's classes for check **/ + private final static String class_for_check = package_prefix + "visibmethod005aInterfaceForCheck"; + private final static String super_interf_for_check_1 = package_prefix + "visibmethod005aSuperInterfaceForCheck_1"; + private final static String super_interf_for_check_2 = package_prefix + "visibmethod005aSuperInterfaceForCheck_2"; + private final static String not_visible_sign = "NOT VISIBLE"; + private final static String passed_sign = "PASSED"; + private static String methods_for_check[][] = { + +// method name declaring class check result + + {"i_multiple_inherited_abstract_method_1", super_interf_for_check_1, not_visible_sign}, + {"i_multiple_inherited_abstract_method_2", super_interf_for_check_2, not_visible_sign} + + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int exitCode = run(argv,System.out); + System.exit(exitCode + 95/*STATUS_TEMP*/); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + out_stream = out; + + int v_test_result = new visibmethod005().runThis(argv,out_stream); + if ( v_test_result == 2/*STATUS_FAILED*/ ) { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod005 test FAILED"); + } + else { + out_stream.println("\n==> nsk/jdi/ReferenceType/visibleMethods/visibmethod005 test PASSED"); + } + return v_test_result; + } + + private void print_log_on_verbose(String message) { + display(message); + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + verbose_mode = argHandler.verbose(); + + if ( out_stream == null ) { + out_stream = out; + } + + out_stream.println("==> nsk/jdi/ReferenceType/visibleMethods/visibmethod005 test LOG:"); + out_stream.println("==> test checks visibleMethods() method of ReferenceType interface "); + out_stream.println(" of the com.sun.jdi package for multiple inherited abstract methods\n"); + + String debugee_launch_command = debugeeName; + if (verbose_mode) { + logTo(out_stream); + } + + Binder binder = new Binder(argHandler,this); + Debugee debugee = binder.bindToDebugee(debugee_launch_command); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + print_log_on_verbose("--> visibmethod005: visibmethod005a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if (line == null) { + out_stream.println + ("##> visibmethod005: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + if (!line.equals("ready")) { + out_stream.println + ("##> visibmethod005: UNEXPECTED debugee's signal (not \"ready\") - " + line); + return 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose("--> visibmethod005: debugee's \"ready\" signal recieved!"); + } + + out_stream.println + ("--> visibmethod005: check ReferenceType.visibleMethods() method for debugee's " + + class_for_check + " class..."); + boolean class_not_found_error = false; + boolean visibleMethods_method_error = false; + int methods_for_check_number = methods_for_check.length; + int not_visible_methods_number = 0; + int visible_methods_number = 0; + int unexpected_visible_methods_number = 0; + + while ( true ) { + ReferenceType refType = debugee.classByName(class_for_check); + if (refType == null) { + out_stream.println("##> visibmethod005: Could NOT FIND class: " + class_for_check); + class_not_found_error = true; + break; + } + List visible_methods_list = null; + try { + visible_methods_list = refType.visibleMethods(); + } + catch (Throwable thrown) { + out_stream.println("##> visibmethod005: FAILED: ReferenceType.visibleMethods() throws unexpected " + + thrown); + visibleMethods_method_error = true; + break; + } + visible_methods_number = visible_methods_list.size(); + Method visible_methods[] = new Method[visible_methods_number]; + String unexpected_visible_methods[] = new String[visible_methods_number]; + visible_methods_list.toArray(visible_methods); + for (int i=0; i visibmethod005: FAILED: method is NOT visible: " + current_method_for_check); + not_visible_methods_number++; + } + else { + print_log_on_verbose + ("--> visibmethod005: PASSED for method: " + current_method_for_check); + } + } + for (int i=0; i visibmethod005: FAILED: unexpected visible method: " + unexpected_visible_methods[i]); + } + break; + } + + out_stream.println("--> visibmethod005: check completed!"); + int v_test_result = 0/*STATUS_PASSED*/; + if ( class_not_found_error || visibleMethods_method_error ) { + v_test_result = 2/*STATUS_FAILED*/; + } + else { + out_stream.println("--> visibmethod005: expected visible methods number = " + methods_for_check_number); + out_stream.println("--> visibmethod005: in fact visible methods number = " + + visible_methods_number); + out_stream.println("--> visibmethod005: expected and in fact visible methods number = " + + (methods_for_check_number - not_visible_methods_number)); + out_stream.println + ("##> visibmethod005: NOT visible methods number = " + not_visible_methods_number); + out_stream.println + ("##> visibmethod005: UNEXPECTED visible methods number = " + unexpected_visible_methods_number); + } + if ( not_visible_methods_number + unexpected_visible_methods_number > 0 ) { + v_test_result = 2/*STATUS_FAILED*/; + } + + print_log_on_verbose("--> visibmethod005: waiting for debugee finish..."); + pipe.println("quit"); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != 0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/) { + out_stream.println + ("##> visibmethod005: UNEXPECTED Debugee's exit status (not 95) - " + status); + v_test_result = 2/*STATUS_FAILED*/; + } + else { + print_log_on_verbose + ("--> visibmethod005: expected Debugee's exit status - " + status); + } + + return v_test_result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005/TestDescription.java new file mode 100644 index 00000000000..9c3114798b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleMethods/visibmethod005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/ReferenceType/visibleMethods/visibmethod005 test + * checks the visibleMethods() method of ReferenceType interface + * of the com.sun.jdi package for multiple inherited abstract methods: + * the ReferenceType.visibleMethods() method is checked for methods of + * debugee's interface which extends two super interfaces. + * Debugee's interface has only multipe inherited abstract methods which + * should be visible. + * Each visible method is checked for method name and declaring class name. + * COMMENTS + * Fixed test due to bug: + * Incorrect initialization of Binder object with argv instead of argHandler. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleMethods.visibmethod005 + * nsk.jdi.ReferenceType.visibleMethods.visibmethod005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleMethods.visibmethod005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005a.java new file mode 100644 index 00000000000..a1c74711229 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod005a.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the visibmethod005 JDI test. + */ + +public class visibmethod005a { + + static boolean verbose_mode = false; // debugger may switch to true + // - for more easy failure evaluation + private final static String + package_prefix = "nsk.jdi.ReferenceType.visibleMethods."; +// package_prefix = ""; // for DEBUG without package + static String checked_class_name = package_prefix + "visibmethod005aInterfaceForCheck"; + + + private static void print_log_on_verbose(String message) { + if ( verbose_mode ) { + System.err.println(message); + } + } + + public static void main (String argv[]) { + + for (int i=0; i visibmethod005a: debugee started!"); + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + Class checked_class_classobj = null; + try { + checked_class_classobj = + Class.forName(checked_class_name, true, visibmethod005a.class.getClassLoader()); + print_log_on_verbose + ("--> visibmethod005a: checked class loaded:" + checked_class_name); + } + catch ( Throwable thrown ) { // ClassNotFoundException +// System.err.println +// ("**> visibmethod005a: load class: Throwable thrown = " + thrown.toString()); + print_log_on_verbose + ("--> visibmethod005a: checked class NOT loaded: " + checked_class_name); + // Debuuger finds this fact itself + } + + print_log_on_verbose("**> visibmethod005a: waiting for \"quit\" signal..."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + print_log_on_verbose("**> visibmethod005a: \"quit\" signal recieved!"); + print_log_on_verbose("**> visibmethod005a: completed succesfully!"); + System.exit(0/*STATUS_PASSED*/ + 95/*STATUS_TEMP*/); + } + System.err.println("!!**> visibmethod005a: unexpected signal (no \"quit\") - " + instruction); + System.err.println("!!**> visibmethod005a: FAILED!"); + System.exit(2/*STATUS_FAILED*/ + 95/*STATUS_TEMP*/); + } +} + +interface visibmethod005aInterfaceForCheck extends visibmethod005aSuperInterfaceForCheck_1, visibmethod005aSuperInterfaceForCheck_2 { + +} + +interface visibmethod005aSuperInterfaceForCheck_1 { + + Object i_multiple_inherited_abstract_method_1(Object obj); +} + +interface visibmethod005aSuperInterfaceForCheck_2 { + + Object i_multiple_inherited_abstract_method_2(Object obj); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006.java new file mode 100644 index 00000000000..9c1e9280622 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method + * com.sun.jdi.ReferenceType.visibleMethods() + * properly returns an empty method list for arrays (ArrayType) and primitive + * classes.

    + * + * Debugger part of it attempts to get a list of visible methods in several + * reference types corresponding to debuggee field values, which themselves + * are:
    + * primitive classes, and arrays of primitive types and classes. + */ +public class visibmethod006 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ReferenceType.visibleMethods.visibmethod006t"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 52; + + static final int FLD_NUM = 24; + // tested fields used to verify the assertion + static final String DEBUGGEE_FLDS[] = { + "boolCls", + "byteCls", + "charCls", + "doubleCls", + "floatCls", + "intCls", + "longCls", + "shortCls", + "boolArr", + "byteArr", + "charArr", + "doubleArr", + "floatArr", + "intArr", + "longArr", + "shortArr", + "boolClsArr", + "byteClsArr", + "charClsArr", + "doubleClsArr", + "floatClsArr", + "intClsArr", + "longClsArr", + "shortClsArr" + }; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + static final int DELAY = 500; // in milliseconds + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private volatile int tot_res = Consts.TEST_PASSED; + private BreakpointRequest BPreq; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new visibmethod006().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "visibmethod006t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main & dummy classes + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + // suspend debuggee VM at breakpoint + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < testedFieldNames.length; i++) { + check(testedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + // check existence of inherited methods for this enum type + List l = checkedClass.visibleMethods(); + if (l.isEmpty()) { + complain("\t ReferenceType.visibleMethods() returned empty list for type: " + className); + exitStatus = Consts.TEST_FAILED; + } else { + Vector methodNames = new Vector(); + Iterator it = l.iterator(); + while (it.hasNext()) { + methodNames.add(it.next().name()); + } + + for (int i = 0; i < testedMethodNames.length; i++) { + String methodName = testedMethodNames[i]; + if (methodNames.contains(methodName)) { + display("CHECK" + (i+1) + " PASSED: " + className + " has method " + methodName); + } else { + complain("CHECK" + (i+1) + " FAILED: " + className + " does not have method " + methodName); + exitStatus = Consts.TEST_FAILED; + } + } + } + + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007/TestDescription.java new file mode 100644 index 00000000000..ce74e8db0eb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ReferenceType/visibleMethods/visibmethod007. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for visibleMethods() method of ReferenceType interface. + * The test checks if this method returns all methods declared + * in java.lang.Enum and java.lang.Object classes for any mirrored + * enum type. The java.lang.Enum class is superclass for each enum + * type. + * The test checks existence of methods with following names in + * returned List: + * clone(), + * compareTo(E o), + * equals(Object o), + * getDeclaringClass(), + * hashCode(), + * name(), + * ordinal(), + * toString() + * The test consists of a debugger program (visibmethod007.java) + * and debugged application (visibmethod007a.java). + * Package name is nsk.jdi.ReferenceType.visibleMethods . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger calls visibleMethods() method for each field + * of enum type declared in visibmethod007a class. + * The debugger checks if each of expected method names exists + * in returned list. The test fails if any of expected method + * names has not been met. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ReferenceType.visibleMethods.visibmethod007 + * nsk.jdi.ReferenceType.visibleMethods.visibmethod007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ReferenceType.visibleMethods.visibmethod007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007a.java new file mode 100644 index 00000000000..444db3a5cef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod007a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ReferenceType.visibleMethods; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class visibmethod007a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static visibmethod007Enum1 f1 = visibmethod007Enum1.e2; + static visibmethod007Enum2 f2 = visibmethod007Enum2.e1; + static visibmethod007Enum1.Enum1_ f3 = visibmethod007Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(visibmethod007.SIGNAL_READY); + + + //pipe.println(visibmethod007.SIGNAL_GO); + receiveSignal(visibmethod007.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum visibmethod007Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum visibmethod007Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001.java new file mode 100644 index 00000000000..401fe637154 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Scenarios.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Debuggee's part contains a tested class (class B) and debugger exercises + * method runIt() of this class by the following steps:
    + * 1. On ClassPrepareEvent of class B, + * MethodExitRequest is created and debugger waits + * MethodExitEvent for to be shure the static + * members of class B have been initialized
    + * 2. After getting MethodExitEvent for ,
    + * - debugger creates MethodEntryRequest
    + * - invokes the tested method (method runIt) by calling + * com.sun.jdi.ClassType.invokeMethod().
    + * This invoking occurs in special thread of debugger's part so that + * debugger can process the events of the target VM. + * 3. When getting MethodEntryEvent from the invoked method, + * debugger tries to pop current frame (with 0 index). + * + * The test passes when the above steps have been successfuly executed. + */ + +public class popframes001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.Scenarios.invokeMethod."; + private final static String debuggerName = prefix + "popframes001"; + public final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + // We expect runIt() method to be called 2 times. + // First time the method call frame will be popped. + // When the metod is recalled it will complete normally. + public final static int expectedEventCount = 2; + private int eventCount = 0; + private ClassType debugeeClass, testedClass; + private EventRequestManager evm; + + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain(msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + popframes001 thisTest = new popframes001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.redirectOutput(log); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canPopFrames()) { + display("\n>>>canPopFrames() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + evm = debugee.getEventRequestManager(); + + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(testedClassName); + req.enable(); + display("\nresuming..."); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\nevent ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\nevent ===>>> " + event); + testedClass = (ClassType )debugee.classByName(testedClassName); + debugeeClass = (ClassType )debugee.classByName(debugeeName); + + display("\ncreating MethodExitRequest for the \"" + + testedClassName + + "\" class"); + + MethodExitRequest mreq = evm.createMethodExitRequest(); + mreq.addClassFilter(testedClassName); + mreq.enable(); + + display("\nresuming..."); + debugee.resume(); + + } else if (event instanceof MethodExitEvent) { + display("\nevent ===>>> " + event); + hitMethodExitEvent((MethodExitEvent )event); + + } else if (event instanceof MethodEntryEvent) { + display("\nevent ===>>> " + event); + hitMethodEntryEvent((MethodEntryEvent )event); + display("\nresuming..."); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (eventCount != expectedEventCount) { + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void hitMethodExitEvent(MethodExitEvent event) { + Method mthd = event.method(); + display("MethodExitEvent:: method name :\t" + mthd.name()); + display("MethodExitEvent:: is it :\t" + + mthd.isStaticInitializer()); + if (mthd.isStaticInitializer()) { + display("\nMethodExitEvent:: creating MethodEntryRequest for the \"" + + testedClassName + + "\" class"); + + evm.createExceptionRequest(testedClass, false, true).enable(); + + MethodEntryRequest req = evm.createMethodEntryRequest(); + req.addClassFilter(testedClassName); + req.enable(); + MethodInvoker invoker = new MethodInvoker(testedClass, + popframes001b.methodNameCaller, + event.thread()); + invoker.start(); + + } else { + display("MethodExitEvent:: no actions for this method"); + display("\nresuming..."); + debugee.resume(); + } + } + + // Set a flag that the frame has been popped. + // Otherwise we would get an eternal loop calling and popping runIt(). + private boolean isFramePopped = false; + + private void hitMethodEntryEvent(MethodEntryEvent event) { + String methodName = event.method().name(); + display("MethodEntryEvent:: method name:\t" + methodName); + if (popframes001b.methodName.compareTo(methodName) == 0) { + if (!isFramePopped) { + displayActiveFrames(event.thread()); + popFrames(event.thread()); + displayActiveFrames(event.thread()); + isFramePopped = true; + } + eventCount++; + } + } + + private void displayActiveFrames(ThreadReference thread) { + int i = 0; + display("\nActive frames:"); + try { + for (i = 0; i < thread.frameCount(); i++) { + display("\t" + i + ". " + thread.frame(i).location() + + "\tmethod: " + thread.frame(i).location().method().name()); + } + } catch(IncompatibleThreadStateException e) { + display("\t" + i + ". ??? " + e); + } + } + + private void popFrames(ThreadReference thread) { + try { + StackFrame frame = thread.frame(0); + display("\nresetting frame of " + frame.location().method()); + thread.popFrames(frame); + display("frame has been reset"); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + class MethodInvoker extends Thread { + private ClassType clsType; + private String methodName; + private ThreadReference thread; + + public MethodInvoker(ClassType clsType, String methodName, + ThreadReference thread) { + display("\ninvokingMethodThread:: thread created"); + this.clsType = clsType; + this.methodName = methodName; + this.thread = thread; + } + + public void run() { + Method mthd = debugee.methodByName(clsType, methodName); + display("invokingMethodThread:: invoking method\t:\"" + mthd.name() + "\""); + display("invokingMethodThread:: -------------------------------"); + + try { + clsType.invokeMethod(thread, mthd, new Vector(), 0); + } catch (Throwable e) { + complain("invokingMethodThread:: " + UNEXPECTED_STRING + e); + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } + + display("setting field"); + Field fld = debugeeClass.fieldByName("finishIt"); + try { + debugeeClass.setValue(fld,debugee.VM().mirrorOf(true)); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + debugee.resume(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001/TestDescription.java new file mode 100644 index 00000000000..2559e112438 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Scenarios/invokeMethod/popframes001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * Debuggee's part contains a tested class (class B) and debugger exercises + * method runIt() of this class by the following steps: + * 1. On ClassPrepareEvent of class B, MethodExitRequest is created and + * debugger waits MethodExitEvent for to be shure the static + * members of class B have been initialized + * 2. After getting MethodExitEvent for , + * - debugger creates MethodEntryRequest + * - invokes the tested method (method "runIt") by calling + * com.sun.jdi.ClassType.invokeMethod(). + * This invoking occurs in special thread of debugger's part so that + * debugger can process the events of the target VM. + * 3. When getting MethodEntryEvent from the invoked method (method "runIt"), + * debugger tries to pop current frame (with 0 index). + * The test passes when the above steps have been successfuly executed. + * COMMENTS + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Scenarios.invokeMethod.popframes001 + * nsk.jdi.Scenarios.invokeMethod.popframes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Scenarios.invokeMethod.popframes001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001a.java new file mode 100644 index 00000000000..42d8f5446c6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001a.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Scenarios.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * popframes001a is deugee's part of the popframes001. + */ + +public class popframes001a { + + volatile public static boolean finishIt = false; + + public static void main(String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.out, argHandler); + + popframes001b.loadClass = true; + + while (!finishIt) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + } + } + + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } +} + +class popframes001b { + public final static int INITIAL_VALUE = 0; + + public static boolean loadClass = false; + public static int flag = INITIAL_VALUE; + + public final static String methodName = "runIt"; + public final static String methodNameCaller = "runItCaller"; + public final static String flagName = "flag"; + + public static void runIt() { + flag = INITIAL_VALUE; + } + + // We need to call runIt() from a java function. + // This is because jvmti function popFrame() requires that + // both calling and called methods are java functions. + public static void runItCaller() { + runIt(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001.java new file mode 100644 index 00000000000..61174bbf09a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Scenarios.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import jdk.test.lib.Utils; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * This test based on a scenario which consists of the following steps: + * 1. Invoking debugee's static method by ClassType.invokeMethod().
    + * 2. Redefinition of this method.
    + * 3. Invoking the one again.
    + * + * The test checks a value of static field to be equal to new value. + * When the field has unexpected value, the test fails. + */ + +public class redefineclasses001 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.Scenarios.invokeMethod."; + private final static String debuggerName = prefix + "redefineclasses001"; + public final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b"; + + private final static String classFileName = "redefineclasses001b.class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + public final static int expectedEventCount = redefineclasses001a.brkpLineNumber.length; + private int eventCount = 0; + private ReferenceType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain(msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses001 thisTest = new redefineclasses001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.redirectOutput(log); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debugeeName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); +// display("\nevent ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + display("\nevent ===>>> " + event); + prepareTestCases(); + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + display("\nevent ===>>> " + event); + event.request().disable(); + display("\n\n=================="); + display(eventCount + "-case"); + performCase(eventCount, ((BreakpointEvent )event).thread()); + eventCount++; + if (eventCount < expectedEventCount) prepareTestCases(); + + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (eventCount != expectedEventCount) { + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void performCase(int num, ThreadReference thread) { + ClassType testedClass = (ClassType )debugee.classByName(testedClassName); + invokeMethod(testedClass, redefineclasses001b.methodName, + thread); + checkFieldVal(testedClass, redefineclasses001b.flagName, + redefineclasses001b.BEFORE_REDEFINITION); + + display("\nredefining..."); + String newClassFile = classDir + File.separator + + "newclass" + File.separator + + prefix.replace('.',File.separatorChar) + + classFileName; + redefineDebugee(testedClass, newClassFile); + + invokeMethod(testedClass, redefineclasses001b.methodName, + thread); + checkFieldVal(testedClass, redefineclasses001b.flagName, + redefineclasses001b.AFTER_REDEFINITION); + + display("\nreturning the previous state..."); + redefineDebugee(testedClass, + ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString()); + } + + private void redefineDebugee(ReferenceType refType, String classFileName) { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(refType, classFileName); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(ReferenceType refType, String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(refType, arrayToRedefine); + return mapForClass; + } + + private void prepareTestCases() { + debugeeClass = debugee.classByName(debugeeName); + display("\npreparing the next testcase..."); + display("debugeeClass\t\t:" + debugeeClass.name()); + display("line number:\t" + redefineclasses001a.brkpLineNumber[eventCount]); + display("setting breakpoint..."); + debugee.setBreakpoint(debugeeClass, + redefineclasses001a.brkpMethodName, + redefineclasses001a.brkpLineNumber[eventCount]); + } + + private void invokeMethod(ClassType clsType, String methodName, + ThreadReference thread) { + Method mthd = debugee.methodByName(clsType, methodName); + display("\ninvoking method\t:\"" + mthd.name() + "\""); + display("-------------------------------"); + Vector args = new Vector(); + args.add(debugee.VM().mirrorOf(false)); + try { + clsType.invokeMethod(thread, mthd, args, 0); + } catch (InvalidTypeException e) { + throw new Failure(UNEXPECTED_STRING + e); + } catch (ClassNotLoadedException e) { + throw new Failure(UNEXPECTED_STRING + e); + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } catch (InvocationException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private boolean checkFieldVal(ReferenceType refType, String fieldName, + int expectedValue) { + display("checking flag's value"); + Field fld = refType.fieldByName(fieldName); + PrimitiveValue val = (PrimitiveValue )refType.getValue(fld); + if (val.intValue() == expectedValue) { + display("The field has expected value:\t" + + redefineclasses001b.flag2String(expectedValue)); + return true; + } else { + complain("The field has value:\t" + + redefineclasses001b.flag2String(val.intValue())); + complain("but it is expected:\t" + + redefineclasses001b.flag2String(expectedValue)); + exitStatus = Consts.TEST_FAILED; + + return false; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/TestDescription.java new file mode 100644 index 00000000000..a5ca6696161 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Scenarios/invokeMethod/redefineclasses001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * This test based on a scenario which consists of the following steps: + * 1. Invoking debugee's static method by ClassType.invokeMethod(). + * 2. Redefinition of this method. + * 3. Invoking the one again. + * The test checks a value of static field to be equal to new value. + * When the field has unexpected value, the test fails. + * COMMENTS + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Scenarios.invokeMethod.redefineclasses001 + * nsk.jdi.Scenarios.invokeMethod.redefineclasses001a + * nsk.jdi.Scenarios.invokeMethod.redefineclasses001b + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Scenarios.invokeMethod.redefineclasses001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/newclass/redefineclasses001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/newclass/redefineclasses001b.java new file mode 100644 index 00000000000..599296ab69b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001/newclass/redefineclasses001b.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Scenarios.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * redefineclasses001b is deugee's part of the redefineclasses001. + */ + +public class redefineclasses001b extends Thread{ + public final static int INITIAL_VALUE = 0; + public final static int BEFORE_REDEFINITION = 1; + public final static int AFTER_REDEFINITION = 2; + + public static boolean loadClass = false; + public static int flag = INITIAL_VALUE; + + public final static String methodName = "runIt"; + public final static String flagName = "flag"; + + public static Object waitStarting = new Object(); + public static Object waitFinishing = new Object(); + public volatile static boolean notified = false; + + public void run() { + runIt(true); + } + + public static void runIt(boolean doWait) { + + flag = AFTER_REDEFINITION; +// ^^^^^^^^^^^^^^^^^^^ it will be redefined + +// System.out.println("runIt::notify..."); + notified = false; + synchronized(waitStarting) { + waitStarting.notify(); + } + notified = true; + System.out.println("runIt::notified..."); + + if (!doWait) { + return; + } + + synchronized(waitFinishing) { + try { + waitFinishing.wait(); + } catch(InterruptedException e) { + e.printStackTrace(); + } + } + } + + public static String flag2String(int value) { + switch (value) { + case INITIAL_VALUE: + return "INITIAL_VALUE(" + INITIAL_VALUE + ")"; + case BEFORE_REDEFINITION: + return "BEFORE_REDEFINITION(" + BEFORE_REDEFINITION + ")"; + case AFTER_REDEFINITION: + return "AFTER_REDEFINITION(" + AFTER_REDEFINITION + ")"; + default: + return "UNKNOWN_VALUE"; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001a.java new file mode 100644 index 00000000000..9bce5539953 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001a.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Scenarios.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses001a is deugee's part of the redefineclasses001. + */ +public class redefineclasses001a { + public final static String brkpMethodName = "main"; + public final static int [] brkpLineNumber = {51, 59}; + + public final static String testedObjName = "obj"; + private static Log log = null; + + public static void main(String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.out, argHandler); + + redefineclasses001b.loadClass = true; + int i = 0; + do { + switch (++i) { // brkpLineNumber[0] + case 0: + break; + case 1: + new redefineclasses001b().start(); + + waitStarting(); + + notifyFinishing(); // brkpLineNumber[1] + break; + } + } while (i < redefineclasses001.expectedEventCount); + + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void waitStarting() { + log.display("waiting start of the tested thread..."); + synchronized(redefineclasses001b.waitStarting) { + while(!redefineclasses001b.notified) { + try { + redefineclasses001b.waitStarting.wait(10); + } catch(InterruptedException e) { + log.display("Unexpected" + e); + } + } + } + } + + private static void notifyFinishing() { + log.display("notifying the thread to finish..."); + synchronized(redefineclasses001b.waitFinishing) { + redefineclasses001b.waitFinishing.notify(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001b.java new file mode 100644 index 00000000000..8871e566edf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Scenarios/invokeMethod/redefineclasses001b.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Scenarios.invokeMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * redefineclasses001b is deugee's part of the redefineclasses001. + */ + +public class redefineclasses001b extends Thread{ + public final static int INITIAL_VALUE = 0; + public final static int BEFORE_REDEFINITION = 1; + public final static int AFTER_REDEFINITION = 2; + + public static boolean loadClass = false; + public static int flag = INITIAL_VALUE; + + public final static String methodName = "runIt"; + public final static String flagName = "flag"; + + public static Object waitStarting = new Object(); + public static Object waitFinishing = new Object(); + public volatile static boolean notified = false; + + public void run() { + runIt(true); + } + + public static void runIt(boolean doWait) { + + flag = BEFORE_REDEFINITION; +// ^^^^^^^^^^^^^^^^^^^ it will be redefined + +// System.out.println("runIt::notify..."); + notified = false; + synchronized(waitStarting) { + waitStarting.notify(); + } + notified = true; + System.out.println("runIt::notified..."); + + if (!doWait) { + return; + } + + synchronized(waitFinishing) { + try { + waitFinishing.wait(); + } catch(InterruptedException e) { + e.printStackTrace(); + } + } + } + + public static String flag2String(int value) { + switch (value) { + case INITIAL_VALUE: + return "INITIAL_VALUE(" + INITIAL_VALUE + ")"; + case BEFORE_REDEFINITION: + return "BEFORE_REDEFINITION(" + BEFORE_REDEFINITION + ")"; + case AFTER_REDEFINITION: + return "AFTER_REDEFINITION(" + AFTER_REDEFINITION + ")"; + default: + return "UNKNOWN_VALUE"; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/choices/choices001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/choices/choices001.java new file mode 100644 index 00000000000..2194062a6bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/choices/choices001.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.SelectedArgument.choices; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.SelectedArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector.SelectedArgument.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.SelectedArgument.choices()
    + * complies with its specification, in particular,
    + * a returned value is a non-empty "List of String".
    + * Values of Strings are not checked up.
    + *
    + * In case of error the test produces the return value 97 and
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class choices001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.SelectedArgument.choices\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.SelectedArgument.choices\n" ; + + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.SelectedArgument argument = null; + + for ( ; ; ) { + try { +//out.println("connector"); + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// +//out.println(" argument"); + argument = (Connector.SelectedArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with SelectedArgument found\n"); + return exitCode0; + } + } + + List listofChoices = argument.choices(); + + if (listofChoices.isEmpty()) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isEmpty\n" + + "error: returned List of String is empty\n"); + } else { + Iterator listIterator = listofChoices.iterator(); + + for ( ; ; ) { + try { + String choice = (String) listIterator.next(); + + } catch ( ClassCastException e1 ) { + exitCode = exitCode2; + out.println(sErr2 + + "check: String\n" + + "error: List contains non-String\n"); + break ; + } catch ( NoSuchElementException e2) { + break ; + } + } + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/choices/choices001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/choices/choices001/TestDescription.java new file mode 100644 index 00000000000..0d7acf7eee8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/choices/choices001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/SelectedArgument/choices/choices001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.SelectedArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.SelectedArgument.choices() + * complies with its specification, in particular, + * a returned value is a non-empty "List of String". + * Values of Strings are not checked up. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.SelectedArgument object is searched among + * Arguments of Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - Using the method argument.choices(), + * the list of possible values is obtained. + * IF the list is empty + * THEN an error detected + * - each member of the list is checked up whether + * it is a string or not. + * IF the member is not a string + * THEN an error detected + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Since current version of VMM doesn't implement SelectedArgument + * only this is detected but other checks are impossible. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.SelectedArgument.choices.choices001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.SelectedArgument.choices.choices001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001.java new file mode 100644 index 00000000000..6ae87b3e198 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.SelectedArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.SelectedArgument.
    + * + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.SelectedArgument.isValid()
    + * complies with its specification in the following case:
    + * - for each String in List of choices, isValid returns true;
    + *
    + * In case of any check returns a wrong value - false,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class isvalid001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.SelectedArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.SelectedArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.SelectedArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.SelectedArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with SelectedArgument found\n"); + return exitCode0; + } + } + + List listofChoices = argument.choices(); + + if (listofChoices.isEmpty()) { + exitCode = exitCode2; + out.println(sErr2 + + "error: returned List of String is empty\n"); + } else { + + Iterator listIterator = listofChoices.iterator(); + + for ( ; ; ) { + try { + String choiceString = (String) listIterator.next(); + + if (!argument.isValid(choiceString)) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(arg)\n" + + "error: List contains invalid String\n"); + break ; + } + + } catch ( ClassCastException e1 ) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(arg)\n" + + "error: List contains non-String\n"); + break ; + } catch ( NoSuchElementException e2) { + break ; + } + } + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001/TestDescription.java new file mode 100644 index 00000000000..8b90e0bacd4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid001/TestDescription.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/SelectedArgument/isValid/isvalid001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.SelectedArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.SelectedArgument.isValid() + * complies with its specification in the following case: + * - for each String in List of choices, isValid returns true. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.SelectedArgument object is searched among + * Arguments of Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - To argument's List of choices, the above checks are applied. + * In case of any check returns a wrong value, + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Since current version of VMM doesn't implement SelectedArgument + * only this is detected but other checks are impossible. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.SelectedArgument.isValid.isvalid001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.SelectedArgument.isValid.isvalid001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002.java new file mode 100644 index 00000000000..bf564e1de0e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.SelectedArgument.isValid; + + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Connector.SelectedArgument; + + +/** + * The test for the implementation of an object of the type
    + * Connector.SelectedArgument.
    + * + * The test checks up that results of the method
    + * com.sun.jdi.connect.Connector.SelectedArgument.isValid()
    + * complies with its specification in the follwing cases:
    + * - isValid returns false for null-string and
    + * for a string, different from any in the List.
    + *
    + * In case of any check returns a wrong value - true,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class isvalid002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.SelectedArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.SelectedArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.SelectedArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.SelectedArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with SelectedArgument found\n"); + return exitCode0; + } + } + + String longestString = " "; + + List listofChoices = argument.choices(); + + if (listofChoices.isEmpty()) { + exitCode = exitCode2; + out.println(sErr1 + + "error: returned List of String is empty\n"); + } else { + Iterator listIterator = listofChoices.iterator(); + + for ( ; ; ) { + try { + String choiceString = (String) listIterator.next(); + + if (longestString.length() < choiceString.length()) { + longestString = choiceString; + } + } catch ( NoSuchElementException e) { + break ; + } + } + + if (argument.isValid(null)) { + exitCode = exitCode2; + out.println(sErr1 + + "check: isValid(null)\n" + + "error: isValid returns true\n"); + } + + longestString.concat("9"); + if (argument.isValid(longestString)) { + exitCode = exitCode2; + out.println(sErr1 + + "check: isValid(longest+1 String)\n" + + "error: isValid returns true\n"); + } + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002/TestDescription.java new file mode 100644 index 00000000000..15d3ae9b636 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/SelectedArgument/isValid/isvalid002/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/SelectedArgument/isValid/isvalid002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.SelectedArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.SelectedArgument.isValid() + * complies with its specification in the follwing cases: + * - isValid returns false for null-string and + * - for a string, different from any in the List. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.SelectedArgument object is searched among + * Arguments of Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - To argument's List of choices, the above checks are applied. + * In case of any check returns a wrong value, + * the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Since current version of VMM doesn't implement SelectedArgument + * only this is detected but other checks are impossible. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.SelectedArgument.isValid.isvalid002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.SelectedArgument.isValid.isvalid002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java new file mode 100644 index 00000000000..6cdd5bd4455 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ShortType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ShortType.
    + *
    + * The test checks that for a mirror of a short value, the casts
    + * from Type to ShortType and from PrimitiveType to ShortType
    + * don't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the casts,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares a short field and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the checks.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class shorttype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ShortType/_itself_/shorttype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new shorttype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ShortType._itself_.shorttype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......String name = 'sh';"); + String name = "sh"; + + log2(" getting: Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type();"); + Type type = debuggeeClass.getValue(debuggeeClass.fieldByName(name)).type(); + log2(" PrimitiveType primitiveType = (PrimitiveType) type;"); + PrimitiveType primitiveType = (PrimitiveType) type; + + ShortType shortType = null; + try { + log2(" checking up on cast: ShortType shortType = (ShortType) type;"); + shortType = (ShortType) type; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + try { + log2(" checking up on cast: ShortType shortType = (ShortType) primitiveType;"); + shortType = (ShortType) primitiveType; + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001/TestDescription.java new file mode 100644 index 00000000000..7db5f7169dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ShortType/_itself_/shorttype001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ShortType. + * The test checks that for a mirror of a short value the casts + * from Type to ShortType and from PrimitiveType to ShortType + * don't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.ShortType._itself_.shorttype001; + * the debuggee program - nsk.jdi.ShortType._itself_.shorttype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ShortType._itself_.shorttype001 + * nsk.jdi.ShortType._itself_.shorttype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ShortType._itself_.shorttype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001a.java new file mode 100644 index 00000000000..82eb70e0eb5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ShortType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the shorttype001 JDI test. + */ + +public class shorttype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static short sh = 0; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001.java new file mode 100644 index 00000000000..483897bcc9c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ShortValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + + +public class compareto001 { + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ShortValue.compareTo"; + private final static String className = ".compareto001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + private static Value objectValue; + private static List fieldList; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return; + } + + // getting of object to check + Field field = debuggeeClass.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + + objectValue = debuggeeClass.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = debuggeeClass.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = debuggeeClass.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitiveValues = (ArrayReference)arrValue; + + fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + ShortValue value; + Field fldOtherType; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof ShortValue) ) { + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (ShortValue )v1; + + // comparing with debuggee's fields + display("Checking compateTo(Object object) method for ShortValue: " + value); + + for (int j = 0; j < primitiveValues.length(); j++) { + arrValue = primitiveValues.getValue(j); + + fldOtherType = debuggeeClass.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = debuggeeClass.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + + } + + //--------------------------------------------------------- test specific methods + + + private static boolean PerformComparing(ShortValue value, Object object ) { + boolean result = true; + + // assertion [ x.compareTo(x) == 0 ] + if (value.compareTo(value) != 0) { + complain("Failed assertion [ x.compareTo(x) == 0 ] for value: " + value.toString()); + result = false; + } + + if (object instanceof ShortValue) { + ShortValue shortObject = (ShortValue)object; + try { + // assertion [ x.compareTo(y) == 0 <==> x.equals(y) ] + if ( ((value.equals(object)) && (value.compareTo(shortObject) != 0)) || + (!(value.equals(object)) && (value.compareTo(shortObject) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (x.equals(y) == true) ] \n\t" + + "where 'x' is ShortValue: " + value + " and 'y' is ShortValue : " + shortObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(shortObject) + "\n\t" + + "result of (x.equals(y)): " + value.equals(object) ); + result = false; + } + + // assertion [ x.compareTo(y) == 0 <==> y.compareTo(x) == 0 ] + if ( ((value.compareTo(shortObject) == 0) && (shortObject.compareTo(value) != 0)) || + ((value.compareTo(shortObject) != 0) && (shortObject.compareTo(value) == 0)) ) { + complain("Failed assertion [ (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0) ] \n\t" + + "where 'x' is ShortValue: " + value + " and 'y' is ShortValue : " + shortObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(shortObject) + "\n\t" + + "result of (y.compareTo(x)): " + shortObject.compareTo(value) ); + result = false; + } + if (value.compareTo(shortObject) != 0) { + // assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] + if (value.compareTo(shortObject) != -(shortObject.compareTo(value))) { + complain("Failed assertion [ if (x.compareTo(y) == i) then (y.compareTo(x) == -i) ] \n\t" + + "where 'x' is ShortValue: " + value + " and 'y' is ShortValue : " + shortObject + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(shortObject) + "\n\t" + + "result of (y.compareTo(x)): " + shortObject.compareTo(value) ); + result = false; + } + } + + // assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] + if (value.compareTo(shortObject) > 0) { + ShortValue lessValue = FindLessShortValue(shortObject); + if (lessValue != null) { + if (value.compareTo(lessValue) <= 0) { + complain("Failed assertion [ if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0) ] \n\t" + + "where 'x' is ShortValue: " + value + " , 'y' is ShortValue : " + shortObject + " , 'z' is ShortValue : " + lessValue + " \n\t" + + "result of (x.compareTo(y)): " + value.compareTo(shortObject) + "\n\t" + + "result of (y.compareTo(z)): " + shortObject.compareTo(lessValue) + "\n\t" + + "result of (x.compareTo(z)): " + value.compareTo(lessValue) ); + result = false; + } + } + } + + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "ShortValue: " + value + " and ShortValue argument: " + object); + result = false; + } + + } else if (object == null) { + try { + value.compareTo(null); + complain("Does not throw expected NullPointerException when comparing \n\t" + + "ShortValue: " + value + " and null argument"); + result = false; + } catch (NullPointerException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "ShortValue: " + value + " and null argument"); + result = false; + } + } else { + try { + value.compareTo((ShortValue)object); + complain("Does not throw expected ClassCastException when comparing \n\t" + + "ShortValue: " + value + " and argument: " + object); + result = false; + } catch (ClassCastException ne) { + // continue + } catch (Exception e) { + complain("Caught unexpected " + e + " when comparing \n\t" + + "ShortValue: " + value + " and argument: " + object); + result = false; + } + } + + return result; + } + + /** + * This function searches the static fieldList - the list of mirrored + * fields of debuggee's compareto001aClassToCheck class. Search is aimed + * to find another ShortValue field which is less then method's argument via + * compareTo method. + */ + + private static ShortValue FindLessShortValue (ShortValue currentValue) { + ShortValue result = null; + + for (int i = 0; i < fieldList.size(); i++ ) { + + Field field = (Field )fieldList.get(i); + ShortValue newValue = (ShortValue)((ObjectReference )objectValue).getValue(field); + + if (currentValue.compareTo(newValue) > 0) { + result = newValue; + break; + } + } + return result; + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001/TestDescription.java new file mode 100644 index 00000000000..921d39928fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ShortValue/compareTo/compareto001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the compareTo(Object o) method of com.sun.jdi.ShortValue + * interface. This method is inherited from java.lang.Comparable interface. + * The test checks the following assertions which imply from spec for + * Comparable.compareTo(Object o): + * - (x.compareTo(y) == 0) is identical to (x.equals(y) == true); + * - (x.compareTo(y) == 0) is identical to (y.compareTo(x) == 0); + * - if (x.compareTo(y) == i) then (y.compareTo(x) == -i); + * - if (x.compareTo(y) > 0) and (y.compareTo(z) > 0), then (x.compareTo(z) > 0); + * - if an argument is null, then NullPointerException is thrown; + * - if an argument is not of ShortValue type, then a ClassCastException is thrown. + * where 'x', 'y' and 'z' denote ShortValue object. + * The debugger program - nsk.jdi.ShortValue.compareto.compareto001; + * the debuggee program - nsk.jdi.ShortValue.compareto.compareto001a; + * The test works as follows: + * Using nsk.jdi.share classes, the debugger connects to the debuggee. + * Then the debugger gets a list of short fields of debuggee's object of + * compareto001aClassToCheck type. For every field a mirror of ShortValue type + * is created and the assertions are checked. A various values for comparison + * are got from values of mirrors of debuggee's static fields. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ShortValue.compareTo.compareto001 + * nsk.jdi.ShortValue.compareTo.compareto001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ShortValue.compareTo.compareto001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001a.java new file mode 100644 index 00000000000..85b281d3373 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/compareTo/compareto001a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ShortValue.compareTo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class compareto001a { + + //----------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //---------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + static compareto001aClassToCheck testedObj = new compareto001aClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(log); + + try { + pipe.println(compareto001.SIGNAL_READY); +// receiveSignal(compareto001.SIGNAL_GO); + + receiveSignal(compareto001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class compareto001aClassToCheck { + public short shortMAX = Short.MAX_VALUE; + public short short1 = 1; + public short short0 = 0; + public short short_1 = -1; + public short shortMIN = Short.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001.java new file mode 100644 index 00000000000..92150b242dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ShortValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ShortValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ShortValue.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static short plus1_1 = +1;
    + * public static short plus1_2 = +1;
    + * public static short minus1 = -1;
    + * public static int intplus1 = +1;
    + *
    + * which a debugger mirros as :
    + *
    + * ShortValue svplus1_1;
    + * ShortValue svplus1_2;
    + * ShortValue svminus1;
    + * IntegerValue ivplus1;
    + *
    + * the following is true:
    + *
    + * svplus1_1 == svplus1_2
    + * svplus1_1 != svminus1
    + * svplus1_1 != ivplus1
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ShortValue/equals/equals001", + sHeader2 = "--> equals001: ", + sHeader3 = "##> equals001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ShortValue.equals.equals001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("equals001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsplus1_1 = execClass.fieldByName("plus1_1"); + Field fsplus1_2 = execClass.fieldByName("plus1_2"); + Field fsminus1 = execClass.fieldByName("minus1"); + Field fiplus1 = execClass.fieldByName("intplus1"); + + ShortValue svplus1_1 = (ShortValue) execClass.getValue(fsplus1_1); + ShortValue svplus1_2 = (ShortValue) execClass.getValue(fsplus1_2); + ShortValue svminus1 = (ShortValue) execClass.getValue(fsminus1); + IntegerValue ivplus1 = (IntegerValue) execClass.getValue(fiplus1); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (!svplus1_1.equals(svplus1_2)) + expresult = 1; + break; + + case 1: if (svplus1_1.equals(svminus1)) + expresult = 1; + break; + + case 2: if (svplus1_1.equals(ivplus1)) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001/TestDescription.java new file mode 100644 index 00000000000..b6b50a25403 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ShortValue/equals/equals001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ShortValue. + * The test checks up that a result of the method + * com.sun.jdi.ShortValue.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this ShortValue for equality. + * Returns: true if the Object is a ShortValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.ShortValue.equals.equals001; + * a debuggee program - nsk.jdi.ShortValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ShortValue.equals.equals001 + * nsk.jdi.ShortValue.equals.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ShortValue.equals.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001a.java new file mode 100644 index 00000000000..d1f49112d3d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ShortValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001a JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> equals001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> equals001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static short smallest = Short.MIN_VALUE; +// public static short zero = 0; +// public static short largest = Short.MAX_VALUE; + + public static short plus1_1 = +1; + public static short plus1_2 = +1; + public static short minus1 = -1; + + public static int intplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * types and when parameter is null.
    + * Analyse of the method executing is performed by PerformComparing + * method.
    + * First parameter of PerformComparing is static field of testedObj,
    + * which is placed onto debugee's side.
    + * + * Second parameter is got from debugee too:
    + * Debugee has array of boundary values of each primitive type, execTest reads
    + * them and calls PerformComparing for each of them.
    + */ +public class equals002 { + + private final static String prefix = "nsk.jdi.ShortValue.equals."; + private final static String className = "equals002"; + private final static String debuggerName = prefix + className; + private final static String debugeeName = debuggerName + "a"; + private final static String objectToCheck = "testedObj"; + private final static String arrPrimitives = "testedFields"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static ReferenceType refType; + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_FAILED; + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + execTest(); + debugee.quit(); + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + private static void execTest() { + + exitStatus = Consts.TEST_FAILED; + + refType = debugee.classByName(debugeeName); + if ( refType == null ) { + complain("Class '" + debugeeName + "' not found."); + return; + } + + // getting of object to check + Field field = refType.fieldByName(objectToCheck); + if ( field == null ) { + complain("Field '" + objectToCheck + "' not found."); + return; + } + Value objectValue = refType.getValue(field); + if ( objectValue == null ) { + complain("Field '" + objectToCheck + "' not initialized."); + return; + } + + // geting of array of primitive types + field = refType.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + return; + } + Value arrValue = refType.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + return; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + List fieldList = ((ClassType )objectValue.type()).allFields(); + + Value v1, currentValue; + ShortValue value; + Field fldOtherType; + String msg; + + exitStatus = Consts.TEST_PASSED; + + // comparing loop + for (int i = 0; i < fieldList.size(); i++ ) { + field = (Field )fieldList.get(i); + log.display(""); + msg = "***" + field; + v1 = ((ObjectReference )objectValue).getValue(field); + if ( !(v1 instanceof ShortValue) ) { + msg += " is not ShortValue (skipped)"; + exitStatus = Consts.TEST_FAILED; + continue; + } + value = (ShortValue )v1; + + // comparing with debugee's fields + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = refType.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + currentValue = refType.getValue(fldOtherType); + + if ( !PerformComparing(value, currentValue) ) + exitStatus = Consts.TEST_FAILED; + } + } + } + + private static boolean PerformComparing(ShortValue value, Object object ) { + boolean res = true; + String msg = ""; + try { + if ( value.equals(object) ) { + if ( object instanceof ShortValue ) { + if ( value.value() == ((PrimitiveValue )object).shortValue() ) { + msg += "--> " + value + " == " + object; + } else { + msg += "##> " + value + " == " + object; + res = false; + } + } + else { + msg += "##> " + value + " == " + object + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if ( object == null ) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if ( object instanceof ShortValue ) { + if ( value.value() != ((PrimitiveValue )object).shortValue() ) { + msg += "--> " + value + " != " + object; + } else { + msg += "##> " + value + " != " + object; + res = false; + } + } + else { + msg += "--> " + value + " != " + object; + } + } + + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..7d64104bf54 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ShortValue/equals/equals002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.ShortValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this ShortValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is a ShortValue and if applying "==" to the two + * mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has boundary values of primitive + * types. Also, case when parameter is considered. + * No exceptions are expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ShortValue.equals.equals002 + * nsk.jdi.ShortValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ShortValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002a.java new file mode 100644 index 00000000000..aa9782c4330 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/equals/equals002a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ShortValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * equals002a is deugee's part of the test.
    + * It contains the static fields with boundary values for each primitive type.
    + * ClassToCheck delivers values for first parameter of equals.
    + */ +public class equals002a { + + static ClassToCheck testedObj = new ClassToCheck(); + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByte1", + "cmpByte0", + "cmpByte_1", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDouble1", + "cmpDouble0", + "cmpDouble_1", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloat1", + "cmpFloat0", + "cmpFloat_1", + "cmpFloatMIN", + "cmpIntMAX", + "cmpInt1", + "cmpInt0", + "cmpInt_1", + "cmpIntMIN", + "cmpLongMAX", + "cmpLong1", + "cmpLong0", + "cmpLong_1", + "cmpLongMIN", + "cmpShortMAX", + "cmpShort1", + "cmpShort0", + "cmpShort_1", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByte1 = 1; + static byte cmpByte0 = 0; + static byte cmpByte_1 = -1; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDouble1 = 1; + static double cmpDouble0 = 0; + static double cmpDouble_1 = -1; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloat1 = 1; + static float cmpFloat0 = 0; + static float cmpFloat_1 = -1; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpInt1 = 1; + static int cmpInt0 = 0; + static int cmpInt_1 = -1; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLong1 = 1; + static long cmpLong0 = 0; + static long cmpLong_1 = -1; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShort1 = 1; + static short cmpShort0 = 0; + static short cmpShort_1 = -1; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instruction = pipe.readln(); + + if ( instruction.equals("quit") ) { + log.display("DEBUGEE> \"quit\" signal received."); + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class ClassToCheck { + public short shortMAX = Short.MAX_VALUE; + public short short1 = 1; + public short short0 = 0; + public short short_1 = -1; + public short shortMIN = Short.MIN_VALUE; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001.java new file mode 100644 index 00000000000..61819af6665 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ShortValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ShortValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ShortValue.hashCode()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static short plus1_1 = +1;
    + * public static short plus1_2 = +1;
    + *
    + * which a debugger mirros as :
    + *
    + * ShortValue svplus1_1;
    + * ShortValue svplus1_2;
    + *
    + * the following is true:
    + *
    + * svplus1_1.hashCode() == svplus1_1.hashCode()
    + * svplus1_1.hashCode() == svplus1_2.hashCode()
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ShortValue/hashCode/hashcode001", + sHeader2 = "--> hashcode001: ", + sHeader3 = "##> hashcode001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ShortValue.hashCode.hashcode001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("hashcode001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsplus1_1 = execClass.fieldByName("plus1_1"); + Field fsplus1_2 = execClass.fieldByName("plus1_2"); + + ShortValue svplus1_1 = (ShortValue) execClass.getValue(fsplus1_1); + ShortValue svplus1_2 = (ShortValue) execClass.getValue(fsplus1_2); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (svplus1_1.hashCode() != svplus1_1.hashCode()) + expresult = 1; + break; + + case 1: if (svplus1_1.hashCode() != svplus1_2.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..092a529bc5e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ShortValue/hashCode/hashcode001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ShortValue. + * The test checks up that a result of the method + * com.sun.jdi.ShortValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this ShortValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.ShortValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.ShortValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ShortValue.hashCode.hashcode001 + * nsk.jdi.ShortValue.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ShortValue.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001a.java new file mode 100644 index 00000000000..1c52d8cf363 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/hashCode/hashcode001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ShortValue.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001a JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> hashcode001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> hashcode001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + +// public static short smallest = Short.MIN_VALUE; +// public static short zero = 0; +// public static short largest = Short.MAX_VALUE; + + public static short plus1_1 = +1; + public static short plus1_2 = +1; +// public static short minus1 = -1; + +// public static int intplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ShortValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ShortValue.value()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * public static short smallest = Short.MIN_VALUE;
    + * public static short zero = 0;
    + * public static short largest = Short.MAX_VALUE;
    + *
    + * which a debugger mirros as :
    + *
    + * ShortValue svsmallest;
    + * ShortValue svzero;
    + * ShortValue svlargest;
    + *
    + * the following is true:
    + *
    + * svsmallest == Short.MIN_VALUE
    + * svzero == 0
    + * svlargest == Short.MAX_VALUE
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ShortValue/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ShortValue.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("value001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fssmallest = execClass.fieldByName("smallest"); + Field fszero = execClass.fieldByName("zero"); + Field fslargest = execClass.fieldByName("largest"); + + ShortValue svsmallest = (ShortValue) execClass.getValue(fssmallest); + ShortValue svzero = (ShortValue) execClass.getValue(fszero); + ShortValue svlargest = (ShortValue) execClass.getValue(fslargest); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: if (svsmallest.value() != Short.MIN_VALUE) + expresult = 1; + break; + + case 1: if (svzero.value() != 0) + expresult = 1; + break; + + case 2: if (svlargest.value() != Short.MAX_VALUE) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001/TestDescription.java new file mode 100644 index 00000000000..f6a4b0e89aa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ShortValue/value/value001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ShortValue. + * The test checks up that a result of the method + * com.sun.jdi.ShortValue.value() + * complies with its spec: + * public short value() + * Returns this ShortValue as a short. + * Returns: the short mirrored by this object. + * The test works as follows: + * A debugger program - nsk.jdi.ShortValue.value.value001; + * a debuggee program - nsk.jdi.ShortValue.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ShortValue.value.value001 + * nsk.jdi.ShortValue.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ShortValue.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001a.java new file mode 100644 index 00000000000..82aa1a1979f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortValue/value/value001a.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.ShortValue.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + public static short smallest = Short.MIN_VALUE; + public static short zero = 0; + public static short largest = Short.MAX_VALUE; + +// public static short plus1_1 = +1; +// public static short plus1_2 = +1; +// public static short minus1 = -1; + +// public static int intplus1 = +1; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.StackFrame.setValue(Var, Object)
    + * com.sun.jdi.StackFrame.getValue(Var)
    + * for boundry values of primitive types
    + * + * Test checks up the following assertion:
    + * Primitive arguments must be either assignment compatible with
    + * the Var type or must be convertible to the Var type
    + * without loss of information.
    + * for every primitive type.
    + */ + +public class bounds001 extends ValueConversionDebugger { + + static class TestedVariableData { + String name; + ValueType type; + + TestedVariableData(String name, ValueType type) { + this.name = name; + this.type = type; + } + } + + private static TestedVariableData[] testedVars = { + new TestedVariableData("byteVar", BYTE), + new TestedVariableData("charVar", CHAR), + new TestedVariableData("doubleVar", DOUBLE), + new TestedVariableData("floatVar", FLOAT), + new TestedVariableData("intVar", INT), + new TestedVariableData("longVar", LONG), + new TestedVariableData("shortVar", SHORT) + }; + + private static byte [] byteVarValues = + {Byte.MIN_VALUE, + -1, + 0, + 1, + Byte.MAX_VALUE}; + private static char [] charVarValues = + {Character.MIN_VALUE, + Character.MAX_VALUE}; + private static double [] doubleVarValues = + {Double.NEGATIVE_INFINITY, + -1.5D, + -1.0D, + -0.0D, + +0.0D, + Double.MIN_VALUE, + 1.0D, + 1.5D, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY}; + private static float [] floatVarValues = + {Float.NEGATIVE_INFINITY, + -1.5F, + -1.0F, + -0.0F, + +0.0F, + Float.MIN_VALUE, + 1.0F, + 1.5F, + Float.MAX_VALUE, + Float.POSITIVE_INFINITY}; + private static int [] intVarValues = + {Integer.MIN_VALUE, + -1, + 0, + 1, + 1234567890, + Integer.MAX_VALUE}; + private static long [] longVarValues = + {Long.MIN_VALUE, + -1L, + 0L, + 1234567890123456789L, + 1L, + Long.MAX_VALUE}; + private static short [] shortVarValues = + {Short.MIN_VALUE, + -1, + 0, + 1, + Short.MAX_VALUE}; + + protected String debuggeeClassName() { + return bounds001a.class.getName(); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + return new bounds001().runIt(argv, out); + } + + protected void doTest() { + debuggee.suspend(); + + ThreadReference thread = debuggee.threadByName(bounds001a.TEST_THREAD_NAME); + StackFrame stackFrame = null; + try { + for (int i = 0; i < thread.frameCount(); i++) { + stackFrame = thread.frame(i); + if (stackFrame.location().method().name().equals("run") ) { + break; + } + } + } catch (IncompatibleThreadStateException e) { + complain("Unexpected " + e); + setSuccess(false); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + Location loc = stackFrame.location(); + display("StackFrame: " + loc.declaringType().name()); + display(" method: " + loc.method().name()); + display(""); + + PrimitiveValue retValue, value; + Object arr = null; + boolean validConversion; + + LocalVariable var = null; + for (TestedVariableData testedVar : testedVars) { + try { + var = stackFrame.visibleVariableByName(testedVar.name); + } catch (AbsentInformationException e) { + complain("Unexpected " + e); + setSuccess(false); + continue; + } + display("LocalVariable: " + var.name()); + display("======================"); + for (ValueType type : ValueType.values()) { + switch (type) { + case BYTE: + arr = byteVarValues; + display("byte values"); + break; + case CHAR: + arr = charVarValues; + display("char values"); + break; + case DOUBLE: + arr = doubleVarValues; + display("double values"); + break; + case FLOAT: + arr = floatVarValues; + display("float values"); + break; + case INT: + arr = intVarValues; + display("integer values"); + break; + case LONG: + arr = longVarValues; + display("long values"); + break; + case SHORT: + arr = shortVarValues; + display("short values"); + break; + default: + complain("***TEST CASE ERROR***"); + setSuccess(false); + continue; + } + display("-----------------"); + for (int i = 0; i < Array.getLength(arr); i++) { + value = createValue(arr, i); + validConversion = isValidConversion(testedVar.type, value); + display(">value = " + value.toString()); + try { + stackFrame.setValue(var, value); + if (!validConversion) { + complain(lastConversion); + complain("***InvalidTypeException is not thrown***"); + display(""); + setSuccess(false); + continue; + } + retValue = (PrimitiveValue )stackFrame.getValue(var); + + checkValueConversion(value, retValue); + } catch(InvalidTypeException e) { + if (validConversion) { + complain(lastConversion); + complain("*** unexpected InvalidTypeException***"); + display(""); + setSuccess(false); + } else { + display(lastConversion); + display("!!!expected InvalidTypeException"); + display(""); + } + } catch(Exception e) { + complain("unexpected " + e); + display(""); + setSuccess(false); + } + } + display(""); + } + } + + display("============="); + display("TEST FINISHES\n"); + + debuggee.resume(); + + pipe.println(bounds001a.COMMAND_STOP_TEST_THREAD); + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001/TestDescription.java new file mode 100644 index 00000000000..c47f4b906f8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/_bounds_/bounds001. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-6604963 + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the methods: + * com.sun.jdi.StackFrame.setValue(Field, Object) + * com.sun.jdi.StackFrame.getValue(Field) + * for boundry values of primitive types + * Test checks up the following assertion: + * Primitive arguments must be either assignment compatible with + * the field type or must be convertible to the field type + * without loss of information. + * for every primitive type. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame._bounds_.bounds001 + * nsk.jdi.StackFrame._bounds_.bounds001a + * + * @comment make sure bounds001a is compiled with full debug info + * @clean nsk.jdi.StackFrame._bounds_.bounds001a + * @compile -g:lines,source,vars ../bounds001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame._bounds_.bounds001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001a.java new file mode 100644 index 00000000000..7362c558c79 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds001a.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.StackFrame._bounds_; + +import nsk.share.jdi.*; + +/** + * bounds001a is deugee's part of the bounds001. + */ +public class bounds001a extends AbstractJDIDebuggee { + + static public final String COMMAND_STOP_TEST_THREAD = "COMMAND_STOP_TEST_THREAD"; + + static public final String TEST_THREAD_NAME = "nsk.jdi.StackFrame._bounds_.bounds001a_TestThread"; + + class TestThread extends Thread { + boolean started; + + TestThread() { + super(TEST_THREAD_NAME); + } + + public void run() { + /* + * Local variables required by debugger + */ + byte byteVar = 0; + char charVar = ' '; + double doubleVar = 0; + float floatVar = 0; + int intVar = 0; + long longVar = 0; + short shortVar = 0; + + started = true; + + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + // expected exception + } + } + } + + private TestThread testThread; + + protected String[] doInit(String[] args) { + testThread = new TestThread(); + testThread.start(); + + while (!testThread.started) + Thread.yield(); + + return super.doInit(args); + } + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_STOP_TEST_THREAD)) { + testThread.interrupt(); + try { + log.display("Wait for test thread: " + testThread); + testThread.join(); + } catch (InterruptedException e) { + unexpectedException(e); + } + + return true; + } + + return false; + } + + public static void main (String args[]) { + new bounds001a().doTest(args); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002.java new file mode 100644 index 00000000000..acd9db249ed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.StackFrame._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up StackFrame methods for the following cases:
    + * - getValue(null)
    + * - getValues(null)
    + * - getValues(list with size = 0)
    + * - setValue(null, null)
    + * - setValue(field, null)
    + * - visibleVariableByName(null)
    + * - visibleVariableByName("")
    + * NullPointerException is expected for every test case + * except for the three last. + */ + +public class bounds002 { + + private final static String prefix = "nsk.jdi.StackFrame._bounds_."; + private final static String debuggerName = prefix + "bounds002"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + bounds002 thisTest = new bounds002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + ThreadReference thread = debugee.threadByName("main"); + StackFrame stackFrame = null; + try { + for (int i = 0; i < thread.frameCount(); i++) { + stackFrame = thread.frame(i); + if (stackFrame.location().method().name().equals("main") ) { + break; + } + } + } catch (IncompatibleThreadStateException e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + Location loc = stackFrame.location(); + try { + display("StackFrame: " + loc.sourcePath()); + display(" method: " + loc.method().name()); + } catch (AbsentInformationException e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + return; + } + display(""); + + Value retValue; + + display("getValue(null)"); + try { + retValue = stackFrame.getValue(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("getValues(null)"); + try { + stackFrame.getValues(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + List lst = null; + display("getValues(list with size = 0)"); + try { + stackFrame.getValues(lst); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("setValue(null, null)"); + try { + stackFrame.setValue(null, null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("setValue(variable, null)"); + LocalVariable var = null; + try { + var = stackFrame.visibleVariableByName(bounds002a.testedFieldName); + } catch (AbsentInformationException e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + try { + stackFrame.setValue(var, null); + display("OK"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("visibleVariableByName(null)"); + try { + var = stackFrame.visibleVariableByName(null); + if (var != null ) { + complain("Unexpected local variable "); + exitStatus = Consts.TEST_FAILED; + } else { + display("OK"); + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("visibleVariableByName(\"\")"); + try { + var = stackFrame.visibleVariableByName(""); + if (var != null ) { + complain("Unexpected local variable \"\""); + exitStatus = Consts.TEST_FAILED; + } else { + display("OK"); + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002/TestDescription.java new file mode 100644 index 00000000000..3d0f0cd5768 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/_bounds_/bounds002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the methods com.sun.jdi.StackFrame + * for the following cases: + * - getValue(null) + * - getValues(null) + * - getValues(list with size = 0) + * - setValue(null, null) + * - setValue(field, null) + * - visibleVariableByName(null) + * - visibleVariableByName("") + * NullPointerException is expected for every test case except for + * the three last. + * In cases + * setValue(field, null) + * visibleVariableByName(null) + * visibleVariableByName("") + * no exception is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame._bounds_.bounds002 + * nsk.jdi.StackFrame._bounds_.bounds002a + * + * @comment make sure bounds002a is compiled with full debug info + * @clean nsk.jdi.StackFrame._bounds_.bounds002a + * @compile -g:lines,source,vars ../bounds002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame._bounds_.bounds002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002a.java new file mode 100644 index 00000000000..097a82cbd2d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/_bounds_/bounds002a.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.StackFrame._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * bounds002a is deugee's part of the bounds002. + */ +public class bounds002a { + + public final static String testedFieldName = "testedObj"; + + public static void main (String argv[]) { + bounds002b testedObj = new bounds002b(); + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(bounds002.SGNL_READY); + String instr = pipe.readln(); + if (instr.equals(bounds002.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class bounds002b { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001.java new file mode 100644 index 00000000000..dafba15cb59 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that method 'StackFrame.getArgumentValues()' returns the values of all arguments in this frame. + * Test calls 'StackFrame.getArgumentValues()' for following methods: + * - methods receiving as argument single argument of primitive type + * - method receiving as argument Object + * - method receiving as argument String + * - method without arguments + * - method receiving all primitive types and Object as arguments + * - method receiving arrays of all primitive types and Object array as arguments + * - method receiving multidimensional arrays of all primitive types and Object multidimensional array as arguments + * - method with single arument, method changes argument several times + * - method with several arguments, arguments are changed in loop many times + * - static method receiving all primitive types and Object as arguments + * - static method with single arument, method changes argument several times + * - static method with several arguments, arguments are changed in loop many times + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.getArgumentValues.getArgumentValues001.getArgumentValues001 + * nsk.jdi.StackFrame.getArgumentValues.getArgumentValues001.getArgumentValues001a + * + * @comment make sure getArgumentValues001a is compiled with full debug info + * @clean nsk.jdi.StackFrame.getArgumentValues.getArgumentValues001.getArgumentValues001a + * @compile -g:lines,source,vars getArgumentValues001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.getArgumentValues.getArgumentValues001.getArgumentValues001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.StackFrame.getArgumentValues.getArgumentValues001; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.*; +import nsk.share.jdi.*; + +/* + * Test checks that method 'StackFrame.getArgumentValues()' returns the values of all arguments in this frame. + * + * Test checks method 'getArgumentValues()' using special class 'getArgumentValues001a.TestClass'. This class + * contains methods with various arguments and contains static array 'testLocations' with information about + * locations intended for breakpoints, before executing code at this locations debuggee saves values of current + * method arguments at special static array 'TestClass.expectedArgumentValues'. + * Debugger creates BreakpointRequests for test locations using infromation from 'TestClass.testLocations', + * starts thread listening BreakpointEvents and forces debuggee to execute methods of 'getArgumentValues001a.TestClass'. + * When BreakpointEvent is received debugger obtains StackFrame for current frame of thread which was stoped by breakpoint, + * then debugger obtains expected argument values from static array 'TestClass.expectedArgumentValues' and compares + * expected values with values returned by method 'StackFrame.getArgumentValues()'. + */ +public class getArgumentValues001 extends TestDebuggerType2 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getArgumentValues001().runIt(argv, out); + } + + protected String debuggeeClassName() { + return getArgumentValues001a.class.getName(); + } + + private Value extractValue(Value value) { + if (value == null) + return value; + + String valueClassName = getArgumentValues001a.Value.class.getName(); + + /* if value is instance of 'getArgumentValues001a.Value' extact primitive type value + * (name of primitive type is stored in field 'name' and primitive type value is stored + * in field with name "Value") + */ + if (value.type().name().equals(valueClassName)) { + ReferenceType valueClass = debuggee.classByName(valueClassName); + + Field typeNameField = valueClass.fieldByName("name"); + String typeName = ((StringReference)((ObjectReference)value).getValue(typeNameField)).value(); + + Field valueField = valueClass.fieldByName(typeName + "Value"); + + return ((ObjectReference)value).getValue(valueField); + } else + return value; + } + + // print information about expected and actual argument values + void printDebugInfo(List values, ArrayReference expectedValues) { + log.display("Values:"); + int i = 0; + for (Value value : values) { + log.display("Value " + i + ": " + value); + i++; + } + log.display("Expected values:"); + for (i = 0; i < expectedValues.length(); i++) { + log.display("Value " + i + ": " + extractValue(expectedValues.getValue(i))); + } + } + + // information about BreakpointEvents generated by debuggee VM + static class BreakpointData { + + public BreakpointData(BreakpointRequest request, int breakpointsNumber) { + this.request = request; + this.breakpointsNumber = breakpointsNumber; + } + + // breakpoint request + BreakpointRequest request; + // how events are generated for request + int breakpointsNumber; + } + + private Location getLocation(ReferenceType referenceType, int lineNumber) throws AbsentInformationException { + for (Location location : referenceType.allLineLocations()) { + if (location.lineNumber() == lineNumber) + return location; + } + + throw new TestBug("Can't find location with lineNumber = " + lineNumber + " for class " + referenceType); + } + + public void doTest() { + List requests = new ArrayList(); + + ReferenceType referenceType = debuggee.classByName(getArgumentValues001a.TestClass.class.getName()); + try { + // array 'getArgumentValues001a.TestClass.testLocations' contains infromation about BreakpointEvents + // which will be generated during test, create List of BreakpointData based on this information + for (getArgumentValues001a.LocationData locationData : getArgumentValues001a.TestClass.testLocations) { + BreakpointRequest request = debuggee.getEventRequestManager().createBreakpointRequest(getLocation(referenceType, locationData.lineNumber)); + request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + requests.add(new BreakpointData(request, locationData.breakpointsNumber)); + request.enable(); + } + } catch (AbsentInformationException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + return; + } + + boolean testThreadStarted = false; + ThreadReference testThread = null; + + try { + for (BreakpointData requestData : requests) { + + for (int i = 0; i < requestData.breakpointsNumber; i++) { + // start thread wich waits next event generated for given EventRequest + EventListenerThread listenerThread = new EventListenerThread(requestData.request); + listenerThread.start(); + listenerThread.waitStartListen(); + + // if thread wasn't started start it + if (!testThreadStarted) { + pipe.println(getArgumentValues001a.COMMAND_START_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + testThreadStarted = true; + } else + testThread.resume(); + + // wait for next BreakpointEvent + BreakpointEvent event = (BreakpointEvent)listenerThread.getEvent(); + + // expected argument values are stored in special static array 'expectedArgumentValues' + ArrayReference expectedArgValues = (ArrayReference)referenceType.getValue(referenceType.fieldByName("expectedArgumentValues")); + + // get current frame + StackFrame frame = event.thread().frame(0); + List values = frame.getArgumentValues(); + System.out.println("Total values: " + values.size()); + + if (expectedArgValues.length() != values.size()) { + setSuccess(false); + log.complain("Unexpected arguments number: " + values.size() + ", expected number is " + expectedArgValues.length()); + printDebugInfo(values, expectedArgValues); + continue; + } else { + for (int j = 0; j < values.size(); j++) { + Value value = values.get(j); + // values for primitive types are wrapped in special class 'getArgumentValues001a.Value' and + // real value should be extracted before comparing + Value expectedValue = extractValue(expectedArgValues.getValue(j)); + + boolean success; + + if (expectedValue == null) { + success = (value == null); + } else { + success = expectedValue.equals(value); + } + + if (!success) { + setSuccess(false); + log.complain("Unexpected argument value: " + value + ", expected value: " + expectedValue); + printDebugInfo(values, expectedArgValues); + continue; + } + } + } + + if (testThread == null) + testThread = event.thread(); + } + + } + } catch (Throwable t) { + setSuccess(false); + log.complain("Unexpected exception: " + t); + t.printStackTrace(log.getOutStream()); + return; + } + + if (testThread != null) + testThread.resume(); + + pipe.println(getArgumentValues001a.COMMAND_STOP_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001a.java new file mode 100644 index 00000000000..d88268c4690 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues001/getArgumentValues001a.java @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.StackFrame.getArgumentValues.getArgumentValues001; + +import java.util.*; +import nsk.share.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/* + * Debugee class, starts thread which executes methods with various arguments. + * + * !!! Edit carefully, array 'getArgumentValues001a.TestClass.testLocations' contains hardcored line numbers !!! + */ +public class getArgumentValues001a extends AbstractJDIDebuggee { + + // class contains methods with different arguments + static class TestClass { + + Log log; + + TestClass(Log log) { + this.log = log; + } + + static List testLocations = new ArrayList(); + + static Object expectedArgumentValues[]; + + // methods receiving as arguments all possible primitive types + + void testMethod1(boolean arg1) { + log.display("testMethod1"); // testLocations.at(0) + } + + void testMethod2(byte arg1) { + log.display("testMethod2"); // testLocations.at(1) + } + + void testMethod3(short arg1) { + log.display("testMethod3"); // testLocations.at(2) + } + + void testMethod4(char arg1) { + log.display("testMethod4"); // testLocations.at(3) + } + + void testMethod5(int arg1) { + log.display("testMethod5"); // testLocations.at(4) // // testLocations.at(13) + } + + void testMethod6(long arg1) { + log.display("testMethod6"); // testLocations.at(5) + } + + void testMethod7(float arg1) { + log.display("testMethod7"); // testLocations.at(6) + } + + void testMethod8(double arg1) { + log.display("testMethod8"); // testLocations.at(7) + } + + // method receiving Object as argument + void testMethod9(Object object) { + log.display("testMethod9"); // testLocations.at(8) + } + + // method receiving String as argument + void testMethod10(String object) { + log.display("testMethod10"); // testLocations.at(9) + } + + // method receiving TestClass as argument + void testMethod11(TestClass object) { + log.display("testMethod11"); // testLocations.at(10) + } + + // method without arguments + void testMethod12() { + log.display("testMethod12"); // testLocations.at(11) + } + + // method receiving all primitive type and Object as arguments + void testMethod13(boolean arg1, byte arg2, short arg3, char arg4, int arg5, long arg6, float arg7, double arg8, Object arg9) { + log.display("testMethod13"); // testLocations.at(12) + } + + // method with single arument changes argument's value several times + void testMethod14(int arg1) { + log.display("testMethod14"); // testLocations.at(14) + arg1++; + TestClass.expectedArgumentValues = new Object[] { new Value(arg1) }; + log.display("testMethod14"); // testLocations.at(15) + arg1--; + TestClass.expectedArgumentValues = new Object[] { new Value(arg1) }; + log.display("testMethod14"); // testLocations.at(16) + arg1 = 0; + TestClass.expectedArgumentValues = new Object[] { new Value(arg1) }; + log.display("testMethod14"); // testLocations.at(17) + } + + // method with several arguments changes its values in loop + void testMethod15(int arg1, float arg2, Object arg3) { + long v1 = (long)(arg1 + arg2); + for (int i = 0; i < 10; i++) { + arg1 = (int)(i * arg2 - v1); + arg2 += 1; + arg2 += v1; + arg3 = (i % 2 == 0) ? null : new Object(); + TestClass.expectedArgumentValues = new Object[] { new Value(arg1), new Value(arg2), arg3}; + log.display("testMethod15"); // testLocations.at(18) + } + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + arg1 = (int)(i * arg2 + j + v1); + arg2 += i; + arg3 = arg1 + " " + arg2; + TestClass.expectedArgumentValues = new Object[] { new Value(arg1), new Value(arg2), arg3}; + log.display("testMethod15"); // testLocations.at(19) + } + } + } + + // static method with different arguments + static void testMethod16(Log log, boolean arg1, short arg2, char arg3, int arg4, long arg5, float arg6, double arg7, Object arg8) { + log.display("testMethod16"); // testLocations.at(20) + } + + // static method changing argument value + static void testMethod17(Log log, int arg1) { + log.display("testMethod17"); // testLocations.at(21) + arg1++; + TestClass.expectedArgumentValues = new Object[] { log, new Value(arg1) }; + log.display("testMethod17"); // testLocations.at(22) + arg1--; + TestClass.expectedArgumentValues = new Object[] { log, new Value(arg1) }; + log.display("testMethod17"); // testLocations.at(23) + arg1 = 0; + TestClass.expectedArgumentValues = new Object[] { log, new Value(arg1) }; + log.display("testMethod17"); // testLocations.at(24) + } + + // static method changing arguments in loop + static void testMethod18(Log log, int arg1, float arg2, Object arg3) { + long v1 = (long)(arg1 + arg2); + for (int i = 0; i < 10; i++) { + arg1 = (int)(i * arg2 - v1); + arg2 += 1; + arg2 += v1; + arg3 = (i % 2 == 0) ? null : new Object(); + TestClass.expectedArgumentValues = new Object[] { log, new Value(arg1), new Value(arg2), arg3}; + log.display("testMethod18"); // testLocations.at(25) + } + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + arg1 = (int)(i * arg2 + j + v1); + arg2 += i; + arg3 = arg1 + " " + arg2; + TestClass.expectedArgumentValues = new Object[] { log, new Value(arg1), new Value(arg2), arg3}; + log.display("testMethod18"); // testLocations.at(26) + } + } + } + + // method receiving arrays as arguments + void testMethod19(boolean[] arg1, byte[] arg2, short[] arg3, char[] arg4, int[] arg5, long[] arg6, float[] arg7, double[] arg8, Object[] arg9) { + log.display("testMethod19"); // testLocations.at(27) + } + + // method receiving multidimensional arrays as arguments + void testMethod20(boolean[][][] arg1, byte[][][] arg2, short[][][] arg3, char[][][] arg4, int[][][] arg5, long[][][] arg6, float[][][] arg7, double[][][] arg8, Object[][][] arg9) { + log.display("testMethod20"); // testLocations.at(28) + } + + static { + // primitive values + testLocations.add(new LocationData(54, 1)); + testLocations.add(new LocationData(58, 1)); + testLocations.add(new LocationData(62, 1)); + testLocations.add(new LocationData(66, 1)); + testLocations.add(new LocationData(70, 1)); + testLocations.add(new LocationData(74, 1)); + testLocations.add(new LocationData(78, 1)); + testLocations.add(new LocationData(82, 1)); + + // objects + testLocations.add(new LocationData(87, 1)); + testLocations.add(new LocationData(92, 1)); + testLocations.add(new LocationData(97, 1)); + + // method without args + testLocations.add(new LocationData(102, 1)); + + // method with many arguments + testLocations.add(new LocationData(107, 1)); + + // method 'testMethod5' is called 50 times + testLocations.add(new LocationData(70, 50)); + + // method 3 times changes argument value + testLocations.add(new LocationData(112, 1)); + testLocations.add(new LocationData(115, 1)); + testLocations.add(new LocationData(118, 1)); + testLocations.add(new LocationData(121, 1)); + + // method changes arguments in loop + testLocations.add(new LocationData(133, 10)); + testLocations.add(new LocationData(141, 25)); + + // static method with many arguments + testLocations.add(new LocationData(148, 1)); + + // static method 3 times changes argument value + testLocations.add(new LocationData(153, 1)); + testLocations.add(new LocationData(156, 1)); + testLocations.add(new LocationData(159, 1)); + testLocations.add(new LocationData(162, 1)); + + // static method changes arguments in loop + testLocations.add(new LocationData(174, 10)); + testLocations.add(new LocationData(182, 25)); + + // arrays + testLocations.add(new LocationData(189, 1)); + + // multidimensional arrays + testLocations.add(new LocationData(194, 1)); + } + } + + public static void main(String args[]) { + new getArgumentValues001a().doTest(args); + } + + static class LocationData { + + public LocationData(int lineNumber, int breakpointsNumber) { + this.lineNumber = lineNumber; + this.breakpointsNumber = breakpointsNumber; + } + + public int breakpointsNumber; + + public int lineNumber; + } + + /* + * This class used to store primitive type values, storing type name is stored in + * field type and value is stored in field 'Value' + */ + static class Value { + boolean booleanValue; + + byte byteValue; + + short shortValue; + + char charValue; + + int intValue; + + long longValue; + + float floatValue; + + double doubleValue; + + String name; + + Value(boolean value) { + name = "boolean"; + booleanValue = value; + } + + Value(byte value) { + name = "byte"; + byteValue = value; + } + + Value(short value) { + name = "short"; + shortValue = value; + } + + Value(char value) { + name = "char"; + charValue = value; + } + + Value(int value) { + name = "int"; + intValue = value; + } + + Value(long value) { + name = "long"; + longValue = value; + } + + Value(float value) { + name = "float"; + floatValue = value; + } + + Value(double value) { + name = "double"; + doubleValue = value; + } + } + + public static final String COMMAND_START_TEST_THREAD = "COMMAND_START_TEST_THREAD"; + + public static final String COMMAND_STOP_TEST_THREAD = "COMMAND_STOP_TEST_THREAD"; + + public String[] doInit(String args[]) { + args = super.doInit(args); + + try { + Class.forName(TestClass.class.getName()); + } catch (Throwable t) { + setSuccess(false); + System.out.println("Unexpected exception during initialization: " + t); + t.printStackTrace(); + throw new TestBug("Unexpected exception during initialization: " + t); + } + + return args; + } + + class TestThread extends Thread { + public void run() { + TestClass testClass = new TestClass(log); + + TestClass.expectedArgumentValues = new Object[] { new Value(true) }; + testClass.testMethod1(true); + + TestClass.expectedArgumentValues = new Object[] { new Value((byte)10) }; + testClass.testMethod2((byte) 10); + + TestClass.expectedArgumentValues = new Object[] { new Value((short) 10) }; + testClass.testMethod3((short) 10); + + TestClass.expectedArgumentValues = new Object[] { new Value((char) 10) }; + testClass.testMethod4((char) 10); + + TestClass.expectedArgumentValues = new Object[] { new Value((int) 10) }; + testClass.testMethod5((int) 10); + + TestClass.expectedArgumentValues = new Object[] { new Value((long) 10) }; + testClass.testMethod6((long) 10); + + TestClass.expectedArgumentValues = new Object[] { new Value((float) 10) }; + testClass.testMethod7((float) 10); + + TestClass.expectedArgumentValues = new Object[] { new Value((double) 10) }; + testClass.testMethod8((double) 10); + + Object arg = new Object(); + TestClass.expectedArgumentValues = new Object[] { arg }; + testClass.testMethod9(arg); + + arg = "String"; + TestClass.expectedArgumentValues = new Object[] { arg }; + testClass.testMethod10((String) arg); + + arg = testClass; + TestClass.expectedArgumentValues = new Object[] { arg }; + testClass.testMethod11((TestClass) arg); + + TestClass.expectedArgumentValues = new Object[] {}; + testClass.testMethod12(); + + arg = new Object(); + TestClass.expectedArgumentValues = new Object[] { new Value(false), new Value((byte) 0), new Value((short) 1), new Value((char) 2), new Value(3), + new Value((long) 4), new Value((float) 5), new Value((double) 6), arg }; + testClass.testMethod13(false, (byte) 0, (short) 1, (char) 2, 3, 4, 5, 6, arg); + + for (int i = 0; i < 50; i++) { + int intArg = 50 + i; + TestClass.expectedArgumentValues = new Object[] { new Value(intArg) }; + testClass.testMethod5(intArg); + } + + TestClass.expectedArgumentValues = new Object[] { new Value((int) 10) }; + testClass.testMethod14(10); + + testClass.testMethod15(11, 0.1f, new Object()); + + arg = new Object(); + TestClass.expectedArgumentValues = new Object[] { log, new Value(false), new Value((short) 1), new Value((char) 2), new Value(3), + new Value((long) 4), new Value((float) 5), new Value((double) 6), arg }; + TestClass.testMethod16(log, false, (short) 1, (char) 2, 3, 4, 5, 6, arg); + + TestClass.expectedArgumentValues = new Object[] {log, new Value((int) 10) }; + TestClass.testMethod17(log, 10); + + TestClass.testMethod18(log, 11, 0.1f, new Object()); + + { + boolean[] arg1 = {}; + byte[] arg2 = {}; + short[] arg3 = {}; + char[] arg4 = {}; + int[] arg5 = {}; + long[] arg6 = {}; + float[] arg7 = {}; + double[] arg8 = {}; + Object[] arg9 = {}; + TestClass.expectedArgumentValues = new Object[] {arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9}; + testClass.testMethod19(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + { + boolean[][][] arg1 = {}; + byte[][][] arg2 = {}; + short[][][] arg3 = {}; + char[][][] arg4 = {}; + int[][][] arg5 = {}; + long[][][] arg6 = {}; + float[][][] arg7 = {}; + double[][][] arg8 = {}; + Object[][][] arg9 = {}; + TestClass.expectedArgumentValues = new Object[] {arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9}; + testClass.testMethod20(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + } + } + + private TestThread testThread; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_TEST_THREAD)) { + + if (testThread != null) + throw new TestBug("Thread is already created"); + + testThread = new TestThread(); + testThread.start(); + + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREAD)) { + + if (testThread == null) + throw new TestBug("Thread isn't created"); + + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + return true; + } + + return false; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java new file mode 100644 index 00000000000..3cae2654b01 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that method 'StackFrame.getArgumentValues()' returns the values of all arguments in this frame. + * The test checks case when thread has stack with 300 frames and checks result of 'StackFrame.getArgumentValues()' for + * all thread's frames. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.getArgumentValues.getArgumentValues002.getArgumentValues002 + * nsk.jdi.StackFrame.getArgumentValues.getArgumentValues002.getArgumentValues002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.getArgumentValues.getArgumentValues002.getArgumentValues002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.StackFrame.getArgumentValues.getArgumentValues002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.*; + +/* + * Test checks that method 'StackFrame.getArgumentValues()' returns the values of all arguments in this frame. + * Test checks case when thread has stack with many frames: + * - debuggee starts test thread which using recursion creates stack frame containing 300 frames + * - debugger suspends test thread and for each frame of this thread calls method 'StackFrame.getArgumentValues()' and + * compares returned values with expected. + */ +public class getArgumentValues002 extends TestDebuggerType2 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getArgumentValues002().runIt(argv, out); + } + + protected String debuggeeClassName() { + return getArgumentValues002a.class.getName(); + } + + public void doTest() { + pipe.println(getArgumentValues002a.COMMAND_START_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + ThreadReference testThread = debuggee.threadByName(getArgumentValues002a.testThreadName); + testThread.suspend(); + try { + for (int i = 0; i < testThread.frameCount(); i++) { + boolean success = true; + StackFrame frame = testThread.frame(i); + List values = frame.getArgumentValues(); + + // last frame if method Thread.run() + if (i == testThread.frameCount() - 1) { + if (values.size() != 0) { + success = false; + log.complain("ERROR: unexpected values count: " + values.size() + ", expected is 0"); + } + } else { + // StackFrame should have argument equals to it serial number (look at code of getArgumentValues002a.TreadThread for details) + Value expectedValue = vm.mirrorOf((int) i); + + log.display("Expected value: " + expectedValue); + + if (values.size() != 1) { + success = false; + log.complain("ERROR: unexpected values count: " + values.size() + ", expected is 1"); + } else { + if (!values.get(0).equals(expectedValue)) { + success = false; + log.complain("ERROR: unexpected value: " + values.get(0) + ", expected is " + expectedValue); + } + } + } + + if (!success) { + setSuccess(false); + log.complain("Returned values:"); + for (Value value : values) { + log.complain("" + value); + } + } else { + log.display("OK"); + } + } + } catch (Throwable t) { + setSuccess(false); + log.complain("Unexpected exception: " + t); + t.printStackTrace(log.getOutStream()); + } finally { + testThread.resume(); + } + + pipe.println(getArgumentValues002a.COMMAND_STOP_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002a.java new file mode 100644 index 00000000000..5b0d6341fea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.StackFrame.getArgumentValues.getArgumentValues002; + +import nsk.share.TestBug; +import nsk.share.jdi.*; + +// Debuggee class, starts test thread which has stack with many frames +public class getArgumentValues002a extends AbstractJDIDebuggee { + + public static final String COMMAND_START_TEST_THREAD = "COMMAND_START_TEST_THREAD"; + + public static final String COMMAND_STOP_TEST_THREAD = "COMMAND_STOP_TEST_THREAD"; + + public static final String testThreadName = "getArgumentValues002a_TestThread"; + + class TestThread extends Thread { + + volatile boolean stackWasCreated; + + volatile boolean stoped; + + public TestThread() { + super(testThreadName); + } + + public void run() { + recursiveMethod1(300); + } + + void recursiveMethod1(int arg1) { + log.display("recursiveMethod1: " + arg1); + if (arg1 > 0) { + if (arg1 % 3 == 0) + recursiveMethod3(arg1 - 1); + else if (arg1 % 3 == 1) + recursiveMethod2(arg1 - 1); + else + recursiveMethod1(arg1 - 1); + } + else { + stackWasCreated = true; + while (!stoped); + } + } + + void recursiveMethod2(int arg1) { + log.display("recursiveMethod2: " + arg1); + if (arg1 > 0) { + if (arg1 % 3 == 0) + recursiveMethod3(arg1 - 1); + else if (arg1 % 3 == 1) + recursiveMethod2(arg1 - 1); + else + recursiveMethod1(arg1 - 1); + } + else { + stackWasCreated = true; + while (!stoped); + } + } + + void recursiveMethod3(int arg1) { + log.display("recursiveMethod3: " + arg1); + if (arg1 > 0) { + if (arg1 % 3 == 0) + recursiveMethod3(arg1 - 1); + else if (arg1 % 3 == 1) + recursiveMethod2(arg1 - 1); + else + recursiveMethod1(arg1 - 1); + } + else { + stackWasCreated = true; + while (!stoped); + } + } + } + + private TestThread testThread; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_TEST_THREAD)) { + + if (testThread != null) + throw new TestBug("Thread is already created"); + + testThread = new TestThread(); + testThread.start(); + while (!testThread.stackWasCreated) + Thread.yield(); + + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREAD)) { + + if (testThread == null) + throw new TestBug("Thread isn't created"); + + testThread.stoped = true; + + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + return true; + } + + return false; + } + + public static void main(String args[]) { + new getArgumentValues002a().doTest(args); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java new file mode 100644 index 00000000000..0250b95d1ef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that method 'StackFrame.getArgumentValues()' throws InvalidStackFrameException if this stack + * frame has become invalid. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.getArgumentValues.getArgumentValues003.getArgumentValues003 + * nsk.jdi.StackFrame.getArgumentValues.getArgumentValues003.getArgumentValues003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.getArgumentValues.getArgumentValues003.getArgumentValues003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.StackFrame.getArgumentValues.getArgumentValues003; + +import java.io.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.*; + +/* + * Test checks that method 'StackFrame.getArgumentValues()' throws InvalidStackFrameException if this stack + * frame has become invalid (once the frame's thread is resumed, the stack frame is no longer valid). + * + * Test obtains ThreadReference for debuggee test thread, suspends test thread, obtains StackFrame instance for current + * thread frame, calls StackFrame.getArgumentValues() first time and checks that no exception is thrown. Then debugger + * resumes test thread, calls getArgumentValues again and checks that in this case InvalidStackFrameException is thrown. + */ +public class getArgumentValues003 extends TestDebuggerType2 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getArgumentValues003().runIt(argv, out); + } + + protected String debuggeeClassName() { + return getArgumentValues003a.class.getName(); + } + + public void doTest() { + pipe.println(getArgumentValues003a.COMMAND_START_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + ThreadReference testThread = debuggee.threadByName(getArgumentValues003a.testThreadName); + testThread.suspend(); + try { + StackFrame frame = testThread.frame(0); + log.display("Call getArgumentValues()"); + frame.getArgumentValues(); + log.display("OK"); + log.display("Resume thread"); + testThread.resume(); + log.display("Call getArgumentValues()"); + try { + frame.getArgumentValues(); + setSuccess(false); + log.complain("Expected InvalidStackFrameException was not thrown"); + } catch (InvalidStackFrameException e) { + log.display("Expected InvalidStackFrameException was thrown"); + } + } catch (Throwable t) { + setSuccess(false); + log.complain("Unexpected exception: " + t); + t.printStackTrace(log.getOutStream()); + } finally { + if (testThread.isSuspended()) + testThread.resume(); + } + + pipe.println(getArgumentValues003a.COMMAND_STOP_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003a.java new file mode 100644 index 00000000000..1dccef59b38 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.StackFrame.getArgumentValues.getArgumentValues003; + +import nsk.share.TestBug; +import nsk.share.jdi.*; + +//Debuggee class, handles command to start and stop test thread +public class getArgumentValues003a extends AbstractJDIDebuggee { + + public static final String COMMAND_START_TEST_THREAD = "COMMAND_START_TEST_THREAD"; + + public static final String COMMAND_STOP_TEST_THREAD = "COMMAND_STOP_TEST_THREAD"; + + public static final String testThreadName = "getArgumentValues003a_TestThread"; + + class TestThread extends Thread { + + volatile boolean stackWasCreated; + + volatile boolean stoped; + + public TestThread() { + super(getArgumentValues003a.testThreadName); + } + + public void run() { + stackWasCreated = true; + + while (!stoped); + } + } + + private TestThread testThread; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_TEST_THREAD)) { + + if (testThread != null) + throw new TestBug("Thread is already created"); + + testThread = new TestThread(); + testThread.start(); + + while (!testThread.stackWasCreated) + Thread.yield(); + + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREAD)) { + + if (testThread == null) + throw new TestBug("Thread isn't created"); + + testThread.stoped = true; + + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + return true; + } + + return false; + } + + public static void main(String args[]) { + new getArgumentValues003a().doTest(args); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001.java new file mode 100644 index 00000000000..2072cf7d267 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001.java @@ -0,0 +1,749 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.getValue()
    + * complies with its spec in case when a tested program
    + * is prepared with full information (see README file),
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * 1) After getting a thread2 suspended but before to resume it,
    + * StackFrame.getValue() is used for getting and
    + * checking up the values of visible variables,
    + * local in a tested method, two for each PrimitiveType;
    + * 2) After resuming the thread2, the method StackFrame.getValue() is
    + * invoked second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class getvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/getValue/getvalue001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.getValue.getvalue001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.getValue.Threadgetvalue001a"; + + //String mName = "nsk.jdi.StackFrame.getValue"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("getvalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + // BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting thread2's StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + // StackFrame stackFrame is ready for testing + + String bl1 = "bl1", bl2 = "bl2"; + String bt1 = "bt1", bt2 = "bt2"; + String ch1 = "ch1", ch2 = "ch2"; + String db1 = "db1", db2 = "db2"; + String fl1 = "fl1", fl2 = "fl2"; + String in1 = "in1", in2 = "in2"; + String ln1 = "ln1", ln2 = "ln2"; + String sh1 = "sh1", sh2 = "sh2"; + + String ini0 = "i0"; + + + for ( int i3 = 0; i3 < 8; i3++) { + + try { + + switch (i3) { + + case 0: BooleanValue blv1 = null; + BooleanValue blv2 = null; + + locvar1 = stackFrame.visibleVariableByName(bl1); + locvar2 = stackFrame.visibleVariableByName(bl2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Boolean"); + expresult = returnCode1; + break; + } + + blv1 = (BooleanValue) stackFrame.getValue(locvar1); + if (blv1.value() != true) { + log3("ERROR: blv1 != true : " + blv1.value() ); + expresult = returnCode1; + } + blv2 = (BooleanValue) stackFrame.getValue(locvar2); + if (blv2.value() != false) { + log3("ERROR: blv2 != false : " + blv2.value() ); + } + + break; + + + case 1: ByteValue btv1 = null; + ByteValue btv2 = null; + + locvar1 = stackFrame.visibleVariableByName(bt1); + locvar2 = stackFrame.visibleVariableByName(bt2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Byte"); + expresult = returnCode1; + break; + } + + btv1 = (ByteValue) stackFrame.getValue(locvar1); + if (btv1.value() != 0) { + log3("ERROR: btv1 != 0 : " + btv1.value() ); + expresult = returnCode1; + } + btv2 = (ByteValue) stackFrame.getValue(locvar2); + if (btv2.value() != 1) { + log3("ERROR: btv2 != 1 : " + btv2.value() ); + expresult = returnCode1; + } + + break; + + + case 2: CharValue chv1 = null; + CharValue chv2 = null; + + locvar1 = stackFrame.visibleVariableByName(ch1); + locvar2 = stackFrame.visibleVariableByName(ch2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Char"); + expresult = returnCode1; + break; + } + + chv1 = (CharValue) stackFrame.getValue(locvar1); + if (chv1.value() != 0) { + log3("ERROR: chv1 != 0 : " + chv1.value() ); + expresult = returnCode1; + } + chv2 = (CharValue) stackFrame.getValue(locvar2); + if (chv2.value() != 1) { + log3("ERROR: chv2 != 1 : " + chv2.value() ); + expresult = returnCode1; + } + + break; + + + case 3: DoubleValue dbv1 = null; + DoubleValue dbv2 = null; + + locvar1 = stackFrame.visibleVariableByName(db1); + locvar2 = stackFrame.visibleVariableByName(db2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Double"); + expresult = returnCode1; + break; + } + + dbv1 = (DoubleValue) stackFrame.getValue(locvar1); + if (dbv1.value() != 0.0d) { + log3("ERROR: dbv1 != 0.0d : " + dbv1.value() ); + expresult = returnCode1; + } + dbv2 = (DoubleValue) stackFrame.getValue(locvar2); + if (dbv2.value() != 1111111111.0d) { + log3("ERROR: dbv2 != 1111111111.0d : " + dbv2.value() ); + expresult = returnCode1; + } + + break; + + + case 4: FloatValue flv1 = null; + FloatValue flv2 = null; + + locvar1 = stackFrame.visibleVariableByName(fl1); + locvar2 = stackFrame.visibleVariableByName(fl2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Float"); + expresult = returnCode1; + break; + } + + flv1 = (FloatValue) stackFrame.getValue(locvar1); + if (flv1.value() != 0.0f) { + log3("ERROR: flv1 != 0.0f : " + flv1.value() ); + expresult = returnCode1; + } + flv2 = (FloatValue) stackFrame.getValue(locvar2); + if (flv2.value() != 1111111111.0f) { + log3("ERROR: flv2 != 1111111111.0f : " + flv2.value() ); + expresult = returnCode1; + } + + break; + + case 5: IntegerValue inv1 = null; + IntegerValue inv2 = null; + + locvar1 = stackFrame.visibleVariableByName(in1); + locvar2 = stackFrame.visibleVariableByName(in2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Integer"); + expresult = returnCode1; + break; + } + + inv1 = (IntegerValue) stackFrame.getValue(locvar1); + if (inv1.value() != 0) { + log3("ERROR: inv1 != 0 : " + inv1.value() ); + expresult = 1; + } + inv2 = (IntegerValue) stackFrame.getValue(locvar2); + if (inv2.value() != 1) { + log3("ERROR: inv2 != 1 : " + inv2.value() ); + expresult = returnCode1; + } + + break; + + + case 6: LongValue lnv1 = null; + LongValue lnv2 = null; + + locvar1 = stackFrame.visibleVariableByName(ln1); + locvar2 = stackFrame.visibleVariableByName(ln2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Long"); + expresult = returnCode1; + break; + } + + lnv1 = (LongValue) stackFrame.getValue(locvar1); + lnv2 = (LongValue) stackFrame.getValue(locvar2); + log2("2 : lnv1= 0x" + Long.toHexString(lnv1.value()) + + " lnv2= 0x" + Long.toHexString(lnv2.value()) ); + if (lnv1.value() != 0) { + log3("ERROR: lnv1 != 0 : " + Long.toHexString(lnv1.value()) ); + expresult = returnCode1; + } + if (lnv2.value() != 0x1234567890abcdefL) { + log3("ERROR: lnv2 != 0x1234567890abcdefL : " + Long.toHexString(lnv2.value()) ); + expresult = returnCode1; + } + + break; + + + case 7: ShortValue shv1 = null; + ShortValue shv2 = null; + locvar1 = stackFrame.visibleVariableByName(sh1); + locvar2 = stackFrame.visibleVariableByName(sh2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Short"); + expresult = returnCode1; + break; + } + + shv1 = (ShortValue) stackFrame.getValue(locvar1); + if (shv1.value() != 0) { + log3("ERROR: shv1 != 0 : " + shv1.value() ); + expresult = returnCode1; + } + shv2 = (ShortValue) stackFrame.getValue(locvar2); + if (shv2.value() != 1) { + log3("ERROR: shv2 != 1 : " + shv2.value() ); + expresult = returnCode1; + } + + break; + + + default : log3("ERROR: TEST ERROR: case: default:"); + expresult = returnCode1; + break; + + } // end of switch + + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for: stackFrame.getValue()"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameException before the thread is resumed "); + expresult = 1; + } catch ( Exception e ) { + log3("ERROR: unexpected exception: " + e); + expresult = returnCode1; + } // end of try + + } // end of for + } + + label2: { + + log2(" resuming the thread2"); + eventSet.resume(); + + if (expresult != returnCode0) + break label2; + + try { + Value value = stackFrame.getValue(locvar1); + + log3("ERROR: no InvalidStackFrameExceprtion after the thread is resumed"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameException after the thread is resumed"); + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001/TestDescription.java new file mode 100644 index 00000000000..227ae2d6af4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001/TestDescription.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/getValue/getvalue001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.getValue() + * complies with its spec: + * public Value getValue(LocalVariable variable) + * Gets the Value of a LocalVariable in this frame. + * The variable must be valid for this frame's method and visible + * according to the rules described in visibleVariables(). + * Parameters: variable - the LocalVariable to be accessed + * Returns: the Value of the instance field. + * Throws: java.lang.IllegalArgumentException - + * if the variable is either invalid for this frame's method or + * not visible. + * InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.getValue.getvalue001; + * the debuggee program - nsk.jdi.StackFrame.getValue.getvalue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.getValue.getvalue001 + * nsk.jdi.StackFrame.getValue.getvalue001a + * + * @comment make sure getvalue001a is compiled with full debug info + * @clean nsk.jdi.StackFrame.getValue.getvalue001a + * @compile -g:lines,source,vars ../getvalue001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.getValue.getvalue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001a.java new file mode 100644 index 00000000000..8313b2d1d44 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue001a.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the getvalue001 JDI test. + */ + +public class getvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.getValue()
    + * complies with its spec in case when a tested program
    + * is prepared with full information (see README file),
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The case for testing is as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * Since debuggee's method runt1() calls to the method runt2(),
    + * at the beginning the debugger sets up breakpoints at both
    + * methods, so that, in run-time runt2() is suspended first.
    + * After getting the thread2 suspended first time, the debugger
    + * gets a LocalVariable object locvar1, mirroring
    + * a method variable in the runt2(), which becomes invalid
    + * when runt2() is resumed and runt1() is suspended.
    + * After getting the thread2 suspended second time,
    + * the debugger checks up that the method invocation
    + * StackFrame.getValue() on locvar1 does throw
    + * IllegalArgumentException.
    + *
    + */ + +public class getvalue002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/getValue/getvalue002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalue002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.getValue.getvalue002a"; + + private String testedClassName = + "nsk.jdi.StackFrame.getValue.Threadgetvalue002a"; + + //String mName = "nsk.jdi.StackFrame.getValue"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("getvalue002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + + log2(" getting LocalVariable locvar1 for checking up"); + + String bl1 = "bl1"; + + try { + locvar1 = stackFrame.visibleVariableByName(bl1); + } catch ( Exception e ) { + log3("ERROR: unexpected exception: " + e); + expresult = returnCode1; + break label1; + } + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" resuming the thread2"); + eventSet.resume(); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting thread2's current StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + log2(" checking up that locvar1 is not valid for current StackFrame"); + + try { + Value value = stackFrame.getValue(locvar1); + + log3("ERROR: no IllegalArgumentException after runt() returned"); + expresult = returnCode1; + } catch ( IllegalArgumentException e1 ) { + log2(" : IllegalArgumentException after runt() returned"); + } catch ( Exception e ) { + log3("ERROR: Exception for: Value value = stackFrame.getValue(locvar1); :" + e); + expresult = returnCode1; + break label1; + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002/TestDescription.java new file mode 100644 index 00000000000..1bef8e6eea8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002/TestDescription.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/getValue/getvalue002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.getValue() + * complies with its spec: + * public Value getValue(LocalVariable variable) + * Gets the Value of a LocalVariable in this frame. + * The variable must be valid for this frame's method and visible + * according to the rules described in visibleVariables(). + * Parameters: variable - the LocalVariable to be accessed + * Returns: the Value of the instance field. + * Throws: java.lang.IllegalArgumentException - + * if the variable is either invalid for this frame's method or + * not visible. + * InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.getValue.getvalue002; + * the debuggee program - nsk.jdi.StackFrame.getValue.getvalue002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.getValue.getvalue002 + * nsk.jdi.StackFrame.getValue.getvalue002a + * + * @comment make sure getvalue002a is compiled with full debug info + * @clean nsk.jdi.StackFrame.getValue.getvalue002a + * @compile -g:lines,source,vars ../getvalue002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.getValue.getvalue002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002a.java new file mode 100644 index 00000000000..15bc1fa553c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue002a.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the getvalue002 JDI test. + */ + +public class getvalue002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.StackFrame.getValue()
    + * properly throws IllegalArgumentException - if + * specified variable is invalid for this frame's method.

    + * + * The test works as follows. The target VM executes two debuggee + * threads: getvalue003tMainThr and getvalue003tAuxThr. + * Debugger part tries to get value of the local variable + * getvalue003tFindMe in stack frame obtained from the + * getvalue003tMainThr thread using as a parameter a + * LocalVariable object obtained from the getvalue003tAuxThr thread. + */ +public class getvalue003 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.StackFrame.getValue.getvalue003t"; + + // names of debuggee threads + static final String DEBUGGEE_THRDNAMES[] = { + "getvalue003tMainThr", "getvalue003tAuxThr" + }; + + // debuggee local var used in testing + static final String DEBUGGEE_LOCALVAR = "getvalue003tFindMe"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 69; + + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + private LocalVariable wrongLocVar; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getvalue003().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "getvalue003t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[2]; + for (int i=0; i<2; i++) + if ((thrRef[i] = + debuggee.threadByName(DEBUGGEE_THRDNAMES[i])) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRDNAMES[i]); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + // get a stack frame which belongs to the "getvalue003tMainThr" thread + StackFrame stFrame = findFrame(thrRef[0], DEBUGGEE_LOCALVAR, false); + + // store a LocalVariable which belongs to the "getvalue003tAuxThr" thread + findFrame(thrRef[1], DEBUGGEE_LOCALVAR, true); + + log.display("\nTrying to get value of local variable \"" + + wrongLocVar + + "\"\n\tgotten from thread \"" + thrRef[1] + + "\"\n\tusing stack frame \"" + stFrame + + "\"\n\tbelongs to thread \"" + thrRef[0] + + "\" ..."); + +// Check the tested assersion + try { + Value val = stFrame.getValue(wrongLocVar); + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to get value of local variable \"" + + wrongLocVar + + "\"\n\tgotten from thread \"" + thrRef[1] + + "\"\n\tusing stack frame \"" + stFrame + + "\"\n\tbelongs to thread \"" + thrRef[0] + "\""); + tot_res = Consts.TEST_FAILED; + } catch(IllegalArgumentException ee) { + log.display("CHECK PASSED: caught expected " + ee); + } catch(Exception ue) { + ue.printStackTrace(); + log.complain("TEST FAILED: StackFrame.getValue(): caught unexpected " + + ue + "\n\tinstead of IllegalArgumentException" + + "\n\twhen attempted to get value of local variable \"" + + wrongLocVar + + "\"\n\tgotten from thread \"" + thrRef[1] + + "\"\n\tusing stack frame \"" + stFrame + + "\"\n\tbelongs to thread \"" + thrRef[0] + "\""); + tot_res = Consts.TEST_FAILED; + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + + return quitDebuggee(); + } + + private StackFrame findFrame(ThreadReference thrRef, + String varName, boolean storeLocVar) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = + stackFr.visibleVariableByName(varName); + // visible variable with the given name is found + if (locVar != null) { + if (storeLocVar) // store a LocalVariable as well + wrongLocVar = locVar; + + return stackFr; + } + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("Final resumption of debuggee VM"); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003/TestDescription.java new file mode 100644 index 00000000000..274fd5e43d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/getValue/getvalue003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method: + * com.sun.jdi.StackFrame.getValue() + * properly throws IllegalArgumentException - if specified variable + * is invalid for this frame's method. + * The test works as follows. The target VM executes two debuggee + * threads: "getvalue003tMainThr" and "getvalue003tAuxThr". + * Debugger part tries to get value of the local variable + * "getvalue003tFindMe" in stack frame obtained from the + * "getvalue003tMainThr" thread using as a parameter a LocalVariable + * object obtained from the "getvalue003tAuxThr" thread. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.getValue.getvalue003 + * nsk.jdi.StackFrame.getValue.getvalue003t + * + * @comment make sure getvalue003t is compiled with full debug info + * @clean nsk.jdi.StackFrame.getValue.getvalue003t + * @compile -g:lines,source,vars ../getvalue003t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.getValue.getvalue003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003t.java new file mode 100644 index 00000000000..431641de0ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValue/getvalue003t.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.StackFrame.getValue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class getvalue003t { + private Log log; + private IOPipe pipe; + private OtherThr auxThr; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new getvalue003t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(getvalue003.DEBUGGEE_THRDNAMES[0]); + startThread(); + + // local var used by debugger to find appropriate stack frame + int getvalue003tFindMe = 0; + + // Now the debuggee is ready for testing + pipe.println(getvalue003.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(getvalue003.COMMAND_QUIT)) { + killThread(argHandler.getWaitTime()*60000); + log.complain("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // getvalue003.DEBUGGEE_STOPATLINE + + cmd = pipe.readln(); + killThread(argHandler.getWaitTime()*60000); + if (!cmd.equals(getvalue003.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + return Consts.TEST_FAILED; + } + return Consts.TEST_PASSED; + } + + private void startThread() { + Object readyObj = new Object(); + + auxThr = new OtherThr(readyObj, + getvalue003.DEBUGGEE_THRDNAMES[1]); + auxThr.setDaemon(true); + + log.display("Debuggee: starting thread \"" + + auxThr.getName() + "\" ..."); + synchronized(readyObj) { + auxThr.start(); + try { + readyObj.wait(); // wait for the thread's readiness + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: waiting for the thread " + + auxThr + " start: caught " + e); + pipe.println("failed"); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + } + log.display("Debuggee: the thread \"" + + auxThr.getName() + "\" started"); + } + + private void killThread(int waitTime) { + auxThr.doExit = true; + try { + auxThr.join(waitTime); + log.display("Debuggee: thread \"" + + auxThr.getName() + "\" done"); + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: joining the thread \"" + + auxThr.getName() + "\": caught " + e); + } + } + + /** + * This is an auxiliary thread class used to check + * an IllegalArgumentException in debugger. + */ + class OtherThr extends Thread { + volatile boolean doExit = false; + private Object readyObj; + + OtherThr(Object readyObj, String name) { + super(name); + this.readyObj = readyObj; + } + + public void run() { + // var used by debugger for searching + int getvalue003tFindMe = 0; + + Thread thr = Thread.currentThread(); + + synchronized(readyObj) { + readyObj.notify(); // notify the main thread + } + log.display("Debuggee thread \"" + + thr.getName() + "\": going to loop"); + while(!doExit) { + int i = 0; + i++; i--; + + // reliable analogue of Thread.yield() + synchronized(this) { + try { + this.wait(30); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + log.complain("TEST FAILURE: Debuggee thread \"" + + thr.getName() + + "\" interrupted while sleeping:\n\t" + e); + break; + } + } + } + log.display("Debuggee thread \"" + + thr.getName() + "\" exiting ..."); + } + } +///////////////////////////////////////////////////////////////////////////// + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001.java new file mode 100644 index 00000000000..8471e297026 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001.java @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.getValues()
    + * complies with its spec in case when a tested program
    + * is prepared with full information (see README file),
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * 1) After getting the thread2 suspended but before to resume it,
    + * StackFrame.getValues() is used for getting and
    + * checking up a number of visible variables
    + * local in a tested method, and that all the variables
    + * are of PrimitiveType as in the debugged program.
    + * 2) After resuming the thread2, the method StackFrame.getValues() is
    + * invoked second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class getvalues001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/getValues/getvalues001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalues001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.getValues.getvalues001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.getValues.Threadgetvalues001a"; + + //String mName = "nsk.jdi.StackFrame.getValues"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("getvalues001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + // BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting thread2's StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + log2(" StackFrame stackFrame is ready for testing"); + + List testedVars = null; + + log2(" getting List of method's variables"); + try { + testedVars = ( (Method) testedclass.methodsByName(breakpointMethod1).get(0)).variables(); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for testedVars = runMethod.variables()"); + expresult = returnCode1; + break label1; + } + + label:{ + Map returnedVars = null; + + log2(" getting Map of variable's returnedValues"); + try { + returnedVars = stackFrame.getValues(testedVars); + } catch ( IllegalArgumentException e ) { + log3("ERROR: IllegalArgumentException for: stackFrame.getValue()"); + expresult = returnCode1; + break label; + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameException before the thread is resumed "); + expresult = returnCode1; + break label; + } catch ( Throwable e ) { + log3("ERROR: some exception for stackFrame.getValues(testedVars) : " + e); + expresult = returnCode1; + break label; + } + + String bl1 = "bl1"; + String bt1 = "bt1"; + String ch1 = "ch1"; + String db1 = "db1"; + String fl1 = "fl1"; + String in1 = "in1"; + String ln1 = "ln1"; + String sh1 = "sh1"; + + Set keyset = returnedVars.keySet(); + Iterator setIterator = keyset.iterator(); + + log2(" loop of casting returnedValues"); + int i4 = 0; + for (int i3 = 0; setIterator.hasNext(); i3++) { + + LocalVariable lvar = (LocalVariable) setIterator.next(); + + try { + Value val = (Value) returnedVars.get(lvar); + + if (lvar.name().equals(bl1)) { + BooleanValue blv = (BooleanValue) val; + i4 += 1; + } else if (lvar.name().equals(bt1)) { + ByteValue btv = (ByteValue) val; + i4 += 10; + } else if (lvar.name().equals(ch1)) { + CharValue chv = (CharValue) val; + i4 += 100; + } else if (lvar.name().equals(db1)) { + DoubleValue chv = (DoubleValue) val; + i4 += 1000; + } else if (lvar.name().equals(fl1)) { + FloatValue dbv = (FloatValue) val; + i4 += 10000; + } else if (lvar.name().equals(in1)) { + IntegerValue inv = (IntegerValue) val; + i4 += 100000; + } else if (lvar.name().equals(ln1)) { + LongValue dbv = (LongValue) val; + i4 += 1000000; + } else if (lvar.name().equals(sh1)) { + ShortValue shv = (ShortValue) val; + i4 += 10000000; + } else { + log3("ERROR: name in Map doesn't match any expected : " + lvar.name()); + expresult = returnCode1; + } + } catch ( ClassCastException e1 ) { + log3("ERROR: ClassCastException for values in the returned Map: #= " + i3); + expresult = returnCode1; + break label; + } catch ( NullPointerException e2 ) { + log3("ERROR: NullPointerException for values in the returned Map: #= " + i3); + expresult = returnCode1; + break label; + } + + } // end of for + + log2(" checking up whether all PrimitiveValues are tested"); + if (i4 != 11111111) { + log3("ERROR: not all PrimitiveValues are in the returned Map"); + expresult = returnCode1; + break label; + } + } // end of label: + + log2(" resuming the thread2"); + eventSet.resume(); + + if (expresult != 0) + break label1; + + log2(" testing StackFrame validity after resuming the thread2"); + try { + Map returnedVars = stackFrame.getValues(testedVars); + + log3("ERROR: no InvalidStackFrameExceprtion after the thread2 is resumed"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameException after the thread2 is resumed"); + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001/TestDescription.java new file mode 100644 index 00000000000..d46d9ad117d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/getValues/getvalues001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.getValues() + * complies with its spec: + * public java.util.Map getValues(java.util.List variables) + * Returns the values of multiple local variables in this frame. + * Each variable must be valid for this frame's method and + * visible according to the rules described in visibleVariables(). + * Parameters: variables - a list of LocalVariable objects to be accessed + * Returns: a map associating each LocalVariable with its Value + * Throws: java.lang.IllegalArgumentException - + * if any variable is either invalid for this frame's method or + * not visible. + * InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.getValues.getvalues001; + * the debuggee program - nsk.jdi.StackFrame.getValues.getvalues001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.getValues.getvalues001 + * nsk.jdi.StackFrame.getValues.getvalues001a + * + * @comment make sure getvalues001a is compiled with full debug info + * @clean nsk.jdi.StackFrame.getValues.getvalues001a + * @compile -g:lines,source,vars ../getvalues001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.getValues.getvalues001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001a.java new file mode 100644 index 00000000000..7cf3736120c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues001a.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the getvalues001 JDI test. + */ + +public class getvalues001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.getValues()
    + * complies with its spec in case when a tested program
    + * is prepared with full information (see README file),
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The case for testing is as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * Since debuggee's method runt1() calls to the method runt2(),
    + * at the beginning the debugger sets up breakpoints at both
    + * methods, so that, in run-time runt2() is suspended first.
    + * After getting the thread2 suspended first time, the debugger
    + * gets a Map containing LocalVariable objects, mirroring
    + * method variables in the runt2(), which becomes invalid
    + * when runt2() is resumed and runt1() is suspended.
    + * After getting the thread2 suspended second time,
    + * the debugger extracts a List of LocalVariables from
    + * the Map and checks up that the method invocation
    + * StackFrame.getValues() on the List argument does throw
    + * IllegalArgumentException.
    + *
    + */ + +public class getvalues002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/getValues/getvalues002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new getvalues002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.getValues.getvalues002a"; + + private String testedClassName = + "nsk.jdi.StackFrame.getValues.Threadgetvalues002a"; + + //String mName = "nsk.jdi.StackFrame.getValues"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("getvalues002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting current StackFrame object at first breakpoint"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + List testedVars = null; + + log2(" getting List of LocalVariables for checking up"); + try { + testedVars = stackFrame.visibleVariables(); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for testedVars = runMethod.variables()"); + expresult = returnCode1; + break label1; + } + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" resuming the thread2"); + eventSet.resume(); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + + log2(" getting current StackFrame object at second breakpoint"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + log2(" checking up that the List of testedVars is not valid for current StackFrame"); + try { + Map returnedVars = stackFrame.getValues(testedVars); + + log3("ERROR: no IllegalArgumentException after exit from runt2()"); + expresult = returnCode1; + } catch ( IllegalArgumentException eIllegal ) { + log2(" : IllegalArgumentException after exit from runt2()"); + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002/TestDescription.java new file mode 100644 index 00000000000..c756c8529c6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002/TestDescription.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/getValues/getvalues002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.getValues() + * complies with its spec: + * public java.util.Map getValues(java.util.List variables) + * Returns the values of multiple local variables in this frame. + * Each variable must be valid for this frame's method and + * visible according to the rules described in visibleVariables(). + * Parameters: variables - a list of LocalVariable objects to be accessed + * Returns: a map associating each LocalVariable with its Value + * Throws: java.lang.IllegalArgumentException - + * if any variable is either invalid for this frame's method or + * not visible. + * InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * VMMismatchException - + * if a Mirror argument and this mirror do not belong to + * the same VirtualMachine. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.getValues.getvalues002; + * the debuggee program - nsk.jdi.StackFrame.getValues.getvalues002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.getValues.getvalues002 + * nsk.jdi.StackFrame.getValues.getvalues002a + * + * @comment make sure getvalues002a is compiled with full debug info + * @clean nsk.jdi.StackFrame.getValues.getvalues002a + * @compile -g:lines,source,vars ../getvalues002a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.getValues.getvalues002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002a.java new file mode 100644 index 00000000000..d23ee96d2d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/getValues/getvalues002a.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.getValues; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the getvalues002 JDI test. + */ + +public class getvalues002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.StackFrame.getValues()
    + * properly throws IllegalArgumentException - if + * specified variable is invalid for this frame's method.

    + * + * The test works as follows. The target VM executes two debuggee + * threads: getvalues003tMainThr and getvalues003tAuxThr. + * Debugger part tries to provoke the exception by getting values of + * the local variables in stack frame obtained from the + * getvalue0s03tMainThr thread, and one among them obtained + * from the getvalues003tAuxThr thread. + */ +public class getvalues003 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.StackFrame.getValues.getvalues003t"; + + // names of debuggee threads + static final String DEBUGGEE_THRDNAMES[] = { + "getvalues003tMainThr", "getvalues003tAuxThr" + }; + + // tested debuggee local vars + static final int VAR_NUM = 9; + static final String DEBUGGEE_VARS[] = { + "getvalues003tFindMe", "shortVar", "intVar", + "longVar", "floatVar", "doubleVar", "charVar", + "booleanVar", "strVar" + }; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 78; + + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + private List locVars; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new getvalues003().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "getvalues003t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[2]; + for (int i=0; i<2; i++) + if ((thrRef[i] = + debuggee.threadByName(DEBUGGEE_THRDNAMES[i])) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRDNAMES[i]); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + // get a stack frame which belongs to the "getvalue003tMainThr" thread + StackFrame stFrame = findFrame(thrRef[0], DEBUGGEE_VARS[0], true); + + // store a LocalVariable which belongs to the "getvalue003tAuxThr" thread + StackFrame wrongStFrame = findFrame(thrRef[1], DEBUGGEE_VARS[0], false); + + StringBuffer varNames = new StringBuffer(); + Iterator varIter = locVars.iterator(); + while (varIter.hasNext()) { + LocalVariable locv = (LocalVariable) varIter.next(); + varNames = varNames.append("\n\t\t" + locv.typeName() + + " " + locv.name() + " " + locv.signature()); + } + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + BreakpointRequest brkp = debuggee.setBreakpoint(debuggeeClass, + hashcode001a.brkpMethodName, + hashcode001a.brkpLineNumber); + debuggee.resume(); + + debuggee.sendSignal(SIGNAL_GO); + Event event = null; + + // waiting the breakpoint event + try { + event = debuggee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected InterruptedException while waiting for Breakpoint event"); + } + if (!(event instanceof BreakpointEvent)) { + debuggee.resume(); + throw new Failure("BreakpointEvent didn't arrive"); + } + + ThreadReference thread = ((BreakpointEvent)event).thread(); + List frames = null; + try { + frames = thread.frames(); + } catch(IncompatibleThreadStateException e) { + throw new Failure("Unexpected IncompatibleThreadStateException when getting list of frames"); + } + + display("Checking hashCode() method for debuggee's stack frames..."); + + // Check all methods from debuggee + for (int i = 0; i < frames.size(); i++) { + + StackFrame stackFrame = null; + try { + stackFrame = (StackFrame)frames.get(i); + int hCode = stackFrame.hashCode(); + if (hCode == 0) { + complain("hashCode() returns 0 for stack frame #" + i); + exitStatus = Consts.TEST_FAILED; + } + + int hCode1 = stackFrame.hashCode(); + if (hCode != hCode1) { + complain("hashCode() is not consistent for stack frame #" + i + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + // get new reference to the same stack frame and get hash code. + hCode1 = ((StackFrame)frames.get(i)).hashCode(); + if (hCode != stackFrame.hashCode()) { + complain("hashCode() does not return same value for stack frame equal to one #" + i + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + display("hashCode() returns for stack frame #" + i + " : " + hCode); + + } catch(Exception e) { + complain("Unexpected " + e + " when getting StackFrame for stack frame #" + i); + exitStatus = Consts.TEST_FAILED; + } + + } + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..3689514d84a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/hashCode/hashcode001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public hashCode() method of an implementing class of + * com.sun.jdi.StackFrame interface. + * The test checks an assertion cited from spec for hashCode() method of + * java.lang.Object class: + * The general contract of hashCode is: + * - Whenever it is invoked on the same object more than once during an execution + * of a Java application, the hashCode method must consistently return the same + * integer, provided no information used in equals comparisons on the object is + * modified. + * ... + * - If two objects are equal according to the equals(Object) method, then calling the + * hashCode method on each of the two objects must produce the same integer result. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for StackFrame + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.hashCode.hashcode001 + * nsk.jdi.StackFrame.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001a.java new file mode 100644 index 00000000000..be793196de8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/hashCode/hashcode001a.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.StackFrame.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class hashcode001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + public final static String brkpMethodName = "breakHere"; + public final static int brkpLineNumber = 92; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(hashcode001.SIGNAL_READY); + breakHere(); + receiveSignal(hashcode001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + public static void breakHere () { + receiveSignal(hashcode001.SIGNAL_GO); + log.display("breakpoint line"); // brkpLineNumber + } +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001.java new file mode 100644 index 00000000000..10da14bfd46 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001.java @@ -0,0 +1,537 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.location()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * 1) After getting the thread2 suspended but before to resume it,
    + * two sequential invokations of the method StackFrame.location()
    + * are executed. Since the thread2 is not resumed yet,
    + * InvalidStackFrameException must not be thrown on
    + * on second invokation, and both returned Location objects
    + * must have the same values returned by invokations on them
    + * methods codeIndex() and lineNumber();
    + * 2) The debugger gets two mirrors of current method in the debuggee
    + * one directly with Location.Method(), and another one with
    + * VirtualMachine.classesByName().get().methodsByName().get(),
    + * and checks up that both mirrors are equal to each other.
    + * 3) After resuming the thread2, the method is invoked one more
    + * time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class location001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/location/location001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new location001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.location.location001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.location.Threadlocation001a"; + + //String mName = "nsk.jdi.StackFrame.location"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("location001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + // BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + + Location location1; + Location location2; + + log2(" getting two Location objects, 1 and 2"); + try { + stackFrame = thread2.frame(0); + location1 = stackFrame.location(); + location2 = stackFrame.location(); + } catch ( InvalidStackFrameException e1 ) { + expresult = returnCode1; + log3("ERROR: InvalidStackFrameException before thread2 is resumed"); + break label1; + } catch ( IncompatibleThreadStateException e2 ) { + expresult = returnCode1; + log3("ERROR: IncompatibleThreadStateException ??!!"); + break label1; + } + + log2(" checking up that location1&2 have the same codeIndex and lineNumber"); + if ( location1.codeIndex() != location2.codeIndex() || + location1.lineNumber() != location2.lineNumber() ) { + log3("ERROR: codeIndexes or lineNumbers are not equal"); + log3(" line1 # = " + location1.lineNumber() + + " line2 # = " + location2.lineNumber()); + expresult = returnCode1; + break label1; + } + + + log2(" checking up that method is accessable through its Location"); + log2(" and two method's mirrors are equal"); + Method m = location1.method(); + if (m == null) { + log3("ERROR: m == null for: m = location1.method()"); + expresult = returnCode1; + } else if ( !m.equals( (Method) testedclass.methodsByName(breakpointMethod1).get(0)) ) { + log3("ERROR: two method's mirrors are not equal"); + expresult = returnCode1; + } else + log2(" two method's mirrors are equal"); + + + log2(" resuming the thread2 and "); + eventSet.resume(); + + log2(" checking up throwing InvalidStackFrameException"); + try { + location1 = stackFrame.location(); + expresult = returnCode1; + log3("ERROR: no InvalidStackFrameException after thread2 is resumed"); + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameException after thread2 is resumed"); + } + + } + eventSet.resume(); // for case if thread2 was not resumed because of error in a check + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001/TestDescription.java new file mode 100644 index 00000000000..63da70e4387 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/location/location001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.location() + * complies with its spec: + * public Location location() + * Returns the Location of the current instruction in the frame. + * The method for which this frame was created can also + * be accessed through the returned location. + * For the top frame in the stack, + * this location identifies the next instruction to be executed. + * For all other frames, this location identifies the instruction that + * caused the next frame's method to be invoked. + * If the frame represents a native method invocation, + * the returned location indicates the class and method, but + * the code index will not be valid. + * Specified by: location in interface Locatable + * Returns: the Location of the current instruction. + * Throws: InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * The test checks up results of method invokations before and after + * a tested suspended thread is resumed. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.location.location001; + * the debuggee program - nsk.jdi.StackFrame.location.location001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.location.location001 + * nsk.jdi.StackFrame.location.location001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.location.location001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001a.java new file mode 100644 index 00000000000..d5b9562db42 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/location/location001a.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.location; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the location001 JDI test. + */ + +public class location001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.setValue()
    + * complies with its spec in case when a tested program
    + * is prepared with full information (see README file),
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * 1) After getting the thread2 suspended but before to resume it,
    + * StackFrame.setValue() is used for setting and
    + * following checking up the values of visible variables,
    + * local in a tested method, two for each PrimitiveType.
    + * 2) After resuming the thread2, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class setvalue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/setValue/setvalue001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.setValue.setvalue001.setvalue001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.setValue.setvalue001.Threadsetvalue001a"; + + //String mName = "nsk.jdi.StackFrame.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + // BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting thread2's StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + // StackFrame stackFrame is ready for testing + + String bl1 = "bl1", bl2 = "bl2"; + String bt1 = "bt1", bt2 = "bt2"; + String ch1 = "ch1", ch2 = "ch2"; + String db1 = "db1", db2 = "db2"; + String fl1 = "fl1", fl2 = "fl2"; + String in1 = "in1", in2 = "in2"; + String ln1 = "ln1", ln2 = "ln2"; + String sh1 = "sh1", sh2 = "sh2"; + + String ini0 = "i0"; + + + for ( int i3 = 0; i3 < 8; i3++) { + + try { + + switch (i3) { + + case 0: BooleanValue blv1 = null; + BooleanValue blv2 = null; + + locvar1 = stackFrame.visibleVariableByName(bl1); + locvar2 = stackFrame.visibleVariableByName(bl2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Boolean"); + expresult = returnCode1; + break; + } + + blv2 = (BooleanValue) stackFrame.getValue(locvar2); + stackFrame.setValue(locvar1, blv2); + blv1 = (BooleanValue) stackFrame.getValue(locvar1); + if (blv1.value() != false) { + log3("ERROR: blv1 != false : " + blv1.value() ); + expresult = returnCode1; + } + + break; + + + case 1: ByteValue btv1 = null; + ByteValue btv2 = null; + + locvar1 = stackFrame.visibleVariableByName(bt1); + locvar2 = stackFrame.visibleVariableByName(bt2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Byte"); + expresult = returnCode1; + break; + } + + btv2 = (ByteValue) stackFrame.getValue(locvar2); + stackFrame.setValue(locvar1, btv2); + btv1 = (ByteValue) stackFrame.getValue(locvar1); + if (btv1.value() != 1) { + log3("ERROR: btv1 != 1 : " + btv1.value() ); + expresult = returnCode1; + } + + break; + + + case 2: CharValue chv1 = null; + CharValue chv2 = null; + + locvar1 = stackFrame.visibleVariableByName(ch1); + locvar2 = stackFrame.visibleVariableByName(ch2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Char"); + expresult = returnCode1; + break; + } + + chv2 = (CharValue) stackFrame.getValue(locvar2); + stackFrame.setValue(locvar1, chv2); + chv1 = (CharValue) stackFrame.getValue(locvar1); + if (chv1.value() != 1) { + log3("ERROR: chv1 != 1 : " + chv1.value() ); + expresult = returnCode1; + } + + break; + + + case 3: DoubleValue dbv1 = null; + DoubleValue dbv2 = null; + + locvar1 = stackFrame.visibleVariableByName(db1); + locvar2 = stackFrame.visibleVariableByName(db2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Double"); + expresult = returnCode1; + break; + } + + dbv2 = (DoubleValue) stackFrame.getValue(locvar2); + log2("1 : dbv2 = " + Double.doubleToRawLongBits(dbv2.value()) ); + stackFrame.setValue(locvar1, dbv2); + dbv1 = (DoubleValue) stackFrame.getValue(locvar1); + log2("2 : dbv1 = " + Double.doubleToRawLongBits(dbv1.value()) ); + if (dbv1.value() != 1111111111.0d) { + log3("ERROR: dbv1 != 1111111111.0d : " + dbv1.value() ); + expresult = returnCode1; + } + + break; + + + case 4: FloatValue flv1 = null; + FloatValue flv2 = null; + + locvar1 = stackFrame.visibleVariableByName(fl1); + locvar2 = stackFrame.visibleVariableByName(fl2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Float"); + expresult = returnCode1; + break; + } + + flv2 = (FloatValue) stackFrame.getValue(locvar2); + stackFrame.setValue(locvar1, flv2); + flv1 = (FloatValue) stackFrame.getValue(locvar1); + if (flv1.value() != 1111111111.0f) { + log3("ERROR: flv1 != 1111111111.0f : " + flv1.value() ); + expresult = returnCode1; + } + + break; + + case 5: IntegerValue inv1 = null; + IntegerValue inv2 = null; + + locvar1 = stackFrame.visibleVariableByName(in1); + locvar2 = stackFrame.visibleVariableByName(in2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Integer"); + expresult = returnCode1; + break; + } + + inv2 = (IntegerValue) stackFrame.getValue(locvar2); + stackFrame.setValue(locvar1, inv2); + inv1 = (IntegerValue) stackFrame.getValue(locvar1); + if (inv1.value() != 1) { + log3("ERROR: inv1 != 1 : " + inv1.value() ); + expresult = returnCode1; + } + + break; + + + case 6: LongValue lnv1 = null; + LongValue lnv2 = null; + + locvar1 = stackFrame.visibleVariableByName(ln1); + locvar2 = stackFrame.visibleVariableByName(ln2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Long"); + expresult = returnCode1; + break; + } + + lnv2 = (LongValue) stackFrame.getValue(locvar2); + lnv1 = (LongValue) stackFrame.getValue(locvar1); + log2("1 : lnv1= 0x" + Long.toHexString(lnv1.value()) + + " lnv2= 0x" + Long.toHexString(lnv2.value()) ); + + stackFrame.setValue(locvar1, lnv2); + + lnv1 = (LongValue) stackFrame.getValue(locvar1); + log2("2 : lnv1= 0x" + Long.toHexString(lnv1.value()) + + " lnv2= 0x" + Long.toHexString(lnv2.value())); + if (lnv1.value() != 0x1234567890abcdefL) { + log3("ERROR: lnv1 != 0x1234567890abcdefL : " + + Long.toHexString(lnv1.value()) ); + expresult = returnCode1; + } + + break; + + + case 7: ShortValue shv1 = null; + ShortValue shv2 = null; + locvar1 = stackFrame.visibleVariableByName(sh1); + locvar2 = stackFrame.visibleVariableByName(sh2); + if (locvar1 == null || locvar2 == null) { + log3("ERROR: 'locvar1 == null || locvar2 == null' for Short"); + expresult = returnCode1; + break; + } + + shv2 = (ShortValue) stackFrame.getValue(locvar2); + stackFrame.setValue(locvar1, shv2); + shv1 = (ShortValue) stackFrame.getValue(locvar1); + if (shv1.value() != 1) { + log3("ERROR: shv1 != 1 : " + shv1.value() ); + expresult = returnCode1; + } + + break; + + + default : log3("ERROR: TEST ERROR: case: default:"); + expresult = returnCode1; + break; + + } // end of switch + + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for: stackFrame.getValue()"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameException before the thread is resumed "); + expresult = returnCode1; + } catch ( Throwable e ) { + log3("ERROR: unexpected exception: " + e); + expresult = returnCode1; + } // end of try + + } // end of for + } + + label2: { + + log2(" resuming the thread2"); + eventSet.resume(); + + if (expresult != returnCode0) + break label2; + + try { + Value value = stackFrame.getValue(locvar1); + + log3("ERROR: no InvalidStackFrameExceprtion after the thread is resumed"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameException after the thread is resumed"); + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue001/setvalue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue001/setvalue001a.java new file mode 100644 index 00000000000..aeae4528980 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue001/setvalue001a.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.setValue.setvalue001; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the setvalue001 JDI test. + */ + +public class setvalue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.setValue()
    + * complies with its spec in case when a tested program
    + * is prepared with full information (see README file),
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The test checks up throwing
    + * IllegalArgumentException and
    + * InvalidTypeException.
    + * The case for testing is as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * Debuggee's method runt1() calls to the method runt2().
    + * At the beginning the debugger sets up breakpoints at both
    + * methods, so that, in run-time runt2() is suspended first.
    + * After getting the thread2 suspended first time, the debugger
    + * gets a LocalVariable object locvar1, mirroring
    + * a boolean variable in the runt2(), which becomes invalid
    + * when runt2() is left and the thread2 is suspended within run1t().
    + * After getting the thread2 suspended second time,
    + * the debugger checks up that the method invocation
    + * StackFrame.setValue() on locvar1 does throw
    + * IllegalArgumentException.
    + * Then the debugger gets a LocalVariable locvar2 mirroring
    + * a byte variable in current (valid) StackFrame and
    + * checks up that the method invocation
    + * setValue(locvar2, byte argument)
    + * does throw InvalidTypeException.
    + *
    + */ + +public class setvalue002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/setValue/setvalue002/setvalue002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.setValue.setvalue002.setvalue002a"; + + private String testedClassName = + "nsk.jdi.StackFrame.setValue.setvalue002.Threadsetvalue002a"; + + //String mName = "nsk.jdi.StackFrame.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + String bl3 = "bl3"; + String bl4 = "bl4"; + String bl1 = "bl1"; + String locThread = "locThread"; + + log2(" getting LocalVariables for checking up "); + try { + locvar1 = stackFrame.visibleVariableByName(bl3); + locvar2 = stackFrame.visibleVariableByName(bl4); + } catch ( Exception e ) { + log3("ERROR: unexpected exception: " + e); + expresult = returnCode1; + break label1; + } + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" resuming the thread2"); + eventSet.resume(); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting thread2's current StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + + BooleanValue blv2 = null; + + try { + locvar2 = stackFrame.visibleVariableByName(bl1); + blv2 = (BooleanValue) stackFrame.getValue(locvar2); + + log2(" checking up IllegalArgumentException"); + stackFrame.setValue(locvar1, blv2); + + log3("ERROR: no IllegalArgumentException after thread2 returned from runt2()"); + expresult = returnCode1; + } catch ( IllegalArgumentException e1 ) { + log2(" : IllegalArgumentException after thread2 returned from runt2()"); + } catch ( InvalidTypeException e2 ) { + log3("ERROR: InvalidTypeException for stackFrame.setValue(locvar1, blv2)"); + expresult = returnCode1; + } catch ( Exception e ) { + log3("ERROR: unexpected exception: " + e); + expresult = returnCode1; + } + + + try { + locvar2 = stackFrame.visibleVariableByName(locThread); + + log2(" checking up InvalidTypeException"); + stackFrame.setValue(locvar2, blv2); + + log3("ERROR: no InvalidTypeException"); + expresult = returnCode1; + } catch ( InvalidTypeException eInavalid ) { + log2(" : InvalidTypeException"); + } catch ( Exception e ) { + log3("ERROR: unexpected exception: " + e); + expresult = returnCode1; + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue002/setvalue002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue002/setvalue002a.java new file mode 100644 index 00000000000..e520deb28a9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue002/setvalue002a.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.setValue.setvalue002; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the setvalue002 JDI test. + */ + +public class setvalue002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + static public Threadsetvalue002a test_thread = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.setValue()
    + * complies with its spec in case when a tested program
    + * is prepared with full information (see README file),
    + * hence, AbsentInformationException is not expected to happen.
    + * The test makes checking up on ReferenceTypes only.
    + *
    + * The case for testing is as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, and
    + * after getting the thread2 suspended, checks up that
    + * for LocalVariables locvar1 and locvar2 the following sequence
    + * Value val1 = stackFrame.getValue(locvar1);
    + * stackFrame.setValue(locvar2, val1);
    + * Value val2 = stackFrame.getValue(locvar2);
    + * results in: val1.equals(val2)
    + * for the following tested ReferenceType objects
    + * ClassType
    + * InterfaceType
    + * ClassArray
    + * InterfaceArray
    + * PrimitiveArray
    + *
    + */ + +public class setvalue003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/setValue/setvalue003/setvalue003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.setValue.setvalue003.setvalue003a"; + + private String testedClassName = + "nsk.jdi.StackFrame.setValue.setvalue003.Threadsetvalue003a"; + + //String mName = "nsk.jdi.StackFrame.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + + String names[][] = { { "class1", "class2" }, + { "class3", "class4" }, + { "iface1", "iface2" }, + { "iface3", "iface4" }, + { "array1", "array2" } }; + + + + log2(" checking up variables of ReferenceTypes"); + + for (int i2 = 0; i2 < 5; i2++) { + try { + locvar1 = stackFrame.visibleVariableByName(names[i2][0]); + locvar2 = stackFrame.visibleVariableByName(names[i2][1]); + log2(" : tested type: " + locvar1.typeName()); + log2(" : tested variables: " + names[i2][0] + " " + names[i2][1]); + if (locvar1 != null && locvar2 != null) { + Value val1 = stackFrame.getValue(locvar1); + stackFrame.setValue(locvar2, val1); + Value val2 = stackFrame.getValue(locvar2); + if ( !val1.equals(val2)) { + log3("ERROR: !val1.equals(val2)"); + expresult = returnCode1; + } + } else { + log3("ERROR: locvar1 != null && locvar2 != null"); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue003/setvalue003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue003/setvalue003a.java new file mode 100644 index 00000000000..040066b3e01 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue003/setvalue003a.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.setValue.setvalue003; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the setvalue003 JDI test. + */ + +public class setvalue003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.setValue()
    + * complies with its spec in case when a tested program
    + * is prepared with full information (see README file),
    + * hence, AbsentInformationException is not expected to happen.
    + * The test checks up throwing InvalidTypeException
    + *
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, and after getting the thread2 suspended,
    + * checks up that for each in primitive types
    + * (1) setValue(PrimitiveType variable, null) does throw whereas
    + * (2) setValue(Object variable, null); does not throw
    + * InvalidTypeException
    + *
    + */ + +public class setvalue004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/setValue/setvalue004/setvalue004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new setvalue004().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.setValue.setvalue004.setvalue004a"; + + private String testedClassName = + "nsk.jdi.StackFrame.setValue.setvalue004.Threadsetvalue004a"; + + //String mName = "nsk.jdi.StackFrame.setValue"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue004a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + + String names[] = { "bl1", "bt1", "ch1", "db1", + "fl1", "in1", "ln1", "sh1" }; + + log2(" checking up exception for: stackFrame.setValue(PrimitiveType variable, null);"); + for ( int i2 = 0; i2 < 8; i2++ ) { + + try { + locvar1 = stackFrame.visibleVariableByName(names[i2]); + log2(" checking up exception for: LocalVariable of " + locvar1.typeName() + " type"); + stackFrame.setValue(locvar1, null); + log3("ERROR: no Exception"); + expresult = returnCode1; + } catch ( java.lang.IllegalArgumentException e1 ) { + log3("ERROR: java.lang.IllegalArgumentException "); + expresult = returnCode1; + } catch ( InvalidTypeException e2 ) { + log2(" : InvalidTypeException "); + } catch ( ClassNotLoadedException e3 ) { + log3("ERROR: ClassNotLoadedException "); + expresult = returnCode1; + } catch ( InvalidStackFrameException e4 ) { + log3("ERROR: InvalidStackFrameException "); + expresult = returnCode1; + } catch ( VMMismatchException e5 ) { + log3("ERROR: VMMismatchException "); + expresult = returnCode1; + } catch ( AbsentInformationException e7 ) { + log3("ERROR: AbsentInformationException "); + expresult = returnCode1; + } catch ( Exception e6 ) { + log3("ERROR: UNSPECIFIED EXCEPTION: " + e6); + expresult = returnCode1; + } + } + + + String name = "testObj"; + + log2(" checking up exception for: stackFrame.setValue(Object variable, null);"); + try { + locvar1 = stackFrame.visibleVariableByName(name); + if (locvar1 != null) { + stackFrame.setValue(locvar1, null); + log2(" : no Exception"); + } else { + expresult = returnCode1; + log3("ERROR: locvar1 == null after: locvar1 = stackFrame.visibleVariableByName(name);"); + } + } catch ( java.lang.IllegalArgumentException e1 ) { + log3("ERROR: java.lang.IllegalArgumentException "); + expresult = returnCode1; + } catch ( InvalidTypeException e2 ) { + log3("ERROR: InvalidTypeException "); + expresult = returnCode1; + } catch ( ClassNotLoadedException e3 ) { + log3("ERROR: ClassNotLoadedException "); + expresult = returnCode1; + } catch ( InvalidStackFrameException e4 ) { + log3("ERROR: InvalidStackFrameException "); + expresult = returnCode1; + } catch ( VMMismatchException e5 ) { + log3("ERROR: VMMismatchException "); + expresult = returnCode1; + } catch ( AbsentInformationException e7 ) { + log3("ERROR: AbsentInformationException "); + expresult = returnCode1; + } catch ( Exception e6 ) { + log3("ERROR: UNSPECIFIED EXCEPTION: " + e6); + expresult = returnCode1; + } + + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue004/setvalue004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue004/setvalue004a.java new file mode 100644 index 00000000000..0c028b86498 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/setValue/setvalue004/setvalue004a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.setValue.setvalue004; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the setvalue004 JDI test. + */ + +public class setvalue004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.StackFrame.setValue()
    + * does not throw ClassNotLoadedException when a debugger part + * of the test attempts to set null value for a debuggee local variable + * which type has not yet been loaded through the appropriate class + * loader.

    + * + * The test works as follows. The debuggee part has two local + * variables: dummyVar of non-loaded type DummyType and + * finDummyVar of non-loaded type FinDummyType. + * Debugger part tries to provoke the exception by setting values of + * these variables. The test makes sure that class has not been loaded + * by the debuggee VM through the JDI method VirtualMachine.classesByName() + * which should return list of loaded classes only. + */ +public class setvalue005 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.StackFrame.setValue.setvalue005.setvalue005t"; + + // names of debuggee threads + static final String DEBUGGEE_THRDNAME = + "setvalue005tMainThr"; + + // tested debuggee local vars and theirs types + static final int VAR_NUM = 3; + static final String DEBUGGEE_VARS[][] = { + {"setvalue005tFindMe", "IGNORE MY TYPE"}, + {"dummyVar", "nsk.jdi.StackFrame.setValue.setvalue005.DummyType"}, + {"finDummyVar", "nsk.jdi.StackFrame.setValue.setvalue005.FinDummyType"} + }; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 67; + + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setvalue005().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "setvalue005t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef = null; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRDNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRDNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + // find a stack frame which belongs to the "setvalue005tMainThr" thread + StackFrame stFrame = findFrame(thrRef, DEBUGGEE_VARS[0][0]); + + for (int i=1; i + * com.sun.jdi.StackFrame.getValues()
    + * properly throws InvalidTypeException - if the value's type + * does not match type of specified variable.

    + * + * Debugger part of the test tries to provoke the exception by setting + * values of different primitive types and own DummyType which + * are not assignment compatible with the variable type, and not + * convertible without loss of information as well. + */ +public class setvalue006 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.StackFrame.setValue.setvalue006.setvalue006t"; + + // names of debuggee threads + static final String DEBUGGEE_THRDNAME = + "setvalue006tMainThr"; + + // tested debuggee local vars and theirs types + static final int VAR_NUM = 30; + static final String DEBUGGEE_VARS[][] = { + // list of debuggee's vars used to set values and ones + // used to get their wrong non-conversionable values, + // see section "5.1.2 Widening Primitive Conversion" in the JLS + {"setvalue006tFindMe", "doubleVar"}, + {"byteVar", "strVar"}, + {"byteVar", "shortVar"}, + {"byteVar", "intVar"}, + {"byteVar", "longVar"}, + {"byteVar", "floatVar"}, + {"byteVar", "doubleVar"}, + {"shortVar", "intVar"}, + {"shortVar", "longVar"}, + {"shortVar", "floatVar"}, + {"shortVar", "doubleVar"}, + {"intVar", "longVar"}, + {"intVar", "floatVar"}, + {"intVar", "doubleVar"}, + {"longVar", "floatVar"}, + {"longVar", "doubleVar"}, + {"floatVar", "doubleVar"}, + {"doubleVar", "setvalue006tFindMe"}, + {"charVar", "strVar"}, + {"booleanVar", "byteVar"}, + {"strVar", "charVar"}, + // see section "5.1.1 Identity Conversions" in the JLS: + // "the only permitted conversion that involves the type boolean is + // the identity conversion from boolean to boolean" + {"byteVar", "booleanVar"}, + {"shortVar", "booleanVar"}, + {"intVar", "booleanVar"}, + {"longVar", "booleanVar"}, + {"floatVar", "booleanVar"}, + {"doubleVar", "booleanVar"}, + {"charVar", "booleanVar"}, + {"strVar", "booleanVar"}, + {"setvalue006tFindMe", "booleanVar"} + }; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 72; + + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setvalue006().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "setvalue006t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef = null; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRDNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRDNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + // find a stack frame which belongs to the "setvalue006tMainThr" thread + StackFrame stFrame = findFrame(thrRef, DEBUGGEE_VARS[0][0]); + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.thisObject()
    + * complies with its spec when the frame represents
    + * a non-native, non-static method.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, and performs the following.
    + * 1) After getting a thread2 suspended but before to resume it,
    + * StackFrame.thisObject() is invoked and
    + * its returned value is casted to ThreadReference.
    + * Since the thread is not resumed yet, neither
    + * InvalidStackFrameException no ClassCastException must be thrown.
    + * 2) After resuming the thread2, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class thisobject001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/thisObject/thisobject001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new thisobject001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.thisObject.thisobject001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.thisObject.Threadthisobject001a"; + + //String mName = "nsk.jdi.StackFrame.thisObject"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + ObjectReference thisobj; + + log2(" getting stackFrame.thisObject() which must not be null"); + try { + thisobj = stackFrame.thisObject(); + if (thisobj == null) { + log3("ERROR: stackFrame.thisObject()==null for non-static method"); + expresult = returnCode1; + break label1; + } + log2(" casting ObjectReference to ThreadReference"); + ThreadReference t = (ThreadReference) thisobj; + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameExceprtion before the thread is resumed"); + expresult = returnCode1; + break label1; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException for ThreadReference t = (ThreadReference) thisobj;"); + expresult = returnCode1; + break label1; + } + + log2(" resuming the thread2"); + eventSet.resume(); + + log2(" checking up throwing InvalidStackFrameExceprtion after the thread2 is resumed"); + try { + thisobj = stackFrame.thisObject(); + log3("ERROR: no InvalidStackFrameExceprtion after the thread2 is resumed"); + expresult = returnCode1; + break label1; + } catch ( InvalidStackFrameException e ) { + } + + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001/TestDescription.java new file mode 100644 index 00000000000..16b38e6f7dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/thisObject/thisobject001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.thisObject() + * complies with its spec: + * public ObjectReference thisObject() + * Returns the value of 'this' for the current frame. + * The ObjectReference for 'this' is only available for + * non-native instance methods. + * Returns: an ObjectReference, + * or null if the frame represents a native or static method. + * Throws: InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * when the frame represents a non-native, non-static method. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.thisObject.thisobject001; + * the debuggee program - nsk.jdi.StackFrame.thisObject.thisobject001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.thisObject.thisobject001 + * nsk.jdi.StackFrame.thisObject.thisobject001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.thisObject.thisobject001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001a.java new file mode 100644 index 00000000000..80d06e0364f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject001a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.thisObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the thisobject001 JDI test. + */ + +public class thisobject001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.thisObject()
    + * complies with its spec for a static method.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, and performs the following.
    + * 1) After getting a thread2 suspended but before to resume it,
    + * StackFrame.thisObject() is invoked and
    + * its returned value must be null.
    + * Since the thread is not resumed yet,
    + * InvalidStackFrameException must not be throw.
    + * 2) After resuming the thread2, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class thisobject002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/thisObject/thisobject002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new thisobject002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.thisObject.thisobject002a"; + + private String testedClassName = + "nsk.jdi.StackFrame.thisObject.Threadthisobject002a"; + + //String mName = "nsk.jdi.StackFrame.thisObject"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + ObjectReference thisobj; + + log2(" getting stackFrame.thisObject() which must not be null"); + try { + thisobj = stackFrame.thisObject(); + if (thisobj != null) { + log3("ERROR: stackFrame.thisObject() != null for a static method"); + expresult = returnCode1; + break label1; + } + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameExceprtion before the thread2 is resumed"); + expresult = returnCode1; + break label1; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException for ThreadReference t = (ThreadReference) thisobj;"); + expresult = returnCode1; + break label1; + } + + log2(" resuming the thread2"); + eventSet.resume(); + + log2(" checking up throwing InvalidStackFrameExceprtion after the thread2 is resumed"); + try { + thisobj = stackFrame.thisObject(); + log3("ERROR: no InvalidStackFrameExceprtion after the thread2 is resumed"); + expresult = returnCode1; + break label1; + } catch ( InvalidStackFrameException e ) { + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002/TestDescription.java new file mode 100644 index 00000000000..e3363086932 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/thisObject/thisobject002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.thisObject() + * complies with its spec: + * public ObjectReference thisObject() + * Returns the value of 'this' for the current frame. + * The ObjectReference for 'this' is only available for + * non-native instance methods. + * Returns: an ObjectReference, + * or null if the frame represents a native or static method. + * Throws: InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * when the frame represents a static method. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.thisObject.thisobject002; + * the debuggee program - nsk.jdi.StackFrame.thisObject.thisobject002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.thisObject.thisobject002 + * nsk.jdi.StackFrame.thisObject.thisobject002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.thisObject.thisobject002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002a.java new file mode 100644 index 00000000000..78961e0d4ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thisObject/thisobject002a.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.thisObject; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the thisobject002 JDI test. + */ + +public class thisobject002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.thread()
    + * complies with its spec.
    + *
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * 1) After getting a thread2 suspended but before to resume it,
    + * the name of the thread2 got with StackFrame.thread() is equal to
    + * its name used for suspending the thread2.
    + * Since the thread2 is not resumed yet,
    + * InvalidStackFrameException must not be thrown.
    + * 2) After resuming the thread2, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class thread001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/thread/thread001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new thread001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.thread.thread001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.thread.Threadthread001a"; + + //String mName = "nsk.jdi.StackFrame.thread"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("location001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + // BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + log2(" checking up that thread2's two names are equal"); + try { + if (!stackFrame.thread().name().equals(threadName) ) { + log3("ERROR: !stackFrame.thread().name().equals(threadName)"); + expresult = returnCode1; + break label1; + } + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameException before the thread2 is resumed"); + expresult = returnCode1; + break label1; + } + + log2(" resuming the thread2 and "); + eventSet.resume(); + + log2(" checking up throwing InvalidStackFrameException"); + try { + ThreadReference t = stackFrame.thread(); + expresult = 1; + log3("ERROR: no InvalidStackFrameExceprtion after the thread2 is resumed"); + } catch ( InvalidStackFrameException e ) { + } + } + eventSet.resume(); // for case if thread2 was not resumed because of error in a check + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001/TestDescription.java new file mode 100644 index 00000000000..50acc4329d0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/thread/thread001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.thread() + * complies with its spec: + * public ThreadReference thread() + * Returns the thread under which this frame's method is running. + * Returns: a ThreadReference which mirrors the frame's thread. + * Throws: InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.thread.thread001; + * the debuggee program - nsk.jdi.StackFrame.thread.thread001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.thread.thread001 + * nsk.jdi.StackFrame.thread.thread001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.thread.thread001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001a.java new file mode 100644 index 00000000000..ccba427ba63 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/thread/thread001a.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the thread001 JDI test. + */ + +public class thread001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + BreakpointRequest brkp = debuggee.setBreakpoint(debuggeeClass, + tostring001a.brkpMethodName, + tostring001a.brkpLineNumber); + debuggee.resume(); + + debuggee.sendSignal(SIGNAL_GO); + Event event = null; + + // waiting the breakpoint event + try { + event = debuggee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected InterruptedException while waiting for Breakpoint event"); + } + if (!(event instanceof BreakpointEvent)) { + debuggee.resume(); + throw new Failure("BreakpointEvent didn't arrive"); + } + + ThreadReference thread = ((BreakpointEvent)event).thread(); + List frames = null; + try { + frames = thread.frames(); + } catch(IncompatibleThreadStateException e) { + throw new Failure("Unexpected IncompatibleThreadStateException when getting list of frames"); + } + + display("Checking toString() method for debuggee's stack frames..."); + + // Check all methods from debuggee + for (int i = 0; i < frames.size(); i++) { + + StackFrame stackFrame = null; + try { + stackFrame = (StackFrame)frames.get(i); + String str = stackFrame.toString(); + if (str == null) { + complain("toString() returns null for stack frame #" + i); + exitStatus = Consts.TEST_FAILED; + } else if (str.length() == 0) { + complain("toString() returns empty string for stack frame #" + i); + exitStatus = Consts.TEST_FAILED; + } else { + display("toString() returns for stack frame #" + i + " : " + str); + } + } catch(Exception e) { + complain("Unexpected " + e + " when getting StackFrame for stack frame #" + i); + exitStatus = Consts.TEST_FAILED; + } + + } + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..7f01c79ca2e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/toString/tostring001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public toString() method of an implementing class of + * com.sun.jdi.StackFrame interface. + * The test checks an assertion: + * In conformity with the contract for java.lang.Object.toString(), + * the overrided method returns representing non-empty string for + * a StackFrame mirror of a debuggee's stack frame. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for StackFrame + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.toString.tostring001 + * nsk.jdi.StackFrame.toString.tostring001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001a.java new file mode 100644 index 00000000000..4542991e33a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/toString/tostring001a.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.StackFrame.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class tostring001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + public final static String brkpMethodName = "breakHere"; + public final static int brkpLineNumber = 92; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(tostring001.SIGNAL_READY); + breakHere(); + receiveSignal(tostring001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + public static void breakHere () { + receiveSignal(tostring001.SIGNAL_GO); + log.display("breakpoint line"); // brkpLineNumber + } +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001.java new file mode 100644 index 00000000000..eb53cb45ee4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001.java @@ -0,0 +1,608 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.visibleVariableByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.visibleVariableByName()
    + * complies with its spec in case when a tested program
    + * is prepared with line number information,
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, and performs the following.
    + * 1) After getting a thread2 suspended but before to resume it,
    + * StackFrame.visibleVariablesByName() is used to check up
    + * that the following is true:
    + * - two visible variables - local in a tested method;
    + * - invisible variable - a class variable;
    + * - invisible variable - local in another method;
    + * - invisible variable - local in the tested method.
    + * 2) After resuming the thread2, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class visiblevarbyname001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new visiblevarbyname001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.visibleVariableByName.Threadvisiblevarbyname001a"; + + //String mName = "nsk.jdi.StackFrame.visibleVariableByName"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + String name0 = "invi_i0"; + String name1 = "vi_i1"; + String name2 = "invi_i2"; + String name3 = "invi_i3"; + + + label01: { + log2(" checking up visibility of vi_i1"); + try { + locvar1 = stackFrame.visibleVariableByName(name1); + + if (locvar1 == null) { + log3("ERROR: locvar1 == null for 'vi_i1'"); + expresult = returnCode1; + break label01; + } + if (!locvar1.name().equals(name1)) { + log3("ERROR: !locvar1.name().equals(name1) for 'vi_i1'"); + expresult = returnCode1; + break label01; + } + log2(" vi_i1 is OK"); + } catch ( AbsentInformationException e1 ) { + log3("ERROR: AbsentInformationException for locvar1"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e2 ) { + log3("ERROR: InvalidStackFrameExceprtion before the thread2 is resumed"); + expresult = returnCode1; + } + } + label02: { + log2(" checking up invisibility of invi_i0"); + try { + locvar1 = stackFrame.visibleVariableByName(name0); + if (locvar1 != null) { + log3("ERROR: locvar1 == null for 'invi_i0'"); + expresult = returnCode1; + break label02; + } + log2(" invi_i0 is OK"); + } catch ( AbsentInformationException e1 ) { + log3("ERROR: AbsentInformationException for locvar1"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e2 ) { + log3("ERROR: InvalidStackFrameExceprtion before the thread2 is resumed"); + expresult = returnCode1; + } + } + label03: { + log2(" checking up invisibility of invi_i2"); + try { + locvar1 = stackFrame.visibleVariableByName(name2); + if (locvar1 != null) { + log3("ERROR: locvar1 != null for 'invi_i2'"); + expresult = returnCode1; + break label03; + } + log2(" invi_i2 is OK"); + } catch ( AbsentInformationException e1 ) { + log3("ERROR: AbsentInformationException for locvar1"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e2 ) { + log3("ERROR: InvalidStackFrameExceprtion before the thread2 is resumed"); + expresult = returnCode1; + } + } + label04: { + log2(" checking up invisibility of invi_i3"); + try { + locvar1 = stackFrame.visibleVariableByName(name3); + if (locvar1 != null) { + log3("ERROR: locvar1 != null for 'invi_i3'"); + expresult = returnCode1; + break label04; + } + log2(" invi_i3 is OK"); + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for locvar1"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameExceprtion before the thread2 is resumed"); + expresult = returnCode1; + } + } + + log2(" resuming the thread2"); + eventSet.resume(); + + if (expresult == returnCode1) + break label1; + + log2(" checking up InvalidStackFrameException after resuming the thread2"); + try { + locvar2 = stackFrame.visibleVariableByName(name1); + log3("ERROR: no InvalidStackFrameExceprtion after the thread2 is resumed"); + expresult = returnCode1; + break label1; + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for locvar2"); + expresult = returnCode1; + break label1; + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameException for locvar2"); + } + + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001/TestDescription.java new file mode 100644 index 00000000000..0729b439891 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.visibleVariableByName() + * complies with its spec: + * public LocalVariable visibleVariableByName(java.lang.String name) + * throws AbsentInformationException + * Finds a LocalVariable that matches the given name and is visible + * at the current frame location. + * See visibleVariables() for more information on visibility. + * Parameters: name - the variable name to find + * Returns: the matching LocalVariable, or + * null if there is no visible variable with the given name. + * Throws: AbsentInformationException - + * if there is no line number information for this method. + * InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname001; + * the debuggee program - nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname001 + * nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname001a + * + * @comment make sure visiblevarbyname001a is compiled with full debug info + * @clean nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname001a + * @compile -g:lines,source,vars ../visiblevarbyname001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001a.java new file mode 100644 index 00000000000..f9ff4bd6581 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname001a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.visibleVariableByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the visiblevarbyname001 JDI test. + */ + +public class visiblevarbyname001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.visibleVariableByName()
    + * complies with its spec in case when a tested program
    + * is prepared with no full information,
    + * hence, AbsentInformationException is expected to happen.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, and after getting the thread2 suspended,
    + * it resumes it the thread2, invokes the tested method second time
    + * and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class visiblevarbyname002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new visiblevarbyname002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname002a"; + + private String testedClassName = + "nsk.jdi.StackFrame.visibleVariableByName.Threadvisiblevarbyname002a"; + + //String mName = "nsk.jdi.StackFrame.visibleVariableByName"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + String name1 = "vi_i1"; + + log2(" checking up visibility of vi_i1"); + try { + locvar1 = stackFrame.visibleVariableByName(name1); + log3("ERROR: no AbsentInformationException for locvar1"); + expresult = returnCode1; + } catch ( AbsentInformationException e ) { + log2(" : AbsentInformationException is thrown: OK"); + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameExceprtion before the thread is resumed"); + } + + log2(" resuming the thread2"); + eventSet.resume(); + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002/TestDescription.java new file mode 100644 index 00000000000..4d6b1006c9f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.visibleVariableByName() + * complies with its spec: + * public LocalVariable visibleVariableByName(java.lang.String name) + * throws AbsentInformationException + * Finds a LocalVariable that matches the given name and is visible + * at the current frame location. + * See visibleVariables() for more information on visibility. + * Parameters: name - the variable name to find + * Returns: the matching LocalVariable, or + * null if there is no visible variable with the given name. + * Throws: AbsentInformationException - + * if there is no line number information for this method. + * InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * when a tested program is prepared with no full information, + * hence, AbsentInformationException is expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname002; + * the debuggee program - nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname002 + * nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.visibleVariableByName.visiblevarbyname002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002a.java new file mode 100644 index 00000000000..924557532ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariableByName/visiblevarbyname002a.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.visibleVariableByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the visiblevarbyname002 JDI test. + */ + +public class visiblevarbyname002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.visibleVariables()
    + * complies with its spec in case when a tested program
    + * is prepared with line number information,
    + * hence, AbsentInformationException is not expected to happen.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, and performs the following.
    + * 1) StackFrame.visiblevariables() is used to check up
    + * that returned List contains expected number and names
    + * of visible variables.
    + * 2) After resuming the thread2, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class visiblevariables001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/visibleVariables/visiblevariables001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new visiblevariables001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.visibleVariables.visiblevariables001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.visibleVariables.Threadvisiblevariables001a"; + + //String mName = "nsk.jdi.StackFrame.visibleVariables"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + + String name0 = null; + String name1 = null; + String testedName0 = "vi_i1"; + String testedName1 = "vi_bl1"; + + List visiblevars = null; + + log2(" checking up names of visible variables in the List"); + try { + visiblevars = stackFrame.visibleVariables(); + if (visiblevars.size() != 2) { + log3("ERROR: visiblevars.size() != 2 :" + visiblevars.size()); + expresult = returnCode1; + } else { + name0 = ( (LocalVariable) visiblevars.get(0) ).name(); + name1 = ( (LocalVariable) visiblevars.get(1) ).name(); + + if (name0.equals(testedName0)) { + if (!name1.equals(testedName1)) { + log3("ERROR: !name1.equals(testedName1)"); + expresult = returnCode1; + } + } else if (name0.equals(testedName1)) { + if (!name1.equals(testedName0)) { + log3("ERROR: !name1.equals(testedName0)"); + expresult = returnCode1; + } + } else { + log3("ERROR: !name0.equals(testedName1)"); + expresult = returnCode1; + } + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for stackFrame.visiblevariables()"); + expresult = returnCode1; + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameExceprtion before the thread2 is resumed"); + expresult = returnCode1; + } + + log2(" resuming the thread2"); + eventSet.resume(); + + if (expresult == returnCode1) + break label1; + + log2(" checking up InvalidStackFrameException after resuming the thread2"); + try { + visiblevars = stackFrame.visibleVariables(); + log3("ERROR: no InvalidStackFrameExceprtion after the thread2 is resumed"); + expresult = returnCode1; + break label1; + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for locvar2"); + expresult = returnCode1; + break label1; + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameException is thrown: OK"); + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001/TestDescription.java new file mode 100644 index 00000000000..3336d0b4c23 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001/TestDescription.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/visibleVariables/visiblevariables001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.visibleVariables() + * complies with its spec: + * public java.util.List visibleVariables() + * throws AbsentInformationException + * Returns a list containing each LocalVariable that + * can be accessed from this frame's location. + * Visibility is based on the code index of the current instruction of + * this StackFrame. Each variable has a range of byte code indices in which + * it is accessible. If this stack frame's method matches + * this variable's method and if the code index of this StackFrame is within + * the variable's byte code range, the variable is visible. + * A variable's byte code range is at least as large as the scope of that + * variable, but can continue beyond the end of the scope under certain + * circumstances: + * the compiler/VM does not immediately reuse the variable's slot. + * the compiler/VM is implemented to report the extended range that + * would result from the item above. + * The advantage of an extended range is that variables from recently + * exited scopes may remain available for examination (this is especially + * useful for loop indices). If, as a result of the extensions above, + * the current frame location is contained within the range of + * multiple local variables of the same name, the variable with + * the highest-starting range is chosen for the returned list. + * Returns: the list of LocalVariable objects currently visible. + * Throws: AbsentInformationException - + * if there is no line number information for this method. + * InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * when a tested program is prepared with full information (see COMMENTS), + * hence, AbsentInformationException is not expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.visibleVariables.visiblevariables001; + * the debuggee program - nsk.jdi.StackFrame.visibleVariables.visiblevariables001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * This test is option depended, + * that is its .cfg file contains the option + * JAVAC_OPTS=-g + * because at the date of preparing the test + * javac prepared full information for the test only + * been invoked with the option. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.visibleVariables.visiblevariables001 + * nsk.jdi.StackFrame.visibleVariables.visiblevariables001a + * + * @comment make sure visiblevariables001a is compiled with full debug info + * @clean nsk.jdi.StackFrame.visibleVariables.visiblevariables001a + * @compile -g:lines,source,vars ../visiblevariables001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.visibleVariables.visiblevariables001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001a.java new file mode 100644 index 00000000000..76fc656852b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables001a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.visibleVariables; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the visiblevariables001 JDI test. + */ + +public class visiblevariables001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * StackFrame.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StackFrame.visibleVariables()
    + * complies with its spec in case when a tested program
    + * is prepared with no full information,
    + * hence, AbsentInformationException is expected to happen.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up a breakpoint, and performs the following.
    + * 1) StackFrame.visiblevariables() is used to check up
    + * that AbsentInformationException is do thrown.
    + * 2) After resuming the thread2, the tested method is invoked
    + * second time and InvalidStackFrameException must be thrown.
    + *
    + */ + +public class visiblevariables002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StackFrame/visibleVariables/visiblevariables002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new visiblevariables002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StackFrame.visibleVariables.visiblevariables002a"; + + private String testedClassName = + "nsk.jdi.StackFrame.visibleVariables.Threadvisiblevariables002a"; + + //String mName = "nsk.jdi.StackFrame.visibleVariables"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + LocalVariable locvar1 = null; + LocalVariable locvar2 = null; + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + thread2 = debuggee.threadByName(threadName); + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + log2(" the thread2 is at the breakpoint"); + log2(" the check that the thread2 is suspended at the breakpoint"); + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + expresult = returnCode1; + break label1; + } + + + String name0 = null; + String name1 = null; + String testedName0 = "vi_i1"; + String testedName1 = "vi_bl1"; + + List visiblevars = null; + + log2(" invoking stackFrame.visibleVariables() first time before resuming thread2"); + try { + visiblevars = stackFrame.visibleVariables(); + + log3("ERROR: no Exception thrown"); + expresult = returnCode1; + } catch ( AbsentInformationException e ) { + log2(" : AbsentInformationException for stackFrame.visiblevariables()"); + } catch ( InvalidStackFrameException e ) { + log3("ERROR: InvalidStackFrameExceprtion before the thread2 is resumed"); + expresult = returnCode1; + } + + log2(" resuming the thread2"); + eventSet.resume(); + + log2(" invoking stackFrame.visibleVariables() second time after resuming thread2"); + try { + visiblevars = stackFrame.visibleVariables(); + + log3("ERROR: no Exception thrown"); + expresult = returnCode1; + } catch ( AbsentInformationException e ) { + log2(" : AbsentInformationException for stackFrame.visiblevariables()"); + } catch ( InvalidStackFrameException e ) { + log2(" : InvalidStackFrameExceprtion before the thread2 is resumed"); + } + } + + log2(" resuming the thread2 for case it was suspended but not resumed yet"); + eventSet.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002/TestDescription.java new file mode 100644 index 00000000000..0caaab23d25 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002/TestDescription.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StackFrame/visibleVariables/visiblevariables002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StackFrame. + * The test checks up that a result of the method + * com.sun.jdi.StackFrame.visibleVariables() + * complies with its spec: + * public java.util.List visibleVariables() + * throws AbsentInformationException + * Returns a list containing each LocalVariable that + * can be accessed from this frame's location. + * Visibility is based on the code index of the current instruction of + * this StackFrame. Each variable has a range of byte code indices in which + * it is accessible. If this stack frame's method matches + * this variable's method and if the code index of this StackFrame is within + * the variable's byte code range, the variable is visible. + * A variable's byte code range is at least as large as the scope of that + * variable, but can continue beyond the end of the scope under certain + * circumstances: + * the compiler/VM does not immediately reuse the variable's slot. + * the compiler/VM is implemented to report the extended range that + * would result from the item above. + * The advantage of an extended range is that variables from recently + * exited scopes may remain available for examination (this is especially + * useful for loop indices). If, as a result of the extensions above, + * the current frame location is contained within the range of + * multiple local variables of the same name, the variable with + * the highest-starting range is chosen for the returned list. + * Returns: the list of LocalVariable objects currently visible. + * Throws: AbsentInformationException - + * if there is no line number information for this method. + * InvalidStackFrameException - + * if this stack frame has become invalid. + * Once the frame's thread is resumed, + * the stack frame is no longer valid. + * when a tested program is prepared with no full information, + * hence, AbsentInformationException is expected to happen. + * The test works as follows: + * The debugger program - nsk.jdi.StackFrame.visibleVariables.visiblevariables002; + * the debuggee program - nsk.jdi.StackFrame.visibleVariables.visiblevariables002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StackFrame.visibleVariables.visiblevariables002 + * nsk.jdi.StackFrame.visibleVariables.visiblevariables002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StackFrame.visibleVariables.visiblevariables002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002a.java new file mode 100644 index 00000000000..37652469c50 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StackFrame/visibleVariables/visiblevariables002a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StackFrame.visibleVariables; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the visiblevariables002 JDI test. + */ + +public class visiblevariables002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i line 1, source 1 + * line 2 --> line 1, source 2 + * line 3 --> line 1, source 3 + * (lines in "Test stratum" has same numbers but different sources) + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 1 non-Java stratum and for this stratum following line mapping is defined: + * "Java" "TestStratum" + * + * 32 --> 1000, source1 + * 33 --> 1000, source2 + * ... ... + * sde_testMethod1 + * 43 --> 1100, source1 + * 44 --> 1100, source2 + * ... ... + * sde_testMethod1 + * 54 --> 1200, source1 + * 55 --> 1200, source2 + * ... ... + * Then debugger forces debuggee to load 'TestClass1' from updated class file, starts event listener thread which saves all received StepEvents, + * enables StepEvent request(class filter is used to receive events only for 'TestClass1') and forces debuggee to execute all methods defined in 'TestClass1'. + * When all methods was executed debugger checks up that StepEvents was generated for each location specified for 'TestStratum'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepEvent._itself_.stepEvent003.stepEvent003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepEvent._itself_.stepEvent003.stepEvent003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + */ + +package nsk.jdi.StepEvent._itself_.stepEvent003; + +import java.io.*; +import java.util.*; +import com.sun.jdi.request.StepRequest; +import nsk.share.Consts; +import nsk.share.jdi.EventHandler; +import nsk.share.jdi.sde.*; + +public class stepEvent003 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new stepEvent003().runIt(argv, out); + } + + private EventHandler eventHandler; + + protected List preparePatchedClassFile(String className) { + /* + * Create file with following line mapping: + * + * "Java" "TestStratum" + * + * + * 32 --> 1000, source1 + * ... + * 39 --> 1000, source8 + * + * sde_testMethod1 + * 43 --> 1100, source1 + * ... + * 50 --> 1100, source8 + * + * sde_testMethod2 + * 54 --> 1200, source1 + * ... + * 61 --> 1200, source8 + */ + + String sourceName = testStratumSourceName; + String sourcePath = testStratumSourcePath; + String stratumName = testStratumName; + + String smapFileName = "TestSMAP.smap"; + SmapGenerator smapGenerator = new SmapGenerator(); + + SmapStratum smapStratum = new SmapStratum(stratumName); + + List testStratumData = new ArrayList(); + + for (int i = 0; i < 8; i++) { + String source = sourceName + (i + 1); + String path = sourcePath + (i + 1); + testStratumData.add(new DebugLocation(source, path, + "", 1000 + i, INIT_LINE + i)); + smapStratum.addFile(source, path); + + testStratumData.add(new DebugLocation(source, path, + "sde_testMethod1", 1100 + i, METHOD1_LINE + i)); + smapStratum.addFile(source, path); + + testStratumData.add(new DebugLocation(source, path, + "sde_testMethod2", 1200 + i, METHOD2_LINE + i)); + smapStratum.addFile(source, path); + } + + for (DebugLocation debugLocation : testStratumData) { + smapStratum.addLineData(debugLocation.inputLine, debugLocation.sourceName, 1, debugLocation.outputLine, 1); + } + + smapGenerator.addStratum(smapStratum, false); + + savePathcedClassFile(className, smapGenerator, smapFileName); + + return testStratumData; + } + + public void doTest() { + String className = TestClass1.class.getName(); + + List locations = preparePatchedClassFile(className); + + initDefaultBreakpoint(); + + eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + StepEventListener stepEventListener = new StepEventListener(); + eventHandler.addListener(stepEventListener); + + StepRequest stepRequest = debuggee.getEventRequestManager().createStepRequest( + debuggee.threadByName(SDEDebuggee.mainThreadName), + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + + stepRequest.setSuspendPolicy(StepRequest.SUSPEND_EVENT_THREAD); + stepRequest.addClassFilter(TestClass1.class.getName()); + stepRequest.enable(); + + vm.setDefaultStratum(testStratumName); + + pipe.println(SDEDebuggee.COMMAND_EXECUTE_TEST_METHODS + ":" + className); + + if (!isDebuggeeReady()) + return; + + stepEventListener.waitBreakpointEvent(); + + compareLocations(stepEventListener.stepLocations(), locations, testStratumName); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/TestClass1.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/TestClass1.java new file mode 100644 index 00000000000..4162f14f240 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/TestClass1.java @@ -0,0 +1,1072 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.StepEvent._itself_.stepEvent004; + +// THIS TEST IS LINE NUMBER SENSITIVE + +public class TestClass1 // Class contains 10 methods with 100 locations, do not edit this file because of line numbers are hardcoded in test +{ + public TestClass1() + { + super(); // stepEvent004.INIT_LINE + } + public void sde_testMethod1() + { + int i = 0; // stepEvent004.METHOD1_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod2() + { + int i = 0; // stepEvent004.METHOD2_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod3() + { + int i = 0; // stepEvent004.METHOD3_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod4() + { + int i = 0; // stepEvent004.METHOD4_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod5() + { + int i = 0; // stepEvent004.METHOD5_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod6() + { + int i = 0; // stepEvent004.METHOD6_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod7() + { + int i = 0; // stepEvent004.METHOD7_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod8() + { + int i = 0; // stepEvent004.METHOD8_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod9() + { + int i = 0; // stepEvent004.METHOD9_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } + + public void sde_testMethod10() + { + int i = 0; // stepEvent004.METHOD10_LINE + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + i++; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/stepEvent004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/stepEvent004.java new file mode 100644 index 00000000000..331d0fbb36b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepEvent004/stepEvent004.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/StepEvent/_itself_/stepEvent004. + * VM Testbase keywords: [jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test scenario: + * There is class 'TestClass1' defined in test package wich has 10 method with 100 locations in each method. + * Debugger creates copy of class file for this class with SourceDebugExtension attribute which contains informations for 3 + * stratums('TestStratum1'-'TestStratum3') and for all this stratums following line mapping is defined: + * "Java" "TestStratum" + * + * 31 --> 1001, source1 + * sde_testMethod1 + * 35 --> 2000, source1 + * ... ... + * 135 --> 2100, source1 + * sde_testMethod2 + * 139 --> 3000, source1 + * ... ... + * 239 --> 3100, source1 + * ... ... + * sde_testMethod10 + * 971 --> 11000, source1 + * ... ... + * 1071 --> 11100, source1 + * Then debugger forces debuggee to load 'TestClass1' from updated class file, starts event listener thread which saves all received StepEvents + * and enables StepEvent request(class filter is used to receive events only for 'TestClass1'). + * for TestStratum in 'TestStratum1'-'TestStratum3' + * do + * - set TestStratum as VM default + * - force debuggee to execute all methods defined in 'TestClass1' + * - when all methods was executed check up that StepEvents was generated for each location specified for TestStratum + * Described event generation is performed 10 times. + * done + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepEvent._itself_.stepEvent004.stepEvent004 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepEvent._itself_.stepEvent004.stepEvent004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.StepEvent._itself_.stepEvent004; + +import java.io.*; +import java.util.*; +import com.sun.jdi.request.StepRequest; +import nsk.share.Consts; +import nsk.share.jdi.EventHandler; +import nsk.share.jdi.sde.*; + +public class stepEvent004 extends SDEDebugger { + private static final int INIT_LINE = 31; + private static final int METHOD1_LINE = 35; + private static final int METHOD2_LINE = 139; + private static final int METHOD3_LINE = 243; + private static final int METHOD4_LINE = 347; + private static final int METHOD5_LINE = 451; + private static final int METHOD6_LINE = 555; + private static final int METHOD7_LINE = 659; + private static final int METHOD8_LINE = 763; + private static final int METHOD9_LINE = 867; + private static final int METHOD10_LINE = 971; + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new stepEvent004().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + private EventHandler eventHandler; + + protected Map preparePatchedClassFile(String className, int testStratumCount) { + /* + * Create file with following line mapping for each test stratum: + * + * "Java" "TestStratum" + * + * 31 --> 1001, source1 + * sde_testMethod1 + * 35 --> 2000, source1 + * ... ... + * 135 --> 2100, source1 + * sde_testMethod2 + * 139 --> 3000, source1 + * ... ... + * 239 --> 3100, source1 + * ... ... + * sde_testMethod10 + * 971 --> 11000, source1 + * ... ... + * 1071 --> 11100, source1 + */ + String smapFileName = "TestSMAP.smap"; + SmapGenerator smapGenerator = new SmapGenerator(); + + Map testStratumData = new TreeMap(); + + for (int i = 0; i < testStratumCount; i++) { + String stratumName = testStratumName + (i + 1); + + LocationsData locationsData = new LocationsData(stratumName); + + String sourceName = testStratumSourceName + (i + 1); + String sourcePath = testStratumSourcePath + (i + 1); + + locationsData.paths.add(sourcePath); + + SmapStratum smapStratum = new SmapStratum(stratumName); + + List sourceLocations = new ArrayList(); + + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "", 1001, INIT_LINE)); + + for (int j = 0; j < 100; j++) { + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod1", 2000 + j, METHOD1_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod2", 3000 + j, METHOD2_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod3", 4000 + j, METHOD3_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod4", 5000 + j, METHOD4_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod5", 6000 + j, METHOD5_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod6", 7000 + j, METHOD6_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod7", 8000 + j, METHOD7_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod8", 9000 + j, METHOD8_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod9", 10000 + j, METHOD9_LINE + j)); + sourceLocations.add(new DebugLocation(sourceName, sourcePath, + "sde_testMethod10", 11000 + j, METHOD10_LINE + j)); + } + + locationsData.sourceLocations.put(sourceName, sourceLocations); + locationsData.allLocations.addAll(sourceLocations); + testStratumData.put(stratumName, locationsData); + + smapStratum.addFile(sourceName, sourcePath); + + for (DebugLocation debugLocation : sourceLocations) { + smapStratum.addLineData( + debugLocation.inputLine, + debugLocation.sourceName, + 1, + debugLocation.outputLine, + 1); + } + + smapGenerator.addStratum(smapStratum, false); + } + + savePathcedClassFile(className, smapGenerator, smapFileName); + + return testStratumData; + } + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = preparePatchedClassFile(className, testStratumCount); + + initDefaultBreakpoint(); + + eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + StepEventListener stepEventListener = new StepEventListener(); + eventHandler.addListener(stepEventListener); + + StepRequest stepRequest = debuggee.getEventRequestManager().createStepRequest( + debuggee.threadByName(SDEDebuggee.mainThreadName), + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + + stepRequest.setSuspendPolicy(StepRequest.SUSPEND_EVENT_THREAD); + stepRequest.addClassFilter(TestClass1.class.getName()); + stepRequest.enable(); + + // for each stratum defined for class + for (String stratumName : testStratumData.keySet()) { + log.display("Generate events for stratum: " + stratumName); + + vm.setDefaultStratum(stratumName); + + // perform event generation 10 times + for (int i = 0; i < 10; i++) { + stepEventListener.clearLocations(); + + pipe.println(SDEDebuggee.COMMAND_EXECUTE_TEST_METHODS + ":" + className); + + if (!isDebuggeeReady()) + return; + + stepEventListener.waitBreakpointEvent(); + + compareLocations( + stepEventListener.stepLocations(), + testStratumData.get(stratumName).allLocations, + stratumName); + } + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001.java new file mode 100644 index 00000000000..47bf5432157 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001.java @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepEvent._itself_; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.List; +import java.util.Iterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class stepevent001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static final String TEST_NAME = "nsk.jdi.StepEvent._itself_.stepevent001"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + + static private final int EXPECTED_EVENTS_COUNT = 10; + + static private Debugee debuggee; + static private IOPipe pipe; + static private VirtualMachine vm; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private StepRequest checkedRequest; + static private BreakpointRequest breakpointRequest; + static private Field checkedField; + static private Method checkedMethod; + static private Location checkedLocation; + static private ThreadReference checkedThread; + static private ReferenceType checkedClass; + + static private boolean testFailed; + static private long eventTimeout; + static private int eventsReceived, oldValue; + + static private volatile boolean methodCompleted; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + methodCompleted = false; + eventsReceived = 0; + oldValue = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + debuggee.resume(); + + try { + + // waiting for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + + // find checked location and create StepEventrequest + EventRequestManager eventRManager = vm.eventRequestManager(); + + log.display("Getting loaded class in debuggee"); + List classes = vm.classesByName(DEBUGGEE_NAME); + checkedClass = (ReferenceType) classes.get(0); + + log.display("Getting reference to main thread"); + Iterator threadIterator = vm.allThreads().iterator(); + while (threadIterator.hasNext()) { + ThreadReference curThread = (ThreadReference) threadIterator.next(); + if (curThread.name().equals("main")) { + checkedThread = curThread; + } + } + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to main thread"); + } + + log.display("Getting reference to method "); + List allMethods = checkedClass.methodsByName("foo"); + checkedMethod = (Method) allMethods.get(0); + + log.display("Getting reference to field "); + checkedField = checkedClass.fieldByName("counter"); + if (checkedField == null) { + throw new Failure("TEST BUG: unable to find reference to field "); + } + + log.display("Getting all locations"); + List allLineLocations; + try { + allLineLocations = checkedMethod.allLineLocations(); + } catch ( AbsentInformationException e) { + throw new Failure("TEST BUG: caught AbsentInformationException " + e); + } + + log.display("Getting checked location"); + Iterator locIterator = allLineLocations.iterator(); + while (locIterator.hasNext()) { + Location curLocation = (Location)locIterator.next(); + int curNumber = curLocation.lineNumber(); + if (curLocation.lineNumber() == stepevent001a.stepLineBegin) { + if (checkedLocation != null) { + throw new Failure("TEST BUG: multiple locations on breakpoint line"); + } else { + checkedLocation = curLocation; + } + } + } + + if (checkedLocation == null) { + throw new Failure("TEST BUG: incorrect line number of the location in method"); + } + + log.display("Creating auxiliary BreakpointRequest"); + if ((breakpointRequest = eventRManager.createBreakpointRequest(checkedLocation)) == null) { + throw new Failure("TEST BUG: unable to create BreakpointRequest"); + } + + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + + switch (breakpointRequest.suspendPolicy()) { + case EventRequest.SUSPEND_ALL: + log.display("suspend policy is SUSPEND_ALL"); + break; + case EventRequest.SUSPEND_EVENT_THREAD: + log.display("suspend policy is SUSPEND_EVENT_THREAD"); + break; + case EventRequest.SUSPEND_NONE: + log.display("suspend policy is SUSPEND_NONE"); + break; + default: + log.complain("TEST BUG: Unknown suspend policy!"); + } + + breakpointRequest.enable(); + log.display("Auxiliary BreakpointRequest is created"); + + log.display("Creating StepRequest"); + if ((checkedRequest = eventRManager.createStepRequest(checkedThread, + StepRequest.STEP_LINE, StepRequest.STEP_OVER)) == null) { + throw new Failure("TEST BUG: unable to create StepRequest"); + } + checkedRequest.addClassFilter(checkedClass); + log.display("StepRequest is created but not yet enabled"); + + // sdefine separate thread for handleing received events + class EventHandler extends Thread { + public void run() { + // handle events antil method invoking completes and all expected events received + while (!methodCompleted || eventsReceived < EXPECTED_EVENTS_COUNT) { + eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (InterruptedException e) { + log.complain("Unexpected InterruptedException while receiving event: " + e); + break; + } + + if (eventSet == null) { + log.display("No event"); + continue; + } + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + // handle BreakPointEvent + if (event instanceof BreakpointEvent) { + Location eventLocation = ((BreakpointEvent)event).location(); + log.display("BreakpointEvent received for location " + eventLocation.lineNumber()); + if (eventLocation.lineNumber() == stepevent001a.stepLineBegin) { + checkedRequest.enable(); + log.display("StepRequest is enabled upon receiving breakpoint event on checked line"); + } + } + + // handle StepEvent + if (event instanceof StepEvent) { + StepEvent castedEvent = (StepEvent) event; + log.display("Received event is StepEvent:\n " + event); + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 1: eventRequest is not equal to checked request"); + testFailed = true; + } else { + eventsReceived++; + log.display("Expected StepEvent received: " + eventsReceived + " times"); + } + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 2: eventThread is not equal to checked thread"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 3: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + Location eventLocation = castedEvent.location(); + int lineNumber = eventLocation.lineNumber(); + log.display("StepEvent received for location: " + lineNumber); + + try { + int counterValue = ((IntegerValue)checkedClass.getValue(checkedField)).value(); + log.display("Counter == " + counterValue); + if ( counterValue > oldValue) { + if (!eventThread.isSuspended()) { + log.complain("FAILURE 4: eventThread is not suspended"); + } else { + log.complain("FAILURE 5: StepEvent is generated after code execution"); + } + testFailed = true; + } + oldValue++; // modify for the next event + + } catch (ClassCastException e) { + log.complain("TEST BUG: cannot get value of field"); + testFailed = true; + } + + // disable StepEvent when last checked line reached + if (lineNumber == stepevent001a.stepLineEnd) { + log.display("Disabling event request at the last checked line: " + lineNumber); + checkedRequest.disable(); + } + + } + + // ignore all oter events + } + + log.display("Resuming event set"); + eventSet.resume(); + } + + log.display("eventHandler completed"); + } + } + + // start EventHandler thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to invoke method and generate StepEvents + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + log.display(""); + + // waiting for debuggee finished invoking method + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unknown debuggee's command: " + command); + } + methodCompleted = true; + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // Check if all StepEvents are received + if (eventsReceived < EXPECTED_EVENTS_COUNT) { + log.display("Too few StepEvents are received: " + eventsReceived); + testFailed = true; + } else if (eventsReceived > EXPECTED_EVENTS_COUNT) { + log.display("Too many StepEvents are received: " + eventsReceived); + testFailed = true; + } else { + log.display("All expected StepEvents are received"); + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + // disable event requests to prevent appearance of further events + if (checkedRequest != null && checkedRequest.isEnabled()) { + log.display("Disabling StepEvent request"); + checkedRequest.disable(); + } + if (breakpointRequest != null && breakpointRequest.isEnabled()) { + log.display("Disabling auxilary breakpoint request"); + breakpointRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001/TestDescription.java new file mode 100644 index 00000000000..d513a60e9c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent001/TestDescription.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/StepEvent/_itself_/stepevent001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises com.sun.jdi.event.StepEvent interface. + * The test checks the following assertions: + * - StepEvent is received by debugger for requested + * location if this location is reached by some executing thread + * in debugged VM; + * - received StepEvent has proper references to: + * debugged VM, + * executed thread, + * related StepRequest, + * checked location. + * - StepEvent is generated before the code at its location + * is executed. + * A debugger class - nsk.jdi.StepEvent._itself_.stepevent001 ; + * a debuggee class - nsk.jdi.StepEvent._itself_.stepevent001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger launches and connects to debuggee using the default launching + * connector. The debugger creates auxiliary BreakpointRequest on location in + * method of class where field is assigned + * to zero. The field in incremented on next lines of this method + * until exit. Also debugger creates but disables the StepRequest to receive + * StepEvent with size equals to STEP_LINE and depth equals to STEP_OVER + * The debugger starts thread for listening events delivered + * from debuggee, sends command to debuggee and waits for command . + * Upon receiving command from debugger, the debuggee invokes + * method and, after method has been invoked, sends command to debugger. + * When BreakpointEvent is received by , it enables + * StepRequest. + * For each StepEvent received by , it compares all refencies + * of this event ( , , , ) + * with expected values. The current value of field reference + * is compared with expected value. + * When StepEvent for last checked line is received, + * disables StepRequest to prevent further generation of StepEvents. + * When command received from debuggee, debugger notifies + * that method is invoked and waits for + * receives all expected events. If not all events received for + * WAITIME period, debugger interrupts thread and + * complains about an error. + * Finally, debugger disables all requests, sends debuggee command from debugger + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + // invoke checked method to generate StepEvents + foo(); + + // notify debugger that checked method invoked + pipe.println(COMMAND_DONE); + + // wait for command from debugger and exit + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + return PASSED; + } + + void foo() { + // Increment 10 times; + counter = 0; // stepLineBegin + counter = 1; + counter = 2; + counter = 3; + counter = 4; + counter = 5; + counter = 6; + counter = 7; + counter = 8; + counter = 9; + counter = 10; // stepLineEnd + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002.java new file mode 100644 index 00000000000..64514434612 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002.java @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepEvent._itself_; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.List; +import java.util.Iterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class stepevent002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static final String TEST_NAME = "nsk.jdi.StepEvent._itself_.stepevent002"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + + static final int EXPECTED_EVENTS_COUNT = 10; + + static private Debugee debuggee; + static private IOPipe pipe; + static private VirtualMachine vm; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private StepRequest checkedRequest; + static private Location checkedLocation; + static private ThreadReference checkedThread; + static private ReferenceType checkedClass; + + static private long eventTimeout; + static private EventRequestManager eventRManager; + static private boolean testFailed; + static private int eventsCount, frameCount, oldFrameCount; + + static private volatile boolean threadFinished; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + threadFinished = false; + eventsCount = 0; + frameCount = -1; + oldFrameCount = -1; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // prepare debugee, create request, and wait for StepEvent + try { + + // resume debugee and wait for it becomes ready + log.display("Resuming debuggee"); + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (command == null || !command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirror of debugee class + if ((checkedClass = debuggee.classByName(DEBUGGEE_NAME)) == null) { + throw new Failure("TEST BUG: cannot find debuggee's class " + DEBUGGEE_NAME); + } + + // create request for step event + log.display("Getting reference to thread "); + checkedThread = (ThreadReference) checkedClass.getValue(checkedClass.fieldByName("threadForEvent") ) ; + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to "); + } + + log.display("Creating StepRequest with size = STEP_LINE, depth = STEP_INTO"); + eventRManager = vm.eventRequestManager(); + if ((checkedRequest = eventRManager.createStepRequest( checkedThread, + StepRequest.STEP_LINE, StepRequest.STEP_INTO)) == null) { + throw new Failure("TEST BUG: unable to create StepRequest"); + } +// checkedRequest.addClassFilter(checkedThread.referenceType()); + checkedRequest.addClassFilter(checkedClass); + + // separate thread for handling events + class EventHandler extends Thread { + public void run() { + log.display("Event handler started"); + + // handle events until thread finishes and all expected events received + while (!(threadFinished && eventsCount >= EXPECTED_EVENTS_COUNT)) { + + // get next available event set + eventSet = null; + try { + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + } catch (Exception e) { + throw new Failure("TEST INCOMPLETE: Unexpected exception while getting event: " + e); + } + if (eventSet == null) + continue; + + // handle each event from the event set + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + // handle StepEvent + if (event instanceof StepEvent) { + + StepEvent castedEvent = (StepEvent)event; + log.display("Received event is StepEvent:\n " + castedEvent); + + // check that received event is for checked request + EventRequest eventRequest = castedEvent.request(); + if (checkedRequest.equals(eventRequest)) { + eventsCount++; + log.display("Expected StepEvent for checked request received: " + eventsCount); + } else { + log.complain("FAILURE 1: eventRequest is not equal to checked request"); + testFailed = true; + } + + // check that received event is for checked VM + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + // check that received event is for checked thread + ThreadReference eventThread = castedEvent.thread(); + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 3: eventThread is not equal to checked thread"); + testFailed = true; + } + + Location eventLocation = castedEvent.location(); + log.display("StepEvent received for location: " + eventLocation.lineNumber()); + + try { + frameCount = checkedThread.frameCount(); + log.display("frame count " + frameCount); + if (oldFrameCount > frameCount) { + log.complain("FAILURE 4: step event is not generated for STEP_INTO"); + testFailed = true; + } + oldFrameCount = frameCount; + } catch (Exception e) { + log.complain("ERROR: Unexpected exception is thrown while trying frame count " + e.getMessage()); + testFailed = true; + } + } + + // ignore all other events + } + + // resume each received event set + log.display("Resuming event set"); + eventSet.resume(); + } + + log.display("Event handler finished successfully"); + } + } + + // start event handler in a separate thread + log.display("Starting event handler thread"); + EventHandler eventHandler = new EventHandler(); + eventHandler.start(); + + // enable event request + log.display("Enabling event request"); + checkedRequest.enable(); + log.display("StepRequest for threadForEvent is created and enabled"); + + // force checked class to be unloaded from debuggee + log.display("Force debuggee to invoke checked method and generate step events"); + pipe.println(COMMAND_GO); + + log.display(""); + + // wait for thread finished in debugee + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (command == null || !command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + threadFinished = true; + + log.display(""); + + // waiting for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + if (eventHandler.isAlive()) { + log.display("Interrupting event handler thread"); + eventHandler.interrupt(); + } + + // check number of received events + if (eventsCount == 0) { + log.complain("FAILURE 4: No any StepEvent received"); + testFailed = true; + } + if (eventsCount < EXPECTED_EVENTS_COUNT) { + log.complain("FAILURE 4: Too few StepEvents received: " + eventsCount); + testFailed = true; + } + if (eventsCount > EXPECTED_EVENTS_COUNT) { + log.complain("FAILURE 4: Too many StepEvents received: " + eventsCount); + testFailed = true; + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + // disable event request to prevent appearance of further events + if (checkedRequest != null) { + log.display("Disabling event request"); + checkedRequest.disable(); + } + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002/TestDescription.java new file mode 100644 index 00000000000..d1e88daa105 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002/TestDescription.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/StepEvent/_itself_/stepevent002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises com.sun.jdi.event.StepEvent interface. + * The test checks the following assertions: + * - if debugger creates StepRequest with depth equals to + * STEP_INTO, then for every received StepEvent frame count + * of thead's stack is increased every time. + * A debugger class - nsk.jdi.StepEvent._itself_.stepevent002 ; + * a debuggee class - nsk.jdi.StepEvent._itself_.stepevent002a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger launches and connects to debuggee using the default launching + * connector. The debugger creates the StepRequest to receive StepEvent + * with size equals to STEP_LINE and depth equals to STEP_INTO. + * The debugger clears event queue and starts thread + * to handle received events asynchronously. After started + * debugger enables Steprequest and sends debuggee command to + * force it to invoke checked method in checked thread. + * Upon receiving command from debugger, the debuggee permits + * started thread to invokes recursively method. The + * method of is written at a single line to avoid generating + * step events of line changing while execution. When thread finished + * invoking method it stopped and debuggee sends debugger + * command . + * If in debugger receives StepEvent, it compares all + * refencies of this event ( , , , ) + * with expected values. It is checked that current count of frame of + * checked thread is more or equal to count of frame at the moment of + * previous step event. + * When debugger receives command from debuggee it notifies + * that all metod invokations in the checked thread done and waits for + * finishes. finishes only if all expected events + * received. If no all events received for WAITTIME period, debugger interrupts + * , checks number of received events, and complains about an error. + * Finally, debugger sends debuggee command to quit, clears event queue, + * waits for debugee finished, and exits. + * The test fails if any of this checks failed. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4463674: TEST_BUG: some JDI tests are timing dependent + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepEvent._itself_.stepevent002 + * nsk.jdi.StepEvent._itself_.stepevent002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepEvent._itself_.stepevent002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002a.java new file mode 100644 index 00000000000..87a0846be97 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepEvent/_itself_/stepevent002a.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepEvent._itself_; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +public class stepevent002a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + // commands + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + // monitors + public static Object threadStarted = new Object(); + public static Object threadExecuted = new Object(); + public static Object threadFinished = new Object(); + + // checked thread + private static stepevent002aThread threadForEvent; + + // support classes + private static ArgumentHandler argHandler; + private static IOPipe pipe; + public static Log log; + + public static void main(String args[]) { + stepevent002a _stepevent002a = new stepevent002a(); + System.exit(JCK_STATUS_BASE + _stepevent002a.runIt(args, System.err)); + } + + int runIt( String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + pipe = argHandler.createDebugeeIOPipe(); + + // create checked thread + threadForEvent = new stepevent002aThread("threadForEvent"); + + // lock monitor threadFinished to prevent checked thread + // from exiting after it executed + synchronized (threadFinished) { + + // lock monitor threadExecuted to prevent checked method invokation + // before command received + synchronized (threadExecuted) { + + // start checked thread and wait for it actually started + synchronized (threadStarted) { + log.display("Starting checked thread"); + threadForEvent.start(); + try { + threadStarted.wait(); + } catch (InterruptedException e) { + log.complain("TEST BUG: Debugee: InterruptedException caught: " + e); + return FAILED; + } + } + + // thread started; notify debugger and wait for command + pipe.println(COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + // unlock threadExecuted monitor to permit checked thread to execute + // and wait for checked thread finishes invoking method + try { + log.display("Waiting for checked thread executed"); + threadExecuted.wait(); + } catch (InterruptedException e) { + log.complain("TEST BUG: Debugee: InterruptedException caught: " + e); + return FAILED; + } + } + + // checked method invoked (but thread not finished yet) + // notify debugger + pipe.println(COMMAND_DONE); + + // wait for command from debugger and exit debuggee + String command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + log.complain("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + + // unlock monitor threadFinished to permit checked thread to finish + } + + return PASSED; + } + + // checked method (recursive for 10 times) + static void foo(int i) { if (i-- > 1) { foo(i); } } +} + +// checked thread class +class stepevent002aThread extends Thread { + static private int counter; + + stepevent002aThread (String name) { + super(name); + } + + public void run() { + + // notify main thread that checked thread started + synchronized (stepevent002a.threadStarted) { + stepevent002a.log.display("Checked thread started"); + stepevent002a.threadStarted.notify(); + } + + // wait for main thread releases monitor to permit checked thread to execute + synchronized (stepevent002a.threadExecuted) { + counter = stepevent002.EXPECTED_EVENTS_COUNT; + stepevent002a.log.display("Invoking checked method from checked thread"); + stepevent002a.foo(counter); + stepevent002a.log.display("Checked method invoked"); + + // notify main thread that checked thread executed + stepevent002a.threadExecuted.notify(); + } + + // wait for main thread releases monitor to permit thread to finish + synchronized (stepevent002a.threadFinished) { + stepevent002a.log.display("Checked thread finished"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001.java new file mode 100644 index 00000000000..4055b762f5b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.StepRequest._bounds_; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; + +import java.io.*; + +/** + * The test checks up the
    + * - addInstanceFilter(ObjectReference)
    + * - addClassFilter(ReferenceType)
    + * - addClassFilter(String)
    + * - addClassExclusionFilter(String)
    + * methods with null argument value. + * In any cases NullPointerException is expected. + */ +public class filters001 { + + private final static String prefix = "nsk.jdi.StepRequest._bounds_."; + private final static String debuggerName = prefix + "filters001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + filters001 thisTest = new filters001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + display(""); + display(">>>creating StepRequest"); + + ThreadReference thread = debugee.threadByName("main"); + EventRequestManager evm = debugee.getEventRequestManager(); + StepRequest request = evm.createStepRequest(thread, StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + + display(""); + addInstanceFilter(request, null); + + display(""); + addClassFilter(request, (ReferenceType )null); + + display(""); + addClassFilter(request, (String )null); + + display(""); + addClassExclusionFilter(request, (String )null); + + display(""); + debugee.quit(); + } + + private void addInstanceFilter(StepRequest request, + ObjectReference instance) { + String tmp = "addInstanceFilter :object value> "; + tmp += (instance == null) ? "" : instance.toString(); + display(tmp); + + try { + request.addInstanceFilter(instance); + if (instance==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (instance == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(StepRequest request, ReferenceType refType) { + + display("addClassFilter :ReferenceType> <" + refType + ">"); + + try { + request.addClassFilter(refType); + if (refType==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (refType==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(StepRequest request, String classPattern) { + + display("addClassFilter :classPattern> <" + classPattern + ">"); + try { + request.addClassFilter(classPattern); + if (classPattern==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (classPattern==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassExclusionFilter(StepRequest request, + String classPattern) { + display("addExclusionClassFilter :classPattern> <" + classPattern + ">"); + try { + request.addClassExclusionFilter(classPattern); + if (classPattern==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (classPattern==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001/TestDescription.java new file mode 100644 index 00000000000..5421c1ee410 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001/TestDescription.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/_bounds_/filters001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the methods + * com.sun.jdi.request.StepRequest.addInstanceFilter(ObjectReference) + * com.sun.jdi.request.StepRequest.addClassFilter(ReferenceType) + * com.sun.jdi.request.StepRequest.addClassFilter(String) + * com.sun.jdi.request.StepRequest.addClassExclusionFilter(String) + * correctly work for the boundary value of parameter and throw described + * exceptions. + * The test check up this methods with argument value. In any cases + * NullPointerException is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest._bounds_.filters001 + * nsk.jdi.StepRequest._bounds_.filters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest._bounds_.filters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001a.java new file mode 100644 index 00000000000..2ecfdf6d4a4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/_bounds_/filters001a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.StepRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filters001a is deugee's part of the test. + */ +public class filters001a { + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001.java new file mode 100644 index 00000000000..6146d1476fa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * StepRequest. + * + * The test checks that results of the method + * com.sun.jdi.StepRequest.addClassExclusionFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The cases to check include both a pattern that begin with '*' and + * one that end with '*'. + * + * The test works as follows. + * - The debugger + * - sets up StepRequest1 and restricts it using a pattern that + * begins with '*' + * - resumes the debuggee, and waits for expected StepEvent. + * - The debuggee creates and starts a thread, thread1, + * which being run, invokes methods used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + * Then the same is repeated for a pattern that ends with *. + */ + +public class filter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.StepRequest.addClassExclusionFilter.filter001a"; + return new filter001().runThis(argv, out); + } + + private String testedClassName1 = "TestClass11"; + private String testedClassName2 = "nsk.jdi.StepRequest.addClassExclusionFilter.Thread2filter001a"; + + private static EventRequest eventRequest1; + private static EventRequest eventRequest2; + + protected void testRun() { + + String property1 = "StepRequest1"; + String property2 = "StepRequest2"; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String threadName1 = "thread1"; + String threadName2 = "thread2"; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + thread1 = debuggee.threadByName(threadName1); + eventRequest1 = setting23StepRequest(thread1, "*" + testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof StepEvent && event.request().equals(eventRequest1)) { + String str = ((StepEvent)event).location().declaringType().name(); + if (str.endsWith(testedClassName1)) { + setFailedStatus("eventRequest1: Received unexpected StepEvent for excluded class:" + str); + } else { + display("eventRequest1: Received expected StepEvent for " + str); + } + return true; + } + return false; + } + } + ); + + display("......waiting1 for StepEvent in expected thread"); + vm.resume(); + break; + + case 1: + thread2 = debuggee.threadByName(threadName2); + eventRequest2 = setting23StepRequest(thread2, testedClassName2 + "*", + EventRequest.SUSPEND_NONE, property2); + + eventRequest2.enable(); + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof StepEvent && event.request().equals(eventRequest2)) { + String str = ((StepEvent)event).location().declaringType().name(); + if (str.endsWith(testedClassName2)) { + setFailedStatus("eventRequest2: Received unexpected StepEvent for excluded class:" + str); + } else { + display("eventRequest2: Received expected StepEvent for " + str); + } + return true; + } + return false; + } + } + ); + + display("......waiting2 for StepEvent in expected thread"); + vm.resume(); + break; + + case 2: + display("disabling event requests"); + eventRequest1.disable(); + eventRequest2.disable(); + + display("resuming debuggee"); + vm.resume(); + break; + + default: + throw new TestBug("Test logic error"); + } + } + return; + } + + private StepRequest setting23StepRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up StepRequest:"); + display(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + // limit events number (otherwise too many events will be generated) + str.addCountFilter(10); + str.setSuspendPolicy(suspendPolicy); + str.addClassExclusionFilter(testedClass); + + display(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001/TestDescription.java new file mode 100644 index 00000000000..d0b6c42fd6a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addClassExclusionFilter/filter001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateStep - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addClassExclusionFilter.filter001; + * the debuggee program - nsk.jdi.StepRequest.addClassExclusionFilter.filter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4687906 TEST_BUG: some tests for jdi StepRequest are invalid + * Modified due to fix of the bug: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addClassExclusionFilter.filter001 + * nsk.jdi.StepRequest.addClassExclusionFilter.filter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addClassExclusionFilter.filter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001a.java new file mode 100644 index 00000000000..73e334a34d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter001a.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter001 JDI test. + */ + +public class filter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter001a thread1 = null; + static Thread2filter001a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + + static int maxInstr = 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----1"); + methodForCommunication(); + } + try { + thread1.join(); + } catch ( InterruptedException e ) { + } + break; + + + case 1: + thread2 = new Thread2filter001a("thread2"); + + synchronized (lockObj) { + threadStart(thread2); + log1("methodForCommunication();----2"); + methodForCommunication(); + } + try { + thread2.join(); + } catch ( InterruptedException e ) { + } + break; + //------------------------------------------------- standard end section + + case 2: + log1("methodForCommunication();----3"); + methodForCommunication(); + break; + + default: + instruction = end; + break; + } + + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class Thread1filter001a extends Thread { + + class TestClass10{ + void m10() { + throw new NullPointerException("m10"); + } + } + class TestClass11 extends TestClass10{ + void m11() { + + try { + (new TestClass10()).m10(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } + } + + + String tName = null; + + public Thread1filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(filter001a.waitnotifyObj) { + filter001a.waitnotifyObj.notify(); + } + synchronized(filter001a.lockObj) { + try { + (new TestClass11()).m11(); + } catch ( NullPointerException e) { + } + } + filter001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class Thread2filter001a extends Thread { + + class TestClass20{ + void m20() { + throw new NullPointerException("m20"); + } + } + class TestClass21 extends TestClass20{ + void m21() { + + try { + (new TestClass20()).m20(); + } catch ( NullPointerException e ) { + } + throw new NullPointerException("m11"); + } + } + + String tName = null; + + public Thread2filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(filter001a.waitnotifyObj) { + filter001a.waitnotifyObj.notify(); + } + synchronized(filter001a.lockObj) { + try { + (new TestClass21()).m21(); + } catch ( NullPointerException e) { + } + } + filter001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java new file mode 100644 index 00000000000..5e44ed731bf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.addClassExclusionFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an StepRequest and enables it,
    + * - invokes the method addClassExclusionFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassExclusionFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassExclusionFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/addClassExclusionFilter/filter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.addClassExclusionFilter.filter002a"; + + private String testedClassName1 = + "nsk.jdi.StepRequest.addClassExclusionFilter.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "StepRequest1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + ThreadReference thread1 = threadByName("main"); + eventRequest1 = setting23StepRequest(thread1, testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassExclusionFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassExclusionFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassExclusionFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassExclusionFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassExclusionFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassExclusionFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + Event evt = eventIterator.nextEvent(); + + if (evt instanceof BreakpointEvent) + return; + + log3("Didn't get expected BreakpointEvent, events are:"); + while(true) { + log3(" event = " + evt); + if (!eventIterator.hasNext()) { + break; + } + evt = eventIterator.nextEvent(); + } + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting23StepRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.addCountFilter(1); + str.setSuspendPolicy(suspendPolicy); + str.addClassExclusionFilter(testedClass); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002/TestDescription.java new file mode 100644 index 00000000000..316c8e6d470 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addClassExclusionFilter/filter002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateStep - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateStep - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addClassExclusionFilter.filter002; + * the debuggee program - nsk.jdi.StepRequest.addClassExclusionFilter.filter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was modified to fix the bug: + * 4689354 TEST_BUG: StepRequest/addClassExclusionFilter/filter002 misses its purpose + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addClassExclusionFilter.filter002 + * nsk.jdi.StepRequest.addClassExclusionFilter.filter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addClassExclusionFilter.filter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002a.java new file mode 100644 index 00000000000..a3a63231662 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter002 JDI test. + */ + +public class filter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001.java new file mode 100644 index 00000000000..d6076960d09 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * StepRequest. + * + * The test checks that results of the method + * com.sun.jdi.StepRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or + * any of its subtypes. + * The cases to check include Steps in debuggee's four types, + * two in TestClass10 and its sub-class TestClass11, and + * two in TestClass20 and its sub-class TestClass21. + * The filter restricts StepEvent to only TestClass11. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates and starts two threads, thread1 and thread2; + * thread1 will invoke methods in TestClass10 and TestClass11, and + * thread2 in TestClass20 and TestClass21, + * and steps into methods are objects to test; + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes to use to filter StepEvents, + * - sets up StepRequest for the events, + * - restricts the events to those in TestClass10, that is, in thread1, + * - and resumes the debuggee and waits for the events. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_rt001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.StepRequest.addClassFilter_rt.filter_rt001a"; + return new filter_rt001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.StepRequest.addClassFilter_rt.TestClass11"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + String property1 = "StepRequest1"; + ReferenceType testClassReference = null; + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = (ReferenceType)debuggee.classByName(testedClassName); + thread1 = debuggee.threadByName(threadName1); + if (thread1 == null) + throw new Failure("Cannot get ThreadReference for " + threadName1); + eventRequest1 = setting21StepRequest(thread1, testClassReference, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for StepEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, false); + + if ( !(newEvent instanceof StepEvent)) { + setFailedStatus("ERROR: new event is not StepEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new StepEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ReferenceType refType = ((StepEvent)newEvent).location().declaringType(); + if (!refType.equals(testClassReference)) { + setFailedStatus("Received unexpected declaring type of the event: " + refType.name() + + "\n\texpected one: " + testClassReference.name()); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private StepRequest setting21StepRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up StepRequest:"); + display(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.setSuspendPolicy(suspendPolicy); + str.addClassFilter(testedClass); + str.addCountFilter(1); + + display(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + throw new Failure("FAILURE to set up StepRequest:" + e); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001/TestDescription.java new file mode 100644 index 00000000000..266dbda3905 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addClassFilter_rt.filter_rt001; + * the debuggee program - nsk.jdi.StepRequest.addClassFilter_rt.filter_rt001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4687906 TEST_BUG: some tests for jdi StepRequest are invalid + * Modified due to fix of the bug: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addClassFilter_rt.filter_rt001 + * nsk.jdi.StepRequest.addClassFilter_rt.filter_rt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addClassFilter_rt.filter_rt001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001a.java new file mode 100644 index 00000000000..00c25667c33 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt001a.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import nsk.share.jdi.ThreadState; + +/** + * This class is used as debuggee application for the filter_rt001 JDI test. + */ + +public class filter_rt001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static final long THREAD_STATE_TIMEOUT_MS = 30000; + static final String STATE_INIT = "init"; + static final String STATE_THREAD_STARTED = "threadStarted"; + static final String STATE_JDI_INITED = "jdiInited"; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_rt001a thread1 = new Thread1filter_rt001a( + "thread1", new ThreadState(STATE_INIT, THREAD_STATE_TIMEOUT_MS)); + static Thread2filter_rt001a thread2 = new Thread2filter_rt001a( + "thread2", new ThreadState(STATE_INIT, THREAD_STATE_TIMEOUT_MS)); + + static TestClass11 obj = new TestClass11(); + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1.start(); + thread2.start(); + thread1.getThreadState().waitForState(STATE_THREAD_STARTED); + thread2.getThreadState().waitForState(STATE_THREAD_STARTED); + + log1("debuggee started!"); + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + thread1.getThreadState().setState(STATE_JDI_INITED); + thread2.getThreadState().setState(STATE_JDI_INITED); + waitForThreadJoin ( thread1, "thread1" ); + waitForThreadJoin ( thread2, "thread2" ); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static void waitForThreadJoin (Thread thread, String threadName) { + log1("waiting for " + threadName + " join"); + int waitMs = argHandler.getWaitTime() * 60 * 1000; + if (thread.isAlive()) { + try { + thread.join(waitMs); + } catch (InterruptedException e) { + throw new Failure("catched unexpected InterruptedException while waiting of " + threadName + " join:" + e); + }; + } + if (thread.isAlive()) { + throw new Failure(threadName + " is still alive"); + } else { + log1(threadName + " joined"); + } + } +} + +class TestClass10{ + static void m10() { + filter_rt001a.log1("entered: m10"); + } +} +class TestClass11 extends TestClass10{ + static void m11() { + filter_rt001a.log1("entered: m11"); + TestClass10.m10(); + } +} + +class Thread1filter_rt001a extends Thread { + + private String tName = null; + private ThreadState threadState = null; + + public Thread1filter_rt001a(String threadName, ThreadState threadState) { + super(threadName); + tName = threadName; + this.threadState = threadState; + } + + public ThreadState getThreadState() { + return threadState; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + threadState.setAndWait(filter_rt001a.STATE_THREAD_STARTED, filter_rt001a.STATE_JDI_INITED); + TestClass11.m11(); + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class TestClass20{ + static void m20() { + filter_rt001a.log1("entered: m20"); + } +} +class TestClass21 extends TestClass20{ + static void m21() { + filter_rt001a.log1("entered: m21"); + TestClass20.m20(); + } +} + +class Thread2filter_rt001a extends Thread { + + private String tName = null; + private ThreadState threadState = null; + + public Thread2filter_rt001a(String threadName, ThreadState threadState) { + super(threadName); + tName = threadName; + this.threadState = threadState; + } + + public ThreadState getThreadState() { + return threadState; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + threadState.setAndWait(filter_rt001a.STATE_THREAD_STARTED, filter_rt001a.STATE_JDI_INITED); + TestClass21.m21(); + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java new file mode 100644 index 00000000000..212abb2fbd5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.addClassFilter(ReferenceType)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a filter_rt002aTestClass10 object, to use as a filter,
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an StepRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_rt002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_rt002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.addClassFilter_rt.filter_rt002a"; + + private String testedClassName = + "nsk.jdi.StepRequest.addClassFilter_rt.filter_rt002aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "StepRequest1"; + + ReferenceType testClassReference = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = threadByName(threadName1); + + eventRequest1 = setting21StepRequest(thread1, testClassReference, + EventRequest.SUSPEND_NONE, property1); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" no InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassFilter(testClassReference); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testClassReference);"); + log2(" InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting21StepRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.addCountFilter(2); + str.setSuspendPolicy(suspendPolicy); + str.addClassFilter(testedClass); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002/TestDescription.java new file mode 100644 index 00000000000..51d13582dd8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addClassFilter_rt.filter_rt002; + * the debuggee program - nsk.jdi.StepRequest.addClassFilter_rt.filter_rt002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4687906 TEST_BUG: some tests for jdi StepRequest are invalid + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addClassFilter_rt.filter_rt002 + * nsk.jdi.StepRequest.addClassFilter_rt.filter_rt002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addClassFilter_rt.filter_rt002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002a.java new file mode 100644 index 00000000000..b95d34ce1f3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002a.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt002 JDI test. + */ + +public class filter_rt002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_rt002a thread1 = null; + + static filter_rt002aTestClass10 obj = new filter_rt002aTestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_rt002a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class filter_rt002aTestClass10{ + static void m10() { + filter_rt002a.log1("entered: m10"); + } +} +class filter_rt002aTestClass11 extends filter_rt002aTestClass10{ + static void m11() { + filter_rt002a.log1("entered: m11"); + filter_rt002aTestClass10.m10(); + } +} + +class Thread1filter_rt002a extends Thread { + + String tName = null; + + public Thread1filter_rt002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(filter_rt002a.waitnotifyObj) { + filter_rt002a.waitnotifyObj.notify(); + } + synchronized(filter_rt002a.lockObj) { + filter_rt002aTestClass11.m11(); + } + filter_rt002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003.java new file mode 100644 index 00000000000..2fb842f790a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * StepRequest. + * + * The test checks that results of the method + * com.sun.jdi.StepRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to be + * the preparation of the given reference type and any subtypes. + * The cases to test include re-invocations of the method + * addClassFilter() on the same StepRequest object. + * There are two StepRequests to check as follows: + * (1) For StepRequest2, both invocations are with different + * ReferenceTypes restricting one Step event to two classes. + * The test expects no Step event will be received. + * (2) For StepRequest1, both invocations are with the same + * ReferenceType restricting one Step event to one class. + * The test expects this Step event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2; + * thread1 will invoke methods in filter_rt003aTestClass10 and filter_rt003aTestClass11, and + * thread2 in filter_rt003aTestClass20 and filter_rt003aTestClass21, + * and steps into methods are objects to test; + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes 1&2 for the Classes to filter, + * - sets up two StepRequests 1&2, + * - double restricts StepRequest1 to the RefTypes 1 and 1, + * - double restricts StepRequest2 to the RefTypes 1 and 2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_rt003 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.StepRequest.addClassFilter_rt.filter_rt003a"; + return new filter_rt003().runThis(argv, out); + } + + private String testedClassName11 = + "nsk.jdi.StepRequest.addClassFilter_rt.filter_rt003aTestClass11"; + private String testedClassName21 = + "nsk.jdi.StepRequest.addClassFilter_rt.filter_rt003aTestClass21"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "StepRequest1"; + String property2 = "StepRequest2"; + + ReferenceType testClassReference11 = null; + ReferenceType testClassReference21 = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ThreadReference thread2 = null; + String threadName2 = "thread2"; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference11 = (ReferenceType)debuggee.classByName(testedClassName11); + testClassReference21 = (ReferenceType)debuggee.classByName(testedClassName21); + + thread1 = debuggee.threadByName(threadName1); + thread2 = debuggee.threadByName(threadName2); + + eventRequest1 = setting21StepRequest(thread1, testClassReference11, + EventRequest.SUSPEND_ALL, property1); + + eventRequest2 = setting21StepRequest(thread2, testClassReference11, + EventRequest.SUSPEND_ALL, property2); + + ((StepRequest) eventRequest1).addClassFilter(testClassReference11); + ((StepRequest) eventRequest2).addClassFilter(testClassReference21); + + display("......waiting for StepEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, false); + + if ( !(newEvent instanceof StepEvent)) { + setFailedStatus("ERROR: new event is not StepEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new StepEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + ReferenceType refType = ((StepEvent)newEvent).location().declaringType(); + if (!refType.equals(testClassReference11)) { + setFailedStatus("Received unexpected declaring type of the event: " + refType.name() + + "\n\texpected one: " + testClassReference11.name()); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private StepRequest setting21StepRequest ( ThreadReference thread, + ReferenceType testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up StepRequest:"); + display(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.setSuspendPolicy(suspendPolicy); + str.addClassFilter(testedClass); + str.addCountFilter(1); + + display(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up StepRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003/TestDescription.java new file mode 100644 index 00000000000..270cc11ff5b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addClassFilter_rt.filter_rt003; + * the debuggee program - nsk.jdi.StepRequest.addClassFilter_rt.filter_rt003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4621092 TEST_BUG: filter_rt003 test uses wrong thread synchronization scheme + * The test was fixed due to bug: + * 4687906 TEST_BUG: some tests for jdi StepRequest are invalid + * Modified due to fix of the bug: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addClassFilter_rt.filter_rt003 + * nsk.jdi.StepRequest.addClassFilter_rt.filter_rt003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addClassFilter_rt.filter_rt003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003a.java new file mode 100644 index 00000000000..77b28d80b9f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt003a.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import nsk.share.jdi.ThreadState; + +/** + * This class is used as debuggee application for the filter_rt003 JDI test. + */ + +public class filter_rt003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static final long THREAD_STATE_TIMEOUT_MS = 30000; + static final String STATE_INIT = "init"; + static final String STATE_THREAD_STARTED = "threadStarted"; + static final String STATE_JDI_INITED = "jdiInited"; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_rt003a thread1 = new Thread1filter_rt003a( + "thread1", new ThreadState(STATE_INIT, THREAD_STATE_TIMEOUT_MS)); + static Thread2filter_rt003a thread2 = new Thread2filter_rt003a( + "thread2", new ThreadState(STATE_INIT, THREAD_STATE_TIMEOUT_MS)); + + static filter_rt003aTestClass11 obj1 = new filter_rt003aTestClass11(); + static filter_rt003aTestClass21 obj2 = new filter_rt003aTestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + thread1.start(); + thread2.start(); + thread1.getThreadState().waitForState(STATE_THREAD_STARTED); + thread2.getThreadState().waitForState(STATE_THREAD_STARTED); + + log1("debuggee started!"); + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + +//------------------------------------------------------ section tested + + case 0: + thread1.getThreadState().setState(STATE_JDI_INITED); + thread2.getThreadState().setState(STATE_JDI_INITED); + waitForThreadJoin ( thread1, "thread1" ); + waitForThreadJoin ( thread2, "thread2" ); + +//------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static void waitForThreadJoin (Thread thread, String threadName) { + log1("waiting for " + threadName + " join"); + + // get internal timeout in minutes for waiting of thread completion. + int waitTime = argHandler.getWaitTime(); + if (thread.isAlive()) { + try { + thread.join(waitTime * 60 * 1000); + } catch (InterruptedException e) { + throw new Failure("catched unexpected InterruptedException while waiting of " + threadName + " join:" + e); + }; + } + if (thread.isAlive()) { + throw new Failure(threadName + " is still alive"); + } else { + log1(threadName + " joined"); + } + } + +} + +class filter_rt003aTestClass10{ + static void m10() { + filter_rt003a.log1("entered: m10"); + } +} +class filter_rt003aTestClass11 extends filter_rt003aTestClass10{ + static void m11() { + filter_rt003a.log1("entered: m11"); + filter_rt003aTestClass10.m10(); + } +} + +class Thread1filter_rt003a extends Thread { + + private String tName = null; + private ThreadState threadState = null; + + public Thread1filter_rt003a(String threadName, ThreadState threadState) { + super(threadName); + tName = threadName; + this.threadState = threadState; + } + + public ThreadState getThreadState() { + return threadState; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + threadState.setAndWait(filter_rt001a.STATE_THREAD_STARTED, filter_rt001a.STATE_JDI_INITED); + filter_rt003aTestClass11.m11(); + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt003aTestClass20{ + static void m20() { + filter_rt003a.log1("entered: m20"); + } +} +class filter_rt003aTestClass21 extends filter_rt003aTestClass20{ + static void m21() { + filter_rt003a.log1("entered: m21"); + filter_rt003aTestClass20.m20(); + } +} + +class Thread2filter_rt003a extends Thread { + + private String tName = null; + private ThreadState threadState = null; + + public Thread2filter_rt003a(String threadName, ThreadState threadState) { + super(threadName); + tName = threadName; + this.threadState = threadState; + } + + public ThreadState getThreadState() { + return threadState; + } + + public void run() { + filter_rt003a.log1(" 'run': enter :: threadName == " + tName); + threadState.setAndWait(filter_rt001a.STATE_THREAD_STARTED, filter_rt001a.STATE_JDI_INITED); + filter_rt003aTestClass21.m21(); + filter_rt003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001.java new file mode 100644 index 00000000000..4e9e15fb69e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * StepRequest. + * + * The test checks that results of the method + * com.sun.jdi.StepRequest.addClassFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The cases to check include both a pattern that begin with '*' and + * one that end with '*'. + * + * The test works as follows. + * - The debugger + * - sets up StepRequests 1&2 and restricts them using patterns that + * begin with '*' and end with '*', + * - resumes the debuggee, and waits for expected StepEvent. + * - The debuggee creates and starts two threads, thread1 and thread2, + * which being run, invoke methods used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_s001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.StepRequest.addClassFilter_s.filter_s001a"; + return new filter_s001().runThis(argv, out); + } + + private String testedClassName1 = "TestClass11"; + private String testedClassName2 = "nsk.jdi.StepRequest.addClassFilter_s.Thread2filter_s001a"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "StepRequest1"; + String property2 = "StepRequest2"; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String threadName1 = "thread1"; + String threadName2 = "thread2"; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + thread1 = debuggee.threadByName(threadName1); + eventRequest1 = setting23StepRequest(thread1, "*" + testedClassName1, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting1 for StepEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof StepEvent)) { + setFailedStatus("ERROR: new event is not StepEvent"); + } else { + String str = ((StepEvent)newEvent).location().declaringType().name(); + if (!str.endsWith(testedClassName1)) { + setFailedStatus("Received StepEvent for unexpected class: \n\t" + str); + } else { + display("Received StepEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + case 1: + thread2 = debuggee.threadByName(threadName2); + eventRequest2 = setting23StepRequest(thread2, testedClassName2 + "*", + EventRequest.SUSPEND_ALL, property2); + + display("......waiting2 for StepEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof StepEvent)) { + setFailedStatus("ERROR: new event is not StepEvent"); + } else { + + String str = ((StepEvent)newEvent).location().declaringType().name(); + if (!(str.indexOf(testedClassName2) == 0)) { + setFailedStatus("Received StepEvent for unexpected class: \n\t" + str); + } else { + display("Received StepEvent for expected class: \n\t" + str); + } + + String property = (String) newEvent.request().getProperty("number"); + if ( !property.equals(property2) ) { + setFailedStatus("ERROR: property is not : " + property2); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private StepRequest setting23StepRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) { + try { + display("......setting up StepRequest:"); + display(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.setSuspendPolicy(suspendPolicy); + str.addClassFilter(testedClass); + + str.addCountFilter(1); + + display(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001/TestDescription.java new file mode 100644 index 00000000000..4d8f3393ca6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addClassFilter_s/filter_s001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addClassFilter() + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name matches + * a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateStep - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. e.g. "java.*" or "*.Foo". + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addClassFilter_s.filter_s001; + * the debuggee program - nsk.jdi.StepRequest.addClassFilter_s.filter_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addClassFilter_s.filter_s001 + * nsk.jdi.StepRequest.addClassFilter_s.filter_s001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addClassFilter_s.filter_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001a.java new file mode 100644 index 00000000000..1f7fea330d8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s001a.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s001 JDI test. + */ + +public class filter_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_s001a thread1 = null; + static Thread2filter_s001a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_s001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----1"); + methodForCommunication(); + } + try { + thread1.join(); + } catch ( InterruptedException e ) { + } + break; + + + case 1: + thread2 = new Thread2filter_s001a("thread2"); + + synchronized (lockObj) { + threadStart(thread2); + log1("methodForCommunication();----2"); + methodForCommunication(); + } + try { + thread2.join(); + } catch ( InterruptedException e ) { + } + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); +// methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + static void m10() { + filter_s001a.log1("entered: m10"); + } +} +class TestClass11 extends TestClass10{ + static void m11() { + filter_s001a.log1("entered: m11"); + TestClass10.m10(); + } +} + +class Thread1filter_s001a extends Thread { + + String tName = null; + + public Thread1filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(filter_s001a.waitnotifyObj) { + filter_s001a.waitnotifyObj.notify(); + } + synchronized(filter_s001a.lockObj) { + TestClass11.m11(); + } + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class Thread2filter_s001a extends Thread { + + static class TestClass20{ + static void m20() { + filter_s001a.log1("entered: m20"); + } + } + static class TestClass21 extends TestClass20{ + static void m21() { + filter_s001a.log1("entered: m20"); + TestClass20.m20(); + } + } + + String tName = null; + + public Thread2filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(filter_s001a.waitnotifyObj) { + filter_s001a.waitnotifyObj.notify(); + } + synchronized(filter_s001a.lockObj) { + TestClass21.m21(); + } + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java new file mode 100644 index 00000000000..2b179b531f0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.addClassFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates and starts a thread, thread1, and
    + * invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a StepRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_s002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/addClassFilter_s/filter_s002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_s002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.addClassFilter_s.filter_s002a"; + + private String testedClassName1 = + "nsk.jdi.StepRequest.addClassFilter_s.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + String property1 = "StepRequest1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + ThreadReference thread1 = threadByName("thread1"); + eventRequest1 = setting23StepRequest(thread1, testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((StepRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting23StepRequest ( ThreadReference thread, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.setSuspendPolicy(suspendPolicy); + str.addClassFilter(testedClass); + +// str.addCountFilter(1); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002/TestDescription.java new file mode 100644 index 00000000000..cfc2c1e536b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addClassFilter_s/filter_s002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addClassFilter() + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose method is in a class whose name does not match + * this restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateStep - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateStep - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addClassFilter_s.filter_s002; + * the debuggee program - nsk.jdi.StepRequest.addClassFilter_s.filter_s002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addClassFilter_s.filter_s002 + * nsk.jdi.StepRequest.addClassFilter_s.filter_s002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addClassFilter_s.filter_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002a.java new file mode 100644 index 00000000000..d8524596ea8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002a.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s002 JDI test. + */ + +public class filter_s002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_s002a thread1 = null; + + static TestClass objTC = new TestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_s002a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Thread1filter_s002a extends Thread { + + String tName = null; + int tNumber; + + public Thread1filter_s002a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + + synchronized (lockObj) { +// log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); +// objTC[tNumber].method(); + } + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class TestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001.java new file mode 100644 index 00000000000..dbf11610f18 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * StepRequest. + * + * The test checks that results of the method + * com.sun.jdi.StepRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * in which the currently executing instance is the object specified. + * The cases to test include invocations of the method addInstanceFilter() on + * two StepRequest objects with different array element (instances) arguments. + * (1) For StepRequest2, a testing thread will not execute an ObjectRefernce + * instance used as the filter; + * hence, the test expects this Step event will not be received. + * (2) For StepRequest1, a testing thread will do execute an ObjectRefernce + * instance used as the filter; + * hence, the test expects this Step event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a special array with three Object instances, + * and two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a StepRequest within the method + * within the method in the class TestClass + * whose array element instances #0 and #1 + * will be calling by the thread1 and the thread2 accordingly, + * - invokes addInstanceFilter() on array element #0 for the thread1 + * and #2 for the thread2, + * thus restricting the Watchpoint event only to thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.StepRequest.addInstanceFilter.instancefilter001a"; + return new instancefilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.StepRequest.addInstanceFilter.TestClass"; + + + protected void testRun() { + + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "StepRequest1"; + String property2 = "StepRequest2"; + + String arrayName = "objTC"; + + ObjectReference instance1 = null; + ObjectReference instance2 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + eventRequest1 = setting2StepRequest (thread1, + EventRequest.SUSPEND_ALL, property1); + instance1 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + ((StepRequest) eventRequest1).addInstanceFilter(instance1); + + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + eventRequest2 = setting2StepRequest (thread2, + EventRequest.SUSPEND_ALL, property2); + instance2 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(2); + ((StepRequest) eventRequest2).addInstanceFilter(instance2); + + display("......waiting for StepEvent in expected thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof StepEvent)) { + setFailedStatus("ERROR: new event is not StepEvent"); + throw new Failure("** unexpected event **"); + } else { + Location location = ((StepEvent) newEvent).location(); + StepRequest stepR = (StepRequest) newEvent.request(); + String property = (String) stepR.getProperty("number"); + display(" got new StepEvent with property 'number' == " + property); + display(" thread name == " + stepR.thread().name()); + display(" size == " + stepR.size() + "; depth == " + stepR.depth()); + display(" lineNumber == " + location.lineNumber()); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private StepRequest setting2StepRequest ( ThreadReference thread, + int suspendPolicy, + String property ) + throws Failure { + try { + display("......setting up StepRequest:"); + display(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.setSuspendPolicy(suspendPolicy); + + display(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up StepRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001/TestDescription.java new file mode 100644 index 00000000000..b344f1a4cd8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001/TestDescription.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addInstanceFilter/instancefilter001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test include invocations of the method addInstanceFilter() on + * two StepRequest objects with defferent array element (instances) arquments. + * (1) For StepRequest2, a testing thread will not execute an ObjectRefernce + * instance used as the filter; + * hence, the test expects this Step event will not be received. + * (2) For StepRequest1, a testing thread will do execute an ObjectRefernce + * instance used as the filter; + * hence, the test expects this Step event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addInstanceFilter.instancefilter001; + * the debuggee program - nsk.jdi.StepRequest.addInstanceFilter.instancefilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4687906 TEST_BUG: some tests for jdi StepRequest are invalid + * Modified due to fix of the bug: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addInstanceFilter.instancefilter001 + * nsk.jdi.StepRequest.addInstanceFilter.instancefilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addInstanceFilter.instancefilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001a.java new file mode 100644 index 00000000000..78ddc3b90bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter001a.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter001 JDI test. + */ + +public class instancefilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter001a thread1 = null; + static Threadinstancefilter001a thread2 = null; + + static TestClass objTC[] = { new TestClass(), new TestClass(), new TestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter001a("thread1"); + thread2 = new Threadinstancefilter001a("thread2"); + + synchronized (lockObj) { + threadStart(thread1); + threadStart(thread2); + log1("methodForCommunication();----"); + methodForCommunication(); + } + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter001a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter001a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + + synchronized (lockObj) { +// log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class TestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java new file mode 100644 index 00000000000..e486da70739 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a StepRequest and enables it,
    + * - invokes the method addInstanceFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addInstanceFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addInstanceFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/addInstanceFilter/instancefilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.addInstanceFilter.instancefilter002a"; + + private String testedClassName = + "nsk.jdi.StepRequest.addInstanceFilter.instancefilter002aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "StepRequest1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2StepRequest (thread1, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + ((StepRequest) eventRequest1).addInstanceFilter(instance); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((StepRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" no InvalidRequestStateException expected"); + ((StepRequest) eventRequest1).addInstanceFilter(instance); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((StepRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting2StepRequest ( ThreadReference thread, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.addCountFilter(2); + str.setSuspendPolicy(suspendPolicy); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002/TestDescription.java new file mode 100644 index 00000000000..1dd74774f6d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addInstanceFilter/instancefilter002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addInstanceFilter.instancefilter002; + * the debuggee program - nsk.jdi.StepRequest.addInstanceFilter.instancefilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4687906 TEST_BUG: some tests for jdi StepRequest are invalid + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addInstanceFilter.instancefilter002 + * nsk.jdi.StepRequest.addInstanceFilter.instancefilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addInstanceFilter.instancefilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002a.java new file mode 100644 index 00000000000..cb18be123a4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002a.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter002 JDI test. + */ + +public class instancefilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter002a thread1 = null; + + static instancefilter002aTestClass objTC[] = { new instancefilter002aTestClass(), new instancefilter002aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter002a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter002a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter002a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + objTC[0].method(); + objTC[1].method(); + } + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter002aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java new file mode 100644 index 00000000000..0e4b3eb7b34 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: UnsupportedOperationException -
    + * if the target virtual machine
    + * does not support this operation.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger creates
    + * a BreakpointRequest and if addInstanceFilter() is not supported,
    + * invokes the method on the request expecting
    + * to catch UnsupportedOperationException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/addInstanceFilter/instancefilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.addInstanceFilter.instancefilter003a"; + + private String testedClassName = + "nsk.jdi.StepRequest.addInstanceFilter.instancefilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "StepRequest1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2StepRequest (thread1, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + if ( vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == true :: test cancelled"); + } else { + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" UnsupportedOperationException expected"); + ((StepRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no UnsupportedOperationException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" UnsupportedOperationException "); + } + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting2StepRequest ( ThreadReference thread, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.addCountFilter(2); + str.setSuspendPolicy(suspendPolicy); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003/TestDescription.java new file mode 100644 index 00000000000..9b1f07d0887 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addInstanceFilter/instancefilter003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addInstanceFilter.instancefilter003; + * the debuggee program - nsk.jdi.StepRequest.addInstanceFilter.instancefilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4687906 TEST_BUG: some tests for jdi StepRequest are invalid + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addInstanceFilter.instancefilter003 + * nsk.jdi.StepRequest.addInstanceFilter.instancefilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addInstanceFilter.instancefilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003a.java new file mode 100644 index 00000000000..01669e2d5ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003a.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter003 JDI test. + */ + +public class instancefilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter003a thread1 = null; + + static instancefilter003aTestClass objTC[] = { new instancefilter003aTestClass(), new instancefilter003aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter003a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter003a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter003a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + objTC[0].method(); + objTC[1].method(); + } + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter003aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004.java new file mode 100644 index 00000000000..76d6ace6d38 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * StepRequest. + * + * The test checks that results of the method + * com.sun.jdi.StepRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * in which the currently executing instance is + * the object specified. + * The case to test includes re-invocation of the method + * addInstanceFilter() on the same StepRequest object. + * There are two StepRequests to check as follows: + * (1) For StepRequest2, both invocations are with different + * ObjectReferences restricting one Step event to two objects. + * The test expects no Step event will be received. + * (2) For StepRequest1, both invocations are with the same + * ObjectReference restricting one Step event to one object. + * The test expects this Step event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a special array with two instances for testing, + * and two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up StepRequests 1&2 within the method + * in the class instancefilter004aTestClass which will be calling by both threads, + * - restricts the StepRequest1 to the tread1 and + * to the array elements #0 & #0 calling only within thread1, + * - restricts the StepRequest2 to the thread2 and + * the array elements #0 & #1 calling within thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.StepRequest.addInstanceFilter.instancefilter004a"; + return new instancefilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.StepRequest.addInstanceFilter.instancefilter004aTestClass"; + + protected void testRun() { + + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "StepRequest1"; + String property2 = "StepRequest2"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + + ObjectReference instance1 = null; + ObjectReference instance2 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = (ReferenceType)debuggee.classByName(testedClassName); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2StepRequest (thread1, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2StepRequest (thread2, + EventRequest.SUSPEND_ALL, property2); + + instance1 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + instance2 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(1); + + ((StepRequest) eventRequest1).addInstanceFilter(instance1); + ((StepRequest) eventRequest1).addInstanceFilter(instance1); + ((StepRequest) eventRequest2).addInstanceFilter(instance1); + ((StepRequest) eventRequest2).addInstanceFilter(instance2); + + display("......waiting for StepEvent in expected thread"); + StepEvent newEvent = (StepEvent)eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + EventRequest newEventRequest = newEvent.request(); + if ( newEventRequest.equals(eventRequest1) ) { + display(" received expected event: " + newEvent); + + ThreadReference newEventThread = newEvent.thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private StepRequest setting2StepRequest ( ThreadReference thread, + int suspendPolicy, + String property ) { + try { + display("......setting up StepRequest:"); + display(" thread: " + thread + "; property: " + property); + + StepRequest + str = eventRManager.createStepRequest(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + str.putProperty("number", property); + str.setSuspendPolicy(suspendPolicy); + + display(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up StepRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004/TestDescription.java new file mode 100644 index 00000000000..6009d693563 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/addInstanceFilter/instancefilter004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same StepRequest object. + * There are two StepRequests to check as follows: + * (1) For StepRequest2, both invocations are with different + * ObjectReferences restricting one Step event to two objects. + * The test expects no Step event will be received. + * (2) For StepRequest1, both invocations are with the same + * ObjectReference restricting one Step event to one object. + * The test expects this Step event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.addInstanceFilter.instancefilter001; + * the debuggee program - nsk.jdi.StepRequest.addInstanceFilter.instancefilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4687906 TEST_BUG: some tests for jdi StepRequest are invalid + * Modified due to fix of the bug: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.addInstanceFilter.instancefilter004 + * nsk.jdi.StepRequest.addInstanceFilter.instancefilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.addInstanceFilter.instancefilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004a.java new file mode 100644 index 00000000000..fd068b59960 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter004a.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter004 JDI test. + */ + +public class instancefilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter004a thread1 = null; + static Threadinstancefilter004a thread2 = null; + + static instancefilter004aTestClass objTC[] = { new instancefilter004aTestClass(), new instancefilter004aTestClass(), new instancefilter004aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter004a("thread1"); + thread2 = new Threadinstancefilter004a("thread2"); + + synchronized (lockObj) { + threadStart(thread1); + threadStart(thread2); + log1("methodForCommunication();---2"); + methodForCommunication(); + } + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter004a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter004a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + + synchronized (lockObj) { +// log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter004aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java new file mode 100644 index 00000000000..38eaf7aff0f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.depth; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.depth()
    + * complies with its spec.
    + *
    + * The test checks if an int value StepRequest.STEP_INTO,
    + * an argument of the method
    + * EventRequestManager.createAccessWatchpointRequest(),
    + * is equal to one returned by the method StepRequest.depth()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a tested thread
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an StepRequest with the depth StepRequest.STEP_INTO,
    + * - gets the depth of the Request with the method StepRequest.depth(),
    + * - and compares the values.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class depth001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/depth/depth001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new depth001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.depth.depth001a"; + + private String testedClassName = + "nsk.jdi.StepRequest.depth.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + int depth; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest with depth StepRequest.STEP_INTO"); + eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + + log2("......getting: depth = ((StepRequest) eventRequest1).depth();"); + depth = ((StepRequest) eventRequest1).depth(); + + log2(" checking up on equality of values"); + if ( depth != StepRequest.STEP_INTO ) { + testExitCode = FAILED; + log3("ERROR: depth() != StepRequest.STEP_INTO : " + depth); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting24StepRequest ( ThreadReference thread, + int size, + int depth ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; size: " + size + "; depth: " + depth); + + StepRequest + str = eventRManager.createStepRequest(thread, size, depth); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001/TestDescription.java new file mode 100644 index 00000000000..ea834f2436b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/depth/depth001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.depth() + * complies with its spec: + * public int depth() + * Returns: the step depth + * The test checks if an int value StepRequest.STEP_INTO, + * an argument of the method EventRequestManager.createAccessWatchpointRequest(), + * is equal to one returned by the method StepRequest.depth() + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.depth.depth001; + * the debuggee program - nsk.jdi.StepRequest.depth.depth001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.depth.depth001 + * nsk.jdi.StepRequest.depth.depth001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.depth.depth001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001a.java new file mode 100644 index 00000000000..fb2f80fd26f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001a.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.depth; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the depth001 JDI test. + */ + +public class depth001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1depth001a thread1 = null; + + static TestClass10 obj = new TestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1depth001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + static void m10() { + depth001a.log1("entered: m10"); + } +} +class TestClass11 extends TestClass10{ + static void m11() { + depth001a.log1("entered: m11"); + TestClass10.m10(); + } +} + +class Thread1depth001a extends Thread { + + String tName = null; + + public Thread1depth001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + depth001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(depth001a.waitnotifyObj) { + depth001a.waitnotifyObj.notify(); + } + synchronized(depth001a.lockObj) { + TestClass11.m11(); + } + depth001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java new file mode 100644 index 00000000000..967e47982cb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.depth; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.depth()
    + * complies with its spec.
    + *
    + * The test checks if an int value StepRequest.STEP_OVER,
    + * an argument of the method
    + * EventRequestManager.createAccessWatchpointRequest(),
    + * is equal to one returned by the method StepRequest.depth()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a tested thread
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an StepRequest with the depth StepRequest.STEP_OVER,
    + * - gets the depth of the Request with the method StepRequest.depth(),
    + * - and compares the values.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class depth002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/depth/depth002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new depth002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.depth.depth002a"; + + private String testedClassName = + "nsk.jdi.StepRequest.depth.depth002aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + int depth; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest with depth StepRequest.STEP_OVER"); + eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_LINE, + StepRequest.STEP_OVER); + + log2("......getting: depth = ((StepRequest) eventRequest1).depth();"); + depth = ((StepRequest) eventRequest1).depth(); + + log2(" checking up on equality of values"); + if ( depth != StepRequest.STEP_OVER ) { + testExitCode = FAILED; + log3("ERROR: depth() != StepRequest.STEP_OVER : " + depth); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting24StepRequest ( ThreadReference thread, + int size, + int depth ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; size: " + size + "; depth: " + depth); + + StepRequest + str = eventRManager.createStepRequest(thread, size, depth); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002/TestDescription.java new file mode 100644 index 00000000000..b797f895a48 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/depth/depth002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.depth() + * complies with its spec: + * public int depth() + * Returns: the step depth + * The test checks if an int value StepRequest.STEP_OVER, + * an argument of the method EventRequestManager.createAccessWatchpointRequest(), + * is equal to one returned by the method StepRequest.depth() + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.depth.depth002; + * the debuggee program - nsk.jdi.StepRequest.depth.depth002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.depth.depth002 + * nsk.jdi.StepRequest.depth.depth002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.depth.depth002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002a.java new file mode 100644 index 00000000000..2c50eebb83c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002a.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.depth; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the depth002 JDI test. + */ + +public class depth002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1depth002a thread1 = null; + + static depth002aTestClass10 obj = new depth002aTestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1depth002a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class depth002aTestClass10{ + static void m10() { + depth002a.log1("entered: m10"); + } +} +class depth002aTestClass11 extends depth002aTestClass10{ + static void m11() { + depth002a.log1("entered: m11"); + depth002aTestClass10.m10(); + } +} + +class Thread1depth002a extends Thread { + + String tName = null; + + public Thread1depth002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + depth002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(depth002a.waitnotifyObj) { + depth002a.waitnotifyObj.notify(); + } + synchronized(depth002a.lockObj) { + depth002aTestClass11.m11(); + } + depth002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java new file mode 100644 index 00000000000..6c47720eaa8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.depth; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.depth()
    + * complies with its spec.
    + *
    + * The test checks if an int value StepRequest.STEP_OUT,
    + * an argument of the method
    + * EventRequestManager.createAccessWatchpointRequest(),
    + * is equal to one returned by the method StepRequest.depth()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a tested thread
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an StepRequest with the depth StepRequest.STEP_OUT,
    + * - gets the depth of the Request with the method StepRequest.depth(),
    + * - and compares the values.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class depth003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/depth/depth003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new depth003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.depth.depth003a"; + + private String testedClassName = + "nsk.jdi.StepRequest.depth.depth003aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + int depth; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest with depth StepRequest.STEP_OUT"); + eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_LINE, + StepRequest.STEP_OUT); + + log2("......getting: depth = ((StepRequest) eventRequest1).depth();"); + depth = ((StepRequest) eventRequest1).depth(); + + log2(" checking up on equality of values"); + if ( depth != StepRequest.STEP_OUT ) { + testExitCode = FAILED; + log3("ERROR: depth() != StepRequest.STEP_OUT : " + depth); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting24StepRequest ( ThreadReference thread, + int size, + int depth ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; size: " + size + "; depth: " + depth); + + StepRequest + str = eventRManager.createStepRequest(thread, size, depth); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003/TestDescription.java new file mode 100644 index 00000000000..8c6b0f6ad4e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/depth/depth003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.depth() + * complies with its spec: + * public int depth() + * Returns: the step depth + * The test checks if an int value StepRequest.STEP_OUT, + * an argument of the method EventRequestManager.createAccessWatchpointRequest(), + * is equal to one returned by the method StepRequest.depth() + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.depth.depth003; + * the debuggee program - nsk.jdi.StepRequest.depth.depth003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.depth.depth003 + * nsk.jdi.StepRequest.depth.depth003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.depth.depth003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003a.java new file mode 100644 index 00000000000..e30a1de8747 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003a.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.depth; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the depth003 JDI test. + */ + +public class depth003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1depth003a thread1 = null; + + static depth003aTestClass10 obj = new depth003aTestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1depth003a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class depth003aTestClass10{ + static void m10() { + depth003a.log1("entered: m10"); + } +} +class depth003aTestClass11 extends depth003aTestClass10{ + static void m11() { + depth003a.log1("entered: m11"); + depth003aTestClass10.m10(); + } +} + +class Thread1depth003a extends Thread { + + String tName = null; + + public Thread1depth003a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + depth003a.log1(" 'run': enter :: threadName == " + tName); + synchronized(depth003a.waitnotifyObj) { + depth003a.waitnotifyObj.notify(); + } + synchronized(depth003a.lockObj) { + depth003aTestClass11.m11(); + } + depth003a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java new file mode 100644 index 00000000000..3485153b8f5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.size; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.size()
    + * complies with its spec.
    + *
    + * The test checks if an int value StepRequest.STEP_MIN,
    + * an argument of the method
    + * EventRequestManager.createAccessWatchpointRequest(),
    + * is equal to one returned by the method StepRequest.size()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a tested thread
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an StepRequest with the size StepRequest.STEP_MIN,
    + * - gets the size of the Request with the method StepRequest.size(),
    + * - and compares the values.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class size001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/size/size001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new size001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.size.size001a"; + + private String testedClassName = + "nsk.jdi.StepRequest.size.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + int size; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest with size StepRequest.STEP_MIN"); + eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_MIN, + StepRequest.STEP_INTO); + + log2("......getting: size = ((StepRequest) eventRequest1).size();"); + size = ((StepRequest) eventRequest1).size(); + + log2(" checking up on equality of values"); + if ( size != StepRequest.STEP_MIN ) { + testExitCode = FAILED; + log3("ERROR: size() != StepRequest.STEP_MIN : " + size); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting24StepRequest ( ThreadReference thread, + int size, + int depth ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; size: " + size + "; depth: " + depth); + + StepRequest + str = eventRManager.createStepRequest(thread, size, depth); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001/TestDescription.java new file mode 100644 index 00000000000..5e22a8f192f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/size/size001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.size() + * complies with its spec: + * public int size() + * Returns: the step size + * The test checks if an int value StepRequest.STEP_MIN, + * an argument of the method EventRequestManager.createAccessWatchpointRequest(), + * is equal to one returned by the method StepRequest.size() + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.size.size001; + * the debuggee program - nsk.jdi.StepRequest.size.size001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.size.size001 + * nsk.jdi.StepRequest.size.size001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.size.size001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001a.java new file mode 100644 index 00000000000..70b4f0910b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001a.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.size; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the size001 JDI test. + */ + +public class size001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1size001a thread1 = null; + + static TestClass10 obj = new TestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1size001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + static void m10() { + size001a.log1("entered: m10"); + } +} +class TestClass11 extends TestClass10{ + static void m11() { + size001a.log1("entered: m11"); + TestClass10.m10(); + } +} + +class Thread1size001a extends Thread { + + String tName = null; + + public Thread1size001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + size001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(size001a.waitnotifyObj) { + size001a.waitnotifyObj.notify(); + } + synchronized(size001a.lockObj) { + TestClass11.m11(); + } + size001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java new file mode 100644 index 00000000000..72ea53da199 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.size; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.size()
    + * complies with its spec.
    + *
    + * The test checks if an int value StepRequest.STEP_LINE,
    + * an argument of the method
    + * EventRequestManager.createAccessWatchpointRequest(),
    + * is equal to one returned by the method StepRequest.size()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a tested thread
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an StepRequest with the size StepRequest.STEP_LINE,
    + * - gets the size of the Request with the method StepRequest.size(),
    + * - and compares the values.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class size002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/size/size002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new size002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.size.size002a"; + + private String testedClassName = + "nsk.jdi.StepRequest.size.size002aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + int size; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest with size StepRequest.STEP_LINE"); + eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + + log2("......getting: size = ((StepRequest) eventRequest1).size();"); + size = ((StepRequest) eventRequest1).size(); + + log2(" checking up on equality of values"); + if ( size != StepRequest.STEP_LINE ) { + testExitCode = FAILED; + log3("ERROR: size() != StepRequest.STEP_LINE : " + size); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting24StepRequest ( ThreadReference thread, + int size, + int depth ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; size: " + size + "; depth: " + depth); + + StepRequest + str = eventRManager.createStepRequest(thread, size, depth); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002/TestDescription.java new file mode 100644 index 00000000000..e7d6e2d19cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/size/size002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.size() + * complies with its spec: + * public int size() + * Returns: the step size + * The test checks if an int value StepRequest.STEP_LINE, + * an argument of the method EventRequestManager.createAccessWatchpointRequest(), + * is equal to one returned by the method StepRequest.size() + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.size.size002; + * the debuggee program - nsk.jdi.StepRequest.size.size002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.size.size002 + * nsk.jdi.StepRequest.size.size002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.size.size002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002a.java new file mode 100644 index 00000000000..924cbea53c8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002a.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.size; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the size002 JDI test. + */ + +public class size002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1size002a thread1 = null; + + static size002aTestClass10 obj = new size002aTestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1size002a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class size002aTestClass10{ + static void m10() { + size002a.log1("entered: m10"); + } +} +class size002aTestClass11 extends size002aTestClass10{ + static void m11() { + size002a.log1("entered: m11"); + size002aTestClass10.m10(); + } +} + +class Thread1size002a extends Thread { + + String tName = null; + + public Thread1size002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + size002a.log1(" 'run': enter :: threadName == " + tName); + synchronized(size002a.waitnotifyObj) { + size002a.waitnotifyObj.notify(); + } + synchronized(size002a.lockObj) { + size002aTestClass11.m11(); + } + size002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java new file mode 100644 index 00000000000..d70f1a748d8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StepRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.StepRequest.thread()
    + * complies with its spec.
    + *
    + * The test checks if a ThreadReference object,
    + * an argument of the method
    + * EventRequestManager.createAccessWatchpointRequest(),
    + * is equal to one returned by the method StepRequest.thread()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates a tested thread
    + * and invokes the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an StepRequest with the thread1,
    + * - gets the thread of the Request, the thread2,
    + * with the method StepRequest.thread(),
    + * - and compares the objects thrtead1 and thread2.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class thread001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StepRequest/thread/thread001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new thread001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StepRequest.thread.thread001a"; + + private String testedClassName = + "nsk.jdi.StepRequest.thread.TestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String threadName1 = "thread1"; + + ThreadReference thread2; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + thread1 = threadByName(threadName1); + + log2("......setting up StepRequest with size StepRequest.STEP_MIN"); + eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_MIN, + StepRequest.STEP_INTO); + + log2("......getting: size = ((StepRequest) eventRequest1).thread();"); + thread2 = ((StepRequest) eventRequest1).thread(); + + log2(" checking up on equality of values"); + if ( !thread2.equals(thread1) ) { + testExitCode = FAILED; + log3("ERROR: !thread2.equals(thread1) : " + thread2); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private StepRequest setting24StepRequest ( ThreadReference thread, + int size, + int depth ) + throws JDITestRuntimeException { + try { + log2("......setting up StepRequest:"); + log2(" thread: " + thread + "; size: " + size + "; depth: " + depth); + + StepRequest + str = eventRManager.createStepRequest(thread, size, depth); + + log2(" StepRequest has been set up"); + return str; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingStepRequest() : " + e); + log3(" StepRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up StepRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001/TestDescription.java new file mode 100644 index 00000000000..1f128a2bec5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StepRequest/thread/thread001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StepRequest. + * The test checks up that a result of the method + * com.sun.jdi.StepRequest.thread() + * complies with its spec: + * public ThreadReference thread() + * Returns: the thread on which the step event is being requested. + * The test checks if a ThreadReference object, + * an argument of the method EventRequestManager.createAccessWatchpointRequest(), + * is equal to one returned by the method StepRequest.thread() + * The test works as follows: + * The debugger program - nsk.jdi.StepRequest.thread.thread001; + * the debuggee program - nsk.jdi.StepRequest.thread.thread001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StepRequest.thread.thread001 + * nsk.jdi.StepRequest.thread.thread001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StepRequest.thread.thread001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001a.java new file mode 100644 index 00000000000..60b1e602032 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001a.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StepRequest.thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the thread001 JDI test. + */ + +public class thread001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1thread001a thread1 = null; + + static TestClass10 obj = new TestClass10(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1thread001a("thread1"); + + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();----"); + methodForCommunication(); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } +} + +class TestClass10{ + static void m10() { + thread001a.log1("entered: m10"); + } +} +class TestClass11 extends TestClass10{ + static void m11() { + thread001a.log1("entered: m11"); + TestClass10.m10(); + } +} + +class Thread1thread001a extends Thread { + + String tName = null; + + public Thread1thread001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + thread001a.log1(" 'run': enter :: threadName == " + tName); + synchronized(thread001a.waitnotifyObj) { + thread001a.waitnotifyObj.notify(); + } + synchronized(thread001a.lockObj) { + TestClass11.m11(); + } + thread001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001.java new file mode 100644 index 00000000000..624f11b221c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.StringArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.StringArgument.
    + *
    + * The test checks up that a result of the method
    + * com.sun.jdi.connect.Connector.StringArgument.isValid()
    + * complies with its specification:
    + * "Returns: true always"
    + * when parameters are empty and non-empty strings.
    + *
    + * In case of the method does set the value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class isvalid001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.StringArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.StringArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.StringArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.StringArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with StringArgument found\n"); + return exitCode0; + } + } + + if (!argument.isValid("")) { + exitCode = exitCode2; + out.println(sErr2 + + "case: parameter == empty string\n" + + "error: return value != true\n"); + } + + if (!argument.isValid("0")) { + exitCode = exitCode2; + out.println(sErr2 + + "case: parameter == non-empty string\n" + + "error: return value != true\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001/TestDescription.java new file mode 100644 index 00000000000..d94cdd5eaa9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StringArgument/isValid/isvalid001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.StringArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.StringArgument.isValid() + * complies with its specification: + * "Returns: true always" + * when parameters are empty and non-empty strings. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.StringArgument object is searched among + * Arguments of Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * IF (!argument.isValid("")) or (!argument.isValid("0")) + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StringArgument.isValid.isvalid001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StringArgument.isValid.isvalid001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002.java new file mode 100644 index 00000000000..ea4d3f248fa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.StringArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.StringArgument.
    + *
    + * The test checks up that a result of the method
    + * com.sun.jdi.connect.Connector.StringArgument.isValid()
    + * complies with its specification:
    + * "Returns: true always"
    + * when parameter is null.
    + *
    + * In case of the method does set the value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class isvalid002 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.StringArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.StringArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.StringArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.StringArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with StringArgument found\n"); + return exitCode0; + } + } + + try { + if (!argument.isValid(null)) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(null)\n" + +// + "error: returned value != true\n"); + } + } catch ( NullPointerException e ) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(null)\n" + + "error: NullPointerException\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002/TestDescription.java new file mode 100644 index 00000000000..47fbc0809d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid002/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StringArgument/isValid/isvalid002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.StringArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.StringArgument.isValid() + * complies with its specification: + * "Returns: true always" + * when parameter is the null-value. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.StringArgument object is searched among + * Arguments of Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * IF !argument.isValid(null) + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StringArgument.isValid.isvalid002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StringArgument.isValid.isvalid002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003.java new file mode 100644 index 00000000000..923db27d78a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.StringArgument.isValid; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; + + +/** + * The test for the implementation of an object of the type
    + * Connector.StringArgument.
    + *
    + * The test checks up that a result of the method
    + * com.sun.jdi.connect.Connector.StringArgument.isValid()
    + * complies with its specification:
    + * "Returns: true always"
    + * when parameter is a null-string.
    + *
    + * In case of the method does set the value,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class isvalid003 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; +// + String sErr1 = "WARNING\n" + + "Method tested: " + + "jdi.Connector.StringArgument.isValid\n" ; +// + String sErr2 = "ERROR\n" + + "Method tested: " + + "jdi.Connector.StringArgument.isValid\n" ; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + List connectorsList = vmm.allConnectors(); + Iterator connectorsListIterator = connectorsList.iterator(); +// + Connector.StringArgument argument = null; + + for ( ; ; ) { + try { + Connector connector = + (Connector) connectorsListIterator.next(); + + Map defaultArguments = connector.defaultArguments(); + Set keyset = defaultArguments.keySet(); + int keysetSize = defaultArguments.size(); + Iterator keysetIterator = keyset.iterator(); + + for ( ; ; ) { + try { + String argName = (String) keysetIterator.next(); + + try { +// + argument = (Connector.StringArgument) + defaultArguments.get(argName); + break ; + } catch ( ClassCastException e) { + } + } catch ( NoSuchElementException e) { + break ; + } + } + if (argument != null) { + break ; + } + } catch ( NoSuchElementException e) { + out.println(sErr1 + + "no Connector with StringArgument found\n"); + return exitCode0; + } + } + + String sNull = null; + try { + if (!argument.isValid(sNull)) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(sNull)\n" + +// + "error: returned value != true\n"); + } + } catch ( NullPointerException e ) { + exitCode = exitCode2; + out.println(sErr2 + + "check: isValid(sNull)\n" + + "error: NullPointerException\n"); + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003/TestDescription.java new file mode 100644 index 00000000000..291d133a546 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringArgument/isValid/isvalid003/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StringArgument/isValid/isvalid003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.StringArgument. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.StringArgument.isValid() + * complies with its specification: + * "Returns: true always" + * when parameter is the null-string. + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - First Connector.StringArgument object is searched among + * Arguments of Connectors. + * If no the argument is found out the test exits + * with the return value = 95 and a warning message. + * - The following checks are applied: + * String sNull = null; + * IF !argument.isValid(sNull) + * THEN an error detected + * ELSE the check passed + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StringArgument.isValid.isvalid003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StringArgument.isValid.isvalid003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001.java new file mode 100644 index 00000000000..85207ce0e77 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StringReference.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * StringReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.StringReference.value()
    + * complies with its spec regarding the following requirement:
    + * "Returns the StringReference as a String.
    + * The returned string is the equivalent of the mirrored string,
    + * but is an entity in the client VM and can be manipulated
    + * like any other string."
    + *
    + * The test checks up that a returned string is the equivalent
    + * of the mirrored string.
    + *
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/StringReference/value/value001", + sHeader2 = "--> value001: ", + sHeader3 = "##> value001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.StringReference.value.value001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + static StringReference str_ref = null; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("value001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String classForCheckName = + "nsk.jdi.StringReference.value.ClassForCheck"; + + List listOfDebuggeeLoadedClasses = + vm.classesByName(classForCheckName); +/* + if (listOfDebuggeeLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeLoadedClasses.size() != 1 " + + listOfDebuggeeLoadedClasses.size()); + break ; + } +*/ + ReferenceType testClass = + (ReferenceType) listOfDebuggeeLoadedClasses.get(0); + + Field fstr = null; + + try { + fstr = testClass.fieldByName("str"); + } catch ( ClassNotPreparedException e) { + testExitCode = FAILED; + log3("ERROR: 'fstr = testClass.fieldByName' throws " + + "ClassNotPreparedException"); + break ; + } catch ( ObjectCollectedException e) { + testExitCode = FAILED; + log3("ERROR: 'fstr = testClass.fieldByName' throws " + + "ObjectCollectedException"); + break ; + } + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: + try { + str_ref = (StringReference) testClass.getValue(fstr); + log2(" : 1st str_ref = testClass.getValue(fstr) " + + "doesn't throws ObjectCollectedException"); + if (str_ref.value().compareTo("abc") != 0) { + log3("ERROR: strings are not equal"); + expresult = 1; + break ; + } + } catch ( ObjectCollectedException e ) { + log3("ERROR: 1st str_ref = testClass.getValue(fstr) " + + "does throws ObjectCollectedException"); + expresult = 1; + break ; + } + + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: debuggee's reply is not 'docontinue'"); + expresult = 1; + break ; + } + + try { + str_ref = (StringReference) testClass.getValue(fstr); + log2(" : 2nd str_ref = testClass.getValue(fstr) " + + "doesn't throws ObjectCollectedException"); + } catch ( ObjectCollectedException e ) { + log3("ERROR: 2nd str_ref = testClass.getValue(fstr) " + + "does throws ObjectCollectedException"); + expresult = 1; + } + break ; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001/TestDescription.java new file mode 100644 index 00000000000..2ef3883b279 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/StringReference/value/value001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * StringReference. + * The test checks up that a result of the method + * com.sun.jdi.StringReference.value() + * complies with its spec: + * public java.lang.String value() + * Returns the StringReference as a String. + * The returned string is the equivalent of the mirrored string, + * but is an entity in the client VM and can be manipulated + * like any other string. + * Returns: the string value. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * Note. The test doesn't check up the following: + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * The test works as follows: + * A debugger program - nsk.jdi.StringReference.value.value001; + * a debuggee program - nsk.jdi.StringReference.value.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.StringReference.value.value001 + * nsk.jdi.StringReference.value.value001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.StringReference.value.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001a.java new file mode 100644 index 00000000000..8c8caf1fdc4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StringReference/value/value001a.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.StringReference.value; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * This class is used as debuggee application for the value001a JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> value001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> value001a: " + message); + } + + //====================================================== test program + //................................................... globals for a debugger + + static ClassForCheck class1 = null; + + //.................................................... + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = new value001a().runThis(argv, System.out); + + System.exit(result + PASS_BASE); + } + + + private static int runThis (String argv[], PrintStream out) { + + for (int i=0; i"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // resume debuggee suspended at start up + log.display("Resuming debuggee"); + debuggee.resume(); + + // perform the test, catch exceptions and finally quit debuggee + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // create and enable event request + log.display("Creating request for ClassPrepareEvent"); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + if ((checkedRequest = erManager.createThreadDeathRequest()) == null) { + log.complain("TEST BUG: unable to create createThreadDeathRequest"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return thread001.FAILED; + } + checkedRequest.enable(); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + eventHandlingLoop: + while (eventsReceived < eventsExpected) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + // handle ThreadDeathEvent + if (event instanceof ThreadDeathEvent) { + log.display("\nThreadDeathEvent received"); + ThreadDeathEvent castedEvent = (ThreadDeathEvent)event; + + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 1: eventRequest is not equal to checked request"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + ThreadReference eventThread = ((ThreadDeathEvent)event).thread(); + if (eventThread == null) { + log.complain("FAILURE 2: ThreadDeathEvent.thread() returns null"); + testFailed = true; + } + + String threadName = eventThread.name(); + if ((threadName == null) || (threadName.equals(""))) { + log.complain("FAILURE 3: thread reference has invalid empty name"); + testFailed = true; + } else { + log.display ("Expected ThreadDeathEvent was received for " + threadName); + } + + // Check that all expected debuggee's thread create ThreadDeathEvent only once + eventsReceived = 0; + for (int i = 0; i < checkedThreads.length; i++) { + if (threadName.equals(checkedThreads[i][0])) { + if (checkedThreads[i][1].equals("0")) { + checkedThreads[i][1] = "1"; + } else { + log.complain("FAILURE 5: ThreadDeathEvent for " + threadName + " is received more that once"); + testFailed = true; + } + } + if (checkedThreads[i][1].equals("1")) { + eventsReceived++; + } + } + } + + // ignore each other events + + } // end of event handling loop + +// log.display("Resuming event set"); + eventSet.resume(); + + } // end of event set handling loop + + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptionException while waiting for event"); + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + + log.display("Disabling event request"); + checkedRequest.disable(); + + log.display("eventHandler completed"); + + } // end of run() + + } // end of EventHandler + + // start EventHandler thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to quit + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + // wait for all tested threads completed + command = pipe.readln(); + if (!command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + log.display(""); + + // wait for all expected events received or timeout exceeds + log.display("Waiting for all expected events received"); + try { + eventHandler.join(eventTimeout); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // Check that all expected debuggee's thread created ThreadDeathEvent + for (int i = 0; i < checkedThreads.length; i++) { + if (checkedThreads[i][1].equals("0")) { + log.complain("FAILURE 1: ThreadDeathEvent for thread " + checkedThreads[i][0] + " is not received"); + testFailed = true; + } + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("TEST FAILURE: Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + log.display(""); + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001/TestDescription.java new file mode 100644 index 00000000000..58e8ee3a8f9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ThreadDeathEvent/thread/thread001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.ThreadDeathEvent.thread() method. + * The test checks the following assertions: + * - ThreadDeathEvent is always received by debugger + * for all normally completed threads in target VM, + * - ThreadDeathEvent.thread() returns valid ThreadReference + * to expected thread in target VM, + * - ThreadDeathEvent is received only once for each expected thread + * A debugger class - nsk.jdi.ThreadDeathEvent.thread.thread001 ; + * a debuggee class - nsk.jdi.ThreadDeathEvent.thread.thread001a . + * The test uses NSK supporting classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates and enables ThreadDeathRequest. + * The debugger starts special thread for listening events + * delivered from debuggee. + * The debuggee starts the following checked threads: , + * , , . These threads consequently + * lock synchronizing object and complete. The main thread waits + * the completion of and threads and complete + * upon receiving command from debugger. + * The debugger switches to to listen the event during + * the time specified by parameter. + * The debugger checks if ThreadDeathEvent were receiced for every + * checked threads. + * The debugger also checks the other assertions of the test. + * The test fails if any of this checks failed. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4463674 TEST_BUG: some JDI tests are timing dependent + * ----------------- + * to fix the bug 4502899, + * the statement + * eventTimeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds + * is added next to line #66: + * log = new Log(out, argHandler); + * ----------------- + * 4757762 nsk/jdi/ThreadDeathEvent/thread/thread001 has a race + * ----------------- + * - Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * - Additional synchronization via IOPipe is used after completing + * of tested threads + * - Event handling loop is completed on receiving all expected events + * instead of receiving VMDisconnectEvent + * - Testing main thread is removed + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadDeathEvent.thread.thread001 + * nsk.jdi.ThreadDeathEvent.thread.thread001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadDeathEvent.thread.thread001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001a.java new file mode 100644 index 00000000000..7184db1cc84 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathEvent/thread/thread001a.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathEvent.thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class thread001a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static int result; + static volatile boolean mainExited = false; + + public static ArgumentHandler argHandler; + public static Log log; + + public static Object threadsLock = new Object(); + public static Object mainThreadLock = new Object(); + + public static Object threadsStarted = new Object(); + public static Object mainThreadCompleted = new Object(); + + public static void main(String args[]) { + argHandler = new ArgumentHandler(args); + log = argHandler.createDebugeeLog(); + + // execute the test + thread001a _thread001a = new thread001a(); + System.exit(JCK_STATUS_BASE + _thread001a.runIt()); + } + + // perform the test + int runIt() { + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + class InnerThread extends Thread { + InnerThread (String name) { + super(name); + } + public void run() { + log.display(this.getName() + " thread started"); + synchronized (threadsLock) { + threadsLock.notifyAll(); + } + log.display(this.getName() + " thread completed"); + } + } + + // create inner and outer threads + InnerThread innerThread = new InnerThread("innerThread"); + InnerThread innerDaemon = new InnerThread("innerDaemon"); + innerDaemon.setDaemon(true); + + OuterThread outerThread = new OuterThread("outerThread"); + OuterThread outerDaemon = new OuterThread("outerDaemon"); + outerDaemon.setDaemon(true); + + // start threads and lock monitor to prevent threads from exit + synchronized (threadsLock) { + innerThread.start(); + innerDaemon.start(); + outerThread.start(); + outerDaemon.start(); + + // wait for all threads started + while (!(innerThread.isAlive() && + innerDaemon.isAlive() && + outerThread.isAlive() && + outerDaemon.isAlive())) { + try { + synchronized (threadsStarted) { + threadsStarted.wait(1000); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for threads started"); + return FAILED; + } + } + + log.display("All checked threads started in debuggee."); + + // notify debugger that debuggee started and ready for testing + pipe.println(COMMAND_READY); + + // wait for command from debuggee + String command = pipe.readln(); + if (!command.equals(COMMAND_GO)) { + log.complain("TEST BUG: unexpected command: " + command); + return FAILED; + } + + // release lock to permit thread to complete + } + + // wait for all threads completed + while (innerThread.isAlive() || + innerDaemon.isAlive() || + outerThread.isAlive() || + outerDaemon.isAlive()) { + try { + synchronized (threadsLock) { + threadsLock.wait(1000); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for threads completed"); + return FAILED; + } + } + + log.display("All checked threads completed in debuggee."); + + // notify debugger that all threads completed + pipe.println(COMMAND_DONE); + + // wait for command from debuggee + String command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + log.complain("TEST BUG: unexpected command: " + command); + return FAILED; + } + + return PASSED; + } +} + +class OuterThread extends Thread { + OuterThread (String name) { + super(name); + } + public void run() { + thread001a.log.display(this.getName() + " thread started"); + synchronized (thread001a.threadsLock) { + thread001a.threadsLock.notifyAll(); + } + thread001a.log.display(this.getName() + " thread completed"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java new file mode 100644 index 00000000000..8b7557b30d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadDeathRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ThreadDeathRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks that the method restricts the events
    + * genereted by this request to those in the thread to filter.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger creates three ThreadDeathRequests with
    + * addThreadFilter(debuggee's thread2) invoked only on third Request,
    + * resumes the debuggee and waits for the ThreadDeathEvent.
    + * - Debuggee's main thread creates and starts new thread, thread2, and
    + * invokes the methodForCommunication
    + * to inform the debugger with the event.
    + * - Upon getting ThreadDeathEvent, the debugger checks
    + * if EventSet contains all three events; if no, the test FAILED.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class addthreadfilter001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ThreadReference testThread = (ThreadReference) + debuggeeClass.getValue(debuggeeClass.fieldByName("thread2")); + + log2("......setting up ThreadDeathRequest"); + ThreadDeathRequest tdr1 = eventRManager.createThreadDeathRequest(); +// tdr1.addThreadFilter(mainThread); + tdr1.addCountFilter(1); + tdr1.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tdr1.putProperty("number", "ThreadDeathRequest1"); + tdr1.enable(); + + ThreadDeathRequest tdr2 = eventRManager.createThreadDeathRequest(); +// tsr2.addThreadFilter(mainThread); + tdr2.addCountFilter(1); + tdr2.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tdr2.putProperty("number", "ThreadDeathRequest2"); + tdr2.enable(); + + ThreadDeathRequest tdr3 = eventRManager.createThreadDeathRequest(); + tdr3.addThreadFilter(testThread); + tdr3.addCountFilter(1); + tdr3.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tdr3.putProperty("number", "ThreadDeathRequest3"); + tdr3.enable(); + + log2("......vm.resume();"); + vm.resume(); + + log2("......waiting for ThreadDeathEvent"); + getEventSet(); + EventSet eventSet1 = eventSet; + if ( !(eventIterator.nextEvent() instanceof ThreadDeathEvent) ) { + testExitCode = FAILED; + log3("ERROR: new event is not ThreadDeathEvent"); + return; + } + tdr1.disable(); + tdr2.disable(); + tdr3.disable(); + + int setSize = eventSet1.size(); + log2("......eventSet1.size() == " + setSize); + if (setSize != 3) { + log3("ERROR: eventSet1.size() != 3 :: " + setSize); + testExitCode = FAILED; + + EventIterator evI1 = eventSet1.eventIterator(); + while (evI1.hasNext()) { + Event ev1 = evI1.nextEvent(); + log2("........event property : " + ev1.request().getProperty("number")); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001/TestDescription.java new file mode 100644 index 00000000000..79b3c8b6a6a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadDeathRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadDeathRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks that the method restricts the events genereted by + * this request to those in a thread to filter which is not main. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter001; + * the debuggee program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter001 + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001a.java new file mode 100644 index 00000000000..44498dbdc13 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001a.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter001 JDI test. + */ + +public class addthreadfilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread2addthreadfilter001a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread2 = new Thread2addthreadfilter001a("thread2"); + methodForCommunication(); + + threadStart(thread2); + try { + thread2.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static class Thread2addthreadfilter001a extends Thread { + + String tName = null; + + public Thread2addthreadfilter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log3(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log3(" 'run': exit :: threadName == " + tName); + return; + } + } + + + private static void log3(String str) { + log1(Thread.currentThread().getName() + " : " + str); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java new file mode 100644 index 00000000000..d86de05f35c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadDeathRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ThreadDeathRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The cases to check are as follows: + * (1) if this request is currently enabled,
    + * - addThreadFilter(ThreadReference) results in throwing
    + * InvalidRequestStateException;
    + * - addThreadFilter(null) results in throwing
    + * NullPointerException or InvalidRequestStateException;
    + * (2) if this request is currently disabled,
    + * addThreadFilter(null) results in throwing
    + * NullPointerException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase, the debugger creates ThreadDeathRequest
    + * and performs the above checks.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class addthreadfilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......setting up ThreadDeathRequest"); + log2("...... ThreadDeathRequest tdr1 = eventRManager.createThreadDeathRequest();"); + ThreadDeathRequest tdr1 = eventRManager.createThreadDeathRequest(); + tdr1.addCountFilter(1); + tdr1.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tdr1.putProperty("number", "ThreadDeathRequest1"); + + log2("...... tdr1.enable();"); + tdr1.enable(); + + try { + log2("...... tdr1.addThreadFilter(mainThread);"); + log2(" InvalidRequestStateException is expected"); + tdr1.addThreadFilter(mainThread); + log3("ERROR: no InvalidRequestStateException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } catch ( Exception e ) { + log3("ERROR: unexpected Exception : " + e); + testExitCode = FAILED; + } + try { + log2("...... tdr1.addThreadFilter(null);"); + log2(" NullPointerException is expected"); + tdr1.addThreadFilter(null); + log3("ERROR: no NullPointerException "); + testExitCode = FAILED; + } catch ( NullPointerException e ) { + log2(" NullPointerException"); + } catch ( Exception e ) { + log3("ERROR: unexpected Exception : " + e); + testExitCode = FAILED; + } + + log2("...... tdr1.disable()"); + tdr1.disable(); + + try { + log2("...... tdr1.addThreadFilter(null);"); + log2(" NullPointerException or InvalidRequestStateException is expected"); + tdr1.addThreadFilter(null); + log3("ERROR: no Exception thrown"); + testExitCode = FAILED; + } catch ( NullPointerException e ) { + log2(" NullPointerException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } catch ( Exception e ) { + log3("ERROR: unexpected Exception : " + e); + testExitCode = FAILED; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002/TestDescription.java new file mode 100644 index 00000000000..cec53f09576 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadDeathRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadDeathRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks that "if this request is currently enabled" + * calling the method results in throwing InvalidRequestStateException. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter002; + * the debuggee program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter002 + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002a.java new file mode 100644 index 00000000000..1f8a447f497 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter002 JDI test. + */ + +public class addthreadfilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java new file mode 100644 index 00000000000..28550d18b21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadDeathRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ThreadDeathRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ThreadDeathRequest and enables it,
    + * - invokes the method addThreadFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addThreadFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addThreadFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + * + + */ + +public class addthreadfilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter003a"; + + private String testedClassName = + "nsk.jdi.ThreadDeathRequest.addThreadFilter.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "ThreadDeathRequest1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ThreadDeathRequest (null, + EventRequest.SUSPEND_NONE, "ThreadDeathRequest1"); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((ThreadDeathRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no InvalidRequestStateException expected"); + ((ThreadDeathRequest)eventRequest1).addThreadFilter(thread1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((ThreadDeathRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ThreadDeathRequest setting2ThreadDeathRequest( ThreadReference thread, + int suspendPolicy, + String property) + throws JDITestRuntimeException { + try { + ThreadDeathRequest tsr = eventRManager.createThreadDeathRequest(); + if (thread != null) + tsr.addThreadFilter(thread); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingThreadDeathRequest() : " + e); + log3(" ThreadDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ThreadDeathRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003/TestDescription.java new file mode 100644 index 00000000000..47315f8662f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadDeathRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadDeathRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter003; + * the debuggee program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter003 + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003a.java new file mode 100644 index 00000000000..0760402f515 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003a.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter003 JDI test. + */ + +public class addthreadfilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter003a thread1 = null; + + static TestClass objTC = new TestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter003a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter003a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter003a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class TestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004.java new file mode 100644 index 00000000000..0d875bf0924 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ThreadDeathRequest. + * + * The test checks that results of the method + * com.sun.jdi.ThreadDeathRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same ThreadDeathRequest object. + * There are two ThreadDeathRequests to check as follows: + * (1) For ThreadDeathRequest2, both invocations are with different + * ThreadReferences restricting one ThreadDeath event to two threads. + * The test expects no ThreadDeath event will be received. + * (2) For ThreadDeathRequest1, both invocations are with the same + * ThreadReference restricting one ThreadDeath event to one thread. + * The test expects this ThreadDeath event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up ThreadDeathRequests 1&2 within the method + * in the class addthreadfilter004aTestClass which will be calling by both threads, + * - restricts the ThreadDeathRequest1 only to thread1, + * - restricts the ThreadDeathRequest2 only to thread2, + * - resumes debuggee's main thread, and + * - waits for the requested events for both threads. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class addthreadfilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter004a"; + return new addthreadfilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter004aTestClass"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ThreadDeathRequest1"; + String property2 = "ThreadDeathRequest2"; + + ReferenceType testClassReference = null; + + boolean thread1EventReceived = false; + boolean thread2EventReceived = false; + boolean bpEventReceived = false; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2ThreadDeathRequest (thread1, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2ThreadDeathRequest (thread1, + EventRequest.SUSPEND_ALL, property2); + + ((ThreadDeathRequest) eventRequest1).addThreadFilter(thread1); + ((ThreadDeathRequest) eventRequest2).addThreadFilter(thread2); + + display("......waiting for ThreadDeathEvent in tested thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ThreadDeathEvent)) { + setFailedStatus("ERROR: new event is not ThreadDeathEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ThreadDeathEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + EventRequest newEventRequest = newEvent.request(); + if (!newEventRequest.equals(eventRequest1) ) { + setFailedStatus("The ThreadDeathEvent occured not for eventRequest1"); + } + + ThreadReference thr = ((ThreadDeathEvent)newEvent).thread(); + if (!thr.equals(thread1)) { + setFailedStatus("The ThreadDeathEvent occured in unexpected thread: " + thr); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ThreadDeathRequest setting2ThreadDeathRequest( ThreadReference thread, + int suspendPolicy, + String property) { + try { + ThreadDeathRequest tsr = eventRManager.createThreadDeathRequest(); + if (thread != null) + tsr.addThreadFilter(thread); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ThreadDeathRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004/TestDescription.java new file mode 100644 index 00000000000..8710d3725e6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadDeathRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadDeathRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * There are two ThreadDeathRequests, each one with filter for for his own thread. + * After enabling the requests, the debuggee starts both threads. + * The test expects this ThreadDeath event for both threads will be received. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter004; + * the debuggee program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was fixed due to bug: + * 4559026 TEST_BUG: NSK test addthreadfilter004 fails in -Xcomp mode + * Modified due to fix of the bug: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter004 + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004a.java new file mode 100644 index 00000000000..42aa00db4ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter004a.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addaddthreadfilter004 JDI test. + */ + +public class addthreadfilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter004a thread1 = null; + static Threadaddthreadfilter004a thread2 = null; + + static addthreadfilter004aTestClass objTC = new addthreadfilter004aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter004a("thread1"); + thread2 = new Threadaddthreadfilter004a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + waitForThreadJoin (thread1, "thread1"); + waitForThreadJoin (thread2, "thread2"); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static void waitForThreadJoin (Thread thread, String threadName) { + log1("waiting for " + threadName + " join"); + + // get internal timeout in minutes for waiting of thread completion. + int waitTime = argHandler.getWaitTime(); + if (thread.isAlive()) { + try { + thread.join(waitTime * 60 * 1000); + } catch (InterruptedException e) { + throw new Failure("catched unexpected InterruptedException while waiting of " + threadName + " join:" + e); + }; + } + if (thread.isAlive()) { + throw new Failure(threadName + " is still alive"); + } else { + log1(threadName + " joined"); + } + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter004a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter004a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class addthreadfilter004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java new file mode 100644 index 00000000000..ae742b7d7ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java @@ -0,0 +1,540 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadDeathRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ThreadDeathRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Restricts the events generated by this request
    + * to those in the given thread.
    + * The cases to test include three thread's states:
    + * not started, running, dead.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates ThreadDeathRequest1 and
    + * invokes the method addThreadFilter(tread1) on the request1,
    + * - creates ThreadDeathRequest2,
    + * resumes the debuggee to get the thread1 started, and
    + * invokes the method addThreadFilter(thread) on the request2,
    + * - creates ThreadDeathRequest3, waits the thread1 to die, and
    + * invokes the method addThreadFilter(thread) on the request3.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + * + + */ + +public class addthreadfilter005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter005().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter005a"; + + private String testedClassName = + "nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter005aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + ThreadReference thread1 = null; + + String thread1Name = "thread1"; + + String property1 = "ThreadDeathRequest1"; + String property2 = "ThreadDeathRequest2"; + String property3 = "ThreadDeathRequest3"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ThreadDeathRequest (null, + EventRequest.SUSPEND_NONE, property1); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ThreadDeathRequest)eventRequest1).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 1: + eventRequest2 = setting2ThreadDeathRequest (null, + EventRequest.SUSPEND_NONE, property2); + + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ThreadDeathRequest)eventRequest2).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2ThreadDeathRequest (null, + EventRequest.SUSPEND_NONE, property3); + + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ThreadDeathRequest)eventRequest3).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ThreadDeathRequest setting2ThreadDeathRequest( ThreadReference thread, + int suspendPolicy, + String property) + throws JDITestRuntimeException { + try { + ThreadDeathRequest tsr = eventRManager.createThreadDeathRequest(); + if (thread != null) + tsr.addThreadFilter(thread); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingThreadDeathRequest() : " + e); + log3(" ThreadDeathRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ThreadDeathRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005/TestDescription.java new file mode 100644 index 00000000000..43f0dcaa911 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadDeathRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadDeathRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include three thread's states: not started, running, dead. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter005; + * the debuggee program - nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter005 + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadDeathRequest.addThreadFilter.addthreadfilter005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005a.java new file mode 100644 index 00000000000..f43cf02f605 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005a.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadDeathRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addaddthreadfilter005 JDI test. + */ + +public class addthreadfilter005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter005a thread1 = null; + + static addthreadfilter005aTestClass objTC = new addthreadfilter005aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter005a("thread1"); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();"); + methodForCommunication(); + } + break; + + case 2: + try { + thread1.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter005a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter005a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter "); + + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + log1(" 'run': exit "); + } + return; + } + } + +} + +class addthreadfilter005aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001.java new file mode 100644 index 00000000000..ea71477890e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadGroupReference.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +//import com.sun.jdi.event.*; +//import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadGroupReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadGroupReference.name()
    + * complies with its spec.
    + *
    + * The case for testing includes two ThreadGroup objects defined in two
    + * debuggee's classes, and their mirrors in a debugger.
    + * The objects are created together with two debuggee's threads,
    + * main and another one.
    + * The test works as follows. After being started up,
    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger gets the mirrors of the ThreadGroup objects,
    + * uses the method ThreadGroupReference.name() to get the names of both
    + * objects, and checks up the names are ones expected.
    + */ + +public class name001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadGroupReference/name/name001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new name001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadGroupReference.name.name001a"; + + private String testedClassName = + "nsk.jdi.ThreadGroupReference.name.Threadname001a"; + + //String mName = "nsk.jdi.ThreadGroupReference.name"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + //static EventRequestManager eventRManager = null; + //static EventQueue eventQueue = null; + //static EventSet eventSet = null; + + ReferenceType thread2class = null; + ReferenceType mainthreadclass = null; + + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + String mainGroupObj = "mainGroupObj"; + String thread2GroupObj = "thread2GroupObj"; + + String mainGroupName = "mainthreadGroupName"; + String thread2GroupName = "thread2GroupName"; + List classes = null; + + + label0: { + + log2("getting ThreadReference objects"); + try { + classes = vm.classesByName(testedClassName); + thread2class = (ReferenceType) classes.get(0); + classes = vm.classesByName(debuggeeName); + mainthreadclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + + log2(" getting: ThreadGroupReference mainGroup"); + ThreadGroupReference mainGroup = (ThreadGroupReference) + mainthreadclass.getValue(mainthreadclass.fieldByName(mainGroupObj) ); + + log2(" getting: ThreadGroupReference thread2Group"); + ThreadGroupReference thread2Group = (ThreadGroupReference) + thread2class.getValue(thread2class.fieldByName(thread2GroupObj) ); + + log2(" checking up: mainGroup.name().equals(mainGroupName)"); + if ( !mainGroup.name().equals(mainGroupName) ) { + log3("ERROR: !mainGroup.name().equals(mainGroupName) : " + mainGroup.name() ); + expresult = returnCode1; + } + + log2(" checking up: thread2Group.name().equals(thread2GroupName)"); + if ( !thread2Group.name().equals(thread2GroupName) ) { + log3("ERROR: !thread2Group.name().equals(thread2GroupName) : " + thread2Group.name() ); + expresult = returnCode1; + } + + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001/TestDescription.java new file mode 100644 index 00000000000..acac4797b40 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadGroupReference/name/name001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadGroupReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadGroupReference.name() + * complies with its spec: + * public String name() + * Returns the name of this thread group. + * Returns: the string containing the thread group name. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadGroupReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadGroupReference.name.name001; + * the debuggee program - nsk.jdi.ThreadGroupReference.name.name001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadGroupReference.name.name001 + * nsk.jdi.ThreadGroupReference.name.name001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadGroupReference.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001a.java new file mode 100644 index 00000000000..9172457a897 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/name/name001a.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadGroupReference.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the name001 JDI test. + */ + +public class name001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + private static ThreadGroup mainGroupObj = new ThreadGroup("mainthreadGroupName"); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadGroupReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadGroupReference.parent()
    + * complies with its spec.
    + *
    + * The case for testing includes four ThreadGroup objects defined
    + * in two debuggee's classes and in an external class,
    + * and their mirrors in a debugger.
    + * Parenthood relationships between the objects are as follows:
    + * mainParent -> mainthreadGroup -> thread2Group1 -> thread2Group2
    + * The objects are created together with two debuggee's threads,
    + * mainthread and a thread2.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread,
    + * the thread2, informs a debugger of the thread2 creation,
    + * and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger gets the mirrors of all the ThreadGroup objects,
    + * and checks up the above mentioned parenthood relationships.
    + */ + +public class parent001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadGroupReference/parent/parent001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new parent001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadGroupReference.parent.parent001a"; + + private String testedClassName = + "nsk.jdi.ThreadGroupReference.parent.Threadparent001a"; + + //String mName = "nsk.jdi.ThreadGroupReference.parent"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + //static EventRequestManager eventRManager = null; + //static EventQueue eventQueue = null; + //static EventSet eventSet = null; + + ReferenceType testedclass = null; + + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + List classes = null; + + ThreadGroupReference group0 = null; + ThreadGroupReference group1 = null; + ThreadGroupReference group2 = null; + ThreadGroupReference group3 = null; + + String obj0Name = "obj0Name"; + String obj1Name = "obj1Name"; + String obj2Name = "obj2Name"; + String obj3Name = "obj3Name"; + + String str = null; + + ReferenceType mainthreadClass = null; + ReferenceType thread2Class = null; + + label0: { + + log2("getting ThreadReference objects"); + try { + classes = vm.classesByName(testedClassName); + thread2Class = (ReferenceType) classes.get(0); + classes = vm.classesByName(debuggeeName); + mainthreadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + + + log2(" getting a ThreadGroupReference object for a parent of 'mainthreadGroup'"); + str = ( (StringReference) + thread2Class.getValue(thread2Class.fieldByName(obj0Name)) ).value(); + group0 = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(str)); + + + log2(" getting a ThreadGroupReference object for 'mainthreadGroup'"); + str = ( (StringReference) + thread2Class.getValue(thread2Class.fieldByName(obj1Name)) ).value(); + group1 = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(str)); + + + log2(" getting a ThreadGroupReference object for 'thread2Group1'"); + str = ( (StringReference) + thread2Class.getValue(thread2Class.fieldByName(obj2Name)) ).value(); + group2 = (ThreadGroupReference) + thread2Class.getValue(thread2Class.fieldByName(str)); + + log2(" getting a ThreadGroupReference object for 'thread2Group2'"); + str = ( (StringReference) + thread2Class.getValue(thread2Class.fieldByName(obj3Name)) ).value(); + group3 = (ThreadGroupReference) + thread2Class.getValue(thread2Class.fieldByName(str)); + + + log2(" checking up the parent of 'thread2Group2'; 'thread2Group1' is expected"); + if (!group3.parent().equals(group2)) { + log3("ERROR: !group3.parent().equals(group2)"); + expresult = returnCode1; + } + log2(" checking up the parent of 'thread2Group1'; 'mainthreadGroup' is expected"); + if (!group2.parent().equals(group1)) { + log3("ERROR: !group2.parent().equals(group1)"); + expresult = returnCode1; + } + log2(" checking up the parent of 'mainthreadGroup'; 'mainParent' is expected"); + if (!group1.parent().equals(group0)) { + log3("ERROR: group1.parent().equals(group0) : " + group1.parent().name()); + expresult = returnCode1; + } + + + log2(" instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001/TestDescription.java new file mode 100644 index 00000000000..1fa4b96286a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadGroupReference/parent/parent001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadGroupReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadGroupReference.parent() + * complies with its spec: + * public ThreadGroupReference parent() + * Returns the parent of this thread group. + * Returns: a ThreadGroupReference mirroring the parent of this thread group + * in the target VM, or null if this is a top-level thread group. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadGroupReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadGroupReference.parent.parent001; + * the debuggee program - nsk.jdi.ThreadGroupReference.parent.parent001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadGroupReference.parent.parent001 + * nsk.jdi.ThreadGroupReference.parent.parent001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadGroupReference.parent.parent001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001a.java new file mode 100644 index 00000000000..6c07f0bf03a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/parent/parent001a.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadGroupReference.parent; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the parent001 JDI test. + */ + +public class parent001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + public static final String mainthreadGroupName = "mainthreadGroup"; + public static ThreadGroup mainthreadGroupObj = new ThreadGroup(mainthreadGroupName); + + public static ThreadGroup mainParent = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadGroupReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadGroupReference.resume()
    + * complies with its spec.
    + *
    + * The case for testing includes four ThreadGroup objects defined
    + * in a debuggee and their mirrors in a debugger.
    + * Parenthood relationships between the objects are as follows:
    + * threadGroups 2&3 are subgroups of threadGroup1
    + * threadGroup4 is a subgroup of threadGroup3
    + * The objects are created together with three threads, Thread 2,3,4,
    + * belonging to the corresponding subgroups.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates the threads,
    + * informs the debugger of the threads creation,
    + * and is waiting for reply.
    + * Since the threads use the same locking object in their 'run' methods
    + * they are locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger gets mirrors of threadGroups and checks up that
    + * after suspending all the three threads:
    + * - group4.resume(); resumes only Thread4;
    + * - group3.resume(); resumes Thread3 and Thread4;
    + * - group2.resume(); resumes only Thread2;
    + * - group1.resume(); resumes Thread2, Thread3 and Thread4.
    + */ + +public class resume001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadGroupReference/resume/resume001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new resume001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadGroupReference.resume.resume001a"; + + private String testedClassName = + "nsk.jdi.ThreadGroupReference.resume.Threadresume001a"; + + //String mName = "nsk.jdi.ThreadGroupReference.resume"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + List classes = null; + + ThreadGroupReference groups[] = { null, null, null, null }; + + String groupNames [] = { "threadGroup1Obj", + "threadGroup2Obj", + "threadGroup3Obj", + "threadGroup4Obj" }; + + List threads; + ListIterator iterator; + int flag; + String threadName; + ThreadReference thread; + + + String threadNames [] = { "Thread2", "Thread3", "Thread4" }; + + ReferenceType mainthreadClass = null; + ReferenceType thread2Class = null; + + label0: { + + log2("getting ThreadReference objects"); + try { + classes = vm.classesByName(testedClassName); + thread2Class = (ReferenceType) classes.get(0); + classes = vm.classesByName(debuggeeName); + mainthreadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + log2(" getting a List of all threadGroups"); + for (int i1 = 0; i1 < 4; i1++) { + groups[i1] = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(groupNames[i1])); + } + + log2(" getting a List of all running threads"); + threads = vm.allThreads(); + + + log2("......checking up threads resumed with groups[3].resume()"); + log2(" expected: 'Thread4'"); + groups[0].suspend(); + groups[3].resume(); + + iterator = threads.listIterator(); + flag = 0; + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + if (!thread.isSuspended()) + continue; + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + flag |= 1; + else if (threadName.equals(threadNames[1])) + flag |= 2; + else if (threadName.equals(threadNames[2])) + flag |= 4; + else flag |= 8; + } + if (flag != 3) { + expresult = returnCode1; + if (flag == 0) + log3("ERROR: no threads suspunded"); + if ((flag & 4) != 0) + log3("ERROR: 'Thread4' is among suspended threads"); + if ((flag & 2) == 0) + log3("ERROR: 'Thread3' is not suspended"); + if ((flag & 1) == 0) + log3("ERROR: 'Thread2' is not suspended"); + if (flag >= 8) + log3("ERROR: some extra thread(s) is also suspended"); + } + vm.resume(); + + + log2("......checking up threads resumed with groups[2].resume()"); + log2(" expected: 'Thread3' and 'Thread4'"); + groups[0].suspend(); + groups[2].resume(); + + iterator = threads.listIterator(); + flag = 0; + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + if (!thread.isSuspended()) + continue; + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + flag |= 1; + else if (threadName.equals(threadNames[1])) + flag |= 2; + else if (threadName.equals(threadNames[2])) + flag |= 4; + else flag |= 8; + } + if (flag != 1) { + expresult = returnCode1; + if (flag == 0) + log3("ERROR: no threads suspunded"); + if ((flag & 4) != 0) + log3("ERROR: 'Thread4' is among suspended threads"); + if ((flag & 2) != 0) + log3("ERROR: 'Thread3' is among suspended threads"); + if ((flag & 1) == 0) + log3("ERROR: 'Thread2' is not suspended"); + if (flag >= 8) + log3("ERROR: some extra thread(s) is also suspended"); + } + vm.resume(); + + + log2("......checking up threads resumed with groups[1].resume()"); + log2(" expected: 'Thread2'"); + groups[0].suspend(); + groups[1].resume(); + + iterator = threads.listIterator(); + flag = 0; + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + if (!thread.isSuspended()) + continue; + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + flag |= 1; + else if (threadName.equals(threadNames[1])) + flag |= 2; + else if (threadName.equals(threadNames[2])) + flag |= 4; + else flag |= 8; + } + if (flag != 6) { + expresult = returnCode1; + if (flag == 0) + log3("ERROR: no threads suspunded"); + if ((flag & 4) == 0) + log3("ERROR: 'Thread4' is not suspended"); + if ((flag & 2) == 0) + log3("ERROR: 'Thread3' is not suspended"); + if ((flag & 1) != 0) + log3("ERROR: 'Thread2' is among suspended threads"); + if (flag >= 8) + log3("ERROR: some extra thread(s) is also suspended"); + } + vm.resume(); + + + log2("......checking up threads resumed with groups[0].resume()"); + log2(" expected: 'Thread2', 'Thread3', and 'Thread4'"); + groups[0].suspend(); + groups[0].resume(); + + iterator = threads.listIterator(); + flag = 0; + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + if (!thread.isSuspended()) + continue; + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + flag |= 1; + else if (threadName.equals(threadNames[1])) + flag |= 2; + else if (threadName.equals(threadNames[2])) + flag |= 4; + else flag |= 8; + } + if (flag != 0) { + expresult = returnCode1; + if (flag == 0) + log3("ERROR: no threads suspunded"); + if ((flag & 4) != 0) + log3("ERROR: 'Thread4' is among suspended threads"); + if ((flag & 2) != 0) + log3("ERROR: 'Thread3' is among suspended threads"); + if ((flag & 1) != 0) + log3("ERROR: 'Thread2' is among suspended threads"); + if (flag >= 8) + log3("ERROR: some extra thread(s) is also suspended"); + } + vm.resume(); + + + log2("......instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001/TestDescription.java new file mode 100644 index 00000000000..a4c98f4a97c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadGroupReference/resume/resume001. + * VM Testbase keywords: [quick, jpda, jdi, quarantine] + * VM Testbase comments: JDK-8016181 + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadGroupReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadGroupReference.resume() + * complies with its spec: + * public void resume() + * Resumes all threads in this thread group. + * Each thread in this group and in all of its subgroups will be resumed as + * described in ThreadReference.resume(). + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadGroupReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadGroupReference.resume.resume001; + * the debuggee program - nsk.jdi.ThreadGroupReference.resume.resume001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadGroupReference.resume.resume001 + * nsk.jdi.ThreadGroupReference.resume.resume001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadGroupReference.resume.resume001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001a.java new file mode 100644 index 00000000000..718a9fd7327 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/resume/resume001a.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadGroupReference.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the resume001 JDI test. + */ + +public class resume001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + public static final String mainthreadGroupName = "mainthreadGroup"; + public static final String threadGroup2Name = "threadGroup2"; + public static final String threadGroup3Name = "threadGroup3"; + public static final String threadGroup4Name = "threadGroup4"; + + public static ThreadGroup threadGroup1Obj = new ThreadGroup(mainthreadGroupName); + public static ThreadGroup threadGroup2Obj = new ThreadGroup(threadGroup1Obj, threadGroup2Name); + public static ThreadGroup threadGroup3Obj = new ThreadGroup(threadGroup1Obj, threadGroup3Name); + public static ThreadGroup threadGroup4Obj = new ThreadGroup(threadGroup3Obj, threadGroup4Name); + + private static Threadresume001a thread2 = null; + private static Threadresume001a thread3 = null; + private static Threadresume001a thread4 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadGroupReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadGroupReference.suspend()
    + * complies with its spec.
    + *
    + * The case for testing includes four ThreadGroup objects defined
    + * in a debuggee and their mirrors in a debugger.
    + * Parenthood relationships between the objects are as follows:
    + * threadGroups 2&3 are subgroups of threadGroup1
    + * threadGroup4 is a subgroup of threadGroup3
    + * The objects are created together with three threads, Thread 2,3,4,
    + * belonging to the corresponding subgroups.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates the threads,
    + * informs the debugger of the threads creation,
    + * and is waiting for reply.
    + * Since the threads use the same locking object in their 'run' methods
    + * they are locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger gets mirrors of threadGroups and checks up that:
    + * - group4.suspend(); suspends only Thread4;
    + * - group3.suspend(); suspends Thread3 and Thread4;
    + * - group2.suspend(); suspends only Thread2;
    + * - group1.suspend(); suspends Thread2, Thread3 and Thread4.
    + */ + +public class suspend001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadGroupReference/suspend/suspend001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new suspend001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadGroupReference.suspend.suspend001a"; + + private String testedClassName = + "nsk.jdi.ThreadGroupReference.suspend.Threadsuspend001a"; + + //String mName = "nsk.jdi.ThreadGroupReference.suspend"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + List classes = null; + + ThreadGroupReference groups[] = { null, null, null, null }; + + String groupNames [] = { "threadGroup1Obj", + "threadGroup2Obj", + "threadGroup3Obj", + "threadGroup4Obj" }; + + List threads; + ListIterator iterator; + int flag; + String threadName; + ThreadReference thread; + + String threadNames [] = { "Thread2", "Thread3", "Thread4" }; + + ReferenceType mainthreadClass = null; + ReferenceType thread2Class = null; + + label0: { + + log2("getting ThreadReference objects"); + try { + classes = vm.classesByName(testedClassName); + thread2Class = (ReferenceType) classes.get(0); + classes = vm.classesByName(debuggeeName); + mainthreadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + log2(" getting a List of all threadGroups"); + for (int i1 = 0; i1 < 4; i1++) { + groups[i1] = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(groupNames[i1])); + } + + log2(" getting a List of all running threads"); + threads = vm.allThreads(); + + + log2("......checking up threads suspended with groups[3].suspend()"); + log2(" expected: 'Thread4'"); + groups[3].suspend(); + + iterator = threads.listIterator(); + flag = 0; + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + if (!thread.isSuspended()) + continue; + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + flag |= 1; + else if (threadName.equals(threadNames[1])) + flag |= 2; + else if (threadName.equals(threadNames[2])) + flag |= 4; + else flag |= 8; + } + if (flag != 4) { + expresult = returnCode1; + if (flag == 0) + log3("ERROR: no threads suspunded"); + if ((flag & 4) == 0) + log3("ERROR: 'Thread4' is not among suspended threads"); + if ((flag & 2) != 0) + log3("ERROR: 'Thread3' is also suspended"); + if ((flag & 1) != 0) + log3("ERROR: 'Thread2' is also suspended"); + if (flag >= 8) + log3("ERROR: some extra thread(s) is also suspended"); + } + vm.resume(); + + + log2("......checking up threads suspended with groups[2].suspend()"); + log2(" expected: 'Thread3' and 'Thread4'"); + groups[2].suspend(); + + iterator = threads.listIterator(); + flag = 0; + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + if (!thread.isSuspended()) + continue; + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + flag |= 1; + else if (threadName.equals(threadNames[1])) + flag |= 2; + else if (threadName.equals(threadNames[2])) + flag |= 4; + else flag |= 8; + } + if (flag != 6) { + expresult = returnCode1; + if (flag == 0) + log3("ERROR: no threads suspunded"); + if ((flag & 4) == 0) + log3("ERROR: 'Thread4' is not among suspended threads"); + if ((flag & 2) == 0) + log3("ERROR: 'Thread3' is not among suspended threads"); + if ((flag & 1) != 0) + log3("ERROR: 'Thread2' is also suspended"); + if (flag >= 8) + log3("ERROR: some extra thread(s) is also suspended"); + } + vm.resume(); + + + log2("......checking up threads suspended with groups[1].suspend()"); + log2(" expected: 'Thread2'"); + groups[1].suspend(); + + iterator = threads.listIterator(); + flag = 0; + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + if (!thread.isSuspended()) + continue; + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + flag |= 1; + else if (threadName.equals(threadNames[1])) + flag |= 2; + else if (threadName.equals(threadNames[2])) + flag |= 4; + else flag |= 8; + } + if (flag != 1) { + expresult = returnCode1; + if (flag == 0) + log3("ERROR: no threads suspunded"); + if ((flag & 4) != 0) + log3("ERROR: 'Thread4' is among suspended threads"); + if ((flag & 2) != 0) + log3("ERROR: 'Thread3' is among suspended threads"); + if ((flag & 1) == 0) + log3("ERROR: 'Thread2' is not among suspended threads"); + if (flag >= 8) + log3("ERROR: some extra thread(s) is also suspended"); + } + vm.resume(); + + log2("......checking up threads suspended with groups[0].suspend()"); + log2(" expected: 'Thread2', 'Thread3', and 'Thread4'"); + groups[0].suspend(); + + iterator = threads.listIterator(); + flag = 0; + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + if (!thread.isSuspended()) + continue; + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + flag |= 1; + else if (threadName.equals(threadNames[1])) + flag |= 2; + else if (threadName.equals(threadNames[2])) + flag |= 4; + else flag |= 8; + } + if (flag != 7) { + expresult = returnCode1; + if (flag == 0) + log3("ERROR: no threads suspunded"); + if ((flag & 4) == 0) + log3("ERROR: 'Thread4' is not among suspended threads"); + if ((flag & 2) == 0) + log3("ERROR: 'Thread3' is not among suspended threads"); + if ((flag & 1) == 0) + log3("ERROR: 'Thread2' is not among suspended threads"); + if (flag >= 8) + log3("ERROR: some extra thread(s) is also suspended"); + } + vm.resume(); + + + + + log2("......instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001/TestDescription.java new file mode 100644 index 00000000000..dcf042b460e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadGroupReference/suspend/suspend001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadGroupReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadGroupReference.suspend() + * complies with its spec: + * public void suspend() + * Suspends all threads in this thread group. + * Each thread in this group and in all of its subgroups will be suspended as + * described in ThreadReference.suspend(). This is not guaranteed to be + * an atomic operation; if the target VM is not interrupted + * at the time this method is called, it is possible that new threads + * will be created between the time that + * threads are enumerated and all of them have been suspended. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadGroupReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadGroupReference.suspend.suspend001; + * the debuggee program - nsk.jdi.ThreadGroupReference.suspend.suspend001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadGroupReference.suspend.suspend001 + * nsk.jdi.ThreadGroupReference.suspend.suspend001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadGroupReference.suspend.suspend001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001a.java new file mode 100644 index 00000000000..468912e349d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/suspend/suspend001a.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadGroupReference.suspend; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the suspend001 JDI test. + */ + +public class suspend001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + public static final String mainthreadGroupName = "mainthreadGroup"; + public static final String threadGroup2Name = "threadGroup2"; + public static final String threadGroup3Name = "threadGroup3"; + public static final String threadGroup4Name = "threadGroup4"; + + public static ThreadGroup threadGroup1Obj = new ThreadGroup(mainthreadGroupName); + public static ThreadGroup threadGroup2Obj = new ThreadGroup(threadGroup1Obj, threadGroup2Name); + public static ThreadGroup threadGroup3Obj = new ThreadGroup(threadGroup1Obj, threadGroup3Name); + public static ThreadGroup threadGroup4Obj = new ThreadGroup(threadGroup3Obj, threadGroup4Name); + + private static Threadsuspend001a thread2 = null; + private static Threadsuspend001a thread3 = null; + private static Threadsuspend001a thread4 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadGroupReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadGroupReference.threadGroups()
    + * complies with its spec.
    + *
    + * The case for testing includes four ThreadGroup objects defined
    + * in a debuggee and their mirrors in a debugger.
    + * Parenthood relationships between the objects are as follows:
    + * threadGroups 2&3 are subgroups of threadGroup1
    + * threadGroup4 is a subgroup of threadGroup3
    + * The objects are created together with three threads, Thread 2,3,4,
    + * belonnging to the corresponding subgroups.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates the threads,
    + * informs the debugger of the threads creation,
    + * and is waiting for reply.
    + * Since the threads use the same locking object in their 'run' methods
    + * they are locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger gets mirrors of threadGroups and checks up that:
    + * - threadGroup4 has 0 threadGroup members;
    + * - threadGroup3 has 1 threadGroup member;
    + * - threadGroup1 has 2 threadGroup members with certain names.
    + */ + +public class threadgroups001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new threadgroups001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadGroupReference.threadGroups.threadgroups001a"; + + private String testedClassName = + "nsk.jdi.ThreadGroupReference.threadGroups.Threadthreadgroups001a"; + + //String mName = "nsk.jdi.ThreadGroupReference.threadGroups"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "Thread2"; + + List classes = null; + + ThreadGroupReference group1 = null; + ThreadGroupReference group2 = null; + ThreadGroupReference group3 = null; + ThreadGroupReference group4 = null; + + String parentName = "threadGroup1Obj"; + String group2Name = "threadGroup2Obj"; + String group3Name = "threadGroup3Obj"; + String group4Name = "threadGroup4Obj"; + + String str = null; + + ReferenceType mainthreadClass = null; + ReferenceType thread2Class = null; + + label0: { + + log2("getting ThreadReference objects"); + try { + classes = vm.classesByName(testedClassName); + thread2Class = (ReferenceType) classes.get(0); + classes = vm.classesByName(debuggeeName); + mainthreadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + + + log2(" getting a ThreadGroupReference object for group1"); + group1 = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(parentName)); + + log2(" getting a ThreadGroupReference object for group2"); + group2 = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(group2Name)); + + log2(" getting a ThreadGroupReference object for group3"); + group3 = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(group3Name)); + + log2(" getting a ThreadGroupReference object for group4"); + group4 = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(group4Name)); + + + List threadGroups = null; + + log2(" checking up List size for threadGroup4; should be == 0"); + threadGroups = group4.threadGroups(); + if (threadGroups.size() != 0) { + log3("ERROR: threadGroups.size() != 0 for group4: " + threadGroups.size() ); + expresult = 1; + } + + log2(" checking up List size for threadGroup3; should be == 1"); + threadGroups = group3.threadGroups(); + if (threadGroups.size() != 1) { + log3("ERROR: threadGroups.size() != 1 for group3: " + threadGroups.size() ); + expresult = 1; + } + + log2(" checking up List size for threadGroup1; should be == 2"); + threadGroups = group1.threadGroups(); + if (threadGroups.size() != 2) { + log3("ERROR: threadGroups.size() != 2 for group1: " + threadGroups.size() ); + expresult = 1; + } + + log2(" checking up threadGroup names in List for threadGroup1"); + String s1 = ( (ThreadGroupReference) threadGroups.get(0)).name(); + String s2 = ( (ThreadGroupReference) threadGroups.get(1)).name(); + if (s1.equals("threadGroup2")) { + if (!s2.equals("threadGroup3")) { + log3("ERROR: s1.equals('threadGroup2') but !s2.equals('threadGroup3') : " + s2); + expresult = 1; + } + } else if (s1.equals("threadGroup3")) { + if (!s2.equals("threadGroup2")) { + log3("ERROR: s1.equals('threadGroup3') but !s2.equals('threadGroup2') : " + s2); + expresult = 1; + } + } else { + log3("ERROR: !s1.equals('threadGroup2') or !s1.equals('threadGroup3') : " + s1); + expresult = 1; + } + + + log2(" instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001/TestDescription.java new file mode 100644 index 00000000000..f52d42b1311 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadGroupReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadGroupReference.threadGroups() + * complies with its spec: + * public List threadGroups() + * Returns a List containing each ThreadGroupReference in this thread group. + * Only the thread groups in this immediate thread group + * (and not its subgroups) are returned. + * Returns: a List of ThreadGroupReference objects mirroring the threads + * from this thread group in the target VM. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadGroupReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadGroupReference.threadGroups.threadgroups001; + * the debuggee program - nsk.jdi.ThreadGroupReference.threadGroups.threadgroups001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadGroupReference.threadGroups.threadgroups001 + * nsk.jdi.ThreadGroupReference.threadGroups.threadgroups001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadGroupReference.threadGroups.threadgroups001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001a.java new file mode 100644 index 00000000000..e5ea28b6e35 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threadGroups/threadgroups001a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadGroupReference.threadGroups; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the threadgroups001 JDI test. + */ + +public class threadgroups001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + public static final String mainthreadGroupName = "mainthreadGroup"; + public static final String threadGroup2Name = "threadGroup2"; + public static final String threadGroup3Name = "threadGroup3"; + public static final String threadGroup4Name = "threadGroup4"; + + public static ThreadGroup threadGroup1Obj = new ThreadGroup(mainthreadGroupName); + public static ThreadGroup threadGroup2Obj = new ThreadGroup(threadGroup1Obj, threadGroup2Name); + public static ThreadGroup threadGroup3Obj = new ThreadGroup(threadGroup1Obj, threadGroup3Name); + public static ThreadGroup threadGroup4Obj = new ThreadGroup(threadGroup3Obj, threadGroup4Name); + + public static ThreadGroup mainParent = null; + + private static Threadthreadgroups001a thread2 = null; + private static Threadthreadgroups001a thread3 = null; + private static Threadthreadgroups001a thread4 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadGroupReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadGroupReference.threads()
    + * complies with its spec.
    + *
    + * The case for testing includes two ThreadGroup objects defined
    + * in a debuggee and their mirrors in a debugger.
    + * Parenthood relationships between the objects are as follows:
    + * threadGroup2 is a subgroup of mainParent
    + * The objects are created together with three debuggee's threads;
    + * the main thread and a thread2 belong to the mainParent group,
    + * whereas a thread3 to the subgroup.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates two new threads,
    + * informs the debugger of the threads creation,
    + * and is waiting for reply.
    + * Since the threads use the same locking object in their 'run' methods
    + * they are locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger gets Lists of threads in each of the groups,
    + * and checks up the sizes of Lists and names of ThreadReference objects
    + * in the List returned by the tested method,
    + * that is, mainParent.threads().
    + */ + +public class threads001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadGroupReference/threads/threads001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new threads001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadGroupReference.threads.threads001a"; + + private String testedClassName = + "nsk.jdi.ThreadGroupReference.threads.Threadthreads001a"; + + //String mName = "nsk.jdi.ThreadGroupReference.threads"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "Thread2"; + + List classes = null; + + ThreadGroupReference group1 = null; + ThreadGroupReference group2 = null; + + + String parentName = "mainParent"; + String group2Name = "threadGroup2Obj"; + + String str = null; + + ReferenceType mainthreadClass = null; + ReferenceType thread2Class = null; + + label0: { + + log2("getting ThreadReference objects"); + try { + classes = vm.classesByName(testedClassName); + thread2Class = (ReferenceType) classes.get(0); + classes = vm.classesByName(debuggeeName); + mainthreadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + + + log2(" getting a ThreadGroupReference object for main tested group"); + group1 = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(parentName)); + + log2(" getting a ThreadGroupReference object for subgroup"); + group2 = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(group2Name)); + + + List threads = null; + + log2(" checking up sizes of Lists of thread groups returned"); + threads = group2.threads(); + if (threads.size() != 1) { + log3("ERROR: threads.size() != 1 for group2: " + threads.size() ); + expresult = 1; + } + threads = group1.threads(); + if (threads.size() < 2) { + log3("ERROR: threads.size() < 2 for group1 : " + threads.size() ); + expresult = 1; + } + + log2(" checking up names of threads 'main' and 'Thread2' in List returned"); + ListIterator li = threads.listIterator(); + int nMain = 0; + int nThread2 = 0; + for ( int i2 = 0; li.hasNext(); i2++ ) { + String s1 = ( (ThreadReference) li.next()).name(); + if (s1.equals("main")) + nMain += 1; + if (s1.equals("Thread2")) + nThread2 += 1; + } + if (nMain != 1) { + log3("ERROR: # of 'main' threads != 1 : " + nMain); + expresult = 1; + } + if (nThread2 != 1) { + log3("ERROR: # of 'Thread2' threads != 1 : " + nThread2); + expresult = 1; + } + + log2(" instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001/TestDescription.java new file mode 100644 index 00000000000..6b55f8bc21f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadGroupReference/threads/threads001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadGroupReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadGroupReference.threads() + * complies with its spec: + * public List threads() + * Returns a List containing each ThreadReference in this thread group. + * Only the threads in this immediate thread group (and not its subgroups) + * are returned. + * Returns: a List of ThreadReference objects mirroring + * the threads from this thread group in the target VM. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadGroupReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadGroupReference.threads.threads001; + * the debuggee program - nsk.jdi.ThreadGroupReference.threads.threads001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * To fix the bug 4475063, the following correction in file threads001.java are made : + * - new check on + * threads = group1.threads(); + * if (threads.size() < 2) { + * - the check on only two names, "main" and "Thread2", is replaced with the loop + * in which these two names are detected. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadGroupReference.threads.threads001 + * nsk.jdi.ThreadGroupReference.threads.threads001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadGroupReference.threads.threads001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001a.java new file mode 100644 index 00000000000..f316fcf8fc2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/threads/threads001a.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadGroupReference.threads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the threads001 JDI test. + */ + +public class threads001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + public static final String mainthreadGroupName = "mainthreadGroup"; + public static final String threadGroup2Name = "threadGroup2"; + + public static ThreadGroup mainthreadGroupObj = new ThreadGroup(mainthreadGroupName); + public static ThreadGroup threadGroup2Obj = new ThreadGroup(threadGroup2Name); + + public static ThreadGroup mainParent = null; + + private static Threadthreads001a thread2 = null; + private static Threadthreads001a thread3 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + checkToString (debuggeeName, mainGroup); + + checkToString (testedClassName, thread2Group); + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static Method methodByName (ReferenceType refType, String methodName) { + List methodList = refType.methodsByName(methodName); + if (methodList == null) return null; + + Method method = (Method) methodList.get(0); + return method; + } + + private static void checkToString (String className, String fieldName) { + display("Checking toString() method for " + + "\n\tclass: " + className + + "\n\tthread group: " + fieldName ); + + ReferenceType testedClass = debuggee.classByName(className); + + ThreadGroupReference threadGroupRef = null; + try { + threadGroupRef = (ThreadGroupReference)testedClass.getValue(testedClass.fieldByName(fieldName)); + } catch (Exception e) { + throw new Failure("Unexpected exception while getting ThreadGroupReference for " + fieldName + " : " + e.getMessage() ); + } + + String str = threadGroupRef.toString(); + if (str == null) { + complain("toString() returns null for " + threadGroupRef.name()); + exitStatus = Consts.TEST_FAILED; + } else if (str.length() == 0) { + complain("toString() returns empty string for for " + threadGroupRef.name()); + exitStatus = Consts.TEST_FAILED; + } else { + display("toString() returns for " + threadGroupRef.name() + " : " + str); + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..da96b484749 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadGroupReference/toString/tostring001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public toString() method of an implementing class of + * com.sun.jdi.ThreadGroupReference interface. + * The test checks an assertion: + * In conformity with the contract for java.lang.Object.toString(), + * the overrided method returns representing non-empty string for + * a ThreadGroupReference mirror of a debuggee's thread group. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for ThreadGroupReference + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadGroupReference.toString.tostring001 + * nsk.jdi.ThreadGroupReference.toString.tostring001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadGroupReference.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001a.java new file mode 100644 index 00000000000..ebc175a3dd4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadGroupReference/toString/tostring001a.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadGroupReference.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class tostring001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static ThreadGroup mainGroup = new ThreadGroup("mainThreadGroup"); + static ThreadGroup thread2Group = new ThreadGroup("thread2Group"); + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + tostring001aThread thread2 = new tostring001aThread(thread2Group, "testedThread"); + display("thread2 is created"); + + synchronized (tostring001aThread.lockingObject) { + synchronized (tostring001aThread.waitnotifyObj) { + thread2.start(); + try { + tostring001aThread.waitnotifyObj.wait(); + } catch (InterruptedException ie) { + thread2.interrupt(); + throw new Failure("Unexpected InterruptedException while waiting for notifying."); + } + + pipe.println(tostring001.SIGNAL_READY); + receiveSignal(tostring001.SIGNAL_QUIT); + } + } + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class tostring001aThread extends Thread { + + public static Object waitnotifyObj = new Object(); + public static Object lockingObject = new Object(); + + private static ThreadGroup thread2Group = null; + + public tostring001aThread(ThreadGroup groupName, String threadName) { + super(groupName, threadName); + thread2Group = groupName; + } + + public void run() { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockingObject) {} + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001.java new file mode 100644 index 00000000000..d1447e7d91a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadReference._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * Test checks up ThreadReference methods for the following cases:
    + * - getValue(null)
    + * - getValues(null)
    + * - getValues(list with size = 0)
    + * - setValue(null, null)
    + * - setValue(field, null)
    + * - visibleVariableByName(null)
    + * - visibleVariableByName("")
    + * NullPointerException is expected for every test case + * except for the three last. + */ + +public class bounds001 { + + private final static String prefix = "nsk.jdi.ThreadReference._bounds_."; + private final static String debuggerName = prefix + "bounds001"; + private final static String debugeeName = debuggerName + "a"; + + public final static String SGNL_READY = "ready"; + public final static String SGNL_QUIT = "quit"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private int[] frameParam = {-1, Integer.MAX_VALUE, -1, -1}; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + bounds001 thisTest = new bounds001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + debugee.VM().suspend(); + ThreadReference thread = debugee.threadByName("main"); + + display("\nTEST BEGINS"); + display("==========="); + + display("stop(null)"); + try { + thread.stop(null); + complain("InvalidTypeException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(InvalidTypeException e) { + display("!!!expected InvalidTypeException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + display("popFrames(null)"); + try { + thread.popFrames(null); + complain("NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } catch(NullPointerException e) { + display("!!!expected NullPointerException"); + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + + int frameCount = 0; + try { + frameCount = thread.frameCount(); + } catch (IncompatibleThreadStateException e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + frameParam[2] = frameCount; + frameParam[3] = frameParam[2] + 1; + display("frame count: " + frameParam[2]); + display("---------------"); + + for (int i = 0; i < frameParam.length; i++) { + display("frame(" + frameParam[i] + ")"); + try { + thread.frame(frameParam[i]); + if (frameParam[i] < 0 || frameParam[i] >= frameCount) { + complain("IndexOutOfBoundsException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } else { + display("OK"); + } + } catch(IndexOutOfBoundsException e) { + if (frameParam[i] < 0 || frameParam[i] >= frameCount) { + display("!!!expected IndexOutOfBoundsException"); + } else { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + + for (int i = 0; i < frameParam.length; i++) { + for (int j = 0; j < frameParam.length; j++) { + display("frames(" + frameParam[i] + ", " + frameParam[j] + ")"); + try { + thread.frames(frameParam[i], frameParam[j]); + if (frameParam[i] < 0 || + frameParam[j] < 0 || + frameParam[i] >= frameCount || + frameParam[i] + frameParam[j] > frameCount) { + complain("IndexOutOfBoundsException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } else { + display("OK"); + } + } catch(IndexOutOfBoundsException e) { + if (frameParam[i] < 0 || + frameParam[j] < 0 || + frameParam[i] >= frameCount || + frameParam[i] + frameParam[j] > frameCount) { + display("!!!expected IndexOutOfBoundsException"); + } else { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch(Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + display(""); + } + } + display(""); + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001/TestDescription.java new file mode 100644 index 00000000000..d5ac645474f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/_bounds_/bounds001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up the methods com.sun.jdi.ThreadReference + * for the following cases: + * - getValue(null) + * - getValues(null) + * - getValues(list with size = 0) + * - setValue(null, null) + * - setValue(field, null) + * - visibleVariableByName(null) + * - visibleVariableByName("") + * NullPointerException is expected for every test case except for + * the three last. + * In cases + * setValue(field, null) + * visibleVariableByName(null) + * visibleVariableByName("") + * no exception is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference._bounds_.bounds001 + * nsk.jdi.ThreadReference._bounds_.bounds001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference._bounds_.bounds001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001a.java new file mode 100644 index 00000000000..67d79abdafb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/_bounds_/bounds001a.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadReference._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * bounds001a is deugee's part of the bounds001. + */ +public class bounds001a { + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(bounds001.SGNL_READY); + String instr = pipe.readln(); + if (instr.equals(bounds001.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001.java new file mode 100644 index 00000000000..6033e10f9bf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001.java @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.currentContendedMonitor; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.currentContendedMonitor()
    + * complies with its spec.
    + *
    + * The test checks up that if a target VM doesn't support
    + * this operation, that is, the method
    + * VirtualMachine.canGetCurrentContendedMonitor()
    + * returns false, and a thread in the target VM is suspended,
    + * invoking the method currentContendedMonitor() on the thread
    + * throws UnsupportedOperationException.
    + */ + +public class currentcm001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new currentcm001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.currentContendedMonitor.currentcm001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.currentContendedMonitor.Threadcurrentcm001a"; + + //String mName = "nsk.jdi.ThreadReference.currentContendedMonitor"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + //static EventRequestManager eventRManager = null; + //static EventQueue eventQueue = null; + //static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + //eventRManager = vm.eventRequestManager(); + //eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + //String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + //String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + + ObjectReference monitor = null; + + ListIterator listIterator = null; + List classes = null; + + //BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + + label0: { + + log2("getting ThreadReference objects"); + try { + allThreads = vm.allThreads(); +// classes = vm.classesByName(testedClassName); +// testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO 'main' thread ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + label1: { + + if (expresult != 0 ) + break label1; + + log2(" suspending the main thread"); + mainThread.suspend(); + + log2("......checking up on canGetCurrentContendedMonitor()"); + if (!vm.canGetCurrentContendedMonitor()) { + log2(" !vm.canGetCurrentContendedMonitor()"); + log2("......checking up throwing UnsupportedOperationException"); + try { + monitor = mainThread.currentContendedMonitor(); + log3("ERROR: no UnsupportedOperationException thrown"); + expresult = returnCode1; + } catch ( UnsupportedOperationException e1 ) { + log2(" UnsupportedOperationException is thrown"); + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: IncompatibleThreadStateException for a suspended thread"); + expresult = returnCode1; + } catch ( Exception e3 ) { + log3("ERROR: unspecified Exception is thrown" + e3); + expresult = returnCode1; + } + } + log2(" resuming the main thread"); + mainThread.resume(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ +/* + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } +*/ + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ +/* + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +*/ +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001/TestDescription.java new file mode 100644 index 00000000000..d69fd057714 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001/TestDescription.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.currentContendedMonitor() + * complies with its spec: + * public ObjectReference currentContendedMonitor() + * throws IncompatibleThreadStateException + * Returns an ObjectReference for the monitor, if any, + * for which this thread is currently waiting. + * The thread can be waiting for a monitor through entry into + * a synchronized method, the synchronized statement, or Object.wait(long). + * The status() method can be used to differentiate between + * the first two cases and the third. + * Not all target virtual machines support this operation. + * Use VirtualMachine.canGetCurrentContendedMonitor() to determine if + * the operation is supported. + * Returns: the ObjectReference corresponding to the contended monitor, or + * null if it is not waiting for a monitor. + * Throws: java.lang.UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * IncompatibleThreadStateException - + * if the thread is not suspended in the target VM + * ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadGroupReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.currentContendedMonitor.currentcm001; + * the debuggee program - nsk.jdi.ThreadReference.currentContendedMonitor.currentcm001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.currentContendedMonitor.currentcm001 + * nsk.jdi.ThreadReference.currentContendedMonitor.currentcm001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.currentContendedMonitor.currentcm001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001a.java new file mode 100644 index 00000000000..298b7b408ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/currentContendedMonitor/currentcm001a.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.currentContendedMonitor; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the currentcm001 JDI test. + */ + +public class currentcm001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + +// private static Threadcurrentcm001a thread2 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-totalThreadsCount") && (i < args.length - 1)) { + totalThreadsCount = Integer.parseInt(args[i + 1]); + + // if threads count is specified, test should take in account threads factor + totalThreadsCount *= stressOptions.getThreadsFactor(); + + i++; + } else if (args[i].equals("-iterationsNumber") && (i < args.length - 1)) { + baseIterationsNumber = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int totalThreadsCount = 1; + + private int baseIterationsNumber = 1; + + private TestExecutorThread testThread; + + // predefined in TestThread values to pass in forceEarlyReturn() + private Value testValues[]; + + private Value invalidValues[]; + + class TestExecutorThread extends Thread { + TestData testDataArray[]; + + private ThreadReference thread; + + public TestExecutorThread(ReferenceType testedThreadReferenceType, String threadName) { + thread = debuggee.threadByName(threadName); + + testDataArray = new TestData[ForceEarlyReturnTestThread.testedTypesNames.length]; + + for (int i = 0; i < testDataArray.length; i++) { + testDataArray[i] = new TestData(testedThreadReferenceType, + ForceEarlyReturnTestThread.testedTypesNames[i] + "Method", + ForceEarlyReturnTestThread.breakpointLines[i], thread, testValues[i], invalidValues[i]); + } + } + + public void run() { + stresser.start(baseIterationsNumber); + try { + /* + * In this test exit loop condition should be checked before + * resuming test thread + */ + while (true) { + /* + * In this test single iteration is test forceEarlyReturn using + * all elements of testDataArray + */ + stresser.iteration(); + + boolean stopExecution = false; + + for (int i = 0; i < testDataArray.length; i++) { + testForceEarlyReturn(testDataArray[i]); + + // check exit loop condition before resuming test thread + stopExecution = !stresser.continueExecution() || (stresser.getIterationsLeft() == 0); + + if (stopExecution) { + log.display("Execution finished, stopping test threads"); + + /* + * When test completed debuggee should call for test thread + * ForceEstopExecution.stopExecution() before this thread is resumed + */ + pipe.println(forceEarlyReturn001a.COMMAND_STOP_TEST_THREADS); + + if (!isDebuggeeReady()) + return; + + thread.resume(); + + break; + } else { + thread.resume(); + } + } + + if (stopExecution) + break; + } + } finally { + stresser.finish(); + } + + log.display("Waiting for test threads finishing"); + + pipe.println(forceEarlyReturn001a.COMMAND_JOIN_TEST_THREADS); + + if (!isDebuggeeReady()) + return; + } + + private void testForceEarlyReturn(TestData testData) { + BreakpointEvent breakPointEvent = waitForBreakpoint(testData.breakpointRequest); + + try { + log.display("Calling forceEarlyReturn with incompatible value: " + testData.incompatibleValue); + + thread.forceEarlyReturn(testData.incompatibleValue); + setSuccess(false); + log.complain("Expected InvalidTypeException was not thrown, method: " + testData.methodName); + } catch (InvalidTypeException e) { + // expected exception + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e + ", method: " + testData.methodName); + e.printStackTrace(System.out); + } + + try { + log.display("Calling forceEarlyReturn with value: " + testData.returnValue); + breakPointEvent.thread().forceEarlyReturn(testData.returnValue); + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e + ", method: " + testData.methodName); + e.printStackTrace(System.out); + } + + testMethodExitEvent(thread, testData.methodName, false); + } + } + + // initialize Values objects to pass in forceEarlyReturn() + protected void initTestValues() { + ReferenceType referenceType = debuggee.classByName(ForceEarlyReturnTestThread.class.getName()); + + Value voidValue = createVoidValue(); + + if (voidValue == null) { + setSuccess(false); + log.complain("Can't create void value"); + return; + } + + testValues = new Value[ForceEarlyReturnTestThread.testedTypesNames.length + 1]; + invalidValues = new Value[ForceEarlyReturnTestThread.testedTypesNames.length + 1]; + + testValues[0] = voidValue; + + for (int i = 1; i < ForceEarlyReturnTestThread.testedTypesNames.length; i++) + testValues[i] = referenceType.getValue(referenceType.fieldByName("expected" + + ForceEarlyReturnTestThread.testedTypesNames[i] + "Value")); + + for (int i = 0; i < ForceEarlyReturnTestThread.testedTypesNames.length; i++) { + invalidValues[i] = referenceType.getValue(referenceType.fieldByName("invalid" + + ForceEarlyReturnTestThread.testedTypesNames[i] + "Value")); + } + } + + private void startTestThread() { + ReferenceType referenceType = debuggee.classByName(ForceEarlyReturnTestThread.class.getName()); + + testThread = new TestExecutorThread(referenceType, forceEarlyReturn001a.baseTestThreadName + 0); + + testThread.start(); + } + + private void waitTestEnd() { + try { + testThread.join(); + } catch (InterruptedException e) { + unexpectedException(e); + } + } + + public void doTest() { + initTestValues(); + + pipe.println(forceEarlyReturn001a.COMMAND_START_AND_SUSPEND_TEST_THREADS + ":" + totalThreadsCount + ":" + + baseIterationsNumber * stressOptions.getIterationsFactor()); + + if (!isDebuggeeReady()) + return; + + startTestThread(); + + pipe.println(forceEarlyReturn001a.COMMAND_START_TEST_THREADS_EXECUTION); + + if (!isDebuggeeReady()) + return; + + waitTestEnd(); + + // delete all created breakpoints + for (TestData testData : testThread.testDataArray) { + debuggee.getEventRequestManager().deleteEventRequest(testData.breakpointRequest); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001a.java new file mode 100644 index 00000000000..9fac59836db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001a.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001; + +import java.io.*; +import nsk.share.*; +import nsk.share.jpda.ForceEarlyReturnTestThread; +import nsk.share.jdi.*; + +public class forceEarlyReturn001a extends AbstractJDIDebuggee { + static { + try { + // load thread class to let debugger get ReferenceType for + // TestThread class + Class.forName(ForceEarlyReturnTestThread.class.getName()); + } catch (ClassNotFoundException e) { + System.out.println("ClassNotFoundException while loading test thread class: " + e); + e.printStackTrace(System.out); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + } + + public static void main(String args[]) { + new forceEarlyReturn001a().doTest(args); + } + + // start and suspend test threads to let debugger initialize breakpoints + // (debugger should obtain ThreadReference) + // command:threadsNumber:iterationsNumber + public static final String COMMAND_START_AND_SUSPEND_TEST_THREADS = "startAndSuspendTestThreads"; + + // let test threads continue execution + public static final String COMMAND_START_TEST_THREADS_EXECUTION = "startTestThreadsExecution"; + + // set flag 'stopExecution' for test threads + public static final String COMMAND_STOP_TEST_THREADS = "stopTestThreads"; + + // wait for test threads finishing + public static final String COMMAND_JOIN_TEST_THREADS = "joinTestThreads"; + + // base name for test threads, test thread should be named + // 'baseTestThreadName + threadIndex' + public static final String baseTestThreadName = "forceEarlyReturn001aTestThread_"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command)); + tokenizer.whitespaceChars(':', ':'); + + try { + if (command.startsWith(COMMAND_START_AND_SUSPEND_TEST_THREADS)) { + tokenizer.nextToken(); + + if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) + throw new TestBug("Invalid command format: " + command); + + int threadsCount = (int) tokenizer.nval; + + if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) + throw new TestBug("Invalid command format: " + command); + + int iterationsNumber = (int) tokenizer.nval; + + startTestThreads(threadsCount, iterationsNumber); + + return true; + } else if (command.equals(COMMAND_START_TEST_THREADS_EXECUTION)) { + startTestThreadsExecution(); + + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREADS)) { + stopTestThreads(); + + return true; + } else if (command.equals(COMMAND_JOIN_TEST_THREADS)) { + joinTestThreads(); + + return true; + } + } catch (IOException e) { + throw new TestBug("Invalid command format: " + command); + } + + return false; + } + + private ForceEarlyReturnTestThread testThreads[]; + + private void startTestThreads(int threadsCount, int iterationsNumber) { + testThreads = new ForceEarlyReturnTestThread[threadsCount]; + + for (int i = 0; i < threadsCount; i++) { + testThreads[i] = new ForceEarlyReturnTestThread(log, (i == 0), iterationsNumber); + testThreads[i].setName(baseTestThreadName + i); + + // testThreads[i] should wait in beginning of run() + testThreads[i].start(); + } + } + + private void startTestThreadsExecution() { + if (testThreads == null) { + throw new TestBug("Test threads weren't started"); + } + + // let test threads continue execution + for (int i = 0; i < testThreads.length; i++) + testThreads[i].startExecuion(); + } + + private void stopTestThreads() { + if (testThreads == null) { + throw new TestBug("Test threads weren't started"); + } + + for (int i = 0; i < testThreads.length; i++) { + testThreads[i].stopExecution(); + } + } + + private void joinTestThreads() { + if (testThreads == null) { + throw new TestBug("Test threads weren't started"); + } + + for (int i = 0; i < testThreads.length; i++) { + try { + testThreads[i].join(); + } catch (InterruptedException e) { + unexpectedException(e); + } + + if (!testThreads[i].getSuccess()) + setSuccess(false); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java new file mode 100644 index 00000000000..7a19c6f966b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - attempt to call forceEarlyReturn for the type which has not yet been loaded throws ClassNotLoadedException + * - MethodExitEvent is generated as it would be in a normal return + * Test scenario: + * Debugger VM enable breakpoint in test method which return type is 'nsk.share.jdi.TestClass1', + * force debugee call this method and when debugee VM stop at breakpoint, call forceEarlyReturn(). + * ClassNotLoadedException should be thrown (expect that nsk.share.jdi.TestClass1 isn't loaded in debuggee VM). + * Debugger VM force debuggee VM create instance of 'nsk.share.jdi.TestClass1' and call test method again. + * When debugee VM stop at breakpoint, call forceEarlyReturn() and check that no exception is thrown. + * Debugee checks that correct value is returned from test method after force return. + * Debugger checks that MethodExitEvent is generated after forceEarlyReturn. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002; + +import java.io.PrintStream; +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import nsk.share.Consts; +import nsk.share.jdi.ForceEarlyReturnDebugger; + +public class forceEarlyReturn002 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return forceEarlyReturn002a.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn002().runIt(argv, out); + } + + public void doTest() { + // initialize breakpoint + + ReferenceType referenceType = debuggee.classByName(ClassUsingTestClass.class.getName()); + + BreakpointRequest breakpointRequest = debuggee.makeBreakpoint(referenceType, + ClassUsingTestClass.breakpointMethodName, + ClassUsingTestClass.breakpointLine); + + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + breakpointRequest.enable(); + + pipe.println(forceEarlyReturn002a.COMMAND_CALL_OBJECT_METHOD); + + BreakpointEvent breakPointEvent = waitForBreakpoint(breakpointRequest); + + // if no breakpoint happened then test failed, stop testing + if (breakPointEvent == null) + return; + + /* + * Test can't guarantee that TestClass1 isn't loaded in the debuggee VM (it isn't loaded + * if VM implements lazy loading). Here test checks that TestClass1 isn't loaded and + * if class is really absent in the debuggee VM it is possible to check ClassNotLoadedException. + */ + boolean testClassIsLoaded = false; + + ClassLoaderReference classLoader = debuggee.classByName(forceEarlyReturn002a.class.getName()).classLoader(); + for (ReferenceType loadedClass : classLoader.visibleClasses()) { + if (loadedClass.name().equals("nsk.share.jdi.TestClass1")) { + log.display("WARNING: TestClass1 is loaded in the debuggee VM, can't test ClassNotLoadedException"); + testClassIsLoaded = true; + break; + } + } + + ThreadReference threadReference = debuggee.threadByName(forceEarlyReturn002a.mainThreadName); + + try { + if (testClassIsLoaded) { + threadReference.forceEarlyReturn(null); + } else { + try { + threadReference.forceEarlyReturn(threadReference); + setSuccess(false); + log.complain("Expected 'ClassNotLoadedException' was not thrown"); + } catch (ClassNotLoadedException e) { + log.display("Got expected ClassNotLoadedException"); + } + } + } catch (Exception e) { + unexpectedException(e); + } + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + + // after this command test class should be loaded + pipe.println(forceEarlyReturn002a.COMMAND_LOAD_CLASS_AND_CALL_OBJECT_METHOD); + + breakPointEvent = waitForBreakpoint(breakpointRequest); + + // if no breakpoint happened then test failed, stop testing + if (breakPointEvent == null) + return; + + // get value for early return + ObjectReference returnValue = (ObjectReference) referenceType.getValue(referenceType.fieldByName("expectedValue")); + + try { + // don't expect any exception + threadReference.forceEarlyReturn(returnValue); + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + testMethodExitEvent(threadReference, ClassUsingTestClass.breakpointMethodName); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002a.java new file mode 100644 index 00000000000..d06ed40322f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002a.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002; + +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/* + * Methods using TestClass1 were moved to the special class ClassUsingTestClass because of when these methods were in + * the forceEarlyReturn002a class TestClass1 were loaded together with forceEarlyReturn002a but + * this test expects that TestClass1 isn't loaded until method createExpectedValue() isn't called (see 6758252). + * + * NOTE: edit this file carefully, breakpoint line number is hardcoded + */ +class ClassUsingTestClass { + + public static final int breakpointLine = 45; + + public static final String breakpointMethodName = "testClassMethod"; + + static Object expectedValue; + + TestClass1 testClassMethod() { + System.out.println("Inside testClassMethod()"); // breakpointLine + + return null; + } + + void createExpectedValue() { + expectedValue = new TestClass1(); + } +} + +public class forceEarlyReturn002a extends AbstractJDIDebuggee { + + private ClassUsingTestClass classUsingTestClass = new ClassUsingTestClass(); + + public String[] doInit(String args[]) { + args = super.doInit(args); + + Thread.currentThread().setName(mainThreadName); + + return args; + } + + public static String mainThreadName = "MainThread"; + + // call testClassMethod() + public final static String COMMAND_CALL_OBJECT_METHOD = "callObjectMethod"; + + // load TestClass1 and call testClassMethod() + public final static String COMMAND_LOAD_CLASS_AND_CALL_OBJECT_METHOD = "testObjectMethod"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_CALL_OBJECT_METHOD)) { + classUsingTestClass.testClassMethod(); + return true; + } else if (command.equals(COMMAND_LOAD_CLASS_AND_CALL_OBJECT_METHOD)) { + classUsingTestClass.createExpectedValue(); + Object value = classUsingTestClass.testClassMethod(); + + if (ClassUsingTestClass.expectedValue != value) { + setSuccess(false); + log.complain("Unexpected result of testClassMethod: " + value); + } + + return true; + } + + return false; + } + + public static void main(String[] args) { + new forceEarlyReturn002a().doTest(args); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn003/forceEarlyReturn003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn003/forceEarlyReturn003.java new file mode 100644 index 00000000000..8ccbabec479 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn003/forceEarlyReturn003.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn003. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - attempt to call forceEarlyReturn on not suspended thread throws IncompatibleThreadStateException + * Test scenario: + * Special thread class is used in debugee VM for testing thread in different states - nsk.share.jpda.StateTestThread. + * StateTestThread sequentially changes its state in following order: + * - thread not started + * - thread is running + * - thread is sleeping + * - thread in Object.wait() + * - thread wait on java monitor + * - thread is finished + * Debugger VM calls ThreadReference.forceEarlyReturn() for all this states and expects IncompatibleThreadStateException. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003; + +import java.io.PrintStream; +import com.sun.jdi.IncompatibleThreadStateException; +import com.sun.jdi.ThreadReference; +import nsk.share.Consts; +import nsk.share.jdi.*; +import nsk.share.jpda.*; + +public class forceEarlyReturn003 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return AbstractJDIDebuggee.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn003().runIt(argv, out); + } + + public void test(ThreadReference threadReference) { + log.display("Thread state: " + threadReference.status()); + try { + // call ThreadReference.forceEarlyReturn() on non-suspended VM + // IncompatibleThreadStateException should be thrown + threadReference.forceEarlyReturn(vm.mirrorOf(0)); + + setSuccess(false); + log.complain("Expected IncompatibleThreadStateException was not thrown"); + } catch (IncompatibleThreadStateException e) { + // expected exception + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(System.out); + } + } + + public void doTest() { + pipe.println(AbstractDebuggeeTest.COMMAND_CREATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + + ThreadReference threadReference = (ThreadReference) debuggee.classByName(AbstractDebuggeeTest.stateTestThreadClassName).instances(0).get(0); + + test(threadReference); + + int state = 1; + + while (state++ < StateTestThread.stateTestThreadStates.length) { + pipe.println(AbstractDebuggeeTest.COMMAND_NEXTSTATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + + test(threadReference); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004.java new file mode 100644 index 00000000000..d2e690375de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - attempt to call com.sun.jdi.forceEarlyReturn for native Java method throws NativeMethodException + * Test scenario: + * Debugger VM force debuggee VM start test thread which execute infinite loop in native method, debugger suspend + * debuggee VM and try call forceEarlyReturn() for test thread, NativeMethodException should be thrown. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004a + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004; + +import java.io.PrintStream; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.ForceEarlyReturnDebugger; + +public class forceEarlyReturn004 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004a.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn004().runIt(argv, out); + } + + public void doTest() { + pipe.println(forceEarlyReturn004a.COMMAND_STOP_THREAD_IN_NATIVE); + + if (!isDebuggeeReady()) + return; + + // this thread execute native method + ThreadReference threadReference = debuggee.threadByName(forceEarlyReturn004a.testThreadInNativeName); + + vm.suspend(); + + try { + // expect NativeMethodException + threadReference.forceEarlyReturn(vm.mirrorOf(0)); + setSuccess(false); + log.complain("Expected 'NativeMethodException' exception was not thrown"); + } catch (NativeMethodException e) { + // expected exception + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + vm.resume(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004a.java new file mode 100644 index 00000000000..5c12fe0495d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004a.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004; + +import nsk.share.Consts; +import nsk.share.jdi.*; + +public class forceEarlyReturn004a extends AbstractJDIDebuggee { + static { + try { + System.loadLibrary("forceEarlyReturn004a"); + } catch (UnsatisfiedLinkError e) { + System.out.println("UnsatisfiedLinkError when load library 'forceEarlyReturn004a'"); + e.printStackTrace(System.out); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + } + + public static void main(String args[]) { + new forceEarlyReturn004a().doTest(args); + } + + public final static String testThreadInNativeName = "forceEarlyReturn004aTestThreadInNative"; + + public final static String COMMAND_STOP_THREAD_IN_NATIVE = "stopInNative"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_STOP_THREAD_IN_NATIVE)) { + stopThreadInNative(); + return true; + } else + + return false; + } + + private Thread testThreadInNative; + + private void stopThreadInNative() { + testThreadInNative = new Thread(new Runnable() { + public void run() { + Thread.currentThread().setName(testThreadInNativeName); + log.display("Enter native method"); + nativeMethod(forceEarlyReturn004a.this); + } + }); + + testThreadInNative.start(); + + while (!threadInNative) + Thread.yield(); + } + + public volatile boolean threadInNative; + + private static native int nativeMethod(Object object); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/libforceEarlyReturn004a.c b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/libforceEarlyReturn004a.c new file mode 100644 index 00000000000..1f97882dfac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/libforceEarlyReturn004a.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +#include "jni.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JNI_ENV_PTR + +#ifdef __cplusplus +#define JNI_ENV_ARG_2(x, y) y +#define JNI_ENV_ARG_3(x, y, z) y, z +#define JNI_ENV_ARG_4(x, y, z, a) y, z, a +#define JNI_ENV_PTR(x) x +#else +#define JNI_ENV_ARG_2(x,y) x, y +#define JNI_ENV_ARG_3(x, y, z) x, y, z +#define JNI_ENV_ARG_4(x, y, z, a) x, y, z, a +#define JNI_ENV_PTR(x) (*x) +#endif + +#endif + +int always_true = 1; + +JNIEXPORT jint JNICALL +Java_nsk_jdi_ThreadReference_forceEarlyReturn_forceEarlyReturn004_forceEarlyReturn004a_nativeMethod(JNIEnv *env, jobject classObject, jobject object) +{ + int dummy_counter = 0; + // notify another thread that thread in native method + jclass klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, object)); + jfieldID field = JNI_ENV_PTR(env)->GetFieldID(JNI_ENV_ARG_4(env, klass, "threadInNative", "Z")); + JNI_ENV_PTR(env)->SetBooleanField(JNI_ENV_ARG_4(env, object, field, 1)); + + // execute infinite loop to be sure that thread in native method + while(always_true) + { + // Need some dummy code so the optimizer does not remove this loop. + dummy_counter = dummy_counter < 1000 ? 0 : dummy_counter + 1; + } + // The optimizer can be surprisingly clever. + // Use dummy_counter so it can never be optimized out. + // This statement will always return 0. + return dummy_counter >= 0 ? 0 : 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005.java new file mode 100644 index 00000000000..7b2bfdf84c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - after force return occurred any locks acquired by calling the called method(if it is a synchronized method) + * and locks acquired by entering synchronized blocks within the called method are released in Debuggee VM. + * Also checks that this does not apply to JNI locks or java.util.concurrent.locks locks. + * - MethodExitEvent is generated as it would be in a normal return + * Test scenario: + * Special thread class 'TestThread' is used in debugee VM. This class contains following test method: + * - it is synchronized method + * - JNI lock is acquired in this method + * - java.util.concurrent.locks.ReentrantLock is acquired in this method + * - at the end the method contains synchronized block + * Debugger initialize breakpoint in test method(inside the synchronized block) and force debugee VM run test + * thread which call this method. When debuggee's test thread stop at breakpoint debugger call forceEarlyReturn() + * and resume debuggee VM. + * Debugee's test thread after force return check that locks acquired through synchronized method and synchronized block + * was freed and JNI lock and java.util.concurrent.locks.ReentrantLock still locked. + * Also debugger checks that MethodExitEvent is generated after forceEarlyReturn. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005a + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005; + +import java.io.PrintStream; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.ThreadReference; +import com.sun.jdi.event.BreakpointEvent; +import com.sun.jdi.request.BreakpointRequest; +import com.sun.jdi.request.EventRequest; +import nsk.share.Consts; +import nsk.share.jdi.ForceEarlyReturnDebugger; + +public class forceEarlyReturn005 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005a.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn005().runIt(argv, out); + } + + public void doTest() { + // init breakpont in tested method + ReferenceType referenceType = debuggee.classByName( + nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.TestThread.class.getName()); + + BreakpointRequest breakpointRequest = debuggee.makeBreakpoint(referenceType, + TestThread.BREAKPOINT_METHOD_NAME, + TestThread.BREAKPOINT_LINE); + + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + breakpointRequest.enable(); + + // start test thread + pipe.println(forceEarlyReturn005a.COMMAND_RUN_TEST_THREAD); + + BreakpointEvent event = waitForBreakpoint(breakpointRequest); + + ThreadReference threadReference = event.thread(); + + try { + // call forceEarlyReturn, all asserts should be done in debuggee + threadReference.forceEarlyReturn(vm.mirrorOf(0)); + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + testMethodExitEvent(threadReference, TestThread.BREAKPOINT_METHOD_NAME); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005a.java new file mode 100644 index 00000000000..53bf9b601a1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/forceEarlyReturn005a.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005; + +import java.util.concurrent.locks.ReentrantLock; +import nsk.share.Consts; +import nsk.share.Log; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +class TestThread extends Thread { + // lock acquired through synchronized block + private Object javaLock = new Object(); + + // lock acquired through JNI MonitorEnter + private Object nativeLock = new Object(); + + // java.util.concurrent.ReentrantLock + private ReentrantLock reentrantLock = new ReentrantLock(); + + private forceEarlyReturn005a testObject; + + public TestThread(forceEarlyReturn005a testObject) { + this.testObject = testObject; + } + + public void run() { + // forceEarlyReturn() should be called for methodForEarlyReturn() + methodForEarlyReturn(); + + // check that after forceEarlyReturn() thread released locks acquired through synchronized method and synchronized block + // and didn't release native lock and java.util.concurrent.ReentrantLock + if (holdsLock(this)) { + testObject.setSuccess(false); + testObject.log().complain("Test thread didn't release lock(synchronized method): " + this); + } + if (holdsLock(javaLock)) { + testObject.setSuccess(false); + testObject.log().complain("Test thread didn't release lock(synchronized block): " + javaLock); + } + if (!holdsLock(nativeLock)) { + testObject.setSuccess(false); + testObject.log().complain("Test thread release native lock: " + nativeLock); + } + if (!reentrantLock.isLocked()) { + testObject.setSuccess(false); + testObject.log().complain("Test thread release reentrant lock: " + reentrantLock); + } + } + + static public final int BREAKPOINT_LINE = 83; + + static public final String BREAKPOINT_METHOD_NAME = "methodForEarlyReturn"; + + public synchronized int methodForEarlyReturn() { + // acquire all locks: + + forceEarlyReturn005a.nativeJNIMonitorEnter(nativeLock); + + reentrantLock.lock(); + + synchronized (javaLock) { + testObject.log().display(getName() + " in methodForEarlyReturn"); // BREAKPOINT_LINE + } + + return 0; + } +} + +public class forceEarlyReturn005a extends AbstractJDIDebuggee { + static { + try { + System.loadLibrary("forceEarlyReturn005a"); + } catch (UnsatisfiedLinkError e) { + System.out.println("UnsatisfiedLinkError when load library 'forceEarlyReturn005a'"); + ; + e.printStackTrace(System.out); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + + try { + // load thread class to let debugger get ReferenceType for TestThread class + Class.forName("nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.TestThread"); + } catch (ClassNotFoundException e) { + System.out.println("ClassNotFoundException when load test thread class: " + e); + e.printStackTrace(System.out); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + } + + public static void main(String args[]) { + new forceEarlyReturn005a().doTest(args); + } + + static public final String testThreadName = "forceEarlyReturn004aTestThread"; + + static public final String COMMAND_RUN_TEST_THREAD = "runTestThread"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_RUN_TEST_THREAD)) { + Thread testThread = new TestThread(this); + testThread.setName(testThreadName); + testThread.start(); + + return true; + } + + return false; + } + + // native method uses this class + private static final Class jniError = nsk.share.TestJNIError.class; + + static native void nativeJNIMonitorEnter(Object object); + + // access to log for TestThread + Log log() { + return log; + } + + // access to success status for TestThread + public void setSuccess(boolean value) { + super.setSuccess(value); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/libforceEarlyReturn005a.c b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/libforceEarlyReturn005a.c new file mode 100644 index 00000000000..da7a6469f29 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn005/libforceEarlyReturn005a.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ + +#include "jni.h" +#include "nsk_tools.c" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JNI_ENV_PTR + +#ifdef __cplusplus +#define JNI_ENV_ARG_2(x, y) y +#define JNI_ENV_ARG_3(x,y,z) y, z +#define JNI_ENV_PTR(x) x +#else +#define JNI_ENV_ARG_2(x,y) x, y +#define JNI_ENV_ARG_3(x,y,z) x, y, z +#define JNI_ENV_PTR(x) (*x) +#endif + +#endif + +JNIEXPORT void JNICALL +Java_nsk_jdi_ThreadReference_forceEarlyReturn_forceEarlyReturn005_forceEarlyReturn005a_nativeJNIMonitorEnter(JNIEnv *env, jobject classObject, jobject object) +{ + jint success = JNI_ENV_PTR(env)->MonitorEnter(JNI_ENV_ARG_2(env, object)); + + if(success != 0) + { + NSK_COMPLAIN1("MonitorEnter return non-zero: %d\n", success); + + JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorEnter return non-zero")); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn006/TestDescription.java new file mode 100644 index 00000000000..b38b6ffb3a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn006/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn006. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for com.sun.jdi.forceEarlyReturn(Value value). + * The test do the same as forceEarlyReturn001, but do all checks 1000 times. + * Test scenario: + * Debuggee VM start thread(class nsk.share.jpda.ForceEarlyReturnTestThread is used) which in + * loop 1000 times sequentially call test methods with different return value type: + * - void + * - all primitive types + * - String + * - Object + * - array of java.lang.Object + * - Thread + * - ThreadGroup + * - Class object + * - ClassLoader + * Debugger VM set breakpoints in all this methods and wait while BreakpointEvent occurs. When debuggee's + * test thread stop at breakpoint debugger call forceEarlyReturn() with follows parameters: + * - try pass incompatible value to forceEarlyReturn (expect InvalidTypeException) + * - force thread return with value defined at test thread class + * Test thread in debuggee VM check that value returned from test methods equals predefined value and no + * instructions was executed in called method after force return (finally blocks are not executed too). + * Debugger checks that MethodExit is generated after forceEarlyReturn. + * Debugger performs all this check for each tested method 1000 times. + * This test execute test 'nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001' with follows parameters '-iterationsNumber 1000'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -iterationsNumber 100 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007/TestDescription.java new file mode 100644 index 00000000000..6097dd4adfa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for com.sun.jdi.forceEarlyReturn(Value value). + * The test do the same as forceEarlyReturn001, but do all checks 100 times and + * with multiple number of threads in debuggee VM. + * Test scenario: + * Debuggee VM start multiple number of threads(class nsk.share.jpda.ForceEarlyReturnTestThread is used) which + * sequentially call test methods with different return value type: + * - void + * - all primitive types + * - String + * - Object + * - array of java.lang.Object + * - Thread + * - ThreadGroup + * - Class object + * - ClassLoader + * One of this threads is intended for force early return and call test method in loop 100 times, another threads + * execute until not stoped. + * Debugger VM create breakpoint requests for all this methods and add breakpoint request's filter only for + * thread which intended for force early return. When debuggee's test thread stop at breakpoint debugger call + * forceEarlyReturn() with follows parameters: + * - try pass incompatible value to forceEarlyReturn (expect InvalidTypeException) + * - force thread return with value defined at test thread class + * Test thread in debuggee VM intended for force return check that value returned from test methods equals predefined + * value and no instructions was executed in called method after force return (finally blocks are not executed too). + * Another debuggee's threads check that values returned from test methods aren't affected by force return. + * Debugger check that MethodExitEvent is generated after forceEarlyReturn. + * Debugger perform all this check for each tested method 100 times. + * This test execute test 'nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001' with follows parameters: '-iterationsNumber 100 -totalThreadsCount 20' + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -iterationsNumber 50 + * -totalThreadsCount 3 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008.java new file mode 100644 index 00000000000..abd6cac0d8c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - after force return no extra StepEvent events are generated + * - MethodExitEvent is generated as it would be in a normal return + * Test scenario: + * Following thread class is used in debuggee VM: + * 1 class TestThread + * 2 extends Thread + * 3 { + * 4 public void run() + * 5 { + * 6 methodForEarlyReturn(); + * 7 } + * 8 + * 9 public int methodForEarlyReturn() + * 10 { + * 11 // next line for breakpoint + * 12 int i = 0; + * 13 + * 14 // dummy code, test thread shouldn't execute this code and StepEvents shouldn't be generated for this code + * 15 for(i = 0; i < 100; i++) + * 16 { + * 17 int j = 0; + * 18 j = j + i; + * 19 } + * 20 + * 21 return 0; + * 22 } + * 23 } + * Debugger set breakpoint in TestThread.methodForEarlyReturn() at line marked in this description as 12 and force debugee + * start this thread. + * When test thread stop at breakpoint debuggeer initializes StepRequest for this thread, starts event listener thread + * which counting StepEvents, call forceEarlyReturn for test thread and resume debuggee VM. + * Then, debugger waits when debuggee's test thread finish execution and check that number of received step events + * is equal 2: + * - 1st step: thread exit from methodForEarlyReturn() + * - 2ns step: thread exit from run() + * Also debugger checks that MethodExitEvent is generated after forceEarlyReturn. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008; + +import java.io.PrintStream; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.jdi.EventHandler; +import nsk.share.jdi.ForceEarlyReturnDebugger; + +public class forceEarlyReturn008 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008a.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn008().runIt(argv, out); + } + + // event listener which counts StepEvents and checks is MethodExitEvent was generated + public class EventsListener extends EventHandler.EventListener { + int totalStepEvents; + + boolean methodExitEventReceived; + + public boolean eventReceived(Event event) { + if (event instanceof StepEvent) { + log.display(++totalStepEvents + " " + ((StepEvent) event)); + + if (!(((StepEvent) event).location().method().name().equals("run"))) { + setSuccess(false); + log.complain("Event was generated for unexpected method: " + ((StepEvent) event).location().method()); + } + + vm.resume(); + + return true; + } + if (event instanceof MethodExitEvent) { + if (((MethodExitEvent) event).method().name().equals(forceEarlyReturn008a.breakpointMethod)) { + methodExitEventReceived = true; + } + + return true; + } + + return false; + } + } + + public void doTest() { + // set breakpoint in TestThread.intMethod + BreakpointRequest breakpointRequest; + + breakpointRequest = debuggee.makeBreakpoint(debuggee.classByName(forceEarlyReturn008a.TestThread.class.getName()), + forceEarlyReturn008a.breakpointMethod, forceEarlyReturn008a.breakpointLine); + + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + breakpointRequest.enable(); + + // force debuggee start TestThread + pipe.println(forceEarlyReturn008a.COMMAND_START_TEST_THREAD); + + waitForBreakpoint(breakpointRequest); + + ThreadReference threadReference = debuggee.threadByName(forceEarlyReturn008a.testThreadName); + + // initialize step request for TestThread + StepRequest stepRequest = debuggee.getEventRequestManager().createStepRequest(threadReference, StepRequest.STEP_LINE, StepRequest.STEP_INTO); + stepRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + stepRequest.addClassFilter(debuggee.classByName(forceEarlyReturn008a.TestThread.class.getName())); + stepRequest.enable(); + + EventHandler eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + // add event listener + EventsListener eventListener = new EventsListener(); + eventHandler.addListener(eventListener); + + // create MethodExitRequest for tested thread + MethodExitRequest methodExitRequest; + methodExitRequest = debuggee.getEventRequestManager().createMethodExitRequest(); + methodExitRequest.addThreadFilter(threadReference); + methodExitRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); + methodExitRequest.enable(); + + try { + threadReference.forceEarlyReturn(vm.mirrorOf(0)); + } catch (Throwable t) { + setSuccess(false); + t.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + t); + } + + vm.resume(); + + // wait READY signal for previous command 'forceEarlyReturn008a.COMMAND_START_TEST_THREAD' + if (!isDebuggeeReady()) + return; + + pipe.println(forceEarlyReturn008a.COMMAND_JOIN_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + + // expect only 2 step events: + // - exit from methodForEarlyReturn() + // - exit from run() + if (eventListener.totalStepEvents != 2) { + setSuccess(false); + log.complain("Unexpected number of step events: " + eventListener + ", only 2 is expected"); + } + + if (!eventListener.methodExitEventReceived) { + setSuccess(false); + log.complain("MethodExit event wasn't generated"); + } + + eventHandler.stopEventHandler(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008a.java new file mode 100644 index 00000000000..64851020209 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn008/forceEarlyReturn008a.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008; + +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +public class forceEarlyReturn008a extends AbstractJDIDebuggee { + public static void main(String args[]) { + new forceEarlyReturn008a().doTest(args); + } + + class TestThread extends Thread { + public void run() { + methodForEarlyReturn(); + } + + public int methodForEarlyReturn() { + int i = 0; // breakpointLine + + // dummy code, test thread shouldn't execute this code and StepEvents shouldn't be generated for this code + for (i = 0; i < 100; i++) { + int j = 0; + j = j + i; + } + + return 0; + } + } + + public static final String testThreadName = "forceEarlyReturn008a_TestThread"; + + // start TestThread + public static final String COMMAND_START_TEST_THREAD = "startTestThread"; + + // wait when TestThread finish execution + public static final String COMMAND_JOIN_TEST_THREAD = "joinTestThread"; + + public static final String breakpointMethod = "methodForEarlyReturn"; + + public static final int breakpointLine = 39; + + private TestThread testThread = new TestThread(); + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_TEST_THREAD)) { + testThread.setName(testThreadName); + testThread.start(); + + return true; + } else if (command.equals(COMMAND_JOIN_TEST_THREAD)) { + try { + testThread.join(); + } catch (InterruptedException e) { + setSuccess(false); + e.printStackTrace(log.getOutStream()); + log.complain("Unexpected exception: " + e); + } + + return true; + } + + return false; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009.java new file mode 100644 index 00000000000..6b36a9381d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - forcing return on a thread with only one frame on the stack causes the thread to exit when resumed + * - MethodExitEvent is generated as it would be in a normal return + * Test scenario: + * Debugger forces debuggee start test thread which executes infinite loop in it's run() method, so it always has + * only one frame on stack. Debugger suspends debuggee VM, call forceEarlyReturn() for test thread, resumes debuggee + * VM and checks that test thread has status ThreadReference.THREAD_STATUS_ZOMBIE(thread has completed execution) and + * checks that ThreadDeathEvent and MethodExitEvent was generated for test thread. + * Used in this test classes can be used to check forceEarlyReturn() behavior when + * thread has single frame on the stack because of methods which this thread calls were got inlined, + * in this case thread in it's run() in infinite loop calls methods which should be inlined. + * To check this case run test with parameter -inlineType , where is one of: + * - INLINE_METHOD_RETURNING_CONST, thread calls methods which return const values + * - INLINE_METHOD_ACCESSIN_INTERNAL_FIELDS, thread calls methods which access only internal fields + * - INLINE_HOT_METHOD, thread calls method which should be executed a certain number of times before it is compiled + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009; + +import java.io.PrintStream; +import java.util.ArrayList; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.jdi.ForceEarlyReturnDebugger; + +public class forceEarlyReturn009 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return forceEarlyReturn009a.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn009().runIt(argv, out); + } + + private String inlineType; + + protected String[] doInit(String args[], PrintStream out) { + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-inlineType") && (i < args.length - 1)) { + inlineType = args[i + 1]; + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + public void doTest() { + if (inlineType != null) + pipe.println(forceEarlyReturn009a.COMMAND_RUN_THREAD_WITH_SINGLE_FRAME + ":" + inlineType); + else + pipe.println(forceEarlyReturn009a.COMMAND_RUN_THREAD_WITH_SINGLE_FRAME); + + if (!isDebuggeeReady()) + return; + + // this thread has one frame on stack + ThreadReference threadReference = debuggee.threadByName(forceEarlyReturn009a.testThreadWithSingleFrameName); + + Value voidValue = createVoidValue(); + + vm.suspend(); + + try { + // thread should exit when resumed + threadReference.forceEarlyReturn(voidValue); + } catch (InvalidTypeException e) { + // this exception could be thrown if inlining was not done, in this case stop test execution + if (inlineType != null) { + log.display("WARNING: InvalidTypeException was caught, possible inlining was not done, stop test execution"); + vm.resume(); + pipe.println(forceEarlyReturn009a.COMMAND_JOIN_THREAD_WITH_SINGLE_FRAME); + isDebuggeeReady(); + return; + } else { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + } catch (Throwable e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + // create request for ThreadDeathEvent + ThreadDeathRequest threadDeathRequest; + threadDeathRequest = debuggee.getEventRequestManager().createThreadDeathRequest(); + threadDeathRequest.addThreadFilter(threadReference); + threadDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + threadDeathRequest.enable(); + + testMethodExitEvent(threadReference, "run", false); + + vm.resume(); + + EventListenerThread threadDeathEventListeningThread = new EventListenerThread(threadDeathRequest); + threadDeathEventListeningThread.start(); + threadDeathEventListeningThread.waitStartListen(); + + Event event = threadDeathEventListeningThread.getEvent(); + + if (event == null) { + setSuccess(false); + log.complain("ThreadDeath event wasn't generated"); + } + + vm.resume(); + + pipe.println(forceEarlyReturn009a.COMMAND_JOIN_THREAD_WITH_SINGLE_FRAME); + + if (!isDebuggeeReady()) + return; + + // check thread status + int threadStatus = threadReference.status(); + + if (threadStatus != ThreadReference.THREAD_STATUS_ZOMBIE) { + setSuccess(false); + log.complain("Unexpected status of test thread: " + threadStatus + ", expected is 'THREAD_STATUS_ZOMBIE'(" + + ThreadReference.THREAD_STATUS_ZOMBIE + ")"); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009a.java new file mode 100644 index 00000000000..43af687d133 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009a.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009; + +import nsk.share.Log; +import nsk.share.jdi.*; + +public class forceEarlyReturn009a extends AbstractJDIDebuggee { + + public static void main(String args[]) { + new forceEarlyReturn009a().doTest(args); + } + + public final static String testThreadWithSingleFrameName = "forceEarlyReturn009aTestThreadWithSingleFrame"; + + // command:[inlineType] + public final static String COMMAND_RUN_THREAD_WITH_SINGLE_FRAME = "runThreadWithSingleFrame"; + + public final static String COMMAND_JOIN_THREAD_WITH_SINGLE_FRAME = "joinThreadWithSingleFrame"; + + // type of inlined methods + enum InlineType { + // method return const values + INLINE_METHOD_RETURNING_CONST, + + // method access only internal fields + INLINE_METHOD_ACCESSIN_INTERNAL_FIELDS, + + // method which should be executed a certain number of times before it is compiled + INLINE_HOT_METHOD + } + + /* + * Thread can has single frame on the stack because of methods which this thread calls was inlined + * + * inlineType - type of inlined methods which test thread calls + */ + private InlineType inlineType; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.startsWith(COMMAND_RUN_THREAD_WITH_SINGLE_FRAME)) { + int index = command.indexOf(':'); + + if (index < 0) { + inlineType = null; + } else { + inlineType = InlineType.valueOf(command.substring(index + 1)); + log.display("InlineType: " + inlineType); + } + + runThreadWithSingleFrame(); + + return true; + } else if (command.equals(COMMAND_JOIN_THREAD_WITH_SINGLE_FRAME)) { + joinThreadWithSingleFrame(); + return true; + } + + return false; + } + + private ThreadWithSingleFrame threadWithSingleFrame; + + static class ThreadWithSingleFrame extends Thread { + + volatile boolean isSingleFrameThreadStarted; + + // this variable is used to stop thread with signle frame if debugger can't stop it by forceEarlyReturn + // (for example if inlining was not done) + volatile boolean isSingleFrameThreadStoped; + + private Log log; + + private InlineType inlineType; + + public ThreadWithSingleFrame(Log log, InlineType inlineType) { + this.log = log; + this.inlineType = inlineType; + + if (inlineType == InlineType.INLINE_HOT_METHOD) { + // call inlinedHotMethod1() and inlinedHotMethod2() 20000 times to be sure that this method was compiled/inlined + for (long i = 0; i < 20000; i++) { + inlinedHotMethod1(); + inlinedHotMethod2(); + } + } + + } + + private int internalField1; + + private int inlinedMethodAccessingInternalFields1() { + return internalField1++ + internalField2; + } + + private int internalField2; + + private int inlinedMethodAccessingInternalFields2() { + return internalField2++ + internalField1; + } + + private int inlinedMethodReturningInt() { + return 0; + } + + private boolean inlinedMethodReturningBoolean() { + return true; + } + + private Object inlinedMethodReturningObject() { + return null; + } + + public int publicField1; + + public int publicField2; + + public int inlinedHotMethod1() { + return publicField1++ + publicField2 * 2; + } + + public int inlinedHotMethod2() { + return publicField2++ + publicField1 * 2; + } + + public void run() { + Thread.currentThread().setName(testThreadWithSingleFrameName); + + log.display("Thread with single frame started"); + + // if inlineType was specified call methods which should be inlined + if (inlineType == InlineType.INLINE_METHOD_ACCESSIN_INTERNAL_FIELDS) { + while (!isSingleFrameThreadStoped) { + inlinedMethodAccessingInternalFields1(); + inlinedMethodAccessingInternalFields2(); + isSingleFrameThreadStarted = true; + } + } else if (inlineType == InlineType.INLINE_METHOD_RETURNING_CONST) { + while (!isSingleFrameThreadStoped) { + boolean bool = inlinedMethodReturningBoolean(); + int integer = inlinedMethodReturningInt(); + Object object = inlinedMethodReturningObject(); + isSingleFrameThreadStarted = true; + + } + } else if (inlineType == InlineType.INLINE_HOT_METHOD) { + while (!isSingleFrameThreadStoped) { + int temp = inlinedHotMethod1() + inlinedHotMethod2(); + isSingleFrameThreadStarted = true; + } + } else { + while (!isSingleFrameThreadStoped) + isSingleFrameThreadStarted = true; + } + } + } + + private void runThreadWithSingleFrame() { + threadWithSingleFrame = new ThreadWithSingleFrame(log, inlineType); + threadWithSingleFrame.start(); + + while (!threadWithSingleFrame.isSingleFrameThreadStarted) + Thread.yield(); + } + + private void joinThreadWithSingleFrame() { + try { + threadWithSingleFrame.isSingleFrameThreadStoped = true; + + threadWithSingleFrame.join(argHandler.getWaitTime() * 60000); + + if (threadWithSingleFrame.getState() != Thread.State.TERMINATED) { + setSuccess(false); + log.complain("ThreadWithSingleThread didn'f finish execution as expected"); + } + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn010/TestDescription.java new file mode 100644 index 00000000000..e7f5025b498 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn010/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn010. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - forcing return on a thread with only one frame on the stack causes the thread to exit when resumed + * - MethodExitEvent is generated as it would be in a normal return + * Test scenario: + * Test checks case when thread has single frame on the stack because of methods which this thread calls was inlined, + * Debugger VM forces debuggee VM start test thread which in it's run() method call in infinite loop + * methods which return const values, this methods should be inlined, so thread always has + * only one frame on stack. Debugger suspends debuggee VM, calls forceEarlyReturn() for test thread, resumes debuggee + * VM and checks that test thread has status ThreadReference.THREAD_STATUS_ZOMBIE(thread has completed execution) and + * checks that ThreadDeathEvent and MethodExitEvent was generated for test thread. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-XX:+Inline" + * -inlineType INLINE_METHOD_RETURNING_CONST + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn011/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn011/TestDescription.java new file mode 100644 index 00000000000..a120c3030ea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn011/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn011. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - forcing return on a thread with only one frame on the stack causes the thread to exit when resumed + * - MethodExitEvent is generated as it would be in a normal return + * Test scenario: + * Test check case when thread has single frame on the stack because of methods which this thread calls was inlined, + * Debugger VM force debuggee VM start test thread which in it's run() method call in infinite loop + * methods which access only internal fields, this methods should be inlined, so thread always has + * only one frame on stack. Debugger suspends debuggee VM, calls forceEarlyReturn() for test thread, resumes debuggee + * VM and checks that test thread has status ThreadReference.THREAD_STATUS_ZOMBIE(thread has completed execution) and + * checks that ThreadDeathEvent and MethodExitEvent was generated for test thread. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-XX:+Inline" + * -inlineType INLINE_METHOD_ACCESSIN_INTERNAL_FIELDS + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn012/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn012/TestDescription.java new file mode 100644 index 00000000000..623cc0a8e0f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn012/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn012. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - forcing return on a thread with only one frame on the stack causes the thread to exit when resumed + * - MethodExitEvent is generated as it would be in a normal return + * Test scenario: + * Test check case when thread has single frame on the stack because of methods which this thread calls was inlined, + * Debugger forces debuggee start test thread which in it's run() method calls in infinite loop + * method which should be executed a certain number of times before it is compiled and inlined, debuggee during + * initialization calls this method 20000 times, so, this methods should be inlined and thread always has + * only one frame on stack. Debugger suspends debuggee VM, calls forceEarlyReturn() for test thread, + * resumes debuggee VM and checks that test thread has status ThreadReference.THREAD_STATUS_ZOMBIE(thread has completed execution) + * and checks that ThreadDeathEvent and MethodExitEvent was generated for test thread. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn009.forceEarlyReturn009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-XX:+Inline" + * -inlineType INLINE_HOT_METHOD + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013.java new file mode 100644 index 00000000000..4786f6db748 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks that a result of the method com.sun.jdi.forceEarlyReturn(Value value) + * complies with its specification. The test checks: + * - after force return occurred any locks acquired by calling the called method(if it is a synchronized method) + * and locks acquired by entering synchronized blocks within the called method are released in Debuggee VM. + * - MethodExitEvent is generated as it would be in a normal return + * Test scenario: + * Special class 'TestThread' implementing 'Runnable' is used in debugee VM. TestThread has following 'run' method: + * - it is synchronized method + * - it contains 5 nested synchronized blocks for 5 different objects + * Debugger initializes breakpoint in TestThread's run method(inside the deepest synchronized block) and + * forces debugee VM create thread using instance of 'TestThread' and run this thread. When debuggee's test + * thread stops at breakpoint debugger calls forceEarlyReturn() and resumes debuggee VM. + * Then, debuggee creates new thread object using the same instance of 'TestThread' as for first test thread, + * starts new thread and wait when it finish execution. If first test thread released all locks + * new thread can acquire the same locks and finish, otherwise new thread will be blocked and will be unable to complete + * execution. + * Also debugger checks that MethodExitEvent is generated after forceEarlyReturn. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013; + +import java.io.PrintStream; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.jdi.ForceEarlyReturnDebugger; + +public class forceEarlyReturn013 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013a.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn013().runIt(argv, out); + } + + public void doTest() { + Value voidValue = createVoidValue(); + + // init breakpont in tested method + ReferenceType referenceType = debuggee.classByName(TestThread.class.getName()); + + BreakpointRequest breakpointRequest = debuggee.makeBreakpoint(referenceType, TestThread.BREAKPOINT_METHOD_NAME, TestThread.BREAKPOINT_LINE); + + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + breakpointRequest.enable(); + + // start test thread + pipe.println(forceEarlyReturn013a.COMMAND_RUN_TEST_THREAD); + + BreakpointEvent event = waitForBreakpoint(breakpointRequest); + + breakpointRequest.disable(); + + ThreadReference threadReference = event.thread(); + + try { + threadReference.forceEarlyReturn(voidValue); + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + testMethodExitEvent(threadReference, TestThread.BREAKPOINT_METHOD_NAME); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013a.java new file mode 100644 index 00000000000..be705b35149 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn013/forceEarlyReturn013a.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013; + +import nsk.share.Consts; +import nsk.share.Log; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +class TestThread implements Runnable { + // locks acquired through synchronized block + public static Object javaLock1 = new Object(); + + public static Object javaLock2 = new Object(); + + public static Object javaLock3 = new Object(); + + public static Object javaLock4 = new Object(); + + public static Object javaLock5 = new Object(); + + private forceEarlyReturn013a testObject; + + public TestThread(forceEarlyReturn013a testObject) { + this.testObject = testObject; + } + + public synchronized void run() { + synchronized (javaLock1) { + synchronized (javaLock2) { + synchronized (javaLock3) { // BREAKPOINT_LINE + synchronized (javaLock4) { + synchronized (javaLock5) { + testObject.log().display(Thread.currentThread().getName() + " in run"); + } + } + + } + + } + } + } + + static public final int BREAKPOINT_LINE = 51; + + static public final String BREAKPOINT_METHOD_NAME = "run"; + +} + +public class forceEarlyReturn013a extends AbstractJDIDebuggee { + static { + try { + // load thread class to let debugger get ReferenceType for TestThread class + Class.forName(TestThread.class.getName()); + } catch (ClassNotFoundException e) { + System.out.println("ClassNotFoundException when load test thread class: " + e); + e.printStackTrace(System.out); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + } + + public static void main(String args[]) { + new forceEarlyReturn013a().doTest(args); + } + + static public final String testThreadName = "forceEarlyReturn0013aTestThread"; + + static public final String COMMAND_RUN_TEST_THREAD = "runTestThread"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_RUN_TEST_THREAD)) { + TestThread testThread = new TestThread(this); + + Thread thread1 = new Thread(testThread); + thread1.setName(testThreadName); + thread1.start(); + + try { + thread1.join(argHandler.getWaitTime() * 60000); + + if (thread1.getState() != Thread.State.TERMINATED) { + setSuccess(false); + log.complain("Test thread didn't complete execution for " + argHandler.getWaitTime() * 60000 + + ", possible, forceEarlyReturn works incorrect"); + } + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + setSuccess(false); + log.complain("Unexpected exception: " + e); + } + + // start new thread, if thread1 released locks this thread can acquire the same locks and finish + Thread thread2 = new Thread(testThread); + thread2.setName("LocksCheckingThread"); + thread2.start(); + + try { + thread2.join(argHandler.getWaitTime() * 60000); + + if (thread2.getState() != Thread.State.TERMINATED) { + setSuccess(false); + log.complain("Locks checking thread didn't complete execution for " + argHandler.getWaitTime() * 60000 + + ", possible, test thread didn't release locks"); + } + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + setSuccess(false); + log.complain("Unexpected exception: " + e); + } + + return true; + } + + return false; + } + + // access to log for TestThread + Log log() { + return log; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014.java new file mode 100644 index 00000000000..a7c15616d16 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test scenario: + * Debuggee contains following test method: + * public int publicField1 = 1; + * public int publicField2 = 2; + * public int hotMethod() + * { + * return publicField1++ + publicField2 * 2; + * } + * Fisrt, debugger set breakpoint in test method, forces debuggee call this method and wait breakpoint event. + * When debuggee stop at breakpoint debugger call forceEarlyReturn() for suspended thread, checks that no + * any exceptions was thrown and resumes debuggee. Then, debugger disables breakpoint request and forces debuggee + * call test method 20000 times, after this test method should be compiled with JIT. Then, debugger enables + * breakpoint, forces debuggee call test method and when debuggee stop at breakpoint checks that behavior of + * forceEarlyReturn() didn't change. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014; + +import java.io.PrintStream; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.jdi.ForceEarlyReturnDebugger; + +public class forceEarlyReturn014 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014a.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn014().runIt(argv, out); + } + + private void testForceEarlyReturn(ReferenceType debuggeeClass, BreakpointRequest breakpointRequest) { + EventListenerThread eventListeningThread = new EventListenerThread(breakpointRequest); + eventListeningThread.start(); + eventListeningThread.waitStartListen(); + + pipe.println(forceEarlyReturn014a.COMMAND_EXECUTE_HOT_METHOD); + + BreakpointEvent event = (BreakpointEvent) eventListeningThread.getEvent(); + + Value valueToReturn = debuggeeClass.getValue(debuggeeClass.fieldByName("expectedHotMethodReturnValue")); + + try { + event.thread().forceEarlyReturn(valueToReturn); + } catch (Throwable t) { + t.printStackTrace(log.getOutStream()); + setSuccess(false); + log.complain("Unexpected exception: " + t); + } + + testMethodExitEvent(event.thread(), forceEarlyReturn014a.breakpointMethodName); + + if (!isDebuggeeReady()) + return; + } + + public void doTest() { + ReferenceType debuggeeClass = debuggee.classByName(debuggeeClassName()); + + BreakpointRequest breakpointRequest = debuggee.makeBreakpoint(debuggeeClass, + forceEarlyReturn014a.breakpointMethodName, + forceEarlyReturn014a.breakpointLine); + + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + breakpointRequest.enable(); + + // call forceEarlyReturn for hotMethod() first time + testForceEarlyReturn(debuggeeClass, breakpointRequest); + + breakpointRequest.disable(); + + // fire hotMethod(), it should be compiled + pipe.println(forceEarlyReturn014a.COMMAND_FIRE_HOT_METHOD); + + if (!isDebuggeeReady()) + return; + + breakpointRequest.enable(); + + // call forceEarlyReturn for hotMethod() second time + testForceEarlyReturn(debuggeeClass, breakpointRequest); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014a.java new file mode 100644 index 00000000000..3c26f83d482 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn014/forceEarlyReturn014a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014; + +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE +public class forceEarlyReturn014a extends AbstractJDIDebuggee { + + public static void main(String args[]) { + new forceEarlyReturn014a().doTest(args); + } + + public int publicField1 = 1; + + public int publicField2 = 2; + + public int hotMethod() { + return publicField1++ + publicField2 * 2; // breakpointLine + } + + public static final String breakpointMethodName = "hotMethod"; + + public static final int breakpointLine = 39; + + public static final int expectedHotMethodReturnValue = Integer.MAX_VALUE; + + public static final String COMMAND_EXECUTE_HOT_METHOD = "executeHotMethod"; + + public static final String COMMAND_FIRE_HOT_METHOD = "fireHotMethod"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_EXECUTE_HOT_METHOD)) { + int result = hotMethod(); + + if (result != expectedHotMethodReturnValue) { + setSuccess(false); + log.complain("Unexpected value is returned from hotMethod(): " + result); + } + + return true; + } else if (command.equals(COMMAND_FIRE_HOT_METHOD)) { + // after this loop hotMethod() should be compiled + for (int i = 0; i < 20000; i++) + hotMethod(); + + return true; + } + + return false; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015.java new file mode 100644 index 00000000000..9ce0239e917 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test provokes method 'ThreadReference.forceEarlyReturn()' throw 'InvalidStackFrameException'. + * Test scenario: + * Debugger enables ThreadStartRequest with suspend policy SUSPEND_ALL and starts thread listening JDI events. + * Then debugger forces debuggee VM to start new thread. When ThreadStartEvent is received debugger obtains + * ThreadReference through 'ThreadStartEvent.thread()' and call 'ThreadReference.forceEarlyReturn()', since + * just started thread has no frames yet 'ThreadReference.forceEarlyReturn()' should throw 'InvalidStackFrameException'. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn015.forceEarlyReturn015 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn015.forceEarlyReturn015a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn015.forceEarlyReturn015 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn015; + +import java.io.PrintStream; + +import com.sun.jdi.InvalidStackFrameException; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.jdi.ForceEarlyReturnDebugger; + +public class forceEarlyReturn015 extends ForceEarlyReturnDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public String debuggeeClassName() { + return forceEarlyReturn015a.class.getName(); + } + + public static int run(String argv[], PrintStream out) { + return new forceEarlyReturn015().runIt(argv, out); + } + + public void doTest() { + ThreadStartRequest threadStartRequest = debuggee.getEventRequestManager().createThreadStartRequest(); + threadStartRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); + threadStartRequest.enable(); + + EventListenerThread eventListener = new EventListenerThread(threadStartRequest); + eventListener.start(); + eventListener.waitStartListen(); + + pipe.println(forceEarlyReturn015a.COMMAND_START_NEW_THREAD); + + ThreadStartEvent event = (ThreadStartEvent) eventListener.getEvent(); + + try { + // just started thread has no frames and InvalidStackFrameException + // should be thrown + event.thread().forceEarlyReturn(vm.mirrorOf(0)); + + setSuccess(false); + log.complain("Expected 'InvalidStackFrameException' was not thrown"); + } catch (InvalidStackFrameException e) { + // expected exception + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + threadStartRequest.disable(); + + vm.resume(); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015a.java new file mode 100644 index 00000000000..a2e9255543d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn015/forceEarlyReturn015a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn015; + +import nsk.share.jdi.*; + +public class forceEarlyReturn015a extends AbstractJDIDebuggee { + + public static void main(String args[]) { + new forceEarlyReturn015a().doTest(args); + } + + public static final String COMMAND_START_NEW_THREAD = "startNewThread"; + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_START_NEW_THREAD)) { + Thread thread = new Thread(new Runnable() { + public void run() { + log.display("Thread exit"); + } + }); + + thread.setName("forceEarlyReturn015a_NewThread"); + thread.start(); + + return true; + } + + return false; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001.java new file mode 100644 index 00000000000..d2ca672840e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001.java @@ -0,0 +1,714 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.frame; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.frame()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since thread2 uses the same locking object in its 'run' method
    + * it is locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * (1) sets up breakpoints within thread2's two methods to be called
    + * in stack order;
    + * (2) checks up that invoking ThreadReference.frame()
    + * doesn't throw 'IncompatibleThreadStateException' when
    + * thread2 is suspended, and does throw otherwize;
    + * (3) forces first thread to leave the synchronized block
    + * in order to unlock the thread2.
    + * Then the debugger sequentially checks up that:
    + * - when the thread2 is suspended at first breakpoint within 'runt1',
    + * only invoking methods thread2.frame(0) and
    + * thread2.frame(1)
    + * doesn't throw IndexOutOfBoundsException;
    + * - when the thread2 is suspended at first breakpoint within 'runt2',
    + * only invoking methods thread2.frame(0),
    + * thread2.frame(1), and
    + * thread2.frame(2)
    + * doesn't throw IndexOutOfBoundsException;
    + * - when the thread2 is suspended at second breakpoint within 'runt1',
    + * after return from 'runt2',
    + * only invoking methods thread2.frame(0) and
    + * thread2.frame(1)
    + * whereas invoking the method with negative or larger number
    + * does throw IndexOutOfBoundsException.
    + *
    + */ + +public class frame001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/frame/frame001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new frame001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.frame.frame001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.frame.Threadframe001a"; + + //String mName = "nsk.jdi.ThreadReference.frame"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + StackFrame stackFrame = null; + StackFrame stackFrame0 = null; + StackFrame stackFrame1 = null; + StackFrame stackFrame2 = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest3 = settingBreakpoint(breakpointMethod1, bpLine3, "three"); + if (breakpRequest3 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" the check that 'thread2.frameCount()' does throw exception"); + log2(" when the thread2 is not suspended"); + try { + thread2.frame(0); + log3 ("ERROR: no IncompatibleThreadStateException"); + expresult = returnCode1; + } catch ( IncompatibleThreadStateException e1 ) { + log2(" : IncompatibleThreadStateException"); + } catch ( ObjectCollectedException e2 ) { + log3("ERROR: wrong ObjectCollectedException"); + expresult = returnCode1; + } + + log2(" suspending the thread2"); + thread2.suspend(); + + log2(" the check that 'thread2.frameCount()' doesn't throw exception"); + log2(" when the thread2 is suspended"); + try { + stackFrame0 = thread2.frame(0); + log2(" : no exception"); + } catch ( IncompatibleThreadStateException e1 ) { + log3("ERROR: wrong IncompatibleThreadStateException"); + expresult = returnCode1; + } catch ( ObjectCollectedException e2 ) { + log3("ERROR: wrong ObjectCollectedException"); + expresult = returnCode1; + } + + log2(" resuming the thread2"); + thread2.resume(); + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + log2(" testing the thread2 at breakpoints"); + for (int i3 = 0; i3 < 3; i3++) { + + log2(" : new check case i3# = " + i3); + + int iCount = 0; + + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + + log2(" checking up that thread2.frame(-1) does throw exception"); + try { + stackFrame = thread2.frame(-1); + log3 ("ERROR: no IndexOutOfBoundsException for: thread2.frame(-1)"); + expresult = returnCode1; + } catch ( IndexOutOfBoundsException e1 ) { + log2(" : IndexOutOfBoundsException for: thread2.frame(-1)"); + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: IncompatibleThreadStateException for thread2.frame(-1)"); + expresult = returnCode1; + } catch ( ObjectCollectedException e3 ) { + log3("ERROR: ObjectCollectedException for thread2.frame(-1)"); + expresult = returnCode1; + } + + log2(" checking up that thread2.frame(index) does throw exception"); + log2(" when index is equal to frameCount()"); + + try { + iCount = thread2.frameCount(); + stackFrame = thread2.frame(iCount); + log3 ("ERROR: no IndexOutOfBoundsException for: thread2.frame(iCount) : " + iCount); + expresult = returnCode1; + } catch ( IndexOutOfBoundsException e1 ) { + log2(" : IndexOutOfBoundsException for: thread2.frame(iCount) : " + iCount); + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: IncompatibleThreadStateException for thread2.frameCount()"); + expresult = returnCode1; + } catch ( ObjectCollectedException e3 ) { + log3("ERROR: ObjectCollectedException for thread2.frameCount()"); + expresult = returnCode1; + } + + log2(" checking up that thread2.frame(index) does throw exception"); + log2(" when index is greater than frameCount()"); + + try { + iCount = thread2.frameCount(); + stackFrame = thread2.frame(iCount + 1); + log3 ("ERROR: no IndexOutOfBoundsException for: thread2.frame(iCount + 1) : " + + (thread2.frameCount() +1) ); + expresult = returnCode1; + } catch ( IndexOutOfBoundsException e1 ) { + log2(" : IndexOutOfBoundsException for: thread2.frame(iCount + 1) : " + + (iCount + 1) ); + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: IncompatibleThreadStateException for thread2.frameCount()"); + expresult = returnCode1; + } catch ( ObjectCollectedException e3 ) { + log3("ERROR: ObjectCollectedException for thread2.frameCount()"); + expresult = returnCode1; + } + + + log2(" checking up that thread2.frame(0) doesn't throw exception"); + try { + stackFrame = thread2.frame(0); + log2(" : no Exception for: stackFrame = thread2.frame(0)"); + } catch ( IndexOutOfBoundsException e1 ) { + log3("ERROR: IndexOutOfBoundsException for: thread2.frame(0)"); + expresult = returnCode1; + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: wrong IncompatibleThreadStateException for thread2.frame(0)"); + expresult = returnCode1; + } catch ( ObjectCollectedException e3 ) { + log3("ERROR: ObjectCollectedException for thread2.frame(0)"); + expresult = returnCode1; + } + + + switch (i3) { + + case 0: log2(" first breakpoint in 'runt1'"); + + log2(" checking up that thread2.frame(1) doesn't throw exception"); + try { + stackFrame1 = thread2.frame(1); + log2(" : no exception for: stackFrame1 = thread2.frame(1)"); + } catch ( IndexOutOfBoundsException e1 ) { + log3("ERROR: IndexOutOfBoundsException for case 0:"); + expresult = returnCode1; + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: IncompatibleThreadStateException for case 0:"); + expresult = returnCode1; + } catch ( ObjectCollectedException e3 ) { + log3("ERROR: ObjectCollectedException for case 0:"); + expresult = returnCode1; + } + if (expresult == returnCode0) { + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + } + break; + + case 1: log2(" first breakpoint in 'runt2'"); + + log2(" checking up that thread2.frame(1) and "); + log2(" that thread2.frame(2) don't throw exceptions"); + try { + stackFrame1 = thread2.frame(1); + log2(" : no exception for: stackFrame1 = thread2.frame(1)"); + stackFrame2 = thread2.frame(2); + log2(" : no exception for: stackFrame2 = thread2.frame(2)"); + } catch ( IndexOutOfBoundsException e1 ) { + log3("ERROR: IndexOutOfBoundsException for case 1:"); + expresult = returnCode1; + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: IncompatibleThreadStateException for case 1:"); + expresult = returnCode1; + } catch ( ObjectCollectedException e3 ) { + log3("ERROR: ObjectCollectedException for case 1:"); + expresult = returnCode1; + } + if (expresult == returnCode0) { + log2(" enabling breakpRequest3"); + breakpRequest3.enable(); + } + break; + + case 2: log2(" second breakpoint in 'runt1'"); + + log2(" checking up that thread2.frame(1) doesn't throw exception"); + try { + stackFrame1 = thread2.frame(1); + log2(" : no exception for: stackFrame1 = thread2.frame(1)"); + } catch ( IndexOutOfBoundsException e1 ) { + log3("ERROR: IndexOutOfBoundsException for case 2:"); + expresult = returnCode1; + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: IncompatibleThreadStateException for case 2:"); + expresult = returnCode1; + } catch ( ObjectCollectedException e3 ) { + log3("ERROR: ObjectCollectedException for case 2:"); + expresult = returnCode1; + } + break; + } + + log2(" resuming the thread2"); + eventSet.resume(); + if (expresult != returnCode0) + break; + } + } + eventSet.resume(); // for case if error when the thread2 was suspended + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001/TestDescription.java new file mode 100644 index 00000000000..135938a78ca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/frame/frame001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.frame() + * complies with its spec: + * public StackFrame frame(int index) + * throws IncompatibleThreadStateException + * Returns the StackFrame at the given index in the thread's current call stack. + * Index 0 retrieves the current frame; + * higher indices retrieve caller frames. + * The thread must be suspended (normally through an interruption to the VM) + * to get this information, and + * it is only valid until the thread is resumed again. + * Parameters: index - the desired frame + * Returns: the requested StackFrame + * Throws: IncompatibleThreadStateException - + * if the thread is not suspended in the target VM + * java.lang.IndexOutOfBoundsException - + * if the index is greater than or equal to frameCount() or + * is negative. + * ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.frame.frame001; + * the debuggee program - nsk.jdi.ThreadReference.frame.frame001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.frame.frame001 + * nsk.jdi.ThreadReference.frame.frame001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.frame.frame001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001a.java new file mode 100644 index 00000000000..7e9951e5554 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frame/frame001a.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.frame; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the frame001 JDI test. + */ + +public class frame001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.frameCount()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until fmain thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * (1) sets up breakpoints within thread2's two methods to be called
    + * in stack order;
    + * (2) checks up that invocation ThreadReference.frameCount()
    + * doesn't throw 'IncompatibleThreadStateException' when
    + * the thread2 is suspended, and does throw otherwize;
    + * (3) fixes the number of a current frame of the thread2;
    + * (4) forces main thread to leave the synchronized block
    + * in order to unlock the thread2.
    + * Then the debugger sequentially checks up that:
    + * - when the thread2 is suspended at first breakpoint within 'runt1',
    + * new frameCount() returned value is incremented;
    + * - when the thread2 is suspended at first breakpoint within 'runt2',
    + * new frameCount() returned value is incremented again;
    + * - when the thread2 is suspended at second breakpoint within 'runt1',
    + * after return from 'runt2',
    + * new frameCount() returned value is decremented.
    + *
    + */ + +public class framecount001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/frameCount/framecount001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new framecount001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.frameCount.framecount001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.frameCount.Threadframecount001a"; + + //String mName = "nsk.jdi.ThreadReference.frameCount"; + + //====================================================== test program + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount = 0; + + StackFrame stackFrame = null; + StackFrame stackFrame0 = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest3 = settingBreakpoint(breakpointMethod1, bpLine3, "three"); + if (breakpRequest3 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" the check that 'thread2.frameCount()' does throw IncompatibleThreadStateException"); + log2(" when the thread2 is not suspended"); + try { + thread2.frameCount(); + log3 ("ERROR: no IncompatibleThreadStateException "); + expresult = returnCode1; + } catch ( IncompatibleThreadStateException e1 ) { + log2(" : IncompatibleThreadStateException ;"); + } catch ( ObjectCollectedException e2 ) { + log3("ERROR: ObjectCollectedException"); + expresult = returnCode1; + } + + log2(" suspending the thread2"); + thread2.suspend(); + + log2(" the check that 'thread2.frameCount()' doesn't throw exception"); + log2(" when the thread2 is suspended"); + try { + frameCount = thread2.frameCount(); + log2(" : no exception"); + } catch ( IncompatibleThreadStateException e1 ) { + log3("ERROR: wrong IncompatibleThreadStateException"); + expresult = returnCode1; + } catch ( ObjectCollectedException e2 ) { + log3("ERROR: wrong ObjectCollectedException"); + expresult = returnCode1; + } + + log2(" resuming the thread2"); + thread2.resume(); + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + log2(" testing the thread2 at breakpoints"); + for (int i3 = 0; i3 < 3; i3++) { + + log2(" : new check case i3# = " + i3); + + int iCount = 0; + int frameCount1 = 0; + + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting a value of current frameCount"); + try { + frameCount1 = thread2.frameCount(); + } catch ( IncompatibleThreadStateException e ) { + log3("ERROR: IncompatibleThreadStateException ???"); + expresult = returnCode1; + continue; + } + + switch (i3) { + + case 0: + log2(" the thread2 is at first breakpoint in 'runt1'"); + log2(" checking up that frameCount has been incremented"); + if (frameCount1 != (frameCount + 1) ) { + log3("ERROR: case 0: frameCount1 != (frameCount + 1) : " + frameCount1 ); + expresult = returnCode1; + } + if (expresult == returnCode0) { + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + } + break; + + case 1: + log2(" the thread2 is at first breakpoint in 'runt2'"); + log2(" checking up that frameCount has been incremented one more time"); + if (frameCount1 != (frameCount + 2) ) { + log3("ERROR: case 1: frameCount1 != (frameCount + 2) : " + frameCount1 ); + expresult = returnCode1; + } + if (expresult == returnCode0) { + log2(" enabling breakpRequest3"); + breakpRequest3.enable(); + } + break; + + case 2: + log2(" the thread2 is at second breakpoint in 'runt1'"); + log2(" checking up that frameCount has been decremented"); + if (frameCount1 != (frameCount + 1) ) { + log3("ERROR: case 2: frameCount1 != (frameCount + 1) : " + frameCount1 ); + expresult = returnCode1; + } + break; + } + + log2(" resuming the thread2"); + eventSet.resume(); + if (expresult != returnCode0) + break; + } + } + eventSet.resume(); // for case if error when the thread2 was suspended + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001/TestDescription.java new file mode 100644 index 00000000000..ca25fccccb0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/frameCount/framecount001. + * VM Testbase keywords: [quick, jpda, jdi, quarantine] + * VM Testbase comments: JDK-6530620 + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.frameCount() + * complies with its spec: + * public int frameCount() + * throws IncompatibleThreadStateException + * Returns the number of stack frames in the thread's current call stack. + * The thread must be suspended (normally through an interruption to the VM) + * to get this information, and + * it is only valid until the thread is resumed again. + * Returns: an integer frame count + * Throws: IncompatibleThreadStateException - + * if the thread is not suspended in the target VM + * ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.frameCount.framecount001; + * the debuggee program - nsk.jdi.ThreadReference.frameCount.framecount001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.frameCount.framecount001 + * nsk.jdi.ThreadReference.frameCount.framecount001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.frameCount.framecount001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001a.java new file mode 100644 index 00000000000..4b470ace728 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frameCount/framecount001a.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.frameCount; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the framecount001 JDI test. + */ + +public class framecount001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.frames()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until first thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * (1) checks up that invocation ThreadReference.frames()
    + * doesn't throw 'IncompatibleThreadStateException' when
    + * the thread2 is suspended, and does throw otherwize;
    + * (2) sets up breackpoints within thread2's two methods to be called
    + * in stack order;
    + * (3) gets from the debuggee Method objects mirroring
    + * methods 'run', 'runt1', and 'runt2';
    + * (4) forces first thread to leave the synchronized block
    + * in order to unlock the thread2.
    + * Then the debugger checks up that:
    + *
    + * - when the thread2 is suspended at entering first method, 'runt1',
    + * a frameList object returned by threadRef.frames(), has size of 2,
    + * and both StackFrame.location().method() objects in the list
    + * are equal to their mirrors formed earlier;
    + *
    + * - when the thread2 is suspended at entering second method, 'runt2',
    + * a frameList object returned by threadRef.frames(), has size of 3,
    + * and all the three StackFrame.location().method() objects
    + * in the list are equal to their mirrors formed earlier;
    + *
    + * - when the thread2 is suspended
    + * second time in first method after exiting second method,
    + * a frameList object returned by threadRef.frames(), has size of 2,
    + * and both StackFrame.location().method() objects in the list
    + * are equal to their mirrors formed earlier.
    + *
    + */ + +public class frames001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/frames/frames001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new frames001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.frames.frames001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.frames.Threadframes001a"; + + //String mName = "nsk.jdi.ThreadReference.frames"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + BreakpointRequest breakpRequest3 = null; + + String synchroMethod = "run"; + + Method runMethod0 = null; + Method runMethod1 = null; + Method runMethod2 = null; + + List frameList = null; + List frameList0 = null; + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest3 = settingBreakpoint(breakpointMethod1, bpLine3, "three"); + if (breakpRequest3 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" the check that 'thread2.frames()' does throw exception"); + log2(" when the thread2 is not suspended"); + try { + thread2.frames(); + log3 ("ERROR: no IncompatibleThreadStateException"); + expresult = returnCode1; + } catch ( IncompatibleThreadStateException e1 ) { + log2(" : IncompatibleThreadStateException"); + } catch ( ObjectCollectedException e2 ) { + log3("ERROR: wrong ObjectCollectedException"); + expresult = returnCode1; + } + + log2(" suspending the thread2"); + thread2.suspend(); + + log2(" the check that 'thread2.frames()' doesn't throw exception"); + log2(" when the thread2 is suspended"); + try { + frameList0 = thread2.frames(); + log2(" : no exception"); + } catch ( IncompatibleThreadStateException e1 ) { + log3("ERROR: wrong IncompatibleThreadStateException"); + expresult = returnCode1; + } catch ( ObjectCollectedException e2 ) { + log3("ERROR: wrong ObjectCollectedException"); + expresult = returnCode1; + } + + log2(" resuming the thread2"); + thread2.resume(); + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + runMethod0 = (Method) testedclass.methodsByName(synchroMethod).get(0); + runMethod1 = (Method) testedclass.methodsByName(breakpointMethod1).get(0); + runMethod2 = (Method) testedclass.methodsByName(breakpointMethod2).get(0); + + Method run0Method = null; + Method runt1Method = null; + Method runt2Method = null; + + StackFrame frame = null; + Location location = null; + + log2(" testing the thread2 at breakpoints"); + for (int i3 = 0; i3 < 3; i3++) { + + log2(" : new check case i3# = " + i3); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + log2(" getting new List of frames"); + try { + frameList = thread2.frames();; + } catch ( IndexOutOfBoundsException e1 ) { + log3("ERROR: IndexOutOfBoundsException"); + expresult = returnCode1; + break label1; + } catch ( IncompatibleThreadStateException e2 ) { + log3("ERROR: IncompatibleThreadStateException"); + expresult = returnCode1; + break label1; + } catch ( ObjectCollectedException e3 ) { + log3("ERROR: ObjectCollectedException"); + expresult = returnCode1; + break label1; + } + + + switch (i3) { + + case 0: + log2(" first breakpoint within 'runt1'"); + log2(" checking up the size of frameList"); + if (frameList.size() != 2) { + log3("ERROR: frameList.size() != 2 for case 0: " + frameList.size()); + expresult = returnCode1; + break; + } + + frame = (StackFrame) frameList.get(0); + location = frame.location(); + runt1Method = location.method(); + + frame = (StackFrame) frameList.get(1); + location = frame.location(); + run0Method = location.method(); + + log2(" checking up the equality of method mirrors"); + if ( !runt1Method.equals(runMethod1) ) { + log3("ERROR: !runt1Method.equals(runMethod1)"); + expresult = returnCode1;; + } + if ( !run0Method.equals(runMethod0) ) { + log3("ERROR: !run0Method.equals(runMethod0)"); + expresult = returnCode1; + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + } + break; + + case 1: + log2(" a breakpoint within 'runt2'"); + log2(" checking up the size of frameList"); + if (frameList.size() != 3) { + log3("ERROR: frameList.size() != 3 for case 1: " + frameList.size()); + expresult = returnCode1; + break; + } + + frame = (StackFrame) frameList.get(0); + location = frame.location(); + runt2Method = location.method(); + + frame = (StackFrame) frameList.get(1); + location = frame.location(); + runt1Method = location.method(); + + frame = (StackFrame) frameList.get(2); + location = frame.location(); + run0Method = location.method(); + + log2(" checking up the equality of method mirrors"); + if ( !runt2Method.equals(runMethod2) ) { + log3("ERROR: !runt2Method.equals(runMethod2)"); + expresult = returnCode1; + } + if ( !runt1Method.equals(runMethod1) ) { + log3("ERROR: !runt1Method.equals(runMethod1)"); + expresult = returnCode1; + } + if ( !run0Method.equals(runMethod0) ) { + log3("ERROR: !run0Method.equals(runMethod0)"); + expresult = returnCode1; + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest3"); + breakpRequest3.enable(); + } + break; + + case 2: + log2(" second breakpoint within 'runt1'"); + log2(" checking up the size of frameList"); + if (frameList.size() != 2) { + log3("ERROR: frameList.size() != 2 for case 2: " + frameList.size()); + expresult = returnCode1; + break; + } + + frame = (StackFrame) frameList.get(0); + location = frame.location(); + runt1Method = location.method(); + + frame = (StackFrame) frameList.get(1); + location = frame.location(); + run0Method = location.method(); + + log2(" checking up the equality of method mirrors"); + if ( !runt1Method.equals(runMethod1) ) { + log3("ERROR: !runt1Method.equals(runMethod1)"); + expresult = returnCode1; + } + if ( !run0Method.equals(runMethod0) ) { + log3("ERROR: !run0Method.equals(runMethod0)"); + expresult = returnCode1; + } + + break; + } + + log2(" resuming the thread2"); + eventSet.resume(); + if (expresult != returnCode0) + break; + } + } + eventSet.resume(); // for case if error when the thread2 was suspended + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001/TestDescription.java new file mode 100644 index 00000000000..97f6e8b6688 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/frames/frames001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.frames() + * complies with its spec: + * public java.util.List frames() + * throws IncompatibleThreadStateException + * Returns a List containing each StackFrame in the thread's current call stack. + * The thread must be suspended + * (normally through an interruption to the VM) to get this information, and + * it is only valid until the thread is resumed again. + * Returns: a List of StackFrame with the current frame first + * followed by each caller's frame. + * Throws: IncompatibleThreadStateException - + * if the thread is not suspended in the target VM + * ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.frames.frames001; + * the debuggee program - nsk.jdi.ThreadReference.frames.frames001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.frames.frames001 + * nsk.jdi.ThreadReference.frames.frames001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.frames.frames001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001a.java new file mode 100644 index 00000000000..4e5f4987a0a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001a.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.frames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the frames001 JDI test. + */ + +public class frames001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.frames_ii()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - checks up that invocation ThreadReference.frames(,)
    + * doesn't throw 'IncompatibleThreadStateException' when
    + * the thread2 is suspended, and does throw otherwize;
    + * - sets up breakpoints within thread2's 'run', 'runt1', and
    + * 'runt2' methods providing the thread2 will be suspended within
    + * 'runt1' two times, before to call 'runt2' and after return from it;
    + * - forces main thread to leave the synchronized block in order to
    + * unlock the thread2 which will be suspended at the breakpoints.
    + *
    + * At the breakpoints the debugger performs a number of checks as follows.
    + * (1) The breakpoint within 'run':
    + * - frameList = thread2.frames(0, 1); doesn't throw an exception
    + * and frameList.size() == 1
    + * - the sequence of method calls 'frame>location>method'
    + * doesn't throw exception
    + * (2) First breakpoint within 'runt1':
    + * - no exceptions thrown for: frameList = thread2.frames(0, 2);
    + * frameList = thread2.frames(1, 1);
    + * - additionally, two Method objects, mirroring gebuggee's methods
    + * 'run' and 'runt1' are created for further check
    + * (3) The breakpoint within 'runt2':
    + * - no exceptions thrown for several correct pairs of
    + * the arguments index and lenght
    + * (4) Second breakpoint within 'runt1':
    + * - another pair of Method objects, mirroring gebuggee's methods
    + * 'run' and 'runt1', is created , and
    + * first mirror objects are compared to second mirror objects.
    + *
    + */ + +public class frames_ii001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/frames_ii/frames_ii001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new frames_ii001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.frames_ii.frames_ii001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.frames_ii.Threadframes_ii001a"; + + //String mName = "nsk.jdi.ThreadReference.frames_ii"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine0 = "breakpointLineNumber0"; + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest0 = null; + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + BreakpointRequest breakpRequest3 = null; + + String synchroMethod = "run"; + + Method runMethod0 = null; + Method runMethod1 = null; + Method runMethod2 = null; + + List frameList = null; + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest0 = settingBreakpoint(synchroMethod, bpLine0, "zero"); + if (breakpRequest0 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest3 = settingBreakpoint(breakpointMethod1, bpLine3, "three"); + if (breakpRequest3 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" the check that 'thread2.frames(,)' does throw exception"); + log2(" when the thread2 is not suspended"); + try { + thread2.frames(0, 1); + log3 ("ERROR: no IncompatibleThreadStateException"); + expresult = returnCode1; + } catch ( IncompatibleThreadStateException e1 ) { + log2(" : IncompatibleThreadStateException"); + } catch ( ObjectCollectedException e2 ) { + log3("ERROR: wrong ObjectCollectedException"); + expresult = returnCode1; + } + + log2(" suspending the thread2"); + thread2.suspend(); + + log2(" the check that 'thread2.frames(,)' doesn't throw exception"); + log2(" when the thread2 is suspended"); + try { + thread2.frames(0, 1); + log2(" : no exception"); + } catch ( IncompatibleThreadStateException e1 ) { + log3("ERROR: wrong IncompatibleThreadStateException"); + expresult = returnCode1; + } catch ( ObjectCollectedException e2 ) { + log3("ERROR: wrong ObjectCollectedException"); + expresult = returnCode1; + } + + log2(" resuming the thread2"); + thread2.resume(); + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest0"); + breakpRequest0.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + runMethod0 = (Method) testedclass.methodsByName(synchroMethod).get(0); + runMethod1 = (Method) testedclass.methodsByName(breakpointMethod1).get(0); + runMethod2 = (Method) testedclass.methodsByName(breakpointMethod2).get(0); + + Method runt1Method1 = null; + Method runt1Method2 = null; + + StackFrame frame = null; + Location location = null; + + log2(" testing the thread2 at breakpoints"); + for (int i3 = 0; i3 < 4; i3++) { + + log2(" : new check case i3# = " + i3); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + + switch (i3) { + + case 0: + log2("......a breakpoint within 'run'"); + log2(" case for check: thread2.frames(0, 1);"); + frameList = null; + try { + frameList = thread2.frames(0, 1); + + log2(" checking up on: frameList.size() == 1"); + if (frameList.size() != 1) { + log3("ERROR: frameList.size() != 1 : " + frameList.size()); + expresult = returnCode1; + } + + log2(" checking up on: method calls: frame>location>method"); + try { + frame = (StackFrame) frameList.get(0); + location = frame.location(); + runMethod0 = location.method(); + } catch ( Exception e ) { + log3("ERROR: exception : " + e); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + log2(" case for check: frameList = thread2.frames(0, -1);"); + try { + frameList = thread2.frames(0, -1); + log3("ERROR: no IndexOutOfBoundsException"); + expresult = returnCode1; + } catch ( Exception e ) { + log2(" IndexOutOfBoundsException"); + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + } + break; + + + case 1: + log2("......first breakpoint within 'runt1'"); + log2(" case for check: frameList = thread2.frames(0, 2);"); + frameList = null; + try { + frameList = thread2.frames(0, 2); + + log2(" checking up on: frameList.size() == 2"); + if (frameList.size() != 2) { + log3("ERROR: frameList.size() != 2 : " + frameList.size()); + expresult = returnCode1; + } + + log2(" checking up on: method calls: frame>location>method"); + try { + frame = (StackFrame) frameList.get(0); + location = frame.location(); + runt1Method1 = location.method(); + + frame = (StackFrame) frameList.get(1); + location = frame.location(); + runMethod1 = location.method(); + } catch ( Exception e ) { + log3("ERROR: exception : " + e); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + log2(" case for check: frameList = thread2.frames(0, -1);"); + try { + frameList = thread2.frames(0, -1); + log3("ERROR: no IndexOutOfBoundsException"); + expresult = returnCode1; + } catch ( Exception e ) { + log2(" IndexOutOfBoundsException"); + } + + log2(" case for check: frameList = thread2.frames(1, 1);"); + frameList = null; + try { + frameList = thread2.frames(1, 1); + + log2(" checking up on: frameList.size() == 1"); + if (frameList.size() != 1) { + log3("ERROR: frameList.size() != 1 : " + frameList.size()); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + } + break; + + + case 2: + log2("......a breakpoint within 'runt2'"); + log2(" case for check: thread2.frames(0, 3);"); + frameList = null; + try { + frameList = thread2.frames(0, 3); + + log2(" checking up on: frameList.size() == 3"); + if (frameList.size() != 3) { + log3("ERROR: frameList.size() != 3 : " + frameList.size()); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + log2(" case for check: frameList = thread2.frames(0, -1);"); + try { + frameList = thread2.frames(0, -1); + log3("ERROR: no IndexOutOfBoundsException"); + expresult = returnCode1; + } catch ( Exception e ) { + log2(" IndexOutOfBoundsException"); + } + + log2(" case for check: frameList = thread2.frames(1, 2);"); + frameList = null; + try { + frameList = thread2.frames(1, 2); + + log2(" checking up on: frameList.size() == 2"); + if (frameList.size() != 2) { + log3("ERROR: frameList.size() != 2 : " + frameList.size()); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + log2(" case for check: frameList = thread2.frames(1, -1);"); + try { + frameList = thread2.frames(1, -1); + log3("ERROR: no IndexOutOfBoundsException"); + expresult = returnCode1; + } catch ( Exception e ) { + log2(" IndexOutOfBoundsException"); + } + + log2(" case for check: frameList = thread2.frames(2, 1);"); + frameList = null; + try { + frameList = thread2.frames(2, 1); + + log2(" checking up on: frameList.size() == 1"); + if (frameList.size() != 1) { + log3("ERROR: frameList.size() != 1 : " + frameList.size()); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + log2(" case for check: frameList = thread2.frames(2, -1);"); + try { + frameList = thread2.frames(2, -1); + log3("ERROR: no IndexOutOfBoundsException"); + expresult = returnCode1; + } catch ( Exception e ) { + log2(" IndexOutOfBoundsException"); + } + + log2(" case for check: frameList = thread2.frames(1, 1);"); + frameList = null; + try { + frameList = thread2.frames(1, 1); + + log2(" checking up on: frameList.size() == 1"); + if (frameList.size() != 1) { + log3("ERROR: frameList.size() != 1 : " + frameList.size()); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest3"); + breakpRequest3.enable(); + } + break; + + + case 3: + log2("......second breakpoint within 'runt1'"); + log2(" case for check: frameList = thread2.frames(0, 2);"); + frameList = null; + try { + frameList = thread2.frames(0, 2); + + log2(" checking up on: frameList.size() == 2"); + if (frameList.size() != 2) { + log3("ERROR: frameList.size() != 2 : " + frameList.size()); + expresult = returnCode1; + } + + log2(" checking up on: method calls: frame>location>method"); + try { + frame = (StackFrame) frameList.get(0); + location = frame.location(); + runt1Method2 = location.method(); + + frame = (StackFrame) frameList.get(1); + location = frame.location(); + runMethod2 = location.method(); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + expresult = returnCode1; + } + + log2(" case for check: frameList = thread2.frames(0, -1);"); + try { + frameList = thread2.frames(0, -1); + log3("ERROR: no IndexOutOfBoundsException"); + expresult = returnCode1; + } catch ( Exception e ) { + log2(" IndexOutOfBoundsException"); + } + + if ( !runt1Method1.equals(runt1Method2) ) { + log3("ERROR: !runt1Method1.equals(runt1Method2)"); + expresult = returnCode1; + } + if ( !runMethod1.equals(runMethod2) ) { + log3("ERROR: !runMethod1.equals(runMethod2)"); + expresult = returnCode1; + } + + break; + } + + log2(" resuming the thread2"); + eventSet.resume(); + if (expresult != returnCode0) { + testExitCode = FAILED; + break label1; + } + } + } + eventSet.resume(); // for case if error when the thread2 was suspended + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001/TestDescription.java new file mode 100644 index 00000000000..6c6f607268e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001/TestDescription.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/frames_ii/frames_ii001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.frames(int,int) + * complies with its spec: + * public java.util.List frames(int start, int length) + * throws IncompatibleThreadStateException + * Returns a List containing a range of StackFrame mirrors from + * the thread's current call stack. The thread must be suspended + * (normally through an interruption to the VM) to get this information, and + * it is only valid until the thread is resumed again. + * Parameters: start - the index of the first frame + * length - the number of frames to retrieve + * Returns: a List of StackFrame with the current frame first + * followed by each caller's frame. + * Throws: IncompatibleThreadStateException - + * if the thread is not suspended in the target VM + * IndexOutOfBoundsException - + * if the specified range is not within the range + * from 0 to frameCount() - 1. + * ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.frames_ii.frames_ii001; + * the debuggee program - nsk.jdi.ThreadReference.frames_ii.frames_ii001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * New Merlin specification contains the following conditions to throw + * IndexOutOfBoundsException: + * if the specified range is not within the range of stack frame indicies. + * That is, the exception is thrown if any of the following are true: + * start < 0 + * start >= frameCount() + * length < 0 + * (start+length) > frameCount() + * To comply with the conditions, + * all checks on "length < 0" in the test were corrected + * to catch the specified Exception. + * If the Exception is not thrown, + * the test returnes the value FAILED. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.frames_ii.frames_ii001 + * nsk.jdi.ThreadReference.frames_ii.frames_ii001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.frames_ii.frames_ii001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001a.java new file mode 100644 index 00000000000..70c5d280a47 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii001a.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.frames_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the frames_ii001 JDI test. + */ + +public class frames_ii001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.frames(int index, int lenght)
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - sets up a breakpoint within thread2's 'run' method;
    + * - forces main thread to leave the synchronized block in order to
    + * unlock the thread2 to get it suspended at the breakpoint.
    + * Then the debugger performs a number of checking calls to
    + * thread2.frames(index,lenght) with the following arguments:
    + *
    + * start < 0 (-1)
    + * lenght < -1 (-2)
    + * lenght == 0
    + * length == thread2.frameCount()
    + * lenght > thread2.frameCount()
    + *
    + */ + +public class frames_ii002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/frames_ii/frames_ii002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new frames_ii002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.frames_ii.frames_ii002a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.frames_ii.Threadframes_ii002a"; + + //String mName = "nsk.jdi.ThreadReference.frames_ii"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine0 = "breakpointLineNumber0"; + //String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest0 = null; + //BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + String synchroMethod = "run"; + + //Method runMethod0 = null; + //Method runMethod1 = null; + //Method runMethod2 = null; + + List frameList = null; + + + label0: { + + log2("getting ThreadReference objects"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up a breakpoint"); + + breakpRequest0 = settingBreakpoint(synchroMethod, bpLine0, "zero"); + if (breakpRequest0 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + + log2(" enabling breakpRequest0"); + breakpRequest0.enable(); + + log2(" making the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + log2(" checks begin"); + + log2("......case for check: start < 0 {thread2.frames(-1, 1);} IndexOutOfBoundsException expected"); + frameList = null; + try { + frameList = thread2.frames(-1, 1); + log3("ERROR: no Exception "); + log2(" frameCount == " + thread2.frameCount()); + expresult = returnCode1;; + } catch ( IndexOutOfBoundsException e1 ) { + log2(" IndexOutOfBoundsException"); + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception : " + e2); + expresult = returnCode1; + } + + log2("......case for check: lenght < -1 {thread2.frames(0, -2);} IndexOutOfBoundsException expected"); + frameList = null; + try { + frameList = thread2.frames(0, -2); + log3("ERROR: no Exception "); + log2(" frameList.size() = " + frameList.size() ); + expresult = returnCode1; + } catch ( IndexOutOfBoundsException e1 ) { + log2(" IndexOutOfBoundsException"); + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception : " + e2); + expresult = returnCode1; + } + + log2("......case for check: lenght == 0: frameList == thread2.frames(0, 0);"); + log2(" no IndexOutOfBoundsException expected"); + frameList = null; + try { + frameList = thread2.frames(0, 0); + log2(" checking up on frameList.size() == 0"); + if (frameList.size() != 0) { + log3("ERROR: frameList.size() != 0: " + frameList.size()); + expresult = returnCode1; + } + } catch ( IndexOutOfBoundsException e1 ) { + log3("ERROR: IndexOutOfBoundsException "); + expresult = returnCode1; + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception " + e2); + expresult = returnCode1; + } + + log2("......case for check: lenght == frameCount() {thread2.frames(0, thread2.frameCount());}"); + log2(" no IndexOutOfBoundsException expected"); + frameList = null; + try { + frameList = thread2.frames(0, thread2.frameCount()); + + log2(" checking up on frameList.size() == 1"); + if (frameList.size() != 1) { + log3("ERROR: frameList.size() != 1: " + frameList.size()); + expresult = returnCode1; + } + } catch ( IndexOutOfBoundsException e1 ) { + log3("ERROR: IndexOutOfBoundsException "); + expresult = returnCode1; + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception : " + e2); + expresult = returnCode1; + } + + + log2("......case for check: lenght > frameCount() {thread2.frames(0, thread2.frameCount() + 1);}"); + log2(" IndexOutOfBoundsException expected"); + frameList = null; + try { + frameList = thread2.frames(0, thread2.frameCount() + 1); + log3("ERROR: no Exception"); + log2(" frameList.size() = " + frameList.size() ); + expresult = returnCode1; + } catch ( IndexOutOfBoundsException e1 ) { + log2(" IndexOutOfBoundsException"); + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception : " + e2); + expresult = returnCode1; + } + + log2(" resuming the thread2"); + eventSet.resume(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002/TestDescription.java new file mode 100644 index 00000000000..75a5d4a6604 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/frames_ii/frames_ii002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.frames(int,int) + * complies with its spec: + * public java.util.List frames(int start, int length) + * throws IncompatibleThreadStateException + * Returns a List containing a range of StackFrame mirrors from + * the thread's current call stack. The thread must be suspended + * (normally through an interruption to the VM) to get this information, and + * it is only valid until the thread is resumed again. + * Parameters: start - the index of the first frame + * length - the number of frames to retrieve + * Returns: a List of StackFrame with the current frame first + * followed by each caller's frame. + * Throws: IncompatibleThreadStateException - + * if the thread is not suspended in the target VM + * IndexOutOfBoundsException - + * if the specified range is not within the range + * from 0 to frameCount() - 1. + * ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.frames_ii.frames_ii002; + * the debuggee program - nsk.jdi.ThreadReference.frames_ii.frames_ii002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.frames_ii.frames_ii002 + * nsk.jdi.ThreadReference.frames_ii.frames_ii002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.frames_ii.frames_ii002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002a.java new file mode 100644 index 00000000000..013ef438b8c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames_ii/frames_ii002a.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.frames_ii; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the frames_ii002 JDI test. + */ + +public class frames_ii002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.interrupt()
    + * complies with its spec.
    + *
    + * The case for testing includes two tested threads in a debuggee
    + * named thread2 and thread3, and a mirror of thread2 in a debugger.
    + * The method of testing is the comparison of "interrupted status" of
    + * both threads after the method Thread.interrupt() is applied to
    + * thread3 and its "mirroring" method ThreadReference.interrupt() is
    + * applied to the ThreadReference object mirroring thread2.
    + * The test is passed if both 'interrupted status" are equal,
    + * otherwise the test failed.
    + *
    + * The test consists of two cases as follows:
    + * - both debuggee's threads are locked up at synchronized block and
    + * are not suspended;
    + * - both debuggee's threads are locked up at synchronized block and
    + * are suspended by java.lang.Thread.suspend() method;
    + */ + +public class interrupt001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + + static final int FAILED = 2; + + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String sHeader1 = "\n==> nsk/jdi/ThreadReference/interrupt/interrupt001 ", sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main(String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new interrupt001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + + public static void log2(String message) { + logHandler.display(sHeader2 + message); + } + + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = "nsk.jdi.ThreadReference.interrupt.interrupt001a"; + + //String mName = "nsk.jdi.ThreadReference.interrupt"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static VirtualMachine vm; + + static Debugee debuggee; + + static IOPipe pipe; + + static int waitTime; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + + static final int returnCode1 = 1; + + static final int returnCode2 = 2; + + static final int returnCode3 = 3; + + static final int returnCode4 = 4; + + static final String EQUALS_INTERRUPTED = "Statuses of threads are equal: interrupted"; + + static final String ONLY_CHECKED_INTERRUPTED = "Only checked Thread2 is interrupted"; + + static final String CHECKED_NOT_INTERRUPTED = "Checked Thread2 is not interrupted"; + + static final String EQUALS_NOT_INTERRUPTED = "Statuses of threads are equal: not interrupted"; + + static final int MAX_CASE = 2; + + //------------------------------------------------------ methods + + private int runThis(String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + pipe = debuggee.createIOPipe(); + + debuggee.redirectStderr(out); + log2("interrupt002a debuggee launched"); + debuggee.resume(); + + try { + debuggee.receiveExpectedSignal("ready"); + } catch (Failure e) { + debuggee.quit(); + throw e; + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; i < MAX_CASE; i++) { + + debuggee.sendSignal("newcheck"); + try { + debuggee.receiveExpectedSignal("checkready"); + } catch (Failure e) { + debuggee.quit(); + throw e; + } + + log1("BEGIN OF CASE #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + switch (i) { + case 0: + executeCase(i, "Thread02"); + break; + + case 1: + executeCase(i, "Thread12"); + break; + } + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + debuggee.sendSignal("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + + } + + private void executeCase(int testCase, String threadName2) { + ThreadReference thread2 = debuggee.threadByName(threadName2); + if (thread2 == null) { + debuggee.quit(); + throw new TestBug("ERROR: Not found ThreadReference for name :" + threadName2); + } + + log2("......interrupting the thread2"); + thread2.interrupt(); + + log2("......instructing main thread to check up threads' interrupted statuses"); + debuggee.sendSignal("check_interruption"); + try { + debuggee.receiveExpectedSignal(EQUALS_INTERRUPTED); + log2("CASE #" + testCase + " PASSED: " + EQUALS_INTERRUPTED); + } catch (Failure e) { + log3("CASE #" + testCase + " FAILED: " + e.getMessage()); + testExitCode = returnCode1; + } + + log2(" forcing the main thread to leave synchronized block"); + debuggee.sendSignal("continue"); + try { + debuggee.receiveExpectedSignal("docontinue"); + } catch (Failure e) { + debuggee.quit(); + throw e; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001/TestDescription.java new file mode 100644 index 00000000000..53ccb6b9175 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/interrupt/interrupt001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.interrupt() + * complies with its spec: + * public void interrupt() + * Interrupts this thread. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * See Also: java.lang.Thread#interrupt() + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.interrupt.interrupt001; + * the debuggee program - nsk.jdi.ThreadReference.interrupt.interrupt001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4759463 TEST_BUG: tests against ThreadReference.interrupt() should be corrected + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.interrupt.interrupt001 + * nsk.jdi.ThreadReference.interrupt.interrupt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.interrupt.interrupt001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001a.java new file mode 100644 index 00000000000..8c8a2cb67f4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/interrupt/interrupt001a.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.interrupt; + +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the interrupt001 JDI test. + */ + +public class interrupt001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + + static final int FAILED = 2; + + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("ERROR: " + message); + } + + //====================================================== test program + + // scaffold objects + private static volatile ArgumentHandler argumentHandler = null; + + private static interrupt001aThread thread2 = null; + + private static interrupt001aThread thread3 = null; + + private static IOPipe pipe; + + //---------------------------------------------------- main method + + public static void main(String argv[]) { + + int exitCode = PASSED; + + argumentHandler = new ArgumentHandler(argv); + + for (int i = 0; i < argv.length; i++) { + if (argv[i].equals("-vbs") || argv[i].equals("-verbose")) { + verbMode = true; + break; + } + } + log1("debuggee started!"); + + // informing a debugger of readyness + pipe = argumentHandler.createDebugeeIOPipe(); + pipe.println("ready"); + + label0: for (int i = 0;; i++) { + + log1("waiting for an instruction from the debugger ..."); + String instruction = pipe.readln(); + + if (instruction.equals("quit")) { + log1("'quit' recieved"); + break; + + } else if (instruction.equals("newcheck")) { + + switch (i) { + case 0: + synchronized (interrupt001aThread.lockingObject) { + thread2 = threadStart("Thread02"); + thread3 = threadStart("Thread03"); + + pipe.println("checkready"); + if (checkInterruptStatus() == FAILED) { + exitCode = FAILED; + break label0; + } + } + log1("mainThread is out of: synchronized (lockingObject)"); + + if (waitThreadJoin(thread2) == FAILED) { + exitCode = FAILED; + } + if (waitThreadJoin(thread3) == FAILED) { + exitCode = FAILED; + } + + instruction = pipe.readln(); + if (!instruction.equals("continue")) { + logErr("Unexpected instruction #1: " + instruction); + exitCode = FAILED; + break label0; + } + pipe.println("docontinue"); + break; + + case 1: + synchronized (interrupt001aThread.lockingObject) { + thread2 = threadStart("Thread12"); + thread3 = threadStart("Thread13"); + + log1("suspending Thread2"); + thread2.suspend(); + + log1("suspending Thread3"); + thread3.suspend(); + + log1("interrupting the Thread3"); + thread3.interrupt(); + + pipe.println("checkready"); + if (checkInterruptStatus() == FAILED) { + exitCode = FAILED; + break label0; + } + } + log1("mainThread is out of: synchronized (lockingObject)"); + + log1("resuming Thread2"); + thread2.resume(); + if (waitThreadJoin(thread2) == FAILED) { + exitCode = FAILED; + } + log1("resuming Thread3"); + thread3.resume(); + if (waitThreadJoin(thread3) == FAILED) { + exitCode = FAILED; + } + + instruction = pipe.readln(); + if (!instruction.equals("continue")) { + logErr("Unexpected instruction #2: " + instruction); + exitCode = FAILED; + break label0; + } + pipe.println("docontinue"); + break; + + //------------------------------------------------- standard end section + } + + } else { + logErr("Unexpected instruction #0: " + instruction); + exitCode = FAILED; + break; + } + } + + System.exit(exitCode + PASS_BASE); + } + + private static interrupt001aThread threadStart(String threadName) { + interrupt001aThread resultThread = new interrupt001aThread(threadName); + synchronized (resultThread.waitnotifyObj) { + resultThread.start(); + try { + log1(" before: waitnotifyObj.wait();"); + while (!resultThread.ready) + resultThread.waitnotifyObj.wait(); + log1(" after: waitnotifyObj.wait();"); + } catch (InterruptedException e) { + logErr("Unexpected InterruptedException while waiting for start of : " + threadName); + } + } + return resultThread; + } + + private static int waitThreadJoin(Thread testedThread) { + long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds + + if (testedThread.isAlive()) { + // wait for thread finished in a waittime interval + log1("Waiting for tested thread " + testedThread.getName() + " finished for timeout: " + timeout); + try { + testedThread.join(timeout); + } catch (InterruptedException e) { + logErr("Interruption while waiting for tested thread " + testedThread.getName() + " finished:\n\t" + e); + return interrupt001a.FAILED; + } + } + return interrupt001a.PASSED; + } + + private static int checkInterruptStatus() { + log1("waiting for 'check_interruption'"); + String instruction = pipe.readln(); + if (!instruction.equals("check_interruption")) { + logErr("Unexpected instruction #3: " + instruction); + return FAILED; + } + + log1("interrupting thread3"); + thread3.interrupt(); + + log1("checking up statuses of (checked) Thread2 and Thread3"); + if (thread2.isInterrupted()) { + if (thread3.isInterrupted()) { + pipe.println(interrupt001.EQUALS_INTERRUPTED); + log1(" " + interrupt001.EQUALS_INTERRUPTED); + } else { + pipe.println(interrupt001.ONLY_CHECKED_INTERRUPTED); + log1(" " + interrupt001.ONLY_CHECKED_INTERRUPTED); + } + } else if (thread3.isInterrupted()) { + pipe.println(interrupt001.CHECKED_NOT_INTERRUPTED); + log1(" " + interrupt001.CHECKED_NOT_INTERRUPTED); + } else { + pipe.println(interrupt001.EQUALS_NOT_INTERRUPTED); + log1(" " + interrupt001.EQUALS_NOT_INTERRUPTED); + } + return PASSED; + } +} + +class interrupt001aThread extends Thread { + + public interrupt001aThread(String threadName) { + super(threadName); + } + + public boolean ready; + + public Object waitnotifyObj = new Object(); + + public static Object lockingObject = new Object(); + + public void run() { + log("started"); + synchronized (waitnotifyObj) { + log("entered into block: synchronized (waitnotifyObj)"); + ready = true; + waitnotifyObj.notifyAll(); + } + + synchronized (lockingObject) { + log("entered into block: synchronized (lockingObject)"); + } + log("exited from block: synchronized (lockingObject)"); + + log("exited"); + return; + } + + void log(String str) { + interrupt001a.log2(Thread.currentThread().getName() + " : " + str); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001.java new file mode 100644 index 00000000000..99491e0ac97 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001.java @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.isAtBreakpoint; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.isAtBreakpoint()
    + * complies with its spec.
    + *
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until the debuggee leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - checks up the values returned by the method isAtBreakpoint();
    + * - sets up a breakpoint within the 'runt1' method to be called.
    + * - forces main thread to leave the synchronized block
    + * in order to unlock the thread2.
    + * When the thread2 is suspended at the breakpoint,
    + * the debugger checks up the value returned by thread2.isAtBreakpoint()
    + * two times, before to resume the thread2 and after that.
    + *
    + */ + +public class isatbreakpoint001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new isatbreakpoint001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.isAtBreakpoint.isatbreakpoint001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.isAtBreakpoint.Threadisatbreakpoint001a"; + + //String mName = "nsk.jdi.ThreadReference.isAtBreakpoint"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + //StackFrame stackFrame = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + + } + + label1: { + if (expresult != returnCode0) + break label1; + + + log2(" checking up the thread2 locked but not at a breakpoint yet"); + if (!thread2.isAtBreakpoint()) { + log2(" : !thread2.isAtBreakpoint()"); + } else { + log3("ERROR: thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + // checking up for Code4 here is to allow further checks that impossible otherwise + if (expresult == returnCode4) + break label1; + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + + log2(" checking up the thread2 before to resume it"); + if (thread2.isAtBreakpoint()) { + log2(" : thread2.isAtBreakpoint()"); + } else { + log3("ERROR: !thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + + log2(" resuming the thread2"); + eventSet.resume(); + + log2(" checking up the thread2 after resuming it"); + if (!thread2.isAtBreakpoint()) { + log2(" : !thread2.isAtBreakpoint()"); + } else { + log3("ERROR: thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + + } + eventSet.resume(); // for case if error when the thread2 was suspended + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001/TestDescription.java new file mode 100644 index 00000000000..e5128862dcf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.isAtBreakpoint() + * complies with its spec: + * public boolean isAtBreakpoint() + * Determines whether the thread is suspended at a breakpoint. + * Returns: true if the thread is currently stopped at a breakpoint; + * false otherwise. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.isAtBreakpoint.isatbreakpoint001; + * the debuggee program - nsk.jdi.ThreadReference.isAtBreakpoint.isatbreakpoint001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.isAtBreakpoint.isatbreakpoint001 + * nsk.jdi.ThreadReference.isAtBreakpoint.isatbreakpoint001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.isAtBreakpoint.isatbreakpoint001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001a.java new file mode 100644 index 00000000000..f3e96f2a1fb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isAtBreakpoint/isatbreakpoint001a.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.isAtBreakpoint; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the isatbreakpoint001 JDI test. + */ + +public class isatbreakpoint001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.isSuspended()
    + * complies with its spec.
    + *
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * (1) Using the method ThreadReference.isSuspended() to get thread2's
    + * state in the following three pairs of suspend-resume methods:
    + * ThreadReference.suspend() - ThreadReference.resume()
    + * ThreadReference.suspend() - VirtualMachine.resume()
    + * VirtualMachine.suspend() - VirtualMachine.resume()
    + * (2) sets up three breakpoints for the thread2 at which it
    + * checks up thread2's state in the following pairs:
    + * suspended_at_breakpoint - EventSet.resume()
    + * suspended_at_breakpoint - ThreadReference.resume()
    + * suspended_at_breakpoint - VirtualMachine.resume()
    + *
    + */ + +public class issuspended001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/isSuspended/issuspended001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + // sHeader2 = "--> issuspended003: ", + // sHeader3 = "##> issuspended003: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new issuspended001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.isSuspended.issuspended001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.isSuspended.Threadissuspended001a"; + + //String mName = "nsk.jdi.ThreadReference.isSuspended"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (line.equals("waitnotifyerr")) { + log2(" : returned string is 'waitnotifyerr'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("getting ThreadReference objects for main thread"); + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next() for 'mainThread'"); + log3("ERROR: NO MAIN THREAD ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest3 = settingBreakpoint(breakpointMethod1, bpLine3, "three"); + if (breakpRequest3 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" checking up the thread2 before to begin testing it"); + + suspCount = thread2.suspendCount(); + log2(" suspendCount == " + suspCount); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + + if (expresult != returnCode0) + break label1; + + log2(".....testing case 1:"); + log2(".....the thread2 is suspended with thread2.suspend();"); + log2(".....and resumed with thread2.resume();"); + + thread2.suspend(); + + suspCount = thread2.suspendCount(); + log2(" checking up the thread2 after suspending it"); + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + log2(" suspendCount == " + suspCount); + + thread2.resume(); + + suspCount = thread2.suspendCount(); + log2(" checking up the thread2 after resuming it"); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + log2(" suspendCount == " + suspCount); + + + log2(".....testing case 2:"); + log2(".....the thread2 is suspended with thread2.suspend();"); + log2(".....and resumed with vm.resume();"); + + thread2.suspend(); + + suspCount = thread2.suspendCount(); + log2(" checking up the thread2 after suspending it"); + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + log2(" suspendCount == " + suspCount); + + vm.resume(); + + suspCount = thread2.suspendCount(); + log2(" checking up the thread2 after resuming the application in VM"); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + log2(" suspendCount == " + suspCount); + + + log2(".....testing case 3:"); + log2(".....the thread2 is suspended with vm.suspend();"); + log2(".....and resumed with vm.resume();"); + + vm.suspend(); + + suspCount = thread2.suspendCount(); + log2(" checking up the thread2 after suspending the application in VM"); + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + log2(" suspendCount == " + suspCount); + + vm.resume(); + + suspCount = thread2.suspendCount(); + log2(" checking up the thread2 after resuming the application in VM"); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + log2(" suspendCount == " + suspCount); + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + } + + log2(" instructing main thread to leave the synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("out_of_synchronized")) { + log3("ERROR: returned string is not 'out_of_synchronized'"); + expresult = returnCode2; + } + + label2: { + + if (expresult == returnCode0) + expresult = breakpoint(); + if (expresult != returnCode0) + break label2; + + log2(" the thread2 is at first breakpoint"); + try { + frameCount = thread2.frameCount(); + log2(" frameCount == " + frameCount); + } catch ( Exception e ) { + log3("ERROR: Exception for : frameCount = thread2.frameCount(); : " + e); + expresult = returnCode1; + } + + log2(" checking up that thread2 is suspended at first breakpoint"); + log2(" suspendCount == " + thread2.suspendCount()); + if ( thread2.isAtBreakpoint() ) { + log2(" : thread2.isAtBreakpoint()"); + } else { + log3("ERROR: !thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + } + + label3: { + + if (expresult != returnCode0) + break label3; + + log2(" instructing main thread to enter the synchronized block"); + pipe.println("enter_synchronized"); + line = pipe.readln(); + if (!line.equals("in_synchronized")) { + log3("ERROR: returned string is not 'in_synchronized'"); + expresult = returnCode4; + break label3; + } + + eventSet.resume(); + + log2(" the thread2 has left the breakpoint"); + + log2(".....testing case 4: suspended_at_breakpoint - eventSet.resume();"); + log2(".....checking up that the thread2 is not at first breakpoint"); + if ( !thread2.isAtBreakpoint() ) { + log2(" : !thread2.isAtBreakpoint()"); + } else { + log3("ERROR: thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + log2(" checking up that the thread2 is not suspended"); + log2(" suspendCount == " + thread2.suspendCount()); + if ( !thread2.isSuspended() ) { + log2(" : !thread2.isSuspended() "); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + } + + log2(" instructing main thread to leave the synchronized block"); + + pipe.println("leave_synchronized"); + line = pipe.readln(); + if (!line.equals("out_of_synchronized")) { + log3("ERROR: returned string is not 'out_of_synchronized'"); + expresult = returnCode4; + } + } + + label4: { + + if (expresult == returnCode0) + expresult = breakpoint(); + if (expresult != returnCode0) + break label4; + + log2(" the thread2 is at second breakpoint"); + try { + frameCount = thread2.frameCount(); + log2(" frameCount == " + frameCount); + } catch ( Exception e ) { + log3("ERROR: Exception for : frameCount = thread2.frameCount(); : " + e); + expresult = returnCode1; + } + + log2(" checking up that the thread2 is suspended at second breakpoint"); + log2(" suspendCount == " + thread2.suspendCount()); + if ( thread2.isAtBreakpoint() ) { + log2(" : thread2.isAtBreakpoint()"); + } else { + log3("ERROR: !thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + } + + label5: { + + if (expresult != returnCode0) + break label5; + + log2(" instructing main thread to enter the synchronized block"); + pipe.println("enter_synchronized"); + line = pipe.readln(); + if (!line.equals("in_synchronized")) { + log3("ERROR: returned string is not 'in_synchronized'"); + expresult = returnCode4; + break label5; + } + + thread2.resume(); + + log2(" the thread2 has left the breakpoint"); + + log2(".....testing case 5: suspended_at_breakpoint - thread2.resume();"); + log2(".....checking up that the thread is not at a breakpoint"); + if ( !thread2.isAtBreakpoint() ) { + log2(" : !thread2.isAtBreakpoint() "); + } else { + log3("ERROR: thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + log2(" checking up that the thread is not suspended"); + log2(" suspendCount == " + thread2.suspendCount()); + if ( !thread2.isSuspended() ) { + log2(" : !thread2.isSuspended() "); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest3"); + breakpRequest3.enable(); + } + + log2(" instructing main thread to leave the synchronized block"); + pipe.println("leave_synchronized"); + line = pipe.readln(); + if (!line.equals("out_of_synchronized")) { + log3("ERROR: returned string is not 'out_of_synchronized'"); + expresult = returnCode4; + } + } + + label6: { + + if (expresult == returnCode0) + expresult = breakpoint(); + if (expresult != returnCode0) + break label6; + + log2(" the thread2 is at third breakpoint"); + try { + frameCount = thread2.frameCount(); + log2(" frameCount == " + frameCount); + } catch ( Exception e ) { + log3("ERROR: Exception for : frameCount = thread2.frameCount(); : " + e); + expresult = returnCode1; + } + + log2(" checking up that the thread2 is suspended at third breakpoint"); + log2(" suspendCount == " + thread2.suspendCount()); + if ( thread2.isAtBreakpoint() ) { + log2(" : thread2.isAtBreakpoint()"); + } else { + log3("ERROR: !thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + + vm.resume(); + + log2(" the thread has left the breakpoint"); + + log2(".....testing case 6: suspended_at_breakpoint - vm.resume();"); + log2(".....checking up that the thread is not at a breakpoint"); + if ( !thread2.isAtBreakpoint() ) { + log2(" : !thread2.isAtBreakpoint() "); + } else { + log3("ERROR: thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + log2(" checking that the thread is not suspended"); + log2(" suspendCount == " + thread2.suspendCount()); + if ( !thread2.isSuspended() ) { + log2(" : !thread2.isSuspended() "); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + } + + if (expresult != returnCode4) { + if (line.equals("in_synchronized")) { + log2("instrucring the main thread to leave synchronized block"); + pipe.println("leave_synchronized"); + line = pipe.readln(); + } + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode2; + } + } + + log2("resuming vm; for case :"); + log2("the thread2 had been suspended at a breakpoint when the test has been aborted"); + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode2; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001/TestDescription.java new file mode 100644 index 00000000000..7eb5f003b5b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/isSuspended/issuspended001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.isSuspended() + * complies with its spec: + * public boolean isSuspended() + * Determines whether the thread has been suspended by the the debugger. + * Returns: true if the thread is currently suspended; false otherwise. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * Testing includes one level suspend()-resume() + * possible pairs of methods specified in + * ThreadReference, VirtualMachine, and EventSet interfaces, + * except for the pair VirtualMachine.suspend()-ThreadReference.resume(). + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.isSuspended.issuspended001; + * the debuggee program - nsk.jdi.ThreadReference.isSuspended.issuspended001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.isSuspended.issuspended001 + * nsk.jdi.ThreadReference.isSuspended.issuspended001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.isSuspended.issuspended001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001a.java new file mode 100644 index 00000000000..0aa5ede48f3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended001a.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.isSuspended; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the issuspended001 JDI test. + */ + +public class issuspended001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.isSuspended()
    + * complies with its spec.
    + * The test checks up the following case:
    + * - a debuggee with two threads is suspended with VirtualMachine.suspend();
    + * - then one thread is resumed with ThreadReference.resume().
    + *
    + * After being started up, the debuggee :
    + * - creates a 'lockingObject'for synchronizing threads;
    + * - enters into the synchronized block
    + * in which it creates new thread, thread2;
    + * - informs a debugger of the thread creation, and is waiting for reply.
    + * Since the thread2 uses the same lockingObject in its 'run' method
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - sets up a breakpoint for the thread2;
    + * - suspends the thread2 with ThreadReference.suspend();
    + * - instructs the main thread to leave the synchronized block,
    + * after what the thread is waiting for
    + * new instruction from the debugger again;
    + * - totally suspends the debuggee with VirtualMahcine.suspend();
    + * - resumes only the thread2 with double ThreadReference.resume()
    + * that results in thread2's suspendCount == 0;
    + * - checks up that the thread2 is suspended at the breakpoint;
    + * - resumes the debuggee with VirtualMachine.resume().
    + *
    + */ + +public class issuspended002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/isSuspended/issuspended002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new issuspended002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.isSuspended.issuspended002a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.isSuspended.Threadissuspended002a"; + + //String mName = "nsk.jdi.ThreadReference.isSuspended"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("getting ThreadReference objects for main thread"); + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next() for 'mainThread'"); + log3("ERROR: NO MAIN THREAD ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" checking up before to begin testing the thread2"); + log2(" thread2.suspendCount() == " + thread2.suspendCount()); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + log2(" mainThread.suspendCount() == " + mainThread.suspendCount()); + if (!mainThread.isSuspended()) { + log2(" : !mainThread.isSuspended()"); + } else { + log3("ERROR: mainThread.isSuspended()"); + expresult = returnCode1; + } + + + log2(" suspending thread2 with thread2.suspend();"); + thread2.suspend(); + + log2(" thread2.suspendCount() == " + thread2.suspendCount()); + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + log2(" mainThread.suspendCount() == " + mainThread.suspendCount()); + if (!mainThread.isSuspended()) { + log2(" : !mainThread.isSuspended()"); + } else { + log3("ERROR: mainThread.isSuspended() ????????!!!"); + expresult = returnCode1; + } + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + + log2(" suspending VM with vm.suspend();"); + vm.suspend(); + + suspCount = thread2.suspendCount(); + if (suspCount != 2) { + log3("ERROR: thread2.suspendCount() != 2 : " + suspCount); + expresult = returnCode1; + } else { + log2(" thread2.suspendCount() == 2"); + } + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + suspCount = mainThread.suspendCount(); + if (suspCount != 1) { + log3("ERROR: mainThread.suspendCount() != 1 : " + suspCount); + expresult = returnCode1; + } else { + log2(" mainThread.suspendCount() == 1"); + } + if (mainThread.isSuspended()) { + log2(" : mainThread.isSuspended()"); + } else { + log3("ERROR: !mainThread.isSuspended()"); + expresult = returnCode1; + } + + + log2(" double resuming thread2 with thread2.resume();"); + + thread2.resume(); + + suspCount = thread2.suspendCount(); + log2(" thread2.suspendCount() == " + suspCount); + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + + if (expresult == returnCode0) { + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + } + + thread2.resume(); + + suspCount = thread2.suspendCount(); + log2(" thread2.suspendCount() == " + suspCount); + if ( thread2.isAtBreakpoint() ) { + log2(" : thread2.isAtBreakpoint() before call to breakpoint()"); + } else { + log2(" : !thread2.isAtBreakpoint() before call to breakpoint()"); + } + } + + label2: { + + if (expresult == returnCode0) + expresult = breakpoint(); + if (expresult != returnCode0) + break label2; + + log2(" the thread2 is at the breakpoint"); + + log2(" the check that the thread2 is suspended at the breakpoint"); + log2(" thread2.suspendCount() == " + thread2.suspendCount()); + if ( thread2.isAtBreakpoint() ) { + log2(" : thread2.isAtBreakpoint()"); + } else { + log3("ERROR: !thread2.isAtBreakpoint()"); + expresult = returnCode1; + } + if ( thread2.isSuspended() ) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + } + if (mainThread.isSuspended()) { + log2(" : mainThread.isSuspended()"); + } else { + log3("ERROR: !mainThread.isSuspended()"); + expresult = returnCode1; + } + } + + log2(" resuming both second and main thread"); + + vm.resume(); + + if (expresult == returnCode0) { + if ( !thread2.isSuspended() ) { + log2(" : !thread2.isSuspended()"); + } else { + log3("ERROR: thread2.isSuspended()"); + expresult = returnCode1; + } + if ( !mainThread.isSuspended() ) { + log2(" : !mainThread.isSuspended()"); + } else { + log3("ERROR: mainThread.isSuspended()"); + expresult = returnCode2; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002/TestDescription.java new file mode 100644 index 00000000000..109340eea6c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/isSuspended/issuspended002. + * VM Testbase keywords: [jpda, jdi, quarantine] + * VM Testbase comments: JDK-4903717 + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.isSuspended() + * complies with its spec: + * public boolean isSuspended() + * Determines whether the thread has been suspended by the the debugger. + * Returns: true if the thread is currently suspended; false otherwise. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * Testing includes only the pair + * VirtualMachine.suspend()-ThreadReference.resume(). + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.isSuspended.issuspended002; + * the debuggee program - nsk.jdi.ThreadReference.isSuspended.issuspended002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.isSuspended.issuspended002 + * nsk.jdi.ThreadReference.isSuspended.issuspended002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.isSuspended.issuspended002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002a.java new file mode 100644 index 00000000000..25a50e0ed2a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002a.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.isSuspended; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the issuspended002 JDI test. + */ + +public class issuspended002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.isSuspended()
    + * complies with its spec.
    + * The test checks up the following case:
    + * - a debuggee with second thread, thread2 started up and
    + * locked up at a synchronized block,
    + * - suspending the thread2 with ThreadReference.suspend()
    + * after making debugger's EventQueue empty. + *
    + * After being started up, the debuggee :
    + * - creates a 'lockingObject'for synchronizing threads;
    + * - enters into the synchronized block
    + * in which it creates the thread2;
    + * - informs a debugger of the thread2 creation,
    + * and is waiting for an instruction.
    + * Since thread2 uses the same lockingObject in its 'run' method
    + * it is locked up until the debuggee leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - removes all events from an EventQueue object;
    + * - suspends thread2 with ThreadReference.suspend();
    + * - checks up that the thread2 is suspended.
    + *
    + */ + +public class issuspended003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/isSuspended/issuspended003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + // sHeader2 = "--> issuspended003: ", + // sHeader3 = "##> issuspended003: "; + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new issuspended003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.isSuspended.issuspended003a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.isSuspended.Threadissuspended003a"; + + //String mName = "nsk.jdi.ThreadReference.isSuspended"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("getting ThreadReference objects for main thread"); + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next() for 'mainThread'"); + log3("ERROR: NO MAIN THREAD ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" checking up before to make eventQueue empty"); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + log2(" suspendCount == " + thread2.suspendCount()); + } else { + log3("ERROR: thread2.isSuspended()"); + log2(" suspendCount == " + thread2.suspendCount()); + expresult = returnCode1; + } + + if (expresult == returnCode0) + expresult = removingEvents(); + + if (expresult != returnCode0) + log2("aborting the check because of unsuccessful removing events"); + else { + log2(" checking up after getting eventQueue empty"); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + log2(" thread2.suspendCount() == " + thread2.suspendCount()); + } else { + log3("ERROR: thread2.isSuspended()"); + log2(" thread2.suspendCount() == " + thread2.suspendCount()); + expresult = returnCode1; + } + } + + if (expresult == returnCode0) { + + log2(" suspending thread2 with threadRef.suspend();"); + thread2.suspend(); + + suspCount = thread2.suspendCount(); + boolean isSusp = thread2.isSuspended(); + + log2(" thread2.suspendCount() == " + suspCount); + if (suspCount != returnCode0) + if (isSusp) { + log2(" : thread2.isSuspended() and suspendCount() != 0"); + } else { + log3("ERROR: !thread2.isSuspended() but suspendCount() != 0"); + expresult = returnCode1; + } + else + if (isSusp) { + log2("ERROR: thread2.isSuspended() but suspendCount() == 0"); + } else { + log3("ERROR: !thread2.isSuspended() and suspendCount() == 0"); + expresult = returnCode1; + } + + thread2.resume(); + + } + + log2(" disabling breakpRequest1"); + breakpRequest1.disable(); + + pipe.println("continue"); + + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It set up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ +/* + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode2; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +*/ + /* + * private int removingEvents() + * + * It removs all events from EventQueue. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "1000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove(1000)" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int removingEvents() { + + int returnCode = returnCode0; + + log2(" removing events from EventQueue"); + + for (;;) { + + log2(" new: eventSet = eventQueue.remove(1000);"); + try { + eventSet = eventQueue.remove(1000); + } catch ( Exception e ) { + log3("ERROR: eventSet = eventQueue.remove() : " + e); + returnCode = returnCode2; + break; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break ll; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // end of switch + } catch ( ClassCastException e ) { + } + } // ll: + } // for (; ev.hasNext(); ) + + } else { + log2(" : eventSet == null: EventQueue is empty"); + break; + } + } + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003/TestDescription.java new file mode 100644 index 00000000000..73886d1cb0b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/isSuspended/issuspended003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.isSuspended() + * complies with its spec: + * public boolean isSuspended() + * Determines whether the thread has been suspended by the the debugger. + * Returns: true if the thread is currently suspended; false otherwise. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test checks up the following particular case: + * - a debuggee with second thread started up and + * locked up at a synchronized block, + * - suspending the thread with ThreadReference.suspend() after + * making debugger's EventQueue empty. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.isSuspended.issuspended003; + * the debuggee program - nsk.jdi.ThreadReference.isSuspended.issuspended003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.isSuspended.issuspended003 + * nsk.jdi.ThreadReference.isSuspended.issuspended003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.isSuspended.issuspended003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003a.java new file mode 100644 index 00000000000..4a60d3769b1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended003a.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.isSuspended; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the issuspended003 JDI test. + */ + +public class issuspended003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.isSuspended()
    + * complies with its spec.
    + * The test checks up the following case:
    + * - a debuggee with second thread started up and
    + * locked up at a synchronized block,
    + * - suspending the thread with VirualMachine.suspend() after
    + * after removing all events from debugger's EventQueue.
    + *
    + * After being started up, the debuggee :
    + * - creates a 'lockingObject'for synchronizing threads;
    + * - enters into the synchronized block
    + * in which it creates new thread, thread2;
    + * - informs a debugger of the thread2 creation,
    + * and is waiting for instruction.
    + * Since new thread uses the same lockingObject in its 'run' method
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - removes all events from its EventQueue object;
    + * - suspends whole the debuggee with VirualMachine.suspend();
    + * - checks up that the thread2 is suspended.
    + *
    + */ + +public class issuspended004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/isSuspended/issuspended004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new issuspended004().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.isSuspended.issuspended004a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.isSuspended.Threadissuspended004a"; + + //String mName = "nsk.jdi.ThreadReference.isSuspended"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended004a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + int frameCount; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("getting ThreadReference objects for main thread"); + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next() for 'mainThread'"); + log3("ERROR: NO MAIN THREAD ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" checking up before to make eventQueue empty"); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + log2(" suspendCount == " + thread2.suspendCount()); + } else { + log3("ERROR: thread2.isSuspended()"); + log2(" suspendCount == " + thread2.suspendCount()); + expresult = returnCode1; + } + + if (expresult == returnCode0) + expresult = removingEvents(); + + if (expresult != returnCode0) + log2("aborting the check because of unsuccessful removing events"); + else { + log2(" checking up after getting eventQueue empty"); + if (!thread2.isSuspended()) { + log2(" : !thread2.isSuspended()"); + log2(" thread2.suspendCount() == " + thread2.suspendCount()); + } else { + log3("ERROR: thread2.isSuspended()"); + log2(" thread2.suspendCount() == " + thread2.suspendCount()); + expresult = returnCode1; + } + } + + if (expresult == returnCode0) { + + log2(" suspending thread2 with threadRef.suspend();"); + vm.suspend(); + + suspCount = thread2.suspendCount(); + boolean isSusp = thread2.isSuspended(); + + log2(" thread2.suspendCount() == " + suspCount); + if (suspCount != returnCode0) + if (isSusp) { + log2(" : thread2.isSuspended() and suspendCount() != 0"); + } else { + log3("ERROR: !thread2.isSuspended() but suspendCount() != 0"); + expresult = returnCode1; + } + else + if (isSusp) { + log2("ERROR: thread2.isSuspended() but suspendCount() == 0"); + } else { + log3("ERROR: !thread2.isSuspended() and suspendCount() == 0"); + expresult = returnCode1; + } + } + + log2(" disabling breakpRequest1"); + breakpRequest1.disable(); + + pipe.println("continue"); + + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It set up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ +/* + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode2; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +*/ + + /* + * private int removingEvents() + * + * It removs all events from EventQueue. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "1000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove(1000)" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int removingEvents() { + + int returnCode = 0; + + log2(" removing events from EventQueue"); + + for (;;) { + + log2(" new: eventSet = eventQueue.remove(1000);"); + try { + eventSet = eventQueue.remove(1000); + } catch ( Exception e ) { + log3("ERROR: eventSet = eventQueue.remove() : " + e); + returnCode = 1; + break; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != 0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break ll; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = 1; + break ll; + } // end of switch + } catch ( ClassCastException e ) { + } + } // ll: + } // for (; ev.hasNext(); ) { + + } else { + log2(" : eventSet == null: EventQueue is empty"); + break; + } + } + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004/TestDescription.java new file mode 100644 index 00000000000..20b3ebc7f60 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/isSuspended/issuspended004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.isSuspended() + * complies with its spec: + * public boolean isSuspended() + * Determines whether the thread has been suspended by the the debugger. + * Returns: true if the thread is currently suspended; false otherwise. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test checks up the following particular case: + * - a debuggee with second thread started up and + * locked up at a synchronized block, + * - suspending the thread with VirtualMachine.suspend() after + * making debugger's EventQueue empty. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.isSuspended.issuspended004; + * the debuggee program - nsk.jdi.ThreadReference.isSuspended.issuspended004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.isSuspended.issuspended004 + * nsk.jdi.ThreadReference.isSuspended.issuspended004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.isSuspended.issuspended004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004a.java new file mode 100644 index 00000000000..465ec33e080 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended004a.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.isSuspended; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the issuspended004 JDI test. + */ + +public class issuspended004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.name()
    + * complies with its spec.
    + *
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until the debuggee leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger checks up that the string returned by thread2.name()
    + * is equal to one used to create it.
    + *
    + */ + +public class name001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/name/name001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new name001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.name.name001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.name.Threadname001a"; + + //String mName = "nsk.jdi.ThreadReference.name"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + //String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + //String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + //BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" checking up thread2's name; expected: 'testedThread'"); + String name = thread2.name(); + if (!name.equals(threadName)) { + log3("ERROR: !name.equals(threadName) :" + name); + expresult = returnCode1; + } + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ +/* + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } +*/ + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ +/* + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +*/ +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001/TestDescription.java new file mode 100644 index 00000000000..035434148db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/name/name001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.name() + * complies with its spec: + * public java.lang.String name() + * Returns the name of this thread. + * Returns: the string containing the thread name. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.name.name001; + * the debuggee program - nsk.jdi.ThreadReference.name.name001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.name.name001 + * nsk.jdi.ThreadReference.name.name001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001a.java new file mode 100644 index 00000000000..0c110d46034 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/name/name001a.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the name001 JDI test. + */ + +public class name001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.ownedMonitors()
    + * complies with its spec.
    + */ + +public class ownedmonitors001 { + + //----------------------------------------------------- template section + private static final int PASSED = 0; + private static final int FAILED = 2; + private static final int PASS_BASE = 95; + + private static final String sHeader1 = "==> debugger: "; + private static final String sHeader2 = "--> debugger: "; + private static final String sHeader3 = "ERROR ##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new ownedmonitors001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private static final String debuggeeName = "nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors001a"; +// private static String testedClassName = "nsk.jdi.ThreadReference.ownedMonitors.Threadownedmonitors001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + private static ArgumentHandler argsHandler; + private static int waitTime; + private static VirtualMachine vm = null; + private static int testExitCode = PASSED; + private static ReferenceType debuggeeRef; + + private static Vector expMonitors = new Vector(); + private static Vector monitorNames = new Vector(); + private static final int monitorCount = 2; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + IOPipe pipe = debuggee.createIOPipe(); + + debuggee.redirectStderr(logHandler, "debuggee.err > "); + log2("debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("Signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + log2("TESTING BEGINS"); + label1: { + debuggeeRef = debuggee.classByName(debuggeeName); + if (debuggeeRef == null) { + log3("Cannot find ReferenceType for " + debuggeeName); + testExitCode = FAILED; + break label1; + } + + for (int i2 = 0; ; i2++) { + if (!vm.canGetOwnedMonitorInfo()) { + log1("TEST ABORTED: vm.canGetOwnedMonitorInfo() returned false."); + break label1; + } + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2("'checkend' received"); + break ; + } else if (!line.equals("checkready")) { + log3("Returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log2("Case #" + i2); + switch (i2) { + + case 0 : + checkMonitors("main", 0); + break; + + case 1 : + checkMonitors("main", monitorCount); + break; + + default: + log3("default:"); + break label1; + } + + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("Returned string is not 'docontinue'"); + testExitCode = FAILED; + break label1; + } + + } // for + } + log2("TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log1("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log1("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + private void checkMonitors(String threadName, int expSize) { + log1("Getting ThreadReference for " + threadName + " thread"); + ThreadReference checkedThread = null; + Iterator itr = vm.allThreads().listIterator(); + while (itr.hasNext()) { + ThreadReference thread = (ThreadReference) itr.next(); + if (thread.name().equals(threadName)) { + checkedThread = thread; + } + } + if (checkedThread == null) { + log3("Cannot find " + threadName + "thread in the debuggee"); + testExitCode = FAILED; + return; + } + log1("Checking up throwing an IncompatibleThreadStateException for not suspended thread"); + List monitors; + try { + monitors = checkedThread.ownedMonitors(); + log3("No IncompatibleThreadStateException for " + threadName + " thread"); + testExitCode = FAILED; + } catch ( IncompatibleThreadStateException e1 ) { + log1("Expected IncompatibleThreadStateException is thrown"); + } + + log1("Suspending the " + threadName + " thread"); + checkedThread.suspend(); + + log1("Checking up ownedMonitors() list"); + try { + monitors = checkedThread.ownedMonitors(); + int monSize = monitors.size(); + if (monSize < expSize) { + log3("Got unexpected ownedMonitors() list size : " + monSize + + "\n\t expected minimal value : " + expSize); + testExitCode = FAILED; + } else { + log1("Got size of ownedMonitors() list: " + monSize); + + if (expSize > 0) { + log1("Checking up items in ownedMonitors() list"); + getMonitorRefs(); + itr = expMonitors.iterator(); + while (itr.hasNext()) { + ObjectReference mon = (ObjectReference) itr.next(); + if (monitors.contains(mon)) { + log1("Found expected item in ownedMonitors() list : " + mon); + } else { + log3("Did not found expected item in ownedMonitors() list : " + mon); + testExitCode = FAILED; + } + } + } + } + } catch ( IncompatibleThreadStateException e1 ) { + log3("Unexpected IncompatibleThreadStateException is thrown"); + testExitCode = FAILED; + } + log1("Resuming the main thread"); + checkedThread.resume(); + } + + private void getMonitorRefs () { + monitorNames.add("waitnotifyObj"); + monitorNames.add("lockingObject"); + Iterator itr = monitorNames.iterator(); + while (itr.hasNext()) { + try { + String monName = (String)itr.next(); + Field field = debuggeeRef.fieldByName(monName); + Value value = debuggeeRef.getValue(field); + expMonitors.add((ObjectReference)value); + } catch (Exception e) { + log3("Unexpected excption while getting ObjectReference for monitors"); + testExitCode = FAILED; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001/TestDescription.java new file mode 100644 index 00000000000..05a30e39277 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up that an implementation of the method + * com.sun.jdi.ThreadReference.ownedMonitors() conforms with its spec. + * The test checks an assertion: + * Returns a List containing an ObjectReference for each monitor owned by the thread. + * A monitor is owned by a thread if it has been entered (via the synchronized statement + * or entry into a synchronized method) and has not been relinquished through Object.wait(long). + * There are two test cases: + * - for a thread with no owned monitors, + * - for a thread with owned monitors, entered via the synchronized statement. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors001; + * the debuggee program - nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors001a. + * Communication details between the debugger and the debuggee: + * Using nsk.jdi.share classes, the debugger connects to debuggee program running + * on another VM and establishes a communication pipe with the debuggee. The pipe + * is used in bi-directional way by sending and receiving special commands between + * the debugger and debuggee for synchronization + * In case of error the test produces the exit code 97 and a corresponding error + * message(s). Otherwise, the test is passed and produces the exit code 95 and + * no message. + * COMMENTS: + * 4769563 NSK ownedmonitors001 sends an incorrect test-sync mesg + * 5009132 nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001 monitor count fail + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors001 + * nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001a.java new file mode 100644 index 00000000000..4a9a34803cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors001a.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.ownedMonitors; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the ownedmonitors001 JDI test. + */ + +public class ownedmonitors001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println(Thread.currentThread().getName() + " : " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + public static Object waitnotifyObj = new Object(); + public static Object lockingObject = new Object(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.ThreadReference.ownedMonitors()
    + * properly throws UnsupportedOperationException, if + * the target VM does not support the retrieval of the monitor for + * which a thread is currently waiting (determinated by calling + * VirtualMachine.canGetOwnedMonitorInfo()), and vise versa + * otherwise. + */ +public class ownedmonitors002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors002t"; + + // name of debuggee's main thread + static final String DEBUGGEE_THRNAME = "ownedmonitors002tThr"; + + static final int ATTEMPTS = 5; + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private int tot_res = Consts.TEST_PASSED; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedmonitors002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "ownedmonitors002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + int num = 0; + thrRef.suspend(); + while(!thrRef.isSuspended()) { + num++; + if (num > ATTEMPTS) { + log.complain("TEST FAILURE: Unable to suspend debuggee thread after " + + ATTEMPTS + " attempts"); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + log.display("Waiting for debuggee thread suspension ..."); + try { + Thread.currentThread().sleep(DELAY); + } catch(InterruptedException ie) { + ie.printStackTrace(); + log.complain("TEST FAILURE: caught: " + ie); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + } + +// Check the tested assersion + try { + List mons = thrRef.ownedMonitors(); + if (vm.canGetOwnedMonitorInfo()) { + log.display("CHECK PASSED: got a List of monitors owned by the thread," + + "\n\tand VirtualMachine.canGetOwnedMonitorInfo() shows, that the target VM" + + "supports the retrieval of the monitors owned by a thread as well: " + + vm.canGetOwnedMonitorInfo()); + } else { + log.complain("TEST FAILED: got a List of monitors owned by the thread," + + "\n\thowever, VirtualMachine.canGetOwnedMonitorInfo() shows, that the target VM" + + "\n\tdoes not support the retrieval of the monitors owned by a thread: " + + vm.canGetOwnedMonitorInfo()); + tot_res = Consts.TEST_FAILED; + } + } catch(UnsupportedOperationException une) { + if (vm.canGetOwnedMonitorInfo()) { + une.printStackTrace(); + log.complain("TEST FAILED: caught exception: " + une + + "\n\tHowever, VirtualMachine.canGetOwnedMonitorInfo() shows, that the target VM" + + "\n\tsupports the retrieval of the monitors owned by a thread: " + + vm.canGetOwnedMonitorInfo()); + tot_res = Consts.TEST_FAILED; + } else { + log.display("CHECK PASSED: caught expected exception: " + une + + "\n\tand VirtualMachine.canGetOwnedMonitorInfo() shows, that the target VM" + + "\n\tdoes not support the retrieval of the monitors owned by a thread as well: " + + vm.canGetOwnedMonitorInfo()); + } + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILED: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } + +// Finish the test + return quitDebuggee(); + } + + private int quitDebuggee() { + log.display("Resuming debuggee ..."); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002/TestDescription.java new file mode 100644 index 00000000000..420b3cbd8ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method: + * com.sun.jdi.ThreadReference.ownedMonitors() + * properly throws UnsupportedOperationException, if the target VM + * does not support the retrieval of the monitor for which a thread + * is currently waiting (determinated by calling + * VirtualMachine.canGetOwnedMonitorInfo()), and vise versa otherwise. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors002 + * nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors002t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitors.ownedmonitors002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002t.java new file mode 100644 index 00000000000..f55817ddcdc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitors/ownedmonitors002t.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadReference.ownedMonitors; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is a debuggee class. + */ +public class ownedmonitors002t { + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(ownedmonitors002.DEBUGGEE_THRNAME); + + // Now the debuggee is ready for testing + pipe.println(ownedmonitors002.COMMAND_READY); + + String cmd = pipe.readln(); + if (!cmd.equals(ownedmonitors002.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.java new file mode 100644 index 00000000000..14b5e5d844a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames001. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test check that attempt to call com.sun.jdi.ThreadReference.ownedMonitorsAndFrames on non-suspended VM + * throws IncompatibleThreadStateException. + * Special thread class is used in debugee VM for testing thread in different states - nsk.share.jpda.StateTestThread. + * StateTestThread sequentially changes its state in following order: + * - thread not started + * - thread is running + * - thread is sleeping + * - thread in Object.wait() + * - thread wait on java monitor + * - thread is finished + * Debugger VM calls ThreadReference.ownedMonitorsAndFrames() for all this states and expects IncompatibleThreadStateException. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001; + +import java.io.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.*; +import nsk.share.jpda.StateTestThread; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class ownedMonitorsAndFrames001 extends TestDebuggerType2 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsAndFrames001().runIt(argv, out); + } + + protected String debuggeeClassName() { + return AbstractJDIDebuggee.class.getName(); + } + + private void test(ThreadReference threadReference) { + log.display("Thread state: " + threadReference.status()); + try { + // call ThreadReference.ownedMonitorsAndFrames() on non-suspended VM + // IncompatibleThreadStateException should be thrown + threadReference.ownedMonitorsAndFrames(); + setSuccess(false); + log.complain("Expected IncompatibleThreadStateException was not thrown"); + } catch (IncompatibleThreadStateException e) { + // expected exception + } catch (Throwable e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void doTest() { + // create StateTestThread + pipe.println(AbstractDebuggeeTest.COMMAND_CREATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + + // StateTestThread in state 0 + ThreadReference threadReference = (ThreadReference) findSingleObjectReference(AbstractDebuggeeTest.stateTestThreadClassName); + + test(threadReference); + + // change StateTestThread's state from 1 to stateTestThreadStates.length + int state = 1; + + while (state++ < StateTestThread.stateTestThreadStates.length) { + pipe.println(AbstractDebuggeeTest.COMMAND_NEXTSTATE_STATETESTTHREAD); + + if (!isDebuggeeReady()) + return; + + test(threadReference); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.java new file mode 100644 index 00000000000..771186bfcf3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Debuggee VM create thread which acquires several monitors in following ways: + * - entering synchronized method + * - entering synchronized method for thread object itself + * - entering synchronized static method + * - entering synchronized method for thread class itself + * - entering synchronized block on non-static object + * - entering synchronized block on non-static on thread object itself + * - entering synchronized block on static object + * - entering synchronized block on static thread object itself + * Information about all monitors acquired by test thread is stored in debuggee VM and can be obtained through + * special field in debuggee class: OwnedMonitorsDebuggee.monitorsInfo. + * When debuggee's test threads acquires all monitors debugger reads information about acquired monitors + * from 'OwnedMonitorsDebuggee.monitorsInfo' and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects. + * Debugger VM forces test thread in debuggee VM sequentially free all monitors(exit from synchronized blocks/methods), + * update debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo object. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002; + +import java.util.*; +import java.io.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.OwnedMonitorsDebuggee; +import nsk.share.jdi.OwnedMonitorsDebugger; +import nsk.share.locks.LockingThread; + +public class ownedMonitorsAndFrames002 extends OwnedMonitorsDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsAndFrames002().runIt(argv, out); + } + + public void doTest() { + initDefaultBreakpoint(); + + try { + // create command: + + List locksTypes = new ArrayList(); + + // debuggee thread acquires monitors in different ways + locksTypes.add(LockingThread.SYNCHRONIZED_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_BLOCK_STATIC_THREAD_OBJECT); + locksTypes.add(LockingThread.SYNCHRONIZED_THREAD_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_STATIC_THREAD_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_THIS_BLOCK); + locksTypes.add(LockingThread.SYNCHRONIZED_OBJECT_BLOCK); + locksTypes.add(LockingThread.SYNCHRONIZED_BLOCK_STATIC_OBJECT); + locksTypes.add(LockingThread.SYNCHRONIZED_STATIC_METHOD); + locksTypes.add(LockingThread.FRAME_WITHOUT_LOCK); + + String threadName = "ownedMonitorsAndFrames002_LockingThread1"; + String command = OwnedMonitorsDebuggee.COMMAND_CREATE_LOCKING_THREAD + ":" + threadName; + + for (String lockType : locksTypes) { + command += ":" + lockType; + } + + pipe.println(command); + + if (!isDebuggeeReady()) + return; + + ThreadReference threadReference = debuggee.threadByName(threadName); + + // debuggee save information about acquired monitors in array 'OwnedMonitorsDebuggee.monitorsInfo' + pipe.println(OwnedMonitorsDebuggee.COMMAND_UPDATE_MONITOR_INFO + ":" + threadName); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + // check that ThreadReference.ownedMonitorsAndFrames() returns correct data + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + + // force debuggee thread sequentially exit from synchronized blocks/methods and check results of ownedMonitorsAndFrames() + for (int i = 0; i < locksTypes.size(); i++) { + pipe.println(OwnedMonitorsDebuggee.COMMAND_EXIT_SINGLE_FRAME + ":" + threadName); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + // check that ThreadReference.ownedMonitorsAndFrames() returns correct data + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } + } finally { + removeDefaultBreakpoint(); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames003/ownedMonitorsAndFrames003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames003/ownedMonitorsAndFrames003.java new file mode 100644 index 00000000000..34a0d815676 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames003/ownedMonitorsAndFrames003.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames003. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Debuggee VM create thread which acquires 5 different monitors in following ways: + * - entering synchronized method + * - entering synchronized method for thread object itself + * - entering synchronized static method + * - entering synchronized method for thread class itself + * - entering synchronized block on non-static object + * Information about all monitors acquired by test thread is stored in debuggee VM and can be obtained through + * special field in debuggee class: OwnedMonitorsDebuggee.monitorsInfo. + * Debugger VM reads information about acquired monitors from 'OwnedMonitorsDebuggee.monitorsInfo' + * and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames returns correct list of MonitorInfo objects. + * Debugger VM forces test thread in debuggee VM sequentially free monitors through Object.wait(), + * updates debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects. + * Debugger VM forces test thread in debuggee VM free all monitors(exit from all synchronized objects/blocks), + * update debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames003.ownedMonitorsAndFrames003 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames003.ownedMonitorsAndFrames003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames003; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.jdi.OwnedMonitorsDebuggee; +import nsk.share.jdi.OwnedMonitorsDebugger; +import nsk.share.locks.LockingThread; +import nsk.share.Consts; + +public class ownedMonitorsAndFrames003 extends OwnedMonitorsDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsAndFrames003().runIt(argv, out); + } + + public void doTest() { + initDefaultBreakpoint(); + + try { + List locksTypes = new ArrayList(); + + // LockingThread acquire 5 different monitors + locksTypes.add(LockingThread.SYNCHRONIZED_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_THREAD_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_STATIC_THREAD_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_OBJECT_BLOCK); + locksTypes.add(LockingThread.SYNCHRONIZED_STATIC_METHOD); + + String threadName = "ownedMonitorsAndFrames003_LockingThread1"; + String command = OwnedMonitorsDebuggee.COMMAND_CREATE_LOCKING_THREAD + ":" + threadName; + + for (String lockType : locksTypes) { + command += ":" + lockType; + } + + pipe.println(command); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + ThreadReference threadReference = debuggee.threadByName(threadName); + + // check ownedMonitorsAndFrames() first time when all monitors are locked + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + + // For all LockingThread's monitors: + // - force thread relinquish monitors through Object.wait(), + // - check results of ownedMonitorsAndFrames() + // - force debuggee thread acquire relinquished monitor + // - check results of ownedMonitorsAndFrames() + for (int i = 0; i < locksTypes.size(); i++) { + pipe.println(OwnedMonitorsDebuggee.COMMAND_RELINQUISH_MONITOR + ":" + threadName + ":" + i); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + + pipe.println(OwnedMonitorsDebuggee.COMMAND_ACQUIRE_RELINQUISHED_MONITOR + ":" + threadName); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } + + // LockingThread should free all monitors + + pipe.println(OwnedMonitorsDebuggee.COMMAND_STOP_LOCKING_THREAD + ":" + threadName); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } finally { + removeDefaultBreakpoint(); + } + + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004.java new file mode 100644 index 00000000000..8d08d81cd9b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Debuggee VM creates 3 deadlocks(package nsk.share.locks is used) with usage of following resources: + * - first thread acquires java lock through synchronized block, + * second thread acquires java lock through synchronized method + * - first thread acquires java lock through synchronized blocks, + * second thread acquires lock through JNI function 'MonitorEnter' + * - first thread acquires java locks through synchronized blocks, + * second thread acquires lock through JNI function 'MonitorEnter', + * third thread acquires java locks through synchronized method + * Information about all monitors acquired by test threads is stored in debuggee VM and can be obtained through + * special field in debuggee class: OwnedMonitorsDebuggee.monitorsInfo. + * Debugger VM reads information about acquired monitors from 'OwnedMonitorsDebuggee.monitorsInfo' + * and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames returns correct list of MonitorInfo objects. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004a + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import nsk.share.Consts; +import nsk.share.jdi.OwnedMonitorsDebugger; +import nsk.share.locks.LockType; + +public class ownedMonitorsAndFrames004 extends OwnedMonitorsDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsAndFrames004().runIt(argv, out); + } + + public String debuggeeClassName() { + return "nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004a"; + } + + private void checkDeadlockedThread(String... threadNames) { + // expectedData.get(i) - data for thread with name 'threadNames[i]' + List expectedData = getDebugMonitorsInfo(); + + if (expectedData.size() != threadNames.length) { + log.complain("TEST BUG: debugee didn't provide correct debug information"); + setSuccess(false); + return; + } + + List expectedDataForSingleThread = new ArrayList(); + + for (int i = 0; i < threadNames.length; i++) { + expectedDataForSingleThread.clear(); + expectedDataForSingleThread.add(expectedData.get(i)); + + try { + compare(debuggee.threadByName(threadNames[i]).ownedMonitorsAndFrames(), expectedDataForSingleThread); + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + } + } + + private int threadNameIndex; + + private void createAndCheckDeadlock(LockType... lockTypes) { + String threadNames[] = new String[lockTypes.length]; + + for (int i = 0; i < threadNames.length; i++) + threadNames[i] = "ownedMonitorsAndFrames004_DeadlockedThread" + (++threadNameIndex); + + String command = ownedMonitorsAndFrames004a.COMMAND_CREATE_DEADLOCK; + + for (int i = 0; i < threadNames.length; i++) { + command += ":" + threadNames[i] + ":" + lockTypes[i]; + } + + pipe.println(command); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + // check result of ownedMonitorsAndFrames() for deadlocked threads + checkDeadlockedThread(threadNames); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } + + public void doTest() { + initDefaultBreakpoint(); + + try { + createAndCheckDeadlock(LockType.SYNCHRONIZED_BLOCK, LockType.SYNCHRONIZED_METHOD); + + createAndCheckDeadlock(LockType.SYNCHRONIZED_BLOCK, LockType.JNI_LOCK); + + createAndCheckDeadlock(LockType.SYNCHRONIZED_BLOCK, LockType.JNI_LOCK, LockType.SYNCHRONIZED_METHOD); + } finally { + removeDefaultBreakpoint(); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004a.java new file mode 100644 index 00000000000..424de3673bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004a.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004; + +import java.io.*; +import java.util.ArrayList; +import nsk.share.TestBug; +import nsk.share.jdi.OwnedMonitorsDebuggee; +import nsk.share.locks.*; + +public class ownedMonitorsAndFrames004a extends OwnedMonitorsDebuggee { + // command:threadName:lock_type:threadName:lock_type + public static final String COMMAND_CREATE_DEADLOCK = "createDeadlock"; + + public static void main(String args[]) { + ownedMonitorsAndFrames004a debuggee = new ownedMonitorsAndFrames004a(); + debuggee.init(args); + debuggee.doTest(); + } + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + try { + if (command.startsWith(COMMAND_CREATE_DEADLOCK)) { + StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command)); + tokenizer.whitespaceChars(':', ':'); + tokenizer.wordChars('_', '_'); + tokenizer.wordChars(' ', ' '); + tokenizer.wordChars('$', '$'); + + tokenizer.nextToken(); + + ArrayList deadlockedThreadsNames = new ArrayList(); + ArrayList deadlockedThreadsLocksTypes = new ArrayList(); + + int nextToken = tokenizer.nextToken(); + + while (nextToken != StreamTokenizer.TT_EOF) { + String threadName = tokenizer.sval; + + if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) + throw new TestBug("Invalid command format: " + command); + + LockType lockType; + + try { + lockType = LockType.valueOf(tokenizer.sval); + } catch (IllegalArgumentException e) { + throw new TestBug("Invalid command format: " + command + ", invalid lock type: " + tokenizer.sval); + } + + deadlockedThreadsNames.add(threadName); + deadlockedThreadsLocksTypes.add(lockType); + + nextToken = tokenizer.nextToken(); + } + + if (deadlockedThreadsNames.size() < 2) + throw new TestBug("Invalid command format: " + command + ", at least 2 thread are required for deadlock"); + + createDeadlock(deadlockedThreadsNames, deadlockedThreadsLocksTypes); + + return true; + } + } catch (IOException e) { + throw new TestBug("Invalid command format: " + command); + } + + return false; + } + + private DeadlockedThread deadlockedThreads[]; + + public void createDeadlock(ArrayList deadlockedThreadsNames, ArrayList deadlockedThreadsLocksTypes) { + deadlockedThreads = DeadlockMaker.createDeadlockedThreads(deadlockedThreadsLocksTypes); + + monitorsInfo = new LockingThread.DebugMonitorInfo[deadlockedThreadsNames.size()]; + + // fill 'monitorsInfo' array with debug data using knowledge about nsk.share.locks.DeadlockedThread + for (int i = 0; i < deadlockedThreadsNames.size(); i++) { + deadlockedThreads[i].setName(deadlockedThreadsNames.get(i)); + + Object monitor = deadlockedThreads[i].getLocker().getLock(); + + int stackDepth = 2; + boolean isJNILock = false; + + if (deadlockedThreads[i].getLocker() instanceof JNIMonitorLocker) { + stackDepth = -1; + isJNILock = true; + } + + monitorsInfo[i] = new LockingThread.DebugMonitorInfo(monitor, stackDepth, deadlockedThreads[i], isJNILock); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames005/ownedMonitorsAndFrames005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames005/ownedMonitorsAndFrames005.java new file mode 100644 index 00000000000..3dffabd4c21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames005/ownedMonitorsAndFrames005.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames005. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test checks that acquired JNI monitors are handled correctly. Possibility to return JNI monitors related to 6415394, + * it should be fixed in Mustang b85. If JNI monitors should be returned by ThreadReference.ownedMonitorsAndFrames() + * run test with parameter '-expectJNIMonitors', otherwise run test without parameters. + * Test scenario: + * Debuggee VM creates thread which acquires several JNI monitors(through JNI MonitorEnter()) and + * one monitor through entering synchronized block. + * Information about all monitors acquired by test thread is stored in debuggee VM and can be obtained through + * special field in debuggee class: OwnedMonitorsDebuggee.monitorsInfo. + * Debugger VM reads information about acquired monitors from 'OwnedMonitorsDebuggee.monitorsInfo' + * and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames returns correct list of MonitorInfo objects. + * Debugger VM forces test thread in debuggee VM sequentially free all monitors(exit from synchronized block or + * call JNI MonitorExit()), updates debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames005.ownedMonitorsAndFrames005 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames005.ownedMonitorsAndFrames005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -expectJNIMonitors + */ + +package nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames005; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.OwnedMonitorsDebuggee; +import nsk.share.jdi.OwnedMonitorsDebugger; +import nsk.share.locks.LockingThread; + +public class ownedMonitorsAndFrames005 extends OwnedMonitorsDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsAndFrames005().runIt(argv, out); + } + + // expect or not JNI monitors in results of ownedMonitorsAndFrames() + private boolean expectJNIMonitors; + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equalsIgnoreCase("-expectJNIMonitors")) { + expectJNIMonitors = true; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + public String debuggeeClassName() { + if (expectJNIMonitors) + return super.debuggeeClassName() + " -returnJNIMonitors"; + else + return super.debuggeeClassName(); + } + + public void doTest() { + initDefaultBreakpoint(); + + try { + List locksTypes = new ArrayList(); + + // LockingThead should acquire 3 JNI monitors and 1 non-JNI monitor + locksTypes.add(LockingThread.SYNCHRONIZED_OBJECT_BLOCK); + locksTypes.add(LockingThread.JNI_MONITOR_ENTER); + locksTypes.add(LockingThread.JNI_MONITOR_ENTER); + locksTypes.add(LockingThread.JNI_MONITOR_ENTER); + + String threadName = "ownedMonitorsAndFrames005_LockingThread1"; + String command = OwnedMonitorsDebuggee.COMMAND_CREATE_LOCKING_THREAD + ":" + threadName; + + for (String lockType : locksTypes) { + command += ":" + lockType; + } + + pipe.println(command); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + ThreadReference threadReference = debuggee.threadByName(threadName); + + // check ownedMonitorsAndFrames() first time + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + + // force debuggee thread sequentially exit from synchronized blocks, free JNI monitors and check results of ownedMonitorsAndFrames() + for (int i = 0; i < locksTypes.size(); i++) { + pipe.println(OwnedMonitorsDebuggee.COMMAND_EXIT_SINGLE_FRAME + ":" + threadName); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } + } finally { + removeDefaultBreakpoint(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames006/ownedMonitorsAndFrames006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames006/ownedMonitorsAndFrames006.java new file mode 100644 index 00000000000..764e2f3c284 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames006/ownedMonitorsAndFrames006.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames006. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test do the same things as 'ownedMonitorsAndFrames002', but run in debuggee VM several test threads. + * Default test threads count is 10, but number of test threads can be changed through test parameter '-testThreadsCount' + * (for example "-testThreadsCount 100"). + * Debuggee VM creates a number of threads which acquire several monitors in following ways: + * - entering synchronized method + * - entering synchronized method for thread object itself + * - entering synchronized block on non-static object + * - entering synchronized block on thread object itself + * Information about all monitors acquired by test threads is stored in debuggee VM and can be obtained through + * special field in debuggee class: OwnedMonitorsDebuggee.monitorsInfo. + * Debugger VM reads information about acquired monitors from 'OwnedMonitorsDebuggee.monitorsInfo' + * and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames returns correct list of MonitorInfo objects for + * all test threads. + * Debugger VM forces test all threads in debuggee VM sequentially free all monitors(exit from synchronized blocks/methods), + * updates debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects for all test threads. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames006.ownedMonitorsAndFrames006 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames006.ownedMonitorsAndFrames006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames006; + +import java.io.PrintStream; +import nsk.share.Consts; +import nsk.share.jdi.OwnedMonitorsDebugger; +import nsk.share.jdi.OwnedMonitorsDebuggee; +import nsk.share.locks.*; +import java.util.*; + +import com.sun.jdi.ThreadReference; + +public class ownedMonitorsAndFrames006 extends OwnedMonitorsDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsAndFrames006().runIt(argv, out); + } + + private int testThreadsCount = 10; + + // initialize test and remove unsupported by nsk.share.jdi.ArgumentHandler arguments + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testThreadsCount") && (i < args.length - 1)) { + testThreadsCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + public void doTest() { + initDefaultBreakpoint(); + + try { + String testThreadsNames[] = new String[testThreadsCount]; + + for (int i = 0; i < testThreadsNames.length; i++) + testThreadsNames[i] = "ownedMonitorsAndFrames006_LockingThread" + (i + 1); + + List locksTypes = new ArrayList(); + + locksTypes.add(LockingThread.SYNCHRONIZED_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_THREAD_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_THIS_BLOCK); + locksTypes.add(LockingThread.SYNCHRONIZED_OBJECT_BLOCK); + locksTypes.add(LockingThread.FRAME_WITHOUT_LOCK); + + for (int i = 0; i < testThreadsNames.length; i++) { + String threadName = testThreadsNames[i]; + String command = OwnedMonitorsDebuggee.COMMAND_CREATE_LOCKING_THREAD + ":" + threadName; + + for (String lockType : locksTypes) { + command += ":" + lockType; + } + + pipe.println(command); + + if (!isDebuggeeReady()) + return; + } + + // check ownedMonitorsAndFrames() for all threads + for (int i = 0; i < testThreadsNames.length; i++) { + ThreadReference threadReference = debuggee.threadByName(testThreadsNames[i]); + + pipe.println(OwnedMonitorsDebuggee.COMMAND_UPDATE_MONITOR_INFO + ":" + testThreadsNames[i]); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } + + // force debuggee threads sequentially exit from synchronized blocks/methods and check results of ownedMonitorsAndFrames() + for (int i = 0; i < locksTypes.size(); i++) { + // all threads free single lock + for (int j = 0; j < testThreadsNames.length; j++) { + pipe.println(OwnedMonitorsDebuggee.COMMAND_EXIT_SINGLE_FRAME + ":" + testThreadsNames[j]); + + if (!isDebuggeeReady()) + return; + } + + // check results of ownedMonitorsAndFrames() + for (int j = 0; j < testThreadsNames.length; j++) { + ThreadReference threadReference = debuggee.threadByName(testThreadsNames[j]); + + pipe.println(OwnedMonitorsDebuggee.COMMAND_UPDATE_MONITOR_INFO + ":" + testThreadsNames[j]); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } + } + } finally { + removeDefaultBreakpoint(); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames007/ownedMonitorsAndFrames007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames007/ownedMonitorsAndFrames007.java new file mode 100644 index 00000000000..3978374132a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames007/ownedMonitorsAndFrames007.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames007. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test do the same things as 'ownedMonitorsAndFrames003', but run in debuggee VM several test threads. + * Default test threads count is 10, but number of test threads can be changed through test parameter '-testThreadsCount' + * (for example "-testThreadsCount 100"). + * Debuggee VM creates a number of threads and each test thread acquires 4 different monitors in following ways: + * - entering synchronized method + * - entering synchronized block on non-static object + * - entering synchronized method for thread object itself + * - entering synchronized block on static object + * Information about all monitors acquired by test thread is stored in debuggee VM and can be obtained through + * special field in debuggee class: OwnedMonitorsDebuggee.monitorsInfo. + * Debugger VM reads information about acquired monitors from 'OwnedMonitorsDebuggee.monitorsInfo' + * and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames returns correct list of MonitorInfo objects, this + * check is performed for all test threads. + * Debugger VM forces all test threads in debuggee VM sequentially free monitors through Object.wait(), + * updates debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects for all test threads. + * Debugger VM forces all test threads in debuggee VM free all monitors(exit from all synchronized objects/blocks), + * updates debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects for all test threads. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007.ownedMonitorsAndFrames007 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007.ownedMonitorsAndFrames007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007; + +import java.io.PrintStream; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.OwnedMonitorsDebuggee; +import nsk.share.jdi.OwnedMonitorsDebugger; +import nsk.share.locks.LockingThread; + +public class ownedMonitorsAndFrames007 extends OwnedMonitorsDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsAndFrames007().runIt(argv, out); + } + + private int testThreadsCount = 10; + + // initialize test and remove unsupported by nsk.share.jdi.ArgumentHandler arguments + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testThreadsCount") && (i < args.length - 1)) { + testThreadsCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private void checkAllThreads(String testThreadsNames[]) { + for (int j = 0; j < testThreadsNames.length; j++) { + ThreadReference threadReference = debuggee.threadByName(testThreadsNames[j]); + + pipe.println(OwnedMonitorsDebuggee.COMMAND_UPDATE_MONITOR_INFO + ":" + testThreadsNames[j]); + + if (!isDebuggeeReady()) + return; + + forceBreakpoint(); + + checkMonitorInfo(threadReference); + + debuggee.resume(); + + if (!isDebuggeeReady()) + return; + } + } + + public void doTest() { + initDefaultBreakpoint(); + + try { + List locksTypes = new ArrayList(); + + String testThreadsNames[] = new String[testThreadsCount]; + + for (int i = 0; i < testThreadsNames.length; i++) + testThreadsNames[i] = "ownedMonitorsAndFrames007_LockingThread" + (i + 1); + + // LockingThreads should acquire 4 different monitors + locksTypes.add(LockingThread.SYNCHRONIZED_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_OBJECT_BLOCK); + locksTypes.add(LockingThread.SYNCHRONIZED_THREAD_METHOD); + locksTypes.add(LockingThread.SYNCHRONIZED_BLOCK_STATIC_OBJECT); + + for (int i = 0; i < testThreadsNames.length; i++) { + String threadName = testThreadsNames[i]; + String command = OwnedMonitorsDebuggee.COMMAND_CREATE_LOCKING_THREAD + ":" + threadName; + + for (String lockType : locksTypes) { + command += ":" + lockType; + } + + pipe.println(command); + + if (!isDebuggeeReady()) + return; + } + + checkAllThreads(testThreadsNames); + + // For all LockingThread's monitors: + // - force thread relinquish monitors through Object.wait(), + // - check results of ownedMonitorsAndFrames() + // - force debuggee thread acquire relinquished monitor + // - check results of ownedMonitorsAndFrames() + for (int i = 0; i < locksTypes.size(); i++) { + // all threads relinquish monitor + for (int j = 0; j < testThreadsNames.length; j++) { + pipe.println(OwnedMonitorsDebuggee.COMMAND_RELINQUISH_MONITOR + ":" + testThreadsNames[j] + ":" + i); + + if (!isDebuggeeReady()) + return; + } + + checkAllThreads(testThreadsNames); + + // all threads acquire monitor + for (int j = 0; j < testThreadsNames.length; j++) { + pipe.println(OwnedMonitorsDebuggee.COMMAND_ACQUIRE_RELINQUISHED_MONITOR + ":" + testThreadsNames[j]); + + if (!isDebuggeeReady()) + return; + } + + checkAllThreads(testThreadsNames); + } + + // LockingThreads should free all monitors + for (int i = 0; i < testThreadsNames.length; i++) { + pipe.println(OwnedMonitorsDebuggee.COMMAND_STOP_LOCKING_THREAD + ":" + testThreadsNames[i]); + + if (!isDebuggeeReady()) + return; + } + + checkAllThreads(testThreadsNames); + } finally { + removeDefaultBreakpoint(); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames008/TestDescription.java new file mode 100644 index 00000000000..cb983232797 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames008/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames008. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test do the same things as 'ownedMonitorsAndFrames003', but run in debuggee VM several test threads. + * Default test threads count is 10, but number of test threads can be changed through test parameter '-testThreadsCount' + * (for example "-testThreadsCount 100"). + * This test explicitly set following debuggee VM keys: -Xmixed -XX:CompileThreshold=2 to check that tested + * functionality was not broken after JIT compilation. + * Debuggee VM creates a number of threads and each test thread acquires 4 different monitors in following ways: + * - entering synchronized method + * - entering synchronized block on non-static object + * - entering synchronized method for thread object itself + * - entering synchronized block on static object + * Information about all monitors acquired by test thread is stored in debuggee VM and can be obtained through + * special field in debuggee class: OwnedMonitorsDebuggee.monitorsInfo. + * Debugger VM reads information about acquired monitors from 'OwnedMonitorsDebuggee.monitorsInfo' + * and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames returns correct list of MonitorInfo objects, this + * check is performed for all test threads. + * Debugger VM forces all test threads in debuggee VM sequentially free monitors through Object.wait(), + * updates debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects for all test threads. + * Debugger VM forces all test threads in debuggee VM free all monitors(exit from all synchronized objects/blocks), + * updates debug information about acquired monitors and checks that com.sun.jdi.ThreadReference.ownedMonitorsAndFrames + * returns correct list of MonitorInfo objects for all test threads. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007.ownedMonitorsAndFrames007 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007.ownedMonitorsAndFrames007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmixed + * -XX:CompileThreshold=2" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009/ownedMonitorsAndFrames009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009/ownedMonitorsAndFrames009.java new file mode 100644 index 00000000000..f96b2fb57f9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009/ownedMonitorsAndFrames009.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009. + * VM Testbase keywords: [jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * + * Test checks that acquired ReentrantLock, ReentrantReadWriteLock.ReadLock and ReentrantReadWriteLock.WriteLock + * are not returned by ThreadReference,ownedMonitorsAndFrames. + * + * Debuggee creates test thread wich acquires ReentrantLock, ReentrantReadWriteLock.ReadLock and + * ReentrantReadWriteLock.WriteLock. + * + * Debugger obtains ThreadReference for debugee's test thread and checks that ownedMonitorsAndFrames() returns + * empty list. + * Then, debugger forces test thread release all locks and checks again that ownedMonitorsAndFrames() returns empty list. + * + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009.ownedMonitorsAndFrames009 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009.ownedMonitorsAndFrames009a + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009.ownedMonitorsAndFrames009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009; + +import java.io.PrintStream; +import java.util.ArrayList; +import com.sun.jdi.ThreadReference; +import nsk.share.Consts; +import nsk.share.jdi.OwnedMonitorsDebugger; + +public class ownedMonitorsAndFrames009 extends OwnedMonitorsDebugger { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ownedMonitorsAndFrames009().runIt(argv, out); + } + + protected String debuggeeClassName() { + return ownedMonitorsAndFrames009a.class.getName(); + } + + private void test(ThreadReference thread) { + thread.suspend(); + + try { + // compare result of ownedMonitorsAndFrames() with empty list + compare(thread.ownedMonitorsAndFrames(), new ArrayList()); + } catch (Exception e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + + thread.resume(); + } + + public void doTest() { + ThreadReference thread = debuggee.threadByName(ownedMonitorsAndFrames009a.testThreadName); + + test(thread); + + pipe.println(ownedMonitorsAndFrames009a.COMMAND_RELEASE_ALL_LOCKS); + + if (!isDebuggeeReady()) + return; + + test(thread); + + pipe.println(ownedMonitorsAndFrames009a.COMMAND_STOP_TEST_THREAD); + + if (!isDebuggeeReady()) + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009/ownedMonitorsAndFrames009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009/ownedMonitorsAndFrames009a.java new file mode 100644 index 00000000000..0dc5e4a6890 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames009/ownedMonitorsAndFrames009a.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009; + +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import nsk.share.jdi.*; + +public class ownedMonitorsAndFrames009a extends AbstractJDIDebuggee { + + public static String testThreadName = "ownedMonitorsAndFrames009a_TestThread"; + + public static String COMMAND_RELEASE_ALL_LOCKS = "releaseAllLocks"; + + public static String COMMAND_STOP_TEST_THREAD = "stopTestThread"; + + class TestThread extends Thread { + + private volatile boolean locksAcquied; + + private volatile boolean locksReleased; + + private ReentrantLock lock1 = new ReentrantLock(); + + private ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock(); + + private ReentrantReadWriteLock lock3 = new ReentrantReadWriteLock(); + + public TestThread() { + super(testThreadName); + } + + public void run() { + lock1.lock(); + lock2.readLock().lock(); + lock3.writeLock().lock(); + + locksAcquied = true; + + /* + * Methods Thread.sleep/Thread.interrupt are used for synchronization + * with main thread because of wait/notify can't be used in this test + * (see for example test bug 6487131). + */ + + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + // expected exception + } + + lock1.unlock(); + lock2.readLock().unlock(); + lock3.writeLock().unlock(); + + locksReleased = true; + + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + // expected exception + } + } + + public void startTestThread() { + start(); + + while (!locksAcquied) + Thread.yield(); + } + + public void stopTestThread() { + interrupt(); + + try { + join(); + } catch (InterruptedException e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + } + + public void releaseLocks() { + testThread.interrupt(); + + while (!locksReleased) + Thread.yield(); + } + } + + private TestThread testThread; + + public String[] doInit(String args[]) { + args = super.doInit(args); + + testThread = new TestThread(); + testThread.startTestThread(); + + return args; + } + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_RELEASE_ALL_LOCKS)) { + testThread.releaseLocks(); + return true; + } else if (command.equals(COMMAND_STOP_TEST_THREAD)) { + testThread.stopTestThread(); + return true; + } + + return false; + } + + public static void main(String[] args) { + new ownedMonitorsAndFrames009a().doTest(args); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java new file mode 100644 index 00000000000..f35bf61ae83 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.popFrames()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * After this operation,
    + * this thread will be suspended at the invoke instruction of
    + * the target method that created frame.
    + * The frame's method can be reentered with a
    + * step into the instruction.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent, + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + * In the second phase, the debuggee creates second thread which
    + * will call a tested poppedMethod() from its run() method.
    + * Being called, the poppedMethod() increments the value of
    + * the global variable testVar1.
    + * The debugger sets up a breakpoint within the poppedMethod() and,
    + * after getting this brakpoint event, invokes the popFrames() method,
    + * checks the value of testVar1 after first incerment,
    + * and resumes debuggee's second thread to reenter the poppedMethod().
    + * After getting the breakpoint event second time,
    + * the debugger just checks the value of testVar1 which
    + * has to be incremented one more time.
    + */ + +public class popframes001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/popFrames/popframes001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new popframes001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.popFrames.popframes001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + BreakpointRequest breakpointRequest; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + log2("......vm.resume(); resuming debuggee's main thread"); + vm.resume(); + + for (int i = 0; ; i++) { + +// vm.resume(); + + breakpointForCommunication(); + + int instruction; + + log2("......instruction = ((IntegerValue)...; no Exception expected"); + try { + instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + } catch ( Exception e ) { + log3("ERROR: Exception when 'instruction = ((IntegerValue)...' : " + e); + testExitCode = FAILED; + return; + } + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + if ( !vm.canPopFrames() ) { + log2("......vm.canPopFrames() == false : test is cancelled"); + return; + } + + String thread2Name = "thread2"; + ThreadReference thread2Ref = threadByName(thread2Name); + + + String poppedMethod = "poppedMethod"; + String breakpointLine = "breakpointLine"; + String testVariable = "testVar1"; + + log2("......setting breakpoint in poppedMethod"); + try { + breakpointRequest = settingBreakpoint(threadByName(thread2Name), + debuggeeClass, + poppedMethod, breakpointLine, "one"); + } catch ( Exception e ) { + throw e; + } + log2("......breakpointRequest.enable();"); + breakpointRequest.enable(); + + log2("......eventSet.resume(); resuming debuggee's main thread"); + log2(" to get new rendevous at the breakpointForCommunication"); + eventSet.resume(); + log2("......breakpointInMethod();"); + breakpointInMethod(); + + log2("......getting value of 'testVar1'; 1 is expected"); + Value val = debuggeeClass.getValue(debuggeeClass.fieldByName(testVariable)); + int intVal = ((IntegerValue) val).value(); + if (intVal != 1) { + log3("ERROR: intVal != 1"); + testExitCode = FAILED; + break; + } + + log2("......StackFrame stackFrame = thread2Ref.frame(0);"); + StackFrame stackFrame = thread2Ref.frame(0); + + log2("......thread2Ref.popFrames(stackFrame);"); + try { + thread2Ref.popFrames(stackFrame); + } catch ( IncompatibleThreadStateException e ) { + log3("ERROR: IncompatibleThreadStateException"); + testExitCode = FAILED; + break; + } + + log2("......thread2Ref.resume();"); + thread2Ref.resume(); + log2("......breakpointInMethod();"); + breakpointInMethod(); + + log2("......getting value of 'testVar1'; 2 is expected"); + val = debuggeeClass.getValue(debuggeeClass.fieldByName(testVariable)); + intVal = ((IntegerValue) val).value(); + if (intVal != 2) { + log3("ERROR: intVal != 2"); + testExitCode = FAILED; + break; + } + + log2("......thread2Ref.resume();"); + thread2Ref.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private void breakpointInMethod() + throws JDITestRuntimeException { + + log2("breakpointInMethod"); + getEventSet(); + Event event = eventIterator.nextEvent(); + + if ( !(event instanceof BreakpointEvent) ) + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + + if ( !event.request().equals(breakpointRequest) ) + throw new JDITestRuntimeException("** unexpected breakpoint **"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001/TestDescription.java new file mode 100644 index 00000000000..5f566a2f708 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001/TestDescription.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/popFrames/popframes001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.popFrames() + * complies with its spec: + * public void popFrames(StackFrame frame) + * throws IncompatibleThreadStateException + * Pop stack frames. + * All frames up to and including the frame are popped off the stack. + * The frame previous to the + * parameter frame will become the current frame. + * After this operation, this thread will be suspended at the invoke + * instruction of the target method that created frame. + * The frame's method can be reentered with a step into the instruction. + * The operand stack is restored, however, any changes to the arguments that + * occurred in the called method, remain. For example, if the method foo: + * void foo(int x) { + * System.out.println("Foo: " + x); + * x = 4; + * System.out.println("pop here"); + * } + * was called with foo(7) and foo is popped at the second println and resumed, + * it will print: Foo: 4. + * Locks acquired by a popped frame are released when it is popped. + * This applies to synchronized methods that are popped, and + * to any synchronized blocks within them. + * Finally blocks are not executed. + * No aspect of state, other than this thread's execution point and locks, + * is affected by this call. Specifically, the values of fields are unchanged, + * as are external resources such as I/O streams. Additionally, + * the target program might be placed in a state that is impossible with + * normal program flow; for example, order of lock acquisition might be + * perturbed. Thus the target program may proceed differently than the user would expect. + * The specified thread must be suspended. + * All StackFrame objects for this thread are invalidated. + * No events are generated by this method. + * None of the frames through and including frame may be native. + * Not all target virtual machines support this operation. Use + * VirtualMachine.canPopFrames() to determine if the operation is supported. + * Parameters: frame - Stack frame to pop. + * frame is on this thread's call stack. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation - see + * VirtualMachine.canPopFrames(). + * IncompatibleThreadStateException - + * if this thread is not suspended. + * IllegalArgumentException - + * if frame is not on this thread's call stack. + * NativeMethodException - + * if one of the frames that would be popped is that of + * a native method or if frame is native. + * InvalidStackFrameException - + * if frame has become invalid. Once this thread is resumed, + * the stack frame is no longer valid. + * The test checks up on the following assertion: + * After this operation, this thread will be suspended at the invoke instruction of + * the target method that created frame. The frame's method can be reentered with a + * step into the instruction. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.popFrames.popframes001; + * the debuggee program - nsk.jdi.ThreadReference.popFrames.popframes001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * To fix the bug 4510417, + * vm.resume(); is out of (before) the loop + * to eliminate double resuming debeggee's main thread. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.popFrames.popframes001 + * nsk.jdi.ThreadReference.popFrames.popframes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.popFrames.popframes001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001a.java new file mode 100644 index 00000000000..acfdff08f81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001a.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the popframes001 JDI test. + */ + +public class popframes001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadpopframes001a thread2 = null; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread2 = new Threadpopframes001a("thread2"); + log1(" thread2 is created"); + + synchronized (lockingObject) { + synchronized (waitnotifyObj) { + log1(" thread2.start()"); + thread2.start(); + + try { + log1(" before: waitnotifyObj.wait();"); + waitnotifyObj.wait(); + log1(" after: waitnotifyObj.wait();"); + } catch ( Exception e2) { + log1(" Exception e2 exception: " + e2 ); + exitCode = FAILED; + break label0; + } + } + methodForCommunication(); + } + + synchronized (lockingObject2) { + log1("mainThread is in: synchronized (lockingObject2)"); + } + + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + + log1("before: methodForCommunication();"); + methodForCommunication(); + log1("after: methodForCommunication();"); + + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + static int testVar1 = 0; + static int testVar2 = 0; + static int breakpointLine = 4; + + static void poppedMethod() { + log1("poppedMethod: enter"); + testVar1 +=1; + testVar2 +=1; + testVar2 +=1; + + log1("poppedMethod: exit"); + return; + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static Object lockingObject2 = new Object(); + + static class Threadpopframes001a extends Thread { + + public Threadpopframes001a(String threadName) { + super(threadName); + } + + public void run() { + synchronized (lockingObject2) { + log1("thread2: method 'run' enter"); + synchronized (waitnotifyObj) { + log1("thread2: entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log1("thread2: exited from block: synchronized (waitnotifyObj)"); + synchronized (lockingObject) { + log1("thread2: entered into block: synchronized (lockingObject)"); + } + log1("thread2: exited from block: synchronized (lockingObject)"); + + log1("thread2: before: 'poppedMethod()'"); + poppedMethod(); + log1("thread2: after: 'poppedMethod()'"); + } + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java new file mode 100644 index 00000000000..026a8775ca9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java @@ -0,0 +1,543 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.popFrames()
    + * complies with its spec.
    + *
    + * The test checks up that
    + * a BreakpointRequest in debuggee's third thread
    + * is not affected when
    + * its second thread is suspended at a breakpoint in a method
    + * and method's frame is popped by a debugger.
    + *
    + * The test has two phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent, + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to perform the above check,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates two threads, thread2 and thread3, which will
    + * call a tested synchronized poppedMethod() from their run() methods.
    + * After getting the threads started, the debuggee invokes the
    + * methodForCommunication() to inform the debugger of the threads.
    + * - The debugger sets up two breakpoints within the poppedMethod(),
    + * one for the thread2 and another one for the thread3, and
    + * resumes debuggee's main thread.
    + * - The main thread releases the thread2 and the thread3 in the order
    + * which makes the thread2 to be suspended at the breakpoint within
    + * the poppedMethod and the thread3 to be waiting for releasing the
    + * synchronized poppedMethod by the thread2. Then
    + * the main thread informs the debugger via methodForCommunication().
    + * - After getting both breakpoint events, from the thread2 and the main,
    + * the debugger invokes the popFrames() method and waits for
    + * the breakpoint event in poppedMethod from the thread3.
    + * If no the event, the test FAILED.
    + */ + +public class popframes002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/popFrames/popframes002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new popframes002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.popFrames.popframes002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + BreakpointRequest bpRequest; + BreakpointRequest breakpointRequest2; + BreakpointRequest breakpointRequest3; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + if ( !vm.canPopFrames() ) { + log2("......vm.canPopFrames() == false : test is cancelled"); + vm.resume(); + return; + } + + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + log2("......setting BreakpointRequest (bpRequest) in main thread"); + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + log2("bpRequest.enable();"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + label0: + { + vm.resume(); + breakpointForCommunication(); + + String thread2Name = "thread2"; + ThreadReference thread2Ref = threadByName(thread2Name); + + String thread3Name = "thread3"; + ThreadReference thread3Ref = threadByName(thread3Name); + + String poppedMethod = "poppedMethod"; + String breakpointLine = "breakpointLine"; + String testVariable = "testVar1"; + + log2("......setting breakpoints in poppedMethod"); + try { + breakpointRequest2 = settingBreakpoint(thread2Ref, debuggeeClass, + poppedMethod, breakpointLine, "one"); + } catch ( Exception e ) { + throw e; + } + log2("......breakpointRequest2.enable();"); + breakpointRequest2.enable(); + try { + breakpointRequest3 = settingBreakpoint(thread3Ref, debuggeeClass, + poppedMethod, breakpointLine, "two"); + } catch ( Exception e ) { + throw e; + } + log2("......breakpointRequest3.enable();"); + breakpointRequest3.enable(); + + + log2("......eventSet.resume();"); + eventSet.resume(); + log2("......breakpointInMethod(breakpointRequest2);"); + breakpointInMethod("one"); + + if ( bpRequestFlag == 0 ) + breakpointForCommunication(); + + log2("......StackFrame stackFrame = thread2Ref.frame(0);"); + StackFrame stackFrame = thread2Ref.frame(0); + + log2("......thread2Ref.popFrames(stackFrame);"); + try { + thread2Ref.popFrames(stackFrame); + } catch ( IncompatibleThreadStateException e ) { + log3("ERROR: IncompatibleThreadStateException"); + testExitCode = FAILED; + break label0; + } + + log2("......breakpointInMethod(breakpointRequest3);"); + try { + breakpointInMethod("two"); + } catch ( JDITestRuntimeException e ) { + log3("ERROR: timeout while waiting for thread3's BreakpointEvent"); + log2(" THREAD_STATUS_MONITOR == " + ThreadReference.THREAD_STATUS_MONITOR ); + log2(" thread3's status == " + thread3Ref.status()); + testExitCode = FAILED; + } + + if (!thread3Ref.isSuspended()) { + log3("ERROR: thread3 is not suspended at the breakpoint"); + testExitCode = FAILED; + break label0; + } + } + + log2("......disabling breakpointRequests 2&3"); + breakpointRequest2.disable(); + breakpointRequest3.disable(); + + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + static int bpRequestFlag = 0; + + private void breakpointInMethod(String number) + throws JDITestRuntimeException { + + Event event; + + for ( ; ; ) { + getEventSet(); + event = eventIterator.nextEvent(); + + if ( !(event instanceof BreakpointEvent) ) + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + + log2("---->: request().getProperty == " + + event.request().getProperty("number")); + + if ( event.request().getProperty("number").equals(number) ) + return; + + if ( !event.request().getProperty("number").equals("zero") ) + throw new JDITestRuntimeException("** unexpected breakpoint **"); + bpRequestFlag = 1; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002/TestDescription.java new file mode 100644 index 00000000000..2cba987ab17 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002/TestDescription.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/popFrames/popframes002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.popFrames() + * complies with its spec: + * public void popFrames(StackFrame frame) + * throws IncompatibleThreadStateException + * Pop stack frames. + * All frames up to and including the frame are popped off the stack. + * The frame previous to the + * parameter frame will become the current frame. + * After this operation, this thread will be suspended at the invoke + * instruction of the target method that created frame. + * The frame's method can be reentered with a step into the instruction. + * The operand stack is restored, however, any changes to the arguments that + * occurred in the called method, remain. For example, if the method foo: + * void foo(int x) { + * System.out.println("Foo: " + x); + * x = 4; + * System.out.println("pop here"); + * } + * was called with foo(7) and foo is popped at the second println and resumed, + * it will print: Foo: 4. + * Locks acquired by a popped frame are released when it is popped. + * This applies to synchronized methods that are popped, and + * to any synchronized blocks within them. + * Finally blocks are not executed. + * No aspect of state, other than this thread's execution point and locks, + * is affected by this call. Specifically, the values of fields are unchanged, + * as are external resources such as I/O streams. Additionally, + * the target program might be placed in a state that is impossible with + * normal program flow; for example, order of lock acquisition might be + * perturbed. Thus the target program may proceed differently than the user would expect. + * The specified thread must be suspended. + * All StackFrame objects for this thread are invalidated. + * No events are generated by this method. + * None of the frames through and including frame may be native. + * Not all target virtual machines support this operation. Use + * VirtualMachine.canPopFrames() to determine if the operation is supported. + * Parameters: frame - Stack frame to pop. + * frame is on this thread's call stack. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation - see + * VirtualMachine.canPopFrames(). + * IncompatibleThreadStateException - + * if this thread is not suspended. + * IllegalArgumentException - + * if frame is not on this thread's call stack. + * NativeMethodException - + * if one of the frames that would be popped is that of + * a native method or if frame is native. + * InvalidStackFrameException - + * if frame has become invalid. Once this thread is resumed, + * the stack frame is no longer valid. + * The test checks up that a BreakpointRequest in debuggee's third thread + * is not affected when its second thread is suspended at a breakpoint + * in a method and method's frame is popped by a debugger. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.popFrames.popframes002; + * the debuggee program - nsk.jdi.ThreadReference.popFrames.popframes002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.popFrames.popframes002 + * nsk.jdi.ThreadReference.popFrames.popframes002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.popFrames.popframes002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002a.java new file mode 100644 index 00000000000..d7d0a6b7a1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002a.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the popframes002 JDI test. + */ + +public class popframes002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread2popframes002a thread2 = null; + static Thread3popframes002a thread3 = null; + + //------------------------------------------------------ common section + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + { + + //------------------------------------------------------ section tested + + thread2 = new Thread2popframes002a("thread2"); + log1(" thread2 is created"); + thread3 = new Thread3popframes002a("thread3"); + log1(" thread3 is created"); + + synchronized (lockingObject1) { + synchronized (lockingObject3) { + synchronized (lockingObject2) { + log1(" thread2.start()"); + if ( threadStart(thread2) != PASSED ) + break label0; + + log1(" thread3.start()"); + if ( threadStart(thread3) != PASSED ) + break label0; + + log1(" methodForCommunication(); ----1"); + methodForCommunication(); + } + + log1(" before: lockingObject1.wait();"); + try { + lockingObject1.wait(); + } catch ( InterruptedException e ) { + logErr(" Exception : " + e ); + break label0; + } + log1(" after: lockingObject1.wait();"); + } + } + log1(" methodForCommunication(); ----2"); + methodForCommunication(); + } + //------------------------------------------------- standard end section + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + log1(" before: waitnotifyObj.wait();"); + waitnotifyObj.wait(); + log1(" after: waitnotifyObj.wait();"); + } catch ( Exception e) { + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObject1 = new Object(); + + static int testVar1 = 0; + static int testVar2 = 0; + static int breakpointLine = 4; + + static synchronized void poppedMethod() { + log1("poppedMethod entered by the thread : " + Thread.currentThread().getName() ); + synchronized (lockingObject1) { lockingObject1.notify(); } + testVar1 +=1; + testVar2 +=1; + testVar2 +=1; + + log1("poppedMethod: exit"); + return; + } + + static Object lockingObject2 = new Object(); + + static class Thread2popframes002a extends Thread { + + public Thread2popframes002a(String threadName) { + super(threadName); + } + + public void run() { + log1("thread2: method 'run' enter"); + synchronized (waitnotifyObj) { + log1("thread2: entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log1("thread2: exited from block: synchronized (waitnotifyObj)"); + + synchronized (lockingObject2) { + log1("thread2: before: 'poppedMethod()'"); + poppedMethod(); + log1("thread2: after: 'poppedMethod()'"); + } + return; + } + } + + static Object lockingObject3 = new Object(); + + static class Thread3popframes002a extends Thread { + + public Thread3popframes002a(String threadName) { + super(threadName); + } + + public void run() { + log1("thread3: method 'run' enter"); + synchronized (waitnotifyObj) { + log1("thread3: entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log1("thread3: exited from block: synchronized (waitnotifyObj)"); + + synchronized (lockingObject3) { + log1("thread3: before: 'poppedMethod()'"); + poppedMethod(); + log1("thread3: after: 'poppedMethod()'"); + } + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java new file mode 100644 index 00000000000..a2a625daa81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.popFrames()
    + * complies with its spec.
    + *
    + *
    + * The test checks up that locks acquired by a popped frame,
    + * are released when it is popped.
    + * This applies to synchronized methods being popped.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to perform the above check,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates two threads, thread2 and thread3, which will
    + * call a tested synchronized poppedMethod() from their run() methods.
    + * After getting the threads started, the debuggee invokes the
    + * methodForCommunication() to inform the debugger of the threads.
    + * - The debugger sets up Breakpoint and MethodEntry Requests
    + * within the poppedMethod(), first one for the thread2 and
    + * second one for the thread3, and resumes debuggee's main thread.
    + * - The main thread releases the thread2 and the thread3 in the order
    + * which makes the thread2 to be suspended at the breakpoint within
    + * the poppedMethod and the thread3 to be waiting for releasing the
    + * synchronized poppedMethod by the thread2. Then
    + * the main thread informs the debugger via methodForCommunication().
    + * - After getting both events, from the thread2 and the main,
    + * the debugger invokes the popFrames() method and waits for
    + * the MethodEntry event in poppedMethod from the thread3.
    + * If no the event, the test FAILED.
    + */ + +public class popframes003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/popFrames/popframes003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new popframes003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.popFrames.popframes003a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + BreakpointRequest bpRequest; + MethodEntryRequest meRequest; + + BreakpointRequest bpRequest2; + MethodEntryRequest meRequest3; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + + if ( !vm.canPopFrames() ) { + log2("......vm.canPopFrames() == false : test is cancelled"); + vm.resume(); + return; + } + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference threadMainRef = threadByName("main"); + try { + bpRequest = settingBreakpoint(threadMainRef, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventSet mainThreadEventSet = null; + + int flag = 0; + + + vm.resume(); + breakpointForCommunication(); + + log2("......setting MethodEntryRequest (meRequest) in ForCommunication.methodForCommunication"); + meRequest = settingMethodEntryRequest(threadMainRef, + debuggeeName + "$ForCommunication", + "zero"); + log2("meRequest.enable();"); + meRequest.enable(); + + + String thread2Name = "thread2"; + ThreadReference thread2Ref = threadByName(thread2Name); + + String thread3Name = "thread3"; + ThreadReference thread3Ref = threadByName(thread3Name); + + String poppedMethod = "poppedMethod"; + String breakpointLine = "breakpointLine"; + String testVariable = "testVar1"; + + log2("......setting BreakpointRequest (bpRequest2) in poppedMethod"); + List classes = vm.classesByName(debuggeeName + "$Popped"); + ReferenceType poppedClass = (ReferenceType) classes.get(0); + bpRequest2 = settingBreakpoint(thread2Ref, poppedClass, + poppedMethod, breakpointLine, "one"); + log2("......bpRequest2.enable();"); + bpRequest2.enable(); + + log2("......setting MethodEntryRequest (meRequest3) in poppedMethod"); + meRequest3 = settingMethodEntryRequest(thread3Ref, debuggeeName + "$Popped", + "two"); + log2("......meRequest3.enable();"); + meRequest3.enable(); + + log2("......eventSet.resume();"); + eventSet.resume(); + + log2(".....waiting for Breakpoint(thread2) and MethodEntry(main) Events"); + for ( ; ; ) { + + Event event1; + + if (flag == 3) + break; + + getEventSet(); + event1 = eventIterator.nextEvent(); + + if ( event1 instanceof MethodEntryEvent ) { + mainThreadEventSet = eventSet; + flag |= 1; + log2("......event1 instanceof MethodEntryEvent"); + } else if ( event1 instanceof BreakpointEvent ) { + flag |= 2; + log2("......event1 instanceof BreakpointEvent"); + } else + throw new JDITestRuntimeException("** event1 IS NOT Breakpoint or MethodEntry **"); + } + + log2("......bpRequest2.disable();"); + bpRequest2.disable(); + + label0: + { +// log2(" THREAD_STATUS_RUNNING == " + ThreadReference.THREAD_STATUS_RUNNING ); +// log2(" thread2's status == " + thread2Ref.status()); + + if (thread2Ref.isSuspended()) + log2(" thread2Ref.isSuspended()"); + else { + log3("ERROR: !thread2Ref.isSuspended()"); + testExitCode = FAILED; + break label0; + } + + log2("......mainThreadEventSet.resume();"); + mainThreadEventSet.resume(); + + log2("......up to WAITTIME loop of sleeping"); + log2(" to get thread3 waiting on monitor after calling poppedMethod"); + int thread3Status = 0; + for ( int i1 = 0; i1 < waitTime; i1 += 10000) { + if (thread3Ref.status() == ThreadReference.THREAD_STATUS_MONITOR) { + thread3Status = 1; + break; + } + Thread.sleep(10000); + } + if (thread3Status != 1) { + log3("ERROR: thread3Ref.status() != THREAD_STATUS_MONITOR"); + testExitCode = FAILED; + break label0; + } + + log2("......StackFrame stackFrame = thread2Ref.frame(0);"); + StackFrame stackFrame = thread2Ref.frame(0); + + log2("......thread2Ref.popFrames(stackFrame);"); + try { + thread2Ref.popFrames(stackFrame); + } catch ( IncompatibleThreadStateException e ) { + log3("ERROR: IncompatibleThreadStateException"); + testExitCode = FAILED; + break label0; + } + + log2(".....waiting for MethodEntry (main and thread3) Events"); + { + flag = 0; + + for ( ; ; ) { + + Event event1; + + if (flag == 3) + break; + + getEventSet(); + event1 = eventIterator.nextEvent(); + + if ( !(event1 instanceof MethodEntryEvent) ) + throw new JDITestRuntimeException("** event IS NOT MethodEntry **"); + + if ( event1.request().getProperty("number").equals("zero") ) { + flag |= 1; + log2("......MethodEntry in mainThread"); + } else { + flag |= 2; + log2("......MethodEntry in thread3"); + } + } + } + + } + + log2("......disabling requests and resuming vm"); + meRequest3.disable(); + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + /* + * private MethodEntryRequest settingMethodEntryRequest(ThreadReference, ReferenceType, + * String) + * + * It sets up a MethodEntryRequest in a given class for a given thread. + * + * Return value: MethodEntryRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private MethodEntryRequest settingMethodEntryRequest ( ThreadReference thread, + String className, + String property) + throws JDITestRuntimeException { + + log2("......setting up a methodEntryRequest:"); + log2(" thread: " + thread + "; className: " + className + + "; property: " + property); + + List classList = vm.classesByName(className); + ReferenceType classRef = (ReferenceType) classList.get(0); + + MethodEntryRequest methodEntryRequest = null; + + try { + methodEntryRequest = eventRManager.createMethodEntryRequest(); + methodEntryRequest.putProperty("number", property); + methodEntryRequest.addThreadFilter(thread); + methodEntryRequest.addClassFilter(classRef); + methodEntryRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e ) { + log3("ERROR: Exception within methodEntryRequest() : " + e); + throw new JDITestRuntimeException("** FAILURE to set up a MethodEntryRequest **"); + } + + log2(" a methodEntryRequest has been set up"); + return methodEntryRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void eventForCommunication() + throws JDITestRuntimeException { + + log2("eventForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof MethodEntryEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a MethodEntryEvent **"); + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003/TestDescription.java new file mode 100644 index 00000000000..dca528d538f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003/TestDescription.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/popFrames/popframes003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.popFrames() + * complies with its spec: + * public void popFrames(StackFrame frame) + * throws IncompatibleThreadStateException + * Pop stack frames. + * All frames up to and including the frame are popped off the stack. + * The frame previous to the + * parameter frame will become the current frame. + * After this operation, this thread will be suspended at the invoke + * instruction of the target method that created frame. + * The frame's method can be reentered with a step into the instruction. + * The operand stack is restored, however, any changes to the arguments that + * occurred in the called method, remain. For example, if the method foo: + * void foo(int x) { + * System.out.println("Foo: " + x); + * x = 4; + * System.out.println("pop here"); + * } + * was called with foo(7) and foo is popped at the second println and resumed, + * it will print: Foo: 4. + * Locks acquired by a popped frame are released when it is popped. + * This applies to synchronized methods that are popped, and + * to any synchronized blocks within them. + * Finally blocks are not executed. + * No aspect of state, other than this thread's execution point and locks, + * is affected by this call. Specifically, the values of fields are unchanged, + * as are external resources such as I/O streams. Additionally, + * the target program might be placed in a state that is impossible with + * normal program flow; for example, order of lock acquisition might be + * perturbed. Thus the target program may proceed differently than the user would expect. + * The specified thread must be suspended. + * All StackFrame objects for this thread are invalidated. + * No events are generated by this method. + * None of the frames through and including frame may be native. + * Not all target virtual machines support this operation. Use + * VirtualMachine.canPopFrames() to determine if the operation is supported. + * Parameters: frame - Stack frame to pop. + * frame is on this thread's call stack. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation - see + * VirtualMachine.canPopFrames(). + * IncompatibleThreadStateException - + * if this thread is not suspended. + * IllegalArgumentException - + * if frame is not on this thread's call stack. + * NativeMethodException - + * if one of the frames that would be popped is that of + * a native method or if frame is native. + * InvalidStackFrameException - + * if frame has become invalid. Once this thread is resumed, + * the stack frame is no longer valid. + * The test checks up that locks acquired by a popped frame, + * are released when it is popped. + * This applies to synchronized methods being popped. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.popFrames.popframes003; + * the debuggee program - nsk.jdi.ThreadReference.popFrames.popframes003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.popFrames.popframes003 + * nsk.jdi.ThreadReference.popFrames.popframes003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.popFrames.popframes003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003a.java new file mode 100644 index 00000000000..a2b2879e094 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003a.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the popframes003 JDI test. + */ + +public class popframes003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread2popframes003a thread2 = null; + static Thread3popframes003a thread3 = null; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + { + thread2 = new Thread2popframes003a("thread2"); + log1(" thread2 is created"); + thread3 = new Thread3popframes003a("thread3"); + log1(" thread3 is created"); + + synchronized (lockingObject1) { + synchronized (lockingObject3) { + synchronized (lockingObject2) { + log1(" thread2.start()"); + if ( threadStart(thread2) != PASSED ) + break label0; + + log1(" thread3.start()"); + if ( threadStart(thread3) != PASSED ) + break label0; + + // to get classes Popped&ForCommunication prepared + Popped.poppedMethod(); + ForCommunication.methodForCommunication(); + + log1(" methodForCommunication();"); + methodForCommunication(); + } + + log1(" before: lockingObject1.wait();"); + try { + lockingObject1.wait(); + } catch ( InterruptedException e ) { + logErr(" Exception : " + e ); + break label0; + } + log1(" after: lockingObject1.wait();"); + } + + log1(" ForCommunication.methodForCommunication(); --1"); + ForCommunication.methodForCommunication(); + } + log1(" ForCommunication.methodForCommunication(); --2"); + ForCommunication.methodForCommunication(); + } + + System.exit(exitCode + PASS_BASE); + } + + + static int testVar1 = 0; + static int testVar2 = 0; + + static class Popped { + + static int breakpointLine = 4; + + static synchronized void poppedMethod() { + log1("poppedMethod entered by the thread : " + Thread.currentThread().getName() ); + synchronized (lockingObject1) { lockingObject1.notify(); } + testVar1 +=1; + testVar2 +=1; + testVar2 +=1; + + log1("poppedMethod: exit"); + return; + } + } + + static class ForCommunication { + + public static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + log1(" before: waitnotifyObj.wait();"); + waitnotifyObj.wait(); + log1(" after: waitnotifyObj.wait();"); + } catch ( Exception e) { + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObject1 = new Object(); + + static Object lockingObject2 = new Object(); + + static class Thread2popframes003a extends Thread { + + public Thread2popframes003a(String threadName) { + super(threadName); + } + + public void run() { + log1("thread2: method 'run' enter"); + synchronized (waitnotifyObj) { + log1("thread2: entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log1("thread2: exited from block: synchronized (waitnotifyObj)"); + + synchronized (lockingObject2) { + log1("thread2: before: 'poppedMethod()'"); + Popped.poppedMethod(); + log1("thread2: after: 'poppedMethod()'"); + } + return; + } + } + + static Object lockingObject3 = new Object(); + + static class Thread3popframes003a extends Thread { + + public Thread3popframes003a(String threadName) { + super(threadName); + } + + public void run() { + log1("thread3: method 'run' enter"); + synchronized (waitnotifyObj) { + log1("thread3: entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log1("thread3: exited from block: synchronized (waitnotifyObj)"); + + synchronized (lockingObject3) { + log1("thread3: before: 'poppedMethod()'"); + Popped.poppedMethod(); + log1("thread3: after: 'poppedMethod()'"); + } + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java new file mode 100644 index 00000000000..ed3a048d66c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.popFrames()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Finally blocks are not executed.
    + *
    + * The test has two phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent
    + * in the methodForCommunication().
    + * - The debuggee creates second thread, the thread2, which will
    + * call a tested poppedMethod() two times from its run() method.
    + * The poppedMethod will call the special breakpointMethod,
    + * first time from try clause, second time from catch clause.
    + * The finally clause contains assignment of 1 to the variable testVar,
    + * whose initial value is 0; hence, if the finally clause is executed,
    + * the value of the testVar is changed as well.
    + * After creating the thread2, the debuggee invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent in the methodForCommunication,
    + * the debugger sets up a breakpoint in the breakpointMethod,
    + * resumes the debuggee, waits for BreakpointEvents in the
    + * breakpointMethod and, and upon getting them, invokes popFrames() and
    + * checks up on the value of the testVar.
    + *
    + */ + +public class popframes004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/popFrames/popframes004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new popframes004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.popFrames.popframes004a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + BreakpointRequest bpRequest; + BreakpointRequest breakpointRequest2; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + if ( !vm.canPopFrames() ) { + log2("......vm.canPopFrames() == false : test is cancelled"); + vm.resume(); + return; + } + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + log2("......setting BreakpointRequest (bpRequest) in main thread"); + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + log2("bpRequest.enable();"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + label0: + { + vm.resume(); + breakpointForCommunication(); + + String thread2Name = "thread2"; + ThreadReference thread2Ref = threadByName(thread2Name); + + StackFrame stackFrame = null; + int var; + + String breakpointMethod = "breakpointMethod"; + String breakpointLine = "breakpointLine"; + + String testVar = "testVar"; + + log2("......setting breakpoint in breakpointMethod"); + breakpointRequest2 = settingBreakpoint(thread2Ref, debuggeeClass, + breakpointMethod, breakpointLine, "one"); + log2("......breakpointRequest2.enable();"); + breakpointRequest2.enable(); + + { // to get mainThread suspended; otherwise its end results in + // no suspention for breakpointRequest2 (bug or not?), end of test, + // and VMDisconnectException + thread2Ref.suspend(); + log2("......eventSet.resume();"); + eventSet.resume(); + breakpointForCommunication(); + log2("bpRequest.disable();"); + bpRequest.disable(); + thread2Ref.resume(); + } + + log2("......breakpointInMethod(breakpointRequest2);"); + breakpointInMethod("one"); + + log2(" "); + log2("......TEST CASE: try clause"); + log2(" "); + log2("......stackFrame = thread2Ref.frame(1);"); + stackFrame = thread2Ref.frame(1); + + log2("......thread2Ref.popFrames(stackFrame);"); + try { + thread2Ref.popFrames(stackFrame); + } catch ( IncompatibleThreadStateException e ) { + log3("ERROR: IncompatibleThreadStateException"); + testExitCode = FAILED; + break label0; + } + var = ((IntegerValue) debuggeeClass.getValue( + debuggeeClass.fieldByName(testVar))).value(); + if (var != 0) { + log3("ERROR: testVar != 0"); + testExitCode = FAILED; + } + + thread2Ref.resume(); + log2("......breakpointInMethod(breakpointRequest2);"); + breakpointInMethod("one"); + + thread2Ref.resume(); + log2("......breakpointInMethod(breakpointRequest2);"); + breakpointInMethod("one"); + + log2(" "); + log2("......TEST CASE: catch clause"); + log2(" "); + + log2("......StackFrame stackFrame = thread2Ref.frame(1);"); + stackFrame = thread2Ref.frame(1); + + log2("......thread2Ref.popFrames(stackFrame);"); + try { + thread2Ref.popFrames(stackFrame); + } catch ( IncompatibleThreadStateException e ) { + log3("ERROR: IncompatibleThreadStateException"); + testExitCode = FAILED; + break label0; + } + var = ((IntegerValue) debuggeeClass.getValue( + debuggeeClass.fieldByName(testVar))).value(); + if (var != 0) { + log3("ERROR: testVar != 0"); + testExitCode = FAILED; + } + + log2("......breakpointRequest2.disable();"); + breakpointRequest2.disable(); + + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private void breakpointInMethod(String number) + throws JDITestRuntimeException { + + Event event; + + getEventSet(); + event = eventIterator.nextEvent(); + + if ( !(event instanceof BreakpointEvent) ) + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + + log2("---->: request().getProperty == " + + event.request().getProperty("number")); + + if ( event.request().getProperty("number").equals(number) ) + return; + + throw new JDITestRuntimeException("** UNEXPECTED breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004/TestDescription.java new file mode 100644 index 00000000000..56800751c9f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004/TestDescription.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/popFrames/popframes004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.popFrames() + * complies with its spec: + * public void popFrames(StackFrame frame) + * throws IncompatibleThreadStateException + * Pop stack frames. + * All frames up to and including the frame are popped off the stack. + * The frame previous to the + * parameter frame will become the current frame. + * After this operation, this thread will be suspended at the invoke + * instruction of the target method that created frame. + * The frame's method can be reentered with a step into the instruction. + * The operand stack is restored, however, any changes to the arguments that + * occurred in the called method, remain. For example, if the method foo: + * void foo(int x) { + * System.out.println("Foo: " + x); + * x = 4; + * System.out.println("pop here"); + * } + * was called with foo(7) and foo is popped at the second println and resumed, + * it will print: Foo: 4. + * Locks acquired by a popped frame are released when it is popped. + * This applies to synchronized methods that are popped, and + * to any synchronized blocks within them. + * Finally blocks are not executed. + * No aspect of state, other than this thread's execution point and locks, + * is affected by this call. Specifically, the values of fields are unchanged, + * as are external resources such as I/O streams. Additionally, + * the target program might be placed in a state that is impossible with + * normal program flow; for example, order of lock acquisition might be + * perturbed. Thus the target program may proceed differently than the user would expect. + * The specified thread must be suspended. + * All StackFrame objects for this thread are invalidated. + * No events are generated by this method. + * None of the frames through and including frame may be native. + * Not all target virtual machines support this operation. Use + * VirtualMachine.canPopFrames() to determine if the operation is supported. + * Parameters: frame - Stack frame to pop. + * frame is on this thread's call stack. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation - see + * VirtualMachine.canPopFrames(). + * IncompatibleThreadStateException - + * if this thread is not suspended. + * IllegalArgumentException - + * if frame is not on this thread's call stack. + * NativeMethodException - + * if one of the frames that would be popped is that of + * a native method or if frame is native. + * InvalidStackFrameException - + * if frame has become invalid. Once this thread is resumed, + * the stack frame is no longer valid. + * The test checks up on the assertion: + * Finally blocks are not executed. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.popFrames.popframes004; + * the debuggee program - nsk.jdi.ThreadReference.popFrames.popframes004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.popFrames.popframes004 + * nsk.jdi.ThreadReference.popFrames.popframes004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.popFrames.popframes004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004a.java new file mode 100644 index 00000000000..fe70728550a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004a.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the popframes004 JDI test. + */ + +public class popframes004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread2popframes004a thread2 = null; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + + + static class JDIDebuggeeException extends Exception { + JDIDebuggeeException(String str) { + super("JDIDebuggeeException : " + str); + } + } + //---------------------------------------------------- main method + + static int var1 = 0; + static volatile int testVar = 0; + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + label0: + { + thread2 = new Thread2popframes004a("thread2"); + log1(" thread2 is created"); + + synchronized (lockingObject2) { + log1(" thread2.start()"); + if ( threadStart(thread2) != PASSED ) + break label0; + + log1(" methodForCommunication();"); + methodForCommunication(); + } + methodForCommunication(); + } + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + log1(" before: waitnotifyObj.wait();"); + waitnotifyObj.wait(); + log1(" after: waitnotifyObj.wait();"); + } catch ( Exception e) { + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static int breakpointLine = 3; + + static void breakpointMethod () { + log1("breakpointMethod entered by the thread : " + Thread.currentThread().getName() ); + var1 += 1; + var1 += 1; + var1 += 1; + log1("breakpointMethod: exit"); + } + + static void poppedMethod(int arg) { + log1("poppedMethod entered by the thread : " + Thread.currentThread().getName() ); + try { + if (arg == 0) { + log1("thread2: try clause: calling breakpointMethod();"); + breakpointMethod(); + } else { + log1("thread2: try clause: throwing JDIDebuggeeException"); + throw new JDIDebuggeeException("poppedMethod"); + } + } catch ( JDIDebuggeeException e ) { + log1("thread2: catch clause: caught JDIDebuggeeException"); + log1("thread2: catch clause: calling breakpointMethod();"); + breakpointMethod(); + } finally { + log1("thread2: finally clause"); + testVar = 1; + } + + log1("poppedMethod: exit"); + return; + } + + static Object lockingObject2 = new Object(); + + static class Thread2popframes004a extends Thread { + + public Thread2popframes004a(String threadName) { + super(threadName); + } + + public void run() { + log1("thread2: method 'run' enter"); + synchronized (waitnotifyObj) { + log1("thread2: entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log1("thread2: exited from block: synchronized (waitnotifyObj)"); + + synchronized (lockingObject2) { + testVar = 0; + log1("thread2: before: 'poppedMethod(0)'"); + poppedMethod(0); + log1("thread2: after: 'poppedMethod(0)'"); + + testVar = 0; + log1("thread2: before: 'poppedMethod(1)'"); + poppedMethod(1); + log1("thread2: after: 'poppedMethod(1)'"); + } + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java new file mode 100644 index 00000000000..5c471e9182b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.popFrames()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertions:
    + * - All StackFrame objects for this thread are invalidated.
    + * - The frame previous to the parameter frame
    + * will become the current frame.
    + *
    + * The test has two phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent
    + * in the methodForCommunication().
    + * - The debuggee creates second thread, the thread2, which will
    + * call a tested poppedMethod() from its run() method.
    + * The poppedMethod will call the special breakpointMethod,
    + * After creating the thread2, the debuggee invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent in the methodForCommunication,
    + * the debugger sets up a breakpoint in the breakpointMethod,
    + * resumes the debuggee, waits for BreakpointEvent in the
    + * breakpointMethod and, and upon getting it,
    + * (1) to check up on first assertion, gets thread2.frame(2),
    + * invokes popFrames() and checks up on equality of thread2.frame(2)
    + * and thread2.frame(0). Since thread2.frame(2) has to be invalid,
    + * the expected result is false; otherwise, the test FAILED.
    + * (2) to check up on second assertion, gets thread2.frame(1)
    + * which has to result in the IndexOutOfBoundsException because
    + * the current frame is the only one in FramesStack.
    + *
    + */ + +public class popframes005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/popFrames/popframes005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new popframes005().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.popFrames.popframes005a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + BreakpointRequest bpRequest; + BreakpointRequest breakpointRequest2; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + if ( !vm.canPopFrames() ) { + log2("......vm.canPopFrames() == false : test is cancelled"); + vm.resume(); + return; + } + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + log2("......setting BreakpointRequest (bpRequest) in main thread"); + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + log2("bpRequest.enable();"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + label0: + { + vm.resume(); + breakpointForCommunication(); + + String thread2Name = "thread2"; + ThreadReference thread2Ref = threadByName(thread2Name); + + StackFrame stackFrame0 = null; + StackFrame stackFrame1 = null; + StackFrame stackFrame2 = null; + + String breakpointMethod = "breakpointMethod"; + String breakpointLine = "breakpointLine"; + + log2("......setting breakpoint in breakpointMethod"); + breakpointRequest2 = settingBreakpoint(thread2Ref, debuggeeClass, + breakpointMethod, breakpointLine, "one"); + log2("......breakpointRequest2.enable();"); + breakpointRequest2.enable(); + + { // to get mainThread suspended; otherwise its end results in + // no suspention for breakpointRequest2 (bug or not?), end of test, + // and VMDisconnectException + thread2Ref.suspend(); + log2("......eventSet.resume();"); + eventSet.resume(); + breakpointForCommunication(); + log2("bpRequest.disable();"); + bpRequest.disable(); + thread2Ref.resume(); + } + + log2("......breakpointInMethod(breakpointRequest2);"); + breakpointInMethod("one"); + + log2("......stackFrame2 = thread2Ref.frame(2);"); + stackFrame2 = thread2Ref.frame(2); + + log2("......stackFrame1 = thread2Ref.frame(1);"); + stackFrame1 = thread2Ref.frame(1); + + log2("......thread2Ref.popFrames(stackFrame1);"); + try { + thread2Ref.popFrames(stackFrame1); + } catch ( IncompatibleThreadStateException e ) { + log3("ERROR: IncompatibleThreadStateException"); + testExitCode = FAILED; + break label0; + } + log2("......checking up on equality"); + if ( thread2Ref.frame(0).equals(stackFrame2) ) { + log3("ERROR: thread2Ref.frame(0).equals(stackFrame2)"); + testExitCode = FAILED; + } + + log2("......stackFrame1 = thread2Ref.frame(1);"); + try { + stackFrame1 = thread2Ref.frame(1); + log3("ERROR: no IndexOutOfBoundsException"); + testExitCode = FAILED; + } catch ( IndexOutOfBoundsException e ) { + log2(" IndexOutOfBoundsException"); + } + + + log2("......breakpointRequest2.disable();"); + breakpointRequest2.disable(); + + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private void breakpointInMethod(String number) + throws JDITestRuntimeException { + + Event event; + + getEventSet(); + event = eventIterator.nextEvent(); + + if ( !(event instanceof BreakpointEvent) ) + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + + log2("---->: request().getProperty == " + + event.request().getProperty("number")); + + if ( event.request().getProperty("number").equals(number) ) + return; + + throw new JDITestRuntimeException("** UNEXPECTED breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005/TestDescription.java new file mode 100644 index 00000000000..50f03ca86ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005/TestDescription.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/popFrames/popframes005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.popFrames() + * complies with its spec: + * public void popFrames(StackFrame frame) + * throws IncompatibleThreadStateException + * Pop stack frames. + * All frames up to and including the frame are popped off the stack. + * The frame previous to the + * parameter frame will become the current frame. + * After this operation, this thread will be suspended at the invoke + * instruction of the target method that created frame. + * The frame's method can be reentered with a step into the instruction. + * The operand stack is restored, however, any changes to the arguments that + * occurred in the called method, remain. For example, if the method foo: + * void foo(int x) { + * System.out.println("Foo: " + x); + * x = 4; + * System.out.println("pop here"); + * } + * was called with foo(7) and foo is popped at the second println and resumed, + * it will print: Foo: 4. + * Locks acquired by a popped frame are released when it is popped. + * This applies to synchronized methods that are popped, and + * to any synchronized blocks within them. + * Finally blocks are not executed. + * No aspect of state, other than this thread's execution point and locks, + * is affected by this call. Specifically, the values of fields are unchanged, + * as are external resources such as I/O streams. Additionally, + * the target program might be placed in a state that is impossible with + * normal program flow; for example, order of lock acquisition might be + * perturbed. Thus the target program may proceed differently than the user would expect. + * The specified thread must be suspended. + * All StackFrame objects for this thread are invalidated. + * No events are generated by this method. + * None of the frames through and including frame may be native. + * Not all target virtual machines support this operation. Use + * VirtualMachine.canPopFrames() to determine if the operation is supported. + * Parameters: frame - Stack frame to pop. + * frame is on this thread's call stack. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation - see + * VirtualMachine.canPopFrames(). + * IncompatibleThreadStateException - + * if this thread is not suspended. + * IllegalArgumentException - + * if frame is not on this thread's call stack. + * NativeMethodException - + * if one of the frames that would be popped is that of + * a native method or if frame is native. + * InvalidStackFrameException - + * if frame has become invalid. Once this thread is resumed, + * the stack frame is no longer valid. + * The test checks up on the assertions: + * (1) All StackFrame objects for this thread are invalidated. + * (2) The frame previous to the parameter frame will become the current frame. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.popFrames.popframes005; + * the debuggee program - nsk.jdi.ThreadReference.popFrames.popframes005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.popFrames.popframes005 + * nsk.jdi.ThreadReference.popFrames.popframes005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.popFrames.popframes005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005a.java new file mode 100644 index 00000000000..97028a557de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005a.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the popframes005 JDI test. + */ + +public class popframes005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread2popframes005a thread2 = null; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + + + static class JDIDebuggeeException extends Exception { + JDIDebuggeeException(String str) { + super("JDIDebuggeeException : " + str); + } + } + //---------------------------------------------------- main method + + static int var1 = 0; + static volatile int testVar = 0; + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + label0: + { + thread2 = new Thread2popframes005a("thread2"); + log1(" thread2 is created"); + + synchronized (lockingObject2) { + log1(" thread2.start()"); + if ( threadStart(thread2) != PASSED ) + break label0; + + log1(" methodForCommunication();"); + methodForCommunication(); + } + methodForCommunication(); + } + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + log1(" before: waitnotifyObj.wait();"); + waitnotifyObj.wait(); + log1(" after: waitnotifyObj.wait();"); + } catch ( Exception e) { + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static int breakpointLine = 3; + + static void breakpointMethod () { + log1("breakpointMethod entered by the thread : " + Thread.currentThread().getName() ); + var1 += 1; + var1 += 1; + var1 += 1; + log1("breakpointMethod: exit"); + } + + static void poppedMethod() { + log1("poppedMethod entered by the thread : " + Thread.currentThread().getName() ); + + log1("thread2: try clause: calling breakpointMethod();"); + breakpointMethod(); + + log1("poppedMethod: exit"); + return; + } + + static Object lockingObject2 = new Object(); + + static class Thread2popframes005a extends Thread { + + public Thread2popframes005a(String threadName) { + super(threadName); + } + + public void run() { + log1("thread2: method 'run' enter"); + synchronized (waitnotifyObj) { + log1("thread2: entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log1("thread2: exited from block: synchronized (waitnotifyObj)"); + + synchronized (lockingObject2) { + testVar = 0; + log1("thread2: before: 'poppedMethod()'"); + poppedMethod(); + log1("thread2: after: 'poppedMethod()'"); + } + return; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006.java new file mode 100644 index 00000000000..185ec14a7bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006.java @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method:
    + * com.sun.jdi.ThreadReference.popFrames()
    + * properly throws IncompatibleThreadStateException or + * InvalidStackFrameException, if specified thread is resumed. + * + *

    Note, the test is pending decision on the bug:

    + * + * 4512840 JDI spec: for ThreadReference.popFrame() needs clarification

    + * + * Actually, only one exception should be thrown in case of resumed + * thread instead of two ones. + */ +public class popframes006 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ThreadReference.popFrames.popframes006t"; + + // name of debuggee's main thread + static final String DEBUGGEE_THRNAME = "popframes006tThr"; + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = "popframes006tFindMe"; + // debuggee field used to indicate that popping has been done + static final String DEBUGGEE_FIELD = "wasPopped"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 80; + + static final int ATTEMPTS = 5; + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private ObjectReference objRef; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new popframes006().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "popframes006t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef = null; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + Field doExit = null; + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + // debuggee field used to indicate that popping has been done + doExit = rType.fieldByName(DEBUGGEE_FIELD); + + // debuggee stack frame to be popped + StackFrame stFrame = findFrame(thrRef, DEBUGGEE_LOCALVAR); + + log.display("\nTrying to pop stack frame \"" + stFrame + + "\"\n\tlocation \"" + stFrame.location() + + "\"\n\tgot from thread reference \"" + thrRef + + "\"\n\twith resumed debuggee thread ..."); + + log.display("Resuming debuggee ..."); + vm.resume(); + + // wait for the thread resumption + int num = 0; + while (thrRef.isSuspended()) { + if (num > ATTEMPTS) + throw new Failure("unable to continue testing after " + + ATTEMPTS + + " attempts: debuggee thread " + + thrRef + " is not resumed yet"); + + Thread.currentThread().sleep(DELAY); + num++; + } + log.display("Debugee is resumed"); + +// Check the tested assersion + try { + thrRef.popFrames(stFrame); + log.complain("TEST FAILED: expected IncompatibleThreadStateException or InvalidStackFrameException was not thrown" + + "\n\twhen attempted to pop stack frame got from thread reference \"" + + thrRef + "\"\n\twith resumed debuggee thread"); + tot_res = Consts.TEST_FAILED; + // actually, it should be only one expected exception instead of two ones: + // see the bug 4512840 + } catch(IncompatibleThreadStateException ee) { + log.display("CHECK PASSED: caught expected " + ee); + } catch(InvalidStackFrameException ee2) { + log.display("CHECK PASSED: caught expected " + ee2); + } catch(UnsupportedOperationException une) { + if (vm.canPopFrames()) { + une.printStackTrace(); + log.complain("TEST FAILED: caught exception: " + une + + "\n\tHowever, VirtualMachine.canPopFrames() shows, that the target VM" + + "\n\tdoes support popping frames of a threads stack: " + + vm.canPopFrames()); + tot_res = Consts.TEST_FAILED; + } else { + log.display("Warinig: unable to test an assertion: caught exception: " + une + + "\n\tand VirtualMachine.canPopFrames() shows, that the target VM" + + "\n\tdoes not support popping frames of a threads stack as well: " + + vm.canPopFrames()); + } + + } catch(Exception ue) { + ue.printStackTrace(); + log.complain("TEST FAILED: ThreadReference.popFrames(): caught unexpected " + + ue + "\n\tinstead of IncompatibleThreadStateException or InvalidStackFrameException" + + "\n\twhen attempted to pop stack frame got from thread reference \"" + + thrRef + "\"\n\twith resumed debuggee thread"); + tot_res = Consts.TEST_FAILED; + } + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } finally { +// Finish the test + // force an method to exit + if (objRef != null && doExit != null) { + try { + objRef.setValue(doExit, vm.mirrorOf(true)); + } catch(Exception sve) { + sve.printStackTrace(); + } + } + } + + return quitDebuggee(); + } + + private StackFrame findFrame(ThreadReference thrRef, String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = + stackFr.visibleVariableByName(varName); + // visible variable with the given name is found + if (locVar != null) { + objRef = (ObjectReference) + stackFr.getValue(locVar); + return stackFr; + } + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findFrame: caught unexpected exception: " + e); + } + throw new Failure("findFrame: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("Final resumption of debuggee VM"); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006/TestDescription.java new file mode 100644 index 00000000000..f181e7e6903 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/popFrames/popframes006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method: + * com.sun.jdi.ThreadReference.popFrames() + * properly throws IncompatibleThreadStateException or + * InvalidStackFrameException, if specified thread is resumed. + * COMMENTS + * Note, the test is pending decision on the bug: + * 4512840 JDI spec: for ThreadReference.popFrame() needs clarification + * Actually, only one exception should be thrown in case of resumed + * thread instead of two ones. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.popFrames.popframes006 + * nsk.jdi.ThreadReference.popFrames.popframes006t + * + * @comment make sure popframes006t is compiled with full debug info + * @clean nsk.jdi.ThreadReference.popFrames.popframes006t + * @compile -g:lines,source,vars ../popframes006t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.popFrames.popframes006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006t.java new file mode 100644 index 00000000000..73e70052c60 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes006t.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class popframes006t { + private Log log; + private IOPipe pipe; + volatile boolean wasPopped = false; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new popframes006t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(popframes006.DEBUGGEE_THRNAME); + + pipe.println(popframes006.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(popframes006.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + frameToBePopped(); + + cmd = pipe.readln(); + if (!cmd.equals(popframes006.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + return Consts.TEST_FAILED; + } + return Consts.TEST_PASSED; + } + + private void frameToBePopped() { + popframes006t popframes006tFindMe = this; + + log.display("frameToBePopped: enter frameToBePopped()"); + + int stopMeHere = 0; // popframes006.DEBUGGEE_STOPATLINE + + while(!wasPopped) { // looping + stopMeHere++; stopMeHere--; + } + + log.display("frameToBePopped: leaving frameToBePopped()"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007.java new file mode 100644 index 00000000000..c4c25cd2a40 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007.java @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The test checks that the JDI method:
    + * com.sun.jdi.ThreadReference.popFrames()
    + * properly throws IllegalArgumentException - if frame is not + * on specified thread's call stack.

    + * + * The target VM executes two debuggee threads: popframes007tMainThr + * and popframes007tAuxThr. Debugger part of the test tries to + * pop stack frame of the popframes007tAuxThr thread using + * reference of the popframes007tMainThr thread. + */ +public class popframes007 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ThreadReference.popFrames.popframes007t"; + + // names of debuggee threads + static final String DEBUGGEE_THRDS[] = { + "popframes007tMainThr", "popframes007tAuxThr" + }; + // debuggee local var used to find needed stack frame + static final String DEBUGGEE_LOCALVAR = "popframes007tFindMe"; + // debuggee field used to indicate that popping has been done + static final String DEBUGGEE_FIELD = "leaveMethod"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 83; + + static final int ATTEMPTS = 5; + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private ObjectReference objRef; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new popframes007().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "popframes007t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef[] = new ThreadReference[2]; + for (int i=0; i<2; i++) + if ((thrRef[i] = + debuggee.threadByName(DEBUGGEE_THRDS[i])) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRDS[i]); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + Field doExit = null; + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + + // debuggee field used to indicate that popping has been done + doExit = rType.fieldByName(DEBUGGEE_FIELD); + + // debuggee stack frame to be popped which is not on specified thread's call stack + StackFrame stFrame = findFrame(thrRef[1], DEBUGGEE_LOCALVAR); + + log.display("\nTrying to pop stack frame \"" + stFrame + + "\"\n\tlocation \"" + stFrame.location() + + "\"\n\tgot from thread reference \"" + thrRef[1] + + "\"\n\tand the frame is not on the following thread's call stack: \"" + + thrRef[0] + "\" ..."); + +// Check the tested assersion + try { + thrRef[0].popFrames(stFrame); + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to pop stack frame \"" + stFrame + + "\"\n\tlocation \"" + stFrame.location() + + "\"\n\tgot from thread reference \"" + thrRef[1] + + "\"\n\tand the frame is not on the following thread's call stack: \"" + + thrRef[0] + "\""); + tot_res = Consts.TEST_FAILED; + } catch(IllegalArgumentException ee) { + log.display("CHECK PASSED: caught expected " + ee); + } catch(UnsupportedOperationException une) { + if (vm.canPopFrames()) { + une.printStackTrace(); + log.complain("TEST FAILED: caught exception: " + une + + "\n\tHowever, VirtualMachine.canPopFrames() shows, that the target VM" + + "\n\tdoes support popping frames of a threads stack: " + + vm.canPopFrames()); + tot_res = Consts.TEST_FAILED; + } else { + log.display("Warinig: unable to test an assertion: caught exception: " + une + + "\n\tand VirtualMachine.canPopFrames() shows, that the target VM" + + "\n\tdoes not support popping frames of a threads stack as well: " + + vm.canPopFrames()); + } + } catch(Exception ue) { + ue.printStackTrace(); + log.complain("TEST FAILED: ThreadReference.popFrames(): caught unexpected " + + ue + "\n\tinstead of IllegalArgumentException" + + "\n\twhen attempted to pop stack \"" + stFrame + + "\"\n\tlocation \"" + stFrame.location() + + "\"\n\tgot from thread reference \"" + thrRef[1] + + "\"\n\tand the frame is not on the following thread's call stack: \"" + + thrRef[0] + "\""); + tot_res = Consts.TEST_FAILED; + } + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } finally { +// Finish the test + // force an method to exit + if (objRef != null && doExit != null) { + try { + objRef.setValue(doExit, vm.mirrorOf(true)); + } catch(Exception sve) { + sve.printStackTrace(); + } + } + } + + return quitDebuggee(); + } + + private StackFrame findFrame(ThreadReference thrRef, String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = + stackFr.visibleVariableByName(varName); + // visible variable with the given name is found + if (locVar != null) { + objRef = (ObjectReference) + stackFr.getValue(locVar); + return stackFr; + } + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findFrame: caught unexpected exception: " + e); + } + throw new Failure("findFrame: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("Final resumption of debuggee VM"); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007/TestDescription.java new file mode 100644 index 00000000000..8bc0a33aad4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/popFrames/popframes007. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method: + * com.sun.jdi.ThreadReference.popFrames() + * properly throws IllegalArgumentException - if frame is not + * on this thread's call stack. + * The target VM executes two debuggee threads: "popframes007tMainThr" + * and "popframes007tAuxThr". Debugger part of the test tries to + * pop stack frame of the popframes007tAuxThr thread using + * reference of the popframes007tMainThr thread. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.popFrames.popframes007 + * nsk.jdi.ThreadReference.popFrames.popframes007t + * + * @comment make sure popframes007t is compiled with full debug info + * @clean nsk.jdi.ThreadReference.popFrames.popframes007t + * @compile -g:lines,source,vars ../popframes007t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.popFrames.popframes007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007t.java new file mode 100644 index 00000000000..a6eb18078db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes007t.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadReference.popFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class popframes007t { + private Log log; + private IOPipe pipe; + private OtherThr auxThr; + volatile boolean leaveMethod = false; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new popframes007t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(popframes007.DEBUGGEE_THRDS[0]); + startThread(); + + // Now the debuggee is ready for testing + pipe.println(popframes007.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(popframes007.COMMAND_QUIT)) { + killThread(argHandler.getWaitTime()*60000); + log.complain("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + frameToBePopped(); + + cmd = pipe.readln(); + killThread(argHandler.getWaitTime()*60000); + if (!cmd.equals(popframes007.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + return Consts.TEST_FAILED; + } + return Consts.TEST_PASSED; + } + + private void frameToBePopped() { + log.display("frameToBePopped: enter frameToBePopped()"); + + int stopMeHere = 0; // popframes007.DEBUGGEE_STOPATLINE + + while(!leaveMethod) { // looping + stopMeHere++; stopMeHere--; + } + + log.display("frameToBePopped: leaving frameToBePopped()"); + } + + private void startThread() { + Object readyObj = new Object(); + + auxThr = new OtherThr(readyObj, + popframes007.DEBUGGEE_THRDS[1], this); + auxThr.setDaemon(true); + + log.display("Debuggee: starting thread \"" + + auxThr.getName() + "\" ..."); + synchronized(readyObj) { + auxThr.start(); + try { + readyObj.wait(); // wait for the thread's readiness + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: waiting for the thread " + + auxThr + " start: caught " + e); + pipe.println("failed"); + System.exit(Consts.JCK_STATUS_BASE + + Consts.TEST_FAILED); + } + } + log.display("Debuggee: the thread \"" + + auxThr.getName() + "\" started"); + } + + private void killThread(int waitTime) { + auxThr.doExit = true; + try { + auxThr.join(waitTime); + log.display("Debuggee: thread \"" + + auxThr.getName() + "\" done"); + } catch (InterruptedException e) { + log.complain("TEST FAILURE: Debuggee: joining the thread \"" + + auxThr.getName() + "\": caught " + e); + } + } + + /** + * This is an auxiliary thread class used to check frame popping + * in the debugger. + */ + class OtherThr extends Thread { + volatile boolean doExit = false; + private Object readyObj; + private popframes007t mainThrObj; + + OtherThr(Object readyObj, String name, popframes007t mainThrObj) { + super(name); + this.readyObj = readyObj; + this.mainThrObj = mainThrObj; + } + + public void run() { + // var used by debugger for searching needed stack frame + popframes007t popframes007tFindMe = mainThrObj; + + Thread thr = Thread.currentThread(); + + synchronized(readyObj) { + readyObj.notify(); // notify the main thread + } + log.display("Debuggee thread \"" + + thr.getName() + "\": going to loop"); + while(!doExit) { + int i = 0; + i++; i--; + + // reliable analogue of Thread.yield() + synchronized(this) { + try { + this.wait(30); + } catch (InterruptedException e) { + e.printStackTrace(log.getOutStream()); + log.complain("TEST FAILURE: Debuggee thread \"" + + thr.getName() + + "\" interrupted while sleeping:\n\t" + e); + break; + } + } + } + log.display("Debuggee thread \"" + + thr.getName() + "\" exiting ..."); + } + } +///////////////////////////////////////////////////////////////////////////// + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001.java new file mode 100644 index 00000000000..58ab1a1c4c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001.java @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.resume()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since thread2 uses the same locking object in its 'run' method
    + * it is locked up until first thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up breakpoints within thread2's two methods and checks up that
    + * call to the method thread2.resume() has no effect when the thread2
    + * is not suspended but is just waiting at a synchronized block, and
    + * resumes the thread2 when it is suspended:
    + * - with thread2.suspend()
    + * - at a breakpoint
    + * - with VirtualMachine.suspend()
    + */ + +public class resume001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/resume/resume001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new resume001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.resume.resume001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.resume.Threadresume001a"; + + //String mName = "nsk.jdi.ThreadReference.resume"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + BreakpointRequest breakpRequest3 = null; + + int suspCount = 0; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest3 = settingBreakpoint(breakpointMethod1, bpLine3, "three"); + if (breakpRequest3 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + + log2("......checking up that thread2.resume() has no effect to not suspended thread"); + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" resuming the thread2"); + thread2.resume(); + + log2(" checking up that the thread2 is not at breakpoint"); + if (thread2.isAtBreakpoint()) { + log3("ERROR: thread2.isAtBreakpoint() ???"); + expresult = returnCode1; + } + log2(" checking up that thread2's suspendCount == 0"); + if (thread2.suspendCount() != 0) { + log3("ERROR: thread2.suspendCount() != 0 ???"); + expresult = returnCode1; + } + + log2(" disabling breakpRequest1"); + breakpRequest1.disable(); + + if (expresult != returnCode0) + break label1; + + + log2("......checking up that thread2.resume() resumes thread2 suspended with thread2.suspend()"); + + log2(" suspending the thread2 with thread2.suspend()"); + thread2.suspend(); + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + log2(" resuming the thread2"); + thread2.resume(); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + + log2("......checking up that thread2.resume() resumes thread2 suspended at a breakpoint"); + + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + + log2(" resuming the thread2"); + thread2.resume(); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + + log2("......checking up that thread2.resume() resumes thread2 suspended with VirtualMachine.suspend()"); + + log2(" enabling breakpRequest3"); + breakpRequest3.enable(); + log2(" suspending the thread2 with vm.suspend()"); + vm.suspend(); + log2(" first resuming the thread2 with eventSet.resume()"); + eventSet.resume(); + log2(" checking up thread's state"); + if (thread2.isSuspended()) { + log2(" : thread2.isSuspended()"); + } else { + log3("ERROR: !thread2.isSuspended()"); + expresult = returnCode1; + break label1; + } + log2(" second resuming the thread2 with thread2.resume()"); + thread2.resume(); + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + + log2(" resuming the thread2"); + thread2.resume(); + + } + vm.resume(); + vm.resume(); // for case error when both VirtualMachine and the thread2 were suspended + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001/TestDescription.java new file mode 100644 index 00000000000..aca24385791 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/resume/resume001. + * VM Testbase keywords: [quick, jpda, jdi, quarantine] + * VM Testbase comments: JDK-8072701 + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.resume() + * complies with its spec: + * public void resume() + * Resumes this thread. If this thread was not previously suspended through + * suspend() or through VirtualMachine.suspend(), invoking this method + * has no effect. Otherwise, the count of pending suspends on this thread + * is decremented. If it is decremented to 0, + * the thread will continue to execute. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.resume.resume001; + * the debuggee program - nsk.jdi.ThreadReference.resume.resume001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.resume.resume001 + * nsk.jdi.ThreadReference.resume.resume001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.resume.resume001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001a.java new file mode 100644 index 00000000000..9f3b7da3c1d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/resume/resume001a.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.resume; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the resume001 JDI test. + */ + +public class resume001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggee.receiveExpectedSignal(SIGNAL_GO); + check(status003a.testedThreadNames[0], "CHECK1", "CHECK2"); + check(status003a.testedThreadNames[1], "CHECK3", "CHECK4"); + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static String getThreadStatusName (int status) { + switch (status) { + case ThreadReference.THREAD_STATUS_UNKNOWN: + return "THREAD_STATUS_UNKNOWN"; + case ThreadReference.THREAD_STATUS_ZOMBIE: + return "THREAD_STATUS_ZOMBIE"; + case ThreadReference.THREAD_STATUS_RUNNING: + return "THREAD_STATUS_RUNNING"; + case ThreadReference.THREAD_STATUS_SLEEPING: + return "THREAD_STATUS_SLEEPING"; + case ThreadReference.THREAD_STATUS_MONITOR: + return "THREAD_STATUS_MONITOR"; + case ThreadReference.THREAD_STATUS_WAIT: + return "THREAD_STATUS_WAIT"; + case ThreadReference.THREAD_STATUS_NOT_STARTED: + return "THREAD_STATUS_NOT_STARTED"; + default: + return "ERROR: Unknown ThreadReference status " + status; + } + } + + private static void check (String threadName, String check1, String check2) { + ThreadReference testedThread = (ThreadReference)debuggeeClass.getValue(debuggeeClass.fieldByName(threadName)); + int threadStatus = testedThread.status(); + + if (threadStatus == ThreadReference.THREAD_STATUS_ZOMBIE) { + display(check1 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_ZOMBIE for unsuspended " + threadName); + } else { + complain(check1 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus)+ " for unsuspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_ZOMBIE)); + exitStatus = Consts.TEST_FAILED; + } + + try { + testedThread.suspend(); + threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_ZOMBIE) { + display(check2 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_ZOMBIE for suspended " + threadName); + } else { + complain(check2 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus) + " for suspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_ZOMBIE)); + exitStatus = Consts.TEST_FAILED; + } + testedThread.resume(); + } catch (Exception e) { + complain(check2 + " FAILED"); + complain("\t Unexpected exception while calling ThreadReference.suspend() for " + threadName + " : " + e); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status003/status003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status003/status003a.java new file mode 100644 index 00000000000..09ead2f35e1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status003/status003a.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ThreadReference.status.status003; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class status003a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static String testedThreadNames[] = {"finishedThread", "interruptedThread"}; + static Thread finishedThread; + static Thread interruptedThread; + + static Wicket wicket1 = new Wicket(); + static Wicket wicket2 = new Wicket(); + static Object lock = new Object(); + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(status003.SIGNAL_READY); + + finishedThread = new status003aThreadFinished(testedThreadNames[0]); + display(finishedThread.getName() + " is created"); + + finishedThread.start(); + wicket1.waitFor(); + waitForFinish(finishedThread); + + interruptedThread = new status003aThreadInterrupted(testedThreadNames[1]); + display(interruptedThread.getName() + " is created"); + + synchronized (lock) { + interruptedThread.start(); + wicket2.waitFor(); + + interruptedThread.interrupt(); + if (!interruptedThread.isInterrupted()) { + throw new Failure(interruptedThread.getName() + " has not been interrupted"); + } + } + waitForFinish(interruptedThread); + + pipe.println(status003.SIGNAL_GO); + receiveSignal(status003.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void waitForFinish (Thread thread) { + if (thread.isAlive()) { + try { + thread.join(argHandler.getWaitTime() * 60000); + display(thread.getName() + " is finished"); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for join of " + thread.getName()); + } + if (thread.isAlive()) { + throw new Failure(thread.getName() + " has not finished after " + argHandler.getWaitTime() + " mins"); + } + } + } + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class status003aThreadFinished extends Thread { + status003aThreadFinished (String name) { + super(name); + } + + public void run () { + status003a.wicket1.unlock(); + status003a.display(Thread.currentThread().getName() + " finished."); + } +} + +class status003aThreadInterrupted extends Thread { + status003aThreadInterrupted (String name) { + super(name); + } + + public void run () { + status003a.wicket2.unlock(); + synchronized (status003a.lock) {}; + status003a.display(Thread.currentThread().getName() + " finished."); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status004/status004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status004/status004.java new file mode 100644 index 00000000000..7ec88df60e3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status004/status004.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/status/status004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for status() method of ThreadReference interface. + * The test checks if the method returns + * ThreadReference.THREAD_STATUS_MONITOR status for debuggee's + * thread when it contends to lock a monitor. + * The test has two cases: + * - thread is blocked on enter of synchronized method, + * - thread is blocked on enter of synchronized statement. + * The test checks status of unsuspended and suspended thread in + * both cases. + * The test consists of a debugger program (status004.java) + * and debuggee application (status004a.java). + * Package name is nsk.jdi.ThreadReference.status. + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * In both test cases the debuggee starts special axiliary threads. + * After notification of readiness from debuggee, the debugger + * checks if ThreadReference.status() returns expected status + * for checked thread. Then the debugger suspends the checked + * thread and checks its status again. + * The test fails if status() method returned a status code + * other then expected THREAD_STATUS_MONITOR one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.status.status004.status004 + * nsk.jdi.ThreadReference.status.status004.status004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.status.status004.status004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.status.status004; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.ThreadReference; + +//import com.sun.jdi.request.*; +//import com.sun.jdi.event.*; +//import com.sun.jdi.connect.*; +import java.io.*; +//import java.util.*; + +/** + * The debugger application of the test. + */ +public class status004 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ThreadReference.status.status004."; + private final static String className = "status004"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String testedThreadName = prefix + "status004aThread"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggee.receiveExpectedSignal(SIGNAL_GO); + check(status004a.testedThreadNames[0], "CHECK1", "CHECK2"); + check(status004a.testedThreadNames[1], "CHECK3", "CHECK4"); + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static String getThreadStatusName (int status) { + switch (status) { + case ThreadReference.THREAD_STATUS_UNKNOWN: + return "THREAD_STATUS_UNKNOWN"; + case ThreadReference.THREAD_STATUS_ZOMBIE: + return "THREAD_STATUS_ZOMBIE"; + case ThreadReference.THREAD_STATUS_RUNNING: + return "THREAD_STATUS_RUNNING"; + case ThreadReference.THREAD_STATUS_SLEEPING: + return "THREAD_STATUS_SLEEPING"; + case ThreadReference.THREAD_STATUS_MONITOR: + return "THREAD_STATUS_MONITOR"; + case ThreadReference.THREAD_STATUS_WAIT: + return "THREAD_STATUS_WAIT"; + case ThreadReference.THREAD_STATUS_NOT_STARTED: + return "THREAD_STATUS_NOT_STARTED"; + default: + return "ERROR: Unknown ThreadReference status " + status; + } + } + + private static void check (String threadName, String check1, String check2) { + ThreadReference testedThread = (ThreadReference)debuggeeClass.getValue(debuggeeClass.fieldByName(threadName)); + + // wait during waitTime until testedThread has been blocked on monitor + boolean monitorReached = false; + if (debuggee.VM().canGetCurrentContendedMonitor()) { + try { + long oldTime = System.currentTimeMillis(); + while (!monitorReached && (System.currentTimeMillis() - oldTime) <= status004.waitTime) { + testedThread.suspend(); + ObjectReference monitor = testedThread.currentContendedMonitor(); + testedThread.resume(); + + if (monitor != null && monitor.referenceType().name().equals(prefix + "Lock")) { + display("ThreadReference.currentContendedMonitor() returned correct monitor reference for " + threadName); + monitorReached = true; + } else { + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException e) { + display("Debugger's main thread was interrupted while sleeping "); + } + } + } + } catch (Exception e) { + complain("Unexpected exception while waiting until " + threadName + " has been blocked : " + e); + exitStatus = Consts.TEST_FAILED; + } + } else { + display("WARNING: ThreadReference.currentContendedMonitor() was not checked for " + threadName); + monitorReached = true; + } + if (!monitorReached) { + complain("Tested " + threadName + " has not been blocked on monitor"); + exitStatus = Consts.TEST_FAILED; + + } else { + int threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_MONITOR) { + display(check1 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_MONITOR for unsuspended " + threadName); + } else { + complain(check1 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus)+ " for unsuspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_MONITOR)); + exitStatus = Consts.TEST_FAILED; + } + + try { + testedThread.suspend(); + threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_MONITOR) { + display(check2 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_MONITOR for suspended " + threadName); + } else { + complain(check2 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus) + " for suspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_MONITOR)); + exitStatus = Consts.TEST_FAILED; + } + testedThread.resume(); + } catch (Exception e) { + complain(check2 + " FAILED"); + complain("\t Unexpected exception while calling ThreadReference.suspend for " + threadName + " : " + e); + exitStatus = Consts.TEST_FAILED; + } + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status004/status004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status004/status004a.java new file mode 100644 index 00000000000..32e046a7833 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status004/status004a.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ThreadReference.status.status004; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class status004a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static String testedThreadNames[] = {"threadBlockedOnMethod", "threadBlockedOnStatmt"}; + static status004aThreadBlockedOnMethod threadBlockedOnMethod; + static status004aThreadBlockedOnStatmt threadBlockedOnStatmt; + + static Wicket wickets[] = { new Wicket(), new Wicket() }; + static Lock lock = new Lock(); + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(status004.SIGNAL_READY); + + threadBlockedOnMethod = new status004aThreadBlockedOnMethod(testedThreadNames[0]); + threadBlockedOnStatmt = new status004aThreadBlockedOnStatmt(testedThreadNames[1]); + + synchronized (lock) { + threadBlockedOnMethod.start(); + wickets[0].waitFor(); + + threadBlockedOnStatmt.start(); + wickets[1].waitFor(); + + pipe.println(status004.SIGNAL_GO); + receiveSignal(status004.SIGNAL_QUIT); + } + + waitForFinish(threadBlockedOnMethod); + waitForFinish(threadBlockedOnStatmt); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void waitForFinish (Thread thread) { + if (thread.isAlive()) { + try { + thread.join(argHandler.getWaitTime() * 60000); + display(thread.getName() + " is finished"); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for join of " + thread.getName()); + } + if (thread.isAlive()) { + throw new Failure(thread.getName() + " has not finished after " + argHandler.getWaitTime() + " mins"); + } + } + } + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class Lock { + synchronized void foo () {} +} + + +class status004aThreadBlockedOnMethod extends Thread { + status004aThreadBlockedOnMethod (String name) { + super(name); + } + + public void run () { + status004a.wickets[0].unlock(); + synchronized (status004a.lock) {}; + } +} + +class status004aThreadBlockedOnStatmt extends Thread { + status004aThreadBlockedOnStatmt (String name) { + super(name); + } + + public void run () { + status004a.wickets[1].unlock(); + status004a.lock.foo(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status005/status005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status005/status005.java new file mode 100644 index 00000000000..b445b72988a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status005/status005.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/status/status005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for status() method of ThreadReference interface. + * The test checks if the method returns + * ThreadReference.THREAD_STATUS_WAIT status for + * debuggee's thread when it performs Object.wait() call. + * The test has two cases: + * - for Object.wait() call, + * - for Object.wait(long) call. + * The test checks status of unsuspended and suspended thread in + * both cases. + * The test consists of a debugger program (status005.java) + * and debuggee application (status005a.java). + * Package name is nsk.jdi.ThreadReference.status. + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * In both test cases the debuggee starts special axiliary threads. + * After notification of readiness from debuggee, the debugger + * checks if ThreadReference.status() returns expected status + * for checked thread. Then the debugger suspends the checked + * thread and checks its status again. + * The test fails if status() method returned a status code + * other then expected THREAD_STATUS_WAIT one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.status.status005.status005 + * nsk.jdi.ThreadReference.status.status005.status005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.status.status005.status005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.status.status005; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.ThreadReference; + +//import com.sun.jdi.request.*; +//import com.sun.jdi.event.*; +//import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class status005 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ThreadReference.status.status005."; + private final static String className = "status005"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String testedThreadName = prefix + "status005aThread"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggee.receiveExpectedSignal(SIGNAL_GO); + check(status005a.testedThreadNames[0], "CHECK1", "CHECK2"); + check(status005a.testedThreadNames[1], "CHECK3", "CHECK4"); + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static String getThreadStatusName (int status) { + switch (status) { + case ThreadReference.THREAD_STATUS_UNKNOWN: + return "THREAD_STATUS_UNKNOWN"; + case ThreadReference.THREAD_STATUS_ZOMBIE: + return "THREAD_STATUS_ZOMBIE"; + case ThreadReference.THREAD_STATUS_RUNNING: + return "THREAD_STATUS_RUNNING"; + case ThreadReference.THREAD_STATUS_SLEEPING: + return "THREAD_STATUS_SLEEPING"; + case ThreadReference.THREAD_STATUS_MONITOR: + return "THREAD_STATUS_MONITOR"; + case ThreadReference.THREAD_STATUS_WAIT: + return "THREAD_STATUS_WAIT"; + case ThreadReference.THREAD_STATUS_NOT_STARTED: + return "THREAD_STATUS_NOT_STARTED"; + default: + return "ERROR: Unknown ThreadReference status " + status; + } + } + + private static void check (String threadName, String check1, String check2) { + ThreadReference testedThread = (ThreadReference)debuggeeClass.getValue(debuggeeClass.fieldByName(threadName)); + ObjectReference lockRef = (ObjectReference)debuggeeClass.getValue(debuggeeClass.fieldByName("lock")); + + // wait during waitTime until testedThread becomes waiting notification + boolean waitingNotify = false; + if (debuggee.VM().canGetMonitorInfo()) { + try { + long oldTime = System.currentTimeMillis(); + while (!waitingNotify && (System.currentTimeMillis() - oldTime) <= status005.waitTime) { + + debuggee.VM().suspend(); + + Iterator waitingThreads = lockRef.waitingThreads().iterator(); + while (waitingThreads.hasNext()) { + ThreadReference threadRef = (ThreadReference)waitingThreads.next(); + if (threadRef.equals(testedThread)) { + waitingNotify = true; + display("ObjectReference.waitingThreads() contains expected reference to " + threadName); + } + } + + debuggee.VM().resume(); + + if (!waitingNotify) { + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException e) { + display("Debugger's main thread was interrupted while sleeping "); + } + } + } + } catch (Exception e) { + complain("Unexpected exception while waiting until " + threadName + " set on waiting state: " + e); + exitStatus = Consts.TEST_FAILED; + } + } else { + display("WARNING: ObjectReference.waitingThreads() was not checked for " + threadName); + waitingNotify = true; + } + if (!waitingNotify) { + complain("Tested " + threadName + " did not wait "); + exitStatus = Consts.TEST_FAILED; + + } else { + int threadStatus = testedThread.status(); + + if (threadStatus == ThreadReference.THREAD_STATUS_WAIT) { + display(check1 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_WAIT for unsuspended " + threadName); + } else { + complain(check1 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus) + " for unsuspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_WAIT)); + exitStatus = Consts.TEST_FAILED; + } + + try { + testedThread.suspend(); + threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_WAIT) { + display(check2 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_WAIT for suspended " + threadName); + } else { + complain(check2 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus)+ " for suspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_WAIT)); + exitStatus = Consts.TEST_FAILED; + } + testedThread.resume(); + } catch (Exception e) { + complain(check2 + " FAILED"); + complain("\t Unexpected exception while calling ThreadReference.suspend for " + threadName + " : " + e); + exitStatus = Consts.TEST_FAILED; + } + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status005/status005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status005/status005a.java new file mode 100644 index 00000000000..5dac6645b49 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status005/status005a.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ThreadReference.status.status005; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class status005a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static Log log; + private static IOPipe pipe; + static ArgumentHandler argHandler; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static String testedThreadNames[] = {"threadWaitingInfinitely", "threadWaitingLong"}; + static status005aThreadWaitingInfinitely threadWaitingInfinitely; + static status005aThreadWaitingLong threadWaitingLong; + + static Wicket wickets[] = { new Wicket(), new Wicket() }; + static Lock lock = new Lock(); + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(status005.SIGNAL_READY); + + threadWaitingInfinitely = new status005aThreadWaitingInfinitely(testedThreadNames[0]); + threadWaitingLong = new status005aThreadWaitingLong(testedThreadNames[1]); + + threadWaitingInfinitely.start(); + wickets[0].waitFor(); + + threadWaitingLong.start(); + wickets[1].waitFor(); + + pipe.println(status005.SIGNAL_GO); + receiveSignal(status005.SIGNAL_QUIT); + + synchronized (lock) { + lock.notifyAll(); + } + + waitForFinish(threadWaitingInfinitely); + waitForFinish(threadWaitingLong); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void waitForFinish (Thread thread) { + if (thread.isAlive()) { + try { + thread.join(argHandler.getWaitTime() * 60000); + display(thread.getName() + " is finished"); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for join of " + thread.getName()); + } + if (thread.isAlive()) { + throw new Failure(thread.getName() + " has not finished after " + argHandler.getWaitTime() + " mins"); + } + } + } + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class Lock { + synchronized void foo () {} +} + + +class status005aThreadWaitingInfinitely extends Thread { + status005aThreadWaitingInfinitely (String name) { + super(name); + } + + public void run () { + status005a.wickets[0].unlock(); + synchronized (status005a.lock) { + try { + status005a.lock.wait(); + } catch (InterruptedException e) { + throw new Failure(Thread.currentThread().getName() + ": Unexpected InterruptedException while waiting"); + } + } + } +} + +class status005aThreadWaitingLong extends Thread { + status005aThreadWaitingLong (String name) { + super(name); + } + + public void run () { + status005a.wickets[1].unlock(); + synchronized (status005a.lock) { + try { + status005a.lock.wait(status005a.argHandler.getWaitTime() * 60000 * 2); + } catch (InterruptedException e) { + throw new Failure(Thread.currentThread().getName() + ": Unexpected InterruptedException while waiting"); + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status006/status006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status006/status006.java new file mode 100644 index 00000000000..95b60ed1a98 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status006/status006.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/status/status006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for status() method of ThreadReference interface. + * The test checks if the method returns + * ThreadReference.THREAD_STATUS_SLEEPING status for + * debuggee's thread when it performs Thread.sleep() call. + * The test has two cases: + * - for Thread.sleep(long) call, + * - for Thread.sleep(long, int) call. + * The test checks status of unsuspended and suspended thread + * in both cases. + * The test consists of a debugger program (status006.java) + * and debuggee application (status006a.java). + * Package name is nsk.jdi.ThreadReference.status. + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * In both test cases the debuggee starts special axiliary threads. + * These threads call Thread.sleep() before checking. After + * notification of readiness from debuggee, the debugger + * checks if ThreadReference.status() returns expected status + * for checked thread. Then the debugger suspends the checked + * thread and checks its status again. + * The test fails if status() method returned a status code + * other then expected THREAD_STATUS_SLEEPING one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.status.status006.status006 + * nsk.jdi.ThreadReference.status.status006.status006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.status.status006.status006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.status.status006; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.ThreadReference; + +//import com.sun.jdi.request.*; +//import com.sun.jdi.event.*; +//import com.sun.jdi.connect.*; +import java.io.*; +//import java.util.*; + +/** + * The debugger application of the test. + */ +public class status006 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ThreadReference.status.status006."; + private final static String className = "status006"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + final static String SIGNAL_NEXT = "next"; + + private final static String testedThreadName = prefix + "status006aThread"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggee.receiveExpectedSignal(SIGNAL_GO); + check(status006a.testedThreadNames[0], "CHECK1", "CHECK2"); + debuggee.sendSignal(SIGNAL_NEXT); + debuggee.receiveExpectedSignal(SIGNAL_GO); + check(status006a.testedThreadNames[1], "CHECK3", "CHECK4"); + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static String getThreadStatusName (int status) { + switch (status) { + case ThreadReference.THREAD_STATUS_UNKNOWN: + return "THREAD_STATUS_UNKNOWN"; + case ThreadReference.THREAD_STATUS_ZOMBIE: + return "THREAD_STATUS_ZOMBIE"; + case ThreadReference.THREAD_STATUS_RUNNING: + return "THREAD_STATUS_RUNNING"; + case ThreadReference.THREAD_STATUS_SLEEPING: + return "THREAD_STATUS_SLEEPING"; + case ThreadReference.THREAD_STATUS_MONITOR: + return "THREAD_STATUS_MONITOR"; + case ThreadReference.THREAD_STATUS_WAIT: + return "THREAD_STATUS_WAIT"; + case ThreadReference.THREAD_STATUS_NOT_STARTED: + return "THREAD_STATUS_NOT_STARTED"; + default: + return "ERROR: Unknown ThreadReference status " + status; + } + } + + private static void check (String threadName, String check1, String check2) { + ThreadReference testedThread = (ThreadReference)debuggeeClass.getValue(debuggeeClass.fieldByName(threadName)); + + boolean threadWasSleeping = false; + int threadStatus = ThreadReference.THREAD_STATUS_UNKNOWN; + + // check up to 20 times if tested thread was sleeping + for (int i = 0; !threadWasSleeping && i < 20; i++) { + + threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_SLEEPING) { + threadWasSleeping = true; + } else { + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException e) { + display("Debugger's main thread was interrupted while sleeping "); + } + } + } + + if (threadWasSleeping) { + display(check1 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_SLEEPING for unsuspended " + threadName); + } else { + complain(check1 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus) + " for unsuspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_SLEEPING)); + exitStatus = Consts.TEST_FAILED; + } + + try { + testedThread.suspend(); + threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_SLEEPING) { + display(check2 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_SLEEPING for suspended " + threadName); + } else { + complain(check2 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus) + " for suspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_SLEEPING)); + exitStatus = Consts.TEST_FAILED; + } + testedThread.resume(); + } catch (Exception e) { + complain(check2 + " FAILED"); + complain("\t Unexpected exception while calling ThreadReference.suspend for " + threadName + " : " + e); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status006/status006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status006/status006a.java new file mode 100644 index 00000000000..fe3f517172d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status006/status006a.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ThreadReference.status.status006; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class status006a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static Log log; + private static IOPipe pipe; + static ArgumentHandler argHandler; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static String testedThreadNames[] = {"threadSleepingLong", "threadSleepingLongInt"}; + static status006aThreadSleepingLong threadSleepingLong; + static status006aThreadSleepingLongInt threadSleepingLongInt; + static Wicket wickets[] = { new Wicket(), new Wicket() }; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(status006.SIGNAL_READY); + + threadSleepingLong = new status006aThreadSleepingLong(testedThreadNames[0]); + threadSleepingLong.start(); + wickets[0].waitFor(); + + pipe.println(status006.SIGNAL_GO); + receiveSignal(status006.SIGNAL_NEXT); + threadSleepingLong.interrupt(); + + threadSleepingLongInt = new status006aThreadSleepingLongInt(testedThreadNames[1]); + threadSleepingLongInt.start(); + wickets[1].waitFor(); + + pipe.println(status006.SIGNAL_GO); + receiveSignal(status006.SIGNAL_QUIT); + threadSleepingLongInt.interrupt(); + + waitForFinish(threadSleepingLong); + waitForFinish(threadSleepingLongInt); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void waitForFinish (Thread thread) { + if (thread.isAlive()) { + try { + thread.join(argHandler.getWaitTime() * 60000); + display(thread.getName() + " is finished"); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for join of " + thread.getName()); + } + if (thread.isAlive()) { + throw new Failure(thread.getName() + " has not finished after " + argHandler.getWaitTime() + " mins"); + } + } + } + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class status006aThreadSleepingLong extends Thread { + status006aThreadSleepingLong (String name) { + super(name); + } + + public void run () { + status006a.wickets[0].unlock(); + try { + Thread.currentThread().sleep(status006a.argHandler.getWaitTime() * 60000); + } catch (InterruptedException e) { + // its's OK + } + } +} + +class status006aThreadSleepingLongInt extends Thread { + status006aThreadSleepingLongInt (String name) { + super(name); + } + + public void run () { + status006a.wickets[1].unlock(); + try { + Thread.currentThread().sleep(status006a.argHandler.getWaitTime() * 60000, 0); + } catch (InterruptedException e) { + // it's OK + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status007/status007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status007/status007.java new file mode 100644 index 00000000000..82c4564784c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status007/status007.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/status/status007. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for status() method of ThreadReference interface. + * The test checks if the method returns + * ThreadReference.THREAD_STATUS_RUNNING status for + * debuggee's thread when it is running. + * The test consists of a debugger program (status007.java) + * and debuggee application (status007a.java). + * Package name is nsk.jdi.ThreadReference.status. + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * The debuggee starts special checked thread. This thread + * executes some 'while' loop. + * After notification of readiness from debuggee, the debugger + * checks if ThreadReference.status() returns expected status + * for checked thread. Then the debugger suspends the checked + * thread and checks its status again. + * The test fails if status() method returned a status code + * other then expected THREAD_STATUS_RUNNING one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.status.status007.status007 + * nsk.jdi.ThreadReference.status.status007.status007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.status.status007.status007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.status.status007; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.ThreadReference; + +//import com.sun.jdi.request.*; +//import com.sun.jdi.event.*; +//import com.sun.jdi.connect.*; +import java.io.*; + +/** + * The debugger application of the test. + */ +public class status007 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ThreadReference.status.status007."; + private final static String className = "status007"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String testedThreadName = prefix + "status007aThread"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + debuggee.receiveExpectedSignal(SIGNAL_GO); + check(status007a.testedThreadNames[0], "CHECK1", "CHECK2"); + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static String getThreadStatusName (int status) { + switch (status) { + case ThreadReference.THREAD_STATUS_UNKNOWN: + return "THREAD_STATUS_UNKNOWN"; + case ThreadReference.THREAD_STATUS_ZOMBIE: + return "THREAD_STATUS_ZOMBIE"; + case ThreadReference.THREAD_STATUS_RUNNING: + return "THREAD_STATUS_RUNNING"; + case ThreadReference.THREAD_STATUS_SLEEPING: + return "THREAD_STATUS_SLEEPING"; + case ThreadReference.THREAD_STATUS_MONITOR: + return "THREAD_STATUS_MONITOR"; + case ThreadReference.THREAD_STATUS_WAIT: + return "THREAD_STATUS_WAIT"; + case ThreadReference.THREAD_STATUS_NOT_STARTED: + return "THREAD_STATUS_NOT_STARTED"; + default: + return "ERROR: Unknown ThreadReference status " + status; + } + } + + private static void check (String threadName, String check1, String check2) { + ThreadReference testedThread = (ThreadReference)debuggeeClass.getValue(debuggeeClass.fieldByName(threadName)); + int threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_RUNNING) { + display(check1 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_RUNNING for unsuspended " + threadName); + } else { + complain(check1 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus)+ " for unsuspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_RUNNING)); + exitStatus = Consts.TEST_FAILED; + } + + try { + testedThread.suspend(); + threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_RUNNING) { + display(check2 + " PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_RUNNING for suspended " + threadName); + } else { + complain(check2 + " FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus) + " for suspended " + threadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_RUNNING)); + exitStatus = Consts.TEST_FAILED; + } + testedThread.resume(); + } catch (Exception e) { + complain(check2 + " FAILED"); + complain("\t Unexpected exception while calling ThreadReference.suspend for " + threadName + " : " + e); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status007/status007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status007/status007a.java new file mode 100644 index 00000000000..f775f14d7ea --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status007/status007a.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ThreadReference.status.status007; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import java.util.*; + +/** + * The debugged application of the test. + */ +public class status007a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static Log log; + private static IOPipe pipe; + static ArgumentHandler argHandler; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static String testedThreadNames[] = {"threadRunning", "threadRunningNanos"}; + static status007aThreadRunning threadRunning; + static Wicket wicket = new Wicket(); + static volatile boolean shouldRun = true; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(status007.SIGNAL_READY); + + threadRunning = new status007aThreadRunning(testedThreadNames[0]); + threadRunning.start(); + wicket.waitFor(); + + pipe.println(status007.SIGNAL_GO); + receiveSignal(status007.SIGNAL_QUIT); + + shouldRun = false; + waitForFinish(threadRunning); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void waitForFinish (Thread thread) { + if (thread.isAlive()) { + try { + thread.join(argHandler.getWaitTime() * 60000); + display(thread.getName() + " is finished"); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while waiting for join of " + thread.getName()); + } + if (thread.isAlive()) { + throw new Failure(thread.getName() + " has not finished after " + argHandler.getWaitTime() + " mins"); + } + } + } + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes + +class status007aThreadRunning extends Thread { + status007aThreadRunning (String name) { + super(name); + } + + public void run () { + status007a.wicket.unlock(); + // do something + Vector v = new Vector(); + while (status007a.shouldRun) { + v.add("bla-"); + if (v.size() > 1000) { + v.removeAllElements(); + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status008/status008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status008/status008.java new file mode 100644 index 00000000000..bb5ba64623e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status008/status008.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2003, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/status/status008. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for status() method of ThreadReference interface. + * The test checks if the method returns + * ThreadReference.THREAD_STATUS_UNKNOWN status for + * debuggee's thread when it has not been started yet. + * The test checks status of unsuspended and suspended thread. + * The test consists of a debugger program (status008.java) + * and debuggee application (status008a.java). + * Package name is nsk.jdi.ThreadReference.status. + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * The debuggee's create checked thread, but does not start it. + * After notification of readiness from debuggee, + * the debugger checks if ThreadReference.status() returns + * expected status for checked thread. Then the debugger + * suspends the checked thread and checks its status again. + * The test fails if status() method returned a status code + * other then expected THREAD_STATUS_UNKNOWN one. + * COMMENTS: + * Though JDI spec has THREAD_STATUS_NOT_STARTED status for unstarted + * threads, JDI implementation of status() method never returned this + * status code, but THREAD_STATUS_UNKNOWN one for unstarted threads. + * The 4490152 bug relates to this issue. The 4956818 bug states that + * JPDA interfaces should not return unstarted threads. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.status.status008.status008 + * nsk.jdi.ThreadReference.status.status008.status008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.status.status008.status008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.ThreadReference.status.status008; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class status008 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.ThreadReference.status.status008."; + private final static String className = "status008"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String testedThreadName = prefix + "status008aThread"; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + ThreadReference testedThread = (ThreadReference)debuggeeClass.getValue(debuggeeClass.fieldByName(status008a.testedThreadName)); + int threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_UNKNOWN) { + display("CHECK1 PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_UNKNOWN for unsuspended " + status008a.testedThreadName); + } else { + complain("CHECK1 FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus)+ " for unsuspended " + status008a.testedThreadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_NOT_STARTED)); + exitStatus = Consts.TEST_FAILED; + } + + try { + testedThread.suspend(); + threadStatus = testedThread.status(); + if (threadStatus == ThreadReference.THREAD_STATUS_UNKNOWN) { + display("CHECK2 PASSED"); + display("\t ThreadReference.status() returned expected status THREAD_STATUS_UNKNOWN for suspended " + status008a.testedThreadName); + } else { + complain("CHECK2 FAILED"); + complain("\t ThreadReference.status() returned unexpected status " + + getThreadStatusName(threadStatus) + " for suspended " + status008a.testedThreadName); + complain("\t Expected status : " + getThreadStatusName(ThreadReference.THREAD_STATUS_NOT_STARTED)); + exitStatus = Consts.TEST_FAILED; + } + testedThread.resume(); + } catch (Exception e) { + complain("CHECK2 FAILED"); + complain("\t Unexpected exception while calling ThreadReference.suspend for " + status008a.testedThreadName + " : " + e); + exitStatus = Consts.TEST_FAILED; + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static String getThreadStatusName (int status) { + switch (status) { + case ThreadReference.THREAD_STATUS_UNKNOWN: + return "THREAD_STATUS_UNKNOWN"; + case ThreadReference.THREAD_STATUS_ZOMBIE: + return "THREAD_STATUS_ZOMBIE"; + case ThreadReference.THREAD_STATUS_RUNNING: + return "THREAD_STATUS_RUNNING"; + case ThreadReference.THREAD_STATUS_SLEEPING: + return "THREAD_STATUS_SLEEPING"; + case ThreadReference.THREAD_STATUS_MONITOR: + return "THREAD_STATUS_MONITOR"; + case ThreadReference.THREAD_STATUS_WAIT: + return "THREAD_STATUS_WAIT"; + case ThreadReference.THREAD_STATUS_NOT_STARTED: + return "THREAD_STATUS_NOT_STARTED"; + default: + return "ERROR: Unknown ThreadReference status " + status; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status008/status008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status008/status008a.java new file mode 100644 index 00000000000..ac99fca86a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/status/status008/status008a.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.ThreadReference.status.status008; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class status008a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static String testedThreadName = "unStartedThread"; + static Thread unStartedThread; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + unStartedThread = new Thread(testedThreadName); + + pipe.println(status008.SIGNAL_READY); + receiveSignal(status008.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific methods + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001.java new file mode 100644 index 00000000000..4b911b9c9d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.stop; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.stop()
    + * complies with its spec.
    + *
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs the debugger of the thread2 creation,
    + * and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until getting Exception from the debugger.
    + * Upon the receiption a message from the debuggee,
    + * the debugger gets a ThreadReference thread2 mirroring the thread2 and
    + * an ObjectReference throwableObj mirroring a special Throwable object
    + * prepared by the main thread in the debuggee,
    + * (note: for identification, throwableObj.getMessage() returns
    + * the string "testException")
    + * and invokes thread2.stop(throwableObj) which should throw exception
    + * in the locked thread2 in the debugger.
    + * In catch subclouse, the thread2 assigns Exception it got to a special
    + * variable tObj of the Throwable type and ends its running.
    + * The main thread reads tObj.message(), compares to "testException",
    + * and informs the debugger of strings match or mismatch.
    + */ + +public class stop001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/stop/stop001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new stop001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.stop.stop001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.stop.Threadstop001a"; + + //String mName = "nsk.jdi.ThreadReference.stop"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "Thread2"; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + ReferenceType mainthreadClass = null; + ObjectReference throwableObj = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(debuggeeName); + mainthreadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + + label1: { + if (expresult != returnCode0) + break label1; + + + try { + log2(" getting a mirror of the throwableObj"); + throwableObj = (ObjectReference) + mainthreadClass.getValue(mainthreadClass.fieldByName("throwableObj")); + + log2(" stopping the thread2"); + thread2.stop(throwableObj); + + } catch ( InvalidTypeException e1 ) { + log3("ERROR: InvalidTypeException ???"); + expresult = returnCode1; + } catch ( Exception e2 ) { + log3("ERROR: unexpected exception: " + e2); + expresult = returnCode1; + } + + log2("......instructing mainThread to leave synchronized block"); + pipe.println("continue"); + + log2("......getting result from mainThread:"); + line = pipe.readln(); + log2(" returned string is: " + line); + if (line.equals("null")) { + log3("ERROR: 'stop001a.tObj = e1;' was not assigned"); + expresult = returnCode1; + } else if (line.equals("equal")) { + } else if (line.equals("NOT_equal")) { + log3("ERROR: in the debugee, e1 is not 'LineUnavailableException'"); + expresult = returnCode1; + } else { + log3("ERROR: returned string is unexpected"); + expresult = returnCode4; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java new file mode 100644 index 00000000000..4b305a50b4f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/stop/stop001. + * VM Testbase keywords: [quick, jpda, jdi, quarantine] + * VM Testbase comments: JDK-7034630 + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.stop() + * complies with its spec: + * public void stop(ObjectReference throwable) + * throws InvalidTypeException + * Stops this thread with an asynchronous exception. + * A debugger thread in the target VM will stop this thread with the + * given Throwable object. + * Parameters: throwable - the asynchronous exception to throw. + * Throws: InvalidTypeException - + * if throwable is not an instance of java.lang.Throwable in + * the target VM. + * ObjectCollectedException - + * if this object or the asynchronous exception has been garbage collected. + * See Also: java.lang.Thread#stop(Throwable) + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.stop.stop001; + * the debuggee program - nsk.jdi.ThreadReference.stop.stop001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test ws modified to fixe the bug: + * 4637894 TEST_BUG: stop001a does not check object against null + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.stop.stop001 + * nsk.jdi.ThreadReference.stop.stop001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.stop.stop001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001a.java new file mode 100644 index 00000000000..06ce56593e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop001a.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.stop; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + + +/** + * This class is used as debuggee application for the stop001 JDI test. + * + * corrected 5/13/2001 + */ + +public class stop001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; +// static final int FAILED = 2; // see int FAILED below + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + public static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + private static Threadstop001a thread2 = null; + + public static String strException = "testException"; + + private static Throwable throwableObj = new Exception(strException); + public static Throwable tObj = null; + + public static int exitCode = PASSED; + public static final int FAILED = 2; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * com.sun.jdi.ThreadReference.stop()
    + * properly throws InvalidTypeException - if specified + * throwable is not an instance of java.lang.Throwable in the + * target VM.

    + * + * Debugger part of the test tries to stop debuggee thread + * through the JDI method using as a parameter an object + * reference of the main debuggee class stop002t itself + * which is not Throwable. + */ +public class stop002 { + static final String DEBUGGEE_CLASS = + "nsk.jdi.ThreadReference.stop.stop002t"; + + // names of debuggee main thread + static final String DEBUGGEE_THRNAME = "stop002tThr"; + + // debuggee local var used to find needed non-throwable object + static final String DEBUGGEE_LOCALVAR = "stop002tNonThrowable"; + // debuggee field used to indicate that testing is over + static final String DEBUGGEE_FIELD = "stopLooping"; + + // debuggee source line where it should be stopped + static final int DEBUGGEE_STOPATLINE = 69; + + static final int DELAY = 500; // in milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_GO = "go"; + static final String COMMAND_QUIT = "quit"; + + private ArgumentHandler argHandler; + private Log log; + private IOPipe pipe; + private Debugee debuggee; + private VirtualMachine vm; + private BreakpointRequest BPreq; + private volatile int tot_res = Consts.TEST_PASSED; + private volatile boolean gotEvent = false; + + public static void main (String argv[]) { + System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new stop002().runIt(argv, out); + } + + private int runIt(String args[], PrintStream out) { + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + + debuggee = binder.bindToDebugee(DEBUGGEE_CLASS); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + debuggee.redirectStderr(log, "stop002t.err> "); + debuggee.resume(); + String cmd = pipe.readln(); + if (!cmd.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee command: " + cmd); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + ThreadReference thrRef = null; + if ((thrRef = + debuggee.threadByName(DEBUGGEE_THRNAME)) == null) { + log.complain("TEST FAILURE: method Debugee.threadByName() returned null for debuggee thread " + + DEBUGGEE_THRNAME); + tot_res = Consts.TEST_FAILED; + return quitDebuggee(); + } + + Field doExit = null; + ObjectReference objRef = null; + try { + // debuggee main class + ReferenceType rType = debuggee.classByName(DEBUGGEE_CLASS); + + suspendAtBP(rType, DEBUGGEE_STOPATLINE); + objRef = findObjRef(thrRef, DEBUGGEE_LOCALVAR); + + // this field is used to indicate that debuggee has to + // stop looping + doExit = rType.fieldByName(DEBUGGEE_FIELD); + + log.display("Resuming debuggee VM ..."); + vm.resume(); + log.display("Resumption of debuggee VM done"); + + log.display("\nTrying to stop debuggee thread \"" + thrRef + + "\"\n\tusing non-throwable object reference \"" + + objRef + "\" as a parameter ..."); + +// Check the tested assersion + try { + thrRef.stop(objRef); + log.complain("TEST FAILED: expected IllegalArgumentException was not thrown" + + "\n\twhen attempted to stop debuggee thread \"" + thrRef + + "\"\n\tusing non-throwable object reference \"" + + objRef + "\" as a parameter"); + tot_res = Consts.TEST_FAILED; + } catch(InvalidTypeException ee) { + log.display("CHECK PASSED: caught expected " + ee); + } catch(Exception ue) { + ue.printStackTrace(); + log.complain("TEST FAILED: ThreadReference.stop(): caught unexpected " + + ue + "\n\tinstead of InvalidTypeException" + + "\n\twhen attempted to stop debuggee thread \"" + thrRef + + "\"\n\tusing non-throwable object reference \"" + + objRef + "\" as a parameter"); + tot_res = Consts.TEST_FAILED; + } + + } catch (Exception e) { + e.printStackTrace(); + log.complain("TEST FAILURE: caught unexpected exception: " + e); + tot_res = Consts.TEST_FAILED; + } finally { +// Finish the test + // force an method to exit + if (objRef != null && doExit != null) { + try { + objRef.setValue(doExit, vm.mirrorOf(true)); + } catch(Exception sve) { + sve.printStackTrace(); + } + } + } + + return quitDebuggee(); + } + + private ObjectReference findObjRef(ThreadReference thrRef, String varName) { + try { + List frames = thrRef.frames(); + Iterator iter = frames.iterator(); + while (iter.hasNext()) { + StackFrame stackFr = (StackFrame) iter.next(); + try { + LocalVariable locVar = + stackFr.visibleVariableByName(varName); + // visible variable with the given name is found + if (locVar != null) { + return (ObjectReference) + stackFr.getValue(locVar); + } + } catch(AbsentInformationException e) { + // this is not needed stack frame, ignoring + } catch(NativeMethodException ne) { + // current method is native, also ignoring + } + } + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + throw new Failure("findObjRef: caught unexpected exception: " + e); + } + throw new Failure("findObjRef: needed debuggee stack frame not found"); + } + + private BreakpointRequest setBP(ReferenceType refType, int bpLine) { + EventRequestManager evReqMan = + debuggee.getEventRequestManager(); + Location loc; + + try { + List locations = refType.allLineLocations(); + Iterator iter = locations.iterator(); + while (iter.hasNext()) { + loc = (Location) iter.next(); + if (loc.lineNumber() == bpLine) { + BreakpointRequest BPreq = + evReqMan.createBreakpointRequest(loc); + log.display("created " + BPreq + "\n\tfor " + refType + + " ; line=" + bpLine); + return BPreq; + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Failure("setBP: caught unexpected exception: " + e); + } + throw new Failure("setBP: location corresponding debuggee source line " + + bpLine + " not found"); + } + + private void suspendAtBP(ReferenceType rType, int bpLine) { + + /** + * This is a class containing a critical section which may lead to time + * out of the test. + */ + class CriticalSection extends Thread { + public volatile boolean waitFor = true; + + public void run() { + try { + do { + EventSet eventSet = vm.eventQueue().remove(DELAY); + if (eventSet != null) { // it is not a timeout + EventIterator it = eventSet.eventIterator(); + while (it.hasNext()) { + Event event = it.nextEvent(); + if (event instanceof VMDisconnectEvent) { + log.complain("TEST FAILED: unexpected VMDisconnectEvent"); + break; + } else if (event instanceof VMDeathEvent) { + log.complain("TEST FAILED: unexpected VMDeathEvent"); + break; + } else if (event instanceof BreakpointEvent) { + if (event.request().equals(BPreq)) { + log.display("expected Breakpoint event occured: " + + event.toString()); + gotEvent = true; + return; + } + } else + log.display("following JDI event occured: " + + event.toString()); + } + } + } while(waitFor); + log.complain("TEST FAILED: no expected Breakpoint event"); + tot_res = Consts.TEST_FAILED; + } catch (Exception e) { + e.printStackTrace(); + tot_res = Consts.TEST_FAILED; + log.complain("TEST FAILED: caught unexpected exception: " + e); + } + } + } +///////////////////////////////////////////////////////////////////////////// + + BPreq = setBP(rType, bpLine); + BPreq.enable(); + CriticalSection critSect = new CriticalSection(); + log.display("\nStarting potential timed out section:\n\twaiting " + + (argHandler.getWaitTime()) + + " minute(s) for JDI Breakpoint event ...\n"); + critSect.start(); + pipe.println(COMMAND_GO); + try { + critSect.join((argHandler.getWaitTime())*60000); + if (critSect.isAlive()) { + critSect.waitFor = false; + throw new Failure("timeout occured while waiting for Breakpoint event"); + } + } catch (InterruptedException e) { + critSect.waitFor = false; + throw new Failure("TEST INCOMPLETE: InterruptedException occured while waiting for Breakpoint event"); + } finally { + BPreq.disable(); + } + log.display("\nPotential timed out section successfully passed\n"); + if (gotEvent == false) + throw new Failure("unable to suspend debuggee thread at breakpoint"); + } + + private int quitDebuggee() { + log.display("Final resumption of debuggee VM"); + vm.resume(); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + int debStat = debuggee.getStatus(); + if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) { + log.complain("TEST FAILED: debuggee process finished with status: " + + debStat); + tot_res = Consts.TEST_FAILED; + } else + log.display("\nDebuggee process finished with the status: " + + debStat); + + return tot_res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002/TestDescription.java new file mode 100644 index 00000000000..35032e636f7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/stop/stop002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks that the JDI method: + * com.sun.jdi.ThreadReference.stop() + * properly throws InvalidTypeException - if specified throwable + * is not an instance of java.lang.Throwable in the target VM. + * Debugger part of the test tries to stop debuggee thread + * through the JDI method using as a parameter an object + * reference of the main debuggee class stop002t itself + * which is not Throwable. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.stop.stop002 + * nsk.jdi.ThreadReference.stop.stop002t + * + * @comment make sure stop002t is compiled with full debug info + * @clean nsk.jdi.ThreadReference.stop.stop002t + * @compile -g:lines,source,vars ../stop002t.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.stop.stop002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002t.java new file mode 100644 index 00000000000..a3af4a17a9d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/stop/stop002t.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.ThreadReference.stop; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * This is a debuggee class. + */ +public class stop002t { + private Log log; + private IOPipe pipe; + volatile boolean stopLooping = false; + + public static void main(String args[]) { + System.exit(run(args) + Consts.JCK_STATUS_BASE); + } + + public static int run(String args[]) { + return new stop002t().runIt(args); + } + + private int runIt(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + + log = argHandler.createDebugeeLog(); + pipe = argHandler.createDebugeeIOPipe(); + + Thread.currentThread().setName(stop002.DEBUGGEE_THRNAME); + + // non-throwable object which will be used by debugger + // as wrong parameter of JDI method ThreadReference.stop() + stop002t stop002tNonThrowable = this; + + // Now the debuggee is ready for testing + pipe.println(stop002.COMMAND_READY); + String cmd = pipe.readln(); + if (cmd.equals(stop002.COMMAND_QUIT)) { + log.complain("Debuggee: exiting due to the command " + + cmd); + return Consts.TEST_PASSED; + } + + int stopMeHere = 0; // stop002.DEBUGGEE_STOPATLINE + + log.display("Debuggee: going to loop ..."); + while(!stopLooping) { // looping + stopMeHere++; stopMeHere--; + } + log.display("Debuggee: looping done"); + + cmd = pipe.readln(); + if (!cmd.equals(stop002.COMMAND_QUIT)) { + log.complain("TEST BUG: unknown debugger command: " + + cmd); + return Consts.TEST_FAILED; + } + return Consts.TEST_PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001.java new file mode 100644 index 00000000000..ff6038e7f8d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001.java @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.suspend; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.suspend()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since thread2 uses the same locking object in its 'run' method
    + * it is locked up until first thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * sets up breakpoints within thread2's methods and checks up that
    + * call to the method thread2.suspend() does suspend the thread2 when
    + * - the thread2 is not suspended and when
    + * - it is suspended at a breakpoint
    + * In both cases is expected that resuming the thread2 results in
    + * timeout for waiting for the thread2 gets stopping at a breakpoint.
    + */ + +public class suspend001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/suspend/suspend001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new suspend001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.suspend.suspend001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.suspend.Threadsuspend001a"; + + //String mName = "nsk.jdi.ThreadReference.suspend"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + + label1: { + if (expresult != returnCode0) + break label1; + + log2("......checking up that thread2.suspend() does suspend the non-suspended thread2"); + + log2(" suspending the thread2"); + thread2.suspend(); + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + log2(" checking up that the thread2 is not at breakpoint1 because of suspension"); + expresult = breakpoint(); + if (expresult != returnCode3) { + log3("ERROR: no timeout for waiting for BreakpointEvent when the thread2 is suspended"); + expresult = returnCode1; + break label1; + } else + expresult = returnCode0; + + + log2("......checking up that thread2.suspend() does suspend the suspended thread2"); + + log2(" resuming the thread2 with thread2.resume();"); + thread2.resume(); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + if (!thread2.isSuspended()) { + log3("ERROR: !thread2.isSuspended() at the breakpoint ???"); + expresult = returnCode1; + break label1; + } + + log2(" suspending the thread2"); + thread2.suspend(); + + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + + log2(" resuming the thread2 with eventSet.resume();"); + eventSet.resume(); + + log2(" checking up that the thread2 is not at breakpoint2 because of suspension"); + expresult = breakpoint(); + if (expresult != returnCode3) { + log3("ERROR: no timeout for waiting for BreakpointEvent when the thread2 is suspended"); + expresult = returnCode1; + break label1; + } else + expresult = returnCode0; + + log2(" resuming the thread2 with thread2.resume();"); + thread2.resume(); + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult == returnCode0) { + log2(" thread2 is at breakpoint"); + log2(" resuming the thread2 with eventSet.resume();"); + eventSet.resume(); + } else { + log3("ERROR: breakpoint was not reached"); + expresult = returnCode1; + break label1; + } + } + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove (waitTime*60000); + if (eventSet == null) { + log2(":::::: timeout when waiting for a BreakpintEvent"); +// log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001/TestDescription.java new file mode 100644 index 00000000000..41cb02c2ff6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/suspend/suspend001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.suspend() + * complies with its spec: + * public void suspend() + * Suspends this thread. The thread can be resumed through resume() or + * resumed with other threads through VirtualMachine.resume(). + * Unlike java.lang.Thread#suspend, suspends of both the virtual machine and + * individual threads are counted. + * Before a thread will run again, it must be resumed (through resume() or + * resume()) the same number of times it has been suspended. + * Suspending single threads with this method has the same dangers as + * java.lang.Thread.suspend(). If the suspended thread holds a monitor + * needed by another running thread, deadlock is possible + * in the target VM (at least until the suspended thread is resumed again). + * The suspended thread is guaranteed to remain suspended until resumed + * through one of the JDI resume methods mentioned above; + * the application in the target VM cannot resume the suspended thread + * through java.lang.Thread#resume. + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.suspend.suspend001; + * the debuggee program - nsk.jdi.ThreadReference.suspend.suspend001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.suspend.suspend001 + * nsk.jdi.ThreadReference.suspend.suspend001a + * @run main/othervm/timeout=420 PropertyResolvingWrapper + * nsk.jdi.ThreadReference.suspend.suspend001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001a.java new file mode 100644 index 00000000000..ee0712a25dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspend/suspend001a.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.suspend; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the suspend001 JDI test. + */ + +public class suspend001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.suspendCount()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object in its 'run' method
    + * it is locked up until the debuggee leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * calls methods ThreadReference.suspend() and .resume(), and
    + * VirualMachine.suspend() and .resume() in a number of combinations,
    + * and checks up that each combination results in the expected value
    + * returned by the method suspendCount().
    + * At the end the debugger instructs the debuggee to unlock the thread2.
    + *
    + */ + +public class suspendcount001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/suspendCount/suspendcount001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new suspendcount001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.suspendCount.suspendcount001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.suspendCount.Threadsuspendcount001a"; + + //String mName = "nsk.jdi.ThreadReference.suspendCount"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + //String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + //String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + //BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + + int suspCount; + + log2(" check #1: the beginning: suspCount == 0 "); + suspCount = thread2.suspendCount(); + if (suspCount != 0) { + log3("ERROR: 1: suspCount != 0 : " + suspCount); + expresult = returnCode1; + } + + + log2(" suspending thread2 with: thread2.suspend(); "); + thread2.suspend(); + + log2(" check #2: suspCount == 1 "); + suspCount = thread2.suspendCount(); + if (suspCount != 1) { + log3("ERROR: 2: suspCount != 1 : " + suspCount); + expresult = returnCode1; + } + + + log2(" suspending thread2 with: thread2.suspend(); "); + thread2.suspend(); + + log2(" check #3: suspCount == 2 "); + suspCount = thread2.suspendCount(); + if (suspCount != 2) { + log3("ERROR: 3: suspCount != 2 : " + suspCount); + expresult = returnCode1;; + } + + + log2(" resuming thread2 with: thread2.resume(); "); + thread2.resume(); + + log2(" check #4: suspCount == 1 "); + suspCount = thread2.suspendCount(); + if (suspCount != 1) { + log3("ERROR: 4: suspCount != 1 : " + suspCount); + expresult = returnCode1; + } + + + log2(" resuming thread2 with: thread2.resume(); "); + thread2.resume(); + + log2(" check #5: suspCount == 0 "); + suspCount = thread2.suspendCount(); + if (suspCount != 0) { + log3("ERROR: 5: suspCount != 0 : " + suspCount); + expresult = returnCode1; + } + + + log2(" resuming NON-SUSPENDED thread2 with: thread2.resume(); "); + thread2.resume(); + + log2(" check #6: suspCount == 0 "); + suspCount = thread2.suspendCount(); + if (suspCount != 0) { + log3("ERROR: 6: suspCount != 0 : " + suspCount); + expresult = returnCode1; + } + + + log2(" suspending thread2 with: thread2.suspend(); "); + thread2.suspend(); + + log2(" check #7: suspCount == 1 "); + suspCount = thread2.suspendCount(); + if (suspCount != 1) { + log3("ERROR: 7: suspCount != 1 : " + suspCount); + expresult = returnCode1; + } + + + log2(" suspending VirtualMachine with vm.suspend(); "); + vm.suspend(); + + log2(" check #8: suspCount == 2 "); + suspCount = thread2.suspendCount(); + if (suspCount != 2) { + log3("ERROR: 8: suspCount != 2 : " + suspCount); + expresult = returnCode1; + } + + + log2(" 9: resuming only thread2 with double thread2.resume(); "); + thread2.resume(); + thread2.resume(); + + log2(" check #9: suspCount == 0 "); + suspCount = thread2.suspendCount(); + if (suspCount != 0) { + log3("ERROR: 9: suspCount != 0 : " + suspCount); + expresult = returnCode1; + } + + + log2(" 10: suspending VirtualMachine with double vm.suspend(); "); + vm.suspend(); + vm.suspend(); + + log2(" check #10: suspCount == 2 "); + suspCount = thread2.suspendCount(); + if (suspCount != 2) { + log3("ERROR: 10: suspCount != 2 : " + suspCount); + expresult = returnCode1; + } + + + log2(" 11: resuming with thread2.resume(); and vm.resume(); "); + thread2.resume(); + vm.resume(); + + log2(" check #11: suspCount == 0 "); + suspCount = thread2.suspendCount(); + if (suspCount != 0) { + log3("ERROR: 11: suspCount != 0 : " + suspCount); + expresult = returnCode1; + } + + vm.resume(); + vm.resume(); + + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ +/* + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } +*/ + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ +/* + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +*/ +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001/TestDescription.java new file mode 100644 index 00000000000..11501b939c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/suspendCount/suspendcount001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.suspendCount() + * complies with its spec: + * public int suspendCount() + * Resumes the number of pending suspends for this thread. + * See suspend() for an explanation of counted suspends. + * Returns: the integer pending suspend count + * Throws: ObjectCollectedException - + * if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.suspendCount.suspendcount001; + * the debuggee program - nsk.jdi.ThreadReference.suspendCount.suspendcount001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.suspendCount.suspendcount001 + * nsk.jdi.ThreadReference.suspendCount.suspendcount001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.suspendCount.suspendcount001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001a.java new file mode 100644 index 00000000000..62d9f146331 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/suspendCount/suspendcount001a.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.suspendCount; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the suspendcount001 JDI test. + */ + +public class suspendcount001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * ThreadReference.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.ThreadReference.threadGroup()
    + * complies with its spec.
    + *
    + * The case for testing includes four ThreadGroup objects defined
    + * in a debuggee and their mirrors in a debugger.
    + * Parenthood relationships between the objects are as follows:
    + * threadGroups 2&3 are subgroups of threadGroup1
    + * threadGroup4 is a subgroup of threadGroup3
    + * The objects are created together with three threads, Thread 2,3,4,
    + * belonging to the corresponding subgroups.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates the threads,
    + * informs the debugger of the threads creation,
    + * and is waiting for reply.
    + * Since the threads use the same locking object in their 'run' methods
    + * they are locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee,
    + * the debugger gets mirrors of threadGroups and running threads,
    + * selects mirrors of Thread2,3,4, and checks up that :
    + * - object returned by Thread4.threadGroup(), is equal to threadGroup4;
    + * - object returned by Thread3.threadGroup(), is equal to threadGroup3;
    + * - object returned by Thread2.threadGroup(), is equal to threadGroup2.
    + */ + +public class threadgroup001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadReference/threadGroup/threadgroup001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new threadgroup001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadReference.threadGroup.threadgroup001a"; + + private String testedClassName = + "nsk.jdi.ThreadReference.threadGroup.Threadthreadgroup001a"; + + //String mName = "nsk.jdi.ThreadReference.threadGroup"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + List classes = null; + + ThreadGroupReference groups[] = { null, null, null, null }; + + String groupNames [] = { "threadGroup1Obj", + "threadGroup2Obj", + "threadGroup3Obj", + "threadGroup4Obj" }; + + List threads; + ListIterator iterator; + int flag; + String threadName; + ThreadReference thread; + + ThreadReference thread2 = null; + ThreadReference thread3 = null; + ThreadReference thread4 = null; + + String threadNames [] = { "Thread2", "Thread3", "Thread4" }; + + ReferenceType mainthreadClass = null; + ReferenceType thread2Class = null; + + label0: { + + log2("getting ThreadReference objects"); + try { + classes = vm.classesByName(testedClassName); + thread2Class = (ReferenceType) classes.get(0); + classes = vm.classesByName(debuggeeName); + mainthreadClass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + log2(" getting a List of all threadGroups"); + for (int i1 = 0; i1 < 4; i1++) { + groups[i1] = (ThreadGroupReference) + mainthreadClass.getValue(mainthreadClass.fieldByName(groupNames[i1])); + } + + log2(" getting a List of all running threads"); + threads = vm.allThreads(); + + + log2(" getting Thread 2,3,4 mirror objects"); + + iterator = threads.listIterator(); + for ( int i2 = 0; iterator.hasNext(); i2++ ) { + thread = (ThreadReference) iterator.next(); + threadName = thread.name(); + if (threadName.equals(threadNames[0])) + thread2 = thread; + else if (threadName.equals(threadNames[1])) + thread3 = thread; + else if (threadName.equals(threadNames[2])) + thread4 = thread; + } + + + log2("......checking up Thread2's group"); + if (!thread2.threadGroup().equals(groups[1])) { + log3("ERROR: !thread2.threadGroup.equals(groups[1])"); + expresult = 1; + } + + log2("......checking up Thread3's group"); + if (!thread3.threadGroup().equals(groups[2])) { + log3("ERROR: !thread3.threadGroup.equals(groups[2])"); + expresult = 1; + } + + + log2("......checking up Thread4's group"); + if (!thread4.threadGroup().equals(groups[3])) { + log3("ERROR: !thread4.threadGroup.equals(groups[3])"); + expresult = 1; + } + + + log2("......instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001/TestDescription.java new file mode 100644 index 00000000000..12a7d2291e1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadReference/threadGroup/threadgroup001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadReference. + * The test checks up that a result of the method + * com.sun.jdi.ThreadReference.threadGroup() + * complies with its spec: + * public ThreadGroupReference threadGroup() + * Returns this thread's thread group. + * Returns: a ThreadGroupReference that mirrors this thread's thread group + * in the target VM. + * Throws: ObjectCollectedException - if this object has been garbage collected. + * when a ThreadReference object has not been garbage collected, + * hence ObjectCollectedException is not expected to be thrown. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadReference.threadGroup.threadgroup001; + * the debuggee program - nsk.jdi.ThreadReference.threadGroup.threadgroup001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadReference.threadGroup.threadgroup001 + * nsk.jdi.ThreadReference.threadGroup.threadgroup001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadReference.threadGroup.threadgroup001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001a.java new file mode 100644 index 00000000000..e6faf0914e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/threadGroup/threadgroup001a.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadReference.threadGroup; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the threadgroup001 JDI test. + */ + +public class threadgroup001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + public static final String mainthreadGroupName = "mainthreadGroup"; + public static final String threadGroup2Name = "threadGroup2"; + public static final String threadGroup3Name = "threadGroup3"; + public static final String threadGroup4Name = "threadGroup4"; + + public static ThreadGroup threadGroup1Obj = new ThreadGroup(mainthreadGroupName); + public static ThreadGroup threadGroup2Obj = new ThreadGroup(threadGroup1Obj, threadGroup2Name); + public static ThreadGroup threadGroup3Obj = new ThreadGroup(threadGroup1Obj, threadGroup3Name); + public static ThreadGroup threadGroup4Obj = new ThreadGroup(threadGroup3Obj, threadGroup4Name); + + private static Threadthreadgroup001a thread2 = null; + private static Threadthreadgroup001a thread3 = null; + private static Threadthreadgroup001a thread4 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // create event request and waits for events + try { + + log.display("Creating request for ThreadStartEvent"); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + if ((checkedRequest = erManager.createThreadStartRequest()) == null) { + log.complain("TEST BUG: unable to create createThreadStartRequest"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return thread001.FAILED; + } + checkedRequest.enable(); + + // start event handler + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + // wait for all expected events handled or timeout exceeds + try { + eventHandler.join(eventTimeout); + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: interrupted exception while waiting for events: " + e); + testFailed = false; + } + + // interrupt events handler thread if not completed yet + if (eventHandler.isAlive()) { + log.display("Interrupting EventHandler"); + eventHandler.interrupt(); + } + + // check that all expected events received + if (eventsReceived) { + log.display("\nAll expected events received!"); + } else { + for (int i = 0; i < checkedThreads.length; i++) { + if (checkedThreads[i][1].equals("0")) { + log.complain("FAILURE 6: ThreadStartEvent was not received for thread: " + checkedThreads[i][0]); + } + } + testFailed = true; + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception caught: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + // disable event request to prevent appearance of further events + if (checkedRequest != null) { + log.display("Disabling event request"); + checkedRequest.disable(); + } + + // force debuggee to quit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // waiting for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminated"); + int exitCode = debuggee.endDebugee(); + if (exitCode != PASSED + JCK_STATUS_BASE) { + log.complain("Debuggee FAILED with exit code: " + exitCode); + testFailed = true; + } else { + log.display("Debuggee PASSED with exit code: " + exitCode); + } + } + + // exit + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } + + // handle events in a separate thread + static class EventHandler extends Thread { + public void run() { + log.display("EventHandler started"); + eventSet = null; + while (!eventsReceived) { + try { + eventSet = vm.eventQueue().remove(); + } catch (InterruptedException e) { + log.complain("Unexpected interrupted exception while receiving event: " + e); + testFailed = false; + break; + } + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + log.display("\nEvent received:\n " + event); + + if (event instanceof ThreadStartEvent) { + ThreadStartEvent castedEvent = (ThreadStartEvent)event; + log.display("Received event is ThreadStartEvent:\n " + castedEvent); + + EventRequest eventRequest = castedEvent.request(); + if (!(checkedRequest.equals(eventRequest))) { + log.complain("FAILURE 1: eventRequest is not equal to checked request"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + ThreadReference eventThread = castedEvent.thread(); + if (eventThread == null) { + log.complain("FAILURE 2: ThreadStartEvent.thread() returns null"); + testFailed = true; + } + + String threadName = eventThread.name(); + if ((threadName == null) || (threadName.equals(""))) { + log.complain("FAILURE 3: thread reference has invalid empty name"); + testFailed = true; + } else { + log.display ("Expected ThreadStartEvent was received for thread: " + threadName); + } + + // Check that thread is in VirtualMachine.allThreads() list + boolean found = false; + Iterator threadsList = debuggee.VM().allThreads().iterator(); + while (!found && threadsList.hasNext()) { + found = eventThread.equals((ThreadReference)threadsList.next()); + } + if (!found) { + log.complain("FAILURE 4: " + threadName + " is not in debuggee's allThreads() list"); + testFailed = true; + } + + // Check that all expected debuggee's thread create ThreadStartEvent only once + for (int i = 0; i < checkedThreads.length; i++) { + if (threadName.equals(checkedThreads[i][0])) { + if (checkedThreads[i][1].equals("0")) { + checkedThreads[i][1] = "1"; + } else { + log.complain("FAILURE 5: ThreadStartEvent for " + threadName + " is received more that once"); + testFailed = true; + } + } + } + + // Check whether all expected events received + if (!eventsReceived) { + for (int i = 0; i < checkedThreads.length; i++) { + if (checkedThreads[i][1] == "0") { + eventsReceived = false; + break; + } + eventsReceived = true; + } + } + } + // ignore all other events + } + eventSet.resume(); + } + log.display("EventHandler completed"); + } /* run() */ + } /* EventHandler */ + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001/TestDescription.java new file mode 100644 index 00000000000..d93c62d33bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001/TestDescription.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/ThreadStartEvent/thread/thread001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.ThreadStartEvent.thread() method. + * The test checks the following assertions: + * - ThreadStartEvent is always received by debugger + * for all started threads in target VM, + * - ThreadStartEvent.thread() returns valid ThreadReference + * to expected thread in target VM, + * - ThreadStartEvent is received only once for each expected thread + * A debugger class - nsk.jdi.ThreadStartEvent.thread.thread001 ; + * a debuggee class - nsk.jdi.ThreadStartEvent.thread.thread001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates and enables ThreadStartRequest. + * The debuggee creates two auxiliary checked threads: , . + * Before starting threads, debuggee's main thread locks special + * synchronized object to prevent auxiliary threads from finishing + * before test checks performed. + * The debugger starts special thread for listening events + * received from debuggee, and resumes debuggee.The expects + * ThreadStartEvent for each debuggee threads, including main thread, and + * marks that thread in array. + * For each received ThreadStartEvent it is verified to refer to the + * right request, VM, thread references. + * Debugger waits for receives all expected events + * for WAITTIME timeout. If not all events have been received, + * debugger complains about an error. + * Finally, debugger disables event request, cleans events queue, + * sends debuggee command , waits for debuggee terminated, + * and exits. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bugs: + * 4455653 VMDisconnectedException on resume + * 4463674 TEST_BUG: some JDI tests are timing dependent + * ------------------------------------------------------------- + * Modified to fix the bug 4501953, + * the file thread001a.java is modified as follows. + * - A special waitnotify Object is added in the class thread001a. + * - In classes InnerThread and OuterThread, + * synchronized blocks are added + * to make newly created thread certainly to run. + * - In the class thread001a, + * the pervious mechanizm of waiting for predefined time + * is replaced with new one based on wait-notify. + * ------------------------------------------------------------- + * 4434432 TEST_BUG: ThreadStartEvent does not received on Linux + * ------------------------------------------------------------- + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadStartEvent.thread.thread001 + * nsk.jdi.ThreadStartEvent.thread.thread001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadStartEvent.thread.thread001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001a.java new file mode 100644 index 00000000000..03210618001 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartEvent/thread/thread001a.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartEvent.thread; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class thread001a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int THREADS_COUNT = 2; + + public static Log log; + + public static Object lock = new Object(); + public static Object waitnotify = new Object(); + + private static Thread threads[] = new Thread[THREADS_COUNT]; + + public static void main(String args[]) { + thread001a _thread001a = new thread001a(); + System.exit(JCK_STATUS_BASE + _thread001a.runIt(args, System.err)); + } + + int runIt(String args[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // creating threads + threads[0] = new thread001aThread("Thread1"); + threads[1] = new thread001aThread("Thread2"); + threads[1].setDaemon(true); + + // lock monitor to prevent threads from finishing after they started + synchronized (lock) { + + synchronized (waitnotify) { + // start all threads + for (int i = 0; i < THREADS_COUNT; i++) { + threads[i].start(); + try { + waitnotify.wait(); + } catch ( Exception e ) { + System.err.println("TEST INCOMPLETE: caught InterruptedException while sleeping"); + pipe.println("ERROR"); + return FAILED; + } + } + } + + // waiting for command to finish threads and exit + String command = pipe.readln(); + if (command.equals(thread001.COMMAND_QUIT)) { + System.err.println("'quit' received"); + } else { + System.err.println("TEST BUG: Unexpected debugger's command: " + command); + return FAILED; + } + } + + for (int i = 0; i < THREADS_COUNT; i++) { + if (threads[i].isAlive()) { + try { + threads[i].join(); + } catch (InterruptedException e ) { + System.err.println("TEST INCOMPLETE: caught InterruptedException while waiting for aux thread join"); + pipe.println("ERROR"); + } + } + } + System.err.println("Debuggee exited"); + return PASSED; + } +} + +class thread001aThread extends Thread { + thread001aThread (String name) { + super(name); + } + public void run() { + System.err.println("Thread started: " + this.getName()); + + synchronized (thread001a.waitnotify) { + thread001a.waitnotify.notify(); + } + // prevent thread for early finish + synchronized (thread001a.lock) { + } + System.err.println("Thread completed: "+ this.getName()); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java new file mode 100644 index 00000000000..73cc0c527f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadStartRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ThreadStartRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks that the method restricts the events
    + * genereted by this request to those in the thread to filter.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger creates three ThreadStartRequests with
    + * addThreadFilter(debuggee's thread2) invoked only on third Request,
    + * resumes the debuggee and waits for the ThreadStartEvent.
    + * - Debuggee's main thread creates and starts new thread, thread2, and
    + * invokes the methodForCommunication
    + * to inform the debugger with the event.
    + * - Upon getting ThreadStartEvent, the debugger checks
    + * if EventSet contains all three events; if no, the test FAILED.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggee's variable "instruction".
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class addthreadfilter001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + ThreadReference testThread = (ThreadReference) + debuggeeClass.getValue(debuggeeClass.fieldByName("thread2")); + + log1(" TESTING BEGINS"); + + log2("......setting up ThreadStartRequest"); + ThreadStartRequest tsr1 = eventRManager.createThreadStartRequest(); +// tsr1.addThreadFilter(testThread); + tsr1.addCountFilter(1); + tsr1.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tsr1.putProperty("number", "ThreadStartRequest1"); + tsr1.enable(); + + ThreadStartRequest tsr2 = eventRManager.createThreadStartRequest(); +// tsr2.addThreadFilter(testThread); + tsr2.addCountFilter(1); + tsr2.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tsr2.putProperty("number", "ThreadStartRequest2"); + tsr2.enable(); + + ThreadStartRequest tsr3 = eventRManager.createThreadStartRequest(); + tsr3.addThreadFilter(testThread); + tsr3.addCountFilter(1); + tsr3.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tsr3.putProperty("number", "ThreadStartRequest3"); + tsr3.enable(); + + log2("......vm.resume();"); + vm.resume(); + + log2("......waiting for ThreadStartEvent"); + getEventSet(); + EventSet eventSet1 = eventSet; + if ( !(eventIterator.nextEvent() instanceof ThreadStartEvent) ) { + testExitCode = FAILED; + log3("ERROR: new event is not ThreadStartEvent"); + return; + } + tsr1.disable(); + tsr2.disable(); + tsr3.disable(); + + int setSize = eventSet1.size(); + log2("......eventSet1.size() == " + setSize); + if (setSize != 3) { + log3("ERROR: eventSet1.size() != 3 :: " + setSize); + testExitCode = FAILED; + + EventIterator evI1 = eventSet1.eventIterator(); + while (evI1.hasNext()) { + Event ev1 = evI1.nextEvent(); + log2("........event property : " + ev1.request().getProperty("number")); + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001/TestDescription.java new file mode 100644 index 00000000000..e49cb619f1f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadStartRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadStartRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks that the method restricts the events genereted by + * this request to those in a thread to filter which is not main. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter001; + * the debuggee program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter001 + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001a.java new file mode 100644 index 00000000000..0fa9c7dfedd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001a.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter001 JDI test. + */ + +public class addthreadfilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread2addthreadfilter001a thread2 = null; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread2 = new Thread2addthreadfilter001a("thread2"); + methodForCommunication(); + + threadStart(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + static Object lockingObject = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static class Thread2addthreadfilter001a extends Thread { + + String tName = null; + + public Thread2addthreadfilter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log3(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log3(" 'run': exit :: threadName == " + tName); + return; + } + } + + + private static void log3(String str) { + log1(Thread.currentThread().getName() + " : " + str); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java new file mode 100644 index 00000000000..76b2dbe93b0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadStartRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ThreadStartRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The cases to check are as follows: + * (1) if this request is currently enabled,
    + * - addThreadFilter(ThreadReference) results in throwing
    + * InvalidRequestStateException;
    + * - addThreadFilter(null) results in throwing
    + * NullPointerException or InvalidRequestStateException;
    + * (2) if this request is currently disabled,
    + * addThreadFilter(null) results in throwing
    + * NullPointerException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase, the debugger creates ThreadStartRequest
    + * and performs the above checks.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class addthreadfilter002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + ThreadReference mainThread = threadByName("main"); + + bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......setting up ThreadStartRequest"); + log2("...... ThreadStartRequest tsr1 = eventRManager.createThreadStartRequest();"); + ThreadStartRequest tsr1 = eventRManager.createThreadStartRequest(); + tsr1.addCountFilter(1); + tsr1.setSuspendPolicy(EventRequest.SUSPEND_ALL); + tsr1.putProperty("number", "ThreadStartRequest1"); + + log2("...... tsr1.enable();"); + tsr1.enable(); + + try { + log2("...... tsr1.addThreadFilter(mainThread);"); + log2(" InvalidRequestStateException is expected"); + tsr1.addThreadFilter(mainThread); + log3("ERROR: no InvalidRequestStateException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } catch ( Exception e ) { + log3("ERROR: unexpected Exception : " + e); + testExitCode = FAILED; + } + try { + log2("...... tsr1.addThreadFilter(null);"); + log2(" NullPointerException or InvalidRequestStateException is expected"); + tsr1.addThreadFilter(null); + log3("ERROR: no Exception thrown"); + testExitCode = FAILED; + } catch ( NullPointerException e ) { + log2(" NullPointerException"); + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } catch ( Exception e ) { + log3("ERROR: unexpected Exception : " + e); + testExitCode = FAILED; + } + + log2("...... tsr1.disable()"); + tsr1.disable(); + + try { + log2("...... tsr1.addThreadFilter(null);"); + log2(" NullPointerException is expected"); + tsr1.addThreadFilter(null); + log3("ERROR: no NullPointerException "); + testExitCode = FAILED; + } catch ( NullPointerException e ) { + log2(" NullPointerException"); + } catch ( Exception e ) { + log3("ERROR: unexpected Exception : " + e); + testExitCode = FAILED; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002/TestDescription.java new file mode 100644 index 00000000000..1dc5560a460 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadStartRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadStartRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks that "if this request is currently enabled" + * calling the method results in throwing InvalidRequestStateException. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter002; + * the debuggee program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter002 + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002a.java new file mode 100644 index 00000000000..d903cc9be22 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter002 JDI test. + */ + +public class addthreadfilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java new file mode 100644 index 00000000000..dd0710a7c75 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadStartRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.ThreadStartRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * Filters may be added only to disabled requests.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ThreadStartRequest and enables it,
    + * - invokes the method addThreadFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addThreadFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addThreadFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + * + + */ + +public class addthreadfilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter003a"; + + private String testedClassName = + "nsk.jdi.ThreadStartRequest.addThreadFilter.TestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "ThreadStartRequest1"; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ThreadStartRequest (null, + EventRequest.SUSPEND_NONE, "ThreadStartRequest1"); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((ThreadStartRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no InvalidRequestStateException expected"); + ((ThreadStartRequest)eventRequest1).addThreadFilter(thread1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((ThreadStartRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ThreadStartRequest setting2ThreadStartRequest( ThreadReference thread, + int suspendPolicy, + String property) + throws JDITestRuntimeException { + try { + ThreadStartRequest tsr = eventRManager.createThreadStartRequest(); + if (thread != null) + tsr.addThreadFilter(thread); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingThreadStartRequest() : " + e); + log3(" ThreadStartRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ThreadStartRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003/TestDescription.java new file mode 100644 index 00000000000..95b7952b7db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadStartRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadStartRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter003; + * the debuggee program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter003 + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003a.java new file mode 100644 index 00000000000..80dd6ded8b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003a.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter003 JDI test. + */ + +public class addthreadfilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter003a thread1 = null; + + static TestClass objTC = new TestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter003a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter003a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter003a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class TestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004.java new file mode 100644 index 00000000000..bb744b3208f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * ThreadStartRequest. + * + * The test checks that results of the method + * com.sun.jdi.ThreadStartRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same ThreadStartRequest object. + * There are two ThreadStartRequests to check as follows: + * (1) For ThreadStartRequest2, both invocations are with different + * ThreadReferences restricting one ThreadStart event to two threads. + * The test expects no ThreadStart event will be received. + * (2) For ThreadStartRequest1, both invocations are with the same + * ThreadReference restricting one ThreadStart event to one thread. + * The test expects this ThreadStart event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up ThreadStartRequests 1&2 within the method + * in the class addthreadfilter004aTestClass which will be calling by both threads, + * - restricts the ThreadStartRequest1 only to thread1, + * - restricts the ThreadStartRequest2 only to thread2, + * - resumes debuggee's main thread, and + * - waits for the requested events for both threads. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class addthreadfilter004 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter004a"; + return new addthreadfilter004().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter004aTestClass"; + + protected void testRun() { + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ThreadStartRequest1"; + String property2 = "ThreadStartRequest2"; + + ReferenceType testClassReference = null; + + boolean thread1EventReceived = false; + boolean thread2EventReceived = false; + boolean bpEventReceived = false; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2ThreadStartRequest (thread1, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2ThreadStartRequest (thread1, + EventRequest.SUSPEND_ALL, property2); + + ((ThreadStartRequest) eventRequest1).addThreadFilter(thread1); + ((ThreadStartRequest) eventRequest2).addThreadFilter(thread2); + + display("......waiting for ThreadStartEvent in tested thread"); + Event newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ThreadStartEvent)) { + setFailedStatus("ERROR: new event is not ThreadStartEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ThreadStartEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + EventRequest newEventRequest = newEvent.request(); + if (!newEventRequest.equals(eventRequest1) ) { + setFailedStatus("The ThreadStartEvent occured not for eventRequest1"); + } + + ThreadReference thr = ((ThreadStartEvent)newEvent).thread(); + if (!thr.equals(thread1)) { + setFailedStatus("The ThreadStartEvent occured in unexpected thread: " + thr); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ThreadStartRequest setting2ThreadStartRequest( ThreadReference thread, + int suspendPolicy, + String property) { + try { + ThreadStartRequest tsr = eventRManager.createThreadStartRequest(); + if (thread != null) + tsr.addThreadFilter(thread); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ThreadStartRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004/TestDescription.java new file mode 100644 index 00000000000..f290090c88d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadStartRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadStartRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same ThreadStartRequest object. + * There are two ThreadStartRequests to check as follows: + * (1) For ThreadStartRequest2, both invocations are with different + * ThreadReferences restricting one ThreadStart event to two threads. + * The test expects no ThreadStart event will be received. + * (2) For ThreadStartRequest1, both invocations are with the same + * ThreadReference restricting one ThreadStart event to one thread. + * The test expects this ThreadStart event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter004; + * the debuggee program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter004 + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004a.java new file mode 100644 index 00000000000..9dd95703d21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter004a.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter004 JDI test. + */ + +public class addthreadfilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter004a thread1 = null; + static Threadaddthreadfilter004a thread2 = null; + + static addthreadfilter004aTestClass objTC = new addthreadfilter004aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter004a("thread1"); + thread2 = new Threadaddthreadfilter004a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter004a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter004a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class addthreadfilter004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java new file mode 100644 index 00000000000..2dc413b36f0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * ThreadStartRequest.
    + *
    + * The test checks up on the following assertion:
    + * Restricts the events generated by this request
    + * to those in the given thread.
    + * The cases to test include three thread's states:
    + * not started, running, dead.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates ThreadStartRequest1 and
    + * invokes the method addThreadFilter(tread1) on the request1,
    + * - creates ThreadStartRequest2,
    + * resumes the debuggee to get the thread1 started, and
    + * invokes the method addThreadFilter(thread) on the request2,
    + * - creates ThreadStartRequest3, waits the thread1 to die, and
    + * invokes the method addThreadFilter(thread) on the request3.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + * + + */ + +public class addthreadfilter005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter005().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter005a"; + + private String testedClassName = + "nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter005aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + ThreadReference thread1 = null; + + String thread1Name = "thread1"; + + String property1 = "ThreadStartRequest1"; + String property2 = "ThreadStartRequest2"; + String property3 = "ThreadStartRequest3"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ThreadStartRequest (null, + EventRequest.SUSPEND_NONE, property1); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ThreadStartRequest)eventRequest1).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 1: + eventRequest2 = setting2ThreadStartRequest (null, + EventRequest.SUSPEND_NONE, property2); + + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ThreadStartRequest)eventRequest2).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2ThreadStartRequest (null, + EventRequest.SUSPEND_NONE, property3); + + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ThreadStartRequest)eventRequest3).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ThreadStartRequest setting2ThreadStartRequest( ThreadReference thread, + int suspendPolicy, + String property) + throws JDITestRuntimeException { + try { + ThreadStartRequest tsr = eventRManager.createThreadStartRequest(); + if (thread != null) + tsr.addThreadFilter(thread); + tsr.addCountFilter(1); + tsr.setSuspendPolicy(suspendPolicy); + tsr.putProperty("number", property); + return tsr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingThreadStartRequest() : " + e); + log3(" ThreadStartRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ThreadStartRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005/TestDescription.java new file mode 100644 index 00000000000..d44191cd679 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * ThreadStartRequest. + * The test checks up that a result of the method + * com.sun.jdi.ThreadStartRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include three thread's states: not started, running, dead. + * The test works as follows: + * The debugger program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter005; + * the debuggee program - nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter005 + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.ThreadStartRequest.addThreadFilter.addthreadfilter005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005a.java new file mode 100644 index 00000000000..160caab47d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005a.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.ThreadStartRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addaddthreadfilter005 JDI test. + */ + +public class addthreadfilter005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter005a thread1 = null; + + static addthreadfilter005aTestClass objTC = new addthreadfilter005aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter005a("thread1"); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();"); + methodForCommunication(); + } + break; + + case 2: + try { + thread1.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter005a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter005a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter "); + + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + log1(" 'run': exit "); + } + return; + } + } + +} + +class addthreadfilter005aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Transport/name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Transport/name/name001.java new file mode 100644 index 00000000000..6d129e722ca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Transport/name/name001.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.Transport.name; + +import java.io.PrintStream; +import java.io.Serializable; + +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jdi.VirtualMachineManager; +import com.sun.jdi.Bootstrap; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.Transport; + + +/** + * The test for the implementation of an object of the type Transport
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.connect.Transport.name()
    + * complies with its specification:
    + * "Returns a short identifier for the transport."
    + *
    + * In case of the method returns string
    + * beginning with another prefix,
    + * the test produces the return value 97 and
    + * a corresponding error message.
    + * Otherwise, the test is passed and produces
    + * the return value 95 and no message.
    + */ + + +public class name001 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + 95); // JCK-compatible exit status + } + + public static int run(String argv[], PrintStream out) { + + int exitCode = 0; + int exitCode0 = 0; + int exitCode2 = 2; + + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + + for (Connector connector : vmm.allConnectors()) { + String sName = connector.transport().name(); + + out.println("Transport name: " + sName); + + if (sName == null || sName == "") { + exitCode = exitCode2; + out.println("Transport name is empty"); + } + } + + if (exitCode != exitCode0) + out.println("TEST FAILED"); + + return exitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Transport/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Transport/name/name001/TestDescription.java new file mode 100644 index 00000000000..721f671c406 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Transport/name/name001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Transport/name/name001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Connector.Transport. + * The test checks up that a result of the method + * com.sun.jdi.connect.Connector.Transport.name() + * complies with its specification: + * public java.lang.String name() + * Returns a short identifier for the transport. + * Transport implementors should follow similar naming conventions as are + * used with packages to avoid name collisions. For example, the Sun transport + * implementations have names prefixed with "com.sun.jdi.". + * Returns: the name of this transport. + * Note. The name of this transport is either "dt_socket" or "dt_shmem" + * as it is defined in the document "Connection and Invocation Details". + * The test works as follows: + * - Virtual Machine Manager is invoked. + * - To Transport objects of Connectors + * the following check is applied: + * String returned by tTransport.name() should be + * either "dt_socket" or "dt_shmem" + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Fixed 6265221. Transport.name() only checked for emptiness. Former behavior is unspecified and incorrect. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Transport.name.name001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Transport.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001.java new file mode 100644 index 00000000000..66f47634a30 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Type.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class hashcode001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.Type.hashCode."; + private final static String className = "hashcode001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] checkedFields = { + "z0", "z1", "z2", + "b0", "b1", "b2", + "c0", "c1", "c2", + "d0", "d1", "d2", + "f0", "f1", "f2", + "i0", "i1", "i2", + "l0", "l1", "l2", + "r0", "r1", "r2", + "s0", "s1", "s2", + "o0", "o1", "o2" + }; + + private final static String[] checkedMethods = { + "Mv", "MvS", "MvI", + "MvY", "MvU", "MvR", + "MvP", "MvN", + "Mz", "Mb", "Mc", + "Md", "Mf", "Mi", + "Ml", "Mr", "Ms", "Mo" + }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + display("Checking hashCode() method for Type mirrors of debuggee's fields"); + + for (int i = 0; i < checkedFields.length; i++) { + checkHashCodeForField(i); + } + + display("Checking hashCode() method for Type mirrors of debuggee's void methods"); + + for (int i = 0; i < checkedMethods.length; i++) { + checkHashCodeForMethod(i); + } + + display("Checking completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + + private static void checkHashCodeForField (int ind) { + Type type; + try { + type = (Type)debuggeeClass.fieldByName(checkedFields[ind]).type(); + } catch (ClassNotLoadedException e) { + throw new Failure("Unexpected ClassNotLoadedException was thrown while first getting Type " + + "mirror for field : " + checkedFields[ind]); + } + int hCode = type.hashCode(); + + if (hCode == 0) { + complain("hashCode() returns 0 for debuggee's field : " + checkedFields[ind] ); + exitStatus = Consts.TEST_FAILED; + } + + int hCode1 = type.hashCode(); + if (hCode != hCode1) { + complain("hashCode() is not consistent for debuggee's field : " + checkedFields[ind] + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + // get new reference to the same debuggee's field and get hash code. + try { + type = (Type)debuggeeClass.fieldByName(checkedFields[ind]).type(); + } catch (ClassNotLoadedException e) { + throw new Failure("Unexpected ClassNotLoadedException was thrown while second getting Type " + + "mirror for field : " + checkedFields[ind]); + } + hCode1 = type.hashCode(); + if (hCode != hCode1) { + complain("hashCode() does not return same value for equal mirror of debuggee's field : " + checkedFields[ind] + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + display("hashCode() returns for debuggee's field : " + checkedFields[ind] + " : " + hCode); + } + + private static void checkHashCodeForMethod (int ind) { + Type type; + try { + type = (Type)methodByName(debuggeeClass, checkedMethods[ind]).returnType(); + } catch (ClassNotLoadedException e) { + throw new Failure("Unexpected ClassNotLoadedException was thrown while first getting Type " + + "mirror for method : " + checkedMethods[ind]); + } + int hCode = type.hashCode(); + + if (hCode == 0) { + complain("hashCode() returns 0 for debuggee's method : " + checkedMethods[ind] ); + exitStatus = Consts.TEST_FAILED; + } + + int hCode1 = type.hashCode(); + if (hCode != hCode1) { + complain("hashCode() is not consistent for debuggee's method : " + checkedMethods[ind] + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + // get new reference to the same debuggee's method and get hash code. + try { + type = (Type)methodByName(debuggeeClass, checkedMethods[ind]).returnType(); + } catch (ClassNotLoadedException e) { + throw new Failure("Unexpected ClassNotLoadedException was thrown while second getting Type " + + "mirror for method : " + checkedMethods[ind]); + } + hCode1 = type.hashCode(); + if (hCode != hCode1) { + complain("hashCode() does not return same value for equal mirror of debuggee's method : " + checkedMethods[ind] + + "\n\t first value :" + hCode + " ; second value : " + hCode1); + exitStatus = Consts.TEST_FAILED; + } + + display("hashCode() returns for debuggee's method : " + checkedMethods[ind] + " : " + hCode); + } + + private static Method methodByName(ReferenceType refType, String methodName) { + List methodList = refType.methodsByName(methodName); + if (methodList == null) return null; + + Method method = (Method) methodList.get(0); + return method; + } + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001/TestDescription.java new file mode 100644 index 00000000000..c8de097eba5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Type/hashCode/hashcode001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public hashCode() method of an implementing class of + * com.sun.jdi.Type interface. + * The test checks an assertion cited from spec for hashCode() method of + * java.lang.Object class: + * The general contract of hashCode is: + * - Whenever it is invoked on the same object more than once during + * an execution of a Java application, the hashCode method must + * consistently return the same integer, provided no information used + * in equals comparisons on the object is modified. + * ... + * - If two objects are equal according to the equals(Object) method, + * then calling the hashCode method on each of the two objects must + * produce the same integer result. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for Type + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Type.hashCode.hashcode001 + * nsk.jdi.Type.hashCode.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Type.hashCode.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001a.java new file mode 100644 index 00000000000..c52ca9821c6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/hashCode/hashcode001a.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.Type.hashCode; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class hashcode001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static boolean z0 = true, z1[] = {z0}, z2[][] = {z1}; + static byte b0 = 0, b1[] = {b0}, b2[][] = {b1}; + static char c0 = '0', c1[] = {c0}, c2[][] = {c1}; + static double d0 = 0.0d, d1[] = {d0}, d2[][] = {d1}; + static float f0 = 0.0f, f1[] = {f0}, f2[][] = {f1}; + static int i0 = 0, i1[] = {i0}, i2[][] = {i1}; + static long l0 = 0, l1[] = {l0}, l2[][] = {l1}; + static short r0 = 0, r1[] = {r0}, r2[][] = {r1}; + + static String s0 = "0", s1[] = {s0}, s2[][] = {s1}; + static Object o0 = new Object(), o1[] = {o0}, o2[][] = {o1}; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(hashcode001.SIGNAL_READY); + receiveSignal(hashcode001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + + void Mv() {}; + + static void MvS() {}; + strictfp void MvI() {}; + synchronized void MvY() {}; + public void MvU() {}; + protected void MvR() {}; + private void MvP() {}; + native void MvN(); + + boolean Mz () { return true; }; + byte Mb () { return (byte)0; }; + char Mc () { return '0'; }; + double Md () { return 0.0d; }; + float Mf () { return 0.0f; }; + int Mi () { return 0; }; + long Ml () { return (long)0; }; + short Mr () { return (short)0; }; + + String Ms () { return "0"; }; + Object Mo () { return new Object(); }; + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001.java new file mode 100644 index 00000000000..18aa4a20782 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Type.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * Type.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Type.name()
    + * complies with its spec when a type is one of primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee executes the following :
    + * static boolean bl = false;
    + * static byte bt = 0;
    + * static char ch = 0;
    + * static double db = 0.0d;
    + * static float fl = 0.0f;
    + * static int in = 0;
    + * static long ln = 0;
    + * static short sh = 0;
    + *
    + * for all of the above primitive type variables,
    + * a debugger forms their corresponding Type objects
    + * from which it forms text representations of
    + * original types in the debuggee in String variables
    + * named blName, btName, and etc.
    + *
    + * Then the debugger checks up that
    + * the each of the following is true :
    + *
    + * blName.equals("boolean")
    + * btName.equals("byte")
    + * chName.equals("char")
    + * dbName.equals("double")
    + * flName.equals("float")
    + * inName.equals("int")
    + * lnName.equals("long")
    + * shName.equals("short")
    + *
    + */ + +public class name001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Type/name/name001", + sHeader2 = "--> name001: ", + sHeader3 = "##> name001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new name001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Type.name.name001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("name001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl = execClass.fieldByName("bl"); + Field fsbt = execClass.fieldByName("bt"); + Field fsch = execClass.fieldByName("ch"); + Field fsdb = execClass.fieldByName("db"); + Field fsfl = execClass.fieldByName("fl"); + Field fsin = execClass.fieldByName("in"); + Field fsln = execClass.fieldByName("ln"); + Field fssh = execClass.fieldByName("sh"); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean + String blName = execClass.getValue(fsbl).type().name(); + if (!blName.equals("boolean")) { + expresult = 1; + log3("ERROR: !blName.equals('boolean')"); + } + break; + + case 1: // byte + String btName = execClass.getValue(fsbt).type().name(); + if (!btName.equals("byte")) { + expresult = 1; + log3("ERROR: !btName.equals('byte')"); + } + break; + + case 2: // char + String chName = execClass.getValue(fsch).type().name(); + if (!chName.equals("char")) { + expresult = 1; + log3("ERROR: !chName.equals('char')"); + } + break; + + case 3: // double + String dbName = execClass.getValue(fsdb).type().name(); + if (!dbName.equals("double")) { + expresult = 1; + log3("ERROR: !dbName.equals('double')"); + } + break; + + case 4: // float + String flName = execClass.getValue(fsfl).type().name(); + if (!flName.equals("float")) { + expresult = 1; + log3("ERROR: !flName.equals('float')"); + } + break; + + case 5: // int + String inName = execClass.getValue(fsin).type().name(); + if (!inName.equals("int")) { + expresult = 1; + log3("ERROR: !inName.equals('int')"); + } + break; + + case 6: // long + String lnName = execClass.getValue(fsln).type().name(); + if (!lnName.equals("long")) { + expresult = 1; + log3("ERROR: !lnName.equals('long')"); + } + break; + + case 7: // short + String shName = execClass.getValue(fssh).type().name(); + if (!shName.equals("short")) { + expresult = 1; + log3("ERROR: !shName.equals('short')"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001/TestDescription.java new file mode 100644 index 00000000000..9c47a8c3adb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Type/name/name001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Type. + * The test checks up that a result of the method + * com.sun.jdi.Type.name() + * complies with its spec: + * public java.lang.String name() + * Returns: a text representation of this type. + * when the type is one of primitive types. + * The test works as follows: + * A debugger program - nsk.jdi.Type.name.name001; + * a debuggee program - nsk.jdi.Type.name.name001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Type.name.name001 + * nsk.jdi.Type.name.name001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Type.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001a.java new file mode 100644 index 00000000000..3b24a0185ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name001a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Type.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the name001a JDI test. + */ + +public class name001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> name001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> name001a: " + message); + } + + //====================================================== test program + + static boolean bl = false; + static byte bt = 0; + static char ch = 0; + static double db = 0.0d; + static float fl = 0.0f; + static int in = 0; + static long ln = 0; + static short sh = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Type.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Type.name()
    + * complies with its spec when
    + * a type is one of ReferenceType(s).
    + *
    + * The test checks up that the names of three Type objects,
    + * corresponding in a debugger to the following in a debuggee:
    + *
    + * array of a class type - "ClassForCheck_2[] class3" field,
    + * class type - "ClassForCheck_2 class2" field,
    + * interface type - "IntefaceForCheck iface" field
    + *
    + * are as follows:
    + * "nsk.jdi.Type.name.ClassForCheck_2[]"
    + * "nsk.jdi.Type.name.ClassForCheck"
    + * "nsk.jdi.Type.name.InterfaceForCheck"
    + *
    + */ + +public class name002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Type/name/name002", + sHeader2 = "--> name002: ", + sHeader3 = "##> name002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new name002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Type.name.name002a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("name002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String namePrefix = "nsk.jdi.Type.name"; + List listOfDebuggeeClasses = null; + ReferenceType reftypeObj = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // ArrayType + + listOfDebuggeeClasses = + vm.classesByName(namePrefix + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ArrayType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field arrayField = reftypeObj.fieldByName("class3"); + + Type arrayfieldType = null; + try { + arrayfieldType = arrayField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: arrayfieldType = arrayField.type();"); + expresult =1; + break ; + } + + String arrayfieldTypeName = arrayfieldType.name(); + if (!arrayfieldTypeName.equals(namePrefix + ".ClassForCheck_2[]")) { + expresult = 1; + log3("ERROR: !arrayfieldTypeName.equals(namePrefix + '.ClassForCheck_2[]')"); + } + break; + + case 1: // ClassType + listOfDebuggeeClasses = + vm.classesByName(namePrefix + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ClassType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field classField = reftypeObj.fieldByName("class2"); + + Type classfieldType = null; + try { + classfieldType = classField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: classfieldType = classField.type();"); + expresult =1; + break ; + } + + String classfieldTypeName = classfieldType.name(); + if (!classfieldTypeName.equals(namePrefix + ".ClassForCheck_2")) { + expresult = 1; + log3("ERROR: !classfieldTypeName.equals(namePrefix + '.ClassForCheck_2')"); + } + break; + + case 2: // InterfaceType + listOfDebuggeeClasses = + vm.classesByName(namePrefix + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for InterfaceType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field ifaceField = reftypeObj.fieldByName("iface"); + + Type ifacefieldType = null; + try { + ifacefieldType = ifaceField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: ifacefieldType = ifaceField.type();"); + expresult =1; + break ; + } + + String ifacefieldTypeName = ifacefieldType.name(); + if (!ifacefieldTypeName.equals(namePrefix + ".InterfaceForCheck")) { + expresult = 1; + log3("ERROR: !ifacefieldTypeName.equals(namePrefix + '.InterfaceForCheck')"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002/TestDescription.java new file mode 100644 index 00000000000..a2b13036ae2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Type/name/name002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Type. + * The test checks up that a result of the method + * com.sun.jdi.Type.name() + * complies with its spec: + * public java.lang.String name() + * Returns: a text representation of this type. + * when the type is one of the ReferenceType(s). + * The test works as follows: + * A debugger program - nsk.jdi.Type.name.name002; + * a debuggee program - nsk.jdi.Type.name.name002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Type.name.name002 + * nsk.jdi.Type.name.name002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Type.name.name002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002a.java new file mode 100644 index 00000000000..5c156312e15 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name002a.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Type.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the name002 JDI test. + */ + +public class name002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> name002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> name002a: " + message); + } + + //====================================================== test program + + static ClassForCheck class1 = new ClassForCheck(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Type.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Type.name()
    + * complies with its spec when
    + * a type is the VoidType.
    + *
    + * The test checks up that the name of the Type objects,
    + * corresponding in a debugger to
    + * the void return type of a test method in a debuggee
    + * is "void".
    + *
    + */ + +public class name003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Type/name/name003", + sHeader2 = "--> name003: ", + sHeader3 = "##> name003: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new name003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Type.name.name003a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("name003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + List methods = execClass.methodsByName("testMethod"); + if (methods.size() != 1) { + testExitCode = FAILED; + log3("ERROR: methods.size() != 1"); + break ; + } + + Method testmethod = (Method) methods.get(0); + + Type testmethodReturnType = null; + try { + testmethodReturnType = testmethod.returnType(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: testmethodReturnType = testmethod.returnType();"); + testExitCode = FAILED; + break ; + } + + String testmethodReturnTypeName = testmethodReturnType.name(); + + if (!testmethodReturnTypeName.equals("void")) { + testExitCode = FAILED; + log3("ERROR: !testmethodReturnTypeName.equals('void')"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003/TestDescription.java new file mode 100644 index 00000000000..8aa12a27a1f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Type/name/name003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Type. + * The test checks up that a result of the method + * com.sun.jdi.Type.name() + * complies with its spec: + * public java.lang.String name() + * Returns: a text representation of this type. + * when the type is the VoidType. + * The test works as follows: + * A debugger program - nsk.jdi.Type.name.name003; + * a debuggee program - nsk.jdi.Type.name.name003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Type.name.name003 + * nsk.jdi.Type.name.name003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Type.name.name003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003a.java new file mode 100644 index 00000000000..3f2cfdd2758 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/name/name003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Type.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the name003 JDI test. + */ + +public class name003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> name003a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> name003a: " + message); + } + + //====================================================== test program + + public void testMethod () { + return; + } + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Type.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Type.signature()
    + * complies with its spec when a type is one of primitive types.
    + *
    + * The cases for testing are as follows.
    + *
    + * When a gebuggee executes the following :
    + * static boolean bl = false;
    + * static byte bt = 0;
    + * static char ch = 0;
    + * static double db = 0.0d;
    + * static float fl = 0.0f;
    + * static int in = 0;
    + * static long ln = 0;
    + * static short sh = 0;
    + *
    + * for all of the above primitive type variables,
    + * a debugger forms their corresponding Type objects
    + * from which it forms text representations of
    + * original types in a debuggee in String variables
    + * named blSignature, btSignature, and etc.
    + *
    + * Then the debugger checks up that
    + *the each of the following is true :
    + *
    + * blSignature.equals("Z")
    + * btSignature.equals("B")
    + * chSignature.equals("C")
    + * dbSignature.equals("D")
    + * flSignature.equals("F")
    + * inSignature.equals("I")
    + * lnSignature.equals("J")
    + * shSignature.equals("S")
    + */ + +public class signature001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Type/signature/signature001", + sHeader2 = "--> signature001: ", + sHeader3 = "##> signature001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new signature001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Type.signature.signature001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("signature001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl = execClass.fieldByName("bl"); + Field fsbt = execClass.fieldByName("bt"); + Field fsch = execClass.fieldByName("ch"); + Field fsdb = execClass.fieldByName("db"); + Field fsfl = execClass.fieldByName("fl"); + Field fsin = execClass.fieldByName("in"); + Field fsln = execClass.fieldByName("ln"); + Field fssh = execClass.fieldByName("sh"); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // boolean + String blSignature = + execClass.getValue(fsbl).type().signature(); + if (!blSignature.equals("Z")) { + expresult = 1; + log3("ERROR: !blSignature.equals('Z')"); + } + break; + + case 1: // byte + String btSignature = + execClass.getValue(fsbt).type().signature(); + if (!btSignature.equals("B")) { + expresult = 1; + log3("ERROR: !btSignature.equals('B')"); + } + break; + + case 2: // char + String chSignature = + execClass.getValue(fsch).type().signature(); + if (!chSignature.equals("C")) { + expresult = 1; + log3("ERROR: !chSignature.equals('C')"); + } + break; + + case 3: // double + String dbSignature = + execClass.getValue(fsdb).type().signature(); + if (!dbSignature.equals("D")) { + expresult = 1; + log3("ERROR: !dbSignature.equals('D')"); + } + break; + + case 4: // float + String flSignature = + execClass.getValue(fsfl).type().signature(); + if (!flSignature.equals("F")) { + expresult = 1; + log3("ERROR: !flSignature.equals('F')"); + } + break; + + case 5: // int + String inSignature = + execClass.getValue(fsin).type().signature(); + if (!inSignature.equals("I")) { + expresult = 1; + log3("ERROR: !inSignature.equals('I')"); + } + break; + + case 6: // long + String lnSignature = + execClass.getValue(fsln).type().signature(); + if (!lnSignature.equals("J")) { + expresult = 1; + log3("ERROR: !lnSignature.equals('J')"); + } + break; + + case 7: // short + String shSignature = + execClass.getValue(fssh).type().signature(); + if (!shSignature.equals("S")) { + expresult = 1; + log3("ERROR: !shSignature.equals('S')"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001/TestDescription.java new file mode 100644 index 00000000000..75199690039 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Type/signature/signature001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Type. + * The test checks up that a result of the method + * com.sun.jdi.Type.signature() + * complies with its spec: + * public java.lang.String signature() + * Returns the JNI-style signature for this type. + * For primitive classes the returned signature is the signature of + * the corresponding primitive type; for example, + * "I" is returned as the signature of the class + * represented by java.lang.Integer#TYPE. + * Returns: the string containing the type signature. + * when the type is one of primitive types. + * The test works as follows: + * A debugger program - nsk.jdi.Type.signature.signature001; + * a debuggee program - nsk.jdi.Type.signature.signature001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Type.signature.signature001 + * nsk.jdi.Type.signature.signature001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Type.signature.signature001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001a.java new file mode 100644 index 00000000000..c0fedb15afb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature001a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Type.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the signature001 JDI test. + */ + +public class signature001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> signature001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> signature001a: " + message); + } + + //====================================================== test program + + static boolean bl = false; + static byte bt = 0; + static char ch = 0; + static double db = 0.0d; + static float fl = 0.0f; + static int in = 0; + static long ln = 0; + static short sh = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Type.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Type.signature()
    + * a type is one of ReferenceType(s).
    + *
    + * The test checks up that the signatures of three Type objects,
    + * corresponding in a debugger to the following in a debuggee:
    + *
    + * array of a class type - "ClassForCheck_2[] class3" field,
    + * class type - "ClassForCheck_2 class2" field,
    + * interface type - "IntefaceForCheck iface" field
    + *
    + * are as follows:
    + * "[Lnsk/jdi/Type/signature/ClassForCheck_2[];"
    + * "Lnsk/jdi/Type/signature/ClassForCheck;"
    + * "Lnsk/jdi/Type/signature/InterfaceForCheck;"
    + *
    + */ + +public class signature002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Type/signature/signature002", + sHeader2 = "--> signature002: ", + sHeader3 = "##> signature002: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new signature002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Type.signature.signature002a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("signature002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String namePrefix = "nsk.jdi.Type.signature"; + String signaturePrefix = "nsk/jdi/Type/signature"; + List listOfDebuggeeClasses = null; + ReferenceType reftypeObj = null; + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // ArrayType + + listOfDebuggeeClasses = + vm.classesByName(namePrefix + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ArrayType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field arrayField = reftypeObj.fieldByName("class3"); + + Type arrayfieldType = null; + try { + arrayfieldType = arrayField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: arrayfieldType = arrayField.type();"); + expresult =1; + break ; + } + + String arrayfieldTypeSignature = + arrayfieldType.signature(); + if (!arrayfieldTypeSignature.equals( + "[L" + signaturePrefix + "/ClassForCheck_2;")) { + expresult = 1; + log3("ERROR: !arrayfieldTypeSignature.equals(namePrefix +" + + "'.ClassForCheck_2[]')" /* + " " + arrayfieldTypeSignature */ ); + } + break; + + case 1: // ClassType + listOfDebuggeeClasses = + vm.classesByName(namePrefix + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for ClassType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field classField = reftypeObj.fieldByName("class2"); + + Type classfieldType = null; + try { + classfieldType = classField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: classfieldType = classField.type();"); + expresult =1; + break ; + } + + String classfieldTypeSignature = + classfieldType.signature(); + if (!classfieldTypeSignature.equals( + "L" + signaturePrefix + "/ClassForCheck_2;")) { + expresult = 1; + log3("ERROR: !classfieldTypeSignature.equals(namePrefix + " + + "'.ClassForCheck_2')" /* + " " + classfieldTypeSignature */ ); + } + break; + + case 2: // InterfaceType + listOfDebuggeeClasses = + vm.classesByName(namePrefix + ".ClassForCheck"); + if (listOfDebuggeeClasses.size() != 1) { + expresult = 1; + log3("ERROR: for InterfaceType listOfDebuggeeClasses.size() != 1"); + break ; + } + reftypeObj = (ReferenceType) listOfDebuggeeClasses.get(0); + + Field ifaceField = reftypeObj.fieldByName("iface"); + + Type ifacefieldType = null; + try { + ifacefieldType = ifaceField.type(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: ifacefieldType = ifaceField.type();"); + expresult =1; + break ; + } + + String ifacefieldTypeSignature = + ifacefieldType.signature(); + if (!ifacefieldTypeSignature.equals( + "L" + signaturePrefix + "/InterfaceForCheck;")) { + expresult = 1; + log3("ERROR: !ifacefieldTypeSignature.equals(namePrefix + " + + "'.InterfaceForCheck')" /* + " " + ifacefieldTypeSignature */ ); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002/TestDescription.java new file mode 100644 index 00000000000..2bce3a311ed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Type/signature/signature002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Type. + * The test checks up that a result of the method + * com.sun.jdi.Type.signature() + * complies with its spec: + * public java.lang.String signature() + * Returns the JNI-style signature for this type. + * For primitive classes the returned signature is the signature of + * the corresponding primitive type; for example, + * "I" is returned as the signature of the class + * represented by java.lang.Integer#TYPE. + * Returns: the string containing the type signature. + * when the type is one of the ReferenceType(s). + * The test works as follows: + * A debugger program - nsk.jdi.Type.signature.signature002; + * a debuggee program - nsk.jdi.Type.signature.signature002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Type.signature.signature002 + * nsk.jdi.Type.signature.signature002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Type.signature.signature002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002a.java new file mode 100644 index 00000000000..a3cea639dba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature002a.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Type.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the signature002 JDI test. + */ + +public class signature002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> signature002a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> signature002a: " + message); + } + + //====================================================== test program + + static ClassForCheck class1 = new ClassForCheck(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Type.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Type.signature()
    + * complies with its spec when
    + * a type is the VoidType.
    + *
    + * The test checks up that the signature of the Type objects,
    + * corresponding in a debugger to
    + * the void return type of a test method in a debuggee
    + * is "V".
    + *
    + */ + +public class signature003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Type/signature/signature003", + sHeader2 = "--> signature003: ", + sHeader3 = "##> signature003: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new signature003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Type.signature.signature003a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("signature003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + List methods = execClass.methodsByName("testMethod"); + if (methods.size() != 1) { + testExitCode = FAILED; + log3("ERROR: methods.size() != 1"); + break ; + } + + Method testmethod = (Method) methods.get(0); + + Type testmethodReturnType = null; + try { + testmethodReturnType = testmethod.returnType(); + } catch ( ClassNotLoadedException e ) { + log3("ERROR: testmethodReturnType = testmethod.returnType();"); + testExitCode = FAILED; + break ; + } + + String testmethodReturnTypeSignature = testmethodReturnType.signature(); + if (!testmethodReturnTypeSignature.equals("V")) { + testExitCode = FAILED; + log3("ERROR: !testmethodReturnTypeSignature.equals('V')" + + " " + testmethodReturnTypeSignature); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003/TestDescription.java new file mode 100644 index 00000000000..3ff3e27b52e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Type/signature/signature003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Type. + * The test checks up that a result of the method + * com.sun.jdi.Type.signature() + * complies with its spec: + * public java.lang.String signature() + * Returns the JNI-style signature for this type. + * For primitive classes the returned signature is the signature of + * the corresponding primitive type; for example, + * "I" is returned as the signature of the class + * represented by java.lang.Integer#TYPE. + * Returns: the string containing the type signature. + * when the type is the VoidType. + * The test works as follows: + * A debugger program - nsk.jdi.Type.signature.signature003; + * a debuggee program - nsk.jdi.Type.signature.signature003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Type.signature.signature003 + * nsk.jdi.Type.signature.signature003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Type.signature.signature003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003a.java new file mode 100644 index 00000000000..9efdd906bb3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Type/signature/signature003a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Type.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the signature003 JDI test. + */ + +public class signature003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> signature003a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> signature003a: " + message); + } + + //====================================================== test program + + public void testMethod () { + return; + } + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get MainClass and MainInter from debugee + mainClass = debugee.classByName(mainClassName); + if (mainClass == null) { + log.complain("debuger FAILURE> Class " + mainClassName + " not " + + "found."); + return 2; + } + mainInter = debugee.classByName(mainInterName); + if (mainInter == null) { + log.complain("debuger FAILURE> Interface " + mainInterName + " not " + + "found."); + return 2; + } + + // Check all fields from MainClass + log.display("debuger> Total fields in " + mainClassName + ": " + + + mainClass.allFields().size()); + for (int i = 0; i < FIELD_NAME_CLASS.length; i++) { + Field field; + String name; + ReferenceType declType; + boolean equal; + + try { + field = mainClass.fieldByName(FIELD_NAME_CLASS[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + FIELD_NAME_CLASS[i] + " from " + mainClassName); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + declType = field.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 2> Declaring type is null " + + " for field " + name + " in class " + + mainClassName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + name + " from class " + + mainClassName + " read."); + try { + equal = declType.equals(mainClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 3> Cannot compare reference " + + " types " + declType.name() + " and " + + mainClassName); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 4> Declaring type of field " + + name + " is " + declType.name() + ", but should " + + "be " + mainClassName); + testFailed = true; + } + } + + // Check all fields from MainInter + log.display("debuger> Total fields in " + mainInterName + ": " + + + mainInter.allFields().size()); + for (int i = 0; i < FIELD_NAME_INTER.length; i++) { + Field field; + String name; + ReferenceType declType; + boolean equal; + + try { + field = mainInter.fieldByName(FIELD_NAME_INTER[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 5> Can't get field by name " + + FIELD_NAME_INTER[i] + " from " + mainInterName); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + declType = field.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 6> Declaring type is null " + + " for field " + name + " in class " + + mainInterName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + name + " from interface " + + mainInterName + " read."); + try { + equal = declType.equals(mainInter); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 7> Cannot compare reference " + + " types " + declType.name() + " and " + + mainInterName); + log.complain("debuger FAILURE 7> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 8> Declaring type of field " + + name + " is " + declType.name() + ", but should " + + "be " + mainInterName); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001/TestDescription.java new file mode 100644 index 00000000000..437379c6e8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the declaringType() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public ReferenceType declaringType() + * Returns the type in which this component was declared. The returned + * ReferenceType mirrors either a class or an interface in the target VM. + * nsk/jdi/TypeComponent/declaringType/declType001 checks assertions: + * public java.lang.String declaringType() + * 1. Returns the type in which a field was declared if the type mirrors + * a class in the target VM. + * 2. Returns the type in which a field was declared if the type mirrors + * an interface in the target VM. + * Debugger gets each field from debuggee (MainClass and MainInter) calling + * by name and then checks if method declaringType() returns the same + * reference type. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype001 + * nsk.jdi.TypeComponent.declaringType.decltype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001a.java new file mode 100644 index 00000000000..4606386d964 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001a.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class decltype001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + MainClass mainClass = new MainClass(); + ImplClass implClass = new ImplClass(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +// User class and interface +class Class {} +interface Inter {} + +class MainClass { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + static long l0S, l1S[]={l0S}, l2S[][]={l1S}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + Class X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + static Long L0S, L1S[]={L0S}, L2S[][]={L1S}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + Inter E0, E1[]={E0}, E2[][]={E1}; + + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + static Inter E0S, E1S[]={E0S}, E2S[][]={E1S}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; +} + +class ImplClass implements MainInter {} + +interface MainInter { + boolean z0 = true, z1[]={z0}, z2[][]={z1}; + byte b0 = 1, b1[]={b0}, b2[][]={b1}; + char c0 = '\u00ff', c1[]={c0}, c2[][]={c1}; + double d0 = 0, d1[]={d0}, d2[][]={d1}; + float f0 = 0f, f1[]={f0}, f2[][]={f1}; + int i0 = 0, i1[]={i0}, i2[][]={i1}; + long l0 = 0l, l1[]={l0}, l2[][]={l1}; + short r0 = 0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + public long lU0 = 1l, lU1[]={lU0}, lU2[][]={lU1}; + static long l0S = 1l, l1S[]={l0S}, l2S[][]={l1S}; + + Class X0 = new Class(), X1[]={X0}, X2[][]={X1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + public Long LU0 = new Long(1), LU1[]={LU0}, LU2[][]={LU1}; + static Long L0S = new Long(1), L1S[]={L0S}, L2S[][]={L1S}; + + Inter E0 = null, E1[]={E0}, E2[][]={E1}; + + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + public Inter EU0 = null, EU1[]={EU0}, EU2[][]={EU1}; + static Inter E0S = null, E1S[]={E0S}, E2S[][]={E1S}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002.java new file mode 100644 index 00000000000..2093e40c4ac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class decltype002 { + final static String FIELD_NAME_CLASS[] = { + "z0", "z1", "z2", + "b0", "b1", "b2", + "c0", "c1", "c2", + "d0", "d1", "d2", + "f0", "f1", "f2", + "i0", "i1", "i2", + "l0", "l1", "l2", + "r0", "r1", "r2", + + "lF0", "lF1", "lF2", + "lP0", "lP1", "lP2", + "lU0", "lU1", "lU2", + "lR0", "lR1", "lR2", + "l0S", "l1S", "l2S", + "lT0", "lT1", "lT2", + "lV0", "lV1", "lV2", + + "X0", "X1", "X2", + "O0", "O1", "O2", + + "LF0", "LF1", "LF2", + "LP0", "LP1", "LP2", + "LU0", "LU1", "LU2", + "LR0", "LR1", "LR2", + "L0S", "L1S", "L2S", + "LT0", "LT1", "LT2", + "LV0", "LV1", "LV2", + + "E0", "E1", "E2", + "EF0", "EF1", "EF2", + "EP0", "EP1", "EP2", + "EU0", "EU1", "EU2", + "ER0", "ER1", "ER2", + "E0S", "E1S", "E2S", + "ET0", "ET1", "ET2", + "EV0", "EV1", "EV2" + }; + final static String FIELD_NAME_INTER[] = { + "z0", "z1", "z2", + "b0", "b1", "b2", + "c0", "c1", "c2", + "d0", "d1", "d2", + "f0", "f1", "f2", + "i0", "i1", "i2", + "l0", "l1", "l2", + "r0", "r1", "r2", + + "lF0", "lF1", "lF2", + "lU0", "lU1", "lU2", + "l0S", "l1S", "l2S", + + "X0", "X1", "X2", + "O0", "O1", "O2", + + "LF0", "LF1", "LF2", + "LU0", "LU1", "LU2", + "L0S", "L1S", "L2S", + + "E0", "E1", "E2", + "EF0", "EF1", "EF2", + "EU0", "EU1", "EU2", + "E0S", "E1S", "E2S", + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.declaringType."; + private final static String className = "decltype002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String mainClassName = prefix + "decltype002aMainClass"; + private final static String sameClassName = prefix + "decltype002aSameClass"; + private final static String mainInterName = prefix + "decltype002aMainInter"; + private final static String sameInterName = prefix + "decltype002aSameInter"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + ReferenceType mainClass; + ReferenceType sameClass; + ReferenceType mainInter; + ReferenceType sameInter; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get decltype002aMainClass, decltype002aMainInter, decltype002aSameClass and decltype002aSameInter from debugee + mainClass = debugee.classByName(mainClassName); + if (mainClass == null) { + log.complain("debuger FAILURE> Class " + mainClassName + " not " + + "found."); + return 2; + } + sameClass = debugee.classByName(sameClassName); + if (sameClass == null) { + log.complain("debuger FAILURE> Class " + sameClassName + " not " + + "found."); + return 2; + } + mainInter = debugee.classByName(mainInterName); + if (mainInter == null) { + log.complain("debuger FAILURE> Interface " + mainInterName + " not " + + "found."); + return 2; + } + sameInter = debugee.classByName(sameInterName); + if (sameClass == null) { + log.complain("debuger FAILURE> Interface " + sameInterName + " not " + + "found."); + return 2; + } + + // Check all fields from decltype002aSameClass + log.display("debuger> Total fields in " + mainClassName + ": " + + + mainClass.allFields().size()); + for (int i = 0; i < FIELD_NAME_CLASS.length; i++) { + Field field; + String name; + ReferenceType declType; + boolean equal; + + try { + field = sameClass.fieldByName(FIELD_NAME_CLASS[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + FIELD_NAME_CLASS[i] + " from type " + sameClassName); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + declType = field.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 2> Declaring type is null " + + " for field " + name + " in class " + + sameClassName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + name + " with declaring " + + "type " + declType.name() + " from class " + + sameClassName + " read."); + try { + equal = declType.equals(mainClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 3> Cannot compare reference " + + " types " + declType.name() + " and " + + mainClassName); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 4> Declaring type of field " + + name + " is " + declType.name() + ", but should " + + "be " + mainClassName); + testFailed = true; + } + } + + // Check all fields from decltype002aSameInter + log.display("debuger> Total fields in " + mainInterName + ": " + + + mainInter.allFields().size()); + for (int i = 0; i < FIELD_NAME_INTER.length; i++) { + Field field; + String name; + ReferenceType declType; + boolean equal; + + try { + field = sameInter.fieldByName(FIELD_NAME_INTER[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 5> Can't get field by name " + + FIELD_NAME_INTER[i] + " from type " + + sameInterName); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + declType = field.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 6> Declaring type is null " + + " for field " + name + " in class " + + sameInterName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + name + " with declaring " + + "type " + declType.name() + " from class " + + sameInterName + " read."); + try { + equal = declType.equals(mainInter); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 7> Cannot compare reference " + + " types " + declType.name() + " and " + + mainInterName); + log.complain("debuger FAILURE 7> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 8> Declaring type of field " + + name + " is " + declType.name() + ", but should " + + "be " + mainInterName); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002/TestDescription.java new file mode 100644 index 00000000000..f40535fd5f7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the declaringType() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public ReferenceType declaringType() + * Returns the type in which this component was declared. The returned + * ReferenceType mirrors either a class or an interface in the target VM. + * nsk/jdi/TypeComponent/declaringType/declType002 checks assertions: + * public java.lang.String declaringType() + * 1. Returns the type in which a field was declared if the type mirrors + * a class in the target VM. + * 2. Returns the type in which a field was declared if the type mirrors + * an interface in the target VM. + * There are classes MainClass and SameClass that extends it and do not + * override fields from super class; interfaces MainInter and SameInter that + * extends MainInter and do not override fields from it. + * Debugger gets each field from debuggee (SameClass and SameInter) calling + * by name and then checks if method declaringType() returns reference type + * where all fields were declared (MainClass and MainInter). + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype002 + * nsk.jdi.TypeComponent.declaringType.decltype002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002a.java new file mode 100644 index 00000000000..1be71f70fd3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002a.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class decltype002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); +// MainClass mainClass = new MainClass(); + decltype002aSameClass sameClass = new decltype002aSameClass(); + decltype002aImplClass implClass = new decltype002aImplClass(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +// User class and interface +class decltype002aClass {} +interface decltype002aInter {} + +class decltype002aSameClass extends decltype002aMainClass { + // All fields are the same as in MainClass +} + +class decltype002aMainClass { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + static long l0S, l1S[]={l0S}, l2S[][]={l1S}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + decltype002aClass X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + static Long L0S, L1S[]={L0S}, L2S[][]={L1S}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + decltype002aInter E0, E1[]={E0}, E2[][]={E1}; + + final decltype002aInter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + private decltype002aInter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public decltype002aInter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected decltype002aInter ER0, ER1[]={ER0}, ER2[][]={ER1}; + static decltype002aInter E0S, E1S[]={E0S}, E2S[][]={E1S}; + transient decltype002aInter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile decltype002aInter EV0, EV1[]={EV0}, EV2[][]={EV1}; +} + +class decltype002aImplClass implements decltype002aSameInter {} + +interface decltype002aSameInter extends decltype002aMainInter { + // All fields are the same as in MainInter +} + +interface decltype002aMainInter { + boolean z0 = true, z1[]={z0}, z2[][]={z1}; + byte b0 = 1, b1[]={b0}, b2[][]={b1}; + char c0 = '\u00ff', c1[]={c0}, c2[][]={c1}; + double d0 = 0, d1[]={d0}, d2[][]={d1}; + float f0 = 0f, f1[]={f0}, f2[][]={f1}; + int i0 = 0, i1[]={i0}, i2[][]={i1}; + long l0 = 0l, l1[]={l0}, l2[][]={l1}; + short r0 = 0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + public long lU0 = 1l, lU1[]={lU0}, lU2[][]={lU1}; + static long l0S = 1l, l1S[]={l0S}, l2S[][]={l1S}; + + decltype002aClass X0 = new decltype002aClass(), X1[]={X0}, X2[][]={X1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + public Long LU0 = new Long(1), LU1[]={LU0}, LU2[][]={LU1}; + static Long L0S = new Long(1), L1S[]={L0S}, L2S[][]={L1S}; + + decltype002aInter E0 = null, E1[]={E0}, E2[][]={E1}; + + final decltype002aInter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + public decltype002aInter EU0 = null, EU1[]={EU0}, EU2[][]={EU1}; + static decltype002aInter E0S = null, E1S[]={E0S}, E2S[][]={E1S}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003.java new file mode 100644 index 00000000000..d1af14dd610 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class decltype003 { + final static String FIELD_NAME_CLASS[] = { + "z0", "z1", "z2", + "b0", "b1", "b2", + "c0", "c1", "c2", + "d0", "d1", "d2", + "f0", "f1", "f2", + "i0", "i1", "i2", + "l0", "l1", "l2", + "r0", "r1", "r2", + + "lF0", "lF1", "lF2", + "lP0", "lP1", "lP2", + "lU0", "lU1", "lU2", + "lR0", "lR1", "lR2", + "l0S", "l1S", "l2S", + "lT0", "lT1", "lT2", + "lV0", "lV1", "lV2", + + "X0", "X1", "X2", + "O0", "O1", "O2", + + "LF0", "LF1", "LF2", + "LP0", "LP1", "LP2", + "LU0", "LU1", "LU2", + "LR0", "LR1", "LR2", + "L0S", "L1S", "L2S", + "LT0", "LT1", "LT2", + "LV0", "LV1", "LV2", + + "E0", "E1", "E2", + "EF0", "EF1", "EF2", + "EP0", "EP1", "EP2", + "EU0", "EU1", "EU2", + "ER0", "ER1", "ER2", + "E0S", "E1S", "E2S", + "ET0", "ET1", "ET2", + "EV0", "EV1", "EV2" + }; + final static String FIELD_NAME_INTER[] = { + "z0", "z1", "z2", + "b0", "b1", "b2", + "c0", "c1", "c2", + "d0", "d1", "d2", + "f0", "f1", "f2", + "i0", "i1", "i2", + "l0", "l1", "l2", + "r0", "r1", "r2", + + "lF0", "lF1", "lF2", + "lU0", "lU1", "lU2", + "l0S", "l1S", "l2S", + + "X0", "X1", "X2", + "O0", "O1", "O2", + + "LF0", "LF1", "LF2", + "LU0", "LU1", "LU2", + "L0S", "L1S", "L2S", + + "E0", "E1", "E2", + "EF0", "EF1", "EF2", + "EU0", "EU1", "EU2", + "E0S", "E1S", "E2S", + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.declaringType."; + private final static String className = "decltype003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String overClassName = prefix + "decltype003aOverridenClass"; + private final static String overInterName = prefix + "decltype003aOverridenInter"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + ReferenceType overClass; + ReferenceType overInter; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get OverridenClass and OverridenInter from debugee + overClass = debugee.classByName(overClassName); + if (overClass == null) { + log.complain("debuger FAILURE> Class " + overClassName + " not " + + "found."); + return 2; + } + overInter = debugee.classByName(overInterName); + if (overInter == null) { + log.complain("debuger FAILURE> Interface " + overInterName + " not " + + "found."); + return 2; + } + + // Check all fields from OverridenClass + log.display("debuger> Total fields in " + overClassName + ": " + + + overClass.fields().size()); + for (int i = 0; i < FIELD_NAME_CLASS.length; i++) { + Field field; + String name; + ReferenceType declType; + boolean equal; + + try { + field = overClass.fieldByName(FIELD_NAME_CLASS[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + FIELD_NAME_CLASS[i] + " from type " + + overClassName); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + declType = field.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 2> Declaring type is null " + + " for field " + name + " in class " + + overClassName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + name + " with declaring " + + "type " + declType.name() + " from class " + + overClassName + " read."); + try { + equal = declType.equals(overClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 3> Cannot compare reference " + + " types " + declType.name() + " and " + + overClassName); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 4> Declaring type of field " + + name + " is " + declType.name() + ", but should " + + "be " + overClassName); + testFailed = true; + } + } + + // Check all fields from OverridenInter + log.display("debuger> Total fields in " + overInterName + ": " + + + overInter.fields().size()); + for (int i = 0; i < FIELD_NAME_INTER.length; i++) { + Field field; + String name; + ReferenceType declType; + boolean equal; + + try { + field = overInter.fieldByName(FIELD_NAME_INTER[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 5> Can't get field by name " + + FIELD_NAME_INTER[i] + " from type " + + overInterName); + log.complain("debuger FAILURE 5> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + declType = field.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 6> Declaring type is null " + + " for field " + name + " in class " + + overInterName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " field " + name + " with declaring " + + "type " + declType.name() + " from class " + + overInterName + " read."); + try { + equal = declType.equals(overInter); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 7> Cannot compare reference " + + " types " + declType.name() + " and " + + overInterName); + log.complain("debuger FAILURE 7> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 8> Declaring type of field " + + name + " is " + declType.name() + ", but should " + + "be " + overInterName); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003/TestDescription.java new file mode 100644 index 00000000000..ade78a9dd5e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the declaringType() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public ReferenceType declaringType() + * Returns the type in which this component was declared. The returned + * ReferenceType mirrors either a class or an interface in the target VM. + * nsk/jdi/TypeComponent/declaringType/declType003 checks assertion: + * public java.lang.String declaringType() + * 1. Returns the type in which a field was declared if the type mirrors + * a class in the target VM. + * 2. Returns the type in which a field was declared if the type mirrors + * an interface in the target VM. + * There are classes MainClass and OverridenClass extends MainClass and + * overrides all fields; interfaces MainInter and OverridenInter that + * extends MainInter and overrides all fields from it. + * Debugger gets each field from debuggee (OverridenClass and OverridenInter) + * calling by name and then checks if method declaringType() returns reference + * type where all fields were declared (OverridenClass and OverridenInter). + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype003 + * nsk.jdi.TypeComponent.declaringType.decltype003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003a.java new file mode 100644 index 00000000000..e8387e5ad70 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003a.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class decltype003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + decltype003aOverridenClass overridenClass = new decltype003aOverridenClass(); + decltype003aImplClass implClass = new decltype003aImplClass(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +// User class and interface +class decltype003aClass {} +interface decltype003aInter {} + +class decltype003aOverridenClass extends decltype003aMainClass { + // All fields are overriden from MainClass + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + static long l0S, l1S[]={l0S}, l2S[][]={l1S}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + decltype003aClass X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + static Long L0S, L1S[]={L0S}, L2S[][]={L1S}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + decltype003aInter E0, E1[]={E0}, E2[][]={E1}; + + final decltype003aInter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + private decltype003aInter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public decltype003aInter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected decltype003aInter ER0, ER1[]={ER0}, ER2[][]={ER1}; + static decltype003aInter E0S, E1S[]={E0S}, E2S[][]={E1S}; + transient decltype003aInter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile decltype003aInter EV0, EV1[]={EV0}, EV2[][]={EV1}; +} + +class decltype003aMainClass { + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + static long l0S, l1S[]={l0S}, l2S[][]={l1S}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + decltype003aClass X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + static Long L0S, L1S[]={L0S}, L2S[][]={L1S}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + decltype003aInter E0, E1[]={E0}, E2[][]={E1}; + + final decltype003aInter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + private decltype003aInter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public decltype003aInter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected decltype003aInter ER0, ER1[]={ER0}, ER2[][]={ER1}; + static decltype003aInter E0S, E1S[]={E0S}, E2S[][]={E1S}; + transient decltype003aInter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile decltype003aInter EV0, EV1[]={EV0}, EV2[][]={EV1}; +} + +class decltype003aImplClass implements decltype003aOverridenInter {} + +interface decltype003aOverridenInter extends decltype003aMainInter { + // All fields are overriden from decltype003aMainInter + + boolean z0 = true, z1[]={z0}, z2[][]={z1}; + byte b0 = 1, b1[]={b0}, b2[][]={b1}; + char c0 = '\u00ff', c1[]={c0}, c2[][]={c1}; + double d0 = 0, d1[]={d0}, d2[][]={d1}; + float f0 = 0f, f1[]={f0}, f2[][]={f1}; + int i0 = 0, i1[]={i0}, i2[][]={i1}; + long l0 = 0l, l1[]={l0}, l2[][]={l1}; + short r0 = 0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + public long lU0 = 1l, lU1[]={lU0}, lU2[][]={lU1}; + static long l0S = 1l, l1S[]={l0S}, l2S[][]={l1S}; + + decltype003aClass X0 = new decltype003aClass(), X1[]={X0}, X2[][]={X1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + public Long LU0 = new Long(1), LU1[]={LU0}, LU2[][]={LU1}; + static Long L0S = new Long(1), L1S[]={L0S}, L2S[][]={L1S}; + + decltype003aInter E0 = null, E1[]={E0}, E2[][]={E1}; + + final decltype003aInter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + public decltype003aInter EU0 = null, EU1[]={EU0}, EU2[][]={EU1}; + static decltype003aInter E0S = null, E1S[]={E0S}, E2S[][]={E1S}; +} + +interface decltype003aMainInter { + boolean z0 = true, z1[]={z0}, z2[][]={z1}; + byte b0 = 1, b1[]={b0}, b2[][]={b1}; + char c0 = '\u00ff', c1[]={c0}, c2[][]={c1}; + double d0 = 0, d1[]={d0}, d2[][]={d1}; + float f0 = 0f, f1[]={f0}, f2[][]={f1}; + int i0 = 0, i1[]={i0}, i2[][]={i1}; + long l0 = 0l, l1[]={l0}, l2[][]={l1}; + short r0 = 0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + public long lU0 = 1l, lU1[]={lU0}, lU2[][]={lU1}; + static long l0S = 1l, l1S[]={l0S}, l2S[][]={l1S}; + + decltype003aClass X0 = new decltype003aClass(), X1[]={X0}, X2[][]={X1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + public Long LU0 = new Long(1), LU1[]={LU0}, LU2[][]={LU1}; + static Long L0S = new Long(1), L1S[]={L0S}, L2S[][]={L1S}; + + decltype003aInter E0 = null, E1[]={E0}, E2[][]={E1}; + + final decltype003aInter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + public decltype003aInter EU0 = null, EU1[]={EU0}, EU2[][]={EU1}; + static decltype003aInter E0S = null, E1S[]={E0S}, E2S[][]={E1S}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004.java new file mode 100644 index 00000000000..6dcef73ea31 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004.java @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class decltype004 { + final static String METHOD_NAME_CLASS[] = { + "Mv", + "Mz", "Mz1", "Mz2", + "Mb", "Mb1", "Mb2", + "Mc", "Mc1", "Mc2", + "Md", "Md1", "Md2", + "Mf", "Mf1", "Mf2", + "Mi", "Mi1", "Mi2", + "Ml", "Ml1", "Ml2", + "Mr", "Mr1", "Mr2", + + "MvF", "MlF", "MlF1", "MlF2", + "MvN", "MlN", "MlN1", "MlN2", + "MvS", "MlS", "MlS1", "MlS2", + "MvI", "MlI", "MlI1", "MlI2", + "MvY", "MlY", "MlY1", "MlY2", + "MvU", "MlU", "MlU1", "MlU2", + "MvR", "MlR", "MlR1", "MlR2", + "MvP", "MlP", "MlP1", "MlP2", + + "MX", "MX1", "MX2", + "MO", "MO1", "MO2", + + "MLF", "MLF1", "MLF2", + "MLN", "MLN1", "MLN2", + "MLS", "MLS1", "MLS2", + "MLI", "MLI1", "MLI2", + "MLY", "MLY1", "MLY2", + "MLU", "MLU1", "MLU2", + "MLR", "MLR1", "MLR2", + "MLP", "MLP1", "MLP2", + + "ME", "ME1", "ME2", + "MEF", "MEF1", "MEF2", + "MEN", "MEN1", "MEN2", + "MES", "ME1S", "ME2S", + "MEI", "MEI1", "MEI2", + "MEY", "MEY1", "MEY2", + "MEU", "MEU1", "MEU2", + "MER", "MER1", "MER2", + "MEP", "MEP1", "MEP2" + }; + final static String METHOD_NAME_INTER[] = { + "Mv", + "Mz", "Mz1", "Mz2", + "Mb", "Mb1", "Mb2", + "Mc", "Mc1", "Mc2", + "Md", "Md1", "Md2", + "Mf", "Mf1", "Mf2", + "Mi", "Mi1", "Mi2", + "Ml", "Ml1", "Ml2", + "Mr", "Mr1", "Mr2", + + "MvU", "MlU", "MlU1", "MlU2", + + "MX", "MX1", "MX2", + "MO", "MO1", "MO2", + + "MLU", "MLU1", "MLU2", + + "ME", "ME1", "ME2", + "MEU", "MEU1", "MEU2", + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.declaringType."; + private final static String className = "decltype004"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String mainClassName = prefix + "decltype004aMainClass"; + private final static String mainInterName = prefix + "decltype004aMainInter"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + ReferenceType mainClass; + ReferenceType mainInter; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get MainClass and decltype004aMainInter from debugee + mainClass = debugee.classByName(mainClassName); + if (mainClass == null) { + log.complain("debuger FAILURE> Class " + mainClassName + " not " + + "found."); + return 2; + } + mainInter = debugee.classByName(mainInterName); + if (mainInter == null) { + log.complain("debuger FAILURE> Interface " + mainInterName + " not " + + "found."); + return 2; + } + + // Check all methods from MainClass + log.display("debuger> Total methods in " + mainClassName + ": " + + + mainClass.methods().size()); + for (int i = 0; i < METHOD_NAME_CLASS.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + ReferenceType declType; + boolean equal; + + try { + listOfMethods = mainClass.methodsByName(METHOD_NAME_CLASS[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get method by name " + + METHOD_NAME_CLASS[i]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + METHOD_NAME_CLASS[i] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + declType = method.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 3> Declaring type is null " + + " for method " + name + " in class " + + mainClassName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " method " + name + " from class " + + mainClassName + " read."); + try { + equal = declType.equals(mainClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot compare reference " + + " types " + declType.name() + " and " + + mainClassName); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 5> Declaring type of method " + + name + " is " + declType.name() + ", but should " + + "be " + mainClassName); + testFailed = true; + } + } + + // Check all methods from MainInter + log.display("debuger> Total methods in " + mainInterName + ": " + + + mainInter.methods().size()); + for (int i = 0; i < METHOD_NAME_INTER.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + ReferenceType declType; + boolean equal; + + try { + listOfMethods = mainInter.methodsByName(METHOD_NAME_INTER[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 6> Can't get method by name " + + METHOD_NAME_INTER[i]); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 7> Number of methods by name " + + METHOD_NAME_INTER[i] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + declType = method.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 8> Declaring type is null " + + " for method " + name + " in class " + + mainInterName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " method " + name + " from interface " + + mainInterName + " read."); + try { + equal = declType.equals(mainInter); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 9> Cannot compare reference " + + " types " + declType.name() + " and " + + mainInterName); + log.complain("debuger FAILURE 9> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 10> Declaring type of method " + + name + " is " + declType.name() + ", but should " + + "be " + mainInterName); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004/TestDescription.java new file mode 100644 index 00000000000..84e31330466 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the declaringType() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public ReferenceType declaringType() + * Returns the type in which this component was declared. The returned + * ReferenceType mirrors either a class or an interface in the target VM. + * nsk/jdi/TypeComponent/declaringType/declType004 checks assertions: + * public java.lang.String declaringType() + * 1. Returns the type in which a method was declared if the type mirrors + * a class in the target VM. + * 2. Returns the type in which a method was declared if the type mirrors + * an interface in the target VM. + * Debugger gets each method from debuggee (MainClass and MainInter) calling + * by name and then checks if declaringType() returns the same reference type. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype004 + * nsk.jdi.TypeComponent.declaringType.decltype004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004a.java new file mode 100644 index 00000000000..700b2947afb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype004a.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class decltype004a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + decltype004aMainClass mainClass = new decltype004aMainClass(); + decltype004aImplClass implClass = new decltype004aImplClass(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +// User class and interface +class decltype004aClass {} +interface decltype004aInter {} + +class decltype004aMainClass { + void Mv() {}; + boolean Mz(boolean z) { return !z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + final void MvF() {}; + final long MlF(long l) { return l; }; + final long[] MlF1(long l[]) { return l; }; + final long[][] MlF2(long l[][]){ return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + decltype004aClass MX(decltype004aClass X) { return X; }; + decltype004aClass[] MX1(decltype004aClass X[]) { return X; }; + decltype004aClass[][] MX2(decltype004aClass X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + final Long MLF(Long L) { return L; }; + final Long[] MLF1(Long L[]) { return L; }; + final Long[][] MLF2(Long L[][]) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long L[]) { return L; }; + static Long[][] MLS2(Long L[][]) { return L; }; + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + decltype004aInter ME(decltype004aInter E) { return E; }; + decltype004aInter[] ME1(decltype004aInter[] E) { return E; }; + decltype004aInter[][] ME2(decltype004aInter[][] E) { return E; }; + + final decltype004aInter MEF(decltype004aInter E) { return E; }; + final decltype004aInter[] MEF1(decltype004aInter[] E) { return E; }; + final decltype004aInter[][] MEF2(decltype004aInter[][] E) { return E; }; + native decltype004aInter MEN(decltype004aInter E); + native decltype004aInter[] MEN1(decltype004aInter[] E); + native decltype004aInter[][] MEN2(decltype004aInter[][] E); + static decltype004aInter MES(decltype004aInter E) { return E; }; + static decltype004aInter[] ME1S(decltype004aInter[] E) { return E; }; + static decltype004aInter[][] ME2S(decltype004aInter[][] E) { return E; }; + strictfp decltype004aInter MEI(decltype004aInter E) { return E; }; + strictfp decltype004aInter[] MEI1(decltype004aInter[] E) { return E; }; + strictfp decltype004aInter[][] MEI2(decltype004aInter[][] E) { return E; }; + synchronized decltype004aInter MEY(decltype004aInter E) { return E; }; + synchronized decltype004aInter[] MEY1(decltype004aInter[] E) { return E; }; + synchronized decltype004aInter[][] MEY2(decltype004aInter[][] E) { return E; }; + public decltype004aInter MEU(decltype004aInter E) { return E; }; + public decltype004aInter[] MEU1(decltype004aInter[] E) { return E; }; + public decltype004aInter[][] MEU2(decltype004aInter[][] E) { return E; }; + protected decltype004aInter MER(decltype004aInter E) { return E; }; + protected decltype004aInter[] MER1(decltype004aInter[] E) { return E; }; + protected decltype004aInter[][] MER2(decltype004aInter[][] E) { return E; }; + private decltype004aInter MEP(decltype004aInter E) { return E; }; + private decltype004aInter[] MEP1(decltype004aInter[] E) { return E; }; + private decltype004aInter[][] MEP2(decltype004aInter[][] E) { return E; }; +} + +class decltype004aImplClass implements decltype004aMainInter { + public void Mv() {}; + public boolean Mz(boolean z) { return !z; }; + public boolean[] Mz1(boolean z[]) { return z; }; + public boolean[][] Mz2(boolean z[][]) { return z; }; + public byte Mb(byte b) { return b; }; + public byte[] Mb1(byte b[]) { return b; }; + public byte[][] Mb2(byte b[][]) { return b; }; + public char Mc(char c) { return c; }; + public char[] Mc1(char c[]) { return c; }; + public char[][] Mc2(char c[][]) { return c; }; + public double Md(double d) { return d; }; + public double[] Md1(double d[]) { return d; }; + public double[][] Md2(double d[][]) { return d; }; + public float Mf(float f) { return f; }; + public float[] Mf1(float f[]) { return f; }; + public float[][] Mf2(float f[][]) { return f; }; + public int Mi(int i) { return i; }; + public int[] Mi1(int i[]) { return i; }; + public int[][] Mi2(int i[][]) { return i; }; + public long Ml(long l) { return l; }; + public long[] Ml1(long l[]) { return l; }; + public long[][] Ml2(long l[][]) { return l; }; + public short Mr(short r) { return r; }; + public short[] Mr1(short r[]) { return r; }; + public short[][] Mr2(short r[][]) { return r; }; + + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + + public decltype004aClass MX(decltype004aClass X) { return X; }; + public decltype004aClass[] MX1(decltype004aClass X[]) { return X; }; + public decltype004aClass[][] MX2(decltype004aClass X[][]) { return X; }; + public Object MO(Object O) { return O; }; + public Object[] MO1(Object[] O) { return O; }; + public Object[][] MO2(Object[][] O) { return O; }; + + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + + public decltype004aInter ME(decltype004aInter E) { return E; }; + public decltype004aInter[] ME1(decltype004aInter[] E) { return E; }; + public decltype004aInter[][] ME2(decltype004aInter[][] E) { return E; }; + + public decltype004aInter MEU(decltype004aInter E) { return E; }; + public decltype004aInter[] MEU1(decltype004aInter[] E) { return E; }; + public decltype004aInter[][] MEU2(decltype004aInter[][] E) { return E; }; +} + +interface decltype004aMainInter { + void Mv(); + boolean Mz(boolean z); + boolean[] Mz1(boolean z[]); + boolean[][] Mz2(boolean z[][]); + byte Mb(byte b); + byte[] Mb1(byte b[]); + byte[][] Mb2(byte b[][]); + char Mc(char c); + char[] Mc1(char c[]); + char[][] Mc2(char c[][]); + double Md(double d); + double[] Md1(double d[]); + double[][] Md2(double d[][]); + float Mf(float f); + float[] Mf1(float f[]); + float[][] Mf2(float f[][]); + int Mi(int i); + int[] Mi1(int i[]); + int[][] Mi2(int i[][]); + long Ml(long l); + long[] Ml1(long l[]); + long[][] Ml2(long l[][]); + short Mr(short r); + short[] Mr1(short r[]); + short[][] Mr2(short r[][]); + + public void MvU(); + public long MlU(long l); + public long[] MlU1(long l[]); + public long[][] MlU2(long l[][]); + + decltype004aClass MX(decltype004aClass X); + decltype004aClass[] MX1(decltype004aClass X[]); + decltype004aClass[][] MX2(decltype004aClass X[][]); + Object MO(Object O); + Object[] MO1(Object[] O); + Object[][] MO2(Object[][] O); + + public Long MLU(Long L); + public Long[] MLU1(Long[] L); + public Long[][] MLU2(Long[][] L); + + decltype004aInter ME(decltype004aInter E); + decltype004aInter[] ME1(decltype004aInter[] E); + decltype004aInter[][] ME2(decltype004aInter[][] E); + + public decltype004aInter MEU(decltype004aInter E); + public decltype004aInter[] MEU1(decltype004aInter[] E); + public decltype004aInter[][] MEU2(decltype004aInter[][] E); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005.java new file mode 100644 index 00000000000..2a5379b510e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class decltype005 { + final static String METHOD_NAME_CLASS[] = { + "Mv", + "Mz", "Mz1", "Mz2", + "Mb", "Mb1", "Mb2", + "Mc", "Mc1", "Mc2", + "Md", "Md1", "Md2", + "Mf", "Mf1", "Mf2", + "Mi", "Mi1", "Mi2", + "Ml", "Ml1", "Ml2", + "Mr", "Mr1", "Mr2", + + "MvF", "MlF", "MlF1", "MlF2", + "MvN", "MlN", "MlN1", "MlN2", + "MvS", "MlS", "MlS1", "MlS2", + "MvI", "MlI", "MlI1", "MlI2", + "MvY", "MlY", "MlY1", "MlY2", + "MvU", "MlU", "MlU1", "MlU2", + "MvR", "MlR", "MlR1", "MlR2", + "MvP", "MlP", "MlP1", "MlP2", + + "MX", "MX1", "MX2", + "MO", "MO1", "MO2", + + "MLF", "MLF1", "MLF2", + "MLN", "MLN1", "MLN2", + "MLS", "MLS1", "MLS2", + "MLI", "MLI1", "MLI2", + "MLY", "MLY1", "MLY2", + "MLU", "MLU1", "MLU2", + "MLR", "MLR1", "MLR2", + "MLP", "MLP1", "MLP2", + + "ME", "ME1", "ME2", + "MEF", "MEF1", "MEF2", + "MEN", "MEN1", "MEN2", + "MES", "ME1S", "ME2S", + "MEI", "MEI1", "MEI2", + "MEY", "MEY1", "MEY2", + "MEU", "MEU1", "MEU2", + "MER", "MER1", "MER2", + "MEP", "MEP1", "MEP2" + }; + final static String METHOD_NAME_INTER[] = { + "Mv", + "Mz", "Mz1", "Mz2", + "Mb", "Mb1", "Mb2", + "Mc", "Mc1", "Mc2", + "Md", "Md1", "Md2", + "Mf", "Mf1", "Mf2", + "Mi", "Mi1", "Mi2", + "Ml", "Ml1", "Ml2", + "Mr", "Mr1", "Mr2", + + "MvU", "MlU", "MlU1", "MlU2", + + "MX", "MX1", "MX2", + "MO", "MO1", "MO2", + + "MLU", "MLU1", "MLU2", + + "ME", "ME1", "ME2", + "MEU", "MEU1", "MEU2", + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.declaringType."; + private final static String className = "decltype005"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String mainClassName = prefix + "decltype005aMainClass"; + private final static String sameClassName = prefix + "decltype005aSameClass"; + private final static String mainInterName = prefix + "decltype005aMainInter"; + private final static String sameInterName = prefix + "decltype005aSameInter"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + ReferenceType mainClass; + ReferenceType sameClass; + ReferenceType mainInter; + ReferenceType sameInter; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get MainClass, MainInter, SameClass and SameInter from debugee + mainClass = debugee.classByName(mainClassName); + if (mainClass == null) { + log.complain("debuger FAILURE> Class " + mainClassName + " not " + + "found."); + return 2; + } + sameClass = debugee.classByName(sameClassName); + if (sameClass == null) { + log.complain("debuger FAILURE> Class " + sameClassName + " not " + + "found."); + return 2; + } + mainInter = debugee.classByName(mainInterName); + if (mainClass == null) { + log.complain("debuger FAILURE> Interface " + mainInterName + " not " + + "found."); + return 2; + } + sameInter = debugee.classByName(sameInterName); + if (sameClass == null) { + log.complain("debuger FAILURE> Interface " + sameInterName + " not " + + "found."); + return 2; + } + + // Check all methods from SameClass + log.display("debuger> Total methods in " + mainClassName + ": " + + + mainClass.methods().size()); + for (int i = 0; i < METHOD_NAME_CLASS.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + ReferenceType declType; + boolean equal; + + try { + listOfMethods = sameClass.methodsByName(METHOD_NAME_CLASS[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get method by name " + + METHOD_NAME_CLASS[i]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + METHOD_NAME_CLASS[i] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + declType = method.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 3> Declaring type is null " + + " for method " + name + " in class " + + sameClassName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " method " + name + " with declaring " + + "type " + declType.name() + " from class " + + sameClassName + " read."); + try { + equal = declType.equals(mainClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot compare reference " + + " types " + declType.name() + " and " + + mainClassName); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 5> Declaring type of method " + + name + " is " + declType.name() + ", but should " + + "be " + mainClassName); + testFailed = true; + } + } + + // Check all methods from SameInter + log.display("debuger> Total methods in " + mainInterName + ": " + + + mainInter.methods().size()); + for (int i = 0; i < METHOD_NAME_INTER.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + ReferenceType declType; + boolean equal; + + try { + listOfMethods = sameInter.methodsByName(METHOD_NAME_INTER[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 6> Can't get method by name " + + METHOD_NAME_INTER[i]); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 7> Number of methods by name " + + METHOD_NAME_INTER[i] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + declType = method.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 8> Declaring type is null " + + " for method " + name + " in class " + + sameInterName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " method " + name + " with declaring " + + "type " + declType.name() + " from class " + + sameInterName + " read."); + try { + equal = declType.equals(mainInter); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 9> Cannot compare reference " + + " types " + declType.name() + " and " + + mainInterName); + log.complain("debuger FAILURE 9> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 10> Declaring type of method " + + name + " is " + declType.name() + ", but should " + + "be " + mainInterName); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005/TestDescription.java new file mode 100644 index 00000000000..c6de3c388ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the declaringType() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public ReferenceType declaringType() + * Returns the type in which this component was declared. The returned + * ReferenceType mirrors either a class or an interface in the target VM. + * nsk/jdi/TypeComponent/declaringType/declType005 checks assertions: + * public java.lang.String declaringType() + * 1. Returns the type in which a method was declared if the type mirrors + * a class in the target VM. + * 2. Returns the type in which a method was declared if the type mirrors + * an interface in the target VM. + * There are classes MainClass and SameClass that extends it and do not + * override methods from super class; interfaces MainInter and SameInter that + * extends MainInter and do not override methods from it. + * Debugger gets each method from debuggee (SameClass and SameInter) calling + * by name and then checks if method declaringType() returns reference type + * where all methods were declared (MainClass and MainInter). + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype005 + * nsk.jdi.TypeComponent.declaringType.decltype005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005a.java new file mode 100644 index 00000000000..036d049335b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype005a.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class decltype005a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + decltype005aSameClass sameClass = new decltype005aSameClass(); + decltype005aImplClass implClass = new decltype005aImplClass(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +// User class and interface +class decltype005aClass {} +interface decltype005aInter {} + +class decltype005aSameClass extends decltype005aMainClass { + // All methods are the same as in MainClass +} + +class decltype005aMainClass { + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + final void MvF() {}; + final long MlF(long l) { return l; }; + final long[] MlF1(long l[]) { return l; }; + final long[][] MlF2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + decltype005aClass MX(decltype005aClass X) { return X; }; + decltype005aClass[] MX1(decltype005aClass X[]) { return X; }; + decltype005aClass[][] MX2(decltype005aClass X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + final Long MLF(Long L) { return L; }; + final Long[] MLF1(Long[] L) { return L; }; + final Long[][] MLF2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long L[]) { return L; }; + static Long[][] MLS2(Long L[][]) { return L; }; + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + decltype005aInter ME(decltype005aInter E) { return E; }; + decltype005aInter[] ME1(decltype005aInter[] E) { return E; }; + decltype005aInter[][] ME2(decltype005aInter[][] E) { return E; }; + + final decltype005aInter MEF(decltype005aInter E) { return E; }; + final decltype005aInter[] MEF1(decltype005aInter[] E) { return E; }; + final decltype005aInter[][] MEF2(decltype005aInter[][] E) { return E; }; + native decltype005aInter MEN(decltype005aInter E); + native decltype005aInter[] MEN1(decltype005aInter[] E); + native decltype005aInter[][] MEN2(decltype005aInter[][] E); + static decltype005aInter MES(decltype005aInter E) { return E; }; + static decltype005aInter[] ME1S(decltype005aInter[] E) { return E; }; + static decltype005aInter[][] ME2S(decltype005aInter[][] E) { return E; }; + strictfp decltype005aInter MEI(decltype005aInter E) { return E; }; + strictfp decltype005aInter[] MEI1(decltype005aInter[] E) { return E; }; + strictfp decltype005aInter[][] MEI2(decltype005aInter[][] E) { return E; }; + synchronized decltype005aInter MEY(decltype005aInter E) { return E; }; + synchronized decltype005aInter[] MEY1(decltype005aInter[] E) { return E; }; + synchronized decltype005aInter[][] MEY2(decltype005aInter[][] E) { return E; }; + public decltype005aInter MEU(decltype005aInter E) { return E; }; + public decltype005aInter[] MEU1(decltype005aInter[] E) { return E; }; + public decltype005aInter[][] MEU2(decltype005aInter[][] E) { return E; }; + protected decltype005aInter MER(decltype005aInter E) { return E; }; + protected decltype005aInter[] MER1(decltype005aInter[] E) { return E; }; + protected decltype005aInter[][] MER2(decltype005aInter[][] E) { return E; }; + private decltype005aInter MEP(decltype005aInter E) { return E; }; + private decltype005aInter[] MEP1(decltype005aInter[] E) { return E; }; + private decltype005aInter[][] MEP2(decltype005aInter[][] E) { return E; }; +} + +class decltype005aImplClass implements decltype005aSameInter { + public void Mv() {}; + public boolean Mz(boolean z) { return !z; }; + public boolean[] Mz1(boolean z[]) { return z; }; + public boolean[][] Mz2(boolean z[][]) { return z; }; + public byte Mb(byte b) { return b; }; + public byte[] Mb1(byte b[]) { return b; }; + public byte[][] Mb2(byte b[][]) { return b; }; + public char Mc(char c) { return c; }; + public char[] Mc1(char c[]) { return c; }; + public char[][] Mc2(char c[][]) { return c; }; + public double Md(double d) { return d; }; + public double[] Md1(double d[]) { return d; }; + public double[][] Md2(double d[][]) { return d; }; + public float Mf(float f) { return f; }; + public float[] Mf1(float f[]) { return f; }; + public float[][] Mf2(float f[][]) { return f; }; + public int Mi(int i) { return i; }; + public int[] Mi1(int i[]) { return i; }; + public int[][] Mi2(int i[][]) { return i; }; + public long Ml(long l) { return l; }; + public long[] Ml1(long l[]) { return l; }; + public long[][] Ml2(long l[][]) { return l; }; + public short Mr(short r) { return r; }; + public short[] Mr1(short r[]) { return r; }; + public short[][] Mr2(short r[][]) { return r; }; + + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + + public decltype005aClass MX(decltype005aClass X) { return X; }; + public decltype005aClass[] MX1(decltype005aClass X[]) { return X; }; + public decltype005aClass[][] MX2(decltype005aClass X[][]) { return X; }; + public Object MO(Object O) { return O; }; + public Object[] MO1(Object[] O) { return O; }; + public Object[][] MO2(Object[][] O) { return O; }; + + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + + public decltype005aInter ME(decltype005aInter E) { return E; }; + public decltype005aInter[] ME1(decltype005aInter[] E) { return E; }; + public decltype005aInter[][] ME2(decltype005aInter[][] E) { return E; }; + + public decltype005aInter MEU(decltype005aInter E) { return E; }; + public decltype005aInter[] MEU1(decltype005aInter[] E) { return E; }; + public decltype005aInter[][] MEU2(decltype005aInter[][] E) { return E; }; +} + +interface decltype005aSameInter extends decltype005aMainInter { + // All methods are the same as in MainInter +} + +interface decltype005aMainInter { + void Mv(); + boolean Mz(boolean z); + boolean[] Mz1(boolean z[]); + boolean[][] Mz2(boolean z[][]); + byte Mb(byte b); + byte[] Mb1(byte b[]); + byte[][] Mb2(byte b[][]); + char Mc(char c); + char[] Mc1(char c[]); + char[][] Mc2(char c[][]); + double Md(double d); + double[] Md1(double d[]); + double[][] Md2(double d[][]); + float Mf(float f); + float[] Mf1(float f[]); + float[][] Mf2(float f[][]); + int Mi(int i); + int[] Mi1(int i[]); + int[][] Mi2(int i[][]); + long Ml(long l); + long[] Ml1(long l[]); + long[][] Ml2(long l[][]); + short Mr(short r); + short[] Mr1(short r[]); + short[][] Mr2(short r[][]); + + public void MvU(); + public long MlU(long l); + public long[] MlU1(long l[]); + public long[][] MlU2(long l[][]); + + decltype005aClass MX(decltype005aClass X); + decltype005aClass[] MX1(decltype005aClass X[]); + decltype005aClass[][] MX2(decltype005aClass X[][]); + Object MO(Object O); + Object[] MO1(Object[] O); + Object[][] MO2(Object[][] O); + + public Long MLU(Long L); + public Long[] MLU1(Long[] L); + public Long[][] MLU2(Long[][] L); + + decltype005aInter ME(decltype005aInter E); + decltype005aInter[] ME1(decltype005aInter[] E); + decltype005aInter[][] ME2(decltype005aInter[][] E); + + public decltype005aInter MEU(decltype005aInter E); + public decltype005aInter[] MEU1(decltype005aInter[] E); + public decltype005aInter[][] MEU2(decltype005aInter[][] E); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006.java new file mode 100644 index 00000000000..0787af781d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class decltype006 { + final static String METHOD_NAME_CLASS[] = { + "Mv", + "Mz", "Mz1", "Mz2", + "Mb", "Mb1", "Mb2", + "Mc", "Mc1", "Mc2", + "Md", "Md1", "Md2", + "Mf", "Mf1", "Mf2", + "Mi", "Mi1", "Mi2", + "Ml", "Ml1", "Ml2", + "Mr", "Mr1", "Mr2", + + "MvN", "MlN", "MlN1", "MlN2", + "MvS", "MlS", "MlS1", "MlS2", + "MvI", "MlI", "MlI1", "MlI2", + "MvY", "MlY", "MlY1", "MlY2", + "MvU", "MlU", "MlU1", "MlU2", + "MvR", "MlR", "MlR1", "MlR2", + "MvP", "MlP", "MlP1", "MlP2", + + "MX", "MX1", "MX2", + "MO", "MO1", "MO2", + "MLN", "MLN1", "MLN2", + "MLS", "MLS1", "MLS2", + "MLI", "MLI1", "MLI2", + "MLY", "MLY1", "MLY2", + "MLU", "MLU1", "MLU2", + "MLR", "MLR1", "MLR2", + "MLP", "MLP1", "MLP2", + + "ME", "ME1", "ME2", + "MEN", "MEN1", "MEN2", + "MES", "ME1S", "ME2S", + "MEI", "MEI1", "MEI2", + "MEY", "MEY1", "MEY2", + "MEU", "MEU1", "MEU2", + "MER", "MER1", "MER2", + "MEP", "MEP1", "MEP2" + }; + final static String METHOD_NAME_INTER[] = { + "Mv", + "Mz", "Mz1", "Mz2", + "Mb", "Mb1", "Mb2", + "Mc", "Mc1", "Mc2", + "Md", "Md1", "Md2", + "Mf", "Mf1", "Mf2", + "Mi", "Mi1", "Mi2", + "Ml", "Ml1", "Ml2", + "Mr", "Mr1", "Mr2", + + "MvU", "MlU", "MlU1", "MlU2", + + "MX", "MX1", "MX2", + "MO", "MO1", "MO2", + + "MLU", "MLU1", "MLU2", + + "ME", "ME1", "ME2", + "MEU", "MEU1", "MEU2", + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.declaringType."; + private final static String className = "decltype006"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String overClassName = prefix + "decltype006aOverridenClass"; + private final static String overInterName = prefix + "decltype006aOverridenInter"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + ReferenceType overClass; + ReferenceType overInter; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + // Get OverridenClass and OverridenInter,from debugee + overClass = debugee.classByName(overClassName); + if (overClass == null) { + log.complain("debuger FAILURE> Class " + overClassName + " not " + + "found."); + return 2; + } + overInter = debugee.classByName(overInterName); + if (overClass == null) { + log.complain("debuger FAILURE> Interface " + overInterName + " not " + + "found."); + return 2; + } + + // Check all methods from OverridenClass + log.display("debuger> Total methods in " + overClassName + ": " + + + overClass.methods().size()); + for (int i = 0; i < METHOD_NAME_CLASS.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + ReferenceType declType; + boolean equal; + + try { + listOfMethods = overClass.methodsByName(METHOD_NAME_CLASS[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get method by name " + + METHOD_NAME_CLASS[i]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + METHOD_NAME_CLASS[i] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + declType = method.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 3> Declaring type is null " + + " for method " + name + " in class " + + overClassName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " method " + name + " with declaring " + + "type " + declType.name() + " from class " + + overClassName + " read."); + try { + equal = declType.equals(overClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot compare reference " + + " types " + declType.name() + " and " + + overClassName); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 5> Declaring type of method " + + name + " is " + declType.name() + ", but should " + + "be " + overClassName); + testFailed = true; + } + } + + // Check all methods from OverridenInter + log.display("debuger> Total methods in " + overInterName + ": " + + + overInter.methods().size()); + for (int i = 0; i < METHOD_NAME_INTER.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + ReferenceType declType; + boolean equal; + + try { + listOfMethods = overInter.methodsByName(METHOD_NAME_INTER[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 6> Can't get method by name " + + METHOD_NAME_INTER[i]); + log.complain("debuger FAILURE 6> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 7> Number of methods by name " + + METHOD_NAME_INTER[i] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + declType = method.declaringType(); + if (declType == null) { + log.complain("debuger FAILURE 8> Declaring type is null " + + " for method " + name + " in class " + + overInterName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " method " + name + " with declaring " + + "type " + declType.name() + " from class " + + overInterName + " read."); + try { + equal = declType.equals(overInter); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 9> Cannot compare reference " + + " types " + declType.name() + " and " + + overInterName); + log.complain("debuger FAILURE 9> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 10> Declaring type of method " + + name + " is " + declType.name() + ", but should " + + "be " + overInterName); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006/TestDescription.java new file mode 100644 index 00000000000..44de7b470c6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype006. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the declaringType() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public ReferenceType declaringType() + * Returns the type in which this component was declared. The returned + * ReferenceType mirrors either a class or an interface in the target VM. + * nsk/jdi/TypeComponent/declaringType/declType006 checks assertion: + * public java.lang.String declaringType() + * 1. Returns the type in which a method was declared if the type mirrors + * a class in the target VM. + * 2. Returns the type in which a method was declared if the type mirrors + * an interface in the target VM. + * There are classes MainClass and OverridenClass extends MainClass and + * overrides all method; interfaces MainInter and OverridenInter that + * extends MainInter and overrides all method from it. + * Debugger gets each method from debuggee (OverridenClass and OverridenInter) + * calling by name and then checks if declaringType() returns reference + * type where all method were declared (OverridenClass and OverridenInter). + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype006 + * nsk.jdi.TypeComponent.declaringType.decltype006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006a.java new file mode 100644 index 00000000000..4cb7066753a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype006a.java @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class decltype006a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + decltype006aOverridenClass overridenClass = new decltype006aOverridenClass(); + decltype006aImplClass implClass = new decltype006aImplClass(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +// User class and interface +class decltype006aClass {} +interface decltype006aInter {} + +class decltype006aOverridenClass extends decltype006aMainClass { + // All methods are overriden from decltype006aMainClass + + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + decltype006aClass MX(decltype006aClass X) { return X; }; + decltype006aClass[] MX1(decltype006aClass X[]) { return X; }; + decltype006aClass[][] MX2(decltype006aClass X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long L[]) { return L; }; + static Long[][] MLS2(Long L[][]) { return L; }; + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + decltype006aInter ME(decltype006aInter E) { return E; }; + decltype006aInter[] ME1(decltype006aInter[] E) { return E; }; + decltype006aInter[][] ME2(decltype006aInter[][] E) { return E; }; + + native decltype006aInter MEN(decltype006aInter E); + native decltype006aInter[] MEN1(decltype006aInter[] E); + native decltype006aInter[][] MEN2(decltype006aInter[][] E); + static decltype006aInter MES(decltype006aInter E) { return E; }; + static decltype006aInter[] ME1S(decltype006aInter[] E) { return E; }; + static decltype006aInter[][] ME2S(decltype006aInter[][] E) { return E; }; + strictfp decltype006aInter MEI(decltype006aInter E) { return E; }; + strictfp decltype006aInter[] MEI1(decltype006aInter[] E) { return E; }; + strictfp decltype006aInter[][] MEI2(decltype006aInter[][] E) { return E; }; + synchronized decltype006aInter MEY(decltype006aInter E) { return E; }; + synchronized decltype006aInter[] MEY1(decltype006aInter[] E) { return E; }; + synchronized decltype006aInter[][] MEY2(decltype006aInter[][] E) { return E; }; + public decltype006aInter MEU(decltype006aInter E) { return E; }; + public decltype006aInter[] MEU1(decltype006aInter[] E) { return E; }; + public decltype006aInter[][] MEU2(decltype006aInter[][] E) { return E; }; + protected decltype006aInter MER(decltype006aInter E) { return E; }; + protected decltype006aInter[] MER1(decltype006aInter[] E) { return E; }; + protected decltype006aInter[][] MER2(decltype006aInter[][] E) { return E; }; + private decltype006aInter MEP(decltype006aInter E) { return E; }; + private decltype006aInter[] MEP1(decltype006aInter[] E) { return E; }; + private decltype006aInter[][] MEP2(decltype006aInter[][] E) { return E; }; +} + +class decltype006aMainClass { + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + decltype006aClass MX(decltype006aClass X) { return X; }; + decltype006aClass[] MX1(decltype006aClass X[]) { return X; }; + decltype006aClass[][] MX2(decltype006aClass X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long L[]) { return L; }; + static Long[][] MLS2(Long L[][]) { return L; }; + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + decltype006aInter ME(decltype006aInter E) { return E; }; + decltype006aInter[] ME1(decltype006aInter[] E) { return E; }; + decltype006aInter[][] ME2(decltype006aInter[][] E) { return E; }; + + native decltype006aInter MEN(decltype006aInter E); + native decltype006aInter[] MEN1(decltype006aInter[] E); + native decltype006aInter[][] MEN2(decltype006aInter[][] E); + static decltype006aInter MES(decltype006aInter E) { return E; }; + static decltype006aInter[] ME1S(decltype006aInter[] E) { return E; }; + static decltype006aInter[][] ME2S(decltype006aInter[][] E) { return E; }; + strictfp decltype006aInter MEI(decltype006aInter E) { return E; }; + strictfp decltype006aInter[] MEI1(decltype006aInter[] E) { return E; }; + strictfp decltype006aInter[][] MEI2(decltype006aInter[][] E) { return E; }; + synchronized decltype006aInter MEY(decltype006aInter E) { return E; }; + synchronized decltype006aInter[] MEY1(decltype006aInter[] E) { return E; }; + synchronized decltype006aInter[][] MEY2(decltype006aInter[][] E) { return E; }; + public decltype006aInter MEU(decltype006aInter E) { return E; }; + public decltype006aInter[] MEU1(decltype006aInter[] E) { return E; }; + public decltype006aInter[][] MEU2(decltype006aInter[][] E) { return E; }; + protected decltype006aInter MER(decltype006aInter E) { return E; }; + protected decltype006aInter[] MER1(decltype006aInter[] E) { return E; }; + protected decltype006aInter[][] MER2(decltype006aInter[][] E) { return E; }; + private decltype006aInter MEP(decltype006aInter E) { return E; }; + private decltype006aInter[] MEP1(decltype006aInter[] E) { return E; }; + private decltype006aInter[][] MEP2(decltype006aInter[][] E) { return E; }; +} + +class decltype006aImplClass implements decltype006aOverridenInter { + public void Mv() {}; + public boolean Mz(boolean z) { return !z; }; + public boolean[] Mz1(boolean z[]) { return z; }; + public boolean[][] Mz2(boolean z[][]) { return z; }; + public byte Mb(byte b) { return b; }; + public byte[] Mb1(byte b[]) { return b; }; + public byte[][] Mb2(byte b[][]) { return b; }; + public char Mc(char c) { return c; }; + public char[] Mc1(char c[]) { return c; }; + public char[][] Mc2(char c[][]) { return c; }; + public double Md(double d) { return d; }; + public double[] Md1(double d[]) { return d; }; + public double[][] Md2(double d[][]) { return d; }; + public float Mf(float f) { return f; }; + public float[] Mf1(float f[]) { return f; }; + public float[][] Mf2(float f[][]) { return f; }; + public int Mi(int i) { return i; }; + public int[] Mi1(int i[]) { return i; }; + public int[][] Mi2(int i[][]) { return i; }; + public long Ml(long l) { return l; }; + public long[] Ml1(long l[]) { return l; }; + public long[][] Ml2(long l[][]) { return l; }; + public short Mr(short r) { return r; }; + public short[] Mr1(short r[]) { return r; }; + public short[][] Mr2(short r[][]) { return r; }; + + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + + public decltype006aClass MX(decltype006aClass X) { return X; }; + public decltype006aClass[] MX1(decltype006aClass X[]) { return X; }; + public decltype006aClass[][] MX2(decltype006aClass X[][]) { return X; }; + public Object MO(Object O) { return O; }; + public Object[] MO1(Object[] O) { return O; }; + public Object[][] MO2(Object[][] O) { return O; }; + + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + + public decltype006aInter ME(decltype006aInter E) { return E; }; + public decltype006aInter[] ME1(decltype006aInter[] E) { return E; }; + public decltype006aInter[][] ME2(decltype006aInter[][] E) { return E; }; + + public decltype006aInter MEU(decltype006aInter E) { return E; }; + public decltype006aInter[] MEU1(decltype006aInter[] E) { return E; }; + public decltype006aInter[][] MEU2(decltype006aInter[][] E) { return E; }; +} + +interface decltype006aOverridenInter extends decltype006aMainInter { + // All methods are overriden from decltype006aMainInter + + void Mv(); + boolean Mz(boolean z); + boolean[] Mz1(boolean z[]); + boolean[][] Mz2(boolean z[][]); + byte Mb(byte b); + byte[] Mb1(byte b[]); + byte[][] Mb2(byte b[][]); + char Mc(char c); + char[] Mc1(char c[]); + char[][] Mc2(char c[][]); + double Md(double d); + double[] Md1(double d[]); + double[][] Md2(double d[][]); + float Mf(float f); + float[] Mf1(float f[]); + float[][] Mf2(float f[][]); + int Mi(int i); + int[] Mi1(int i[]); + int[][] Mi2(int i[][]); + long Ml(long l); + long[] Ml1(long l[]); + long[][] Ml2(long l[][]); + short Mr(short r); + short[] Mr1(short r[]); + short[][] Mr2(short r[][]); + + public void MvU(); + public long MlU(long l); + public long[] MlU1(long l[]); + public long[][] MlU2(long l[][]); + + decltype006aClass MX(decltype006aClass X); + decltype006aClass[] MX1(decltype006aClass X[]); + decltype006aClass[][] MX2(decltype006aClass X[][]); + Object MO(Object O); + Object[] MO1(Object[] O); + Object[][] MO2(Object[][] O); + + public Long MLU(Long L); + public Long[] MLU1(Long[] L); + public Long[][] MLU2(Long[][] L); + + decltype006aInter ME(decltype006aInter E); + decltype006aInter[] ME1(decltype006aInter[] E); + decltype006aInter[][] ME2(decltype006aInter[][] E); + + public decltype006aInter MEU(decltype006aInter E); + public decltype006aInter[] MEU1(decltype006aInter[] E); + public decltype006aInter[][] MEU2(decltype006aInter[][] E); +} + + +interface decltype006aMainInter { + void Mv(); + boolean Mz(boolean z); + boolean[] Mz1(boolean z[]); + boolean[][] Mz2(boolean z[][]); + byte Mb(byte b); + byte[] Mb1(byte b[]); + byte[][] Mb2(byte b[][]); + char Mc(char c); + char[] Mc1(char c[]); + char[][] Mc2(char c[][]); + double Md(double d); + double[] Md1(double d[]); + double[][] Md2(double d[][]); + float Mf(float f); + float[] Mf1(float f[]); + float[][] Mf2(float f[][]); + int Mi(int i); + int[] Mi1(int i[]); + int[][] Mi2(int i[][]); + long Ml(long l); + long[] Ml1(long l[]); + long[][] Ml2(long l[][]); + short Mr(short r); + short[] Mr1(short r[]); + short[][] Mr2(short r[][]); + + public void MvU(); + public long MlU(long l); + public long[] MlU1(long l[]); + public long[][] MlU2(long l[][]); + + decltype006aClass MX(decltype006aClass X); + decltype006aClass[] MX1(decltype006aClass X[]); + decltype006aClass[][] MX2(decltype006aClass X[][]); + Object MO(Object O); + Object[] MO1(Object[] O); + Object[][] MO2(Object[][] O); + + public Long MLU(Long L); + public Long[] MLU1(Long[] L); + public Long[][] MLU2(Long[][] L); + + decltype006aInter ME(decltype006aInter E); + decltype006aInter[] ME1(decltype006aInter[] E); + decltype006aInter[][] ME2(decltype006aInter[][] E); + + public decltype006aInter MEU(decltype006aInter E); + public decltype006aInter[] MEU1(decltype006aInter[] E); + public decltype006aInter[][] MEU2(decltype006aInter[][] E); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007.java new file mode 100644 index 00000000000..b63ecf1849e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class decltype007 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.declaringType."; + private final static String className = "decltype007"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String mainClassName = prefix + "decltype007aMainClass"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + ReferenceType mainClass; + List methods; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + mainClass = debugee.classByName(mainClassName); + if (mainClass == null) { + log.complain("debuger FAILURE> Class " + mainClassName + " not " + + "found."); + return 2; + } + + // Get all methods, find constructors and static initializers and + // check them + try { + methods = mainClass.methods(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get methods from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalMethods = methods.size(); + if (totalMethods < 1) { + log.complain("debuger FAILURE> Total number of methods read " + + totalMethods); + return 2; + } + log.display("debuger> Total methods found: " + totalMethods); + Iterator methodsIterator = methods.iterator(); + for (int i = 0; methodsIterator.hasNext(); i++) { + Method method = (Method)methodsIterator.next(); + String name = method.name(); + ReferenceType declType = method.declaringType(); + String declTypeName = declType.name(); + boolean equal; + + log.display("debuger> " + i + " method " + name + " from " + + declTypeName + " with sign " + method.signature() + + " read."); + if (method.isConstructor() || method.isStaticInitializer()) { + try { + equal = declType.equals(mainClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Cannot compare reference " + + " types " + declType.name() + " and " + + mainClassName); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 2> Declaring type of " + + name + " is " + declTypeName + ", but should " + + "be " + mainClassName); + testFailed = true; + } + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007/TestDescription.java new file mode 100644 index 00000000000..e0f64c55159 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype007. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the declaringType() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public ReferenceType declaringType() + * Returns the type in which this component was declared. The returned + * ReferenceType mirrors either a class or an interface in the target VM. + * nsk/jdi/TypeComponent/declaringType/declType007 checks assertion: + * public java.lang.String declaringType() + * 1. Returns the type in which a method was declared if the type mirrors + * a class in the target VM. + * Debugger gets all methods from debuggee (MainClass), finds constructors and + * static initializers and then checks if declaringType() returns the same + * reference type. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype007 + * nsk.jdi.TypeComponent.declaringType.decltype007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007a.java new file mode 100644 index 00000000000..71a185a04eb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007a.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class decltype007a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + decltype007aMainClass mainClass = new decltype007aMainClass(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class decltype007aMainClass { + decltype007aMainClass() {}; + public decltype007aMainClass(long l) {}; + private decltype007aMainClass(Object obj) {}; + protected decltype007aMainClass(long[] l) {}; + + static int ci; + static Long cL; + static long[] cl = new long[10]; + + static { ci = 1; } + static { cL = new Long(1l); } + static { + for (int i = 0; i < 10; i++) { + cl[i] = (long)i; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008.java new file mode 100644 index 00000000000..6f21d63e9d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class decltype008 { + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.declaringType."; + private final static String className = "decltype008"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String mainClassName = prefix + "decltype008aMainClass"; + private final static String otherClassName = prefix + "decltype008aOtherClass"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + ReferenceType mainClass; + ReferenceType otherClass; + List methods; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + mainClass = debugee.classByName(mainClassName); + if (mainClass == null) { + log.complain("debuger FAILURE> Class " + mainClassName + " not " + + "found."); + return 2; + } + otherClass = debugee.classByName(otherClassName); + if (otherClass == null) { + log.complain("debuger FAILURE> Class " + otherClassName + " not " + + "found."); + return 2; + } + + // Get all methods, find constructors and static initializers and + // check them + try { + methods = otherClass.visibleMethods(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get methods from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalMethods = methods.size(); + if (totalMethods < 1) { + log.complain("debuger FAILURE> Total number of methods read " + + totalMethods); + return 2; + } + log.display("debuger> Total methods found: " + totalMethods); + Iterator methodsIterator = methods.iterator(); + for (int i = 0; methodsIterator.hasNext(); i++) { + Method method = (Method)methodsIterator.next(); + String name = method.name(); + ReferenceType declType = method.declaringType(); + String declTypeName = declType.name(); + String signature = method.signature(); + + if (method.isStaticInitializer()) { + // Static initializers are in OtherClass only + boolean equal; + + log.display("debuger> " + i + " static initializer " + name + + " from " + declTypeName + " with signature " + + signature + " read."); + try { + equal = declType.equals(otherClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 1> Cannot compare reference " + + " types " + declType.name() + " and " + + otherClassName); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + if (!equal) { + log.complain("debuger FAILURE 2> Declaring type of " + + name + " is " + declTypeName + ", but should " + + "be " + otherClassName); + testFailed = true; + } + } else { + if (method.isConstructor()) { + boolean equalOther; + boolean equalMain; + // Constructors from OtherClass starts with reference to + // String object + boolean fromOther = + signature.startsWith("(Ljava/lang/String;"); + // Constructors from MainClass starts with reference to + // Long object + boolean fromMain = + signature.startsWith("(Ljava/lang/Long;"); + + log.display("debuger> " + i + " constructor " + name + + " from " + declTypeName + " with signature " + + signature + " read."); + try { + equalOther = declType.equals(otherClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 3> Cannot compare " + + " reference types " + declType.name() + + " and " + otherClassName); + log.complain("debuger FAILURE 3> Exception: " + e); + testFailed = true; + continue; + } + try { + equalMain = declType.equals(mainClass); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE 4> Cannot compare " + + " reference types " + declType.name() + + " and " + mainClassName); + log.complain("debuger FAILURE 4> Exception: " + e); + testFailed = true; + continue; + } + + if (fromOther && !equalOther) { + log.complain("debuger FAILURE 5> Declaring type of " + + name + " is " + declTypeName + ", but should " + + "be " + otherClassName); + testFailed = true; + } + if (fromMain && !equalMain) { + log.complain("debuger FAILURE 6> Declaring type of " + + name + " is " + declTypeName + ", but should " + + "be " + mainClassName); + testFailed = true; + } + } else { + log.display("debuger> " + i + " method " + name + " from " + + declTypeName + " with signature " + + signature + " passed."); + } + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008/TestDescription.java new file mode 100644 index 00000000000..546c018fe63 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype008. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the declaringType() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public ReferenceType declaringType() + * Returns the type in which this component was declared. The returned + * ReferenceType mirrors either a class or an interface in the target VM. + * nsk/jdi/TypeComponent/declaringType/declType008 checks assertion: + * public java.lang.String declaringType() + * 1. Returns the type in which a method was declared if the type mirrors + * a class in the target VM. + * There are classes MainClass and OtherClass that extends MainClass in + * target VM. Both classes have constructors and static initializers. + * Debugger gets all visible methods from debuggee (OtherClass), finds + * constructors and static initializers and checks their declaring types. For + * all initializers declaring type must be OtherClass. Each constructor + * that signature begins with reference to Long object must have declaring + * type MainClass. Each constructor that signature begins with reference to + * String object must have declaring type OtherClass. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype008 + * nsk.jdi.TypeComponent.declaringType.decltype008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008a.java new file mode 100644 index 00000000000..beee2e30f08 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008a.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class decltype008a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + decltype008aOtherClass otherClass = new decltype008aOtherClass(new String("decltype008a"), 1f); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class decltype008aOtherClass extends decltype008aMainClass { + // All contructors from decltype008aOtherClass starts with reference to String object + public decltype008aOtherClass(String S, float f) { + super(new Long(1), f); + }; + private decltype008aOtherClass(String S, Object obj){ + super(new Long(1), obj); + }; + protected decltype008aOtherClass(String S, long[] l) { + super(new Long(1), l); + }; + + static double cd; + static String cS; + static float[] cf = new float[10]; + + static { cd = 1; } + static { cS = new String(); } + static { + for (int i = 0; i < 10; i++) { + cf[i] = (float)i; + } + } +} + +class decltype008aMainClass { + // All contructors from decltype008aMainClass starts with reference to Long object + decltype008aMainClass(Long L, float f) {}; + decltype008aMainClass(Long L, Object obj) {}; + decltype008aMainClass(Long L, long[] l) {}; + + static int ci; + static Long cL; + static long[] cl = new long[10]; + + static { ci = 1; } + static { cL = new Long(1l); } + static { + for (int i = 0; i < 10; i++) { + cl[i] = (long)i; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009.java new file mode 100644 index 00000000000..9681c05fb04 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class decltype009 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.TypeComponent.declaringType."; + private final static String className = "decltype009"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] expectedFieldNames = {"f1", "f2", "f3"}; + private final static String[] expectedEnumFieldsNames = { "e1", "e2" }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + Field foundField = checkedClass.fieldByName(expectedEnumFieldsNames[i]); + if (foundField != null) { + if (foundField.declaringType().equals(checkedClass)) { + display("enum " + className + " has field " + expectedEnumFieldsNames[i]); + display("\t of expected type " + className); + } else { + complain("enum " + className + " has field " + expectedEnumFieldsNames[i]); + complain("\t of unexpected type " + foundField.declaringType().name()); + exitStatus = Consts.TEST_FAILED; + } + } else { + complain("enum " + className + " does not have field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009/TestDescription.java new file mode 100644 index 00000000000..1e287051af1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/declaringType/decltype009. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for declaringType() method of TypeComponent interface. + * The test checks if the method returns correct result for + * each enum constant field declared in mirrored enum type. + * The test consists of a debugger program (decltype009.java) + * and debuggee application (decltype009a.java). + * Package name is nsk.jdi.TypeComponent.declaringType . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger finds mirrors of enum types. Every of these + * enum types has the same enum constant fields: e1 and e2. + * The debugger checks if declaringType() method returns + * enum type itself as declaring for each enum constans. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.declaringType.decltype009 + * nsk.jdi.TypeComponent.declaringType.decltype009a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.declaringType.decltype009 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009a.java new file mode 100644 index 00000000000..74fbd31232f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype009a.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.declaringType; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class decltype009a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static decltype009Enum1 f1 = decltype009Enum1.e2; + static decltype009Enum2 f2 = decltype009Enum2.e1; + static decltype009Enum1.Enum1_ f3 = decltype009Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(decltype009.SIGNAL_READY); + receiveSignal(decltype009.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum decltype009Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum decltype009Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001.java new file mode 100644 index 00000000000..498e6adefaa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001.java @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the TypeComponent.genericSignature() method.
    + *
    + * The test checks up TypeComponent.genericSignature() method
    + * for Field objects.
    + *
    + * The first: the test checks that genericSignature() method returns
    + * null for fields of all primitive types and for fields which are
    + * arrays of primitive types.
    + *
    + * The second: the test checks that genericSignature() method returns
    + * null for fields whivh are arrays of non-generic reference types.
    + *
    + * The third: the test checks that genericSignature() method returns
    + * null for fields of non-generic reference types.
    + *
    + * At last: the test checks that genericSignature() method returns
    + * a corresponding signature string for fields of generic reference
    + * types.
    + *
    + */ + +public class genericSignature001 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "genericSignature001: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> genericSignature001: "; + static final String infoLogPrefix = "--> "; + static final String packagePrefix = "nsk.jdi.TypeComponent.genericSignature."; + static final String targetVMClassName = packagePrefix + "genericSignature001a"; + + static ArgumentHandler argsHandler; + static Log logHandler; + static boolean verboseMode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + + private final static String primitiveTypeSign = "primitiveType"; + private final static String referenceTypeSign = "referenceType"; + + /** + * Debugee's fields for check: + * fieldsForCheck[i][0] - field name + * fieldsForCheck[i][1] - expected string returned by genericSignature() + */ + private final static String fieldsForCheck[][] = { + {"z0", null}, + {"b0", null}, + {"c0", null}, + {"d0", null}, + {"f0", null}, + {"i0", null}, + {"l0", null}, + + {"z1", null}, + {"b1", null}, + {"c1", null}, + {"d1", null}, + {"f1", null}, + {"i1", null}, + {"l1", null}, + + {"z2", null}, + {"b2", null}, + {"c2", null}, + {"d2", null}, + {"f2", null}, + {"i2", null}, + {"l2", null}, + + {"GS001_Class01_Obj0", null}, + {"GS001_Class02_Obj0", null}, + {"GS001_Class03_Obj0", null}, + {"GS001_Class04_Obj0", null}, + {"GS001_Class05_Obj0", null}, + + {"GS001_Class01_Obj1", null}, + {"GS001_Class02_Obj1", null}, + {"GS001_Class03_Obj1", null}, + {"GS001_Class04_Obj1", null}, + {"GS001_Class05_Obj1", null}, + + {"GS001_Class01_Obj2", null}, + {"GS001_Class02_Obj2", null}, + {"GS001_Class03_Obj2", null}, + {"GS001_Class04_Obj2", null}, + {"GS001_Class05_Obj2", null}, + + {"GS001_Class06_Obj", + "Lnsk/jdi/TypeComponent/genericSignature/GS001_Class06;"}, + {"GS001_Class07_Obj", + "Lnsk/jdi/TypeComponent/genericSignature/GS001_Class07;"}, + {"GS001_Class08_Obj", + "Lnsk/jdi/TypeComponent/genericSignature/GS001_Class08;"}, + {"GS001_Class09_Obj", + "Lnsk/jdi/TypeComponent/genericSignature/GS001_Class09;"}, + {"GS001_Class10_Obj", + "Lnsk/jdi/TypeComponent/genericSignature/GS001_Class10;"} + + }; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int result = new genericSignature001().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/TypeComponent/genericSignature/genericSignature001 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/TypeComponent/genericSignature/genericSignature001 test PASSED"); + } + return result; + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + verboseMode = argsHandler.verbose(); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/TypeComponent/genericSignature/genericSignature001 test..."); + logOnVerbose + ("==> Test checks the genericSignature() method of TypeComponent interface"); + logOnVerbose + ("==> of the com.sun.jdi package for Field objects."); + + Binder binder = new Binder(argsHandler,logHandler); + Debugee debugee = binder.bindToDebugee(targetVMClassName); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + logOnVerbose(infoLogPrefixHead + "Debugee (" + targetVMClassName + ") launched..."); + debugee.resume(); + + String readySignal = "ready"; + String signalFromDebugee = pipe.readln(); + if ( ! readySignal.equals(signalFromDebugee) ) { + logOnError(errorLogPrefixHead + "Uexpected debugee's signal:"); + logOnError(errorLogPrefix + "Expected signal = '" + readySignal + "'"); + logOnError(errorLogPrefix + "Actual signal = '" + signalFromDebugee + "'"); + return STATUS_FAILED; + } + logOnVerbose(infoLogPrefixHead + "Debugee's signal recieved = '" + readySignal + "'"); + + logOnVerbose(infoLogPrefixHead + "Request ReferenceType object for debugee's class..."); + ReferenceType targetVMClass = null; + try { + targetVMClass = debugee.classByName(targetVMClassName); + } catch (Throwable thrown) { + logOnError(errorLogPrefixHead + "Unexpected exception during requesting ReferenceType: "); + logOnError(errorLogPrefix + "Requested class name = '" + targetVMClassName + "'"); + logOnError(errorLogPrefix + "Exception = '" + thrown + "'"); + return STATUS_FAILED; + } + if (targetVMClass == null) { + logOnError(errorLogPrefixHead + "Could NOT find ReferenceType object for debugee's class: "); + logOnError(errorLogPrefix + "Requested class name = '" + targetVMClassName + "'"); + return STATUS_FAILED; + } + + logOnVerbose(infoLogPrefixHead + "check TypeComponent.genericSignature() method for debugee's fields..."); + String brackets[] = {"", "[]", "[][]"}; + for (int i=0; i < fieldsForCheck.length; i++) { + String checkedFieldName = fieldsForCheck[i][0]; + + TypeComponent checkedField = null; + try { + checkedField = targetVMClass.fieldByName(checkedFieldName); + } catch (Throwable thrown) { + logOnError(errorLogPrefixHead + "ReferenceType.fieldByName() throws unexpected exception: "); + logOnError(errorLogPrefix + "Class name = '" + targetVMClassName + "'"); + logOnError(errorLogPrefix + "Requested field name = '" + checkedFieldName + "'"); + testResult = STATUS_FAILED; + continue; + } + if (checkedField == null) { + logOnError(errorLogPrefixHead + "Could NOT find Field object in debugee's class: "); + logOnError(errorLogPrefix + "Debugee's class name = '" + targetVMClassName + "'"); + logOnError(errorLogPrefix + "Requested field name = '" + checkedFieldName + "'"); + testResult = STATUS_FAILED; + continue; + } + String expectedGenericSignature = fieldsForCheck[i][1]; + String actualGenericSignature = null; + try { + actualGenericSignature = checkedField.genericSignature(); + } catch (Throwable thrown) { + logOnError(errorLogPrefixHead + "TypeComponent.genericSignature() throws unexpected exception: "); + logOnError(errorLogPrefix + "TypeComponent = '" + checkedField + "'"); + logOnError(errorLogPrefix + "Field name for this TypeComponent = '" + checkedFieldName + "'"); + testResult = STATUS_FAILED; + continue; + } + boolean isFailure = false; + if ( expectedGenericSignature == null ) { + if ( actualGenericSignature != null ) { + isFailure = true; + } + } else { + if ( ! expectedGenericSignature.equals(actualGenericSignature) ) { + isFailure = true; + } + } + if ( isFailure ) { + logOnError(errorLogPrefixHead + "TypeComponent.genericSignature() returns unexpected signature: "); + logOnError(errorLogPrefix + "TypeComponent = '" + checkedField + "'"); + logOnError(errorLogPrefix + "Field name for this TypeComponent = '" + checkedFieldName + "'"); + logOnError(errorLogPrefix + "Expected generic signature = '" + expectedGenericSignature + "'"); + logOnError(errorLogPrefix + "Actual generic signature = '" + actualGenericSignature + "'"); + testResult = STATUS_FAILED; + } + + } + logOnVerbose(infoLogPrefixHead + + "Check TypeComponent.genericSignature() method for debugee's fields completed."); + + logOnVerbose(infoLogPrefixHead + "Waiting for debugee finish..."); + String quitSignal = "quit"; + pipe.println(quitSignal); + debugee.waitFor(); + + int debugeeExitStatus = debugee.getStatus(); + if (debugeeExitStatus != (STATUS_PASSED + STATUS_TEMP) ) { + logOnError(errorLogPrefixHead + "Unexpected Debugee's exit status: "); + logOnError(errorLogPrefix + "Expected status = '" + (STATUS_PASSED + STATUS_TEMP) + "'"); + logOnError(errorLogPrefix + "Actual status = '" + debugeeExitStatus + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of genericSignature001 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001/TestDescription.java new file mode 100644 index 00000000000..db4afdc1d3f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/genericSignature/genericSignature001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/TypeComponent/genericSignature/genericSignature001 test: + * The test for the TypeComponent.genericSignature() method. + * The test checks up TypeComponent.genericSignature() method + * for Field objects. + * The first: the test checks that genericSignature() method returns + * null for fields of all primitive types and for fields which are + * arrays of primitive types. + * The second: the test checks that genericSignature() method returns + * null for fields whivh are arrays of non-generic reference types. + * The third: the test checks that genericSignature() method returns + * null for fields of non-generic reference types. + * At last: the test checks that genericSignature() method returns + * a corresponding signature string for fields of generic reference + * types. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.genericSignature.genericSignature001 + * nsk.jdi.TypeComponent.genericSignature.genericSignature001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.genericSignature.genericSignature001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001a.java new file mode 100644 index 00000000000..6fe6f41c89f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature001a.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for + * the nsk/jdi/TypeComponent/genericSignature/genericSignature001 JDI test. + */ + +public class genericSignature001a { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "genericSignature001(Debugee): "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> genericSignature001(Debugee): "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + // primitive type fields and arrays of primitive types + // for check TypeComponent.genericSignature() method + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + + // non-generic reference type fields and arrays of non-generic reference types + // for check TypeComponent.genericSignature() method + + GS001_Class01 GS001_Class01_Obj0 = new GS001_Class01(), + GS001_Class01_Obj1[]={GS001_Class01_Obj0}, + GS001_Class01_Obj2[][]={GS001_Class01_Obj1}; + + GS001_Class02 GS001_Class02_Obj0 = new GS001_Class02(), + GS001_Class02_Obj1[]={GS001_Class02_Obj0}, + GS001_Class02_Obj2[][]={GS001_Class02_Obj1}; + + GS001_Class03 GS001_Class03_Obj0 = new GS001_Class03(), + GS001_Class03_Obj1[]={GS001_Class03_Obj0}, + GS001_Class03_Obj2[][]={GS001_Class03_Obj1}; + + GS001_Class04 GS001_Class04_Obj0 = new GS001_Class04(), + GS001_Class04_Obj1[]={GS001_Class04_Obj0}, + GS001_Class04_Obj2[][]={GS001_Class04_Obj1}; + + GS001_Class05 GS001_Class05_Obj0 = new GS001_Class05(), + GS001_Class05_Obj1[]={GS001_Class05_Obj0}, + GS001_Class05_Obj2[][]={GS001_Class05_Obj1}; + + // generic type fields for check TypeComponent.genericSignature() method + + GS001_Class06 GS001_Class06_Obj = new GS001_Class06(); + + GS001_Class07 GS001_Class07_Obj = + new GS001_Class07(); + + GS001_Class08 GS001_Class08_Obj = new GS001_Class08(); + + GS001_Class09 GS001_Class09_Obj = new GS001_Class09(); + + GS001_Class10 GS001_Class10_Obj = + new GS001_Class10(); + + + public static void main (String argv[]) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(System.err, argsHandler); + logHandler.enableErrorsSummary(false); + IOPipe pipe = argsHandler.createDebugeeIOPipe(); + + logOnVerbose(infoLogPrefixHead + "Debugee started!"); + + genericSignature001a genericSignature001aDebugee = new genericSignature001a(); + + String readySignal = "ready"; + pipe.println(readySignal); + String quitSignal = "quit"; + logOnVerbose(infoLogPrefixHead + "Wait for '" + quitSignal + "' signal..."); + String signalFromDebugger = pipe.readln(); + if ( ! (quitSignal.equals(signalFromDebugger)) ) { + logOnError(errorLogPrefixHead + "UNEXPECTED debugger's signal:"); + logOnError(errorLogPrefix + "Expected signal = '" + quitSignal + "'"); + logOnError(errorLogPrefix + "Actual signal = '" + signalFromDebugger + "'"); + logOnError(errorLogPrefix + "Exiting with Exit Status = '" + (STATUS_FAILED + STATUS_TEMP) + "'"); + System.exit(STATUS_FAILED + STATUS_TEMP); + } + logOnVerbose(infoLogPrefixHead + "'" + quitSignal + "' signal from debugger is received."); + logOnVerbose(infoLogPrefix + "Exiting with Exit Status = '" + (STATUS_PASSED + STATUS_TEMP) + "'"); + System.exit(STATUS_PASSED + STATUS_TEMP); + } +} // end of genericSignature001a class + + +// non generic classes: + +class GS001_Class01 {} + +class GS001_Class02 {} + +interface GS001_Interf01 {} + +interface GS001_Interf02 {} + +class GS001_Class03 extends GS001_Class01 {} + +class GS001_Class04 extends GS001_Class01 implements GS001_Interf01 {} + +class GS001_Class05 extends GS001_Class02 implements GS001_Interf02 {} + + +// generic classes: + +class GS001_Class06 {} + +class GS001_Class07 {} + +class GS001_Class08 {} + +class GS001_Class09 {} + +class GS001_Class10 {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002.java new file mode 100644 index 00000000000..0257c81a9b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the TypeComponent.genericSignature() method.
    + *
    + * The test checks up TypeComponent.genericSignature() method
    + * for Method objects.
    + *
    + * The first: the test checks that genericSignature() method returns
    + * null for methods which have not generic signature. The methods with
    + * different sets of arguments and with different returned types are
    + * used.
    + *
    + * The second: the test checks that genericSignature() method returns
    + * a corresponding signature string for methods which have generic
    + * signature. The methods with different sets of generic types
    + * arguments and with different returned generic types are used.
    + *
    + */ + +public class genericSignature002 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "genericSignature002: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> genericSignature002: "; + static final String infoLogPrefix = "--> "; + static final String packagePrefix = "nsk.jdi.TypeComponent.genericSignature."; + static final String targetVMClassName = packagePrefix + "genericSignature002a"; + + static ArgumentHandler argsHandler; + static Log logHandler; + static boolean verboseMode = false; // test argument -verbose switches to true + // - for more easy failure evaluation + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + + private final static String primitiveTypeSign = "primitiveType"; + private final static String referenceTypeSign = "referenceType"; + + /** + * Debugee's methods for check: + * methodsForCheck[i][0] - method name + * methodsForCheck[i][1] - expected string returned by genericSignature() + */ + private final static String methodsForCheck[][] = { + {"testMethod_001", null}, + {"testMethod_002", null}, + {"testMethod_003", null}, + {"testMethod_004", null}, + {"testMethod_005", null}, + {"testMethod_006", null}, + {"testMethod_007", null}, + {"testMethod_008", null}, + {"testMethod_009", null}, + {"testMethod_010", null}, + {"testMethod_011", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class06;)V"}, + {"testMethod_012", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class06;)Lnsk/jdi/TypeComponent/genericSignature/GS002_Class06;"}, + {"testMethod_013", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class07;)V"}, + {"testMethod_014", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class07;)Lnsk/jdi/TypeComponent/genericSignature/GS002_Class07;"}, + {"testMethod_015", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class08;)V"}, + {"testMethod_016", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class08;)Lnsk/jdi/TypeComponent/genericSignature/GS002_Class08;"}, + {"testMethod_017", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class09;)V"}, + {"testMethod_018", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class09;)Lnsk/jdi/TypeComponent/genericSignature/GS002_Class09;"}, + {"testMethod_019", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class10;)V"}, + {"testMethod_020", + "(Lnsk/jdi/TypeComponent/genericSignature/GS002_Class10;)Lnsk/jdi/TypeComponent/genericSignature/GS002_Class10;"}, + {"testMethod_021", + "()V"}, + {"testMethod_022", + "(TC;)V"}, + {"testMethod_023", + "(TC;)TC;"}, + {"testMethod_024", + "()V"}, + {"testMethod_025", + "(TC1;TC2;)V"}, + {"testMethod_026", + "(TC1;TC2;)TC2;"}, + {"testMethod_027", + "()V"}, + {"testMethod_028", + "(TC2;TC1;)V"}, + {"testMethod_029", + "(TC2;TC1;)TC1;"}, + + }; + + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (PASSED) or either 2 (FAILED). + */ + public static int run (String argv[], PrintStream out) { + + int result = new genericSignature002().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/TypeComponent/genericSignature/genericSignature002 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/TypeComponent/genericSignature/genericSignature002 test PASSED"); + } + return result; + } + + /** + * Non-static variant of the method run(args,out) + */ + private int runThis (String argv[], PrintStream out) { + + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + verboseMode = argsHandler.verbose(); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/TypeComponent/genericSignature/genericSignature002 test..."); + logOnVerbose + ("==> Test checks the genericSignature() method of TypeComponent interface"); + logOnVerbose + ("==> of the com.sun.jdi package for Method objects."); + + Binder binder = new Binder(argsHandler,logHandler); + Debugee debugee = binder.bindToDebugee(targetVMClassName); + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + logOnVerbose(infoLogPrefixHead + "Debugee (" + targetVMClassName + ") launched..."); + debugee.resume(); + + String readySignal = "ready"; + String signalFromDebugee = pipe.readln(); + if ( ! readySignal.equals(signalFromDebugee) ) { + logOnError(errorLogPrefixHead + "Uexpected debugee's signal:"); + logOnError(errorLogPrefix + "Expected signal = '" + readySignal + "'"); + logOnError(errorLogPrefix + "Actual signal = '" + signalFromDebugee + "'"); + return STATUS_FAILED; + } + logOnVerbose(infoLogPrefixHead + "Debugee's signal recieved = '" + readySignal + "'"); + + logOnVerbose(infoLogPrefixHead + "Request ReferenceType object for debugee's class..."); + ReferenceType targetVMClass = null; + try { + targetVMClass = debugee.classByName(targetVMClassName); + } catch (Throwable thrown) { + logOnError(errorLogPrefixHead + "Unexpected exception during requesting ReferenceType: "); + logOnError(errorLogPrefix + "Requested class name = '" + targetVMClassName + "'"); + logOnError(errorLogPrefix + "Exception = '" + thrown + "'"); + return STATUS_FAILED; + } + if (targetVMClass == null) { + logOnError(errorLogPrefixHead + "Could NOT find ReferenceType object for debugee's class: "); + logOnError(errorLogPrefix + "Requested class name = '" + targetVMClassName + "'"); + return STATUS_FAILED; + } + + logOnVerbose(infoLogPrefixHead + "check TypeComponent.genericSignature() method for debugee's methods..."); + String brackets[] = {"", "[]", "[][]"}; + for (int i=0; i < methodsForCheck.length; i++) { + String checkedMethodName = methodsForCheck[i][0]; + + List checkedMethodList = null; + try { + checkedMethodList = targetVMClass.methodsByName(checkedMethodName); + } catch (Throwable thrown) { + logOnError(errorLogPrefixHead + "ReferenceType.methodsByName() throws unexpected exception: "); + logOnError(errorLogPrefix + "Class name = '" + targetVMClassName + "'"); + logOnError(errorLogPrefix + "Requested method name = '" + checkedMethodName + "'"); + testResult = STATUS_FAILED; + continue; + } + + if (checkedMethodList.size() != 1) { + logOnError(errorLogPrefixHead + "ReferenceType.methodsByName() returns unexpected number of methods:"); + logOnError(errorLogPrefix + "Debugee's class name = '" + targetVMClassName + "'"); + logOnError(errorLogPrefix + "Requested method name = '" + checkedMethodName + "'"); + logOnError(errorLogPrefix + "Expected number of methods = 1"); + logOnError(errorLogPrefix + "Actual number of methods = " + checkedMethodList.size()); + testResult = STATUS_FAILED; + continue; + } + + TypeComponent checkedMethod = (TypeComponent)(checkedMethodList.get(0)); + + String expectedGenericSignature = methodsForCheck[i][1]; + String actualGenericSignature = null; + try { + actualGenericSignature = checkedMethod.genericSignature(); + } catch (Throwable thrown) { + logOnError(errorLogPrefixHead + "TypeComponent.genericSignature() throws unexpected exception: "); + logOnError(errorLogPrefix + "TypeComponent = '" + checkedMethod + "'"); + logOnError(errorLogPrefix + "Method name for this TypeComponent = '" + checkedMethodName + "'"); + testResult = STATUS_FAILED; + continue; + } + boolean isFailure = false; + if ( expectedGenericSignature == null ) { + if ( actualGenericSignature != null ) { + isFailure = true; + } + } else { + if ( ! expectedGenericSignature.equals(actualGenericSignature) ) { + isFailure = true; + } + } + if ( isFailure ) { + logOnError(errorLogPrefixHead + "TypeComponent.genericSignature() returns unexpected signature: "); + logOnError(errorLogPrefix + "TypeComponent = '" + checkedMethod + "'"); + logOnError(errorLogPrefix + "Method name for this TypeComponent = '" + checkedMethodName + "'"); + logOnError(errorLogPrefix + "Expected generic signature = '" + expectedGenericSignature + "'"); + logOnError(errorLogPrefix + "Actual generic signature = '" + actualGenericSignature + "'"); + testResult = STATUS_FAILED; + } + + } + logOnVerbose(infoLogPrefixHead + + "Check TypeComponent.genericSignature() method for debugee's methods completed."); + + logOnVerbose(infoLogPrefixHead + "Waiting for debugee finish..."); + String quitSignal = "quit"; + pipe.println(quitSignal); + debugee.waitFor(); + + int debugeeExitStatus = debugee.getStatus(); + if (debugeeExitStatus != (STATUS_PASSED + STATUS_TEMP) ) { + logOnError(errorLogPrefixHead + "Unexpected Debugee's exit status: "); + logOnError(errorLogPrefix + "Expected status = '" + (STATUS_PASSED + STATUS_TEMP) + "'"); + logOnError(errorLogPrefix + "Actual status = '" + debugeeExitStatus + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } +} // end of genericSignature002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002/TestDescription.java new file mode 100644 index 00000000000..6922d34f273 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/genericSignature/genericSignature002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * nsk/jdi/TypeComponent/genericSignature/genericSignature002 test: + * The test for the TypeComponent.genericSignature() method. + * The test checks up TypeComponent.genericSignature() method + * for Method objects. + * The first: the test checks that genericSignature() method returns + * null for methods which have not generic signature. The methods with + * different sets of arguments and with different returned types are + * used. + * The second: the test checks that genericSignature() method returns + * a corresponding signature string for methods which have generic + * signature. The methods with different sets of generic types + * arguments and with different returned generic types are used. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.genericSignature.genericSignature002 + * nsk.jdi.TypeComponent.genericSignature.genericSignature002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.genericSignature.genericSignature002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002a.java new file mode 100644 index 00000000000..de3b50167c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/genericSignature/genericSignature002a.java @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.genericSignature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for + * the nsk/jdi/TypeComponent/genericSignature/genericSignature002 JDI test. + */ + +public class genericSignature002a { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "genericSignature002(Debugee): "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> genericSignature002(Debugee): "; + static final String infoLogPrefix = "--> "; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + // methods without generic signature + // for check TypeComponent.genericSignature() method + + void testMethod_001() + { + } + + void testMethod_002 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + } + + boolean testMethod_003 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + return booleanArg; + } + + byte testMethod_004 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + return byteArg; + } + + char testMethod_005 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + return charArg; + } + + double testMethod_006 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + return doubleArg; + } + + float testMethod_007 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + return floatArg; + } + + int testMethod_008 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + return intArg; + } + + long testMethod_009 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + return longArg; + } + + Object testMethod_010 ( + boolean booleanArg, + byte byteArg, + char charArg, + double doubleArg, + float floatArg, + int intArg, + long longArg, + Object objectArg) + { + return objectArg; + } + + // methods with generic signature + // for check TypeComponent.genericSignature() method + + void testMethod_011 ( + GS002_Class06 GS002_Class06_Arg) + { + } + + GS002_Class06 testMethod_012 ( + GS002_Class06 GS002_Class06_Arg) + { + return GS002_Class06_Arg; + } + + void testMethod_013 ( + GS002_Class07 GS002_Class07_Arg) + { + } + + GS002_Class07 testMethod_014 ( + GS002_Class07 GS002_Class07_Arg) + { + return GS002_Class07_Arg; + } + + void testMethod_015 ( + GS002_Class08 GS002_Class08_Arg) + { + } + + GS002_Class08 testMethod_016 ( + GS002_Class08 GS002_Class08_Arg) + { + return GS002_Class08_Arg; + } + + void testMethod_017 ( + GS002_Class09 GS002_Class09_Arg) + { + } + + GS002_Class09 testMethod_018 ( + GS002_Class09 GS002_Class09_Arg) + { + return GS002_Class09_Arg; + } + + void testMethod_019 ( + GS002_Class10 GS002_Class10_Arg) + { + } + + GS002_Class10 testMethod_020 ( + GS002_Class10 GS002_Class10_Arg) + { + return GS002_Class10_Arg; + } + + + void testMethod_021 () + { + } + + void testMethod_022 (C C_Arg) + { + } + + C testMethod_023 (C C_Arg) + { + return C_Arg; + } + + void testMethod_024 () + { + } + + void testMethod_025 (C1 C1_Arg, C2 C2_Arg) + { + } + + C2 testMethod_026 (C1 C1_Arg, C2 C2_Arg) + { + return C2_Arg; + } + + void testMethod_027 () + { + } + + void testMethod_028 ( + C2 C2_Arg, C1 C1_Arg) + { + } + + + C1 testMethod_029 ( + C2 C2_Arg, C1 C1_Arg) + { + return C1_Arg; + } + + + public static void main (String argv[]) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(System.err, argsHandler); + logHandler.enableErrorsSummary(false); + IOPipe pipe = argsHandler.createDebugeeIOPipe(); + + logOnVerbose(infoLogPrefixHead + "Debugee started!"); + + genericSignature002a genericSignature002aDebugee = new genericSignature002a(); + + String readySignal = "ready"; + pipe.println(readySignal); + String quitSignal = "quit"; + logOnVerbose(infoLogPrefixHead + "Wait for '" + quitSignal + "' signal..."); + String signalFromDebugger = pipe.readln(); + if ( ! (quitSignal.equals(signalFromDebugger)) ) { + logOnError(errorLogPrefixHead + "UNEXPECTED debugger's signal:"); + logOnError(errorLogPrefix + "Expected signal = '" + quitSignal + "'"); + logOnError(errorLogPrefix + "Actual signal = '" + signalFromDebugger + "'"); + logOnError(errorLogPrefix + "Exiting with Exit Status = '" + (STATUS_FAILED + STATUS_TEMP) + "'"); + System.exit(STATUS_FAILED + STATUS_TEMP); + } + logOnVerbose(infoLogPrefixHead + "'" + quitSignal + "' signal from debugger is received."); + logOnVerbose(infoLogPrefix + "Exiting with Exit Status = '" + (STATUS_PASSED + STATUS_TEMP) + "'"); + System.exit(STATUS_PASSED + STATUS_TEMP); + } +} // end of genericSignature002a class + + +// non generic classes: + +class GS002_Class01 {} + +class GS002_Class02 {} + +interface GS002_Interf01 {} + +interface GS002_Interf02 {} + +class GS002_Class03 extends GS002_Class01 {} + +class GS002_Class04 extends GS002_Class01 implements GS002_Interf01 {} + +class GS002_Class05 extends GS002_Class02 implements GS002_Interf02 {} + + +// generic classes: + +class GS002_Class06 {} + +class GS002_Class07 {} + +class GS002_Class08 {} + +class GS002_Class09 {} + +class GS002_Class10 {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001.java new file mode 100644 index 00000000000..f88290841e4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class isfinal001 { + final static String IS_FINAL = "true"; + final static String NOT_FINAL = "false"; + final static int TOTAL_FIELDS = 165; + final static String FIELD_NAME[][] = { + {"z0", NOT_FINAL}, + {"z1", NOT_FINAL}, + {"z2", NOT_FINAL}, + {"b0", NOT_FINAL}, + {"b1", NOT_FINAL}, + {"b2", NOT_FINAL}, + {"c0", NOT_FINAL}, + {"c1", NOT_FINAL}, + {"c2", NOT_FINAL}, + {"d0", NOT_FINAL}, + {"d1", NOT_FINAL}, + {"d2", NOT_FINAL}, + {"f0", NOT_FINAL}, + {"f1", NOT_FINAL}, + {"f2", NOT_FINAL}, + {"i0", NOT_FINAL}, + {"i1", NOT_FINAL}, + {"i2", NOT_FINAL}, + {"l0", NOT_FINAL}, + {"l1", NOT_FINAL}, + {"l2", NOT_FINAL}, + {"r0", NOT_FINAL}, + {"r1", NOT_FINAL}, + {"r2", NOT_FINAL}, + + {"z0F", IS_FINAL}, + {"z1F", IS_FINAL}, + {"z2F", IS_FINAL}, + {"b0F", IS_FINAL}, + {"b1F", IS_FINAL}, + {"b2F", IS_FINAL}, + {"c0F", IS_FINAL}, + {"c1F", IS_FINAL}, + {"c2F", IS_FINAL}, + {"d0F", IS_FINAL}, + {"d1F", IS_FINAL}, + {"d2F", IS_FINAL}, + {"f0F", IS_FINAL}, + {"f1F", IS_FINAL}, + {"f2F", IS_FINAL}, + {"i0F", IS_FINAL}, + {"i1F", IS_FINAL}, + {"i2F", IS_FINAL}, + {"l0F", IS_FINAL}, + {"l1F", IS_FINAL}, + {"l2F", IS_FINAL}, + {"r0F", IS_FINAL}, + {"r1F", IS_FINAL}, + {"r2F", IS_FINAL}, + + {"lS0", NOT_FINAL}, + {"lS1", NOT_FINAL}, + {"lS2", NOT_FINAL}, + {"lP0", NOT_FINAL}, + {"lP1", NOT_FINAL}, + {"lP2", NOT_FINAL}, + {"lU0", NOT_FINAL}, + {"lU1", NOT_FINAL}, + {"lU2", NOT_FINAL}, + {"lR0", NOT_FINAL}, + {"lR1", NOT_FINAL}, + {"lR2", NOT_FINAL}, + {"lT0", NOT_FINAL}, + {"lT1", NOT_FINAL}, + {"lT2", NOT_FINAL}, + {"lV0", NOT_FINAL}, + {"lV1", NOT_FINAL}, + {"lV2", NOT_FINAL}, + + {"lS0F", IS_FINAL}, + {"lS1F", IS_FINAL}, + {"lS2F", IS_FINAL}, + {"lP0F", IS_FINAL}, + {"lP1F", IS_FINAL}, + {"lP2F", IS_FINAL}, + {"lU0F", IS_FINAL}, + {"lU1F", IS_FINAL}, + {"lU2F", IS_FINAL}, + {"lR0F", IS_FINAL}, + {"lR1F", IS_FINAL}, + {"lR2F", IS_FINAL}, + {"lT0F", IS_FINAL}, + {"lT1F", IS_FINAL}, + {"lT2F", IS_FINAL}, + + {"X0", NOT_FINAL}, + {"X1", NOT_FINAL}, + {"X2", NOT_FINAL}, + {"O0", NOT_FINAL}, + {"O1", NOT_FINAL}, + {"O2", NOT_FINAL}, + + {"X0F", IS_FINAL}, + {"X1F", IS_FINAL}, + {"X2F", IS_FINAL}, + {"O0F", IS_FINAL}, + {"O1F", IS_FINAL}, + {"O2F", IS_FINAL}, + + {"LS0", NOT_FINAL}, + {"LS1", NOT_FINAL}, + {"LS2", NOT_FINAL}, + {"LP0", NOT_FINAL}, + {"LP1", NOT_FINAL}, + {"LP2", NOT_FINAL}, + {"LU0", NOT_FINAL}, + {"LU1", NOT_FINAL}, + {"LU2", NOT_FINAL}, + {"LR0", NOT_FINAL}, + {"LR1", NOT_FINAL}, + {"LR2", NOT_FINAL}, + {"LT0", NOT_FINAL}, + {"LT1", NOT_FINAL}, + {"LT2", NOT_FINAL}, + {"LV0", NOT_FINAL}, + {"LV1", NOT_FINAL}, + {"LV2", NOT_FINAL}, + + {"LS0F", IS_FINAL}, + {"LS1F", IS_FINAL}, + {"LS2F", IS_FINAL}, + {"LP0F", IS_FINAL}, + {"LP1F", IS_FINAL}, + {"LP2F", IS_FINAL}, + {"LU0F", IS_FINAL}, + {"LU1F", IS_FINAL}, + {"LU2F", IS_FINAL}, + {"LR0F", IS_FINAL}, + {"LR1F", IS_FINAL}, + {"LR2F", IS_FINAL}, + {"LT0F", IS_FINAL}, + {"LT1F", IS_FINAL}, + {"LT2F", IS_FINAL}, + + {"E0", NOT_FINAL}, + {"E1", NOT_FINAL}, + {"E2", NOT_FINAL}, + + {"E0F", IS_FINAL}, + {"E1F", IS_FINAL}, + {"E2F", IS_FINAL}, + + {"ES0", NOT_FINAL}, + {"ES1", NOT_FINAL}, + {"ES2", NOT_FINAL}, + {"EP0", NOT_FINAL}, + {"EP1", NOT_FINAL}, + {"EP2", NOT_FINAL}, + {"EU0", NOT_FINAL}, + {"EU1", NOT_FINAL}, + {"EU2", NOT_FINAL}, + {"ER0", NOT_FINAL}, + {"ER1", NOT_FINAL}, + {"ER2", NOT_FINAL}, + {"ET0", NOT_FINAL}, + {"ET1", NOT_FINAL}, + {"ET2", NOT_FINAL}, + {"EV0", NOT_FINAL}, + {"EV1", NOT_FINAL}, + {"EV2", NOT_FINAL}, + + {"ES0F", IS_FINAL}, + {"ES1F", IS_FINAL}, + {"ES2F", IS_FINAL}, + {"EP0F", IS_FINAL}, + {"EP1F", IS_FINAL}, + {"EP2F", IS_FINAL}, + {"EU0F", IS_FINAL}, + {"EU1F", IS_FINAL}, + {"EU2F", IS_FINAL}, + {"ER0F", IS_FINAL}, + {"ER1F", IS_FINAL}, + {"ER2F", IS_FINAL}, + {"ET0F", IS_FINAL}, + {"ET1F", IS_FINAL}, + {"ET2F", IS_FINAL} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isFinal."; + private final static String className = "isfinal001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "isfinal001aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + ", total fields in debuger: " + + TOTAL_FIELDS); + // Check all fields from debugee + for (int i = 0; i < TOTAL_FIELDS; i++) { + Field field; + String name; + boolean isFinal; + String realIsFinal; + + try { + field = refType.fieldByName(FIELD_NAME[i][0]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + FIELD_NAME[i][0]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + isFinal = field.isFinal(); + realIsFinal = FIELD_NAME[i][1]; + log.display("debuger> " + i + " field (" + name + "), " + + "isFinal = " + isFinal + " read."); + + // isFinal() returns true if this type component is declared final, + // returns false otherwise + if ((isFinal && !realIsFinal.equals(IS_FINAL)) || + (!isFinal && realIsFinal.equals(IS_FINAL)) + ) { + log.complain("debuger FAILURE 2> " + i + " field " + name + + ": read field.isFinal() = " + isFinal + + "; real isFinal should be " + realIsFinal); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001/TestDescription.java new file mode 100644 index 00000000000..fe0df028b7f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isFinal/isfinal001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isFinal() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public boolean isFinal() + * Determines if this TypeComponent is final. Return value is undefined for + * constructors and static initializers. + * Returns: true if this type component was declared final; false otherwise. + * nsk/jdi/TypeComponent/isFinal/isfinal001 checks assertions: + * public boolean isFinal() + * 1. Returns true if the field was declared final. + * 2. Returns false otherwise. + * Debugger gets each field from debuggee calling by name and then checks + * if method isFinal() returns expected value. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isFinal.isfinal001 + * nsk.jdi.TypeComponent.isFinal.isfinal001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isFinal.isfinal001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001a.java new file mode 100644 index 00000000000..4faa54b2e94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001a.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isfinal001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + isfinal001aClassToCheck classToCheck = new isfinal001aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class isfinal001aClassToCheck { + // User class and interface + class isfinal001aClass {} + interface isfinal001aInter {} + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + final boolean z0F = true, z1F[]={z0F}, z2F[][]={z1F}; + final byte b0F = 1, b1F[]={b0F}, b2F[][]={b1F}; + final char c0F = '\u00ff', c1F[]={c0F}, c2F[][]={c1F}; + final double d0F = 1, d1F[]={d0F}, d2F[][]={d1F}; + final float f0F = 1f, f1F[]={f0F}, f2F[][]={f1F}; + final int i0F = 1, i1F[]={i0F}, i2F[][]={i1F}; + final long l0F = 1l, l1F[]={l0F}, l2F[][]={l1F}; + final short r0F = 1, r1F[]={r0F}, r2F[][]={r1F}; + + static long lS0, lS1[]={lS0}, lS2[][]={lS1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + final static long lS0F = 1l, lS1F[]={lS0F}, lS2F[][]={lS1F}; + final private long lP0F = 1l, lP1F[]={lP0F}, lP2F[][]={lP1F}; + final public long lU0F = 1l, lU1F[]={lU0F}, lU2F[][]={lU1F}; + final protected long lR0F = 1l, lR1F[]={lR0F}, lR2F[][]={lR1F}; + final transient long lT0F = 1l, lT1F[]={lT0F}, lT2F[][]={lT1F}; + + isfinal001aClass X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + final isfinal001aClass X0F = new isfinal001aClass(), X1F[]={X0F}, X2F[][]={X1F}; + final Object O0F = new Object(), O1F[]={O0F}, O2F[][]={O1F}; + + static Long LS0, LS1[]={LS0}, LS2[][]={LS1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + final static Long LS0F = new Long(1), LS1F[]={LS0F}, LS2F[][]={LS1F}; + final private Long LP0F = new Long(1), LP1F[]={LP0F}, LP2F[][]={LP1F}; + final public Long LU0F = new Long(1), LU1F[]={LU0F}, LU2F[][]={LU1F}; + final protected Long LR0F = new Long(1), LR1F[]={LR0F}, LR2F[][]={LR1F}; + final transient Long LT0F = new Long(1), LT1F[]={LT0F}, LT2F[][]={LT1F}; + + isfinal001aInter E0, E1[]={E0}, E2[][]={E1}; + final isfinal001aInter E0F = null, E1F[]={E0F}, E2F[][]={E1F}; + + static isfinal001aInter ES0, ES1[]={ES0}, ES2[][]={ES1}; + private isfinal001aInter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public isfinal001aInter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected isfinal001aInter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient isfinal001aInter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile isfinal001aInter EV0, EV1[]={EV0}, EV2[][]={EV1}; + + final static isfinal001aInter ES0F = null, ES1F[]={ES0F}, ES2F[][]={ES1F}; + final private isfinal001aInter EP0F = null, EP1F[]={EP0F}, EP2F[][]={EP1F}; + final public isfinal001aInter EU0F = null, EU1F[]={EU0F}, EU2F[][]={EU1F}; + final protected isfinal001aInter ER0F = null, ER1F[]={ER0F}, ER2F[][]={ER1F}; + final transient isfinal001aInter ET0F = null, ET1F[]={ET0F}, ET2F[][]={ET1F}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002.java new file mode 100644 index 00000000000..d9b10503f59 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class isfinal002 { + final static String IS_FINAL = "true"; + final static String NOT_FINAL = "false"; + final static int TOTAL_METHODS = 208; + final static String METHOD_NAME[][] = { + {"Mv", NOT_FINAL}, + {"Mz", NOT_FINAL}, + {"Mz1", NOT_FINAL}, + {"Mz2", NOT_FINAL}, + {"Mb", NOT_FINAL}, + {"Mb1", NOT_FINAL}, + {"Mb2", NOT_FINAL}, + {"Mc", NOT_FINAL}, + {"Mc1", NOT_FINAL}, + {"Mc2", NOT_FINAL}, + {"Md", NOT_FINAL}, + {"Md1", NOT_FINAL}, + {"Md2", NOT_FINAL}, + {"Mf", NOT_FINAL}, + {"Mf1", NOT_FINAL}, + {"Mf2", NOT_FINAL}, + {"Mi", NOT_FINAL}, + {"Mi1", NOT_FINAL}, + {"Mi2", NOT_FINAL}, + {"Ml", NOT_FINAL}, + {"Ml1", NOT_FINAL}, + {"Ml2", NOT_FINAL}, + {"Mr", NOT_FINAL}, + {"Mr1", NOT_FINAL}, + {"Mr2", NOT_FINAL}, + + {"MvF", IS_FINAL}, + {"MzF", IS_FINAL}, + {"Mz1F", IS_FINAL}, + {"Mz2F", IS_FINAL}, + {"MbF", IS_FINAL}, + {"Mb1F", IS_FINAL}, + {"Mb2F", IS_FINAL}, + {"McF", IS_FINAL}, + {"Mc1F", IS_FINAL}, + {"Mc2F", IS_FINAL}, + {"MdF", IS_FINAL}, + {"Md1F", IS_FINAL}, + {"Md2F", IS_FINAL}, + {"MfF", IS_FINAL}, + {"Mf1F", IS_FINAL}, + {"Mf2F", IS_FINAL}, + {"MiF", IS_FINAL}, + {"Mi1F", IS_FINAL}, + {"Mi2F", IS_FINAL}, + {"MlF", IS_FINAL}, + {"Ml1F", IS_FINAL}, + {"Ml2F", IS_FINAL}, + {"MrF", IS_FINAL}, + {"Mr1F", IS_FINAL}, + {"Mr2F", IS_FINAL}, + + {"MvS", NOT_FINAL}, + {"MlS", NOT_FINAL}, + {"MlS1", NOT_FINAL}, + {"MlS2", NOT_FINAL}, + {"MvN", NOT_FINAL}, + {"MlN", NOT_FINAL}, + {"MlN1", NOT_FINAL}, + {"MlN2", NOT_FINAL}, + {"MvI", NOT_FINAL}, + {"MlI", NOT_FINAL}, + {"MlI1", NOT_FINAL}, + {"MlI2", NOT_FINAL}, + {"MvY", NOT_FINAL}, + {"MlY", NOT_FINAL}, + {"MlY1", NOT_FINAL}, + {"MlY2", NOT_FINAL}, + {"MvU", NOT_FINAL}, + {"MlU", NOT_FINAL}, + {"MlU1", NOT_FINAL}, + {"MlU2", NOT_FINAL}, + {"MvR", NOT_FINAL}, + {"MlR", NOT_FINAL}, + {"MlR1", NOT_FINAL}, + {"MlR2", NOT_FINAL}, + {"MvP", NOT_FINAL}, + {"MlP", NOT_FINAL}, + {"MlP1", NOT_FINAL}, + {"MlP2", NOT_FINAL}, + + {"MvSF", IS_FINAL}, + {"MlSF", IS_FINAL}, + {"MlS1F", IS_FINAL}, + {"MlS2F", IS_FINAL}, + {"MvNF", IS_FINAL}, + {"MlNF", IS_FINAL}, + {"MlN1F", IS_FINAL}, + {"MlN2F", IS_FINAL}, + {"MvIF", IS_FINAL}, + {"MlIF", IS_FINAL}, + {"MlI1F", IS_FINAL}, + {"MlI2F", IS_FINAL}, + {"MvYF", IS_FINAL}, + {"MlYF", IS_FINAL}, + {"MlY1F", IS_FINAL}, + {"MlY2F", IS_FINAL}, + {"MvUF", IS_FINAL}, + {"MlUF", IS_FINAL}, + {"MlU1F", IS_FINAL}, + {"MlU2F", IS_FINAL}, + {"MvRF", IS_FINAL}, + {"MlRF", IS_FINAL}, + {"MlR1F", IS_FINAL}, + {"MlR2F", IS_FINAL}, + {"MvPF", IS_FINAL}, + {"MlPF", IS_FINAL}, + {"MlP1F", IS_FINAL}, + {"MlP2F", IS_FINAL}, + + {"MX", NOT_FINAL}, + {"MX1", NOT_FINAL}, + {"MX2", NOT_FINAL}, + {"MO", NOT_FINAL}, + {"MO1", NOT_FINAL}, + {"MO2", NOT_FINAL}, + + {"MXF", IS_FINAL}, + {"MX1F", IS_FINAL}, + {"MX2F", IS_FINAL}, + {"MOF", IS_FINAL}, + {"MO1F", IS_FINAL}, + {"MO2F", IS_FINAL}, + + {"MLS", NOT_FINAL}, + {"MLS1", NOT_FINAL}, + {"MLS2", NOT_FINAL}, + {"MLN", NOT_FINAL}, + {"MLN1", NOT_FINAL}, + {"MLN2", NOT_FINAL}, + {"MLI", NOT_FINAL}, + {"MLI1", NOT_FINAL}, + {"MLI2", NOT_FINAL}, + {"MLY", NOT_FINAL}, + {"MLY1", NOT_FINAL}, + {"MLY2", NOT_FINAL}, + {"MLU", NOT_FINAL}, + {"MLU1", NOT_FINAL}, + {"MLU2", NOT_FINAL}, + {"MLR", NOT_FINAL}, + {"MLR1", NOT_FINAL}, + {"MLR2", NOT_FINAL}, + {"MLP", NOT_FINAL}, + {"MLP1", NOT_FINAL}, + {"MLP2", NOT_FINAL}, + + {"MLSF", IS_FINAL}, + {"MLS1F", IS_FINAL}, + {"MLS2F", IS_FINAL}, + {"MLNF", IS_FINAL}, + {"MLN1F", IS_FINAL}, + {"MLN2F", IS_FINAL}, + {"MLIF", IS_FINAL}, + {"MLI1F", IS_FINAL}, + {"MLI2F", IS_FINAL}, + {"MLYF", IS_FINAL}, + {"MLY1F", IS_FINAL}, + {"MLY2F", IS_FINAL}, + {"MLUF", IS_FINAL}, + {"MLU1F", IS_FINAL}, + {"MLU2F", IS_FINAL}, + {"MLRF", IS_FINAL}, + {"MLR1F", IS_FINAL}, + {"MLR2F", IS_FINAL}, + {"MLPF", IS_FINAL}, + {"MLP1F", IS_FINAL}, + {"MLP2F", IS_FINAL}, + + {"ME", NOT_FINAL}, + {"ME1", NOT_FINAL}, + {"ME2", NOT_FINAL}, + {"MEF", IS_FINAL}, + {"ME1F", IS_FINAL}, + {"ME2F", IS_FINAL}, + + {"MES", NOT_FINAL}, + {"MES1", NOT_FINAL}, + {"MES2", NOT_FINAL}, + {"MEN", NOT_FINAL}, + {"MEN1", NOT_FINAL}, + {"MEN2", NOT_FINAL}, + {"MEI", NOT_FINAL}, + {"MEI1", NOT_FINAL}, + {"MEI2", NOT_FINAL}, + {"MEY", NOT_FINAL}, + {"MEY1", NOT_FINAL}, + {"MEY2", NOT_FINAL}, + {"MEU", NOT_FINAL}, + {"MEU1", NOT_FINAL}, + {"MEU2", NOT_FINAL}, + {"MER", NOT_FINAL}, + {"MER1", NOT_FINAL}, + {"MER2", NOT_FINAL}, + {"MEP", NOT_FINAL}, + {"MEP1", NOT_FINAL}, + {"MEP2", NOT_FINAL}, + + {"MESF", IS_FINAL}, + {"MES1F", IS_FINAL}, + {"MES2F", IS_FINAL}, + {"MENF", IS_FINAL}, + {"MEN1F", IS_FINAL}, + {"MEN2F", IS_FINAL}, + {"MEIF", IS_FINAL}, + {"MEI1F", IS_FINAL}, + {"MEI2F", IS_FINAL}, + {"MEYF", IS_FINAL}, + {"MEY1F", IS_FINAL}, + {"MEY2F", IS_FINAL}, + {"MEUF", IS_FINAL}, + {"MEU1F", IS_FINAL}, + {"MEU2F", IS_FINAL}, + {"MERF", IS_FINAL}, + {"MER1F", IS_FINAL}, + {"MER2F", IS_FINAL}, + {"MEPF", IS_FINAL}, + {"MEP1F", IS_FINAL}, + {"MEP2F", IS_FINAL} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isFinal."; + private final static String className = "isfinal002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "isfinal002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Check all methods from debugee + for (int i = 0; i < METHOD_NAME.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + boolean isFinal; + String realIsFinal; + + try { + listOfMethods = refType.methodsByName(METHOD_NAME[i][0]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get method by name " + + METHOD_NAME[i][0]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + METHOD_NAME[i][0] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + isFinal = method.isFinal(); + realIsFinal = METHOD_NAME[i][1]; + log.display("debuger> " + i + " method (" + name + "), " + + "isFinal = " + isFinal + " read."); + + // isFinal() returns true if this type component is declared + // final, returns false otherwise + if ((isFinal && !realIsFinal.equals(IS_FINAL)) || + (!isFinal && realIsFinal.equals(IS_FINAL)) + ) { + log.display("debuger FAILURE 3> " + i + " method " + name + + ": read method.isFinal() = " + isFinal + + "; real isFinal should be " + realIsFinal); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002/TestDescription.java new file mode 100644 index 00000000000..dd23afba875 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isFinal/isfinal002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isFinal() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public boolean isFinal() + * Determines if this TypeComponent is final. Return value is undefined for + * constructors and static initializers. + * Returns: true if this type component was declared final; false otherwise. + * nsk/jdi/TypeComponent/isFinal/isfinal002 checks assertions: + * public boolean isFinal() + * 1. Returns true if the method was declared final. + * 2. Returns false otherwise. + * Debugger gets each method from debuggee calling by name and then checks + * if isFinal() returns expected value. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isFinal.isfinal002 + * nsk.jdi.TypeComponent.isFinal.isfinal002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isFinal.isfinal002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002a.java new file mode 100644 index 00000000000..4676f6728bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal002a.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isfinal002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + isfinal002aClassToCheck classToCheck = new isfinal002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class isfinal002aClassToCheck { + // User class and interface + class isfinal002aClass {} + interface isfinal002aInter {} + + // Methods + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + final void MvF() {}; + final boolean MzF(boolean z) { return z; }; + final boolean[] Mz1F(boolean z[]) { return z; }; + final boolean[][] Mz2F(boolean z[][]) { return z; }; + final byte MbF(byte b) { return b; }; + final byte[] Mb1F(byte b[]) { return b; }; + final byte[][] Mb2F(byte b[][]) { return b; }; + final char McF(char c) { return c; }; + final char[] Mc1F(char c[]) { return c; }; + final char[][] Mc2F(char c[][]) { return c; }; + final double MdF(double d) { return d; }; + final double[] Md1F(double d[]) { return d; }; + final double[][] Md2F(double d[][]) { return d; }; + final float MfF(float f) { return f; }; + final float[] Mf1F(float f[]) { return f; }; + final float[][] Mf2F(float f[][]) { return f; }; + final int MiF(int i) { return i; }; + final int[] Mi1F(int i[]) { return i; }; + final int[][] Mi2F(int i[][]) { return i; }; + final long MlF(long l) { return l; }; + final long[] Ml1F(long l[]) { return l; }; + final long[][] Ml2F(long l[][]) { return l; }; + final short MrF(short r) { return r; }; + final short[] Mr1F(short r[]) { return r; }; + final short[][] Mr2F(short r[][]) { return r; }; + + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + final static void MvSF() {}; + final static long MlSF(long l) { return l; }; + final static long[] MlS1F(long l[]) { return l; }; + final static long[][] MlS2F(long l[][]) { return l; }; + final native void MvNF(); + final native long MlNF(long l); + final native long[] MlN1F(long l[]); + final native long[][] MlN2F(long l[][]); + final strictfp void MvIF() {}; + final strictfp long MlIF(long l) { return l; }; + final strictfp long[] MlI1F(long l[]) { return l; }; + final strictfp long[][] MlI2F(long l[][]) { return l; }; + final synchronized void MvYF() {}; + final synchronized long MlYF(long l) { return l; }; + final synchronized long[] MlY1F(long l[]) { return l; }; + final synchronized long[][] MlY2F(long l[][]) { return l; }; + final public void MvUF() {}; + final public long MlUF(long l) { return l; }; + final public long[] MlU1F(long l[]) { return l; }; + final public long[][] MlU2F(long l[][]) { return l; }; + final protected void MvRF() {}; + final protected long MlRF(long l) { return l; }; + final protected long[] MlR1F(long l[]) { return l; }; + final protected long[][] MlR2F(long l[][]) { return l; }; + final private void MvPF() {}; + final private long MlPF(long l) { return l; }; + final private long[] MlP1F(long l[]) { return l; }; + final private long[][] MlP2F(long l[][]) { return l; }; + + isfinal002aClass MX(isfinal002aClass X) { return X; }; + isfinal002aClass[] MX1(isfinal002aClass X[]) { return X; }; + isfinal002aClass[][] MX2(isfinal002aClass X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + final isfinal002aClass MXF(isfinal002aClass X) { return X; }; + final isfinal002aClass[] MX1F(isfinal002aClass X[]) { return X; }; + final isfinal002aClass[][] MX2F(isfinal002aClass X[][]) { return X; }; + final Object MOF(Object O) { return O; }; + final Object[] MO1F(Object[] O) { return O; }; + final Object[][] MO2F(Object[][] O) { return O; }; + + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long[] L) { return L; }; + static Long[][] MLS2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + final static Long MLSF(Long L) { return L; }; + final static Long[] MLS1F(Long[] L) { return L; }; + final static Long[][] MLS2F(Long[][] L) { return L; }; + final native Long MLNF(Long L); + final native Long[] MLN1F(Long[] L); + final native Long[][] MLN2F(Long[][] L); + final strictfp Long MLIF(Long L) { return L; }; + final strictfp Long[] MLI1F(Long[] L) { return L; }; + final strictfp Long[][] MLI2F(Long[][] L) { return L; }; + final synchronized Long MLYF(Long L) { return L; }; + final synchronized Long[] MLY1F(Long[] L) { return L; }; + final synchronized Long[][] MLY2F(Long[][] L) { return L; }; + final public Long MLUF(Long L) { return L; }; + final public Long[] MLU1F(Long[] L) { return L; }; + final public Long[][] MLU2F(Long[][] L) { return L; }; + final protected Long MLRF(Long L) { return L; }; + final protected Long[] MLR1F(Long[] L) { return L; }; + final protected Long[][] MLR2F(Long[][] L) { return L; }; + final private Long MLPF(Long L) { return L; }; + final private Long[] MLP1F(Long[] L) { return L; }; + final private Long[][] MLP2F(Long[][] L) { return L; }; + + isfinal002aInter ME(isfinal002aInter E) { return E; }; + isfinal002aInter[] ME1(isfinal002aInter[] E) { return E; }; + isfinal002aInter[][] ME2(isfinal002aInter[][] E) { return E; }; + final isfinal002aInter MEF(isfinal002aInter E) { return E; }; + final isfinal002aInter[] ME1F(isfinal002aInter[] E) { return E; }; + final isfinal002aInter[][] ME2F(isfinal002aInter[][] E) { return E; }; + + static isfinal002aInter MES(isfinal002aInter E) { return E; }; + static isfinal002aInter[] MES1(isfinal002aInter[] E) { return E; }; + static isfinal002aInter[][] MES2(isfinal002aInter[][] E) { return E; }; + native isfinal002aInter MEN(isfinal002aInter E); + native isfinal002aInter[] MEN1(isfinal002aInter[] E); + native isfinal002aInter[][] MEN2(isfinal002aInter[][] E); + strictfp isfinal002aInter MEI(isfinal002aInter E) { return E; }; + strictfp isfinal002aInter[] MEI1(isfinal002aInter[] E) { return E; }; + strictfp isfinal002aInter[][] MEI2(isfinal002aInter[][] E) { return E; }; + synchronized isfinal002aInter MEY(isfinal002aInter E) { return E; }; + synchronized isfinal002aInter[] MEY1(isfinal002aInter[] E) { return E; }; + synchronized isfinal002aInter[][] MEY2(isfinal002aInter[][] E) { return E; }; + public isfinal002aInter MEU(isfinal002aInter E) { return E; }; + public isfinal002aInter[] MEU1(isfinal002aInter[] E) { return E; }; + public isfinal002aInter[][] MEU2(isfinal002aInter[][] E) { return E; }; + protected isfinal002aInter MER(isfinal002aInter E) { return E; }; + protected isfinal002aInter[] MER1(isfinal002aInter[] E) { return E; }; + protected isfinal002aInter[][] MER2(isfinal002aInter[][] E) { return E; }; + private isfinal002aInter MEP(isfinal002aInter E) { return E; }; + private isfinal002aInter[] MEP1(isfinal002aInter[] E) { return E; }; + private isfinal002aInter[][] MEP2(isfinal002aInter[][] E) { return E; }; + + final static isfinal002aInter MESF(isfinal002aInter E) { return E; }; + final static isfinal002aInter[] MES1F(isfinal002aInter[] E) { return E; }; + final static isfinal002aInter[][] MES2F(isfinal002aInter[][] E) { return E; }; + final native isfinal002aInter MENF(isfinal002aInter E); + final native isfinal002aInter[] MEN1F(isfinal002aInter[] E); + final native isfinal002aInter[][] MEN2F(isfinal002aInter[][] E); + final strictfp isfinal002aInter MEIF(isfinal002aInter E) { return E; }; + final strictfp isfinal002aInter[] MEI1F(isfinal002aInter[] E) { return E; }; + final strictfp isfinal002aInter[][] MEI2F(isfinal002aInter[][] E) { return E; }; + final synchronized isfinal002aInter MEYF(isfinal002aInter E) { return E; }; + final synchronized isfinal002aInter[] MEY1F(isfinal002aInter[] E) { return E; }; + final synchronized isfinal002aInter[][] MEY2F(isfinal002aInter[][] E) { return E; }; + final public isfinal002aInter MEUF(isfinal002aInter E) { return E; }; + final public isfinal002aInter[] MEU1F(isfinal002aInter[] E) { return E; }; + final public isfinal002aInter[][] MEU2F(isfinal002aInter[][] E) { return E; }; + final protected isfinal002aInter MERF(isfinal002aInter E) { return E; }; + final protected isfinal002aInter[] MER1F(isfinal002aInter[] E) { return E; }; + final protected isfinal002aInter[][] MER2F(isfinal002aInter[][] E) { return E; }; + final private isfinal002aInter MEPF(isfinal002aInter E) { return E; }; + final private isfinal002aInter[] MEP1F(isfinal002aInter[] E) { return E; }; + final private isfinal002aInter[][] MEP2F(isfinal002aInter[][] E) { return E; }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003.java new file mode 100644 index 00000000000..ff67f43c5dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class isfinal003 { + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isFinal."; + private final static String className = "isfinal003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "isfinal003aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List methods; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Get all methods, find constructors and static initializers and + // check them + try { + methods = refType.allMethods(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get methods from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalMethods = methods.size(); + if (totalMethods < 1) { + log.complain("debuger FAILURE> Total number of methods read " + + totalMethods); + return 2; + } + log.display("debuger> Total methods found: " + totalMethods); + Iterator methodsIterator = methods.iterator(); + for (int i = 0; methodsIterator.hasNext(); i++) { + Method method = (Method)methodsIterator.next(); + boolean isFinal; + String decTypeName = method.declaringType().name(); + String name = method.name(); + + if (method.isConstructor() || method.isStaticInitializer()) { + try { + isFinal = method.isFinal(); + } catch(Exception e) { + log.complain("debuger FAILURE 1> Cannot get isFinal from " + + "method " + name + " in " + decTypeName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " method (" + name + "), " + + "isFinal = " + isFinal + " read in " + + decTypeName); + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003/TestDescription.java new file mode 100644 index 00000000000..03b2905b223 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isFinal/isfinal003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isFinal() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public boolean isFinal() + * Determines if this TypeComponent is final. Return value is undefined for + * constructors and static initializers. + * Returns: true if this type component was declared final; false otherwise. + * nsk/jdi/TypeComponent/isFinal/isfinal003 checks assertion: + * public boolean isFinal() + * 1. method isFinal() is defined for constructors and static initializers and + * does not throw an Exception. + * Debugger gets all methods from debuggee, finds contructors and static + * initializers only and checks if isFinal() doesn't throw any Exception. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isFinal.isfinal003 + * nsk.jdi.TypeComponent.isFinal.isfinal003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isFinal.isfinal003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003a.java new file mode 100644 index 00000000000..8dbdebc426e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003a.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isfinal003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + isfinal003aClassToCheck classToCheck = new isfinal003aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class isfinal003aClassToCheck extends isfinal003aSuperClass { + isfinal003aClassToCheck() {}; + public isfinal003aClassToCheck(long l) {}; + private isfinal003aClassToCheck(Object obj) {}; + protected isfinal003aClassToCheck(long[] l) {}; + + static int ci; + static Long cL; + static long[] cl = new long[10]; + + static { ci = 1; } + static { cL = new Long(1l); } + static { + for (int i = 0; i < 10; i++) { + cl[i] = (long)i; + } + } +} + +class isfinal003aSuperClass { + isfinal003aSuperClass() {}; + public isfinal003aSuperClass(long l) {}; + private isfinal003aSuperClass(Object obj) {}; + protected isfinal003aSuperClass(long[] l) {}; + + static boolean sb; + static Object sO; + static float[] sf = new float[10]; + + static { sb = true; } + static { sO = new Object(); } + static { + for (int i = 0; i < 10; i++) { + sf[i] = (float)i; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004.java new file mode 100644 index 00000000000..66934851fdf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isfinal004 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.TypeComponent.isFinal."; + private final static String className = "isfinal004"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] expectedFieldNames = {"f1", "f2", "f3"}; + private final static String[] expectedEnumFieldsNames = { "e1", "e2" }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + Field foundField = checkedClass.fieldByName(expectedEnumFieldsNames[i]); + if (foundField != null) { + if (foundField.isFinal()) { + display("enum " + className + " has final field " + expectedEnumFieldsNames[i]); + display("\t of type " + className); + } else { + complain("enum " + className + " has not-final field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } else { + complain("enum " + className + " does not have field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004/TestDescription.java new file mode 100644 index 00000000000..acac69188fe --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isFinal/isfinal004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isFinal() method of TypeComponent interface. + * The test checks if the method returns true for each enum + * constants declared in mirrored enum type. + * The test consists of a debugger program (isfinal004.java) + * and debuggee application (isfinal004a.java). + * Package name is nsk.jdi.TypeComponent.isFinal . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger finds fields of enum type declared in isfinal004a + * class. Then the debugger checks if test assertion for + * every enum constants declared in mirrored enum types. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isFinal.isfinal004 + * nsk.jdi.TypeComponent.isFinal.isfinal004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isFinal.isfinal004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004a.java new file mode 100644 index 00000000000..40b6a169833 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal004a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.isFinal; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isfinal004a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static isfinal004Enum1 f1 = isfinal004Enum1.e2; + static isfinal004Enum2 f2 = isfinal004Enum2.e1; + static isfinal004Enum1.Enum1_ f3 = isfinal004Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isfinal004.SIGNAL_READY); + + + //pipe.println(isfinal004.SIGNAL_GO); + receiveSignal(isfinal004.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum isfinal004Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum isfinal004Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001.java new file mode 100644 index 00000000000..889a2604edd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPackagePrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class ispackageprivate001 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isPackagePrivate."; + private final static String debuggerName = prefix + "ispackageprivate001"; + private final static String debuggeeName = debuggerName + "a"; + + private static ReferenceType debuggeeClass; + + final static String IS_PPRIVATE = "true"; + final static String NOT_PPRIVATE = "false"; + final static int TOTAL_FIELDS = 132; + + /** debuggee's fields for check **/ + private final static String checkedFields[][] = { + {"z0", IS_PPRIVATE}, {"z1", IS_PPRIVATE}, {"z2", IS_PPRIVATE}, + {"b0", IS_PPRIVATE}, {"b1", IS_PPRIVATE}, {"b2", IS_PPRIVATE}, + {"c0", IS_PPRIVATE}, {"c1", IS_PPRIVATE}, {"c2", IS_PPRIVATE}, + {"d0", IS_PPRIVATE}, {"d1", IS_PPRIVATE}, {"d2", IS_PPRIVATE}, + {"f0", IS_PPRIVATE}, {"f1", IS_PPRIVATE}, {"f2", IS_PPRIVATE}, + {"i0", IS_PPRIVATE}, {"i1", IS_PPRIVATE}, {"i2", IS_PPRIVATE}, + {"l0", IS_PPRIVATE}, {"l1", IS_PPRIVATE}, {"l2", IS_PPRIVATE}, + {"r0", IS_PPRIVATE}, {"r1", IS_PPRIVATE}, {"r2", IS_PPRIVATE}, + + {"zP0", NOT_PPRIVATE}, {"zP1", NOT_PPRIVATE}, {"zP2", NOT_PPRIVATE}, + {"bP0", NOT_PPRIVATE}, {"bP1", NOT_PPRIVATE}, {"bP2", NOT_PPRIVATE}, + {"cP0", NOT_PPRIVATE}, {"cP1", NOT_PPRIVATE}, {"cP2", NOT_PPRIVATE}, + {"dP0", NOT_PPRIVATE}, {"dP1", NOT_PPRIVATE}, {"dP2", NOT_PPRIVATE}, + {"fP0", NOT_PPRIVATE}, {"fP1", NOT_PPRIVATE}, {"fP2", NOT_PPRIVATE}, + {"iP0", NOT_PPRIVATE}, {"iP1", NOT_PPRIVATE}, {"iP2", NOT_PPRIVATE}, + {"lP0", NOT_PPRIVATE}, {"lP1", NOT_PPRIVATE}, {"lP2", NOT_PPRIVATE}, + {"rP0", NOT_PPRIVATE}, {"rP1", NOT_PPRIVATE}, {"rP2", NOT_PPRIVATE}, + + {"Z0", IS_PPRIVATE}, {"Z1", IS_PPRIVATE}, {"Z2", IS_PPRIVATE}, + {"B0", IS_PPRIVATE}, {"B1", IS_PPRIVATE}, {"B2", IS_PPRIVATE}, + {"C0", IS_PPRIVATE}, {"C1", IS_PPRIVATE}, {"C2", IS_PPRIVATE}, + {"D0", IS_PPRIVATE}, {"D1", IS_PPRIVATE}, {"D2", IS_PPRIVATE}, + {"F0", IS_PPRIVATE}, {"F1", IS_PPRIVATE}, {"F2", IS_PPRIVATE}, + {"I0", IS_PPRIVATE}, {"I1", IS_PPRIVATE}, {"I2", IS_PPRIVATE}, + {"L0", IS_PPRIVATE}, {"L1", IS_PPRIVATE}, {"L2", IS_PPRIVATE}, + {"R0", IS_PPRIVATE}, {"R1", IS_PPRIVATE}, {"R2", IS_PPRIVATE}, + + {"ZP0", NOT_PPRIVATE}, {"ZP1", NOT_PPRIVATE}, {"ZP2", NOT_PPRIVATE}, + {"BP0", NOT_PPRIVATE}, {"BP1", NOT_PPRIVATE}, {"BP2", NOT_PPRIVATE}, + {"CP0", NOT_PPRIVATE}, {"CP1", NOT_PPRIVATE}, {"CP2", NOT_PPRIVATE}, + {"DP0", NOT_PPRIVATE}, {"DP1", NOT_PPRIVATE}, {"DP2", NOT_PPRIVATE}, + {"FP0", NOT_PPRIVATE}, {"FP1", NOT_PPRIVATE}, {"FP2", NOT_PPRIVATE}, + {"IP0", NOT_PPRIVATE}, {"IP1", NOT_PPRIVATE}, {"IP2", NOT_PPRIVATE}, + {"LP0", NOT_PPRIVATE}, {"LP1", NOT_PPRIVATE}, {"LP2", NOT_PPRIVATE}, + {"RP0", NOT_PPRIVATE}, {"RP1", NOT_PPRIVATE}, {"RP2", NOT_PPRIVATE}, + + {"s0", NOT_PPRIVATE}, {"s1", NOT_PPRIVATE}, {"s2", NOT_PPRIVATE}, + {"o0", NOT_PPRIVATE}, {"o1", NOT_PPRIVATE}, {"o2", NOT_PPRIVATE}, + {"S0", IS_PPRIVATE}, {"S1", IS_PPRIVATE}, {"S2", IS_PPRIVATE}, + {"O0", IS_PPRIVATE}, {"O1", IS_PPRIVATE}, {"O2", IS_PPRIVATE}, + + {"u0", NOT_PPRIVATE}, {"u1", NOT_PPRIVATE}, {"u2", NOT_PPRIVATE}, + {"v0", IS_PPRIVATE}, {"v1", IS_PPRIVATE}, {"v2", IS_PPRIVATE}, + {"w0", NOT_PPRIVATE}, {"w1", NOT_PPRIVATE}, {"w2", NOT_PPRIVATE}, + {"p0", NOT_PPRIVATE}, {"p1", NOT_PPRIVATE}, {"p2", NOT_PPRIVATE}, + + {"h0", NOT_PPRIVATE}, {"h1", NOT_PPRIVATE}, {"h2", NOT_PPRIVATE}, + {"j0", IS_PPRIVATE}, {"j1", IS_PPRIVATE}, {"j2", IS_PPRIVATE}, + {"k0", NOT_PPRIVATE}, {"k1", NOT_PPRIVATE}, {"k2", NOT_PPRIVATE}, + {"m0", NOT_PPRIVATE}, {"m1", NOT_PPRIVATE}, {"m2", NOT_PPRIVATE} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (Consts.TEST_PASSED) or either 2 (Consts.TEST_FAILED). + */ + public static int run (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + Debugee debuggee = binder.bindToDebugee(debuggeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "debugger > "); + + debuggee.resume(); + display("Waiting debuggee's \"ready\" signal..."); + String line = pipe.readln(); + + if (line == null) { + complain("UNEXPECTED debuggee's signal - null"); + return Consts.TEST_FAILED; + } + if (!line.equals("ready")) { + complain("UNEXPECTED debuggee's signal - " + line); + return Consts.TEST_FAILED; + } else { + display("debuggee's \"ready\" signal recieved."); + } + + int exitStatus = Consts.TEST_PASSED; + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return Consts.TEST_FAILED; + } + + + display("Checking isPackagePrivate() method for debuggee's fields..."); + + display("Total count of fields read from debuggee: " + + debuggeeClass.allFields().size() + ", expected count : " + + TOTAL_FIELDS); + + // Check all fields from debuggee + for (int i = 0; i < TOTAL_FIELDS; i++) { + Field field; + String name; + boolean isPackagePrivate; + String expectedValue; + + try { + field = debuggeeClass.fieldByName(checkedFields[i][0]); + } catch (Exception e) { + complain("Can't get field by name " + checkedFields[i][0]); + complain("Unexpected Exception: " + e); + exitStatus = Consts.TEST_FAILED; + continue; + } + + name = field.name(); + isPackagePrivate = ((TypeComponent)field).isPackagePrivate(); // cast to TypeComponent interface + expectedValue = checkedFields[i][1]; + if ((isPackagePrivate && !expectedValue.equals(IS_PPRIVATE)) || + (!isPackagePrivate && expectedValue.equals(IS_PPRIVATE)) ) { + complain("isPackagePrivate() returned wrong value: " + isPackagePrivate + + " for field " + name + + "; expected value : " + expectedValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("isPackagePrivate() returned expected " + isPackagePrivate + + " for field " + name); + } + } + + display("Checking debuggee's fields completed!"); + display("Waiting for debuggee's finish..."); + pipe.println("quit"); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != Consts.TEST_PASSED + Consts.JCK_STATUS_BASE) { + complain("UNEXPECTED debuggee's exit status (not 95) - " + status); + exitStatus = Consts.TEST_FAILED; + } else { + display("Got expected debuggee's exit status - " + status); + } + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001/TestDescription.java new file mode 100644 index 00000000000..42c5b24ba7d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isPackagePrivate() method of Accessible interface + * for TypeComponent sub-interface of com.sun.jdi package. + * The method spec: + * public boolean isPackagePrivate() + * Determines if this object mirrors a package private item. A package + * private item is declared with no access specifier. For ArrayType, the return + * value depends on the array component type. For primitive arrays the return + * value is always false. For object arrays, the return value is the same + * as would be returned for the component type. For primitive classes, such + * as Integer.TYPE, the return value is always false. + * Returns: + * true for items with package private access; false otherwise. + * nsk/jdi/TypeComponent/isPackagePrivate/isprivate001 checks assertions: + * public boolean isPackagePrivate() + * 1. Returns true if the field was declared package private. + * 2. Returns false otherwise. + * Debugger gets each field from debuggee calling by name and then checks + * if method isPackagePrivate() returns an expected value. + * COMMENTS + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for isPackagePrivate method. + * The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isPackagePrivate.ispackageprivate001 + * nsk.jdi.TypeComponent.isPackagePrivate.ispackageprivate001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isPackagePrivate.ispackageprivate001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001a.java new file mode 100644 index 00000000000..cab9f831129 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate001a.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPackagePrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class ispackageprivate001a { + + boolean z0, z1[] = {z0}, z2[][] = {z1}; + byte b0, b1[] = {b0}, b2[][] = {b1}; + char c0, c1[] = {c0}, c2[][] = {c1}; + double d0, d1[] = {d0}, d2[][] = {d1}; + float f0, f1[] = {f0}, f2[][] = {f1}; + int i0, i1[] = {i0}, i2[][] = {i1}; + long l0, l1[] = {l0}, l2[][] = {l1}; + short r0, r1[] = {r0}, r2[][] = {r1}; + + private boolean zP0, zP1[] = {zP0}, zP2[][] = {zP1}; + private byte bP0, bP1[] = {bP0}, bP2[][] = {bP1}; + private char cP0, cP1[] = {cP0}, cP2[][] = {cP1}; + private double dP0, dP1[] = {dP0}, dP2[][] = {dP1}; + private float fP0, fP1[] = {fP0}, fP2[][] = {fP1}; + private int iP0, iP1[] = {iP0}, iP2[][] = {iP1}; + private long lP0, lP1[] = {lP0}, lP2[][] = {lP1}; + private short rP0, rP1[] = {rP0}, rP2[][] = {rP1}; + + Boolean Z0, Z1[] = {Z0}, Z2[][] = {Z1}; + Byte B0, B1[] = {B0}, B2[][] = {B1}; + Character C0, C1[] = {C0}, C2[][] = {C1}; + Double D0, D1[] = {D0}, D2[][] = {D1}; + Float F0, F1[] = {F0}, F2[][] = {F1}; + Integer I0, I1[] = {I0}, I2[][] = {I1}; + Long L0, L1[] = {L0}, L2[][] = {L1}; + Short R0, R1[] = {R0}, R2[][] = {R1}; + + private Boolean ZP0, ZP1[] = {ZP0}, ZP2[][] = {ZP1}; + private Byte BP0, BP1[] = {BP0}, BP2[][] = {BP1}; + private Character CP0, CP1[] = {CP0}, CP2[][] = {CP1}; + private Double DP0, DP1[] = {DP0}, DP2[][] = {DP1}; + private Float FP0, FP1[] = {FP0}, FP2[][] = {FP1}; + private Integer IP0, IP1[] = {IP0}, IP2[][] = {IP1}; + private Long LP0, LP1[] = {LP0}, LP2[][] = {LP1}; + private Short RP0, RP1[] = {RP0}, RP2[][] = {RP1}; + + private String s0, s1[] = {s0}, s2[][] = {s1}; + private Object o0, o1[] = {o0}, o2[][] = {o1}; + String S0, S1[] = {S0}, S2[][] = {S1}; + Object O0, O1[] = {O0}, O2[][] = {O1}; + + protected P u0, u1[] = {u0}, u2[][] = {u1}; + public P w0, w1[] = {w0}, w2[][] = {w1}; + private P p0, p1[] = {p0}, p2[][] = {p1}; + P v0, v1[] = {v0}, v2[][] = {v1}; // package private + + protected M h0, h1[] = {h0}, h2[][] = {h1}; + public M k0, k1[] = {k0}, k2[][] = {k1}; + private M m0, m1[] = {m0}, m2[][] = {m1}; + M j0, j1[] = {j0}, j2[][] = {j1}; // package private + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + ispackageprivate001a ispackageprivate001a_ = new ispackageprivate001a(); + + log.display(" debuggee started."); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("debuggee > \"quit\" signal recieved."); + log.display("debuggee > completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("debuggee > unexpected signal (not \"quit\") - " + instruction); + log.complain("debuggee > TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class P {} +interface M {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002.java new file mode 100644 index 00000000000..04583e6c8f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPackagePrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class ispackageprivate002 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isPackagePrivate."; + private final static String debuggerName = prefix + "ispackageprivate002"; + private final static String debuggeeName = debuggerName + "a"; + + private static ReferenceType debuggeeClass; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (Consts.TEST_PASSED) or either 2 (Consts.TEST_FAILED). + */ + public static int run (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + Debugee debuggee = binder.bindToDebugee(debuggeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "debugger > "); + + debuggee.resume(); + display("Waiting debuggee's \"ready\" signal..."); + String line = pipe.readln(); + + if (line == null) { + complain("UNEXPECTED debuggee's signal - null"); + return Consts.TEST_FAILED; + } + if (!line.equals("ready")) { + complain("UNEXPECTED debuggee's signal - " + line); + return Consts.TEST_FAILED; + } else { + display("debuggee's \"ready\" signal recieved."); + } + + int exitStatus = Consts.TEST_PASSED; + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return Consts.TEST_FAILED; + } + + + display("Checking isPackagePrivate() method for debuggee's methods..."); + + display("Total count of methods read from debuggee: " + + debuggeeClass.allFields().size() + ", expected count : " + + checkedMethods.length+1); + + // Check all methods from debuggee + for (int i = 0; i < checkedMethods.length-1; i++) { + List listOfMethods; + int totalMethodsByName; + Method method; + String name; + boolean isPackagePrivate; + String expectedValue; + + try { + listOfMethods = debuggeeClass.methodsByName(checkedMethods[i][0]); + } catch (Exception e) { + complain("Can't get method by name " + checkedMethods[i][0]); + complain("Unexpected Exception: " + e); + exitStatus = Consts.TEST_FAILED; + continue; + } + + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + checkedMethods[i][0] + " is " + totalMethodsByName + + ", should be 1."); + exitStatus = Consts.TEST_FAILED; + continue; + } + method = (Method)listOfMethods.get(0); + + name = method.name(); + isPackagePrivate = ((TypeComponent)method).isPackagePrivate(); // cast to TypeComponent interface + expectedValue = checkedMethods[i][1]; + if ((isPackagePrivate && !expectedValue.equals(IS_PPRIVATE)) || + (!isPackagePrivate && expectedValue.equals(IS_PPRIVATE)) ) { + complain("isPackagePrivate() returned wrong value: " + isPackagePrivate + + " for method " + name + + "; expected value : " + expectedValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("isPackagePrivate() returned expected " + isPackagePrivate + + " for method " + name); + } + } + + display("Checking debuggee's methods completed!"); + display("Waiting for debuggee's finish..."); + pipe.println("quit"); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != Consts.TEST_PASSED + Consts.JCK_STATUS_BASE) { + complain("UNEXPECTED debuggee's exit status (not 95) - " + status); + exitStatus = Consts.TEST_FAILED; + } else { + display("Got expected debuggee's exit status - " + status); + } + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + //--------------------------------------------- test specific fields + + final static String IS_PPRIVATE = "true"; + final static String NOT_PPRIVATE = "false"; + + /** debuggee's methods for check **/ + private final static String checkedMethods[][] = { + {"Mv", IS_PPRIVATE}, + {"Mz", IS_PPRIVATE}, + {"Mz1", IS_PPRIVATE}, + {"Mz2", IS_PPRIVATE}, + {"Mb", IS_PPRIVATE}, + {"Mb1", IS_PPRIVATE}, + {"Mb2", IS_PPRIVATE}, + {"Mc", IS_PPRIVATE}, + {"Mc1", IS_PPRIVATE}, + {"Mc2", IS_PPRIVATE}, + {"Md", IS_PPRIVATE}, + {"Md1", IS_PPRIVATE}, + {"Md2", IS_PPRIVATE}, + {"Mf1", IS_PPRIVATE}, + {"Mf2", IS_PPRIVATE}, + {"Mi", IS_PPRIVATE}, + {"Mi1", IS_PPRIVATE}, + {"Mi2", IS_PPRIVATE}, + {"Ml", IS_PPRIVATE}, + {"Ml1", IS_PPRIVATE}, + {"Ml2", IS_PPRIVATE}, + {"Mr", IS_PPRIVATE}, + {"Mr1", IS_PPRIVATE}, + {"Mr2", IS_PPRIVATE}, + + {"MvM", NOT_PPRIVATE}, + {"MzM", NOT_PPRIVATE}, + {"Mz1M", NOT_PPRIVATE}, + {"Mz2M", NOT_PPRIVATE}, + {"MbM", NOT_PPRIVATE}, + {"Mb1M", NOT_PPRIVATE}, + {"Mb2M", NOT_PPRIVATE}, + {"McM", NOT_PPRIVATE}, + {"Mc1M", NOT_PPRIVATE}, + {"Mc2M", NOT_PPRIVATE}, + {"MdM", NOT_PPRIVATE}, + {"Md1M", NOT_PPRIVATE}, + {"Md2M", NOT_PPRIVATE}, + {"MfM", NOT_PPRIVATE}, + {"Mf1M", NOT_PPRIVATE}, + {"Mf2M", NOT_PPRIVATE}, + {"MiM", NOT_PPRIVATE}, + {"Mi1M", NOT_PPRIVATE}, + {"Mi2M", NOT_PPRIVATE}, + {"MlM", NOT_PPRIVATE}, + {"Ml1M", NOT_PPRIVATE}, + {"Ml2M", NOT_PPRIVATE}, + {"MrM", NOT_PPRIVATE}, + {"Mr1M", NOT_PPRIVATE}, + {"Mr2M", NOT_PPRIVATE}, + + {"MvS", IS_PPRIVATE}, + {"MlS", IS_PPRIVATE}, + {"MlS1", IS_PPRIVATE}, + {"MlS2", IS_PPRIVATE}, + {"MvN", IS_PPRIVATE}, + {"MlN", IS_PPRIVATE}, + {"MlN1", IS_PPRIVATE}, + {"MlN2", IS_PPRIVATE}, + {"MvI", IS_PPRIVATE}, + {"MlI", IS_PPRIVATE}, + {"MlI1", IS_PPRIVATE}, + {"MlI2", IS_PPRIVATE}, + {"MvY", IS_PPRIVATE}, + {"MlY", IS_PPRIVATE}, + {"MlY1", IS_PPRIVATE}, + {"MlY2", IS_PPRIVATE}, + {"MvU", NOT_PPRIVATE}, + {"MlU", NOT_PPRIVATE}, + {"MlU1", NOT_PPRIVATE}, + {"MlU2", NOT_PPRIVATE}, + {"MvR", NOT_PPRIVATE}, + {"MlR", NOT_PPRIVATE}, + {"MlR1", NOT_PPRIVATE}, + {"MlR2", NOT_PPRIVATE}, + {"MvP", NOT_PPRIVATE}, + {"MlP", NOT_PPRIVATE}, + {"MlP1", NOT_PPRIVATE}, + {"MlP2", NOT_PPRIVATE}, + + {"MvSM", NOT_PPRIVATE}, + {"MlSM", NOT_PPRIVATE}, + {"MlS1M", NOT_PPRIVATE}, + {"MlS2M", NOT_PPRIVATE}, + {"MvNM", NOT_PPRIVATE}, + {"MlNM", NOT_PPRIVATE}, + {"MlN1M", NOT_PPRIVATE}, + {"MlN2M", NOT_PPRIVATE}, + {"MvIM", NOT_PPRIVATE}, + {"MlIM", NOT_PPRIVATE}, + {"MlI1M", NOT_PPRIVATE}, + {"MlI2M", NOT_PPRIVATE}, + {"MvYM", NOT_PPRIVATE}, + {"MlYM", NOT_PPRIVATE}, + {"MlY1M", NOT_PPRIVATE}, + {"MlY2M", NOT_PPRIVATE}, + {"MvPM", NOT_PPRIVATE}, + {"MlPM", NOT_PPRIVATE}, + {"MlP1M", NOT_PPRIVATE}, + {"MlP2M", NOT_PPRIVATE}, + + {"MX", IS_PPRIVATE}, + {"MX1", IS_PPRIVATE}, + {"MX2", IS_PPRIVATE}, + {"MO", IS_PPRIVATE}, + {"MO1", IS_PPRIVATE}, + {"MO2", IS_PPRIVATE}, + + {"MXM", NOT_PPRIVATE}, + {"MX1M", NOT_PPRIVATE}, + {"MX2M", NOT_PPRIVATE}, + {"MOM", NOT_PPRIVATE}, + {"MO1M", NOT_PPRIVATE}, + {"MO2M", NOT_PPRIVATE}, + + {"MLS", IS_PPRIVATE}, + {"MLS1", IS_PPRIVATE}, + {"MLS2", IS_PPRIVATE}, + {"MLN", IS_PPRIVATE}, + {"MLN1", IS_PPRIVATE}, + {"MLN2", IS_PPRIVATE}, + {"MLI", IS_PPRIVATE}, + {"MLI1", IS_PPRIVATE}, + {"MLI2", IS_PPRIVATE}, + {"MLY", IS_PPRIVATE}, + {"MLY1", IS_PPRIVATE}, + {"MLY2", IS_PPRIVATE}, + {"MLU", NOT_PPRIVATE}, + {"MLU1", NOT_PPRIVATE}, + {"MLU2", NOT_PPRIVATE}, + {"MLR", NOT_PPRIVATE}, + {"MLR1", NOT_PPRIVATE}, + {"MLR2", NOT_PPRIVATE}, + {"MLP", NOT_PPRIVATE}, + {"MLP1", NOT_PPRIVATE}, + {"MLP2", NOT_PPRIVATE}, + + {"MLSM", NOT_PPRIVATE}, + {"MLS1M", NOT_PPRIVATE}, + {"MLS2M", NOT_PPRIVATE}, + {"MLNM", NOT_PPRIVATE}, + {"MLN1M", NOT_PPRIVATE}, + {"MLN2M", NOT_PPRIVATE}, + {"MLIM", NOT_PPRIVATE}, + {"MLI1M", NOT_PPRIVATE}, + {"MLI2M", NOT_PPRIVATE}, + {"MLYM", NOT_PPRIVATE}, + {"MLY1M", NOT_PPRIVATE}, + {"MLY2M", NOT_PPRIVATE}, + {"MLPM", NOT_PPRIVATE}, + {"MLP1M", NOT_PPRIVATE}, + {"MLP2M", NOT_PPRIVATE}, + + {"ME", IS_PPRIVATE}, + {"ME1", IS_PPRIVATE}, + {"ME2", IS_PPRIVATE}, + {"MEM", NOT_PPRIVATE}, + {"ME1M", NOT_PPRIVATE}, + {"ME2M", NOT_PPRIVATE}, + + {"MES", IS_PPRIVATE}, + {"MES1", IS_PPRIVATE}, + {"MES2", IS_PPRIVATE}, + {"MEN", IS_PPRIVATE}, + {"MEN1", IS_PPRIVATE}, + {"MEN2", IS_PPRIVATE}, + {"MEI", IS_PPRIVATE}, + {"MEI1", IS_PPRIVATE}, + {"MEI2", IS_PPRIVATE}, + {"MEY", IS_PPRIVATE}, + {"MEY1", IS_PPRIVATE}, + {"MEY2", IS_PPRIVATE}, + {"MEU", NOT_PPRIVATE}, + {"MEU1", NOT_PPRIVATE}, + {"MEU2", NOT_PPRIVATE}, + {"MER", NOT_PPRIVATE}, + {"MER1", NOT_PPRIVATE}, + {"MER2", NOT_PPRIVATE}, + {"MEP", NOT_PPRIVATE}, + {"MEP1", NOT_PPRIVATE}, + {"MEP2", NOT_PPRIVATE}, + + {"MESM", NOT_PPRIVATE}, + {"MES1M", NOT_PPRIVATE}, + {"MES2M", NOT_PPRIVATE}, + {"MENM", NOT_PPRIVATE}, + {"MEN1M", NOT_PPRIVATE}, + {"MEN2M", NOT_PPRIVATE}, + {"MEIM", NOT_PPRIVATE}, + {"MEI1M", NOT_PPRIVATE}, + {"MEI2M", NOT_PPRIVATE}, + {"MEYM", NOT_PPRIVATE}, + {"MEY1M", NOT_PPRIVATE}, + {"MEY2M", NOT_PPRIVATE}, + {"MEPM", NOT_PPRIVATE}, + {"MEP1M", NOT_PPRIVATE}, + {"MEP2M", NOT_PPRIVATE} + }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002/TestDescription.java new file mode 100644 index 00000000000..cbcb4d4dc58 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isPackagePrivate() method of Accessible interface + * for TypeComponent sub-interface of com.sun.jdi package. + * The method spec: + * public boolean isPackagePrivate() + * Determines if this object mirrors a package private item. A package + * private item is declared with no access specifier. For ArrayType, the return + * value depends on the array component type. For primitive arrays the return + * value is always false. For object arrays, the return value is the same + * as would be returned for the component type. For primitive classes, such + * as Integer.TYPE, the return value is always false. + * Returns: + * true for items with package private access; false otherwise. + * nsk/jdi/TypeComponent/isPackagePrivate/isprivate002 checks assertions: + * public boolean isPackagePrivate() + * 1. Returns true if the method was declared package private. + * 2. Returns false otherwise. + * Debugger gets each method from debuggee calling by name and then checks + * if method isPackagePrivate() returns an expected value. + * COMMENTS + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for isPackagePrivate method. + * The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isPackagePrivate.ispackageprivate002 + * nsk.jdi.TypeComponent.isPackagePrivate.ispackageprivate002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isPackagePrivate.ispackageprivate002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002a.java new file mode 100644 index 00000000000..eb04b5ad552 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPackagePrivate/ispackageprivate002a.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPackagePrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class ispackageprivate002a { + + //--------------------------------------------- test mutable methods + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + ispackageprivate002a ispackageprivate002a_ = new ispackageprivate002a(); + + log.display(" debuggee started."); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("debuggee > \"quit\" signal recieved."); + log.display("debuggee > completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("debuggee > unexpected signal (not \"quit\") - " + instruction); + log.complain("debuggee > TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------- test specific methods + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + public void MvM() {}; + public boolean MzM(boolean z) { return z; }; + public boolean[] Mz1M(boolean z[]) { return z; }; + public boolean[][] Mz2M(boolean z[][]) { return z; }; + public byte MbM(byte b) { return b; }; + public byte[] Mb1M(byte b[]) { return b; }; + public byte[][] Mb2M(byte b[][]) { return b; }; + public char McM(char c) { return c; }; + public char[] Mc1M(char c[]) { return c; }; + public char[][] Mc2M(char c[][]) { return c; }; + public double MdM(double d) { return d; }; + public double[] Md1M(double d[]) { return d; }; + public double[][] Md2M(double d[][]) { return d; }; + public float MfM(float f) { return f; }; + public float[] Mf1M(float f[]) { return f; }; + public float[][] Mf2M(float f[][]) { return f; }; + public int MiM(int i) { return i; }; + public int[] Mi1M(int i[]) { return i; }; + public int[][] Mi2M(int i[][]) { return i; }; + public long MlM(long l) { return l; }; + public long[] Ml1M(long l[]) { return l; }; + public long[][] Ml2M(long l[][]) { return l; }; + public short MrM(short r) { return r; }; + public short[] Mr1M(short r[]) { return r; }; + public short[][] Mr2M(short r[][]) { return r; }; + + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + public static void MvSM() {}; + public static long MlSM(long l) { return l; }; + public static long[] MlS1M(long l[]) { return l; }; + public static long[][] MlS2M(long l[][]) { return l; }; + public native void MvNM(); + public native long MlNM(long l); + public native long[] MlN1M(long l[]); + public native long[][] MlN2M(long l[][]); + public strictfp void MvIM() {}; + public strictfp long MlIM(long l) { return l; }; + public strictfp long[] MlI1M(long l[]) { return l; }; + public strictfp long[][] MlI2M(long l[][]) { return l; }; + public synchronized void MvYM() {}; + public synchronized long MlYM(long l) { return l; }; + public synchronized long[] MlY1M(long l[]) { return l; }; + public synchronized long[][] MlY2M(long l[][]) { return l; }; + public final void MvPM() {}; + public final long MlPM(long l) { return l; }; + public final long[] MlP1M(long l[]) { return l; }; + public final long[][] MlP2M(long l[][]) { return l; }; + + C002 MX(C002 X) { return X; }; + C002[] MX1(C002 X[]) { return X; }; + C002[][] MX2(C002 X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + public C002 MXM(C002 X) { return X; }; + public C002[] MX1M(C002 X[]) { return X; }; + public C002[][] MX2M(C002 X[][]) { return X; }; + public Object MOM(Object O) { return O; }; + public Object[] MO1M(Object[] O) { return O; }; + public Object[][] MO2M(Object[][] O) { return O; }; + + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long[] L) { return L; }; + static Long[][] MLS2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + public static Long MLSM(Long L) { return L; }; + public static Long[] MLS1M(Long[] L) { return L; }; + public static Long[][] MLS2M(Long[][] L) { return L; }; + public native Long MLNM(Long L); + public native Long[] MLN1M(Long[] L); + public native Long[][] MLN2M(Long[][] L); + public strictfp Long MLIM(Long L) { return L; }; + public strictfp Long[] MLI1M(Long[] L) { return L; }; + public strictfp Long[][] MLI2M(Long[][] L) { return L; }; + public synchronized Long MLYM(Long L) { return L; }; + public synchronized Long[] MLY1M(Long[] L) { return L; }; + public synchronized Long[][] MLY2M(Long[][] L) { return L; }; + public final Long MLPM(Long L) { return L; }; + public final Long[] MLP1M(Long[] L) { return L; }; + public final Long[][] MLP2M(Long[][] L) { return L; }; + + I002 ME(I002 E) { return E; }; + I002[] ME1(I002[] E) { return E; }; + I002[][] ME2(I002[][] E) { return E; }; + public I002 MEM(I002 E) { return E; }; + public I002[] ME1M(I002[] E) { return E; }; + public I002[][] ME2M(I002[][] E) { return E; }; + + static I002 MES(I002 E) { return E; }; + static I002[] MES1(I002[] E) { return E; }; + static I002[][] MES2(I002[][] E) { return E; }; + native I002 MEN(I002 E); + native I002[] MEN1(I002[] E); + native I002[][] MEN2(I002[][] E); + strictfp I002 MEI(I002 E) { return E; }; + strictfp I002[] MEI1(I002[] E) { return E; }; + strictfp I002[][] MEI2(I002[][] E) { return E; }; + synchronized I002 MEY(I002 E) { return E; }; + synchronized I002[] MEY1(I002[] E) { return E; }; + synchronized I002[][] MEY2(I002[][] E) { return E; }; + public I002 MEU(I002 E) { return E; }; + public I002[] MEU1(I002[] E) { return E; }; + public I002[][] MEU2(I002[][] E) { return E; }; + protected I002 MER(I002 E) { return E; }; + protected I002[] MER1(I002[] E) { return E; }; + protected I002[][] MER2(I002[][] E) { return E; }; + private I002 MEP(I002 E) { return E; }; + private I002[] MEP1(I002[] E) { return E; }; + private I002[][] MEP2(I002[][] E) { return E; }; + + public static I002 MESM(I002 E) { return E; }; + public static I002[] MES1M(I002[] E) { return E; }; + public static I002[][] MES2M(I002[][] E) { return E; }; + public native I002 MENM(I002 E); + public native I002[] MEN1M(I002[] E); + public native I002[][] MEN2M(I002[][] E); + public strictfp I002 MEIM(I002 E) { return E; }; + public strictfp I002[] MEI1M(I002[] E) { return E; }; + public strictfp I002[][] MEI2M(I002[][] E) { return E; }; + public synchronized I002 MEYM(I002 E) { return E; }; + public synchronized I002[] MEY1M(I002[] E) { return E; }; + public synchronized I002[][] MEY2M(I002[][] E) { return E; }; + public final I002 MEPM(I002 E) { return E; }; + public final I002[] MEP1M(I002[] E) { return E; }; + public final I002[][] MEP2M(I002[][] E) { return E; }; + +} + +//--------------------------------------------- test specific methods +class C002 {} +interface I002 {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001.java new file mode 100644 index 00000000000..bab410e1145 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class isprivate001 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isPrivate."; + private final static String debuggerName = prefix + "isprivate001"; + private final static String debuggeeName = debuggerName + "a"; + + private static ReferenceType debuggeeClass; + + final static String IS_PRIVATE = "true"; + final static String NOT_PRIVATE = "false"; + final static int TOTAL_FIELDS = 132; + + /** debuggee's fields for check **/ + private final static String checkedFields[][] = { + {"z0", NOT_PRIVATE}, {"z1", NOT_PRIVATE}, {"z2", NOT_PRIVATE}, + {"b0", NOT_PRIVATE}, {"b1", NOT_PRIVATE}, {"b2", NOT_PRIVATE}, + {"c0", NOT_PRIVATE}, {"c1", NOT_PRIVATE}, {"c2", NOT_PRIVATE}, + {"d0", NOT_PRIVATE}, {"d1", NOT_PRIVATE}, {"d2", NOT_PRIVATE}, + {"f0", NOT_PRIVATE}, {"f1", NOT_PRIVATE}, {"f2", NOT_PRIVATE}, + {"i0", NOT_PRIVATE}, {"i1", NOT_PRIVATE}, {"i2", NOT_PRIVATE}, + {"l0", NOT_PRIVATE}, {"l1", NOT_PRIVATE}, {"l2", NOT_PRIVATE}, + {"r0", NOT_PRIVATE}, {"r1", NOT_PRIVATE}, {"r2", NOT_PRIVATE}, + + {"zP0", IS_PRIVATE}, {"zP1", IS_PRIVATE}, {"zP2", IS_PRIVATE}, + {"bP0", IS_PRIVATE}, {"bP1", IS_PRIVATE}, {"bP2", IS_PRIVATE}, + {"cP0", IS_PRIVATE}, {"cP1", IS_PRIVATE}, {"cP2", IS_PRIVATE}, + {"dP0", IS_PRIVATE}, {"dP1", IS_PRIVATE}, {"dP2", IS_PRIVATE}, + {"fP0", IS_PRIVATE}, {"fP1", IS_PRIVATE}, {"fP2", IS_PRIVATE}, + {"iP0", IS_PRIVATE}, {"iP1", IS_PRIVATE}, {"iP2", IS_PRIVATE}, + {"lP0", IS_PRIVATE}, {"lP1", IS_PRIVATE}, {"lP2", IS_PRIVATE}, + {"rP0", IS_PRIVATE}, {"rP1", IS_PRIVATE}, {"rP2", IS_PRIVATE}, + + {"Z0", NOT_PRIVATE}, {"Z1", NOT_PRIVATE}, {"Z2", NOT_PRIVATE}, + {"B0", NOT_PRIVATE}, {"B1", NOT_PRIVATE}, {"B2", NOT_PRIVATE}, + {"C0", NOT_PRIVATE}, {"C1", NOT_PRIVATE}, {"C2", NOT_PRIVATE}, + {"D0", NOT_PRIVATE}, {"D1", NOT_PRIVATE}, {"D2", NOT_PRIVATE}, + {"F0", NOT_PRIVATE}, {"F1", NOT_PRIVATE}, {"F2", NOT_PRIVATE}, + {"I0", NOT_PRIVATE}, {"I1", NOT_PRIVATE}, {"I2", NOT_PRIVATE}, + {"L0", NOT_PRIVATE}, {"L1", NOT_PRIVATE}, {"L2", NOT_PRIVATE}, + {"R0", NOT_PRIVATE}, {"R1", NOT_PRIVATE}, {"R2", NOT_PRIVATE}, + + {"ZP0", IS_PRIVATE}, {"ZP1", IS_PRIVATE}, {"ZP2", IS_PRIVATE}, + {"BP0", IS_PRIVATE}, {"BP1", IS_PRIVATE}, {"BP2", IS_PRIVATE}, + {"CP0", IS_PRIVATE}, {"CP1", IS_PRIVATE}, {"CP2", IS_PRIVATE}, + {"DP0", IS_PRIVATE}, {"DP1", IS_PRIVATE}, {"DP2", IS_PRIVATE}, + {"FP0", IS_PRIVATE}, {"FP1", IS_PRIVATE}, {"FP2", IS_PRIVATE}, + {"IP0", IS_PRIVATE}, {"IP1", IS_PRIVATE}, {"IP2", IS_PRIVATE}, + {"LP0", IS_PRIVATE}, {"LP1", IS_PRIVATE}, {"LP2", IS_PRIVATE}, + {"RP0", IS_PRIVATE}, {"RP1", IS_PRIVATE}, {"RP2", IS_PRIVATE}, + + {"s0", NOT_PRIVATE}, {"s1", NOT_PRIVATE}, {"s2", NOT_PRIVATE}, + {"o0", NOT_PRIVATE}, {"o1", NOT_PRIVATE}, {"o2", NOT_PRIVATE}, + {"S0", IS_PRIVATE}, {"S1", IS_PRIVATE}, {"S2", IS_PRIVATE}, + {"O0", IS_PRIVATE}, {"O1", IS_PRIVATE}, {"O2", IS_PRIVATE}, + + {"u0", NOT_PRIVATE}, {"u1", NOT_PRIVATE}, {"u2", NOT_PRIVATE}, + {"v0", IS_PRIVATE}, {"v1", IS_PRIVATE}, {"v2", IS_PRIVATE}, + {"w0", NOT_PRIVATE}, {"w1", NOT_PRIVATE}, {"w2", NOT_PRIVATE}, + {"p0", NOT_PRIVATE}, {"p1", NOT_PRIVATE}, {"p2", NOT_PRIVATE}, + + {"h0", NOT_PRIVATE}, {"h1", NOT_PRIVATE}, {"h2", NOT_PRIVATE}, + {"j0", IS_PRIVATE}, {"j1", IS_PRIVATE}, {"j2", IS_PRIVATE}, + {"k0", NOT_PRIVATE}, {"k1", NOT_PRIVATE}, {"k2", NOT_PRIVATE}, + {"m0", NOT_PRIVATE}, {"m1", NOT_PRIVATE}, {"m2", NOT_PRIVATE} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (Consts.TEST_PASSED) or either 2 (Consts.TEST_FAILED). + */ + public static int run (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + Debugee debuggee = binder.bindToDebugee(debuggeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "debugger > "); + + debuggee.resume(); + display("Waiting debuggee's \"ready\" signal..."); + String line = pipe.readln(); + + if (line == null) { + complain("UNEXPECTED debuggee's signal - null"); + return Consts.TEST_FAILED; + } + if (!line.equals("ready")) { + complain("UNEXPECTED debuggee's signal - " + line); + return Consts.TEST_FAILED; + } else { + display("debuggee's \"ready\" signal recieved."); + } + + int exitStatus = Consts.TEST_PASSED; + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return Consts.TEST_FAILED; + } + + + display("Checking isPrivate() method for debuggee's fields..."); + + display("Total count of fields read from debuggee: " + + debuggeeClass.allFields().size() + ", expected count : " + + TOTAL_FIELDS); + + // Check all fields from debuggee + for (int i = 0; i < TOTAL_FIELDS; i++) { + Field field; + String name; + boolean isPrivate; + String expectedValue; + + try { + field = debuggeeClass.fieldByName(checkedFields[i][0]); + } catch (Exception e) { + complain("Can't get field by name " + checkedFields[i][0]); + complain("Unexpected Exception: " + e); + exitStatus = Consts.TEST_FAILED; + continue; + } + + name = field.name(); + isPrivate = ((TypeComponent)field).isPrivate(); // cast to TypeComponent interface + expectedValue = checkedFields[i][1]; + if ((isPrivate && !expectedValue.equals(IS_PRIVATE)) || + (!isPrivate && expectedValue.equals(IS_PRIVATE)) ) { + complain("isPrivate() returned wrong value: " + isPrivate + + " for field " + name + + "; expected value : " + expectedValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("isPrivate() returned expected " + isPrivate + + " for field " + name); + } + } + + display("Checking debuggee's fields completed!"); + display("Waiting for debuggee's finish..."); + pipe.println("quit"); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != Consts.TEST_PASSED + Consts.JCK_STATUS_BASE) { + complain("UNEXPECTED debuggee's exit status (not 95) - " + status); + exitStatus = Consts.TEST_FAILED; + } else { + display("Got expected debuggee's exit status - " + status); + } + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001/TestDescription.java new file mode 100644 index 00000000000..48276967462 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isPrivate/isprivate001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isPrivate() method of Accessible interface + * for TypeComponent sub-interface of com.sun.jdi package. + * The method spec: + * public boolean isPrivate() + * Determines if this object mirrors a private item. For ArrayType, + * the return value depends on the array component type. For primitive + * arrays the return value is always false. For object arrays, the + * return value is the same as would be returned for the component type. + * For primitive classes, such as Integer.TYPE, the return value is + * always false. + * Returns: + * true for items with private access; false otherwise. + * nsk/jdi/TypeComponent/isPrivate/isprivate001 checks assertions: + * public boolean isPrivate() + * 1. Returns true if the field was declared private. + * 2. Returns false otherwise. + * Debugger gets each field from debuggee calling by name and then checks + * if method isPrivate() returns an expected value. + * COMMENTS + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for isPrivate method. + * The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isPrivate.isprivate001 + * nsk.jdi.TypeComponent.isPrivate.isprivate001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isPrivate.isprivate001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001a.java new file mode 100644 index 00000000000..7c537c07314 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate001a.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isprivate001a { + + boolean z0, z1[] = {z0}, z2[][] = {z1}; + byte b0, b1[] = {b0}, b2[][] = {b1}; + char c0, c1[] = {c0}, c2[][] = {c1}; + double d0, d1[] = {d0}, d2[][] = {d1}; + float f0, f1[] = {f0}, f2[][] = {f1}; + int i0, i1[] = {i0}, i2[][] = {i1}; + long l0, l1[] = {l0}, l2[][] = {l1}; + short r0, r1[] = {r0}, r2[][] = {r1}; + + private boolean zP0, zP1[] = {zP0}, zP2[][] = {zP1}; + private byte bP0, bP1[] = {bP0}, bP2[][] = {bP1}; + private char cP0, cP1[] = {cP0}, cP2[][] = {cP1}; + private double dP0, dP1[] = {dP0}, dP2[][] = {dP1}; + private float fP0, fP1[] = {fP0}, fP2[][] = {fP1}; + private int iP0, iP1[] = {iP0}, iP2[][] = {iP1}; + private long lP0, lP1[] = {lP0}, lP2[][] = {lP1}; + private short rP0, rP1[] = {rP0}, rP2[][] = {rP1}; + + Boolean Z0, Z1[] = {Z0}, Z2[][] = {Z1}; + Byte B0, B1[] = {B0}, B2[][] = {B1}; + Character C0, C1[] = {C0}, C2[][] = {C1}; + Double D0, D1[] = {D0}, D2[][] = {D1}; + Float F0, F1[] = {F0}, F2[][] = {F1}; + Integer I0, I1[] = {I0}, I2[][] = {I1}; + Long L0, L1[] = {L0}, L2[][] = {L1}; + Short R0, R1[] = {R0}, R2[][] = {R1}; + + private Boolean ZP0, ZP1[] = {ZP0}, ZP2[][] = {ZP1}; + private Byte BP0, BP1[] = {BP0}, BP2[][] = {BP1}; + private Character CP0, CP1[] = {CP0}, CP2[][] = {CP1}; + private Double DP0, DP1[] = {DP0}, DP2[][] = {DP1}; + private Float FP0, FP1[] = {FP0}, FP2[][] = {FP1}; + private Integer IP0, IP1[] = {IP0}, IP2[][] = {IP1}; + private Long LP0, LP1[] = {LP0}, LP2[][] = {LP1}; + private Short RP0, RP1[] = {RP0}, RP2[][] = {RP1}; + + String s0, s1[] = {s0}, s2[][] = {s1}; + Object o0, o1[] = {o0}, o2[][] = {o1}; + private String S0, S1[] = {S0}, S2[][] = {S1}; + private Object O0, O1[] = {O0}, O2[][] = {O1}; + + protected P u0, u1[] = {u0}, u2[][] = {u1}; + private P v0, v1[] = {v0}, v2[][] = {v1}; + public P w0, w1[] = {w0}, w2[][] = {w1}; + P p0, p1[] = {p0}, p2[][] = {p1}; // package private + + protected M h0, h1[] = {h0}, h2[][] = {h1}; + private M j0, j1[] = {j0}, j2[][] = {j1}; + public M k0, k1[] = {k0}, k2[][] = {k1}; + M m0, m1[] = {m0}, m2[][] = {m1}; // package private + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + isprivate001a isprivate001a_ = new isprivate001a(); + + log.display(" debuggee started."); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("debuggee > \"quit\" signal recieved."); + log.display("debuggee > completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("debuggee > unexpected signal (not \"quit\") - " + instruction); + log.complain("debuggee > TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class P {} +interface M {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002.java new file mode 100644 index 00000000000..3abff8e1a7c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class isprivate002 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isPrivate."; + private final static String debuggerName = prefix + "isprivate002"; + private final static String debuggeeName = debuggerName + "a"; + + private static ReferenceType debuggeeClass; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (Consts.TEST_PASSED) or either 2 (Consts.TEST_FAILED). + */ + public static int run (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + Debugee debuggee = binder.bindToDebugee(debuggeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "debugger > "); + + debuggee.resume(); + display("Waiting debuggee's \"ready\" signal..."); + String line = pipe.readln(); + + if (line == null) { + complain("UNEXPECTED debuggee's signal - null"); + return Consts.TEST_FAILED; + } + if (!line.equals("ready")) { + complain("UNEXPECTED debuggee's signal - " + line); + return Consts.TEST_FAILED; + } else { + display("debuggee's \"ready\" signal recieved."); + } + + int exitStatus = Consts.TEST_PASSED; + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return Consts.TEST_FAILED; + } + + + display("Checking isPrivate() method for debuggee's methods..."); + + display("Total count of methods read from debuggee: " + + debuggeeClass.allFields().size() + ", expected count : " + + checkedMethods.length+1); + + // Check all methods from debuggee + for (int i = 0; i < checkedMethods.length-1; i++) { + List listOfMethods; + int totalMethodsByName; + Method method; + String name; + boolean isPrivate; + String expectedValue; + + try { + listOfMethods = debuggeeClass.methodsByName(checkedMethods[i][0]); + } catch (Exception e) { + complain("Can't get method by name " + checkedMethods[i][0]); + complain("Unexpected Exception: " + e); + exitStatus = Consts.TEST_FAILED; + continue; + } + + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + checkedMethods[i][0] + " is " + totalMethodsByName + + ", should be 1."); + exitStatus = Consts.TEST_FAILED; + continue; + } + method = (Method)listOfMethods.get(0); + + name = method.name(); + isPrivate = ((TypeComponent)method).isPrivate(); // cast to TypeComponent interface + expectedValue = checkedMethods[i][1]; + if ((isPrivate && !expectedValue.equals(IS_PRIVATE)) || + (!isPrivate && expectedValue.equals(IS_PRIVATE)) ) { + complain("isPrivate() returned wrong value: " + isPrivate + + " for method " + name + + "; expected value : " + expectedValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("isPrivate() returned expected " + isPrivate + + " for method " + name); + } + } + + display("Checking debuggee's methods completed!"); + display("Waiting for debuggee's finish..."); + pipe.println("quit"); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != Consts.TEST_PASSED + Consts.JCK_STATUS_BASE) { + complain("UNEXPECTED debuggee's exit status (not 95) - " + status); + exitStatus = Consts.TEST_FAILED; + } else { + display("Got expected debuggee's exit status - " + status); + } + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + //--------------------------------------------- test specific fields + + final static String IS_PRIVATE = "true"; + final static String NOT_PRIVATE = "false"; + + /** debuggee's methods for check **/ + private final static String checkedMethods[][] = { + {"Mv", NOT_PRIVATE}, + {"Mz", NOT_PRIVATE}, + {"Mz1", NOT_PRIVATE}, + {"Mz2", NOT_PRIVATE}, + {"Mb", NOT_PRIVATE}, + {"Mb1", NOT_PRIVATE}, + {"Mb2", NOT_PRIVATE}, + {"Mc", NOT_PRIVATE}, + {"Mc1", NOT_PRIVATE}, + {"Mc2", NOT_PRIVATE}, + {"Md", NOT_PRIVATE}, + {"Md1", NOT_PRIVATE}, + {"Md2", NOT_PRIVATE}, + {"Mf1", NOT_PRIVATE}, + {"Mf2", NOT_PRIVATE}, + {"Mi", NOT_PRIVATE}, + {"Mi1", NOT_PRIVATE}, + {"Mi2", NOT_PRIVATE}, + {"Ml", NOT_PRIVATE}, + {"Ml1", NOT_PRIVATE}, + {"Ml2", NOT_PRIVATE}, + {"Mr", NOT_PRIVATE}, + {"Mr1", NOT_PRIVATE}, + {"Mr2", NOT_PRIVATE}, + + {"MvM", IS_PRIVATE}, + {"MzM", IS_PRIVATE}, + {"Mz1M", IS_PRIVATE}, + {"Mz2M", IS_PRIVATE}, + {"MbM", IS_PRIVATE}, + {"Mb1M", IS_PRIVATE}, + {"Mb2M", IS_PRIVATE}, + {"McM", IS_PRIVATE}, + {"Mc1M", IS_PRIVATE}, + {"Mc2M", IS_PRIVATE}, + {"MdM", IS_PRIVATE}, + {"Md1M", IS_PRIVATE}, + {"Md2M", IS_PRIVATE}, + {"MfM", IS_PRIVATE}, + {"Mf1M", IS_PRIVATE}, + {"Mf2M", IS_PRIVATE}, + {"MiM", IS_PRIVATE}, + {"Mi1M", IS_PRIVATE}, + {"Mi2M", IS_PRIVATE}, + {"MlM", IS_PRIVATE}, + {"Ml1M", IS_PRIVATE}, + {"Ml2M", IS_PRIVATE}, + {"MrM", IS_PRIVATE}, + {"Mr1M", IS_PRIVATE}, + {"Mr2M", IS_PRIVATE}, + + {"MvS", NOT_PRIVATE}, + {"MlS", NOT_PRIVATE}, + {"MlS1", NOT_PRIVATE}, + {"MlS2", NOT_PRIVATE}, + {"MvN", NOT_PRIVATE}, + {"MlN", NOT_PRIVATE}, + {"MlN1", NOT_PRIVATE}, + {"MlN2", NOT_PRIVATE}, + {"MvI", NOT_PRIVATE}, + {"MlI", NOT_PRIVATE}, + {"MlI1", NOT_PRIVATE}, + {"MlI2", NOT_PRIVATE}, + {"MvY", NOT_PRIVATE}, + {"MlY", NOT_PRIVATE}, + {"MlY1", NOT_PRIVATE}, + {"MlY2", NOT_PRIVATE}, + {"MvU", NOT_PRIVATE}, + {"MlU", NOT_PRIVATE}, + {"MlU1", NOT_PRIVATE}, + {"MlU2", NOT_PRIVATE}, + {"MvR", NOT_PRIVATE}, + {"MlR", NOT_PRIVATE}, + {"MlR1", NOT_PRIVATE}, + {"MlR2", NOT_PRIVATE}, + {"MvP", IS_PRIVATE}, + {"MlP", IS_PRIVATE}, + {"MlP1", IS_PRIVATE}, + {"MlP2", IS_PRIVATE}, + + {"MvSM", IS_PRIVATE}, + {"MlSM", IS_PRIVATE}, + {"MlS1M", IS_PRIVATE}, + {"MlS2M", IS_PRIVATE}, + {"MvNM", IS_PRIVATE}, + {"MlNM", IS_PRIVATE}, + {"MlN1M", IS_PRIVATE}, + {"MlN2M", IS_PRIVATE}, + {"MvIM", IS_PRIVATE}, + {"MlIM", IS_PRIVATE}, + {"MlI1M", IS_PRIVATE}, + {"MlI2M", IS_PRIVATE}, + {"MvYM", IS_PRIVATE}, + {"MlYM", IS_PRIVATE}, + {"MlY1M", IS_PRIVATE}, + {"MlY2M", IS_PRIVATE}, + {"MvPM", IS_PRIVATE}, + {"MlPM", IS_PRIVATE}, + {"MlP1M", IS_PRIVATE}, + {"MlP2M", IS_PRIVATE}, + + {"MX", NOT_PRIVATE}, + {"MX1", NOT_PRIVATE}, + {"MX2", NOT_PRIVATE}, + {"MO", NOT_PRIVATE}, + {"MO1", NOT_PRIVATE}, + {"MO2", NOT_PRIVATE}, + + {"MXM", IS_PRIVATE}, + {"MX1M", IS_PRIVATE}, + {"MX2M", IS_PRIVATE}, + {"MOM", IS_PRIVATE}, + {"MO1M", IS_PRIVATE}, + {"MO2M", IS_PRIVATE}, + + {"MLS", NOT_PRIVATE}, + {"MLS1", NOT_PRIVATE}, + {"MLS2", NOT_PRIVATE}, + {"MLN", NOT_PRIVATE}, + {"MLN1", NOT_PRIVATE}, + {"MLN2", NOT_PRIVATE}, + {"MLI", NOT_PRIVATE}, + {"MLI1", NOT_PRIVATE}, + {"MLI2", NOT_PRIVATE}, + {"MLY", NOT_PRIVATE}, + {"MLY1", NOT_PRIVATE}, + {"MLY2", NOT_PRIVATE}, + {"MLU", NOT_PRIVATE}, + {"MLU1", NOT_PRIVATE}, + {"MLU2", NOT_PRIVATE}, + {"MLR", NOT_PRIVATE}, + {"MLR1", NOT_PRIVATE}, + {"MLR2", NOT_PRIVATE}, + {"MLP", IS_PRIVATE}, + {"MLP1", IS_PRIVATE}, + {"MLP2", IS_PRIVATE}, + + {"MLSM", IS_PRIVATE}, + {"MLS1M", IS_PRIVATE}, + {"MLS2M", IS_PRIVATE}, + {"MLNM", IS_PRIVATE}, + {"MLN1M", IS_PRIVATE}, + {"MLN2M", IS_PRIVATE}, + {"MLIM", IS_PRIVATE}, + {"MLI1M", IS_PRIVATE}, + {"MLI2M", IS_PRIVATE}, + {"MLYM", IS_PRIVATE}, + {"MLY1M", IS_PRIVATE}, + {"MLY2M", IS_PRIVATE}, + {"MLPM", IS_PRIVATE}, + {"MLP1M", IS_PRIVATE}, + {"MLP2M", IS_PRIVATE}, + + {"ME", NOT_PRIVATE}, + {"ME1", NOT_PRIVATE}, + {"ME2", NOT_PRIVATE}, + {"MEM", IS_PRIVATE}, + {"ME1M", IS_PRIVATE}, + {"ME2M", IS_PRIVATE}, + + {"MES", NOT_PRIVATE}, + {"MES1", NOT_PRIVATE}, + {"MES2", NOT_PRIVATE}, + {"MEN", NOT_PRIVATE}, + {"MEN1", NOT_PRIVATE}, + {"MEN2", NOT_PRIVATE}, + {"MEI", NOT_PRIVATE}, + {"MEI1", NOT_PRIVATE}, + {"MEI2", NOT_PRIVATE}, + {"MEY", NOT_PRIVATE}, + {"MEY1", NOT_PRIVATE}, + {"MEY2", NOT_PRIVATE}, + {"MEU", NOT_PRIVATE}, + {"MEU1", NOT_PRIVATE}, + {"MEU2", NOT_PRIVATE}, + {"MER", NOT_PRIVATE}, + {"MER1", NOT_PRIVATE}, + {"MER2", NOT_PRIVATE}, + {"MEP", IS_PRIVATE}, + {"MEP1", IS_PRIVATE}, + {"MEP2", IS_PRIVATE}, + + {"MESM", IS_PRIVATE}, + {"MES1M", IS_PRIVATE}, + {"MES2M", IS_PRIVATE}, + {"MENM", IS_PRIVATE}, + {"MEN1M", IS_PRIVATE}, + {"MEN2M", IS_PRIVATE}, + {"MEIM", IS_PRIVATE}, + {"MEI1M", IS_PRIVATE}, + {"MEI2M", IS_PRIVATE}, + {"MEYM", IS_PRIVATE}, + {"MEY1M", IS_PRIVATE}, + {"MEY2M", IS_PRIVATE}, + {"MEPM", IS_PRIVATE}, + {"MEP1M", IS_PRIVATE}, + {"MEP2M", IS_PRIVATE} + }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002/TestDescription.java new file mode 100644 index 00000000000..c1b21a21716 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isPrivate/isprivate002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isPrivate() method of Accessible interface + * for TypeComponent sub-interface of com.sun.jdi package. + * The method spec: + * public boolean isPrivate() + * Determines if this object mirrors a private item. For ArrayType, + * the return value depends on the array component type. For primitive + * arrays the return value is always false. For object arrays, the + * return value is the same as would be returned for the component type. + * For primitive classes, such as Integer.TYPE, the return value is + * always false. + * Returns: + * true for items with private access; false otherwise. + * nsk/jdi/TypeComponent/isPrivate/isprivate002 checks assertions: + * public boolean isPrivate() + * 1. Returns true if the method was declared private. + * 2. Returns false otherwise. + * Debugger gets each field from debuggee calling by name and then checks + * if method isPrivate() returns an expected value. + * COMMENTS + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for isPrivate method. + * The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isPrivate.isprivate002 + * nsk.jdi.TypeComponent.isPrivate.isprivate002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isPrivate.isprivate002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002a.java new file mode 100644 index 00000000000..627c4658f30 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPrivate/isprivate002a.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPrivate; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isprivate002a { + + //--------------------------------------------- test mutable methods + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + isprivate002a isprivate002a_ = new isprivate002a(); + + log.display(" debuggee started."); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("debuggee > \"quit\" signal recieved."); + log.display("debuggee > completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("debuggee > unexpected signal (not \"quit\") - " + instruction); + log.complain("debuggee > TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------- test specific methods + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + private void MvM() {}; + private boolean MzM(boolean z) { return z; }; + private boolean[] Mz1M(boolean z[]) { return z; }; + private boolean[][] Mz2M(boolean z[][]) { return z; }; + private byte MbM(byte b) { return b; }; + private byte[] Mb1M(byte b[]) { return b; }; + private byte[][] Mb2M(byte b[][]) { return b; }; + private char McM(char c) { return c; }; + private char[] Mc1M(char c[]) { return c; }; + private char[][] Mc2M(char c[][]) { return c; }; + private double MdM(double d) { return d; }; + private double[] Md1M(double d[]) { return d; }; + private double[][] Md2M(double d[][]) { return d; }; + private float MfM(float f) { return f; }; + private float[] Mf1M(float f[]) { return f; }; + private float[][] Mf2M(float f[][]) { return f; }; + private int MiM(int i) { return i; }; + private int[] Mi1M(int i[]) { return i; }; + private int[][] Mi2M(int i[][]) { return i; }; + private long MlM(long l) { return l; }; + private long[] Ml1M(long l[]) { return l; }; + private long[][] Ml2M(long l[][]) { return l; }; + private short MrM(short r) { return r; }; + private short[] Mr1M(short r[]) { return r; }; + private short[][] Mr2M(short r[][]) { return r; }; + + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + private static void MvSM() {}; + private static long MlSM(long l) { return l; }; + private static long[] MlS1M(long l[]) { return l; }; + private static long[][] MlS2M(long l[][]) { return l; }; + private native void MvNM(); + private native long MlNM(long l); + private native long[] MlN1M(long l[]); + private native long[][] MlN2M(long l[][]); + private strictfp void MvIM() {}; + private strictfp long MlIM(long l) { return l; }; + private strictfp long[] MlI1M(long l[]) { return l; }; + private strictfp long[][] MlI2M(long l[][]) { return l; }; + private synchronized void MvYM() {}; + private synchronized long MlYM(long l) { return l; }; + private synchronized long[] MlY1M(long l[]) { return l; }; + private synchronized long[][] MlY2M(long l[][]) { return l; }; + private final void MvPM() {}; + private final long MlPM(long l) { return l; }; + private final long[] MlP1M(long l[]) { return l; }; + private final long[][] MlP2M(long l[][]) { return l; }; + + C002 MX(C002 X) { return X; }; + C002[] MX1(C002 X[]) { return X; }; + C002[][] MX2(C002 X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + private C002 MXM(C002 X) { return X; }; + private C002[] MX1M(C002 X[]) { return X; }; + private C002[][] MX2M(C002 X[][]) { return X; }; + private Object MOM(Object O) { return O; }; + private Object[] MO1M(Object[] O) { return O; }; + private Object[][] MO2M(Object[][] O) { return O; }; + + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long[] L) { return L; }; + static Long[][] MLS2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + private static Long MLSM(Long L) { return L; }; + private static Long[] MLS1M(Long[] L) { return L; }; + private static Long[][] MLS2M(Long[][] L) { return L; }; + private native Long MLNM(Long L); + private native Long[] MLN1M(Long[] L); + private native Long[][] MLN2M(Long[][] L); + private strictfp Long MLIM(Long L) { return L; }; + private strictfp Long[] MLI1M(Long[] L) { return L; }; + private strictfp Long[][] MLI2M(Long[][] L) { return L; }; + private synchronized Long MLYM(Long L) { return L; }; + private synchronized Long[] MLY1M(Long[] L) { return L; }; + private synchronized Long[][] MLY2M(Long[][] L) { return L; }; + private final Long MLPM(Long L) { return L; }; + private final Long[] MLP1M(Long[] L) { return L; }; + private final Long[][] MLP2M(Long[][] L) { return L; }; + + I002 ME(I002 E) { return E; }; + I002[] ME1(I002[] E) { return E; }; + I002[][] ME2(I002[][] E) { return E; }; + private I002 MEM(I002 E) { return E; }; + private I002[] ME1M(I002[] E) { return E; }; + private I002[][] ME2M(I002[][] E) { return E; }; + + static I002 MES(I002 E) { return E; }; + static I002[] MES1(I002[] E) { return E; }; + static I002[][] MES2(I002[][] E) { return E; }; + native I002 MEN(I002 E); + native I002[] MEN1(I002[] E); + native I002[][] MEN2(I002[][] E); + strictfp I002 MEI(I002 E) { return E; }; + strictfp I002[] MEI1(I002[] E) { return E; }; + strictfp I002[][] MEI2(I002[][] E) { return E; }; + synchronized I002 MEY(I002 E) { return E; }; + synchronized I002[] MEY1(I002[] E) { return E; }; + synchronized I002[][] MEY2(I002[][] E) { return E; }; + public I002 MEU(I002 E) { return E; }; + public I002[] MEU1(I002[] E) { return E; }; + public I002[][] MEU2(I002[][] E) { return E; }; + protected I002 MER(I002 E) { return E; }; + protected I002[] MER1(I002[] E) { return E; }; + protected I002[][] MER2(I002[][] E) { return E; }; + private I002 MEP(I002 E) { return E; }; + private I002[] MEP1(I002[] E) { return E; }; + private I002[][] MEP2(I002[][] E) { return E; }; + + private static I002 MESM(I002 E) { return E; }; + private static I002[] MES1M(I002[] E) { return E; }; + private static I002[][] MES2M(I002[][] E) { return E; }; + private native I002 MENM(I002 E); + private native I002[] MEN1M(I002[] E); + private native I002[][] MEN2M(I002[][] E); + private strictfp I002 MEIM(I002 E) { return E; }; + private strictfp I002[] MEI1M(I002[] E) { return E; }; + private strictfp I002[][] MEI2M(I002[][] E) { return E; }; + private synchronized I002 MEYM(I002 E) { return E; }; + private synchronized I002[] MEY1M(I002[] E) { return E; }; + private synchronized I002[][] MEY2M(I002[][] E) { return E; }; + private final I002 MEPM(I002 E) { return E; }; + private final I002[] MEP1M(I002[] E) { return E; }; + private final I002[][] MEP2M(I002[][] E) { return E; }; + +} + +//--------------------------------------------- test specific methods +class C002 {} +interface I002 {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001.java new file mode 100644 index 00000000000..3c422c62019 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isProtected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class isprotected001 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isProtected."; + private final static String debuggerName = prefix + "isprotected001"; + private final static String debuggeeName = debuggerName + "a"; + + private static ReferenceType debuggeeClass; + + final static String IS_PROTECTED = "true"; + final static String NOT_PROTECTED = "false"; + final static int TOTAL_FIELDS = 132; + + /** debuggee's fields for check **/ + private final static String checkedFields[][] = { + {"z0", NOT_PROTECTED}, {"z1", NOT_PROTECTED}, {"z2", NOT_PROTECTED}, + {"b0", NOT_PROTECTED}, {"b1", NOT_PROTECTED}, {"b2", NOT_PROTECTED}, + {"c0", NOT_PROTECTED}, {"c1", NOT_PROTECTED}, {"c2", NOT_PROTECTED}, + {"d0", NOT_PROTECTED}, {"d1", NOT_PROTECTED}, {"d2", NOT_PROTECTED}, + {"f0", NOT_PROTECTED}, {"f1", NOT_PROTECTED}, {"f2", NOT_PROTECTED}, + {"i0", NOT_PROTECTED}, {"i1", NOT_PROTECTED}, {"i2", NOT_PROTECTED}, + {"l0", NOT_PROTECTED}, {"l1", NOT_PROTECTED}, {"l2", NOT_PROTECTED}, + {"r0", NOT_PROTECTED}, {"r1", NOT_PROTECTED}, {"r2", NOT_PROTECTED}, + + {"zP0", IS_PROTECTED}, {"zP1", IS_PROTECTED}, {"zP2", IS_PROTECTED}, + {"bP0", IS_PROTECTED}, {"bP1", IS_PROTECTED}, {"bP2", IS_PROTECTED}, + {"cP0", IS_PROTECTED}, {"cP1", IS_PROTECTED}, {"cP2", IS_PROTECTED}, + {"dP0", IS_PROTECTED}, {"dP1", IS_PROTECTED}, {"dP2", IS_PROTECTED}, + {"fP0", IS_PROTECTED}, {"fP1", IS_PROTECTED}, {"fP2", IS_PROTECTED}, + {"iP0", IS_PROTECTED}, {"iP1", IS_PROTECTED}, {"iP2", IS_PROTECTED}, + {"lP0", IS_PROTECTED}, {"lP1", IS_PROTECTED}, {"lP2", IS_PROTECTED}, + {"rP0", IS_PROTECTED}, {"rP1", IS_PROTECTED}, {"rP2", IS_PROTECTED}, + + {"Z0", NOT_PROTECTED}, {"Z1", NOT_PROTECTED}, {"Z2", NOT_PROTECTED}, + {"B0", NOT_PROTECTED}, {"B1", NOT_PROTECTED}, {"B2", NOT_PROTECTED}, + {"C0", NOT_PROTECTED}, {"C1", NOT_PROTECTED}, {"C2", NOT_PROTECTED}, + {"D0", NOT_PROTECTED}, {"D1", NOT_PROTECTED}, {"D2", NOT_PROTECTED}, + {"F0", NOT_PROTECTED}, {"F1", NOT_PROTECTED}, {"F2", NOT_PROTECTED}, + {"I0", NOT_PROTECTED}, {"I1", NOT_PROTECTED}, {"I2", NOT_PROTECTED}, + {"L0", NOT_PROTECTED}, {"L1", NOT_PROTECTED}, {"L2", NOT_PROTECTED}, + {"R0", NOT_PROTECTED}, {"R1", NOT_PROTECTED}, {"R2", NOT_PROTECTED}, + + {"ZP0", IS_PROTECTED}, {"ZP1", IS_PROTECTED}, {"ZP2", IS_PROTECTED}, + {"BP0", IS_PROTECTED}, {"BP1", IS_PROTECTED}, {"BP2", IS_PROTECTED}, + {"CP0", IS_PROTECTED}, {"CP1", IS_PROTECTED}, {"CP2", IS_PROTECTED}, + {"DP0", IS_PROTECTED}, {"DP1", IS_PROTECTED}, {"DP2", IS_PROTECTED}, + {"FP0", IS_PROTECTED}, {"FP1", IS_PROTECTED}, {"FP2", IS_PROTECTED}, + {"IP0", IS_PROTECTED}, {"IP1", IS_PROTECTED}, {"IP2", IS_PROTECTED}, + {"LP0", IS_PROTECTED}, {"LP1", IS_PROTECTED}, {"LP2", IS_PROTECTED}, + {"RP0", IS_PROTECTED}, {"RP1", IS_PROTECTED}, {"RP2", IS_PROTECTED}, + + {"s0", NOT_PROTECTED}, {"s1", NOT_PROTECTED}, {"s2", NOT_PROTECTED}, + {"o0", NOT_PROTECTED}, {"o1", NOT_PROTECTED}, {"o2", NOT_PROTECTED}, + {"S0", IS_PROTECTED}, {"S1", IS_PROTECTED}, {"S2", IS_PROTECTED}, + {"O0", IS_PROTECTED}, {"O1", IS_PROTECTED}, {"O2", IS_PROTECTED}, + + {"u0", NOT_PROTECTED}, {"u1", NOT_PROTECTED}, {"u2", NOT_PROTECTED}, + {"v0", IS_PROTECTED}, {"v1", IS_PROTECTED}, {"v2", IS_PROTECTED}, + {"w0", NOT_PROTECTED}, {"w1", NOT_PROTECTED}, {"w2", NOT_PROTECTED}, + {"p0", NOT_PROTECTED}, {"p1", NOT_PROTECTED}, {"p2", NOT_PROTECTED}, + + {"h0", NOT_PROTECTED}, {"h1", NOT_PROTECTED}, {"h2", NOT_PROTECTED}, + {"j0", IS_PROTECTED}, {"j1", IS_PROTECTED}, {"j2", IS_PROTECTED}, + {"k0", NOT_PROTECTED}, {"k1", NOT_PROTECTED}, {"k2", NOT_PROTECTED}, + {"m0", NOT_PROTECTED}, {"m1", NOT_PROTECTED}, {"m2", NOT_PROTECTED} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (Consts.TEST_PASSED) or either 2 (Consts.TEST_FAILED). + */ + public static int run (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + Debugee debuggee = binder.bindToDebugee(debuggeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "debugger > "); + + debuggee.resume(); + display("Waiting debuggee's \"ready\" signal..."); + String line = pipe.readln(); + + if (line == null) { + complain("UNEXPECTED debuggee's signal - null"); + return Consts.TEST_FAILED; + } + if (!line.equals("ready")) { + complain("UNEXPECTED debuggee's signal - " + line); + return Consts.TEST_FAILED; + } else { + display("debuggee's \"ready\" signal recieved."); + } + + int exitStatus = Consts.TEST_PASSED; + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return Consts.TEST_FAILED; + } + + + display("Checking isProtected() method for debuggee's fields..."); + + display("Total count of fields read from debuggee: " + + debuggeeClass.allFields().size() + ", expected count : " + + TOTAL_FIELDS); + + // Check all fields from debuggee + for (int i = 0; i < TOTAL_FIELDS; i++) { + Field field; + String name; + boolean isProtected; + String expectedValue; + + try { + field = debuggeeClass.fieldByName(checkedFields[i][0]); + } catch (Exception e) { + complain("Can't get field by name " + checkedFields[i][0]); + complain("Unexpected Exception: " + e); + exitStatus = Consts.TEST_FAILED; + continue; + } + + name = field.name(); + isProtected = ((TypeComponent)field).isProtected(); // cast to TypeComponent interface + expectedValue = checkedFields[i][1]; + if ((isProtected && !expectedValue.equals(IS_PROTECTED)) || + (!isProtected && expectedValue.equals(IS_PROTECTED)) ) { + complain("isProtected() returned wrong value: " + isProtected + + " for field " + name + + "; expected value : " + expectedValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("isProtected() returned expected " + isProtected + + " for field " + name); + } + } + + display("Checking debuggee's fields completed!"); + display("Waiting for debuggee's finish..."); + pipe.println("quit"); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != Consts.TEST_PASSED + Consts.JCK_STATUS_BASE) { + complain("UNEXPECTED debuggee's exit status (not 95) - " + status); + exitStatus = Consts.TEST_FAILED; + } else { + display("Got expected debuggee's exit status - " + status); + } + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001/TestDescription.java new file mode 100644 index 00000000000..0b48cc8cbda --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isProtected/isprotected001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isProtected() method of Accessible interface + * for TypeComponent sub-interface of com.sun.jdi package. + * The method spec: + * public boolean isProtected() + * Determines if this object mirrors a protected item. For ArrayType, + * the return value depends on the array component type. For primitive arrays + * the return value is always false. For object arrays, the return value is + * the same as would be returned for the component type. For primitive + * classes, such as Integer.TYPE, the return value is always false. + * Returns: + * true for items with private access; false otherwise. + * nsk/jdi/TypeComponent/isProtected/isprotected001 checks assertions: + * public boolean isProtected() + * 1. Returns true if the field was declared protected. + * 2. Returns false otherwise. + * Debugger gets each field from debuggee calling by name and then checks + * if method isProtected() returns an expected value. + * COMMENTS + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for isProtected method. + * The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isProtected.isprotected001 + * nsk.jdi.TypeComponent.isProtected.isprotected001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isProtected.isprotected001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001a.java new file mode 100644 index 00000000000..69eec73ebb2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected001a.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isProtected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isprotected001a { + + boolean z0, z1[] = {z0}, z2[][] = {z1}; + byte b0, b1[] = {b0}, b2[][] = {b1}; + char c0, c1[] = {c0}, c2[][] = {c1}; + double d0, d1[] = {d0}, d2[][] = {d1}; + float f0, f1[] = {f0}, f2[][] = {f1}; + int i0, i1[] = {i0}, i2[][] = {i1}; + long l0, l1[] = {l0}, l2[][] = {l1}; + short r0, r1[] = {r0}, r2[][] = {r1}; + + protected boolean zP0, zP1[] = {zP0}, zP2[][] = {zP1}; + protected byte bP0, bP1[] = {bP0}, bP2[][] = {bP1}; + protected char cP0, cP1[] = {cP0}, cP2[][] = {cP1}; + protected double dP0, dP1[] = {dP0}, dP2[][] = {dP1}; + protected float fP0, fP1[] = {fP0}, fP2[][] = {fP1}; + protected int iP0, iP1[] = {iP0}, iP2[][] = {iP1}; + protected long lP0, lP1[] = {lP0}, lP2[][] = {lP1}; + protected short rP0, rP1[] = {rP0}, rP2[][] = {rP1}; + + Boolean Z0, Z1[] = {Z0}, Z2[][] = {Z1}; + Byte B0, B1[] = {B0}, B2[][] = {B1}; + Character C0, C1[] = {C0}, C2[][] = {C1}; + Double D0, D1[] = {D0}, D2[][] = {D1}; + Float F0, F1[] = {F0}, F2[][] = {F1}; + Integer I0, I1[] = {I0}, I2[][] = {I1}; + Long L0, L1[] = {L0}, L2[][] = {L1}; + Short R0, R1[] = {R0}, R2[][] = {R1}; + + protected Boolean ZP0, ZP1[] = {ZP0}, ZP2[][] = {ZP1}; + protected Byte BP0, BP1[] = {BP0}, BP2[][] = {BP1}; + protected Character CP0, CP1[] = {CP0}, CP2[][] = {CP1}; + protected Double DP0, DP1[] = {DP0}, DP2[][] = {DP1}; + protected Float FP0, FP1[] = {FP0}, FP2[][] = {FP1}; + protected Integer IP0, IP1[] = {IP0}, IP2[][] = {IP1}; + protected Long LP0, LP1[] = {LP0}, LP2[][] = {LP1}; + protected Short RP0, RP1[] = {RP0}, RP2[][] = {RP1}; + + String s0, s1[] = {s0}, s2[][] = {s1}; + Object o0, o1[] = {o0}, o2[][] = {o1}; + protected String S0, S1[] = {S0}, S2[][] = {S1}; + protected Object O0, O1[] = {O0}, O2[][] = {O1}; + + private P u0, u1[] = {u0}, u2[][] = {u1}; + protected P v0, v1[] = {v0}, v2[][] = {v1}; + public P w0, w1[] = {w0}, w2[][] = {w1}; + P p0, p1[] = {p0}, p2[][] = {p1}; // package private + + private M h0, h1[] = {h0}, h2[][] = {h1}; + protected M j0, j1[] = {j0}, j2[][] = {j1}; + public M k0, k1[] = {k0}, k2[][] = {k1}; + M m0, m1[] = {m0}, m2[][] = {m1}; // package private + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + isprotected001a isprotected001a_ = new isprotected001a(); + + log.display(" debuggee started."); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("debuggee > \"quit\" signal recieved."); + log.display("debuggee > completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("debuggee > unexpected signal (not \"quit\") - " + instruction); + log.complain("debuggee > TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class P {} +interface M {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002.java new file mode 100644 index 00000000000..3b6a3a891f0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isProtected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class isprotected002 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isProtected."; + private final static String debuggerName = prefix + "isprotected002"; + private final static String debuggeeName = debuggerName + "a"; + + private static ReferenceType debuggeeClass; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (Consts.TEST_PASSED) or either 2 (Consts.TEST_FAILED). + */ + public static int run (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + Debugee debuggee = binder.bindToDebugee(debuggeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "debugger > "); + + debuggee.resume(); + display("Waiting debuggee's \"ready\" signal..."); + String line = pipe.readln(); + + if (line == null) { + complain("UNEXPECTED debuggee's signal - null"); + return Consts.TEST_FAILED; + } + if (!line.equals("ready")) { + complain("UNEXPECTED debuggee's signal - " + line); + return Consts.TEST_FAILED; + } else { + display("debuggee's \"ready\" signal recieved."); + } + + int exitStatus = Consts.TEST_PASSED; + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return Consts.TEST_FAILED; + } + + + display("Checking isProtected() method for debuggee's methods..."); + + display("Total count of methods read from debuggee: " + + debuggeeClass.allFields().size() + ", expected count : " + + checkedMethods.length+1); + + // Check all methods from debuggee + for (int i = 0; i < checkedMethods.length-1; i++) { + List listOfMethods; + int totalMethodsByName; + Method method; + String name; + boolean isProtected; + String expectedValue; + + try { + listOfMethods = debuggeeClass.methodsByName(checkedMethods[i][0]); + } catch (Exception e) { + complain("Can't get method by name " + checkedMethods[i][0]); + complain("Unexpected Exception: " + e); + exitStatus = Consts.TEST_FAILED; + continue; + } + + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + checkedMethods[i][0] + " is " + totalMethodsByName + + ", should be 1."); + exitStatus = Consts.TEST_FAILED; + continue; + } + method = (Method)listOfMethods.get(0); + + name = method.name(); + isProtected = ((TypeComponent)method).isProtected(); // cast to TypeComponent interface + expectedValue = checkedMethods[i][1]; + if ((isProtected && !expectedValue.equals(IS_PROTECTED)) || + (!isProtected && expectedValue.equals(IS_PROTECTED)) ) { + complain("isProtected() returned wrong value: " + isProtected + + " for method " + name + + "; expected value : " + expectedValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("isProtected() returned expected " + isProtected + + " for method " + name); + } + } + + display("Checking debuggee's methods completed!"); + display("Waiting for debuggee's finish..."); + pipe.println("quit"); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != Consts.TEST_PASSED + Consts.JCK_STATUS_BASE) { + complain("UNEXPECTED debuggee's exit status (not 95) - " + status); + exitStatus = Consts.TEST_FAILED; + } else { + display("Got expected debuggee's exit status - " + status); + } + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + //--------------------------------------------- test specific fields + + final static String IS_PROTECTED = "true"; + final static String NOT_PROTECTED = "false"; + + /** debuggee's methods for check **/ + private final static String checkedMethods[][] = { + {"Mv", NOT_PROTECTED}, + {"Mz", NOT_PROTECTED}, + {"Mz1", NOT_PROTECTED}, + {"Mz2", NOT_PROTECTED}, + {"Mb", NOT_PROTECTED}, + {"Mb1", NOT_PROTECTED}, + {"Mb2", NOT_PROTECTED}, + {"Mc", NOT_PROTECTED}, + {"Mc1", NOT_PROTECTED}, + {"Mc2", NOT_PROTECTED}, + {"Md", NOT_PROTECTED}, + {"Md1", NOT_PROTECTED}, + {"Md2", NOT_PROTECTED}, + {"Mf1", NOT_PROTECTED}, + {"Mf2", NOT_PROTECTED}, + {"Mi", NOT_PROTECTED}, + {"Mi1", NOT_PROTECTED}, + {"Mi2", NOT_PROTECTED}, + {"Ml", NOT_PROTECTED}, + {"Ml1", NOT_PROTECTED}, + {"Ml2", NOT_PROTECTED}, + {"Mr", NOT_PROTECTED}, + {"Mr1", NOT_PROTECTED}, + {"Mr2", NOT_PROTECTED}, + + {"MvM", IS_PROTECTED}, + {"MzM", IS_PROTECTED}, + {"Mz1M", IS_PROTECTED}, + {"Mz2M", IS_PROTECTED}, + {"MbM", IS_PROTECTED}, + {"Mb1M", IS_PROTECTED}, + {"Mb2M", IS_PROTECTED}, + {"McM", IS_PROTECTED}, + {"Mc1M", IS_PROTECTED}, + {"Mc2M", IS_PROTECTED}, + {"MdM", IS_PROTECTED}, + {"Md1M", IS_PROTECTED}, + {"Md2M", IS_PROTECTED}, + {"MfM", IS_PROTECTED}, + {"Mf1M", IS_PROTECTED}, + {"Mf2M", IS_PROTECTED}, + {"MiM", IS_PROTECTED}, + {"Mi1M", IS_PROTECTED}, + {"Mi2M", IS_PROTECTED}, + {"MlM", IS_PROTECTED}, + {"Ml1M", IS_PROTECTED}, + {"Ml2M", IS_PROTECTED}, + {"MrM", IS_PROTECTED}, + {"Mr1M", IS_PROTECTED}, + {"Mr2M", IS_PROTECTED}, + + {"MvS", NOT_PROTECTED}, + {"MlS", NOT_PROTECTED}, + {"MlS1", NOT_PROTECTED}, + {"MlS2", NOT_PROTECTED}, + {"MvN", NOT_PROTECTED}, + {"MlN", NOT_PROTECTED}, + {"MlN1", NOT_PROTECTED}, + {"MlN2", NOT_PROTECTED}, + {"MvI", NOT_PROTECTED}, + {"MlI", NOT_PROTECTED}, + {"MlI1", NOT_PROTECTED}, + {"MlI2", NOT_PROTECTED}, + {"MvY", NOT_PROTECTED}, + {"MlY", NOT_PROTECTED}, + {"MlY1", NOT_PROTECTED}, + {"MlY2", NOT_PROTECTED}, + {"MvU", NOT_PROTECTED}, + {"MlU", NOT_PROTECTED}, + {"MlU1", NOT_PROTECTED}, + {"MlU2", NOT_PROTECTED}, + {"MvR", IS_PROTECTED}, + {"MlR", IS_PROTECTED}, + {"MlR1", IS_PROTECTED}, + {"MlR2", IS_PROTECTED}, + {"MvP", NOT_PROTECTED}, + {"MlP", NOT_PROTECTED}, + {"MlP1", NOT_PROTECTED}, + {"MlP2", NOT_PROTECTED}, + + {"MvSM", IS_PROTECTED}, + {"MlSM", IS_PROTECTED}, + {"MlS1M", IS_PROTECTED}, + {"MlS2M", IS_PROTECTED}, + {"MvNM", IS_PROTECTED}, + {"MlNM", IS_PROTECTED}, + {"MlN1M", IS_PROTECTED}, + {"MlN2M", IS_PROTECTED}, + {"MvIM", IS_PROTECTED}, + {"MlIM", IS_PROTECTED}, + {"MlI1M", IS_PROTECTED}, + {"MlI2M", IS_PROTECTED}, + {"MvYM", IS_PROTECTED}, + {"MlYM", IS_PROTECTED}, + {"MlY1M", IS_PROTECTED}, + {"MlY2M", IS_PROTECTED}, + {"MvPM", IS_PROTECTED}, + {"MlPM", IS_PROTECTED}, + {"MlP1M", IS_PROTECTED}, + {"MlP2M", IS_PROTECTED}, + + {"MX", NOT_PROTECTED}, + {"MX1", NOT_PROTECTED}, + {"MX2", NOT_PROTECTED}, + {"MO", NOT_PROTECTED}, + {"MO1", NOT_PROTECTED}, + {"MO2", NOT_PROTECTED}, + + {"MXM", IS_PROTECTED}, + {"MX1M", IS_PROTECTED}, + {"MX2M", IS_PROTECTED}, + {"MOM", IS_PROTECTED}, + {"MO1M", IS_PROTECTED}, + {"MO2M", IS_PROTECTED}, + + {"MLS", NOT_PROTECTED}, + {"MLS1", NOT_PROTECTED}, + {"MLS2", NOT_PROTECTED}, + {"MLN", NOT_PROTECTED}, + {"MLN1", NOT_PROTECTED}, + {"MLN2", NOT_PROTECTED}, + {"MLI", NOT_PROTECTED}, + {"MLI1", NOT_PROTECTED}, + {"MLI2", NOT_PROTECTED}, + {"MLY", NOT_PROTECTED}, + {"MLY1", NOT_PROTECTED}, + {"MLY2", NOT_PROTECTED}, + {"MLU", NOT_PROTECTED}, + {"MLU1", NOT_PROTECTED}, + {"MLU2", NOT_PROTECTED}, + {"MLR", IS_PROTECTED}, + {"MLR1", IS_PROTECTED}, + {"MLR2", IS_PROTECTED}, + {"MLP", NOT_PROTECTED}, + {"MLP1", NOT_PROTECTED}, + {"MLP2", NOT_PROTECTED}, + + {"MLSM", IS_PROTECTED}, + {"MLS1M", IS_PROTECTED}, + {"MLS2M", IS_PROTECTED}, + {"MLNM", IS_PROTECTED}, + {"MLN1M", IS_PROTECTED}, + {"MLN2M", IS_PROTECTED}, + {"MLIM", IS_PROTECTED}, + {"MLI1M", IS_PROTECTED}, + {"MLI2M", IS_PROTECTED}, + {"MLYM", IS_PROTECTED}, + {"MLY1M", IS_PROTECTED}, + {"MLY2M", IS_PROTECTED}, + {"MLPM", IS_PROTECTED}, + {"MLP1M", IS_PROTECTED}, + {"MLP2M", IS_PROTECTED}, + + {"ME", NOT_PROTECTED}, + {"ME1", NOT_PROTECTED}, + {"ME2", NOT_PROTECTED}, + {"MEM", IS_PROTECTED}, + {"ME1M", IS_PROTECTED}, + {"ME2M", IS_PROTECTED}, + + {"MES", NOT_PROTECTED}, + {"MES1", NOT_PROTECTED}, + {"MES2", NOT_PROTECTED}, + {"MEN", NOT_PROTECTED}, + {"MEN1", NOT_PROTECTED}, + {"MEN2", NOT_PROTECTED}, + {"MEI", NOT_PROTECTED}, + {"MEI1", NOT_PROTECTED}, + {"MEI2", NOT_PROTECTED}, + {"MEY", NOT_PROTECTED}, + {"MEY1", NOT_PROTECTED}, + {"MEY2", NOT_PROTECTED}, + {"MEU", NOT_PROTECTED}, + {"MEU1", NOT_PROTECTED}, + {"MEU2", NOT_PROTECTED}, + {"MER", IS_PROTECTED}, + {"MER1", IS_PROTECTED}, + {"MER2", IS_PROTECTED}, + {"MEP", NOT_PROTECTED}, + {"MEP1", NOT_PROTECTED}, + {"MEP2", NOT_PROTECTED}, + + {"MESM", IS_PROTECTED}, + {"MES1M", IS_PROTECTED}, + {"MES2M", IS_PROTECTED}, + {"MENM", IS_PROTECTED}, + {"MEN1M", IS_PROTECTED}, + {"MEN2M", IS_PROTECTED}, + {"MEIM", IS_PROTECTED}, + {"MEI1M", IS_PROTECTED}, + {"MEI2M", IS_PROTECTED}, + {"MEYM", IS_PROTECTED}, + {"MEY1M", IS_PROTECTED}, + {"MEY2M", IS_PROTECTED}, + {"MEPM", IS_PROTECTED}, + {"MEP1M", IS_PROTECTED}, + {"MEP2M", IS_PROTECTED} + }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002/TestDescription.java new file mode 100644 index 00000000000..5a80970f3d1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isProtected/isprotected002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isProtected() method of Accessible interface + * for TypeComponent sub-interface of com.sun.jdi package. + * The method spec: + * public boolean isProtected() + * Determines if this object mirrors a protected item. For ArrayType, + * the return value depends on the array component type. For primitive arrays + * the return value is always false. For object arrays, the return value is + * the same as would be returned for the component type. For primitive + * classes, such as Integer.TYPE, the return value is always false. + * Returns: + * true for items with private access; false otherwise. + * nsk/jdi/TypeComponent/isProtected/isprotected002 checks assertions: + * public boolean isProtected() + * 1. Returns true if the method was declared protected. + * 2. Returns false otherwise. + * Debugger gets each method from debuggee calling by name and then checks + * if method isProtected() returns an expected value. + * COMMENTS + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for isProtected method. + * The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isProtected.isprotected002 + * nsk.jdi.TypeComponent.isProtected.isprotected002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isProtected.isprotected002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002a.java new file mode 100644 index 00000000000..2b912cd57f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isProtected/isprotected002a.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isProtected; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isprotected002a { + + //--------------------------------------------- test mutable methods + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + isprotected002a isprotected002a_ = new isprotected002a(); + + log.display(" debuggee started."); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("debuggee > \"quit\" signal recieved."); + log.display("debuggee > completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("debuggee > unexpected signal (not \"quit\") - " + instruction); + log.complain("debuggee > TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------- test specific methods + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + protected void MvM() {}; + protected boolean MzM(boolean z) { return z; }; + protected boolean[] Mz1M(boolean z[]) { return z; }; + protected boolean[][] Mz2M(boolean z[][]) { return z; }; + protected byte MbM(byte b) { return b; }; + protected byte[] Mb1M(byte b[]) { return b; }; + protected byte[][] Mb2M(byte b[][]) { return b; }; + protected char McM(char c) { return c; }; + protected char[] Mc1M(char c[]) { return c; }; + protected char[][] Mc2M(char c[][]) { return c; }; + protected double MdM(double d) { return d; }; + protected double[] Md1M(double d[]) { return d; }; + protected double[][] Md2M(double d[][]) { return d; }; + protected float MfM(float f) { return f; }; + protected float[] Mf1M(float f[]) { return f; }; + protected float[][] Mf2M(float f[][]) { return f; }; + protected int MiM(int i) { return i; }; + protected int[] Mi1M(int i[]) { return i; }; + protected int[][] Mi2M(int i[][]) { return i; }; + protected long MlM(long l) { return l; }; + protected long[] Ml1M(long l[]) { return l; }; + protected long[][] Ml2M(long l[][]) { return l; }; + protected short MrM(short r) { return r; }; + protected short[] Mr1M(short r[]) { return r; }; + protected short[][] Mr2M(short r[][]) { return r; }; + + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + protected static void MvSM() {}; + protected static long MlSM(long l) { return l; }; + protected static long[] MlS1M(long l[]) { return l; }; + protected static long[][] MlS2M(long l[][]) { return l; }; + protected native void MvNM(); + protected native long MlNM(long l); + protected native long[] MlN1M(long l[]); + protected native long[][] MlN2M(long l[][]); + protected strictfp void MvIM() {}; + protected strictfp long MlIM(long l) { return l; }; + protected strictfp long[] MlI1M(long l[]) { return l; }; + protected strictfp long[][] MlI2M(long l[][]) { return l; }; + protected synchronized void MvYM() {}; + protected synchronized long MlYM(long l) { return l; }; + protected synchronized long[] MlY1M(long l[]) { return l; }; + protected synchronized long[][] MlY2M(long l[][]) { return l; }; + protected final void MvPM() {}; + protected final long MlPM(long l) { return l; }; + protected final long[] MlP1M(long l[]) { return l; }; + protected final long[][] MlP2M(long l[][]) { return l; }; + + C002 MX(C002 X) { return X; }; + C002[] MX1(C002 X[]) { return X; }; + C002[][] MX2(C002 X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + protected C002 MXM(C002 X) { return X; }; + protected C002[] MX1M(C002 X[]) { return X; }; + protected C002[][] MX2M(C002 X[][]) { return X; }; + protected Object MOM(Object O) { return O; }; + protected Object[] MO1M(Object[] O) { return O; }; + protected Object[][] MO2M(Object[][] O) { return O; }; + + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long[] L) { return L; }; + static Long[][] MLS2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + protected static Long MLSM(Long L) { return L; }; + protected static Long[] MLS1M(Long[] L) { return L; }; + protected static Long[][] MLS2M(Long[][] L) { return L; }; + protected native Long MLNM(Long L); + protected native Long[] MLN1M(Long[] L); + protected native Long[][] MLN2M(Long[][] L); + protected strictfp Long MLIM(Long L) { return L; }; + protected strictfp Long[] MLI1M(Long[] L) { return L; }; + protected strictfp Long[][] MLI2M(Long[][] L) { return L; }; + protected synchronized Long MLYM(Long L) { return L; }; + protected synchronized Long[] MLY1M(Long[] L) { return L; }; + protected synchronized Long[][] MLY2M(Long[][] L) { return L; }; + protected final Long MLPM(Long L) { return L; }; + protected final Long[] MLP1M(Long[] L) { return L; }; + protected final Long[][] MLP2M(Long[][] L) { return L; }; + + I002 ME(I002 E) { return E; }; + I002[] ME1(I002[] E) { return E; }; + I002[][] ME2(I002[][] E) { return E; }; + protected I002 MEM(I002 E) { return E; }; + protected I002[] ME1M(I002[] E) { return E; }; + protected I002[][] ME2M(I002[][] E) { return E; }; + + static I002 MES(I002 E) { return E; }; + static I002[] MES1(I002[] E) { return E; }; + static I002[][] MES2(I002[][] E) { return E; }; + native I002 MEN(I002 E); + native I002[] MEN1(I002[] E); + native I002[][] MEN2(I002[][] E); + strictfp I002 MEI(I002 E) { return E; }; + strictfp I002[] MEI1(I002[] E) { return E; }; + strictfp I002[][] MEI2(I002[][] E) { return E; }; + synchronized I002 MEY(I002 E) { return E; }; + synchronized I002[] MEY1(I002[] E) { return E; }; + synchronized I002[][] MEY2(I002[][] E) { return E; }; + public I002 MEU(I002 E) { return E; }; + public I002[] MEU1(I002[] E) { return E; }; + public I002[][] MEU2(I002[][] E) { return E; }; + protected I002 MER(I002 E) { return E; }; + protected I002[] MER1(I002[] E) { return E; }; + protected I002[][] MER2(I002[][] E) { return E; }; + private I002 MEP(I002 E) { return E; }; + private I002[] MEP1(I002[] E) { return E; }; + private I002[][] MEP2(I002[][] E) { return E; }; + + protected static I002 MESM(I002 E) { return E; }; + protected static I002[] MES1M(I002[] E) { return E; }; + protected static I002[][] MES2M(I002[][] E) { return E; }; + protected native I002 MENM(I002 E); + protected native I002[] MEN1M(I002[] E); + protected native I002[][] MEN2M(I002[][] E); + protected strictfp I002 MEIM(I002 E) { return E; }; + protected strictfp I002[] MEI1M(I002[] E) { return E; }; + protected strictfp I002[][] MEI2M(I002[][] E) { return E; }; + protected synchronized I002 MEYM(I002 E) { return E; }; + protected synchronized I002[] MEY1M(I002[] E) { return E; }; + protected synchronized I002[][] MEY2M(I002[][] E) { return E; }; + protected final I002 MEPM(I002 E) { return E; }; + protected final I002[] MEP1M(I002[] E) { return E; }; + protected final I002[][] MEP2M(I002[][] E) { return E; }; + +} + +//--------------------------------------------- test specific methods +class C002 {} +interface I002 {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001.java new file mode 100644 index 00000000000..83961f8ba0b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class ispublic001 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isPublic."; + private final static String debuggerName = prefix + "ispublic001"; + private final static String debuggeeName = debuggerName + "a"; + + private static ReferenceType debuggeeClass; + + final static String IS_PUBLIC = "true"; + final static String NOT_PUBLIC = "false"; + final static int TOTAL_FIELDS = 132; + + /** debuggee's fields for check **/ + private final static String checkedFields[][] = { + {"z0", NOT_PUBLIC}, {"z1", NOT_PUBLIC}, {"z2", NOT_PUBLIC}, + {"b0", NOT_PUBLIC}, {"b1", NOT_PUBLIC}, {"b2", NOT_PUBLIC}, + {"c0", NOT_PUBLIC}, {"c1", NOT_PUBLIC}, {"c2", NOT_PUBLIC}, + {"d0", NOT_PUBLIC}, {"d1", NOT_PUBLIC}, {"d2", NOT_PUBLIC}, + {"f0", NOT_PUBLIC}, {"f1", NOT_PUBLIC}, {"f2", NOT_PUBLIC}, + {"i0", NOT_PUBLIC}, {"i1", NOT_PUBLIC}, {"i2", NOT_PUBLIC}, + {"l0", NOT_PUBLIC}, {"l1", NOT_PUBLIC}, {"l2", NOT_PUBLIC}, + {"r0", NOT_PUBLIC}, {"r1", NOT_PUBLIC}, {"r2", NOT_PUBLIC}, + + {"zP0", IS_PUBLIC}, {"zP1", IS_PUBLIC}, {"zP2", IS_PUBLIC}, + {"bP0", IS_PUBLIC}, {"bP1", IS_PUBLIC}, {"bP2", IS_PUBLIC}, + {"cP0", IS_PUBLIC}, {"cP1", IS_PUBLIC}, {"cP2", IS_PUBLIC}, + {"dP0", IS_PUBLIC}, {"dP1", IS_PUBLIC}, {"dP2", IS_PUBLIC}, + {"fP0", IS_PUBLIC}, {"fP1", IS_PUBLIC}, {"fP2", IS_PUBLIC}, + {"iP0", IS_PUBLIC}, {"iP1", IS_PUBLIC}, {"iP2", IS_PUBLIC}, + {"lP0", IS_PUBLIC}, {"lP1", IS_PUBLIC}, {"lP2", IS_PUBLIC}, + {"rP0", IS_PUBLIC}, {"rP1", IS_PUBLIC}, {"rP2", IS_PUBLIC}, + + {"Z0", NOT_PUBLIC}, {"Z1", NOT_PUBLIC}, {"Z2", NOT_PUBLIC}, + {"B0", NOT_PUBLIC}, {"B1", NOT_PUBLIC}, {"B2", NOT_PUBLIC}, + {"C0", NOT_PUBLIC}, {"C1", NOT_PUBLIC}, {"C2", NOT_PUBLIC}, + {"D0", NOT_PUBLIC}, {"D1", NOT_PUBLIC}, {"D2", NOT_PUBLIC}, + {"F0", NOT_PUBLIC}, {"F1", NOT_PUBLIC}, {"F2", NOT_PUBLIC}, + {"I0", NOT_PUBLIC}, {"I1", NOT_PUBLIC}, {"I2", NOT_PUBLIC}, + {"L0", NOT_PUBLIC}, {"L1", NOT_PUBLIC}, {"L2", NOT_PUBLIC}, + {"R0", NOT_PUBLIC}, {"R1", NOT_PUBLIC}, {"R2", NOT_PUBLIC}, + + {"ZP0", IS_PUBLIC}, {"ZP1", IS_PUBLIC}, {"ZP2", IS_PUBLIC}, + {"BP0", IS_PUBLIC}, {"BP1", IS_PUBLIC}, {"BP2", IS_PUBLIC}, + {"CP0", IS_PUBLIC}, {"CP1", IS_PUBLIC}, {"CP2", IS_PUBLIC}, + {"DP0", IS_PUBLIC}, {"DP1", IS_PUBLIC}, {"DP2", IS_PUBLIC}, + {"FP0", IS_PUBLIC}, {"FP1", IS_PUBLIC}, {"FP2", IS_PUBLIC}, + {"IP0", IS_PUBLIC}, {"IP1", IS_PUBLIC}, {"IP2", IS_PUBLIC}, + {"LP0", IS_PUBLIC}, {"LP1", IS_PUBLIC}, {"LP2", IS_PUBLIC}, + {"RP0", IS_PUBLIC}, {"RP1", IS_PUBLIC}, {"RP2", IS_PUBLIC}, + + {"s0", NOT_PUBLIC}, {"s1", NOT_PUBLIC}, {"s2", NOT_PUBLIC}, + {"o0", NOT_PUBLIC}, {"o1", NOT_PUBLIC}, {"o2", NOT_PUBLIC}, + {"S0", IS_PUBLIC}, {"S1", IS_PUBLIC}, {"S2", IS_PUBLIC}, + {"O0", IS_PUBLIC}, {"O1", IS_PUBLIC}, {"O2", IS_PUBLIC}, + + {"u0", NOT_PUBLIC}, {"u1", NOT_PUBLIC}, {"u2", NOT_PUBLIC}, + {"v0", NOT_PUBLIC}, {"v1", NOT_PUBLIC}, {"v2", NOT_PUBLIC}, + {"w0", IS_PUBLIC}, {"w1", IS_PUBLIC}, {"w2", IS_PUBLIC}, + {"p0", NOT_PUBLIC}, {"p1", NOT_PUBLIC}, {"p2", NOT_PUBLIC}, + + {"h0", NOT_PUBLIC}, {"h1", NOT_PUBLIC}, {"h2", NOT_PUBLIC}, + {"j0", NOT_PUBLIC}, {"j1", NOT_PUBLIC}, {"j2", NOT_PUBLIC}, + {"k0", IS_PUBLIC}, {"k1", IS_PUBLIC}, {"k2", IS_PUBLIC}, + {"m0", NOT_PUBLIC}, {"m1", NOT_PUBLIC}, {"m2", NOT_PUBLIC} + }; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (Consts.TEST_PASSED) or either 2 (Consts.TEST_FAILED). + */ + public static int run (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + Debugee debuggee = binder.bindToDebugee(debuggeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "debugger > "); + + debuggee.resume(); + display("Waiting debuggee's \"ready\" signal..."); + String line = pipe.readln(); + + if (line == null) { + complain("UNEXPECTED debuggee's signal - null"); + return Consts.TEST_FAILED; + } + if (!line.equals("ready")) { + complain("UNEXPECTED debuggee's signal - " + line); + return Consts.TEST_FAILED; + } else { + display("debuggee's \"ready\" signal recieved."); + } + + int exitStatus = Consts.TEST_PASSED; + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return Consts.TEST_FAILED; + } + + + display("Checking isPublic() method for debuggee's fields..."); + + display("Total count of fields read from debuggee: " + + debuggeeClass.allFields().size() + ", expected count : " + + TOTAL_FIELDS); + + // Check all fields from debuggee + for (int i = 0; i < TOTAL_FIELDS; i++) { + Field field; + String name; + boolean isPublic; + String expectedValue; + + try { + field = debuggeeClass.fieldByName(checkedFields[i][0]); + } catch (Exception e) { + complain("Can't get field by name " + checkedFields[i][0]); + complain("Unexpected Exception: " + e); + exitStatus = Consts.TEST_FAILED; + continue; + } + + name = field.name(); + isPublic = ((TypeComponent)field).isPublic(); // cast to TypeComponent interface + expectedValue = checkedFields[i][1]; + if ((isPublic && !expectedValue.equals(IS_PUBLIC)) || + (!isPublic && expectedValue.equals(IS_PUBLIC)) ) { + complain("isPublic() returned wrong value: " + isPublic + + " for field " + name + + "; expected value : " + expectedValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("isPublic() returned expected " + isPublic + + " for field " + name); + } + } + + display("Checking debuggee's fields completed!"); + display("Waiting for debuggee's finish..."); + pipe.println("quit"); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != Consts.TEST_PASSED + Consts.JCK_STATUS_BASE) { + complain("UNEXPECTED debuggee's exit status (not 95) - " + status); + exitStatus = Consts.TEST_FAILED; + } else { + display("Got expected debuggee's exit status - " + status); + } + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001/TestDescription.java new file mode 100644 index 00000000000..70564fde7f6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isPublic/ispublic001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isPublic() method of Accessible interface + * for TypeComponent sub-interface of com.sun.jdi package. + * The method spec: + * public boolean isPublic() + * Determines if this object mirrors a public item. For ArrayType, the return + * value depends on the array component type. For primitive arrays the return + * value is always true. For object arrays, the return value is the same as + * would be returned for the component type. For primitive classes, such as + * Integer.TYPE, the return value is always true. + * Returns: + * true for items with public access; false otherwise. + * nsk/jdi/TypeComponent/isPublic/ispublic001 checks assertions: + * public boolean isPublic() + * 1. Returns true if the field was declared public. + * 2. Returns false otherwise. + * Debugger gets each field from debuggee calling by name and then checks + * if method isPublic() returns an expected value. + * COMMENTS + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for isPublic method. + * The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isPublic.ispublic001 + * nsk.jdi.TypeComponent.isPublic.ispublic001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isPublic.ispublic001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001a.java new file mode 100644 index 00000000000..587e91c975f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic001a.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class ispublic001a { + + boolean z0, z1[] = {z0}, z2[][] = {z1}; + byte b0, b1[] = {b0}, b2[][] = {b1}; + char c0, c1[] = {c0}, c2[][] = {c1}; + double d0, d1[] = {d0}, d2[][] = {d1}; + float f0, f1[] = {f0}, f2[][] = {f1}; + int i0, i1[] = {i0}, i2[][] = {i1}; + long l0, l1[] = {l0}, l2[][] = {l1}; + short r0, r1[] = {r0}, r2[][] = {r1}; + + public boolean zP0, zP1[] = {zP0}, zP2[][] = {zP1}; + public byte bP0, bP1[] = {bP0}, bP2[][] = {bP1}; + public char cP0, cP1[] = {cP0}, cP2[][] = {cP1}; + public double dP0, dP1[] = {dP0}, dP2[][] = {dP1}; + public float fP0, fP1[] = {fP0}, fP2[][] = {fP1}; + public int iP0, iP1[] = {iP0}, iP2[][] = {iP1}; + public long lP0, lP1[] = {lP0}, lP2[][] = {lP1}; + public short rP0, rP1[] = {rP0}, rP2[][] = {rP1}; + + Boolean Z0, Z1[] = {Z0}, Z2[][] = {Z1}; + Byte B0, B1[] = {B0}, B2[][] = {B1}; + Character C0, C1[] = {C0}, C2[][] = {C1}; + Double D0, D1[] = {D0}, D2[][] = {D1}; + Float F0, F1[] = {F0}, F2[][] = {F1}; + Integer I0, I1[] = {I0}, I2[][] = {I1}; + Long L0, L1[] = {L0}, L2[][] = {L1}; + Short R0, R1[] = {R0}, R2[][] = {R1}; + + public Boolean ZP0, ZP1[] = {ZP0}, ZP2[][] = {ZP1}; + public Byte BP0, BP1[] = {BP0}, BP2[][] = {BP1}; + public Character CP0, CP1[] = {CP0}, CP2[][] = {CP1}; + public Double DP0, DP1[] = {DP0}, DP2[][] = {DP1}; + public Float FP0, FP1[] = {FP0}, FP2[][] = {FP1}; + public Integer IP0, IP1[] = {IP0}, IP2[][] = {IP1}; + public Long LP0, LP1[] = {LP0}, LP2[][] = {LP1}; + public Short RP0, RP1[] = {RP0}, RP2[][] = {RP1}; + + String s0, s1[] = {s0}, s2[][] = {s1}; + Object o0, o1[] = {o0}, o2[][] = {o1}; + public String S0, S1[] = {S0}, S2[][] = {S1}; + public Object O0, O1[] = {O0}, O2[][] = {O1}; + + private P u0, u1[] = {u0}, u2[][] = {u1}; + protected P v0, v1[] = {v0}, v2[][] = {v1}; + public P w0, w1[] = {w0}, w2[][] = {w1}; + P p0, p1[] = {p0}, p2[][] = {p1}; // package private + + private M h0, h1[] = {h0}, h2[][] = {h1}; + protected M j0, j1[] = {j0}, j2[][] = {j1}; + public M k0, k1[] = {k0}, k2[][] = {k1}; + M m0, m1[] = {m0}, m2[][] = {m1}; // package private + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + ispublic001a ispublic001a_ = new ispublic001a(); + + log.display(" debuggee started."); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("debuggee > \"quit\" signal recieved."); + log.display("debuggee > completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("debuggee > unexpected signal (not \"quit\") - " + instruction); + log.complain("debuggee > TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class P {} +interface M {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002.java new file mode 100644 index 00000000000..3b9725280d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; +import java.util.*; + +public class ispublic002 { + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isPublic."; + private final static String debuggerName = prefix + "ispublic002"; + private final static String debuggeeName = debuggerName + "a"; + + private static ReferenceType debuggeeClass; + + /** + * Re-call to run(args,out), and exit with + * either status 95 or 97 (JCK-like exit status). + */ + public static void main (String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + /** + * JCK-like entry point to the test: perform testing, and + * return exit code 0 (Consts.TEST_PASSED) or either 2 (Consts.TEST_FAILED). + */ + public static int run (String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + Debugee debuggee = binder.bindToDebugee(debuggeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = debuggee.createIOPipe(); + debuggee.redirectStderr(log, "debugger > "); + + debuggee.resume(); + display("Waiting debuggee's \"ready\" signal..."); + String line = pipe.readln(); + + if (line == null) { + complain("UNEXPECTED debuggee's signal - null"); + return Consts.TEST_FAILED; + } + if (!line.equals("ready")) { + complain("UNEXPECTED debuggee's signal - " + line); + return Consts.TEST_FAILED; + } else { + display("debuggee's \"ready\" signal recieved."); + } + + int exitStatus = Consts.TEST_PASSED; + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + return Consts.TEST_FAILED; + } + + + display("Checking isPublic() method for debuggee's methods..."); + + display("Total count of methods read from debuggee: " + + debuggeeClass.allFields().size() + ", expected count : " + + checkedMethods.length+1); + + // Check all methods from debuggee + for (int i = 0; i < checkedMethods.length-1; i++) { + List listOfMethods; + int totalMethodsByName; + Method method; + String name; + boolean isPublic; + String expectedValue; + + try { + listOfMethods = debuggeeClass.methodsByName(checkedMethods[i][0]); + } catch (Exception e) { + complain("Can't get method by name " + checkedMethods[i][0]); + complain("Unexpected Exception: " + e); + exitStatus = Consts.TEST_FAILED; + continue; + } + + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + checkedMethods[i][0] + " is " + totalMethodsByName + + ", should be 1."); + exitStatus = Consts.TEST_FAILED; + continue; + } + method = (Method)listOfMethods.get(0); + + name = method.name(); + isPublic = ((TypeComponent)method).isPublic(); // cast to TypeComponent interface + expectedValue = checkedMethods[i][1]; + if ((isPublic && !expectedValue.equals(IS_PUBLIC)) || + (!isPublic && expectedValue.equals(IS_PUBLIC)) ) { + complain("isPublic() returned wrong value: " + isPublic + + " for method " + name + + "; expected value : " + expectedValue); + exitStatus = Consts.TEST_FAILED; + } else { + display("isPublic() returned expected " + isPublic + + " for method " + name); + } + } + + display("Checking debuggee's methods completed!"); + display("Waiting for debuggee's finish..."); + pipe.println("quit"); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != Consts.TEST_PASSED + Consts.JCK_STATUS_BASE) { + complain("UNEXPECTED debuggee's exit status (not 95) - " + status); + exitStatus = Consts.TEST_FAILED; + } else { + display("Got expected debuggee's exit status - " + status); + } + + return exitStatus; + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + //--------------------------------------------- test specific fields + + final static String IS_PUBLIC = "true"; + final static String NOT_PUBLIC = "false"; + + /** debuggee's methods for check **/ + private final static String checkedMethods[][] = { + {"Mv", NOT_PUBLIC}, + {"Mz", NOT_PUBLIC}, + {"Mz1", NOT_PUBLIC}, + {"Mz2", NOT_PUBLIC}, + {"Mb", NOT_PUBLIC}, + {"Mb1", NOT_PUBLIC}, + {"Mb2", NOT_PUBLIC}, + {"Mc", NOT_PUBLIC}, + {"Mc1", NOT_PUBLIC}, + {"Mc2", NOT_PUBLIC}, + {"Md", NOT_PUBLIC}, + {"Md1", NOT_PUBLIC}, + {"Md2", NOT_PUBLIC}, + {"Mf1", NOT_PUBLIC}, + {"Mf2", NOT_PUBLIC}, + {"Mi", NOT_PUBLIC}, + {"Mi1", NOT_PUBLIC}, + {"Mi2", NOT_PUBLIC}, + {"Ml", NOT_PUBLIC}, + {"Ml1", NOT_PUBLIC}, + {"Ml2", NOT_PUBLIC}, + {"Mr", NOT_PUBLIC}, + {"Mr1", NOT_PUBLIC}, + {"Mr2", NOT_PUBLIC}, + + {"MvM", IS_PUBLIC}, + {"MzM", IS_PUBLIC}, + {"Mz1M", IS_PUBLIC}, + {"Mz2M", IS_PUBLIC}, + {"MbM", IS_PUBLIC}, + {"Mb1M", IS_PUBLIC}, + {"Mb2M", IS_PUBLIC}, + {"McM", IS_PUBLIC}, + {"Mc1M", IS_PUBLIC}, + {"Mc2M", IS_PUBLIC}, + {"MdM", IS_PUBLIC}, + {"Md1M", IS_PUBLIC}, + {"Md2M", IS_PUBLIC}, + {"MfM", IS_PUBLIC}, + {"Mf1M", IS_PUBLIC}, + {"Mf2M", IS_PUBLIC}, + {"MiM", IS_PUBLIC}, + {"Mi1M", IS_PUBLIC}, + {"Mi2M", IS_PUBLIC}, + {"MlM", IS_PUBLIC}, + {"Ml1M", IS_PUBLIC}, + {"Ml2M", IS_PUBLIC}, + {"MrM", IS_PUBLIC}, + {"Mr1M", IS_PUBLIC}, + {"Mr2M", IS_PUBLIC}, + + {"MvS", NOT_PUBLIC}, + {"MlS", NOT_PUBLIC}, + {"MlS1", NOT_PUBLIC}, + {"MlS2", NOT_PUBLIC}, + {"MvN", NOT_PUBLIC}, + {"MlN", NOT_PUBLIC}, + {"MlN1", NOT_PUBLIC}, + {"MlN2", NOT_PUBLIC}, + {"MvI", NOT_PUBLIC}, + {"MlI", NOT_PUBLIC}, + {"MlI1", NOT_PUBLIC}, + {"MlI2", NOT_PUBLIC}, + {"MvY", NOT_PUBLIC}, + {"MlY", NOT_PUBLIC}, + {"MlY1", NOT_PUBLIC}, + {"MlY2", NOT_PUBLIC}, + {"MvU", IS_PUBLIC}, + {"MlU", IS_PUBLIC}, + {"MlU1", IS_PUBLIC}, + {"MlU2", IS_PUBLIC}, + {"MvR", NOT_PUBLIC}, + {"MlR", NOT_PUBLIC}, + {"MlR1", NOT_PUBLIC}, + {"MlR2", NOT_PUBLIC}, + {"MvP", NOT_PUBLIC}, + {"MlP", NOT_PUBLIC}, + {"MlP1", NOT_PUBLIC}, + {"MlP2", NOT_PUBLIC}, + + {"MvSM", IS_PUBLIC}, + {"MlSM", IS_PUBLIC}, + {"MlS1M", IS_PUBLIC}, + {"MlS2M", IS_PUBLIC}, + {"MvNM", IS_PUBLIC}, + {"MlNM", IS_PUBLIC}, + {"MlN1M", IS_PUBLIC}, + {"MlN2M", IS_PUBLIC}, + {"MvIM", IS_PUBLIC}, + {"MlIM", IS_PUBLIC}, + {"MlI1M", IS_PUBLIC}, + {"MlI2M", IS_PUBLIC}, + {"MvYM", IS_PUBLIC}, + {"MlYM", IS_PUBLIC}, + {"MlY1M", IS_PUBLIC}, + {"MlY2M", IS_PUBLIC}, + {"MvPM", IS_PUBLIC}, + {"MlPM", IS_PUBLIC}, + {"MlP1M", IS_PUBLIC}, + {"MlP2M", IS_PUBLIC}, + + {"MX", NOT_PUBLIC}, + {"MX1", NOT_PUBLIC}, + {"MX2", NOT_PUBLIC}, + {"MO", NOT_PUBLIC}, + {"MO1", NOT_PUBLIC}, + {"MO2", NOT_PUBLIC}, + + {"MXM", IS_PUBLIC}, + {"MX1M", IS_PUBLIC}, + {"MX2M", IS_PUBLIC}, + {"MOM", IS_PUBLIC}, + {"MO1M", IS_PUBLIC}, + {"MO2M", IS_PUBLIC}, + + {"MLS", NOT_PUBLIC}, + {"MLS1", NOT_PUBLIC}, + {"MLS2", NOT_PUBLIC}, + {"MLN", NOT_PUBLIC}, + {"MLN1", NOT_PUBLIC}, + {"MLN2", NOT_PUBLIC}, + {"MLI", NOT_PUBLIC}, + {"MLI1", NOT_PUBLIC}, + {"MLI2", NOT_PUBLIC}, + {"MLY", NOT_PUBLIC}, + {"MLY1", NOT_PUBLIC}, + {"MLY2", NOT_PUBLIC}, + {"MLU", IS_PUBLIC}, + {"MLU1", IS_PUBLIC}, + {"MLU2", IS_PUBLIC}, + {"MLR", NOT_PUBLIC}, + {"MLR1", NOT_PUBLIC}, + {"MLR2", NOT_PUBLIC}, + {"MLP", NOT_PUBLIC}, + {"MLP1", NOT_PUBLIC}, + {"MLP2", NOT_PUBLIC}, + + {"MLSM", IS_PUBLIC}, + {"MLS1M", IS_PUBLIC}, + {"MLS2M", IS_PUBLIC}, + {"MLNM", IS_PUBLIC}, + {"MLN1M", IS_PUBLIC}, + {"MLN2M", IS_PUBLIC}, + {"MLIM", IS_PUBLIC}, + {"MLI1M", IS_PUBLIC}, + {"MLI2M", IS_PUBLIC}, + {"MLYM", IS_PUBLIC}, + {"MLY1M", IS_PUBLIC}, + {"MLY2M", IS_PUBLIC}, + {"MLPM", IS_PUBLIC}, + {"MLP1M", IS_PUBLIC}, + {"MLP2M", IS_PUBLIC}, + + {"ME", NOT_PUBLIC}, + {"ME1", NOT_PUBLIC}, + {"ME2", NOT_PUBLIC}, + {"MEM", IS_PUBLIC}, + {"ME1M", IS_PUBLIC}, + {"ME2M", IS_PUBLIC}, + + {"MES", NOT_PUBLIC}, + {"MES1", NOT_PUBLIC}, + {"MES2", NOT_PUBLIC}, + {"MEN", NOT_PUBLIC}, + {"MEN1", NOT_PUBLIC}, + {"MEN2", NOT_PUBLIC}, + {"MEI", NOT_PUBLIC}, + {"MEI1", NOT_PUBLIC}, + {"MEI2", NOT_PUBLIC}, + {"MEY", NOT_PUBLIC}, + {"MEY1", NOT_PUBLIC}, + {"MEY2", NOT_PUBLIC}, + {"MEU", IS_PUBLIC}, + {"MEU1", IS_PUBLIC}, + {"MEU2", IS_PUBLIC}, + {"MER", NOT_PUBLIC}, + {"MER1", NOT_PUBLIC}, + {"MER2", NOT_PUBLIC}, + {"MEP", NOT_PUBLIC}, + {"MEP1", NOT_PUBLIC}, + {"MEP2", NOT_PUBLIC}, + + {"MESM", IS_PUBLIC}, + {"MES1M", IS_PUBLIC}, + {"MES2M", IS_PUBLIC}, + {"MENM", IS_PUBLIC}, + {"MEN1M", IS_PUBLIC}, + {"MEN2M", IS_PUBLIC}, + {"MEIM", IS_PUBLIC}, + {"MEI1M", IS_PUBLIC}, + {"MEI2M", IS_PUBLIC}, + {"MEYM", IS_PUBLIC}, + {"MEY1M", IS_PUBLIC}, + {"MEY2M", IS_PUBLIC}, + {"MEPM", IS_PUBLIC}, + {"MEP1M", IS_PUBLIC}, + {"MEP2M", IS_PUBLIC} + }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002/TestDescription.java new file mode 100644 index 00000000000..7541bca6452 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isPublic/ispublic002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isPublic() method of Accessible interface + * for TypeComponent sub-interface of com.sun.jdi package. + * The method spec: + * public boolean isPublic() + * Determines if this object mirrors a public item. For ArrayType, the return + * value depends on the array component type. For primitive arrays the return + * value is always true. For object arrays, the return value is the same as + * would be returned for the component type. For primitive classes, such as + * Integer.TYPE, the return value is always true. + * Returns: + * true for items with public access; false otherwise. + * nsk/jdi/TypeComponent/isPublic/ispublic002 checks assertions: + * public boolean isPublic() + * 1. Returns true if the method was declared public. + * 2. Returns false otherwise. + * Debugger gets each method from debuggee calling by name and then checks + * if method isPublic() returns an expected value. + * COMMENTS + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for isPublic method. + * The coverage analysis was done for jdk1.4.0-b92 build. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isPublic.ispublic002 + * nsk.jdi.TypeComponent.isPublic.ispublic002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isPublic.ispublic002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002a.java new file mode 100644 index 00000000000..24bf2a0012d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isPublic/ispublic002a.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.TypeComponent.isPublic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class ispublic002a { + + //--------------------------------------------- test mutable methods + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = argHandler.createDebugeeLog(); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + ispublic002a ispublic002a_ = new ispublic002a(); + + log.display(" debuggee started."); + pipe.println("ready"); + + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("debuggee > \"quit\" signal recieved."); + log.display("debuggee > completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + log.complain("debuggee > unexpected signal (not \"quit\") - " + instruction); + log.complain("debuggee > TEST FAILED"); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------- test specific methods + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + public void MvM() {}; + public boolean MzM(boolean z) { return z; }; + public boolean[] Mz1M(boolean z[]) { return z; }; + public boolean[][] Mz2M(boolean z[][]) { return z; }; + public byte MbM(byte b) { return b; }; + public byte[] Mb1M(byte b[]) { return b; }; + public byte[][] Mb2M(byte b[][]) { return b; }; + public char McM(char c) { return c; }; + public char[] Mc1M(char c[]) { return c; }; + public char[][] Mc2M(char c[][]) { return c; }; + public double MdM(double d) { return d; }; + public double[] Md1M(double d[]) { return d; }; + public double[][] Md2M(double d[][]) { return d; }; + public float MfM(float f) { return f; }; + public float[] Mf1M(float f[]) { return f; }; + public float[][] Mf2M(float f[][]) { return f; }; + public int MiM(int i) { return i; }; + public int[] Mi1M(int i[]) { return i; }; + public int[][] Mi2M(int i[][]) { return i; }; + public long MlM(long l) { return l; }; + public long[] Ml1M(long l[]) { return l; }; + public long[][] Ml2M(long l[][]) { return l; }; + public short MrM(short r) { return r; }; + public short[] Mr1M(short r[]) { return r; }; + public short[][] Mr2M(short r[][]) { return r; }; + + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + public static void MvSM() {}; + public static long MlSM(long l) { return l; }; + public static long[] MlS1M(long l[]) { return l; }; + public static long[][] MlS2M(long l[][]) { return l; }; + public native void MvNM(); + public native long MlNM(long l); + public native long[] MlN1M(long l[]); + public native long[][] MlN2M(long l[][]); + public strictfp void MvIM() {}; + public strictfp long MlIM(long l) { return l; }; + public strictfp long[] MlI1M(long l[]) { return l; }; + public strictfp long[][] MlI2M(long l[][]) { return l; }; + public synchronized void MvYM() {}; + public synchronized long MlYM(long l) { return l; }; + public synchronized long[] MlY1M(long l[]) { return l; }; + public synchronized long[][] MlY2M(long l[][]) { return l; }; + public final void MvPM() {}; + public final long MlPM(long l) { return l; }; + public final long[] MlP1M(long l[]) { return l; }; + public final long[][] MlP2M(long l[][]) { return l; }; + + C002 MX(C002 X) { return X; }; + C002[] MX1(C002 X[]) { return X; }; + C002[][] MX2(C002 X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + public C002 MXM(C002 X) { return X; }; + public C002[] MX1M(C002 X[]) { return X; }; + public C002[][] MX2M(C002 X[][]) { return X; }; + public Object MOM(Object O) { return O; }; + public Object[] MO1M(Object[] O) { return O; }; + public Object[][] MO2M(Object[][] O) { return O; }; + + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long[] L) { return L; }; + static Long[][] MLS2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + public static Long MLSM(Long L) { return L; }; + public static Long[] MLS1M(Long[] L) { return L; }; + public static Long[][] MLS2M(Long[][] L) { return L; }; + public native Long MLNM(Long L); + public native Long[] MLN1M(Long[] L); + public native Long[][] MLN2M(Long[][] L); + public strictfp Long MLIM(Long L) { return L; }; + public strictfp Long[] MLI1M(Long[] L) { return L; }; + public strictfp Long[][] MLI2M(Long[][] L) { return L; }; + public synchronized Long MLYM(Long L) { return L; }; + public synchronized Long[] MLY1M(Long[] L) { return L; }; + public synchronized Long[][] MLY2M(Long[][] L) { return L; }; + public final Long MLPM(Long L) { return L; }; + public final Long[] MLP1M(Long[] L) { return L; }; + public final Long[][] MLP2M(Long[][] L) { return L; }; + + I002 ME(I002 E) { return E; }; + I002[] ME1(I002[] E) { return E; }; + I002[][] ME2(I002[][] E) { return E; }; + public I002 MEM(I002 E) { return E; }; + public I002[] ME1M(I002[] E) { return E; }; + public I002[][] ME2M(I002[][] E) { return E; }; + + static I002 MES(I002 E) { return E; }; + static I002[] MES1(I002[] E) { return E; }; + static I002[][] MES2(I002[][] E) { return E; }; + native I002 MEN(I002 E); + native I002[] MEN1(I002[] E); + native I002[][] MEN2(I002[][] E); + strictfp I002 MEI(I002 E) { return E; }; + strictfp I002[] MEI1(I002[] E) { return E; }; + strictfp I002[][] MEI2(I002[][] E) { return E; }; + synchronized I002 MEY(I002 E) { return E; }; + synchronized I002[] MEY1(I002[] E) { return E; }; + synchronized I002[][] MEY2(I002[][] E) { return E; }; + public I002 MEU(I002 E) { return E; }; + public I002[] MEU1(I002[] E) { return E; }; + public I002[][] MEU2(I002[][] E) { return E; }; + protected I002 MER(I002 E) { return E; }; + protected I002[] MER1(I002[] E) { return E; }; + protected I002[][] MER2(I002[][] E) { return E; }; + private I002 MEP(I002 E) { return E; }; + private I002[] MEP1(I002[] E) { return E; }; + private I002[][] MEP2(I002[][] E) { return E; }; + + public static I002 MESM(I002 E) { return E; }; + public static I002[] MES1M(I002[] E) { return E; }; + public static I002[][] MES2M(I002[][] E) { return E; }; + public native I002 MENM(I002 E); + public native I002[] MEN1M(I002[] E); + public native I002[][] MEN2M(I002[][] E); + public strictfp I002 MEIM(I002 E) { return E; }; + public strictfp I002[] MEI1M(I002[] E) { return E; }; + public strictfp I002[][] MEI2M(I002[][] E) { return E; }; + public synchronized I002 MEYM(I002 E) { return E; }; + public synchronized I002[] MEY1M(I002[] E) { return E; }; + public synchronized I002[][] MEY2M(I002[][] E) { return E; }; + public final I002 MEPM(I002 E) { return E; }; + public final I002[] MEP1M(I002[] E) { return E; }; + public final I002[][] MEP2M(I002[][] E) { return E; }; + +} + +//--------------------------------------------- test specific methods +class C002 {} +interface I002 {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001.java new file mode 100644 index 00000000000..16f5dde6ccc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001.java @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class isstatic001 { + final static String IS_STATIC = "true"; + final static String NOT_STATIC = "false"; + final static int TOTAL_FIELDS = 174; + final static String FIELD_NAME[][] = { + {"z0", NOT_STATIC}, + {"z1", NOT_STATIC}, + {"z2", NOT_STATIC}, + {"b0", NOT_STATIC}, + {"b1", NOT_STATIC}, + {"b2", NOT_STATIC}, + {"c0", NOT_STATIC}, + {"c1", NOT_STATIC}, + {"c2", NOT_STATIC}, + {"d0", NOT_STATIC}, + {"d1", NOT_STATIC}, + {"d2", NOT_STATIC}, + {"f0", NOT_STATIC}, + {"f1", NOT_STATIC}, + {"f2", NOT_STATIC}, + {"i0", NOT_STATIC}, + {"i1", NOT_STATIC}, + {"i2", NOT_STATIC}, + {"l0", NOT_STATIC}, + {"l1", NOT_STATIC}, + {"l2", NOT_STATIC}, + {"r0", NOT_STATIC}, + {"r1", NOT_STATIC}, + {"r2", NOT_STATIC}, + + {"z0S", IS_STATIC}, + {"z1S", IS_STATIC}, + {"z2S", IS_STATIC}, + {"b0S", IS_STATIC}, + {"b1S", IS_STATIC}, + {"b2S", IS_STATIC}, + {"c0S", IS_STATIC}, + {"c1S", IS_STATIC}, + {"c2S", IS_STATIC}, + {"d0S", IS_STATIC}, + {"d1S", IS_STATIC}, + {"d2S", IS_STATIC}, + {"f0S", IS_STATIC}, + {"f1S", IS_STATIC}, + {"f2S", IS_STATIC}, + {"i0S", IS_STATIC}, + {"i1S", IS_STATIC}, + {"i2S", IS_STATIC}, + {"l0S", IS_STATIC}, + {"l1S", IS_STATIC}, + {"l2S", IS_STATIC}, + {"r0S", IS_STATIC}, + {"r1S", IS_STATIC}, + {"r2S", IS_STATIC}, + + {"lF0", NOT_STATIC}, + {"lF1", NOT_STATIC}, + {"lF2", NOT_STATIC}, + {"lP0", NOT_STATIC}, + {"lP1", NOT_STATIC}, + {"lP2", NOT_STATIC}, + {"lU0", NOT_STATIC}, + {"lU1", NOT_STATIC}, + {"lU2", NOT_STATIC}, + {"lR0", NOT_STATIC}, + {"lR1", NOT_STATIC}, + {"lR2", NOT_STATIC}, + {"lT0", NOT_STATIC}, + {"lT1", NOT_STATIC}, + {"lT2", NOT_STATIC}, + {"lV0", NOT_STATIC}, + {"lV1", NOT_STATIC}, + {"lV2", NOT_STATIC}, + + {"lF0S", IS_STATIC}, + {"lF1S", IS_STATIC}, + {"lF2S", IS_STATIC}, + {"lP0S", IS_STATIC}, + {"lP1S", IS_STATIC}, + {"lP2S", IS_STATIC}, + {"lU0S", IS_STATIC}, + {"lU1S", IS_STATIC}, + {"lU2S", IS_STATIC}, + {"lR0S", IS_STATIC}, + {"lR1S", IS_STATIC}, + {"lR2S", IS_STATIC}, + {"lT0S", IS_STATIC}, + {"lT1S", IS_STATIC}, + {"lT2S", IS_STATIC}, + {"lV0S", IS_STATIC}, + {"lV1S", IS_STATIC}, + {"lV2S", IS_STATIC}, + + {"X0", NOT_STATIC}, + {"X1", NOT_STATIC}, + {"X2", NOT_STATIC}, + {"O0", NOT_STATIC}, + {"O1", NOT_STATIC}, + {"O2", NOT_STATIC}, + + {"X0S", IS_STATIC}, + {"X1S", IS_STATIC}, + {"X2S", IS_STATIC}, + {"O0S", IS_STATIC}, + {"O1S", IS_STATIC}, + {"O2S", IS_STATIC}, + + {"LF0", NOT_STATIC}, + {"LF1", NOT_STATIC}, + {"LF2", NOT_STATIC}, + {"LP0", NOT_STATIC}, + {"LP1", NOT_STATIC}, + {"LP2", NOT_STATIC}, + {"LU0", NOT_STATIC}, + {"LU1", NOT_STATIC}, + {"LU2", NOT_STATIC}, + {"LR0", NOT_STATIC}, + {"LR1", NOT_STATIC}, + {"LR2", NOT_STATIC}, + {"LT0", NOT_STATIC}, + {"LT1", NOT_STATIC}, + {"LT2", NOT_STATIC}, + {"LV0", NOT_STATIC}, + {"LV1", NOT_STATIC}, + {"LV2", NOT_STATIC}, + + {"LF0S", IS_STATIC}, + {"LF1S", IS_STATIC}, + {"LF2S", IS_STATIC}, + {"LP0S", IS_STATIC}, + {"LP1S", IS_STATIC}, + {"LP2S", IS_STATIC}, + {"LU0S", IS_STATIC}, + {"LU1S", IS_STATIC}, + {"LU2S", IS_STATIC}, + {"LR0S", IS_STATIC}, + {"LR1S", IS_STATIC}, + {"LR2S", IS_STATIC}, + {"LT0S", IS_STATIC}, + {"LT1S", IS_STATIC}, + {"LT2S", IS_STATIC}, + {"LV0S", IS_STATIC}, + {"LV1S", IS_STATIC}, + {"LV2S", IS_STATIC}, + + {"E0", NOT_STATIC}, + {"E1", NOT_STATIC}, + {"E2", NOT_STATIC}, + + {"E0S", IS_STATIC}, + {"E1S", IS_STATIC}, + {"E2S", IS_STATIC}, + + {"EF0", NOT_STATIC}, + {"EF1", NOT_STATIC}, + {"EF2", NOT_STATIC}, + {"EP0", NOT_STATIC}, + {"EP1", NOT_STATIC}, + {"EP2", NOT_STATIC}, + {"EU0", NOT_STATIC}, + {"EU1", NOT_STATIC}, + {"EU2", NOT_STATIC}, + {"ER0", NOT_STATIC}, + {"ER1", NOT_STATIC}, + {"ER2", NOT_STATIC}, + {"ET0", NOT_STATIC}, + {"ET1", NOT_STATIC}, + {"ET2", NOT_STATIC}, + {"EV0", NOT_STATIC}, + {"EV1", NOT_STATIC}, + {"EV2", NOT_STATIC}, + + {"EF0S", IS_STATIC}, + {"EF1S", IS_STATIC}, + {"EF2S", IS_STATIC}, + {"EP0S", IS_STATIC}, + {"EP1S", IS_STATIC}, + {"EP2S", IS_STATIC}, + {"EU0S", IS_STATIC}, + {"EU1S", IS_STATIC}, + {"EU2S", IS_STATIC}, + {"ER0S", IS_STATIC}, + {"ER1S", IS_STATIC}, + {"ER2S", IS_STATIC}, + {"ET0S", IS_STATIC}, + {"ET1S", IS_STATIC}, + {"ET2S", IS_STATIC}, + {"EV0S", IS_STATIC}, + {"EV1S", IS_STATIC}, + {"EV2S", IS_STATIC} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isStatic."; + private final static String className = "isstatic001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "ClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + log.complain("debuger> Total fields in debugee read: " + + refType.allFields().size() + ", total fields in debuger: " + + TOTAL_FIELDS); + // Check all fields from debugee + for (int i = 0; i < TOTAL_FIELDS; i++) { + Field field; + String name; + boolean isStatic; + String realIsStatic; + + try { + field = refType.fieldByName(FIELD_NAME[i][0]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + FIELD_NAME[i][0]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + isStatic = field.isStatic(); + realIsStatic = FIELD_NAME[i][1]; + log.display("debuger> " + i + " field (" + name + "), " + + "isStatic = " + isStatic + " read."); + + // isStatic() returns true if this type component is declared + // static, returns false otherwise + if ((isStatic && !realIsStatic.equals(IS_STATIC)) || + (!isStatic && realIsStatic.equals(IS_STATIC)) + ) { + log.complain("debuger FAILURE 2> " + i + " field " + name + + ": read field.isStatic() = " + isStatic + + "; real isStatic should be " + realIsStatic); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001/TestDescription.java new file mode 100644 index 00000000000..09399fb230d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isStatic/isstatic001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isStatic() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public boolean isStatic() + * Determines if this TypeComponent is static. Return value is undefined for + * constructors and static initializers. + * Returns: true if this type component was declared static; false otherwise. + * nsk/jdi/TypeComponent/isStatic/isstatic001 checks assertions: + * public boolean isStatic() + * 1. Returns true if the field was declared static. + * 2. Returns false otherwise. + * Debugger gets each field from debuggee calling by name and then checks + * if method isStatic() returns expected value. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isStatic.isstatic001 + * nsk.jdi.TypeComponent.isStatic.isstatic001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isStatic.isstatic001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001a.java new file mode 100644 index 00000000000..49cd0e814ef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001a.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isstatic001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + ClassToCheck classToCheck = new ClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class ClassToCheck { + // User class and interface + class Class {} + interface Inter {} + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + static boolean z0S, z1S[]={z0S}, z2S[][]={z1S}; + static byte b0S, b1S[]={b0S}, b2S[][]={b1S}; + static char c0S, c1S[]={c0S}, c2S[][]={c1S}; + static double d0S, d1S[]={d0S}, d2S[][]={d1S}; + static float f0S, f1S[]={f0S}, f2S[][]={f1S}; + static int i0S, i1S[]={i0S}, i2S[][]={i1S}; + static long l0S, l1S[]={l0S}, l2S[][]={l1S}; + static short r0S, r1S[]={r0S}, r2S[][]={r1S}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + static final long lF0S = 1l, lF1S[]={lF0S}, lF2S[][]={lF1S}; + static private long lP0S, lP1S[]={lP0S}, lP2S[][]={lP1S}; + static public long lU0S, lU1S[]={lU0S}, lU2S[][]={lU1S}; + static protected long lR0S, lR1S[]={lR0S}, lR2S[][]={lR1S}; + static transient long lT0S, lT1S[]={lT0S}, lT2S[][]={lT1S}; + static volatile long lV0S, lV1S[]={lV0S}, lV2S[][]={lV1S}; + + Class X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + static Class X0S, X1S[]={X0S}, X2S[][]={X1S}; + static Object O0S, O1S[]={O0S}, O2S[][]={O1S}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + static final Long LF0S = new Long(1), LF1S[]={LF0S}, LF2S[][]={LF1S}; + static private Long LP0S, LP1S[]={LP0S}, LP2S[][]={LP1S}; + static public Long LU0S, LU1S[]={LU0S}, LU2S[][]={LU1S}; + static protected Long LR0S, LR1S[]={LR0S}, LR2S[][]={LR1S}; + static transient Long LT0S, LT1S[]={LT0S}, LT2S[][]={LT1S}; + static volatile Long LV0S, LV1S[]={LV0S}, LV2S[][]={LV1S}; + + Inter E0, E1[]={E0}, E2[][]={E1}; + static Inter E0S, E1S[]={E0S}, E2S[][]={E1S}; + + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + + static final Inter EF0S = null, EF1S[]={EF0S}, EF2S[][]={EF1S}; + static private Inter EP0S, EP1S[]={EP0S}, EP2S[][]={EP1S}; + static public Inter EU0S, EU1S[]={EU0S}, EU2S[][]={EU1S}; + static protected Inter ER0S, ER1S[]={ER0S}, ER2S[][]={ER1S}; + static transient Inter ET0S, ET1S[]={ET0S}, ET2S[][]={ET1S}; + static volatile Inter EV0S, EV1S[]={EV0S}, EV2S[][]={EV1S}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002.java new file mode 100644 index 00000000000..2b0411fd423 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class isstatic002 { + final static String IS_STATIC = "true"; + final static String NOT_STATIC = "false"; + final static int TOTAL_METHODS = 208; + final static String METHOD_NAME[][] = { + {"Mv", NOT_STATIC}, + {"Mz", NOT_STATIC}, + {"Mz1", NOT_STATIC}, + {"Mz2", NOT_STATIC}, + {"Mb", NOT_STATIC}, + {"Mb1", NOT_STATIC}, + {"Mb2", NOT_STATIC}, + {"Mc", NOT_STATIC}, + {"Mc1", NOT_STATIC}, + {"Mc2", NOT_STATIC}, + {"Md", NOT_STATIC}, + {"Md1", NOT_STATIC}, + {"Md2", NOT_STATIC}, + {"Mf", NOT_STATIC}, + {"Mf1", NOT_STATIC}, + {"Mf2", NOT_STATIC}, + {"Mi", NOT_STATIC}, + {"Mi1", NOT_STATIC}, + {"Mi2", NOT_STATIC}, + {"Ml", NOT_STATIC}, + {"Ml1", NOT_STATIC}, + {"Ml2", NOT_STATIC}, + {"Mr", NOT_STATIC}, + {"Mr1", NOT_STATIC}, + {"Mr2", NOT_STATIC}, + + {"MvS", IS_STATIC}, + {"MzS", IS_STATIC}, + {"Mz1S", IS_STATIC}, + {"Mz2S", IS_STATIC}, + {"MbS", IS_STATIC}, + {"Mb1S", IS_STATIC}, + {"Mb2S", IS_STATIC}, + {"McS", IS_STATIC}, + {"Mc1S", IS_STATIC}, + {"Mc2S", IS_STATIC}, + {"MdS", IS_STATIC}, + {"Md1S", IS_STATIC}, + {"Md2S", IS_STATIC}, + {"MfS", IS_STATIC}, + {"Mf1S", IS_STATIC}, + {"Mf2S", IS_STATIC}, + {"MiS", IS_STATIC}, + {"Mi1S", IS_STATIC}, + {"Mi2S", IS_STATIC}, + {"MlS", IS_STATIC}, + {"Ml1S", IS_STATIC}, + {"Ml2S", IS_STATIC}, + {"MrS", IS_STATIC}, + {"Mr1S", IS_STATIC}, + {"Mr2S", IS_STATIC}, + + {"MvF", NOT_STATIC}, + {"MlF", NOT_STATIC}, + {"MlF1", NOT_STATIC}, + {"MlF2", NOT_STATIC}, + {"MvN", NOT_STATIC}, + {"MlN", NOT_STATIC}, + {"MlN1", NOT_STATIC}, + {"MlN2", NOT_STATIC}, + {"MvI", NOT_STATIC}, + {"MlI", NOT_STATIC}, + {"MlI1", NOT_STATIC}, + {"MlI2", NOT_STATIC}, + {"MvY", NOT_STATIC}, + {"MlY", NOT_STATIC}, + {"MlY1", NOT_STATIC}, + {"MlY2", NOT_STATIC}, + {"MvU", NOT_STATIC}, + {"MlU", NOT_STATIC}, + {"MlU1", NOT_STATIC}, + {"MlU2", NOT_STATIC}, + {"MvR", NOT_STATIC}, + {"MlR", NOT_STATIC}, + {"MlR1", NOT_STATIC}, + {"MlR2", NOT_STATIC}, + {"MvP", NOT_STATIC}, + {"MlP", NOT_STATIC}, + {"MlP1", NOT_STATIC}, + {"MlP2", NOT_STATIC}, + + {"MvFS", IS_STATIC}, + {"MlFS", IS_STATIC}, + {"MlF1S", IS_STATIC}, + {"MlF2S", IS_STATIC}, + {"MvNS", IS_STATIC}, + {"MlNS", IS_STATIC}, + {"MlN1S", IS_STATIC}, + {"MlN2S", IS_STATIC}, + {"MvIS", IS_STATIC}, + {"MlIS", IS_STATIC}, + {"MlI1S", IS_STATIC}, + {"MlI2S", IS_STATIC}, + {"MvYS", IS_STATIC}, + {"MlYS", IS_STATIC}, + {"MlY1S", IS_STATIC}, + {"MlY2S", IS_STATIC}, + {"MvUS", IS_STATIC}, + {"MlUS", IS_STATIC}, + {"MlU1S", IS_STATIC}, + {"MlU2S", IS_STATIC}, + {"MvRS", IS_STATIC}, + {"MlRS", IS_STATIC}, + {"MlR1S", IS_STATIC}, + {"MlR2S", IS_STATIC}, + {"MvPS", IS_STATIC}, + {"MlPS", IS_STATIC}, + {"MlP1S", IS_STATIC}, + {"MlP2S", IS_STATIC}, + + {"MX", NOT_STATIC}, + {"MX1", NOT_STATIC}, + {"MX2", NOT_STATIC}, + {"MO", NOT_STATIC}, + {"MO1", NOT_STATIC}, + {"MO2", NOT_STATIC}, + + {"MXS", IS_STATIC}, + {"MX1S", IS_STATIC}, + {"MX2S", IS_STATIC}, + {"MOS", IS_STATIC}, + {"MO1S", IS_STATIC}, + {"MO2S", IS_STATIC}, + + {"MLF", NOT_STATIC}, + {"MLF1", NOT_STATIC}, + {"MLF2", NOT_STATIC}, + {"MLN", NOT_STATIC}, + {"MLN1", NOT_STATIC}, + {"MLN2", NOT_STATIC}, + {"MLI", NOT_STATIC}, + {"MLI1", NOT_STATIC}, + {"MLI2", NOT_STATIC}, + {"MLY", NOT_STATIC}, + {"MLY1", NOT_STATIC}, + {"MLY2", NOT_STATIC}, + {"MLU", NOT_STATIC}, + {"MLU1", NOT_STATIC}, + {"MLU2", NOT_STATIC}, + {"MLR", NOT_STATIC}, + {"MLR1", NOT_STATIC}, + {"MLR2", NOT_STATIC}, + {"MLP", NOT_STATIC}, + {"MLP1", NOT_STATIC}, + {"MLP2", NOT_STATIC}, + + {"MLFS", IS_STATIC}, + {"MLF1S", IS_STATIC}, + {"MLF2S", IS_STATIC}, + {"MLNS", IS_STATIC}, + {"MLN1S", IS_STATIC}, + {"MLN2S", IS_STATIC}, + {"MLIS", IS_STATIC}, + {"MLI1S", IS_STATIC}, + {"MLI2S", IS_STATIC}, + {"MLYS", IS_STATIC}, + {"MLY1S", IS_STATIC}, + {"MLY2S", IS_STATIC}, + {"MLUS", IS_STATIC}, + {"MLU1S", IS_STATIC}, + {"MLU2S", IS_STATIC}, + {"MLRS", IS_STATIC}, + {"MLR1S", IS_STATIC}, + {"MLR2S", IS_STATIC}, + {"MLPS", IS_STATIC}, + {"MLP1S", IS_STATIC}, + {"MLP2S", IS_STATIC}, + + {"ME", NOT_STATIC}, + {"ME1", NOT_STATIC}, + {"ME2", NOT_STATIC}, + {"MES", IS_STATIC}, + {"ME1S", IS_STATIC}, + {"ME2S", IS_STATIC}, + + {"MEF", NOT_STATIC}, + {"MEF1", NOT_STATIC}, + {"MEF2", NOT_STATIC}, + {"MEN", NOT_STATIC}, + {"MEN1", NOT_STATIC}, + {"MEN2", NOT_STATIC}, + {"MEI", NOT_STATIC}, + {"MEI1", NOT_STATIC}, + {"MEI2", NOT_STATIC}, + {"MEY", NOT_STATIC}, + {"MEY1", NOT_STATIC}, + {"MEY2", NOT_STATIC}, + {"MEU", NOT_STATIC}, + {"MEU1", NOT_STATIC}, + {"MEU2", NOT_STATIC}, + {"MER", NOT_STATIC}, + {"MER1", NOT_STATIC}, + {"MER2", NOT_STATIC}, + {"MEP", NOT_STATIC}, + {"MEP1", NOT_STATIC}, + {"MEP2", NOT_STATIC}, + + {"MEFS", IS_STATIC}, + {"MEF1S", IS_STATIC}, + {"MEF2S", IS_STATIC}, + {"MENS", IS_STATIC}, + {"MEN1S", IS_STATIC}, + {"MEN2S", IS_STATIC}, + {"MEIS", IS_STATIC}, + {"MEI1S", IS_STATIC}, + {"MEI2S", IS_STATIC}, + {"MEYS", IS_STATIC}, + {"MEY1S", IS_STATIC}, + {"MEY2S", IS_STATIC}, + {"MEUS", IS_STATIC}, + {"MEU1S", IS_STATIC}, + {"MEU2S", IS_STATIC}, + {"MERS", IS_STATIC}, + {"MER1S", IS_STATIC}, + {"MER2S", IS_STATIC}, + {"MEPS", IS_STATIC}, + {"MEP1S", IS_STATIC}, + {"MEP2S", IS_STATIC}, + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isStatic."; + private final static String className = "isstatic002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "isstatic002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Check all methods from debugee + for (int i = 0; i < METHOD_NAME.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + boolean isStatic; + String realIsStatic; + + try { + listOfMethods = refType.methodsByName(METHOD_NAME[i][0]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get method by name " + + METHOD_NAME[i][0]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + METHOD_NAME[i][0] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + isStatic = method.isStatic(); + realIsStatic = METHOD_NAME[i][1]; + log.display("debuger> " + i + " method (" + name + "), " + + "isStatic = " + isStatic + " read."); + + // isStatic() returns true if this type component is declared + // final, returns false otherwise + if ((isStatic && !realIsStatic.equals(IS_STATIC)) || + (!isStatic && realIsStatic.equals(IS_STATIC)) + ) { + log.display("debuger FAILURE 3> " + i + " method " + name + + ": read method.isStatic() = " + isStatic + + "; real isStatic should be " + realIsStatic); + testFailed = true; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002/TestDescription.java new file mode 100644 index 00000000000..34b7f91750c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isStatic/isstatic002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isStatic() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public boolean isStatic() + * Determines if this TypeComponent is static. Return value is undefined for + * constructors and static initializers. + * Returns: true if this type component was declared static; false otherwise. + * nsk/jdi/TypeComponent/isStatic/isstatic002 checks assertions: + * public boolean isStatic() + * 1. Returns true if the method was declared static + * 2. Returns false otherwise. + * Debugger gets each method from debuggee calling by name and then checks + * if isStatic() returns expected value. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isStatic.isstatic002 + * nsk.jdi.TypeComponent.isStatic.isstatic002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isStatic.isstatic002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002a.java new file mode 100644 index 00000000000..2f6bea12310 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic002a.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isstatic002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + isstatic002aClassToCheck classToCheck = new isstatic002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class isstatic002aClassToCheck { + // User class and interface + class Class {} + interface Inter {} + + // Methods + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + static void MvS() {}; + static boolean MzS(boolean z) { return z; }; + static boolean[] Mz1S(boolean z[]) { return z; }; + static boolean[][] Mz2S(boolean z[][]) { return z; }; + static byte MbS(byte b) { return b; }; + static byte[] Mb1S(byte b[]) { return b; }; + static byte[][] Mb2S(byte b[][]) { return b; }; + static char McS(char c) { return c; }; + static char[] Mc1S(char c[]) { return c; }; + static char[][] Mc2S(char c[][]) { return c; }; + static double MdS(double d) { return d; }; + static double[] Md1S(double d[]) { return d; }; + static double[][] Md2S(double d[][]) { return d; }; + static float MfS(float f) { return f; }; + static float[] Mf1S(float f[]) { return f; }; + static float[][] Mf2S(float f[][]) { return f; }; + static int MiS(int i) { return i; }; + static int[] Mi1S(int i[]) { return i; }; + static int[][] Mi2S(int i[][]) { return i; }; + static long MlS(long l) { return l; }; + static long[] Ml1S(long l[]) { return l; }; + static long[][] Ml2S(long l[][]) { return l; }; + static short MrS(short r) { return r; }; + static short[] Mr1S(short r[]) { return r; }; + static short[][] Mr2S(short r[][]) { return r; }; + + final void MvF() {}; + final long MlF(long l) { return l; }; + final long[] MlF1(long l[]) { return l; }; + final long[][] MlF2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + static final void MvFS() {}; + static final long MlFS(long l) { return l; }; + static final long[] MlF1S(long l[]) { return l; }; + static final long[][] MlF2S(long l[][]) { return l; }; + static native void MvNS(); + static native long MlNS(long l); + static native long[] MlN1S(long l[]); + static native long[][] MlN2S(long l[][]); + static strictfp void MvIS() {}; + static strictfp long MlIS(long l) { return l; }; + static strictfp long[] MlI1S(long l[]) { return l; }; + static strictfp long[][] MlI2S(long l[][]) { return l; }; + static synchronized void MvYS() {}; + static synchronized long MlYS(long l) { return l; }; + static synchronized long[] MlY1S(long l[]) { return l; }; + static synchronized long[][] MlY2S(long l[][]) { return l; }; + static public void MvUS() {}; + static public long MlUS(long l) { return l; }; + static public long[] MlU1S(long l[]) { return l; }; + static public long[][] MlU2S(long l[][]) { return l; }; + static protected void MvRS() {}; + static protected long MlRS(long l) { return l; }; + static protected long[] MlR1S(long l[]) { return l; }; + static protected long[][] MlR2S(long l[][]) { return l; }; + static private void MvPS() {}; + static private long MlPS(long l) { return l; }; + static private long[] MlP1S(long l[]) { return l; }; + static private long[][] MlP2S(long l[][]) { return l; }; + + Class MX(Class X) { return X; }; + Class[] MX1(Class X[]) { return X; }; + Class[][] MX2(Class X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + static Class MXS(Class X) { return X; }; + static Class[] MX1S(Class X[]) { return X; }; + static Class[][] MX2S(Class X[][]) { return X; }; + static Object MOS(Object O) { return O; }; + static Object[] MO1S(Object[] O) { return O; }; + static Object[][] MO2S(Object[][] O) { return O; }; + + final Long MLF(Long L) { return L; }; + final Long[] MLF1(Long[] L) { return L; }; + final Long[][] MLF2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + static final Long MLFS(Long L) { return L; }; + static final Long[] MLF1S(Long[] L) { return L; }; + static final Long[][] MLF2S(Long[][] L) { return L; }; + static native Long MLNS(Long L); + static native Long[] MLN1S(Long[] L); + static native Long[][] MLN2S(Long[][] L); + static strictfp Long MLIS(Long L) { return L; }; + static strictfp Long[] MLI1S(Long[] L) { return L; }; + static strictfp Long[][] MLI2S(Long[][] L) { return L; }; + static synchronized Long MLYS(Long L) { return L; }; + static synchronized Long[] MLY1S(Long[] L) { return L; }; + static synchronized Long[][] MLY2S(Long[][] L) { return L; }; + static public Long MLUS(Long L) { return L; }; + static public Long[] MLU1S(Long[] L) { return L; }; + static public Long[][] MLU2S(Long[][] L) { return L; }; + static protected Long MLRS(Long L) { return L; }; + static protected Long[] MLR1S(Long[] L) { return L; }; + static protected Long[][] MLR2S(Long[][] L) { return L; }; + static private Long MLPS(Long L) { return L; }; + static private Long[] MLP1S(Long[] L) { return L; }; + static private Long[][] MLP2S(Long[][] L) { return L; }; + + Inter ME(Inter E) { return E; }; + Inter[] ME1(Inter[] E) { return E; }; + Inter[][] ME2(Inter[][] E) { return E; }; + static Inter MES(Inter E) { return E; }; + static Inter[] ME1S(Inter[] E) { return E; }; + static Inter[][] ME2S(Inter[][] E) { return E; }; + + final Inter MEF(Inter E) { return E; }; + final Inter[] MEF1(Inter[] E) { return E; }; + final Inter[][] MEF2(Inter[][] E) { return E; }; + native Inter MEN(Inter E); + native Inter[] MEN1(Inter[] E); + native Inter[][] MEN2(Inter[][] E); + strictfp Inter MEI(Inter E) { return E; }; + strictfp Inter[] MEI1(Inter[] E) { return E; }; + strictfp Inter[][] MEI2(Inter[][] E) { return E; }; + synchronized Inter MEY(Inter E) { return E; }; + synchronized Inter[] MEY1(Inter[] E) { return E; }; + synchronized Inter[][] MEY2(Inter[][] E) { return E; }; + public Inter MEU(Inter E) { return E; }; + public Inter[] MEU1(Inter[] E) { return E; }; + public Inter[][] MEU2(Inter[][] E) { return E; }; + protected Inter MER(Inter E) { return E; }; + protected Inter[] MER1(Inter[] E) { return E; }; + protected Inter[][] MER2(Inter[][] E) { return E; }; + private Inter MEP(Inter E) { return E; }; + private Inter[] MEP1(Inter[] E) { return E; }; + private Inter[][] MEP2(Inter[][] E) { return E; }; + + static final Inter MEFS(Inter E) { return E; }; + static final Inter[] MEF1S(Inter[] E) { return E; }; + static final Inter[][] MEF2S(Inter[][] E) { return E; }; + static native Inter MENS(Inter E); + static native Inter[] MEN1S(Inter[] E); + static native Inter[][] MEN2S(Inter[][] E); + static strictfp Inter MEIS(Inter E) { return E; }; + static strictfp Inter[] MEI1S(Inter[] E) { return E; }; + static strictfp Inter[][] MEI2S(Inter[][] E) { return E; }; + static synchronized Inter MEYS(Inter E) { return E; }; + static synchronized Inter[] MEY1S(Inter[] E) { return E; }; + static synchronized Inter[][] MEY2S(Inter[][] E) { return E; }; + static public Inter MEUS(Inter E) { return E; }; + static public Inter[] MEU1S(Inter[] E) { return E; }; + static public Inter[][] MEU2S(Inter[][] E) { return E; }; + static protected Inter MERS(Inter E) { return E; }; + static protected Inter[] MER1S(Inter[] E) { return E; }; + static protected Inter[][] MER2S(Inter[][] E) { return E; }; + static private Inter MEPS(Inter E) { return E; }; + static private Inter[] MEP1S(Inter[] E) { return E; }; + static private Inter[][] MEP2S(Inter[][] E) { return E; }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003.java new file mode 100644 index 00000000000..00996cdaf9b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class isstatic003 { + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isStatic."; + private final static String className = "isstatic003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "isstatic003aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List methods; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Get all methods, find constructors and static initializers and + // check them + try { + methods = refType.allMethods(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get methods from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalMethods = methods.size(); + if (totalMethods < 1) { + log.complain("debuger FAILURE> Total number of methods read " + + totalMethods); + return 2; + } + log.display("debuger> Total methods found: " + totalMethods); + Iterator methodsIterator = methods.iterator(); + for (int i = 0; methodsIterator.hasNext(); i++) { + Method method = (Method)methodsIterator.next(); + boolean isStatic; + String decTypeName = method.declaringType().name(); + String name = method.name(); + + if (method.isConstructor() || method.isStaticInitializer()) { + try { + isStatic = method.isStatic(); + } catch(Exception e) { + log.complain("debuger FAILURE 1> Cannot get isStatic from " + + "method " + name + " in " + decTypeName); + testFailed = true; + continue; + } + log.display("debuger> " + i + " method (" + name + "), " + + "isStatic = " + isStatic + " read in " + + decTypeName); + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003/TestDescription.java new file mode 100644 index 00000000000..344dca68fa7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isStatic/isstatic003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isStatic() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public boolean isStatic() + * Determines if this TypeComponent is static. Return value is undefined for + * constructors and static initializers. + * Returns: true if this type component was declared static; false otherwise. + * nsk/jdi/TypeComponent/isStatic/isstatic003 checks assertion: + * public boolean isStatic() + * 1. method isStatic() is defined for constructors and static initializers + * and does not throw an Exception. + * Debugger gets all methods from debuggee, finds contructors and static + * initializers only and checks if isStatic() doesn't throw any Exception. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isStatic.isstatic003 + * nsk.jdi.TypeComponent.isStatic.isstatic003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isStatic.isstatic003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003a.java new file mode 100644 index 00000000000..d9b4e38ab29 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003a.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class isstatic003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + isstatic003aClassToCheck classToCheck = new isstatic003aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class isstatic003aClassToCheck extends isstatic003aSuperClass { + isstatic003aClassToCheck() {}; + public isstatic003aClassToCheck(long l) {}; + private isstatic003aClassToCheck(Object obj) {}; + protected isstatic003aClassToCheck(long[] l) {}; + + static int ci; + static Long cL; + static long[] cl = new long[10]; + + static { ci = 1; } + static { cL = new Long(1l); } + static { + for (int i = 0; i < 10; i++) { + cl[i] = (long)i; + } + } +} + +class isstatic003aSuperClass { + isstatic003aSuperClass() {}; + public isstatic003aSuperClass(long l) {}; + private isstatic003aSuperClass(Object obj) {}; + protected isstatic003aSuperClass(long[] l) {}; + + static boolean sb; + static Object sO; + static float[] sf = new float[10]; + + static { sb = true; } + static { sO = new Object(); } + static { + for (int i = 0; i < 10; i++) { + sf[i] = (float)i; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004.java new file mode 100644 index 00000000000..922c85a32f0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class isstatic004 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.TypeComponent.isStatic."; + private final static String className = "isstatic004"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + private final static String[] expectedFieldNames = {"f1", "f2", "f3"}; + private final static String[] expectedEnumFieldsNames = { "e1", "e2" }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + //debuggee.receiveExpectedSignal(SIGNAL_GO); + + for (int i=0; i < expectedFieldNames.length; i++) { + check(expectedFieldNames[i]); + display(""); + } + + display("Checking completed!"); + } + + //--------------------------------------------------------- test specific methods + + private static void check (String fieldName) { + try { + ClassType checkedClass = (ClassType)debuggeeClass.fieldByName(fieldName).type(); + String className = checkedClass.name(); + + for (int i = 0; i < expectedEnumFieldsNames.length; i++) { + Field foundField = checkedClass.fieldByName(expectedEnumFieldsNames[i]); + if (foundField != null) { + if (foundField.isStatic()) { + display("enum " + className + " has static field " + expectedEnumFieldsNames[i]); + display("\t of type " + className); + } else { + complain("enum " + className + " has instance field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } else { + complain("enum " + className + " does not have field " + expectedEnumFieldsNames[i]); + complain("\t of type " + className); + exitStatus = Consts.TEST_FAILED; + } + } + } catch (Exception e) { + complain("Unexpected exception while checking of " + className + ": " + e); + e.printStackTrace(System.out); + exitStatus = Consts.TEST_FAILED; + } + } +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004/TestDescription.java new file mode 100644 index 00000000000..f8c697f7cf4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isStatic/isstatic004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * A test for isStatic() method of TypeComponent interface. + * The test checks if the method returns true for each enum + * constants declared in mirrored enum type. + * The test consists of a debugger program (isstatic004.java) + * and debuggee application (isstatic004a.java). + * Package name is nsk.jdi.TypeComponent.isStatic . + * The test works as follows. + * The debugger uses nsk.jdi.share framework classes to + * establish connection with debuggee. The debugger and debuggee + * synchronize with each other using special commands over + * communication channel provided by framework classes. + * Upon receiving the signal of readiness from debuggee, + * the debugger finds fields of enum type declared in isstatic004a + * class. Then the debugger checks test assertion for every + * enum constants declared in mirrored enum types. + * COMMENTS: + * 5029502 TEST_BUG: jdi tests against enum should not use abstract + * modifier + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isStatic.isstatic004 + * nsk.jdi.TypeComponent.isStatic.isstatic004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isStatic.isstatic004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004a.java new file mode 100644 index 00000000000..194c2962334 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic004a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.TypeComponent.isStatic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * The debugged application of the test. + */ +public class isstatic004a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debugger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + static isstatic004Enum1 f1 = isstatic004Enum1.e2; + static isstatic004Enum2 f2 = isstatic004Enum2.e1; + static isstatic004Enum1.Enum1_ f3 = isstatic004Enum1.Enum1_.e1; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println(isstatic004.SIGNAL_READY); + + + //pipe.println(isstatic004.SIGNAL_GO); + receiveSignal(isstatic004.SIGNAL_QUIT); + + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + //--------------------------------------------------------- test specific inner classes + +} + +//--------------------------------------------------------- test specific classes + +enum isstatic004Enum1 { + e1, e2; + + enum Enum1_ { + e1, e2; + } +} + +enum isstatic004Enum2 { + e1 { + int val() {return 1;} + }, + + e2 { + int val() {return 2;} + }; + abstract int val(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001.java new file mode 100644 index 00000000000..8bf280dd2cd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isSynthetic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class issynthetic001 { + final static String FIELD_NAME[] = { + "z0", "z1", "z2", + "b0", "b1", "b2", + "c0", "c1", "c2", + "d0", "d1", "d2", + "f0", "f1", "f2", + "i0", "i1", "i2", + "l0", "l1", "l2", + "r0", "r1", "r2", + + "lF0", "lF1", "lF2", + "lP0", "lP1", "lP2", + "lU0", "lU1", "lU2", + "lR0", "lR1", "lR2", + "lT0", "lT1", "lT2", + "lV0", "lV1", "lV2", + + "X0", "X1", "X2", + "O0", "O1", "O2", + + "LF0", "LF1", "LF2", + "LP0", "LP1", "LP2", + "LU0", "LU1", "LU2", + "LR0", "LR1", "LR2", + "LT0", "LT1", "LT2", + "LV0", "LV1", "LV2", + + "E0", "E1", "E2", + "EF0", "EF1", "EF2", + "EP0", "EP1", "EP2", + "EU0", "EU1", "EU2", + "ER0", "ER1", "ER2", + "ET0", "ET1", "ET2", + "EV0", "EV1", "EV2" + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isSynthetic."; + private final static String className = "issynthetic001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "ClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + VirtualMachine vm = debugee.VM(); + boolean canGetSynthetic = vm.canGetSyntheticAttribute(); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List fields; + List nestedTypes; + ReferenceType nestedClass = null; + int totalSyntheticFields = 0; + + log.display("debuger> Value of canGetSyntheticAttribute in current " + + "VM is " + canGetSynthetic); + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Get nested class + try { + nestedTypes = refType.nestedTypes(); + } catch (ObjectCollectedException e) { + log.complain("debuger FAILURE> Cannot get nested types from " + + classToCheckName); + return 2; + } + int totalNestedTypes = nestedTypes.size(); + if (totalNestedTypes == 0) { + log.complain("debuger FAILURE> No nested classes found."); + return 2; + } + nestedClass = (ReferenceType)nestedTypes.get(0); + if (nestedClass == null) { + log.complain("debuger FAILURE> Cannot find nested class."); + return 2; + } + + // Get all fields and check them + try { + fields = nestedClass.fields(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get fields from nested class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalFields = fields.size(); + if (totalFields < 1) { + log.complain("debuger FAILURE> Total number of fields read " + + totalFields); + return 2; + } + log.display("debuger> Total fields in debugee read: " + + totalFields + " total fields in debuger: " + + FIELD_NAME.length); + for (int i = 0; i < fields.size(); i++) { + Field field = (Field)fields.get(i); + String name = field.name(); + boolean isSynthetic; + boolean isRealSynthetic = true; + + try { + isSynthetic = field.isSynthetic(); + + if (!canGetSynthetic) { + log.complain("debuger FAILURE 1> Value of " + + "canGetSyntheticAttribute in current VM is " + + "false, so UnsupportedOperationException was " + + "expected for " + i + " field " + name); + testFailed = true; + continue; + } else { + log.display("debuger> " + i + " field " + name + " with " + + "synthetic value " + isSynthetic + " read " + + "without UnsupportedOperationException."); + } + } catch (UnsupportedOperationException e) { + if (canGetSynthetic) { + log.complain("debuger FAILURE 2> Value of " + + "canGetSyntheticAttribute in current VM is " + + "true, but cannot get synthetic for field " + + "name."); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + } else { + log.display("debuger> UnsupportedOperationException was " + + "thrown while getting isSynthetic for " + i + + " field " + name + " because value " + + "canGetSynthetic is false."); + } + continue; + } + + // Find out if field exists in list of fields + for (int j = 0; j < FIELD_NAME.length; j++) { + String nameFromList = FIELD_NAME[j]; + + if (nameFromList.equals(name)) { + // Field found in list - is not synthetic + + isRealSynthetic = false; + break; + } + } + + if (isRealSynthetic != isSynthetic) { + log.complain("debuger FAILURE 3> Field's " + name + + " synthetic is " + isSynthetic + ", but expected " + + "is " + isRealSynthetic); + testFailed = true; + continue; + } + + if (isSynthetic) { + totalSyntheticFields++; + } + } + + if (totalSyntheticFields == 0) { + log.complain("debuger FAILURE 4> Synthetic fields not found."); + testFailed = true; + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001/TestDescription.java new file mode 100644 index 00000000000..865780a8070 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isSynthetic/issynthetic001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isSynthetic() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public boolean isSynthetic() + * Determines if this TypeComponent is synthetic. Synthetic members are + * generated by the compiler and are not present in the source code for the + * containing class. + * Not all target VMs support this query. See + * VirtualMachine.canGetSyntheticAttribute() to determine if the operation + * is supported. + * Returns: true if this type component is synthetic; false otherwise. + * Throws: java.lang.UnsupportedOperationException - if the target VM cannot + * provide information on synthetic attributes. + * nsk/jdi/TypeComponent/isSynthetic/issynthetic001 checks assertions: + * public java.lang.String isSynthetic() + * 1. Returns true if the operation is supported and the field is synthetic; + * 2. Returns false if the operation is supported and the field is not + * present in the source code for the containing class; + * 3. Throws java.lang.UnsupportedOperationException if the target VM cannot + * provide information on synthetic attributes + * (VirtualMachine.canGetSyntheticAttribute() is false). + * 4. Does not throw java.lang.UnsupportedOperationException if the target + * VM provides information on synthetic attributes + * (VirtualMachine.canGetSyntheticAttribute() is true). + * There are classes ClassToCheck and NestedClass declared within + * ClassToCheck in debugee. So synthetic field (reference to ClassToCheck) + * must exist in NestedClass. + * Debugger gets all fields from NestedClass, gets isSynthetic() value. + * If VirtualMachine.canGetSyntheticAttribute() is false then exception + * java.lang.UnsupportedOperationException must be thrown. Otherwise + * exception is not thrown. + * Then test tries to find field's name in list of fileds that are present + * in the source code. If field is not found, then isSynthetic() value + * expects to be true, otherwise isSynthetic() value expects to be false. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isSynthetic.issynthetic001 + * nsk.jdi.TypeComponent.isSynthetic.issynthetic001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isSynthetic.issynthetic001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java new file mode 100644 index 00000000000..c8abb6a319a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isSynthetic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class issynthetic001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + ClassToCheck classToCheck = new ClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +// User class and interface +class Class {} +interface Inter {} + +class ClassToCheck { + NestedClass nestedClass = new NestedClass(); + + class NestedClass { + // Not-synthetic fields + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + Class X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + Inter E0, E1[]={E0}, E2[][]={E1}; + + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002.java new file mode 100644 index 00000000000..fb684c807c5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isSynthetic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class issynthetic002 { + final static String METHOD_NAME[] = { + "", + "Mv", + "Mz", "Mz1", "Mz2", + "Mb", "Mb1", "Mb2", + "Mc", "Mc1", "Mc2", + "Md", "Md1", "Md2", + "Mf", "Mf1", "Mf2", + "Mi", "Mi1", "Mi2", + "Ml", "Ml1", "Ml2", + "Mr", "Mr1", "Mr2", + + "MvF", "MlF", "MlF1", "MlF2", + "MvN", "MlN", "MlN1", "MlN2", + "MvS", "MlS", "MlS1", "MlS2", + "MvI", "MlI", "MlI1", "MlI2", + "MvY", "MlY", "MlY1", "MlY2", + "MvU", "MlU", "MlU1", "MlU2", + "MvR", "MlR", "MlR1", "MlR2", + "MvP", "MlP", "MlP1", "MlP2", + + "MX", "MX1", "MX2", + "MO", "MO1", "MO2", + + "MLF", "MLF1", "MLF2", + "MLN", "MLN1", "MLN2", + "MLS", "MLS1", "MLS2", + "MLI", "MLI1", "MLI2", + "MLY", "MLY1", "MLY2", + "MLU", "MLU1", "MLU2", + "MLR", "MLR1", "MLR2", + "MLP", "MLP1", "MLP2", + + "ME", "ME1", "ME2", + "MEF", "MEF1", "MEF2", + "MEN", "MEN1", "MEN2", + "MES", "ME1S", "ME2S", + "MEI", "MEI1", "MEI2", + "MEY", "MEY1", "MEY2", + "MEU", "MEU1", "MEU2", + "MER", "MER1", "MER2", + "MEP", "MEP1", "MEP2" + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.isSynthetic."; + private final static String className = "issynthetic002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "issynthetic002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + VirtualMachine vm = debugee.VM(); + boolean canGetSynthetic = vm.canGetSyntheticAttribute(); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List methods; + int totalSyntheticMethods = 0; + + log.display("debuger> Value of canGetSyntheticAttribute in current " + + "VM is " + canGetSynthetic); + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Check methods from debuggee + try { + methods = refType.methods(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get methods from " + + classToCheckName); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalMethods = methods.size(); + if (totalMethods < 1) { + log.complain("debuger FAILURE> Total number of methods in debuggee " + + "read " + totalMethods); + return 2; + } + log.display("debuger> Total methods in debuggee read: " + + totalMethods + " total methods in debuger: " + + METHOD_NAME.length); + for (int i = 0; i < totalMethods; i++) { + Method method = (Method)methods.get(i); + String name = method.name(); + boolean isSynthetic; + boolean isRealSynthetic = true; + + try { + isSynthetic = method.isSynthetic(); + + if (!canGetSynthetic) { + log.complain("debuger FAILURE 1> Value of " + + "canGetSyntheticAttribute in current VM is " + + "false, so UnsupportedOperationException was " + + "expected for " + i + " method " + name); + testFailed = true; + continue; + } else { + log.display("debuger> " + i + " method " + name + " with " + + "synthetic value " + isSynthetic + " read " + + "without UnsupportedOperationException"); + } + } catch (UnsupportedOperationException e) { + if (canGetSynthetic) { + log.complain("debuger FAILURE 2> Value of " + + "canGetSyntheticAttribute in current VM is " + + "true, but cannot get synthetic for method " + + "name."); + log.complain("debuger FAILURE 2> Exception: " + e); + testFailed = true; + } else { + log.display("debuger> UnsupportedOperationException was " + + "thrown while getting isSynthetic for " + i + + " method " + name + " because value " + + "canGetSynthetic is false."); + } + continue; + } + + // Find out if method exists in list of methods + for (int j = 0; j < METHOD_NAME.length; j++) { + String nameFromList = METHOD_NAME[j]; + + if (nameFromList.equals(name)) { + // Method found in list - is not synthetic + + isRealSynthetic = false; + break; + } + } + + if (isRealSynthetic != isSynthetic) { + log.complain("debuger FAILURE 3> Method's " + name + + " synthetic is " + isSynthetic + ", but expected " + + "is " + isRealSynthetic); + testFailed = true; + continue; + } + + if (isSynthetic) { + totalSyntheticMethods++; + } + } + + if (totalSyntheticMethods == 0) { + log.complain("debuger FAILURE 4> Synthetic methods not found."); + testFailed = true; + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002/TestDescription.java new file mode 100644 index 00000000000..c03394d8160 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/isSynthetic/issynthetic002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the isSynthetic() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public boolean isSynthetic() + * Determines if this TypeComponent is synthetic. Synthetic members are + * generated by the compiler and are not present in the source code for the + * containing class. + * Not all target VMs support this query. See + * VirtualMachine.canGetSyntheticAttribute() to determine if the operation + * is supported. + * Returns: true if this type component is synthetic; false otherwise. + * Throws: java.lang.UnsupportedOperationException - if the target VM cannot + * provide information on synthetic attributes. + * nsk/jdi/TypeComponent/isSynthetic/issynthetic002 checks assertions: + * public java.lang.String isSynthetic() + * 1. Returns true if the operation is supported and the method is synthetic; + * 2. Returns false if the operation is supported and the method is not + * present in the source code for the containing class; + * 3. Throws java.lang.UnsupportedOperationException if the target VM cannot + * provide information on synthetic attributes + * (VirtualMachine.canGetSyntheticAttribute() is false). + * 4. Does not throw java.lang.UnsupportedOperationException if the target + * VM provides information on synthetic attributes + * (VirtualMachine.canGetSyntheticAttribute() is true). + * There are ClassToCheck and NestedClass declared within ClassToCheck in + * debugee. Nested class uses two private variables from ClassToCheck, so + * synthetic methods (two for each variable) must exist in ClassToCheck. + * Debugger gets all methods from debuggee, gets isSynthetic() value. + * If VirtualMachine.canGetSyntheticAttribute() is false then exception + * java.lang.UnsupportedOperationException must be thrown. Otherwise + * exception is not thrown. + * Then test tries to find method's name in list of methods that are present + * in the source code. If method is not found, then isSynthetic() value + * expects to be true, otherwise isSynthetic() value expects to be false. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.isSynthetic.issynthetic002 + * nsk.jdi.TypeComponent.isSynthetic.issynthetic002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.isSynthetic.issynthetic002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002a.java new file mode 100644 index 00000000000..710b8e58859 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002a.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.isSynthetic; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class issynthetic002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + issynthetic002aClassToCheck classToCheck = new issynthetic002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class issynthetic002aClassToCheck { + // Not-synthetic methods + + // User class and interface + class Class {} + interface Inter {} + + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + final void MvF() {}; + final long MlF(long l) { return l; }; + final long[] MlF1(long l[]) { return l; }; + final long[][] MlF2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + Class MX(Class X) { return X; }; + Class[] MX1(Class X[]) { return X; }; + Class[][] MX2(Class X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + final Long MLF(Long L) { return L; }; + final Long[] MLF1(Long[] L) { return L; }; + final Long[][] MLF2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long L[]) { return L; }; + static Long[][] MLS2(Long L[][]) { return L; }; + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + Inter ME(Inter E) { return E; }; + Inter[] ME1(Inter[] E) { return E; }; + Inter[][] ME2(Inter[][] E) { return E; }; + + final Inter MEF(Inter E) { return E; }; + final Inter[] MEF1(Inter[] E) { return E; }; + final Inter[][] MEF2(Inter[][] E) { return E; }; + native Inter MEN(Inter E); + native Inter[] MEN1(Inter[] E); + native Inter[][] MEN2(Inter[][] E); + static Inter MES(Inter E) { return E; }; + static Inter[] ME1S(Inter[] E) { return E; }; + static Inter[][] ME2S(Inter[][] E) { return E; }; + strictfp Inter MEI(Inter E) { return E; }; + strictfp Inter[] MEI1(Inter[] E) { return E; }; + strictfp Inter[][] MEI2(Inter[][] E) { return E; }; + synchronized Inter MEY(Inter E) { return E; }; + synchronized Inter[] MEY1(Inter[] E) { return E; }; + synchronized Inter[][] MEY2(Inter[][] E) { return E; }; + public Inter MEU(Inter E) { return E; }; + public Inter[] MEU1(Inter[] E) { return E; }; + public Inter[][] MEU2(Inter[][] E) { return E; }; + protected Inter MER(Inter E) { return E; }; + protected Inter[] MER1(Inter[] E) { return E; }; + protected Inter[][] MER2(Inter[][] E) { return E; }; + private Inter MEP(Inter E) { return E; }; + private Inter[] MEP1(Inter[] E) { return E; }; + private Inter[][] MEP2(Inter[][] E) { return E; }; + + // Synthetic methods + + private int i; + private String s; + + class NestedClass { + boolean MS(String str) { + // Method uses private variable s from ClassToCheck, + // so two synthetic methods must appear in ClassToCheck + + s = s + "NestedClass"; + return s.equals(str); + }; + + boolean Mi(int j) { + // Method uses private variable i from ClassToCheck, + // so two synthetic methods must appear in ClassToCheck + + i = i + 1; + return (i == j); + }; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001.java new file mode 100644 index 00000000000..7d12ab2471f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class name001 { + final static String FIELD_NAME[] = { + "z0", "z1", "z2", + "b0", "b1", "b2", + "c0", "c1", "c2", + "d0", "d1", "d2", + "f0", "f1", "f2", + "i0", "i1", "i2", + "l0", "l1", "l2", + "r0", "r1", "r2", + + "lF0", "lF1", "lF2", + "lP0", "lP1", "lP2", + "lU0", "lU1", "lU2", + "lR0", "lR1", "lR2", + "l0S", "l1S", "l2S", + "lT0", "lT1", "lT2", + "lV0", "lV1", "lV2", + + "X0", "X1", "X2", + "O0", "O1", "O2", + + "LF0", "LF1", "LF2", + "LP0", "LP1", "LP2", + "LU0", "LU1", "LU2", + "LR0", "LR1", "LR2", + "L0S", "L1S", "L2S", + "LT0", "LT1", "LT2", + "LV0", "LV1", "LV2", + + "E0", "E1", "E2", + "EF0", "EF1", "EF2", + "EP0", "EP1", "EP2", + "EU0", "EU1", "EU2", + "ER0", "ER1", "ER2", + "E0S", "E1S", "E2S", + "ET0", "ET1", "ET2", + "EV0", "EV1", "EV2" + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.name."; + private final static String className = "name001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "ClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + FIELD_NAME.length); + // Check all fields from debugee + for (int i = 0; i < FIELD_NAME.length; i++) { + Field field; + String name; + + try { + field = refType.fieldByName(FIELD_NAME[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + FIELD_NAME[i]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + name = field.name(); + if (name == null) { + log.complain("debuger FAILURE 2> Name is null for " + i + + " field (" + FIELD_NAME[i] + ")"); + testFailed = true; + continue; + } + log.display("debuger> " + i + " name of field (" + FIELD_NAME[i] + + ") " + name + " read."); + if (!name.equals(FIELD_NAME[i])) { + log.complain("debuger FAILURE 3> Returned name for field (" + + FIELD_NAME[i] + ") is " + name); + testFailed = true; + continue; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001/TestDescription.java new file mode 100644 index 00000000000..986d0e2ca01 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/name/name001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the name() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public java.lang.String name() + * Gets the name of this type component. + * Note: for fields, this is the field name; for methods, this is the + * method name; for constructors, this is ; for static + * initializers, this is . + * Returns: a string containing the name. + * nsk/jdi/TypeComponent/name/name001 checks assertion: + * public java.lang.String name() + * 1. Returns field name for a field. + * Debugger gets each field from debuggee calling by name and then checks + * if method name() returns the same name of the field. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.name.name001 + * nsk.jdi.TypeComponent.name.name001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001a.java new file mode 100644 index 00000000000..70140884761 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001a.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class name001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + ClassToCheck classToCheck = new ClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class ClassToCheck { + // User class and interface + class Class {} + interface Inter {} + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + static long l0S, l1S[]={l0S}, l2S[][]={l1S}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + Class X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + static Long L0S, L1S[]={L0S}, L2S[][]={L1S}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + Inter E0, E1[]={E0}, E2[][]={E1}; + + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + static Inter E0S, E1S[]={E0S}, E2S[][]={E1S}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002.java new file mode 100644 index 00000000000..fdc3cb3c57b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class name002 { + final static String METHOD_NAME[] = { + "Mv", + "Mz", "Mz1", "Mz2", + "Mb", "Mb1", "Mb2", + "Mc", "Mc1", "Mc2", + "Md", "Md1", "Md2", + "Mf", "Mf1", "Mf2", + "Mi", "Mi1", "Mi2", + "Ml", "Ml1", "Ml2", + "Mr", "Mr1", "Mr2", + + "MvF", "MlF", "MlF1", "MlF2", + "MvN", "MlN", "MlN1", "MlN2", + "MvS", "MlS", "MlS1", "MlS2", + "MvI", "MlI", "MlI1", "MlI2", + "MvY", "MlY", "MlY1", "MlY2", + "MvU", "MlU", "MlU1", "MlU2", + "MvR", "MlR", "MlR1", "MlR2", + "MvP", "MlP", "MlP1", "MlP2", + + "MX", "MX1", "MX2", + "MO", "MO1", "MO2", + + "MLF", "MLF1", "MLF2", + "MLN", "MLN1", "MLN2", + "MLS", "MLS1", "MLS2", + "MLI", "MLI1", "MLI2", + "MLY", "MLY1", "MLY2", + "MLU", "MLU1", "MLU2", + "MLR", "MLR1", "MLR2", + "MLP", "MLP1", "MLP2", + + "ME", "ME1", "ME2", + "MEF", "MEF1", "MEF2", + "MEN", "MEN1", "MEN2", + "MES", "ME1S", "ME2S", + "MEI", "MEI1", "MEI2", + "MEY", "MEY1", "MEY2", + "MEU", "MEU1", "MEU2", + "MER", "MER1", "MER2", + "MEP", "MEP1", "MEP2" + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.name."; + private final static String className = "name002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "name002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Check all methods from debugee + for (int i = 0; i < METHOD_NAME.length; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String name; + + try { + listOfMethods = refType.methodsByName(METHOD_NAME[i]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get method by name " + + METHOD_NAME[i]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + METHOD_NAME[i] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + name = method.name(); + if (name == null) { + log.complain("debuger FAILURE 3> Name is null for " + i + + " method (" + METHOD_NAME[i] + ")"); + testFailed = true; + continue; + } + log.display("debuger> " + i + " name of method (" + METHOD_NAME[i] + + ") " + name + " read."); + if (!name.equals(METHOD_NAME[i])) { + log.complain("debuger FAILURE 4> Returned name for method (" + + METHOD_NAME[i] + ") is " + name); + testFailed = true; + continue; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002/TestDescription.java new file mode 100644 index 00000000000..1c92e4b20dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/name/name002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the name() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public java.lang.String name() + * Gets the name of this type component. + * Note: for fields, this is the field name; for methods, this is the + * method name; for constructors, this is ; for static + * initializers, this is . + * Returns: a string containing the name. + * nsk/jdi/TypeComponent/name/name002 checks assertion: + * public java.lang.String name() + * 1. Returns method name for a method. + * Debugger gets each method from debuggee calling by name and then checks + * if name() returns the same name of the method. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.name.name002 + * nsk.jdi.TypeComponent.name.name002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.name.name002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002a.java new file mode 100644 index 00000000000..6ef98dd6a8b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name002a.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class name002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + name002aClassToCheck classToCheck = new name002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class name002aClassToCheck { + // User class and interface + class Class {} + interface Inter {} + + void Mv() {}; + boolean Mz(boolean z) { return z; }; + boolean[] Mz1(boolean z[]) { return z; }; + boolean[][] Mz2(boolean z[][]) { return z; }; + byte Mb(byte b) { return b; }; + byte[] Mb1(byte b[]) { return b; }; + byte[][] Mb2(byte b[][]) { return b; }; + char Mc(char c) { return c; }; + char[] Mc1(char c[]) { return c; }; + char[][] Mc2(char c[][]) { return c; }; + double Md(double d) { return d; }; + double[] Md1(double d[]) { return d; }; + double[][] Md2(double d[][]) { return d; }; + float Mf(float f) { return f; }; + float[] Mf1(float f[]) { return f; }; + float[][] Mf2(float f[][]) { return f; }; + int Mi(int i) { return i; }; + int[] Mi1(int i[]) { return i; }; + int[][] Mi2(int i[][]) { return i; }; + long Ml(long l) { return l; }; + long[] Ml1(long l[]) { return l; }; + long[][] Ml2(long l[][]) { return l; }; + short Mr(short r) { return r; }; + short[] Mr1(short r[]) { return r; }; + short[][] Mr2(short r[][]) { return r; }; + + final void MvF() {}; + final long MlF(long l) { return l; }; + final long[] MlF1(long l[]) { return l; }; + final long[][] MlF2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + Class MX(Class X) { return X; }; + Class[] MX1(Class X[]) { return X; }; + Class[][] MX2(Class X[][]) { return X; }; + Object MO(Object O) { return O; }; + Object[] MO1(Object[] O) { return O; }; + Object[][] MO2(Object[][] O) { return O; }; + + final Long MLF(Long L) { return L; }; + final Long[] MLF1(Long[] L) { return L; }; + final Long[][] MLF2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long L[]) { return L; }; + static Long[][] MLS2(Long L[][]) { return L; }; + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + Inter ME(Inter E) { return E; }; + Inter[] ME1(Inter[] E) { return E; }; + Inter[][] ME2(Inter[][] E) { return E; }; + + final Inter MEF(Inter E) { return E; }; + final Inter[] MEF1(Inter[] E) { return E; }; + final Inter[][] MEF2(Inter[][] E) { return E; }; + native Inter MEN(Inter E); + native Inter[] MEN1(Inter[] E); + native Inter[][] MEN2(Inter[][] E); + static Inter MES(Inter E) { return E; }; + static Inter[] ME1S(Inter[] E) { return E; }; + static Inter[][] ME2S(Inter[][] E) { return E; }; + strictfp Inter MEI(Inter E) { return E; }; + strictfp Inter[] MEI1(Inter[] E) { return E; }; + strictfp Inter[][] MEI2(Inter[][] E) { return E; }; + synchronized Inter MEY(Inter E) { return E; }; + synchronized Inter[] MEY1(Inter[] E) { return E; }; + synchronized Inter[][] MEY2(Inter[][] E) { return E; }; + public Inter MEU(Inter E) { return E; }; + public Inter[] MEU1(Inter[] E) { return E; }; + public Inter[][] MEU2(Inter[][] E) { return E; }; + protected Inter MER(Inter E) { return E; }; + protected Inter[] MER1(Inter[] E) { return E; }; + protected Inter[][] MER2(Inter[][] E) { return E; }; + private Inter MEP(Inter E) { return E; }; + private Inter[] MEP1(Inter[] E) { return E; }; + private Inter[][] MEP2(Inter[][] E) { return E; }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003.java new file mode 100644 index 00000000000..9eb4f553dd1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class name003 { + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.name."; + private final static String className = "name003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "name003aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List methods; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Get all methods, find constructors and static initializers and + // check them + try { + methods = refType.allMethods(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get methods from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalMethods = methods.size(); + if (totalMethods < 1) { + log.complain("debuger FAILURE> Total number of methods read " + + totalMethods); + return 2; + } + log.display("debuger> Total methods found: " + totalMethods); + Iterator methodsIterator = methods.iterator(); + for (int i = 0; methodsIterator.hasNext(); i++) { + Method method = (Method)methodsIterator.next(); + String decTypeName = method.declaringType().name(); + String name = method.name(); + + log.display("debuger> " + i + " method " + name + " from " + + decTypeName + " read."); + if (method.isConstructor()) { + // For constructors TypeComponent.name() is "" + if (!name.equals("")) { + log.complain("debuger FAILURE 1> Constructor from " + + decTypeName + " is read with name " + name + + ", but name should be "); + testFailed = true; + continue; + } else { + log.display("debuger> Constructor " + name + " from " + + decTypeName + " checked."); + } + } + if (method.isStaticInitializer()) { + // For static initializers TypeComponent.name() is "" + if (!name.equals("")) { + log.complain("debuger FAILURE 2> Static initializer from " + + decTypeName + " is read with name " + name + + ", but name should be "); + testFailed = true; + continue; + } else { + log.display("debuger> Static initializer " + name + + " from " + decTypeName + " checked."); + } + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003/TestDescription.java new file mode 100644 index 00000000000..e6f494aaff4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/name/name003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the name() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public java.lang.String name() + * Gets the name of this type component. + * Note: for fields, this is the field name; for methods, this is the + * method name; for constructors, this is ; for static + * initializers, this is . + * Returns: a string containing the name. + * nsk/jdi/TypeComponent/name/name003 checks assertions: + * public java.lang.String name() + * 1. Returns "" for a constructor; + * 2. Returns "" for a static initializer. + * Debugger gets all methods from debuggee, finds only constructors and + * static initializers and then checks if name() returns "" for + * constructors and "" for static initializers. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.name.name003 + * nsk.jdi.TypeComponent.name.name003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.name.name003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003a.java new file mode 100644 index 00000000000..a4e96e9e6eb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003a.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class name003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + name003aClassToCheck classToCheck = new name003aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class name003aClassToCheck extends name003aSuperClass { + name003aClassToCheck() {}; + public name003aClassToCheck(long l) {}; + private name003aClassToCheck(Object obj) {}; + protected name003aClassToCheck(long[] l) {}; + + static int ci; + static Long cL; + static long[] cl = new long[10]; + + static { ci = 1; } + static { cL = new Long(1l); } + static { + for (int i = 0; i < 10; i++) { + cl[i] = (long)i; + } + } +} + +class name003aSuperClass { + name003aSuperClass() {}; + public name003aSuperClass(long l) {}; + private name003aSuperClass(Object obj) {}; + protected name003aSuperClass(long[] l) {}; + + static boolean sb; + static Object sO; + static float[] sf = new float[10]; + + static { sb = true; } + static { sO = new Object(); } + static { + for (int i = 0; i < 10; i++) { + sf[i] = (float)i; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001.java new file mode 100644 index 00000000000..b44ac0265d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.io.*; + +public class sign001 { + final static int TOTAL_FIELDS = 96; + final static String FIELD_NAME[][] = { + {"z0", "Z"}, + {"z1", "[Z"}, + {"z2", "[[Z"}, + {"b0", "B"}, + {"b1", "[B"}, + {"b2", "[[B"}, + {"c0", "C"}, + {"c1", "[C"}, + {"c2", "[[C"}, + {"d0", "D"}, + {"d1", "[D"}, + {"d2", "[[D"}, + {"f0", "F"}, + {"f1", "[F"}, + {"f2", "[[F"}, + {"i0", "I"}, + {"i1", "[I"}, + {"i2", "[[I"}, + {"l0", "J"}, + {"l1", "[J"}, + {"l2", "[[J"}, + {"r0", "S"}, + {"r1", "[S"}, + {"r2", "[[S"}, + {"lF0", "J"}, + {"lF1", "[J"}, + {"lF2", "[[J"}, + {"lP0", "J"}, + {"lP1", "[J"}, + {"lP2", "[[J"}, + {"lU0", "J"}, + {"lU1", "[J"}, + {"lU2", "[[J"}, + {"lR0", "J"}, + {"lR1", "[J"}, + {"lR2", "[[J"}, + {"l0S", "J"}, + {"l1S", "[J"}, + {"l2S", "[[J"}, + {"lT0", "J"}, + {"lT1", "[J"}, + {"lT2", "[[J"}, + {"lV0", "J"}, + {"lV1", "[J"}, + {"lV2", "[[J"}, + {"X0", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Class;"}, + {"X1", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Class;"}, + {"X2", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Class;"}, + {"O0", "Ljava/lang/Object;"}, + {"O1", "[Ljava/lang/Object;"}, + {"O2", "[[Ljava/lang/Object;"}, + {"LF0", "Ljava/lang/Long;"}, + {"LF1", "[Ljava/lang/Long;"}, + {"LF2", "[[Ljava/lang/Long;"}, + {"LP0", "Ljava/lang/Long;"}, + {"LP1", "[Ljava/lang/Long;"}, + {"LP2", "[[Ljava/lang/Long;"}, + {"LU0", "Ljava/lang/Long;"}, + {"LU1", "[Ljava/lang/Long;"}, + {"LU2", "[[Ljava/lang/Long;"}, + {"LR0", "Ljava/lang/Long;"}, + {"LR1", "[Ljava/lang/Long;"}, + {"LR2", "[[Ljava/lang/Long;"}, + {"L0S", "Ljava/lang/Long;"}, + {"L1S", "[Ljava/lang/Long;"}, + {"L2S", "[[Ljava/lang/Long;"}, + {"LT0", "Ljava/lang/Long;"}, + {"LT1", "[Ljava/lang/Long;"}, + {"LT2", "[[Ljava/lang/Long;"}, + {"LV0", "Ljava/lang/Long;"}, + {"LV1", "[Ljava/lang/Long;"}, + {"LV2", "[[Ljava/lang/Long;"}, + {"E0", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"E1", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"E2", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EF0", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EF1", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EF2", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EP0", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EP1", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EP2", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EU0", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EU1", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EU2", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"ER0", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"ER1", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"ER2", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"E0S", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"E1S", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"E2S", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"ET0", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"ET1", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"ET2", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EV0", "Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EV1", "[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"}, + {"EV2", "[[Lnsk/jdi/TypeComponent/signature/ClassToCheck$Inter;"} + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.signature."; + private final static String className = "sign001"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "ClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + log.display("debuger> Total fields in debugee read: " + + refType.allFields().size() + " total fields in debuger: " + + TOTAL_FIELDS); + // Check all fields from debugee + for (int i = 0; i < TOTAL_FIELDS; i++) { + Field field; + String signature; + String realSign; + + try { + field = refType.fieldByName(FIELD_NAME[i][0]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get field by name " + + FIELD_NAME[i][0]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + signature = field.signature(); + realSign = FIELD_NAME[i][1]; + log.display("debuger> " + i + " field (" + FIELD_NAME[i][0] + + ") with signature " + signature + " read."); + if (!realSign.equals(signature)) { + log.complain("debuger FAILURE 2> Returned signature for field (" + + FIELD_NAME[i][0] + ") is " + signature + + ", expected " + realSign); + testFailed = true; + continue; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001/TestDescription.java new file mode 100644 index 00000000000..48e44b632f8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/signature/sign001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the signature() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public java.lang.String signature() + * Gets the JNI-style signature for this type component. The signature is + * encoded type information as defined in the JNI documentation. It is a + * convenient, compact format for for manipulating type information + * internally, not necessarily for display to an end user. See + * Field.typeName() and Method.returnTypeName() for ways to help get a more + * readable representation of the type. + * Returns: a string containing the signature + * See Also: Type Signatures + * nsk/jdi/TypeComponent/signature/signature001 checks assertion: + * public java.lang.String signature() + * 1. Gets the JNI-style signature for a field. + * Debugger gets each field from debuggee calling by name and then checks + * if method signature() returns the expected value for the field. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.signature.sign001 + * nsk.jdi.TypeComponent.signature.sign001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.signature.sign001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001a.java new file mode 100644 index 00000000000..7202aa45494 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001a.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class sign001a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + ClassToCheck classToCheck = new ClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class ClassToCheck { + // User class and interface + class Class {} + interface Inter {} + + boolean z0, z1[]={z0}, z2[][]={z1}; + byte b0, b1[]={b0}, b2[][]={b1}; + char c0, c1[]={c0}, c2[][]={c1}; + double d0, d1[]={d0}, d2[][]={d1}; + float f0, f1[]={f0}, f2[][]={f1}; + int i0, i1[]={i0}, i2[][]={i1}; + long l0, l1[]={l0}, l2[][]={l1}; + short r0, r1[]={r0}, r2[][]={r1}; + + final long lF0 = 1l, lF1[]={lF0}, lF2[][]={lF1}; + private long lP0, lP1[]={lP0}, lP2[][]={lP1}; + public long lU0, lU1[]={lU0}, lU2[][]={lU1}; + protected long lR0, lR1[]={lR0}, lR2[][]={lR1}; + static long l0S, l1S[]={l0S}, l2S[][]={l1S}; + transient long lT0, lT1[]={lT0}, lT2[][]={lT1}; + volatile long lV0, lV1[]={lV0}, lV2[][]={lV1}; + + Class X0, X1[]={X0}, X2[][]={X1}; + Object O0, O1[]={O0}, O2[][]={O1}; + + final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; + public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; + protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; + static Long L0S, L1S[]={L0S}, L2S[][]={L1S}; + transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; + volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; + + Inter E0, E1[]={E0}, E2[][]={E1}; + + final Inter EF0 = null, EF1[]={EF0}, EF2[][]={EF1}; + private Inter EP0, EP1[]={EP0}, EP2[][]={EP1}; + public Inter EU0, EU1[]={EU0}, EU2[][]={EU1}; + protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; + static Inter E0S, E1S[]={E0S}, E2S[][]={E1S}; + transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; + volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002.java new file mode 100644 index 00000000000..3072849d5b2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class sign002 { + final static int TOTAL_METHODS = 114; + final static String METHOD_NAME[][] = { + {"Mv", "()V"}, + {"Mz", "(Z[[S)Z"}, + {"Mz1", "([ZZ)[Z"}, + {"Mz2", "([[Z[Z)[[Z"}, + {"Mb", "(B[[Z)B"}, + {"Mb1", "([BB)[B"}, + {"Mb2", "([[B[B)[[B"}, + {"Mc", "(C[[B)C"}, + {"Mc1", "([CC)[C"}, + {"Mc2", "([[C[C)[[C"}, + {"Md", "(D[[C)D"}, + {"Md1", "([DD)[D"}, + {"Md2", "([[D[D)[[D"}, + {"Mf", "(F[[D)F"}, + {"Mf1", "([FF)[F"}, + {"Mf2", "([[F[F)[[F"}, + {"Mi", "(I[[F)I"}, + {"Mi1", "([II)[I"}, + {"Mi2", "([[I[I)[[I"}, + {"Ml", "(J[[I)J"}, + {"Ml1", "([JJ)[J"}, + {"Ml2", "([[J[J)[[J"}, + {"Mr", "(S[[J)S"}, + {"Mr1", "([SS)[S"}, + {"Mr2", "([[S[S)[[S"}, + {"MvF", "()V"}, + {"MlF", "(J)J"}, + {"MlF1", "([J)[J"}, + {"MlF2", "([[J)[[J"}, + {"MvN", "()V"}, + {"MlN", "(J)J"}, + {"MlN1", "([J)[J"}, + {"MlN2", "([[J)[[J"}, + {"MvS", "()V"}, + {"MlS", "(J)J"}, + {"MlS1", "([J)[J"}, + {"MlS2", "([[J)[[J"}, + {"MvI", "()V"}, + {"MlI", "(J)J"}, + {"MlI1", "([J)[J"}, + {"MlI2", "([[J)[[J"}, + {"MvY", "()V"}, + {"MlY", "(J)J"}, + {"MlY1", "([J)[J"}, + {"MlY2", "([[J)[[J"}, + {"MvU", "()V"}, + {"MlU", "(J)J"}, + {"MlU1", "([J)[J"}, + {"MlU2", "([[J)[[J"}, + {"MvR", "()V"}, + {"MlR", "(J)J"}, + {"MlR1", "([J)[J"}, + {"MlR2", "([[J)[[J"}, + {"MvP", "()V"}, + {"MlP", "(J)J"}, + {"MlP1", "([J)[J"}, + {"MlP2", "([[J)[[J"}, + {"MX", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;[[Ljava/lang/Object;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;"}, + {"MX1", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;"}, + {"MX2", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;"}, + {"MO", "(Ljava/lang/Object;[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Class;)Ljava/lang/Object;"}, + {"MO1", "([Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;"}, + {"MO2", "([[Ljava/lang/Object;[Ljava/lang/Object;)[[Ljava/lang/Object;"}, + {"MLF", "(Ljava/lang/Long;)Ljava/lang/Long;"}, + {"MLF1", "([Ljava/lang/Long;)[Ljava/lang/Long;"}, + {"MLF2", "([[Ljava/lang/Long;)[[Ljava/lang/Long;"}, + {"MLN", "(Ljava/lang/Long;)Ljava/lang/Long;"}, + {"MLN1", "([Ljava/lang/Long;)[Ljava/lang/Long;"}, + {"MLN2", "([[Ljava/lang/Long;)[[Ljava/lang/Long;"}, + {"MLS", "(Ljava/lang/Long;)Ljava/lang/Long;"}, + {"MLS1", "([Ljava/lang/Long;)[Ljava/lang/Long;"}, + {"MLS2", "([[Ljava/lang/Long;)[[Ljava/lang/Long;"}, + {"MLI", "(Ljava/lang/Long;)Ljava/lang/Long;"}, + {"MLI1", "([Ljava/lang/Long;)[Ljava/lang/Long;"}, + {"MLI2", "([[Ljava/lang/Long;)[[Ljava/lang/Long;"}, + {"MLY", "(Ljava/lang/Long;)Ljava/lang/Long;"}, + {"MLY1", "([Ljava/lang/Long;)[Ljava/lang/Long;"}, + {"MLY2", "([[Ljava/lang/Long;)[[Ljava/lang/Long;"}, + {"MLU", "(Ljava/lang/Long;)Ljava/lang/Long;"}, + {"MLU1", "([Ljava/lang/Long;)[Ljava/lang/Long;"}, + {"MLU2", "([[Ljava/lang/Long;)[[Ljava/lang/Long;"}, + {"MLR", "(Ljava/lang/Long;)Ljava/lang/Long;"}, + {"MLR1", "([Ljava/lang/Long;)[Ljava/lang/Long;"}, + {"MLR2", "([[Ljava/lang/Long;)[[Ljava/lang/Long;"}, + {"MLP", "(Ljava/lang/Long;)Ljava/lang/Long;"}, + {"MLP1", "([Ljava/lang/Long;)[Ljava/lang/Long;"}, + {"MLP2", "([[Ljava/lang/Long;)[[Ljava/lang/Long;"}, + {"ME", "(IJLnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"ME1", "([I[Ljava/lang/Long;[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"ME2", "([[I[[Ljava/lang/Long;[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEF", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEF1", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEF2", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEN", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEN1", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEN2", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MES", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"ME1S", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"ME2S", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEI", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEI1", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEI2", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEY", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEY1", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEY2", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEU", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEU1", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEU2", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MER", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MER1", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MER2", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEP", "(Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEP1", "([Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + {"MEP2", "([[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;)[[Lnsk/jdi/TypeComponent/signature/sign002aClassToCheck$Inter;"}, + }; + + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.signature."; + private final static String className = "sign002"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "sign002aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Check all methods from debugee + for (int i = 0; i < TOTAL_METHODS; i++) { + Method method; + List listOfMethods; + int totalMethodsByName; + String signature; + String realSign; + + try { + listOfMethods = refType.methodsByName(METHOD_NAME[i][0]); + } catch (Exception e) { + log.complain("debuger FAILURE 1> Can't get method by name " + + METHOD_NAME[i][0]); + log.complain("debuger FAILURE 1> Exception: " + e); + testFailed = true; + continue; + } + totalMethodsByName = listOfMethods.size(); + if (totalMethodsByName != 1) { + log.complain("debuger FAILURE 2> Number of methods by name " + + METHOD_NAME[i][0] + " is " + totalMethodsByName + + ", should be 1."); + testFailed = true; + continue; + } + method = (Method)listOfMethods.get(0); + signature = method.signature(); + realSign = METHOD_NAME[i][1]; + log.display("debuger> " + i + " method (" + METHOD_NAME[i][0] + + ") with signature " + signature + " read."); + if (!realSign.equals(signature)) { + log.complain("debuger FAILURE 3> Returned signature for method " + + " (" + METHOD_NAME[i][0] + ") is " + signature + + " expected " + realSign); + testFailed = true; + continue; + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002/TestDescription.java new file mode 100644 index 00000000000..91247df05cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/signature/sign002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the signature() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public java.lang.String signature() + * Gets the JNI-style signature for this type component. The signature is + * encoded type information as defined in the JNI documentation. It is a + * convenient, compact format for for manipulating type information + * internally, not necessarily for display to an end user. See + * Field.typeName() and Method.returnTypeName() for ways to help get a more + * readable representation of the type. + * Returns: a string containing the signature + * See Also: Type Signatures + * nsk/jdi/TypeComponent/signature/signature002 checks assertion: + * public java.lang.String signature() + * 1. Gets the JNI-style signature for a method. + * Debugger gets each method from debuggee calling by name and then checks + * if signature() returns the expected value for the method. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.signature.sign002 + * nsk.jdi.TypeComponent.signature.sign002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.signature.sign002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002a.java new file mode 100644 index 00000000000..eebb277a96c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign002a.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class sign002a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + sign002aClassToCheck classToCheck = new sign002aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class sign002aClassToCheck { + // User class and interface + class Class {} + interface Inter {} + + void Mv() {}; + boolean Mz (boolean z, short r2[][]) { return z; }; + boolean[] Mz1(boolean z1[], boolean z) { return z1; }; + boolean[][] Mz2(boolean z2[][], boolean z1[]) { return z2; }; + byte Mb (byte b, boolean z2[][]) { return b; }; + byte[] Mb1(byte b1[], byte b) { return b1; }; + byte[][] Mb2(byte b2[][], byte b1[]) { return b2; }; + char Mc (char c, byte b2[][]) { return c; }; + char[] Mc1(char c1[], char c) { return c1; }; + char[][] Mc2(char c2[][], char c1[]) { return c2; }; + double Md (double d, char c2[][]) { return d; }; + double[] Md1(double d1[], double d) { return d1; }; + double[][] Md2(double d2[][], double d1[]) { return d2; }; + float Mf (float f, double d2[][]) { return f; }; + float[] Mf1(float f1[], float f) { return f1; }; + float[][] Mf2(float f2[][], float f1[]) { return f2; }; + int Mi (int i, float f2[][]) { return i; }; + int[] Mi1(int i1[], int i) { return i1; }; + int[][] Mi2(int i2[][], int i1[]) { return i2; }; + long Ml (long l, int i2[][]) { return l; }; + long[] Ml1(long l1[], long l) { return l1; }; + long[][] Ml2(long l2[][], long l1[]) { return l2; }; + short Mr (short r, long l2[][]) { return r; }; + short[] Mr1(short r1[], short r) { return r1; }; + short[][] Mr2(short r2[][], short r1[]) { return r2; }; + + final void MvF() {}; + final long MlF(long l) { return l; }; + final long[] MlF1(long l[]) { return l; }; + final long[][] MlF2(long l[][]) { return l; }; + native void MvN(); + native long MlN(long l); + native long[] MlN1(long l[]); + native long[][] MlN2(long l[][]); + static void MvS() {}; + static long MlS(long l) { return l; }; + static long[] MlS1(long l[]) { return l; }; + static long[][] MlS2(long l[][]) { return l; }; + strictfp void MvI() {}; + strictfp long MlI(long l) { return l; }; + strictfp long[] MlI1(long l[]) { return l; }; + strictfp long[][] MlI2(long l[][]) { return l; }; + synchronized void MvY() {}; + synchronized long MlY(long l) { return l; }; + synchronized long[] MlY1(long l[]) { return l; }; + synchronized long[][] MlY2(long l[][]) { return l; }; + public void MvU() {}; + public long MlU(long l) { return l; }; + public long[] MlU1(long l[]) { return l; }; + public long[][] MlU2(long l[][]) { return l; }; + protected void MvR() {}; + protected long MlR(long l) { return l; }; + protected long[] MlR1(long l[]) { return l; }; + protected long[][] MlR2(long l[][]) { return l; }; + private void MvP() {}; + private long MlP(long l) { return l; }; + private long[] MlP1(long l[]) { return l; }; + private long[][] MlP2(long l[][]) { return l; }; + + Class MX (Class X, Object[][] O2) { return X; }; + Class[] MX1(Class X1[], Class X) { return X1; }; + Class[][] MX2(Class X2[][], Class X1[]) { return X2; }; + Object MO (Object O, Class X2[][]) { return O; }; + Object[] MO1(Object[] O1, Object O) { return O1; }; + Object[][] MO2(Object[][] O2, Object[] O1) { return O2; }; + + final Long MLF(Long L) { return L; }; + final Long[] MLF1(Long[] L) { return L; }; + final Long[][] MLF2(Long[][] L) { return L; }; + native Long MLN(Long L); + native Long[] MLN1(Long L[]); + native Long[][] MLN2(Long L[][]); + static Long MLS(Long L) { return L; }; + static Long[] MLS1(Long L[]) { return L; }; + static Long[][] MLS2(Long L[][]) { return L; }; + strictfp Long MLI(Long L) { return L; }; + strictfp Long[] MLI1(Long L[]) { return L; }; + strictfp Long[][] MLI2(Long L[][]) { return L; }; + synchronized Long MLY(Long L) { return L; }; + synchronized Long[] MLY1(Long[] L) { return L; }; + synchronized Long[][] MLY2(Long[][] L) { return L; }; + public Long MLU(Long L) { return L; }; + public Long[] MLU1(Long[] L) { return L; }; + public Long[][] MLU2(Long[][] L) { return L; }; + protected Long MLR(Long L) { return L; }; + protected Long[] MLR1(Long[] L) { return L; }; + protected Long[][] MLR2(Long[][] L) { return L; }; + private Long MLP(Long L) { return L; }; + private Long[] MLP1(Long[] L) { return L; }; + private Long[][] MLP2(Long[][] L) { return L; }; + + Inter ME (int i, long l, Inter E) { return E; }; + Inter[] ME1(int i[], Long L[], Inter E1[]) { return E1; }; + Inter[][] ME2(int i[][], Long L[][], Inter E2[][]) { return E2; }; + + final Inter MEF(Inter E) { return E; }; + final Inter[] MEF1(Inter[] E) { return E; }; + final Inter[][] MEF2(Inter[][] E) { return E; }; + native Inter MEN(Inter E); + native Inter[] MEN1(Inter[] E); + native Inter[][] MEN2(Inter[][] E); + static Inter MES(Inter E) { return E; }; + static Inter[] ME1S(Inter[] E) { return E; }; + static Inter[][] ME2S(Inter[][] E) { return E; }; + strictfp Inter MEI(Inter E) { return E; }; + strictfp Inter[] MEI1(Inter[] E) { return E; }; + strictfp Inter[][] MEI2(Inter[][] E) { return E; }; + synchronized Inter MEY(Inter E) { return E; }; + synchronized Inter[] MEY1(Inter[] E) { return E; }; + synchronized Inter[][] MEY2(Inter[][] E) { return E; }; + public Inter MEU(Inter E) { return E; }; + public Inter[] MEU1(Inter[] E) { return E; }; + public Inter[][] MEU2(Inter[][] E) { return E; }; + protected Inter MER(Inter E) { return E; }; + protected Inter[] MER1(Inter[] E) { return E; }; + protected Inter[][] MER2(Inter[][] E) { return E; }; + private Inter MEP(Inter E) { return E; }; + private Inter[] MEP1(Inter[] E) { return E; }; + private Inter[][] MEP2(Inter[][] E) { return E; }; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003.java new file mode 100644 index 00000000000..804e8ad6c23 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +public class sign003 { + final static String CONSTR_SIGN[] = { + "()V", + "(ID)V", "([I[D)V", "([[I[[D)V", + + "(Ljava/lang/Long;Ljava/lang/String;Ljava/lang/Object;)V", + "([Ljava/lang/Long;[Ljava/lang/String;[Ljava/lang/Object;)V", + "([[Ljava/lang/Long;[[Ljava/lang/String;[[Ljava/lang/Object;)V", + + "(J)V", "(Ljava/lang/Object;)V", "([J)V" + }; + private static Log log; + private final static String prefix = "nsk.jdi.TypeComponent.signature."; + private final static String className = "sign003"; + private final static String debugerName = prefix + className; + private final static String debugeeName = debugerName + "a"; + private final static String classToCheckName = prefix + "sign003aClassToCheck"; + + public static void main(String argv[]) { + System.exit(95 + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + Binder binder = new Binder(argHandler, log); + Debugee debugee = binder.bindToDebugee(debugeeName + + (argHandler.verbose() ? " -verbose" : "")); + IOPipe pipe = new IOPipe(debugee); + boolean testFailed = false; + List methods; + + // Connect with debugee and resume it + debugee.redirectStderr(out); + debugee.resume(); + String line = pipe.readln(); + if (line == null) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + return 2; + } + if (!line.equals("ready")) { + log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + + line); + return 2; + } + else { + log.display("debuger> debugee's \"ready\" signal recieved."); + } + + ReferenceType refType = debugee.classByName(classToCheckName); + if (refType == null) { + log.complain("debuger FAILURE> Class " + classToCheckName + + " not found."); + return 2; + } + + // Get all methods, find constructors and static initializers and + // check them + try { + methods = refType.methods(); + } catch (Exception e) { + log.complain("debuger FAILURE> Can't get methods from class"); + log.complain("debuger FAILURE> Exception: " + e); + return 2; + } + int totalMethods = methods.size(); + if (totalMethods < 1) { + log.complain("debuger FAILURE> Total number of methods read " + + totalMethods); + return 2; + } + log.display("debuger> Total methods found: " + totalMethods); + Iterator methodsIterator = methods.iterator(); + for (int i = 0; methodsIterator.hasNext(); i++) { + Method method = (Method)methodsIterator.next(); + String decTypeName = method.declaringType().name(); + String name = method.name(); + String signature = method.signature(); + + if (method.isConstructor()) { + boolean signFound = false; + + log.display("debuger> " + i + " method (constructor) " + name + + " from " + decTypeName + " with signature " + + signature + " read."); + for (int j = 0; j < CONSTR_SIGN.length; j++) { + // If signature does not exist in list then failure + String realSign = CONSTR_SIGN[j]; + + if (realSign.equals(signature)) { + // Signature found - OK + signFound = true; + log.display("debuger> Signature " + signature + + " found in list - " + j + " element."); + break; + } + } + if (!signFound) { + log.complain("debuger FAILURE 1> Signature " + signature + + " not found in expected list."); + testFailed = true; + continue; + } + } else { + if (method.isStaticInitializer()) { + log.display("debuger> " + i + " method (static " + + "initializer) " + name + " from " + + decTypeName + " with signature " + signature + + " read."); + if (signature == null) { + log.complain("debuger FAILURE 2> Static initializer " + + "from " + decTypeName + " has signature " + + "null."); + testFailed = true; + continue; + } + if (signature.length() == 0) { + log.complain("debuger FAILURE 3> Static initializer " + + "from " + decTypeName + " has empty " + + "signature."); + testFailed = true; + continue; + } + } else { + log.display("debuger> " + i + " method " + name + " from " + + decTypeName + " passed."); + } + } + } + + pipe.println("quit"); + debugee.waitFor(); + int status = debugee.getStatus(); + if (testFailed) { + log.complain("debuger FAILURE> TEST FAILED"); + return 2; + } else { + if (status == 95) { + log.display("debuger> expected Debugee's exit " + + "status - " + status); + return 0; + } else { + log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + + "status (not 95) - " + status); + return 2; + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003/TestDescription.java new file mode 100644 index 00000000000..ec6713e3825 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/TypeComponent/signature/sign003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test checks the signature() method of TypeComponent interface of + * com.sun.jdi package. + * The method spec: + * public java.lang.String signature() + * Gets the JNI-style signature for this type component. The signature is + * encoded type information as defined in the JNI documentation. It is a + * convenient, compact format for for manipulating type information + * internally, not necessarily for display to an end user. See + * Field.typeName() and Method.returnTypeName() for ways to help get a more + * readable representation of the type. + * Returns: a string containing the signature + * See Also: Type Signatures + * nsk/jdi/TypeComponent/signature/signature003 checks assertions: + * public java.lang.String signature() + * 1. Gets the JNI-style signature for a constructor. + * 2. Returns not null and not empty string for a static initializer. + * Debugger gets all method from debuggee calling by name and then checks + * if signature() returns the expected value for the method. + * Debugger gets all methods from debuggee, if a method is constructor test + * checks that signature() returns expected value for the constructor. If a + * method is static initializer test checks that signature() returns not null + * and not empty string. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.TypeComponent.signature.sign003 + * nsk.jdi.TypeComponent.signature.sign003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.TypeComponent.signature.sign003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003a.java new file mode 100644 index 00000000000..a15bc8ce67c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign003a.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.TypeComponent.signature; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +public class sign003a { + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + sign003aClassToCheck classToCheck = new sign003aClassToCheck(); + + log.display("DEBUGEE> debugee started."); + pipe.println("ready"); + String instruction = pipe.readln(); + if (instruction.equals("quit")) { + log.display("DEBUGEE> \"quit\" signal recieved."); + log.display("DEBUGEE> completed succesfully."); + System.exit(95); + } + log.complain("DEBUGEE FAILURE> unexpected signal " + + "(no \"quit\") - " + instruction); + log.complain("DEBUGEE FAILURE> TEST FAILED"); + System.exit(97); + } +} + +class sign003aClassToCheck { + sign003aClassToCheck() {}; + sign003aClassToCheck(int i, double d) {}; + sign003aClassToCheck(int[] i, double[] d) {}; + sign003aClassToCheck(int[][] i, double[][] d) {}; + sign003aClassToCheck(Long L, String S, Object O) {}; + sign003aClassToCheck(Long[] L, String[] S, Object[] O) {}; + sign003aClassToCheck(Long[][] L, String[][] S, Object[][] O) {}; + public sign003aClassToCheck(long l) {}; + private sign003aClassToCheck(Object obj) {}; + protected sign003aClassToCheck(long[] l) {}; + + static boolean sb; + static Object sO; + static float[] sf = new float[10]; + + static { sb = true; } + static { sO = new Object(); } + static { + for (int i = 0; i < 10; i++) { + sf[i] = (float)i; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001.java new file mode 100644 index 00000000000..e3d5b590092 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VMCannotBeModifiedEx._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; + +import java.io.*; + +/** + * The test checks up com.sun.jdi.VMCannotBeModifiedException. + * It creates, throws, catches and inspects the exception using each + * of two public constructors. + */ + +public class canntbemod001 { + + private static int exitStatus; + private static Log log; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain(msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + canntbemod001 thisTest = new canntbemod001(); + + log = new Log(out, new ArgumentHandler(argv)); + + thisTest.execTest(); + + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + exitStatus = Consts.TEST_PASSED; + display("\nTEST BEGINS"); + display("==========="); + + boolean isThrown = false; + try { + throwException(); + } catch (VMCannotBeModifiedException e) { + isThrown = true; + display("VMCannnotBeModifiedException was caught: " + e); + } + if (!isThrown) { + exitStatus = Consts.TEST_FAILED; + complain("VMCannnotBeModifiedException was NOT thrown"); + } + + display(""); + isThrown = false; + try { + throwException("message"); + } catch (VMCannotBeModifiedException e) { + isThrown = true; + display("VMCannnotBeModifiedException was caught: " + e); + } + if (!isThrown) { + exitStatus = Consts.TEST_FAILED; + complain("VMCannnotBeModifiedException was NOT thrown"); + } + display("============="); + display("TEST FINISHES\n"); + } + + private void throwException() { + display("throwing VMCannotBeModifiedException()"); + throw new VMCannotBeModifiedException(); + } + + private void throwException(String msg) { + display("throwing VMCannotBeModifiedException(msg)"); + throw new VMCannotBeModifiedException(msg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001/TestDescription.java new file mode 100644 index 00000000000..9b7496b84de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001/TestDescription.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VMCannotBeModifiedEx/_itself_/canntbemod001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up com.sun.jdi.VMCannotBeModifiedException. + * It creates, throws, catches and inspects the exception using each + * of two public constructors. + * COMMENTS + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMCannotBeModifiedEx._itself_.canntbemod001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMCannotBeModifiedEx._itself_.canntbemod001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001.java new file mode 100644 index 00000000000..2409172f9aa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDeathEvent._itself_; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class vmdeath001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String TEST_NAME = "nsk.jdi.VMDeathEvent._itself_.vmdeath001"; + static final String DEBUGEE_NAME = TEST_NAME + "a"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private boolean testFailed; + static private boolean eventReceived; + + static private boolean disconnectReceived; + static private boolean vmdeathIsPrior; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + + disconnectReceived = false; + vmdeathIsPrior = true; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + log.display("Resuming debuggee"); + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + command); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return vmdeath001.FAILED; + } + + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + isConnected: + while (true) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); +// log.display("Event received: " + event.toString()); + + if (event instanceof VMDeathEvent) { + log.display("VMDeathEvent received"); + VMDeathEvent castedEvent = (VMDeathEvent)event; + eventReceived = true; + + // try to check event references if not disconnected + try { + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 3: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + EventRequest request = castedEvent.request(); + if( request != null) { + log.complain("FAILURE 4: Non-null reference returned by Event.request(): " + request); + testFailed = false; + } + } catch (VMDisconnectedException e) { + log.display("Unable to check event references because of VM disconnection"); + } + + } else if (event instanceof VMDisconnectEvent) { + log.display("VMDisconnectEvent received"); + VMDisconnectEvent castedEvent = (VMDisconnectEvent)event; + + if (!eventReceived) { + vmdeathIsPrior = false; + } + disconnectReceived = true; + break isConnected; + } else if (event instanceof VMDeathEvent) { + eventReceived = true; + } + } + + // try to resume event set if not disconnected + try { + eventSet.resume(); + } catch (VMDisconnectedException e) { + log.display("Unable to resume event set because of VM disconnection"); + } + + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + log.display("Waiting for debuggee terminating"); + debuggee.waitFor(); + + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + if (!eventReceived) { + log.complain("FAILURE 1: VMDeathEvent is not received after target VM terminating"); + return vmdeath001.FAILED; + } else if (!vmdeathIsPrior) { + log.complain("FAILURE 2: VMDeathEvent is not received before VMDisconnectEvent"); + return vmdeath001.FAILED; + } + return vmdeath001.PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001/TestDescription.java new file mode 100644 index 00000000000..bbe3e6d20ce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/VMDeathEvent/_itself_/vmdeath001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises com.sun.jdi.event.VMDeathEvent interface. + * The test checks the following assertions: + * - VMDeathEvent is received by debugger when target VM terminates, + * - VMDeathEvent is received without creating any EventRequest, + * - VMDeathEvent precedes VMDisconnectEvent. + * A debugger class - nsk.jdi.VMDeathEvent.thread.thread001 ; + * a debuggee class - nsk.jdi.VMDeathEvent.thread.thread001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger starts special thread for listening events + * delivered from debuggee. + * The debuggee waits for command from debugger and completes + * upon receiving it. + * The debugger switches to to listen the event during + * the time specified by parameter. + * If the debugger receives VMDeathEvent, it checks all assertions + * of the test. Since debugee may has been terminated this time, + * debugger carefully handles VMDisconnectedException. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - initial IOPipe synchronization is used before starting event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMDeathEvent._itself_.vmdeath001 + * nsk.jdi.VMDeathEvent._itself_.vmdeath001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMDeathEvent._itself_.vmdeath001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001a.java new file mode 100644 index 00000000000..82a3f1f605c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath001a.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDeathEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +public class vmdeath001a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + public static void main(String args[]) { + vmdeath001a _vmdeath001a = new vmdeath001a(); + System.exit(JCK_STATUS_BASE + _vmdeath001a.communication(args)); + } + + int communication( String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + + command); + return FAILED; + } + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java new file mode 100644 index 00000000000..d23a86ee2a0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDeathEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VMDeathEvent.
    + *
    + * The test checks that the interface
    + * com.sun.jdi.VMDeathEvent
    + * complies with its spec.
    + *
    + * The case to test includes receiving the VMDeathEvent
    + * as a response to VirtualMachine.exit(int);
    + *
    + * The test works as follows.
    + *
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * Then to test the interface,
    + * the debugger invokes the method VirtualMachine.exit() and checks up
    + * on the event received in the response to.
    + *
    + */ + +public class vmdeath002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VMDeathEvent/_itself_/vmdeath002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new vmdeath002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VMDeathEvent._itself_.vmdeath002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + Event event = eventIterator.nextEvent(); + if ( !(event instanceof VMDeathEvent) ) { + testExitCode = FAILED; + log3("ERROR: last event is not the VMDeathEvent"); + + if (event instanceof VMDisconnectEvent) + log3(" event is the VMDisconnectEvent ????"); + else + log3(" event is NOT the VMDisconnectEvent ????!!!!!!!"); + return 2; + + } + return 0; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + //vm.eventRequestManager().createVMDeathRequest().enable(); + + log2("......vm.exit(PASS_BASE); :: VMDeathEvent is excpected"); + + //vm.exit(PASS_BASE); + break; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } + + //System.out.println("================getEventSet()"); + //for (Event e : eventSet) + //System.out.println("Event in queue: " + e.toString()); + +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002/TestDescription.java new file mode 100644 index 00000000000..2462ccca691 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002/TestDescription.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VMDeathEvent/_itself_/vmdeath002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VMDeathEvent. + * The test checks up that the intefrace com.sun.jdi.VMDeathEvent + * complies with its spec: + * public interface VMDeathEvent + * extends Event + * Notification of target VM termination. This event occurs + * if the target VM terminates before the VM disconnects (VMDisconnectEvent). + * Thus, this event will NOT occur if external forces terminate the connection + * (e.g. a crash) or if the + * connection is intentionally terminated with VirtualMachine.dispose() + * On VM termination, a single unsolicited VMDeathEvent will always be sent + * with a suspend policy of SUSPEND_NONE. + * Additional VMDeathEvents will be sent in the same event set if + * they are requested with a VMDeathRequest. + * The VM is still intact and can be queried at the point this event was initiated + * but immediately thereafter it is not considered intact and cannot be queried. + * Note: If the enclosing EventSet has a suspend policy other than + * SUSPEND_ALL the initiating point may be long past. + * All VMDeathEvents will be in a single EventSet, + * no other events will be in the event set. + * A resume must occur to continue execution + * after any event set which performs suspensions - + * in this case to allow proper shutdown. + * The test checks that + * this event occurs + * if the target VM terminates before the VM disconnects + * as result of calling VirtualMachine.exit(int). + * The test works as follows: + * The debugger program - nsk.jdi.VMDeathEvent._itself_.vmdeath002; + * the debuggee program - nsk.jdi.VMDeathEvent._itself_.vmdeath002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - waiting for VMStartEvent removed because it is handled now in + * binder.bindToDebugee() method + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMDeathEvent._itself_.vmdeath002 + * nsk.jdi.VMDeathEvent._itself_.vmdeath002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMDeathEvent._itself_.vmdeath002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002a.java new file mode 100644 index 00000000000..986574c5c88 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002a.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDeathEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the vmdeath002 JDI test. + */ + +public class vmdeath002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 0; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + //System.exit(exitCode + PASS_BASE); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + System.exit(exitCode + PASS_BASE); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java new file mode 100644 index 00000000000..c6fb72983ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2001, 2018, 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. + */ +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! templete parameters !!!! + +// VMDeathEvent Interface Name VMDeathEvent +// _itself_ Method Name _itself_ +// vmdeath003 Test Name vmdeath003 +// ------------------------------------------------------ + +package nsk.jdi.VMDeathEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VMDeathEvent.
    + *
    + * The test checks that the interface
    + * com.sun.jdi.VMDeathEvent
    + * complies with its spec.
    + *
    + * The case to test includes receiving no VMDeathEvent
    + * as a response to VirtualMachine.dispose();
    + *
    + * The test works as follows.
    + *
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * Then to test the interface,
    + * the debugger invokes the method VirtualMachine.dispose() and
    + * checks up on the event received in the response to.
    + *
    + */ + +public class vmdeath003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VMDeathEvent/_itself_/vmdeath003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new vmdeath003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VMDeathEvent._itself_.vmdeath003a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : //log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); +// testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDisconnectEvent"); + getEventSet(); + Event newEvent = eventIterator.nextEvent(); + if (newEvent instanceof VMDeathEvent) { + testExitCode = FAILED; + log3("ERROR: last event is the VMDeathEvent"); + return 0; + } + if (newEvent instanceof VMDisconnectEvent) { + log2("......received : VMDisconnectEvent"); + return 2; + } + + throw new JDITestRuntimeException("** Unexpected event **"); + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......vm.dispose(); :: VMDeathEvent is NOT excpected"); + + vm.dispose(); + break; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003/TestDescription.java new file mode 100644 index 00000000000..44b81d9d111 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VMDeathEvent/_itself_/vmdeath003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VMDeathEvent. + * The test checks up that the intefrace com.sun.jdi.VMDeathEvent + * complies with its spec: + * public interface VMDeathEvent + * extends Event + * Notification of target VM termination. This event occurs + * if the target VM terminates before the VM disconnects (VMDisconnectEvent). + * Thus, this event will NOT occur if external forces terminate the connection + * (e.g. a crash) or if the + * connection is intentionally terminated with VirtualMachine.dispose() + * On VM termination, a single unsolicited VMDeathEvent will always be sent + * with a suspend policy of SUSPEND_NONE. + * Additional VMDeathEvents will be sent in the same event set if + * they are requested with a VMDeathRequest. + * The VM is still intact and can be queried at the point this event was initiated + * but immediately thereafter it is not considered intact and cannot be queried. + * Note: If the enclosing EventSet has a suspend policy other than + * SUSPEND_ALL the initiating point may be long past. + * All VMDeathEvents will be in a single EventSet, + * no other events will be in the event set. + * A resume must occur to continue execution + * after any event set which performs suspensions - + * in this case to allow proper shutdown. + * The test checks that + * this event will NOT occur if + * the connection is intentionally terminated with VirtualMachine.dispose() + * The test works as follows: + * The debugger program - nsk.jdi.VMDeathEvent._itself_.vmdeath003; + * the debuggee program - nsk.jdi.VMDeathEvent._itself_.vmdeath003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - waiting for VMStartEvent removed because it is handled now in + * binder.bindToDebugee() method + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMDeathEvent._itself_.vmdeath003 + * nsk.jdi.VMDeathEvent._itself_.vmdeath003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMDeathEvent._itself_.vmdeath003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003a.java new file mode 100644 index 00000000000..6a5c1212362 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDeathEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the vmdeath003 JDI test. + */ + +public class vmdeath003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001.java new file mode 100644 index 00000000000..e12ec008d92 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDisconnectEvent._itself_; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger application in the test + +public class disconnect001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String TEST_NAME = "nsk.jdi.VMDisconnectEvent._itself_.disconnect001"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private boolean testFailed; + static private boolean eventReceived; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + Debugee debuggee; + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + command); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return disconnect001.FAILED; + } + + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + isConnected: + while (true) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); +// log.display("Event received: " + event.toString()); + + if (event instanceof VMDisconnectEvent) { + log.display("VMDisconnectEvent received"); + VMDisconnectEvent castedEvent = (VMDisconnectEvent)event; + + // try to check event references if not disconnected + try { + + EventRequest eventRequest = castedEvent.request(); + if (eventRequest != null) { + log.complain("FAILURE 1: eventRequest is not equal to null"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + } catch (VMDisconnectedException e) { + log.display("Unable to check event references because of VM disconnection"); + } + + eventReceived = true; + break isConnected; + } + } + + // try to resume event set if not disconnected + try { + eventSet.resume(); + } catch (VMDisconnectedException e) { + log.display("Unable to resume event set because of VM disconnection"); + } + + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + log.display("Waiting for debuggee terminating"); + debuggee.waitFor(); + + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + if (!eventReceived) { + log.complain("FAILURE 3: VMDisconnectEvent is not received after target VM terminating"); + return disconnect001.FAILED; + } + return disconnect001.PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001/TestDescription.java new file mode 100644 index 00000000000..987eab83954 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/VMDisconnectEvent/_itself_/disconnect001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises com.sun.jdi.event.VMDisconnectEvent interface. + * The test checks the following assertions: + * - VMDisconnectEvent is received by debugger when target VM + * terminates before disconnection, + * - VMDeathEvent is received without creating any EventRequest. + * A debugger class - nsk.jdi.VMDisconnectEvent._itself_.disconnect001 ; + * a debuggee class - nsk.jdi.VMDisconnectEvent._itself_.disconnect001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger starts special thread for listening events + * delivered from debuggee. + * The debuggee waits for command from debugger and completes + * upon receiving. + * The debugger switches to to listen the event during + * the time specified by parameter. + * If the debugger receives VMDisconnectEvent, it checks all assertions + * of the test. Since debugee may been terminated this time, + * debugger carefully handles VMDisconnectedException. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - initial IOPipe synchronization is used before starting event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMDisconnectEvent._itself_.disconnect001 + * nsk.jdi.VMDisconnectEvent._itself_.disconnect001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMDisconnectEvent._itself_.disconnect001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001a.java new file mode 100644 index 00000000000..d2d71e108d1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect001a.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDisconnectEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +public class disconnect001a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + public static void main(String args[]) { + disconnect001a _disconnect001a = new disconnect001a(); + System.exit(JCK_STATUS_BASE + _disconnect001a.communication(args)); + } + + int communication( String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + command); + return FAILED; + } + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002.java new file mode 100644 index 00000000000..195d54dde97 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDisconnectEvent._itself_; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger application in the test + +public class disconnect002 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String TEST_NAME = "nsk.jdi.VMDisconnectEvent._itself_.disconnect002"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private boolean testFailed; + static private boolean eventReceived; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + Debugee debuggee; + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + command); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return disconnect002.FAILED; + } + + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + isConnected: + while (true) { + + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); +// log.display("Event received: " + event.toString()); + + if (event instanceof VMDisconnectEvent) { + log.display("VMDisconnectEvent received"); + VMDisconnectEvent castedEvent = (VMDisconnectEvent)event; + + // try to check event references if not disconnected + try { + + EventRequest eventRequest = castedEvent.request(); + if (eventRequest != null) { + log.complain("FAILURE 1: eventRequest is not equal to null"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + } catch (VMDisconnectedException e) { + log.display("Unable to check event references because of VM disconnection"); + } + + eventReceived = true; + break isConnected; + } + } + + // try to resume event set if not disconnected + try { + eventSet.resume(); + } catch (VMDisconnectedException e) { + log.display("Unable to resume event set because of VM disconnection"); + } + + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + log.display("Invoking VirtualMachine.dispose() for debuggee."); + vm.dispose(); + + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + log.display("Waiting for debuggee terminating"); + debuggee.waitFor(); + + if (!eventReceived) { + log.complain("FAILURE 3: VMDisconnectEvent is not received after target VM terminating"); + return disconnect002.FAILED; + } + + return disconnect002.PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002/TestDescription.java new file mode 100644 index 00000000000..1b1afceeb0d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/VMDisconnectEvent/_itself_/disconnect002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises com.sun.jdi.event.VMDisconnectEvent interface. + * The test checks the following assertion: + * - VMDisconnectEvent is received by debugger after invocation + * com.sun.jdi.VirtualMachine.dispose() method for target VM. + * - VMDeathEvent is received without creating any EventRequest. + * A debugger class - nsk.jdi.VMDisconnectEvent._itself_.disconnect002 ; + * a debuggee class - nsk.jdi.VMDisconnectEvent._itself_.disconnect002a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger starts special thread for listening events + * delivered from debuggee. + * Then the debugger invokes VirtualMachine.dispose() method. + * The debugger switches to to listen the event during + * the time specified by parameter. + * If the debugger receives VMDisconnectEvent, it checks all assertions + * of the test. Since debugee may been terminated this time, + * debugger carefully handles VMDisconnectedException. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - initial IOPipe synchronization is used before starting event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMDisconnectEvent._itself_.disconnect002 + * nsk.jdi.VMDisconnectEvent._itself_.disconnect002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMDisconnectEvent._itself_.disconnect002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002a.java new file mode 100644 index 00000000000..98d016381e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect002a.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDisconnectEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +public class disconnect002a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + public static void main(String args[]) { + disconnect002a _disconnect002a = new disconnect002a(); + System.exit(JCK_STATUS_BASE + _disconnect002a.communication(args)); + } + + int communication( String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + + command); + return FAILED; + } + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003.java new file mode 100644 index 00000000000..f4e120bf250 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDisconnectEvent._itself_; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger application in the test + +public class disconnect003 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String TEST_NAME = "nsk.jdi.VMDisconnectEvent._itself_.disconnect003"; + static final String DEBUGGEE_NAME = TEST_NAME + "a"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private boolean testFailed; + static private boolean eventReceived; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + Debugee debuggee; + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + debuggee.resume(); + + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + log.complain("TEST BUG: unknown debuggee's command: " + command); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return disconnect003.FAILED; + } + + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + isConnected: + while (true) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); +// log.display("Event received: " + event.toString()); + + if (event instanceof VMDisconnectEvent) { + log.display("VMDisconnectEvent received"); + VMDisconnectEvent castedEvent = (VMDisconnectEvent)event; + + // try to check event references if not disconnected + try { + + EventRequest eventRequest = castedEvent.request(); + if (eventRequest != null) { + log.complain("FAILURE 1: eventRequest is not equal to null"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + } catch (VMDisconnectedException e) { + log.display("Unable to check event references because of VM disconnection"); + } + + eventReceived = true; + break isConnected; + } + } + + // try to resume event set if not disconnected + try { + eventSet.resume(); + } catch (VMDisconnectedException e) { + log.display("Unable to resume event set because of VM disconnection"); + } + + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught VMInterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + log.display("Invoking VirtualMachine.exit(int) for debuggee."); + vm.exit(disconnect003.PASSED); + + log.display("Waiting for debuggee terminating"); + debuggee.waitFor(); + + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + if (!eventReceived) { + log.complain("FAILURE 3: VMDisconnectEvent is not received after target VM terminating"); + return disconnect003.FAILED; + } + + return disconnect003.PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003/TestDescription.java new file mode 100644 index 00000000000..17cc6b003ed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/VMDisconnectEvent/_itself_/disconnect003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises com.sun.jdi.event.VMDisconnectEvent interface. + * The test checks the following assertion: + * - VMDisconnectEvent is received by debugger after invocation + * com.sun.jdi.VirtualMachine.exit(int) method for target VM. + * - VMDeathEvent is received without creating any EventRequest. + * A debugger class - nsk.jdi.VMDisconnectEvent._itself_.disconnect003 ; + * a debuggee class - nsk.jdi.VMDisconnectEvent._itself_.disconnect003a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger starts special thread for listening events + * delivered from debuggee. + * Then the debugger invokes VirtualMachine.exit() method. + * The debugger switches to to listen the event during + * the time specified by parameter. + * If the debugger receives VMDisconnectEvent, it checks all assertions + * of the test. Since debugee may been terminated this time, + * debugger carefully handles VMDisconnectedException. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - initial IOPipe synchronization is used before starting event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMDisconnectEvent._itself_.disconnect003 + * nsk.jdi.VMDisconnectEvent._itself_.disconnect003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMDisconnectEvent._itself_.disconnect003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003a.java new file mode 100644 index 00000000000..e7175a7295c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDisconnectEvent/_itself_/disconnect003a.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMDisconnectEvent._itself_; + +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +public class disconnect003a { + static final String COMMAND_READY = "ready"; + + public static void main(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + pipe.println(COMMAND_READY); + + /* + * In this test debugger kills debuggee using VirtualMachine.exit, so + * standard JDI tests communication protocol isn't used here + */ + try { + Thread.sleep(Long.MAX_VALUE); + } catch (Throwable t) { + // ignore all exceptions + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java new file mode 100644 index 00000000000..77dd0f5afaa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * Test provokes 'VMOutOfMemoryException'. + * Test scenario: + * Debugger obtains 'ArrayType' instance for int array and in endless loop instantiates arrays + * in debuggee VM through 'ArrayType.newInstance()' till VMOutOfMemoryException. Any other exception + * thrown by 'ArrayType.newInstance()' is treated as product bug. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMOutOfMemoryException.VMOutOfMemoryException001.VMOutOfMemoryException001 + * nsk.jdi.VMOutOfMemoryException.VMOutOfMemoryException001.VMOutOfMemoryException001t + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMOutOfMemoryException.VMOutOfMemoryException001.VMOutOfMemoryException001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.VMOutOfMemoryException.VMOutOfMemoryException001; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.*; + +public class VMOutOfMemoryException001 extends TestDebuggerType2 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new VMOutOfMemoryException001().runIt(argv, out); + } + + protected String debuggeeClassName() { + return VMOutOfMemoryException001t.class.getName(); + } + + public void doTest() { + ArrayType referenceType = (ArrayType) debuggee.classByName("int[]"); + + try { + List objects = new ArrayList(); + + // create array in debuggee VM till VMOutOfMemoryException + while (true) { + ArrayReference array = referenceType.newInstance(100000); + array.disableCollection(); + objects.add(array); + } + } catch (VMOutOfMemoryException e) { + // expected exception + log.display("Got expected exception: " + e.toString()); + } catch (Throwable t) { + setSuccess(false); + log.complain("Unexpected exception(VMOutOfMemoryException was expected): " + t); + t.printStackTrace(log.getOutStream()); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001t.java new file mode 100644 index 00000000000..6b41e8f790e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001t.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 2018, 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 nsk.jdi.VMOutOfMemoryException.VMOutOfMemoryException001; + +import nsk.share.Consts; +import nsk.share.jdi.AbstractJDIDebuggee; + +/* + * This test verifies that a VMOutOfMemoryException is thrown when the debugge runs out of memory. + * The debugger will allocate memory in this debugge until it gets a VMOutOfMemoryException. + * This means that we are likely to get an OutOfMemoryError during the test. + * Any OutOfMemoryErrors is just ignored, since they are expected. + */ +public class VMOutOfMemoryException001t extends AbstractJDIDebuggee { + + public static void main(String args[]) { + new VMOutOfMemoryException001t().doTest(args); + } + + // Just call normal doTest() function, but hide any OutOfMemoryErrors. + public void doTest() { + boolean isOutOfMemory = false; + + try { + super.doTest(); + } catch (OutOfMemoryError e) { + // Don't log anything. We are out of memory. + // A println is likely to genereate a new OutOfMemoryError + isOutOfMemory = true; + } + + // Normally the super class handles the return value. + // If we got here after an OutOfMemoryError, we consider the test passed. + if (isOutOfMemory && callExit) { + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001.java new file mode 100644 index 00000000000..00abeadbe04 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMStartEvent.thread; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger application in the test + +public class thread001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + static final String DEBUGEE_NAME = "nsk.jdi.VMStartEvent.thread.thread001a"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private boolean testFailed; + static private boolean eventReceived; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run (final String args[], final PrintStream out) { + + testFailed = false; + eventReceived = false; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + // launch debuggee + Binder binder = new Binder(argHandler, log); + thread001.log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugeeNoWait(DEBUGEE_NAME); + debuggee.redirectStderr(thread001.log, "debuggee >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + while (!eventReceived) { + eventSet = vm.eventQueue().remove(); + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + log.display("Event received: " + event.toString()); + + // handle VMStartEvent + if (event instanceof VMStartEvent) { + VMStartEvent castedEvent = (VMStartEvent)event; + + EventRequest eventRequest = castedEvent.request(); + if (eventRequest != null) { + log.complain("FAILURE 1: eventRequest is not equal to null"); + testFailed = true; + } + VirtualMachine eventMachine = castedEvent.virtualMachine(); + if (!(vm.equals(eventMachine))) { + log.complain("FAILURE 2: eventVirtualMachine is not equal to checked vm"); + testFailed = true; + } + + ThreadReference eventThread = castedEvent.thread(); + if (eventThread == null) { + log.complain("FAILURE 3: ThreadStartEvent.thread() returns null"); + testFailed = true; + } + + String threadName = eventThread.name(); + if ((threadName == null) || (threadName.equals(""))) { + log.complain("FAILURE 4: thread reference has invalid empty name"); + testFailed = true; + } else { + log.display ("VMStartEvent was received in thread " + threadName); + } + + // Check that thread is in VirtualMachine.allThreads() list + boolean found = false; + Iterator threadsList = debuggee.VM().allThreads().iterator(); + while (!found && threadsList.hasNext()) { + found = eventThread.equals((ThreadReference)threadsList.next()); + } + if (!found) { + log.complain("FAILURE 5: " + threadName + " is not in debuggee's allThreads() list"); + testFailed = true; + } + + eventReceived = true; + } + } + // resume each handled event set + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // wait for debuggee started + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + log.complain("Unknown command from debuggee :" + command); + testFailed = true; + } + + // wait for all expected events received + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // force debuggee to exit + thread001.log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee terminated + thread001.log.display("Waiting for debuggee terminating"); + debuggee.endDebugee(); + + // check test results + if (!eventReceived) { + thread001.log.complain("FAILURE 6: VMStartEvent is not received"); + testFailed = true; + } + + if (testFailed) { + return thread001.FAILED; + } + return thread001.PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001/TestDescription.java new file mode 100644 index 00000000000..28b0b7ca13b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VMStartEvent/thread/thread001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * The test exercises + * com.sun.jdi.event.VMStartEvent.thread() method. + * The test checks the following assertions: + * - VMStartEvent is received without creating any EventRequest, + * - VMStarEvent.thread() returns valid ThreadReference + * to the thread in target VM, + * A debugger class - nsk.jdi.VMStartEvent.thread.thread001 ; + * a debuggee class - nsk.jdi.VMStartEvent.thread.thread001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger starts special thread for listening events + * delivered from debuggee. + * The debugger resumes debuggee and waits for command . + * Upon starting debuggee sends command and waits for command + * from debugger and completes upon receiving. + * The debugger switches to listen the event during + * the time specified by parameter. + * If the debugger receives VMStartEvent, it checks all assertions + * of the test. + * The test fails if any of the checks failed. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * Test updated to prevent possible VMDisconnectedException on VMDeathEvent: + * - standard method Debugee.endDebugee() is used instead of cleaning event queue + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VMStartEvent.thread.thread001 + * nsk.jdi.VMStartEvent.thread.thread001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VMStartEvent.thread.thread001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001a.java new file mode 100644 index 00000000000..594ddc58f71 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMStartEvent/thread/thread001a.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VMStartEvent.thread; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class thread001a { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + + public static void main(String args[]) { + thread001a _thread001a = new thread001a(); + System.exit(JCK_STATUS_BASE + _thread001a.communication(args)); + } + + int communication( String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // notify debbugger that debuggee started + pipe.println(COMMAND_READY); + + // wait from debugger command QUIT + String command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: Debugee: unknown command: " + + command); + return FAILED; + } + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001.java new file mode 100644 index 00000000000..10b56b0b9bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001.java @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Value._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * Value.
    + *
    + * The test checks up that a Value object, mirroring neither
    + * a primitive type value nor a void, is casted to both
    + * ObjectReference and a corresponding object reference;
    + * the tested are ArrayReference, ClassObjectReference,
    + * StringReference, ThreadReference, and ThreadGroupReference.
    + *
    + * The test contains two test cases with different ways to get
    + * a tested Value object:
    + * Value = ReferenceType.getValue(Field);
    + * tested types are all of five mentioned above
    + * Value = StackFrame.getValue(LocalVariable);
    + * tested types are String, Array, and ClassObject only
    + */ + +public class value001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Value/_itself_/value001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new value001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Value._itself_.value001a"; + + private String testedClassName = + "nsk.jdi.Value._itself_.Threadvalue001a"; + + //String mName = "nsk.jdi.Value._itself_"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("===> test case : Value = ReferenceType.getValue(Field);"); + + String stringObjName = "str"; + String arrayObjName = "bArray"; + String threadObjName = "thread2"; + String threadgroupObjName = "threadGroupObj"; + String classObj1Name = "classObj1"; + String classObj2Name = "classObj2"; + + ObjectReference stringObjRef = null; + ObjectReference arrayObjRef = null; + ObjectReference threadObjRef = null; + ObjectReference threadgroupObjRef = null; + ObjectReference classObj1Ref = null; + ObjectReference classObj2Ref = null; + + ReferenceType debuggeeClass = null; + + Value val = null; + + + List classes = null; + + classes = vm.classesByName(debuggeeName); + debuggeeClass = (ReferenceType) classes.get(0); + + + log2("......check for a mirror of String object"); + val = debuggeeClass.getValue(debuggeeClass.fieldByName(stringObjName)); + try { + log2(" cast from Value to String"); + StringReference sRef = (StringReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + stringObjRef = (ObjectReference) val; + log2(" cast from ObjectReference to String"); + StringReference sRef = (StringReference) stringObjRef; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + + + log2("......check for a mirror of Array object"); + val = debuggeeClass.getValue(debuggeeClass.fieldByName(arrayObjName)); + try { + log2(" cast from Value to ArrayReference"); + ArrayReference aRef = (ArrayReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + arrayObjRef = (ObjectReference) val; + log2(" cast from ObjectReference to ArrayReference"); + ArrayReference aRef = (ArrayReference) arrayObjRef; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + + + log2("......check for a mirror of Thread object"); + val = debuggeeClass.getValue(debuggeeClass.fieldByName(threadObjName)); + try { + log2(" cast from Value to ThreadReference"); + ThreadReference tRef = (ThreadReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + threadObjRef = (ObjectReference) val; + log2(" cast from ObjectReference to ThreadReference"); + ThreadReference tRef = (ThreadReference) threadObjRef; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + + + log2("......check for a mirror of ThreadGroup object"); + val = debuggeeClass.getValue(debuggeeClass.fieldByName(threadgroupObjName)); + try { + log2(" cast from Value to ThreadGroupReference"); + ThreadGroupReference gRef = (ThreadGroupReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + threadgroupObjRef = (ObjectReference) val; + log2(" cast from ObjectReference to ThreadGroupReference"); + ThreadGroupReference gRef = (ThreadGroupReference) threadgroupObjRef; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + + + log2("......check for a mirror of Class object"); + val = debuggeeClass.getValue(debuggeeClass.fieldByName(classObj1Name)); + try { + log2(" cast from Value to ClassObjectReference"); + ClassObjectReference c1Ref = (ClassObjectReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + classObj1Ref = (ObjectReference) val; + log2(" cast from ObjectReference to ClassObjectReference"); + ClassObjectReference c1Ref = (ClassObjectReference) classObj1Ref; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + + + log2("......check for a mirror of Class object"); + val = debuggeeClass.getValue(debuggeeClass.fieldByName(classObj2Name)); + try { + log2(" cast from Value to ClassObjectReference"); + ClassObjectReference c2Ref = (ClassObjectReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + classObj2Ref = (ObjectReference) val; + log2(" cast from ObjectReference to ClassObjectReference"); + ClassObjectReference c2Ref = (ClassObjectReference) classObj2Ref; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + + + log2("===> test case : Value = StackFrame.getValue(LocalVariable);"); + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "Thread2"; + + String breakpointMethod1 = "run"; + String bpLine1 = "breakpointLineNumber1"; + BreakpointRequest breakpRequest1 = null; + + StackFrame stackFrame = null; + + List allThreads = null; + ListIterator listIterator = null; + + + int expresult = returnCode0; + + label0: { + + log2("getting ThreadReference object"); + + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up a breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + + log2(" getting thread2's StackFrame"); + try { + stackFrame = thread2.frame(0); + } catch ( Exception e ) { + log3("ERROR: Exception for stackFrame = thread2.frame(0) :" + e); + testExitCode = FAILED; + break label1; + } + + String stringObj2Name = "str2"; + String arrayObj2Name = "bArray2"; + String classObj3Name = "classObj3"; + + log2("......check for a mirror of String object"); + try { + val = stackFrame.getValue(stackFrame.visibleVariableByName(stringObj2Name)); + + try { + log2(" cast from Value to String"); + StringReference sRef = (StringReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + stringObjRef = (ObjectReference) val; + log2(" cast from ObjectReference to String"); + StringReference sRef = (StringReference) stringObjRef; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for: stackFrame.getValue()"); + expresult = returnCode1; + } + + log2("......check for a mirror of Array object"); + try { + val = stackFrame.getValue(stackFrame.visibleVariableByName(arrayObj2Name)); + try { + log2(" cast from Value to ArrayReference"); + ArrayReference aRef = (ArrayReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + arrayObjRef = (ObjectReference) val; + log2(" cast from ObjectReference to ArrayReference"); + ArrayReference aRef = (ArrayReference) arrayObjRef; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for: stackFrame.getValue()"); + expresult = returnCode1; + } + + log2("......check for a mirror of Class object"); + try { + val = stackFrame.getValue(stackFrame.visibleVariableByName(classObj3Name)); + try { + log2(" cast from Value to ClassObjectReference"); + ClassObjectReference c1Ref = (ClassObjectReference) val; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + try { + log2(" cast from Value to ObjectReference"); + classObj1Ref = (ObjectReference) val; + log2(" cast from ObjectReference to ClassObjectReference"); + ClassObjectReference c1Ref = (ClassObjectReference) classObj1Ref; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + } + + } catch ( AbsentInformationException e ) { + log3("ERROR: AbsentInformationException for: stackFrame.getValue()"); + expresult = returnCode1; + } + } + + thread2.resume(); + + if (expresult != returnCode0) + testExitCode = FAILED; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001/TestDescription.java new file mode 100644 index 00000000000..d9d34770505 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Value/_itself_/value001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Value. + * The test checks up that a Value object, + * mirroring neither a primitive type value nor a void, + * is casted to both ObjectReference and a corresponding object reference; + * the tested are ArrayReference, ClassObjectReference, + * StringReference, ThreadReference, and ThreadGroupReference. + * The test works as follows: + * The debugger program - nsk.jdi.Value._itself_.value001; + * the debuggee program - nsk.jdi.Value._itself_.value001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Value._itself_.value001 + * nsk.jdi.Value._itself_.value001a + * + * @comment make sure value001a is compiled with full debug info + * @clean nsk.jdi.Value._itself_.value001a + * @compile -g:lines,source,vars ../value001a.java + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Value._itself_.value001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001a.java new file mode 100644 index 00000000000..93e25042dd7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/_itself_/value001a.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Value._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the value001 JDI test. + */ + +public class value001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static String str = "Hello, world!"; + + static boolean[][][][] bArray = + { { {{true, false}, {true, false}}, {{true, false}, {true, false}} }, + { {{true, false}, {true, false}}, {{true, false}, {true, false}} } }; + + + static String threadGroupName = "threadGroup"; + static ThreadGroup threadGroupObj = new ThreadGroup(threadGroupName); + static Threadvalue001a thread2 = null; + + static value001a classObj11 = new value001a(); + static final Class classObj1 = classObj11.getClass(); + + static TestClass classObj21 = new TestClass(); + static final Class classObj2 = classObj21.getClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Value.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Value.type()
    + * complies with its spec when a Value object represents
    + * an object of a primitive type.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee executes the following :
    + * static boolean bl = false;
    + * static byte bt = 0;
    + * static char ch = 0;
    + * static double db = 0.0d;
    + * static float fl = 0.0f;
    + * static int in = 0;
    + * static long ln = 0;
    + * static short sh = 0;
    + *
    + * for each of the above primitive type variables,
    + * a coresponding Type object is created in a debugger
    + * by the statement like the following :
    + *
    + * Type tbl = execClass.getValue(Field fsbl).type();
    + *
    + * the following pair of statements don't throw
    + * ClassCastExceptions:
    + *
    + * PrimitiveType prtbl = (PrimitiveType) tbl;
    + * BooleanType bl = (BooleanType) prtbl;
    + *
    + * PrimitiveType prtbt = (PrimitiveType) tbt;
    + * ByteType bt = (ByteType) prtbt;
    + * .
    + * .
    + * PrimitiveType prtsh = (PrimitiveType) tsh;
    + * ShortType sh = (ShortType) prtsh;
    + *
    + */ + +public class type001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Value/type/type001", + sHeader2 = "--> type001: ", + sHeader3 = "##> type001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new type001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Value.type.type001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("type001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfDebuggeeExecClasses = vm.classesByName(debuggeeName); + if (listOfDebuggeeExecClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfDebuggeeExecClasses.size() != 1"); + break ; + } + ReferenceType execClass = + (ReferenceType) listOfDebuggeeExecClasses.get(0); + + Field fsbl = execClass.fieldByName("bl"); + Field fsbt = execClass.fieldByName("bt"); + Field fsch = execClass.fieldByName("ch"); + Field fsdb = execClass.fieldByName("db"); + Field fsfl = execClass.fieldByName("fl"); + Field fsin = execClass.fieldByName("in"); + Field fsln = execClass.fieldByName("ln"); + Field fssh = execClass.fieldByName("sh"); + + int i2; + + for (i2 = 0; ; i2++) { + + int expresult = 0; + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // BooleanType + Type tbl = execClass.getValue(fsbl).type(); + PrimitiveType prtbl = null; + try { + prtbl = (PrimitiveType) tbl; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: PrimitiveType prtbl = (PrimitiveType) tbl;"); + break ; + } + try { + BooleanType bl = (BooleanType) prtbl; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: BooleanType blt = (BooleanType) prtbl;"); + } + break; + + case 1: // ByteType + Type tbt = execClass.getValue(fsbt).type(); + PrimitiveType prtbt = null; + try { + prtbt = (PrimitiveType) tbt; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: PrimitiveType ptbt = (PrimitiveType) tbt;"); + break ; + } + try { + ByteType bt = (ByteType) prtbt; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: ByteType bt = (ByteType) ptbt;"); + } + break; + + case 2: // CharType + Type tch = execClass.getValue(fsch).type(); + PrimitiveType prtch = null; + try { + prtch = (PrimitiveType) tch; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: PrimitiveType prtch = (PrimitiveType) tch;"); + break ; + } + try { + CharType ch = (CharType) prtch; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: CharType ch = (CharType) prtch;"); + } + break; + + case 3: // DoubleType + Type tdb = execClass.getValue(fsdb).type(); + PrimitiveType prtdb = null; + try { + prtdb = (PrimitiveType) tdb; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: PrimitiveType prtdb = (PrimitiveType) tdb;"); + break ; + } + try { + DoubleType db = (DoubleType) prtdb; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: DoubleType db = (DoubleType) prtdb;"); + } + break; + + case 4: // FloatType + Type tfl = execClass.getValue(fsfl).type(); + PrimitiveType prtfl = null; + try { + prtfl = (PrimitiveType) tfl; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: PrimitiveType prtfl = (PrimitiveType) tfl;"); + break ; + } + try { + FloatType fl = (FloatType) prtfl; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: FloatType fl = (FloatType) prtfl;"); + } + break; + + case 5: // IntegerType + Type tin = execClass.getValue(fsin).type(); + PrimitiveType prtin = null; + try { + prtin = (PrimitiveType) tin; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: PrimitiveType prtin = (PrimitiveType) tin;"); + break ; + } + try { + IntegerType in = (IntegerType) prtin; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: IntegerType in = (IntegerType) prtin;"); + } + break; + + case 6: // LongType + Type tln = execClass.getValue(fsln).type(); + PrimitiveType prtln = null; + try { + prtln = (PrimitiveType) tln; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: PrimitiveType prtln = (PrimitiveType) tln;"); + break ; + } + try { + LongType ln = (LongType) prtln; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: LongType ln = (LongType) prtln;"); + } + break; + + case 7: // ShortType + Type tsh = execClass.getValue(fssh).type(); + PrimitiveType prtsh = null; + try { + prtsh = (PrimitiveType) tsh; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: PrimitiveType prtsh = (PrimitiveType) tsh;"); + break ; + } + try { + ShortType sh = (ShortType) prtsh; + } catch ( ClassCastException e ) { + expresult = 1; + log3("ERROR: ShortType sh = (ShortType) prtsh;"); + } + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001/TestDescription.java new file mode 100644 index 00000000000..7d7a6fcce81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Value/type/type001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Value. + * The test checks up that a result of the method + * com.sun.jdi.Value() + * complies with its spec when Value objects represent + * objects of the PrimitiveType. + * Note: The spec is missed. + * The test works as follows: + * A debugger program - nsk.jdi.Value.type.type001; + * a debuggee program - nsk.jdi.Value.type.type001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Value.type.type001 + * nsk.jdi.Value.type.type001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Value.type.type001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001a.java new file mode 100644 index 00000000000..6c71fbb5e21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type001a.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Value.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the type001 JDI test. + */ + +public class type001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> type001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> type001a: " + message); + } + + //====================================================== test program + + static boolean bl = false; + static byte bt = 0; + static char ch = 0; + static double db = 0.0d; + static float fl = 0.0f; + static int in = 0; + static long ln = 0; + static short sh = 0; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Value.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Value.type()
    + * complies with its spec when a Value object represents
    + * an object of a VoidType.
    + *
    + * The case for testing is as follows.
    + *
    + * When a gebuggee is suspended at a breakpoint set up
    + * by a debugger, the debugger invokes debuggee's method
    + * void vdValue1(); to get Value returnvdValue1
    + *
    + * Then it forms a Type object for returnvdValue1
    + * Type typevdValue = returnvdValue1.type();
    + * and performs the following cast:
    + * VoidType voidtypevdValue = (VoidType) typevdValue;
    + * which should not throw ClassCastException.
    + *
    + */ + +public class type002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Value/type/type002/type002", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new type002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Value.type.type002.type002a"; + + private String testedClassName = + "nsk.jdi.Value.type.type002.Threadtype002a"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + String threadName = "Thread2"; + + String breakpointMethod1 = "run"; + String bpLine1 = "breakpointLineNumber1"; + + BreakpointRequest breakpRequest1 = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting a breakpoint event"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + + Value returnvdValue1 = null; + + List invokeMethods = testedclass.methodsByName("vdValue1"); + Method invokeMethod = invokeMethods.get(0); + + List argumentList = Collections.emptyList(); + + try { + log2(" invoking type002a.vdValue1()"); + returnvdValue1 = thread2.invokeMethod(thread2, + invokeMethod, argumentList, 0); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + expresult = returnCode1; + break label1; + } + + log2(" resuming the thread2"); + eventSet.resume(); + + log2(" Type typevdValue = returnvdValue1.type();"); + Type typevdValue = returnvdValue1.type(); + + log2(" checking up cast"); + try { + log2(" VoidType voidtypevdValue = (VoidType) typevdValue; no Exception expected"); + VoidType voidtypevdValue = (VoidType) typevdValue; + } catch ( ClassCastException e ) { + log3("ERROR : ClassCastException"); + expresult = returnCode1; + break label1; + } + + } + + log2(" resuming the vm"); + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type002/type002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type002/type002a.java new file mode 100644 index 00000000000..434d759a528 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type002/type002a.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Value.type.type002; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the type002 JDI test. + */ + +public class type002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * Value.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.Value.type()
    + * complies with its spec when a Value object represents
    + * an object of a ReferenceType.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee created the following objects:
    + * static ClassForCheck_2 classObj =
    + * new ClassForCheck_2();
    + * static InterfaceForCheck ifaceObj = classObj;
    + * static ClassForCheck[] cfcObj =
    + * { new ClassForCheck(), new ClassForCheck() };
    + *
    + * for each of the above refrence type static fields,
    + * a coresponding Type object named
    + * classFieldType,
    + * ifaceFieldType, and
    + * arrayFieldType
    + * are created in a debugger, which then checks up that
    + * the following statements
    + * don't throw ClassCastExceptions:
    + * ClassType ct = (ClassType) classFieldType;
    + * ClassType ct = (ClassType) ifaceFieldType;
    + * ArrayType at = (ArrayType) arrayFieldType;
    + * whereas the statement
    + * InterfaceType it = (InterfaceType) ifaceFieldType;
    + * does throw the exception.
    + *
    + */ + +public class type003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/Value/type/type003", + sHeader2 = "--> type003: ", + sHeader3 = "##> type003: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new type003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.Value.type.type003a"; + + String mName = "nsk.jdi.Value.type"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("type003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listOfLoadedClasses = vm.classesByName(mName + ".TestClass"); + + if (listOfLoadedClasses.size() != 1) { + testExitCode = FAILED; + log3("ERROR: listOfLoadedClasses.size() != 1 " + + listOfLoadedClasses.size()); + break ; + } + + ReferenceType testedClass = (ReferenceType) listOfLoadedClasses.get(0); + + int i2; + int expresult = 0; + + for (i2 = 0; ; i2++) { + + log2("new check: #" + i2); + + switch (i2) { + + case 0: // ClassType + + String classFieldName = "classObj"; + Field classField = + testedClass.fieldByName(classFieldName); + + Value classFieldValue = testedClass.getValue(classField); + Type classFieldType = classFieldValue.type(); + + try { + ClassType ct = (ClassType) classFieldType; + log2(" : ClassType ct = (ClassType) classFieldType;"); + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassType ct = (ClassType) classFieldType;"); + } + + break; + + case 1: // InterfaceType + + String ifaceFieldName = "ifaceObj"; + Field ifaceField = + testedClass.fieldByName(ifaceFieldName); + + Value ifaceFieldValue = testedClass.getValue(ifaceField); + Type ifaceFieldType = ifaceFieldValue.type(); + + try { + InterfaceType it = (InterfaceType) ifaceFieldType; + testExitCode = FAILED; + log3("ERROR: InterfaceType it = (InterfaceType) ifaceFieldType;"); + } catch ( ClassCastException e ) { + log2(" : ClassCastException for: InterfaceType it = (InterfaceType) ifaceFieldType;"); + } + try { + ClassType ct = (ClassType) ifaceFieldType; + log2(" : ClassType ct = (ClassType) ifaceFieldType;"); + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ClassCastException for: ClassType ct = (ClassType) ifaceFieldType;"); + } + break; + + case 2: // ArrayType + + String arrayFieldName = "cfcObj"; + Field arrayField = + testedClass.fieldByName(arrayFieldName); + + Value arrayFieldValue = testedClass.getValue(arrayField); + Type arrayFieldType = arrayFieldValue.type(); + + try { + ArrayType at = (ArrayType) arrayFieldType; + log2(" : ArrayType at = (ArrayType) arrayFieldType;"); + } catch ( ClassCastException e ) { + testExitCode = FAILED; + log3("ERROR: ArrayType at = (ArrayType) arrayFieldType;"); + } + + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003/TestDescription.java new file mode 100644 index 00000000000..968020de7e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/Value/type/type003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * Value. + * The test checks up that a result of the method + * com.sun.jdi.Value() + * complies with its spec when Value objects represent + * objects of the ReferenceType. + * Note: The spec is missed. + * The test works as follows: + * A debugger program - nsk.jdi.Value.type.type003; + * a debuggee program - nsk.jdi.Value.type.type003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.Value.type.type003 + * nsk.jdi.Value.type.type003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.Value.type.type003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003a.java new file mode 100644 index 00000000000..475e24e8560 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Value/type/type003a.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.Value.type; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the type003 JDI test. + */ + +public class type003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> type003a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> type003a: " + message); + } + + //====================================================== test program + + static TestClass obj = new TestClass(); + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.allClasses()
    + * complies with its spec.
    + *
    + * The test check up that new class and interface types
    + * are in returned List only after corresponding objects
    + * have been created within the debuggee.
    + * The sequence of the cases for testing is as follows:
    + *
    + * Objects# == 0, Classes# == 0, Interfaces# == 0
    + * hence, the returned List must contain no mirrors of
    + * tested reference types;
    + * Objects# == 1, Classes# == 1, Interfaces# == 0
    + * the returned list must contain only one expected
    + * object mirroring a tested Class type;
    + * Objects# == 2, Classes# == 2, Interfaces# == 1
    + * the returned list must contain three expected objects
    + * mirroring two Class and one Interface types;
    + * Objects# == 3, Classes# == 2, Interfaces# == 1,
    + * the returned list must contain three expected objects
    + * mirroring two Class and one Interface types;
    + * repetirion of previous check after one more object
    + * has been created;
    + * Objects# == 4, Classes# == 3, Interfaces# == 1,
    + * the returned list must contain four expected objects
    + * mirroring three Class and one Interface types;
    + *
    + */ + +public class allclasses001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/allClasses/allclasses001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new allclasses001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return exitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.allClasses.allclasses001a"; + + private String namePrefix = + "nsk.jdi.VirtualMachine.allClasses."; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) ( + debuggeeClass.getValue( + debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String name[] = { "Class1ForCheck", + "Class2ForCheck", + "Class3ForCheck", + "InterfaceForCheck" }; + + + switch (i) { + + case 0: + log2("...... check case: Objects# ==0, Classes# ==0, Interfaces# ==0,"); + if (refTypeYes(name[0]) != 0) { + log3("ERROR: Class in the List: " + name[0]); + expresult = returnCode1; + } + if (refTypeYes(name[1]) != 0) { + log3("ERROR: Class in the List: " + name[1]); + expresult = returnCode1; + } + if (refTypeYes(name[2]) != 0) { + log3("ERROR: Class in the List: " + name[2]); + expresult = returnCode1; + } + if (refTypeYes(name[3]) != 0) { + log3("ERROR: Interface in the List: " + name[3]); + expresult = returnCode1; + } + break; + + + + case 1: + log2("...... check case: Objects# ==1, Classes# ==1, Interfaces# ==0,"); + if (refTypeYes(name[0]) == 0) { + log3("ERROR: Class not in the List: " + name[0]); + expresult = returnCode1; + } + if (refTypeYes(name[1]) != 0) { + log3("ERROR: Class in the List: " + name[1]); + expresult = returnCode1; + } + if (refTypeYes(name[2]) != 0) { + log3("ERROR: Class in the List: " + name[2]); + expresult = returnCode1; + } + if (refTypeYes(name[3]) != 0) { + log3("ERROR: Interface in the List: " + name[3]); + expresult = returnCode1; + } + break; + + + case 2: + log2("...... check case: Objects# ==2, Classes# ==2, Interfaces# ==1,"); + if (refTypeYes(name[0]) == 0) { + log3("ERROR: Class not in the List: " + name[0]); + expresult = returnCode1; + } + if (refTypeYes(name[1]) == 0) { + log3("ERROR: Class not in the List: " + name[1]); + expresult = returnCode1; + } + if (refTypeYes(name[2]) != 0) { + log3("ERROR: Class in the List: " + name[2]); + expresult = returnCode1; + } + if (refTypeYes(name[3]) == 0) { + log3("ERROR: Interface not in the List: " + name[3]); + expresult = returnCode1; + } + break; + + + case 3: + log2("...... check case: Objects# ==3, Classes# ==2, Interfaces# ==1,"); + if (refTypeYes(name[0]) == 0) { + log3("ERROR: Class not in the List: " + name[0]); + expresult = returnCode1; + } + if (refTypeYes(name[1]) == 0) { + log3("ERROR: Class not in the List: " + name[1]); + expresult = returnCode1; + } + if (refTypeYes(name[2]) != 0) { + log3("ERROR: Class in the List: " + name[2]); + expresult = returnCode1; + } + if (refTypeYes(name[3]) == 0) { + log3("ERROR: Interface not in the List: " + name[3]); + expresult = returnCode1; + } + break; + + + case 4: + log2("...... check case: Objects# ==4, Classes# ==3, Interfaces# ==1,"); + if (refTypeYes(name[0]) == 0) { + log3("ERROR: Class not in the List: " + name[0]); + expresult = returnCode1; + } + if (refTypeYes(name[1]) == 0) { + log3("ERROR: Class not in the List: " + name[1]); + expresult = returnCode1; + } + if (refTypeYes(name[2]) == 0) { + log3("ERROR: Class not in the List: " + name[2]); + expresult = returnCode1; + } + if (refTypeYes(name[3]) == 0) { + log3("ERROR: Interface not in the List: " + name[3]); + expresult = returnCode1; + } + break; + + + default: + break ; + } + + if (expresult != returnCode0) + testExitCode = FAILED; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException, Exception { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); +// breakpRequest = null; + throw e1; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); +// breakpRequest = null; + throw e2; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private int refTypeYes ( String name ) { + + List vmClasses = vm.allClasses(); + ListIterator li = vmClasses.listIterator(); + + for ( int i = 0; li.hasNext(); i++) { + ReferenceType obj = (ReferenceType) li.next(); + if ( obj.name().equals(namePrefix + name) ) + return 1; + } + return 0; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001/TestDescription.java new file mode 100644 index 00000000000..dc7818f8e92 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/allClasses/allclasses001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.allClasses() + * complies with its spec: + * public java.util.List allClasses() + * Returns all loaded types. For each loaded type in the target VM + * a ReferenceType will be placed in the returned list. + * The list will include ReferenceTypes which mirror classes, interfaces, and + * array types. + * Returns: a list of ReferenceType objects, each mirroring a loaded type + * in the target VM. + * The case for testing includes only non-array Class and Interface types + * loaded within user's application, that is, + * any system Class and Interface are not taken into account. + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.allClasses.allclasses001; + * a debuggee program - nsk.jdi.VirtualMachine.allClasses.allclasses001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test is modified to fix the bug 4482592: + * IOPipe is removed from the test. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.allClasses.allclasses001 + * nsk.jdi.VirtualMachine.allClasses.allclasses001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.allClasses.allclasses001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001a.java new file mode 100644 index 00000000000..0b407ae3de4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001a.java @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.allClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debugee application for the allclasses001a JDI test. + + */ + +public class allclasses001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.out.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.out.println("!!**> debuggee: " + message); + } + + //====================================================== test program + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i maxInstr || instruction < 0) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: // Objects# =0;; Classes# =0; Interfaces# =0 + + methodForCommunication(); + break ; + + case 1: // Objects# =1; Classes# =1; Interfaces# =0; + + obj11 = new Class1ForCheck(); + methodForCommunication(); + break ; + + case 2: // Objects# =2; Classes# =2; Interfaces# =1; + + obj21 = new Class2ForCheck(); + methodForCommunication(); + break ; + + case 3: // Objects# =3; Classes# =2; Interfaces# =1; + + obj22 = new Class2ForCheck(); + methodForCommunication(); + break ; + + case 4: // Objects# =4; Classes# =3; Interfaces# =1; + + obj31 = new Class3ForCheck(); + methodForCommunication(); + break ; + + + //------------------------------------------------- standard end section + + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} + + +class Class1ForCheck { + + // static fields + + static boolean s_boolean; + static byte s_byte; + static char s_char; + static double s_double; + static float s_float; + static int s_int; + static long s_long; + static short s_short; + static Object s_object; + static long[] s_prim_array; + static Object[] s_ref_array; + + // instance fields + + boolean i_boolean; + byte i_byte; + char i_char; + double i_double; + float i_float; + int i_int; + long i_long; + short i_short; + Object i_object; + long[] i_prim_array; + Object[] i_ref_array; +} + + +interface InterfaceForCheck { + + static final boolean s_iface_boolean = true; + static final byte s_iface_byte = (byte)1; + static final char s_iface_char = '1'; + static final double s_iface_double = 999; + static final float s_iface_float = 99; + static final int s_iface_int = 100; + static final long s_iface_long = 1000; + static final short s_iface_short = 1000; + static final Object s_iface_object = new Object(); +} + + + +class Class2ForCheck implements InterfaceForCheck { + + // static fields + + static boolean s_boolean; + static byte s_byte; + static char s_char; + static double s_double; + static float s_float; + static int s_int; + static long s_long; + static short s_short; + static Object s_object; + static long[] s_prim_array; + static Object[] s_ref_array; + + // instance fields + + boolean i_boolean; + byte i_byte; + char i_char; + double i_double; + float i_float; + int i_int; + long i_long; + short i_short; + Object i_object; + long[] i_prim_array; + Object[] i_ref_array; +} + +class Class3ForCheck implements InterfaceForCheck { + + // static fields + + static boolean s_boolean; + static byte s_byte; + static char s_char; + static double s_double; + static float s_float; + static int s_int; + static long s_long; + static short s_short; + static Object s_object; + static long[] s_prim_array; + static Object[] s_ref_array; + + // instance fields + + boolean i_boolean; + byte i_byte; + char i_char; + double i_double; + float i_float; + int i_int; + long i_long; + short i_short; + Object i_object; + long[] i_prim_array; + Object[] i_ref_array; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002.java new file mode 100644 index 00000000000..f60e48535e6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.allClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.allClasses()
    + * complies with its spec.
    + * The test check up that class array type, interface array
    + * type, and all primitive array types are in a List returned
    + * by the method.
    + *
    + */ + +public class allclasses002 { + + //----------------------------------------------------- template section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- template parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/allClasses/allclasses002", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new allclasses002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.allClasses.allclasses002a"; + + private String namePrefix = + "nsk.jdi.VirtualMachine.allClasses."; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("allclasses002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log1(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String name[] = { "allclasses002aClassForCheck[]", + "allclasses002aInterfaceForCheck[]", + "boolean[][][][]", + "byte[][][][]", + "char[][][][]", + "double[][][][]", + "float[][][][]", + "int[][][][]", + "long[][][][]", + "short[][][][]" }; + + + log2(" check for loaded " + namePrefix + name[0] + " type"); + if (refTypeYes(namePrefix + name[0]) == 0) { + log3("ERROR: no " + namePrefix + name[0] + " type in the List"); + testExitCode = FAILED; + } + + log2(" check for loaded " + namePrefix + name[1] + " type"); + if (refTypeYes(namePrefix + name[1]) == 0) { + log3("ERROR: no " + namePrefix + name[1] + " type in the List"); + testExitCode = FAILED; + } + + for (int i1 = 2; i1 < 10; i1++) { + + log2("......check for loaded " + name[i1] + " type"); + if (refTypeYes(name[i1]) == 0) { + log3("ERROR: no " + name[i1] + " type in the List"); + testExitCode = FAILED; + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + int refTypeYes ( String name ) { + + int retCode = 0; + + List vmClasses = vm.allClasses(); + ListIterator li = vmClasses.listIterator(); + + log2("loaded '" + namePrefix + "' types:"); + for ( int i = 0; li.hasNext(); i++) { + ReferenceType obj = (ReferenceType) li.next(); + + if (obj.name().startsWith("nsk.jdi.VirtualMachine")) + log2(" " + i + " : " + obj.name() ); + + if (obj.name().endsWith("[][][][]")) + log2(" " + i + " : " + obj.name() ); + + if ( obj.name().equals(name) ) + retCode = 1; + } + return retCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002/TestDescription.java new file mode 100644 index 00000000000..0cc55159937 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/allClasses/allclasses002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.allClasses() + * complies with its spec: + * public java.util.List allClasses() + * Returns all loaded types. For each loaded type in the target VM + * a ReferenceType will be placed in the returned list. + * The list will include ReferenceTypes which mirror classes, interfaces, and + * array types. + * Returns: a list of ReferenceType objects, each mirroring a loaded type + * in the target VM. + * The case for testing includes only array Class and Interface types + * loaded within user's application, that is, + * system Class and Interface arrays are not taken into account. + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.allClasses.allclasses002; + * a debuggee program - nsk.jdi.VirtualMachine.allClasses.allclasses002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.allClasses.allclasses002 + * nsk.jdi.VirtualMachine.allClasses.allclasses002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.allClasses.allclasses002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002a.java new file mode 100644 index 00000000000..afab6c21958 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses002a.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.allClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debugee application for the allclasses002a JDI test. + + */ + +public class allclasses002a { + + //----------------------------------------------------- template section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + //====================================================== test program + + static final allclasses002aClassForCheck[] obj1 = { new allclasses002aClassForCheck(), + new allclasses002aClassForCheck() }; + + static final allclasses002aInterfaceForCheck[] ifaceObj = { new allclasses002aClass2ForCheck(), + new allclasses002aClass2ForCheck() }; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.allThreads()
    + * complies with the its spec.
    + *
    + * The test checks up the reasults of the method when
    + * it is invoked two times in raw immediately after
    + * new thread has been started in the debuggee VM.
    + *
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since the thread2 uses the same locking object as main one
    + * it is locked up until the main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * performs the following.
    + * - Upon the receiption of the message "checkready",
    + * the debugger invokes the method VirtualMachine.allThreads()
    + * two times in raw, compares two List objects returned,
    + * and prints out log containing numbers and names of threads
    + * in first returned list.
    + *
    + */ + +public class allthreads001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/allThreads/allthreads001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new allthreads001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.allThreads.allthreads001a"; + + private String testedClassName = + "nsk.jdi.StackFrame.setValue.Threadallthreads001a"; + + //String mName = "nsk.jdi.VirtualMachine.allThreads"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("location001a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + List allThreads1 = vm.allThreads(); + log2("allThreads1.size() = " + allThreads1.size()); + + List allThreads2 = vm.allThreads(); + log2("allThreads2.size() = " + allThreads2.size()); + + if ( allThreads1.size() != allThreads2.size() ) { + log3("ERROR: allThreads1.size() != allThreads2.size()"); + expresult = returnCode1; + } + // Verify that the target thread is running: + boolean foundThread = false; + for (int ii = 0; ii < allThreads1.size(); ii++) { + if ((((ThreadReference) allThreads1.get(ii)).name().equals(threadName))) { + foundThread = true; + break; + } + } + if (!foundThread) { + log3("ERROR: did not find '" + threadName + "' on allThreads1 list."); + expresult = returnCode1; + } + + ThreadReference thread = null; + Object[] arrayT = allThreads1.toArray(); + + for (int iii=0; iii < allThreads1.size(); iii++) { + thread = (ThreadReference) arrayT[iii]; + log2("thread.name(" + iii + ") = " + thread.name()); + } + + log2(" forcing main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ +/* + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } +*/ + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ +/* + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } +*/ +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001/TestDescription.java new file mode 100644 index 00000000000..56dec01b96a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/allThreads/allthreads001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.allThreads() + * complies with its spec: + * public java.util.List allThreads() + * Returns a list of the currently running threads. + * For each running thread in the target VM, a ThreadReference + * that mirrors it is placed in the list. + * The returned list contains threads created through java.lang.Thread, + * all native threads attached to the target VM through JNI, and + * system threads created by the target VM. + * Thread objects that have not yet been started (see java.lang.Thread#start) + * and thread objects that have completed their execution are not + * included in the returned list. + * Returns: a list of ThreadReference objects, + * one for each running thread in the mirrored VM. + * The testing case is as follows: + * - new thread in a gebuggee is created, started, and waiting for + * entering a synchronized block. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.allThreads.allthreads001; + * the debuggee program - nsk.jdi.VirtualMachine.allThreads.allthreads001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.allThreads.allthreads001 + * nsk.jdi.VirtualMachine.allThreads.allthreads001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.allThreads.allthreads001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001a.java new file mode 100644 index 00000000000..c748c224067 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allThreads/allthreads001a.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.allThreads; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the allthreads001 JDI test. + */ + +public class allthreads001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canAddMethod()
    + * complies with its spec.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class canaddmethod001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new canaddmethod001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canAddMethod.canaddmethod001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("...... vm.canAddMethod()"); + if ( vm.canAddMethod() ) + log2(" vm.canAddMethod() == true"); + else + log2(" vm.canAddMethod() == false"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001/TestDescription.java new file mode 100644 index 00000000000..8666ae15efc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canAddMethod() + * complies with its spec: + * public boolean canAddMethod() + * Determines if the target VM supports the addition of methods + * when performing class redefinition. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canAddMethod.canaddmethod001; + * the debuggee program - nsk.jdi.VirtualMachine.canAddMethod.canaddmethod001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canAddMethod.canaddmethod001 + * nsk.jdi.VirtualMachine.canAddMethod.canaddmethod001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canAddMethod.canaddmethod001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001a.java new file mode 100644 index 00000000000..2e37cbdf4fd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canAddMethod; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the canaddmethod001 JDI test. + */ + +public class canaddmethod001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001.java new file mode 100644 index 00000000000..9c731ebbc3e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachine.canBeModified; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; + +/** + * The test checks up com.sun.jdi.VirtualMachine.canBeModified() + * to return true unconditionally. + */ + +public class canbemodified001 { + + private final static String prefix = "nsk.jdi.VirtualMachine.canBeModified."; + private final static String debuggerName = prefix + "canbemodified001"; + public final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain(msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + canbemodified001 thisTest = new canbemodified001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.redirectOutput(log); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + display("\nTEST BEGINS"); + display("==========="); + + boolean canBeModified = debugee.VM().canBeModified(); + if (canBeModified) { + display("target VM can be modified"); + exitStatus = Consts.TEST_PASSED; + } else { + complain("target VM can not be modified"); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001/TestDescription.java new file mode 100644 index 00000000000..00823f94175 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001/TestDescription.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canBeModified/canbemodified001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up com.sun.jdi.VirtualMachine.canBeModified() + * to return true unconditionally. + * COMMENTS + * Current JDI implementation allows VM to be modified. + * Besides that read-only JDI implementation may be integrated + * into JDK. In this case the test should be reimplemented + * to be run against both implementations. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canBeModified.canbemodified001 + * nsk.jdi.VirtualMachine.canBeModified.canbemodified001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canBeModified.canbemodified001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001a.java new file mode 100644 index 00000000000..39cdf7e3adb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001a.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachine.canBeModified; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; +import java.net.*; + +/** + * canbemodified001a is deugee's part of the canbemodified001. + */ + +public class canbemodified001a { + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.out, argHandler); + + String oldClassDir = argv[0] + File.separator + "loadclass"; + + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001.java new file mode 100644 index 00000000000..28150c40e6c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canGetBytecodes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canGetBytecodes()
    + * complies with its spec.
    + *
    + * The test works as follows.
    + * After being started up, a debuggee informs a debugger.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - gets the Method mtd object
    + * mirroring the method "testedMethod" in the debuggee,
    + * - calls to the method VirtualMachine.canGetBytecodes()
    + * to get its returned value.
    + * Then if the value is true the debugger checks up that invoking
    + * the method Method.bytecodes() on the mtd doesn't throw
    + * UnsupportedOperationException.
    + * If the value is false the debugger checks up that invoking
    + * the method Method.bytecodes() on the mtd does throw
    + * UnsupportedOperationException.
    + */ + +public class cangetbytecodes001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new cangetbytecodes001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canGetBytecodes.cangetbytecodes001a"; + + //String mName = "nsk.jdi.VirtualMachine.canGetBytecodes"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + Method mtd = null; + + label0: { + + log2("......getting Method mtd object"); + testedclass = (ReferenceType) vm.classesByName(debuggeeName).get(0); + mtd = (Method) testedclass.methodsByName("testedMethod").get(0); + + + if (vm.canGetBytecodes()) { + + log2("......vm.canGetBytecodes() == true"); + log2(" checking up on no UnsupportedOperationException trown"); + try { + mtd.bytecodes(); + log2(" no Exception thrown"); + } catch ( UnsupportedOperationException e1 ) { + log3("ERROR: UnsupportedOperationException"); + expresult = returnCode1; + } catch ( Exception e2 ) { + expresult = returnCode1; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + + } else { + + log2(".......vm.canGetBytecodes() == false"); + log2(" checking up on UnsupportedOperationException trown"); + try { + mtd.bytecodes(); + log3("ERROR: no UnsupportedOperationException thrown"); + expresult = returnCode1; + } catch ( UnsupportedOperationException e1 ) { + log2(" UnsupportedOperationException thrown"); + } catch ( Exception e2 ) { + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + expresult = returnCode1; + } + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001/TestDescription.java new file mode 100644 index 00000000000..bdd416dd5d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canGetBytecodes() + * complies with its spec: + * public boolean canGetBytecodes() + * Determines if this implementation supports the retrieval of + * a method's bytecodes. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canGetBytecodes.cangetbytecodes001; + * the debuggee program - nsk.jdi.VirtualMachine.canGetBytecodes.cangetbytecodes001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canGetBytecodes.cangetbytecodes001 + * nsk.jdi.VirtualMachine.canGetBytecodes.cangetbytecodes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canGetBytecodes.cangetbytecodes001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001a.java new file mode 100644 index 00000000000..964e05c6205 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canGetBytecodes; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the cangetbytecodes001 JDI test. + */ + +public class cangetbytecodes001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> cangetbytecodes001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> cangetbytecodes001a: " + message); + } + + //====================================================== test program + + public static int testedMethod() { + return PASS_BASE; + } + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canGetCurrentContendedMonitor()
    + * complies with its spec.
    + *
    + * The case for testing includes two threads in a debuggee
    + * and their mirrors in a debugger.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs the debugger of the thread2 creation,
    + * and is waiting for reply.
    + * Since the thread2 use the same locking object in its 'run' method
    + * it is locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * suspends the 'main' thread and gets a boolean value returned by
    + * the method VirtualMachine.canGetCurrentContendedMonitor()
    + *
    + * Then if the value is true the debugger checks up that call to
    + * the method mainThread.currentContendedMonitor() doesn't throw
    + * UnsupportedOperationException.
    + * If the value is false the debugger checks up that call to the
    + * the method mainThread.currentContendedMonitor() does throw
    + * UnsupportedOperationException.
    + */ + +public class cangccm001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new cangccm001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor.cangccm001a"; + + private String testedClassName = + "nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor.Threadcangccm001a"; + + //String mName = "nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + List allThreads = null; + ObjectReference monitor = null; + ListIterator listIterator = null; + List classes = null; + + + label0: { + + log2("getting ThreadReference objects"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO 'main' thread ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + + label1: { + if (expresult != returnCode0) + break label1; + + + log2(" supending the main thread"); + mainThread.suspend(); + + if (vm.canGetCurrentContendedMonitor()) { + + log2(".......vm.canGetCurrentContendedMonitor() == true"); + log2(" checking up on no UnsupportedOperationException trown"); + try { + monitor = mainThread.currentContendedMonitor(); + log2(" no Exception thrown"); + } catch ( UnsupportedOperationException e1 ) { + log3("ERROR: UnsupportedOperationException"); + expresult = returnCode1; + } catch ( Exception e2 ) { + expresult = returnCode1; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + } else { + log2(".......vm.canGetCurrentContendedMonitor() == false"); + log2(" checking up on UnsupportedOperationException trown"); + try { + monitor = mainThread.currentContendedMonitor(); + log3("ERROR: no UnsupportedOperationException thrown"); + expresult = returnCode1; + } catch ( UnsupportedOperationException e1 ) { + log2(" UnsupportedOperationException thrown"); + } catch ( Exception e2 ) { + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + expresult = returnCode1; + } + } + log2(" resuming the main thread"); + mainThread.resume(); + } + + log2("......instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001/TestDescription.java new file mode 100644 index 00000000000..624faa42c6c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canGetCurrentContendedMonitor() + * complies with its spec: + * public boolean canGetCurrentContendedMonitor() + * Determines if the target VM supports the retrieval of the monitor for + * which a thread is currently waiting. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor.cangccm001; + * the debuggee program - nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor.cangccm001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor.cangccm001 + * nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor.cangccm001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor.cangccm001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001a.java new file mode 100644 index 00000000000..de29feb1a62 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canGetCurrentContendedMonitor; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the cangccm001 JDI test. + */ + +public class cangccm001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + private static Threadcangccm001a thread2 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canGetMonitorInfo()
    + * complies with its spec.
    + *
    + * The case for testing includes two threads in a debuggee.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs the debugger of the thread2 creation,
    + * and is waiting for reply.
    + * Since the thread2 use the same locking object in its 'run' method
    + * it is locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - gets ThreadReference thread2 mirroring thread2 in the debuggee;
    + * - calls to the method VirtualMachine.canGetCurrentContendedMonitor()
    + * to detect whether debuggee's VM supports corresponding method.
    + * This is because the debugger needs to get a special object,
    + * ObjectReference monitor, mirroring a monitor in the debuggee
    + * on which debuggee's thread2 is locked up and waiting;
    + * - If the needed facility is not supported the debugger cancels the test.
    + * - Othewise, it suspends the thread2, calls to the method
    + * tread2.currentContendedMonitor() to get the object "monitor"
    + * mirroring a monitor in the debuggee and gets a boolean value
    + * returned by the method VirtualMachine.canGetMonitorInfo()
    + *
    + * Then if the value is true the debugger checks up that call to
    + * the method monitor.waitingThreads() doesn't throw
    + * UnsupportedOperationException.
    + * If the value is false the debugger checks up that call to the
    + * the method monitor.waitingThreads() does throw
    + * UnsupportedOperationException.
    + */ + +public class cangetmonitorinfo001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new cangetmonitorinfo001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canGetMonitorInfo.cangetmonitorinfo001a"; + + private String testedClassName = + "nsk.jdi.VirtualMachine.canGetMonitorInfo.Threadcangetmonitorinfo001a"; + + //String mName = "nsk.jdi.VirtualMachine.canGetMonitorInfo"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "Thread2"; + + List allThreads = null; + ObjectReference monitor = null; + ListIterator listIterator = null; + List classes = null; + + + label0: { + + log2("getting ThreadReference objects"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO 'main' thread ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + if (!vm.canGetCurrentContendedMonitor()) { + log2(".......vm.canGetCurrentContendedMonitor() == false; the test is cancelled"); + break label1; + } + log2(".......vm.canGetCurrentContendedMonitor() == true"); + + + log2(" supending the thread2"); + thread2.suspend(); + + log2(" monitor = thread2.currentContendedMonitor();"); + try { + monitor = waitForMonitor(thread2); + } catch ( UnsupportedOperationException e1 ) { + log3("ERROR: UnsupportedOperationException"); + expresult = returnCode1; + } catch ( Exception e2 ) { + expresult = returnCode1; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + e2.printStackTrace(); + } + if (expresult != returnCode0) + break label1; + + + if (vm.canGetMonitorInfo()) { + log2(".......vm.canGetMonitorInfo() == true"); + log2(" checking up on no UnsupportedOperationException trown"); + try { + monitor.waitingThreads(); + log2(" no Exception thrown"); + } catch ( UnsupportedOperationException e1 ) { + log3("ERROR: UnsupportedOperationException"); + expresult = returnCode1; + } catch ( Exception e2 ) { + expresult = returnCode1; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + e2.printStackTrace(); + } + } else { + log2(".......vm.canGetMonitorInfo() == false"); + log2(" checking up on UnsupportedOperationException trown"); + try { + monitor.waitingThreads(); + log3("ERROR: no UnsupportedOperationException thrown"); + expresult = returnCode1; + } catch ( UnsupportedOperationException e1 ) { + log2(" UnsupportedOperationException thrown"); + } catch ( Exception e2 ) { + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + e2.printStackTrace(); + expresult = returnCode1; + } + } + + } + + log2(" resuming the thread2 (for case it was suspended)"); + thread2.resume(); + + log2("......instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + // This function will wait until the debuggee thread has reached its monitor. + // The debuggee thread is already running, and should just be a few instructions + // away from reaching the monitor. We should not have to wait a long time. + // + // The debuggee thread should be suspended before calling this method, + // and it should still be suspended after this call. + private ObjectReference waitForMonitor(ThreadReference threadReference) throws Exception { + // Wait for at most 10 seconds. That is more than enough. + long remainingWaitMs = 10000; + final long iterationWaitMs = 100; + + while (remainingWaitMs >= 0) { + ObjectReference monitor = threadReference.currentContendedMonitor(); + if (monitor != null) { + return monitor; + } + + log2("Waiting for currentContendedMonitor. remainingWaitMs " + remainingWaitMs); + remainingWaitMs -= iterationWaitMs; + + try { + // Resume thread so it can reach its monitor. Suspend again after wait. + threadReference.resume(); + Thread.currentThread().sleep(iterationWaitMs); + } finally { + threadReference.suspend(); + } + } + + String msg = String.format("No currentContendedMonitor in thread '%s'", threadReference); + throw new Exception(msg); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001/TestDescription.java new file mode 100644 index 00000000000..e1c0dfed153 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canGetMonitorInfo() + * complies with its spec: + * public boolean canGetMonitorInfo() + * Determines if this implementation supports the retrieval of + * the monitor information for an object. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canGetMonitorInfo.cangetmonitorinfo001; + * the debuggee program - nsk.jdi.VirtualMachine.canGetMonitorInfo.cangetmonitorinfo001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canGetMonitorInfo.cangetmonitorinfo001 + * nsk.jdi.VirtualMachine.canGetMonitorInfo.cangetmonitorinfo001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canGetMonitorInfo.cangetmonitorinfo001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001a.java new file mode 100644 index 00000000000..7b5af2d6be7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001a.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2001, 2018, 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. + */ +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! templete parameters !!!! +// VirtualMachine InterfaceName VirtualMachine +// canGetMonitorInfo MethodName canGetMonitorInfo +// cangetmonitorinfo001 TestName cangetmonitorinfo001a +// ------------------------------------------------------ + +package nsk.jdi.VirtualMachine.canGetMonitorInfo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the cangetmonitorinfo001 JDI test. + */ + +public class cangetmonitorinfo001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + private static Threadcangetmonitorinfo001a thread2 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canGetOwnedMonitorInfo()
    + * complies with its spec.
    + *
    + * The case for testing includes two threads objects defined
    + * in a debuggee and their mirrors in a debugger.
    + * The test works as follows. After being started up,

    + * the debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs the debugger of the thread2 creation,
    + * and is waiting for reply.
    + * Since the thread2 use the same locking object in its 'run' method
    + * it is locked up until main thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger
    + * suspends the 'main' thread and gets a boolean value returned by
    + * the method VirtualMachine.canGetOwnedMonitorInfo()
    + *
    + * Then if the value is true the debugger checks up that call to the
    + * the method mainThread.ownedMonitors() doesn't throw
    + * UnsupportedOperationException.
    + * If the value is false the debugger checks up that call to the
    + * the method mainThread.ownedMonitors() does throw
    + * UnsupportedOperationException.
    + */ + +public class cangetinfo001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new cangetinfo001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo.cangetinfo001a"; + + private String testedClassName = + "nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo.Threadcangetinfo001a"; + + //String mName = "nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + List allThreads = null; + List monitors = null; + ListIterator listIterator = null; + List classes = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO 'main' thread ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + + label1: { + if (expresult != returnCode0) + break label1; + + + log2(" supending the main thread"); + mainThread.suspend(); + + if (vm.canGetOwnedMonitorInfo()) { + + log2(".......vm.canGetOwnedMonitorInfo() == true"); + log2(" checking up on no UnsupportedOperationException trown"); + try { + monitors = mainThread.ownedMonitors(); + log2(" no Exception thrown"); + } catch ( UnsupportedOperationException e1 ) { + log3("ERROR: UnsupportedOperationException"); + expresult = returnCode1; + } catch ( Exception e2 ) { + expresult = returnCode1; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + } else { + log2(".......vm.canGetOwnedMonitorInfo() == false"); + log2(" checking up on UnsupportedOperationException trown"); + try { + monitors = mainThread.ownedMonitors(); + log3("ERROR: no UnsupportedOperationException thrown"); + expresult = returnCode1; + } catch ( UnsupportedOperationException e1 ) { + log2(" UnsupportedOperationException thrown"); + } catch ( Exception e2 ) { + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + expresult = returnCode1; + } + } + log2(" resuming the main thread"); + mainThread.resume(); + } + + log2("......instructing mainThread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001/TestDescription.java new file mode 100644 index 00000000000..09fda1a4bca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canGetOwnedMonitorInfo() + * complies with its spec: + * public boolean canGetOwnedMonitorInfo() + * Determines if the target VM supports the retrieval of the monitors + * owned by a thread. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo.cangetinfo001; + * the debuggee program - nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo.cangetinfo001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo.cangetinfo001 + * nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo.cangetinfo001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo.cangetinfo001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001a.java new file mode 100644 index 00000000000..bed0b57dc80 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetOwnedMonitorInfo/cangetinfo001a.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canGetOwnedMonitorInfo; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the cangetinfo001 JDI test. + */ + +public class cangetinfo001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + + private static Threadcangetinfo001a thread2 = null; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canGetSourceDebugExtension()
    + * complies with its specification.
    + *
    + * The test checks that the method doesn't throw exceptions.
    + */ + +public class cangetsde001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new cangetsde001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canGetSourceDebugExtension.cangetsde001a"; + + //String mName = "nsk.jdi.VirtualMachine.canGetSourceDebugExtension"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + boolean can = vm.canGetSourceDebugExtension(); + + try { + if (can) + log2(" can"); + else + log2(" cannot"); + } catch ( Throwable t ) { + log3("ERROR: Throwable : " + t); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001/TestDescription.java new file mode 100644 index 00000000000..11e8351e0dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canGetSourceDebugExtension() + * complies with its spec: + * public boolean canGetSourceDebugExtension() + * Determines if the target VM supports getting the source debug extension. + * Returns: true if the feature is supported, false otherwise. + * The test checks that the method doesn't throw exceptions. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canGetSourceDebugExtension.cangetsde001; + * the debuggee program - nsk.jdi.VirtualMachine.canGetSourceDebugExtension.cangetsde001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canGetSourceDebugExtension.cangetsde001 + * nsk.jdi.VirtualMachine.canGetSourceDebugExtension.cangetsde001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canGetSourceDebugExtension.cangetsde001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001a.java new file mode 100644 index 00000000000..43ce902b6ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSourceDebugExtension/cangetsde001a.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canGetSourceDebugExtension; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the cangetsde001 JDI test. + */ + +public class cangetsde001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canGetSyntheticAttribute()
    + * complies with its spec.
    + *
    + * The test works as follows.
    + * After being started up, a debuggee informs a debugger.
    + * Upon the receiption a message from the debuggee, the debugger
    + * - gets the Field flagField object
    + * mirroring int variable "flag" in the debuggee,
    + * - calls to the method VirtualMachine.canGetCurrentContendedMonitor()
    + * to get its returned value.
    + * Then if the value is true the debugger checks up that invoking
    + * the method Field.isSynthetic() on the flagField doesn't throw
    + * UnsupportedOperationException.
    + * If the value is false the debugger checks up that invoking
    + * the method Field.isSynthetic() on the flagField does throw
    + * UnsupportedOperationException.
    + */ + +public class cangetattr001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new cangetattr001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canGetSyntheticAttribute.cangetattr001a"; + + //String mName = "nsk.jdi.VirtualMachine.canGetSyntheticAttribute"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + Field flagField = null; + + label0: { + + log2("......getting Field flagField object"); + testedclass = (ReferenceType) vm.classesByName(debuggeeName).get(0); + flagField = testedclass.fieldByName("flag"); + + + if (vm.canGetSyntheticAttribute()) { + + log2("......vm.canGetSyntheticAttribute() == true"); + log2(" checking up on no UnsupportedOperationException trown"); + try { + flagField.isSynthetic(); + log2(" no Exception thrown"); + } catch ( UnsupportedOperationException e1 ) { + log3("ERROR: UnsupportedOperationException"); + expresult = returnCode1; + } catch ( Exception e2 ) { + expresult = returnCode1; + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + } + + } else { + + log2(".......vm.canGetSyntheticAttribute() == false"); + log2(" checking up on UnsupportedOperationException trown"); + try { + flagField.isSynthetic(); + log3("ERROR: no UnsupportedOperationException thrown"); + expresult = returnCode1; + } catch ( UnsupportedOperationException e1 ) { + log2(" UnsupportedOperationException thrown"); + } catch ( Exception e2 ) { + log3("ERROR: UNEXPECTED Exception is thrown : " + e2); + expresult = returnCode1; + } + } + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001/TestDescription.java new file mode 100644 index 00000000000..df17f9271d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canGetSyntheticAttribute() + * complies with its spec: + * public boolean canGetSyntheticAttribute() + * Determines if the target VM supports the query of the synthetic attribute + * of a method or field. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canGetSyntheticAttribute.cangetattr001; + * the debuggee program - nsk.jdi.VirtualMachine.canGetSyntheticAttribute.cangetattr001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canGetSyntheticAttribute.cangetattr001 + * nsk.jdi.VirtualMachine.canGetSyntheticAttribute.cangetattr001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canGetSyntheticAttribute.cangetattr001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001a.java new file mode 100644 index 00000000000..debd8611aa7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canGetSyntheticAttribute/cangetattr001a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canGetSyntheticAttribute; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the cangetattr001 JDI test. + */ + +public class cangetattr001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> cangetattr001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> cangetattr001a: " + message); + } + + //====================================================== test program + + static int flag = 99; + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canPopFrames()
    + * complies with its spec.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class canpopframes001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canPopFrames/canpopframes001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new canpopframes001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canPopFrames.canpopframes001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("...... vm.canPopFrames()"); + if ( vm.canPopFrames() ) + log2(" vm.canPopFrames() == true"); + else + log2(" vm.canPopFrames() == false"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001/TestDescription.java new file mode 100644 index 00000000000..63e3ad1ea33 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canPopFrames/canpopframes001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canPopFrames() + * complies with its spec: + * public boolean canPopFrames() + * Determines if the target VM supports popping frames of a threads stack. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canPopFrames.canpopframes001; + * the debuggee program - nsk.jdi.VirtualMachine.canPopFrames.canpopframes001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canPopFrames.canpopframes001 + * nsk.jdi.VirtualMachine.canPopFrames.canpopframes001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canPopFrames.canpopframes001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001a.java new file mode 100644 index 00000000000..19aa7c3c7c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canPopFrames; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the canpopframes001 JDI test. + */ + +public class canpopframes001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java new file mode 100644 index 00000000000..c1ecbd95cad --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canRedefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canRedefineClasses()
    + * complies with its spec.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class canredefineclasses001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new canredefineclasses001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canRedefineClasses.canredefineclasses001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("...... vm.canRedefineClasses()"); + if ( vm.canRedefineClasses() ) + log2(" vm.canRedefineClasses() == true"); + else + log2(" vm.canRedefineClasses() == false"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001/TestDescription.java new file mode 100644 index 00000000000..73c0f5bad52 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canRedefineClasses() + * complies with its spec: + * public boolean canRedefineClasses() + * Determines if the target VM supports any level of class redefinition. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canRedefineClasses.canredefineclasses001; + * the debuggee program - nsk.jdi.VirtualMachine.canRedefineClasses.canredefineclasses001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canRedefineClasses.canredefineclasses001 + * nsk.jdi.VirtualMachine.canRedefineClasses.canredefineclasses001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canRedefineClasses.canredefineclasses001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001a.java new file mode 100644 index 00000000000..255e11afbe7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canRedefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the canredefineclasses001 JDI test. + */ + +public class canredefineclasses001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java new file mode 100644 index 00000000000..961901a7857 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canRequestVMDeathEvent; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canRequestVMDeathEvent()
    + * complies with its spec.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class canreqvmdev001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new canreqvmdev001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canRequestVMDeathEvent.canreqvmdev001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("...... canRequestVMDeathEvent()"); + if ( vm.canRequestVMDeathEvent() ) + log2(" vm.canRequestVMDeathEvent() == true"); + else + log2(" vm.canRequestVMDeathEvent() == false"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001/TestDescription.java new file mode 100644 index 00000000000..c9dc8a4cebd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canRequestVMDeathEvent() + * complies with its spec: + * public boolean canRequestVMDeathEvent() + * Determines if the target VM supports the creation of VMDeathRequests. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canRequestVMDeathEvent.canreqvmdev001; + * the debuggee program - nsk.jdi.VirtualMachine.canRequestVMDeathEvent.canreqvmdev001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canRequestVMDeathEvent.canreqvmdev001 + * nsk.jdi.VirtualMachine.canRequestVMDeathEvent.canreqvmdev001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canRequestVMDeathEvent.canreqvmdev001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001a.java new file mode 100644 index 00000000000..53234fdf771 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canRequestVMDeathEvent; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the canreqvmdev001 JDI test. + */ + +public class canreqvmdev001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java new file mode 100644 index 00000000000..f8773004333 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses()
    + * complies with its spec.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class curc001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new curc001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses.curc001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("...... vm.canUnrestrictedlyRedefineClasses()"); + if ( vm.canUnrestrictedlyRedefineClasses() ) + log2(" vm.canUnrestrictedlyRedefineClasses() == true"); + else + log2(" vm.canUnrestrictedlyRedefineClasses() == false"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001/TestDescription.java new file mode 100644 index 00000000000..c2104e509b1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses() + * complies with its spec: + * public boolean canUnrestrictedlyRedefineClasses() + * Determines if the target VM supports unrestricted changes when + * performing class redefinition. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses.curc001; + * the debuggee program - nsk.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses.curc001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses.curc001 + * nsk.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses.curc001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses.curc001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001a.java new file mode 100644 index 00000000000..90b252b8536 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canUnrestrictedlyRedefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the curc001 JDI test. + */ + +public class curc001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java new file mode 100644 index 00000000000..3e73b7f58bc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canUseInstanceFilters; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canUseInstanceFilters()
    + * complies with its spec.
    + *
    + * The test works as follows.
    + * Upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request
    + * for debuggee's ClassPrepareEvent with SUSPEND_EVENT_THREAD,
    + * resumes the VM, and waits for the event within the predefined
    + * time interval. If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD,
    + * the debugger resumes the debuggee and waits for the BreakpointEvent.
    + * The debuggee prepares new check and invokes the methodForCommunication
    + * to be suspended and to inform the debugger with the event.
    + * Upon getting the BreakpointEvent, the debugger performs the check.
    + * At the end, the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class canusefilters001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new canusefilters001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canUseInstanceFilters.canusefilters001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("...... vm.canUseInstanceFilters()"); + if ( vm.canUseInstanceFilters() ) + log2(" vm.canUseInstanceFilters() == true"); + else + log2(" vm.canUseInstanceFilters() == false"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001/TestDescription.java new file mode 100644 index 00000000000..dae09c7bdc9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canUseInstanceFilters() + * complies with its spec: + * public boolean canUseInstanceFilters() + * Determines if the target VM supports filtering events by + * specific instance object. For example, see + * BreakpointRequest.addInstanceFilter(com.sun.jdi.ObjectReference). + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canUseInstanceFilters.canusefilters001; + * the debuggee program - nsk.jdi.VirtualMachine.canUseInstanceFilters.canusefilters001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canUseInstanceFilters.canusefilters001 + * nsk.jdi.VirtualMachine.canUseInstanceFilters.canusefilters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canUseInstanceFilters.canusefilters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001a.java new file mode 100644 index 00000000000..8ee5148cfa1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canUseInstanceFilters; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the canusefilters001 JDI test. + */ + +public class canusefilters001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java new file mode 100644 index 00000000000..9ec3c9afc84 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canWatchFieldAccess; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canWatchFieldAccess()
    + * complies with its spec.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + */ + +public class canwatchaccess001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new canwatchaccess001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canWatchFieldAccess.canwatchaccess001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("...... vm.canWatchFieldAccess()"); + if ( vm.canWatchFieldAccess() ) + log2(" vm.canWatchFieldAccess() == true"); + else + log2(" vm.canWatchFieldAccess() == false"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001/TestDescription.java new file mode 100644 index 00000000000..5f6ed571e86 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canWatchFieldAccess() + * complies with its spec: + * public boolean canWatchFieldAccess() + * Determines if the target VM supports watchpoints for field access. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canWatchFieldAccess.canwatchaccess001; + * the debuggee program - nsk.jdi.VirtualMachine.canWatchFieldAccess.canwatchaccess001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * To fix the bug 4509034 and + * to eliminate the possibility of the bug 4482592 in the test, + * the test is re-implemented on the base of new interaction mechanism + * for communication between a debugger and debuggee. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canWatchFieldAccess.canwatchaccess001 + * nsk.jdi.VirtualMachine.canWatchFieldAccess.canwatchaccess001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canWatchFieldAccess.canwatchaccess001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001a.java new file mode 100644 index 00000000000..195c3154778 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canWatchFieldAccess; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the canwatchaccess001 JDI test. + */ + +public class canwatchaccess001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java new file mode 100644 index 00000000000..d0d6fe245d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canWatchFieldModification; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.canWatchFieldModification()
    + * complies with its spec.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following loop.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check case required.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class canwatchmod001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new canwatchmod001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.canWatchFieldModification.canwatchmod001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + try { + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + } catch ( Exception e ) { + throw e; + } + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(" new check: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("...... vm.canWatchFieldModification()"); + if ( vm.canWatchFieldModification() ) + log2(" vm.canWatchFieldModification() == true"); + else + log2(" vm.canWatchFieldModification() == false"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001/TestDescription.java new file mode 100644 index 00000000000..4d97049322e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.canWatchFieldModification() + * complies with its spec: + * public boolean canWatchFieldModification() + * Determines if the target VM supports watchpoints for field modification. + * Returns: true if the feature is supported, false otherwise. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.canWatchFieldModification.canwatchmod001; + * the debuggee program - nsk.jdi.VirtualMachine.canWatchFieldModification.canwatchmod001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * To fix the bug 4509034 and + * to eliminate the possibility of the bug 4482592 in the test, + * the test is re-implemented on the base of new interaction mechanism + * for communication between a debugger and debuggee. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.canWatchFieldModification.canwatchmod001 + * nsk.jdi.VirtualMachine.canWatchFieldModification.canwatchmod001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.canWatchFieldModification.canwatchmod001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001a.java new file mode 100644 index 00000000000..23dc76c173c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.canWatchFieldModification; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the canwatchmod001 JDI test. + */ + +public class canwatchmod001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001.java new file mode 100644 index 00000000000..7f5416d3908 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.classesByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.classesByName()
    + * complies with the spec for
    + * com.sun.jdi.classesByName methods
    + *
    + * The cases for testing are as follows :
    + *
    + * debuggee debugger
    + * classes loaded
    + *
    + * no vm.classesByName(".Class1ForCheck") ==0
    + *
    + * ".ClassForCheck" vm.classesByName(".Class1ForCheck") ==1
    + * vm.classesByName(".Class2ForCheck") ==0
    + * vm.classesByName(".InterfaceForCheck") ==0
    + *
    + * ".Class2ForCheck" vm.classesByName(".Class2ForCheck") ==1
    + * vm.classesByName(".InterfaceForCheck") ==1
    + *
    + * "Class2ForCheck" vm.classesByName(".Class2ForCheck") ==0
    + */ + +public class classesbyname001 { + + //----------------------------------------------------- template section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- template parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/classesByName/classesbyname001", + sHeader2 = "--> classesbyname001: ", + sHeader3 = "##> classesbyname001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new classesbyname001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.classesByName.classesbyname001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("classesbyname001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1("TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log3(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + String mName = + "nsk.jdi.VirtualMachine.classesByName"; + + log2("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List listVMClasses = null; + int expN = 0; + + switch (i) { + + // no attempt is made to load a class of given name + + case 0: + listVMClasses = vm.classesByName(mName + + ".Class1ForCheck"); + expN = 0; // O#=0; I#=0; + break; + + case 1: + listVMClasses = vm.classesByName(mName + + ".Class1ForCheck"); + expN = 0; // O#=0; I#=0; + break; + + + // Returns the loaded reference types that match a given name + + case 2: + listVMClasses = vm.classesByName(mName + + ".Class1ForCheck"); + expN = 1; // O#=1; I#=0; + break; + case 3: + listVMClasses = vm.classesByName(mName + + ".Class2ForCheck"); + expN = 0; // O#=0; I#=0; + break; + case 4: + listVMClasses = vm.classesByName(mName + + ".InterfaceForCheck"); + expN = 0; // O#=0; I#=0; + break; + case 5: + listVMClasses = vm.classesByName(mName + + ".Class2ForCheck"); + expN = 1; // O#=1; I#=1; + break; + case 6: + listVMClasses = vm.classesByName(mName + + ".InterfaceForCheck"); + expN = 1; // O#=1; I#=1; + break; + + + // not a fully qualified name + + case 7: + listVMClasses = vm.classesByName("Class2ForCheck"); + expN = 0; // O#=2; I#=3?; + break; + + + default: + break ; + } + + if (listVMClasses.size() != expN) { + log3("ERROR: size of returned list != expN but == " + + listVMClasses.size() + "; check # = " + i); + testExitCode = FAILED; + } else { + log2("size of returned list == expN ; check # = " + i); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1("TESTING ENDS"); + + //-------------------------------------------------- test summary section + + + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("ERROR: debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java new file mode 100644 index 00000000000..9fa4e1a9f85 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/classesByName/classesbyname001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.classesByName() + * complies with the following requirements: + * "The name must be fully qualified (for example, java.lang.String). + * The returned list will contain a ReferenceType for each class or + * interface found with given name. + * The search is confined to loaded classes only; no attempt is made + * to load a class of the given name." + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.classesByName.classesbyname001; + * a debuggee program - nsk.jdi.VirtualMachine.classesByName.classesbyname001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe after executing instructions. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data on the state of the debuggee.VM, and compares + * the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.classesByName.classesbyname001 + * nsk.jdi.VirtualMachine.classesByName.classesbyname001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.classesByName.classesbyname001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001a.java new file mode 100644 index 00000000000..470263e5e9b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/classesByName/classesbyname001a.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.classesByName; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the classesbyname001 JDI test. + */ + +public class classesbyname001a { + + //----------------------------------------------------- template section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbose_mode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbose_mode) + System.err.println("**> classesbyname001a: " + message); + } + + private static void logErr(String message) { + if (verbose_mode) + System.err.println("!!**> classesbyname001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.description()
    + * complies with its specification.
    + */ + +public class description001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/description/description001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new description001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.description.description001a"; + + //String mName = "nsk.jdi.VirtualMachine.description"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String description = vm.description(); + if (description == null) { + log3("ERROR: description == null"); + expresult = returnCode1; + } else + log2(" description == " + description); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001/TestDescription.java new file mode 100644 index 00000000000..85272a99426 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/description/description001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.description() + * complies with its spec: + * public java.lang.String description() + * Returns text information on the target VM and the debugger support that + * mirrors it. No specific format for this information is guaranteed. + * Typically, this string contains version information for the target VM and + * debugger interfaces. More precise information on VM and JDI versions + * is available through version(), + * VirtualMachineManager.majorInterfaceVersion(), and + * VirtualMachineManager.minorInterfaceVersion() + * Returns: the description. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.description.description001; + * the debuggee program - nsk.jdi.VirtualMachine.description.description001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.description.description001 + * nsk.jdi.VirtualMachine.description.description001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.description.description001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001a.java new file mode 100644 index 00000000000..ac7722ff422 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/description/description001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.description; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the description001 JDI test. + */ + +public class description001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> description001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> description001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.dispose()
    + * complies with its specification.
    + * The test checks up that after call to VirtualMachine.dispose(),
    + * the communication channel is closed, hence,
    + * the VirtualMachine object becomes invalid.
    + *
    + * The test works as follows.
    + * After launching a debuggee, a debugger gets its VirtualMachine
    + * object (vm), invokes the method vm.dispose(); and performs
    + * checking call to the method vm.allClasses().
    + * An expected correct reaction to the method allClasses() is
    + * throwing VMDisconnectedException.
    + */ + +public class dispose001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/dispose/dispose001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new dispose001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.dispose.dispose001a"; + + //String mName = "nsk.jdi.VirtualMachine.dispose"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + //log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......vm.dispose();"); + vm.dispose(); + + try { + log2("...... try: vm.allClasses(); VMDisconnectedException is expected"); + vm.allClasses(); + log3("ERROR: no VMDisconnectedException"); + testExitCode = FAILED; + } catch ( VMDisconnectedException e1 ) { + log2(" : VMDisconnectedException"); + } catch ( Exception e2 ) { + log3("ERROR: unexpected Exception : " + e2); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001/TestDescription.java new file mode 100644 index 00000000000..60ef68f2f67 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/dispose/dispose001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.dispose() + * complies with its spec: + * public void dispose() + * Invalidates this virtual machine mirror. + * The communication channel to the target VM is closed, and + * the target VM prepares to accept another subsequent connection from + * this debugger or another debugger, including the following tasks: + * All event requests are cancelled. + * All threads suspended by suspend() or by ThreadReference.suspend() + * are resumed as many times as necessary for them to run. + * Garbage collection is re-enabled in all cases where + * it was disabled through ObjectReference.disableCollection(). + * Any current method invocations executing in the target VM are continued + * after the disconnection. Upon completion of any such method invocation, + * the invoking thread continues from the location where + * it was originally stopped. + * Resources originating in this VirtualMachine (ObjectReferences, + * ReferenceTypes, etc.) will become invalid. + * The test checks up that after call to VirtualMachine.dispose(), + * the communication channel is closed, hence, + * the VirtualMachine object becomes invalid. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.dispose.dispose001; + * the debuggee program - nsk.jdi.VirtualMachine.dispose.dispose001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.dispose.dispose001 + * nsk.jdi.VirtualMachine.dispose.dispose001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.dispose.dispose001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001a.java new file mode 100644 index 00000000000..11b76fca184 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose001a.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.dispose; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the dispose001 JDI test. + */ + +public class dispose001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> dispose001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> dispose001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.dispose()
    + * complies with its specification.
    + * The test checks up that after call to VirtualMachine.dispose(),
    + * a breakpoint event request set up before the call,
    + * is cancelled.
    + *
    + * The test work as follows.
    + * Upon launch a debuggee creates new thread which is waiting
    + * until a main thread leaves a synchronized block, and informs
    + * a debugger of the tread creation. The debugger sets up
    + * a breakpoint for the tested thread, performs vm.dispose() and
    + * sleeps for a predefined time-test parameter. Then the debugger
    + * asks the debuggee to check up on the tested thread state
    + * which should be "not alive" if the breakpoint was cancelled.
    + */ + +public class dispose002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/dispose/dispose002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new dispose002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.dispose.dispose002a"; + + private String testedClassName = + "nsk.jdi.VirtualMachine.dispose.Threaddispose002a"; + + //String mName = "nsk.jdi.VirtualMachine.dispose"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" vm.dispose()"); + vm.dispose(); + + if (breakpRequest1.isEnabled()) + log2(" breakpRequest1 is enabled"); + else + log2(" breakpRequest1 is disabled"); + + + log2("......forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + log2(" Thread.sleep(waitTime*60000);"); + try { + Thread.sleep(waitTime*60000); + } catch ( InterruptedException e ) { + log3("ERROR: InterruptedException"); + expresult = returnCode1; + break label1; + } + + log2("......sending to the debuggee: 'check_alive'"); + log2(" expected reply: 'not_alive'"); + pipe.println("check_alive"); + line = pipe.readln(); + if (line.equals("alive")) { + log3("ERROR: thread2 is alive"); + expresult = returnCode1; + } else if (line.equals("not_alive")) { + log2(" thread2 is not alive"); + } else { + log3("ERROR: unexpected reply: " + line); + expresult = returnCode4; + } + + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002/TestDescription.java new file mode 100644 index 00000000000..4e45c88c89b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/dispose/dispose002. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.dispose() + * complies with its spec: + * public void dispose() + * Invalidates this virtual machine mirror. + * The communication channel to the target VM is closed, and + * the target VM prepares to accept another subsequent connection from + * this debugger or another debugger, including the following tasks: + * All event requests are cancelled. + * All threads suspended by suspend() or by ThreadReference.suspend() + * are resumed as many times as necessary for them to run. + * Garbage collection is re-enabled in all cases where + * it was disabled through ObjectReference.disableCollection(). + * Any current method invocations executing in the target VM are continued + * after the disconnection. Upon completion of any such method invocation, + * the invoking thread continues from the location where + * it was originally stopped. + * Resources originating in this VirtualMachine (ObjectReferences, + * ReferenceTypes, etc.) will become invalid. + * The test checks up that after call to VirtualMachine.dispose(), + * debuggee's tested thread is not suspended at a breakpoint set up before, + * hence, corresponding event request is cancelled. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.dispose.dispose002; + * the debuggee program - nsk.jdi.VirtualMachine.dispose.dispose002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.dispose.dispose002 + * nsk.jdi.VirtualMachine.dispose.dispose002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.dispose.dispose002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002a.java new file mode 100644 index 00000000000..52469ccc636 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose002a.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.dispose; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the dispose002 JDI test. + */ + +public class dispose002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.dispose()
    + * complies with its specification.
    + * The test checks up that after call to VirtualMachine.dispose(),
    + * debuggee's thread suspended before the call by a debugger,
    + * with method ThreadReference.suspend(), is resumed and runs.
    + *
    + * The test work as follows.
    + * Upon launch the debuggee creates new thread which is waiting
    + * until a main thread leaves a synchronized block, and informs
    + * the debugger of the thread creation. The debugger suspends
    + * the tested thread, performs vm.dispose() and sleeps
    + * for a predefined time-test parameter. Then the debugger
    + * asks the debuggee to check up on the tested thread state
    + * which should be "not alive" if the thread was resumed.
    + */ + +public class dispose003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/dispose/dispose003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new dispose003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.dispose.dispose003a"; + + private String testedClassName = + "nsk.jdi.VirtualMachine.dispose.Threaddispose003a"; + + //String mName = "nsk.jdi.VirtualMachine.dispose"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" suspending thread2"); + thread2.suspend(); + + + log2(" vm.dispose()"); + vm.dispose(); + + log2("......forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + log2(" Thread.sleep(waitTime*60000);"); + try { + Thread.sleep(waitTime*60000); + } catch ( InterruptedException e ) { + log3("ERROR: InterruptedException"); + expresult = returnCode1; + break label1; + } + + log2("......sending to the debuggee: 'check_alive'"); + log2(" expected reply: 'not_alive'"); + pipe.println("check_alive"); + line = pipe.readln(); + if (line.equals("alive")) { + log3("ERROR: thread2 is alive"); + expresult = returnCode1; + } else if (line.equals("not_alive")) { + log2(" thread2 is not alive"); + } else { + log3("ERROR: unexpected reply: " + line); + expresult = returnCode4; + } + + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003/TestDescription.java new file mode 100644 index 00000000000..5fab7b7a082 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/dispose/dispose003. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.dispose() + * complies with its spec: + * public void dispose() + * Invalidates this virtual machine mirror. + * The communication channel to the target VM is closed, and + * the target VM prepares to accept another subsequent connection from + * this debugger or another debugger, including the following tasks: + * All event requests are cancelled. + * All threads suspended by suspend() or by ThreadReference.suspend() + * are resumed as many times as necessary for them to run. + * Garbage collection is re-enabled in all cases where + * it was disabled through ObjectReference.disableCollection(). + * Any current method invocations executing in the target VM are continued + * after the disconnection. Upon completion of any such method invocation, + * the invoking thread continues from the location where + * it was originally stopped. + * Resources originating in this VirtualMachine (ObjectReferences, + * ReferenceTypes, etc.) will become invalid. + * The test checks up that after call to VirtualMachine.dispose(), + * debuggee's tested thread suspended by the debugger with the method + * ThreadRefrence.suspend(), is resumed and runs. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.dispose.dispose003; + * the debuggee program - nsk.jdi.VirtualMachine.dispose.dispose003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.dispose.dispose003 + * nsk.jdi.VirtualMachine.dispose.dispose003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.dispose.dispose003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003a.java new file mode 100644 index 00000000000..39c491b6fbc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003a.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.dispose; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the dispose003 JDI test. + */ + +public class dispose003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> dispose003a: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> dispose003a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.dispose()
    + * complies with its specification.
    + * The test checks up that after call to VirtualMachine.dispose(),
    + * debuggee's thread suspended before the call by a debugger,
    + * with method VirtualMachine.suspend(), is resumed and runs.
    + *
    + * The test work as follows.
    + * Upon launch the debuggee creates new thread which is waiting
    + * until a main thread leaves a synchronized block, and informs
    + * the debugger of the thread creation. The debugger suspends
    + * all threads, resumes the main thread, performs vm.dispose()
    + * and sleeps for a predefined time-test parameter.
    + * Then the debugger
    + * asks the debuggee to check up on the tested thread state
    + * which should be "not alive" if the thread was resumed.
    + */ + +public class dispose004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/dispose/dispose004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new dispose004().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.dispose.dispose004a"; + + private String testedClassName = + "nsk.jdi.VirtualMachine.dispose.Threaddispose004a"; + + //String mName = "nsk.jdi.VirtualMachine.dispose"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String threadName = "testedThread"; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" suspending Virtual Machine"); + vm.suspend(); + log2(" resuming debuggee's main thread"); + mainThread.resume(); + + + log2(" checking up on mainThread state: not suspened is expected"); + if (!mainThread.isSuspended()) { + log2(" mainThread is not suspended"); + } else { + log3("ERROR: mainThread is suspended"); + expresult = returnCode1; + break label1; + } + + log2(" vm.dispose()"); + vm.dispose(); + + log2("......forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + log2(" Thread.sleep(waitTime*60000);"); + try { + Thread.sleep(waitTime*60000); + } catch ( InterruptedException e ) { + log3("ERROR: InterruptedException"); + expresult = returnCode1; + break label1; + } + + log2("......sending to the debuggee: 'check_alive'"); + log2(" expected reply: 'not_alive'"); + pipe.println("check_alive"); + line = pipe.readln(); + if (line.equals("alive")) { + log3("ERROR: thread2 is alive"); + expresult = returnCode1; + } else if (line.equals("not_alive")) { + log2(" thread2 is not alive"); + } else { + log3("ERROR: unexpected reply: " + line); + expresult = returnCode4; + } + + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004/TestDescription.java new file mode 100644 index 00000000000..2586fd29661 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/dispose/dispose004. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.dispose() + * complies with its spec: + * public void dispose() + * Invalidates this virtual machine mirror. + * The communication channel to the target VM is closed, and + * the target VM prepares to accept another subsequent connection from + * this debugger or another debugger, including the following tasks: + * All event requests are cancelled. + * All threads suspended by suspend() or by ThreadReference.suspend() + * are resumed as many times as necessary for them to run. + * Garbage collection is re-enabled in all cases where + * it was disabled through ObjectReference.disableCollection(). + * Any current method invocations executing in the target VM are continued + * after the disconnection. Upon completion of any such method invocation, + * the invoking thread continues from the location where + * it was originally stopped. + * Resources originating in this VirtualMachine (ObjectReferences, + * ReferenceTypes, etc.) will become invalid. + * The test checks up that after call to VirtualMachine.dispose(), + * debuggee's tested thread suspended by the debuggee with the method + * Thread.suspend(), is resumed and runs. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.dispose.dispose004; + * the debuggee program - nsk.jdi.VirtualMachine.dispose.dispose004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.dispose.dispose004 + * nsk.jdi.VirtualMachine.dispose.dispose004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.dispose.dispose004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004a.java new file mode 100644 index 00000000000..46aa79d58d4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose004a.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.dispose; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the dispose004 JDI test. + */ + +public class dispose004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> dispose004a: " + message); + } + + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> dispose004a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.dispose()
    + * complies with its specification.
    + * The test checks up that after call to VirtualMachine.dispose(),
    + * a method invocations executing in the target VM is continued,
    + * and upon completion of the method invocation,
    + * the invoking thread continues from the location where
    + * it was originally stopped.
    + *
    + * The test work as follows.
    + * Upon its launch the debuggee :
    + * creates new thread, thread2 which is waiting until
    + * the main thread leaves a synchronized block, and
    + * informs the debugger of the thread creation.
    + * The thread2 contains a method to be invoked from the debugger
    + * The debugger :
    + * sets up a breakpoint for debuggee's thread2,
    + * instructs the debuggee to leave the synchronized block in
    + * order to get its thread2 suspended at the breakpoint,
    + * waits for a reply from the debuggee.
    + * The debuggee :
    + * leaves the synchronized block and
    + * enter another synchronized block to lock itself at a monitor
    + * which the method "runt2" to be invoked from
    + * the debugger will unlock,
    + * informs the debugger and waits for new instruction.
    + * The debugger :
    + * upon getting the thread2 at the breakpoint,
    + * creates its own Thread object, named thread2 too,
    + * gets its thread2 running;
    + * debuggee's thread2 suspended at the breakpoint;
    + * the method is at once locked at the monitor holding by
    + * debuggee's main thread;
    + * instructs the debuggee to check whether "runt2" is invoked.
    + * The debuggee :
    + * upon getting unlocked by "runt2",
    + * informs the debugger and waits for new instruction.
    + * The debugger : + * clears interruption status,
    + * invokes vm.dispose() that results in
    + * VMDisconnectException in the thread2
    + * which has been suspended after invoking "runt2"
    + * but after exception it is resumed and sends interruption
    + * to the main thread;
    + * if the interruption is not received yet,
    + * sleeps for a predefined waitTime and within this time
    + * catchs InterruptedException;
    + * Then the debugger
    + * asks the debuggee to check up on its thread2 state
    + * which should be "not alive" if the thread2 was resumed.
    + */ + +public class dispose005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + public static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/dispose/dispose005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new dispose005().runThis(argv, out); + } + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + public static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.dispose.dispose005a"; + + private String testedClassName = + "nsk.jdi.VirtualMachine.dispose.Threaddispose005a"; + + //String mName = "nsk.jdi.VirtualMachine.dispose"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + static ReferenceType testedclass = null; + static ClassType classType = null; + + static ThreadReference thread2 = null; + static ThreadReference mainThread = null; + + static ObjectReference threadObjRef = null; + + + public static int testExitCode = PASSED; + + static final int returnCode0 = 0; + public static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + + static Thread currentThread = Thread.currentThread(); + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + int expresult = returnCode0; + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "testedThread"; + + String breakpointMethod1 = "runt1"; + //String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + //String bpLine2 = "breakpointLineNumber2"; + //String bpLine3 = "breakpointLineNumber3"; + + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + //BreakpointRequest breakpRequest2 = null; + //BreakpointRequest breakpRequest3 = null; + + StackFrame stackFrame = null; + + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + classType = (ClassType) testedclass; + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + mainThread = debuggee.threadByName("main"); + thread2 = debuggee.threadByName(threadName); + threadObjRef = thread2; + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + + log2("......forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + } + + if (expresult != returnCode0) + break label1; + + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" testedThread is at breakpoint"); + + + Threaddispose005 thread2 = new Threaddispose005("Thread2"); + log2("......thread2 is created"); + + synchronized (Threaddispose005.lockingObject) { + synchronized (Threaddispose005.waitnotifyObj) { + log2(" synchronized (waitnotifyObj) { enter"); + log2(" before: thread2.start()"); + thread2.start(); + + try { + log2(" before: waitnotifyObj.wait();"); + Threaddispose005.waitnotifyObj.wait(); + log2(" after: waitnotifyObj.wait();"); + + } catch ( Exception e2) { + log3("ERROR: Exception : " + e2 ); +//? pipe.println("waitnotifyerr"); + } + } + } + log2("mainThread is out of: synchronized (lockingObject)"); + + + + log2("......line = pipe.readln(); 'method_invoked' is expected"); + line = pipe.readln(); + if (!line.equals("method_invoked")) { + log3("ERROR: unexpected reply: " + line); + expresult = returnCode4; + break label1; + } + + if (Thread.interrupted()) + log2(" ==>Thread.interrupted()"); + + log2(" vm.dispose()"); + vm.dispose(); + + + if (!Thread.interrupted()) { + log2(" Thread.sleep(waitTime*60000);"); + try { + Thread.sleep(waitTime*60000); + } catch ( InterruptedException e ) { + log2(" : InterruptedException"); + } + } + + log2("......sending to the debuggee: 'check_alive'"); + log2(" expected reply: 'not_alive'"); + pipe.println("check_alive"); + line = pipe.readln(); + if (line.equals("alive")) { + log3("ERROR: testedThread is alive"); + expresult = returnCode1; + } else if (line.equals("not_alive")) { + log2(" testedThread is not alive"); + } else { + log3("ERROR: unexpected reply: " + line); + expresult = returnCode4; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (expresult != returnCode0) + { + log3("expresult != 0 (= " + expresult + ")"); + + testExitCode = FAILED; + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + case 14: VMDisconnectEvent wmde = (VMDisconnectEvent) ev; + log2(" VMDisconnectEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + + +} + +class Threaddispose005 extends Thread { + + public Threaddispose005 (String threadName) { + super(threadName); + } + + public static Object waitnotifyObj = new Object(); + public static Object lockingObject = new Object(); + + + public void run() { + log("method 'run' enter"); + + synchronized (waitnotifyObj) { + log("entered into block: synchronized (waitnotifyObj)"); + waitnotifyObj.notify(); + } + log("exited from block: synchronized (waitnotifyObj)"); + synchronized (lockingObject) { + log("entered into block: synchronized (lockingObject)"); + } + log("exited from block: synchronized (lockingObject)"); + + + List invokeMethods = dispose005.testedclass.methodsByName("runt2"); + Method invokeMethod = invokeMethods.get(0); + + List argumentList = Collections.emptyList(); + + try { + log("......invoking a method in the debuggee; VMDisconnectedException is expected"); + dispose005.threadObjRef.invokeMethod(dispose005.thread2, + invokeMethod, argumentList, 0); + } catch ( VMDisconnectedException e ) { + log(" : VMDisconnectedException "); + } catch ( Exception t ) { + log("ERROR: Exception:" + t); + dispose005.testExitCode = dispose005.FAILED; + } + log("dispose005.currentThread.interrupt();"); + dispose005.currentThread.interrupt(); + + + log("method 'run' exit"); + return; + } + + void log(String str) { + dispose005.log2("thread2: " + str); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005/TestDescription.java new file mode 100644 index 00000000000..6dc631a4a94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005/TestDescription.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/dispose/dispose005. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.dispose() + * complies with its spec: + * public void dispose() + * Invalidates this virtual machine mirror. + * The communication channel to the target VM is closed, and + * the target VM prepares to accept another subsequent connection from + * this debugger or another debugger, including the following tasks: + * All event requests are cancelled. + * All threads suspended by suspend() or by ThreadReference.suspend() + * are resumed as many times as necessary for them to run. + * Garbage collection is re-enabled in all cases where + * it was disabled through ObjectReference.disableCollection(). + * Any current method invocations executing in the target VM are continued + * after the disconnection. Upon completion of any such method invocation, + * the invoking thread continues from the location where + * it was originally stopped. + * Resources originating in this VirtualMachine (ObjectReferences, + * ReferenceTypes, etc.) will become invalid. + * Any current method invocations executing in the target VM are continued + * after the disconnection. Upon completion of any such method invocation, + * the invoking thread continues from the location where + * it was originally stopped. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.dispose.dispose005; + * the debuggee program - nsk.jdi.VirtualMachine.dispose.dispose005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.dispose.dispose005 + * nsk.jdi.VirtualMachine.dispose.dispose005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.dispose.dispose005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005a.java new file mode 100644 index 00000000000..a6cb14f5fd9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005a.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.dispose; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the dispose005 JDI test. + */ + +public class dispose005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> dispose005a: " + message); + } + + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> dispose005a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.eventQueue()
    + * complies with its specification.
    + *
    + * The test checks up that values of two EventQueue variables,
    + * one static and one instance, after assigning them results of
    + * two calls to the method VirtualMachine.eventQueue(),
    + * are equal.
    + */ + +public class eventqueue001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/eventQueue/eventqueue001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new eventqueue001().runThis(argv, out); + } + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.eventQueue.eventqueue001a"; + + //String mName = "nsk.jdi.VirtualMachine.eventQueue"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static EventQueue eventQueue1 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + EventQueue eventQueue2 = null; + + + log2("...... getting two EventQueue objects, one is static, another one is instance"); + eventQueue1 = vm.eventQueue(); + eventQueue2 = vm.eventQueue(); + if (eventQueue1 == null) { + log3("ERROR: eventQueue1 == null"); + expresult = returnCode1; + } + if (eventQueue2 == null) { + log3("ERROR: eventQueue2 == null"); + expresult = returnCode1; + } + if (expresult == returnCode0) { + log2("...... compareing two EventQueue objects"); + if (!eventQueue1.equals(eventQueue2)) { + log3("ERROR: !eventQueue1.equals(eventQueue2)"); + expresult = returnCode1; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001/TestDescription.java new file mode 100644 index 00000000000..d5080060f01 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/eventQueue/eventqueue001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.eventQueue() + * complies with its spec: + * public EventQueue eventQueue() + * Returns the event queue for this virtual machine. + * A virtual machine has only one EventQueue object, + * this method will return the same instance each time it is invoked. + * Returns: the EventQueue for this virtual machine. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.eventQueue.eventqueue001; + * the debuggee program - nsk.jdi.VirtualMachine.eventQueue.eventqueue001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.eventQueue.eventqueue001 + * nsk.jdi.VirtualMachine.eventQueue.eventqueue001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.eventQueue.eventqueue001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001a.java new file mode 100644 index 00000000000..d052fa3c32e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventQueue/eventqueue001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.eventQueue; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the eventqueue001 JDI test. + */ + +public class eventqueue001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> eventqueue001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> eventqueue001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.eventRequestManager()
    + * complies with its specification.
    + *
    + * The test checks up that values of two EventRequestManager variables,
    + * one static and one instance, after assigning them results of
    + * two calls to the method VirtualMachine.eventRequestManager(),
    + * are equal.
    + */ + +public class eventrmanager001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new eventrmanager001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.eventRequestManager.eventrmanager001a"; + + //String mName = "nsk.jdi.VirtualMachine.eventRequestManager"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static EventRequestManager eventRManager1 = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + EventRequestManager eventRManager2 = null; + + + log2("...... getting two EventRequestManager objects, one is static, another one is instance"); + eventRManager1 = vm.eventRequestManager(); + eventRManager2 = vm.eventRequestManager(); + if (eventRManager1 == null) { + log3("ERROR: eventRManager1 == null"); + expresult = returnCode1; + } + if (eventRManager2 == null) { + log3("ERROR: eventRManager2 == null"); + expresult = returnCode1; + } + if (expresult == returnCode0) { + log2("...... compareing two EventRequestManager objects"); + if (!eventRManager1.equals(eventRManager2)) { + log3("ERROR: !eventRManager1.equals(eventRManager2)"); + expresult = returnCode1; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001/TestDescription.java new file mode 100644 index 00000000000..e8a92778991 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.eventRequestManager() + * complies with its spec: + * public EventRequestManager eventRequestManager() + * Returns the event request manager for this virtual machine. + * The EventRequestManager controls user settable events such as breakpoints. + * A virtual machine has only one EventRequestManager object, + * this method will return the same instance each time it is invoked. + * Returns: the EventRequestManager for this virtual machine. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.eventRequestManager.eventrmanager001; + * the debuggee program - nsk.jdi.VirtualMachine.eventRequestManager.eventrmanager001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.eventRequestManager.eventrmanager001 + * nsk.jdi.VirtualMachine.eventRequestManager.eventrmanager001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.eventRequestManager.eventrmanager001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001a.java new file mode 100644 index 00000000000..b494753c90e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/eventRequestManager/eventrmanager001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.eventRequestManager; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the eventrmanager001 JDI test. + */ + +public class eventrmanager001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> eventrmanager001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> eventrmanager001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.exit()
    + * complies with its specification.
    + * The test checks up that after call to VirtualMachine.exit(),
    + * the communication channel is closed, hence,
    + * the VirtualMachine object becomes invalid.
    + *
    + * The test works as follows.
    + * After launching a debuggee, a debugger gets its VirtualMachine
    + * object (vm), invokes the method vm.exit(0); and performs
    + * checking call to the method vm.allClasses().
    + * An expected correct reaction to the method allClasses() is
    + * throwing VMDisconnectedException.
    + */ + +public class exit001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + + static final int FAILED = 2; + + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String sHeader1 = "\n==> nsk/jdi/VirtualMachine/exit/exit001 ", sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main(String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new exit001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = "nsk.jdi.VirtualMachine.exit.exit001a"; + + //String mName = "nsk.jdi.VirtualMachine.exit"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + + static final int returnCode1 = 1; + + static final int returnCode2 = 2; + + static final int returnCode3 = 3; + + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis(String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + log1(" TESTING BEGINS"); + + log2("......vm.exit(0);"); + vm.exit(0); + + try { + log2("...... try: vm.allClasses(); VMDisconnectedException is expected"); + vm.allClasses(); + log3("ERROR: no VMDisconnectedException"); + testExitCode = FAILED; + } catch (VMDisconnectedException e1) { + log2(" : VMDisconnectedException"); + } catch (Exception e2) { + log3("ERROR: unexpected Exception : " + e2); + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001/TestDescription.java new file mode 100644 index 00000000000..fdaa4aa4eb5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/exit/exit001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.exit() + * complies with its spec: + * public void exit(int exitCode) + * Causes the mirrored VM to terminate with the given error code. + * All resources associated with this VirtualMachine are freed. + * If the mirrored VM is remote, the communication channel to it will be closed. + * Resources originating in this VirtualMachine (ObjectReferences, + * ReferenceTypes, etc.) will become invalid. + * Threads running in the mirrored VM are abruptly terminated. + * A thread death exception is not thrown and finally blocks are not run. + * Parameters: exitCode - the exit code for the target VM. + * The test checks up that after call to VirtualMachine.exit(), + * the communication channel is closed, hence, + * the VirtualMachine object becomes invalid. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.exit.exit001; + * the debuggee program - nsk.jdi.VirtualMachine.exit.exit001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.exit.exit001 + * nsk.jdi.VirtualMachine.exit.exit001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.exit.exit001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001a.java new file mode 100644 index 00000000000..93bc079a1b8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit001a.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.exit; + +import nsk.share.Log; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the exit001 JDI test. + */ + +public class exit001a { + + static Log log; + + private static void log1(String message) { + log.display("**> exit001a: " + message); + } + + public static void main(String argv[]) { + // informing a debugger of readiness + ArgumentHandler argHandler = new ArgumentHandler(argv); + + log = argHandler.createDebugeeLog(); + log1("debuggee started!"); + + IOPipe pipe = argHandler.createDebugeeIOPipe(); + pipe.println("ready"); + + /* + * In this test debugger kills debuggee using VirtualMachine.exit, so + * standard JDI tests communication protocol isn't used here + */ + try { + Thread.sleep(Long.MAX_VALUE); + } catch (Throwable t) { + // ignore all exceptions + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002.java new file mode 100644 index 00000000000..d63b13519da --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.exit; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; +import com.sun.jdi.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.exit()
    + * complies with its specification.
    + *
    + * The test works as follows.
    + * After launching a debuggee, a debugger gets its VirtualMachine
    + * object (vm), invokes the method vm.exit(testedReturnCode);
    + * and is waiting for the debuggee to finish and to return
    + * its exit code which should be testedReturnCode
    + * if debuggee's main thread death exception is not thrown.
    + * If the thread death exception is do thrown
    + * the exit code is FAILED.
    + */ + +public class exit002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + + static final int FAILED = 2; + + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String sHeader1 = "\n==> nsk/jdi/VirtualMachine/exit/exit002 ", sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main(String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new exit002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = "nsk.jdi.VirtualMachine.exit.exit002a"; + + //String mName = "nsk.jdi.VirtualMachine.exit"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + + static final int returnCode1 = 1; + + static final int returnCode2 = 2; + + static final int returnCode3 = 3; + + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis(String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + // Linux returns only 8 least significant bits of exit status - see #4459019 bug. + int testedReturnCode = 0x7F; + + log2("......Call vm.exit(testedReturnCode) with exit code: " + testedReturnCode); + vm.exit(testedReturnCode); + + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != testedReturnCode) { + log3("debuggee returned UNEXPECTED exit status: " + testedReturnCode); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + testedReturnCode); + } + + log1(" TESTING ENDS"); + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002/TestDescription.java new file mode 100644 index 00000000000..f60fe44cc00 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/exit/exit002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.exit() + * complies with its spec: + * public void exit(int exitCode) + * Causes the mirrored VM to terminate with the given error code. + * All resources associated with this VirtualMachine are freed. + * If the mirrored VM is remote, the communication channel to it will be closed. + * Resources originating in this VirtualMachine (ObjectReferences, + * ReferenceTypes, etc.) will become invalid. + * Threads running in the mirrored VM are abruptly terminated. + * A thread death exception is not thrown and finally blocks are not run. + * Parameters: exitCode - the exit code for the target VM. + * The test checks up that after call to VirtualMachine.exit(testedReturnCode), + * a thread death exception is not thrown and + * debuggee's exit code is equal to testedReturnCode. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.exit.exit002; + * the debuggee program - nsk.jdi.VirtualMachine.exit.exit002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4759453 TEST_BUG: tests against VirtualMachine.exit(int) should be corrected for Mantis + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.exit.exit002 + * nsk.jdi.VirtualMachine.exit.exit002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.exit.exit002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002a.java new file mode 100644 index 00000000000..c90f7f63e0e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/exit/exit002a.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.exit; + +import nsk.share.Log; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the exit002 JDI test. + */ + +public class exit002a { + + static Log log; + + private static void log1(String message) { + log.display("**> exit002a: " + message); + } + + public static void main(String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + + log = argHandler.createDebugeeLog(); + log1("debuggee started!"); + + // informing a debugger of readyness + IOPipe pipe = argHandler.createDebugeeIOPipe(); + pipe.println("ready"); + + /* + * In this test debugger kills debuggee using VirtualMachine.exit, so + * standard JDI tests communication protocol isn't used here + */ + try { + Thread.sleep(Long.MAX_VALUE); + } catch (Throwable t) { + // ignore all exceptions + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001.java new file mode 100644 index 00000000000..a36f5eee74a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.getDefaultStratum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.getDefaultStratum()
    + * complies with its specification.
    + *
    + * The test checks that String returned by the method
    + * VirtualMachine.getDefaultStratum() is null
    + * if the default stratum has not been set with setDefaultStratum(String).
    + *
    + */ + +public class getdefaultstratum001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new getdefaultstratum001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.getDefaultStratum.getdefaultstratum001a"; + + //String mName = "nsk.jdi.VirtualMachine.getDefaultStratum"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String defaultStratum = vm.getDefaultStratum(); + + if (defaultStratum != null) { + log3("ERROR: defaultStratum != null : " + defaultStratum); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001/TestDescription.java new file mode 100644 index 00000000000..eedee8160f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.getDefaultStratum() + * complies with its spec: + * public String getDefaultStratum() + * Return this VM's default stratum. + * Returns: null (meaning that the per-class default - + * ReferenceType.defaultStratum() - should be used) unless + * the default stratum has been set with setDefaultStratum(String). + * The test checks that a returned value is null if + * the default stratum has not been set with setDefaultStratum(String). + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.getDefaultStratum.getdefaultstratum001; + * the debuggee program - nsk.jdi.VirtualMachine.getDefaultStratum.getdefaultstratum001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.getDefaultStratum.getdefaultstratum001 + * nsk.jdi.VirtualMachine.getDefaultStratum.getdefaultstratum001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.getDefaultStratum.getdefaultstratum001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001a.java new file mode 100644 index 00000000000..c0e104d8b05 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/getDefaultStratum/getdefaultstratum001a.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.getDefaultStratum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the getdefaultstratum001 JDI test. + */ + +public class getdefaultstratum001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } +/* + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } +*/ + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-forceGC")) + forceGC = true; + else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + protected String debuggeeClassName() { + return nsk.share.jdi.HeapwalkingDebuggee.class.getName(); + } + + protected void doTest() { + String testClassNames[] = { "nsk.share.jdi.TestClass1", "nsk.share.jdi.TestClass2", "nsk.share.jdi.TestInterfaceImplementer1"}; + + int testInstanceCount[] = { 2, 20, 1000, 500 }; + + //create instances + for (int i = 0; i < testClassNames.length; i++) { + pipe.println(HeapwalkingDebuggee.COMMAND_CREATE_INSTANCES + ":" + testClassNames[i] + ":" + testInstanceCount[i]); + checkDebugeeAnswer_instanceCounts(testClassNames[i], testInstanceCount[i]); + } + + testInstanceCounts(); + + //delete half of instances + for (int i = 0; i < testClassNames.length; i++) { + int deleteCount = (testInstanceCount[i] / 2); + + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + testClassNames[i] + ":" + deleteCount); + + testInstanceCount[i] -= deleteCount; + checkDebugeeAnswer_instanceCounts(testClassNames[i], testInstanceCount[i]); + } + + if (forceGC) { + forceGC(); + } + + testInstanceCounts(); + + //delete all instances + for (int i = 0; i < testClassNames.length; i++) { + int deleteCount = testInstanceCount[i]; + + pipe.println(HeapwalkingDebuggee.COMMAND_DELETE_INSTANCES + ":" + testClassNames[i] + ":" + deleteCount); + + testInstanceCount[i] -= deleteCount; + checkDebugeeAnswer_instanceCounts(testClassNames[i], testInstanceCount[i]); + } + + testInstanceCounts(); + + } + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts002/TestDescription.java new file mode 100644 index 00000000000..8502ee0d4a9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts002/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/instanceCounts/instancecounts002. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This scenario in particular cover the situation described in CR 6376715. + * The test scenario is following: + * - the debugger gets the debuggee running on another JavaVM and + * establishes a pipe with the debuggee program + * - upon receiving corresponding command from the debugger process the debuggee + * loads set of classes and creates the number of class instances + * - the debugger process check that instanceCounts returns correct number + * - the debuggee process delete previously created objects + * (make them unreachable) + * - the debugger process checks that instanceCounts returns 0 and no + * com.sun.jdi.ObjectCollectedException is thrown + * Test execute class nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 with parameter -forceGC + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 + * nsk.share.jdi.TestClass1 + * nsk.share.jdi.TestClass2 + * nsk.share.jdi.TestInterfaceImplementer1 + * @run main/othervm/native PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + * -forceGC + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts003/instancecounts003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts003/instancecounts003.java new file mode 100644 index 00000000000..79e59f2f524 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts003/instancecounts003.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/instanceCounts/instancecounts003. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This scenario in particular cover the situation described in CR 6376715. + * The test scenario is following: + * - the debugger gets the debuggee running on another JavaVM and + * establishes a pipe with the debuggee program + * - upon receiving corresponding command from the debugger process the debuggee + * do load set of classes. No instances of classes are created + * - the debugger process check that instanceCounts returns 0 + * - the debuggee process drop all references to the class and forces VM + * to unload them. + * - the debuggee process will check that instanceCounts returns 0 and no + * com.sun.jdi.ObjectCollectedException or com.sun.jdi.ClassNotLoadedException + * exception is thrown. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.instanceCounts.instancecounts003.instancecounts003 + * nsk.share.jdi.TestClass1 + * nsk.share.jdi.TestInterfaceImplementer1 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.instanceCounts.instancecounts003.instancecounts003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + */ + +package nsk.jdi.VirtualMachine.instanceCounts.instancecounts003; + +import java.io.PrintStream; +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.*; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class instancecounts003 extends HeapwalkingDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new instancecounts003().runIt(argv, out); + } + + protected String debuggeeClassName() { + if (classpath == null) { + throw new TestBug("Debugger requires 'testClassPath' parameter"); + } + + return AbstractJDIDebuggee.class.getName() + " -testClassPath " + classpath; + } + + protected void doTest() { + String testClassNames[] = { "nsk.share.jdi.TestClass1", "nsk.share.jdi.TestInterfaceImplementer1" }; + + // load classes, don't create instances, check that instancCounts returns 0 + for (String className : testClassNames) { + pipe.println(AbstractDebuggeeTest.COMMAND_LOAD_CLASS + ":" + className); + checkDebugeeAnswer_instanceCounts(className, 0); + } + + testInstanceCounts(); + + // unload classes, check that instancCounts returns 0 and there are no unexpected exceptions + for (String className : testClassNames) { + pipe.println(AbstractDebuggeeTest.COMMAND_UNLOAD_CLASS + ":" + className); + checkDebugeeAnswer_instanceCounts(className, 0); + } + + testInstanceCounts(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004.java new file mode 100644 index 00000000000..c1bdc45f9f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/instanceCounts/instancecounts004. + * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test against method "VirtualMachine.instanceCounts()". + * Test scenario: + * - Repeat the following steps 3 times: + * - Debuggee VM: create the number of different objects to consume 30% of available memory + * - Debuggee VM: create new thread 'GCProvocateur' which will try to consume the rest of memory to provoke GC + * - Debugger VM: at the same time call VirtualMachine.instanceCounts(VirtualMachine.allClasses()) 10 times + * - Debuggee VM: stop 'GCProvocateur' thread + * Test is treated as passed if no any unexpected events was caught during test execution and debuggee VM doesn't crash. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.instanceCounts.instancecounts004.instancecounts004 + * nsk.jdi.VirtualMachine.instanceCounts.instancecounts004.instancecounts004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.instanceCounts.instancecounts004.instancecounts004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.VirtualMachine.instanceCounts.instancecounts004; + +import java.io.PrintStream; +import java.util.*; +import nsk.share.Consts; +import nsk.share.jdi.HeapwalkingDebugger; +import nsk.share.test.Stresser; + +public class instancecounts004 extends HeapwalkingDebugger { + + // It is possible to specify 'testCount', 'methodCallCount' via command line (for example: -methodCallCount 10) + + // test iterations count + private int testCount = 1; + + // how many times call vm.instanceCounts() during single iteration + private int methodCallCount = 10; + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new instancecounts004().runIt(argv, out); + } + + protected String debuggeeClassName() { + return instancecounts004a.class.getName(); + } + + // initialize test and remove arguments unsupported by nsk.share.jdi.ArgumentHandler + protected String[] doInit(String[] args, PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testCount") && (i < args.length - 1)) { + testCount = Integer.parseInt(args[i + 1]); + i++; + } else if (args[i].equals("-methodCallCount") && (i < args.length - 1)) { + methodCallCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + protected void testInstanceCounts(Stresser stresser) { + for (int i = 0; i < methodCallCount && stresser.continueExecution(); i++) { + try { + log.display("Doing vm.instanceCounts(vm.allClasses())"); + vm.instanceCounts(vm.allClasses()); + } catch (Throwable e) { + setSuccess(false); + log.complain("Unexpected exception: " + e); + e.printStackTrace(log.getOutStream()); + } + } + } + + protected void doTest() { + log.display("Use testCount = " + testCount); + log.display("Use methodCallCount = " + methodCallCount); + + stresser.start(testCount); + + try { + while (stresser.iteration()) { + pipe.println(instancecounts004a.COMMAND_CONSUME_MEMORY + ":" + 0.3); + + if (!isDebuggeeReady()) + break; + + pipe.println(instancecounts004a.COMMAND_START_GC_PROVOCATEUR); + + if (!isDebuggeeReady()) + break; + + testInstanceCounts(stresser); + + pipe.println(instancecounts004a.COMMAND_STOP_GC_PROVOCATEUR); + + if (!isDebuggeeReady()) + break; + } + + if (stresser.getIterationsLeft() > 0) { + log.display("Test execution stopped because of test time exceeded"); + } + } finally { + stresser.finish(); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004a.java new file mode 100644 index 00000000000..037c0d6a26a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts004/instancecounts004a.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.jdi.VirtualMachine.instanceCounts.instancecounts004; + +import nsk.share.Consts; +import nsk.share.TestBug; +import nsk.share.jdi.*; + +import java.io.*; +import java.util.*; + +/* + * This debuggee class handle requests for start/stop thread which provokes GC + */ +public class instancecounts004a extends HeapwalkingDebuggee { + static public final String COMMAND_START_GC_PROVOCATEUR = "startGCProvokateur"; + + static public final String COMMAND_STOP_GC_PROVOCATEUR = "stopGCProvokateur"; + + static public final String COMMAND_CONSUME_MEMORY = "consumeMemory"; + + protected GCProvokateur provokateur; + + class GCProvokateur extends Thread { + public volatile boolean stop; + + Collection garbage; + + public void run() { + while (!stop) { + try { + while (!stop) { + long memory = Runtime.getRuntime().freeMemory() / 100; + + int arraySize; + + if (memory > Integer.MAX_VALUE) + arraySize = Integer.MAX_VALUE; + else + arraySize = (int) memory; + + garbage = new ArrayList(); + + for (int i = 0; i < 50; i++) + garbage.add(new byte[arraySize]); + + try { + Thread.sleep(10); + } catch (InterruptedException e) { + + } + } + } catch (OutOfMemoryError ignoreError) { + } + } + } + } + + // create large list to increase time needed for VirtualMachine.instanceCount + ArrayList garbageList = new ArrayList(); + + protected String[] doInit(String args[]) { + args = super.doInit(args); + + for (int i = 0; i < 250000; i++) { + TestClass1 t1 = new TestClass1(); + TestClass2 t2 = new TestClass2(); + garbageList.add(t1); + garbageList.add(t2); + } + return args; + } + + protected void consumeMemory(double consumedPart) { + Collection garbage = new ArrayList(); + + log.display("consumeMemory: " + consumedPart); + + if ((consumedPart > 1.0) || (consumedPart < 0)) { + throw new TestBug("Invalid value 'consumedPart'=" + consumedPart + " in consumeMemory, sholud be in [0..1]"); + } + + garbage = new ArrayList(); + + long freeSize = (long) (Runtime.getRuntime().totalMemory() * (1 - consumedPart)); + + int arraySize = (int) (freeSize / 100F); + if (arraySize < 1000) + arraySize = 1000; + + while (Runtime.getRuntime().freeMemory() > freeSize) { + garbage.add(new byte[arraySize]); + } + } + + protected void stopGCProvokateur() { + if (provokateur != null) { + provokateur.stop = true; + + try { + provokateur.join(); + } catch (InterruptedException e) { + log.complain("Main thread was unexpected interrupted when waiting for GCProvokateur termination"); + System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED); + } + } + } + + protected void startGCProvokateur() { + stopGCProvokateur(); + + provokateur = new GCProvokateur(); + provokateur.start(); + } + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + try { + StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command)); + tokenizer.whitespaceChars(':', ':'); + + if (command.equals(COMMAND_START_GC_PROVOCATEUR)) { + startGCProvokateur(); + + return true; + } else if (command.equals(COMMAND_STOP_GC_PROVOCATEUR)) { + stopGCProvokateur(); + + return true; + } else if (command.startsWith(COMMAND_CONSUME_MEMORY)) { + tokenizer.nextToken(); + + if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) + throw new TestBug("Invalid command format"); + + consumeMemory(tokenizer.nval); + + return true; + } + + } catch (IOException e) { + throw new TestBug("Invalid command format: " + command); + } + + return false; + } + + public static void main(String args[]) { + new instancecounts004a().doTest(args); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001.java new file mode 100644 index 00000000000..b306513f70f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_bool; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf(boolean value)
    + * complies with the spec for
    + * com.sun.jdi.BooleanValue methods
    + *
    + * The cases for testing are as follows
    + * (prefix 'bv' means 'boolean_value') :
    + *
    + * // BooleanValue bv.value() method
    + *
    + * bvTrue.value() == true
    + * bvFalse.value() == false
    + *
    + * // BooleanValue bv.equals() method
    + *
    + * bvTrue1.equals(bvTrue2)
    + * !bvTrue1.equals(bvFalse1)
    + * bvFalse1.equals(bvFalse2)
    + * !bvFalse1.equals(bvTrue1)
    + *
    + * !bvTrue1.equals(IntegerValue i0)
    + * !bvFalse1.equals(IntegerValue i1)
    + *
    + * // BooleanValue bv.hashCode() method
    + *
    + * bvTrue1.hashCode() == bvTrue1.hashCode()
    + * bvFalse1.hashCode() == bvFalse1.hashCode()
    + * bvTrue1.hashCode() == bvTrue2.hashCode()
    + * bvFalse1.hashCode() == bvFalse2.hashCode()
    + * bvTrue1.hashCode() != bvFalse1.hashCode()
    + */ + +public class mirrorof_bool001 { + + //----------------------------------------------------- template section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- template parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001", + sHeader2 = "--> mirrorof001: ", + sHeader3 = "##> mirrorof001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_bool001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_bool.mirrorof_bool001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_bool001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1("TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + BooleanValue bvTrue1 = vm.mirrorOf(true); + BooleanValue bvTrue2 = vm.mirrorOf(true); + BooleanValue bvFalse1 = vm.mirrorOf(false); + BooleanValue bvFalse2 = vm.mirrorOf(false); + + int i; + + for (i = 0; ; i++) { + + int expresult = 0; + + log2("new check: #" + i); + + switch (i) { + + case 0: if (bvTrue1.value() != true) + expresult = 1; + break; + + case 1: if (bvFalse1.value() != false) + expresult = 1; + break; + + + case 2: if (!bvTrue1.equals(bvTrue2)) + expresult = 1; + break; + + case 3: if (bvTrue1.equals(bvFalse1)) + expresult = 1; + break; + + case 4: if (!bvFalse1.equals(bvFalse2)) + expresult = 1; + break; + + case 5: if (bvFalse1.equals(bvTrue1)) + expresult = 1; + break; + + case 6: IntegerValue i0 = vm.mirrorOf(0); + if (bvTrue1.equals(i0)) + expresult = 1; + break; + + case 7: IntegerValue i1 = vm.mirrorOf(1); + if (bvFalse1.equals(i1)) + expresult = 1; + break; + + + case 8: if (bvTrue1.hashCode() != bvTrue1.hashCode()) + expresult = 1; + break; + + case 9: if (bvFalse1.hashCode() != bvFalse1.hashCode()) + expresult = 1; + break; + + case 10: if (bvTrue1.hashCode() != bvTrue2.hashCode()) + expresult = 1; + break; + + case 11: if (bvFalse1.hashCode() != bvFalse2.hashCode()) + expresult = 1; + break; + + case 12: if (bvTrue1.hashCode() == bvFalse1.hashCode()) + expresult = 1; + break; + + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) { + // verbMode=true; + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + + log1("TESTING ENDS"); + + //-------------------------------------------------- test summary section + + + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001/TestDescription.java new file mode 100644 index 00000000000..2326f5724e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(boolean value) + * complies with the following requirements for BooleanValue: + * public boolean value() + * Returns this BooleanValue as a boolean. + * Returns: the boolean mirrored by this object. + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this BooleanValue + * for equality. + * Returns: + * true if the Object is a BooleanValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * public int hashCode() + * Returns the hash code value for this BooleanValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_bool.mirrorof_bool001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_bool.mirrorof_bool001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_bool.mirrorof_bool001 + * nsk.jdi.VirtualMachine.mirrorOf_bool.mirrorof_bool001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_bool.mirrorof_bool001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001a.java new file mode 100644 index 00000000000..45d43848106 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_bool/mirrorof_bool001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_bool; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as a debugee application for the mirrorof_bool001 JDI test. + */ + +public class mirrorof_bool001a { + + //----------------------------------------------------- template section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_bool001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_bool001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf(byte value)
    + * complies with the spec for
    + * com.sun.jdi.ByteValue methods
    + *
    + * The cases for testing are as follows
    + * ('val_i' means 'byte_value_i') :
    + *
    + * // ByteValue val.value() method
    + *
    + * val_i.value(Byte.MIN_VALUE) == Byte.MIN_VALUE
    + * val_i.value(Byte.MAX_VALUE) == Byte.MAX_VALUE
    + * val_i.value(0) == 0
    + * val_i.value(-1) == -1
    + * val_i.value(+1) == +1
    + *
    + * // ByteValue val.equals() method
    + *
    + * val_i.value(1) == val_j.value(1)
    + * val_i.value(1) != val_j.value(-1)
    + *
    + * val_i.value(1) != (ShortValue) val_j.value(1)
    + *
    + * // ByteValue val.hashCode() method
    + *
    + * val_i.hashCode() == val_i.hashCode()
    + *
    + * if (val_i.value() == val_j.value()) {
    + * val_i.hashCode() == val_j.hashCode()
    + * }
    + *
    + */ + +public class mirrorof_byte001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001", + sHeader2 = "--> mirrorof_byte001: ", + sHeader3 = "##> mirrorof_byte001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_byte001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_byte.mirrorof_byte001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_byte001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + byte smallest = Byte.MIN_VALUE; + byte zero = 0; + byte largest = Byte.MAX_VALUE; + byte plus1 = +1; + byte minus1 = -1; + + ByteValue val_1 = vm.mirrorOf(smallest); + ByteValue val_2 = vm.mirrorOf(zero); + ByteValue val_3 = vm.mirrorOf(largest); + ByteValue val_4 = vm.mirrorOf(plus1); + ByteValue val_5 = vm.mirrorOf(plus1); + ByteValue val_6 = vm.mirrorOf(minus1); + + ShortValue val_7 = vm.mirrorOf((short)plus1); + + int i; + + for (i = 0; ; i++) { + + int expresult = 0; + + log2(" new check: #" + i); + + switch (i) { + + // tests for ByteValue.value() + + case 0: if (val_1.value() != smallest) + expresult = 1; + break; + + case 1: if (val_2.value() != zero) + expresult = 1; + break; + + case 2: if (val_3.value() != largest) + expresult = 1; + break; + + + // tests for ByteValue.equals() + + case 3: if (!val_4.equals(val_5)) + expresult = 1; + break; + + case 4: if (val_4.equals(val_6)) + expresult = 1; + break; + + case 5: if (val_4.equals(val_7)) + expresult = 1; + break; + + + // tests for ByteValue.hashCode() + + case 6: if (val_1.hashCode() != val_1.hashCode()) + expresult = 1; + break; + + case 7: if (val_4.hashCode() != val_5.hashCode()) + expresult = 1; + break; + + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) {; + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001/TestDescription.java new file mode 100644 index 00000000000..62c7b3781b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(byte value) + * complies with the following requirements for ByteValue: + * public byte value() + * Returns this ByteValue as a byte. + * Returns: the byte mirrored by this object. + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this ByteValue for equality. + * Returns: true if the Object is a ByteValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * public int hashCode() + * Returns the hash code value for this ByteValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_byte.mirrorof_byte001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_byte.mirrorof_byte001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_byte.mirrorof_byte001 + * nsk.jdi.VirtualMachine.mirrorOf_byte.mirrorof_byte001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_byte.mirrorof_byte001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001a.java new file mode 100644 index 00000000000..a78aa56f570 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_byte/mirrorof_byte001a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_byte; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the mirrorof_byte001a JDI test. + */ + +public class mirrorof_byte001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_byte001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_byte001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf_char()
    + * complies with the spec for
    + * com.sun.jdi.CharValue methods
    + *
    + * The cases for testing are as follows
    + * ('val_i' means 'char_value_i') :
    + *
    + * // CharValue val.value() method
    + *
    + * val_i.value(Character.MIN_VALUE) == Character.MIN_VALUE
    + * val_i.value(Character.MAX_VALUE) == Character.MAX_VALUE
    + * val_i.value(0) == 0
    + * val_i.value(-1) == -1
    + * val_i.value(+1) == +1
    + *
    + * // CharValue val.equals() method
    + *
    + * val_i.value(1) == val_j.value(1)
    + * val_i.value(1) != val_j.value(-1)
    + *
    + * val_i.value(1) != (ShortValue) val_j.value(1)
    + *
    + * // CharValue val.hashCode() method
    + *
    + * val_i.hashCode() == val_i.hashCode()
    + *
    + * if (val_i.value() == val_j.value()) {
    + * val_i.hashCode() == val_j.hashCode()
    + * }
    + *
    + */ + +public class mirrorof_char001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001", + sHeader2 = "--> mirrorof_char001: ", + sHeader3 = "##> mirrorof_char001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_char001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_char.mirrorof_char001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_char001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + char smallest = Character.MIN_VALUE; + char largest = Character.MAX_VALUE; + + char char_a = 'a'; + char char_b = 'b'; + + CharValue val_1 = vm.mirrorOf(smallest); + CharValue val_2 = vm.mirrorOf(largest); + + CharValue val_4 = vm.mirrorOf(char_a); + CharValue val_5 = vm.mirrorOf(char_a); + CharValue val_6 = vm.mirrorOf(char_b); + + ShortValue val_7 = vm.mirrorOf((short) char_a); + + int i; + + for (i = 0; ; i++) { + + int expresult = 0; + + log2(" new check: #" + i); + + switch (i) { + + // tests for CharValue.value() + + case 0: if (val_1.value() != smallest) + expresult = 1; + break; + + case 1: if (val_2.value() != largest) + expresult = 1; + break; + + + // tests for CharValue.equals() + + case 2: if (!val_4.equals(val_5)) + expresult = 1; + break; + + case 3: if (val_4.equals(val_6)) + expresult = 1; + break; + + case 4: if (val_4.equals(val_7)) + expresult = 1; + break; + + + // tests for CharValue.hashCode() + + case 5: if (val_1.hashCode() != val_1.hashCode()) + expresult = 1; + break; + + case 6: if (val_4.hashCode() != val_5.hashCode()) + expresult = 1; + break; + + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) {; + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001/TestDescription.java new file mode 100644 index 00000000000..9f5a82eda98 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(char value) + * complies with the following requirements for CharValue: + * public char value() + * Returns this CharValue as a char. + * Returns: the char mirrored by this object. + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this CharValue for equality. + * Returns: true if the Object is a CharValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * public int hashCode() + * Returns the hash code value for this CharValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_char.mirrorof_char001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_char.mirrorof_char001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_char.mirrorof_char001 + * nsk.jdi.VirtualMachine.mirrorOf_char.mirrorof_char001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_char.mirrorof_char001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001a.java new file mode 100644 index 00000000000..9d0dbbad3e1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_char/mirrorof_char001a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_char; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the mirrorof_char001a JDI test. + */ + +public class mirrorof_char001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_char001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_char001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf_double()
    + * complies with the spec for
    + * com.sun.jdi.DoubleValue methods
    + *
    + * The cases for testing are as follows
    + * ('val_i' means 'double_value_i') :
    + *
    + * // DoubleValue val.value() method
    + *
    + * val_i.value(Double.NEGATIVE_INFINITY) == Double.NEGATIVE_INFINITY
    + * val_i.value(-Double.MAX_VALUE) == -Double.MAX_VALUE
    + * val_i.value(-Double.MIN_VALUE) == -Double.MIN_VALUE
    + * val_i.value(-0.0f) == -0.0f
    + * val_i.value(0.0f) == 0.0f
    + * val_i.value(Double.MIN_VALUE) == Double.MIN_VALUE
    + * val_i.value(Double.MAX_VALUE) == Double.MAX_VALUE
    + * val_i.value(Double.POSITIVE_INFINITY) == Double.POSITIVE_INFINITY
    + * val_i.value(Double.NaN) == Double.NaN
    + *
    + * // DoubleValue val.equals() method
    + *
    + * val_i.value(+1.0f) == val_j.value(+1.0f)
    + * val_i.value(+1.0f) != val_j.value(-1.0f)
    + *
    + * val_i.value(1.0) != doubleValue.value(1.0)
    + *
    + * // DoubleValue val.hashCode() method
    + *
    + * val_i.hashCode() == val_i.hashCode()
    + *
    + * if (val_i.value() == val_j.value()) {
    + * val_i.hashCode() == val_j.hashCode()
    + * }
    + *
    + */ + +public class mirrorof_double001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001", + sHeader2 = "--> mirrorof_double001: ", + sHeader3 = "##> mirrorof_double001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_double001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_double.mirrorof_double001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_double001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + double pos_inf = Double.POSITIVE_INFINITY; + double pos_zero = 0.0d; + double neg_zero = -0.0d; + double neg_inf = Double.NEGATIVE_INFINITY; + + double pos_largest = Double.MAX_VALUE; + double pos_smallest = Double.MIN_VALUE; + double neg_largest = -Double.MAX_VALUE; + double neg_smallest = -Double.MIN_VALUE; + + double double_nan = Double.NaN; + + double plus1 = +1.0d; + double minus1 = -1.0d; + + DoubleValue val_1 = vm.mirrorOf(neg_inf); + DoubleValue val_2 = vm.mirrorOf(neg_largest); + DoubleValue val_3 = vm.mirrorOf(neg_smallest); + DoubleValue val_4 = vm.mirrorOf(neg_zero); + DoubleValue val_5 = vm.mirrorOf(pos_zero); + DoubleValue val_6 = vm.mirrorOf(pos_smallest); + DoubleValue val_7 = vm.mirrorOf(pos_largest); + DoubleValue val_8 = vm.mirrorOf(pos_inf); + + DoubleValue val_9 = vm.mirrorOf(double_nan); + + DoubleValue val_10 = vm.mirrorOf(plus1); + DoubleValue val_11 = vm.mirrorOf(plus1); + DoubleValue val_12 = vm.mirrorOf(minus1); + + FloatValue val_13 = vm.mirrorOf((float)plus1); + + + int i; + + for (i = 0; ; i++) { + + int expresult = 0; + + log2(" new check: #" + i); + + switch (i) { + + // tests for DoubleValue.value() + + case 0: if (val_1.value() != neg_inf) + expresult = 1; + break; + + case 1: if (val_2.value() != neg_largest) + expresult = 1; + break; + + case 2: if (val_3.value() != neg_smallest) + expresult = 1; + break; + + case 3: if (val_4.value() != neg_zero) + expresult = 1; + break; + + case 4: if (val_5.value() != pos_zero) + expresult = 1; + break; + + case 5: if (val_6.value() != pos_smallest) + expresult = 1; + break; + + case 6: if (val_7.value() != pos_largest) + expresult = 1; + break; + + case 7: if (val_8.value() != pos_inf) + expresult = 1; + break; + + case 8: if ( !(val_9.value() != val_9.value()) ) + expresult = 1; + break; + + + // tests for DoubleValue.equals() + + case 9: if (!val_10.equals(val_11)) + expresult = 1; + break; + + case 10: if (val_10.equals(val_12)) + expresult = 1; + break; + + case 11: if (val_10.equals(val_13)) + expresult = 1; + break; + + + // tests for DoubleValue.hashCode() + + case 12: if (val_7.hashCode() != val_7.hashCode()) + expresult = 1; + break; + + case 13: if (val_10.hashCode() != val_11.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) {; + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + + + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001/TestDescription.java new file mode 100644 index 00000000000..c4fe41c4e84 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(double value) + * complies with the following requirements for DoubleValue: + * public double value() + * Returns this DoubleValue as a double. + * Returns: the double mirrored by this object. + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this DoubleValue for equality. + * Returns: true if the Object is a DoubleValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * public int hashCode() + * Returns the hash code value for this DoubleValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_double.mirrorof_double001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_double.mirrorof_double001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_double.mirrorof_double001 + * nsk.jdi.VirtualMachine.mirrorOf_double.mirrorof_double001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_double.mirrorof_double001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001a.java new file mode 100644 index 00000000000..999f170082f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_double/mirrorof_double001a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_double; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the mirrorof_double001a JDI test. + */ + +public class mirrorof_double001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + private static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_double001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_double001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf_float()
    + * complies with the spec for
    + * com.sun.jdi.FloatValue methods
    + *
    + * The cases for testing are as follows
    + * ('val_i' means 'float_value_i') :
    + *
    + * // FloatValue val.value() method
    + *
    + * val_i.value(Float.NEGATIVE_INFINITY) == Float.NEGATIVE_INFINITY
    + * val_i.value(-Float.MAX_VALUE) == -Float.MAX_VALUE
    + * val_i.value(-Float.MIN_VALUE) == -Float.MIN_VALUE
    + * val_i.value(-0.0f) == -0.0f
    + * val_i.value(0.0f) == 0.0f
    + * val_i.value(Float.MIN_VALUE) == Float.MIN_VALUE
    + * val_i.value(Float.MAX_VALUE) == Float.MAX_VALUE
    + * val_i.value(Float.POSITIVE_INFINITY) == Float.POSITIVE_INFINITY
    + * val_i.value(Float.NaN) == Float.NaN
    + *
    + * // FloatValue val.equals() method
    + *
    + * val_i.value(+1.0f) == val_j.value(+1.0f)
    + * val_i.value(+1.0f) != val_j.value(-1.0f)
    + *
    + * val_i.value(1.0) != doubleValue.value(1.0)
    + *
    + * // FloatValue val.hashCode() method
    + *
    + * val_i.hashCode() == val_i.hashCode()
    + *
    + * if (val_i.value() == val_j.value()) {
    + * val_i.hashCode() == val_j.hashCode()
    + * }
    + *
    + */ + +public class mirrorof_float001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001", + sHeader2 = "--> mirrorof_float001: ", + sHeader3 = "##> mirrorof_float001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_float001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_float.mirrorof_float001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_float001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + float pos_inf = Float.POSITIVE_INFINITY; + float pos_zero = 0.0f; + float neg_zero = -0.0f; + float neg_inf = Float.NEGATIVE_INFINITY; + + float pos_largest = Float.MAX_VALUE; + float pos_smallest = Float.MIN_VALUE; + float neg_largest = -Float.MAX_VALUE; + float neg_smallest = -Float.MIN_VALUE; + + float float_nan = Float.NaN; + + float plus1 = +1.0f; + float minus1 = -1.0f; + + FloatValue val_1 = vm.mirrorOf(neg_inf); + FloatValue val_2 = vm.mirrorOf(neg_largest); + FloatValue val_3 = vm.mirrorOf(neg_smallest); + FloatValue val_4 = vm.mirrorOf(neg_zero); + FloatValue val_5 = vm.mirrorOf(pos_zero); + FloatValue val_6 = vm.mirrorOf(pos_smallest); + FloatValue val_7 = vm.mirrorOf(pos_largest); + FloatValue val_8 = vm.mirrorOf(pos_inf); + + FloatValue val_9 = vm.mirrorOf(float_nan); + + FloatValue val_10 = vm.mirrorOf(plus1); + FloatValue val_11 = vm.mirrorOf(plus1); + FloatValue val_12 = vm.mirrorOf(minus1); + + DoubleValue val_13 = vm.mirrorOf((double)plus1); + + + int i; + + for (i = 0; ; i++) { + + int expresult = 0; + + log2(" new check: #" + i); + + switch (i) { + + // tests for FloatValue.value() + + case 0: if (val_1.value() != neg_inf) + expresult = 1; + break; + + case 1: if (val_2.value() != neg_largest) + expresult = 1; + break; + + case 2: if (val_3.value() != neg_smallest) + expresult = 1; + break; + + case 3: if (val_4.value() != neg_zero) + expresult = 1; + break; + + case 4: if (val_5.value() != pos_zero) + expresult = 1; + break; + + case 5: if (val_6.value() != pos_smallest) + expresult = 1; + break; + + case 6: if (val_7.value() != pos_largest) + expresult = 1; + break; + + case 7: if (val_8.value() != pos_inf) + expresult = 1; + break; + + case 8: if ( !(val_9.value() != val_9.value()) ) + expresult = 1; + break; + + + // tests for FloatValue.equals() + + case 9: if (!val_10.equals(val_11)) + expresult = 1; + break; + + case 10: if (val_10.equals(val_12)) + expresult = 1; + break; + + case 11: if (val_10.equals(val_13)) + expresult = 1; + break; + + + // tests for FloatValue.hashCode() + + case 12: if (val_7.hashCode() != val_7.hashCode()) + expresult = 1; + break; + + case 13: if (val_10.hashCode() != val_11.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) {; + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001/TestDescription.java new file mode 100644 index 00000000000..3f9eea6055c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(float value) + * complies with the following requirements for FloatValue: + * public float value() + * Returns this FloatValue as a float. + * Returns: the float mirrored by this object. + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this FloatValue for equality. + * Returns: true if the Object is a FloatValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * public int hashCode() + * Returns the hash code value for this FloatValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_float.mirrorof_float001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_float.mirrorof_float001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_float.mirrorof_float001 + * nsk.jdi.VirtualMachine.mirrorOf_float.mirrorof_float001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_float.mirrorof_float001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001a.java new file mode 100644 index 00000000000..5b30c8193a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_float/mirrorof_float001a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_float; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the mirrorof_float001a JDI test. + */ + +public class mirrorof_float001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_float001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_float001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf_int()
    + * complies with the spec for
    + * com.sun.jdi.IntegerValue methods
    + *
    + * The cases for testing are as follows
    + * ('val_i' means 'integer_value_i') :
    + *
    + * // IntegerValue val.value() method
    + *
    + * val_i.value(Integer.MIN_VALUE) == Integer.MIN_VALUE
    + * val_i.value(Integer.MAX_VALUE) == Integer.MAX_VALUE
    + * val_i.value(0) == 0
    + * val_i.value(-1) == -1
    + * val_i.value(+1) == +1
    + *
    + * // IntegerValue val.equals() method
    + *
    + * val_i.value(1) == val_j.value(1)
    + * val_i.value(1) != val_j.value(-1)
    + *
    + * val_i.value(1) != integerValue.value(1)
    + *
    + * // IntegerValue val.hashCode() method
    + *
    + * val_i.hashCode() == val_i.hashCode()
    + *
    + * if (val_i.value() == val_j.value()) {
    + * val_i.hashCode() == val_j.hashCode()
    + * }
    + *
    + */ + +public class mirrorof_int001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001", + sHeader2 = "--> mirrorof_int001: ", + sHeader3 = "##> mirrorof_int001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_int001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_int.mirrorof_int001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_int001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int smallest = Integer.MIN_VALUE; + int zero = 0; + int largest = Integer.MAX_VALUE; + int plus1 = +1; + int minus1 = -1; + + IntegerValue val_1 = vm.mirrorOf(smallest); + IntegerValue val_2 = vm.mirrorOf(zero); + IntegerValue val_3 = vm.mirrorOf(largest); + IntegerValue val_4 = vm.mirrorOf(plus1); + IntegerValue val_5 = vm.mirrorOf(plus1); + IntegerValue val_6 = vm.mirrorOf(minus1); + + LongValue val_7 = vm.mirrorOf((long)plus1); + + int i; + + for (i = 0; ; i++) { + + int expresult = 0; + + log2(" new check: #" + i); + + switch (i) { + + // tests for IntegerValue.value() + + case 0: if (val_1.value() != smallest) + expresult = 1; + break; + + case 1: if (val_2.value() != zero) + expresult = 1; + break; + + case 2: if (val_3.value() != largest) + expresult = 1; + break; + + + // tests for IntegerValue.equals() + + case 3: if (!val_4.equals(val_5)) + expresult = 1; + break; + + case 4: if (val_4.equals(val_6)) + expresult = 1; + break; + + case 5: if (val_4.equals(val_7)) + expresult = 1; + break; + + + // tests for IntegerValue.hashCode() + + case 6: if (val_1.hashCode() != val_1.hashCode()) + expresult = 1; + break; + + case 7: if (val_4.hashCode() != val_5.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) {; + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001/TestDescription.java new file mode 100644 index 00000000000..1368b7b20a1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(int value) + * complies with the following requirements for IntegerValue: + * public int value() + * Returns this IntegerValue as an int. + * Returns: the int mirrored by this object. + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this IntegerValue for equality. + * Returns: true if the Object is an IntegerValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * public int hashCode() + * Returns the hash code value for this IntegerValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_int.mirrorof_int001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_int.mirrorof_int001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_int.mirrorof_int001 + * nsk.jdi.VirtualMachine.mirrorOf_int.mirrorof_int001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_int.mirrorof_int001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001a.java new file mode 100644 index 00000000000..453f43c2d23 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_int/mirrorof_int001a.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_int; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the mirrorof_int001a JDI test. + */ + +public class mirrorof_int001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_int001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_int001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf_long()
    + * complies with the spec for
    + * com.sun.jdi.LongValue methods
    + *
    + * The cases for testing are as follows
    + * ('val_i' means 'long_value_i') :
    + *
    + * // LongValue val.value() method
    + *
    + * val_i.value(Long.MIN_VALUE) == Long.MIN_VALUE
    + * val_i.value(Long.MAX_VALUE) == Long.MAX_VALUE
    + * val_i.value(0) == 0
    + * val_i.value(-1) == -1
    + * val_i.value(+1) == +1
    + *
    + * // LongValue val.equals() method
    + *
    + * val_i.value(1) == val_j.value(1)
    + * val_i.value(1) != val_j.value(-1)
    + *
    + * val_i.value(1) != integerValue.value(1)
    + *
    + * // LongValue val.hashCode() method
    + *
    + * val_i.hashCode() == val_i.hashCode()
    + *
    + * if (val_i.value() == val_j.value()) {
    + * val_i.hashCode() == val_j.hashCode()
    + * }
    + *
    + */ + +public class mirrorof_long001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001", + sHeader2 = "--> mirrorof_long001: ", + sHeader3 = "##> mirrorof_long001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_long001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_long.mirrorof_long001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_long001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + long smallest = Long.MIN_VALUE; + long zero = 0; + long largest = Long.MAX_VALUE; + long plus1 = +1; + long minus1 = -1; + + LongValue val_1 = vm.mirrorOf(smallest); + LongValue val_2 = vm.mirrorOf(zero); + LongValue val_3 = vm.mirrorOf(largest); + LongValue val_4 = vm.mirrorOf(plus1); + LongValue val_5 = vm.mirrorOf(plus1); + LongValue val_6 = vm.mirrorOf(minus1); + + FloatValue val_7 = vm.mirrorOf((float)plus1); + + int i; + + for (i = 0; ; i++) { + + int expresult = 0; + + log2(" new check: #" + i); + + switch (i) { + + // tests for LongValue.value() + + case 0: if (val_1.value() != smallest) + expresult = 1; + break; + + case 1: if (val_2.value() != zero) + expresult = 1; + break; + + case 2: if (val_3.value() != largest) + expresult = 1; + break; + + + // tests for LongValue.equals() + + case 3: if (!val_4.equals(val_5)) + expresult = 1; + break; + + case 4: if (val_4.equals(val_6)) + expresult = 1; + break; + + case 5: if (val_4.equals(val_7)) + expresult = 1; + break; + + + // tests for LongValue.hashCode() + + case 6: if (val_1.hashCode() != val_1.hashCode()) + expresult = 1; + break; + + case 7: if (val_4.hashCode() != val_5.hashCode()) + expresult = 1; + break; + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) {; + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001/TestDescription.java new file mode 100644 index 00000000000..14843c23520 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(long value) + * complies with the following requirements for LongValue: + * public long value() + * Returns this LongValue as a long. + * Returns: the long mirrored by this object. + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this LongValue for equality. + * Returns: true if the Object is a LongValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * public int hashCode() + * Returns the hash code value for this LongValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_long.mirrorof_long001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_long.mirrorof_long001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_long.mirrorof_long001 + * nsk.jdi.VirtualMachine.mirrorOf_long.mirrorof_long001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_long.mirrorof_long001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001a.java new file mode 100644 index 00000000000..418ba3fb7be --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_long/mirrorof_long001a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_long; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the mirrorof_long001a JDI test. + + */ + +public class mirrorof_long001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_long001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_long001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf_short()
    + * complies with the spec for
    + * com.sun.jdi.ShortValue methods
    + *
    + * The cases for testing are as follows
    + * ('val_i' means 'short_value_i') :
    + *
    + * // ShortValue val.value() method
    + *
    + * val_i.value(Short.MIN_VALUE) == Short.MIN_VALUE
    + * val_i.value(Short.MAX_VALUE) == Short.MAX_VALUE
    + * val_i.value(0) == 0
    + * val_i.value(-1) == -1
    + * val_i.value(+1) == +1
    + *
    + * // ShortValue val.equals() method
    + *
    + * val_i.value(1) == val_j.value(1)
    + * val_i.value(1) != val_j.value(-1)
    + *
    + * val_i.value(1) != integerValue.value(1)
    + *
    + * // ShortValue val.hashCode() method
    + *
    + * val_i.hashCode() == val_i.hashCode()
    + *
    + * if (val_i.value() == val_j.value()) {
    + * val_i.hashCode() == val_j.hashCode()
    + * }
    + *
    + */ + +public class mirrorof_short001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001", + sHeader2 = "--> mirrorof_short001: ", + sHeader3 = "##> mirrorof_short001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_short001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_short.mirrorof_short001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_short001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + short smallest = Short.MIN_VALUE; + short zero = 0; + short largest = Short.MAX_VALUE; + short plus1 = +1; + short minus1 = -1; + + ShortValue val_1 = vm.mirrorOf(smallest); + ShortValue val_2 = vm.mirrorOf(zero); + ShortValue val_3 = vm.mirrorOf(largest); + ShortValue val_4 = vm.mirrorOf(plus1); + ShortValue val_5 = vm.mirrorOf(plus1); + ShortValue val_6 = vm.mirrorOf(minus1); + + IntegerValue val_7 = vm.mirrorOf((int)plus1); + + int i; + + for (i = 0; ; i++) { + + int expresult = 0; + + log2(" new check: #" + i); + + switch (i) { + + // tests for ShortValue.value() + + case 0: if (val_1.value() != smallest) + expresult = 1; + break; + + case 1: if (val_2.value() != zero) + expresult = 1; + break; + + case 2: if (val_3.value() != largest) + expresult = 1; + break; + + + // tests for ShortValue.equals() + + case 3: if (!val_4.equals(val_5)) + expresult = 1; + break; + + case 4: if (val_4.equals(val_6)) + expresult = 1; + break; + + case 5: if (val_4.equals(val_7)) + expresult = 1; + break; + + + // tests for ShortValue.hashCode() + + case 6: if (val_1.hashCode() != val_1.hashCode()) + expresult = 1; + break; + + case 7: if (val_4.hashCode() != val_5.hashCode()) + expresult = 1; + break; + + + + default: expresult = 2; + break ; + } + + if (expresult == 2) { + log2(" test cases finished"); + break ; + } else if (expresult == 1) {; + log3("ERROR: expresult != true; check # = " + i); + testExitCode = FAILED; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001/TestDescription.java new file mode 100644 index 00000000000..786e62c12b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001/TestDescription.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(short value) + * complies with the following requirements for ShortValue: + * public short value() + * Returns this ShortValue as a short. + * Returns: the short mirrored by this object. + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this ShortValue for equality. + * Returns: true if the Object is a ShortValue and if applying "==" + * to the two mirrored primitives would evaluate to true; + * false otherwise. + * public int hashCode() + * Returns the hash code value for this ShortValue. + * Returns: the integer hash code + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_short.mirrorof_short001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_short.mirrorof_short001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_short.mirrorof_short001 + * nsk.jdi.VirtualMachine.mirrorOf_short.mirrorof_short001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_short.mirrorof_short001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001a.java new file mode 100644 index 00000000000..49dc174c346 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_short/mirrorof_short001a.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_short; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the mirrorof_short001a JDI test. + + */ + +public class mirrorof_short001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_short001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_short001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.mirrorOf_string()
    + * complies with the spec for
    + * com.sun.jdi.StringValue methods.
    + *
    + * The cases for testing are as follows:
    + * s2 = s_ref.value();
    + * doesn't throw ObjectCollectedException
    + *
    + * for String objects s1 and s2
    + * s_ref = vm.mirrorOf(s1); s1.compareTo(s2) == 0
    + *
    + */ + +public class mirrorof_string001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001", + sHeader2 = "--> mirrorof_string001: ", + sHeader3 = "##> mirrorof_string001: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new mirrorof_string001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debugeeName = + "nsk.jdi.VirtualMachine.mirrorOf_string.mirrorof_string001a"; + + //====================================================== test program + + static ArgumentHandler argsHandler; + static int testExitCode = PASSED; + + //------------------------------------------------------ common section + + private int runThis (String argv[], PrintStream out) { + + Debugee debugee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debugee = binder.bindToDebugee(debugeeName + " -vbs"); // *** tp + } else { + debugee = binder.bindToDebugee(debugeeName); // *** tp + } + + IOPipe pipe = new IOPipe(debugee); + + debugee.redirectStderr(out); + log2("mirrorof_string001a debugee launched"); + debugee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debugee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String s1 = "abc"; + String s2 = null; + + StringReference s_ref = vm.mirrorOf(s1); + + try { + s2 = s_ref.value(); + } catch ( ObjectCollectedException e ) { + log3("ERROR: 's2=s_ref.value' throws ObjectCollectedException"); + testExitCode = FAILED; + } + + if (testExitCode != FAILED) + if (s1.compareTo(s2) != 0) { + log3("ERROR: strings are not equal"); + testExitCode = FAILED; + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log1(" TESTING ENDS"); + //-------------------------------------------------- test summary section + + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debugee finish ..."); + debugee.waitFor(); + + int status = debugee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debugee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debugee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001/TestDescription.java new file mode 100644 index 00000000000..ecc5322a573 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.mirrorOf(String value) + * complies with the following requirements: + * public java.lang.String value() + * Returns the StringReference as a String. + * The returned string is the equivalent of the mirrored string, + * but is an entity in the client VM and + * can be manipulated like any other string. + * Returns: the string value. + * Throws: + * ObjectCollectedException - if this object has been garbage collected. + * The test works as follows: + * A debugger program - nsk.jdi.VirtualMachine.mirrorOf_string.mirrorof_string001; + * a debuggee program - nsk.jdi.VirtualMachine.mirrorOf_string.mirrorof_string001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.mirrorOf_string.mirrorof_string001 + * nsk.jdi.VirtualMachine.mirrorOf_string.mirrorof_string001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.mirrorOf_string.mirrorof_string001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001a.java new file mode 100644 index 00000000000..59525056755 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/mirrorOf_string/mirrorof_string001a.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000, 2018, 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 nsk.jdi.VirtualMachine.mirrorOf_string; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debugee application for the mirrorof_string001a JDI test. + */ + +public class mirrorof_string001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; // debugger may switch to true + + private static void log1(String message) { + if (verbMode) + System.err.println("**> mirrorof_string001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mirrorof_string001a: " + message); + } + + //====================================================== test program + + //------------------------------------------------------ common section + + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.name()
    + * complies with its specification.
    + */ + +public class name001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/name/name001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new name001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.name.name001a"; + + //String mName = "nsk.jdi.VirtualMachine.name"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String name = vm.name(); + if (name == null) { + log3("ERROR: name == null"); + expresult = returnCode1; + } else + log2(" name == " + name); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001/TestDescription.java new file mode 100644 index 00000000000..79fa778406f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/name/name001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.name() + * complies with its spec: + * public java.lang.String name() + * Returns the name of the target VM as reported by the property java.vm.name. + * Returns: the target VM name. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.name.name001; + * the debuggee program - nsk.jdi.VirtualMachine.name.name001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.name.name001 + * nsk.jdi.VirtualMachine.name.name001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.name.name001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001a.java new file mode 100644 index 00000000000..b297606b0bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/name/name001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.name; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the name001 JDI test. + */ + +public class name001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> name001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> name001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.process()
    + * complies with it specification.
    + *
    + * The test checks up that if a target VirtualMachine is
    + * launched by a LaunchingConnector a value returned by the
    + * method is not null.
    + */ + +public class process001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/process/process001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new process001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.process.process001a"; + + //String mName = "nsk.jdi.VirtualMachine.process"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + Process process = vm.process(); + + if (argsHandler.isLaunchingConnector()) { + log2("......VirtualMachine is launched by a LaunchingConnector"); + log2(" check that VirtualMachine.process() has retuned not null"); + if (process == null) { + log3("ERROR: VirtualMachine.process() has retuned null"); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001/TestDescription.java new file mode 100644 index 00000000000..629c9e31f3a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/process/process001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.process() + * complies with its spec: + * public java.lang.Process process() + * Returns the Process object for this virtual machine + * if launched by a LaunchingConnector + * Returns: the Process object for this virtual machine, or + * null if it was not launched by a LaunchingConnector. + * The test case includes only a LaunchingConnector. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.process.process001; + * the debuggee program - nsk.jdi.VirtualMachine.process.process001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.process.process001 + * nsk.jdi.VirtualMachine.process.process001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.process.process001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001a.java new file mode 100644 index 00000000000..c11a3feebed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/process/process001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.process; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the process001 JDI test. + */ + +public class process001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> process001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> process001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.redefineClasses()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * If any redefined methods have active stack frames,
    + * those active frames continue to run the bytecodes of
    + * the previous method.
    + * The redefined methods will be used on new invokes.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assetion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new tested class object, objRF1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the breakpointForCommunication Event,
    + * the debugger sets up the breakpoint bpRequest2 in the tested method
    + * redefineclasses001b.m2(), resumes the debuggee.
    + * - The debuggee invokes objRF1.m1() method to be suspended
    + * at the breakpoint in the method m2().
    + * - Upon getting the breakpointInMethod Event,
    + * the debugger prepares mapClassToByte, invokes
    + * VirtualMachine.redefineClasses(mapClassToByte)
    + * and resumes the debuggee.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * once again and to inform the debugger with the event.
    + * - Upon getting seconf breakpointForCommunication Event,
    + * the debugger sets up another breakpoint in the redefined method m2()
    + * and resumes the debuggee.
    + * - The debuggee invokes the method m1() to invoke m2() second time,
    + * wher it will be suspended once again.
    + * - Upon getting second breakpointInMethod Event,
    + * the debugger checks up the value of the class variable "i1"
    + * which should be equal to the expected value.
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class redefineclasses001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new redefineclasses001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.redefineClasses.redefineclasses001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + + debuggee = binder.bindToDebugee(debuggeeName); + + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + + if ( !vm.canRedefineClasses() ) { + log2("......vm.canRedefineClasses() == false : test is cancelled"); + vm.resume(); + return; + } + + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + String bpClassName = "nsk.jdi.VirtualMachine.redefineClasses.redefineclasses001b"; + String bpMethodName = "m2"; + String bpLineName = "bpline"; + String varName = "i1"; + int varValue = 2; + + BreakpointRequest bpRequest2 = null; + BreakpointRequest bpRequest3 = null; + ReferenceType bpClass = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + case 0: + List classes = vm.classesByName(bpClassName); + bpClass = (ReferenceType) classes.get(0); + bpRequest2 = settingBreakpoint(threadByName("main"), + bpClass, + bpMethodName, bpLineName, "one"); + bpRequest2.enable(); + + vm.resume(); + breakpointInMethod("one"); + bpRequest2.disable(); + + try { + log2("......vm.redefineClasses(mapClassToBytes());"); + vm.redefineClasses(mapClassToBytes()); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + testExitCode = FAILED; + throw e; + } catch ( Error e ) { + log3("ERROR: Error: " + e); + testExitCode = FAILED; + throw e; + } + break; + + case 1: + + bpRequest3 = settingBreakpoint(threadByName("main"), + bpClass, + bpMethodName, bpLineName, "one"); + + bpRequest3.enable(); + + vm.resume(); + breakpointInMethod("one"); + bpRequest3.disable(); + + int i1 = ( (IntegerValue) + bpClass.getValue(bpClass.fieldByName(varName) ) ).value(); + + if (i1 != varValue) { + testExitCode = FAILED; + log3("ERROR: value of i1 != 2 (expected) but : " + i1); + } + break; + + default: + throw new JDITestRuntimeException ("** default case **"); + } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } +// this is for debugging +// testExitCode = FAILED; + + vm.resume(); + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + alllineLocations = method.allLineLocations(); + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private void breakpointInMethod(String number) + throws JDITestRuntimeException { + + Event event; + + getEventSet(); + event = eventIterator.nextEvent(); + + if ( !(event instanceof BreakpointEvent) ) + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + + log2("---->: request().getProperty == " + + event.request().getProperty("number")); + + if ( event.request().getProperty("number").equals(number) ) + return; + + throw new JDITestRuntimeException("** UNEXPECTED breakpoint **"); + } + + + private Map mapClassToBytes() + throws JDITestRuntimeException { + + byte []arrayToRedefine; + +// ----------------------------- + log2("......getting: String[] args = argsHandler.getArguments();"); + String[] args = argsHandler.getArguments(); + if (args.length <= 0) { + log3("ERROR: args.length <= 0"); + testExitCode = FAILED; + throw new JDITestRuntimeException("** args.length <= 0 **"); + } + String testDir = args[0]; + log2("...... testDir = " + testDir); + + + String filePrefix = File.separator + "nsk" + + File.separator + "jdi" + + File.separator + "VirtualMachine" + + File.separator + "redefineClasses"; + + String fileToRedefineName = testDir + + File.separator + "newclass" + + filePrefix + + File.separator + "redefineclasses001b.class"; + + log2("...... fileToRedefineName = " + fileToRedefineName); +// ----------------------------- + + try { + log2("......File fileToRedefine = new File(fileToRedefineName);"); + File fileToRedefine = new File(fileToRedefineName); + if (fileToRedefine.exists()) + log2(" fileToRedefine.exists()"); + else { + log3("ERROR: fileToRedefine doesn't exist"); + testExitCode = FAILED; + } + + if (testExitCode == FAILED) + throw new JDITestRuntimeException("** testExitCode == FAILED **"); + + int fileToRedefineLength = (int) fileToRedefine.length(); + log2(" fileToRedefineLength == " + fileToRedefineLength); + + FileInputStream inputFile = new FileInputStream(fileToRedefine); + arrayToRedefine = new byte[fileToRedefineLength]; + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch ( IOException e ) { + log3("ERROR: IOException: " + e); + throw new JDITestRuntimeException("** IOException **"); + } + + String testClassName = "nsk.jdi.VirtualMachine.redefineClasses.redefineclasses001b"; + List classes = vm.classesByName(testClassName); + ReferenceType testClass = (ReferenceType) classes.get(0); + + HashMap mapForClass = new HashMap(); + mapForClass.put(testClass, arrayToRedefine); + + return mapForClass; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/TestDescription.java new file mode 100644 index 00000000000..186d491bd9a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/TestDescription.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.redefineClasses() + * complies with its spec: + * public void redefineClasses(Map classToBytes) + * All classes given are redefined according to the definitions supplied. + * If any redefined methods have active stack frames, those + * active frames continue to run the bytecodes of the previous method. + * The redefined methods will be used on new invokes. + * If resetting these frames is desired, use ThreadReference.popFrames(StackFrame) + * with Method.isObsolete(). + * This function does not cause any initialization except that which + * would occur under the customary JVM semantics. In other words, + * redefining a class does not cause its initializers to be run. + * The values of preexisting static variables will remain as they were + * prior to the call. However, completely uninitialized (new) static variables + * will be assigned their default value. + * If a redefined class has instances then all those instances will have + * the fields defined by the redefined class at the completion of the call. + * Preexisting fields will retain their previous values. + * Any new fields will have their default values; + * no instance initializers or constructors are run. + * Threads need not be suspended. + * No events are generated by this function. + * Not all target virtual machines support this operation. + * Use canRedefineClasses() to determine if the operation is supported. + * Use canAddMethod() to determine if the redefinition can add methods. + * Use canUnrestrictedlyRedefineClasses() to determine if + * the redefinition can change the schema, delete methods, + * change the class hierarchy, etc. + * Parameters: + * classToBytes - A map from ReferenceType to array of byte. + * The bytes represent the new class definition and + * are in Java Virtual Machine class file format. + * Throws: + * UnsupportedOperationException - if the target virtual machine does not + * support this operation. + * If canRedefineClasses() is false + * any call of this method will throw this exception. + * If canAddMethod() is false attempting to add a method + * will throw this exception. + * If canUnrestrictedlyRedefineClasses() is false, + * attempting any of the following will throw this exception + * changing the schema (the fields) + * changing the hierarchy (subclasses, interfaces) + * deleting a method + * changing class modifiers + * changing method modifiers + * NoClassDefFoundError - if the bytes don't correspond to the reference type + * (the names don't match). + * VerifyError - if a "verifier" detects that a class, though well formed, + * contains an internal inconsistency or security problem. + * ClassFormatError - if the bytes do not represent a valid class. + * ClassCircularityError - if a circularity has been detected + * while initializing a class. + * UnsupportedClassVersionError - if the major and minor version numbers in bytes + * are not supported by the VM. + * The test checks up on the following assertion: + * If any redefined methods have active stack frames, + * those active frames continue to run the bytecodes of the previous method. + * The redefined methods will be used on new invokes. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.redefineClasses.redefineclasses001; + * the debuggee program - nsk.jdi.VirtualMachine.redefineClasses.redefineclasses001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test suite contains + * the precompiled class file redefineclasses001b.klass . + * Its source file is redefineclasses001b.ja . + * Test was updated according to rfe: + * 4691123 TEST: some jdi tests contain precompiled .klass files undes SCCS. + * redefineclasses001b.ja was moved into newclass directory and renamed + * to redefineclasses001b.java. + * The precompiled class file is created during test base build process. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses001 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses001a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses001 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/newclass/redefineclasses001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/newclass/redefineclasses001b.java new file mode 100644 index 00000000000..86ef9d1eaa0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001/newclass/redefineclasses001b.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is the redefining class for the redefineclasses001 JDI test. + */ + +public class redefineclasses001b { + + static final String prefix = "**> debuggee: "; + static Log log; + + redefineclasses001b(Log log) { + this.log = log; + log.display(prefix + " This is the class to be redefine"); + } + + static int i1 = 0; + + static int bpline = 2; + + static void m2() { + i1 = 2; + i1 = 2; + } + + static void m1() { + log.display(prefix + "redefining method: before: m2()"); + m2(); + log.display(prefix + "redefining method: after: m2()"); + log.display(prefix + "redefining method: value of i1 == " + i1); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001a.java new file mode 100644 index 00000000000..9e80c9125b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001a.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the redefineclasses001 JDI test. + */ + +public class redefineclasses001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static redefineclasses001b objRF1; + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + objRF1 = new redefineclasses001b(log); + methodForCommunication(); + objRF1.m1(); + break ; + + case 1: + methodForCommunication(); + objRF1.m1(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001b.java new file mode 100644 index 00000000000..65c174b84e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001b.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This is the redefined class for the redefineclasses001 JDI test. + */ + +public class redefineclasses001b { + + static final String prefix = "**> debuggee: "; + static Log log; + + redefineclasses001b(Log log) { + this.log = log; + log.display(prefix + " This is the class to be redefined"); + } + + static int i1 = 0; + + static int bpline = 2; + + static void m2() { + i1 = 1; + i1 = 1; + } + + static void m1() { + log.display(prefix + "redefined method: before: m2()"); + m2(); + log.display(prefix + "redefined method: after: m2()"); + log.display(prefix + "redefined method: value of i1 == " + i1); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002.java new file mode 100644 index 00000000000..7182fa752ef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002.java @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * The redefined methods will be used on new invokes.
    + * If resetting these frames is desired, use + * ThreadReference.popFrames(StackFrame) with + * Method.isObsolete().
    + * + * The test consits of the following files:
    + * redefineclasses002.java - debugger
    + * redefineclasses002a.java - initial debuggee
    + * newclass/redefineclasses002a.java - redefined debuggee
    + * + * + * This test performs the following steps:
    + * 1. Setting breakpoint at line of method, which will be redefined. + * This method has a local variable testedVar and the breakpoint + * is placed after it's initializing.
    + * 2. When breakpoint event is arrived, Debugger requests initial + * value of testedVar
    + * 3. While VM suspended Debugger redefines the tested method. + * It is added new line, after execution point. That line changes + * value of testedVar, different from initial-value.
    + * 4. While debugee remains suspending, debuger tries to get value of + * testedVar. In this case AbsentInformationException + * is expected.
    + * 5. Popping the active frame and trying to get value again. + * It is expected, method will be not found in active stack frames.
    + * 6. Setting breakpoint at line after the new one and resuming debugee.
    + * 7. Trying to get new value of testedVar. It is expected the last + * value will be different from initial-value.
    + * + * The test should be compiled with -g option, so cfg-file redefines + * JAVA_OPTS variable. + */ + +public class redefineclasses002 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses002"; + private final static String debugeeName = debuggerName + "a"; + private final static String newClass = "newclass" + + File.separator + prefix.replace('.',File.separatorChar) + + "redefineclasses002a.class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + + private ClassType testedClass; + + class MethodNotFoundException extends RuntimeException { + MethodNotFoundException (String msg) { + super(msg); + } + } + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses002 thisTest = new redefineclasses002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses002a.brkpMethodName, + redefineclasses002a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + BreakpointEvent brkpEvent = waitBreakpointEvent(brkp, waitTime); + + ThreadReference thread = brkpEvent.thread(); + + display("\nTEST BEGINS"); + display("==========="); + + IntegerValue val = readVariableValue(thread, brkpEvent.location().method(), + redefineclasses002a.testedVarName); + + if ( val.intValue() != redefineclasses002a.INITIAL_VALUE) { + complain("***UNEXPECTED value*** " + val); + exitStatus = Consts.TEST_FAILED; + } + + display(">redefining the Debugee class..."); + Map mapBytes = mapClassToBytes(testDir + File.separator + newClass); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canRedefineClasses()) { + complain("*** Warning: " + e); + complain("*** The test is considered as passed"); + return; + } + throw new TestBug(UNEXPECTED_STRING + e); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + Method method = null; + try { + display("thread location>" + thread.frame(0).location()); + method = thread.frame(0).location().method(); + } catch(IncompatibleThreadStateException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + val = readVariableValue(thread, method, redefineclasses002a.testedVarName); + + display(">frames is being popped..."); + try { + thread.popFrames(thread.frame(0)); + } catch (IncompatibleThreadStateException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + val = readVariableValue(thread, method, redefineclasses002a.testedVarName); + } catch (MethodNotFoundException e) { + display(EXPECTED_STRING + e + "\n"); + } + + brkp = debugee.setBreakpoint(testedClass, + redefineclasses002a.brkpMethodName, + redefineclasses002a.brkpLineNumber + 2); + debugee.resume(); + + brkpEvent = waitBreakpointEvent(brkp, waitTime); + + ThreadReference thrd = brkpEvent.thread(); + val = readVariableValue(thrd, brkpEvent.location().method(), + redefineclasses002a.testedVarName); + if ( val.intValue() != redefineclasses002a.REDEFINED_VALUE) { + complain("***UNEXPECTED value*** " + val); + exitStatus = Consts.TEST_FAILED; + } + + debugee.resume(); + + display("============="); + display("TEST FINISHES\n"); + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private IntegerValue readVariableValue(ThreadReference thrd, Method method, + String varName) { + String methodName = method.name(); + display(">getting value of local variable..."); + display("method name\t: " + methodName); + display("variable name\t: " + varName); + StackFrame stckFrm = null; + List frames = null; + try { + frames = thrd.frames(); + } catch (IncompatibleThreadStateException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + Iterator iterator = frames.iterator(); + boolean isMethodFound = false; + boolean isIntegerExpected = true; + IntegerValue res = null; + + while (iterator.hasNext()) { + stckFrm = (StackFrame )iterator.next(); + + if (stckFrm == null) + throw new TestBug("Not defined frame"); + if (method.equals(stckFrm.location().method())) { + isMethodFound = true; + try { + LocalVariable var = stckFrm.visibleVariableByName(varName); + res = (IntegerValue )stckFrm.getValue(var); + } catch (AbsentInformationException e) { + if (method.isObsolete()) { + display(EXPECTED_STRING + e + "\n"); + isIntegerExpected = false; + } + else + throw new TestBug(UNEXPECTED_STRING + e); + } + break; + } + } + if (!isMethodFound) + throw new MethodNotFoundException("Method :" + methodName + " not found"); + + if ( !(res instanceof IntegerValue) ) { + if (isIntegerExpected) + display("unexpected value\t: <" + res + ">\n"); + } else { + display(varName + " = " + res + "\n"); + } + + return res; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/TestDescription.java new file mode 100644 index 00000000000..443241b3c58 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/TestDescription.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * The redefined methods will be used on new invokes. + * If resetting these frames is desired, use + * ThreadReference.popFrames(StackFrame) with Method.isObsolete(). + * The test consists of the following files: + * redefineclasses002.java - debugger + * redefineclasses002a.java - initial debuggee + * newclass/redefineclasses002a.java - redefining debuggee + * This test performs the following steps: + * 1. Setting breakpoint at line of method, which will be redefined. + * This method has a local variable and the breakpoint + * is placed after it's initializing. + * 2. When breakpoint event is arrived, Debugger requests initial + * value of + * 3. While VM suspended Debugger redefines the tested method. + * It is added new line, after execution point. That line changes + * value of , different from initial-value. + * 4. While debugee remains suspending, debuger tries to get value of + * . In this case AbsentInformationException is expected. + * 5. Popping the active frame and trying to get value again. + * It is expected, method will be not found in active stack frames. + * 6. Setting breakpoint at line after the new one and resuming debugee. + * 7. Trying to get new value of . It is expected the last + * value will be different from initial-value. + * The test should be compiled with "-g" option, so cfg-file redefines + * JAVA_OPTS variable. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses002 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses002a + * + * @comment make sure redefineclasses002a is compiled with full debug info + * @clean nsk.jdi.VirtualMachine.redefineClasses.redefineclasses002a + * @compile -g:lines,source,vars ../redefineclasses002a.java + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses002 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/newclass/redefineclasses002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/newclass/redefineclasses002a.java new file mode 100644 index 00000000000..25b4340348c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/newclass/redefineclasses002a.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses002a is deugee's part of the redefineclasses002. + */ +public class redefineclasses002a { + + public final static String testedVarName = "testedVar"; + + public final static String brkpMethodName = "redefinedMethod"; + public final static int brkpLineNumber = 77; + + public final static int INITIAL_VALUE = 0; + public final static int REDEFINED_VALUE = 1; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("continue")) { + runIt(); + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + private static void runIt() { + redefineclasses002a obj = new redefineclasses002a(); + obj.redefinedMethod(); + } + + public void redefinedMethod() { + int testedVar = INITIAL_VALUE; // brkpLineNumber + log.display("redefinedMethod> breakpoint line"); + testedVar = REDEFINED_VALUE; + log.display("redefinedMethod> breakpoint line"); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002a.java new file mode 100644 index 00000000000..b5ddbc50899 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002a.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses002a is deugee's part of the redefineclasses002. + */ +public class redefineclasses002a { + + public final static String testedVarName = "testedVar"; + + public final static String brkpMethodName = "redefinedMethod"; + public final static int brkpLineNumber = 78; + + public final static int INITIAL_VALUE = 0; + public final static int REDEFINED_VALUE = 1; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("continue")) { + runIt(); + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + private static void runIt() { + redefineclasses002a obj = new redefineclasses002a(); + obj.redefinedMethod(); + } + + public void redefinedMethod() { + int testedVar = INITIAL_VALUE; + log.display("redefinedMethod> breakpoint line"); // brkpLineNumber + // Let's try to insert code here + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003.java new file mode 100644 index 00000000000..dc3e5458dec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test consits of the following files: + * redefineclasses003.java - debugger + * redefineclasses003a.java - initial debuggee + * newclass/redefineclasses003a.java - redefined debuggee + * + * When the test is starting debugee, debugger sets breakpoint at + * a line of method_A, where method_B is called. + * After the breakpoint is reached, debugger: + * - redefines debugee-class, that is inserting line after point of + * execution: log.display("new line"); + * - creates step request adding class filter + * - waits for a step event three times. + * + * In case, a step event didn't arrive from method_B, test fails. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + * + * The test should be compiled with -g option, so cfg-file redefines + * JAVA_OPTS variable. + */ + +public class redefineclasses003 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses003"; + private final static String debugeeName = debuggerName + "a"; + private final static String newClassFile = "newclass" + + File.separator + prefix.replace('.',File.separatorChar) + + "redefineclasses003a.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(debugeeName, Utils.TEST_CLASS_PATH) + .toString(); + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String clsDir; + + private ClassType testedClass; + + class MethodNotFoundException extends RuntimeException { + MethodNotFoundException (String msg) { + super(msg); + } + } + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses003 thisTest = new redefineclasses003(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + clsDir = argv[0]; + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses003a.brkpMethodName, + redefineclasses003a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + waitBreakpointEvent(brkp, waitTime); + + Field fld = null; + + display("\nTEST BEGINS"); + display("==========="); + + display(">>> Static fields initialized by "); + checkFields(redefineclasses003a.INITIAL_VALUE); + redefineClass(clsDir + File.separator + newClassFile); + checkFields(redefineclasses003a.INITIAL_VALUE); + + display("\n>>> Static fields initialized by debugger"); + IntegerValue newValue = debugee.VM().mirrorOf(redefineclasses003a.ASSIGNED_VALUE); + for (int i = 0; i < redefineclasses003a.testedFields.length; i++) { + fld = testedClass.fieldByName(redefineclasses003a.testedFields[i]); + try { + ((ClassType )testedClass).setValue(fld, newValue); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + checkFields(redefineclasses003a.ASSIGNED_VALUE); + redefineClass(oldClassFile); + checkFields(redefineclasses003a.ASSIGNED_VALUE); + + display("\n>>> Static fields initialized by debuggee at runtime"); + brkp = debugee.setBreakpoint(testedClass, + redefineclasses003a.brkpMethodName, + redefineclasses003a.brkpLineNumber + 9); + debugee.resume(); + + waitBreakpointEvent(brkp, waitTime); + + checkFields(redefineclasses003a.REASSIGNED_VALUE); + redefineClass(clsDir + File.separator + newClassFile); + checkFields(redefineclasses003a.REASSIGNED_VALUE); + + debugee.resume(); + display("============="); + display("TEST FINISHES\n"); + } + + private void checkFields(int expectedValue) { + int value; + Field fld; + Value val; + for (int i = 0; i < redefineclasses003a.testedFields.length; i++) { + fld = testedClass.fieldByName(redefineclasses003a.testedFields[i]); + val = testedClass.getValue(fld); + value = ((IntegerValue )val).value(); + if (value != expectedValue) { + complain("Unexpected " + fld.name() + " = " + + redefineclasses003a.value2String(value)); + exitStatus = Consts.TEST_FAILED; + return; + } + display(fld.name() + " = " + redefineclasses003a.value2String(value)); + } + } + + private void redefineClass(String classFile) { + display(">redefining the Debugee class..."); + Map mapBytes = mapClassToBytes(classFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canRedefineClasses()) { + complain("*** Warning: " + e); + complain("*** The test is considered as passed"); + return; + } + throw new TestBug(UNEXPECTED_STRING + e); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/TestDescription.java new file mode 100644 index 00000000000..d7adf74d742 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "...redefining a class does not cause its initializers to be run. + * The values of preexisting static variables will remain as they + * were prior to the call." + * The test consists of the following files: + * redefineclasses003.java - debugger + * redefineclasses003a.java - initial debuggee + * newclass/redefineclasses003a.java - redefining debuggee + * The redefined debugee differs from the initial debuggee by static + * initializer only. + * This test performs the following cases: + * 1. Values of static fields are assigned by + * 2. Values of static fields are changed by debugger + * 3. Values of static fields are changed by debugee + * After changing values of static fields, debugger redefines + * and checks that no initializer are run. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses003 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses003a + * + * @comment make sure redefineclasses003a is compiled with full debug info + * @clean nsk.jdi.VirtualMachine.redefineClasses.redefineclasses003a + * @compile -g:lines,source,vars ../redefineclasses003a.java + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses003 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/newclass/redefineclasses003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/newclass/redefineclasses003a.java new file mode 100644 index 00000000000..8a94c1ed0fd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003/newclass/redefineclasses003a.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses003a is deugee's part of the redefineclasses003. + */ +public class redefineclasses003a { + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 60; + public final static int INITIAL_VALUE = 0; + public final static int REDEFINED_VALUE = 1; + public final static int ASSIGNED_VALUE = 2; + public final static int REASSIGNED_VALUE = 3; + public final static String[] testedFields = { + "Field_1", + "Field_2", + "Field_3" + }; + // tested fields + private static int Field_1; + protected static int Field_2; + public static int Field_3; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (instr.equals("continue")) { + Field_1 = REASSIGNED_VALUE; + Field_2 = REASSIGNED_VALUE; + Field_3 = REASSIGNED_VALUE; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static String value2String(int val) { + switch (val) { + case INITIAL_VALUE: + return "INITIAL_VALUE"; + case REDEFINED_VALUE: + return "REDEFINED_VALUE"; + case ASSIGNED_VALUE: + return "ASSIGNED_VALUE"; + case REASSIGNED_VALUE: + return "REASSIGNED_VALUE"; + } + return ""; + } + + static { + Field_1 = REDEFINED_VALUE; + Field_2 = REDEFINED_VALUE; + Field_3 = REDEFINED_VALUE; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003a.java new file mode 100644 index 00000000000..ceafadb1596 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses003a.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses003a is deugee's part of the redefineclasses003. + */ +public class redefineclasses003a { + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 63; + + public final static int INITIAL_VALUE = 0; + public final static int REDEFINED_VALUE = 1; + public final static int ASSIGNED_VALUE = 2; + public final static int REASSIGNED_VALUE = 3; + public final static String[] testedFields = { + "Field_1", + "Field_2", + "Field_3" + }; + + // tested fields + private static int Field_1; + protected static int Field_2; + public static int Field_3; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("continue")) { // brkpLineNumber + Field_1 = REASSIGNED_VALUE; + Field_2 = REASSIGNED_VALUE; + Field_3 = REASSIGNED_VALUE; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static String value2String(int val) { + switch (val) { + case INITIAL_VALUE: + return "INITIAL_VALUE"; + case REDEFINED_VALUE: + return "REDEFINED_VALUE"; + case ASSIGNED_VALUE: + return "ASSIGNED_VALUE"; + case REASSIGNED_VALUE: + return "REASSIGNED_VALUE"; + } + return ""; + } + + static { + Field_1 = INITIAL_VALUE; + Field_2 = INITIAL_VALUE; + Field_3 = INITIAL_VALUE; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004.java new file mode 100644 index 00000000000..97987dc2e8e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * changing the schema(the fields) will throw UnsupportedOperationException + * exception" + * + * The test consists of the following files:
    + * redefineclasses004.java - debugger
    + * redefineclasses004a.java - initial debuggee
    + * newclassXX/redefineclasses004a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - adding the fields
    + * 2. newclass02 - deleting the fields
    + * 3. newclass03 - changing field modifiers (adding static)
    + * 4. newclass04 - changing field modifiers (adding final)
    + * 5. newclass05 - changing field modifiers (adding transient)
    + * 6. newclass06 - changing field modifiers (adding volatile)
    + * 7. newclass07 - changing field modifiers (changing public to protected)
    + * 8. newclass08 - changing field modifiers (changing protected to private)
    + * 9. newclass09 - changing field modifiers (changing protected to public)
    + * 10. newclass10 - changing field modifiers (changing private to public)
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses004 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses004"; + private final static String debugeeName = debuggerName + "a"; + + private final static String[][] subDirs = { + {"newclass01","adding the fields"}, + {"newclass02","deleting the fields"}, + {"newclass03","changing field modifiers (adding static)"}, + {"newclass04","changing field modifiers (adding final)"}, + {"newclass05","changing field modifiers (adding transient)"}, + {"newclass06","changing field modifiers (adding volatile)"}, + {"newclass07","changing field modifiers (changing public to protected"}, + {"newclass08","changing field modifiers (changing protected to private"}, + {"newclass09","changing field modifiers (changing protected to public)"}, + {"newclass10","changing field modifiers (changing private to public)"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses004a.class"; + private final static String oldClassFile = "classes" + + File.separator + prefix.replace('.',File.separatorChar) + + "redefineclasses004a.class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String clsDir; + + private ClassType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses004 thisTest = new redefineclasses004(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + clsDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + display("\n\n<<>>"); + display("--------------------------"); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + display("\n\n<<>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + complain("***" + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(clsDir + File.separator + fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/TestDescription.java new file mode 100644 index 00000000000..950aa1c547d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, changing the schema + * (the fields) will throw UnsupportedOperationException exception" + * The test consists of the following files: + * redefineclasses004.java - debugger + * redefineclasses004a.java - initial debuggee + * newclassXX/redefineclasses004a.java - redefining debuggees + * This test performs the following cases: + * 1. newclass01 - adding the fields + * 2. newclass02 - deleting the fields + * 3. newclass03 - changing field modifiers (adding static) + * 4. newclass04 - changing field modifiers (adding final) + * 5. newclass05 - changing field modifiers (adding transient) + * 6. newclass06 - changing field modifiers (adding volatile) + * 7. newclass07 - changing field modifiers (changing public to protected) + * 8. newclass08 - changing field modifiers (changing protected to private) + * 9. newclass09 - changing field modifiers (changing protected to public) + * 10. newclass10 - changing field modifiers (changing private to public) + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses004 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses004a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 newclass05 newclass06 newclass07 newclass08 newclass09 newclass10 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses004 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass01/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass01/redefineclasses004a.java new file mode 100644 index 00000000000..8e56507bfa9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass01/redefineclasses004a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing the schema (adding the fields) + */ + +public class redefineclasses004a { + + //preexisting fields + public Object field001; + protected Object field002; + private Object field003; + Object field004; + + static public Object field005 = null; + static protected Object field006 = null; + static private Object field007 = null; + static Object field008 = null; + + //new fields + public Object newField001; + protected Object newField002; + private Object newField003; + Object newField004; + + static public Object newField005; + static protected Object newField006; + static private Object newField007; + static Object newField008; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass02/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass02/redefineclasses004a.java new file mode 100644 index 00000000000..b799f6fc46b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass02/redefineclasses004a.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing the schema (deleting the fields) + */ + +public class redefineclasses004a { + + //preexisting fields + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass03/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass03/redefineclasses004a.java new file mode 100644 index 00000000000..ea9e4bc65e3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass03/redefineclasses004a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing field modifiers - adding static + */ + +public class redefineclasses004a { + + //preexisting fields + static public Object field001; + static protected Object field002; + static private Object field003; + static Object field004; + + static public Object field005 = null; + static protected Object field006 = null; + static private Object field007 = null; + static Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass04/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass04/redefineclasses004a.java new file mode 100644 index 00000000000..e38d4607fd6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass04/redefineclasses004a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing field modifiers (adding final) + */ + +public class redefineclasses004a { + + //preexisting fields + public Object field001; + protected Object field002; + private Object field003; + Object field004; + + static final public Object field005 = null; + static final protected Object field006 = null; + static final private Object field007 = null; + static final Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass05/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass05/redefineclasses004a.java new file mode 100644 index 00000000000..7fbccdd861e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass05/redefineclasses004a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing field modifiers (adding transient) + */ + +public class redefineclasses004a { + + //preexisting fields + transient public Object field001; + transient protected Object field002; + transient private Object field003; + transient Object field004; + + static public Object field005 = null; + static protected Object field006 = null; + static private Object field007 = null; + static Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass06/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass06/redefineclasses004a.java new file mode 100644 index 00000000000..3b5f901e893 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass06/redefineclasses004a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing field modifiers (adding volatile) + */ + +public class redefineclasses004a { + + //preexisting fields + volatile public Object field001; + volatile protected Object field002; + volatile private Object field003; + volatile Object field004; + + static public Object field005 = null; + static protected Object field006 = null; + static private Object field007 = null; + static Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass07/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass07/redefineclasses004a.java new file mode 100644 index 00000000000..6937a955c14 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass07/redefineclasses004a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing field modifiers (changing public to protected) + */ + +public class redefineclasses004a { + + //preexisting fields + protected Object field001; + protected Object field002; + private Object field003; + Object field004; + + static protected Object field005 = null; + static protected Object field006 = null; + static private Object field007 = null; + static Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass08/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass08/redefineclasses004a.java new file mode 100644 index 00000000000..bc1760df82a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass08/redefineclasses004a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing field modifiers (changing protected to private) + */ + +public class redefineclasses004a { + + //preexisting fields + public Object field001; + private Object field002; + private Object field003; + Object field004; + + static public Object field005 = null; + static private Object field006 = null; + static private Object field007 = null; + static Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass09/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass09/redefineclasses004a.java new file mode 100644 index 00000000000..8436355817d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass09/redefineclasses004a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing field modifiers (changing private to public) + */ + +public class redefineclasses004a { + + //preexisting fields + public Object field001; + protected Object field002; + public Object field003; + Object field004; + + static public Object field005 = null; + static protected Object field006 = null; + static public Object field007 = null; + static Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass10/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass10/redefineclasses004a.java new file mode 100644 index 00000000000..bc1760df82a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004/newclass10/redefineclasses004a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + * changing field modifiers (changing protected to private) + */ + +public class redefineclasses004a { + + //preexisting fields + public Object field001; + private Object field002; + private Object field003; + Object field004; + + static public Object field005 = null; + static private Object field006 = null; + static private Object field007 = null; + static Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004a.java new file mode 100644 index 00000000000..8d25dbaba4f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses004a.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses004a is deugee's part of the redefineclasses004. + */ + +public class redefineclasses004a { + + //preexisting fields + public Object field001; + protected Object field002; + private Object field003; + Object field004; + + static public Object field005 = null; + static protected Object field006 = null; + static private Object field007 = null; + static Object field008 = null; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005.java new file mode 100644 index 00000000000..c70a620b39e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canAddMethod() is false attempting to add + * a method will throw UnsupportedOperationException exception." + * + * The test consists of the following files:
    + * redefineclasses005.java - debugger
    + * redefineclasses005a.java - initial debuggee
    + * newclassXX/redefineclasses005a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - adding a public method
    + * 2. newclass02 - adding a protected method
    + * 3. newclass03 - adding a private method
    + * 4. newclass04 - adding a private package method
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses005 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses005"; + private final static String debugeeName = debuggerName + "a"; + + private final static String[][] subDirs = { + {"newclass01","adding a public method"}, + {"newclass02","adding a protected method"}, + {"newclass03","adding a private method"}, + {"newclass04","adding a private package method"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses005a.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(debugeeName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String clsDir; + private static String statDebugee; + + private ClassType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses005 thisTest = new redefineclasses005(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + clsDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses005a.brkpMethodName, + redefineclasses005a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + waitBreakpointEvent(brkp, waitTime); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(clsDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canAddMethod()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canAddMethod()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/TestDescription.java new file mode 100644 index 00000000000..3ae0fe7ea93 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canAddMethod() is false attempting to add a method will throw + * UnsupportedOperationException exception." + * The test consists of the following files: + * redefineclasses005.java - debugger + * redefineclasses005a.java - initial debuggee + * newclassXX/redefineclasses005a.java - redefining debuggees + * This test performs the following cases: + * 1. newclass01 - adding a public method + * 2. newclass02 - adding a protected method + * 3. newclass03 - adding a private method + * 4. newclass04 - adding a private package method + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses005 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses005a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses005 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass01/redefineclasses005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass01/redefineclasses005a.java new file mode 100644 index 00000000000..8f27c9c5785 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass01/redefineclasses005a.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses005a is deugee's part of the redefineclasses005. + * adding a public method + */ +public class redefineclasses005a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public void newMethod() { + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass02/redefineclasses005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass02/redefineclasses005a.java new file mode 100644 index 00000000000..ff8d591ee97 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass02/redefineclasses005a.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses005a is deugee's part of the redefineclasses005. + * adding a protected method + */ +public class redefineclasses005a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 50; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + protected void newMethod() { + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass03/redefineclasses005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass03/redefineclasses005a.java new file mode 100644 index 00000000000..58341e74f0a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass03/redefineclasses005a.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses005a is deugee's part of the redefineclasses005. + * adding a private method + */ +public class redefineclasses005a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + private void newMethod() { + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass04/redefineclasses005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass04/redefineclasses005a.java new file mode 100644 index 00000000000..34d79198f92 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005/newclass04/redefineclasses005a.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses005a is deugee's part of the redefineclasses005. + * adding a private package method + */ +public class redefineclasses005a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 50; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + void newMethod() { + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005a.java new file mode 100644 index 00000000000..231b47bb3e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses005a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses005a is deugee's part of the redefineclasses005. + */ +public class redefineclasses005a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006.java new file mode 100644 index 00000000000..de6ff8afc22 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * attempting to delete a method will throw UnsupportedOperationException + * exception." + * + * The test consists of the following files:
    + * redefineclasses006.java - debugger
    + * redefineclasses006a.java - initial debuggee
    + * newclassXX/redefineclasses006a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - deleting a public method
    + * 2. newclass02 - deleting a protected method
    + * 3. newclass03 - deleting a private method
    + * 4. newclass04 - deleting a private package method
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses006 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses006"; + private final static String debugeeName = debuggerName + "a"; + + private final static String[][] subDirs = { + {"newclass01","deleting a public method"}, + {"newclass02","deleting a protected method"}, + {"newclass03","deleting a private method"}, + {"newclass04","deleting a private package method"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses006a.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(debugeeName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ClassType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses006 thisTest = new redefineclasses006(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses006a.brkpMethodName, + redefineclasses006a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + waitBreakpointEvent(brkp, waitTime); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***" + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/TestDescription.java new file mode 100644 index 00000000000..35aacba6cce --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, attempting to + * delete a method will throw UnsupportedOperationException exception" + * The test consists of the following files: + * redefineclasses006.java - debugger + * redefineclasses006a.java - initial debuggee + * newclassXX/redefineclasses006a.java - redefining debuggees + * This test performs the following cases: + * 1. newclass01 - deleting a public method + * 2. newclass02 - deleting a protected method + * 3. newclass03 - deleting a private method + * 4. newclass04 - deleting a private package method + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses006 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses006a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses006 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass01/redefineclasses006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass01/redefineclasses006a.java new file mode 100644 index 00000000000..d95f5755484 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass01/redefineclasses006a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses006a is deugee's part of the redefineclasses006. + * deleting a public method + */ +public class redefineclasses006a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass02/redefineclasses006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass02/redefineclasses006a.java new file mode 100644 index 00000000000..0dc5f253fef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass02/redefineclasses006a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses006a is deugee's part of the redefineclasses006. + * deleting a protected method + */ +public class redefineclasses006a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public void dummyMethod01() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass03/redefineclasses006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass03/redefineclasses006a.java new file mode 100644 index 00000000000..60fd3c0bda0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass03/redefineclasses006a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses006a is deugee's part of the redefineclasses006. + * deleting a private method + */ +public class redefineclasses006a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass04/redefineclasses006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass04/redefineclasses006a.java new file mode 100644 index 00000000000..d338188510a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006/newclass04/redefineclasses006a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses006a is deugee's part of the redefineclasses006. + * deleting a private package method + */ +public class redefineclasses006a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006a.java new file mode 100644 index 00000000000..279c5b25398 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses006a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses006a is deugee's part of the redefineclasses006. + */ +public class redefineclasses006a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007.java new file mode 100644 index 00000000000..cd386c8ada7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * attempting to change method modifiers will throw + * UnsupportedOperationException exception + * + * The test consists of the following files:
    + * redefineclasses007.java - debugger
    + * redefineclasses007a.java - initial debuggee
    + * newclassXX/redefineclasses007a.java - redefining debuggees
    + * + * Initial debugee-class has four dummy methods with different kind of accessibility: + * public, protected, private and + * default access (package private). + * This test performs the following cases:
    + * 1. adding modifiers to public method
    + * 2. adding modifiers to 4 methods
    + * 3. adding modifiers to public method
    + * 4. adding modifiers to 4 methods
    + * 5. adding modifiers to public method
    + * 6. adding modifiers to 4 methods
    + * 7. adding modifiers to public method
    + * 8. adding modifiers to 4 methods
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses007 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses007"; + private final static String debugeeName = debuggerName + "a"; + + private final static String[][] subDirs = { + {"newclass01","adding modifiers to public method"}, + {"newclass02","adding modifiers to 4 methods"}, + {"newclass03","adding modifiers to public method"}, + {"newclass04","adding modifiers to 4 methods"}, + {"newclass05","adding modifiers to public method"}, + {"newclass06","adding modifiers to 4 methods"}, + {"newclass07","adding modifiers to public method"}, + {"newclass08","adding modifiers to 4 methods"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses007a.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(debugeeName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ClassType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses007 thisTest = new redefineclasses007(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses007a.brkpMethodName, + redefineclasses007a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + waitBreakpointEvent(brkp, waitTime); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***" + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/TestDescription.java new file mode 100644 index 00000000000..d53762c0598 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, attempting to + * change method modifiers will throw UnsupportedOperationException + * exception" + * The test consists of the following files: + * redefineclasses007.java - debugger + * redefineclasses007a.java - initial debuggee + * newclassXX/redefineclasses007a.java - redefining debuggees + * Initial debugee-class has four dummy methods with different + * kind of accessibility: public, protected, private and + * default access (package private). + * This test performs the following cases: + * 1. newclass01 - adding modifiers to public method + * 2. newclass02 - adding modifiers to 4 methods + * 3. newclass03 - adding modifiers to public method + * 4. newclass04 - adding modifiers to 4 methods + * 5. newclass05 - adding modifiers to public method + * 6. newclass06 - adding modifiers to 4 methods + * 7. newclass07 - adding modifiers to public method + * 8. newclass08 - adding modifiers to 4 methods + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses007 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses007a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 newclass05 newclass06 newclass07 newclass08 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses007 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass01/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass01/redefineclasses007a.java new file mode 100644 index 00000000000..7f3530c82ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass01/redefineclasses007a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + * changing method modifiers (1 method to static) + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + static public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass02/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass02/redefineclasses007a.java new file mode 100644 index 00000000000..be4842b3092 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass02/redefineclasses007a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + * changing method modifiers (4 methods to static) + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + static public void dummyMethod01() { + } + + static protected void dummyMethod02() { + } + + static private void dummyMethod03() { + } + + static void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass03/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass03/redefineclasses007a.java new file mode 100644 index 00000000000..3e665456b47 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass03/redefineclasses007a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + * changing method modifiers (1 method to final) + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public final void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass04/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass04/redefineclasses007a.java new file mode 100644 index 00000000000..092bedb8124 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass04/redefineclasses007a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + * changing method modifiers (4 methods to final) + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + final public void dummyMethod01() { + } + + final protected void dummyMethod02() { + } + + final private void dummyMethod03() { + } + + final void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass05/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass05/redefineclasses007a.java new file mode 100644 index 00000000000..7f126200c45 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass05/redefineclasses007a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + * changing method modifiers (to synchronized) + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 50; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + synchronized public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass06/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass06/redefineclasses007a.java new file mode 100644 index 00000000000..cd7807e2adf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass06/redefineclasses007a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + * changing method modifiers (4 methods to synchronized) + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + synchronized public void dummyMethod01(){ + } + + synchronized protected void dummyMethod02(){ + } + + synchronized private void dummyMethod03(){ + } + + synchronized void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass07/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass07/redefineclasses007a.java new file mode 100644 index 00000000000..6dccb5cb496 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass07/redefineclasses007a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + * changing method modifiers (1 method to strictfp) + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + strictfp public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass08/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass08/redefineclasses007a.java new file mode 100644 index 00000000000..ca99ce12732 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007/newclass08/redefineclasses007a.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + * changing method modifiers (4 methods to strictfp) + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + strictfp public void dummyMethod01(){ + } + + strictfp protected void dummyMethod02(){ + } + + strictfp private void dummyMethod03(){ + } + + strictfp void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007a.java new file mode 100644 index 00000000000..22e1d0dfb65 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses007a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses007a is deugee's part of the redefineclasses007. + */ +public class redefineclasses007a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } + + void dummyMethod04() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008.java new file mode 100644 index 00000000000..fee67914466 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * attempting to change method modifiers will throw + * UnsupportedOperationException exception" + * + * The test consists of the following files:
    + * redefineclasses008.java - debugger
    + * redefineclasses008a.java - initial debuggee
    + * newclassXX/redefineclasses008a.java - redefining debuggees
    + * + * Initial debugee-class has three dummy methods with different + * kind of accessibility: public, protected and private (see COMMENTS into readme-file) + * This test performs the following cases:
    + * 1.newclass01 - adding modifiers to public method
    + * 2.newclass02 - adding modifiers to 3 methods
    + * 3.newclass03 - adding modifiers to public method
    + * 4.newclass04 - adding modifiers to 3 methods
    + * 5.newclass05 - adding modifiers to public method
    + * 6.newclass06 - adding modifiers to 3 methods
    + * 7.newclass07 - adding modifiers to public method
    + * 8.newclass08 - adding modifiers to 3 methods
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses008 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses008"; + private final static String debugeeName = debuggerName + "a"; + + private final static String[][] subDirs = { + {"newclass01","adding modifiers to public method"}, + {"newclass02","adding modifiers to 3 methods"}, + {"newclass03","adding modifiers to public method"}, + {"newclass04","adding modifiers to 3 methods"}, + {"newclass05","adding modifiers to public method"}, + {"newclass06","adding modifiers to 3 methods"}, + {"newclass07","adding modifiers to public method"}, + {"newclass08","adding modifiers to 3 methods"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses008a.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(debugeeName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ClassType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses008 thisTest = new redefineclasses008(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses008a.brkpMethodName, + redefineclasses008a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + waitBreakpointEvent(brkp, waitTime); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/TestDescription.java new file mode 100644 index 00000000000..087af8ea2b0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, attempting to + * change method modifiers will throw UnsupportedOperationException + * exception" + * The test consists of the following files: + * redefineclasses008.java - debugger + * redefineclasses008a.java - initial debuggee + * newclassXX/redefineclasses008a.java - redefining debuggees + * Initial debugee-class has three dummy methods with different + * kind of accessibility: public, protected and private (see COMMENTS) + * This test performs the following cases: + * 1. newclass01 - adding modifiers to public method + * 2. newclass02 - adding modifiers to 3 methods + * 3. newclass03 - adding modifiers to public method + * 4. newclass04 - adding modifiers to 3 methods + * 5. newclass05 - adding modifiers to public method + * 6. newclass06 - adding modifiers to 3 methods + * 7. newclass07 - adding modifiers to public method + * 8. newclass08 - adding modifiers to 3 methods + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * This test looks like redefinclasses07 and differs from redefinclasses07 + * that default access (package private) is excluded from examintation. + * There are no differs except the one. It was observed, count and + * accessibility of the methods affect the test behaviour. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses008 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses008a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 newclass05 newclass06 newclass07 newclass08 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses008 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass01/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass01/redefineclasses008a.java new file mode 100644 index 00000000000..4cd288f0756 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass01/redefineclasses008a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + * changing method modifiers (1 method to static) + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + static public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass02/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass02/redefineclasses008a.java new file mode 100644 index 00000000000..4396922ca62 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass02/redefineclasses008a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + * changing method modifiers (3 methods to static) + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + static public void dummyMethod01() { + } + + static protected void dummyMethod02() { + } + + static private void dummyMethod03() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass03/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass03/redefineclasses008a.java new file mode 100644 index 00000000000..ac9dc5694ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass03/redefineclasses008a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + * changing method modifiers (1 method to final) + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public final void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass04/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass04/redefineclasses008a.java new file mode 100644 index 00000000000..c65b3f4ca73 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass04/redefineclasses008a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + * changing method modifiers (3 methods to final) + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + final public void dummyMethod01() { + } + + final protected void dummyMethod02() { + } + + final private void dummyMethod03() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass05/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass05/redefineclasses008a.java new file mode 100644 index 00000000000..51acebb8384 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass05/redefineclasses008a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + * changing method modifiers (to synchronized) + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 50; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + synchronized public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass06/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass06/redefineclasses008a.java new file mode 100644 index 00000000000..a92f0b5f591 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass06/redefineclasses008a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + * changing method modifiers (3 methods to synchronized) + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + synchronized public void dummyMethod01(){ + } + + synchronized protected void dummyMethod02(){ + } + + synchronized private void dummyMethod03(){ + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass07/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass07/redefineclasses008a.java new file mode 100644 index 00000000000..b48ead051d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass07/redefineclasses008a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + * changing method modifiers (1 method to strictfp) + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + strictfp public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass08/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass08/redefineclasses008a.java new file mode 100644 index 00000000000..13330e1ab14 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008/newclass08/redefineclasses008a.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + * changing method modifiers (3 methods to strictfp) + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + strictfp public void dummyMethod01(){ + } + + strictfp protected void dummyMethod02(){ + } + + strictfp private void dummyMethod03(){ + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008a.java new file mode 100644 index 00000000000..591f8e77067 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses008a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses008a is deugee's part of the redefineclasses008. + */ +public class redefineclasses008a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public void dummyMethod01() { + } + + protected void dummyMethod02() { + } + + private void dummyMethod03() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009.java new file mode 100644 index 00000000000..17bdee16578 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009.java @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * attempting to change constructor modifiers will throw + * UnsupportedOperationException exception" + * + * The test consists of the following files:
    + * redefineclasses009.java - debugger
    + * redefineclasses009a.java - initial debuggee
    + * newclassXX/redefineclasses009a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1.newclass01 - adding modifier to constructor
    + * 2.newclass02 - adding modifier to constructor
    + * 3.newclass03 - adding modifier to constructor
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses009 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses009"; + private final static String debugeeName = debuggerName + "a"; + + private final static String[][] subDirs = { + {"newclass01","adding modifier to constructor"}, + {"newclass02","adding modifier to constructor"}, + {"newclass03","adding modifier to constructor"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses009a.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(debugeeName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ClassType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses009 thisTest = new redefineclasses009(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses009a.brkpMethodName, + redefineclasses009a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + waitBreakpointEvent(brkp, waitTime); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/TestDescription.java new file mode 100644 index 00000000000..5a545224f11 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, attempting to + * change constructor modifiers will throw UnsupportedOperationException + * exception" + * The test consists of the following files: + * redefineclasses009.java - debugger + * redefineclasses009a.java - initial debugee + * newclassXX/redefineclasses009a.java - redefining debugees + * This test performs the following cases: + * 1. newclass01 - adding modifier to constructor + * 2. newclass02 - adding modifier to constructor + * 3. newclass03 - adding modifier to constructor + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * This test looks like redefinclasses07 and differs from redefinclasses07 + * that default access (package private) is excluded from examintation. + * There are no differs except the one. It was observed, count and + * accessibility of the methods affect the test behaviour. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses009 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses009a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses009 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass01/redefineclasses009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass01/redefineclasses009a.java new file mode 100644 index 00000000000..db8fc9a904e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass01/redefineclasses009a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses009a is deugee's part of the redefineclasses009. + */ +public class redefineclasses009a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public redefineclasses009a() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass02/redefineclasses009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass02/redefineclasses009a.java new file mode 100644 index 00000000000..659551a4d6c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass02/redefineclasses009a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses009a is deugee's part of the redefineclasses009. + */ +public class redefineclasses009a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + protected redefineclasses009a() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass03/redefineclasses009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass03/redefineclasses009a.java new file mode 100644 index 00000000000..827c2ac71f0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009/newclass03/redefineclasses009a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses009a is deugee's part of the redefineclasses009. + */ +public class redefineclasses009a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + private redefineclasses009a() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009a.java new file mode 100644 index 00000000000..0b428e18466 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses009a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses009a is deugee's part of the redefineclasses009. + */ +public class redefineclasses009a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + redefineclasses009a() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010.java new file mode 100644 index 00000000000..740e38485fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * attempting to delete constructor will throw + * UnsupportedOperationException exception" + * + * The test consists of the following files:
    + * redefineclasses010.java - debugger
    + * redefineclasses010a.java - initial debuggee
    + * newclassXX/redefineclasses010a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1.newclass01 - deleting constructor
    + * 2.newclass02 - deleting constructor
    + * 3.newclass03 - deleting constructor
    + * 4.newclass04 - deleting constructor
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses010 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses010"; + private final static String debugeeName = debuggerName + "a"; + + private final static String[][] subDirs = { + {"newclass01","deleting constructor"}, + {"newclass02","deleting constructor"}, + {"newclass03","deleting constructor"}, + {"newclass04","deleting constructor"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses010a.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(debugeeName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ClassType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses010 thisTest = new redefineclasses010(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses010a.brkpMethodName, + redefineclasses010a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + waitBreakpointEvent(brkp, waitTime); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/TestDescription.java new file mode 100644 index 00000000000..5a5297e67a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, attempting to + * delete constructor will throw UnsupportedOperationException + * exception" + * The test consists of the following files: + * redefineclasses010.java - debugger + * redefineclasses010a.java - initial debugee + * newclassXX/redefineclasses010a.java - redefining debugees + * This test performs the following cases: + * 1. newclass01 - deleting constructor + * 2. newclass02 - deleting constructor + * 3. newclass03 - deleting constructor + * 4. newclass04 - deleting constructor + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses010 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses010a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses010 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass01/redefineclasses010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass01/redefineclasses010a.java new file mode 100644 index 00000000000..06eb341b4f2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass01/redefineclasses010a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses010a is deugee's part of the redefineclasses010. + */ +public class redefineclasses010a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + protected redefineclasses010a(Object par) { + } + + private redefineclasses010a(Object par1, Object par2) { + } + + redefineclasses010a(Object par1, Object par2, Object par3) { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass02/redefineclasses010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass02/redefineclasses010a.java new file mode 100644 index 00000000000..68343dedc95 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass02/redefineclasses010a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses010a is deugee's part of the redefineclasses010. + */ +public class redefineclasses010a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public redefineclasses010a() { + } + + private redefineclasses010a(Object par1, Object par2) { + } + + redefineclasses010a(Object par1, Object par2, Object par3) { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass03/redefineclasses010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass03/redefineclasses010a.java new file mode 100644 index 00000000000..724d1f4916f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass03/redefineclasses010a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses010a is deugee's part of the redefineclasses010. + */ +public class redefineclasses010a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public redefineclasses010a() { + } + + protected redefineclasses010a(Object par) { + } + + redefineclasses010a(Object par1, Object par2, Object par3) { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass04/redefineclasses010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass04/redefineclasses010a.java new file mode 100644 index 00000000000..248bdd1bb1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010/newclass04/redefineclasses010a.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses010a is deugee's part of the redefineclasses010. + */ +public class redefineclasses010a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public redefineclasses010a() { + } + + protected redefineclasses010a(Object par) { + } + + private redefineclasses010a(Object par1, Object par2) { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010a.java new file mode 100644 index 00000000000..7d4ceacb898 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses010a.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses010a is deugee's part of the redefineclasses010. + */ +public class redefineclasses010a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public redefineclasses010a() { + } + + protected redefineclasses010a(Object par) { + } + + private redefineclasses010a(Object par1, Object par2) { + } + + redefineclasses010a(Object par1, Object par2, Object par3) { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011.java new file mode 100644 index 00000000000..28d9a53f272 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011.java @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * attempting to add a constructor will throw + * UnsupportedOperationException exception" + * + * The test consists of the following files:
    + * redefineclasses011.java - debugger
    + * redefineclasses011a.java - initial debuggee
    + * newclassXX/redefineclasses011a.java - redefining debuggees
    + * + * Initial debugee-class has four dummy methods with different + * kind of accessibility: public, protected and private (see COMMENTS into readme-file) + * This test performs the following cases:
    + * 1.newclass01 - adding constructor
    + * 2.newclass02 - adding constructor
    + * 3.newclass03 - adding constructor
    + * 4.newclass04 - adding constructor
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses011 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses011"; + private final static String debugeeName = debuggerName + "a"; + + private final static String[][] subDirs = { + {"newclass01","adding constructor"}, + {"newclass02","adding constructor"}, + {"newclass03","adding constructor"}, + {"newclass04","adding constructor"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses011a.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(debugeeName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ClassType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses011 thisTest = new redefineclasses011(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + debugee.sendSignal("continue"); + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + testedClass = (ClassType)debugee.classByName(debugeeName); + display("Tested class\t:" + testedClass.name()); + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + redefineclasses011a.brkpMethodName, + redefineclasses011a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal("continue"); + + waitBreakpointEvent(brkp, waitTime); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + + /* adding an explicit public ctor into a public class without + constructor declarations. + The JLS 2nd ed. says: + "8.8.7 Default Constructor + If a class contains no constructor declarations, then a + default constructor that takes no parameters is automatically + provided. + ... + If the class is declared public, then the default constructor + is implicitly given the access modifier public (6.6)" + + So, no exception is expected. + */ + display("\n" + subDirs[0][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [0][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + + display(">check passed: class file redefinition done successfully" + + "\n>return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } catch(Exception e) { + complain("***Unexpected " + e +" is thrown" + + "\n***\twhile " + subDirs[0][1]); + exitStatus = Consts.TEST_FAILED; + } + + // adding an explicit ctor with different access modifiers + for (int i = 1; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canAddMethod()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canAddMethod()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + display(">waiting breakpoint event..."); + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new TestBug("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/TestDescription.java new file mode 100644 index 00000000000..fb3bd40fdfe --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/TestDescription.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, attempting to + * add a constructor will throw UnsupportedOperationException + * exception" + * The test consists of the following files: + * redefineclasses011.java - debugger + * redefineclasses011a.java - initial debugee + * newclassXX/redefineclasses011a.java - redefining debugees + * This test performs the following cases: + * 1. newclass01 - adding an explicit constructor into a public + * class without constructor declarations. No exception is expected: + * the JLS 2nd ed. says: + * "8.8.7 Default Constructor + * If a class contains no constructor declarations, then a + * default constructor that takes no parameters is automatically + * provided. + * ... + * If the class is declared public, then the default constructor + * is implicitly given the access modifier public (6.6)" + * 2. newclass02 - adding constructor into a public class + * without constructor declarations, exception may occure + * 3. newclass03 - adding constructor into a public class + * without constructor declarations, exception may occure + * 4. newclass04 - adding constructor into a public class + * without constructor declarations, exception may occure + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * The test was fixed due to the following bug: + * 4762721 TEST_BUG: Some tests for RedefineClasses erroneously change + * ctor modifier + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses011 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses011a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses011 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass01/redefineclasses011a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass01/redefineclasses011a.java new file mode 100644 index 00000000000..92bd1c596d6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass01/redefineclasses011a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses011a is deugee's part of the redefineclasses011. + */ +public class redefineclasses011a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public redefineclasses011a() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass02/redefineclasses011a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass02/redefineclasses011a.java new file mode 100644 index 00000000000..85068514d65 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass02/redefineclasses011a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses011a is deugee's part of the redefineclasses011. + */ +public class redefineclasses011a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + protected redefineclasses011a() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass03/redefineclasses011a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass03/redefineclasses011a.java new file mode 100644 index 00000000000..0ce5a6023c0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass03/redefineclasses011a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses011a is deugee's part of the redefineclasses011. + */ +public class redefineclasses011a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + private redefineclasses011a() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass04/redefineclasses011a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass04/redefineclasses011a.java new file mode 100644 index 00000000000..9d91baa0154 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011/newclass04/redefineclasses011a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses011a is deugee's part of the redefineclasses011. + */ +public class redefineclasses011a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 48; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); // brkpLineNumber + if (!instr.equals("continue")) { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + redefineclasses011a() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011a.java new file mode 100644 index 00000000000..ba9a9a63239 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses011a.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses011a is deugee's part of the redefineclasses011. + */ +public class redefineclasses011a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 49; + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (!instr.equals("continue")) { // brkpLineNumber + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012.java new file mode 100644 index 00000000000..b5490cbbfd7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * changing the schema(the fields) will throw UnsupportedOperationException + * exception" + * This test looks like redefineclasses004 and checks the assertion + * against interfaces. + * + * The test consists of the following files:
    + * redefineclasses012.java - debugger
    + * redefineclasses012a.java - initial debuggee
    + * newclassXX/redefineclasses012a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - adding the fields
    + * 2. newclass02 - deleting the fields
    + * 3. newclass03 - adding modifier
    + * 4. newclass04 - adding modifier
    + * 5. newclass05 - changing modifier to
    + * 6. newclass06 - changing modifier to
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses012 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses012"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debuggerName + "b"; + + private final static String[][] subDirs = { + {"newclass01","adding the fields"}, + {"newclass02","deleting the fields"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses012b.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String testDir; + private static String statDebugee; + + private ReferenceType debugeeClass, testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses012 thisTest = new redefineclasses012(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + debugeeClass = debugee.classByName(debugeeName); + testedClass = debugee.classByName(testedClassName); + display("Tested class\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***" + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/TestDescription.java new file mode 100644 index 00000000000..7a075502631 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, changing the schema + * (the fields) will throw UnsupportedOperationException exception" + * This test looks like redefineclasses004 and checks the assertion + * against interfaces. + * The test consists of the following files: + * redefineclasses012.java - debugger + * redefineclasses012a.java - debuggee + * redefineclasses012b.java - an initial redefined class + * newclassXX/redefineclasses012b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - adding the fields + * 2. newclass02 - deleting the fields + * 3. newclass03 - adding modifier + * 4. newclass04 - adding modifier + * 5. newclass05 - changing modifier to + * 6. newclass06 - changing modifier to + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses012 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses012a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses012 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/newclass01/redefineclasses012b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/newclass01/redefineclasses012b.java new file mode 100644 index 00000000000..d005e19ae83 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/newclass01/redefineclasses012b.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses012b is deugee's part of the redefineclasses012. + * adding new field + */ + +public interface redefineclasses012b { + + //new fields + static public final Object newField001 = null; + + //preexisting fields + static public final Object field001 = null; + public final Object field002 = null; + final Object field003 = null; + Object field004 = null; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/newclass02/redefineclasses012b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/newclass02/redefineclasses012b.java new file mode 100644 index 00000000000..56bb1fc0032 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012/newclass02/redefineclasses012b.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses012b is deugee's part of the redefineclasses012. + * deleting fields + */ + +public interface redefineclasses012b { + + //preexisting fields +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012a.java new file mode 100644 index 00000000000..017eee1a0cd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012a.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses012a is deugee's part of the redefineclasses012. + */ + +public class redefineclasses012a { + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + redefineclasses012bc obj = new redefineclasses012bc(); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class redefineclasses012bc implements redefineclasses012b { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012b.java new file mode 100644 index 00000000000..53e2b150244 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses012b.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses012b is deugee's part of the redefineclasses012. + */ + +public interface redefineclasses012b { + + //preexisting fields + static public final Object field001 = null; + public final Object field002 = null; + final Object field003 = null; + Object field004 = null; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013.java new file mode 100644 index 00000000000..beb100e86d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013.java @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canAddMethod() is false attempting to add + * a method will throw UnsupportedOperationException exception." + * This test looks like redefineclasses005 and checks the assertion + * against interfaces. + * + * The test consists of the following files:
    + * redefineclasses013.java - debugger
    + * redefineclasses013a.java - initial debuggee
    + * newclassXX/redefineclasses013a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - adding new method declared as
    + * abstract public void newMethod()
    + * 2. newclass02 - adding new method declared as
    + * public void newMethod()
    + * 3. newclass03 - adding new method declared as
    + * void newMethod()
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses013 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses013"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debuggerName + "b"; + + private final static String[][] subDirs = { + {"newclass01","adding \"abstract public void newMethod()\""}, + {"newclass02","adding \"public void newMethod()\""}, + {"newclass03","adding \"void newMethod()\""} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses013b.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses013 thisTest = new redefineclasses013(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + ClassPrepareRequest clpr = debugee.getEventRequestManager().createClassPrepareRequest(); + clpr.addClassFilter(testedClassName); + clpr.enable(); + + debugee.sendSignal("load_class"); + + ClassPrepareEvent clpEvent = waitClassPrepareEvent(clpr, waitTime); + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canAddMethod()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canAddMethod()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private ClassPrepareEvent waitClassPrepareEvent(ClassPrepareRequest clpr, long waitTime) { + Event event; + display(">waiting class prepare event..."); + try { + event = debugee.waitingEvent(clpr, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof ClassPrepareEvent )) { + throw new TestBug("ClassPrepareEvent didn't arrive"); + } + + return (ClassPrepareEvent )event; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/TestDescription.java new file mode 100644 index 00000000000..29dc5cba634 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canAddMethod() is false attempting to add a method will throw + * UnsupportedOperationException exception." + * This test looks like redefineclasses005 and checks the assertion + * against interfaces. + * The test consists of the following files: + * redefineclasses013.java - debugger + * redefineclasses013a.java - debuggee + * redefineclasses013b.java - an initial redefined class + * newclassXX/redefineclasses013b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - adding new method declared as + * "abstract public void newMethod()" + * 2. newclass02 - adding new method declared as "public void newMethod()" + * 3. newclass03 - adding new method declared as "void newMethod()" + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses013 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses013a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses013 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass01/redefineclasses013b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass01/redefineclasses013b.java new file mode 100644 index 00000000000..fffb19a1263 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass01/redefineclasses013b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses013b is deugee's part of the redefineclasses013. + * adding new method declared as abstract public void newMethod() + */ + +public interface redefineclasses013b { + + abstract public void newMethod(); + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass02/redefineclasses013b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass02/redefineclasses013b.java new file mode 100644 index 00000000000..6cadc886333 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass02/redefineclasses013b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses013b is deugee's part of the redefineclasses013. + * adding new method declared as public void newMethod() + */ + +public interface redefineclasses013b { + + public void newMethod(); + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass03/redefineclasses013b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass03/redefineclasses013b.java new file mode 100644 index 00000000000..7e6d6c74f76 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013/newclass03/redefineclasses013b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses013b is deugee's part of the redefineclasses013. + * adding new method declared as void newMethod() + */ + +public interface redefineclasses013b { + + void newMethod(); + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013a.java new file mode 100644 index 00000000000..e5c19184561 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013a.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses013a is deugee's part of the redefineclasses013. + */ + +public class redefineclasses013a { + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("load_class")) { + // to force ClassPrepareEvent, change value of this field + redefineclasses013bc.classPrepare = true; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + +} + +abstract class redefineclasses013bc implements redefineclasses013b { + // to force ClassPrepareEvent, change value of this field + static boolean classPrepare; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013b.java new file mode 100644 index 00000000000..46fc7f2aa09 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses013b.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses013b is deugee's part of the redefineclasses013. + */ + +public interface redefineclasses013b { + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014.java new file mode 100644 index 00000000000..7f5e2ec4c57 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * attempting to delete a method will throw UnsupportedOperationException + * exception." + * This test looks like redefineclasses006 and checks the assertion + * against interfaces. + * + * The test consists of the following files:
    + * redefineclasses014.java - debugger
    + * redefineclasses014a.java - initial debuggee
    + * newclassXX/redefineclasses014a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - deleting method declared as abstract
    + * abstract public void dummyMethod01()
    + * 2. newclass02 - deleting method declared as
    + * public void dummyMethod02()
    + * 3. newclass03 - deleting method declared as
    + * void dummyMethod03()
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses014 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses014"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debuggerName + "b"; + + private final static String[][] subDirs = { + {"newclass01","deleting \"abstract public void dummyMethod01()\""}, + {"newclass02","deleting \"public void dummyMethod02()\""}, + {"newclass03","deleting \"void dummyMethod03()\""} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses014b.class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses014 thisTest = new redefineclasses014(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + ClassPrepareRequest clpr = debugee.getEventRequestManager().createClassPrepareRequest(); + clpr.addClassFilter(testedClassName); + clpr.enable(); + + debugee.sendSignal("load_class"); + + ClassPrepareEvent clpEvent = waitClassPrepareEvent(clpr, waitTime); + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canAddMethod()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canAddMethod()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private ClassPrepareEvent waitClassPrepareEvent(ClassPrepareRequest clpr, long waitTime) { + Event event; + display(">waiting class prepare event..."); + try { + event = debugee.waitingEvent(clpr, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof ClassPrepareEvent )) { + throw new TestBug("ClassPrepareEvent didn't arrive"); + } + + return (ClassPrepareEvent )event; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/TestDescription.java new file mode 100644 index 00000000000..5e151ea7fac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, attempting to + * delete a method will throw UnsupportedOperationException exception" + * This test looks like redefineclasses006 and checks the assertion + * against interfaces. + * The test consists of the following files: + * redefineclasses014.java - debugger + * redefineclasses014a.java - debuggee + * redefineclasses014b.java - an initial redefined class + * newclassXX/redefineclasses014b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - deleting a public method + * 2. newclass02 - deleting a private package method + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses014 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses014a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses014 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass01/redefineclasses014b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass01/redefineclasses014b.java new file mode 100644 index 00000000000..cdd7fa32342 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass01/redefineclasses014b.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses014b is deugee's part of the redefineclasses014. + * deleting method declared as abstract abstract public void dummyMethod01() + */ + +public interface redefineclasses014b { + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass02/redefineclasses014b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass02/redefineclasses014b.java new file mode 100644 index 00000000000..be09cd35093 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass02/redefineclasses014b.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses014b is deugee's part of the redefineclasses014. + * deleting method declared as public void dummyMethod02() + */ + +public interface redefineclasses014b { + + abstract public void dummyMethod01(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass03/redefineclasses014b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass03/redefineclasses014b.java new file mode 100644 index 00000000000..30561f15e29 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014/newclass03/redefineclasses014b.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses014b is deugee's part of the redefineclasses014. + * deleting method declared as void dummyMethod03() + */ + +public interface redefineclasses014b { + + abstract public void dummyMethod01(); + + public void dummyMethod02(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014a.java new file mode 100644 index 00000000000..0354af09f7f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014a.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses014a is deugee's part of the redefineclasses014. + */ + +public class redefineclasses014a { + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("load_class")) { + // to force ClassPrepareEvent, change value of this field + redefineclasses014bc.classPrepare = true; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + +} + +abstract class redefineclasses014bc implements redefineclasses014b { + // to force ClassPrepareEvent, change value of this field + static boolean classPrepare; + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014b.java new file mode 100644 index 00000000000..7ac2493aba1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses014b.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses014b is deugee's part of the redefineclasses014. + */ + +public interface redefineclasses014b { + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015.java new file mode 100644 index 00000000000..9c1596b5e52 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015.java @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * attempting to change a method will throw UnsupportedOperationException + * exception"
    + * On debugee part there is an interface that has three method declarations:
    + * abstract public void dummyMethod01();
    + * public void dummyMethod02();
    + * void dummyMethod03();
    + * JLSS 9.4 says "...every method declaration in the body of an interface is + * implicitly abstract..." and "...every method declaration in the body + * of an interface is implicitly public..." + * The test tries to redefine this interface, manipulating modifiers of + * these methods, and expects UnsupportedOperationException will not be thrown. + * + * The test consists of the following files:
    + * redefineclasses015.java - debugger
    + * redefineclasses015a.java - initial debuggee
    + * newclassXX/redefineclasses015a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - deleting abstract modifier from + * abstract public void dummyMethod01()
    + * 2. newclass02 - deleting public modifier from + * abstract public void dummyMethod01()
    + * 3. newclass03 - deleting abstract,public modifiers from + * abstract public void dummyMethod01()
    + * 4. newclass04 - deleting public modifier from + * public void dummyMethod02()
    + * 5. newclass05 - adding abstract modifier to + * public void dummyMethod02()
    + * 6. newclass06 - adding abstract modifier to + * void dummyMethod03()
    + * 7. newclass07 - adding public modifier to + * void dummyMethod03()
    + * 8. newclass08 - adding abstract,public modifiers to + * void dummyMethod03()
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses015 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses015"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debuggerName + "b"; + + private final static String[][] subDirs = { + {"newclass01","deleting modifier from \"abstract public void dummyMethod01()\""}, + {"newclass02","deleting modifier from \"abstract public void dummyMethod01()\""}, + {"newclass03","deleting , modifiers from \"abstract public void dummyMethod01()\""}, + {"newclass04","deleting modifier from \"public void dummyMethod02()\""}, + {"newclass05","adding modifier to \"public void dummyMethod02()\""}, + {"newclass06","adding modifier to \"void dummyMethod03()\""}, + {"newclass07","adding modifier to \"void dummyMethod03()\""}, + {"newclass08","adding , modifiers to \"void dummyMethod03()\""} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses015b.class"; + + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses015 thisTest = new redefineclasses015(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + ClassPrepareRequest clpr = debugee.getEventRequestManager().createClassPrepareRequest(); + clpr.addClassFilter(testedClassName); + clpr.enable(); + + debugee.sendSignal("load_class"); + + ClassPrepareEvent clpEvent = waitClassPrepareEvent(clpr, waitTime); + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + display("REDEFINED"); + } catch (UnsupportedOperationException e) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private ClassPrepareEvent waitClassPrepareEvent(ClassPrepareRequest clpr, long waitTime) { + Event event; + display(">waiting class prepare event..."); + try { + event = debugee.waitingEvent(clpr, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof ClassPrepareEvent )) { + throw new TestBug("ClassPrepareEvent didn't arrive"); + } + + return (ClassPrepareEvent )event; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/TestDescription.java new file mode 100644 index 00000000000..d6d2b048b9f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/TestDescription.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, attempting to + * change a method will throw UnsupportedOperationException exception" + * On debugee part there is an interface that has three method declarations: + * abstract public void dummyMethod01(); + * public void dummyMethod02(); + * void dummyMethod03(); + * JLSS 9.4 says "...every method declaration in the body of an interface is + * implicitly abstract..." and "...every method declaration in the body + * of an interface is implicitly public..." + * The test tries to redefine this interface, manipulating modifiers of + * these methods, and expects UnsupportedOperationException will not be + * thrown. + * The test consists of the following files: + * redefineclasses015.java - debugger + * redefineclasses015a.java - debuggee + * redefineclasses015b.java - an initial redefined class + * newclassXX/redefineclasses015b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - deleting modifier from + * "abstract public void dummyMethod01()" + * 2. newclass02 - deleting modifier from + * "abstract public void dummyMethod01()" + * 3. newclass03 - deleting , modifiers from + * "abstract public void dummyMethod01()" + * 4. newclass04 - deleting modifier from + * "public void dummyMethod02()" + * 5. newclass05 - adding modifier to + * "public void dummyMethod02()" + * 6. newclass06 - adding modifier to "void dummyMethod03()" + * 7. newclass07 - adding modifier to "void dummyMethod03()" + * 8. newclass08 - adding , modifiers to + * "void dummyMethod03()" + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses015 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses015a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 newclass05 newclass06 newclass07 newclass08 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses015 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass01/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass01/redefineclasses015b.java new file mode 100644 index 00000000000..520cda12f0e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass01/redefineclasses015b.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + * deleting abstract modifier from + * abstract public void dummyMethod01() + */ + +public interface redefineclasses015b { + +// ======== + public void dummyMethod01(); +// ======== + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass02/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass02/redefineclasses015b.java new file mode 100644 index 00000000000..2b80ab4793b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass02/redefineclasses015b.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + * deleting public modifier from + * abstract public void dummyMethod01() + */ + +public interface redefineclasses015b { + +// ====== + abstract void dummyMethod01(); +// ====== + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass03/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass03/redefineclasses015b.java new file mode 100644 index 00000000000..c8bbf14d4db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass03/redefineclasses015b.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + * deleting abstract public modifiers from + * abstract public void dummyMethod01() + */ + +public interface redefineclasses015b { + +// =============== + void dummyMethod01(); +// =============== + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass04/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass04/redefineclasses015b.java new file mode 100644 index 00000000000..bc131ca901e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass04/redefineclasses015b.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + * deleting public modifier from + * public void dummyMethod02() + */ + +public interface redefineclasses015b { + + abstract public void dummyMethod01(); + +// ====== + void dummyMethod02(); +// ====== + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass05/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass05/redefineclasses015b.java new file mode 100644 index 00000000000..73b64ff0ddb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass05/redefineclasses015b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + * adding abstract modifier to + * public void dummyMethod02() + */ + +public interface redefineclasses015b { + + abstract public void dummyMethod01(); + +// ======== + abstract public void dummyMethod02(); +// ======== + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass06/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass06/redefineclasses015b.java new file mode 100644 index 00000000000..4af3c14b0bf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass06/redefineclasses015b.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + * adding abstract modifier to + * void dummyMethod03() + */ + +public interface redefineclasses015b { + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + +// ======== + abstract void dummyMethod03(); +// ======== +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass07/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass07/redefineclasses015b.java new file mode 100644 index 00000000000..ca147ed97c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass07/redefineclasses015b.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + * adding public modifier to + * void dummyMethod03() + */ + +public interface redefineclasses015b { + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + +// ====== + public void dummyMethod03(); +// ====== +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass08/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass08/redefineclasses015b.java new file mode 100644 index 00000000000..b12089bc764 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015/newclass08/redefineclasses015b.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + * adding abstract public modifiers to + * void dummyMethod03() + */ + +public interface redefineclasses015b { + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + +// =============== + abstract public void dummyMethod03(); +// =============== +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015a.java new file mode 100644 index 00000000000..70401212af0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015a.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015a is deugee's part of the redefineclasses015. + */ + +public class redefineclasses015a { + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("load_class")) { + // to force ClassPrepareEvent, change value of this field + redefineclasses015bc.classPrepare = true; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + +} + +abstract class redefineclasses015bc implements redefineclasses015b { + // to force ClassPrepareEvent, change value of this field + static boolean classPrepare; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015b.java new file mode 100644 index 00000000000..30fed7870af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses015b.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses015b is deugee's part of the redefineclasses015. + */ + +public interface redefineclasses015b { + + abstract public void dummyMethod01(); + + public void dummyMethod02(); + + void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016.java new file mode 100644 index 00000000000..caf6ec689e8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false, + * changing the schema(the fields) will throw UnsupportedOperationException + * exception" + * On debugee part there is an interface that has three method declarations:
    + * static public final Object field001
    + * public final Object field002
    + * final Object field003
    + * Object field004
    + * JLSS 9.3 says "...every field declaration in the body of an interface is implicitly + * public, static and final..." + * The test tries to redefine this interface, manipulating modifiers of + * these fields, and expects UnsupportedOperationException will not be thrown. + * + * The test consists of the following files:
    + * redefineclasses016.java - debugger
    + * redefineclasses016a.java - initial debuggee
    + * newclassXX/redefineclasses016a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - removing static modifiers
    + * 2. newclass02 - adding static modifiers
    + * 3. newclass03 - removing final modifiers
    + * 4. newclass04 - adding final modifiers
    + * 5. newclass05 - removing public modifiers
    + * 6. newclass06 - adding public modifiers
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses016 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses016"; + private final static String debugeeName = debuggerName + "a"; + private final static String testedClassName = debuggerName + "b"; + + private final static String[][] subDirs = { + {"newclass01","removing modifiers"}, + {"newclass02","adding modifiers"}, + {"newclass03","removing modifiers"}, + {"newclass04","adding modifiers"}, + {"newclass05","removing modifiers"}, + {"newclass06","adding modifiers"} + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses016b.class"; + + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String testDir; + private static String statDebugee; + + private ReferenceType debugeeClass, testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses016 thisTest = new redefineclasses016(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + debugeeClass = debugee.classByName(debugeeName); + testedClass = debugee.classByName(testedClassName); + display("Tested class\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } + performCases(); + + debugee.resume(); + + thrd = debugee.threadByName("main"); + if (!thrd.isSuspended()) { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + display("REDEFINED"); + } catch (UnsupportedOperationException e) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/TestDescription.java new file mode 100644 index 00000000000..6453a11f90c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/TestDescription.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, + * changing the schema(the fields) will throw UnsupportedOperationException + * exception" + * On debugee part there is an interface that has three method declarations: + * static public final Object field001 + * public final Object field002 + * final Object field003 + * Object field004 + * JLSS 9.3 says "...every field declaration in the body of an interface is + * implicitly public, static and final..." + * The test tries to redefine this interface, manipulating modifiers of + * these fields, and expects UnsupportedOperationException will not be thrown. + * The test consists of the following files: + * redefineclasses016.java - debugger + * redefineclasses016a.java - debuggee + * redefineclasses016b.java - an initial redefined class + * newclassXX/redefineclasses016b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - removing modifiers + * 2. newclass02 - adding modifiers + * 3. newclass03 - removing modifiers + * 4. newclass04 - adding modifiers + * 5. newclass05 - removing modifiers + * 6. newclass06 - adding modifiers + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is considered as passed and + * completes it's execution. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses016 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses016a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 newclass05 newclass06 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses016 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass01/redefineclasses016b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass01/redefineclasses016b.java new file mode 100644 index 00000000000..f431d617b37 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass01/redefineclasses016b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses016b is deugee's part of the redefineclasses016. + * removing modifiers + */ + +public interface redefineclasses016b { + + //preexisting fields +// ====== + public final Object field001 = null; +// ====== + public final Object field002 = null; + final Object field003 = null; + Object field004 = null; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass02/redefineclasses016b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass02/redefineclasses016b.java new file mode 100644 index 00000000000..38aab5feff3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass02/redefineclasses016b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses016b is deugee's part of the redefineclasses016. + * adding modifiers + */ + +public interface redefineclasses016b { + + //preexisting fields + static public final Object field001 = null; +// ====== + static public final Object field002 = null; + static final Object field003 = null; + static Object field004 = null; +// ====== +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass03/redefineclasses016b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass03/redefineclasses016b.java new file mode 100644 index 00000000000..ae1405654be --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass03/redefineclasses016b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses016b is deugee's part of the redefineclasses016. + * removing modifiers + */ + +public interface redefineclasses016b { + + //preexisting fields +// ===== + static public Object field001 = null; + public Object field002 = null; + Object field003 = null; +// ===== + Object field004 = null; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass04/redefineclasses016b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass04/redefineclasses016b.java new file mode 100644 index 00000000000..e5d220964ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass04/redefineclasses016b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses016b is deugee's part of the redefineclasses016. + * adding modifier to fields + */ + +public interface redefineclasses016b { + + //preexisting fields + static public final Object field001 = null; + public final Object field002 = null; + final Object field003 = null; +// ===== + final Object field004 = null; +// ===== +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass05/redefineclasses016b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass05/redefineclasses016b.java new file mode 100644 index 00000000000..cff3890c395 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass05/redefineclasses016b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses016b is deugee's part of the redefineclasses016. + * removing modifiers + */ + +public interface redefineclasses016b { + + //preexisting fields +// ====== + static final Object field001 = null; + final Object field002 = null; +// ====== + final Object field003 = null; + Object field004 = null; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass06/redefineclasses016b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass06/redefineclasses016b.java new file mode 100644 index 00000000000..d777596860c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016/newclass06/redefineclasses016b.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses016b is deugee's part of the redefineclasses016. + * adding modifiers + */ + +public interface redefineclasses016b { + + //preexisting fields + static public final Object field001 = null; + public final Object field002 = null; +// ====== + public final Object field003 = null; + public Object field004 = null; +// ====== +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016a.java new file mode 100644 index 00000000000..01ee7bc00b1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016a.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses016a is deugee's part of the redefineclasses016. + */ + +public class redefineclasses016a { + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + redefineclasses016bc obj = new redefineclasses016bc(); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} + +class redefineclasses016bc implements redefineclasses016b { +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016b.java new file mode 100644 index 00000000000..c53dc94871a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses016b.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses016b is deugee's part of the redefineclasses016. + */ + +public interface redefineclasses016b { + + //preexisting fields + static public final Object field001 = null; + public final Object field002 = null; + final Object field003 = null; + Object field004 = null; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020.java new file mode 100644 index 00000000000..a4f0eefbe2a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false attempting + * to add a class modifiers will throw UnsupportedOperationException + * exception." + * + * The test consists of the following files:
    + * redefineclasses020.java - debugger
    + * redefineclasses020a.java - initial debuggee
    + * newclassXX/redefineclasses020a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - adding class modifier
    + * 2. newclass02 - adding class modifier
    + * 3. newclass03 - adding class modifier
    + * 4. newclass04 - adding class modifier
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses020 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses020"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b$redefineclasses020ib"; + + private final static String[][] subDirs = { + {"newclass01","adding class-modifier"}, + {"newclass02","adding class-modifier"}, + {"newclass03","adding class-modifier"}, + {"newclass04","adding class-modifier"} + }; + + private final static String newClassFile = File.separator + + testedClassName.replace('.',File.separatorChar) + + ".class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String testDir; + private static String statDebugee; + + private ReferenceType debugeeClass, testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses020 thisTest = new redefineclasses020(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + debugeeClass = debugee.classByName(debugeeName); + testedClass = debugee.classByName(testedClassName); + display("Tested class\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + displayVMStatus(); + performCases(); + + debugee.resume(); + + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/TestDescription.java new file mode 100644 index 00000000000..fc6c32771dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, adding class + * modifiers will throw UnsupportedOperationException exception" + * The test consists of the following files: + * redefineclasses020.java - debugger + * redefineclasses020a.java - debuggee + * redefineclasses020b.java - an initial redefined class + * newclassXX/redefineclasses020b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - adding class modifier + * 2. newclass02 - adding class modifier + * 3. newclass03 - adding class modifier + * 4. newclass04 - adding class-modifier + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses020 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses020a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses020 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass01/redefineclasses020b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass01/redefineclasses020b.java new file mode 100644 index 00000000000..c9d04663491 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass01/redefineclasses020b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses020b is deugee's part of the redefineclasses020. + * adding class modifier + */ + +public class redefineclasses020b { + + Object obj = new redefineclasses020ib(); + + public class redefineclasses020ib { +// ^^^^^^ + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass02/redefineclasses020b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass02/redefineclasses020b.java new file mode 100644 index 00000000000..1dc53a9f744 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass02/redefineclasses020b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses020b is deugee's part of the redefineclasses020. + * adding class modifier + */ + +public class redefineclasses020b { + + Object obj = new redefineclasses020ib(); + + protected class redefineclasses020ib { +// ^^^^^^^^^ + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass03/redefineclasses020b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass03/redefineclasses020b.java new file mode 100644 index 00000000000..080bf6c0551 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass03/redefineclasses020b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses020b is deugee's part of the redefineclasses020. + * adding class modifier + */ + +public class redefineclasses020b { + + Object obj = new redefineclasses020ib(); + + private class redefineclasses020ib { +// ^^^^^^^ + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass04/redefineclasses020b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass04/redefineclasses020b.java new file mode 100644 index 00000000000..cf5ef55b3cb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020/newclass04/redefineclasses020b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses020b is deugee's part of the redefineclasses020. + * adding class modifier + */ + +public class redefineclasses020b { + + Object obj = new redefineclasses020ib(); + + static class redefineclasses020ib { +// ^^^^^^ + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020a.java new file mode 100644 index 00000000000..6138f6273f7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020a.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses020a is deugee's part of the redefineclasses020. + */ +public class redefineclasses020a { + + private static Log log; + + static redefineclasses020b obj = new redefineclasses020b(); + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020b.java new file mode 100644 index 00000000000..ad06c4f97a5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses020b.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses020b is deugee's part of the redefineclasses020. + */ + +public class redefineclasses020b { + + Object obj = new redefineclasses020ib(); + + class redefineclasses020ib { + + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021.java new file mode 100644 index 00000000000..2a963de200b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021.java @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false attempting + * to add a interface modifiers will throw UnsupportedOperationException + * exception." + * + * The test consists of the following files:
    + * redefineclasses021.java - debugger
    + * redefineclasses021a.java - initial debuggee
    + * newclassXX/redefineclasses021a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - adding public interface-modifier
    + * 2. newclass02 - adding protected interface-modifier
    + * 3. newclass03 - adding private interface-modifier
    + * 4. newclass04 - adding static interface-modifier
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses021 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses021"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b$redefineclasses021bi"; + + private final static String[][] subDirs = { + {"newclass01","adding interface-modifier"}, + {"newclass02","adding interface-modifier"}, + {"newclass03","adding interface-modifier"}, + {"newclass04","adding interface-modifier"} + }; + + private final static String newClassFile = File.separator + + testedClassName.replace('.',File.separatorChar) + + ".class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses021 thisTest = new redefineclasses021(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Failure e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + debugee.VM().suspend(); + displayVMStatus(); + performCases(); + + debugee.resume(); + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (i < 3) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + } else { + display("!!!No exception is thrown!!! Member interfaces are always implicitly static"); + } + } catch (UnsupportedOperationException e) { + if (i == 3) { + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + exitStatus = Consts.TEST_FAILED; + } else { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java new file mode 100644 index 00000000000..eccdf2efbfc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021. + * VM Testbase keywords: [jpda, jdi, redefine, quarantine] + * VM Testbase comments: JDK-8065773 + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, adding interface + * modifiers will throw UnsupportedOperationException exception" + * The test consists of the following files: + * redefineclasses021.java - debugger + * redefineclasses021a.java - debuggee + * redefineclasses021b.java - an initial redefined class + * newclassXX/redefineclasses021b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - adding interface-modifier + * 2. newclass02 - adding interface-modifier + * 3. newclass03 - adding interface-modifier + * 4. newclass04 - adding interface-modifier + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * 10.17.2002 fix for #4764339 + * For the 4-th testcase UnsupportedOperationException should not be thrown. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses021 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses021a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses021 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass01/redefineclasses021b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass01/redefineclasses021b.java new file mode 100644 index 00000000000..76cc8cc73d3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass01/redefineclasses021b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses021b is deugee's part of the redefineclasses021. + * adding public modifier + */ + +public class redefineclasses021b { + + redefineclasses021bc obj = new redefineclasses021bc(); + + public interface redefineclasses021bi { +// ^^^^^^ + void dummyMethod01(); + + } + + class redefineclasses021bc implements redefineclasses021bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass02/redefineclasses021b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass02/redefineclasses021b.java new file mode 100644 index 00000000000..424a345494f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass02/redefineclasses021b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses021b is deugee's part of the redefineclasses021. + * adding protected modifier + */ + +public class redefineclasses021b { + + redefineclasses021bc obj = new redefineclasses021bc(); + + protected interface redefineclasses021bi { +// ^^^^^^^^^ + void dummyMethod01(); + + } + + class redefineclasses021bc implements redefineclasses021bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass03/redefineclasses021b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass03/redefineclasses021b.java new file mode 100644 index 00000000000..07d86dc1b8f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass03/redefineclasses021b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses021b is deugee's part of the redefineclasses021. + * adding private modifier + */ + +public class redefineclasses021b { + + redefineclasses021bc obj = new redefineclasses021bc(); + + private interface redefineclasses021bi { +// ^^^^^^^ + void dummyMethod01(); + + } + + class redefineclasses021bc implements redefineclasses021bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass04/redefineclasses021b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass04/redefineclasses021b.java new file mode 100644 index 00000000000..18a61272780 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/newclass04/redefineclasses021b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses021b is deugee's part of the redefineclasses021. + * adding static modifier + */ + +public class redefineclasses021b { + + redefineclasses021bc obj = new redefineclasses021bc(); + + static interface redefineclasses021bi { +// ^^^^^^ + void dummyMethod01(); + + } + + class redefineclasses021bc implements redefineclasses021bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021a.java new file mode 100644 index 00000000000..5001ab764b8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021a.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses021a is deugee's part of the redefineclasses021. + */ +public class redefineclasses021a { + + private static Log log; + + // to force ClassPrepareEvent, create instance + static redefineclasses021b obj = new redefineclasses021b(); + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021b.java new file mode 100644 index 00000000000..cdf22005bc5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses021b is deugee's part of the redefineclasses021. + */ + +public class redefineclasses021b { + + redefineclasses021bc obj = new redefineclasses021bc(); + + interface redefineclasses021bi { + + + void dummyMethod01(); + + } + + class redefineclasses021bc implements redefineclasses021bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022.java new file mode 100644 index 00000000000..4204945ac81 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false attempting + * to change a class modifiers will throw UnsupportedOperationException + * exception." + * + * The test consists of the following files:
    + * redefineclasses022.java - debugger
    + * redefineclasses022a.java - initial debuggee
    + * newclassXX/redefineclasses022a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - changing class-modifier to
    + * 2. newclass02 - changing class-modifier to
    + * 3. newclass03 - changing class-modifier to
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses022 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses022"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b$redefineclasses022ib"; + + private final static String[][] subDirs = { + {"newclass01","changing class-modifier to "}, + {"newclass02","changing class-modifier to "}, + {"newclass03","changing class-modifier to "} + }; + + private final static String newClassFile = File.separator + + testedClassName.replace('.',File.separatorChar) + + ".class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String testDir; + private static String statDebugee; + + private ReferenceType debugeeClass, testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses022 thisTest = new redefineclasses022(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugee.VM().suspend(); + debugeeClass = debugee.classByName(debugeeName); + testedClass = debugee.classByName(testedClassName); + display("Tested class\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + displayVMStatus(); + performCases(); + + debugee.resume(); + + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/TestDescription.java new file mode 100644 index 00000000000..4d9d4decae1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, changing class + * modifiers will throw UnsupportedOperationException exception" + * The test consists of the following files: + * redefineclasses022.java - debugger + * redefineclasses022a.java - debuggee + * redefineclasses022b.java - an initial redefined class + * newclassXX/redefineclasses022b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - changing class-modifier to + * 2. newclass02 - changing class-modifier to + * 3. newclass03 - changing class-modifier to + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses022 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses022a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses022 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass01/redefineclasses022b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass01/redefineclasses022b.java new file mode 100644 index 00000000000..7fc6ca15d41 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass01/redefineclasses022b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses022b is deugee's part of the redefineclasses022. + * changing class modifier to + */ + +public class redefineclasses022b { + + Object obj = new redefineclasses022ib(); + + protected class redefineclasses022ib { +// ^^^^^^^^^ + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass02/redefineclasses022b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass02/redefineclasses022b.java new file mode 100644 index 00000000000..33ad76beb26 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass02/redefineclasses022b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses022b is deugee's part of the redefineclasses022. + * changing class modifier to + */ + +public class redefineclasses022b { + + Object obj = new redefineclasses022ib(); + + private class redefineclasses022ib { +// ^^^^^^^ + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass03/redefineclasses022b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass03/redefineclasses022b.java new file mode 100644 index 00000000000..3f2ec5d8597 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022/newclass03/redefineclasses022b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses022b is deugee's part of the redefineclasses022. + * adding class modifier to + */ + +public class redefineclasses022b { + + Object obj = new redefineclasses022ib(); + + class redefineclasses022ib { +// ^^^^^^^^ + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022a.java new file mode 100644 index 00000000000..21b25d95fbc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022a.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses022a is deugee's part of the redefineclasses022. + */ +public class redefineclasses022a { + + private static Log log; + + static redefineclasses022b obj = new redefineclasses022b(); + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022b.java new file mode 100644 index 00000000000..6baf48bc54e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses022b.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses022b is deugee's part of the redefineclasses022. + */ + +public class redefineclasses022b { + + Object obj = new redefineclasses022ib(); + + public class redefineclasses022ib { + + + public void dummyMethod01(){ + } + + protected void dummyMethod02(){ + } + + private void dummyMethod03(){ + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023.java new file mode 100644 index 00000000000..ad2d9e10be3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false attempting + * to change a class modifiers will throw UnsupportedOperationException + * exception." + * + * The test consists of the following files:
    + * redefineclasses023.java - debugger
    + * redefineclasses023a.java - initial debuggee
    + * newclassXX/redefineclasses023a.java - redefining debuggees
    + * + * This test performs the following cases:
    + * 1. newclass01 - changing class-modifier to
    + * 2. newclass02 - changing class-modifier to
    + * 3. newclass03 - changing class-modifier to
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses023 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses023"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b$redefineclasses023bi"; + + private final static String[][] subDirs = { + {"newclass01","changing class-modifier to "}, + {"newclass02","changing class-modifier to "}, + {"newclass03","changing class-modifier to "} + }; + + private final static String newClassFile = File.separator + + testedClassName.replace('.',File.separatorChar) + + ".class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses023 thisTest = new redefineclasses023(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + debugee.VM().suspend(); + displayVMStatus(); + performCases(); + + debugee.resume(); + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java new file mode 100644 index 00000000000..ce9beebdc96 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023. + * VM Testbase keywords: [jpda, jdi, redefine, quarantine] + * VM Testbase comments: JDK-8065773 + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, changing class + * modifiers will throw UnsupportedOperationException exception" + * The test consists of the following files: + * redefineclasses023.java - debugger + * redefineclasses023a.java - debuggee + * redefineclasses023b.java - an initial redefined class + * newclassXX/redefineclasses023b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - changing class-modifier to + * 2. newclass02 - changing class-modifier to + * 3. newclass03 - changing class-modifier to + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses023 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses023a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses023 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass01/redefineclasses023b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass01/redefineclasses023b.java new file mode 100644 index 00000000000..29b2230ff09 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass01/redefineclasses023b.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses023b is deugee's part of the redefineclasses023. + * changing class-modifier to + */ + +public class redefineclasses023b { + + redefineclasses023bc obj = new redefineclasses023bc(); + + protected interface redefineclasses023bi { +// ^^^^^^^^^ + + void dummyMethod01(); + + } + + class redefineclasses023bc implements redefineclasses023bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass02/redefineclasses023b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass02/redefineclasses023b.java new file mode 100644 index 00000000000..f5e4ef6697a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass02/redefineclasses023b.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses023b is deugee's part of the redefineclasses023. + * changing class-modifier to + */ + +public class redefineclasses023b { + + redefineclasses023bc obj = new redefineclasses023bc(); + + private interface redefineclasses023bi { +// ^^^^^^^ + + void dummyMethod01(); + + } + + class redefineclasses023bc implements redefineclasses023bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass03/redefineclasses023b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass03/redefineclasses023b.java new file mode 100644 index 00000000000..ead162abd93 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/newclass03/redefineclasses023b.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses023b is deugee's part of the redefineclasses023. + * changing class-modifier to + */ + +public class redefineclasses023b { + + redefineclasses023bc obj = new redefineclasses023bc(); + + interface redefineclasses023bi { +// ^^^^^^ + + void dummyMethod01(); + + } + + class redefineclasses023bc implements redefineclasses023bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023a.java new file mode 100644 index 00000000000..eb2e0c63393 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023a.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses023a is deugee's part of the redefineclasses023. + */ +public class redefineclasses023a { + + private static Log log; + + // to force ClassPrepareEvent, create instance + static redefineclasses023b obj = new redefineclasses023b(); + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023b.java new file mode 100644 index 00000000000..a839510bf0b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses023b is deugee's part of the redefineclasses023. + */ + +public class redefineclasses023b { + + redefineclasses023bc obj = new redefineclasses023bc(); + + public interface redefineclasses023bi { + + + void dummyMethod01(); + + } + + class redefineclasses023bc implements redefineclasses023bi { + + public void dummyMethod01() { + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024.java new file mode 100644 index 00000000000..fad049736f1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024.java @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false attempting + * to change a a class hierarchy will throw UnsupportedOperationException + * exception." + * + * The test consists of the following files:
    + * redefineclasses024.java - debugger
    + * redefineclasses024a.java - debuggee
    + * redefineclasses024c.java - a subsidiary class
    + * redefineclasses024i.java - a subsidiary interface
    + * redefineclasses024b.java - an initial redefined class
    + * newclassXX/redefineclasses024b.java - redefining debuggee's class
    + * + * This test performs the following cases:
    + * 1. newclass01 - implements an interface
    + * 2. newclass02 - extends a class
    + * 3. newclass03 - extends a class, implements an interface
    + * 4. newclass04 - extends Object class
    + * The last case assumes the exception will not be thrown. + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses024 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses024"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b"; + + private final static String[][] subDirs = { + {"newclass01","implements an interface"}, + {"newclass02","extends a class"}, + {"newclass03","extends a class, implements an interface"}, + {"newclass04","extends Object"} + }; + + private final static String newClassFile = File.separator + + testedClassName.replace('.',File.separatorChar) + + ".class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses024 thisTest = new redefineclasses024(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + waitTime = argHandler.getWaitTime() * 60000; + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + ClassPrepareRequest clpr = debugee.getEventRequestManager().createClassPrepareRequest(); + clpr.addClassFilter(testedClassName); + clpr.enable(); + + debugee.sendSignal("load_class"); + + ClassPrepareEvent clpEvent = waitClassPrepareEvent(clpr, waitTime); + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + displayVMStatus(); + performCases(); + + debugee.resume(); + + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if ( i < 3 ) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } else { + display("REDEFINED"); + } + } catch (UnsupportedOperationException e) { + if ( i < 3 ) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private ClassPrepareEvent waitClassPrepareEvent(ClassPrepareRequest clpr, long waitTime) { + Event event; + display(">waiting class prepare event..."); + try { + event = debugee.waitingEvent(clpr, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof ClassPrepareEvent )) { + throw new TestBug("ClassPrepareEvent didn't arrive"); + } + + return (ClassPrepareEvent )event; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/TestDescription.java new file mode 100644 index 00000000000..67afbe6c624 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, changing a class + * hierarchy will throw UnsupportedOperationException exception" + * The test consists of the following files: + * redefineclasses024.java - debugger + * redefineclasses024a.java - debuggee + * redefineclasses024c.java - a subsidiary class + * redefineclasses024i.java - a subsidiary interface + * redefineclasses024b.java - an initial redefined class + * newclassXX/redefineclasses024b.java - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - implements an interface + * 2. newclass02 - extends a class + * 3. newclass03 - extends a class, implements an interface + * 4. newclass04 - extends Object class + * The last case assumes the exception will not be thrown. + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses024 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses024a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses024 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass01/redefineclasses024b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass01/redefineclasses024b.java new file mode 100644 index 00000000000..26467596ece --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass01/redefineclasses024b.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses024b is deugee's part of the redefineclasses024. + * implements an interface + */ + +class redefineclasses024b implements redefineclasses024i { +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + static boolean classPrepare = false; + + public void dummyMethod01() { + } +} + +interface redefineclasses024i { + + public void dummyMethod01(); +} + +class redefineclasses024c { + + public void dummyMethod01() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass02/redefineclasses024b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass02/redefineclasses024b.java new file mode 100644 index 00000000000..a82efd6ec03 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass02/redefineclasses024b.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses024b is deugee's part of the redefineclasses024. + * extends a class + */ + +class redefineclasses024b extends redefineclasses024c { +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + static boolean classPrepare = false; + + public void dummyMethod01() { + } +} + +interface redefineclasses024i { + + public void dummyMethod01(); +} + +class redefineclasses024c { + + public void dummyMethod01() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass03/redefineclasses024b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass03/redefineclasses024b.java new file mode 100644 index 00000000000..9a0e5e8c268 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass03/redefineclasses024b.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses024b is deugee's part of the redefineclasses024. + * extends a class implements an interface + */ + +class redefineclasses024b extends redefineclasses024c implements redefineclasses024i { + + static boolean classPrepare = false; + + public void dummyMethod01() { + } +} + +interface redefineclasses024i { + + public void dummyMethod01(); +} + +class redefineclasses024c { + + public void dummyMethod01() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass04/redefineclasses024b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass04/redefineclasses024b.java new file mode 100644 index 00000000000..a30d729a12b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024/newclass04/redefineclasses024b.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses024b is deugee's part of the redefineclasses024. + * extends Object + */ + +class redefineclasses024b extends Object { +// ^^^^^^^^^^^^^^ + static boolean classPrepare = false; + + public void dummyMethod01() { + } +} + +interface redefineclasses024i { + + public void dummyMethod01(); +} + +class redefineclasses024c { + + public void dummyMethod01() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024a.java new file mode 100644 index 00000000000..3fefa04fe5e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024a.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses024a is deugee's part of the redefineclasses024. + */ +public class redefineclasses024a { + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("load_class")) { + // to force ClassPrepareEvent, change value of this field + redefineclasses024b.classPrepare = true; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024b.java new file mode 100644 index 00000000000..84c8188eaa7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses024b.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses024b is deugee's part of the redefineclasses024. + */ + +class redefineclasses024b { + + static boolean classPrepare = false; + + public void dummyMethod01() { + } +} + +interface redefineclasses024i { + + public void dummyMethod01(); +} + +class redefineclasses024c { + + public void dummyMethod01() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025.java new file mode 100644 index 00000000000..ab78dc5d1a4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If canUnrestrictedlyRedefineClasses() is false attempting + * to change interface hierarchy will throw UnsupportedOperationException exception." + * + * The test consists of the following files:
    + * redefineclasses025.java - debugger
    + * redefineclasses025a.java - debuggee
    + * redefineclasses025b.java - an initial redefined interface
    + * newclassXX/redefineclasses025b.java - redefining debuggee's interface
    + * + * This test performs the following cases:
    + * 1. newclass01 - adding implemented interface
    + * 2. newclass02 - removing implemented interface
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses025 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses025"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b"; + + private final static String[][] subDirs = { + {"newclass01","adding extended interface"}, + {"newclass02","removing extended interface"} + }; + + private final static String newClassFile = File.separator + + testedClassName.replace('.',File.separatorChar) + + ".class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses025 thisTest = new redefineclasses025(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + waitTime = argHandler.getWaitTime() * 60000; + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + ClassPrepareRequest clpr = debugee.getEventRequestManager().createClassPrepareRequest(); + clpr.addClassFilter(testedClassName); + clpr.enable(); + + debugee.sendSignal("load_class"); + + ClassPrepareEvent clpEvent = waitClassPrepareEvent(clpr, waitTime); + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + displayVMStatus(); + performCases(); + + debugee.resume(); + + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedOperationException is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } catch (UnsupportedOperationException e) { + if (!debugee.VM().canUnrestrictedlyRedefineClasses()) { + display(EXPECTED_STRING + e); + } else { + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain(statDebugee + UNEXPECTED_STRING + + "UnsupportedOperationException"); + complain("***\twhile " + subDirs[i][1]); + } + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private ClassPrepareEvent waitClassPrepareEvent(ClassPrepareRequest clpr, long waitTime) { + Event event; + display(">waiting class prepare event..."); + try { + event = debugee.waitingEvent(clpr, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof ClassPrepareEvent )) { + throw new TestBug("ClassPrepareEvent didn't arrive"); + } + + return (ClassPrepareEvent )event; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/TestDescription.java new file mode 100644 index 00000000000..a5aed63222f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025. + * VM Testbase keywords: [jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If canUnrestrictedlyRedefineClasses() is false, changing interface + * hierarchy will throw UnsupportedOperationException exception" + * The test consists of the following files: + * redefineclasses025.java - debugger + * redefineclasses025a.java - debuggee + * redefineclasses025b.java - an initial redefined interface + * newclassXX/redefineclasses025b.java - redefining debuggee's interface + * This test performs the following cases: + * 1. newclass01 - adding extendeded interface + * 2. newclass02 - removing extendeded interface + * The test checks two different cases for suspended debugee and not + * suspended one. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses025 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses025a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses025 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/newclass01/redefineclasses025b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/newclass01/redefineclasses025b.java new file mode 100644 index 00000000000..529af4dc54b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/newclass01/redefineclasses025b.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses025b is deugee's part of the redefineclasses025. + */ + +interface redefineclasses025b extends redefineclasses025i, redefineclasses025j { +// ^^^^^^^^^^^^^^^^^^^^^^^^ + public void dummyMethod01(); +} + +interface redefineclasses025i { + + public void dummyMethod02(); +} + +interface redefineclasses025j { + + public void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/newclass02/redefineclasses025b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/newclass02/redefineclasses025b.java new file mode 100644 index 00000000000..7baf9bc6eff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025/newclass02/redefineclasses025b.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses025b is deugee's part of the redefineclasses025. + */ + +interface redefineclasses025b { +// ^^^ + public void dummyMethod01(); +} + +interface redefineclasses025i { + + public void dummyMethod02(); +} + +interface redefineclasses025j { + + public void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025a.java new file mode 100644 index 00000000000..02610173ec4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025a.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses025a is deugee's part of the redefineclasses025. + */ +public class redefineclasses025a { + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("load_class")) { + // to force ClassPrepareEvent, change value of this field + redefineclasses025c.classPrepare = true; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} + +abstract class redefineclasses025c implements redefineclasses025b { + static boolean classPrepare = false; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025b.java new file mode 100644 index 00000000000..f3250835429 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses025b.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses025b is deugee's part of the redefineclasses025. + */ + +interface redefineclasses025b extends redefineclasses025i { + + public void dummyMethod01(); +} + +interface redefineclasses025i { + + public void dummyMethod02(); +} + +interface redefineclasses025j { + + public void dummyMethod03(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026.java new file mode 100644 index 00000000000..3eee2a7b9ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If the bytes don't correspond to the reference type (the names don't match) + * NoClassDefFoundError will be thrown." + * + * The test consists of the following files:
    + * redefineclasses026.java - debugger
    + * redefineclasses026a.java - debuggee
    + * redefineclasses026c.java - an initial class
    + * newclass/redefineclasses026c.java - redefining class
    + * + * This test attepmts to redefine class with wrong classname. + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses026 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses026"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "c"; + + private final static String newClassFile = "newclass" + File.separator + + testedClassName.replace('.',File.separatorChar) + + "_otherName.class"; + + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses026 thisTest = new redefineclasses026(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + waitTime = argHandler.getWaitTime() * 60000; + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + debugee.VM().suspend(); + + displayVMStatus(); + performCases(); + + debugee.resume(); + + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + mapBytes = mapClassToBytes(testDir + File.separator + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + exitStatus = Consts.TEST_FAILED; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + complain("***NoClassDefFoundError is not thrown"); + + } catch (NoClassDefFoundError e) { + display(EXPECTED_STRING + e); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/TestDescription.java new file mode 100644 index 00000000000..5e764cf35c9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/TestDescription.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If the bytes don't correspond to the reference type (the names + * don't match) NoClassDefFoundError will be thrown." + * The test consists of the following files: + * redefineclasses026.java - debugger + * redefineclasses026a.java - debuggee + * redefineclasses026c.java - an initial class + * newclass/redefineclasses026c.java - redefining class + * This test attepmts to redefine class with wrong classname. + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses026 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses026a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses026 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/newclass/redefineclasses026c_otherName.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/newclass/redefineclasses026c_otherName.java new file mode 100644 index 00000000000..50971e71bc3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026/newclass/redefineclasses026c_otherName.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses026c is deugee's part of the redefineclasses026. + */ + +public class redefineclasses026c_otherName { +// ^^^^^^^^^^ + public void dummyMethod01() { + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026a.java new file mode 100644 index 00000000000..c95cbf78c1f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026a.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses026a is deugee's part of the redefineclasses026. + */ +public class redefineclasses026a { + + private static Log log; + + static redefineclasses026c obj = new redefineclasses026c(); + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026c.java new file mode 100644 index 00000000000..3bc614b93c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses026c.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses026c is deugee's part of the redefineclasses026. + */ + +public class redefineclasses026c { + + public void dummyMethod01() { + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027.java new file mode 100644 index 00000000000..654ec5bd5f1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If the major and minor version numbers in bytes are not supported by the VM + * UnsupportedClassVersionError will be thrown." + * + * The test consists of the following files:
    + * redefineclasses027.java - debugger
    + * redefineclasses027a.java - debuggee
    + * redefineclasses027c.java - tested class
    + * redefineclasses027i.java - tested interface
    + * + * This test corrupts byte-code of the version number and tries to redefine + * the tested classes. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses027 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses027"; + private final static String debugeeName = debuggerName + "a"; + + public final static String [] testedClassNames = { + debuggerName + "c", + debuggerName + "i" + }; + + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses027 thisTest = new redefineclasses027(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + waitTime = argHandler.getWaitTime() * 60000; + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + ClassPrepareRequest clpr = debugee.getEventRequestManager().createClassPrepareRequest(); + clpr.addClassFilter(debuggerName + "*"); + // #4736633 is fixed + clpr.addClassExclusionFilter(debuggerName + "ic"); + clpr.enable(); + + debugee.sendSignal("load_class"); + + ClassPrepareEvent clpEvent = waitClassPrepareEvent(clpr, waitTime); + display(typePrompt(testedClass) + ":\t" + clpEvent.referenceType().name()); + debugee.resume(); + + clpEvent = waitClassPrepareEvent(clpr, waitTime); + display(typePrompt(testedClass) + ":\t" + clpEvent.referenceType().name()); + + + display("\nTEST BEGINS"); + display("==========="); + + displayVMStatus(); + performCases(); + + debugee.resume(); + + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + + String oldClassFile; + for (int i = 0; i < testedClassNames.length; i++) { + testedClass = debugee.classByName(testedClassNames[i]); + display(typePrompt(testedClass) + ":\t" + testedClass.name()); + + oldClassFile = ClassFileFinder.findClassFile(testedClassNames[i], Utils.TEST_CLASS_PATH).toString(); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***UnsupportedClassVersionError is not thrown"); + } catch (UnsupportedClassVersionError e) { + display(EXPECTED_STRING + e); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + display(""); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file:\t" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + + // corrupting major and minor version numbers of class file structure + display("actual version number: \t" + + getValue(arrayToRedefine[6], arrayToRedefine[7]) + + "." + + getValue(arrayToRedefine[4], arrayToRedefine[5])); + arrayToRedefine[4] = (byte )0xF; + arrayToRedefine[5] = arrayToRedefine[4]; + arrayToRedefine[6] = arrayToRedefine[4]; + arrayToRedefine[7] = arrayToRedefine[4]; + display("corrupted version number:\t" + + getValue(arrayToRedefine[6], arrayToRedefine[7]) + + "." + + getValue(arrayToRedefine[4], arrayToRedefine[5])); + + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + int getValue(byte b1, byte b2) { + int val = b1 * 0x100 + b2; + return val; + } + + private ClassPrepareEvent waitClassPrepareEvent(ClassPrepareRequest clpr, long waitTime) { + Event event; + display(">waiting class prepare event..."); + try { + event = debugee.waitingEvent(clpr, waitTime); + } catch (InterruptedException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + if (!(event instanceof ClassPrepareEvent )) { + throw new TestBug("ClassPrepareEvent didn't arrive"); + } + + return (ClassPrepareEvent )event; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027/TestDescription.java new file mode 100644 index 00000000000..6efdef033ab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If the major and minor version numbers in bytes are not supported + * by the VM, UnsupportedClassVersionError will be thrown." + * The test consists of the following files: + * redefineclasses027.java - debugger + * redefineclasses027a.java - debuggee + * redefineclasses027c.java - tested class + * redefineclasses027i.java - tested interface + * This test corrupts byte-code of the version number and tries to redefine + * the tested classes. When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + * COMMENTS: + * #4736633 is fixed + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses027 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses027a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses027 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027a.java new file mode 100644 index 00000000000..d0e0e1fbed6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027a.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses027a is deugee's part of the redefineclasses027. + */ +public class redefineclasses027a { + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("load_class")) { + // to force ClassPrepareEvent, create instance + redefineclasses027c obj = new redefineclasses027c(); + redefineclasses027ic.classPrepare = true; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} + +abstract class redefineclasses027ic implements redefineclasses027i { + static boolean classPrepare = false; +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027c.java new file mode 100644 index 00000000000..6ab0013263f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027c.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses027c is deugee's part of the redefineclasses027. + */ + +public class redefineclasses027c { + + public void dummyMethod01() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027i.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027i.java new file mode 100644 index 00000000000..42f5b85a9dc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses027i.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses027i is deugee's part of the redefineclasses027. + */ + +interface redefineclasses027i { + + public void dummyMethod01(); +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028.java new file mode 100644 index 00000000000..7b9e39c7d4d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If the bytes do not represent a valid class, ClassFormatError + * will be thrown." + * + * The test consists of the following files:
    + * redefineclasses028.java - debugger
    + * redefineclasses028a.java - debuggee
    + * redefineclasses028b.java - initial class
    + * + * This test reads redefineclasses028b class-file and corrupts it. Then tries + * to redefine the redefineclasses028b class using the corrupted byte-code. + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses028 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses028"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b"; + + private final static String newClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses028 thisTest = new redefineclasses028(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + debugee.VM().suspend(); + + displayVMStatus(); + performCases(); + + debugee.resume(); + + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + exitStatus = Consts.TEST_FAILED; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + complain("***ClassFormatError is not thrown"); + } catch (ClassFormatError e) { + display(EXPECTED_STRING + e); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + // corrupting bytes + for (int i = 8; i < fileToRedefineLength; i++) { + arrayToRedefine[i] = (byte )i; + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028/TestDescription.java new file mode 100644 index 00000000000..e7cc7f7a67b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If the bytes do not represent a valid class, ClassFormatError + * will be thrown." + * The test consists of the following files: + * redefineclasses028.java - debugger + * redefineclasses028a.java - debuggee + * redefineclasses028b.java - initial class + * This test reads redefineclasses028b class-file and corrupts it. + * Then tries to redefine the redefineclasses028b class using the + * corrupted byte-code. + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is considered as passed + * and completes it's execution. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses028 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses028a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses028 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028a.java new file mode 100644 index 00000000000..35e1a97cc97 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028a.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses028a is deugee's part of the redefineclasses028. + */ +public class redefineclasses028a { + + private static Log log; + + static redefineclasses028b obj = new redefineclasses028b(); + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028b.java new file mode 100644 index 00000000000..f235285c02d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses028b.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses028b is deugee's part of the redefineclasses028. + */ + +class redefineclasses028b { + + public void dummyMethod01() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029.java new file mode 100644 index 00000000000..469d2d5304d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If the bytes do not represent a valid class, ClassFormatError + * will be thrown." + * + * The test consists of the following files:
    + * redefineclasses029.java - debugger
    + * redefineclasses029a.java - initial debuggee
    + * + * This test creates byte code, that has zero-length, and tries it + * to redefine the debugee. The test expects ClassFormatError exception. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses029 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses029"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses029 thisTest = new redefineclasses029(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + testedClass = debugee.classByName(debugeeName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + HashMap mapBytes = new HashMap(); + display(">attempting to redefine a class by \"empty\" class-file..."); + mapBytes.put(testedClass, new byte[0]); + try { + debugee.VM().redefineClasses(mapBytes); + exitStatus = Consts.TEST_FAILED; + complain("***ClassFormatError is not thrown"); + } catch (ClassFormatError e) { + display(EXPECTED_STRING + e); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + complain(UNEXPECTED_STRING + e); + e.printStackTrace(); + } + debugee.resume(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029/TestDescription.java new file mode 100644 index 00000000000..df21af79743 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If the bytes do not represent a valid class, ClassFormatError + * will be thrown." + * The test consists of the following files: + * redefineclasses029.java - debugger + * redefineclasses029a.java - initial debuggee + * This test creates byte code, that has zero-length, and tries it + * to redefine the debugee. The test expects ClassFormatError exception. + * When canRedefineClasses() is false, the test is considered as passed + * and completes it's execution. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses029 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses029a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses029 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029a.java new file mode 100644 index 00000000000..629395ed212 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses029a.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses029a is deugee's part of the redefineclasses029. + */ +public class redefineclasses029a { + + private static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030.java new file mode 100644 index 00000000000..efa6ba4db79 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import jdk.test.lib.Utils; +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion:
    + * "If a "verifier" detects that a class, though well formed, contains an internal + * inconsistency or security problem, VerifyError will be thrown." + * + * The test consists of the following files:
    + * redefineclasses030.java - debugger
    + * redefineclasses030a.java - debuggee
    + * redefineclasses030b.java - an initial redefined class
    + * newclassXX/redefineclasses030b.jasm - redefining debuggee's class
    + * + * This test performs the following cases:
    + * 1. newclass01 - reducing stack size
    + * 2. newclass02 - pushing a local variable with wrong index
    + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses030 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses030"; + private final static String debugeeName = debuggerName + "a"; + public final static String testedClassName = debuggerName + "b"; + + private final static String[][] subDirs = { + {"newclass01","reducing stack size"}, + {"newclass02","pushing a local variable with wrong index"} + }; + + private final static String classFileName = + testedClassName.replace('.',File.separatorChar) + + ".class"; + private final static String oldClassFile + = ClassFileFinder.findClassFile(testedClassName, Utils.TEST_CLASS_PATH) + .toString(); + + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static String testDir; + private static String statDebugee; + + private ReferenceType testedClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses030 thisTest = new redefineclasses030(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (TestBug e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } catch (Exception e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws TestBug { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + testedClass = debugee.classByName(testedClassName); + display(typePrompt(testedClass) + "\t:" + testedClass.name()); + + display("\nTEST BEGINS"); + display("==========="); + + debugee.VM().suspend(); + + displayVMStatus(); + performCases(); + + debugee.resume(); + + displayVMStatus(); + performCases(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void performCases() { + Map mapBytes; + boolean alreadyComplained = false; + for (int i = 0; i < subDirs.length; i++) { + display("\n" + subDirs[i][1] + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + subDirs [i][0] + File.separator + classFileName); + try { + debugee.VM().redefineClasses(mapBytes); + exitStatus = Consts.TEST_FAILED; + if (!alreadyComplained) { + alreadyComplained = true; + complain("***" + dashes); + complain("***" + statDebugee); + complain("***" + dashes); + } + complain("***VerifyError is not thrown"); + complain("***\twhile " + subDirs[i][1]); + + display(">return to the previous state..."); + mapBytes = mapClassToBytes(oldClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } catch (VerifyError e) { + display(EXPECTED_STRING + e); + } catch (Exception e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new TestBug(UNEXPECTED_STRING + e); + } + + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private String typePrompt(ReferenceType refType) { + String msg = "Tested "; + if (refType instanceof InterfaceType) { + msg += "interface"; + } else if (refType instanceof ClassType) { + msg += "class"; + } else { + msg += "type"; + } + return msg; + } + + void displayVMStatus() { + ThreadReference thrd = debugee.threadByName("main"); + if (thrd.isSuspended()) { + statDebugee = "Debugee is suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display(dashes); + } else { + statDebugee = "Debugee is not suspended"; + display("\n\n<<<" + statDebugee + ">>>"); + display("------------------------------"); + } + } + + public static String toHexString(long b, int length) { + return Right(Long.toHexString(b), length).replace(' ', '0').toUpperCase(); + } + + private static String Right(String source, int length) { + + if (length <= 0) + return ""; + + if (length <= source.length()) + return source.substring(source.length() - length, source.length()); + else + return PadL(source, length); + } + + private static String PadL(String source, int length, String what) { + + if (length <= 0) + return ""; + + if (source.length() > length) + return PadL("", length, "*"); + + while (source.length() < length) + source = what + source; + + return source; + } + + + private static String PadL(String source, int length) { + return PadL(source, length, " "); + } + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/TestDescription.java new file mode 100644 index 00000000000..8ffcc43a185 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test against the method com.sun.jdi.VirtualMachine.redefineClasses() + * and checks up the following assertion: + * "If a "verifier" detects that a class, though well formed, contains + * an internal inconsistency or security problem, VerifyError will be + * thrown." + * The test consists of the following files: + * redefineclasses030.java - debugger + * redefineclasses030a.java - debuggee + * redefineclasses030b.java - an initial redefined class + * newclassXX/redefineclasses030b.jasm - redefining debuggee's class + * This test performs the following cases: + * 1. newclass01 - reducing stack size + * 2. newclass02 - pushing a local variable with wrong index + * The test checks two different cases for suspended debugee and not + * suspended one. + * When canRedefineClasses() is false, the test is considered as passed + * and completes it's execution. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * + * @comment compile newclassXX/*.jasm to bin/newclassXX and make sure the classes + * aren't in test.class.path + * @compile newclass01/redefineclasses030b.jasm + * @run driver + * nsk.jdi.ExtraClassesInstaller + * newclass01 nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030b.class + * @clean nsk.jdi.VirtualMachine.redefineClasses.redefineclasses030b + * @compile newclass02/redefineclasses030b.jasm + * @run driver + * nsk.jdi.ExtraClassesInstaller + * newclass02 nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030b.class + * @clean nsk.jdi.VirtualMachine.redefineClasses.redefineclasses030b + * + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses030 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses030a + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses030 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/newclass01/redefineclasses030b.jasm b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/newclass01/redefineclasses030b.jasm new file mode 100644 index 00000000000..c5d0a2391c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/newclass01/redefineclasses030b.jasm @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk/jdi/VirtualMachine/redefineClasses; + +super class redefineclasses030b +{ + +Field Value:I; + +Method "":"()V" +//------------------------------- +//-----> test substitution <----- +//------------------------------- +// stack 1 locals 1 + stack 0 locals 1 // instead of the previous line +//------------------------------- +//------------------------------- +{ +// null + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public Method dummyMethod01:"()V" + stack 0 locals 1 +{ +// null + return; +} + +} // end Class redefineclasses030b diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/newclass02/redefineclasses030b.jasm b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/newclass02/redefineclasses030b.jasm new file mode 100644 index 00000000000..4c19491644b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030/newclass02/redefineclasses030b.jasm @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk/jdi/VirtualMachine/redefineClasses; + +super class redefineclasses030b +{ + +Field Value:I; + +Method "":"()V" + stack 1 locals 1 +{ +// null +//------------------------------- +//-----> test substitution <----- +//------------------------------- +// aload_0; + aload_1; // instead of the previous line +//------------------------------- +//------------------------------- + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public Method dummyMethod01:"()V" + stack 0 locals 1 +{ +// null + return; +} + +} // end Class redefineclasses030b diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030a.java new file mode 100644 index 00000000000..6d0da69d6a0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030a.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses030a is deugee's part of the redefineclasses030. + */ +public class redefineclasses030a { + + private static Log log; + + static redefineclasses030b obj = new redefineclasses030b(); + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr = pipe.readln(); + if (instr.equals("quit")) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030b.java new file mode 100644 index 00000000000..dfee6d99eab --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030b.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses030b is deugee's part of the redefineclasses030. + * to generate jasm-file: + * java -cp javasoft.sqe.jdis.Main -sl nsk/jdi/VirtualMachine/redefineClasses/redefineclasses030b.class > redefineclasses030b.jasm + */ + +class redefineclasses030b { + + int Value; + + public void dummyMethod01() { + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031.java new file mode 100644 index 00000000000..7a98229d5ad --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test checks up com.sun.jdi.VirtualMachine.redefineClasses(). + * In for loop the test sets breakpoint and tries to redefines debugee's + * method by changing value of debugee's field. After resuming debugee, + * the test checks if a tested field contains correct value. + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses031 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + public final static String EXPECTED_STRING = "!!!Expected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses031"; + private final static String debugeeName = debuggerName + "a"; + private final static String Name = debuggerName + "b"; + + public final static String PREPARE_SGL = "prepare"; + public final static String PERFORM_SGL = "perform"; + public final static String QUIT_SGL = "quit"; + public final static String READY_SGL = "ready"; + + private final static String[] subDirs = { + "newclass01", + "newclass02", + "newclass03", + "newclass04", + "newclass05" + }; + + private final static String newClassFile = File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses031a.class"; + private static final String dashes = "--------------------------"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + private static String statDebugee; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses031 thisTest = new redefineclasses031(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Failure e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + debugee.VM().suspend(); + debugee.sendSignal(PERFORM_SGL); + + display("Tested class\t:" + debugeeClass.name()); + + ThreadReference thrd = debugee.threadByName("main"); + + StepRequest sreq; + BreakpointRequest brkp; + Field testedField; + PrimitiveValue val; + + for (int i = 0; i < subDirs.length; i++) { + brkp = debugee.setBreakpoint(debugeeClass, + redefineclasses031a.brkpMethodName, + redefineclasses031a.brkpLineNumber); + debugee.resume(); + + waitBreakpointEvent(brkp, waitTime); + + redefineDebugee(subDirs[i]); + + sreq = debugee.getEventRequestManager().createStepRequest(thrd, + StepRequest.STEP_LINE, + StepRequest.STEP_OVER); + sreq.enable(); + debugee.resume(); + + waitStepEvent(sreq, waitTime); + + testedField = debugeeClass.fieldByName("testedField"); + val = (PrimitiveValue )debugeeClass.getValue(testedField); + if (val.intValue() != redefineclasses031a.NEW_VALUES[i]) { + exitStatus = Consts.TEST_FAILED; + complain("actual value = " + val.intValue() + + ", expected " + redefineclasses031a.NEW_VALUES[i]); + } else { + display("actual value = " + val.intValue() + + ", expected " + redefineclasses031a.NEW_VALUES[i]); + } + + debugee.getEventRequestManager().deleteEventRequest(sreq); + } + debugee.resume(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee(String newClassDir) { + Map mapBytes; + boolean alreadyComplained = false; + display("\n" + newClassDir + ">>>"); + mapBytes = mapClassToBytes(testDir + File.separator + newClassDir + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new Failure("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } + + private StepEvent waitStepEvent(StepRequest brkp, long waitTime) { + Event event; + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + if (!(event instanceof StepEvent )) { + throw new Failure("StepEvent didn't arrive"); + } + + return (StepEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/TestDescription.java new file mode 100644 index 00000000000..1dacd22efca --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/TestDescription.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031. + * VM Testbase keywords: [jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up com.sun.jdi.VirtualMachine.redefineClasses(). + * In for loop the test sets breakpoint and tries to redefines debugee's + * method by changing value of debugee's field. After resuming + * debugee, the test checks if a tested field contains correct + * value. + * COMMENTS + * This is a regression test on the following bug: + * 4724076 Redefine does not work in for/while loop + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses031 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses031a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass01 newclass02 newclass03 newclass04 newclass05 + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses031 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass01/redefineclasses031a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass01/redefineclasses031a.java new file mode 100644 index 00000000000..981d20b42ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass01/redefineclasses031a.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses031a is deugee's part of the redefineclasses031. + */ +public class redefineclasses031a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 78; + + static final int [] NEW_VALUES = { + 1, 2, 3, 4, 5 + }; + + static int testedField = 0; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + performTest(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static public void doSomething() { + + testedField = NEW_VALUES[0]; +// ^^^ will be changed + } + + static void performTest() { + // invoking of redefined method + for(int i = 0; i < NEW_VALUES.length; i++) { + // brkpLineNumber + doSomething(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass02/redefineclasses031a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass02/redefineclasses031a.java new file mode 100644 index 00000000000..55a93d492aa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass02/redefineclasses031a.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses031a is deugee's part of the redefineclasses031. + */ +public class redefineclasses031a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 78; + + static final int [] NEW_VALUES = { + 1, 2, 3, 4, 5 + }; + + static int testedField = 0; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + performTest(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static public void doSomething() { + + testedField = NEW_VALUES[1]; +// ^^^ will be changed + } + + static void performTest() { + // invoking of redefined method + for(int i = 0; i < NEW_VALUES.length; i++) { + // brkpLineNumber + doSomething(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass03/redefineclasses031a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass03/redefineclasses031a.java new file mode 100644 index 00000000000..620d4fb961b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass03/redefineclasses031a.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses031a is deugee's part of the redefineclasses031. + */ +public class redefineclasses031a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 78; + + static final int [] NEW_VALUES = { + 1, 2, 3, 4, 5 + }; + + static int testedField = 0; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + performTest(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static public void doSomething() { + + testedField = NEW_VALUES[2]; +// ^^^ will be changed + } + + static void performTest() { + // invoking of redefined method + for(int i = 0; i < NEW_VALUES.length; i++) { + // brkpLineNumber + doSomething(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass04/redefineclasses031a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass04/redefineclasses031a.java new file mode 100644 index 00000000000..527951266d2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass04/redefineclasses031a.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses031a is deugee's part of the redefineclasses031. + */ +public class redefineclasses031a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 78; + + static final int [] NEW_VALUES = { + 1, 2, 3, 4, 5 + }; + + static int testedField = 0; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + performTest(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static public void doSomething() { + + testedField = NEW_VALUES[3]; +// ^^^ will be changed + } + + static void performTest() { + // invoking of redefined method + for(int i = 0; i < NEW_VALUES.length; i++) { + // brkpLineNumber + doSomething(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass05/redefineclasses031a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass05/redefineclasses031a.java new file mode 100644 index 00000000000..941315415ae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031/newclass05/redefineclasses031a.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses031a is deugee's part of the redefineclasses031. + */ +public class redefineclasses031a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 78; + + static final int [] NEW_VALUES = { + 1, 2, 3, 4, 5 + }; + + static int testedField = 0; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + performTest(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static public void doSomething() { + + testedField = NEW_VALUES[4]; +// ^^^ will be changed + } + + static void performTest() { + // invoking of redefined method + for(int i = 0; i < NEW_VALUES.length; i++) { + // brkpLineNumber + doSomething(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031a.java new file mode 100644 index 00000000000..8f3980b4e41 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses031a.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses031a is deugee's part of the redefineclasses031. + */ +public class redefineclasses031a { + + public final static String brkpMethodName = "performTest"; + public final static int brkpLineNumber = 79; + + static final int [] NEW_VALUES = { + 1, 2, 3, 4, 5 + }; + + static int testedField = 0; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + performTest(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static public void doSomething() { + + testedField = 0; +// ^^^ will be changed + } + + static void performTest() { + // invoking of redefined method + for(int i = 0; i < NEW_VALUES.length; i++) { + + doSomething(); // brkpLineNumber + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032.java new file mode 100644 index 00000000000..b5401270162 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test checks up com.sun.jdi.VirtualMachine.redefineClasses(). + * The test stops in justMethod, does a redefineClasses which deletes + * a line in that method and then tries to get StackFrame.thisObject(). + * When canRedefineClasses() is false, the test is + * considered as passed and completes it's execution. + */ + +public class redefineclasses032 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses032"; + private final static String debugeeName = debuggerName + "a"; + private final static String Name = debuggerName + "b"; + + public final static String PERFORM_SGL = "perform"; + + private final static String newClassFile = "newclass" + File.separator + + prefix.replace('.',File.separatorChar) + + "redefineclasses032a.class"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String testDir; + + private ClassType debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses032 thisTest = new redefineclasses032(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + testDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + try { + thisTest.execTest(); + } catch (Failure e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.resume(); + debugee.quit(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + debugeeClass = (ClassType)debugee.classByName(debugeeName); + + display("\nTEST BEGINS"); + display("==========="); + + debugee.VM().suspend(); + + display("Tested class\t:" + debugeeClass.name()); + + ThreadReference thrd = debugee.threadByName("main"); + + BreakpointRequest brkp = debugee.setBreakpoint(debugeeClass, + redefineclasses032a.brkpMethodName, + redefineclasses032a.brkpLineNumber); + debugee.resume(); + debugee.sendSignal(PERFORM_SGL); + + waitBreakpointEvent(brkp, waitTime); + + display("\nredefining..."); + redefineDebugee(); + + StackFrame stackFrame = null; + ObjectReference obj = null; + display("getting current frane..."); + try { + stackFrame = thrd.frame(0); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + display("getting stackFrame.thisObject()..."); + try { + obj = stackFrame.thisObject(); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + if (obj != null) { + exitStatus = Consts.TEST_FAILED; + complain("stackFrame.thisObject() is not null for static method"); + } + + debugee.resume(); + + display("\n============="); + display("TEST FINISHES\n"); + } + + private void redefineDebugee() { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(testDir + File.separator + newClassFile); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(debugeeClass, arrayToRedefine); + return mapForClass; + } + + private BreakpointEvent waitBreakpointEvent(BreakpointRequest brkp, long waitTime) { + Event event; + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + if (!(event instanceof BreakpointEvent )) { + throw new Failure("BreakpointEvent didn't arrive"); + } + + return (BreakpointEvent )event; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/TestDescription.java new file mode 100644 index 00000000000..db8b11e6178 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up com.sun.jdi.VirtualMachine.redefineClasses(). + * The test stops in justMethod, does a redefineClasses which deletes + * a line in that method and then tries to get StackFrame.thisObject(). + * COMMENTS + * This is a regression test on the following bug: + * 4660477 After a redefineClasses, StackFrame.thisObject() + * gets JDWP Error 23 + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses032 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses032a + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses032 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/newclass/redefineclasses032a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/newclass/redefineclasses032a.java new file mode 100644 index 00000000000..54f538dd158 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032/newclass/redefineclasses032a.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses032a is deugee's part of the redefineclasses032. + */ +public class redefineclasses032a { + + public final static String brkpMethodName = "justMethod"; + public final static int brkpLineNumber = 63; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + justMethod(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static void justMethod() { // brkpLineNumber +// int local = 0; +// return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032a.java new file mode 100644 index 00000000000..214e6420f36 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses032a.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses032a is deugee's part of the redefineclasses032. + */ +public class redefineclasses032a { + + public final static String brkpMethodName = "justMethod"; + public final static int brkpLineNumber = 64; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println("ready"); + + String instr; + do { + instr = pipe.readln(); + if (instr.equals("perform")) { + justMethod(); + } else if (instr.equals("quit")) { + log.display(instr); + break; + } else { + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } while (true); + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + static void justMethod() { + int local = 0; // brkpLineNumber + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034.java new file mode 100644 index 00000000000..8651738aeef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test checks up com.sun.jdi.VirtualMachine.redefineClasses() + * in case when redefined class loaded by a custom loader. + * + * The test perform next steps:
    + * 1. Debugee loads a tested class by the custom loader.
    + * 2. When getting ClassPrepareEvent, debugger checks + * class loader of tested class to be the custom class loader.
    + * 3. Debugger redefines the tested class and checks the redefinition + * to be successful.
    + * The abose steps are performed for two cases, when the custom loader + * extends java.net.URLClassLoader and when the custom loader + * directly extends java.lang.ClassLoader. + */ + +public class redefineclasses034 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses034"; + public final static String debugeeName = debuggerName + "a"; + public final static int TESTCASE_NUMBER = 2; + public final static String [] testedClassName = { + debuggerName + "b", + debuggerName + "c" + }; + private final static String [] clsLdrs = { + debugeeName + "ClassLoaderB", + debugeeName + "ClassLoaderC" + }; + + private static final String redefinedMethodName = "justMethod"; + + private final static String PATH = "newclass" + File.separator + + prefix.replace('.',File.separatorChar); + private final static String [] newClassFile = { + PATH + "redefineclasses034b.class", + PATH + "redefineclasses034c.class" + }; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 3; + private int currentCase = -1; + private ReferenceType testedClass, debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain(msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses034 thisTest = new redefineclasses034(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); +// debugee.redirectStderr(log.getOutStream()); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); +// debugee.resume(); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + int eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debuggerName + "*"); + req.addClassExclusionFilter(debugeeName + "Class*"); + req.addClassExclusionFilter(debuggerName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + display(" event ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + testedClass = ((ClassPrepareEvent )event).referenceType();// debugee.classByName(testedClassNameB); + String className = testedClass.name(); + debugeeClass = debugee.classByName(debugeeName); + display(">>>>" + className); + if (className.compareTo(debugeeName) == 0) { + debugee.setBreakpoint(testedClass, + redefineclasses034a.brkpMethodName, + redefineclasses034a.brkpLineNumber); + display(""); + + } else if ( !checkCase(currentCase) ) { + complain("Unexpected event for \"" + className + + "\" class"); + exitStatus = Consts.TEST_FAILED; + } + + debugee.resume(); + eventCount++; + + } else if (event instanceof BreakpointEvent) { + currentCase++; + display("\ntestcase " + (currentCase + 1)); + display("==========="); + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (eventCount != expectedEventCount) { + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private boolean checkCase(int index) { + display("\nclasses info on debugger side:"); + display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + display("testedClass\t:" + testedClassName[index]); + + String clsLdrName = testedClass.classLoader().referenceType().name(); + String clsLdrName4Debugee = debugeeClass.classLoader().referenceType().name(); + display("class loader\t:" + clsLdrName); + display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + display("debugeeClass\t:" + debugeeClass.name()); + display("class loader\t:" + clsLdrName4Debugee); + display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + if (clsLdrName.compareTo(clsLdrName4Debugee) == 0 + || clsLdrName.compareTo(clsLdrs[index]) != 0) { + complain("wrong class loader \"" + clsLdrName + + "\"\n\tfor \"" + testedClassName[index] + "\""); + exitStatus = Consts.TEST_FAILED; + } + + List methods = testedClass.methodsByName(redefinedMethodName); + Method mthd = (Method)methods.get(0); + int varsBefore = localVars(mthd); + + display("\nredefining..."); + redefineDebugee(newClassFile[index]); + + methods = testedClass.methodsByName(redefinedMethodName); + mthd = (Method)methods.get(0); + int varsAfter = localVars(mthd); + + if (varsAfter == varsBefore) { + complain("count of local variables is not changed!"); + exitStatus = Consts.TEST_FAILED; + } + display(""); + return exitStatus != Consts.TEST_FAILED; + } + + private void redefineDebugee(String classFileName) { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(classDir + File.separator + classFileName); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private int localVars(Method mthd) { + int res = 0; + try { + List locVars = mthd.variables(); + res = locVars.size(); + display("\ncount of local variables: " + res); + + } catch (AbsentInformationException e) { + display("AbsentInformationException: no info"); + } + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/TestDescription.java new file mode 100644 index 00000000000..4c9f21e17fa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up com.sun.jdi.VirtualMachine.redefineClasses() + * in case when redefined class loaded by a custom loader. + * The test perform next steps: + * 1. Debugee loads a tested class by the custom loader. + * 2. When getting ClassPrepareEvent, debugger checks + * class loader of tested class to be the custom class loader. + * 3. Debugger redefines the tested class and checks the redefinition + * to be successful. + * The abose steps are performed for two cases, when the custom loader + * extends java.net.URLClassLoader and when the custom loader directly + * extends java.lang.ClassLoader. + * COMMENTS + * The test was developed as a regression test for + * #4739099 JDI HotSwap class file replacement with custom classloader broken + * 12/20/2002 test was fixed according to test bug 4778296: + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses034 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses034a + * + * @comment make sure redefineclasses034a is compiled with full debug info + * @clean nsk.jdi.VirtualMachine.redefineClasses.redefineclasses034a + * @compile -g:lines,source,vars ../redefineclasses034a.java + * + * @comment compile loadclassXX to bin/loadclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * loadclass + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses034 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/loadclass/redefineclasses034b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/loadclass/redefineclasses034b.java new file mode 100644 index 00000000000..e4c8641d5de --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/loadclass/redefineclasses034b.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses034b is deugee's part of the redefineclasses034. + */ + +public class redefineclasses034b { + + void justMethod() { +// int local = 0; +// return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/loadclass/redefineclasses034c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/loadclass/redefineclasses034c.java new file mode 100644 index 00000000000..9bd4734f00c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/loadclass/redefineclasses034c.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses034b is deugee's part of the redefineclasses034. + */ + +public class redefineclasses034c { + + void justMethod() { +// int local = 0; +// return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/newclass/redefineclasses034b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/newclass/redefineclasses034b.java new file mode 100644 index 00000000000..03bed706a52 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/newclass/redefineclasses034b.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses034b is deugee's part of the redefineclasses034. + */ + +public class redefineclasses034b { + + void justMethod() { + int local = 0; + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/newclass/redefineclasses034c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/newclass/redefineclasses034c.java new file mode 100644 index 00000000000..8b3490e4910 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034/newclass/redefineclasses034c.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses034b is deugee's part of the redefineclasses034. + */ + +public class redefineclasses034c { + + void justMethod() { + int local = 0; + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034a.java new file mode 100644 index 00000000000..ba0205b8987 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses034a.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; +import java.net.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses034a is deugee's part of the redefineclasses034. + */ +public class redefineclasses034a { + public final static String brkpMethodName = "loadClass"; + public final static int brkpLineNumber = 72; + + static Object obj; + static Class cls; + static ClassLoader clsLoader[]; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + + String oldClassDir = argv[0] + File.separator + "loadclass"; + + URL urls[] = new URL[1]; + clsLoader = new ClassLoader[redefineclasses034.TESTCASE_NUMBER]; + try { + urls[0] = new File(oldClassDir).toURL(); + } catch (MalformedURLException e) { + log.display("->" + e); + } + clsLoader[0] = new redefineclasses034aClassLoaderB(urls); + clsLoader[1] = new redefineclasses034aClassLoaderC(oldClassDir); + + for (int i = 0; i < 2; i++) { + loadClass(clsLoader[i],redefineclasses034.testedClassName[i]); + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void loadClass(ClassLoader clsLoader, String className) { + try { + cls = clsLoader.loadClass(className); // brkpLineNumber + obj = cls.newInstance(); + log.display(className); + log.display("===================================="); + log.display("class loader's info on debugee side:"); + log.display("===================================="); + log.display("custom class loader\t:" + cls.getClassLoader()); + log.display("default class loader\t:" + + Class.forName(redefineclasses034.debugeeName).getClassLoader()); + + log.display("------------------------------------"); + } catch (Exception e) { + log.display("" + e); + e.printStackTrace(); + } + } +} + +class redefineclasses034aClassLoaderB extends URLClassLoader{ + + redefineclasses034aClassLoaderB(URL [] urllst) { + super(urllst); + } +} + +class redefineclasses034aClassLoaderC extends ClassLoader{ + + private String classPath; + + redefineclasses034aClassLoaderC(String classPath) { + super(redefineclasses034aClassLoaderC.class.getClassLoader()); + this.classPath = classPath; + } + + protected Class findClass(String name) throws ClassNotFoundException { + String classFileName = classPath + File.separator + + name.replace('.', File.separatorChar) + + ".class"; + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + try { + int len = in.available(); + byte[] data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + return defineClass(name, data, 0, data.length); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (Throwable e) { + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035.java new file mode 100644 index 00000000000..ca7b7c167c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035.java @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; + +import java.util.*; +import java.io.*; + +/** + * The test checks up com.sun.jdi.VirtualMachine.redefineClasses() + * in case when redefined class loaded by a custom loader. + * + * The test perform next steps:
    + * 1. Debugee loads a tested class by the custom loader.
    + * 2. When getting ClassPrepareEvent, debugger checks class + * loader of tested class to be the custom class loader and creates + * MethodEntryRequest for tested class and waits + * a corresponding event.
    + * 3. Debugee calls a method of the tested class.
    + * 4. After getting MethodEntryEvent, debugger redefines + * the tested class and checks the redefinition to be successful.
    + * + * The above steps are performed for two cases, when the custom loader + * extends java.net.URLClassLoader and when the custom loader directly + * extends java.lang.ClassLoader. + */ + +public class redefineclasses035 { + + public final static String UNEXPECTED_STRING = "***Unexpected exception "; + + private final static String prefix = "nsk.jdi.VirtualMachine.redefineClasses."; + private final static String debuggerName = prefix + "redefineclasses035"; + public final static String debugeeName = debuggerName + "a"; + public final static int TESTCASE_NUMBER = 2; + public final static String [] testedClassName = { + debuggerName + "b", + debuggerName + "c" + }; + private final static String [] expectedClsLdrs = { + debugeeName + "ClassLoaderB", + debugeeName + "ClassLoaderC" + }; + + static final String redefinedMethodName = "justMethod"; + + private final static String PATH = "newclass" + File.separator + + prefix.replace('.',File.separatorChar); + private final static String [] newClassFile = { + PATH + "redefineclasses035b.class", + PATH + "redefineclasses035c.class" + }; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + private static long waitTime; + private static String classDir; + + private int expectedEventCount = 4; + private int currentCase = -1; + private ReferenceType testedClass, debugeeClass; + + private static void display(String msg) { + log.display(msg); + } + + private static void complain(String msg) { + log.complain(msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + redefineclasses035 thisTest = new redefineclasses035(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + classDir = argv[0]; + waitTime = argHandler.getWaitTime() * 60000; + + Binder binder = new Binder(argHandler, log); + debugee = binder.bindToDebugee(debugeeName); + debugee.redirectOutput(log); + + try { + thisTest.execTest(); + } catch (Throwable e) { + exitStatus = Consts.TEST_FAILED; + e.printStackTrace(); + } finally { + debugee.endDebugee(); + } + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() throws Failure { + + if (!debugee.VM().canRedefineClasses()) { + display("\n>>>canRedefineClasses() is false<<< test canceled.\n"); + return; + } + + display("\nTEST BEGINS"); + display("==========="); + + EventSet eventSet = null; + EventIterator eventIterator = null; + Event event; + long totalTime = waitTime; + long tmp, begin = System.currentTimeMillis(), + delta = 0; + boolean exit = false; + + int eventCount = 0; + EventRequestManager evm = debugee.getEventRequestManager(); + ClassPrepareRequest req = evm.createClassPrepareRequest(); + req.addClassFilter(debuggerName + "*"); + req.addClassExclusionFilter(debugeeName + "Class*"); + req.addClassExclusionFilter(debuggerName); + req.enable(); + debugee.resume(); + + while (totalTime > 0 && !exit) { + if (eventIterator == null || !eventIterator.hasNext()) { + try { + eventSet = debugee.VM().eventQueue().remove(totalTime); + } catch (InterruptedException e) { + new Failure(e); + } + if (eventSet != null) { + eventIterator = eventSet.eventIterator(); + } else { + eventIterator = null; + } + } + if (eventIterator != null) { + while (eventIterator.hasNext()) { + event = eventIterator.nextEvent(); + display("\nevent ===>>> " + event); + + if (event instanceof ClassPrepareEvent) { + testedClass = ((ClassPrepareEvent )event).referenceType(); + String className = testedClass.name(); + + if (className.compareTo(debugeeName) == 0) { + prepareTestCases(); + + } else { + createMethodEntryRequest(currentCase); + } + + debugee.resume(); + + } else if (event instanceof BreakpointEvent) { + currentCase++; + display("\ntestcase " + (currentCase + 1)); + display("==========="); + debugee.resume(); + + } else if (event instanceof MethodEntryEvent) { + checkCase((MethodEntryEvent )event); + eventCount++; + debugee.resume(); + + } else if (event instanceof VMDeathEvent) { + exit = true; + break; + } else if (event instanceof VMDisconnectEvent) { + exit = true; + break; + } // if + } // while + } // if + tmp = System.currentTimeMillis(); + delta = tmp - begin; + totalTime -= delta; + begin = tmp; + } + + if (totalTime <= 0) { + complain("out of wait time..."); + exitStatus = Consts.TEST_FAILED; + } + if (eventCount != expectedEventCount) { + complain("expecting " + expectedEventCount + + " events, but " + + eventCount + " events arrived."); + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + } + + private void checkCase(MethodEntryEvent event) { + Method mthd = getCurrentMethod(event.thread()); + if (mthd.isConstructor()) { + display("it is constructor (skipped)"); + return; + } + + display("\nredefining..."); + redefineDebugee(newClassFile[currentCase]); + + mthd = getCurrentMethod(event.thread()); + + if (mthd.isObsolete()) { + display("!!!method is obsolete!!!"); + display("redefinition is OK"); + event.request().disable(); + display("MethodEntryEvent is being disabled"); + } else { + complain("method is not obsolete"); + complain("redefinition was not OK"); + exitStatus = Consts.TEST_FAILED; + } + display(""); + return; + } + + private MethodEntryRequest createMethodEntryRequest(int index) { + display("\nclasses info on debugger side:"); + display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + display("testedClass\t:" + testedClassName[currentCase]); + + String clsLdrName = testedClass.classLoader().referenceType().name(); + String clsLdrName4Debugee = debugeeClass.classLoader().referenceType().name(); + display("class loader\t:" + clsLdrName); + display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + if (clsLdrName.compareTo(expectedClsLdrs[currentCase]) != 0) { + complain("wrong class loader \"" + clsLdrName + + "\"\n\tfor \"" + testedClassName[currentCase] + "\""); + exitStatus = Consts.TEST_FAILED; + } + + EventRequestManager evm = debugee.getEventRequestManager(); + MethodEntryRequest request = evm.createMethodEntryRequest(); + request.addClassFilter(testedClassName[index]); + request.enable(); + return request; + } + + private void redefineDebugee(String classFileName) { + Map mapBytes; + boolean alreadyComplained = false; + mapBytes = mapClassToBytes(classDir + File.separator + classFileName); + try { + debugee.VM().redefineClasses(mapBytes); + } catch (Exception e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private Map mapClassToBytes(String fileName) { + display("class-file\t:" + fileName); + File fileToBeRedefined = new File(fileName); + int fileToRedefineLength = (int )fileToBeRedefined.length(); + byte[] arrayToRedefine = new byte[fileToRedefineLength]; + + FileInputStream inputFile; + try { + inputFile = new FileInputStream(fileToBeRedefined); + } catch (FileNotFoundException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + + try { + inputFile.read(arrayToRedefine); + inputFile.close(); + } catch (IOException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + HashMap mapForClass = new HashMap(); + mapForClass.put(testedClass, arrayToRedefine); + return mapForClass; + } + + private Method getCurrentMethod(ThreadReference thread) { + try { + Method mthd = thread.frame(0).location().method(); + display("current method\t:" + mthd); + return mthd; + } catch (IncompatibleThreadStateException e) { + throw new Failure(UNEXPECTED_STRING + e); + } + } + + private void prepareTestCases() { + debugeeClass = debugee.classByName(debugeeName); + display("debugeeClass\t\t:" + debugeeClass.name()); + display("default class loader\t:" + + debugeeClass.classLoader().referenceType().name()); + display("setting breakpoint..."); + debugee.setBreakpoint(testedClass, + redefineclasses035a.brkpMethodName, + redefineclasses035a.brkpLineNumber); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/TestDescription.java new file mode 100644 index 00000000000..d6f04cef61a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test checks up com.sun.jdi.VirtualMachine.redefineClasses() + * in case when redefined class loaded by a custom loader. + * The test perform next steps: + * 1. Debugee loads a tested class by the custom loader. + * 2. When getting ClassPrepareEvent, debugger checks class loader + * of tested class to be the custom class loader and creates + * MethodEntryRequest for tested class and waits a corresponding + * event. + * 3. Debugee calls a method of the tested class. + * 4. After getting MethodEntryEvent, debugger redefines the tested + * class and checks the redefinition to be successful. + * The above steps are performed for two cases, when the custom loader + * extends java.net.URLClassLoader and when the custom loader directly + * extends java.lang.ClassLoader. + * COMMENTS + * The test was developed as a regression test for + * #4739099 JDI HotSwap class file replacement with custom classloader broken + * 4777347 TEST_BUG: redefineclasses035 wrongly redefines method + * Test was fixed according to test bug 4778296: + * - handling VMStartEvent was removed from the debugger part of the test + * - quit on VMDeathEvent was added to the event handling loop + * Test updated to wait for debugee VM exit: + * - standard method Debugee.endDebugee() is used instead of final Debugee.resume() + * #5055417 TEST: warnings and notes caused by generification + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.redefineClasses.redefineclasses035 + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses035a + * + * @comment compile loadclassXX to bin/loadclassXX + * @run driver nsk.share.ExtraClassesBuilder + * loadclass + * + * @comment compile newclassXX to bin/newclassXX + * with full debug info + * @run driver nsk.share.ExtraClassesBuilder + * -g:lines,source,vars + * newclass + * + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.redefineClasses.redefineclasses035 + * ./bin + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/loadclass/redefineclasses035b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/loadclass/redefineclasses035b.java new file mode 100644 index 00000000000..3e78d3e3f63 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/loadclass/redefineclasses035b.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses035b is deugee's part of the redefineclasses035. + */ + +public class redefineclasses035b { + + public void justMethod() { + int local = 0; + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/loadclass/redefineclasses035c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/loadclass/redefineclasses035c.java new file mode 100644 index 00000000000..0bdc28011ee --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/loadclass/redefineclasses035c.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses035b is deugee's part of the redefineclasses035. + */ + +public class redefineclasses035c { + + public void justMethod() { + int local = 0; + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/newclass/redefineclasses035b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/newclass/redefineclasses035b.java new file mode 100644 index 00000000000..5dfb82a3ed7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/newclass/redefineclasses035b.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses035b is deugee's part of the redefineclasses035. + */ + +public class redefineclasses035b { + + public void justMethod() { + int local = 0, local1 = 1; + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/newclass/redefineclasses035c.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/newclass/redefineclasses035c.java new file mode 100644 index 00000000000..32d70c6eb20 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035/newclass/redefineclasses035c.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * redefineclasses035b is deugee's part of the redefineclasses035. + */ + +public class redefineclasses035c { + + public void justMethod() { + int local = 0, local1 = 1; + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035a.java new file mode 100644 index 00000000000..bb12bc8c9ba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses035a.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VirtualMachine.redefineClasses; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import java.io.*; +import java.net.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * redefineclasses035a is deugee's part of the redefineclasses035. + */ +public class redefineclasses035a { + public final static String brkpMethodName = "loadClass"; + public final static int brkpLineNumber = 72; + + static Object obj; + static Class cls; + static ClassLoader clsLoader[]; + static Log log; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(System.out, argHandler); + + String oldClassDir = argv[0] + File.separator + "loadclass"; + + URL urls[] = new URL[1]; + clsLoader = new ClassLoader[redefineclasses035.TESTCASE_NUMBER]; + try { + urls[0] = new File(oldClassDir).toURL(); + } catch (MalformedURLException e) { + log.display("->" + e); + } + clsLoader[0] = new redefineclasses035aClassLoaderB(urls); + clsLoader[1] = new redefineclasses035aClassLoaderC(oldClassDir); + + for (int i = 0; i < 2; i++) { + loadClass(clsLoader[i],redefineclasses035.testedClassName[i]); + } + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + private static void loadClass(ClassLoader clsLoader, String className) { + try { + log.display("loading class \"" + className + "\"..."); // brkpLineNumber + cls = clsLoader.loadClass(className); + obj = cls.newInstance(); + log.display("===================================="); + log.display("class loader's info on debugee side:"); + log.display("===================================="); + log.display("custom class loader\t:" + cls.getClassLoader()); + log.display("default class loader\t:" + + Class.forName(redefineclasses035.debugeeName).getClassLoader()); + + log.display("------------------------------------"); + + log.display("invoking \"" + redefineclasses035.redefinedMethodName + + "\"..."); + java.lang.reflect.Method mthd; + mthd = cls.getMethod(redefineclasses035.redefinedMethodName); + mthd.invoke(obj); + + } catch (Exception e) { + log.display("" + e); + e.printStackTrace(); + } + } +} + +class redefineclasses035aClassLoaderB extends URLClassLoader{ + + redefineclasses035aClassLoaderB(URL [] urllst) { + super(urllst); + } +} + +class redefineclasses035aClassLoaderC extends ClassLoader{ + + private String classPath; + + redefineclasses035aClassLoaderC(String classPath) { + super(redefineclasses035aClassLoaderC.class.getClassLoader()); + this.classPath = classPath; + } + + protected Class findClass(String name) throws ClassNotFoundException { + String classFileName = classPath + File.separator + + name.replace('.', File.separatorChar) + + ".class"; + FileInputStream in; + try { + in = new FileInputStream(classFileName); + if (in == null) { + throw new ClassNotFoundException(classFileName); + } + } catch (FileNotFoundException e) { + throw new ClassNotFoundException(classFileName, e); + } + + try { + int len = in.available(); + byte[] data = new byte[len]; + for (int total = 0; total < data.length; ) { + total += in.read(data, total, data.length - total); + } + return defineClass(name, data, 0, data.length); + } catch (IOException e) { + throw new ClassNotFoundException(classFileName, e); + } finally { + try { + in.close(); + } catch (Throwable e) { + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001.java new file mode 100644 index 00000000000..db12a441e96 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.resume; + +import nsk.share.*; +import nsk.share.jdi.*; +import com.sun.jdi.*; +import java.io.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +public class resume001 extends TestDebuggerType2 { + + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new resume001().runIt(argv, out); + } + + protected String debuggeeClassName() { + return resume001a.class.getName(); + } + + class EventListener extends EventHandler.EventListener { + Object lock = new Object(); + + volatile int breakpointCounter; + + volatile int expectedBreakpointNumber; + + EventListener(int expectedBreakpointNumber) { + this.expectedBreakpointNumber = expectedBreakpointNumber; + } + + void waitForBreakpoints() { + synchronized (lock) { + while (breakpointCounter < expectedBreakpointNumber) { + try { + lock.wait(); + } catch (InterruptedException e) { + unexpectedException(e); + } + } + } + } + + public boolean eventReceived(Event event) { + if (event instanceof BreakpointEvent) { + log.display("BreakpointEvent was received: " + event); + + breakpointCounter++; + + if (breakpointCounter == expectedBreakpointNumber) { + synchronized (lock) { + lock.notify(); + } + } + + if (breakpointCounter > expectedBreakpointNumber) { + setSuccess(false); + System.out.println("Extra breakpoint event was received: " + event); + } + + return true; + } + + return false; + } + } + + protected void doTest() { + ReferenceType testThreadClass = debuggee.classByName(resume001a.class.getName()); + + BreakpointRequest breakpointRequest = null; + + try { + for (Location location : testThreadClass.allLineLocations()) { + if (location.lineNumber() == resume001a.BREAKPOINT_LINE_NUMBER) { + breakpointRequest = debuggee.getEventRequestManager().createBreakpointRequest(location); + break; + } + } + } catch (AbsentInformationException e) { + unexpectedException(e); + return; + } + + if (breakpointRequest == null) { + setSuccess(false); + log.complain("Location for line " + resume001a.BREAKPOINT_LINE_NUMBER + " wasn't found in class " + testThreadClass.name()); + return; + } + + breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + breakpointRequest.enable(); + + log.display("BreakpointRequest was created: " + breakpointRequest); + + EventHandler eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + try { + /* + * Wait for BreakpointEvents from debuggee main thread and from each + * additional test thread + */ + final int suspendedThreadsNumber = resume001a.TEST_THREAD_NUMBER + 1; + + EventListener listener = new EventListener(suspendedThreadsNumber); + eventHandler.addListener(listener); + + pipe.println(resume001a.COMMAND_STOP_ALL_THREADS_AT_BREAKPOINT); + + listener.waitForBreakpoints(); + + log.display("Resume debuggee VM"); + + debuggee.VM().resume(); + + /* + * Wait for replay for previous command (resume001a.COMMAND_STOP_ALL_THREADS_AT_BREAKPOINT) + */ + if (!isDebuggeeReady()) + return; + + pipe.println(resume001a.COMMAND_JOIN_TEST_THREADS); + + if (!isDebuggeeReady()) + return; + + ReferenceType debuggeeClass = debuggee.classByName(debuggeeClassNameWithoutArgs()); + + Field counterField = debuggeeClass.fieldByName(resume001a.COUNTER_FIELD_NAME); + if (counterField == null) { + setSuccess(false); + log.complain("Field " + resume001a.COUNTER_FIELD_NAME + " wasn't found in class " + debuggeeClassNameWithoutArgs()); + return; + } + + IntegerValue value = (IntegerValue) debuggeeClass.getValue(counterField); + + /* + * Each suspended thread should increment counter after resuming + */ + if (value.value() != suspendedThreadsNumber) { + setSuccess(false); + log.complain("Unexpected value of field " + resume001a.COUNTER_FIELD_NAME + + ": " + value.intValue() + ", expected value is " + suspendedThreadsNumber); + } + } finally { + eventHandler.stopEventHandler(); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001/TestDescription.java new file mode 100644 index 00000000000..8bb58e72b9a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001/TestDescription.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/resume/resume001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test checks that method VirtualMachine.resume resumes all threads in debuggee VM + * as documented in ThreadReference.resume(). + * Test scenario: + * Debugger creates breakpoint at the special method in debuggee application's class. + * Then debugger forces debuggee to start several threads executing this method with + * breakpoint, main debuggee thread also calls this method. Debugger waits when all + * debuggee threads will be suspended at breakpoint, calls method VirtualMachine.resume + * and checks that all suspended threads in debuggee VM were resumed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.resume.resume001 + * nsk.jdi.VirtualMachine.resume.resume001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.resume.resume001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001a.java new file mode 100644 index 00000000000..a22ae0bdc78 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/resume/resume001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.resume; + +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/* + * Debuggee part of test (debuggee starts several test threads which should + * be suspended at breakpoint) + * + * WARNING: edit this file carefully, breakpoint line number is hardcoded + */ +public class resume001a extends AbstractJDIDebuggee { + + static final String COMMAND_STOP_ALL_THREADS_AT_BREAKPOINT = "COMMAND_START_TEST_THREADS"; + + static final String COMMAND_JOIN_TEST_THREADS = "COMMAND_JOIN_TEST_THREADS"; + + static int counter; + + static final String COUNTER_FIELD_NAME = "counter"; + + synchronized static void incCounter() { + counter++; + } + + class TestThread extends Thread { + + public void run() { + log.display(getName() + " started"); + + stopAtBreakpoint(); + + log.display(getName() + " finished"); + } + } + + static final int BREAKPOINT_LINE_NUMBER = 63; + + static void stopAtBreakpoint() { + int i = 0; // BREAKPOINT_LINE_NUMBER + + incCounter(); + } + + static final int TEST_THREAD_NUMBER = 10; + + private TestThread[] testThreads = new TestThread[TEST_THREAD_NUMBER]; + + public resume001a() { + for (int i = 0; i < testThreads.length; i++) { + testThreads[i] = new TestThread(); + } + } + + public boolean parseCommand(String command) { + if (super.parseCommand(command)) + return true; + + if (command.equals(COMMAND_STOP_ALL_THREADS_AT_BREAKPOINT)) { + /* + * All TestThreads execute method stopAtBreakpoint() + */ + for (TestThread testThread : testThreads) { + testThread.start(); + } + + // debuggee main thread also stops at breakpoint + stopAtBreakpoint(); + + return true; + } else if (command.equals(COMMAND_JOIN_TEST_THREADS)) { + for (TestThread testThread : testThreads) { + try { + testThread.join(); + } catch (InterruptedException e) { + unexpectedException(e); + } + } + return true; + } + + return false; + } + + public static void main(String args[]) { + new resume001a().doTest(args); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum002/setDefaultStratum002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum002/setDefaultStratum002.java new file mode 100644 index 00000000000..ae3f0c2f1fa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum002/setDefaultStratum002.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2007, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum002. + * VM Testbase keywords: [quick, jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that method 'com.sun.jdi.VirtualMachine.setDefaultStratum(String stratum)' affects result of following methods: + * - ReferenceType.defaultStratum() + * - ReferenceType.sourceName() + * - ReferenceType.allLineLocations() + * - ReferenceType.locationsOfLine(int lineNumber) + * - Method.allLineLocations() + * - Method.locationsOfLine(int lineNumber) + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3') and for each of this stratums following line mapping + * is defined: + * "Java" "TestStratum" + * + * 9 --> 1000, source1 + * 10 --> 1001, source1 + * ... ... + * 16 --> 1007, source1 + * sde_testMethod1 + * 20 --> 1100, source1 + * 21 --> 1101, source1 + * ... ... + * 27 --> 1107, source1 + * sde_testMethod1 + * 31 --> 1200, source1 + * 32 --> 1201, source1 + * ... ... + * 38 --> 1207, source1 + * Then debugger forces debuggee to load 'TestClass1' from updated class file and obtains ReferenceType for this class + * for TestStratum in 'TestStratum1'-'TestStratum3' + * do + * - set TestStratum as VM default using 'VirtualMachine.setDefaultStratum(String stratum)' + * - checks up that following methods: + * - ReferenceType.defaultStratum() + * - ReferenceType.sourceName() + * - ReferenceType.allLineLocations() + * - ReferenceType.locationsOfLine(int lineNumber) + * - Method.allLineLocations() + * - Method.locationsOfLine(int lineNumber) + * returns information for TestStratum. + * done + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.setDefaultStratum.setDefaultStratum002.setDefaultStratum002 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.setDefaultStratum.setDefaultStratum002.setDefaultStratum002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.VirtualMachine.setDefaultStratum.setDefaultStratum002; + +import java.io.*; +import java.util.*; +import com.sun.jdi.*; +import nsk.share.Consts; +import nsk.share.jdi.sde.*; + +public class setDefaultStratum002 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setDefaultStratum002().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type1( + className, + testStratumCount, + true); + + // debuggee loads TestClass1 from patched class file + pipe.println(SDEDebuggee.COMMAND_LOAD_CLASS + ":" + className); + + if (!isDebuggeeReady()) + return; + + // obtain ReferenceType for loaded class + ReferenceType referenceType = debuggee.classByName(className); + + List sourceNames = new ArrayList(); + List sourcePaths = new ArrayList(); + // if ReferenceType.sourcePaths(String stratum) is called with 'null' + // argument it returns source path for + // declaring type's default stratum, in this test default stratum for + // TestClass1 is "Java" + sourcePaths.add(javaSourcePath_TestClass1); + + // for each stratum available for class + for (String stratumName : testStratumData.keySet()) { + // for each stratum all locations have similar sourceName + String sourceName = testStratumData.get(stratumName).allLocations.get(0).sourceName; + + log.display("Check default stratum '" + stratumName + "' (source name '" + sourceName + "')"); + + sourceNames.clear(); + sourceNames.add(sourceName); + + vm.setDefaultStratum(stratumName); + checkReferenceType( + null, + referenceType, + sourceNames, + sourcePaths, + testStratumData.get(stratumName).allLocations); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum003/setDefaultStratum003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum003/setDefaultStratum003.java new file mode 100644 index 00000000000..27c15b952ff --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum003/setDefaultStratum003.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum003. + * VM Testbase keywords: [jpda, jdi, feature_sde, vm6] + * VM Testbase readme: + * DESCRIPTION + * The test checks up that method 'com.sun.jdi.VirtualMachine.setDefaultStratum(String stratum)' affects StepEvents generation. + * Debugger creates copy of class file for class 'nsk.share.jdi.TestClass1' with SourceDebugExtension attribute + * which contains informations for 3 stratums('TestStratum1'-'TestStratum3') and for each of this stratums following line mapping + * is defined: + * "Java" "TestStratum" + * + * 9 --> 1000, source1 + * 11 --> 1002, source1 + * ... ... + * sde_testMethod1 + * 20 --> 1100, source1 + * 22 --> 1101, source1 + * ... ... + * sde_testMethod1 + * 31 --> 1200, source1 + * 33 --> 1201, source1 + * ... ... + * Then debugger forces debuggee to load 'TestClass1' from updated class file, starts event listener thread which saves all received StepEvents, + * enables StepEvent request(class filter is used to receive events only for 'TestClass1'). + * for TestStratum in 'TestStratum1'-'TestStratum3' + * do + * - set TestStratum as VM default + * - force debuggee to execute all methods defined in 'TestClass1' + * - when all methods was executed check up that StepEvents was generated for each location specified for TestStratum + * done + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.setDefaultStratum.setDefaultStratum003.setDefaultStratum003 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.setDefaultStratum.setDefaultStratum003.setDefaultStratum003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -testWorkDir . + * -testStratumCount 3 + */ + +package nsk.jdi.VirtualMachine.setDefaultStratum.setDefaultStratum003; + +import java.io.*; +import java.util.*; +import com.sun.jdi.request.*; +import nsk.share.Consts; +import nsk.share.jdi.EventHandler; +import nsk.share.jdi.sde.*; + +public class setDefaultStratum003 extends SDEDebugger { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new setDefaultStratum003().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-testStratumCount") && (i < args.length - 1)) { + testStratumCount = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + private int testStratumCount = 1; + + private EventHandler eventHandler; + + public void doTest() { + String className = TestClass1.class.getName(); + + Map testStratumData = prepareDefaultPatchedClassFile_Type3( + className, + testStratumCount, + true); + /* + * Method 'prepareDefaultPatchedClassFile_Type3' creates class file with + * following line mapping for each test stratum: + * + * "Java" "TestStratum" + * + * + * 9 --> 1001, source1 + * 11 --> 1002, source1 + * 14 --> 1003, source1 + * 16 --> 1004, source1 + * + * sde_testMethod1 + * 20 --> 1101, source1 + * 22 --> 1102, source1 + * 24 --> 1103, source1 + * 26 --> 1104, source1 + * + * sde_testMethod2 + * 31 --> 1201, source1 + * 33 --> 1202, source1 + * 35 --> 1203, source1 + * 37 --> 1204, source1 + */ + + eventHandler = new EventHandler(debuggee, log); + eventHandler.startListening(); + + StepEventListener stepEventListener = new StepEventListener(); + eventHandler.addListener(stepEventListener); + + StepRequest stepRequest = debuggee.getEventRequestManager().createStepRequest( + debuggee.threadByName(SDEDebuggee.mainThreadName), + StepRequest.STEP_LINE, + StepRequest.STEP_INTO); + + stepRequest.setSuspendPolicy(StepRequest.SUSPEND_EVENT_THREAD); + stepRequest.addClassFilter(TestClass1.class.getName()); + stepRequest.enable(); + + // for each stratum available for class + for (String defaultStratum : testStratumData.keySet()) { + log.display("Set default stratum: " + defaultStratum); + + stepEventListener.clearLocations(); + + vm.setDefaultStratum(defaultStratum); + + pipe.println(SDEDebuggee.COMMAND_EXECUTE_TEST_METHODS + ":" + className); + + if (!isDebuggeeReady()) + return; + + compareLocations( + stepEventListener.stepLocations(), + testStratumData.get(defaultStratum).allLocations, + defaultStratum); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001.java new file mode 100644 index 00000000000..99263fb0695 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.setDefaultStratum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.setDefaultStratum()
    + * complies with its specification.
    + *
    + * The test checks that String returned by the method
    + * VirtualMachine.getDefaultStratum() is equal to one
    + * set with setDefaultStratum(String).
    + *
    + */ + +public class setdefaultstratum001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + return new setdefaultstratum001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.setDefaultStratum.setdefaultstratum001a"; + + //String mName = "nsk.jdi.VirtualMachine.setDefaultStratum"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + ReferenceType testedClass = null; + + static int testExitCode = PASSED; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + String newDefaultStratum = "krop"; + + try { + vm.setDefaultStratum(newDefaultStratum); + String defaultStratum = vm.getDefaultStratum(); + if (defaultStratum != newDefaultStratum) { + log3("ERROR: defaultStratum is not set up correctly : " + defaultStratum); + testExitCode = FAILED; + } + } catch ( UnsupportedOperationException e ) { + log2(" UnsupportedOperationException"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001/TestDescription.java new file mode 100644 index 00000000000..2baa33d31d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001. + * VM Testbase keywords: [quick, jpda, jdi, redefine] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.setDefaultStratum(String) + * complies with its spec: + * public void setDefaultStratum(String stratum) + * Set this VM's default stratum (see Location for a discussion of strata). + * Overrides the per-class default set in the class file. + * Affects location queries (such as, Location.sourceName()) and + * the line boundaries used in single stepping. + * Parameters: stratum - the stratum to set as VM default, or + * null to use per-class defaults. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.setDefaultStratum.setdefaultstratum001; + * the debuggee program - nsk.jdi.VirtualMachine.setDefaultStratum.setdefaultstratum001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.setDefaultStratum.setdefaultstratum001 + * nsk.jdi.VirtualMachine.setDefaultStratum.setdefaultstratum001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.setDefaultStratum.setdefaultstratum001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001a.java new file mode 100644 index 00000000000..a3dd356c4a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setdefaultstratum001a.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.setDefaultStratum; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the setdefaultstratum001 JDI test. + */ + +public class setdefaultstratum001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> debuggee: " + message); + } +/* + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } +*/ + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> debuggee: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.suspend()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows.
    + * After being started up,
    + * a debuggee creates a 'lockingObject' for synchronizing threads,
    + * enters a synchronized block in which it creates new thread, thread2,
    + * informs a debugger of the thread2 creation, and is waiting for reply.
    + * Since thread2 uses the same locking object in its 'run' method
    + * it is locked up until first thread leaves the synchronized block.
    + * Upon the receiption a message from the debuggee, the debugger :
    + * - sets up breakpoints for both thread2 and main thread in the debuggee,
    + * - gets both threads suspended at the breakpoints,
    + * - calls to the method VirtualMachine.suspend(),
    + * - resumes both threads individually, one time each,
    + * - sleeps for predefined time - a standard parameter of the test,
    + * - then checks up the value of debuggee's field "flagCount" which is
    + * incremented by both tested threads only after their points of
    + * suspension. Hence, if the value == 0 (initial), it has not been
    + * changed by any tested thread while the debugger has been sleeping.
    + */ + +public class suspend001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/suspend/suspend001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new suspend001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.suspend.suspend001a"; + + private String testedClassName = + "nsk.jdi.VirtualMachine.suspend.VMsuspend001a"; + + //String mName = "nsk.jdi.VirtualMachine.suspend"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + String threadName = "Thread2"; + String flagName = "flagCount"; + + String breakpointMethod1 = "runt1"; + String breakpointMethod2 = "runt2"; + + String bpLine1 = "breakpointLineNumber1"; + String bpLine2 = "breakpointLineNumber2"; + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + BreakpointRequest breakpRequest1 = null; + BreakpointRequest breakpRequest2 = null; + + + label0: { + + log2("getting ThreadReference objects and setting up breakponts"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + listIterator = allThreads.listIterator(); + for (;;) { + try { + mainThread = (ThreadReference) listIterator.next(); + if (mainThread.name().equals("main")) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoints"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + breakpRequest2 = settingBreakpoint(breakpointMethod2, bpLine2, "two"); + if (breakpRequest2 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" instructing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" thread2 is at breakpoint"); + + log2(" copying: EventSet eventSet1 = eventSet;"); + EventSet eventSet1 = eventSet; + + log2(" enabling breakpRequest2"); + breakpRequest2.enable(); + + log2(" instructing the main thread to leave to continue"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting BreakpointEvent"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + log2(" mainThread is at breakpoint"); + + log2(" debugger turned off pipe pinging"); + pipe.setPingTimeout(0); + + log2(" suspending VM"); + vm.suspend(); + + log2(" resuming threads individually: eventSet1.resume(); eventSet.resume();"); + eventSet1.resume(); + eventSet.resume(); + + log2(" before: Thread.sleep(waitTime*60000);"); + try { + Thread.sleep(waitTime*60000); + } catch ( InterruptedException e ) { + log3("ERROR: InterruptedException"); + expresult = returnCode1; + break label1; + } + + log2(" checking up debuggee's flagCount value"); + int flag = ((IntegerValue) testedclass.getValue(testedclass.fieldByName(flagName))).value(); + log2(" value of flagCount == " + flag); + if (flag != 0) { + log3("ERROR: value of flagCount != 0"); + expresult = returnCode1; + } + } + + log2(" resuming VM"); + vm.resume(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); +// breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove (waitTime*60000); + if (eventSet == null) { +// log2(":::::: timeout when waiting for a BreakpintEvent"); + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001/TestDescription.java new file mode 100644 index 00000000000..6676e8e00d9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/suspend/suspend001. + * VM Testbase keywords: [jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.suspend() + * complies with its spec: + * public void suspend() + * Suspends the execution of the application running in this virtual machine. + * All threads currently running will be suspended. + * Unlike java.lang.Thread#suspend, suspends of both the virtual machine and + * individual threads are counted. Before a thread will run again, + * it must be resumed (through resume() or ThreadReference.resume()) + * the same number of times it has been suspended. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.suspend.suspend001; + * the debuggee program - nsk.jdi.VirtualMachine.suspend.suspend001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * The test was modified due to fix for the bug: + * 4623150 TEST_BUG: suspend001 test fails due to internal ping timeout + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.suspend.suspend001 + * nsk.jdi.VirtualMachine.suspend.suspend001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.suspend.suspend001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001a.java new file mode 100644 index 00000000000..20898633f44 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/suspend/suspend001a.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.suspend; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the suspend001 JDI test. + */ + +public class suspend001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> suspend001a: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> suspend001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.topLevelThreadGroups()
    + * complies with its specification.
    + *
    + * The test checks up that a List object returned by
    + * the method VirtualMachine.topLevelThreadGroups() contains
    + * only one element which type is ThreadGroupReference.
    + */ + +public class toplevelgroups001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new toplevelgroups001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.topLevelThreadGroups.toplevelgroups001a"; + + //String mName = "nsk.jdi.VirtualMachine.topLevelThreadGroups"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + List groupList = vm.topLevelThreadGroups(); + + log2("...... checking up groupList.size(); expected value == 1"); + int size = groupList.size(); + + if (size != 1) { + + log3("ERROR: groupList.size() != 1 : " + size); + testExitCode = FAILED; + + } else { + + log2("......checking up cast to ThreadGroupReference type"); + try { + String name = ((ThreadGroupReference) groupList.get(0)).name(); + log2(" groupName == " + name); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001/TestDescription.java new file mode 100644 index 00000000000..6a029487fa4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.topLevelThreadGroups() + * complies with its spec: + * public java.util.List topLevelThreadGroups() + * Returns each thread group which does not have a parent. + * For each top level thread group a ThreadGroupReference is + * placed in the returned list. + * This command may be used as the first step in building a tree (or trees) + * of the existing thread groups. + * Returns: a list of ThreadGroupReference objects, + * one for each top level thread group. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.topLevelThreadGroups.toplevelgroups001; + * the debuggee program - nsk.jdi.VirtualMachine.topLevelThreadGroups.toplevelgroups001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.topLevelThreadGroups.toplevelgroups001 + * nsk.jdi.VirtualMachine.topLevelThreadGroups.toplevelgroups001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.topLevelThreadGroups.toplevelgroups001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001a.java new file mode 100644 index 00000000000..0e69c9110d0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/topLevelThreadGroups/toplevelgroups001a.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.topLevelThreadGroups; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the toplevelgroups001 JDI test. + */ + +public class toplevelgroups001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachine.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachine.version()
    +** complies with its specification.
    + */ + +public class version001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachine/version/version001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new version001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachine.version.version001a"; + + //String mName = "nsk.jdi.VirtualMachine.version"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + String version = vm.version(); + if (version == null) { + log3("ERROR: version == null"); + expresult = returnCode1; + } else + log2(" version == " + version); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001/TestDescription.java new file mode 100644 index 00000000000..a2d41371010 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachine/version/version001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachine. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachine.version() + * complies with its spec: + * public java.lang.String version() + * Returns the version of the Java Runtime Environment in the target VM as + * reported by the property java.version. For obtaining the JDI interface + * version, use VirtualMachineManager.majorInterfaceVersion() and + * VirtualMachineManager.minorInterfaceVersion() + * Returns: the target VM version. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachine.version.version001; + * the debuggee program - nsk.jdi.VirtualMachine.version.version001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachine.version.version001 + * nsk.jdi.VirtualMachine.version.version001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachine.version.version001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001a.java new file mode 100644 index 00000000000..656ea1bb696 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/version/version001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachine.version; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the version001 JDI test. + */ + +public class version001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> version001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> version001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.allConnectors()
    + * complies with its specification.
    + *
    + * The test checks up that invoking the method
    + * VirtualMachineManager.allConnectors() doesn't throw
    + * an exception and returnes a List of non-null values of
    + * the Connector type each.
    + */ + +public class allconnectors001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/allConnectors/allconnectors001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new allconnectors001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + waitTime = argsHandler.getWaitTime(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......call to Bootstrap.virtualMachineManager()"); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + try { + log2("......call to vmm.allConnectors()"); + List connectors = vmm.allConnectors(); + log2(" size of List == " + connectors.size()); + + log2("......checking up on nulls and casts to Connector"); + ListIterator li = connectors.listIterator(); + for (; li.hasNext(); ) { + Connector connector = (Connector) li.next(); + if (connector == null) { + log3("ERROR: connector == null"); + testExitCode = FAILED; + } + } + } catch ( Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/allConnectors/allconnectors001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/allConnectors/allconnectors001/TestDescription.java new file mode 100644 index 00000000000..5c6e5195d25 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/allConnectors/allconnectors001/TestDescription.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/allConnectors/allconnectors001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.allConnectors() + * complies with its spec: + * public java.util.List allConnectors() + * Returns the list of all known Connector objects. + * Returns: a list of Connector objects. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.allConnectors.allconnectors001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.allConnectors.allconnectors001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001.java new file mode 100644 index 00000000000..e2c03af18c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.attachingConnectors; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * complies with its specification.
    + *
    + * The test checks up that invoking the method
    + * VirtualMachineManager.attachingConnectors() doesn't throw
    + * an exception and returnes a List of non-null values of
    + * the AttachingConnector type each.
    + */ + +public class attaching001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new attaching001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + waitTime = argsHandler.getWaitTime(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......call to Bootstrap.virtualMachineManager()"); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + try { + log2("......call to vmm.attachingConnectors()"); + List connectors = vmm.attachingConnectors(); + log2(" size of List == " + connectors.size()); + + log2("......checking up on nulls and casts to AttachingConnector"); + ListIterator li = connectors.listIterator(); + for (; li.hasNext(); ) { + AttachingConnector attachingConnector = (AttachingConnector) li.next(); + if (attachingConnector == null) { + log3("ERROR: attachingConnector == null"); + testExitCode = FAILED; + } + } + } catch ( Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001/TestDescription.java new file mode 100644 index 00000000000..7e8d5078a9a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/attachingConnectors/attaching001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.attachingConnectors() + * complies with its spec: + * public java.util.List attachingConnectors() + * Returns the list of known AttachingConnector objects. + * Any of the returned objects can be used to attach to + * an existing target VM and create a VirtualMachine mirror for it. + * Returns: a list of AttachingConnector objects. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.attachingConnectors.attaching001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.attachingConnectors.attaching001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001.java new file mode 100644 index 00000000000..a1ab73fefa4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001.java @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.connectedVirtualMachines; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +import java.net.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.connectedVirtualMachines()
    + * complies with its specification.
    + *
    + * Test case includes only one debuggee.
    + * The test checks up that :
    + * - after launching debugged Virtual Machine the tested method
    + * returns List containing one element of
    + * a VirtualMachine type which is equal to a mirror of
    + * the debuggee already got after launching;
    + * - after the deguggee normally ends via its exit() method,
    + * the call to the method returns an empty List.
    + */ + +public class convm001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new convm001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm001a"; + + //String mName = "nsk.jdi.VirtualMachineManager.connectedVirtualMachines"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + VirtualMachineManager vmm = null; + + List connectedVM; + VirtualMachine vm1 = null; + + int size = 0; + + + for (int i = 0; ; i++) { + + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......call to Bootstrap.virtualMachineManager()"); + + vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + log2("......call to vmm.connectedVirtualMachines()"); + connectedVM = vmm.connectedVirtualMachines(); + + size = connectedVM.size(); + if (size != 1) { + log3("ERROR: connectedVM.size() != 1 : " + size); + testExitCode = FAILED; + } else { + log2(" connectedVM.size() == 1"); + log2("......getting: VirtualMachine vm1 = connectedVM.get(0);"); + vm1 = (VirtualMachine) connectedVM.get(0); + + log2("......comparing: vm.equals(vm1)"); + if (!vm.equals(vm1)) { + log3("ERROR: !vm.equals(vm1)"); + testExitCode = FAILED; + } + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + + eventQueue = vm.eventQueue(); + eventSet = null; + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + + if (vmDisconnect() == 0 ) { + log2("......connectedVM = vmm.connectedVirtualMachines();"); + connectedVM = vmm.connectedVirtualMachines(); + + size = connectedVM.size(); + if (size != 0) { + log3("ERROR: connectedVM.size() != 0 : " + size); + testExitCode = FAILED; + + log2("......since a returned list is not empty"); + log2("......try to get first element and compare to the mirror of the vm tested"); + try { + log2(" getting: vm1 = (VirtualMachine) connectedVM.get(0);"); + vm1 = (VirtualMachine) connectedVM.get(0); + + log2(" vm.name()== " + vm1.name()); + if (vm.equals(vm1)) + log2("vm.equals(vm1)"); + else + log2("!vm.equals(vm1)"); + } catch ( Exception e ) { + log2("......failure because of Exception: " + e); + } + + } else + log2(" connectedVM.size() == 0"); + } else { + log3("ERROR: threadDeath != 0"); + testExitCode = FAILED; + } + + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + private int vmDisconnect () { + + int returnCode = returnCode0; + + log2(" waiting for VMDisconnectEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a ThreadDeathEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break ll; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + case 14: VMDisconnectEvent wmde = (VMDisconnectEvent) ev; + log2(" VMDisconnectEvent removed"); + break labelBP; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001/TestDescription.java new file mode 100644 index 00000000000..203a40f8573 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.connectedVirtualMachines() + * complies with its spec: + * public List connectedVirtualMachines() + * Lists all target VMs which are connected to the debugger. + * The list includes VirtualMachine instances for any + * target VMs which initiated a connection and any target VMs to which + * this manager has initiated a connection. + * A target VM will remain in this list until the VM is disconnected. + * VMDisconnectEvent is placed in the event queue after the VM is removed from the list. + * Returns: a list of VirtualMachine objects, each mirroring a target VM. + * The tested case includes normal VM termination. + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm001; + * the debuggee program - nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger forces debuggee to invoke method System.exit() to get debuggee's death + * and checks up on the list of connected VM. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - waiting for VMStartEvent was removed from the debugger part of the test + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm001 + * nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001a.java new file mode 100644 index 00000000000..f42467be496 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm001a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.connectedVirtualMachines; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the convm001 JDI test. + */ + +public class convm001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> convm001a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> convm001a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.connectedVirtualMachines()
    + * complies with its specification.
    + *
    + * Test case includes only one debuggee.
    + * The test checks up that :
    + * - after launching debugged Virtual Machine the tested method
    + * returns List containing one element of
    + * a VirtualMachine type which is equal to a mirror of
    + * the debuggee already got after launching;
    + * - after the degugger terminates the debuggee with the method
    + * VirtualMachine.exit(),
    + * the call to the method returns an empty List.
    + */ + +public class convm002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + + static final int FAILED = 2; + + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002 ", + sHeader2 = "--> debugger: ", sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main(String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new convm002().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = "nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm002a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static EventRequestManager eventRManager = null; + + static EventQueue eventQueue = null; + + static EventSet eventSet = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + + static final int returnCode1 = 1; + + static final int returnCode2 = 2; + + static final int returnCode3 = 3; + + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis(String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + VirtualMachineManager vmm = null; + + List connectedVM; + VirtualMachine vm1 = null; + + int size = 0; + + log2("......call to Bootstrap.virtualMachineManager()"); + + vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + log2("......call to vmm.connectedVirtualMachines()"); + connectedVM = vmm.connectedVirtualMachines(); + + size = connectedVM.size(); + if (size != 1) { + log3("ERROR: connectedVM.size() != 1 : " + size); + testExitCode = FAILED; + } else { + log2(" connectedVM.size() == 1"); + log2("......getting: VirtualMachine vm1 = connectedVM.get(0);"); + vm1 = (VirtualMachine) connectedVM.get(0); + + log2("......comparing: vm.equals(vm1)"); + if (!vm.equals(vm1)) { + log3("ERROR: !vm.equals(vm1)"); + testExitCode = FAILED; + } + } + } + + eventQueue = vm.eventQueue(); + eventSet = null; + + log2("......vm1.exit(" + (PASSED + PASS_BASE) + ")"); + vm1.exit(PASSED + PASS_BASE); + + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + status + " == PASS_BASE"); + } + + if (vmDisconnect() == 0) { + log2("......connectedVM = vmm.connectedVirtualMachines();"); + connectedVM = vmm.connectedVirtualMachines(); + + size = connectedVM.size(); + if (size != 0) { + log3("ERROR: connectedVM.size() != 0 : " + size); + testExitCode = FAILED; + + log2("......since a returned list is not empty"); + log2("......try to get first element and compare to the mirror of the vm tested"); + try { + log2(" getting: vm1 = (VirtualMachine) connectedVM.get(0);"); + vm1 = (VirtualMachine) connectedVM.get(0); + + log2(" vm.name()== " + vm1.name()); + if (vm.equals(vm1)) + log2("vm.equals(vm1)"); + else + log2("!vm.equals(vm1)"); + } catch (Exception e) { + log2("......failure because of Exception: " + e); + } + + } else + log2(" connectedVM.size() == 0"); + } else { + log3("ERROR: threadDeath != 0"); + testExitCode = FAILED; + } + + log1(" TESTING ENDS"); + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + private int vmDisconnect() { + + int returnCode = returnCode0; + + log2(" waiting for VMDisconnectEvent"); + + labelBP: for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime * 60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a ThreadDeathEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch (Exception e) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext();) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor = 0;; ifor++) { + + try { + switch (ifor) { + + case 0: + AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: + BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break ll; + case 2: + ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: + ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: + ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: + MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: + MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: + ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: + StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: + ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: + ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: + VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: + VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: + WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + case 14: + VMDisconnectEvent wmde = (VMDisconnectEvent) ev; + log2(" VMDisconnectEvent removed"); + break labelBP; + + default: + log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch (ClassCastException e) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002/TestDescription.java new file mode 100644 index 00000000000..5858253ddf4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.connectedVirtualMachines() + * complies with its spec: + * public List connectedVirtualMachines() + * Lists all target VMs which are connected to the debugger. + * The list includes VirtualMachine instances for any + * target VMs which initiated a connection and any target VMs to which + * this manager has initiated a connection. + * A target VM will remain in this list until the VM is disconnected. + * VMDisconnectEvent is placed in the event queue after the VM is removed from the list. + * Returns: a list of VirtualMachine objects, each mirroring a target VM. + * The tested case includes terminating a gebuggee by a debugger with + * the method VirtualMachine.exit(). + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm002; + * the debuggee program - nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls to the method VirtualMachine.exit() to get debuggee's death + * and checks up on the list of connected VM. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - waiting for VMStartEvent was removed from the debugger part of the test + * - waiting for debuggee VM exit was added after invocation of vm.exit() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm002 + * nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002a.java new file mode 100644 index 00000000000..f13f9232702 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm002a.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.connectedVirtualMachines; + +import nsk.share.Log; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the convm002 JDI test. + */ + +public class convm002a { + + static Log log; + + private static void log1(String message) { + log.display("**> convm002a: " + message); + } + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + + log = argHandler.createDebugeeLog(); + log1("debuggee started!"); + + // informing a debugger of readiness + IOPipe pipe = argHandler.createDebugeeIOPipe(); + pipe.println("ready"); + + /* + * In this test debugger kills debuggee using VirtualMachine.exit, so + * standard JDI tests communication protocol isn't used here + */ + try { + Thread.sleep(Long.MAX_VALUE); + } catch (Throwable t) { + // ignore all exceptions + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003.java new file mode 100644 index 00000000000..4b53a61d03e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003.java @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.connectedVirtualMachines; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.connectedVirtualMachines()
    + * complies with its specification.
    + *
    + * Test case includes only one debuggee.
    + * The test checks up that :
    + * - after launching debugged Virtual Machine the tested method
    + * returns List containing one element of
    + * a VirtualMachine type which is equal to a mirror of
    + * the debuggee already got after launching;
    + * - after a debugger invalidates the debuggee
    + * with the method VirtualMachine.dispose(),
    + * the call to the method returns an empty List.
    + */ + +public class convm003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new convm003().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm003a"; + + //String mName = "nsk.jdi.VirtualMachineManager.connectedVirtualMachines"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("issuspended002a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + VirtualMachineManager vmm = null; + + List connectedVM; + VirtualMachine vm1 = null; + + int size = 0; + + + //for (int i = 0; ; i++) { + + label0 : + { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break label0; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break label0; + } + + //log1("new checkready: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + log2("......call to Bootstrap.virtualMachineManager()"); + + vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + log2("......call to vmm.connectedVirtualMachines()"); + connectedVM = vmm.connectedVirtualMachines(); + + size = connectedVM.size(); + if (size != 1) { + log3("ERROR: connectedVM.size() != 1 : " + size); + testExitCode = FAILED; + } else { + log2(" connectedVM.size() == 1"); + log2("......getting: VirtualMachine vm1 = connectedVM.get(0);"); + vm1 = (VirtualMachine) connectedVM.get(0); + + log2("......comparing: vm.equals(vm1)"); + if (!vm.equals(vm1)) { + log3("ERROR: !vm.equals(vm1)"); + testExitCode = FAILED; + } + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + //log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + eventQueue = vm.eventQueue(); + eventSet = null; + + log2("......vm1.dispose()"); + vm1.dispose(); + + if (vmDisconnect() == 0 ) { + log2("......connectedVM = vmm.connectedVirtualMachines();"); + connectedVM = vmm.connectedVirtualMachines(); + + size = connectedVM.size(); + if (size != 0) { + log3("ERROR: connectedVM.size() != 0 : " + size); + testExitCode = FAILED; + + log2("......since a returned list is not empty"); + log2("......try to get first element and compare to the mirror of the vm tested"); + try { + log2(" getting: vm1 = (VirtualMachine) connectedVM.get(0);"); + vm1 = (VirtualMachine) connectedVM.get(0); + + log2(" vm.name()== " + vm1.name()); + if (vm.equals(vm1)) + log2("vm.equals(vm1)"); + else + log2("!vm.equals(vm1)"); + } catch ( Exception e ) { + log2("......failure because of Exception: " + e); + } + + } else + log2(" connectedVM.size() == 0"); + } else { + log3("ERROR: threadDeath != 0"); + testExitCode = FAILED; + } + + log1(" TESTING ENDS"); + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + private int vmDisconnect () { + + int returnCode = returnCode0; + + log2(" waiting for VMDisconnectEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a ThreadDeathEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break ll; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + case 14: VMDisconnectEvent wmde = (VMDisconnectEvent) ev; + log2(" VMDisconnectEvent removed"); + break labelBP; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003/TestDescription.java new file mode 100644 index 00000000000..0c4ad742862 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.connectedVirtualMachines() + * complies with its spec: + * public List connectedVirtualMachines() + * Lists all target VMs which are connected to the debugger. + * The list includes VirtualMachine instances for any + * target VMs which initiated a connection and any target VMs to which + * this manager has initiated a connection. + * A target VM will remain in this list until the VM is disconnected. + * VMDisconnectEvent is placed in the event queue after the VM is removed from the list. + * Returns: a list of VirtualMachine objects, each mirroring a target VM. + * The tested case includes invalidating a gebuggee by a debugger with + * the method VirtualMachine.dispose(). + * The test works as follows: + * The debugger program - nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm003; + * the debuggee program - nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls to the method VirtualMachine.exit() to get debuggee's death + * and checks up on the list of connected VM. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - waiting for VMStartEvent was removed from the debugger part of the test + * - waiting for debuggee VM exit was added after invocation of vm.dispose() + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm003 + * nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.connectedVirtualMachines.convm003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003a.java new file mode 100644 index 00000000000..e35533935aa --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/connectedVirtualMachines/convm003a.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.connectedVirtualMachines; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the convm003 JDI test. + */ + +public class convm003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + private static void log1(String message) { + if (verbMode) + System.err.println("**> convm003a: " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> convm003a: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002 test.
    + *
    + */ + +public class CreateVM002_TargetVM { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + + public static void main (String argv[]) { + System.exit(STATUS_PASSED + STATUS_TEMP); + } + + +} // end of CreateVM002_TargetVM class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM002_TranspServ.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM002_TranspServ.java new file mode 100644 index 00000000000..7ee86bf6f8a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM002_TranspServ.java @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.net.*; +import java.io.*; +import java.util.*; + +/* + * A transport service implementation based on a TCP connection used by + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002 test. + * It is borrowed from the com.sun.tools.jdi.SocketTransportService + */ + +public class CreateVM002_TranspServ extends TransportService { + + /** + * The listener returned by startListening encapsulates + * the ServerSocket. + */ + static class SocketListenKey extends ListenKey { + ServerSocket ss; + + SocketListenKey(ServerSocket ss) { + this.ss = ss; + } + + ServerSocket socket() { + return ss; + } + + public String address() { + InetAddress localaddr = ss.getInetAddress(); + int port = ss.getLocalPort(); + if (localaddr.isAnyLocalAddress()) { + return "" + port; + } else { + return localaddr + ":" + port; + } + } + + public String toString() { + return address(); + } + } + + /** + * Handshake with the debuggee + */ + void handshake(Socket s, long timeout) throws IOException { + s.setSoTimeout((int)timeout); + + byte[] hello = "JDWP-Handshake".getBytes("UTF-8"); + s.getOutputStream().write(hello); + + byte[] b = new byte[hello.length]; + int received = 0; + while (received < hello.length) { + int n; + try { + n = s.getInputStream().read(b, received, hello.length-received); + } catch (SocketTimeoutException x) { + throw new IOException("##> CreateVM002_TranspServ: Handshake timeout"); + } + if (n < 0) { + s.close(); + throw new IOException + ("##> CreateVM002_TranspServ: Handshake FAILED - connection prematurally closed!"); + } + received += n; + } + for (int i=0; i CreateVM002_TranspServ: Handshake FAILED - unrecognized message from target VM"); + } + } + + // disable read timeout + s.setSoTimeout(0); + } + + /** + * No-arg constructor + */ + public CreateVM002_TranspServ() { + } + + /** + * The name of this transport service + */ + public String name() { + return "CreateVM002_TranspServ"; + } + + /** + * The description of this transport service + */ + public String description() { + return "SocketTransportService for nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002 test."; + } + + /** + * Return the capabilities of this transport service + */ + public Capabilities capabilities() { + return new CreateVM002_TranspServCapabilities(); + } + + + /** + * Attach to the specified address with optional attach and handshake + * timeout. + */ + public Connection attach(String address, long attachTimeout, long handshakeTimeout) + throws IOException { + + if (address == null) { + throw new NullPointerException("##> CreateVM002_TranspServ: attach() - address is null"); + } + if (attachTimeout < 0 || handshakeTimeout < 0) { + throw new IllegalArgumentException("##> CreateVM002_TranspServ: attach() - timeout is negative"); + } + + int splitIndex = address.indexOf(':'); + String host; + String portStr; + if (splitIndex < 0) { + host = InetAddress.getLocalHost().getHostName(); + portStr = address; + } else { + host = address.substring(0, splitIndex); + portStr = address.substring(splitIndex+1); + } + + int port; + try { + port = Integer.decode(portStr).intValue(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "##> CreateVM002_TranspServ: attach() - unable to parse port number in address"); + } + + + // open TCP connection to VM + + InetSocketAddress sa = new InetSocketAddress(host, port); + Socket s = new Socket(); + try { + s.connect(sa, (int)attachTimeout); + } catch (SocketTimeoutException exc) { + try { + s.close(); + } catch (IOException x) { } + throw new TransportTimeoutException + ("##> CreateVM002_TranspServ: attach() - timed out trying to establish connection"); + } + + // handshake with the target VM + try { + handshake(s, handshakeTimeout); + } catch (IOException exc) { + try { + s.close(); + } catch (IOException x) { } + throw exc; + } + + return new CreateVM002_Connection(s); + } + + /* + * Listen on the specified address and port. Return a listener + * that encapsulates the ServerSocket. + */ + ListenKey startListening(String localaddress, int port) throws IOException { + InetSocketAddress sa; + if (localaddress == null) { + sa = new InetSocketAddress(port); + } else { + sa = new InetSocketAddress(localaddress, port); + } + ServerSocket ss = new ServerSocket(); + // if port is 0 do not set the SO_REUSEADDR flag + if (port == 0) { + ss.setReuseAddress(false); + } + ss.bind(sa); + return new SocketListenKey(ss); + } + + /** + * Listen on the specified address + */ + public ListenKey startListening(String address) throws IOException { + // use ephemeral port if address isn't specified. + if (address == null || address.length() == 0) { + address = "0"; + } + + int splitIndex = address.indexOf(':'); + String localaddr = null; + if (splitIndex >= 0) { + localaddr = address.substring(0, splitIndex); + address = address.substring(splitIndex+1); + } + + int port; + try { + port = Integer.decode(address).intValue(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "##> CreateVM002_TranspServ: startListening() - unable to parse port number in address"); + } + + return startListening(localaddr, port); + } + + /** + * Listen on the default address + */ + public ListenKey startListening() throws IOException { + return startListening(null, 0); + } + + /** + * Stop the listener + */ + public void stopListening(ListenKey listener) throws IOException { + if (!(listener instanceof SocketListenKey)) { + throw new IllegalArgumentException + ("##> CreateVM002_TranspServ: stopListening() - Invalid listener"); + } + + synchronized (listener) { + ServerSocket ss = ((SocketListenKey)listener).socket(); + + // if the ServerSocket has been closed it means + // the listener is invalid + if (ss.isClosed()) { + throw new IllegalArgumentException + ("##> CreateVM002_TranspServ: stopListening() - Invalid listener"); + } + ss.close(); + } + } + + /** + * Accept a connection from a debuggee and handshake with it. + */ + public Connection accept(ListenKey listener, long acceptTimeout, long handshakeTimeout) throws IOException { + if (acceptTimeout < 0 || handshakeTimeout < 0) { + throw new IllegalArgumentException + ("##> CreateVM002_TranspServ: accept() - timeout is negative"); + } + if (!(listener instanceof SocketListenKey)) { + throw new IllegalArgumentException + ("##> CreateVM002_TranspServ: accept() - Invalid listener"); + } + ServerSocket ss; + + // obtain the ServerSocket from the listener - if the + // socket is closed it means the listener is invalid + synchronized (listener) { + ss = ((SocketListenKey)listener).socket(); + if (ss.isClosed()) { + throw new IllegalArgumentException + ("##> CreateVM002_TranspServ: accept() - Invalid listener"); + } + } + + ss.setSoTimeout((int)acceptTimeout); + Socket s; + try { + s = ss.accept(); + } catch (SocketTimeoutException x) { + throw new TransportTimeoutException + ("##> CreateVM002_TranspServ: accept() - timeout waiting for connection"); + } + + // handshake here + handshake(s, handshakeTimeout); + + return new CreateVM002_Connection(s); + } + + public String toString() { + return name(); + } +} // end of CreateVM002_TranspServ class + +class CreateVM002_Connection extends Connection { + private Socket socket; + private boolean closed = false; + private OutputStream socketOutput; + private InputStream socketInput; + private Object receiveLock = new Object(); + private Object sendLock = new Object(); + private Object closeLock = new Object(); + private boolean toPrintPacket = false; + private int readPacketRequestNumber = 0; + private int writePacketRequestNumber = 0; + public boolean wasIOException = false; + + CreateVM002_Connection(Socket socket) throws IOException { + this.socket = socket; + socket.setTcpNoDelay(true); + socketInput = socket.getInputStream(); + socketOutput = socket.getOutputStream(); + } + + public void close() throws IOException { + synchronized (closeLock) { + if (closed) { + return; + } + socketOutput.close(); + socketInput.close(); + socket.close(); + closed = true; + } + } + + public boolean isOpen() { + synchronized (closeLock) { + return !closed; + } + } + + public byte[] readPacket() throws IOException { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM002_Connection: readPacket() - connection is closed: N1"); + } + synchronized (receiveLock) { + int b1,b2,b3,b4; + + // length + try { + b1 = socketInput.read(); + b2 = socketInput.read(); + b3 = socketInput.read(); + b4 = socketInput.read(); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM002_Connection: readPacket() - connection is closed: N2"); + } else { + throw ioe; + } + } + + if (b1<0 || b2<0 || b3<0 || b4<0) + throw new EOFException(); + + int len = ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0)); + + if (len < 0) { + throw new IOException + ("##> CreateVM002_Connection: readPacket() - protocol error: invalid Packet's length"); + } + + byte b[] = new byte[len]; + b[0] = (byte)b1; + b[1] = (byte)b2; + b[2] = (byte)b3; + b[3] = (byte)b4; + + int off = 4; + len -= off; + + while (len > 0) { + int count; + try { + count = socketInput.read(b, off, len); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM002_Connection: readPacket() - connection is closed: N3"); + } else { + throw ioe; + } + } + if (count < 0) { + throw new EOFException + ("##> CreateVM002_Connection: readPacket() - read() method returns negative value"); + } + len -= count; + off += count; + } + + readPacketRequestNumber++; + if ( readPacketRequestNumber == -1 ) { + throw new IOException + ("Dummy IOException in CreateVM002_Connection.readPacket(); readPacketRequestNumber = " + + readPacketRequestNumber); + } + printPacket("readPacket:", b); + return b; + } + } + + public void writePacket(byte b[]) throws IOException { + writePacketRequestNumber++; + if ( writePacketRequestNumber == 2 ) { + wasIOException = true; + throw new IOException + ("Dummy IOException in CreateVM002_Connection.writePacket(); writePacketRequestNumber = " + + writePacketRequestNumber); + } + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM002_Connection: writePacket() - connection is closed: N1"); + } + + printPacket("writePacket:", b); + + /* + * Check the packet size + */ + if (b.length < 11) { + throw new IllegalArgumentException + ("##> CreateVM002_Connection: writePacket() - packet is insufficient size: N1"); + } + int b0 = b[0] & 0xff; + int b1 = b[1] & 0xff; + int b2 = b[2] & 0xff; + int b3 = b[3] & 0xff; + int len = ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0)); + if (len < 11) { + throw new IllegalArgumentException + ("##> CreateVM002_Connection: writePacket() - packet is insufficient size: N2"); + } + + /* + * Check that the byte array contains the complete packet + */ + if (len > b.length) { + throw new IllegalArgumentException + ("##> CreateVM002_Connection: writePacket() - length mis-match"); + } + + synchronized (sendLock) { + try { + /* + * Send the packet (ignoring any bytes that follow + * the packet in the byte array). + */ + socketOutput.write(b, 0, len); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM002_Connection: writePacket() - connection is closed: N2"); + } else { + throw ioe; + } + } + } + } + + public void toPrintPacket(boolean toPrint) { + + if ( toPrintPacket ) { + if ( ! toPrint ) { + toPrintPacket = false; + System.out.println("\n>>>> CreateVM002_Connection: toPrintPacket - Off! " + + currentDateWithMlsecs()); + } + } else { + if ( toPrint ) { + toPrintPacket = true; + System.out.println("\n>>>> CreateVM002_Connection: toPrintPacket - On! " + + currentDateWithMlsecs()); + } + } + + } + + String currentDateWithMlsecs() { + GregorianCalendar calendar = new GregorianCalendar(); + int year = calendar.get(Calendar.YEAR); + int month = calendar.get(Calendar.MONTH) + 1; + String strMonth = month > 9 ? "" + month : "0" + month; + int day = calendar.get(Calendar.DAY_OF_MONTH); + String strDay = day > 9 ? "" + day : "0" + day; + int hours = calendar.get(Calendar.HOUR_OF_DAY); + String strHours = hours > 9 ? "" + hours : "0" + hours; + int minutes = calendar.get(Calendar.MINUTE); + String strMinutes = minutes > 9 ? "" + minutes : "0" + minutes; + int seconds = calendar.get(Calendar.SECOND); + String strSeconds = seconds > 9 ? "" + seconds : "0" + seconds; + int mlsecs = (int)(calendar.getTimeInMillis() % 1000); + String strMlsecs = mlsecs < 10 ? "00" + mlsecs : (mlsecs < 100 ? "0" + mlsecs : "" + mlsecs); + return "" + year + "." + strMonth + "." + strDay + "; " + strHours + + ":" + strMinutes + ":" + strSeconds + "::" + strMlsecs; + } + + public void printPacket(String headMessage, byte b[]) { + + if ( ! toPrintPacket ) { + return; + } + + System.out.println("\n>>>> CreateVM005_Connection: printPacket: " + currentDateWithMlsecs()); + System.out.println(" >> " + headMessage); + int packetLength = b.length; + + String handsHake = "JDWP-Handshake"; + + System.out.println(" >> packet length = " + packetLength); + if ( packetLength < 11 ) { + System.out.println(" >> Invalid packet length!"); + System.out.println("\n>>>> CreateVM005_Connection: printPacket - END\n"); + return; + } + + String packetString = new String(b); + if ( handsHake.equals(packetString) ) { + System.out.println(" >> Packet as String = " + packetString); + System.out.println("\n>>>> CreateVM005_Connection: printPacket - END\n"); + return; + } + + int b0 = b[0] & 0xff; + int b1 = b[1] & 0xff; + int b2 = b[2] & 0xff; + int b3 = b[3] & 0xff; + int lengthField = ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0)); + System.out.println(" >> lengthField = " + lengthField); + + int b4 = b[4] & 0xff; + int b5 = b[5] & 0xff; + int b6 = b[6] & 0xff; + int b7 = b[7] & 0xff; + int idField = ((b4 << 24) | (b5 << 16) | (b6 << 8) | (b7 << 0)); + System.out.println(" >> idField(integer) = " + idField); + + int flagsField = b[8] & 0xff; + System.out.println(" >> flagsField(integer) = " + flagsField); + int replyPacket = b[8] & 0x80; + if ( replyPacket != 0 ) { + System.out.println(" >> Replay Packet:"); + int b9 = b[9] & 0xff; + int b10 = b[10] & 0xff; + int errorCodeField = ((b9 << 8) | (b10 << 0)); + System.out.println(" >> errorCodeField(integer) = " + errorCodeField); + } else { + System.out.println(" >> Command Packet:"); + int commandSetField = b[9] & 0xff; + System.out.println(" >> commandSetField(integer) = " + commandSetField); + int commandField = b[10] & 0xff; + System.out.println(" >> commandField(integer) = " + commandField); + } + + if ( packetLength > 11 ) { + int dataLength = packetLength-11; + String data = ""; + for (int i=0; i < dataLength; i++) { + data = data + "," + (int)(b[11+i] & 0xff); + } + System.out.println(" >> Packet's data = " + data); + } + System.out.println(">>>> CreateVM005_Connection: printPacket - END"); + } + +} // end of CreateVM002_Connection class + +/* + * The capabilities of the socket transport service + */ +class CreateVM002_TranspServCapabilities extends TransportService.Capabilities { + + public boolean supportsMultipleConnections() { + return true; + } + + public boolean supportsAttachTimeout() { + return true; + } + + public boolean supportsAcceptTimeout() { + return true; + } + + public boolean supportsHandshakeTimeout() { + return true; + } + +} // end of CreateVM002_TranspServCapabilities class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM003_TargetVM.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM003_TargetVM.java new file mode 100644 index 00000000000..bad8453daba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM003_TargetVM.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + + +/** + * This is the target Java VM for the
    + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003 test.
    + *
    + */ + +public class CreateVM003_TargetVM { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + + public static void main (String argv[]) { + System.exit(STATUS_PASSED + STATUS_TEMP); + } + + +} // end of CreateVM003_TargetVM class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM003_TranspServ.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM003_TranspServ.java new file mode 100644 index 00000000000..771c48963af --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM003_TranspServ.java @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.net.*; +import java.io.*; +import java.util.*; + +/* + * A transport service implementation based on a TCP connection used by + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003 test. + * It is borrowed from the com.sun.tools.jdi.SocketTransportService + */ + +public class CreateVM003_TranspServ extends TransportService { + + /** + * The listener returned by startListening encapsulates + * the ServerSocket. + */ + static class SocketListenKey extends ListenKey { + ServerSocket ss; + + SocketListenKey(ServerSocket ss) { + this.ss = ss; + } + + ServerSocket socket() { + return ss; + } + + public String address() { + InetAddress localaddr = ss.getInetAddress(); + int port = ss.getLocalPort(); + if (localaddr.isAnyLocalAddress()) { + return "" + port; + } else { + return localaddr + ":" + port; + } + } + + public String toString() { + return address(); + } + } + + /** + * Handshake with the debuggee + */ + void handshake(Socket s, long timeout) throws IOException { + s.setSoTimeout((int)timeout); + + byte[] hello = "JDWP-Handshake".getBytes("UTF-8"); + s.getOutputStream().write(hello); + + byte[] b = new byte[hello.length]; + int received = 0; + while (received < hello.length) { + int n; + try { + n = s.getInputStream().read(b, received, hello.length-received); + } catch (SocketTimeoutException x) { + throw new IOException("##> CreateVM003_TranspServ: Handshake timeout"); + } + if (n < 0) { + s.close(); + throw new IOException + ("##> CreateVM003_TranspServ: Handshake FAILED - connection prematurally closed!"); + } + received += n; + } + for (int i=0; i CreateVM003_TranspServ: Handshake FAILED - unrecognized message from target VM"); + } + } + + // disable read timeout + s.setSoTimeout(0); + } + + /** + * No-arg constructor + */ + public CreateVM003_TranspServ() { + } + + /** + * The name of this transport service + */ + public String name() { + return "CreateVM003_TranspServ"; + } + + /** + * The description of this transport service + */ + public String description() { + return "SocketTransportService for nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003 test."; + } + + /** + * Return the capabilities of this transport service + */ + public Capabilities capabilities() { + return new CreateVM003_TranspServCapabilities(); + } + + + /** + * Attach to the specified address with optional attach and handshake + * timeout. + */ + public Connection attach(String address, long attachTimeout, long handshakeTimeout) + throws IOException { + + if (address == null) { + throw new NullPointerException("##> CreateVM003_TranspServ: attach() - address is null"); + } + if (attachTimeout < 0 || handshakeTimeout < 0) { + throw new IllegalArgumentException("##> CreateVM003_TranspServ: attach() - timeout is negative"); + } + + int splitIndex = address.indexOf(':'); + String host; + String portStr; + if (splitIndex < 0) { + host = InetAddress.getLocalHost().getHostName(); + portStr = address; + } else { + host = address.substring(0, splitIndex); + portStr = address.substring(splitIndex+1); + } + + int port; + try { + port = Integer.decode(portStr).intValue(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "##> CreateVM003_TranspServ: attach() - unable to parse port number in address"); + } + + + // open TCP connection to VM + + InetSocketAddress sa = new InetSocketAddress(host, port); + Socket s = new Socket(); + try { + s.connect(sa, (int)attachTimeout); + } catch (SocketTimeoutException exc) { + try { + s.close(); + } catch (IOException x) { } + throw new TransportTimeoutException + ("##> CreateVM003_TranspServ: attach() - timed out trying to establish connection"); + } + + // handshake with the target VM + try { + handshake(s, handshakeTimeout); + } catch (IOException exc) { + try { + s.close(); + } catch (IOException x) { } + throw exc; + } + + return new CreateVM003_Connection(s); + } + + /* + * Listen on the specified address and port. Return a listener + * that encapsulates the ServerSocket. + */ + ListenKey startListening(String localaddress, int port) throws IOException { + InetSocketAddress sa; + if (localaddress == null) { + sa = new InetSocketAddress(port); + } else { + sa = new InetSocketAddress(localaddress, port); + } + ServerSocket ss = new ServerSocket(); + // if port is 0 do not set the SO_REUSEADDR flag + if (port == 0) { + ss.setReuseAddress(false); + } + ss.bind(sa); + return new SocketListenKey(ss); + } + + /** + * Listen on the specified address + */ + public ListenKey startListening(String address) throws IOException { + // use ephemeral port if address isn't specified. + if (address == null || address.length() == 0) { + address = "0"; + } + + int splitIndex = address.indexOf(':'); + String localaddr = null; + if (splitIndex >= 0) { + localaddr = address.substring(0, splitIndex); + address = address.substring(splitIndex+1); + } + + int port; + try { + port = Integer.decode(address).intValue(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "##> CreateVM003_TranspServ: startListening() - unable to parse port number in address"); + } + + return startListening(localaddr, port); + } + + /** + * Listen on the default address + */ + public ListenKey startListening() throws IOException { + return startListening(null, 0); + } + + /** + * Stop the listener + */ + public void stopListening(ListenKey listener) throws IOException { + if (!(listener instanceof SocketListenKey)) { + throw new IllegalArgumentException + ("##> CreateVM003_TranspServ: stopListening() - Invalid listener"); + } + + synchronized (listener) { + ServerSocket ss = ((SocketListenKey)listener).socket(); + + // if the ServerSocket has been closed it means + // the listener is invalid + if (ss.isClosed()) { + throw new IllegalArgumentException + ("##> CreateVM003_TranspServ: stopListening() - Invalid listener"); + } + ss.close(); + } + } + + /** + * Accept a connection from a debuggee and handshake with it. + */ + public Connection accept(ListenKey listener, long acceptTimeout, long handshakeTimeout) throws IOException { + if (acceptTimeout < 0 || handshakeTimeout < 0) { + throw new IllegalArgumentException + ("##> CreateVM003_TranspServ: accept() - timeout is negative"); + } + if (!(listener instanceof SocketListenKey)) { + throw new IllegalArgumentException + ("##> CreateVM003_TranspServ: accept() - Invalid listener"); + } + ServerSocket ss; + + // obtain the ServerSocket from the listener - if the + // socket is closed it means the listener is invalid + synchronized (listener) { + ss = ((SocketListenKey)listener).socket(); + if (ss.isClosed()) { + throw new IllegalArgumentException + ("##> CreateVM003_TranspServ: accept() - Invalid listener"); + } + } + + ss.setSoTimeout((int)acceptTimeout); + Socket s; + try { + s = ss.accept(); + } catch (SocketTimeoutException x) { + throw new TransportTimeoutException + ("##> CreateVM003_TranspServ: accept() - timeout waiting for connection"); + } + + // handshake here + handshake(s, handshakeTimeout); + + return new CreateVM003_Connection(s); + } + + public String toString() { + return name(); + } +} // end of CreateVM003_TranspServ class + +class CreateVM003_Connection extends Connection { + private Socket socket; + private boolean closed = false; + private OutputStream socketOutput; + private InputStream socketInput; + private Object receiveLock = new Object(); + private Object sendLock = new Object(); + private Object closeLock = new Object(); + + CreateVM003_Connection(Socket socket) throws IOException { + this.socket = socket; + socket.setTcpNoDelay(true); + socketInput = socket.getInputStream(); + socketOutput = socket.getOutputStream(); + } + + public void close() throws IOException { + synchronized (closeLock) { + if (closed) { + return; + } + socketOutput.close(); + socketInput.close(); + socket.close(); + closed = true; + } + } + + public boolean isOpen() { + synchronized (closeLock) { + return !closed; + } + } + + public byte[] readPacket() throws IOException { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM003_Connection: readPacket() - connection is closed"); + } + synchronized (receiveLock) { + int b1,b2,b3,b4; + + // length + try { + b1 = socketInput.read(); + b2 = socketInput.read(); + b3 = socketInput.read(); + b4 = socketInput.read(); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM003_Connection: readPacket() - connection is closed"); + } else { + throw ioe; + } + } + + if (b1<0 || b2<0 || b3<0 || b4<0) + throw new EOFException(); + + int len = ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0)); + + if (len < 0) { + throw new IOException + ("##> CreateVM003_Connection: readPacket() - protocol error: invalid Packet's length"); + } + + byte b[] = new byte[len]; + b[0] = (byte)b1; + b[1] = (byte)b2; + b[2] = (byte)b3; + b[3] = (byte)b4; + + int off = 4; + len -= off; + + while (len > 0) { + int count; + try { + count = socketInput.read(b, off, len); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM003_Connection: readPacket() - connection is closed"); + } else { + throw ioe; + } + } + if (count < 0) { + throw new EOFException + ("##> CreateVM003_Connection: readPacket() - read() method returns negative value"); + } + len -= count; + off += count; + } + + return b; + } + } + + public void writePacket(byte b[]) throws IOException { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM003_Connection: writePacket() - connection is closed"); + } + + /* + * Check the packet size + */ + if (b.length < 11) { + throw new IllegalArgumentException + ("##> CreateVM003_Connection: writePacket() - packet is insufficient size"); + } + int b0 = b[0] & 0xff; + int b1 = b[1] & 0xff; + int b2 = b[2] & 0xff; + int b3 = b[3] & 0xff; + int len = ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0)); + if (len < 11) { + throw new IllegalArgumentException + ("##> CreateVM003_Connection: writePacket() - packet is insufficient size"); + } + + /* + * Check that the byte array contains the complete packet + */ + if (len > b.length) { + throw new IllegalArgumentException + ("##> CreateVM003_Connection: writePacket() - length mis-match"); + } + + synchronized (sendLock) { + try { + /* + * Send the packet (ignoring any bytes that follow + * the packet in the byte array). + */ + socketOutput.write(b, 0, len); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM003_Connection: writePacket() - connection is closed"); + } else { + throw ioe; + } + } + } + } + +} // end of CreateVM003_Connection class + +/* + * The capabilities of the socket transport service + */ +class CreateVM003_TranspServCapabilities extends TransportService.Capabilities { + + public boolean supportsMultipleConnections() { + return true; + } + + public boolean supportsAttachTimeout() { + return true; + } + + public boolean supportsAcceptTimeout() { + return true; + } + + public boolean supportsHandshakeTimeout() { + return true; + } + +} // end of CreateVM003_TranspServCapabilities class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM004_TargetVM.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM004_TargetVM.java new file mode 100644 index 00000000000..34f056de81d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM004_TargetVM.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + + +/** + * This is the target Java VM for the
    + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004 test.
    + *
    + */ + +public class CreateVM004_TargetVM { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + + public static void main (String argv[]) { + System.exit(STATUS_PASSED + STATUS_TEMP); + } + + +} // end of CreateVM004_TargetVM class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM004_TranspServ.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM004_TranspServ.java new file mode 100644 index 00000000000..bbed62c3bfd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM004_TranspServ.java @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.net.*; +import java.io.*; +import java.util.*; + +/* + * A transport service implementation based on a TCP connection used by + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004 test. + * It is borrowed from the com.sun.tools.jdi.SocketTransportService + */ + +public class CreateVM004_TranspServ extends TransportService { + + /** + * The listener returned by startListening encapsulates + * the ServerSocket. + */ + static class SocketListenKey extends ListenKey { + ServerSocket ss; + + SocketListenKey(ServerSocket ss) { + this.ss = ss; + } + + ServerSocket socket() { + return ss; + } + + public String address() { + InetAddress localaddr = ss.getInetAddress(); + int port = ss.getLocalPort(); + if (localaddr.isAnyLocalAddress()) { + return "" + port; + } else { + return localaddr + ":" + port; + } + } + + public String toString() { + return address(); + } + } + + /** + * Handshake with the debuggee + */ + void handshake(Socket s, long timeout) throws IOException { + s.setSoTimeout((int)timeout); + + byte[] hello = "JDWP-Handshake".getBytes("UTF-8"); + s.getOutputStream().write(hello); + + byte[] b = new byte[hello.length]; + int received = 0; + while (received < hello.length) { + int n; + try { + n = s.getInputStream().read(b, received, hello.length-received); + } catch (SocketTimeoutException x) { + throw new IOException("##> CreateVM004_TranspServ: Handshake timeout"); + } + if (n < 0) { + s.close(); + throw new IOException + ("##> CreateVM004_TranspServ: Handshake FAILED - connection prematurally closed!"); + } + received += n; + } + for (int i=0; i CreateVM004_TranspServ: Handshake FAILED - unrecognized message from target VM"); + } + } + + // disable read timeout + s.setSoTimeout(0); + } + + /** + * No-arg constructor + */ + public CreateVM004_TranspServ() { + } + + /** + * The name of this transport service + */ + public String name() { + return "CreateVM004_TranspServ"; + } + + /** + * The description of this transport service + */ + public String description() { + return "SocketTransportService for nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004 test."; + } + + /** + * Return the capabilities of this transport service + */ + public Capabilities capabilities() { + return new CreateVM004_TranspServCapabilities(); + } + + + /** + * Attach to the specified address with optional attach and handshake + * timeout. + */ + public Connection attach(String address, long attachTimeout, long handshakeTimeout) + throws IOException { + + if (address == null) { + throw new NullPointerException("##> CreateVM004_TranspServ: attach() - address is null"); + } + if (attachTimeout < 0 || handshakeTimeout < 0) { + throw new IllegalArgumentException("##> CreateVM004_TranspServ: attach() - timeout is negative"); + } + + int splitIndex = address.indexOf(':'); + String host; + String portStr; + if (splitIndex < 0) { + host = InetAddress.getLocalHost().getHostName(); + portStr = address; + } else { + host = address.substring(0, splitIndex); + portStr = address.substring(splitIndex+1); + } + + int port; + try { + port = Integer.decode(portStr).intValue(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "##> CreateVM004_TranspServ: attach() - unable to parse port number in address"); + } + + + // open TCP connection to VM + + InetSocketAddress sa = new InetSocketAddress(host, port); + Socket s = new Socket(); + try { + s.connect(sa, (int)attachTimeout); + } catch (SocketTimeoutException exc) { + try { + s.close(); + } catch (IOException x) { } + throw new TransportTimeoutException + ("##> CreateVM004_TranspServ: attach() - timed out trying to establish connection"); + } + + // handshake with the target VM + try { + handshake(s, handshakeTimeout); + } catch (IOException exc) { + try { + s.close(); + } catch (IOException x) { } + throw exc; + } + + return new CreateVM004_Connection(s); + } + + /* + * Listen on the specified address and port. Return a listener + * that encapsulates the ServerSocket. + */ + ListenKey startListening(String localaddress, int port) throws IOException { + InetSocketAddress sa; + if (localaddress == null) { + sa = new InetSocketAddress(port); + } else { + sa = new InetSocketAddress(localaddress, port); + } + ServerSocket ss = new ServerSocket(); + // if port is 0 do not set the SO_REUSEADDR flag + if (port == 0) { + ss.setReuseAddress(false); + } + ss.bind(sa); + return new SocketListenKey(ss); + } + + /** + * Listen on the specified address + */ + public ListenKey startListening(String address) throws IOException { + // use ephemeral port if address isn't specified. + if (address == null || address.length() == 0) { + address = "0"; + } + + int splitIndex = address.indexOf(':'); + String localaddr = null; + if (splitIndex >= 0) { + localaddr = address.substring(0, splitIndex); + address = address.substring(splitIndex+1); + } + + int port; + try { + port = Integer.decode(address).intValue(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "##> CreateVM004_TranspServ: startListening() - unable to parse port number in address"); + } + + return startListening(localaddr, port); + } + + /** + * Listen on the default address + */ + public ListenKey startListening() throws IOException { + return startListening(null, 0); + } + + /** + * Stop the listener + */ + public void stopListening(ListenKey listener) throws IOException { + if (!(listener instanceof SocketListenKey)) { + throw new IllegalArgumentException + ("##> CreateVM004_TranspServ: stopListening() - Invalid listener"); + } + + synchronized (listener) { + ServerSocket ss = ((SocketListenKey)listener).socket(); + + // if the ServerSocket has been closed it means + // the listener is invalid + if (ss.isClosed()) { + throw new IllegalArgumentException + ("##> CreateVM004_TranspServ: stopListening() - Invalid listener"); + } + ss.close(); + } + } + + /** + * Accept a connection from a debuggee and handshake with it. + */ + public Connection accept(ListenKey listener, long acceptTimeout, long handshakeTimeout) throws IOException { + if (acceptTimeout < 0 || handshakeTimeout < 0) { + throw new IllegalArgumentException + ("##> CreateVM004_TranspServ: accept() - timeout is negative"); + } + if (!(listener instanceof SocketListenKey)) { + throw new IllegalArgumentException + ("##> CreateVM004_TranspServ: accept() - Invalid listener"); + } + ServerSocket ss; + + // obtain the ServerSocket from the listener - if the + // socket is closed it means the listener is invalid + synchronized (listener) { + ss = ((SocketListenKey)listener).socket(); + if (ss.isClosed()) { + throw new IllegalArgumentException + ("##> CreateVM004_TranspServ: accept() - Invalid listener"); + } + } + + ss.setSoTimeout((int)acceptTimeout); + Socket s; + try { + s = ss.accept(); + } catch (SocketTimeoutException x) { + throw new TransportTimeoutException + ("##> CreateVM004_TranspServ: accept() - timeout waiting for connection"); + } + + // handshake here + handshake(s, handshakeTimeout); + + return new CreateVM004_Connection(s); + } + + public String toString() { + return name(); + } +} // end of CreateVM004_TranspServ class + +class CreateVM004_Connection extends Connection { + private Socket socket; + private boolean closed = false; + private OutputStream socketOutput; + private InputStream socketInput; + private Object receiveLock = new Object(); + private Object sendLock = new Object(); + private Object closeLock = new Object(); + + CreateVM004_Connection(Socket socket) throws IOException { + this.socket = socket; + socket.setTcpNoDelay(true); + socketInput = socket.getInputStream(); + socketOutput = socket.getOutputStream(); + } + + public void close() throws IOException { + synchronized (closeLock) { + if (closed) { + return; + } + socketOutput.close(); + socketInput.close(); + socket.close(); + closed = true; + } + } + + public boolean isOpen() { + synchronized (closeLock) { + return !closed; + } + } + + public byte[] readPacket() throws IOException { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM004_Connection: readPacket() - connection is closed"); + } + synchronized (receiveLock) { + int b1,b2,b3,b4; + + // length + try { + b1 = socketInput.read(); + b2 = socketInput.read(); + b3 = socketInput.read(); + b4 = socketInput.read(); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM004_Connection: readPacket() - connection is closed"); + } else { + throw ioe; + } + } + + if (b1<0 || b2<0 || b3<0 || b4<0) + throw new EOFException(); + + int len = ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0)); + + if (len < 0) { + throw new IOException + ("##> CreateVM004_Connection: readPacket() - protocol error: invalid Packet's length"); + } + + byte b[] = new byte[len]; + b[0] = (byte)b1; + b[1] = (byte)b2; + b[2] = (byte)b3; + b[3] = (byte)b4; + + int off = 4; + len -= off; + + while (len > 0) { + int count; + try { + count = socketInput.read(b, off, len); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM004_Connection: readPacket() - connection is closed"); + } else { + throw ioe; + } + } + if (count < 0) { + throw new EOFException + ("##> CreateVM004_Connection: readPacket() - read() method returns negative value"); + } + len -= count; + off += count; + } + + return b; + } + } + + public void writePacket(byte b[]) throws IOException { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM004_Connection: writePacket() - connection is closed"); + } + + /* + * Check the packet size + */ + if (b.length < 11) { + throw new IllegalArgumentException + ("##> CreateVM004_Connection: writePacket() - packet is insufficient size"); + } + int b0 = b[0] & 0xff; + int b1 = b[1] & 0xff; + int b2 = b[2] & 0xff; + int b3 = b[3] & 0xff; + int len = ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0)); + if (len < 11) { + throw new IllegalArgumentException + ("##> CreateVM004_Connection: writePacket() - packet is insufficient size"); + } + + /* + * Check that the byte array contains the complete packet + */ + if (len > b.length) { + throw new IllegalArgumentException + ("##> CreateVM004_Connection: writePacket() - length mis-match"); + } + + synchronized (sendLock) { + try { + /* + * Send the packet (ignoring any bytes that follow + * the packet in the byte array). + */ + socketOutput.write(b, 0, len); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM004_Connection: writePacket() - connection is closed"); + } else { + throw ioe; + } + } + } + } + +} // end of CreateVM004_Connection class + + +/* + * The capabilities of the socket transport service + */ +class CreateVM004_TranspServCapabilities extends TransportService.Capabilities { + + public boolean supportsMultipleConnections() { + return true; + } + + public boolean supportsAttachTimeout() { + return true; + } + + public boolean supportsAcceptTimeout() { + return true; + } + + public boolean supportsHandshakeTimeout() { + return true; + } + +} // end of CreateVM004_TranspServCapabilities class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM005_TargetVM.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM005_TargetVM.java new file mode 100644 index 00000000000..c69cd901c1d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM005_TargetVM.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + + +/** + * This is the target Java VM for the
    + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005 test.
    + *
    + */ + +public class CreateVM005_TargetVM { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + + public static void main (String argv[]) { + System.exit(STATUS_PASSED + STATUS_TEMP); + } + + +} // end of CreateVM005_TargetVM class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM005_TranspServ.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM005_TranspServ.java new file mode 100644 index 00000000000..7a45c16e6b9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/CreateVM005_TranspServ.java @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.net.*; +import java.io.*; +import java.util.*; + +/* + * A transport service implementation based on a TCP connection used by + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005 test. + * It is borrowed from the com.sun.tools.jdi.SocketTransportService + */ + +public class CreateVM005_TranspServ extends TransportService { + + /** + * The listener returned by startListening encapsulates + * the ServerSocket. + */ + static class SocketListenKey extends ListenKey { + ServerSocket ss; + + SocketListenKey(ServerSocket ss) { + this.ss = ss; + } + + ServerSocket socket() { + return ss; + } + + public String address() { + InetAddress localaddr = ss.getInetAddress(); + int port = ss.getLocalPort(); + if (localaddr.isAnyLocalAddress()) { + return "" + port; + } else { + return localaddr + ":" + port; + } + } + + public String toString() { + return address(); + } + } + + /** + * Handshake with the debuggee + */ + void handshake(Socket s, long timeout) throws IOException { + s.setSoTimeout((int)timeout); + + byte[] hello = "JDWP-Handshake".getBytes("UTF-8"); + s.getOutputStream().write(hello); + + byte[] b = new byte[hello.length]; + int received = 0; + while (received < hello.length) { + int n; + try { + n = s.getInputStream().read(b, received, hello.length-received); + } catch (SocketTimeoutException x) { + throw new IOException("##> CreateVM005_TranspServ: Handshake timeout"); + } + if (n < 0) { + s.close(); + throw new IOException + ("##> CreateVM005_TranspServ: Handshake FAILED - connection prematurally closed!"); + } + received += n; + } + for (int i=0; i CreateVM005_TranspServ: Handshake FAILED - unrecognized message from target VM"); + } + } + + // disable read timeout + s.setSoTimeout(0); + } + + /** + * No-arg constructor + */ + public CreateVM005_TranspServ() { + } + + /** + * The name of this transport service + */ + public String name() { + return "CreateVM005_TranspServ"; + } + + /** + * The description of this transport service + */ + public String description() { + return "SocketTransportService for nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005 test."; + } + + /** + * Return the capabilities of this transport service + */ + public Capabilities capabilities() { + return new CreateVM005_TranspServCapabilities(); + } + + + /** + * Attach to the specified address with optional attach and handshake + * timeout. + */ + public Connection attach(String address, long attachTimeout, long handshakeTimeout) + throws IOException { + + if (address == null) { + throw new NullPointerException("##> CreateVM005_TranspServ: attach() - address is null"); + } + if (attachTimeout < 0 || handshakeTimeout < 0) { + throw new IllegalArgumentException("##> CreateVM005_TranspServ: attach() - timeout is negative"); + } + + int splitIndex = address.indexOf(':'); + String host; + String portStr; + if (splitIndex < 0) { + host = InetAddress.getLocalHost().getHostName(); + portStr = address; + } else { + host = address.substring(0, splitIndex); + portStr = address.substring(splitIndex+1); + } + + int port; + try { + port = Integer.decode(portStr).intValue(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "##> CreateVM005_TranspServ: attach() - unable to parse port number in address"); + } + + + // open TCP connection to VM + + InetSocketAddress sa = new InetSocketAddress(host, port); + Socket s = new Socket(); + try { + s.connect(sa, (int)attachTimeout); + } catch (SocketTimeoutException exc) { + try { + s.close(); + } catch (IOException x) { } + throw new TransportTimeoutException + ("##> CreateVM005_TranspServ: attach() - timed out trying to establish connection"); + } + + // handshake with the target VM + try { + handshake(s, handshakeTimeout); + } catch (IOException exc) { + try { + s.close(); + } catch (IOException x) { } + throw exc; + } + + return new CreateVM005_Connection(s); + } + + /* + * Listen on the specified address and port. Return a listener + * that encapsulates the ServerSocket. + */ + ListenKey startListening(String localaddress, int port) throws IOException { + InetSocketAddress sa; + if (localaddress == null) { + sa = new InetSocketAddress(port); + } else { + sa = new InetSocketAddress(localaddress, port); + } + ServerSocket ss = new ServerSocket(); + // if port is 0 do not set the SO_REUSEADDR flag + if (port == 0) { + ss.setReuseAddress(false); + } + ss.bind(sa); + return new SocketListenKey(ss); + } + + /** + * Listen on the specified address + */ + public ListenKey startListening(String address) throws IOException { + // use ephemeral port if address isn't specified. + if (address == null || address.length() == 0) { + address = "0"; + } + + int splitIndex = address.indexOf(':'); + String localaddr = null; + if (splitIndex >= 0) { + localaddr = address.substring(0, splitIndex); + address = address.substring(splitIndex+1); + } + + int port; + try { + port = Integer.decode(address).intValue(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "##> CreateVM005_TranspServ: startListening() - unable to parse port number in address"); + } + + return startListening(localaddr, port); + } + + /** + * Listen on the default address + */ + public ListenKey startListening() throws IOException { + return startListening(null, 0); + } + + /** + * Stop the listener + */ + public void stopListening(ListenKey listener) throws IOException { + if (!(listener instanceof SocketListenKey)) { + throw new IllegalArgumentException + ("##> CreateVM005_TranspServ: stopListening() - Invalid listener"); + } + + synchronized (listener) { + ServerSocket ss = ((SocketListenKey)listener).socket(); + + // if the ServerSocket has been closed it means + // the listener is invalid + if (ss.isClosed()) { + throw new IllegalArgumentException + ("##> CreateVM005_TranspServ: stopListening() - Invalid listener"); + } + ss.close(); + } + } + + /** + * Accept a connection from a debuggee and handshake with it. + */ + public Connection accept(ListenKey listener, long acceptTimeout, long handshakeTimeout) throws IOException { + if (acceptTimeout < 0 || handshakeTimeout < 0) { + throw new IllegalArgumentException + ("##> CreateVM005_TranspServ: accept() - timeout is negative"); + } + if (!(listener instanceof SocketListenKey)) { + throw new IllegalArgumentException + ("##> CreateVM005_TranspServ: accept() - Invalid listener"); + } + ServerSocket ss; + + // obtain the ServerSocket from the listener - if the + // socket is closed it means the listener is invalid + synchronized (listener) { + ss = ((SocketListenKey)listener).socket(); + if (ss.isClosed()) { + throw new IllegalArgumentException + ("##> CreateVM005_TranspServ: accept() - Invalid listener"); + } + } + + ss.setSoTimeout((int)acceptTimeout); + Socket s; + try { + s = ss.accept(); + } catch (SocketTimeoutException x) { + throw new TransportTimeoutException + ("##> CreateVM005_TranspServ: accept() - timeout waiting for connection"); + } + + // handshake here + handshake(s, handshakeTimeout); + + return new CreateVM005_Connection(s); + } + + public String toString() { + return name(); + } +} // end of CreateVM005_TranspServ class + +class CreateVM005_Connection extends Connection { + private Socket socket; + private boolean closed = false; + private OutputStream socketOutput; + private InputStream socketInput; + private Object receiveLock = new Object(); + private Object sendLock = new Object(); + private Object closeLock = new Object(); + + CreateVM005_Connection(Socket socket) throws IOException { + this.socket = socket; + socket.setTcpNoDelay(true); + socketInput = socket.getInputStream(); + socketOutput = socket.getOutputStream(); + } + + public void close() throws IOException { + synchronized (closeLock) { + if (closed) { + return; + } + socketOutput.close(); + socketInput.close(); + socket.close(); + closed = true; + } + } + + public boolean isOpen() { + synchronized (closeLock) { + return !closed; + } + } + + public byte[] readPacket() throws IOException { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM005_Connection: readPacket() - connection is closed"); + } + synchronized (receiveLock) { + int b1,b2,b3,b4; + + // length + try { + b1 = socketInput.read(); + b2 = socketInput.read(); + b3 = socketInput.read(); + b4 = socketInput.read(); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM005_Connection: readPacket() - connection is closed"); + } else { + throw ioe; + } + } + + if (b1<0 || b2<0 || b3<0 || b4<0) + throw new EOFException(); + + int len = ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0)); + + if (len < 0) { + throw new IOException + ("##> CreateVM005_Connection: readPacket() - protocol error: invalid Packet's length"); + } + + byte b[] = new byte[len]; + b[0] = (byte)b1; + b[1] = (byte)b2; + b[2] = (byte)b3; + b[3] = (byte)b4; + + int off = 4; + len -= off; + + while (len > 0) { + int count; + try { + count = socketInput.read(b, off, len); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM005_Connection: readPacket() - connection is closed"); + } else { + throw ioe; + } + } + if (count < 0) { + throw new EOFException + ("##> CreateVM005_Connection: readPacket() - read() method returns negative value"); + } + len -= count; + off += count; + } + + return b; + } + } + + public void writePacket(byte b[]) throws IOException { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM005_Connection: writePacket() - connection is closed"); + } + + /* + * Check the packet size + */ + if (b.length < 11) { + throw new IllegalArgumentException + ("##> CreateVM005_Connection: writePacket() - packet is insufficient size"); + } + int b0 = b[0] & 0xff; + int b1 = b[1] & 0xff; + int b2 = b[2] & 0xff; + int b3 = b[3] & 0xff; + int len = ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0)); + if (len < 11) { + throw new IllegalArgumentException + ("##> CreateVM005_Connection: writePacket() - packet is insufficient size"); + } + + /* + * Check that the byte array contains the complete packet + */ + if (len > b.length) { + throw new IllegalArgumentException + ("##> CreateVM005_Connection: writePacket() - length mis-match"); + } + + synchronized (sendLock) { + try { + /* + * Send the packet (ignoring any bytes that follow + * the packet in the byte array). + */ + socketOutput.write(b, 0, len); + } catch (IOException ioe) { + if (!isOpen()) { + throw new ClosedConnectionException + ("##> CreateVM005_Connection: writePacket() - connection is closed"); + } else { + throw ioe; + } + } + } + } + +} // end of CreateVM005_Connection class + +/* + * The capabilities of the socket transport service + */ +class CreateVM005_TranspServCapabilities extends TransportService.Capabilities { + + public boolean supportsMultipleConnections() { + return true; + } + + public boolean supportsAttachTimeout() { + return true; + } + + public boolean supportsAcceptTimeout() { + return true; + } + + public boolean supportsHandshakeTimeout() { + return true; + } + +} // end of CreateVM005_TranspServCapabilities class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001.java new file mode 100644 index 00000000000..4a30f01fe58 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the
    + * virtualMachineManager.createVirtualMachine(...) methods.
    + *
    + * The test checks up that both createVirtualMachine(Connection) and
    + * createVirtualMachine(Connection, Process) methods throw
    + * IllegalStateException if the used Connection is not open.
    + *
    + */ + +public class createVM001 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "createVM001: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> createVM001: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new createVM001().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + logHandler.enableErrorsSummary(false); + + logAlways("==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001 test..."); + logOnVerbose + ("==> Test checks that virtualMachineManager.createVirtualMachine(...) methods"); + logOnVerbose + ("==> throw IllegalStateException for Connection that is not open."); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + // check method virtualMachineManager.createVirtualMachine(Connection)... + Connection testConnection = new createVM001_Connection(); + try { + VirtualMachine dummyVM = virtualMachineManager.createVirtualMachine(testConnection); + } catch ( IllegalStateException illegStExcep ) { + // OK - expected IllegalStateException because Connection is not open + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "virtualMachineManager.createVirtualMachine(Connection) throws"); + logOnError(errorLogPrefix + "unexpected Exception for Connection that is not open:"); + logOnError(errorLogPrefix + "Expected Exception - IllegalStateException"); + logOnError(errorLogPrefix + "Actual Exception - '" + thrown + "'"); + testResult = STATUS_FAILED; + } + + // check method virtualMachineManager.createVirtualMachine(Connection, Process)... + testConnection = new createVM001_Connection(); + Process dummyProcess = new createVM001_Process(); + try { + VirtualMachine dummyVM = virtualMachineManager.createVirtualMachine(testConnection, dummyProcess); + } catch ( IllegalStateException illegStExcep ) { + // OK - expected IllegalStateException because Connection is not open + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "virtualMachineManager.createVirtualMachine(Connection, Process)"); + logOnError(errorLogPrefix + "throws unexpected Exception for Connection that is not open:"); + logOnError(errorLogPrefix + "Expected Exception - IllegalStateException"); + logOnError(errorLogPrefix + "Actual Exception - '" + thrown + "'"); + testResult = STATUS_FAILED; + } + + return testResult; + } + +} // end of createVM001 class + +class createVM001_Connection extends Connection { + + public void close() throws IOException { + if ( true ) { + throw new IOException("Dummy IOException in createVM001_Connection.close()."); + } + } + + public boolean isOpen() { + return false; + } + + public byte[] readPacket() throws IOException { + if ( true ) { + throw new IOException("Dummy IOException in createVM001_Connection.readPacket()."); + } + + return new byte[11]; + } + + public void writePacket(byte b[]) throws IOException { + if ( true ) { + throw new IOException("Dummy IOException in createVM001_Connection.writePacket(byte b[])."); + } + + } + +} // end of createVM001_Connection class + +class createVM001_Process extends Process { + + public OutputStream getOutputStream() { + return null; + } + + public InputStream getInputStream() { + return null; + } + + public InputStream getErrorStream() { + return null; + } + + public int waitFor() throws InterruptedException { + return 0; + } + + public int exitValue() { + return 0; + } + + public void destroy() { + } + +} // end of createVM001_Process class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001/TestDescription.java new file mode 100644 index 00000000000..8dbbe63ac29 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001/TestDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM001 test: + * The test for the + * virtualMachineManager.createVirtualMachine(...) methods. + * The test checks up that both createVirtualMachine(Connection) and + * createVirtualMachine(Connection, Process) methods throw + * IllegalStateException if the used Connection is not open. + * COMMENTS: + * Test fixed according to test RFE: + * 4943437 TEST_RFE: createVM002 does not honor DEBUGEE_VM_* setting + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002.java new file mode 100644 index 00000000000..e49fc7460cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the
    + * virtualMachineManager.createVirtualMachine(...) methods.
    + *
    + * The test checks up that the
    + * createVirtualMachine(Connection, Process) method throws
    + * IOException when I/O error occurs in used Connection during
    + * creating of Virtual Mashine.
    + *
    + */ +public class createVM002 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "createVM002: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> createVM002: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + static final String packagePrefix = "nsk.jdi.VirtualMachineManager.createVirtualMachine."; +// static final String packagePrefix = emptyString; + static final String targetVMClassName = packagePrefix + "CreateVM002_TargetVM"; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new createVM002().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_FAILED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + logAlways("==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002 test..."); + logOnVerbose + ("==> Test checks that virtualMachineManager.createVirtualMachine(Connection, Process) method"); + logOnVerbose + ("==> throw IOException when I/O error occurs in Connection."); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + TransportService testTransportService = new CreateVM002_TranspServ(); + + TransportService.ListenKey testTransportServiceListenKey = null; + logOnVerbose(infoLogPrefixHead + "Start Listening for target VM..."); + try { + testTransportServiceListenKey = testTransportService.startListening(); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.startListening() throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "testTransportService.startListening() throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + String targetJava = argsHandler.getLaunchExecPath() + + " " + argsHandler.getLaunchOptions(); + String commandToRun = targetJava + " -Xdebug -Xrunjdwp:transport=dt_socket,address=" + + testTransportServiceListenKey.address() + + // Addind "suspend=n' option helps avoid debugee hang. See 6803636. + ",suspend=n" + + " " + targetVMClassName; + + Binder binder = new Binder(argsHandler, logHandler); + Debugee debugee = null; + Process processToRun = null; + Connection testTransportServiceConnection = null; + VirtualMachine testVirtualMachine = null; + + try { + + logOnVerbose(infoLogPrefixHead + "PROCESS is being created:"); + logOnVerbose(infoLogPrefix + "Command to run: " + commandToRun); + + debugee = binder.startLocalDebugee(commandToRun); + debugee.redirectOutput(logHandler); + processToRun = debugee.getProcess(); + + logOnVerbose(infoLogPrefixHead + "Accepting launched target VM..."); + try { + testTransportServiceConnection + = testTransportService.accept(testTransportServiceListenKey, 0, 0); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.accept(testTransportServiceListenKey, 0, 0) throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "testTransportService.accept(testTransportServiceListenKey) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + try { + testTransportService.stopListening(testTransportServiceListenKey); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.stopListening(testTransportServiceListenKey) throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + + "testTransportService.stopListening(testTransportServiceListenKey) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + logOnVerbose(infoLogPrefixHead + "Creating VirtualMachine for target VM..."); +// ( (CreateVM002_Connection)testTransportServiceConnection).toPrintPacket(true); + boolean wasIOExceptionInConnection = false; + try { + testVirtualMachine + = virtualMachineManager.createVirtualMachine(testTransportServiceConnection, + processToRun); + wasIOExceptionInConnection + =( (CreateVM002_Connection)testTransportServiceConnection).wasIOException; + if ( wasIOExceptionInConnection ) { + logOnError(errorLogPrefixHead + "VirtualMachineManager.createVirtualMachine(Connection, Process) does"); + logOnError(errorLogPrefix + "NOT throw IOException when I/O error occurs in Connection."); + testResult = STATUS_FAILED; + } + debugee.setupVM(testVirtualMachine); + } catch ( IOException ioExcept ) { + // OK. It is expected Exception + logOnVerbose(infoLogPrefixHead + + "VirtualMachineManager.createVirtualMachine(Connection, Process) throws IOException."); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + testResult = STATUS_PASSED; + } catch ( Throwable thrown ) { + wasIOExceptionInConnection + =( (CreateVM002_Connection)testTransportServiceConnection).wasIOException; + logOnError(errorLogPrefixHead + "VirtualMachineManager.createVirtualMachine(Connection, Process) throws"); + if ( wasIOExceptionInConnection ) { + logOnError(errorLogPrefix + "unexpected Exception when I/O error occurs in Connection:"); + logOnError(errorLogPrefix + "Expected Exception - 'IOException'"); + logOnError(errorLogPrefix + "Actual Exception - '" + thrown + "'"); + } else { + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + } + testResult = STATUS_FAILED; + } +// ( (CreateVM002_Connection)testTransportServiceConnection).toPrintPacket(false); + + } finally { + + logOnVerbose(infoLogPrefixHead + "Closing connection and destroying target VM..."); + if (testVirtualMachine != null) { + logOnVerbose(infoLogPrefix + "Disposing target VM mirror"); + testVirtualMachine.dispose(); + } + if (testTransportServiceConnection != null) { + logOnVerbose(infoLogPrefix + "Closing transport connection"); + try { + testTransportServiceConnection.close(); + } catch (IOException e) { + logAlways("# WARNING: IOException while closing connection:\n\t" + e); + } + } + if (debugee != null) { + logOnVerbose(infoLogPrefix + "Waiting for target VM exit"); + int status = debugee.waitFor(); + logOnVerbose(infoLogPrefix + "debuggee exit status: " + status); + } + } + + return testResult; + } + +} // end of createVM002 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002/TestDescription.java new file mode 100644 index 00000000000..406822f74a4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002/TestDescription.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM002 test: + * The test for the + * virtualMachineManager.createVirtualMachine(...) methods. + * The test checks up that the + * createVirtualMachine(Connection, Process) method throws + * IOException when I/O error occurs in used Connection during + * creating of Virtual Mashine. + * COMMENTS: + * Test fixed according to test RFE: + * 4943437 TEST_RFE: createVM002 does not honor DEBUGEE_VM_* setting + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM002 + * nsk.jdi.VirtualMachineManager.createVirtualMachine.CreateVM002_TargetVM + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003.java new file mode 100644 index 00000000000..92bed251e41 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003.java @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the
    + * virtualMachineManager.createVirtualMachine(...) methods.
    + *
    + * The test checks up that createVirtualMachine(Connection, Process)
    + * method creates the VirtualMachine properly for Process that is NOT
    + * null.
    + *
    + * After the VirtualMachine is created the test checks that:
    + * - VirtualMachine.process() method returns the same Process passed
    + * to the createVirtualMachine(Connection, Process) method;
    + * - after VirtualMachine.resume() the Process should finish for
    + * specified time with expected Exit Status value;
    + *
    + */ +public class createVM003 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "createVM003: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> createVM003: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + static final String packagePrefix = "nsk.jdi.VirtualMachineManager.createVirtualMachine."; +// static final String packagePrefix = emptyString; + static final String targetVMClassName = packagePrefix + "CreateVM003_TargetVM"; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new createVM003().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + logAlways("==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003 test..."); + logOnVerbose + ("==> Test checks that virtualMachineManager.createVirtualMachine(Connection, Process) method"); + logOnVerbose + ("==> creates Virtual Machine properly for Process that is NOT null."); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + TransportService testTransportService = new CreateVM003_TranspServ(); + + TransportService.ListenKey testTransportServiceListenKey = null; + logOnVerbose(infoLogPrefixHead + "Start Listening for target VM..."); + try { + testTransportServiceListenKey = testTransportService.startListening(); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.startListening() throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "testTransportService.startListening() throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + String targetJava = argsHandler.getLaunchExecPath() + + " " + argsHandler.getLaunchOptions(); + String commandToRun = targetJava + " -Xdebug -Xrunjdwp:transport=dt_socket,address=" + + testTransportServiceListenKey.address() + " " + targetVMClassName; + + Binder binder = new Binder(argsHandler, logHandler); + Debugee debugee = null; + Process processToRun = null; + Connection testTransportServiceConnection = null; + + try { + + logOnVerbose(infoLogPrefixHead + "PROCESS is being created:"); + logOnVerbose(infoLogPrefix + "Command to run: " + commandToRun); + + debugee = binder.startLocalDebugee(commandToRun); + debugee.redirectOutput(logHandler); + processToRun = debugee.getProcess(); + + logOnVerbose(infoLogPrefixHead + "Accepting launched target VM..."); + try { + testTransportServiceConnection + = testTransportService.accept(testTransportServiceListenKey, 0, 0); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.accept(testTransportServiceListenKey, 0, 0) throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "testTransportService.accept(testTransportServiceListenKey) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + try { + testTransportService.stopListening(testTransportServiceListenKey); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.stopListening(testTransportServiceListenKey) throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + + "testTransportService.stopListening(testTransportServiceListenKey) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + logOnVerbose(infoLogPrefixHead + "Creating VirtualMachine for target VM..."); + VirtualMachine testVirtualMachine = null; + try { + testVirtualMachine + = virtualMachineManager.createVirtualMachine(testTransportServiceConnection, + processToRun); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "VirtualMachineManager.createVirtualMachine(Connection, Process) throws IOException."); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + + "VirtualMachineManager.createVirtualMachine(Connection, Process) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "Connection = '" + testTransportServiceConnection + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + Process testVirtualMachineProcess = testVirtualMachine.process(); + if ( ! processToRun.equals(testVirtualMachineProcess) ) { + logOnError(errorLogPrefixHead + "Created VirtualMachine returns unexpected Process:"); + logOnError(errorLogPrefix + "Expected Process = '" + processToRun + "'"); + logOnError(errorLogPrefix + "Returned Process = '" + testVirtualMachineProcess + "'"); + testResult = STATUS_FAILED; + } + + long timeout = argsHandler.getWaitTime() * 60 * 1000; // milliseconds + + logOnVerbose(infoLogPrefixHead + "Managing target VM"); + debugee.setupVM(testVirtualMachine); + logOnVerbose(infoLogPrefix + "Waiting for VM initialized"); + debugee.waitForVMInit(timeout); + logOnVerbose(infoLogPrefix + "Resuming VM"); + debugee.resume(); + logOnVerbose(infoLogPrefix + "Waiting for VM exit"); + int procExitValue = debugee.waitFor(); + logOnVerbose(infoLogPrefix + "VM exit status: " + procExitValue); + + if ( procExitValue != (STATUS_PASSED + STATUS_TEMP) ) { + logOnError(errorLogPrefixHead + "Target VM finished unexpectedly:"); + logOnError(errorLogPrefix + "Expected Exit status = " + (STATUS_PASSED + STATUS_TEMP)); + logOnError(errorLogPrefix + "Actual Exit status = " + procExitValue); + testResult = STATUS_FAILED; + } else { + logOnVerbose(infoLogPrefixHead + "Target VM finished succesfully!"); + } + + } finally { + + logOnVerbose(infoLogPrefixHead + "Closing connection and destroying target VM..."); + if (testTransportServiceConnection != null) { + try { + testTransportServiceConnection.close(); + } catch (IOException e) { + logAlways("# WARNING: IOException while closing connection:\n\t" + e); + } + } + if (debugee != null) { + debugee.close(); + } + } + + return testResult; + } + +} // end of createVM003 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003/TestDescription.java new file mode 100644 index 00000000000..5d36a5f4737 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM003 test: + * The test for the + * virtualMachineManager.createVirtualMachine(...) methods. + * The test checks up that createVirtualMachine(Connection, Process) + * method creates the VirtualMachine properly for Process that is NOT null. + * After the VirtualMachine is created the test checks that: + * - VirtualMachine.process() method returns the same Process passed + * to the createVirtualMachine(Connection, Process) method; + * - VMStartEvent should be received for specified timeout; + * - after VirtualMachine.resume() the Process should finish + * with expected exit status; + * COMMENTS: + * Test fixed according to test RFE: + * 4943437 TEST_RFE: createVM002 does not honor DEBUGEE_VM_* setting + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM003 + * nsk.jdi.VirtualMachineManager.createVirtualMachine.CreateVM003_TargetVM + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004.java new file mode 100644 index 00000000000..4a485e21d21 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the
    + * virtualMachineManager.createVirtualMachine(...) methods.
    + *
    + * The test checks up that createVirtualMachine(Connection, Process)
    + * method creates the VirtualMachine properly when 'Process' argument
    + * is null.
    + *
    + * After the VirtualMachine is created the test checks that:
    + * - VirtualMachine.process() method returns the null as
    + * the specification says about it.
    + * - nevertheless after VirtualMachine.resume() the target VM should
    + * finish for specified time with expected Exit Status value;
    + *
    + */ +public class createVM004 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "createVM004: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> createVM004: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + static final String packagePrefix = "nsk.jdi.VirtualMachineManager.createVirtualMachine."; +// static final String packagePrefix = emptyString; + static final String targetVMClassName = packagePrefix + "CreateVM004_TargetVM"; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new createVM004().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + logAlways("==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004 test..."); + logOnVerbose + ("==> Test checks that virtualMachineManager.createVirtualMachine(Connection, Process) method"); + logOnVerbose + ("==> creates Virtual Machine properly when 'Process' argument is null."); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + String targetJavaKey = "targetJava="; + String[] testArgs = argsHandler.getArguments(); + + TransportService testTransportService = new CreateVM004_TranspServ(); + + TransportService.ListenKey testTransportServiceListenKey = null; + logOnVerbose(infoLogPrefixHead + "Start Listening for target VM..."); + try { + testTransportServiceListenKey = testTransportService.startListening(); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.startListening() throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "testTransportService.startListening() throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + String targetJava = argsHandler.getLaunchExecPath() + + " " + argsHandler.getLaunchOptions(); + String commandToRun = targetJava + " -Xdebug -Xrunjdwp:transport=dt_socket,address=" + + testTransportServiceListenKey.address() + " " + targetVMClassName; + + Binder binder = new Binder(argsHandler, logHandler); + Debugee debugee = null; + Process processToRun = null; + Connection testTransportServiceConnection = null; + + try { + + logOnVerbose(infoLogPrefixHead + "PROCESS is being created:"); + logOnVerbose(infoLogPrefix + "Command to run: " + commandToRun); + + debugee = binder.startLocalDebugee(commandToRun); + debugee.redirectOutput(logHandler); + processToRun = debugee.getProcess(); + + logOnVerbose(infoLogPrefixHead + "Accepting launched target VM..."); + try { + testTransportServiceConnection + = testTransportService.accept(testTransportServiceListenKey, 0, 0); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.accept(testTransportServiceListenKey, 0, 0) throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "testTransportService.accept(testTransportServiceListenKey) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + try { + testTransportService.stopListening(testTransportServiceListenKey); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.stopListening(testTransportServiceListenKey) throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + + "testTransportService.stopListening(testTransportServiceListenKey) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + logOnVerbose(infoLogPrefixHead + "Creating VirtualMachine for target VM..."); + VirtualMachine testVirtualMachine = null; + try { + testVirtualMachine + = virtualMachineManager.createVirtualMachine(testTransportServiceConnection, null); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "VirtualMachineManager.createVirtualMachine(Connection, null) throws IOException."); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "VirtualMachineManager.createVirtualMachine(Connection, null) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "Connection = '" + testTransportServiceConnection + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + Process testVirtualMachineProcess = testVirtualMachine.process(); + if ( testVirtualMachineProcess != null ) { + logOnError(errorLogPrefixHead + + "Created VirtualMachine with null 'Process' argument returns unexpected Process:"); + logOnError(errorLogPrefix + "Expected Process = null"); + logOnError(errorLogPrefix + "Returned Process = '" + testVirtualMachineProcess + "'"); + testResult = STATUS_FAILED; + } + + long timeout = argsHandler.getWaitTime() * 60 * 1000; // milliseconds + + logOnVerbose(infoLogPrefixHead + "Managing target VM"); + debugee.setupVM(testVirtualMachine); + logOnVerbose(infoLogPrefix + "Waiting for VM initialized"); + debugee.waitForVMInit(timeout); + logOnVerbose(infoLogPrefix + "Resuming VM"); + debugee.resume(); + logOnVerbose(infoLogPrefix + "Waiting for VM exit"); + int procExitValue = debugee.waitFor(); + logOnVerbose(infoLogPrefix + "VM exit status: " + procExitValue); + + if ( procExitValue != (STATUS_PASSED + STATUS_TEMP) ) { + logOnError(errorLogPrefixHead + "Target VM finished unexpectedly:"); + logOnError(errorLogPrefix + "Expected Exit status = " + (STATUS_PASSED + STATUS_TEMP)); + logOnError(errorLogPrefix + "Actual Exit status = " + procExitValue); + testResult = STATUS_FAILED; + } else { + logOnVerbose(infoLogPrefixHead + "Target VM finished succesfully!"); + } + + } finally { + + logOnVerbose(infoLogPrefixHead + "Closing connection and destroying target VM..."); + if (testTransportServiceConnection != null) { + try { + testTransportServiceConnection.close(); + } catch (IOException e) { + logAlways("# WARNING: IOException while closing connection:\n\t" + e); + } + } + if (debugee != null) { + debugee.close(); + } + } + + return testResult; + } + +} // end of createVM004 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004/TestDescription.java new file mode 100644 index 00000000000..49d4cb9d911 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004/TestDescription.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM004 test: + * The test for the + * virtualMachineManager.createVirtualMachine(...) methods. + * The test checks up that createVirtualMachine(Connection, Process) + * method creates the VirtualMachine properly when 'Process' argument + * is null. + * After the VirtualMachine is created the test checks that: + * - VirtualMachine.process() method returns the null as + * the specification says about it. + * - VMStartEvent should be received for specified timeout; + * - after VirtualMachine.resume() the Process should finish + * with expected exit status; + * COMMENTS: + * Test fixed according to test RFE: + * 4943437 TEST_RFE: createVM002 does not honor DEBUGEE_VM_* setting + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM004 + * nsk.jdi.VirtualMachineManager.createVirtualMachine.CreateVM004_TargetVM + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005.java new file mode 100644 index 00000000000..2b47fede424 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2003, 2018, 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 nsk.jdi.VirtualMachineManager.createVirtualMachine; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import com.sun.jdi.connect.spi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the
    + * virtualMachineManager.createVirtualMachine(Connection) method.
    + *
    + * The test checks up that createVirtualMachine(Connection) method
    + * creates the VirtualMachine properly.
    + *
    + * After the VirtualMachine is created the test checks that:
    + * - VirtualMachine.process() method returns the null as
    + * the specification says about it.
    + * - nevertheless after VirtualMachine.resume() the target VM should
    + * finish for specified time with expected Exit Status value;
    + *
    + */ +public class createVM005 { + + static final int STATUS_PASSED = 0; + static final int STATUS_FAILED = 2; + static final int STATUS_TEMP = 95; + + static final String errorLogPrefixHead = "createVM005: "; + static final String errorLogPrefix = " "; + static final String infoLogPrefixHead = "--> createVM005: "; + static final String infoLogPrefix = "--> "; + static final String emptyString = ""; + static final String packagePrefix = "nsk.jdi.VirtualMachineManager.createVirtualMachine."; +// static final String packagePrefix = emptyString; + static final String targetVMClassName = packagePrefix + "CreateVM005_TargetVM"; + + static ArgumentHandler argsHandler; + static Log logHandler; + + private static void logOnVerbose(String message) { + logHandler.display(message); + } + + private static void logOnError(String message) { + logHandler.complain(message); + } + + private static void logAlways(String message) { + logHandler.println(message); + } + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + STATUS_TEMP); + } + + public static int run (String argv[], PrintStream out) { + int result = new createVM005().runThis(argv, out); + if ( result == STATUS_FAILED ) { + logAlways("\n##> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005 test FAILED"); + } + else { + logAlways("\n==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005 test PASSED"); + } + return result; + } + + + private int runThis (String argv[], PrintStream out) { + int testResult = STATUS_PASSED; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + logAlways("==> nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005 test..."); + logOnVerbose + ("==> Test checks that virtualMachineManager.createVirtualMachine(Connection) method"); + logOnVerbose + ("==> creates Virtual Machine properly."); + + VirtualMachineManager virtualMachineManager = Bootstrap.virtualMachineManager(); + if (virtualMachineManager == null) { + logOnError(errorLogPrefixHead + "Bootstrap.virtualMachineManager() returns null."); + return STATUS_FAILED; + } + + TransportService testTransportService = new CreateVM005_TranspServ(); + + TransportService.ListenKey testTransportServiceListenKey = null; + logOnVerbose(infoLogPrefixHead + "Start Listening for target VM..."); + try { + testTransportServiceListenKey = testTransportService.startListening(); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.startListening() throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "testTransportService.startListening() throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + String targetJava = argsHandler.getLaunchExecPath() + + " " + argsHandler.getLaunchOptions(); + String commandToRun = targetJava + " -Xdebug -Xrunjdwp:transport=dt_socket,address=" + + testTransportServiceListenKey.address() + " " + targetVMClassName; + + Binder binder = new Binder(argsHandler, logHandler); + Debugee debugee = null; + Process processToRun = null; + Connection testTransportServiceConnection = null; + + try { + + logOnVerbose(infoLogPrefixHead + "PROCESS is being created:"); + logOnVerbose(infoLogPrefix + "Command to run: " + commandToRun); + + debugee = binder.startLocalDebugee(commandToRun); + debugee.redirectOutput(logHandler); + processToRun = debugee.getProcess(); + + logOnVerbose(infoLogPrefixHead + "Accepting launched target VM..."); + try { + testTransportServiceConnection + = testTransportService.accept(testTransportServiceListenKey, 0, 0); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.accept(testTransportServiceListenKey, 0, 0) throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "testTransportService.accept(testTransportServiceListenKey) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + try { + testTransportService.stopListening(testTransportServiceListenKey); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "testTransportService.stopListening(testTransportServiceListenKey) throws IOException."); + logOnVerbose(infoLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnVerbose(infoLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + + "testTransportService.stopListening(testTransportServiceListenKey) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "testTransportService = '" + testTransportService + "'"); + logOnError(errorLogPrefix + "testTransportServiceListenKey = '" + testTransportServiceListenKey + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + logOnVerbose(infoLogPrefixHead + "Creating VirtualMachine for target VM..."); + VirtualMachine testVirtualMachine = null; + try { + testVirtualMachine + = virtualMachineManager.createVirtualMachine(testTransportServiceConnection); + } catch ( IOException ioExcept ) { + // OK. It is possible Exception + logOnVerbose(infoLogPrefixHead + + "VirtualMachineManager.createVirtualMachine(Connection) throws IOException."); + logOnVerbose(infoLogPrefix + "IOException - '" + ioExcept + "'"); + logOnVerbose(infoLogPrefix + "The test is stopped."); + return STATUS_PASSED; + } catch ( Throwable thrown ) { + logOnError(errorLogPrefixHead + "VirtualMachineManager.createVirtualMachine(Connection) throws"); + logOnError(errorLogPrefix + "unexpected Exception:"); + logOnError(errorLogPrefix + "Connection = '" + testTransportServiceConnection + "'"); + logOnError(errorLogPrefix + "Exception - '" + thrown + "'"); + return STATUS_FAILED; + } + + Process testVirtualMachineProcess = testVirtualMachine.process(); + if ( testVirtualMachineProcess != null ) { + logOnError(errorLogPrefixHead + + "Created VirtualMachine without 'Process' argument returns unexpected Process:"); + logOnError(errorLogPrefix + "Expected Process = null"); + logOnError(errorLogPrefix + "Returned Process = '" + testVirtualMachineProcess + "'"); + testResult = STATUS_FAILED; + } + + long timeout = argsHandler.getWaitTime() * 60 * 1000; // milliseconds + + logOnVerbose(infoLogPrefixHead + "Managing target VM"); + debugee.setupVM(testVirtualMachine); + logOnVerbose(infoLogPrefix + "Waiting for VM initialized"); + debugee.waitForVMInit(timeout); + logOnVerbose(infoLogPrefix + "Resuming VM"); + debugee.resume(); + logOnVerbose(infoLogPrefix + "Waiting for VM exit"); + int procExitValue = debugee.waitFor(); + logOnVerbose(infoLogPrefix + "VM exit status: " + procExitValue); + + if ( procExitValue != (STATUS_PASSED + STATUS_TEMP) ) { + logOnError(errorLogPrefixHead + "Target VM finished unexpectedly:"); + logOnError(errorLogPrefix + "Expected Exit status = " + (STATUS_PASSED + STATUS_TEMP)); + logOnError(errorLogPrefix + "Actual Exit status = " + procExitValue); + testResult = STATUS_FAILED; + } else { + logOnVerbose(infoLogPrefixHead + "Target VM finished succesfully!"); + } + + } finally { + + logOnVerbose(infoLogPrefixHead + "Closing connection and destroying target VM..."); + if (testTransportServiceConnection != null) { + try { + testTransportServiceConnection.close(); + } catch (IOException e) { + logAlways("# WARNING: IOException while closing connection:\n\t" + e); + } + } + if (debugee != null) { + debugee.close(); + } + } + return testResult; + } + +} // end of createVM005 class diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005/TestDescription.java new file mode 100644 index 00000000000..cf69a7b9fb7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * nsk/jdi/VirtualMachineManager/createVirtualMachine/createVM005 test: + * The test for the + * virtualMachineManager.createVirtualMachine(Connection) method. + * The test checks up that createVirtualMachine(Connection) method + * creates the VirtualMachine properly. + * After the VirtualMachine is created the test checks that: + * - VirtualMachine.process() method returns the null as + * the specification says about it. + * - VMStartEvent should be received for specified timeout; + * - after VirtualMachine.resume() the Process should finish + * with expected exit status; + * COMMENTS: + * Test fixed according to test RFE: + * 4943437 TEST_RFE: createVM002 does not honor DEBUGEE_VM_* setting + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM005 + * nsk.jdi.VirtualMachineManager.createVirtualMachine.CreateVM005_TargetVM + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.createVirtualMachine.createVM005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001.java new file mode 100644 index 00000000000..6a230db6877 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.defaultConnector; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.defaultConnector()
    + * complies with its specification.
    + *
    + * The test checks up that invoking the method
    + * VirtualMachineManager.defaultConnector() doesn't throw
    + * an exception and returnes a non-null value of the
    + * LaunchingConnector type.
    + */ + +public class default001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/defaultConnector/default001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new default001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + waitTime = argsHandler.getWaitTime(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......call to Bootstrap.virtualMachineManager()"); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + log2("......call to vmm.defaultConnector()"); + LaunchingConnector defaultConnector; + try { + defaultConnector = vmm.defaultConnector(); + if (defaultConnector == null) { + log3("ERROR: defaultConnector == null"); + testExitCode = FAILED; + } + } catch ( Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001/TestDescription.java new file mode 100644 index 00000000000..1a609febaf3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/defaultConnector/default001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/defaultConnector/default001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.defaultConnector() + * complies with its spec: + * public LaunchingConnector defaultConnector() + * Identifies the default connector. + * This connector should be used as the launching connector when + * selection of a connector with specific characteristics is unnecessary. + * Returns: the default LaunchingConnector + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.defaultConnector.default001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.defaultConnector.default001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001.java new file mode 100644 index 00000000000..fdd198189e5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.launchingConnectors; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.launchingConnectors()
    + * complies with its specification.
    + *
    + * The test checks up that invoking the method
    + * VirtualMachineManager.launchingConnectors() doesn't throw
    + * an exception and returnes a List of non-null values of
    + * the LaunchingConnector type each.
    + */ + +public class launching001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/launchingConnectors/launching001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new launching001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......call to Bootstrap.virtualMachineManager()"); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + try { + log2("......call to vmm.launchingConnectors()"); + List connectors = vmm.launchingConnectors(); + log2(" size of List == " + connectors.size()); + + log2("......checking up on nulls and casts to LaunchingConnector"); + ListIterator li = connectors.listIterator(); + for (; li.hasNext(); ) { + LaunchingConnector launchingConnector = (LaunchingConnector) li.next(); + if (launchingConnector == null) { + log3("ERROR: launchingConnector == null"); + testExitCode = FAILED; + } + } + } catch ( Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001/TestDescription.java new file mode 100644 index 00000000000..44f355063bd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/launchingConnectors/launching001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/launchingConnectors/launching001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.launchingConnectors() + * complies with its spec: + * public java.util.List launchingConnectors() + * Returns the list of known LaunchingConnector objects. + * Any of the returned objects can be used to launch + * a new target VM and immediately create a VirtualMachine mirror for it. + * Returns: a list of LaunchingConnector objects. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.launchingConnectors.launching001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.launchingConnectors.launching001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001.java new file mode 100644 index 00000000000..4e7e4009a68 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.listeningConnectors; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.connect.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.listeningConnectors()
    + * complies with its specification.
    + *
    + * The test checks up that invoking the method
    + * VirtualMachineManager.listeningConnectors() doesn't throw
    + * an exception and returnes a List of non-null values of
    + * the ListeningConnector type each.
    + */ + +public class listening001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/listeningConnectors/listening001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new listening001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + waitTime = argsHandler.getWaitTime(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......call to Bootstrap.virtualMachineManager()"); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + try { + log2("......call to vmm.listeningConnectors()"); + List connectors = vmm.listeningConnectors(); + log2(" size of List == " + connectors.size()); + + log2("......checking up on nulls and casts to ListeningConnector"); + ListIterator li = connectors.listIterator(); + for (; li.hasNext(); ) { + ListeningConnector listeningConnector = (ListeningConnector) li.next(); + if (listeningConnector == null) { + log3("ERROR: listeningConnector == null"); + testExitCode = FAILED; + } + } + } catch ( Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001/TestDescription.java new file mode 100644 index 00000000000..3a1dd4aa8e0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/listeningConnectors/listening001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/listeningConnectors/listening001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.listeningConnectors() + * complies with its spec: + * public java.util.List listeningConnectors() + * Returns the list of known ListeningConnector objects. + * Any of the returned objects can be used to listen for a connection + * initiated by a target VM and create a VirtualMachine mirror for it. + * Returns: a list of ListeningConnector objects. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.listeningConnectors.listening001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.listeningConnectors.listening001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001.java new file mode 100644 index 00000000000..dd11ba4d854 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VirtualMachineManager.majorInterfaceVersion; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.majorInterfaceVersion()
    + * complies with its specification.
    + *
    + * The test checks up that invoking the method
    + * VirtualMachineManager.majorInterfaceVersion() doesn't throw
    + * an exception and a returned value is of the int type.
    + */ + +public class major001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new major001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + waitTime = argsHandler.getWaitTime(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......call to Bootstrap.virtualMachineManager()"); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + log2("......call to vmm.majorInterfaceVersion()"); + int majorVersion; + try { + majorVersion = vmm.majorInterfaceVersion(); + log2(" majorInterfaceVersion() == " + majorVersion); + } catch ( Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001/TestDescription.java new file mode 100644 index 00000000000..2b2d1e86e49 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/majorInterfaceVersion/major001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager.majorInterfaceVersion() + * complies with its spec: + * public int majorInterfaceVersion() + * Returns the major version number of the JDI interface. + * See VirtualMachine.version() target VM version and + * information and VirtualMachine.description() more version information. + * Returns: the integer major version number. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.majorInterfaceVersion.major001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.majorInterfaceVersion.major001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001.java new file mode 100644 index 00000000000..d2293425828 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2001, 2018, 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. + */ +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! templete parameters !!!! + +// VirtualMachineManager Interface Name VirtualMachineManager +// minorInterfaceVersion Method Name minorInterfaceVersion +// minor001 Test Name minor001 +// ------------------------------------------------------ + +package nsk.jdi.VirtualMachineManager.minorInterfaceVersion; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VirtualMachineManager.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VirtualMachineManager.minorInterfaceVersion()
    + * complies with its specification.
    + *
    + * The test checks up that invoking the method
    + * VirtualMachineManager.minorInterfaceVersion() doesn't throw
    + * an exception and a returned value is of the int type.
    + */ + +public class minor001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new minor001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + + waitTime = argsHandler.getWaitTime(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......call to Bootstrap.virtualMachineManager()"); + VirtualMachineManager vmm = Bootstrap.virtualMachineManager(); + if (vmm == null) { + log3("ERROR: null returned"); + testExitCode = FAILED; + } else { + + log2("......call to vmm.minorInterfaceVersion()"); + int minorVersion; + try { + minorVersion = vmm.minorInterfaceVersion(); + log2(" minorInterfaceVersion() == " + minorVersion); + } catch ( Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001/TestDescription.java new file mode 100644 index 00000000000..614e1615682 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VirtualMachineManager/minorInterfaceVersion/minor001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VirtualMachineManager. + * The test checks up that a result of the method + * com.sun.jdi.VirtualMachineManager. minorInterfaceVersion() + * complies with its spec: + * public int minorInterfaceVersion() + * Returns the minor version number of the JDI interface. + * See VirtualMachine.version() target VM version + * and information and VirtualMachine.description() more version information. + * Returns: the integer minor version number + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VirtualMachineManager.minorInterfaceVersion.minor001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VirtualMachineManager.minorInterfaceVersion.minor001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java new file mode 100644 index 00000000000..4997fc38879 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VoidType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VoidType.
    + *
    + * The test checks that for a mirror of a "void" value the cast
    + * from Type to VoidType doesn't throw ClassCastException.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the cast,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee prepares new check case and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent,
    + * the debugger performs the check.
    + * Note. To inform each other of needed actions, the debugger and
    + * and the debuggee use debuggeee's variable "instruction".
    + *
    + * In third phase when at the end,
    + * the debuggee changes the value of the "instruction"
    + * to inform the debugger of checks finished, and both end.
    + *
    + */ + +public class voidtype001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VoidType/_itself_/voidtype001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new voidtype001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VoidType._itself_.voidtype001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : e"); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + BreakpointRequest bpRequest; + + bpRequest = settingBreakpoint(threadByName("main"), + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + log2("......getting: List methods = debuggeeClass.methodsByName('testMethod');"); + List methods = debuggeeClass.methodsByName("testMethod"); + if (methods.size() != 1) { + testExitCode = FAILED; + log3("ERROR: methods.size() != 1"); + break ; + } + + log2("......getting: Method testMethod = (Method) methods.get(0);"); + Method testMethod = (Method) methods.get(0); + + try { + log2("......getting: Type testMethodReturnType = testMethod.returnType();"); + Type testMethodReturnType = testMethod.returnType(); + + log2("......VoidType voidType = (VoidType) testMethodReturnType;"); + VoidType voidType = (VoidType) testMethodReturnType; + } catch ( ClassNotLoadedException e ) { + log3("ERROR: testmethodReturnType = testmethod.returnType();"); + testExitCode = FAILED; + break ; + } catch ( ClassCastException e ) { + log3("ERROR: ClassCastException"); + testExitCode = FAILED; + break ; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001/TestDescription.java new file mode 100644 index 00000000000..a580f0c4cde --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VoidType/_itself_/voidtype001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VoidType. + * The test checks that for a mirror of a "void" value the cast + * from Type to VoidType doesn't throw ClassCastException. + * The test works as follows: + * The debugger program - nsk.jdi.VoidType._itself_.voidtype001; + * the debuggee program - nsk.jdi.VoidType._itself_.voidtype001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VoidType._itself_.voidtype001 + * nsk.jdi.VoidType._itself_.voidtype001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VoidType._itself_.voidtype001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001a.java new file mode 100644 index 00000000000..d9b6ce0442e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001a.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VoidType._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the voidtype001 JDI test. + */ + +public class voidtype001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + public void testMethod () { + return; + } + + //------------------------------------------------------ common section + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + int exitCode = PASSED; + + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + methodForCommunication(); + break ; + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + System.exit(exitCode + PASS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001.java new file mode 100644 index 00000000000..37686b6f956 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VoidType.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; +import com.sun.jdi.event.*; +import com.sun.jdi.connect.*; +import java.io.*; +import java.util.*; + +/** + * The debugger application of the test. + */ +public class tostring001 { + + //------------------------------------------------------- immutable common fields + + final static String SIGNAL_READY = "ready"; + final static String SIGNAL_GO = "go"; + final static String SIGNAL_QUIT = "quit"; + + private static int waitTime; + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static Debugee debuggee; + private static ReferenceType debuggeeClass; + + //------------------------------------------------------- mutable common fields + + private final static String prefix = "nsk.jdi.VoidType.toString."; + private final static String className = "tostring001"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; + + //------------------------------------------------------- test specific fields + + /** debuggee's methods for check **/ + private final static String checkedMethods[] = { + "Mv" , "MvS", "MvI", "MvY", "MvU", "MvN", + "MvR", "MvP", "MvSM", "MvIM", "MvYM", "MvPM", "MvNP" + }; + + //------------------------------------------------------- immutable common methods + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + private static void display(String msg) { + log.display("debugger > " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + BreakpointRequest brkp = debuggee.setBreakpoint(debuggeeClass, + tostring001a.brkpMethodName, + tostring001a.brkpLineNumber); + debuggee.resume(); + + debuggee.sendSignal(SIGNAL_GO); + Event event = null; + + // waiting the breakpoint event + try { + event = debuggee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected InterruptedException while waiting for Breakpoint event"); + } + if (!(event instanceof BreakpointEvent)) { + debuggee.resume(); + throw new Failure("BreakpointEvent didn't arrive"); + } + + ThreadReference thread = ((BreakpointEvent)event).thread(); + List params = new Vector(); + ClassType testedClass = (ClassType)debuggeeClass; + ObjectReference testedObject = null; + + // Finding of debuggee's class constructor + Method ctor = debuggee.methodByName(debuggeeClass, ""); + + try { + testedObject = testedClass.newInstance(thread, ctor, params, 0); + } catch (Exception e) { + throw new Failure("unexpected " + e + " when invoking debuggee's constructor"); + } + + display("Checking toString() method for debuggee's void type methods..."); + + // Check all methods from debuggee + for (int i = 0; i < checkedMethods.length-1; i++) { + + VoidType voidType = null; + Method method; + + method = debuggee.methodByName(debuggeeClass, checkedMethods[i]); + try { + voidType = (VoidType)method.returnType(); + String str = voidType.toString(); + if (str == null) { + complain("toString() returns null for VoidType of debugges's method: " + checkedMethods[i]); + exitStatus = Consts.TEST_FAILED; + } else if (str.length() == 0) { + complain("toString() returns empty string for VoidType of debugges's method: " + checkedMethods[i]); + exitStatus = Consts.TEST_FAILED; + } else { + display("toString() returns for debuggee's void method " + checkedMethods[i] + " : " + str); + } + } catch(Exception e) { + complain("Unexpected " + e + " when getting VoidType of debuggee's method: " + checkedMethods[i]); + exitStatus = Consts.TEST_FAILED; + } + + } + + display("Checking of debuggee's void type methods completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods + +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..df13a6dea95 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VoidType/toString/tostring001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public toString() method of an implementing class of + * com.sun.jdi.VoidType interface. + * The test checks an assertion: + * In conformity with the contract for java.lang.Object.toString(), + * the overrided method returns representing non-empty string for + * a VoidType object of a debuggee's void type method. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for VoidType + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VoidType.toString.tostring001 + * nsk.jdi.VoidType.toString.tostring001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VoidType.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001a.java new file mode 100644 index 00000000000..1dd64e50b1b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/toString/tostring001a.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VoidType.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class tostring001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 80; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(tostring001.SIGNAL_READY); + receiveSignal(tostring001.SIGNAL_GO); + log.display("breakpoint line"); // brkpLineNumber + receiveSignal(tostring001.SIGNAL_QUIT); + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + + void Mv() {}; + + static void MvS() {}; + strictfp void MvI() {}; + synchronized void MvY() {}; + public void MvU() {}; + protected void MvR() {}; + private void MvP() {}; + native void MvN(); + + public static void MvSM() {}; + private strictfp void MvIM() {}; + static synchronized void MvYM() {}; + public final void MvPM() {}; + native protected void MvNP(); + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001.java new file mode 100644 index 00000000000..97b07c7383d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001.java @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2001, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VoidValue/equals/equals001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VoidValue. + * The test checks up that a result of the method + * com.sun.jdi.VoidValue.equals() + * complies with its spec: + * public boolean equals(java.lang.Object obj) + * Compares the specified Object with this VoidValue for equality. + * Returns: true if the Object is a VoidValue; false otherwise. + * The test works as follows: + * A debugger program - nsk.jdi.VoidValue.equals.equals001; + * a debuggee program - nsk.jdi.VoidValue.equals.equals001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VoidValue.equals.equals001.equals001 + * nsk.jdi.VoidValue.equals.equals001.equals001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VoidValue.equals.equals001.equals001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.VoidValue.equals.equals001; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VoidValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VoidValue.equals()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee is suspended at a breakpoint set up
    + * by a debugger the debugger invokes two debuggee's methods:
    + * void vdValue1(); and void vdValue2();
    + * to form objects
    + * Value returnvdValue1, Value returnvdValue2;
    + *
    + * then performs the following casts:
    + * VoidValue vdValue1 = (VoidValue) returnvdValue1;
    + * VoidValue vdValue2 = (VoidValue) returnvdValue2;
    + *
    + * and checks up that the following is true:
    + *
    + * a) vdValue1.equals(vdValue2)
    + *
    + * b) Object testObj = null;
    + * !vdValue1.equals(testObj)
    + *
    + */ + +public class equals001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VoidValue/equals/equals001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new equals001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VoidValue.equals.equals001.equals001a"; + + private String testedClassName = + "nsk.jdi.VoidValue.equals.equals001.Threadequals001a"; + + //====================================================== test program + //------------------------------------------------------ common section + + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + String threadName = "Thread2"; + + String breakpointMethod1 = "run"; + String bpLine1 = "breakpointLineNumber1"; + + BreakpointRequest breakpRequest1 = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting a breakpoint event"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + + Value returnvdValue1 = null; + Value returnvdValue2 = null; + List invokeMethods = null; + Method invokeMethod = null; + List argumentList = null; + + + invokeMethods = testedclass.methodsByName("vdValue1"); + invokeMethod = (Method) invokeMethods.get(0); + + argumentList = Collections.emptyList(); + + try { + log2(" invoking equals001a.vdValue1(); no Exception expected"); + returnvdValue1 = thread2.invokeMethod(thread2, + invokeMethod, argumentList, 0); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + expresult = returnCode1; + break label1; + } + + invokeMethods = testedclass.methodsByName("vdValue2"); + invokeMethod = (Method) invokeMethods.get(0); + + try { + log2(" invoking equals001a.vdValue2(); no Exception expected"); + returnvdValue2 = thread2.invokeMethod(thread2, + invokeMethod, argumentList, 0); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + expresult = returnCode1; + break label1; + } + + + VoidValue vdValue1 = null; + VoidValue vdValue2 = null; + + log2(" checking up cast: vdValue1 = (VoidValue) returnvdValue1;"); + try { + vdValue1 = (VoidValue) returnvdValue1; + } catch ( ClassCastException e ) { + log3("ERROR : ClassCastException"); + expresult = returnCode1; + break label1; + } + + log2(" checking up cast: vdValue2 = (VoidValue) returnvdValue2;"); + try { + vdValue2 = (VoidValue) returnvdValue2; + } catch ( ClassCastException e ) { + log3("ERROR : ClassCastException"); + expresult = returnCode1; + break label1; + } + + log2(" checking up equality: vdValue1.equals(vdValue2)"); + if (!vdValue1.equals(vdValue2)) { + log3("ERROR: !vdValue1.equals(vdValue2)"); + expresult = returnCode1; + } + + Object testObj = null; + log2(" checking up equality: vdValue1.equals(null)"); + if (vdValue1.equals(testObj)) { + log3("ERROR: vdValue1.equals(null)"); + expresult = returnCode1; + } + } + log2(" resuming the vm"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + logHandler.complain("TEST FAILED"); + } + return testExitCode; + } + + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001a.java new file mode 100644 index 00000000000..d8f3155f7f5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals001/equals001a.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VoidValue.equals.equals001; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the equals001 JDI test. + */ + +public class equals001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + equals002 thisTest = new equals002(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + waitTime = argHandler.getWaitTime() * 60000; + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("Test finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + debugee.VM().suspend(); + testedClass = (ClassType )debugee.classByName(debugeeName); + + BreakpointRequest brkp = debugee.setBreakpoint(testedClass, + equals002a.brkpMethodName, + equals002a.brkpLineNumber); + debugee.resume(); + + debugee.sendSignal(""); + Event event = null; + + // waiting the breakpoint event + try { + event = debugee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new TestRuntimeException("unexpected InterruptedException"); + } + if (!(event instanceof BreakpointEvent )) { + debugee.resume(); + throw new TestRuntimeException("BreakpointEvent didn't arrive"); + } + + BreakpointEvent brkpEvent = (BreakpointEvent )event; + if (brkpEvent == null) { + debugee.resume(); + throw new TestRuntimeException("No breakpoint events"); + } + + thread = brkpEvent.thread(); + + display("\nTEST BEGINS"); + display("==========="); + + Method method = debugee.methodByName(testedClass, method2Invoke); + List params = new Vector(); + VoidValue voidValue1 = null, + voidValue2 = null; + try { + voidValue1 = (VoidValue )testedClass.invokeMethod(thread, method, params, 0); + voidValue2 = (VoidValue )testedClass.invokeMethod(thread, method, params, 0); + } catch(Exception e) { + complain("unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + + // geting of array of primitive types + Field fldOtherType, field = testedClass.fieldByName(arrPrimitives); + if ( field == null ) { + complain("Field '" + arrPrimitives + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + Value valueOtherType, arrValue = testedClass.getValue(field); + if ( arrValue == null || !(arrValue instanceof ArrayReference) ) { + complain("Field '" + arrValue + "' is wrong."); + exitStatus = Consts.TEST_FAILED; + } + ArrayReference primitivValues = (ArrayReference )arrValue; + + // comparing with debugee's fields + if ( !PerformComparing(voidValue1, voidValue2) ) + exitStatus = Consts.TEST_FAILED; + for (int j = 0; j < primitivValues.length(); j++) { + arrValue = primitivValues.getValue(j); + + fldOtherType = testedClass.fieldByName(((StringReference )arrValue).value()); + if ( fldOtherType == null ) { + complain("Field '" + arrValue + "' not found."); + exitStatus = Consts.TEST_FAILED; + continue; + } + + valueOtherType = testedClass.getValue(fldOtherType); + + if ( !PerformComparing(voidValue1, valueOtherType) ) + exitStatus = Consts.TEST_FAILED; + } + + display("============="); + display("TEST FINISHES\n"); + + debugee.resume(); + debugee.quit(); + } + + private boolean PerformComparing(VoidValue value, Value object ) { + boolean res = true; + String msg = ""; + String type = "(" + (object == null ? "" : object.type().toString()) + ")"; + try { + if (value.equals(object)) { + if (object instanceof VoidValue) { + msg += "--> " + value + " == " + object + type; + } + else { + msg += "##> " + value + " == " + object + type + + " : are different types " + value.type() + " - " + + ((Value )object).type(); + res = false; + } + if (object == null) { + msg += " ***Wrong result!!!***"; + res = false; + } + } else { + if (!(object instanceof VoidValue)) { + msg += "--> " + value + " != " + object + type; + } + } + } catch (Exception e) { + msg += " ***Unexpected " + e + "***"; + res = false; + } + + if ( !res ) + complain(msg); + else + display(msg); + + return res; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002/TestDescription.java new file mode 100644 index 00000000000..8fdca046c06 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VoidValue/equals/equals002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the method + * com.sun.jdi.BooleanValue.equals(Object) + * correctly works for the boundary value of parameter, throws described + * exceptions and complies with its spec: + * public boolean equals(Object obj) + * Compares the specified Object with this BooleanValue for equality. + * Overrides: + * equals in class Object + * Returns: + * true if the Object is a BooleanValue and if applying "==" to the + * two mirrored primitives would evaluate to true; false otherwise. + * The test check up case when parameter has value or boundary + * values of primitive types. In this case no exception is expected. + * In case of error the test produces the return value 97 and a corresponding + * error message(s). Otherwise, the test is passed and produces the return + * value 95 and no message. + * COMMENTS: + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VoidValue.equals.equals002 + * nsk.jdi.VoidValue.equals.equals002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VoidValue.equals.equals002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002a.java new file mode 100644 index 00000000000..f5271843112 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/equals/equals002a.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VoidValue.equals; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +public class equals002a { + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 83; + + static String[] testedFields = { + "cmpObjNULL", + "cmpObject", + "cmpBoolMAX", + "cmpBoolMIN", + "cmpByteMAX", + "cmpByteMIN", + "cmpCharMAX", + "cmpCharMIN", + "cmpDoubleMAX", + "cmpDoubleMIN", + "cmpFloatMAX", + "cmpFloatMIN", + "cmpIntMAX", + "cmpIntMIN", + "cmpLongMAX", + "cmpLongMIN", + "cmpShortMAX", + "cmpShortMIN" + }; + + static Object cmpObjNULL = null; + static Object cmpObject = new Object(); + static boolean cmpBoolMAX = true; + static boolean cmpBoolMIN = false; + static byte cmpByteMAX = Byte.MAX_VALUE; + static byte cmpByteMIN = Byte.MIN_VALUE; + static char cmpCharMAX = Character.MAX_VALUE; + static char cmpCharMIN = Character.MIN_VALUE; + static double cmpDoubleMAX= Double.MAX_VALUE; + static double cmpDoubleMIN= Double.MIN_VALUE; + static float cmpFloatMAX = Float.MAX_VALUE; + static float cmpFloatMIN = Float.MIN_VALUE; + static int cmpIntMAX = Integer.MAX_VALUE; + static int cmpIntMIN = Integer.MIN_VALUE; + static long cmpLongMAX = Long.MAX_VALUE; + static long cmpLongMIN = Long.MIN_VALUE; + static short cmpShortMAX = Short.MAX_VALUE; + static short cmpShortMIN = Short.MIN_VALUE; + + public static void main (String argv[]) { + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + pipe.println(equals002.SGNL_READY); + String instr = pipe.readln(); + log.display("breakpoint line"); // brkpLineNumber + instr = pipe.readln(); + if (instr.equals(equals002.SGNL_QUIT)) { + log.display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + + public static void voidValue() { + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001.java new file mode 100644 index 00000000000..213c8cb37b4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001.java @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2001, 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VoidValue/hashCode/hashcode001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * VoidValue. + * The test checks up that a result of the method + * com.sun.jdi.VoidValue.hashCode() + * complies with its spec: + * public int hashCode() + * Returns the hash code value for this VoidValue. + * Returns: the hash code + * Overrides: hashCode in class java.lang.Object + * The test works as follows: + * A debugger program - nsk.jdi.VoidValue.hashCode.hashcode001; + * a debuggee program - nsk.jdi.VoidValue.hashCode.hashcode001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, + * establishes a pipe with the debuggee program, and then + * send to the programm commands, to which the debuggee replies + * via the pipe. Upon getting reply, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and compares the data got to the data expected. + * In case of mismatch the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VoidValue.hashCode.hashcode001.hashcode001 + * nsk.jdi.VoidValue.hashCode.hashcode001.hashcode001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VoidValue.hashCode.hashcode001.hashcode001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdi.VoidValue.hashCode.hashcode001; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * VoidValue.
    + *
    + * The test checks up that results of the method
    + * com.sun.jdi.VoidValue.hashCode()
    + * complies with its spec.
    + *
    + * The cases for testing are as follows :
    + *
    + * when a gebuggee is suspended at a breakpoint
    + * set by a debugger,
    + * the debugger invokes debuggee's methods:
    + * void vdValue1(); void vdValue1(); void vdValue2();
    + * to form the follwing objects: Value returnvdValue1,
    + * Value returnvdValue2, and Value returnvdValue3;
    + *
    + * performs following casts:
    + * VoidValue vdValue1 = (VoidValue) returnvdValue1;
    + * VoidValue vdValue2 = (VoidValue) returnvdValue2;
    + * VoidValue vdValue3 = (VoidValue) returnvdValue3;
    + *
    + * and checks up that each of the following is true:
    + *
    + * vdValue1.hashCode() == vdValue2.hashCode()
    + * vdValue1.hashCode() == vdValue3.hashCode()
    + *
    + */ + +public class hashcode001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/VoidValue/hashCode/hashcode001", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + int result = run(argv, System.out); + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + return new hashcode001().runThis(argv, out); + } + + //-------------------------------------------------- log procedures + + //private static boolean verbMode = false; + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.VoidValue.hashCode.hashcode001.hashcode001a"; + + private String testedClassName = + "nsk.jdi.VoidValue.hashCode.hashcode001.Threadhashcode001a"; + + //====================================================== test program + //------------------------------------------------------ common section + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + + ReferenceType testedclass = null; + ThreadReference thread2 = null; + ThreadReference mainThread = null; + + static int testExitCode = PASSED; + + static final int returnCode0 = 0; + static final int returnCode1 = 1; + static final int returnCode2 = 2; + static final int returnCode3 = 3; + static final int returnCode4 = 4; + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + Debugee debuggee; + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); // *** tp + } else { + debuggee = binder.bindToDebugee(debuggeeName); // *** tp + } + + waitTime = argsHandler.getWaitTime(); + + + IOPipe pipe = new IOPipe(debuggee); + + debuggee.redirectStderr(out); + log2("setvalue003a debuggee launched"); + debuggee.resume(); + + String line = pipe.readln(); + if ((line == null) || !line.equals("ready")) { + log3("signal received is not 'ready' but: " + line); + return FAILED; + } else { + log2("'ready' recieved"); + } + + VirtualMachine vm = debuggee.VM(); + + //------------------------------------------------------ testing section + log1(" TESTING BEGINS"); + + for (int i = 0; ; i++) { + pipe.println("newcheck"); + line = pipe.readln(); + + if (line.equals("checkend")) { + log2(" : returned string is 'checkend'"); + break ; + } else if (!line.equals("checkready")) { + log3("ERROR: returned string is not 'checkready'"); + testExitCode = FAILED; + break ; + } + + log1("new check: #" + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + int expresult = returnCode0; + + eventRManager = vm.eventRequestManager(); + eventQueue = vm.eventQueue(); + + List allThreads = null; + ListIterator listIterator = null; + List classes = null; + + String threadName = "Thread2"; + + String breakpointMethod1 = "run"; + String bpLine1 = "breakpointLineNumber1"; + + BreakpointRequest breakpRequest1 = null; + + + label0: { + + log2("getting ThreadReference object"); + try { + allThreads = vm.allThreads(); + classes = vm.classesByName(testedClassName); + testedclass = (ReferenceType) classes.get(0); + } catch ( Exception e) { + log3("ERROR: Exception at very beginning !? : " + e); + expresult = returnCode1; + break label0; + } + + listIterator = allThreads.listIterator(); + for (;;) { + try { + thread2 = (ThreadReference) listIterator.next(); + if (thread2.name().equals(threadName)) + break ; + } catch ( NoSuchElementException e ) { + log3("ERROR: NoSuchElementException for listIterator.next()"); + log3("ERROR: NO THREAD2 ?????????!!!!!!!"); + expresult = returnCode1; + break label0; + } + } + + log2("setting up breakpoint"); + + breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one"); + if (breakpRequest1 == null) { + expresult = returnCode1; + break label0; + } + } + + label1: { + + if (expresult != returnCode0) + break label1; + + log2(" enabling breakpRequest1"); + breakpRequest1.enable(); + + log2(" forcing the main thread to leave synchronized block"); + pipe.println("continue"); + line = pipe.readln(); + if (!line.equals("docontinue")) { + log3("ERROR: returned string is not 'docontinue'"); + expresult = returnCode4; + break label1; + } + + log2(" getting a breakpoint event"); + expresult = breakpoint(); + if (expresult != returnCode0) + break label1; + + + Value returnvdValue1 = null; + Value returnvdValue2 = null; + Value returnvdValue3 = null; + List invokeMethods = null; + Method invokeMethod = null; + List argumentList = null; + + + invokeMethods = testedclass.methodsByName("vdValue1"); + invokeMethod = (Method) invokeMethods.get(0); + + argumentList = Collections.emptyList(); + + try { + log2(" 1st invoking hashcode001a.vdValue1(); no Exception expected"); + returnvdValue1 = thread2.invokeMethod(thread2, + invokeMethod, argumentList, 0); + log2(" 2nd invoking hashcode001a.vdValue1(); no Exception expected"); + returnvdValue2 = thread2.invokeMethod(thread2, + invokeMethod, argumentList, 0); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + expresult = returnCode1; + break label1; + } + + // invoking hashcode001a.vdValue2() + + invokeMethods = testedclass.methodsByName("vdValue2"); + invokeMethod = (Method) invokeMethods.get(0); + + try { + log2(" invoking hashcode001a.vdValue2(); no Exception expected"); + returnvdValue3 = thread2.invokeMethod(thread2, + invokeMethod, argumentList, 0); + } catch ( Exception e ) { + log3("ERROR: Exception: " + e); + expresult = returnCode1; + break label1; + } + + + VoidValue vdValue1 = null; + VoidValue vdValue2 = null; + VoidValue vdValue3 = null; + + try { + log2(" checking up cast: vdValue1 = (VoidValue) returnvdValue1; no Exception expected"); + vdValue1 = (VoidValue) returnvdValue1; + } catch ( ClassCastException e ) { + log3("ERROR : ClassCastException"); + expresult = returnCode1; + break label1; + } + + try { + log2(" checking up cast: vdValue2 = (VoidValue) returnvdValue2; no Exception expected"); + vdValue2 = (VoidValue) returnvdValue2; + } catch ( ClassCastException e ) { + log3("ERROR : ClassCastException"); + expresult = returnCode1; + break label1; + } + + try { + log2(" checking up cast: vdValue3 = (VoidValue) returnvdValue3; no Exception expected"); + vdValue3 = (VoidValue) returnvdValue3; + } catch ( ClassCastException e ) { + log3("ERROR : ClassCastException"); + expresult = returnCode1; + break label1; + } + + log2(" checking up: dValue1.hashCode() == vdValue2.hashCode()"); + if (vdValue1.hashCode() != vdValue2.hashCode() ) { + log3("ERROR: vdValue1.hashCode() != vdValue2.hashCode()"); + expresult = returnCode1; + } + log2(" checking up: dValue1.hashCode() == vdValue3.hashCode()"); + if (vdValue1.hashCode() != vdValue3.hashCode() ) { + log3("ERROR: vdValue1.hashCode() != vdValue3.hashCode()"); + expresult = returnCode1; + } + } + log2(" resuming the vm"); + vm.resume(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + log2(" the end of testing"); + if (expresult != returnCode0) + testExitCode = FAILED; + } + log1(" TESTING ENDS"); + + //-------------------------------------------------- test summary section + //------------------------------------------------- standard end section + + pipe.println("quit"); + log2("waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + int status = debuggee.getStatus(); + if (status != PASSED + PASS_BASE) { + log3("debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + + if (testExitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + + + /* + * private BreakpointRequest settingBreakpoint(String, String, String) + * + * It sets up a breakpoint within a given method at given line number + * for the thread2 only. + * Third parameter is required for any case in future debugging, as if. + * + * Return codes: + * = BreakpointRequest object in case of success + * = null in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( String methodName, + String bpLine, + String property) { + + log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine ); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedclass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread2); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + else + log2(" a breakpoint has been set up"); + + return breakpRequest; + } + + + /* + * private int breakpoint () + * + * It removes events from EventQueue until gets first BreakpointEvent. + * To get next EventSet value, it uses the method + * EventQueue.remove(int timeout) + * The timeout argument passed to the method, is "waitTime*60000". + * Note: the value of waitTime is set up with + * the method ArgumentHandler.getWaitTime() at the beginning of the test. + * + * Return codes: + * = returnCode0 - success; + * = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed + * = returnCode3 - default case when loop of processing an event, that is, + * an unspecified event was taken from the EventQueue + */ + + private int breakpoint () { + + int returnCode = returnCode0; + + log2(" waiting for BreakpointEvent"); + + labelBP: + for (;;) { + + log2(" new: eventSet = eventQueue.remove();"); + try { + eventSet = eventQueue.remove(waitTime*60000); + if (eventSet == null) { + log3("ERROR: timeout for waiting for a BreakpintEvent"); + returnCode = returnCode3; + break labelBP; + } + } catch ( Exception e ) { + log3("ERROR: Exception for eventSet = eventQueue.remove(); : " + e); + returnCode = 1; + break labelBP; + } + + if (eventSet != null) { + + log2(" : eventSet != null; size == " + eventSet.size()); + + EventIterator eIter = eventSet.eventIterator(); + Event ev = null; + + for (; eIter.hasNext(); ) { + + if (returnCode != returnCode0) + break; + + ev = eIter.nextEvent(); + + ll: for (int ifor =0; ; ifor++) { + + try { + switch (ifor) { + + case 0: AccessWatchpointEvent awe = (AccessWatchpointEvent) ev; + log2(" AccessWatchpointEvent removed"); + break ll; + case 1: BreakpointEvent be = (BreakpointEvent) ev; + log2(" BreakpointEvent removed"); + break labelBP; + case 2: ClassPrepareEvent cpe = (ClassPrepareEvent) ev; + log2(" ClassPreparEvent removed"); + break ll; + case 3: ClassUnloadEvent cue = (ClassUnloadEvent) ev; + log2(" ClassUnloadEvent removed"); + break ll; + case 4: ExceptionEvent ee = (ExceptionEvent) ev; + log2(" ExceptionEvent removed"); + break ll; + case 5: MethodEntryEvent mene = (MethodEntryEvent) ev; + log2(" MethodEntryEvent removed"); + break ll; + case 6: MethodExitEvent mexe = (MethodExitEvent) ev; + log2(" MethodExiEvent removed"); + break ll; + case 7: ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev; + log2(" ModificationWatchpointEvent removed"); + break ll; + case 8: StepEvent se = (StepEvent) ev; + log2(" StepEvent removed"); + break ll; + case 9: ThreadDeathEvent tde = (ThreadDeathEvent) ev; + log2(" ThreadDeathEvent removed"); + break ll; + case 10: ThreadStartEvent tse = (ThreadStartEvent) ev; + log2(" ThreadStartEvent removed"); + break ll; + case 11: VMDeathEvent vmde = (VMDeathEvent) ev; + log2(" VMDeathEvent removed"); + break ll; + case 12: VMStartEvent vmse = (VMStartEvent) ev; + log2(" VMStartEvent removed"); + break ll; + case 13: WatchpointEvent we = (WatchpointEvent) ev; + log2(" WatchpointEvent removed"); + break ll; + + default: log3("ERROR: default case for casting event"); + returnCode = returnCode3; + break ll; + } // switch + } catch ( ClassCastException e ) { + } // try + } // ll: for (int ifor =0; ; ifor++) + } // for (; ev.hasNext(); ) + } + } + if (returnCode == returnCode0) + log2(" : eventSet == null: EventQueue is empty"); + + return returnCode; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001a.java new file mode 100644 index 00000000000..5cee04fa40a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/hashCode/hashcode001/hashcode001a.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.VoidValue.hashCode.hashcode001; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +/** + * This class is used as debuggee application for the hashcode001 JDI test. + */ + +public class hashcode001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //-------------------------------------------------- log procedures + + static boolean verbMode = false; + + public static void log1(String message) { + if (verbMode) + System.err.println("**> mainThread: " + message); + } + public static void log2(String message) { + if (verbMode) + System.err.println("**> " + message); + } + + private static void logErr(String message) { + if (verbMode) + System.err.println("!!**> mainThread: " + message); + } + + //====================================================== test program + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + for (int i=0; i " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE > " + msg); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + waitTime = argHandler.getWaitTime() * 60000; + + debuggee = Debugee.prepareDebugee(argHandler, log, debuggeeName); + + debuggeeClass = debuggee.classByName(debuggeeName); + if ( debuggeeClass == null ) { + complain("Class '" + debuggeeName + "' not found."); + exitStatus = Consts.TEST_FAILED; + } + + execTest(); + + debuggee.quit(); + + return exitStatus; + } + + //------------------------------------------------------ mutable common method + + private static void execTest() { + + BreakpointRequest brkp = debuggee.setBreakpoint(debuggeeClass, + tostring001a.brkpMethodName, + tostring001a.brkpLineNumber); + debuggee.resume(); + + debuggee.sendSignal(SIGNAL_GO); + Event event = null; + + // waiting the breakpoint event + try { + event = debuggee.waitingEvent(brkp, waitTime); + } catch (InterruptedException e) { + throw new Failure("unexpected InterruptedException while waiting for Breakpoint event"); + } + if (!(event instanceof BreakpointEvent)) { + debuggee.resume(); + throw new Failure("BreakpointEvent didn't arrive"); + } + + ThreadReference thread = ((BreakpointEvent)event).thread(); + List params = new Vector(); + ClassType testedClass = (ClassType)debuggeeClass; + ObjectReference testedObject = null; + + // Finding of debuggee's class constructor + Method ctor = debuggee.methodByName(debuggeeClass, ""); + + try { + testedObject = testedClass.newInstance(thread, ctor, params, 0); + } catch (Exception e) { + throw new Failure("unexpected " + e + " when invoking debuggee's constructor"); + } + + display("Checking toString() method for debuggee's void value methods..."); + + // Check all methods from debuggee + for (int i = 0; i < checkedMethods.length-1; i++) { + + VoidValue voidValue = null; + Method method; + + method = debuggee.methodByName(debuggeeClass, checkedMethods[i]); + try { + if (method.isStatic()) { + voidValue = (VoidValue) testedClass.invokeMethod(thread, method, params, 0); + } else { + voidValue = (VoidValue) testedObject.invokeMethod(thread, method, params, 0); + } + + String str = voidValue.toString(); + if (str == null) { + complain("toString() returns null for VoidValue of debugges's method: " + checkedMethods[i]); + exitStatus = Consts.TEST_FAILED; + } else if (str.length() == 0) { + complain("toString() returns empty string for VoidValue of debugges's method: " + checkedMethods[i]); + exitStatus = Consts.TEST_FAILED; + } else { + display("toString() returns for VoidValue of debugges's method " + checkedMethods[i] + " : " + str); + } + } catch(Exception e) { + complain("Unexpected " + e + " when invoking debuggee's method: " + checkedMethods[i]); + exitStatus = Consts.TEST_FAILED; + } + + } + + display("Checking of debuggee's void value methods completed!"); + debuggee.resume(); + } + + //--------------------------------------------------------- test specific methods +} +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001/TestDescription.java new file mode 100644 index 00000000000..dd5ef890b61 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/VoidValue/toString/tostring001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for public toString() method of an implementing class of + * com.sun.jdi.VoidValue interface. + * The test checks an assertion: + * In conformity with the contract for java.lang.Object.toString(), + * the overrided method returns representing non-empty string for + * for a VoidValue object returned by an invocation of a debuggee's + * void type method. + * COMMENTS: + * The test is aimed to increase jdi source code coverage and checks + * the code which was not yet covered by previous tests for VoidValue + * interface. The coverage analysis was done for jdk1.4.0-b92 build. + * Test was fixed according to test bug: + * 4778296 TEST_BUG: debuggee VM intemittently hangs after resuming + * - handling VMStartEvent was removed from the debugger part of the test + * Test fixed according to test bug: + * 4798088 TEST_BUG: setBreakpoint() method depends of the locations implementation + * - using standard Debugee.setBreakpoint() method + * - adjusting source line numbers used for setting breakpoint + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.VoidValue.toString.tostring001 + * nsk.jdi.VoidValue.toString.tostring001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.VoidValue.toString.tostring001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001a.java new file mode 100644 index 00000000000..4a8c1be9a59 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidValue/toString/tostring001a.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.VoidValue.toString; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/** + * The debugged application of the test. + */ +public class tostring001a { + + //------------------------------------------------------- immutable common fields + + private static int exitStatus; + private static ArgumentHandler argHandler; + private static Log log; + private static IOPipe pipe; + + //------------------------------------------------------- immutable common methods + + static void display(String msg) { + log.display("debuggee > " + msg); + } + + static void complain(String msg) { + log.complain("debuggee FAILURE > " + msg); + } + + public static void receiveSignal(String signal) { + String line = pipe.readln(); + + if ( !line.equals(signal) ) + throw new Failure("UNEXPECTED debugger's signal " + line); + + display("debuger's <" + signal + "> signal received."); + } + + //------------------------------------------------------ mutable common fields + + //------------------------------------------------------ test specific fields + + public final static String brkpMethodName = "main"; + public final static int brkpLineNumber = 81; + + //------------------------------------------------------ mutable common method + + public static void main (String argv[]) { + exitStatus = Consts.TEST_FAILED; + argHandler = new ArgumentHandler(argv); + log = new Log(System.err, argHandler); + pipe = argHandler.createDebugeeIOPipe(log); + try { + pipe.println(tostring001.SIGNAL_READY); + receiveSignal(tostring001.SIGNAL_GO); + log.display("breakpoint line"); + receiveSignal(tostring001.SIGNAL_QUIT); // brkpLineNumber + display("completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } catch (Failure e) { + log.complain(e.getMessage()); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } + } + + //--------------------------------------------------------- test specific methods + + void Mv() {}; + + static void MvS() {}; + strictfp void MvI() {}; + synchronized void MvY() {}; + public void MvU() {}; + protected void MvR() {}; + private void MvP() {}; + + public static void MvSM() {}; + private strictfp void MvIM() {}; + static synchronized void MvYM() {}; + public final void MvPM() {}; + +} + +//--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001.java new file mode 100644 index 00000000000..adfd1d56e2a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointEvent. + * + * The test checks that results of methods in the interface + * com.sun.jdi.WatchpointEvent + * complies with its spec. + * + * The test checks up on the following assertion: + * The number of WatchpointEvents received is equal to + * the number of WatchpointRequestsset up by a debugger. + * Tested are both Access and Modification WatchpointEvents. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee an object foo of CheckedClass and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger: + * - set up enabled WatchpointRequests for all fields, + * - resumes the debuggee, and + * - waiting for all expected events to receive. + */ + +public class wevent001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointEvent._itself_.wevent001a"; + return new wevent001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointEvent._itself_.CheckedClass"; + + volatile int mwEventsCount = 0; + volatile int awEventsCount = 0; + volatile int requestsCount = 0; + + protected void testRun() { + + if ( !vm.canWatchFieldModification() ) { + display("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + if ( !vm.canWatchFieldAccess() ) { + display("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + ReferenceType refType = null; + List fields = null; + ListIterator li = null; + Field field = null; + + ModificationWatchpointRequest mwRequest = null; + AccessWatchpointRequest awRequest = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + refType = (ReferenceType) vm.classesByName(testedClassName).get(0); + fields = refType.fields(); + li = fields.listIterator(); + + display("......setting up WatchpointRequests"); + while (li.hasNext()) { + field = (Field) li.next(); + if (!field.isSynthetic()) { + mwRequest = eventRManager.createModificationWatchpointRequest(field); + mwRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); + mwRequest.enable(); + + awRequest = eventRManager.createAccessWatchpointRequest(field); + awRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); + awRequest.enable(); + + requestsCount++; + } + } + display(" # Requests set up : " + requestsCount); + + eventHandler.addListener( + new EventHandler.EventListener() { + public boolean eventReceived(Event event) { + if (event instanceof ModificationWatchpointEvent) { + display("Received ModificationWatchpointEvent "); + mwEventsCount++; + return true; + } else if (event instanceof AccessWatchpointEvent) { + display("Received AccessWatchpointEvent "); + awEventsCount++; + return true; + } + if (gotAllRequestedEvents()) { + synchronized (eventHandler) { + eventHandler.notifyAll(); + } + } + return false; + } + } + ); + + display("......waiting for WatchpointEvents"); + vm.resume(); + + long timeToFinish = System.currentTimeMillis() + waitTime; + long timeLeft = waitTime; + while (!gotAllRequestedEvents() && timeLeft > 0) { + try { + synchronized (eventHandler) { + eventHandler.wait(timeLeft); + timeLeft = timeToFinish - System.currentTimeMillis(); + } + } catch (InterruptedException e) { + setFailedStatus("InterruptedException was thrown while waiting for the events."); + throw new Failure(e); + } + } + + display("......checking up on numbers"); + if ( mwEventsCount != requestsCount ) { + setFailedStatus("ERROR: # ModificationWatchpointEvents != # Requests :: " + + mwEventsCount + " != " + requestsCount); + } + if ( awEventsCount != requestsCount ) { + setFailedStatus("ERROR: # AccessWatchpointEvents != # Requests :: " + + awEventsCount + " != " + requestsCount); + } + + display(" # mwEventsCount == " + mwEventsCount); + display(" # awEventsCount == " + awEventsCount); + + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + boolean gotAllRequestedEvents() { + return (mwEventsCount >= requestsCount && awEventsCount >= requestsCount); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001/TestDescription.java new file mode 100644 index 00000000000..8484ca54077 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001/TestDescription.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/WatchpointEvent/_itself_/wevent001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointEvent. + * The test checks up on the following assertion: + * The number of WatchpointEvents received is equal to + * the number of WatchpointRequestsset up by a debugger. + * Tested are both Access and Modification WatchpointEvents. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointEvent._itself_.wevent001; + * the debuggee program - nsk.jdi.WatchpointEvent._itself_.wevent001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * class CheckedClass being used in the debuggee + * has been taken from the test + * nsk.jdi.WatchpointEvent.valueCurrent.valuecur001 + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointEvent._itself_.wevent001 + * nsk.jdi.WatchpointEvent._itself_.wevent001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointEvent._itself_.wevent001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001a.java new file mode 100644 index 00000000000..ceaacf9e672 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001a.java @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointEvent._itself_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the wevent001 JDI test. + */ + +public class wevent001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + CheckedClass foo = new CheckedClass(); +// foo.run(); + methodForCommunication(); + foo.run(); + + //------------------------------------------------- standard end section + + default: + instruction = end; + methodForCommunication(); + break label0; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} + +class CheckedClass { + + boolean z0, z1[], z2[][]; + byte b0, b1[], b2[][]; + char c0, c1[], c2[][]; + double d0, d1[], d2[][]; + float f0, f1[], f2[][]; + int i0, i1[], i2[][]; + long l0, l1[], l2[][]; + short s0, s1[], s2[][]; + + static long lS0, lS1[], lS2[][]; + private long lP0, lP1[], lP2[][]; + public long lU0, lU1[], lU2[][]; + protected long lR0, lR1[], lR2[][]; + transient long lT0, lT1[], lT2[][]; + volatile long lV0, lV1[], lV2[][]; + + Boolean Z0, Z1[], Z2[][]; + Byte B0, B1[], B2[][]; + Character C0, C1[], C2[][]; + Double D0, D1[], D2[][]; + Float F0, F1[], F2[][]; + Integer I0, I1[], I2[][]; + Long L0, L1[], L2[][]; + String W0, W1[], W2[][]; + Short S0, S1[], S2[][]; + Object O0, O1[], O2[][]; + + static Long LS0, LS1[], LS2[][]; + private Long LP0, LP1[], LP2[][]; + public Long LU0, LU1[], LU2[][]; + protected Long LR0, LR1[], LR2[][]; + transient Long LT0, LT1[], LT2[][]; + volatile Long LV0, LV1[], LV2[][]; + + interface Inter {} + class Class implements Inter {} + Class X0, X1[], X2[][]; + Inter E0, E1[], E2[][]; + static Inter ES0, ES1[], ES2[][]; + private Inter EP0, EP1[], EP2[][]; + public Inter EU0, EU1[], EU2[][]; + protected Inter ER0, ER1[], ER2[][]; + transient Inter ET0, ET1[], ET2[][]; + volatile Inter EV0, EV1[], EV2[][]; + + void run() { + + z0 = true; + b0 = 0; + c0 = 0; + d0 = 0; + f0 = 0; + i0 = 0; + l0 = 0; + s0 = 0; + + lS0 = 0; + lP0 = 0; + lU0 = 0; + lR0 = 0; + lT0 = 0; + lV0 = 0; + + z1 = new boolean[] {z0}; + z2 = new boolean[][] {z1}; + b1 = new byte[] {b0}; + b2 = new byte[][] {b1}; + c1 = new char[] {c0}; + c2 = new char[][] {c1}; + d1 = new double[] {d0}; + d2 = new double[][] {d1}; + f1 = new float[] {f0}; + f2 = new float[][] {f1}; + i1 = new int[] {i0}; + i2 = new int[][] {i1}; + l1 = new long[] {l0}; + l2 = new long[][] {l1}; + s1 = new short[] {s0}; + s2 = new short[][] {s1}; + + lS1 = new long[] {lS0}; + lS2 = new long[][] {lS1}; + lP1 = new long[] {lP0}; + lP2 = new long[][] {lP1}; + lU1 = new long[] {lU0}; + lU2 = new long[][] {lU1}; + lR1 = new long[] {lR0}; + lR2 = new long[][] {lR1}; + lT1 = new long[] {lT0}; + lT2 = new long[][] {lT1}; + lV1 = new long[] {lV0}; + lV2 = new long[][] {lV1}; + + X0 = new Class(); + X1 = new Class[] {X0}; + X2 = new Class[][] {X1}; + Z0 = new Boolean(true); + Z1 = new Boolean[] {Z0}; + Z2 = new Boolean[][] {Z1}; + B0 = new Byte(java.lang.Byte.MIN_VALUE); + B1 = new Byte[] {B0}; + B2 = new Byte[][] {B1}; + C0 = new Character(java.lang.Character.MIN_VALUE); + C1 = new Character[] {C0}; + C2 = new Character[][]{C1}; + D0 = new Double(java.lang.Double.MIN_VALUE); + D1 = new Double[] {D0}; + D2 = new Double[][] {D1}; + F0 = new Float(java.lang.Float.MIN_VALUE); + F1 = new Float[] {F0}; + F2 = new Float[][] {F1}; + I0 = new Integer(java.lang.Integer.MIN_VALUE); + I1 = new Integer[] {I0}; + I2 = new Integer[][] {I1}; + L0 = new Long(java.lang.Long.MIN_VALUE); + L1 = new Long[] {L0}; + L2 = new Long[][] {L1}; + S0 = new Short(java.lang.Short.MIN_VALUE); + S1 = new Short[] {S0}; + S2 = new Short[][] {S1}; + W0 = new String(); + W1 = new String[] {W0}; + W2 = new String[][] {W1}; + O0 = new Object(); + O1 = new Object[] {O0}; + O2 = new Object[][] {O1}; + + LS0 = new Long(java.lang.Long.MAX_VALUE); + LS1 = new Long[] {LS0}; + LS2 = new Long[][] {LS1}; + LP0 = new Long(java.lang.Long.MAX_VALUE); + LP1 = new Long[] {LP0}; + LP2 = new Long[][] {LP1}; + LU0 = new Long(java.lang.Long.MAX_VALUE); + LU1 = new Long[] {LU0}; + LU2 = new Long[][] {LU1}; + LR0 = new Long(java.lang.Long.MAX_VALUE); + LR1 = new Long[] {LR0}; + LR2 = new Long[][] {LR1}; + LT0 = new Long(java.lang.Long.MAX_VALUE); + LT1 = new Long[] {LT0}; + LT2 = new Long[][] {LT1}; + LV0 = new Long(java.lang.Long.MAX_VALUE); + LV1 = new Long[] {LV0}; + LV2 = new Long[][] {LV1}; + + E0 = new Class(); + E1 = new Inter[] {E0}; + E2 = new Inter[][] {E1}; + ES0 = new Class(); + ES1 = new Inter[] {ES0}; + ES2 = new Inter[][] {ES1}; + EP0 = new Class(); + EP1 = new Inter[] {EP0}; + EP2 = new Inter[][] {EP1}; + EU0 = new Class(); + EU1 = new Inter[] {EU0}; + EU2 = new Inter[][] {EU1}; + ER0 = new Class(); + ER1 = new Inter[] {ER0}; + ER2 = new Inter[][] {ER1}; + ET0 = new Class(); + ET1 = new Inter[] {ET0}; + ET2 = new Inter[][] {ET1}; + EV0 = new Class(); + EV1 = new Inter[] {EV0}; + EV2 = new Inter[][] {EV1}; + + m(z2); m(b2); m(c2); m(d2); m(f2); m(i2); m(l2); m(s2); + + m(lS2); m(lP2); m(lU2); m(lR2); m(lT2); m(lV2); + + m(X2); m(Z2); m(B2); m(C2); m(D2); m(F2); m(I2); m(S2); m(W2); m(O2); + + m(LS2); m(LP2); m(LU2); m(LR2); m(LT2); m(LV2); + + m(X2); m(E2); m(ES2); m(EP2); m(EU2); m(ER2); m(ET2); m(EV2); + + } + + void m(Object obj) { + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001.java new file mode 100644 index 00000000000..f60ea00bca1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001.java @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointEvent.field; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class field001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static final String DEBUGGEE_NAME = "nsk.jdi.WatchpointEvent.field.field001a"; + static final String CHECKED_CLASS_NAME = "nsk.jdi.WatchpointEvent.field.CheckedClass"; + + static final int EXPECTED_ACCESS_EVENTS = field001a.ACCESS_COUNT; + static final int EXPECTED_MODIFICATION_EVENTS = field001a.MODIFICATIONS_COUNT; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private ReferenceType rType; + static private WatchpointRequest wpRequest; + static private List fieldsList; + + static private volatile boolean testFailed; + static private volatile boolean done; + static private volatile int requestsCount, awpEventsCount, mwpEventsCount; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + done = false; + requestsCount = 0; + awpEventsCount = 0; + mwpEventsCount = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "field001a >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + // check for debuggee's capabilities + if (!debuggee.VM().canWatchFieldAccess()) { + log.display("TEST WARNING: test passed because JDI implementation does not support " + + "watchpoints for field access"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return field001.PASSED; + } + + if (!debuggee.VM().canWatchFieldModification()) { + log.display("TEST WARNING: test passed because JDI implementation does not support " + + "watchpoints for field modification"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return field001.PASSED; + } + + // catch all exceptions while testing + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (command == null || !command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + if ((rType = debuggee.classByName(CHECKED_CLASS_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + CHECKED_CLASS_NAME); + } + + // create event requests + log.display("Creating requests for WatchpointEvent"); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + Iterator fieldsIter; + try { + fieldsList = rType.fields(); + fieldsIter = fieldsList.iterator(); + } catch (ClassNotPreparedException e) { + throw new Failure( "TEST_BUG: " + rType.name() + " is not prepared"); + } + while (fieldsIter.hasNext()) { + Field refField = (Field)fieldsIter.next(); + if ((wpRequest = erManager.createAccessWatchpointRequest(refField)) == null) { + throw new Failure("TEST BUG: unable to create AccessWatchpointRequest"); + } else { + log.display("AccessWatchpointRequest for field " + refField.name() + " created"); + wpRequest.enable(); + } + if ((wpRequest = erManager.createModificationWatchpointRequest(refField)) == null) { + throw new Failure("TEST BUG: unable to create ModificationWatchpointRequest"); + } else { + log.display("ModificationWatchpointRequest for field " + refField.name() + " created"); + wpRequest.enable(); + } + requestsCount++; + } + log.display("Created total " + requestsCount + " WatchpointRequests"); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + // handle events until all events generated and received + while (!(done + && awpEventsCount >= EXPECTED_ACCESS_EVENTS + && mwpEventsCount >= EXPECTED_MODIFICATION_EVENTS)) { + + eventSet = null; + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + + if (eventSet == null) + continue; + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); +// log.display("Event received: " + event); + + // handle WatchpointEvent + if (event instanceof WatchpointEvent) { + WatchpointEvent castedEvent = (WatchpointEvent)event; + Field evField = castedEvent.field(); + Field evField1 = castedEvent.field(); + + if (event instanceof AccessWatchpointEvent) { + awpEventsCount++; + log.display("AccessWatchpointEvent received for " + evField.name()); + } else if (event instanceof ModificationWatchpointEvent) { + mwpEventsCount++; + log.display("ModificationWatchpointEvent received for " + evField.name()); + } + + if (evField == null) { + log.complain("FAILURE 1: WatchpointEvent.field() returns null"); + testFailed = true; + } else if (evField != evField1) { + log.complain("FAILURE 2: method fieldd() returns inconsistent results for " + + evField.name() + "\nevField: " + evField + " ; evField1: " + evField1); + testFailed = true; + } else if (!(fieldsList.contains(evField))) { + log.complain("FAILURE 3: Watchpoint.field() returns unknown field"); + testFailed = true; + } else { + log.display("WatchpointEvent received for " + evField.name()); + } + } + } + + // resume each hamdled event set + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to generate events + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + // wait for confirmation from debugee + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (command == null || !command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // notify EventHandler that all events generated + done = true; + + // wait for all expected events received + log.display("Waiting for all expected events received"); + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check for all expected events received + if (awpEventsCount == 0) { + log.complain("FAILURE 4: No AccessWatchpointEvents were received"); + testFailed = true; + } else if (awpEventsCount < EXPECTED_ACCESS_EVENTS) { + log.complain("FAILURE 4: Too few AccessWatchpointEvents were received: " + + (EXPECTED_ACCESS_EVENTS - awpEventsCount) + " not received"); + testFailed = true; + } else if (awpEventsCount > EXPECTED_ACCESS_EVENTS) { + log.complain("FAILURE 4: Too many AccessWatchpointEvents were received: " + + "extra " + (awpEventsCount - EXPECTED_ACCESS_EVENTS) + " received"); + testFailed = true; + } else { + log.display("All expected AccessWatchpointEvents were received: " + + awpEventsCount + " events"); + } + if (mwpEventsCount == 0) { + log.complain("FAILURE 4: No ModificationWatchpointEvents were received"); + testFailed = true; + } else if (mwpEventsCount < EXPECTED_MODIFICATION_EVENTS) { + log.complain("FAILURE 4: Too few ModificationWatchpointEvents were received: " + + (EXPECTED_MODIFICATION_EVENTS - mwpEventsCount) + " not received"); + testFailed = true; + } else if (mwpEventsCount > EXPECTED_MODIFICATION_EVENTS) { + log.complain("FAILURE 4: Too many ModificationWatchpointEvents were received: " + + "extra " + (mwpEventsCount - EXPECTED_MODIFICATION_EVENTS) + " received"); + testFailed = true; + } else { + log.display("All expected ModificationWatchpointEvents were received: " + + mwpEventsCount + " events"); + } + + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001/TestDescription.java new file mode 100644 index 00000000000..f4c1884f8d4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/WatchpointEvent/field/field001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exercises + * com.sun.jdi.event.WatchpointEvent.field() method. + * The test checks the following assertion: + * Field reference returned by WatchpointEvent.field() + * exists in the list of fields returned by com.sun.jdi.ReferenceType.fields() + * method for . + * A debugger class - nsk.jdi.WatchpointEvent.field.field001 ; + * a debuggee class - nsk.jdi.WatchpointEvent.field.field001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates WatchpointRequests to the fields defined + * in checked class. + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee initializes its + * fields. + * The debugger switches to to listen the event during the + * time specified by parameter. Then debugger shuts down debuggee + * by command. + * If debugger receives WatchpointEvent, it checks if reference returned by + * WatchpointEvent.field() exists in the list of fields of the class loaded + * in the debuggee. + * The test also fails if no WatchpointEvent was received. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointEvent.field.field001 + * nsk.jdi.WatchpointEvent.field.field001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointEvent.field.field001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001a.java new file mode 100644 index 00000000000..9df72d45d71 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/field/field001a.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointEvent.field; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class field001a { + + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static final int ACCESS_COUNT = 76; + static final int MODIFICATIONS_COUNT = ACCESS_COUNT; + + public static void main(String args[]) { + System.exit(JCK_STATUS_BASE + run(args)); + } + + static int run( String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // create instance of checked class + CheckedClass foo = new CheckedClass(); + + // notify debugger that debuggee started + pipe.println(COMMAND_READY); + + // wait for command GO from debugger + String command = pipe.readln(); + if (command.equals(COMMAND_QUIT)) { + return PASSED; + } + if (!command.equals(COMMAND_GO)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + + // perform actions + foo.run(); + + // notify debugger that the command done + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger and exit + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + return PASSED; + } +} + +// class for checking +class CheckedClass { + + boolean z0, z1[], z2[][]; + byte b0, b1[], b2[][]; + char c0, c1[], c2[][]; + double d0, d1[], d2[][]; + float f0, f1[], f2[][]; + int i0, i1[], i2[][]; + long l0, l1[], l2[][]; + short s0, s1[], s2[][]; + + static long lS0, lS1[], lS2[][]; + private long lP0, lP1[], lP2[][]; + public long lU0, lU1[], lU2[][]; + protected long lR0, lR1[], lR2[][]; + transient long lT0, lT1[], lT2[][]; + volatile long lV0, lV1[], lV2[][]; + + class Class {} + Class X0, X1[], X2[][]; + Boolean Z0, Z1[], Z2[][]; + Byte B0, B1[], B2[][]; + Character C0, C1[], C2[][]; + Double D0, D1[], D2[][]; + Float F0, F1[], F2[][]; + Integer I0, I1[], I2[][]; + Long L0, L1[], L2[][]; + String W0, W1[], W2[][]; + Short S0, S1[], S2[][]; + Object O0, O1[], O2[][]; + + static Long LS0, LS1[], LS2[][]; + private Long LP0, LP1[], LP2[][]; + public Long LU0, LU1[], LU2[][]; + protected Long LR0, LR1[], LR2[][]; + transient Long LT0, LT1[], LT2[][]; + volatile Long LV0, LV1[], LV2[][]; + + interface Inter {} + Inter E0, E1[], E2[][]; + static Inter ES0, ES1[], ES2[][]; + private Inter EP0, EP1[], EP2[][]; + public Inter EU0, EU1[], EU2[][]; + protected Inter ER0, ER1[], ER2[][]; + transient Inter ET0, ET1[], ET2[][]; + volatile Inter EV0, EV1[], EV2[][]; + + public void run() { + + z1 = new boolean[] {z0}; + z2 = new boolean[][] {z1}; + b1 = new byte[] {b0}; + b2 = new byte[][] {b1}; + c1 = new char[] {c0}; + c2 = new char[][] {c1}; + d1 = new double[] {d0}; + d2 = new double[][] {d1}; + f1 = new float[] {f0}; + f2 = new float[][] {f1}; + i1 = new int[] {i0}; + i2 = new int[][] {i1}; + l1 = new long[] {l0}; + l2 = new long[][] {l1}; + s1 = new short[] {s0}; + s2 = new short[][] {s1}; + + lS1 = new long[] {lS0}; + lS2 = new long[][] {lS1}; + lP1 = new long[] {lP0}; + lP2 = new long[][] {lP1}; + lU1 = new long[] {lU0}; + lU2 = new long[][] {lU1}; + lR1 = new long[] {lR0}; + lR2 = new long[][] {lR1}; + lT1 = new long[] {lT0}; + lT2 = new long[][] {lT1}; + lV1 = new long[] {lV0}; + lV2 = new long[][] {lV1}; + + X1 = new Class[] {X0}; + X2 = new Class[][] {X1}; + Z1 = new Boolean[] {Z0}; + Z2 = new Boolean[][] {Z1}; + B1 = new Byte[] {B0}; + B2 = new Byte[][] {B1}; + C1 = new Character[] {C0}; + C2 = new Character[][]{C1}; + D1 = new Double[] {D0}; + D2 = new Double[][] {D1}; + F1 = new Float[] {F0}; + F2 = new Float[][] {F1}; + I1 = new Integer[] {I0}; + I2 = new Integer[][] {I1}; + L1 = new Long[] {L0}; + L2 = new Long[][] {L1}; + S1 = new Short[] {S0}; + S2 = new Short[][] {S1}; + W1 = new String[] {W0}; + W2 = new String[][] {W1}; + O1 = new Object[] {O0}; + O2 = new Object[][] {O1}; + + LS1 = new Long[] {LS0}; + LS2 = new Long[][] {LS1}; + LP1 = new Long[] {LP0}; + LP2 = new Long[][] {LP1}; + LU1 = new Long[] {LU0}; + LU2 = new Long[][] {LU1}; + LR1 = new Long[] {LR0}; + LR2 = new Long[][] {LR1}; + LT1 = new Long[] {LT0}; + LT2 = new Long[][] {LT1}; + LV1 = new Long[] {LV0}; + LV2 = new Long[][] {LV1}; + + E1 = new Inter[] {E0}; + E2 = new Inter[][] {E1}; + ES1 = new Inter[] {ES0}; + ES2 = new Inter[][] {ES1}; + EP1 = new Inter[] {EP0}; + EP2 = new Inter[][] {EP1}; + EU1 = new Inter[] {EU0}; + EU2 = new Inter[][] {EU1}; + ER1 = new Inter[] {ER0}; + ER2 = new Inter[][] {ER1}; + ET1 = new Inter[] {ET0}; + ET2 = new Inter[][] {ET1}; + EV1 = new Inter[] {EV0}; + EV2 = new Inter[][] {EV1}; + + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001.java new file mode 100644 index 00000000000..ab86e0dc272 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001.java @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointEvent.object; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class object001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final int EXPECTED_ACCESS_EVENTS = object001a.ACCESS_COUNT; + static final int EXPECTED_MODIFICATION_EVENTS = object001a.MODIFICATIONS_COUNT; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static final String DEBUGGEE_NAME = "nsk.jdi.WatchpointEvent.object.object001a"; + static final String CHECKED_CLASS_NAME = "nsk.jdi.WatchpointEvent.object.CheckedClass"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private WatchpointRequest checkedRequest; + static private ObjectReference checkedObject; +// static private Method checkedMethod; +// static private LocalVariable checkedVariable; + static private ReferenceType checkedClass; + static private ReferenceType debuggeeClass; + static private ThreadReference checkedThread; +// static private Location checkedLocation; +// static private StackFrame checkedFrame; + + static private List fieldsList; + + static private volatile boolean testFailed; + static private volatile boolean done; + static private volatile int requestsCount, awpEventsCount, mwpEventsCount; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + done = false; + requestsCount = 0; + awpEventsCount = 0; + mwpEventsCount = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + //launch debugee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "object001a >"); + + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + // check debuggee's capabilities + if (!debuggee.VM().canWatchFieldAccess()) { + log.display("TEST WARNING: test passed because JDI implementation does not support " + + "watchpoints for field access"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return PASSED; + } + + if (!debuggee.VM().canWatchFieldModification()) { + log.display("TEST WARNING: test passed because JDI implementation does not support " + + "watchpoints for field modification"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return PASSED; + } + + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (command == null || !command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirrors + log.display("Getting loaded classes in debuggee"); + if ((debuggeeClass = debuggee.classByName(DEBUGGEE_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + DEBUGGEE_NAME); + } + if ((checkedClass = debuggee.classByName(CHECKED_CLASS_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + CHECKED_CLASS_NAME); + } + + log.display("Getting reference to
    thread"); + Iterator threadIterator = vm.allThreads().iterator(); + while (threadIterator.hasNext()) { + ThreadReference curThread = (ThreadReference) threadIterator.next(); + if (curThread.name().equals("main")) { + checkedThread = curThread; + } + } + if (checkedThread == null) { + throw new Failure("TEST BUG: unable to find reference to
    thread"); + } + + // get object of checked class + log.display("Getting object of checked class"); + Field fooField = debuggeeClass.fieldByName("foo"); + if (fooField == null) { + throw new Failure("TEST BUG: unable to find field "); + } + try { + checkedObject = (ObjectReference)debuggeeClass.getValue(fooField); + } catch (Exception e) { + log.complain("TEST BUG: Exception while trying to get value of field : " + e.getMessage()); + e.printStackTrace(out); + testFailed = true; + } + if (checkedObject == null) { + log.complain("TEST BUG: unable to get value of field "); + testFailed = true; + } + + // create events requests + log.display("Creating requests for WatchpointEvent"); + Iterator fieldsIter; + try { + fieldsList = checkedClass.fields(); + fieldsIter = fieldsList.iterator(); + } catch (ClassNotPreparedException e) { + throw new Failure( "TEST_BUG: " + checkedClass.name() + " is not prepared"); + } + while (fieldsIter.hasNext()) { + Field refField = (Field)fieldsIter.next(); + if ((checkedRequest = erManager.createAccessWatchpointRequest(refField)) == null) { + throw new Failure("TEST BUG: unable to create AccessWatchpointRequest"); + } else { + log.display("AccessWatchpointRequest for field " + refField.name() + " created"); + checkedRequest.enable(); + } + if ((checkedRequest = erManager.createModificationWatchpointRequest(refField)) == null) { + throw new Failure("TEST BUG: unable to create ModificationWatchpointRequest"); + } else { + log.display("ModificationWatchpointRequest for field " + refField.name() + " created"); + checkedRequest.enable(); + } + requestsCount++; + } + log.display("Created total " + requestsCount + " WatchpointRequests"); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + // handle events until all expected events generated and received + while (!(done + && awpEventsCount >= EXPECTED_ACCESS_EVENTS + && mwpEventsCount >= EXPECTED_MODIFICATION_EVENTS)) { + + eventSet = null; + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + + if (eventSet == null) + continue; + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + +/* + // handle BreakpointEvent + if (event instanceof BreakpointEvent) { + + BreakpointEvent castedEvent = (BreakpointEvent) event; + ThreadReference eventThread = castedEvent.thread(); + + log.complain("BreakpointEvent is received in thread " + eventThread.name()); + + if (!(checkedThread.equals(eventThread))) { + log.complain("FAILURE 3: eventThread is not equal to checked thread"); + testFailed = true; + } + + log.display("Getting reference to stack frame"); + try { + checkedFrame = eventThread.frame(0); + } catch (Exception e) { + log.complain("TEST BUG: Exception while trying to get reference stack frame: " + e.getMessage()); + e.printStackTrace(out); + testFailed = true; + } + + log.display("Getting reference to <_object001a> variable"); + try { + checkedVariable = checkedFrame.visibleVariableByName("_object001a"); + } catch (Exception e) { + log.complain("TEST BUG: Exception while trying to get reference to <_object001a> variable: " + e.getMessage()); + e.printStackTrace(out); + testFailed = true; + } + if (checkedVariable == null) { + log.complain("TEST BUG: unable to find reference to <_object001a> variable"); + testFailed = true; + } + + log.display("Getting value of <_object001a> variable"); + try { + checkedObject = (ObjectReference)checkedFrame.getValue(checkedVariable); + } catch (Exception e) { + log.complain("TEST BUG: Exception while trying to get value of <_object001a> variable: " + e.getMessage()); + e.printStackTrace(out); + testFailed = true; + } + if (checkedObject == null) { + log.complain("TEST BUG: unable to get value of <_object001a> variable"); + testFailed = true; + } + + } +*/ + + // handle WatchpointEvent + if (event instanceof WatchpointEvent) { + WatchpointEvent castedEvent = (WatchpointEvent)event; + Value evValue = castedEvent.valueCurrent(); + Field evField = castedEvent.field(); + ObjectReference evObject = castedEvent.object(); + + if (event instanceof AccessWatchpointEvent) { + awpEventsCount++; + log.display("AccessWatchpointEvent received for " + evField.name()); + } else if (event instanceof ModificationWatchpointEvent) { + mwpEventsCount++; + log.display("ModificationWatchpointEvent received for " + evField.name()); + } + + if (castedEvent.field().isStatic()) { + if (evObject != null) { + object001.log.complain("FAILURE 1: WatchpointEvent.object() returns not null for static field"); + testFailed = true; + } else { + object001.log.display("WatchpointEvent received for static field " + castedEvent.field().name()); + } + } else { + if (evObject == null) { + object001.log.complain("FAILURE 2: WatchpointEvent.object() returns null for instance field"); + testFailed = true; + } else { + object001.log.display("WatchpointEvent received for instance field " + castedEvent.field().name()); + if (checkedObject == null) { + object001.log.complain("FAILURE 3: BreakpointEvent was not received prior to WatchpointEvent"); + testFailed = true; + } else if (!castedEvent.object().equals(checkedObject)) { + object001.log.complain("FAILURE 3: WatchpointEvent.object() does not equal to checked object"); + testFailed = true; + } + } + } + } + } + // resume each handled event set + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to generate events + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + // wait for confirmation from debugee + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (command == null || !command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // notify EventHandler that all events generated + done = true; + + // wait for all expected events received + log.display("Waiting for all expected events received"); + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + + // check for all expected events received + if (awpEventsCount == 0) { + log.complain("FAILURE 4: No AccessWatchpointEvents were received"); + testFailed = true; + } else if (awpEventsCount < EXPECTED_ACCESS_EVENTS) { + log.complain("FAILURE 4: Too few AccessWatchpointEvents were received: " + + (EXPECTED_ACCESS_EVENTS - awpEventsCount) + " not received"); + testFailed = true; + } else if (awpEventsCount > EXPECTED_ACCESS_EVENTS) { + log.complain("FAILURE 4: Too many AccessWatchpointEvents were received: " + + "extra " + (awpEventsCount - EXPECTED_ACCESS_EVENTS) + " received"); + testFailed = true; + } else { + log.display("All expected AccessWatchpointEvents were received: " + + awpEventsCount + " events"); + } + if (mwpEventsCount == 0) { + log.complain("FAILURE 4: No ModificationWatchpointEvents were received"); + testFailed = true; + } else if (mwpEventsCount < EXPECTED_MODIFICATION_EVENTS) { + log.complain("FAILURE 4: Too few ModificationWatchpointEvents were received: " + + (EXPECTED_MODIFICATION_EVENTS - mwpEventsCount) + " not received"); + testFailed = true; + } else if (mwpEventsCount > EXPECTED_MODIFICATION_EVENTS) { + log.complain("FAILURE 4: Too many ModificationWatchpointEvents were received: " + + "extra " + (mwpEventsCount - EXPECTED_MODIFICATION_EVENTS) + " received"); + testFailed = true; + } else { + log.display("All expected ModificationWatchpointEvents were received: " + + mwpEventsCount + " events"); + } + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001/TestDescription.java new file mode 100644 index 00000000000..b2793827bd9 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/WatchpointEvent/object/object001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exercises + * com.sun.jdi.event.WatchpointEvent.object() method. + * The test checks the following assertion: + * method WatchpointEvent.object() returns + * correct ObjectReference for instance field and + * null for static field. + * A debugger class - nsk.jdi.WatchpointEvent.object.object001 ; + * a debuggee class - nsk.jdi.WatchpointEvent.object.object001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates WatchpointRequests to the fields defined + * in checked class. + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee initializes its + * fields and sends command . + * The debugger switches to to listen the event during the + * time specified by parameter. Finally debugger shuts down debuggee + * by command. + * If debugger receives WatchpointEvent, it checks the assertion of the test. + * The test also fails if no WatchpointEvent was received. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointEvent.object.object001 + * nsk.jdi.WatchpointEvent.object.object001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointEvent.object.object001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001a.java new file mode 100644 index 00000000000..87dc289cbeb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001a.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointEvent.object; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class object001a { + + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + +// public static final int BREAKPOINT_LINE_NUMBER = 75; + + static final int ACCESS_COUNT = 76; + static final int MODIFICATIONS_COUNT = 100; + + public static CheckedClass foo; + + public static void main(String args[]) { +// object001a _object001a = new object001a(); + System.exit(JCK_STATUS_BASE + run(args)); + } + + static int run( String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // create instance of checked class + foo = new CheckedClass(); + + // notify debugger that debuggee started + pipe.println(COMMAND_READY); + + // wait for command GO from debugger + String command = pipe.readln(); + if (command.equals(COMMAND_QUIT)) { + return PASSED; + } + if (!command.equals(COMMAND_GO)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + + // perform actions + foo.run(); + + // notify debugger that the command done + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + return PASSED; + } +} + +// class for checking +class CheckedClass { + + boolean z0, z1[], z2[][]; + byte b0, b1[], b2[][]; + char c0, c1[], c2[][]; + double d0, d1[], d2[][]; + float f0, f1[], f2[][]; + int i0, i1[], i2[][]; + long l0, l1[], l2[][]; + short s0, s1[], s2[][]; + + static long lS0, lS1[], lS2[][]; + private long lP0, lP1[], lP2[][]; + public long lU0, lU1[], lU2[][]; + protected long lR0, lR1[], lR2[][]; + transient long lT0, lT1[], lT2[][]; + volatile long lV0, lV1[], lV2[][]; + + Boolean Z0, Z1[], Z2[][]; + Byte B0, B1[], B2[][]; + Character C0, C1[], C2[][]; + Double D0, D1[], D2[][]; + Float F0, F1[], F2[][]; + Integer I0, I1[], I2[][]; + Long L0, L1[], L2[][]; + String W0, W1[], W2[][]; + Short S0, S1[], S2[][]; + Object O0, O1[], O2[][]; + + static Long LS0, LS1[], LS2[][]; + private Long LP0, LP1[], LP2[][]; + public Long LU0, LU1[], LU2[][]; + protected Long LR0, LR1[], LR2[][]; + transient Long LT0, LT1[], LT2[][]; + volatile Long LV0, LV1[], LV2[][]; + + interface Inter {} + class Class implements Inter {} + Class X0, X1[], X2[][]; + Inter E0, E1[], E2[][]; + static Inter ES0, ES1[], ES2[][]; + private Inter EP0, EP1[], EP2[][]; + public Inter EU0, EU1[], EU2[][]; + protected Inter ER0, ER1[], ER2[][]; + transient Inter ET0, ET1[], ET2[][]; + volatile Inter EV0, EV1[], EV2[][]; + + void run() { + + z1 = new boolean[] {z0}; + z2 = new boolean[][] {z1}; + b1 = new byte[] {b0}; + b2 = new byte[][] {b1}; + c1 = new char[] {c0}; + c2 = new char[][] {c1}; + d1 = new double[] {d0}; + d2 = new double[][] {d1}; + f1 = new float[] {f0}; + f2 = new float[][] {f1}; + i1 = new int[] {i0}; + i2 = new int[][] {i1}; + l1 = new long[] {l0}; + l2 = new long[][] {l1}; + s1 = new short[] {s0}; + s2 = new short[][] {s1}; + + lS1 = new long[] {lS0}; + lS2 = new long[][] {lS1}; + lP1 = new long[] {lP0}; + lP2 = new long[][] {lP1}; + lU1 = new long[] {lU0}; + lU2 = new long[][] {lU1}; + lR1 = new long[] {lR0}; + lR2 = new long[][] {lR1}; + lT1 = new long[] {lT0}; + lT2 = new long[][] {lT1}; + lV1 = new long[] {lV0}; + lV2 = new long[][] {lV1}; + + X0 = new Class(); + X1 = new Class[] {X0}; + X2 = new Class[][] {X1}; + Z0 = new Boolean(true); + Z1 = new Boolean[] {Z0}; + Z2 = new Boolean[][] {Z1}; + B0 = new Byte(java.lang.Byte.MIN_VALUE); + B1 = new Byte[] {B0}; + B2 = new Byte[][] {B1}; + C0 = new Character(java.lang.Character.MIN_VALUE); + C1 = new Character[] {C0}; + C2 = new Character[][]{C1}; + D0 = new Double(java.lang.Double.MIN_VALUE); + D1 = new Double[] {D0}; + D2 = new Double[][] {D1}; + F0 = new Float(java.lang.Float.MIN_VALUE); + F1 = new Float[] {F0}; + F2 = new Float[][] {F1}; + I0 = new Integer(java.lang.Integer.MIN_VALUE); + I1 = new Integer[] {I0}; + I2 = new Integer[][] {I1}; + L0 = new Long(java.lang.Long.MIN_VALUE); + L1 = new Long[] {L0}; + L2 = new Long[][] {L1}; + S0 = new Short(java.lang.Short.MIN_VALUE); + S1 = new Short[] {S0}; + S2 = new Short[][] {S1}; + W0 = new String(); + W1 = new String[] {W0}; + W2 = new String[][] {W1}; + O0 = new Object(); + O1 = new Object[] {O0}; + O2 = new Object[][] {O1}; + + LS0 = new Long(java.lang.Long.MAX_VALUE); + LS1 = new Long[] {LS0}; + LS2 = new Long[][] {LS1}; + LP0 = new Long(java.lang.Long.MAX_VALUE); + LP1 = new Long[] {LP0}; + LP2 = new Long[][] {LP1}; + LU0 = new Long(java.lang.Long.MAX_VALUE); + LU1 = new Long[] {LU0}; + LU2 = new Long[][] {LU1}; + LR0 = new Long(java.lang.Long.MAX_VALUE); + LR1 = new Long[] {LR0}; + LR2 = new Long[][] {LR1}; + LT0 = new Long(java.lang.Long.MAX_VALUE); + LT1 = new Long[] {LT0}; + LT2 = new Long[][] {LT1}; + LV0 = new Long(java.lang.Long.MAX_VALUE); + LV1 = new Long[] {LV0}; + LV2 = new Long[][] {LV1}; + + E0 = new Class(); + E1 = new Inter[] {E0}; + E2 = new Inter[][] {E1}; + ES0 = new Class(); + ES1 = new Inter[] {ES0}; + ES2 = new Inter[][] {ES1}; + EP0 = new Class(); + EP1 = new Inter[] {EP0}; + EP2 = new Inter[][] {EP1}; + EU0 = new Class(); + EU1 = new Inter[] {EU0}; + EU2 = new Inter[][] {EU1}; + ER0 = new Class(); + ER1 = new Inter[] {ER0}; + ER2 = new Inter[][] {ER1}; + ET0 = new Class(); + ET1 = new Inter[] {ET0}; + ET2 = new Inter[][] {ET1}; + EV0 = new Class(); + EV1 = new Inter[] {EV0}; + EV2 = new Inter[][] {EV1}; + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001.java new file mode 100644 index 00000000000..34a0fad1f53 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointEvent.valueCurrent; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.*; +import java.util.Iterator; +import java.util.List; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugger in the test + +public class valuecur001 { + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final int TIMEOUT_DELTA = 1000; // milliseconds + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + static final String DEBUGGEE_NAME = "nsk.jdi.WatchpointEvent.valueCurrent.valuecur001a"; + static final String CHECKED_CLASS_NAME = "nsk.jdi.WatchpointEvent.valueCurrent.CheckedClass"; + + static private Debugee debuggee; + static private VirtualMachine vm; + static private IOPipe pipe; + static private Log log; + static private ArgumentHandler argHandler; + static private EventSet eventSet; + + static private ReferenceType rType; + static private WatchpointRequest checkedRequest; + static private List fieldsList; + + static private volatile boolean testFailed; + static private volatile boolean done; + static private volatile int requestsCount, awpEventsCount, mwpEventsCount; + + public static void main (String args[]) { + System.exit(run(args, System.out) + JCK_STATUS_BASE); + } + + public static int run(final String args[], final PrintStream out) { + + testFailed = false; + requestsCount = 0; + awpEventsCount = 0; + mwpEventsCount = 0; + + argHandler = new ArgumentHandler(args); + log = new Log(out, argHandler); + + // launch debuggee + Binder binder = new Binder(argHandler, log); + log.display("Connecting to debuggee"); + debuggee = binder.bindToDebugee(DEBUGGEE_NAME); + debuggee.redirectStderr(log, "valuecur001a >"); + pipe = debuggee.createIOPipe(); + vm = debuggee.VM(); + + // resume debuggee + log.display("Resuming debuggee"); + debuggee.resume(); + + // check debuggee's capabilities + if (!debuggee.VM().canWatchFieldAccess()) { + log.display("TEST WARNING: test passed because JDI implementation does not support " + + "watchpoints for field access"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return PASSED; + } + + if (!debuggee.VM().canWatchFieldModification()) { + log.display("TEST WARNING: test passed because JDI implementation does not support " + + "watchpoints for field modification"); + pipe.println(COMMAND_QUIT); + debuggee.waitFor(); + return PASSED; + } + + try { + + // wait for debuggee started + log.display("Waiting for command: " + COMMAND_READY); + String command = pipe.readln(); + if (!command.equals(COMMAND_READY)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // get mirrors + if ((rType = debuggee.classByName(CHECKED_CLASS_NAME)) == null) { + throw new Failure("TEST BUG: cannot find " + CHECKED_CLASS_NAME); + } + + // create events requests + log.display("Creating requests for WatchpointEvent"); + EventRequestManager erManager = debuggee.VM().eventRequestManager(); + Iterator fieldsIter; + try { + fieldsList = rType.fields(); + fieldsIter = fieldsList.iterator(); + } catch (ClassNotPreparedException e) { + throw new Failure( "TEST_BUG: " + rType.name() + " is not prepared"); + } + while (fieldsIter.hasNext()) { + Field refField = (Field)fieldsIter.next(); + if ((checkedRequest = erManager.createAccessWatchpointRequest(refField)) == null) { + throw new Failure("TEST BUG: unable to create AccessWatchpointRequest"); + } else { + log.display("AccessWatchpointRequest for field " + refField.name() + " created"); + checkedRequest.enable(); + } + if ((checkedRequest = erManager.createModificationWatchpointRequest(refField)) == null) { + throw new Failure("TEST BUG: unable to create ModificationWatchpointRequest"); + } else { + log.display("ModificationWatchpointRequest for field " + refField.name() + " created"); + checkedRequest.enable(); + } + requestsCount++; + } + log.display("Created total " + requestsCount + " WatchpointRequests"); + + // define separate thread for handling events + class EventHandler extends Thread { + public void run() { + eventSet = null; + try { + // handle events until all events generated and received + while ( awpEventsCount < requestsCount + || mwpEventsCount < requestsCount ) { + + eventSet = null; + eventSet = vm.eventQueue().remove(TIMEOUT_DELTA); + + if (eventSet == null) + continue; + + EventIterator eventIterator = eventSet.eventIterator(); + while (eventIterator.hasNext()) { + + Event event = eventIterator.nextEvent(); + + // handle WatchpointEvent + if (event instanceof WatchpointEvent) { + WatchpointEvent castedEvent = (WatchpointEvent)event; + Value evValue = castedEvent.valueCurrent(); + Field evField = castedEvent.field(); + + if (event instanceof AccessWatchpointEvent) { + awpEventsCount++; + log.display("AccessWatchpointEvent received for " + evField.name()); + } else if (event instanceof ModificationWatchpointEvent) { + mwpEventsCount++; + log.display("ModificationWatchpointEvent received for " + evField.name()); + } + + if (evValue == null) { + log.complain("FAILURE 1: WatchpointEvent.valueCurrent() returns null for " + evField.name()); + testFailed = true; + } else { + int ind = fieldsList.indexOf(evField); + if (ind == -1) { + log.complain("FAILURE 2: Watchpoint.field() returns unknown field"); + testFailed = true; + } else { + Value valueCur = castedEvent.valueCurrent(); + Value valueFld; + try { + valueFld = castedEvent.object().getValue(evField); + } catch (NullPointerException e) { + // field is static + valueFld = rType.getValue(evField); + } + if (!valueFld.equals(valueCur)) { + log.complain("FAILURE 3: Watchpoint.valueCurrent() returns incorrect value for " + + evField.name() + "\nvalueCurrent(): " + valueCur + " ; getValue(): " + valueFld); + testFailed = true; + } else { + valuecur001.log.display(evField.name() + " equals to " + castedEvent.valueCurrent().toString()); + } + } + } + } + } + eventSet.resume(); + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: caught InterruptedException while waiting for event"); + testFailed = true; + } catch (VMDisconnectedException e) { + log.complain("TEST INCOMPLETE: caught VMDisconnectedException while waiting for event"); + testFailed = true; + } + log.display("eventHandler completed"); + } + } + + // start event handling thread + EventHandler eventHandler = new EventHandler(); + log.display("Starting eventHandler"); + eventHandler.start(); + + // force debuggee to generate events + log.display("Sending command: " + COMMAND_GO); + pipe.println(COMMAND_GO); + + // wait for confirmation from debugee + log.display("Waiting for command: " + COMMAND_DONE); + command = pipe.readln(); + if (command == null || !command.equals(COMMAND_DONE)) { + throw new Failure("TEST BUG: unexpected debuggee's command: " + command); + } + + // notify EventHandler that all events generated + done = true; + + // wait for all expected events received + log.display("Waiting for all expected events received"); + try { + eventHandler.join(argHandler.getWaitTime()*60000); + if (eventHandler.isAlive()) { + log.complain("FAILURE 20: Timeout for waiting of event was exceeded"); + eventHandler.interrupt(); + testFailed = true; + } + } catch (InterruptedException e) { + log.complain("TEST INCOMPLETE: InterruptedException caught while waiting for eventHandler's death"); + testFailed = true; + } + } catch (Failure e) { + log.complain("TEST FAILURE: " + e.getMessage()); + testFailed = true; + } catch (Exception e) { + log.complain("Unexpected exception: " + e); + e.printStackTrace(out); + testFailed = true; + } finally { + + log.display(""); + + // force debugee to exit + log.display("Sending command: " + COMMAND_QUIT); + pipe.println(COMMAND_QUIT); + + // wait for debuggee exits and analize its exit code + log.display("Waiting for debuggee terminating"); + int debuggeeStatus = debuggee.endDebugee(); + if (debuggeeStatus == PASSED + JCK_STATUS_BASE) { + log.display("Debuggee PASSED with exit code: " + debuggeeStatus); + } else { + log.complain("Debuggee FAILED with exit code: " + debuggeeStatus); + testFailed = true; + } + } + + // check test results + if (testFailed) { + log.complain("TEST FAILED"); + return FAILED; + } + + log.display("TEST PASSED"); + return PASSED; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001/TestDescription.java new file mode 100644 index 00000000000..db9d7a238f3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001/TestDescription.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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 + * @modules java.base/jdk.internal.misc:+open + * + * @summary converted from VM Testbase nsk/jdi/WatchpointEvent/valueCurrent/valuecur001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION + * This test exercises + * com.sun.jdi.event.WatchpointEvent.valueCurrent() method. + * The test checks the following assertion: + * the Value reference returned by WatchpointEvent.valueCurrent() + * equals to one returned by ObjectReference.getValue() for instance + * field or to one returned ReferenceType.getValue() for static field. + * A debugger class - nsk.jdi.WatchpointEvent.valueCurrent.valuecur001 ; + * a debuggee class - nsk.jdi.WatchpointEvent.valueCurrent.valuecur001a . + * The test uses supporting nsk/jdi/share classes for launching debuggee + * and for creating communication pipe between debugger and debuggee. The + * debugger and debugee communicates with special commands. + * The debugger creates WatchpointRequests to the fields defined + * in debuggee class. + * The debugger starts thread for listening events delivered + * from debuggee. + * Upon receiving command from debugger, the debuggee initializes its + * fields and sends command . + * The debugger switches to to listen the event during the + * time specified by parameter. Then debugger shuts down debuggee + * by command. + * If debugger receives WatchpointEvent, it checks the assertion of the test. + * The test also fails if no WatchpointEvent was received. + * COMMENTS + * Test fixed due to bug: + * 4455653 VMDisconnectedException on resume + * ----------------- + * The test has been modified as follows. + * 1. To fix the bug 4505743, + * foo.run(); is added right after + * CheckedClass foo = new CheckedClass(); (line 37 in valuecur001a.java) + * 2. As the test contains unnecessary check on numbers of received events, + * hence wrong because the spec for the method doesn't require to check, + * the check is removed. + * A special test with such check against the inteface will be added. + * 3. The number of checks on AccessWatchpointEvents put in correcpondence with + * the number of checks on ModificationWatchpointEvents. + * ----------------- + * Standard method Debugee.endDebugee() is used instead of cleaning + * event queue on debuggee VM exit. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointEvent.valueCurrent.valuecur001 + * nsk.jdi.WatchpointEvent.valueCurrent.valuecur001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointEvent.valueCurrent.valuecur001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001a.java new file mode 100644 index 00000000000..b9ae0a1ae3b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001a.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointEvent.valueCurrent; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + + +// This class is the debugged application in the test + +class valuecur001a { + + static final int PASSED = 0; + static final int FAILED = 2; + static final int JCK_STATUS_BASE = 95; + + static final String COMMAND_READY = "ready"; + static final String COMMAND_QUIT = "quit"; + static final String COMMAND_GO = "go"; + static final String COMMAND_DONE = "done"; + + public static void main(String args[]) { + System.exit(JCK_STATUS_BASE + run(args)); + } + + static int run(String args[]) { + ArgumentHandler argHandler = new ArgumentHandler(args); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + + // create instance of checked class + CheckedClass foo = new CheckedClass(); + foo.run(); + + // notify debuggeer that debuggee started + pipe.println(COMMAND_READY); + + // wait for command GO from debugger + String command = pipe.readln(); + if (command.equals(COMMAND_QUIT)) { + return PASSED; + } + if (!command.equals(COMMAND_GO)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + + // perform actions + foo.run(); + + // notify debugger that the command done + pipe.println(COMMAND_DONE); + + // wait for command QUIT from debugger and exit + command = pipe.readln(); + if (!command.equals(COMMAND_QUIT)) { + System.err.println("TEST BUG: unknown command: " + command); + return FAILED; + } + return PASSED; + } +} + +// class for checking +class CheckedClass { + + boolean z0, z1[], z2[][]; + byte b0, b1[], b2[][]; + char c0, c1[], c2[][]; + double d0, d1[], d2[][]; + float f0, f1[], f2[][]; + int i0, i1[], i2[][]; + long l0, l1[], l2[][]; + short s0, s1[], s2[][]; + + static long lS0, lS1[], lS2[][]; + private long lP0, lP1[], lP2[][]; + public long lU0, lU1[], lU2[][]; + protected long lR0, lR1[], lR2[][]; + transient long lT0, lT1[], lT2[][]; + volatile long lV0, lV1[], lV2[][]; + + Boolean Z0, Z1[], Z2[][]; + Byte B0, B1[], B2[][]; + Character C0, C1[], C2[][]; + Double D0, D1[], D2[][]; + Float F0, F1[], F2[][]; + Integer I0, I1[], I2[][]; + Long L0, L1[], L2[][]; + String W0, W1[], W2[][]; + Short S0, S1[], S2[][]; + Object O0, O1[], O2[][]; + + static Long LS0, LS1[], LS2[][]; + private Long LP0, LP1[], LP2[][]; + public Long LU0, LU1[], LU2[][]; + protected Long LR0, LR1[], LR2[][]; + transient Long LT0, LT1[], LT2[][]; + volatile Long LV0, LV1[], LV2[][]; + + interface Inter {} + class Class implements Inter {} + Class X0, X1[], X2[][]; + Inter E0, E1[], E2[][]; + static Inter ES0, ES1[], ES2[][]; + private Inter EP0, EP1[], EP2[][]; + public Inter EU0, EU1[], EU2[][]; + protected Inter ER0, ER1[], ER2[][]; + transient Inter ET0, ET1[], ET2[][]; + volatile Inter EV0, EV1[], EV2[][]; + + void run() { + + z0 = true; + b0 = 0; + c0 = 0; + d0 = 0; + f0 = 0; + i0 = 0; + l0 = 0; + s0 = 0; + + lS0 = 0; + lP0 = 0; + lU0 = 0; + lR0 = 0; + lT0 = 0; + lV0 = 0; + + z1 = new boolean[] {z0}; + z2 = new boolean[][] {z1}; + b1 = new byte[] {b0}; + b2 = new byte[][] {b1}; + c1 = new char[] {c0}; + c2 = new char[][] {c1}; + d1 = new double[] {d0}; + d2 = new double[][] {d1}; + f1 = new float[] {f0}; + f2 = new float[][] {f1}; + i1 = new int[] {i0}; + i2 = new int[][] {i1}; + l1 = new long[] {l0}; + l2 = new long[][] {l1}; + s1 = new short[] {s0}; + s2 = new short[][] {s1}; + + lS1 = new long[] {lS0}; + lS2 = new long[][] {lS1}; + lP1 = new long[] {lP0}; + lP2 = new long[][] {lP1}; + lU1 = new long[] {lU0}; + lU2 = new long[][] {lU1}; + lR1 = new long[] {lR0}; + lR2 = new long[][] {lR1}; + lT1 = new long[] {lT0}; + lT2 = new long[][] {lT1}; + lV1 = new long[] {lV0}; + lV2 = new long[][] {lV1}; + + X0 = new Class(); + X1 = new Class[] {X0}; + X2 = new Class[][] {X1}; + Z0 = new Boolean(true); + Z1 = new Boolean[] {Z0}; + Z2 = new Boolean[][] {Z1}; + B0 = new Byte(java.lang.Byte.MIN_VALUE); + B1 = new Byte[] {B0}; + B2 = new Byte[][] {B1}; + C0 = new Character(java.lang.Character.MIN_VALUE); + C1 = new Character[] {C0}; + C2 = new Character[][]{C1}; + D0 = new Double(java.lang.Double.MIN_VALUE); + D1 = new Double[] {D0}; + D2 = new Double[][] {D1}; + F0 = new Float(java.lang.Float.MIN_VALUE); + F1 = new Float[] {F0}; + F2 = new Float[][] {F1}; + I0 = new Integer(java.lang.Integer.MIN_VALUE); + I1 = new Integer[] {I0}; + I2 = new Integer[][] {I1}; + L0 = new Long(java.lang.Long.MIN_VALUE); + L1 = new Long[] {L0}; + L2 = new Long[][] {L1}; + S0 = new Short(java.lang.Short.MIN_VALUE); + S1 = new Short[] {S0}; + S2 = new Short[][] {S1}; + W0 = new String(); + W1 = new String[] {W0}; + W2 = new String[][] {W1}; + O0 = new Object(); + O1 = new Object[] {O0}; + O2 = new Object[][] {O1}; + + LS0 = new Long(java.lang.Long.MAX_VALUE); + LS1 = new Long[] {LS0}; + LS2 = new Long[][] {LS1}; + LP0 = new Long(java.lang.Long.MAX_VALUE); + LP1 = new Long[] {LP0}; + LP2 = new Long[][] {LP1}; + LU0 = new Long(java.lang.Long.MAX_VALUE); + LU1 = new Long[] {LU0}; + LU2 = new Long[][] {LU1}; + LR0 = new Long(java.lang.Long.MAX_VALUE); + LR1 = new Long[] {LR0}; + LR2 = new Long[][] {LR1}; + LT0 = new Long(java.lang.Long.MAX_VALUE); + LT1 = new Long[] {LT0}; + LT2 = new Long[][] {LT1}; + LV0 = new Long(java.lang.Long.MAX_VALUE); + LV1 = new Long[] {LV0}; + LV2 = new Long[][] {LV1}; + + E0 = new Class(); + E1 = new Inter[] {E0}; + E2 = new Inter[][] {E1}; + ES0 = new Class(); + ES1 = new Inter[] {ES0}; + ES2 = new Inter[][] {ES1}; + EP0 = new Class(); + EP1 = new Inter[] {EP0}; + EP2 = new Inter[][] {EP1}; + EU0 = new Class(); + EU1 = new Inter[] {EU0}; + EU2 = new Inter[][] {EU1}; + ER0 = new Class(); + ER1 = new Inter[] {ER0}; + ER2 = new Inter[][] {ER1}; + ET0 = new Class(); + ET1 = new Inter[] {ET0}; + ET2 = new Inter[][] {ET1}; + EV0 = new Class(); + EV1 = new Inter[] {EV0}; + EV2 = new Inter[][] {EV1}; + + m(z2); m(b2); m(c2); m(d2); m(f2); m(i2); m(l2); m(s2); + + m(lS2); m(lP2); m(lU2); m(lR2); m(lT2); m(lV2); + + m(X2); m(Z2); m(B2); m(C2); m(D2); m(F2); m(I2); m(S2); m(W2); m(O2); + + m(LS2); m(LP2); m(LU2); m(LR2); m(LT2); m(LV2); + + m(X2); m(E2); m(ES2); m(EP2); m(EU2); m(ER2); m(ET2); m(EV2); + + } + + void m(Object obj) { + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001.java new file mode 100644 index 00000000000..8a444234744 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.WatchpointRequest._bounds_; + +import nsk.share.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.request.*; + +import java.io.*; + +/** + * The test checks up the
    + * - addThreadFilter(ThreadReference)
    + * - addInstanceFilter(ObjectReference)
    + * - addClassFilter(ReferenceType)
    + * - addClassFilter(String)
    + * - addClassExclusionFilter(String)
    + * methods with null argument value.
    + *

    + * This test performs checking for the AccessWatchpointRequest and + * ModificationWatchpointRequest instances. In any cases + * NullPointerException is expected. + */ +public class filters001 { + + private final static String prefix = "nsk.jdi.WatchpointRequest._bounds_."; + private final static String debuggerName = prefix + "filters001"; + private final static String debugeeName = debuggerName + "a"; + + private static int exitStatus; + private static Log log; + private static Debugee debugee; + + private static void display(String msg) { + log.display("debugger> " + msg); + } + + private static void complain(String msg) { + log.complain("debugger FAILURE> " + msg + "\n"); + } + + public static void main(String argv[]) { + System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); + } + + public static int run(String argv[], PrintStream out) { + + exitStatus = Consts.TEST_PASSED; + + filters001 thisTest = new filters001(); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + log = new Log(out, argHandler); + + debugee = Debugee.prepareDebugee(argHandler, log, debugeeName); + + thisTest.execTest(); + display("execTest finished. exitStatus = " + exitStatus); + + return exitStatus; + } + + private void execTest() { + + ReferenceType refType = debugee.classByName(debugeeName); + Field field = refType.fieldByName(filters001a.fieldName); + + EventRequestManager evm = debugee.getEventRequestManager(); + WatchpointRequest[] request = new WatchpointRequest[2]; + request[0] = evm.createAccessWatchpointRequest(field); + request[1] = evm.createModificationWatchpointRequest(field); + + for (int i = 0; i < request.length; i++) { + display(""); + if (i == 0 ) { + display(">>>checking AccessWatchpointRequest"); + } else { + display(">>>checking ModificationWatchpointRequest"); + } + display("-----------------------------------------"); + addThreadFilter(request[i], null); + + display(""); + addInstanceFilter(request[i], null); + + display(""); + addClassFilter(request[i], (ReferenceType )null); + + display(""); + addClassFilter(request[i], (String )null); + + display(""); + addClassExclusionFilter(request[i], (String )null); + } + display(""); + debugee.quit(); + } + + private void addThreadFilter(WatchpointRequest request, ThreadReference thread) { + String tmp = "addThreadFilter :thread name> "; + tmp += (thread == null) ? "" : thread.name(); + display(tmp); + + try { + request.addThreadFilter(thread); + if (thread==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (thread == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addInstanceFilter(WatchpointRequest request, + ObjectReference instance) { + String tmp = "addInstanceFilter :object value> "; + tmp += (instance == null) ? "" : instance.toString(); + display(tmp); + + try { + request.addInstanceFilter(instance); + if (instance==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (instance == null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(WatchpointRequest request, ReferenceType refType) { + + display("addClassFilter :ReferenceType> <" + refType + ">"); + + try { + request.addClassFilter(refType); + if (refType==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (refType==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassFilter(WatchpointRequest request, String classPattern) { + + display("addClassFilter :classPattern> <" + classPattern + ">"); + try { + request.addClassFilter(classPattern); + if (classPattern==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (classPattern==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + + private void addClassExclusionFilter(WatchpointRequest request, + String classPattern) { + display("addExclusionClassFilter :classPattern> <" + classPattern + ">"); + try { + request.addClassExclusionFilter(classPattern); + if (classPattern==null){ + complain("*****NullPointerException is not thrown"); + exitStatus = Consts.TEST_FAILED; + } + } catch (NullPointerException e) { + if (classPattern==null){ + display("!!!Expected " + e); + } else { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } catch (Exception e) { + complain("*****Unexpected " + e); + exitStatus = Consts.TEST_FAILED; + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001/TestDescription.java new file mode 100644 index 00000000000..748151cb36a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001/TestDescription.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/_bounds_/filters001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the boundary value of the parameters. + * The test checks up that the methods + * com.sun.jdi.request.WatchpointRequest.addThreadFilter(ThreadReference) + * com.sun.jdi.request.WatchpointRequest.addInstanceFilter(ObjectReference) + * com.sun.jdi.request.WatchpointRequest.addClassFilter(ReferenceType) + * com.sun.jdi.request.WatchpointRequest.addClassFilter(String) + * com.sun.jdi.request.WatchpointRequest.addClassExclusionFilter(String) + * correctly work for the boundary value of parameter and throw described + * exceptions. + * The test check up this methods with argument value. The test + * performs checking for the AccessWatchpointRequest and + * ModificationWatchpointRequest instances. In any cases + * NullPointerException is expected. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest._bounds_.filters001 + * nsk.jdi.WatchpointRequest._bounds_.filters001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest._bounds_.filters001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001a.java new file mode 100644 index 00000000000..a3be022b500 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/_bounds_/filters001a.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002, 2018, 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 nsk.jdi.WatchpointRequest._bounds_; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * filters001a is deugee's part of the test. + */ +public class filters001a { + + static String fieldName = "justField"; + + static int justField = 0; + + public static void main (String argv[]) { + + ArgumentHandler argHandler = new ArgumentHandler(argv); + Log log = new Log(System.err, argHandler); + IOPipe pipe = argHandler.createDebugeeIOPipe(log); + + pipe.println("ready"); + + String instr = pipe.readln(); + + if (instr.equals("quit")) { + log.display("DEBUGEE> completed succesfully."); + System.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); + } + + log.complain("DEBUGEE> unexpected signal of debugger."); + System.exit(Consts.TEST_FAILED + Consts.JCK_STATUS_BASE); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001.java new file mode 100644 index 00000000000..7446bd971e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addClassExclusionFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to check include both a pattern that begin with '*' and + * one that end with '*'. + * - The debugger + * - sets up two WatchpointRequests, + * - using patterns that begins with '*' and ends with *, + * restricts the Requests, + * - waits for expected WatchpointEvents. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, throw NullPointerExceptions used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter001a"; + return new filter001().runThis(argv, out); + } + + private String classExclFilter1 = "*TestClass11"; + private String classExclFilter2 = + "nsk.jdi.WatchpointRequest.addClassExclusionFilter.TestClass21*"; + + private String classExclName1 = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.TestClass11"; + private String classExclName2 = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.TestClass21"; + + private String className1 = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.TestClass10"; + private String className2 = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.TestClass20"; + + protected void testRun() { + + if ( !vm.canWatchFieldAccess() ) { + display("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "AccessWatchpointRequest1"; + String property2 = "AccessWatchpointRequest2"; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String fieldName1 = "var101"; + String fieldName2 = "var201"; + + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(className1).get(0); + + eventRequest1 = setting23AccessWatchpointRequest (null, + testClassReference, fieldName1, + classExclFilter1, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for AccessWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("ERROR: new event is not AccessWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new AccessWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + String str = ((AccessWatchpointEvent) newEvent).location().declaringType().name(); + display(" Class name == " + str); + if (str.endsWith(classExclName1)) { + setFailedStatus("ERROR: name of Class ends with the testing pattern: " + str); + } + } + vm.resume(); + break; + + case 1: + testClassReference = + (ReferenceType) vm.classesByName(className2).get(0); + + eventRequest2 = setting23AccessWatchpointRequest (null, + testClassReference, fieldName2, + classExclFilter2, + EventRequest.SUSPEND_ALL, property2); + + display("......waiting for AccessWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("ERROR: new event is not AccessWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new AccessWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property2) ) { + setFailedStatus("ERROR: property is not : " + property2); + } + + String str = ((AccessWatchpointEvent) newEvent).location().declaringType().name(); + display(" Class name == " + str); + if (str.endsWith(classExclName2)) { + setFailedStatus("ERROR: name of Class ends with the testing pattern: " + str); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private AccessWatchpointRequest setting23AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + String classExclFilter, + int suspendPolicy, + String property ) { + try { + display("......setting up AccessWatchpointRequest:"); + display(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + awr.addClassExclusionFilter(classExclFilter); + + display(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up AccessWatchpointRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001/TestDescription.java new file mode 100644 index 00000000000..bcf8273551c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name does not match a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to test include AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter001; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter001 + * nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001a.java new file mode 100644 index 00000000000..708da9194f4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter001a.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter001 JDI test. + */ + +public class filter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter001a thread1 = null; + static Thread2filter001a thread2 = null; + + static TestClass10 obj10 = new TestClass10(); + static TestClass11 obj11 = new TestClass11(); + static TestClass20 obj20 = new TestClass20(); + static TestClass21 obj21 = new TestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter001a("thread1"); + log1("run1(thread1);"); + run1(thread1); + + break; + + case 1: + thread2 = new Thread2filter001a("thread2"); + log1("run1(thread2);"); + run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + threadStart(t); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + + + static class Thread1filter001a extends Thread { + + String tName = null; + + public Thread1filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + obj10.method(); + obj11.method(); + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + + static class Thread2filter001a extends Thread { + + String tName = null; + + public Thread2filter001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + obj20.method(); + obj21.method(); + log1(" 'run': exit :: threadName == " + tName); + return; + } + } +} + +class TestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class TestClass11 extends TestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; +// TestClass10.method(); + } +} + +class TestClass20 { + + static int var201 = 0; + static int var202 = 0; + static int var203 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + } +} +class TestClass21 extends TestClass20 { + + static int var211 = 0; + static int var212 = 0; + static int var213 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + + var211 = 1; + var213 = var211; + var212 = var213; +// TestClass20.method(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002.java new file mode 100644 index 00000000000..ecf875735db --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addClassExclusionFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to check include both a pattern that begin with '*' and + * one that end with '*'. + * - The debugger + * - sets up two WatchpointRequests, + * - using patterns that begins with '*' and ends with *, + * restricts the Requests, + * - waits for expected WatchpointEvents. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, throw NullPointerExceptions used + * to generate Events and to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter002 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002a"; + return new filter002().runThis(argv, out); + } + + private String classExclFilter1 = "*filter002aTestClass11"; + private String classExclFilter2 = + "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002aTestClass21*"; + + private String classExclName1 = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002aTestClass11"; + private String classExclName2 = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002aTestClass21"; + + private String className1 = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002aTestClass10"; + private String className2 = "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002aTestClass20"; + + protected void testRun() { + + if ( !vm.canWatchFieldModification() ) { + display("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "ModificationWatchpointRequest1"; + String property2 = "ModificationWatchpointRequest2"; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String fieldName1 = "var101"; + String fieldName2 = "var201"; + + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(className1).get(0); + + eventRequest1 = setting23ModificationWatchpointRequest (null, + testClassReference, fieldName1, + classExclFilter1, + EventRequest.SUSPEND_ALL, property1); + + display("......waiting for ModificationWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("ERROR: new event is not ModificationWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ModificationWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + + String str = ((ModificationWatchpointEvent) newEvent).location().declaringType().name(); + display(" Class name == " + str); + if (str.endsWith(classExclName1)) { + setFailedStatus("ERROR: name of Class ends with the testing pattern: " + str); + } + } + vm.resume(); + break; + + case 1: + testClassReference = + (ReferenceType) vm.classesByName(className2).get(0); + + eventRequest2 = setting23ModificationWatchpointRequest (null, + testClassReference, fieldName2, + classExclFilter2, + EventRequest.SUSPEND_ALL, property2); + + display("......waiting for ModificationWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("ERROR: new event is not ModificationWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ModificationWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property2) ) { + setFailedStatus("ERROR: property is not : " + property2); + } + + String str = ((ModificationWatchpointEvent) newEvent).location().declaringType().name(); + display(" Class name == " + str); + if (str.endsWith(classExclName2)) { + setFailedStatus("ERROR: name of Class ends with the testing pattern: " + str); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ModificationWatchpointRequest setting23ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + String classExclFilter, + int suspendPolicy, + String property ) { + try { + display("......setting up ModificationWatchpointRequest:"); + display(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + awr.addClassExclusionFilter(classExclFilter); + + display(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ModificationWatchpointRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002/TestDescription.java new file mode 100644 index 00000000000..0d041f634bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name does not match a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to test include ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002 + * nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002a.java new file mode 100644 index 00000000000..b034912dc23 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter002a.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter002 JDI test. + */ + +public class filter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter002a thread1 = null; + static Thread2filter002a thread2 = null; + + static filter002aTestClass10 obj10 = new filter002aTestClass10(); + static filter002aTestClass11 obj11 = new filter002aTestClass11(); + static filter002aTestClass20 obj20 = new filter002aTestClass20(); + static filter002aTestClass21 obj21 = new filter002aTestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter002a("thread1"); + log1("run1(thread1);"); + run1(thread1); + + break; + + case 1: + thread2 = new Thread2filter002a("thread2"); + log1("run1(thread2);"); + run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + threadStart(t); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + + + static class Thread1filter002a extends Thread { + + String tName = null; + + public Thread1filter002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + obj10.method(); + obj11.method(); + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + + static class Thread2filter002a extends Thread { + + String tName = null; + + public Thread2filter002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + obj20.method(); + obj21.method(); + log1(" 'run': exit :: threadName == " + tName); + return; + } + } +} + +class filter002aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter002aTestClass11 extends filter002aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; +// TestClass10.method(); + } +} + +class filter002aTestClass20 { + + static int var201 = 0; + static int var202 = 0; + static int var203 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + } +} +class filter002aTestClass21 extends filter002aTestClass20 { + + static int var211 = 0; + static int var212 = 0; + static int var213 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + + var211 = 1; + var213 = var211; + var212 = var213; +// filter002aTestClass20.method(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java new file mode 100644 index 00000000000..27de4de00fd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addClassExclusionFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + * The cases to test include AccessWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an AccessWatchpointRequest and enables it,
    + * - invokes the method addClassExclusionFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassExclusionFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassExclusionFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter003a"; + + private String testedClassName1 = + "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter003aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + String property1 = "AccessWatchpointRequest1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName1).get(0); + + eventRequest1 = setting23AccessWatchpointRequest (null, + testClassReference, fieldName1, + testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest setting23AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + awr.addClassExclusionFilter(testedClass); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003/TestDescription.java new file mode 100644 index 00000000000..41e38d1d1ba --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name does not match a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter003; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter003 + * nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003a.java new file mode 100644 index 00000000000..e7b5c4880d8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003a.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter003 JDI test. + */ + +public class filter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter003aTestClass10 obj10 = new filter003aTestClass10(); + static filter003aTestClass11 obj11 = new filter003aTestClass11(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +/* + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +*/ +} + +class filter003aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter003aTestClass11 extends filter003aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; +// filter003aTestClass10.method(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java new file mode 100644 index 00000000000..c405dfbac72 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addClassExclusionFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + * The cases to test include ModificationWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ModificationWatchpointRequest and enables it,
    + * - invokes the method addClassExclusionFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassExclusionFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassExclusionFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter004a"; + + private String testedClassName1 = + "nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter004aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + String property1 = "ModificationWatchpointRequest1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName1).get(0); + + eventRequest1 = setting23ModificationWatchpointRequest (null, + testClassReference, fieldName1, + testedClassName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest setting23ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + String testedClass, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + awr.addClassExclusionFilter(testedClass); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004/TestDescription.java new file mode 100644 index 00000000000..b2b07fdcc5f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassExclusionFilter() + * complies with its spec: + * public void addClassExclusionFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name does not match a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter against. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The cases to test include ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter004; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter004 + * nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassExclusionFilter.filter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004a.java new file mode 100644 index 00000000000..a832e079ec0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004a.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassExclusionFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter004 JDI test. + */ + +public class filter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter004aTestClass10 obj10 = new filter004aTestClass10(); + static filter004aTestClass11 obj11 = new filter004aTestClass11(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +/* + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +*/ +} + +class filter004aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter004aTestClass11 extends filter004aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; +// filter004aTestClass10.method(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001.java new file mode 100644 index 00000000000..06500aa6a94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those whose + * location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * The case to test include AccessWatchpointRequest. + * + * The test works as follows: + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates objects of ClassTypes to test and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a WatchpointRequest, + * - gets ReferenecType and, using it, restricts the Request, + * - resumes the debuggee and waits for expected WatchpointEvent. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, invokes methods performing access to fileds, + * used to generate Event and to test the filters. + * - Upon getting the event, the debugger performs checks required. + */ + +public class filter_rt001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt001a"; + return new filter_rt001().runThis(argv, out); + } + + String className1 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.TestClass10"; + String className2 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.TestClass11"; + + + protected void testRun() { + + if ( !vm.canWatchFieldAccess() ) { + display("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + String property1 = "AccessWatchpointRequest1"; + ThreadReference thread1 = null; + String thread1Name = "thread1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(className1).get(0); + + eventRequest1 = setting21AccessWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_ALL, property1); + + testClassReference = + (ReferenceType) vm.classesByName(className2).get(0); + + ((AccessWatchpointRequest) eventRequest1).addClassFilter(testClassReference); + + display("......waiting for AccessWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("ERROR: new event is not AccessWatchpointEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new AccessWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private AccessWatchpointRequest setting21AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up AccessWatchpointRequest:"); + display(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001/TestDescription.java new file mode 100644 index 00000000000..6305c3d00fe --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * The cases to test include AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt001; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt001 + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001a.java new file mode 100644 index 00000000000..46f26faaf60 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt001a.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt001 JDI test. + */ + +public class filter_rt001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_rt001a thread1 = null; + static Thread2filter_rt001a thread2 = null; + + static TestClass10 obj10 = new TestClass10(); + static TestClass11 obj11 = new TestClass11(); + + static Thread2filter_rt001a.TestClass20 obj20 = new Thread2filter_rt001a.TestClass20(); + static Thread2filter_rt001a.TestClass21 obj21 = new Thread2filter_rt001a.TestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_rt001a("thread1"); + log1("run1(thread1);"); + run1(thread1); + + thread2 = new Thread2filter_rt001a("thread2"); + log1("run1(thread2);"); + run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + threadStart(t); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class TestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class TestClass11 extends TestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1filter_rt001a extends Thread { + + String tName = null; + + public Thread1filter_rt001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_rt001a.waitnotifyObj) { + filter_rt001a.waitnotifyObj.notify(); + } + TestClass10.method(); + TestClass11.method(); + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class Thread2filter_rt001a extends Thread { + + String tName = null; + + public Thread2filter_rt001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt001a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_rt001a.waitnotifyObj) { + filter_rt001a.waitnotifyObj.notify(); + } + TestClass20.method(); + TestClass21.method(); + filter_rt001a.log1(" 'run': exit :: threadName == " + tName); + return; + } + + static class TestClass20 { + + static int var201 = 0; + static int var202 = 0; + static int var203 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + } + } + static class TestClass21 extends TestClass20 { + + static int var211 = 0; + static int var212 = 0; + static int var213 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + + var211 = 1; + var213 = var211; + var212 = var213; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002.java new file mode 100644 index 00000000000..75da12ed92e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those whose + * location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * The case to test include ModificationWatchpointRequest. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates objects of ClassTypes to test and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a WatchpointRequest, + * - gets ReferenecType and, using it, restricts the Request, + * - resumes the debuggee and waits for expected WatchpointEvent. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, invokes methods performing access to fileds, + * used to generate Event and to test the filters. + * - Upon getting the event, the debugger performs checks required. + */ + +public class filter_rt002 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt002a"; + return new filter_rt002().runThis(argv, out); + } + + // ************************************************ test parameters + + String className1 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt002aTestClass10"; + String className2 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt002aTestClass11"; + + protected void testRun() { + + if ( !vm.canWatchFieldModification() ) { + display("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + String property1 = "ModificationWatchpointRequest1"; + ThreadReference thread1 = null; + String thread1Name = "thread1"; + String fieldName1 = "var101"; + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(className1).get(0); + + eventRequest1 = setting21ModificationWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_ALL, property1); + + testClassReference = + (ReferenceType) vm.classesByName(className2).get(0); + + ((ModificationWatchpointRequest) eventRequest1).addClassFilter(testClassReference); + + display("......waiting for ModificationWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("new event is not ModificationWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ModificationWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ModificationWatchpointRequest setting21ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up ModificationWatchpointRequest:"); + display(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ModificationWatchpointRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002/TestDescription.java new file mode 100644 index 00000000000..87c46475024 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * The cases to test include ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt002; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt002 + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002a.java new file mode 100644 index 00000000000..c70eb2361fc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt002a.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt002 JDI test. + */ + +public class filter_rt002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_rt002a thread1 = null; + static Thread2filter_rt002a thread2 = null; + + static filter_rt002aTestClass10 obj10 = new filter_rt002aTestClass10(); + static filter_rt002aTestClass11 obj11 = new filter_rt002aTestClass11(); + + static Thread2filter_rt002a.TestClass20 obj20 = new Thread2filter_rt002a.TestClass20(); + static Thread2filter_rt002a.TestClass21 obj21 = new Thread2filter_rt002a.TestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_rt002a("thread1"); + log1("run1(thread1);"); + run1(thread1); + + thread2 = new Thread2filter_rt002a("thread2"); + log1("run1(thread2);"); + run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + threadStart(t); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class filter_rt002aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter_rt002aTestClass11 extends filter_rt002aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1filter_rt002a extends Thread { + + String tName = null; + + public Thread1filter_rt002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt002a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_rt002a.waitnotifyObj) { + filter_rt002a.waitnotifyObj.notify(); + } + filter_rt002aTestClass10.method(); + filter_rt002aTestClass11.method(); + filter_rt002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class Thread2filter_rt002a extends Thread { + + String tName = null; + + public Thread2filter_rt002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt002a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_rt002a.waitnotifyObj) { + filter_rt002a.waitnotifyObj.notify(); + } + TestClass20.method(); + TestClass21.method(); + filter_rt002a.log1(" 'run': exit :: threadName == " + tName); + return; + } + + static class TestClass20 { + + static int var201 = 0; + static int var202 = 0; + static int var203 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + } + } + static class TestClass21 extends TestClass20 { + + static int var211 = 0; + static int var212 = 0; + static int var213 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + + var211 = 1; + var213 = var211; + var212 = var213; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java new file mode 100644 index 00000000000..463bdc5768e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + * The cases to test include AccessWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an AccessWatchpointRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_rt003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_rt003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt003a"; + + private String testedClassName1 = + "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt003aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + String property1 = "AccessWatchpointRequest1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName1).get(0); + + eventRequest1 = setting21AccessWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testClassReference); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest setting21AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003/TestDescription.java new file mode 100644 index 00000000000..2ead856ca94 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The cases to test include AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt003; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt003 + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003a.java new file mode 100644 index 00000000000..967870c0275 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003a.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt003 JDI test. + */ + +public class filter_rt003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt003aTestClass10 obj10 = new filter_rt003aTestClass10(); + static filter_rt003aTestClass11 obj11 = new filter_rt003aTestClass11(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} + +class filter_rt003aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter_rt003aTestClass11 extends filter_rt003aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java new file mode 100644 index 00000000000..a633bd7a6ec --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + * The cases to test include ModificationWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ModificationWatchpointRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_rt004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_rt004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt004a"; + + private String testedClassName1 = + "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt004aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + String property1 = "ModificationWatchpointRequest1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName1).get(0); + + eventRequest1 = setting21ModificationWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testClassReference); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testClassReference); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest setting21ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004/TestDescription.java new file mode 100644 index 00000000000..43cbcce270f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004/TestDescription.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The cases to test include ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt004; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt004 + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004a.java new file mode 100644 index 00000000000..a9ad445d072 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004a.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt004 JDI test. + */ + +public class filter_rt004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_rt004aTestClass10 obj10 = new filter_rt004aTestClass10(); + static filter_rt004aTestClass11 obj11 = new filter_rt004aTestClass11(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +} + +class filter_rt004aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter_rt004aTestClass11 extends filter_rt004aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005.java new file mode 100644 index 00000000000..4f002b6b0c7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The WatchpointRequest to test is AccessWatchpointRequest. + * The cases to test include re-invocations of the method + * addClassFilter() on the same AccessWatchpointtRequest object. + * There are two AccessWatchpointRequests to check as follows: + * (1) For AccessWatchpointRequest2, both invocations are with different + * ReferenceTypes restricting one AccessWatchpoint event to two classes. + * The test expects no AccessWatchpoint event will be received. + * (2) For AccessWatchpointRequest1, both invocations are with the same + * ReferenceType restricting one AccessWatchpoint event to one class. + * The test expects this AccessWatchpoint event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates objects of needed classes + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes 1&2 for the Classes to filter, + * - sets up two AccessWatchpointRequests 1&2, + * - double restricts AccessWatchpointRequest1 to the RefTypes 1 and 1, + * - double restricts AccessWatchpointRequest2 to the RefTypes 1 and 2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - The debuggee creates and starts two threads, thread1 and thread2, + * generating the events to be filtered. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_rt005 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005a"; + return new filter_rt005().runThis(argv, out); + } + + // ************************************************ test parameters + + String className10 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005aTestClass10"; + String className20 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005aTestClass20"; + + String className11 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005aTestClass11"; + String className21 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005aTestClass21"; + + protected void testRun() { + + if ( !vm.canWatchFieldAccess() ) { + display("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "AccessWatchpointRequest1"; + String property2 = "AccessWatchpointRequest2"; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String fieldName1 = "var101"; + String fieldName2 = "var201"; + + ReferenceType testClassReference10 = null; + ReferenceType testClassReference11 = null; + ReferenceType testClassReference20 = null; + ReferenceType testClassReference21 = null; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference10 = + (ReferenceType) vm.classesByName(className10).get(0); + testClassReference11 = + (ReferenceType) vm.classesByName(className11).get(0); + testClassReference20 = + (ReferenceType) vm.classesByName(className20).get(0); + testClassReference21 = + (ReferenceType) vm.classesByName(className21).get(0); + + eventRequest1 = setting21AccessWatchpointRequest (null, + testClassReference10, fieldName1, + EventRequest.SUSPEND_ALL, property1); + + eventRequest2 = setting21AccessWatchpointRequest (null, + testClassReference20, fieldName2, + EventRequest.SUSPEND_ALL, property2); + + + ((AccessWatchpointRequest) eventRequest1).addClassFilter(testClassReference11); + ((AccessWatchpointRequest) eventRequest1).addClassFilter(testClassReference11); + + ((AccessWatchpointRequest) eventRequest2).addClassFilter(testClassReference11); + ((AccessWatchpointRequest) eventRequest2).addClassFilter(testClassReference21); + + display("......waiting for AccessWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("New event is not AccessWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new AccessWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private AccessWatchpointRequest setting21AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) + throws Failure { + try { + display("......setting up AccessWatchpointRequest:"); + display(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005/TestDescription.java new file mode 100644 index 00000000000..5fbe9179ecc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * The cases to test include AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005 + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005a.java new file mode 100644 index 00000000000..029496ffdb3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt005a.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt005 JDI test. + */ + +public class filter_rt005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_rt005a thread1 = null; + static Thread2filter_rt005a thread2 = null; + + static filter_rt005aTestClass10 obj10 = new filter_rt005aTestClass10(); + static filter_rt005aTestClass11 obj11 = new filter_rt005aTestClass11(); + + static filter_rt005aTestClass20 obj20 = new filter_rt005aTestClass20(); + static filter_rt005aTestClass21 obj21 = new filter_rt005aTestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_rt005a("thread1"); + log1("run1(thread1);"); + run1(thread1); + + thread2 = new Thread2filter_rt005a("thread2"); + log1("run1(thread2);"); + run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + threadStart(t); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class filter_rt005aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter_rt005aTestClass11 extends filter_rt005aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1filter_rt005a extends Thread { + + String tName = null; + + public Thread1filter_rt005a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt005a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_rt005a.waitnotifyObj) { + filter_rt005a.waitnotifyObj.notify(); + } + filter_rt005aTestClass10.method(); + filter_rt005aTestClass11.method(); + filter_rt005a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt005aTestClass20 { + + static int var201 = 0; + static int var202 = 0; + static int var203 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + } +} +class filter_rt005aTestClass21 extends filter_rt005aTestClass20 { + + static int var211 = 0; + static int var212 = 0; + static int var213 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + + var211 = 1; + var213 = var211; + var212 = var213; + } +} + +class Thread2filter_rt005a extends Thread { + + String tName = null; + + public Thread2filter_rt005a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt005a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_rt005a.waitnotifyObj) { + filter_rt005a.waitnotifyObj.notify(); + } + filter_rt005aTestClass20.method(); + filter_rt005aTestClass21.method(); + filter_rt005a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006.java new file mode 100644 index 00000000000..fee62ff52a8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The WatchpointRequest to test is ModificationWatchpointRequest. + * The cases to test include re-invocations of the method + * addClassFilter() on the same ModificationWatchpointtRequest object. + * There are two ModificationWatchpointRequests to check as follows: + * (1) For ModificationWatchpointRequest2, both invocations are with different + * ReferenceTypes restricting one ModificationWatchpoint event to two classes. + * The test expects no ModificationWatchpoint event will be received. + * (2) For ModificationWatchpointRequest1, both invocations are with the same + * ReferenceType restricting one ModificationWatchpoint event to one class. + * The test expects this ModificationWatchpoint event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates objects of needed classes + * and invokes the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - gets ReferenceTypes 1&2 for the Classes to filter, + * - sets up two ModificationWatchpointRequests 1&2, + * - double restricts ModificationWatchpointRequest1 to the RefTypes 1 and 1, + * - double restricts ModificationWatchpointRequest2 to the RefTypes 1 and 2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - The debuggee creates and starts two threads, thread1 and thread2, + * generating the events to be filtered. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_rt006 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006a"; + return new filter_rt006().runThis(argv, out); + } + + String className10 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006aTestClass10"; + String className20 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006aTestClass20"; + + String className11 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006aTestClass11"; + String className21 = "nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006aTestClass21"; + + protected void testRun() { + + if ( !vm.canWatchFieldAccess() ) { + display("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "ModificationWatchpointRequest1"; + String property2 = "ModificationWatchpointRequest2"; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String fieldName1 = "var101"; + String fieldName2 = "var201"; + + ReferenceType testClassReference10 = null; + ReferenceType testClassReference11 = null; + ReferenceType testClassReference20 = null; + ReferenceType testClassReference21 = null; + + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference10 = + (ReferenceType) vm.classesByName(className10).get(0); + testClassReference11 = + (ReferenceType) vm.classesByName(className11).get(0); + testClassReference20 = + (ReferenceType) vm.classesByName(className20).get(0); + testClassReference21 = + (ReferenceType) vm.classesByName(className21).get(0); + + eventRequest1 = setting21ModificationWatchpointRequest (null, + testClassReference10, fieldName1, + EventRequest.SUSPEND_ALL, property1); + + eventRequest2 = setting21ModificationWatchpointRequest (null, + testClassReference20, fieldName2, + EventRequest.SUSPEND_ALL, property2); + + + ((ModificationWatchpointRequest) eventRequest1).addClassFilter(testClassReference11); + ((ModificationWatchpointRequest) eventRequest1).addClassFilter(testClassReference11); + + ((ModificationWatchpointRequest) eventRequest2).addClassFilter(testClassReference11); + ((ModificationWatchpointRequest) eventRequest2).addClassFilter(testClassReference21); + + display("......waiting for ModificationWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("New event is not ModificationWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ModificationWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) + setFailedStatus("Property is not : " + property1); + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ModificationWatchpointRequest setting21ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) + throws Failure { + try { + display("......setting up ModificationWatchpointRequest:"); + display(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ModificationWatchpointRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006/TestDescription.java new file mode 100644 index 00000000000..431a8c2dbbc --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(ReferenceType) + * complies with its spec: + * public void addClassFilter(ReferenceType refType) + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * Parameters: refType - the reference type to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in the given reference type or any of its subtypes. + * An event will be generated for any location in a reference type + * that can be safely cast to the given reference type. + * The cases to test include ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006 + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_rt.filter_rt006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006a.java new file mode 100644 index 00000000000..c420b249704 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt006a.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_rt; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_rt006 JDI test. + */ + +public class filter_rt006a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_rt006a thread1 = null; + static Thread2filter_rt006a thread2 = null; + + static filter_rt006aTestClass10 obj10 = new filter_rt006aTestClass10(); + static filter_rt006aTestClass11 obj11 = new filter_rt006aTestClass11(); + + static filter_rt006aTestClass20 obj20 = new filter_rt006aTestClass20(); + static filter_rt006aTestClass21 obj21 = new filter_rt006aTestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_rt006a("thread1"); + log1("run1(thread1);"); + run1(thread1); + + thread2 = new Thread2filter_rt006a("thread2"); + log1("run1(thread2);"); + run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + threadStart(t); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +} + +class filter_rt006aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter_rt006aTestClass11 extends filter_rt006aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1filter_rt006a extends Thread { + + String tName = null; + + public Thread1filter_rt006a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt006a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_rt006a.waitnotifyObj) { + filter_rt006a.waitnotifyObj.notify(); + } + filter_rt006aTestClass10.method(); + filter_rt006aTestClass11.method(); + filter_rt006a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_rt006aTestClass20 { + + static int var201 = 0; + static int var202 = 0; + static int var203 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + } +} +class filter_rt006aTestClass21 extends filter_rt006aTestClass20 { + + static int var211 = 0; + static int var212 = 0; + static int var213 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + + var211 = 1; + var213 = var211; + var212 = var213; + } +} + +class Thread2filter_rt006a extends Thread { + + String tName = null; + + public Thread2filter_rt006a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_rt006a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_rt006a.waitnotifyObj) { + filter_rt006a.waitnotifyObj.notify(); + } + filter_rt006aTestClass20.method(); + filter_rt006aTestClass21.method(); + filter_rt006a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001.java new file mode 100644 index 00000000000..562efe4cac1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(String) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to check include both a pattern that begin with '*' and + * one that end with '*'. + * The cases to test include AccessWatchpointRequest. + * + * The test works as follows. + * - The debugger + * - sets up two WatchpointRequests, + * - using patterns that begins with '*' and ends with *, + * restricts the Requests, so that, + * first time events will be filtered only from thread1 and + * second time events will be filtered only from thread2, + * - resumes the debuggee, and + * - waits for expected WatchpointEvents. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, generate Events to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_s001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s001a"; + return new filter_s001().runThis(argv, out); + } + + private String testedClassName1 = "*TestClass11"; + + private String testedClassName2 = + "nsk.jdi.WatchpointRequest.addClassFilter_s.Thread2filter_s001a*"; + + String className1 = "nsk.jdi.WatchpointRequest.addClassFilter_s.TestClass10"; + String className2 = "nsk.jdi.WatchpointRequest.addClassFilter_s.TestClass20"; + + protected void testRun() { + + if ( !vm.canWatchFieldAccess() ) { + display("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "AccessWatchpointRequest1"; + String property2 = "AccessWatchpointRequest2"; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String fieldName1 = "var101"; + String fieldName2 = "var201"; + + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(className1).get(0); + + eventRequest1 = setting21AccessWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_ALL, property1); + + ((AccessWatchpointRequest) eventRequest1).addClassFilter(testedClassName1); + + display("......waiting for AccessWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("ERROR: new event is not AccessWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new AccessWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + case 1: + testClassReference = + (ReferenceType) vm.classesByName(className2).get(0); + + eventRequest2 = setting21AccessWatchpointRequest (null, + testClassReference, fieldName2, + EventRequest.SUSPEND_ALL, property2); + + ((AccessWatchpointRequest) eventRequest2).addClassFilter(testedClassName2); + + display("......waiting for AccessWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("ERROR: new event is not AccessWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new AccessWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property2) ) { + setFailedStatus("ERROR: property is not : " + property2); + } + } + vm.resume(); + break; + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private AccessWatchpointRequest setting21AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up AccessWatchpointRequest:"); + display(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001/TestDescription.java new file mode 100644 index 00000000000..17091207082 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(String) + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to test include AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s001; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s001 + * nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001a.java new file mode 100644 index 00000000000..3836f92e51e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s001a.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s001 JDI test. + */ + +public class filter_s001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_s001a thread1 = null; + static Thread2filter_s001a thread2 = null; + + static TestClass10 obj10 = new TestClass10(); + static TestClass11 obj11 = new TestClass11(); + + static TestClass20 obj20 = new TestClass20(); + static Thread2filter_s001a.TestClass21 obj21 = new Thread2filter_s001a.TestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_s001a("thread1"); + log1("run1(thread1);"); + run1(thread1); + + TestClass20.method(); // otherwise TestClass20 is not loaded; bug? + break; + + case 1: + thread2 = new Thread2filter_s001a("thread2"); + log1("run1(thread2);"); + run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + threadStart(t); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + +class TestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class TestClass11 extends TestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1filter_s001a extends Thread { + + String tName = null; + + public Thread1filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_s001a.waitnotifyObj) { + filter_s001a.waitnotifyObj.notify(); + } + TestClass10.method(); + TestClass11.method(); + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class TestClass20 { + + static int var201 = 0; + static int var202 = 0; + static int var203 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + } +} + +class Thread2filter_s001a extends Thread { + + String tName = null; + + public Thread2filter_s001a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s001a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_s001a.waitnotifyObj) { + filter_s001a.waitnotifyObj.notify(); + } + TestClass20.method(); + TestClass21.method(); + filter_s001a.log1(" 'run': exit :: threadName == " + tName); + return; + } + + static class TestClass21 extends TestClass20 { + + static int var211 = 0; + static int var212 = 0; + static int var213 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + + var211 = 1; + var213 = var211; + var212 = var213; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002.java new file mode 100644 index 00000000000..fccb6ab8b3e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(String) + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to check include both a pattern that begin with '*' and + * one that end with '*'. + * The cases to test include ModificationWatchpointRequest. + * + * The test works as follows. + * - The debugger + * - sets up two WatchpointRequests, + * - using patterns that begins with '*' and ends with *, + * restricts the Requests, so that, + * first time events will be filtered only from thread1 and + * second time events will be filtered only from thread2, + * - resumes the debuggee, and + * - waits for expected WatchpointEvents. + * - The debuggee creates and starts two threads, thread1 and thread2, + * that being run, generate Events to test the filters. + * - Upon getting the events, the debugger performs checks required. + */ + +public class filter_s002 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s002a"; + return new filter_s002().runThis(argv, out); + } + + private String testedClassName1 = "*filter_s002aTestClass11"; + + private String testedClassName2 = + "nsk.jdi.WatchpointRequest.addClassFilter_s.Thread2filter_s002a*"; + + String className1 = "nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s002aTestClass10"; + String className2 = "nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s002aTestClass20"; + + protected void testRun() { + if ( !vm.canWatchFieldModification() ) { + display("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + String property1 = "ModificationWatchpointRequest1"; + String property2 = "ModificationWatchpointRequest2"; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String fieldName1 = "var101"; + String fieldName2 = "var201"; + + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(className1).get(0); + + eventRequest1 = setting21ModificationWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_ALL, property1); + + ((ModificationWatchpointRequest) eventRequest1).addClassFilter(testedClassName1); + + display("......waiting for ModificationWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("ERROR: new event is not ModificationWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ModificationWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + case 1: + testClassReference = + (ReferenceType) vm.classesByName(className2).get(0); + + eventRequest2 = setting21ModificationWatchpointRequest (null, + testClassReference, fieldName2, + EventRequest.SUSPEND_ALL, property2); + + ((ModificationWatchpointRequest) eventRequest2).addClassFilter(testedClassName2); + + display("......waiting for ModificationWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("ERROR: new event is not ModificationWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ModificationWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property2) ) { + setFailedStatus("ERROR: property is not : " + property2); + } + } + vm.resume(); + break; + default: + throw new Failure("** default case 2 **"); + } + } + return; + } + + private ModificationWatchpointRequest setting21ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up ModificationWatchpointRequest:"); + display(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002/TestDescription.java new file mode 100644 index 00000000000..6f7e4c05c71 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(String) + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * The cases to test include ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s002; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s002 + * nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002a.java new file mode 100644 index 00000000000..4b805545721 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s002a.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s002 JDI test. + */ + +public class filter_s002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Thread1filter_s002a thread1 = null; + static Thread2filter_s002a thread2 = null; + + static filter_s002aTestClass10 obj10 = new filter_s002aTestClass10(); + static filter_s002aTestClass11 obj11 = new filter_s002aTestClass11(); + + static filter_s002aTestClass20 obj20 = new filter_s002aTestClass20(); + static Thread2filter_s002a.TestClass21 obj21 = new Thread2filter_s002a.TestClass21(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Thread1filter_s002a("thread1"); + log1("run1(thread1);"); + run1(thread1); + + filter_s002aTestClass20.method(); // otherwise filter_s002aTestClass20 is not loaded; bug? + break; + + case 1: + thread2 = new Thread2filter_s002a("thread2"); + log1("run1(thread2);"); + run1(thread2); + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static void run1(Thread t) { + threadStart(t); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } + +} + +class filter_s002aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter_s002aTestClass11 extends filter_s002aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; + } +} + +class Thread1filter_s002a extends Thread { + + String tName = null; + + public Thread1filter_s002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s002a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_s002a.waitnotifyObj) { + filter_s002a.waitnotifyObj.notify(); + } + filter_s002aTestClass10.method(); + filter_s002aTestClass11.method(); + filter_s002a.log1(" 'run': exit :: threadName == " + tName); + return; + } +} + +class filter_s002aTestClass20 { + + static int var201 = 0; + static int var202 = 0; + static int var203 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + } +} + +class Thread2filter_s002a extends Thread { + + String tName = null; + + public Thread2filter_s002a(String threadName) { + super(threadName); + tName = threadName; + } + + public void run() { + filter_s002a.log1(" 'run': enter :: threadName == " + tName); + synchronized (filter_s002a.waitnotifyObj) { + filter_s002a.waitnotifyObj.notify(); + } + filter_s002aTestClass20.method(); + TestClass21.method(); + filter_s002a.log1(" 'run': exit :: threadName == " + tName); + return; + } + + static class TestClass21 extends filter_s002aTestClass20 { + + static int var211 = 0; + static int var212 = 0; + static int var213 = 0; + + static void method () { + var201 = 1; + var203 = var201; + var202 = var203; + + var211 = 1; + var213 = var211; + var212 = var213; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java new file mode 100644 index 00000000000..cf64ce2b7c2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addClassFilter(String)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + * The cases to test include AccessWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an AccessWatchpointRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_s003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_s003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s003a"; + + private String testedClassName1 = + "nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s003aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + String property1 = "AccessWatchpointRequest1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName1).get(0); + + eventRequest1 = setting21AccessWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest setting21AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003/TestDescription.java new file mode 100644 index 00000000000..ffb8c33bfae --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(String) + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The cases to test include AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s003; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s003 + * nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003a.java new file mode 100644 index 00000000000..43ac0e97b76 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003a.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s003 JDI test. + */ + +public class filter_s003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_s003aTestClass10 obj10 = new filter_s003aTestClass10(); + static filter_s003aTestClass11 obj11 = new filter_s003aTestClass11(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +/* + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +*/ +} + +class filter_s003aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter_s003aTestClass11 extends filter_s003aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; +// filter_s003aTestClass10.method(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java new file mode 100644 index 00000000000..24f96c2c323 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addClassFilter(String)
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled or has been deleted.
    + * Filters may be added only to disabled requests.
    + * The cases to test include ModificationWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ModificationWatchpointRequest and enables it,
    + * - invokes the method addClassFilter() on the request
    + * expecting to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addClassFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addClassFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class filter_s004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new filter_s004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s004a"; + + private String testedClassName1 = + "nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s004aTestClass10"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + String property1 = "ModificationWatchpointRequest1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName1).get(0); + + eventRequest1 = setting21ModificationWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_NONE, property1); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" no InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addClassFilter(testedClassName1);"); + log2(" InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addClassFilter(testedClassName1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest setting21ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004/TestDescription.java new file mode 100644 index 00000000000..e335b95b790 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004/TestDescription.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addClassFilter(String) + * complies with its spec: + * public void addClassFilter(String classPattern) + * Restricts the events generated by this request to those + * whose location is in a class + * whose name matches a restricted regular expression. + * Regular expressions are limited to exact matches and patterns + * that begin with '*' or end with '*'; for example, "*.Foo" or "java.*". + * Parameters: classPattern - the pattern String to filter for. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The cases to test include ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s004; + * the debuggee program - nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s004 + * nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addClassFilter_s.filter_s004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004a.java new file mode 100644 index 00000000000..a9fdb591d03 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004a.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addClassFilter_s; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the filter_s004 JDI test. + */ + +public class filter_s004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static filter_s004aTestClass10 obj10 = new filter_s004aTestClass10(); + static filter_s004aTestClass11 obj11 = new filter_s004aTestClass11(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +/* + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +*/ +} + +class filter_s004aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class filter_s004aTestClass11 extends filter_s004aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; +// filter_s004aTestClass10.method(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001.java new file mode 100644 index 00000000000..6b54694b2ef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * in which the currently executing instance is + * the object specified. + * This request is AccessWatchpointRequest. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a special array with three Object instances, + * and two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a WatchpointRequest + * within the method in the class TestClass + * whose array element instances #0 and #1 + * will be calling by the thread1 and the thread2 accordinly, + * - invokes addInstanceFilter() on array element #0 for the thread1 + * and #2 for the thread2, + * thus restricting the Watchpoint event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter001a"; + return new instancefilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.TestClass"; + + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "AccessWatchpointRequest1"; + String property2 = "AccessWatchpointRequest2"; + + String fieldName = "var1"; + + Event newEvent = null; + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + eventRequest1 = setting2AccessWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property1); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + eventRequest2 = setting2AccessWatchpointRequest (thread2, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property2); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(2); + ((WatchpointRequest) eventRequest2).addInstanceFilter(instance); + + display("......waiting for WatchpointEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof WatchpointEvent)) { + setFailedStatus("ERROR: new event is not WatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new WatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + + private AccessWatchpointRequest setting2AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up AccessWatchpointRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001/TestDescription.java new file mode 100644 index 00000000000..ac8c6c8775b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * This request is AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter001; + * the debuggee program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter001 + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001a.java new file mode 100644 index 00000000000..d0867c1cca1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter001a.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter001 JDI test. + */ + +public class instancefilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter001a thread1 = null; + static Threadinstancefilter001a thread2 = null; + + static TestClass objTC[] = { new TestClass(), new TestClass(), new TestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter001a("thread1"); + thread2 = new Threadinstancefilter001a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter001a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter001a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class TestClass { + + static int breakpointLine = 3; + + int var1 = 0; + int var2 = 0; + int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002.java new file mode 100644 index 00000000000..ab5a0ca5104 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those + * in which the currently executing instance is + * the object specified. + * This request is ModificationWatchpointRequest. + * + * The test works as follows. + * + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates a special array with three Object instances, + * and two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a WatchpointRequest + * within the method in the class instancefilter002aTestClass + * whose array element instances #0 and #1 + * will be calling by the thread1 and the thread2 accordinly, + * - invokes addInstanceFilter() on array element #0 for the thread1 + * and #2 for the thread2, + * thus restricting the Modification event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter002 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter002a"; + return new instancefilter002().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter002aTestClass"; + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ModificationWatchpointRequest1"; + String property2 = "ModificationWatchpointRequest2"; + + String fieldName = "var1"; + + Event newEvent = null; + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + eventRequest1 = setting2ModificationWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property1); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + eventRequest2 = setting2ModificationWatchpointRequest (thread2, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property2); + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(2); + ((WatchpointRequest) eventRequest2).addInstanceFilter(instance); + + display("......waiting for WatchpointEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if ( !(newEvent instanceof WatchpointEvent)) { + setFailedStatus("ERROR: new event is not WatchpointEvent"); + } else { + + String property = (String) newEvent.request().getProperty("number"); + display(" got new WatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ModificationWatchpointRequest setting2ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up ModificationWatchpointRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ModificationWatchpointRequest **"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002/TestDescription.java new file mode 100644 index 00000000000..649ed43d4e5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002/TestDescription.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * This request is ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter002; + * the debuggee program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter002 + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002a.java new file mode 100644 index 00000000000..5525dcd5d9e --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter002a.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter002 JDI test. + */ + +public class instancefilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter002a thread1 = null; + static Threadinstancefilter002a thread2 = null; + + static instancefilter002aTestClass objTC[] = { new instancefilter002aTestClass(), new instancefilter002aTestClass(), new instancefilter002aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter002a("thread1"); + thread2 = new Threadinstancefilter002a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter002a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter002a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter002aTestClass { + + static int breakpointLine = 3; + + int var1 = 0; + int var2 = 0; + int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java new file mode 100644 index 00000000000..79c7e8e54b5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * This request is AccessWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an AccessWatchpointRequest and enables it,
    + * - invokes the method addInstanceFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addInstanceFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addInstanceFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter003a"; + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "AccessWatchpointRequest1"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2AccessWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" no InvalidRequestStateException expected"); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest setting2AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003/TestDescription.java new file mode 100644 index 00000000000..3b74ca779d5 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequestRequest. + * The test checks up that a result of the method + * com.sun.jdi.MethodExitRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * This request is AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter003; + * the debuggee program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter003 + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003a.java new file mode 100644 index 00000000000..7b177420cac --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter003 JDI test. + */ + +public class instancefilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter003a thread1 = null; + + static instancefilter003aTestClass objTC[] = { new instancefilter003aTestClass(), new instancefilter003aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter003a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter003a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter003a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter003aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java new file mode 100644 index 00000000000..4bd8dbf2016 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * This request is ModificationWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates a ModificationWatchpointRequest and enables it,
    + * - invokes the method addInstanceFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addInstanceFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addInstanceFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter004a"; + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter004aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ModificationWatchpointRequest1"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ModificationWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + + eventRequest1.enable(); + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" no InvalidRequestStateException expected"); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" InvalidRequestStateException expected"); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest setting2ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004/TestDescription.java new file mode 100644 index 00000000000..7ead0841ac6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004/TestDescription.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * This request is ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter004; + * the debuggee program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter004 + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004a.java new file mode 100644 index 00000000000..b951e6ed189 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter004 JDI test. + */ + +public class instancefilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter004a thread1 = null; + + static instancefilter004aTestClass objTC[] = { new instancefilter004aTestClass(), new instancefilter004aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter004a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter004a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter004a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter004aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java new file mode 100644 index 00000000000..fda553215d7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: UnsupportedOperationException -
    + * if the target virtual machine
    + * does not support this operation.
    + * This request is AccessWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger creates
    + * a WatchpointRequest and if addInstanceFilter() is not supported,
    + * invokes the method on the request expecting
    + * to catch UnsupportedOperationException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter005().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter005a"; + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter005aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "AccessWatchpointRequest1"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2AccessWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + if ( vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == true :: test cancelled"); + } else { + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" UnsupportedOperationException expected"); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no UnsupportedOperationException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" UnsupportedOperationException "); + } + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest setting2AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005/TestDescription.java new file mode 100644 index 00000000000..fa068169ce6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter005; + * the debuggee program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter005 + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005a.java new file mode 100644 index 00000000000..1f67260cfd0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter005 JDI test. + */ + +public class instancefilter005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter005a thread1 = null; + + static instancefilter005aTestClass objTC[] = { new instancefilter005aTestClass(), new instancefilter005aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter005a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter005a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter005a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter005aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java new file mode 100644 index 00000000000..4343ca0abb8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addInstanceFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: UnsupportedOperationException -
    + * if the target virtual machine
    + * does not support this operation.
    + * This request is ModificationWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger creates
    + * a ModificationWatchpointRequest and if addInstanceFilter()
    + * is not supported, invokes the method on the request expecting
    + * to catch UnsupportedOperationException.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class instancefilter006 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new instancefilter006().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter006a"; + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter006aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ModificationWatchpointRequest1"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + ObjectReference instance = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ModificationWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, property1); + + instance = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + + if ( vm.canUseInstanceFilters() ) { + log2("......vm.canUseInstanceFilters == true :: test cancelled"); + } else { + + try { + log2("......eventRequest1.addInstanceFilter(instance);"); + log2(" UnsupportedOperationException expected"); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance); + log3("ERROR: no UnsupportedOperationException "); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" UnsupportedOperationException "); + } + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest setting2ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006/TestDescription.java new file mode 100644 index 00000000000..1e7db87c516 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006/TestDescription.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter006; + * the debuggee program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter006a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter006 + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006a.java new file mode 100644 index 00000000000..b798f685063 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006a.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter006 JDI test. + */ + +public class instancefilter006a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter006a thread1 = null; + + static instancefilter006aTestClass objTC[] = { new instancefilter006aTestClass(), new instancefilter006aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter006a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter006a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter006a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter006aTestClass { + + static int breakpointLine = 3; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007.java new file mode 100644 index 00000000000..8d2095bb8f1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * This request is AccessWatchpointRequest. + * The case to test includes re-invocation of the method + * addInstanceFilter() on the same AccessWatchpointRequest object. + * There are two AccessWatchpointRequests to check as follows: + * (1) For AccessWatchpointRequest2, both invocations are with different + * ObjectReferences restricting one AccessWatchpoint event to two objects. + * The test expects no AccessWatchpoint event will be received. + * (2) For AccessWatchpointRequest1, both invocations are with the same + * ObjectReference restricting one AccessWatchpoint event to one object. + * The test expects this AccessWatchpoint event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up AccessWatchpointRequests 1&2 within the method + * in the class instancefilter007aTestClass which will be calling by both threads, + * - restricts the AccessWatchpointRequest1 to the tread1 and + * to the array elements #0 & #0 calling only within thread1, + * - restricts the AccessWatchpointRequest2 to the thread2 and + * the array elements #0 & #1 calling within thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter007 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter007a"; + return new instancefilter007().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter007aTestClass"; + + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "AccessWatchpointRequest1"; + String property2 = "AccessWatchpointRequest2"; + + String fieldName = "var1"; + + Event newEvent = null; + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + + ObjectReference instance1 = null; + ObjectReference instance2 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2AccessWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2AccessWatchpointRequest (thread2, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property2); + + instance1 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + instance2 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(1); + + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance1); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance1); + ((WatchpointRequest) eventRequest2).addInstanceFilter(instance1); + ((WatchpointRequest) eventRequest2).addInstanceFilter(instance2); + + display("......waiting for AccessWatchpointEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + EventRequest newEventRequest = newEvent.request(); + if (!(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("ERROR: new event is not WatchpointEvent"); + } else { + display(" got expected event"); + + ThreadReference newEventThread = ((AccessWatchpointEvent) newEvent).thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private AccessWatchpointRequest setting2AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up AccessWatchpointRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007/TestDescription.java new file mode 100644 index 00000000000..2bedd09b2a6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same AccessWatchpointRequest object. + * There are two AccessWatchpointRequests to check as follows: + * (1) For AccessWatchpointRequest2, both invocations are with different + * ObjectReferences restricting one AccessWatchpoint event to two objects. + * The test expects no AccessWatchpoint event will be received. + * (2) For AccessWatchpointRequest1, both invocations are with the same + * ObjectReference restricting one AccessWatchpoint event to one object. + * The test expects this AccessWatchpoint event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter007; + * the debuggee program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter007a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter007 + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007a.java new file mode 100644 index 00000000000..bf52ae67c80 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter007a.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter007 JDI test. + */ + +public class instancefilter007a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter007a thread1 = null; + static Threadinstancefilter007a thread2 = null; + + static instancefilter007aTestClass objTC[] = { new instancefilter007aTestClass(), new instancefilter007aTestClass(), new instancefilter007aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter007a("thread1"); + thread2 = new Threadinstancefilter007a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter007a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter007a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter007aTestClass { + + static int breakpointLine = 3; + + int var1 = 0; + int var2 = 0; + int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008.java new file mode 100644 index 00000000000..e800a5cfa52 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * This request is ModificationWatchpointRequest. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same ModificationWatchpointRequest object. + * There are two ModificationWatchpointRequests to check as follows: + * (1) For ModificationWatchpointRequest2, both invocations are with different + * ObjectReferences restricting one ModificationWatchpoint event to two objects. + * The test expects no ModificationWatchpoint event will be received. + * (2) For ModificationWatchpointRequest1, both invocations are with the same + * ObjectReference restricting one ModificationWatchpoint event to one object. + * The test expects this ModificationWatchpoint event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up ModificationWatchpointRequests 1&2 within the method + * in the class instancefilter008aTestClass which will be calling by both threads, + * - restricts the ModificationWatchpointRequest1 to the tread1 and + * to the array elements #0 & #0 calling only within thread1, + * - restricts the ModificationWatchpointRequest2 to the thread2 and + * the array elements #0 & #1 calling within thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class instancefilter008 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter008a"; + return new instancefilter008().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter008aTestClass"; + + + protected void testRun() { + if ( !vm.canUseInstanceFilters() ) { + display("......vm.canUseInstanceFilters == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ModificationWatchpointRequest1"; + String property2 = "ModificationWatchpointRequest2"; + + String fieldName = "var1"; + + Event newEvent = null; + ReferenceType testClassReference = null; + + String arrayName = "objTC"; + + ObjectReference instance1 = null; + ObjectReference instance2 = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2ModificationWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2ModificationWatchpointRequest (thread2, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property2); + + instance1 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(0); + instance2 = (ObjectReference) + ((ArrayReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(arrayName)) ).getValue(1); + + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance1); + ((WatchpointRequest) eventRequest1).addInstanceFilter(instance1); + ((WatchpointRequest) eventRequest2).addInstanceFilter(instance1); + ((WatchpointRequest) eventRequest2).addInstanceFilter(instance2); + + display("......waiting for ModificationWatchpointEvent in expected thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if (!(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("ERROR: new event is not WatchpointEvent"); + } else { + display(" got expected event"); + + ThreadReference newEventThread = ((ModificationWatchpointEvent) newEvent).thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ModificationWatchpointRequest setting2ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up ModificationWatchpointRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008/TestDescription.java new file mode 100644 index 00000000000..963fbc05489 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008/TestDescription.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addInstanceFilter() + * complies with its spec: + * public void addInstanceFilter(ObjectReference instance) + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * Not all targets support this operation. + * Use VirtualMachine.canUseInstanceFilters() to determine + * if the operation is supported. + * Parameters: instance - the object which must be the current instance + * in order to pass this filter. + * Throws: UnsupportedOperationException - + * if the target virtual machine does not support this operation. + * InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in which + * the currently executing instance is the object specified. + * The cases to test includes re-invocation of the method + * addInstanceFilter() on the same WatchpointRequest object. + * There are two ModificationWatchpointRequests to check as follows: + * (1) For ModificationWatchpointRequest2, both invocations are with different + * ObjectReferences restricting one ModificationWatchpoint event to two objects. + * The test expects no ModificationWatchpoint event will be received. + * (2) For ModificationWatchpointRequest1, both invocations are with the same + * ObjectReference restricting one ModificationWatchpoint event to one object. + * The test expects this ModificationWatchpoint event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter008; + * the debuggee program - nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter008a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter008 + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addInstanceFilter.instancefilter008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008a.java new file mode 100644 index 00000000000..47b953e5b46 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter008a.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addInstanceFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the instancefilter008 JDI test. + */ + +public class instancefilter008a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadinstancefilter008a thread1 = null; + static Threadinstancefilter008a thread2 = null; + + static instancefilter008aTestClass objTC[] = { new instancefilter008aTestClass(), new instancefilter008aTestClass(), new instancefilter008aTestClass() }; + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadinstancefilter008a("thread1"); + thread2 = new Threadinstancefilter008a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("main: synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("main: synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadinstancefilter008a extends Thread { + + String tName = null; + int tNumber; + + public Threadinstancefilter008a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + log1(" objTC[tNumber].method(); :: threadName == " + tName + " tNumber == " + tNumber); + objTC[tNumber].method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class instancefilter008aTestClass { + + static int breakpointLine = 3; + + int var1 = 0; + int var2 = 0; + int var3 = 0; + + public void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001.java new file mode 100644 index 00000000000..882a3cf3724 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a WatchpointRequest within the method + * in the class TestClass which will be calling by both threads, + * - restricts the watchpoint event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class addthreadfilter001 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter001a"; + return new addthreadfilter001().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addThreadFilter.TestClass"; + + + protected void testRun() { + + if ( !vm.canWatchFieldAccess() ) { + display("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + ThreadReference thread1 = null; + String thread1Name = "thread1"; + String property1 = "AccessWatchpointRequest1"; + String fieldName = "var1"; + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2AccessWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, "AccessWatchpointRequest1"); + + display("......waiting for AccessWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("ERROR: new event is not AccessWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new AccessWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private AccessWatchpointRequest setting2AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up AccessWatchpointRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001/TestDescription.java new file mode 100644 index 00000000000..631b3ff4ab2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * This request is AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter001; + * the debuggee program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter001 + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001a.java new file mode 100644 index 00000000000..65502ec94a2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter001a.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter001 JDI test. + */ + +public class addthreadfilter001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter001a thread1 = null; + static Threadaddthreadfilter001a thread2 = null; + + static TestClass objTC = new TestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter001a("thread1"); + thread2 = new Threadaddthreadfilter001a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter001a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter001a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class TestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002.java new file mode 100644 index 00000000000..1bc6e165d43 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks that results of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up a WatchpointRequest within the method + * in the class TestClass which will be calling by both threads, + * - restricts the watchpoint event only for thread1, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class addthreadfilter002 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter002a"; + return new addthreadfilter002().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter002aTestClass"; + + protected void testRun() { + + if ( !vm.canWatchFieldModification() ) { + display("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + ThreadReference thread1 = null; + String thread1Name = "thread1"; + String property1 = "ModificationWatchpointRequest1"; + String fieldName = "var1"; + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ModificationWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, "ModificationWatchpointRequest1"); + + display("......waiting for ModificationWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1}, waitTime, true); + + if ( !(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("ERROR: new event is not ModificationWatchpointEvent"); + } else { + String property = (String) newEvent.request().getProperty("number"); + display(" got new ModificationWatchpointEvent with property 'number' == " + property); + + if ( !property.equals(property1) ) { + setFailedStatus("ERROR: property is not : " + property1); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ModificationWatchpointRequest setting2ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up ModificationWatchpointRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002/TestDescription.java new file mode 100644 index 00000000000..d3fafec1fe8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * This request is ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter002; + * the debuggee program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter002 + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002a.java new file mode 100644 index 00000000000..56807766120 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter002a.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter002 JDI test. + */ + +public class addthreadfilter002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter002a thread1 = null; + static Threadaddthreadfilter002a thread2 = null; + + static addthreadfilter002aTestClass objTC = new addthreadfilter002aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter002a("thread1"); + thread2 = new Threadaddthreadfilter002a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter002a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter002a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class addthreadfilter002aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java new file mode 100644 index 00000000000..3320fc6b274 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * Filters may be added only to disabled requests.
    + * The test case includes AccessWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an AccessWatchpointRequest and enables it,
    + * - invokes the method addThreadFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addThreadFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addThreadFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class addthreadfilter003 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter003().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter003a"; + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter003aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldAccess() ) { + log2("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "AccessWatchpointRequest1"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2AccessWatchpointRequest (null, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, "AccessWatchpointRequest1"); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addThreadFilter(thread1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((AccessWatchpointRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest setting2AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003/TestDescription.java new file mode 100644 index 00000000000..e11281f777a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter003; + * the debuggee program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter003a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter003 + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter003a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter003 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003a.java new file mode 100644 index 00000000000..3b725ff511c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003a.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter003 JDI test. + */ + +public class addthreadfilter003a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter003a thread1 = null; + + static addthreadfilter003aTestClass objTC = new addthreadfilter003aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter003a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter003a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter003a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class addthreadfilter003aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java new file mode 100644 index 00000000000..61d8894fd5a --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Throws: InvalidRequestStateException -
    + * if this request is currently enabled
    + * or has been deleted.
    + * Filters may be added only to disabled requests.
    + * The test case includes ModificationWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new threads, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ModificationWatchpointRequest and enables it,
    + * - invokes the method addThreadFilter() on the request expecting
    + * to catch InvalidRequestStateException,
    + * - disables the request and invokes the method addThreadFilter()
    + * expecting to catch no InvalidRequestStateException,
    + * - deletes the request and invokes the method addThreadFilter()
    + * once again expecting to catch InvalidRequestStateException.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class addthreadfilter004 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter004().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter004a"; + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter004aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldModification() ) { + log2("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "ModificationWatchpointRequest1"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ModificationWatchpointRequest (null, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, "ModificationWatchpointRequest1"); + + log2("......eventRequest1.enable();"); + eventRequest1.enable(); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + + log2("......eventRequest1.disable();"); + eventRequest1.disable(); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addThreadFilter(thread1); + log2(" no InvalidRequestStateException"); + } catch ( InvalidRequestStateException e ) { + log3("ERROR: InvalidRequestStateException"); + testExitCode = FAILED; + } + + log2("......eventRManager.deleteEventRequest(eventRequest1);"); + eventRManager.deleteEventRequest(eventRequest1); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" InvalidRequestStateException expected"); + ((ModificationWatchpointRequest)eventRequest1).addThreadFilter(thread1); + log3("ERROR: no InvalidRequestStateException"); + testExitCode = FAILED; + } catch ( InvalidRequestStateException e ) { + log2(" InvalidRequestStateException"); + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest setting2ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004/TestDescription.java new file mode 100644 index 00000000000..4544e3119ed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter004; + * the debuggee program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter004a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter004 + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter004a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter004 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004a.java new file mode 100644 index 00000000000..3fcd781d203 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004a.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter004 JDI test. + */ + +public class addthreadfilter004a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter004a thread1 = null; + + static addthreadfilter004aTestClass objTC = new addthreadfilter004aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter004a("thread1"); + break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter004a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter004a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class addthreadfilter004aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java new file mode 100644 index 00000000000..7f6ad0d47ef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Restricts the events generated by this request
    + * to those in the given thread.
    + * The cases to test include three thread's states:
    + * not started, running, dead.
    + * The tested Request is AccessWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates AccessWatchpointRequest1 and
    + * invokes the method addThreadFilter(tread1) on the request1,
    + * - creates AccessWatchpointRequest2,
    + * resumes the debuggee to get the thread1 started, and
    + * invokes the method addThreadFilter(thread) on the request2,
    + * - creates AccessWatchpointRequest3, waits the thread1 to die, and
    + * invokes the method addThreadFilter(thread) on the request3.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class addthreadfilter005 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter005().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter005a"; + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter005aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldAccess() ) { + log2("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "AccessWatchpointRequest1"; + String property2 = "AccessWatchpointRequest2"; + String property3 = "AccessWatchpointRequest3"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2AccessWatchpointRequest (null, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, "AccessWatchpointRequest1"); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((AccessWatchpointRequest)eventRequest1).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 1: + eventRequest2 = setting2AccessWatchpointRequest (null, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, "AccessWatchpointRequest2"); + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((AccessWatchpointRequest)eventRequest2).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2AccessWatchpointRequest (null, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, "AccessWatchpointRequest3"); + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((AccessWatchpointRequest)eventRequest3).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest setting2AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005/TestDescription.java new file mode 100644 index 00000000000..b72c8d0c3cf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include three thread's states: not started, running, dead. + * The tested Request is AccessWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter005; + * the debuggee program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter005a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter005 + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter005a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter005 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005a.java new file mode 100644 index 00000000000..f9831d54e43 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005a.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter005 JDI test. + */ + +public class addthreadfilter005a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter005a thread1 = null; + + static addthreadfilter005aTestClass objTC = new addthreadfilter005aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter005a("thread1"); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();"); + methodForCommunication(); + } + break; + + case 2: + try { + thread1.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class Threadaddthreadfilter005a extends Thread { + + public Threadaddthreadfilter005a(String threadName) { + super(threadName); + } + + public void run() { + log1(" 'run': enter "); + + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + log1(" 'run': exit "); + } + return; + } + } + +} + +class addthreadfilter005aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java new file mode 100644 index 00000000000..498a27dff33 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.addThreadFilter()
    + * complies with its spec.
    + *
    + * The test checks up on the following assertion:
    + * Restricts the events generated by this request
    + * to those in the given thread.
    + * The cases to test include three thread's states:
    + * not started, running, dead.
    + * The tested Request is ModificationWatchpointRequest.
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee creates new thread, thread1, and invokes
    + * the methodForCommunication to be suspended and
    + * to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates ModificationWatchpointRequest1 and
    + * invokes the method addThreadFilter(tread1) on the request1,
    + * - creates ModificationWatchpointRequest2,
    + * resumes the debuggee to get the thread1 started, and
    + * invokes the method addThreadFilter(thread) on the request2,
    + * - creates ModificationWatchpointRequest3, waits the thread1 to die,
    + * and invokes the method addThreadFilter(thread) on the request3.
    + *
    + * In third phase, at the end of the test,
    + * the debuggee changes the value of the "instruction" which
    + * the debugger and debuggee use to inform each other of needed actions,
    + * and both end. + *
    + */ + +public class addthreadfilter006 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new addthreadfilter006().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter006a"; + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter006aTestClass"; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + if ( !vm.canWatchFieldModification() ) { + log2("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(PASS_BASE); + return; + } + + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + EventRequest eventRequest3 = null; + + ThreadReference thread1 = null; + String thread1Name = "thread1"; + + String property1 = "ModificationWatchpointRequest1"; + String property2 = "ModificationWatchpointRequest2"; + String property3 = "ModificationWatchpointRequest3"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2ModificationWatchpointRequest (null, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, "ModificationWatchpointRequest1"); + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ModificationWatchpointRequest)eventRequest1).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 1: + eventRequest2 = setting2ModificationWatchpointRequest (null, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, "ModificationWatchpointRequest2"); + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ModificationWatchpointRequest)eventRequest2).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2ModificationWatchpointRequest (null, + testClassReference, fieldName, + EventRequest.SUSPEND_NONE, "ModificationWatchpointRequest3"); + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((ModificationWatchpointRequest)eventRequest3).addThreadFilter(thread1); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest setting2ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006/TestDescription.java new file mode 100644 index 00000000000..632412c7706 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006/TestDescription.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The cases to test include three thread's states: not started, running, dead. + * The tested Request is ModificationWatchpointRequest. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter006; + * the debuggee program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter006a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter006 + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter006a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter006 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006a.java new file mode 100644 index 00000000000..b6299fce536 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006a.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter006 JDI test. + */ + +public class addthreadfilter006a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter006a thread1 = null; + + static addthreadfilter006aTestClass objTC = new addthreadfilter006aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter006a("thread1"); + break; + + case 1: + synchronized (lockObj) { + threadStart(thread1); + log1("methodForCommunication();"); + methodForCommunication(); + } + break; + + case 2: + try { + thread1.join(); + } catch ( InterruptedException e) { + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + static Object lockObj = new Object(); + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static class Threadaddthreadfilter006a extends Thread { + + public Threadaddthreadfilter006a(String threadName) { + super(threadName); + } + + public void run() { + log1(" 'run': enter "); + + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + synchronized (lockObj) { + log1(" 'run': exit "); + } + return; + } + } + +} + +class addthreadfilter006aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007.java new file mode 100644 index 00000000000..e8b7f6268e2 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same AccessWatchpointRequest object. + * There are two AccessWatchpointRequests to check as follows: + * (1) For AccessWatchpointRequest2, both invocations are with different + * ThreadReferences restricting one AccessWatchpoint event to two threads. + * The test expects no AccessWatchpoint event will be received. + * (2) For AccessWatchpointRequest1, both invocations are with the same + * ThreadReference restricting one AccessWatchpoint event to one thread. + * The test expects this AccessWatchpoint event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up AccessWatchpointRequests 1&2 within the method + * in the class addthreadfilter007aTestClass which will be calling by both threads, + * - restricts the AccessWatchpointRequest1 only to thread1, + * - restricts the AccessWatchpointRequest2 to both thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class addthreadfilter007 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter007a"; + return new addthreadfilter007().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter007aTestClass"; + + + protected void testRun() { + if ( !vm.canWatchFieldAccess() ) { + display("......vm.canWatchFieldAccess == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "AccessWatchpointRequest1"; + String property2 = "AccessWatchpointRequest2"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2AccessWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2AccessWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property2); + + ((AccessWatchpointRequest) eventRequest1).addThreadFilter(thread1); + ((AccessWatchpointRequest) eventRequest2).addThreadFilter(thread2); + + display("......waiting for AccessWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if (!(newEvent instanceof AccessWatchpointEvent)) { + setFailedStatus("ERROR: new event is not WatchpointEvent"); + } else { + display(" got expected event"); + + ThreadReference newEventThread = ((AccessWatchpointEvent) newEvent).thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private AccessWatchpointRequest setting2AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up AccessWatchpointRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007/TestDescription.java new file mode 100644 index 00000000000..24c3e74bb56 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The tested Request is AccessWatchpointRequest and + * the cases to test include re-invocations of the method + * addThreadFilter() on the same AccessWatchpointRequest object. + * There are two AccessWatchpointRequests to check as follows: + * (1) For AccessWatchpointRequest2, both invocations are with different + * ThreadReferences restricting one AccessWatchpoint event to two threads. + * The test expects no AccessWatchpoint event will be received. + * (2) For AccessWatchpointRequest1, both invocations are with the same + * ThreadReference restricting one AccessWatchpoint event to one thread. + * The test expects this AccessWatchpoint event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter007; + * the debuggee program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter007a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter007 + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter007a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter007 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007a.java new file mode 100644 index 00000000000..e9737904e34 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter007a.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter007 JDI test. + */ + +public class addthreadfilter007a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter007a thread1 = null; + static Threadaddthreadfilter007a thread2 = null; + + static addthreadfilter007aTestClass objTC = new addthreadfilter007aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter007a("thread1"); + thread2 = new Threadaddthreadfilter007a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter007a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter007a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class addthreadfilter007aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008.java new file mode 100644 index 00000000000..130510f45b6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type + * WatchpointRequest. + * + * The test checks up on the following assertion: + * Restricts the events generated by this request + * to those in the given thread. + * The cases to test include re-invocations of the method + * addThreadFilter() on the same ModificationWatchpointRequest object. + * There are two ModificationWatchpointRequests to check as follows: + * (1) For ModificationWatchpointRequest2, both invocations are with different + * ThreadReferences restricting one ModificationWatchpoint event to two threads. + * The test expects no ModificationWatchpoint event will be received. + * (2) For ModificationWatchpointRequest1, both invocations are with the same + * ThreadReference restricting one ModificationWatchpoint event to one thread. + * The test expects this ModificationWatchpoint event will be received. + * + * The test works as follows. + * - The debugger resumes the debuggee and waits for the BreakpointEvent. + * - The debuggee creates two threads, thread1 and thread2, and invokes + * the methodForCommunication to be suspended and + * to inform the debugger with the event. + * - Upon getting the BreakpointEvent, the debugger + * - sets up ModificationWatchpointRequests 1&2 within the method + * in the class addthreadfilter008aTestClass which will be calling by both threads, + * - restricts the ModificationWatchpointRequest1 only to thread1, + * - restricts the ModificationWatchpointRequest2 to both thread1 and thread2, + * - resumes debuggee's main thread, and + * - waits for the event. + * - Debuggee's main thread starts both threads. + * - Upon getting the event, the debugger performs the checks required. + */ + +public class addthreadfilter008 extends TestDebuggerType1 { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run (String argv[], PrintStream out) { + debuggeeName = "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter008a"; + return new addthreadfilter008().runThis(argv, out); + } + + private String testedClassName = + "nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter008aTestClass"; + + + protected void testRun() { + if ( !vm.canWatchFieldModification() ) { + display("......vm.canWatchFieldModification == false :: test cancelled"); + vm.exit(Consts.JCK_STATUS_BASE); + return; + } + + EventRequest eventRequest1 = null; + EventRequest eventRequest2 = null; + + ThreadReference thread1 = null; + ThreadReference thread2 = null; + + String thread1Name = "thread1"; + String thread2Name = "thread2"; + + String property1 = "ModificationWatchpointRequest1"; + String property2 = "ModificationWatchpointRequest2"; + + String fieldName = "var1"; + + ReferenceType testClassReference = null; + Event newEvent = null; + + for (int i = 0; ; i++) { + + if (!shouldRunAfterBreakpoint()) { + vm.resume(); + break; + } + + display(":::::: case: # " + i); + + switch (i) { + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName).get(0); + + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + thread2 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread2Name)); + + eventRequest1 = setting2ModificationWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property1); + eventRequest2 = setting2ModificationWatchpointRequest (thread1, + testClassReference, fieldName, + EventRequest.SUSPEND_ALL, property2); + + ((ModificationWatchpointRequest) eventRequest1).addThreadFilter(thread1); + ((ModificationWatchpointRequest) eventRequest2).addThreadFilter(thread2); + + display("......waiting for ModificationWatchpointEvent in tested thread"); + newEvent = eventHandler.waitForRequestedEvent(new EventRequest[]{eventRequest1, eventRequest2}, waitTime, true); + + if (!(newEvent instanceof ModificationWatchpointEvent)) { + setFailedStatus("ERROR: new event is not WatchpointEvent"); + } else { + display(" got expected event"); + + ThreadReference newEventThread = ((ModificationWatchpointEvent) newEvent).thread(); + String threadName = newEventThread.name(); + display(" the event is in thread == " + newEventThread.name()); + if ( !newEventThread.equals(thread1) ) { + setFailedStatus("ERROR: the event is not in thread1"); + } + } + vm.resume(); + break; + + default: + throw new Failure("** default case 1 **"); + } + } + return; + } + + private ModificationWatchpointRequest setting2ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType testedClass, + String fieldName, + int suspendPolicy, + String property ) { + try { + display("......setting up ModificationWatchpointRequest:"); + display(" thread: " + thread + "; class: " + testedClass + "; fieldName: " + fieldName); + Field field = testedClass.fieldByName(fieldName); + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + display(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + throw new Failure("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008/TestDescription.java new file mode 100644 index 00000000000..aa236d990df --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008/TestDescription.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.addThreadFilter() + * complies with its spec: + * public void addThreadFilter(ThreadReference thread) + * Restricts the events generated by this request to those in the given thread. + * Parameters: thread - the thread to filter on. + * Throws: InvalidRequestStateException - + * if this request is currently enabled or has been deleted. + * Filters may be added only to disabled requests. + * The test checks up on the following assertion: + * Restricts the events generated by this request to those in the given thread. + * The tested Request is ModificationWatchpointRequest and + * the cases to test include re-invocations of the method + * addThreadFilter() on the same ModificationWatchpointRequest object. + * There are two ModificationWatchpointRequests to check as follows: + * (1) For ModificationWatchpointRequest2, both invocations are with different + * ThreadReferences restricting one ModificationWatchpoint event to two threads. + * The test expects no ModificationWatchpoint event will be received. + * (2) For ModificationWatchpointRequest1, both invocations are with the same + * ThreadReference restricting one ModificationWatchpoint event to one thread. + * The test expects this ModificationWatchpoint event will be received. + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter008; + * the debuggee program - nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter008a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * 4930911 TEST_BUG: filter_rt006 debuggee has a race + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter008 + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter008a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.addThreadFilter.addthreadfilter008 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008a.java new file mode 100644 index 00000000000..8eeb68ac3c1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter008a.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.addThreadFilter; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the addthreadfilter008 JDI test. + */ + +public class addthreadfilter008a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + private static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static Threadaddthreadfilter008a thread1 = null; + static Threadaddthreadfilter008a thread2 = null; + + static addthreadfilter008aTestClass objTC = new addthreadfilter008aTestClass(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: + thread1 = new Threadaddthreadfilter008a("thread1"); + thread2 = new Threadaddthreadfilter008a("thread2"); + break; + + case 1: + threadStart(thread1); + threadStart(thread2); + synchronized(lockingObj[0]) { + log1("synchronized(lockingObj[0])"); + } + synchronized(lockingObj[1]) { + log1("synchronized(lockingObj[1])"); + } + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } + + + + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + static Object lockingObj[] = new Object[2]; + static volatile int number = 0; + + static class Threadaddthreadfilter008a extends Thread { + + String tName = null; + int tNumber; + + public Threadaddthreadfilter008a(String threadName) { + super(threadName); + tName = threadName; + tNumber = number; + number++; + lockingObj[tNumber] = threadName; + } + + public void run() { + log1(" 'run': enter :: threadName == " + tName); + if (lockingObj[tNumber] == null) + log1("lockingObj[tNumber] == null"); + synchronized(lockingObj[tNumber]) { + synchronized (waitnotifyObj) { + waitnotifyObj.notify(); + } + objTC.method(); + } + log1(" 'run': exit :: threadName == " + tName); + return; + } + } + +} + +class addthreadfilter008aTestClass { + + static int breakpointLine = 3; + static String awFieldName = "var1"; + static String mwFieldName = "var2"; + + static int var1 = 0; + static int var2 = 0; + static int var3 = 0; + + static void method () { + var1 = 1; + var3 = var1; + var2 = var3; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java new file mode 100644 index 00000000000..3746a3b4eb3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.field; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.field()
    + * complies with its spec.
    + *
    + * The case to test include AccessWatchpointRequest.
    + * The test checks if a Field object, an argument of the method
    + * EventRequestManager.createAccessWatchpointRequest(Field),
    + * is equal to one returned by the method WatchpointRequest.field()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an AccessWatchpointRequest and gets Field object filed1,
    + * - gets Field object field2 with the method WatchpointRequest.field(),
    + * - compares the Filed objects.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class field001 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/field/field001 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new field001().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.field.field001a"; + + private String testedClassName1 = + "nsk.jdi.WatchpointRequest.field.TestClass10"; + + Field field1 = null; + Field field2 = null; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + String property1 = "AccessWatchpointRequest1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName1).get(0); + + log2("......setting up AccessWatchpointRequest and getting Field object field1"); + eventRequest1 = setting21AccessWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_NONE, property1); + + log2("......getting: field2 = ((WatchpointRequest) eventRequest1).field();"); + field2 = ((WatchpointRequest) eventRequest1).field(); + + log2(" checking up on equality of field1 and field2"); + if ( !field1.equals(field2) ) { + testExitCode = FAILED; + log3("ERROR: Field objects are not equal"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private AccessWatchpointRequest setting21AccessWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up AccessWatchpointRequest:"); + log2(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + field1 = field; + + AccessWatchpointRequest + awr = eventRManager.createAccessWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" AccessWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingAccessWatchpointRequest() : " + e); + log3(" AccessWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up AccessWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001/TestDescription.java new file mode 100644 index 00000000000..89593b3641f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/field/field001. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.field() + * complies with its spec: + * public Field field() + * Gets the Field being watched by this WatchpointRequest. + * Returns: the Field this Watchpoint is monitoring. + * The case to test include AccessWatchpointRequest. + * The test checks if a Field object, + * an argument of the method EventRequestManager.createAccessWatchpointRequest(Field), + * is equal to one returned by the method WatchpointRequest.field() + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.field.field001; + * the debuggee program - nsk.jdi.WatchpointRequest.field.field001a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.field.field001 + * nsk.jdi.WatchpointRequest.field.field001a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.field.field001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001a.java new file mode 100644 index 00000000000..375e84573ed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001a.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.field; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the field001 JDI test. + */ + +public class field001a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static TestClass10 obj10 = new TestClass10(); + static TestClass11 obj11 = new TestClass11(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +/* + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +*/ +} + +class TestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class TestClass11 extends TestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; +// TestClass10.method(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java new file mode 100644 index 00000000000..1e09ff899b8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.field; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; +import java.io.*; + +/** + * The test for the implementation of an object of the type
    + * WatchpointRequest.
    + *
    + * The test checks that results of the method
    + * com.sun.jdi.WatchpointRequest.field()
    + * complies with its spec.
    + *
    + * The case to test include ModificationWatchpointRequest.
    + * The test checks if a Field object, an argument of the method
    + * EventRequestManager.createModificationWatchpointRequest(Field),
    + * is equal to one returned by the method WatchpointRequest.field()
    + *
    + * The test has three phases and works as follows.
    + *
    + * In first phase,
    + * upon launching debuggee's VM which will be suspended,
    + * a debugger waits for the VMStartEvent within a predefined
    + * time interval. If no the VMStartEvent received, the test is FAILED.
    + * Upon getting the VMStartEvent, it makes the request for debuggee's
    + * ClassPrepareEvent with SUSPEND_EVENT_THREAD, resumes the VM,
    + * and waits for the event within the predefined time interval.
    + * If no the ClassPrepareEvent received, the test is FAILED.
    + * Upon getting the ClassPrepareEvent,
    + * the debugger sets up the breakpoint with SUSPEND_EVENT_THREAD
    + * within debuggee's special methodForCommunication().
    + *
    + * In second phase to check the assertion,
    + * the debugger and the debuggee perform the following.
    + * - The debugger resumes the debuggee and waits for the BreakpointEvent.
    + * - The debuggee invokes the methodForCommunication to be suspended
    + * and to inform the debugger with the event.
    + * - Upon getting the BreakpointEvent, the debugger
    + * - creates an ModificationWatchpointRequest and
    + * gets Field object filed1,
    + * - gets Field object field2 with the method WatchpointRequest.field(),
    + * - compares the Filed objects.
    + *
    + * In third phase, at the end of the test, the debuggee changes
    + * the value of the "instruction" which the debugger and debuggee
    + * use to inform each other of needed actions, and both end.
    + *
    + */ + +public class field002 { + + //----------------------------------------------------- templete section + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + //----------------------------------------------------- templete parameters + static final String + sHeader1 = "\n==> nsk/jdi/WatchpointRequest/field/field002 ", + sHeader2 = "--> debugger: ", + sHeader3 = "##> debugger: "; + + //----------------------------------------------------- main method + + public static void main (String argv[]) { + + int result = run(argv, System.out); + + System.exit(result + PASS_BASE); + } + + public static int run (String argv[], PrintStream out) { + + int exitCode = new field002().runThis(argv, out); + + if (exitCode != PASSED) { + System.out.println("TEST FAILED"); + } + return testExitCode; + } + + //-------------------------------------------------- log procedures + + private static Log logHandler; + + private static void log1(String message) { + logHandler.display(sHeader1 + message); + } + private static void log2(String message) { + logHandler.display(sHeader2 + message); + } + private static void log3(String message) { + logHandler.complain(sHeader3 + message); + } + + // ************************************************ test parameters + + private String debuggeeName = + "nsk.jdi.WatchpointRequest.field.field002a"; + + private String testedClassName1 = + "nsk.jdi.WatchpointRequest.field.field002aTestClass10"; + + Field field1 = null; + Field field2 = null; + + //====================================================== test program + //------------------------------------------------------ common section + + static Debugee debuggee; + static ArgumentHandler argsHandler; + + static int waitTime; + + static VirtualMachine vm = null; + static EventRequestManager eventRManager = null; + static EventQueue eventQueue = null; + static EventSet eventSet = null; + static EventIterator eventIterator = null; + + static ReferenceType debuggeeClass = null; + + static int testExitCode = PASSED; + + + class JDITestRuntimeException extends RuntimeException { + JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } + } + + //------------------------------------------------------ methods + + private int runThis (String argv[], PrintStream out) { + + argsHandler = new ArgumentHandler(argv); + logHandler = new Log(out, argsHandler); + Binder binder = new Binder(argsHandler, logHandler); + + waitTime = argsHandler.getWaitTime() * 60000; + + try { + log2("launching a debuggee :"); + log2(" " + debuggeeName); + if (argsHandler.verbose()) { + debuggee = binder.bindToDebugee(debuggeeName + " -vbs"); + } else { + debuggee = binder.bindToDebugee(debuggeeName); + } + if (debuggee == null) { + log3("ERROR: no debuggee launched"); + return FAILED; + } + log2("debuggee launched"); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + log2(" test cancelled"); + return FAILED; + } + + debuggee.redirectOutput(logHandler); + + vm = debuggee.VM(); + + eventQueue = vm.eventQueue(); + if (eventQueue == null) { + log3("ERROR: eventQueue == null : TEST ABORTED"); + vm.exit(PASS_BASE); + return FAILED; + } + + log2("invocation of the method runTest()"); + switch (runTest()) { + + case 0 : log2("test phase has finished normally"); + log2(" waiting for the debuggee to finish ..."); + debuggee.waitFor(); + + log2("......getting the debuggee's exit status"); + int status = debuggee.getStatus(); + if (status != PASS_BASE) { + log3("ERROR: debuggee returned UNEXPECTED exit status: " + + status + " != PASS_BASE"); + testExitCode = FAILED; + } else { + log2("......debuggee returned expected exit status: " + + status + " == PASS_BASE"); + } + break; + + default : log3("ERROR: runTest() returned unexpected value"); + + case 1 : log3("test phase has not finished normally: debuggee is still alive"); + log2("......forcing: vm.exit();"); + testExitCode = FAILED; + try { + vm.exit(PASS_BASE); + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + + case 2 : log3("test cancelled due to VMDisconnectedException"); + log2("......trying: vm.process().destroy();"); + testExitCode = FAILED; + try { + Process vmProcess = vm.process(); + if (vmProcess != null) { + vmProcess.destroy(); + } + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + } + break; + } + + return testExitCode; + } + + + /* + * Return value: 0 - normal end of the test + * 1 - ubnormal end of the test + * 2 - VMDisconnectedException while test phase + */ + + private int runTest() { + + try { + testRun(); + + log2("waiting for VMDeathEvent"); + getEventSet(); + if (eventIterator.nextEvent() instanceof VMDeathEvent) + return 0; + + log3("ERROR: last event is not the VMDeathEvent"); + return 1; + } catch ( VMDisconnectedException e ) { + log3("ERROR: VMDisconnectedException : " + e); + return 2; + } catch ( Exception e ) { + log3("ERROR: Exception : " + e); + return 1; + } + + } + + private void testRun() + throws JDITestRuntimeException, Exception { + + eventRManager = vm.eventRequestManager(); + + ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); + cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.addClassFilter(debuggeeName); + + cpRequest.enable(); + vm.resume(); + getEventSet(); + cpRequest.disable(); + + ClassPrepareEvent event = (ClassPrepareEvent) eventIterator.next(); + debuggeeClass = event.referenceType(); + + if (!debuggeeClass.name().equals(debuggeeName)) + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + + log2(" received: ClassPrepareEvent for debuggeeClass"); + + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + ThreadReference mainThread = threadByName("main"); + + BreakpointRequest bpRequest = settingBreakpoint(mainThread, + debuggeeClass, + bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + + //------------------------------------------------------ testing section + + log1(" TESTING BEGINS"); + + EventRequest eventRequest1 = null; + String property1 = "ModificationWatchpointRequest1"; + String fieldName1 = "var101"; + + ReferenceType testClassReference = null; + + + for (int i = 0; ; i++) { + + vm.resume(); + breakpointForCommunication(); + + int instruction = ((IntegerValue) + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + + if (instruction == 0) { + vm.resume(); + break; + } + + + log1(":::::: case: # " + i); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part + + switch (i) { + + case 0: + testClassReference = + (ReferenceType) vm.classesByName(testedClassName1).get(0); + + log2(".....setting up ModificationWatchpointRequest and getting Field object field1"); + eventRequest1 = setting21ModificationWatchpointRequest (null, + testClassReference, fieldName1, + EventRequest.SUSPEND_NONE, property1); + + log2("......getting: field2 = ((WatchpointRequest) eventRequest1).field();"); + field2 = ((WatchpointRequest) eventRequest1).field(); + + log2(" checking up on equality of field1 and field2"); + if ( !field1.equals(field2) ) { + testExitCode = FAILED; + log3("ERROR: Field objects are not equal"); + } + + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + log1(" TESTING ENDS"); + return; + } + + private ThreadReference threadByName(String name) + throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + + /* + * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, + * String, String, String) + * + * It sets up a breakpoint at given line number within a given method in a given class + * for a given thread. + * + * Return value: BreakpointRequest object in case of success + * + * JDITestRuntimeException in case of an Exception thrown within the method + */ + + private BreakpointRequest settingBreakpoint ( ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + + log2("......setting up a breakpoint:"); + log2(" thread: " + thread + "; class: " + testedClass + + "; method: " + methodName + "; line: " + bpLine); + + List alllineLocations = null; + Location lineLocation = null; + BreakpointRequest breakpRequest = null; + + try { + Method method = (Method) testedClass.methodsByName(methodName).get(0); + + alllineLocations = method.allLineLocations(); + + int n = + ( (IntegerValue) testedClass.getValue(testedClass.fieldByName(bpLine) ) ).value(); + if (n > alllineLocations.size()) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines"); + } else { + lineLocation = (Location) alllineLocations.get(n); + try { + breakpRequest = eventRManager.createBreakpointRequest(lineLocation); + breakpRequest.putProperty("number", property); + breakpRequest.addThreadFilter(thread); + breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + } catch ( Exception e1 ) { + log3("ERROR: inner Exception within settingBreakpoint() : " + e1); + breakpRequest = null; + } + } + } catch ( Exception e2 ) { + log3("ERROR: ATTENTION: outer Exception within settingBreakpoint() : " + e2); + breakpRequest = null; + } + + if (breakpRequest == null) { + log2(" A BREAKPOINT HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("**FAILURE to set up a breakpoint**"); + } + + log2(" a breakpoint has been set up"); + return breakpRequest; + } + + + private void getEventSet() + throws JDITestRuntimeException { + try { +// log2(" eventSet = eventQueue.remove(waitTime);"); + eventSet = eventQueue.remove(waitTime); + if (eventSet == null) { + throw new JDITestRuntimeException("** TIMEOUT while waiting for event **"); + } +// log2(" eventIterator = eventSet.eventIterator;"); + eventIterator = eventSet.eventIterator(); + } catch ( Exception e ) { + throw new JDITestRuntimeException("** EXCEPTION while waiting for event ** : " + e); + } + } + + + private void breakpointForCommunication() + throws JDITestRuntimeException { + + log2("breakpointForCommunication"); + getEventSet(); + + if (eventIterator.nextEvent() instanceof BreakpointEvent) + return; + + throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + } + + // ============================== test's additional methods + + private ModificationWatchpointRequest setting21ModificationWatchpointRequest ( + ThreadReference thread, + ReferenceType fieldClass, + String fieldName, + int suspendPolicy, + String property ) + throws JDITestRuntimeException { + try { + log2("......setting up ModificationWatchpointRequest:"); + log2(" thread: " + thread + "; fieldClass: " + fieldClass + "; fieldName: " + fieldName); + Field field = fieldClass.fieldByName(fieldName); + + field1 = field; + + ModificationWatchpointRequest + awr = eventRManager.createModificationWatchpointRequest(field); + awr.putProperty("number", property); + + if (thread != null) + awr.addThreadFilter(thread); + awr.setSuspendPolicy(suspendPolicy); + + log2(" ModificationWatchpointRequest has been set up"); + return awr; + } catch ( Exception e ) { + log3("ERROR: ATTENTION: Exception within settingModificationWatchpointRequest() : " + e); + log3(" ModificationWatchpointRequest HAS NOT BEEN SET UP"); + throw new JDITestRuntimeException("** FAILURE to set up ModificationWatchpointRequest **"); + } + } + +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002/TestDescription.java new file mode 100644 index 00000000000..e7053acf918 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002/TestDescription.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * + * @summary converted from VM Testbase nsk/jdi/WatchpointRequest/field/field002. + * VM Testbase keywords: [quick, jpda, jdi] + * VM Testbase readme: + * DESCRIPTION: + * The test for the implementation of an object of the type + * WatchpointRequest. + * The test checks up that a result of the method + * com.sun.jdi.WatchpointRequest.field() + * complies with its spec: + * public Field field() + * Gets the Field being watched by this WatchpointRequest. + * Returns: the Field this Watchpoint is monitoring. + * The case to test include ModificationWatchpointRequest. + * The test checks if a Field object, + * an argument of the method EventRequestManager.createModificationWatchpointRequest(Field), + * is equal to one returned by the method WatchpointRequest.field() + * The test works as follows: + * The debugger program - nsk.jdi.WatchpointRequest.field.field002; + * the debuggee program - nsk.jdi.WatchpointRequest.field.field002a. + * Using nsk.jdi.share classes, + * the debugger gets the debuggee running on another JavaVM, + * creates the object debuggee.VM, and waits for VMStartEvent. + * Upon getting the debuggee VM started, + * the debugger calls corresponding debuggee.VM methods to get + * needed data and to perform checks. + * In case of error the test produces the return value 97 and + * a corresponding error message(s). + * Otherwise, the test is passed and produces + * the return value 95 and no message. + * COMMENTS: + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.WatchpointRequest.field.field002 + * nsk.jdi.WatchpointRequest.field.field002a + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.WatchpointRequest.field.field002 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002a.java new file mode 100644 index 00000000000..1ccb944aed0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002a.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2001, 2018, 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 nsk.jdi.WatchpointRequest.field; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * This class is used as debuggee application for the field002 JDI test. + */ + +public class field002a { + + //----------------------------------------------------- templete section + + static final int PASSED = 0; + static final int FAILED = 2; + static final int PASS_BASE = 95; + + static ArgumentHandler argHandler; + static Log log; + + //-------------------------------------------------- log procedures + + public static void log1(String message) { + log.display("**> debuggee: " + message); + } + + private static void logErr(String message) { + log.complain("**> debuggee: " + message); + } + + //====================================================== test program + + static field002aTestClass10 obj10 = new field002aTestClass10(); + static field002aTestClass11 obj11 = new field002aTestClass11(); + + //------------------------------------------------------ common section + + static int exitCode = PASSED; + + static int instruction = 1; + static int end = 0; + // static int quit = 0; + // static int continue = 2; + static int maxInstr = 1; // 2; + + static int lineForComm = 2; + + private static void methodForCommunication() { + int i1 = instruction; + int i2 = i1; + int i3 = i2; + } + //---------------------------------------------------- main method + + public static void main (String argv[]) { + + argHandler = new ArgumentHandler(argv); + log = argHandler.createDebugeeLog(); + + log1("debuggee started!"); + + label0: + for (int i = 0; ; i++) { + + log1("methodForCommunication();"); + methodForCommunication(); + if (instruction == end) + break; + + if (instruction > maxInstr) { + logErr("ERROR: unexpected instruction: " + instruction); + exitCode = FAILED; + break ; + } + + switch (i) { + + //------------------------------------------------------ section tested + + case 0: +// break; + + //------------------------------------------------- standard end section + + default: + instruction = end; + break; + } + } + + log1("debuggee exits"); + System.exit(exitCode + PASS_BASE); + } +/* + static Object waitnotifyObj = new Object(); + + static int threadStart(Thread t) { + synchronized (waitnotifyObj) { + t.start(); + try { + waitnotifyObj.wait(); + } catch ( Exception e) { + exitCode = FAILED; + logErr(" Exception : " + e ); + return FAILED; + } + } + return PASSED; + } + + public void run1(Thread t) { + t.start(); + try { + t.join(); + } catch ( InterruptedException e ) { + } + } +*/ +} + +class field002aTestClass10 { + static int var101 = 0; + static int var102 = 0; + static int var103 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + } +} +class field002aTestClass11 extends field002aTestClass10 { + + static int var111 = 0; + static int var112 = 0; + static int var113 = 0; + + static void method () { + var101 = 1; + var103 = var101; + var102 = var103; + + var111 = 1; + var113 = var111; + var112 = var113; +// field002aTestClass10.method(); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001/ClassPrepareEvents001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001/ClassPrepareEvents001.java new file mode 100644 index 00000000000..e4d8961cb77 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001/ClassPrepareEvents001.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2007, 2018, 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 + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6, quarantine] + * VM Testbase comments: JDK-6426321 + * VM Testbase readme: + * DESCRIPTION + * Test covers bug 6426321. Test stress event queue forcing loading of 3000 classes in debuggee. + * Debugger in loop sends commad to debuggee to load class and waits READY answer. + * Test passes if no hangs or any other errors occur in debuggee (if debuggee successfully sends answers for all commands). + * (number of classes to load can be changed through parameter -classesToLoad (for example -classesToLoad 1000)). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdi.stress.ClassPrepareEvents.ClassPrepareEvents001.ClassPrepareEvents001 + * @run main/othervm PropertyResolvingWrapper + * nsk.jdi.stress.ClassPrepareEvents.ClassPrepareEvents001.ClassPrepareEvents001 + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + */ + +package nsk.jdi.stress.ClassPrepareEvents.ClassPrepareEvents001; + +import java.io.*; +import java.util.ArrayList; +import nsk.share.*; +import nsk.share.jdi.*; +import nsk.share.jpda.AbstractDebuggeeTest; + +public class ClassPrepareEvents001 extends TestDebuggerType2 { + public static void main(String argv[]) { + System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + return new ClassPrepareEvents001().runIt(argv, out); + } + + protected String[] doInit(String args[], PrintStream out) { + args = super.doInit(args, out); + + ArrayList standardArgs = new ArrayList(); + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-classesToLoad") && (i < args.length - 1)) { + classesToLoad = Integer.parseInt(args[i + 1]); + i++; + } else + standardArgs.add(args[i]); + } + + return standardArgs.toArray(new String[] {}); + } + + protected String debuggeeClassName() { + if (classpath == null) + throw new TestBug("Debugger requires 'testClassPath' parameter"); + + return AbstractJDIDebuggee.class.getName() + " -testClassPath " + classpath; + } + + private int classesToLoad = 3000; + + public void doTest() { + log.display("Debugger forces debuggee to load " + classesToLoad + " classes"); + + // force loading of 'classesToLoad' classes in debuggee VM + for (int i = 0; i < classesToLoad; i++) { + pipe.println(AbstractDebuggeeTest.COMMAND_LOAD_CLASS + ":" + TestClass1.class.getName()); + if (!isDebuggeeReady()) + return; + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents001/TestDescription.java new file mode 100644 index 00000000000..59d117049a3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents001/TestDescription.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/MonitorEvents/MonitorEvents001. + * VM Testbase keywords: [stress, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for following jdi events and event requests: + * - MonitorContendedEnteredRequest/MonitorContendedEnteredEvent + * - MonitorContendedEnterRequest/MonitorContendedEnterEvent + * - MonitorWaitRequest/MonitorWaitEvent + * - MonitorWaitedRequest/MonitorWaitedEvent + * Debugger forces debuggee generate several thousands of monitor events and checks that all events was received and contain + * correct information. + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debuggee VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint, all event generators save information about generated events + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 500 and threadsNumber to 1, but because of framework design each requested + * MonitorEnterEvent and MonitorEnteredEvent should be generated in 3 different way(through synchronized block, synchronized method + * and JNI MonitorEnter), and by 3 different threads, so actual number of this events is (eventsNumber * 9) and + * actual number of threads generating this events is (threadsNumber * 3). + * MonitorWait and MonitorWaited events are generated by 3 different threads and each MonitorWaited event should be generated for 4 cases: + * thread exits from wait() after timeout, waiting thread is waked up with notify() or notifyAll(), or waiting thread + * is interrupted with interrupt(), so actual number of this events is (eventsNumber * 12), and actual number of threads generating this events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED:MONITOR_CONTENTED_ENTER + * -allowExtraEvents MONITOR_CONTENTED_ENTER:MONITOR_CONTENTED_ENTERED + * -eventTypes MONITOR_CONTENTED_ENTERED:MONITOR_CONTENTED_ENTER:MONITOR_WAIT:MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 100 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents002/TestDescription.java new file mode 100644 index 00000000000..0581f8dced6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/MonitorEvents/MonitorEvents002/TestDescription.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open java.base/jdk.internal.misc:+open + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/MonitorEvents/MonitorEvents002. + * VM Testbase keywords: [stress, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This is stress test for following jdi events and event requests: + * - MonitorContendedEnteredRequest/MonitorContendedEnteredEvent + * - MonitorContendedEnterRequest/MonitorContendedEnterEvent + * - MonitorWaitRequest/MonitorWaitEvent + * - MonitorWaitedRequest/MonitorWaitedEvent + * Debugger force debuggee start several threads which simultaneously generate events and check that all events + * was received and contain correct information. + * Test executes class nsk.share.jdi.EventTestTemplates$StressTestTemplate which uses JDI events testing + * framework based on classes from package nsk.share.jdi.*. + * This framework uses following scenario: + * - debugger VM forces debuggee VM to create number of objects which should generate events during test + * - debuggee performs event generation and stop at breakpoint, all event generators save information about generated events + * - debugger reads data saved by debuggee's event generators and checks is only expected events was generated + * Stress test template allows to specify number of events which should be generated during test execution(parameter -eventsNumber) + * and number of threads which simultaneously generate events (parameter -threadsNumber). + * This test set eventsNumber to 50 and threadsNumber to 10, but because of framework design each requested + * MonitorEnterEvent and MonitorEnteredEvent should be generated in 3 different way(through synchronized block, synchronized method + * and JNI MonitorEnter), and by 3 different threads, so actual number of this events is (eventsNumber * 9) and + * actual number of threads generating this events is (threadsNumber * 3). + * MonitorWait and MonitorWaited events are generated by 3 different threads and each MonitorWaited event should be generated for 4 cases: + * thread exits from wait() after timeout, waiting thread is waked up with notify() or notifyAll(), or waiting thread + * is interrupted with interrupt(), so actual number of this events is (eventsNumber * 12), and actual number of threads generating this events is (threadsNumber * 3). + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.EventTestTemplates$StressTestTemplate + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -allowMissedEvents MONITOR_CONTENTED_ENTERED:MONITOR_CONTENTED_ENTER + * -allowExtraEvents MONITOR_CONTENTED_ENTER:MONITOR_CONTENTED_ENTERED + * -eventTypes MONITOR_CONTENTED_ENTERED:MONITOR_CONTENTED_ENTER:MONITOR_WAIT:MONITOR_WAITED + * -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + * -eventsNumber 10 + * -threadsNumber 2 + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java new file mode 100644 index 00000000000..c77f621ac01 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, 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 + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/forceEarlyReturn001. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'forceEarlyReturn001.tests' and tests are executed in given order. + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from forceEarlyReturn001.tests + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014a + * + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./forceEarlyReturn001.tests + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/forceEarlyReturn001.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/forceEarlyReturn001.tests new file mode 100644 index 00000000000..b58a2ffaeef --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/forceEarlyReturn001.tests @@ -0,0 +1,8 @@ +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java new file mode 100644 index 00000000000..e59c810490d --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/forceEarlyReturn002. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'forceEarlyReturn002.tests', before execution test list is shuffled and tests are executed + * in random order, resulted test order is saved in file 'run.tests', to reproduce failed test execute it + * with option '-configFile run.tests'(instead of -configFile forceEarlyReturn002.tests). + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from forceEarlyReturn002.tests + * @build nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014a + * + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./forceEarlyReturn002.tests + * -testWorkDir . + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/forceEarlyReturn002.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/forceEarlyReturn002.tests new file mode 100644 index 00000000000..36baf61f6dd --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/forceEarlyReturn002.tests @@ -0,0 +1,9 @@ +OPTIONS:shuffle +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn005.forceEarlyReturn005 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn008.forceEarlyReturn008 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn013.forceEarlyReturn013 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn014.forceEarlyReturn014 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java new file mode 100644 index 00000000000..3b925d509e7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, 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 + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/heapwalking001. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'heapwalking001.tests' and tests are executed in given order. + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from heapwalking001.tests + * @build nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 + * nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003a + * nsk.jdi.ObjectReference.referringObjects.referringObjects004.referringObjects004 + * nsk.jdi.ReferenceType.instances.instances003.instances003 + * nsk.share.jdi.TestClass1 + * nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 + * nsk.share.jdi.TestClass1 + * nsk.share.jdi.TestClass2 + * nsk.share.jdi.TestInterfaceImplementer1 + * + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./heapwalking001.tests + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/heapwalking001.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/heapwalking001.tests new file mode 100644 index 00000000000..f727d6b2cda --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/heapwalking001.tests @@ -0,0 +1,5 @@ +nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 +nsk.jdi.ObjectReference.referringObjects.referringObjects004.referringObjects004 +nsk.jdi.ReferenceType.instances.instances003.instances003 -testClassNames java.lang.String:nsk.share.jdi.TestClass1:boolean[] +nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 +nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 -forceGC diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java new file mode 100644 index 00000000000..2c6cc6a2121 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018, 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 + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/heapwalking002. + * VM Testbase keywords: [stress, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'heapwalkin002.tests', before execution test list is shuffled and tests are executed + * in random order, resulted test order is saved in file 'run.tests', to reproduce failed test execute it + * with option '-configFile run.tests'(instead of -configFile heapwalking002.tests). + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from heapwalking002.tests + * @build nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 + * nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003a + * nsk.jdi.ObjectReference.referringObjects.referringObjects004.referringObjects004 + * nsk.jdi.ReferenceType.instances.instances003.instances003 + * nsk.share.jdi.TestClass1 + * nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 + * nsk.share.jdi.TestClass1 + * nsk.share.jdi.TestClass2 + * nsk.share.jdi.TestInterfaceImplementer1 + * + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./heapwalking002.tests + * -testWorkDir . + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/heapwalking002.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/heapwalking002.tests new file mode 100644 index 00000000000..066ad40c267 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/heapwalking002.tests @@ -0,0 +1,6 @@ +OPTIONS:shuffle +nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 +nsk.jdi.ObjectReference.referringObjects.referringObjects004.referringObjects004 +nsk.jdi.ReferenceType.instances.instances003.instances003 -testClassNames java.lang.String:nsk.share.jdi.TestClass1:boolean[] +nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 +nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 -forceGC diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java new file mode 100644 index 00000000000..3397778dd12 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/mixed001. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'mixed001.tests' and tests are executed in given order. + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from mixed001.tests + * @build nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 + * nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003a + * nsk.jdi.ReferenceType.instances.instances003.instances003 + * nsk.share.jdi.TestClass1 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004a + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 + * nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 + * nsk.share.jdi.TestClass1 + * nsk.share.jdi.TestClass2 + * nsk.share.jdi.TestInterfaceImplementer1 + * nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./mixed001.tests + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/mixed001.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/mixed001.tests new file mode 100644 index 00000000000..e4c49c96f1f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/mixed001.tests @@ -0,0 +1,15 @@ +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 + +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -eventType MONITOR_WAIT -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -eventType MONITOR_WAITED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + +nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 +nsk.jdi.ReferenceType.instances.instances003.instances003 -testClassNames java.lang.String:nsk.share.jdi.TestClass1:boolean[] +nsk.jdi.VirtualMachine.instanceCounts.instancecounts001.instancecounts001 + +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java new file mode 100644 index 00000000000..192a98dde45 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/mixed002. + * VM Testbase keywords: [stress, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'mixed002.tests', before execution test list is shuffled and tests are executed + * in random order, resulted test order is saved in file 'run.tests', to reproduce failed test execute it + * with option '-configFile run.tests'(instead of -configFile mixed002.tests). + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from mixed002.tests + * @build nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 + * nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003a + * nsk.jdi.ReferenceType.instances.instances003.instances003 + * nsk.share.jdi.TestClass1 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001a + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 + * nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004a + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 + * nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=-Xmx128M ${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./mixed002.tests + * -testWorkDir . + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/mixed002.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/mixed002.tests new file mode 100644 index 00000000000..02eecb9625f --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/mixed002.tests @@ -0,0 +1,15 @@ +OPTIONS:shuffle +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 + +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -eventType MONITOR_WAIT -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -eventType MONITOR_WAITED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee + +nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003 +nsk.jdi.ReferenceType.instances.instances003.instances003 -testClassNames java.lang.String:nsk.share.jdi.TestClass1:boolean[] + +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn003.forceEarlyReturn003 +nsk.jdi.ThreadReference.forceEarlyReturn.forceEarlyReturn004.forceEarlyReturn004 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java new file mode 100644 index 00000000000..f43557b5df4 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/monitorEvents001. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'monitorEvents001.tests' and tests are executed in given order. + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from monitorEvents001.tests + * @build nsk.share.jdi.EventTestTemplates + * + * @build nsk.share.jdi.SerialExecutionDebugger + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./monitorEvents001.tests + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/monitorEvents001.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/monitorEvents001.tests new file mode 100644 index 00000000000..fe54bc37eed --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/monitorEvents001.tests @@ -0,0 +1,10 @@ +nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_*:*Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass +nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_*:*Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass +nsk.share.jdi.EventTestTemplates$ClassFilterTest_ClassName -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_*:*Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass +nsk.share.jdi.EventTestTemplates$ClassFilterTest_ClassName -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_*:*Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass +nsk.share.jdi.EventTestTemplates$ClassFilterTest_ReferenceType -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_1Subclass:nsk.share.jdi.MonitorEnterExecutor_2Subclass +nsk.share.jdi.EventTestTemplates$ClassFilterTest_ReferenceType -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_1Subclass:nsk.share.jdi.MonitorEnterExecutor_2Subclass +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -eventType MONITOR_WAIT -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -eventType MONITOR_WAITED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java new file mode 100644 index 00000000000..0e0283cf5a7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, 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 + * @modules jdk.jdi/com.sun.tools.jdi:+open + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/monitorEvents002. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'monitorEvents002.tests', before execution test list is shuffled and tests are executed + * in random order, resulted test order is saved in file 'run.tests', to reproduce failed test execute it + * with option '-configFile run.tests'(instead of -configFile monitorEvents002.tests). + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from monitorEvents002.tests + * @build nsk.share.jdi.EventTestTemplates + * nsk.share.jdi.JDIEventsDebuggee + * nsk.share.jdi.MonitorEventsDebuggee + * + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./monitorEvents002.tests + * -testWorkDir . + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/monitorEvents002.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/monitorEvents002.tests new file mode 100644 index 00000000000..34d11de48c0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/monitorEvents002.tests @@ -0,0 +1,11 @@ +OPTIONS:shuffle +nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_*:*Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass +nsk.share.jdi.EventTestTemplates$ClassExclusionFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_*:*Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass +nsk.share.jdi.EventTestTemplates$ClassFilterTest_ClassName -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_*:*Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass +nsk.share.jdi.EventTestTemplates$ClassFilterTest_ClassName -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_*:*Subclass:nsk.share.jdi.MonitorEnterExecutor_1Subclass +nsk.share.jdi.EventTestTemplates$ClassFilterTest_ReferenceType -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_1Subclass:nsk.share.jdi.MonitorEnterExecutor_2Subclass +nsk.share.jdi.EventTestTemplates$ClassFilterTest_ReferenceType -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee -classPatterns nsk.share.jdi.MonitorEnterExecutor_1Subclass:nsk.share.jdi.MonitorEnterExecutor_2Subclass +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTERED -eventType MONITOR_CONTENTED_ENTERED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -allowMissedEvents MONITOR_CONTENTED_ENTER -eventType MONITOR_CONTENTED_ENTER -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -eventType MONITOR_WAIT -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee +nsk.share.jdi.EventTestTemplates$ThreadFilterTest -eventType MONITOR_WAITED -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java new file mode 100644 index 00000000000..a3667ec89bb --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/ownedMonitorsAndFrames001. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'ownedMonitorsAndFrames001.tests' and tests are executed in given order. + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from ownedMonitorsAndFrames001.tests + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames003.ownedMonitorsAndFrames003 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004a + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames005.ownedMonitorsAndFrames005 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames006.ownedMonitorsAndFrames006 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007.ownedMonitorsAndFrames007 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009.ownedMonitorsAndFrames009 + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./ownedMonitorsAndFrames001.tests + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.tests new file mode 100644 index 00000000000..3f88f41f4b3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.tests @@ -0,0 +1,8 @@ +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames003.ownedMonitorsAndFrames003 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames005.ownedMonitorsAndFrames005 -expectJNIMonitors +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames006.ownedMonitorsAndFrames006 -testThreadsCount 5 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007.ownedMonitorsAndFrames007 -testThreadsCount 5 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009.ownedMonitorsAndFrames009 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java new file mode 100644 index 00000000000..479c8802f1c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, 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 + * @key stress + * + * @summary converted from VM Testbase nsk/jdi/stress/serial/ownedMonitorsAndFrames002. + * VM Testbase keywords: [stress, quick, jpda, jdi, feature_jdk6_jpda, vm6] + * VM Testbase readme: + * DESCRIPTION + * This test executes one after another several JDI tests in single VM + * (for detailed description see nsk.share.jdi.SerialExecutionDebugger and nsk.share.jdi.SerialExecutionDebuggee). + * Tests to execute are specified in file 'ownedMonitorsAndFrames002.tests', before execution test list is shuffled and tests are executed + * in random order, resulted test order is saved in file 'run.tests', to reproduce failed test execute it + * with option '-configFile run.tests'(instead of -configFile ownedMonitorsAndFrames002.tests). + * Test is treated as FAILED if at least one of executed tests failed. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * + * @comment build classes required for tests from ownedMonitorsAndFrames002.tests + * @build nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames003.ownedMonitorsAndFrames003 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004a + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames005.ownedMonitorsAndFrames005 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames006.ownedMonitorsAndFrames006 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007.ownedMonitorsAndFrames007 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009.ownedMonitorsAndFrames009 + * nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009.ownedMonitorsAndFrames009a + * + * @build nsk.share.jdi.SerialExecutionDebugger + * @run main/othervm/native PropertyResolvingWrapper + * nsk.share.jdi.SerialExecutionDebugger + * -verbose + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * -testClassPath ${test.class.path} + * -configFile ./ownedMonitorsAndFrames002.tests + * -testWorkDir . + */ + diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.tests b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.tests new file mode 100644 index 00000000000..a76b4839ae1 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/ownedMonitorsAndFrames002.tests @@ -0,0 +1,9 @@ +OPTIONS:shuffle +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames001.ownedMonitorsAndFrames001 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames002.ownedMonitorsAndFrames002 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames003.ownedMonitorsAndFrames003 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames004.ownedMonitorsAndFrames004 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames005.ownedMonitorsAndFrames005 -expectJNIMonitors +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames006.ownedMonitorsAndFrames006 -testThreadsCount 5 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames007.ownedMonitorsAndFrames007 -testThreadsCount 5 +nsk.jdi.ThreadReference.ownedMonitorsAndFrames.ownedMonitorsAndFrames009.ownedMonitorsAndFrames009 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/ExtraClassesBuilder.java b/test/hotspot/jtreg/vmTestbase/nsk/share/ExtraClassesBuilder.java new file mode 100644 index 00000000000..162f8fa84c6 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ExtraClassesBuilder.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, 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 nsk.share; + +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.Utils; +import jdk.test.lib.process.ProcessTools; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.stream.Stream; + +public class ExtraClassesBuilder { + public static void main(String[] args) { + String[] javacOpts = Arrays.stream(args) + .takeWhile(s -> s.startsWith("-")) + .toArray(String[]::new); + + Arrays.stream(args) + .dropWhile(s -> s.startsWith("-")) + .forEach(s -> ExtraClassesBuilder.compile(s, javacOpts)); + } + + private static void compile(String name, String[] args) { + Path src = Paths.get(Utils.TEST_SRC) + .resolve(name) + .toAbsolutePath(); + if (Files.notExists(src)) { + throw new Error(src + " doesn't exist"); + } + Path dst = Paths.get("bin") + .resolve(Paths.get(name).getFileName()) + .toAbsolutePath(); + try { + Files.createDirectories(dst); + } catch (IOException e) { + throw new Error("can't create dir " + dst, e); + } + JDKToolLauncher javac = JDKToolLauncher.create("javac") + .addToolArg("-d") + .addToolArg(dst.toString()) + .addToolArg("-cp") + .addToolArg(Utils.TEST_CLASS_PATH); + + for (String arg : args) { + javac.addToolArg(arg); + } + + try (Stream stream = Files.walk(src)) { + stream.map(Path::toAbsolutePath) + .map(Path::toString) + .filter(s -> s.endsWith(".java")) + .forEach(javac::addToolArg); + } catch (IOException e) { + throw new Error("traverse dir " + src, e); + } + + executeTool(javac); + } + + private static void executeTool(JDKToolLauncher tool) { + String[] command = tool.getCommand(); + try { + ProcessTools.executeCommand(command) + .shouldHaveExitValue(0); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable e) { + throw new Error("execution of " + Arrays.toString(command) + " failed", e); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/libMonitorEnterExecutor.c b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/libMonitorEnterExecutor.c new file mode 100644 index 00000000000..db9236055d0 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/libMonitorEnterExecutor.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "nsk_tools.c" +#include "MonitorEnterExecutor.c" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jni/libJNIreferences.c b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/libJNIreferences.c new file mode 100644 index 00000000000..d5bcd73b9c8 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/libJNIreferences.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, 2018, 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. + */ + +#include "JNIreferences.c" +#include "nsk_tools.c" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/NativeMethodsTestThread.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/NativeMethodsTestThread.java new file mode 100644 index 00000000000..c373e023bbf --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/NativeMethodsTestThread.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2007, 2018, 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 nsk.share.jpda; + +import java.net.*; +import nsk.share.*; + +/* + * This thread class executes in loop native methods with different return types + */ +public class NativeMethodsTestThread extends Thread { + + static { + System.loadLibrary("NativeMethodsTestThread"); + } + + native void VoidMethod(String message); + + native boolean BooleanMethod(String message); + + native byte ByteMethod(String message); + + native short ShortMethod(String message); + + native char CharMethod(String message); + + native int IntMethod(String message); + + native long LongMethod(String message); + + native float FloatMethod(String message); + + native double DoubleMethod(String message); + + native Object[] ObjectArrayMethod(String message); + + native String StringMethod(String message); + + native Thread ThreadMethod(String message); + + native ThreadGroup ThreadGroupMethod(String message); + + native Class ClassObjectMethod(String message); + + native ClassLoader ClassLoaderMethod(String message); + + native Object ObjectMethod(String message); + + native Boolean BooleanWrapperMethod(String message); + + native Byte ByteWrapperMethod(String message); + + native Short ShortWrapperMethod(String message); + + native Character CharWrapperMethod(String message); + + native Integer IntWrapperMethod(String message); + + native Long LongWrapperMethod(String message); + + native Float FloatWrapperMethod(String message); + + native Double DoubleWrapperMethod(String message); + + private void log(String message) { + log.display(message); + } + + public static boolean expectedBooleanValue = Boolean.TRUE; + + public static byte expectedByteValue = Byte.MAX_VALUE; + + public static char expectedCharValue = Character.MAX_VALUE; + + public static short expectedShortValue = Short.MAX_VALUE; + + public static int expectedIntValue = Integer.MAX_VALUE; + + public static long expectedLongValue = Long.MAX_VALUE; + + public static float expectedFloatValue = Float.MAX_VALUE; + + public static double expectedDoubleValue = Double.MAX_VALUE; + + public static Object[] expectedObjectArrayValue = new Object[1000]; + + public static Thread expectedThreadValue = new Thread(); + + public static ThreadGroup expectedThreadGroupValue = new ThreadGroup("Expected thread group"); + + public static Class expectedClassObjectValue = NativeMethodsTestThread.class; + + public static ClassLoader expectedClassLoaderValue = new URLClassLoader(new URL[] {}); + + public static String expectedStringValue = "EXPECTED STRING"; + + public static Object expectedObjectValue = new Object(); + + public static Boolean expectedBooleanWrapperValue = new Boolean(Boolean.TRUE); + + public static Byte expectedByteWrapperValue = new Byte(Byte.MAX_VALUE); + + public static Character expectedCharWrapperValue = new Character(Character.MAX_VALUE); + + public static Short expectedShortWrapperValue = new Short(Short.MAX_VALUE); + + public static Integer expectedIntWrapperValue = new Integer(Integer.MAX_VALUE); + + public static Long expectedLongWrapperValue = new Long(Long.MAX_VALUE); + + public static Float expectedFloatWrapperValue = new Float(Float.MAX_VALUE); + + public static Double expectedDoubleWrapperValue = new Double(Double.MAX_VALUE); + + // names of tested types, this names can be used to derive names of tested methods(typeName + 'Method'), + public static String testedTypesNames[] = {"Void", "Boolean", "Byte", "Short", "Char", "Int", "Long", "Float", "Double", "ObjectArray", + "String", "Thread", "ThreadGroup", "ClassObject", "ClassLoader", "Object", "BooleanWrapper", "ByteWrapper", "ShortWrapper", + "CharWrapper", "IntWrapper", "LongWrapper", "FloatWrapper", "DoubleWrapper" }; + + private Log log; + + // is forceEarlyReturn would called for this thread + private boolean isTestThread; + + // how many times call all test methods + private int iterationsNumber = 1; + + // test thread wait on 'startExecutionWicket' in beginning of run() + private Wicket startExecutionWicket = new Wicket(); + + private boolean success = true; + + public NativeMethodsTestThread(Log log, boolean isTestThread, int iterationNumber) { + this.log = log; + this.isTestThread = isTestThread; + + this.iterationsNumber = iterationNumber; + } + + private volatile boolean stopExecution; + + public void stopExecution() { + stopExecution = true; + } + + public void startExecuion() { + startExecutionWicket.unlockAll(); + } + + public void run() { + // first, debuggee VM starts and suspends test threads to let debugger initialize breakpoints + startExecutionWicket.waitFor(); + + int iterationCount = 0; + + // test thread executes test methods 'iterationNumber' times + // non-test thread execute until not interrupted + while ((iterationCount++ < iterationsNumber) || (!isTestThread && !stopExecution)) { + // execute test methods in order given in 'testMethodsNames' array + for (int i = 0; i < testedTypesNames.length; i++) { + executeMethod(testedTypesNames[i] + "Method"); + } + } + + log("Test thread exit"); + } + + // execute test method and check that correct value is returned + private void executeMethod(String methodName) { + String message = Thread.currentThread() + " in " + methodName; + if (methodName.equals("VoidMethod")) { + VoidMethod(message); + } + if (methodName.equals("BooleanMethod")) { + boolean result = BooleanMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ByteMethod")) { + byte result = ByteMethod(message); + + log("Result: " + result); + } + if (methodName.equals("CharMethod")) { + char result = CharMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ShortMethod")) { + short result = ShortMethod(message); + + log("Result: " + result); + } + if (methodName.equals("IntMethod")) { + int result = IntMethod(message); + + log("Result: " + result); + } + if (methodName.equals("LongMethod")) { + long result = LongMethod(message); + + log("Result: " + result); + } + if (methodName.equals("FloatMethod")) { + float result = FloatMethod(message); + + log("Result: " + result); + } + if (methodName.equals("DoubleMethod")) { + double result = DoubleMethod(message); + + log("Result: " + result); + } + if (methodName.equals("StringMethod")) { + String result = StringMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ObjectMethod")) { + Object result = ObjectMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ObjectArrayMethod")) { + Object[] result = ObjectArrayMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ThreadMethod")) { + Thread result = ThreadMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ThreadGroupMethod")) { + ThreadGroup result = ThreadGroupMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ClassObjectMethod")) { + Class result = ClassObjectMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ClassLoaderMethod")) { + ClassLoader result = ClassLoaderMethod(message); + + log("Result: " + result); + } + if (methodName.equals("BooleanWrapperMethod")) { + Boolean result = BooleanWrapperMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ByteWrapperMethod")) { + Byte result = ByteWrapperMethod(message); + + log("Result: " + result); + } + if (methodName.equals("ShortWrapperMethod")) { + Short result = ShortWrapperMethod(message); + + log("Result: " + result); + } + if (methodName.equals("CharWrapperMethod")) { + Character result = CharWrapperMethod(message); + + log("Result: " + result); + } + if (methodName.equals("IntWrapperMethod")) { + Integer result = IntWrapperMethod(message); + + log("Result: " + result); + } + if (methodName.equals("LongWrapperMethod")) { + Long result = LongWrapperMethod(message); + + log("Result: " + result); + } + if (methodName.equals("FloatWrapperMethod")) { + Float result = FloatWrapperMethod(message); + + log("Result: " + result); + } + if (methodName.equals("DoubleWrapperMethod")) { + Double result = DoubleWrapperMethod(message); + + log("Result: " + result); + } + } + + public boolean getSuccess() { + return success; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/libNativeMethodsTestThread.c b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/libNativeMethodsTestThread.c new file mode 100644 index 00000000000..caf6e73f652 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/libNativeMethodsTestThread.c @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2007, 2018, 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. + */ +#include "jni.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JNI_ENV_PTR + +#ifdef __cplusplus +#define JNI_ENV_ARG_2(x, y) y +#define JNI_ENV_ARG_3(x, y, z) y, z +#define JNI_ENV_ARG_4(x, y, z, a) y, z, a +#define JNI_ENV_PTR(x) x +#else +#define JNI_ENV_ARG_2(x,y) x, y +#define JNI_ENV_ARG_3(x, y, z) x, y, z +#define JNI_ENV_ARG_4(x, y, z, a) x, y, z, a +#define JNI_ENV_PTR(x) (*x) +#endif + +#endif + +static void logMessage(JNIEnv *env, jobject thisObject, jstring message) +{ + jclass klass; + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + JNI_ENV_PTR(env)->CallVoidMethod( + JNI_ENV_ARG_4( + env, + thisObject, + JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG_4(env, klass, "log", "(Ljava/lang/String;)V")), + message)); +} + +JNIEXPORT void JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_VoidMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + logMessage(env, thisObject, message); +} + +JNIEXPORT jboolean JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_BooleanMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedBooleanValue", + "Z")); + + return JNI_ENV_PTR(env)->GetStaticBooleanField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jbyte JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ByteMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedByteValue", + "B")); + + return JNI_ENV_PTR(env)->GetStaticByteField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jshort JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ShortMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedShortValue", + "S")); + + return JNI_ENV_PTR(env)->GetStaticShortField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jchar JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_CharMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedCharValue", + "C")); + + return JNI_ENV_PTR(env)->GetStaticCharField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jint JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_IntMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedIntValue", + "I")); + + return JNI_ENV_PTR(env)->GetStaticIntField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jlong JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_LongMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedLongValue", + "J")); + + return JNI_ENV_PTR(env)->GetStaticLongField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jfloat JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_FloatMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedFloatValue", + "F")); + + return JNI_ENV_PTR(env)->GetStaticFloatField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jdouble JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_DoubleMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedDoubleValue", + "D")); + + return JNI_ENV_PTR(env)->GetStaticDoubleField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ObjectArrayMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedObjectArrayValue", + "[Ljava/lang/Object;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_StringMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedStringValue", + "Ljava/lang/String;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ThreadMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedThreadValue", + "Ljava/lang/Thread;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ThreadGroupMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedThreadGroupValue", + "Ljava/lang/ThreadGroup;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ClassObjectMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedClassObjectValue", + "Ljava/lang/Class;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ClassLoaderMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedClassLoaderValue", + "Ljava/lang/ClassLoader;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ObjectMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedObjectValue", + "Ljava/lang/Object;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_BooleanWrapperMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedBooleanWrapperValue", + "Ljava/lang/Boolean;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ByteWrapperMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedByteWrapperValue", + "Ljava/lang/Byte;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_ShortWrapperMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedShortWrapperValue", + "Ljava/lang/Short;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_CharWrapperMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedCharWrapperValue", + "Ljava/lang/Character;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_IntWrapperMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedIntWrapperValue", + "Ljava/lang/Integer;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_LongWrapperMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedLongWrapperValue", + "Ljava/lang/Long;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_FloatWrapperMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedFloatWrapperValue", + "Ljava/lang/Float;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +JNIEXPORT jobject JNICALL +Java_nsk_share_jpda_NativeMethodsTestThread_DoubleWrapperMethod(JNIEnv *env, + jobject thisObject, jstring message) +{ + jclass klass; + jfieldID valueField; + + logMessage(env, thisObject, message); + + klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject)); + + valueField = JNI_ENV_PTR(env)->GetStaticFieldID(JNI_ENV_ARG_4( + env, + klass, + "expectedDoubleWrapperValue", + "Ljava/lang/Double;")); + + return JNI_ENV_PTR(env)->GetStaticObjectField(JNI_ENV_ARG_3(env, klass, valueField)); +} + +#ifdef __cplusplus +} +#endif diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/locks/libJNIMonitorLocker.c b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/libJNIMonitorLocker.c new file mode 100644 index 00000000000..85f46f45307 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/libJNIMonitorLocker.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include "nsk_tools.c" +#include "JNIMonitorLocker.c" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/locks/libLockingThread.c b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/libLockingThread.c new file mode 100644 index 00000000000..0eef28071c3 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/libLockingThread.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, 2018, 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. + */ + +#include "LockingThread.c" +#include "nsk_tools.c" From 42c3c3b5f777e13552c446b7463e3931cb954a21 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Sat, 5 May 2018 09:34:01 -0700 Subject: [PATCH 05/40] 8202599: Mark intermittently failing jshell tests Reviewed-by: rfield --- test/langtools/TEST.groups | 2 ++ .../jdk/jshell/FailOverDirectExecutionControlTest.java | 3 ++- .../jdk/jshell/FailOverExecutionControlDyingLaunchTest.java | 3 ++- .../jdk/jshell/FailOverExecutionControlHangingListenTest.java | 3 ++- .../jdk/jshell/JdiHangingListenExecutionControlTest.java | 3 ++- .../langtools/jdk/jshell/JdiLaunchingExecutionControlTest.java | 3 ++- .../langtools/jdk/jshell/JdiListeningExecutionControlTest.java | 3 ++- .../jdk/jshell/JdiListeningLocalhostExecutionControlTest.java | 3 ++- test/langtools/jdk/jshell/ToolBasicTest.java | 3 ++- test/langtools/jdk/jshell/UserJdiUserRemoteTest.java | 3 ++- 10 files changed, 20 insertions(+), 9 deletions(-) diff --git a/test/langtools/TEST.groups b/test/langtools/TEST.groups index 2c2d9815a57..8c54260ff90 100644 --- a/test/langtools/TEST.groups +++ b/test/langtools/TEST.groups @@ -38,6 +38,7 @@ tier1 = \ -jdk/jshell/ToolBasicTest.java \ -jdk/jshell/ToolLocaleMessageTest.java \ -jdk/jshell/ToolReloadTest.java \ + -jdk/jshell/UserInputTest.java \ -jdk/jshell/UserJdiUserRemoteTest.java # (Almost) no langtools tests are tier 2. @@ -53,6 +54,7 @@ tier2 = \ jdk/jshell/ToolBasicTest.java \ jdk/jshell/ToolLocaleMessageTest.java \ jdk/jshell/ToolReloadTest.java \ + jdk/jshell/UserInputTest.java \ jdk/jshell/UserJdiUserRemoteTest.java # No langtools tests are tier 3 either. diff --git a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java index 918af79c91b..4f6700927a3 100644 --- a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java +++ b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -35,6 +35,7 @@ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask * @build KullaTesting ExecutionControlTestBase Compiler * @run testng FailOverDirectExecutionControlTest + * @key intermittent */ import java.nio.file.Path; diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java index e838252f540..0cc828a01d3 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -29,6 +29,7 @@ * jdk.jshell/jdk.jshell.spi * @build KullaTesting ExecutionControlTestBase DyingRemoteAgent * @run testng FailOverExecutionControlDyingLaunchTest + * @key intermittent */ import org.testng.annotations.Test; diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java index fc40f886c1e..8c0131df288 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -29,6 +29,7 @@ * jdk.jshell/jdk.jshell.spi * @build KullaTesting ExecutionControlTestBase * @run testng FailOverExecutionControlHangingListenTest + * @key intermittent */ import java.net.InetAddress; diff --git a/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java b/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java index d305577a70c..6f1c86b950c 100644 --- a/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java +++ b/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -28,6 +28,7 @@ * @modules jdk.jshell/jdk.jshell jdk.jshell/jdk.jshell.spi jdk.jshell/jdk.jshell.execution * @build HangingRemoteAgent * @run testng JdiHangingListenExecutionControlTest + * @key intermittent */ import org.testng.annotations.Test; diff --git a/test/langtools/jdk/jshell/JdiLaunchingExecutionControlTest.java b/test/langtools/jdk/jshell/JdiLaunchingExecutionControlTest.java index 41cfe6c019c..af9dce89bcf 100644 --- a/test/langtools/jdk/jshell/JdiLaunchingExecutionControlTest.java +++ b/test/langtools/jdk/jshell/JdiLaunchingExecutionControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -28,6 +28,7 @@ * @modules jdk.jshell/jdk.jshell.execution * @build KullaTesting ExecutionControlTestBase * @run testng JdiLaunchingExecutionControlTest + * @key intermittent */ diff --git a/test/langtools/jdk/jshell/JdiListeningExecutionControlTest.java b/test/langtools/jdk/jshell/JdiListeningExecutionControlTest.java index 7003eb7a006..700ec077e34 100644 --- a/test/langtools/jdk/jshell/JdiListeningExecutionControlTest.java +++ b/test/langtools/jdk/jshell/JdiListeningExecutionControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -28,6 +28,7 @@ * @modules jdk.jshell/jdk.jshell.execution * @build KullaTesting ExecutionControlTestBase * @run testng JdiListeningExecutionControlTest + * @key intermittent */ diff --git a/test/langtools/jdk/jshell/JdiListeningLocalhostExecutionControlTest.java b/test/langtools/jdk/jshell/JdiListeningLocalhostExecutionControlTest.java index 14daf2bcd82..241774d639e 100644 --- a/test/langtools/jdk/jshell/JdiListeningLocalhostExecutionControlTest.java +++ b/test/langtools/jdk/jshell/JdiListeningLocalhostExecutionControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -28,6 +28,7 @@ * @modules jdk.jshell/jdk.jshell.execution * @build KullaTesting ExecutionControlTestBase * @run testng JdiListeningLocalhostExecutionControlTest + * @key intermittent */ diff --git a/test/langtools/jdk/jshell/ToolBasicTest.java b/test/langtools/jdk/jshell/ToolBasicTest.java index 0789e399908..2a2a8a93237 100644 --- a/test/langtools/jdk/jshell/ToolBasicTest.java +++ b/test/langtools/jdk/jshell/ToolBasicTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -33,6 +33,7 @@ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask * @build KullaTesting TestingInputStream Compiler * @run testng/timeout=600 ToolBasicTest + * @key intermittent */ import java.io.File; diff --git a/test/langtools/jdk/jshell/UserJdiUserRemoteTest.java b/test/langtools/jdk/jshell/UserJdiUserRemoteTest.java index 56cce3f02ca..02c725cffa4 100644 --- a/test/langtools/jdk/jshell/UserJdiUserRemoteTest.java +++ b/test/langtools/jdk/jshell/UserJdiUserRemoteTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -27,6 +27,7 @@ * @summary Tests for Aux channel, custom remote agents, custom JDI implementations. * @build KullaTesting ExecutionControlTestBase MyExecutionControl MyRemoteExecutionControl MyExecutionControlProvider * @run testng UserJdiUserRemoteTest + * @key intermittent */ import java.io.ByteArrayOutputStream; import org.testng.annotations.Test; From a313d5961a6e73ec4a66e05bf9cee050c449db71 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Sat, 5 May 2018 12:38:15 -0400 Subject: [PATCH 06/40] 8202672: Build failed in metaspace.cpp with VS2017 Add whitespace between string and identifier. Reviewed-by: dcubed, erikj --- src/hotspot/share/memory/metaspace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 1a685b4b807..f400c01e230 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -4131,7 +4131,7 @@ void MetaspaceUtils::print_report(outputStream* out, size_t scale, int flags) { cl._stats_total.class_sm_stats().free_blocks_cap_words(); out->print("Deallocated from chunks in use: "); print_scaled_words_and_percentage(out, free_blocks_cap_words, committed_words, scale, 6); - out->print(" ("UINTX_FORMAT " blocks)", free_blocks_num); + out->print(" (" UINTX_FORMAT " blocks)", free_blocks_num); out->cr(); // Print total waste. From aef2df31e64451c720237b4df598b243597ba37a Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Sat, 5 May 2018 18:55:31 +0200 Subject: [PATCH 07/40] 8202684: Minimal VM build is broken after JDK-8199067, JDK-8202638 Reviewed-by: eosterlund, stuefe --- src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp | 2 +- src/hotspot/share/utilities/macros.hpp | 4 ++++ test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp index babe350e40e..ac556519e4b 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp +++ b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp @@ -70,7 +70,7 @@ void MetaspaceDCmd::execute(DCmdSource source, TRAPS) { if (strcasecmp("dynamic", scale_value) == 0) { scale = 0; } else { - scale = NMTUtil::scale_from_name(scale_value); + scale = NMT_ONLY(NMTUtil::scale_from_name(scale_value)) NOT_NMT(0); if (scale == 0) { output()->print_cr("Invalid scale: \"%s\". Will use dynamic scaling.", scale_value); } diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp index 00e0d511a8f..0d8635a4e1b 100644 --- a/src/hotspot/share/utilities/macros.hpp +++ b/src/hotspot/share/utilities/macros.hpp @@ -218,9 +218,13 @@ #if INCLUDE_NMT #define NOT_NMT_RETURN /* next token must be ; */ #define NOT_NMT_RETURN_(code) /* next token must be ; */ +#define NMT_ONLY(x) x +#define NOT_NMT(x) #else #define NOT_NMT_RETURN {} #define NOT_NMT_RETURN_(code) { return code; } +#define NMT_ONLY(x) +#define NOT_NMT(x) x #endif // INCLUDE_NMT #ifndef INCLUDE_TRACE diff --git a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp index ef9e6e11abc..dd4bdf3bd51 100644 --- a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp +++ b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp @@ -26,6 +26,8 @@ // Included early because the NMT flags don't include it. #include "utilities/macros.hpp" +#if INCLUDE_NMT + #include "runtime/thread.hpp" #include "services/memTracker.hpp" #include "services/virtualMemoryTracker.hpp" @@ -208,3 +210,5 @@ TEST_VM(CommittedVirtualMemoryTracker, test_committed_virtualmemory_region) { CommittedVirtualMemoryTest::test_committed_region(); CommittedVirtualMemoryTest::test_partial_region(); } + +#endif // INCLUDE_NMT From 19f0e3f5d7d9d9a5692f86f4c125a6dd627d2a96 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 3 May 2018 17:10:39 +0200 Subject: [PATCH 08/40] 8202435: [aix] print program break as part of memory info into hs-err file Reviewed-by: mdoerr, dholmes --- src/hotspot/os/aix/os_aix.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index a922568bc31..1f9d43761a6 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -1459,6 +1459,7 @@ void os::print_memory_info(outputStream* st) { const char* const aixthread_guardpages = ::getenv("AIXTHREAD_GUARDPAGES"); st->print_cr(" AIXTHREAD_GUARDPAGES=%s.", aixthread_guardpages ? aixthread_guardpages : ""); + st->cr(); os::Aix::meminfo_t mi; if (os::Aix::get_meminfo(&mi)) { @@ -1481,6 +1482,16 @@ void os::print_memory_info(outputStream* st) { } st->cr(); + // Print program break. + st->print_cr("Program break at VM startup: " PTR_FORMAT ".", p2i(g_brk_at_startup)); + address brk_now = (address)::sbrk(0); + if (brk_now != (address)-1) { + st->print_cr("Program break now : " PTR_FORMAT " (distance: " SIZE_FORMAT "k).", + p2i(brk_now), (size_t)((brk_now - g_brk_at_startup) / K)); + } + st->print_cr("MaxExpectedDataSegmentSize : " SIZE_FORMAT "k.", MaxExpectedDataSegmentSize / K); + st->cr(); + // Print segments allocated with os::reserve_memory. st->print_cr("internal virtual memory regions used by vm:"); vmembk_print_on(st); From e6bccc9d8656b29338b1c9578a0b132e6c56f1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96sterlund?= Date: Sat, 5 May 2018 22:19:19 +0200 Subject: [PATCH 09/40] 8202640: Small C1 cleanups for BarrierSetC1 Reviewed-by: kvn, neliasso --- src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp | 4 +-- src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp | 3 +- src/hotspot/cpu/x86/c1_Runtime1_x86.cpp | 35 +++++++++++-------- .../x86/gc/g1/g1BarrierSetAssembler_x86.cpp | 4 +-- src/hotspot/share/c1/c1_LIR.cpp | 5 ++- src/hotspot/share/c1/c1_LIR.hpp | 3 +- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp b/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp index 57bc7be205d..917b19cf009 100644 --- a/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp +++ b/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp @@ -236,12 +236,12 @@ void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) { #define __ sasm-> static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers = true) { - sasm->save_live_registers_no_oop_map(save_fpu_registers); + __ save_live_registers_no_oop_map(save_fpu_registers); return generate_oop_map(sasm, save_fpu_registers); } static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { - sasm->restore_live_registers(restore_fpu_registers); + __ restore_live_registers(restore_fpu_registers); } diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp index 98bfe88491b..e3254b456fb 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp @@ -123,7 +123,8 @@ void load_parameter(int offset_in_words, Register reg); - void save_live_registers_no_oop_map(int num_rt_args, bool save_fpu_registers); + void save_live_registers_no_oop_map(bool save_fpu_registers); + void restore_live_registers_except_rax(bool restore_fpu_registers); void restore_live_registers(bool restore_fpu_registers); #endif // CPU_X86_VM_C1_MACROASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index 9740ef99ffd..e9c6bcdd58f 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -411,7 +411,7 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args, #define __ this-> -void C1_MacroAssembler::save_live_registers_no_oop_map(int num_rt_args, bool save_fpu_registers) { +void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers) { __ block_comment("save_live_registers"); __ pusha(); // integer registers @@ -551,23 +551,11 @@ void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) { __ popa(); } -#undef __ -#define __ sasm-> -static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args, - bool save_fpu_registers = true) { - sasm->save_live_registers_no_oop_map(num_rt_args, save_fpu_registers); - return generate_oop_map(sasm, num_rt_args, save_fpu_registers); -} - -static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { - sasm->restore_live_registers(restore_fpu_registers); -} - -static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) { +void C1_MacroAssembler::restore_live_registers_except_rax(bool restore_fpu_registers) { __ block_comment("restore_live_registers_except_rax"); - restore_fpu(sasm, restore_fpu_registers); + restore_fpu(this, restore_fpu_registers); #ifdef _LP64 __ movptr(r15, Address(rsp, 0)); @@ -600,6 +588,23 @@ static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_ #endif // _LP64 } +#undef __ +#define __ sasm-> + +static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args, + bool save_fpu_registers = true) { + __ save_live_registers_no_oop_map(save_fpu_registers); + return generate_oop_map(sasm, num_rt_args, save_fpu_registers); +} + +static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { + __ restore_live_registers(restore_fpu_registers); +} + +static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) { + sasm->restore_live_registers_except_rax(restore_fpu_registers); +} + void Runtime1::initialize_pd() { // nothing to do diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp index 1d63e8ec0f8..f4082dbc6d8 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp @@ -496,7 +496,7 @@ void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* __ bind(runtime); - __ save_live_registers_no_oop_map(3, true); + __ save_live_registers_no_oop_map(true); // load the pre-value __ load_parameter(0, rcx); @@ -575,7 +575,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* __ bind(runtime); - __ save_live_registers_no_oop_map(3, true); + __ save_live_registers_no_oop_map(true); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index 924ac78c1c4..3a41eb87f10 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -917,10 +917,13 @@ void LIR_OpVisitState::visit(LIR_Op* op) { break; } default: - ShouldNotReachHere(); + op->visit(this); } } +void LIR_Op::visit(LIR_OpVisitState* state) { + ShouldNotReachHere(); +} void LIR_OpVisitState::do_stub(CodeStub* stub) { if (stub != NULL) { diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp index 980cd4d07dc..ed50932392c 100644 --- a/src/hotspot/share/c1/c1_LIR.hpp +++ b/src/hotspot/share/c1/c1_LIR.hpp @@ -1096,6 +1096,7 @@ class LIR_Op: public CompilationResourceObj { #endif virtual const char * name() const PRODUCT_RETURN0; + virtual void visit(LIR_OpVisitState* state); int id() const { return _id; } void set_id(int id) { _id = id; } @@ -1983,6 +1984,7 @@ class LIR_List: public CompilationResourceObj { int _line; #endif + public: void append(LIR_Op* op) { if (op->source() == NULL) op->set_source(_compilation->current_instruction()); @@ -2003,7 +2005,6 @@ class LIR_List: public CompilationResourceObj { #endif } - public: LIR_List(Compilation* compilation, BlockBegin* block = NULL); #ifdef ASSERT From 97ff2fce38514d344d6f11b53d67099de94f2554 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Sun, 6 May 2018 00:42:59 +0200 Subject: [PATCH 10/40] 8202676: AArch64: Missing enter/leave around barrier leads to infinite loop Reviewed-by: aph, eosterlund --- .../cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp | 3 +++ .../cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp | 3 +++ .../cpu/aarch64/templateInterpreterGenerator_aarch64.cpp | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp index 21ec91db4e5..38ca8938fc4 100644 --- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp @@ -259,6 +259,8 @@ void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorator bool on_reference = on_weak || on_phantom; ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); if (on_oop && on_reference) { + // LR is live. It must be saved around calls. + __ enter(); // barrier may call runtime // Generate the G1 pre-barrier code to log the value of // the referent field in an SATB buffer. g1_write_barrier_pre(masm /* masm */, @@ -268,6 +270,7 @@ void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorator tmp1 /* tmp */, true /* tosca_live */, true /* expand_call */); + __ leave(); } } diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp index 007f5250828..22fcc655571 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp @@ -30,6 +30,9 @@ void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register dst, Address src, Register tmp1, Register tmp_thread) { + + // LR is live. It must be saved around calls. + bool on_heap = (decorators & IN_HEAP) != 0; bool on_root = (decorators & IN_ROOT) != 0; switch (type) { diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index ca594d3db54..cb382edbf85 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -918,6 +918,8 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { // rmethod: Method* // r13: senderSP must preserve for slow path, set SP to it on fast path + // LR is live. It must be saved around calls. + address entry = __ pc(); const int referent_offset = java_lang_ref_Reference::referent_offset; From 20324b99d36e21884f20971c017ea00d78f3126d Mon Sep 17 00:00:00 2001 From: Priya Lakshmi Muthuswamy Date: Mon, 7 May 2018 07:44:49 +0530 Subject: [PATCH 11/40] =?UTF-8?q?8200094:=20Turkish=20locale=20reports=20N?= =?UTF-8?q?PE=20No=20enum=20constant=20com.sun.source.doctree.DocTree.Kind?= =?UTF-8?q?.S=C4=B0NCE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: ksrini, jjg --- .../javadoc/internal/doclets/toolkit/util/Utils.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index 55f62e6b771..84cfb6e00c1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1337,6 +1337,16 @@ public class Utils { } } + /** + * Returns a locale independent upper cased String. That is, it + * always uses US locale, this is a clone of the one in StringUtils. + * @param s to convert + * @return converted String + */ + public static String toUpperCase(String s) { + return s.toUpperCase(Locale.US); + } + /** * Returns a locale independent lower cased String. That is, it * always uses US locale, this is a clone of the one in StringUtils. @@ -2869,7 +2879,7 @@ public class Utils { case "throws": case "exception": case "version": - kind = DocTree.Kind.valueOf(tagName.toUpperCase()); + kind = DocTree.Kind.valueOf(toUpperCase(tagName)); return getBlockTags(element, kind); case "serialData": kind = SERIAL_DATA; From 29b1984560d2e177c2228df64312c2b9985fcae9 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Mon, 7 May 2018 08:56:35 +0200 Subject: [PATCH 12/40] 8202565: C1 compilation crashes with "assert(is_double_stack() && !is_virtual()) failed: type check" Only eagerly resolving the address into a register if the store is precise. Reviewed-by: roland, eosterlund --- src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp index 3eb94314f9c..8db1c70d5ce 100644 --- a/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp @@ -87,6 +87,9 @@ LIR_Opr ModRefBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_r DecoratorSet decorators = access.decorators(); bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0; bool is_write = (decorators & C1_WRITE_ACCESS) != 0; - resolve_in_register |= !needs_patching && is_write && access.is_oop(); + bool on_array = (decorators & IN_HEAP_ARRAY) != 0; + bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0; + bool precise = on_array || on_anonymous; + resolve_in_register |= !needs_patching && is_write && access.is_oop() && precise; return BarrierSetC1::resolve_address(access, resolve_in_register); } From 81bad1fe6bb89f3dbbb553ac7c9a597f8097ec83 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 7 May 2018 10:37:46 +0200 Subject: [PATCH 13/40] 8202387: javac --release 11 not supported Adding historical data for JDK 10; adding ability to produce the historical data incrementally. Reviewed-by: erikj, forax, jjg --- make/data/symbols/java.activation-A.sym.txt | 31 + make/data/symbols/java.base-A.sym.txt | 310 +++++++++ make/data/symbols/java.compiler-A.sym.txt | 115 ++++ make/data/symbols/java.corba-A.sym.txt | 31 + make/data/symbols/java.datatransfer-A.sym.txt | 31 + make/data/symbols/java.desktop-A.sym.txt | 87 +++ make/data/symbols/java.instrument-A.sym.txt | 31 + make/data/symbols/java.logging-A.sym.txt | 31 + make/data/symbols/java.management-A.sym.txt | 40 ++ .../symbols/java.management.rmi-A.sym.txt | 44 ++ make/data/symbols/java.naming-A.sym.txt | 31 + make/data/symbols/java.prefs-A.sym.txt | 31 + make/data/symbols/java.rmi-A.sym.txt | 31 + make/data/symbols/java.scripting-A.sym.txt | 31 + make/data/symbols/java.se-A.sym.txt | 31 + make/data/symbols/java.se.ee-A.sym.txt | 31 + .../data/symbols/java.security.jgss-A.sym.txt | 31 + .../data/symbols/java.security.sasl-A.sym.txt | 31 + make/data/symbols/java.smartcardio-A.sym.txt | 31 + make/data/symbols/java.sql-A.sym.txt | 31 + make/data/symbols/java.sql.rowset-A.sym.txt | 31 + make/data/symbols/java.transaction-A.sym.txt | 31 + make/data/symbols/java.xml-A.sym.txt | 57 ++ make/data/symbols/java.xml.bind-A.sym.txt | 31 + make/data/symbols/java.xml.crypto-A.sym.txt | 31 + make/data/symbols/java.xml.ws-A.sym.txt | 31 + .../symbols/java.xml.ws.annotation-A.sym.txt | 31 + make/data/symbols/jdk.accessibility-A.sym.txt | 31 + make/data/symbols/jdk.attach-A.sym.txt | 31 + make/data/symbols/jdk.charsets-A.sym.txt | 31 + make/data/symbols/jdk.compiler-A.sym.txt | 72 +++ .../symbols/jdk.crypto.cryptoki-A.sym.txt | 31 + make/data/symbols/jdk.crypto.ec-A.sym.txt | 31 + make/data/symbols/jdk.dynalink-A.sym.txt | 34 + make/data/symbols/jdk.editpad-A.sym.txt | 31 + make/data/symbols/jdk.hotspot.agent-A.sym.txt | 31 + make/data/symbols/jdk.httpserver-A.sym.txt | 31 + .../jdk.incubator.httpclient-A.sym.txt | 187 ++++++ make/data/symbols/jdk.jartool-A.sym.txt | 31 + make/data/symbols/jdk.javadoc-A.sym.txt | 35 + make/data/symbols/jdk.jcmd-A.sym.txt | 31 + make/data/symbols/jdk.jconsole-A.sym.txt | 31 + make/data/symbols/jdk.jdeps-A.sym.txt | 31 + make/data/symbols/jdk.jdi-A.sym.txt | 31 + make/data/symbols/jdk.jdwp.agent-A.sym.txt | 31 + make/data/symbols/jdk.jlink-A.sym.txt | 31 + make/data/symbols/jdk.jshell-A.sym.txt | 37 ++ make/data/symbols/jdk.jsobject-A.sym.txt | 31 + make/data/symbols/jdk.jstatd-A.sym.txt | 31 + make/data/symbols/jdk.localedata-A.sym.txt | 31 + make/data/symbols/jdk.management-A.sym.txt | 31 + .../symbols/jdk.management.agent-A.sym.txt | 31 + make/data/symbols/jdk.naming.dns-A.sym.txt | 31 + make/data/symbols/jdk.naming.rmi-A.sym.txt | 31 + make/data/symbols/jdk.net-A.sym.txt | 34 + make/data/symbols/jdk.pack-A.sym.txt | 31 + make/data/symbols/jdk.policytool-A.sym.txt | 30 + make/data/symbols/jdk.rmic-A.sym.txt | 31 + .../symbols/jdk.scripting.nashorn-A.sym.txt | 31 + make/data/symbols/jdk.sctp-A.sym.txt | 31 + make/data/symbols/jdk.security.auth-A.sym.txt | 45 ++ make/data/symbols/jdk.security.jgss-A.sym.txt | 31 + make/data/symbols/jdk.unsupported-A.sym.txt | 39 ++ make/data/symbols/jdk.xml.dom-A.sym.txt | 31 + make/data/symbols/jdk.zipfs-A.sym.txt | 31 + make/data/symbols/symbols | 7 +- make/gendata/Gendata-jdk.compiler.gmk | 7 +- .../tools/symbolgenerator/CreateSymbols.java | 611 ++++++++++++------ .../TransitiveDependencies.java | 64 +- .../options/release/ReleaseOptionCurrent.java | 60 ++ .../javac/preview/PreviewOptionTest.java | 8 +- 71 files changed, 3231 insertions(+), 242 deletions(-) create mode 100644 make/data/symbols/java.activation-A.sym.txt create mode 100644 make/data/symbols/java.base-A.sym.txt create mode 100644 make/data/symbols/java.compiler-A.sym.txt create mode 100644 make/data/symbols/java.corba-A.sym.txt create mode 100644 make/data/symbols/java.datatransfer-A.sym.txt create mode 100644 make/data/symbols/java.desktop-A.sym.txt create mode 100644 make/data/symbols/java.instrument-A.sym.txt create mode 100644 make/data/symbols/java.logging-A.sym.txt create mode 100644 make/data/symbols/java.management-A.sym.txt create mode 100644 make/data/symbols/java.management.rmi-A.sym.txt create mode 100644 make/data/symbols/java.naming-A.sym.txt create mode 100644 make/data/symbols/java.prefs-A.sym.txt create mode 100644 make/data/symbols/java.rmi-A.sym.txt create mode 100644 make/data/symbols/java.scripting-A.sym.txt create mode 100644 make/data/symbols/java.se-A.sym.txt create mode 100644 make/data/symbols/java.se.ee-A.sym.txt create mode 100644 make/data/symbols/java.security.jgss-A.sym.txt create mode 100644 make/data/symbols/java.security.sasl-A.sym.txt create mode 100644 make/data/symbols/java.smartcardio-A.sym.txt create mode 100644 make/data/symbols/java.sql-A.sym.txt create mode 100644 make/data/symbols/java.sql.rowset-A.sym.txt create mode 100644 make/data/symbols/java.transaction-A.sym.txt create mode 100644 make/data/symbols/java.xml-A.sym.txt create mode 100644 make/data/symbols/java.xml.bind-A.sym.txt create mode 100644 make/data/symbols/java.xml.crypto-A.sym.txt create mode 100644 make/data/symbols/java.xml.ws-A.sym.txt create mode 100644 make/data/symbols/java.xml.ws.annotation-A.sym.txt create mode 100644 make/data/symbols/jdk.accessibility-A.sym.txt create mode 100644 make/data/symbols/jdk.attach-A.sym.txt create mode 100644 make/data/symbols/jdk.charsets-A.sym.txt create mode 100644 make/data/symbols/jdk.compiler-A.sym.txt create mode 100644 make/data/symbols/jdk.crypto.cryptoki-A.sym.txt create mode 100644 make/data/symbols/jdk.crypto.ec-A.sym.txt create mode 100644 make/data/symbols/jdk.dynalink-A.sym.txt create mode 100644 make/data/symbols/jdk.editpad-A.sym.txt create mode 100644 make/data/symbols/jdk.hotspot.agent-A.sym.txt create mode 100644 make/data/symbols/jdk.httpserver-A.sym.txt create mode 100644 make/data/symbols/jdk.incubator.httpclient-A.sym.txt create mode 100644 make/data/symbols/jdk.jartool-A.sym.txt create mode 100644 make/data/symbols/jdk.javadoc-A.sym.txt create mode 100644 make/data/symbols/jdk.jcmd-A.sym.txt create mode 100644 make/data/symbols/jdk.jconsole-A.sym.txt create mode 100644 make/data/symbols/jdk.jdeps-A.sym.txt create mode 100644 make/data/symbols/jdk.jdi-A.sym.txt create mode 100644 make/data/symbols/jdk.jdwp.agent-A.sym.txt create mode 100644 make/data/symbols/jdk.jlink-A.sym.txt create mode 100644 make/data/symbols/jdk.jshell-A.sym.txt create mode 100644 make/data/symbols/jdk.jsobject-A.sym.txt create mode 100644 make/data/symbols/jdk.jstatd-A.sym.txt create mode 100644 make/data/symbols/jdk.localedata-A.sym.txt create mode 100644 make/data/symbols/jdk.management-A.sym.txt create mode 100644 make/data/symbols/jdk.management.agent-A.sym.txt create mode 100644 make/data/symbols/jdk.naming.dns-A.sym.txt create mode 100644 make/data/symbols/jdk.naming.rmi-A.sym.txt create mode 100644 make/data/symbols/jdk.net-A.sym.txt create mode 100644 make/data/symbols/jdk.pack-A.sym.txt create mode 100644 make/data/symbols/jdk.policytool-A.sym.txt create mode 100644 make/data/symbols/jdk.rmic-A.sym.txt create mode 100644 make/data/symbols/jdk.scripting.nashorn-A.sym.txt create mode 100644 make/data/symbols/jdk.sctp-A.sym.txt create mode 100644 make/data/symbols/jdk.security.auth-A.sym.txt create mode 100644 make/data/symbols/jdk.security.jgss-A.sym.txt create mode 100644 make/data/symbols/jdk.unsupported-A.sym.txt create mode 100644 make/data/symbols/jdk.xml.dom-A.sym.txt create mode 100644 make/data/symbols/jdk.zipfs-A.sym.txt create mode 100644 test/langtools/tools/javac/options/release/ReleaseOptionCurrent.java diff --git a/make/data/symbols/java.activation-A.sym.txt b/make/data/symbols/java.activation-A.sym.txt new file mode 100644 index 00000000000..23788457096 --- /dev/null +++ b/make/data/symbols/java.activation-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.activation +header exports javax/activation requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;java.datatransfer\u0020;flags\u0020;20 target linux-amd64 flags 8000 runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + diff --git a/make/data/symbols/java.base-A.sym.txt b/make/data/symbols/java.base-A.sym.txt new file mode 100644 index 00000000000..26413c778c1 --- /dev/null +++ b/make/data/symbols/java.base-A.sym.txt @@ -0,0 +1,310 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.base +header exports java/io,java/lang,java/lang/annotation,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/acl,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/security/ssl/ClientKeyExchangeService,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 + +class name java/io/ByteArrayOutputStream +method name toString descriptor (Ljava/nio/charset/Charset;)Ljava/lang/String; flags 21 + +class name java/io/FileInputStream +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/io/IOException flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/io/FileOutputStream +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/io/IOException flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/io/ObjectStreamClass +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/io/PrintStream +method name descriptor (Ljava/io/OutputStream;ZLjava/nio/charset/Charset;)V flags 1 +method name descriptor (Ljava/lang/String;Ljava/nio/charset/Charset;)V thrownTypes java/io/IOException flags 1 +method name descriptor (Ljava/io/File;Ljava/nio/charset/Charset;)V thrownTypes java/io/IOException flags 1 + +class name java/io/PrintWriter +method name descriptor (Ljava/io/OutputStream;ZLjava/nio/charset/Charset;)V flags 1 +method name descriptor (Ljava/lang/String;Ljava/nio/charset/Charset;)V thrownTypes java/io/IOException flags 1 +method name descriptor (Ljava/io/File;Ljava/nio/charset/Charset;)V thrownTypes java/io/IOException flags 1 + +class name java/io/Reader +method name transferTo descriptor (Ljava/io/Writer;)J thrownTypes java/io/IOException flags 1 + +class name java/lang/Math +-method name multiplyHigh descriptor (JJ)J +method name multiplyHigh descriptor (JJ)J flags 9 runtimeAnnotations @Ljdk/internal/HotSpotIntrinsicCandidate; + +class name java/lang/Module +header extends java/lang/Object implements java/lang/reflect/AnnotatedElement flags 31 +innerclass innerClass java/lang/module/ModuleDescriptor$Version outerClass java/lang/module/ModuleDescriptor innerClassName Version flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Exports outerClass java/lang/module/ModuleDescriptor innerClassName Exports flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Opens outerClass java/lang/module/ModuleDescriptor innerClassName Opens flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/Runtime +-method name getLocalizedInputStream descriptor (Ljava/io/InputStream;)Ljava/io/InputStream; +-method name getLocalizedOutputStream descriptor (Ljava/io/OutputStream;)Ljava/io/OutputStream; + +class name java/lang/Runtime$Version +-method name major descriptor ()I +-method name minor descriptor ()I +-method name security descriptor ()I +method name feature descriptor ()I flags 1 +method name interim descriptor ()I flags 1 +method name update descriptor ()I flags 1 +method name patch descriptor ()I flags 1 +method name major descriptor ()I flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="10") +method name minor descriptor ()I flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="10") +method name security descriptor ()I flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="10") + +class name java/lang/SecurityManager +-field name inCheck descriptor Z +-method name getInCheck descriptor ()Z +-method name currentClassLoader descriptor ()Ljava/lang/ClassLoader; +-method name currentLoadedClass descriptor ()Ljava/lang/Class; +-method name classDepth descriptor (Ljava/lang/String;)I +-method name classLoaderDepth descriptor ()I +-method name inClass descriptor (Ljava/lang/String;)Z +-method name inClassLoader descriptor ()Z +-method name checkMemberAccess descriptor (Ljava/lang/Class;I)V +method name checkMemberAccess descriptor (Ljava/lang/Class;I)V flags 1 deprecated true signature (Ljava/lang/Class<*>;I)V runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.8") + +class name java/lang/StackWalker$StackFrame +method name getMethodType descriptor ()Ljava/lang/invoke/MethodType; flags 1 +method name getDescriptor descriptor ()Ljava/lang/String; flags 1 + +class name java/lang/invoke/MethodType +method name lastParameterType descriptor ()Ljava/lang/Class; flags 1 signature ()Ljava/lang/Class<*>; + +class name java/lang/reflect/MalformedParameterizedTypeException +method name descriptor (Ljava/lang/String;)V flags 1 + +class name java/net/URLDecoder +method name decode descriptor (Ljava/lang/String;Ljava/nio/charset/Charset;)Ljava/lang/String; flags 9 + +class name java/net/URLEncoder +method name encode descriptor (Ljava/lang/String;Ljava/nio/charset/Charset;)Ljava/lang/String; flags 9 + +class name java/nio/channels/Channels +method name newReader descriptor (Ljava/nio/channels/ReadableByteChannel;Ljava/nio/charset/Charset;)Ljava/io/Reader; flags 9 +method name newWriter descriptor (Ljava/nio/channels/WritableByteChannel;Ljava/nio/charset/Charset;)Ljava/io/Writer; flags 9 + +class name java/nio/file/FileStore +method name getBlockSize descriptor ()J thrownTypes java/io/IOException flags 1 + +class name java/security/Certificate +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/security/Identity +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 421 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/security/IdentityScope +header extends java/security/Identity flags 421 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/security/Signer +header extends java/security/Identity flags 421 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/security/acl/Acl +header extends java/lang/Object implements java/security/acl/Owner flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/security/acl/AclEntry +header extends java/lang/Object implements java/lang/Cloneable flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/security/acl/AclNotFoundException +header extends java/lang/Exception flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/security/acl/Group +header extends java/lang/Object implements java/security/Principal flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/security/acl/LastOwnerException +header extends java/lang/Exception flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/security/acl/NotOwnerException +header extends java/lang/Exception flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/security/acl/Owner +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/security/acl/Permission +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/time/chrono/AbstractChronology +header extends java/lang/Object implements java/time/chrono/Chronology flags 421 classAnnotations @Ljdk/Profile+Annotation;(value=I1) + +class name java/time/chrono/ChronoLocalDate +header extends java/lang/Object implements java/time/temporal/Temporal,java/time/temporal/TemporalAdjuster,java/lang/Comparable flags 601 signature Ljava/lang/Object;Ljava/time/temporal/Temporal;Ljava/time/temporal/TemporalAdjuster;Ljava/lang/Comparable; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/chrono/ChronoLocalDateTime +header extends java/lang/Object implements java/time/temporal/Temporal,java/time/temporal/TemporalAdjuster,java/lang/Comparable flags 601 signature Ljava/lang/Object;Ljava/time/temporal/Temporal;Ljava/time/temporal/TemporalAdjuster;Ljava/lang/Comparable;>; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/chrono/ChronoZonedDateTime +header extends java/lang/Object implements java/time/temporal/Temporal,java/lang/Comparable flags 601 signature Ljava/lang/Object;Ljava/time/temporal/Temporal;Ljava/lang/Comparable;>; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/chrono/HijrahEra +method name getDisplayName descriptor (Ljava/time/format/TextStyle;Ljava/util/Locale;)Ljava/lang/String; flags 1 + +class name java/time/chrono/MinguoEra +method name getDisplayName descriptor (Ljava/time/format/TextStyle;Ljava/util/Locale;)Ljava/lang/String; flags 1 + +class name java/time/chrono/ThaiBuddhistEra +method name getDisplayName descriptor (Ljava/time/format/TextStyle;Ljava/util/Locale;)Ljava/lang/String; flags 1 + +class name java/time/format/DateTimeFormatter +method name localizedBy descriptor (Ljava/util/Locale;)Ljava/time/format/DateTimeFormatter; flags 1 + +class name java/util/Calendar +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable,java/lang/Comparable flags 421 signature Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Cloneable;Ljava/lang/Comparable; +innerclass innerClass java/util/Calendar$Builder outerClass java/util/Calendar innerClassName Builder flags 9 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/DoubleSummaryStatistics +header extends java/lang/Object implements java/util/function/DoubleConsumer flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name descriptor (JDDD)V thrownTypes java/lang/IllegalArgumentException flags 1 + +class name java/util/Formatter +method name descriptor (Ljava/lang/String;Ljava/nio/charset/Charset;Ljava/util/Locale;)V thrownTypes java/io/IOException flags 1 +method name descriptor (Ljava/io/File;Ljava/nio/charset/Charset;Ljava/util/Locale;)V thrownTypes java/io/IOException flags 1 +method name descriptor (Ljava/io/OutputStream;Ljava/nio/charset/Charset;Ljava/util/Locale;)V flags 1 + +class name java/util/HashSet +header extends java/util/AbstractSet implements java/util/Set,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/AbstractSet;Ljava/util/Set;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/util/IntSummaryStatistics +method name descriptor (JIIJ)V thrownTypes java/lang/IllegalArgumentException flags 1 + +class name java/util/List +method name copyOf descriptor (Ljava/util/Collection;)Ljava/util/List; flags 9 signature (Ljava/util/Collection<+TE;>;)Ljava/util/List; + +class name java/util/Locale +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable flags 31 +innerclass innerClass java/util/Locale$LanguageRange outerClass java/util/Locale innerClassName LanguageRange flags 19 +innerclass innerClass java/util/Locale$FilteringMode outerClass java/util/Locale innerClassName FilteringMode flags 4019 +innerclass innerClass java/util/Locale$Builder outerClass java/util/Locale innerClassName Builder flags 19 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 +innerclass innerClass java/util/Locale$IsoCountryCode outerClass java/util/Locale innerClassName IsoCountryCode flags 4409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/LongSummaryStatistics +method name descriptor (JJJJ)V thrownTypes java/lang/IllegalArgumentException flags 1 + +class name java/util/Map +method name copyOf descriptor (Ljava/util/Map;)Ljava/util/Map; flags 9 signature (Ljava/util/Map<+TK;+TV;>;)Ljava/util/Map; + +class name java/util/Optional +method name orElseThrow descriptor ()Ljava/lang/Object; flags 1 signature ()TT; + +class name java/util/OptionalDouble +method name orElseThrow descriptor ()D flags 1 + +class name java/util/OptionalInt +method name orElseThrow descriptor ()I flags 1 + +class name java/util/OptionalLong +method name orElseThrow descriptor ()J flags 1 + +class name java/util/Properties +method name descriptor (I)V flags 1 +method name storeToXML descriptor (Ljava/io/OutputStream;Ljava/lang/String;Ljava/nio/charset/Charset;)V thrownTypes java/io/IOException flags 1 + +class name java/util/Scanner +method name descriptor (Ljava/io/InputStream;Ljava/nio/charset/Charset;)V flags 1 +method name descriptor (Ljava/io/File;Ljava/nio/charset/Charset;)V thrownTypes java/io/IOException flags 1 +method name descriptor (Ljava/nio/file/Path;Ljava/nio/charset/Charset;)V thrownTypes java/io/IOException flags 1 +method name descriptor (Ljava/nio/channels/ReadableByteChannel;Ljava/nio/charset/Charset;)V flags 1 + +class name java/util/Set +method name copyOf descriptor (Ljava/util/Collection;)Ljava/util/Set; flags 9 signature (Ljava/util/Collection<+TE;>;)Ljava/util/Set; + +class name java/util/SimpleTimeZone +-method name hashCode descriptor ()I +method name hashCode descriptor ()I flags 1 + +class name java/util/SplittableRandom +method name nextBytes descriptor ([B)V flags 1 + +class name java/util/concurrent/ConcurrentSkipListMap +header extends java/util/AbstractMap implements java/util/concurrent/ConcurrentNavigableMap,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/AbstractMap;Ljava/util/concurrent/ConcurrentNavigableMap;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/AbstractMap$SimpleImmutableEntry outerClass java/util/AbstractMap innerClassName SimpleImmutableEntry flags 9 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/FutureTask +method name toString descriptor ()Ljava/lang/String; flags 1 + +class name java/util/concurrent/locks/StampedLock +method name isWriteLockStamp descriptor (J)Z flags 9 +method name isReadLockStamp descriptor (J)Z flags 9 +method name isLockStamp descriptor (J)Z flags 9 +method name isOptimisticReadStamp descriptor (J)Z flags 9 + +class name java/util/jar/JarEntry +method name getRealName descriptor ()Ljava/lang/String; flags 1 + +class name java/util/jar/JarFile +header extends java/util/zip/ZipFile flags 21 +innerclass innerClass java/lang/Runtime$Version outerClass java/lang/Runtime innerClassName Version flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name versionedStream descriptor ()Ljava/util/stream/Stream; flags 1 signature ()Ljava/util/stream/Stream; + +class name java/util/spi/LocaleNameProvider +method name getDisplayUnicodeExtensionKey descriptor (Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String; flags 1 +method name getDisplayUnicodeExtensionType descriptor (Ljava/lang/String;Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String; flags 1 + +class name java/util/stream/Collectors +method name toUnmodifiableList descriptor ()Ljava/util/stream/Collector; flags 9 signature ()Ljava/util/stream/Collector;>; +method name toUnmodifiableSet descriptor ()Ljava/util/stream/Collector; flags 9 signature ()Ljava/util/stream/Collector;>; +method name toUnmodifiableMap descriptor (Ljava/util/function/Function;Ljava/util/function/Function;)Ljava/util/stream/Collector; flags 9 signature (Ljava/util/function/Function<-TT;+TK;>;Ljava/util/function/Function<-TT;+TU;>;)Ljava/util/stream/Collector;>; +method name toUnmodifiableMap descriptor (Ljava/util/function/Function;Ljava/util/function/Function;Ljava/util/function/BinaryOperator;)Ljava/util/stream/Collector; flags 9 signature (Ljava/util/function/Function<-TT;+TK;>;Ljava/util/function/Function<-TT;+TU;>;Ljava/util/function/BinaryOperator;)Ljava/util/stream/Collector;>; + +class name java/util/zip/Deflater +-method name finalize descriptor ()V +method name finalize descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/util/zip/Inflater +-method name finalize descriptor ()V +method name finalize descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/util/zip/ZipFile +header extends java/lang/Object implements java/util/zip/ZipConstants,java/io/Closeable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/io/IOException flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name javax/security/auth/Policy +header extends java/lang/Object flags 421 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.4") + diff --git a/make/data/symbols/java.compiler-A.sym.txt b/make/data/symbols/java.compiler-A.sym.txt new file mode 100644 index 00000000000..2568f48ed3e --- /dev/null +++ b/make/data/symbols/java.compiler-A.sym.txt @@ -0,0 +1,115 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.compiler +header exports javax/annotation/processing,javax/lang/model,javax/lang/model/element,javax/lang/model/type,javax/lang/model/util,javax/tools requires name\u0020;java.base\u0020;flags\u0020;8000 uses javax/tools/DocumentationTool,javax/tools/JavaCompiler target linux-amd64 flags 8000 + +class name javax/lang/model/SourceVersion +field name RELEASE_10 descriptor Ljavax/lang/model/SourceVersion; flags 4019 + +class name javax/lang/model/util/AbstractAnnotationValueVisitor6 +-method name descriptor ()V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name javax/lang/model/util/AbstractAnnotationValueVisitor9 +header extends javax/lang/model/util/AbstractAnnotationValueVisitor8 flags 421 signature Ljavax/lang/model/util/AbstractAnnotationValueVisitor8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) + +class name javax/lang/model/util/AbstractElementVisitor6 +-method name descriptor ()V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name javax/lang/model/util/AbstractElementVisitor9 +header extends javax/lang/model/util/AbstractElementVisitor8 flags 421 signature Ljavax/lang/model/util/AbstractElementVisitor8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) + +class name javax/lang/model/util/AbstractTypeVisitor6 +-method name descriptor ()V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name javax/lang/model/util/AbstractTypeVisitor9 +header extends javax/lang/model/util/AbstractTypeVisitor8 flags 421 signature Ljavax/lang/model/util/AbstractTypeVisitor8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) + +class name javax/lang/model/util/ElementKindVisitor6 +-method name descriptor ()V +-method name descriptor (Ljava/lang/Object;)V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +method name descriptor (Ljava/lang/Object;)V flags 4 deprecated true signature (TR;)V runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name javax/lang/model/util/ElementKindVisitor9 +header extends javax/lang/model/util/ElementKindVisitor8 flags 21 signature Ljavax/lang/model/util/ElementKindVisitor8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) + +class name javax/lang/model/util/ElementScanner6 +-method name descriptor ()V +-method name descriptor (Ljava/lang/Object;)V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +method name descriptor (Ljava/lang/Object;)V flags 4 deprecated true signature (TR;)V runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name javax/lang/model/util/ElementScanner9 +header extends javax/lang/model/util/ElementScanner8 flags 21 signature Ljavax/lang/model/util/ElementScanner8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) + +class name javax/lang/model/util/SimpleAnnotationValueVisitor6 +-method name descriptor ()V +-method name descriptor (Ljava/lang/Object;)V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +method name descriptor (Ljava/lang/Object;)V flags 4 deprecated true signature (TR;)V runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name javax/lang/model/util/SimpleAnnotationValueVisitor9 +header extends javax/lang/model/util/SimpleAnnotationValueVisitor8 flags 21 signature Ljavax/lang/model/util/SimpleAnnotationValueVisitor8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) + +class name javax/lang/model/util/SimpleElementVisitor6 +-method name descriptor ()V +-method name descriptor (Ljava/lang/Object;)V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +method name descriptor (Ljava/lang/Object;)V flags 4 deprecated true signature (TR;)V runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name javax/lang/model/util/SimpleElementVisitor9 +header extends javax/lang/model/util/SimpleElementVisitor8 flags 21 signature Ljavax/lang/model/util/SimpleElementVisitor8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) + +class name javax/lang/model/util/SimpleTypeVisitor6 +-method name descriptor ()V +-method name descriptor (Ljava/lang/Object;)V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +method name descriptor (Ljava/lang/Object;)V flags 4 deprecated true signature (TR;)V runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name javax/lang/model/util/SimpleTypeVisitor9 +header extends javax/lang/model/util/SimpleTypeVisitor8 flags 21 signature Ljavax/lang/model/util/SimpleTypeVisitor8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) + +class name javax/lang/model/util/TypeKindVisitor6 +-method name descriptor ()V +-method name descriptor (Ljava/lang/Object;)V +method name descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +method name descriptor (Ljava/lang/Object;)V flags 4 deprecated true signature (TR;)V runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +method name visitNoTypeAsModule descriptor (Ljavax/lang/model/type/NoType;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Ljavax/lang/model/type/NoType;TP;)TR; + +class name javax/lang/model/util/TypeKindVisitor9 +header extends javax/lang/model/util/TypeKindVisitor8 flags 21 signature Ljavax/lang/model/util/TypeKindVisitor8; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_10;) +method name visitNoTypeAsModule descriptor (Ljavax/lang/model/type/NoType;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Ljavax/lang/model/type/NoType;TP;)TR; + +class name javax/tools/ToolProvider +-method name getSystemToolClassLoader descriptor ()Ljava/lang/ClassLoader; +method name getSystemToolClassLoader descriptor ()Ljava/lang/ClassLoader; flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + diff --git a/make/data/symbols/java.corba-A.sym.txt b/make/data/symbols/java.corba-A.sym.txt new file mode 100644 index 00000000000..017d65008cd --- /dev/null +++ b/make/data/symbols/java.corba-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.corba +header exports javax/activity,javax/rmi,javax/rmi/CORBA,org/omg/CORBA,org/omg/CORBA/DynAnyPackage,org/omg/CORBA/ORBPackage,org/omg/CORBA/TypeCodePackage,org/omg/CORBA/portable,org/omg/CORBA_2_3,org/omg/CORBA_2_3/portable,org/omg/CosNaming,org/omg/CosNaming/NamingContextExtPackage,org/omg/CosNaming/NamingContextPackage,org/omg/Dynamic,org/omg/DynamicAny,org/omg/DynamicAny/DynAnyFactoryPackage,org/omg/DynamicAny/DynAnyPackage,org/omg/IOP,org/omg/IOP/CodecFactoryPackage,org/omg/IOP/CodecPackage,org/omg/Messaging,org/omg/PortableInterceptor,org/omg/PortableInterceptor/ORBInitInfoPackage,org/omg/PortableServer,org/omg/PortableServer/CurrentPackage,org/omg/PortableServer/POAManagerPackage,org/omg/PortableServer/POAPackage,org/omg/PortableServer/ServantLocatorPackage,org/omg/PortableServer/portable,org/omg/SendingContext,org/omg/stub/java/rmi requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;java.naming\u0020;flags\u0020;0,name\u0020;java.transaction\u0020;flags\u0020;0,name\u0020;jdk.unsupported\u0020;flags\u0020;0,name\u0020;java.desktop\u0020;flags\u0020;20,name\u0020;java.rmi\u0020;flags\u0020;20 target linux-amd64 flags 8000 runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + diff --git a/make/data/symbols/java.datatransfer-A.sym.txt b/make/data/symbols/java.datatransfer-A.sym.txt new file mode 100644 index 00000000000..4e4a80ab79e --- /dev/null +++ b/make/data/symbols/java.datatransfer-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.datatransfer +header exports java/awt/datatransfer requires name\u0020;java.base\u0020;flags\u0020;8000 uses sun/datatransfer/DesktopDatatransferService target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.desktop-A.sym.txt b/make/data/symbols/java.desktop-A.sym.txt new file mode 100644 index 00000000000..f3ddc92fb82 --- /dev/null +++ b/make/data/symbols/java.desktop-A.sym.txt @@ -0,0 +1,87 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.desktop +header exports java/applet,java/awt,java/awt/color,java/awt/desktop,java/awt/dnd,java/awt/event,java/awt/font,java/awt/geom,java/awt/im,java/awt/im/spi,java/awt/image,java/awt/image/renderable,java/awt/print,java/beans,java/beans/beancontext,javax/accessibility,javax/imageio,javax/imageio/event,javax/imageio/metadata,javax/imageio/plugins/bmp,javax/imageio/plugins/jpeg,javax/imageio/plugins/tiff,javax/imageio/spi,javax/imageio/stream,javax/print,javax/print/attribute,javax/print/attribute/standard,javax/print/event,javax/sound/midi,javax/sound/midi/spi,javax/sound/sampled,javax/sound/sampled/spi,javax/swing,javax/swing/border,javax/swing/colorchooser,javax/swing/event,javax/swing/filechooser,javax/swing/plaf,javax/swing/plaf/basic,javax/swing/plaf/metal,javax/swing/plaf/multi,javax/swing/plaf/nimbus,javax/swing/plaf/synth,javax/swing/table,javax/swing/text,javax/swing/text/html,javax/swing/text/html/parser,javax/swing/text/rtf,javax/swing/tree,javax/swing/undo requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.prefs\u0020;flags\u0020;0,name\u0020;java.datatransfer\u0020;flags\u0020;20,name\u0020;java.xml\u0020;flags\u0020;20 uses java/awt/im/spi/InputMethodDescriptor,javax/accessibility/AccessibilityProvider,javax/imageio/spi/ImageInputStreamSpi,javax/imageio/spi/ImageOutputStreamSpi,javax/imageio/spi/ImageReaderSpi,javax/imageio/spi/ImageTranscoderSpi,javax/imageio/spi/ImageWriterSpi,javax/print/PrintServiceLookup,javax/print/StreamPrintServiceFactory,javax/sound/midi/spi/MidiDeviceProvider,javax/sound/midi/spi/MidiFileReader,javax/sound/midi/spi/MidiFileWriter,javax/sound/midi/spi/SoundbankReader,javax/sound/sampled/spi/AudioFileReader,javax/sound/sampled/spi/AudioFileWriter,javax/sound/sampled/spi/FormatConversionProvider,javax/sound/sampled/spi/MixerProvider provides interface\u0020;sun/datatransfer/DesktopDatatransferService\u0020;impls\u0020;sun/awt/datatransfer/DesktopDatatransferServiceImpl,interface\u0020;java/net/ContentHandlerFactory\u0020;impls\u0020;sun/awt/www/content/MultimediaContentHandlers,interface\u0020;javax/print/PrintServiceLookup\u0020;impls\u0020;sun/print/PrintServiceLookupProvider,interface\u0020;javax/print/StreamPrintServiceFactory\u0020;impls\u0020;sun/print/PSStreamPrinterFactory,interface\u0020;javax/sound/midi/spi/MidiDeviceProvider\u0020;impls\u0020;com/sun/media/sound/MidiInDeviceProvider\u005C;u002C;com/sun/media/sound/MidiOutDeviceProvider\u005C;u002C;com/sun/media/sound/RealTimeSequencerProvider\u005C;u002C;com/sun/media/sound/SoftProvider,interface\u0020;javax/sound/midi/spi/MidiFileReader\u0020;impls\u0020;com/sun/media/sound/StandardMidiFileReader,interface\u0020;javax/sound/midi/spi/MidiFileWriter\u0020;impls\u0020;com/sun/media/sound/StandardMidiFileWriter,interface\u0020;javax/sound/midi/spi/SoundbankReader\u0020;impls\u0020;com/sun/media/sound/AudioFileSoundbankReader\u005C;u002C;com/sun/media/sound/DLSSoundbankReader\u005C;u002C;com/sun/media/sound/JARSoundbankReader\u005C;u002C;com/sun/media/sound/SF2SoundbankReader,interface\u0020;javax/sound/sampled/spi/AudioFileReader\u0020;impls\u0020;com/sun/media/sound/AiffFileReader\u005C;u002C;com/sun/media/sound/AuFileReader\u005C;u002C;com/sun/media/sound/SoftMidiAudioFileReader\u005C;u002C;com/sun/media/sound/WaveFileReader\u005C;u002C;com/sun/media/sound/WaveFloatFileReader\u005C;u002C;com/sun/media/sound/WaveExtensibleFileReader,interface\u0020;javax/sound/sampled/spi/AudioFileWriter\u0020;impls\u0020;com/sun/media/sound/AiffFileWriter\u005C;u002C;com/sun/media/sound/AuFileWriter\u005C;u002C;com/sun/media/sound/WaveFileWriter\u005C;u002C;com/sun/media/sound/WaveFloatFileWriter,interface\u0020;javax/sound/sampled/spi/FormatConversionProvider\u0020;impls\u0020;com/sun/media/sound/AlawCodec\u005C;u002C;com/sun/media/sound/AudioFloatFormatConverter\u005C;u002C;com/sun/media/sound/PCMtoPCMCodec\u005C;u002C;com/sun/media/sound/UlawCodec,interface\u0020;javax/sound/sampled/spi/MixerProvider\u0020;impls\u0020;com/sun/media/sound/DirectAudioDeviceProvider\u005C;u002C;com/sun/media/sound/PortMixerProvider target linux-amd64 flags 8000 + +class name java/awt/GraphicsEnvironment +-method name getLocalGraphicsEnvironment descriptor ()Ljava/awt/GraphicsEnvironment; +method name getLocalGraphicsEnvironment descriptor ()Ljava/awt/GraphicsEnvironment; flags 9 + +class name java/awt/Toolkit +-method name getMenuShortcutKeyMask descriptor ()I +method name getMenuShortcutKeyMask descriptor ()I thrownTypes java/awt/HeadlessException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="10") +method name getMenuShortcutKeyMaskEx descriptor ()I thrownTypes java/awt/HeadlessException flags 1 + +class name java/awt/geom/Path2D +method name trimToSize descriptor ()V flags 401 + +class name java/awt/geom/Path2D$Double +method name trimToSize descriptor ()V flags 11 + +class name java/awt/geom/Path2D$Float +method name trimToSize descriptor ()V flags 11 + +class name java/awt/image/BufferedImage +-method name setRGB descriptor (III)V +method name setRGB descriptor (III)V flags 1 + +class name java/awt/image/FilteredImageSource +-method name startProduction descriptor (Ljava/awt/image/ImageConsumer;)V +-method name requestTopDownLeftRightResend descriptor (Ljava/awt/image/ImageConsumer;)V +method name startProduction descriptor (Ljava/awt/image/ImageConsumer;)V flags 21 +method name requestTopDownLeftRightResend descriptor (Ljava/awt/image/ImageConsumer;)V flags 21 + +class name javax/swing/ButtonModel +method name getGroup descriptor ()Ljavax/swing/ButtonGroup; flags 1 + +class name javax/swing/LayoutFocusTraversalPolicy +header extends javax/swing/SortingFocusTraversalPolicy implements java/io/Serializable flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I4) + +class name javax/swing/event/EventListenerList +-field name listenerList descriptor [Ljava/lang/Object; +field name listenerList descriptor [Ljava/lang/Object; flags c4 + +class name javax/swing/filechooser/FileSystemView +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/ref/Cleaner$Cleanable outerClass java/lang/ref/Cleaner innerClassName Cleanable flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/basic/BasicMenuUI +method name getMinimumSize descriptor (Ljavax/swing/JComponent;)Ljava/awt/Dimension; flags 1 + +class name javax/swing/text/DefaultCaret +header extends java/awt/Rectangle implements javax/swing/text/Caret,java/awt/event/FocusListener,java/awt/event/MouseListener,java/awt/event/MouseMotionListener flags 21 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass javax/swing/text/NavigationFilter$FilterBypass outerClass javax/swing/text/NavigationFilter innerClassName FilterBypass flags 409 +innerclass innerClass javax/swing/text/Highlighter$HighlightPainter outerClass javax/swing/text/Highlighter innerClassName HighlightPainter flags 609 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass javax/swing/text/LayeredHighlighter$LayerPainter outerClass javax/swing/text/LayeredHighlighter innerClassName LayerPainter flags 409 +innerclass innerClass java/awt/event/FocusEvent$Cause outerClass java/awt/event/FocusEvent innerClassName Cause flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.instrument-A.sym.txt b/make/data/symbols/java.instrument-A.sym.txt new file mode 100644 index 00000000000..d4632bf97b1 --- /dev/null +++ b/make/data/symbols/java.instrument-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.instrument +header exports java/lang/instrument requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.logging-A.sym.txt b/make/data/symbols/java.logging-A.sym.txt new file mode 100644 index 00000000000..4630412f2ab --- /dev/null +++ b/make/data/symbols/java.logging-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.logging +header exports java/util/logging requires name\u0020;java.base\u0020;flags\u0020;8000 provides interface\u0020;jdk/internal/logger/DefaultLoggerFinder\u0020;impls\u0020;sun/util/logging/internal/LoggingProviderImpl target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.management-A.sym.txt b/make/data/symbols/java.management-A.sym.txt new file mode 100644 index 00000000000..98553208154 --- /dev/null +++ b/make/data/symbols/java.management-A.sym.txt @@ -0,0 +1,40 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.management +header exports java/lang/management,javax/management,javax/management/loading,javax/management/modelmbean,javax/management/monitor,javax/management/openmbean,javax/management/relation,javax/management/remote,javax/management/timer requires name\u0020;java.base\u0020;flags\u0020;8000 uses javax/management/remote/JMXConnectorProvider,javax/management/remote/JMXConnectorServerProvider,sun/management/spi/PlatformMBeanProvider provides interface\u0020;javax/security/auth/spi/LoginModule\u0020;impls\u0020;com/sun/jmx/remote/security/FileLoginModule target linux-amd64 flags 8000 + +class name java/lang/management/RuntimeMXBean +header extends java/lang/Object implements java/lang/management/PlatformManagedObject flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name getPid descriptor ()J flags 1 + +class name java/lang/management/ThreadMXBean +method name getThreadInfo descriptor ([JZZI)[Ljava/lang/management/ThreadInfo; flags 1 +method name dumpAllThreads descriptor (ZZI)[Ljava/lang/management/ThreadInfo; flags 1 + diff --git a/make/data/symbols/java.management.rmi-A.sym.txt b/make/data/symbols/java.management.rmi-A.sym.txt new file mode 100644 index 00000000000..934360d4682 --- /dev/null +++ b/make/data/symbols/java.management.rmi-A.sym.txt @@ -0,0 +1,44 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.management.rmi +header exports javax/management/remote/rmi requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.naming\u0020;flags\u0020;0,name\u0020;java.management\u0020;flags\u0020;20,name\u0020;java.rmi\u0020;flags\u0020;20 provides interface\u0020;javax/management/remote/JMXConnectorProvider\u0020;impls\u0020;com/sun/jmx/remote/protocol/rmi/ClientProvider,interface\u0020;javax/management/remote/JMXConnectorServerProvider\u0020;impls\u0020;com/sun/jmx/remote/protocol/rmi/ServerProvider target linux-amd64 flags 8000 + +class name javax/management/remote/rmi/RMIConnectorServer +-field name CREDENTIAL_TYPES descriptor Ljava/lang/String; +field name CREDENTIAL_TYPES descriptor Ljava/lang/String; constantValue jmx.remote.rmi.server.credential.types flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="10") +field name CREDENTIALS_FILTER_PATTERN descriptor Ljava/lang/String; constantValue jmx.remote.rmi.server.credentials.filter.pattern flags 19 +field name SERIAL_FILTER_PATTERN descriptor Ljava/lang/String; constantValue jmx.remote.rmi.server.serial.filter.pattern flags 19 + +class name javax/management/remote/rmi/RMIJRMPServerImpl +header extends javax/management/remote/rmi/RMIServerImpl flags 21 +innerclass innerClass java/io/ObjectInputFilter$FilterInfo outerClass java/io/ObjectInputFilter innerClassName FilterInfo flags 609 +innerclass innerClass java/io/ObjectInputFilter$Status outerClass java/io/ObjectInputFilter innerClassName Status flags 4019 +innerclass innerClass java/io/ObjectInputFilter$Config outerClass java/io/ObjectInputFilter innerClassName Config flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.naming-A.sym.txt b/make/data/symbols/java.naming-A.sym.txt new file mode 100644 index 00000000000..3d9b497bf39 --- /dev/null +++ b/make/data/symbols/java.naming-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.naming +header exports javax/naming,javax/naming/directory,javax/naming/event,javax/naming/ldap,javax/naming/spi requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.security.sasl\u0020;flags\u0020;0 uses javax/naming/ldap/StartTlsResponse,javax/naming/spi/InitialContextFactory provides interface\u0020;java/security/Provider\u0020;impls\u0020;sun/security/provider/certpath/ldap/JdkLDAP target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.prefs-A.sym.txt b/make/data/symbols/java.prefs-A.sym.txt new file mode 100644 index 00000000000..1458a51bdc8 --- /dev/null +++ b/make/data/symbols/java.prefs-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.prefs +header exports java/util/prefs requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.xml\u0020;flags\u0020;0 uses java/util/prefs/PreferencesFactory target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.rmi-A.sym.txt b/make/data/symbols/java.rmi-A.sym.txt new file mode 100644 index 00000000000..020d49ad22b --- /dev/null +++ b/make/data/symbols/java.rmi-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.rmi +header exports java/rmi,java/rmi/activation,java/rmi/dgc,java/rmi/registry,java/rmi/server,javax/rmi/ssl requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0 uses java/rmi/server/RMIClassLoaderSpi target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.scripting-A.sym.txt b/make/data/symbols/java.scripting-A.sym.txt new file mode 100644 index 00000000000..ab88ff08528 --- /dev/null +++ b/make/data/symbols/java.scripting-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.scripting +header exports javax/script requires name\u0020;java.base\u0020;flags\u0020;8000 uses javax/script/ScriptEngineFactory target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.se-A.sym.txt b/make/data/symbols/java.se-A.sym.txt new file mode 100644 index 00000000000..b1d66e24133 --- /dev/null +++ b/make/data/symbols/java.se-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.se +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.compiler\u0020;flags\u0020;20,name\u0020;java.datatransfer\u0020;flags\u0020;20,name\u0020;java.desktop\u0020;flags\u0020;20,name\u0020;java.instrument\u0020;flags\u0020;20,name\u0020;java.logging\u0020;flags\u0020;20,name\u0020;java.management\u0020;flags\u0020;20,name\u0020;java.management.rmi\u0020;flags\u0020;20,name\u0020;java.naming\u0020;flags\u0020;20,name\u0020;java.prefs\u0020;flags\u0020;20,name\u0020;java.rmi\u0020;flags\u0020;20,name\u0020;java.scripting\u0020;flags\u0020;20,name\u0020;java.security.jgss\u0020;flags\u0020;20,name\u0020;java.security.sasl\u0020;flags\u0020;20,name\u0020;java.sql\u0020;flags\u0020;20,name\u0020;java.sql.rowset\u0020;flags\u0020;20,name\u0020;java.xml\u0020;flags\u0020;20,name\u0020;java.xml.crypto\u0020;flags\u0020;20 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.se.ee-A.sym.txt b/make/data/symbols/java.se.ee-A.sym.txt new file mode 100644 index 00000000000..d254af95f74 --- /dev/null +++ b/make/data/symbols/java.se.ee-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.se.ee +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.se\u0020;flags\u0020;20,name\u0020;java.activation\u0020;flags\u0020;20,name\u0020;java.corba\u0020;flags\u0020;20,name\u0020;java.transaction\u0020;flags\u0020;20,name\u0020;java.xml.bind\u0020;flags\u0020;20,name\u0020;java.xml.ws\u0020;flags\u0020;20,name\u0020;java.xml.ws.annotation\u0020;flags\u0020;20 target linux-amd64 flags 8000 runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + diff --git a/make/data/symbols/java.security.jgss-A.sym.txt b/make/data/symbols/java.security.jgss-A.sym.txt new file mode 100644 index 00000000000..0f98da5f237 --- /dev/null +++ b/make/data/symbols/java.security.jgss-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.security.jgss +header exports javax/security/auth/kerberos,org/ietf/jgss requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.naming\u0020;flags\u0020;0 provides interface\u0020;java/security/Provider\u0020;impls\u0020;sun/security/jgss/SunProvider,interface\u0020;sun/security/ssl/ClientKeyExchangeService\u0020;impls\u0020;sun/security/krb5/internal/ssl/Krb5KeyExchangeService target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.security.sasl-A.sym.txt b/make/data/symbols/java.security.sasl-A.sym.txt new file mode 100644 index 00000000000..3f0104ef545 --- /dev/null +++ b/make/data/symbols/java.security.sasl-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.security.sasl +header exports javax/security/sasl requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0 provides interface\u0020;java/security/Provider\u0020;impls\u0020;com/sun/security/sasl/Provider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.smartcardio-A.sym.txt b/make/data/symbols/java.smartcardio-A.sym.txt new file mode 100644 index 00000000000..f874525553c --- /dev/null +++ b/make/data/symbols/java.smartcardio-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.smartcardio +header exports javax/smartcardio requires name\u0020;java.base\u0020;flags\u0020;8000 provides interface\u0020;java/security/Provider\u0020;impls\u0020;sun/security/smartcardio/SunPCSC target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.sql-A.sym.txt b/make/data/symbols/java.sql-A.sym.txt new file mode 100644 index 00000000000..e86c26be5ba --- /dev/null +++ b/make/data/symbols/java.sql-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.sql +header exports java/sql,javax/sql,javax/transaction/xa requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;20,name\u0020;java.xml\u0020;flags\u0020;20 uses java/sql/Driver target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.sql.rowset-A.sym.txt b/make/data/symbols/java.sql.rowset-A.sym.txt new file mode 100644 index 00000000000..1f2eaefafab --- /dev/null +++ b/make/data/symbols/java.sql.rowset-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.sql.rowset +header exports javax/sql/rowset,javax/sql/rowset/serial,javax/sql/rowset/spi requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;20,name\u0020;java.naming\u0020;flags\u0020;20,name\u0020;java.sql\u0020;flags\u0020;20 uses javax/sql/rowset/RowSetFactory target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.transaction-A.sym.txt b/make/data/symbols/java.transaction-A.sym.txt new file mode 100644 index 00000000000..eb5cfa6337c --- /dev/null +++ b/make/data/symbols/java.transaction-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.transaction +header exports javax/transaction requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.rmi\u0020;flags\u0020;20 target linux-amd64 flags 8000 runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + diff --git a/make/data/symbols/java.xml-A.sym.txt b/make/data/symbols/java.xml-A.sym.txt new file mode 100644 index 00000000000..2f37f86e9a7 --- /dev/null +++ b/make/data/symbols/java.xml-A.sym.txt @@ -0,0 +1,57 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.xml +header exports javax/xml,javax/xml/catalog,javax/xml/datatype,javax/xml/namespace,javax/xml/parsers,javax/xml/stream,javax/xml/stream/events,javax/xml/stream/util,javax/xml/transform,javax/xml/transform/dom,javax/xml/transform/sax,javax/xml/transform/stax,javax/xml/transform/stream,javax/xml/validation,javax/xml/xpath,org/w3c/dom,org/w3c/dom/bootstrap,org/w3c/dom/events,org/w3c/dom/ls,org/w3c/dom/ranges,org/w3c/dom/traversal,org/w3c/dom/views,org/xml/sax,org/xml/sax/ext,org/xml/sax/helpers requires name\u0020;java.base\u0020;flags\u0020;8000 uses javax/xml/datatype/DatatypeFactory,javax/xml/parsers/DocumentBuilderFactory,javax/xml/parsers/SAXParserFactory,javax/xml/stream/XMLEventFactory,javax/xml/stream/XMLInputFactory,javax/xml/stream/XMLOutputFactory,javax/xml/transform/TransformerFactory,javax/xml/validation/SchemaFactory,javax/xml/xpath/XPathFactory,org/xml/sax/XMLReader target linux-amd64 flags 8000 + +class name javax/xml/namespace/NamespaceContext +-method name getPrefixes descriptor (Ljava/lang/String;)Ljava/util/Iterator; +method name getPrefixes descriptor (Ljava/lang/String;)Ljava/util/Iterator; flags 401 signature (Ljava/lang/String;)Ljava/util/Iterator; + +class name javax/xml/stream/XMLInputFactory +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 +-method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; + +class name javax/xml/xpath/XPathFunction +-method name evaluate descriptor (Ljava/util/List;)Ljava/lang/Object; +method name evaluate descriptor (Ljava/util/List;)Ljava/lang/Object; thrownTypes javax/xml/xpath/XPathFunctionException flags 401 signature (Ljava/util/List<*>;)Ljava/lang/Object; + +class name org/xml/sax/HandlerBase +header extends java/lang/Object implements org/xml/sax/EntityResolver,org/xml/sax/DTDHandler,org/xml/sax/DocumentHandler,org/xml/sax/ErrorHandler flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/helpers/AttributeListImpl +header extends java/lang/Object implements org/xml/sax/AttributeList flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/helpers/NamespaceSupport +-method name getPrefixes descriptor ()Ljava/util/Enumeration; +-method name getPrefixes descriptor (Ljava/lang/String;)Ljava/util/Enumeration; +-method name getDeclaredPrefixes descriptor ()Ljava/util/Enumeration; +method name getPrefixes descriptor ()Ljava/util/Enumeration; flags 1 signature ()Ljava/util/Enumeration; +method name getPrefixes descriptor (Ljava/lang/String;)Ljava/util/Enumeration; flags 1 signature (Ljava/lang/String;)Ljava/util/Enumeration; +method name getDeclaredPrefixes descriptor ()Ljava/util/Enumeration; flags 1 signature ()Ljava/util/Enumeration; + diff --git a/make/data/symbols/java.xml.bind-A.sym.txt b/make/data/symbols/java.xml.bind-A.sym.txt new file mode 100644 index 00000000000..4c63a0f0988 --- /dev/null +++ b/make/data/symbols/java.xml.bind-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.xml.bind +header exports javax/xml/bind,javax/xml/bind/annotation,javax/xml/bind/annotation/adapters,javax/xml/bind/attachment,javax/xml/bind/helpers,javax/xml/bind/util requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.compiler\u0020;flags\u0020;0,name\u0020;java.desktop\u0020;flags\u0020;0,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;jdk.unsupported\u0020;flags\u0020;0,name\u0020;java.activation\u0020;flags\u0020;20,name\u0020;java.xml\u0020;flags\u0020;20 uses javax/xml/bind/JAXBContextFactory target linux-amd64 flags 8000 runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + diff --git a/make/data/symbols/java.xml.crypto-A.sym.txt b/make/data/symbols/java.xml.crypto-A.sym.txt new file mode 100644 index 00000000000..c72735a2545 --- /dev/null +++ b/make/data/symbols/java.xml.crypto-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.xml.crypto +header exports javax/xml/crypto,javax/xml/crypto/dom,javax/xml/crypto/dsig,javax/xml/crypto/dsig/dom,javax/xml/crypto/dsig/keyinfo,javax/xml/crypto/dsig/spec requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;java.xml\u0020;flags\u0020;20 provides interface\u0020;java/security/Provider\u0020;impls\u0020;org/jcp/xml/dsig/internal/dom/XMLDSigRI target linux-amd64 flags 8000 + diff --git a/make/data/symbols/java.xml.ws-A.sym.txt b/make/data/symbols/java.xml.ws-A.sym.txt new file mode 100644 index 00000000000..3aa58588dbb --- /dev/null +++ b/make/data/symbols/java.xml.ws-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.xml.ws +header exports javax/jws,javax/jws/soap,javax/xml/soap,javax/xml/ws,javax/xml/ws/handler,javax/xml/ws/handler/soap,javax/xml/ws/http,javax/xml/ws/soap,javax/xml/ws/spi,javax/xml/ws/spi/http,javax/xml/ws/wsaddressing requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.desktop\u0020;flags\u0020;0,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;java.management\u0020;flags\u0020;0,name\u0020;java.xml.ws.annotation\u0020;flags\u0020;0,name\u0020;jdk.httpserver\u0020;flags\u0020;0,name\u0020;jdk.unsupported\u0020;flags\u0020;0,name\u0020;java.activation\u0020;flags\u0020;20,name\u0020;java.xml\u0020;flags\u0020;20,name\u0020;java.xml.bind\u0020;flags\u0020;20 uses javax/xml/ws/spi/Provider,javax/xml/soap/MessageFactory,javax/xml/soap/SAAJMetaFactory,javax/xml/soap/SOAPConnectionFactory,javax/xml/soap/SOAPFactory target linux-amd64 flags 8000 runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + diff --git a/make/data/symbols/java.xml.ws.annotation-A.sym.txt b/make/data/symbols/java.xml.ws.annotation-A.sym.txt new file mode 100644 index 00000000000..ecd8247822b --- /dev/null +++ b/make/data/symbols/java.xml.ws.annotation-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.xml.ws.annotation +header exports javax/annotation requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + diff --git a/make/data/symbols/jdk.accessibility-A.sym.txt b/make/data/symbols/jdk.accessibility-A.sym.txt new file mode 100644 index 00000000000..4cc17606819 --- /dev/null +++ b/make/data/symbols/jdk.accessibility-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.accessibility +header exports com/sun/java/accessibility/util requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.desktop\u0020;flags\u0020;20 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.attach-A.sym.txt b/make/data/symbols/jdk.attach-A.sym.txt new file mode 100644 index 00000000000..a05c4a71095 --- /dev/null +++ b/make/data/symbols/jdk.attach-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.attach +header exports com/sun/tools/attach,com/sun/tools/attach/spi requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.internal.jvmstat\u0020;flags\u0020;0 uses com/sun/tools/attach/spi/AttachProvider provides interface\u0020;com/sun/tools/attach/spi/AttachProvider\u0020;impls\u0020;sun/tools/attach/AttachProviderImpl target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.charsets-A.sym.txt b/make/data/symbols/jdk.charsets-A.sym.txt new file mode 100644 index 00000000000..4c5ddb1bc1e --- /dev/null +++ b/make/data/symbols/jdk.charsets-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.charsets +header requires name\u0020;java.base\u0020;flags\u0020;8000 provides interface\u0020;java/nio/charset/spi/CharsetProvider\u0020;impls\u0020;sun/nio/cs/ext/ExtendedCharsets target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.compiler-A.sym.txt b/make/data/symbols/jdk.compiler-A.sym.txt new file mode 100644 index 00000000000..718fbc2384e --- /dev/null +++ b/make/data/symbols/jdk.compiler-A.sym.txt @@ -0,0 +1,72 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.compiler +header exports com/sun/source/doctree,com/sun/source/tree,com/sun/source/util,com/sun/tools/javac requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.compiler\u0020;flags\u0020;20 uses javax/annotation/processing/Processor,com/sun/source/util/Plugin,com/sun/tools/javac/platform/PlatformProvider provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;com/sun/tools/javac/main/JavacToolProvider,interface\u0020;com/sun/tools/javac/platform/PlatformProvider\u0020;impls\u0020;com/sun/tools/javac/platform/JDKPlatformProvider,interface\u0020;javax/tools/JavaCompiler\u0020;impls\u0020;com/sun/tools/javac/api/JavacTool,interface\u0020;javax/tools/Tool\u0020;impls\u0020;com/sun/tools/javac/api/JavacTool target linux-amd64 flags 8000 + +class name com/sun/source/doctree/DocCommentTree +method name getPreamble descriptor ()Ljava/util/List; flags 1 signature ()Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>; +method name getPostamble descriptor ()Ljava/util/List; flags 1 signature ()Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>; + +class name com/sun/source/doctree/DocTree$Kind +field name DOC_TYPE descriptor Lcom/sun/source/doctree/DocTree$Kind; flags 4019 +field name SUMMARY descriptor Lcom/sun/source/doctree/DocTree$Kind; flags 4019 + +class name com/sun/source/doctree/DocTreeVisitor +-method name visitHidden descriptor (Lcom/sun/source/doctree/HiddenTree;Ljava/lang/Object;)Ljava/lang/Object; +-method name visitIndex descriptor (Lcom/sun/source/doctree/IndexTree;Ljava/lang/Object;)Ljava/lang/Object; +-method name visitProvides descriptor (Lcom/sun/source/doctree/ProvidesTree;Ljava/lang/Object;)Ljava/lang/Object; +-method name visitUses descriptor (Lcom/sun/source/doctree/UsesTree;Ljava/lang/Object;)Ljava/lang/Object; +method name visitDocType descriptor (Lcom/sun/source/doctree/DocTypeTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/DocTypeTree;TP;)TR; +method name visitHidden descriptor (Lcom/sun/source/doctree/HiddenTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/HiddenTree;TP;)TR; +method name visitIndex descriptor (Lcom/sun/source/doctree/IndexTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/IndexTree;TP;)TR; +method name visitProvides descriptor (Lcom/sun/source/doctree/ProvidesTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/ProvidesTree;TP;)TR; +method name visitSummary descriptor (Lcom/sun/source/doctree/SummaryTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SummaryTree;TP;)TR; +method name visitUses descriptor (Lcom/sun/source/doctree/UsesTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/UsesTree;TP;)TR; + +class name com/sun/source/doctree/DocTypeTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 +method name getText descriptor ()Ljava/lang/String; flags 401 + +class name com/sun/source/doctree/SummaryTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 +method name getSummary descriptor ()Ljava/util/List; flags 401 signature ()Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>; + +class name com/sun/source/util/DocTreeFactory +method name newDocCommentTree descriptor (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;)Lcom/sun/source/doctree/DocCommentTree; flags 401 signature (Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>;Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>;Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>;Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>;)Lcom/sun/source/doctree/DocCommentTree; +method name newDocTypeTree descriptor (Ljava/lang/String;)Lcom/sun/source/doctree/DocTypeTree; flags 401 +method name newSummaryTree descriptor (Ljava/util/List;)Lcom/sun/source/doctree/SummaryTree; flags 1 signature (Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>;)Lcom/sun/source/doctree/SummaryTree; + +class name com/sun/source/util/DocTreeScanner +method name visitDocType descriptor (Lcom/sun/source/doctree/DocTypeTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/DocTypeTree;TP;)TR; +method name visitSummary descriptor (Lcom/sun/source/doctree/SummaryTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SummaryTree;TP;)TR; + +class name com/sun/source/util/SimpleDocTreeVisitor +method name visitDocType descriptor (Lcom/sun/source/doctree/DocTypeTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/DocTypeTree;TP;)TR; +method name visitSummary descriptor (Lcom/sun/source/doctree/SummaryTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SummaryTree;TP;)TR; + diff --git a/make/data/symbols/jdk.crypto.cryptoki-A.sym.txt b/make/data/symbols/jdk.crypto.cryptoki-A.sym.txt new file mode 100644 index 00000000000..c0f4206d660 --- /dev/null +++ b/make/data/symbols/jdk.crypto.cryptoki-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.crypto.cryptoki +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.crypto.ec\u0020;flags\u0020;0 provides interface\u0020;java/security/Provider\u0020;impls\u0020;sun/security/pkcs11/SunPKCS11 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.crypto.ec-A.sym.txt b/make/data/symbols/jdk.crypto.ec-A.sym.txt new file mode 100644 index 00000000000..2cc8a1b3219 --- /dev/null +++ b/make/data/symbols/jdk.crypto.ec-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.crypto.ec +header requires name\u0020;java.base\u0020;flags\u0020;8000 provides interface\u0020;java/security/Provider\u0020;impls\u0020;sun/security/ec/SunEC target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.dynalink-A.sym.txt b/make/data/symbols/jdk.dynalink-A.sym.txt new file mode 100644 index 00000000000..4c00e6c3b38 --- /dev/null +++ b/make/data/symbols/jdk.dynalink-A.sym.txt @@ -0,0 +1,34 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.dynalink +header exports jdk/dynalink,jdk/dynalink/beans,jdk/dynalink/linker,jdk/dynalink/linker/support,jdk/dynalink/support requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0 uses jdk/dynalink/linker/GuardingDynamicLinkerExporter target linux-amd64 flags 8000 + +class name jdk/dynalink/StandardOperation +field name REMOVE descriptor Ljdk/dynalink/StandardOperation; flags 4019 + diff --git a/make/data/symbols/jdk.editpad-A.sym.txt b/make/data/symbols/jdk.editpad-A.sym.txt new file mode 100644 index 00000000000..ebad01694f4 --- /dev/null +++ b/make/data/symbols/jdk.editpad-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.editpad +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.desktop\u0020;flags\u0020;0,name\u0020;jdk.internal.ed\u0020;flags\u0020;0 provides interface\u0020;jdk/internal/editor/spi/BuildInEditorProvider\u0020;impls\u0020;jdk/editpad/EditPadProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.hotspot.agent-A.sym.txt b/make/data/symbols/jdk.hotspot.agent-A.sym.txt new file mode 100644 index 00000000000..6831c83bad0 --- /dev/null +++ b/make/data/symbols/jdk.hotspot.agent-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.hotspot.agent +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.datatransfer\u0020;flags\u0020;0,name\u0020;java.desktop\u0020;flags\u0020;0,name\u0020;java.rmi\u0020;flags\u0020;0,name\u0020;java.scripting\u0020;flags\u0020;0 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.httpserver-A.sym.txt b/make/data/symbols/jdk.httpserver-A.sym.txt new file mode 100644 index 00000000000..e4c90d63b03 --- /dev/null +++ b/make/data/symbols/jdk.httpserver-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.httpserver +header exports com/sun/net/httpserver,com/sun/net/httpserver/spi requires name\u0020;java.base\u0020;flags\u0020;8000 uses com/sun/net/httpserver/spi/HttpServerProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.incubator.httpclient-A.sym.txt b/make/data/symbols/jdk.incubator.httpclient-A.sym.txt new file mode 100644 index 00000000000..40c2b23e6fa --- /dev/null +++ b/make/data/symbols/jdk.incubator.httpclient-A.sym.txt @@ -0,0 +1,187 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.incubator.httpclient +header exports jdk/incubator/http requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 resolution 9 flags 8000 + +class name jdk/incubator/http/HttpClient +header extends java/lang/Object flags 421 +innerclass innerClass jdk/incubator/http/HttpClient$Redirect outerClass jdk/incubator/http/HttpClient innerClassName Redirect flags 4019 +innerclass innerClass jdk/incubator/http/HttpClient$Version outerClass jdk/incubator/http/HttpClient innerClassName Version flags 4019 +innerclass innerClass jdk/incubator/http/HttpClient$Builder outerClass jdk/incubator/http/HttpClient innerClassName Builder flags 409 +innerclass innerClass jdk/incubator/http/HttpResponse$BodyHandler outerClass jdk/incubator/http/HttpResponse innerClassName BodyHandler flags 609 +innerclass innerClass jdk/incubator/http/HttpResponse$MultiSubscriber outerClass jdk/incubator/http/HttpResponse innerClassName MultiSubscriber flags 609 +innerclass innerClass jdk/incubator/http/WebSocket$Builder outerClass jdk/incubator/http/WebSocket innerClassName Builder flags 609 +-method name cookieManager descriptor ()Ljava/util/Optional; +-method name sslParameters descriptor ()Ljava/util/Optional; +-method name executor descriptor ()Ljava/util/concurrent/Executor; +-method name sendAsync descriptor (Ljdk/incubator/http/HttpRequest;Ljdk/incubator/http/HttpResponse$MultiProcessor;)Ljava/util/concurrent/CompletableFuture; +-method name newWebSocketBuilder descriptor (Ljava/net/URI;Ljdk/incubator/http/WebSocket$Listener;)Ljdk/incubator/http/WebSocket$Builder; +method name cookieHandler descriptor ()Ljava/util/Optional; flags 401 signature ()Ljava/util/Optional; +method name sslParameters descriptor ()Ljavax/net/ssl/SSLParameters; flags 401 +method name executor descriptor ()Ljava/util/Optional; flags 401 signature ()Ljava/util/Optional; +method name sendAsync descriptor (Ljdk/incubator/http/HttpRequest;Ljdk/incubator/http/HttpResponse$MultiSubscriber;)Ljava/util/concurrent/CompletableFuture; flags 401 signature (Ljdk/incubator/http/HttpRequest;Ljdk/incubator/http/HttpResponse$MultiSubscriber;)Ljava/util/concurrent/CompletableFuture; +method name newWebSocketBuilder descriptor ()Ljdk/incubator/http/WebSocket$Builder; flags 1 + +class name jdk/incubator/http/HttpClient$Builder +field name NO_PROXY descriptor Ljava/net/ProxySelector; flags 19 +-method name cookieManager descriptor (Ljava/net/CookieManager;)Ljdk/incubator/http/HttpClient$Builder; +method name cookieHandler descriptor (Ljava/net/CookieHandler;)Ljdk/incubator/http/HttpClient$Builder; flags 401 + +class name jdk/incubator/http/HttpHeaders +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name firstValue descriptor (Ljava/lang/String;)Ljava/util/Optional; +-method name firstValueAsLong descriptor (Ljava/lang/String;)Ljava/util/OptionalLong; +-method name allValues descriptor (Ljava/lang/String;)Ljava/util/List; +method name descriptor ()V flags 4 +method name firstValue descriptor (Ljava/lang/String;)Ljava/util/Optional; flags 1 signature (Ljava/lang/String;)Ljava/util/Optional; +method name firstValueAsLong descriptor (Ljava/lang/String;)Ljava/util/OptionalLong; flags 1 +method name allValues descriptor (Ljava/lang/String;)Ljava/util/List; flags 1 signature (Ljava/lang/String;)Ljava/util/List; +method name equals descriptor (Ljava/lang/Object;)Z flags 11 +method name hashCode descriptor ()I flags 11 +method name toString descriptor ()Ljava/lang/String; flags 1 + +class name jdk/incubator/http/HttpRequest +header extends java/lang/Object flags 421 +innerclass innerClass jdk/incubator/http/HttpRequest$BodyPublisher outerClass jdk/incubator/http/HttpRequest innerClassName BodyPublisher flags 609 +innerclass innerClass jdk/incubator/http/HttpRequest$Builder outerClass jdk/incubator/http/HttpRequest innerClassName Builder flags 409 +innerclass innerClass jdk/incubator/http/HttpClient$Version outerClass jdk/incubator/http/HttpClient innerClassName Version flags 4019 +-method name bodyProcessor descriptor ()Ljava/util/Optional; +-method name duration descriptor ()Ljava/time/Duration; +-method name noBody descriptor ()Ljdk/incubator/http/HttpRequest$BodyProcessor; +method name bodyPublisher descriptor ()Ljava/util/Optional; flags 401 signature ()Ljava/util/Optional; +method name timeout descriptor ()Ljava/util/Optional; flags 401 signature ()Ljava/util/Optional; +method name equals descriptor (Ljava/lang/Object;)Z flags 11 +method name hashCode descriptor ()I flags 11 + +-class name jdk/incubator/http/HttpRequest$BodyProcessor + +class name jdk/incubator/http/HttpRequest$BodyPublisher +header extends java/lang/Object implements java/util/concurrent/Flow$Publisher flags 601 signature Ljava/lang/Object;Ljava/util/concurrent/Flow$Publisher; +innerclass innerClass java/util/concurrent/Flow$Publisher outerClass java/util/concurrent/Flow innerClassName Publisher flags 609 +innerclass innerClass jdk/incubator/http/HttpRequest$BodyPublisher outerClass jdk/incubator/http/HttpRequest innerClassName BodyPublisher flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name fromPublisher descriptor (Ljava/util/concurrent/Flow$Publisher;)Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 signature (Ljava/util/concurrent/Flow$Publisher<+Ljava/nio/ByteBuffer;>;)Ljdk/incubator/http/HttpRequest$BodyPublisher; +method name fromPublisher descriptor (Ljava/util/concurrent/Flow$Publisher;J)Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 signature (Ljava/util/concurrent/Flow$Publisher<+Ljava/nio/ByteBuffer;>;J)Ljdk/incubator/http/HttpRequest$BodyPublisher; +method name fromString descriptor (Ljava/lang/String;)Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 +method name fromString descriptor (Ljava/lang/String;Ljava/nio/charset/Charset;)Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 +method name fromInputStream descriptor (Ljava/util/function/Supplier;)Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 signature (Ljava/util/function/Supplier<+Ljava/io/InputStream;>;)Ljdk/incubator/http/HttpRequest$BodyPublisher; +method name fromByteArray descriptor ([B)Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 +method name fromByteArray descriptor ([BII)Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 +method name fromFile descriptor (Ljava/nio/file/Path;)Ljdk/incubator/http/HttpRequest$BodyPublisher; thrownTypes java/io/FileNotFoundException flags 9 +method name fromByteArrays descriptor (Ljava/lang/Iterable;)Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 signature (Ljava/lang/Iterable<[B>;)Ljdk/incubator/http/HttpRequest$BodyPublisher; +method name noBody descriptor ()Ljdk/incubator/http/HttpRequest$BodyPublisher; flags 9 +method name contentLength descriptor ()J flags 401 + +class name jdk/incubator/http/HttpRequest$Builder +header extends java/lang/Object flags 421 +innerclass innerClass jdk/incubator/http/HttpRequest$Builder outerClass jdk/incubator/http/HttpRequest innerClassName Builder flags 409 +innerclass innerClass jdk/incubator/http/HttpClient$Version outerClass jdk/incubator/http/HttpClient innerClassName Version flags 4019 +innerclass innerClass jdk/incubator/http/HttpRequest$BodyPublisher outerClass jdk/incubator/http/HttpRequest innerClassName BodyPublisher flags 609 +-method name POST descriptor (Ljdk/incubator/http/HttpRequest$BodyProcessor;)Ljdk/incubator/http/HttpRequest$Builder; +-method name PUT descriptor (Ljdk/incubator/http/HttpRequest$BodyProcessor;)Ljdk/incubator/http/HttpRequest$Builder; +-method name DELETE descriptor (Ljdk/incubator/http/HttpRequest$BodyProcessor;)Ljdk/incubator/http/HttpRequest$Builder; +-method name method descriptor (Ljava/lang/String;Ljdk/incubator/http/HttpRequest$BodyProcessor;)Ljdk/incubator/http/HttpRequest$Builder; +method name POST descriptor (Ljdk/incubator/http/HttpRequest$BodyPublisher;)Ljdk/incubator/http/HttpRequest$Builder; flags 401 +method name PUT descriptor (Ljdk/incubator/http/HttpRequest$BodyPublisher;)Ljdk/incubator/http/HttpRequest$Builder; flags 401 +method name DELETE descriptor (Ljdk/incubator/http/HttpRequest$BodyPublisher;)Ljdk/incubator/http/HttpRequest$Builder; flags 401 +method name method descriptor (Ljava/lang/String;Ljdk/incubator/http/HttpRequest$BodyPublisher;)Ljdk/incubator/http/HttpRequest$Builder; flags 401 + +class name jdk/incubator/http/HttpResponse +header extends java/lang/Object flags 421 signature Ljava/lang/Object; +innerclass innerClass jdk/incubator/http/HttpResponse$MultiSubscriber outerClass jdk/incubator/http/HttpResponse innerClassName MultiSubscriber flags 609 +innerclass innerClass jdk/incubator/http/HttpResponse$BodySubscriber outerClass jdk/incubator/http/HttpResponse innerClassName BodySubscriber flags 609 +innerclass innerClass jdk/incubator/http/HttpResponse$BodyHandler outerClass jdk/incubator/http/HttpResponse innerClassName BodyHandler flags 609 +innerclass innerClass jdk/incubator/http/HttpClient$Version outerClass jdk/incubator/http/HttpClient innerClassName Version flags 4019 +-method name finalRequest descriptor ()Ljdk/incubator/http/HttpRequest; +-method name trailers descriptor ()Ljava/util/concurrent/CompletableFuture; +method name previousResponse descriptor ()Ljava/util/Optional; flags 401 signature ()Ljava/util/Optional;>; + +class name jdk/incubator/http/HttpResponse$BodyHandler +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass jdk/incubator/http/HttpResponse$BodySubscriber outerClass jdk/incubator/http/HttpResponse innerClassName BodySubscriber flags 609 +innerclass innerClass java/util/concurrent/Flow$Subscriber outerClass java/util/concurrent/Flow innerClassName Subscriber flags 609 +innerclass innerClass jdk/incubator/http/HttpResponse$BodyHandler outerClass jdk/incubator/http/HttpResponse innerClassName BodyHandler flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name apply descriptor (ILjdk/incubator/http/HttpHeaders;)Ljdk/incubator/http/HttpResponse$BodyProcessor; +method name apply descriptor (ILjdk/incubator/http/HttpHeaders;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 401 signature (ILjdk/incubator/http/HttpHeaders;)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name fromSubscriber descriptor (Ljava/util/concurrent/Flow$Subscriber;)Ljdk/incubator/http/HttpResponse$BodyHandler; flags 9 signature (Ljava/util/concurrent/Flow$Subscriber<-Ljava/util/List;>;)Ljdk/incubator/http/HttpResponse$BodyHandler; +method name fromSubscriber descriptor (Ljava/util/concurrent/Flow$Subscriber;Ljava/util/function/Function;)Ljdk/incubator/http/HttpResponse$BodyHandler; flags 9 signature ;>;T:Ljava/lang/Object;>(TS;Ljava/util/function/Function;)Ljdk/incubator/http/HttpResponse$BodyHandler; +method name asInputStream descriptor ()Ljdk/incubator/http/HttpResponse$BodyHandler; flags 9 signature ()Ljdk/incubator/http/HttpResponse$BodyHandler; +method name buffering descriptor (Ljdk/incubator/http/HttpResponse$BodyHandler;I)Ljdk/incubator/http/HttpResponse$BodyHandler; flags 9 signature (Ljdk/incubator/http/HttpResponse$BodyHandler;I)Ljdk/incubator/http/HttpResponse$BodyHandler; + +-class name jdk/incubator/http/HttpResponse$BodyProcessor + +class name jdk/incubator/http/HttpResponse$BodySubscriber +header extends java/lang/Object implements java/util/concurrent/Flow$Subscriber flags 601 signature Ljava/lang/Object;Ljava/util/concurrent/Flow$Subscriber;>; +innerclass innerClass java/util/concurrent/Flow$Subscriber outerClass java/util/concurrent/Flow innerClassName Subscriber flags 609 +innerclass innerClass jdk/incubator/http/HttpResponse$BodySubscriber outerClass jdk/incubator/http/HttpResponse innerClassName BodySubscriber flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name getBody descriptor ()Ljava/util/concurrent/CompletionStage; flags 401 signature ()Ljava/util/concurrent/CompletionStage; +method name fromSubscriber descriptor (Ljava/util/concurrent/Flow$Subscriber;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature ;>;>(TS;)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name fromSubscriber descriptor (Ljava/util/concurrent/Flow$Subscriber;Ljava/util/function/Function;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature ;>;T:Ljava/lang/Object;>(TS;Ljava/util/function/Function;)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name asString descriptor (Ljava/nio/charset/Charset;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature (Ljava/nio/charset/Charset;)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name asByteArray descriptor ()Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature ()Ljdk/incubator/http/HttpResponse$BodySubscriber<[B>; +method name asFile descriptor (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 89 signature (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name asFile descriptor (Ljava/nio/file/Path;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature (Ljava/nio/file/Path;)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name asByteArrayConsumer descriptor (Ljava/util/function/Consumer;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature (Ljava/util/function/Consumer;>;)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name asInputStream descriptor ()Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature ()Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name discard descriptor (Ljava/lang/Object;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature (TU;)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name buffering descriptor (Ljdk/incubator/http/HttpResponse$BodySubscriber;I)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 9 signature (Ljdk/incubator/http/HttpResponse$BodySubscriber;I)Ljdk/incubator/http/HttpResponse$BodySubscriber; +method name access$000 descriptor (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljdk/incubator/http/HttpResponse$BodySubscriber; flags 1009 + +-class name jdk/incubator/http/HttpResponse$MultiProcessor + +class name jdk/incubator/http/HttpResponse$MultiSubscriber +header extends java/lang/Object flags 601 signature Ljava/lang/Object; +innerclass innerClass jdk/incubator/http/HttpResponse$BodyHandler outerClass jdk/incubator/http/HttpResponse innerClassName BodyHandler flags 609 +innerclass innerClass jdk/incubator/http/HttpResponse$MultiSubscriber outerClass jdk/incubator/http/HttpResponse innerClassName MultiSubscriber flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name onRequest descriptor (Ljdk/incubator/http/HttpRequest;)Ljdk/incubator/http/HttpResponse$BodyHandler; flags 401 signature (Ljdk/incubator/http/HttpRequest;)Ljdk/incubator/http/HttpResponse$BodyHandler; +method name onPushPromise descriptor (Ljdk/incubator/http/HttpRequest;)Ljava/util/Optional; flags 401 signature (Ljdk/incubator/http/HttpRequest;)Ljava/util/Optional;>; +method name onResponse descriptor (Ljdk/incubator/http/HttpResponse;)V flags 401 signature (Ljdk/incubator/http/HttpResponse;)V +method name onError descriptor (Ljdk/incubator/http/HttpRequest;Ljava/lang/Throwable;)V flags 401 +method name completion descriptor (Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)Ljava/util/concurrent/CompletableFuture; flags 401 signature (Ljava/util/concurrent/CompletableFuture;Ljava/util/concurrent/CompletableFuture;)Ljava/util/concurrent/CompletableFuture; +method name asMap descriptor (Ljava/util/function/Function;Z)Ljdk/incubator/http/HttpResponse$MultiSubscriber; flags 9 signature (Ljava/util/function/Function;>;>;Z)Ljdk/incubator/http/HttpResponse$MultiSubscriber;TV;>; +method name asMap descriptor (Ljava/util/function/Function;)Ljdk/incubator/http/HttpResponse$MultiSubscriber; flags 9 signature (Ljava/util/function/Function;>;>;)Ljdk/incubator/http/HttpResponse$MultiSubscriber;TV;>; + +class name jdk/incubator/http/WebSocket +-method name isClosed descriptor ()Z +-method name abort descriptor ()V +method name isOutputClosed descriptor ()Z flags 401 +method name isInputClosed descriptor ()Z flags 401 +method name abort descriptor ()V flags 401 + +class name jdk/incubator/http/WebSocket$Builder +header extends java/lang/Object flags 601 +innerclass innerClass jdk/incubator/http/WebSocket$Builder outerClass jdk/incubator/http/WebSocket innerClassName Builder flags 609 +innerclass innerClass jdk/incubator/http/WebSocket$Listener outerClass jdk/incubator/http/WebSocket innerClassName Listener flags 609 +-method name buildAsync descriptor ()Ljava/util/concurrent/CompletableFuture; +method name buildAsync descriptor (Ljava/net/URI;Ljdk/incubator/http/WebSocket$Listener;)Ljava/util/concurrent/CompletableFuture; flags 401 signature (Ljava/net/URI;Ljdk/incubator/http/WebSocket$Listener;)Ljava/util/concurrent/CompletableFuture; + diff --git a/make/data/symbols/jdk.jartool-A.sym.txt b/make/data/symbols/jdk.jartool-A.sym.txt new file mode 100644 index 00000000000..0356ab54305 --- /dev/null +++ b/make/data/symbols/jdk.jartool-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jartool +header exports com/sun/jarsigner,jdk/security/jarsigner requires name\u0020;java.base\u0020;flags\u0020;8000 provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;sun/tools/jar/JarToolProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.javadoc-A.sym.txt b/make/data/symbols/jdk.javadoc-A.sym.txt new file mode 100644 index 00000000000..c8b12e6eadd --- /dev/null +++ b/make/data/symbols/jdk.javadoc-A.sym.txt @@ -0,0 +1,35 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.javadoc +header exports com/sun/javadoc,com/sun/tools/javadoc,jdk/javadoc/doclet requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.xml\u0020;flags\u0020;0,name\u0020;java.compiler\u0020;flags\u0020;20,name\u0020;jdk.compiler\u0020;flags\u0020;20 provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;jdk/javadoc/internal/tool/JavadocToolProvider,interface\u0020;javax/tools/DocumentationTool\u0020;impls\u0020;jdk/javadoc/internal/api/JavadocTool,interface\u0020;javax/tools/Tool\u0020;impls\u0020;jdk/javadoc/internal/api/JavadocTool target linux-amd64 flags 8000 + +-class name com/sun/tools/doclets/Taglet + +-class name com/sun/tools/doclets/standard/Standard + diff --git a/make/data/symbols/jdk.jcmd-A.sym.txt b/make/data/symbols/jdk.jcmd-A.sym.txt new file mode 100644 index 00000000000..12e06f241b8 --- /dev/null +++ b/make/data/symbols/jdk.jcmd-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jcmd +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.attach\u0020;flags\u0020;0,name\u0020;jdk.internal.jvmstat\u0020;flags\u0020;0 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.jconsole-A.sym.txt b/make/data/symbols/jdk.jconsole-A.sym.txt new file mode 100644 index 00000000000..bb10c002082 --- /dev/null +++ b/make/data/symbols/jdk.jconsole-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jconsole +header exports com/sun/tools/jconsole requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.management.rmi\u0020;flags\u0020;0,name\u0020;java.rmi\u0020;flags\u0020;0,name\u0020;jdk.attach\u0020;flags\u0020;0,name\u0020;jdk.internal.jvmstat\u0020;flags\u0020;0,name\u0020;jdk.management\u0020;flags\u0020;0,name\u0020;jdk.management.agent\u0020;flags\u0020;0,name\u0020;java.desktop\u0020;flags\u0020;20,name\u0020;java.management\u0020;flags\u0020;20 uses com/sun/tools/jconsole/JConsolePlugin target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.jdeps-A.sym.txt b/make/data/symbols/jdk.jdeps-A.sym.txt new file mode 100644 index 00000000000..56ecbd4036c --- /dev/null +++ b/make/data/symbols/jdk.jdeps-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jdeps +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.compiler\u0020;flags\u0020;0,name\u0020;jdk.compiler\u0020;flags\u0020;0 provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;com/sun/tools/javap/Main$JavapToolProvider\u005C;u002C;com/sun/tools/jdeps/Main$JDepsToolProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.jdi-A.sym.txt b/make/data/symbols/jdk.jdi-A.sym.txt new file mode 100644 index 00000000000..086b27d5ce2 --- /dev/null +++ b/make/data/symbols/jdk.jdi-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jdi +header exports com/sun/jdi,com/sun/jdi/connect,com/sun/jdi/connect/spi,com/sun/jdi/event,com/sun/jdi/request requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.attach\u0020;flags\u0020;0,name\u0020;jdk.jdwp.agent\u0020;flags\u0020;0 uses com/sun/jdi/connect/Connector,com/sun/jdi/connect/spi/TransportService provides interface\u0020;com/sun/jdi/connect/Connector\u0020;impls\u0020;com/sun/tools/jdi/ProcessAttachingConnector\u005C;u002C;com/sun/tools/jdi/RawCommandLineLauncher\u005C;u002C;com/sun/tools/jdi/SocketAttachingConnector\u005C;u002C;com/sun/tools/jdi/SocketListeningConnector\u005C;u002C;com/sun/tools/jdi/SunCommandLineLauncher target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.jdwp.agent-A.sym.txt b/make/data/symbols/jdk.jdwp.agent-A.sym.txt new file mode 100644 index 00000000000..1cffb4867f0 --- /dev/null +++ b/make/data/symbols/jdk.jdwp.agent-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jdwp.agent +header requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.jlink-A.sym.txt b/make/data/symbols/jdk.jlink-A.sym.txt new file mode 100644 index 00000000000..c97a1c17ff6 --- /dev/null +++ b/make/data/symbols/jdk.jlink-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jlink +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.internal.opt\u0020;flags\u0020;0,name\u0020;jdk.jdeps\u0020;flags\u0020;0 uses jdk/tools/jlink/plugin/Plugin provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;jdk/tools/jmod/Main$JmodToolProvider\u005C;u002C;jdk/tools/jlink/internal/Main$JlinkToolProvider,interface\u0020;jdk/tools/jlink/plugin/Plugin\u0020;impls\u0020;jdk/tools/jlink/internal/plugins/StripDebugPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludePlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/LegalNoticeFilePlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/SystemModulesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/OrderResourcesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/DefaultCompressPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeVMPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ClassForNamePlugin target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.jshell-A.sym.txt b/make/data/symbols/jdk.jshell-A.sym.txt new file mode 100644 index 00000000000..21524d824ea --- /dev/null +++ b/make/data/symbols/jdk.jshell-A.sym.txt @@ -0,0 +1,37 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jshell +header exports jdk/jshell,jdk/jshell/execution,jdk/jshell/spi,jdk/jshell/tool requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;jdk.compiler\u0020;flags\u0020;0,name\u0020;jdk.internal.ed\u0020;flags\u0020;0,name\u0020;jdk.internal.le\u0020;flags\u0020;0,name\u0020;jdk.internal.opt\u0020;flags\u0020;0,name\u0020;java.compiler\u0020;flags\u0020;20,name\u0020;java.prefs\u0020;flags\u0020;20,name\u0020;jdk.jdi\u0020;flags\u0020;20 uses jdk/jshell/spi/ExecutionControlProvider,jdk/internal/editor/spi/BuildInEditorProvider provides interface\u0020;javax/tools/Tool\u0020;impls\u0020;jdk/internal/jshell/tool/JShellToolProvider,interface\u0020;jdk/jshell/spi/ExecutionControlProvider\u0020;impls\u0020;jdk/jshell/execution/JdiExecutionControlProvider\u005C;u002C;jdk/jshell/execution/LocalExecutionControlProvider\u005C;u002C;jdk/jshell/execution/FailOverExecutionControlProvider target linux-amd64 flags 8000 + +class name jdk/jshell/SourceCodeAnalysis +method name sourceToSnippets descriptor (Ljava/lang/String;)Ljava/util/List; flags 401 signature (Ljava/lang/String;)Ljava/util/List; + +class name jdk/jshell/tool/JavaShellToolBuilder +method name start descriptor ([Ljava/lang/String;)I thrownTypes java/lang/Exception flags 81 + diff --git a/make/data/symbols/jdk.jsobject-A.sym.txt b/make/data/symbols/jdk.jsobject-A.sym.txt new file mode 100644 index 00000000000..9148b865908 --- /dev/null +++ b/make/data/symbols/jdk.jsobject-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jsobject +header exports netscape/javascript requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.desktop\u0020;flags\u0020;0 uses jdk/internal/netscape/javascript/spi/JSObjectProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.jstatd-A.sym.txt b/make/data/symbols/jdk.jstatd-A.sym.txt new file mode 100644 index 00000000000..bee957301b9 --- /dev/null +++ b/make/data/symbols/jdk.jstatd-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jstatd +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.rmi\u0020;flags\u0020;0,name\u0020;jdk.internal.jvmstat\u0020;flags\u0020;0 provides interface\u0020;sun/jvmstat/monitor/MonitoredHostService\u0020;impls\u0020;sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.localedata-A.sym.txt b/make/data/symbols/jdk.localedata-A.sym.txt new file mode 100644 index 00000000000..fc06e8ed64b --- /dev/null +++ b/make/data/symbols/jdk.localedata-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.localedata +header requires name\u0020;java.base\u0020;flags\u0020;8000 provides interface\u0020;sun/util/locale/provider/LocaleDataMetaInfo\u0020;impls\u0020;sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo\u005C;u002C;sun/util/resources/provider/NonBaseLocaleDataMetaInfo,interface\u0020;sun/util/resources/LocaleData$CommonResourceBundleProvider\u0020;impls\u0020;sun/util/resources/provider/LocaleDataProvider,interface\u0020;sun/util/resources/LocaleData$SupplementaryResourceBundleProvider\u0020;impls\u0020;sun/util/resources/provider/SupplementaryLocaleDataProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.management-A.sym.txt b/make/data/symbols/jdk.management-A.sym.txt new file mode 100644 index 00000000000..90ab3d4b962 --- /dev/null +++ b/make/data/symbols/jdk.management-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.management +header exports com/sun/management requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.management\u0020;flags\u0020;20 provides interface\u0020;sun/management/spi/PlatformMBeanProvider\u0020;impls\u0020;com/sun/management/internal/PlatformMBeanProviderImpl target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.management.agent-A.sym.txt b/make/data/symbols/jdk.management.agent-A.sym.txt new file mode 100644 index 00000000000..4e02f609f26 --- /dev/null +++ b/make/data/symbols/jdk.management.agent-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.management.agent +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.management\u0020;flags\u0020;0,name\u0020;java.management.rmi\u0020;flags\u0020;0 uses jdk/internal/agent/spi/AgentProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.naming.dns-A.sym.txt b/make/data/symbols/jdk.naming.dns-A.sym.txt new file mode 100644 index 00000000000..701d26e8dba --- /dev/null +++ b/make/data/symbols/jdk.naming.dns-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.naming.dns +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.naming\u0020;flags\u0020;0 provides interface\u0020;javax/naming/spi/InitialContextFactory\u0020;impls\u0020;com/sun/jndi/dns/DnsContextFactory target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.naming.rmi-A.sym.txt b/make/data/symbols/jdk.naming.rmi-A.sym.txt new file mode 100644 index 00000000000..b72ef1b5295 --- /dev/null +++ b/make/data/symbols/jdk.naming.rmi-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.naming.rmi +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.naming\u0020;flags\u0020;0,name\u0020;java.rmi\u0020;flags\u0020;0 provides interface\u0020;javax/naming/spi/InitialContextFactory\u0020;impls\u0020;com/sun/jndi/rmi/registry/RegistryContextFactory target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.net-A.sym.txt b/make/data/symbols/jdk.net-A.sym.txt new file mode 100644 index 00000000000..5227388a1fe --- /dev/null +++ b/make/data/symbols/jdk.net-A.sym.txt @@ -0,0 +1,34 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.net +header exports jdk/net requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 + +class name jdk/net/ExtendedSocketOptions +field name TCP_QUICKACK descriptor Ljava/net/SocketOption; flags 19 signature Ljava/net/SocketOption; + diff --git a/make/data/symbols/jdk.pack-A.sym.txt b/make/data/symbols/jdk.pack-A.sym.txt new file mode 100644 index 00000000000..593f50e78ab --- /dev/null +++ b/make/data/symbols/jdk.pack-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.pack +header requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.policytool-A.sym.txt b/make/data/symbols/jdk.policytool-A.sym.txt new file mode 100644 index 00000000000..af5e3549692 --- /dev/null +++ b/make/data/symbols/jdk.policytool-A.sym.txt @@ -0,0 +1,30 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +-module name jdk.policytool + diff --git a/make/data/symbols/jdk.rmic-A.sym.txt b/make/data/symbols/jdk.rmic-A.sym.txt new file mode 100644 index 00000000000..c66f19abbfa --- /dev/null +++ b/make/data/symbols/jdk.rmic-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.rmic +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.corba\u0020;flags\u0020;0,name\u0020;jdk.compiler\u0020;flags\u0020;0,name\u0020;jdk.javadoc\u0020;flags\u0020;0 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.scripting.nashorn-A.sym.txt b/make/data/symbols/jdk.scripting.nashorn-A.sym.txt new file mode 100644 index 00000000000..66afc4999cc --- /dev/null +++ b/make/data/symbols/jdk.scripting.nashorn-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.scripting.nashorn +header exports jdk/nashorn/api/scripting,jdk/nashorn/api/tree requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;jdk.dynalink\u0020;flags\u0020;0,name\u0020;java.scripting\u0020;flags\u0020;20 provides interface\u0020;javax/script/ScriptEngineFactory\u0020;impls\u0020;jdk/nashorn/api/scripting/NashornScriptEngineFactory,interface\u0020;jdk/dynalink/linker/GuardingDynamicLinkerExporter\u0020;impls\u0020;jdk/nashorn/api/linker/NashornLinkerExporter target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.sctp-A.sym.txt b/make/data/symbols/jdk.sctp-A.sym.txt new file mode 100644 index 00000000000..6aef6f45561 --- /dev/null +++ b/make/data/symbols/jdk.sctp-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.sctp +header exports com/sun/nio/sctp requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.security.auth-A.sym.txt b/make/data/symbols/jdk.security.auth-A.sym.txt new file mode 100644 index 00000000000..3b4add6bc63 --- /dev/null +++ b/make/data/symbols/jdk.security.auth-A.sym.txt @@ -0,0 +1,45 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.security.auth +header exports com/sun/security/auth,com/sun/security/auth/callback,com/sun/security/auth/login,com/sun/security/auth/module requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.security.jgss\u0020;flags\u0020;0,name\u0020;java.naming\u0020;flags\u0020;20 provides interface\u0020;javax/security/auth/spi/LoginModule\u0020;impls\u0020;com/sun/security/auth/module/Krb5LoginModule\u005C;u002C;com/sun/security/auth/module/UnixLoginModule\u005C;u002C;com/sun/security/auth/module/JndiLoginModule\u005C;u002C;com/sun/security/auth/module/KeyStoreLoginModule\u005C;u002C;com/sun/security/auth/module/LdapLoginModule\u005C;u002C;com/sun/security/auth/module/NTLoginModule target linux-amd64 flags 8000 + +-class name com/sun/security/auth/PolicyFile + +-class name com/sun/security/auth/SolarisNumericGroupPrincipal + +-class name com/sun/security/auth/SolarisNumericUserPrincipal + +-class name com/sun/security/auth/SolarisPrincipal + +-class name com/sun/security/auth/X500Principal + +-class name com/sun/security/auth/module/SolarisLoginModule + +-class name com/sun/security/auth/module/SolarisSystem + diff --git a/make/data/symbols/jdk.security.jgss-A.sym.txt b/make/data/symbols/jdk.security.jgss-A.sym.txt new file mode 100644 index 00000000000..6765899d41c --- /dev/null +++ b/make/data/symbols/jdk.security.jgss-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.security.jgss +header exports com/sun/security/jgss requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;java.security.sasl\u0020;flags\u0020;0,name\u0020;java.security.jgss\u0020;flags\u0020;20 provides interface\u0020;java/security/Provider\u0020;impls\u0020;com/sun/security/sasl/gsskerb/JdkSASL target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.unsupported-A.sym.txt b/make/data/symbols/jdk.unsupported-A.sym.txt new file mode 100644 index 00000000000..1119e81fabd --- /dev/null +++ b/make/data/symbols/jdk.unsupported-A.sym.txt @@ -0,0 +1,39 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.unsupported +header exports com/sun/nio/file,sun/misc,sun/reflect requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 + +class name com/sun/nio/file/ExtendedOpenOption +field name DIRECT descriptor Lcom/sun/nio/file/ExtendedOpenOption; flags 4019 + +class name sun/reflect/ReflectionFactory +header extends java/lang/Object flags 21 classAnnotations @Lsun/Proprietary+Annotation; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name newInstanceForSerialization descriptor (Ljava/lang/reflect/Constructor;[Ljava/security/ProtectionDomain;)Ljava/lang/Object; thrownTypes java/lang/InstantiationException,java/lang/reflect/InvocationTargetException,java/lang/IllegalAccessException flags 11 signature (Ljava/lang/reflect/Constructor<*>;[Ljava/security/ProtectionDomain;)Ljava/lang/Object; + diff --git a/make/data/symbols/jdk.xml.dom-A.sym.txt b/make/data/symbols/jdk.xml.dom-A.sym.txt new file mode 100644 index 00000000000..2342beace35 --- /dev/null +++ b/make/data/symbols/jdk.xml.dom-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.xml.dom +header exports org/w3c/dom/css,org/w3c/dom/html,org/w3c/dom/stylesheets,org/w3c/dom/xpath requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.xml\u0020;flags\u0020;20 target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.zipfs-A.sym.txt b/make/data/symbols/jdk.zipfs-A.sym.txt new file mode 100644 index 00000000000..56609610d44 --- /dev/null +++ b/make/data/symbols/jdk.zipfs-A.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.zipfs +header requires name\u0020;java.base\u0020;flags\u0020;8000 provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/nio/zipfs/ZipFileSystemProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/symbols b/make/data/symbols/symbols index 21c1504c4f7..ca0a74f5217 100644 --- a/make/data/symbols/symbols +++ b/make/data/symbols/symbols @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2018, 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 @@ -27,10 +27,11 @@ # ########################################################## # #command used to generate this file: -#build.tools.symbolgenerator.CreateSymbols build-description new-symbols symbols/include.list 8 JDK8.classes 7 JDK7.classes 8 6 JDK6u4.classes 7 9 JDK9.classes 8 +#build.tools.symbolgenerator.CreateSymbols build-description-incremental symbols include.list # -generate platforms 6:7:8:9 +generate platforms 6:7:8:9:A platform version 8 files java.activation-8.sym.txt:java.base-8.sym.txt:java.compiler-8.sym.txt:java.corba-8.sym.txt:java.datatransfer-8.sym.txt:java.desktop-8.sym.txt:java.instrument-8.sym.txt:java.logging-8.sym.txt:java.management-8.sym.txt:java.management.rmi-8.sym.txt:java.naming-8.sym.txt:java.prefs-8.sym.txt:java.rmi-8.sym.txt:java.scripting-8.sym.txt:java.security.jgss-8.sym.txt:java.security.sasl-8.sym.txt:java.sql-8.sym.txt:java.sql.rowset-8.sym.txt:java.transaction-8.sym.txt:java.xml-8.sym.txt:java.xml.bind-8.sym.txt:java.xml.crypto-8.sym.txt:java.xml.ws-8.sym.txt:java.xml.ws.annotation-8.sym.txt:jdk.httpserver-8.sym.txt:jdk.management-8.sym.txt:jdk.scripting.nashorn-8.sym.txt:jdk.sctp-8.sym.txt:jdk.security.auth-8.sym.txt:jdk.security.jgss-8.sym.txt platform version 7 base 8 files java.base-7.sym.txt:java.compiler-7.sym.txt:java.datatransfer-7.sym.txt:java.desktop-7.sym.txt:java.logging-7.sym.txt:java.management-7.sym.txt:java.naming-7.sym.txt:java.prefs-7.sym.txt:java.rmi-7.sym.txt:java.scripting-7.sym.txt:java.security.jgss-7.sym.txt:java.security.sasl-7.sym.txt:java.sql-7.sym.txt:java.sql.rowset-7.sym.txt:java.xml-7.sym.txt:java.xml.bind-7.sym.txt:java.xml.ws.annotation-7.sym.txt:jdk.httpserver-7.sym.txt:jdk.management-7.sym.txt:jdk.scripting.nashorn-7.sym.txt:jdk.sctp-7.sym.txt:jdk.security.auth-7.sym.txt:jdk.security.jgss-7.sym.txt platform version 6 base 7 files java.base-6.sym.txt:java.compiler-6.sym.txt:java.desktop-6.sym.txt:java.logging-6.sym.txt:java.management-6.sym.txt:java.rmi-6.sym.txt:java.security.jgss-6.sym.txt:java.sql-6.sym.txt:java.sql.rowset-6.sym.txt:java.xml-6.sym.txt:java.xml.bind-6.sym.txt:java.xml.ws-6.sym.txt:java.xml.ws.annotation-6.sym.txt:jdk.management-6.sym.txt:jdk.sctp-6.sym.txt:jdk.security.jgss-6.sym.txt platform version 9 base 8 files java.activation-9.sym.txt:java.base-9.sym.txt:java.compiler-9.sym.txt:java.corba-9.sym.txt:java.datatransfer-9.sym.txt:java.desktop-9.sym.txt:java.instrument-9.sym.txt:java.logging-9.sym.txt:java.management-9.sym.txt:java.management.rmi-9.sym.txt:java.naming-9.sym.txt:java.prefs-9.sym.txt:java.rmi-9.sym.txt:java.scripting-9.sym.txt:java.se-9.sym.txt:java.se.ee-9.sym.txt:java.security.jgss-9.sym.txt:java.security.sasl-9.sym.txt:java.smartcardio-9.sym.txt:java.sql-9.sym.txt:java.sql.rowset-9.sym.txt:java.transaction-9.sym.txt:java.xml-9.sym.txt:java.xml.bind-9.sym.txt:java.xml.crypto-9.sym.txt:java.xml.ws-9.sym.txt:java.xml.ws.annotation-9.sym.txt:jdk.accessibility-9.sym.txt:jdk.attach-9.sym.txt:jdk.charsets-9.sym.txt:jdk.compiler-9.sym.txt:jdk.crypto.cryptoki-9.sym.txt:jdk.crypto.ec-9.sym.txt:jdk.dynalink-9.sym.txt:jdk.editpad-9.sym.txt:jdk.hotspot.agent-9.sym.txt:jdk.httpserver-9.sym.txt:jdk.incubator.httpclient-9.sym.txt:jdk.jartool-9.sym.txt:jdk.javadoc-9.sym.txt:jdk.jcmd-9.sym.txt:jdk.jconsole-9.sym.txt:jdk.jdeps-9.sym.txt:jdk.jdi-9.sym.txt:jdk.jdwp.agent-9.sym.txt:jdk.jlink-9.sym.txt:jdk.jshell-9.sym.txt:jdk.jsobject-9.sym.txt:jdk.jstatd-9.sym.txt:jdk.localedata-9.sym.txt:jdk.management-9.sym.txt:jdk.management.agent-9.sym.txt:jdk.naming.dns-9.sym.txt:jdk.naming.rmi-9.sym.txt:jdk.net-9.sym.txt:jdk.pack-9.sym.txt:jdk.policytool-9.sym.txt:jdk.rmic-9.sym.txt:jdk.scripting.nashorn-9.sym.txt:jdk.sctp-9.sym.txt:jdk.security.auth-9.sym.txt:jdk.security.jgss-9.sym.txt:jdk.unsupported-9.sym.txt:jdk.xml.dom-9.sym.txt:jdk.zipfs-9.sym.txt +platform version A base 9 files java.activation-A.sym.txt:java.base-A.sym.txt:java.compiler-A.sym.txt:java.corba-A.sym.txt:java.datatransfer-A.sym.txt:java.desktop-A.sym.txt:java.instrument-A.sym.txt:java.logging-A.sym.txt:java.management-A.sym.txt:java.management.rmi-A.sym.txt:java.naming-A.sym.txt:java.prefs-A.sym.txt:java.rmi-A.sym.txt:java.scripting-A.sym.txt:java.se-A.sym.txt:java.se.ee-A.sym.txt:java.security.jgss-A.sym.txt:java.security.sasl-A.sym.txt:java.smartcardio-A.sym.txt:java.sql-A.sym.txt:java.sql.rowset-A.sym.txt:java.transaction-A.sym.txt:java.xml-A.sym.txt:java.xml.bind-A.sym.txt:java.xml.crypto-A.sym.txt:java.xml.ws-A.sym.txt:java.xml.ws.annotation-A.sym.txt:jdk.accessibility-A.sym.txt:jdk.attach-A.sym.txt:jdk.charsets-A.sym.txt:jdk.compiler-A.sym.txt:jdk.crypto.cryptoki-A.sym.txt:jdk.crypto.ec-A.sym.txt:jdk.dynalink-A.sym.txt:jdk.editpad-A.sym.txt:jdk.hotspot.agent-A.sym.txt:jdk.httpserver-A.sym.txt:jdk.incubator.httpclient-A.sym.txt:jdk.jartool-A.sym.txt:jdk.javadoc-A.sym.txt:jdk.jcmd-A.sym.txt:jdk.jconsole-A.sym.txt:jdk.jdeps-A.sym.txt:jdk.jdi-A.sym.txt:jdk.jdwp.agent-A.sym.txt:jdk.jlink-A.sym.txt:jdk.jshell-A.sym.txt:jdk.jsobject-A.sym.txt:jdk.jstatd-A.sym.txt:jdk.localedata-A.sym.txt:jdk.management-A.sym.txt:jdk.management.agent-A.sym.txt:jdk.naming.dns-A.sym.txt:jdk.naming.rmi-A.sym.txt:jdk.net-A.sym.txt:jdk.pack-A.sym.txt:jdk.policytool-A.sym.txt:jdk.rmic-A.sym.txt:jdk.scripting.nashorn-A.sym.txt:jdk.sctp-A.sym.txt:jdk.security.auth-A.sym.txt:jdk.security.jgss-A.sym.txt:jdk.unsupported-A.sym.txt:jdk.xml.dom-A.sym.txt:jdk.zipfs-A.sym.txt diff --git a/make/gendata/Gendata-jdk.compiler.gmk b/make/gendata/Gendata-jdk.compiler.gmk index 7a7f5c6647e..1d034828598 100644 --- a/make/gendata/Gendata-jdk.compiler.gmk +++ b/make/gendata/Gendata-jdk.compiler.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2018, 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 @@ -75,14 +75,13 @@ $(SUPPORT_OUTPUTDIR)/symbols/ct.sym-files/_the.symbols: \ build-ctsym \ $(CT_DATA_DESCRIPTION) \ $(@D) - $(MKDIR) $(@D)/A $(JAVA_SMALL) $(INTERIM_LANGTOOLS_ARGS) \ $(COMPILECREATESYMBOLS_ADD_EXPORTS) \ -classpath $(BUILDTOOLS_OUTPUTDIR)/create_symbols \ build.tools.symbolgenerator.TransitiveDependencies \ + $(@D) \ $(CT_MODULESOURCEPATH) \ - $(CT_MODULES) \ - >$(@D)/A/system-modules + $(CT_MODULES) $(TOUCH) $@ # Can't generate ct.sym directly into modules libs as the SetupJarArchive macro diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 9511a3f15b4..03f84fa8565 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2018, 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 @@ -31,6 +31,7 @@ import build.tools.symbolgenerator.CreateSymbols import build.tools.symbolgenerator.CreateSymbols .ModuleHeaderDescription .RequiresDescription; +import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -38,8 +39,8 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.StringWriter; import java.io.Writer; -import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; @@ -49,23 +50,34 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.stream.Stream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; +import java.util.TimeZone; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.StandardLocation; + +import com.sun.source.util.JavacTask; import com.sun.tools.classfile.AccessFlags; import com.sun.tools.classfile.Annotation; import com.sun.tools.classfile.Annotation.Annotation_element_value; @@ -115,18 +127,20 @@ import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; import com.sun.tools.classfile.Signature_attribute; +import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Pair; -import java.io.StringWriter; /** * A tool for processing the .sym.txt files. It allows to: * * convert the .sym.txt into class/sig files for ct.sym * * in cooperation with the adjacent history Probe, construct .sym.txt files for previous platforms + * * enhance existing .sym.txt files with a a new set .sym.txt for the current platform * * To convert the .sym.txt files to class/sig files from ct.sym, run: - * java build.tool.symbolgenerator.CreateSymbols build-ctsym [JOINED_VERSIONS|SEPARATE] + * java build.tool.symbolgenerator.CreateSymbols build-ctsym * * The is a file of this format: * generate platforms @@ -166,11 +180,15 @@ import java.io.StringWriter; * To generate the .sym.txt files for OpenJDK 7 and 8: * /bin/java build.tools.symbolgenerator.Probe OpenJDK7.classes * /bin/java build.tools.symbolgenerator.Probe OpenJDK8.classes - * java build.tools.symbolgenerator.CreateSymbols build-description langtools/make/data/symbols $TOPDIR langtools/make/data/symbols/include.list + * java build.tools.symbolgenerator.CreateSymbols build-description make/data/symbols $TOPDIR make/data/symbols/include.list * 8 OpenJDK8.classes '' * 7 OpenJDK7.classes 8 * * Note: the versions are expected to be a single character. + * + * To enhance existing historical data with data for JDK N, run: + * /bin/java build.tools.symbolgenerator.CreateSymbols build-description-incremental make/data/symbols/symbols make/data/symbols/include.list + * */ public class CreateSymbols { @@ -180,11 +198,11 @@ public class CreateSymbols { */ @SuppressWarnings("unchecked") public void createSymbols(String ctDescriptionFile, String ctSymLocation, CtSymKind ctSymKind) throws IOException { - Pair> data = load(Paths.get(ctDescriptionFile)); + LoadDescriptions data = load(Paths.get(ctDescriptionFile), null); - splitHeaders(data.fst); + splitHeaders(data.classes); - for (ModuleDescription md : data.snd) { + for (ModuleDescription md : data.modules.values()) { for (ModuleHeaderDescription mhd : md.header) { List versionsList = Collections.singletonList(mhd.versions); @@ -195,7 +213,7 @@ public class CreateSymbols { } } - for (ClassDescription classDescription : data.fst) { + for (ClassDescription classDescription : data.classes) { for (ClassHeaderDescription header : classDescription.header) { switch (ctSymKind) { case JOINED_VERSIONS: @@ -219,7 +237,7 @@ public class CreateSymbols { public static String EXTENSION = ".sig"; - Pair> load(Path ctDescription) throws IOException { + LoadDescriptions load(Path ctDescription, String deletePlatform) throws IOException { List platforms = new ArrayList<>(); Set generatePlatforms = null; @@ -228,11 +246,14 @@ public class CreateSymbols { switch (reader.lineKey) { case "generate": String[] platformsAttr = reader.attributes.get("platforms").split(":"); - generatePlatforms = new HashSet<>(Arrays.asList(platformsAttr)); + generatePlatforms = new HashSet<>(List.of(platformsAttr)); + generatePlatforms.remove(deletePlatform); reader.moveNext(); break; case "platform": - platforms.add(PlatformInput.load(reader)); + PlatformInput platform = PlatformInput.load(reader); + if (!platform.version.equals(deletePlatform)) + platforms.add(platform); reader.moveNext(); break; default: @@ -250,7 +271,9 @@ public class CreateSymbols { addNewVersion(cd.fields, platform.basePlatform, platform.version); addNewVersion(cd.methods, platform.basePlatform, platform.version); } - //XXX: enhance module versions + for (ModuleDescription md : modules.values()) { + addNewVersion(md.header, platform.basePlatform, platform.version); + } for (String input : platform.files) { Path inputFile = ctDescription.getParent().resolve(input); try (LineBasedReader reader = new LineBasedReader(inputFile)) { @@ -270,13 +293,23 @@ public class CreateSymbols { cd.read(reader, platform.basePlatform, platform.version); break; - case "module": + case "module": { ModuleDescription md = modules.computeIfAbsent(nameAttr, n -> new ModuleDescription()); md.read(reader, platform.basePlatform, platform.version); break; + } + case "-module": { + ModuleDescription md = + modules.computeIfAbsent(nameAttr, + n -> new ModuleDescription()); + removeVersion(md.header, h -> true, + platform.version); + reader.moveNext(); + break; + } } } } @@ -323,7 +356,7 @@ public class CreateSymbols { result.add(desc); } - List moduleList = new ArrayList<>(); + Map moduleList = new HashMap<>(); for (ModuleDescription desc : modules.values()) { Iterator mhdIt = desc.header.iterator(); @@ -340,10 +373,25 @@ public class CreateSymbols { continue; } - moduleList.add(desc); + moduleList.put(desc.name, desc); + } + + return new LoadDescriptions(result, moduleList, platforms); + } + + static final class LoadDescriptions { + public final ClassList classes; + public final Map modules; + public final List versions; + + public LoadDescriptions(ClassList classes, + Map modules, + List versions) { + this.classes = classes; + this.modules = modules; + this.versions = versions; } - return Pair.of(result, moduleList); } static final class LineBasedReader implements AutoCloseable { @@ -423,7 +471,7 @@ public class CreateSymbols { public static PlatformInput load(LineBasedReader in) throws IOException { return new PlatformInput(in.attributes.get("version"), in.attributes.get("base"), - Arrays.asList(in.attributes.get("files").split(":"))); + List.of(in.attributes.get("files").split(":"))); } } @@ -792,7 +840,7 @@ public class CreateSymbols { private void addAttributes(MethodDescription desc, List constantPool, Map attributes) { addGenericAttributes(desc, constantPool, attributes); - if (desc.thrownTypes != null && !desc.thrownTypes.isEmpty()) { + if (desc.thrownTypes != null) { int[] exceptions = new int[desc.thrownTypes.size()]; int i = 0; for (String exc : desc.thrownTypes) { @@ -1081,175 +1129,228 @@ public class CreateSymbols { Map modules = new HashMap<>(); for (VersionDescription desc : versions) { - Map currentVersionModules = - new HashMap<>(); + List classFileData = new ArrayList<>(); + try (BufferedReader descIn = Files.newBufferedReader(Paths.get(desc.classes))) { - String classFileData; - - while ((classFileData = descIn.readLine()) != null) { + String line; + while ((line = descIn.readLine()) != null) { ByteArrayOutputStream data = new ByteArrayOutputStream(); - for (int i = 0; i < classFileData.length(); i += 2) { - String hex = classFileData.substring(i, i + 2); + for (int i = 0; i < line.length(); i += 2) { + String hex = line.substring(i, i + 2); data.write(Integer.parseInt(hex, 16)); } - try (InputStream in = - new ByteArrayInputStream(data.toByteArray())) { - inspectModuleInfoClassFile(in, - currentVersionModules, desc.version); - } catch (IOException | ConstantPoolException ex) { - throw new IllegalStateException(ex); - } + classFileData.add(data.toByteArray()); } + } catch (IOException ex) { + throw new IllegalStateException(ex); } - ExcludeIncludeList currentEIList = excludesIncludes; + loadVersionClasses(classes, modules, classFileData, excludesIncludes, desc.version); + } - if (!currentVersionModules.isEmpty()) { - Set includes = new HashSet<>(); + List platforms = + versions.stream() + .map(desc -> new PlatformInput(desc.version, + desc.primaryBaseline, + null)) + .collect(Collectors.toList()); - for (ModuleDescription md : currentVersionModules.values()) { - md.header.get(0).exports.stream().map(e -> e + '/') - .forEach(includes::add); - } + dumpDescriptions(classes, modules, platforms, descDest.resolve("symbols"), args); + } + //where: + private static final String DO_NO_MODIFY = + "#\n" + + "# Copyright (c) {YEAR}, Oracle and/or its affiliates. All rights reserved.\n" + + "# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n" + + "#\n" + + "# This code is free software; you can redistribute it and/or modify it\n" + + "# under the terms of the GNU General Public License version 2 only, as\n" + + "# published by the Free Software Foundation. Oracle designates this\n" + + "# particular file as subject to the \"Classpath\" exception as provided\n" + + "# by Oracle in the LICENSE file that accompanied this code.\n" + + "#\n" + + "# This code is distributed in the hope that it will be useful, but WITHOUT\n" + + "# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n" + + "# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n" + + "# version 2 for more details (a copy is included in the LICENSE file that\n" + + "# accompanied this code).\n" + + "#\n" + + "# You should have received a copy of the GNU General Public License version\n" + + "# 2 along with this work; if not, write to the Free Software Foundation,\n" + + "# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n" + + "#\n" + + "# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n" + + "# or visit www.oracle.com if you need additional information or have any\n" + + "# questions.\n" + + "#\n" + + "# ##########################################################\n" + + "# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ###\n" + + "# ##########################################################\n" + + "#\n"; - currentEIList = new ExcludeIncludeList(includes, - Collections.emptySet()); + private void loadVersionClasses(ClassList classes, + Map modules, + Iterable classData, + ExcludeIncludeList excludesIncludes, + String version) { + Map currentVersionModules = + new HashMap<>(); + + for (byte[] classFileData : classData) { + try (InputStream in = new ByteArrayInputStream(classFileData)) { + inspectModuleInfoClassFile(in, + currentVersionModules, version); + } catch (IOException | ConstantPoolException ex) { + throw new IllegalStateException(ex); + } + } + + ExcludeIncludeList currentEIList = excludesIncludes; + + if (!currentVersionModules.isEmpty()) { + Set includes = new HashSet<>(); + + for (ModuleDescription md : currentVersionModules.values()) { + md.header.get(0).exports.stream().map(e -> e + '/') + .forEach(includes::add); } - ClassList currentVersionClasses = new ClassList(); - try (BufferedReader descIn = - Files.newBufferedReader(Paths.get(desc.classes))) { - String classFileData; + currentEIList = new ExcludeIncludeList(includes, + Collections.emptySet()); + } - while ((classFileData = descIn.readLine()) != null) { - ByteArrayOutputStream data = new ByteArrayOutputStream(); - for (int i = 0; i < classFileData.length(); i += 2) { - String hex = classFileData.substring(i, i + 2); - data.write(Integer.parseInt(hex, 16)); - } - try (InputStream in = - new ByteArrayInputStream(data.toByteArray())) { - inspectClassFile(in, currentVersionClasses, - currentEIList, desc.version); - } catch (IOException | ConstantPoolException ex) { - throw new IllegalStateException(ex); - } - } + ClassList currentVersionClasses = new ClassList(); + + for (byte[] classFileData : classData) { + try (InputStream in = new ByteArrayInputStream(classFileData)) { + inspectClassFile(in, currentVersionClasses, + currentEIList, version); + } catch (IOException | ConstantPoolException ex) { + throw new IllegalStateException(ex); } + } - ModuleDescription unsupported = - currentVersionModules.get("jdk.unsupported"); + ModuleDescription unsupported = + currentVersionModules.get("jdk.unsupported"); - if (unsupported != null) { - for (ClassDescription cd : currentVersionClasses.classes) { - if (unsupported.header - .get(0) - .exports - .contains(cd.packge().replace('.', '/'))) { - ClassHeaderDescription ch = cd.header.get(0); - if (ch.classAnnotations == null) { - ch.classAnnotations = new ArrayList<>(); - } - AnnotationDescription ad; - ad = new AnnotationDescription(PROPERITARY_ANNOTATION, - Collections.emptyMap()); - ch.classAnnotations.add(ad); + if (unsupported != null) { + for (ClassDescription cd : currentVersionClasses.classes) { + if (unsupported.header + .get(0) + .exports + .contains(cd.packge().replace('.', '/'))) { + ClassHeaderDescription ch = cd.header.get(0); + if (ch.classAnnotations == null) { + ch.classAnnotations = new ArrayList<>(); } - } - } - - Set includedClasses = new HashSet<>(); - boolean modified; - - do { - modified = false; - - for (ClassDescription clazz : currentVersionClasses) { - ClassHeaderDescription header = clazz.header.get(0); - - if (includeEffectiveAccess(currentVersionClasses, clazz)) { - modified |= include(includedClasses, currentVersionClasses, clazz.name); - } - - if (includedClasses.contains(clazz.name)) { - modified |= include(includedClasses, currentVersionClasses, header.extendsAttr); - for (String i : header.implementsAttr) { - modified |= include(includedClasses, currentVersionClasses, i); - } - - modified |= includeOutputType(Collections.singleton(header), - h -> "", - includedClasses, - currentVersionClasses); - modified |= includeOutputType(clazz.fields, - f -> f.descriptor, - includedClasses, - currentVersionClasses); - modified |= includeOutputType(clazz.methods, - m -> m.descriptor, - includedClasses, - currentVersionClasses); - } - } - } while (modified); - - for (ClassDescription clazz : currentVersionClasses) { - if (!includedClasses.contains(clazz.name)) { - continue; - } - - ClassHeaderDescription header = clazz.header.get(0); - - if (header.innerClasses != null) { - Iterator innerClassIt = header.innerClasses.iterator(); - - while(innerClassIt.hasNext()) { - InnerClassInfo ici = innerClassIt.next(); - if (!includedClasses.contains(ici.innerClass)) - innerClassIt.remove(); - } - } - - ClassDescription existing = classes.find(clazz.name, true); - - if (existing != null) { - addClassHeader(existing, header, desc.version); - for (MethodDescription currentMethod : clazz.methods) { - addMethod(existing, currentMethod, desc.version); - } - for (FieldDescription currentField : clazz.fields) { - addField(existing, currentField, desc.version); - } - } else { - classes.add(clazz); - } - } - - for (ModuleDescription module : currentVersionModules.values()) { - ModuleHeaderDescription header = module.header.get(0); - - if (header.innerClasses != null) { - Iterator innerClassIt = - header.innerClasses.iterator(); - - while(innerClassIt.hasNext()) { - InnerClassInfo ici = innerClassIt.next(); - if (!includedClasses.contains(ici.innerClass)) - innerClassIt.remove(); - } - } - - ModuleDescription existing = modules.get(module.name); - - if (existing != null) { - addModuleHeader(existing, header, desc.version); - } else { - modules.put(module.name, module); + AnnotationDescription ad; + ad = new AnnotationDescription(PROPERITARY_ANNOTATION, + Collections.emptyMap()); + ch.classAnnotations.add(ad); } } } + Set includedClasses = new HashSet<>(); + boolean modified; + + do { + modified = false; + + for (ClassDescription clazz : currentVersionClasses) { + ClassHeaderDescription header = clazz.header.get(0); + + if (includeEffectiveAccess(currentVersionClasses, clazz)) { + modified |= include(includedClasses, currentVersionClasses, clazz.name); + } + + if (includedClasses.contains(clazz.name)) { + modified |= include(includedClasses, currentVersionClasses, header.extendsAttr); + for (String i : header.implementsAttr) { + modified |= include(includedClasses, currentVersionClasses, i); + } + + modified |= includeOutputType(Collections.singleton(header), + h -> "", + includedClasses, + currentVersionClasses); + modified |= includeOutputType(clazz.fields, + f -> f.descriptor, + includedClasses, + currentVersionClasses); + modified |= includeOutputType(clazz.methods, + m -> m.descriptor, + includedClasses, + currentVersionClasses); + } + } + } while (modified); + + for (ClassDescription clazz : currentVersionClasses) { + if (!includedClasses.contains(clazz.name)) { + continue; + } + + ClassHeaderDescription header = clazz.header.get(0); + + if (header.innerClasses != null) { + Iterator innerClassIt = header.innerClasses.iterator(); + + while(innerClassIt.hasNext()) { + InnerClassInfo ici = innerClassIt.next(); + if (!includedClasses.contains(ici.innerClass)) + innerClassIt.remove(); + } + } + + ClassDescription existing = classes.find(clazz.name, true); + + if (existing != null) { + addClassHeader(existing, header, version); + for (MethodDescription currentMethod : clazz.methods) { + addMethod(existing, currentMethod, version); + } + for (FieldDescription currentField : clazz.fields) { + addField(existing, currentField, version); + } + } else { + classes.add(clazz); + } + } + + for (ModuleDescription module : currentVersionModules.values()) { + ModuleHeaderDescription header = module.header.get(0); + + if (header.innerClasses != null) { + Iterator innerClassIt = + header.innerClasses.iterator(); + + while(innerClassIt.hasNext()) { + InnerClassInfo ici = innerClassIt.next(); + if (!includedClasses.contains(ici.innerClass)) + innerClassIt.remove(); + } + } + + ModuleDescription existing = modules.get(module.name); + + if (existing != null) { + addModuleHeader(existing, header, version); + } else { + modules.put(module.name, module); + } + } + } + //where: + private static final String PROPERITARY_ANNOTATION = + "Lsun/Proprietary+Annotation;"; + + private void dumpDescriptions(ClassList classes, + Map modules, + List versions, + Path ctDescriptionFile, + String[] args) throws IOException { classes.sort(); Map package2Modules = new HashMap<>(); @@ -1298,46 +1399,52 @@ public class CreateSymbols { .filter(m -> !module2Classes.containsKey(m)) .forEach(m -> module2Classes.put(m, Collections.emptyList())); - Path symbolsFile = descDest.resolve("symbols"); + Files.createDirectories(ctDescriptionFile.getParent()); - Files.createDirectories(symbolsFile.getParent()); + int year = Calendar.getInstance(TimeZone.getTimeZone("UTF"), Locale.ROOT) + .get(Calendar.YEAR); - try (Writer symbolsOut = Files.newBufferedWriter(symbolsFile)) { - Map> outputFiles = new LinkedHashMap<>(); + try (Writer symbolsOut = Files.newBufferedWriter(ctDescriptionFile)) { + Map> outputFiles = new LinkedHashMap<>(); - for (Entry> e : module2Classes.entrySet()) { - for (VersionDescription desc : versions) { - StringWriter data = new StringWriter(); - ModuleDescription module = modules.get(e.getKey()); + for (PlatformInput desc : versions) { + List files = desc.files; - module.write(data, desc.primaryBaseline, desc.version); + if (files == null) { + files = new ArrayList<>(); + for (Entry> e : module2Classes.entrySet()) { + StringWriter data = new StringWriter(); + ModuleDescription module = modules.get(e.getKey()); - for (ClassDescription clazz : e.getValue()) { - clazz.write(data, desc.primaryBaseline, desc.version); - } + module.write(data, desc.basePlatform, desc.version); - Path f = descDest.resolve(e.getKey() + "-" + desc.version + ".sym.txt"); - - String dataString = data.toString(); - - if (!dataString.isEmpty()) { - try (Writer out = Files.newBufferedWriter(f)) { - out.append(DO_NO_MODIFY); - out.write(dataString); + for (ClassDescription clazz : e.getValue()) { + clazz.write(data, desc.basePlatform, desc.version); } - outputFiles.computeIfAbsent(desc, d -> new ArrayList<>()) - .add(f); + String fileName = e.getKey() + "-" + desc.version + ".sym.txt"; + Path f = ctDescriptionFile.getParent().resolve(fileName); + + String dataString = data.toString(); + + if (!dataString.isEmpty()) { + try (Writer out = Files.newBufferedWriter(f)) { + out.append(DO_NO_MODIFY.replace("{YEAR}", String.valueOf(year))); + out.write(dataString); + } + files.add(f.getFileName().toString()); + } } } + + outputFiles.put(desc, files); } - symbolsOut.append(DO_NO_MODIFY); + symbolsOut.append(DO_NO_MODIFY.replace("{YEAR}", "2015, " + year)); symbolsOut.append("#command used to generate this file:\n"); symbolsOut.append("#") .append(CreateSymbols.class.getName()) .append(" ") - .append(Arrays.asList(args) - .stream() + .append(Arrays.stream(args) .collect(Collectors.joining(" "))) .append("\n"); symbolsOut.append("#\n"); @@ -1347,31 +1454,102 @@ public class CreateSymbols { .sorted() .collect(Collectors.joining(":"))) .append("\n"); - for (Entry> versionFileEntry : outputFiles.entrySet()) { + for (Entry> versionFileEntry : outputFiles.entrySet()) { symbolsOut.append("platform version ") .append(versionFileEntry.getKey().version); - if (versionFileEntry.getKey().primaryBaseline != null) { + if (versionFileEntry.getKey().basePlatform != null) { symbolsOut.append(" base ") - .append(versionFileEntry.getKey().primaryBaseline); + .append(versionFileEntry.getKey().basePlatform); } symbolsOut.append(" files ") .append(versionFileEntry.getValue() .stream() - .map(p -> p.getFileName().toString()) + .map(p -> p) .sorted() .collect(Collectors.joining(":"))) .append("\n"); } } } + + public void createIncrementalBaseLine(String ctDescriptionFile, + String excludeFile, + String[] args) throws IOException { + String specVersion = System.getProperty("java.specification.version"); + String currentVersion = + Integer.toString(Integer.parseInt(specVersion), Character.MAX_RADIX); + currentVersion = currentVersion.toUpperCase(Locale.ROOT); + Path ctDescriptionPath = Paths.get(ctDescriptionFile).toAbsolutePath(); + LoadDescriptions data = load(ctDescriptionPath, currentVersion); + + ClassList classes = data.classes; + Map modules = data.modules; + List versions = data.versions; + + ExcludeIncludeList excludeList = + ExcludeIncludeList.create(excludeFile); + + Iterable classBytes = dumpCurrentClasses(); + loadVersionClasses(classes, modules, classBytes, excludeList, currentVersion); + + String baseline; + + if (versions.isEmpty()) { + baseline = null; + } else { + baseline = versions.stream() + .sorted((v1, v2) -> v2.version.compareTo(v1.version)) + .findFirst() + .get() + .version; + } + + versions.add(new PlatformInput(currentVersion, baseline, null)); + dumpDescriptions(classes, modules, versions, ctDescriptionPath, args); + } + + private List dumpCurrentClasses() throws IOException { + JavacTool tool = JavacTool.create(); + Context ctx = new Context(); + String version = System.getProperty("java.specification.version"); + JavacTask task = tool.getTask(null, null, null, + List.of("--release", version), + null, null, ctx); + task.getElements().getTypeElement("java.lang.Object"); + JavaFileManager fm = ctx.get(JavaFileManager.class); + + List data = new ArrayList<>(); + for (Location modLoc : LOCATIONS) { + for (Set module : + fm.listLocationsForModules(modLoc)) { + for (JavaFileManager.Location loc : module) { + Iterable files = + fm.list(loc, + "", + EnumSet.of(Kind.CLASS), + true); + + for (JavaFileObject jfo : files) { + try (InputStream is = jfo.openInputStream(); + InputStream in = + new BufferedInputStream(is)) { + ByteArrayOutputStream baos = + new ByteArrayOutputStream(); + + in.transferTo(baos); + data.add(baos.toByteArray()); + } + } + } + } + } + + return data; + } //where: - private static final String DO_NO_MODIFY = - "# ##########################################################\n" + - "# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ###\n" + - "# ##########################################################\n" + - "#\n"; - private static final String PROPERITARY_ANNOTATION = - "Lsun/Proprietary+Annotation;"; + private static final List LOCATIONS = + List.of(StandardLocation.SYSTEM_MODULES, + StandardLocation.UPGRADE_MODULE_PATH); // //non-final for tests: @@ -2006,11 +2184,11 @@ public class CreateSymbols { signature = reader.attributes.get("signature"); String inClassAnnotations = reader.attributes.get("classAnnotations"); if (inClassAnnotations != null) { - classAnnotations = parseAnnotations(unquote(inClassAnnotations), new int[1]); + classAnnotations = parseAnnotations(inClassAnnotations, new int[1]); } String inRuntimeAnnotations = reader.attributes.get("runtimeAnnotations"); if (inRuntimeAnnotations != null) { - runtimeAnnotations = parseAnnotations(unquote(inRuntimeAnnotations), new int[1]); + runtimeAnnotations = parseAnnotations(inRuntimeAnnotations, new int[1]); } } @@ -2115,6 +2293,7 @@ public class CreateSymbols { ModuleHeaderDescription mhd = new ModuleHeaderDescription(); mhd.read(reader); + mhd.name = name; mhd.versions = version; header.add(mhd); break; @@ -2695,7 +2874,11 @@ public class CreateSymbols { name = reader.attributes.get("name"); descriptor = reader.attributes.get("descriptor"); - thrownTypes = deserializeList(reader.attributes.get("thrownTypes")); + String thrownTypesValue = reader.attributes.get("thrownTypes"); + + if (thrownTypesValue != null) { + thrownTypes = deserializeList(thrownTypesValue); + } String inAnnotationDefaultValue = reader.attributes.get("annotationDefaultValue"); @@ -2803,9 +2986,9 @@ public class CreateSymbols { if (inConstantValue != null) { switch (descriptor) { case "Z": constantValue = "true".equals(inConstantValue); break; - case "B": constantValue = Byte.parseByte(inConstantValue); break; + case "B": constantValue = Integer.parseInt(inConstantValue); break; case "C": constantValue = inConstantValue.charAt(0); break; - case "S": constantValue = Short.parseShort(inConstantValue); break; + case "S": constantValue = Integer.parseInt(inConstantValue); break; case "I": constantValue = Integer.parseInt(inConstantValue); break; case "J": constantValue = Long.parseLong(inConstantValue); break; case "F": constantValue = Float.parseFloat(inConstantValue); break; @@ -3141,7 +3324,7 @@ public class CreateSymbols { serialized = unquote ? unquote(serialized) : serialized; if (serialized == null) return new ArrayList<>(); - return new ArrayList<>(Arrays.asList(serialized.split(","))); + return new ArrayList<>(List.of(serialized.split(","))); } private static String quote(String value, boolean quoteQuotes) { @@ -3291,7 +3474,7 @@ public class CreateSymbols { } switch (args[0]) { - case "build-description": + case "build-description": { if (args.length < 3) { help(); return ; @@ -3332,6 +3515,16 @@ public class CreateSymbols { descDest, args); break; + } + case "build-description-incremental": { + if (args.length != 3) { + help(); + return ; + } + + new CreateSymbols().createIncrementalBaseLine(args[1], args[2], args); + break; + } case "build-ctsym": if (args.length != 3) { help(); diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/TransitiveDependencies.java b/make/langtools/src/classes/build/tools/symbolgenerator/TransitiveDependencies.java index 3734204d7b9..e197bea7fc9 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/TransitiveDependencies.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/TransitiveDependencies.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -26,56 +26,67 @@ package build.tools.symbolgenerator; import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayDeque; import java.util.Arrays; +import java.util.Deque; import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; import javax.lang.model.element.ModuleElement.RequiresDirective; import javax.lang.model.util.Elements; import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Source; import com.sun.tools.javac.code.Symbol.ModuleSymbol; +import com.sun.tools.javac.jvm.Target; /** - * Print reflexive transitive closure of the given modules along their requires transitive edges. + * Write reflexive transitive closure of the given modules along their requires transitive edges into + * file /system-modules in the specified directory. */ public class TransitiveDependencies { private static void help() { - System.err.println("java TransitiveDependencies "); + System.err.println("java TransitiveDependencies "); } public static void main(String... args) throws IOException { - if (args.length < 1) { + if (args.length < 2) { help(); return ; } JavaCompiler compiler = JavacTool.create(); - List options = Arrays.asList("-source", "10", - "-target", "10", - "-proc:only", - "--system", "none", - "--module-source-path", args[0], - "--add-modules", Arrays.stream(args) - .skip(1) - .collect(Collectors.joining(","))); - List jlObjectList = Arrays.asList("java.lang.Object"); + List options = List.of("-source", Source.DEFAULT.name, + "-target", Target.DEFAULT.name, + "-proc:only", + "--system", "none", + "--module-source-path", args[1], + "--add-modules", Arrays.stream(args) + .skip(2) + .collect(Collectors.joining(","))); + List jlObjectList = List.of("java.lang.Object"); JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, null, null, options, jlObjectList, null); task.enter(); Elements elements = task.getElements(); - List todo = new LinkedList<>(); - Arrays.stream(args).skip(1).forEach(todo::add); + Deque todo = new ArrayDeque<>(); + Arrays.stream(args).skip(2).forEach(todo::add); Set allModules = new HashSet<>(); while (!todo.isEmpty()) { - String current = todo.remove(0); + String current = todo.removeFirst(); if (!allModules.add(current)) continue; @@ -89,7 +100,7 @@ public class TransitiveDependencies { //use the internal structure to avoid unnecesarily completing the symbol using the UsesProvidesVisitor: for (RequiresDirective rd : mod.requires) { if (rd.isTransitive()) { - todo.add(rd.getDependency().getQualifiedName().toString()); + todo.offerLast(rd.getDependency().getQualifiedName().toString()); } } } @@ -97,9 +108,20 @@ public class TransitiveDependencies { allModules.add("java.base"); allModules.add("jdk.unsupported"); - allModules.stream() - .sorted() - .forEach(System.out::println); + String version = + Integer.toString(Integer.parseInt(Source.DEFAULT.name), Character.MAX_RADIX); + version = version.toUpperCase(Locale.ROOT); + + Path targetFile = Paths.get(args[0]).resolve(version).resolve("system-modules"); + + Files.createDirectories(targetFile.getParent()); + + try (Writer w = Files.newBufferedWriter(targetFile); + PrintWriter out = new PrintWriter(w)) { + allModules.stream() + .sorted() + .forEach(out::println); + } } } diff --git a/test/langtools/tools/javac/options/release/ReleaseOptionCurrent.java b/test/langtools/tools/javac/options/release/ReleaseOptionCurrent.java new file mode 100644 index 00000000000..76b20d21ca6 --- /dev/null +++ b/test/langtools/tools/javac/options/release/ReleaseOptionCurrent.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, 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 8202387 + * @summary Verify that javac can handle --release + * @modules jdk.compiler/com.sun.tools.javac.code + */ + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import com.sun.tools.javac.code.Source; + +public class ReleaseOptionCurrent { + public static void main(String... args) throws IOException { + new ReleaseOptionCurrent().run(); + } + + void run() throws IOException { + String lineSep = System.getProperty("line.separator"); + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { + Iterable input = + fm.getJavaFileObjects(System.getProperty("test.src") + "/ReleaseOption.java"); + List options = Arrays.asList("--release", Source.DEFAULT.name); + + boolean result = compiler.getTask(null, fm, null, options, null, input).call(); + if (!result) { + throw new AssertionError("Compilation failed unexpectedly."); + } + } + } +} diff --git a/test/langtools/tools/javac/preview/PreviewOptionTest.java b/test/langtools/tools/javac/preview/PreviewOptionTest.java index 80db6ba595c..fe880738ad5 100644 --- a/test/langtools/tools/javac/preview/PreviewOptionTest.java +++ b/test/langtools/tools/javac/preview/PreviewOptionTest.java @@ -54,8 +54,8 @@ public class PreviewOptionTest { .filter(s -> s.compareTo(Source.MIN) >= 0) .collect(Collectors.toList()); - versionsToTest.stream().forEach(this::testWithSourceFlag); - versionsToTest.stream().forEach(this::testWithReleaseFlag); + versionsToTest.forEach(this::testWithSourceFlag); + versionsToTest.forEach(this::testWithReleaseFlag); if (errors > 0) throw new Exception(errors + " errors occurred"); @@ -70,9 +70,7 @@ public class PreviewOptionTest { } void testWithReleaseFlag(Source release) { - //Todo: the condition below should say "release != Source.DEFAULT", but we can't do that - //since --release 11 is not supported yet. - testInternal(null, release, true); + testInternal(null, release, release != Source.DEFAULT); } void testInternal(Source source, Source release, boolean shouldFail) { From 6869c08e6aa394567d9fb1a41877ebe6eea0a56b Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Mon, 7 May 2018 18:23:59 +0800 Subject: [PATCH 14/40] 8202291: java/rmi/Naming/LookupIPv6.java failed with Connection refused Reviewed-by: clanger --- test/jdk/java/rmi/Naming/LookupIPv6.java | 26 +++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/test/jdk/java/rmi/Naming/LookupIPv6.java b/test/jdk/java/rmi/Naming/LookupIPv6.java index ea8d7d451e1..4db080b977a 100644 --- a/test/jdk/java/rmi/Naming/LookupIPv6.java +++ b/test/jdk/java/rmi/Naming/LookupIPv6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2018, 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 @@ -30,16 +30,16 @@ * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary + * @build RegistryVM * @run main/othervm -Djava.net.preferIPv6Addresses=true LookupIPv6 */ +import java.io.Serializable; import java.net.InetAddress; import java.net.Inet6Address; import java.net.MalformedURLException; import java.rmi.Naming; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; +import java.rmi.Remote; public class LookupIPv6 { public static void main(String[] args) throws Exception { @@ -67,19 +67,21 @@ public class LookupIPv6 { * an Inet6Address since this test is run with * -Djava.net.preferIPv6Addresses=true. */ - int port = TestLibrary.getUnusedRandomPort(); InetAddress localAddr = InetAddress.getAllByName(null)[0]; if (localAddr instanceof Inet6Address) { System.out.println("IPv6 detected"); - Registry reg; + RegistryVM rvm = RegistryVM.createRegistryVM(); try { - reg = LocateRegistry.createRegistry(port); - } catch (Exception ex) { - reg = LocateRegistry.getRegistry(); + rvm.start(); + String name = String.format("rmi://[%s]:%d/foo", + localAddr.getHostAddress(), rvm.getPort()); + Naming.rebind(name, new R()); + Naming.lookup(name); + } finally { + rvm.cleanup(); } - reg.rebind("foo", reg); - Naming.lookup(String.format("rmi://[%s]:%d/foo", - localAddr.getHostAddress(), port)); } } + + private static class R implements Remote, Serializable { } } From 71a38a4720a64178ed668f178d143a186b3f76bd Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Mon, 7 May 2018 12:28:11 +0200 Subject: [PATCH 15/40] 8202080: Introduce ordering semantics for Atomic::add and other RMW atomics Reviewed-by: lucy, rehn, dholmes --- src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp | 168 ++++++++++-------- src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp | 24 +-- .../os_cpu/bsd_zero/atomic_bsd_zero.hpp | 20 ++- .../linux_aarch64/atomic_linux_aarch64.hpp | 9 +- .../os_cpu/linux_arm/atomic_linux_arm.hpp | 20 ++- .../os_cpu/linux_ppc/atomic_linux_ppc.hpp | 103 ++++++----- .../os_cpu/linux_s390/atomic_linux_s390.hpp | 32 +++- .../os_cpu/linux_sparc/atomic_linux_sparc.hpp | 20 ++- .../os_cpu/linux_x86/atomic_linux_x86.hpp | 25 +-- .../os_cpu/linux_zero/atomic_linux_zero.hpp | 20 ++- .../solaris_sparc/atomic_solaris_sparc.hpp | 12 +- .../os_cpu/solaris_x86/atomic_solaris_x86.hpp | 22 ++- .../os_cpu/windows_x86/atomic_windows_x86.hpp | 27 +-- src/hotspot/share/runtime/atomic.hpp | 117 ++++++------ src/hotspot/share/utilities/globalCounter.cpp | 3 +- 15 files changed, 354 insertions(+), 268 deletions(-) diff --git a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp b/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp index ec124e8e2a6..a5afdd2b689 100644 --- a/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp +++ b/src/hotspot/os_cpu/aix_ppc/atomic_aix_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 SAP SE. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. 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 @@ -26,8 +26,8 @@ #ifndef OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_HPP #define OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_HPP -#ifndef _LP64 -#error "Atomic currently only impleneted for PPC64" +#ifndef PPC64 +#error "Atomic currently only implemented for PPC64" #endif #include "utilities/debug.hpp" @@ -35,39 +35,39 @@ // Implementation of class atomic // -// machine barrier instructions: +// machine barrier instructions: // -// - ppc_sync two-way memory barrier, aka fence -// - ppc_lwsync orders Store|Store, -// Load|Store, -// Load|Load, -// but not Store|Load -// - ppc_eieio orders memory accesses for device memory (only) -// - ppc_isync invalidates speculatively executed instructions -// From the POWER ISA 2.06 documentation: -// "[...] an isync instruction prevents the execution of -// instructions following the isync until instructions -// preceding the isync have completed, [...]" -// From IBM's AIX assembler reference: -// "The isync [...] instructions causes the processor to -// refetch any instructions that might have been fetched -// prior to the isync instruction. The instruction isync -// causes the processor to wait for all previous instructions -// to complete. Then any instructions already fetched are -// discarded and instruction processing continues in the -// environment established by the previous instructions." +// - sync two-way memory barrier, aka fence +// - lwsync orders Store|Store, +// Load|Store, +// Load|Load, +// but not Store|Load +// - eieio orders memory accesses for device memory (only) +// - isync invalidates speculatively executed instructions +// From the POWER ISA 2.06 documentation: +// "[...] an isync instruction prevents the execution of +// instructions following the isync until instructions +// preceding the isync have completed, [...]" +// From IBM's AIX assembler reference: +// "The isync [...] instructions causes the processor to +// refetch any instructions that might have been fetched +// prior to the isync instruction. The instruction isync +// causes the processor to wait for all previous instructions +// to complete. Then any instructions already fetched are +// discarded and instruction processing continues in the +// environment established by the previous instructions." // -// semantic barrier instructions: -// (as defined in orderAccess.hpp) +// semantic barrier instructions: +// (as defined in orderAccess.hpp) // -// - ppc_release orders Store|Store, (maps to ppc_lwsync) -// Load|Store -// - ppc_acquire orders Load|Store, (maps to ppc_lwsync) -// Load|Load -// - ppc_fence orders Store|Store, (maps to ppc_sync) -// Load|Store, -// Load|Load, -// Store|Load +// - release orders Store|Store, (maps to lwsync) +// Load|Store +// - acquire orders Load|Store, (maps to lwsync) +// Load|Load +// - fence orders Store|Store, (maps to sync) +// Load|Store, +// Load|Load, +// Store|Load // #define strasm_sync "\n sync \n" @@ -79,80 +79,105 @@ #define strasm_nobarrier "" #define strasm_nobarrier_clobber_memory "" +inline void pre_membar(atomic_memory_order order) { + switch (order) { + case memory_order_relaxed: + case memory_order_acquire: break; + case memory_order_release: + case memory_order_acq_rel: __asm__ __volatile__ (strasm_lwsync); break; + default /*conservative*/ : __asm__ __volatile__ (strasm_sync); break; + } +} + +inline void post_membar(atomic_memory_order order) { + switch (order) { + case memory_order_relaxed: + case memory_order_release: break; + case memory_order_acquire: + case memory_order_acq_rel: __asm__ __volatile__ (strasm_isync); break; + default /*conservative*/ : __asm__ __volatile__ (strasm_sync); break; + } +} + + template struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); D result; + pre_membar(order); + __asm__ __volatile__ ( - strasm_lwsync "1: lwarx %0, 0, %2 \n" " add %0, %0, %1 \n" " stwcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_isync : /*%0*/"=&r" (result) : /*%1*/"r" (add_value), /*%2*/"r" (dest) : "cc", "memory" ); + post_membar(order); + return result; } template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); D result; + pre_membar(order); + __asm__ __volatile__ ( - strasm_lwsync "1: ldarx %0, 0, %2 \n" " add %0, %0, %1 \n" " stdcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_isync : /*%0*/"=&r" (result) : /*%1*/"r" (add_value), /*%2*/"r" (dest) : "cc", "memory" ); + post_membar(order); + return result; } template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { - STATIC_ASSERT(4 == sizeof(T)); + T volatile* dest, + atomic_memory_order order) const { // Note that xchg doesn't necessarily do an acquire // (see synchronizer.cpp). T old_value; const uint64_t zero = 0; + pre_membar(order); + __asm__ __volatile__ ( - /* lwsync */ - strasm_lwsync /* atomic loop */ "1: \n" " lwarx %[old_value], %[dest], %[zero] \n" " stwcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" - /* isync */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -168,13 +193,16 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, "memory" ); + post_membar(order); + return old_value; } template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); // Note that xchg doesn't necessarily do an acquire // (see synchronizer.cpp). @@ -182,16 +210,14 @@ inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, T old_value; const uint64_t zero = 0; + pre_membar(order); + __asm__ __volatile__ ( - /* lwsync */ - strasm_lwsync /* atomic loop */ "1: \n" " ldarx %[old_value], %[dest], %[zero] \n" " stdcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" - /* isync */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -207,33 +233,17 @@ inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, "memory" ); + post_membar(order); + return old_value; } -inline void cmpxchg_pre_membar(cmpxchg_memory_order order) { - if (order != memory_order_relaxed) { - __asm__ __volatile__ ( - /* fence */ - strasm_sync - ); - } -} - -inline void cmpxchg_post_membar(cmpxchg_memory_order order) { - if (order != memory_order_relaxed) { - __asm__ __volatile__ ( - /* fence */ - strasm_sync - ); - } -} - template<> template inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(1 == sizeof(T)); // Note that cmpxchg guarantees a two-way memory barrier across @@ -254,7 +264,7 @@ inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, unsigned int old_value, value32; - cmpxchg_pre_membar(order); + pre_membar(order); __asm__ __volatile__ ( /* simple guard */ @@ -293,7 +303,7 @@ inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, "memory" ); - cmpxchg_post_membar(order); + post_membar(order); return PrimitiveConversions::cast((unsigned char)old_value); } @@ -303,7 +313,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); // Note that cmpxchg guarantees a two-way memory barrier across @@ -313,7 +323,7 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T old_value; const uint64_t zero = 0; - cmpxchg_pre_membar(order); + pre_membar(order); __asm__ __volatile__ ( /* simple guard */ @@ -343,7 +353,7 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, "memory" ); - cmpxchg_post_membar(order); + post_membar(order); return old_value; } @@ -353,7 +363,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); // Note that cmpxchg guarantees a two-way memory barrier across @@ -363,7 +373,7 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T old_value; const uint64_t zero = 0; - cmpxchg_pre_membar(order); + pre_membar(order); __asm__ __volatile__ ( /* simple guard */ @@ -393,7 +403,7 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, "memory" ); - cmpxchg_post_membar(order); + post_membar(order); return old_value; } diff --git a/src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp b/src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp index 40021fa9a65..9e8302b9f2d 100644 --- a/src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp +++ b/src/hotspot/os_cpu/bsd_x86/atomic_bsd_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, 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 @@ -32,12 +32,13 @@ struct Atomic::PlatformAdd : Atomic::FetchAndAdd > { template - D fetch_and_add(I add_value, D volatile* dest) const; + D fetch_and_add(I add_value, D volatile* dest, atomic_memory_order /* order */) const; }; template<> template -inline D Atomic::PlatformAdd<4>::fetch_and_add(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::fetch_and_add(I add_value, D volatile* dest, + atomic_memory_order /* order */) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); D old_value; @@ -51,7 +52,8 @@ inline D Atomic::PlatformAdd<4>::fetch_and_add(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order /* order */) const { STATIC_ASSERT(4 == sizeof(T)); __asm__ volatile ( "xchgl (%2),%0" : "=r" (exchange_value) @@ -65,7 +67,7 @@ template inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order /* order */) const { + atomic_memory_order /* order */) const { STATIC_ASSERT(1 == sizeof(T)); __asm__ volatile ( "lock cmpxchgb %1,(%3)" : "=a" (exchange_value) @@ -79,7 +81,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order /* order */) const { + atomic_memory_order /* order */) const { STATIC_ASSERT(4 == sizeof(T)); __asm__ volatile ( "lock cmpxchgl %1,(%3)" : "=a" (exchange_value) @@ -91,7 +93,8 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, #ifdef AMD64 template<> template -inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest, + atomic_memory_order /* order */) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); D old_value; @@ -105,7 +108,8 @@ inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order /* order */) const { STATIC_ASSERT(8 == sizeof(T)); __asm__ __volatile__ ("xchgq (%2),%0" : "=r" (exchange_value) @@ -119,7 +123,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order /* order */) const { + atomic_memory_order /* order */) const { STATIC_ASSERT(8 == sizeof(T)); __asm__ __volatile__ ( "lock cmpxchgq %1,(%3)" : "=a" (exchange_value) @@ -141,7 +145,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order /* order */) const { STATIC_ASSERT(8 == sizeof(T)); return cmpxchg_using_helper(_Atomic_cmpxchg_long, exchange_value, dest, compare_value); } diff --git a/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp b/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp index 82027fa3188..c699918f2f8 100644 --- a/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp +++ b/src/hotspot/os_cpu/bsd_zero/atomic_bsd_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2011, 2015, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -164,12 +164,13 @@ struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); @@ -186,7 +187,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); @@ -196,7 +198,8 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); #ifdef ARM return xchg_using_helper(arm_lock_test_and_set, exchange_value, dest); @@ -222,7 +225,8 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); T result = __sync_lock_test_and_set (dest, exchange_value); __sync_synchronize(); @@ -238,7 +242,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); #ifdef ARM return cmpxchg_using_helper(arm_compare_and_swap, exchange_value, dest, compare_value); @@ -256,7 +260,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); return __sync_val_compare_and_swap(dest, compare_value, exchange_value); } diff --git a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp index e4076609924..e1f59bb43e5 100644 --- a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -39,7 +39,7 @@ struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const { + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const { return __sync_add_and_fetch(dest, add_value); } }; @@ -47,7 +47,8 @@ struct Atomic::PlatformAdd template template inline T Atomic::PlatformXchg::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(byte_size == sizeof(T)); T res = __sync_lock_test_and_set(dest, exchange_value); FULL_MEM_BARRIER; @@ -59,7 +60,7 @@ template inline T Atomic::PlatformCmpxchg::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(byte_size == sizeof(T)); if (order == memory_order_relaxed) { T value = compare_value; diff --git a/src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp b/src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp index 0e675007c0f..90441901327 100644 --- a/src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp +++ b/src/hotspot/os_cpu/linux_arm/atomic_linux_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2018, 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 @@ -81,12 +81,13 @@ struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); #ifdef AARCH64 @@ -110,7 +111,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co #ifdef AARCH64 template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); D val; @@ -131,7 +133,8 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); #ifdef AARCH64 T old_val; @@ -154,7 +157,8 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); T old_val; int tmp; @@ -200,7 +204,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); #ifdef AARCH64 T rv; @@ -230,7 +234,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); #ifdef AARCH64 T rv; diff --git a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp b/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp index 764243960cc..2d008a1ff6d 100644 --- a/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp +++ b/src/hotspot/os_cpu/linux_ppc/atomic_linux_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 SAP SE. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. 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 @@ -77,79 +77,105 @@ #define strasm_nobarrier "" #define strasm_nobarrier_clobber_memory "" +inline void pre_membar(atomic_memory_order order) { + switch (order) { + case memory_order_relaxed: + case memory_order_acquire: break; + case memory_order_release: + case memory_order_acq_rel: __asm__ __volatile__ (strasm_lwsync); break; + default /*conservative*/ : __asm__ __volatile__ (strasm_sync); break; + } +} + +inline void post_membar(atomic_memory_order order) { + switch (order) { + case memory_order_relaxed: + case memory_order_release: break; + case memory_order_acquire: + case memory_order_acq_rel: __asm__ __volatile__ (strasm_isync); break; + default /*conservative*/ : __asm__ __volatile__ (strasm_sync); break; + } +} + + template struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); D result; + pre_membar(order); + __asm__ __volatile__ ( - strasm_lwsync "1: lwarx %0, 0, %2 \n" " add %0, %0, %1 \n" " stwcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_isync : /*%0*/"=&r" (result) : /*%1*/"r" (add_value), /*%2*/"r" (dest) : "cc", "memory" ); + post_membar(order); + return result; } template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); D result; + pre_membar(order); + __asm__ __volatile__ ( - strasm_lwsync "1: ldarx %0, 0, %2 \n" " add %0, %0, %1 \n" " stdcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_isync : /*%0*/"=&r" (result) : /*%1*/"r" (add_value), /*%2*/"r" (dest) : "cc", "memory" ); + post_membar(order); + return result; } template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { // Note that xchg doesn't necessarily do an acquire // (see synchronizer.cpp). T old_value; const uint64_t zero = 0; + pre_membar(order); + __asm__ __volatile__ ( - /* lwsync */ - strasm_lwsync /* atomic loop */ "1: \n" " lwarx %[old_value], %[dest], %[zero] \n" " stwcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" - /* isync */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -165,13 +191,16 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, "memory" ); + post_membar(order); + return old_value; } template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); // Note that xchg doesn't necessarily do an acquire // (see synchronizer.cpp). @@ -179,16 +208,14 @@ inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, T old_value; const uint64_t zero = 0; + pre_membar(order); + __asm__ __volatile__ ( - /* lwsync */ - strasm_lwsync /* atomic loop */ "1: \n" " ldarx %[old_value], %[dest], %[zero] \n" " stdcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" - /* isync */ - strasm_sync /* exit */ "2: \n" /* out */ @@ -204,33 +231,17 @@ inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, "memory" ); + post_membar(order); + return old_value; } -inline void cmpxchg_pre_membar(cmpxchg_memory_order order) { - if (order != memory_order_relaxed) { - __asm__ __volatile__ ( - /* fence */ - strasm_sync - ); - } -} - -inline void cmpxchg_post_membar(cmpxchg_memory_order order) { - if (order != memory_order_relaxed) { - __asm__ __volatile__ ( - /* fence */ - strasm_sync - ); - } -} - template<> template inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(1 == sizeof(T)); // Note that cmpxchg guarantees a two-way memory barrier across @@ -251,7 +262,7 @@ inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, unsigned int old_value, value32; - cmpxchg_pre_membar(order); + pre_membar(order); __asm__ __volatile__ ( /* simple guard */ @@ -290,7 +301,7 @@ inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, "memory" ); - cmpxchg_post_membar(order); + post_membar(order); return PrimitiveConversions::cast((unsigned char)old_value); } @@ -300,7 +311,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); // Note that cmpxchg guarantees a two-way memory barrier across @@ -310,7 +321,7 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T old_value; const uint64_t zero = 0; - cmpxchg_pre_membar(order); + pre_membar(order); __asm__ __volatile__ ( /* simple guard */ @@ -340,7 +351,7 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, "memory" ); - cmpxchg_post_membar(order); + post_membar(order); return old_value; } @@ -350,7 +361,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); // Note that cmpxchg guarantees a two-way memory barrier across @@ -360,7 +371,7 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T old_value; const uint64_t zero = 0; - cmpxchg_pre_membar(order); + pre_membar(order); __asm__ __volatile__ ( /* simple guard */ @@ -390,7 +401,7 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, "memory" ); - cmpxchg_post_membar(order); + post_membar(order); return old_value; } diff --git a/src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp b/src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp index 5821bb018c3..8462f4b6da0 100644 --- a/src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp +++ b/src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018 SAP SE. 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 @@ -68,23 +68,31 @@ // The return value of the method is the value that was successfully stored. At the // time the caller receives back control, the value in memory may have changed already. +// New atomic operations only include specific-operand-serialization, not full +// memory barriers. We can use the Fast-BCR-Serialization Facility for them. +inline void z196_fast_sync() { + __asm__ __volatile__ ("bcr 14, 0" : : : "memory"); +} + template struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I inc, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I inc, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); D old, upd; if (VM_Version::has_LoadAndALUAtomicV1()) { + if (order == memory_order_conservative) { z196_fast_sync(); } __asm__ __volatile__ ( " LGFR 0,%[inc] \n\t" // save increment " LA 3,%[mem] \n\t" // force data address into ARG2 @@ -106,6 +114,7 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I inc, D volatile* dest) const { //---< clobbered >--- : "cc", "r0", "r2", "r3", "memory" ); + if (order == memory_order_conservative) { z196_fast_sync(); } } else { __asm__ __volatile__ ( " LLGF %[old],%[mem] \n\t" // get old value @@ -129,13 +138,15 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I inc, D volatile* dest) const { template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I inc, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I inc, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); D old, upd; if (VM_Version::has_LoadAndALUAtomicV1()) { + if (order == memory_order_conservative) { z196_fast_sync(); } __asm__ __volatile__ ( " LGR 0,%[inc] \n\t" // save increment " LA 3,%[mem] \n\t" // force data address into ARG2 @@ -157,6 +168,7 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I inc, D volatile* dest) const { //---< clobbered >--- : "cc", "r0", "r2", "r3", "memory" ); + if (order == memory_order_conservative) { z196_fast_sync(); } } else { __asm__ __volatile__ ( " LG %[old],%[mem] \n\t" // get old value @@ -197,7 +209,8 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I inc, D volatile* dest) const { template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order unused) const { STATIC_ASSERT(4 == sizeof(T)); T old; @@ -220,7 +233,8 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order unused) const { STATIC_ASSERT(8 == sizeof(T)); T old; @@ -278,7 +292,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T xchg_val, T volatile* dest, T cmp_val, - cmpxchg_memory_order unused) const { + atomic_memory_order unused) const { STATIC_ASSERT(4 == sizeof(T)); T old; @@ -302,7 +316,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T xchg_val, T volatile* dest, T cmp_val, - cmpxchg_memory_order unused) const { + atomic_memory_order unused) const { STATIC_ASSERT(8 == sizeof(T)); T old; diff --git a/src/hotspot/os_cpu/linux_sparc/atomic_linux_sparc.hpp b/src/hotspot/os_cpu/linux_sparc/atomic_linux_sparc.hpp index 46a1268347a..f572d1b10a2 100644 --- a/src/hotspot/os_cpu/linux_sparc/atomic_linux_sparc.hpp +++ b/src/hotspot/os_cpu/linux_sparc/atomic_linux_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, 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 @@ -32,12 +32,13 @@ struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); @@ -59,7 +60,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); @@ -82,7 +84,8 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); T rv = exchange_value; __asm__ volatile( @@ -96,7 +99,8 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); T rv = exchange_value; __asm__ volatile( @@ -123,7 +127,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); T rv; __asm__ volatile( @@ -139,7 +143,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); T rv; __asm__ volatile( diff --git a/src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp b/src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp index 882ec3a5a9e..f4f8d9898c1 100644 --- a/src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp +++ b/src/hotspot/os_cpu/linux_x86/atomic_linux_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, 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 @@ -32,12 +32,13 @@ struct Atomic::PlatformAdd : Atomic::FetchAndAdd > { template - D fetch_and_add(I add_value, D volatile* dest) const; + D fetch_and_add(I add_value, D volatile* dest, atomic_memory_order order) const; }; template<> template -inline D Atomic::PlatformAdd<4>::fetch_and_add(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::fetch_and_add(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); D old_value; @@ -51,7 +52,8 @@ inline D Atomic::PlatformAdd<4>::fetch_and_add(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); __asm__ volatile ( "xchgl (%2),%0" : "=r" (exchange_value) @@ -65,7 +67,7 @@ template inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order /* order */) const { + atomic_memory_order /* order */) const { STATIC_ASSERT(1 == sizeof(T)); __asm__ volatile ("lock cmpxchgb %1,(%3)" : "=a" (exchange_value) @@ -79,7 +81,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order /* order */) const { + atomic_memory_order /* order */) const { STATIC_ASSERT(4 == sizeof(T)); __asm__ volatile ("lock cmpxchgl %1,(%3)" : "=a" (exchange_value) @@ -92,7 +94,8 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, template<> template -inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); D old_value; @@ -105,8 +108,8 @@ inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest) co template<> template -inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { +inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); __asm__ __volatile__ ("xchgq (%2),%0" : "=r" (exchange_value) @@ -120,7 +123,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order /* order */) const { + atomic_memory_order /* order */) const { STATIC_ASSERT(8 == sizeof(T)); __asm__ __volatile__ ("lock cmpxchgq %1,(%3)" : "=a" (exchange_value) @@ -142,7 +145,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); return cmpxchg_using_helper(_Atomic_cmpxchg_long, exchange_value, dest, compare_value); } diff --git a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp index 8a088d6444e..2ab748c9785 100644 --- a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp +++ b/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2011, 2015, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -35,12 +35,13 @@ struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); @@ -49,7 +50,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); return __sync_add_and_fetch(dest, add_value); @@ -58,7 +60,8 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); // __sync_lock_test_and_set is a bizarrely named atomic exchange // operation. Note that some platforms only support this with the @@ -76,7 +79,8 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); T result = __sync_lock_test_and_set (dest, exchange_value); __sync_synchronize(); @@ -92,7 +96,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); return __sync_val_compare_and_swap(dest, compare_value, exchange_value); } @@ -102,7 +106,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); return __sync_val_compare_and_swap(dest, compare_value, exchange_value); } diff --git a/src/hotspot/os_cpu/solaris_sparc/atomic_solaris_sparc.hpp b/src/hotspot/os_cpu/solaris_sparc/atomic_solaris_sparc.hpp index 6a96abe835f..0ca8811771a 100644 --- a/src/hotspot/os_cpu/solaris_sparc/atomic_solaris_sparc.hpp +++ b/src/hotspot/os_cpu/solaris_sparc/atomic_solaris_sparc.hpp @@ -31,7 +31,7 @@ template struct Atomic::PlatformAdd { template - inline D operator()(I add_value, D volatile* dest) const { + inline D operator()(I add_value, D volatile* dest, atomic_memory_order order) const { D old_value = *dest; while (true) { D new_value = old_value + add_value; @@ -46,7 +46,8 @@ struct Atomic::PlatformAdd { template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); __asm__ volatile ( "swap [%2],%0" : "=r" (exchange_value) @@ -58,7 +59,8 @@ inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); T old_value = *dest; while (true) { @@ -78,7 +80,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); T rv; __asm__ volatile( @@ -94,7 +96,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); T rv; __asm__ volatile( diff --git a/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp b/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp index 7844a146a32..ebb0d8325cc 100644 --- a/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp +++ b/src/hotspot/os_cpu/solaris_x86/atomic_solaris_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, 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 @@ -45,13 +45,14 @@ struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; // Not using add_using_helper; see comment for cmpxchg. template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); return PrimitiveConversions::cast( @@ -62,7 +63,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co // Not using add_using_helper; see comment for cmpxchg. template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(I)); STATIC_ASSERT(8 == sizeof(D)); return PrimitiveConversions::cast( @@ -73,7 +75,8 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); return PrimitiveConversions::cast( _Atomic_xchg(PrimitiveConversions::cast(exchange_value), @@ -85,7 +88,8 @@ extern "C" int64_t _Atomic_xchg_long(int64_t exchange_value, volatile int64_t* d template<> template inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); return PrimitiveConversions::cast( _Atomic_xchg_long(PrimitiveConversions::cast(exchange_value), @@ -103,7 +107,7 @@ template inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(1 == sizeof(T)); return PrimitiveConversions::cast( _Atomic_cmpxchg_byte(PrimitiveConversions::cast(exchange_value), @@ -116,7 +120,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); return PrimitiveConversions::cast( _Atomic_cmpxchg(PrimitiveConversions::cast(exchange_value), @@ -129,7 +133,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); return PrimitiveConversions::cast( _Atomic_cmpxchg_long(PrimitiveConversions::cast(exchange_value), diff --git a/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp b/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp index 293e051ffcf..7872c9b6fd4 100644 --- a/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp +++ b/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, 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 @@ -47,19 +47,21 @@ struct Atomic::PlatformAdd : Atomic::AddAndFetch > { template - D add_and_fetch(I add_value, D volatile* dest) const; + D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const; }; #ifdef AMD64 template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { return add_using_helper(os::atomic_add_func, add_value, dest); } template<> template -inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { return add_using_helper(os::atomic_add_long_func, add_value, dest); } @@ -67,7 +69,8 @@ inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) co template<> \ template \ inline T Atomic::PlatformXchg::operator()(T exchange_value, \ - T volatile* dest) const { \ + T volatile* dest, \ + atomic_memory_order order) const { \ STATIC_ASSERT(ByteSize == sizeof(T)); \ return xchg_using_helper(StubName, exchange_value, dest); \ } @@ -83,7 +86,7 @@ DEFINE_STUB_XCHG(8, int64_t, os::atomic_xchg_long_func) inline T Atomic::PlatformCmpxchg::operator()(T exchange_value, \ T volatile* dest, \ T compare_value, \ - cmpxchg_memory_order order) const { \ + atomic_memory_order order) const { \ STATIC_ASSERT(ByteSize == sizeof(T)); \ return cmpxchg_using_helper(StubName, exchange_value, dest, compare_value); \ } @@ -98,7 +101,8 @@ DEFINE_STUB_CMPXCHG(8, int64_t, os::atomic_cmpxchg_long_func) template<> template -inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const { +inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(I)); STATIC_ASSERT(4 == sizeof(D)); __asm { @@ -113,7 +117,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co template<> template inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, - T volatile* dest) const { + T volatile* dest, + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); // alternative for InterlockedExchange __asm { @@ -128,7 +133,7 @@ template inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(1 == sizeof(T)); // alternative for InterlockedCompareExchange __asm { @@ -144,7 +149,7 @@ template inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(4 == sizeof(T)); // alternative for InterlockedCompareExchange __asm { @@ -160,7 +165,7 @@ template inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(8 == sizeof(T)); int32_t ex_lo = (int32_t)exchange_value; int32_t ex_hi = *( ((int32_t*)&exchange_value) + 1 ); diff --git a/src/hotspot/share/runtime/atomic.hpp b/src/hotspot/share/runtime/atomic.hpp index 9fa19346749..89d4433be4a 100644 --- a/src/hotspot/share/runtime/atomic.hpp +++ b/src/hotspot/share/runtime/atomic.hpp @@ -37,9 +37,14 @@ #include "utilities/align.hpp" #include "utilities/macros.hpp" -enum cmpxchg_memory_order { - memory_order_relaxed, - // Use value which doesn't interfere with C++2011. We need to be more conservative. +enum atomic_memory_order { + // The modes that align with C++11 are intended to + // follow the same semantics. + memory_order_relaxed = 0, + memory_order_acquire = 2, + memory_order_release = 3, + memory_order_acq_rel = 4, + // Strong two-way memory barrier. memory_order_conservative = 8 }; @@ -80,10 +85,12 @@ public: // add-value-to-dest template - inline static D add(I add_value, D volatile* dest); + inline static D add(I add_value, D volatile* dest, + atomic_memory_order order = memory_order_conservative); template - inline static D sub(I sub_value, D volatile* dest); + inline static D sub(I sub_value, D volatile* dest, + atomic_memory_order order = memory_order_conservative); // Atomically increment location. inc() provide: // increment-dest @@ -91,7 +98,8 @@ public: // type. If it is a pointer type, then the increment is // scaled to the size of the type pointed to by the pointer. template - inline static void inc(D volatile* dest); + inline static void inc(D volatile* dest, + atomic_memory_order order = memory_order_conservative); // Atomically decrement a location. dec() provide: // decrement-dest @@ -99,7 +107,8 @@ public: // type. If it is a pointer type, then the decrement is // scaled to the size of the type pointed to by the pointer. template - inline static void dec(D volatile* dest); + inline static void dec(D volatile* dest, + atomic_memory_order order = memory_order_conservative); // Performs atomic exchange of *dest with exchange_value. Returns old // prior value of *dest. xchg*() provide: @@ -108,7 +117,8 @@ public: // to D, an integral/enum type equal to D, or a type equal to D that // is primitive convertible using PrimitiveConversions. template - inline static D xchg(T exchange_value, volatile D* dest); + inline static D xchg(T exchange_value, volatile D* dest, + atomic_memory_order order = memory_order_conservative); // Performs atomic compare of *dest and compare_value, and exchanges // *dest with exchange_value if the comparison succeeded. Returns prior @@ -119,7 +129,7 @@ public: inline static D cmpxchg(T exchange_value, D volatile* dest, U compare_value, - cmpxchg_memory_order order = memory_order_conservative); + atomic_memory_order order = memory_order_conservative); // Performs atomic compare of *dest and NULL, and replaces *dest // with exchange_value if the comparison succeeded. Returns true if @@ -128,7 +138,7 @@ public: // alternative to the Double-Checked Locking Pattern. template inline static bool replace_if_null(T* value, D* volatile* dest, - cmpxchg_memory_order order = memory_order_conservative); + atomic_memory_order order = memory_order_conservative); private: WINDOWS_ONLY(public:) // VS2017 warns (C2027) use of undefined type if IsPointerConvertible is declared private @@ -272,7 +282,7 @@ private: // // - dest is of type T*. // - exchange_value and compare_value are of type T. - // - order is of type cmpxchg_memory_order. + // - order is of type atomic_memory_order. // - platform_cmpxchg is an object of type PlatformCmpxchg. // // Then @@ -280,7 +290,7 @@ private: // must be a valid expression, returning a result convertible to T. // // A default definition is provided, which declares a function template - // T operator()(T, T volatile*, T, cmpxchg_memory_order) const + // T operator()(T, T volatile*, T, atomic_memory_order) const // // For each required size, a platform must either provide an // appropriate definition of that function, or must entirely @@ -327,7 +337,7 @@ private: // must be a valid expression, returning a result convertible to T. // // A default definition is provided, which declares a function template - // T operator()(T, T volatile*, T, cmpxchg_memory_order) const + // T operator()(T, T volatile*, T, atomic_memory_order) const // // For each required size, a platform must either provide an // appropriate definition of that function, or must entirely @@ -488,33 +498,33 @@ struct Atomic::PlatformStore { template struct Atomic::FetchAndAdd { template - D operator()(I add_value, D volatile* dest) const; + D operator()(I add_value, D volatile* dest, atomic_memory_order order) const; }; template struct Atomic::AddAndFetch { template - D operator()(I add_value, D volatile* dest) const; + D operator()(I add_value, D volatile* dest, atomic_memory_order order) const; }; template -inline void Atomic::inc(D volatile* dest) { +inline void Atomic::inc(D volatile* dest, atomic_memory_order order) { STATIC_ASSERT(IsPointer::value || IsIntegral::value); typedef typename Conditional::value, ptrdiff_t, D>::type I; - Atomic::add(I(1), dest); + Atomic::add(I(1), dest, order); } template -inline void Atomic::dec(D volatile* dest) { +inline void Atomic::dec(D volatile* dest, atomic_memory_order order) { STATIC_ASSERT(IsPointer::value || IsIntegral::value); typedef typename Conditional::value, ptrdiff_t, D>::type I; // Assumes two's complement integer representation. #pragma warning(suppress: 4146) - Atomic::add(I(-1), dest); + Atomic::add(I(-1), dest, order); } template -inline D Atomic::sub(I sub_value, D volatile* dest) { +inline D Atomic::sub(I sub_value, D volatile* dest, atomic_memory_order order) { STATIC_ASSERT(IsPointer::value || IsIntegral::value); STATIC_ASSERT(IsIntegral::value); // If D is a pointer type, use [u]intptr_t as the addend type, @@ -527,7 +537,7 @@ inline D Atomic::sub(I sub_value, D volatile* dest) { AddendType addend = sub_value; // Assumes two's complement integer representation. #pragma warning(suppress: 4146) // In case AddendType is not signed. - return Atomic::add(-addend, dest); + return Atomic::add(-addend, dest, order); } // Define the class before including platform file, which may specialize @@ -541,7 +551,7 @@ struct Atomic::PlatformCmpxchg { T operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const; + atomic_memory_order order) const; }; // Define the class before including platform file, which may use this @@ -552,7 +562,7 @@ struct Atomic::CmpxchgByteUsingInt { T operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const; + atomic_memory_order order) const; }; // Define the class before including platform file, which may specialize @@ -564,7 +574,8 @@ template struct Atomic::PlatformXchg { template T operator()(T exchange_value, - T volatile* dest) const; + T volatile* dest, + atomic_memory_order order) const; }; // platform specific in-line definitions - must come before shared definitions @@ -589,8 +600,9 @@ inline void Atomic::store(T store_value, volatile D* dest) { } template -inline D Atomic::add(I add_value, D volatile* dest) { - return AddImpl()(add_value, dest); +inline D Atomic::add(I add_value, D volatile* dest, + atomic_memory_order order) { + return AddImpl()(add_value, dest, order); } template @@ -601,9 +613,9 @@ struct Atomic::AddImpl< (sizeof(I) <= sizeof(D)) && (IsSigned::value == IsSigned::value)>::type> { - D operator()(I add_value, D volatile* dest) const { + D operator()(I add_value, D volatile* dest, atomic_memory_order order) const { D addend = add_value; - return PlatformAdd()(addend, dest); + return PlatformAdd()(addend, dest, order); } }; @@ -612,14 +624,14 @@ struct Atomic::AddImpl< I, P*, typename EnableIf::value && (sizeof(I) <= sizeof(P*))>::type> { - P* operator()(I add_value, P* volatile* dest) const { + P* operator()(I add_value, P* volatile* dest, atomic_memory_order order) const { STATIC_ASSERT(sizeof(intptr_t) == sizeof(P*)); STATIC_ASSERT(sizeof(uintptr_t) == sizeof(P*)); typedef typename Conditional::value, intptr_t, uintptr_t>::type CI; CI addend = add_value; - return PlatformAdd()(addend, dest); + return PlatformAdd()(addend, dest, order); } }; @@ -634,13 +646,13 @@ struct Atomic::AddImpl< // Use the ATOMIC_SHORT_PAIR macro (see macros.hpp) to get the desired alignment. template<> struct Atomic::AddImpl { - short operator()(short add_value, short volatile* dest) const { + short operator()(short add_value, short volatile* dest, atomic_memory_order order) const { #ifdef VM_LITTLE_ENDIAN assert((intx(dest) & 0x03) == 0x02, "wrong alignment"); - int new_value = Atomic::add(add_value << 16, (volatile int*)(dest-1)); + int new_value = Atomic::add(add_value << 16, (volatile int*)(dest-1), order); #else assert((intx(dest) & 0x03) == 0x00, "wrong alignment"); - int new_value = Atomic::add(add_value << 16, (volatile int*)(dest)); + int new_value = Atomic::add(add_value << 16, (volatile int*)(dest), order); #endif return (short)(new_value >> 16); // preserves sign } @@ -648,24 +660,26 @@ struct Atomic::AddImpl { template template -inline D Atomic::FetchAndAdd::operator()(I add_value, D volatile* dest) const { +inline D Atomic::FetchAndAdd::operator()(I add_value, D volatile* dest, + atomic_memory_order order) const { I addend = add_value; // If D is a pointer type P*, scale by sizeof(P). if (IsPointer::value) { addend *= sizeof(typename RemovePointer::type); } - D old = static_cast(this)->fetch_and_add(addend, dest); + D old = static_cast(this)->fetch_and_add(addend, dest, order); return old + add_value; } template template -inline D Atomic::AddAndFetch::operator()(I add_value, D volatile* dest) const { +inline D Atomic::AddAndFetch::operator()(I add_value, D volatile* dest, + atomic_memory_order order) const { // If D is a pointer type P*, scale by sizeof(P). if (IsPointer::value) { add_value *= sizeof(typename RemovePointer::type); } - return static_cast(this)->add_and_fetch(add_value, dest); + return static_cast(this)->add_and_fetch(add_value, dest, order); } template @@ -679,13 +693,13 @@ template inline D Atomic::cmpxchg(T exchange_value, D volatile* dest, U compare_value, - cmpxchg_memory_order order) { + atomic_memory_order order) { return CmpxchgImpl()(exchange_value, dest, compare_value, order); } template inline bool Atomic::replace_if_null(T* value, D* volatile* dest, - cmpxchg_memory_order order) { + atomic_memory_order order) { // Presently using a trivial implementation in terms of cmpxchg. // Consider adding platform support, to permit the use of compiler // intrinsics like gcc's __sync_bool_compare_and_swap. @@ -702,7 +716,7 @@ struct Atomic::CmpxchgImpl< typename EnableIf::value || IsRegisteredEnum::value>::type> { T operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { // Forward to the platform handler for the size of T. return PlatformCmpxchg()(exchange_value, dest, @@ -728,7 +742,7 @@ struct Atomic::CmpxchgImpl< typename RemoveCV::type>::value>::type> { D* operator()(T* exchange_value, D* volatile* dest, U* compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { // Allow derived to base conversion, and adding cv-qualifiers. D* new_value = exchange_value; // Don't care what the CV qualifiers for compare_value are, @@ -751,7 +765,7 @@ struct Atomic::CmpxchgImpl< typename EnableIf::value>::type> { T operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { typedef PrimitiveConversions::Translate Translator; typedef typename Translator::Decayed Decayed; STATIC_ASSERT(sizeof(T) == sizeof(Decayed)); @@ -779,7 +793,7 @@ template inline T Atomic::CmpxchgByteUsingInt::operator()(T exchange_value, T volatile* dest, T compare_value, - cmpxchg_memory_order order) const { + atomic_memory_order order) const { STATIC_ASSERT(sizeof(T) == sizeof(uint8_t)); uint8_t canon_exchange_value = exchange_value; uint8_t canon_compare_value = compare_value; @@ -821,9 +835,9 @@ struct Atomic::XchgImpl< T, T, typename EnableIf::value || IsRegisteredEnum::value>::type> { - T operator()(T exchange_value, T volatile* dest) const { + T operator()(T exchange_value, T volatile* dest, atomic_memory_order order) const { // Forward to the platform handler for the size of T. - return PlatformXchg()(exchange_value, dest); + return PlatformXchg()(exchange_value, dest, order); } }; @@ -837,10 +851,10 @@ struct Atomic::XchgImpl< T*, D*, typename EnableIf::value>::type> { - D* operator()(T* exchange_value, D* volatile* dest) const { + D* operator()(T* exchange_value, D* volatile* dest, atomic_memory_order order) const { // Allow derived to base conversion, and adding cv-qualifiers. D* new_value = exchange_value; - return PlatformXchg()(new_value, dest); + return PlatformXchg()(new_value, dest, order); } }; @@ -856,13 +870,14 @@ struct Atomic::XchgImpl< T, T, typename EnableIf::value>::type> { - T operator()(T exchange_value, T volatile* dest) const { + T operator()(T exchange_value, T volatile* dest, atomic_memory_order order) const { typedef PrimitiveConversions::Translate Translator; typedef typename Translator::Decayed Decayed; STATIC_ASSERT(sizeof(T) == sizeof(Decayed)); return Translator::recover( xchg(Translator::decay(exchange_value), - reinterpret_cast(dest))); + reinterpret_cast(dest), + order)); } }; @@ -877,8 +892,8 @@ inline T Atomic::xchg_using_helper(Fn fn, } template -inline D Atomic::xchg(T exchange_value, volatile D* dest) { - return XchgImpl()(exchange_value, dest); +inline D Atomic::xchg(T exchange_value, volatile D* dest, atomic_memory_order order) { + return XchgImpl()(exchange_value, dest, order); } #endif // SHARE_VM_RUNTIME_ATOMIC_HPP diff --git a/src/hotspot/share/utilities/globalCounter.cpp b/src/hotspot/share/utilities/globalCounter.cpp index db481f0fcf7..75a4439dc63 100644 --- a/src/hotspot/share/utilities/globalCounter.cpp +++ b/src/hotspot/share/utilities/globalCounter.cpp @@ -59,7 +59,8 @@ class GlobalCounter::CounterThreadCheck : public ThreadClosure { void GlobalCounter::write_synchronize() { assert((*Thread::current()->get_rcu_counter() & COUNTER_ACTIVE) == 0x0, "must be outside a critcal section"); // Atomic::add must provide fence since we have storeload dependency. - volatile uintx gbl_cnt = Atomic::add((uintx)COUNTER_INCREMENT, &_global_counter._counter); + volatile uintx gbl_cnt = Atomic::add((uintx)COUNTER_INCREMENT, &_global_counter._counter, + memory_order_conservative); // Do all RCU threads. CounterThreadCheck ctc(gbl_cnt); for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { From 983911c6977064a57e38f58acc9303daff066624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96sterlund?= Date: Mon, 7 May 2018 10:36:38 +0200 Subject: [PATCH 16/40] 8202083: Remove explicit CMS checks in CardTableBarrierSet Reviewed-by: kbarrett --- src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp index abdc7e9368b..b0eb89bd342 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp @@ -32,9 +32,8 @@ template inline void CardTableBarrierSet::write_ref_field_post(T* field, oop newVal) { volatile jbyte* byte = _card_table->byte_for(field); - if (UseConcMarkSweepGC) { - // Perform a releasing store if using CMS so that it may - // scan and clear the cards concurrently during pre-cleaning. + if (_card_table->scanned_concurrently()) { + // Perform a releasing store if the card table is scanned concurrently OrderAccess::release_store(byte, CardTable::dirty_card_val()); } else { *byte = CardTable::dirty_card_val(); From 7d380f1708d6d79cab24b125392622b81fde117d Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 7 May 2018 14:42:00 +0200 Subject: [PATCH 17/40] 8202591: Remove usage of CMSEdenChunksRecordAlways in defNewGeneration.cpp Reviewed-by: eosterlund, kbarrett --- src/hotspot/share/gc/serial/defNewGeneration.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 51bf6c0f226..2f12fcc3a8d 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -1006,11 +1006,9 @@ HeapWord* DefNewGeneration::allocate(size_t word_size, bool is_tlab) { // have to use it here, as well. HeapWord* result = eden()->par_allocate(word_size); if (result != NULL) { -#if INCLUDE_CMSGC - if (CMSEdenChunksRecordAlways && _old_gen != NULL) { + if (_old_gen != NULL) { _old_gen->sample_eden_chunk(); } -#endif } else { // If the eden is full and the last collection bailed out, we are running // out of heap space, and we try to allocate the from-space, too. @@ -1024,11 +1022,9 @@ HeapWord* DefNewGeneration::allocate(size_t word_size, bool is_tlab) { HeapWord* DefNewGeneration::par_allocate(size_t word_size, bool is_tlab) { HeapWord* res = eden()->par_allocate(word_size); -#if INCLUDE_CMSGC - if (CMSEdenChunksRecordAlways && _old_gen != NULL) { + if (_old_gen != NULL) { _old_gen->sample_eden_chunk(); } -#endif return res; } From 5dfccac11f6158a5eca4129a95aabaa521ab6688 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 7 May 2018 14:42:04 +0200 Subject: [PATCH 18/40] 8202592: Remove unused EvacuateFollowersClosure Reviewed-by: kbarrett, tschatzl --- src/hotspot/share/gc/serial/defNewGeneration.cpp | 13 ------------- src/hotspot/share/gc/serial/defNewGeneration.hpp | 10 ---------- 2 files changed, 23 deletions(-) diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 2f12fcc3a8d..e51442cfa1c 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -92,19 +92,6 @@ FastKeepAliveClosure(DefNewGeneration* g, ScanWeakRefClosure* cl) : void DefNewGeneration::FastKeepAliveClosure::do_oop(oop* p) { DefNewGeneration::FastKeepAliveClosure::do_oop_work(p); } void DefNewGeneration::FastKeepAliveClosure::do_oop(narrowOop* p) { DefNewGeneration::FastKeepAliveClosure::do_oop_work(p); } -DefNewGeneration::EvacuateFollowersClosure:: -EvacuateFollowersClosure(GenCollectedHeap* gch, - ScanClosure* cur, - ScanClosure* older) : - _gch(gch), _scan_cur_or_nonheap(cur), _scan_older(older) -{} - -void DefNewGeneration::EvacuateFollowersClosure::do_void() { - do { - _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older); - } while (!_gch->no_allocs_since_save_marks()); -} - DefNewGeneration::FastEvacuateFollowersClosure:: FastEvacuateFollowersClosure(GenCollectedHeap* gch, FastScanClosure* cur, diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index 19ca2ac4707..3e1711ce0e4 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -178,16 +178,6 @@ protected: virtual void do_oop(narrowOop* p); }; - class EvacuateFollowersClosure: public VoidClosure { - GenCollectedHeap* _gch; - ScanClosure* _scan_cur_or_nonheap; - ScanClosure* _scan_older; - public: - EvacuateFollowersClosure(GenCollectedHeap* gch, - ScanClosure* cur, ScanClosure* older); - void do_void(); - }; - class FastEvacuateFollowersClosure: public VoidClosure { GenCollectedHeap* _gch; DefNewGeneration* _young_gen; From 2e1bd03bad4ef3585065a0210989586a0e98f106 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 7 May 2018 14:42:05 +0200 Subject: [PATCH 19/40] 8202639: Use concrete Generation classes in SerialHeap and CMSHeap Reviewed-by: eosterlund, ehelin --- src/hotspot/share/gc/cms/cmsHeap.cpp | 11 +--- src/hotspot/share/gc/cms/cmsHeap.hpp | 15 +++-- .../gc/cms/concurrentMarkSweepGeneration.cpp | 4 +- .../share/gc/cms/jvmFlagConstraintsCMS.cpp | 6 +- .../share/gc/serial/defNewGeneration.cpp | 59 +++++++++---------- .../share/gc/serial/defNewGeneration.hpp | 6 +- src/hotspot/share/gc/serial/serialHeap.cpp | 19 +++--- src/hotspot/share/gc/serial/serialHeap.hpp | 18 +++++- .../share/gc/shared/genCollectedHeap.cpp | 14 ++--- .../share/gc/shared/genCollectedHeap.hpp | 5 +- 10 files changed, 83 insertions(+), 74 deletions(-) diff --git a/src/hotspot/share/gc/cms/cmsHeap.cpp b/src/hotspot/share/gc/cms/cmsHeap.cpp index 4671eaed023..408775114b0 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.cpp +++ b/src/hotspot/share/gc/cms/cmsHeap.cpp @@ -100,7 +100,7 @@ void CMSHeap::initialize_serviceability() { _young_manager = new GCMemoryManager("ParNew", "end of minor GC"); _old_manager = new GCMemoryManager("ConcurrentMarkSweep", "end of major GC"); - ParNewGeneration* young = (ParNewGeneration*) young_gen(); + ParNewGeneration* young = young_gen(); _eden_pool = new ContiguousSpacePool(young->eden(), "Par Eden Space", young->max_eden_size(), @@ -128,18 +128,11 @@ void CMSHeap::initialize_serviceability() { } -void CMSHeap::check_gen_kinds() { - assert(young_gen()->kind() == Generation::ParNew, - "Wrong youngest generation type"); - assert(old_gen()->kind() == Generation::ConcurrentMarkSweep, - "Wrong generation kind"); -} - CMSHeap* CMSHeap::heap() { CollectedHeap* heap = Universe::heap(); assert(heap != NULL, "Uninitialized access to CMSHeap::heap()"); assert(heap->kind() == CollectedHeap::CMS, "Invalid name"); - return (CMSHeap*) heap; + return static_cast(heap); } void CMSHeap::gc_threads_do(ThreadClosure* tc) const { diff --git a/src/hotspot/share/gc/cms/cmsHeap.hpp b/src/hotspot/share/gc/cms/cmsHeap.hpp index ad0dab072e5..d743a9eac5e 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.hpp +++ b/src/hotspot/share/gc/cms/cmsHeap.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_GC_CMS_CMSHEAP_HPP #include "gc/cms/concurrentMarkSweepGeneration.hpp" +#include "gc/cms/parNewGeneration.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/genCollectedHeap.hpp" @@ -42,10 +43,6 @@ class ThreadClosure; class WorkGang; class CMSHeap : public GenCollectedHeap { - -protected: - virtual void check_gen_kinds(); - public: CMSHeap(GenCollectorPolicy *policy); @@ -97,6 +94,16 @@ public: GCMemoryManager* old_manager() const { return _old_manager; } + ParNewGeneration* young_gen() const { + assert(_young_gen->kind() == Generation::ParNew, "Wrong generation type"); + return static_cast(_young_gen); + } + + ConcurrentMarkSweepGeneration* old_gen() const { + assert(_old_gen->kind() == Generation::ConcurrentMarkSweep, "Wrong generation kind"); + return static_cast(_old_gen); + } + private: WorkGang* _workers; MemoryPool* _eden_pool; diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index 7492c96b81a..02c6689db9b 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -602,8 +602,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, // Support for parallelizing young gen rescan CMSHeap* heap = CMSHeap::heap(); - assert(heap->young_gen()->kind() == Generation::ParNew, "CMS can only be used with ParNew"); - _young_gen = (ParNewGeneration*)heap->young_gen(); + _young_gen = heap->young_gen(); if (heap->supports_inline_contig_alloc()) { _top_addr = heap->top_addr(); _end_addr = heap->end_addr(); @@ -770,7 +769,6 @@ void ConcurrentMarkSweepGeneration::compute_new_size_free_list() { log.trace(" Capacity " SIZE_FORMAT, capacity() / 1000); log.trace(" Desired capacity " SIZE_FORMAT, desired_capacity / 1000); CMSHeap* heap = CMSHeap::heap(); - assert(heap->is_old_gen(this), "The CMS generation should always be the old generation"); size_t young_size = heap->young_gen()->capacity(); log.trace(" Young gen size " SIZE_FORMAT, young_size / 1000); log.trace(" unsafe_max_alloc_nogc " SIZE_FORMAT, unsafe_max_alloc_nogc() / 1000); diff --git a/src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.cpp b/src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.cpp index 777ed6ce13d..bb3282634ce 100644 --- a/src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.cpp +++ b/src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.cpp @@ -126,7 +126,7 @@ JVMFlag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose) { static JVMFlag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) { if (UseConcMarkSweepGC) { - ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen(); + ConcurrentMarkSweepGeneration* cms = CMSHeap::heap()->old_gen(); const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size(); if (value > ergo_max) { CommandLineError::print(verbose, @@ -189,7 +189,7 @@ JVMFlag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose) { JVMFlag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose) { if (UseConcMarkSweepGC) { - size_t max_capacity = GenCollectedHeap::heap()->young_gen()->max_capacity(); + size_t max_capacity = CMSHeap::heap()->young_gen()->max_capacity(); if (value > max_uintx - max_capacity) { CommandLineError::print(verbose, "CMSSamplingGrain (" UINTX_FORMAT ") must be " @@ -212,7 +212,7 @@ JVMFlag::Error CMSBitMapYieldQuantumConstraintFunc(size_t value, bool verbose) { // Skip for current default value. if (UseConcMarkSweepGC && FLAG_IS_CMDLINE(CMSBitMapYieldQuantum)) { // CMSBitMapYieldQuantum should be compared with mark bitmap size. - ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen(); + ConcurrentMarkSweepGeneration* cms = CMSHeap::heap()->old_gen(); size_t bitmap_size = cms->collector()->markBitMap()->sizeInWords(); if (value > bitmap_size) { diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index e51442cfa1c..354b9d16a48 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "gc/serial/defNewGeneration.inline.hpp" +#include "gc/serial/serialHeap.hpp" +#include "gc/serial/tenuredGeneration.hpp" #include "gc/shared/adaptiveSizePolicy.hpp" #include "gc/shared/ageTable.inline.hpp" #include "gc/shared/cardTableRS.hpp" @@ -34,7 +36,6 @@ #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/gcTraceTime.inline.hpp" -#include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/generationSpec.hpp" #include "gc/shared/preservedMarks.inline.hpp" @@ -93,20 +94,18 @@ void DefNewGeneration::FastKeepAliveClosure::do_oop(oop* p) { DefNewGenera void DefNewGeneration::FastKeepAliveClosure::do_oop(narrowOop* p) { DefNewGeneration::FastKeepAliveClosure::do_oop_work(p); } DefNewGeneration::FastEvacuateFollowersClosure:: -FastEvacuateFollowersClosure(GenCollectedHeap* gch, +FastEvacuateFollowersClosure(SerialHeap* heap, FastScanClosure* cur, FastScanClosure* older) : - _gch(gch), _scan_cur_or_nonheap(cur), _scan_older(older) + _heap(heap), _scan_cur_or_nonheap(cur), _scan_older(older) { - assert(_gch->young_gen()->kind() == Generation::DefNew, "Generation should be DefNew"); - _young_gen = (DefNewGeneration*)_gch->young_gen(); } void DefNewGeneration::FastEvacuateFollowersClosure::do_void() { do { - _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older); - } while (!_gch->no_allocs_since_save_marks()); - guarantee(_young_gen->promo_failure_scan_is_complete(), "Failed to finish scan"); + _heap->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older); + } while (!_heap->no_allocs_since_save_marks()); + guarantee(_heap->young_gen()->promo_failure_scan_is_complete(), "Failed to finish scan"); } ScanClosure::ScanClosure(DefNewGeneration* g, bool gc_barrier) : @@ -563,29 +562,29 @@ void DefNewGeneration::collect(bool full, bool is_tlab) { assert(full || size > 0, "otherwise we don't want to collect"); - GenCollectedHeap* gch = GenCollectedHeap::heap(); + SerialHeap* heap = SerialHeap::heap(); _gc_timer->register_gc_start(); DefNewTracer gc_tracer; - gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start()); + gc_tracer.report_gc_start(heap->gc_cause(), _gc_timer->gc_start()); - _old_gen = gch->old_gen(); + _old_gen = heap->old_gen(); // If the next generation is too full to accommodate promotion // from this generation, pass on collection; let the next generation // do it. if (!collection_attempt_is_safe()) { log_trace(gc)(":: Collection attempt not safe ::"); - gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one + heap->set_incremental_collection_failed(); // Slight lie: we did not even attempt one return; } assert(to()->is_empty(), "Else not collection_attempt_is_safe"); init_assuming_no_promotion_failure(); - GCTraceTime(Trace, gc, phases) tm("DefNew", NULL, gch->gc_cause()); + GCTraceTime(Trace, gc, phases) tm("DefNew", NULL, heap->gc_cause()); - gch->trace_heap_before_gc(&gc_tracer); + heap->trace_heap_before_gc(&gc_tracer); // These can be shared for all code paths IsAliveClosure is_alive(this); @@ -596,23 +595,23 @@ void DefNewGeneration::collect(bool full, // The preserved marks should be empty at the start of the GC. _preserved_marks_set.init(1); - gch->rem_set()->prepare_for_younger_refs_iterate(false); + heap->rem_set()->prepare_for_younger_refs_iterate(false); - assert(gch->no_allocs_since_save_marks(), + assert(heap->no_allocs_since_save_marks(), "save marks have not been newly set."); FastScanClosure fsc_with_no_gc_barrier(this, false); FastScanClosure fsc_with_gc_barrier(this, true); CLDScanClosure cld_scan_closure(&fsc_with_no_gc_barrier, - gch->rem_set()->cld_rem_set()->accumulate_modified_oops()); + heap->rem_set()->cld_rem_set()->accumulate_modified_oops()); set_promo_failure_scan_stack_closure(&fsc_with_no_gc_barrier); - FastEvacuateFollowersClosure evacuate_followers(gch, + FastEvacuateFollowersClosure evacuate_followers(heap, &fsc_with_no_gc_barrier, &fsc_with_gc_barrier); - assert(gch->no_allocs_since_save_marks(), + assert(heap->no_allocs_since_save_marks(), "save marks have not been newly set."); { @@ -621,10 +620,10 @@ void DefNewGeneration::collect(bool full, // See: CardTableRS::non_clean_card_iterate_possibly_parallel. StrongRootsScope srs(0); - gch->young_process_roots(&srs, - &fsc_with_no_gc_barrier, - &fsc_with_gc_barrier, - &cld_scan_closure); + heap->young_process_roots(&srs, + &fsc_with_no_gc_barrier, + &fsc_with_gc_barrier, + &cld_scan_closure); } // "evacuate followers". @@ -641,12 +640,12 @@ void DefNewGeneration::collect(bool full, gc_tracer.report_tenuring_threshold(tenuring_threshold()); pt.print_all_references(); - assert(gch->no_allocs_since_save_marks(), "save marks have not been newly set."); + assert(heap->no_allocs_since_save_marks(), "save marks have not been newly set."); WeakProcessor::weak_oops_do(&is_alive, &keep_alive); // Verify that the usage of keep_alive didn't copy any objects. - assert(gch->no_allocs_since_save_marks(), "save marks have not been newly set."); + assert(heap->no_allocs_since_save_marks(), "save marks have not been newly set."); if (!_promotion_failed) { // Swap the survivor spaces. @@ -670,9 +669,9 @@ void DefNewGeneration::collect(bool full, // A successful scavenge should restart the GC time limit count which is // for full GC's. - AdaptiveSizePolicy* size_policy = gch->size_policy(); + AdaptiveSizePolicy* size_policy = heap->size_policy(); size_policy->reset_gc_overhead_limit_count(); - assert(!gch->incremental_collection_failed(), "Should be clear"); + assert(!heap->incremental_collection_failed(), "Should be clear"); } else { assert(_promo_failure_scan_stack.is_empty(), "post condition"); _promo_failure_scan_stack.clear(true); // Clear cached segments. @@ -686,14 +685,14 @@ void DefNewGeneration::collect(bool full, // and from-space. swap_spaces(); // For uniformity wrt ParNewGeneration. from()->set_next_compaction_space(to()); - gch->set_incremental_collection_failed(); + heap->set_incremental_collection_failed(); // Inform the next generation that a promotion failure occurred. _old_gen->promotion_failure_occurred(); gc_tracer.report_promotion_failed(_promotion_failed_info); // Reset the PromotionFailureALot counters. - NOT_PRODUCT(gch->reset_promotion_should_fail();) + NOT_PRODUCT(heap->reset_promotion_should_fail();) } // We should have processed and cleared all the preserved marks. _preserved_marks_set.reclaim(); @@ -707,7 +706,7 @@ void DefNewGeneration::collect(bool full, jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; update_time_of_last_gc(now); - gch->trace_heap_after_gc(&gc_tracer); + heap->trace_heap_after_gc(&gc_tracer); _gc_timer->register_gc_end(); diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index 3e1711ce0e4..69845a4ed9f 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -39,6 +39,7 @@ class ScanClosure; class STWGCTimer; class CSpaceCounters; class ScanWeakRefClosure; +class SerialHeap; // DefNewGeneration is a young generation containing eden, from- and // to-space. @@ -179,12 +180,11 @@ protected: }; class FastEvacuateFollowersClosure: public VoidClosure { - GenCollectedHeap* _gch; - DefNewGeneration* _young_gen; + SerialHeap* _heap; FastScanClosure* _scan_cur_or_nonheap; FastScanClosure* _scan_older; public: - FastEvacuateFollowersClosure(GenCollectedHeap* gch, + FastEvacuateFollowersClosure(SerialHeap* heap, FastScanClosure* cur, FastScanClosure* older); void do_void(); diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index 9e413a063da..c347646fbb0 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -25,9 +25,17 @@ #include "precompiled.hpp" #include "gc/serial/defNewGeneration.hpp" #include "gc/serial/serialHeap.hpp" +#include "gc/serial/tenuredGeneration.hpp" #include "gc/shared/genMemoryPools.hpp" #include "services/memoryManager.hpp" +SerialHeap* SerialHeap::heap() { + CollectedHeap* heap = Universe::heap(); + assert(heap != NULL, "Uninitialized access to SerialHeap::heap()"); + assert(heap->kind() == CollectedHeap::Serial, "Invalid name"); + return static_cast(heap); +} + SerialHeap::SerialHeap(GenCollectorPolicy* policy) : GenCollectedHeap(policy, Generation::DefNew, @@ -42,7 +50,7 @@ SerialHeap::SerialHeap(GenCollectorPolicy* policy) : void SerialHeap::initialize_serviceability() { - DefNewGeneration* young = (DefNewGeneration*) young_gen(); + DefNewGeneration* young = young_gen(); // Add a memory pool for each space and young gen doesn't // support low memory detection as it is expected to get filled up. @@ -54,7 +62,7 @@ void SerialHeap::initialize_serviceability() { "Survivor Space", young->max_survivor_size(), false /* support_usage_threshold */); - Generation* old = old_gen(); + TenuredGeneration* old = old_gen(); _old_pool = new GenerationPool(old, "Tenured Gen", true); _young_manager->add_pool(_eden_pool); @@ -68,13 +76,6 @@ void SerialHeap::initialize_serviceability() { } -void SerialHeap::check_gen_kinds() { - assert(young_gen()->kind() == Generation::DefNew, - "Wrong youngest generation type"); - assert(old_gen()->kind() == Generation::MarkSweepCompact, - "Wrong generation kind"); -} - GrowableArray SerialHeap::memory_managers() { GrowableArray memory_managers(2); memory_managers.append(_young_manager); diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index e4e5018b4c9..07bac656021 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -25,12 +25,15 @@ #ifndef SHARE_VM_GC_SERIAL_SERIALHEAP_HPP #define SHARE_VM_GC_SERIAL_SERIALHEAP_HPP +#include "gc/serial/defNewGeneration.hpp" +#include "gc/serial/tenuredGeneration.hpp" #include "gc/shared/genCollectedHeap.hpp" #include "utilities/growableArray.hpp" class GenCollectorPolicy; class GCMemoryManager; class MemoryPool; +class TenuredGeneration; class SerialHeap : public GenCollectedHeap { private: @@ -40,10 +43,9 @@ private: virtual void initialize_serviceability(); -protected: - virtual void check_gen_kinds(); - public: + static SerialHeap* heap(); + SerialHeap(GenCollectorPolicy* policy); virtual Name kind() const { @@ -61,6 +63,16 @@ public: virtual bool is_in_closed_subset(const void* p) const { return is_in(p); } + + DefNewGeneration* young_gen() const { + assert(_young_gen->kind() == Generation::DefNew, "Wrong generation type"); + return static_cast(_young_gen); + } + + TenuredGeneration* old_gen() const { + assert(_old_gen->kind() == Generation::MarkSweepCompact, "Wrong generation type"); + return static_cast(_old_gen); + } }; #endif // SHARE_VM_GC_CMS_CMSHEAP_HPP diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index 14c29b1afc3..36c9e48021d 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -176,7 +176,7 @@ char* GenCollectedHeap::allocate(size_t alignment, void GenCollectedHeap::post_initialize() { CollectedHeap::post_initialize(); ref_processing_init(); - check_gen_kinds(); + DefNewGeneration* def_new_gen = (DefNewGeneration*)_young_gen; initialize_size_policy(def_new_gen->eden()->capacity(), @@ -249,7 +249,7 @@ unsigned int GenCollectedHeap::update_full_collections_completed(unsigned int co // was a full collection because a partial collection (would // have) failed and is likely to fail again bool GenCollectedHeap::should_try_older_generation_allocation(size_t word_size) const { - size_t young_capacity = young_gen()->capacity_before_gc(); + size_t young_capacity = _young_gen->capacity_before_gc(); return (word_size > heap_word_size(young_capacity)) || GCLocker::is_active_and_needs_gc() || incremental_collection_failed(); @@ -257,12 +257,12 @@ bool GenCollectedHeap::should_try_older_generation_allocation(size_t word_size) HeapWord* GenCollectedHeap::expand_heap_and_allocate(size_t size, bool is_tlab) { HeapWord* result = NULL; - if (old_gen()->should_allocate(size, is_tlab)) { - result = old_gen()->expand_and_allocate(size, is_tlab); + if (_old_gen->should_allocate(size, is_tlab)) { + result = _old_gen->expand_and_allocate(size, is_tlab); } if (result == NULL) { - if (young_gen()->should_allocate(size, is_tlab)) { - result = young_gen()->expand_and_allocate(size, is_tlab); + if (_young_gen->should_allocate(size, is_tlab)) { + result = _young_gen->expand_and_allocate(size, is_tlab); } } assert(result == NULL || is_in_reserved(result), "result not in heap"); @@ -287,7 +287,7 @@ HeapWord* GenCollectedHeap::mem_allocate_work(size_t size, HandleMark hm; // Discard any handles allocated in each iteration. // First allocation attempt is lock-free. - Generation *young = young_gen(); + Generation *young = _young_gen; assert(young->supports_inline_contig_alloc(), "Otherwise, must do alloc within heap lock"); if (young->should_allocate(size, is_tlab)) { diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index 34008d69579..76c2a935575 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -63,10 +63,11 @@ public: OldGen }; -private: +protected: Generation* _young_gen; Generation* _old_gen; +private: GenerationSpec* _young_gen_spec; GenerationSpec* _old_gen_spec; @@ -161,8 +162,6 @@ protected: Generation::Name old, const char* policy_counters_name); - virtual void check_gen_kinds() = 0; - public: // Returns JNI_OK on success From 1dd85fe2f4a297bc8ec886a1d5e144cbd797bdbc Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 7 May 2018 14:42:08 +0200 Subject: [PATCH 20/40] 8202641: Replace OOP_SINCE_SAVE_MARKS with templates Reviewed-by: eosterlund, sjohanss --- src/hotspot/share/gc/cms/cmsHeap.hpp | 8 ++ src/hotspot/share/gc/cms/cmsHeap.inline.hpp | 39 ++++++++++ .../gc/cms/cms_specialized_oop_closures.hpp | 4 - .../share/gc/cms/compactibleFreeListSpace.cpp | 16 ---- .../share/gc/cms/compactibleFreeListSpace.hpp | 6 +- .../cms/compactibleFreeListSpace.inline.hpp | 42 ++++++++++ .../gc/cms/concurrentMarkSweepGeneration.cpp | 15 +--- .../gc/cms/concurrentMarkSweepGeneration.hpp | 8 +- .../concurrentMarkSweepGeneration.inline.hpp | 10 ++- src/hotspot/share/gc/cms/parNewGeneration.cpp | 22 +++--- src/hotspot/share/gc/cms/parNewGeneration.hpp | 9 ++- src/hotspot/share/gc/cms/promotionInfo.cpp | 54 ------------- src/hotspot/share/gc/cms/promotionInfo.hpp | 11 +-- .../share/gc/cms/promotionInfo.inline.hpp | 77 +++++++++++++++++++ .../share/gc/serial/defNewGeneration.cpp | 23 +----- .../share/gc/serial/defNewGeneration.hpp | 8 +- .../gc/serial/defNewGeneration.inline.hpp | 12 ++- src/hotspot/share/gc/serial/serialHeap.cpp | 4 +- src/hotspot/share/gc/serial/serialHeap.hpp | 8 ++ .../share/gc/serial/serialHeap.inline.hpp | 39 ++++++++++ .../serial_specialized_oop_closures.hpp | 4 - .../share/gc/serial/tenuredGeneration.cpp | 14 ---- .../share/gc/serial/tenuredGeneration.hpp | 6 +- .../gc/serial/tenuredGeneration.inline.hpp | 10 ++- .../share/gc/shared/genCollectedHeap.cpp | 17 ---- .../share/gc/shared/genCollectedHeap.hpp | 14 ---- src/hotspot/share/gc/shared/generation.hpp | 19 ----- src/hotspot/share/gc/shared/space.cpp | 26 ------- src/hotspot/share/gc/shared/space.hpp | 7 +- src/hotspot/share/gc/shared/space.inline.hpp | 20 +++++ .../gc/shared/specialized_oop_closures.hpp | 21 ----- 31 files changed, 297 insertions(+), 276 deletions(-) create mode 100644 src/hotspot/share/gc/cms/cmsHeap.inline.hpp create mode 100644 src/hotspot/share/gc/cms/compactibleFreeListSpace.inline.hpp create mode 100644 src/hotspot/share/gc/cms/promotionInfo.inline.hpp create mode 100644 src/hotspot/share/gc/serial/serialHeap.inline.hpp diff --git a/src/hotspot/share/gc/cms/cmsHeap.hpp b/src/hotspot/share/gc/cms/cmsHeap.hpp index d743a9eac5e..ee800fff7f8 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.hpp +++ b/src/hotspot/share/gc/cms/cmsHeap.hpp @@ -104,6 +104,14 @@ public: return static_cast(_old_gen); } + // Apply "cur->do_oop" or "older->do_oop" to all the oops in objects + // allocated since the last call to save_marks in the young generation. + // The "cur" closure is applied to references in the younger generation + // at "level", and the "older" closure to older generations. + template + void oop_since_save_marks_iterate(OopClosureType1* cur, + OopClosureType2* older); + private: WorkGang* _workers; MemoryPool* _eden_pool; diff --git a/src/hotspot/share/gc/cms/cmsHeap.inline.hpp b/src/hotspot/share/gc/cms/cmsHeap.inline.hpp new file mode 100644 index 00000000000..be7f0c9750b --- /dev/null +++ b/src/hotspot/share/gc/cms/cmsHeap.inline.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2001, 2018, 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. + * + */ + +#ifndef SHARE_GC_CMS_CMSHEAP_INLINE_HPP +#define SHARE_GC_CMS_CMSHEAP_INLINE_HPP + +#include "gc/cms/cmsHeap.hpp" +#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp" +#include "gc/serial/defNewGeneration.inline.hpp" + +template +void CMSHeap::oop_since_save_marks_iterate(OopClosureType1* cur, + OopClosureType2* older) { + young_gen()->oop_since_save_marks_iterate(cur); + old_gen()->oop_since_save_marks_iterate(older); +} + +#endif // SHARE_GC_CMS_CMSHEAP_INLINE_HPP diff --git a/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp b/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp index eddc06d4702..064e0b80819 100644 --- a/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp +++ b/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp @@ -66,8 +66,4 @@ class CMSInnerParMarkAndPushClosure; f(ParMarkRefsIntoAndScanClosure,_nv) \ f(ParPushAndMarkClosure,_nv) -#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) \ - f(ParScanWithBarrierClosure,_nv) \ - f(ParScanWithoutBarrierClosure,_nv) - #endif // SHARE_GC_CMS_CMS_SPECIALIZED_OOP_CLOSURES_HPP diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp index 0123a9bd0ac..53b54cd3476 100644 --- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp +++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp @@ -2103,22 +2103,6 @@ bool CompactibleFreeListSpace::no_allocs_since_save_marks() { return _promoInfo.noPromotions(); } -#define CFLS_OOP_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix) \ - \ -void CompactibleFreeListSpace:: \ -oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) { \ - _promoInfo.promoted_oops_iterate##nv_suffix(blk); \ - /* \ - * This also restores any displaced headers and removes the elements from \ - * the iteration set as they are processed, so that we have a clean slate \ - * at the end of the iteration. Note, thus, that if new objects are \ - * promoted as a result of the iteration they are iterated over as well. \ - */ \ - assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); \ -} - -ALL_SINCE_SAVE_MARKS_CLOSURES(CFLS_OOP_SINCE_SAVE_MARKS_DEFN) - bool CompactibleFreeListSpace::linearAllocationWouldFail() const { return _smallLinearAllocBlock._word_size == 0; } diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp index 1120e866d2d..12b555fa19e 100644 --- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp +++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp @@ -501,10 +501,8 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Fields in objects allocated by applications of the closure // *are* included in the iteration. Thus, when the iteration completes // there should be no further such objects remaining. - #define CFLS_OOP_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \ - void oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk); - ALL_SINCE_SAVE_MARKS_CLOSURES(CFLS_OOP_SINCE_SAVE_MARKS_DECL) - #undef CFLS_OOP_SINCE_SAVE_MARKS_DECL + template + void oop_since_save_marks_iterate(OopClosureType* blk); // Allocation support HeapWord* allocate(size_t size); diff --git a/src/hotspot/share/gc/cms/compactibleFreeListSpace.inline.hpp b/src/hotspot/share/gc/cms/compactibleFreeListSpace.inline.hpp new file mode 100644 index 00000000000..8b265c853b4 --- /dev/null +++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.inline.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2001, 2018, 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. + * + */ + +#ifndef SHARE_GC_CMS_COMPACTIBLEFREELISTSPACE_INLINE_HPP +#define SHARE_GC_CMS_COMPACTIBLEFREELISTSPACE_INLINE_HPP + +#include "gc/cms/compactibleFreeListSpace.hpp" +#include "gc/cms/promotionInfo.inline.hpp" + +template +void CompactibleFreeListSpace::oop_since_save_marks_iterate(OopClosureType* blk) { + _promoInfo.promoted_oops_iterate(blk); + + // This also restores any displaced headers and removes the elements from + // the iteration set as they are processed, so that we have a clean slate + // at the end of the iteration. Note, thus, that if new objects are + // promoted as a result of the iteration they are iterated over as well. + assert(_promoInfo.noPromotions(), "_promoInfo inconsistency"); +} + +#endif // SHARE_GC_CMS_COMPACTIBLEFREELISTSPACE_INLINE_HPP diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index 02c6689db9b..ef855456063 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -36,6 +36,7 @@ #include "gc/cms/concurrentMarkSweepGeneration.inline.hpp" #include "gc/cms/concurrentMarkSweepThread.hpp" #include "gc/cms/parNewGeneration.hpp" +#include "gc/cms/promotionInfo.inline.hpp" #include "gc/cms/vmCMSOperations.hpp" #include "gc/serial/genMarkSweep.hpp" #include "gc/serial/tenuredGeneration.hpp" @@ -1099,7 +1100,7 @@ ConcurrentMarkSweepGeneration:: par_oop_since_save_marks_iterate_done(int thread_num) { CMSParGCThreadState* ps = _par_gc_thread_states[thread_num]; ParScanWithoutBarrierClosure* dummy_cl = NULL; - ps->promo.promoted_oops_iterate_nv(dummy_cl); + ps->promo.promoted_oops_iterate(dummy_cl); // Because card-scanning has been completed, subsequent phases // (e.g., reference processing) will not need to recognize which @@ -2461,18 +2462,6 @@ bool ConcurrentMarkSweepGeneration::no_allocs_since_save_marks() { return cmsSpace()->no_allocs_since_save_marks(); } -#define CMS_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix) \ - \ -void ConcurrentMarkSweepGeneration:: \ -oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl) { \ - cl->set_generation(this); \ - cmsSpace()->oop_since_save_marks_iterate##nv_suffix(cl); \ - cl->reset_generation(); \ - save_marks(); \ -} - -ALL_SINCE_SAVE_MARKS_CLOSURES(CMS_SINCE_SAVE_MARKS_DEFN) - void ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) { if (freelistLock()->owned_by_self()) { diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp index 961600ec20b..37d011aa762 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp @@ -1195,12 +1195,8 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { virtual void safe_object_iterate(ObjectClosure* cl); virtual void object_iterate(ObjectClosure* cl); - // Need to declare the full complement of closures, whether we'll - // override them or not, or get message from the compiler: - // oop_since_save_marks_iterate_nv hides virtual function... - #define CMS_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \ - void oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl); - ALL_SINCE_SAVE_MARKS_CLOSURES(CMS_SINCE_SAVE_MARKS_DECL) + template + void oop_since_save_marks_iterate(OopClosureType* cl); // Smart allocation XXX -- move to CFLSpace? void setNearLargestChunk(); diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.inline.hpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.inline.hpp index ff04458a439..a8c711b4c9c 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.inline.hpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.inline.hpp @@ -27,7 +27,7 @@ #include "gc/cms/cmsHeap.hpp" #include "gc/cms/cmsLockVerifier.hpp" -#include "gc/cms/compactibleFreeListSpace.hpp" +#include "gc/cms/compactibleFreeListSpace.inline.hpp" #include "gc/cms/concurrentMarkSweepGeneration.hpp" #include "gc/cms/concurrentMarkSweepThread.hpp" #include "gc/cms/parNewGeneration.hpp" @@ -375,6 +375,14 @@ inline MemRegion ConcurrentMarkSweepGeneration::used_region_at_save_marks() cons return _cmsSpace->used_region_at_save_marks(); } +template +void ConcurrentMarkSweepGeneration::oop_since_save_marks_iterate(OopClosureType* cl) { + cl->set_generation(this); + cmsSpace()->oop_since_save_marks_iterate(cl); + cl->reset_generation(); + save_marks(); +} + inline void MarkFromRootsClosure::do_yield_check() { if (ConcurrentMarkSweepThread::should_yield() && !_collector->foregroundGCIsActive() && diff --git a/src/hotspot/share/gc/cms/parNewGeneration.cpp b/src/hotspot/share/gc/cms/parNewGeneration.cpp index cfde8aa51de..0aa8bc97628 100644 --- a/src/hotspot/share/gc/cms/parNewGeneration.cpp +++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "gc/cms/cmsHeap.hpp" +#include "gc/cms/cmsHeap.inline.hpp" #include "gc/cms/compactibleFreeListSpace.hpp" #include "gc/cms/concurrentMarkSweepGeneration.hpp" #include "gc/cms/parNewGeneration.inline.hpp" @@ -36,7 +36,6 @@ #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/gcTraceTime.inline.hpp" -#include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/generation.hpp" #include "gc/shared/plab.inline.hpp" @@ -836,20 +835,19 @@ ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier) : ScanClosure(g, gc_barrier) { } -EvacuateFollowersClosureGeneral:: +template +EvacuateFollowersClosureGeneral:: EvacuateFollowersClosureGeneral(CMSHeap* heap, - OopsInGenClosure* cur, - OopsInGenClosure* older) : + OopClosureType1* cur, + OopClosureType2* older) : _heap(heap), _scan_cur_or_nonheap(cur), _scan_older(older) { } -void EvacuateFollowersClosureGeneral::do_void() { +template +void EvacuateFollowersClosureGeneral::do_void() { do { - // Beware: this call will lead to closure applications via virtual - // calls. - _heap->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, - _scan_cur_or_nonheap, + _heap->oop_since_save_marks_iterate(_scan_cur_or_nonheap, _scan_older); } while (!_heap->no_allocs_since_save_marks()); } @@ -977,8 +975,8 @@ void ParNewGeneration::collect(bool full, ScanClosure scan_without_gc_barrier(this, false); ScanClosureWithParBarrier scan_with_gc_barrier(this, true); set_promo_failure_scan_stack_closure(&scan_without_gc_barrier); - EvacuateFollowersClosureGeneral evacuate_followers(gch, - &scan_without_gc_barrier, &scan_with_gc_barrier); + EvacuateFollowersClosureGeneral evacuate_followers( + gch, &scan_without_gc_barrier, &scan_with_gc_barrier); rp->setup_policy(clear_all_soft_refs); // Can the mt_degree be set later (at run_task() time would be best)? rp->set_active_mt_degree(active_workers); diff --git a/src/hotspot/share/gc/cms/parNewGeneration.hpp b/src/hotspot/share/gc/cms/parNewGeneration.hpp index a27c7c36c43..04439d45099 100644 --- a/src/hotspot/share/gc/cms/parNewGeneration.hpp +++ b/src/hotspot/share/gc/cms/parNewGeneration.hpp @@ -258,15 +258,16 @@ class KeepAliveClosure: public DefNewGeneration::KeepAliveClosure { virtual void do_oop(narrowOop* p); }; +template class EvacuateFollowersClosureGeneral: public VoidClosure { private: CMSHeap* _heap; - OopsInGenClosure* _scan_cur_or_nonheap; - OopsInGenClosure* _scan_older; + OopClosureType1* _scan_cur_or_nonheap; + OopClosureType2* _scan_older; public: EvacuateFollowersClosureGeneral(CMSHeap* heap, - OopsInGenClosure* cur, - OopsInGenClosure* older); + OopClosureType1* cur, + OopClosureType2* older); virtual void do_void(); }; diff --git a/src/hotspot/share/gc/cms/promotionInfo.cpp b/src/hotspot/share/gc/cms/promotionInfo.cpp index f6979bc72dd..971368c121d 100644 --- a/src/hotspot/share/gc/cms/promotionInfo.cpp +++ b/src/hotspot/share/gc/cms/promotionInfo.cpp @@ -60,60 +60,6 @@ inline void PromotedObject::setNext(PromotedObject* x) { assert(!((FreeChunk*)this)->is_free(), "Error"); } -////////////////////////////////////////////////////////////////////////////// -// We go over the list of promoted objects, removing each from the list, -// and applying the closure (this may, in turn, add more elements to -// the tail of the promoted list, and these newly added objects will -// also be processed) until the list is empty. -// To aid verification and debugging, in the non-product builds -// we actually forward _promoHead each time we process a promoted oop. -// Note that this is not necessary in general (i.e. when we don't need to -// call PromotionInfo::verify()) because oop_iterate can only add to the -// end of _promoTail, and never needs to look at _promoHead. - -#define PROMOTED_OOPS_ITERATE_DEFN(OopClosureType, nv_suffix) \ - \ -void PromotionInfo::promoted_oops_iterate##nv_suffix(OopClosureType* cl) { \ - NOT_PRODUCT(verify()); \ - PromotedObject *curObj, *nextObj; \ - for (curObj = _promoHead; curObj != NULL; curObj = nextObj) { \ - if ((nextObj = curObj->next()) == NULL) { \ - /* protect ourselves against additions due to closure application \ - below by resetting the list. */ \ - assert(_promoTail == curObj, "Should have been the tail"); \ - _promoHead = _promoTail = NULL; \ - } \ - if (curObj->hasDisplacedMark()) { \ - /* restore displaced header */ \ - oop(curObj)->set_mark_raw(nextDisplacedHeader()); \ - } else { \ - /* restore prototypical header */ \ - oop(curObj)->init_mark_raw(); \ - } \ - /* The "promoted_mark" should now not be set */ \ - assert(!curObj->hasPromotedMark(), \ - "Should have been cleared by restoring displaced mark-word"); \ - NOT_PRODUCT(_promoHead = nextObj); \ - if (cl != NULL) oop(curObj)->oop_iterate(cl); \ - if (nextObj == NULL) { /* start at head of list reset above */ \ - nextObj = _promoHead; \ - } \ - } \ - assert(noPromotions(), "post-condition violation"); \ - assert(_promoHead == NULL && _promoTail == NULL, "emptied promoted list");\ - assert(_spoolHead == _spoolTail, "emptied spooling buffers"); \ - assert(_firstIndex == _nextIndex, "empty buffer"); \ -} - -// This should have been ALL_SINCE_...() just like the others, -// but, because the body of the method above is somehwat longer, -// the MSVC compiler cannot cope; as a workaround, we split the -// macro into its 3 constituent parts below (see original macro -// definition in specializedOopClosures.hpp). -SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(PROMOTED_OOPS_ITERATE_DEFN) -PROMOTED_OOPS_ITERATE_DEFN(OopsInGenClosure,_v) - - // Return the next displaced header, incrementing the pointer and // recycling spool area as necessary. markOop PromotionInfo::nextDisplacedHeader() { diff --git a/src/hotspot/share/gc/cms/promotionInfo.hpp b/src/hotspot/share/gc/cms/promotionInfo.hpp index 821eb2b5d66..aa2de84b77b 100644 --- a/src/hotspot/share/gc/cms/promotionInfo.hpp +++ b/src/hotspot/share/gc/cms/promotionInfo.hpp @@ -165,13 +165,10 @@ class PromotionInfo { bool ensure_spooling_space() { return has_spooling_space() || ensure_spooling_space_work(); } - #define PROMOTED_OOPS_ITERATE_DECL(OopClosureType, nv_suffix) \ - void promoted_oops_iterate##nv_suffix(OopClosureType* cl); - ALL_SINCE_SAVE_MARKS_CLOSURES(PROMOTED_OOPS_ITERATE_DECL) - #undef PROMOTED_OOPS_ITERATE_DECL - void promoted_oops_iterate(OopsInGenClosure* cl) { - promoted_oops_iterate_v(cl); - } + + template + void promoted_oops_iterate(OopClosureType* cl); + void verify() const; void reset() { _promoHead = NULL; diff --git a/src/hotspot/share/gc/cms/promotionInfo.inline.hpp b/src/hotspot/share/gc/cms/promotionInfo.inline.hpp new file mode 100644 index 00000000000..97a71ede522 --- /dev/null +++ b/src/hotspot/share/gc/cms/promotionInfo.inline.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2010, 2018, 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. + * + */ + +#ifndef SHARE_GC_CMS_PROMOTIONINFO_INLINE_HPP +#define SHARE_GC_CMS_PROMOTIONINFO_INLINE_HPP + +#include "gc/cms/promotionInfo.hpp" +#include "oops/oop.inline.hpp" +#include "utilities/debug.hpp" +#include "utilities/macros.hpp" + +////////////////////////////////////////////////////////////////////////////// +// We go over the list of promoted objects, removing each from the list, +// and applying the closure (this may, in turn, add more elements to +// the tail of the promoted list, and these newly added objects will +// also be processed) until the list is empty. +// To aid verification and debugging, in the non-product builds +// we actually forward _promoHead each time we process a promoted oop. +// Note that this is not necessary in general (i.e. when we don't need to +// call PromotionInfo::verify()) because oop_iterate can only add to the +// end of _promoTail, and never needs to look at _promoHead. + +template +void PromotionInfo::promoted_oops_iterate(OopClosureType* cl) { + NOT_PRODUCT(verify()); + PromotedObject *curObj, *nextObj; + for (curObj = _promoHead; curObj != NULL; curObj = nextObj) { + if ((nextObj = curObj->next()) == NULL) { + /* protect ourselves against additions due to closure application + below by resetting the list. */ + assert(_promoTail == curObj, "Should have been the tail"); + _promoHead = _promoTail = NULL; + } + if (curObj->hasDisplacedMark()) { + /* restore displaced header */ + oop(curObj)->set_mark_raw(nextDisplacedHeader()); + } else { + /* restore prototypical header */ + oop(curObj)->init_mark_raw(); + } + /* The "promoted_mark" should now not be set */ + assert(!curObj->hasPromotedMark(), + "Should have been cleared by restoring displaced mark-word"); + NOT_PRODUCT(_promoHead = nextObj); + if (cl != NULL) oop(curObj)->oop_iterate(cl); + if (nextObj == NULL) { /* start at head of list reset above */ + nextObj = _promoHead; + } + } + assert(noPromotions(), "post-condition violation"); + assert(_promoHead == NULL && _promoTail == NULL, "emptied promoted list"); + assert(_spoolHead == _spoolTail, "emptied spooling buffers"); + assert(_firstIndex == _nextIndex, "empty buffer"); +} + +#endif // SHARE_GC_CMS_PROMOTIONINFO_INLINE_HPP diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 354b9d16a48..0413e9c71ac 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -24,7 +24,7 @@ #include "precompiled.hpp" #include "gc/serial/defNewGeneration.inline.hpp" -#include "gc/serial/serialHeap.hpp" +#include "gc/serial/serialHeap.inline.hpp" #include "gc/serial/tenuredGeneration.hpp" #include "gc/shared/adaptiveSizePolicy.hpp" #include "gc/shared/ageTable.inline.hpp" @@ -57,9 +57,6 @@ #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/stack.inline.hpp" -#if INCLUDE_CMSGC -#include "gc/cms/parOopClosures.hpp" -#endif // // DefNewGeneration functions. @@ -103,7 +100,7 @@ FastEvacuateFollowersClosure(SerialHeap* heap, void DefNewGeneration::FastEvacuateFollowersClosure::do_void() { do { - _heap->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older); + _heap->oop_since_save_marks_iterate(_scan_cur_or_nonheap, _scan_older); } while (!_heap->no_allocs_since_save_marks()); guarantee(_heap->young_gen()->promo_failure_scan_is_complete(), "Failed to finish scan"); } @@ -814,22 +811,6 @@ bool DefNewGeneration::no_allocs_since_save_marks() { return to()->saved_mark_at_top(); } -#define DefNew_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix) \ - \ -void DefNewGeneration:: \ -oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl) { \ - cl->set_generation(this); \ - eden()->oop_since_save_marks_iterate##nv_suffix(cl); \ - to()->oop_since_save_marks_iterate##nv_suffix(cl); \ - from()->oop_since_save_marks_iterate##nv_suffix(cl); \ - cl->reset_generation(); \ - save_marks(); \ -} - -ALL_SINCE_SAVE_MARKS_CLOSURES(DefNew_SINCE_SAVE_MARKS_DEFN) - -#undef DefNew_SINCE_SAVE_MARKS_DEFN - void DefNewGeneration::contribute_scratch(ScratchBlock*& list, Generation* requestor, size_t max_alloc_words) { if (requestor == this || _promotion_failed) { diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index 69845a4ed9f..2263d85ff44 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -280,12 +280,8 @@ protected: // Need to declare the full complement of closures, whether we'll // override them or not, or get message from the compiler: // oop_since_save_marks_iterate_nv hides virtual function... -#define DefNew_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \ - void oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl); - - ALL_SINCE_SAVE_MARKS_CLOSURES(DefNew_SINCE_SAVE_MARKS_DECL) - -#undef DefNew_SINCE_SAVE_MARKS_DECL + template + void oop_since_save_marks_iterate(OopClosureType* cl); // For non-youngest collection, the DefNewGeneration can contribute // "to-space". diff --git a/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp b/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp index 49e86dfb47e..84a25410f14 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp @@ -29,7 +29,7 @@ #include "gc/shared/cardTableRS.hpp" #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.inline.hpp" -#include "gc/shared/space.hpp" +#include "gc/shared/space.inline.hpp" #include "oops/access.inline.hpp" // Methods of protected closure types @@ -88,4 +88,14 @@ inline void DefNewGeneration::FastKeepAliveClosure::do_oop_work(T* p) { } } +template +void DefNewGeneration::oop_since_save_marks_iterate(OopClosureType* cl) { + cl->set_generation(this); + eden()->oop_since_save_marks_iterate(cl); + to()->oop_since_save_marks_iterate(cl); + from()->oop_since_save_marks_iterate(cl); + cl->reset_generation(); + save_marks(); +} + #endif // SHARE_VM_GC_SERIAL_DEFNEWGENERATION_INLINE_HPP diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index c347646fbb0..c06252c614d 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -23,9 +23,9 @@ */ #include "precompiled.hpp" -#include "gc/serial/defNewGeneration.hpp" +#include "gc/serial/defNewGeneration.inline.hpp" #include "gc/serial/serialHeap.hpp" -#include "gc/serial/tenuredGeneration.hpp" +#include "gc/serial/tenuredGeneration.inline.hpp" #include "gc/shared/genMemoryPools.hpp" #include "services/memoryManager.hpp" diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 07bac656021..820e00adc71 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -73,6 +73,14 @@ public: assert(_old_gen->kind() == Generation::MarkSweepCompact, "Wrong generation type"); return static_cast(_old_gen); } + + // Apply "cur->do_oop" or "older->do_oop" to all the oops in objects + // allocated since the last call to save_marks in the young generation. + // The "cur" closure is applied to references in the younger generation + // at "level", and the "older" closure to older generations. + template + void oop_since_save_marks_iterate(OopClosureType1* cur, + OopClosureType2* older); }; #endif // SHARE_VM_GC_CMS_CMSHEAP_HPP diff --git a/src/hotspot/share/gc/serial/serialHeap.inline.hpp b/src/hotspot/share/gc/serial/serialHeap.inline.hpp new file mode 100644 index 00000000000..68dd7236633 --- /dev/null +++ b/src/hotspot/share/gc/serial/serialHeap.inline.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017, 2018, 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. + * + */ + +#ifndef SHARE_GC_SERIAL_SERIALHEAP_INLINE_HPP +#define SHARE_GC_SERIAL_SERIALHEAP_INLINE_HPP + +#include "gc/serial/defNewGeneration.inline.hpp" +#include "gc/serial/serialHeap.hpp" +#include "gc/serial/tenuredGeneration.inline.hpp" + +template +void SerialHeap::oop_since_save_marks_iterate(OopClosureType1* cur, + OopClosureType2* older) { + young_gen()->oop_since_save_marks_iterate(cur); + old_gen()->oop_since_save_marks_iterate(older); +} + +#endif // SHARE_GC_SERIAL_SERIALHEAP_INLINE_HPP diff --git a/src/hotspot/share/gc/serial/serial_specialized_oop_closures.hpp b/src/hotspot/share/gc/serial/serial_specialized_oop_closures.hpp index bb73afcfed3..1d83aa48599 100644 --- a/src/hotspot/share/gc/serial/serial_specialized_oop_closures.hpp +++ b/src/hotspot/share/gc/serial/serial_specialized_oop_closures.hpp @@ -50,8 +50,4 @@ class AdjustPointerClosure; f(MarkAndPushClosure,_nv) \ f(AdjustPointerClosure,_nv) -#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f) \ - f(ScanClosure,_nv) \ - f(FastScanClosure,_nv) - #endif // SHARE_GC_SERIAL_SERIAL_SPECIALIZED_OOP_CLOSURES_HPP diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index 3396715957a..e59a1700580 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -256,20 +256,6 @@ bool TenuredGeneration::no_allocs_since_save_marks() { return _the_space->saved_mark_at_top(); } -#define TenuredGen_SINCE_SAVE_MARKS_ITERATE_DEFN(OopClosureType, nv_suffix) \ - \ -void TenuredGeneration:: \ -oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) { \ - blk->set_generation(this); \ - _the_space->oop_since_save_marks_iterate##nv_suffix(blk); \ - blk->reset_generation(); \ - save_marks(); \ -} - -ALL_SINCE_SAVE_MARKS_CLOSURES(TenuredGen_SINCE_SAVE_MARKS_ITERATE_DEFN) - -#undef TenuredGen_SINCE_SAVE_MARKS_ITERATE_DEFN - void TenuredGeneration::gc_epilogue(bool full) { // update the generation and space performance counters update_counters(); diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index 03b9e3daae1..9bd0890c707 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -75,10 +75,8 @@ class TenuredGeneration: public CardGeneration { virtual inline HeapWord* allocate(size_t word_size, bool is_tlab); virtual inline HeapWord* par_allocate(size_t word_size, bool is_tlab); -#define TenuredGen_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \ - void oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl); - TenuredGen_SINCE_SAVE_MARKS_DECL(OopsInGenClosure,_v) - SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(TenuredGen_SINCE_SAVE_MARKS_DECL) + template + void oop_since_save_marks_iterate(OopClosureType* cl); void save_marks(); void reset_saved_marks(); diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp index 490f0abaa48..0e144820ece 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_GC_SERIAL_TENUREDGENERATION_INLINE_HPP #include "gc/serial/tenuredGeneration.hpp" -#include "gc/shared/space.hpp" +#include "gc/shared/space.inline.hpp" HeapWord* TenuredGeneration::allocate(size_t word_size, bool is_tlab) { @@ -53,4 +53,12 @@ bool TenuredGeneration::block_is_obj(const HeapWord* addr) const { return addr < _the_space ->top(); } +template +void TenuredGeneration::oop_since_save_marks_iterate(OopClosureType* blk) { + blk->set_generation(this); + _the_space->oop_since_save_marks_iterate(blk); + blk->reset_generation(); + save_marks(); +} + #endif // SHARE_VM_GC_SERIAL_TENUREDGENERATION_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index 36c9e48021d..775fa8b6609 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -913,23 +913,6 @@ void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) { _old_gen->ref_processor()->weak_oops_do(root_closure); } -#define GCH_SINCE_SAVE_MARKS_ITERATE_DEFN(OopClosureType, nv_suffix) \ -void GenCollectedHeap:: \ -oop_since_save_marks_iterate(GenerationType gen, \ - OopClosureType* cur, \ - OopClosureType* older) { \ - if (gen == YoungGen) { \ - _young_gen->oop_since_save_marks_iterate##nv_suffix(cur); \ - _old_gen->oop_since_save_marks_iterate##nv_suffix(older); \ - } else { \ - _old_gen->oop_since_save_marks_iterate##nv_suffix(cur); \ - } \ -} - -ALL_SINCE_SAVE_MARKS_CLOSURES(GCH_SINCE_SAVE_MARKS_ITERATE_DEFN) - -#undef GCH_SINCE_SAVE_MARKS_ITERATE_DEFN - bool GenCollectedHeap::no_allocs_since_save_marks() { return _young_gen->no_allocs_since_save_marks() && _old_gen->no_allocs_since_save_marks(); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index 76c2a935575..a8b4dd704f9 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -435,20 +435,6 @@ public: // in other generations, it should call this method. void save_marks(); - // Apply "cur->do_oop" or "older->do_oop" to all the oops in objects - // allocated since the last call to save_marks in generations at or above - // "level". The "cur" closure is - // applied to references in the generation at "level", and the "older" - // closure to older generations. -#define GCH_SINCE_SAVE_MARKS_ITERATE_DECL(OopClosureType, nv_suffix) \ - void oop_since_save_marks_iterate(GenerationType start_gen, \ - OopClosureType* cur, \ - OopClosureType* older); - - ALL_SINCE_SAVE_MARKS_CLOSURES(GCH_SINCE_SAVE_MARKS_ITERATE_DECL) - -#undef GCH_SINCE_SAVE_MARKS_ITERATE_DECL - // Returns "true" iff no allocations have occurred since the last // call to "save_marks". bool no_allocs_since_save_marks(); diff --git a/src/hotspot/share/gc/shared/generation.hpp b/src/hotspot/share/gc/shared/generation.hpp index b9f66799165..dc74e119833 100644 --- a/src/hotspot/share/gc/shared/generation.hpp +++ b/src/hotspot/share/gc/shared/generation.hpp @@ -442,25 +442,6 @@ class Generation: public CHeapObj { // generation since the last call to "save_marks". virtual bool no_allocs_since_save_marks() = 0; - // Apply "cl->apply" to (the addresses of) all reference fields in objects - // allocated in the current generation since the last call to "save_marks". - // If more objects are allocated in this generation as a result of applying - // the closure, iterates over reference fields in those objects as well. - // Calls "save_marks" at the end of the iteration. - // General signature... - virtual void oop_since_save_marks_iterate_v(OopsInGenClosure* cl) = 0; - // ...and specializations for de-virtualization. (The general - // implementation of the _nv versions call the virtual version. - // Note that the _nv suffix is not really semantically necessary, - // but it avoids some not-so-useful warnings on Solaris.) -#define Generation_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \ - virtual void oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl) { \ - oop_since_save_marks_iterate_v((OopsInGenClosure*)cl); \ - } - SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(Generation_SINCE_SAVE_MARKS_DECL) - -#undef Generation_SINCE_SAVE_MARKS_DECL - // The "requestor" generation is performing some garbage collection // action for which it would be useful to have scratch space. If // the target is not the requestor, no gc actions will be required diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index 82b62dd3e24..ecf4b94741f 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -550,32 +550,6 @@ ContiguousSpace::object_iterate_careful(ObjectClosureCareful* blk) { return NULL; // all done } -#define ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix) \ - \ -void ContiguousSpace:: \ -oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) { \ - HeapWord* t; \ - HeapWord* p = saved_mark_word(); \ - assert(p != NULL, "expected saved mark"); \ - \ - const intx interval = PrefetchScanIntervalInBytes; \ - do { \ - t = top(); \ - while (p < t) { \ - Prefetch::write(p, interval); \ - debug_only(HeapWord* prev = p); \ - oop m = oop(p); \ - p += m->oop_iterate_size(blk); \ - } \ - } while (t < top()); \ - \ - set_saved_mark_word(p); \ -} - -ALL_SINCE_SAVE_MARKS_CLOSURES(ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN) - -#undef ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN - // Very general, slow implementation. HeapWord* ContiguousSpace::block_start_const(const void* p) const { assert(MemRegion(bottom(), end()).contains(p), diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index f7e44ced8d5..ef869ba4dd2 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -639,11 +639,8 @@ class ContiguousSpace: public CompactibleSpace { // *are* included in the iteration. // Updates _saved_mark_word to point to just after the last object // iterated over. -#define ContigSpace_OOP_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \ - void oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk); - - ALL_SINCE_SAVE_MARKS_CLOSURES(ContigSpace_OOP_SINCE_SAVE_MARKS_DECL) -#undef ContigSpace_OOP_SINCE_SAVE_MARKS_DECL + template + void oop_since_save_marks_iterate(OopClosureType* blk); // Same as object_iterate, but starting from "mark", which is required // to denote the start of an object. Objects allocated by diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp index 24345b0be8e..1ec71164939 100644 --- a/src/hotspot/share/gc/shared/space.inline.hpp +++ b/src/hotspot/share/gc/shared/space.inline.hpp @@ -357,4 +357,24 @@ size_t ContiguousSpace::scanned_block_size(const HeapWord* addr) const { return oop(addr)->size(); } +template +void ContiguousSpace::oop_since_save_marks_iterate(OopClosureType* blk) { + HeapWord* t; + HeapWord* p = saved_mark_word(); + assert(p != NULL, "expected saved mark"); + + const intx interval = PrefetchScanIntervalInBytes; + do { + t = top(); + while (p < t) { + Prefetch::write(p, interval); + debug_only(HeapWord* prev = p); + oop m = oop(p); + p += m->oop_iterate_size(blk); + } + } while (t < top()); + + set_saved_mark_word(p); +} + #endif // SHARE_VM_GC_SHARED_SPACE_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/specialized_oop_closures.hpp b/src/hotspot/share/gc/shared/specialized_oop_closures.hpp index 66c5fa85abb..f6942c55dfd 100644 --- a/src/hotspot/share/gc/shared/specialized_oop_closures.hpp +++ b/src/hotspot/share/gc/shared/specialized_oop_closures.hpp @@ -91,25 +91,4 @@ class OopsInGenClosure; f(ExtendedOopClosure,_v) \ CMSGC_ONLY(SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f)) -// This macro applies an argument macro to all OopClosures for which we -// want specialized bodies of a family of methods related to -// "oops_since_save_marks_do". The arguments to f are the same as above. -// The "root_class" is the most general class to define; this may be -// "OopClosure" in some applications and "OopsInGenClosure" in others. - -#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f) \ - SERIALGC_ONLY(SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f)) \ - CMSGC_ONLY(SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f)) - -#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) \ - SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f) - -// We separate these out, because sometime the general one has -// a different definition from the specialized ones, and sometimes it -// doesn't. - -#define ALL_SINCE_SAVE_MARKS_CLOSURES(f) \ - f(OopsInGenClosure,_v) \ - SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) - #endif // SHARE_VM_GC_SHARED_SPECIALIZED_OOP_CLOSURES_HPP From 5f40eda733c58ed22a699afe41fca547d4743920 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 7 May 2018 14:42:10 +0200 Subject: [PATCH 21/40] 8202642: Replace PAR_OOP_ITERATE with templates Reviewed-by: eosterlund, sjohanss --- .../gc/cms/cms_specialized_oop_closures.hpp | 6 ------ .../gc/cms/concurrentMarkSweepGeneration.cpp | 1 + src/hotspot/share/gc/shared/space.cpp | 17 ----------------- src/hotspot/share/gc/shared/space.hpp | 10 ++-------- src/hotspot/share/gc/shared/space.inline.hpp | 10 ++++++++++ .../gc/shared/specialized_oop_closures.hpp | 11 ----------- 6 files changed, 13 insertions(+), 42 deletions(-) diff --git a/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp b/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp index 064e0b80819..5a3d88c8f37 100644 --- a/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp +++ b/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp @@ -60,10 +60,4 @@ class CMSInnerParMarkAndPushClosure; f(CMSKeepAliveClosure,_nv) \ f(CMSInnerParMarkAndPushClosure,_nv) -#define SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f) \ - f(MarkRefsIntoAndScanClosure,_nv) \ - f(PushAndMarkClosure,_nv) \ - f(ParMarkRefsIntoAndScanClosure,_nv) \ - f(ParPushAndMarkClosure,_nv) - #endif // SHARE_GC_CMS_CMS_SPECIALIZED_OOP_CLOSURES_HPP diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index ef855456063..df7a44426e2 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -55,6 +55,7 @@ #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/isGCActiveMark.hpp" #include "gc/shared/referencePolicy.hpp" +#include "gc/shared/space.inline.hpp" #include "gc/shared/strongRootsScope.hpp" #include "gc/shared/taskqueue.inline.hpp" #include "gc/shared/weakProcessor.hpp" diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index ecf4b94741f..5fa1ec8cae1 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -490,23 +490,6 @@ bool Space::obj_is_alive(const HeapWord* p) const { return true; } -#if INCLUDE_CMSGC -#define ContigSpace_PAR_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ - \ - void ContiguousSpace::par_oop_iterate(MemRegion mr, OopClosureType* blk) {\ - HeapWord* obj_addr = mr.start(); \ - HeapWord* t = mr.end(); \ - while (obj_addr < t) { \ - assert(oopDesc::is_oop(oop(obj_addr)), "Should be an oop"); \ - obj_addr += oop(obj_addr)->oop_iterate_size(blk); \ - } \ - } - - ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DEFN) - -#undef ContigSpace_PAR_OOP_ITERATE_DEFN -#endif // INCLUDE_CMSGC - void ContiguousSpace::oop_iterate(ExtendedOopClosure* blk) { if (is_empty()) return; HeapWord* obj_addr = bottom(); diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index ef869ba4dd2..5073e2e1b4b 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -608,15 +608,9 @@ class ContiguousSpace: public CompactibleSpace { _concurrent_iteration_safe_limit = new_limit; } - -#if INCLUDE_CMSGC // In support of parallel oop_iterate. - #define ContigSpace_PAR_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \ - void par_oop_iterate(MemRegion mr, OopClosureType* blk); - - ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DECL) - #undef ContigSpace_PAR_OOP_ITERATE_DECL -#endif // INCLUDE_CMSGC + template + void par_oop_iterate(MemRegion mr, OopClosureType* blk); // Compaction support virtual void reset_after_compaction() { diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp index 1ec71164939..672118930cd 100644 --- a/src/hotspot/share/gc/shared/space.inline.hpp +++ b/src/hotspot/share/gc/shared/space.inline.hpp @@ -377,4 +377,14 @@ void ContiguousSpace::oop_since_save_marks_iterate(OopClosureType* blk) { set_saved_mark_word(p); } +template +void ContiguousSpace::par_oop_iterate(MemRegion mr, OopClosureType* blk) { + HeapWord* obj_addr = mr.start(); + HeapWord* limit = mr.end(); + while (obj_addr < limit) { + assert(oopDesc::is_oop(oop(obj_addr)), "Should be an oop"); + obj_addr += oop(obj_addr)->oop_iterate_size(blk); + } +} + #endif // SHARE_VM_GC_SHARED_SPACE_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/specialized_oop_closures.hpp b/src/hotspot/share/gc/shared/specialized_oop_closures.hpp index f6942c55dfd..af2ab821563 100644 --- a/src/hotspot/share/gc/shared/specialized_oop_closures.hpp +++ b/src/hotspot/share/gc/shared/specialized_oop_closures.hpp @@ -80,15 +80,4 @@ class OopsInGenClosure; #define ALL_OOP_OOP_ITERATE_CLOSURES_2(f) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) -// This macro applies an argument macro to all OopClosures for which we -// want specialized bodies of a family of methods related to -// "par_oop_iterate". The arguments to f are the same as above. -// The "root_class" is the most general class to define; this may be -// "OopClosure" in some applications and "OopsInGenClosure" in others. - - -#define ALL_PAR_OOP_ITERATE_CLOSURES(f) \ - f(ExtendedOopClosure,_v) \ - CMSGC_ONLY(SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f)) - #endif // SHARE_VM_GC_SHARED_SPECIALIZED_OOP_CLOSURES_HPP From 72a2ac8b8bbf2f174fd574bad6bc3920b9477069 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Mon, 7 May 2018 11:38:21 +0200 Subject: [PATCH 22/40] 8199852: Print more information about class loaders in LinkageErrors Reviewed-by: dholmes, lfoltan, gtriantafill --- src/hotspot/share/classfile/javaClasses.cpp | 42 +++++++ src/hotspot/share/classfile/javaClasses.hpp | 6 + .../share/classfile/systemDictionary.cpp | 55 ++++---- .../share/interpreter/linkResolver.cpp | 16 +-- src/hotspot/share/oops/klassVtable.cpp | 43 +++---- .../runtime/LoaderConstraints/common/C.jasm | 4 +- .../runtime/LoaderConstraints/common/Foo.java | 4 +- .../runtime/LoaderConstraints/common/J.java | 4 +- .../common/PreemptingClassLoader.java | 16 ++- .../differentLE/D_ambgs.jasm | 67 ++++++++++ .../LoaderConstraints/differentLE/Test.java | 118 ++++++++++++++++++ .../LoaderConstraints/differentLE/test/A.java | 32 +++++ .../LoaderConstraints/differentLE/test/B.java | 35 ++++++ .../LoaderConstraints/differentLE/test/C.java | 29 +++++ .../differentLE/test/D_ambgs.java | 43 +++++++ .../LoaderConstraints/duplicateLE/Test.java | 90 +++++++++++++ .../LoaderConstraints/itableICCE/I.java | 4 +- .../LoaderConstraints/itableICCE/Task.java | 4 +- .../LoaderConstraints/itableICCE/Test.java | 10 +- .../itableLdrConstraint/I.java | 4 +- .../itableLdrConstraint/Task.java | 4 +- .../itableLdrConstraint/Test.java | 47 +++++-- .../LoaderConstraints/vtableAME/I.java | 4 +- .../LoaderConstraints/vtableAME/Task.java | 4 +- .../LoaderConstraints/vtableAME/Test.java | 14 +-- .../vtableLdrConstraint/I.java | 4 +- .../vtableLdrConstraint/Task.java | 4 +- .../vtableLdrConstraint/Test.java | 50 ++++++-- 28 files changed, 660 insertions(+), 97 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/D_ambgs.jasm create mode 100644 test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/Test.java create mode 100644 test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/A.java create mode 100644 test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/B.java create mode 100644 test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/C.java create mode 100644 test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/D_ambgs.java create mode 100644 test/hotspot/jtreg/runtime/LoaderConstraints/duplicateLE/Test.java diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index a6d3c8b3c13..29b6f7c05e6 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -4134,6 +4134,48 @@ oop java_lang_ClassLoader::unnamedModule(oop loader) { return loader->obj_field(unnamedModule_offset); } +// Caller needs ResourceMark. +const char* java_lang_ClassLoader::describe_external(const oop loader) { + if (loader == NULL) { + return ""; + } + + bool well_known_loader = SystemDictionary::is_system_class_loader(loader) || + SystemDictionary::is_platform_class_loader(loader); + + const char* name = NULL; + oop nameOop = java_lang_ClassLoader::name(loader); + if (nameOop != NULL) { + name = java_lang_String::as_utf8_string(nameOop); + } + if (name == NULL) { + // Use placeholder for missing name to have fixed message format. + name = ""; + } + + stringStream ss; + ss.print("\"%s\" (instance of %s", name, loader->klass()->external_name()); + if (!well_known_loader) { + const char* parentName = NULL; + oop pl = java_lang_ClassLoader::parent(loader); + if (pl != NULL) { + oop parentNameOop = java_lang_ClassLoader::name(pl); + if (parentNameOop != NULL) { + parentName = java_lang_String::as_utf8_string(parentNameOop); + if (parentName == NULL) { + parentName = ""; + } + } + ss.print(", child of \"%s\" %s", parentName, pl->klass()->external_name()); + } else { + ss.print(", child of "); + } + } + ss.print(")"); + + return ss.as_string(); +} + // Support for java_lang_System // #define SYSTEM_FIELDS_DO(macro) \ diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 79c2db13800..83a80cc3a39 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -1321,6 +1321,12 @@ class java_lang_ClassLoader : AllStatic { // Debugging friend class JavaClasses; friend class ClassFileParser; // access to number_of_fake_fields + + // Describe ClassLoader for exceptions, tracing ... + // Prints "" (instance of , child of "" ). + // If a classloader has no name, it prints instead. The output + // for well known loaders (system/platform) is abbreviated. + static const char* describe_external(const oop loader); }; diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 8035981b52c..184031a5ae7 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -2124,10 +2124,19 @@ BasicType SystemDictionary::box_klass_type(Klass* k) { void SystemDictionary::check_constraints(unsigned int d_hash, InstanceKlass* k, - Handle class_loader, bool defining, + Handle class_loader, + bool defining, TRAPS) { + ResourceMark rm(THREAD); + stringStream ss; + bool throwException = false; + const char *linkage_error1 = NULL; const char *linkage_error2 = NULL; + const char *linkage_error3 = ""; + // Remember the loader of the similar class that is already loaded. + const char *existing_klass_loader_name = ""; + { Symbol* name = k->name(); ClassLoaderData *loader_data = class_loader_data(class_loader); @@ -2136,16 +2145,18 @@ void SystemDictionary::check_constraints(unsigned int d_hash, InstanceKlass* check = find_class(d_hash, name, loader_data->dictionary()); if (check != NULL) { - // if different InstanceKlass - duplicate class definition, - // else - ok, class loaded by a different thread in parallel, - // we should only have found it if it was done loading and ok to use - // dictionary only holds instance classes, placeholders - // also holds array classes + // If different InstanceKlass - duplicate class definition, + // else - ok, class loaded by a different thread in parallel. + // We should only have found it if it was done loading and ok to use. + // The dictionary only holds instance classes, placeholders + // also hold array classes. assert(check->is_instance_klass(), "noninstance in systemdictionary"); if ((defining == true) || (k != check)) { - linkage_error1 = "loader (instance of "; - linkage_error2 = "): attempted duplicate class definition for name: \""; + throwException = true; + ss.print("loader %s", java_lang_ClassLoader::describe_external(class_loader())); + ss.print(" attempted duplicate %s definition for %s.", + k->external_kind(), k->external_name()); } else { return; } @@ -2156,30 +2167,30 @@ void SystemDictionary::check_constraints(unsigned int d_hash, assert(ph_check == NULL || ph_check == name, "invalid symbol"); #endif - if (linkage_error1 == NULL) { + if (throwException == false) { if (constraints()->check_or_update(k, class_loader, name) == false) { - linkage_error1 = "loader constraint violation: loader (instance of "; - linkage_error2 = ") previously initiated loading for a different type with name \""; + throwException = true; + ss.print("loader constraint violation: loader %s", + java_lang_ClassLoader::describe_external(class_loader())); + ss.print(" wants to load %s %s.", + k->external_kind(), k->external_name()); + Klass *existing_klass = constraints()->find_constrained_klass(name, class_loader); + if (existing_klass->class_loader() != class_loader()) { + ss.print(" A different %s with the same name was previously loaded by %s.", + existing_klass->external_kind(), + java_lang_ClassLoader::describe_external(existing_klass->class_loader())); + } } } } // Throw error now if needed (cannot throw while holding // SystemDictionary_lock because of rank ordering) - - if (linkage_error1) { - ResourceMark rm(THREAD); - const char* class_loader_name = loader_name(class_loader()); - char* type_name = k->name()->as_C_string(); - size_t buflen = strlen(linkage_error1) + strlen(class_loader_name) + - strlen(linkage_error2) + strlen(type_name) + 2; // +2 for '"' and null byte. - char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); - jio_snprintf(buf, buflen, "%s%s%s%s\"", linkage_error1, class_loader_name, linkage_error2, type_name); - THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); + if (throwException == true) { + THROW_MSG(vmSymbols::java_lang_LinkageError(), ss.as_string()); } } - // Update class loader data dictionary - done after check_constraint and add_to_hierachy // have been called. void SystemDictionary::update_dictionary(unsigned int d_hash, diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index 4763897adac..029e29cb2b8 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -655,13 +655,13 @@ void LinkResolver::check_method_loader_constraints(const LinkInfo& link_info, resolved_loader, true, CHECK); if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation: when resolving %s" - " \"%s\" the class loader (instance of %s) of the current class, %s," - " and the class loader (instance of %s) for the method's defining class, %s, have" + " \"%s\" the class loader %s of the current class, %s," + " and the class loader %s for the method's defining class, %s, have" " different Class objects for the type %s used in the signature"; char* sig = link_info.method_string(); - const char* loader1_name = SystemDictionary::loader_name(current_loader()); + const char* loader1_name = java_lang_ClassLoader::describe_external(current_loader()); char* current = link_info.current_klass()->name()->as_C_string(); - const char* loader2_name = SystemDictionary::loader_name(resolved_loader()); + const char* loader2_name = java_lang_ClassLoader::describe_external(resolved_loader()); char* target = resolved_method->method_holder()->name()->as_C_string(); char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1_name) + @@ -688,13 +688,13 @@ void LinkResolver::check_field_loader_constraints(Symbol* field, Symbol* sig, CHECK); if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation: when resolving field" - " \"%s\" the class loader (instance of %s) of the referring class, " - "%s, and the class loader (instance of %s) for the field's resolved " + " \"%s\" the class loader %s of the referring class, " + "%s, and the class loader %s for the field's resolved " "type, %s, have different Class objects for that type"; char* field_name = field->as_C_string(); - const char* loader1_name = SystemDictionary::loader_name(ref_loader()); + const char* loader1_name = java_lang_ClassLoader::describe_external(ref_loader()); char* sel = sel_klass->name()->as_C_string(); - const char* loader2_name = SystemDictionary::loader_name(sel_loader()); + const char* loader2_name = java_lang_ClassLoader::describe_external(sel_loader()); char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1_name) + strlen(sel) + strlen(loader2_name) + strlen(failed_type_name) + 1; diff --git a/src/hotspot/share/oops/klassVtable.cpp b/src/hotspot/share/oops/klassVtable.cpp index a6bcef24b85..afa37adb9a5 100644 --- a/src/hotspot/share/oops/klassVtable.cpp +++ b/src/hotspot/share/oops/klassVtable.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "jvm.h" +#include "classfile/javaClasses.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" @@ -506,21 +507,21 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, const methodHand CHECK_(false)); if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation for class %s: when selecting " - "overriding method \"%s\" the class loader (instance of %s) of the " - "selected method's type %s, and the class loader (instance of %s) for its super " + "overriding method %s the class loader %s of the " + "selected method's type %s, and the class loader %s for its super " "type %s have different Class objects for the type %s used in the signature"; - char* curr_class = klass->name()->as_C_string(); - char* sig = target_method()->name_and_sig_as_C_string(); - const char* loader1 = SystemDictionary::loader_name(target_loader()); - char* sel_class = target_klass->name()->as_C_string(); - const char* loader2 = SystemDictionary::loader_name(super_loader()); - char* super_class = super_klass->name()->as_C_string(); - char* failed_type_name = failed_type_symbol->as_C_string(); - size_t buflen = strlen(msg) + strlen(curr_class) + strlen(sig) + + const char* curr_class = klass->external_name(); + const char* method = target_method()->name_and_sig_as_C_string(); + const char* loader1 = java_lang_ClassLoader::describe_external(target_loader()); + const char* sel_class = target_klass->external_name(); + const char* loader2 = java_lang_ClassLoader::describe_external(super_loader()); + const char* super_class = super_klass->external_name(); + const char* failed_type_name = failed_type_symbol->as_klass_external_name(); + size_t buflen = strlen(msg) + strlen(curr_class) + strlen(method) + strlen(loader1) + strlen(sel_class) + strlen(loader2) + strlen(super_class) + strlen(failed_type_name); char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); - jio_snprintf(buf, buflen, msg, curr_class, sig, loader1, sel_class, loader2, + jio_snprintf(buf, buflen, msg, curr_class, method, loader1, sel_class, loader2, super_class, failed_type_name); THROW_MSG_(vmSymbols::java_lang_LinkageError(), buf, false); } @@ -1236,17 +1237,17 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass true, CHECK); if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation in interface itable" - " initialization for class %s: when selecting method \"%s\" the" - " class loader (instance of %s) for super interface %s, and the class" - " loader (instance of %s) of the selected method's type, %s have" + " initialization for class %s: when selecting method %s the" + " class loader %s for super interface %s, and the class" + " loader %s of the selected method's type, %s have" " different Class objects for the type %s used in the signature"; - char* current = _klass->name()->as_C_string(); - char* sig = m->name_and_sig_as_C_string(); - const char* loader1 = SystemDictionary::loader_name(interface_loader()); - char* iface = InstanceKlass::cast(interf)->name()->as_C_string(); - const char* loader2 = SystemDictionary::loader_name(method_holder_loader()); - char* mclass = target()->method_holder()->name()->as_C_string(); - char* failed_type_name = failed_type_symbol->as_C_string(); + const char* current = _klass->external_name(); + const char* sig = m->name_and_sig_as_C_string(); + const char* loader1 = java_lang_ClassLoader::describe_external(interface_loader()); + const char* iface = InstanceKlass::cast(interf)->external_name(); + const char* loader2 = java_lang_ClassLoader::describe_external(method_holder_loader()); + const char* mclass = target()->method_holder()->external_name(); + const char* failed_type_name = failed_type_symbol->as_klass_external_name(); size_t buflen = strlen(msg) + strlen(current) + strlen(sig) + strlen(loader1) + strlen(iface) + strlen(loader2) + strlen(mclass) + strlen(failed_type_name); diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/common/C.jasm b/test/hotspot/jtreg/runtime/LoaderConstraints/common/C.jasm index a7d3f94dffd..d308cf8a6f2 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/common/C.jasm +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/common/C.jasm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -26,6 +26,8 @@ // class C inherits unrelated defaults for m() from types I and J // C is not abstract and does not override abstract method m() in I +package test; + super public class C implements I, J version 52:0 { public Method "":"()V" stack 1 locals 1 { diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/common/Foo.java b/test/hotspot/jtreg/runtime/LoaderConstraints/common/Foo.java index 1a82277ad34..e8a2319b0af 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/common/Foo.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/common/Foo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,4 +21,6 @@ * questions. */ +package test; + public class Foo {} diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/common/J.java b/test/hotspot/jtreg/runtime/LoaderConstraints/common/J.java index e9f58ca2777..81266f35f85 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/common/J.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/common/J.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,6 +21,8 @@ * questions. */ +package test; + public interface J { public default Foo m() { return null; } } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/common/PreemptingClassLoader.java b/test/hotspot/jtreg/runtime/LoaderConstraints/common/PreemptingClassLoader.java index 2cc8db0b3ec..29f2c2f01d3 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/common/PreemptingClassLoader.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/common/PreemptingClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -27,14 +27,26 @@ import java.io.*; public class PreemptingClassLoader extends ClassLoader { private final Set names = new HashSet<>(); + boolean checkLoaded = true; public PreemptingClassLoader(String... names) { for (String n : names) this.names.add(n); } + public PreemptingClassLoader(String name, String[] names) { + super(name, ClassLoader.getSystemClassLoader()); + for (String n : names) this.names.add(n); + } + + public PreemptingClassLoader(String name, String[] names, boolean cL) { + super(name, ClassLoader.getSystemClassLoader()); + for (String n : names) this.names.add(n); + checkLoaded = cL; + } + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { if (!names.contains(name)) return super.loadClass(name, resolve); - Class result = findLoadedClass(name); + Class result = checkLoaded ? findLoadedClass(name) : null; if (result == null) { String filename = name.replace('.', '/') + ".class"; try (InputStream data = getResourceAsStream(filename)) { diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/D_ambgs.jasm b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/D_ambgs.jasm new file mode 100644 index 00000000000..6a63a380f04 --- /dev/null +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/D_ambgs.jasm @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 test; + +// A simple class to extend an abstract class and get loaded with different +// loaders. This class is loaded via Loader2. A similar named class will +// be loaded via the bootstrap loader. +// +// The following code is implemented as java assembler to avoid checks +// of javac. +// +// public class D_ambgs extends bug_21227 { +// +// D_ambgs() { +// System.out.println("Gonna hack this thing"); +// } +// +// public D_ambgs[] make(A iface) { +// throw new Error("do not call me"); +// } +// } + +class D_ambgs extends C { + + Method D_ambgs:"()V" + stack 2 locals 1 + { + aload_0; + invokespecial Method test/C."":"()V"; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + ldc String "Gonna hack this thing"; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; + return; + } + + public Method make:"(Ltest/A;)[Ltest/D_ambgs;" + stack 3 locals 2 + { + new class java/lang/Error; + dup; + ldc String "do not call me"; + invokespecial Method java/lang/Error."":"(Ljava/lang/String;)V"; + athrow; + } +} diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/Test.java b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/Test.java new file mode 100644 index 00000000000..85c573919ff --- /dev/null +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/Test.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018 SAP SE. 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 8199852 + * @summary Test exception messages of LinkageError. Two class loaders load + * two different versions of a class. Should trigger exception in + * SystemDictionary::check_constraints(). + * @library /test/lib + * @compile D_ambgs.jasm + * @run driver ClassFileInstaller test.D_ambgs + * @compile ../common/PreemptingClassLoader.java + * test/D_ambgs.java Test.java test/B.java + * @run driver ClassFileInstaller test.B + * @run main/othervm Test + */ + +import test.*; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class Test { + + // Force LinkageError. + // + // Derived from test runtime/6626217. + // + // Uses the specialized class loader PreemptingClassLoader. + // PreemptingClassLoader only loads files with names passed to it in its + // constructor. If it does not find it, it delegates to the super class loader. + // + // A // interface + // | + // B // Compiled to the current working directory so that it is found by our + // // special class loader. B uses D, so that loading B triggers loading D. + // + // C // An abstract class. + // | + // D // Class with two different implementations D1 and D2. D2 is + // // compiled to the current working directory so that it is found by our + // // special class loader. + // + // First, the bootstrap loader will load D1. It already has loaded interface A. + // Then, the second class loader PreemptingClassLoader will load B. Recursive, + // it tries to load interface A. As it does not find it (there is no A.impl2), + // it asks the super classloader for A. + // Then it loads the D2 variant of D from the current working directory and it's + // superclass C. This fails as D1 is already loaded with the same superclass. + + static String expectedErrorMessage = + "loader constraint violation: loader \"\" (instance of PreemptingClassLoader, " + + "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) wants to load " + + "class test.D_ambgs. A different class with the same name was previously loaded " + + "by \"app\" (instance of jdk.internal.loader.ClassLoaders$AppClassLoader)."; + + public static void test_access() throws Exception { + try { + // Make a Class 'D_ambgs' under the default loader. + // This uses the implementation from the .java file. + C c_1 = new D_ambgs(); + + // Some classes under a new Loader, loader2, including, indirectly, + // another version of 'D_ambgs' + String[] classNames = {"test.B", "test.D_ambgs"}; + + ClassLoader loader2 = new PreemptingClassLoader(null, classNames, false); + Class class2 = loader2.loadClass("test.B"); + A iface = (A)class2.newInstance(); + + // Call D1.make() loaded by bootstrap loader with B loaded by Loader2. + D_ambgs[] x2 = c_1.make(iface); + + throw new RuntimeException("Expected LinkageError was not thrown."); + } catch (LinkageError jle) { + String errorMsg = jle.getMessage(); + if (!errorMsg.equals(expectedErrorMessage)) { + System.out.println("Expected: " + expectedErrorMessage + "\n" + + "but got: " + errorMsg); + throw new RuntimeException("Wrong error message of LinkageError."); + } else { + System.out.println("Passed with message: " + errorMsg); + } + } + } + + public static void main(String[] args) throws Exception { + test_access(); + } +} + diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/A.java b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/A.java new file mode 100644 index 00000000000..ca94e35562b --- /dev/null +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/A.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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 test; + +// A simple interface, to allow an unknown foreign call from a class +// loaded with the bootstrap loader to a class loaded with Loader2. +public interface A { + public D_ambgs[] gen(); +} + diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/B.java b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/B.java new file mode 100644 index 00000000000..e21377ad2fb --- /dev/null +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/B.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, 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 test; + +// This class is loaded via Loader2. Using D_ambgs here will trigger +// loading it's second version with Loader2. +public class B implements A { + public D_ambgs[] gen() { + D_ambgs[] x = new D_ambgs[1]; + x[0] = new D_ambgs(); + return x; + } +} diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/C.java b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/C.java new file mode 100644 index 00000000000..fa55213041f --- /dev/null +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/C.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, 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 test; + +abstract public class C { + public abstract D_ambgs[] make(A iface); // abstract factory +} diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/D_ambgs.java b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/D_ambgs.java new file mode 100644 index 00000000000..d078eb4afaf --- /dev/null +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/test/D_ambgs.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, 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 test; + +// A simple class to extend an abstract class and get loaded with different +// loaders. This class is loaded via the bootstrap loader. A similar named class will +// be loaded via Loader2. +public class D_ambgs extends C { + + // We are loaded by the bootstrap loader. iface is an object of a class + // loaded by Loader2. As it references D_ambgs, Loader2 will trigger + // loading the version known to it, which differs from this one. + public D_ambgs[] make(A iface) { + // This function needs to return a value known to be loaded from Loader2. + // Since I need to use a yet different loader, I need to make an unknown + // foreign call. In this case I'll be using an interface to make the + // unknown call, with but a single implementor so the compiler can do the + // upcast statically. + return iface == null ? null : iface.gen(); + } +} diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/duplicateLE/Test.java b/test/hotspot/jtreg/runtime/LoaderConstraints/duplicateLE/Test.java new file mode 100644 index 00000000000..e520379bfa1 --- /dev/null +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/duplicateLE/Test.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, 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 8199852 + * @summary Test exception messages of LinkageError. A class loader loads + * twice the same class. Should trigger exception in + * SystemDictionary::check_constraints(). + * @compile ../common/Foo.java + * @compile ../common/J.java + * ../common/PreemptingClassLoader.java + * @run main/othervm Test + */ + +public class Test { + + // Check that all names have external formatting ('.' and not '/' in package names). + // Check for parent of class loader. + static String expectedErrorMessage1 = + "loader \"\" (instance of PreemptingClassLoader, " + + "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "attempted duplicate class definition for test.Foo."; + + // Check that all names have external formatting ('.' and not '/' in package names). + // Check for name and parent of class loader. + static String expectedErrorMessage2 = + "loader \"DuplicateLE_Test_Loader\" (instance of PreemptingClassLoader, " + + "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "attempted duplicate class definition for test.Foo."; + + // Check that all names have external formatting ('.' and not '/' in package names). + // Check for name and parent of class loader. Type should be mentioned as 'interface'. + static String expectedErrorMessage3 = + "loader \"DuplicateLE_Test_Loader_IF\" (instance of PreemptingClassLoader, " + + "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "attempted duplicate interface definition for test.J."; + + // Test that the error message is correct when a loader constraint error is + // detected during vtable creation. + // + // In this test, during vtable creation for class Task, method "Task.m()LFoo;" + // overrides "J.m()LFoo;". But, Task's class Foo and super type J's class Foo + // are different. So, a LinkageError exception should be thrown because the + // loader constraint check will fail. + public static void test(String loaderName, String expectedErrorMessage, String testType) throws Exception { + String[] classNames = {testType}; + ClassLoader l = new PreemptingClassLoader(loaderName, classNames, false); + l.loadClass(testType); + try { + l.loadClass(testType).newInstance(); + throw new RuntimeException("Expected LinkageError exception not thrown"); + } catch (LinkageError e) { + String errorMsg = e.getMessage(); + if (!errorMsg.equals(expectedErrorMessage)) { + System.out.println("Expected: " + expectedErrorMessage + "\n" + + "but got: " + errorMsg); + throw new RuntimeException("Wrong LinkageError exception thrown: " + errorMsg); + } + System.out.println("Passed with message: " + errorMsg); + } + } + + public static void main(String args[]) throws Exception { + test(null, expectedErrorMessage1, "test.Foo"); + test("DuplicateLE_Test_Loader", expectedErrorMessage2, "test.Foo"); + test("DuplicateLE_Test_Loader_IF", expectedErrorMessage3, "test.J"); + } +} + diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/I.java b/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/I.java index 25a6c63acfc..360bb2c8a2a 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/I.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/I.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,6 +21,8 @@ * questions. */ +package test; + public interface I { public default Foo m() { return null; } } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/Task.java b/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/Task.java index 144d8514010..b2dce5c580c 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/Task.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/Task.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,6 +21,8 @@ * questions. */ +package test; + public class Task implements Runnable { public void run() { diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/Test.java b/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/Test.java index 3cc83b2351b..8855ecf0f70 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/Test.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/itableICCE/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -44,14 +44,14 @@ public class Test { // ICCE). So, no LinkageError exception should be thrown because the loader // constraint check that would cause the LinkageError should not be done. public static void main(String... args) throws Exception { - Class c = Foo.class; // forces standard class loader to load Foo - ClassLoader l = new PreemptingClassLoader("Task", "Foo", "C", "I"); - Runnable r = (Runnable) l.loadClass("Task").newInstance(); + Class c = test.Foo.class; // forces standard class loader to load Foo + ClassLoader l = new PreemptingClassLoader("test.Task", "test.Foo", "test.C", "test.I"); + Runnable r = (Runnable) l.loadClass("test.Task").newInstance(); try { r.run(); // Cause an ICCE because both I and J define m()LFoo; throw new RuntimeException("Expected ICCE exception not thrown"); } catch (IncompatibleClassChangeError e) { - if (!e.getMessage().contains("Conflicting default methods: I.m J.m")) { + if (!e.getMessage().contains("Conflicting default methods: test/I.m test/J.m")) { throw new RuntimeException("Wrong ICCE exception thrown: " + e.getMessage()); } } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/I.java b/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/I.java index 97fdaa8830b..59a2906b69a 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/I.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/I.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,6 +21,8 @@ * questions. */ +package test; + public interface I { public Foo m(); } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Task.java b/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Task.java index 6d409023eec..1157c3b2685 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Task.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Task.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,6 +21,8 @@ * questions. */ +package test; + public class Task implements Runnable { public void run() { diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java b/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java index 3f2793934c7..7c10d020542 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8186092 + * @bug 8186092 8199852 * @compile ../common/Foo.java * ../common/J.java * I.java @@ -35,6 +35,26 @@ public class Test { + static String expectedErrorMessage1 = + "loader constraint violation in interface itable initialization for class test.C: " + + "when selecting method test.I.m()Ltest/Foo; " + + "the class loader \"\" (instance of PreemptingClassLoader, " + + "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "for super interface test.I, and the class loader \"app\" " + + "(instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "of the selected method's type, test.J have different Class objects " + + "for the type test.Foo used in the signature"; + + static String expectedErrorMessage2 = + "loader constraint violation in interface itable initialization for class test.C: " + + "when selecting method test.I.m()Ltest/Foo; " + + "the class loader \"ItableLdrCnstrnt_Test_Loader\" (instance of PreemptingClassLoader, " + + "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "for super interface test.I, and the class loader \"app\" " + + "(instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "of the selected method's type, test.J have different Class objects " + + "for the type test.Foo used in the signature"; + // Test that the error message is correct when a loader constraint error is // detected during itable creation. // @@ -43,18 +63,27 @@ public class Test { // type super interface J. The selected method is not an overpass method nor // otherwise excluded from loader constraint checking. So, a LinkageError // exception should be thrown because the loader constraint check will fail. - public static void main(String... args) throws Exception { - Class c = Foo.class; // forces standard class loader to load Foo - ClassLoader l = new PreemptingClassLoader("Task", "Foo", "C", "I"); - Runnable r = (Runnable) l.loadClass("Task").newInstance(); + public static void test(String loaderName, String expectedErrorMessage) throws Exception { + Class c = test.Foo.class; // Forces standard class loader to load Foo. + String[] classNames = {"test.Task", "test.Foo", "test.C", "test.I"}; + ClassLoader l = new PreemptingClassLoader(loaderName, classNames); + Runnable r = (Runnable) l.loadClass("test.Task").newInstance(); try { r.run(); throw new RuntimeException("Expected LinkageError exception not thrown"); } catch (LinkageError e) { - if (!e.getMessage().contains( - "loader constraint violation in interface itable initialization for class C:")) { - throw new RuntimeException("Wrong LinkageError exception thrown: " + e.getMessage()); + String errorMsg = e.getMessage(); + if (!errorMsg.equals(expectedErrorMessage)) { + System.out.println("Expected: " + expectedErrorMessage + "\n" + + "but got: " + errorMsg); + throw new RuntimeException("Wrong LinkageError exception thrown: " + errorMsg); } + System.out.println("Passed with message: " + errorMsg); } } + + public static void main(String... args) throws Exception { + test(null, expectedErrorMessage1); + test("ItableLdrCnstrnt_Test_Loader", expectedErrorMessage2); + } } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/I.java b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/I.java index f6e47464837..c51ba06a868 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/I.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/I.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,6 +21,8 @@ * questions. */ +package test; + public interface I extends J { public Foo m(); } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/Task.java b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/Task.java index ffc2acd8223..e27fff31a6e 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/Task.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/Task.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,4 +21,6 @@ * questions. */ +package test; + public class Task extends C { } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/Test.java b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/Test.java index 83a5a7f01e7..7957704bdd5 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/Test.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableAME/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -48,16 +48,16 @@ public class Test { // because the loader constraint check that would cause the LinkageError // should not be done. public static void main(String args[]) throws Exception { - Class c = Foo.class; // forces standard class loader to load Foo - ClassLoader l = new PreemptingClassLoader("Task", "Foo", "I", "J"); - l.loadClass("Foo"); - l.loadClass("Task").newInstance(); - Task t = new Task(); + Class c = test.Foo.class; // forces standard class loader to load Foo + ClassLoader l = new PreemptingClassLoader("test.Task", "test.Foo", "test.I", "test.J"); + l.loadClass("test.Foo"); + l.loadClass("test.Task").newInstance(); + test.Task t = new test.Task(); try { t.m(); // Should get AME throw new RuntimeException("Missing AbstractMethodError exception"); } catch (AbstractMethodError e) { - if (!e.getMessage().contains("Method Task.m()LFoo; is abstract")) { + if (!e.getMessage().contains("Method test/Task.m()Ltest/Foo; is abstract")) { throw new RuntimeException("Wrong AME exception thrown: " + e.getMessage()); } } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/I.java b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/I.java index f6db30fe83b..ceac6cd8e28 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/I.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/I.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,5 +21,7 @@ * questions. */ +package test; + public interface I extends J { } diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Task.java b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Task.java index d59a7a4fc76..dd4e697ff1c 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Task.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Task.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -21,6 +21,8 @@ * questions. */ +package test; + public class Task extends C { public Foo m() { diff --git a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java index e474c1ee16d..81e0c88a2cd 100644 --- a/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java +++ b/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8186092 + * @bug 8186092 8199852 * @compile ../common/Foo.java * ../common/J.java * I.java @@ -35,6 +35,26 @@ public class Test { + static String expectedErrorMessage1 = + "loader constraint violation for class test.Task: " + + "when selecting overriding method test.Task.m()Ltest/Foo; " + + "the class loader \"\" (instance of PreemptingClassLoader, " + + "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "of the selected method's type test.Task, " + + "and the class loader \"app\" (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "for its super type test.J " + + "have different Class objects for the type test.Foo used in the signature"; + + static String expectedErrorMessage2 = + "loader constraint violation for class test.Task: " + + "when selecting overriding method test.Task.m()Ltest/Foo; " + + "the class loader \"VtableLdrCnstrnt_Test_Loader\" (instance of PreemptingClassLoader, " + + "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "of the selected method's type test.Task, " + + "and the class loader \"app\" (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "for its super type test.J " + + "have different Class objects for the type test.Foo used in the signature"; + // Test that the error message is correct when a loader constraint error is // detected during vtable creation. // @@ -42,22 +62,28 @@ public class Test { // overrides "J.m()LFoo;". But, Task's class Foo and super type J's class Foo // are different. So, a LinkageError exception should be thrown because the // loader constraint check will fail. - public static void main(String args[]) throws Exception { - Class c = Foo.class; // forces standard class loader to load Foo - ClassLoader l = new PreemptingClassLoader("Task", "Foo", "I"); - l.loadClass("Foo"); + public static void test(String loaderName, String expectedErrorMessage) throws Exception { + Class c = test.Foo.class; // Forces standard class loader to load Foo. + String[] classNames = {"test.Task", "test.Foo", "test.I"}; + ClassLoader l = new PreemptingClassLoader(loaderName, classNames); + l.loadClass("test.Foo"); try { - l.loadClass("Task").newInstance(); + l.loadClass("test.Task").newInstance(); throw new RuntimeException("Expected LinkageError exception not thrown"); } catch (LinkageError e) { - if (!e.getMessage().contains( - "loader constraint violation for class Task: when selecting overriding method") || - !e.getMessage().contains( - "for its super type J have different Class objects for the type Foo")) { - throw new RuntimeException("Wrong LinkageError exception thrown: " + e.getMessage()); + String errorMsg = e.getMessage(); + if (!errorMsg.equals(expectedErrorMessage)) { + System.out.println("Expected: " + expectedErrorMessage + "\n" + + "but got: " + errorMsg); + throw new RuntimeException("Wrong LinkageError exception thrown: " + errorMsg); } + System.out.println("Passed with message: " + errorMsg); } } + public static void main(String args[]) throws Exception { + test(null, expectedErrorMessage1); + test("VtableLdrCnstrnt_Test_Loader", expectedErrorMessage2); + } } From 31c128ef22442527503ebf180b3feca3701cb6a0 Mon Sep 17 00:00:00 2001 From: Vivek Theeyarath Date: Thu, 3 May 2018 04:18:22 -0700 Subject: [PATCH 23/40] 8195717: test java/lang/invoke/MethodHandlesTest timed out running testAsCollector1 Refactor MethodHandlesTest Reviewed-by: psandoz --- .../invoke/MethodHandlesAsCollectorTest.java | 138 + .../invoke/MethodHandlesCastFailureTest.java | 157 + .../lang/invoke/MethodHandlesGeneralTest.java | 2122 ++++++++++++ .../MethodHandlesInsertArgumentsTest.java | 91 + .../invoke/MethodHandlesInvokersTest.java | 222 ++ .../MethodHandlesPermuteArgumentsTest.java | 194 ++ .../MethodHandlesSpreadArgumentsTest.java | 210 ++ .../java/lang/invoke/MethodHandlesTest.java | 2855 +---------------- 8 files changed, 3208 insertions(+), 2781 deletions(-) create mode 100644 test/jdk/java/lang/invoke/MethodHandlesAsCollectorTest.java create mode 100644 test/jdk/java/lang/invoke/MethodHandlesCastFailureTest.java create mode 100644 test/jdk/java/lang/invoke/MethodHandlesGeneralTest.java create mode 100644 test/jdk/java/lang/invoke/MethodHandlesInsertArgumentsTest.java create mode 100644 test/jdk/java/lang/invoke/MethodHandlesInvokersTest.java create mode 100644 test/jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java create mode 100644 test/jdk/java/lang/invoke/MethodHandlesSpreadArgumentsTest.java diff --git a/test/jdk/java/lang/invoke/MethodHandlesAsCollectorTest.java b/test/jdk/java/lang/invoke/MethodHandlesAsCollectorTest.java new file mode 100644 index 00000000000..6b816f89c11 --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandlesAsCollectorTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2018, 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 + * @summary unit tests for java.lang.invoke.MethodHandles + * @library /lib/testlibrary /java/lang/invoke/common + * @compile MethodHandlesTest.java MethodHandlesAsCollectorTest.java remote/RemoteExample.java + * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions + * -XX:-VerifyDependencies + * -esa + * test.java.lang.invoke.MethodHandlesAsCollectorTest + */ + +package test.java.lang.invoke; + +import org.junit.*; +import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class MethodHandlesAsCollectorTest extends MethodHandlesTest { + + @Test // SLOW + public void testAsCollector() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testAsCollector0); + CodeCacheOverflowProcessor.runMHTest(this::testAsCollector1); + } + + public void testAsCollector0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("asCollector"); + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + if (verbosity >= 3) + System.out.println("asCollector "+argType); + for (int nargs = 0; nargs < 50; nargs++) { + if (CAN_TEST_LIGHTLY && nargs > 11) break; + for (int pos = 0; pos <= nargs; pos++) { + if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; + if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) + continue; + testAsCollector(argType, pos, nargs); + } + } + } + } + + public void testAsCollector(Class argType, int pos, int nargs) throws Throwable { + countTest(); + // fake up a MH with the same type as the desired adapter: + MethodHandle fake = varargsArray(nargs); + fake = changeArgTypes(fake, argType); + MethodType newType = fake.type(); + Object[] args = randomArgs(newType.parameterArray()); + // here is what should happen: + Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1); + collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length); + // here is the MH which will witness the collected argument tail: + MethodHandle target = varargsArray(pos+1); + target = changeArgTypes(target, 0, pos, argType); + target = changeArgTypes(target, pos, pos+1, Object[].class); + if (verbosity >= 3) + System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]"); + MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType); + Object[] returnValue = (Object[]) result.invokeWithArguments(args); + assertArrayEquals(collectedArgs, returnValue); + } + + public void testAsCollector1() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("asCollector/pos"); + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + if (verbosity >= 3) + System.out.println("asCollector/pos "+argType); + for (int nargs = 0; nargs < 50; nargs++) { + if (CAN_TEST_LIGHTLY && nargs > 11) break; + for (int pos = 0; pos <= nargs; pos++) { + if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; + if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) + continue; + for (int coll = 1; coll < nargs - pos; ++coll) { + if (coll > 4 && coll != 7 && coll != 11 && coll != 20 && coll < nargs - pos - 4) continue; + testAsCollector(argType, pos, coll, nargs); + } + } + } + } + } + + public void testAsCollector(Class argType, int pos, int collect, int nargs) throws Throwable { + countTest(); + // fake up a MH with the same type as the desired adapter: + MethodHandle fake = varargsArray(nargs); + fake = changeArgTypes(fake, argType); + MethodType newType = fake.type(); + Object[] args = randomArgs(newType.parameterArray()); + // here is what should happen: + // new arg list has "collect" less arguments, but one extra for collected arguments array + int collectedLength = nargs-(collect-1); + Object[] collectedArgs = new Object[collectedLength]; + System.arraycopy(args, 0, collectedArgs, 0, pos); + collectedArgs[pos] = Arrays.copyOfRange(args, pos, pos+collect); + System.arraycopy(args, pos+collect, collectedArgs, pos+1, args.length-(pos+collect)); + // here is the MH which will witness the collected argument part (not tail!): + MethodHandle target = varargsArray(collectedLength); + target = changeArgTypes(target, 0, pos, argType); + target = changeArgTypes(target, pos, pos+1, Object[].class); + target = changeArgTypes(target, pos+1, collectedLength, argType); + if (verbosity >= 3) + System.out.println("collect "+collect+" from "+Arrays.asList(args)+" ["+pos+".."+(pos+collect)+"["); + MethodHandle result = target.asCollector(pos, Object[].class, collect).asType(newType); + Object[] returnValue = (Object[]) result.invokeWithArguments(args); + assertArrayEquals(collectedArgs, returnValue); + } +} diff --git a/test/jdk/java/lang/invoke/MethodHandlesCastFailureTest.java b/test/jdk/java/lang/invoke/MethodHandlesCastFailureTest.java new file mode 100644 index 00000000000..479bd2d14db --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandlesCastFailureTest.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2018, 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 + * @summary unit tests for java.lang.invoke.MethodHandles + * @library /lib/testlibrary /java/lang/invoke/common + * @compile MethodHandlesTest.java MethodHandlesCastFailureTest.java remote/RemoteExample.java + * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions + * -XX:-VerifyDependencies + * -esa + * test.java.lang.invoke.MethodHandlesCastFailureTest + */ + +package test.java.lang.invoke; + +import org.junit.*; +import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +import static org.junit.Assert.*; + +public class MethodHandlesCastFailureTest extends MethodHandlesTest { + + @Test // SLOW + public void testCastFailure() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testCastFailure0); + } + + public void testCastFailure0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("testCastFailure"); + testCastFailure("cast/argument", 11000); + if (CAN_TEST_LIGHTLY) return; + testCastFailure("unbox/argument", 11000); + testCastFailure("cast/return", 11000); + testCastFailure("unbox/return", 11000); + } + + static class Surprise { + public MethodHandle asMethodHandle() { + return VALUE.bindTo(this); + } + Object value(Object x) { + trace("value", x); + if (boo != null) return boo; + return x; + } + Object boo; + void boo(Object x) { boo = x; } + + static void trace(String x, Object y) { + if (verbosity > 8) System.out.println(x+"="+y); + } + static Object refIdentity(Object x) { trace("ref.x", x); return x; } + static Integer boxIdentity(Integer x) { trace("box.x", x); return x; } + static int intIdentity(int x) { trace("int.x", x); return x; } + static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY; + static { + try { + VALUE = PRIVATE.findVirtual( + Surprise.class, "value", + MethodType.methodType(Object.class, Object.class)); + REF_IDENTITY = PRIVATE.findStatic( + Surprise.class, "refIdentity", + MethodType.methodType(Object.class, Object.class)); + BOX_IDENTITY = PRIVATE.findStatic( + Surprise.class, "boxIdentity", + MethodType.methodType(Integer.class, Integer.class)); + INT_IDENTITY = PRIVATE.findStatic( + Surprise.class, "intIdentity", + MethodType.methodType(int.class, int.class)); + } catch (NoSuchMethodException | IllegalAccessException ex) { + throw new RuntimeException(ex); + } + } + } + + @SuppressWarnings("ConvertToStringSwitch") + void testCastFailure(String mode, int okCount) throws Throwable { + countTest(false); + if (verbosity > 2) System.out.println("mode="+mode); + Surprise boo = new Surprise(); + MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0; + if (mode.endsWith("/return")) { + if (mode.equals("unbox/return")) { + // fail on return to ((Integer)surprise).intValue + surprise = surprise.asType(MethodType.methodType(int.class, Object.class)); + identity = identity.asType(MethodType.methodType(int.class, Object.class)); + } else if (mode.equals("cast/return")) { + // fail on return to (Integer)surprise + surprise = surprise.asType(MethodType.methodType(Integer.class, Object.class)); + identity = identity.asType(MethodType.methodType(Integer.class, Object.class)); + } + } else if (mode.endsWith("/argument")) { + MethodHandle callee = null; + if (mode.equals("unbox/argument")) { + // fail on handing surprise to int argument + callee = Surprise.INT_IDENTITY; + } else if (mode.equals("cast/argument")) { + // fail on handing surprise to Integer argument + callee = Surprise.BOX_IDENTITY; + } + if (callee != null) { + callee = callee.asType(MethodType.genericMethodType(1)); + surprise = MethodHandles.filterArguments(callee, 0, surprise); + identity = MethodHandles.filterArguments(callee, 0, identity); + } + } + assertNotSame(mode, surprise, surprise0); + identity = identity.asType(MethodType.genericMethodType(1)); + surprise = surprise.asType(MethodType.genericMethodType(1)); + Object x = 42; + for (int i = 0; i < okCount; i++) { + Object y = identity.invokeExact(x); + assertEquals(x, y); + Object z = surprise.invokeExact(x); + assertEquals(x, z); + } + boo.boo("Boo!"); + Object y = identity.invokeExact(x); + assertEquals(x, y); + try { + Object z = surprise.invokeExact(x); + System.out.println("Failed to throw; got z="+z); + assertTrue(false); + } catch (ClassCastException ex) { + if (verbosity > 2) + System.out.println("caught "+ex); + if (verbosity > 3) + ex.printStackTrace(System.out); + assertTrue(true); // all is well + } + } +} diff --git a/test/jdk/java/lang/invoke/MethodHandlesGeneralTest.java b/test/jdk/java/lang/invoke/MethodHandlesGeneralTest.java new file mode 100644 index 00000000000..cd859c8809a --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandlesGeneralTest.java @@ -0,0 +1,2122 @@ +/* + * Copyright (c) 2018, 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 + * @summary unit tests for java.lang.invoke.MethodHandles + * @library /lib/testlibrary /java/lang/invoke/common + * @compile MethodHandlesTest.java MethodHandlesGeneralTest.java remote/RemoteExample.java + * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions + * -XX:-VerifyDependencies + * -esa + * test.java.lang.invoke.MethodHandlesGeneralTest + */ + +package test.java.lang.invoke; + +import org.junit.*; +import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; +import test.java.lang.invoke.remote.RemoteExample; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleProxies; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Formatter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.lang.invoke.MethodType.methodType; +import static org.junit.Assert.*; + +public class MethodHandlesGeneralTest extends MethodHandlesTest { + + @Test + public void testFirst() throws Throwable { + verbosity += 9; + try { + // left blank for debugging + } finally { printCounts(); verbosity -= 9; } + } + + @Test + public void testFindStatic() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindStatic0); + } + + public void testFindStatic0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findStatic"); + testFindStatic(PubExample.class, void.class, "s0"); + testFindStatic(Example.class, void.class, "s0"); + testFindStatic(Example.class, void.class, "pkg_s0"); + testFindStatic(Example.class, void.class, "pri_s0"); + testFindStatic(Example.class, void.class, "pro_s0"); + testFindStatic(PubExample.class, void.class, "Pub/pro_s0"); + + testFindStatic(Example.class, Object.class, "s1", Object.class); + testFindStatic(Example.class, Object.class, "s2", int.class); + testFindStatic(Example.class, Object.class, "s3", long.class); + testFindStatic(Example.class, Object.class, "s4", int.class, int.class); + testFindStatic(Example.class, Object.class, "s5", long.class, int.class); + testFindStatic(Example.class, Object.class, "s6", int.class, long.class); + testFindStatic(Example.class, Object.class, "s7", float.class, double.class); + + testFindStatic(false, PRIVATE, Example.class, void.class, "bogus"); + testFindStatic(false, PRIVATE, Example.class, void.class, "", int.class); + testFindStatic(false, PRIVATE, Example.class, void.class, "", Void.class); + testFindStatic(false, PRIVATE, Example.class, void.class, "v0"); + } + + void testFindStatic(Class defc, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); + } + } + + void testFindStatic(Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { + testFindStatic(true, lookup, defc, ret, name, params); + } + + void testFindStatic(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo + MethodType type = MethodType.methodType(ret, params); + MethodHandle target = null; + Exception noAccess = null; + try { + if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); + target = maybeMoveIn(lookup, defc).findStatic(defc, methodName, type); + } catch (ReflectiveOperationException ex) { + noAccess = ex; + assertExceptionClass( + (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("")) + ? NoSuchMethodException.class + : IllegalAccessException.class, + noAccess); + if (verbosity >= 5) ex.printStackTrace(System.out); + } + if (verbosity >= 3) + System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(type, target.type()); + assertNameStringContains(target, methodName); + Object[] args = randomArgs(params); + printCalled(target, name, args); + target.invokeWithArguments(args); + assertCalled(name, args); + if (verbosity >= 1) + System.out.print(':'); + } + + @Test + public void testFindVirtual() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindVirtual0); + } + + public void testFindVirtual0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findVirtual"); + testFindVirtual(Example.class, void.class, "v0"); + testFindVirtual(Example.class, void.class, "pkg_v0"); + testFindVirtual(Example.class, void.class, "pri_v0"); + testFindVirtual(Example.class, Object.class, "v1", Object.class); + testFindVirtual(Example.class, Object.class, "v2", Object.class, Object.class); + testFindVirtual(Example.class, Object.class, "v2", Object.class, int.class); + testFindVirtual(Example.class, Object.class, "v2", int.class, Object.class); + testFindVirtual(Example.class, Object.class, "v2", int.class, int.class); + testFindVirtual(Example.class, void.class, "pro_v0"); + testFindVirtual(PubExample.class, void.class, "Pub/pro_v0"); + + testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus"); + testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "", int.class); + testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "", Void.class); + testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "s0"); + + // test dispatch + testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/v0"); + testFindVirtual(SubExample.class, Example.class, void.class, "Sub/v0"); + testFindVirtual(SubExample.class, IntExample.class, void.class, "Sub/v0"); + testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/pkg_v0"); + testFindVirtual(SubExample.class, Example.class, void.class, "Sub/pkg_v0"); + testFindVirtual(Example.class, IntExample.class, void.class, "v0"); + testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0"); + } + + @Test + public void testFindVirtualClone() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindVirtualClone0); + } + + public void testFindVirtualClone0() throws Throwable { + if (CAN_SKIP_WORKING) return; + // test some ad hoc system methods + testFindVirtual(false, PUBLIC, Object.class, Object.class, "clone"); + + // ##### FIXME - disable tests for clone until we figure out how they should work with modules + + /* + testFindVirtual(true, PUBLIC, Object[].class, Object.class, "clone"); + testFindVirtual(true, PUBLIC, int[].class, Object.class, "clone"); + for (Class cls : new Class[]{ boolean[].class, long[].class, float[].class, char[].class }) + testFindVirtual(true, PUBLIC, cls, Object.class, "clone"); + */ + } + + void testFindVirtual(Class defc, Class ret, String name, Class... params) throws Throwable { + Class rcvc = defc; + testFindVirtual(rcvc, defc, ret, name, params); + } + + void testFindVirtual(Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params); + } + } + + void testFindVirtual(Lookup lookup, Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { + testFindVirtual(true, lookup, rcvc, defc, ret, name, params); + } + + void testFindVirtual(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { + testFindVirtual(positive, lookup, defc, defc, ret, name, params); + } + + void testFindVirtual(boolean positive, Lookup lookup, Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo + MethodType type = MethodType.methodType(ret, params); + MethodHandle target = null; + Exception noAccess = null; + try { + if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); + target = maybeMoveIn(lookup, defc).findVirtual(defc, methodName, type); + } catch (ReflectiveOperationException ex) { + noAccess = ex; + assertExceptionClass( + (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("")) + ? NoSuchMethodException.class + : IllegalAccessException.class, + noAccess); + if (verbosity >= 5) ex.printStackTrace(System.out); + } + if (verbosity >= 3) + System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + Class selfc = defc; + // predict receiver type narrowing: + if (lookup == SUBCLASS && + name.contains("pro_") && + selfc.isAssignableFrom(lookup.lookupClass())) { + selfc = lookup.lookupClass(); + if (name.startsWith("Pub/")) name = "Rem/"+name.substring(4); + } + Class[] paramsWithSelf = cat(array(Class[].class, (Class)selfc), params); + MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); + assertEquals(typeWithSelf, target.type()); + assertNameStringContains(target, methodName); + Object[] argsWithSelf = randomArgs(paramsWithSelf); + if (selfc.isAssignableFrom(rcvc) && rcvc != selfc) argsWithSelf[0] = randomArg(rcvc); + printCalled(target, name, argsWithSelf); + Object res = target.invokeWithArguments(argsWithSelf); + if (Example.class.isAssignableFrom(defc) || IntExample.class.isAssignableFrom(defc)) { + assertCalled(name, argsWithSelf); + } else if (name.equals("clone")) { + // Ad hoc method call outside Example. For Object[].clone. + printCalled(target, name, argsWithSelf); + assertEquals(MethodType.methodType(Object.class, rcvc), target.type()); + Object orig = argsWithSelf[0]; + assertEquals(orig.getClass(), res.getClass()); + if (res instanceof Object[]) + assertArrayEquals((Object[])res, (Object[])argsWithSelf[0]); + assert(Arrays.deepEquals(new Object[]{res}, new Object[]{argsWithSelf[0]})); + } else { + assert(false) : Arrays.asList(positive, lookup, rcvc, defc, ret, name, deepToString(params)); + } + if (verbosity >= 1) + System.out.print(':'); + } + + @Test + public void testFindSpecial() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindSpecial0); + } + + public void testFindSpecial0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findSpecial"); + testFindSpecial(SubExample.class, Example.class, void.class, false, "v0"); + testFindSpecial(SubExample.class, Example.class, void.class, false, "pkg_v0"); + testFindSpecial(RemoteExample.class, PubExample.class, void.class, false, "Pub/pro_v0"); + testFindSpecial(Example.class, IntExample.class, void.class, true, "vd"); + // Do some negative testing: + for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) { + testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0"); + testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus"); + testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "", int.class); + testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "", Void.class); + testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0"); + testFindSpecial(false, lookup, Example.class, IntExample.class, void.class, "v0"); + } + } + + void testFindSpecial(Class specialCaller, + Class defc, Class ret, boolean dflt, String name, Class... params) throws Throwable { + if (specialCaller == RemoteExample.class) { + testFindSpecial(false, EXAMPLE, specialCaller, defc, ret, name, params); + testFindSpecial(false, PRIVATE, specialCaller, defc, ret, name, params); + testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params); + testFindSpecial(true, SUBCLASS, specialCaller, defc, ret, name, params); + testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params); + return; + } + testFindSpecial(true, EXAMPLE, specialCaller, defc, ret, name, params); + testFindSpecial(true, PRIVATE, specialCaller, defc, ret, name, params); + testFindSpecial(false || dflt, PACKAGE, specialCaller, defc, ret, name, params); + testFindSpecial(false, SUBCLASS, specialCaller, defc, ret, name, params); + testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params); + } + + void testFindSpecial(boolean positive, Lookup lookup, Class specialCaller, + Class defc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo + MethodType type = MethodType.methodType(ret, params); + Lookup specialLookup = maybeMoveIn(lookup, specialCaller); + boolean specialAccessOK = (specialLookup.lookupClass() == specialCaller && + (specialLookup.lookupModes() & Lookup.PRIVATE) != 0); + MethodHandle target = null; + Exception noAccess = null; + try { + if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); + if (verbosity >= 5) System.out.println(" lookup => "+specialLookup); + target = specialLookup.findSpecial(defc, methodName, type, specialCaller); + } catch (ReflectiveOperationException ex) { + noAccess = ex; + assertExceptionClass( + (!specialAccessOK) // this check should happen first + ? IllegalAccessException.class + : (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("")) + ? NoSuchMethodException.class + : IllegalAccessException.class, + noAccess); + if (verbosity >= 5) ex.printStackTrace(System.out); + } + if (verbosity >= 3) + System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target + +(target == null ? "" : target.type()) + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(specialCaller, target.type().parameterType(0)); + assertEquals(type, target.type().dropParameterTypes(0,1)); + Class[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params); + MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); + assertNameStringContains(target, methodName); + Object[] args = randomArgs(paramsWithSelf); + printCalled(target, name, args); + target.invokeWithArguments(args); + assertCalled(name, args); + } + + @Test + public void testFindConstructor() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindConstructor0); + } + + public void testFindConstructor0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findConstructor"); + testFindConstructor(true, EXAMPLE, Example.class); + testFindConstructor(true, EXAMPLE, Example.class, int.class); + testFindConstructor(true, EXAMPLE, Example.class, int.class, int.class); + testFindConstructor(true, EXAMPLE, Example.class, int.class, long.class); + testFindConstructor(true, EXAMPLE, Example.class, int.class, float.class); + testFindConstructor(true, EXAMPLE, Example.class, int.class, double.class); + testFindConstructor(true, EXAMPLE, Example.class, String.class); + testFindConstructor(true, EXAMPLE, Example.class, int.class, int.class, int.class); + testFindConstructor(true, EXAMPLE, Example.class, int.class, int.class, int.class, int.class); + } + + void testFindConstructor(boolean positive, Lookup lookup, + Class defc, Class... params) throws Throwable { + countTest(positive); + MethodType type = MethodType.methodType(void.class, params); + MethodHandle target = null; + Exception noAccess = null; + try { + if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+type); + target = lookup.findConstructor(defc, type); + } catch (ReflectiveOperationException ex) { + noAccess = ex; + assertTrue(noAccess.getClass().getName(), noAccess instanceof IllegalAccessException); + } + if (verbosity >= 3) + System.out.println("findConstructor "+defc.getName()+"./"+type+" => "+target + +(target == null ? "" : target.type()) + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(type.changeReturnType(defc), target.type()); + Object[] args = randomArgs(params); + printCalled(target, defc.getSimpleName(), args); + Object obj = target.invokeWithArguments(args); + if (!(defc == Example.class && params.length < 2)) + assertCalled(defc.getSimpleName()+".", args); + assertTrue("instance of "+defc.getName(), defc.isInstance(obj)); + } + + @Test + public void testBind() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testBind0); + } + + public void testBind0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("bind"); + testBind(Example.class, void.class, "v0"); + testBind(Example.class, void.class, "pkg_v0"); + testBind(Example.class, void.class, "pri_v0"); + testBind(Example.class, Object.class, "v1", Object.class); + testBind(Example.class, Object.class, "v2", Object.class, Object.class); + testBind(Example.class, Object.class, "v2", Object.class, int.class); + testBind(Example.class, Object.class, "v2", int.class, Object.class); + testBind(Example.class, Object.class, "v2", int.class, int.class); + testBind(false, PRIVATE, Example.class, void.class, "bogus"); + testBind(false, PRIVATE, Example.class, void.class, "", int.class); + testBind(false, PRIVATE, Example.class, void.class, "", Void.class); + testBind(SubExample.class, void.class, "Sub/v0"); + testBind(SubExample.class, void.class, "Sub/pkg_v0"); + testBind(IntExample.Impl.class, void.class, "Int/v0"); + } + + void testBind(Class defc, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); + } + } + + void testBind(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo + MethodType type = MethodType.methodType(ret, params); + Object receiver = randomArg(defc); + MethodHandle target = null; + Exception noAccess = null; + try { + if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); + target = maybeMoveIn(lookup, defc).bind(receiver, methodName, type); + } catch (ReflectiveOperationException ex) { + noAccess = ex; + assertExceptionClass( + (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("")) + ? NoSuchMethodException.class + : IllegalAccessException.class, + noAccess); + if (verbosity >= 5) ex.printStackTrace(System.out); + } + if (verbosity >= 3) + System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(type, target.type()); + Object[] args = randomArgs(params); + printCalled(target, name, args); + target.invokeWithArguments(args); + Object[] argsWithReceiver = cat(array(Object[].class, receiver), args); + assertCalled(name, argsWithReceiver); + if (verbosity >= 1) + System.out.print(':'); + } + + @Test + public void testUnreflect() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testUnreflect0); + } + + public void testUnreflect0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("unreflect"); + testUnreflect(Example.class, true, void.class, "s0"); + testUnreflect(Example.class, true, void.class, "pro_s0"); + testUnreflect(Example.class, true, void.class, "pkg_s0"); + testUnreflect(Example.class, true, void.class, "pri_s0"); + + testUnreflect(Example.class, true, Object.class, "s1", Object.class); + testUnreflect(Example.class, true, Object.class, "s2", int.class); + testUnreflect(Example.class, true, Object.class, "s3", long.class); + testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); + testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); + testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); + + testUnreflect(Example.class, false, void.class, "v0"); + testUnreflect(Example.class, false, void.class, "pkg_v0"); + testUnreflect(Example.class, false, void.class, "pri_v0"); + testUnreflect(Example.class, false, Object.class, "v1", Object.class); + testUnreflect(Example.class, false, Object.class, "v2", Object.class, Object.class); + testUnreflect(Example.class, false, Object.class, "v2", Object.class, int.class); + testUnreflect(Example.class, false, Object.class, "v2", int.class, Object.class); + testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); + + // Test a public final member in another package: + testUnreflect(RemoteExample.class, false, void.class, "Rem/fin_v0"); + } + + void testUnreflect(Class defc, boolean isStatic, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params); + } + } + + void testUnreflect(Class defc, Class rcvc, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); + } + } + + void testUnreflectMaybeSpecial(Class specialCaller, + boolean positive, Lookup lookup, + Class defc, Class rcvc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo + MethodType type = MethodType.methodType(ret, params); + Lookup specialLookup = (specialCaller != null ? maybeMoveIn(lookup, specialCaller) : null); + boolean specialAccessOK = (specialCaller != null && + specialLookup.lookupClass() == specialCaller && + (specialLookup.lookupModes() & Lookup.PRIVATE) != 0); + Method rmethod = defc.getDeclaredMethod(methodName, params); + MethodHandle target = null; + Exception noAccess = null; + boolean isStatic = (rcvc == null); + boolean isSpecial = (specialCaller != null); + try { + if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); + if (isSpecial) + target = specialLookup.unreflectSpecial(rmethod, specialCaller); + else + target = maybeMoveIn(lookup, defc).unreflect(rmethod); + } catch (ReflectiveOperationException ex) { + noAccess = ex; + assertExceptionClass( + IllegalAccessException.class, // NSME is impossible, since it was already reflected + noAccess); + if (verbosity >= 5) ex.printStackTrace(System.out); + } + if (verbosity >= 3) + System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type + +(!isSpecial ? "" : " specialCaller="+specialCaller) + +( isStatic ? "" : " receiver="+rcvc) + +" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); + Class[] paramsMaybeWithSelf = params; + if (!isStatic) { + paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params); + } + MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); + if (isStatic) { + assertEquals(typeMaybeWithSelf, target.type()); + } else { + if (isSpecial) + assertEquals(specialCaller, target.type().parameterType(0)); + else + assertEquals(defc, target.type().parameterType(0)); + assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc)); + } + Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); + printCalled(target, name, argsMaybeWithSelf); + target.invokeWithArguments(argsMaybeWithSelf); + assertCalled(name, argsMaybeWithSelf); + if (verbosity >= 1) + System.out.print(':'); + } + + void testUnreflectSpecial(Class defc, Class rcvc, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name, true)) { + Class specialCaller = rcvc; + testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); + } + } + + @Test + public void testUnreflectSpecial() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testUnreflectSpecial0); + } + + public void testUnreflectSpecial0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("unreflectSpecial"); + testUnreflectSpecial(Example.class, Example.class, void.class, "v0"); + testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0"); + testUnreflectSpecial(Example.class, Example.class, void.class, "pkg_v0"); + testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0"); + testUnreflectSpecial(Example.class, Example.class, Object.class, "v2", int.class, int.class); + testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class); + testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0"); + } + + @Test + public void testUnreflectGetter() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testUnreflectGetter0); + } + + public void testUnreflectGetter0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("unreflectGetter"); + testGetter(TEST_UNREFLECT); + } + + @Test + public void testFindGetter() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindGetter0); + } + + public void testFindGetter0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findGetter"); + testGetter(TEST_FIND_FIELD); + testGetter(TEST_FIND_FIELD | TEST_BOUND); + } + + @Test + public void testFindStaticGetter() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindStaticGetter0); + } + + public void testFindStaticGetter0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findStaticGetter"); + testGetter(TEST_FIND_STATIC); + } + + public void testGetter(int testMode) throws Throwable { + Lookup lookup = PRIVATE; // FIXME: test more lookups than this one + for (Object[] c : HasFields.CASES) { + boolean positive = (c[1] != Error.class); + testGetter(positive, lookup, c[0], c[1], testMode); + if (positive) + testGetter(positive, lookup, c[0], c[1], testMode | TEST_NPE); + } + testGetter(true, lookup, + new Object[]{ true, System.class, "out", java.io.PrintStream.class }, + System.out, testMode); + for (int isStaticN = 0; isStaticN <= 1; isStaticN++) { + testGetter(false, lookup, + new Object[]{ (isStaticN != 0), System.class, "bogus", char.class }, + null, testMode); + } + } + + public void testGetter(boolean positive, MethodHandles.Lookup lookup, + Object fieldRef, Object value, int testMode) throws Throwable { + testAccessor(positive, lookup, fieldRef, value, testMode); + } + + public void testAccessor(boolean positive0, MethodHandles.Lookup lookup, + Object fieldRef, Object value, int testMode0) throws Throwable { + if (verbosity >= 4) + System.out.println("testAccessor"+Arrays.deepToString(new Object[]{positive0, lookup, fieldRef, value, testMode0})); + boolean isGetter = ((testMode0 & TEST_SETTER) == 0); + boolean doBound = ((testMode0 & TEST_BOUND) != 0); + boolean testNPE = ((testMode0 & TEST_NPE) != 0); + int testMode = testMode0 & ~(TEST_SETTER | TEST_BOUND | TEST_NPE); + boolean positive = positive0 && !testNPE; + boolean isStatic; + Class fclass; + String fname; + Class ftype; + Field f = (fieldRef instanceof Field ? (Field)fieldRef : null); + if (f != null) { + isStatic = Modifier.isStatic(f.getModifiers()); + fclass = f.getDeclaringClass(); + fname = f.getName(); + ftype = f.getType(); + } else { + Object[] scnt = (Object[]) fieldRef; + isStatic = (Boolean) scnt[0]; + fclass = (Class) scnt[1]; + fname = (String) scnt[2]; + ftype = (Class) scnt[3]; + try { + f = fclass.getDeclaredField(fname); + } catch (ReflectiveOperationException ex) { + f = null; + } + } + if (!testModeMatches(testMode, isStatic)) return; + if (f == null && testMode == TEST_UNREFLECT) return; + if (testNPE && isStatic) return; + countTest(positive); + MethodType expType; + if (isGetter) + expType = MethodType.methodType(ftype, HasFields.class); + else + expType = MethodType.methodType(void.class, HasFields.class, ftype); + if (isStatic) expType = expType.dropParameterTypes(0, 1); + Exception noAccess = null; + MethodHandle mh; + try { + switch (testMode0 & ~(TEST_BOUND | TEST_NPE)) { + case TEST_UNREFLECT: mh = lookup.unreflectGetter(f); break; + case TEST_FIND_FIELD: mh = lookup.findGetter(fclass, fname, ftype); break; + case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype); break; + case TEST_SETTER| + TEST_UNREFLECT: mh = lookup.unreflectSetter(f); break; + case TEST_SETTER| + TEST_FIND_FIELD: mh = lookup.findSetter(fclass, fname, ftype); break; + case TEST_SETTER| + TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype); break; + default: + throw new InternalError("testMode="+testMode); + } + } catch (ReflectiveOperationException ex) { + mh = null; + noAccess = ex; + assertExceptionClass( + (fname.contains("bogus")) + ? NoSuchFieldException.class + : IllegalAccessException.class, + noAccess); + if (verbosity >= 5) ex.printStackTrace(System.out); + } + if (verbosity >= 3) + System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype + +" => "+mh + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && !testNPE && noAccess != null) throw new RuntimeException(noAccess); + assertEquals(positive0 ? "positive test" : "negative test erroneously passed", positive0, mh != null); + if (!positive && !testNPE) return; // negative access test failed as expected + assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount()); + + + assertSame(mh.type(), expType); + //assertNameStringContains(mh, fname); // This does not hold anymore with LFs + HasFields fields = new HasFields(); + HasFields fieldsForMH = fields; + if (testNPE) fieldsForMH = null; // perturb MH argument to elicit expected error + if (doBound) + mh = mh.bindTo(fieldsForMH); + Object sawValue; + Class vtype = ftype; + if (ftype != int.class) vtype = Object.class; + if (isGetter) { + mh = mh.asType(mh.type().generic() + .changeReturnType(vtype)); + } else { + int last = mh.type().parameterCount() - 1; + mh = mh.asType(mh.type().generic() + .changeReturnType(void.class) + .changeParameterType(last, vtype)); + } + if (f != null && f.getDeclaringClass() == HasFields.class) { + assertEquals(f.get(fields), value); // clean to start with + } + Throwable caughtEx = null; + if (isGetter) { + Object expValue = value; + for (int i = 0; i <= 1; i++) { + sawValue = null; // make DA rules happy under try/catch + try { + if (isStatic || doBound) { + if (ftype == int.class) + sawValue = (int) mh.invokeExact(); // do these exactly + else + sawValue = mh.invokeExact(); + } else { + if (ftype == int.class) + sawValue = (int) mh.invokeExact((Object) fieldsForMH); + else + sawValue = mh.invokeExact((Object) fieldsForMH); + } + } catch (RuntimeException ex) { + if (ex instanceof NullPointerException && testNPE) { + caughtEx = ex; + break; + } + } + assertEquals(sawValue, expValue); + if (f != null && f.getDeclaringClass() == HasFields.class + && !Modifier.isFinal(f.getModifiers())) { + Object random = randomArg(ftype); + f.set(fields, random); + expValue = random; + } else { + break; + } + } + } else { + for (int i = 0; i <= 1; i++) { + Object putValue = randomArg(ftype); + try { + if (isStatic || doBound) { + if (ftype == int.class) + mh.invokeExact((int)putValue); // do these exactly + else + mh.invokeExact(putValue); + } else { + if (ftype == int.class) + mh.invokeExact((Object) fieldsForMH, (int)putValue); + else + mh.invokeExact((Object) fieldsForMH, putValue); + } + } catch (RuntimeException ex) { + if (ex instanceof NullPointerException && testNPE) { + caughtEx = ex; + break; + } + } + if (f != null && f.getDeclaringClass() == HasFields.class) { + assertEquals(f.get(fields), putValue); + } + } + } + if (f != null && f.getDeclaringClass() == HasFields.class) { + f.set(fields, value); // put it back + } + if (testNPE) { + if (caughtEx == null || !(caughtEx instanceof NullPointerException)) + throw new RuntimeException("failed to catch NPE exception"+(caughtEx == null ? " (caughtEx=null)" : ""), caughtEx); + caughtEx = null; // nullify expected exception + } + if (caughtEx != null) { + throw new RuntimeException("unexpected exception", caughtEx); + } + } + + @Test + public void testUnreflectSetter() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testUnreflectSetter0); + } + + public void testUnreflectSetter0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("unreflectSetter"); + testSetter(TEST_UNREFLECT); + } + + @Test + public void testFindSetter() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindSetter0); + } + + public void testFindSetter0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findSetter"); + testSetter(TEST_FIND_FIELD); + testSetter(TEST_FIND_FIELD | TEST_BOUND); + } + + @Test + public void testFindStaticSetter() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFindStaticSetter0); + } + + public void testFindStaticSetter0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findStaticSetter"); + testSetter(TEST_FIND_STATIC); + } + + public void testSetter(int testMode) throws Throwable { + Lookup lookup = PRIVATE; // FIXME: test more lookups than this one + startTest("unreflectSetter"); + for (Object[] c : HasFields.CASES) { + boolean positive = (c[1] != Error.class); + testSetter(positive, lookup, c[0], c[1], testMode); + if (positive) + testSetter(positive, lookup, c[0], c[1], testMode | TEST_NPE); + } + for (int isStaticN = 0; isStaticN <= 1; isStaticN++) { + testSetter(false, lookup, + new Object[]{ (isStaticN != 0), System.class, "bogus", char.class }, + null, testMode); + } + } + + public void testSetter(boolean positive, MethodHandles.Lookup lookup, + Object fieldRef, Object value, int testMode) throws Throwable { + testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER); + } + + @Test + public void testArrayElementGetter() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testArrayElementGetter0); + } + + public void testArrayElementGetter0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("arrayElementGetter"); + testArrayElementGetterSetter(false); + } + + @Test + public void testArrayElementSetter() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testArrayElementSetter0); + } + + public void testArrayElementSetter0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("arrayElementSetter"); + testArrayElementGetterSetter(true); + } + + private static final int TEST_ARRAY_NONE = 0, TEST_ARRAY_NPE = 1, TEST_ARRAY_OOB = 2, TEST_ARRAY_ASE = 3; + + public void testArrayElementGetterSetter(boolean testSetter) throws Throwable { + testArrayElementGetterSetter(testSetter, TEST_ARRAY_NONE); + } + + @Test + public void testArrayElementErrors() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testArrayElementErrors0); + } + + public void testArrayElementErrors0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("arrayElementErrors"); + testArrayElementGetterSetter(false, TEST_ARRAY_NPE); + testArrayElementGetterSetter(true, TEST_ARRAY_NPE); + testArrayElementGetterSetter(false, TEST_ARRAY_OOB); + testArrayElementGetterSetter(true, TEST_ARRAY_OOB); + testArrayElementGetterSetter(new Object[10], true, TEST_ARRAY_ASE); + testArrayElementGetterSetter(new Example[10], true, TEST_ARRAY_ASE); + testArrayElementGetterSetter(new IntExample[10], true, TEST_ARRAY_ASE); + } + + public void testArrayElementGetterSetter(boolean testSetter, int negTest) throws Throwable { + testArrayElementGetterSetter(new String[10], testSetter, negTest); + testArrayElementGetterSetter(new Iterable[10], testSetter, negTest); + testArrayElementGetterSetter(new Example[10], testSetter, negTest); + testArrayElementGetterSetter(new IntExample[10], testSetter, negTest); + testArrayElementGetterSetter(new Object[10], testSetter, negTest); + testArrayElementGetterSetter(new boolean[10], testSetter, negTest); + testArrayElementGetterSetter(new byte[10], testSetter, negTest); + testArrayElementGetterSetter(new char[10], testSetter, negTest); + testArrayElementGetterSetter(new short[10], testSetter, negTest); + testArrayElementGetterSetter(new int[10], testSetter, negTest); + testArrayElementGetterSetter(new float[10], testSetter, negTest); + testArrayElementGetterSetter(new long[10], testSetter, negTest); + testArrayElementGetterSetter(new double[10], testSetter, negTest); + } + + public void testArrayElementGetterSetter(Object array, boolean testSetter, int negTest) throws Throwable { + boolean positive = (negTest == TEST_ARRAY_NONE); + int length = Array.getLength(array); + Class arrayType = array.getClass(); + Class elemType = arrayType.getComponentType(); + Object arrayToMH = array; + // this stanza allows negative tests to make argument perturbations: + switch (negTest) { + case TEST_ARRAY_NPE: + arrayToMH = null; + break; + case TEST_ARRAY_OOB: + assert(length > 0); + arrayToMH = Array.newInstance(elemType, 0); + break; + case TEST_ARRAY_ASE: + assert(testSetter && !elemType.isPrimitive()); + if (elemType == Object.class) + arrayToMH = new StringBuffer[length]; // very random subclass of Object! + else if (elemType == Example.class) + arrayToMH = new SubExample[length]; + else if (elemType == IntExample.class) + arrayToMH = new SubIntExample[length]; + else + return; // can't make an ArrayStoreException test + assert(arrayType.isInstance(arrayToMH)) + : Arrays.asList(arrayType, arrayToMH.getClass(), testSetter, negTest); + break; + } + countTest(positive); + if (verbosity > 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+length+"]"+(positive ? "" : " negative test #"+negTest+" using "+Arrays.deepToString(new Object[]{arrayToMH}))); + MethodType expType = !testSetter + ? MethodType.methodType(elemType, arrayType, int.class) + : MethodType.methodType(void.class, arrayType, int.class, elemType); + MethodHandle mh = !testSetter + ? MethodHandles.arrayElementGetter(arrayType) + : MethodHandles.arrayElementSetter(arrayType); + assertSame(mh.type(), expType); + if (elemType != int.class && elemType != boolean.class) { + MethodType gtype = mh.type().generic().changeParameterType(1, int.class); + if (testSetter) gtype = gtype.changeReturnType(void.class); + mh = mh.asType(gtype); + } + Object sawValue, expValue; + List model = array2list(array); + Throwable caughtEx = null; + for (int i = 0; i < length; i++) { + // update array element + Object random = randomArg(elemType); + model.set(i, random); + if (testSetter) { + try { + if (elemType == int.class) + mh.invokeExact((int[]) arrayToMH, i, (int)random); + else if (elemType == boolean.class) + mh.invokeExact((boolean[]) arrayToMH, i, (boolean)random); + else + mh.invokeExact(arrayToMH, i, random); + } catch (RuntimeException ex) { + caughtEx = ex; + break; + } + assertEquals(model, array2list(array)); + } else { + Array.set(array, i, random); + } + if (verbosity >= 5) { + List array2list = array2list(array); + System.out.println("a["+i+"]="+random+" => "+array2list); + if (!array2list.equals(model)) + System.out.println("*** != "+model); + } + // observe array element + sawValue = Array.get(array, i); + if (!testSetter) { + expValue = sawValue; + try { + if (elemType == int.class) + sawValue = (int) mh.invokeExact((int[]) arrayToMH, i); + else if (elemType == boolean.class) + sawValue = (boolean) mh.invokeExact((boolean[]) arrayToMH, i); + else + sawValue = mh.invokeExact(arrayToMH, i); + } catch (RuntimeException ex) { + caughtEx = ex; + break; + } + assertEquals(sawValue, expValue); + assertEquals(model, array2list(array)); + } + } + if (!positive) { + if (caughtEx == null) + throw new RuntimeException("failed to catch exception for negTest="+negTest); + // test the kind of exception + Class reqType = null; + switch (negTest) { + case TEST_ARRAY_ASE: reqType = ArrayStoreException.class; break; + case TEST_ARRAY_OOB: reqType = ArrayIndexOutOfBoundsException.class; break; + case TEST_ARRAY_NPE: reqType = NullPointerException.class; break; + default: assert(false); + } + if (reqType.isInstance(caughtEx)) { + caughtEx = null; // nullify expected exception + } + } + if (caughtEx != null) { + throw new RuntimeException("unexpected exception", caughtEx); + } + } + + List array2list(Object array) { + int length = Array.getLength(array); + ArrayList model = new ArrayList<>(length); + for (int i = 0; i < length; i++) + model.add(Array.get(array, i)); + return model; + } + + @Test + public void testConvertArguments() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testConvertArguments0); + } + + public void testConvertArguments0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("convertArguments"); + testConvert(Callee.ofType(1), null, "id", int.class); + testConvert(Callee.ofType(1), null, "id", String.class); + testConvert(Callee.ofType(1), null, "id", Integer.class); + testConvert(Callee.ofType(1), null, "id", short.class); + testConvert(Callee.ofType(1), null, "id", char.class); + testConvert(Callee.ofType(1), null, "id", byte.class); + } + + void testConvert(MethodHandle id, Class rtype, String name, Class... params) throws Throwable { + testConvert(true, id, rtype, name, params); + } + + void testConvert(boolean positive, + MethodHandle id, Class rtype, String name, Class... params) throws Throwable { + countTest(positive); + MethodType idType = id.type(); + if (rtype == null) rtype = idType.returnType(); + for (int i = 0; i < params.length; i++) { + if (params[i] == null) params[i] = idType.parameterType(i); + } + // simulate the pairwise conversion + MethodType newType = MethodType.methodType(rtype, params); + Object[] args = randomArgs(newType.parameterArray()); + Object[] convArgs = args.clone(); + for (int i = 0; i < args.length; i++) { + Class src = newType.parameterType(i); + Class dst = idType.parameterType(i); + if (src != dst) + convArgs[i] = castToWrapper(convArgs[i], dst); + } + Object convResult = id.invokeWithArguments(convArgs); + { + Class dst = newType.returnType(); + Class src = idType.returnType(); + if (src != dst) + convResult = castToWrapper(convResult, dst); + } + MethodHandle target = null; + RuntimeException error = null; + try { + target = id.asType(newType); + } catch (WrongMethodTypeException ex) { + error = ex; + } + if (verbosity >= 3) + System.out.println("convert "+id+ " to "+newType+" => "+target + +(error == null ? "" : " !! "+error)); + if (positive && error != null) throw error; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(newType, target.type()); + printCalled(target, id.toString(), args); + Object result = target.invokeWithArguments(args); + assertCalled(name, convArgs); + assertEquals(convResult, result); + if (verbosity >= 1) + System.out.print(':'); + } + + @Test + public void testVarargsCollector() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testVarargsCollector0); + } + + public void testVarargsCollector0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("varargsCollector"); + MethodHandle vac0 = PRIVATE.findStatic(MethodHandlesTest.class, "called", + MethodType.methodType(Object.class, String.class, Object[].class)); + vac0 = vac0.bindTo("vac"); + MethodHandle vac = vac0.asVarargsCollector(Object[].class); + testConvert(true, vac.asType(MethodType.genericMethodType(0)), null, "vac"); + testConvert(true, vac.asType(MethodType.genericMethodType(0)), null, "vac"); + for (Class at : new Class[] { Object.class, String.class, Integer.class }) { + testConvert(true, vac.asType(MethodType.genericMethodType(1)), null, "vac", at); + testConvert(true, vac.asType(MethodType.genericMethodType(2)), null, "vac", at, at); + } + } + + @Test + public void testFilterReturnValue() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFilterReturnValue0); + } + + public void testFilterReturnValue0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("filterReturnValue"); + Class classOfVCList = varargsList(1).invokeWithArguments(0).getClass(); + assertTrue(List.class.isAssignableFrom(classOfVCList)); + for (int nargs = 0; nargs <= 3; nargs++) { + for (Class rtype : new Class[] { Object.class, + List.class, + int.class, + byte.class, + long.class, + CharSequence.class, + String.class }) { + testFilterReturnValue(nargs, rtype); + } + } + } + + void testFilterReturnValue(int nargs, Class rtype) throws Throwable { + countTest(); + MethodHandle target = varargsList(nargs, rtype); + MethodHandle filter; + if (List.class.isAssignableFrom(rtype) || rtype.isAssignableFrom(List.class)) + filter = varargsList(1); // add another layer of list-ness + else + filter = MethodHandles.identity(rtype); + filter = filter.asType(MethodType.methodType(target.type().returnType(), rtype)); + Object[] argsToPass = randomArgs(nargs, Object.class); + if (verbosity >= 3) + System.out.println("filter "+target+" to "+rtype.getSimpleName()+" with "+filter); + MethodHandle target2 = MethodHandles.filterReturnValue(target, filter); + if (verbosity >= 4) + System.out.println("filtered target: "+target2); + // Simulate expected effect of filter on return value: + Object unfiltered = target.invokeWithArguments(argsToPass); + Object expected = filter.invokeWithArguments(unfiltered); + if (verbosity >= 4) + System.out.println("unfiltered: "+unfiltered+" : "+unfiltered.getClass().getSimpleName()); + if (verbosity >= 4) + System.out.println("expected: "+expected+" : "+expected.getClass().getSimpleName()); + Object result = target2.invokeWithArguments(argsToPass); + if (verbosity >= 3) + System.out.println("result: "+result+" : "+result.getClass().getSimpleName()); + if (!expected.equals(result)) + System.out.println("*** fail at n/rt = "+nargs+"/"+rtype.getSimpleName()+": "+ + Arrays.asList(argsToPass)+" => "+result+" != "+expected); + assertEquals(expected, result); + } + + @Test + public void testFilterArguments() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFilterArguments0); + } + + public void testFilterArguments0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("filterArguments"); + for (int nargs = 1; nargs <= 6; nargs++) { + for (int pos = 0; pos < nargs; pos++) { + testFilterArguments(nargs, pos); + } + } + } + + void testFilterArguments(int nargs, int pos) throws Throwable { + countTest(); + MethodHandle target = varargsList(nargs); + MethodHandle filter = varargsList(1); + filter = filter.asType(filter.type().generic()); + Object[] argsToPass = randomArgs(nargs, Object.class); + if (verbosity >= 3) + System.out.println("filter "+target+" at "+pos+" with "+filter); + MethodHandle target2 = MethodHandles.filterArguments(target, pos, filter); + // Simulate expected effect of filter on arglist: + Object[] filteredArgs = argsToPass.clone(); + filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]); + List expected = Arrays.asList(filteredArgs); + Object result = target2.invokeWithArguments(argsToPass); + if (verbosity >= 3) + System.out.println("result: "+result); + if (!expected.equals(result)) + System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected); + assertEquals(expected, result); + } + + @Test + public void testCollectArguments() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testCollectArguments0); + } + + public void testCollectArguments0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("collectArguments"); + testFoldOrCollectArguments(true, false); + } + + @Test + public void testFoldArguments() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testFoldArguments0); + CodeCacheOverflowProcessor.runMHTest(this::testFoldArguments1); + } + + public void testFoldArguments0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("foldArguments"); + testFoldOrCollectArguments(false, false); + } + + public void testFoldArguments1() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("foldArguments/pos"); + testFoldOrCollectArguments(false, true); + } + + void testFoldOrCollectArguments(boolean isCollect, boolean withFoldPos) throws Throwable { + assert !(isCollect && withFoldPos); // exclude illegal argument combination + for (Class lastType : new Class[]{ Object.class, String.class, int.class }) { + for (Class collectType : new Class[]{ Object.class, String.class, int.class, void.class }) { + int maxArity = 10; + if (collectType != String.class) maxArity = 5; + if (lastType != Object.class) maxArity = 4; + for (int nargs = 0; nargs <= maxArity; nargs++) { + ArrayList> argTypes = new ArrayList<>(Collections.nCopies(nargs, Object.class)); + int maxMix = 20; + if (collectType != Object.class) maxMix = 0; + Map argTypesSeen = new HashMap<>(); + for (int mix = 0; mix <= maxMix; mix++) { + if (!mixArgs(argTypes, mix, argTypesSeen)) continue; + for (int collect = 0; collect <= nargs; collect++) { + for (int pos = 0; pos <= nargs - collect; pos++) { + testFoldOrCollectArguments(argTypes, pos, collect, collectType, lastType, isCollect, withFoldPos); + } + } + } + } + } + } + } + + boolean mixArgs(List> argTypes, int mix, Map argTypesSeen) { + assert(mix >= 0); + if (mix == 0) return true; // no change + if ((mix >>> argTypes.size()) != 0) return false; + for (int i = 0; i < argTypes.size(); i++) { + if (i >= 31) break; + boolean bit = (mix & (1 << i)) != 0; + if (bit) { + Class type = argTypes.get(i); + if (type == Object.class) + type = String.class; + else if (type == String.class) + type = int.class; + else + type = Object.class; + argTypes.set(i, type); + } + } + Integer prev = argTypesSeen.put(new ArrayList<>(argTypes), mix); + if (prev != null) { + if (verbosity >= 4) System.out.println("mix "+prev+" repeated "+mix+": "+argTypes); + return false; + } + if (verbosity >= 3) System.out.println("mix "+mix+" = "+argTypes); + return true; + } + + void testFoldOrCollectArguments(List> argTypes, // argument types minus the inserted combineType + int pos, int fold, // position and length of the folded arguments + Class combineType, // type returned from the combiner + Class lastType, // type returned from the target + boolean isCollect, + boolean withFoldPos) throws Throwable { + int nargs = argTypes.size(); + if (pos != 0 && !isCollect && !withFoldPos) return; // test MethodHandles.foldArguments(MH,MH) only for pos=0 + countTest(); + List> combineArgTypes = argTypes.subList(pos, pos + fold); + List> targetArgTypes = new ArrayList<>(argTypes); + if (isCollect) // does target see arg[pos..pos+cc-1]? + targetArgTypes.subList(pos, pos + fold).clear(); + if (combineType != void.class) + targetArgTypes.add(pos, combineType); + MethodHandle target = varargsList(targetArgTypes, lastType); + MethodHandle combine = varargsList(combineArgTypes, combineType); + List argsToPass = Arrays.asList(randomArgs(argTypes)); + if (verbosity >= 3) + System.out.println((isCollect ? "collect" : "fold")+" "+target+" with "+combine); + MethodHandle target2; + if (isCollect) + target2 = MethodHandles.collectArguments(target, pos, combine); + else + target2 = withFoldPos ? MethodHandles.foldArguments(target, pos, combine) : MethodHandles.foldArguments(target, combine); + // Simulate expected effect of combiner on arglist: + List expectedList = new ArrayList<>(argsToPass); + List argsToFold = expectedList.subList(pos, pos + fold); + if (verbosity >= 3) + System.out.println((isCollect ? "collect" : "fold")+": "+argsToFold+" into "+target2); + Object foldedArgs = combine.invokeWithArguments(argsToFold); + if (isCollect) + argsToFold.clear(); + if (combineType != void.class) + argsToFold.add(0, foldedArgs); + Object result = target2.invokeWithArguments(argsToPass); + if (verbosity >= 3) + System.out.println("result: "+result); + Object expected = target.invokeWithArguments(expectedList); + if (!expected.equals(result)) + System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected); + assertEquals(expected, result); + } + + @Test + public void testDropArguments() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testDropArguments0); + } + + public void testDropArguments0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("dropArguments"); + for (int nargs = 0; nargs <= 4; nargs++) { + for (int drop = 1; drop <= 4; drop++) { + for (int pos = 0; pos <= nargs; pos++) { + testDropArguments(nargs, pos, drop); + } + } + } + } + + void testDropArguments(int nargs, int pos, int drop) throws Throwable { + countTest(); + MethodHandle target = varargsArray(nargs); + Object[] args = randomArgs(target.type().parameterArray()); + MethodHandle target2 = MethodHandles.dropArguments(target, pos, + Collections.nCopies(drop, Object.class).toArray(new Class[0])); + List resList = Arrays.asList(args); + List argsToDrop = new ArrayList<>(resList); + for (int i = drop; i > 0; i--) { + argsToDrop.add(pos, "blort#"+i); + } + Object res2 = target2.invokeWithArguments(argsToDrop); + Object res2List = Arrays.asList((Object[])res2); + //if (!resList.equals(res2List)) + // System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List); + assertEquals(resList, res2List); + } + + @Test + public void testGuardWithTest() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testGuardWithTest0); + } + + public void testGuardWithTest0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("guardWithTest"); + for (int nargs = 0; nargs <= 50; nargs++) { + if (CAN_TEST_LIGHTLY && nargs > 7) break; + testGuardWithTest(nargs, Object.class); + testGuardWithTest(nargs, String.class); + } + } + + void testGuardWithTest(int nargs, Class argClass) throws Throwable { + testGuardWithTest(nargs, 0, argClass); + if (nargs <= 5 || nargs % 10 == 3) { + for (int testDrops = 1; testDrops <= nargs; testDrops++) + testGuardWithTest(nargs, testDrops, argClass); + } + } + + void testGuardWithTest(int nargs, int testDrops, Class argClass) throws Throwable { + countTest(); + int nargs1 = Math.min(3, nargs); + MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class)); + MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs1)); + MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs1)); + while (test.type().parameterCount() > nargs) + // 0: test = constant(MISSING_ARG.equals(MISSING_ARG)) + // 1: test = lambda (_) MISSING_ARG.equals(_) + test = MethodHandles.insertArguments(test, 0, MISSING_ARG); + if (argClass != Object.class) { + test = changeArgTypes(test, argClass); + target = changeArgTypes(target, argClass); + fallback = changeArgTypes(fallback, argClass); + } + int testArgs = nargs - testDrops; + assert(testArgs >= 0); + test = addTrailingArgs(test, Math.min(testArgs, nargs), argClass); + target = addTrailingArgs(target, nargs, argClass); + fallback = addTrailingArgs(fallback, nargs, argClass); + Object[][] argLists = { + { }, + { "foo" }, { MethodHandlesTest.MISSING_ARG }, + { "foo", "foo" }, { "foo", "bar" }, + { "foo", "foo", "baz" }, { "foo", "bar", "baz" } + }; + for (Object[] argList : argLists) { + Object[] argList1 = argList; + if (argList.length != nargs) { + if (argList.length != nargs1) continue; + argList1 = Arrays.copyOf(argList, nargs); + Arrays.fill(argList1, nargs1, nargs, MethodHandlesTest.MISSING_ARG_2); + } + MethodHandle test1 = test; + if (test1.type().parameterCount() > testArgs) { + int pc = test1.type().parameterCount(); + test1 = MethodHandles.insertArguments(test, testArgs, Arrays.copyOfRange(argList1, testArgs, pc)); + } + MethodHandle mh = MethodHandles.guardWithTest(test1, target, fallback); + assertEquals(target.type(), mh.type()); + boolean equals; + switch (nargs) { + case 0: equals = true; break; + case 1: equals = MethodHandlesTest.MISSING_ARG.equals(argList[0]); break; + default: equals = argList[0].equals(argList[1]); break; + } + String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals"); + if (verbosity >= 3) + System.out.println(logEntry(willCall, argList)); + Object result = mh.invokeWithArguments(argList1); + assertCalled(willCall, argList); + } + } + + @Test + public void testGenericLoopCombinator() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testGenericLoopCombinator0); + } + + public void testGenericLoopCombinator0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("loop"); + // Test as follows: + // * Have an increasing number of loop-local state. Local state type diversity grows with the number. + // * Initializers set the starting value of loop-local state from the corresponding loop argument. + // * For each local state element, there is a predicate - for all state combinations, exercise all predicates. + // * Steps modify each local state element in each iteration. + // * Finalizers group all local state elements into a resulting array. Verify end values. + // * Exercise both pre- and post-checked loops. + // Local state types, start values, predicates, and steps: + // * int a, 0, a < 7, a = a + 1 + // * double b, 7.0, b > 0.5, b = b / 2.0 + // * String c, "start", c.length <= 9, c = c + a + final Class[] argTypes = new Class[] {int.class, double.class, String.class}; + final Object[][] args = new Object[][] { + new Object[]{0 }, + new Object[]{0, 7.0 }, + new Object[]{0, 7.0, "start"} + }; + // These are the expected final state tuples for argument type tuple / predicate combinations, for pre- and + // post-checked loops: + final Object[][] preCheckedResults = new Object[][] { + new Object[]{7 }, // (int) / int + new Object[]{7, 0.0546875 }, // (int,double) / int + new Object[]{5, 0.4375 }, // (int,double) / double + new Object[]{7, 0.0546875, "start1234567"}, // (int,double,String) / int + new Object[]{5, 0.4375, "start1234" }, // (int,double,String) / double + new Object[]{6, 0.109375, "start12345" } // (int,double,String) / String + }; + final Object[][] postCheckedResults = new Object[][] { + new Object[]{7 }, // (int) / int + new Object[]{7, 0.109375 }, // (int,double) / int + new Object[]{4, 0.4375 }, // (int,double) / double + new Object[]{7, 0.109375, "start123456"}, // (int,double,String) / int + new Object[]{4, 0.4375, "start123" }, // (int,double,String) / double + new Object[]{5, 0.21875, "start12345" } // (int,double,String) / String + }; + final Lookup l = MethodHandles.lookup(); + final Class MHT = MethodHandlesTest.class; + final Class B = boolean.class; + final Class I = int.class; + final Class D = double.class; + final Class S = String.class; + final MethodHandle hip = l.findStatic(MHT, "loopIntPred", methodType(B, I)); + final MethodHandle hdp = l.findStatic(MHT, "loopDoublePred", methodType(B, I, D)); + final MethodHandle hsp = l.findStatic(MHT, "loopStringPred", methodType(B, I, D, S)); + final MethodHandle his = l.findStatic(MHT, "loopIntStep", methodType(I, I)); + final MethodHandle hds = l.findStatic(MHT, "loopDoubleStep", methodType(D, I, D)); + final MethodHandle hss = l.findStatic(MHT, "loopStringStep", methodType(S, I, D, S)); + final MethodHandle[] preds = new MethodHandle[] {hip, hdp, hsp}; + final MethodHandle[] steps = new MethodHandle[] {his, hds, hss}; + for (int nargs = 1, useResultsStart = 0; nargs <= argTypes.length; useResultsStart += nargs++) { + Class[] useArgTypes = Arrays.copyOf(argTypes, nargs, Class[].class); + MethodHandle[] usePreds = Arrays.copyOf(preds, nargs, MethodHandle[].class); + MethodHandle[] useSteps = Arrays.copyOf(steps, nargs, MethodHandle[].class); + Object[] useArgs = args[nargs - 1]; + Object[][] usePreCheckedResults = new Object[nargs][]; + Object[][] usePostCheckedResults = new Object[nargs][]; + System.arraycopy(preCheckedResults, useResultsStart, usePreCheckedResults, 0, nargs); + System.arraycopy(postCheckedResults, useResultsStart, usePostCheckedResults, 0, nargs); + testGenericLoopCombinator(nargs, useArgTypes, usePreds, useSteps, useArgs, usePreCheckedResults, + usePostCheckedResults); + } + } + + void testGenericLoopCombinator(int nargs, Class[] argTypes, MethodHandle[] preds, MethodHandle[] steps, + Object[] args, Object[][] preCheckedResults, Object[][] postCheckedResults) + throws Throwable { + List> lArgTypes = Arrays.asList(argTypes); + // Predicate and step handles are passed in as arguments, initializer and finalizer handles are constructed here + // from the available information. + MethodHandle[] inits = new MethodHandle[nargs]; + for (int i = 0; i < nargs; ++i) { + MethodHandle h; + // Initializers are meant to return whatever they are passed at a given argument position. This means that + // additional arguments may have to be appended and prepended. + h = MethodHandles.identity(argTypes[i]); + if (i < nargs - 1) { + h = MethodHandles.dropArguments(h, 1, lArgTypes.subList(i + 1, nargs)); + } + if (i > 0) { + h = MethodHandles.dropArguments(h, 0, lArgTypes.subList(0, i)); + } + inits[i] = h; + } + // Finalizers are all meant to collect all of the loop-local state in a single array and return that. Local + // state is passed before the loop args. Construct such a finalizer by first taking a varargsArray collector for + // the number of local state arguments, and then appending the loop args as to-be-dropped arguments. + MethodHandle[] finis = new MethodHandle[nargs]; + MethodHandle genericFini = MethodHandles.dropArguments( + varargsArray(nargs).asType(methodType(Object[].class, lArgTypes)), nargs, lArgTypes); + Arrays.fill(finis, genericFini); + // The predicate and step handles' signatures need to be extended. They currently just accept local state args; + // append possibly missing local state args and loop args using dropArguments. + for (int i = 0; i < nargs; ++i) { + List> additionalLocalStateArgTypes = lArgTypes.subList(i + 1, nargs); + preds[i] = MethodHandles.dropArguments( + MethodHandles.dropArguments(preds[i], i + 1, additionalLocalStateArgTypes), nargs, lArgTypes); + steps[i] = MethodHandles.dropArguments( + MethodHandles.dropArguments(steps[i], i + 1, additionalLocalStateArgTypes), nargs, lArgTypes); + } + // Iterate over all of the predicates, using only one of them at a time. + for (int i = 0; i < nargs; ++i) { + MethodHandle[] usePreds; + if (nargs == 1) { + usePreds = preds; + } else { + // Create an all-null preds array, and only use one predicate in this iteration. The null entries will + // be substituted with true predicates by the loop combinator. + usePreds = new MethodHandle[nargs]; + usePreds[i] = preds[i]; + } + // Go for it. + if (verbosity >= 3) { + System.out.println("calling loop for argument types " + lArgTypes + " with predicate at index " + i); + if (verbosity >= 5) { + System.out.println("predicates: " + Arrays.asList(usePreds)); + } + } + MethodHandle[] preInits = new MethodHandle[nargs + 1]; + MethodHandle[] prePreds = new MethodHandle[nargs + 1]; + MethodHandle[] preSteps = new MethodHandle[nargs + 1]; + MethodHandle[] preFinis = new MethodHandle[nargs + 1]; + System.arraycopy(inits, 0, preInits, 1, nargs); + System.arraycopy(usePreds, 0, prePreds, 0, nargs); // preds are offset by 1 for pre-checked loops + System.arraycopy(steps, 0, preSteps, 1, nargs); + System.arraycopy(finis, 0, preFinis, 0, nargs); // finis are also offset by 1 for pre-checked loops + // Convert to clause-major form. + MethodHandle[][] preClauses = new MethodHandle[nargs + 1][4]; + MethodHandle[][] postClauses = new MethodHandle[nargs][4]; + toClauseMajor(preClauses, preInits, preSteps, prePreds, preFinis); + toClauseMajor(postClauses, inits, steps, usePreds, finis); + MethodHandle pre = MethodHandles.loop(preClauses); + MethodHandle post = MethodHandles.loop(postClauses); + if (verbosity >= 6) { + System.out.println("pre-handle: " + pre); + } + Object[] preResults = (Object[]) pre.invokeWithArguments(args); + if (verbosity >= 4) { + System.out.println("pre-checked: expected " + Arrays.asList(preCheckedResults[i]) + ", actual " + + Arrays.asList(preResults)); + } + if (verbosity >= 6) { + System.out.println("post-handle: " + post); + } + Object[] postResults = (Object[]) post.invokeWithArguments(args); + if (verbosity >= 4) { + System.out.println("post-checked: expected " + Arrays.asList(postCheckedResults[i]) + ", actual " + + Arrays.asList(postResults)); + } + assertArrayEquals(preCheckedResults[i], preResults); + assertArrayEquals(postCheckedResults[i], postResults); + } + } + + static void toClauseMajor(MethodHandle[][] clauses, MethodHandle[] init, MethodHandle[] step, MethodHandle[] pred, MethodHandle[] fini) { + for (int i = 0; i < clauses.length; ++i) { + clauses[i][0] = init[i]; + clauses[i][1] = step[i]; + clauses[i][2] = pred[i]; + clauses[i][3] = fini[i]; + } + } + + @Test + public void testThrowException() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testThrowException0); + } + + public void testThrowException0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("throwException"); + testThrowException(int.class, new ClassCastException("testing")); + testThrowException(void.class, new java.io.IOException("testing")); + testThrowException(String.class, new LinkageError("testing")); + } + + void testThrowException(Class returnType, Throwable thrown) throws Throwable { + countTest(); + Class exType = thrown.getClass(); + MethodHandle target = MethodHandles.throwException(returnType, exType); + //System.out.println("throwing with "+target+" : "+thrown); + MethodType expectedType = MethodType.methodType(returnType, exType); + assertEquals(expectedType, target.type()); + target = target.asType(target.type().generic()); + Throwable caught = null; + try { + Object res = target.invokeExact((Object) thrown); + fail("got "+res+" instead of throwing "+thrown); + } catch (Throwable ex) { + if (ex != thrown) { + if (ex instanceof Error) throw (Error)ex; + if (ex instanceof RuntimeException) throw (RuntimeException)ex; + } + caught = ex; + } + assertSame(thrown, caught); + } + + @Test + public void testTryFinally() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testTryFinally0); + } + + public void testTryFinally0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("tryFinally"); + String inputMessage = "returned"; + String augmentedMessage = "augmented"; + String thrownMessage = "thrown"; + String rethrownMessage = "rethrown"; + // Test these cases: + // * target returns, cleanup passes through + // * target returns, cleanup augments + // * target throws, cleanup augments and returns + // * target throws, cleanup augments and rethrows + MethodHandle target = MethodHandles.identity(String.class); + MethodHandle targetThrow = MethodHandles.dropArguments( + MethodHandles.throwException(String.class, Exception.class).bindTo(new Exception(thrownMessage)), 0, String.class); + MethodHandle cleanupPassThrough = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0, + Throwable.class, String.class); + MethodHandle cleanupAugment = MethodHandles.dropArguments(MethodHandles.constant(String.class, augmentedMessage), + 0, Throwable.class, String.class, String.class); + MethodHandle cleanupCatch = MethodHandles.dropArguments(MethodHandles.constant(String.class, thrownMessage), 0, + Throwable.class, String.class, String.class); + MethodHandle cleanupThrow = MethodHandles.dropArguments(MethodHandles.throwException(String.class, Exception.class). + bindTo(new Exception(rethrownMessage)), 0, Throwable.class, String.class, String.class); + testTryFinally(target, cleanupPassThrough, inputMessage, inputMessage, false); + testTryFinally(target, cleanupAugment, inputMessage, augmentedMessage, false); + testTryFinally(targetThrow, cleanupCatch, inputMessage, thrownMessage, true); + testTryFinally(targetThrow, cleanupThrow, inputMessage, rethrownMessage, true); + // Test the same cases as above for void targets and cleanups. + MethodHandles.Lookup lookup = MethodHandles.lookup(); + Class C = this.getClass(); + MethodType targetType = methodType(void.class, String[].class); + MethodType cleanupType = methodType(void.class, Throwable.class, String[].class); + MethodHandle vtarget = lookup.findStatic(C, "vtarget", targetType); + MethodHandle vtargetThrow = lookup.findStatic(C, "vtargetThrow", targetType); + MethodHandle vcleanupPassThrough = lookup.findStatic(C, "vcleanupPassThrough", cleanupType); + MethodHandle vcleanupAugment = lookup.findStatic(C, "vcleanupAugment", cleanupType); + MethodHandle vcleanupCatch = lookup.findStatic(C, "vcleanupCatch", cleanupType); + MethodHandle vcleanupThrow = lookup.findStatic(C, "vcleanupThrow", cleanupType); + testTryFinally(vtarget, vcleanupPassThrough, inputMessage, inputMessage, false); + testTryFinally(vtarget, vcleanupAugment, inputMessage, augmentedMessage, false); + testTryFinally(vtargetThrow, vcleanupCatch, inputMessage, thrownMessage, true); + testTryFinally(vtargetThrow, vcleanupThrow, inputMessage, rethrownMessage, true); + } + + void testTryFinally(MethodHandle target, MethodHandle cleanup, String input, String msg, boolean mustCatch) + throws Throwable { + countTest(); + MethodHandle tf = MethodHandles.tryFinally(target, cleanup); + String result = null; + boolean isVoid = target.type().returnType() == void.class; + String[] argArray = new String[]{input}; + try { + if (isVoid) { + tf.invoke(argArray); + } else { + result = (String) tf.invoke(input); + } + } catch (Throwable t) { + assertTrue(mustCatch); + assertEquals(msg, t.getMessage()); + return; + } + assertFalse(mustCatch); + if (isVoid) { + assertEquals(msg, argArray[0]); + } else { + assertEquals(msg, result); + } + } + + @Test + public void testAsInterfaceInstance() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testAsInterfaceInstance0); + } + + public void testAsInterfaceInstance0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("asInterfaceInstance"); + Lookup lookup = MethodHandles.lookup(); + // test typical case: Runnable.run + { + countTest(); + if (verbosity >= 2) System.out.println("Runnable"); + MethodType mt = MethodType.methodType(void.class); + MethodHandle mh = lookup.findStatic(MethodHandlesGeneralTest.class, "runForRunnable", mt); + Runnable proxy = MethodHandleProxies.asInterfaceInstance(Runnable.class, mh); + proxy.run(); + assertCalled("runForRunnable"); + } + // well known single-name overloaded interface: Appendable.append + { + countTest(); + if (verbosity >= 2) System.out.println("Appendable"); + ArrayList> appendResults = new ArrayList<>(); + MethodHandle append = lookup.bind(appendResults, "add", MethodType.methodType(boolean.class, Object.class)); + append = append.asType(MethodType.methodType(void.class, List.class)); // specialize the type + MethodHandle asList = lookup.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class)); + MethodHandle mh = MethodHandles.filterReturnValue(asList, append).asVarargsCollector(Object[].class); + Appendable proxy = MethodHandleProxies.asInterfaceInstance(Appendable.class, mh); + proxy.append("one"); + proxy.append("two", 3, 4); + proxy.append('5'); + assertEquals(Arrays.asList(Arrays.asList("one"), + Arrays.asList("two", 3, 4), + Arrays.asList('5')), + appendResults); + if (verbosity >= 3) System.out.println("appendResults="+appendResults); + appendResults.clear(); + Formatter formatter = new Formatter(proxy); + String fmt = "foo str=%s char='%c' num=%d"; + Object[] fmtArgs = { "str!", 'C', 42 }; + String expect = String.format(fmt, fmtArgs); + formatter.format(fmt, fmtArgs); + String actual = ""; + if (verbosity >= 3) System.out.println("appendResults="+appendResults); + for (List l : appendResults) { + Object x = l.get(0); + switch (l.size()) { + case 1: actual += x; continue; + case 3: actual += ((String)x).substring((int)(Object)l.get(1), (int)(Object)l.get(2)); continue; + } + actual += l; + } + if (verbosity >= 3) System.out.println("expect="+expect); + if (verbosity >= 3) System.out.println("actual="+actual); + assertEquals(expect, actual); + } + // test case of an single name which is overloaded: Fooable.foo(...) + { + if (verbosity >= 2) System.out.println("Fooable"); + MethodHandle mh = lookup.findStatic(MethodHandlesGeneralTest.class, "fooForFooable", + MethodType.methodType(Object.class, String.class, Object[].class)); + Fooable proxy = MethodHandleProxies.asInterfaceInstance(Fooable.class, mh); + for (Method m : Fooable.class.getDeclaredMethods()) { + countTest(); + assertSame("foo", m.getName()); + if (verbosity > 3) + System.out.println("calling "+m); + MethodHandle invoker = lookup.unreflect(m); + MethodType mt = invoker.type(); + Class[] types = mt.parameterArray(); + types[0] = int.class; // placeholder + Object[] args = randomArgs(types); + args[0] = proxy; + if (verbosity > 3) + System.out.println("calling "+m+" on "+Arrays.asList(args)); + Object result = invoker.invokeWithArguments(args); + if (verbosity > 4) + System.out.println("result = "+result); + String name = "fooForFooable/"+args[1]; + Object[] argTail = Arrays.copyOfRange(args, 2, args.length); + assertCalled(name, argTail); + assertEquals(result, logEntry(name, argTail)); + } + } + // test processing of thrown exceptions: + for (Throwable ex : new Throwable[] { new NullPointerException("ok"), + new InternalError("ok"), + new Throwable("fail"), + new Exception("fail"), + new MyCheckedException() + }) { + MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class); + mh = MethodHandles.insertArguments(mh, 0, ex); + WillThrow proxy = MethodHandleProxies.asInterfaceInstance(WillThrow.class, mh); + try { + countTest(); + proxy.willThrow(); + System.out.println("Failed to throw: "+ex); + assertTrue(false); + } catch (Throwable ex1) { + if (verbosity > 3) { + System.out.println("throw "+ex); + System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1)); + } + if (ex instanceof RuntimeException || + ex instanceof Error) { + assertSame("must pass unchecked exception out without wrapping", ex, ex1); + } else if (ex instanceof MyCheckedException) { + assertSame("must pass declared exception out without wrapping", ex, ex1); + } else { + assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1); + if (!(ex1 instanceof UndeclaredThrowableException) || ex1.getCause() != ex) { + ex1.printStackTrace(System.out); + } + assertSame(ex, ex1.getCause()); + UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1; + } + } + } + // Test error checking on bad interfaces: + for (Class nonSMI : new Class[] { Object.class, + String.class, + CharSequence.class, + java.io.Serializable.class, + PrivateRunnable.class, + Example.class }) { + if (verbosity > 2) System.out.println(nonSMI.getName()); + try { + countTest(false); + MethodHandleProxies.asInterfaceInstance(nonSMI, varargsArray(0)); + assertTrue("Failed to throw on "+nonSMI.getName(), false); + } catch (IllegalArgumentException ex) { + if (verbosity > 2) System.out.println(nonSMI.getSimpleName()+": "+ex); + // Object: java.lang.IllegalArgumentException: + // not a public interface: java.lang.Object + // String: java.lang.IllegalArgumentException: + // not a public interface: java.lang.String + // CharSequence: java.lang.IllegalArgumentException: + // not a single-method interface: java.lang.CharSequence + // Serializable: java.lang.IllegalArgumentException: + // not a single-method interface: java.io.Serializable + // PrivateRunnable: java.lang.IllegalArgumentException: + // not a public interface: test.java.lang.invoke.MethodHandlesTest$PrivateRunnable + // Example: java.lang.IllegalArgumentException: + // not a public interface: test.java.lang.invoke.MethodHandlesTest$Example + } + } + // Test error checking on interfaces with the wrong method type: + for (Class intfc : new Class[] { Runnable.class /*arity 0*/, + Fooable.class /*arity 1 & 2*/ }) { + int badArity = 1; // known to be incompatible + if (verbosity > 2) System.out.println(intfc.getName()); + try { + countTest(false); + MethodHandleProxies.asInterfaceInstance(intfc, varargsArray(badArity)); + assertTrue("Failed to throw on "+intfc.getName(), false); + } catch (WrongMethodTypeException ex) { + if (verbosity > 2) System.out.println(intfc.getSimpleName()+": "+ex); + // Runnable: java.lang.invoke.WrongMethodTypeException: + // cannot convert MethodHandle(Object)Object[] to ()void + // Fooable: java.lang.invoke.WrongMethodTypeException: + // cannot convert MethodHandle(Object)Object[] to (Object,String)Object + } + } + } + + @Test + public void testInterfaceCast() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testInterfaceCast0); + } + + public void testInterfaceCast0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("interfaceCast"); + assert( (((Object)"foo") instanceof CharSequence)); + assert(!(((Object)"foo") instanceof Iterable)); + for (MethodHandle mh : new MethodHandle[]{ + MethodHandles.identity(String.class), + MethodHandles.identity(CharSequence.class), + MethodHandles.identity(Iterable.class) + }) { + if (verbosity > 0) System.out.println("-- mh = "+mh); + for (Class ctype : new Class[]{ + Object.class, String.class, CharSequence.class, + Number.class, Iterable.class + }) { + if (verbosity > 0) System.out.println("---- ctype = "+ctype.getName()); + // doret docast + testInterfaceCast(mh, ctype, false, false); + testInterfaceCast(mh, ctype, true, false); + testInterfaceCast(mh, ctype, false, true); + testInterfaceCast(mh, ctype, true, true); + } + } + } + + private static Class i2o(Class c) { + return (c.isInterface() ? Object.class : c); + } + + public void testInterfaceCast(MethodHandle mh, Class ctype, + boolean doret, boolean docast) throws Throwable { + MethodHandle mh0 = mh; + if (verbosity > 1) + System.out.println("mh="+mh+", ctype="+ctype.getName()+", doret="+doret+", docast="+docast); + String normalRetVal = "normal return value"; + MethodType mt = mh.type(); + MethodType mt0 = mt; + if (doret) mt = mt.changeReturnType(ctype); + else mt = mt.changeParameterType(0, ctype); + if (docast) mh = MethodHandles.explicitCastArguments(mh, mt); + else mh = mh.asType(mt); + assertEquals(mt, mh.type()); + MethodType mt1 = mt; + // this bit is needed to make the interface types disappear for invokeWithArguments: + mh = MethodHandles.explicitCastArguments(mh, mt.generic()); + Class[] step = { + mt1.parameterType(0), // param as passed to mh at first + mt0.parameterType(0), // param after incoming cast + mt0.returnType(), // return value before cast + mt1.returnType(), // return value after outgoing cast + }; + // where might a checkCast occur? + boolean[] checkCast = new boolean[step.length]; + // the string value must pass each step without causing an exception + if (!docast) { + if (!doret) { + if (step[0] != step[1]) + checkCast[1] = true; // incoming value is cast + } else { + if (step[2] != step[3]) + checkCast[3] = true; // outgoing value is cast + } + } + boolean expectFail = false; + for (int i = 0; i < step.length; i++) { + Class c = step[i]; + if (!checkCast[i]) c = i2o(c); + if (!c.isInstance(normalRetVal)) { + if (verbosity > 3) + System.out.println("expect failure at step "+i+" in "+Arrays.toString(step)+Arrays.toString(checkCast)); + expectFail = true; + break; + } + } + countTest(!expectFail); + if (verbosity > 2) + System.out.println("expectFail="+expectFail+", mt="+mt); + Object res; + try { + res = mh.invokeWithArguments(normalRetVal); + } catch (Exception ex) { + res = ex; + } + boolean sawFail = !(res instanceof String); + if (sawFail != expectFail) { + System.out.println("*** testInterfaceCast: mh0 = "+mh0); + System.out.println(" retype using "+(docast ? "explicitCastArguments" : "asType")+" to "+mt+" => "+mh); + System.out.println(" call returned "+res); + System.out.println(" expected "+(expectFail ? "an exception" : normalRetVal)); + } + if (!expectFail) { + assertFalse(res.toString(), sawFail); + assertEquals(normalRetVal, res); + } else { + assertTrue(res.toString(), sawFail); + } + } + + static Example userMethod(Object o, String s, int i) { + called("userMethod", o, s, i); + return null; + } + + @Test + public void testUserClassInSignature() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testUserClassInSignature0); + } + + public void testUserClassInSignature0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("testUserClassInSignature"); + Lookup lookup = MethodHandles.lookup(); + String name; MethodType mt; MethodHandle mh; + Object[] args; + + // Try a static method. + name = "userMethod"; + mt = MethodType.methodType(Example.class, Object.class, String.class, int.class); + mh = lookup.findStatic(lookup.lookupClass(), name, mt); + assertEquals(mt, mh.type()); + assertEquals(Example.class, mh.type().returnType()); + args = randomArgs(mh.type().parameterArray()); + mh.invokeWithArguments(args); + assertCalled(name, args); + + // Try a virtual method. + name = "v2"; + mt = MethodType.methodType(Object.class, Object.class, int.class); + mh = lookup.findVirtual(Example.class, name, mt); + assertEquals(mt, mh.type().dropParameterTypes(0,1)); + assertTrue(mh.type().parameterList().contains(Example.class)); + args = randomArgs(mh.type().parameterArray()); + mh.invokeWithArguments(args); + assertCalled(name, args); + } + + static void runForRunnable() { + called("runForRunnable"); + } + + public interface Fooable { + // overloads: + Object foo(Object x, String y); + List foo(String x, int y); + Object foo(String x); + } + + static Object fooForFooable(String x, Object... y) { + return called("fooForFooable/"+x, y); + } + + @SuppressWarnings("serial") // not really a public API, just a test case + public static class MyCheckedException extends Exception { + } + + public interface WillThrow { + void willThrow() throws MyCheckedException; + } + + /*non-public*/ interface PrivateRunnable { + public void run(); + } + + @Test + public void testRunnableProxy() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testRunnableProxy0); + } + + public void testRunnableProxy0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("testRunnableProxy"); + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodHandle run = lookup.findStatic(lookup.lookupClass(), "runForRunnable", MethodType.methodType(void.class)); + Runnable r = MethodHandleProxies.asInterfaceInstance(Runnable.class, run); + testRunnableProxy(r); + assertCalled("runForRunnable"); + } + + private static void testRunnableProxy(Runnable r) { + //7058630: JSR 292 method handle proxy violates contract for Object methods + r.run(); + Object o = r; + r = null; + boolean eq = (o == o); + int hc = System.identityHashCode(o); + String st = o.getClass().getName() + "@" + Integer.toHexString(hc); + Object expect = Arrays.asList(st, eq, hc); + if (verbosity >= 2) System.out.println("expect st/eq/hc = "+expect); + Object actual = Arrays.asList(o.toString(), o.equals(o), o.hashCode()); + if (verbosity >= 2) System.out.println("actual st/eq/hc = "+actual); + assertEquals(expect, actual); + } +} diff --git a/test/jdk/java/lang/invoke/MethodHandlesInsertArgumentsTest.java b/test/jdk/java/lang/invoke/MethodHandlesInsertArgumentsTest.java new file mode 100644 index 00000000000..a40876c6206 --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandlesInsertArgumentsTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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 + * @summary unit tests for java.lang.invoke.MethodHandles + * @library /lib/testlibrary /java/lang/invoke/common + * @compile MethodHandlesTest.java MethodHandlesInsertArgumentsTest.java remote/RemoteExample.java + * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions + * -XX:-VerifyDependencies + * -esa + * test.java.lang.invoke.MethodHandlesInsertArgumentsTest + */ + +package test.java.lang.invoke; + +import org.junit.*; +import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.*; + +public class MethodHandlesInsertArgumentsTest extends MethodHandlesTest { + + @Test // SLOW + public void testInsertArguments() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testInsertArguments0); + } + + public void testInsertArguments0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("insertArguments"); + for (int nargs = 0; nargs < 50; nargs++) { + if (CAN_TEST_LIGHTLY && nargs > 11) break; + for (int ins = 0; ins <= nargs; ins++) { + if (nargs > 10 && ins > 4 && ins < nargs-4 && ins % 10 != 3) + continue; + for (int pos = 0; pos <= nargs; pos++) { + if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) + continue; + if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; + testInsertArguments(nargs, pos, ins); + } + } + } + } + + void testInsertArguments(int nargs, int pos, int ins) throws Throwable { + countTest(); + MethodHandle target = varargsArray(nargs + ins); + Object[] args = randomArgs(target.type().parameterArray()); + List resList = Arrays.asList(args); + List argsToPass = new ArrayList<>(resList); + List argsToInsert = argsToPass.subList(pos, pos + ins); + if (verbosity >= 3) + System.out.println("insert: "+argsToInsert+" @"+pos+" into "+target); + @SuppressWarnings("cast") // cast to spread Object... is helpful + MethodHandle target2 = MethodHandles.insertArguments(target, pos, + (Object[]/*...*/) argsToInsert.toArray()); + argsToInsert.clear(); // remove from argsToInsert + Object res2 = target2.invokeWithArguments(argsToPass); + Object res2List = Arrays.asList((Object[])res2); + if (verbosity >= 3) + System.out.println("result: "+res2List); + assertEquals(resList, res2List); + } +} diff --git a/test/jdk/java/lang/invoke/MethodHandlesInvokersTest.java b/test/jdk/java/lang/invoke/MethodHandlesInvokersTest.java new file mode 100644 index 00000000000..589881a2b9f --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandlesInvokersTest.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2018, 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 + * @summary unit tests for java.lang.invoke.MethodHandles + * @library /lib/testlibrary /java/lang/invoke/common + * @compile MethodHandlesTest.java MethodHandlesInvokersTest.java remote/RemoteExample.java + * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions + * -XX:-VerifyDependencies + * -esa + * test.java.lang.invoke.MethodHandlesInvokersTest + */ + +package test.java.lang.invoke; + +import org.junit.*; +import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.junit.Assert.*; + +public class MethodHandlesInvokersTest extends MethodHandlesTest { + + @Test // SLOW + public void testInvokers() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testInvokers0); + } + + public void testInvokers0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker"); + // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker + Set done = new HashSet<>(); + for (int i = 0; i <= 6; i++) { + if (CAN_TEST_LIGHTLY && i > 3) break; + MethodType gtype = MethodType.genericMethodType(i); + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + for (int j = -1; j < i; j++) { + MethodType type = gtype; + if (j < 0) + type = type.changeReturnType(argType); + else if (argType == void.class) + continue; + else + type = type.changeParameterType(j, argType); + if (done.add(type)) + testInvokersWithCatch(type); + MethodType vtype = type.changeReturnType(void.class); + if (done.add(vtype)) + testInvokersWithCatch(vtype); + } + } + } + } + + public void testInvokersWithCatch(MethodType type) throws Throwable { + try { + testInvokers(type); + } catch (Throwable ex) { + System.out.println("*** testInvokers on "+type+" => "); + ex.printStackTrace(System.out); + } + } + + public void testInvokers(MethodType type) throws Throwable { + if (verbosity >= 3) + System.out.println("test invokers for "+type); + int nargs = type.parameterCount(); + boolean testRetCode = type.returnType() != void.class; + MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee", + MethodType.genericMethodType(0, true)); + assertTrue(target.isVarargsCollector()); + target = target.asType(type); + Object[] args = randomArgs(type.parameterArray()); + List targetPlusArgs = new ArrayList<>(Arrays.asList(args)); + targetPlusArgs.add(0, target); + int code = (Integer) invokee(args); + Object log = logEntry("invokee", args); + assertEquals(log.hashCode(), code); + assertCalled("invokee", args); + MethodHandle inv; + Object result; + // exact invoker + countTest(); + calledLog.clear(); + inv = MethodHandles.exactInvoker(type); + result = inv.invokeWithArguments(targetPlusArgs); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + // generic invoker + countTest(); + inv = MethodHandles.invoker(type); + if (nargs <= 3 && type == type.generic()) { + calledLog.clear(); + switch (nargs) { + case 0: + result = inv.invokeExact(target); + break; + case 1: + result = inv.invokeExact(target, args[0]); + break; + case 2: + result = inv.invokeExact(target, args[0], args[1]); + break; + case 3: + result = inv.invokeExact(target, args[0], args[1], args[2]); + break; + } + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + calledLog.clear(); + result = inv.invokeWithArguments(targetPlusArgs); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + // varargs invoker #0 + calledLog.clear(); + inv = MethodHandles.spreadInvoker(type, 0); + if (type.returnType() == Object.class) { + result = inv.invokeExact(target, args); + } else if (type.returnType() == void.class) { + result = null; inv.invokeExact(target, args); + } else { + result = inv.invokeWithArguments(target, (Object) args); + } + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + if (nargs >= 1 && type == type.generic()) { + // varargs invoker #1 + calledLog.clear(); + inv = MethodHandles.spreadInvoker(type, 1); + result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs)); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + if (nargs >= 2 && type == type.generic()) { + // varargs invoker #2 + calledLog.clear(); + inv = MethodHandles.spreadInvoker(type, 2); + result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + if (nargs >= 3 && type == type.generic()) { + // varargs invoker #3 + calledLog.clear(); + inv = MethodHandles.spreadInvoker(type, 3); + result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + for (int k = 0; k <= nargs; k++) { + // varargs invoker #0..N + if (CAN_TEST_LIGHTLY && (k > 1 || k < nargs - 1)) continue; + countTest(); + calledLog.clear(); + inv = MethodHandles.spreadInvoker(type, k); + MethodType expType = (type.dropParameterTypes(k, nargs) + .appendParameterTypes(Object[].class) + .insertParameterTypes(0, MethodHandle.class)); + assertEquals(expType, inv.type()); + List targetPlusVarArgs = new ArrayList<>(targetPlusArgs); + List tailList = targetPlusVarArgs.subList(1+k, 1+nargs); + Object[] tail = tailList.toArray(); + tailList.clear(); tailList.add(tail); + result = inv.invokeWithArguments(targetPlusVarArgs); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + + // dynamic invoker + countTest(); + CallSite site = new MutableCallSite(type); + inv = site.dynamicInvoker(); + + // see if we get the result of the original target: + try { + result = inv.invokeWithArguments(args); + assertTrue("should not reach here", false); + } catch (IllegalStateException ex) { + String msg = ex.getMessage(); + assertTrue(msg, msg.contains("site")); + } + + // set new target after invoker is created, to make sure we track target + site.setTarget(target); + calledLog.clear(); + result = inv.invokeWithArguments(args); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } +} diff --git a/test/jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java b/test/jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java new file mode 100644 index 00000000000..912a2b9256c --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2018, 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 + * @summary unit tests for java.lang.invoke.MethodHandles + * @library /lib/testlibrary /java/lang/invoke/common + * @compile MethodHandlesTest.java MethodHandlesPermuteArgumentsTest.java remote/RemoteExample.java + * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions + * -XX:-VerifyDependencies + * -esa + * test.java.lang.invoke.MethodHandlesPermuteArgumentsTest + */ + + +package test.java.lang.invoke; + +import org.junit.*; +import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class MethodHandlesPermuteArgumentsTest extends MethodHandlesTest { + + @Test // SLOW + public void testPermuteArguments() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testPermuteArguments0); + } + + public void testPermuteArguments0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("permuteArguments"); + testPermuteArguments(4, Integer.class, 2, long.class, 6); + if (CAN_TEST_LIGHTLY) return; + testPermuteArguments(4, Integer.class, 2, String.class, 0); + testPermuteArguments(6, Integer.class, 0, null, 30); + } + + public void testPermuteArguments(int max, Class type1, int t2c, Class type2, int dilution) throws Throwable { + if (verbosity >= 2) + System.out.println("permuteArguments "+max+"*"+type1.getName() + +(t2c==0?"":"/"+t2c+"*"+type2.getName()) + +(dilution > 0 ? " with dilution "+dilution : "")); + int t2pos = t2c == 0 ? 0 : 1; + for (int inargs = t2pos+1; inargs <= max; inargs++) { + Class[] types = new Class[inargs]; + Arrays.fill(types, type1); + if (t2c != 0) { + // Fill in a middle range with type2: + Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2); + } + Object[] args = randomArgs(types); + int numcases = 1; + for (int outargs = 0; outargs <= max; outargs++) { + if (outargs - inargs >= MAX_ARG_INCREASE) continue; + int casStep = dilution + 1; + // Avoid some common factors: + while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) || + (casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0)) + casStep++; + testPermuteArguments(args, types, outargs, numcases, casStep); + numcases *= inargs; + if (CAN_TEST_LIGHTLY && outargs < max-2) continue; + if (dilution > 10 && outargs >= 4) { + if (CAN_TEST_LIGHTLY) continue; + int[] reorder = new int[outargs]; + // Do some special patterns, which we probably missed. + // Replication of a single argument or argument pair. + for (int i = 0; i < inargs; i++) { + Arrays.fill(reorder, i); + testPermuteArguments(args, types, reorder); + for (int d = 1; d <= 2; d++) { + if (i + d >= inargs) continue; + for (int j = 1; j < outargs; j += 2) + reorder[j] += 1; + testPermuteArguments(args, types, reorder); + testPermuteArguments(args, types, reverse(reorder)); + } + } + // Repetition of a sequence of 3 or more arguments. + for (int i = 1; i < inargs; i++) { + for (int len = 3; len <= inargs; len++) { + for (int j = 0; j < outargs; j++) + reorder[j] = (i + (j % len)) % inargs; + testPermuteArguments(args, types, reorder); + testPermuteArguments(args, types, reverse(reorder)); + } + } + } + } + } + } + + public void testPermuteArguments(Object[] args, Class[] types, + int outargs, int numcases, int casStep) throws Throwable { + int inargs = args.length; + int[] reorder = new int[outargs]; + for (int cas = 0; cas < numcases; cas += casStep) { + for (int i = 0, c = cas; i < outargs; i++) { + reorder[i] = c % inargs; + c /= inargs; + } + if (CAN_TEST_LIGHTLY && outargs >= 3 && + (reorder[0] == reorder[1] || reorder[1] == reorder[2])) + continue; + testPermuteArguments(args, types, reorder); + } + } + + static int[] reverse(int[] reorder) { + reorder = reorder.clone(); + for (int i = 0, imax = reorder.length / 2; i < imax; i++) { + int j = reorder.length - 1 - i; + int tem = reorder[i]; + reorder[i] = reorder[j]; + reorder[j] = tem; + } + return reorder; + } + + void testPermuteArguments(Object[] args, Class[] types, int[] reorder) throws Throwable { + countTest(); + if (args == null && types == null) { + int max = 0; + for (int j : reorder) { + if (max < j) max = j; + } + args = randomArgs(max+1, Integer.class); + } + if (args == null) { + args = randomArgs(types); + } + if (types == null) { + types = new Class[args.length]; + for (int i = 0; i < args.length; i++) + types[i] = args[i].getClass(); + } + int inargs = args.length, outargs = reorder.length; + assertTrue(inargs == types.length); + if (verbosity >= 3) + System.out.println("permuteArguments "+Arrays.toString(reorder)); + Object[] permArgs = new Object[outargs]; + Class[] permTypes = new Class[outargs]; + for (int i = 0; i < outargs; i++) { + permArgs[i] = args[reorder[i]]; + permTypes[i] = types[reorder[i]]; + } + if (verbosity >= 4) { + System.out.println("in args: "+Arrays.asList(args)); + System.out.println("out args: "+Arrays.asList(permArgs)); + System.out.println("in types: "+Arrays.asList(types)); + System.out.println("out types: "+Arrays.asList(permTypes)); + } + MethodType inType = MethodType.methodType(Object.class, types); + MethodType outType = MethodType.methodType(Object.class, permTypes); + MethodHandle target = varargsList(outargs).asType(outType); + MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder); + if (verbosity >= 5) System.out.println("newTarget = "+newTarget); + Object result = newTarget.invokeWithArguments(args); + Object expected = Arrays.asList(permArgs); + if (!expected.equals(result)) { + System.out.println("*** failed permuteArguments "+Arrays.toString(reorder)+ + " types="+Arrays.asList(types)); + System.out.println("in args: "+Arrays.asList(args)); + System.out.println("out args: "+expected); + System.out.println("bad args: "+result); + } + assertEquals(expected, result); + } +} diff --git a/test/jdk/java/lang/invoke/MethodHandlesSpreadArgumentsTest.java b/test/jdk/java/lang/invoke/MethodHandlesSpreadArgumentsTest.java new file mode 100644 index 00000000000..b0b6f4a3d3e --- /dev/null +++ b/test/jdk/java/lang/invoke/MethodHandlesSpreadArgumentsTest.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2018, 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 + * @summary unit tests for java.lang.invoke.MethodHandles + * @library /lib/testlibrary /java/lang/invoke/common + * @compile MethodHandlesTest.java MethodHandlesSpreadArgumentsTest.java remote/RemoteExample.java + * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions + * -XX:-VerifyDependencies + * -esa + * test.java.lang.invoke.MethodHandlesSpreadArgumentsTest + */ + +package test.java.lang.invoke; + +import org.junit.*; +import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.*; + +public class MethodHandlesSpreadArgumentsTest extends MethodHandlesTest { + + @Test // SLOW + public void testSpreadArguments() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::testSpreadArguments0); + CodeCacheOverflowProcessor.runMHTest(this::testSpreadArguments1); + } + + public void testSpreadArguments0() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("spreadArguments"); + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + if (verbosity >= 3) + System.out.println("spreadArguments "+argType); + Class arrayType = java.lang.reflect.Array.newInstance(argType, 0).getClass(); + for (int nargs = 0; nargs < 50; nargs++) { + if (CAN_TEST_LIGHTLY && nargs > 11) break; + for (int pos = 0; pos <= nargs; pos++) { + if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; + if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) + continue; + testSpreadArguments(argType, arrayType, pos, nargs); + } + } + } + } + + public void testSpreadArguments(Class argType, Class arrayType, int pos, int nargs) throws Throwable { + countTest(); + MethodHandle target2 = varargsArray(arrayType, nargs); + MethodHandle target = target2.asType(target2.type().generic()); + if (verbosity >= 3) + System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); + Object[] args = randomArgs(target2.type().parameterArray()); + // make sure the target does what we think it does: + checkTarget(argType, pos, nargs, target, args); + List> newParams = new ArrayList<>(target2.type().parameterList()); + { // modify newParams in place + List> spreadParams = newParams.subList(pos, nargs); + spreadParams.clear(); spreadParams.add(arrayType); + } + MethodType newType = MethodType.methodType(arrayType, newParams); + MethodHandle result = target2.asSpreader(arrayType, nargs-pos); + assert(result.type() == newType) : Arrays.asList(result, newType); + result = result.asType(newType.generic()); + Object returnValue; + if (pos == 0) { + Object args2 = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length)); + returnValue = result.invokeExact(args2); + } else { + Object[] args1 = Arrays.copyOfRange(args, 0, pos+1); + args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length)); + returnValue = result.invokeWithArguments(args1); + } + checkReturnValue(argType, args, result, returnValue); + } + + public void testSpreadArguments1() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("spreadArguments/pos"); + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + if (verbosity >= 3) + System.out.println("spreadArguments "+argType); + Class arrayType = java.lang.reflect.Array.newInstance(argType, 0).getClass(); + for (int nargs = 0; nargs < 50; nargs++) { + if (CAN_TEST_LIGHTLY && nargs > 11) break; + for (int pos = 0; pos <= nargs; pos++) { + if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; + if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) + continue; + for (int spr = 1; spr < nargs - pos; ++spr) { + if (spr > 4 && spr != 7 && spr != 11 && spr != 20 && spr < nargs - pos - 4) continue; + testSpreadArguments(argType, arrayType, pos, spr, nargs); + } + } + } + } + } + + public void testSpreadArguments(Class argType, Class arrayType, + int pos, int spread, int nargs) throws Throwable { + countTest(); + MethodHandle target2 = varargsArray(arrayType, nargs); + MethodHandle target = target2.asType(target2.type().generic()); + if (verbosity >= 3) + System.out.println("spread into " + target2 + " [" + pos + ".." + (pos + spread) + "["); + Object[] args = randomArgs(target2.type().parameterArray()); + // make sure the target does what we think it does: + checkTarget(argType, pos, nargs, target, args); + List> newParams = new ArrayList<>(target2.type().parameterList()); + { // modify newParams in place + List> spreadParams = newParams.subList(pos, pos + spread); + spreadParams.clear(); + spreadParams.add(arrayType); + } + MethodType newType = MethodType.methodType(arrayType, newParams); + MethodHandle result = target2.asSpreader(pos, arrayType, spread); + assert (result.type() == newType) : Arrays.asList(result, newType); + result = result.asType(newType.generic()); + // args1 has nargs-spread entries, plus one for the to-be-spread array + int args1Length = nargs - (spread - 1); + Object[] args1 = new Object[args1Length]; + System.arraycopy(args, 0, args1, 0, pos); + args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, pos + spread)); + System.arraycopy(args, pos + spread, args1, pos + 1, nargs - spread - pos); + Object returnValue = result.invokeWithArguments(args1); + checkReturnValue(argType, args, result, returnValue); + } + + private static void checkTarget(Class argType, int pos, int nargs, + MethodHandle target, Object[] args) throws Throwable { + if (pos == 0 && nargs < 5 && !argType.isPrimitive()) { + Object[] check = (Object[]) target.invokeWithArguments(args); + assertArrayEquals(args, check); + switch (nargs) { + case 0: + check = (Object[]) (Object) target.invokeExact(); + assertArrayEquals(args, check); + break; + case 1: + check = (Object[]) (Object) target.invokeExact(args[0]); + assertArrayEquals(args, check); + break; + case 2: + check = (Object[]) (Object) target.invokeExact(args[0], args[1]); + assertArrayEquals(args, check); + break; + } + } + } + + private static void checkReturnValue(Class argType, Object[] args, MethodHandle result, Object returnValue) { + String argstr = Arrays.toString(args); + if (!argType.isPrimitive()) { + Object[] rv = (Object[]) returnValue; + String rvs = Arrays.toString(rv); + if (!Arrays.equals(args, rv)) { + System.out.println("method: "+result); + System.out.println("expected: "+argstr); + System.out.println("returned: "+rvs); + assertArrayEquals(args, rv); + } + } else if (argType == int.class) { + String rvs = Arrays.toString((int[]) returnValue); + if (!argstr.equals(rvs)) { + System.out.println("method: "+result); + System.out.println("expected: "+argstr); + System.out.println("returned: "+rvs); + assertEquals(argstr, rvs); + } + } else if (argType == long.class) { + String rvs = Arrays.toString((long[]) returnValue); + if (!argstr.equals(rvs)) { + System.out.println("method: "+result); + System.out.println("expected: "+argstr); + System.out.println("returned: "+rvs); + assertEquals(argstr, rvs); + } + } else { + // cannot test... + } + } + +} diff --git a/test/jdk/java/lang/invoke/MethodHandlesTest.java b/test/jdk/java/lang/invoke/MethodHandlesTest.java index cc3d30d39ed..314d2a27fee 100644 --- a/test/jdk/java/lang/invoke/MethodHandlesTest.java +++ b/test/jdk/java/lang/invoke/MethodHandlesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2018, 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 @@ -21,57 +21,36 @@ * questions. */ -/* @test - * @summary unit tests for java.lang.invoke.MethodHandles - * @library /lib/testlibrary /java/lang/invoke/common - * @compile MethodHandlesTest.java remote/RemoteExample.java - * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions - * -XX:-VerifyDependencies - * -esa - * test.java.lang.invoke.MethodHandlesTest - */ - package test.java.lang.invoke; import org.junit.*; -import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; import test.java.lang.invoke.remote.RemoteExample; -import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandleProxies; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; -import java.lang.invoke.MutableCallSite; -import java.lang.invoke.WrongMethodTypeException; import java.lang.reflect.Array; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.UndeclaredThrowableException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Formatter; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; -import static java.lang.invoke.MethodType.methodType; import static org.junit.Assert.*; /** * * @author jrose */ -public class MethodHandlesTest { +public abstract class MethodHandlesTest { + static final Class THIS_CLASS = MethodHandlesTest.class; // How much output? static int verbosity = 0; + static { String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".verbosity"); if (vstr == null) @@ -83,6 +62,7 @@ public class MethodHandlesTest { // a particular new, non-working test. Tests which are known to // work (or have recently worked) test this flag and return on true. static final boolean CAN_SKIP_WORKING; + static { String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".CAN_SKIP_WORKING"); if (vstr == null) @@ -94,21 +74,12 @@ public class MethodHandlesTest { // This might be useful with -Xcomp stress tests that compile all method handles. static boolean CAN_TEST_LIGHTLY = Boolean.getBoolean(THIS_CLASS.getName()+".CAN_TEST_LIGHTLY"); - @Test - public void testFirst() throws Throwable { - verbosity += 9; try { - // left blank for debugging - } finally { printCounts(); verbosity -= 9; } - } - static final int MAX_ARG_INCREASE = 3; - public MethodHandlesTest() { - } - String testName; static int allPosTests, allNegTests; int posTests, negTests; + @After public void printCounts() { if (verbosity >= 2 && (posTests | negTests) != 0) { @@ -120,11 +91,14 @@ public class MethodHandlesTest { posTests = negTests = 0; } } + void countTest(boolean positive) { if (positive) ++posTests; else ++negTests; } + void countTest() { countTest(true); } + void startTest(String name) { if (testName != null) printCounts(); if (verbosity >= 1) @@ -151,14 +125,17 @@ public class MethodHandlesTest { } static List calledLog = new ArrayList<>(); + static Object logEntry(String name, Object... args) { return Arrays.asList(name, Arrays.asList(args)); } + public static Object called(String name, Object... args) { Object entry = logEntry(name, args); calledLog.add(entry); return entry; } + static void assertCalled(String name, Object... args) { Object expected = logEntry(name, args); Object actual = calledLog.get(calledLog.size() - 1); @@ -170,10 +147,12 @@ public class MethodHandlesTest { System.out.println("act. types: "+getClasses(actual)); assertEquals("previous method call", expected, actual); } + static void printCalled(MethodHandle target, String name, Object... args) { if (verbosity >= 3) System.out.println("calling MH="+target+" to "+name+deepToString(args)); } + static String deepToString(Object x) { if (x == null) return "null"; if (x instanceof Collection) @@ -228,6 +207,7 @@ public class MethodHandlesTest { TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit; static long nextArgVal; + static long nextArg(boolean moreBits) { long val = nextArgVal++; long sign = -(val & 1); // alternate signs @@ -240,11 +220,13 @@ public class MethodHandlesTest { val += (val % ONE_MILLION) * TEN_BILLION; return val ^ sign; } + static int nextArg() { // Produce a 32-bit result something like ONE_MILLION+(smallint). // Example: 1_000_042. return (int) nextArg(false); } + static long nextArg(Class kind) { if (kind == long.class || kind == Long.class || kind == double.class || kind == Double.class) @@ -260,12 +242,12 @@ public class MethodHandlesTest { if (wrap != null) { return wrap; } -// import sun.invoke.util.Wrapper; -// Wrapper wrap = Wrapper.forBasicType(dst); -// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) -// wrap = Wrapper.forWrapperType(dst); -// if (wrap != Wrapper.OBJECT) -// return wrap.wrap(nextArg++); + //import sun.invoke.util.Wrapper; + //Wrapper wrap = Wrapper.forBasicType(dst); + //if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) + // wrap = Wrapper.forWrapperType(dst); + // if (wrap != Wrapper.OBJECT) + // return wrap.wrap(nextArg++); if (param.isInterface()) { for (Class c : param.getClasses()) { if (param.isAssignableFrom(c) && !c.isInterface()) @@ -289,18 +271,21 @@ public class MethodHandlesTest { } return null; // random class not Object, String, Integer, etc. } + static Object[] randomArgs(Class... params) { Object[] args = new Object[params.length]; for (int i = 0; i < args.length; i++) args[i] = randomArg(params[i]); return args; } + static Object[] randomArgs(int nargs, Class param) { Object[] args = new Object[nargs]; for (int i = 0; i < args.length; i++) args[i] = randomArg(param); return args; } + static Object[] randomArgs(List> params) { return randomArgs(params.toArray(new Class[params.size()])); } @@ -309,6 +294,7 @@ public class MethodHandlesTest { static T[] array(Class atype, E... a) { return Arrays.copyOf(a, a.length, atype); } + @SafeVarargs @SuppressWarnings("varargs") static T[] cat(T[] a, T... b) { int alen = a.length, blen = b.length; @@ -317,6 +303,7 @@ public class MethodHandlesTest { System.arraycopy(b, 0, c, alen, blen); return c; } + static Integer[] boxAll(int... vx) { Integer[] res = new Integer[vx.length]; for (int i = 0; i < res.length; i++) { @@ -324,6 +311,7 @@ public class MethodHandlesTest { } return res; } + static Object getClasses(Object x) { if (x == null) return x; if (x instanceof String) return x; // keep the name @@ -341,13 +329,16 @@ public class MethodHandlesTest { static MethodHandle varargsList(int arity) { return ValueConversions.varargsList(arity); } + /** Return lambda(arg...[arity]) { Arrays.asList(arg...) } */ static MethodHandle varargsArray(int arity) { return ValueConversions.varargsArray(arity); } + static MethodHandle varargsArray(Class arrayType, int arity) { return ValueConversions.varargsArray(arrayType, arity); } + /** Variation of varargsList, but with the given rtype. */ static MethodHandle varargsList(int arity, Class rtype) { MethodHandle list = varargsList(arity); @@ -374,11 +365,13 @@ public class MethodHandlesTest { } return list.asType(listType); } + /** Variation of varargsList, but with the given ptypes and rtype. */ static MethodHandle varargsList(List> ptypes, Class rtype) { MethodHandle list = varargsList(ptypes.size(), rtype); return list.asType(MethodType.methodType(rtype, ptypes)); } + private static MethodHandle LIST_TO_STRING, LIST_TO_INT; private static String listToString(List x) { return x.toString(); } private static int listToInt(List x) { return x.toString().hashCode(); } @@ -386,6 +379,7 @@ public class MethodHandlesTest { static MethodHandle changeArgTypes(MethodHandle target, Class argType) { return changeArgTypes(target, 0, 999, argType); } + static MethodHandle changeArgTypes(MethodHandle target, int beg, int end, Class argType) { MethodType targetType = target.type(); @@ -395,6 +389,7 @@ public class MethodHandlesTest { MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); return target.asType(ttype2); } + static MethodHandle addTrailingArgs(MethodHandle target, int nargs, Class argClass) { int targetLen = target.type().parameterCount(); int extra = (nargs - targetLen); @@ -456,6 +451,7 @@ public class MethodHandlesTest { static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial } + static final Lookup EXAMPLE = Example.EXAMPLE; public static class PubExample extends Example { public PubExample() { this("PubExample"); } @@ -463,6 +459,7 @@ public class MethodHandlesTest { protected void pro_v0() { called("Pub/pro_v0", this); } protected static void pro_s0() { called("Pub/pro_s0"); } } + static class SubExample extends Example { @Override public void v0() { called("Sub/v0", this); } @Override void pkg_v0() { called("Sub/pkg_v0", this); } @@ -470,6 +467,7 @@ public class MethodHandlesTest { private SubExample(int x) { called("", this, x); } public SubExample() { super("SubExample#"+nextArg()); } } + public static interface IntExample { public void v0(); public default void vd() { called("vd", this); } @@ -480,14 +478,15 @@ public class MethodHandlesTest { @Override public String toString() { return name; } } } + static interface SubIntExample extends IntExample { } static final Object[][][] ACCESS_CASES = { { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false - { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE - { { false, PUBLIC }, { false, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false - { { false, PUBLIC }, { true, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: subclass OK - { { true, PUBLIC }, { true, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[4]: all true + { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE + { { false, PUBLIC }, { false, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false + { { false, PUBLIC }, { true, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: subclass OK + { { true, PUBLIC }, { true, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[4]: all true }; static Object[][] accessCases(Class defc, String name, boolean isSpecial) { @@ -510,6 +509,7 @@ public class MethodHandlesTest { cases = Arrays.copyOfRange(cases, 0, cases.length-1); return cases; } + static Object[][] accessCases(Class defc, String name) { return accessCases(defc, name, false); } @@ -524,77 +524,6 @@ public class MethodHandlesTest { /** Is findVirtual (etc.) of "<init<" supposed to elicit a NoSuchMethodException? */ static final boolean INIT_REF_CAUSES_NSME = true; - @Test - public void testFindStatic() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindStatic0); - } - - public void testFindStatic0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("findStatic"); - testFindStatic(PubExample.class, void.class, "s0"); - testFindStatic(Example.class, void.class, "s0"); - testFindStatic(Example.class, void.class, "pkg_s0"); - testFindStatic(Example.class, void.class, "pri_s0"); - testFindStatic(Example.class, void.class, "pro_s0"); - testFindStatic(PubExample.class, void.class, "Pub/pro_s0"); - - testFindStatic(Example.class, Object.class, "s1", Object.class); - testFindStatic(Example.class, Object.class, "s2", int.class); - testFindStatic(Example.class, Object.class, "s3", long.class); - testFindStatic(Example.class, Object.class, "s4", int.class, int.class); - testFindStatic(Example.class, Object.class, "s5", long.class, int.class); - testFindStatic(Example.class, Object.class, "s6", int.class, long.class); - testFindStatic(Example.class, Object.class, "s7", float.class, double.class); - - testFindStatic(false, PRIVATE, Example.class, void.class, "bogus"); - testFindStatic(false, PRIVATE, Example.class, void.class, "", int.class); - testFindStatic(false, PRIVATE, Example.class, void.class, "", Void.class); - testFindStatic(false, PRIVATE, Example.class, void.class, "v0"); - } - - void testFindStatic(Class defc, Class ret, String name, Class... params) throws Throwable { - for (Object[] ac : accessCases(defc, name)) { - testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); - } - } - void testFindStatic(Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { - testFindStatic(true, lookup, defc, ret, name, params); - } - void testFindStatic(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { - countTest(positive); - String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo - MethodType type = MethodType.methodType(ret, params); - MethodHandle target = null; - Exception noAccess = null; - try { - if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - target = maybeMoveIn(lookup, defc).findStatic(defc, methodName, type); - } catch (ReflectiveOperationException ex) { - noAccess = ex; - assertExceptionClass( - (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("")) - ? NoSuchMethodException.class - : IllegalAccessException.class, - noAccess); - if (verbosity >= 5) ex.printStackTrace(System.out); - } - if (verbosity >= 3) - System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target - +(noAccess == null ? "" : " !! "+noAccess)); - if (positive && noAccess != null) throw noAccess; - assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); - if (!positive) return; // negative test failed as expected - assertEquals(type, target.type()); - assertNameStringContains(target, methodName); - Object[] args = randomArgs(params); - printCalled(target, name, args); - target.invokeWithArguments(args); - assertCalled(name, args); - if (verbosity >= 1) - System.out.print(':'); - } - static void assertExceptionClass(Class expected, Throwable actual) { if (expected.isInstance(actual)) return; @@ -615,454 +544,6 @@ public class MethodHandlesTest { assertEquals(s, x); } - @Test - public void testFindVirtual() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindVirtual0); - } - - public void testFindVirtual0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("findVirtual"); - testFindVirtual(Example.class, void.class, "v0"); - testFindVirtual(Example.class, void.class, "pkg_v0"); - testFindVirtual(Example.class, void.class, "pri_v0"); - testFindVirtual(Example.class, Object.class, "v1", Object.class); - testFindVirtual(Example.class, Object.class, "v2", Object.class, Object.class); - testFindVirtual(Example.class, Object.class, "v2", Object.class, int.class); - testFindVirtual(Example.class, Object.class, "v2", int.class, Object.class); - testFindVirtual(Example.class, Object.class, "v2", int.class, int.class); - testFindVirtual(Example.class, void.class, "pro_v0"); - testFindVirtual(PubExample.class, void.class, "Pub/pro_v0"); - - testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus"); - testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "", int.class); - testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "", Void.class); - testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "s0"); - - // test dispatch - testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/v0"); - testFindVirtual(SubExample.class, Example.class, void.class, "Sub/v0"); - testFindVirtual(SubExample.class, IntExample.class, void.class, "Sub/v0"); - testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/pkg_v0"); - testFindVirtual(SubExample.class, Example.class, void.class, "Sub/pkg_v0"); - testFindVirtual(Example.class, IntExample.class, void.class, "v0"); - testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0"); - } - - @Test - public void testFindVirtualClone() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindVirtualClone0); - } - - public void testFindVirtualClone0() throws Throwable { - if (CAN_SKIP_WORKING) return; - // test some ad hoc system methods - testFindVirtual(false, PUBLIC, Object.class, Object.class, "clone"); - - // ##### FIXME - disable tests for clone until we figure out how they should work with modules - - /* - testFindVirtual(true, PUBLIC, Object[].class, Object.class, "clone"); - testFindVirtual(true, PUBLIC, int[].class, Object.class, "clone"); - for (Class cls : new Class[]{ boolean[].class, long[].class, float[].class, char[].class }) - testFindVirtual(true, PUBLIC, cls, Object.class, "clone"); - */ - } - - void testFindVirtual(Class defc, Class ret, String name, Class... params) throws Throwable { - Class rcvc = defc; - testFindVirtual(rcvc, defc, ret, name, params); - } - void testFindVirtual(Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { - for (Object[] ac : accessCases(defc, name)) { - testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params); - } - } - void testFindVirtual(Lookup lookup, Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { - testFindVirtual(true, lookup, rcvc, defc, ret, name, params); - } - void testFindVirtual(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { - testFindVirtual(positive, lookup, defc, defc, ret, name, params); - } - void testFindVirtual(boolean positive, Lookup lookup, Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { - countTest(positive); - String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo - MethodType type = MethodType.methodType(ret, params); - MethodHandle target = null; - Exception noAccess = null; - try { - if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - target = maybeMoveIn(lookup, defc).findVirtual(defc, methodName, type); - } catch (ReflectiveOperationException ex) { - noAccess = ex; - assertExceptionClass( - (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("")) - ? NoSuchMethodException.class - : IllegalAccessException.class, - noAccess); - if (verbosity >= 5) ex.printStackTrace(System.out); - } - if (verbosity >= 3) - System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target - +(noAccess == null ? "" : " !! "+noAccess)); - if (positive && noAccess != null) throw noAccess; - assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); - if (!positive) return; // negative test failed as expected - Class selfc = defc; - // predict receiver type narrowing: - if (lookup == SUBCLASS && - name.contains("pro_") && - selfc.isAssignableFrom(lookup.lookupClass())) { - selfc = lookup.lookupClass(); - if (name.startsWith("Pub/")) name = "Rem/"+name.substring(4); - } - Class[] paramsWithSelf = cat(array(Class[].class, (Class)selfc), params); - MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); - assertEquals(typeWithSelf, target.type()); - assertNameStringContains(target, methodName); - Object[] argsWithSelf = randomArgs(paramsWithSelf); - if (selfc.isAssignableFrom(rcvc) && rcvc != selfc) argsWithSelf[0] = randomArg(rcvc); - printCalled(target, name, argsWithSelf); - Object res = target.invokeWithArguments(argsWithSelf); - if (Example.class.isAssignableFrom(defc) || IntExample.class.isAssignableFrom(defc)) { - assertCalled(name, argsWithSelf); - } else if (name.equals("clone")) { - // Ad hoc method call outside Example. For Object[].clone. - printCalled(target, name, argsWithSelf); - assertEquals(MethodType.methodType(Object.class, rcvc), target.type()); - Object orig = argsWithSelf[0]; - assertEquals(orig.getClass(), res.getClass()); - if (res instanceof Object[]) - assertArrayEquals((Object[])res, (Object[])argsWithSelf[0]); - assert(Arrays.deepEquals(new Object[]{res}, new Object[]{argsWithSelf[0]})); - } else { - assert(false) : Arrays.asList(positive, lookup, rcvc, defc, ret, name, deepToString(params)); - } - if (verbosity >= 1) - System.out.print(':'); - } - - @Test - public void testFindSpecial() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindSpecial0); - } - - public void testFindSpecial0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("findSpecial"); - testFindSpecial(SubExample.class, Example.class, void.class, false, "v0"); - testFindSpecial(SubExample.class, Example.class, void.class, false, "pkg_v0"); - testFindSpecial(RemoteExample.class, PubExample.class, void.class, false, "Pub/pro_v0"); - testFindSpecial(Example.class, IntExample.class, void.class, true, "vd"); - // Do some negative testing: - for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) { - testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0"); - testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus"); - testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "", int.class); - testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "", Void.class); - testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0"); - testFindSpecial(false, lookup, Example.class, IntExample.class, void.class, "v0"); - } - } - - void testFindSpecial(Class specialCaller, - Class defc, Class ret, boolean dflt, String name, Class... params) throws Throwable { - if (specialCaller == RemoteExample.class) { - testFindSpecial(false, EXAMPLE, specialCaller, defc, ret, name, params); - testFindSpecial(false, PRIVATE, specialCaller, defc, ret, name, params); - testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params); - testFindSpecial(true, SUBCLASS, specialCaller, defc, ret, name, params); - testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params); - return; - } - testFindSpecial(true, EXAMPLE, specialCaller, defc, ret, name, params); - testFindSpecial(true, PRIVATE, specialCaller, defc, ret, name, params); - testFindSpecial(false || dflt, PACKAGE, specialCaller, defc, ret, name, params); - testFindSpecial(false, SUBCLASS, specialCaller, defc, ret, name, params); - testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params); - } - void testFindSpecial(boolean positive, Lookup lookup, Class specialCaller, - Class defc, Class ret, String name, Class... params) throws Throwable { - countTest(positive); - String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo - MethodType type = MethodType.methodType(ret, params); - Lookup specialLookup = maybeMoveIn(lookup, specialCaller); - boolean specialAccessOK = (specialLookup.lookupClass() == specialCaller && - (specialLookup.lookupModes() & Lookup.PRIVATE) != 0); - MethodHandle target = null; - Exception noAccess = null; - try { - if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - if (verbosity >= 5) System.out.println(" lookup => "+specialLookup); - target = specialLookup.findSpecial(defc, methodName, type, specialCaller); - } catch (ReflectiveOperationException ex) { - noAccess = ex; - assertExceptionClass( - (!specialAccessOK) // this check should happen first - ? IllegalAccessException.class - : (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("")) - ? NoSuchMethodException.class - : IllegalAccessException.class, - noAccess); - if (verbosity >= 5) ex.printStackTrace(System.out); - } - if (verbosity >= 3) - System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target - +(target == null ? "" : target.type()) - +(noAccess == null ? "" : " !! "+noAccess)); - if (positive && noAccess != null) throw noAccess; - assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); - if (!positive) return; // negative test failed as expected - assertEquals(specialCaller, target.type().parameterType(0)); - assertEquals(type, target.type().dropParameterTypes(0,1)); - Class[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params); - MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); - assertNameStringContains(target, methodName); - Object[] args = randomArgs(paramsWithSelf); - printCalled(target, name, args); - target.invokeWithArguments(args); - assertCalled(name, args); - } - - @Test - public void testFindConstructor() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindConstructor0); - } - - public void testFindConstructor0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("findConstructor"); - testFindConstructor(true, EXAMPLE, Example.class); - testFindConstructor(true, EXAMPLE, Example.class, int.class); - testFindConstructor(true, EXAMPLE, Example.class, int.class, int.class); - testFindConstructor(true, EXAMPLE, Example.class, int.class, long.class); - testFindConstructor(true, EXAMPLE, Example.class, int.class, float.class); - testFindConstructor(true, EXAMPLE, Example.class, int.class, double.class); - testFindConstructor(true, EXAMPLE, Example.class, String.class); - testFindConstructor(true, EXAMPLE, Example.class, int.class, int.class, int.class); - testFindConstructor(true, EXAMPLE, Example.class, int.class, int.class, int.class, int.class); - } - void testFindConstructor(boolean positive, Lookup lookup, - Class defc, Class... params) throws Throwable { - countTest(positive); - MethodType type = MethodType.methodType(void.class, params); - MethodHandle target = null; - Exception noAccess = null; - try { - if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+type); - target = lookup.findConstructor(defc, type); - } catch (ReflectiveOperationException ex) { - noAccess = ex; - assertTrue(noAccess.getClass().getName(), noAccess instanceof IllegalAccessException); - } - if (verbosity >= 3) - System.out.println("findConstructor "+defc.getName()+"./"+type+" => "+target - +(target == null ? "" : target.type()) - +(noAccess == null ? "" : " !! "+noAccess)); - if (positive && noAccess != null) throw noAccess; - assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); - if (!positive) return; // negative test failed as expected - assertEquals(type.changeReturnType(defc), target.type()); - Object[] args = randomArgs(params); - printCalled(target, defc.getSimpleName(), args); - Object obj = target.invokeWithArguments(args); - if (!(defc == Example.class && params.length < 2)) - assertCalled(defc.getSimpleName()+".", args); - assertTrue("instance of "+defc.getName(), defc.isInstance(obj)); - } - - @Test - public void testBind() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testBind0); - } - - public void testBind0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("bind"); - testBind(Example.class, void.class, "v0"); - testBind(Example.class, void.class, "pkg_v0"); - testBind(Example.class, void.class, "pri_v0"); - testBind(Example.class, Object.class, "v1", Object.class); - testBind(Example.class, Object.class, "v2", Object.class, Object.class); - testBind(Example.class, Object.class, "v2", Object.class, int.class); - testBind(Example.class, Object.class, "v2", int.class, Object.class); - testBind(Example.class, Object.class, "v2", int.class, int.class); - testBind(false, PRIVATE, Example.class, void.class, "bogus"); - testBind(false, PRIVATE, Example.class, void.class, "", int.class); - testBind(false, PRIVATE, Example.class, void.class, "", Void.class); - testBind(SubExample.class, void.class, "Sub/v0"); - testBind(SubExample.class, void.class, "Sub/pkg_v0"); - testBind(IntExample.Impl.class, void.class, "Int/v0"); - } - - void testBind(Class defc, Class ret, String name, Class... params) throws Throwable { - for (Object[] ac : accessCases(defc, name)) { - testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); - } - } - - void testBind(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { - countTest(positive); - String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo - MethodType type = MethodType.methodType(ret, params); - Object receiver = randomArg(defc); - MethodHandle target = null; - Exception noAccess = null; - try { - if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - target = maybeMoveIn(lookup, defc).bind(receiver, methodName, type); - } catch (ReflectiveOperationException ex) { - noAccess = ex; - assertExceptionClass( - (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("")) - ? NoSuchMethodException.class - : IllegalAccessException.class, - noAccess); - if (verbosity >= 5) ex.printStackTrace(System.out); - } - if (verbosity >= 3) - System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target - +(noAccess == null ? "" : " !! "+noAccess)); - if (positive && noAccess != null) throw noAccess; - assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); - if (!positive) return; // negative test failed as expected - assertEquals(type, target.type()); - Object[] args = randomArgs(params); - printCalled(target, name, args); - target.invokeWithArguments(args); - Object[] argsWithReceiver = cat(array(Object[].class, receiver), args); - assertCalled(name, argsWithReceiver); - if (verbosity >= 1) - System.out.print(':'); - } - - @Test - public void testUnreflect() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testUnreflect0); - } - - public void testUnreflect0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("unreflect"); - testUnreflect(Example.class, true, void.class, "s0"); - testUnreflect(Example.class, true, void.class, "pro_s0"); - testUnreflect(Example.class, true, void.class, "pkg_s0"); - testUnreflect(Example.class, true, void.class, "pri_s0"); - - testUnreflect(Example.class, true, Object.class, "s1", Object.class); - testUnreflect(Example.class, true, Object.class, "s2", int.class); - testUnreflect(Example.class, true, Object.class, "s3", long.class); - testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); - testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); - testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); - - testUnreflect(Example.class, false, void.class, "v0"); - testUnreflect(Example.class, false, void.class, "pkg_v0"); - testUnreflect(Example.class, false, void.class, "pri_v0"); - testUnreflect(Example.class, false, Object.class, "v1", Object.class); - testUnreflect(Example.class, false, Object.class, "v2", Object.class, Object.class); - testUnreflect(Example.class, false, Object.class, "v2", Object.class, int.class); - testUnreflect(Example.class, false, Object.class, "v2", int.class, Object.class); - testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); - - // Test a public final member in another package: - testUnreflect(RemoteExample.class, false, void.class, "Rem/fin_v0"); - } - - void testUnreflect(Class defc, boolean isStatic, Class ret, String name, Class... params) throws Throwable { - for (Object[] ac : accessCases(defc, name)) { - testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params); - } - } - void testUnreflect(Class defc, Class rcvc, Class ret, String name, Class... params) throws Throwable { - for (Object[] ac : accessCases(defc, name)) { - testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); - } - } - void testUnreflectMaybeSpecial(Class specialCaller, - boolean positive, Lookup lookup, - Class defc, Class rcvc, Class ret, String name, Class... params) throws Throwable { - countTest(positive); - String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo - MethodType type = MethodType.methodType(ret, params); - Lookup specialLookup = (specialCaller != null ? maybeMoveIn(lookup, specialCaller) : null); - boolean specialAccessOK = (specialCaller != null && - specialLookup.lookupClass() == specialCaller && - (specialLookup.lookupModes() & Lookup.PRIVATE) != 0); - Method rmethod = defc.getDeclaredMethod(methodName, params); - MethodHandle target = null; - Exception noAccess = null; - boolean isStatic = (rcvc == null); - boolean isSpecial = (specialCaller != null); - try { - if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - if (isSpecial) - target = specialLookup.unreflectSpecial(rmethod, specialCaller); - else - target = maybeMoveIn(lookup, defc).unreflect(rmethod); - } catch (ReflectiveOperationException ex) { - noAccess = ex; - assertExceptionClass( - IllegalAccessException.class, // NSME is impossible, since it was already reflected - noAccess); - if (verbosity >= 5) ex.printStackTrace(System.out); - } - if (verbosity >= 3) - System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type - +(!isSpecial ? "" : " specialCaller="+specialCaller) - +( isStatic ? "" : " receiver="+rcvc) - +" => "+target - +(noAccess == null ? "" : " !! "+noAccess)); - if (positive && noAccess != null) throw noAccess; - assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); - if (!positive) return; // negative test failed as expected - assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); - Class[] paramsMaybeWithSelf = params; - if (!isStatic) { - paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params); - } - MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); - if (isStatic) { - assertEquals(typeMaybeWithSelf, target.type()); - } else { - if (isSpecial) - assertEquals(specialCaller, target.type().parameterType(0)); - else - assertEquals(defc, target.type().parameterType(0)); - assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc)); - } - Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); - printCalled(target, name, argsMaybeWithSelf); - target.invokeWithArguments(argsMaybeWithSelf); - assertCalled(name, argsMaybeWithSelf); - if (verbosity >= 1) - System.out.print(':'); - } - - void testUnreflectSpecial(Class defc, Class rcvc, Class ret, String name, Class... params) throws Throwable { - for (Object[] ac : accessCases(defc, name, true)) { - Class specialCaller = rcvc; - testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); - } - } - - @Test - public void testUnreflectSpecial() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testUnreflectSpecial0); - } - - public void testUnreflectSpecial0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("unreflectSpecial"); - testUnreflectSpecial(Example.class, Example.class, void.class, "v0"); - testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0"); - testUnreflectSpecial(Example.class, Example.class, void.class, "pkg_v0"); - testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0"); - testUnreflectSpecial(Example.class, Example.class, Object.class, "v2", int.class, int.class); - testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class); - testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0"); - } - public static class HasFields { boolean fZ = false; byte fB = (byte)'B'; @@ -1133,6 +614,7 @@ public class MethodHandlesTest { } static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC = 3, TEST_SETTER = 0x10, TEST_BOUND = 0x20, TEST_NPE = 0x40; + static boolean testModeMatches(int testMode, boolean isStatic) { switch (testMode) { case TEST_FIND_STATIC: return isStatic; @@ -1142,467 +624,6 @@ public class MethodHandlesTest { throw new InternalError("testMode="+testMode); } - @Test - public void testUnreflectGetter() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testUnreflectGetter0); - } - - public void testUnreflectGetter0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("unreflectGetter"); - testGetter(TEST_UNREFLECT); - } - - @Test - public void testFindGetter() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindGetter0); - } - - public void testFindGetter0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("findGetter"); - testGetter(TEST_FIND_FIELD); - testGetter(TEST_FIND_FIELD | TEST_BOUND); - } - - @Test - public void testFindStaticGetter() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindStaticGetter0); - } - - public void testFindStaticGetter0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("findStaticGetter"); - testGetter(TEST_FIND_STATIC); - } - - public void testGetter(int testMode) throws Throwable { - Lookup lookup = PRIVATE; // FIXME: test more lookups than this one - for (Object[] c : HasFields.CASES) { - boolean positive = (c[1] != Error.class); - testGetter(positive, lookup, c[0], c[1], testMode); - if (positive) - testGetter(positive, lookup, c[0], c[1], testMode | TEST_NPE); - } - testGetter(true, lookup, - new Object[]{ true, System.class, "out", java.io.PrintStream.class }, - System.out, testMode); - for (int isStaticN = 0; isStaticN <= 1; isStaticN++) { - testGetter(false, lookup, - new Object[]{ (isStaticN != 0), System.class, "bogus", char.class }, - null, testMode); - } - } - public void testGetter(boolean positive, MethodHandles.Lookup lookup, - Object fieldRef, Object value, int testMode) throws Throwable { - testAccessor(positive, lookup, fieldRef, value, testMode); - } - - public void testAccessor(boolean positive0, MethodHandles.Lookup lookup, - Object fieldRef, Object value, int testMode0) throws Throwable { - if (verbosity >= 4) - System.out.println("testAccessor"+Arrays.deepToString(new Object[]{positive0, lookup, fieldRef, value, testMode0})); - boolean isGetter = ((testMode0 & TEST_SETTER) == 0); - boolean doBound = ((testMode0 & TEST_BOUND) != 0); - boolean testNPE = ((testMode0 & TEST_NPE) != 0); - int testMode = testMode0 & ~(TEST_SETTER | TEST_BOUND | TEST_NPE); - boolean positive = positive0 && !testNPE; - boolean isStatic; - Class fclass; - String fname; - Class ftype; - Field f = (fieldRef instanceof Field ? (Field)fieldRef : null); - if (f != null) { - isStatic = Modifier.isStatic(f.getModifiers()); - fclass = f.getDeclaringClass(); - fname = f.getName(); - ftype = f.getType(); - } else { - Object[] scnt = (Object[]) fieldRef; - isStatic = (Boolean) scnt[0]; - fclass = (Class) scnt[1]; - fname = (String) scnt[2]; - ftype = (Class) scnt[3]; - try { - f = fclass.getDeclaredField(fname); - } catch (ReflectiveOperationException ex) { - f = null; - } - } - if (!testModeMatches(testMode, isStatic)) return; - if (f == null && testMode == TEST_UNREFLECT) return; - if (testNPE && isStatic) return; - countTest(positive); - MethodType expType; - if (isGetter) - expType = MethodType.methodType(ftype, HasFields.class); - else - expType = MethodType.methodType(void.class, HasFields.class, ftype); - if (isStatic) expType = expType.dropParameterTypes(0, 1); - Exception noAccess = null; - MethodHandle mh; - try { - switch (testMode0 & ~(TEST_BOUND | TEST_NPE)) { - case TEST_UNREFLECT: mh = lookup.unreflectGetter(f); break; - case TEST_FIND_FIELD: mh = lookup.findGetter(fclass, fname, ftype); break; - case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype); break; - case TEST_SETTER| - TEST_UNREFLECT: mh = lookup.unreflectSetter(f); break; - case TEST_SETTER| - TEST_FIND_FIELD: mh = lookup.findSetter(fclass, fname, ftype); break; - case TEST_SETTER| - TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype); break; - default: - throw new InternalError("testMode="+testMode); - } - } catch (ReflectiveOperationException ex) { - mh = null; - noAccess = ex; - assertExceptionClass( - (fname.contains("bogus")) - ? NoSuchFieldException.class - : IllegalAccessException.class, - noAccess); - if (verbosity >= 5) ex.printStackTrace(System.out); - } - if (verbosity >= 3) - System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype - +" => "+mh - +(noAccess == null ? "" : " !! "+noAccess)); - if (positive && !testNPE && noAccess != null) throw new RuntimeException(noAccess); - assertEquals(positive0 ? "positive test" : "negative test erroneously passed", positive0, mh != null); - if (!positive && !testNPE) return; // negative access test failed as expected - assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount()); - - - assertSame(mh.type(), expType); - //assertNameStringContains(mh, fname); // This does not hold anymore with LFs - HasFields fields = new HasFields(); - HasFields fieldsForMH = fields; - if (testNPE) fieldsForMH = null; // perturb MH argument to elicit expected error - if (doBound) - mh = mh.bindTo(fieldsForMH); - Object sawValue; - Class vtype = ftype; - if (ftype != int.class) vtype = Object.class; - if (isGetter) { - mh = mh.asType(mh.type().generic() - .changeReturnType(vtype)); - } else { - int last = mh.type().parameterCount() - 1; - mh = mh.asType(mh.type().generic() - .changeReturnType(void.class) - .changeParameterType(last, vtype)); - } - if (f != null && f.getDeclaringClass() == HasFields.class) { - assertEquals(f.get(fields), value); // clean to start with - } - Throwable caughtEx = null; - if (isGetter) { - Object expValue = value; - for (int i = 0; i <= 1; i++) { - sawValue = null; // make DA rules happy under try/catch - try { - if (isStatic || doBound) { - if (ftype == int.class) - sawValue = (int) mh.invokeExact(); // do these exactly - else - sawValue = mh.invokeExact(); - } else { - if (ftype == int.class) - sawValue = (int) mh.invokeExact((Object) fieldsForMH); - else - sawValue = mh.invokeExact((Object) fieldsForMH); - } - } catch (RuntimeException ex) { - if (ex instanceof NullPointerException && testNPE) { - caughtEx = ex; - break; - } - } - assertEquals(sawValue, expValue); - if (f != null && f.getDeclaringClass() == HasFields.class - && !Modifier.isFinal(f.getModifiers())) { - Object random = randomArg(ftype); - f.set(fields, random); - expValue = random; - } else { - break; - } - } - } else { - for (int i = 0; i <= 1; i++) { - Object putValue = randomArg(ftype); - try { - if (isStatic || doBound) { - if (ftype == int.class) - mh.invokeExact((int)putValue); // do these exactly - else - mh.invokeExact(putValue); - } else { - if (ftype == int.class) - mh.invokeExact((Object) fieldsForMH, (int)putValue); - else - mh.invokeExact((Object) fieldsForMH, putValue); - } - } catch (RuntimeException ex) { - if (ex instanceof NullPointerException && testNPE) { - caughtEx = ex; - break; - } - } - if (f != null && f.getDeclaringClass() == HasFields.class) { - assertEquals(f.get(fields), putValue); - } - } - } - if (f != null && f.getDeclaringClass() == HasFields.class) { - f.set(fields, value); // put it back - } - if (testNPE) { - if (caughtEx == null || !(caughtEx instanceof NullPointerException)) - throw new RuntimeException("failed to catch NPE exception"+(caughtEx == null ? " (caughtEx=null)" : ""), caughtEx); - caughtEx = null; // nullify expected exception - } - if (caughtEx != null) { - throw new RuntimeException("unexpected exception", caughtEx); - } - } - - @Test - public void testUnreflectSetter() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testUnreflectSetter0); - } - - public void testUnreflectSetter0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("unreflectSetter"); - testSetter(TEST_UNREFLECT); - } - - @Test - public void testFindSetter() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindSetter0); - } - - public void testFindSetter0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("findSetter"); - testSetter(TEST_FIND_FIELD); - testSetter(TEST_FIND_FIELD | TEST_BOUND); - } - - @Test - public void testFindStaticSetter() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFindStaticSetter0); - } - - public void testFindStaticSetter0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("findStaticSetter"); - testSetter(TEST_FIND_STATIC); - } - - public void testSetter(int testMode) throws Throwable { - Lookup lookup = PRIVATE; // FIXME: test more lookups than this one - startTest("unreflectSetter"); - for (Object[] c : HasFields.CASES) { - boolean positive = (c[1] != Error.class); - testSetter(positive, lookup, c[0], c[1], testMode); - if (positive) - testSetter(positive, lookup, c[0], c[1], testMode | TEST_NPE); - } - for (int isStaticN = 0; isStaticN <= 1; isStaticN++) { - testSetter(false, lookup, - new Object[]{ (isStaticN != 0), System.class, "bogus", char.class }, - null, testMode); - } - } - public void testSetter(boolean positive, MethodHandles.Lookup lookup, - Object fieldRef, Object value, int testMode) throws Throwable { - testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER); - } - - @Test - public void testArrayElementGetter() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testArrayElementGetter0); - } - - public void testArrayElementGetter0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("arrayElementGetter"); - testArrayElementGetterSetter(false); - } - - @Test - public void testArrayElementSetter() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testArrayElementSetter0); - } - - public void testArrayElementSetter0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("arrayElementSetter"); - testArrayElementGetterSetter(true); - } - - private static final int TEST_ARRAY_NONE = 0, TEST_ARRAY_NPE = 1, TEST_ARRAY_OOB = 2, TEST_ARRAY_ASE = 3; - - public void testArrayElementGetterSetter(boolean testSetter) throws Throwable { - testArrayElementGetterSetter(testSetter, TEST_ARRAY_NONE); - } - - @Test - public void testArrayElementErrors() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testArrayElementErrors0); - } - - public void testArrayElementErrors0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("arrayElementErrors"); - testArrayElementGetterSetter(false, TEST_ARRAY_NPE); - testArrayElementGetterSetter(true, TEST_ARRAY_NPE); - testArrayElementGetterSetter(false, TEST_ARRAY_OOB); - testArrayElementGetterSetter(true, TEST_ARRAY_OOB); - testArrayElementGetterSetter(new Object[10], true, TEST_ARRAY_ASE); - testArrayElementGetterSetter(new Example[10], true, TEST_ARRAY_ASE); - testArrayElementGetterSetter(new IntExample[10], true, TEST_ARRAY_ASE); - } - - public void testArrayElementGetterSetter(boolean testSetter, int negTest) throws Throwable { - testArrayElementGetterSetter(new String[10], testSetter, negTest); - testArrayElementGetterSetter(new Iterable[10], testSetter, negTest); - testArrayElementGetterSetter(new Example[10], testSetter, negTest); - testArrayElementGetterSetter(new IntExample[10], testSetter, negTest); - testArrayElementGetterSetter(new Object[10], testSetter, negTest); - testArrayElementGetterSetter(new boolean[10], testSetter, negTest); - testArrayElementGetterSetter(new byte[10], testSetter, negTest); - testArrayElementGetterSetter(new char[10], testSetter, negTest); - testArrayElementGetterSetter(new short[10], testSetter, negTest); - testArrayElementGetterSetter(new int[10], testSetter, negTest); - testArrayElementGetterSetter(new float[10], testSetter, negTest); - testArrayElementGetterSetter(new long[10], testSetter, negTest); - testArrayElementGetterSetter(new double[10], testSetter, negTest); - } - - public void testArrayElementGetterSetter(Object array, boolean testSetter, int negTest) throws Throwable { - boolean positive = (negTest == TEST_ARRAY_NONE); - int length = java.lang.reflect.Array.getLength(array); - Class arrayType = array.getClass(); - Class elemType = arrayType.getComponentType(); - Object arrayToMH = array; - // this stanza allows negative tests to make argument perturbations: - switch (negTest) { - case TEST_ARRAY_NPE: - arrayToMH = null; - break; - case TEST_ARRAY_OOB: - assert(length > 0); - arrayToMH = java.lang.reflect.Array.newInstance(elemType, 0); - break; - case TEST_ARRAY_ASE: - assert(testSetter && !elemType.isPrimitive()); - if (elemType == Object.class) - arrayToMH = new StringBuffer[length]; // very random subclass of Object! - else if (elemType == Example.class) - arrayToMH = new SubExample[length]; - else if (elemType == IntExample.class) - arrayToMH = new SubIntExample[length]; - else - return; // can't make an ArrayStoreException test - assert(arrayType.isInstance(arrayToMH)) - : Arrays.asList(arrayType, arrayToMH.getClass(), testSetter, negTest); - break; - } - countTest(positive); - if (verbosity > 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+length+"]"+(positive ? "" : " negative test #"+negTest+" using "+Arrays.deepToString(new Object[]{arrayToMH}))); - MethodType expType = !testSetter - ? MethodType.methodType(elemType, arrayType, int.class) - : MethodType.methodType(void.class, arrayType, int.class, elemType); - MethodHandle mh = !testSetter - ? MethodHandles.arrayElementGetter(arrayType) - : MethodHandles.arrayElementSetter(arrayType); - assertSame(mh.type(), expType); - if (elemType != int.class && elemType != boolean.class) { - MethodType gtype = mh.type().generic().changeParameterType(1, int.class); - if (testSetter) gtype = gtype.changeReturnType(void.class); - mh = mh.asType(gtype); - } - Object sawValue, expValue; - List model = array2list(array); - Throwable caughtEx = null; - for (int i = 0; i < length; i++) { - // update array element - Object random = randomArg(elemType); - model.set(i, random); - if (testSetter) { - try { - if (elemType == int.class) - mh.invokeExact((int[]) arrayToMH, i, (int)random); - else if (elemType == boolean.class) - mh.invokeExact((boolean[]) arrayToMH, i, (boolean)random); - else - mh.invokeExact(arrayToMH, i, random); - } catch (RuntimeException ex) { - caughtEx = ex; - break; - } - assertEquals(model, array2list(array)); - } else { - Array.set(array, i, random); - } - if (verbosity >= 5) { - List array2list = array2list(array); - System.out.println("a["+i+"]="+random+" => "+array2list); - if (!array2list.equals(model)) - System.out.println("*** != "+model); - } - // observe array element - sawValue = Array.get(array, i); - if (!testSetter) { - expValue = sawValue; - try { - if (elemType == int.class) - sawValue = (int) mh.invokeExact((int[]) arrayToMH, i); - else if (elemType == boolean.class) - sawValue = (boolean) mh.invokeExact((boolean[]) arrayToMH, i); - else - sawValue = mh.invokeExact(arrayToMH, i); - } catch (RuntimeException ex) { - caughtEx = ex; - break; - } - assertEquals(sawValue, expValue); - assertEquals(model, array2list(array)); - } - } - if (!positive) { - if (caughtEx == null) - throw new RuntimeException("failed to catch exception for negTest="+negTest); - // test the kind of exception - Class reqType = null; - switch (negTest) { - case TEST_ARRAY_ASE: reqType = ArrayStoreException.class; break; - case TEST_ARRAY_OOB: reqType = ArrayIndexOutOfBoundsException.class; break; - case TEST_ARRAY_NPE: reqType = NullPointerException.class; break; - default: assert(false); - } - if (reqType.isInstance(caughtEx)) { - caughtEx = null; // nullify expected exception - } - } - if (caughtEx != null) { - throw new RuntimeException("unexpected exception", caughtEx); - } - } - - List array2list(Object array) { - int length = Array.getLength(array); - ArrayList model = new ArrayList<>(length); - for (int i = 0; i < length; i++) - model.add(Array.get(array, i)); - return model; - } - static class Callee { static Object id() { return called("id"); } static Object id(Object x) { return called("id", x); } @@ -1634,1252 +655,86 @@ public class MethodHandlesTest { } } - @Test - public void testConvertArguments() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testConvertArguments0); - } - - public void testConvertArguments0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("convertArguments"); - testConvert(Callee.ofType(1), null, "id", int.class); - testConvert(Callee.ofType(1), null, "id", String.class); - testConvert(Callee.ofType(1), null, "id", Integer.class); - testConvert(Callee.ofType(1), null, "id", short.class); - testConvert(Callee.ofType(1), null, "id", char.class); - testConvert(Callee.ofType(1), null, "id", byte.class); - } - - void testConvert(MethodHandle id, Class rtype, String name, Class... params) throws Throwable { - testConvert(true, id, rtype, name, params); - } - - void testConvert(boolean positive, - MethodHandle id, Class rtype, String name, Class... params) throws Throwable { - countTest(positive); - MethodType idType = id.type(); - if (rtype == null) rtype = idType.returnType(); - for (int i = 0; i < params.length; i++) { - if (params[i] == null) params[i] = idType.parameterType(i); - } - // simulate the pairwise conversion - MethodType newType = MethodType.methodType(rtype, params); - Object[] args = randomArgs(newType.parameterArray()); - Object[] convArgs = args.clone(); - for (int i = 0; i < args.length; i++) { - Class src = newType.parameterType(i); - Class dst = idType.parameterType(i); - if (src != dst) - convArgs[i] = castToWrapper(convArgs[i], dst); - } - Object convResult = id.invokeWithArguments(convArgs); - { - Class dst = newType.returnType(); - Class src = idType.returnType(); - if (src != dst) - convResult = castToWrapper(convResult, dst); - } - MethodHandle target = null; - RuntimeException error = null; - try { - target = id.asType(newType); - } catch (WrongMethodTypeException ex) { - error = ex; - } - if (verbosity >= 3) - System.out.println("convert "+id+ " to "+newType+" => "+target - +(error == null ? "" : " !! "+error)); - if (positive && error != null) throw error; - assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); - if (!positive) return; // negative test failed as expected - assertEquals(newType, target.type()); - printCalled(target, id.toString(), args); - Object result = target.invokeWithArguments(args); - assertCalled(name, convArgs); - assertEquals(convResult, result); - if (verbosity >= 1) - System.out.print(':'); - } - - @Test - public void testVarargsCollector() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testVarargsCollector0); - } - - public void testVarargsCollector0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("varargsCollector"); - MethodHandle vac0 = PRIVATE.findStatic(MethodHandlesTest.class, "called", - MethodType.methodType(Object.class, String.class, Object[].class)); - vac0 = vac0.bindTo("vac"); - MethodHandle vac = vac0.asVarargsCollector(Object[].class); - testConvert(true, vac.asType(MethodType.genericMethodType(0)), null, "vac"); - testConvert(true, vac.asType(MethodType.genericMethodType(0)), null, "vac"); - for (Class at : new Class[] { Object.class, String.class, Integer.class }) { - testConvert(true, vac.asType(MethodType.genericMethodType(1)), null, "vac", at); - testConvert(true, vac.asType(MethodType.genericMethodType(2)), null, "vac", at, at); - } - } - - @Test // SLOW - public void testPermuteArguments() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testPermuteArguments0); - } - - public void testPermuteArguments0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("permuteArguments"); - testPermuteArguments(4, Integer.class, 2, long.class, 6); - if (CAN_TEST_LIGHTLY) return; - testPermuteArguments(4, Integer.class, 2, String.class, 0); - testPermuteArguments(6, Integer.class, 0, null, 30); - } - public void testPermuteArguments(int max, Class type1, int t2c, Class type2, int dilution) throws Throwable { - if (verbosity >= 2) - System.out.println("permuteArguments "+max+"*"+type1.getName() - +(t2c==0?"":"/"+t2c+"*"+type2.getName()) - +(dilution > 0 ? " with dilution "+dilution : "")); - int t2pos = t2c == 0 ? 0 : 1; - for (int inargs = t2pos+1; inargs <= max; inargs++) { - Class[] types = new Class[inargs]; - Arrays.fill(types, type1); - if (t2c != 0) { - // Fill in a middle range with type2: - Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2); - } - Object[] args = randomArgs(types); - int numcases = 1; - for (int outargs = 0; outargs <= max; outargs++) { - if (outargs - inargs >= MAX_ARG_INCREASE) continue; - int casStep = dilution + 1; - // Avoid some common factors: - while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) || - (casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0)) - casStep++; - testPermuteArguments(args, types, outargs, numcases, casStep); - numcases *= inargs; - if (CAN_TEST_LIGHTLY && outargs < max-2) continue; - if (dilution > 10 && outargs >= 4) { - if (CAN_TEST_LIGHTLY) continue; - int[] reorder = new int[outargs]; - // Do some special patterns, which we probably missed. - // Replication of a single argument or argument pair. - for (int i = 0; i < inargs; i++) { - Arrays.fill(reorder, i); - testPermuteArguments(args, types, reorder); - for (int d = 1; d <= 2; d++) { - if (i + d >= inargs) continue; - for (int j = 1; j < outargs; j += 2) - reorder[j] += 1; - testPermuteArguments(args, types, reorder); - testPermuteArguments(args, types, reverse(reorder)); - } - } - // Repetition of a sequence of 3 or more arguments. - for (int i = 1; i < inargs; i++) { - for (int len = 3; len <= inargs; len++) { - for (int j = 0; j < outargs; j++) - reorder[j] = (i + (j % len)) % inargs; - testPermuteArguments(args, types, reorder); - testPermuteArguments(args, types, reverse(reorder)); - } - } - } - } - } - } - - public void testPermuteArguments(Object[] args, Class[] types, - int outargs, int numcases, int casStep) throws Throwable { - int inargs = args.length; - int[] reorder = new int[outargs]; - for (int cas = 0; cas < numcases; cas += casStep) { - for (int i = 0, c = cas; i < outargs; i++) { - reorder[i] = c % inargs; - c /= inargs; - } - if (CAN_TEST_LIGHTLY && outargs >= 3 && (reorder[0] == reorder[1] || reorder[1] == reorder[2])) continue; - testPermuteArguments(args, types, reorder); - } - } - - static int[] reverse(int[] reorder) { - reorder = reorder.clone(); - for (int i = 0, imax = reorder.length / 2; i < imax; i++) { - int j = reorder.length - 1 - i; - int tem = reorder[i]; - reorder[i] = reorder[j]; - reorder[j] = tem; - } - return reorder; - } - - void testPermuteArguments(Object[] args, Class[] types, int[] reorder) throws Throwable { - countTest(); - if (args == null && types == null) { - int max = 0; - for (int j : reorder) { - if (max < j) max = j; - } - args = randomArgs(max+1, Integer.class); - } - if (args == null) { - args = randomArgs(types); - } - if (types == null) { - types = new Class[args.length]; - for (int i = 0; i < args.length; i++) - types[i] = args[i].getClass(); - } - int inargs = args.length, outargs = reorder.length; - assertTrue(inargs == types.length); - if (verbosity >= 3) - System.out.println("permuteArguments "+Arrays.toString(reorder)); - Object[] permArgs = new Object[outargs]; - Class[] permTypes = new Class[outargs]; - for (int i = 0; i < outargs; i++) { - permArgs[i] = args[reorder[i]]; - permTypes[i] = types[reorder[i]]; - } - if (verbosity >= 4) { - System.out.println("in args: "+Arrays.asList(args)); - System.out.println("out args: "+Arrays.asList(permArgs)); - System.out.println("in types: "+Arrays.asList(types)); - System.out.println("out types: "+Arrays.asList(permTypes)); - } - MethodType inType = MethodType.methodType(Object.class, types); - MethodType outType = MethodType.methodType(Object.class, permTypes); - MethodHandle target = varargsList(outargs).asType(outType); - MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder); - if (verbosity >= 5) System.out.println("newTarget = "+newTarget); - Object result = newTarget.invokeWithArguments(args); - Object expected = Arrays.asList(permArgs); - if (!expected.equals(result)) { - System.out.println("*** failed permuteArguments "+Arrays.toString(reorder)+" types="+Arrays.asList(types)); - System.out.println("in args: "+Arrays.asList(args)); - System.out.println("out args: "+expected); - System.out.println("bad args: "+result); - } - assertEquals(expected, result); - } - - - @Test // SLOW - public void testSpreadArguments() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testSpreadArguments0); - CodeCacheOverflowProcessor.runMHTest(this::testSpreadArguments1); - } - - public void testSpreadArguments0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("spreadArguments"); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { - if (verbosity >= 3) - System.out.println("spreadArguments "+argType); - Class arrayType = java.lang.reflect.Array.newInstance(argType, 0).getClass(); - for (int nargs = 0; nargs < 50; nargs++) { - if (CAN_TEST_LIGHTLY && nargs > 11) break; - for (int pos = 0; pos <= nargs; pos++) { - if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; - if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) - continue; - testSpreadArguments(argType, arrayType, pos, nargs); - } - } - } - } - public void testSpreadArguments(Class argType, Class arrayType, int pos, int nargs) throws Throwable { - countTest(); - MethodHandle target2 = varargsArray(arrayType, nargs); - MethodHandle target = target2.asType(target2.type().generic()); - if (verbosity >= 3) - System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); - Object[] args = randomArgs(target2.type().parameterArray()); - // make sure the target does what we think it does: - checkTarget(argType, pos, nargs, target, args); - List> newParams = new ArrayList<>(target2.type().parameterList()); - { // modify newParams in place - List> spreadParams = newParams.subList(pos, nargs); - spreadParams.clear(); spreadParams.add(arrayType); - } - MethodType newType = MethodType.methodType(arrayType, newParams); - MethodHandle result = target2.asSpreader(arrayType, nargs-pos); - assert(result.type() == newType) : Arrays.asList(result, newType); - result = result.asType(newType.generic()); - Object returnValue; - if (pos == 0) { - Object args2 = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length)); - returnValue = result.invokeExact(args2); - } else { - Object[] args1 = Arrays.copyOfRange(args, 0, pos+1); - args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length)); - returnValue = result.invokeWithArguments(args1); - } - checkReturnValue(argType, args, result, returnValue); - } - public void testSpreadArguments1() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("spreadArguments/pos"); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { - if (verbosity >= 3) - System.out.println("spreadArguments "+argType); - Class arrayType = java.lang.reflect.Array.newInstance(argType, 0).getClass(); - for (int nargs = 0; nargs < 50; nargs++) { - if (CAN_TEST_LIGHTLY && nargs > 11) break; - for (int pos = 0; pos <= nargs; pos++) { - if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; - if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) - continue; - for (int spr = 1; spr < nargs - pos; ++spr) { - if (spr > 4 && spr != 7 && spr != 11 && spr != 20 && spr < nargs - pos - 4) continue; - testSpreadArguments(argType, arrayType, pos, spr, nargs); - } - } - } - } - } - public void testSpreadArguments(Class argType, Class arrayType, int pos, int spread, int nargs) throws Throwable { - countTest(); - MethodHandle target2 = varargsArray(arrayType, nargs); - MethodHandle target = target2.asType(target2.type().generic()); - if (verbosity >= 3) - System.out.println("spread into " + target2 + " [" + pos + ".." + (pos + spread) + "["); - Object[] args = randomArgs(target2.type().parameterArray()); - // make sure the target does what we think it does: - checkTarget(argType, pos, nargs, target, args); - List> newParams = new ArrayList<>(target2.type().parameterList()); - { // modify newParams in place - List> spreadParams = newParams.subList(pos, pos + spread); - spreadParams.clear(); - spreadParams.add(arrayType); - } - MethodType newType = MethodType.methodType(arrayType, newParams); - MethodHandle result = target2.asSpreader(pos, arrayType, spread); - assert (result.type() == newType) : Arrays.asList(result, newType); - result = result.asType(newType.generic()); - // args1 has nargs-spread entries, plus one for the to-be-spread array - int args1Length = nargs - (spread - 1); - Object[] args1 = new Object[args1Length]; - System.arraycopy(args, 0, args1, 0, pos); - args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, pos + spread)); - System.arraycopy(args, pos + spread, args1, pos + 1, nargs - spread - pos); - Object returnValue = result.invokeWithArguments(args1); - checkReturnValue(argType, args, result, returnValue); - } - private static void checkTarget(Class argType, int pos, int nargs, MethodHandle target, Object[] args) throws Throwable { - if (pos == 0 && nargs < 5 && !argType.isPrimitive()) { - Object[] check = (Object[]) target.invokeWithArguments(args); - assertArrayEquals(args, check); - switch (nargs) { - case 0: - check = (Object[]) (Object) target.invokeExact(); - assertArrayEquals(args, check); - break; - case 1: - check = (Object[]) (Object) target.invokeExact(args[0]); - assertArrayEquals(args, check); - break; - case 2: - check = (Object[]) (Object) target.invokeExact(args[0], args[1]); - assertArrayEquals(args, check); - break; - } - } - } - private static void checkReturnValue(Class argType, Object[] args, MethodHandle result, Object returnValue) { - String argstr = Arrays.toString(args); - if (!argType.isPrimitive()) { - Object[] rv = (Object[]) returnValue; - String rvs = Arrays.toString(rv); - if (!Arrays.equals(args, rv)) { - System.out.println("method: "+result); - System.out.println("expected: "+argstr); - System.out.println("returned: "+rvs); - assertArrayEquals(args, rv); - } - } else if (argType == int.class) { - String rvs = Arrays.toString((int[]) returnValue); - if (!argstr.equals(rvs)) { - System.out.println("method: "+result); - System.out.println("expected: "+argstr); - System.out.println("returned: "+rvs); - assertEquals(argstr, rvs); - } - } else if (argType == long.class) { - String rvs = Arrays.toString((long[]) returnValue); - if (!argstr.equals(rvs)) { - System.out.println("method: "+result); - System.out.println("expected: "+argstr); - System.out.println("returned: "+rvs); - assertEquals(argstr, rvs); - } - } else { - // cannot test... - } - } - - @Test // SLOW - public void testAsCollector() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testAsCollector0); - CodeCacheOverflowProcessor.runMHTest(this::testAsCollector1); - } - - public void testAsCollector0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("asCollector"); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { - if (verbosity >= 3) - System.out.println("asCollector "+argType); - for (int nargs = 0; nargs < 50; nargs++) { - if (CAN_TEST_LIGHTLY && nargs > 11) break; - for (int pos = 0; pos <= nargs; pos++) { - if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; - if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) - continue; - testAsCollector(argType, pos, nargs); - } - } - } - } - public void testAsCollector(Class argType, int pos, int nargs) throws Throwable { - countTest(); - // fake up a MH with the same type as the desired adapter: - MethodHandle fake = varargsArray(nargs); - fake = changeArgTypes(fake, argType); - MethodType newType = fake.type(); - Object[] args = randomArgs(newType.parameterArray()); - // here is what should happen: - Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1); - collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length); - // here is the MH which will witness the collected argument tail: - MethodHandle target = varargsArray(pos+1); - target = changeArgTypes(target, 0, pos, argType); - target = changeArgTypes(target, pos, pos+1, Object[].class); - if (verbosity >= 3) - System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]"); - MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType); - Object[] returnValue = (Object[]) result.invokeWithArguments(args); -// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]); -// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]); -// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]); - assertArrayEquals(collectedArgs, returnValue); - } - public void testAsCollector1() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("asCollector/pos"); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { - if (verbosity >= 3) - System.out.println("asCollector/pos "+argType); - for (int nargs = 0; nargs < 50; nargs++) { - if (CAN_TEST_LIGHTLY && nargs > 11) break; - for (int pos = 0; pos <= nargs; pos++) { - if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; - if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) - continue; - for (int coll = 1; coll < nargs - pos; ++coll) { - if (coll > 4 && coll != 7 && coll != 11 && coll != 20 && coll < nargs - pos - 4) continue; - testAsCollector(argType, pos, coll, nargs); - } - } - } - } - } - public void testAsCollector(Class argType, int pos, int collect, int nargs) throws Throwable { - countTest(); - // fake up a MH with the same type as the desired adapter: - MethodHandle fake = varargsArray(nargs); - fake = changeArgTypes(fake, argType); - MethodType newType = fake.type(); - Object[] args = randomArgs(newType.parameterArray()); - // here is what should happen: - // new arg list has "collect" less arguments, but one extra for collected arguments array - int collectedLength = nargs-(collect-1); - Object[] collectedArgs = new Object[collectedLength]; - System.arraycopy(args, 0, collectedArgs, 0, pos); - collectedArgs[pos] = Arrays.copyOfRange(args, pos, pos+collect); - System.arraycopy(args, pos+collect, collectedArgs, pos+1, args.length-(pos+collect)); - // here is the MH which will witness the collected argument part (not tail!): - MethodHandle target = varargsArray(collectedLength); - target = changeArgTypes(target, 0, pos, argType); - target = changeArgTypes(target, pos, pos+1, Object[].class); - target = changeArgTypes(target, pos+1, collectedLength, argType); - if (verbosity >= 3) - System.out.println("collect "+collect+" from "+Arrays.asList(args)+" ["+pos+".."+(pos+collect)+"["); - MethodHandle result = target.asCollector(pos, Object[].class, collect).asType(newType); - Object[] returnValue = (Object[]) result.invokeWithArguments(args); - assertArrayEquals(collectedArgs, returnValue); - } - - @Test // SLOW - public void testInsertArguments() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testInsertArguments0); - } - - public void testInsertArguments0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("insertArguments"); - for (int nargs = 0; nargs < 50; nargs++) { - if (CAN_TEST_LIGHTLY && nargs > 11) break; - for (int ins = 0; ins <= nargs; ins++) { - if (nargs > 10 && ins > 4 && ins < nargs-4 && ins % 10 != 3) - continue; - for (int pos = 0; pos <= nargs; pos++) { - if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) - continue; - if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; - testInsertArguments(nargs, pos, ins); - } - } - } - } - - void testInsertArguments(int nargs, int pos, int ins) throws Throwable { - countTest(); - MethodHandle target = varargsArray(nargs + ins); - Object[] args = randomArgs(target.type().parameterArray()); - List resList = Arrays.asList(args); - List argsToPass = new ArrayList<>(resList); - List argsToInsert = argsToPass.subList(pos, pos + ins); - if (verbosity >= 3) - System.out.println("insert: "+argsToInsert+" @"+pos+" into "+target); - @SuppressWarnings("cast") // cast to spread Object... is helpful - MethodHandle target2 = MethodHandles.insertArguments(target, pos, - (Object[]/*...*/) argsToInsert.toArray()); - argsToInsert.clear(); // remove from argsToInsert - Object res2 = target2.invokeWithArguments(argsToPass); - Object res2List = Arrays.asList((Object[])res2); - if (verbosity >= 3) - System.out.println("result: "+res2List); - //if (!resList.equals(res2List)) - // System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List); - assertEquals(resList, res2List); - } - - @Test - public void testFilterReturnValue() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFilterReturnValue0); - } - - public void testFilterReturnValue0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("filterReturnValue"); - Class classOfVCList = varargsList(1).invokeWithArguments(0).getClass(); - assertTrue(List.class.isAssignableFrom(classOfVCList)); - for (int nargs = 0; nargs <= 3; nargs++) { - for (Class rtype : new Class[] { Object.class, - List.class, - int.class, - byte.class, - long.class, - CharSequence.class, - String.class }) { - testFilterReturnValue(nargs, rtype); - } - } - } - - void testFilterReturnValue(int nargs, Class rtype) throws Throwable { - countTest(); - MethodHandle target = varargsList(nargs, rtype); - MethodHandle filter; - if (List.class.isAssignableFrom(rtype) || rtype.isAssignableFrom(List.class)) - filter = varargsList(1); // add another layer of list-ness - else - filter = MethodHandles.identity(rtype); - filter = filter.asType(MethodType.methodType(target.type().returnType(), rtype)); - Object[] argsToPass = randomArgs(nargs, Object.class); - if (verbosity >= 3) - System.out.println("filter "+target+" to "+rtype.getSimpleName()+" with "+filter); - MethodHandle target2 = MethodHandles.filterReturnValue(target, filter); - if (verbosity >= 4) - System.out.println("filtered target: "+target2); - // Simulate expected effect of filter on return value: - Object unfiltered = target.invokeWithArguments(argsToPass); - Object expected = filter.invokeWithArguments(unfiltered); - if (verbosity >= 4) - System.out.println("unfiltered: "+unfiltered+" : "+unfiltered.getClass().getSimpleName()); - if (verbosity >= 4) - System.out.println("expected: "+expected+" : "+expected.getClass().getSimpleName()); - Object result = target2.invokeWithArguments(argsToPass); - if (verbosity >= 3) - System.out.println("result: "+result+" : "+result.getClass().getSimpleName()); - if (!expected.equals(result)) - System.out.println("*** fail at n/rt = "+nargs+"/"+rtype.getSimpleName()+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected); - assertEquals(expected, result); - } - - @Test - public void testFilterArguments() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFilterArguments0); - } - - public void testFilterArguments0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("filterArguments"); - for (int nargs = 1; nargs <= 6; nargs++) { - for (int pos = 0; pos < nargs; pos++) { - testFilterArguments(nargs, pos); - } - } - } - - void testFilterArguments(int nargs, int pos) throws Throwable { - countTest(); - MethodHandle target = varargsList(nargs); - MethodHandle filter = varargsList(1); - filter = filter.asType(filter.type().generic()); - Object[] argsToPass = randomArgs(nargs, Object.class); - if (verbosity >= 3) - System.out.println("filter "+target+" at "+pos+" with "+filter); - MethodHandle target2 = MethodHandles.filterArguments(target, pos, filter); - // Simulate expected effect of filter on arglist: - Object[] filteredArgs = argsToPass.clone(); - filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]); - List expected = Arrays.asList(filteredArgs); - Object result = target2.invokeWithArguments(argsToPass); - if (verbosity >= 3) - System.out.println("result: "+result); - if (!expected.equals(result)) - System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected); - assertEquals(expected, result); - } - - @Test - public void testCollectArguments() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testCollectArguments0); - } - - public void testCollectArguments0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("collectArguments"); - testFoldOrCollectArguments(true, false); - } - - @Test - public void testFoldArguments() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testFoldArguments0); - CodeCacheOverflowProcessor.runMHTest(this::testFoldArguments1); - } - - public void testFoldArguments0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("foldArguments"); - testFoldOrCollectArguments(false, false); - } - - public void testFoldArguments1() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("foldArguments/pos"); - testFoldOrCollectArguments(false, true); - } - - void testFoldOrCollectArguments(boolean isCollect, boolean withFoldPos) throws Throwable { - assert !(isCollect && withFoldPos); // exclude illegal argument combination - for (Class lastType : new Class[]{ Object.class, String.class, int.class }) { - for (Class collectType : new Class[]{ Object.class, String.class, int.class, void.class }) { - int maxArity = 10; - if (collectType != String.class) maxArity = 5; - if (lastType != Object.class) maxArity = 4; - for (int nargs = 0; nargs <= maxArity; nargs++) { - ArrayList> argTypes = new ArrayList<>(Collections.nCopies(nargs, Object.class)); - int maxMix = 20; - if (collectType != Object.class) maxMix = 0; - Map argTypesSeen = new HashMap<>(); - for (int mix = 0; mix <= maxMix; mix++) { - if (!mixArgs(argTypes, mix, argTypesSeen)) continue; - for (int collect = 0; collect <= nargs; collect++) { - for (int pos = 0; pos <= nargs - collect; pos++) { - testFoldOrCollectArguments(argTypes, pos, collect, collectType, lastType, isCollect, withFoldPos); - } - } - } - } - } - } - } - - boolean mixArgs(List> argTypes, int mix, Map argTypesSeen) { - assert(mix >= 0); - if (mix == 0) return true; // no change - if ((mix >>> argTypes.size()) != 0) return false; - for (int i = 0; i < argTypes.size(); i++) { - if (i >= 31) break; - boolean bit = (mix & (1 << i)) != 0; - if (bit) { - Class type = argTypes.get(i); - if (type == Object.class) - type = String.class; - else if (type == String.class) - type = int.class; - else - type = Object.class; - argTypes.set(i, type); - } - } - Integer prev = argTypesSeen.put(new ArrayList<>(argTypes), mix); - if (prev != null) { - if (verbosity >= 4) System.out.println("mix "+prev+" repeated "+mix+": "+argTypes); - return false; - } - if (verbosity >= 3) System.out.println("mix "+mix+" = "+argTypes); - return true; - } - - void testFoldOrCollectArguments(List> argTypes, // argument types minus the inserted combineType - int pos, int fold, // position and length of the folded arguments - Class combineType, // type returned from the combiner - Class lastType, // type returned from the target - boolean isCollect, - boolean withFoldPos) throws Throwable { - int nargs = argTypes.size(); - if (pos != 0 && !isCollect && !withFoldPos) return; // test MethodHandles.foldArguments(MH,MH) only for pos=0 - countTest(); - List> combineArgTypes = argTypes.subList(pos, pos + fold); - List> targetArgTypes = new ArrayList<>(argTypes); - if (isCollect) // does target see arg[pos..pos+cc-1]? - targetArgTypes.subList(pos, pos + fold).clear(); - if (combineType != void.class) - targetArgTypes.add(pos, combineType); - MethodHandle target = varargsList(targetArgTypes, lastType); - MethodHandle combine = varargsList(combineArgTypes, combineType); - List argsToPass = Arrays.asList(randomArgs(argTypes)); - if (verbosity >= 3) - System.out.println((isCollect ? "collect" : "fold")+" "+target+" with "+combine); - MethodHandle target2; - if (isCollect) - target2 = MethodHandles.collectArguments(target, pos, combine); - else - target2 = withFoldPos ? MethodHandles.foldArguments(target, pos, combine) : MethodHandles.foldArguments(target, combine); - // Simulate expected effect of combiner on arglist: - List expectedList = new ArrayList<>(argsToPass); - List argsToFold = expectedList.subList(pos, pos + fold); - if (verbosity >= 3) - System.out.println((isCollect ? "collect" : "fold")+": "+argsToFold+" into "+target2); - Object foldedArgs = combine.invokeWithArguments(argsToFold); - if (isCollect) - argsToFold.clear(); - if (combineType != void.class) - argsToFold.add(0, foldedArgs); - Object result = target2.invokeWithArguments(argsToPass); - if (verbosity >= 3) - System.out.println("result: "+result); - Object expected = target.invokeWithArguments(expectedList); - if (!expected.equals(result)) - System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected); - assertEquals(expected, result); - } - - @Test - public void testDropArguments() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testDropArguments0); - } - - public void testDropArguments0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("dropArguments"); - for (int nargs = 0; nargs <= 4; nargs++) { - for (int drop = 1; drop <= 4; drop++) { - for (int pos = 0; pos <= nargs; pos++) { - testDropArguments(nargs, pos, drop); - } - } - } - } - - void testDropArguments(int nargs, int pos, int drop) throws Throwable { - countTest(); - MethodHandle target = varargsArray(nargs); - Object[] args = randomArgs(target.type().parameterArray()); - MethodHandle target2 = MethodHandles.dropArguments(target, pos, - Collections.nCopies(drop, Object.class).toArray(new Class[0])); - List resList = Arrays.asList(args); - List argsToDrop = new ArrayList<>(resList); - for (int i = drop; i > 0; i--) { - argsToDrop.add(pos, "blort#"+i); - } - Object res2 = target2.invokeWithArguments(argsToDrop); - Object res2List = Arrays.asList((Object[])res2); - //if (!resList.equals(res2List)) - // System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List); - assertEquals(resList, res2List); - } - - @Test // SLOW - public void testInvokers() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testInvokers0); - } - - public void testInvokers0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker"); - // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker - Set done = new HashSet<>(); - for (int i = 0; i <= 6; i++) { - if (CAN_TEST_LIGHTLY && i > 3) break; - MethodType gtype = MethodType.genericMethodType(i); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { - for (int j = -1; j < i; j++) { - MethodType type = gtype; - if (j < 0) - type = type.changeReturnType(argType); - else if (argType == void.class) - continue; - else - type = type.changeParameterType(j, argType); - if (done.add(type)) - testInvokersWithCatch(type); - MethodType vtype = type.changeReturnType(void.class); - if (done.add(vtype)) - testInvokersWithCatch(vtype); - } - } - } - } - - public void testInvokersWithCatch(MethodType type) throws Throwable { - try { - testInvokers(type); - } catch (Throwable ex) { - System.out.println("*** testInvokers on "+type+" => "); - ex.printStackTrace(System.out); - } - } - public void testInvokers(MethodType type) throws Throwable { - if (verbosity >= 3) - System.out.println("test invokers for "+type); - int nargs = type.parameterCount(); - boolean testRetCode = type.returnType() != void.class; - MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee", - MethodType.genericMethodType(0, true)); - assertTrue(target.isVarargsCollector()); - target = target.asType(type); - Object[] args = randomArgs(type.parameterArray()); - List targetPlusArgs = new ArrayList<>(Arrays.asList(args)); - targetPlusArgs.add(0, target); - int code = (Integer) invokee(args); - Object log = logEntry("invokee", args); - assertEquals(log.hashCode(), code); - assertCalled("invokee", args); - MethodHandle inv; - Object result; - // exact invoker - countTest(); - calledLog.clear(); - inv = MethodHandles.exactInvoker(type); - result = inv.invokeWithArguments(targetPlusArgs); - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - // generic invoker - countTest(); - inv = MethodHandles.invoker(type); - if (nargs <= 3 && type == type.generic()) { - calledLog.clear(); - switch (nargs) { - case 0: - result = inv.invokeExact(target); - break; - case 1: - result = inv.invokeExact(target, args[0]); - break; - case 2: - result = inv.invokeExact(target, args[0], args[1]); - break; - case 3: - result = inv.invokeExact(target, args[0], args[1], args[2]); - break; - } - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - } - calledLog.clear(); - result = inv.invokeWithArguments(targetPlusArgs); - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - // varargs invoker #0 - calledLog.clear(); - inv = MethodHandles.spreadInvoker(type, 0); - if (type.returnType() == Object.class) { - result = inv.invokeExact(target, args); - } else if (type.returnType() == void.class) { - result = null; inv.invokeExact(target, args); - } else { - result = inv.invokeWithArguments(target, (Object) args); - } - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - if (nargs >= 1 && type == type.generic()) { - // varargs invoker #1 - calledLog.clear(); - inv = MethodHandles.spreadInvoker(type, 1); - result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs)); - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - } - if (nargs >= 2 && type == type.generic()) { - // varargs invoker #2 - calledLog.clear(); - inv = MethodHandles.spreadInvoker(type, 2); - result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - } - if (nargs >= 3 && type == type.generic()) { - // varargs invoker #3 - calledLog.clear(); - inv = MethodHandles.spreadInvoker(type, 3); - result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - } - for (int k = 0; k <= nargs; k++) { - // varargs invoker #0..N - if (CAN_TEST_LIGHTLY && (k > 1 || k < nargs - 1)) continue; - countTest(); - calledLog.clear(); - inv = MethodHandles.spreadInvoker(type, k); - MethodType expType = (type.dropParameterTypes(k, nargs) - .appendParameterTypes(Object[].class) - .insertParameterTypes(0, MethodHandle.class)); - assertEquals(expType, inv.type()); - List targetPlusVarArgs = new ArrayList<>(targetPlusArgs); - List tailList = targetPlusVarArgs.subList(1+k, 1+nargs); - Object[] tail = tailList.toArray(); - tailList.clear(); tailList.add(tail); - result = inv.invokeWithArguments(targetPlusVarArgs); - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - } - - // dynamic invoker - countTest(); - CallSite site = new MutableCallSite(type); - inv = site.dynamicInvoker(); - - // see if we get the result of the original target: - try { - result = inv.invokeWithArguments(args); - assertTrue("should not reach here", false); - } catch (IllegalStateException ex) { - String msg = ex.getMessage(); - assertTrue(msg, msg.contains("site")); - } - - // set new target after invoker is created, to make sure we track target - site.setTarget(target); - calledLog.clear(); - result = inv.invokeWithArguments(args); - if (testRetCode) assertEquals(code, result); - assertCalled("invokee", args); - } - static Object invokee(Object... args) { return called("invokee", args).hashCode(); } - private static final String MISSING_ARG = "missingArg"; - private static final String MISSING_ARG_2 = "missingArg#2"; + protected static final String MISSING_ARG = "missingArg"; + protected static final String MISSING_ARG_2 = "missingArg#2"; + static Object targetIfEquals() { return called("targetIfEquals"); } + static Object fallbackIfNotEquals() { return called("fallbackIfNotEquals"); } + static Object targetIfEquals(Object x) { assertEquals(x, MISSING_ARG); return called("targetIfEquals", x); } + static Object fallbackIfNotEquals(Object x) { assertFalse(x.toString(), x.equals(MISSING_ARG)); return called("fallbackIfNotEquals", x); } + static Object targetIfEquals(Object x, Object y) { assertEquals(x, y); return called("targetIfEquals", x, y); } + static Object fallbackIfNotEquals(Object x, Object y) { assertFalse(x.toString(), x.equals(y)); return called("fallbackIfNotEquals", x, y); } + static Object targetIfEquals(Object x, Object y, Object z) { assertEquals(x, y); return called("targetIfEquals", x, y, z); } + static Object fallbackIfNotEquals(Object x, Object y, Object z) { assertFalse(x.toString(), x.equals(y)); return called("fallbackIfNotEquals", x, y, z); } - @Test - public void testGuardWithTest() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testGuardWithTest0); - } - - public void testGuardWithTest0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("guardWithTest"); - for (int nargs = 0; nargs <= 50; nargs++) { - if (CAN_TEST_LIGHTLY && nargs > 7) break; - testGuardWithTest(nargs, Object.class); - testGuardWithTest(nargs, String.class); - } - } - void testGuardWithTest(int nargs, Class argClass) throws Throwable { - testGuardWithTest(nargs, 0, argClass); - if (nargs <= 5 || nargs % 10 == 3) { - for (int testDrops = 1; testDrops <= nargs; testDrops++) - testGuardWithTest(nargs, testDrops, argClass); - } - } - void testGuardWithTest(int nargs, int testDrops, Class argClass) throws Throwable { - countTest(); - int nargs1 = Math.min(3, nargs); - MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class)); - MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs1)); - MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs1)); - while (test.type().parameterCount() > nargs) - // 0: test = constant(MISSING_ARG.equals(MISSING_ARG)) - // 1: test = lambda (_) MISSING_ARG.equals(_) - test = MethodHandles.insertArguments(test, 0, MISSING_ARG); - if (argClass != Object.class) { - test = changeArgTypes(test, argClass); - target = changeArgTypes(target, argClass); - fallback = changeArgTypes(fallback, argClass); - } - int testArgs = nargs - testDrops; - assert(testArgs >= 0); - test = addTrailingArgs(test, Math.min(testArgs, nargs), argClass); - target = addTrailingArgs(target, nargs, argClass); - fallback = addTrailingArgs(fallback, nargs, argClass); - Object[][] argLists = { - { }, - { "foo" }, { MISSING_ARG }, - { "foo", "foo" }, { "foo", "bar" }, - { "foo", "foo", "baz" }, { "foo", "bar", "baz" } - }; - for (Object[] argList : argLists) { - Object[] argList1 = argList; - if (argList.length != nargs) { - if (argList.length != nargs1) continue; - argList1 = Arrays.copyOf(argList, nargs); - Arrays.fill(argList1, nargs1, nargs, MISSING_ARG_2); - } - MethodHandle test1 = test; - if (test1.type().parameterCount() > testArgs) { - int pc = test1.type().parameterCount(); - test1 = MethodHandles.insertArguments(test, testArgs, Arrays.copyOfRange(argList1, testArgs, pc)); - } - MethodHandle mh = MethodHandles.guardWithTest(test1, target, fallback); - assertEquals(target.type(), mh.type()); - boolean equals; - switch (nargs) { - case 0: equals = true; break; - case 1: equals = MISSING_ARG.equals(argList[0]); break; - default: equals = argList[0].equals(argList[1]); break; - } - String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals"); - if (verbosity >= 3) - System.out.println(logEntry(willCall, argList)); - Object result = mh.invokeWithArguments(argList1); - assertCalled(willCall, argList); - } - } - - @Test - public void testGenericLoopCombinator() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testGenericLoopCombinator0); - } - public void testGenericLoopCombinator0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("loop"); - // Test as follows: - // * Have an increasing number of loop-local state. Local state type diversity grows with the number. - // * Initializers set the starting value of loop-local state from the corresponding loop argument. - // * For each local state element, there is a predicate - for all state combinations, exercise all predicates. - // * Steps modify each local state element in each iteration. - // * Finalizers group all local state elements into a resulting array. Verify end values. - // * Exercise both pre- and post-checked loops. - // Local state types, start values, predicates, and steps: - // * int a, 0, a < 7, a = a + 1 - // * double b, 7.0, b > 0.5, b = b / 2.0 - // * String c, "start", c.length <= 9, c = c + a - final Class[] argTypes = new Class[] {int.class, double.class, String.class}; - final Object[][] args = new Object[][] { - new Object[]{0 }, - new Object[]{0, 7.0 }, - new Object[]{0, 7.0, "start"} - }; - // These are the expected final state tuples for argument type tuple / predicate combinations, for pre- and - // post-checked loops: - final Object[][] preCheckedResults = new Object[][] { - new Object[]{7 }, // (int) / int - new Object[]{7, 0.0546875 }, // (int,double) / int - new Object[]{5, 0.4375 }, // (int,double) / double - new Object[]{7, 0.0546875, "start1234567"}, // (int,double,String) / int - new Object[]{5, 0.4375, "start1234" }, // (int,double,String) / double - new Object[]{6, 0.109375, "start12345" } // (int,double,String) / String - }; - final Object[][] postCheckedResults = new Object[][] { - new Object[]{7 }, // (int) / int - new Object[]{7, 0.109375 }, // (int,double) / int - new Object[]{4, 0.4375 }, // (int,double) / double - new Object[]{7, 0.109375, "start123456"}, // (int,double,String) / int - new Object[]{4, 0.4375, "start123" }, // (int,double,String) / double - new Object[]{5, 0.21875, "start12345" } // (int,double,String) / String - }; - final Lookup l = MethodHandles.lookup(); - final Class MHT = MethodHandlesTest.class; - final Class B = boolean.class; - final Class I = int.class; - final Class D = double.class; - final Class S = String.class; - final MethodHandle hip = l.findStatic(MHT, "loopIntPred", methodType(B, I)); - final MethodHandle hdp = l.findStatic(MHT, "loopDoublePred", methodType(B, I, D)); - final MethodHandle hsp = l.findStatic(MHT, "loopStringPred", methodType(B, I, D, S)); - final MethodHandle his = l.findStatic(MHT, "loopIntStep", methodType(I, I)); - final MethodHandle hds = l.findStatic(MHT, "loopDoubleStep", methodType(D, I, D)); - final MethodHandle hss = l.findStatic(MHT, "loopStringStep", methodType(S, I, D, S)); - final MethodHandle[] preds = new MethodHandle[] {hip, hdp, hsp}; - final MethodHandle[] steps = new MethodHandle[] {his, hds, hss}; - for (int nargs = 1, useResultsStart = 0; nargs <= argTypes.length; useResultsStart += nargs++) { - Class[] useArgTypes = Arrays.copyOf(argTypes, nargs, Class[].class); - MethodHandle[] usePreds = Arrays.copyOf(preds, nargs, MethodHandle[].class); - MethodHandle[] useSteps = Arrays.copyOf(steps, nargs, MethodHandle[].class); - Object[] useArgs = args[nargs - 1]; - Object[][] usePreCheckedResults = new Object[nargs][]; - Object[][] usePostCheckedResults = new Object[nargs][]; - System.arraycopy(preCheckedResults, useResultsStart, usePreCheckedResults, 0, nargs); - System.arraycopy(postCheckedResults, useResultsStart, usePostCheckedResults, 0, nargs); - testGenericLoopCombinator(nargs, useArgTypes, usePreds, useSteps, useArgs, usePreCheckedResults, - usePostCheckedResults); - } - } - void testGenericLoopCombinator(int nargs, Class[] argTypes, MethodHandle[] preds, MethodHandle[] steps, - Object[] args, Object[][] preCheckedResults, Object[][] postCheckedResults) - throws Throwable { - List> lArgTypes = Arrays.asList(argTypes); - // Predicate and step handles are passed in as arguments, initializer and finalizer handles are constructed here - // from the available information. - MethodHandle[] inits = new MethodHandle[nargs]; - for (int i = 0; i < nargs; ++i) { - MethodHandle h; - // Initializers are meant to return whatever they are passed at a given argument position. This means that - // additional arguments may have to be appended and prepended. - h = MethodHandles.identity(argTypes[i]); - if (i < nargs - 1) { - h = MethodHandles.dropArguments(h, 1, lArgTypes.subList(i + 1, nargs)); - } - if (i > 0) { - h = MethodHandles.dropArguments(h, 0, lArgTypes.subList(0, i)); - } - inits[i] = h; - } - // Finalizers are all meant to collect all of the loop-local state in a single array and return that. Local - // state is passed before the loop args. Construct such a finalizer by first taking a varargsArray collector for - // the number of local state arguments, and then appending the loop args as to-be-dropped arguments. - MethodHandle[] finis = new MethodHandle[nargs]; - MethodHandle genericFini = MethodHandles.dropArguments( - varargsArray(nargs).asType(methodType(Object[].class, lArgTypes)), nargs, lArgTypes); - Arrays.fill(finis, genericFini); - // The predicate and step handles' signatures need to be extended. They currently just accept local state args; - // append possibly missing local state args and loop args using dropArguments. - for (int i = 0; i < nargs; ++i) { - List> additionalLocalStateArgTypes = lArgTypes.subList(i + 1, nargs); - preds[i] = MethodHandles.dropArguments( - MethodHandles.dropArguments(preds[i], i + 1, additionalLocalStateArgTypes), nargs, lArgTypes); - steps[i] = MethodHandles.dropArguments( - MethodHandles.dropArguments(steps[i], i + 1, additionalLocalStateArgTypes), nargs, lArgTypes); - } - // Iterate over all of the predicates, using only one of them at a time. - for (int i = 0; i < nargs; ++i) { - MethodHandle[] usePreds; - if (nargs == 1) { - usePreds = preds; - } else { - // Create an all-null preds array, and only use one predicate in this iteration. The null entries will - // be substituted with true predicates by the loop combinator. - usePreds = new MethodHandle[nargs]; - usePreds[i] = preds[i]; - } - // Go for it. - if (verbosity >= 3) { - System.out.println("calling loop for argument types " + lArgTypes + " with predicate at index " + i); - if (verbosity >= 5) { - System.out.println("predicates: " + Arrays.asList(usePreds)); - } - } - MethodHandle[] preInits = new MethodHandle[nargs + 1]; - MethodHandle[] prePreds = new MethodHandle[nargs + 1]; - MethodHandle[] preSteps = new MethodHandle[nargs + 1]; - MethodHandle[] preFinis = new MethodHandle[nargs + 1]; - System.arraycopy(inits, 0, preInits, 1, nargs); - System.arraycopy(usePreds, 0, prePreds, 0, nargs); // preds are offset by 1 for pre-checked loops - System.arraycopy(steps, 0, preSteps, 1, nargs); - System.arraycopy(finis, 0, preFinis, 0, nargs); // finis are also offset by 1 for pre-checked loops - // Convert to clause-major form. - MethodHandle[][] preClauses = new MethodHandle[nargs + 1][4]; - MethodHandle[][] postClauses = new MethodHandle[nargs][4]; - toClauseMajor(preClauses, preInits, preSteps, prePreds, preFinis); - toClauseMajor(postClauses, inits, steps, usePreds, finis); - MethodHandle pre = MethodHandles.loop(preClauses); - MethodHandle post = MethodHandles.loop(postClauses); - if (verbosity >= 6) { - System.out.println("pre-handle: " + pre); - } - Object[] preResults = (Object[]) pre.invokeWithArguments(args); - if (verbosity >= 4) { - System.out.println("pre-checked: expected " + Arrays.asList(preCheckedResults[i]) + ", actual " + - Arrays.asList(preResults)); - } - if (verbosity >= 6) { - System.out.println("post-handle: " + post); - } - Object[] postResults = (Object[]) post.invokeWithArguments(args); - if (verbosity >= 4) { - System.out.println("post-checked: expected " + Arrays.asList(postCheckedResults[i]) + ", actual " + - Arrays.asList(postResults)); - } - assertArrayEquals(preCheckedResults[i], preResults); - assertArrayEquals(postCheckedResults[i], postResults); - } - } - static void toClauseMajor(MethodHandle[][] clauses, MethodHandle[] init, MethodHandle[] step, MethodHandle[] pred, MethodHandle[] fini) { - for (int i = 0; i < clauses.length; ++i) { - clauses[i][0] = init[i]; - clauses[i][1] = step[i]; - clauses[i][2] = pred[i]; - clauses[i][3] = fini[i]; - } - } static boolean loopIntPred(int a) { if (verbosity >= 5) { System.out.println("int pred " + a + " -> " + (a < 7)); } return a < 7; } + static boolean loopDoublePred(int a, double b) { if (verbosity >= 5) { System.out.println("double pred (a=" + a + ") " + b + " -> " + (b > 0.5)); } return b > 0.5; } + static boolean loopStringPred(int a, double b, String c) { if (verbosity >= 5) { System.out.println("String pred (a=" + a + ",b=" + b + ") " + c + " -> " + (c.length() <= 9)); } return c.length() <= 9; } + static int loopIntStep(int a) { if (verbosity >= 5) { System.out.println("int step " + a + " -> " + (a + 1)); } return a + 1; } + static double loopDoubleStep(int a, double b) { if (verbosity >= 5) { System.out.println("double step (a=" + a + ") " + b + " -> " + (b / 2.0)); } return b / 2.0; } + static String loopStringStep(int a, double b, String c) { if (verbosity >= 5) { System.out.println("String step (a=" + a + ",b=" + b + ") " + c + " -> " + (c + a)); @@ -2887,603 +742,33 @@ public class MethodHandlesTest { return c + a; } - @Test - public void testThrowException() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testThrowException0); - } - - public void testThrowException0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("throwException"); - testThrowException(int.class, new ClassCastException("testing")); - testThrowException(void.class, new java.io.IOException("testing")); - testThrowException(String.class, new LinkageError("testing")); - } - - void testThrowException(Class returnType, Throwable thrown) throws Throwable { - countTest(); - Class exType = thrown.getClass(); - MethodHandle target = MethodHandles.throwException(returnType, exType); - //System.out.println("throwing with "+target+" : "+thrown); - MethodType expectedType = MethodType.methodType(returnType, exType); - assertEquals(expectedType, target.type()); - target = target.asType(target.type().generic()); - Throwable caught = null; - try { - Object res = target.invokeExact((Object) thrown); - fail("got "+res+" instead of throwing "+thrown); - } catch (Throwable ex) { - if (ex != thrown) { - if (ex instanceof Error) throw (Error)ex; - if (ex instanceof RuntimeException) throw (RuntimeException)ex; - } - caught = ex; - } - assertSame(thrown, caught); - } - - @Test - public void testTryFinally() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testTryFinally0); - } - public void testTryFinally0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("tryFinally"); - String inputMessage = "returned"; - String augmentedMessage = "augmented"; - String thrownMessage = "thrown"; - String rethrownMessage = "rethrown"; - // Test these cases: - // * target returns, cleanup passes through - // * target returns, cleanup augments - // * target throws, cleanup augments and returns - // * target throws, cleanup augments and rethrows - MethodHandle target = MethodHandles.identity(String.class); - MethodHandle targetThrow = MethodHandles.dropArguments( - MethodHandles.throwException(String.class, Exception.class).bindTo(new Exception(thrownMessage)), 0, String.class); - MethodHandle cleanupPassThrough = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0, - Throwable.class, String.class); - MethodHandle cleanupAugment = MethodHandles.dropArguments(MethodHandles.constant(String.class, augmentedMessage), - 0, Throwable.class, String.class, String.class); - MethodHandle cleanupCatch = MethodHandles.dropArguments(MethodHandles.constant(String.class, thrownMessage), 0, - Throwable.class, String.class, String.class); - MethodHandle cleanupThrow = MethodHandles.dropArguments(MethodHandles.throwException(String.class, Exception.class). - bindTo(new Exception(rethrownMessage)), 0, Throwable.class, String.class, String.class); - testTryFinally(target, cleanupPassThrough, inputMessage, inputMessage, false); - testTryFinally(target, cleanupAugment, inputMessage, augmentedMessage, false); - testTryFinally(targetThrow, cleanupCatch, inputMessage, thrownMessage, true); - testTryFinally(targetThrow, cleanupThrow, inputMessage, rethrownMessage, true); - // Test the same cases as above for void targets and cleanups. - MethodHandles.Lookup lookup = MethodHandles.lookup(); - Class C = this.getClass(); - MethodType targetType = methodType(void.class, String[].class); - MethodType cleanupType = methodType(void.class, Throwable.class, String[].class); - MethodHandle vtarget = lookup.findStatic(C, "vtarget", targetType); - MethodHandle vtargetThrow = lookup.findStatic(C, "vtargetThrow", targetType); - MethodHandle vcleanupPassThrough = lookup.findStatic(C, "vcleanupPassThrough", cleanupType); - MethodHandle vcleanupAugment = lookup.findStatic(C, "vcleanupAugment", cleanupType); - MethodHandle vcleanupCatch = lookup.findStatic(C, "vcleanupCatch", cleanupType); - MethodHandle vcleanupThrow = lookup.findStatic(C, "vcleanupThrow", cleanupType); - testTryFinally(vtarget, vcleanupPassThrough, inputMessage, inputMessage, false); - testTryFinally(vtarget, vcleanupAugment, inputMessage, augmentedMessage, false); - testTryFinally(vtargetThrow, vcleanupCatch, inputMessage, thrownMessage, true); - testTryFinally(vtargetThrow, vcleanupThrow, inputMessage, rethrownMessage, true); - } - void testTryFinally(MethodHandle target, MethodHandle cleanup, String input, String msg, boolean mustCatch) - throws Throwable { - countTest(); - MethodHandle tf = MethodHandles.tryFinally(target, cleanup); - String result = null; - boolean isVoid = target.type().returnType() == void.class; - String[] argArray = new String[]{input}; - try { - if (isVoid) { - tf.invoke(argArray); - } else { - result = (String) tf.invoke(input); - } - } catch (Throwable t) { - assertTrue(mustCatch); - assertEquals(msg, t.getMessage()); - return; - } - assertFalse(mustCatch); - if (isVoid) { - assertEquals(msg, argArray[0]); - } else { - assertEquals(msg, result); - } - } static void vtarget(String[] a) { // naught, akin to identity } + static void vtargetThrow(String[] a) throws Exception { throw new Exception("thrown"); } + static void vcleanupPassThrough(Throwable t, String[] a) { assertNull(t); // naught, akin to identity } + static void vcleanupAugment(Throwable t, String[] a) { assertNull(t); a[0] = "augmented"; } + static void vcleanupCatch(Throwable t, String[] a) { assertNotNull(t); a[0] = "caught"; } + static void vcleanupThrow(Throwable t, String[] a) throws Exception { assertNotNull(t); throw new Exception("rethrown"); } - - @Test - public void testInterfaceCast() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testInterfaceCast0); - } - - public void testInterfaceCast0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("interfaceCast"); - assert( (((Object)"foo") instanceof CharSequence)); - assert(!(((Object)"foo") instanceof Iterable)); - for (MethodHandle mh : new MethodHandle[]{ - MethodHandles.identity(String.class), - MethodHandles.identity(CharSequence.class), - MethodHandles.identity(Iterable.class) - }) { - if (verbosity > 0) System.out.println("-- mh = "+mh); - for (Class ctype : new Class[]{ - Object.class, String.class, CharSequence.class, - Number.class, Iterable.class - }) { - if (verbosity > 0) System.out.println("---- ctype = "+ctype.getName()); - // doret docast - testInterfaceCast(mh, ctype, false, false); - testInterfaceCast(mh, ctype, true, false); - testInterfaceCast(mh, ctype, false, true); - testInterfaceCast(mh, ctype, true, true); - } - } - } - private static Class i2o(Class c) { - return (c.isInterface() ? Object.class : c); - } - public void testInterfaceCast(MethodHandle mh, Class ctype, - boolean doret, boolean docast) throws Throwable { - MethodHandle mh0 = mh; - if (verbosity > 1) - System.out.println("mh="+mh+", ctype="+ctype.getName()+", doret="+doret+", docast="+docast); - String normalRetVal = "normal return value"; - MethodType mt = mh.type(); - MethodType mt0 = mt; - if (doret) mt = mt.changeReturnType(ctype); - else mt = mt.changeParameterType(0, ctype); - if (docast) mh = MethodHandles.explicitCastArguments(mh, mt); - else mh = mh.asType(mt); - assertEquals(mt, mh.type()); - MethodType mt1 = mt; - // this bit is needed to make the interface types disappear for invokeWithArguments: - mh = MethodHandles.explicitCastArguments(mh, mt.generic()); - Class[] step = { - mt1.parameterType(0), // param as passed to mh at first - mt0.parameterType(0), // param after incoming cast - mt0.returnType(), // return value before cast - mt1.returnType(), // return value after outgoing cast - }; - // where might a checkCast occur? - boolean[] checkCast = new boolean[step.length]; - // the string value must pass each step without causing an exception - if (!docast) { - if (!doret) { - if (step[0] != step[1]) - checkCast[1] = true; // incoming value is cast - } else { - if (step[2] != step[3]) - checkCast[3] = true; // outgoing value is cast - } - } - boolean expectFail = false; - for (int i = 0; i < step.length; i++) { - Class c = step[i]; - if (!checkCast[i]) c = i2o(c); - if (!c.isInstance(normalRetVal)) { - if (verbosity > 3) - System.out.println("expect failure at step "+i+" in "+Arrays.toString(step)+Arrays.toString(checkCast)); - expectFail = true; - break; - } - } - countTest(!expectFail); - if (verbosity > 2) - System.out.println("expectFail="+expectFail+", mt="+mt); - Object res; - try { - res = mh.invokeWithArguments(normalRetVal); - } catch (Exception ex) { - res = ex; - } - boolean sawFail = !(res instanceof String); - if (sawFail != expectFail) { - System.out.println("*** testInterfaceCast: mh0 = "+mh0); - System.out.println(" retype using "+(docast ? "explicitCastArguments" : "asType")+" to "+mt+" => "+mh); - System.out.println(" call returned "+res); - System.out.println(" expected "+(expectFail ? "an exception" : normalRetVal)); - } - if (!expectFail) { - assertFalse(res.toString(), sawFail); - assertEquals(normalRetVal, res); - } else { - assertTrue(res.toString(), sawFail); - } - } - - @Test // SLOW - public void testCastFailure() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testCastFailure0); - } - - public void testCastFailure0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("testCastFailure"); - testCastFailure("cast/argument", 11000); - if (CAN_TEST_LIGHTLY) return; - testCastFailure("unbox/argument", 11000); - testCastFailure("cast/return", 11000); - testCastFailure("unbox/return", 11000); - } - - static class Surprise { - public MethodHandle asMethodHandle() { - return VALUE.bindTo(this); - } - Object value(Object x) { - trace("value", x); - if (boo != null) return boo; - return x; - } - Object boo; - void boo(Object x) { boo = x; } - - static void trace(String x, Object y) { - if (verbosity > 8) System.out.println(x+"="+y); - } - static Object refIdentity(Object x) { trace("ref.x", x); return x; } - static Integer boxIdentity(Integer x) { trace("box.x", x); return x; } - static int intIdentity(int x) { trace("int.x", x); return x; } - static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY; - static { - try { - VALUE = PRIVATE.findVirtual( - Surprise.class, "value", - MethodType.methodType(Object.class, Object.class)); - REF_IDENTITY = PRIVATE.findStatic( - Surprise.class, "refIdentity", - MethodType.methodType(Object.class, Object.class)); - BOX_IDENTITY = PRIVATE.findStatic( - Surprise.class, "boxIdentity", - MethodType.methodType(Integer.class, Integer.class)); - INT_IDENTITY = PRIVATE.findStatic( - Surprise.class, "intIdentity", - MethodType.methodType(int.class, int.class)); - } catch (NoSuchMethodException | IllegalAccessException ex) { - throw new RuntimeException(ex); - } - } - } - - @SuppressWarnings("ConvertToStringSwitch") - void testCastFailure(String mode, int okCount) throws Throwable { - countTest(false); - if (verbosity > 2) System.out.println("mode="+mode); - Surprise boo = new Surprise(); - MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0; - if (mode.endsWith("/return")) { - if (mode.equals("unbox/return")) { - // fail on return to ((Integer)surprise).intValue - surprise = surprise.asType(MethodType.methodType(int.class, Object.class)); - identity = identity.asType(MethodType.methodType(int.class, Object.class)); - } else if (mode.equals("cast/return")) { - // fail on return to (Integer)surprise - surprise = surprise.asType(MethodType.methodType(Integer.class, Object.class)); - identity = identity.asType(MethodType.methodType(Integer.class, Object.class)); - } - } else if (mode.endsWith("/argument")) { - MethodHandle callee = null; - if (mode.equals("unbox/argument")) { - // fail on handing surprise to int argument - callee = Surprise.INT_IDENTITY; - } else if (mode.equals("cast/argument")) { - // fail on handing surprise to Integer argument - callee = Surprise.BOX_IDENTITY; - } - if (callee != null) { - callee = callee.asType(MethodType.genericMethodType(1)); - surprise = MethodHandles.filterArguments(callee, 0, surprise); - identity = MethodHandles.filterArguments(callee, 0, identity); - } - } - assertNotSame(mode, surprise, surprise0); - identity = identity.asType(MethodType.genericMethodType(1)); - surprise = surprise.asType(MethodType.genericMethodType(1)); - Object x = 42; - for (int i = 0; i < okCount; i++) { - Object y = identity.invokeExact(x); - assertEquals(x, y); - Object z = surprise.invokeExact(x); - assertEquals(x, z); - } - boo.boo("Boo!"); - Object y = identity.invokeExact(x); - assertEquals(x, y); - try { - Object z = surprise.invokeExact(x); - System.out.println("Failed to throw; got z="+z); - assertTrue(false); - } catch (ClassCastException ex) { - if (verbosity > 2) - System.out.println("caught "+ex); - if (verbosity > 3) - ex.printStackTrace(System.out); - assertTrue(true); // all is well - } - } - - static Example userMethod(Object o, String s, int i) { - called("userMethod", o, s, i); - return null; - } - - @Test - public void testUserClassInSignature() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testUserClassInSignature0); - } - - public void testUserClassInSignature0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("testUserClassInSignature"); - Lookup lookup = MethodHandles.lookup(); - String name; MethodType mt; MethodHandle mh; - Object[] args; - - // Try a static method. - name = "userMethod"; - mt = MethodType.methodType(Example.class, Object.class, String.class, int.class); - mh = lookup.findStatic(lookup.lookupClass(), name, mt); - assertEquals(mt, mh.type()); - assertEquals(Example.class, mh.type().returnType()); - args = randomArgs(mh.type().parameterArray()); - mh.invokeWithArguments(args); - assertCalled(name, args); - - // Try a virtual method. - name = "v2"; - mt = MethodType.methodType(Object.class, Object.class, int.class); - mh = lookup.findVirtual(Example.class, name, mt); - assertEquals(mt, mh.type().dropParameterTypes(0,1)); - assertTrue(mh.type().parameterList().contains(Example.class)); - args = randomArgs(mh.type().parameterArray()); - mh.invokeWithArguments(args); - assertCalled(name, args); - } - - static void runForRunnable() { - called("runForRunnable"); - } - public interface Fooable { - // overloads: - Object foo(Object x, String y); - List foo(String x, int y); - Object foo(String x); - } - static Object fooForFooable(String x, Object... y) { - return called("fooForFooable/"+x, y); - } - @SuppressWarnings("serial") // not really a public API, just a test case - public static class MyCheckedException extends Exception { - } - public interface WillThrow { - void willThrow() throws MyCheckedException; - } - /*non-public*/ interface PrivateRunnable { - public void run(); - } - - @Test - public void testAsInterfaceInstance() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testAsInterfaceInstance0); - } - - public void testAsInterfaceInstance0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("asInterfaceInstance"); - Lookup lookup = MethodHandles.lookup(); - // test typical case: Runnable.run - { - countTest(); - if (verbosity >= 2) System.out.println("Runnable"); - MethodType mt = MethodType.methodType(void.class); - MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt); - Runnable proxy = MethodHandleProxies.asInterfaceInstance(Runnable.class, mh); - proxy.run(); - assertCalled("runForRunnable"); - } - // well known single-name overloaded interface: Appendable.append - { - countTest(); - if (verbosity >= 2) System.out.println("Appendable"); - ArrayList> appendResults = new ArrayList<>(); - MethodHandle append = lookup.bind(appendResults, "add", MethodType.methodType(boolean.class, Object.class)); - append = append.asType(MethodType.methodType(void.class, List.class)); // specialize the type - MethodHandle asList = lookup.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class)); - MethodHandle mh = MethodHandles.filterReturnValue(asList, append).asVarargsCollector(Object[].class); - Appendable proxy = MethodHandleProxies.asInterfaceInstance(Appendable.class, mh); - proxy.append("one"); - proxy.append("two", 3, 4); - proxy.append('5'); - assertEquals(Arrays.asList(Arrays.asList("one"), - Arrays.asList("two", 3, 4), - Arrays.asList('5')), - appendResults); - if (verbosity >= 3) System.out.println("appendResults="+appendResults); - appendResults.clear(); - Formatter formatter = new Formatter(proxy); - String fmt = "foo str=%s char='%c' num=%d"; - Object[] fmtArgs = { "str!", 'C', 42 }; - String expect = String.format(fmt, fmtArgs); - formatter.format(fmt, fmtArgs); - String actual = ""; - if (verbosity >= 3) System.out.println("appendResults="+appendResults); - for (List l : appendResults) { - Object x = l.get(0); - switch (l.size()) { - case 1: actual += x; continue; - case 3: actual += ((String)x).substring((int)(Object)l.get(1), (int)(Object)l.get(2)); continue; - } - actual += l; - } - if (verbosity >= 3) System.out.println("expect="+expect); - if (verbosity >= 3) System.out.println("actual="+actual); - assertEquals(expect, actual); - } - // test case of an single name which is overloaded: Fooable.foo(...) - { - if (verbosity >= 2) System.out.println("Fooable"); - MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", - MethodType.methodType(Object.class, String.class, Object[].class)); - Fooable proxy = MethodHandleProxies.asInterfaceInstance(Fooable.class, mh); - for (Method m : Fooable.class.getDeclaredMethods()) { - countTest(); - assertSame("foo", m.getName()); - if (verbosity > 3) - System.out.println("calling "+m); - MethodHandle invoker = lookup.unreflect(m); - MethodType mt = invoker.type(); - Class[] types = mt.parameterArray(); - types[0] = int.class; // placeholder - Object[] args = randomArgs(types); - args[0] = proxy; - if (verbosity > 3) - System.out.println("calling "+m+" on "+Arrays.asList(args)); - Object result = invoker.invokeWithArguments(args); - if (verbosity > 4) - System.out.println("result = "+result); - String name = "fooForFooable/"+args[1]; - Object[] argTail = Arrays.copyOfRange(args, 2, args.length); - assertCalled(name, argTail); - assertEquals(result, logEntry(name, argTail)); - } - } - // test processing of thrown exceptions: - for (Throwable ex : new Throwable[] { new NullPointerException("ok"), - new InternalError("ok"), - new Throwable("fail"), - new Exception("fail"), - new MyCheckedException() - }) { - MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class); - mh = MethodHandles.insertArguments(mh, 0, ex); - WillThrow proxy = MethodHandleProxies.asInterfaceInstance(WillThrow.class, mh); - try { - countTest(); - proxy.willThrow(); - System.out.println("Failed to throw: "+ex); - assertTrue(false); - } catch (Throwable ex1) { - if (verbosity > 3) { - System.out.println("throw "+ex); - System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1)); - } - if (ex instanceof RuntimeException || - ex instanceof Error) { - assertSame("must pass unchecked exception out without wrapping", ex, ex1); - } else if (ex instanceof MyCheckedException) { - assertSame("must pass declared exception out without wrapping", ex, ex1); - } else { - assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1); - if (!(ex1 instanceof UndeclaredThrowableException) || ex1.getCause() != ex) { - ex1.printStackTrace(System.out); - } - assertSame(ex, ex1.getCause()); - UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1; - } - } - } - // Test error checking on bad interfaces: - for (Class nonSMI : new Class[] { Object.class, - String.class, - CharSequence.class, - java.io.Serializable.class, - PrivateRunnable.class, - Example.class }) { - if (verbosity > 2) System.out.println(nonSMI.getName()); - try { - countTest(false); - MethodHandleProxies.asInterfaceInstance(nonSMI, varargsArray(0)); - assertTrue("Failed to throw on "+nonSMI.getName(), false); - } catch (IllegalArgumentException ex) { - if (verbosity > 2) System.out.println(nonSMI.getSimpleName()+": "+ex); - // Object: java.lang.IllegalArgumentException: - // not a public interface: java.lang.Object - // String: java.lang.IllegalArgumentException: - // not a public interface: java.lang.String - // CharSequence: java.lang.IllegalArgumentException: - // not a single-method interface: java.lang.CharSequence - // Serializable: java.lang.IllegalArgumentException: - // not a single-method interface: java.io.Serializable - // PrivateRunnable: java.lang.IllegalArgumentException: - // not a public interface: test.java.lang.invoke.MethodHandlesTest$PrivateRunnable - // Example: java.lang.IllegalArgumentException: - // not a public interface: test.java.lang.invoke.MethodHandlesTest$Example - } - } - // Test error checking on interfaces with the wrong method type: - for (Class intfc : new Class[] { Runnable.class /*arity 0*/, - Fooable.class /*arity 1 & 2*/ }) { - int badArity = 1; // known to be incompatible - if (verbosity > 2) System.out.println(intfc.getName()); - try { - countTest(false); - MethodHandleProxies.asInterfaceInstance(intfc, varargsArray(badArity)); - assertTrue("Failed to throw on "+intfc.getName(), false); - } catch (WrongMethodTypeException ex) { - if (verbosity > 2) System.out.println(intfc.getSimpleName()+": "+ex); - // Runnable: java.lang.invoke.WrongMethodTypeException: - // cannot convert MethodHandle(Object)Object[] to ()void - // Fooable: java.lang.invoke.WrongMethodTypeException: - // cannot convert MethodHandle(Object)Object[] to (Object,String)Object - } - } - } - - @Test - public void testRunnableProxy() throws Throwable { - CodeCacheOverflowProcessor.runMHTest(this::testRunnableProxy0); - } - - public void testRunnableProxy0() throws Throwable { - if (CAN_SKIP_WORKING) return; - startTest("testRunnableProxy"); - MethodHandles.Lookup lookup = MethodHandles.lookup(); - MethodHandle run = lookup.findStatic(lookup.lookupClass(), "runForRunnable", MethodType.methodType(void.class)); - Runnable r = MethodHandleProxies.asInterfaceInstance(Runnable.class, run); - testRunnableProxy(r); - assertCalled("runForRunnable"); - } - private static void testRunnableProxy(Runnable r) { - //7058630: JSR 292 method handle proxy violates contract for Object methods - r.run(); - Object o = r; - r = null; - boolean eq = (o == o); - int hc = System.identityHashCode(o); - String st = o.getClass().getName() + "@" + Integer.toHexString(hc); - Object expect = Arrays.asList(st, eq, hc); - if (verbosity >= 2) System.out.println("expect st/eq/hc = "+expect); - Object actual = Arrays.asList(o.toString(), o.equals(o), o.hashCode()); - if (verbosity >= 2) System.out.println("actual st/eq/hc = "+actual); - assertEquals(expect, actual); - } } // Local abbreviated copy of sun.invoke.util.ValueConversions // This guy tests access from outside the same package member, but inside @@ -3521,6 +806,7 @@ class ValueConversions { Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + static MethodHandle[] makeArrays() { ArrayList arrays = new ArrayList<>(); MethodHandles.Lookup lookup = IMPL_LOOKUP; @@ -3540,6 +826,7 @@ class ValueConversions { assertTrue(arrays.size() == 11); // current number of methods return arrays.toArray(new MethodHandle[0]); } + static final MethodHandle[] ARRAYS = makeArrays(); /** Return a method handle that takes the indicated number of Object @@ -3550,6 +837,7 @@ class ValueConversions { return ARRAYS[nargs]; return MethodHandles.identity(Object[].class).asCollector(Object[].class, nargs); } + public static MethodHandle varargsArray(Class arrayType, int nargs) { Class elemType = arrayType.getComponentType(); MethodType vaType = MethodType.methodType(arrayType, Collections.>nCopies(nargs, elemType)); @@ -3558,6 +846,7 @@ class ValueConversions { mh = MethodHandles.filterReturnValue(mh, CHANGE_ARRAY_TYPE.bindTo(arrayType)); return mh.asType(vaType); } + static Object changeArrayType(Class arrayType, Object[] a) { Class elemType = arrayType.getComponentType(); if (!elemType.isPrimitive()) @@ -3567,6 +856,7 @@ class ValueConversions { java.lang.reflect.Array.set(b, i, a[i]); return b; } + private static final MethodHandle CHANGE_ARRAY_TYPE; static { try { @@ -3610,6 +900,7 @@ class ValueConversions { Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + static MethodHandle[] makeLists() { ArrayList lists = new ArrayList<>(); MethodHandles.Lookup lookup = IMPL_LOOKUP; @@ -3629,8 +920,10 @@ class ValueConversions { assertTrue(lists.size() == 11); // current number of methods return lists.toArray(new MethodHandle[0]); } + static final MethodHandle[] LISTS = makeLists(); static final MethodHandle AS_LIST; + static { try { AS_LIST = IMPL_LOOKUP.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class)); From 1ea9f48936f9bff921028d4c547dd10dec1995a9 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 7 May 2018 20:42:36 +0200 Subject: [PATCH 24/40] 8185034: Cleanup and consolidate Metaspace coding Reviewed-by: coleenp, zgu --- src/hotspot/share/memory/metaspace.cpp | 31 -------------------------- 1 file changed, 31 deletions(-) diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index f400c01e230..3a489f3d5ad 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -245,7 +245,6 @@ class ChunkManager : public CHeapObj { locked_verify_free_chunks_count(); } } - void verify_free_chunks_count(); // Given a pointer to a chunk, attempts to merge it with neighboring // free chunks to form a bigger chunk. Returns true if successful. @@ -368,13 +367,10 @@ class ChunkManager : public CHeapObj { locked_verify(); } } - void verify_free_chunks_total(); void locked_print_free_chunks(outputStream* st); void locked_print_sum_free_chunks(outputStream* st); - void print_on(outputStream* st) const; - // Fill in current statistic values to the given statistics object. void collect_statistics(ChunkManagerStatistics* out) const; @@ -1705,7 +1701,6 @@ Metachunk* VirtualSpaceNode::take_from_committed(size_t chunk_word_size) { ls.print("VirtualSpaceNode::take_from_committed() not available " SIZE_FORMAT " words ", chunk_word_size); // Dump some information about the virtual space that is nearly full print_on(&ls); - ls.cr(); // ~LogStream does not autoflush. } return NULL; } @@ -2221,7 +2216,6 @@ void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry) { VirtualSpaceNode* vsl = current_virtual_space(); ResourceMark rm; vsl->print_on(&ls); - ls.cr(); // ~LogStream does not autoflush. } } @@ -2710,12 +2704,6 @@ void ChunkManager::locked_verify_free_chunks_total() { sum_free_chunks()); } -void ChunkManager::verify_free_chunks_total() { - MutexLockerEx cl(MetaspaceExpand_lock, - Mutex::_no_safepoint_check_flag); - locked_verify_free_chunks_total(); -} - void ChunkManager::locked_verify_free_chunks_count() { assert_lock_strong(MetaspaceExpand_lock); assert(sum_free_chunks_count() == _free_chunks_count, @@ -2724,14 +2712,6 @@ void ChunkManager::locked_verify_free_chunks_count() { sum_free_chunks_count()); } -void ChunkManager::verify_free_chunks_count() { -#ifdef ASSERT - MutexLockerEx cl(MetaspaceExpand_lock, - Mutex::_no_safepoint_check_flag); - locked_verify_free_chunks_count(); -#endif -} - void ChunkManager::verify() { MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); @@ -3041,7 +3021,6 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { p2i(this), p2i(chunk), chunk->word_size(), list_count); ResourceMark rm; locked_print_free_chunks(&ls); - ls.cr(); // ~LogStream does not autoflush. } return chunk; @@ -3132,10 +3111,6 @@ void ChunkManager::return_chunk_list(ChunkIndex index, Metachunk* chunks) { } } -void ChunkManager::print_on(outputStream* out) const { - _humongous_dictionary.report_statistics(out); -} - void ChunkManager::collect_statistics(ChunkManagerStatistics* out) const { MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { @@ -3220,7 +3195,6 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { } chunk_manager()->locked_print_free_chunks(st); - chunk_manager()->locked_print_sum_free_chunks(st); } size_t SpaceManager::calc_chunk_size(size_t word_size) { @@ -3418,7 +3392,6 @@ SpaceManager::~SpaceManager() { if (block_freelists() != NULL) { block_freelists()->print_on(&ls); } - ls.cr(); // ~LogStream does not autoflush. } // Add all the chunks in use by this space manager @@ -3487,7 +3460,6 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) { LogStream ls(log.trace()); new_chunk->print_on(&ls); chunk_manager()->locked_print_free_chunks(&ls); - ls.cr(); // ~LogStream does not autoflush. } } @@ -4441,7 +4413,6 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a ResourceMark rm; LogStream ls(lt); print_compressed_class_space(&ls, requested_addr); - ls.cr(); // ~LogStream does not autoflush. } } @@ -4663,13 +4634,11 @@ void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_s if (loader_data->metaspace_or_null() != NULL) { LogStream ls(log.debug()); loader_data->print_value_on(&ls); - ls.cr(); // ~LogStream does not autoflush. } } LogStream ls(log.info()); // In case of an OOM, log out a short but still useful report. MetaspaceUtils::print_basic_report(&ls, 0); - ls.cr(); // ~LogStream does not autoflush. } bool out_of_compressed_class_space = false; From e48f38966be8ad6a401d28c7c0de3512a0b4d813 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 26 Apr 2018 13:40:58 -0700 Subject: [PATCH 25/40] 8197954: Remove unnecessary intermediary APIs from AppCDS implementation Reviewed-by: jiangli, ccheung --- .../share/classfile/classListParser.cpp | 1 - src/hotspot/share/classfile/classLoader.cpp | 12 +- src/hotspot/share/classfile/classLoader.hpp | 2 - .../share/classfile/classLoaderExt.cpp | 10 +- .../share/classfile/classLoaderExt.hpp | 67 +---- src/hotspot/share/classfile/dictionary.cpp | 1 - src/hotspot/share/classfile/klassFactory.cpp | 2 +- .../share/classfile/sharedClassUtil.cpp | 255 ------------------ .../share/classfile/sharedClassUtil.hpp | 141 ---------- .../share/classfile/sharedPathsMiscInfo.cpp | 36 ++- .../share/classfile/sharedPathsMiscInfo.hpp | 44 ++- .../share/classfile/systemDictionary.cpp | 1 - .../share/classfile/systemDictionary.hpp | 5 +- .../classfile/systemDictionaryShared.cpp | 49 ++-- .../share/classfile/systemDictionary_ext.hpp | 41 --- src/hotspot/share/memory/filemap.cpp | 130 ++++++++- src/hotspot/share/memory/filemap.hpp | 37 ++- src/hotspot/share/memory/metaspaceShared.cpp | 41 ++- src/hotspot/share/memory/metaspaceShared.hpp | 4 + src/hotspot/share/memory/universe.cpp | 5 +- src/hotspot/share/oops/klass.hpp | 1 - src/hotspot/share/prims/jvm.cpp | 1 - 22 files changed, 294 insertions(+), 592 deletions(-) delete mode 100644 src/hotspot/share/classfile/sharedClassUtil.cpp delete mode 100644 src/hotspot/share/classfile/sharedClassUtil.hpp delete mode 100644 src/hotspot/share/classfile/systemDictionary_ext.hpp diff --git a/src/hotspot/share/classfile/classListParser.cpp b/src/hotspot/share/classfile/classListParser.cpp index 43107ee426e..dd21405df70 100644 --- a/src/hotspot/share/classfile/classListParser.cpp +++ b/src/hotspot/share/classfile/classListParser.cpp @@ -27,7 +27,6 @@ #include "jimage.hpp" #include "classfile/classListParser.hpp" #include "classfile/classLoaderExt.hpp" -#include "classfile/sharedClassUtil.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 82a51fb982f..4bc7480d02e 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -72,7 +72,6 @@ #include "utilities/hashtable.inline.hpp" #include "utilities/macros.hpp" #if INCLUDE_CDS -#include "classfile/sharedClassUtil.hpp" #include "classfile/sharedPathsMiscInfo.hpp" #endif @@ -660,7 +659,7 @@ void* ClassLoader::get_shared_paths_misc_info() { } bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) { - SharedPathsMiscInfo* checker = SharedClassUtil::allocate_shared_paths_misc_info((char*)buf, size); + SharedPathsMiscInfo* checker = new SharedPathsMiscInfo((char*)buf, size); bool result = checker->check(); delete checker; return result; @@ -1406,8 +1405,6 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR name->utf8_length()); assert(file_name != NULL, "invariant"); - ClassLoaderExt::Context context(class_name, file_name, THREAD); - // Lookup stream for parsing .class file ClassFileStream* stream = NULL; s2 classpath_index = 0; @@ -1480,7 +1477,7 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR return NULL; } - stream->set_verify(context.should_verify(classpath_index)); + stream->set_verify(ClassLoaderExt::should_verify(classpath_index)); ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); Handle protection_domain; @@ -1628,8 +1625,7 @@ void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream ik->name()->utf8_length()); assert(file_name != NULL, "invariant"); - ClassLoaderExt::Context context(class_name, file_name, CATCH); - context.record_result(ik->name(), classpath_index, ik, THREAD); + ClassLoaderExt::record_result(classpath_index, ik, THREAD); } #endif // INCLUDE_CDS @@ -1699,7 +1695,7 @@ void ClassLoader::initialize() { #if INCLUDE_CDS // initialize search path if (DumpSharedSpaces) { - _shared_paths_misc_info = SharedClassUtil::allocate_shared_paths_misc_info(); + _shared_paths_misc_info = new SharedPathsMiscInfo(); } #endif setup_bootstrap_search_path(); diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index ac6ca416f96..b9eb2405035 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -426,8 +426,6 @@ class ClassLoader: AllStatic { static int get_shared_paths_misc_info_size(); static void* get_shared_paths_misc_info(); static bool check_shared_paths_misc_info(void* info, int size); - static int get_module_paths_misc_info_size(); - static void* get_module_paths_misc_info(); static void exit_with_path_failure(const char* error, const char* message); static char* skip_uri_protocol(char* source); static void record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS); diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp index b182e6e5d86..3b0c9237677 100644 --- a/src/hotspot/share/classfile/classLoaderExt.cpp +++ b/src/hotspot/share/classfile/classLoaderExt.cpp @@ -31,7 +31,6 @@ #include "classfile/classLoaderData.inline.hpp" #include "classfile/klassFactory.hpp" #include "classfile/modules.hpp" -#include "classfile/sharedClassUtil.hpp" #include "classfile/sharedPathsMiscInfo.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmSymbols.hpp" @@ -57,8 +56,7 @@ bool ClassLoaderExt::_has_platform_classes = false; void ClassLoaderExt::append_boot_classpath(ClassPathEntry* new_entry) { #if INCLUDE_CDS warning("Sharing is only supported for boot loader classes because bootstrap classpath has been appended"); - FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header(); - header->set_has_platform_or_app_classes(false); + FileMapInfo::current_info()->header()->set_has_platform_or_app_classes(false); #endif ClassLoader::add_to_boot_append_entries(new_entry); } @@ -228,11 +226,7 @@ void ClassLoaderExt::setup_search_paths() { ClassLoaderExt::setup_app_search_path(); } -Thread* ClassLoaderExt::Context::_dump_thread = NULL; - -void ClassLoaderExt::record_result(ClassLoaderExt::Context *context, - Symbol* class_name, - const s2 classpath_index, +void ClassLoaderExt::record_result(const s2 classpath_index, InstanceKlass* result, TRAPS) { assert(DumpSharedSpaces, "Sanity"); diff --git a/src/hotspot/share/classfile/classLoaderExt.hpp b/src/hotspot/share/classfile/classLoaderExt.hpp index a452acc4ed0..6863a69a177 100644 --- a/src/hotspot/share/classfile/classLoaderExt.hpp +++ b/src/hotspot/share/classfile/classLoaderExt.hpp @@ -29,74 +29,21 @@ #include "classfile/moduleEntry.hpp" #include "utilities/macros.hpp" -CDS_ONLY(class SharedPathsMiscInfoExt;) -CDS_ONLY(class ClassListParser;) +class ClassListParser; class ClassLoaderExt: public ClassLoader { // AllStatic public: enum SomeConstants { max_classpath_index = 0x7fff }; - // ClassLoaderExt::Context -- - // - // This is used by DumpSharedSpaces only - it enforces the same classloader - // delegation model as would be in run-time. I.e., - // + classes defined by the NULL class loader cannot load classes in the PLATFORM or APP paths. - // + classes defined by the PLATFORM class loader cannot load classes in the APP paths. - class Context { - static Thread* _dump_thread; - const char* _class_name; - const char* _file_name; - public: - const char* class_name() { - return _class_name; - } - const char* file_name() { - return _file_name; - } - - Context(const char* class_name, const char* file_name, TRAPS) { - _class_name = class_name; - _file_name = file_name; -#if INCLUDE_CDS - if (!DumpSharedSpaces && !UseSharedSpaces) { - // Must not modify _app_class_paths_start_index if we're not using CDS. - assert(_app_class_paths_start_index == ClassLoaderExt::max_classpath_index, "must be"); - } -#endif - } - - bool should_verify(int classpath_index) { - CDS_ONLY(return (classpath_index >= _app_class_paths_start_index);) - NOT_CDS(return false;) - } - - void record_result(Symbol* class_name, - const s2 classpath_index, - InstanceKlass* result, - TRAPS) { -#if INCLUDE_CDS - ClassLoaderExt::record_result(this, class_name, classpath_index, result, THREAD); -#endif - } - - ~Context() { -#if INCLUDE_CDS - if (!DumpSharedSpaces && !UseSharedSpaces) { - // Must not modify app_class_paths_start_index if we're not using CDS. - assert(_app_class_paths_start_index == ClassLoaderExt::max_classpath_index, "must be"); - } -#endif - } - }; // end ClassLoaderExt::Context private: #if INCLUDE_CDS static char* get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size); static void setup_app_search_path(); // Only when -Xshare:dump static void process_module_table(ModuleEntryTable* met, TRAPS); - static SharedPathsMiscInfoExt* shared_paths_misc_info() { - return (SharedPathsMiscInfoExt*)_shared_paths_misc_info; + static SharedPathsMiscInfo* shared_paths_misc_info() { + return (SharedPathsMiscInfo*)_shared_paths_misc_info; } // index of first app JAR in shared classpath entry table static jshort _app_class_paths_start_index; @@ -110,6 +57,10 @@ private: public: CDS_ONLY(static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates);) + static bool should_verify(int classpath_index) { + CDS_ONLY(return (classpath_index >= _app_class_paths_start_index);) + NOT_CDS(return false;) + } // Called by JVMTI code to add boot classpath static void append_boot_classpath(ClassPathEntry* new_entry); @@ -156,9 +107,7 @@ public: return _has_app_classes || _has_platform_classes; } - static void record_result(class ClassLoaderExt::Context *context, - Symbol* class_name, - const s2 classpath_index, + static void record_result(const s2 classpath_index, InstanceKlass* result, TRAPS); static InstanceKlass* load_class(Symbol* h_name, const char* path, TRAPS); static Klass* load_one_class(ClassListParser* parser, TRAPS); diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp index e6cab6a0ada..db35510398d 100644 --- a/src/hotspot/share/classfile/dictionary.cpp +++ b/src/hotspot/share/classfile/dictionary.cpp @@ -24,7 +24,6 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.inline.hpp" -#include "classfile/sharedClassUtil.hpp" #include "classfile/dictionary.inline.hpp" #include "classfile/protectionDomainCache.hpp" #include "classfile/systemDictionary.hpp" diff --git a/src/hotspot/share/classfile/klassFactory.cpp b/src/hotspot/share/classfile/klassFactory.cpp index 8e52c787260..474d7f8c66a 100644 --- a/src/hotspot/share/classfile/klassFactory.cpp +++ b/src/hotspot/share/classfile/klassFactory.cpp @@ -29,7 +29,7 @@ #include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/klassFactory.hpp" -#include "classfile/sharedClassUtil.hpp" +#include "memory/filemap.hpp" #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "prims/jvmtiEnvBase.hpp" diff --git a/src/hotspot/share/classfile/sharedClassUtil.cpp b/src/hotspot/share/classfile/sharedClassUtil.cpp deleted file mode 100644 index 0e215cbb353..00000000000 --- a/src/hotspot/share/classfile/sharedClassUtil.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2014, 2018, 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. - * - */ - -#include "precompiled.hpp" -#include "classfile/classLoader.hpp" -#include "classfile/classLoaderExt.hpp" -#include "classfile/dictionary.hpp" -#include "classfile/javaClasses.hpp" -#include "classfile/sharedClassUtil.hpp" -#include "classfile/stringTable.hpp" -#include "classfile/symbolTable.hpp" -#include "classfile/systemDictionary.hpp" -#include "classfile/systemDictionaryShared.hpp" -#include "memory/filemap.hpp" -#include "memory/metadataFactory.hpp" -#include "memory/resourceArea.hpp" -#include "oops/instanceKlass.hpp" -#include "runtime/arguments.hpp" -#include "runtime/java.hpp" -#include "runtime/os.inline.hpp" - -class ManifestStream: public ResourceObj { - private: - u1* _buffer_start; // Buffer bottom - u1* _buffer_end; // Buffer top (one past last element) - u1* _current; // Current buffer position - - public: - // Constructor - ManifestStream(u1* buffer, int length) : _buffer_start(buffer), - _current(buffer) { - _buffer_end = buffer + length; - } - - static bool is_attr(u1* attr, const char* name) { - return strncmp((const char*)attr, name, strlen(name)) == 0; - } - - static char* copy_attr(u1* value, size_t len) { - char* buf = NEW_RESOURCE_ARRAY(char, len + 1); - strncpy(buf, (char*)value, len); - buf[len] = 0; - return buf; - } - - // The return value indicates if the JAR is signed or not - bool check_is_signed() { - u1* attr = _current; - bool isSigned = false; - while (_current < _buffer_end) { - if (*_current == '\n') { - *_current = '\0'; - u1* value = (u1*)strchr((char*)attr, ':'); - if (value != NULL) { - assert(*(value+1) == ' ', "Unrecognized format" ); - if (strstr((char*)attr, "-Digest") != NULL) { - isSigned = true; - break; - } - } - *_current = '\n'; // restore - attr = _current + 1; - } - _current ++; - } - return isSigned; - } -}; - -void SharedPathsMiscInfoExt::print_path(outputStream* out, int type, const char* path) { - switch(type) { - case APP: - ClassLoader::trace_class_path("Expecting -Djava.class.path=", path); - break; - case MODULE: - ClassLoader::trace_class_path("Checking module path: ", path); - break; - default: - SharedPathsMiscInfo::print_path(out, type, path); - } -} - -bool SharedPathsMiscInfoExt::check(jint type, const char* path) { - - switch (type) { - case APP: - { - // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar - size_t len = strlen(path); - const char *appcp = Arguments::get_appclasspath(); - assert(appcp != NULL, "NULL app classpath"); - size_t appcp_len = strlen(appcp); - if (appcp_len < len) { - return fail("Run time APP classpath is shorter than the one at dump time: ", appcp); - } - ResourceMark rm; - char* tmp_path; - if (len == appcp_len) { - tmp_path = (char*)appcp; - } else { - tmp_path = NEW_RESOURCE_ARRAY(char, len + 1); - strncpy(tmp_path, appcp, len); - tmp_path[len] = 0; - } - if (os::file_name_strcmp(path, tmp_path) != 0) { - return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp); - } - if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) { - return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp); - } - } - break; - default: - return SharedPathsMiscInfo::check(type, path); - } - - return true; -} - -void SharedClassUtil::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* e, TRAPS) { - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)e; - ResourceMark rm(THREAD); - jint manifest_size; - bool isSigned; - - if (cpe->is_jar_file()) { - char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK); - if (manifest != NULL) { - ManifestStream* stream = new ManifestStream((u1*)manifest, - manifest_size); - isSigned = stream->check_is_signed(); - if (isSigned) { - ent->_is_signed = true; - } else { - // Copy the manifest into the shared archive - manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK); - Array* buf = MetadataFactory::new_array(loader_data, - manifest_size, - THREAD); - char* p = (char*)(buf->data()); - memcpy(p, manifest, manifest_size); - ent->set_manifest(buf); - ent->_is_signed = false; - } - } - } -} - -void SharedClassUtil::initialize(TRAPS) { - if (UseSharedSpaces) { - int size = FileMapInfo::get_number_of_shared_paths(); - if (size > 0) { - SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD); - FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header(); - ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index); - ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index); - } - } - - if (DumpSharedSpaces) { - if (SharedArchiveConfigFile) { - read_extra_data(SharedArchiveConfigFile, THREAD); - } - } -} - -void SharedClassUtil::read_extra_data(const char* filename, TRAPS) { - HashtableTextDump reader(filename); - reader.check_version("VERSION: 1.0"); - - while (reader.remain() > 0) { - int utf8_length; - int prefix_type = reader.scan_prefix(&utf8_length); - ResourceMark rm(THREAD); - char* utf8_buffer = NEW_RESOURCE_ARRAY(char, utf8_length); - reader.get_utf8(utf8_buffer, utf8_length); - - if (prefix_type == HashtableTextDump::SymbolPrefix) { - SymbolTable::new_symbol(utf8_buffer, utf8_length, THREAD); - } else{ - assert(prefix_type == HashtableTextDump::StringPrefix, "Sanity"); - utf8_buffer[utf8_length] = '\0'; - oop s = StringTable::intern(utf8_buffer, THREAD); - } - } -} - -bool SharedClassUtil::is_classpath_entry_signed(int classpath_index) { - assert(classpath_index >= 0, "Sanity"); - SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*) - FileMapInfo::shared_path(classpath_index); - return ent->_is_signed; -} - -void FileMapHeaderExt::populate(FileMapInfo* mapinfo, size_t alignment) { - FileMapInfo::FileMapHeader::populate(mapinfo, alignment); - - ClassLoaderExt::finalize_shared_paths_misc_info(); - _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index(); - _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index(); - - _verify_local = BytecodeVerificationLocal; - _verify_remote = BytecodeVerificationRemote; - _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes(); -} - -bool FileMapHeaderExt::validate() { - if (!FileMapInfo::FileMapHeader::validate()) { - return false; - } - - // This must be done after header validation because it might change the - // header data - const char* prop = Arguments::get_property("java.system.class.loader"); - if (prop != NULL) { - warning("Archived non-system classes are disabled because the " - "java.system.class.loader property is specified (value = \"%s\"). " - "To use archived non-system classes, this property must be not be set", prop); - _has_platform_or_app_classes = false; - } - - // For backwards compatibility, we don't check the verification setting - // if the archive only contains system classes. - if (_has_platform_or_app_classes && - ((!_verify_local && BytecodeVerificationLocal) || - (!_verify_remote && BytecodeVerificationRemote))) { - FileMapInfo::fail_continue("The shared archive file was created with less restrictive " - "verification setting than the current setting."); - return false; - } - - return true; -} diff --git a/src/hotspot/share/classfile/sharedClassUtil.hpp b/src/hotspot/share/classfile/sharedClassUtil.hpp deleted file mode 100644 index caccfce9deb..00000000000 --- a/src/hotspot/share/classfile/sharedClassUtil.hpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2014, 2018, 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. - * - */ - -#ifndef SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP -#define SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP - -#include "classfile/sharedPathsMiscInfo.hpp" -#include "memory/filemap.hpp" -#include "classfile/classLoaderExt.hpp" -#include "classfile/dictionary.hpp" -#include "classfile/systemDictionaryShared.hpp" -#include "oops/klass.hpp" - -class FileMapHeaderExt: public FileMapInfo::FileMapHeader { -public: - jshort _app_class_paths_start_index; // Index of first app classpath entry - jshort _app_module_paths_start_index; // Index of first module path entry - bool _verify_local; // BytecodeVerificationLocal setting - bool _verify_remote; // BytecodeVerificationRemote setting - bool _has_platform_or_app_classes; // Archive contains app classes - - FileMapHeaderExt() { - _has_platform_or_app_classes = true; - } - void set_has_platform_or_app_classes(bool v) { - _has_platform_or_app_classes = v; - } - bool has_platform_or_app_classes() { return _has_platform_or_app_classes; } - virtual void populate(FileMapInfo* mapinfo, size_t alignment); - virtual bool validate(); -}; - -// In addition to SharedPathsMiscInfo, the following information is also stored -// -// -// + The value of Arguments::get_appclasspath() used during dumping. -// -class SharedPathsMiscInfoExt : public SharedPathsMiscInfo { -private: - int _app_offset; -public: - enum { - APP = 5, - MODULE = 6 - }; - - virtual const char* type_name(int type) { - switch (type) { - case APP: return "APP"; - case MODULE: return "MODULE"; - default: return SharedPathsMiscInfo::type_name(type); - } - } - - virtual void print_path(outputStream* out, int type, const char* path); - - SharedPathsMiscInfoExt() : SharedPathsMiscInfo() { - _app_offset = 0; - } - SharedPathsMiscInfoExt(char* buf, int size) : SharedPathsMiscInfo(buf, size) { - _app_offset = 0; - } - - virtual bool check(jint type, const char* path); - - void add_app_classpath(const char* path) { - add_path(path, APP); - } - - void record_app_offset() { - _app_offset = get_used_bytes(); - } - void pop_app() { - _cur_ptr = _buf_start + _app_offset; - write_jint(0); - } -}; - -class SharedClassPathEntryExt: public SharedClassPathEntry { -public: - //Maniest attributes - bool _is_signed; - void set_manifest(Array* manifest) { - _manifest = manifest; - } -}; - -class SharedClassUtil : AllStatic { -public: - static SharedPathsMiscInfo* allocate_shared_paths_misc_info() { - return new SharedPathsMiscInfoExt(); - } - - static SharedPathsMiscInfo* allocate_shared_paths_misc_info(char* buf, int size) { - return new SharedPathsMiscInfoExt(buf, size); - } - - static FileMapInfo::FileMapHeader* allocate_file_map_header() { - return new FileMapHeaderExt(); - } - - static size_t file_map_header_size() { - return sizeof(FileMapHeaderExt); - } - - static size_t shared_class_path_entry_size() { - return sizeof(SharedClassPathEntryExt); - } - - static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS); - static void initialize(TRAPS); - -private: - static void read_extra_data(const char* filename, TRAPS); - -public: - static bool is_classpath_entry_signed(int classpath_index); -}; - -#endif // SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP diff --git a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp b/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp index 5cb57e40559..f8d1ba59b76 100644 --- a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp +++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp @@ -24,7 +24,6 @@ #include "precompiled.hpp" #include "classfile/classLoader.hpp" -#include "classfile/classLoaderData.inline.hpp" #include "classfile/sharedPathsMiscInfo.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" @@ -36,6 +35,7 @@ #include "utilities/ostream.hpp" SharedPathsMiscInfo::SharedPathsMiscInfo() { + _app_offset = 0; _buf_size = INITIAL_BUF_SIZE; _cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass); _allocated = true; @@ -89,12 +89,15 @@ bool SharedPathsMiscInfo::fail(const char* msg, const char* name) { void SharedPathsMiscInfo::print_path(outputStream* out, int type, const char* path) { switch (type) { - case BOOT: + case BOOT_PATH: out->print("Expecting BOOT path=%s", path); break; case NON_EXIST: out->print("Expecting that %s does not exist", path); break; + case APP_PATH: + ClassLoader::trace_class_path("Expecting -Djava.class.path=", path); + break; default: ShouldNotReachHere(); } @@ -139,7 +142,7 @@ bool SharedPathsMiscInfo::check() { bool SharedPathsMiscInfo::check(jint type, const char* path) { switch (type) { - case BOOT: + case BOOT_PATH: // In the future we should perform the check based on the content of the mapped archive. if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) { return fail("[BOOT classpath mismatch, actual =", Arguments::get_sysclasspath()); @@ -155,6 +158,33 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) { } } break; + case APP_PATH: + { + // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar + size_t len = strlen(path); + const char *appcp = Arguments::get_appclasspath(); + assert(appcp != NULL, "NULL app classpath"); + size_t appcp_len = strlen(appcp); + if (appcp_len < len) { + return fail("Run time APP classpath is shorter than the one at dump time: ", appcp); + } + ResourceMark rm; + char* tmp_path; + if (len == appcp_len) { + tmp_path = (char*)appcp; + } else { + tmp_path = NEW_RESOURCE_ARRAY(char, len + 1); + strncpy(tmp_path, appcp, len); + tmp_path[len] = 0; + } + if (os::file_name_strcmp(path, tmp_path) != 0) { + return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp); + } + if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) { + return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp); + } + } + break; default: return fail("Corrupted archive file header"); } diff --git a/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp b/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp index e5576156e67..6c4b0b84e9f 100644 --- a/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp +++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -35,8 +35,6 @@ class outputStream; // // + The values of Arguments::get_sysclasspath() used during dumping. // -// + The meta-index file(s) used during dumping (incl modification time and size) -// // + The class path elements specified during dumping but did not exist -- // these elements must also be specified at run time, and they also must not // exist at run time. @@ -53,6 +51,8 @@ class outputStream; // two situations. See below. class SharedPathsMiscInfo : public CHeapObj { +private: + int _app_offset; protected: char* _buf_start; char* _cur_ptr; @@ -67,7 +67,7 @@ protected: protected: static bool fail(const char* msg, const char* name = NULL); - virtual bool check(jint type, const char* path); + bool check(jint type, const char* path); public: enum { @@ -77,6 +77,7 @@ public: SharedPathsMiscInfo(); // This constructor is used when validating the misc info (during run time) SharedPathsMiscInfo(char *buff, int size) { + _app_offset = 0; _cur_ptr = _buf_start = buff; _end_ptr = _buf_start + size; _buf_size = size; @@ -100,8 +101,20 @@ public: // The path must exist, and must contain exactly files/dirs void add_boot_classpath(const char* path) { - add_path(path, BOOT); + add_path(path, BOOT_PATH); } + + void add_app_classpath(const char* path) { + add_path(path, APP_PATH); + } + void record_app_offset() { + _app_offset = get_used_bytes(); + } + void pop_app() { + _cur_ptr = _buf_start + _app_offset; + write_jint(0); + } + int write_jint(jint num) { write(&num, sizeof(num)); return 0; @@ -120,22 +133,24 @@ public: // reading -- +private: enum { - BOOT = 1, - NON_EXIST = 2 + BOOT_PATH = 1, + APP_PATH = 2, + NON_EXIST = 3 }; - virtual const char* type_name(int type) { + const char* type_name(int type) { switch (type) { - case BOOT: return "BOOT"; - case NON_EXIST: return "NON_EXIST"; - default: ShouldNotReachHere(); return "?"; + case BOOT_PATH: return "BOOT"; + case APP_PATH: return "APP"; + case NON_EXIST: return "NON_EXIST"; + default: ShouldNotReachHere(); return "?"; } } - virtual void print_path(outputStream* os, int type, const char* path); + void print_path(outputStream* os, int type, const char* path); - bool check(); bool read_jint(jint *ptr) { return read(ptr, sizeof(jint)); } @@ -145,6 +160,9 @@ public: bool read_time(time_t *ptr) { return read(ptr, sizeof(time_t)); } + +public: + bool check(); }; #endif // SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 184031a5ae7..dd72849caa2 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -84,7 +84,6 @@ #include "trace/tracing.hpp" #include "utilities/macros.hpp" #if INCLUDE_CDS -#include "classfile/sharedClassUtil.hpp" #include "classfile/systemDictionaryShared.hpp" #endif #if INCLUDE_JVMCI diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index dad6e754c24..3b53125ed66 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_HPP #include "classfile/classLoader.hpp" -#include "classfile/systemDictionary_ext.hpp" #include "jvmci/systemDictionary_jvmci.hpp" #include "oops/objArrayOop.hpp" #include "oops/symbol.hpp" @@ -186,6 +185,7 @@ class OopStorage; do_klass(File_klass, java_io_File, Pre ) \ do_klass(URL_klass, java_net_URL, Pre ) \ do_klass(Jar_Manifest_klass, java_util_jar_Manifest, Pre ) \ + do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders, Pre ) \ do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader, Pre ) \ do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader, Pre ) \ do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \ @@ -212,8 +212,6 @@ class OopStorage; do_klass(Integer_klass, java_lang_Integer, Pre ) \ do_klass(Long_klass, java_lang_Long, Pre ) \ \ - /* Extensions */ \ - WK_KLASSES_DO_EXT(do_klass) \ /* JVMCI classes. These are loaded on-demand. */ \ JVMCI_WK_KLASSES_DO(do_klass) \ \ @@ -223,7 +221,6 @@ class OopStorage; class SystemDictionary : AllStatic { friend class VMStructs; friend class SystemDictionaryHandles; - friend class SharedClassUtil; public: enum WKID { diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 84cb861e1ce..97562662beb 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -31,7 +31,6 @@ #include "classfile/compactHashtable.inline.hpp" #include "classfile/dictionary.hpp" #include "classfile/javaClasses.hpp" -#include "classfile/sharedClassUtil.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" @@ -92,7 +91,7 @@ Handle SystemDictionaryShared::get_shared_jar_manifest(int shared_path_index, TR Handle empty; Handle manifest ; if (shared_jar_manifest(shared_path_index) == NULL) { - SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)FileMapInfo::shared_path(shared_path_index); + SharedClassPathEntry* ent = FileMapInfo::shared_path(shared_path_index); long size = ent->manifest_size(); if (size <= 0) { return empty; // No manifest - return NULL handle @@ -303,8 +302,7 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK if (ik != NULL) { int index = ik->shared_classpath_index(); assert(index >= 0, "Sanity"); - SharedClassPathEntryExt* ent = - (SharedClassPathEntryExt*)FileMapInfo::shared_path(index); + SharedClassPathEntry* ent = FileMapInfo::shared_path(index); Symbol* class_name = ik->name(); if (ent->is_modules_image()) { @@ -476,41 +474,38 @@ bool SystemDictionaryShared::is_shared_class_visible_for_classloader( // [1] JVM_FindLoadedClass // [2] java.lang.ClassLoader.findLoadedClass0() // [3] java.lang.ClassLoader.findLoadedClass() -// [4] java.lang.ClassLoader.loadClass() -// [5] jdk.internal.loader.ClassLoaders$AppClassLoader_klass.loadClass() +// [4] jdk.internal.loader.BuiltinClassLoader.loadClassOrNull() +// [5] jdk.internal.loader.BuiltinClassLoader.loadClass() +// [6] jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(), or +// jdk.internal.loader.ClassLoaders$PlatformClassLoader.loadClass() // -// Because AppCDS supports only the PlatformClassLoader and AppClassLoader, we make the following -// assumptions (based on the JDK 8.0 source code): +// AppCDS supports fast class loading for these 2 built-in class loaders: +// jdk.internal.loader.ClassLoaders$PlatformClassLoader +// jdk.internal.loader.ClassLoaders$AppClassLoader +// with the following assumptions (based on the JDK core library source code): // -// [a] these two loaders use the default implementation of -// ClassLoader.loadClass(String name, boolean resolve), which -// [b] calls findLoadedClass(name), immediately followed by parent.loadClass(), -// immediately followed by findClass(name). -// [c] If the requested class is a shared class of the current class loader, parent.loadClass() -// always returns null, and -// [d] if AppCDS is not enabled, the class would be loaded by findClass() by decoding it from a -// JAR file and then parsed. +// [a] these two loaders use the BuiltinClassLoader.loadClassOrNull() to +// load the named class. +// [b] BuiltinClassLoader.loadClassOrNull() first calls findLoadedClass(name). +// [c] At this point, if we can find the named class inside the +// shared_dictionary, we can perform further checks (see +// is_shared_class_visible_for_classloader() to ensure that this class +// was loaded by the same class loader during dump time. // // Given these assumptions, we intercept the findLoadedClass() call to invoke // SystemDictionaryShared::find_or_load_shared_class() to load the shared class from -// the archive. The reasons are: -// -// + Because AppCDS is a commercial feature, we want to hide the implementation. There -// is currently no easy way to hide Java code, so we did it with native code. -// + Start-up is improved because we avoid decoding the JAR file, and avoid delegating -// to the parent (since we know the parent will not find this class). +// the archive for the 2 built-in class loaders. This way, +// we can improve start-up because we avoid decoding the classfile, +// and avoid delegating to the parent loader. // // NOTE: there's a lot of assumption about the Java code. If any of that change, this // needs to be redesigned. -// -// An alternative is to modify the Java code of AppClassLoader.loadClass(). -// + InstanceKlass* SystemDictionaryShared::find_or_load_shared_class( Symbol* name, Handle class_loader, TRAPS) { InstanceKlass* k = NULL; if (UseSharedSpaces) { - FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header(); - if (!header->has_platform_or_app_classes()) { + if (!FileMapInfo::current_info()->header()->has_platform_or_app_classes()) { return NULL; } diff --git a/src/hotspot/share/classfile/systemDictionary_ext.hpp b/src/hotspot/share/classfile/systemDictionary_ext.hpp deleted file mode 100644 index 6d257cd09e9..00000000000 --- a/src/hotspot/share/classfile/systemDictionary_ext.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2015, 2017 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. - * - */ - -#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP -#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP - -#if INCLUDE_CDS - -#define WK_KLASSES_DO_EXT(do_klass) \ - /* well-known classes */ \ - do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders, Pre ) \ - /*end*/ - -#else - -#define WK_KLASSES_DO_EXT(do_klass) - -#endif // INCLUDE_CDS - -#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP diff --git a/src/hotspot/share/memory/filemap.cpp b/src/hotspot/share/memory/filemap.cpp index 5af98f8833f..11ff652688d 100644 --- a/src/hotspot/share/memory/filemap.cpp +++ b/src/hotspot/share/memory/filemap.cpp @@ -25,8 +25,8 @@ #include "precompiled.hpp" #include "jvm.h" #include "classfile/classLoader.inline.hpp" +#include "classfile/classLoaderExt.hpp" #include "classfile/compactHashtable.inline.hpp" -#include "classfile/sharedClassUtil.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionaryShared.hpp" @@ -159,8 +159,9 @@ FileMapInfo::FileMapInfo() { memset((void*)this, 0, sizeof(FileMapInfo)); _file_offset = 0; _file_open = false; - _header = SharedClassUtil::allocate_file_map_header(); + _header = new FileMapHeader(); _header->_version = _invalid_version; + _header->_has_platform_or_app_classes = true; } FileMapInfo::~FileMapInfo() { @@ -172,10 +173,6 @@ void FileMapInfo::populate_header(size_t alignment) { _header->populate(this, alignment); } -size_t FileMapInfo::FileMapHeader::data_size() { - return SharedClassUtil::file_map_header_size() - sizeof(FileMapInfo::FileMapHeaderBase); -} - void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) { _magic = 0xf00baba2; _version = _current_version; @@ -198,6 +195,14 @@ void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment // JVM version string ... changes on each build. get_header_version(_jvm_ident); + + ClassLoaderExt::finalize_shared_paths_misc_info(); + _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index(); + _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index(); + + _verify_local = BytecodeVerificationLocal; + _verify_remote = BytecodeVerificationRemote; + _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes(); } void SharedClassPathEntry::init(const char* name, TRAPS) { @@ -278,7 +283,7 @@ void FileMapInfo::allocate_shared_path_table() { assert(jrt != NULL, "No modular java runtime image present when allocating the CDS classpath entry table"); - size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); // assert ( should be 8 byte aligned??) + size_t entry_size = sizeof(SharedClassPathEntry); // assert ( should be 8 byte aligned??) int num_boot_classpath_entries = ClassLoader::num_boot_classpath_entries(); int num_app_classpath_entries = ClassLoader::num_app_classpath_entries(); int num_module_path_entries = ClassLoader::num_module_path_entries(); @@ -299,7 +304,7 @@ void FileMapInfo::allocate_shared_path_table() { ent->init(cpe->name(), THREAD); if (cpe != jrt) { // No need to do jimage. EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. - SharedClassUtil::update_shared_classpath(cpe, ent, THREAD); + update_shared_classpath(cpe, ent, THREAD); } cpe = ClassLoader::get_next_boot_classpath_entry(cpe); i++; @@ -314,7 +319,7 @@ void FileMapInfo::allocate_shared_path_table() { SharedClassPathEntry* ent = shared_path(i); ent->init(acpe->name(), THREAD); EXCEPTION_MARK; - SharedClassUtil::update_shared_classpath(acpe, ent, THREAD); + update_shared_classpath(acpe, ent, THREAD); acpe = acpe->next(); i++; } @@ -326,7 +331,7 @@ void FileMapInfo::allocate_shared_path_table() { SharedClassPathEntry* ent = shared_path(i); ent->init(mpe->name(), THREAD); EXCEPTION_MARK; - SharedClassUtil::update_shared_classpath(mpe, ent, THREAD); + update_shared_classpath(mpe, ent, THREAD); mpe = mpe->next(); i++; } @@ -360,6 +365,84 @@ void FileMapInfo::check_nonempty_dir_in_shared_path_table() { } } +class ManifestStream: public ResourceObj { + private: + u1* _buffer_start; // Buffer bottom + u1* _buffer_end; // Buffer top (one past last element) + u1* _current; // Current buffer position + + public: + // Constructor + ManifestStream(u1* buffer, int length) : _buffer_start(buffer), + _current(buffer) { + _buffer_end = buffer + length; + } + + static bool is_attr(u1* attr, const char* name) { + return strncmp((const char*)attr, name, strlen(name)) == 0; + } + + static char* copy_attr(u1* value, size_t len) { + char* buf = NEW_RESOURCE_ARRAY(char, len + 1); + strncpy(buf, (char*)value, len); + buf[len] = 0; + return buf; + } + + // The return value indicates if the JAR is signed or not + bool check_is_signed() { + u1* attr = _current; + bool isSigned = false; + while (_current < _buffer_end) { + if (*_current == '\n') { + *_current = '\0'; + u1* value = (u1*)strchr((char*)attr, ':'); + if (value != NULL) { + assert(*(value+1) == ' ', "Unrecognized format" ); + if (strstr((char*)attr, "-Digest") != NULL) { + isSigned = true; + break; + } + } + *_current = '\n'; // restore + attr = _current + 1; + } + _current ++; + } + return isSigned; + } +}; + +void FileMapInfo::update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) { + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + ResourceMark rm(THREAD); + jint manifest_size; + bool isSigned; + + if (cpe->is_jar_file()) { + char* manifest = ClassLoaderExt::read_manifest(cpe, &manifest_size, CHECK); + if (manifest != NULL) { + ManifestStream* stream = new ManifestStream((u1*)manifest, + manifest_size); + isSigned = stream->check_is_signed(); + if (isSigned) { + ent->set_is_signed(true); + } else { + // Copy the manifest into the shared archive + manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK); + Array* buf = MetadataFactory::new_array(loader_data, + manifest_size, + THREAD); + char* p = (char*)(buf->data()); + memcpy(p, manifest, manifest_size); + ent->set_manifest(buf); + ent->set_is_signed(false); + } + } + } +} + + bool FileMapInfo::validate_shared_path_table() { assert(UseSharedSpaces, "runtime only"); @@ -368,14 +451,13 @@ bool FileMapInfo::validate_shared_path_table() { _shared_path_entry_size = _header->_shared_path_entry_size; _shared_path_table_size = _header->_shared_path_table_size; - FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header(); - int module_paths_start_index = header->_app_module_paths_start_index; + int module_paths_start_index = _header->_app_module_paths_start_index; // If the shared archive contain app or platform classes, validate all entries // in the shared path table. Otherwise, only validate the boot path entries (with // entry index < _app_class_paths_start_index). - int count = header->has_platform_or_app_classes() ? - _shared_path_table_size : header->_app_class_paths_start_index; + int count = _header->has_platform_or_app_classes() ? + _shared_path_table_size : _header->_app_class_paths_start_index; for (int i=0; i* _name; Array* _manifest; + bool _is_signed; public: void init(const char* name, TRAPS); @@ -70,6 +71,15 @@ public: int manifest_size() const { return (_manifest == NULL) ? 0 : _manifest->length(); } + void set_manifest(Array* manifest) { + _manifest = manifest; + } + void set_is_signed(bool s) { + _is_signed = s; + } + bool is_signed() { + return _is_signed; + } }; class FileMapInfo : public CHeapObj { @@ -97,13 +107,16 @@ private: public: struct FileMapHeaderBase : public CHeapObj { - virtual bool validate() = 0; - virtual void populate(FileMapInfo* info, size_t alignment) = 0; + // Need to put something here. Otherwise, in product build, because CHeapObj has no virtual + // methods, we would get sizeof(FileMapHeaderBase) == 1 with gcc. + intx _dummy; }; struct FileMapHeader : FileMapHeaderBase { // Use data() and data_size() to memcopy to/from the FileMapHeader. We need to // avoid read/writing the C++ vtable pointer. - static size_t data_size(); + static size_t data_size() { + return sizeof(FileMapHeader) - sizeof(FileMapInfo::FileMapHeaderBase); + } char* data() { return ((char*)this) + sizeof(FileMapHeaderBase); } @@ -146,7 +159,7 @@ public: // The _paths_misc_info is a variable-size structure that records "miscellaneous" // information during dumping. It is generated and validated by the - // SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp and sharedClassUtil.hpp for + // SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp for // detailed description. // // The _paths_misc_info data is stored as a byte array in the archive file header, @@ -172,10 +185,21 @@ public: size_t _shared_path_entry_size; Array* _shared_path_table; + jshort _app_class_paths_start_index; // Index of first app classpath entry + jshort _app_module_paths_start_index; // Index of first module path entry + bool _verify_local; // BytecodeVerificationLocal setting + bool _verify_remote; // BytecodeVerificationRemote setting + bool _has_platform_or_app_classes; // Archive contains app classes + + void set_has_platform_or_app_classes(bool v) { + _has_platform_or_app_classes = v; + } + bool has_platform_or_app_classes() { return _has_platform_or_app_classes; } + char* region_addr(int idx); - virtual bool validate(); - virtual void populate(FileMapInfo* info, size_t alignment); + bool validate(); + void populate(FileMapInfo* info, size_t alignment); int compute_crc(); }; @@ -274,6 +298,7 @@ public: static void allocate_shared_path_table(); static void check_nonempty_dir_in_shared_path_table(); bool validate_shared_path_table(); + static void update_shared_classpath(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS); static SharedClassPathEntry* shared_path(int index) { if (index < 0) { diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index 21893ce8cca..1c5106dd228 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -29,7 +29,6 @@ #include "classfile/dictionary.hpp" #include "classfile/loaderConstraints.hpp" #include "classfile/placeholders.hpp" -#include "classfile/sharedClassUtil.hpp" #include "classfile/symbolTable.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" @@ -323,6 +322,46 @@ void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() { _shared_rs.size(), p2i(_shared_rs.base())); } +// Called by universe_post_init() +void MetaspaceShared::post_initialize(TRAPS) { + if (UseSharedSpaces) { + int size = FileMapInfo::get_number_of_shared_paths(); + if (size > 0) { + SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD); + FileMapInfo::FileMapHeader* header = FileMapInfo::current_info()->header(); + ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index); + ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index); + } + } + + if (DumpSharedSpaces) { + if (SharedArchiveConfigFile) { + read_extra_data(SharedArchiveConfigFile, THREAD); + } + } +} + +void MetaspaceShared::read_extra_data(const char* filename, TRAPS) { + HashtableTextDump reader(filename); + reader.check_version("VERSION: 1.0"); + + while (reader.remain() > 0) { + int utf8_length; + int prefix_type = reader.scan_prefix(&utf8_length); + ResourceMark rm(THREAD); + char* utf8_buffer = NEW_RESOURCE_ARRAY(char, utf8_length); + reader.get_utf8(utf8_buffer, utf8_length); + + if (prefix_type == HashtableTextDump::SymbolPrefix) { + SymbolTable::new_symbol(utf8_buffer, utf8_length, THREAD); + } else{ + assert(prefix_type == HashtableTextDump::StringPrefix, "Sanity"); + utf8_buffer[utf8_length] = '\0'; + oop s = StringTable::intern(utf8_buffer, THREAD); + } + } +} + void MetaspaceShared::commit_shared_space_to(char* newtop) { assert(DumpSharedSpaces, "dump-time only"); char* base = _shared_rs.base(); diff --git a/src/hotspot/share/memory/metaspaceShared.hpp b/src/hotspot/share/memory/metaspaceShared.hpp index 1c851397478..2f28cb096d6 100644 --- a/src/hotspot/share/memory/metaspaceShared.hpp +++ b/src/hotspot/share/memory/metaspaceShared.hpp @@ -147,6 +147,7 @@ class MetaspaceShared : AllStatic { } static void initialize_dumptime_shared_and_meta_spaces() NOT_CDS_RETURN; static void initialize_runtime_shared_and_meta_spaces() NOT_CDS_RETURN; + static void post_initialize(TRAPS) NOT_CDS_RETURN; // Delta of this object from the bottom of the archive. static uintx object_delta(void* obj) { @@ -250,5 +251,8 @@ class MetaspaceShared : AllStatic { static void relocate_klass_ptr(oop o); static Klass* get_relocated_klass(Klass *k); + +private: + static void read_extra_data(const char* filename, TRAPS) NOT_CDS_RETURN; }; #endif // SHARE_VM_MEMORY_METASPACESHARED_HPP diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 8c0956df1d5..7deb13b8cf2 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -81,9 +81,6 @@ #include "utilities/macros.hpp" #include "utilities/ostream.hpp" #include "utilities/preserveException.hpp" -#if INCLUDE_CDS -#include "classfile/sharedClassUtil.hpp" -#endif // Known objects Klass* Universe::_boolArrayKlassObj = NULL; @@ -1094,7 +1091,7 @@ bool universe_post_init() { MemoryService::set_universe_heap(Universe::heap()); #if INCLUDE_CDS - SharedClassUtil::initialize(CHECK_false); + MetaspaceShared::post_initialize(CHECK_false); #endif return true; } diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 9136314fef7..e9af35aa69e 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -168,7 +168,6 @@ private: // in the open archive heap region when archiving java object is supported. CDS_JAVA_HEAP_ONLY(narrowOop _archived_mirror;) - friend class SharedClassUtil; protected: // Constructor diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 9eb7c9c2816..0b085493628 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -84,7 +84,6 @@ #include "utilities/macros.hpp" #include "utilities/utf8.hpp" #if INCLUDE_CDS -#include "classfile/sharedClassUtil.hpp" #include "classfile/systemDictionaryShared.hpp" #endif From 00223c1ca5fb815944478cbba4d31dcf9dd23253 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Mon, 7 May 2018 18:48:36 -0400 Subject: [PATCH 26/40] 8202606: Deprecate AllowNonVirtualCalls option Reviewed-by: hseigel, dholmes --- src/hotspot/share/runtime/arguments.cpp | 1 + test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 808fb8f9152..3ad5fc34a07 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -518,6 +518,7 @@ static SpecialFlag const special_jvm_flags[] = { { "PrintSafepointStatisticsTimeout", JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) }, { "PrintSafepointStatisticsCount",JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) }, { "AggressiveOpts", JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) }, + { "AllowNonVirtualCalls", JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() }, diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index c49996d4914..17900fbe0df 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -52,6 +52,7 @@ public class VMDeprecatedOptions { {"PrintSafepointStatisticsCount", "3"}, {"PrintSafepointStatisticsTimeout", "3"}, {"AggressiveOpts", "true"}, + {"AllowNonVirtualCalls", "true"}, // deprecated alias flags (see also aliased_jvm_flags): {"DefaultMaxRAMFraction", "4"}, From 8eb4c9db2a8a0472330d4832326c522ca0623928 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 7 May 2018 19:31:39 -0400 Subject: [PATCH 27/40] 8202686: Missing test case for 8200167 - final Object methods Reviewed-by: psandoz --- .../lang/invoke/SpecialInterfaceCall.java | 29 ++++++++++++++++++- .../lang/invoke/SpecialInterfaceCallI4.jasm | 8 +++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/lang/invoke/SpecialInterfaceCall.java b/test/jdk/java/lang/invoke/SpecialInterfaceCall.java index 8337aa72a87..a67546426c3 100644 --- a/test/jdk/java/lang/invoke/SpecialInterfaceCall.java +++ b/test/jdk/java/lang/invoke/SpecialInterfaceCall.java @@ -60,6 +60,12 @@ public class SpecialInterfaceCall { // to Object.toString String s = (String) mh_I1_toString_from_I2.invokeExact(i); } + // special case of invoking a final Object method via an interface + static void invokeSpecialObjectFinalMH(I2 i) throws Throwable { + // emulates invokespecial of I1.getClass on i, which resolves + // to Object.getClass + Class c = (Class) mh_I1_getClass_from_I2.invokeExact(i); + } } interface I3 extends I2 { // Must take an I3 here rather than I2 else we get @@ -70,11 +76,16 @@ public class SpecialInterfaceCall { mh_I2_pub_m_from_I3.invokeExact(i); } } - // This interface acts like I2 but we define a directInvoke method + // This interface acts like I2 but we define directInvoke* methods // that we will rewrite the bytecode of to use invokespecial // (see SpecialInterfaceCallI4.jasm). interface I4 extends I1 { static void invokeDirect(I4 i) { + // invokeSpecial Object.toString() + throw new Error("Class file for I4 is not overwritten"); + } + static void invokeDirectFinal(I4 i) { + // invokeSpecial Object.getClass() - final method throw new Error("Class file for I4 is not overwritten"); } } @@ -101,6 +112,10 @@ public class SpecialInterfaceCall { // This MH acts likes an invokespecial of I1.toString from I2 static final MethodHandle mh_I1_toString_from_I2; + + // This MH acts likes an invokespecial of I1.getClass from I2 + static final MethodHandle mh_I1_getClass_from_I2; + static { try { MethodType mt = MethodType.methodType(void.class); @@ -112,6 +127,9 @@ public class SpecialInterfaceCall { mt = MethodType.methodType(String.class); mh_I1_toString_from_I2 = lookup.findSpecial(I1.class, "toString", mt, I2.class); + mt = MethodType.methodType(Class.class); + mh_I1_getClass_from_I2 = lookup.findSpecial(I1.class, "getClass", mt, I2.class); + } catch (Throwable e) { throw new Error(e); } @@ -122,10 +140,15 @@ public class SpecialInterfaceCall { shouldNotThrow(() -> I2.invokeDirect(new C3())); shouldNotThrow(() -> I2.invokeSpecialMH(new C2())); shouldNotThrow(() -> I2.invokeSpecialMH(new C3())); + shouldNotThrow(() -> I2.invokeSpecialObjectMH(new C2())); + shouldNotThrow(() -> I2.invokeSpecialObjectMH(new C3())); + shouldNotThrow(() -> I2.invokeSpecialObjectFinalMH(new C2())); + shouldNotThrow(() -> I2.invokeSpecialObjectFinalMH(new C3())); shouldNotThrow(() -> I3.invokeSpecialMH(new C3())); shouldNotThrow(() -> I4.invokeDirect(new C4())); + shouldNotThrow(() -> I4.invokeDirectFinal(new C4())); } static void runNegativeTests() { @@ -145,8 +168,12 @@ public class SpecialInterfaceCall { shouldThrowICCE(() -> I3.invokeSpecialMH(unsafeCastI3(new C2()))); System.out.println("ICCE I4.invokeDirect C1"); shouldThrowIAE(() -> I4.invokeDirect(unsafeCastI4(new C1()))); + System.out.println("ICCE I4.invokeDirectFinal C1"); + shouldThrowIAE(() -> I4.invokeDirectFinal(unsafeCastI4(new C1()))); System.out.println("ICCE I2.invokeObjectMH C1"); shouldThrowICCE(() -> I2.invokeSpecialObjectMH(unsafeCastI2(new C1()))); + System.out.println("ICCE I2.invokeObjectFinalMH C1"); + shouldThrowICCE(() -> I2.invokeSpecialObjectFinalMH(unsafeCastI2(new C1()))); } diff --git a/test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm b/test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm index 87b60307a30..24a02ccd1ee 100644 --- a/test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm +++ b/test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm @@ -35,6 +35,14 @@ interface SpecialInterfaceCall$I4 implements SpecialInterfaceCall$I1 return; } + public static Method invokeDirectFinal:"(LSpecialInterfaceCall$I4;)V" + stack 1 locals 2 + { + aload_0; + invokespecial Method java/lang/Object.getClass:"()Ljava/lang/Class;"; + astore_1; + return; + } static abstract interface InnerClass I4=class SpecialInterfaceCall$I4 of class SpecialInterfaceCall; static abstract interface InnerClass I1=class SpecialInterfaceCall$I1 of class SpecialInterfaceCall; From b62fee051942d3de2b93aa18b46457f17e928ac1 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 7 May 2018 21:48:28 -0400 Subject: [PATCH 28/40] 8202744: Expired flag removal for JDK 11 Reviewed-by: coleenp, jiangli --- src/hotspot/share/runtime/arguments.cpp | 3 --- .../CommandLine/ObsoleteFlagErrorMessage.java | 12 ++++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 3ad5fc34a07..87b46e7f67e 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -527,9 +527,6 @@ static SpecialFlag const special_jvm_flags[] = { { "UnsyncloadClass", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) }, // -------------- Obsolete Flags - sorted by expired_in -------------- - { "ConvertSleepToYield", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) }, - { "ConvertYieldToSleep", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) }, - { "MinSleepInterval", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) }, { "CheckAssertionStatusDirectives",JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) }, { "PrintMallocFree", JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) }, { "PrintMalloc", JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) }, diff --git a/test/hotspot/jtreg/runtime/CommandLine/ObsoleteFlagErrorMessage.java b/test/hotspot/jtreg/runtime/CommandLine/ObsoleteFlagErrorMessage.java index 59d245548a5..f5a0077270f 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/ObsoleteFlagErrorMessage.java +++ b/test/hotspot/jtreg/runtime/CommandLine/ObsoleteFlagErrorMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8060449 8073989 + * @bug 8060449 8073989 8202744 * @summary Newly obsolete command line options should still give useful error messages when used improperly. * @modules java.base/jdk.internal.misc * @library /test/lib @@ -37,18 +37,18 @@ public class ObsoleteFlagErrorMessage { // Case 1: Newly obsolete flags with extra junk appended should not be treated as newly obsolete (8060449) ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-XX:ConvertSleepToYieldPlusJunk", "-version"); + "-XX:SafepointSpinBeforeYieldPlusJunk", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("Unrecognized VM option 'ConvertSleepToYieldPlusJunk'"); // Must identify bad option. + output.shouldContain("Unrecognized VM option 'SafepointSpinBeforeYieldPlusJunk'"); // Must identify bad option. output.shouldHaveExitValue(1); // Case 2: Newly obsolete flags should be recognized as newly obsolete (8073989) ProcessBuilder pb2 = ProcessTools.createJavaProcessBuilder( - "-XX:+ConvertSleepToYield", "-version"); + "-XX:+SafepointSpinBeforeYield", "-version"); OutputAnalyzer output2 = new OutputAnalyzer(pb2.start()); output2.shouldContain("Ignoring option").shouldContain("support was removed"); - output2.shouldContain("ConvertSleepToYield"); + output2.shouldContain("SafepointSpinBeforeYield"); } } From 71660417967e7fac84a7c3454dad30a47e67a904 Mon Sep 17 00:00:00 2001 From: Chris Yin Date: Tue, 8 May 2018 09:51:42 +0800 Subject: [PATCH 29/40] 8202690: jdk/jshell/ToolBasicTest.java failed in testOpenFileOverHttp() and testOpenLocalFileUrl() Reviewed-by: rfield, jlahoda --- .../jdk/internal/jshell/tool/JShellTool.java | 30 ++++++++++++++----- test/langtools/jdk/jshell/ToolBasicTest.java | 2 +- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 4f4bbff438e..9ccb4e8880e 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -42,6 +42,7 @@ import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; import java.net.MalformedURLException; import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.Charset; import java.nio.file.FileSystems; @@ -3000,19 +3001,34 @@ public class JShellTool implements MessageHandler { regenerateOnDeath = false; scanner = new Scanner(cmdin); } else { - Path path = toPathResolvingUserHome(filename); + Path path = null; + URL url = null; String resource; - if (Files.exists(path)) { + try { + path = toPathResolvingUserHome(filename); + } catch (InvalidPathException ipe) { + try { + url = new URL(filename); + if (url.getProtocol().equalsIgnoreCase("file")) { + path = Paths.get(url.toURI()); + } + } catch (MalformedURLException | URISyntaxException e) { + throw new FileNotFoundException(filename); + } + } + if (path != null && Files.exists(path)) { scanner = new Scanner(new FileReader(path.toString())); } else if ((resource = getResource(filename)) != null) { scanner = new Scanner(new StringReader(resource)); } else { - try { - var url = new URL(filename); - scanner = new Scanner(url.openStream()); - } catch (MalformedURLException mue) { - throw new FileNotFoundException(filename); + if (url == null) { + try { + url = new URL(filename); + } catch (MalformedURLException mue) { + throw new FileNotFoundException(filename); + } } + scanner = new Scanner(url.openStream()); } } try (var scannerIOContext = new ScannerIOContext(scanner)) { diff --git a/test/langtools/jdk/jshell/ToolBasicTest.java b/test/langtools/jdk/jshell/ToolBasicTest.java index 2a2a8a93237..37dce8268ec 100644 --- a/test/langtools/jdk/jshell/ToolBasicTest.java +++ b/test/langtools/jdk/jshell/ToolBasicTest.java @@ -501,7 +501,7 @@ public class ToolBasicTest extends ReplToolTesting { compiler.writeToFile(path, "int a = 10;int b = 20;int c = a + b;\n"); for (String s : new String[]{"/o", "/open"}) { test( - (a) -> assertCommand(a, s + " file://" + path.toString(), ""), + (a) -> assertCommand(a, s + " " + path.toUri(), ""), (a) -> assertCommand(a, "a", "a ==> 10"), (a) -> assertCommand(a, "b", "b ==> 20"), (a) -> assertCommand(a, "c", "c ==> 30") From 2dd9adbf249db16edaf2adb2814d665147352160 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Tue, 8 May 2018 12:37:39 +0800 Subject: [PATCH 30/40] 8202581: failure_handler: gather more environment information on macOS Reviewed-by: psandoz --- test/failure_handler/src/share/conf/mac.properties | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/failure_handler/src/share/conf/mac.properties b/test/failure_handler/src/share/conf/mac.properties index de14390fcb1..2371f2777c6 100644 --- a/test/failure_handler/src/share/conf/mac.properties +++ b/test/failure_handler/src/share/conf/mac.properties @@ -76,7 +76,9 @@ environment=\ system.dmesg system.sysctl \ process.ps process.top \ memory.vmstat \ - netstat.av netstat.aL netstat.m netstat.s + netstat.av netstat.aL netstat.m netstat.s \ + ifconfig \ + scutil.nwi scutil.proxy ################################################################################ users.current.app=id users.current.args=-a @@ -107,4 +109,11 @@ netstat.av.args=-av netstat.aL.args=-aL netstat.m.args=-m netstat.s.args=-s + +ifconfig.app=ifconfig +ifconfig.args=-a + +scutil.app=scutil +scutil.nwi.args=--nwi +scutil.proxy.args=--proxy ################################################################################ From 78bd2420972a481d9f75aa837c1bf8d296f9d5f8 Mon Sep 17 00:00:00 2001 From: Rachna Goel Date: Tue, 8 May 2018 11:49:42 +0530 Subject: [PATCH 31/40] 8191410: Unicode 10 Upgrade to Unicode 10 Reviewed-by: naoto, rriggs, igerasim --- .../CharacterData00.java.template | 30 +- .../CharacterData01.java.template | 9 +- make/data/unicodedata/PropList.txt | 275 +- make/data/unicodedata/Scripts.txt | 250 +- make/data/unicodedata/SpecialCasing.txt | 13 +- make/data/unicodedata/UnicodeData.txt | 2411 +- make/data/unicodedata/VERSION | 2 +- .../share/classes/java/lang/Character.java | 781 +- .../sun/text/normalizer/ICUBinary.java | 11 +- .../sun/text/normalizer/Norm2AllModes.java | 4 +- .../sun/text/normalizer/Normalizer2.java | 8 +- .../sun/text/normalizer/NormalizerImpl.java | 1123 +- .../share/classes/sun/text/resources/nfc.icu | Bin 34624 -> 35392 bytes .../share/classes/sun/text/resources/nfkc.icu | Bin 53552 -> 54304 bytes .../classes/sun/text/resources/nfkc_cf.icu | Bin 51040 -> 51936 bytes .../classes/sun/text/resources/ubidi.icu | Bin 23312 -> 24656 bytes .../classes/sun/text/resources/uprops.icu | Bin 117680 -> 126800 bytes .../classes/java/awt/font/NumericShaper.java | 84 +- test/jdk/java/lang/Character/Blocks.txt | 316 + test/jdk/java/lang/Character/CharCheck.java | 560 + test/jdk/java/lang/Character/CheckBlocks.java | 301 + .../jdk/java/lang/Character/CheckUnicode.java | 111 + .../lang/Character/DumpCharProperties.java | 72 + test/jdk/java/lang/Character/PropList.txt | 275 +- .../lang/Character/PropertyValueAliases.txt | 92 +- test/jdk/java/lang/Character/Scripts.txt | 250 +- .../jdk/java/lang/Character/SpecialCasing.txt | 281 + .../UnicodeBlock/OptimalMapSize.java | 10 +- .../lang/Character/UnicodeCasingTest.java | 177 + test/jdk/java/lang/Character/UnicodeData.txt | 31618 ++++++++++++++++ test/jdk/java/lang/Character/UnicodeSpec.java | 756 + test/jdk/java/lang/Character/charprop00.bin | Bin 0 -> 1048617 bytes test/jdk/java/lang/Character/charprop01.bin | Bin 0 -> 1048617 bytes test/jdk/java/lang/Character/charprop02.bin | Bin 0 -> 1048617 bytes test/jdk/java/lang/Character/charprop03.bin | Bin 0 -> 1048617 bytes test/jdk/java/lang/Character/charprop0E.bin | Bin 0 -> 1048617 bytes test/jdk/java/lang/Character/charprop0F.bin | Bin 0 -> 1048617 bytes test/jdk/java/lang/Character/charprop10.bin | Bin 0 -> 1048617 bytes .../java/lang/String/SpecialCasingTest.java | 354 + .../java/lang/String/UnicodeCasingTest.java | 233 + 40 files changed, 39358 insertions(+), 1049 deletions(-) create mode 100644 test/jdk/java/lang/Character/Blocks.txt create mode 100644 test/jdk/java/lang/Character/CharCheck.java create mode 100644 test/jdk/java/lang/Character/CheckBlocks.java create mode 100644 test/jdk/java/lang/Character/CheckUnicode.java create mode 100644 test/jdk/java/lang/Character/DumpCharProperties.java create mode 100644 test/jdk/java/lang/Character/SpecialCasing.txt create mode 100644 test/jdk/java/lang/Character/UnicodeCasingTest.java create mode 100644 test/jdk/java/lang/Character/UnicodeData.txt create mode 100644 test/jdk/java/lang/Character/UnicodeSpec.java create mode 100644 test/jdk/java/lang/Character/charprop00.bin create mode 100644 test/jdk/java/lang/Character/charprop01.bin create mode 100644 test/jdk/java/lang/Character/charprop02.bin create mode 100644 test/jdk/java/lang/Character/charprop03.bin create mode 100644 test/jdk/java/lang/Character/charprop0E.bin create mode 100644 test/jdk/java/lang/Character/charprop0F.bin create mode 100644 test/jdk/java/lang/Character/charprop10.bin create mode 100644 test/jdk/java/lang/String/SpecialCasingTest.java create mode 100644 test/jdk/java/lang/String/UnicodeCasingTest.java diff --git a/make/data/characterdata/CharacterData00.java.template b/make/data/characterdata/CharacterData00.java.template index 6183fb5eaad..7628ab834b6 100644 --- a/make/data/characterdata/CharacterData00.java.template +++ b/make/data/characterdata/CharacterData00.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -139,6 +139,12 @@ class CharacterData00 extends CharacterData { case 0x0130: mapChar = 0x0069; break; case 0x023A: mapChar = 0x2C65; break; case 0x023E: mapChar = 0x2C66; break; + case 0x0412: mapChar = 0x1C80; break; + case 0x0414: mapChar = 0x1C81; break; + case 0x041E: mapChar = 0x1C82; break; + case 0x0421: mapChar = 0x1C83; break; + case 0x042A: mapChar = 0x1C86; break; + case 0x0462: mapChar = 0x1C87; break; case 0x10A0: mapChar = 0x2D00; break; case 0x10A1: mapChar = 0x2D01; break; case 0x10A2: mapChar = 0x2D02; break; @@ -299,12 +305,14 @@ class CharacterData00 extends CharacterData { case 0x2C70: mapChar = 0x0252; break; case 0x2C7E: mapChar = 0x023F; break; case 0x2C7F: mapChar = 0x0240; break; + case 0xA64A: mapChar = 0x1C88; break; case 0xA77D: mapChar = 0x1D79; break; case 0xA78D: mapChar = 0x0265; break; case 0xA7AA: mapChar = 0x0266; break; case 0xA7AB: mapChar = 0x025C; break; case 0xA7AC: mapChar = 0x0261; break; case 0xA7AD: mapChar = 0x026C; break; + case 0xA7AE: mapChar = 0x026A; break; case 0xA7B0: mapChar = 0x029E; break; case 0xA7B1: mapChar = 0x0287; break; case 0xA7B2: mapChar = 0x029D; break; @@ -339,6 +347,7 @@ class CharacterData00 extends CharacterData { case 0x0261: mapChar = 0xA7AC; break; case 0x0265: mapChar = 0xA78D; break; case 0x0266: mapChar = 0xA7AA; break; + case 0x026A: mapChar = 0xA7AE; break; case 0x026B: mapChar = 0x2C62; break; case 0x026C: mapChar = 0xA7AD; break; case 0x0271: mapChar = 0x2C6E; break; @@ -346,6 +355,15 @@ class CharacterData00 extends CharacterData { case 0x0287: mapChar = 0xA7B1; break; case 0x029D: mapChar = 0xA7B2; break; case 0x029E: mapChar = 0xA7B0; break; + case 0x1C80: mapChar = 0x0412; break; + case 0x1C81: mapChar = 0x0414; break; + case 0x1C82: mapChar = 0x041E; break; + case 0x1C83: mapChar = 0x0421; break; + case 0x1C84: mapChar = 0x0422; break; + case 0x1C85: mapChar = 0x0422; break; + case 0x1C86: mapChar = 0x042A; break; + case 0x1C87: mapChar = 0x0462; break; + case 0x1C88: mapChar = 0xA64A; break; case 0x1D79: mapChar = 0xA77D; break; case 0x1D7D: mapChar = 0x2C63; break; case 0x1F80: mapChar = 0x1F88; break; @@ -715,6 +733,7 @@ class CharacterData00 extends CharacterData { case 0x0261: mapChar = 0xA7AC; break; case 0x0265: mapChar = 0xA78D; break; case 0x0266: mapChar = 0xA7AA; break; + case 0x026A: mapChar = 0xA7AE; break; case 0x026B: mapChar = 0x2C62; break; case 0x026C: mapChar = 0xA7AD; break; case 0x0271: mapChar = 0x2C6E; break; @@ -722,6 +741,15 @@ class CharacterData00 extends CharacterData { case 0x0287: mapChar = 0xA7B1; break; case 0x029D: mapChar = 0xA7B2; break; case 0x029E: mapChar = 0xA7B0; break; + case 0x1C80: mapChar = 0x0412; break; + case 0x1C81: mapChar = 0x0414; break; + case 0x1C82: mapChar = 0x041E; break; + case 0x1C83: mapChar = 0x0421; break; + case 0x1C84: mapChar = 0x0422; break; + case 0x1C85: mapChar = 0x0422; break; + case 0x1C86: mapChar = 0x042A; break; + case 0x1C87: mapChar = 0x0462; break; + case 0x1C88: mapChar = 0xA64A; break; case 0x1D79: mapChar = 0xA77D; break; case 0x1D7D: mapChar = 0x2C63; break; case 0x1FBE: mapChar = 0x0399; break; diff --git a/make/data/characterdata/CharacterData01.java.template b/make/data/characterdata/CharacterData01.java.template index 8441de74815..f2a701dff69 100644 --- a/make/data/characterdata/CharacterData01.java.template +++ b/make/data/characterdata/CharacterData01.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -372,6 +372,13 @@ class CharacterData01 extends CharacterData { case 0x11063: retval = 90; break; // BRAHMI NUMBER NINETY case 0x11064: retval = 100; break; // BRAHMI NUMBER ONE HUNDRED case 0x11065: retval = 1000; break; // BRAHMI NUMBER ONE THOUSAND + case 0x11C66: retval = 40; break; // BHAIKSUKI NUMBER FORTY + case 0x11C67: retval = 50; break; // BHAIKSUKI NUMBER FIFTY + case 0x11C68: retval = 60; break; // BHAIKSUKI NUMBER SIXTY + case 0x11C69: retval = 70; break; // BHAIKSUKI NUMBER SEVENTY + case 0x11C6A: retval = 80; break; // BHAIKSUKI NUMBER EIGHTY + case 0x11C6B: retval = 90; break; // BHAIKSUKI NUMBER NINETY + case 0x11C6C: retval = 100; break; // BHAIKSUKI HUNDREDS UNIT MARK case 0x111ED: retval = 40; break; // SINHALA ARCHAIC NUMBER FORTY case 0x111EE: retval = 50; break; // SINHALA ARCHAIC NUMBER FIFTY case 0x111EF: retval = 60; break; // SINHALA ARCHAIC NUMBER SIXTY diff --git a/make/data/unicodedata/PropList.txt b/make/data/unicodedata/PropList.txt index 2eb2926e072..6df0b646fde 100644 --- a/make/data/unicodedata/PropList.txt +++ b/make/data/unicodedata/PropList.txt @@ -1,10 +1,11 @@ -# PropList-8.0.0.txt -# Date: 2015-05-16, 17:50:38 GMT [MD] +# PropList-10.0.0.txt +# Date: 2017-03-10, 08:25:30 GMT +# Copyright (c) 2017 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database -# Copyright (c) 1991-2015 Unicode, Inc. -# For terms of use, see http://www.unicode.org/terms_of_use.html -# For documentation, see http://www.unicode.org/reports/tr44/ +# For documentation, see http://www.unicode.org/reports/tr44/ # ================================================ @@ -192,10 +193,17 @@ FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA 111DE..111DF ; Terminal_Punctuation # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2 11238..1123C ; Terminal_Punctuation # Po [5] KHOJKI DANDA..KHOJKI DOUBLE SECTION MARK 112A9 ; Terminal_Punctuation # Po MULTANI SECTION MARK +1144B..1144D ; Terminal_Punctuation # Po [3] NEWA DANDA..NEWA COMMA +1145B ; Terminal_Punctuation # Po NEWA PLACEHOLDER MARK 115C2..115C5 ; Terminal_Punctuation # Po [4] SIDDHAM DANDA..SIDDHAM SEPARATOR BAR 115C9..115D7 ; Terminal_Punctuation # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES 11641..11642 ; Terminal_Punctuation # Po [2] MODI DANDA..MODI DOUBLE DANDA 1173C..1173E ; Terminal_Punctuation # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI +11A42..11A43 ; Terminal_Punctuation # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD +11A9B..11A9C ; Terminal_Punctuation # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD +11AA1..11AA2 ; Terminal_Punctuation # Po [2] SOYOMBO TERMINAL MARK-1..SOYOMBO TERMINAL MARK-2 +11C41..11C43 ; Terminal_Punctuation # Po [3] BHAIKSUKI DANDA..BHAIKSUKI WORD SEPARATOR +11C71 ; Terminal_Punctuation # Po MARCHEN MARK SHAD 12470..12474 ; Terminal_Punctuation # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON 16A6E..16A6F ; Terminal_Punctuation # Po [2] MRO DANDA..MRO DOUBLE DANDA 16AF5 ; Terminal_Punctuation # Po BASSA VAH FULL STOP @@ -204,7 +212,7 @@ FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA 1BC9F ; Terminal_Punctuation # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP 1DA87..1DA8A ; Terminal_Punctuation # Po [4] SIGNWRITING COMMA..SIGNWRITING COLON -# Total code points: 238 +# Total code points: 252 # ================================================ @@ -429,6 +437,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L 081B..0823 ; Other_Alphabetic # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A 0825..0827 ; Other_Alphabetic # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U 0829..082C ; Other_Alphabetic # Mn [4] SAMARITAN VOWEL SIGN LONG I..SAMARITAN VOWEL SIGN SUKUN +08D4..08DF ; Other_Alphabetic # Mn [12] ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH WORD WAQFA 08E3..08E9 ; Other_Alphabetic # Mn [7] ARABIC TURNED DAMMA BELOW..ARABIC CURLY KASRATAN 08F0..0902 ; Other_Alphabetic # Mn [19] ARABIC OPEN FATHATAN..DEVANAGARI SIGN ANUSVARA 0903 ; Other_Alphabetic # Mc DEVANAGARI SIGN VISARGA @@ -465,6 +474,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L 0AC9 ; Other_Alphabetic # Mc GUJARATI VOWEL SIGN CANDRA O 0ACB..0ACC ; Other_Alphabetic # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU 0AE2..0AE3 ; Other_Alphabetic # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL +0AFA..0AFC ; Other_Alphabetic # Mn [3] GUJARATI SIGN SUKUN..GUJARATI SIGN MADDAH 0B01 ; Other_Alphabetic # Mn ORIYA SIGN CANDRABINDU 0B02..0B03 ; Other_Alphabetic # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA 0B3E ; Other_Alphabetic # Mc ORIYA VOWEL SIGN AA @@ -502,7 +512,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L 0CCC ; Other_Alphabetic # Mn KANNADA VOWEL SIGN AU 0CD5..0CD6 ; Other_Alphabetic # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK 0CE2..0CE3 ; Other_Alphabetic # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL -0D01 ; Other_Alphabetic # Mn MALAYALAM SIGN CANDRABINDU +0D00..0D01 ; Other_Alphabetic # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU 0D02..0D03 ; Other_Alphabetic # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA 0D3E..0D40 ; Other_Alphabetic # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II 0D41..0D44 ; Other_Alphabetic # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR @@ -556,6 +566,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L 17BE..17C5 ; Other_Alphabetic # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU 17C6 ; Other_Alphabetic # Mn KHMER SIGN NIKAHIT 17C7..17C8 ; Other_Alphabetic # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU +1885..1886 ; Other_Alphabetic # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA 18A9 ; Other_Alphabetic # Mn MONGOLIAN LETTER ALI GALI DAGALGA 1920..1922 ; Other_Alphabetic # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U 1923..1926 ; Other_Alphabetic # Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU @@ -613,6 +624,7 @@ A825..A826 ; Other_Alphabetic # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NA A827 ; Other_Alphabetic # Mc SYLOTI NAGRI VOWEL SIGN OO A880..A881 ; Other_Alphabetic # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA A8B4..A8C3 ; Other_Alphabetic # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU +A8C5 ; Other_Alphabetic # Mn SAURASHTRA SIGN CANDRABINDU A926..A92A ; Other_Alphabetic # Mn [5] KAYAH LI VOWEL UE..KAYAH LI VOWEL O A947..A951 ; Other_Alphabetic # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R A952 ; Other_Alphabetic # Mc REJANG CONSONANT SIGN H @@ -671,6 +683,7 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA 11232..11233 ; Other_Alphabetic # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU 11234 ; Other_Alphabetic # Mn KHOJKI SIGN ANUSVARA 11237 ; Other_Alphabetic # Mn KHOJKI SIGN SHADDA +1123E ; Other_Alphabetic # Mn KHOJKI SIGN SUKUN 112DF ; Other_Alphabetic # Mn KHUDAWADI SIGN ANUSVARA 112E0..112E2 ; Other_Alphabetic # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II 112E3..112E8 ; Other_Alphabetic # Mn [6] KHUDAWADI VOWEL SIGN U..KHUDAWADI VOWEL SIGN AU @@ -683,6 +696,11 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA 1134B..1134C ; Other_Alphabetic # Mc [2] GRANTHA VOWEL SIGN OO..GRANTHA VOWEL SIGN AU 11357 ; Other_Alphabetic # Mc GRANTHA AU LENGTH MARK 11362..11363 ; Other_Alphabetic # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL +11435..11437 ; Other_Alphabetic # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II +11438..1143F ; Other_Alphabetic # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI +11440..11441 ; Other_Alphabetic # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU +11443..11444 ; Other_Alphabetic # Mn [2] NEWA SIGN CANDRABINDU..NEWA SIGN ANUSVARA +11445 ; Other_Alphabetic # Mc NEWA SIGN VISARGA 114B0..114B2 ; Other_Alphabetic # Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II 114B3..114B8 ; Other_Alphabetic # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL 114B9 ; Other_Alphabetic # Mc TIRHUTA VOWEL SIGN E @@ -712,14 +730,48 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA 11722..11725 ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU 11726 ; Other_Alphabetic # Mc AHOM VOWEL SIGN E 11727..1172A ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN AW..AHOM VOWEL SIGN AM +11A01..11A06 ; Other_Alphabetic # Mn [6] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL SIGN O +11A07..11A08 ; Other_Alphabetic # Mc [2] ZANABAZAR SQUARE VOWEL SIGN AI..ZANABAZAR SQUARE VOWEL SIGN AU +11A09..11A0A ; Other_Alphabetic # Mn [2] ZANABAZAR SQUARE VOWEL SIGN REVERSED I..ZANABAZAR SQUARE VOWEL LENGTH MARK +11A35..11A38 ; Other_Alphabetic # Mn [4] ZANABAZAR SQUARE SIGN CANDRABINDU..ZANABAZAR SQUARE SIGN ANUSVARA +11A39 ; Other_Alphabetic # Mc ZANABAZAR SQUARE SIGN VISARGA +11A3B..11A3E ; Other_Alphabetic # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA +11A51..11A56 ; Other_Alphabetic # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE +11A57..11A58 ; Other_Alphabetic # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU +11A59..11A5B ; Other_Alphabetic # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK +11A8A..11A96 ; Other_Alphabetic # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA +11A97 ; Other_Alphabetic # Mc SOYOMBO SIGN VISARGA +11C2F ; Other_Alphabetic # Mc BHAIKSUKI VOWEL SIGN AA +11C30..11C36 ; Other_Alphabetic # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L +11C38..11C3D ; Other_Alphabetic # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA +11C3E ; Other_Alphabetic # Mc BHAIKSUKI SIGN VISARGA +11C92..11CA7 ; Other_Alphabetic # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA +11CA9 ; Other_Alphabetic # Mc MARCHEN SUBJOINED LETTER YA +11CAA..11CB0 ; Other_Alphabetic # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA +11CB1 ; Other_Alphabetic # Mc MARCHEN VOWEL SIGN I +11CB2..11CB3 ; Other_Alphabetic # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E +11CB4 ; Other_Alphabetic # Mc MARCHEN VOWEL SIGN O +11CB5..11CB6 ; Other_Alphabetic # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU +11D31..11D36 ; Other_Alphabetic # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R +11D3A ; Other_Alphabetic # Mn MASARAM GONDI VOWEL SIGN E +11D3C..11D3D ; Other_Alphabetic # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O +11D3F..11D41 ; Other_Alphabetic # Mn [3] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI SIGN VISARGA +11D43 ; Other_Alphabetic # Mn MASARAM GONDI SIGN CANDRA +11D47 ; Other_Alphabetic # Mn MASARAM GONDI RA-KARA 16B30..16B36 ; Other_Alphabetic # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM 16F51..16F7E ; Other_Alphabetic # Mc [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG 1BC9E ; Other_Alphabetic # Mn DUPLOYAN DOUBLE MARK +1E000..1E006 ; Other_Alphabetic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE +1E008..1E018 ; Other_Alphabetic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU +1E01B..1E021 ; Other_Alphabetic # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI +1E023..1E024 ; Other_Alphabetic # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS +1E026..1E02A ; Other_Alphabetic # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA +1E947 ; Other_Alphabetic # Mn ADLAM HAMZA 1F130..1F149 ; Other_Alphabetic # So [26] SQUARED LATIN CAPITAL LETTER A..SQUARED LATIN CAPITAL LETTER Z 1F150..1F169 ; Other_Alphabetic # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z 1F170..1F189 ; Other_Alphabetic # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z -# Total code points: 1116 +# Total code points: 1300 # ================================================ @@ -728,16 +780,20 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA 3021..3029 ; Ideographic # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE 3038..303A ; Ideographic # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY 3400..4DB5 ; Ideographic # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5 -4E00..9FD5 ; Ideographic # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5 +4E00..9FEA ; Ideographic # Lo [20971] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEA F900..FA6D ; Ideographic # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 +17000..187EC ; Ideographic # Lo [6125] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187EC +18800..18AF2 ; Ideographic # Lo [755] TANGUT COMPONENT-001..TANGUT COMPONENT-755 +1B170..1B2FB ; Ideographic # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB 20000..2A6D6 ; Ideographic # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6 2A700..2B734 ; Ideographic # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 2B740..2B81D ; Ideographic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; Ideographic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 +2CEB0..2EBE0 ; Ideographic # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 2F800..2FA1D ; Ideographic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D -# Total code points: 81404 +# Total code points: 96174 # ================================================ @@ -793,12 +849,14 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM 0A4D ; Diacritic # Mn GURMUKHI SIGN VIRAMA 0ABC ; Diacritic # Mn GUJARATI SIGN NUKTA 0ACD ; Diacritic # Mn GUJARATI SIGN VIRAMA +0AFD..0AFF ; Diacritic # Mn [3] GUJARATI SIGN THREE-DOT NUKTA ABOVE..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE 0B3C ; Diacritic # Mn ORIYA SIGN NUKTA 0B4D ; Diacritic # Mn ORIYA SIGN VIRAMA 0BCD ; Diacritic # Mn TAMIL SIGN VIRAMA 0C4D ; Diacritic # Mn TELUGU SIGN VIRAMA 0CBC ; Diacritic # Mn KANNADA SIGN NUKTA 0CCD ; Diacritic # Mn KANNADA SIGN VIRAMA +0D3B..0D3C ; Diacritic # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA 0D4D ; Diacritic # Mn MALAYALAM SIGN VIRAMA 0DCA ; Diacritic # Mn SINHALA SIGN AL-LAKUNA 0E47..0E4C ; Diacritic # Mn [6] THAI CHARACTER MAITAIKHU..THAI CHARACTER THANTHAKHAT @@ -838,10 +896,11 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM 1CE2..1CE8 ; Diacritic # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL 1CED ; Diacritic # Mn VEDIC SIGN TIRYAK 1CF4 ; Diacritic # Mn VEDIC TONE CANDRA ABOVE +1CF7 ; Diacritic # Mc VEDIC SIGN ATIKRAMA 1CF8..1CF9 ; Diacritic # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE 1D2C..1D6A ; Diacritic # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI 1DC4..1DCF ; Diacritic # Mn [12] COMBINING MACRON-ACUTE..COMBINING ZIGZAG BELOW -1DF5 ; Diacritic # Mn COMBINING UP TACK ABOVE +1DF5..1DF9 ; Diacritic # Mn [5] COMBINING UP TACK ABOVE..COMBINING WIDE INVERTED BRIDGE BELOW 1DFD..1DFF ; Diacritic # Mn [3] COMBINING ALMOST EQUAL TO BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 1FBD ; Diacritic # Sk GREEK KORONIS 1FBF..1FC1 ; Diacritic # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI @@ -906,12 +965,20 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON 1134D ; Diacritic # Mc GRANTHA SIGN VIRAMA 11366..1136C ; Diacritic # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX 11370..11374 ; Diacritic # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA +11442 ; Diacritic # Mn NEWA SIGN VIRAMA +11446 ; Diacritic # Mn NEWA SIGN NUKTA 114C2..114C3 ; Diacritic # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA 115BF..115C0 ; Diacritic # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA 1163F ; Diacritic # Mn MODI SIGN VIRAMA 116B6 ; Diacritic # Mc TAKRI SIGN VIRAMA 116B7 ; Diacritic # Mn TAKRI SIGN NUKTA 1172B ; Diacritic # Mn AHOM SIGN KILLER +11A34 ; Diacritic # Mn ZANABAZAR SQUARE SIGN VIRAMA +11A47 ; Diacritic # Mn ZANABAZAR SQUARE SUBJOINER +11A99 ; Diacritic # Mn SOYOMBO SUBJOINER +11C3F ; Diacritic # Mn BHAIKSUKI SIGN VIRAMA +11D42 ; Diacritic # Mn MASARAM GONDI SIGN NUKTA +11D44..11D45 ; Diacritic # Mn [2] MASARAM GONDI SIGN HALANTA..MASARAM GONDI VIRAMA 16AF0..16AF4 ; Diacritic # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE 16F8F..16F92 ; Diacritic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW 16F93..16F9F ; Diacritic # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 @@ -921,8 +988,10 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON 1D185..1D18B ; Diacritic # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE 1D1AA..1D1AD ; Diacritic # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO 1E8D0..1E8D6 ; Diacritic # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS +1E944..1E946 ; Diacritic # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK +1E948..1E94A ; Diacritic # Mn [3] ADLAM CONSONANT MODIFIER..ADLAM NUKTA -# Total code points: 773 +# Total code points: 798 # ================================================ @@ -951,9 +1020,12 @@ AAF3..AAF4 ; Extender # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETE FF70 ; Extender # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK 1135D ; Extender # Lo GRANTHA SIGN PLUTA 115C6..115C8 ; Extender # Po [3] SIDDHAM REPETITION MARK-1..SIDDHAM REPETITION MARK-3 +11A98 ; Extender # Mn SOYOMBO GEMINATION MARK 16B42..16B43 ; Extender # Lm [2] PAHAWH HMONG SIGN VOS NRUA..PAHAWH HMONG SIGN IB YAM +16FE0..16FE1 ; Extender # Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK +1E944..1E946 ; Extender # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK -# Total code points: 38 +# Total code points: 44 # ================================================ @@ -1027,7 +1099,7 @@ FFFFE..FFFFF ; Noncharacter_Code_Point # Cn [2] ... 2329 ; Deprecated # Ps LEFT-POINTING ANGLE BRACKET 232A ; Deprecated # Pe RIGHT-POINTING ANGLE BRACKET E0001 ; Deprecated # Cf LANGUAGE TAG -E007F ; Deprecated # Cf CANCEL TAG -# Total code points: 16 +# Total code points: 15 # ================================================ @@ -1160,11 +1233,12 @@ AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET # ================================================ +1885..1886 ; Other_ID_Start # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA 2118 ; Other_ID_Start # Sm SCRIPT CAPITAL P 212E ; Other_ID_Start # So ESTIMATED SYMBOL 309B..309C ; Other_ID_Start # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK -# Total code points: 4 +# Total code points: 6 # ================================================ @@ -1177,72 +1251,76 @@ AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET # ================================================ -0021 ; STerm # Po EXCLAMATION MARK -002E ; STerm # Po FULL STOP -003F ; STerm # Po QUESTION MARK -0589 ; STerm # Po ARMENIAN FULL STOP -061F ; STerm # Po ARABIC QUESTION MARK -06D4 ; STerm # Po ARABIC FULL STOP -0700..0702 ; STerm # Po [3] SYRIAC END OF PARAGRAPH..SYRIAC SUBLINEAR FULL STOP -07F9 ; STerm # Po NKO EXCLAMATION MARK -0964..0965 ; STerm # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA -104A..104B ; STerm # Po [2] MYANMAR SIGN LITTLE SECTION..MYANMAR SIGN SECTION -1362 ; STerm # Po ETHIOPIC FULL STOP -1367..1368 ; STerm # Po [2] ETHIOPIC QUESTION MARK..ETHIOPIC PARAGRAPH SEPARATOR -166E ; STerm # Po CANADIAN SYLLABICS FULL STOP -1735..1736 ; STerm # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION -1803 ; STerm # Po MONGOLIAN FULL STOP -1809 ; STerm # Po MONGOLIAN MANCHU FULL STOP -1944..1945 ; STerm # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK -1AA8..1AAB ; STerm # Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU -1B5A..1B5B ; STerm # Po [2] BALINESE PANTI..BALINESE PAMADA -1B5E..1B5F ; STerm # Po [2] BALINESE CARIK SIKI..BALINESE CARIK PAREREN -1C3B..1C3C ; STerm # Po [2] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION NYET THYOOM TA-ROL -1C7E..1C7F ; STerm # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD -203C..203D ; STerm # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG -2047..2049 ; STerm # Po [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK -2E2E ; STerm # Po REVERSED QUESTION MARK -2E3C ; STerm # Po STENOGRAPHIC FULL STOP -3002 ; STerm # Po IDEOGRAPHIC FULL STOP -A4FF ; STerm # Po LISU PUNCTUATION FULL STOP -A60E..A60F ; STerm # Po [2] VAI FULL STOP..VAI QUESTION MARK -A6F3 ; STerm # Po BAMUM FULL STOP -A6F7 ; STerm # Po BAMUM QUESTION MARK -A876..A877 ; STerm # Po [2] PHAGS-PA MARK SHAD..PHAGS-PA MARK DOUBLE SHAD -A8CE..A8CF ; STerm # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA -A92F ; STerm # Po KAYAH LI SIGN SHYA -A9C8..A9C9 ; STerm # Po [2] JAVANESE PADA LINGSA..JAVANESE PADA LUNGSI -AA5D..AA5F ; STerm # Po [3] CHAM PUNCTUATION DANDA..CHAM PUNCTUATION TRIPLE DANDA -AAF0..AAF1 ; STerm # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM -ABEB ; STerm # Po MEETEI MAYEK CHEIKHEI -FE52 ; STerm # Po SMALL FULL STOP -FE56..FE57 ; STerm # Po [2] SMALL QUESTION MARK..SMALL EXCLAMATION MARK -FF01 ; STerm # Po FULLWIDTH EXCLAMATION MARK -FF0E ; STerm # Po FULLWIDTH FULL STOP -FF1F ; STerm # Po FULLWIDTH QUESTION MARK -FF61 ; STerm # Po HALFWIDTH IDEOGRAPHIC FULL STOP -10A56..10A57 ; STerm # Po [2] KHAROSHTHI PUNCTUATION DANDA..KHAROSHTHI PUNCTUATION DOUBLE DANDA -11047..11048 ; STerm # Po [2] BRAHMI DANDA..BRAHMI DOUBLE DANDA -110BE..110C1 ; STerm # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA -11141..11143 ; STerm # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK -111C5..111C6 ; STerm # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA -111CD ; STerm # Po SHARADA SUTRA MARK -111DE..111DF ; STerm # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2 -11238..11239 ; STerm # Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA -1123B..1123C ; STerm # Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK -112A9 ; STerm # Po MULTANI SECTION MARK -115C2..115C3 ; STerm # Po [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA -115C9..115D7 ; STerm # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES -11641..11642 ; STerm # Po [2] MODI DANDA..MODI DOUBLE DANDA -1173C..1173E ; STerm # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI -16A6E..16A6F ; STerm # Po [2] MRO DANDA..MRO DOUBLE DANDA -16AF5 ; STerm # Po BASSA VAH FULL STOP -16B37..16B38 ; STerm # Po [2] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS TSHAB CEEB -16B44 ; STerm # Po PAHAWH HMONG SIGN XAUS -1BC9F ; STerm # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP -1DA88 ; STerm # Po SIGNWRITING FULL STOP +0021 ; Sentence_Terminal # Po EXCLAMATION MARK +002E ; Sentence_Terminal # Po FULL STOP +003F ; Sentence_Terminal # Po QUESTION MARK +0589 ; Sentence_Terminal # Po ARMENIAN FULL STOP +061F ; Sentence_Terminal # Po ARABIC QUESTION MARK +06D4 ; Sentence_Terminal # Po ARABIC FULL STOP +0700..0702 ; Sentence_Terminal # Po [3] SYRIAC END OF PARAGRAPH..SYRIAC SUBLINEAR FULL STOP +07F9 ; Sentence_Terminal # Po NKO EXCLAMATION MARK +0964..0965 ; Sentence_Terminal # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA +104A..104B ; Sentence_Terminal # Po [2] MYANMAR SIGN LITTLE SECTION..MYANMAR SIGN SECTION +1362 ; Sentence_Terminal # Po ETHIOPIC FULL STOP +1367..1368 ; Sentence_Terminal # Po [2] ETHIOPIC QUESTION MARK..ETHIOPIC PARAGRAPH SEPARATOR +166E ; Sentence_Terminal # Po CANADIAN SYLLABICS FULL STOP +1735..1736 ; Sentence_Terminal # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION +1803 ; Sentence_Terminal # Po MONGOLIAN FULL STOP +1809 ; Sentence_Terminal # Po MONGOLIAN MANCHU FULL STOP +1944..1945 ; Sentence_Terminal # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK +1AA8..1AAB ; Sentence_Terminal # Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU +1B5A..1B5B ; Sentence_Terminal # Po [2] BALINESE PANTI..BALINESE PAMADA +1B5E..1B5F ; Sentence_Terminal # Po [2] BALINESE CARIK SIKI..BALINESE CARIK PAREREN +1C3B..1C3C ; Sentence_Terminal # Po [2] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION NYET THYOOM TA-ROL +1C7E..1C7F ; Sentence_Terminal # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD +203C..203D ; Sentence_Terminal # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG +2047..2049 ; Sentence_Terminal # Po [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK +2E2E ; Sentence_Terminal # Po REVERSED QUESTION MARK +2E3C ; Sentence_Terminal # Po STENOGRAPHIC FULL STOP +3002 ; Sentence_Terminal # Po IDEOGRAPHIC FULL STOP +A4FF ; Sentence_Terminal # Po LISU PUNCTUATION FULL STOP +A60E..A60F ; Sentence_Terminal # Po [2] VAI FULL STOP..VAI QUESTION MARK +A6F3 ; Sentence_Terminal # Po BAMUM FULL STOP +A6F7 ; Sentence_Terminal # Po BAMUM QUESTION MARK +A876..A877 ; Sentence_Terminal # Po [2] PHAGS-PA MARK SHAD..PHAGS-PA MARK DOUBLE SHAD +A8CE..A8CF ; Sentence_Terminal # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA +A92F ; Sentence_Terminal # Po KAYAH LI SIGN SHYA +A9C8..A9C9 ; Sentence_Terminal # Po [2] JAVANESE PADA LINGSA..JAVANESE PADA LUNGSI +AA5D..AA5F ; Sentence_Terminal # Po [3] CHAM PUNCTUATION DANDA..CHAM PUNCTUATION TRIPLE DANDA +AAF0..AAF1 ; Sentence_Terminal # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM +ABEB ; Sentence_Terminal # Po MEETEI MAYEK CHEIKHEI +FE52 ; Sentence_Terminal # Po SMALL FULL STOP +FE56..FE57 ; Sentence_Terminal # Po [2] SMALL QUESTION MARK..SMALL EXCLAMATION MARK +FF01 ; Sentence_Terminal # Po FULLWIDTH EXCLAMATION MARK +FF0E ; Sentence_Terminal # Po FULLWIDTH FULL STOP +FF1F ; Sentence_Terminal # Po FULLWIDTH QUESTION MARK +FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP +10A56..10A57 ; Sentence_Terminal # Po [2] KHAROSHTHI PUNCTUATION DANDA..KHAROSHTHI PUNCTUATION DOUBLE DANDA +11047..11048 ; Sentence_Terminal # Po [2] BRAHMI DANDA..BRAHMI DOUBLE DANDA +110BE..110C1 ; Sentence_Terminal # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA +11141..11143 ; Sentence_Terminal # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK +111C5..111C6 ; Sentence_Terminal # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA +111CD ; Sentence_Terminal # Po SHARADA SUTRA MARK +111DE..111DF ; Sentence_Terminal # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2 +11238..11239 ; Sentence_Terminal # Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA +1123B..1123C ; Sentence_Terminal # Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK +112A9 ; Sentence_Terminal # Po MULTANI SECTION MARK +1144B..1144C ; Sentence_Terminal # Po [2] NEWA DANDA..NEWA DOUBLE DANDA +115C2..115C3 ; Sentence_Terminal # Po [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA +115C9..115D7 ; Sentence_Terminal # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES +11641..11642 ; Sentence_Terminal # Po [2] MODI DANDA..MODI DOUBLE DANDA +1173C..1173E ; Sentence_Terminal # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI +11A42..11A43 ; Sentence_Terminal # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD +11A9B..11A9C ; Sentence_Terminal # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD +11C41..11C42 ; Sentence_Terminal # Po [2] BHAIKSUKI DANDA..BHAIKSUKI DOUBLE DANDA +16A6E..16A6F ; Sentence_Terminal # Po [2] MRO DANDA..MRO DOUBLE DANDA +16AF5 ; Sentence_Terminal # Po BASSA VAH FULL STOP +16B37..16B38 ; Sentence_Terminal # Po [2] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS TSHAB CEEB +16B44 ; Sentence_Terminal # Po PAHAWH HMONG SIGN XAUS +1BC9F ; Sentence_Terminal # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP +1DA88 ; Sentence_Terminal # Po SIGNWRITING FULL STOP -# Total code points: 120 +# Total code points: 128 # ================================================ @@ -1359,9 +1437,7 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S 239B..23B3 ; Pattern_Syntax # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM 23B4..23DB ; Pattern_Syntax # So [40] TOP SQUARE BRACKET..FUSE 23DC..23E1 ; Pattern_Syntax # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET -23E2..23FA ; Pattern_Syntax # So [25] WHITE TRAPEZIUM..BLACK CIRCLE FOR RECORD -23FB..23FF ; Pattern_Syntax # Cn [5] .. -2400..2426 ; Pattern_Syntax # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO +23E2..2426 ; Pattern_Syntax # So [69] WHITE TRAPEZIUM..SYMBOL FOR SUBSTITUTE FORM TWO 2427..243F ; Pattern_Syntax # Cn [25] .. 2440..244A ; Pattern_Syntax # So [11] OCR HOOK..OCR DOUBLE BACKSLASH 244B..245F ; Pattern_Syntax # Cn [21] .. @@ -1449,8 +1525,8 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S 2BBA..2BBC ; Pattern_Syntax # Cn [3] .. 2BBD..2BC8 ; Pattern_Syntax # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED 2BC9 ; Pattern_Syntax # Cn -2BCA..2BD1 ; Pattern_Syntax # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN -2BD2..2BEB ; Pattern_Syntax # Cn [26] .. +2BCA..2BD2 ; Pattern_Syntax # So [9] TOP HALF BLACK CIRCLE..GROUP MARK +2BD3..2BEB ; Pattern_Syntax # Cn [25] .. 2BEC..2BEF ; Pattern_Syntax # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS 2BF0..2BFF ; Pattern_Syntax # Cn [16] .. 2E00..2E01 ; Pattern_Syntax # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER @@ -1490,7 +1566,8 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S 2E40 ; Pattern_Syntax # Pd DOUBLE HYPHEN 2E41 ; Pattern_Syntax # Po REVERSED COMMA 2E42 ; Pattern_Syntax # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK -2E43..2E7F ; Pattern_Syntax # Cn [61] .. +2E43..2E49 ; Pattern_Syntax # Po [7] DASH WITH LEFT UPTURN..DOUBLE STACKED COMMA +2E4A..2E7F ; Pattern_Syntax # Cn [54] .. 3001..3003 ; Pattern_Syntax # Po [3] IDEOGRAPHIC COMMA..DITTO MARK 3008 ; Pattern_Syntax # Ps LEFT ANGLE BRACKET 3009 ; Pattern_Syntax # Pe RIGHT ANGLE BRACKET @@ -1522,4 +1599,20 @@ FE45..FE46 ; Pattern_Syntax # Po [2] SESAME DOT..WHITE SESAME DOT # Total code points: 2760 +# ================================================ + +0600..0605 ; Prepended_Concatenation_Mark # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE +06DD ; Prepended_Concatenation_Mark # Cf ARABIC END OF AYAH +070F ; Prepended_Concatenation_Mark # Cf SYRIAC ABBREVIATION MARK +08E2 ; Prepended_Concatenation_Mark # Cf ARABIC DISPUTED END OF AYAH +110BD ; Prepended_Concatenation_Mark # Cf KAITHI NUMBER SIGN + +# Total code points: 10 + +# ================================================ + +1F1E6..1F1FF ; Regional_Indicator # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + +# Total code points: 26 + # EOF diff --git a/make/data/unicodedata/Scripts.txt b/make/data/unicodedata/Scripts.txt index 7e42740407c..80430b32a8f 100644 --- a/make/data/unicodedata/Scripts.txt +++ b/make/data/unicodedata/Scripts.txt @@ -1,10 +1,11 @@ -# Scripts-8.0.0.txt -# Date: 2015-03-11, 22:29:42 GMT [MD] +# Scripts-10.0.0.txt +# Date: 2017-03-11, 06:40:37 GMT +# Copyright (c) 2017 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database -# Copyright (c) 1991-2015 Unicode, Inc. -# For terms of use, see http://www.unicode.org/terms_of_use.html -# For documentation, see http://www.unicode.org/reports/tr44/ +# For documentation, see http://www.unicode.org/reports/tr44/ # For more information, see: # UAX #24, Unicode Script Property: http://www.unicode.org/reports/tr24/ # Especially the sections: @@ -92,10 +93,10 @@ 0605 ; Common # Cf ARABIC NUMBER MARK ABOVE 060C ; Common # Po ARABIC COMMA 061B ; Common # Po ARABIC SEMICOLON -061C ; Common # Cf ARABIC LETTER MARK 061F ; Common # Po ARABIC QUESTION MARK 0640 ; Common # Lm ARABIC TATWEEL 06DD ; Common # Cf ARABIC END OF AYAH +08E2 ; Common # Cf ARABIC DISPUTED END OF AYAH 0964..0965 ; Common # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA 0E3F ; Common # Sc THAI CURRENCY SYMBOL BAHT 0FD5..0FD8 ; Common # So [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS @@ -110,6 +111,7 @@ 1CEE..1CF1 ; Common # Lo [4] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ANUSVARA UBHAYATO MUKHA 1CF2..1CF3 ; Common # Mc [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIGN ROTATED ARDHAVISARGA 1CF5..1CF6 ; Common # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA +1CF7 ; Common # Mc VEDIC SIGN ATIKRAMA 2000..200A ; Common # Zs [11] EN QUAD..HAIR SPACE 200B ; Common # Cf ZERO WIDTH SPACE 200E..200F ; Common # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK @@ -153,7 +155,7 @@ 208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN 208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS 208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS -20A0..20BE ; Common # Sc [31] EURO-CURRENCY SIGN..LARI SIGN +20A0..20BF ; Common # Sc [32] EURO-CURRENCY SIGN..BITCOIN SIGN 2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT 2102 ; Common # L& DOUBLE-STRUCK CAPITAL C 2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA @@ -223,8 +225,7 @@ 239B..23B3 ; Common # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM 23B4..23DB ; Common # So [40] TOP SQUARE BRACKET..FUSE 23DC..23E1 ; Common # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET -23E2..23FA ; Common # So [25] WHITE TRAPEZIUM..BLACK CIRCLE FOR RECORD -2400..2426 ; Common # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO +23E2..2426 ; Common # So [69] WHITE TRAPEZIUM..SYMBOL FOR SUBSTITUTE FORM TWO 2440..244A ; Common # So [11] OCR HOOK..OCR DOUBLE BACKSLASH 2460..249B ; Common # No [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP 249C..24E9 ; Common # So [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z @@ -309,7 +310,7 @@ 2B76..2B95 ; Common # So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW 2B98..2BB9 ; Common # So [34] THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..UP ARROWHEAD IN A RECTANGLE BOX 2BBD..2BC8 ; Common # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED -2BCA..2BD1 ; Common # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN +2BCA..2BD2 ; Common # So [9] TOP HALF BLACK CIRCLE..GROUP MARK 2BEC..2BEF ; Common # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS 2E00..2E01 ; Common # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER 2E02 ; Common # Pi LEFT SUBSTITUTION BRACKET @@ -348,6 +349,7 @@ 2E40 ; Common # Pd DOUBLE HYPHEN 2E41 ; Common # Po REVERSED COMMA 2E42 ; Common # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK +2E43..2E49 ; Common # Po [7] DASH WITH LEFT UPTURN..DOUBLE STACKED COMMA 2FF0..2FFB ; Common # So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID 3000 ; Common # Zs IDEOGRAPHIC SPACE 3001..3003 ; Common # Po [3] IDEOGRAPHIC COMMA..DITTO MARK @@ -572,19 +574,18 @@ FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHAR 1F100..1F10C ; Common # No [13] DIGIT ZERO FULL STOP..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO 1F110..1F12E ; Common # So [31] PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED WZ 1F130..1F16B ; Common # So [60] SQUARED LATIN CAPITAL LETTER A..RAISED MD SIGN -1F170..1F19A ; Common # So [43] NEGATIVE SQUARED LATIN CAPITAL LETTER A..SQUARED VS +1F170..1F1AC ; Common # So [61] NEGATIVE SQUARED LATIN CAPITAL LETTER A..SQUARED VOD 1F1E6..1F1FF ; Common # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z 1F201..1F202 ; Common # So [2] SQUARED KATAKANA KOKO..SQUARED KATAKANA SA -1F210..1F23A ; Common # So [43] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-55B6 +1F210..1F23B ; Common # So [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D 1F240..1F248 ; Common # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 1F250..1F251 ; Common # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT +1F260..1F265 ; Common # So [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI 1F300..1F3FA ; Common # So [251] CYCLONE..AMPHORA 1F3FB..1F3FF ; Common # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 -1F400..1F579 ; Common # So [378] RAT..JOYSTICK -1F57B..1F5A3 ; Common # So [41] LEFT HAND TELEPHONE RECEIVER..BLACK DOWN POINTING BACKHAND INDEX -1F5A5..1F6D0 ; Common # So [300] DESKTOP COMPUTER..PLACE OF WORSHIP +1F400..1F6D4 ; Common # So [725] RAT..PAGODA 1F6E0..1F6EC ; Common # So [13] HAMMER AND WRENCH..AIRPLANE ARRIVING -1F6F0..1F6F3 ; Common # So [4] SATELLITE..PASSENGER SHIP +1F6F0..1F6F8 ; Common # So [9] SATELLITE..FLYING SAUCER 1F700..1F773 ; Common # So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE 1F780..1F7D4 ; Common # So [85] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..HEAVY TWELVE POINTED PINWHEEL STAR 1F800..1F80B ; Common # So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD @@ -592,13 +593,17 @@ FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHAR 1F850..1F859 ; Common # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW 1F860..1F887 ; Common # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW 1F890..1F8AD ; Common # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS -1F910..1F918 ; Common # So [9] ZIPPER-MOUTH FACE..SIGN OF THE HORNS -1F980..1F984 ; Common # So [5] CRAB..UNICORN FACE +1F900..1F90B ; Common # So [12] CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT +1F910..1F93E ; Common # So [47] ZIPPER-MOUTH FACE..HANDBALL +1F940..1F94C ; Common # So [13] WILTED FLOWER..CURLING STONE +1F950..1F96B ; Common # So [28] CROISSANT..CANNED FOOD +1F980..1F997 ; Common # So [24] CRAB..CRICKET 1F9C0 ; Common # So CHEESE WEDGE +1F9D0..1F9E6 ; Common # So [23] FACE WITH MONOCLE..SOCKS E0001 ; Common # Cf LANGUAGE TAG E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG -# Total code points: 7179 +# Total code points: 7363 # ================================================ @@ -641,7 +646,7 @@ A770 ; Latin # Lm MODIFIER LETTER US A771..A787 ; Latin # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T A78B..A78E ; Latin # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT A78F ; Latin # Lo LATIN LETTER SINOLOGICAL DOT -A790..A7AD ; Latin # L& [30] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN CAPITAL LETTER L WITH BELT +A790..A7AE ; Latin # L& [31] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN CAPITAL LETTER SMALL CAPITAL I A7B0..A7B7 ; Latin # L& [8] LATIN CAPITAL LETTER TURNED K..LATIN SMALL LETTER OMEGA A7F7 ; Latin # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I A7F8..A7F9 ; Latin # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE @@ -654,7 +659,7 @@ FB00..FB06 ; Latin # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE S FF21..FF3A ; Latin # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z FF41..FF5A ; Latin # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z -# Total code points: 1349 +# Total code points: 1350 # ================================================ @@ -708,13 +713,13 @@ AB65 ; Greek # L& GREEK LETTER SMALL CAPITAL OMEGA 10175..10178 ; Greek # No [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN 10179..10189 ; Greek # So [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN 1018A..1018B ; Greek # No [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN -1018C ; Greek # So GREEK SINUSOID SIGN +1018C..1018E ; Greek # So [3] GREEK SINUSOID SIGN..NOMISMA SIGN 101A0 ; Greek # So GREEK SYMBOL TAU RHO 1D200..1D241 ; Greek # So [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54 1D242..1D244 ; Greek # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME 1D245 ; Greek # So GREEK MUSICAL LEIMMA -# Total code points: 516 +# Total code points: 518 # ================================================ @@ -724,6 +729,7 @@ AB65 ; Greek # L& GREEK LETTER SMALL CAPITAL OMEGA 0487 ; Cyrillic # Mn COMBINING CYRILLIC POKRYTIE 0488..0489 ; Cyrillic # Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN 048A..052F ; Cyrillic # L& [166] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER EL WITH DESCENDER +1C80..1C88 ; Cyrillic # L& [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK 1D2B ; Cyrillic # L& CYRILLIC LETTER SMALL CAPITAL EL 1D78 ; Cyrillic # Lm MODIFIER LETTER CYRILLIC EN 2DE0..2DFF ; Cyrillic # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS @@ -740,7 +746,7 @@ A69C..A69D ; Cyrillic # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER A69E..A69F ; Cyrillic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E FE2E..FE2F ; Cyrillic # Mn [2] COMBINING CYRILLIC TITLO LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF -# Total code points: 434 +# Total code points: 443 # ================================================ @@ -791,6 +797,7 @@ FB46..FB4F ; Hebrew # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATU 060D ; Arabic # Po ARABIC DATE SEPARATOR 060E..060F ; Arabic # So [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA 0610..061A ; Arabic # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA +061C ; Arabic # Cf ARABIC LETTER MARK 061E ; Arabic # Po ARABIC TRIPLE DOT PUNCTUATION MARK 0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE 0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH @@ -815,6 +822,8 @@ FB46..FB4F ; Hebrew # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATU 06FF ; Arabic # Lo ARABIC LETTER HEH WITH INVERTED V 0750..077F ; Arabic # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE 08A0..08B4 ; Arabic # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW +08B6..08BD ; Arabic # Lo [8] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER AFRICAN NOON +08D4..08E1 ; Arabic # Mn [14] ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH SIGN SAFHA 08E3..08FF ; Arabic # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA FB50..FBB1 ; Arabic # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM FBB2..FBC1 ; Arabic # Sk [16] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW @@ -862,7 +871,7 @@ FE76..FEFC ; Arabic # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LA 1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN 1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL -# Total code points: 1257 +# Total code points: 1280 # ================================================ @@ -873,8 +882,9 @@ FE76..FEFC ; Arabic # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LA 0712..072F ; Syriac # Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH 0730..074A ; Syriac # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH 074D..074F ; Syriac # Lo [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE +0860..086A ; Syriac # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA -# Total code points: 77 +# Total code points: 88 # ================================================ @@ -944,8 +954,10 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM 09F4..09F9 ; Bengali # No [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN 09FA ; Bengali # So BENGALI ISSHAR 09FB ; Bengali # Sc BENGALI GANDA MARK +09FC ; Bengali # Lo BENGALI LETTER VEDIC ANUSVARA +09FD ; Bengali # Po BENGALI ABBREVIATION SIGN -# Total code points: 93 +# Total code points: 95 # ================================================ @@ -998,8 +1010,9 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM 0AF0 ; Gujarati # Po GUJARATI ABBREVIATION SIGN 0AF1 ; Gujarati # Sc GUJARATI RUPEE SIGN 0AF9 ; Gujarati # Lo GUJARATI LETTER ZHA +0AFA..0AFF ; Gujarati # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE -# Total code points: 85 +# Total code points: 91 # ================================================ @@ -1086,6 +1099,7 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM # ================================================ +0C80 ; Kannada # Lo KANNADA SIGN SPACING CANDRABINDU 0C81 ; Kannada # Mn KANNADA SIGN CANDRABINDU 0C82..0C83 ; Kannada # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA 0C85..0C8C ; Kannada # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L @@ -1109,15 +1123,16 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM 0CE6..0CEF ; Kannada # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE 0CF1..0CF2 ; Kannada # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA -# Total code points: 87 +# Total code points: 88 # ================================================ -0D01 ; Malayalam # Mn MALAYALAM SIGN CANDRABINDU +0D00..0D01 ; Malayalam # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU 0D02..0D03 ; Malayalam # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA 0D05..0D0C ; Malayalam # Lo [8] MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC L 0D0E..0D10 ; Malayalam # Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI 0D12..0D3A ; Malayalam # Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA +0D3B..0D3C ; Malayalam # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA 0D3D ; Malayalam # Lo MALAYALAM SIGN AVAGRAHA 0D3E..0D40 ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II 0D41..0D44 ; Malayalam # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR @@ -1125,15 +1140,18 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM 0D4A..0D4C ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU 0D4D ; Malayalam # Mn MALAYALAM SIGN VIRAMA 0D4E ; Malayalam # Lo MALAYALAM LETTER DOT REPH +0D4F ; Malayalam # So MALAYALAM SIGN PARA +0D54..0D56 ; Malayalam # Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL 0D57 ; Malayalam # Mc MALAYALAM AU LENGTH MARK +0D58..0D5E ; Malayalam # No [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH 0D5F..0D61 ; Malayalam # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL 0D62..0D63 ; Malayalam # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL 0D66..0D6F ; Malayalam # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE -0D70..0D75 ; Malayalam # No [6] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE QUARTERS +0D70..0D78 ; Malayalam # No [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS 0D79 ; Malayalam # So MALAYALAM DATE MARK 0D7A..0D7F ; Malayalam # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K -# Total code points: 100 +# Total code points: 117 # ================================================ @@ -1436,21 +1454,24 @@ AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETT 1820..1842 ; Mongolian # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI 1843 ; Mongolian # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN 1844..1877 ; Mongolian # Lo [52] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER MANCHU ZHA -1880..18A8 ; Mongolian # Lo [41] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER MANCHU ALI GALI BHA +1880..1884 ; Mongolian # Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA +1885..1886 ; Mongolian # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA +1887..18A8 ; Mongolian # Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA 18A9 ; Mongolian # Mn MONGOLIAN LETTER ALI GALI DAGALGA 18AA ; Mongolian # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA +11660..1166C ; Mongolian # Po [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT -# Total code points: 153 +# Total code points: 166 # ================================================ 3041..3096 ; Hiragana # Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE 309D..309E ; Hiragana # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK 309F ; Hiragana # Lo HIRAGANA DIGRAPH YORI -1B001 ; Hiragana # Lo HIRAGANA LETTER ARCHAIC YE +1B001..1B11E ; Hiragana # Lo [286] HIRAGANA LETTER ARCHAIC YE..HENTAIGANA LETTER N-MU-MO-2 1F200 ; Hiragana # So SQUARE HIRAGANA HOKA -# Total code points: 91 +# Total code points: 376 # ================================================ @@ -1469,10 +1490,10 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK # ================================================ 02EA..02EB ; Bopomofo # Sk [2] MODIFIER LETTER YIN DEPARTING TONE MARK..MODIFIER LETTER YANG DEPARTING TONE MARK -3105..312D ; Bopomofo # Lo [41] BOPOMOFO LETTER B..BOPOMOFO LETTER IH +3105..312E ; Bopomofo # Lo [42] BOPOMOFO LETTER B..BOPOMOFO LETTER O WITH DOT ABOVE 31A0..31BA ; Bopomofo # Lo [27] BOPOMOFO LETTER BU..BOPOMOFO LETTER ZY -# Total code points: 70 +# Total code points: 71 # ================================================ @@ -1485,16 +1506,17 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK 3038..303A ; Han # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY 303B ; Han # Lm VERTICAL IDEOGRAPHIC ITERATION MARK 3400..4DB5 ; Han # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5 -4E00..9FD5 ; Han # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5 +4E00..9FEA ; Han # Lo [20971] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEA F900..FA6D ; Han # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D FA70..FAD9 ; Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 20000..2A6D6 ; Han # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6 2A700..2B734 ; Han # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 2B740..2B81D ; Han # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; Han # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 +2CEB0..2EBE0 ; Han # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 2F800..2FA1D ; Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D -# Total code points: 81734 +# Total code points: 89228 # ================================================ @@ -1509,8 +1531,9 @@ A490..A4C6 ; Yi # So [55] YI RADICAL QOT..YI RADICAL KE 10300..1031F ; Old_Italic # Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS 10320..10323 ; Old_Italic # No [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY +1032D..1032F ; Old_Italic # Lo [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE -# Total code points: 36 +# Total code points: 39 # ================================================ @@ -1542,8 +1565,8 @@ A490..A4C6 ; Yi # So [55] YI RADICAL QOT..YI RADICAL KE 1CED ; Inherited # Mn VEDIC SIGN TIRYAK 1CF4 ; Inherited # Mn VEDIC TONE CANDRA ABOVE 1CF8..1CF9 ; Inherited # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE -1DC0..1DF5 ; Inherited # Mn [54] COMBINING DOTTED GRAVE ACCENT..COMBINING UP TACK ABOVE -1DFC..1DFF ; Inherited # Mn [4] COMBINING DOUBLE INVERTED BREVE BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +1DC0..1DF9 ; Inherited # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW +1DFB..1DFF ; Inherited # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 200C..200D ; Inherited # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER 20D0..20DC ; Inherited # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE 20DD..20E0 ; Inherited # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH @@ -1562,7 +1585,7 @@ FE20..FE2D ; Inherited # Mn [14] COMBINING LIGATURE LEFT HALF..COMBINING CON 1D1AA..1D1AD ; Inherited # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 -# Total code points: 563 +# Total code points: 568 # ================================================ @@ -1705,8 +1728,13 @@ E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-2 2C00..2C2E ; Glagolitic # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE 2C30..2C5E ; Glagolitic # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE +1E000..1E006 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE +1E008..1E018 ; Glagolitic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU +1E01B..1E021 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI +1E023..1E024 ; Glagolitic # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS +1E026..1E02A ; Glagolitic # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA -# Total code points: 94 +# Total code points: 132 # ================================================ @@ -1872,11 +1900,11 @@ A62A..A62B ; Vai # Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO A880..A881 ; Saurashtra # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA A882..A8B3 ; Saurashtra # Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA A8B4..A8C3 ; Saurashtra # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU -A8C4 ; Saurashtra # Mn SAURASHTRA SIGN VIRAMA +A8C4..A8C5 ; Saurashtra # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU A8CE..A8CF ; Saurashtra # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA A8D0..A8D9 ; Saurashtra # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE -# Total code points: 81 +# Total code points: 82 # ================================================ @@ -2314,8 +2342,9 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI 11235 ; Khojki # Mc KHOJKI SIGN VIRAMA 11236..11237 ; Khojki # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA 11238..1123D ; Khojki # Po [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN +1123E ; Khojki # Mn KHOJKI SIGN SUKUN -# Total code points: 61 +# Total code points: 62 # ================================================ @@ -2536,4 +2565,129 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI # Total code points: 672 +# ================================================ + +1E900..1E943 ; Adlam # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA +1E944..1E94A ; Adlam # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA +1E950..1E959 ; Adlam # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE +1E95E..1E95F ; Adlam # Po [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK + +# Total code points: 87 + +# ================================================ + +11C00..11C08 ; Bhaiksuki # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L +11C0A..11C2E ; Bhaiksuki # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA +11C2F ; Bhaiksuki # Mc BHAIKSUKI VOWEL SIGN AA +11C30..11C36 ; Bhaiksuki # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L +11C38..11C3D ; Bhaiksuki # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA +11C3E ; Bhaiksuki # Mc BHAIKSUKI SIGN VISARGA +11C3F ; Bhaiksuki # Mn BHAIKSUKI SIGN VIRAMA +11C40 ; Bhaiksuki # Lo BHAIKSUKI SIGN AVAGRAHA +11C41..11C45 ; Bhaiksuki # Po [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2 +11C50..11C59 ; Bhaiksuki # Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE +11C5A..11C6C ; Bhaiksuki # No [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK + +# Total code points: 97 + +# ================================================ + +11C70..11C71 ; Marchen # Po [2] MARCHEN HEAD MARK..MARCHEN MARK SHAD +11C72..11C8F ; Marchen # Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A +11C92..11CA7 ; Marchen # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA +11CA9 ; Marchen # Mc MARCHEN SUBJOINED LETTER YA +11CAA..11CB0 ; Marchen # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA +11CB1 ; Marchen # Mc MARCHEN VOWEL SIGN I +11CB2..11CB3 ; Marchen # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E +11CB4 ; Marchen # Mc MARCHEN VOWEL SIGN O +11CB5..11CB6 ; Marchen # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + +# Total code points: 68 + +# ================================================ + +11400..11434 ; Newa # Lo [53] NEWA LETTER A..NEWA LETTER HA +11435..11437 ; Newa # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II +11438..1143F ; Newa # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI +11440..11441 ; Newa # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU +11442..11444 ; Newa # Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA +11445 ; Newa # Mc NEWA SIGN VISARGA +11446 ; Newa # Mn NEWA SIGN NUKTA +11447..1144A ; Newa # Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI +1144B..1144F ; Newa # Po [5] NEWA DANDA..NEWA ABBREVIATION SIGN +11450..11459 ; Newa # Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE +1145B ; Newa # Po NEWA PLACEHOLDER MARK +1145D ; Newa # Po NEWA INSERTION SIGN + +# Total code points: 92 + +# ================================================ + +104B0..104D3 ; Osage # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA +104D8..104FB ; Osage # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA + +# Total code points: 72 + +# ================================================ + +16FE0 ; Tangut # Lm TANGUT ITERATION MARK +17000..187EC ; Tangut # Lo [6125] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187EC +18800..18AF2 ; Tangut # Lo [755] TANGUT COMPONENT-001..TANGUT COMPONENT-755 + +# Total code points: 6881 + +# ================================================ + +11D00..11D06 ; Masaram_Gondi # Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E +11D08..11D09 ; Masaram_Gondi # Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O +11D0B..11D30 ; Masaram_Gondi # Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA +11D31..11D36 ; Masaram_Gondi # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R +11D3A ; Masaram_Gondi # Mn MASARAM GONDI VOWEL SIGN E +11D3C..11D3D ; Masaram_Gondi # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O +11D3F..11D45 ; Masaram_Gondi # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA +11D46 ; Masaram_Gondi # Lo MASARAM GONDI REPHA +11D47 ; Masaram_Gondi # Mn MASARAM GONDI RA-KARA +11D50..11D59 ; Masaram_Gondi # Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE + +# Total code points: 75 + +# ================================================ + +16FE1 ; Nushu # Lm NUSHU ITERATION MARK +1B170..1B2FB ; Nushu # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB + +# Total code points: 397 + +# ================================================ + +11A50 ; Soyombo # Lo SOYOMBO LETTER A +11A51..11A56 ; Soyombo # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE +11A57..11A58 ; Soyombo # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU +11A59..11A5B ; Soyombo # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK +11A5C..11A83 ; Soyombo # Lo [40] SOYOMBO LETTER KA..SOYOMBO LETTER KSSA +11A86..11A89 ; Soyombo # Lo [4] SOYOMBO CLUSTER-INITIAL LETTER RA..SOYOMBO CLUSTER-INITIAL LETTER SA +11A8A..11A96 ; Soyombo # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA +11A97 ; Soyombo # Mc SOYOMBO SIGN VISARGA +11A98..11A99 ; Soyombo # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER +11A9A..11A9C ; Soyombo # Po [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD +11A9E..11AA2 ; Soyombo # Po [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2 + +# Total code points: 80 + +# ================================================ + +11A00 ; Zanabazar_Square # Lo ZANABAZAR SQUARE LETTER A +11A01..11A06 ; Zanabazar_Square # Mn [6] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL SIGN O +11A07..11A08 ; Zanabazar_Square # Mc [2] ZANABAZAR SQUARE VOWEL SIGN AI..ZANABAZAR SQUARE VOWEL SIGN AU +11A09..11A0A ; Zanabazar_Square # Mn [2] ZANABAZAR SQUARE VOWEL SIGN REVERSED I..ZANABAZAR SQUARE VOWEL LENGTH MARK +11A0B..11A32 ; Zanabazar_Square # Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA +11A33..11A38 ; Zanabazar_Square # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA +11A39 ; Zanabazar_Square # Mc ZANABAZAR SQUARE SIGN VISARGA +11A3A ; Zanabazar_Square # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA +11A3B..11A3E ; Zanabazar_Square # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA +11A3F..11A46 ; Zanabazar_Square # Po [8] ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK +11A47 ; Zanabazar_Square # Mn ZANABAZAR SQUARE SUBJOINER + +# Total code points: 72 + # EOF diff --git a/make/data/unicodedata/SpecialCasing.txt b/make/data/unicodedata/SpecialCasing.txt index 8de6462f18c..26c7ecd6ae1 100644 --- a/make/data/unicodedata/SpecialCasing.txt +++ b/make/data/unicodedata/SpecialCasing.txt @@ -1,10 +1,11 @@ -# SpecialCasing-8.0.0.txt -# Date: 2014-12-16, 23:08:04 GMT [MD] +# SpecialCasing-10.0.0.txt +# Date: 2017-04-14, 05:40:43 GMT +# Copyright (c) 2017 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database -# Copyright (c) 1991-2014 Unicode, Inc. -# For terms of use, see http://www.unicode.org/terms_of_use.html -# For documentation, see http://www.unicode.org/reports/tr44/ +# For documentation, see http://www.unicode.org/reports/tr44/ # # Special Casing # @@ -196,7 +197,7 @@ FB17; FB17; 0544 056D; 0544 053D; # ARMENIAN SMALL LIGATURE MEN XEH # ================================================================================ # Conditional Mappings -# The remainder of this file provides conditional casing data used to produce +# The remainder of this file provides conditional casing data used to produce # full case mappings. # ================================================================================ # Language-Insensitive Mappings diff --git a/make/data/unicodedata/UnicodeData.txt b/make/data/unicodedata/UnicodeData.txt index aa0e914f843..d89c64f526a 100644 --- a/make/data/unicodedata/UnicodeData.txt +++ b/make/data/unicodedata/UnicodeData.txt @@ -616,7 +616,7 @@ 0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;; 0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197 0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196 -026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;;; +026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;A7AE;;A7AE 026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;2C62;;2C62 026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;A7AD;;A7AD 026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;; @@ -2072,6 +2072,17 @@ 085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;; 085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;; 085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;; +0860;SYRIAC LETTER MALAYALAM NGA;Lo;0;AL;;;;;N;;;;; +0861;SYRIAC LETTER MALAYALAM JA;Lo;0;AL;;;;;N;;;;; +0862;SYRIAC LETTER MALAYALAM NYA;Lo;0;AL;;;;;N;;;;; +0863;SYRIAC LETTER MALAYALAM TTA;Lo;0;AL;;;;;N;;;;; +0864;SYRIAC LETTER MALAYALAM NNA;Lo;0;AL;;;;;N;;;;; +0865;SYRIAC LETTER MALAYALAM NNNA;Lo;0;AL;;;;;N;;;;; +0866;SYRIAC LETTER MALAYALAM BHA;Lo;0;AL;;;;;N;;;;; +0867;SYRIAC LETTER MALAYALAM RA;Lo;0;AL;;;;;N;;;;; +0868;SYRIAC LETTER MALAYALAM LLA;Lo;0;AL;;;;;N;;;;; +0869;SYRIAC LETTER MALAYALAM LLLA;Lo;0;AL;;;;;N;;;;; +086A;SYRIAC LETTER MALAYALAM SSA;Lo;0;AL;;;;;N;;;;; 08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;; 08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; 08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; @@ -2093,6 +2104,29 @@ 08B2;ARABIC LETTER ZAIN WITH INVERTED V ABOVE;Lo;0;AL;;;;;N;;;;; 08B3;ARABIC LETTER AIN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; 08B4;ARABIC LETTER KAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +08B6;ARABIC LETTER BEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; +08B7;ARABIC LETTER PEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; +08B8;ARABIC LETTER TEH WITH SMALL TEH ABOVE;Lo;0;AL;;;;;N;;;;; +08B9;ARABIC LETTER REH WITH SMALL NOON ABOVE;Lo;0;AL;;;;;N;;;;; +08BA;ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE;Lo;0;AL;;;;;N;;;;; +08BB;ARABIC LETTER AFRICAN FEH;Lo;0;AL;;;;;N;;;;; +08BC;ARABIC LETTER AFRICAN QAF;Lo;0;AL;;;;;N;;;;; +08BD;ARABIC LETTER AFRICAN NOON;Lo;0;AL;;;;;N;;;;; +08D4;ARABIC SMALL HIGH WORD AR-RUB;Mn;230;NSM;;;;;N;;;;; +08D5;ARABIC SMALL HIGH SAD;Mn;230;NSM;;;;;N;;;;; +08D6;ARABIC SMALL HIGH AIN;Mn;230;NSM;;;;;N;;;;; +08D7;ARABIC SMALL HIGH QAF;Mn;230;NSM;;;;;N;;;;; +08D8;ARABIC SMALL HIGH NOON WITH KASRA;Mn;230;NSM;;;;;N;;;;; +08D9;ARABIC SMALL LOW NOON WITH KASRA;Mn;230;NSM;;;;;N;;;;; +08DA;ARABIC SMALL HIGH WORD ATH-THALATHA;Mn;230;NSM;;;;;N;;;;; +08DB;ARABIC SMALL HIGH WORD AS-SAJDA;Mn;230;NSM;;;;;N;;;;; +08DC;ARABIC SMALL HIGH WORD AN-NISF;Mn;230;NSM;;;;;N;;;;; +08DD;ARABIC SMALL HIGH WORD SAKTA;Mn;230;NSM;;;;;N;;;;; +08DE;ARABIC SMALL HIGH WORD QIF;Mn;230;NSM;;;;;N;;;;; +08DF;ARABIC SMALL HIGH WORD WAQFA;Mn;230;NSM;;;;;N;;;;; +08E0;ARABIC SMALL HIGH FOOTNOTE MARKER;Mn;230;NSM;;;;;N;;;;; +08E1;ARABIC SMALL HIGH SIGN SAFHA;Mn;230;NSM;;;;;N;;;;; +08E2;ARABIC DISPUTED END OF AYAH;Cf;0;AN;;;;;N;;;;; 08E3;ARABIC TURNED DAMMA BELOW;Mn;220;NSM;;;;;N;;;;; 08E4;ARABIC CURLY FATHA;Mn;230;NSM;;;;;N;;;;; 08E5;ARABIC CURLY DAMMA;Mn;230;NSM;;;;;N;;;;; @@ -2343,6 +2377,8 @@ 09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; 09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; 09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;; +09FC;BENGALI LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +09FD;BENGALI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;; 0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; 0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2507,6 +2543,12 @@ 0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 0AF9;GUJARATI LETTER ZHA;Lo;0;L;;;;;N;;;;; +0AFA;GUJARATI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; +0AFB;GUJARATI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; +0AFC;GUJARATI SIGN MADDAH;Mn;0;NSM;;;;;N;;;;; +0AFD;GUJARATI SIGN THREE-DOT NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFE;GUJARATI SIGN CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFF;GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; 0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2765,6 +2807,7 @@ 0C7D;TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR;No;0;ON;;;;2;N;;;;; 0C7E;TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR;No;0;ON;;;;3;N;;;;; 0C7F;TELUGU SIGN TUUMU;So;0;L;;;;;N;;;;; +0C80;KANNADA SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; 0C81;KANNADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2852,6 +2895,7 @@ 0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +0D00;MALAYALAM SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; 0D01;MALAYALAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -2907,6 +2951,8 @@ 0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; 0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; 0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;; +0D3B;MALAYALAM SIGN VERTICAL BAR VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D3C;MALAYALAM SIGN CIRCULAR VIRAMA;Mn;9;NSM;;;;;N;;;;; 0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; @@ -2923,7 +2969,18 @@ 0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;; 0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 0D4E;MALAYALAM LETTER DOT REPH;Lo;0;L;;;;;N;;;;; +0D4F;MALAYALAM SIGN PARA;So;0;L;;;;;N;;;;; +0D54;MALAYALAM LETTER CHILLU M;Lo;0;L;;;;;N;;;;; +0D55;MALAYALAM LETTER CHILLU Y;Lo;0;L;;;;;N;;;;; +0D56;MALAYALAM LETTER CHILLU LLL;Lo;0;L;;;;;N;;;;; 0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +0D58;MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH;No;0;L;;;;1/160;N;;;;; +0D59;MALAYALAM FRACTION ONE FORTIETH;No;0;L;;;;1/40;N;;;;; +0D5A;MALAYALAM FRACTION THREE EIGHTIETHS;No;0;L;;;;3/80;N;;;;; +0D5B;MALAYALAM FRACTION ONE TWENTIETH;No;0;L;;;;1/20;N;;;;; +0D5C;MALAYALAM FRACTION ONE TENTH;No;0;L;;;;1/10;N;;;;; +0D5D;MALAYALAM FRACTION THREE TWENTIETHS;No;0;L;;;;3/20;N;;;;; +0D5E;MALAYALAM FRACTION ONE FIFTH;No;0;L;;;;1/5;N;;;;; 0D5F;MALAYALAM LETTER ARCHAIC II;Lo;0;L;;;;;N;;;;; 0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; @@ -2945,6 +3002,9 @@ 0D73;MALAYALAM FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; 0D74;MALAYALAM FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; 0D75;MALAYALAM FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +0D76;MALAYALAM FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; +0D77;MALAYALAM FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +0D78;MALAYALAM FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; 0D79;MALAYALAM DATE MARK;So;0;L;;;;;N;;;;; 0D7A;MALAYALAM LETTER CHILLU NN;Lo;0;L;;;;;N;;;;; 0D7B;MALAYALAM LETTER CHILLU N;Lo;0;L;;;;;N;;;;; @@ -5458,8 +5518,8 @@ 1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;; 1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;; 1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;; -1885;MONGOLIAN LETTER ALI GALI BALUDA;Lo;0;L;;;;;N;;;;; -1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Lo;0;L;;;;;N;;;;; +1885;MONGOLIAN LETTER ALI GALI BALUDA;Mn;0;NSM;;;;;N;;;;; +1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Mn;0;NSM;;;;;N;;;;; 1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;; 1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;; 1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;; @@ -6319,6 +6379,15 @@ 1C7D;OL CHIKI AHAD;Lm;0;L;;;;;N;;;;; 1C7E;OL CHIKI PUNCTUATION MUCAAD;Po;0;L;;;;;N;;;;; 1C7F;OL CHIKI PUNCTUATION DOUBLE MUCAAD;Po;0;L;;;;;N;;;;; +1C80;CYRILLIC SMALL LETTER ROUNDED VE;Ll;0;L;;;;;N;;;0412;;0412 +1C81;CYRILLIC SMALL LETTER LONG-LEGGED DE;Ll;0;L;;;;;N;;;0414;;0414 +1C82;CYRILLIC SMALL LETTER NARROW O;Ll;0;L;;;;;N;;;041E;;041E +1C83;CYRILLIC SMALL LETTER WIDE ES;Ll;0;L;;;;;N;;;0421;;0421 +1C84;CYRILLIC SMALL LETTER TALL TE;Ll;0;L;;;;;N;;;0422;;0422 +1C85;CYRILLIC SMALL LETTER THREE-LEGGED TE;Ll;0;L;;;;;N;;;0422;;0422 +1C86;CYRILLIC SMALL LETTER TALL HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A +1C87;CYRILLIC SMALL LETTER TALL YAT;Ll;0;L;;;;;N;;;0462;;0462 +1C88;CYRILLIC SMALL LETTER UNBLENDED UK;Ll;0;L;;;;;N;;;A64A;;A64A 1CC0;SUNDANESE PUNCTUATION BINDU SURYA;Po;0;L;;;;;N;;;;; 1CC1;SUNDANESE PUNCTUATION BINDU PANGLONG;Po;0;L;;;;;N;;;;; 1CC2;SUNDANESE PUNCTUATION BINDU PURNAMA;Po;0;L;;;;;N;;;;; @@ -6366,6 +6435,7 @@ 1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; 1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +1CF7;VEDIC SIGN ATIKRAMA;Mc;0;L;;;;;N;;;;; 1CF8;VEDIC TONE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1CF9;VEDIC TONE DOUBLE RING ABOVE;Mn;230;NSM;;;;;N;;;;; 1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;; @@ -6614,6 +6684,11 @@ 1DF3;COMBINING LATIN SMALL LETTER O WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF4;COMBINING LATIN SMALL LETTER U WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; 1DF5;COMBINING UP TACK ABOVE;Mn;230;NSM;;;;;N;;;;; +1DF6;COMBINING KAVYKA ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; +1DF7;COMBINING KAVYKA ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF8;COMBINING DOT ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF9;COMBINING WIDE INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;;;;; +1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;; 1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; 1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; @@ -7291,6 +7366,7 @@ 20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;; 20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;; 20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;; +20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; @@ -8083,6 +8159,11 @@ 23F8;DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; 23F9;BLACK SQUARE FOR STOP;So;0;ON;;;;;N;;;;; 23FA;BLACK CIRCLE FOR RECORD;So;0;ON;;;;;N;;;;; +23FB;POWER SYMBOL;So;0;ON;;;;;N;;;;; +23FC;POWER ON-OFF SYMBOL;So;0;ON;;;;;N;;;;; +23FD;POWER ON SYMBOL;So;0;ON;;;;;N;;;;; +23FE;POWER SLEEP SYMBOL;So;0;ON;;;;;N;;;;; +23FF;OBSERVER EYE SYMBOL;So;0;ON;;;;;N;;;;; 2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; 2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; 2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; @@ -10031,6 +10112,7 @@ 2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; 2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;; 2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;; +2BD2;GROUP MARK;So;0;ON;;;;;N;;;;; 2BEC;LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BED;UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; 2BEE;RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; @@ -10561,6 +10643,13 @@ 2E40;DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; 2E41;REVERSED COMMA;Po;0;ON;;;;;N;;;;; 2E42;DOUBLE LOW-REVERSED-9 QUOTATION MARK;Ps;0;ON;;;;;N;;;;; +2E43;DASH WITH LEFT UPTURN;Po;0;ON;;;;;N;;;;; +2E44;DOUBLE SUSPENSION MARK;Po;0;ON;;;;;N;;;;; +2E45;INVERTED LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E46;INVERTED LOW KAVYKA WITH KAVYKA ABOVE;Po;0;ON;;;;;N;;;;; +2E47;LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E48;LOW KAVYKA WITH DOT;Po;0;ON;;;;;N;;;;; +2E49;DOUBLE STACKED COMMA;Po;0;ON;;;;;N;;;;; 2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; 2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; 2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; @@ -11196,6 +11285,7 @@ 312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; 312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; 312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;; +312E;BOPOMOFO LETTER O WITH DOT ABOVE;Lo;0;L;;;;;N;;;;; 3131;HANGUL LETTER KIYEOK;Lo;0;L; 1100;;;;N;HANGUL LETTER GIYEOG;;;; 3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L; 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; 3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; @@ -11962,7 +12052,7 @@ 4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; 4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; 4E00;;Lo;0;L;;;;;N;;;;; -9FD5;;Lo;0;L;;;;;N;;;;; +9FEA;;Lo;0;L;;;;;N;;;;; A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; @@ -13889,6 +13979,7 @@ A7AA;LATIN CAPITAL LETTER H WITH HOOK;Lu;0;L;;;;;N;;;;0266; A7AB;LATIN CAPITAL LETTER REVERSED OPEN E;Lu;0;L;;;;;N;;;;025C; A7AC;LATIN CAPITAL LETTER SCRIPT G;Lu;0;L;;;;;N;;;;0261; A7AD;LATIN CAPITAL LETTER L WITH BELT;Lu;0;L;;;;;N;;;;026C; +A7AE;LATIN CAPITAL LETTER SMALL CAPITAL I;Lu;0;L;;;;;N;;;;026A; A7B0;LATIN CAPITAL LETTER TURNED K;Lu;0;L;;;;;N;;;;029E; A7B1;LATIN CAPITAL LETTER TURNED T;Lu;0;L;;;;;N;;;;0287; A7B2;LATIN CAPITAL LETTER J WITH CROSSED-TAIL;Lu;0;L;;;;;N;;;;029D; @@ -14085,6 +14176,7 @@ A8C1;SAURASHTRA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; A8C2;SAURASHTRA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; A8C3;SAURASHTRA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; A8C4;SAURASHTRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +A8C5;SAURASHTRA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; A8CE;SAURASHTRA DANDA;Po;0;L;;;;;N;;;;; A8CF;SAURASHTRA DOUBLE DANDA;Po;0;L;;;;;N;;;;; A8D0;SAURASHTRA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; @@ -16834,6 +16926,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1018A;GREEK ZERO SIGN;No;0;ON;;;;0;N;;;;; 1018B;GREEK ONE QUARTER SIGN;No;0;ON;;;;1/4;N;;;;; 1018C;GREEK SINUSOID SIGN;So;0;ON;;;;;N;;;;; +1018D;GREEK INDICTION SIGN;So;0;L;;;;;N;;;;; +1018E;NOMISMA SIGN;So;0;L;;;;;N;;;;; 10190;ROMAN SEXTANS SIGN;So;0;ON;;;;;N;;;;; 10191;ROMAN UNCIA SIGN;So;0;ON;;;;;N;;;;; 10192;ROMAN SEMUNCIA SIGN;So;0;ON;;;;;N;;;;; @@ -17035,6 +17129,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; 10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; 10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; +1032D;OLD ITALIC LETTER YE;Lo;0;L;;;;;N;;;;; +1032E;OLD ITALIC LETTER NORTHERN TSE;Lo;0;L;;;;;N;;;;; +1032F;OLD ITALIC LETTER SOUTHERN TSE;Lo;0;L;;;;;N;;;;; 10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; 10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; 10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; @@ -17354,6 +17451,78 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 104A7;OSMANYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 104A8;OSMANYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 104A9;OSMANYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +104B0;OSAGE CAPITAL LETTER A;Lu;0;L;;;;;N;;;;104D8; +104B1;OSAGE CAPITAL LETTER AI;Lu;0;L;;;;;N;;;;104D9; +104B2;OSAGE CAPITAL LETTER AIN;Lu;0;L;;;;;N;;;;104DA; +104B3;OSAGE CAPITAL LETTER AH;Lu;0;L;;;;;N;;;;104DB; +104B4;OSAGE CAPITAL LETTER BRA;Lu;0;L;;;;;N;;;;104DC; +104B5;OSAGE CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;104DD; +104B6;OSAGE CAPITAL LETTER EHCHA;Lu;0;L;;;;;N;;;;104DE; +104B7;OSAGE CAPITAL LETTER E;Lu;0;L;;;;;N;;;;104DF; +104B8;OSAGE CAPITAL LETTER EIN;Lu;0;L;;;;;N;;;;104E0; +104B9;OSAGE CAPITAL LETTER HA;Lu;0;L;;;;;N;;;;104E1; +104BA;OSAGE CAPITAL LETTER HYA;Lu;0;L;;;;;N;;;;104E2; +104BB;OSAGE CAPITAL LETTER I;Lu;0;L;;;;;N;;;;104E3; +104BC;OSAGE CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;104E4; +104BD;OSAGE CAPITAL LETTER EHKA;Lu;0;L;;;;;N;;;;104E5; +104BE;OSAGE CAPITAL LETTER KYA;Lu;0;L;;;;;N;;;;104E6; +104BF;OSAGE CAPITAL LETTER LA;Lu;0;L;;;;;N;;;;104E7; +104C0;OSAGE CAPITAL LETTER MA;Lu;0;L;;;;;N;;;;104E8; +104C1;OSAGE CAPITAL LETTER NA;Lu;0;L;;;;;N;;;;104E9; +104C2;OSAGE CAPITAL LETTER O;Lu;0;L;;;;;N;;;;104EA; +104C3;OSAGE CAPITAL LETTER OIN;Lu;0;L;;;;;N;;;;104EB; +104C4;OSAGE CAPITAL LETTER PA;Lu;0;L;;;;;N;;;;104EC; +104C5;OSAGE CAPITAL LETTER EHPA;Lu;0;L;;;;;N;;;;104ED; +104C6;OSAGE CAPITAL LETTER SA;Lu;0;L;;;;;N;;;;104EE; +104C7;OSAGE CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;104EF; +104C8;OSAGE CAPITAL LETTER TA;Lu;0;L;;;;;N;;;;104F0; +104C9;OSAGE CAPITAL LETTER EHTA;Lu;0;L;;;;;N;;;;104F1; +104CA;OSAGE CAPITAL LETTER TSA;Lu;0;L;;;;;N;;;;104F2; +104CB;OSAGE CAPITAL LETTER EHTSA;Lu;0;L;;;;;N;;;;104F3; +104CC;OSAGE CAPITAL LETTER TSHA;Lu;0;L;;;;;N;;;;104F4; +104CD;OSAGE CAPITAL LETTER DHA;Lu;0;L;;;;;N;;;;104F5; +104CE;OSAGE CAPITAL LETTER U;Lu;0;L;;;;;N;;;;104F6; +104CF;OSAGE CAPITAL LETTER WA;Lu;0;L;;;;;N;;;;104F7; +104D0;OSAGE CAPITAL LETTER KHA;Lu;0;L;;;;;N;;;;104F8; +104D1;OSAGE CAPITAL LETTER GHA;Lu;0;L;;;;;N;;;;104F9; +104D2;OSAGE CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;104FA; +104D3;OSAGE CAPITAL LETTER ZHA;Lu;0;L;;;;;N;;;;104FB; +104D8;OSAGE SMALL LETTER A;Ll;0;L;;;;;N;;;104B0;;104B0 +104D9;OSAGE SMALL LETTER AI;Ll;0;L;;;;;N;;;104B1;;104B1 +104DA;OSAGE SMALL LETTER AIN;Ll;0;L;;;;;N;;;104B2;;104B2 +104DB;OSAGE SMALL LETTER AH;Ll;0;L;;;;;N;;;104B3;;104B3 +104DC;OSAGE SMALL LETTER BRA;Ll;0;L;;;;;N;;;104B4;;104B4 +104DD;OSAGE SMALL LETTER CHA;Ll;0;L;;;;;N;;;104B5;;104B5 +104DE;OSAGE SMALL LETTER EHCHA;Ll;0;L;;;;;N;;;104B6;;104B6 +104DF;OSAGE SMALL LETTER E;Ll;0;L;;;;;N;;;104B7;;104B7 +104E0;OSAGE SMALL LETTER EIN;Ll;0;L;;;;;N;;;104B8;;104B8 +104E1;OSAGE SMALL LETTER HA;Ll;0;L;;;;;N;;;104B9;;104B9 +104E2;OSAGE SMALL LETTER HYA;Ll;0;L;;;;;N;;;104BA;;104BA +104E3;OSAGE SMALL LETTER I;Ll;0;L;;;;;N;;;104BB;;104BB +104E4;OSAGE SMALL LETTER KA;Ll;0;L;;;;;N;;;104BC;;104BC +104E5;OSAGE SMALL LETTER EHKA;Ll;0;L;;;;;N;;;104BD;;104BD +104E6;OSAGE SMALL LETTER KYA;Ll;0;L;;;;;N;;;104BE;;104BE +104E7;OSAGE SMALL LETTER LA;Ll;0;L;;;;;N;;;104BF;;104BF +104E8;OSAGE SMALL LETTER MA;Ll;0;L;;;;;N;;;104C0;;104C0 +104E9;OSAGE SMALL LETTER NA;Ll;0;L;;;;;N;;;104C1;;104C1 +104EA;OSAGE SMALL LETTER O;Ll;0;L;;;;;N;;;104C2;;104C2 +104EB;OSAGE SMALL LETTER OIN;Ll;0;L;;;;;N;;;104C3;;104C3 +104EC;OSAGE SMALL LETTER PA;Ll;0;L;;;;;N;;;104C4;;104C4 +104ED;OSAGE SMALL LETTER EHPA;Ll;0;L;;;;;N;;;104C5;;104C5 +104EE;OSAGE SMALL LETTER SA;Ll;0;L;;;;;N;;;104C6;;104C6 +104EF;OSAGE SMALL LETTER SHA;Ll;0;L;;;;;N;;;104C7;;104C7 +104F0;OSAGE SMALL LETTER TA;Ll;0;L;;;;;N;;;104C8;;104C8 +104F1;OSAGE SMALL LETTER EHTA;Ll;0;L;;;;;N;;;104C9;;104C9 +104F2;OSAGE SMALL LETTER TSA;Ll;0;L;;;;;N;;;104CA;;104CA +104F3;OSAGE SMALL LETTER EHTSA;Ll;0;L;;;;;N;;;104CB;;104CB +104F4;OSAGE SMALL LETTER TSHA;Ll;0;L;;;;;N;;;104CC;;104CC +104F5;OSAGE SMALL LETTER DHA;Ll;0;L;;;;;N;;;104CD;;104CD +104F6;OSAGE SMALL LETTER U;Ll;0;L;;;;;N;;;104CE;;104CE +104F7;OSAGE SMALL LETTER WA;Ll;0;L;;;;;N;;;104CF;;104CF +104F8;OSAGE SMALL LETTER KHA;Ll;0;L;;;;;N;;;104D0;;104D0 +104F9;OSAGE SMALL LETTER GHA;Ll;0;L;;;;;N;;;104D1;;104D1 +104FA;OSAGE SMALL LETTER ZA;Ll;0;L;;;;;N;;;104D2;;104D2 +104FB;OSAGE SMALL LETTER ZHA;Ll;0;L;;;;;N;;;104D3;;104D3 10500;ELBASAN LETTER A;Lo;0;L;;;;;N;;;;; 10501;ELBASAN LETTER BE;Lo;0;L;;;;;N;;;;; 10502;ELBASAN LETTER CE;Lo;0;L;;;;;N;;;;; @@ -19180,6 +19349,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1123B;KHOJKI SECTION MARK;Po;0;L;;;;;N;;;;; 1123C;KHOJKI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; 1123D;KHOJKI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +1123E;KHOJKI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; 11280;MULTANI LETTER A;Lo;0;L;;;;;N;;;;; 11281;MULTANI LETTER I;Lo;0;L;;;;;N;;;;; 11282;MULTANI LETTER U;Lo;0;L;;;;;N;;;;; @@ -19372,6 +19542,98 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 11372;COMBINING GRANTHA LETTER NA;Mn;230;NSM;;;;;N;;;;; 11373;COMBINING GRANTHA LETTER VI;Mn;230;NSM;;;;;N;;;;; 11374;COMBINING GRANTHA LETTER PA;Mn;230;NSM;;;;;N;;;;; +11400;NEWA LETTER A;Lo;0;L;;;;;N;;;;; +11401;NEWA LETTER AA;Lo;0;L;;;;;N;;;;; +11402;NEWA LETTER I;Lo;0;L;;;;;N;;;;; +11403;NEWA LETTER II;Lo;0;L;;;;;N;;;;; +11404;NEWA LETTER U;Lo;0;L;;;;;N;;;;; +11405;NEWA LETTER UU;Lo;0;L;;;;;N;;;;; +11406;NEWA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11407;NEWA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11408;NEWA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11409;NEWA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1140A;NEWA LETTER E;Lo;0;L;;;;;N;;;;; +1140B;NEWA LETTER AI;Lo;0;L;;;;;N;;;;; +1140C;NEWA LETTER O;Lo;0;L;;;;;N;;;;; +1140D;NEWA LETTER AU;Lo;0;L;;;;;N;;;;; +1140E;NEWA LETTER KA;Lo;0;L;;;;;N;;;;; +1140F;NEWA LETTER KHA;Lo;0;L;;;;;N;;;;; +11410;NEWA LETTER GA;Lo;0;L;;;;;N;;;;; +11411;NEWA LETTER GHA;Lo;0;L;;;;;N;;;;; +11412;NEWA LETTER NGA;Lo;0;L;;;;;N;;;;; +11413;NEWA LETTER NGHA;Lo;0;L;;;;;N;;;;; +11414;NEWA LETTER CA;Lo;0;L;;;;;N;;;;; +11415;NEWA LETTER CHA;Lo;0;L;;;;;N;;;;; +11416;NEWA LETTER JA;Lo;0;L;;;;;N;;;;; +11417;NEWA LETTER JHA;Lo;0;L;;;;;N;;;;; +11418;NEWA LETTER NYA;Lo;0;L;;;;;N;;;;; +11419;NEWA LETTER NYHA;Lo;0;L;;;;;N;;;;; +1141A;NEWA LETTER TTA;Lo;0;L;;;;;N;;;;; +1141B;NEWA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1141C;NEWA LETTER DDA;Lo;0;L;;;;;N;;;;; +1141D;NEWA LETTER DDHA;Lo;0;L;;;;;N;;;;; +1141E;NEWA LETTER NNA;Lo;0;L;;;;;N;;;;; +1141F;NEWA LETTER TA;Lo;0;L;;;;;N;;;;; +11420;NEWA LETTER THA;Lo;0;L;;;;;N;;;;; +11421;NEWA LETTER DA;Lo;0;L;;;;;N;;;;; +11422;NEWA LETTER DHA;Lo;0;L;;;;;N;;;;; +11423;NEWA LETTER NA;Lo;0;L;;;;;N;;;;; +11424;NEWA LETTER NHA;Lo;0;L;;;;;N;;;;; +11425;NEWA LETTER PA;Lo;0;L;;;;;N;;;;; +11426;NEWA LETTER PHA;Lo;0;L;;;;;N;;;;; +11427;NEWA LETTER BA;Lo;0;L;;;;;N;;;;; +11428;NEWA LETTER BHA;Lo;0;L;;;;;N;;;;; +11429;NEWA LETTER MA;Lo;0;L;;;;;N;;;;; +1142A;NEWA LETTER MHA;Lo;0;L;;;;;N;;;;; +1142B;NEWA LETTER YA;Lo;0;L;;;;;N;;;;; +1142C;NEWA LETTER RA;Lo;0;L;;;;;N;;;;; +1142D;NEWA LETTER RHA;Lo;0;L;;;;;N;;;;; +1142E;NEWA LETTER LA;Lo;0;L;;;;;N;;;;; +1142F;NEWA LETTER LHA;Lo;0;L;;;;;N;;;;; +11430;NEWA LETTER WA;Lo;0;L;;;;;N;;;;; +11431;NEWA LETTER SHA;Lo;0;L;;;;;N;;;;; +11432;NEWA LETTER SSA;Lo;0;L;;;;;N;;;;; +11433;NEWA LETTER SA;Lo;0;L;;;;;N;;;;; +11434;NEWA LETTER HA;Lo;0;L;;;;;N;;;;; +11435;NEWA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11436;NEWA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11437;NEWA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +11438;NEWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11439;NEWA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1143A;NEWA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +1143B;NEWA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +1143C;NEWA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +1143D;NEWA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +1143E;NEWA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1143F;NEWA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11440;NEWA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11441;NEWA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11442;NEWA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11443;NEWA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11444;NEWA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11445;NEWA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11446;NEWA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11447;NEWA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +11448;NEWA SIGN FINAL ANUSVARA;Lo;0;L;;;;;N;;;;; +11449;NEWA OM;Lo;0;L;;;;;N;;;;; +1144A;NEWA SIDDHI;Lo;0;L;;;;;N;;;;; +1144B;NEWA DANDA;Po;0;L;;;;;N;;;;; +1144C;NEWA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +1144D;NEWA COMMA;Po;0;L;;;;;N;;;;; +1144E;NEWA GAP FILLER;Po;0;L;;;;;N;;;;; +1144F;NEWA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +11450;NEWA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11451;NEWA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11452;NEWA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11453;NEWA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11454;NEWA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11455;NEWA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11456;NEWA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11457;NEWA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11458;NEWA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11459;NEWA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1145B;NEWA PLACEHOLDER MARK;Po;0;L;;;;;N;;;;; +1145D;NEWA INSERTION SIGN;Po;0;L;;;;;N;;;;; 11480;TIRHUTA ANJI;Lo;0;L;;;;;N;;;;; 11481;TIRHUTA LETTER A;Lo;0;L;;;;;N;;;;; 11482;TIRHUTA LETTER AA;Lo;0;L;;;;;N;;;;; @@ -19625,6 +19887,19 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 11657;MODI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 11658;MODI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 11659;MODI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11660;MONGOLIAN BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11661;MONGOLIAN ROTATED BIRGA;Po;0;ON;;;;;N;;;;; +11662;MONGOLIAN DOUBLE BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11663;MONGOLIAN TRIPLE BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11664;MONGOLIAN BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11665;MONGOLIAN ROTATED BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11666;MONGOLIAN ROTATED BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11667;MONGOLIAN INVERTED BIRGA;Po;0;ON;;;;;N;;;;; +11668;MONGOLIAN INVERTED BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11669;MONGOLIAN SWIRL BIRGA;Po;0;ON;;;;;N;;;;; +1166A;MONGOLIAN SWIRL BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +1166B;MONGOLIAN SWIRL BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +1166C;MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; 11680;TAKRI LETTER A;Lo;0;L;;;;;N;;;;; 11681;TAKRI LETTER AA;Lo;0;L;;;;;N;;;;; 11682;TAKRI LETTER I;Lo;0;L;;;;;N;;;;; @@ -19832,6 +20107,158 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 118F1;WARANG CITI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; 118F2;WARANG CITI NUMBER NINETY;No;0;L;;;;90;N;;;;; 118FF;WARANG CITI OM;Lo;0;L;;;;;N;;;;; +11A00;ZANABAZAR SQUARE LETTER A;Lo;0;L;;;;;N;;;;; +11A01;ZANABAZAR SQUARE VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A02;ZANABAZAR SQUARE VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A03;ZANABAZAR SQUARE VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A04;ZANABAZAR SQUARE VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A05;ZANABAZAR SQUARE VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A06;ZANABAZAR SQUARE VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A07;ZANABAZAR SQUARE VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A08;ZANABAZAR SQUARE VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A09;ZANABAZAR SQUARE VOWEL SIGN REVERSED I;Mn;0;NSM;;;;;N;;;;; +11A0A;ZANABAZAR SQUARE VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A0B;ZANABAZAR SQUARE LETTER KA;Lo;0;L;;;;;N;;;;; +11A0C;ZANABAZAR SQUARE LETTER KHA;Lo;0;L;;;;;N;;;;; +11A0D;ZANABAZAR SQUARE LETTER GA;Lo;0;L;;;;;N;;;;; +11A0E;ZANABAZAR SQUARE LETTER GHA;Lo;0;L;;;;;N;;;;; +11A0F;ZANABAZAR SQUARE LETTER NGA;Lo;0;L;;;;;N;;;;; +11A10;ZANABAZAR SQUARE LETTER CA;Lo;0;L;;;;;N;;;;; +11A11;ZANABAZAR SQUARE LETTER CHA;Lo;0;L;;;;;N;;;;; +11A12;ZANABAZAR SQUARE LETTER JA;Lo;0;L;;;;;N;;;;; +11A13;ZANABAZAR SQUARE LETTER NYA;Lo;0;L;;;;;N;;;;; +11A14;ZANABAZAR SQUARE LETTER TTA;Lo;0;L;;;;;N;;;;; +11A15;ZANABAZAR SQUARE LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A16;ZANABAZAR SQUARE LETTER DDA;Lo;0;L;;;;;N;;;;; +11A17;ZANABAZAR SQUARE LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A18;ZANABAZAR SQUARE LETTER NNA;Lo;0;L;;;;;N;;;;; +11A19;ZANABAZAR SQUARE LETTER TA;Lo;0;L;;;;;N;;;;; +11A1A;ZANABAZAR SQUARE LETTER THA;Lo;0;L;;;;;N;;;;; +11A1B;ZANABAZAR SQUARE LETTER DA;Lo;0;L;;;;;N;;;;; +11A1C;ZANABAZAR SQUARE LETTER DHA;Lo;0;L;;;;;N;;;;; +11A1D;ZANABAZAR SQUARE LETTER NA;Lo;0;L;;;;;N;;;;; +11A1E;ZANABAZAR SQUARE LETTER PA;Lo;0;L;;;;;N;;;;; +11A1F;ZANABAZAR SQUARE LETTER PHA;Lo;0;L;;;;;N;;;;; +11A20;ZANABAZAR SQUARE LETTER BA;Lo;0;L;;;;;N;;;;; +11A21;ZANABAZAR SQUARE LETTER BHA;Lo;0;L;;;;;N;;;;; +11A22;ZANABAZAR SQUARE LETTER MA;Lo;0;L;;;;;N;;;;; +11A23;ZANABAZAR SQUARE LETTER TSA;Lo;0;L;;;;;N;;;;; +11A24;ZANABAZAR SQUARE LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A25;ZANABAZAR SQUARE LETTER DZA;Lo;0;L;;;;;N;;;;; +11A26;ZANABAZAR SQUARE LETTER DZHA;Lo;0;L;;;;;N;;;;; +11A27;ZANABAZAR SQUARE LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A28;ZANABAZAR SQUARE LETTER ZA;Lo;0;L;;;;;N;;;;; +11A29;ZANABAZAR SQUARE LETTER -A;Lo;0;L;;;;;N;;;;; +11A2A;ZANABAZAR SQUARE LETTER YA;Lo;0;L;;;;;N;;;;; +11A2B;ZANABAZAR SQUARE LETTER RA;Lo;0;L;;;;;N;;;;; +11A2C;ZANABAZAR SQUARE LETTER LA;Lo;0;L;;;;;N;;;;; +11A2D;ZANABAZAR SQUARE LETTER VA;Lo;0;L;;;;;N;;;;; +11A2E;ZANABAZAR SQUARE LETTER SHA;Lo;0;L;;;;;N;;;;; +11A2F;ZANABAZAR SQUARE LETTER SSA;Lo;0;L;;;;;N;;;;; +11A30;ZANABAZAR SQUARE LETTER SA;Lo;0;L;;;;;N;;;;; +11A31;ZANABAZAR SQUARE LETTER HA;Lo;0;L;;;;;N;;;;; +11A32;ZANABAZAR SQUARE LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A33;ZANABAZAR SQUARE FINAL CONSONANT MARK;Mn;0;NSM;;;;;N;;;;; +11A34;ZANABAZAR SQUARE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11A35;ZANABAZAR SQUARE SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11A36;ZANABAZAR SQUARE SIGN CANDRABINDU WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A37;ZANABAZAR SQUARE SIGN CANDRA WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A38;ZANABAZAR SQUARE SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A39;ZANABAZAR SQUARE SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A3A;ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A3B;ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA;Mn;0;NSM;;;;;N;;;;; +11A3C;ZANABAZAR SQUARE CLUSTER-FINAL LETTER RA;Mn;0;NSM;;;;;N;;;;; +11A3D;ZANABAZAR SQUARE CLUSTER-FINAL LETTER LA;Mn;0;NSM;;;;;N;;;;; +11A3E;ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA;Mn;0;NSM;;;;;N;;;;; +11A3F;ZANABAZAR SQUARE INITIAL HEAD MARK;Po;0;L;;;;;N;;;;; +11A40;ZANABAZAR SQUARE CLOSING HEAD MARK;Po;0;L;;;;;N;;;;; +11A41;ZANABAZAR SQUARE MARK TSHEG;Po;0;L;;;;;N;;;;; +11A42;ZANABAZAR SQUARE MARK SHAD;Po;0;L;;;;;N;;;;; +11A43;ZANABAZAR SQUARE MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A44;ZANABAZAR SQUARE MARK LONG TSHEG;Po;0;L;;;;;N;;;;; +11A45;ZANABAZAR SQUARE INITIAL DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A46;ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A47;ZANABAZAR SQUARE SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A50;SOYOMBO LETTER A;Lo;0;L;;;;;N;;;;; +11A51;SOYOMBO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A52;SOYOMBO VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A53;SOYOMBO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A54;SOYOMBO VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A55;SOYOMBO VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A56;SOYOMBO VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A57;SOYOMBO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A58;SOYOMBO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A59;SOYOMBO VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11A5A;SOYOMBO VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11A5B;SOYOMBO VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A5C;SOYOMBO LETTER KA;Lo;0;L;;;;;N;;;;; +11A5D;SOYOMBO LETTER KHA;Lo;0;L;;;;;N;;;;; +11A5E;SOYOMBO LETTER GA;Lo;0;L;;;;;N;;;;; +11A5F;SOYOMBO LETTER GHA;Lo;0;L;;;;;N;;;;; +11A60;SOYOMBO LETTER NGA;Lo;0;L;;;;;N;;;;; +11A61;SOYOMBO LETTER CA;Lo;0;L;;;;;N;;;;; +11A62;SOYOMBO LETTER CHA;Lo;0;L;;;;;N;;;;; +11A63;SOYOMBO LETTER JA;Lo;0;L;;;;;N;;;;; +11A64;SOYOMBO LETTER JHA;Lo;0;L;;;;;N;;;;; +11A65;SOYOMBO LETTER NYA;Lo;0;L;;;;;N;;;;; +11A66;SOYOMBO LETTER TTA;Lo;0;L;;;;;N;;;;; +11A67;SOYOMBO LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A68;SOYOMBO LETTER DDA;Lo;0;L;;;;;N;;;;; +11A69;SOYOMBO LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A6A;SOYOMBO LETTER NNA;Lo;0;L;;;;;N;;;;; +11A6B;SOYOMBO LETTER TA;Lo;0;L;;;;;N;;;;; +11A6C;SOYOMBO LETTER THA;Lo;0;L;;;;;N;;;;; +11A6D;SOYOMBO LETTER DA;Lo;0;L;;;;;N;;;;; +11A6E;SOYOMBO LETTER DHA;Lo;0;L;;;;;N;;;;; +11A6F;SOYOMBO LETTER NA;Lo;0;L;;;;;N;;;;; +11A70;SOYOMBO LETTER PA;Lo;0;L;;;;;N;;;;; +11A71;SOYOMBO LETTER PHA;Lo;0;L;;;;;N;;;;; +11A72;SOYOMBO LETTER BA;Lo;0;L;;;;;N;;;;; +11A73;SOYOMBO LETTER BHA;Lo;0;L;;;;;N;;;;; +11A74;SOYOMBO LETTER MA;Lo;0;L;;;;;N;;;;; +11A75;SOYOMBO LETTER TSA;Lo;0;L;;;;;N;;;;; +11A76;SOYOMBO LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A77;SOYOMBO LETTER DZA;Lo;0;L;;;;;N;;;;; +11A78;SOYOMBO LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A79;SOYOMBO LETTER ZA;Lo;0;L;;;;;N;;;;; +11A7A;SOYOMBO LETTER -A;Lo;0;L;;;;;N;;;;; +11A7B;SOYOMBO LETTER YA;Lo;0;L;;;;;N;;;;; +11A7C;SOYOMBO LETTER RA;Lo;0;L;;;;;N;;;;; +11A7D;SOYOMBO LETTER LA;Lo;0;L;;;;;N;;;;; +11A7E;SOYOMBO LETTER VA;Lo;0;L;;;;;N;;;;; +11A7F;SOYOMBO LETTER SHA;Lo;0;L;;;;;N;;;;; +11A80;SOYOMBO LETTER SSA;Lo;0;L;;;;;N;;;;; +11A81;SOYOMBO LETTER SA;Lo;0;L;;;;;N;;;;; +11A82;SOYOMBO LETTER HA;Lo;0;L;;;;;N;;;;; +11A83;SOYOMBO LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A86;SOYOMBO CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A87;SOYOMBO CLUSTER-INITIAL LETTER LA;Lo;0;L;;;;;N;;;;; +11A88;SOYOMBO CLUSTER-INITIAL LETTER SHA;Lo;0;L;;;;;N;;;;; +11A89;SOYOMBO CLUSTER-INITIAL LETTER SA;Lo;0;L;;;;;N;;;;; +11A8A;SOYOMBO FINAL CONSONANT SIGN G;Mn;0;NSM;;;;;N;;;;; +11A8B;SOYOMBO FINAL CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; +11A8C;SOYOMBO FINAL CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +11A8D;SOYOMBO FINAL CONSONANT SIGN D;Mn;0;NSM;;;;;N;;;;; +11A8E;SOYOMBO FINAL CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +11A8F;SOYOMBO FINAL CONSONANT SIGN B;Mn;0;NSM;;;;;N;;;;; +11A90;SOYOMBO FINAL CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; +11A91;SOYOMBO FINAL CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +11A92;SOYOMBO FINAL CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; +11A93;SOYOMBO FINAL CONSONANT SIGN SH;Mn;0;NSM;;;;;N;;;;; +11A94;SOYOMBO FINAL CONSONANT SIGN S;Mn;0;NSM;;;;;N;;;;; +11A95;SOYOMBO FINAL CONSONANT SIGN -A;Mn;0;NSM;;;;;N;;;;; +11A96;SOYOMBO SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A97;SOYOMBO SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A98;SOYOMBO GEMINATION MARK;Mn;0;NSM;;;;;N;;;;; +11A99;SOYOMBO SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A9A;SOYOMBO MARK TSHEG;Po;0;L;;;;;N;;;;; +11A9B;SOYOMBO MARK SHAD;Po;0;L;;;;;N;;;;; +11A9C;SOYOMBO MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A9E;SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME;Po;0;L;;;;;N;;;;; +11A9F;SOYOMBO HEAD MARK WITH MOON AND SUN AND FLAME;Po;0;L;;;;;N;;;;; +11AA0;SOYOMBO HEAD MARK WITH MOON AND SUN;Po;0;L;;;;;N;;;;; +11AA1;SOYOMBO TERMINAL MARK-1;Po;0;L;;;;;N;;;;; +11AA2;SOYOMBO TERMINAL MARK-2;Po;0;L;;;;;N;;;;; 11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;; 11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;; 11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;; @@ -19889,6 +20316,246 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 11AF6;PAU CIN HAU LOW-FALLING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; 11AF7;PAU CIN HAU LOW-FALLING TONE FINAL;Lo;0;L;;;;;N;;;;; 11AF8;PAU CIN HAU GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; +11C00;BHAIKSUKI LETTER A;Lo;0;L;;;;;N;;;;; +11C01;BHAIKSUKI LETTER AA;Lo;0;L;;;;;N;;;;; +11C02;BHAIKSUKI LETTER I;Lo;0;L;;;;;N;;;;; +11C03;BHAIKSUKI LETTER II;Lo;0;L;;;;;N;;;;; +11C04;BHAIKSUKI LETTER U;Lo;0;L;;;;;N;;;;; +11C05;BHAIKSUKI LETTER UU;Lo;0;L;;;;;N;;;;; +11C06;BHAIKSUKI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11C07;BHAIKSUKI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11C08;BHAIKSUKI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11C0A;BHAIKSUKI LETTER E;Lo;0;L;;;;;N;;;;; +11C0B;BHAIKSUKI LETTER AI;Lo;0;L;;;;;N;;;;; +11C0C;BHAIKSUKI LETTER O;Lo;0;L;;;;;N;;;;; +11C0D;BHAIKSUKI LETTER AU;Lo;0;L;;;;;N;;;;; +11C0E;BHAIKSUKI LETTER KA;Lo;0;L;;;;;N;;;;; +11C0F;BHAIKSUKI LETTER KHA;Lo;0;L;;;;;N;;;;; +11C10;BHAIKSUKI LETTER GA;Lo;0;L;;;;;N;;;;; +11C11;BHAIKSUKI LETTER GHA;Lo;0;L;;;;;N;;;;; +11C12;BHAIKSUKI LETTER NGA;Lo;0;L;;;;;N;;;;; +11C13;BHAIKSUKI LETTER CA;Lo;0;L;;;;;N;;;;; +11C14;BHAIKSUKI LETTER CHA;Lo;0;L;;;;;N;;;;; +11C15;BHAIKSUKI LETTER JA;Lo;0;L;;;;;N;;;;; +11C16;BHAIKSUKI LETTER JHA;Lo;0;L;;;;;N;;;;; +11C17;BHAIKSUKI LETTER NYA;Lo;0;L;;;;;N;;;;; +11C18;BHAIKSUKI LETTER TTA;Lo;0;L;;;;;N;;;;; +11C19;BHAIKSUKI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11C1A;BHAIKSUKI LETTER DDA;Lo;0;L;;;;;N;;;;; +11C1B;BHAIKSUKI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11C1C;BHAIKSUKI LETTER NNA;Lo;0;L;;;;;N;;;;; +11C1D;BHAIKSUKI LETTER TA;Lo;0;L;;;;;N;;;;; +11C1E;BHAIKSUKI LETTER THA;Lo;0;L;;;;;N;;;;; +11C1F;BHAIKSUKI LETTER DA;Lo;0;L;;;;;N;;;;; +11C20;BHAIKSUKI LETTER DHA;Lo;0;L;;;;;N;;;;; +11C21;BHAIKSUKI LETTER NA;Lo;0;L;;;;;N;;;;; +11C22;BHAIKSUKI LETTER PA;Lo;0;L;;;;;N;;;;; +11C23;BHAIKSUKI LETTER PHA;Lo;0;L;;;;;N;;;;; +11C24;BHAIKSUKI LETTER BA;Lo;0;L;;;;;N;;;;; +11C25;BHAIKSUKI LETTER BHA;Lo;0;L;;;;;N;;;;; +11C26;BHAIKSUKI LETTER MA;Lo;0;L;;;;;N;;;;; +11C27;BHAIKSUKI LETTER YA;Lo;0;L;;;;;N;;;;; +11C28;BHAIKSUKI LETTER RA;Lo;0;L;;;;;N;;;;; +11C29;BHAIKSUKI LETTER LA;Lo;0;L;;;;;N;;;;; +11C2A;BHAIKSUKI LETTER VA;Lo;0;L;;;;;N;;;;; +11C2B;BHAIKSUKI LETTER SHA;Lo;0;L;;;;;N;;;;; +11C2C;BHAIKSUKI LETTER SSA;Lo;0;L;;;;;N;;;;; +11C2D;BHAIKSUKI LETTER SA;Lo;0;L;;;;;N;;;;; +11C2E;BHAIKSUKI LETTER HA;Lo;0;L;;;;;N;;;;; +11C2F;BHAIKSUKI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11C30;BHAIKSUKI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11C31;BHAIKSUKI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11C32;BHAIKSUKI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11C33;BHAIKSUKI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11C34;BHAIKSUKI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11C35;BHAIKSUKI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11C36;BHAIKSUKI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11C38;BHAIKSUKI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11C39;BHAIKSUKI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11C3A;BHAIKSUKI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11C3B;BHAIKSUKI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11C3C;BHAIKSUKI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11C3D;BHAIKSUKI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11C3E;BHAIKSUKI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11C3F;BHAIKSUKI SIGN VIRAMA;Mn;9;L;;;;;N;;;;; +11C40;BHAIKSUKI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +11C41;BHAIKSUKI DANDA;Po;0;L;;;;;N;;;;; +11C42;BHAIKSUKI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11C43;BHAIKSUKI WORD SEPARATOR;Po;0;L;;;;;N;;;;; +11C44;BHAIKSUKI GAP FILLER-1;Po;0;L;;;;;N;;;;; +11C45;BHAIKSUKI GAP FILLER-2;Po;0;L;;;;;N;;;;; +11C50;BHAIKSUKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11C51;BHAIKSUKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11C52;BHAIKSUKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11C53;BHAIKSUKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11C54;BHAIKSUKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11C55;BHAIKSUKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11C56;BHAIKSUKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11C57;BHAIKSUKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11C58;BHAIKSUKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11C59;BHAIKSUKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11C5A;BHAIKSUKI NUMBER ONE;No;0;L;;;;1;N;;;;; +11C5B;BHAIKSUKI NUMBER TWO;No;0;L;;;;2;N;;;;; +11C5C;BHAIKSUKI NUMBER THREE;No;0;L;;;;3;N;;;;; +11C5D;BHAIKSUKI NUMBER FOUR;No;0;L;;;;4;N;;;;; +11C5E;BHAIKSUKI NUMBER FIVE;No;0;L;;;;5;N;;;;; +11C5F;BHAIKSUKI NUMBER SIX;No;0;L;;;;6;N;;;;; +11C60;BHAIKSUKI NUMBER SEVEN;No;0;L;;;;7;N;;;;; +11C61;BHAIKSUKI NUMBER EIGHT;No;0;L;;;;8;N;;;;; +11C62;BHAIKSUKI NUMBER NINE;No;0;L;;;;9;N;;;;; +11C63;BHAIKSUKI NUMBER TEN;No;0;L;;;;10;N;;;;; +11C64;BHAIKSUKI NUMBER TWENTY;No;0;L;;;;20;N;;;;; +11C65;BHAIKSUKI NUMBER THIRTY;No;0;L;;;;30;N;;;;; +11C66;BHAIKSUKI NUMBER FORTY;No;0;L;;;;40;N;;;;; +11C67;BHAIKSUKI NUMBER FIFTY;No;0;L;;;;50;N;;;;; +11C68;BHAIKSUKI NUMBER SIXTY;No;0;L;;;;60;N;;;;; +11C69;BHAIKSUKI NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +11C6A;BHAIKSUKI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +11C6B;BHAIKSUKI NUMBER NINETY;No;0;L;;;;90;N;;;;; +11C6C;BHAIKSUKI HUNDREDS UNIT MARK;No;0;L;;;;100;N;;;;; +11C70;MARCHEN HEAD MARK;Po;0;L;;;;;N;;;;; +11C71;MARCHEN MARK SHAD;Po;0;L;;;;;N;;;;; +11C72;MARCHEN LETTER KA;Lo;0;L;;;;;N;;;;; +11C73;MARCHEN LETTER KHA;Lo;0;L;;;;;N;;;;; +11C74;MARCHEN LETTER GA;Lo;0;L;;;;;N;;;;; +11C75;MARCHEN LETTER NGA;Lo;0;L;;;;;N;;;;; +11C76;MARCHEN LETTER CA;Lo;0;L;;;;;N;;;;; +11C77;MARCHEN LETTER CHA;Lo;0;L;;;;;N;;;;; +11C78;MARCHEN LETTER JA;Lo;0;L;;;;;N;;;;; +11C79;MARCHEN LETTER NYA;Lo;0;L;;;;;N;;;;; +11C7A;MARCHEN LETTER TA;Lo;0;L;;;;;N;;;;; +11C7B;MARCHEN LETTER THA;Lo;0;L;;;;;N;;;;; +11C7C;MARCHEN LETTER DA;Lo;0;L;;;;;N;;;;; +11C7D;MARCHEN LETTER NA;Lo;0;L;;;;;N;;;;; +11C7E;MARCHEN LETTER PA;Lo;0;L;;;;;N;;;;; +11C7F;MARCHEN LETTER PHA;Lo;0;L;;;;;N;;;;; +11C80;MARCHEN LETTER BA;Lo;0;L;;;;;N;;;;; +11C81;MARCHEN LETTER MA;Lo;0;L;;;;;N;;;;; +11C82;MARCHEN LETTER TSA;Lo;0;L;;;;;N;;;;; +11C83;MARCHEN LETTER TSHA;Lo;0;L;;;;;N;;;;; +11C84;MARCHEN LETTER DZA;Lo;0;L;;;;;N;;;;; +11C85;MARCHEN LETTER WA;Lo;0;L;;;;;N;;;;; +11C86;MARCHEN LETTER ZHA;Lo;0;L;;;;;N;;;;; +11C87;MARCHEN LETTER ZA;Lo;0;L;;;;;N;;;;; +11C88;MARCHEN LETTER -A;Lo;0;L;;;;;N;;;;; +11C89;MARCHEN LETTER YA;Lo;0;L;;;;;N;;;;; +11C8A;MARCHEN LETTER RA;Lo;0;L;;;;;N;;;;; +11C8B;MARCHEN LETTER LA;Lo;0;L;;;;;N;;;;; +11C8C;MARCHEN LETTER SHA;Lo;0;L;;;;;N;;;;; +11C8D;MARCHEN LETTER SA;Lo;0;L;;;;;N;;;;; +11C8E;MARCHEN LETTER HA;Lo;0;L;;;;;N;;;;; +11C8F;MARCHEN LETTER A;Lo;0;L;;;;;N;;;;; +11C92;MARCHEN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; +11C93;MARCHEN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; +11C94;MARCHEN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; +11C95;MARCHEN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; +11C96;MARCHEN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; +11C97;MARCHEN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; +11C98;MARCHEN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; +11C99;MARCHEN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; +11C9A;MARCHEN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; +11C9B;MARCHEN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; +11C9C;MARCHEN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; +11C9D;MARCHEN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; +11C9E;MARCHEN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; +11C9F;MARCHEN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; +11CA0;MARCHEN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; +11CA1;MARCHEN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; +11CA2;MARCHEN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; +11CA3;MARCHEN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; +11CA4;MARCHEN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; +11CA5;MARCHEN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; +11CA6;MARCHEN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; +11CA7;MARCHEN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; +11CA9;MARCHEN SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; +11CAA;MARCHEN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; +11CAB;MARCHEN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; +11CAC;MARCHEN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; +11CAD;MARCHEN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; +11CAE;MARCHEN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; +11CAF;MARCHEN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; +11CB0;MARCHEN VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11CB1;MARCHEN VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11CB2;MARCHEN VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11CB3;MARCHEN VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11CB4;MARCHEN VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11CB5;MARCHEN SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11CB6;MARCHEN SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11D00;MASARAM GONDI LETTER A;Lo;0;L;;;;;N;;;;; +11D01;MASARAM GONDI LETTER AA;Lo;0;L;;;;;N;;;;; +11D02;MASARAM GONDI LETTER I;Lo;0;L;;;;;N;;;;; +11D03;MASARAM GONDI LETTER II;Lo;0;L;;;;;N;;;;; +11D04;MASARAM GONDI LETTER U;Lo;0;L;;;;;N;;;;; +11D05;MASARAM GONDI LETTER UU;Lo;0;L;;;;;N;;;;; +11D06;MASARAM GONDI LETTER E;Lo;0;L;;;;;N;;;;; +11D08;MASARAM GONDI LETTER AI;Lo;0;L;;;;;N;;;;; +11D09;MASARAM GONDI LETTER O;Lo;0;L;;;;;N;;;;; +11D0B;MASARAM GONDI LETTER AU;Lo;0;L;;;;;N;;;;; +11D0C;MASARAM GONDI LETTER KA;Lo;0;L;;;;;N;;;;; +11D0D;MASARAM GONDI LETTER KHA;Lo;0;L;;;;;N;;;;; +11D0E;MASARAM GONDI LETTER GA;Lo;0;L;;;;;N;;;;; +11D0F;MASARAM GONDI LETTER GHA;Lo;0;L;;;;;N;;;;; +11D10;MASARAM GONDI LETTER NGA;Lo;0;L;;;;;N;;;;; +11D11;MASARAM GONDI LETTER CA;Lo;0;L;;;;;N;;;;; +11D12;MASARAM GONDI LETTER CHA;Lo;0;L;;;;;N;;;;; +11D13;MASARAM GONDI LETTER JA;Lo;0;L;;;;;N;;;;; +11D14;MASARAM GONDI LETTER JHA;Lo;0;L;;;;;N;;;;; +11D15;MASARAM GONDI LETTER NYA;Lo;0;L;;;;;N;;;;; +11D16;MASARAM GONDI LETTER TTA;Lo;0;L;;;;;N;;;;; +11D17;MASARAM GONDI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11D18;MASARAM GONDI LETTER DDA;Lo;0;L;;;;;N;;;;; +11D19;MASARAM GONDI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11D1A;MASARAM GONDI LETTER NNA;Lo;0;L;;;;;N;;;;; +11D1B;MASARAM GONDI LETTER TA;Lo;0;L;;;;;N;;;;; +11D1C;MASARAM GONDI LETTER THA;Lo;0;L;;;;;N;;;;; +11D1D;MASARAM GONDI LETTER DA;Lo;0;L;;;;;N;;;;; +11D1E;MASARAM GONDI LETTER DHA;Lo;0;L;;;;;N;;;;; +11D1F;MASARAM GONDI LETTER NA;Lo;0;L;;;;;N;;;;; +11D20;MASARAM GONDI LETTER PA;Lo;0;L;;;;;N;;;;; +11D21;MASARAM GONDI LETTER PHA;Lo;0;L;;;;;N;;;;; +11D22;MASARAM GONDI LETTER BA;Lo;0;L;;;;;N;;;;; +11D23;MASARAM GONDI LETTER BHA;Lo;0;L;;;;;N;;;;; +11D24;MASARAM GONDI LETTER MA;Lo;0;L;;;;;N;;;;; +11D25;MASARAM GONDI LETTER YA;Lo;0;L;;;;;N;;;;; +11D26;MASARAM GONDI LETTER RA;Lo;0;L;;;;;N;;;;; +11D27;MASARAM GONDI LETTER LA;Lo;0;L;;;;;N;;;;; +11D28;MASARAM GONDI LETTER VA;Lo;0;L;;;;;N;;;;; +11D29;MASARAM GONDI LETTER SHA;Lo;0;L;;;;;N;;;;; +11D2A;MASARAM GONDI LETTER SSA;Lo;0;L;;;;;N;;;;; +11D2B;MASARAM GONDI LETTER SA;Lo;0;L;;;;;N;;;;; +11D2C;MASARAM GONDI LETTER HA;Lo;0;L;;;;;N;;;;; +11D2D;MASARAM GONDI LETTER LLA;Lo;0;L;;;;;N;;;;; +11D2E;MASARAM GONDI LETTER KSSA;Lo;0;L;;;;;N;;;;; +11D2F;MASARAM GONDI LETTER JNYA;Lo;0;L;;;;;N;;;;; +11D30;MASARAM GONDI LETTER TRA;Lo;0;L;;;;;N;;;;; +11D31;MASARAM GONDI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11D32;MASARAM GONDI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11D33;MASARAM GONDI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11D34;MASARAM GONDI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11D35;MASARAM GONDI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11D36;MASARAM GONDI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11D3A;MASARAM GONDI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11D3C;MASARAM GONDI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11D3D;MASARAM GONDI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11D3F;MASARAM GONDI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11D40;MASARAM GONDI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11D41;MASARAM GONDI SIGN VISARGA;Mn;0;NSM;;;;;N;;;;; +11D42;MASARAM GONDI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11D43;MASARAM GONDI SIGN CANDRA;Mn;0;NSM;;;;;N;;;;; +11D44;MASARAM GONDI SIGN HALANTA;Mn;9;NSM;;;;;N;;;;; +11D45;MASARAM GONDI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11D46;MASARAM GONDI REPHA;Lo;0;L;;;;;N;;;;; +11D47;MASARAM GONDI RA-KARA;Mn;0;NSM;;;;;N;;;;; +11D50;MASARAM GONDI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11D51;MASARAM GONDI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11D52;MASARAM GONDI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11D53;MASARAM GONDI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11D54;MASARAM GONDI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11D55;MASARAM GONDI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11D56;MASARAM GONDI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11D57;MASARAM GONDI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11D58;MASARAM GONDI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11D59;MASARAM GONDI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;; 12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;; 12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;; @@ -23685,8 +24352,1448 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 16F9D;MIAO LETTER REFORMED TONE-5;Lm;0;L;;;;;N;;;;; 16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;; 16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;; +16FE0;TANGUT ITERATION MARK;Lm;0;L;;;;;N;;;;; +16FE1;NUSHU ITERATION MARK;Lm;0;L;;;;;N;;;;; +17000;;Lo;0;L;;;;;N;;;;; +187EC;;Lo;0;L;;;;;N;;;;; +18800;TANGUT COMPONENT-001;Lo;0;L;;;;;N;;;;; +18801;TANGUT COMPONENT-002;Lo;0;L;;;;;N;;;;; +18802;TANGUT COMPONENT-003;Lo;0;L;;;;;N;;;;; +18803;TANGUT COMPONENT-004;Lo;0;L;;;;;N;;;;; +18804;TANGUT COMPONENT-005;Lo;0;L;;;;;N;;;;; +18805;TANGUT COMPONENT-006;Lo;0;L;;;;;N;;;;; +18806;TANGUT COMPONENT-007;Lo;0;L;;;;;N;;;;; +18807;TANGUT COMPONENT-008;Lo;0;L;;;;;N;;;;; +18808;TANGUT COMPONENT-009;Lo;0;L;;;;;N;;;;; +18809;TANGUT COMPONENT-010;Lo;0;L;;;;;N;;;;; +1880A;TANGUT COMPONENT-011;Lo;0;L;;;;;N;;;;; +1880B;TANGUT COMPONENT-012;Lo;0;L;;;;;N;;;;; +1880C;TANGUT COMPONENT-013;Lo;0;L;;;;;N;;;;; +1880D;TANGUT COMPONENT-014;Lo;0;L;;;;;N;;;;; +1880E;TANGUT COMPONENT-015;Lo;0;L;;;;;N;;;;; +1880F;TANGUT COMPONENT-016;Lo;0;L;;;;;N;;;;; +18810;TANGUT COMPONENT-017;Lo;0;L;;;;;N;;;;; +18811;TANGUT COMPONENT-018;Lo;0;L;;;;;N;;;;; +18812;TANGUT COMPONENT-019;Lo;0;L;;;;;N;;;;; +18813;TANGUT COMPONENT-020;Lo;0;L;;;;;N;;;;; +18814;TANGUT COMPONENT-021;Lo;0;L;;;;;N;;;;; +18815;TANGUT COMPONENT-022;Lo;0;L;;;;;N;;;;; +18816;TANGUT COMPONENT-023;Lo;0;L;;;;;N;;;;; +18817;TANGUT COMPONENT-024;Lo;0;L;;;;;N;;;;; +18818;TANGUT COMPONENT-025;Lo;0;L;;;;;N;;;;; +18819;TANGUT COMPONENT-026;Lo;0;L;;;;;N;;;;; +1881A;TANGUT COMPONENT-027;Lo;0;L;;;;;N;;;;; +1881B;TANGUT COMPONENT-028;Lo;0;L;;;;;N;;;;; +1881C;TANGUT COMPONENT-029;Lo;0;L;;;;;N;;;;; +1881D;TANGUT COMPONENT-030;Lo;0;L;;;;;N;;;;; +1881E;TANGUT COMPONENT-031;Lo;0;L;;;;;N;;;;; +1881F;TANGUT COMPONENT-032;Lo;0;L;;;;;N;;;;; +18820;TANGUT COMPONENT-033;Lo;0;L;;;;;N;;;;; +18821;TANGUT COMPONENT-034;Lo;0;L;;;;;N;;;;; +18822;TANGUT COMPONENT-035;Lo;0;L;;;;;N;;;;; +18823;TANGUT COMPONENT-036;Lo;0;L;;;;;N;;;;; +18824;TANGUT COMPONENT-037;Lo;0;L;;;;;N;;;;; +18825;TANGUT COMPONENT-038;Lo;0;L;;;;;N;;;;; +18826;TANGUT COMPONENT-039;Lo;0;L;;;;;N;;;;; +18827;TANGUT COMPONENT-040;Lo;0;L;;;;;N;;;;; +18828;TANGUT COMPONENT-041;Lo;0;L;;;;;N;;;;; +18829;TANGUT COMPONENT-042;Lo;0;L;;;;;N;;;;; +1882A;TANGUT COMPONENT-043;Lo;0;L;;;;;N;;;;; +1882B;TANGUT COMPONENT-044;Lo;0;L;;;;;N;;;;; +1882C;TANGUT COMPONENT-045;Lo;0;L;;;;;N;;;;; +1882D;TANGUT COMPONENT-046;Lo;0;L;;;;;N;;;;; +1882E;TANGUT COMPONENT-047;Lo;0;L;;;;;N;;;;; +1882F;TANGUT COMPONENT-048;Lo;0;L;;;;;N;;;;; +18830;TANGUT COMPONENT-049;Lo;0;L;;;;;N;;;;; +18831;TANGUT COMPONENT-050;Lo;0;L;;;;;N;;;;; +18832;TANGUT COMPONENT-051;Lo;0;L;;;;;N;;;;; +18833;TANGUT COMPONENT-052;Lo;0;L;;;;;N;;;;; +18834;TANGUT COMPONENT-053;Lo;0;L;;;;;N;;;;; +18835;TANGUT COMPONENT-054;Lo;0;L;;;;;N;;;;; +18836;TANGUT COMPONENT-055;Lo;0;L;;;;;N;;;;; +18837;TANGUT COMPONENT-056;Lo;0;L;;;;;N;;;;; +18838;TANGUT COMPONENT-057;Lo;0;L;;;;;N;;;;; +18839;TANGUT COMPONENT-058;Lo;0;L;;;;;N;;;;; +1883A;TANGUT COMPONENT-059;Lo;0;L;;;;;N;;;;; +1883B;TANGUT COMPONENT-060;Lo;0;L;;;;;N;;;;; +1883C;TANGUT COMPONENT-061;Lo;0;L;;;;;N;;;;; +1883D;TANGUT COMPONENT-062;Lo;0;L;;;;;N;;;;; +1883E;TANGUT COMPONENT-063;Lo;0;L;;;;;N;;;;; +1883F;TANGUT COMPONENT-064;Lo;0;L;;;;;N;;;;; +18840;TANGUT COMPONENT-065;Lo;0;L;;;;;N;;;;; +18841;TANGUT COMPONENT-066;Lo;0;L;;;;;N;;;;; +18842;TANGUT COMPONENT-067;Lo;0;L;;;;;N;;;;; +18843;TANGUT COMPONENT-068;Lo;0;L;;;;;N;;;;; +18844;TANGUT COMPONENT-069;Lo;0;L;;;;;N;;;;; +18845;TANGUT COMPONENT-070;Lo;0;L;;;;;N;;;;; +18846;TANGUT COMPONENT-071;Lo;0;L;;;;;N;;;;; +18847;TANGUT COMPONENT-072;Lo;0;L;;;;;N;;;;; +18848;TANGUT COMPONENT-073;Lo;0;L;;;;;N;;;;; +18849;TANGUT COMPONENT-074;Lo;0;L;;;;;N;;;;; +1884A;TANGUT COMPONENT-075;Lo;0;L;;;;;N;;;;; +1884B;TANGUT COMPONENT-076;Lo;0;L;;;;;N;;;;; +1884C;TANGUT COMPONENT-077;Lo;0;L;;;;;N;;;;; +1884D;TANGUT COMPONENT-078;Lo;0;L;;;;;N;;;;; +1884E;TANGUT COMPONENT-079;Lo;0;L;;;;;N;;;;; +1884F;TANGUT COMPONENT-080;Lo;0;L;;;;;N;;;;; +18850;TANGUT COMPONENT-081;Lo;0;L;;;;;N;;;;; +18851;TANGUT COMPONENT-082;Lo;0;L;;;;;N;;;;; +18852;TANGUT COMPONENT-083;Lo;0;L;;;;;N;;;;; +18853;TANGUT COMPONENT-084;Lo;0;L;;;;;N;;;;; +18854;TANGUT COMPONENT-085;Lo;0;L;;;;;N;;;;; +18855;TANGUT COMPONENT-086;Lo;0;L;;;;;N;;;;; +18856;TANGUT COMPONENT-087;Lo;0;L;;;;;N;;;;; +18857;TANGUT COMPONENT-088;Lo;0;L;;;;;N;;;;; +18858;TANGUT COMPONENT-089;Lo;0;L;;;;;N;;;;; +18859;TANGUT COMPONENT-090;Lo;0;L;;;;;N;;;;; +1885A;TANGUT COMPONENT-091;Lo;0;L;;;;;N;;;;; +1885B;TANGUT COMPONENT-092;Lo;0;L;;;;;N;;;;; +1885C;TANGUT COMPONENT-093;Lo;0;L;;;;;N;;;;; +1885D;TANGUT COMPONENT-094;Lo;0;L;;;;;N;;;;; +1885E;TANGUT COMPONENT-095;Lo;0;L;;;;;N;;;;; +1885F;TANGUT COMPONENT-096;Lo;0;L;;;;;N;;;;; +18860;TANGUT COMPONENT-097;Lo;0;L;;;;;N;;;;; +18861;TANGUT COMPONENT-098;Lo;0;L;;;;;N;;;;; +18862;TANGUT COMPONENT-099;Lo;0;L;;;;;N;;;;; +18863;TANGUT COMPONENT-100;Lo;0;L;;;;;N;;;;; +18864;TANGUT COMPONENT-101;Lo;0;L;;;;;N;;;;; +18865;TANGUT COMPONENT-102;Lo;0;L;;;;;N;;;;; +18866;TANGUT COMPONENT-103;Lo;0;L;;;;;N;;;;; +18867;TANGUT COMPONENT-104;Lo;0;L;;;;;N;;;;; +18868;TANGUT COMPONENT-105;Lo;0;L;;;;;N;;;;; +18869;TANGUT COMPONENT-106;Lo;0;L;;;;;N;;;;; +1886A;TANGUT COMPONENT-107;Lo;0;L;;;;;N;;;;; +1886B;TANGUT COMPONENT-108;Lo;0;L;;;;;N;;;;; +1886C;TANGUT COMPONENT-109;Lo;0;L;;;;;N;;;;; +1886D;TANGUT COMPONENT-110;Lo;0;L;;;;;N;;;;; +1886E;TANGUT COMPONENT-111;Lo;0;L;;;;;N;;;;; +1886F;TANGUT COMPONENT-112;Lo;0;L;;;;;N;;;;; +18870;TANGUT COMPONENT-113;Lo;0;L;;;;;N;;;;; +18871;TANGUT COMPONENT-114;Lo;0;L;;;;;N;;;;; +18872;TANGUT COMPONENT-115;Lo;0;L;;;;;N;;;;; +18873;TANGUT COMPONENT-116;Lo;0;L;;;;;N;;;;; +18874;TANGUT COMPONENT-117;Lo;0;L;;;;;N;;;;; +18875;TANGUT COMPONENT-118;Lo;0;L;;;;;N;;;;; +18876;TANGUT COMPONENT-119;Lo;0;L;;;;;N;;;;; +18877;TANGUT COMPONENT-120;Lo;0;L;;;;;N;;;;; +18878;TANGUT COMPONENT-121;Lo;0;L;;;;;N;;;;; +18879;TANGUT COMPONENT-122;Lo;0;L;;;;;N;;;;; +1887A;TANGUT COMPONENT-123;Lo;0;L;;;;;N;;;;; +1887B;TANGUT COMPONENT-124;Lo;0;L;;;;;N;;;;; +1887C;TANGUT COMPONENT-125;Lo;0;L;;;;;N;;;;; +1887D;TANGUT COMPONENT-126;Lo;0;L;;;;;N;;;;; +1887E;TANGUT COMPONENT-127;Lo;0;L;;;;;N;;;;; +1887F;TANGUT COMPONENT-128;Lo;0;L;;;;;N;;;;; +18880;TANGUT COMPONENT-129;Lo;0;L;;;;;N;;;;; +18881;TANGUT COMPONENT-130;Lo;0;L;;;;;N;;;;; +18882;TANGUT COMPONENT-131;Lo;0;L;;;;;N;;;;; +18883;TANGUT COMPONENT-132;Lo;0;L;;;;;N;;;;; +18884;TANGUT COMPONENT-133;Lo;0;L;;;;;N;;;;; +18885;TANGUT COMPONENT-134;Lo;0;L;;;;;N;;;;; +18886;TANGUT COMPONENT-135;Lo;0;L;;;;;N;;;;; +18887;TANGUT COMPONENT-136;Lo;0;L;;;;;N;;;;; +18888;TANGUT COMPONENT-137;Lo;0;L;;;;;N;;;;; +18889;TANGUT COMPONENT-138;Lo;0;L;;;;;N;;;;; +1888A;TANGUT COMPONENT-139;Lo;0;L;;;;;N;;;;; +1888B;TANGUT COMPONENT-140;Lo;0;L;;;;;N;;;;; +1888C;TANGUT COMPONENT-141;Lo;0;L;;;;;N;;;;; +1888D;TANGUT COMPONENT-142;Lo;0;L;;;;;N;;;;; +1888E;TANGUT COMPONENT-143;Lo;0;L;;;;;N;;;;; +1888F;TANGUT COMPONENT-144;Lo;0;L;;;;;N;;;;; +18890;TANGUT COMPONENT-145;Lo;0;L;;;;;N;;;;; +18891;TANGUT COMPONENT-146;Lo;0;L;;;;;N;;;;; +18892;TANGUT COMPONENT-147;Lo;0;L;;;;;N;;;;; +18893;TANGUT COMPONENT-148;Lo;0;L;;;;;N;;;;; +18894;TANGUT COMPONENT-149;Lo;0;L;;;;;N;;;;; +18895;TANGUT COMPONENT-150;Lo;0;L;;;;;N;;;;; +18896;TANGUT COMPONENT-151;Lo;0;L;;;;;N;;;;; +18897;TANGUT COMPONENT-152;Lo;0;L;;;;;N;;;;; +18898;TANGUT COMPONENT-153;Lo;0;L;;;;;N;;;;; +18899;TANGUT COMPONENT-154;Lo;0;L;;;;;N;;;;; +1889A;TANGUT COMPONENT-155;Lo;0;L;;;;;N;;;;; +1889B;TANGUT COMPONENT-156;Lo;0;L;;;;;N;;;;; +1889C;TANGUT COMPONENT-157;Lo;0;L;;;;;N;;;;; +1889D;TANGUT COMPONENT-158;Lo;0;L;;;;;N;;;;; +1889E;TANGUT COMPONENT-159;Lo;0;L;;;;;N;;;;; +1889F;TANGUT COMPONENT-160;Lo;0;L;;;;;N;;;;; +188A0;TANGUT COMPONENT-161;Lo;0;L;;;;;N;;;;; +188A1;TANGUT COMPONENT-162;Lo;0;L;;;;;N;;;;; +188A2;TANGUT COMPONENT-163;Lo;0;L;;;;;N;;;;; +188A3;TANGUT COMPONENT-164;Lo;0;L;;;;;N;;;;; +188A4;TANGUT COMPONENT-165;Lo;0;L;;;;;N;;;;; +188A5;TANGUT COMPONENT-166;Lo;0;L;;;;;N;;;;; +188A6;TANGUT COMPONENT-167;Lo;0;L;;;;;N;;;;; +188A7;TANGUT COMPONENT-168;Lo;0;L;;;;;N;;;;; +188A8;TANGUT COMPONENT-169;Lo;0;L;;;;;N;;;;; +188A9;TANGUT COMPONENT-170;Lo;0;L;;;;;N;;;;; +188AA;TANGUT COMPONENT-171;Lo;0;L;;;;;N;;;;; +188AB;TANGUT COMPONENT-172;Lo;0;L;;;;;N;;;;; +188AC;TANGUT COMPONENT-173;Lo;0;L;;;;;N;;;;; +188AD;TANGUT COMPONENT-174;Lo;0;L;;;;;N;;;;; +188AE;TANGUT COMPONENT-175;Lo;0;L;;;;;N;;;;; +188AF;TANGUT COMPONENT-176;Lo;0;L;;;;;N;;;;; +188B0;TANGUT COMPONENT-177;Lo;0;L;;;;;N;;;;; +188B1;TANGUT COMPONENT-178;Lo;0;L;;;;;N;;;;; +188B2;TANGUT COMPONENT-179;Lo;0;L;;;;;N;;;;; +188B3;TANGUT COMPONENT-180;Lo;0;L;;;;;N;;;;; +188B4;TANGUT COMPONENT-181;Lo;0;L;;;;;N;;;;; +188B5;TANGUT COMPONENT-182;Lo;0;L;;;;;N;;;;; +188B6;TANGUT COMPONENT-183;Lo;0;L;;;;;N;;;;; +188B7;TANGUT COMPONENT-184;Lo;0;L;;;;;N;;;;; +188B8;TANGUT COMPONENT-185;Lo;0;L;;;;;N;;;;; +188B9;TANGUT COMPONENT-186;Lo;0;L;;;;;N;;;;; +188BA;TANGUT COMPONENT-187;Lo;0;L;;;;;N;;;;; +188BB;TANGUT COMPONENT-188;Lo;0;L;;;;;N;;;;; +188BC;TANGUT COMPONENT-189;Lo;0;L;;;;;N;;;;; +188BD;TANGUT COMPONENT-190;Lo;0;L;;;;;N;;;;; +188BE;TANGUT COMPONENT-191;Lo;0;L;;;;;N;;;;; +188BF;TANGUT COMPONENT-192;Lo;0;L;;;;;N;;;;; +188C0;TANGUT COMPONENT-193;Lo;0;L;;;;;N;;;;; +188C1;TANGUT COMPONENT-194;Lo;0;L;;;;;N;;;;; +188C2;TANGUT COMPONENT-195;Lo;0;L;;;;;N;;;;; +188C3;TANGUT COMPONENT-196;Lo;0;L;;;;;N;;;;; +188C4;TANGUT COMPONENT-197;Lo;0;L;;;;;N;;;;; +188C5;TANGUT COMPONENT-198;Lo;0;L;;;;;N;;;;; +188C6;TANGUT COMPONENT-199;Lo;0;L;;;;;N;;;;; +188C7;TANGUT COMPONENT-200;Lo;0;L;;;;;N;;;;; +188C8;TANGUT COMPONENT-201;Lo;0;L;;;;;N;;;;; +188C9;TANGUT COMPONENT-202;Lo;0;L;;;;;N;;;;; +188CA;TANGUT COMPONENT-203;Lo;0;L;;;;;N;;;;; +188CB;TANGUT COMPONENT-204;Lo;0;L;;;;;N;;;;; +188CC;TANGUT COMPONENT-205;Lo;0;L;;;;;N;;;;; +188CD;TANGUT COMPONENT-206;Lo;0;L;;;;;N;;;;; +188CE;TANGUT COMPONENT-207;Lo;0;L;;;;;N;;;;; +188CF;TANGUT COMPONENT-208;Lo;0;L;;;;;N;;;;; +188D0;TANGUT COMPONENT-209;Lo;0;L;;;;;N;;;;; +188D1;TANGUT COMPONENT-210;Lo;0;L;;;;;N;;;;; +188D2;TANGUT COMPONENT-211;Lo;0;L;;;;;N;;;;; +188D3;TANGUT COMPONENT-212;Lo;0;L;;;;;N;;;;; +188D4;TANGUT COMPONENT-213;Lo;0;L;;;;;N;;;;; +188D5;TANGUT COMPONENT-214;Lo;0;L;;;;;N;;;;; +188D6;TANGUT COMPONENT-215;Lo;0;L;;;;;N;;;;; +188D7;TANGUT COMPONENT-216;Lo;0;L;;;;;N;;;;; +188D8;TANGUT COMPONENT-217;Lo;0;L;;;;;N;;;;; +188D9;TANGUT COMPONENT-218;Lo;0;L;;;;;N;;;;; +188DA;TANGUT COMPONENT-219;Lo;0;L;;;;;N;;;;; +188DB;TANGUT COMPONENT-220;Lo;0;L;;;;;N;;;;; +188DC;TANGUT COMPONENT-221;Lo;0;L;;;;;N;;;;; +188DD;TANGUT COMPONENT-222;Lo;0;L;;;;;N;;;;; +188DE;TANGUT COMPONENT-223;Lo;0;L;;;;;N;;;;; +188DF;TANGUT COMPONENT-224;Lo;0;L;;;;;N;;;;; +188E0;TANGUT COMPONENT-225;Lo;0;L;;;;;N;;;;; +188E1;TANGUT COMPONENT-226;Lo;0;L;;;;;N;;;;; +188E2;TANGUT COMPONENT-227;Lo;0;L;;;;;N;;;;; +188E3;TANGUT COMPONENT-228;Lo;0;L;;;;;N;;;;; +188E4;TANGUT COMPONENT-229;Lo;0;L;;;;;N;;;;; +188E5;TANGUT COMPONENT-230;Lo;0;L;;;;;N;;;;; +188E6;TANGUT COMPONENT-231;Lo;0;L;;;;;N;;;;; +188E7;TANGUT COMPONENT-232;Lo;0;L;;;;;N;;;;; +188E8;TANGUT COMPONENT-233;Lo;0;L;;;;;N;;;;; +188E9;TANGUT COMPONENT-234;Lo;0;L;;;;;N;;;;; +188EA;TANGUT COMPONENT-235;Lo;0;L;;;;;N;;;;; +188EB;TANGUT COMPONENT-236;Lo;0;L;;;;;N;;;;; +188EC;TANGUT COMPONENT-237;Lo;0;L;;;;;N;;;;; +188ED;TANGUT COMPONENT-238;Lo;0;L;;;;;N;;;;; +188EE;TANGUT COMPONENT-239;Lo;0;L;;;;;N;;;;; +188EF;TANGUT COMPONENT-240;Lo;0;L;;;;;N;;;;; +188F0;TANGUT COMPONENT-241;Lo;0;L;;;;;N;;;;; +188F1;TANGUT COMPONENT-242;Lo;0;L;;;;;N;;;;; +188F2;TANGUT COMPONENT-243;Lo;0;L;;;;;N;;;;; +188F3;TANGUT COMPONENT-244;Lo;0;L;;;;;N;;;;; +188F4;TANGUT COMPONENT-245;Lo;0;L;;;;;N;;;;; +188F5;TANGUT COMPONENT-246;Lo;0;L;;;;;N;;;;; +188F6;TANGUT COMPONENT-247;Lo;0;L;;;;;N;;;;; +188F7;TANGUT COMPONENT-248;Lo;0;L;;;;;N;;;;; +188F8;TANGUT COMPONENT-249;Lo;0;L;;;;;N;;;;; +188F9;TANGUT COMPONENT-250;Lo;0;L;;;;;N;;;;; +188FA;TANGUT COMPONENT-251;Lo;0;L;;;;;N;;;;; +188FB;TANGUT COMPONENT-252;Lo;0;L;;;;;N;;;;; +188FC;TANGUT COMPONENT-253;Lo;0;L;;;;;N;;;;; +188FD;TANGUT COMPONENT-254;Lo;0;L;;;;;N;;;;; +188FE;TANGUT COMPONENT-255;Lo;0;L;;;;;N;;;;; +188FF;TANGUT COMPONENT-256;Lo;0;L;;;;;N;;;;; +18900;TANGUT COMPONENT-257;Lo;0;L;;;;;N;;;;; +18901;TANGUT COMPONENT-258;Lo;0;L;;;;;N;;;;; +18902;TANGUT COMPONENT-259;Lo;0;L;;;;;N;;;;; +18903;TANGUT COMPONENT-260;Lo;0;L;;;;;N;;;;; +18904;TANGUT COMPONENT-261;Lo;0;L;;;;;N;;;;; +18905;TANGUT COMPONENT-262;Lo;0;L;;;;;N;;;;; +18906;TANGUT COMPONENT-263;Lo;0;L;;;;;N;;;;; +18907;TANGUT COMPONENT-264;Lo;0;L;;;;;N;;;;; +18908;TANGUT COMPONENT-265;Lo;0;L;;;;;N;;;;; +18909;TANGUT COMPONENT-266;Lo;0;L;;;;;N;;;;; +1890A;TANGUT COMPONENT-267;Lo;0;L;;;;;N;;;;; +1890B;TANGUT COMPONENT-268;Lo;0;L;;;;;N;;;;; +1890C;TANGUT COMPONENT-269;Lo;0;L;;;;;N;;;;; +1890D;TANGUT COMPONENT-270;Lo;0;L;;;;;N;;;;; +1890E;TANGUT COMPONENT-271;Lo;0;L;;;;;N;;;;; +1890F;TANGUT COMPONENT-272;Lo;0;L;;;;;N;;;;; +18910;TANGUT COMPONENT-273;Lo;0;L;;;;;N;;;;; +18911;TANGUT COMPONENT-274;Lo;0;L;;;;;N;;;;; +18912;TANGUT COMPONENT-275;Lo;0;L;;;;;N;;;;; +18913;TANGUT COMPONENT-276;Lo;0;L;;;;;N;;;;; +18914;TANGUT COMPONENT-277;Lo;0;L;;;;;N;;;;; +18915;TANGUT COMPONENT-278;Lo;0;L;;;;;N;;;;; +18916;TANGUT COMPONENT-279;Lo;0;L;;;;;N;;;;; +18917;TANGUT COMPONENT-280;Lo;0;L;;;;;N;;;;; +18918;TANGUT COMPONENT-281;Lo;0;L;;;;;N;;;;; +18919;TANGUT COMPONENT-282;Lo;0;L;;;;;N;;;;; +1891A;TANGUT COMPONENT-283;Lo;0;L;;;;;N;;;;; +1891B;TANGUT COMPONENT-284;Lo;0;L;;;;;N;;;;; +1891C;TANGUT COMPONENT-285;Lo;0;L;;;;;N;;;;; +1891D;TANGUT COMPONENT-286;Lo;0;L;;;;;N;;;;; +1891E;TANGUT COMPONENT-287;Lo;0;L;;;;;N;;;;; +1891F;TANGUT COMPONENT-288;Lo;0;L;;;;;N;;;;; +18920;TANGUT COMPONENT-289;Lo;0;L;;;;;N;;;;; +18921;TANGUT COMPONENT-290;Lo;0;L;;;;;N;;;;; +18922;TANGUT COMPONENT-291;Lo;0;L;;;;;N;;;;; +18923;TANGUT COMPONENT-292;Lo;0;L;;;;;N;;;;; +18924;TANGUT COMPONENT-293;Lo;0;L;;;;;N;;;;; +18925;TANGUT COMPONENT-294;Lo;0;L;;;;;N;;;;; +18926;TANGUT COMPONENT-295;Lo;0;L;;;;;N;;;;; +18927;TANGUT COMPONENT-296;Lo;0;L;;;;;N;;;;; +18928;TANGUT COMPONENT-297;Lo;0;L;;;;;N;;;;; +18929;TANGUT COMPONENT-298;Lo;0;L;;;;;N;;;;; +1892A;TANGUT COMPONENT-299;Lo;0;L;;;;;N;;;;; +1892B;TANGUT COMPONENT-300;Lo;0;L;;;;;N;;;;; +1892C;TANGUT COMPONENT-301;Lo;0;L;;;;;N;;;;; +1892D;TANGUT COMPONENT-302;Lo;0;L;;;;;N;;;;; +1892E;TANGUT COMPONENT-303;Lo;0;L;;;;;N;;;;; +1892F;TANGUT COMPONENT-304;Lo;0;L;;;;;N;;;;; +18930;TANGUT COMPONENT-305;Lo;0;L;;;;;N;;;;; +18931;TANGUT COMPONENT-306;Lo;0;L;;;;;N;;;;; +18932;TANGUT COMPONENT-307;Lo;0;L;;;;;N;;;;; +18933;TANGUT COMPONENT-308;Lo;0;L;;;;;N;;;;; +18934;TANGUT COMPONENT-309;Lo;0;L;;;;;N;;;;; +18935;TANGUT COMPONENT-310;Lo;0;L;;;;;N;;;;; +18936;TANGUT COMPONENT-311;Lo;0;L;;;;;N;;;;; +18937;TANGUT COMPONENT-312;Lo;0;L;;;;;N;;;;; +18938;TANGUT COMPONENT-313;Lo;0;L;;;;;N;;;;; +18939;TANGUT COMPONENT-314;Lo;0;L;;;;;N;;;;; +1893A;TANGUT COMPONENT-315;Lo;0;L;;;;;N;;;;; +1893B;TANGUT COMPONENT-316;Lo;0;L;;;;;N;;;;; +1893C;TANGUT COMPONENT-317;Lo;0;L;;;;;N;;;;; +1893D;TANGUT COMPONENT-318;Lo;0;L;;;;;N;;;;; +1893E;TANGUT COMPONENT-319;Lo;0;L;;;;;N;;;;; +1893F;TANGUT COMPONENT-320;Lo;0;L;;;;;N;;;;; +18940;TANGUT COMPONENT-321;Lo;0;L;;;;;N;;;;; +18941;TANGUT COMPONENT-322;Lo;0;L;;;;;N;;;;; +18942;TANGUT COMPONENT-323;Lo;0;L;;;;;N;;;;; +18943;TANGUT COMPONENT-324;Lo;0;L;;;;;N;;;;; +18944;TANGUT COMPONENT-325;Lo;0;L;;;;;N;;;;; +18945;TANGUT COMPONENT-326;Lo;0;L;;;;;N;;;;; +18946;TANGUT COMPONENT-327;Lo;0;L;;;;;N;;;;; +18947;TANGUT COMPONENT-328;Lo;0;L;;;;;N;;;;; +18948;TANGUT COMPONENT-329;Lo;0;L;;;;;N;;;;; +18949;TANGUT COMPONENT-330;Lo;0;L;;;;;N;;;;; +1894A;TANGUT COMPONENT-331;Lo;0;L;;;;;N;;;;; +1894B;TANGUT COMPONENT-332;Lo;0;L;;;;;N;;;;; +1894C;TANGUT COMPONENT-333;Lo;0;L;;;;;N;;;;; +1894D;TANGUT COMPONENT-334;Lo;0;L;;;;;N;;;;; +1894E;TANGUT COMPONENT-335;Lo;0;L;;;;;N;;;;; +1894F;TANGUT COMPONENT-336;Lo;0;L;;;;;N;;;;; +18950;TANGUT COMPONENT-337;Lo;0;L;;;;;N;;;;; +18951;TANGUT COMPONENT-338;Lo;0;L;;;;;N;;;;; +18952;TANGUT COMPONENT-339;Lo;0;L;;;;;N;;;;; +18953;TANGUT COMPONENT-340;Lo;0;L;;;;;N;;;;; +18954;TANGUT COMPONENT-341;Lo;0;L;;;;;N;;;;; +18955;TANGUT COMPONENT-342;Lo;0;L;;;;;N;;;;; +18956;TANGUT COMPONENT-343;Lo;0;L;;;;;N;;;;; +18957;TANGUT COMPONENT-344;Lo;0;L;;;;;N;;;;; +18958;TANGUT COMPONENT-345;Lo;0;L;;;;;N;;;;; +18959;TANGUT COMPONENT-346;Lo;0;L;;;;;N;;;;; +1895A;TANGUT COMPONENT-347;Lo;0;L;;;;;N;;;;; +1895B;TANGUT COMPONENT-348;Lo;0;L;;;;;N;;;;; +1895C;TANGUT COMPONENT-349;Lo;0;L;;;;;N;;;;; +1895D;TANGUT COMPONENT-350;Lo;0;L;;;;;N;;;;; +1895E;TANGUT COMPONENT-351;Lo;0;L;;;;;N;;;;; +1895F;TANGUT COMPONENT-352;Lo;0;L;;;;;N;;;;; +18960;TANGUT COMPONENT-353;Lo;0;L;;;;;N;;;;; +18961;TANGUT COMPONENT-354;Lo;0;L;;;;;N;;;;; +18962;TANGUT COMPONENT-355;Lo;0;L;;;;;N;;;;; +18963;TANGUT COMPONENT-356;Lo;0;L;;;;;N;;;;; +18964;TANGUT COMPONENT-357;Lo;0;L;;;;;N;;;;; +18965;TANGUT COMPONENT-358;Lo;0;L;;;;;N;;;;; +18966;TANGUT COMPONENT-359;Lo;0;L;;;;;N;;;;; +18967;TANGUT COMPONENT-360;Lo;0;L;;;;;N;;;;; +18968;TANGUT COMPONENT-361;Lo;0;L;;;;;N;;;;; +18969;TANGUT COMPONENT-362;Lo;0;L;;;;;N;;;;; +1896A;TANGUT COMPONENT-363;Lo;0;L;;;;;N;;;;; +1896B;TANGUT COMPONENT-364;Lo;0;L;;;;;N;;;;; +1896C;TANGUT COMPONENT-365;Lo;0;L;;;;;N;;;;; +1896D;TANGUT COMPONENT-366;Lo;0;L;;;;;N;;;;; +1896E;TANGUT COMPONENT-367;Lo;0;L;;;;;N;;;;; +1896F;TANGUT COMPONENT-368;Lo;0;L;;;;;N;;;;; +18970;TANGUT COMPONENT-369;Lo;0;L;;;;;N;;;;; +18971;TANGUT COMPONENT-370;Lo;0;L;;;;;N;;;;; +18972;TANGUT COMPONENT-371;Lo;0;L;;;;;N;;;;; +18973;TANGUT COMPONENT-372;Lo;0;L;;;;;N;;;;; +18974;TANGUT COMPONENT-373;Lo;0;L;;;;;N;;;;; +18975;TANGUT COMPONENT-374;Lo;0;L;;;;;N;;;;; +18976;TANGUT COMPONENT-375;Lo;0;L;;;;;N;;;;; +18977;TANGUT COMPONENT-376;Lo;0;L;;;;;N;;;;; +18978;TANGUT COMPONENT-377;Lo;0;L;;;;;N;;;;; +18979;TANGUT COMPONENT-378;Lo;0;L;;;;;N;;;;; +1897A;TANGUT COMPONENT-379;Lo;0;L;;;;;N;;;;; +1897B;TANGUT COMPONENT-380;Lo;0;L;;;;;N;;;;; +1897C;TANGUT COMPONENT-381;Lo;0;L;;;;;N;;;;; +1897D;TANGUT COMPONENT-382;Lo;0;L;;;;;N;;;;; +1897E;TANGUT COMPONENT-383;Lo;0;L;;;;;N;;;;; +1897F;TANGUT COMPONENT-384;Lo;0;L;;;;;N;;;;; +18980;TANGUT COMPONENT-385;Lo;0;L;;;;;N;;;;; +18981;TANGUT COMPONENT-386;Lo;0;L;;;;;N;;;;; +18982;TANGUT COMPONENT-387;Lo;0;L;;;;;N;;;;; +18983;TANGUT COMPONENT-388;Lo;0;L;;;;;N;;;;; +18984;TANGUT COMPONENT-389;Lo;0;L;;;;;N;;;;; +18985;TANGUT COMPONENT-390;Lo;0;L;;;;;N;;;;; +18986;TANGUT COMPONENT-391;Lo;0;L;;;;;N;;;;; +18987;TANGUT COMPONENT-392;Lo;0;L;;;;;N;;;;; +18988;TANGUT COMPONENT-393;Lo;0;L;;;;;N;;;;; +18989;TANGUT COMPONENT-394;Lo;0;L;;;;;N;;;;; +1898A;TANGUT COMPONENT-395;Lo;0;L;;;;;N;;;;; +1898B;TANGUT COMPONENT-396;Lo;0;L;;;;;N;;;;; +1898C;TANGUT COMPONENT-397;Lo;0;L;;;;;N;;;;; +1898D;TANGUT COMPONENT-398;Lo;0;L;;;;;N;;;;; +1898E;TANGUT COMPONENT-399;Lo;0;L;;;;;N;;;;; +1898F;TANGUT COMPONENT-400;Lo;0;L;;;;;N;;;;; +18990;TANGUT COMPONENT-401;Lo;0;L;;;;;N;;;;; +18991;TANGUT COMPONENT-402;Lo;0;L;;;;;N;;;;; +18992;TANGUT COMPONENT-403;Lo;0;L;;;;;N;;;;; +18993;TANGUT COMPONENT-404;Lo;0;L;;;;;N;;;;; +18994;TANGUT COMPONENT-405;Lo;0;L;;;;;N;;;;; +18995;TANGUT COMPONENT-406;Lo;0;L;;;;;N;;;;; +18996;TANGUT COMPONENT-407;Lo;0;L;;;;;N;;;;; +18997;TANGUT COMPONENT-408;Lo;0;L;;;;;N;;;;; +18998;TANGUT COMPONENT-409;Lo;0;L;;;;;N;;;;; +18999;TANGUT COMPONENT-410;Lo;0;L;;;;;N;;;;; +1899A;TANGUT COMPONENT-411;Lo;0;L;;;;;N;;;;; +1899B;TANGUT COMPONENT-412;Lo;0;L;;;;;N;;;;; +1899C;TANGUT COMPONENT-413;Lo;0;L;;;;;N;;;;; +1899D;TANGUT COMPONENT-414;Lo;0;L;;;;;N;;;;; +1899E;TANGUT COMPONENT-415;Lo;0;L;;;;;N;;;;; +1899F;TANGUT COMPONENT-416;Lo;0;L;;;;;N;;;;; +189A0;TANGUT COMPONENT-417;Lo;0;L;;;;;N;;;;; +189A1;TANGUT COMPONENT-418;Lo;0;L;;;;;N;;;;; +189A2;TANGUT COMPONENT-419;Lo;0;L;;;;;N;;;;; +189A3;TANGUT COMPONENT-420;Lo;0;L;;;;;N;;;;; +189A4;TANGUT COMPONENT-421;Lo;0;L;;;;;N;;;;; +189A5;TANGUT COMPONENT-422;Lo;0;L;;;;;N;;;;; +189A6;TANGUT COMPONENT-423;Lo;0;L;;;;;N;;;;; +189A7;TANGUT COMPONENT-424;Lo;0;L;;;;;N;;;;; +189A8;TANGUT COMPONENT-425;Lo;0;L;;;;;N;;;;; +189A9;TANGUT COMPONENT-426;Lo;0;L;;;;;N;;;;; +189AA;TANGUT COMPONENT-427;Lo;0;L;;;;;N;;;;; +189AB;TANGUT COMPONENT-428;Lo;0;L;;;;;N;;;;; +189AC;TANGUT COMPONENT-429;Lo;0;L;;;;;N;;;;; +189AD;TANGUT COMPONENT-430;Lo;0;L;;;;;N;;;;; +189AE;TANGUT COMPONENT-431;Lo;0;L;;;;;N;;;;; +189AF;TANGUT COMPONENT-432;Lo;0;L;;;;;N;;;;; +189B0;TANGUT COMPONENT-433;Lo;0;L;;;;;N;;;;; +189B1;TANGUT COMPONENT-434;Lo;0;L;;;;;N;;;;; +189B2;TANGUT COMPONENT-435;Lo;0;L;;;;;N;;;;; +189B3;TANGUT COMPONENT-436;Lo;0;L;;;;;N;;;;; +189B4;TANGUT COMPONENT-437;Lo;0;L;;;;;N;;;;; +189B5;TANGUT COMPONENT-438;Lo;0;L;;;;;N;;;;; +189B6;TANGUT COMPONENT-439;Lo;0;L;;;;;N;;;;; +189B7;TANGUT COMPONENT-440;Lo;0;L;;;;;N;;;;; +189B8;TANGUT COMPONENT-441;Lo;0;L;;;;;N;;;;; +189B9;TANGUT COMPONENT-442;Lo;0;L;;;;;N;;;;; +189BA;TANGUT COMPONENT-443;Lo;0;L;;;;;N;;;;; +189BB;TANGUT COMPONENT-444;Lo;0;L;;;;;N;;;;; +189BC;TANGUT COMPONENT-445;Lo;0;L;;;;;N;;;;; +189BD;TANGUT COMPONENT-446;Lo;0;L;;;;;N;;;;; +189BE;TANGUT COMPONENT-447;Lo;0;L;;;;;N;;;;; +189BF;TANGUT COMPONENT-448;Lo;0;L;;;;;N;;;;; +189C0;TANGUT COMPONENT-449;Lo;0;L;;;;;N;;;;; +189C1;TANGUT COMPONENT-450;Lo;0;L;;;;;N;;;;; +189C2;TANGUT COMPONENT-451;Lo;0;L;;;;;N;;;;; +189C3;TANGUT COMPONENT-452;Lo;0;L;;;;;N;;;;; +189C4;TANGUT COMPONENT-453;Lo;0;L;;;;;N;;;;; +189C5;TANGUT COMPONENT-454;Lo;0;L;;;;;N;;;;; +189C6;TANGUT COMPONENT-455;Lo;0;L;;;;;N;;;;; +189C7;TANGUT COMPONENT-456;Lo;0;L;;;;;N;;;;; +189C8;TANGUT COMPONENT-457;Lo;0;L;;;;;N;;;;; +189C9;TANGUT COMPONENT-458;Lo;0;L;;;;;N;;;;; +189CA;TANGUT COMPONENT-459;Lo;0;L;;;;;N;;;;; +189CB;TANGUT COMPONENT-460;Lo;0;L;;;;;N;;;;; +189CC;TANGUT COMPONENT-461;Lo;0;L;;;;;N;;;;; +189CD;TANGUT COMPONENT-462;Lo;0;L;;;;;N;;;;; +189CE;TANGUT COMPONENT-463;Lo;0;L;;;;;N;;;;; +189CF;TANGUT COMPONENT-464;Lo;0;L;;;;;N;;;;; +189D0;TANGUT COMPONENT-465;Lo;0;L;;;;;N;;;;; +189D1;TANGUT COMPONENT-466;Lo;0;L;;;;;N;;;;; +189D2;TANGUT COMPONENT-467;Lo;0;L;;;;;N;;;;; +189D3;TANGUT COMPONENT-468;Lo;0;L;;;;;N;;;;; +189D4;TANGUT COMPONENT-469;Lo;0;L;;;;;N;;;;; +189D5;TANGUT COMPONENT-470;Lo;0;L;;;;;N;;;;; +189D6;TANGUT COMPONENT-471;Lo;0;L;;;;;N;;;;; +189D7;TANGUT COMPONENT-472;Lo;0;L;;;;;N;;;;; +189D8;TANGUT COMPONENT-473;Lo;0;L;;;;;N;;;;; +189D9;TANGUT COMPONENT-474;Lo;0;L;;;;;N;;;;; +189DA;TANGUT COMPONENT-475;Lo;0;L;;;;;N;;;;; +189DB;TANGUT COMPONENT-476;Lo;0;L;;;;;N;;;;; +189DC;TANGUT COMPONENT-477;Lo;0;L;;;;;N;;;;; +189DD;TANGUT COMPONENT-478;Lo;0;L;;;;;N;;;;; +189DE;TANGUT COMPONENT-479;Lo;0;L;;;;;N;;;;; +189DF;TANGUT COMPONENT-480;Lo;0;L;;;;;N;;;;; +189E0;TANGUT COMPONENT-481;Lo;0;L;;;;;N;;;;; +189E1;TANGUT COMPONENT-482;Lo;0;L;;;;;N;;;;; +189E2;TANGUT COMPONENT-483;Lo;0;L;;;;;N;;;;; +189E3;TANGUT COMPONENT-484;Lo;0;L;;;;;N;;;;; +189E4;TANGUT COMPONENT-485;Lo;0;L;;;;;N;;;;; +189E5;TANGUT COMPONENT-486;Lo;0;L;;;;;N;;;;; +189E6;TANGUT COMPONENT-487;Lo;0;L;;;;;N;;;;; +189E7;TANGUT COMPONENT-488;Lo;0;L;;;;;N;;;;; +189E8;TANGUT COMPONENT-489;Lo;0;L;;;;;N;;;;; +189E9;TANGUT COMPONENT-490;Lo;0;L;;;;;N;;;;; +189EA;TANGUT COMPONENT-491;Lo;0;L;;;;;N;;;;; +189EB;TANGUT COMPONENT-492;Lo;0;L;;;;;N;;;;; +189EC;TANGUT COMPONENT-493;Lo;0;L;;;;;N;;;;; +189ED;TANGUT COMPONENT-494;Lo;0;L;;;;;N;;;;; +189EE;TANGUT COMPONENT-495;Lo;0;L;;;;;N;;;;; +189EF;TANGUT COMPONENT-496;Lo;0;L;;;;;N;;;;; +189F0;TANGUT COMPONENT-497;Lo;0;L;;;;;N;;;;; +189F1;TANGUT COMPONENT-498;Lo;0;L;;;;;N;;;;; +189F2;TANGUT COMPONENT-499;Lo;0;L;;;;;N;;;;; +189F3;TANGUT COMPONENT-500;Lo;0;L;;;;;N;;;;; +189F4;TANGUT COMPONENT-501;Lo;0;L;;;;;N;;;;; +189F5;TANGUT COMPONENT-502;Lo;0;L;;;;;N;;;;; +189F6;TANGUT COMPONENT-503;Lo;0;L;;;;;N;;;;; +189F7;TANGUT COMPONENT-504;Lo;0;L;;;;;N;;;;; +189F8;TANGUT COMPONENT-505;Lo;0;L;;;;;N;;;;; +189F9;TANGUT COMPONENT-506;Lo;0;L;;;;;N;;;;; +189FA;TANGUT COMPONENT-507;Lo;0;L;;;;;N;;;;; +189FB;TANGUT COMPONENT-508;Lo;0;L;;;;;N;;;;; +189FC;TANGUT COMPONENT-509;Lo;0;L;;;;;N;;;;; +189FD;TANGUT COMPONENT-510;Lo;0;L;;;;;N;;;;; +189FE;TANGUT COMPONENT-511;Lo;0;L;;;;;N;;;;; +189FF;TANGUT COMPONENT-512;Lo;0;L;;;;;N;;;;; +18A00;TANGUT COMPONENT-513;Lo;0;L;;;;;N;;;;; +18A01;TANGUT COMPONENT-514;Lo;0;L;;;;;N;;;;; +18A02;TANGUT COMPONENT-515;Lo;0;L;;;;;N;;;;; +18A03;TANGUT COMPONENT-516;Lo;0;L;;;;;N;;;;; +18A04;TANGUT COMPONENT-517;Lo;0;L;;;;;N;;;;; +18A05;TANGUT COMPONENT-518;Lo;0;L;;;;;N;;;;; +18A06;TANGUT COMPONENT-519;Lo;0;L;;;;;N;;;;; +18A07;TANGUT COMPONENT-520;Lo;0;L;;;;;N;;;;; +18A08;TANGUT COMPONENT-521;Lo;0;L;;;;;N;;;;; +18A09;TANGUT COMPONENT-522;Lo;0;L;;;;;N;;;;; +18A0A;TANGUT COMPONENT-523;Lo;0;L;;;;;N;;;;; +18A0B;TANGUT COMPONENT-524;Lo;0;L;;;;;N;;;;; +18A0C;TANGUT COMPONENT-525;Lo;0;L;;;;;N;;;;; +18A0D;TANGUT COMPONENT-526;Lo;0;L;;;;;N;;;;; +18A0E;TANGUT COMPONENT-527;Lo;0;L;;;;;N;;;;; +18A0F;TANGUT COMPONENT-528;Lo;0;L;;;;;N;;;;; +18A10;TANGUT COMPONENT-529;Lo;0;L;;;;;N;;;;; +18A11;TANGUT COMPONENT-530;Lo;0;L;;;;;N;;;;; +18A12;TANGUT COMPONENT-531;Lo;0;L;;;;;N;;;;; +18A13;TANGUT COMPONENT-532;Lo;0;L;;;;;N;;;;; +18A14;TANGUT COMPONENT-533;Lo;0;L;;;;;N;;;;; +18A15;TANGUT COMPONENT-534;Lo;0;L;;;;;N;;;;; +18A16;TANGUT COMPONENT-535;Lo;0;L;;;;;N;;;;; +18A17;TANGUT COMPONENT-536;Lo;0;L;;;;;N;;;;; +18A18;TANGUT COMPONENT-537;Lo;0;L;;;;;N;;;;; +18A19;TANGUT COMPONENT-538;Lo;0;L;;;;;N;;;;; +18A1A;TANGUT COMPONENT-539;Lo;0;L;;;;;N;;;;; +18A1B;TANGUT COMPONENT-540;Lo;0;L;;;;;N;;;;; +18A1C;TANGUT COMPONENT-541;Lo;0;L;;;;;N;;;;; +18A1D;TANGUT COMPONENT-542;Lo;0;L;;;;;N;;;;; +18A1E;TANGUT COMPONENT-543;Lo;0;L;;;;;N;;;;; +18A1F;TANGUT COMPONENT-544;Lo;0;L;;;;;N;;;;; +18A20;TANGUT COMPONENT-545;Lo;0;L;;;;;N;;;;; +18A21;TANGUT COMPONENT-546;Lo;0;L;;;;;N;;;;; +18A22;TANGUT COMPONENT-547;Lo;0;L;;;;;N;;;;; +18A23;TANGUT COMPONENT-548;Lo;0;L;;;;;N;;;;; +18A24;TANGUT COMPONENT-549;Lo;0;L;;;;;N;;;;; +18A25;TANGUT COMPONENT-550;Lo;0;L;;;;;N;;;;; +18A26;TANGUT COMPONENT-551;Lo;0;L;;;;;N;;;;; +18A27;TANGUT COMPONENT-552;Lo;0;L;;;;;N;;;;; +18A28;TANGUT COMPONENT-553;Lo;0;L;;;;;N;;;;; +18A29;TANGUT COMPONENT-554;Lo;0;L;;;;;N;;;;; +18A2A;TANGUT COMPONENT-555;Lo;0;L;;;;;N;;;;; +18A2B;TANGUT COMPONENT-556;Lo;0;L;;;;;N;;;;; +18A2C;TANGUT COMPONENT-557;Lo;0;L;;;;;N;;;;; +18A2D;TANGUT COMPONENT-558;Lo;0;L;;;;;N;;;;; +18A2E;TANGUT COMPONENT-559;Lo;0;L;;;;;N;;;;; +18A2F;TANGUT COMPONENT-560;Lo;0;L;;;;;N;;;;; +18A30;TANGUT COMPONENT-561;Lo;0;L;;;;;N;;;;; +18A31;TANGUT COMPONENT-562;Lo;0;L;;;;;N;;;;; +18A32;TANGUT COMPONENT-563;Lo;0;L;;;;;N;;;;; +18A33;TANGUT COMPONENT-564;Lo;0;L;;;;;N;;;;; +18A34;TANGUT COMPONENT-565;Lo;0;L;;;;;N;;;;; +18A35;TANGUT COMPONENT-566;Lo;0;L;;;;;N;;;;; +18A36;TANGUT COMPONENT-567;Lo;0;L;;;;;N;;;;; +18A37;TANGUT COMPONENT-568;Lo;0;L;;;;;N;;;;; +18A38;TANGUT COMPONENT-569;Lo;0;L;;;;;N;;;;; +18A39;TANGUT COMPONENT-570;Lo;0;L;;;;;N;;;;; +18A3A;TANGUT COMPONENT-571;Lo;0;L;;;;;N;;;;; +18A3B;TANGUT COMPONENT-572;Lo;0;L;;;;;N;;;;; +18A3C;TANGUT COMPONENT-573;Lo;0;L;;;;;N;;;;; +18A3D;TANGUT COMPONENT-574;Lo;0;L;;;;;N;;;;; +18A3E;TANGUT COMPONENT-575;Lo;0;L;;;;;N;;;;; +18A3F;TANGUT COMPONENT-576;Lo;0;L;;;;;N;;;;; +18A40;TANGUT COMPONENT-577;Lo;0;L;;;;;N;;;;; +18A41;TANGUT COMPONENT-578;Lo;0;L;;;;;N;;;;; +18A42;TANGUT COMPONENT-579;Lo;0;L;;;;;N;;;;; +18A43;TANGUT COMPONENT-580;Lo;0;L;;;;;N;;;;; +18A44;TANGUT COMPONENT-581;Lo;0;L;;;;;N;;;;; +18A45;TANGUT COMPONENT-582;Lo;0;L;;;;;N;;;;; +18A46;TANGUT COMPONENT-583;Lo;0;L;;;;;N;;;;; +18A47;TANGUT COMPONENT-584;Lo;0;L;;;;;N;;;;; +18A48;TANGUT COMPONENT-585;Lo;0;L;;;;;N;;;;; +18A49;TANGUT COMPONENT-586;Lo;0;L;;;;;N;;;;; +18A4A;TANGUT COMPONENT-587;Lo;0;L;;;;;N;;;;; +18A4B;TANGUT COMPONENT-588;Lo;0;L;;;;;N;;;;; +18A4C;TANGUT COMPONENT-589;Lo;0;L;;;;;N;;;;; +18A4D;TANGUT COMPONENT-590;Lo;0;L;;;;;N;;;;; +18A4E;TANGUT COMPONENT-591;Lo;0;L;;;;;N;;;;; +18A4F;TANGUT COMPONENT-592;Lo;0;L;;;;;N;;;;; +18A50;TANGUT COMPONENT-593;Lo;0;L;;;;;N;;;;; +18A51;TANGUT COMPONENT-594;Lo;0;L;;;;;N;;;;; +18A52;TANGUT COMPONENT-595;Lo;0;L;;;;;N;;;;; +18A53;TANGUT COMPONENT-596;Lo;0;L;;;;;N;;;;; +18A54;TANGUT COMPONENT-597;Lo;0;L;;;;;N;;;;; +18A55;TANGUT COMPONENT-598;Lo;0;L;;;;;N;;;;; +18A56;TANGUT COMPONENT-599;Lo;0;L;;;;;N;;;;; +18A57;TANGUT COMPONENT-600;Lo;0;L;;;;;N;;;;; +18A58;TANGUT COMPONENT-601;Lo;0;L;;;;;N;;;;; +18A59;TANGUT COMPONENT-602;Lo;0;L;;;;;N;;;;; +18A5A;TANGUT COMPONENT-603;Lo;0;L;;;;;N;;;;; +18A5B;TANGUT COMPONENT-604;Lo;0;L;;;;;N;;;;; +18A5C;TANGUT COMPONENT-605;Lo;0;L;;;;;N;;;;; +18A5D;TANGUT COMPONENT-606;Lo;0;L;;;;;N;;;;; +18A5E;TANGUT COMPONENT-607;Lo;0;L;;;;;N;;;;; +18A5F;TANGUT COMPONENT-608;Lo;0;L;;;;;N;;;;; +18A60;TANGUT COMPONENT-609;Lo;0;L;;;;;N;;;;; +18A61;TANGUT COMPONENT-610;Lo;0;L;;;;;N;;;;; +18A62;TANGUT COMPONENT-611;Lo;0;L;;;;;N;;;;; +18A63;TANGUT COMPONENT-612;Lo;0;L;;;;;N;;;;; +18A64;TANGUT COMPONENT-613;Lo;0;L;;;;;N;;;;; +18A65;TANGUT COMPONENT-614;Lo;0;L;;;;;N;;;;; +18A66;TANGUT COMPONENT-615;Lo;0;L;;;;;N;;;;; +18A67;TANGUT COMPONENT-616;Lo;0;L;;;;;N;;;;; +18A68;TANGUT COMPONENT-617;Lo;0;L;;;;;N;;;;; +18A69;TANGUT COMPONENT-618;Lo;0;L;;;;;N;;;;; +18A6A;TANGUT COMPONENT-619;Lo;0;L;;;;;N;;;;; +18A6B;TANGUT COMPONENT-620;Lo;0;L;;;;;N;;;;; +18A6C;TANGUT COMPONENT-621;Lo;0;L;;;;;N;;;;; +18A6D;TANGUT COMPONENT-622;Lo;0;L;;;;;N;;;;; +18A6E;TANGUT COMPONENT-623;Lo;0;L;;;;;N;;;;; +18A6F;TANGUT COMPONENT-624;Lo;0;L;;;;;N;;;;; +18A70;TANGUT COMPONENT-625;Lo;0;L;;;;;N;;;;; +18A71;TANGUT COMPONENT-626;Lo;0;L;;;;;N;;;;; +18A72;TANGUT COMPONENT-627;Lo;0;L;;;;;N;;;;; +18A73;TANGUT COMPONENT-628;Lo;0;L;;;;;N;;;;; +18A74;TANGUT COMPONENT-629;Lo;0;L;;;;;N;;;;; +18A75;TANGUT COMPONENT-630;Lo;0;L;;;;;N;;;;; +18A76;TANGUT COMPONENT-631;Lo;0;L;;;;;N;;;;; +18A77;TANGUT COMPONENT-632;Lo;0;L;;;;;N;;;;; +18A78;TANGUT COMPONENT-633;Lo;0;L;;;;;N;;;;; +18A79;TANGUT COMPONENT-634;Lo;0;L;;;;;N;;;;; +18A7A;TANGUT COMPONENT-635;Lo;0;L;;;;;N;;;;; +18A7B;TANGUT COMPONENT-636;Lo;0;L;;;;;N;;;;; +18A7C;TANGUT COMPONENT-637;Lo;0;L;;;;;N;;;;; +18A7D;TANGUT COMPONENT-638;Lo;0;L;;;;;N;;;;; +18A7E;TANGUT COMPONENT-639;Lo;0;L;;;;;N;;;;; +18A7F;TANGUT COMPONENT-640;Lo;0;L;;;;;N;;;;; +18A80;TANGUT COMPONENT-641;Lo;0;L;;;;;N;;;;; +18A81;TANGUT COMPONENT-642;Lo;0;L;;;;;N;;;;; +18A82;TANGUT COMPONENT-643;Lo;0;L;;;;;N;;;;; +18A83;TANGUT COMPONENT-644;Lo;0;L;;;;;N;;;;; +18A84;TANGUT COMPONENT-645;Lo;0;L;;;;;N;;;;; +18A85;TANGUT COMPONENT-646;Lo;0;L;;;;;N;;;;; +18A86;TANGUT COMPONENT-647;Lo;0;L;;;;;N;;;;; +18A87;TANGUT COMPONENT-648;Lo;0;L;;;;;N;;;;; +18A88;TANGUT COMPONENT-649;Lo;0;L;;;;;N;;;;; +18A89;TANGUT COMPONENT-650;Lo;0;L;;;;;N;;;;; +18A8A;TANGUT COMPONENT-651;Lo;0;L;;;;;N;;;;; +18A8B;TANGUT COMPONENT-652;Lo;0;L;;;;;N;;;;; +18A8C;TANGUT COMPONENT-653;Lo;0;L;;;;;N;;;;; +18A8D;TANGUT COMPONENT-654;Lo;0;L;;;;;N;;;;; +18A8E;TANGUT COMPONENT-655;Lo;0;L;;;;;N;;;;; +18A8F;TANGUT COMPONENT-656;Lo;0;L;;;;;N;;;;; +18A90;TANGUT COMPONENT-657;Lo;0;L;;;;;N;;;;; +18A91;TANGUT COMPONENT-658;Lo;0;L;;;;;N;;;;; +18A92;TANGUT COMPONENT-659;Lo;0;L;;;;;N;;;;; +18A93;TANGUT COMPONENT-660;Lo;0;L;;;;;N;;;;; +18A94;TANGUT COMPONENT-661;Lo;0;L;;;;;N;;;;; +18A95;TANGUT COMPONENT-662;Lo;0;L;;;;;N;;;;; +18A96;TANGUT COMPONENT-663;Lo;0;L;;;;;N;;;;; +18A97;TANGUT COMPONENT-664;Lo;0;L;;;;;N;;;;; +18A98;TANGUT COMPONENT-665;Lo;0;L;;;;;N;;;;; +18A99;TANGUT COMPONENT-666;Lo;0;L;;;;;N;;;;; +18A9A;TANGUT COMPONENT-667;Lo;0;L;;;;;N;;;;; +18A9B;TANGUT COMPONENT-668;Lo;0;L;;;;;N;;;;; +18A9C;TANGUT COMPONENT-669;Lo;0;L;;;;;N;;;;; +18A9D;TANGUT COMPONENT-670;Lo;0;L;;;;;N;;;;; +18A9E;TANGUT COMPONENT-671;Lo;0;L;;;;;N;;;;; +18A9F;TANGUT COMPONENT-672;Lo;0;L;;;;;N;;;;; +18AA0;TANGUT COMPONENT-673;Lo;0;L;;;;;N;;;;; +18AA1;TANGUT COMPONENT-674;Lo;0;L;;;;;N;;;;; +18AA2;TANGUT COMPONENT-675;Lo;0;L;;;;;N;;;;; +18AA3;TANGUT COMPONENT-676;Lo;0;L;;;;;N;;;;; +18AA4;TANGUT COMPONENT-677;Lo;0;L;;;;;N;;;;; +18AA5;TANGUT COMPONENT-678;Lo;0;L;;;;;N;;;;; +18AA6;TANGUT COMPONENT-679;Lo;0;L;;;;;N;;;;; +18AA7;TANGUT COMPONENT-680;Lo;0;L;;;;;N;;;;; +18AA8;TANGUT COMPONENT-681;Lo;0;L;;;;;N;;;;; +18AA9;TANGUT COMPONENT-682;Lo;0;L;;;;;N;;;;; +18AAA;TANGUT COMPONENT-683;Lo;0;L;;;;;N;;;;; +18AAB;TANGUT COMPONENT-684;Lo;0;L;;;;;N;;;;; +18AAC;TANGUT COMPONENT-685;Lo;0;L;;;;;N;;;;; +18AAD;TANGUT COMPONENT-686;Lo;0;L;;;;;N;;;;; +18AAE;TANGUT COMPONENT-687;Lo;0;L;;;;;N;;;;; +18AAF;TANGUT COMPONENT-688;Lo;0;L;;;;;N;;;;; +18AB0;TANGUT COMPONENT-689;Lo;0;L;;;;;N;;;;; +18AB1;TANGUT COMPONENT-690;Lo;0;L;;;;;N;;;;; +18AB2;TANGUT COMPONENT-691;Lo;0;L;;;;;N;;;;; +18AB3;TANGUT COMPONENT-692;Lo;0;L;;;;;N;;;;; +18AB4;TANGUT COMPONENT-693;Lo;0;L;;;;;N;;;;; +18AB5;TANGUT COMPONENT-694;Lo;0;L;;;;;N;;;;; +18AB6;TANGUT COMPONENT-695;Lo;0;L;;;;;N;;;;; +18AB7;TANGUT COMPONENT-696;Lo;0;L;;;;;N;;;;; +18AB8;TANGUT COMPONENT-697;Lo;0;L;;;;;N;;;;; +18AB9;TANGUT COMPONENT-698;Lo;0;L;;;;;N;;;;; +18ABA;TANGUT COMPONENT-699;Lo;0;L;;;;;N;;;;; +18ABB;TANGUT COMPONENT-700;Lo;0;L;;;;;N;;;;; +18ABC;TANGUT COMPONENT-701;Lo;0;L;;;;;N;;;;; +18ABD;TANGUT COMPONENT-702;Lo;0;L;;;;;N;;;;; +18ABE;TANGUT COMPONENT-703;Lo;0;L;;;;;N;;;;; +18ABF;TANGUT COMPONENT-704;Lo;0;L;;;;;N;;;;; +18AC0;TANGUT COMPONENT-705;Lo;0;L;;;;;N;;;;; +18AC1;TANGUT COMPONENT-706;Lo;0;L;;;;;N;;;;; +18AC2;TANGUT COMPONENT-707;Lo;0;L;;;;;N;;;;; +18AC3;TANGUT COMPONENT-708;Lo;0;L;;;;;N;;;;; +18AC4;TANGUT COMPONENT-709;Lo;0;L;;;;;N;;;;; +18AC5;TANGUT COMPONENT-710;Lo;0;L;;;;;N;;;;; +18AC6;TANGUT COMPONENT-711;Lo;0;L;;;;;N;;;;; +18AC7;TANGUT COMPONENT-712;Lo;0;L;;;;;N;;;;; +18AC8;TANGUT COMPONENT-713;Lo;0;L;;;;;N;;;;; +18AC9;TANGUT COMPONENT-714;Lo;0;L;;;;;N;;;;; +18ACA;TANGUT COMPONENT-715;Lo;0;L;;;;;N;;;;; +18ACB;TANGUT COMPONENT-716;Lo;0;L;;;;;N;;;;; +18ACC;TANGUT COMPONENT-717;Lo;0;L;;;;;N;;;;; +18ACD;TANGUT COMPONENT-718;Lo;0;L;;;;;N;;;;; +18ACE;TANGUT COMPONENT-719;Lo;0;L;;;;;N;;;;; +18ACF;TANGUT COMPONENT-720;Lo;0;L;;;;;N;;;;; +18AD0;TANGUT COMPONENT-721;Lo;0;L;;;;;N;;;;; +18AD1;TANGUT COMPONENT-722;Lo;0;L;;;;;N;;;;; +18AD2;TANGUT COMPONENT-723;Lo;0;L;;;;;N;;;;; +18AD3;TANGUT COMPONENT-724;Lo;0;L;;;;;N;;;;; +18AD4;TANGUT COMPONENT-725;Lo;0;L;;;;;N;;;;; +18AD5;TANGUT COMPONENT-726;Lo;0;L;;;;;N;;;;; +18AD6;TANGUT COMPONENT-727;Lo;0;L;;;;;N;;;;; +18AD7;TANGUT COMPONENT-728;Lo;0;L;;;;;N;;;;; +18AD8;TANGUT COMPONENT-729;Lo;0;L;;;;;N;;;;; +18AD9;TANGUT COMPONENT-730;Lo;0;L;;;;;N;;;;; +18ADA;TANGUT COMPONENT-731;Lo;0;L;;;;;N;;;;; +18ADB;TANGUT COMPONENT-732;Lo;0;L;;;;;N;;;;; +18ADC;TANGUT COMPONENT-733;Lo;0;L;;;;;N;;;;; +18ADD;TANGUT COMPONENT-734;Lo;0;L;;;;;N;;;;; +18ADE;TANGUT COMPONENT-735;Lo;0;L;;;;;N;;;;; +18ADF;TANGUT COMPONENT-736;Lo;0;L;;;;;N;;;;; +18AE0;TANGUT COMPONENT-737;Lo;0;L;;;;;N;;;;; +18AE1;TANGUT COMPONENT-738;Lo;0;L;;;;;N;;;;; +18AE2;TANGUT COMPONENT-739;Lo;0;L;;;;;N;;;;; +18AE3;TANGUT COMPONENT-740;Lo;0;L;;;;;N;;;;; +18AE4;TANGUT COMPONENT-741;Lo;0;L;;;;;N;;;;; +18AE5;TANGUT COMPONENT-742;Lo;0;L;;;;;N;;;;; +18AE6;TANGUT COMPONENT-743;Lo;0;L;;;;;N;;;;; +18AE7;TANGUT COMPONENT-744;Lo;0;L;;;;;N;;;;; +18AE8;TANGUT COMPONENT-745;Lo;0;L;;;;;N;;;;; +18AE9;TANGUT COMPONENT-746;Lo;0;L;;;;;N;;;;; +18AEA;TANGUT COMPONENT-747;Lo;0;L;;;;;N;;;;; +18AEB;TANGUT COMPONENT-748;Lo;0;L;;;;;N;;;;; +18AEC;TANGUT COMPONENT-749;Lo;0;L;;;;;N;;;;; +18AED;TANGUT COMPONENT-750;Lo;0;L;;;;;N;;;;; +18AEE;TANGUT COMPONENT-751;Lo;0;L;;;;;N;;;;; +18AEF;TANGUT COMPONENT-752;Lo;0;L;;;;;N;;;;; +18AF0;TANGUT COMPONENT-753;Lo;0;L;;;;;N;;;;; +18AF1;TANGUT COMPONENT-754;Lo;0;L;;;;;N;;;;; +18AF2;TANGUT COMPONENT-755;Lo;0;L;;;;;N;;;;; 1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; 1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; +1B002;HENTAIGANA LETTER A-1;Lo;0;L;;;;;N;;;;; +1B003;HENTAIGANA LETTER A-2;Lo;0;L;;;;;N;;;;; +1B004;HENTAIGANA LETTER A-3;Lo;0;L;;;;;N;;;;; +1B005;HENTAIGANA LETTER A-WO;Lo;0;L;;;;;N;;;;; +1B006;HENTAIGANA LETTER I-1;Lo;0;L;;;;;N;;;;; +1B007;HENTAIGANA LETTER I-2;Lo;0;L;;;;;N;;;;; +1B008;HENTAIGANA LETTER I-3;Lo;0;L;;;;;N;;;;; +1B009;HENTAIGANA LETTER I-4;Lo;0;L;;;;;N;;;;; +1B00A;HENTAIGANA LETTER U-1;Lo;0;L;;;;;N;;;;; +1B00B;HENTAIGANA LETTER U-2;Lo;0;L;;;;;N;;;;; +1B00C;HENTAIGANA LETTER U-3;Lo;0;L;;;;;N;;;;; +1B00D;HENTAIGANA LETTER U-4;Lo;0;L;;;;;N;;;;; +1B00E;HENTAIGANA LETTER U-5;Lo;0;L;;;;;N;;;;; +1B00F;HENTAIGANA LETTER E-2;Lo;0;L;;;;;N;;;;; +1B010;HENTAIGANA LETTER E-3;Lo;0;L;;;;;N;;;;; +1B011;HENTAIGANA LETTER E-4;Lo;0;L;;;;;N;;;;; +1B012;HENTAIGANA LETTER E-5;Lo;0;L;;;;;N;;;;; +1B013;HENTAIGANA LETTER E-6;Lo;0;L;;;;;N;;;;; +1B014;HENTAIGANA LETTER O-1;Lo;0;L;;;;;N;;;;; +1B015;HENTAIGANA LETTER O-2;Lo;0;L;;;;;N;;;;; +1B016;HENTAIGANA LETTER O-3;Lo;0;L;;;;;N;;;;; +1B017;HENTAIGANA LETTER KA-1;Lo;0;L;;;;;N;;;;; +1B018;HENTAIGANA LETTER KA-2;Lo;0;L;;;;;N;;;;; +1B019;HENTAIGANA LETTER KA-3;Lo;0;L;;;;;N;;;;; +1B01A;HENTAIGANA LETTER KA-4;Lo;0;L;;;;;N;;;;; +1B01B;HENTAIGANA LETTER KA-5;Lo;0;L;;;;;N;;;;; +1B01C;HENTAIGANA LETTER KA-6;Lo;0;L;;;;;N;;;;; +1B01D;HENTAIGANA LETTER KA-7;Lo;0;L;;;;;N;;;;; +1B01E;HENTAIGANA LETTER KA-8;Lo;0;L;;;;;N;;;;; +1B01F;HENTAIGANA LETTER KA-9;Lo;0;L;;;;;N;;;;; +1B020;HENTAIGANA LETTER KA-10;Lo;0;L;;;;;N;;;;; +1B021;HENTAIGANA LETTER KA-11;Lo;0;L;;;;;N;;;;; +1B022;HENTAIGANA LETTER KA-KE;Lo;0;L;;;;;N;;;;; +1B023;HENTAIGANA LETTER KI-1;Lo;0;L;;;;;N;;;;; +1B024;HENTAIGANA LETTER KI-2;Lo;0;L;;;;;N;;;;; +1B025;HENTAIGANA LETTER KI-3;Lo;0;L;;;;;N;;;;; +1B026;HENTAIGANA LETTER KI-4;Lo;0;L;;;;;N;;;;; +1B027;HENTAIGANA LETTER KI-5;Lo;0;L;;;;;N;;;;; +1B028;HENTAIGANA LETTER KI-6;Lo;0;L;;;;;N;;;;; +1B029;HENTAIGANA LETTER KI-7;Lo;0;L;;;;;N;;;;; +1B02A;HENTAIGANA LETTER KI-8;Lo;0;L;;;;;N;;;;; +1B02B;HENTAIGANA LETTER KU-1;Lo;0;L;;;;;N;;;;; +1B02C;HENTAIGANA LETTER KU-2;Lo;0;L;;;;;N;;;;; +1B02D;HENTAIGANA LETTER KU-3;Lo;0;L;;;;;N;;;;; +1B02E;HENTAIGANA LETTER KU-4;Lo;0;L;;;;;N;;;;; +1B02F;HENTAIGANA LETTER KU-5;Lo;0;L;;;;;N;;;;; +1B030;HENTAIGANA LETTER KU-6;Lo;0;L;;;;;N;;;;; +1B031;HENTAIGANA LETTER KU-7;Lo;0;L;;;;;N;;;;; +1B032;HENTAIGANA LETTER KE-1;Lo;0;L;;;;;N;;;;; +1B033;HENTAIGANA LETTER KE-2;Lo;0;L;;;;;N;;;;; +1B034;HENTAIGANA LETTER KE-3;Lo;0;L;;;;;N;;;;; +1B035;HENTAIGANA LETTER KE-4;Lo;0;L;;;;;N;;;;; +1B036;HENTAIGANA LETTER KE-5;Lo;0;L;;;;;N;;;;; +1B037;HENTAIGANA LETTER KE-6;Lo;0;L;;;;;N;;;;; +1B038;HENTAIGANA LETTER KO-1;Lo;0;L;;;;;N;;;;; +1B039;HENTAIGANA LETTER KO-2;Lo;0;L;;;;;N;;;;; +1B03A;HENTAIGANA LETTER KO-3;Lo;0;L;;;;;N;;;;; +1B03B;HENTAIGANA LETTER KO-KI;Lo;0;L;;;;;N;;;;; +1B03C;HENTAIGANA LETTER SA-1;Lo;0;L;;;;;N;;;;; +1B03D;HENTAIGANA LETTER SA-2;Lo;0;L;;;;;N;;;;; +1B03E;HENTAIGANA LETTER SA-3;Lo;0;L;;;;;N;;;;; +1B03F;HENTAIGANA LETTER SA-4;Lo;0;L;;;;;N;;;;; +1B040;HENTAIGANA LETTER SA-5;Lo;0;L;;;;;N;;;;; +1B041;HENTAIGANA LETTER SA-6;Lo;0;L;;;;;N;;;;; +1B042;HENTAIGANA LETTER SA-7;Lo;0;L;;;;;N;;;;; +1B043;HENTAIGANA LETTER SA-8;Lo;0;L;;;;;N;;;;; +1B044;HENTAIGANA LETTER SI-1;Lo;0;L;;;;;N;;;;; +1B045;HENTAIGANA LETTER SI-2;Lo;0;L;;;;;N;;;;; +1B046;HENTAIGANA LETTER SI-3;Lo;0;L;;;;;N;;;;; +1B047;HENTAIGANA LETTER SI-4;Lo;0;L;;;;;N;;;;; +1B048;HENTAIGANA LETTER SI-5;Lo;0;L;;;;;N;;;;; +1B049;HENTAIGANA LETTER SI-6;Lo;0;L;;;;;N;;;;; +1B04A;HENTAIGANA LETTER SU-1;Lo;0;L;;;;;N;;;;; +1B04B;HENTAIGANA LETTER SU-2;Lo;0;L;;;;;N;;;;; +1B04C;HENTAIGANA LETTER SU-3;Lo;0;L;;;;;N;;;;; +1B04D;HENTAIGANA LETTER SU-4;Lo;0;L;;;;;N;;;;; +1B04E;HENTAIGANA LETTER SU-5;Lo;0;L;;;;;N;;;;; +1B04F;HENTAIGANA LETTER SU-6;Lo;0;L;;;;;N;;;;; +1B050;HENTAIGANA LETTER SU-7;Lo;0;L;;;;;N;;;;; +1B051;HENTAIGANA LETTER SU-8;Lo;0;L;;;;;N;;;;; +1B052;HENTAIGANA LETTER SE-1;Lo;0;L;;;;;N;;;;; +1B053;HENTAIGANA LETTER SE-2;Lo;0;L;;;;;N;;;;; +1B054;HENTAIGANA LETTER SE-3;Lo;0;L;;;;;N;;;;; +1B055;HENTAIGANA LETTER SE-4;Lo;0;L;;;;;N;;;;; +1B056;HENTAIGANA LETTER SE-5;Lo;0;L;;;;;N;;;;; +1B057;HENTAIGANA LETTER SO-1;Lo;0;L;;;;;N;;;;; +1B058;HENTAIGANA LETTER SO-2;Lo;0;L;;;;;N;;;;; +1B059;HENTAIGANA LETTER SO-3;Lo;0;L;;;;;N;;;;; +1B05A;HENTAIGANA LETTER SO-4;Lo;0;L;;;;;N;;;;; +1B05B;HENTAIGANA LETTER SO-5;Lo;0;L;;;;;N;;;;; +1B05C;HENTAIGANA LETTER SO-6;Lo;0;L;;;;;N;;;;; +1B05D;HENTAIGANA LETTER SO-7;Lo;0;L;;;;;N;;;;; +1B05E;HENTAIGANA LETTER TA-1;Lo;0;L;;;;;N;;;;; +1B05F;HENTAIGANA LETTER TA-2;Lo;0;L;;;;;N;;;;; +1B060;HENTAIGANA LETTER TA-3;Lo;0;L;;;;;N;;;;; +1B061;HENTAIGANA LETTER TA-4;Lo;0;L;;;;;N;;;;; +1B062;HENTAIGANA LETTER TI-1;Lo;0;L;;;;;N;;;;; +1B063;HENTAIGANA LETTER TI-2;Lo;0;L;;;;;N;;;;; +1B064;HENTAIGANA LETTER TI-3;Lo;0;L;;;;;N;;;;; +1B065;HENTAIGANA LETTER TI-4;Lo;0;L;;;;;N;;;;; +1B066;HENTAIGANA LETTER TI-5;Lo;0;L;;;;;N;;;;; +1B067;HENTAIGANA LETTER TI-6;Lo;0;L;;;;;N;;;;; +1B068;HENTAIGANA LETTER TI-7;Lo;0;L;;;;;N;;;;; +1B069;HENTAIGANA LETTER TU-1;Lo;0;L;;;;;N;;;;; +1B06A;HENTAIGANA LETTER TU-2;Lo;0;L;;;;;N;;;;; +1B06B;HENTAIGANA LETTER TU-3;Lo;0;L;;;;;N;;;;; +1B06C;HENTAIGANA LETTER TU-4;Lo;0;L;;;;;N;;;;; +1B06D;HENTAIGANA LETTER TU-TO;Lo;0;L;;;;;N;;;;; +1B06E;HENTAIGANA LETTER TE-1;Lo;0;L;;;;;N;;;;; +1B06F;HENTAIGANA LETTER TE-2;Lo;0;L;;;;;N;;;;; +1B070;HENTAIGANA LETTER TE-3;Lo;0;L;;;;;N;;;;; +1B071;HENTAIGANA LETTER TE-4;Lo;0;L;;;;;N;;;;; +1B072;HENTAIGANA LETTER TE-5;Lo;0;L;;;;;N;;;;; +1B073;HENTAIGANA LETTER TE-6;Lo;0;L;;;;;N;;;;; +1B074;HENTAIGANA LETTER TE-7;Lo;0;L;;;;;N;;;;; +1B075;HENTAIGANA LETTER TE-8;Lo;0;L;;;;;N;;;;; +1B076;HENTAIGANA LETTER TE-9;Lo;0;L;;;;;N;;;;; +1B077;HENTAIGANA LETTER TO-1;Lo;0;L;;;;;N;;;;; +1B078;HENTAIGANA LETTER TO-2;Lo;0;L;;;;;N;;;;; +1B079;HENTAIGANA LETTER TO-3;Lo;0;L;;;;;N;;;;; +1B07A;HENTAIGANA LETTER TO-4;Lo;0;L;;;;;N;;;;; +1B07B;HENTAIGANA LETTER TO-5;Lo;0;L;;;;;N;;;;; +1B07C;HENTAIGANA LETTER TO-6;Lo;0;L;;;;;N;;;;; +1B07D;HENTAIGANA LETTER TO-RA;Lo;0;L;;;;;N;;;;; +1B07E;HENTAIGANA LETTER NA-1;Lo;0;L;;;;;N;;;;; +1B07F;HENTAIGANA LETTER NA-2;Lo;0;L;;;;;N;;;;; +1B080;HENTAIGANA LETTER NA-3;Lo;0;L;;;;;N;;;;; +1B081;HENTAIGANA LETTER NA-4;Lo;0;L;;;;;N;;;;; +1B082;HENTAIGANA LETTER NA-5;Lo;0;L;;;;;N;;;;; +1B083;HENTAIGANA LETTER NA-6;Lo;0;L;;;;;N;;;;; +1B084;HENTAIGANA LETTER NA-7;Lo;0;L;;;;;N;;;;; +1B085;HENTAIGANA LETTER NA-8;Lo;0;L;;;;;N;;;;; +1B086;HENTAIGANA LETTER NA-9;Lo;0;L;;;;;N;;;;; +1B087;HENTAIGANA LETTER NI-1;Lo;0;L;;;;;N;;;;; +1B088;HENTAIGANA LETTER NI-2;Lo;0;L;;;;;N;;;;; +1B089;HENTAIGANA LETTER NI-3;Lo;0;L;;;;;N;;;;; +1B08A;HENTAIGANA LETTER NI-4;Lo;0;L;;;;;N;;;;; +1B08B;HENTAIGANA LETTER NI-5;Lo;0;L;;;;;N;;;;; +1B08C;HENTAIGANA LETTER NI-6;Lo;0;L;;;;;N;;;;; +1B08D;HENTAIGANA LETTER NI-7;Lo;0;L;;;;;N;;;;; +1B08E;HENTAIGANA LETTER NI-TE;Lo;0;L;;;;;N;;;;; +1B08F;HENTAIGANA LETTER NU-1;Lo;0;L;;;;;N;;;;; +1B090;HENTAIGANA LETTER NU-2;Lo;0;L;;;;;N;;;;; +1B091;HENTAIGANA LETTER NU-3;Lo;0;L;;;;;N;;;;; +1B092;HENTAIGANA LETTER NE-1;Lo;0;L;;;;;N;;;;; +1B093;HENTAIGANA LETTER NE-2;Lo;0;L;;;;;N;;;;; +1B094;HENTAIGANA LETTER NE-3;Lo;0;L;;;;;N;;;;; +1B095;HENTAIGANA LETTER NE-4;Lo;0;L;;;;;N;;;;; +1B096;HENTAIGANA LETTER NE-5;Lo;0;L;;;;;N;;;;; +1B097;HENTAIGANA LETTER NE-6;Lo;0;L;;;;;N;;;;; +1B098;HENTAIGANA LETTER NE-KO;Lo;0;L;;;;;N;;;;; +1B099;HENTAIGANA LETTER NO-1;Lo;0;L;;;;;N;;;;; +1B09A;HENTAIGANA LETTER NO-2;Lo;0;L;;;;;N;;;;; +1B09B;HENTAIGANA LETTER NO-3;Lo;0;L;;;;;N;;;;; +1B09C;HENTAIGANA LETTER NO-4;Lo;0;L;;;;;N;;;;; +1B09D;HENTAIGANA LETTER NO-5;Lo;0;L;;;;;N;;;;; +1B09E;HENTAIGANA LETTER HA-1;Lo;0;L;;;;;N;;;;; +1B09F;HENTAIGANA LETTER HA-2;Lo;0;L;;;;;N;;;;; +1B0A0;HENTAIGANA LETTER HA-3;Lo;0;L;;;;;N;;;;; +1B0A1;HENTAIGANA LETTER HA-4;Lo;0;L;;;;;N;;;;; +1B0A2;HENTAIGANA LETTER HA-5;Lo;0;L;;;;;N;;;;; +1B0A3;HENTAIGANA LETTER HA-6;Lo;0;L;;;;;N;;;;; +1B0A4;HENTAIGANA LETTER HA-7;Lo;0;L;;;;;N;;;;; +1B0A5;HENTAIGANA LETTER HA-8;Lo;0;L;;;;;N;;;;; +1B0A6;HENTAIGANA LETTER HA-9;Lo;0;L;;;;;N;;;;; +1B0A7;HENTAIGANA LETTER HA-10;Lo;0;L;;;;;N;;;;; +1B0A8;HENTAIGANA LETTER HA-11;Lo;0;L;;;;;N;;;;; +1B0A9;HENTAIGANA LETTER HI-1;Lo;0;L;;;;;N;;;;; +1B0AA;HENTAIGANA LETTER HI-2;Lo;0;L;;;;;N;;;;; +1B0AB;HENTAIGANA LETTER HI-3;Lo;0;L;;;;;N;;;;; +1B0AC;HENTAIGANA LETTER HI-4;Lo;0;L;;;;;N;;;;; +1B0AD;HENTAIGANA LETTER HI-5;Lo;0;L;;;;;N;;;;; +1B0AE;HENTAIGANA LETTER HI-6;Lo;0;L;;;;;N;;;;; +1B0AF;HENTAIGANA LETTER HI-7;Lo;0;L;;;;;N;;;;; +1B0B0;HENTAIGANA LETTER HU-1;Lo;0;L;;;;;N;;;;; +1B0B1;HENTAIGANA LETTER HU-2;Lo;0;L;;;;;N;;;;; +1B0B2;HENTAIGANA LETTER HU-3;Lo;0;L;;;;;N;;;;; +1B0B3;HENTAIGANA LETTER HE-1;Lo;0;L;;;;;N;;;;; +1B0B4;HENTAIGANA LETTER HE-2;Lo;0;L;;;;;N;;;;; +1B0B5;HENTAIGANA LETTER HE-3;Lo;0;L;;;;;N;;;;; +1B0B6;HENTAIGANA LETTER HE-4;Lo;0;L;;;;;N;;;;; +1B0B7;HENTAIGANA LETTER HE-5;Lo;0;L;;;;;N;;;;; +1B0B8;HENTAIGANA LETTER HE-6;Lo;0;L;;;;;N;;;;; +1B0B9;HENTAIGANA LETTER HE-7;Lo;0;L;;;;;N;;;;; +1B0BA;HENTAIGANA LETTER HO-1;Lo;0;L;;;;;N;;;;; +1B0BB;HENTAIGANA LETTER HO-2;Lo;0;L;;;;;N;;;;; +1B0BC;HENTAIGANA LETTER HO-3;Lo;0;L;;;;;N;;;;; +1B0BD;HENTAIGANA LETTER HO-4;Lo;0;L;;;;;N;;;;; +1B0BE;HENTAIGANA LETTER HO-5;Lo;0;L;;;;;N;;;;; +1B0BF;HENTAIGANA LETTER HO-6;Lo;0;L;;;;;N;;;;; +1B0C0;HENTAIGANA LETTER HO-7;Lo;0;L;;;;;N;;;;; +1B0C1;HENTAIGANA LETTER HO-8;Lo;0;L;;;;;N;;;;; +1B0C2;HENTAIGANA LETTER MA-1;Lo;0;L;;;;;N;;;;; +1B0C3;HENTAIGANA LETTER MA-2;Lo;0;L;;;;;N;;;;; +1B0C4;HENTAIGANA LETTER MA-3;Lo;0;L;;;;;N;;;;; +1B0C5;HENTAIGANA LETTER MA-4;Lo;0;L;;;;;N;;;;; +1B0C6;HENTAIGANA LETTER MA-5;Lo;0;L;;;;;N;;;;; +1B0C7;HENTAIGANA LETTER MA-6;Lo;0;L;;;;;N;;;;; +1B0C8;HENTAIGANA LETTER MA-7;Lo;0;L;;;;;N;;;;; +1B0C9;HENTAIGANA LETTER MI-1;Lo;0;L;;;;;N;;;;; +1B0CA;HENTAIGANA LETTER MI-2;Lo;0;L;;;;;N;;;;; +1B0CB;HENTAIGANA LETTER MI-3;Lo;0;L;;;;;N;;;;; +1B0CC;HENTAIGANA LETTER MI-4;Lo;0;L;;;;;N;;;;; +1B0CD;HENTAIGANA LETTER MI-5;Lo;0;L;;;;;N;;;;; +1B0CE;HENTAIGANA LETTER MI-6;Lo;0;L;;;;;N;;;;; +1B0CF;HENTAIGANA LETTER MI-7;Lo;0;L;;;;;N;;;;; +1B0D0;HENTAIGANA LETTER MU-1;Lo;0;L;;;;;N;;;;; +1B0D1;HENTAIGANA LETTER MU-2;Lo;0;L;;;;;N;;;;; +1B0D2;HENTAIGANA LETTER MU-3;Lo;0;L;;;;;N;;;;; +1B0D3;HENTAIGANA LETTER MU-4;Lo;0;L;;;;;N;;;;; +1B0D4;HENTAIGANA LETTER ME-1;Lo;0;L;;;;;N;;;;; +1B0D5;HENTAIGANA LETTER ME-2;Lo;0;L;;;;;N;;;;; +1B0D6;HENTAIGANA LETTER ME-MA;Lo;0;L;;;;;N;;;;; +1B0D7;HENTAIGANA LETTER MO-1;Lo;0;L;;;;;N;;;;; +1B0D8;HENTAIGANA LETTER MO-2;Lo;0;L;;;;;N;;;;; +1B0D9;HENTAIGANA LETTER MO-3;Lo;0;L;;;;;N;;;;; +1B0DA;HENTAIGANA LETTER MO-4;Lo;0;L;;;;;N;;;;; +1B0DB;HENTAIGANA LETTER MO-5;Lo;0;L;;;;;N;;;;; +1B0DC;HENTAIGANA LETTER MO-6;Lo;0;L;;;;;N;;;;; +1B0DD;HENTAIGANA LETTER YA-1;Lo;0;L;;;;;N;;;;; +1B0DE;HENTAIGANA LETTER YA-2;Lo;0;L;;;;;N;;;;; +1B0DF;HENTAIGANA LETTER YA-3;Lo;0;L;;;;;N;;;;; +1B0E0;HENTAIGANA LETTER YA-4;Lo;0;L;;;;;N;;;;; +1B0E1;HENTAIGANA LETTER YA-5;Lo;0;L;;;;;N;;;;; +1B0E2;HENTAIGANA LETTER YA-YO;Lo;0;L;;;;;N;;;;; +1B0E3;HENTAIGANA LETTER YU-1;Lo;0;L;;;;;N;;;;; +1B0E4;HENTAIGANA LETTER YU-2;Lo;0;L;;;;;N;;;;; +1B0E5;HENTAIGANA LETTER YU-3;Lo;0;L;;;;;N;;;;; +1B0E6;HENTAIGANA LETTER YU-4;Lo;0;L;;;;;N;;;;; +1B0E7;HENTAIGANA LETTER YO-1;Lo;0;L;;;;;N;;;;; +1B0E8;HENTAIGANA LETTER YO-2;Lo;0;L;;;;;N;;;;; +1B0E9;HENTAIGANA LETTER YO-3;Lo;0;L;;;;;N;;;;; +1B0EA;HENTAIGANA LETTER YO-4;Lo;0;L;;;;;N;;;;; +1B0EB;HENTAIGANA LETTER YO-5;Lo;0;L;;;;;N;;;;; +1B0EC;HENTAIGANA LETTER YO-6;Lo;0;L;;;;;N;;;;; +1B0ED;HENTAIGANA LETTER RA-1;Lo;0;L;;;;;N;;;;; +1B0EE;HENTAIGANA LETTER RA-2;Lo;0;L;;;;;N;;;;; +1B0EF;HENTAIGANA LETTER RA-3;Lo;0;L;;;;;N;;;;; +1B0F0;HENTAIGANA LETTER RA-4;Lo;0;L;;;;;N;;;;; +1B0F1;HENTAIGANA LETTER RI-1;Lo;0;L;;;;;N;;;;; +1B0F2;HENTAIGANA LETTER RI-2;Lo;0;L;;;;;N;;;;; +1B0F3;HENTAIGANA LETTER RI-3;Lo;0;L;;;;;N;;;;; +1B0F4;HENTAIGANA LETTER RI-4;Lo;0;L;;;;;N;;;;; +1B0F5;HENTAIGANA LETTER RI-5;Lo;0;L;;;;;N;;;;; +1B0F6;HENTAIGANA LETTER RI-6;Lo;0;L;;;;;N;;;;; +1B0F7;HENTAIGANA LETTER RI-7;Lo;0;L;;;;;N;;;;; +1B0F8;HENTAIGANA LETTER RU-1;Lo;0;L;;;;;N;;;;; +1B0F9;HENTAIGANA LETTER RU-2;Lo;0;L;;;;;N;;;;; +1B0FA;HENTAIGANA LETTER RU-3;Lo;0;L;;;;;N;;;;; +1B0FB;HENTAIGANA LETTER RU-4;Lo;0;L;;;;;N;;;;; +1B0FC;HENTAIGANA LETTER RU-5;Lo;0;L;;;;;N;;;;; +1B0FD;HENTAIGANA LETTER RU-6;Lo;0;L;;;;;N;;;;; +1B0FE;HENTAIGANA LETTER RE-1;Lo;0;L;;;;;N;;;;; +1B0FF;HENTAIGANA LETTER RE-2;Lo;0;L;;;;;N;;;;; +1B100;HENTAIGANA LETTER RE-3;Lo;0;L;;;;;N;;;;; +1B101;HENTAIGANA LETTER RE-4;Lo;0;L;;;;;N;;;;; +1B102;HENTAIGANA LETTER RO-1;Lo;0;L;;;;;N;;;;; +1B103;HENTAIGANA LETTER RO-2;Lo;0;L;;;;;N;;;;; +1B104;HENTAIGANA LETTER RO-3;Lo;0;L;;;;;N;;;;; +1B105;HENTAIGANA LETTER RO-4;Lo;0;L;;;;;N;;;;; +1B106;HENTAIGANA LETTER RO-5;Lo;0;L;;;;;N;;;;; +1B107;HENTAIGANA LETTER RO-6;Lo;0;L;;;;;N;;;;; +1B108;HENTAIGANA LETTER WA-1;Lo;0;L;;;;;N;;;;; +1B109;HENTAIGANA LETTER WA-2;Lo;0;L;;;;;N;;;;; +1B10A;HENTAIGANA LETTER WA-3;Lo;0;L;;;;;N;;;;; +1B10B;HENTAIGANA LETTER WA-4;Lo;0;L;;;;;N;;;;; +1B10C;HENTAIGANA LETTER WA-5;Lo;0;L;;;;;N;;;;; +1B10D;HENTAIGANA LETTER WI-1;Lo;0;L;;;;;N;;;;; +1B10E;HENTAIGANA LETTER WI-2;Lo;0;L;;;;;N;;;;; +1B10F;HENTAIGANA LETTER WI-3;Lo;0;L;;;;;N;;;;; +1B110;HENTAIGANA LETTER WI-4;Lo;0;L;;;;;N;;;;; +1B111;HENTAIGANA LETTER WI-5;Lo;0;L;;;;;N;;;;; +1B112;HENTAIGANA LETTER WE-1;Lo;0;L;;;;;N;;;;; +1B113;HENTAIGANA LETTER WE-2;Lo;0;L;;;;;N;;;;; +1B114;HENTAIGANA LETTER WE-3;Lo;0;L;;;;;N;;;;; +1B115;HENTAIGANA LETTER WE-4;Lo;0;L;;;;;N;;;;; +1B116;HENTAIGANA LETTER WO-1;Lo;0;L;;;;;N;;;;; +1B117;HENTAIGANA LETTER WO-2;Lo;0;L;;;;;N;;;;; +1B118;HENTAIGANA LETTER WO-3;Lo;0;L;;;;;N;;;;; +1B119;HENTAIGANA LETTER WO-4;Lo;0;L;;;;;N;;;;; +1B11A;HENTAIGANA LETTER WO-5;Lo;0;L;;;;;N;;;;; +1B11B;HENTAIGANA LETTER WO-6;Lo;0;L;;;;;N;;;;; +1B11C;HENTAIGANA LETTER WO-7;Lo;0;L;;;;;N;;;;; +1B11D;HENTAIGANA LETTER N-MU-MO-1;Lo;0;L;;;;;N;;;;; +1B11E;HENTAIGANA LETTER N-MU-MO-2;Lo;0;L;;;;;N;;;;; +1B170;NUSHU CHARACTER-1B170;Lo;0;L;;;;;N;;;;; +1B171;NUSHU CHARACTER-1B171;Lo;0;L;;;;;N;;;;; +1B172;NUSHU CHARACTER-1B172;Lo;0;L;;;;;N;;;;; +1B173;NUSHU CHARACTER-1B173;Lo;0;L;;;;;N;;;;; +1B174;NUSHU CHARACTER-1B174;Lo;0;L;;;;;N;;;;; +1B175;NUSHU CHARACTER-1B175;Lo;0;L;;;;;N;;;;; +1B176;NUSHU CHARACTER-1B176;Lo;0;L;;;;;N;;;;; +1B177;NUSHU CHARACTER-1B177;Lo;0;L;;;;;N;;;;; +1B178;NUSHU CHARACTER-1B178;Lo;0;L;;;;;N;;;;; +1B179;NUSHU CHARACTER-1B179;Lo;0;L;;;;;N;;;;; +1B17A;NUSHU CHARACTER-1B17A;Lo;0;L;;;;;N;;;;; +1B17B;NUSHU CHARACTER-1B17B;Lo;0;L;;;;;N;;;;; +1B17C;NUSHU CHARACTER-1B17C;Lo;0;L;;;;;N;;;;; +1B17D;NUSHU CHARACTER-1B17D;Lo;0;L;;;;;N;;;;; +1B17E;NUSHU CHARACTER-1B17E;Lo;0;L;;;;;N;;;;; +1B17F;NUSHU CHARACTER-1B17F;Lo;0;L;;;;;N;;;;; +1B180;NUSHU CHARACTER-1B180;Lo;0;L;;;;;N;;;;; +1B181;NUSHU CHARACTER-1B181;Lo;0;L;;;;;N;;;;; +1B182;NUSHU CHARACTER-1B182;Lo;0;L;;;;;N;;;;; +1B183;NUSHU CHARACTER-1B183;Lo;0;L;;;;;N;;;;; +1B184;NUSHU CHARACTER-1B184;Lo;0;L;;;;;N;;;;; +1B185;NUSHU CHARACTER-1B185;Lo;0;L;;;;;N;;;;; +1B186;NUSHU CHARACTER-1B186;Lo;0;L;;;;;N;;;;; +1B187;NUSHU CHARACTER-1B187;Lo;0;L;;;;;N;;;;; +1B188;NUSHU CHARACTER-1B188;Lo;0;L;;;;;N;;;;; +1B189;NUSHU CHARACTER-1B189;Lo;0;L;;;;;N;;;;; +1B18A;NUSHU CHARACTER-1B18A;Lo;0;L;;;;;N;;;;; +1B18B;NUSHU CHARACTER-1B18B;Lo;0;L;;;;;N;;;;; +1B18C;NUSHU CHARACTER-1B18C;Lo;0;L;;;;;N;;;;; +1B18D;NUSHU CHARACTER-1B18D;Lo;0;L;;;;;N;;;;; +1B18E;NUSHU CHARACTER-1B18E;Lo;0;L;;;;;N;;;;; +1B18F;NUSHU CHARACTER-1B18F;Lo;0;L;;;;;N;;;;; +1B190;NUSHU CHARACTER-1B190;Lo;0;L;;;;;N;;;;; +1B191;NUSHU CHARACTER-1B191;Lo;0;L;;;;;N;;;;; +1B192;NUSHU CHARACTER-1B192;Lo;0;L;;;;;N;;;;; +1B193;NUSHU CHARACTER-1B193;Lo;0;L;;;;;N;;;;; +1B194;NUSHU CHARACTER-1B194;Lo;0;L;;;;;N;;;;; +1B195;NUSHU CHARACTER-1B195;Lo;0;L;;;;;N;;;;; +1B196;NUSHU CHARACTER-1B196;Lo;0;L;;;;;N;;;;; +1B197;NUSHU CHARACTER-1B197;Lo;0;L;;;;;N;;;;; +1B198;NUSHU CHARACTER-1B198;Lo;0;L;;;;;N;;;;; +1B199;NUSHU CHARACTER-1B199;Lo;0;L;;;;;N;;;;; +1B19A;NUSHU CHARACTER-1B19A;Lo;0;L;;;;;N;;;;; +1B19B;NUSHU CHARACTER-1B19B;Lo;0;L;;;;;N;;;;; +1B19C;NUSHU CHARACTER-1B19C;Lo;0;L;;;;;N;;;;; +1B19D;NUSHU CHARACTER-1B19D;Lo;0;L;;;;;N;;;;; +1B19E;NUSHU CHARACTER-1B19E;Lo;0;L;;;;;N;;;;; +1B19F;NUSHU CHARACTER-1B19F;Lo;0;L;;;;;N;;;;; +1B1A0;NUSHU CHARACTER-1B1A0;Lo;0;L;;;;;N;;;;; +1B1A1;NUSHU CHARACTER-1B1A1;Lo;0;L;;;;;N;;;;; +1B1A2;NUSHU CHARACTER-1B1A2;Lo;0;L;;;;;N;;;;; +1B1A3;NUSHU CHARACTER-1B1A3;Lo;0;L;;;;;N;;;;; +1B1A4;NUSHU CHARACTER-1B1A4;Lo;0;L;;;;;N;;;;; +1B1A5;NUSHU CHARACTER-1B1A5;Lo;0;L;;;;;N;;;;; +1B1A6;NUSHU CHARACTER-1B1A6;Lo;0;L;;;;;N;;;;; +1B1A7;NUSHU CHARACTER-1B1A7;Lo;0;L;;;;;N;;;;; +1B1A8;NUSHU CHARACTER-1B1A8;Lo;0;L;;;;;N;;;;; +1B1A9;NUSHU CHARACTER-1B1A9;Lo;0;L;;;;;N;;;;; +1B1AA;NUSHU CHARACTER-1B1AA;Lo;0;L;;;;;N;;;;; +1B1AB;NUSHU CHARACTER-1B1AB;Lo;0;L;;;;;N;;;;; +1B1AC;NUSHU CHARACTER-1B1AC;Lo;0;L;;;;;N;;;;; +1B1AD;NUSHU CHARACTER-1B1AD;Lo;0;L;;;;;N;;;;; +1B1AE;NUSHU CHARACTER-1B1AE;Lo;0;L;;;;;N;;;;; +1B1AF;NUSHU CHARACTER-1B1AF;Lo;0;L;;;;;N;;;;; +1B1B0;NUSHU CHARACTER-1B1B0;Lo;0;L;;;;;N;;;;; +1B1B1;NUSHU CHARACTER-1B1B1;Lo;0;L;;;;;N;;;;; +1B1B2;NUSHU CHARACTER-1B1B2;Lo;0;L;;;;;N;;;;; +1B1B3;NUSHU CHARACTER-1B1B3;Lo;0;L;;;;;N;;;;; +1B1B4;NUSHU CHARACTER-1B1B4;Lo;0;L;;;;;N;;;;; +1B1B5;NUSHU CHARACTER-1B1B5;Lo;0;L;;;;;N;;;;; +1B1B6;NUSHU CHARACTER-1B1B6;Lo;0;L;;;;;N;;;;; +1B1B7;NUSHU CHARACTER-1B1B7;Lo;0;L;;;;;N;;;;; +1B1B8;NUSHU CHARACTER-1B1B8;Lo;0;L;;;;;N;;;;; +1B1B9;NUSHU CHARACTER-1B1B9;Lo;0;L;;;;;N;;;;; +1B1BA;NUSHU CHARACTER-1B1BA;Lo;0;L;;;;;N;;;;; +1B1BB;NUSHU CHARACTER-1B1BB;Lo;0;L;;;;;N;;;;; +1B1BC;NUSHU CHARACTER-1B1BC;Lo;0;L;;;;;N;;;;; +1B1BD;NUSHU CHARACTER-1B1BD;Lo;0;L;;;;;N;;;;; +1B1BE;NUSHU CHARACTER-1B1BE;Lo;0;L;;;;;N;;;;; +1B1BF;NUSHU CHARACTER-1B1BF;Lo;0;L;;;;;N;;;;; +1B1C0;NUSHU CHARACTER-1B1C0;Lo;0;L;;;;;N;;;;; +1B1C1;NUSHU CHARACTER-1B1C1;Lo;0;L;;;;;N;;;;; +1B1C2;NUSHU CHARACTER-1B1C2;Lo;0;L;;;;;N;;;;; +1B1C3;NUSHU CHARACTER-1B1C3;Lo;0;L;;;;;N;;;;; +1B1C4;NUSHU CHARACTER-1B1C4;Lo;0;L;;;;;N;;;;; +1B1C5;NUSHU CHARACTER-1B1C5;Lo;0;L;;;;;N;;;;; +1B1C6;NUSHU CHARACTER-1B1C6;Lo;0;L;;;;;N;;;;; +1B1C7;NUSHU CHARACTER-1B1C7;Lo;0;L;;;;;N;;;;; +1B1C8;NUSHU CHARACTER-1B1C8;Lo;0;L;;;;;N;;;;; +1B1C9;NUSHU CHARACTER-1B1C9;Lo;0;L;;;;;N;;;;; +1B1CA;NUSHU CHARACTER-1B1CA;Lo;0;L;;;;;N;;;;; +1B1CB;NUSHU CHARACTER-1B1CB;Lo;0;L;;;;;N;;;;; +1B1CC;NUSHU CHARACTER-1B1CC;Lo;0;L;;;;;N;;;;; +1B1CD;NUSHU CHARACTER-1B1CD;Lo;0;L;;;;;N;;;;; +1B1CE;NUSHU CHARACTER-1B1CE;Lo;0;L;;;;;N;;;;; +1B1CF;NUSHU CHARACTER-1B1CF;Lo;0;L;;;;;N;;;;; +1B1D0;NUSHU CHARACTER-1B1D0;Lo;0;L;;;;;N;;;;; +1B1D1;NUSHU CHARACTER-1B1D1;Lo;0;L;;;;;N;;;;; +1B1D2;NUSHU CHARACTER-1B1D2;Lo;0;L;;;;;N;;;;; +1B1D3;NUSHU CHARACTER-1B1D3;Lo;0;L;;;;;N;;;;; +1B1D4;NUSHU CHARACTER-1B1D4;Lo;0;L;;;;;N;;;;; +1B1D5;NUSHU CHARACTER-1B1D5;Lo;0;L;;;;;N;;;;; +1B1D6;NUSHU CHARACTER-1B1D6;Lo;0;L;;;;;N;;;;; +1B1D7;NUSHU CHARACTER-1B1D7;Lo;0;L;;;;;N;;;;; +1B1D8;NUSHU CHARACTER-1B1D8;Lo;0;L;;;;;N;;;;; +1B1D9;NUSHU CHARACTER-1B1D9;Lo;0;L;;;;;N;;;;; +1B1DA;NUSHU CHARACTER-1B1DA;Lo;0;L;;;;;N;;;;; +1B1DB;NUSHU CHARACTER-1B1DB;Lo;0;L;;;;;N;;;;; +1B1DC;NUSHU CHARACTER-1B1DC;Lo;0;L;;;;;N;;;;; +1B1DD;NUSHU CHARACTER-1B1DD;Lo;0;L;;;;;N;;;;; +1B1DE;NUSHU CHARACTER-1B1DE;Lo;0;L;;;;;N;;;;; +1B1DF;NUSHU CHARACTER-1B1DF;Lo;0;L;;;;;N;;;;; +1B1E0;NUSHU CHARACTER-1B1E0;Lo;0;L;;;;;N;;;;; +1B1E1;NUSHU CHARACTER-1B1E1;Lo;0;L;;;;;N;;;;; +1B1E2;NUSHU CHARACTER-1B1E2;Lo;0;L;;;;;N;;;;; +1B1E3;NUSHU CHARACTER-1B1E3;Lo;0;L;;;;;N;;;;; +1B1E4;NUSHU CHARACTER-1B1E4;Lo;0;L;;;;;N;;;;; +1B1E5;NUSHU CHARACTER-1B1E5;Lo;0;L;;;;;N;;;;; +1B1E6;NUSHU CHARACTER-1B1E6;Lo;0;L;;;;;N;;;;; +1B1E7;NUSHU CHARACTER-1B1E7;Lo;0;L;;;;;N;;;;; +1B1E8;NUSHU CHARACTER-1B1E8;Lo;0;L;;;;;N;;;;; +1B1E9;NUSHU CHARACTER-1B1E9;Lo;0;L;;;;;N;;;;; +1B1EA;NUSHU CHARACTER-1B1EA;Lo;0;L;;;;;N;;;;; +1B1EB;NUSHU CHARACTER-1B1EB;Lo;0;L;;;;;N;;;;; +1B1EC;NUSHU CHARACTER-1B1EC;Lo;0;L;;;;;N;;;;; +1B1ED;NUSHU CHARACTER-1B1ED;Lo;0;L;;;;;N;;;;; +1B1EE;NUSHU CHARACTER-1B1EE;Lo;0;L;;;;;N;;;;; +1B1EF;NUSHU CHARACTER-1B1EF;Lo;0;L;;;;;N;;;;; +1B1F0;NUSHU CHARACTER-1B1F0;Lo;0;L;;;;;N;;;;; +1B1F1;NUSHU CHARACTER-1B1F1;Lo;0;L;;;;;N;;;;; +1B1F2;NUSHU CHARACTER-1B1F2;Lo;0;L;;;;;N;;;;; +1B1F3;NUSHU CHARACTER-1B1F3;Lo;0;L;;;;;N;;;;; +1B1F4;NUSHU CHARACTER-1B1F4;Lo;0;L;;;;;N;;;;; +1B1F5;NUSHU CHARACTER-1B1F5;Lo;0;L;;;;;N;;;;; +1B1F6;NUSHU CHARACTER-1B1F6;Lo;0;L;;;;;N;;;;; +1B1F7;NUSHU CHARACTER-1B1F7;Lo;0;L;;;;;N;;;;; +1B1F8;NUSHU CHARACTER-1B1F8;Lo;0;L;;;;;N;;;;; +1B1F9;NUSHU CHARACTER-1B1F9;Lo;0;L;;;;;N;;;;; +1B1FA;NUSHU CHARACTER-1B1FA;Lo;0;L;;;;;N;;;;; +1B1FB;NUSHU CHARACTER-1B1FB;Lo;0;L;;;;;N;;;;; +1B1FC;NUSHU CHARACTER-1B1FC;Lo;0;L;;;;;N;;;;; +1B1FD;NUSHU CHARACTER-1B1FD;Lo;0;L;;;;;N;;;;; +1B1FE;NUSHU CHARACTER-1B1FE;Lo;0;L;;;;;N;;;;; +1B1FF;NUSHU CHARACTER-1B1FF;Lo;0;L;;;;;N;;;;; +1B200;NUSHU CHARACTER-1B200;Lo;0;L;;;;;N;;;;; +1B201;NUSHU CHARACTER-1B201;Lo;0;L;;;;;N;;;;; +1B202;NUSHU CHARACTER-1B202;Lo;0;L;;;;;N;;;;; +1B203;NUSHU CHARACTER-1B203;Lo;0;L;;;;;N;;;;; +1B204;NUSHU CHARACTER-1B204;Lo;0;L;;;;;N;;;;; +1B205;NUSHU CHARACTER-1B205;Lo;0;L;;;;;N;;;;; +1B206;NUSHU CHARACTER-1B206;Lo;0;L;;;;;N;;;;; +1B207;NUSHU CHARACTER-1B207;Lo;0;L;;;;;N;;;;; +1B208;NUSHU CHARACTER-1B208;Lo;0;L;;;;;N;;;;; +1B209;NUSHU CHARACTER-1B209;Lo;0;L;;;;;N;;;;; +1B20A;NUSHU CHARACTER-1B20A;Lo;0;L;;;;;N;;;;; +1B20B;NUSHU CHARACTER-1B20B;Lo;0;L;;;;;N;;;;; +1B20C;NUSHU CHARACTER-1B20C;Lo;0;L;;;;;N;;;;; +1B20D;NUSHU CHARACTER-1B20D;Lo;0;L;;;;;N;;;;; +1B20E;NUSHU CHARACTER-1B20E;Lo;0;L;;;;;N;;;;; +1B20F;NUSHU CHARACTER-1B20F;Lo;0;L;;;;;N;;;;; +1B210;NUSHU CHARACTER-1B210;Lo;0;L;;;;;N;;;;; +1B211;NUSHU CHARACTER-1B211;Lo;0;L;;;;;N;;;;; +1B212;NUSHU CHARACTER-1B212;Lo;0;L;;;;;N;;;;; +1B213;NUSHU CHARACTER-1B213;Lo;0;L;;;;;N;;;;; +1B214;NUSHU CHARACTER-1B214;Lo;0;L;;;;;N;;;;; +1B215;NUSHU CHARACTER-1B215;Lo;0;L;;;;;N;;;;; +1B216;NUSHU CHARACTER-1B216;Lo;0;L;;;;;N;;;;; +1B217;NUSHU CHARACTER-1B217;Lo;0;L;;;;;N;;;;; +1B218;NUSHU CHARACTER-1B218;Lo;0;L;;;;;N;;;;; +1B219;NUSHU CHARACTER-1B219;Lo;0;L;;;;;N;;;;; +1B21A;NUSHU CHARACTER-1B21A;Lo;0;L;;;;;N;;;;; +1B21B;NUSHU CHARACTER-1B21B;Lo;0;L;;;;;N;;;;; +1B21C;NUSHU CHARACTER-1B21C;Lo;0;L;;;;;N;;;;; +1B21D;NUSHU CHARACTER-1B21D;Lo;0;L;;;;;N;;;;; +1B21E;NUSHU CHARACTER-1B21E;Lo;0;L;;;;;N;;;;; +1B21F;NUSHU CHARACTER-1B21F;Lo;0;L;;;;;N;;;;; +1B220;NUSHU CHARACTER-1B220;Lo;0;L;;;;;N;;;;; +1B221;NUSHU CHARACTER-1B221;Lo;0;L;;;;;N;;;;; +1B222;NUSHU CHARACTER-1B222;Lo;0;L;;;;;N;;;;; +1B223;NUSHU CHARACTER-1B223;Lo;0;L;;;;;N;;;;; +1B224;NUSHU CHARACTER-1B224;Lo;0;L;;;;;N;;;;; +1B225;NUSHU CHARACTER-1B225;Lo;0;L;;;;;N;;;;; +1B226;NUSHU CHARACTER-1B226;Lo;0;L;;;;;N;;;;; +1B227;NUSHU CHARACTER-1B227;Lo;0;L;;;;;N;;;;; +1B228;NUSHU CHARACTER-1B228;Lo;0;L;;;;;N;;;;; +1B229;NUSHU CHARACTER-1B229;Lo;0;L;;;;;N;;;;; +1B22A;NUSHU CHARACTER-1B22A;Lo;0;L;;;;;N;;;;; +1B22B;NUSHU CHARACTER-1B22B;Lo;0;L;;;;;N;;;;; +1B22C;NUSHU CHARACTER-1B22C;Lo;0;L;;;;;N;;;;; +1B22D;NUSHU CHARACTER-1B22D;Lo;0;L;;;;;N;;;;; +1B22E;NUSHU CHARACTER-1B22E;Lo;0;L;;;;;N;;;;; +1B22F;NUSHU CHARACTER-1B22F;Lo;0;L;;;;;N;;;;; +1B230;NUSHU CHARACTER-1B230;Lo;0;L;;;;;N;;;;; +1B231;NUSHU CHARACTER-1B231;Lo;0;L;;;;;N;;;;; +1B232;NUSHU CHARACTER-1B232;Lo;0;L;;;;;N;;;;; +1B233;NUSHU CHARACTER-1B233;Lo;0;L;;;;;N;;;;; +1B234;NUSHU CHARACTER-1B234;Lo;0;L;;;;;N;;;;; +1B235;NUSHU CHARACTER-1B235;Lo;0;L;;;;;N;;;;; +1B236;NUSHU CHARACTER-1B236;Lo;0;L;;;;;N;;;;; +1B237;NUSHU CHARACTER-1B237;Lo;0;L;;;;;N;;;;; +1B238;NUSHU CHARACTER-1B238;Lo;0;L;;;;;N;;;;; +1B239;NUSHU CHARACTER-1B239;Lo;0;L;;;;;N;;;;; +1B23A;NUSHU CHARACTER-1B23A;Lo;0;L;;;;;N;;;;; +1B23B;NUSHU CHARACTER-1B23B;Lo;0;L;;;;;N;;;;; +1B23C;NUSHU CHARACTER-1B23C;Lo;0;L;;;;;N;;;;; +1B23D;NUSHU CHARACTER-1B23D;Lo;0;L;;;;;N;;;;; +1B23E;NUSHU CHARACTER-1B23E;Lo;0;L;;;;;N;;;;; +1B23F;NUSHU CHARACTER-1B23F;Lo;0;L;;;;;N;;;;; +1B240;NUSHU CHARACTER-1B240;Lo;0;L;;;;;N;;;;; +1B241;NUSHU CHARACTER-1B241;Lo;0;L;;;;;N;;;;; +1B242;NUSHU CHARACTER-1B242;Lo;0;L;;;;;N;;;;; +1B243;NUSHU CHARACTER-1B243;Lo;0;L;;;;;N;;;;; +1B244;NUSHU CHARACTER-1B244;Lo;0;L;;;;;N;;;;; +1B245;NUSHU CHARACTER-1B245;Lo;0;L;;;;;N;;;;; +1B246;NUSHU CHARACTER-1B246;Lo;0;L;;;;;N;;;;; +1B247;NUSHU CHARACTER-1B247;Lo;0;L;;;;;N;;;;; +1B248;NUSHU CHARACTER-1B248;Lo;0;L;;;;;N;;;;; +1B249;NUSHU CHARACTER-1B249;Lo;0;L;;;;;N;;;;; +1B24A;NUSHU CHARACTER-1B24A;Lo;0;L;;;;;N;;;;; +1B24B;NUSHU CHARACTER-1B24B;Lo;0;L;;;;;N;;;;; +1B24C;NUSHU CHARACTER-1B24C;Lo;0;L;;;;;N;;;;; +1B24D;NUSHU CHARACTER-1B24D;Lo;0;L;;;;;N;;;;; +1B24E;NUSHU CHARACTER-1B24E;Lo;0;L;;;;;N;;;;; +1B24F;NUSHU CHARACTER-1B24F;Lo;0;L;;;;;N;;;;; +1B250;NUSHU CHARACTER-1B250;Lo;0;L;;;;;N;;;;; +1B251;NUSHU CHARACTER-1B251;Lo;0;L;;;;;N;;;;; +1B252;NUSHU CHARACTER-1B252;Lo;0;L;;;;;N;;;;; +1B253;NUSHU CHARACTER-1B253;Lo;0;L;;;;;N;;;;; +1B254;NUSHU CHARACTER-1B254;Lo;0;L;;;;;N;;;;; +1B255;NUSHU CHARACTER-1B255;Lo;0;L;;;;;N;;;;; +1B256;NUSHU CHARACTER-1B256;Lo;0;L;;;;;N;;;;; +1B257;NUSHU CHARACTER-1B257;Lo;0;L;;;;;N;;;;; +1B258;NUSHU CHARACTER-1B258;Lo;0;L;;;;;N;;;;; +1B259;NUSHU CHARACTER-1B259;Lo;0;L;;;;;N;;;;; +1B25A;NUSHU CHARACTER-1B25A;Lo;0;L;;;;;N;;;;; +1B25B;NUSHU CHARACTER-1B25B;Lo;0;L;;;;;N;;;;; +1B25C;NUSHU CHARACTER-1B25C;Lo;0;L;;;;;N;;;;; +1B25D;NUSHU CHARACTER-1B25D;Lo;0;L;;;;;N;;;;; +1B25E;NUSHU CHARACTER-1B25E;Lo;0;L;;;;;N;;;;; +1B25F;NUSHU CHARACTER-1B25F;Lo;0;L;;;;;N;;;;; +1B260;NUSHU CHARACTER-1B260;Lo;0;L;;;;;N;;;;; +1B261;NUSHU CHARACTER-1B261;Lo;0;L;;;;;N;;;;; +1B262;NUSHU CHARACTER-1B262;Lo;0;L;;;;;N;;;;; +1B263;NUSHU CHARACTER-1B263;Lo;0;L;;;;;N;;;;; +1B264;NUSHU CHARACTER-1B264;Lo;0;L;;;;;N;;;;; +1B265;NUSHU CHARACTER-1B265;Lo;0;L;;;;;N;;;;; +1B266;NUSHU CHARACTER-1B266;Lo;0;L;;;;;N;;;;; +1B267;NUSHU CHARACTER-1B267;Lo;0;L;;;;;N;;;;; +1B268;NUSHU CHARACTER-1B268;Lo;0;L;;;;;N;;;;; +1B269;NUSHU CHARACTER-1B269;Lo;0;L;;;;;N;;;;; +1B26A;NUSHU CHARACTER-1B26A;Lo;0;L;;;;;N;;;;; +1B26B;NUSHU CHARACTER-1B26B;Lo;0;L;;;;;N;;;;; +1B26C;NUSHU CHARACTER-1B26C;Lo;0;L;;;;;N;;;;; +1B26D;NUSHU CHARACTER-1B26D;Lo;0;L;;;;;N;;;;; +1B26E;NUSHU CHARACTER-1B26E;Lo;0;L;;;;;N;;;;; +1B26F;NUSHU CHARACTER-1B26F;Lo;0;L;;;;;N;;;;; +1B270;NUSHU CHARACTER-1B270;Lo;0;L;;;;;N;;;;; +1B271;NUSHU CHARACTER-1B271;Lo;0;L;;;;;N;;;;; +1B272;NUSHU CHARACTER-1B272;Lo;0;L;;;;;N;;;;; +1B273;NUSHU CHARACTER-1B273;Lo;0;L;;;;;N;;;;; +1B274;NUSHU CHARACTER-1B274;Lo;0;L;;;;;N;;;;; +1B275;NUSHU CHARACTER-1B275;Lo;0;L;;;;;N;;;;; +1B276;NUSHU CHARACTER-1B276;Lo;0;L;;;;;N;;;;; +1B277;NUSHU CHARACTER-1B277;Lo;0;L;;;;;N;;;;; +1B278;NUSHU CHARACTER-1B278;Lo;0;L;;;;;N;;;;; +1B279;NUSHU CHARACTER-1B279;Lo;0;L;;;;;N;;;;; +1B27A;NUSHU CHARACTER-1B27A;Lo;0;L;;;;;N;;;;; +1B27B;NUSHU CHARACTER-1B27B;Lo;0;L;;;;;N;;;;; +1B27C;NUSHU CHARACTER-1B27C;Lo;0;L;;;;;N;;;;; +1B27D;NUSHU CHARACTER-1B27D;Lo;0;L;;;;;N;;;;; +1B27E;NUSHU CHARACTER-1B27E;Lo;0;L;;;;;N;;;;; +1B27F;NUSHU CHARACTER-1B27F;Lo;0;L;;;;;N;;;;; +1B280;NUSHU CHARACTER-1B280;Lo;0;L;;;;;N;;;;; +1B281;NUSHU CHARACTER-1B281;Lo;0;L;;;;;N;;;;; +1B282;NUSHU CHARACTER-1B282;Lo;0;L;;;;;N;;;;; +1B283;NUSHU CHARACTER-1B283;Lo;0;L;;;;;N;;;;; +1B284;NUSHU CHARACTER-1B284;Lo;0;L;;;;;N;;;;; +1B285;NUSHU CHARACTER-1B285;Lo;0;L;;;;;N;;;;; +1B286;NUSHU CHARACTER-1B286;Lo;0;L;;;;;N;;;;; +1B287;NUSHU CHARACTER-1B287;Lo;0;L;;;;;N;;;;; +1B288;NUSHU CHARACTER-1B288;Lo;0;L;;;;;N;;;;; +1B289;NUSHU CHARACTER-1B289;Lo;0;L;;;;;N;;;;; +1B28A;NUSHU CHARACTER-1B28A;Lo;0;L;;;;;N;;;;; +1B28B;NUSHU CHARACTER-1B28B;Lo;0;L;;;;;N;;;;; +1B28C;NUSHU CHARACTER-1B28C;Lo;0;L;;;;;N;;;;; +1B28D;NUSHU CHARACTER-1B28D;Lo;0;L;;;;;N;;;;; +1B28E;NUSHU CHARACTER-1B28E;Lo;0;L;;;;;N;;;;; +1B28F;NUSHU CHARACTER-1B28F;Lo;0;L;;;;;N;;;;; +1B290;NUSHU CHARACTER-1B290;Lo;0;L;;;;;N;;;;; +1B291;NUSHU CHARACTER-1B291;Lo;0;L;;;;;N;;;;; +1B292;NUSHU CHARACTER-1B292;Lo;0;L;;;;;N;;;;; +1B293;NUSHU CHARACTER-1B293;Lo;0;L;;;;;N;;;;; +1B294;NUSHU CHARACTER-1B294;Lo;0;L;;;;;N;;;;; +1B295;NUSHU CHARACTER-1B295;Lo;0;L;;;;;N;;;;; +1B296;NUSHU CHARACTER-1B296;Lo;0;L;;;;;N;;;;; +1B297;NUSHU CHARACTER-1B297;Lo;0;L;;;;;N;;;;; +1B298;NUSHU CHARACTER-1B298;Lo;0;L;;;;;N;;;;; +1B299;NUSHU CHARACTER-1B299;Lo;0;L;;;;;N;;;;; +1B29A;NUSHU CHARACTER-1B29A;Lo;0;L;;;;;N;;;;; +1B29B;NUSHU CHARACTER-1B29B;Lo;0;L;;;;;N;;;;; +1B29C;NUSHU CHARACTER-1B29C;Lo;0;L;;;;;N;;;;; +1B29D;NUSHU CHARACTER-1B29D;Lo;0;L;;;;;N;;;;; +1B29E;NUSHU CHARACTER-1B29E;Lo;0;L;;;;;N;;;;; +1B29F;NUSHU CHARACTER-1B29F;Lo;0;L;;;;;N;;;;; +1B2A0;NUSHU CHARACTER-1B2A0;Lo;0;L;;;;;N;;;;; +1B2A1;NUSHU CHARACTER-1B2A1;Lo;0;L;;;;;N;;;;; +1B2A2;NUSHU CHARACTER-1B2A2;Lo;0;L;;;;;N;;;;; +1B2A3;NUSHU CHARACTER-1B2A3;Lo;0;L;;;;;N;;;;; +1B2A4;NUSHU CHARACTER-1B2A4;Lo;0;L;;;;;N;;;;; +1B2A5;NUSHU CHARACTER-1B2A5;Lo;0;L;;;;;N;;;;; +1B2A6;NUSHU CHARACTER-1B2A6;Lo;0;L;;;;;N;;;;; +1B2A7;NUSHU CHARACTER-1B2A7;Lo;0;L;;;;;N;;;;; +1B2A8;NUSHU CHARACTER-1B2A8;Lo;0;L;;;;;N;;;;; +1B2A9;NUSHU CHARACTER-1B2A9;Lo;0;L;;;;;N;;;;; +1B2AA;NUSHU CHARACTER-1B2AA;Lo;0;L;;;;;N;;;;; +1B2AB;NUSHU CHARACTER-1B2AB;Lo;0;L;;;;;N;;;;; +1B2AC;NUSHU CHARACTER-1B2AC;Lo;0;L;;;;;N;;;;; +1B2AD;NUSHU CHARACTER-1B2AD;Lo;0;L;;;;;N;;;;; +1B2AE;NUSHU CHARACTER-1B2AE;Lo;0;L;;;;;N;;;;; +1B2AF;NUSHU CHARACTER-1B2AF;Lo;0;L;;;;;N;;;;; +1B2B0;NUSHU CHARACTER-1B2B0;Lo;0;L;;;;;N;;;;; +1B2B1;NUSHU CHARACTER-1B2B1;Lo;0;L;;;;;N;;;;; +1B2B2;NUSHU CHARACTER-1B2B2;Lo;0;L;;;;;N;;;;; +1B2B3;NUSHU CHARACTER-1B2B3;Lo;0;L;;;;;N;;;;; +1B2B4;NUSHU CHARACTER-1B2B4;Lo;0;L;;;;;N;;;;; +1B2B5;NUSHU CHARACTER-1B2B5;Lo;0;L;;;;;N;;;;; +1B2B6;NUSHU CHARACTER-1B2B6;Lo;0;L;;;;;N;;;;; +1B2B7;NUSHU CHARACTER-1B2B7;Lo;0;L;;;;;N;;;;; +1B2B8;NUSHU CHARACTER-1B2B8;Lo;0;L;;;;;N;;;;; +1B2B9;NUSHU CHARACTER-1B2B9;Lo;0;L;;;;;N;;;;; +1B2BA;NUSHU CHARACTER-1B2BA;Lo;0;L;;;;;N;;;;; +1B2BB;NUSHU CHARACTER-1B2BB;Lo;0;L;;;;;N;;;;; +1B2BC;NUSHU CHARACTER-1B2BC;Lo;0;L;;;;;N;;;;; +1B2BD;NUSHU CHARACTER-1B2BD;Lo;0;L;;;;;N;;;;; +1B2BE;NUSHU CHARACTER-1B2BE;Lo;0;L;;;;;N;;;;; +1B2BF;NUSHU CHARACTER-1B2BF;Lo;0;L;;;;;N;;;;; +1B2C0;NUSHU CHARACTER-1B2C0;Lo;0;L;;;;;N;;;;; +1B2C1;NUSHU CHARACTER-1B2C1;Lo;0;L;;;;;N;;;;; +1B2C2;NUSHU CHARACTER-1B2C2;Lo;0;L;;;;;N;;;;; +1B2C3;NUSHU CHARACTER-1B2C3;Lo;0;L;;;;;N;;;;; +1B2C4;NUSHU CHARACTER-1B2C4;Lo;0;L;;;;;N;;;;; +1B2C5;NUSHU CHARACTER-1B2C5;Lo;0;L;;;;;N;;;;; +1B2C6;NUSHU CHARACTER-1B2C6;Lo;0;L;;;;;N;;;;; +1B2C7;NUSHU CHARACTER-1B2C7;Lo;0;L;;;;;N;;;;; +1B2C8;NUSHU CHARACTER-1B2C8;Lo;0;L;;;;;N;;;;; +1B2C9;NUSHU CHARACTER-1B2C9;Lo;0;L;;;;;N;;;;; +1B2CA;NUSHU CHARACTER-1B2CA;Lo;0;L;;;;;N;;;;; +1B2CB;NUSHU CHARACTER-1B2CB;Lo;0;L;;;;;N;;;;; +1B2CC;NUSHU CHARACTER-1B2CC;Lo;0;L;;;;;N;;;;; +1B2CD;NUSHU CHARACTER-1B2CD;Lo;0;L;;;;;N;;;;; +1B2CE;NUSHU CHARACTER-1B2CE;Lo;0;L;;;;;N;;;;; +1B2CF;NUSHU CHARACTER-1B2CF;Lo;0;L;;;;;N;;;;; +1B2D0;NUSHU CHARACTER-1B2D0;Lo;0;L;;;;;N;;;;; +1B2D1;NUSHU CHARACTER-1B2D1;Lo;0;L;;;;;N;;;;; +1B2D2;NUSHU CHARACTER-1B2D2;Lo;0;L;;;;;N;;;;; +1B2D3;NUSHU CHARACTER-1B2D3;Lo;0;L;;;;;N;;;;; +1B2D4;NUSHU CHARACTER-1B2D4;Lo;0;L;;;;;N;;;;; +1B2D5;NUSHU CHARACTER-1B2D5;Lo;0;L;;;;;N;;;;; +1B2D6;NUSHU CHARACTER-1B2D6;Lo;0;L;;;;;N;;;;; +1B2D7;NUSHU CHARACTER-1B2D7;Lo;0;L;;;;;N;;;;; +1B2D8;NUSHU CHARACTER-1B2D8;Lo;0;L;;;;;N;;;;; +1B2D9;NUSHU CHARACTER-1B2D9;Lo;0;L;;;;;N;;;;; +1B2DA;NUSHU CHARACTER-1B2DA;Lo;0;L;;;;;N;;;;; +1B2DB;NUSHU CHARACTER-1B2DB;Lo;0;L;;;;;N;;;;; +1B2DC;NUSHU CHARACTER-1B2DC;Lo;0;L;;;;;N;;;;; +1B2DD;NUSHU CHARACTER-1B2DD;Lo;0;L;;;;;N;;;;; +1B2DE;NUSHU CHARACTER-1B2DE;Lo;0;L;;;;;N;;;;; +1B2DF;NUSHU CHARACTER-1B2DF;Lo;0;L;;;;;N;;;;; +1B2E0;NUSHU CHARACTER-1B2E0;Lo;0;L;;;;;N;;;;; +1B2E1;NUSHU CHARACTER-1B2E1;Lo;0;L;;;;;N;;;;; +1B2E2;NUSHU CHARACTER-1B2E2;Lo;0;L;;;;;N;;;;; +1B2E3;NUSHU CHARACTER-1B2E3;Lo;0;L;;;;;N;;;;; +1B2E4;NUSHU CHARACTER-1B2E4;Lo;0;L;;;;;N;;;;; +1B2E5;NUSHU CHARACTER-1B2E5;Lo;0;L;;;;;N;;;;; +1B2E6;NUSHU CHARACTER-1B2E6;Lo;0;L;;;;;N;;;;; +1B2E7;NUSHU CHARACTER-1B2E7;Lo;0;L;;;;;N;;;;; +1B2E8;NUSHU CHARACTER-1B2E8;Lo;0;L;;;;;N;;;;; +1B2E9;NUSHU CHARACTER-1B2E9;Lo;0;L;;;;;N;;;;; +1B2EA;NUSHU CHARACTER-1B2EA;Lo;0;L;;;;;N;;;;; +1B2EB;NUSHU CHARACTER-1B2EB;Lo;0;L;;;;;N;;;;; +1B2EC;NUSHU CHARACTER-1B2EC;Lo;0;L;;;;;N;;;;; +1B2ED;NUSHU CHARACTER-1B2ED;Lo;0;L;;;;;N;;;;; +1B2EE;NUSHU CHARACTER-1B2EE;Lo;0;L;;;;;N;;;;; +1B2EF;NUSHU CHARACTER-1B2EF;Lo;0;L;;;;;N;;;;; +1B2F0;NUSHU CHARACTER-1B2F0;Lo;0;L;;;;;N;;;;; +1B2F1;NUSHU CHARACTER-1B2F1;Lo;0;L;;;;;N;;;;; +1B2F2;NUSHU CHARACTER-1B2F2;Lo;0;L;;;;;N;;;;; +1B2F3;NUSHU CHARACTER-1B2F3;Lo;0;L;;;;;N;;;;; +1B2F4;NUSHU CHARACTER-1B2F4;Lo;0;L;;;;;N;;;;; +1B2F5;NUSHU CHARACTER-1B2F5;Lo;0;L;;;;;N;;;;; +1B2F6;NUSHU CHARACTER-1B2F6;Lo;0;L;;;;;N;;;;; +1B2F7;NUSHU CHARACTER-1B2F7;Lo;0;L;;;;;N;;;;; +1B2F8;NUSHU CHARACTER-1B2F8;Lo;0;L;;;;;N;;;;; +1B2F9;NUSHU CHARACTER-1B2F9;Lo;0;L;;;;;N;;;;; +1B2FA;NUSHU CHARACTER-1B2FA;Lo;0;L;;;;;N;;;;; +1B2FB;NUSHU CHARACTER-1B2FB;Lo;0;L;;;;;N;;;;; 1BC00;DUPLOYAN LETTER H;Lo;0;L;;;;;N;;;;; 1BC01;DUPLOYAN LETTER X;Lo;0;L;;;;;N;;;;; 1BC02;DUPLOYAN LETTER P;Lo;0;L;;;;;N;;;;; @@ -26154,6 +28261,44 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1DAAD;SIGNWRITING ROTATION MODIFIER-14;Mn;0;NSM;;;;;N;;;;; 1DAAE;SIGNWRITING ROTATION MODIFIER-15;Mn;0;NSM;;;;;N;;;;; 1DAAF;SIGNWRITING ROTATION MODIFIER-16;Mn;0;NSM;;;;;N;;;;; +1E000;COMBINING GLAGOLITIC LETTER AZU;Mn;230;NSM;;;;;N;;;;; +1E001;COMBINING GLAGOLITIC LETTER BUKY;Mn;230;NSM;;;;;N;;;;; +1E002;COMBINING GLAGOLITIC LETTER VEDE;Mn;230;NSM;;;;;N;;;;; +1E003;COMBINING GLAGOLITIC LETTER GLAGOLI;Mn;230;NSM;;;;;N;;;;; +1E004;COMBINING GLAGOLITIC LETTER DOBRO;Mn;230;NSM;;;;;N;;;;; +1E005;COMBINING GLAGOLITIC LETTER YESTU;Mn;230;NSM;;;;;N;;;;; +1E006;COMBINING GLAGOLITIC LETTER ZHIVETE;Mn;230;NSM;;;;;N;;;;; +1E008;COMBINING GLAGOLITIC LETTER ZEMLJA;Mn;230;NSM;;;;;N;;;;; +1E009;COMBINING GLAGOLITIC LETTER IZHE;Mn;230;NSM;;;;;N;;;;; +1E00A;COMBINING GLAGOLITIC LETTER INITIAL IZHE;Mn;230;NSM;;;;;N;;;;; +1E00B;COMBINING GLAGOLITIC LETTER I;Mn;230;NSM;;;;;N;;;;; +1E00C;COMBINING GLAGOLITIC LETTER DJERVI;Mn;230;NSM;;;;;N;;;;; +1E00D;COMBINING GLAGOLITIC LETTER KAKO;Mn;230;NSM;;;;;N;;;;; +1E00E;COMBINING GLAGOLITIC LETTER LJUDIJE;Mn;230;NSM;;;;;N;;;;; +1E00F;COMBINING GLAGOLITIC LETTER MYSLITE;Mn;230;NSM;;;;;N;;;;; +1E010;COMBINING GLAGOLITIC LETTER NASHI;Mn;230;NSM;;;;;N;;;;; +1E011;COMBINING GLAGOLITIC LETTER ONU;Mn;230;NSM;;;;;N;;;;; +1E012;COMBINING GLAGOLITIC LETTER POKOJI;Mn;230;NSM;;;;;N;;;;; +1E013;COMBINING GLAGOLITIC LETTER RITSI;Mn;230;NSM;;;;;N;;;;; +1E014;COMBINING GLAGOLITIC LETTER SLOVO;Mn;230;NSM;;;;;N;;;;; +1E015;COMBINING GLAGOLITIC LETTER TVRIDO;Mn;230;NSM;;;;;N;;;;; +1E016;COMBINING GLAGOLITIC LETTER UKU;Mn;230;NSM;;;;;N;;;;; +1E017;COMBINING GLAGOLITIC LETTER FRITU;Mn;230;NSM;;;;;N;;;;; +1E018;COMBINING GLAGOLITIC LETTER HERU;Mn;230;NSM;;;;;N;;;;; +1E01B;COMBINING GLAGOLITIC LETTER SHTA;Mn;230;NSM;;;;;N;;;;; +1E01C;COMBINING GLAGOLITIC LETTER TSI;Mn;230;NSM;;;;;N;;;;; +1E01D;COMBINING GLAGOLITIC LETTER CHRIVI;Mn;230;NSM;;;;;N;;;;; +1E01E;COMBINING GLAGOLITIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; +1E01F;COMBINING GLAGOLITIC LETTER YERU;Mn;230;NSM;;;;;N;;;;; +1E020;COMBINING GLAGOLITIC LETTER YERI;Mn;230;NSM;;;;;N;;;;; +1E021;COMBINING GLAGOLITIC LETTER YATI;Mn;230;NSM;;;;;N;;;;; +1E023;COMBINING GLAGOLITIC LETTER YU;Mn;230;NSM;;;;;N;;;;; +1E024;COMBINING GLAGOLITIC LETTER SMALL YUS;Mn;230;NSM;;;;;N;;;;; +1E026;COMBINING GLAGOLITIC LETTER YO;Mn;230;NSM;;;;;N;;;;; +1E027;COMBINING GLAGOLITIC LETTER IOTATED SMALL YUS;Mn;230;NSM;;;;;N;;;;; +1E028;COMBINING GLAGOLITIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; +1E029;COMBINING GLAGOLITIC LETTER IOTATED BIG YUS;Mn;230;NSM;;;;;N;;;;; +1E02A;COMBINING GLAGOLITIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; 1E800;MENDE KIKAKUI SYLLABLE M001 KI;Lo;0;R;;;;;N;;;;; 1E801;MENDE KIKAKUI SYLLABLE M002 KA;Lo;0;R;;;;;N;;;;; 1E802;MENDE KIKAKUI SYLLABLE M003 KU;Lo;0;R;;;;;N;;;;; @@ -26367,6 +28512,93 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1E8D4;MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS;Mn;220;NSM;;;;;N;;;;; 1E8D5;MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS;Mn;220;NSM;;;;;N;;;;; 1E8D6;MENDE KIKAKUI COMBINING NUMBER MILLIONS;Mn;220;NSM;;;;;N;;;;; +1E900;ADLAM CAPITAL LETTER ALIF;Lu;0;R;;;;;N;;;;1E922; +1E901;ADLAM CAPITAL LETTER DAALI;Lu;0;R;;;;;N;;;;1E923; +1E902;ADLAM CAPITAL LETTER LAAM;Lu;0;R;;;;;N;;;;1E924; +1E903;ADLAM CAPITAL LETTER MIIM;Lu;0;R;;;;;N;;;;1E925; +1E904;ADLAM CAPITAL LETTER BA;Lu;0;R;;;;;N;;;;1E926; +1E905;ADLAM CAPITAL LETTER SINNYIIYHE;Lu;0;R;;;;;N;;;;1E927; +1E906;ADLAM CAPITAL LETTER PE;Lu;0;R;;;;;N;;;;1E928; +1E907;ADLAM CAPITAL LETTER BHE;Lu;0;R;;;;;N;;;;1E929; +1E908;ADLAM CAPITAL LETTER RA;Lu;0;R;;;;;N;;;;1E92A; +1E909;ADLAM CAPITAL LETTER E;Lu;0;R;;;;;N;;;;1E92B; +1E90A;ADLAM CAPITAL LETTER FA;Lu;0;R;;;;;N;;;;1E92C; +1E90B;ADLAM CAPITAL LETTER I;Lu;0;R;;;;;N;;;;1E92D; +1E90C;ADLAM CAPITAL LETTER O;Lu;0;R;;;;;N;;;;1E92E; +1E90D;ADLAM CAPITAL LETTER DHA;Lu;0;R;;;;;N;;;;1E92F; +1E90E;ADLAM CAPITAL LETTER YHE;Lu;0;R;;;;;N;;;;1E930; +1E90F;ADLAM CAPITAL LETTER WAW;Lu;0;R;;;;;N;;;;1E931; +1E910;ADLAM CAPITAL LETTER NUN;Lu;0;R;;;;;N;;;;1E932; +1E911;ADLAM CAPITAL LETTER KAF;Lu;0;R;;;;;N;;;;1E933; +1E912;ADLAM CAPITAL LETTER YA;Lu;0;R;;;;;N;;;;1E934; +1E913;ADLAM CAPITAL LETTER U;Lu;0;R;;;;;N;;;;1E935; +1E914;ADLAM CAPITAL LETTER JIIM;Lu;0;R;;;;;N;;;;1E936; +1E915;ADLAM CAPITAL LETTER CHI;Lu;0;R;;;;;N;;;;1E937; +1E916;ADLAM CAPITAL LETTER HA;Lu;0;R;;;;;N;;;;1E938; +1E917;ADLAM CAPITAL LETTER QAAF;Lu;0;R;;;;;N;;;;1E939; +1E918;ADLAM CAPITAL LETTER GA;Lu;0;R;;;;;N;;;;1E93A; +1E919;ADLAM CAPITAL LETTER NYA;Lu;0;R;;;;;N;;;;1E93B; +1E91A;ADLAM CAPITAL LETTER TU;Lu;0;R;;;;;N;;;;1E93C; +1E91B;ADLAM CAPITAL LETTER NHA;Lu;0;R;;;;;N;;;;1E93D; +1E91C;ADLAM CAPITAL LETTER VA;Lu;0;R;;;;;N;;;;1E93E; +1E91D;ADLAM CAPITAL LETTER KHA;Lu;0;R;;;;;N;;;;1E93F; +1E91E;ADLAM CAPITAL LETTER GBE;Lu;0;R;;;;;N;;;;1E940; +1E91F;ADLAM CAPITAL LETTER ZAL;Lu;0;R;;;;;N;;;;1E941; +1E920;ADLAM CAPITAL LETTER KPO;Lu;0;R;;;;;N;;;;1E942; +1E921;ADLAM CAPITAL LETTER SHA;Lu;0;R;;;;;N;;;;1E943; +1E922;ADLAM SMALL LETTER ALIF;Ll;0;R;;;;;N;;;1E900;;1E900 +1E923;ADLAM SMALL LETTER DAALI;Ll;0;R;;;;;N;;;1E901;;1E901 +1E924;ADLAM SMALL LETTER LAAM;Ll;0;R;;;;;N;;;1E902;;1E902 +1E925;ADLAM SMALL LETTER MIIM;Ll;0;R;;;;;N;;;1E903;;1E903 +1E926;ADLAM SMALL LETTER BA;Ll;0;R;;;;;N;;;1E904;;1E904 +1E927;ADLAM SMALL LETTER SINNYIIYHE;Ll;0;R;;;;;N;;;1E905;;1E905 +1E928;ADLAM SMALL LETTER PE;Ll;0;R;;;;;N;;;1E906;;1E906 +1E929;ADLAM SMALL LETTER BHE;Ll;0;R;;;;;N;;;1E907;;1E907 +1E92A;ADLAM SMALL LETTER RA;Ll;0;R;;;;;N;;;1E908;;1E908 +1E92B;ADLAM SMALL LETTER E;Ll;0;R;;;;;N;;;1E909;;1E909 +1E92C;ADLAM SMALL LETTER FA;Ll;0;R;;;;;N;;;1E90A;;1E90A +1E92D;ADLAM SMALL LETTER I;Ll;0;R;;;;;N;;;1E90B;;1E90B +1E92E;ADLAM SMALL LETTER O;Ll;0;R;;;;;N;;;1E90C;;1E90C +1E92F;ADLAM SMALL LETTER DHA;Ll;0;R;;;;;N;;;1E90D;;1E90D +1E930;ADLAM SMALL LETTER YHE;Ll;0;R;;;;;N;;;1E90E;;1E90E +1E931;ADLAM SMALL LETTER WAW;Ll;0;R;;;;;N;;;1E90F;;1E90F +1E932;ADLAM SMALL LETTER NUN;Ll;0;R;;;;;N;;;1E910;;1E910 +1E933;ADLAM SMALL LETTER KAF;Ll;0;R;;;;;N;;;1E911;;1E911 +1E934;ADLAM SMALL LETTER YA;Ll;0;R;;;;;N;;;1E912;;1E912 +1E935;ADLAM SMALL LETTER U;Ll;0;R;;;;;N;;;1E913;;1E913 +1E936;ADLAM SMALL LETTER JIIM;Ll;0;R;;;;;N;;;1E914;;1E914 +1E937;ADLAM SMALL LETTER CHI;Ll;0;R;;;;;N;;;1E915;;1E915 +1E938;ADLAM SMALL LETTER HA;Ll;0;R;;;;;N;;;1E916;;1E916 +1E939;ADLAM SMALL LETTER QAAF;Ll;0;R;;;;;N;;;1E917;;1E917 +1E93A;ADLAM SMALL LETTER GA;Ll;0;R;;;;;N;;;1E918;;1E918 +1E93B;ADLAM SMALL LETTER NYA;Ll;0;R;;;;;N;;;1E919;;1E919 +1E93C;ADLAM SMALL LETTER TU;Ll;0;R;;;;;N;;;1E91A;;1E91A +1E93D;ADLAM SMALL LETTER NHA;Ll;0;R;;;;;N;;;1E91B;;1E91B +1E93E;ADLAM SMALL LETTER VA;Ll;0;R;;;;;N;;;1E91C;;1E91C +1E93F;ADLAM SMALL LETTER KHA;Ll;0;R;;;;;N;;;1E91D;;1E91D +1E940;ADLAM SMALL LETTER GBE;Ll;0;R;;;;;N;;;1E91E;;1E91E +1E941;ADLAM SMALL LETTER ZAL;Ll;0;R;;;;;N;;;1E91F;;1E91F +1E942;ADLAM SMALL LETTER KPO;Ll;0;R;;;;;N;;;1E920;;1E920 +1E943;ADLAM SMALL LETTER SHA;Ll;0;R;;;;;N;;;1E921;;1E921 +1E944;ADLAM ALIF LENGTHENER;Mn;230;NSM;;;;;N;;;;; +1E945;ADLAM VOWEL LENGTHENER;Mn;230;NSM;;;;;N;;;;; +1E946;ADLAM GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; +1E947;ADLAM HAMZA;Mn;230;NSM;;;;;N;;;;; +1E948;ADLAM CONSONANT MODIFIER;Mn;230;NSM;;;;;N;;;;; +1E949;ADLAM GEMINATE CONSONANT MODIFIER;Mn;230;NSM;;;;;N;;;;; +1E94A;ADLAM NUKTA;Mn;7;NSM;;;;;N;;;;; +1E950;ADLAM DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; +1E951;ADLAM DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; +1E952;ADLAM DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; +1E953;ADLAM DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; +1E954;ADLAM DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; +1E955;ADLAM DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; +1E956;ADLAM DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; +1E957;ADLAM DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; +1E958;ADLAM DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; +1E959;ADLAM DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; +1E95E;ADLAM INITIAL EXCLAMATION MARK;Po;0;R;;;;;N;;;;; +1E95F;ADLAM INITIAL QUESTION MARK;Po;0;R;;;;;N;;;;; 1EE00;ARABIC MATHEMATICAL ALEF;Lo;0;AL; 0627;;;;N;;;;; 1EE01;ARABIC MATHEMATICAL BEH;Lo;0;AL; 0628;;;;N;;;;; 1EE02;ARABIC MATHEMATICAL JEEM;Lo;0;AL; 062C;;;;N;;;;; @@ -26883,6 +29115,24 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F198;SQUARED SOS;So;0;L;;;;;N;;;;; 1F199;SQUARED UP WITH EXCLAMATION MARK;So;0;L;;;;;N;;;;; 1F19A;SQUARED VS;So;0;L;;;;;N;;;;; +1F19B;SQUARED THREE D;So;0;L;;;;;N;;;;; +1F19C;SQUARED SECOND SCREEN;So;0;L;;;;;N;;;;; +1F19D;SQUARED TWO K;So;0;L;;;;;N;;;;; +1F19E;SQUARED FOUR K;So;0;L;;;;;N;;;;; +1F19F;SQUARED EIGHT K;So;0;L;;;;;N;;;;; +1F1A0;SQUARED FIVE POINT ONE;So;0;L;;;;;N;;;;; +1F1A1;SQUARED SEVEN POINT ONE;So;0;L;;;;;N;;;;; +1F1A2;SQUARED TWENTY-TWO POINT TWO;So;0;L;;;;;N;;;;; +1F1A3;SQUARED SIXTY P;So;0;L;;;;;N;;;;; +1F1A4;SQUARED ONE HUNDRED TWENTY P;So;0;L;;;;;N;;;;; +1F1A5;SQUARED LATIN SMALL LETTER D;So;0;L;;;;;N;;;;; +1F1A6;SQUARED HC;So;0;L;;;;;N;;;;; +1F1A7;SQUARED HDR;So;0;L;;;;;N;;;;; +1F1A8;SQUARED HI-RES;So;0;L;;;;;N;;;;; +1F1A9;SQUARED LOSSLESS;So;0;L;;;;;N;;;;; +1F1AA;SQUARED SHV;So;0;L;;;;;N;;;;; +1F1AB;SQUARED UHD;So;0;L;;;;;N;;;;; +1F1AC;SQUARED VOD;So;0;L;;;;;N;;;;; 1F1E6;REGIONAL INDICATOR SYMBOL LETTER A;So;0;L;;;;;N;;;;; 1F1E7;REGIONAL INDICATOR SYMBOL LETTER B;So;0;L;;;;;N;;;;; 1F1E8;REGIONAL INDICATOR SYMBOL LETTER C;So;0;L;;;;;N;;;;; @@ -26955,6 +29205,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F238;SQUARED CJK UNIFIED IDEOGRAPH-7533;So;0;L; 7533;;;;N;;;;; 1F239;SQUARED CJK UNIFIED IDEOGRAPH-5272;So;0;L; 5272;;;;N;;;;; 1F23A;SQUARED CJK UNIFIED IDEOGRAPH-55B6;So;0;L; 55B6;;;;N;;;;; +1F23B;SQUARED CJK UNIFIED IDEOGRAPH-914D;So;0;L; 914D;;;;N;;;;; 1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L; 3014 672C 3015;;;;N;;;;; 1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L; 3014 4E09 3015;;;;N;;;;; 1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L; 3014 4E8C 3015;;;;N;;;;; @@ -26966,6 +29217,12 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L; 3014 6557 3015;;;;N;;;;; 1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L; 5F97;;;;N;;;;; 1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L; 53EF;;;;N;;;;; +1F260;ROUNDED SYMBOL FOR FU;So;0;ON;;;;;N;;;;; +1F261;ROUNDED SYMBOL FOR LU;So;0;ON;;;;;N;;;;; +1F262;ROUNDED SYMBOL FOR SHOU;So;0;ON;;;;;N;;;;; +1F263;ROUNDED SYMBOL FOR XI;So;0;ON;;;;;N;;;;; +1F264;ROUNDED SYMBOL FOR SHUANGXI;So;0;ON;;;;;N;;;;; +1F265;ROUNDED SYMBOL FOR CAI;So;0;ON;;;;;N;;;;; 1F300;CYCLONE;So;0;ON;;;;;N;;;;; 1F301;FOGGY;So;0;ON;;;;;N;;;;; 1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;; @@ -27600,6 +29857,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F577;SPIDER;So;0;ON;;;;;N;;;;; 1F578;SPIDER WEB;So;0;ON;;;;;N;;;;; 1F579;JOYSTICK;So;0;ON;;;;;N;;;;; +1F57A;MAN DANCING;So;0;ON;;;;;N;;;;; 1F57B;LEFT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; 1F57C;TELEPHONE RECEIVER WITH PAGE;So;0;ON;;;;;N;;;;; 1F57D;RIGHT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; @@ -27641,6 +29899,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F5A1;SIDEWAYS BLACK DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; 1F5A2;BLACK UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; 1F5A3;BLACK DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F5A4;BLACK HEART;So;0;ON;;;;;N;;;;; 1F5A5;DESKTOP COMPUTER;So;0;ON;;;;;N;;;;; 1F5A6;KEYBOARD AND MOUSE;So;0;ON;;;;;N;;;;; 1F5A7;THREE NETWORKED COMPUTERS;So;0;ON;;;;;N;;;;; @@ -27941,6 +30200,10 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F6CE;BELLHOP BELL;So;0;ON;;;;;N;;;;; 1F6CF;BED;So;0;ON;;;;;N;;;;; 1F6D0;PLACE OF WORSHIP;So;0;ON;;;;;N;;;;; +1F6D1;OCTAGONAL SIGN;So;0;ON;;;;;N;;;;; +1F6D2;SHOPPING TROLLEY;So;0;ON;;;;;N;;;;; +1F6D3;STUPA;So;0;ON;;;;;N;;;;; +1F6D4;PAGODA;So;0;ON;;;;;N;;;;; 1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;; 1F6E1;SHIELD;So;0;ON;;;;;N;;;;; 1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;; @@ -27958,6 +30221,11 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F6F1;ONCOMING FIRE ENGINE;So;0;ON;;;;;N;;;;; 1F6F2;DIESEL LOCOMOTIVE;So;0;ON;;;;;N;;;;; 1F6F3;PASSENGER SHIP;So;0;ON;;;;;N;;;;; +1F6F4;SCOOTER;So;0;ON;;;;;N;;;;; +1F6F5;MOTOR SCOOTER;So;0;ON;;;;;N;;;;; +1F6F6;CANOE;So;0;ON;;;;;N;;;;; +1F6F7;SLED;So;0;ON;;;;;N;;;;; +1F6F8;FLYING SAUCER;So;0;ON;;;;;N;;;;; 1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;; 1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;; 1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;; @@ -28307,6 +30575,18 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; 1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; 1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; +1F900;CIRCLED CROSS FORMEE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F901;CIRCLED CROSS FORMEE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F902;CIRCLED CROSS FORMEE;So;0;ON;;;;;N;;;;; +1F903;LEFT HALF CIRCLE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F904;LEFT HALF CIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F905;LEFT HALF CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F906;LEFT HALF CIRCLE WITH DOT;So;0;ON;;;;;N;;;;; +1F907;LEFT HALF CIRCLE;So;0;ON;;;;;N;;;;; +1F908;DOWNWARD FACING HOOK;So;0;ON;;;;;N;;;;; +1F909;DOWNWARD FACING NOTCHED HOOK;So;0;ON;;;;;N;;;;; +1F90A;DOWNWARD FACING HOOK WITH DOT;So;0;ON;;;;;N;;;;; +1F90B;DOWNWARD FACING NOTCHED HOOK WITH DOT;So;0;ON;;;;;N;;;;; 1F910;ZIPPER-MOUTH FACE;So;0;ON;;;;;N;;;;; 1F911;MONEY-MOUTH FACE;So;0;ON;;;;;N;;;;; 1F912;FACE WITH THERMOMETER;So;0;ON;;;;;N;;;;; @@ -28316,12 +30596,133 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F916;ROBOT FACE;So;0;ON;;;;;N;;;;; 1F917;HUGGING FACE;So;0;ON;;;;;N;;;;; 1F918;SIGN OF THE HORNS;So;0;ON;;;;;N;;;;; +1F919;CALL ME HAND;So;0;ON;;;;;N;;;;; +1F91A;RAISED BACK OF HAND;So;0;ON;;;;;N;;;;; +1F91B;LEFT-FACING FIST;So;0;ON;;;;;N;;;;; +1F91C;RIGHT-FACING FIST;So;0;ON;;;;;N;;;;; +1F91D;HANDSHAKE;So;0;ON;;;;;N;;;;; +1F91E;HAND WITH INDEX AND MIDDLE FINGERS CROSSED;So;0;ON;;;;;N;;;;; +1F91F;I LOVE YOU HAND SIGN;So;0;ON;;;;;N;;;;; +1F920;FACE WITH COWBOY HAT;So;0;ON;;;;;N;;;;; +1F921;CLOWN FACE;So;0;ON;;;;;N;;;;; +1F922;NAUSEATED FACE;So;0;ON;;;;;N;;;;; +1F923;ROLLING ON THE FLOOR LAUGHING;So;0;ON;;;;;N;;;;; +1F924;DROOLING FACE;So;0;ON;;;;;N;;;;; +1F925;LYING FACE;So;0;ON;;;;;N;;;;; +1F926;FACE PALM;So;0;ON;;;;;N;;;;; +1F927;SNEEZING FACE;So;0;ON;;;;;N;;;;; +1F928;FACE WITH ONE EYEBROW RAISED;So;0;ON;;;;;N;;;;; +1F929;GRINNING FACE WITH STAR EYES;So;0;ON;;;;;N;;;;; +1F92A;GRINNING FACE WITH ONE LARGE AND ONE SMALL EYE;So;0;ON;;;;;N;;;;; +1F92B;FACE WITH FINGER COVERING CLOSED LIPS;So;0;ON;;;;;N;;;;; +1F92C;SERIOUS FACE WITH SYMBOLS COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92D;SMILING FACE WITH SMILING EYES AND HAND COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92E;FACE WITH OPEN MOUTH VOMITING;So;0;ON;;;;;N;;;;; +1F92F;SHOCKED FACE WITH EXPLODING HEAD;So;0;ON;;;;;N;;;;; +1F930;PREGNANT WOMAN;So;0;ON;;;;;N;;;;; +1F931;BREAST-FEEDING;So;0;ON;;;;;N;;;;; +1F932;PALMS UP TOGETHER;So;0;ON;;;;;N;;;;; +1F933;SELFIE;So;0;ON;;;;;N;;;;; +1F934;PRINCE;So;0;ON;;;;;N;;;;; +1F935;MAN IN TUXEDO;So;0;ON;;;;;N;;;;; +1F936;MOTHER CHRISTMAS;So;0;ON;;;;;N;;;;; +1F937;SHRUG;So;0;ON;;;;;N;;;;; +1F938;PERSON DOING CARTWHEEL;So;0;ON;;;;;N;;;;; +1F939;JUGGLING;So;0;ON;;;;;N;;;;; +1F93A;FENCER;So;0;ON;;;;;N;;;;; +1F93B;MODERN PENTATHLON;So;0;ON;;;;;N;;;;; +1F93C;WRESTLERS;So;0;ON;;;;;N;;;;; +1F93D;WATER POLO;So;0;ON;;;;;N;;;;; +1F93E;HANDBALL;So;0;ON;;;;;N;;;;; +1F940;WILTED FLOWER;So;0;ON;;;;;N;;;;; +1F941;DRUM WITH DRUMSTICKS;So;0;ON;;;;;N;;;;; +1F942;CLINKING GLASSES;So;0;ON;;;;;N;;;;; +1F943;TUMBLER GLASS;So;0;ON;;;;;N;;;;; +1F944;SPOON;So;0;ON;;;;;N;;;;; +1F945;GOAL NET;So;0;ON;;;;;N;;;;; +1F946;RIFLE;So;0;ON;;;;;N;;;;; +1F947;FIRST PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F948;SECOND PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F949;THIRD PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F94A;BOXING GLOVE;So;0;ON;;;;;N;;;;; +1F94B;MARTIAL ARTS UNIFORM;So;0;ON;;;;;N;;;;; +1F94C;CURLING STONE;So;0;ON;;;;;N;;;;; +1F950;CROISSANT;So;0;ON;;;;;N;;;;; +1F951;AVOCADO;So;0;ON;;;;;N;;;;; +1F952;CUCUMBER;So;0;ON;;;;;N;;;;; +1F953;BACON;So;0;ON;;;;;N;;;;; +1F954;POTATO;So;0;ON;;;;;N;;;;; +1F955;CARROT;So;0;ON;;;;;N;;;;; +1F956;BAGUETTE BREAD;So;0;ON;;;;;N;;;;; +1F957;GREEN SALAD;So;0;ON;;;;;N;;;;; +1F958;SHALLOW PAN OF FOOD;So;0;ON;;;;;N;;;;; +1F959;STUFFED FLATBREAD;So;0;ON;;;;;N;;;;; +1F95A;EGG;So;0;ON;;;;;N;;;;; +1F95B;GLASS OF MILK;So;0;ON;;;;;N;;;;; +1F95C;PEANUTS;So;0;ON;;;;;N;;;;; +1F95D;KIWIFRUIT;So;0;ON;;;;;N;;;;; +1F95E;PANCAKES;So;0;ON;;;;;N;;;;; +1F95F;DUMPLING;So;0;ON;;;;;N;;;;; +1F960;FORTUNE COOKIE;So;0;ON;;;;;N;;;;; +1F961;TAKEOUT BOX;So;0;ON;;;;;N;;;;; +1F962;CHOPSTICKS;So;0;ON;;;;;N;;;;; +1F963;BOWL WITH SPOON;So;0;ON;;;;;N;;;;; +1F964;CUP WITH STRAW;So;0;ON;;;;;N;;;;; +1F965;COCONUT;So;0;ON;;;;;N;;;;; +1F966;BROCCOLI;So;0;ON;;;;;N;;;;; +1F967;PIE;So;0;ON;;;;;N;;;;; +1F968;PRETZEL;So;0;ON;;;;;N;;;;; +1F969;CUT OF MEAT;So;0;ON;;;;;N;;;;; +1F96A;SANDWICH;So;0;ON;;;;;N;;;;; +1F96B;CANNED FOOD;So;0;ON;;;;;N;;;;; 1F980;CRAB;So;0;ON;;;;;N;;;;; 1F981;LION FACE;So;0;ON;;;;;N;;;;; 1F982;SCORPION;So;0;ON;;;;;N;;;;; 1F983;TURKEY;So;0;ON;;;;;N;;;;; 1F984;UNICORN FACE;So;0;ON;;;;;N;;;;; +1F985;EAGLE;So;0;ON;;;;;N;;;;; +1F986;DUCK;So;0;ON;;;;;N;;;;; +1F987;BAT;So;0;ON;;;;;N;;;;; +1F988;SHARK;So;0;ON;;;;;N;;;;; +1F989;OWL;So;0;ON;;;;;N;;;;; +1F98A;FOX FACE;So;0;ON;;;;;N;;;;; +1F98B;BUTTERFLY;So;0;ON;;;;;N;;;;; +1F98C;DEER;So;0;ON;;;;;N;;;;; +1F98D;GORILLA;So;0;ON;;;;;N;;;;; +1F98E;LIZARD;So;0;ON;;;;;N;;;;; +1F98F;RHINOCEROS;So;0;ON;;;;;N;;;;; +1F990;SHRIMP;So;0;ON;;;;;N;;;;; +1F991;SQUID;So;0;ON;;;;;N;;;;; +1F992;GIRAFFE FACE;So;0;ON;;;;;N;;;;; +1F993;ZEBRA FACE;So;0;ON;;;;;N;;;;; +1F994;HEDGEHOG;So;0;ON;;;;;N;;;;; +1F995;SAUROPOD;So;0;ON;;;;;N;;;;; +1F996;T-REX;So;0;ON;;;;;N;;;;; +1F997;CRICKET;So;0;ON;;;;;N;;;;; 1F9C0;CHEESE WEDGE;So;0;ON;;;;;N;;;;; +1F9D0;FACE WITH MONOCLE;So;0;ON;;;;;N;;;;; +1F9D1;ADULT;So;0;ON;;;;;N;;;;; +1F9D2;CHILD;So;0;ON;;;;;N;;;;; +1F9D3;OLDER ADULT;So;0;ON;;;;;N;;;;; +1F9D4;BEARDED PERSON;So;0;ON;;;;;N;;;;; +1F9D5;PERSON WITH HEADSCARF;So;0;ON;;;;;N;;;;; +1F9D6;PERSON IN STEAMY ROOM;So;0;ON;;;;;N;;;;; +1F9D7;PERSON CLIMBING;So;0;ON;;;;;N;;;;; +1F9D8;PERSON IN LOTUS POSITION;So;0;ON;;;;;N;;;;; +1F9D9;MAGE;So;0;ON;;;;;N;;;;; +1F9DA;FAIRY;So;0;ON;;;;;N;;;;; +1F9DB;VAMPIRE;So;0;ON;;;;;N;;;;; +1F9DC;MERPERSON;So;0;ON;;;;;N;;;;; +1F9DD;ELF;So;0;ON;;;;;N;;;;; +1F9DE;GENIE;So;0;ON;;;;;N;;;;; +1F9DF;ZOMBIE;So;0;ON;;;;;N;;;;; +1F9E0;BRAIN;So;0;ON;;;;;N;;;;; +1F9E1;ORANGE HEART;So;0;ON;;;;;N;;;;; +1F9E2;BILLED CAP;So;0;ON;;;;;N;;;;; +1F9E3;SCARF;So;0;ON;;;;;N;;;;; +1F9E4;GLOVES;So;0;ON;;;;;N;;;;; +1F9E5;COAT;So;0;ON;;;;;N;;;;; +1F9E6;SOCKS;So;0;ON;;;;;N;;;;; 20000;;Lo;0;L;;;;;N;;;;; 2A6D6;;Lo;0;L;;;;;N;;;;; 2A700;;Lo;0;L;;;;;N;;;;; @@ -28330,6 +30731,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 2B81D;;Lo;0;L;;;;;N;;;;; 2B820;;Lo;0;L;;;;;N;;;;; 2CEA1;;Lo;0;L;;;;;N;;;;; +2CEB0;;Lo;0;L;;;;;N;;;;; +2EBE0;;Lo;0;L;;;;;N;;;;; 2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; 2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; 2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; diff --git a/make/data/unicodedata/VERSION b/make/data/unicodedata/VERSION index ae9a76b9249..a13e7b9c87e 100644 --- a/make/data/unicodedata/VERSION +++ b/make/data/unicodedata/VERSION @@ -1 +1 @@ -8.0.0 +10.0.0 diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index d782c7dfcb4..f1b3772cd23 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -42,7 +42,7 @@ import jdk.internal.HotSpotIntrinsicCandidate; * a character's category (lowercase letter, digit, etc.) and for converting * characters from uppercase to lowercase and vice versa. *

    - * Character information is based on the Unicode Standard, version 8.0.0. + * Character information is based on the Unicode Standard, version 10.0.0. *

    * The methods and data of class {@code Character} are defined by * the information in the UnicodeData file that is part of the @@ -672,11 +672,11 @@ class Character implements java.io.Serializable, Comparable { */ public static final class UnicodeBlock extends Subset { /** - * 510 - the expected number of entities + * 638 - the expected number of entities * 0.75 - the default load factor of HashMap */ private static Map map = - new HashMap<>((int)(510 / 0.75f + 1.0f)); + new HashMap<>((int)(638 / 0.75f + 1.0f)); /** * Creates a UnicodeBlock with the given identifier name. @@ -2936,6 +2936,167 @@ class Character implements java.io.Serializable, Comparable { "CJK UNIFIED IDEOGRAPHS EXTENSION E", "CJKUNIFIEDIDEOGRAPHSEXTENSIONE"); + /** + * Constant for the "Syriac Supplement" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock SYRIAC_SUPPLEMENT = + new UnicodeBlock("SYRIAC_SUPPLEMENT", + "SYRIAC SUPPLEMENT", + "SYRIACSUPPLEMENT"); + + /** + * Constant for the "Cyrillic Extended-C" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock CYRILLIC_EXTENDED_C = + new UnicodeBlock("CYRILLIC_EXTENDED_C", + "CYRILLIC EXTENDED-C", + "CYRILLICEXTENDED-C"); + + /** + * Constant for the "Osage" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock OSAGE = + new UnicodeBlock("OSAGE"); + + /** + * Constant for the "Newa" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock NEWA = + new UnicodeBlock("NEWA"); + + /** + * Constant for the "Mongolian Supplement" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock MONGOLIAN_SUPPLEMENT = + new UnicodeBlock("MONGOLIAN_SUPPLEMENT", + "MONGOLIAN SUPPLEMENT", + "MONGOLIANSUPPLEMENT"); + + /** + * Constant for the "Marchen" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock MARCHEN = + new UnicodeBlock("MARCHEN"); + + /** + * Constant for the "Ideographic Symbols and Punctuation" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION = + new UnicodeBlock("IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION", + "IDEOGRAPHIC SYMBOLS AND PUNCTUATION", + "IDEOGRAPHICSYMBOLSANDPUNCTUATION"); + + /** + * Constant for the "Tangut" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock TANGUT = + new UnicodeBlock("TANGUT"); + + /** + * Constant for the "Tangut Components" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock TANGUT_COMPONENTS = + new UnicodeBlock("TANGUT_COMPONENTS", + "TANGUT COMPONENTS", + "TANGUTCOMPONENTS"); + + /** + * Constant for the "Kana Extended-A" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock KANA_EXTENDED_A = + new UnicodeBlock("KANA_EXTENDED_A", + "KANA EXTENDED-A", + "KANAEXTENDED-A"); + /** + * Constant for the "Glagolitic Supplement" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock GLAGOLITIC_SUPPLEMENT = + new UnicodeBlock("GLAGOLITIC_SUPPLEMENT", + "GLAGOLITIC SUPPLEMENT", + "GLAGOLITICSUPPLEMENT"); + /** + * Constant for the "Adlam" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock ADLAM = + new UnicodeBlock("ADLAM"); + + /** + * Constant for the "Masaram Gondi" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock MASARAM_GONDI = + new UnicodeBlock("MASARAM_GONDI", + "MASARAM GONDI", + "MASARAMGONDI"); + + /** + * Constant for the "Zanabazar Square" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock ZANABAZAR_SQUARE = + new UnicodeBlock("ZANABAZAR_SQUARE", + "ZANABAZAR SQUARE", + "ZANABAZARSQUARE"); + + /** + * Constant for the "Nushu" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock NUSHU = + new UnicodeBlock("NUSHU"); + + /** + * Constant for the "Soyombo" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock SOYOMBO = + new UnicodeBlock("SOYOMBO"); + + /** + * Constant for the "Bhaiksuki" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock BHAIKSUKI = + new UnicodeBlock("BHAIKSUKI"); + + /** + * Constant for the "CJK Unified Ideographs Extension F" Unicode + * character block. + * @since 11 + */ + public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F = + new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F", + "CJK UNIFIED IDEOGRAPHS EXTENSION F", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONF"); private static final int blockStarts[] = { 0x0000, // 0000..007F; Basic Latin @@ -2957,7 +3118,8 @@ class Character implements java.io.Serializable, Comparable { 0x07C0, // 07C0..07FF; NKo 0x0800, // 0800..083F; Samaritan 0x0840, // 0840..085F; Mandaic - 0x0860, // unassigned + 0x0860, // 0860..086F; Syriac Supplement + 0x0870, // unassigned 0x08A0, // 08A0..08FF; Arabic Extended-A 0x0900, // 0900..097F; Devanagari 0x0980, // 0980..09FF; Bengali @@ -3000,7 +3162,8 @@ class Character implements java.io.Serializable, Comparable { 0x1BC0, // 1BC0..1BFF; Batak 0x1C00, // 1C00..1C4F; Lepcha 0x1C50, // 1C50..1C7F; Ol Chiki - 0x1C80, // unassigned + 0x1C80, // 1C80..1C8F; Cyrillic Extended-C + 0x1C90, // unassigned 0x1CC0, // 1CC0..1CCF; Sundanese Supplement 0x1CD0, // 1CD0..1CFF; Vedic Extensions 0x1D00, // 1D00..1D7F; Phonetic Extensions @@ -3120,7 +3283,7 @@ class Character implements java.io.Serializable, Comparable { 0x10400, // 10400..1044F; Deseret 0x10450, // 10450..1047F; Shavian 0x10480, // 10480..104AF; Osmanya - 0x104B0, // unassigned + 0x104B0, // 104B0..104FF; Osage 0x10500, // 10500..1052F; Elbasan 0x10530, // 10530..1056F; Caucasian Albanian 0x10570, // unassigned @@ -3166,19 +3329,28 @@ class Character implements java.io.Serializable, Comparable { 0x112B0, // 112B0..112FF; Khudawadi 0x11300, // 11300..1137F; Grantha 0x11380, // unassigned + 0x11400, // 11400..1147F; Newa 0x11480, // 11480..114DF; Tirhuta 0x114E0, // unassigned 0x11580, // 11580..115FF; Siddham 0x11600, // 11600..1165F; Modi - 0x11660, // unassigned + 0x11660, // 11660..1167F; Mongolian Supplement 0x11680, // 11680..116CF; Takri 0x116D0, // unassigned 0x11700, // 11700..1173F; Ahom 0x11740, // unassigned 0x118A0, // 118A0..118FF; Warang Citi 0x11900, // unassigned + 0x11A00, // 11A00..11A4F; Zanabazar Square + 0x11A50, // 11A50..11AAF; Soyombo + 0x11AB0, // unassigned 0x11AC0, // 11AC0..11AFF; Pau Cin Hau 0x11B00, // unassigned + 0x11C00, // 11C00..11C6F; Bhaiksuki + 0x11C70, // 11C70..11CBF; Marchen + 0x11CC0, // unassigned + 0x11D00, // 11D00..11D5F; Masaram Gondi + 0x11D60, // unassigned 0x12000, // 12000..123FF; Cuneiform 0x12400, // 12400..1247F; Cuneiform Numbers and Punctuation 0x12480, // 12480..1254F; Early Dynastic Cuneiform @@ -3195,8 +3367,15 @@ class Character implements java.io.Serializable, Comparable { 0x16B90, // unassigned 0x16F00, // 16F00..16F9F; Miao 0x16FA0, // unassigned + 0x16FE0, // 16FE0..16FFF; Ideographic Symbols and Punctuation + 0x17000, // 17000..187FF; Tangut + 0x18800, // 18800..18AFF; Tangut Components + 0x18B00, // unassigned 0x1B000, // 1B000..1B0FF; Kana Supplement - 0x1B100, // unassigned + 0x1B100, // 1B100..1B12F; Kana Extended-A + 0x1B130, // unassigned + 0x1B170, // 1B170..1B2FF; Nushu + 0x1B300, // unassigned 0x1BC00, // 1BC00..1BC9F; Duployan 0x1BCA0, // 1BCA0..1BCAF; Shorthand Format Controls 0x1BCB0, // unassigned @@ -3210,8 +3389,12 @@ class Character implements java.io.Serializable, Comparable { 0x1D400, // 1D400..1D7FF; Mathematical Alphanumeric Symbols 0x1D800, // 1D800..1DAAF; Sutton SignWriting 0x1DAB0, // unassigned + 0x1E000, // 1E000..1E02F; Glagolitic Supplement + 0x1E030, // unassigned 0x1E800, // 1E800..1E8DF; Mende Kikakui 0x1E8E0, // unassigned + 0x1E900, // 1E900..1E95F; Adlam + 0x1E960, // unassigned 0x1EE00, // 1EE00..1EEFF; Arabic Mathematical Alphabetic Symbols 0x1EF00, // unassigned 0x1F000, // 1F000..1F02F; Mahjong Tiles @@ -3233,7 +3416,8 @@ class Character implements java.io.Serializable, Comparable { 0x2A700, // 2A700..2B73F; CJK Unified Ideographs Extension C 0x2B740, // 2B740..2B81F; CJK Unified Ideographs Extension D 0x2B820, // 2B820..2CEAF; CJK Unified Ideographs Extension E - 0x2CEB0, // unassigned + 0x2CEB0, // 2CEB0..2EBEF; CJK Unified Ideographs Extension F + 0x2EBF0, // unassigned 0x2F800, // 2F800..2FA1F; CJK Compatibility Ideographs Supplement 0x2FA20, // unassigned 0xE0000, // E0000..E007F; Tags @@ -3264,6 +3448,7 @@ class Character implements java.io.Serializable, Comparable { NKO, SAMARITAN, MANDAIC, + SYRIAC_SUPPLEMENT, null, ARABIC_EXTENDED_A, DEVANAGARI, @@ -3307,6 +3492,7 @@ class Character implements java.io.Serializable, Comparable { BATAK, LEPCHA, OL_CHIKI, + CYRILLIC_EXTENDED_C, null, SUNDANESE_SUPPLEMENT, VEDIC_EXTENSIONS, @@ -3427,7 +3613,7 @@ class Character implements java.io.Serializable, Comparable { DESERET, SHAVIAN, OSMANYA, - null, + OSAGE, ELBASAN, CAUCASIAN_ALBANIAN, null, @@ -3473,19 +3659,28 @@ class Character implements java.io.Serializable, Comparable { KHUDAWADI, GRANTHA, null, + NEWA, TIRHUTA, null, SIDDHAM, MODI, - null, + MONGOLIAN_SUPPLEMENT, TAKRI, null, AHOM, null, WARANG_CITI, null, + ZANABAZAR_SQUARE, + SOYOMBO, + null, PAU_CIN_HAU, null, + BHAIKSUKI, + MARCHEN, + null, + MASARAM_GONDI, + null, CUNEIFORM, CUNEIFORM_NUMBERS_AND_PUNCTUATION, EARLY_DYNASTIC_CUNEIFORM, @@ -3502,7 +3697,14 @@ class Character implements java.io.Serializable, Comparable { null, MIAO, null, + IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION, + TANGUT, + TANGUT_COMPONENTS, + null, KANA_SUPPLEMENT, + KANA_EXTENDED_A, + null, + NUSHU, null, DUPLOYAN, SHORTHAND_FORMAT_CONTROLS, @@ -3517,8 +3719,12 @@ class Character implements java.io.Serializable, Comparable { MATHEMATICAL_ALPHANUMERIC_SYMBOLS, SUTTON_SIGNWRITING, null, + GLAGOLITIC_SUPPLEMENT, + null, MENDE_KIKAKUI, null, + ADLAM, + null, ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS, null, MAHJONG_TILES, @@ -3540,6 +3746,7 @@ class Character implements java.io.Serializable, Comparable { CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C, CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D, CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E, + CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F, null, CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT, null, @@ -4363,6 +4570,66 @@ class Character implements java.io.Serializable, Comparable { */ SIGNWRITING, + /** + * Unicode script "Adlam". + * @since 11 + */ + ADLAM, + + /** + * Unicode script "Bhaiksuki". + * @since 11 + */ + BHAIKSUKI, + + /** + * Unicode script "Marchen". + * @since 11 + */ + MARCHEN, + + /** + * Unicode script "Newa". + * @since 11 + */ + NEWA, + + /** + * Unicode script "Osage". + * @since 11 + */ + OSAGE, + + /** + * Unicode script "Tangut". + * @since 11 + */ + TANGUT, + + /** + * Unicode script "Masaram Gondi". + * @since 11 + */ + MASARAM_GONDI, + + /** + * Unicode script "Nushu". + * @since 11 + */ + NUSHU, + + /** + * Unicode script "Soyombo". + * @since 11 + */ + SOYOMBO, + + /** + * Unicode script "Zanabazar Square". + * @since 11 + */ + ZANABAZAR_SQUARE, + /** * Unicode script "Unknown". */ @@ -4436,7 +4703,8 @@ class Character implements java.io.Serializable, Comparable { 0x0606, // 0606..060B; ARABIC 0x060C, // 060C ; COMMON 0x060D, // 060D..061A; ARABIC - 0x061B, // 061B..061C; COMMON + 0x061B, // 061B ; COMMON + 0x061C, // 061C ; ARABIC 0x061D, // 061D ; UNKNOWN 0x061E, // 061E ; ARABIC 0x061F, // 061F ; COMMON @@ -4466,9 +4734,15 @@ class Character implements java.io.Serializable, Comparable { 0x0840, // 0840..085B; MANDAIC 0x085C, // 085C..085D; UNKNOWN 0x085E, // 085E ; MANDAIC - 0x085F, // 085F..089F; UNKNOWN + 0x085F, // 085F ; UNKNOWN + 0x0860, // 0860..086A; SYRIAC + 0x086B, // 086B..089F; UNKNOWN 0x08A0, // 08A0..08B4; ARABIC - 0x08B5, // 08B5..08E2; UNKNOWN + 0x08B5, // 08B5 ; UNKNOWN + 0x08B6, // 08B6..08BD; ARABIC + 0x08BE, // 08BE..08D3; UNKNOWN + 0x08D4, // 08D4..08E1; ARABIC + 0x08E2, // 08E2 ; COMMON 0x08E3, // 08E3..08FF; ARABIC 0x0900, // 0900..0950; DEVANAGARI 0x0951, // 0951..0952; INHERITED @@ -4501,8 +4775,8 @@ class Character implements java.io.Serializable, Comparable { 0x09DE, // 09DE ; UNKNOWN 0x09DF, // 09DF..09E3; BENGALI 0x09E4, // 09E4..09E5; UNKNOWN - 0x09E6, // 09E6..09FB; BENGALI - 0x09FC, // 09FC..0A00; UNKNOWN + 0x09E6, // 09E6..09FD; BENGALI + 0x09FE, // 09FE..0A00; UNKNOWN 0x0A01, // 0A01..0A03; GURMUKHI 0x0A04, // 0A04 ; UNKNOWN 0x0A05, // 0A05..0A0A; GURMUKHI @@ -4561,8 +4835,8 @@ class Character implements java.io.Serializable, Comparable { 0x0AE4, // 0AE4..0AE5; UNKNOWN 0x0AE6, // 0AE6..0AF1; GUJARATI 0x0AF2, // 0AF2..0AF8; UNKNOWN - 0x0AF9, // 0AF9 ; GUJARATI - 0x0AFA, // 0AFA..0B00; UNKNOWN + 0x0AF9, // 0AF9..0AFF; GUJARATI + 0x0B00, // 0B00 ; UNKNOWN 0x0B01, // 0B01..0B03; ORIYA 0x0B04, // 0B04 ; UNKNOWN 0x0B05, // 0B05..0B0C; ORIYA @@ -4648,8 +4922,7 @@ class Character implements java.io.Serializable, Comparable { 0x0C66, // 0C66..0C6F; TELUGU 0x0C70, // 0C70..0C77; UNKNOWN 0x0C78, // 0C78..0C7F; TELUGU - 0x0C80, // 0C80 ; UNKNOWN - 0x0C81, // 0C81..0C83; KANNADA + 0x0C80, // 0C80..0C83; KANNADA 0x0C84, // 0C84 ; UNKNOWN 0x0C85, // 0C85..0C8C; KANNADA 0x0C8D, // 0C8D ; UNKNOWN @@ -4676,28 +4949,22 @@ class Character implements java.io.Serializable, Comparable { 0x0CE6, // 0CE6..0CEF; KANNADA 0x0CF0, // 0CF0 ; UNKNOWN 0x0CF1, // 0CF1..0CF2; KANNADA - 0x0CF3, // 0CF3..0D00; UNKNOWN - 0x0D01, // 0D01..0D03; MALAYALAM + 0x0CF3, // 0CF3..0CFF; UNKNOWN + 0x0D00, // 0D00..0D03; MALAYALAM 0x0D04, // 0D04 ; UNKNOWN 0x0D05, // 0D05..0D0C; MALAYALAM 0x0D0D, // 0D0D ; UNKNOWN 0x0D0E, // 0D0E..0D10; MALAYALAM 0x0D11, // 0D11 ; UNKNOWN - 0x0D12, // 0D12..0D3A; MALAYALAM - 0x0D3B, // 0D3B..0D3C; UNKNOWN - 0x0D3D, // 0D3D..0D44; MALAYALAM + 0x0D12, // 0D12..0D44; MALAYALAM 0x0D45, // 0D45 ; UNKNOWN 0x0D46, // 0D46..0D48; MALAYALAM 0x0D49, // 0D49 ; UNKNOWN - 0x0D4A, // 0D4A..0D4E; MALAYALAM - 0x0D4F, // 0D4F..0D56; UNKNOWN - 0x0D57, // 0D57 ; MALAYALAM - 0x0D58, // 0D58..0D5E; UNKNOWN - 0x0D5F, // 0D5F..0D63; MALAYALAM + 0x0D4A, // 0D4A..0D4F; MALAYALAM + 0x0D50, // 0D50..0D53; UNKNOWN + 0x0D54, // 0D54..0D63; MALAYALAM 0x0D64, // 0D64..0D65; UNKNOWN - 0x0D66, // 0D66..0D75; MALAYALAM - 0x0D76, // 0D76..0D78; UNKNOWN - 0x0D79, // 0D79..0D7F; MALAYALAM + 0x0D66, // 0D66..0D7F; MALAYALAM 0x0D80, // 0D80..0D81; UNKNOWN 0x0D82, // 0D82..0D83; SINHALA 0x0D84, // 0D84 ; UNKNOWN @@ -4921,7 +5188,8 @@ class Character implements java.io.Serializable, Comparable { 0x1C4A, // 1C4A..1C4C; UNKNOWN 0x1C4D, // 1C4D..1C4F; LEPCHA 0x1C50, // 1C50..1C7F; OL_CHIKI - 0x1C80, // 1C80..1CBF; UNKNOWN + 0x1C80, // 1C80..1C88; CYRILLIC + 0x1C89, // 1C89..1CBF; UNKNOWN 0x1CC0, // 1CC0..1CC7; SUNDANESE 0x1CC8, // 1CC8..1CCF; UNKNOWN 0x1CD0, // 1CD0..1CD2; INHERITED @@ -4933,8 +5201,7 @@ class Character implements java.io.Serializable, Comparable { 0x1CED, // 1CED ; INHERITED 0x1CEE, // 1CEE..1CF3; COMMON 0x1CF4, // 1CF4 ; INHERITED - 0x1CF5, // 1CF5..1CF6; COMMON - 0x1CF7, // 1CF7 ; UNKNOWN + 0x1CF5, // 1CF5..1CF7; COMMON 0x1CF8, // 1CF8..1CF9; INHERITED 0x1CFA, // 1CFA..1CFF; UNKNOWN 0x1D00, // 1D00..1D25; LATIN @@ -4948,9 +5215,9 @@ class Character implements java.io.Serializable, Comparable { 0x1D78, // 1D78 ; CYRILLIC 0x1D79, // 1D79..1DBE; LATIN 0x1DBF, // 1DBF ; GREEK - 0x1DC0, // 1DC0..1DF5; INHERITED - 0x1DF6, // 1DF6..1DFB; UNKNOWN - 0x1DFC, // 1DFC..1DFF; INHERITED + 0x1DC0, // 1DC0..1DF9; INHERITED + 0x1DFA, // 1DFA ; UNKNOWN + 0x1DFB, // 1DFB..1DFF; INHERITED 0x1E00, // 1E00..1EFF; LATIN 0x1F00, // 1F00..1F15; GREEK 0x1F16, // 1F16..1F17; UNKNOWN @@ -4997,8 +5264,8 @@ class Character implements java.io.Serializable, Comparable { 0x208F, // 208F ; UNKNOWN 0x2090, // 2090..209C; LATIN 0x209D, // 209D..209F; UNKNOWN - 0x20A0, // 20A0..20BE; COMMON - 0x20BF, // 20BF..20CF; UNKNOWN + 0x20A0, // 20A0..20BF; COMMON + 0x20C0, // 20C0..20CF; UNKNOWN 0x20D0, // 20D0..20F0; INHERITED 0x20F1, // 20F1..20FF; UNKNOWN 0x2100, // 2100..2125; COMMON @@ -5013,9 +5280,7 @@ class Character implements java.io.Serializable, Comparable { 0x2160, // 2160..2188; LATIN 0x2189, // 2189..218B; COMMON 0x218C, // 218C..218F; UNKNOWN - 0x2190, // 2190..23FA; COMMON - 0x23FB, // 23FB..23FF; UNKNOWN - 0x2400, // 2400..2426; COMMON + 0x2190, // 2190..2426; COMMON 0x2427, // 2427..243F; UNKNOWN 0x2440, // 2440..244A; COMMON 0x244B, // 244B..245F; UNKNOWN @@ -5029,8 +5294,8 @@ class Character implements java.io.Serializable, Comparable { 0x2BBA, // 2BBA..2BBC; UNKNOWN 0x2BBD, // 2BBD..2BC8; COMMON 0x2BC9, // 2BC9 ; UNKNOWN - 0x2BCA, // 2BCA..2BD1; COMMON - 0x2BD2, // 2BD2..2BEB; UNKNOWN + 0x2BCA, // 2BCA..2BD2; COMMON + 0x2BD3, // 2BD3..2BEB; UNKNOWN 0x2BEC, // 2BEC..2BEF; COMMON 0x2BF0, // 2BF0..2BFF; UNKNOWN 0x2C00, // 2C00..2C2E; GLAGOLITIC @@ -5071,8 +5336,8 @@ class Character implements java.io.Serializable, Comparable { 0x2DD8, // 2DD8..2DDE; ETHIOPIC 0x2DDF, // 2DDF ; UNKNOWN 0x2DE0, // 2DE0..2DFF; CYRILLIC - 0x2E00, // 2E00..2E42; COMMON - 0x2E43, // 2E43..2E7F; UNKNOWN + 0x2E00, // 2E00..2E49; COMMON + 0x2E50, // 2E50..2E7F; UNKNOWN 0x2E80, // 2E80..2E99; HAN 0x2E9A, // 2E9A ; UNKNOWN 0x2E9B, // 2E9B..2EF3; HAN @@ -5103,8 +5368,8 @@ class Character implements java.io.Serializable, Comparable { 0x30FB, // 30FB..30FC; COMMON 0x30FD, // 30FD..30FF; KATAKANA 0x3100, // 3100..3104; UNKNOWN - 0x3105, // 3105..312D; BOPOMOFO - 0x312E, // 312E..3130; UNKNOWN + 0x3105, // 3105..312E; BOPOMOFO + 0x312F, // 312F..3130; UNKNOWN 0x3131, // 3131..318E; HANGUL 0x318F, // 318F ; UNKNOWN 0x3190, // 3190..319F; COMMON @@ -5125,8 +5390,8 @@ class Character implements java.io.Serializable, Comparable { 0x3400, // 3400..4DB5; HAN 0x4DB6, // 4DB6..4DBF; UNKNOWN 0x4DC0, // 4DC0..4DFF; COMMON - 0x4E00, // 4E00..9FD5; HAN - 0x9FD6, // 9FD6..9FFF; UNKNOWN + 0x4E00, // 4E00..9FEA; HAN + 0x9FEB, // 9FEB..9FFF; UNKNOWN 0xA000, // A000..A48C; YI 0xA48D, // A48D..A48F; UNKNOWN 0xA490, // A490..A4C6; YI @@ -5140,8 +5405,8 @@ class Character implements java.io.Serializable, Comparable { 0xA700, // A700..A721; COMMON 0xA722, // A722..A787; LATIN 0xA788, // A788..A78A; COMMON - 0xA78B, // A78B..A7AD; LATIN - 0xA7AE, // A7AE..A7AF; UNKNOWN + 0xA78B, // A78B..A7AE; LATIN + 0xA7AF, // A7AF ; UNKNOWN 0xA7B0, // A7B0..A7B7; LATIN 0xA7B8, // A7B8..A7F6; UNKNOWN 0xA7F7, // A7F7..A7FF; LATIN @@ -5151,8 +5416,8 @@ class Character implements java.io.Serializable, Comparable { 0xA83A, // A83A..A83F; UNKNOWN 0xA840, // A840..A877; PHAGS_PA 0xA878, // A878..A87F; UNKNOWN - 0xA880, // A880..A8C4; SAURASHTRA - 0xA8C5, // A8C5..A8CD; UNKNOWN + 0xA880, // A880..A8C5; SAURASHTRA + 0xA8C6, // A8C6..A8CD; UNKNOWN 0xA8CE, // A8CE..A8D9; SAURASHTRA 0xA8DA, // A8DA..A8DF; UNKNOWN 0xA8E0, // A8E0..A8FD; DEVANAGARI @@ -5303,8 +5568,8 @@ class Character implements java.io.Serializable, Comparable { 0x10107, // 10107..10133; COMMON 0x10134, // 10134..10136; UNKNOWN 0x10137, // 10137..1013F; COMMON - 0x10140, // 10140..1018C; GREEK - 0x1018D, // 1018D..1018F; UNKNOWN + 0x10140, // 10140..1018E; GREEK + 0x1018F, // 1018F ; UNKNOWN 0x10190, // 10190..1019B; COMMON 0x1019C, // 1019C..1019F; UNKNOWN 0x101A0, // 101A0 ; GREEK @@ -5320,7 +5585,8 @@ class Character implements java.io.Serializable, Comparable { 0x102E1, // 102E1..102FB; COMMON 0x102FC, // 102FC..102FF; UNKNOWN 0x10300, // 10300..10323; OLD_ITALIC - 0x10324, // 10324..1032F; UNKNOWN + 0x10324, // 10324..1032C; UNKNOWN + 0x1032D, // 1032D..1032F; OLD_ITALIC 0x10330, // 10330..1034A; GOTHIC 0x1034B, // 1034B..1034F; UNKNOWN 0x10350, // 10350..1037A; OLD_PERMIC @@ -5337,7 +5603,11 @@ class Character implements java.io.Serializable, Comparable { 0x10480, // 10480..1049D; OSMANYA 0x1049E, // 1049E..1049F; UNKNOWN 0x104A0, // 104A0..104A9; OSMANYA - 0x104AA, // 104AA..104FF; UNKNOWN + 0x104AA, // 104AA..104AF; UNKNOWN + 0x104B0, // 104B0..104D3; OSAGE + 0x104D4, // 104D4..104D7; UNKNOWN + 0x104D8, // 104D8..104FB; OSAGE + 0x104FC, // 104FC..104FF; UNKNOWN 0x10500, // 10500..10527; ELBASAN 0x10528, // 10528..1052F; UNKNOWN 0x10530, // 10530..10563; CAUCASIAN_ALBANIAN @@ -5460,8 +5730,8 @@ class Character implements java.io.Serializable, Comparable { 0x111F5, // 111F5..111FF; UNKNOWN 0x11200, // 11200..11211; KHOJKI 0x11212, // 11212 ; UNKNOWN - 0x11213, // 11213..1123D; KHOJKI - 0x1123E, // 1123E..1127F; UNKNOWN + 0x11213, // 11213..1123E; KHOJKI + 0x1123F, // 1123F..1127F; UNKNOWN 0x11280, // 11280..11286; MULTANI 0x11287, // 11287 ; UNKNOWN 0x11288, // 11288 ; MULTANI @@ -5505,7 +5775,13 @@ class Character implements java.io.Serializable, Comparable { 0x11366, // 11366..1136C; GRANTHA 0x1136D, // 1136D..1136F; UNKNOWN 0x11370, // 11370..11374; GRANTHA - 0x11375, // 11375..1147F; UNKNOWN + 0x11375, // 11375..113FF; UNKNOWN + 0x11400, // 11400..11459; NEWA + 0x1145A, // 1145A ; UNKNOWN + 0x1145B, // 1145B ; NEWA + 0x1145C, // 1145C ; UNKNOWN + 0x1145D, // 1145D ; NEWA + 0x1145E, // 1145E..1147F; UNKNOWN 0x11480, // 11480..114C7; TIRHUTA 0x114C8, // 114C8..114CF; UNKNOWN 0x114D0, // 114D0..114D9; TIRHUTA @@ -5517,7 +5793,9 @@ class Character implements java.io.Serializable, Comparable { 0x11600, // 11600..11644; MODI 0x11645, // 11645..1164F; UNKNOWN 0x11650, // 11650..11659; MODI - 0x1165A, // 1165A..1167F; UNKNOWN + 0x1165A, // 1165A..1165F; UNKNOWN + 0x11660, // 11660..1166C; MONGOLIAN + 0X1166D, // 1166D..1167F; UNKNOWN 0x11680, // 11680..116B7; TAKRI 0x116B8, // 116B8..116BF; UNKNOWN 0x116C0, // 116C0..116C9; TAKRI @@ -5531,9 +5809,45 @@ class Character implements java.io.Serializable, Comparable { 0x118A0, // 118A0..118F2; WARANG_CITI 0x118F3, // 118F3..118FE; UNKNOWN 0x118FF, // 118FF ; WARANG_CITI - 0x11900, // 11900..11ABF; UNKNOWN + 0x11900, // 11900..119FF; UNKNOWN + 0x11A00, // 11A00..11A47; ZANABAZAR_SQUARE + 0X11A48, // 11A48..11A4F; UNKNOWN + 0x11A50, // 11A50..11A83; SOYOMBO + 0x11A84, // 11A84..11A85; UNKNOWN + 0x11A86, // 11A86..11A9C; SOYOMBO + 0x11A9D, // 11A9D ; UNKNOWN + 0x11A9E, // 11A9E..11AA2; SOYOMBO + 0x11AA3, // 11AA3..11ABF; UNKNOWN 0x11AC0, // 11AC0..11AF8; PAU_CIN_HAU - 0x11AF9, // 11AF9..11FFF; UNKNOWN + 0x11AF9, // 11AF9..11BFF; UNKNOWN + 0x11C00, // 11C00..11C08; BHAIKSUKI + 0x11C09, // 11C09 ; UNKNOWN + 0x11C0A, // 11C0A..11C36; BHAIKSUKI + 0x11C37, // 11C37 ; UNKNOWN + 0x11C38, // 11C38..11C45; BHAIKSUKI + 0x11C46, // 11C46..11C49; UNKNOWN + 0x11C50, // 11C50..11C6C; BHAIKSUKI + 0x11C6D, // 11C6D..11C6F; UNKNOWN + 0x11C70, // 11C70..11C8F; MARCHEN + 0x11C90, // 11C90..11C91; UNKNOWN + 0x11C92, // 11C92..11CA7; MARCHEN + 0x11CA8, // 11CA8 ; UNKNOWN + 0x11CA9, // 11CA9..11CB6; MARCHEN + 0x11CB7, // 11CB7..11CFF; UNKNOWN + 0x11D00, // 11D00..11D06; MASARAM_GONDI + 0x11D07, // 11D07 ; UNKNOWN + 0x11D08, // 11D08..11D09; MASARAM_GONDI + 0x11D0A, // 11D0A ; UNKNOWN + 0x11D0B, // 11D0B..11D36; MASARAM_GONDI + 0x11D37, // 11D37..11D39; UNKNOWN + 0x11D3A, // 11D3A ; MASARAM_GONDI + 0x11D3B, // 11D3B ; UNKNOWN + 0x11D3C, // 11D3C..11D3D; MASARAM_GONDI + 0x11D3E, // 11D3E ; UNKNOWN + 0x11D3F, // 11D3F..11D47; MASARAM_GONDI + 0x11D48, // 11D48..11D49, UNKNOWN + 0x11D50, // 11D50..11D59; MASARAM_GONDI + 0x11D5A, // 11D5A..1AFFF; UNKNOWN 0x12000, // 12000..12399; CUNEIFORM 0x1239A, // 1239A..123FF; UNKNOWN 0x12400, // 12400..1246E; CUNEIFORM @@ -5573,10 +5887,19 @@ class Character implements java.io.Serializable, Comparable { 0x16F50, // 16F50..16F7E; MIAO 0x16F7F, // 16F7F..16F8E; UNKNOWN 0x16F8F, // 16F8F..16F9F; MIAO - 0x16FA0, // 16FA0..1AFFF; UNKNOWN + 0x16FA0, // 16FA0..16FDF; UNKNOWN + 0x16FE0, // 16FE0 ; TANGUT + 0x16FE1, // 16FE1 ; NUSHU + 0x16FE2, // 16FE2..16FFF; UNKNOWN + 0x17000, // 17000..187EC; TANGUT + 0x187ED, // 187ED..187FF; UNKNOWN + 0x18800, // 18800..18AF2; TANGUT + 0x18AF3, // 18AF3..1AFFF; UNKNOWN 0x1B000, // 1B000 ; KATAKANA - 0x1B001, // 1B001 ; HIRAGANA - 0x1B002, // 1B002..1BBFF; UNKNOWN + 0x1B001, // 1B001..1B11E; HIRAGANA + 0x1B11F, // 1B11F..1B16F; UNKNOWN + 0x1B170, // 1B170..1B2FB; NUSHU + 0x1B2FC, // 1B2FC..1BBFF; UNKNOWN 0x1BC00, // 1BC00..1BC6A; DUPLOYAN 0x1BC6B, // 1BC6B..1BC6F; UNKNOWN 0x1BC70, // 1BC70..1BC7C; DUPLOYAN @@ -5654,11 +5977,27 @@ class Character implements java.io.Serializable, Comparable { 0x1DA9B, // 1DA9B..1DA9F; SIGNWRITING 0x1DAA0, // 1DAA0 ; UNKNOWN 0x1DAA1, // 1DAA1..1DAAF; SIGNWRITING - 0x1DAB0, // 1DAB0..1E7FF; UNKNOWN + 0x1DAB0, // 1DAB0..1DFFF; UNKNOWN + 0x1E000, // 1E000..1E006; GLAGOLITIC + 0x1E007, // 1E007 ; UNKNOWN + 0x1E008, // 1E008..1E018; GLAGOLITIC + 0x1E019, // 1E019..1E01A; UNKNOWN + 0x1E01B, // 1E01B..1E021; GLAGOLITIC + 0x1E022, // 1E022 ; UNKNOWN + 0x1E023, // 1E023..1E024; GLAGOLITIC + 0x1E025, // 1E025 ; UNKNOWN + 0x1E026, // 1E026..1E02A; GLAGOLITIC + 0x1E02B, // 1E02B..1E7FF; UNKNOWN 0x1E800, // 1E800..1E8C4; MENDE_KIKAKUI 0x1E8C5, // 1E8C5..1E8C6; UNKNOWN 0x1E8C7, // 1E8C7..1E8D6; MENDE_KIKAKUI - 0x1E8D7, // 1E8D7..1EDFF; UNKNOWN + 0x1E8D7, // 1E8D7..1E8FF; UNKNOWN + 0x1E900, // 1E900..1E94A; ADLAM + 0x1E94B, // 1E94B..1E94F; UNKNOWN + 0x1E950, // 1E950..1E959; ADLAM + 0x1E95A, // 1E95A..1E95D; UNKNOWN + 0x1E95E, // 1E95E..1E95F; ADLAM + 0x1E960, // 1E960..1EDFF; UNKNOWN 0x1EE00, // 1EE00..1EE03; ARABIC 0x1EE04, // 1EE04 ; UNKNOWN 0x1EE05, // 1EE05..1EE1F; ARABIC @@ -5745,28 +6084,26 @@ class Character implements java.io.Serializable, Comparable { 0x1F12F, // 1F12F ; UNKNOWN 0x1F130, // 1F130..1F16B; COMMON 0x1F16C, // 1F16C..1F16F; UNKNOWN - 0x1F170, // 1F170..1F19A; COMMON - 0x1F19B, // 1F19B..1F1E5; UNKNOWN + 0x1F170, // 1F170..1F1AC; COMMON + 0x1F1AD, // 1F1AD..1F1E5; UNKNOWN 0x1F1E6, // 1F1E6..1F1FF; COMMON 0x1F200, // 1F200 ; HIRAGANA 0x1F201, // 1F201..1F202; COMMON 0x1F203, // 1F203..1F20F; UNKNOWN - 0x1F210, // 1F210..1F23A; COMMON - 0x1F23B, // 1F23B..1F23F; UNKNOWN + 0x1F210, // 1F210..1F23B; COMMON + 0x1F23C, // 1F23C..1F23F; UNKNOWN 0x1F240, // 1F240..1F248; COMMON 0x1F249, // 1F249..1F24F; UNKNOWN 0x1F250, // 1F250..1F251; COMMON - 0x1F252, // 1F252..1F2FF; UNKNOWN - 0x1F300, // 1F300..1F579; COMMON - 0x1F57A, // 1F57A ; UNKNOWN - 0x1F57B, // 1F57B..1F5A3; COMMON - 0x1F5A4, // 1F5A4 ; UNKNOWN - 0x1F5A5, // 1F5A5..1F6D0; COMMON - 0x1F6D1, // 1F6D1..1F6DF; UNKNOWN + 0x1F252, // 1F252..1F25F; UNKNOWN + 0x1F260, // 1F260..1F265; COMMON + 0x1F266, // 1F266..1F2FF; UNKNOWN + 0x1F300, // 1F300..1F6D4; COMMON + 0x1F6D5, // 1F6D5..1F6DF; UNKNOWN 0x1F6E0, // 1F6E0..1F6EC; COMMON 0x1F6ED, // 1F6ED..1F6EF; UNKNOWN - 0x1F6F0, // 1F6F0..1F6F3; COMMON - 0x1F6F4, // 1F6F4..1F6FF; UNKNOWN + 0x1F6F0, // 1F6F0..1F6F8; COMMON + 0x1F6F9, // 1F6F9..1F6FF; UNKNOWN 0x1F700, // 1F700..1F773; COMMON 0x1F774, // 1F774..1F77F; UNKNOWN 0x1F780, // 1F780..1F7D4; COMMON @@ -5780,13 +6117,21 @@ class Character implements java.io.Serializable, Comparable { 0x1F860, // 1F860..1F887; COMMON 0x1F888, // 1F888..1F88F; UNKNOWN 0x1F890, // 1F890..1F8AD; COMMON - 0x1F8AE, // 1F8AE..1F90F; UNKNOWN - 0x1F910, // 1F910..1F918; COMMON - 0x1F919, // 1F919..1F97F; UNKNOWN - 0x1F980, // 1F980..1F984; COMMON - 0x1F985, // 1F985..1F9BF; UNKNOWN + 0x1F8AE, // 1F8AE..1F8FF; UNKNOWN + 0x1F900, // 1F900..1F90B; COMMON + 0x1F90C, // 1F90C..1F90F; UNKNOWN + 0x1F910, // 1F910..1F93E; COMMON + 0x1F93F, // 1F93F ; UNKNOWN + 0x1F940, // 1F940..1F94C; COMMON + 0x1F94D, // 1F94D..1F94F; UNKNOWN + 0x1F950, // 1F950..1F96B; COMMON + 0x1F96C, // 1F96C..1F97F; UNKNOWN + 0x1F980, // 1F980..1F997; COMMON + 0x1F998, // 1F998..1F9BF; UNKNOWN 0x1F9C0, // 1F9C0 ; COMMON - 0x1F9C1, // 1F9C1..1FFFF; UNKNOWN + 0x1F9C1, // 1F9C1..1F9CF; UNKNOWN + 0x1F9D0, // 1F9D0..1F9E6; COMMON + 0x1F9E7, // 1F9E7..1FFFF; UNKNOWN 0x20000, // 20000..2A6D6; HAN 0x2A6D7, // 2A6D7..2A6FF; UNKNOWN 0x2A700, // 2A700..2B734; HAN @@ -5794,7 +6139,9 @@ class Character implements java.io.Serializable, Comparable { 0x2B740, // 2B740..2B81D; HAN 0x2B81E, // 2B81E..2B81F; UNKNOWN 0x2B820, // 2B820..2CEA1; HAN - 0x2CEA2, // 2CEA2..2F7FF; UNKNOWN + 0x2CEA2, // 2CEA2..2CEAF; UNKNOWN + 0x2CEB0, // 2CEB0..2EBE0; HAN + 0x2EBE1, // 2EBE1..2F7FF; UNKNOWN 0x2F800, // 2F800..2FA1D; HAN 0x2FA1E, // 2FA1E..E0000; UNKNOWN 0xE0001, // E0001 ; COMMON @@ -5873,7 +6220,8 @@ class Character implements java.io.Serializable, Comparable { ARABIC, // 0606..060B COMMON, // 060C ARABIC, // 060D..061A - COMMON, // 061B..061C + COMMON, // 061B + ARABIC, // 061C UNKNOWN, // 061D ARABIC, // 061E COMMON, // 061F @@ -5903,9 +6251,15 @@ class Character implements java.io.Serializable, Comparable { MANDAIC, // 0840..085B UNKNOWN, // 085C..085D MANDAIC, // 085E - UNKNOWN, // 085F..089F + UNKNOWN, // 085F + SYRIAC, // 0860..086A + UNKNOWN, // 086B..089F ARABIC, // 08A0..08B4 - UNKNOWN, // 08B5..08E2 + UNKNOWN, // 08B5 + ARABIC, // 08B6..08BD + UNKNOWN, // 08BE..08D3 + ARABIC, // 08D4..08E1 + COMMON, // 08E2 ARABIC, // 08E3..08FF DEVANAGARI, // 0900..0950 INHERITED, // 0951..0952 @@ -5938,8 +6292,8 @@ class Character implements java.io.Serializable, Comparable { UNKNOWN, // 09DE BENGALI, // 09DF..09E3 UNKNOWN, // 09E4..09E5 - BENGALI, // 09E6..09FB - UNKNOWN, // 09FC..0A00 + BENGALI, // 09E6..09FD + UNKNOWN, // 09FE..0A00 GURMUKHI, // 0A01..0A03 UNKNOWN, // 0A04 GURMUKHI, // 0A05..0A0A @@ -5998,8 +6352,8 @@ class Character implements java.io.Serializable, Comparable { UNKNOWN, // 0AE4..0AE5 GUJARATI, // 0AE6..0AF1 UNKNOWN, // 0AF2..0AF8 - GUJARATI, // 0AF9 - UNKNOWN, // 0AFA..0B00 + GUJARATI, // 0AF9..0AFF + UNKNOWN, // 0B00 ORIYA, // 0B01..0B03 UNKNOWN, // 0B04 ORIYA, // 0B05..0B0C @@ -6085,8 +6439,7 @@ class Character implements java.io.Serializable, Comparable { TELUGU, // 0C66..0C6F UNKNOWN, // 0C70..0C77 TELUGU, // 0C78..0C7F - UNKNOWN, // 0C80 - KANNADA, // 0C81..0C83 + KANNADA, // 0C80..0C83 UNKNOWN, // 0C84 KANNADA, // 0C85..0C8C UNKNOWN, // 0C8D @@ -6113,28 +6466,22 @@ class Character implements java.io.Serializable, Comparable { KANNADA, // 0CE6..0CEF UNKNOWN, // 0CF0 KANNADA, // 0CF1..0CF2 - UNKNOWN, // 0CF3..0D00 - MALAYALAM, // 0D01..0D03 + UNKNOWN, // 0CF3..0CFF + MALAYALAM, // 0D00..0D03 UNKNOWN, // 0D04 MALAYALAM, // 0D05..0D0C UNKNOWN, // 0D0D MALAYALAM, // 0D0E..0D10 UNKNOWN, // 0D11 - MALAYALAM, // 0D12..0D3A - UNKNOWN, // 0D3B..0D3C - MALAYALAM, // 0D3D..0D44 + MALAYALAM, // 0D12..0D44 UNKNOWN, // 0D45 MALAYALAM, // 0D46..0D48 UNKNOWN, // 0D49 - MALAYALAM, // 0D4A..0D4E - UNKNOWN, // 0D4F..0D56 - MALAYALAM, // 0D57 - UNKNOWN, // 0D58..0D5E - MALAYALAM, // 0D5F..0D63 + MALAYALAM, // 0D4A..0D4F + UNKNOWN, // 0D50..0D53 + MALAYALAM, // 0D54..0D63 UNKNOWN, // 0D64..0D65 - MALAYALAM, // 0D66..0D75 - UNKNOWN, // 0D76..0D78 - MALAYALAM, // 0D79..0D7F + MALAYALAM, // 0D66..0D7F UNKNOWN, // 0D80..0D81 SINHALA, // 0D82..0D83 UNKNOWN, // 0D84 @@ -6358,7 +6705,8 @@ class Character implements java.io.Serializable, Comparable { UNKNOWN, // 1C4A..1C4C LEPCHA, // 1C4D..1C4F OL_CHIKI, // 1C50..1C7F - UNKNOWN, // 1C80..1CBF + CYRILLIC, // 1C80..1C88 + UNKNOWN, // 1C89..1CBF SUNDANESE, // 1CC0..1CC7 UNKNOWN, // 1CC8..1CCF INHERITED, // 1CD0..1CD2 @@ -6370,8 +6718,7 @@ class Character implements java.io.Serializable, Comparable { INHERITED, // 1CED COMMON, // 1CEE..1CF3 INHERITED, // 1CF4 - COMMON, // 1CF5..1CF6 - UNKNOWN, // 1CF7 + COMMON, // 1CF5..1CF7 INHERITED, // 1CF8..1CF9 UNKNOWN, // 1CFA..1CFF LATIN, // 1D00..1D25 @@ -6385,9 +6732,9 @@ class Character implements java.io.Serializable, Comparable { CYRILLIC, // 1D78 LATIN, // 1D79..1DBE GREEK, // 1DBF - INHERITED, // 1DC0..1DF5 - UNKNOWN, // 1DF6..1DFB - INHERITED, // 1DFC..1DFF + INHERITED, // 1DC0..1DF9 + UNKNOWN, // 1DFA + INHERITED, // 1DFB..1DFF LATIN, // 1E00..1EFF GREEK, // 1F00..1F15 UNKNOWN, // 1F16..1F17 @@ -6434,8 +6781,8 @@ class Character implements java.io.Serializable, Comparable { UNKNOWN, // 208F LATIN, // 2090..209C UNKNOWN, // 209D..209F - COMMON, // 20A0..20BE - UNKNOWN, // 20BF..20CF + COMMON, // 20A0..20BF + UNKNOWN, // 20C0..20CF INHERITED, // 20D0..20F0 UNKNOWN, // 20F1..20FF COMMON, // 2100..2125 @@ -6450,9 +6797,7 @@ class Character implements java.io.Serializable, Comparable { LATIN, // 2160..2188 COMMON, // 2189..218B UNKNOWN, // 218C..218F - COMMON, // 2190..23FA - UNKNOWN, // 23FB..23FF - COMMON, // 2400..2426 + COMMON, // 2190..2426 UNKNOWN, // 2427..243F COMMON, // 2440..244A UNKNOWN, // 244B..245F @@ -6466,8 +6811,8 @@ class Character implements java.io.Serializable, Comparable { UNKNOWN, // 2BBA..2BBC COMMON, // 2BBD..2BC8 UNKNOWN, // 2BC9 - COMMON, // 2BCA..2BD1 - UNKNOWN, // 2BD2..2BEB + COMMON, // 2BCA..2BD2 + UNKNOWN, // 2BD3..2BEB COMMON, // 2BEC..2BEF UNKNOWN, // 2BF0..2BFF GLAGOLITIC, // 2C00..2C2E @@ -6508,8 +6853,8 @@ class Character implements java.io.Serializable, Comparable { ETHIOPIC, // 2DD8..2DDE UNKNOWN, // 2DDF CYRILLIC, // 2DE0..2DFF - COMMON, // 2E00..2E42 - UNKNOWN, // 2E43..2E7F + COMMON, // 2E00..2E49 + UNKNOWN, // 2E50..2E7F HAN, // 2E80..2E99 UNKNOWN, // 2E9A HAN, // 2E9B..2EF3 @@ -6540,8 +6885,8 @@ class Character implements java.io.Serializable, Comparable { COMMON, // 30FB..30FC KATAKANA, // 30FD..30FF UNKNOWN, // 3100..3104 - BOPOMOFO, // 3105..312D - UNKNOWN, // 312E..3130 + BOPOMOFO, // 3105..312E + UNKNOWN, // 312F..3130 HANGUL, // 3131..318E UNKNOWN, // 318F COMMON, // 3190..319F @@ -6562,8 +6907,8 @@ class Character implements java.io.Serializable, Comparable { HAN, // 3400..4DB5 UNKNOWN, // 4DB6..4DBF COMMON, // 4DC0..4DFF - HAN, // 4E00..9FD5 - UNKNOWN, // 9FD6..9FFF + HAN, // 4E00..9FEA + UNKNOWN, // 9FEB..9FFF YI, // A000..A48C UNKNOWN, // A48D..A48F YI, // A490..A4C6 @@ -6577,8 +6922,8 @@ class Character implements java.io.Serializable, Comparable { COMMON, // A700..A721 LATIN, // A722..A787 COMMON, // A788..A78A - LATIN, // A78B..A7AD - UNKNOWN, // A7AE..A7AF + LATIN, // A78B..A7AE + UNKNOWN, // A7AF LATIN, // A7B0..A7B7 UNKNOWN, // A7B8..A7F6 LATIN, // A7F7..A7FF @@ -6588,8 +6933,8 @@ class Character implements java.io.Serializable, Comparable { UNKNOWN, // A83A..A83F PHAGS_PA, // A840..A877 UNKNOWN, // A878..A87F - SAURASHTRA, // A880..A8C4 - UNKNOWN, // A8C5..A8CD + SAURASHTRA, // A880..A8C5 + UNKNOWN, // A8C6..A8CD SAURASHTRA, // A8CE..A8D9 UNKNOWN, // A8DA..A8DF DEVANAGARI, // A8E0..A8FD @@ -6740,8 +7085,8 @@ class Character implements java.io.Serializable, Comparable { COMMON, // 10107..10133 UNKNOWN, // 10134..10136 COMMON, // 10137..1013F - GREEK, // 10140..1018C - UNKNOWN, // 1018D..1018F + GREEK, // 10140..1018E + UNKNOWN, // 1018F COMMON, // 10190..1019B UNKNOWN, // 1019C..1019F GREEK, // 101A0 @@ -6757,7 +7102,8 @@ class Character implements java.io.Serializable, Comparable { COMMON, // 102E1..102FB UNKNOWN, // 102FC..102FF OLD_ITALIC, // 10300..10323 - UNKNOWN, // 10324..1032F + UNKNOWN, // 10324..1032C + OLD_ITALIC, // 1032D..1032F GOTHIC, // 10330..1034A UNKNOWN, // 1034B..1034F OLD_PERMIC, // 10350..1037A @@ -6774,7 +7120,11 @@ class Character implements java.io.Serializable, Comparable { OSMANYA, // 10480..1049D UNKNOWN, // 1049E..1049F OSMANYA, // 104A0..104A9 - UNKNOWN, // 104AA..104FF + UNKNOWN, // 104AA..104AF + OSAGE, // 104B0..104D3; + UNKNOWN, // 104D4..104D7; + OSAGE, // 104D8..104FB; + UNKNOWN, // 104FC..104FF; ELBASAN, // 10500..10527 UNKNOWN, // 10528..1052F CAUCASIAN_ALBANIAN, // 10530..10563 @@ -6897,8 +7247,8 @@ class Character implements java.io.Serializable, Comparable { UNKNOWN, // 111F5..111FF KHOJKI, // 11200..11211 UNKNOWN, // 11212 - KHOJKI, // 11213..1123D - UNKNOWN, // 1123E..1127F + KHOJKI, // 11213..1123E + UNKNOWN, // 1123F..1127F MULTANI, // 11280..11286 UNKNOWN, // 11287 MULTANI, // 11288 @@ -6942,7 +7292,13 @@ class Character implements java.io.Serializable, Comparable { GRANTHA, // 11366..1136C UNKNOWN, // 1136D..1136F GRANTHA, // 11370..11374 - UNKNOWN, // 11375..1147F + UNKNOWN, // 11375..113FF + NEWA, // 11400..11459 + UNKNOWN, // 1145A + NEWA, // 1145B + UNKNOWN, // 1145C + NEWA, // 1145D + UNKNOWN, // 1145E..1147F TIRHUTA, // 11480..114C7 UNKNOWN, // 114C8..114CF TIRHUTA, // 114D0..114D9 @@ -6954,7 +7310,9 @@ class Character implements java.io.Serializable, Comparable { MODI, // 11600..11644 UNKNOWN, // 11645..1164F MODI, // 11650..11659 - UNKNOWN, // 1165A..1167F + UNKNOWN, // 1165A..1165F + MONGOLIAN, // 11660..1166C + UNKNOWN, // 1166D..1167F TAKRI, // 11680..116B7 UNKNOWN, // 116B8..116BF TAKRI, // 116C0..116C9 @@ -6968,9 +7326,45 @@ class Character implements java.io.Serializable, Comparable { WARANG_CITI, // 118A0..118F2 UNKNOWN, // 118F3..118FE WARANG_CITI, // 118FF - UNKNOWN, // 11900..11ABF + UNKNOWN, // 11900..119FF + ZANABAZAR_SQUARE, // 11A00..11A47 + UNKNOWN, // 11A48..11A4F + SOYOMBO, // 11A50..11A83 + UNKNOWN, // 11A84..11A85 + SOYOMBO, // 11A86..11A9C + UNKNOWN, // 11A9D + SOYOMBO, // 11A9E..11AA2 + UNKNOWN, // 11AA3..11ABF PAU_CIN_HAU, // 11AC0..11AF8 - UNKNOWN, // 11AF9..11FFF + UNKNOWN, // 11AF9..11BFF + BHAIKSUKI, // 11C00..11C08 + UNKNOWN, // 11C09 + BHAIKSUKI, // 11C0A..11C36 + UNKNOWN, // 11C37 + BHAIKSUKI, // 11C38..11C45 + UNKNOWN, // 11C46..11C49 + BHAIKSUKI, // 11C50..11C6C + UNKNOWN, // 11C6D..11C6F + MARCHEN, // 11C70..11C8F + UNKNOWN, // 11C90..11C91 + MARCHEN, // 11C92..11CA7 + UNKNOWN, // 11CA8 + MARCHEN, // 11CA9..11CB6 + UNKNOWN, // 11CB7..11CFF + MASARAM_GONDI, // 11D00..11D06 + UNKNOWN, // 11D07 + MASARAM_GONDI, // 11D08..11D09 + UNKNOWN, // 11D0A + MASARAM_GONDI, // 11D0B..11D36 + UNKNOWN, // 11D37..11D39 + MASARAM_GONDI, // 11D3A + UNKNOWN, // 11D3B + MASARAM_GONDI, // 11D3C..11D3D + UNKNOWN, // 11D3E + MASARAM_GONDI, // 11D3F..11D47 + UNKNOWN, // 11D48..11D49 + MASARAM_GONDI, // 11D50..11D59 + UNKNOWN, // 11D5A..1AFFF; CUNEIFORM, // 12000..12399 UNKNOWN, // 1239A..123FF CUNEIFORM, // 12400..1246E @@ -7010,10 +7404,19 @@ class Character implements java.io.Serializable, Comparable { MIAO, // 16F50..16F7E UNKNOWN, // 16F7F..16F8E MIAO, // 16F8F..16F9F - UNKNOWN, // 16FA0..1AFFF + UNKNOWN, // 16FA0..16FDF + TANGUT, // 16FE0 + NUSHU, // 16FE1 + UNKNOWN, // 16FE2..16FFF + TANGUT, // 17000..187EC + UNKNOWN, // 187ED..187FF + TANGUT, // 18800..18AF2 + UNKNOWN, // 18AF3..1AFFF KATAKANA, // 1B000 - HIRAGANA, // 1B001 - UNKNOWN, // 1B002..1BBFF + HIRAGANA, // 1B001..1B11E + UNKNOWN, // 1B11F..1B16F + NUSHU, // 1B170..1B2FB + UNKNOWN, // 1B2FC..1BBFF DUPLOYAN, // 1BC00..1BC6A UNKNOWN, // 1BC6B..1BC6F DUPLOYAN, // 1BC70..1BC7C @@ -7091,11 +7494,27 @@ class Character implements java.io.Serializable, Comparable { SIGNWRITING, // 1DA9B..1DA9F UNKNOWN, // 1DAA0 SIGNWRITING, // 1DAA1..1DAAF - UNKNOWN, // 1DAB0..1E7FF + UNKNOWN, // 1DAB0..1DFFF + GLAGOLITIC, // 1E000..1E006 + UNKNOWN, // 1E007 + GLAGOLITIC, // 1E008..1E018 + UNKNOWN, // 1E019..1E01A + GLAGOLITIC, // 1E01B..1E021 + UNKNOWN, // 1E022 + GLAGOLITIC, // 1E023..1E024 + UNKNOWN, // 1E025 + GLAGOLITIC, // 1E026..1E02A + UNKNOWN, // 1E02B..1E7FF MENDE_KIKAKUI, // 1E800..1E8C4 UNKNOWN, // 1E8C5..1E8C6 MENDE_KIKAKUI, // 1E8C7..1E8D6 - UNKNOWN, // 1E8D7..1EDFF + UNKNOWN, // 1E8D7..1E8FF + ADLAM, // 1E900..1E94A + UNKNOWN, // 1E94B..1E94F + ADLAM, // 1E950..1E959 + UNKNOWN, // 1E95A..1E95D + ADLAM, // 1E95E..1E95F + UNKNOWN, // 1E960..1EDFF ARABIC, // 1EE00..1EE03 UNKNOWN, // 1EE04 ARABIC, // 1EE05..1EE1F @@ -7182,28 +7601,26 @@ class Character implements java.io.Serializable, Comparable { UNKNOWN, // 1F12F COMMON, // 1F130..1F16B UNKNOWN, // 1F16C..1F16F - COMMON, // 1F170..1F19A - UNKNOWN, // 1F19B..1F1E5 + COMMON, // 1F170..1F1AC + UNKNOWN, // 1F1AD..1F1E5 COMMON, // 1F1E6..1F1FF HIRAGANA, // 1F200 COMMON, // 1F201..1F202 UNKNOWN, // 1F203..1F20F - COMMON, // 1F210..1F23A - UNKNOWN, // 1F23B..1F23F + COMMON, // 1F210..1F23B + UNKNOWN, // 1F23C..1F23F COMMON, // 1F240..1F248 UNKNOWN, // 1F249..1F24F COMMON, // 1F250..1F251 - UNKNOWN, // 1F252..1F2FF - COMMON, // 1F300..1F579 - UNKNOWN, // 1F57A - COMMON, // 1F57B..1F5A3 - UNKNOWN, // 1F5A4 - COMMON, // 1F5A5..1F6D0 - UNKNOWN, // 1F6D1..1F6DF + UNKNOWN, // 1F252..1F25F + COMMON, // 1F260..1F265 + UNKNOWN, // 1F266..1F2FF + COMMON, // 1F300..1F6D4 + UNKNOWN, // 1F6D5..1F6DF COMMON, // 1F6E0..1F6EC UNKNOWN, // 1F6ED..1F6EF - COMMON, // 1F6F0..1F6F3 - UNKNOWN, // 1F6F4..1F6FF + COMMON, // 1F6F0..1F6F8 + UNKNOWN, // 1F6F9..1F6FF COMMON, // 1F700..1F773 UNKNOWN, // 1F774..1F77F COMMON, // 1F780..1F7D4 @@ -7217,13 +7634,21 @@ class Character implements java.io.Serializable, Comparable { COMMON, // 1F860..1F887 UNKNOWN, // 1F888..1F88F COMMON, // 1F890..1F8AD - UNKNOWN, // 1F8AE..1F90F - COMMON, // 1F910..1F918 - UNKNOWN, // 1F919..1F97F - COMMON, // 1F980..1F984 - UNKNOWN, // 1F985..1F9BF + UNKNOWN, // 1F8AE..1F8FF + COMMON, // 1F900..1F90B + UNKNOWN, // 1F90C..1F90F + COMMON, // 1F910..1F93E + UNKNOWN, // 1F93F + COMMON, // 1F940..1F94C + UNKNOWN, // 1F94D..1F94F + COMMON, // 1F950..1F96B + UNKNOWN, // 1F96C..1F97F + COMMON, // 1F980..1F997 + UNKNOWN, // 1F998..1F9BF COMMON, // 1F9C0 - UNKNOWN, // 1F9C1..1FFFF + UNKNOWN, // 1F9C1..1F9CF + COMMON, // 1F9D0..1F9E6 + UNKNOWN, // 1F9E7..1FFFF HAN, // 20000..2A6D6 UNKNOWN, // 2A6D7..2A6FF HAN, // 2A700..2B734 @@ -7231,7 +7656,9 @@ class Character implements java.io.Serializable, Comparable { HAN, // 2B740..2B81D UNKNOWN, // 2B81E..2B81F HAN, // 2B820..2CEA1 - UNKNOWN, // 2CEA2..2F7FF + UNKNOWN, // 2CEA2..2CEAF + HAN, // 2CEB0..2EBE0 + UNKNOWN, // 2EBE1..2F7FF HAN, // 2F800..2FA1D UNKNOWN, // 2FA1E..E0000 COMMON, // E0001 @@ -7244,7 +7671,8 @@ class Character implements java.io.Serializable, Comparable { private static HashMap aliases; static { - aliases = new HashMap<>(134); + aliases = new HashMap<>((int)(142 / 0.75f + 1.0f)); + aliases.put("ADLM", ADLAM); aliases.put("AGHB", CAUCASIAN_ALBANIAN); aliases.put("AHOM", AHOM); aliases.put("ARAB", ARABIC); @@ -7256,6 +7684,7 @@ class Character implements java.io.Serializable, Comparable { aliases.put("BASS", BASSA_VAH); aliases.put("BATK", BATAK); aliases.put("BENG", BENGALI); + aliases.put("BHKS", BHAIKSUKI); aliases.put("BOPO", BOPOMOFO); aliases.put("BRAH", BRAHMI); aliases.put("BRAI", BRAILLE); @@ -7277,6 +7706,7 @@ class Character implements java.io.Serializable, Comparable { aliases.put("ETHI", ETHIOPIC); aliases.put("GEOR", GEORGIAN); aliases.put("GLAG", GLAGOLITIC); + aliases.put("GONM", MASARAM_GONDI); aliases.put("GOTH", GOTHIC); aliases.put("GRAN", GRANTHA); aliases.put("GREK", GREEK); @@ -7313,6 +7743,7 @@ class Character implements java.io.Serializable, Comparable { aliases.put("LYCI", LYCIAN); aliases.put("LYDI", LYDIAN); aliases.put("MAHJ", MAHAJANI); + aliases.put("MARC", MARCHEN); aliases.put("MAND", MANDAIC); aliases.put("MANI", MANICHAEAN); aliases.put("MEND", MENDE_KIKAKUI); @@ -7327,11 +7758,14 @@ class Character implements java.io.Serializable, Comparable { aliases.put("MYMR", MYANMAR); aliases.put("NARB", OLD_NORTH_ARABIAN); aliases.put("NBAT", NABATAEAN); + aliases.put("NEWA", NEWA); aliases.put("NKOO", NKO); + aliases.put("NSHU", NUSHU); aliases.put("OGAM", OGHAM); aliases.put("OLCK", OL_CHIKI); aliases.put("ORKH", OLD_TURKIC); aliases.put("ORYA", ORIYA); + aliases.put("OSGE", OSAGE); aliases.put("OSMA", OSMANYA); aliases.put("PALM", PALMYRENE); aliases.put("PAUC", PAU_CIN_HAU); @@ -7354,6 +7788,7 @@ class Character implements java.io.Serializable, Comparable { aliases.put("SIND", KHUDAWADI); aliases.put("SINH", SINHALA); aliases.put("SORA", SORA_SOMPENG); + aliases.put("SOYO", SOYOMBO); aliases.put("SUND", SUNDANESE); aliases.put("SYLO", SYLOTI_NAGRI); aliases.put("SYRC", SYRIAC); @@ -7362,6 +7797,7 @@ class Character implements java.io.Serializable, Comparable { aliases.put("TALE", TAI_LE); aliases.put("TALU", NEW_TAI_LUE); aliases.put("TAML", TAMIL); + aliases.put("TANG", TANGUT); aliases.put("TAVT", TAI_VIET); aliases.put("TELU", TELUGU); aliases.put("TFNG", TIFINAGH); @@ -7376,6 +7812,7 @@ class Character implements java.io.Serializable, Comparable { aliases.put("XPEO", OLD_PERSIAN); aliases.put("XSUX", CUNEIFORM); aliases.put("YIII", YI); + aliases.put("ZANB", ZANABAZAR_SQUARE); aliases.put("ZINH", INHERITED); aliases.put("ZYYY", COMMON); aliases.put("ZZZZ", UNKNOWN); diff --git a/src/java.base/share/classes/sun/text/normalizer/ICUBinary.java b/src/java.base/share/classes/sun/text/normalizer/ICUBinary.java index 9ba029c5d41..b9650bd7cba 100644 --- a/src/java.base/share/classes/sun/text/normalizer/ICUBinary.java +++ b/src/java.base/share/classes/sun/text/normalizer/ICUBinary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -34,16 +34,11 @@ package sun.text.normalizer; import java.io.BufferedInputStream; import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; import java.io.InputStream; import java.io.IOException; import java.io.UncheckedIOException; -import java.net.URL; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.nio.file.FileSystems; import java.util.Arrays; import java.security.AccessController; import java.security.PrivilegedAction; @@ -51,7 +46,7 @@ import java.security.PrivilegedAction; public final class ICUBinary { private static final class IsAcceptable implements Authenticate { - // @Override when we switch to Java 6 + @Override public boolean isDataVersionAcceptable(byte version[]) { return version[0] == 1; } @@ -93,7 +88,7 @@ public final class ICUBinary { BufferedInputStream b=new BufferedInputStream(is, 4096 /* data buffer size */); DataInputStream inputStream = new DataInputStream(b); - byte[] bb = new byte[120000]; + byte[] bb = new byte[130000]; int n = inputStream.read(bb); ByteBuffer bytes = ByteBuffer.wrap(bb, 0, n); return bytes; diff --git a/src/java.base/share/classes/sun/text/normalizer/Norm2AllModes.java b/src/java.base/share/classes/sun/text/normalizer/Norm2AllModes.java index 5f64fb2c8f3..407a1a2a1a9 100644 --- a/src/java.base/share/classes/sun/text/normalizer/Norm2AllModes.java +++ b/src/java.base/share/classes/sun/text/normalizer/Norm2AllModes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018 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 @@ -194,7 +194,7 @@ final class Norm2AllModes { } @Override - public boolean hasBoundaryBefore(int c) { return impl.hasDecompBoundary(c, true); } + public boolean hasBoundaryBefore(int c) { return impl.hasDecompBoundaryBefore(c); } } public static final class ComposeNormalizer2 extends Normalizer2WithImpl { diff --git a/src/java.base/share/classes/sun/text/normalizer/Normalizer2.java b/src/java.base/share/classes/sun/text/normalizer/Normalizer2.java index f2f31d73d19..56e474976e6 100644 --- a/src/java.base/share/classes/sun/text/normalizer/Normalizer2.java +++ b/src/java.base/share/classes/sun/text/normalizer/Normalizer2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018 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 @@ -135,8 +135,10 @@ abstract class Normalizer2 { if(spanLength==src.length()) { return (String)src; } - StringBuilder sb=new StringBuilder(src.length()).append(src, 0, spanLength); - return normalizeSecondAndAppend(sb, src.subSequence(spanLength, src.length())).toString(); + if (spanLength != 0) { + StringBuilder sb=new StringBuilder(src.length()).append(src, 0, spanLength); + return normalizeSecondAndAppend(sb, src.subSequence(spanLength, src.length())).toString(); + } } return normalize(src, new StringBuilder(src.length())).toString(); } diff --git a/src/java.base/share/classes/sun/text/normalizer/NormalizerImpl.java b/src/java.base/share/classes/sun/text/normalizer/NormalizerImpl.java index e00a7f9af5f..294f83a1e78 100644 --- a/src/java.base/share/classes/sun/text/normalizer/NormalizerImpl.java +++ b/src/java.base/share/classes/sun/text/normalizer/NormalizerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2018, 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 @@ -29,7 +29,6 @@ * Corporation and others. All Rights Reserved. ******************************************************************************* */ - package sun.text.normalizer; import java.io.IOException; @@ -38,7 +37,6 @@ import java.text.Normalizer; // Original filename in ICU4J: Normalizer2Impl.java public final class NormalizerImpl { - public static final class Hangul { /* Korean Hangul and Jamo constants */ public static final int JAMO_L_BASE=0x1100; /* "lead" jamo */ @@ -58,13 +56,12 @@ public final class NormalizerImpl { public static boolean isHangul(int c) { return HANGUL_BASE<=c && c>DELTA_SHIFT)-MAX_DELTA-1; // Read the normTrie. int offset=inIndexes[IX_NORM_TRIE_OFFSET]; @@ -407,7 +390,7 @@ public final class NormalizerImpl { normTrie=Trie2_16.createFromSerialized(bytes); int trieLength=normTrie.getSerializedLength(); if(trieLength>(nextOffset-offset)) { - throw new IOException("Normalizer2 data: not enough bytes for normTrie"); + throw new InternalError("Normalizer2 data: not enough bytes for normTrie"); } ICUBinary.skipBytes(bytes, (nextOffset-offset)-trieLength); // skip padding after trie bytes @@ -422,61 +405,47 @@ public final class NormalizerImpl { chars[i]=bytes.getChar(); } maybeYesCompositions=new String(chars); - extraData=maybeYesCompositions.substring(MIN_NORMAL_MAYBE_YES-minMaybeYes); + extraData=maybeYesCompositions.substring((MIN_NORMAL_MAYBE_YES-minMaybeYes)>>OFFSET_SHIFT); } // smallFCD: new in formatVersion 2 offset=nextOffset; smallFCD=new byte[0x100]; - for(int i=0; i<0x100; ++i) { - smallFCD[i]=bytes.get(); - } - - // Build tccc180[]. - // gennorm2 enforces lccc=0 for c>=1) { - if((c&0xff)==0) { - bits=smallFCD[c>>8]; // one byte per 0x100 code points - } - if((bits&1)!=0) { - for(int i=0; i<0x20; ++i, ++c) { - tccc180[c]=getFCD16FromNormData(c)&0xff; - } - } else { - c+=0x20; - } - } + bytes.get(smallFCD); return this; } catch(IOException e) { throw new InternalError(e); } } - public NormalizerImpl load(String name) { return load(ICUBinary.getRequiredData(name)); } - public int getNorm16(int c) { - return normTrie.get(c); - } + public int getNorm16(int c) { return normTrie.get(c); } + public boolean isAlgorithmicNoNo(int norm16) { return limitNoNo<=norm16 && norm16=MIN_NORMAL_MAYBE_YES) { - return norm16&0xff; + return getCCFromNormalYesOrMaybe(norm16); } if(norm16> OFFSET_SHIFT) & 0xff; + } public static int getCCFromYesOrMaybe(int norm16) { - return norm16>=MIN_NORMAL_MAYBE_YES ? norm16&0xff : 0; + return norm16>=MIN_NORMAL_MAYBE_YES ? getCCFromNormalYesOrMaybe(norm16) : 0; + } + public int getCCFromYesOrMaybeCP(int c) { + if (c < minCompNoMaybeCP) { return 0; } + return getCCFromYesOrMaybe(getNorm16(c)); } /** @@ -485,18 +454,13 @@ public final class NormalizerImpl { * @return The lccc(c) in bits 15..8 and tccc(c) in bits 7..0. */ public int getFCD16(int c) { - if(c<0) { + if(c=MIN_NORMAL_MAYBE_YES) { + int norm16=getNorm16(c); + if (norm16 >= limitNoNo) { + if(norm16>=MIN_NORMAL_MAYBE_YES) { // combining mark - norm16&=0xff; + norm16=getCCFromNormalYesOrMaybe(norm16); return norm16|(norm16<<8); } else if(norm16>=minMaybeYes) { return 0; - } else if(isDecompNoAlgorithmic(norm16)) { - c=mapAlgorithmic(c, norm16); - } else { - // c decomposes, get everything from the variable-length extra data - int firstUnit=extraData.charAt(norm16); - if((firstUnit&MAPPING_LENGTH_MASK)==0) { - // A character that is deleted (maps to an empty string) must - // get the worst-case lccc and tccc values because arbitrary - // characters on both sides will become adjacent. - return 0x1ff; - } else { - int fcd16=firstUnit>>8; // tccc - if((firstUnit&MAPPING_HAS_CCC_LCCC_WORD)!=0) { - fcd16|=extraData.charAt(norm16-1)&0xff00; // lccc - } - return fcd16; + } else { // isDecompNoAlgorithmic(norm16) + int deltaTrailCC = norm16 & DELTA_TCCC_MASK; + if (deltaTrailCC <= DELTA_TCCC_1) { + return deltaTrailCC >> OFFSET_SHIFT; } + // Maps to an isCompYesAndZeroCC. + c=mapAlgorithmic(c, norm16); + norm16=getNorm16(c); } } + if(norm16<=minYesNo || isHangulLVT(norm16)) { + // no decomposition or Hangul syllable, all zeros + return 0; + } + // c decomposes, get everything from the variable-length extra data + int mapping=norm16>>OFFSET_SHIFT; + int firstUnit=extraData.charAt(mapping); + int fcd16=firstUnit>>8; // tccc + if((firstUnit&MAPPING_HAS_CCC_LCCC_WORD)!=0) { + fcd16|=extraData.charAt(mapping-1)&0xff00; // lccc + } + return fcd16; } /** @@ -546,59 +509,92 @@ public final class NormalizerImpl { * @return c's decomposition, if it has one; returns null if it does not have a decomposition */ public String getDecomposition(int c) { - int decomp=-1; int norm16; - for(;;) { - if(c>OFFSET_SHIFT; + int length=extraData.charAt(mapping++)&MAPPING_LENGTH_MASK; + return extraData.substring(mapping, mapping+length); } - public static final int MIN_CCC_LCCC_CP=0x300; + // Fixed norm16 values. + public static final int MIN_YES_YES_WITH_CC=0xfe02; + public static final int JAMO_VT=0xfe00; + public static final int MIN_NORMAL_MAYBE_YES=0xfc00; + public static final int JAMO_L=2; // offset=1 hasCompBoundaryAfter=FALSE + public static final int INERT=1; // offset=0 hasCompBoundaryAfter=TRUE + + // norm16 bit 0 is comp-boundary-after. + public static final int HAS_COMP_BOUNDARY_AFTER=1; + public static final int OFFSET_SHIFT=1; + + // For algorithmic one-way mappings, norm16 bits 2..1 indicate the + // tccc (0, 1, >1) for quick FCC boundary-after tests. + public static final int DELTA_TCCC_0=0; + public static final int DELTA_TCCC_1=2; + public static final int DELTA_TCCC_GT_1=4; + public static final int DELTA_TCCC_MASK=6; + public static final int DELTA_SHIFT=3; - public static final int MIN_YES_YES_WITH_CC=0xff01; - public static final int JAMO_VT=0xff00; - public static final int MIN_NORMAL_MAYBE_YES=0xfe00; public static final int MAX_DELTA=0x40; // Byte offsets from the start of the data, after the generic header. public static final int IX_NORM_TRIE_OFFSET=0; public static final int IX_EXTRA_DATA_OFFSET=1; public static final int IX_SMALL_FCD_OFFSET=2; - + public static final int IX_RESERVED3_OFFSET=3; + public static final int IX_TOTAL_SIZE=7; + public static final int MIN_CCC_LCCC_CP=0x300; // Code point thresholds for quick check codes. public static final int IX_MIN_DECOMP_NO_CP=8; public static final int IX_MIN_COMP_NO_MAYBE_CP=9; // Norm16 value thresholds for quick check combinations and types of extra data. - // Mappings & compositions in [minYesNo..minYesNoMappingsOnly[. + + /** Mappings & compositions in [minYesNo..minYesNoMappingsOnly[. */ public static final int IX_MIN_YES_NO=10; + /** Mappings are comp-normalized. */ public static final int IX_MIN_NO_NO=11; public static final int IX_LIMIT_NO_NO=12; public static final int IX_MIN_MAYBE_YES=13; - // Mappings only in [minYesNoMappingsOnly..minNoNo[. + /** Mappings only in [minYesNoMappingsOnly..minNoNo[. */ public static final int IX_MIN_YES_NO_MAPPINGS_ONLY=14; + /** Mappings are not comp-normalized but have a comp boundary before. */ + public static final int IX_MIN_NO_NO_COMP_BOUNDARY_BEFORE=15; + /** Mappings do not have a comp boundary before. */ + public static final int IX_MIN_NO_NO_COMP_NO_MAYBE_CC=16; + /** Mappings to the empty string. */ + public static final int IX_MIN_NO_NO_EMPTY=17; + + public static final int IX_MIN_LCCC_CP=18; + public static final int IX_COUNT=20; public static final int MAPPING_HAS_CCC_LCCC_WORD=0x80; + public static final int MAPPING_HAS_RAW_MAPPING=0x40; + // unused bit 0x20; public static final int MAPPING_LENGTH_MASK=0x1f; public static final int COMP_1_LAST_TUPLE=0x8000; @@ -702,7 +698,6 @@ public final class NormalizerImpl { } return src; } - public void decomposeAndAppend(CharSequence s, boolean doDecompose, ReorderingBuffer buffer) { int limit=s.length(); if(limit==0) { @@ -737,240 +732,238 @@ public final class NormalizerImpl { boolean onlyContiguous, boolean doCompose, ReorderingBuffer buffer) { + int prevBoundary=src; int minNoMaybeCP=minCompNoMaybeCP; - /* - * prevBoundary points to the last character before the current one - * that has a composition boundary before it with ccc==0 and quick check "yes". - * Keeping track of prevBoundary saves us looking for a composition boundary - * when we find a "no" or "maybe". - * - * When we back out from prevSrc back to prevBoundary, - * then we also remove those same characters (which had been simply copied - * or canonically-order-inserted) from the ReorderingBuffer. - * Therefore, at all times, the [prevBoundary..prevSrc[ source units - * must correspond 1:1 to destination units at the end of the destination buffer. - */ - int prevBoundary=src; - int prevSrc; - int c=0; - int norm16=0; - - // only for isNormalized - int prevCC=0; - - for(;;) { - // count code units below the minimum or with irrelevant data for the quick check - for(prevSrc=src; src!=limit;) { + for (;;) { + // Fast path: Scan over a sequence of characters below the minimum "no or maybe" code point, + // or with (compYes && ccc==0) properties. + int prevSrc; + int c = 0; + int norm16 = 0; + for (;;) { + if (src == limit) { + if (prevBoundary != limit && doCompose) { + buffer.append(s, prevBoundary, limit); + } + return true; + } if( (c=s.charAt(src))=minNoNo. + // The current character is either a "noNo" (has a mapping) + // or a "maybeYes" (combines backward) + // or a "yesYes" with ccc!=0. + // It is not a Hangul syllable or Jamo L because those have "yes" properties. - src+=Character.charCount(c); - /* - * isCompYesAndZeroCC(norm16) is false, that is, norm16>=minNoNo. - * c is either a "noNo" (has a mapping) or a "maybeYes" (combines backward) - * or has ccc!=0. - * Check for Jamo V/T, then for regular characters. - * c is not a Hangul syllable or Jamo L because those have "yes" properties. - */ - if(isJamoVT(norm16) && prevBoundary!=prevSrc) { + // Medium-fast path: Handle cases that do not require full decomposition and recomposition. + if (!isMaybeOrNonZeroCC(norm16)) { // minNoNo <= norm16 < minMaybeYes + if (!doCompose) { + return false; + } + // Fast path for mapping a character that is immediately surrounded by boundaries. + // In this case, we need not decompose around the current character. + if (isDecompNoAlgorithmic(norm16)) { + // Maps to a single isCompYesAndZeroCC character + // which also implies hasCompBoundaryBefore. + if (norm16HasCompBoundaryAfter(norm16, onlyContiguous) || + hasCompBoundaryBefore(s, src, limit)) { + if (prevBoundary != prevSrc) { + buffer.append(s, prevBoundary, prevSrc); + } + buffer.append(mapAlgorithmic(c, norm16), 0); + prevBoundary = src; + continue; + } + } else if (norm16 < minNoNoCompBoundaryBefore) { + // The mapping is comp-normalized which also implies hasCompBoundaryBefore. + if (norm16HasCompBoundaryAfter(norm16, onlyContiguous) || + hasCompBoundaryBefore(s, src, limit)) { + if (prevBoundary != prevSrc) { + buffer.append(s, prevBoundary, prevSrc); + } + int mapping = norm16 >> OFFSET_SHIFT; + int length = extraData.charAt(mapping++) & MAPPING_LENGTH_MASK; + buffer.append(extraData, mapping, mapping + length); + prevBoundary = src; + continue; + } + } else if (norm16 >= minNoNoEmpty) { + // The current character maps to nothing. + // Simply omit it from the output if there is a boundary before _or_ after it. + // The character itself implies no boundaries. + if (hasCompBoundaryBefore(s, src, limit) || + hasCompBoundaryAfter(s, prevBoundary, prevSrc, onlyContiguous)) { + if (prevBoundary != prevSrc) { + buffer.append(s, prevBoundary, prevSrc); + } + prevBoundary = src; + continue; + } + } + // Other "noNo" type, or need to examine more text around this character: + // Fall through to the slow path. + } else if (isJamoVT(norm16) && prevBoundary != prevSrc) { char prev=s.charAt(prevSrc-1); - boolean needToDecompose=false; if(c= 0) { + int syllable = Hangul.HANGUL_BASE + + (l*Hangul.JAMO_V_COUNT + (c-Hangul.JAMO_V_BASE)) * + Hangul.JAMO_T_COUNT + t; + --prevSrc; // Replace the Jamo L as well. + if (prevBoundary != prevSrc) { + buffer.append(s, prevBoundary, prevSrc); + } + buffer.append((char)syllable); + prevBoundary = src; continue; } // If we see L+V+x where x!=T then we drop to the slow path, // decompose and recompose. // This is to deal with NFKC finding normal L and V but a - // compatibility variant of a T. We need to either fully compose that - // combination here (which would complicate the code and may not work - // with strange custom data) or use the slow path -- or else our replacing - // two input characters (L+V) with one output character (LV syllable) - // would violate the invariant that [prevBoundary..prevSrc[ has the same - // length as what we appended to the buffer since prevBoundary. - needToDecompose=true; + // compatibility variant of a T. + // We need to either fully compose that combination here + // (which would complicate the code and may not work with strange custom data) + // or use the slow path. } - } else if(Hangul.isHangulWithoutJamoT(prev)) { - // c is a Jamo Trailing consonant, + } else if (Hangul.isHangulLV(prev)) { + // The current character is a Jamo Trailing consonant, // compose with previous Hangul LV that does not contain a Jamo T. - if(!doCompose) { + if (!doCompose) { return false; } - buffer.setLastChar((char)(prev+c-Hangul.JAMO_T_BASE)); - prevBoundary=src; - continue; - } - if(!needToDecompose) { - // The Jamo V/T did not compose into a Hangul syllable. - if(doCompose) { - buffer.append((char)c); - } else { - prevCC=0; + int syllable = prev + c - Hangul.JAMO_T_BASE; + --prevSrc; // Replace the Hangul LV as well. + if (prevBoundary != prevSrc) { + buffer.append(s, prevBoundary, prevSrc); } + buffer.append((char)syllable); + prevBoundary = src; continue; } - } - /* - * Source buffer pointers: - * - * all done quick check current char not yet - * "yes" but (c) processed - * may combine - * forward - * [-------------[-------------[-------------[-------------[ - * | | | | | - * orig. src prevBoundary prevSrc src limit - * - * - * Destination buffer pointers inside the ReorderingBuffer: - * - * all done might take not filled yet - * characters for - * reordering - * [-------------[-------------[-------------[ - * | | | | - * start reorderStart limit | - * +remainingCap.+ - */ - if(norm16>=MIN_YES_YES_WITH_CC) { - int cc=norm16&0xff; // cc!=0 - if( onlyContiguous && // FCC - (doCompose ? buffer.getLastCC() : prevCC)==0 && - prevBoundarycc - ) { + // No matching context, or may need to decompose surrounding text first: + // Fall through to the slow path. + } else if (norm16 > JAMO_VT) { // norm16 >= MIN_YES_YES_WITH_CC + // One or more combining marks that do not combine-back: + // Check for canonical order, copy unchanged if ok and + // if followed by a character with a boundary-before. + int cc = getCCFromNormalYesOrMaybe(norm16); // cc!=0 + if (onlyContiguous /* FCC */ && getPreviousTrailCC(s, prevBoundary, prevSrc) > cc) { // Fails FCD test, need to decompose and contiguously recompose. - if(!doCompose) { + if (!doCompose) { return false; } - } else if(doCompose) { - buffer.append(c, cc); - continue; - } else if(prevCC<=cc) { - prevCC=cc; - continue; } else { - return false; + // If !onlyContiguous (not FCC), then we ignore the tccc of + // the previous character which passed the quick check "yes && ccc==0" test. + int n16; + for (;;) { + if (src == limit) { + if (doCompose) { + buffer.append(s, prevBoundary, limit); + } + return true; + } + int prevCC = cc; + c = Character.codePointAt(s, src); + n16 = normTrie.get(c); + if (n16 >= MIN_YES_YES_WITH_CC) { + cc = getCCFromNormalYesOrMaybe(n16); + if (prevCC > cc) { + if (!doCompose) { + return false; + } + break; + } + } else { + break; + } + src += Character.charCount(c); + } + // p is after the last in-order combining mark. + // If there is a boundary here, then we continue with no change. + if (norm16HasCompBoundaryBefore(n16)) { + if (isCompYesAndZeroCC(n16)) { + src += Character.charCount(c); + } + continue; + } + // Use the slow path. There is no boundary in [prevSrc, src[. } - } else if(!doCompose && !isMaybeOrNonZeroCC(norm16)) { - return false; } - /* - * Find appropriate boundaries around this character, - * decompose the source text from between the boundaries, - * and recompose it. - * - * We may need to remove the last few characters from the ReorderingBuffer - * to account for source text that was copied or appended - * but needs to take part in the recomposition. - */ - - /* - * Find the last composition boundary in [prevBoundary..src[. - * It is either the decomposition of the current character (at prevSrc), - * or prevBoundary. - */ - if(hasCompBoundaryBefore(c, norm16)) { - prevBoundary=prevSrc; - } else if(doCompose) { - buffer.removeSuffix(prevSrc-prevBoundary); + // Slow path: Find the nearest boundaries around the current character, + // decompose and recompose. + if (prevBoundary != prevSrc && !norm16HasCompBoundaryBefore(norm16)) { + c = Character.codePointBefore(s, prevSrc); + norm16 = normTrie.get(c); + if (!norm16HasCompBoundaryAfter(norm16, onlyContiguous)) { + prevSrc -= Character.charCount(c); + } + } + if (doCompose && prevBoundary != prevSrc) { + buffer.append(s, prevBoundary, prevSrc); } - - // Find the next composition boundary in [src..limit[ - - // modifies src to point to the next starter. - src=findNextCompBoundary(s, src, limit); - - // Decompose [prevBoundary..src[ into the buffer and then recompose that part of it. int recomposeStartIndex=buffer.length(); - decomposeShort(s, prevBoundary, src, buffer); + // We know there is not a boundary here. + decomposeShort(s, prevSrc, src, false /* !stopAtCompBoundary */, onlyContiguous, + buffer); + // Decompose until the next boundary. + src = decomposeShort(s, src, limit, true /* stopAtCompBoundary */, onlyContiguous, + buffer); recompose(buffer, recomposeStartIndex, onlyContiguous); if(!doCompose) { - if(!buffer.equals(s, prevBoundary, src)) { + if(!buffer.equals(s, prevSrc, src)) { return false; } buffer.remove(); - prevCC=0; } - - // Move to the next starter. We never need to look back before this point again. prevBoundary=src; } - return true; } /** @@ -984,21 +977,16 @@ public final class NormalizerImpl { public int composeQuickCheck(CharSequence s, int src, int limit, boolean onlyContiguous, boolean doSpan) { int qcResult=0; + int prevBoundary=src; int minNoMaybeCP=minCompNoMaybeCP; - /* - * prevBoundary points to the last character before the current one - * that has a composition boundary before it with ccc==0 and quick check "yes". - */ - int prevBoundary=src; - int prevSrc; - int c=0; - int norm16=0; - int prevCC=0; - for(;;) { - // count code units below the minimum or with irrelevant data for the quick check - for(prevSrc=src;;) { + // Fast path: Scan over a sequence of characters below the minimum "no or maybe" code point, + // or with (compYes && ccc==0) properties. + int prevSrc; + int c = 0; + int norm16 = 0; + for (;;) { if(src==limit) { return (src<<1)|qcResult; // "yes" or "maybe" } @@ -1006,88 +994,103 @@ public final class NormalizerImpl { isCompYesAndZeroCC(norm16=normTrie.getFromU16SingleLead((char)c)) ) { ++src; - } else if(!UTF16.isSurrogate((char)c)) { - break; } else { - char c2; - if(UTF16Plus.isSurrogateLead(c)) { - if((src+1)!=limit && Character.isLowSurrogate(c2=s.charAt(src+1))) { - c=Character.toCodePoint((char)c, c2); - } - } else /* trail surrogate */ { - if(prevSrc=minNoNo. + // The current character is either a "noNo" (has a mapping) + // or a "maybeYes" (combines backward) + // or a "yesYes" with ccc!=0. + // It is not a Hangul syllable or Jamo L because those have "yes" properties. + + int prevNorm16 = INERT; + if (prevBoundary != prevSrc) { + prevBoundary = prevSrc; + if (!norm16HasCompBoundaryBefore(norm16)) { + c = Character.codePointBefore(s, prevSrc); + int n16 = getNorm16(c); + if (!norm16HasCompBoundaryAfter(n16, onlyContiguous)) { + prevBoundary -= Character.charCount(c); + prevNorm16 = n16; + } } - prevCC=0; - // The start of the current character (c). - prevSrc=src; } - src+=Character.charCount(c); - /* - * isCompYesAndZeroCC(norm16) is false, that is, norm16>=minNoNo. - * c is either a "noNo" (has a mapping) or a "maybeYes" (combines backward) - * or has ccc!=0. - */ if(isMaybeOrNonZeroCC(norm16)) { int cc=getCCFromYesOrMaybe(norm16); - if( onlyContiguous && // FCC - cc!=0 && - prevCC==0 && - prevBoundarycc - ) { - // Fails FCD test. - } else if(prevCC<=cc || cc==0) { - prevCC=cc; - if(norm16 cc) { + // The [prevBoundary..prevSrc[ character + // passed the quick check "yes && ccc==0" test + // but is out of canonical order with the current combining mark. + } else { + // If !onlyContiguous (not FCC), then we ignore the tccc of + // the previous character which passed the quick check "yes && ccc==0" test. + for (;;) { + if (norm16 < MIN_YES_YES_WITH_CC) { + if (!doSpan) { + qcResult = 1; + } else { + return prevBoundary << 1; // spanYes does not care to know it's "maybe" + } } + if (src == limit) { + return (src<<1) | qcResult; // "yes" or "maybe" + } + int prevCC = cc; + c = Character.codePointAt(s, src); + norm16 = getNorm16(c); + if (isMaybeOrNonZeroCC(norm16)) { + cc = getCCFromYesOrMaybe(norm16); + if (!(prevCC <= cc || cc == 0)) { + break; + } + } else { + break; + } + src += Character.charCount(c); + } + // src is after the last in-order combining mark. + if (isCompYesAndZeroCC(norm16)) { + prevBoundary = src; + src += Character.charCount(c); + continue; } - continue; } } return prevBoundary<<1; // "no" } } - public void composeAndAppend(CharSequence s, boolean doCompose, boolean onlyContiguous, ReorderingBuffer buffer) { int src=0, limit=s.length(); if(!buffer.isEmpty()) { - int firstStarterInSrc=findNextCompBoundary(s, 0, limit); + int firstStarterInSrc=findNextCompBoundary(s, 0, limit, onlyContiguous); if(0!=firstStarterInSrc) { int lastStarterInDest=findPreviousCompBoundary(buffer.getStringBuilder(), - buffer.length()); + buffer.length(), onlyContiguous); StringBuilder middle=new StringBuilder((buffer.length()-lastStarterInDest)+ firstStarterInSrc+16); middle.append(buffer.getStringBuilder(), lastStarterInDest, buffer.length()); @@ -1103,7 +1106,6 @@ public final class NormalizerImpl { buffer.append(s, src, limit); } } - // Dual functionality: // buffer!=NULL: normalize // buffer==NULL: isNormalized/quickCheck/spanQuickCheckYes @@ -1125,7 +1127,7 @@ public final class NormalizerImpl { for(;;) { // count code units with lccc==0 for(prevSrc=src; src!=limit;) { - if((c=s.charAt(src))1) { - --prevBoundary; + if(prev1) { + --prevBoundary; + } } } else { int p=src-1; @@ -1228,7 +1234,7 @@ public final class NormalizerImpl { * The source text does not fulfill the conditions for FCD. * Decompose and reorder a limited piece of the text. */ - decomposeShort(s, prevBoundary, src, buffer); + decomposeShort(s, prevBoundary, src, false, false, buffer); prevBoundary=src; prevFCD16=0; } @@ -1236,54 +1242,77 @@ public final class NormalizerImpl { return src; } - // Note: hasDecompBoundary() could be implemented as aliases to - // hasFCDBoundaryBefore() and hasFCDBoundaryAfter() - // at the cost of building the FCD trie for a decomposition normalizer. - public boolean hasDecompBoundary(int c, boolean before) { - for(;;) { - if(cMIN_NORMAL_MAYBE_YES) { - return false; // ccc!=0 - } else if(isDecompNoAlgorithmic(norm16)) { - c=mapAlgorithmic(c, norm16); - } else { - // c decomposes, get everything from the variable-length extra data - int firstUnit=extraData.charAt(norm16); - if((firstUnit&MAPPING_LENGTH_MASK)==0) { - return false; - } - if(!before) { - // decomp after-boundary: same as hasFCDBoundaryAfter(), - // fcd16<=1 || trailCC==0 - if(firstUnit>0x1ff) { - return false; // trailCC>1 - } - if(firstUnit<=0xff) { - return true; // trailCC==0 - } - // if(trailCC==1) test leadCC==0, same as checking for before-boundary - } - // true if leadCC==0 (hasFCDBoundaryBefore()) - return (firstUnit&MAPPING_HAS_CCC_LCCC_WORD)==0 || (extraData.charAt(norm16-1)&0xff00)==0; - } - } + public boolean hasDecompBoundaryBefore(int c) { + return c < minLcccCP || (c <= 0xffff && !singleLeadMightHaveNonZeroFCD16(c)) || + norm16HasDecompBoundaryBefore(getNorm16(c)); } + public boolean norm16HasDecompBoundaryBefore(int norm16) { + if (norm16 < minNoNoCompNoMaybeCC) { + return true; + } + if (norm16 >= limitNoNo) { + return norm16 <= MIN_NORMAL_MAYBE_YES || norm16 == JAMO_VT; + } + // c decomposes, get everything from the variable-length extra data + int mapping=norm16>>OFFSET_SHIFT; + int firstUnit=extraData.charAt(mapping); + // true if leadCC==0 (hasFCDBoundaryBefore()) + return (firstUnit&MAPPING_HAS_CCC_LCCC_WORD)==0 || (extraData.charAt(mapping-1)&0xff00)==0; + } + public boolean hasDecompBoundaryAfter(int c) { + if (c < minDecompNoCP) { + return true; + } + if (c <= 0xffff && !singleLeadMightHaveNonZeroFCD16(c)) { + return true; + } + return norm16HasDecompBoundaryAfter(getNorm16(c)); + } + public boolean norm16HasDecompBoundaryAfter(int norm16) { + if(norm16 <= minYesNo || isHangulLVT(norm16)) { + return true; + } + if (norm16 >= limitNoNo) { + if (isMaybeOrNonZeroCC(norm16)) { + return norm16 <= MIN_NORMAL_MAYBE_YES || norm16 == JAMO_VT; + } + // Maps to an isCompYesAndZeroCC. + return (norm16 & DELTA_TCCC_MASK) <= DELTA_TCCC_1; + } + // c decomposes, get everything from the variable-length extra data + int mapping=norm16>>OFFSET_SHIFT; + int firstUnit=extraData.charAt(mapping); + // decomp after-boundary: same as hasFCDBoundaryAfter(), + // fcd16<=1 || trailCC==0 + if(firstUnit>0x1ff) { + return false; // trailCC>1 + } + if(firstUnit<=0xff) { + return true; // trailCC==0 + } + // if(trailCC==1) test leadCC==0, same as checking for before-boundary + // true if leadCC==0 (hasFCDBoundaryBefore()) + return (firstUnit&MAPPING_HAS_CCC_LCCC_WORD)==0 || (extraData.charAt(mapping-1)&0xff00)==0; + } + public boolean isDecompInert(int c) { return isDecompYesAndZeroCC(getNorm16(c)); } public boolean hasCompBoundaryBefore(int c) { - return c=minMaybeYes; } + private static boolean isInert(int norm16) { return norm16==INERT; } private static boolean isJamoVT(int norm16) { return norm16==JAMO_VT; } - private boolean isHangul(int norm16) { return norm16==minYesNo; } + private int hangulLVT() { return minYesNoMappingsOnly|HAS_COMP_BOUNDARY_AFTER; } + private boolean isHangulLV(int norm16) { return norm16==minYesNo; } + private boolean isHangulLVT(int norm16) { + return norm16==hangulLVT(); + } private boolean isCompYesAndZeroCC(int norm16) { return norm16=MIN_YES_YES_WITH_CC || norm16=limitNoNo; } // For use with isCompYes(). // Perhaps the compiler can combine the two tests for MIN_YES_YES_WITH_CC. // static uint8_t getCCFromYes(uint16_t norm16) { - // return norm16>=MIN_YES_YES_WITH_CC ? (uint8_t)norm16 : 0; + // return norm16>=MIN_YES_YES_WITH_CC ? getCCFromNormalYesOrMaybe(norm16) : 0; // } private int getCCFromNoNo(int norm16) { - if((extraData.charAt(norm16)&MAPPING_HAS_CCC_LCCC_WORD)!=0) { - return extraData.charAt(norm16-1)&0xff; + int mapping=norm16>>OFFSET_SHIFT; + if((extraData.charAt(mapping)&MAPPING_HAS_CCC_LCCC_WORD)!=0) { + return extraData.charAt(mapping-1)&0xff; } else { return 0; } } - - // requires that the [cpStart..cpLimit[ character passes isCompYesAndZeroCC() - int getTrailCCFromCompYesAndZeroCC(CharSequence s, int cpStart, int cpLimit) { - int c; - if(cpStart==(cpLimit-1)) { - c=s.charAt(cpStart); + int getTrailCCFromCompYesAndZeroCC(int norm16) { + if(norm16<=minYesNo) { + return 0; // yesYes and Hangul LV have ccc=tccc=0 } else { - c=Character.codePointAt(s, cpStart); - } - int prevNorm16=getNorm16(c); - if(prevNorm16<=minYesNo) { - return 0; // yesYes and Hangul LV/LVT have ccc=tccc=0 - } else { - return extraData.charAt(prevNorm16)>>8; // tccc from yesNo + // For Hangul LVT we harmlessly fetch a firstUnit with tccc=0 here. + return extraData.charAt(norm16>>OFFSET_SHIFT)>>8; // tccc from yesNo } } // Requires algorithmic-NoNo. private int mapAlgorithmic(int c, int norm16) { - return c+norm16-(minMaybeYes-MAX_DELTA-1); + return c+(norm16>>DELTA_SHIFT)-centerNoNoDelta; } // Requires minYesNo>OFFSET_SHIFT); } /** * @return index into maybeYesCompositions, or -1 */ private int getCompositionsListForDecompYes(int norm16) { - if(norm16==0 || MIN_NORMAL_MAYBE_YES<=norm16) { + if(norm16>OFFSET_SHIFT; } } - /** * @return index into maybeYesCompositions */ private int getCompositionsListForComposite(int norm16) { - // composite has both mapping & compositions list - int firstUnit=extraData.charAt(norm16); - return (MIN_NORMAL_MAYBE_YES-minMaybeYes)+norm16+ // mapping in maybeYesCompositions - 1+ // +1 to skip the first unit with the mapping lenth + // A composite has both mapping & compositions list. + int list=((MIN_NORMAL_MAYBE_YES-minMaybeYes)+norm16)>>OFFSET_SHIFT; + int firstUnit=maybeYesCompositions.charAt(list); + return list+ // mapping in maybeYesCompositions + 1+ // +1 to skip the first unit with the mapping length (firstUnit&MAPPING_LENGTH_MASK); // + mapping length } @@ -1380,45 +1400,58 @@ public final class NormalizerImpl { // is unlikely to be amortized. // Called by the compose() and makeFCD() implementations. // Public in Java for collation implementation code. - public void decomposeShort(CharSequence s, int src, int limit, - ReorderingBuffer buffer) { + private int decomposeShort( + CharSequence s, int src, int limit, + boolean stopAtCompBoundary, boolean onlyContiguous, + ReorderingBuffer buffer) { while(src>8; - if((firstUnit&MAPPING_HAS_CCC_LCCC_WORD)!=0) { - leadCC=extraData.charAt(norm16-1)>>8; - } else { - leadCC=0; - } - ++norm16; // skip over the firstUnit - buffer.append(extraData, norm16, norm16+length, leadCC, trailCC); + if (stopAtCompBoundary && c < minCompNoMaybeCP) { + return src; } - return; + int norm16 = getNorm16(c); + if (stopAtCompBoundary && norm16HasCompBoundaryBefore(norm16)) { + return src; + } + src+=Character.charCount(c); + decompose(c, norm16, buffer); + if (stopAtCompBoundary && norm16HasCompBoundaryAfter(norm16, onlyContiguous)) { + return src; + } + } + return src; + } + private void decompose(int c, int norm16, ReorderingBuffer buffer) { + // get the decomposition and the lead and trail cc's + if (norm16 >= limitNoNo) { + if (isMaybeOrNonZeroCC(norm16)) { + buffer.append(c, getCCFromYesOrMaybe(norm16)); + return; + } + // Maps to an isCompYesAndZeroCC. + c=mapAlgorithmic(c, norm16); + norm16=getNorm16(c); + } + if (norm16 < minYesNo) { + // c does not decompose + buffer.append(c, 0); + } else if(isHangulLV(norm16) || isHangulLVT(norm16)) { + // Hangul syllable: decompose algorithmically + Hangul.decompose(c, buffer); + } else { + // c decomposes, get everything from the variable-length extra data + int mapping=norm16>>OFFSET_SHIFT; + int firstUnit=extraData.charAt(mapping); + int length=firstUnit&MAPPING_LENGTH_MASK; + int leadCC, trailCC; + trailCC=firstUnit>>8; + if((firstUnit&MAPPING_HAS_CCC_LCCC_WORD)!=0) { + leadCC=extraData.charAt(mapping-1)>>8; + } else { + leadCC=0; + } + ++mapping; // skip over the firstUnit + buffer.append(extraData, mapping, mapping+length, leadCC, trailCC); } } @@ -1457,7 +1490,7 @@ public final class NormalizerImpl { } if(key1==(firstUnit&COMP_1_TRAIL_MASK)) { if((firstUnit&COMP_1_TRIPLE)!=0) { - return ((int)compositions.charAt(list+1)<<16)|compositions.charAt(list+2); + return (compositions.charAt(list+1)<<16)|compositions.charAt(list+2); } else { return compositions.charAt(list+1); } @@ -1533,7 +1566,8 @@ public final class NormalizerImpl { // we have seen a starter that combines forward and compositionsList>=0 && // the backward-combining character is not blocked - (prevCC> OFFSET_SHIFT) <= 0x1ff); } - private int findPreviousCompBoundary(CharSequence s, int p) { + private int findPreviousCompBoundary(CharSequence s, int p, boolean onlyContiguous) { while(p>0) { int c=Character.codePointBefore(s, p); - p-=Character.charCount(c); - if(hasCompBoundaryBefore(c)) { + int norm16 = getNorm16(c); + if (norm16HasCompBoundaryAfter(norm16, onlyContiguous)) { + break; + } + p-=Character.charCount(c); + if(hasCompBoundaryBefore(c, norm16)) { break; } - // We could also test hasCompBoundaryAfter() and return iter.codePointLimit, - // but that's probably not worth the extra cost. } return p; } - - private int findNextCompBoundary(CharSequence s, int p, int limit) { + private int findNextCompBoundary(CharSequence s, int p, int limit, boolean onlyContiguous) { while(p|1Q5_LM5c4@FVcQcBUH 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≷1Lq}HV&dV;zt_oGcP}vPxgD^rE<0JHO7aD{X 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 literal 51040 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%0DF6Rs5-IKSzTCOSG}~ny?V86 zRj(=UuKvRAtZuPZR(Fc7gJ)tAcs)tAdFtFM&$tNThTtN$sjtHS^KsQ$OK zz50f=Zq}_<|EzyoL)}kUySx8xZSQ`nWOYB?YuR>>-D|^t+;u9IisyB7bahRiK67TN z)YR11*Jp*(+9yq!+S=3G%azrk&NK)IcME!Ydif9hAt(-yM+c8Ck*5@jF>PAY`Nzl1UrK_W2 z+kJh#Jw1mXUg_#;*ZjwXSO?&!n;A}bJ!QNpGjIe&hC|A(wotmVrs tYr)AMTexuHu^(P~-0>eh>ZnDFKC*c6;u9_SvpF$NIQpbz$84^R{{xW9gW~`I diff --git a/src/java.base/share/classes/sun/text/resources/uprops.icu b/src/java.base/share/classes/sun/text/resources/uprops.icu index 5fcaabf7dae6b428e7ba266b04a024d002d0a066..dcd55f646b243e66dd07dec28e30a1afadbc137e 100644 GIT binary patch literal 126800 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 literal 117680 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

    -K!H*%OiJcWw?vukZ;eoCr(DhX=7wh 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 Sprh+!*gpr>%ZYA}fBpv-T&-mQ diff --git a/src/java.desktop/share/classes/java/awt/font/NumericShaper.java b/src/java.desktop/share/classes/java/awt/font/NumericShaper.java index 31e7011715a..b14bc566109 100644 --- a/src/java.desktop/share/classes/java/awt/font/NumericShaper.java +++ b/src/java.desktop/share/classes/java/awt/font/NumericShaper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, 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 @@ -699,7 +699,8 @@ public final class NumericShaper implements java.io.Serializable { 0x09de, 0x09df, 0x09e2, 0x09e6, 0x09f2, 0x09f4, - 0x09fb, 0x0a03, + 0x09fb, 0x09fc, + 0x09fe, 0x0a03, 0x0a04, 0x0a05, 0x0a0b, 0x0a0f, 0x0a11, 0x0a13, @@ -769,7 +770,7 @@ public final class NumericShaper implements java.io.Serializable { 0x0c5b, 0x0c60, 0x0c62, 0x0c66, 0x0c70, 0x0c7f, - 0x0c80, 0x0c82, + 0x0c81, 0x0c82, 0x0c84, 0x0c85, 0x0c8d, 0x0c8e, 0x0c91, 0x0c92, @@ -791,10 +792,7 @@ public final class NumericShaper implements java.io.Serializable { 0x0d41, 0x0d46, 0x0d49, 0x0d4a, 0x0d4d, 0x0d4e, - 0x0d4f, 0x0d57, - 0x0d58, 0x0d5f, 0x0d62, 0x0d66, - 0x0d76, 0x0d79, 0x0d80, 0x0d82, 0x0d84, 0x0d85, 0x0d97, 0x0d9a, @@ -892,7 +890,8 @@ public final class NumericShaper implements java.io.Serializable { 0x17dd, 0x17e0, 0x17ea, 0x1810, 0x181a, 0x1820, - 0x1878, 0x1880, + 0x1878, 0x1884, + 0x1885, 0x1887, 0x18a9, 0x18aa, 0x18ab, 0x18b0, 0x18f6, 0x1900, @@ -934,13 +933,12 @@ public final class NumericShaper implements java.io.Serializable { 0x1c2c, 0x1c34, 0x1c36, 0x1c3b, 0x1c4a, 0x1c4d, - 0x1c80, 0x1cc0, 0x1cc8, 0x1cd3, 0x1cd4, 0x1ce1, 0x1ce2, 0x1ce9, 0x1ced, 0x1cee, 0x1cf4, 0x1cf5, - 0x1cf7, 0x1d00, + 0x1cf8, 0x1d00, 0x1dc0, 0x1e00, 0x1f16, 0x1f18, 0x1f1e, 0x1f20, @@ -1012,7 +1010,7 @@ public final class NumericShaper implements java.io.Serializable { 0x30a0, 0x30a1, 0x30fb, 0x30fc, 0x3100, 0x3105, - 0x312e, 0x3131, + 0x312f, 0x3131, 0x318f, 0x3190, 0x31bb, 0x31f0, 0x321d, 0x3220, @@ -1025,7 +1023,7 @@ public final class NumericShaper implements java.io.Serializable { 0x33de, 0x33e0, 0x33ff, 0x3400, 0x4db6, 0x4e00, - 0x9fd6, 0xa000, + 0x9feb, 0xa000, 0xa48d, 0xa4d0, 0xa60d, 0xa610, 0xa62c, 0xa640, @@ -1034,7 +1032,7 @@ public final class NumericShaper implements java.io.Serializable { 0xa6f0, 0xa6f2, 0xa6f8, 0xa722, 0xa788, 0xa789, - 0xa7ae, 0xa7b0, + 0xa7af, 0xa7b0, 0xa7b8, 0xa7f7, 0xa802, 0xa803, 0xa806, 0xa807, @@ -1114,18 +1112,21 @@ public final class NumericShaper implements java.io.Serializable { 0x10101, 0x10102, 0x10103, 0x10107, 0x10134, 0x10137, - 0x10140, 0x101d0, + 0x10140, 0x1018d, + 0x1018f, 0x101d0, 0x101fd, 0x10280, 0x1029d, 0x102a0, 0x102d1, 0x10300, - 0x10324, 0x10330, + 0x10324, 0x1032d, 0x1034b, 0x10350, 0x10376, 0x10380, 0x1039e, 0x1039f, 0x103c4, 0x103c8, 0x103d6, 0x10400, 0x1049e, 0x104a0, - 0x104aa, 0x10500, + 0x104aa, 0x104d3, + 0x104d4, 0x104d8, + 0x104fc, 0x10500, 0x10528, 0x10530, 0x10564, 0x1056f, 0x10570, 0x10600, @@ -1186,7 +1187,13 @@ public final class NumericShaper implements java.io.Serializable { 0x1134e, 0x11350, 0x11351, 0x11357, 0x11358, 0x1135d, - 0x11364, 0x11480, + 0x11364, 0x11400, + 0x11438, 0x11440, + 0x11442, 0x11445, + 0x11446, 0x11447, + 0x1145a, 0x1145b, + 0x1145c, 0x1145d, + 0x1145e, 0x11480, 0x114b3, 0x114b9, 0x114ba, 0x114bb, 0x114bf, 0x114c1, @@ -1212,8 +1219,33 @@ public final class NumericShaper implements java.io.Serializable { 0x11727, 0x11730, 0x11740, 0x118a0, 0x118f3, 0x118ff, - 0x11900, 0x11ac0, - 0x11af9, 0x12000, + 0x11900, 0x11a00, + 0x11a01, 0x11a07, + 0x11a09, 0x11a0b, + 0x11a33, 0x11a3a, + 0x11a3b, 0x11a3f, + 0x11a47, 0x11a50, + 0x11a51, 0x11a57, + 0x11a59, 0x11a5c, + 0x11a84, 0x11a86, + 0x11a8a, 0x11a97, + 0x11a98, 0x11a9a, + 0x11a9d, 0x11a9e, + 0x11aa3, 0x11ac0, + 0x11af9, 0x11C00, + 0x11C09, 0x11c0a, + 0x11c30, 0x11c3e, + 0x11c46, 0x11c50, + 0x11c6d, 0x11c70, + 0x11c90, 0x11ca9, + 0x11caa, 0x11cb1, + 0x11cb2, 0x11cb4, + 0x11cb5, 0x11d00, + 0x11d07, 0x11d08, + 0x11d0a, 0x11d0b, + 0x11d31, 0x11d46, + 0x11d47, 0x11d50, + 0x11d5a, 0x12000, 0x1239a, 0x12400, 0x1246f, 0x12470, 0x12475, 0x12480, @@ -1234,8 +1266,12 @@ public final class NumericShaper implements java.io.Serializable { 0x16b90, 0x16f00, 0x16f45, 0x16f50, 0x16f7f, 0x16f93, - 0x16fa0, 0x1b000, - 0x1b002, 0x1bc00, + 0x16fa0, 0x16fe0, + 0x16fe2, 0x17000, + 0x187ed, 0x18800, + 0x18af3, 0x1b000, + 0x1b11f, 0x1b170, + 0x1b2fc, 0x1bc00, 0x1bc6b, 0x1bc70, 0x1bc7d, 0x1bc80, 0x1bc89, 0x1bc90, @@ -1281,19 +1317,21 @@ public final class NumericShaper implements java.io.Serializable { 0x1da84, 0x1da85, 0x1da8c, 0x1e800, 0x1e8d0, 0x1e8d7, + 0x1e944, 0x1e94b, 0x1eef0, 0x1eef2, 0x1f000, 0x1f110, 0x1f12f, 0x1f130, 0x1f16a, 0x1f170, - 0x1f19b, 0x1f1e6, + 0x1f1ad, 0x1f1e6, 0x1f203, 0x1f210, - 0x1f23b, 0x1f240, + 0x1f23c, 0x1f240, 0x1f249, 0x1f250, 0x1f252, 0x20000, 0x2a6d7, 0x2a700, 0x2b735, 0x2b740, 0x2b81e, 0x2b820, - 0x2cea2, 0x2f800, + 0x2cea2, 0x2ceb0, + 0x2ebe1, 0x2f800, 0x2fa1e, 0xf0000, 0xffffe, 0x100000, 0x10fffe, 0x10ffff // sentinel diff --git a/test/jdk/java/lang/Character/Blocks.txt b/test/jdk/java/lang/Character/Blocks.txt new file mode 100644 index 00000000000..8406c531eda --- /dev/null +++ b/test/jdk/java/lang/Character/Blocks.txt @@ -0,0 +1,316 @@ +# Blocks-10.0.0.txt +# Date: 2017-04-12, 17:30:00 GMT [KW] +# Copyright (c) 2017 Unicode, Inc. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Format: +# Start Code..End Code; Block Name + +# ================================================ + +# Note: When comparing block names, casing, whitespace, hyphens, +# and underbars are ignored. +# For example, "Latin Extended-A" and "latin extended a" are equivalent. +# For more information on the comparison of property values, +# see UAX #44: http://www.unicode.org/reports/tr44/ +# +# All block ranges start with a value where (cp MOD 16) = 0, +# and end with a value where (cp MOD 16) = 15. In other words, +# the last hexadecimal digit of the start of range is ...0 +# and the last hexadecimal digit of the end of range is ...F. +# This constraint on block ranges guarantees that allocations +# are done in terms of whole columns, and that code chart display +# never involves splitting columns in the charts. +# +# All code points not explicitly listed for Block +# have the value No_Block. + +# Property: Block +# +# @missing: 0000..10FFFF; No_Block + +0000..007F; Basic Latin +0080..00FF; Latin-1 Supplement +0100..017F; Latin Extended-A +0180..024F; Latin Extended-B +0250..02AF; IPA Extensions +02B0..02FF; Spacing Modifier Letters +0300..036F; Combining Diacritical Marks +0370..03FF; Greek and Coptic +0400..04FF; Cyrillic +0500..052F; Cyrillic Supplement +0530..058F; Armenian +0590..05FF; Hebrew +0600..06FF; Arabic +0700..074F; Syriac +0750..077F; Arabic Supplement +0780..07BF; Thaana +07C0..07FF; NKo +0800..083F; Samaritan +0840..085F; Mandaic +0860..086F; Syriac Supplement +08A0..08FF; Arabic Extended-A +0900..097F; Devanagari +0980..09FF; Bengali +0A00..0A7F; Gurmukhi +0A80..0AFF; Gujarati +0B00..0B7F; Oriya +0B80..0BFF; Tamil +0C00..0C7F; Telugu +0C80..0CFF; Kannada +0D00..0D7F; Malayalam +0D80..0DFF; Sinhala +0E00..0E7F; Thai +0E80..0EFF; Lao +0F00..0FFF; Tibetan +1000..109F; Myanmar +10A0..10FF; Georgian +1100..11FF; Hangul Jamo +1200..137F; Ethiopic +1380..139F; Ethiopic Supplement +13A0..13FF; Cherokee +1400..167F; Unified Canadian Aboriginal Syllabics +1680..169F; Ogham +16A0..16FF; Runic +1700..171F; Tagalog +1720..173F; Hanunoo +1740..175F; Buhid +1760..177F; Tagbanwa +1780..17FF; Khmer +1800..18AF; Mongolian +18B0..18FF; Unified Canadian Aboriginal Syllabics Extended +1900..194F; Limbu +1950..197F; Tai Le +1980..19DF; New Tai Lue +19E0..19FF; Khmer Symbols +1A00..1A1F; Buginese +1A20..1AAF; Tai Tham +1AB0..1AFF; Combining Diacritical Marks Extended +1B00..1B7F; Balinese +1B80..1BBF; Sundanese +1BC0..1BFF; Batak +1C00..1C4F; Lepcha +1C50..1C7F; Ol Chiki +1C80..1C8F; Cyrillic Extended-C +1CC0..1CCF; Sundanese Supplement +1CD0..1CFF; Vedic Extensions +1D00..1D7F; Phonetic Extensions +1D80..1DBF; Phonetic Extensions Supplement +1DC0..1DFF; Combining Diacritical Marks Supplement +1E00..1EFF; Latin Extended Additional +1F00..1FFF; Greek Extended +2000..206F; General Punctuation +2070..209F; Superscripts and Subscripts +20A0..20CF; Currency Symbols +20D0..20FF; Combining Diacritical Marks for Symbols +2100..214F; Letterlike Symbols +2150..218F; Number Forms +2190..21FF; Arrows +2200..22FF; Mathematical Operators +2300..23FF; Miscellaneous Technical +2400..243F; Control Pictures +2440..245F; Optical Character Recognition +2460..24FF; Enclosed Alphanumerics +2500..257F; Box Drawing +2580..259F; Block Elements +25A0..25FF; Geometric Shapes +2600..26FF; Miscellaneous Symbols +2700..27BF; Dingbats +27C0..27EF; Miscellaneous Mathematical Symbols-A +27F0..27FF; Supplemental Arrows-A +2800..28FF; Braille Patterns +2900..297F; Supplemental Arrows-B +2980..29FF; Miscellaneous Mathematical Symbols-B +2A00..2AFF; Supplemental Mathematical Operators +2B00..2BFF; Miscellaneous Symbols and Arrows +2C00..2C5F; Glagolitic +2C60..2C7F; Latin Extended-C +2C80..2CFF; Coptic +2D00..2D2F; Georgian Supplement +2D30..2D7F; Tifinagh +2D80..2DDF; Ethiopic Extended +2DE0..2DFF; Cyrillic Extended-A +2E00..2E7F; Supplemental Punctuation +2E80..2EFF; CJK Radicals Supplement +2F00..2FDF; Kangxi Radicals +2FF0..2FFF; Ideographic Description Characters +3000..303F; CJK Symbols and Punctuation +3040..309F; Hiragana +30A0..30FF; Katakana +3100..312F; Bopomofo +3130..318F; Hangul Compatibility Jamo +3190..319F; Kanbun +31A0..31BF; Bopomofo Extended +31C0..31EF; CJK Strokes +31F0..31FF; Katakana Phonetic Extensions +3200..32FF; Enclosed CJK Letters and Months +3300..33FF; CJK Compatibility +3400..4DBF; CJK Unified Ideographs Extension A +4DC0..4DFF; Yijing Hexagram Symbols +4E00..9FFF; CJK Unified Ideographs +A000..A48F; Yi Syllables +A490..A4CF; Yi Radicals +A4D0..A4FF; Lisu +A500..A63F; Vai +A640..A69F; Cyrillic Extended-B +A6A0..A6FF; Bamum +A700..A71F; Modifier Tone Letters +A720..A7FF; Latin Extended-D +A800..A82F; Syloti Nagri +A830..A83F; Common Indic Number Forms +A840..A87F; Phags-pa +A880..A8DF; Saurashtra +A8E0..A8FF; Devanagari Extended +A900..A92F; Kayah Li +A930..A95F; Rejang +A960..A97F; Hangul Jamo Extended-A +A980..A9DF; Javanese +A9E0..A9FF; Myanmar Extended-B +AA00..AA5F; Cham +AA60..AA7F; Myanmar Extended-A +AA80..AADF; Tai Viet +AAE0..AAFF; Meetei Mayek Extensions +AB00..AB2F; Ethiopic Extended-A +AB30..AB6F; Latin Extended-E +AB70..ABBF; Cherokee Supplement +ABC0..ABFF; Meetei Mayek +AC00..D7AF; Hangul Syllables +D7B0..D7FF; Hangul Jamo Extended-B +D800..DB7F; High Surrogates +DB80..DBFF; High Private Use Surrogates +DC00..DFFF; Low Surrogates +E000..F8FF; Private Use Area +F900..FAFF; CJK Compatibility Ideographs +FB00..FB4F; Alphabetic Presentation Forms +FB50..FDFF; Arabic Presentation Forms-A +FE00..FE0F; Variation Selectors +FE10..FE1F; Vertical Forms +FE20..FE2F; Combining Half Marks +FE30..FE4F; CJK Compatibility Forms +FE50..FE6F; Small Form Variants +FE70..FEFF; Arabic Presentation Forms-B +FF00..FFEF; Halfwidth and Fullwidth Forms +FFF0..FFFF; Specials +10000..1007F; Linear B Syllabary +10080..100FF; Linear B Ideograms +10100..1013F; Aegean Numbers +10140..1018F; Ancient Greek Numbers +10190..101CF; Ancient Symbols +101D0..101FF; Phaistos Disc +10280..1029F; Lycian +102A0..102DF; Carian +102E0..102FF; Coptic Epact Numbers +10300..1032F; Old Italic +10330..1034F; Gothic +10350..1037F; Old Permic +10380..1039F; Ugaritic +103A0..103DF; Old Persian +10400..1044F; Deseret +10450..1047F; Shavian +10480..104AF; Osmanya +104B0..104FF; Osage +10500..1052F; Elbasan +10530..1056F; Caucasian Albanian +10600..1077F; Linear A +10800..1083F; Cypriot Syllabary +10840..1085F; Imperial Aramaic +10860..1087F; Palmyrene +10880..108AF; Nabataean +108E0..108FF; Hatran +10900..1091F; Phoenician +10920..1093F; Lydian +10980..1099F; Meroitic Hieroglyphs +109A0..109FF; Meroitic Cursive +10A00..10A5F; Kharoshthi +10A60..10A7F; Old South Arabian +10A80..10A9F; Old North Arabian +10AC0..10AFF; Manichaean +10B00..10B3F; Avestan +10B40..10B5F; Inscriptional Parthian +10B60..10B7F; Inscriptional Pahlavi +10B80..10BAF; Psalter Pahlavi +10C00..10C4F; Old Turkic +10C80..10CFF; Old Hungarian +10E60..10E7F; Rumi Numeral Symbols +11000..1107F; Brahmi +11080..110CF; Kaithi +110D0..110FF; Sora Sompeng +11100..1114F; Chakma +11150..1117F; Mahajani +11180..111DF; Sharada +111E0..111FF; Sinhala Archaic Numbers +11200..1124F; Khojki +11280..112AF; Multani +112B0..112FF; Khudawadi +11300..1137F; Grantha +11400..1147F; Newa +11480..114DF; Tirhuta +11580..115FF; Siddham +11600..1165F; Modi +11660..1167F; Mongolian Supplement +11680..116CF; Takri +11700..1173F; Ahom +118A0..118FF; Warang Citi +11A00..11A4F; Zanabazar Square +11A50..11AAF; Soyombo +11AC0..11AFF; Pau Cin Hau +11C00..11C6F; Bhaiksuki +11C70..11CBF; Marchen +11D00..11D5F; Masaram Gondi +12000..123FF; Cuneiform +12400..1247F; Cuneiform Numbers and Punctuation +12480..1254F; Early Dynastic Cuneiform +13000..1342F; Egyptian Hieroglyphs +14400..1467F; Anatolian Hieroglyphs +16800..16A3F; Bamum Supplement +16A40..16A6F; Mro +16AD0..16AFF; Bassa Vah +16B00..16B8F; Pahawh Hmong +16F00..16F9F; Miao +16FE0..16FFF; Ideographic Symbols and Punctuation +17000..187FF; Tangut +18800..18AFF; Tangut Components +1B000..1B0FF; Kana Supplement +1B100..1B12F; Kana Extended-A +1B170..1B2FF; Nushu +1BC00..1BC9F; Duployan +1BCA0..1BCAF; Shorthand Format Controls +1D000..1D0FF; Byzantine Musical Symbols +1D100..1D1FF; Musical Symbols +1D200..1D24F; Ancient Greek Musical Notation +1D300..1D35F; Tai Xuan Jing Symbols +1D360..1D37F; Counting Rod Numerals +1D400..1D7FF; Mathematical Alphanumeric Symbols +1D800..1DAAF; Sutton SignWriting +1E000..1E02F; Glagolitic Supplement +1E800..1E8DF; Mende Kikakui +1E900..1E95F; Adlam +1EE00..1EEFF; Arabic Mathematical Alphabetic Symbols +1F000..1F02F; Mahjong Tiles +1F030..1F09F; Domino Tiles +1F0A0..1F0FF; Playing Cards +1F100..1F1FF; Enclosed Alphanumeric Supplement +1F200..1F2FF; Enclosed Ideographic Supplement +1F300..1F5FF; Miscellaneous Symbols and Pictographs +1F600..1F64F; Emoticons +1F650..1F67F; Ornamental Dingbats +1F680..1F6FF; Transport and Map Symbols +1F700..1F77F; Alchemical Symbols +1F780..1F7FF; Geometric Shapes Extended +1F800..1F8FF; Supplemental Arrows-C +1F900..1F9FF; Supplemental Symbols and Pictographs +20000..2A6DF; CJK Unified Ideographs Extension B +2A700..2B73F; CJK Unified Ideographs Extension C +2B740..2B81F; CJK Unified Ideographs Extension D +2B820..2CEAF; CJK Unified Ideographs Extension E +2CEB0..2EBEF; CJK Unified Ideographs Extension F +2F800..2FA1F; CJK Compatibility Ideographs Supplement +E0000..E007F; Tags +E0100..E01EF; Variation Selectors Supplement +F0000..FFFFF; Supplementary Private Use Area-A +100000..10FFFF; Supplementary Private Use Area-B + +# EOF diff --git a/test/jdk/java/lang/Character/CharCheck.java b/test/jdk/java/lang/Character/CharCheck.java new file mode 100644 index 00000000000..d67dd546b1a --- /dev/null +++ b/test/jdk/java/lang/Character/CharCheck.java @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +/** + * + * @author Alan Liu + * @author John O'Conner + */ + +import java.io.*; + + +/** + * This class either loads or dumps the character properties of all Unicode + * characters out to a file. When loading, it compares the loaded data with + * that obtained through the java.lang.Character API. This allows detection of + * changes to the character properties between versions of the Java VM. A + * typical usage would be to dump the properties under an early VM, and load + * them under a later VM. + * + * Also: Check the current VM's character properties against those in a + * Unicode database. The database should be of the format + * available on ftp.unicode.org/Public/UNIDATA. + * + */ +public class CharCheck { + static int differences = 0; + + public static void main(String args[]) throws Exception { + + if (args.length != 2 && args.length != 3) usage(); + if (args[0].equals("dump")) + dump(Integer.parseInt(args[1], 16), new ObjectOutputStream(new FileOutputStream(args[2]))); + else if (args[0].equals("load")) + load(Integer.parseInt(args[1], 16), new ObjectInputStream(new FileInputStream(args[2]))); + else if (args[0].equals("check")) + check(Integer.parseInt(args[1], 16), new File(args[2])); + else if (args[0].equals("char")) + showChar(Integer.parseInt(args[1],16)); + else if (args[0].equals("fchar")) + showFileChar(args[1], Integer.parseInt(args[2],16)); + else usage(); + if (differences != 0) { + throw new RuntimeException("There are differences between Character properties and the specification."); + } + } + + static void usage() { + System.err.println("Usage: java CharCheck "); + System.err.println("where is one of the following:"); + System.err.println("dump - dumps the character properties of the given plane,"); + System.err.println(" read from the current VM, to the given file."); + System.err.println("load - loads the character properties from the given"); + System.err.println(" file and compares them to those of the given character plane"); + System.err.println(" in the current VM."); + System.err.println("check - compare the current VM's character properties"); + System.err.println(" in the given plane to those listed in the given file, "); + System.err.println(" which should be in the format available on "); + System.err.println(" ftp.unicode.org/Public/2.0-Update."); + System.err.println("char - show current VM properties of the given Unicode char."); + System.err.println("fchar - show file properties of the given Unicode char."); + System.exit(0); + } + + static String getTypeName(int type) { + return (type >= 0 && type < UnicodeSpec.generalCategoryList.length) ? + (UnicodeSpec.generalCategoryList[type][UnicodeSpec.LONG] + '(' + type + ')') : + (""); + } + + static int check(int plane, File specFile) throws Exception { + + String version = System.getProperty("java.version"); + System.out.println("Current VM version " + version); + int rangeLimit = (plane << 16) | 0xFFFF; + String record; + UnicodeSpec[] spec = UnicodeSpec.readSpecFile(specFile, plane); + int rangeStart = 0x0000; + boolean isRange = false; + + lastCheck = (plane << 16) - 1; + + for (int currentSpec = 0; currentSpec < spec.length; currentSpec++) { + int c = spec[currentSpec].getCodePoint(); + if (isRange) { + // Must see end of range now + if (spec[currentSpec].getName().endsWith("Last>")) { + for (int d=rangeStart; d<=c; d++) { + checkOneChar(d, spec[currentSpec]); + } + } + else { + // No good -- First without Last + System.out.println("BAD FILE: First without last at '" + escape(rangeStart) + "'"); + } + isRange = false; + } + else { + // Look for a First, Last pair: This is a pair of entries like the following: + // 4E00;;Lo;0;L;;;;;N;;;;; + // 9FA5;;Lo;0;L;;;;;N;;;;; + if (spec[currentSpec].getName().endsWith("First>")) { + rangeStart = c; + isRange = true; + } + else { + checkOneChar(c, spec[currentSpec]); + } + } + } + + // Check undefined chars at the end of the range + + while (lastCheck < rangeLimit) checkOneCharDefined(++lastCheck, "?", false); + + System.out.println("Total differences: "+differences); + return differences; + } + + static int lastCheck = -1; + + static final void checkOneCharDefined(int c, String name, boolean fileDefined) { + if (Character.isDefined(c) != fileDefined) + showDifference(c, name, "isDefined", ""+(!fileDefined), ""+fileDefined); + } + + // In GenerateCharacter, the following ranges are handled specially. + // Each is the start of a 26-character range with values 10..35. + static final char NUMERIC_EXCEPTION[] = { '\u0041', '\u0061', '\uFF21', '\uFF41' }; + + static void checkOneChar(int c, UnicodeSpec charSpec) { + // Handle intervening ranges -- we assume that we will be called in monotonically + // increasing order. If the last char we checked is more than one before this + // char, then check the intervening range -- it should all be undefined. + int lowerLimit = (c & 0xFF0000); + if (lastCheck >= lowerLimit && (lastCheck+1) != c) { + for (int i=lastCheck+1; i= NUMERIC_EXCEPTION[k] && c < (char)(NUMERIC_EXCEPTION[k]+26)) { + numericValueDB = c - NUMERIC_EXCEPTION[k] + 10; + break; + } + } + } + else { + String strValue = charSpec.getNumericValue(); + int parsedNumericValue; + if (strValue.equals("10000000000") + || strValue.equals("1000000000000")) { + System.out.println("Skipping strValue: " + strValue + + " for " + charSpec.getName() + + "(0x" + Integer.toHexString(c) + ")"); + parsedNumericValue = -2; + } else { + parsedNumericValue = strValue.indexOf('/') < 0 ? + Integer.parseInt(strValue) : -2; + } + numericValueDB = parsedNumericValue < 0 ? -2 : parsedNumericValue; + } + if (numericValue != numericValueDB) + showDifference(c, charSpec.getName(), "numeric value", ""+numericValue, ""+numericValueDB); + } + + static void showDifference(int c, String name, String property, String vmValue, String dbValue) { + System.out.println(escape("Mismatch at '" + hex6(c) + "' (" + name+ "): " + + property + "=" + vmValue + ", db=" + dbValue)); + ++differences; + } + + /** + * Given a record containing ';'-separated fields, return the fieldno-th + * field. The first field is field 0. + */ + static String getField(String record, int fieldno) { + int i=0; + int j=record.indexOf(';'); + while (fieldno > 0) { + i=j+1; + j=record.indexOf(';', i); + } + return record.substring(i, j); + } + + static final int FIELD_COUNT = 15; + + /** + * Given a record containing ';'-separated fields, return an array of + * the fields. It is assumed that there are FIELD_COUNT fields per record. + */ + static void getFields(String record, String[] fields) { + int i=0; + int j=record.indexOf(';'); + fields[0] = record.substring(i, j); + for (int n=1; n= 0x20 && c <= 0x7F) buf.append(c); + else { + buf.append("\\u"); + String h = "000" + Integer.toHexString(c); + if (h.length() > 4) h = h.substring(h.length() - 4); + buf.append(h); + } + } + return buf.toString(); + } + + static String escape(int c) { + StringBuffer buf = new StringBuffer(); + if (c >= 0x20 && c <= 0x7F) buf.append(c); + else { + buf.append("\\u"); + String h = "000" + Integer.toHexString(c); + if (h.length() > 4) h = h.substring(h.length() - 4); + buf.append(h); + } + return buf.toString(); + } +} + + +//eof diff --git a/test/jdk/java/lang/Character/CheckBlocks.java b/test/jdk/java/lang/Character/CheckBlocks.java new file mode 100644 index 00000000000..6e1b04ad38d --- /dev/null +++ b/test/jdk/java/lang/Character/CheckBlocks.java @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 4830803 4886934 6565620 6959267 7070436 7198195 8032446 8072600 + * @summary Check that the UnicodeBlock forName() method works as expected and block ranges are correct for all Unicode characters. + * @run main CheckBlocks + * @author John O'Conner + */ + +import java.io.*; +import java.util.*; +import java.lang.Character.UnicodeBlock; + + +public class CheckBlocks { + + static boolean err = false; + static Class character; + + public static void main(String[] args) throws Exception { + generateBlockList(); + + try { + character = Class.forName("java.lang.Character$UnicodeBlock"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Class.forName(\"Character\") failed."); + } + + for (Block blk : blocks) { + test4830803_1(blk); + test4830803_2(); + test4886934(blk); + } + + if (err) { + throw new RuntimeException("Failed"); + } else { + System.out.println("Passed"); + } + } + + /** + * Check that the UnicodeBlock forName() method works as expected. + */ + private static void test4830803_1(Block blk) throws Exception { + + /* + * Try 3 forms of block name in the forName() method. Each form should + * produce the same expected block. + */ + String blkName = blk.getName(); + + // For backward compatibility + if (blkName.equals("COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS")) { + blkName = "COMBINING_MARKS_FOR_SYMBOLS"; + System.out.println("*** COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS is replaced with COMBINING_MARKS_FOR_SYMBOLS for backward compatibility."); + } else if (blkName.equals("GREEK_AND_COPTIC")) { + blkName = "GREEK"; + System.out.println("*** GREEK_AND_COPTIC is replaced with GREEK for backward compatibility."); + } else if (blkName.equals("CYRILLIC_SUPPLEMENT")) { + blkName = "CYRILLIC_SUPPLEMENTARY"; + System.out.println("*** CYRILLIC_SUPPLEMENT is replaced with CYRILLIC_SUPPLEMENTARY for backward compatibility."); + } + + String expectedBlock = null; + try { + expectedBlock = character.getField(blkName).getName(); + } catch (NoSuchFieldException | SecurityException e) { + System.err.println("Error: " + blkName + " was not found."); + err = true; + return; + } + + String canonicalBlockName = blk.getOriginalName(); + String idBlockName = expectedBlock; + String regexBlockName = toRegExString(canonicalBlockName); + + if (regexBlockName == null) { + System.err.println("Error: Block name which was processed with regex was null."); + err = true; + return; + } + + if (!expectedBlock.equals(UnicodeBlock.forName(canonicalBlockName).toString())) { + System.err.println("Error #1: UnicodeBlock.forName(\"" + + canonicalBlockName + "\") returned wrong value.\n\tGot: " + + UnicodeBlock.forName(canonicalBlockName) + + "\n\tExpected: " + expectedBlock); + err = true; + } + + if (!expectedBlock.equals(UnicodeBlock.forName(idBlockName).toString())) { + System.err.println("Error #2: UnicodeBlock.forName(\"" + + idBlockName + "\") returned wrong value.\n\tGot: " + + UnicodeBlock.forName(idBlockName) + + "\n\tExpected: " + expectedBlock); + err = true; + } + + if (!expectedBlock.equals(UnicodeBlock.forName(regexBlockName).toString())) { + System.err.println("Error #3: UnicodeBlock.forName(\"" + + regexBlockName + "\") returned wrong value.\n\tGot: " + + UnicodeBlock.forName(regexBlockName) + + "\n\tExpected: " + expectedBlock); + err = true; + } + } + + /** + * now try a bad block name. This should produce an IAE. + */ + private static void test4830803_2() { + boolean threwExpected = false; + + try { + UnicodeBlock block = UnicodeBlock.forName("notdefined"); + } + catch(IllegalArgumentException e) { + threwExpected = true; + } + + if (threwExpected == false) { + System.err.println("Error: UnicodeBlock.forName(\"notdefined\") should throw IllegalArgumentException."); + err = true; + } + } + + /** + * Convert the argument to a block name form used by the regex package. + * That is, remove all spaces. + */ + private static String toRegExString(String str) { + String[] tokens = null; + StringBuilder retStr = new StringBuilder(); + try { + tokens = str.split(" "); + } + catch(java.util.regex.PatternSyntaxException e) { + return null; + } + for(int x=0; x < tokens.length; ++x) { + retStr.append(tokens[x]); + } + return retStr.toString(); + } + + private static void test4886934(Block blk) { + String blkName = blk.getName(); + String blkOrigName = blk.getOriginalName(); + int ch = blk.getBegin(); + UnicodeBlock block = UnicodeBlock.of(ch); + + if (block == null) { + System.err.println("Error: The block for " + blkName + + " is missing. Please check java.lang.Character.UnicodeBlock."); + err = true; + return; + } + + // For backward compatibility + if (blkName.equals("COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS")) { + blkName = "COMBINING_MARKS_FOR_SYMBOLS"; + System.out.println("*** COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS is replaced with COMBINING_MARKS_FOR_SYMBOLS for backward compatibility."); + } else if (blkName.equals("GREEK_AND_COPTIC")) { + blkName = "GREEK"; + System.out.println("*** GREEK_AND_COPTIC is replaced with GREEK for backward compatibility."); + } else if (blkName.equals("CYRILLIC_SUPPLEMENT")) { + blkName = "CYRILLIC_SUPPLEMENTARY"; + System.out.println("*** CYRILLIC_SUPPLEMENT is replaced with CYRILLIC_SUPPLEMENTARY for backward compatibility."); + } + + String blockName = block.toString(); + if (!blockName.equals(blkName)) { + System.err.println("Error: Begin-of-block character(0x" + + Integer.toHexString(ch).toUpperCase() + + ") should be in \"" + blkName + "\" block " + + "(Block name is \"" + blkOrigName + "\")" + + " but found in \"" + blockName + "\" block."); + err = true; + } + + block = UnicodeBlock.of(++ch); + blockName = block.toString(); + if (!blockName.equals(blkName)) { + System.err.println("Error: Character(0x" + + Integer.toHexString(ch).toUpperCase() + + ") should be in \"" + blkName + "\" block " + + "(Block name is \"" + blkOrigName + "\")" + + " but found in \"" + blockName + "\" block."); + err = true; + } + + ch = blk.getEnd(); + block = UnicodeBlock.of(ch); + blockName = block.toString(); + if (!blockName.equals(blkName)) { + System.err.println("Error: End-of-block Character(0x" + + Integer.toHexString(ch).toUpperCase() + + ") should be in \"" + blkName + "\" block " + + "(Block name is \"" + blkOrigName + "\")" + + " but found in \"" + blockName + "\" block."); + err = true; + } + } + + // List of all Unicode blocks, their start, and end codepoints. + public static HashSet blocks = new HashSet<>(); + + private static void generateBlockList() throws Exception { + BufferedReader f = new BufferedReader(new FileReader(new File(System.getProperty("test.src", "."), "Blocks.txt"))); + + String line; + while ((line = f.readLine()) != null) { + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + + int index1 = line.indexOf('.'); + int begin = Integer.parseInt(line.substring(0, index1), 16); + int index2 = line.indexOf(';'); + int end = Integer.parseInt(line.substring(index1+2, index2), 16); + String name = line.substring(index2+1).trim(); + + System.out.println(" Adding a Block(" + + Integer.toHexString(begin) + ", " + Integer.toHexString(end) + + ", " + name + ")"); + blocks.add(new Block(begin, end, name)); + } + f.close(); + } +} + +class Block { + + public Block() { + blockBegin = 0; + blockEnd = 0; + blockName = null; + } + + public Block(int begin, int end, String name) { + blockBegin = begin; + blockEnd = end; + blockName = name.replaceAll("[ -]", "_").toUpperCase(Locale.ENGLISH); + originalBlockName = name; + } + + public int getBegin() { + return blockBegin; + } + + public int getEnd() { + return blockEnd; + } + + public String getName() { + return blockName; + } + + public String getOriginalName() { + return originalBlockName; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (!(obj instanceof Block)) return false; + + Block other = (Block)obj; + return other.blockBegin == blockBegin && + other.blockEnd == blockEnd && + other.blockName.equals(blockName) && + other.originalBlockName.equals(originalBlockName); + } + int blockBegin, blockEnd; + String blockName, originalBlockName; +} diff --git a/test/jdk/java/lang/Character/CheckUnicode.java b/test/jdk/java/lang/Character/CheckUnicode.java new file mode 100644 index 00000000000..97b2a10fb2e --- /dev/null +++ b/test/jdk/java/lang/Character/CheckUnicode.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 4114080 6565620 6959267 7070436 7198195 8032446 8072600 + * @summary Make sure the attributes of Unicode characters, as + * returned by the Character API, are as expected. Do this by + * comparing them to a baseline file together with a list of + * known diffs. + * @build UnicodeSpec CharCheck + * @run main CheckUnicode + * @author Alan Liu + * @author John O'Conner + */ + +import java.io.*; + +public class CheckUnicode { + public static void main(String args[]) throws Exception { + + // 1. Check that the dumped property files for planes 0, 1, 2, 3, 14, 15, and 16 + // are the same as in the current Character properties. + int[] planes = {0, 1, 2, 3, 14, 15, 16}; + String[] fileNames = {"charprop00.bin", "charprop01.bin", "charprop02.bin", "charprop03.bin", + "charprop0E.bin", "charprop0F.bin", "charprop10.bin" }; + + // Read in the Unicode 4.0 data + + for (int x=0; x < planes.length && x < fileNames.length; ++x) { + File unicodeProp = new File(System.getProperty("test.src", "."), fileNames[x]); + ObjectInputStream ois = new ObjectInputStream(new FileInputStream(unicodeProp)); + // Find differences -- should be none + int diffs = CharCheck.load(planes[x], ois); + if (diffs != 0) { + throw new RuntimeException("Bug 4114080 - Unicode properties have changed " + + "in an unexpected way"); + } + } + + + + + // 2. Check that the current 4.0 spec file is handled by the current + // version of Character. + File unicodeSpec = new File(System.getProperty("test.src", "."), "UnicodeData.txt"); + for (int x=0; x... 2329 ; Deprecated # Ps LEFT-POINTING ANGLE BRACKET 232A ; Deprecated # Pe RIGHT-POINTING ANGLE BRACKET E0001 ; Deprecated # Cf LANGUAGE TAG -E007F ; Deprecated # Cf CANCEL TAG -# Total code points: 16 +# Total code points: 15 # ================================================ @@ -1160,11 +1233,12 @@ AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET # ================================================ +1885..1886 ; Other_ID_Start # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA 2118 ; Other_ID_Start # Sm SCRIPT CAPITAL P 212E ; Other_ID_Start # So ESTIMATED SYMBOL 309B..309C ; Other_ID_Start # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK -# Total code points: 4 +# Total code points: 6 # ================================================ @@ -1177,72 +1251,76 @@ AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET # ================================================ -0021 ; STerm # Po EXCLAMATION MARK -002E ; STerm # Po FULL STOP -003F ; STerm # Po QUESTION MARK -0589 ; STerm # Po ARMENIAN FULL STOP -061F ; STerm # Po ARABIC QUESTION MARK -06D4 ; STerm # Po ARABIC FULL STOP -0700..0702 ; STerm # Po [3] SYRIAC END OF PARAGRAPH..SYRIAC SUBLINEAR FULL STOP -07F9 ; STerm # Po NKO EXCLAMATION MARK -0964..0965 ; STerm # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA -104A..104B ; STerm # Po [2] MYANMAR SIGN LITTLE SECTION..MYANMAR SIGN SECTION -1362 ; STerm # Po ETHIOPIC FULL STOP -1367..1368 ; STerm # Po [2] ETHIOPIC QUESTION MARK..ETHIOPIC PARAGRAPH SEPARATOR -166E ; STerm # Po CANADIAN SYLLABICS FULL STOP -1735..1736 ; STerm # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION -1803 ; STerm # Po MONGOLIAN FULL STOP -1809 ; STerm # Po MONGOLIAN MANCHU FULL STOP -1944..1945 ; STerm # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK -1AA8..1AAB ; STerm # Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU -1B5A..1B5B ; STerm # Po [2] BALINESE PANTI..BALINESE PAMADA -1B5E..1B5F ; STerm # Po [2] BALINESE CARIK SIKI..BALINESE CARIK PAREREN -1C3B..1C3C ; STerm # Po [2] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION NYET THYOOM TA-ROL -1C7E..1C7F ; STerm # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD -203C..203D ; STerm # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG -2047..2049 ; STerm # Po [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK -2E2E ; STerm # Po REVERSED QUESTION MARK -2E3C ; STerm # Po STENOGRAPHIC FULL STOP -3002 ; STerm # Po IDEOGRAPHIC FULL STOP -A4FF ; STerm # Po LISU PUNCTUATION FULL STOP -A60E..A60F ; STerm # Po [2] VAI FULL STOP..VAI QUESTION MARK -A6F3 ; STerm # Po BAMUM FULL STOP -A6F7 ; STerm # Po BAMUM QUESTION MARK -A876..A877 ; STerm # Po [2] PHAGS-PA MARK SHAD..PHAGS-PA MARK DOUBLE SHAD -A8CE..A8CF ; STerm # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA -A92F ; STerm # Po KAYAH LI SIGN SHYA -A9C8..A9C9 ; STerm # Po [2] JAVANESE PADA LINGSA..JAVANESE PADA LUNGSI -AA5D..AA5F ; STerm # Po [3] CHAM PUNCTUATION DANDA..CHAM PUNCTUATION TRIPLE DANDA -AAF0..AAF1 ; STerm # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM -ABEB ; STerm # Po MEETEI MAYEK CHEIKHEI -FE52 ; STerm # Po SMALL FULL STOP -FE56..FE57 ; STerm # Po [2] SMALL QUESTION MARK..SMALL EXCLAMATION MARK -FF01 ; STerm # Po FULLWIDTH EXCLAMATION MARK -FF0E ; STerm # Po FULLWIDTH FULL STOP -FF1F ; STerm # Po FULLWIDTH QUESTION MARK -FF61 ; STerm # Po HALFWIDTH IDEOGRAPHIC FULL STOP -10A56..10A57 ; STerm # Po [2] KHAROSHTHI PUNCTUATION DANDA..KHAROSHTHI PUNCTUATION DOUBLE DANDA -11047..11048 ; STerm # Po [2] BRAHMI DANDA..BRAHMI DOUBLE DANDA -110BE..110C1 ; STerm # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA -11141..11143 ; STerm # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK -111C5..111C6 ; STerm # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA -111CD ; STerm # Po SHARADA SUTRA MARK -111DE..111DF ; STerm # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2 -11238..11239 ; STerm # Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA -1123B..1123C ; STerm # Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK -112A9 ; STerm # Po MULTANI SECTION MARK -115C2..115C3 ; STerm # Po [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA -115C9..115D7 ; STerm # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES -11641..11642 ; STerm # Po [2] MODI DANDA..MODI DOUBLE DANDA -1173C..1173E ; STerm # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI -16A6E..16A6F ; STerm # Po [2] MRO DANDA..MRO DOUBLE DANDA -16AF5 ; STerm # Po BASSA VAH FULL STOP -16B37..16B38 ; STerm # Po [2] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS TSHAB CEEB -16B44 ; STerm # Po PAHAWH HMONG SIGN XAUS -1BC9F ; STerm # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP -1DA88 ; STerm # Po SIGNWRITING FULL STOP +0021 ; Sentence_Terminal # Po EXCLAMATION MARK +002E ; Sentence_Terminal # Po FULL STOP +003F ; Sentence_Terminal # Po QUESTION MARK +0589 ; Sentence_Terminal # Po ARMENIAN FULL STOP +061F ; Sentence_Terminal # Po ARABIC QUESTION MARK +06D4 ; Sentence_Terminal # Po ARABIC FULL STOP +0700..0702 ; Sentence_Terminal # Po [3] SYRIAC END OF PARAGRAPH..SYRIAC SUBLINEAR FULL STOP +07F9 ; Sentence_Terminal # Po NKO EXCLAMATION MARK +0964..0965 ; Sentence_Terminal # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA +104A..104B ; Sentence_Terminal # Po [2] MYANMAR SIGN LITTLE SECTION..MYANMAR SIGN SECTION +1362 ; Sentence_Terminal # Po ETHIOPIC FULL STOP +1367..1368 ; Sentence_Terminal # Po [2] ETHIOPIC QUESTION MARK..ETHIOPIC PARAGRAPH SEPARATOR +166E ; Sentence_Terminal # Po CANADIAN SYLLABICS FULL STOP +1735..1736 ; Sentence_Terminal # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION +1803 ; Sentence_Terminal # Po MONGOLIAN FULL STOP +1809 ; Sentence_Terminal # Po MONGOLIAN MANCHU FULL STOP +1944..1945 ; Sentence_Terminal # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK +1AA8..1AAB ; Sentence_Terminal # Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU +1B5A..1B5B ; Sentence_Terminal # Po [2] BALINESE PANTI..BALINESE PAMADA +1B5E..1B5F ; Sentence_Terminal # Po [2] BALINESE CARIK SIKI..BALINESE CARIK PAREREN +1C3B..1C3C ; Sentence_Terminal # Po [2] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION NYET THYOOM TA-ROL +1C7E..1C7F ; Sentence_Terminal # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD +203C..203D ; Sentence_Terminal # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG +2047..2049 ; Sentence_Terminal # Po [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK +2E2E ; Sentence_Terminal # Po REVERSED QUESTION MARK +2E3C ; Sentence_Terminal # Po STENOGRAPHIC FULL STOP +3002 ; Sentence_Terminal # Po IDEOGRAPHIC FULL STOP +A4FF ; Sentence_Terminal # Po LISU PUNCTUATION FULL STOP +A60E..A60F ; Sentence_Terminal # Po [2] VAI FULL STOP..VAI QUESTION MARK +A6F3 ; Sentence_Terminal # Po BAMUM FULL STOP +A6F7 ; Sentence_Terminal # Po BAMUM QUESTION MARK +A876..A877 ; Sentence_Terminal # Po [2] PHAGS-PA MARK SHAD..PHAGS-PA MARK DOUBLE SHAD +A8CE..A8CF ; Sentence_Terminal # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA +A92F ; Sentence_Terminal # Po KAYAH LI SIGN SHYA +A9C8..A9C9 ; Sentence_Terminal # Po [2] JAVANESE PADA LINGSA..JAVANESE PADA LUNGSI +AA5D..AA5F ; Sentence_Terminal # Po [3] CHAM PUNCTUATION DANDA..CHAM PUNCTUATION TRIPLE DANDA +AAF0..AAF1 ; Sentence_Terminal # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM +ABEB ; Sentence_Terminal # Po MEETEI MAYEK CHEIKHEI +FE52 ; Sentence_Terminal # Po SMALL FULL STOP +FE56..FE57 ; Sentence_Terminal # Po [2] SMALL QUESTION MARK..SMALL EXCLAMATION MARK +FF01 ; Sentence_Terminal # Po FULLWIDTH EXCLAMATION MARK +FF0E ; Sentence_Terminal # Po FULLWIDTH FULL STOP +FF1F ; Sentence_Terminal # Po FULLWIDTH QUESTION MARK +FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP +10A56..10A57 ; Sentence_Terminal # Po [2] KHAROSHTHI PUNCTUATION DANDA..KHAROSHTHI PUNCTUATION DOUBLE DANDA +11047..11048 ; Sentence_Terminal # Po [2] BRAHMI DANDA..BRAHMI DOUBLE DANDA +110BE..110C1 ; Sentence_Terminal # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA +11141..11143 ; Sentence_Terminal # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK +111C5..111C6 ; Sentence_Terminal # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA +111CD ; Sentence_Terminal # Po SHARADA SUTRA MARK +111DE..111DF ; Sentence_Terminal # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2 +11238..11239 ; Sentence_Terminal # Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA +1123B..1123C ; Sentence_Terminal # Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK +112A9 ; Sentence_Terminal # Po MULTANI SECTION MARK +1144B..1144C ; Sentence_Terminal # Po [2] NEWA DANDA..NEWA DOUBLE DANDA +115C2..115C3 ; Sentence_Terminal # Po [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA +115C9..115D7 ; Sentence_Terminal # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES +11641..11642 ; Sentence_Terminal # Po [2] MODI DANDA..MODI DOUBLE DANDA +1173C..1173E ; Sentence_Terminal # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI +11A42..11A43 ; Sentence_Terminal # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD +11A9B..11A9C ; Sentence_Terminal # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD +11C41..11C42 ; Sentence_Terminal # Po [2] BHAIKSUKI DANDA..BHAIKSUKI DOUBLE DANDA +16A6E..16A6F ; Sentence_Terminal # Po [2] MRO DANDA..MRO DOUBLE DANDA +16AF5 ; Sentence_Terminal # Po BASSA VAH FULL STOP +16B37..16B38 ; Sentence_Terminal # Po [2] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS TSHAB CEEB +16B44 ; Sentence_Terminal # Po PAHAWH HMONG SIGN XAUS +1BC9F ; Sentence_Terminal # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP +1DA88 ; Sentence_Terminal # Po SIGNWRITING FULL STOP -# Total code points: 120 +# Total code points: 128 # ================================================ @@ -1359,9 +1437,7 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S 239B..23B3 ; Pattern_Syntax # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM 23B4..23DB ; Pattern_Syntax # So [40] TOP SQUARE BRACKET..FUSE 23DC..23E1 ; Pattern_Syntax # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET -23E2..23FA ; Pattern_Syntax # So [25] WHITE TRAPEZIUM..BLACK CIRCLE FOR RECORD -23FB..23FF ; Pattern_Syntax # Cn [5] .. -2400..2426 ; Pattern_Syntax # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO +23E2..2426 ; Pattern_Syntax # So [69] WHITE TRAPEZIUM..SYMBOL FOR SUBSTITUTE FORM TWO 2427..243F ; Pattern_Syntax # Cn [25] .. 2440..244A ; Pattern_Syntax # So [11] OCR HOOK..OCR DOUBLE BACKSLASH 244B..245F ; Pattern_Syntax # Cn [21] .. @@ -1449,8 +1525,8 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S 2BBA..2BBC ; Pattern_Syntax # Cn [3] .. 2BBD..2BC8 ; Pattern_Syntax # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED 2BC9 ; Pattern_Syntax # Cn -2BCA..2BD1 ; Pattern_Syntax # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN -2BD2..2BEB ; Pattern_Syntax # Cn [26] .. +2BCA..2BD2 ; Pattern_Syntax # So [9] TOP HALF BLACK CIRCLE..GROUP MARK +2BD3..2BEB ; Pattern_Syntax # Cn [25] .. 2BEC..2BEF ; Pattern_Syntax # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS 2BF0..2BFF ; Pattern_Syntax # Cn [16] .. 2E00..2E01 ; Pattern_Syntax # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER @@ -1490,7 +1566,8 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S 2E40 ; Pattern_Syntax # Pd DOUBLE HYPHEN 2E41 ; Pattern_Syntax # Po REVERSED COMMA 2E42 ; Pattern_Syntax # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK -2E43..2E7F ; Pattern_Syntax # Cn [61] .. +2E43..2E49 ; Pattern_Syntax # Po [7] DASH WITH LEFT UPTURN..DOUBLE STACKED COMMA +2E4A..2E7F ; Pattern_Syntax # Cn [54] .. 3001..3003 ; Pattern_Syntax # Po [3] IDEOGRAPHIC COMMA..DITTO MARK 3008 ; Pattern_Syntax # Ps LEFT ANGLE BRACKET 3009 ; Pattern_Syntax # Pe RIGHT ANGLE BRACKET @@ -1522,4 +1599,20 @@ FE45..FE46 ; Pattern_Syntax # Po [2] SESAME DOT..WHITE SESAME DOT # Total code points: 2760 +# ================================================ + +0600..0605 ; Prepended_Concatenation_Mark # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE +06DD ; Prepended_Concatenation_Mark # Cf ARABIC END OF AYAH +070F ; Prepended_Concatenation_Mark # Cf SYRIAC ABBREVIATION MARK +08E2 ; Prepended_Concatenation_Mark # Cf ARABIC DISPUTED END OF AYAH +110BD ; Prepended_Concatenation_Mark # Cf KAITHI NUMBER SIGN + +# Total code points: 10 + +# ================================================ + +1F1E6..1F1FF ; Regional_Indicator # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + +# Total code points: 26 + # EOF diff --git a/test/jdk/java/lang/Character/PropertyValueAliases.txt b/test/jdk/java/lang/Character/PropertyValueAliases.txt index 595744668b0..f48bbd49049 100644 --- a/test/jdk/java/lang/Character/PropertyValueAliases.txt +++ b/test/jdk/java/lang/Character/PropertyValueAliases.txt @@ -1,10 +1,11 @@ -# PropertyValueAliases-8.0.0.txt -# Date: 2015-03-11, 22:29:33 GMT [MD] +# PropertyValueAliases-10.0.0.txt +# Date: 2017-05-17, 08:45:34 GMT +# Copyright (c) 2017 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database -# Copyright (c) 1991-2015 Unicode, Inc. -# For terms of use, see http://www.unicode.org/terms_of_use.html -# For documentation, see http://www.unicode.org/reports/tr44/ +# For documentation, see http://www.unicode.org/reports/tr44/ # # This file contains aliases for property values used in the UCD. # These names can be used for XML formats of UCD data, for regular-expression @@ -78,6 +79,8 @@ age; 6.2 ; V6_2 age; 6.3 ; V6_3 age; 7.0 ; V7_0 age; 8.0 ; V8_0 +age; 9.0 ; V9_0 +age; 10.0 ; V10_0 age; NA ; Unassigned # Alphabetic (Alpha) @@ -138,6 +141,7 @@ bpt; o ; Open # Block (blk) +blk; Adlam ; Adlam blk; Aegean_Numbers ; Aegean_Numbers blk; Ahom ; Ahom blk; Alchemical ; Alchemical_Symbols @@ -162,6 +166,7 @@ blk; Bamum_Sup ; Bamum_Supplement blk; Bassa_Vah ; Bassa_Vah blk; Batak ; Batak blk; Bengali ; Bengali +blk; Bhaiksuki ; Bhaiksuki blk; Block_Elements ; Block_Elements blk; Bopomofo ; Bopomofo blk; Bopomofo_Ext ; Bopomofo_Extended @@ -187,6 +192,7 @@ blk; CJK_Ext_B ; CJK_Unified_Ideographs_Extension_B blk; CJK_Ext_C ; CJK_Unified_Ideographs_Extension_C blk; CJK_Ext_D ; CJK_Unified_Ideographs_Extension_D blk; CJK_Ext_E ; CJK_Unified_Ideographs_Extension_E +blk; CJK_Ext_F ; CJK_Unified_Ideographs_Extension_F blk; CJK_Radicals_Sup ; CJK_Radicals_Supplement blk; CJK_Strokes ; CJK_Strokes blk; CJK_Symbols ; CJK_Symbols_And_Punctuation @@ -202,6 +208,7 @@ blk; Cypriot_Syllabary ; Cypriot_Syllabary blk; Cyrillic ; Cyrillic blk; Cyrillic_Ext_A ; Cyrillic_Extended_A blk; Cyrillic_Ext_B ; Cyrillic_Extended_B +blk; Cyrillic_Ext_C ; Cyrillic_Extended_C blk; Cyrillic_Sup ; Cyrillic_Supplement ; Cyrillic_Supplementary blk; Deseret ; Deseret blk; Devanagari ; Devanagari @@ -230,6 +237,7 @@ blk; Geometric_Shapes_Ext ; Geometric_Shapes_Extended blk; Georgian ; Georgian blk; Georgian_Sup ; Georgian_Supplement blk; Glagolitic ; Glagolitic +blk; Glagolitic_Sup ; Glagolitic_Supplement blk; Gothic ; Gothic blk; Grantha ; Grantha blk; Greek ; Greek_And_Coptic @@ -246,6 +254,7 @@ blk; High_PU_Surrogates ; High_Private_Use_Surrogates blk; High_Surrogates ; High_Surrogates blk; Hiragana ; Hiragana blk; IDC ; Ideographic_Description_Characters +blk; Ideographic_Symbols ; Ideographic_Symbols_And_Punctuation blk; Imperial_Aramaic ; Imperial_Aramaic blk; Indic_Number_Forms ; Common_Indic_Number_Forms blk; Inscriptional_Pahlavi ; Inscriptional_Pahlavi @@ -256,6 +265,7 @@ blk; Jamo_Ext_A ; Hangul_Jamo_Extended_A blk; Jamo_Ext_B ; Hangul_Jamo_Extended_B blk; Javanese ; Javanese blk; Kaithi ; Kaithi +blk; Kana_Ext_A ; Kana_Extended_A blk; Kana_Sup ; Kana_Supplement blk; Kanbun ; Kanbun blk; Kangxi ; Kangxi_Radicals @@ -291,6 +301,8 @@ blk; Mahjong ; Mahjong_Tiles blk; Malayalam ; Malayalam blk; Mandaic ; Mandaic blk; Manichaean ; Manichaean +blk; Marchen ; Marchen +blk; Masaram_Gondi ; Masaram_Gondi blk; Math_Alphanum ; Mathematical_Alphanumeric_Symbols blk; Math_Operators ; Mathematical_Operators blk; Meetei_Mayek ; Meetei_Mayek @@ -309,6 +321,7 @@ blk; Modi ; Modi blk; Modifier_Letters ; Spacing_Modifier_Letters blk; Modifier_Tone_Letters ; Modifier_Tone_Letters blk; Mongolian ; Mongolian +blk; Mongolian_Sup ; Mongolian_Supplement blk; Mro ; Mro blk; Multani ; Multani blk; Music ; Musical_Symbols @@ -318,8 +331,10 @@ blk; Myanmar_Ext_B ; Myanmar_Extended_B blk; Nabataean ; Nabataean blk; NB ; No_Block blk; New_Tai_Lue ; New_Tai_Lue +blk; Newa ; Newa blk; NKo ; NKo blk; Number_Forms ; Number_Forms +blk; Nushu ; Nushu blk; OCR ; Optical_Character_Recognition blk; Ogham ; Ogham blk; Ol_Chiki ; Ol_Chiki @@ -332,6 +347,7 @@ blk; Old_South_Arabian ; Old_South_Arabian blk; Old_Turkic ; Old_Turkic blk; Oriya ; Oriya blk; Ornamental_Dingbats ; Ornamental_Dingbats +blk; Osage ; Osage blk; Osmanya ; Osmanya blk; Pahawh_Hmong ; Pahawh_Hmong blk; Palmyrene ; Palmyrene @@ -358,6 +374,7 @@ blk; Sinhala ; Sinhala blk; Sinhala_Archaic_Numbers ; Sinhala_Archaic_Numbers blk; Small_Forms ; Small_Form_Variants blk; Sora_Sompeng ; Sora_Sompeng +blk; Soyombo ; Soyombo blk; Specials ; Specials blk; Sundanese ; Sundanese blk; Sundanese_Sup ; Sundanese_Supplement @@ -373,6 +390,7 @@ blk; Super_And_Sub ; Superscripts_And_Subscripts blk; Sutton_SignWriting ; Sutton_SignWriting blk; Syloti_Nagri ; Syloti_Nagri blk; Syriac ; Syriac +blk; Syriac_Sup ; Syriac_Supplement blk; Tagalog ; Tagalog blk; Tagbanwa ; Tagbanwa blk; Tags ; Tags @@ -382,6 +400,8 @@ blk; Tai_Viet ; Tai_Viet blk; Tai_Xuan_Jing ; Tai_Xuan_Jing_Symbols blk; Takri ; Takri blk; Tamil ; Tamil +blk; Tangut ; Tangut +blk; Tangut_Components ; Tangut_Components blk; Telugu ; Telugu blk; Thaana ; Thaana blk; Thai ; Thai @@ -401,6 +421,7 @@ blk; Warang_Citi ; Warang_Citi blk; Yi_Radicals ; Yi_Radicals blk; Yi_Syllables ; Yi_Syllables blk; Yijing ; Yijing_Hexagram_Symbols +blk; Zanabazar_Square ; Zanabazar_Square # Canonical_Combining_Class (ccc) @@ -650,7 +671,11 @@ Gr_Base; Y ; Yes ; T GCB; CN ; Control GCB; CR ; CR +GCB; EB ; E_Base +GCB; EBG ; E_Base_GAZ +GCB; EM ; E_Modifier GCB; EX ; Extend +GCB; GAZ ; Glue_After_Zwj GCB; L ; L GCB; LF ; LF GCB; LV ; LV @@ -661,6 +686,7 @@ GCB; SM ; SpacingMark GCB; T ; T GCB; V ; V GCB; XX ; Other +GCB; ZWJ ; ZWJ # Grapheme_Extend (Gr_Ext) @@ -723,6 +749,7 @@ Ideo; Y ; Yes ; T # Indic_Positional_Category (InPC) InPC; Bottom ; Bottom +InPC; Bottom_And_Left ; Bottom_And_Left InPC; Bottom_And_Right ; Bottom_And_Right InPC; Left ; Left InPC; Left_And_Right ; Left_And_Right @@ -838,6 +865,9 @@ Join_C; Y ; Yes ; T # Joining_Group (jg) +jg ; African_Feh ; African_Feh +jg ; African_Noon ; African_Noon +jg ; African_Qaf ; African_Qaf jg ; Ain ; Ain jg ; Alaph ; Alaph jg ; Alef ; Alef @@ -864,6 +894,17 @@ jg ; Khaph ; Khaph jg ; Knotted_Heh ; Knotted_Heh jg ; Lam ; Lam jg ; Lamadh ; Lamadh +jg ; Malayalam_Bha ; Malayalam_Bha +jg ; Malayalam_Ja ; Malayalam_Ja +jg ; Malayalam_Lla ; Malayalam_Lla +jg ; Malayalam_Llla ; Malayalam_Llla +jg ; Malayalam_Nga ; Malayalam_Nga +jg ; Malayalam_Nna ; Malayalam_Nna +jg ; Malayalam_Nnna ; Malayalam_Nnna +jg ; Malayalam_Nya ; Malayalam_Nya +jg ; Malayalam_Ra ; Malayalam_Ra +jg ; Malayalam_Ssa ; Malayalam_Ssa +jg ; Malayalam_Tta ; Malayalam_Tta jg ; Manichaean_Aleph ; Manichaean_Aleph jg ; Manichaean_Ayin ; Manichaean_Ayin jg ; Manichaean_Beth ; Manichaean_Beth @@ -948,6 +989,8 @@ lb ; CL ; Close_Punctuation lb ; CM ; Combining_Mark lb ; CP ; Close_Parenthesis lb ; CR ; Carriage_Return +lb ; EB ; E_Base +lb ; EM ; E_Modifier lb ; EX ; Exclamation lb ; GL ; Glue lb ; H2 ; H2 @@ -976,6 +1019,7 @@ lb ; SY ; Break_Symbols lb ; WJ ; Word_Joiner lb ; XX ; Unknown lb ; ZW ; ZWSpace +lb ; ZWJ ; ZWJ # Logical_Order_Exception (LOE) @@ -1096,6 +1140,11 @@ Pat_Syn; Y ; Yes ; T Pat_WS; N ; No ; F ; False Pat_WS; Y ; Yes ; T ; True +# Prepended_Concatenation_Mark (PCM) + +PCM; N ; No ; F ; False +PCM; Y ; Yes ; T ; True + # Quotation_Mark (QMark) QMark; N ; No ; F ; False @@ -1106,13 +1155,14 @@ QMark; Y ; Yes ; T Radical; N ; No ; F ; False Radical; Y ; Yes ; T ; True -# STerm (STerm) +# Regional_Indicator (RI) -STerm; N ; No ; F ; False -STerm; Y ; Yes ; T ; True +RI ; N ; No ; F ; False +RI ; Y ; Yes ; T ; True # Script (sc) +sc ; Adlm ; Adlam sc ; Aghb ; Caucasian_Albanian sc ; Ahom ; Ahom sc ; Arab ; Arabic @@ -1124,6 +1174,7 @@ sc ; Bamu ; Bamum sc ; Bass ; Bassa_Vah sc ; Batk ; Batak sc ; Beng ; Bengali +sc ; Bhks ; Bhaiksuki sc ; Bopo ; Bopomofo sc ; Brah ; Brahmi sc ; Brai ; Braille @@ -1145,6 +1196,7 @@ sc ; Elba ; Elbasan sc ; Ethi ; Ethiopic sc ; Geor ; Georgian sc ; Glag ; Glagolitic +sc ; Gonm ; Masaram_Gondi sc ; Goth ; Gothic sc ; Gran ; Grantha sc ; Grek ; Greek @@ -1182,6 +1234,7 @@ sc ; Lydi ; Lydian sc ; Mahj ; Mahajani sc ; Mand ; Mandaic sc ; Mani ; Manichaean +sc ; Marc ; Marchen sc ; Mend ; Mende_Kikakui sc ; Merc ; Meroitic_Cursive sc ; Mero ; Meroitic_Hieroglyphs @@ -1194,11 +1247,14 @@ sc ; Mult ; Multani sc ; Mymr ; Myanmar sc ; Narb ; Old_North_Arabian sc ; Nbat ; Nabataean +sc ; Newa ; Newa sc ; Nkoo ; Nko +sc ; Nshu ; Nushu sc ; Ogam ; Ogham sc ; Olck ; Ol_Chiki sc ; Orkh ; Old_Turkic sc ; Orya ; Oriya +sc ; Osge ; Osage sc ; Osma ; Osmanya sc ; Palm ; Palmyrene sc ; Pauc ; Pau_Cin_Hau @@ -1221,6 +1277,7 @@ sc ; Sidd ; Siddham sc ; Sind ; Khudawadi sc ; Sinh ; Sinhala sc ; Sora ; Sora_Sompeng +sc ; Soyo ; Soyombo sc ; Sund ; Sundanese sc ; Sylo ; Syloti_Nagri sc ; Syrc ; Syriac @@ -1229,6 +1286,7 @@ sc ; Takr ; Takri sc ; Tale ; Tai_Le sc ; Talu ; New_Tai_Lue sc ; Taml ; Tamil +sc ; Tang ; Tangut sc ; Tavt ; Tai_Viet sc ; Telu ; Telugu sc ; Tfng ; Tifinagh @@ -1243,6 +1301,7 @@ sc ; Wara ; Warang_Citi sc ; Xpeo ; Old_Persian sc ; Xsux ; Cuneiform sc ; Yiii ; Yi +sc ; Zanb ; Zanabazar_Square sc ; Zinh ; Inherited ; Qaai sc ; Zyyy ; Common sc ; Zzzz ; Unknown @@ -1269,6 +1328,11 @@ SB ; ST ; STerm SB ; UP ; Upper SB ; XX ; Other +# Sentence_Terminal (STerm) + +STerm; N ; No ; F ; False +STerm; Y ; Yes ; T ; True + # Simple_Case_Folding (scf) # @missing: 0000..10FFFF; Simple_Case_Folding; @@ -1322,6 +1386,13 @@ Upper; Y ; Yes ; T VS ; N ; No ; F ; False VS ; Y ; Yes ; T ; True +# Vertical_Orientation (vo) + +vo ; R ; Rotated +vo ; Tr ; Transformed_Rotated +vo ; Tu ; Transformed_Upright +vo ; U ; Upright + # White_Space (WSpace) WSpace; N ; No ; F ; False @@ -1331,9 +1402,13 @@ WSpace; Y ; Yes ; T WB ; CR ; CR WB ; DQ ; Double_Quote +WB ; EB ; E_Base +WB ; EBG ; E_Base_GAZ +WB ; EM ; E_Modifier WB ; EX ; ExtendNumLet WB ; Extend ; Extend WB ; FO ; Format +WB ; GAZ ; Glue_After_Zwj WB ; HL ; Hebrew_Letter WB ; KA ; Katakana WB ; LE ; ALetter @@ -1346,6 +1421,7 @@ WB ; NU ; Numeric WB ; RI ; Regional_Indicator WB ; SQ ; Single_Quote WB ; XX ; Other +WB ; ZWJ ; ZWJ # XID_Continue (XIDC) diff --git a/test/jdk/java/lang/Character/Scripts.txt b/test/jdk/java/lang/Character/Scripts.txt index 7e42740407c..80430b32a8f 100644 --- a/test/jdk/java/lang/Character/Scripts.txt +++ b/test/jdk/java/lang/Character/Scripts.txt @@ -1,10 +1,11 @@ -# Scripts-8.0.0.txt -# Date: 2015-03-11, 22:29:42 GMT [MD] +# Scripts-10.0.0.txt +# Date: 2017-03-11, 06:40:37 GMT +# Copyright (c) 2017 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html # # Unicode Character Database -# Copyright (c) 1991-2015 Unicode, Inc. -# For terms of use, see http://www.unicode.org/terms_of_use.html -# For documentation, see http://www.unicode.org/reports/tr44/ +# For documentation, see http://www.unicode.org/reports/tr44/ # For more information, see: # UAX #24, Unicode Script Property: http://www.unicode.org/reports/tr24/ # Especially the sections: @@ -92,10 +93,10 @@ 0605 ; Common # Cf ARABIC NUMBER MARK ABOVE 060C ; Common # Po ARABIC COMMA 061B ; Common # Po ARABIC SEMICOLON -061C ; Common # Cf ARABIC LETTER MARK 061F ; Common # Po ARABIC QUESTION MARK 0640 ; Common # Lm ARABIC TATWEEL 06DD ; Common # Cf ARABIC END OF AYAH +08E2 ; Common # Cf ARABIC DISPUTED END OF AYAH 0964..0965 ; Common # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA 0E3F ; Common # Sc THAI CURRENCY SYMBOL BAHT 0FD5..0FD8 ; Common # So [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS @@ -110,6 +111,7 @@ 1CEE..1CF1 ; Common # Lo [4] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ANUSVARA UBHAYATO MUKHA 1CF2..1CF3 ; Common # Mc [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIGN ROTATED ARDHAVISARGA 1CF5..1CF6 ; Common # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA +1CF7 ; Common # Mc VEDIC SIGN ATIKRAMA 2000..200A ; Common # Zs [11] EN QUAD..HAIR SPACE 200B ; Common # Cf ZERO WIDTH SPACE 200E..200F ; Common # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK @@ -153,7 +155,7 @@ 208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN 208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS 208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS -20A0..20BE ; Common # Sc [31] EURO-CURRENCY SIGN..LARI SIGN +20A0..20BF ; Common # Sc [32] EURO-CURRENCY SIGN..BITCOIN SIGN 2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT 2102 ; Common # L& DOUBLE-STRUCK CAPITAL C 2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA @@ -223,8 +225,7 @@ 239B..23B3 ; Common # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM 23B4..23DB ; Common # So [40] TOP SQUARE BRACKET..FUSE 23DC..23E1 ; Common # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET -23E2..23FA ; Common # So [25] WHITE TRAPEZIUM..BLACK CIRCLE FOR RECORD -2400..2426 ; Common # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO +23E2..2426 ; Common # So [69] WHITE TRAPEZIUM..SYMBOL FOR SUBSTITUTE FORM TWO 2440..244A ; Common # So [11] OCR HOOK..OCR DOUBLE BACKSLASH 2460..249B ; Common # No [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP 249C..24E9 ; Common # So [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z @@ -309,7 +310,7 @@ 2B76..2B95 ; Common # So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW 2B98..2BB9 ; Common # So [34] THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..UP ARROWHEAD IN A RECTANGLE BOX 2BBD..2BC8 ; Common # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED -2BCA..2BD1 ; Common # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN +2BCA..2BD2 ; Common # So [9] TOP HALF BLACK CIRCLE..GROUP MARK 2BEC..2BEF ; Common # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS 2E00..2E01 ; Common # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER 2E02 ; Common # Pi LEFT SUBSTITUTION BRACKET @@ -348,6 +349,7 @@ 2E40 ; Common # Pd DOUBLE HYPHEN 2E41 ; Common # Po REVERSED COMMA 2E42 ; Common # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK +2E43..2E49 ; Common # Po [7] DASH WITH LEFT UPTURN..DOUBLE STACKED COMMA 2FF0..2FFB ; Common # So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID 3000 ; Common # Zs IDEOGRAPHIC SPACE 3001..3003 ; Common # Po [3] IDEOGRAPHIC COMMA..DITTO MARK @@ -572,19 +574,18 @@ FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHAR 1F100..1F10C ; Common # No [13] DIGIT ZERO FULL STOP..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO 1F110..1F12E ; Common # So [31] PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED WZ 1F130..1F16B ; Common # So [60] SQUARED LATIN CAPITAL LETTER A..RAISED MD SIGN -1F170..1F19A ; Common # So [43] NEGATIVE SQUARED LATIN CAPITAL LETTER A..SQUARED VS +1F170..1F1AC ; Common # So [61] NEGATIVE SQUARED LATIN CAPITAL LETTER A..SQUARED VOD 1F1E6..1F1FF ; Common # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z 1F201..1F202 ; Common # So [2] SQUARED KATAKANA KOKO..SQUARED KATAKANA SA -1F210..1F23A ; Common # So [43] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-55B6 +1F210..1F23B ; Common # So [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D 1F240..1F248 ; Common # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 1F250..1F251 ; Common # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT +1F260..1F265 ; Common # So [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI 1F300..1F3FA ; Common # So [251] CYCLONE..AMPHORA 1F3FB..1F3FF ; Common # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 -1F400..1F579 ; Common # So [378] RAT..JOYSTICK -1F57B..1F5A3 ; Common # So [41] LEFT HAND TELEPHONE RECEIVER..BLACK DOWN POINTING BACKHAND INDEX -1F5A5..1F6D0 ; Common # So [300] DESKTOP COMPUTER..PLACE OF WORSHIP +1F400..1F6D4 ; Common # So [725] RAT..PAGODA 1F6E0..1F6EC ; Common # So [13] HAMMER AND WRENCH..AIRPLANE ARRIVING -1F6F0..1F6F3 ; Common # So [4] SATELLITE..PASSENGER SHIP +1F6F0..1F6F8 ; Common # So [9] SATELLITE..FLYING SAUCER 1F700..1F773 ; Common # So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE 1F780..1F7D4 ; Common # So [85] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..HEAVY TWELVE POINTED PINWHEEL STAR 1F800..1F80B ; Common # So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD @@ -592,13 +593,17 @@ FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHAR 1F850..1F859 ; Common # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW 1F860..1F887 ; Common # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW 1F890..1F8AD ; Common # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS -1F910..1F918 ; Common # So [9] ZIPPER-MOUTH FACE..SIGN OF THE HORNS -1F980..1F984 ; Common # So [5] CRAB..UNICORN FACE +1F900..1F90B ; Common # So [12] CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT +1F910..1F93E ; Common # So [47] ZIPPER-MOUTH FACE..HANDBALL +1F940..1F94C ; Common # So [13] WILTED FLOWER..CURLING STONE +1F950..1F96B ; Common # So [28] CROISSANT..CANNED FOOD +1F980..1F997 ; Common # So [24] CRAB..CRICKET 1F9C0 ; Common # So CHEESE WEDGE +1F9D0..1F9E6 ; Common # So [23] FACE WITH MONOCLE..SOCKS E0001 ; Common # Cf LANGUAGE TAG E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG -# Total code points: 7179 +# Total code points: 7363 # ================================================ @@ -641,7 +646,7 @@ A770 ; Latin # Lm MODIFIER LETTER US A771..A787 ; Latin # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T A78B..A78E ; Latin # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT A78F ; Latin # Lo LATIN LETTER SINOLOGICAL DOT -A790..A7AD ; Latin # L& [30] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN CAPITAL LETTER L WITH BELT +A790..A7AE ; Latin # L& [31] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN CAPITAL LETTER SMALL CAPITAL I A7B0..A7B7 ; Latin # L& [8] LATIN CAPITAL LETTER TURNED K..LATIN SMALL LETTER OMEGA A7F7 ; Latin # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I A7F8..A7F9 ; Latin # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE @@ -654,7 +659,7 @@ FB00..FB06 ; Latin # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE S FF21..FF3A ; Latin # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z FF41..FF5A ; Latin # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z -# Total code points: 1349 +# Total code points: 1350 # ================================================ @@ -708,13 +713,13 @@ AB65 ; Greek # L& GREEK LETTER SMALL CAPITAL OMEGA 10175..10178 ; Greek # No [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN 10179..10189 ; Greek # So [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN 1018A..1018B ; Greek # No [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN -1018C ; Greek # So GREEK SINUSOID SIGN +1018C..1018E ; Greek # So [3] GREEK SINUSOID SIGN..NOMISMA SIGN 101A0 ; Greek # So GREEK SYMBOL TAU RHO 1D200..1D241 ; Greek # So [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54 1D242..1D244 ; Greek # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME 1D245 ; Greek # So GREEK MUSICAL LEIMMA -# Total code points: 516 +# Total code points: 518 # ================================================ @@ -724,6 +729,7 @@ AB65 ; Greek # L& GREEK LETTER SMALL CAPITAL OMEGA 0487 ; Cyrillic # Mn COMBINING CYRILLIC POKRYTIE 0488..0489 ; Cyrillic # Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN 048A..052F ; Cyrillic # L& [166] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER EL WITH DESCENDER +1C80..1C88 ; Cyrillic # L& [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK 1D2B ; Cyrillic # L& CYRILLIC LETTER SMALL CAPITAL EL 1D78 ; Cyrillic # Lm MODIFIER LETTER CYRILLIC EN 2DE0..2DFF ; Cyrillic # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS @@ -740,7 +746,7 @@ A69C..A69D ; Cyrillic # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER A69E..A69F ; Cyrillic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E FE2E..FE2F ; Cyrillic # Mn [2] COMBINING CYRILLIC TITLO LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF -# Total code points: 434 +# Total code points: 443 # ================================================ @@ -791,6 +797,7 @@ FB46..FB4F ; Hebrew # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATU 060D ; Arabic # Po ARABIC DATE SEPARATOR 060E..060F ; Arabic # So [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA 0610..061A ; Arabic # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA +061C ; Arabic # Cf ARABIC LETTER MARK 061E ; Arabic # Po ARABIC TRIPLE DOT PUNCTUATION MARK 0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE 0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH @@ -815,6 +822,8 @@ FB46..FB4F ; Hebrew # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATU 06FF ; Arabic # Lo ARABIC LETTER HEH WITH INVERTED V 0750..077F ; Arabic # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE 08A0..08B4 ; Arabic # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW +08B6..08BD ; Arabic # Lo [8] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER AFRICAN NOON +08D4..08E1 ; Arabic # Mn [14] ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH SIGN SAFHA 08E3..08FF ; Arabic # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA FB50..FBB1 ; Arabic # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM FBB2..FBC1 ; Arabic # Sk [16] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW @@ -862,7 +871,7 @@ FE76..FEFC ; Arabic # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LA 1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN 1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL -# Total code points: 1257 +# Total code points: 1280 # ================================================ @@ -873,8 +882,9 @@ FE76..FEFC ; Arabic # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LA 0712..072F ; Syriac # Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH 0730..074A ; Syriac # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH 074D..074F ; Syriac # Lo [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE +0860..086A ; Syriac # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA -# Total code points: 77 +# Total code points: 88 # ================================================ @@ -944,8 +954,10 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM 09F4..09F9 ; Bengali # No [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN 09FA ; Bengali # So BENGALI ISSHAR 09FB ; Bengali # Sc BENGALI GANDA MARK +09FC ; Bengali # Lo BENGALI LETTER VEDIC ANUSVARA +09FD ; Bengali # Po BENGALI ABBREVIATION SIGN -# Total code points: 93 +# Total code points: 95 # ================================================ @@ -998,8 +1010,9 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM 0AF0 ; Gujarati # Po GUJARATI ABBREVIATION SIGN 0AF1 ; Gujarati # Sc GUJARATI RUPEE SIGN 0AF9 ; Gujarati # Lo GUJARATI LETTER ZHA +0AFA..0AFF ; Gujarati # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE -# Total code points: 85 +# Total code points: 91 # ================================================ @@ -1086,6 +1099,7 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM # ================================================ +0C80 ; Kannada # Lo KANNADA SIGN SPACING CANDRABINDU 0C81 ; Kannada # Mn KANNADA SIGN CANDRABINDU 0C82..0C83 ; Kannada # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA 0C85..0C8C ; Kannada # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L @@ -1109,15 +1123,16 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM 0CE6..0CEF ; Kannada # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE 0CF1..0CF2 ; Kannada # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA -# Total code points: 87 +# Total code points: 88 # ================================================ -0D01 ; Malayalam # Mn MALAYALAM SIGN CANDRABINDU +0D00..0D01 ; Malayalam # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU 0D02..0D03 ; Malayalam # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA 0D05..0D0C ; Malayalam # Lo [8] MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC L 0D0E..0D10 ; Malayalam # Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI 0D12..0D3A ; Malayalam # Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA +0D3B..0D3C ; Malayalam # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA 0D3D ; Malayalam # Lo MALAYALAM SIGN AVAGRAHA 0D3E..0D40 ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II 0D41..0D44 ; Malayalam # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR @@ -1125,15 +1140,18 @@ A8FD ; Devanagari # Lo DEVANAGARI JAIN OM 0D4A..0D4C ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU 0D4D ; Malayalam # Mn MALAYALAM SIGN VIRAMA 0D4E ; Malayalam # Lo MALAYALAM LETTER DOT REPH +0D4F ; Malayalam # So MALAYALAM SIGN PARA +0D54..0D56 ; Malayalam # Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL 0D57 ; Malayalam # Mc MALAYALAM AU LENGTH MARK +0D58..0D5E ; Malayalam # No [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH 0D5F..0D61 ; Malayalam # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL 0D62..0D63 ; Malayalam # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL 0D66..0D6F ; Malayalam # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE -0D70..0D75 ; Malayalam # No [6] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE QUARTERS +0D70..0D78 ; Malayalam # No [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS 0D79 ; Malayalam # So MALAYALAM DATE MARK 0D7A..0D7F ; Malayalam # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K -# Total code points: 100 +# Total code points: 117 # ================================================ @@ -1436,21 +1454,24 @@ AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETT 1820..1842 ; Mongolian # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI 1843 ; Mongolian # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN 1844..1877 ; Mongolian # Lo [52] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER MANCHU ZHA -1880..18A8 ; Mongolian # Lo [41] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER MANCHU ALI GALI BHA +1880..1884 ; Mongolian # Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA +1885..1886 ; Mongolian # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA +1887..18A8 ; Mongolian # Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA 18A9 ; Mongolian # Mn MONGOLIAN LETTER ALI GALI DAGALGA 18AA ; Mongolian # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA +11660..1166C ; Mongolian # Po [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT -# Total code points: 153 +# Total code points: 166 # ================================================ 3041..3096 ; Hiragana # Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE 309D..309E ; Hiragana # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK 309F ; Hiragana # Lo HIRAGANA DIGRAPH YORI -1B001 ; Hiragana # Lo HIRAGANA LETTER ARCHAIC YE +1B001..1B11E ; Hiragana # Lo [286] HIRAGANA LETTER ARCHAIC YE..HENTAIGANA LETTER N-MU-MO-2 1F200 ; Hiragana # So SQUARE HIRAGANA HOKA -# Total code points: 91 +# Total code points: 376 # ================================================ @@ -1469,10 +1490,10 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK # ================================================ 02EA..02EB ; Bopomofo # Sk [2] MODIFIER LETTER YIN DEPARTING TONE MARK..MODIFIER LETTER YANG DEPARTING TONE MARK -3105..312D ; Bopomofo # Lo [41] BOPOMOFO LETTER B..BOPOMOFO LETTER IH +3105..312E ; Bopomofo # Lo [42] BOPOMOFO LETTER B..BOPOMOFO LETTER O WITH DOT ABOVE 31A0..31BA ; Bopomofo # Lo [27] BOPOMOFO LETTER BU..BOPOMOFO LETTER ZY -# Total code points: 70 +# Total code points: 71 # ================================================ @@ -1485,16 +1506,17 @@ FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAK 3038..303A ; Han # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY 303B ; Han # Lm VERTICAL IDEOGRAPHIC ITERATION MARK 3400..4DB5 ; Han # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5 -4E00..9FD5 ; Han # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5 +4E00..9FEA ; Han # Lo [20971] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEA F900..FA6D ; Han # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D FA70..FAD9 ; Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 20000..2A6D6 ; Han # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6 2A700..2B734 ; Han # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734 2B740..2B81D ; Han # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D 2B820..2CEA1 ; Han # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 +2CEB0..2EBE0 ; Han # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 2F800..2FA1D ; Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D -# Total code points: 81734 +# Total code points: 89228 # ================================================ @@ -1509,8 +1531,9 @@ A490..A4C6 ; Yi # So [55] YI RADICAL QOT..YI RADICAL KE 10300..1031F ; Old_Italic # Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS 10320..10323 ; Old_Italic # No [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY +1032D..1032F ; Old_Italic # Lo [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE -# Total code points: 36 +# Total code points: 39 # ================================================ @@ -1542,8 +1565,8 @@ A490..A4C6 ; Yi # So [55] YI RADICAL QOT..YI RADICAL KE 1CED ; Inherited # Mn VEDIC SIGN TIRYAK 1CF4 ; Inherited # Mn VEDIC TONE CANDRA ABOVE 1CF8..1CF9 ; Inherited # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE -1DC0..1DF5 ; Inherited # Mn [54] COMBINING DOTTED GRAVE ACCENT..COMBINING UP TACK ABOVE -1DFC..1DFF ; Inherited # Mn [4] COMBINING DOUBLE INVERTED BREVE BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +1DC0..1DF9 ; Inherited # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW +1DFB..1DFF ; Inherited # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW 200C..200D ; Inherited # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER 20D0..20DC ; Inherited # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE 20DD..20E0 ; Inherited # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH @@ -1562,7 +1585,7 @@ FE20..FE2D ; Inherited # Mn [14] COMBINING LIGATURE LEFT HALF..COMBINING CON 1D1AA..1D1AD ; Inherited # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 -# Total code points: 563 +# Total code points: 568 # ================================================ @@ -1705,8 +1728,13 @@ E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-2 2C00..2C2E ; Glagolitic # L& [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE 2C30..2C5E ; Glagolitic # L& [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE +1E000..1E006 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE +1E008..1E018 ; Glagolitic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU +1E01B..1E021 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI +1E023..1E024 ; Glagolitic # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS +1E026..1E02A ; Glagolitic # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA -# Total code points: 94 +# Total code points: 132 # ================================================ @@ -1872,11 +1900,11 @@ A62A..A62B ; Vai # Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO A880..A881 ; Saurashtra # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA A882..A8B3 ; Saurashtra # Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA A8B4..A8C3 ; Saurashtra # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU -A8C4 ; Saurashtra # Mn SAURASHTRA SIGN VIRAMA +A8C4..A8C5 ; Saurashtra # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU A8CE..A8CF ; Saurashtra # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA A8D0..A8D9 ; Saurashtra # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE -# Total code points: 81 +# Total code points: 82 # ================================================ @@ -2314,8 +2342,9 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI 11235 ; Khojki # Mc KHOJKI SIGN VIRAMA 11236..11237 ; Khojki # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA 11238..1123D ; Khojki # Po [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN +1123E ; Khojki # Mn KHOJKI SIGN SUKUN -# Total code points: 61 +# Total code points: 62 # ================================================ @@ -2536,4 +2565,129 @@ ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DI # Total code points: 672 +# ================================================ + +1E900..1E943 ; Adlam # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA +1E944..1E94A ; Adlam # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA +1E950..1E959 ; Adlam # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE +1E95E..1E95F ; Adlam # Po [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK + +# Total code points: 87 + +# ================================================ + +11C00..11C08 ; Bhaiksuki # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L +11C0A..11C2E ; Bhaiksuki # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA +11C2F ; Bhaiksuki # Mc BHAIKSUKI VOWEL SIGN AA +11C30..11C36 ; Bhaiksuki # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L +11C38..11C3D ; Bhaiksuki # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA +11C3E ; Bhaiksuki # Mc BHAIKSUKI SIGN VISARGA +11C3F ; Bhaiksuki # Mn BHAIKSUKI SIGN VIRAMA +11C40 ; Bhaiksuki # Lo BHAIKSUKI SIGN AVAGRAHA +11C41..11C45 ; Bhaiksuki # Po [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2 +11C50..11C59 ; Bhaiksuki # Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE +11C5A..11C6C ; Bhaiksuki # No [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK + +# Total code points: 97 + +# ================================================ + +11C70..11C71 ; Marchen # Po [2] MARCHEN HEAD MARK..MARCHEN MARK SHAD +11C72..11C8F ; Marchen # Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A +11C92..11CA7 ; Marchen # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA +11CA9 ; Marchen # Mc MARCHEN SUBJOINED LETTER YA +11CAA..11CB0 ; Marchen # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA +11CB1 ; Marchen # Mc MARCHEN VOWEL SIGN I +11CB2..11CB3 ; Marchen # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E +11CB4 ; Marchen # Mc MARCHEN VOWEL SIGN O +11CB5..11CB6 ; Marchen # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + +# Total code points: 68 + +# ================================================ + +11400..11434 ; Newa # Lo [53] NEWA LETTER A..NEWA LETTER HA +11435..11437 ; Newa # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II +11438..1143F ; Newa # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI +11440..11441 ; Newa # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU +11442..11444 ; Newa # Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA +11445 ; Newa # Mc NEWA SIGN VISARGA +11446 ; Newa # Mn NEWA SIGN NUKTA +11447..1144A ; Newa # Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI +1144B..1144F ; Newa # Po [5] NEWA DANDA..NEWA ABBREVIATION SIGN +11450..11459 ; Newa # Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE +1145B ; Newa # Po NEWA PLACEHOLDER MARK +1145D ; Newa # Po NEWA INSERTION SIGN + +# Total code points: 92 + +# ================================================ + +104B0..104D3 ; Osage # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA +104D8..104FB ; Osage # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA + +# Total code points: 72 + +# ================================================ + +16FE0 ; Tangut # Lm TANGUT ITERATION MARK +17000..187EC ; Tangut # Lo [6125] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187EC +18800..18AF2 ; Tangut # Lo [755] TANGUT COMPONENT-001..TANGUT COMPONENT-755 + +# Total code points: 6881 + +# ================================================ + +11D00..11D06 ; Masaram_Gondi # Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E +11D08..11D09 ; Masaram_Gondi # Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O +11D0B..11D30 ; Masaram_Gondi # Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA +11D31..11D36 ; Masaram_Gondi # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R +11D3A ; Masaram_Gondi # Mn MASARAM GONDI VOWEL SIGN E +11D3C..11D3D ; Masaram_Gondi # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O +11D3F..11D45 ; Masaram_Gondi # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA +11D46 ; Masaram_Gondi # Lo MASARAM GONDI REPHA +11D47 ; Masaram_Gondi # Mn MASARAM GONDI RA-KARA +11D50..11D59 ; Masaram_Gondi # Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE + +# Total code points: 75 + +# ================================================ + +16FE1 ; Nushu # Lm NUSHU ITERATION MARK +1B170..1B2FB ; Nushu # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB + +# Total code points: 397 + +# ================================================ + +11A50 ; Soyombo # Lo SOYOMBO LETTER A +11A51..11A56 ; Soyombo # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE +11A57..11A58 ; Soyombo # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU +11A59..11A5B ; Soyombo # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK +11A5C..11A83 ; Soyombo # Lo [40] SOYOMBO LETTER KA..SOYOMBO LETTER KSSA +11A86..11A89 ; Soyombo # Lo [4] SOYOMBO CLUSTER-INITIAL LETTER RA..SOYOMBO CLUSTER-INITIAL LETTER SA +11A8A..11A96 ; Soyombo # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA +11A97 ; Soyombo # Mc SOYOMBO SIGN VISARGA +11A98..11A99 ; Soyombo # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER +11A9A..11A9C ; Soyombo # Po [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD +11A9E..11AA2 ; Soyombo # Po [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2 + +# Total code points: 80 + +# ================================================ + +11A00 ; Zanabazar_Square # Lo ZANABAZAR SQUARE LETTER A +11A01..11A06 ; Zanabazar_Square # Mn [6] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL SIGN O +11A07..11A08 ; Zanabazar_Square # Mc [2] ZANABAZAR SQUARE VOWEL SIGN AI..ZANABAZAR SQUARE VOWEL SIGN AU +11A09..11A0A ; Zanabazar_Square # Mn [2] ZANABAZAR SQUARE VOWEL SIGN REVERSED I..ZANABAZAR SQUARE VOWEL LENGTH MARK +11A0B..11A32 ; Zanabazar_Square # Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA +11A33..11A38 ; Zanabazar_Square # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA +11A39 ; Zanabazar_Square # Mc ZANABAZAR SQUARE SIGN VISARGA +11A3A ; Zanabazar_Square # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA +11A3B..11A3E ; Zanabazar_Square # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA +11A3F..11A46 ; Zanabazar_Square # Po [8] ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK +11A47 ; Zanabazar_Square # Mn ZANABAZAR SQUARE SUBJOINER + +# Total code points: 72 + # EOF diff --git a/test/jdk/java/lang/Character/SpecialCasing.txt b/test/jdk/java/lang/Character/SpecialCasing.txt new file mode 100644 index 00000000000..26c7ecd6ae1 --- /dev/null +++ b/test/jdk/java/lang/Character/SpecialCasing.txt @@ -0,0 +1,281 @@ +# SpecialCasing-10.0.0.txt +# Date: 2017-04-14, 05:40:43 GMT +# Copyright (c) 2017 Unicode, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# Special Casing +# +# This file is a supplement to the UnicodeData.txt file. It does not define any +# properties, but rather provides additional information about the casing of +# Unicode characters, for situations when casing incurs a change in string length +# or is dependent on context or locale. For compatibility, the UnicodeData.txt +# file only contains simple case mappings for characters where they are one-to-one +# and independent of context and language. The data in this file, combined with +# the simple case mappings in UnicodeData.txt, defines the full case mappings +# Lowercase_Mapping (lc), Titlecase_Mapping (tc), and Uppercase_Mapping (uc). +# +# Note that the preferred mechanism for defining tailored casing operations is +# the Unicode Common Locale Data Repository (CLDR). For more information, see the +# discussion of case mappings and case algorithms in the Unicode Standard. +# +# All code points not listed in this file that do not have a simple case mappings +# in UnicodeData.txt map to themselves. +# ================================================================================ +# Format +# ================================================================================ +# The entries in this file are in the following machine-readable format: +# +# ; ; ; <upper>; (<condition_list>;)? # <comment> +# +# <code>, <lower>, <title>, and <upper> provide the respective full case mappings +# of <code>, expressed as character values in hex. If there is more than one character, +# they are separated by spaces. Other than as used to separate elements, spaces are +# to be ignored. +# +# The <condition_list> is optional. Where present, it consists of one or more language IDs +# or casing contexts, separated by spaces. In these conditions: +# - A condition list overrides the normal behavior if all of the listed conditions are true. +# - The casing context is always the context of the characters in the original string, +# NOT in the resulting string. +# - Case distinctions in the condition list are not significant. +# - Conditions preceded by "Not_" represent the negation of the condition. +# The condition list is not represented in the UCD as a formal property. +# +# A language ID is defined by BCP 47, with '-' and '_' treated equivalently. +# +# A casing context for a character is defined by Section 3.13 Default Case Algorithms +# of The Unicode Standard. +# +# Parsers of this file must be prepared to deal with future additions to this format: +# * Additional contexts +# * Additional fields +# ================================================================================ + +# ================================================================================ +# Unconditional mappings +# ================================================================================ + +# The German es-zed is special--the normal mapping is to SS. +# Note: the titlecase should never occur in practice. It is equal to titlecase(uppercase(<es-zed>)) + +00DF; 00DF; 0053 0073; 0053 0053; # LATIN SMALL LETTER SHARP S + +# Preserve canonical equivalence for I with dot. Turkic is handled below. + +0130; 0069 0307; 0130; 0130; # LATIN CAPITAL LETTER I WITH DOT ABOVE + +# Ligatures + +FB00; FB00; 0046 0066; 0046 0046; # LATIN SMALL LIGATURE FF +FB01; FB01; 0046 0069; 0046 0049; # LATIN SMALL LIGATURE FI +FB02; FB02; 0046 006C; 0046 004C; # LATIN SMALL LIGATURE FL +FB03; FB03; 0046 0066 0069; 0046 0046 0049; # LATIN SMALL LIGATURE FFI +FB04; FB04; 0046 0066 006C; 0046 0046 004C; # LATIN SMALL LIGATURE FFL +FB05; FB05; 0053 0074; 0053 0054; # LATIN SMALL LIGATURE LONG S T +FB06; FB06; 0053 0074; 0053 0054; # LATIN SMALL LIGATURE ST + +0587; 0587; 0535 0582; 0535 0552; # ARMENIAN SMALL LIGATURE ECH YIWN +FB13; FB13; 0544 0576; 0544 0546; # ARMENIAN SMALL LIGATURE MEN NOW +FB14; FB14; 0544 0565; 0544 0535; # ARMENIAN SMALL LIGATURE MEN ECH +FB15; FB15; 0544 056B; 0544 053B; # ARMENIAN SMALL LIGATURE MEN INI +FB16; FB16; 054E 0576; 054E 0546; # ARMENIAN SMALL LIGATURE VEW NOW +FB17; FB17; 0544 056D; 0544 053D; # ARMENIAN SMALL LIGATURE MEN XEH + +# No corresponding uppercase precomposed character + +0149; 0149; 02BC 004E; 02BC 004E; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE +0390; 0390; 0399 0308 0301; 0399 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS +03B0; 03B0; 03A5 0308 0301; 03A5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS +01F0; 01F0; 004A 030C; 004A 030C; # LATIN SMALL LETTER J WITH CARON +1E96; 1E96; 0048 0331; 0048 0331; # LATIN SMALL LETTER H WITH LINE BELOW +1E97; 1E97; 0054 0308; 0054 0308; # LATIN SMALL LETTER T WITH DIAERESIS +1E98; 1E98; 0057 030A; 0057 030A; # LATIN SMALL LETTER W WITH RING ABOVE +1E99; 1E99; 0059 030A; 0059 030A; # LATIN SMALL LETTER Y WITH RING ABOVE +1E9A; 1E9A; 0041 02BE; 0041 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING +1F50; 1F50; 03A5 0313; 03A5 0313; # GREEK SMALL LETTER UPSILON WITH PSILI +1F52; 1F52; 03A5 0313 0300; 03A5 0313 0300; # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA +1F54; 1F54; 03A5 0313 0301; 03A5 0313 0301; # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA +1F56; 1F56; 03A5 0313 0342; 03A5 0313 0342; # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI +1FB6; 1FB6; 0391 0342; 0391 0342; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI +1FC6; 1FC6; 0397 0342; 0397 0342; # GREEK SMALL LETTER ETA WITH PERISPOMENI +1FD2; 1FD2; 0399 0308 0300; 0399 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA +1FD3; 1FD3; 0399 0308 0301; 0399 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA +1FD6; 1FD6; 0399 0342; 0399 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI +1FD7; 1FD7; 0399 0308 0342; 0399 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI +1FE2; 1FE2; 03A5 0308 0300; 03A5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA +1FE3; 1FE3; 03A5 0308 0301; 03A5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA +1FE4; 1FE4; 03A1 0313; 03A1 0313; # GREEK SMALL LETTER RHO WITH PSILI +1FE6; 1FE6; 03A5 0342; 03A5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI +1FE7; 1FE7; 03A5 0308 0342; 03A5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI +1FF6; 1FF6; 03A9 0342; 03A9 0342; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI + +# IMPORTANT-when iota-subscript (0345) is uppercased or titlecased, +# the result will be incorrect unless the iota-subscript is moved to the end +# of any sequence of combining marks. Otherwise, the accents will go on the capital iota. +# This process can be achieved by first transforming the text to NFC before casing. +# E.g. <alpha><iota_subscript><acute> is uppercased to <ALPHA><acute><IOTA> + +# The following cases are already in the UnicodeData.txt file, so are only commented here. + +# 0345; 0345; 0345; 0399; # COMBINING GREEK YPOGEGRAMMENI + +# All letters with YPOGEGRAMMENI (iota-subscript) or PROSGEGRAMMENI (iota adscript) +# have special uppercases. +# Note: characters with PROSGEGRAMMENI are actually titlecase, not uppercase! + +1F80; 1F80; 1F88; 1F08 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI +1F81; 1F81; 1F89; 1F09 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI +1F82; 1F82; 1F8A; 1F0A 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1F83; 1F83; 1F8B; 1F0B 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1F84; 1F84; 1F8C; 1F0C 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1F85; 1F85; 1F8D; 1F0D 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1F86; 1F86; 1F8E; 1F0E 0399; # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1F87; 1F87; 1F8F; 1F0F 0399; # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1F88; 1F80; 1F88; 1F08 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI +1F89; 1F81; 1F89; 1F09 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI +1F8A; 1F82; 1F8A; 1F0A 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1F8B; 1F83; 1F8B; 1F0B 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1F8C; 1F84; 1F8C; 1F0C 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1F8D; 1F85; 1F8D; 1F0D 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1F8E; 1F86; 1F8E; 1F0E 0399; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1F8F; 1F87; 1F8F; 1F0F 0399; # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1F90; 1F90; 1F98; 1F28 0399; # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI +1F91; 1F91; 1F99; 1F29 0399; # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI +1F92; 1F92; 1F9A; 1F2A 0399; # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1F93; 1F93; 1F9B; 1F2B 0399; # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1F94; 1F94; 1F9C; 1F2C 0399; # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1F95; 1F95; 1F9D; 1F2D 0399; # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1F96; 1F96; 1F9E; 1F2E 0399; # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1F97; 1F97; 1F9F; 1F2F 0399; # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1F98; 1F90; 1F98; 1F28 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI +1F99; 1F91; 1F99; 1F29 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI +1F9A; 1F92; 1F9A; 1F2A 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1F9B; 1F93; 1F9B; 1F2B 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1F9C; 1F94; 1F9C; 1F2C 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1F9D; 1F95; 1F9D; 1F2D 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1F9E; 1F96; 1F9E; 1F2E 0399; # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1F9F; 1F97; 1F9F; 1F2F 0399; # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1FA0; 1FA0; 1FA8; 1F68 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI +1FA1; 1FA1; 1FA9; 1F69 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI +1FA2; 1FA2; 1FAA; 1F6A 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI +1FA3; 1FA3; 1FAB; 1F6B 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI +1FA4; 1FA4; 1FAC; 1F6C 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI +1FA5; 1FA5; 1FAD; 1F6D 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI +1FA6; 1FA6; 1FAE; 1F6E 0399; # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +1FA7; 1FA7; 1FAF; 1F6F 0399; # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +1FA8; 1FA0; 1FA8; 1F68 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI +1FA9; 1FA1; 1FA9; 1F69 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI +1FAA; 1FA2; 1FAA; 1F6A 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI +1FAB; 1FA3; 1FAB; 1F6B 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI +1FAC; 1FA4; 1FAC; 1F6C 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI +1FAD; 1FA5; 1FAD; 1F6D 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI +1FAE; 1FA6; 1FAE; 1F6E 0399; # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +1FAF; 1FA7; 1FAF; 1F6F 0399; # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +1FB3; 1FB3; 1FBC; 0391 0399; # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI +1FBC; 1FB3; 1FBC; 0391 0399; # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI +1FC3; 1FC3; 1FCC; 0397 0399; # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI +1FCC; 1FC3; 1FCC; 0397 0399; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI +1FF3; 1FF3; 1FFC; 03A9 0399; # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI +1FFC; 1FF3; 1FFC; 03A9 0399; # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI + +# Some characters with YPOGEGRAMMENI also have no corresponding titlecases + +1FB2; 1FB2; 1FBA 0345; 1FBA 0399; # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI +1FB4; 1FB4; 0386 0345; 0386 0399; # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI +1FC2; 1FC2; 1FCA 0345; 1FCA 0399; # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI +1FC4; 1FC4; 0389 0345; 0389 0399; # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI +1FF2; 1FF2; 1FFA 0345; 1FFA 0399; # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI +1FF4; 1FF4; 038F 0345; 038F 0399; # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI + +1FB7; 1FB7; 0391 0342 0345; 0391 0342 0399; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI +1FC7; 1FC7; 0397 0342 0345; 0397 0342 0399; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI +1FF7; 1FF7; 03A9 0342 0345; 03A9 0342 0399; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI + +# ================================================================================ +# Conditional Mappings +# The remainder of this file provides conditional casing data used to produce +# full case mappings. +# ================================================================================ +# Language-Insensitive Mappings +# These are characters whose full case mappings do not depend on language, but do +# depend on context (which characters come before or after). For more information +# see the header of this file and the Unicode Standard. +# ================================================================================ + +# Special case for final form of sigma + +03A3; 03C2; 03A3; 03A3; Final_Sigma; # GREEK CAPITAL LETTER SIGMA + +# Note: the following cases for non-final are already in the UnicodeData.txt file. + +# 03A3; 03C3; 03A3; 03A3; # GREEK CAPITAL LETTER SIGMA +# 03C3; 03C3; 03A3; 03A3; # GREEK SMALL LETTER SIGMA +# 03C2; 03C2; 03A3; 03A3; # GREEK SMALL LETTER FINAL SIGMA + +# Note: the following cases are not included, since they would case-fold in lowercasing + +# 03C3; 03C2; 03A3; 03A3; Final_Sigma; # GREEK SMALL LETTER SIGMA +# 03C2; 03C3; 03A3; 03A3; Not_Final_Sigma; # GREEK SMALL LETTER FINAL SIGMA + +# ================================================================================ +# Language-Sensitive Mappings +# These are characters whose full case mappings depend on language and perhaps also +# context (which characters come before or after). For more information +# see the header of this file and the Unicode Standard. +# ================================================================================ + +# Lithuanian + +# Lithuanian retains the dot in a lowercase i when followed by accents. + +# Remove DOT ABOVE after "i" with upper or titlecase + +0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE + +# Introduce an explicit dot above when lowercasing capital I's and J's +# whenever there are more accents above. +# (of the accents used in Lithuanian: grave, acute, tilde above, and ogonek) + +0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I +004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J +012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK +00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE +00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE +0128; 0069 0307 0303; 0128; 0128; lt; # LATIN CAPITAL LETTER I WITH TILDE + +# ================================================================================ + +# Turkish and Azeri + +# I and i-dotless; I-dot and i are case pairs in Turkish and Azeri +# The following rules handle those cases. + +0130; 0069; 0130; 0130; tr; # LATIN CAPITAL LETTER I WITH DOT ABOVE +0130; 0069; 0130; 0130; az; # LATIN CAPITAL LETTER I WITH DOT ABOVE + +# When lowercasing, remove dot_above in the sequence I + dot_above, which will turn into i. +# This matches the behavior of the canonically equivalent I-dot_above + +0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE +0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE + +# When lowercasing, unless an I is before a dot_above, it turns into a dotless i. + +0049; 0131; 0049; 0049; tr Not_Before_Dot; # LATIN CAPITAL LETTER I +0049; 0131; 0049; 0049; az Not_Before_Dot; # LATIN CAPITAL LETTER I + +# When uppercasing, i turns into a dotted capital I + +0069; 0069; 0130; 0130; tr; # LATIN SMALL LETTER I +0069; 0069; 0130; 0130; az; # LATIN SMALL LETTER I + +# Note: the following case is already in the UnicodeData.txt file. + +# 0131; 0131; 0049; 0049; tr; # LATIN SMALL LETTER DOTLESS I + +# EOF + diff --git a/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java b/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java index 9a7811e5590..abff5a4ebbc 100644 --- a/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java +++ b/test/jdk/java/lang/Character/UnicodeBlock/OptimalMapSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018 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 @@ -23,7 +23,7 @@ /** * @test - * @bug 8080535 + * @bug 8080535 8191410 * @summary Expected size of Character.UnicodeBlock.map is not optimal * @library /lib/testlibrary * @modules java.base/java.lang:open @@ -41,8 +41,8 @@ import jdk.testlibrary.OptimalCapacity; // According to http://www.unicode.org/versions/beta-8.0.0.html , // in Unicode 8 there will be added 10 more blocks (30 with aliases). // -// After implementing support of Unicode 7 and 8 in Java, there will -// be 510+96+30 = 636 entries in Character.UnicodeBlock.map. +// After implementing support of Unicode 9 and 10 in Java, there will +// be 638 entries in Character.UnicodeBlock.map. // // Initialization of the map and this test will have to be adjusted // accordingly then. @@ -51,7 +51,7 @@ public class OptimalMapSize { public static void main(String[] args) throws Throwable { // The initial size of Character.UnicodeBlock.map. // See src/java.base/share/classes/java/lang/Character.java - int initialCapacity = (int)(510 / 0.75f + 1.0f); + int initialCapacity = (int)(638 / 0.75f + 1.0f); OptimalCapacity.ofHashMap(Character.UnicodeBlock.class, "map", initialCapacity); diff --git a/test/jdk/java/lang/Character/UnicodeCasingTest.java b/test/jdk/java/lang/Character/UnicodeCasingTest.java new file mode 100644 index 00000000000..0843ce6a729 --- /dev/null +++ b/test/jdk/java/lang/Character/UnicodeCasingTest.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 4397357 6565620 6959267 8032446 8072600 + * @summary Confirm normal case mappings are handled correctly. + * @run main/timeout=200 UnicodeCasingTest + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class UnicodeCasingTest { + + private static boolean err = false; + + // Locales which are used for testing + private static List<Locale> locales = new ArrayList<>(); + static { + locales.add(new Locale("az", "")); + locales.addAll(java.util.Arrays.asList(Locale.getAvailableLocales())); + } + + + public static void main(String[] args) { + UnicodeCasingTest specialCasingTest = new UnicodeCasingTest(); + specialCasingTest.test(); + } + + private void test() { + Locale defaultLocale = Locale.getDefault(); + + BufferedReader in = null; + + try { + File file = new File(System.getProperty("test.src", "."), + "UnicodeData.txt"); + + int locale_num = locales.size(); + for (int l = 0; l < locale_num; l++) { + Locale locale = locales.get(l); + Locale.setDefault(locale); + System.out.println("Testing on " + locale + " locale...."); + + in = new BufferedReader(new FileReader(file)); + + String line; + while ((line = in.readLine()) != null) { + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + + test(line); + } + + in.close(); + in = null; + } + } + catch (Exception e) { + err = true; + e.printStackTrace(); + } + finally { + if (in != null) { + try { + in.close(); + } + catch (Exception e) { + } + } + + Locale.setDefault(defaultLocale); + + if (err) { + throw new RuntimeException("UnicodeCasingTest failed."); + } else { + System.out.println("UnicodeCasingTest passed."); + } + } + } + + private void test(String line) { + String[] fields = line.split(";", 15); + int orig = convert(fields[0]); + + if (fields[12].length() != 0) { + testUpperCase(orig, convert(fields[12])); + } else { + testUpperCase(orig, orig); + } + + if (fields[13].length() != 0) { + testLowerCase(orig, convert(fields[13])); + } else { + testLowerCase(orig, orig); + } + + if (fields[14].length() != 0) { + testTitleCase(orig, convert(fields[14])); + } else { + testTitleCase(orig, orig); + } + } + + private void testUpperCase(int orig, int expected) { + int got = Character.toUpperCase(orig); + + if (expected != got) { + err = true; + System.err.println("toUpperCase(" + + ") failed.\n\tOriginal: " + toString(orig) + + "\n\tGot: " + toString(got) + + "\n\tExpected: " + toString(expected)); + } + } + + private void testLowerCase(int orig, int expected) { + int got = Character.toLowerCase(orig); + + if (expected != got) { + err = true; + System.err.println("toLowerCase(" + + ") failed.\n\tOriginal: " + toString(orig) + + "\n\tGot: " + toString(got) + + "\n\tExpected: " + toString(expected)); + } + } + + private void testTitleCase(int orig, int expected) { + int got = Character.toTitleCase(orig); + + if (expected != got) { + err = true; + System.err.println("toTitleCase(" + + ") failed.\n\tOriginal: " + toString(orig) + + "\n\tGot: " + toString(got) + + "\n\tExpected: " + toString(expected)); + } + } + + private int convert(String str) { + return Integer.parseInt(str, 16); + } + + private String toString(int i) { + return Integer.toHexString(i).toUpperCase(); + } + +} diff --git a/test/jdk/java/lang/Character/UnicodeData.txt b/test/jdk/java/lang/Character/UnicodeData.txt new file mode 100644 index 00000000000..d89c64f526a --- /dev/null +++ b/test/jdk/java/lang/Character/UnicodeData.txt @@ -0,0 +1,31618 @@ +0000;<control>;Cc;0;BN;;;;;N;NULL;;;; +0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; +0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; +0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; +0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;; +0005;<control>;Cc;0;BN;;;;;N;ENQUIRY;;;; +0006;<control>;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; +0007;<control>;Cc;0;BN;;;;;N;BELL;;;; +0008;<control>;Cc;0;BN;;;;;N;BACKSPACE;;;; +0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;; +000A;<control>;Cc;0;B;;;;;N;LINE FEED (LF);;;; +000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;; +000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;; +000D;<control>;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;; +000E;<control>;Cc;0;BN;;;;;N;SHIFT OUT;;;; +000F;<control>;Cc;0;BN;;;;;N;SHIFT IN;;;; +0010;<control>;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;; +0011;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;; +0012;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;; +0013;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;; +0014;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;; +0015;<control>;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;; +0016;<control>;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;; +0017;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;; +0018;<control>;Cc;0;BN;;;;;N;CANCEL;;;; +0019;<control>;Cc;0;BN;;;;;N;END OF MEDIUM;;;; +001A;<control>;Cc;0;BN;;;;;N;SUBSTITUTE;;;; +001B;<control>;Cc;0;BN;;;;;N;ESCAPE;;;; +001C;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;; +001D;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;; +001E;<control>;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;; +001F;<control>;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;; +0020;SPACE;Zs;0;WS;;;;;N;;;;; +0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;; +0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;; +0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;; +0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;; +0026;AMPERSAND;Po;0;ON;;;;;N;;;;; +0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;; +0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;; +0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;; +002A;ASTERISK;Po;0;ON;;;;;N;;;;; +002B;PLUS SIGN;Sm;0;ES;;;;;N;;;;; +002C;COMMA;Po;0;CS;;;;;N;;;;; +002D;HYPHEN-MINUS;Pd;0;ES;;;;;N;;;;; +002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;; +002F;SOLIDUS;Po;0;CS;;;;;N;SLASH;;;; +0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;; +0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;; +0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;; +0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;; +0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;; +0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;; +0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;; +0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;; +0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;; +0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;; +003A;COLON;Po;0;CS;;;;;N;;;;; +003B;SEMICOLON;Po;0;ON;;;;;N;;;;; +003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;; +003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;; +003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;; +003F;QUESTION MARK;Po;0;ON;;;;;N;;;;; +0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;; +0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061; +0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062; +0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063; +0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064; +0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065; +0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066; +0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067; +0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068; +0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069; +004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A; +004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B; +004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C; +004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D; +004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E; +004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F; +0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070; +0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071; +0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072; +0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073; +0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074; +0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075; +0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076; +0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077; +0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078; +0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079; +005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A; +005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;; +005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;; +005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;; +005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;; +005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;; +0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;; +0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041 +0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042 +0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043 +0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044 +0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045 +0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046 +0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047 +0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048 +0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049 +006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A +006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B +006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C +006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D +006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E +006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F +0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050 +0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051 +0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052 +0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053 +0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054 +0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055 +0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056 +0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057 +0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058 +0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059 +007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A +007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;; +007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;; +007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;; +007E;TILDE;Sm;0;ON;;;;;N;;;;; +007F;<control>;Cc;0;BN;;;;;N;DELETE;;;; +0080;<control>;Cc;0;BN;;;;;N;;;;; +0081;<control>;Cc;0;BN;;;;;N;;;;; +0082;<control>;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;; +0083;<control>;Cc;0;BN;;;;;N;NO BREAK HERE;;;; +0084;<control>;Cc;0;BN;;;;;N;;;;; +0085;<control>;Cc;0;B;;;;;N;NEXT LINE (NEL);;;; +0086;<control>;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;; +0087;<control>;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;; +0088;<control>;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;; +0089;<control>;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;; +008A;<control>;Cc;0;BN;;;;;N;LINE TABULATION SET;;;; +008B;<control>;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;; +008C;<control>;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;; +008D;<control>;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;; +008E;<control>;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;; +008F;<control>;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;; +0090;<control>;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;; +0091;<control>;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;; +0092;<control>;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;; +0093;<control>;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;; +0094;<control>;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;; +0095;<control>;Cc;0;BN;;;;;N;MESSAGE WAITING;;;; +0096;<control>;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;; +0097;<control>;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;; +0098;<control>;Cc;0;BN;;;;;N;START OF STRING;;;; +0099;<control>;Cc;0;BN;;;;;N;;;;; +009A;<control>;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;; +009B;<control>;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;; +009C;<control>;Cc;0;BN;;;;;N;STRING TERMINATOR;;;; +009D;<control>;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;; +009E;<control>;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;; +009F;<control>;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;; +00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;; +00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;; +00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;; +00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; +00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;; +00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;; +00A7;SECTION SIGN;Po;0;ON;;;;;N;;;;; +00A8;DIAERESIS;Sk;0;ON;<compat> 0020 0308;;;;N;SPACING DIAERESIS;;;; +00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;; +00AA;FEMININE ORDINAL INDICATOR;Lo;0;L;<super> 0061;;;;N;;;;; +00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;;;; +00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;; +00AD;SOFT HYPHEN;Cf;0;BN;;;;;N;;;;; +00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;; +00AF;MACRON;Sk;0;ON;<compat> 0020 0304;;;;N;SPACING MACRON;;;; +00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;; +00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;; +00B2;SUPERSCRIPT TWO;No;0;EN;<super> 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;; +00B3;SUPERSCRIPT THREE;No;0;EN;<super> 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;; +00B4;ACUTE ACCENT;Sk;0;ON;<compat> 0020 0301;;;;N;SPACING ACUTE;;;; +00B5;MICRO SIGN;Ll;0;L;<compat> 03BC;;;;N;;;039C;;039C +00B6;PILCROW SIGN;Po;0;ON;;;;;N;PARAGRAPH SIGN;;;; +00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;; +00B8;CEDILLA;Sk;0;ON;<compat> 0020 0327;;;;N;SPACING CEDILLA;;;; +00B9;SUPERSCRIPT ONE;No;0;EN;<super> 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;; +00BA;MASCULINE ORDINAL INDICATOR;Lo;0;L;<super> 006F;;;;N;;;;; +00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;; +00BC;VULGAR FRACTION ONE QUARTER;No;0;ON;<fraction> 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;; +00BD;VULGAR FRACTION ONE HALF;No;0;ON;<fraction> 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;; +00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON;<fraction> 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;; +00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;; +00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0; +00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1; +00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2; +00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3; +00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4; +00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5; +00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;;;00E6; +00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7; +00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8; +00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9; +00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA; +00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB; +00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC; +00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED; +00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE; +00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF; +00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;00F0; +00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1; +00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2; +00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3; +00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4; +00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5; +00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6; +00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;; +00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8; +00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9; +00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA; +00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB; +00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC; +00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD; +00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;;;00FE; +00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;; +00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0 +00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1 +00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2 +00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3 +00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4 +00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5 +00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;;00C6;;00C6 +00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7 +00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8 +00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9 +00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA +00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB +00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC +00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD +00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE +00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF +00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;;00D0;;00D0 +00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1 +00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2 +00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3 +00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4 +00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5 +00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6 +00F7;DIVISION SIGN;Sm;0;ON;;;;;N;;;;; +00F8;LATIN SMALL LETTER O WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER O SLASH;;00D8;;00D8 +00F9;LATIN SMALL LETTER U WITH GRAVE;Ll;0;L;0075 0300;;;;N;LATIN SMALL LETTER U GRAVE;;00D9;;00D9 +00FA;LATIN SMALL LETTER U WITH ACUTE;Ll;0;L;0075 0301;;;;N;LATIN SMALL LETTER U ACUTE;;00DA;;00DA +00FB;LATIN SMALL LETTER U WITH CIRCUMFLEX;Ll;0;L;0075 0302;;;;N;LATIN SMALL LETTER U CIRCUMFLEX;;00DB;;00DB +00FC;LATIN SMALL LETTER U WITH DIAERESIS;Ll;0;L;0075 0308;;;;N;LATIN SMALL LETTER U DIAERESIS;;00DC;;00DC +00FD;LATIN SMALL LETTER Y WITH ACUTE;Ll;0;L;0079 0301;;;;N;LATIN SMALL LETTER Y ACUTE;;00DD;;00DD +00FE;LATIN SMALL LETTER THORN;Ll;0;L;;;;;N;;;00DE;;00DE +00FF;LATIN SMALL LETTER Y WITH DIAERESIS;Ll;0;L;0079 0308;;;;N;LATIN SMALL LETTER Y DIAERESIS;;0178;;0178 +0100;LATIN CAPITAL LETTER A WITH MACRON;Lu;0;L;0041 0304;;;;N;LATIN CAPITAL LETTER A MACRON;;;0101; +0101;LATIN SMALL LETTER A WITH MACRON;Ll;0;L;0061 0304;;;;N;LATIN SMALL LETTER A MACRON;;0100;;0100 +0102;LATIN CAPITAL LETTER A WITH BREVE;Lu;0;L;0041 0306;;;;N;LATIN CAPITAL LETTER A BREVE;;;0103; +0103;LATIN SMALL LETTER A WITH BREVE;Ll;0;L;0061 0306;;;;N;LATIN SMALL LETTER A BREVE;;0102;;0102 +0104;LATIN CAPITAL LETTER A WITH OGONEK;Lu;0;L;0041 0328;;;;N;LATIN CAPITAL LETTER A OGONEK;;;0105; +0105;LATIN SMALL LETTER A WITH OGONEK;Ll;0;L;0061 0328;;;;N;LATIN SMALL LETTER A OGONEK;;0104;;0104 +0106;LATIN CAPITAL LETTER C WITH ACUTE;Lu;0;L;0043 0301;;;;N;LATIN CAPITAL LETTER C ACUTE;;;0107; +0107;LATIN SMALL LETTER C WITH ACUTE;Ll;0;L;0063 0301;;;;N;LATIN SMALL LETTER C ACUTE;;0106;;0106 +0108;LATIN CAPITAL LETTER C WITH CIRCUMFLEX;Lu;0;L;0043 0302;;;;N;LATIN CAPITAL LETTER C CIRCUMFLEX;;;0109; +0109;LATIN SMALL LETTER C WITH CIRCUMFLEX;Ll;0;L;0063 0302;;;;N;LATIN SMALL LETTER C CIRCUMFLEX;;0108;;0108 +010A;LATIN CAPITAL LETTER C WITH DOT ABOVE;Lu;0;L;0043 0307;;;;N;LATIN CAPITAL LETTER C DOT;;;010B; +010B;LATIN SMALL LETTER C WITH DOT ABOVE;Ll;0;L;0063 0307;;;;N;LATIN SMALL LETTER C DOT;;010A;;010A +010C;LATIN CAPITAL LETTER C WITH CARON;Lu;0;L;0043 030C;;;;N;LATIN CAPITAL LETTER C HACEK;;;010D; +010D;LATIN SMALL LETTER C WITH CARON;Ll;0;L;0063 030C;;;;N;LATIN SMALL LETTER C HACEK;;010C;;010C +010E;LATIN CAPITAL LETTER D WITH CARON;Lu;0;L;0044 030C;;;;N;LATIN CAPITAL LETTER D HACEK;;;010F; +010F;LATIN SMALL LETTER D WITH CARON;Ll;0;L;0064 030C;;;;N;LATIN SMALL LETTER D HACEK;;010E;;010E +0110;LATIN CAPITAL LETTER D WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D BAR;;;0111; +0111;LATIN SMALL LETTER D WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER D BAR;;0110;;0110 +0112;LATIN CAPITAL LETTER E WITH MACRON;Lu;0;L;0045 0304;;;;N;LATIN CAPITAL LETTER E MACRON;;;0113; +0113;LATIN SMALL LETTER E WITH MACRON;Ll;0;L;0065 0304;;;;N;LATIN SMALL LETTER E MACRON;;0112;;0112 +0114;LATIN CAPITAL LETTER E WITH BREVE;Lu;0;L;0045 0306;;;;N;LATIN CAPITAL LETTER E BREVE;;;0115; +0115;LATIN SMALL LETTER E WITH BREVE;Ll;0;L;0065 0306;;;;N;LATIN SMALL LETTER E BREVE;;0114;;0114 +0116;LATIN CAPITAL LETTER E WITH DOT ABOVE;Lu;0;L;0045 0307;;;;N;LATIN CAPITAL LETTER E DOT;;;0117; +0117;LATIN SMALL LETTER E WITH DOT ABOVE;Ll;0;L;0065 0307;;;;N;LATIN SMALL LETTER E DOT;;0116;;0116 +0118;LATIN CAPITAL LETTER E WITH OGONEK;Lu;0;L;0045 0328;;;;N;LATIN CAPITAL LETTER E OGONEK;;;0119; +0119;LATIN SMALL LETTER E WITH OGONEK;Ll;0;L;0065 0328;;;;N;LATIN SMALL LETTER E OGONEK;;0118;;0118 +011A;LATIN CAPITAL LETTER E WITH CARON;Lu;0;L;0045 030C;;;;N;LATIN CAPITAL LETTER E HACEK;;;011B; +011B;LATIN SMALL LETTER E WITH CARON;Ll;0;L;0065 030C;;;;N;LATIN SMALL LETTER E HACEK;;011A;;011A +011C;LATIN CAPITAL LETTER G WITH CIRCUMFLEX;Lu;0;L;0047 0302;;;;N;LATIN CAPITAL LETTER G CIRCUMFLEX;;;011D; +011D;LATIN SMALL LETTER G WITH CIRCUMFLEX;Ll;0;L;0067 0302;;;;N;LATIN SMALL LETTER G CIRCUMFLEX;;011C;;011C +011E;LATIN CAPITAL LETTER G WITH BREVE;Lu;0;L;0047 0306;;;;N;LATIN CAPITAL LETTER G BREVE;;;011F; +011F;LATIN SMALL LETTER G WITH BREVE;Ll;0;L;0067 0306;;;;N;LATIN SMALL LETTER G BREVE;;011E;;011E +0120;LATIN CAPITAL LETTER G WITH DOT ABOVE;Lu;0;L;0047 0307;;;;N;LATIN CAPITAL LETTER G DOT;;;0121; +0121;LATIN SMALL LETTER G WITH DOT ABOVE;Ll;0;L;0067 0307;;;;N;LATIN SMALL LETTER G DOT;;0120;;0120 +0122;LATIN CAPITAL LETTER G WITH CEDILLA;Lu;0;L;0047 0327;;;;N;LATIN CAPITAL LETTER G CEDILLA;;;0123; +0123;LATIN SMALL LETTER G WITH CEDILLA;Ll;0;L;0067 0327;;;;N;LATIN SMALL LETTER G CEDILLA;;0122;;0122 +0124;LATIN CAPITAL LETTER H WITH CIRCUMFLEX;Lu;0;L;0048 0302;;;;N;LATIN CAPITAL LETTER H CIRCUMFLEX;;;0125; +0125;LATIN SMALL LETTER H WITH CIRCUMFLEX;Ll;0;L;0068 0302;;;;N;LATIN SMALL LETTER H CIRCUMFLEX;;0124;;0124 +0126;LATIN CAPITAL LETTER H WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER H BAR;;;0127; +0127;LATIN SMALL LETTER H WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER H BAR;;0126;;0126 +0128;LATIN CAPITAL LETTER I WITH TILDE;Lu;0;L;0049 0303;;;;N;LATIN CAPITAL LETTER I TILDE;;;0129; +0129;LATIN SMALL LETTER I WITH TILDE;Ll;0;L;0069 0303;;;;N;LATIN SMALL LETTER I TILDE;;0128;;0128 +012A;LATIN CAPITAL LETTER I WITH MACRON;Lu;0;L;0049 0304;;;;N;LATIN CAPITAL LETTER I MACRON;;;012B; +012B;LATIN SMALL LETTER I WITH MACRON;Ll;0;L;0069 0304;;;;N;LATIN SMALL LETTER I MACRON;;012A;;012A +012C;LATIN CAPITAL LETTER I WITH BREVE;Lu;0;L;0049 0306;;;;N;LATIN CAPITAL LETTER I BREVE;;;012D; +012D;LATIN SMALL LETTER I WITH BREVE;Ll;0;L;0069 0306;;;;N;LATIN SMALL LETTER I BREVE;;012C;;012C +012E;LATIN CAPITAL LETTER I WITH OGONEK;Lu;0;L;0049 0328;;;;N;LATIN CAPITAL LETTER I OGONEK;;;012F; +012F;LATIN SMALL LETTER I WITH OGONEK;Ll;0;L;0069 0328;;;;N;LATIN SMALL LETTER I OGONEK;;012E;;012E +0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069; +0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049 +0132;LATIN CAPITAL LIGATURE IJ;Lu;0;L;<compat> 0049 004A;;;;N;LATIN CAPITAL LETTER I J;;;0133; +0133;LATIN SMALL LIGATURE IJ;Ll;0;L;<compat> 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132 +0134;LATIN CAPITAL LETTER J WITH CIRCUMFLEX;Lu;0;L;004A 0302;;;;N;LATIN CAPITAL LETTER J CIRCUMFLEX;;;0135; +0135;LATIN SMALL LETTER J WITH CIRCUMFLEX;Ll;0;L;006A 0302;;;;N;LATIN SMALL LETTER J CIRCUMFLEX;;0134;;0134 +0136;LATIN CAPITAL LETTER K WITH CEDILLA;Lu;0;L;004B 0327;;;;N;LATIN CAPITAL LETTER K CEDILLA;;;0137; +0137;LATIN SMALL LETTER K WITH CEDILLA;Ll;0;L;006B 0327;;;;N;LATIN SMALL LETTER K CEDILLA;;0136;;0136 +0138;LATIN SMALL LETTER KRA;Ll;0;L;;;;;N;;;;; +0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A; +013A;LATIN SMALL LETTER L WITH ACUTE;Ll;0;L;006C 0301;;;;N;LATIN SMALL LETTER L ACUTE;;0139;;0139 +013B;LATIN CAPITAL LETTER L WITH CEDILLA;Lu;0;L;004C 0327;;;;N;LATIN CAPITAL LETTER L CEDILLA;;;013C; +013C;LATIN SMALL LETTER L WITH CEDILLA;Ll;0;L;006C 0327;;;;N;LATIN SMALL LETTER L CEDILLA;;013B;;013B +013D;LATIN CAPITAL LETTER L WITH CARON;Lu;0;L;004C 030C;;;;N;LATIN CAPITAL LETTER L HACEK;;;013E; +013E;LATIN SMALL LETTER L WITH CARON;Ll;0;L;006C 030C;;;;N;LATIN SMALL LETTER L HACEK;;013D;;013D +013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L;<compat> 004C 00B7;;;;N;;;;0140; +0140;LATIN SMALL LETTER L WITH MIDDLE DOT;Ll;0;L;<compat> 006C 00B7;;;;N;;;013F;;013F +0141;LATIN CAPITAL LETTER L WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER L SLASH;;;0142; +0142;LATIN SMALL LETTER L WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER L SLASH;;0141;;0141 +0143;LATIN CAPITAL LETTER N WITH ACUTE;Lu;0;L;004E 0301;;;;N;LATIN CAPITAL LETTER N ACUTE;;;0144; +0144;LATIN SMALL LETTER N WITH ACUTE;Ll;0;L;006E 0301;;;;N;LATIN SMALL LETTER N ACUTE;;0143;;0143 +0145;LATIN CAPITAL LETTER N WITH CEDILLA;Lu;0;L;004E 0327;;;;N;LATIN CAPITAL LETTER N CEDILLA;;;0146; +0146;LATIN SMALL LETTER N WITH CEDILLA;Ll;0;L;006E 0327;;;;N;LATIN SMALL LETTER N CEDILLA;;0145;;0145 +0147;LATIN CAPITAL LETTER N WITH CARON;Lu;0;L;004E 030C;;;;N;LATIN CAPITAL LETTER N HACEK;;;0148; +0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147 +0149;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE;Ll;0;L;<compat> 02BC 006E;;;;N;LATIN SMALL LETTER APOSTROPHE N;;;; +014A;LATIN CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;014B; +014B;LATIN SMALL LETTER ENG;Ll;0;L;;;;;N;;;014A;;014A +014C;LATIN CAPITAL LETTER O WITH MACRON;Lu;0;L;004F 0304;;;;N;LATIN CAPITAL LETTER O MACRON;;;014D; +014D;LATIN SMALL LETTER O WITH MACRON;Ll;0;L;006F 0304;;;;N;LATIN SMALL LETTER O MACRON;;014C;;014C +014E;LATIN CAPITAL LETTER O WITH BREVE;Lu;0;L;004F 0306;;;;N;LATIN CAPITAL LETTER O BREVE;;;014F; +014F;LATIN SMALL LETTER O WITH BREVE;Ll;0;L;006F 0306;;;;N;LATIN SMALL LETTER O BREVE;;014E;;014E +0150;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE;Lu;0;L;004F 030B;;;;N;LATIN CAPITAL LETTER O DOUBLE ACUTE;;;0151; +0151;LATIN SMALL LETTER O WITH DOUBLE ACUTE;Ll;0;L;006F 030B;;;;N;LATIN SMALL LETTER O DOUBLE ACUTE;;0150;;0150 +0152;LATIN CAPITAL LIGATURE OE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O E;;;0153; +0153;LATIN SMALL LIGATURE OE;Ll;0;L;;;;;N;LATIN SMALL LETTER O E;;0152;;0152 +0154;LATIN CAPITAL LETTER R WITH ACUTE;Lu;0;L;0052 0301;;;;N;LATIN CAPITAL LETTER R ACUTE;;;0155; +0155;LATIN SMALL LETTER R WITH ACUTE;Ll;0;L;0072 0301;;;;N;LATIN SMALL LETTER R ACUTE;;0154;;0154 +0156;LATIN CAPITAL LETTER R WITH CEDILLA;Lu;0;L;0052 0327;;;;N;LATIN CAPITAL LETTER R CEDILLA;;;0157; +0157;LATIN SMALL LETTER R WITH CEDILLA;Ll;0;L;0072 0327;;;;N;LATIN SMALL LETTER R CEDILLA;;0156;;0156 +0158;LATIN CAPITAL LETTER R WITH CARON;Lu;0;L;0052 030C;;;;N;LATIN CAPITAL LETTER R HACEK;;;0159; +0159;LATIN SMALL LETTER R WITH CARON;Ll;0;L;0072 030C;;;;N;LATIN SMALL LETTER R HACEK;;0158;;0158 +015A;LATIN CAPITAL LETTER S WITH ACUTE;Lu;0;L;0053 0301;;;;N;LATIN CAPITAL LETTER S ACUTE;;;015B; +015B;LATIN SMALL LETTER S WITH ACUTE;Ll;0;L;0073 0301;;;;N;LATIN SMALL LETTER S ACUTE;;015A;;015A +015C;LATIN CAPITAL LETTER S WITH CIRCUMFLEX;Lu;0;L;0053 0302;;;;N;LATIN CAPITAL LETTER S CIRCUMFLEX;;;015D; +015D;LATIN SMALL LETTER S WITH CIRCUMFLEX;Ll;0;L;0073 0302;;;;N;LATIN SMALL LETTER S CIRCUMFLEX;;015C;;015C +015E;LATIN CAPITAL LETTER S WITH CEDILLA;Lu;0;L;0053 0327;;;;N;LATIN CAPITAL LETTER S CEDILLA;;;015F; +015F;LATIN SMALL LETTER S WITH CEDILLA;Ll;0;L;0073 0327;;;;N;LATIN SMALL LETTER S CEDILLA;;015E;;015E +0160;LATIN CAPITAL LETTER S WITH CARON;Lu;0;L;0053 030C;;;;N;LATIN CAPITAL LETTER S HACEK;;;0161; +0161;LATIN SMALL LETTER S WITH CARON;Ll;0;L;0073 030C;;;;N;LATIN SMALL LETTER S HACEK;;0160;;0160 +0162;LATIN CAPITAL LETTER T WITH CEDILLA;Lu;0;L;0054 0327;;;;N;LATIN CAPITAL LETTER T CEDILLA;;;0163; +0163;LATIN SMALL LETTER T WITH CEDILLA;Ll;0;L;0074 0327;;;;N;LATIN SMALL LETTER T CEDILLA;;0162;;0162 +0164;LATIN CAPITAL LETTER T WITH CARON;Lu;0;L;0054 030C;;;;N;LATIN CAPITAL LETTER T HACEK;;;0165; +0165;LATIN SMALL LETTER T WITH CARON;Ll;0;L;0074 030C;;;;N;LATIN SMALL LETTER T HACEK;;0164;;0164 +0166;LATIN CAPITAL LETTER T WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T BAR;;;0167; +0167;LATIN SMALL LETTER T WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER T BAR;;0166;;0166 +0168;LATIN CAPITAL LETTER U WITH TILDE;Lu;0;L;0055 0303;;;;N;LATIN CAPITAL LETTER U TILDE;;;0169; +0169;LATIN SMALL LETTER U WITH TILDE;Ll;0;L;0075 0303;;;;N;LATIN SMALL LETTER U TILDE;;0168;;0168 +016A;LATIN CAPITAL LETTER U WITH MACRON;Lu;0;L;0055 0304;;;;N;LATIN CAPITAL LETTER U MACRON;;;016B; +016B;LATIN SMALL LETTER U WITH MACRON;Ll;0;L;0075 0304;;;;N;LATIN SMALL LETTER U MACRON;;016A;;016A +016C;LATIN CAPITAL LETTER U WITH BREVE;Lu;0;L;0055 0306;;;;N;LATIN CAPITAL LETTER U BREVE;;;016D; +016D;LATIN SMALL LETTER U WITH BREVE;Ll;0;L;0075 0306;;;;N;LATIN SMALL LETTER U BREVE;;016C;;016C +016E;LATIN CAPITAL LETTER U WITH RING ABOVE;Lu;0;L;0055 030A;;;;N;LATIN CAPITAL LETTER U RING;;;016F; +016F;LATIN SMALL LETTER U WITH RING ABOVE;Ll;0;L;0075 030A;;;;N;LATIN SMALL LETTER U RING;;016E;;016E +0170;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0055 030B;;;;N;LATIN CAPITAL LETTER U DOUBLE ACUTE;;;0171; +0171;LATIN SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0075 030B;;;;N;LATIN SMALL LETTER U DOUBLE ACUTE;;0170;;0170 +0172;LATIN CAPITAL LETTER U WITH OGONEK;Lu;0;L;0055 0328;;;;N;LATIN CAPITAL LETTER U OGONEK;;;0173; +0173;LATIN SMALL LETTER U WITH OGONEK;Ll;0;L;0075 0328;;;;N;LATIN SMALL LETTER U OGONEK;;0172;;0172 +0174;LATIN CAPITAL LETTER W WITH CIRCUMFLEX;Lu;0;L;0057 0302;;;;N;LATIN CAPITAL LETTER W CIRCUMFLEX;;;0175; +0175;LATIN SMALL LETTER W WITH CIRCUMFLEX;Ll;0;L;0077 0302;;;;N;LATIN SMALL LETTER W CIRCUMFLEX;;0174;;0174 +0176;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX;Lu;0;L;0059 0302;;;;N;LATIN CAPITAL LETTER Y CIRCUMFLEX;;;0177; +0177;LATIN SMALL LETTER Y WITH CIRCUMFLEX;Ll;0;L;0079 0302;;;;N;LATIN SMALL LETTER Y CIRCUMFLEX;;0176;;0176 +0178;LATIN CAPITAL LETTER Y WITH DIAERESIS;Lu;0;L;0059 0308;;;;N;LATIN CAPITAL LETTER Y DIAERESIS;;;00FF; +0179;LATIN CAPITAL LETTER Z WITH ACUTE;Lu;0;L;005A 0301;;;;N;LATIN CAPITAL LETTER Z ACUTE;;;017A; +017A;LATIN SMALL LETTER Z WITH ACUTE;Ll;0;L;007A 0301;;;;N;LATIN SMALL LETTER Z ACUTE;;0179;;0179 +017B;LATIN CAPITAL LETTER Z WITH DOT ABOVE;Lu;0;L;005A 0307;;;;N;LATIN CAPITAL LETTER Z DOT;;;017C; +017C;LATIN SMALL LETTER Z WITH DOT ABOVE;Ll;0;L;007A 0307;;;;N;LATIN SMALL LETTER Z DOT;;017B;;017B +017D;LATIN CAPITAL LETTER Z WITH CARON;Lu;0;L;005A 030C;;;;N;LATIN CAPITAL LETTER Z HACEK;;;017E; +017E;LATIN SMALL LETTER Z WITH CARON;Ll;0;L;007A 030C;;;;N;LATIN SMALL LETTER Z HACEK;;017D;;017D +017F;LATIN SMALL LETTER LONG S;Ll;0;L;<compat> 0073;;;;N;;;0053;;0053 +0180;LATIN SMALL LETTER B WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER B BAR;;0243;;0243 +0181;LATIN CAPITAL LETTER B WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B HOOK;;;0253; +0182;LATIN CAPITAL LETTER B WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B TOPBAR;;;0183; +0183;LATIN SMALL LETTER B WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER B TOPBAR;;0182;;0182 +0184;LATIN CAPITAL LETTER TONE SIX;Lu;0;L;;;;;N;;;;0185; +0185;LATIN SMALL LETTER TONE SIX;Ll;0;L;;;;;N;;;0184;;0184 +0186;LATIN CAPITAL LETTER OPEN O;Lu;0;L;;;;;N;;;;0254; +0187;LATIN CAPITAL LETTER C WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER C HOOK;;;0188; +0188;LATIN SMALL LETTER C WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER C HOOK;;0187;;0187 +0189;LATIN CAPITAL LETTER AFRICAN D;Lu;0;L;;;;;N;;;;0256; +018A;LATIN CAPITAL LETTER D WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D HOOK;;;0257; +018B;LATIN CAPITAL LETTER D WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D TOPBAR;;;018C; +018C;LATIN SMALL LETTER D WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER D TOPBAR;;018B;;018B +018D;LATIN SMALL LETTER TURNED DELTA;Ll;0;L;;;;;N;;;;; +018E;LATIN CAPITAL LETTER REVERSED E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER TURNED E;;;01DD; +018F;LATIN CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;0259; +0190;LATIN CAPITAL LETTER OPEN E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER EPSILON;;;025B; +0191;LATIN CAPITAL LETTER F WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER F HOOK;;;0192; +0192;LATIN SMALL LETTER F WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT F;;0191;;0191 +0193;LATIN CAPITAL LETTER G WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G HOOK;;;0260; +0194;LATIN CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;0263; +0195;LATIN SMALL LETTER HV;Ll;0;L;;;;;N;LATIN SMALL LETTER H V;;01F6;;01F6 +0196;LATIN CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;0269; +0197;LATIN CAPITAL LETTER I WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED I;;;0268; +0198;LATIN CAPITAL LETTER K WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER K HOOK;;;0199; +0199;LATIN SMALL LETTER K WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER K HOOK;;0198;;0198 +019A;LATIN SMALL LETTER L WITH BAR;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED L;;023D;;023D +019B;LATIN SMALL LETTER LAMBDA WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED LAMBDA;;;; +019C;LATIN CAPITAL LETTER TURNED M;Lu;0;L;;;;;N;;;;026F; +019D;LATIN CAPITAL LETTER N WITH LEFT HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER N HOOK;;;0272; +019E;LATIN SMALL LETTER N WITH LONG RIGHT LEG;Ll;0;L;;;;;N;;;0220;;0220 +019F;LATIN CAPITAL LETTER O WITH MIDDLE TILDE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED O;;;0275; +01A0;LATIN CAPITAL LETTER O WITH HORN;Lu;0;L;004F 031B;;;;N;LATIN CAPITAL LETTER O HORN;;;01A1; +01A1;LATIN SMALL LETTER O WITH HORN;Ll;0;L;006F 031B;;;;N;LATIN SMALL LETTER O HORN;;01A0;;01A0 +01A2;LATIN CAPITAL LETTER OI;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O I;;;01A3; +01A3;LATIN SMALL LETTER OI;Ll;0;L;;;;;N;LATIN SMALL LETTER O I;;01A2;;01A2 +01A4;LATIN CAPITAL LETTER P WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER P HOOK;;;01A5; +01A5;LATIN SMALL LETTER P WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER P HOOK;;01A4;;01A4 +01A6;LATIN LETTER YR;Lu;0;L;;;;;N;LATIN LETTER Y R;;;0280; +01A7;LATIN CAPITAL LETTER TONE TWO;Lu;0;L;;;;;N;;;;01A8; +01A8;LATIN SMALL LETTER TONE TWO;Ll;0;L;;;;;N;;;01A7;;01A7 +01A9;LATIN CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;0283; +01AA;LATIN LETTER REVERSED ESH LOOP;Ll;0;L;;;;;N;;;;; +01AB;LATIN SMALL LETTER T WITH PALATAL HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T PALATAL HOOK;;;; +01AC;LATIN CAPITAL LETTER T WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T HOOK;;;01AD; +01AD;LATIN SMALL LETTER T WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T HOOK;;01AC;;01AC +01AE;LATIN CAPITAL LETTER T WITH RETROFLEX HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T RETROFLEX HOOK;;;0288; +01AF;LATIN CAPITAL LETTER U WITH HORN;Lu;0;L;0055 031B;;;;N;LATIN CAPITAL LETTER U HORN;;;01B0; +01B0;LATIN SMALL LETTER U WITH HORN;Ll;0;L;0075 031B;;;;N;LATIN SMALL LETTER U HORN;;01AF;;01AF +01B1;LATIN CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;028A; +01B2;LATIN CAPITAL LETTER V WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER SCRIPT V;;;028B; +01B3;LATIN CAPITAL LETTER Y WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Y HOOK;;;01B4; +01B4;LATIN SMALL LETTER Y WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Y HOOK;;01B3;;01B3 +01B5;LATIN CAPITAL LETTER Z WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Z BAR;;;01B6; +01B6;LATIN SMALL LETTER Z WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER Z BAR;;01B5;;01B5 +01B7;LATIN CAPITAL LETTER EZH;Lu;0;L;;;;;N;LATIN CAPITAL LETTER YOGH;;;0292; +01B8;LATIN CAPITAL LETTER EZH REVERSED;Lu;0;L;;;;;N;LATIN CAPITAL LETTER REVERSED YOGH;;;01B9; +01B9;LATIN SMALL LETTER EZH REVERSED;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED YOGH;;01B8;;01B8 +01BA;LATIN SMALL LETTER EZH WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH WITH TAIL;;;; +01BB;LATIN LETTER TWO WITH STROKE;Lo;0;L;;;;;N;LATIN LETTER TWO BAR;;;; +01BC;LATIN CAPITAL LETTER TONE FIVE;Lu;0;L;;;;;N;;;;01BD; +01BD;LATIN SMALL LETTER TONE FIVE;Ll;0;L;;;;;N;;;01BC;;01BC +01BE;LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER INVERTED GLOTTAL STOP BAR;;;; +01BF;LATIN LETTER WYNN;Ll;0;L;;;;;N;;;01F7;;01F7 +01C0;LATIN LETTER DENTAL CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE;;;; +01C1;LATIN LETTER LATERAL CLICK;Lo;0;L;;;;;N;LATIN LETTER DOUBLE PIPE;;;; +01C2;LATIN LETTER ALVEOLAR CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE DOUBLE BAR;;;; +01C3;LATIN LETTER RETROFLEX CLICK;Lo;0;L;;;;;N;LATIN LETTER EXCLAMATION MARK;;;; +01C4;LATIN CAPITAL LETTER DZ WITH CARON;Lu;0;L;<compat> 0044 017D;;;;N;LATIN CAPITAL LETTER D Z HACEK;;;01C6;01C5 +01C5;LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON;Lt;0;L;<compat> 0044 017E;;;;N;LATIN LETTER CAPITAL D SMALL Z HACEK;;01C4;01C6;01C5 +01C6;LATIN SMALL LETTER DZ WITH CARON;Ll;0;L;<compat> 0064 017E;;;;N;LATIN SMALL LETTER D Z HACEK;;01C4;;01C5 +01C7;LATIN CAPITAL LETTER LJ;Lu;0;L;<compat> 004C 004A;;;;N;LATIN CAPITAL LETTER L J;;;01C9;01C8 +01C8;LATIN CAPITAL LETTER L WITH SMALL LETTER J;Lt;0;L;<compat> 004C 006A;;;;N;LATIN LETTER CAPITAL L SMALL J;;01C7;01C9;01C8 +01C9;LATIN SMALL LETTER LJ;Ll;0;L;<compat> 006C 006A;;;;N;LATIN SMALL LETTER L J;;01C7;;01C8 +01CA;LATIN CAPITAL LETTER NJ;Lu;0;L;<compat> 004E 004A;;;;N;LATIN CAPITAL LETTER N J;;;01CC;01CB +01CB;LATIN CAPITAL LETTER N WITH SMALL LETTER J;Lt;0;L;<compat> 004E 006A;;;;N;LATIN LETTER CAPITAL N SMALL J;;01CA;01CC;01CB +01CC;LATIN SMALL LETTER NJ;Ll;0;L;<compat> 006E 006A;;;;N;LATIN SMALL LETTER N J;;01CA;;01CB +01CD;LATIN CAPITAL LETTER A WITH CARON;Lu;0;L;0041 030C;;;;N;LATIN CAPITAL LETTER A HACEK;;;01CE; +01CE;LATIN SMALL LETTER A WITH CARON;Ll;0;L;0061 030C;;;;N;LATIN SMALL LETTER A HACEK;;01CD;;01CD +01CF;LATIN CAPITAL LETTER I WITH CARON;Lu;0;L;0049 030C;;;;N;LATIN CAPITAL LETTER I HACEK;;;01D0; +01D0;LATIN SMALL LETTER I WITH CARON;Ll;0;L;0069 030C;;;;N;LATIN SMALL LETTER I HACEK;;01CF;;01CF +01D1;LATIN CAPITAL LETTER O WITH CARON;Lu;0;L;004F 030C;;;;N;LATIN CAPITAL LETTER O HACEK;;;01D2; +01D2;LATIN SMALL LETTER O WITH CARON;Ll;0;L;006F 030C;;;;N;LATIN SMALL LETTER O HACEK;;01D1;;01D1 +01D3;LATIN CAPITAL LETTER U WITH CARON;Lu;0;L;0055 030C;;;;N;LATIN CAPITAL LETTER U HACEK;;;01D4; +01D4;LATIN SMALL LETTER U WITH CARON;Ll;0;L;0075 030C;;;;N;LATIN SMALL LETTER U HACEK;;01D3;;01D3 +01D5;LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON;Lu;0;L;00DC 0304;;;;N;LATIN CAPITAL LETTER U DIAERESIS MACRON;;;01D6; +01D6;LATIN SMALL LETTER U WITH DIAERESIS AND MACRON;Ll;0;L;00FC 0304;;;;N;LATIN SMALL LETTER U DIAERESIS MACRON;;01D5;;01D5 +01D7;LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE;Lu;0;L;00DC 0301;;;;N;LATIN CAPITAL LETTER U DIAERESIS ACUTE;;;01D8; +01D8;LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE;Ll;0;L;00FC 0301;;;;N;LATIN SMALL LETTER U DIAERESIS ACUTE;;01D7;;01D7 +01D9;LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON;Lu;0;L;00DC 030C;;;;N;LATIN CAPITAL LETTER U DIAERESIS HACEK;;;01DA; +01DA;LATIN SMALL LETTER U WITH DIAERESIS AND CARON;Ll;0;L;00FC 030C;;;;N;LATIN SMALL LETTER U DIAERESIS HACEK;;01D9;;01D9 +01DB;LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE;Lu;0;L;00DC 0300;;;;N;LATIN CAPITAL LETTER U DIAERESIS GRAVE;;;01DC; +01DC;LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE;Ll;0;L;00FC 0300;;;;N;LATIN SMALL LETTER U DIAERESIS GRAVE;;01DB;;01DB +01DD;LATIN SMALL LETTER TURNED E;Ll;0;L;;;;;N;;;018E;;018E +01DE;LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON;Lu;0;L;00C4 0304;;;;N;LATIN CAPITAL LETTER A DIAERESIS MACRON;;;01DF; +01DF;LATIN SMALL LETTER A WITH DIAERESIS AND MACRON;Ll;0;L;00E4 0304;;;;N;LATIN SMALL LETTER A DIAERESIS MACRON;;01DE;;01DE +01E0;LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON;Lu;0;L;0226 0304;;;;N;LATIN CAPITAL LETTER A DOT MACRON;;;01E1; +01E1;LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON;Ll;0;L;0227 0304;;;;N;LATIN SMALL LETTER A DOT MACRON;;01E0;;01E0 +01E2;LATIN CAPITAL LETTER AE WITH MACRON;Lu;0;L;00C6 0304;;;;N;LATIN CAPITAL LETTER A E MACRON;;;01E3; +01E3;LATIN SMALL LETTER AE WITH MACRON;Ll;0;L;00E6 0304;;;;N;LATIN SMALL LETTER A E MACRON;;01E2;;01E2 +01E4;LATIN CAPITAL LETTER G WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G BAR;;;01E5; +01E5;LATIN SMALL LETTER G WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER G BAR;;01E4;;01E4 +01E6;LATIN CAPITAL LETTER G WITH CARON;Lu;0;L;0047 030C;;;;N;LATIN CAPITAL LETTER G HACEK;;;01E7; +01E7;LATIN SMALL LETTER G WITH CARON;Ll;0;L;0067 030C;;;;N;LATIN SMALL LETTER G HACEK;;01E6;;01E6 +01E8;LATIN CAPITAL LETTER K WITH CARON;Lu;0;L;004B 030C;;;;N;LATIN CAPITAL LETTER K HACEK;;;01E9; +01E9;LATIN SMALL LETTER K WITH CARON;Ll;0;L;006B 030C;;;;N;LATIN SMALL LETTER K HACEK;;01E8;;01E8 +01EA;LATIN CAPITAL LETTER O WITH OGONEK;Lu;0;L;004F 0328;;;;N;LATIN CAPITAL LETTER O OGONEK;;;01EB; +01EB;LATIN SMALL LETTER O WITH OGONEK;Ll;0;L;006F 0328;;;;N;LATIN SMALL LETTER O OGONEK;;01EA;;01EA +01EC;LATIN CAPITAL LETTER O WITH OGONEK AND MACRON;Lu;0;L;01EA 0304;;;;N;LATIN CAPITAL LETTER O OGONEK MACRON;;;01ED; +01ED;LATIN SMALL LETTER O WITH OGONEK AND MACRON;Ll;0;L;01EB 0304;;;;N;LATIN SMALL LETTER O OGONEK MACRON;;01EC;;01EC +01EE;LATIN CAPITAL LETTER EZH WITH CARON;Lu;0;L;01B7 030C;;;;N;LATIN CAPITAL LETTER YOGH HACEK;;;01EF; +01EF;LATIN SMALL LETTER EZH WITH CARON;Ll;0;L;0292 030C;;;;N;LATIN SMALL LETTER YOGH HACEK;;01EE;;01EE +01F0;LATIN SMALL LETTER J WITH CARON;Ll;0;L;006A 030C;;;;N;LATIN SMALL LETTER J HACEK;;;; +01F1;LATIN CAPITAL LETTER DZ;Lu;0;L;<compat> 0044 005A;;;;N;;;;01F3;01F2 +01F2;LATIN CAPITAL LETTER D WITH SMALL LETTER Z;Lt;0;L;<compat> 0044 007A;;;;N;;;01F1;01F3;01F2 +01F3;LATIN SMALL LETTER DZ;Ll;0;L;<compat> 0064 007A;;;;N;;;01F1;;01F2 +01F4;LATIN CAPITAL LETTER G WITH ACUTE;Lu;0;L;0047 0301;;;;N;;;;01F5; +01F5;LATIN SMALL LETTER G WITH ACUTE;Ll;0;L;0067 0301;;;;N;;;01F4;;01F4 +01F6;LATIN CAPITAL LETTER HWAIR;Lu;0;L;;;;;N;;;;0195; +01F7;LATIN CAPITAL LETTER WYNN;Lu;0;L;;;;;N;;;;01BF; +01F8;LATIN CAPITAL LETTER N WITH GRAVE;Lu;0;L;004E 0300;;;;N;;;;01F9; +01F9;LATIN SMALL LETTER N WITH GRAVE;Ll;0;L;006E 0300;;;;N;;;01F8;;01F8 +01FA;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE;Lu;0;L;00C5 0301;;;;N;;;;01FB; +01FB;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE;Ll;0;L;00E5 0301;;;;N;;;01FA;;01FA +01FC;LATIN CAPITAL LETTER AE WITH ACUTE;Lu;0;L;00C6 0301;;;;N;;;;01FD; +01FD;LATIN SMALL LETTER AE WITH ACUTE;Ll;0;L;00E6 0301;;;;N;;;01FC;;01FC +01FE;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE;Lu;0;L;00D8 0301;;;;N;;;;01FF; +01FF;LATIN SMALL LETTER O WITH STROKE AND ACUTE;Ll;0;L;00F8 0301;;;;N;;;01FE;;01FE +0200;LATIN CAPITAL LETTER A WITH DOUBLE GRAVE;Lu;0;L;0041 030F;;;;N;;;;0201; +0201;LATIN SMALL LETTER A WITH DOUBLE GRAVE;Ll;0;L;0061 030F;;;;N;;;0200;;0200 +0202;LATIN CAPITAL LETTER A WITH INVERTED BREVE;Lu;0;L;0041 0311;;;;N;;;;0203; +0203;LATIN SMALL LETTER A WITH INVERTED BREVE;Ll;0;L;0061 0311;;;;N;;;0202;;0202 +0204;LATIN CAPITAL LETTER E WITH DOUBLE GRAVE;Lu;0;L;0045 030F;;;;N;;;;0205; +0205;LATIN SMALL LETTER E WITH DOUBLE GRAVE;Ll;0;L;0065 030F;;;;N;;;0204;;0204 +0206;LATIN CAPITAL LETTER E WITH INVERTED BREVE;Lu;0;L;0045 0311;;;;N;;;;0207; +0207;LATIN SMALL LETTER E WITH INVERTED BREVE;Ll;0;L;0065 0311;;;;N;;;0206;;0206 +0208;LATIN CAPITAL LETTER I WITH DOUBLE GRAVE;Lu;0;L;0049 030F;;;;N;;;;0209; +0209;LATIN SMALL LETTER I WITH DOUBLE GRAVE;Ll;0;L;0069 030F;;;;N;;;0208;;0208 +020A;LATIN CAPITAL LETTER I WITH INVERTED BREVE;Lu;0;L;0049 0311;;;;N;;;;020B; +020B;LATIN SMALL LETTER I WITH INVERTED BREVE;Ll;0;L;0069 0311;;;;N;;;020A;;020A +020C;LATIN CAPITAL LETTER O WITH DOUBLE GRAVE;Lu;0;L;004F 030F;;;;N;;;;020D; +020D;LATIN SMALL LETTER O WITH DOUBLE GRAVE;Ll;0;L;006F 030F;;;;N;;;020C;;020C +020E;LATIN CAPITAL LETTER O WITH INVERTED BREVE;Lu;0;L;004F 0311;;;;N;;;;020F; +020F;LATIN SMALL LETTER O WITH INVERTED BREVE;Ll;0;L;006F 0311;;;;N;;;020E;;020E +0210;LATIN CAPITAL LETTER R WITH DOUBLE GRAVE;Lu;0;L;0052 030F;;;;N;;;;0211; +0211;LATIN SMALL LETTER R WITH DOUBLE GRAVE;Ll;0;L;0072 030F;;;;N;;;0210;;0210 +0212;LATIN CAPITAL LETTER R WITH INVERTED BREVE;Lu;0;L;0052 0311;;;;N;;;;0213; +0213;LATIN SMALL LETTER R WITH INVERTED BREVE;Ll;0;L;0072 0311;;;;N;;;0212;;0212 +0214;LATIN CAPITAL LETTER U WITH DOUBLE GRAVE;Lu;0;L;0055 030F;;;;N;;;;0215; +0215;LATIN SMALL LETTER U WITH DOUBLE GRAVE;Ll;0;L;0075 030F;;;;N;;;0214;;0214 +0216;LATIN CAPITAL LETTER U WITH INVERTED BREVE;Lu;0;L;0055 0311;;;;N;;;;0217; +0217;LATIN SMALL LETTER U WITH INVERTED BREVE;Ll;0;L;0075 0311;;;;N;;;0216;;0216 +0218;LATIN CAPITAL LETTER S WITH COMMA BELOW;Lu;0;L;0053 0326;;;;N;;;;0219; +0219;LATIN SMALL LETTER S WITH COMMA BELOW;Ll;0;L;0073 0326;;;;N;;;0218;;0218 +021A;LATIN CAPITAL LETTER T WITH COMMA BELOW;Lu;0;L;0054 0326;;;;N;;;;021B; +021B;LATIN SMALL LETTER T WITH COMMA BELOW;Ll;0;L;0074 0326;;;;N;;;021A;;021A +021C;LATIN CAPITAL LETTER YOGH;Lu;0;L;;;;;N;;;;021D; +021D;LATIN SMALL LETTER YOGH;Ll;0;L;;;;;N;;;021C;;021C +021E;LATIN CAPITAL LETTER H WITH CARON;Lu;0;L;0048 030C;;;;N;;;;021F; +021F;LATIN SMALL LETTER H WITH CARON;Ll;0;L;0068 030C;;;;N;;;021E;;021E +0220;LATIN CAPITAL LETTER N WITH LONG RIGHT LEG;Lu;0;L;;;;;N;;;;019E; +0221;LATIN SMALL LETTER D WITH CURL;Ll;0;L;;;;;N;;;;; +0222;LATIN CAPITAL LETTER OU;Lu;0;L;;;;;N;;;;0223; +0223;LATIN SMALL LETTER OU;Ll;0;L;;;;;N;;;0222;;0222 +0224;LATIN CAPITAL LETTER Z WITH HOOK;Lu;0;L;;;;;N;;;;0225; +0225;LATIN SMALL LETTER Z WITH HOOK;Ll;0;L;;;;;N;;;0224;;0224 +0226;LATIN CAPITAL LETTER A WITH DOT ABOVE;Lu;0;L;0041 0307;;;;N;;;;0227; +0227;LATIN SMALL LETTER A WITH DOT ABOVE;Ll;0;L;0061 0307;;;;N;;;0226;;0226 +0228;LATIN CAPITAL LETTER E WITH CEDILLA;Lu;0;L;0045 0327;;;;N;;;;0229; +0229;LATIN SMALL LETTER E WITH CEDILLA;Ll;0;L;0065 0327;;;;N;;;0228;;0228 +022A;LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON;Lu;0;L;00D6 0304;;;;N;;;;022B; +022B;LATIN SMALL LETTER O WITH DIAERESIS AND MACRON;Ll;0;L;00F6 0304;;;;N;;;022A;;022A +022C;LATIN CAPITAL LETTER O WITH TILDE AND MACRON;Lu;0;L;00D5 0304;;;;N;;;;022D; +022D;LATIN SMALL LETTER O WITH TILDE AND MACRON;Ll;0;L;00F5 0304;;;;N;;;022C;;022C +022E;LATIN CAPITAL LETTER O WITH DOT ABOVE;Lu;0;L;004F 0307;;;;N;;;;022F; +022F;LATIN SMALL LETTER O WITH DOT ABOVE;Ll;0;L;006F 0307;;;;N;;;022E;;022E +0230;LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON;Lu;0;L;022E 0304;;;;N;;;;0231; +0231;LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON;Ll;0;L;022F 0304;;;;N;;;0230;;0230 +0232;LATIN CAPITAL LETTER Y WITH MACRON;Lu;0;L;0059 0304;;;;N;;;;0233; +0233;LATIN SMALL LETTER Y WITH MACRON;Ll;0;L;0079 0304;;;;N;;;0232;;0232 +0234;LATIN SMALL LETTER L WITH CURL;Ll;0;L;;;;;N;;;;; +0235;LATIN SMALL LETTER N WITH CURL;Ll;0;L;;;;;N;;;;; +0236;LATIN SMALL LETTER T WITH CURL;Ll;0;L;;;;;N;;;;; +0237;LATIN SMALL LETTER DOTLESS J;Ll;0;L;;;;;N;;;;; +0238;LATIN SMALL LETTER DB DIGRAPH;Ll;0;L;;;;;N;;;;; +0239;LATIN SMALL LETTER QP DIGRAPH;Ll;0;L;;;;;N;;;;; +023A;LATIN CAPITAL LETTER A WITH STROKE;Lu;0;L;;;;;N;;;;2C65; +023B;LATIN CAPITAL LETTER C WITH STROKE;Lu;0;L;;;;;N;;;;023C; +023C;LATIN SMALL LETTER C WITH STROKE;Ll;0;L;;;;;N;;;023B;;023B +023D;LATIN CAPITAL LETTER L WITH BAR;Lu;0;L;;;;;N;;;;019A; +023E;LATIN CAPITAL LETTER T WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;2C66; +023F;LATIN SMALL LETTER S WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7E;;2C7E +0240;LATIN SMALL LETTER Z WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7F;;2C7F +0241;LATIN CAPITAL LETTER GLOTTAL STOP;Lu;0;L;;;;;N;;;;0242; +0242;LATIN SMALL LETTER GLOTTAL STOP;Ll;0;L;;;;;N;;;0241;;0241 +0243;LATIN CAPITAL LETTER B WITH STROKE;Lu;0;L;;;;;N;;;;0180; +0244;LATIN CAPITAL LETTER U BAR;Lu;0;L;;;;;N;;;;0289; +0245;LATIN CAPITAL LETTER TURNED V;Lu;0;L;;;;;N;;;;028C; +0246;LATIN CAPITAL LETTER E WITH STROKE;Lu;0;L;;;;;N;;;;0247; +0247;LATIN SMALL LETTER E WITH STROKE;Ll;0;L;;;;;N;;;0246;;0246 +0248;LATIN CAPITAL LETTER J WITH STROKE;Lu;0;L;;;;;N;;;;0249; +0249;LATIN SMALL LETTER J WITH STROKE;Ll;0;L;;;;;N;;;0248;;0248 +024A;LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL;Lu;0;L;;;;;N;;;;024B; +024B;LATIN SMALL LETTER Q WITH HOOK TAIL;Ll;0;L;;;;;N;;;024A;;024A +024C;LATIN CAPITAL LETTER R WITH STROKE;Lu;0;L;;;;;N;;;;024D; +024D;LATIN SMALL LETTER R WITH STROKE;Ll;0;L;;;;;N;;;024C;;024C +024E;LATIN CAPITAL LETTER Y WITH STROKE;Lu;0;L;;;;;N;;;;024F; +024F;LATIN SMALL LETTER Y WITH STROKE;Ll;0;L;;;;;N;;;024E;;024E +0250;LATIN SMALL LETTER TURNED A;Ll;0;L;;;;;N;;;2C6F;;2C6F +0251;LATIN SMALL LETTER ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT A;;2C6D;;2C6D +0252;LATIN SMALL LETTER TURNED ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED SCRIPT A;;2C70;;2C70 +0253;LATIN SMALL LETTER B WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER B HOOK;;0181;;0181 +0254;LATIN SMALL LETTER OPEN O;Ll;0;L;;;;;N;;;0186;;0186 +0255;LATIN SMALL LETTER C WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER C CURL;;;; +0256;LATIN SMALL LETTER D WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER D RETROFLEX HOOK;;0189;;0189 +0257;LATIN SMALL LETTER D WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER D HOOK;;018A;;018A +0258;LATIN SMALL LETTER REVERSED E;Ll;0;L;;;;;N;;;;; +0259;LATIN SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;018F;;018F +025A;LATIN SMALL LETTER SCHWA WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCHWA HOOK;;;; +025B;LATIN SMALL LETTER OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER EPSILON;;0190;;0190 +025C;LATIN SMALL LETTER REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON;;A7AB;;A7AB +025D;LATIN SMALL LETTER REVERSED OPEN E WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON HOOK;;;; +025E;LATIN SMALL LETTER CLOSED REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED REVERSED EPSILON;;;; +025F;LATIN SMALL LETTER DOTLESS J WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR;;;; +0260;LATIN SMALL LETTER G WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER G HOOK;;0193;;0193 +0261;LATIN SMALL LETTER SCRIPT G;Ll;0;L;;;;;N;;;A7AC;;A7AC +0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;; +0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194 +0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;;; +0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;A78D;;A78D +0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;A7AA;;A7AA +0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;; +0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197 +0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196 +026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;A7AE;;A7AE +026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;2C62;;2C62 +026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;A7AD;;A7AD +026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;; +026E;LATIN SMALL LETTER LEZH;Ll;0;L;;;;;N;LATIN SMALL LETTER L YOGH;;;; +026F;LATIN SMALL LETTER TURNED M;Ll;0;L;;;;;N;;;019C;;019C +0270;LATIN SMALL LETTER TURNED M WITH LONG LEG;Ll;0;L;;;;;N;;;;; +0271;LATIN SMALL LETTER M WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER M HOOK;;2C6E;;2C6E +0272;LATIN SMALL LETTER N WITH LEFT HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N HOOK;;019D;;019D +0273;LATIN SMALL LETTER N WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N RETROFLEX HOOK;;;; +0274;LATIN LETTER SMALL CAPITAL N;Ll;0;L;;;;;N;;;;; +0275;LATIN SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;019F;;019F +0276;LATIN LETTER SMALL CAPITAL OE;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL O E;;;; +0277;LATIN SMALL LETTER CLOSED OMEGA;Ll;0;L;;;;;N;;;;; +0278;LATIN SMALL LETTER PHI;Ll;0;L;;;;;N;;;;; +0279;LATIN SMALL LETTER TURNED R;Ll;0;L;;;;;N;;;;; +027A;LATIN SMALL LETTER TURNED R WITH LONG LEG;Ll;0;L;;;;;N;;;;; +027B;LATIN SMALL LETTER TURNED R WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED R HOOK;;;; +027C;LATIN SMALL LETTER R WITH LONG LEG;Ll;0;L;;;;;N;;;;; +027D;LATIN SMALL LETTER R WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER R HOOK;;2C64;;2C64 +027E;LATIN SMALL LETTER R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER FISHHOOK R;;;; +027F;LATIN SMALL LETTER REVERSED R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED FISHHOOK R;;;; +0280;LATIN LETTER SMALL CAPITAL R;Ll;0;L;;;;;N;;;01A6;;01A6 +0281;LATIN LETTER SMALL CAPITAL INVERTED R;Ll;0;L;;;;;N;;;;; +0282;LATIN SMALL LETTER S WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER S HOOK;;;; +0283;LATIN SMALL LETTER ESH;Ll;0;L;;;;;N;;;01A9;;01A9 +0284;LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR HOOK;;;; +0285;LATIN SMALL LETTER SQUAT REVERSED ESH;Ll;0;L;;;;;N;;;;; +0286;LATIN SMALL LETTER ESH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER ESH CURL;;;; +0287;LATIN SMALL LETTER TURNED T;Ll;0;L;;;;;N;;;A7B1;;A7B1 +0288;LATIN SMALL LETTER T WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T RETROFLEX HOOK;;01AE;;01AE +0289;LATIN SMALL LETTER U BAR;Ll;0;L;;;;;N;;;0244;;0244 +028A;LATIN SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;01B1;;01B1 +028B;LATIN SMALL LETTER V WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT V;;01B2;;01B2 +028C;LATIN SMALL LETTER TURNED V;Ll;0;L;;;;;N;;;0245;;0245 +028D;LATIN SMALL LETTER TURNED W;Ll;0;L;;;;;N;;;;; +028E;LATIN SMALL LETTER TURNED Y;Ll;0;L;;;;;N;;;;; +028F;LATIN LETTER SMALL CAPITAL Y;Ll;0;L;;;;;N;;;;; +0290;LATIN SMALL LETTER Z WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Z RETROFLEX HOOK;;;; +0291;LATIN SMALL LETTER Z WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER Z CURL;;;; +0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7 +0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;; +0294;LATIN LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;; +0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;; +0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;; +0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;; +0299;LATIN LETTER SMALL CAPITAL B;Ll;0;L;;;;;N;;;;; +029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;; +029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;; +029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;; +029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;A7B2;;A7B2 +029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;A7B0;;A7B0 +029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;; +02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;; +02A1;LATIN LETTER GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER GLOTTAL STOP BAR;;;; +02A2;LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP BAR;;;; +02A3;LATIN SMALL LETTER DZ DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z;;;; +02A4;LATIN SMALL LETTER DEZH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D YOGH;;;; +02A5;LATIN SMALL LETTER DZ DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z CURL;;;; +02A6;LATIN SMALL LETTER TS DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T S;;;; +02A7;LATIN SMALL LETTER TESH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T ESH;;;; +02A8;LATIN SMALL LETTER TC DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER T C CURL;;;; +02A9;LATIN SMALL LETTER FENG DIGRAPH;Ll;0;L;;;;;N;;;;; +02AA;LATIN SMALL LETTER LS DIGRAPH;Ll;0;L;;;;;N;;;;; +02AB;LATIN SMALL LETTER LZ DIGRAPH;Ll;0;L;;;;;N;;;;; +02AC;LATIN LETTER BILABIAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; +02AD;LATIN LETTER BIDENTAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; +02AE;LATIN SMALL LETTER TURNED H WITH FISHHOOK;Ll;0;L;;;;;N;;;;; +02AF;LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL;Ll;0;L;;;;;N;;;;; +02B0;MODIFIER LETTER SMALL H;Lm;0;L;<super> 0068;;;;N;;;;; +02B1;MODIFIER LETTER SMALL H WITH HOOK;Lm;0;L;<super> 0266;;;;N;MODIFIER LETTER SMALL H HOOK;;;; +02B2;MODIFIER LETTER SMALL J;Lm;0;L;<super> 006A;;;;N;;;;; +02B3;MODIFIER LETTER SMALL R;Lm;0;L;<super> 0072;;;;N;;;;; +02B4;MODIFIER LETTER SMALL TURNED R;Lm;0;L;<super> 0279;;;;N;;;;; +02B5;MODIFIER LETTER SMALL TURNED R WITH HOOK;Lm;0;L;<super> 027B;;;;N;MODIFIER LETTER SMALL TURNED R HOOK;;;; +02B6;MODIFIER LETTER SMALL CAPITAL INVERTED R;Lm;0;L;<super> 0281;;;;N;;;;; +02B7;MODIFIER LETTER SMALL W;Lm;0;L;<super> 0077;;;;N;;;;; +02B8;MODIFIER LETTER SMALL Y;Lm;0;L;<super> 0079;;;;N;;;;; +02B9;MODIFIER LETTER PRIME;Lm;0;ON;;;;;N;;;;; +02BA;MODIFIER LETTER DOUBLE PRIME;Lm;0;ON;;;;;N;;;;; +02BB;MODIFIER LETTER TURNED COMMA;Lm;0;L;;;;;N;;;;; +02BC;MODIFIER LETTER APOSTROPHE;Lm;0;L;;;;;N;;;;; +02BD;MODIFIER LETTER REVERSED COMMA;Lm;0;L;;;;;N;;;;; +02BE;MODIFIER LETTER RIGHT HALF RING;Lm;0;L;;;;;N;;;;; +02BF;MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; +02C0;MODIFIER LETTER GLOTTAL STOP;Lm;0;L;;;;;N;;;;; +02C1;MODIFIER LETTER REVERSED GLOTTAL STOP;Lm;0;L;;;;;N;;;;; +02C2;MODIFIER LETTER LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02C3;MODIFIER LETTER RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02C4;MODIFIER LETTER UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02C5;MODIFIER LETTER DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02C6;MODIFIER LETTER CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER CIRCUMFLEX;;;; +02C7;CARON;Lm;0;ON;;;;;N;MODIFIER LETTER HACEK;;;; +02C8;MODIFIER LETTER VERTICAL LINE;Lm;0;ON;;;;;N;;;;; +02C9;MODIFIER LETTER MACRON;Lm;0;ON;;;;;N;;;;; +02CA;MODIFIER LETTER ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER ACUTE;;;; +02CB;MODIFIER LETTER GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER GRAVE;;;; +02CC;MODIFIER LETTER LOW VERTICAL LINE;Lm;0;ON;;;;;N;;;;; +02CD;MODIFIER LETTER LOW MACRON;Lm;0;ON;;;;;N;;;;; +02CE;MODIFIER LETTER LOW GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW GRAVE;;;; +02CF;MODIFIER LETTER LOW ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW ACUTE;;;; +02D0;MODIFIER LETTER TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; +02D1;MODIFIER LETTER HALF TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; +02D2;MODIFIER LETTER CENTRED RIGHT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED RIGHT HALF RING;;;; +02D3;MODIFIER LETTER CENTRED LEFT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED LEFT HALF RING;;;; +02D4;MODIFIER LETTER UP TACK;Sk;0;ON;;;;;N;;;;; +02D5;MODIFIER LETTER DOWN TACK;Sk;0;ON;;;;;N;;;;; +02D6;MODIFIER LETTER PLUS SIGN;Sk;0;ON;;;;;N;;;;; +02D7;MODIFIER LETTER MINUS SIGN;Sk;0;ON;;;;;N;;;;; +02D8;BREVE;Sk;0;ON;<compat> 0020 0306;;;;N;SPACING BREVE;;;; +02D9;DOT ABOVE;Sk;0;ON;<compat> 0020 0307;;;;N;SPACING DOT ABOVE;;;; +02DA;RING ABOVE;Sk;0;ON;<compat> 0020 030A;;;;N;SPACING RING ABOVE;;;; +02DB;OGONEK;Sk;0;ON;<compat> 0020 0328;;;;N;SPACING OGONEK;;;; +02DC;SMALL TILDE;Sk;0;ON;<compat> 0020 0303;;;;N;SPACING TILDE;;;; +02DD;DOUBLE ACUTE ACCENT;Sk;0;ON;<compat> 0020 030B;;;;N;SPACING DOUBLE ACUTE;;;; +02DE;MODIFIER LETTER RHOTIC HOOK;Sk;0;ON;;;;;N;;;;; +02DF;MODIFIER LETTER CROSS ACCENT;Sk;0;ON;;;;;N;;;;; +02E0;MODIFIER LETTER SMALL GAMMA;Lm;0;L;<super> 0263;;;;N;;;;; +02E1;MODIFIER LETTER SMALL L;Lm;0;L;<super> 006C;;;;N;;;;; +02E2;MODIFIER LETTER SMALL S;Lm;0;L;<super> 0073;;;;N;;;;; +02E3;MODIFIER LETTER SMALL X;Lm;0;L;<super> 0078;;;;N;;;;; +02E4;MODIFIER LETTER SMALL REVERSED GLOTTAL STOP;Lm;0;L;<super> 0295;;;;N;;;;; +02E5;MODIFIER LETTER EXTRA-HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; +02E6;MODIFIER LETTER HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; +02E7;MODIFIER LETTER MID TONE BAR;Sk;0;ON;;;;;N;;;;; +02E8;MODIFIER LETTER LOW TONE BAR;Sk;0;ON;;;;;N;;;;; +02E9;MODIFIER LETTER EXTRA-LOW TONE BAR;Sk;0;ON;;;;;N;;;;; +02EA;MODIFIER LETTER YIN DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; +02EB;MODIFIER LETTER YANG DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; +02EC;MODIFIER LETTER VOICING;Lm;0;ON;;;;;N;;;;; +02ED;MODIFIER LETTER UNASPIRATED;Sk;0;ON;;;;;N;;;;; +02EE;MODIFIER LETTER DOUBLE APOSTROPHE;Lm;0;L;;;;;N;;;;; +02EF;MODIFIER LETTER LOW DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02F0;MODIFIER LETTER LOW UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02F1;MODIFIER LETTER LOW LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02F2;MODIFIER LETTER LOW RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02F3;MODIFIER LETTER LOW RING;Sk;0;ON;;;;;N;;;;; +02F4;MODIFIER LETTER MIDDLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; +02F5;MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; +02F6;MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT;Sk;0;ON;;;;;N;;;;; +02F7;MODIFIER LETTER LOW TILDE;Sk;0;ON;;;;;N;;;;; +02F8;MODIFIER LETTER RAISED COLON;Sk;0;ON;;;;;N;;;;; +02F9;MODIFIER LETTER BEGIN HIGH TONE;Sk;0;ON;;;;;N;;;;; +02FA;MODIFIER LETTER END HIGH TONE;Sk;0;ON;;;;;N;;;;; +02FB;MODIFIER LETTER BEGIN LOW TONE;Sk;0;ON;;;;;N;;;;; +02FC;MODIFIER LETTER END LOW TONE;Sk;0;ON;;;;;N;;;;; +02FD;MODIFIER LETTER SHELF;Sk;0;ON;;;;;N;;;;; +02FE;MODIFIER LETTER OPEN SHELF;Sk;0;ON;;;;;N;;;;; +02FF;MODIFIER LETTER LOW LEFT ARROW;Sk;0;ON;;;;;N;;;;; +0300;COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;; +0301;COMBINING ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING ACUTE;;;; +0302;COMBINING CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;NON-SPACING CIRCUMFLEX;;;; +0303;COMBINING TILDE;Mn;230;NSM;;;;;N;NON-SPACING TILDE;;;; +0304;COMBINING MACRON;Mn;230;NSM;;;;;N;NON-SPACING MACRON;;;; +0305;COMBINING OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING OVERSCORE;;;; +0306;COMBINING BREVE;Mn;230;NSM;;;;;N;NON-SPACING BREVE;;;; +0307;COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOT ABOVE;;;; +0308;COMBINING DIAERESIS;Mn;230;NSM;;;;;N;NON-SPACING DIAERESIS;;;; +0309;COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;NON-SPACING HOOK ABOVE;;;; +030A;COMBINING RING ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RING ABOVE;;;; +030B;COMBINING DOUBLE ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE ACUTE;;;; +030C;COMBINING CARON;Mn;230;NSM;;;;;N;NON-SPACING HACEK;;;; +030D;COMBINING VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL LINE ABOVE;;;; +030E;COMBINING DOUBLE VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE VERTICAL LINE ABOVE;;;; +030F;COMBINING DOUBLE GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE GRAVE;;;; +0310;COMBINING CANDRABINDU;Mn;230;NSM;;;;;N;NON-SPACING CANDRABINDU;;;; +0311;COMBINING INVERTED BREVE;Mn;230;NSM;;;;;N;NON-SPACING INVERTED BREVE;;;; +0312;COMBINING TURNED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING TURNED COMMA ABOVE;;;; +0313;COMBINING COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING COMMA ABOVE;;;; +0314;COMBINING REVERSED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING REVERSED COMMA ABOVE;;;; +0315;COMBINING COMMA ABOVE RIGHT;Mn;232;NSM;;;;;N;NON-SPACING COMMA ABOVE RIGHT;;;; +0316;COMBINING GRAVE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING GRAVE BELOW;;;; +0317;COMBINING ACUTE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING ACUTE BELOW;;;; +0318;COMBINING LEFT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT TACK BELOW;;;; +0319;COMBINING RIGHT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT TACK BELOW;;;; +031A;COMBINING LEFT ANGLE ABOVE;Mn;232;NSM;;;;;N;NON-SPACING LEFT ANGLE ABOVE;;;; +031B;COMBINING HORN;Mn;216;NSM;;;;;N;NON-SPACING HORN;;;; +031C;COMBINING LEFT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT HALF RING BELOW;;;; +031D;COMBINING UP TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING UP TACK BELOW;;;; +031E;COMBINING DOWN TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOWN TACK BELOW;;;; +031F;COMBINING PLUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING PLUS SIGN BELOW;;;; +0320;COMBINING MINUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING MINUS SIGN BELOW;;;; +0321;COMBINING PALATALIZED HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING PALATALIZED HOOK BELOW;;;; +0322;COMBINING RETROFLEX HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING RETROFLEX HOOK BELOW;;;; +0323;COMBINING DOT BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOT BELOW;;;; +0324;COMBINING DIAERESIS BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE DOT BELOW;;;; +0325;COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;; +0326;COMBINING COMMA BELOW;Mn;220;NSM;;;;;N;NON-SPACING COMMA BELOW;;;; +0327;COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;; +0328;COMBINING OGONEK;Mn;202;NSM;;;;;N;NON-SPACING OGONEK;;;; +0329;COMBINING VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;NON-SPACING VERTICAL LINE BELOW;;;; +032A;COMBINING BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BRIDGE BELOW;;;; +032B;COMBINING INVERTED DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED DOUBLE ARCH BELOW;;;; +032C;COMBINING CARON BELOW;Mn;220;NSM;;;;;N;NON-SPACING HACEK BELOW;;;; +032D;COMBINING CIRCUMFLEX ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING CIRCUMFLEX BELOW;;;; +032E;COMBINING BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BREVE BELOW;;;; +032F;COMBINING INVERTED BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BREVE BELOW;;;; +0330;COMBINING TILDE BELOW;Mn;220;NSM;;;;;N;NON-SPACING TILDE BELOW;;;; +0331;COMBINING MACRON BELOW;Mn;220;NSM;;;;;N;NON-SPACING MACRON BELOW;;;; +0332;COMBINING LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING UNDERSCORE;;;; +0333;COMBINING DOUBLE LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE UNDERSCORE;;;; +0334;COMBINING TILDE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING TILDE OVERLAY;;;; +0335;COMBINING SHORT STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT BAR OVERLAY;;;; +0336;COMBINING LONG STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG BAR OVERLAY;;;; +0337;COMBINING SHORT SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT SLASH OVERLAY;;;; +0338;COMBINING LONG SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG SLASH OVERLAY;;;; +0339;COMBINING RIGHT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT HALF RING BELOW;;;; +033A;COMBINING INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BRIDGE BELOW;;;; +033B;COMBINING SQUARE BELOW;Mn;220;NSM;;;;;N;NON-SPACING SQUARE BELOW;;;; +033C;COMBINING SEAGULL BELOW;Mn;220;NSM;;;;;N;NON-SPACING SEAGULL BELOW;;;; +033D;COMBINING X ABOVE;Mn;230;NSM;;;;;N;NON-SPACING X ABOVE;;;; +033E;COMBINING VERTICAL TILDE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL TILDE;;;; +033F;COMBINING DOUBLE OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE OVERSCORE;;;; +0340;COMBINING GRAVE TONE MARK;Mn;230;NSM;0300;;;;N;NON-SPACING GRAVE TONE MARK;;;; +0341;COMBINING ACUTE TONE MARK;Mn;230;NSM;0301;;;;N;NON-SPACING ACUTE TONE MARK;;;; +0342;COMBINING GREEK PERISPOMENI;Mn;230;NSM;;;;;N;;;;; +0343;COMBINING GREEK KORONIS;Mn;230;NSM;0313;;;;N;;;;; +0344;COMBINING GREEK DIALYTIKA TONOS;Mn;230;NSM;0308 0301;;;;N;GREEK NON-SPACING DIAERESIS TONOS;;;; +0345;COMBINING GREEK YPOGEGRAMMENI;Mn;240;NSM;;;;;N;GREEK NON-SPACING IOTA BELOW;;0399;;0399 +0346;COMBINING BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; +0347;COMBINING EQUALS SIGN BELOW;Mn;220;NSM;;;;;N;;;;; +0348;COMBINING DOUBLE VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;;;;; +0349;COMBINING LEFT ANGLE BELOW;Mn;220;NSM;;;;;N;;;;; +034A;COMBINING NOT TILDE ABOVE;Mn;230;NSM;;;;;N;;;;; +034B;COMBINING HOMOTHETIC ABOVE;Mn;230;NSM;;;;;N;;;;; +034C;COMBINING ALMOST EQUAL TO ABOVE;Mn;230;NSM;;;;;N;;;;; +034D;COMBINING LEFT RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; +034E;COMBINING UPWARDS ARROW BELOW;Mn;220;NSM;;;;;N;;;;; +034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;; +0350;COMBINING RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +0351;COMBINING LEFT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; +0352;COMBINING FERMATA;Mn;230;NSM;;;;;N;;;;; +0353;COMBINING X BELOW;Mn;220;NSM;;;;;N;;;;; +0354;COMBINING LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +0355;COMBINING RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +0356;COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +0357;COMBINING RIGHT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; +0358;COMBINING DOT ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; +0359;COMBINING ASTERISK BELOW;Mn;220;NSM;;;;;N;;;;; +035A;COMBINING DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; +035B;COMBINING ZIGZAG ABOVE;Mn;230;NSM;;;;;N;;;;; +035C;COMBINING DOUBLE BREVE BELOW;Mn;233;NSM;;;;;N;;;;; +035D;COMBINING DOUBLE BREVE;Mn;234;NSM;;;;;N;;;;; +035E;COMBINING DOUBLE MACRON;Mn;234;NSM;;;;;N;;;;; +035F;COMBINING DOUBLE MACRON BELOW;Mn;233;NSM;;;;;N;;;;; +0360;COMBINING DOUBLE TILDE;Mn;234;NSM;;;;;N;;;;; +0361;COMBINING DOUBLE INVERTED BREVE;Mn;234;NSM;;;;;N;;;;; +0362;COMBINING DOUBLE RIGHTWARDS ARROW BELOW;Mn;233;NSM;;;;;N;;;;; +0363;COMBINING LATIN SMALL LETTER A;Mn;230;NSM;;;;;N;;;;; +0364;COMBINING LATIN SMALL LETTER E;Mn;230;NSM;;;;;N;;;;; +0365;COMBINING LATIN SMALL LETTER I;Mn;230;NSM;;;;;N;;;;; +0366;COMBINING LATIN SMALL LETTER O;Mn;230;NSM;;;;;N;;;;; +0367;COMBINING LATIN SMALL LETTER U;Mn;230;NSM;;;;;N;;;;; +0368;COMBINING LATIN SMALL LETTER C;Mn;230;NSM;;;;;N;;;;; +0369;COMBINING LATIN SMALL LETTER D;Mn;230;NSM;;;;;N;;;;; +036A;COMBINING LATIN SMALL LETTER H;Mn;230;NSM;;;;;N;;;;; +036B;COMBINING LATIN SMALL LETTER M;Mn;230;NSM;;;;;N;;;;; +036C;COMBINING LATIN SMALL LETTER R;Mn;230;NSM;;;;;N;;;;; +036D;COMBINING LATIN SMALL LETTER T;Mn;230;NSM;;;;;N;;;;; +036E;COMBINING LATIN SMALL LETTER V;Mn;230;NSM;;;;;N;;;;; +036F;COMBINING LATIN SMALL LETTER X;Mn;230;NSM;;;;;N;;;;; +0370;GREEK CAPITAL LETTER HETA;Lu;0;L;;;;;N;;;;0371; +0371;GREEK SMALL LETTER HETA;Ll;0;L;;;;;N;;;0370;;0370 +0372;GREEK CAPITAL LETTER ARCHAIC SAMPI;Lu;0;L;;;;;N;;;;0373; +0373;GREEK SMALL LETTER ARCHAIC SAMPI;Ll;0;L;;;;;N;;;0372;;0372 +0374;GREEK NUMERAL SIGN;Lm;0;ON;02B9;;;;N;GREEK UPPER NUMERAL SIGN;;;; +0375;GREEK LOWER NUMERAL SIGN;Sk;0;ON;;;;;N;;;;; +0376;GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA;Lu;0;L;;;;;N;;;;0377; +0377;GREEK SMALL LETTER PAMPHYLIAN DIGAMMA;Ll;0;L;;;;;N;;;0376;;0376 +037A;GREEK YPOGEGRAMMENI;Lm;0;L;<compat> 0020 0345;;;;N;GREEK SPACING IOTA BELOW;;;; +037B;GREEK SMALL REVERSED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FD;;03FD +037C;GREEK SMALL DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FE;;03FE +037D;GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FF;;03FF +037E;GREEK QUESTION MARK;Po;0;ON;003B;;;;N;;;;; +037F;GREEK CAPITAL LETTER YOT;Lu;0;L;;;;;N;;;;03F3; +0384;GREEK TONOS;Sk;0;ON;<compat> 0020 0301;;;;N;GREEK SPACING TONOS;;;; +0385;GREEK DIALYTIKA TONOS;Sk;0;ON;00A8 0301;;;;N;GREEK SPACING DIAERESIS TONOS;;;; +0386;GREEK CAPITAL LETTER ALPHA WITH TONOS;Lu;0;L;0391 0301;;;;N;GREEK CAPITAL LETTER ALPHA TONOS;;;03AC; +0387;GREEK ANO TELEIA;Po;0;ON;00B7;;;;N;;;;; +0388;GREEK CAPITAL LETTER EPSILON WITH TONOS;Lu;0;L;0395 0301;;;;N;GREEK CAPITAL LETTER EPSILON TONOS;;;03AD; +0389;GREEK CAPITAL LETTER ETA WITH TONOS;Lu;0;L;0397 0301;;;;N;GREEK CAPITAL LETTER ETA TONOS;;;03AE; +038A;GREEK CAPITAL LETTER IOTA WITH TONOS;Lu;0;L;0399 0301;;;;N;GREEK CAPITAL LETTER IOTA TONOS;;;03AF; +038C;GREEK CAPITAL LETTER OMICRON WITH TONOS;Lu;0;L;039F 0301;;;;N;GREEK CAPITAL LETTER OMICRON TONOS;;;03CC; +038E;GREEK CAPITAL LETTER UPSILON WITH TONOS;Lu;0;L;03A5 0301;;;;N;GREEK CAPITAL LETTER UPSILON TONOS;;;03CD; +038F;GREEK CAPITAL LETTER OMEGA WITH TONOS;Lu;0;L;03A9 0301;;;;N;GREEK CAPITAL LETTER OMEGA TONOS;;;03CE; +0390;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS;Ll;0;L;03CA 0301;;;;N;GREEK SMALL LETTER IOTA DIAERESIS TONOS;;;; +0391;GREEK CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;03B1; +0392;GREEK CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;03B2; +0393;GREEK CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;03B3; +0394;GREEK CAPITAL LETTER DELTA;Lu;0;L;;;;;N;;;;03B4; +0395;GREEK CAPITAL LETTER EPSILON;Lu;0;L;;;;;N;;;;03B5; +0396;GREEK CAPITAL LETTER ZETA;Lu;0;L;;;;;N;;;;03B6; +0397;GREEK CAPITAL LETTER ETA;Lu;0;L;;;;;N;;;;03B7; +0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8; +0399;GREEK CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;03B9; +039A;GREEK CAPITAL LETTER KAPPA;Lu;0;L;;;;;N;;;;03BA; +039B;GREEK CAPITAL LETTER LAMDA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER LAMBDA;;;03BB; +039C;GREEK CAPITAL LETTER MU;Lu;0;L;;;;;N;;;;03BC; +039D;GREEK CAPITAL LETTER NU;Lu;0;L;;;;;N;;;;03BD; +039E;GREEK CAPITAL LETTER XI;Lu;0;L;;;;;N;;;;03BE; +039F;GREEK CAPITAL LETTER OMICRON;Lu;0;L;;;;;N;;;;03BF; +03A0;GREEK CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;03C0; +03A1;GREEK CAPITAL LETTER RHO;Lu;0;L;;;;;N;;;;03C1; +03A3;GREEK CAPITAL LETTER SIGMA;Lu;0;L;;;;;N;;;;03C3; +03A4;GREEK CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;03C4; +03A5;GREEK CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;03C5; +03A6;GREEK CAPITAL LETTER PHI;Lu;0;L;;;;;N;;;;03C6; +03A7;GREEK CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;03C7; +03A8;GREEK CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;03C8; +03A9;GREEK CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;03C9; +03AA;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA;Lu;0;L;0399 0308;;;;N;GREEK CAPITAL LETTER IOTA DIAERESIS;;;03CA; +03AB;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA;Lu;0;L;03A5 0308;;;;N;GREEK CAPITAL LETTER UPSILON DIAERESIS;;;03CB; +03AC;GREEK SMALL LETTER ALPHA WITH TONOS;Ll;0;L;03B1 0301;;;;N;GREEK SMALL LETTER ALPHA TONOS;;0386;;0386 +03AD;GREEK SMALL LETTER EPSILON WITH TONOS;Ll;0;L;03B5 0301;;;;N;GREEK SMALL LETTER EPSILON TONOS;;0388;;0388 +03AE;GREEK SMALL LETTER ETA WITH TONOS;Ll;0;L;03B7 0301;;;;N;GREEK SMALL LETTER ETA TONOS;;0389;;0389 +03AF;GREEK SMALL LETTER IOTA WITH TONOS;Ll;0;L;03B9 0301;;;;N;GREEK SMALL LETTER IOTA TONOS;;038A;;038A +03B0;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS;Ll;0;L;03CB 0301;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS TONOS;;;; +03B1;GREEK SMALL LETTER ALPHA;Ll;0;L;;;;;N;;;0391;;0391 +03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392 +03B3;GREEK SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0393;;0393 +03B4;GREEK SMALL LETTER DELTA;Ll;0;L;;;;;N;;;0394;;0394 +03B5;GREEK SMALL LETTER EPSILON;Ll;0;L;;;;;N;;;0395;;0395 +03B6;GREEK SMALL LETTER ZETA;Ll;0;L;;;;;N;;;0396;;0396 +03B7;GREEK SMALL LETTER ETA;Ll;0;L;;;;;N;;;0397;;0397 +03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398 +03B9;GREEK SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0399;;0399 +03BA;GREEK SMALL LETTER KAPPA;Ll;0;L;;;;;N;;;039A;;039A +03BB;GREEK SMALL LETTER LAMDA;Ll;0;L;;;;;N;GREEK SMALL LETTER LAMBDA;;039B;;039B +03BC;GREEK SMALL LETTER MU;Ll;0;L;;;;;N;;;039C;;039C +03BD;GREEK SMALL LETTER NU;Ll;0;L;;;;;N;;;039D;;039D +03BE;GREEK SMALL LETTER XI;Ll;0;L;;;;;N;;;039E;;039E +03BF;GREEK SMALL LETTER OMICRON;Ll;0;L;;;;;N;;;039F;;039F +03C0;GREEK SMALL LETTER PI;Ll;0;L;;;;;N;;;03A0;;03A0 +03C1;GREEK SMALL LETTER RHO;Ll;0;L;;;;;N;;;03A1;;03A1 +03C2;GREEK SMALL LETTER FINAL SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 +03C3;GREEK SMALL LETTER SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 +03C4;GREEK SMALL LETTER TAU;Ll;0;L;;;;;N;;;03A4;;03A4 +03C5;GREEK SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;03A5;;03A5 +03C6;GREEK SMALL LETTER PHI;Ll;0;L;;;;;N;;;03A6;;03A6 +03C7;GREEK SMALL LETTER CHI;Ll;0;L;;;;;N;;;03A7;;03A7 +03C8;GREEK SMALL LETTER PSI;Ll;0;L;;;;;N;;;03A8;;03A8 +03C9;GREEK SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;03A9;;03A9 +03CA;GREEK SMALL LETTER IOTA WITH DIALYTIKA;Ll;0;L;03B9 0308;;;;N;GREEK SMALL LETTER IOTA DIAERESIS;;03AA;;03AA +03CB;GREEK SMALL LETTER UPSILON WITH DIALYTIKA;Ll;0;L;03C5 0308;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS;;03AB;;03AB +03CC;GREEK SMALL LETTER OMICRON WITH TONOS;Ll;0;L;03BF 0301;;;;N;GREEK SMALL LETTER OMICRON TONOS;;038C;;038C +03CD;GREEK SMALL LETTER UPSILON WITH TONOS;Ll;0;L;03C5 0301;;;;N;GREEK SMALL LETTER UPSILON TONOS;;038E;;038E +03CE;GREEK SMALL LETTER OMEGA WITH TONOS;Ll;0;L;03C9 0301;;;;N;GREEK SMALL LETTER OMEGA TONOS;;038F;;038F +03CF;GREEK CAPITAL KAI SYMBOL;Lu;0;L;;;;;N;;;;03D7; +03D0;GREEK BETA SYMBOL;Ll;0;L;<compat> 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392 +03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398 +03D2;GREEK UPSILON WITH HOOK SYMBOL;Lu;0;L;<compat> 03A5;;;;N;GREEK CAPITAL LETTER UPSILON HOOK;;;; +03D3;GREEK UPSILON WITH ACUTE AND HOOK SYMBOL;Lu;0;L;03D2 0301;;;;N;GREEK CAPITAL LETTER UPSILON HOOK TONOS;;;; +03D4;GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL;Lu;0;L;03D2 0308;;;;N;GREEK CAPITAL LETTER UPSILON HOOK DIAERESIS;;;; +03D5;GREEK PHI SYMBOL;Ll;0;L;<compat> 03C6;;;;N;GREEK SMALL LETTER SCRIPT PHI;;03A6;;03A6 +03D6;GREEK PI SYMBOL;Ll;0;L;<compat> 03C0;;;;N;GREEK SMALL LETTER OMEGA PI;;03A0;;03A0 +03D7;GREEK KAI SYMBOL;Ll;0;L;;;;;N;;;03CF;;03CF +03D8;GREEK LETTER ARCHAIC KOPPA;Lu;0;L;;;;;N;;;;03D9; +03D9;GREEK SMALL LETTER ARCHAIC KOPPA;Ll;0;L;;;;;N;;;03D8;;03D8 +03DA;GREEK LETTER STIGMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER STIGMA;;;03DB; +03DB;GREEK SMALL LETTER STIGMA;Ll;0;L;;;;;N;;;03DA;;03DA +03DC;GREEK LETTER DIGAMMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DIGAMMA;;;03DD; +03DD;GREEK SMALL LETTER DIGAMMA;Ll;0;L;;;;;N;;;03DC;;03DC +03DE;GREEK LETTER KOPPA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KOPPA;;;03DF; +03DF;GREEK SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;03DE;;03DE +03E0;GREEK LETTER SAMPI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SAMPI;;;03E1; +03E1;GREEK SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;03E0;;03E0 +03E2;COPTIC CAPITAL LETTER SHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHEI;;;03E3; +03E3;COPTIC SMALL LETTER SHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER SHEI;;03E2;;03E2 +03E4;COPTIC CAPITAL LETTER FEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER FEI;;;03E5; +03E5;COPTIC SMALL LETTER FEI;Ll;0;L;;;;;N;GREEK SMALL LETTER FEI;;03E4;;03E4 +03E6;COPTIC CAPITAL LETTER KHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KHEI;;;03E7; +03E7;COPTIC SMALL LETTER KHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER KHEI;;03E6;;03E6 +03E8;COPTIC CAPITAL LETTER HORI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER HORI;;;03E9; +03E9;COPTIC SMALL LETTER HORI;Ll;0;L;;;;;N;GREEK SMALL LETTER HORI;;03E8;;03E8 +03EA;COPTIC CAPITAL LETTER GANGIA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER GANGIA;;;03EB; +03EB;COPTIC SMALL LETTER GANGIA;Ll;0;L;;;;;N;GREEK SMALL LETTER GANGIA;;03EA;;03EA +03EC;COPTIC CAPITAL LETTER SHIMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHIMA;;;03ED; +03ED;COPTIC SMALL LETTER SHIMA;Ll;0;L;;;;;N;GREEK SMALL LETTER SHIMA;;03EC;;03EC +03EE;COPTIC CAPITAL LETTER DEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DEI;;;03EF; +03EF;COPTIC SMALL LETTER DEI;Ll;0;L;;;;;N;GREEK SMALL LETTER DEI;;03EE;;03EE +03F0;GREEK KAPPA SYMBOL;Ll;0;L;<compat> 03BA;;;;N;GREEK SMALL LETTER SCRIPT KAPPA;;039A;;039A +03F1;GREEK RHO SYMBOL;Ll;0;L;<compat> 03C1;;;;N;GREEK SMALL LETTER TAILED RHO;;03A1;;03A1 +03F2;GREEK LUNATE SIGMA SYMBOL;Ll;0;L;<compat> 03C2;;;;N;GREEK SMALL LETTER LUNATE SIGMA;;03F9;;03F9 +03F3;GREEK LETTER YOT;Ll;0;L;;;;;N;;;037F;;037F +03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8; +03F5;GREEK LUNATE EPSILON SYMBOL;Ll;0;L;<compat> 03B5;;;;N;;;0395;;0395 +03F6;GREEK REVERSED LUNATE EPSILON SYMBOL;Sm;0;ON;;;;;N;;;;; +03F7;GREEK CAPITAL LETTER SHO;Lu;0;L;;;;;N;;;;03F8; +03F8;GREEK SMALL LETTER SHO;Ll;0;L;;;;;N;;;03F7;;03F7 +03F9;GREEK CAPITAL LUNATE SIGMA SYMBOL;Lu;0;L;<compat> 03A3;;;;N;;;;03F2; +03FA;GREEK CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;03FB; +03FB;GREEK SMALL LETTER SAN;Ll;0;L;;;;;N;;;03FA;;03FA +03FC;GREEK RHO WITH STROKE SYMBOL;Ll;0;L;;;;;N;;;;; +03FD;GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037B; +03FE;GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037C; +03FF;GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037D; +0400;CYRILLIC CAPITAL LETTER IE WITH GRAVE;Lu;0;L;0415 0300;;;;N;;;;0450; +0401;CYRILLIC CAPITAL LETTER IO;Lu;0;L;0415 0308;;;;N;;;;0451; +0402;CYRILLIC CAPITAL LETTER DJE;Lu;0;L;;;;;N;;;;0452; +0403;CYRILLIC CAPITAL LETTER GJE;Lu;0;L;0413 0301;;;;N;;;;0453; +0404;CYRILLIC CAPITAL LETTER UKRAINIAN IE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER E;;;0454; +0405;CYRILLIC CAPITAL LETTER DZE;Lu;0;L;;;;;N;;;;0455; +0406;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER I;;;0456; +0407;CYRILLIC CAPITAL LETTER YI;Lu;0;L;0406 0308;;;;N;;;;0457; +0408;CYRILLIC CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;0458; +0409;CYRILLIC CAPITAL LETTER LJE;Lu;0;L;;;;;N;;;;0459; +040A;CYRILLIC CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;045A; +040B;CYRILLIC CAPITAL LETTER TSHE;Lu;0;L;;;;;N;;;;045B; +040C;CYRILLIC CAPITAL LETTER KJE;Lu;0;L;041A 0301;;;;N;;;;045C; +040D;CYRILLIC CAPITAL LETTER I WITH GRAVE;Lu;0;L;0418 0300;;;;N;;;;045D; +040E;CYRILLIC CAPITAL LETTER SHORT U;Lu;0;L;0423 0306;;;;N;;;;045E; +040F;CYRILLIC CAPITAL LETTER DZHE;Lu;0;L;;;;;N;;;;045F; +0410;CYRILLIC CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0430; +0411;CYRILLIC CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;0431; +0412;CYRILLIC CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;0432; +0413;CYRILLIC CAPITAL LETTER GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE;;;0433; +0414;CYRILLIC CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;0434; +0415;CYRILLIC CAPITAL LETTER IE;Lu;0;L;;;;;N;;;;0435; +0416;CYRILLIC CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;0436; +0417;CYRILLIC CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;0437; +0418;CYRILLIC CAPITAL LETTER I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER II;;;0438; +0419;CYRILLIC CAPITAL LETTER SHORT I;Lu;0;L;0418 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT II;;;0439; +041A;CYRILLIC CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;043A; +041B;CYRILLIC CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;043B; +041C;CYRILLIC CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;043C; +041D;CYRILLIC CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;043D; +041E;CYRILLIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;043E; +041F;CYRILLIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;043F; +0420;CYRILLIC CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;0440; +0421;CYRILLIC CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;0441; +0422;CYRILLIC CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;0442; +0423;CYRILLIC CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0443; +0424;CYRILLIC CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;0444; +0425;CYRILLIC CAPITAL LETTER HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA;;;0445; +0426;CYRILLIC CAPITAL LETTER TSE;Lu;0;L;;;;;N;;;;0446; +0427;CYRILLIC CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;0447; +0428;CYRILLIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0448; +0429;CYRILLIC CAPITAL LETTER SHCHA;Lu;0;L;;;;;N;;;;0449; +042A;CYRILLIC CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;044A; +042B;CYRILLIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER YERI;;;044B; +042C;CYRILLIC CAPITAL LETTER SOFT SIGN;Lu;0;L;;;;;N;;;;044C; +042D;CYRILLIC CAPITAL LETTER E;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED E;;;044D; +042E;CYRILLIC CAPITAL LETTER YU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IU;;;044E; +042F;CYRILLIC CAPITAL LETTER YA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IA;;;044F; +0430;CYRILLIC SMALL LETTER A;Ll;0;L;;;;;N;;;0410;;0410 +0431;CYRILLIC SMALL LETTER BE;Ll;0;L;;;;;N;;;0411;;0411 +0432;CYRILLIC SMALL LETTER VE;Ll;0;L;;;;;N;;;0412;;0412 +0433;CYRILLIC SMALL LETTER GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE;;0413;;0413 +0434;CYRILLIC SMALL LETTER DE;Ll;0;L;;;;;N;;;0414;;0414 +0435;CYRILLIC SMALL LETTER IE;Ll;0;L;;;;;N;;;0415;;0415 +0436;CYRILLIC SMALL LETTER ZHE;Ll;0;L;;;;;N;;;0416;;0416 +0437;CYRILLIC SMALL LETTER ZE;Ll;0;L;;;;;N;;;0417;;0417 +0438;CYRILLIC SMALL LETTER I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER II;;0418;;0418 +0439;CYRILLIC SMALL LETTER SHORT I;Ll;0;L;0438 0306;;;;N;CYRILLIC SMALL LETTER SHORT II;;0419;;0419 +043A;CYRILLIC SMALL LETTER KA;Ll;0;L;;;;;N;;;041A;;041A +043B;CYRILLIC SMALL LETTER EL;Ll;0;L;;;;;N;;;041B;;041B +043C;CYRILLIC SMALL LETTER EM;Ll;0;L;;;;;N;;;041C;;041C +043D;CYRILLIC SMALL LETTER EN;Ll;0;L;;;;;N;;;041D;;041D +043E;CYRILLIC SMALL LETTER O;Ll;0;L;;;;;N;;;041E;;041E +043F;CYRILLIC SMALL LETTER PE;Ll;0;L;;;;;N;;;041F;;041F +0440;CYRILLIC SMALL LETTER ER;Ll;0;L;;;;;N;;;0420;;0420 +0441;CYRILLIC SMALL LETTER ES;Ll;0;L;;;;;N;;;0421;;0421 +0442;CYRILLIC SMALL LETTER TE;Ll;0;L;;;;;N;;;0422;;0422 +0443;CYRILLIC SMALL LETTER U;Ll;0;L;;;;;N;;;0423;;0423 +0444;CYRILLIC SMALL LETTER EF;Ll;0;L;;;;;N;;;0424;;0424 +0445;CYRILLIC SMALL LETTER HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA;;0425;;0425 +0446;CYRILLIC SMALL LETTER TSE;Ll;0;L;;;;;N;;;0426;;0426 +0447;CYRILLIC SMALL LETTER CHE;Ll;0;L;;;;;N;;;0427;;0427 +0448;CYRILLIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;0428;;0428 +0449;CYRILLIC SMALL LETTER SHCHA;Ll;0;L;;;;;N;;;0429;;0429 +044A;CYRILLIC SMALL LETTER HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A +044B;CYRILLIC SMALL LETTER YERU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER YERI;;042B;;042B +044C;CYRILLIC SMALL LETTER SOFT SIGN;Ll;0;L;;;;;N;;;042C;;042C +044D;CYRILLIC SMALL LETTER E;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED E;;042D;;042D +044E;CYRILLIC SMALL LETTER YU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IU;;042E;;042E +044F;CYRILLIC SMALL LETTER YA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IA;;042F;;042F +0450;CYRILLIC SMALL LETTER IE WITH GRAVE;Ll;0;L;0435 0300;;;;N;;;0400;;0400 +0451;CYRILLIC SMALL LETTER IO;Ll;0;L;0435 0308;;;;N;;;0401;;0401 +0452;CYRILLIC SMALL LETTER DJE;Ll;0;L;;;;;N;;;0402;;0402 +0453;CYRILLIC SMALL LETTER GJE;Ll;0;L;0433 0301;;;;N;;;0403;;0403 +0454;CYRILLIC SMALL LETTER UKRAINIAN IE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER E;;0404;;0404 +0455;CYRILLIC SMALL LETTER DZE;Ll;0;L;;;;;N;;;0405;;0405 +0456;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER I;;0406;;0406 +0457;CYRILLIC SMALL LETTER YI;Ll;0;L;0456 0308;;;;N;;;0407;;0407 +0458;CYRILLIC SMALL LETTER JE;Ll;0;L;;;;;N;;;0408;;0408 +0459;CYRILLIC SMALL LETTER LJE;Ll;0;L;;;;;N;;;0409;;0409 +045A;CYRILLIC SMALL LETTER NJE;Ll;0;L;;;;;N;;;040A;;040A +045B;CYRILLIC SMALL LETTER TSHE;Ll;0;L;;;;;N;;;040B;;040B +045C;CYRILLIC SMALL LETTER KJE;Ll;0;L;043A 0301;;;;N;;;040C;;040C +045D;CYRILLIC SMALL LETTER I WITH GRAVE;Ll;0;L;0438 0300;;;;N;;;040D;;040D +045E;CYRILLIC SMALL LETTER SHORT U;Ll;0;L;0443 0306;;;;N;;;040E;;040E +045F;CYRILLIC SMALL LETTER DZHE;Ll;0;L;;;;;N;;;040F;;040F +0460;CYRILLIC CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;0461; +0461;CYRILLIC SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;0460;;0460 +0462;CYRILLIC CAPITAL LETTER YAT;Lu;0;L;;;;;N;;;;0463; +0463;CYRILLIC SMALL LETTER YAT;Ll;0;L;;;;;N;;;0462;;0462 +0464;CYRILLIC CAPITAL LETTER IOTIFIED E;Lu;0;L;;;;;N;;;;0465; +0465;CYRILLIC SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;0464;;0464 +0466;CYRILLIC CAPITAL LETTER LITTLE YUS;Lu;0;L;;;;;N;;;;0467; +0467;CYRILLIC SMALL LETTER LITTLE YUS;Ll;0;L;;;;;N;;;0466;;0466 +0468;CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS;Lu;0;L;;;;;N;;;;0469; +0469;CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS;Ll;0;L;;;;;N;;;0468;;0468 +046A;CYRILLIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;046B; +046B;CYRILLIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;046A;;046A +046C;CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS;Lu;0;L;;;;;N;;;;046D; +046D;CYRILLIC SMALL LETTER IOTIFIED BIG YUS;Ll;0;L;;;;;N;;;046C;;046C +046E;CYRILLIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;046F; +046F;CYRILLIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;046E;;046E +0470;CYRILLIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;0471; +0471;CYRILLIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;0470;;0470 +0472;CYRILLIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;0473; +0473;CYRILLIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;0472;;0472 +0474;CYRILLIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;0475; +0475;CYRILLIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;0474;;0474 +0476;CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Lu;0;L;0474 030F;;;;N;CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE;;;0477; +0477;CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Ll;0;L;0475 030F;;;;N;CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE;;0476;;0476 +0478;CYRILLIC CAPITAL LETTER UK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER UK DIGRAPH;;;0479; +0479;CYRILLIC SMALL LETTER UK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER UK DIGRAPH;;0478;;0478 +047A;CYRILLIC CAPITAL LETTER ROUND OMEGA;Lu;0;L;;;;;N;;;;047B; +047B;CYRILLIC SMALL LETTER ROUND OMEGA;Ll;0;L;;;;;N;;;047A;;047A +047C;CYRILLIC CAPITAL LETTER OMEGA WITH TITLO;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER OMEGA TITLO;;;047D; +047D;CYRILLIC SMALL LETTER OMEGA WITH TITLO;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER OMEGA TITLO;;047C;;047C +047E;CYRILLIC CAPITAL LETTER OT;Lu;0;L;;;;;N;;;;047F; +047F;CYRILLIC SMALL LETTER OT;Ll;0;L;;;;;N;;;047E;;047E +0480;CYRILLIC CAPITAL LETTER KOPPA;Lu;0;L;;;;;N;;;;0481; +0481;CYRILLIC SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;0480;;0480 +0482;CYRILLIC THOUSANDS SIGN;So;0;L;;;;;N;;;;; +0483;COMBINING CYRILLIC TITLO;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING TITLO;;;; +0484;COMBINING CYRILLIC PALATALIZATION;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PALATALIZATION;;;; +0485;COMBINING CYRILLIC DASIA PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING DASIA PNEUMATA;;;; +0486;COMBINING CYRILLIC PSILI PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PSILI PNEUMATA;;;; +0487;COMBINING CYRILLIC POKRYTIE;Mn;230;NSM;;;;;N;;;;; +0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;; +0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; +048A;CYRILLIC CAPITAL LETTER SHORT I WITH TAIL;Lu;0;L;;;;;N;;;;048B; +048B;CYRILLIC SMALL LETTER SHORT I WITH TAIL;Ll;0;L;;;;;N;;;048A;;048A +048C;CYRILLIC CAPITAL LETTER SEMISOFT SIGN;Lu;0;L;;;;;N;;;;048D; +048D;CYRILLIC SMALL LETTER SEMISOFT SIGN;Ll;0;L;;;;;N;;;048C;;048C +048E;CYRILLIC CAPITAL LETTER ER WITH TICK;Lu;0;L;;;;;N;;;;048F; +048F;CYRILLIC SMALL LETTER ER WITH TICK;Ll;0;L;;;;;N;;;048E;;048E +0490;CYRILLIC CAPITAL LETTER GHE WITH UPTURN;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE WITH UPTURN;;;0491; +0491;CYRILLIC SMALL LETTER GHE WITH UPTURN;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE WITH UPTURN;;0490;;0490 +0492;CYRILLIC CAPITAL LETTER GHE WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE BAR;;;0493; +0493;CYRILLIC SMALL LETTER GHE WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE BAR;;0492;;0492 +0494;CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE HOOK;;;0495; +0495;CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE HOOK;;0494;;0494 +0496;CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER;;;0497; +0497;CYRILLIC SMALL LETTER ZHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER;;0496;;0496 +0498;CYRILLIC CAPITAL LETTER ZE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZE CEDILLA;;;0499; +0499;CYRILLIC SMALL LETTER ZE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZE CEDILLA;;0498;;0498 +049A;CYRILLIC CAPITAL LETTER KA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER;;;049B; +049B;CYRILLIC SMALL LETTER KA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER;;049A;;049A +049C;CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA VERTICAL BAR;;;049D; +049D;CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA VERTICAL BAR;;049C;;049C +049E;CYRILLIC CAPITAL LETTER KA WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA BAR;;;049F; +049F;CYRILLIC SMALL LETTER KA WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA BAR;;049E;;049E +04A0;CYRILLIC CAPITAL LETTER BASHKIR KA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED GE KA;;;04A1; +04A1;CYRILLIC SMALL LETTER BASHKIR KA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED GE KA;;04A0;;04A0 +04A2;CYRILLIC CAPITAL LETTER EN WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER;;;04A3; +04A3;CYRILLIC SMALL LETTER EN WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER;;04A2;;04A2 +04A4;CYRILLIC CAPITAL LIGATURE EN GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN GE;;;04A5; +04A5;CYRILLIC SMALL LIGATURE EN GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN GE;;04A4;;04A4 +04A6;CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER PE HOOK;;;04A7; +04A7;CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER PE HOOK;;04A6;;04A6 +04A8;CYRILLIC CAPITAL LETTER ABKHASIAN HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER O HOOK;;;04A9; +04A9;CYRILLIC SMALL LETTER ABKHASIAN HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER O HOOK;;04A8;;04A8 +04AA;CYRILLIC CAPITAL LETTER ES WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ES CEDILLA;;;04AB; +04AB;CYRILLIC SMALL LETTER ES WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ES CEDILLA;;04AA;;04AA +04AC;CYRILLIC CAPITAL LETTER TE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER;;;04AD; +04AD;CYRILLIC SMALL LETTER TE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER;;04AC;;04AC +04AE;CYRILLIC CAPITAL LETTER STRAIGHT U;Lu;0;L;;;;;N;;;;04AF; +04AF;CYRILLIC SMALL LETTER STRAIGHT U;Ll;0;L;;;;;N;;;04AE;;04AE +04B0;CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER STRAIGHT U BAR;;;04B1; +04B1;CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER STRAIGHT U BAR;;04B0;;04B0 +04B2;CYRILLIC CAPITAL LETTER HA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER;;;04B3; +04B3;CYRILLIC SMALL LETTER HA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER;;04B2;;04B2 +04B4;CYRILLIC CAPITAL LIGATURE TE TSE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE TSE;;;04B5; +04B5;CYRILLIC SMALL LIGATURE TE TSE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE TSE;;04B4;;04B4 +04B6;CYRILLIC CAPITAL LETTER CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER;;;04B7; +04B7;CYRILLIC SMALL LETTER CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER;;04B6;;04B6 +04B8;CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE VERTICAL BAR;;;04B9; +04B9;CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE VERTICAL BAR;;04B8;;04B8 +04BA;CYRILLIC CAPITAL LETTER SHHA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER H;;;04BB; +04BB;CYRILLIC SMALL LETTER SHHA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER H;;04BA;;04BA +04BC;CYRILLIC CAPITAL LETTER ABKHASIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK;;;04BD; +04BD;CYRILLIC SMALL LETTER ABKHASIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK;;04BC;;04BC +04BE;CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK OGONEK;;;04BF; +04BF;CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK OGONEK;;04BE;;04BE +04C0;CYRILLIC LETTER PALOCHKA;Lu;0;L;;;;;N;CYRILLIC LETTER I;;;04CF; +04C1;CYRILLIC CAPITAL LETTER ZHE WITH BREVE;Lu;0;L;0416 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT ZHE;;;04C2; +04C2;CYRILLIC SMALL LETTER ZHE WITH BREVE;Ll;0;L;0436 0306;;;;N;CYRILLIC SMALL LETTER SHORT ZHE;;04C1;;04C1 +04C3;CYRILLIC CAPITAL LETTER KA WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA HOOK;;;04C4; +04C4;CYRILLIC SMALL LETTER KA WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA HOOK;;04C3;;04C3 +04C5;CYRILLIC CAPITAL LETTER EL WITH TAIL;Lu;0;L;;;;;N;;;;04C6; +04C6;CYRILLIC SMALL LETTER EL WITH TAIL;Ll;0;L;;;;;N;;;04C5;;04C5 +04C7;CYRILLIC CAPITAL LETTER EN WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN HOOK;;;04C8; +04C8;CYRILLIC SMALL LETTER EN WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN HOOK;;04C7;;04C7 +04C9;CYRILLIC CAPITAL LETTER EN WITH TAIL;Lu;0;L;;;;;N;;;;04CA; +04CA;CYRILLIC SMALL LETTER EN WITH TAIL;Ll;0;L;;;;;N;;;04C9;;04C9 +04CB;CYRILLIC CAPITAL LETTER KHAKASSIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER;;;04CC; +04CC;CYRILLIC SMALL LETTER KHAKASSIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER;;04CB;;04CB +04CD;CYRILLIC CAPITAL LETTER EM WITH TAIL;Lu;0;L;;;;;N;;;;04CE; +04CE;CYRILLIC SMALL LETTER EM WITH TAIL;Ll;0;L;;;;;N;;;04CD;;04CD +04CF;CYRILLIC SMALL LETTER PALOCHKA;Ll;0;L;;;;;N;;;04C0;;04C0 +04D0;CYRILLIC CAPITAL LETTER A WITH BREVE;Lu;0;L;0410 0306;;;;N;;;;04D1; +04D1;CYRILLIC SMALL LETTER A WITH BREVE;Ll;0;L;0430 0306;;;;N;;;04D0;;04D0 +04D2;CYRILLIC CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0410 0308;;;;N;;;;04D3; +04D3;CYRILLIC SMALL LETTER A WITH DIAERESIS;Ll;0;L;0430 0308;;;;N;;;04D2;;04D2 +04D4;CYRILLIC CAPITAL LIGATURE A IE;Lu;0;L;;;;;N;;;;04D5; +04D5;CYRILLIC SMALL LIGATURE A IE;Ll;0;L;;;;;N;;;04D4;;04D4 +04D6;CYRILLIC CAPITAL LETTER IE WITH BREVE;Lu;0;L;0415 0306;;;;N;;;;04D7; +04D7;CYRILLIC SMALL LETTER IE WITH BREVE;Ll;0;L;0435 0306;;;;N;;;04D6;;04D6 +04D8;CYRILLIC CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;04D9; +04D9;CYRILLIC SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;04D8;;04D8 +04DA;CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS;Lu;0;L;04D8 0308;;;;N;;;;04DB; +04DB;CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS;Ll;0;L;04D9 0308;;;;N;;;04DA;;04DA +04DC;CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS;Lu;0;L;0416 0308;;;;N;;;;04DD; +04DD;CYRILLIC SMALL LETTER ZHE WITH DIAERESIS;Ll;0;L;0436 0308;;;;N;;;04DC;;04DC +04DE;CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS;Lu;0;L;0417 0308;;;;N;;;;04DF; +04DF;CYRILLIC SMALL LETTER ZE WITH DIAERESIS;Ll;0;L;0437 0308;;;;N;;;04DE;;04DE +04E0;CYRILLIC CAPITAL LETTER ABKHASIAN DZE;Lu;0;L;;;;;N;;;;04E1; +04E1;CYRILLIC SMALL LETTER ABKHASIAN DZE;Ll;0;L;;;;;N;;;04E0;;04E0 +04E2;CYRILLIC CAPITAL LETTER I WITH MACRON;Lu;0;L;0418 0304;;;;N;;;;04E3; +04E3;CYRILLIC SMALL LETTER I WITH MACRON;Ll;0;L;0438 0304;;;;N;;;04E2;;04E2 +04E4;CYRILLIC CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0418 0308;;;;N;;;;04E5; +04E5;CYRILLIC SMALL LETTER I WITH DIAERESIS;Ll;0;L;0438 0308;;;;N;;;04E4;;04E4 +04E6;CYRILLIC CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;041E 0308;;;;N;;;;04E7; +04E7;CYRILLIC SMALL LETTER O WITH DIAERESIS;Ll;0;L;043E 0308;;;;N;;;04E6;;04E6 +04E8;CYRILLIC CAPITAL LETTER BARRED O;Lu;0;L;;;;;N;;;;04E9; +04E9;CYRILLIC SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;04E8;;04E8 +04EA;CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS;Lu;0;L;04E8 0308;;;;N;;;;04EB; +04EB;CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS;Ll;0;L;04E9 0308;;;;N;;;04EA;;04EA +04EC;CYRILLIC CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;042D 0308;;;;N;;;;04ED; +04ED;CYRILLIC SMALL LETTER E WITH DIAERESIS;Ll;0;L;044D 0308;;;;N;;;04EC;;04EC +04EE;CYRILLIC CAPITAL LETTER U WITH MACRON;Lu;0;L;0423 0304;;;;N;;;;04EF; +04EF;CYRILLIC SMALL LETTER U WITH MACRON;Ll;0;L;0443 0304;;;;N;;;04EE;;04EE +04F0;CYRILLIC CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0423 0308;;;;N;;;;04F1; +04F1;CYRILLIC SMALL LETTER U WITH DIAERESIS;Ll;0;L;0443 0308;;;;N;;;04F0;;04F0 +04F2;CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0423 030B;;;;N;;;;04F3; +04F3;CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0443 030B;;;;N;;;04F2;;04F2 +04F4;CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS;Lu;0;L;0427 0308;;;;N;;;;04F5; +04F5;CYRILLIC SMALL LETTER CHE WITH DIAERESIS;Ll;0;L;0447 0308;;;;N;;;04F4;;04F4 +04F6;CYRILLIC CAPITAL LETTER GHE WITH DESCENDER;Lu;0;L;;;;;N;;;;04F7; +04F7;CYRILLIC SMALL LETTER GHE WITH DESCENDER;Ll;0;L;;;;;N;;;04F6;;04F6 +04F8;CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS;Lu;0;L;042B 0308;;;;N;;;;04F9; +04F9;CYRILLIC SMALL LETTER YERU WITH DIAERESIS;Ll;0;L;044B 0308;;;;N;;;04F8;;04F8 +04FA;CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK;Lu;0;L;;;;;N;;;;04FB; +04FB;CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK;Ll;0;L;;;;;N;;;04FA;;04FA +04FC;CYRILLIC CAPITAL LETTER HA WITH HOOK;Lu;0;L;;;;;N;;;;04FD; +04FD;CYRILLIC SMALL LETTER HA WITH HOOK;Ll;0;L;;;;;N;;;04FC;;04FC +04FE;CYRILLIC CAPITAL LETTER HA WITH STROKE;Lu;0;L;;;;;N;;;;04FF; +04FF;CYRILLIC SMALL LETTER HA WITH STROKE;Ll;0;L;;;;;N;;;04FE;;04FE +0500;CYRILLIC CAPITAL LETTER KOMI DE;Lu;0;L;;;;;N;;;;0501; +0501;CYRILLIC SMALL LETTER KOMI DE;Ll;0;L;;;;;N;;;0500;;0500 +0502;CYRILLIC CAPITAL LETTER KOMI DJE;Lu;0;L;;;;;N;;;;0503; +0503;CYRILLIC SMALL LETTER KOMI DJE;Ll;0;L;;;;;N;;;0502;;0502 +0504;CYRILLIC CAPITAL LETTER KOMI ZJE;Lu;0;L;;;;;N;;;;0505; +0505;CYRILLIC SMALL LETTER KOMI ZJE;Ll;0;L;;;;;N;;;0504;;0504 +0506;CYRILLIC CAPITAL LETTER KOMI DZJE;Lu;0;L;;;;;N;;;;0507; +0507;CYRILLIC SMALL LETTER KOMI DZJE;Ll;0;L;;;;;N;;;0506;;0506 +0508;CYRILLIC CAPITAL LETTER KOMI LJE;Lu;0;L;;;;;N;;;;0509; +0509;CYRILLIC SMALL LETTER KOMI LJE;Ll;0;L;;;;;N;;;0508;;0508 +050A;CYRILLIC CAPITAL LETTER KOMI NJE;Lu;0;L;;;;;N;;;;050B; +050B;CYRILLIC SMALL LETTER KOMI NJE;Ll;0;L;;;;;N;;;050A;;050A +050C;CYRILLIC CAPITAL LETTER KOMI SJE;Lu;0;L;;;;;N;;;;050D; +050D;CYRILLIC SMALL LETTER KOMI SJE;Ll;0;L;;;;;N;;;050C;;050C +050E;CYRILLIC CAPITAL LETTER KOMI TJE;Lu;0;L;;;;;N;;;;050F; +050F;CYRILLIC SMALL LETTER KOMI TJE;Ll;0;L;;;;;N;;;050E;;050E +0510;CYRILLIC CAPITAL LETTER REVERSED ZE;Lu;0;L;;;;;N;;;;0511; +0511;CYRILLIC SMALL LETTER REVERSED ZE;Ll;0;L;;;;;N;;;0510;;0510 +0512;CYRILLIC CAPITAL LETTER EL WITH HOOK;Lu;0;L;;;;;N;;;;0513; +0513;CYRILLIC SMALL LETTER EL WITH HOOK;Ll;0;L;;;;;N;;;0512;;0512 +0514;CYRILLIC CAPITAL LETTER LHA;Lu;0;L;;;;;N;;;;0515; +0515;CYRILLIC SMALL LETTER LHA;Ll;0;L;;;;;N;;;0514;;0514 +0516;CYRILLIC CAPITAL LETTER RHA;Lu;0;L;;;;;N;;;;0517; +0517;CYRILLIC SMALL LETTER RHA;Ll;0;L;;;;;N;;;0516;;0516 +0518;CYRILLIC CAPITAL LETTER YAE;Lu;0;L;;;;;N;;;;0519; +0519;CYRILLIC SMALL LETTER YAE;Ll;0;L;;;;;N;;;0518;;0518 +051A;CYRILLIC CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;051B; +051B;CYRILLIC SMALL LETTER QA;Ll;0;L;;;;;N;;;051A;;051A +051C;CYRILLIC CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;051D; +051D;CYRILLIC SMALL LETTER WE;Ll;0;L;;;;;N;;;051C;;051C +051E;CYRILLIC CAPITAL LETTER ALEUT KA;Lu;0;L;;;;;N;;;;051F; +051F;CYRILLIC SMALL LETTER ALEUT KA;Ll;0;L;;;;;N;;;051E;;051E +0520;CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0521; +0521;CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0520;;0520 +0522;CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0523; +0523;CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0522;;0522 +0524;CYRILLIC CAPITAL LETTER PE WITH DESCENDER;Lu;0;L;;;;;N;;;;0525; +0525;CYRILLIC SMALL LETTER PE WITH DESCENDER;Ll;0;L;;;;;N;;;0524;;0524 +0526;CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER;Lu;0;L;;;;;N;;;;0527; +0527;CYRILLIC SMALL LETTER SHHA WITH DESCENDER;Ll;0;L;;;;;N;;;0526;;0526 +0528;CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK;Lu;0;L;;;;;N;;;;0529; +0529;CYRILLIC SMALL LETTER EN WITH LEFT HOOK;Ll;0;L;;;;;N;;;0528;;0528 +052A;CYRILLIC CAPITAL LETTER DZZHE;Lu;0;L;;;;;N;;;;052B; +052B;CYRILLIC SMALL LETTER DZZHE;Ll;0;L;;;;;N;;;052A;;052A +052C;CYRILLIC CAPITAL LETTER DCHE;Lu;0;L;;;;;N;;;;052D; +052D;CYRILLIC SMALL LETTER DCHE;Ll;0;L;;;;;N;;;052C;;052C +052E;CYRILLIC CAPITAL LETTER EL WITH DESCENDER;Lu;0;L;;;;;N;;;;052F; +052F;CYRILLIC SMALL LETTER EL WITH DESCENDER;Ll;0;L;;;;;N;;;052E;;052E +0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561; +0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562; +0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563; +0534;ARMENIAN CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;0564; +0535;ARMENIAN CAPITAL LETTER ECH;Lu;0;L;;;;;N;;;;0565; +0536;ARMENIAN CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;0566; +0537;ARMENIAN CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;0567; +0538;ARMENIAN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;0568; +0539;ARMENIAN CAPITAL LETTER TO;Lu;0;L;;;;;N;;;;0569; +053A;ARMENIAN CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;056A; +053B;ARMENIAN CAPITAL LETTER INI;Lu;0;L;;;;;N;;;;056B; +053C;ARMENIAN CAPITAL LETTER LIWN;Lu;0;L;;;;;N;;;;056C; +053D;ARMENIAN CAPITAL LETTER XEH;Lu;0;L;;;;;N;;;;056D; +053E;ARMENIAN CAPITAL LETTER CA;Lu;0;L;;;;;N;;;;056E; +053F;ARMENIAN CAPITAL LETTER KEN;Lu;0;L;;;;;N;;;;056F; +0540;ARMENIAN CAPITAL LETTER HO;Lu;0;L;;;;;N;;;;0570; +0541;ARMENIAN CAPITAL LETTER JA;Lu;0;L;;;;;N;;;;0571; +0542;ARMENIAN CAPITAL LETTER GHAD;Lu;0;L;;;;;N;ARMENIAN CAPITAL LETTER LAD;;;0572; +0543;ARMENIAN CAPITAL LETTER CHEH;Lu;0;L;;;;;N;;;;0573; +0544;ARMENIAN CAPITAL LETTER MEN;Lu;0;L;;;;;N;;;;0574; +0545;ARMENIAN CAPITAL LETTER YI;Lu;0;L;;;;;N;;;;0575; +0546;ARMENIAN CAPITAL LETTER NOW;Lu;0;L;;;;;N;;;;0576; +0547;ARMENIAN CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0577; +0548;ARMENIAN CAPITAL LETTER VO;Lu;0;L;;;;;N;;;;0578; +0549;ARMENIAN CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;0579; +054A;ARMENIAN CAPITAL LETTER PEH;Lu;0;L;;;;;N;;;;057A; +054B;ARMENIAN CAPITAL LETTER JHEH;Lu;0;L;;;;;N;;;;057B; +054C;ARMENIAN CAPITAL LETTER RA;Lu;0;L;;;;;N;;;;057C; +054D;ARMENIAN CAPITAL LETTER SEH;Lu;0;L;;;;;N;;;;057D; +054E;ARMENIAN CAPITAL LETTER VEW;Lu;0;L;;;;;N;;;;057E; +054F;ARMENIAN CAPITAL LETTER TIWN;Lu;0;L;;;;;N;;;;057F; +0550;ARMENIAN CAPITAL LETTER REH;Lu;0;L;;;;;N;;;;0580; +0551;ARMENIAN CAPITAL LETTER CO;Lu;0;L;;;;;N;;;;0581; +0552;ARMENIAN CAPITAL LETTER YIWN;Lu;0;L;;;;;N;;;;0582; +0553;ARMENIAN CAPITAL LETTER PIWR;Lu;0;L;;;;;N;;;;0583; +0554;ARMENIAN CAPITAL LETTER KEH;Lu;0;L;;;;;N;;;;0584; +0555;ARMENIAN CAPITAL LETTER OH;Lu;0;L;;;;;N;;;;0585; +0556;ARMENIAN CAPITAL LETTER FEH;Lu;0;L;;;;;N;;;;0586; +0559;ARMENIAN MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; +055A;ARMENIAN APOSTROPHE;Po;0;L;;;;;N;ARMENIAN MODIFIER LETTER RIGHT HALF RING;;;; +055B;ARMENIAN EMPHASIS MARK;Po;0;L;;;;;N;;;;; +055C;ARMENIAN EXCLAMATION MARK;Po;0;L;;;;;N;;;;; +055D;ARMENIAN COMMA;Po;0;L;;;;;N;;;;; +055E;ARMENIAN QUESTION MARK;Po;0;L;;;;;N;;;;; +055F;ARMENIAN ABBREVIATION MARK;Po;0;L;;;;;N;;;;; +0561;ARMENIAN SMALL LETTER AYB;Ll;0;L;;;;;N;;;0531;;0531 +0562;ARMENIAN SMALL LETTER BEN;Ll;0;L;;;;;N;;;0532;;0532 +0563;ARMENIAN SMALL LETTER GIM;Ll;0;L;;;;;N;;;0533;;0533 +0564;ARMENIAN SMALL LETTER DA;Ll;0;L;;;;;N;;;0534;;0534 +0565;ARMENIAN SMALL LETTER ECH;Ll;0;L;;;;;N;;;0535;;0535 +0566;ARMENIAN SMALL LETTER ZA;Ll;0;L;;;;;N;;;0536;;0536 +0567;ARMENIAN SMALL LETTER EH;Ll;0;L;;;;;N;;;0537;;0537 +0568;ARMENIAN SMALL LETTER ET;Ll;0;L;;;;;N;;;0538;;0538 +0569;ARMENIAN SMALL LETTER TO;Ll;0;L;;;;;N;;;0539;;0539 +056A;ARMENIAN SMALL LETTER ZHE;Ll;0;L;;;;;N;;;053A;;053A +056B;ARMENIAN SMALL LETTER INI;Ll;0;L;;;;;N;;;053B;;053B +056C;ARMENIAN SMALL LETTER LIWN;Ll;0;L;;;;;N;;;053C;;053C +056D;ARMENIAN SMALL LETTER XEH;Ll;0;L;;;;;N;;;053D;;053D +056E;ARMENIAN SMALL LETTER CA;Ll;0;L;;;;;N;;;053E;;053E +056F;ARMENIAN SMALL LETTER KEN;Ll;0;L;;;;;N;;;053F;;053F +0570;ARMENIAN SMALL LETTER HO;Ll;0;L;;;;;N;;;0540;;0540 +0571;ARMENIAN SMALL LETTER JA;Ll;0;L;;;;;N;;;0541;;0541 +0572;ARMENIAN SMALL LETTER GHAD;Ll;0;L;;;;;N;ARMENIAN SMALL LETTER LAD;;0542;;0542 +0573;ARMENIAN SMALL LETTER CHEH;Ll;0;L;;;;;N;;;0543;;0543 +0574;ARMENIAN SMALL LETTER MEN;Ll;0;L;;;;;N;;;0544;;0544 +0575;ARMENIAN SMALL LETTER YI;Ll;0;L;;;;;N;;;0545;;0545 +0576;ARMENIAN SMALL LETTER NOW;Ll;0;L;;;;;N;;;0546;;0546 +0577;ARMENIAN SMALL LETTER SHA;Ll;0;L;;;;;N;;;0547;;0547 +0578;ARMENIAN SMALL LETTER VO;Ll;0;L;;;;;N;;;0548;;0548 +0579;ARMENIAN SMALL LETTER CHA;Ll;0;L;;;;;N;;;0549;;0549 +057A;ARMENIAN SMALL LETTER PEH;Ll;0;L;;;;;N;;;054A;;054A +057B;ARMENIAN SMALL LETTER JHEH;Ll;0;L;;;;;N;;;054B;;054B +057C;ARMENIAN SMALL LETTER RA;Ll;0;L;;;;;N;;;054C;;054C +057D;ARMENIAN SMALL LETTER SEH;Ll;0;L;;;;;N;;;054D;;054D +057E;ARMENIAN SMALL LETTER VEW;Ll;0;L;;;;;N;;;054E;;054E +057F;ARMENIAN SMALL LETTER TIWN;Ll;0;L;;;;;N;;;054F;;054F +0580;ARMENIAN SMALL LETTER REH;Ll;0;L;;;;;N;;;0550;;0550 +0581;ARMENIAN SMALL LETTER CO;Ll;0;L;;;;;N;;;0551;;0551 +0582;ARMENIAN SMALL LETTER YIWN;Ll;0;L;;;;;N;;;0552;;0552 +0583;ARMENIAN SMALL LETTER PIWR;Ll;0;L;;;;;N;;;0553;;0553 +0584;ARMENIAN SMALL LETTER KEH;Ll;0;L;;;;;N;;;0554;;0554 +0585;ARMENIAN SMALL LETTER OH;Ll;0;L;;;;;N;;;0555;;0555 +0586;ARMENIAN SMALL LETTER FEH;Ll;0;L;;;;;N;;;0556;;0556 +0587;ARMENIAN SMALL LIGATURE ECH YIWN;Ll;0;L;<compat> 0565 0582;;;;N;;;;; +0589;ARMENIAN FULL STOP;Po;0;L;;;;;N;ARMENIAN PERIOD;;;; +058A;ARMENIAN HYPHEN;Pd;0;ON;;;;;N;;;;; +058D;RIGHT-FACING ARMENIAN ETERNITY SIGN;So;0;ON;;;;;N;;;;; +058E;LEFT-FACING ARMENIAN ETERNITY SIGN;So;0;ON;;;;;N;;;;; +058F;ARMENIAN DRAM SIGN;Sc;0;ET;;;;;N;;;;; +0591;HEBREW ACCENT ETNAHTA;Mn;220;NSM;;;;;N;;;;; +0592;HEBREW ACCENT SEGOL;Mn;230;NSM;;;;;N;;;;; +0593;HEBREW ACCENT SHALSHELET;Mn;230;NSM;;;;;N;;;;; +0594;HEBREW ACCENT ZAQEF QATAN;Mn;230;NSM;;;;;N;;;;; +0595;HEBREW ACCENT ZAQEF GADOL;Mn;230;NSM;;;;;N;;;;; +0596;HEBREW ACCENT TIPEHA;Mn;220;NSM;;;;;N;;;;; +0597;HEBREW ACCENT REVIA;Mn;230;NSM;;;;;N;;;;; +0598;HEBREW ACCENT ZARQA;Mn;230;NSM;;;;;N;;;;; +0599;HEBREW ACCENT PASHTA;Mn;230;NSM;;;;;N;;;;; +059A;HEBREW ACCENT YETIV;Mn;222;NSM;;;;;N;;;;; +059B;HEBREW ACCENT TEVIR;Mn;220;NSM;;;;;N;;;;; +059C;HEBREW ACCENT GERESH;Mn;230;NSM;;;;;N;;;;; +059D;HEBREW ACCENT GERESH MUQDAM;Mn;230;NSM;;;;;N;;;;; +059E;HEBREW ACCENT GERSHAYIM;Mn;230;NSM;;;;;N;;;;; +059F;HEBREW ACCENT QARNEY PARA;Mn;230;NSM;;;;;N;;;;; +05A0;HEBREW ACCENT TELISHA GEDOLA;Mn;230;NSM;;;;;N;;;;; +05A1;HEBREW ACCENT PAZER;Mn;230;NSM;;;;;N;;;;; +05A2;HEBREW ACCENT ATNAH HAFUKH;Mn;220;NSM;;;;;N;;;;; +05A3;HEBREW ACCENT MUNAH;Mn;220;NSM;;;;;N;;;;; +05A4;HEBREW ACCENT MAHAPAKH;Mn;220;NSM;;;;;N;;;;; +05A5;HEBREW ACCENT MERKHA;Mn;220;NSM;;;;;N;;;;; +05A6;HEBREW ACCENT MERKHA KEFULA;Mn;220;NSM;;;;;N;;;;; +05A7;HEBREW ACCENT DARGA;Mn;220;NSM;;;;;N;;;;; +05A8;HEBREW ACCENT QADMA;Mn;230;NSM;;;;;N;;;;; +05A9;HEBREW ACCENT TELISHA QETANA;Mn;230;NSM;;;;;N;;;;; +05AA;HEBREW ACCENT YERAH BEN YOMO;Mn;220;NSM;;;;;N;;;;; +05AB;HEBREW ACCENT OLE;Mn;230;NSM;;;;;N;;;;; +05AC;HEBREW ACCENT ILUY;Mn;230;NSM;;;;;N;;;;; +05AD;HEBREW ACCENT DEHI;Mn;222;NSM;;;;;N;;;;; +05AE;HEBREW ACCENT ZINOR;Mn;228;NSM;;;;;N;;;;; +05AF;HEBREW MARK MASORA CIRCLE;Mn;230;NSM;;;;;N;;;;; +05B0;HEBREW POINT SHEVA;Mn;10;NSM;;;;;N;;;;; +05B1;HEBREW POINT HATAF SEGOL;Mn;11;NSM;;;;;N;;;;; +05B2;HEBREW POINT HATAF PATAH;Mn;12;NSM;;;;;N;;;;; +05B3;HEBREW POINT HATAF QAMATS;Mn;13;NSM;;;;;N;;;;; +05B4;HEBREW POINT HIRIQ;Mn;14;NSM;;;;;N;;;;; +05B5;HEBREW POINT TSERE;Mn;15;NSM;;;;;N;;;;; +05B6;HEBREW POINT SEGOL;Mn;16;NSM;;;;;N;;;;; +05B7;HEBREW POINT PATAH;Mn;17;NSM;;;;;N;;;;; +05B8;HEBREW POINT QAMATS;Mn;18;NSM;;;;;N;;;;; +05B9;HEBREW POINT HOLAM;Mn;19;NSM;;;;;N;;;;; +05BA;HEBREW POINT HOLAM HASER FOR VAV;Mn;19;NSM;;;;;N;;;;; +05BB;HEBREW POINT QUBUTS;Mn;20;NSM;;;;;N;;;;; +05BC;HEBREW POINT DAGESH OR MAPIQ;Mn;21;NSM;;;;;N;HEBREW POINT DAGESH;;;; +05BD;HEBREW POINT METEG;Mn;22;NSM;;;;;N;;;;; +05BE;HEBREW PUNCTUATION MAQAF;Pd;0;R;;;;;N;;;;; +05BF;HEBREW POINT RAFE;Mn;23;NSM;;;;;N;;;;; +05C0;HEBREW PUNCTUATION PASEQ;Po;0;R;;;;;N;HEBREW POINT PASEQ;;;; +05C1;HEBREW POINT SHIN DOT;Mn;24;NSM;;;;;N;;;;; +05C2;HEBREW POINT SIN DOT;Mn;25;NSM;;;;;N;;;;; +05C3;HEBREW PUNCTUATION SOF PASUQ;Po;0;R;;;;;N;;;;; +05C4;HEBREW MARK UPPER DOT;Mn;230;NSM;;;;;N;;;;; +05C5;HEBREW MARK LOWER DOT;Mn;220;NSM;;;;;N;;;;; +05C6;HEBREW PUNCTUATION NUN HAFUKHA;Po;0;R;;;;;N;;;;; +05C7;HEBREW POINT QAMATS QATAN;Mn;18;NSM;;;;;N;;;;; +05D0;HEBREW LETTER ALEF;Lo;0;R;;;;;N;;;;; +05D1;HEBREW LETTER BET;Lo;0;R;;;;;N;;;;; +05D2;HEBREW LETTER GIMEL;Lo;0;R;;;;;N;;;;; +05D3;HEBREW LETTER DALET;Lo;0;R;;;;;N;;;;; +05D4;HEBREW LETTER HE;Lo;0;R;;;;;N;;;;; +05D5;HEBREW LETTER VAV;Lo;0;R;;;;;N;;;;; +05D6;HEBREW LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +05D7;HEBREW LETTER HET;Lo;0;R;;;;;N;;;;; +05D8;HEBREW LETTER TET;Lo;0;R;;;;;N;;;;; +05D9;HEBREW LETTER YOD;Lo;0;R;;;;;N;;;;; +05DA;HEBREW LETTER FINAL KAF;Lo;0;R;;;;;N;;;;; +05DB;HEBREW LETTER KAF;Lo;0;R;;;;;N;;;;; +05DC;HEBREW LETTER LAMED;Lo;0;R;;;;;N;;;;; +05DD;HEBREW LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; +05DE;HEBREW LETTER MEM;Lo;0;R;;;;;N;;;;; +05DF;HEBREW LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; +05E0;HEBREW LETTER NUN;Lo;0;R;;;;;N;;;;; +05E1;HEBREW LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +05E2;HEBREW LETTER AYIN;Lo;0;R;;;;;N;;;;; +05E3;HEBREW LETTER FINAL PE;Lo;0;R;;;;;N;;;;; +05E4;HEBREW LETTER PE;Lo;0;R;;;;;N;;;;; +05E5;HEBREW LETTER FINAL TSADI;Lo;0;R;;;;;N;;;;; +05E6;HEBREW LETTER TSADI;Lo;0;R;;;;;N;;;;; +05E7;HEBREW LETTER QOF;Lo;0;R;;;;;N;;;;; +05E8;HEBREW LETTER RESH;Lo;0;R;;;;;N;;;;; +05E9;HEBREW LETTER SHIN;Lo;0;R;;;;;N;;;;; +05EA;HEBREW LETTER TAV;Lo;0;R;;;;;N;;;;; +05F0;HEBREW LIGATURE YIDDISH DOUBLE VAV;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE VAV;;;; +05F1;HEBREW LIGATURE YIDDISH VAV YOD;Lo;0;R;;;;;N;HEBREW LETTER VAV YOD;;;; +05F2;HEBREW LIGATURE YIDDISH DOUBLE YOD;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE YOD;;;; +05F3;HEBREW PUNCTUATION GERESH;Po;0;R;;;;;N;;;;; +05F4;HEBREW PUNCTUATION GERSHAYIM;Po;0;R;;;;;N;;;;; +0600;ARABIC NUMBER SIGN;Cf;0;AN;;;;;N;;;;; +0601;ARABIC SIGN SANAH;Cf;0;AN;;;;;N;;;;; +0602;ARABIC FOOTNOTE MARKER;Cf;0;AN;;;;;N;;;;; +0603;ARABIC SIGN SAFHA;Cf;0;AN;;;;;N;;;;; +0604;ARABIC SIGN SAMVAT;Cf;0;AN;;;;;N;;;;; +0605;ARABIC NUMBER MARK ABOVE;Cf;0;AN;;;;;N;;;;; +0606;ARABIC-INDIC CUBE ROOT;Sm;0;ON;;;;;N;;;;; +0607;ARABIC-INDIC FOURTH ROOT;Sm;0;ON;;;;;N;;;;; +0608;ARABIC RAY;Sm;0;AL;;;;;N;;;;; +0609;ARABIC-INDIC PER MILLE SIGN;Po;0;ET;;;;;N;;;;; +060A;ARABIC-INDIC PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; +060B;AFGHANI SIGN;Sc;0;AL;;;;;N;;;;; +060C;ARABIC COMMA;Po;0;CS;;;;;N;;;;; +060D;ARABIC DATE SEPARATOR;Po;0;AL;;;;;N;;;;; +060E;ARABIC POETIC VERSE SIGN;So;0;ON;;;;;N;;;;; +060F;ARABIC SIGN MISRA;So;0;ON;;;;;N;;;;; +0610;ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM;Mn;230;NSM;;;;;N;;;;; +0611;ARABIC SIGN ALAYHE ASSALLAM;Mn;230;NSM;;;;;N;;;;; +0612;ARABIC SIGN RAHMATULLAH ALAYHE;Mn;230;NSM;;;;;N;;;;; +0613;ARABIC SIGN RADI ALLAHOU ANHU;Mn;230;NSM;;;;;N;;;;; +0614;ARABIC SIGN TAKHALLUS;Mn;230;NSM;;;;;N;;;;; +0615;ARABIC SMALL HIGH TAH;Mn;230;NSM;;;;;N;;;;; +0616;ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH;Mn;230;NSM;;;;;N;;;;; +0617;ARABIC SMALL HIGH ZAIN;Mn;230;NSM;;;;;N;;;;; +0618;ARABIC SMALL FATHA;Mn;30;NSM;;;;;N;;;;; +0619;ARABIC SMALL DAMMA;Mn;31;NSM;;;;;N;;;;; +061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;; +061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;; +061C;ARABIC LETTER MARK;Cf;0;AL;;;;;N;;;;; +061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;; +061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;; +0620;ARABIC LETTER KASHMIRI YEH;Lo;0;AL;;;;;N;;;;; +0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;; +0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;; +0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;; +0624;ARABIC LETTER WAW WITH HAMZA ABOVE;Lo;0;AL;0648 0654;;;;N;ARABIC LETTER HAMZAH ON WAW;;;; +0625;ARABIC LETTER ALEF WITH HAMZA BELOW;Lo;0;AL;0627 0655;;;;N;ARABIC LETTER HAMZAH UNDER ALEF;;;; +0626;ARABIC LETTER YEH WITH HAMZA ABOVE;Lo;0;AL;064A 0654;;;;N;ARABIC LETTER HAMZAH ON YA;;;; +0627;ARABIC LETTER ALEF;Lo;0;AL;;;;;N;;;;; +0628;ARABIC LETTER BEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA;;;; +0629;ARABIC LETTER TEH MARBUTA;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH;;;; +062A;ARABIC LETTER TEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA;;;; +062B;ARABIC LETTER THEH;Lo;0;AL;;;;;N;ARABIC LETTER THAA;;;; +062C;ARABIC LETTER JEEM;Lo;0;AL;;;;;N;;;;; +062D;ARABIC LETTER HAH;Lo;0;AL;;;;;N;ARABIC LETTER HAA;;;; +062E;ARABIC LETTER KHAH;Lo;0;AL;;;;;N;ARABIC LETTER KHAA;;;; +062F;ARABIC LETTER DAL;Lo;0;AL;;;;;N;;;;; +0630;ARABIC LETTER THAL;Lo;0;AL;;;;;N;;;;; +0631;ARABIC LETTER REH;Lo;0;AL;;;;;N;ARABIC LETTER RA;;;; +0632;ARABIC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; +0633;ARABIC LETTER SEEN;Lo;0;AL;;;;;N;;;;; +0634;ARABIC LETTER SHEEN;Lo;0;AL;;;;;N;;;;; +0635;ARABIC LETTER SAD;Lo;0;AL;;;;;N;;;;; +0636;ARABIC LETTER DAD;Lo;0;AL;;;;;N;;;;; +0637;ARABIC LETTER TAH;Lo;0;AL;;;;;N;;;;; +0638;ARABIC LETTER ZAH;Lo;0;AL;;;;;N;ARABIC LETTER DHAH;;;; +0639;ARABIC LETTER AIN;Lo;0;AL;;;;;N;;;;; +063A;ARABIC LETTER GHAIN;Lo;0;AL;;;;;N;;;;; +063B;ARABIC LETTER KEHEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +063C;ARABIC LETTER KEHEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +063D;ARABIC LETTER FARSI YEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +063E;ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +063F;ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0640;ARABIC TATWEEL;Lm;0;AL;;;;;N;;;;; +0641;ARABIC LETTER FEH;Lo;0;AL;;;;;N;ARABIC LETTER FA;;;; +0642;ARABIC LETTER QAF;Lo;0;AL;;;;;N;;;;; +0643;ARABIC LETTER KAF;Lo;0;AL;;;;;N;ARABIC LETTER CAF;;;; +0644;ARABIC LETTER LAM;Lo;0;AL;;;;;N;;;;; +0645;ARABIC LETTER MEEM;Lo;0;AL;;;;;N;;;;; +0646;ARABIC LETTER NOON;Lo;0;AL;;;;;N;;;;; +0647;ARABIC LETTER HEH;Lo;0;AL;;;;;N;ARABIC LETTER HA;;;; +0648;ARABIC LETTER WAW;Lo;0;AL;;;;;N;;;;; +0649;ARABIC LETTER ALEF MAKSURA;Lo;0;AL;;;;;N;ARABIC LETTER ALEF MAQSURAH;;;; +064A;ARABIC LETTER YEH;Lo;0;AL;;;;;N;ARABIC LETTER YA;;;; +064B;ARABIC FATHATAN;Mn;27;NSM;;;;;N;;;;; +064C;ARABIC DAMMATAN;Mn;28;NSM;;;;;N;;;;; +064D;ARABIC KASRATAN;Mn;29;NSM;;;;;N;;;;; +064E;ARABIC FATHA;Mn;30;NSM;;;;;N;ARABIC FATHAH;;;; +064F;ARABIC DAMMA;Mn;31;NSM;;;;;N;ARABIC DAMMAH;;;; +0650;ARABIC KASRA;Mn;32;NSM;;;;;N;ARABIC KASRAH;;;; +0651;ARABIC SHADDA;Mn;33;NSM;;;;;N;ARABIC SHADDAH;;;; +0652;ARABIC SUKUN;Mn;34;NSM;;;;;N;;;;; +0653;ARABIC MADDAH ABOVE;Mn;230;NSM;;;;;N;;;;; +0654;ARABIC HAMZA ABOVE;Mn;230;NSM;;;;;N;;;;; +0655;ARABIC HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; +0656;ARABIC SUBSCRIPT ALEF;Mn;220;NSM;;;;;N;;;;; +0657;ARABIC INVERTED DAMMA;Mn;230;NSM;;;;;N;;;;; +0658;ARABIC MARK NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; +0659;ARABIC ZWARAKAY;Mn;230;NSM;;;;;N;;;;; +065A;ARABIC VOWEL SIGN SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; +065B;ARABIC VOWEL SIGN INVERTED SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; +065C;ARABIC VOWEL SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; +065D;ARABIC REVERSED DAMMA;Mn;230;NSM;;;;;N;;;;; +065E;ARABIC FATHA WITH TWO DOTS;Mn;230;NSM;;;;;N;;;;; +065F;ARABIC WAVY HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; +0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; +0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; +0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; +0663;ARABIC-INDIC DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;; +0664;ARABIC-INDIC DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;; +0665;ARABIC-INDIC DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;; +0666;ARABIC-INDIC DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;; +0667;ARABIC-INDIC DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;; +0668;ARABIC-INDIC DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;; +0669;ARABIC-INDIC DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;; +066A;ARABIC PERCENT SIGN;Po;0;ET;;;;;N;;;;; +066B;ARABIC DECIMAL SEPARATOR;Po;0;AN;;;;;N;;;;; +066C;ARABIC THOUSANDS SEPARATOR;Po;0;AN;;;;;N;;;;; +066D;ARABIC FIVE POINTED STAR;Po;0;AL;;;;;N;;;;; +066E;ARABIC LETTER DOTLESS BEH;Lo;0;AL;;;;;N;;;;; +066F;ARABIC LETTER DOTLESS QAF;Lo;0;AL;;;;;N;;;;; +0670;ARABIC LETTER SUPERSCRIPT ALEF;Mn;35;NSM;;;;;N;ARABIC ALEF ABOVE;;;; +0671;ARABIC LETTER ALEF WASLA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAT WASL ON ALEF;;;; +0672;ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH ON ALEF;;;; +0673;ARABIC LETTER ALEF WITH WAVY HAMZA BELOW;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH UNDER ALEF;;;; +0674;ARABIC LETTER HIGH HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HIGH HAMZAH;;;; +0675;ARABIC LETTER HIGH HAMZA ALEF;Lo;0;AL;<compat> 0627 0674;;;;N;ARABIC LETTER HIGH HAMZAH ALEF;;;; +0676;ARABIC LETTER HIGH HAMZA WAW;Lo;0;AL;<compat> 0648 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW;;;; +0677;ARABIC LETTER U WITH HAMZA ABOVE;Lo;0;AL;<compat> 06C7 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW WITH DAMMAH;;;; +0678;ARABIC LETTER HIGH HAMZA YEH;Lo;0;AL;<compat> 064A 0674;;;;N;ARABIC LETTER HIGH HAMZAH YA;;;; +0679;ARABIC LETTER TTEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH SMALL TAH;;;; +067A;ARABIC LETTER TTEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH TWO DOTS VERTICAL ABOVE;;;; +067B;ARABIC LETTER BEEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH TWO DOTS VERTICAL BELOW;;;; +067C;ARABIC LETTER TEH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH RING;;;; +067D;ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS ABOVE DOWNWARD;;;; +067E;ARABIC LETTER PEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS BELOW;;;; +067F;ARABIC LETTER TEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH FOUR DOTS ABOVE;;;; +0680;ARABIC LETTER BEHEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH FOUR DOTS BELOW;;;; +0681;ARABIC LETTER HAH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH ON HAA;;;; +0682;ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH TWO DOTS VERTICAL ABOVE;;;; +0683;ARABIC LETTER NYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS;;;; +0684;ARABIC LETTER DYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS VERTICAL;;;; +0685;ARABIC LETTER HAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH THREE DOTS ABOVE;;;; +0686;ARABIC LETTER TCHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE THREE DOTS DOWNWARD;;;; +0687;ARABIC LETTER TCHEHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE FOUR DOTS;;;; +0688;ARABIC LETTER DDAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH SMALL TAH;;;; +0689;ARABIC LETTER DAL WITH RING;Lo;0;AL;;;;;N;;;;; +068A;ARABIC LETTER DAL WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +068B;ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; +068C;ARABIC LETTER DAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS ABOVE;;;; +068D;ARABIC LETTER DDAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS BELOW;;;; +068E;ARABIC LETTER DUL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE;;;; +068F;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARD;;;; +0690;ARABIC LETTER DAL WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0691;ARABIC LETTER RREH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL TAH;;;; +0692;ARABIC LETTER REH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V;;;; +0693;ARABIC LETTER REH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH RING;;;; +0694;ARABIC LETTER REH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW;;;; +0695;ARABIC LETTER REH WITH SMALL V BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V BELOW;;;; +0696;ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW AND DOT ABOVE;;;; +0697;ARABIC LETTER REH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH TWO DOTS ABOVE;;;; +0698;ARABIC LETTER JEH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH THREE DOTS ABOVE;;;; +0699;ARABIC LETTER REH WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH FOUR DOTS ABOVE;;;; +069A;ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +069B;ARABIC LETTER SEEN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +069C;ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +069D;ARABIC LETTER SAD WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +069E;ARABIC LETTER SAD WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +069F;ARABIC LETTER TAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06A0;ARABIC LETTER AIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06A1;ARABIC LETTER DOTLESS FEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS FA;;;; +06A2;ARABIC LETTER FEH WITH DOT MOVED BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT MOVED BELOW;;;; +06A3;ARABIC LETTER FEH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT BELOW;;;; +06A4;ARABIC LETTER VEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS ABOVE;;;; +06A5;ARABIC LETTER FEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS BELOW;;;; +06A6;ARABIC LETTER PEHEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH FOUR DOTS ABOVE;;;; +06A7;ARABIC LETTER QAF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +06A8;ARABIC LETTER QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06A9;ARABIC LETTER KEHEH;Lo;0;AL;;;;;N;ARABIC LETTER OPEN CAF;;;; +06AA;ARABIC LETTER SWASH KAF;Lo;0;AL;;;;;N;ARABIC LETTER SWASH CAF;;;; +06AB;ARABIC LETTER KAF WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH RING;;;; +06AC;ARABIC LETTER KAF WITH DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH DOT ABOVE;;;; +06AD;ARABIC LETTER NG;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS ABOVE;;;; +06AE;ARABIC LETTER KAF WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS BELOW;;;; +06AF;ARABIC LETTER GAF;Lo;0;AL;;;;;N;;;;; +06B0;ARABIC LETTER GAF WITH RING;Lo;0;AL;;;;;N;;;;; +06B1;ARABIC LETTER NGOEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS ABOVE;;;; +06B2;ARABIC LETTER GAF WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +06B3;ARABIC LETTER GUEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS VERTICAL BELOW;;;; +06B4;ARABIC LETTER GAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06B5;ARABIC LETTER LAM WITH SMALL V;Lo;0;AL;;;;;N;;;;; +06B6;ARABIC LETTER LAM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +06B7;ARABIC LETTER LAM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06B8;ARABIC LETTER LAM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +06B9;ARABIC LETTER NOON WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +06BA;ARABIC LETTER NOON GHUNNA;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON;;;; +06BB;ARABIC LETTER RNOON;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON WITH SMALL TAH;;;; +06BC;ARABIC LETTER NOON WITH RING;Lo;0;AL;;;;;N;;;;; +06BD;ARABIC LETTER NOON WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06BE;ARABIC LETTER HEH DOACHASHMEE;Lo;0;AL;;;;;N;ARABIC LETTER KNOTTED HA;;;; +06BF;ARABIC LETTER TCHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +06C0;ARABIC LETTER HEH WITH YEH ABOVE;Lo;0;AL;06D5 0654;;;;N;ARABIC LETTER HAMZAH ON HA;;;; +06C1;ARABIC LETTER HEH GOAL;Lo;0;AL;;;;;N;ARABIC LETTER HA GOAL;;;; +06C2;ARABIC LETTER HEH GOAL WITH HAMZA ABOVE;Lo;0;AL;06C1 0654;;;;N;ARABIC LETTER HAMZAH ON HA GOAL;;;; +06C3;ARABIC LETTER TEH MARBUTA GOAL;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH GOAL;;;; +06C4;ARABIC LETTER WAW WITH RING;Lo;0;AL;;;;;N;;;;; +06C5;ARABIC LETTER KIRGHIZ OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH BAR;;;; +06C6;ARABIC LETTER OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH SMALL V;;;; +06C7;ARABIC LETTER U;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH DAMMAH;;;; +06C8;ARABIC LETTER YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH ALEF ABOVE;;;; +06C9;ARABIC LETTER KIRGHIZ YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH INVERTED SMALL V;;;; +06CA;ARABIC LETTER WAW WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06CB;ARABIC LETTER VE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH THREE DOTS ABOVE;;;; +06CC;ARABIC LETTER FARSI YEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS YA;;;; +06CD;ARABIC LETTER YEH WITH TAIL;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TAIL;;;; +06CE;ARABIC LETTER YEH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH SMALL V;;;; +06CF;ARABIC LETTER WAW WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +06D0;ARABIC LETTER E;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TWO DOTS VERTICAL BELOW;;;; +06D1;ARABIC LETTER YEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH THREE DOTS BELOW;;;; +06D2;ARABIC LETTER YEH BARREE;Lo;0;AL;;;;;N;ARABIC LETTER YA BARREE;;;; +06D3;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE;Lo;0;AL;06D2 0654;;;;N;ARABIC LETTER HAMZAH ON YA BARREE;;;; +06D4;ARABIC FULL STOP;Po;0;AL;;;;;N;ARABIC PERIOD;;;; +06D5;ARABIC LETTER AE;Lo;0;AL;;;;;N;;;;; +06D6;ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; +06D7;ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; +06D8;ARABIC SMALL HIGH MEEM INITIAL FORM;Mn;230;NSM;;;;;N;;;;; +06D9;ARABIC SMALL HIGH LAM ALEF;Mn;230;NSM;;;;;N;;;;; +06DA;ARABIC SMALL HIGH JEEM;Mn;230;NSM;;;;;N;;;;; +06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;; +06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;; +06DD;ARABIC END OF AYAH;Cf;0;AN;;;;;N;;;;; +06DE;ARABIC START OF RUB EL HIZB;So;0;ON;;;;;N;;;;; +06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;; +06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;; +06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;; +06E2;ARABIC SMALL HIGH MEEM ISOLATED FORM;Mn;230;NSM;;;;;N;;;;; +06E3;ARABIC SMALL LOW SEEN;Mn;220;NSM;;;;;N;;;;; +06E4;ARABIC SMALL HIGH MADDA;Mn;230;NSM;;;;;N;;;;; +06E5;ARABIC SMALL WAW;Lm;0;AL;;;;;N;;;;; +06E6;ARABIC SMALL YEH;Lm;0;AL;;;;;N;;;;; +06E7;ARABIC SMALL HIGH YEH;Mn;230;NSM;;;;;N;;;;; +06E8;ARABIC SMALL HIGH NOON;Mn;230;NSM;;;;;N;;;;; +06E9;ARABIC PLACE OF SAJDAH;So;0;ON;;;;;N;;;;; +06EA;ARABIC EMPTY CENTRE LOW STOP;Mn;220;NSM;;;;;N;;;;; +06EB;ARABIC EMPTY CENTRE HIGH STOP;Mn;230;NSM;;;;;N;;;;; +06EC;ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE;Mn;230;NSM;;;;;N;;;;; +06ED;ARABIC SMALL LOW MEEM;Mn;220;NSM;;;;;N;;;;; +06EE;ARABIC LETTER DAL WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +06EF;ARABIC LETTER REH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +06F0;EXTENDED ARABIC-INDIC DIGIT ZERO;Nd;0;EN;;0;0;0;N;EASTERN ARABIC-INDIC DIGIT ZERO;;;; +06F1;EXTENDED ARABIC-INDIC DIGIT ONE;Nd;0;EN;;1;1;1;N;EASTERN ARABIC-INDIC DIGIT ONE;;;; +06F2;EXTENDED ARABIC-INDIC DIGIT TWO;Nd;0;EN;;2;2;2;N;EASTERN ARABIC-INDIC DIGIT TWO;;;; +06F3;EXTENDED ARABIC-INDIC DIGIT THREE;Nd;0;EN;;3;3;3;N;EASTERN ARABIC-INDIC DIGIT THREE;;;; +06F4;EXTENDED ARABIC-INDIC DIGIT FOUR;Nd;0;EN;;4;4;4;N;EASTERN ARABIC-INDIC DIGIT FOUR;;;; +06F5;EXTENDED ARABIC-INDIC DIGIT FIVE;Nd;0;EN;;5;5;5;N;EASTERN ARABIC-INDIC DIGIT FIVE;;;; +06F6;EXTENDED ARABIC-INDIC DIGIT SIX;Nd;0;EN;;6;6;6;N;EASTERN ARABIC-INDIC DIGIT SIX;;;; +06F7;EXTENDED ARABIC-INDIC DIGIT SEVEN;Nd;0;EN;;7;7;7;N;EASTERN ARABIC-INDIC DIGIT SEVEN;;;; +06F8;EXTENDED ARABIC-INDIC DIGIT EIGHT;Nd;0;EN;;8;8;8;N;EASTERN ARABIC-INDIC DIGIT EIGHT;;;; +06F9;EXTENDED ARABIC-INDIC DIGIT NINE;Nd;0;EN;;9;9;9;N;EASTERN ARABIC-INDIC DIGIT NINE;;;; +06FA;ARABIC LETTER SHEEN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +06FB;ARABIC LETTER DAD WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +06FC;ARABIC LETTER GHAIN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +06FD;ARABIC SIGN SINDHI AMPERSAND;So;0;AL;;;;;N;;;;; +06FE;ARABIC SIGN SINDHI POSTPOSITION MEN;So;0;AL;;;;;N;;;;; +06FF;ARABIC LETTER HEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +0700;SYRIAC END OF PARAGRAPH;Po;0;AL;;;;;N;;;;; +0701;SYRIAC SUPRALINEAR FULL STOP;Po;0;AL;;;;;N;;;;; +0702;SYRIAC SUBLINEAR FULL STOP;Po;0;AL;;;;;N;;;;; +0703;SYRIAC SUPRALINEAR COLON;Po;0;AL;;;;;N;;;;; +0704;SYRIAC SUBLINEAR COLON;Po;0;AL;;;;;N;;;;; +0705;SYRIAC HORIZONTAL COLON;Po;0;AL;;;;;N;;;;; +0706;SYRIAC COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; +0707;SYRIAC COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; +0708;SYRIAC SUPRALINEAR COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; +0709;SYRIAC SUBLINEAR COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; +070A;SYRIAC CONTRACTION;Po;0;AL;;;;;N;;;;; +070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;; +070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;; +070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;; +070F;SYRIAC ABBREVIATION MARK;Cf;0;AL;;;;;N;;;;; +0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;; +0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;; +0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;; +0713;SYRIAC LETTER GAMAL;Lo;0;AL;;;;;N;;;;; +0714;SYRIAC LETTER GAMAL GARSHUNI;Lo;0;AL;;;;;N;;;;; +0715;SYRIAC LETTER DALATH;Lo;0;AL;;;;;N;;;;; +0716;SYRIAC LETTER DOTLESS DALATH RISH;Lo;0;AL;;;;;N;;;;; +0717;SYRIAC LETTER HE;Lo;0;AL;;;;;N;;;;; +0718;SYRIAC LETTER WAW;Lo;0;AL;;;;;N;;;;; +0719;SYRIAC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; +071A;SYRIAC LETTER HETH;Lo;0;AL;;;;;N;;;;; +071B;SYRIAC LETTER TETH;Lo;0;AL;;;;;N;;;;; +071C;SYRIAC LETTER TETH GARSHUNI;Lo;0;AL;;;;;N;;;;; +071D;SYRIAC LETTER YUDH;Lo;0;AL;;;;;N;;;;; +071E;SYRIAC LETTER YUDH HE;Lo;0;AL;;;;;N;;;;; +071F;SYRIAC LETTER KAPH;Lo;0;AL;;;;;N;;;;; +0720;SYRIAC LETTER LAMADH;Lo;0;AL;;;;;N;;;;; +0721;SYRIAC LETTER MIM;Lo;0;AL;;;;;N;;;;; +0722;SYRIAC LETTER NUN;Lo;0;AL;;;;;N;;;;; +0723;SYRIAC LETTER SEMKATH;Lo;0;AL;;;;;N;;;;; +0724;SYRIAC LETTER FINAL SEMKATH;Lo;0;AL;;;;;N;;;;; +0725;SYRIAC LETTER E;Lo;0;AL;;;;;N;;;;; +0726;SYRIAC LETTER PE;Lo;0;AL;;;;;N;;;;; +0727;SYRIAC LETTER REVERSED PE;Lo;0;AL;;;;;N;;;;; +0728;SYRIAC LETTER SADHE;Lo;0;AL;;;;;N;;;;; +0729;SYRIAC LETTER QAPH;Lo;0;AL;;;;;N;;;;; +072A;SYRIAC LETTER RISH;Lo;0;AL;;;;;N;;;;; +072B;SYRIAC LETTER SHIN;Lo;0;AL;;;;;N;;;;; +072C;SYRIAC LETTER TAW;Lo;0;AL;;;;;N;;;;; +072D;SYRIAC LETTER PERSIAN BHETH;Lo;0;AL;;;;;N;;;;; +072E;SYRIAC LETTER PERSIAN GHAMAL;Lo;0;AL;;;;;N;;;;; +072F;SYRIAC LETTER PERSIAN DHALATH;Lo;0;AL;;;;;N;;;;; +0730;SYRIAC PTHAHA ABOVE;Mn;230;NSM;;;;;N;;;;; +0731;SYRIAC PTHAHA BELOW;Mn;220;NSM;;;;;N;;;;; +0732;SYRIAC PTHAHA DOTTED;Mn;230;NSM;;;;;N;;;;; +0733;SYRIAC ZQAPHA ABOVE;Mn;230;NSM;;;;;N;;;;; +0734;SYRIAC ZQAPHA BELOW;Mn;220;NSM;;;;;N;;;;; +0735;SYRIAC ZQAPHA DOTTED;Mn;230;NSM;;;;;N;;;;; +0736;SYRIAC RBASA ABOVE;Mn;230;NSM;;;;;N;;;;; +0737;SYRIAC RBASA BELOW;Mn;220;NSM;;;;;N;;;;; +0738;SYRIAC DOTTED ZLAMA HORIZONTAL;Mn;220;NSM;;;;;N;;;;; +0739;SYRIAC DOTTED ZLAMA ANGULAR;Mn;220;NSM;;;;;N;;;;; +073A;SYRIAC HBASA ABOVE;Mn;230;NSM;;;;;N;;;;; +073B;SYRIAC HBASA BELOW;Mn;220;NSM;;;;;N;;;;; +073C;SYRIAC HBASA-ESASA DOTTED;Mn;220;NSM;;;;;N;;;;; +073D;SYRIAC ESASA ABOVE;Mn;230;NSM;;;;;N;;;;; +073E;SYRIAC ESASA BELOW;Mn;220;NSM;;;;;N;;;;; +073F;SYRIAC RWAHA;Mn;230;NSM;;;;;N;;;;; +0740;SYRIAC FEMININE DOT;Mn;230;NSM;;;;;N;;;;; +0741;SYRIAC QUSHSHAYA;Mn;230;NSM;;;;;N;;;;; +0742;SYRIAC RUKKAKHA;Mn;220;NSM;;;;;N;;;;; +0743;SYRIAC TWO VERTICAL DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +0744;SYRIAC TWO VERTICAL DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +0745;SYRIAC THREE DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +0746;SYRIAC THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +0747;SYRIAC OBLIQUE LINE ABOVE;Mn;230;NSM;;;;;N;;;;; +0748;SYRIAC OBLIQUE LINE BELOW;Mn;220;NSM;;;;;N;;;;; +0749;SYRIAC MUSIC;Mn;230;NSM;;;;;N;;;;; +074A;SYRIAC BARREKH;Mn;230;NSM;;;;;N;;;;; +074D;SYRIAC LETTER SOGDIAN ZHAIN;Lo;0;AL;;;;;N;;;;; +074E;SYRIAC LETTER SOGDIAN KHAPH;Lo;0;AL;;;;;N;;;;; +074F;SYRIAC LETTER SOGDIAN FE;Lo;0;AL;;;;;N;;;;; +0750;ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW;Lo;0;AL;;;;;N;;;;; +0751;ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0752;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; +0753;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0754;ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +0755;ARABIC LETTER BEH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; +0756;ARABIC LETTER BEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; +0757;ARABIC LETTER HAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0758;ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; +0759;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; +075A;ARABIC LETTER DAL WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; +075B;ARABIC LETTER REH WITH STROKE;Lo;0;AL;;;;;N;;;;; +075C;ARABIC LETTER SEEN WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +075D;ARABIC LETTER AIN WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +075E;ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE;Lo;0;AL;;;;;N;;;;; +075F;ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; +0760;ARABIC LETTER FEH WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +0761;ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; +0762;ARABIC LETTER KEHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +0763;ARABIC LETTER KEHEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0764;ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; +0765;ARABIC LETTER MEEM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +0766;ARABIC LETTER MEEM WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +0767;ARABIC LETTER NOON WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +0768;ARABIC LETTER NOON WITH SMALL TAH;Lo;0;AL;;;;;N;;;;; +0769;ARABIC LETTER NOON WITH SMALL V;Lo;0;AL;;;;;N;;;;; +076A;ARABIC LETTER LAM WITH BAR;Lo;0;AL;;;;;N;;;;; +076B;ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; +076C;ARABIC LETTER REH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; +076D;ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; +076E;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW;Lo;0;AL;;;;;N;;;;; +076F;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; +0770;ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; +0771;ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; +0772;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;; +0773;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; +0774;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; +0775;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; +0776;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; +0777;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; +0778;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; +0779;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; +077A;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; +077B;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; +077C;ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; +077D;ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE;Lo;0;AL;;;;;N;;;;; +077E;ARABIC LETTER SEEN WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +077F;ARABIC LETTER KAF WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0780;THAANA LETTER HAA;Lo;0;AL;;;;;N;;;;; +0781;THAANA LETTER SHAVIYANI;Lo;0;AL;;;;;N;;;;; +0782;THAANA LETTER NOONU;Lo;0;AL;;;;;N;;;;; +0783;THAANA LETTER RAA;Lo;0;AL;;;;;N;;;;; +0784;THAANA LETTER BAA;Lo;0;AL;;;;;N;;;;; +0785;THAANA LETTER LHAVIYANI;Lo;0;AL;;;;;N;;;;; +0786;THAANA LETTER KAAFU;Lo;0;AL;;;;;N;;;;; +0787;THAANA LETTER ALIFU;Lo;0;AL;;;;;N;;;;; +0788;THAANA LETTER VAAVU;Lo;0;AL;;;;;N;;;;; +0789;THAANA LETTER MEEMU;Lo;0;AL;;;;;N;;;;; +078A;THAANA LETTER FAAFU;Lo;0;AL;;;;;N;;;;; +078B;THAANA LETTER DHAALU;Lo;0;AL;;;;;N;;;;; +078C;THAANA LETTER THAA;Lo;0;AL;;;;;N;;;;; +078D;THAANA LETTER LAAMU;Lo;0;AL;;;;;N;;;;; +078E;THAANA LETTER GAAFU;Lo;0;AL;;;;;N;;;;; +078F;THAANA LETTER GNAVIYANI;Lo;0;AL;;;;;N;;;;; +0790;THAANA LETTER SEENU;Lo;0;AL;;;;;N;;;;; +0791;THAANA LETTER DAVIYANI;Lo;0;AL;;;;;N;;;;; +0792;THAANA LETTER ZAVIYANI;Lo;0;AL;;;;;N;;;;; +0793;THAANA LETTER TAVIYANI;Lo;0;AL;;;;;N;;;;; +0794;THAANA LETTER YAA;Lo;0;AL;;;;;N;;;;; +0795;THAANA LETTER PAVIYANI;Lo;0;AL;;;;;N;;;;; +0796;THAANA LETTER JAVIYANI;Lo;0;AL;;;;;N;;;;; +0797;THAANA LETTER CHAVIYANI;Lo;0;AL;;;;;N;;;;; +0798;THAANA LETTER TTAA;Lo;0;AL;;;;;N;;;;; +0799;THAANA LETTER HHAA;Lo;0;AL;;;;;N;;;;; +079A;THAANA LETTER KHAA;Lo;0;AL;;;;;N;;;;; +079B;THAANA LETTER THAALU;Lo;0;AL;;;;;N;;;;; +079C;THAANA LETTER ZAA;Lo;0;AL;;;;;N;;;;; +079D;THAANA LETTER SHEENU;Lo;0;AL;;;;;N;;;;; +079E;THAANA LETTER SAADHU;Lo;0;AL;;;;;N;;;;; +079F;THAANA LETTER DAADHU;Lo;0;AL;;;;;N;;;;; +07A0;THAANA LETTER TO;Lo;0;AL;;;;;N;;;;; +07A1;THAANA LETTER ZO;Lo;0;AL;;;;;N;;;;; +07A2;THAANA LETTER AINU;Lo;0;AL;;;;;N;;;;; +07A3;THAANA LETTER GHAINU;Lo;0;AL;;;;;N;;;;; +07A4;THAANA LETTER QAAFU;Lo;0;AL;;;;;N;;;;; +07A5;THAANA LETTER WAAVU;Lo;0;AL;;;;;N;;;;; +07A6;THAANA ABAFILI;Mn;0;NSM;;;;;N;;;;; +07A7;THAANA AABAAFILI;Mn;0;NSM;;;;;N;;;;; +07A8;THAANA IBIFILI;Mn;0;NSM;;;;;N;;;;; +07A9;THAANA EEBEEFILI;Mn;0;NSM;;;;;N;;;;; +07AA;THAANA UBUFILI;Mn;0;NSM;;;;;N;;;;; +07AB;THAANA OOBOOFILI;Mn;0;NSM;;;;;N;;;;; +07AC;THAANA EBEFILI;Mn;0;NSM;;;;;N;;;;; +07AD;THAANA EYBEYFILI;Mn;0;NSM;;;;;N;;;;; +07AE;THAANA OBOFILI;Mn;0;NSM;;;;;N;;;;; +07AF;THAANA OABOAFILI;Mn;0;NSM;;;;;N;;;;; +07B0;THAANA SUKUN;Mn;0;NSM;;;;;N;;;;; +07B1;THAANA LETTER NAA;Lo;0;AL;;;;;N;;;;; +07C0;NKO DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; +07C1;NKO DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; +07C2;NKO DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; +07C3;NKO DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; +07C4;NKO DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; +07C5;NKO DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; +07C6;NKO DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; +07C7;NKO DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; +07C8;NKO DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; +07C9;NKO DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; +07CA;NKO LETTER A;Lo;0;R;;;;;N;;;;; +07CB;NKO LETTER EE;Lo;0;R;;;;;N;;;;; +07CC;NKO LETTER I;Lo;0;R;;;;;N;;;;; +07CD;NKO LETTER E;Lo;0;R;;;;;N;;;;; +07CE;NKO LETTER U;Lo;0;R;;;;;N;;;;; +07CF;NKO LETTER OO;Lo;0;R;;;;;N;;;;; +07D0;NKO LETTER O;Lo;0;R;;;;;N;;;;; +07D1;NKO LETTER DAGBASINNA;Lo;0;R;;;;;N;;;;; +07D2;NKO LETTER N;Lo;0;R;;;;;N;;;;; +07D3;NKO LETTER BA;Lo;0;R;;;;;N;;;;; +07D4;NKO LETTER PA;Lo;0;R;;;;;N;;;;; +07D5;NKO LETTER TA;Lo;0;R;;;;;N;;;;; +07D6;NKO LETTER JA;Lo;0;R;;;;;N;;;;; +07D7;NKO LETTER CHA;Lo;0;R;;;;;N;;;;; +07D8;NKO LETTER DA;Lo;0;R;;;;;N;;;;; +07D9;NKO LETTER RA;Lo;0;R;;;;;N;;;;; +07DA;NKO LETTER RRA;Lo;0;R;;;;;N;;;;; +07DB;NKO LETTER SA;Lo;0;R;;;;;N;;;;; +07DC;NKO LETTER GBA;Lo;0;R;;;;;N;;;;; +07DD;NKO LETTER FA;Lo;0;R;;;;;N;;;;; +07DE;NKO LETTER KA;Lo;0;R;;;;;N;;;;; +07DF;NKO LETTER LA;Lo;0;R;;;;;N;;;;; +07E0;NKO LETTER NA WOLOSO;Lo;0;R;;;;;N;;;;; +07E1;NKO LETTER MA;Lo;0;R;;;;;N;;;;; +07E2;NKO LETTER NYA;Lo;0;R;;;;;N;;;;; +07E3;NKO LETTER NA;Lo;0;R;;;;;N;;;;; +07E4;NKO LETTER HA;Lo;0;R;;;;;N;;;;; +07E5;NKO LETTER WA;Lo;0;R;;;;;N;;;;; +07E6;NKO LETTER YA;Lo;0;R;;;;;N;;;;; +07E7;NKO LETTER NYA WOLOSO;Lo;0;R;;;;;N;;;;; +07E8;NKO LETTER JONA JA;Lo;0;R;;;;;N;;;;; +07E9;NKO LETTER JONA CHA;Lo;0;R;;;;;N;;;;; +07EA;NKO LETTER JONA RA;Lo;0;R;;;;;N;;;;; +07EB;NKO COMBINING SHORT HIGH TONE;Mn;230;NSM;;;;;N;;;;; +07EC;NKO COMBINING SHORT LOW TONE;Mn;230;NSM;;;;;N;;;;; +07ED;NKO COMBINING SHORT RISING TONE;Mn;230;NSM;;;;;N;;;;; +07EE;NKO COMBINING LONG DESCENDING TONE;Mn;230;NSM;;;;;N;;;;; +07EF;NKO COMBINING LONG HIGH TONE;Mn;230;NSM;;;;;N;;;;; +07F0;NKO COMBINING LONG LOW TONE;Mn;230;NSM;;;;;N;;;;; +07F1;NKO COMBINING LONG RISING TONE;Mn;230;NSM;;;;;N;;;;; +07F2;NKO COMBINING NASALIZATION MARK;Mn;220;NSM;;;;;N;;;;; +07F3;NKO COMBINING DOUBLE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +07F4;NKO HIGH TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; +07F5;NKO LOW TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; +07F6;NKO SYMBOL OO DENNEN;So;0;ON;;;;;N;;;;; +07F7;NKO SYMBOL GBAKURUNEN;Po;0;ON;;;;;N;;;;; +07F8;NKO COMMA;Po;0;ON;;;;;N;;;;; +07F9;NKO EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +07FA;NKO LAJANYALAN;Lm;0;R;;;;;N;;;;; +0800;SAMARITAN LETTER ALAF;Lo;0;R;;;;;N;;;;; +0801;SAMARITAN LETTER BIT;Lo;0;R;;;;;N;;;;; +0802;SAMARITAN LETTER GAMAN;Lo;0;R;;;;;N;;;;; +0803;SAMARITAN LETTER DALAT;Lo;0;R;;;;;N;;;;; +0804;SAMARITAN LETTER IY;Lo;0;R;;;;;N;;;;; +0805;SAMARITAN LETTER BAA;Lo;0;R;;;;;N;;;;; +0806;SAMARITAN LETTER ZEN;Lo;0;R;;;;;N;;;;; +0807;SAMARITAN LETTER IT;Lo;0;R;;;;;N;;;;; +0808;SAMARITAN LETTER TIT;Lo;0;R;;;;;N;;;;; +0809;SAMARITAN LETTER YUT;Lo;0;R;;;;;N;;;;; +080A;SAMARITAN LETTER KAAF;Lo;0;R;;;;;N;;;;; +080B;SAMARITAN LETTER LABAT;Lo;0;R;;;;;N;;;;; +080C;SAMARITAN LETTER MIM;Lo;0;R;;;;;N;;;;; +080D;SAMARITAN LETTER NUN;Lo;0;R;;;;;N;;;;; +080E;SAMARITAN LETTER SINGAAT;Lo;0;R;;;;;N;;;;; +080F;SAMARITAN LETTER IN;Lo;0;R;;;;;N;;;;; +0810;SAMARITAN LETTER FI;Lo;0;R;;;;;N;;;;; +0811;SAMARITAN LETTER TSAADIY;Lo;0;R;;;;;N;;;;; +0812;SAMARITAN LETTER QUF;Lo;0;R;;;;;N;;;;; +0813;SAMARITAN LETTER RISH;Lo;0;R;;;;;N;;;;; +0814;SAMARITAN LETTER SHAN;Lo;0;R;;;;;N;;;;; +0815;SAMARITAN LETTER TAAF;Lo;0;R;;;;;N;;;;; +0816;SAMARITAN MARK IN;Mn;230;NSM;;;;;N;;;;; +0817;SAMARITAN MARK IN-ALAF;Mn;230;NSM;;;;;N;;;;; +0818;SAMARITAN MARK OCCLUSION;Mn;230;NSM;;;;;N;;;;; +0819;SAMARITAN MARK DAGESH;Mn;230;NSM;;;;;N;;;;; +081A;SAMARITAN MODIFIER LETTER EPENTHETIC YUT;Lm;0;R;;;;;N;;;;; +081B;SAMARITAN MARK EPENTHETIC YUT;Mn;230;NSM;;;;;N;;;;; +081C;SAMARITAN VOWEL SIGN LONG E;Mn;230;NSM;;;;;N;;;;; +081D;SAMARITAN VOWEL SIGN E;Mn;230;NSM;;;;;N;;;;; +081E;SAMARITAN VOWEL SIGN OVERLONG AA;Mn;230;NSM;;;;;N;;;;; +081F;SAMARITAN VOWEL SIGN LONG AA;Mn;230;NSM;;;;;N;;;;; +0820;SAMARITAN VOWEL SIGN AA;Mn;230;NSM;;;;;N;;;;; +0821;SAMARITAN VOWEL SIGN OVERLONG A;Mn;230;NSM;;;;;N;;;;; +0822;SAMARITAN VOWEL SIGN LONG A;Mn;230;NSM;;;;;N;;;;; +0823;SAMARITAN VOWEL SIGN A;Mn;230;NSM;;;;;N;;;;; +0824;SAMARITAN MODIFIER LETTER SHORT A;Lm;0;R;;;;;N;;;;; +0825;SAMARITAN VOWEL SIGN SHORT A;Mn;230;NSM;;;;;N;;;;; +0826;SAMARITAN VOWEL SIGN LONG U;Mn;230;NSM;;;;;N;;;;; +0827;SAMARITAN VOWEL SIGN U;Mn;230;NSM;;;;;N;;;;; +0828;SAMARITAN MODIFIER LETTER I;Lm;0;R;;;;;N;;;;; +0829;SAMARITAN VOWEL SIGN LONG I;Mn;230;NSM;;;;;N;;;;; +082A;SAMARITAN VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; +082B;SAMARITAN VOWEL SIGN O;Mn;230;NSM;;;;;N;;;;; +082C;SAMARITAN VOWEL SIGN SUKUN;Mn;230;NSM;;;;;N;;;;; +082D;SAMARITAN MARK NEQUDAA;Mn;230;NSM;;;;;N;;;;; +0830;SAMARITAN PUNCTUATION NEQUDAA;Po;0;R;;;;;N;;;;; +0831;SAMARITAN PUNCTUATION AFSAAQ;Po;0;R;;;;;N;;;;; +0832;SAMARITAN PUNCTUATION ANGED;Po;0;R;;;;;N;;;;; +0833;SAMARITAN PUNCTUATION BAU;Po;0;R;;;;;N;;;;; +0834;SAMARITAN PUNCTUATION ATMAAU;Po;0;R;;;;;N;;;;; +0835;SAMARITAN PUNCTUATION SHIYYAALAA;Po;0;R;;;;;N;;;;; +0836;SAMARITAN ABBREVIATION MARK;Po;0;R;;;;;N;;;;; +0837;SAMARITAN PUNCTUATION MELODIC QITSA;Po;0;R;;;;;N;;;;; +0838;SAMARITAN PUNCTUATION ZIQAA;Po;0;R;;;;;N;;;;; +0839;SAMARITAN PUNCTUATION QITSA;Po;0;R;;;;;N;;;;; +083A;SAMARITAN PUNCTUATION ZAEF;Po;0;R;;;;;N;;;;; +083B;SAMARITAN PUNCTUATION TURU;Po;0;R;;;;;N;;;;; +083C;SAMARITAN PUNCTUATION ARKAANU;Po;0;R;;;;;N;;;;; +083D;SAMARITAN PUNCTUATION SOF MASHFAAT;Po;0;R;;;;;N;;;;; +083E;SAMARITAN PUNCTUATION ANNAAU;Po;0;R;;;;;N;;;;; +0840;MANDAIC LETTER HALQA;Lo;0;R;;;;;N;;;;; +0841;MANDAIC LETTER AB;Lo;0;R;;;;;N;;;;; +0842;MANDAIC LETTER AG;Lo;0;R;;;;;N;;;;; +0843;MANDAIC LETTER AD;Lo;0;R;;;;;N;;;;; +0844;MANDAIC LETTER AH;Lo;0;R;;;;;N;;;;; +0845;MANDAIC LETTER USHENNA;Lo;0;R;;;;;N;;;;; +0846;MANDAIC LETTER AZ;Lo;0;R;;;;;N;;;;; +0847;MANDAIC LETTER IT;Lo;0;R;;;;;N;;;;; +0848;MANDAIC LETTER ATT;Lo;0;R;;;;;N;;;;; +0849;MANDAIC LETTER AKSA;Lo;0;R;;;;;N;;;;; +084A;MANDAIC LETTER AK;Lo;0;R;;;;;N;;;;; +084B;MANDAIC LETTER AL;Lo;0;R;;;;;N;;;;; +084C;MANDAIC LETTER AM;Lo;0;R;;;;;N;;;;; +084D;MANDAIC LETTER AN;Lo;0;R;;;;;N;;;;; +084E;MANDAIC LETTER AS;Lo;0;R;;;;;N;;;;; +084F;MANDAIC LETTER IN;Lo;0;R;;;;;N;;;;; +0850;MANDAIC LETTER AP;Lo;0;R;;;;;N;;;;; +0851;MANDAIC LETTER ASZ;Lo;0;R;;;;;N;;;;; +0852;MANDAIC LETTER AQ;Lo;0;R;;;;;N;;;;; +0853;MANDAIC LETTER AR;Lo;0;R;;;;;N;;;;; +0854;MANDAIC LETTER ASH;Lo;0;R;;;;;N;;;;; +0855;MANDAIC LETTER AT;Lo;0;R;;;;;N;;;;; +0856;MANDAIC LETTER DUSHENNA;Lo;0;R;;;;;N;;;;; +0857;MANDAIC LETTER KAD;Lo;0;R;;;;;N;;;;; +0858;MANDAIC LETTER AIN;Lo;0;R;;;;;N;;;;; +0859;MANDAIC AFFRICATION MARK;Mn;220;NSM;;;;;N;;;;; +085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;; +085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;; +085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;; +0860;SYRIAC LETTER MALAYALAM NGA;Lo;0;AL;;;;;N;;;;; +0861;SYRIAC LETTER MALAYALAM JA;Lo;0;AL;;;;;N;;;;; +0862;SYRIAC LETTER MALAYALAM NYA;Lo;0;AL;;;;;N;;;;; +0863;SYRIAC LETTER MALAYALAM TTA;Lo;0;AL;;;;;N;;;;; +0864;SYRIAC LETTER MALAYALAM NNA;Lo;0;AL;;;;;N;;;;; +0865;SYRIAC LETTER MALAYALAM NNNA;Lo;0;AL;;;;;N;;;;; +0866;SYRIAC LETTER MALAYALAM BHA;Lo;0;AL;;;;;N;;;;; +0867;SYRIAC LETTER MALAYALAM RA;Lo;0;AL;;;;;N;;;;; +0868;SYRIAC LETTER MALAYALAM LLA;Lo;0;AL;;;;;N;;;;; +0869;SYRIAC LETTER MALAYALAM LLLA;Lo;0;AL;;;;;N;;;;; +086A;SYRIAC LETTER MALAYALAM SSA;Lo;0;AL;;;;;N;;;;; +08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;; +08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; +08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08A3;ARABIC LETTER TAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08A4;ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08A5;ARABIC LETTER QAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +08A6;ARABIC LETTER LAM WITH DOUBLE BAR;Lo;0;AL;;;;;N;;;;; +08A7;ARABIC LETTER MEEM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08A8;ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; +08A9;ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +08AA;ARABIC LETTER REH WITH LOOP;Lo;0;AL;;;;;N;;;;; +08AB;ARABIC LETTER WAW WITH DOT WITHIN;Lo;0;AL;;;;;N;;;;; +08AC;ARABIC LETTER ROHINGYA YEH;Lo;0;AL;;;;;N;;;;; +08AD;ARABIC LETTER LOW ALEF;Lo;0;AL;;;;;N;;;;; +08AE;ARABIC LETTER DAL WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +08AF;ARABIC LETTER SAD WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +08B0;ARABIC LETTER GAF WITH INVERTED STROKE;Lo;0;AL;;;;;N;;;;; +08B1;ARABIC LETTER STRAIGHT WAW;Lo;0;AL;;;;;N;;;;; +08B2;ARABIC LETTER ZAIN WITH INVERTED V ABOVE;Lo;0;AL;;;;;N;;;;; +08B3;ARABIC LETTER AIN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +08B4;ARABIC LETTER KAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +08B6;ARABIC LETTER BEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; +08B7;ARABIC LETTER PEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; +08B8;ARABIC LETTER TEH WITH SMALL TEH ABOVE;Lo;0;AL;;;;;N;;;;; +08B9;ARABIC LETTER REH WITH SMALL NOON ABOVE;Lo;0;AL;;;;;N;;;;; +08BA;ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE;Lo;0;AL;;;;;N;;;;; +08BB;ARABIC LETTER AFRICAN FEH;Lo;0;AL;;;;;N;;;;; +08BC;ARABIC LETTER AFRICAN QAF;Lo;0;AL;;;;;N;;;;; +08BD;ARABIC LETTER AFRICAN NOON;Lo;0;AL;;;;;N;;;;; +08D4;ARABIC SMALL HIGH WORD AR-RUB;Mn;230;NSM;;;;;N;;;;; +08D5;ARABIC SMALL HIGH SAD;Mn;230;NSM;;;;;N;;;;; +08D6;ARABIC SMALL HIGH AIN;Mn;230;NSM;;;;;N;;;;; +08D7;ARABIC SMALL HIGH QAF;Mn;230;NSM;;;;;N;;;;; +08D8;ARABIC SMALL HIGH NOON WITH KASRA;Mn;230;NSM;;;;;N;;;;; +08D9;ARABIC SMALL LOW NOON WITH KASRA;Mn;230;NSM;;;;;N;;;;; +08DA;ARABIC SMALL HIGH WORD ATH-THALATHA;Mn;230;NSM;;;;;N;;;;; +08DB;ARABIC SMALL HIGH WORD AS-SAJDA;Mn;230;NSM;;;;;N;;;;; +08DC;ARABIC SMALL HIGH WORD AN-NISF;Mn;230;NSM;;;;;N;;;;; +08DD;ARABIC SMALL HIGH WORD SAKTA;Mn;230;NSM;;;;;N;;;;; +08DE;ARABIC SMALL HIGH WORD QIF;Mn;230;NSM;;;;;N;;;;; +08DF;ARABIC SMALL HIGH WORD WAQFA;Mn;230;NSM;;;;;N;;;;; +08E0;ARABIC SMALL HIGH FOOTNOTE MARKER;Mn;230;NSM;;;;;N;;;;; +08E1;ARABIC SMALL HIGH SIGN SAFHA;Mn;230;NSM;;;;;N;;;;; +08E2;ARABIC DISPUTED END OF AYAH;Cf;0;AN;;;;;N;;;;; +08E3;ARABIC TURNED DAMMA BELOW;Mn;220;NSM;;;;;N;;;;; +08E4;ARABIC CURLY FATHA;Mn;230;NSM;;;;;N;;;;; +08E5;ARABIC CURLY DAMMA;Mn;230;NSM;;;;;N;;;;; +08E6;ARABIC CURLY KASRA;Mn;220;NSM;;;;;N;;;;; +08E7;ARABIC CURLY FATHATAN;Mn;230;NSM;;;;;N;;;;; +08E8;ARABIC CURLY DAMMATAN;Mn;230;NSM;;;;;N;;;;; +08E9;ARABIC CURLY KASRATAN;Mn;220;NSM;;;;;N;;;;; +08EA;ARABIC TONE ONE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +08EB;ARABIC TONE TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +08EC;ARABIC TONE LOOP ABOVE;Mn;230;NSM;;;;;N;;;;; +08ED;ARABIC TONE ONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; +08EE;ARABIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +08EF;ARABIC TONE LOOP BELOW;Mn;220;NSM;;;;;N;;;;; +08F0;ARABIC OPEN FATHATAN;Mn;27;NSM;;;;;N;;;;; +08F1;ARABIC OPEN DAMMATAN;Mn;28;NSM;;;;;N;;;;; +08F2;ARABIC OPEN KASRATAN;Mn;29;NSM;;;;;N;;;;; +08F3;ARABIC SMALL HIGH WAW;Mn;230;NSM;;;;;N;;;;; +08F4;ARABIC FATHA WITH RING;Mn;230;NSM;;;;;N;;;;; +08F5;ARABIC FATHA WITH DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +08F6;ARABIC KASRA WITH DOT BELOW;Mn;220;NSM;;;;;N;;;;; +08F7;ARABIC LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +08F8;ARABIC RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +08F9;ARABIC LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +08FA;ARABIC RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +08FB;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +08FC;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;; +08FD;ARABIC RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;; +08FE;ARABIC DAMMA WITH DOT;Mn;230;NSM;;;;;N;;;;; +08FF;ARABIC MARK SIDEWAYS NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; +0900;DEVANAGARI SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +0903;DEVANAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0904;DEVANAGARI LETTER SHORT A;Lo;0;L;;;;;N;;;;; +0905;DEVANAGARI LETTER A;Lo;0;L;;;;;N;;;;; +0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;; +0907;DEVANAGARI LETTER I;Lo;0;L;;;;;N;;;;; +0908;DEVANAGARI LETTER II;Lo;0;L;;;;;N;;;;; +0909;DEVANAGARI LETTER U;Lo;0;L;;;;;N;;;;; +090A;DEVANAGARI LETTER UU;Lo;0;L;;;;;N;;;;; +090B;DEVANAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +090C;DEVANAGARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +090D;DEVANAGARI LETTER CANDRA E;Lo;0;L;;;;;N;;;;; +090E;DEVANAGARI LETTER SHORT E;Lo;0;L;;;;;N;;;;; +090F;DEVANAGARI LETTER E;Lo;0;L;;;;;N;;;;; +0910;DEVANAGARI LETTER AI;Lo;0;L;;;;;N;;;;; +0911;DEVANAGARI LETTER CANDRA O;Lo;0;L;;;;;N;;;;; +0912;DEVANAGARI LETTER SHORT O;Lo;0;L;;;;;N;;;;; +0913;DEVANAGARI LETTER O;Lo;0;L;;;;;N;;;;; +0914;DEVANAGARI LETTER AU;Lo;0;L;;;;;N;;;;; +0915;DEVANAGARI LETTER KA;Lo;0;L;;;;;N;;;;; +0916;DEVANAGARI LETTER KHA;Lo;0;L;;;;;N;;;;; +0917;DEVANAGARI LETTER GA;Lo;0;L;;;;;N;;;;; +0918;DEVANAGARI LETTER GHA;Lo;0;L;;;;;N;;;;; +0919;DEVANAGARI LETTER NGA;Lo;0;L;;;;;N;;;;; +091A;DEVANAGARI LETTER CA;Lo;0;L;;;;;N;;;;; +091B;DEVANAGARI LETTER CHA;Lo;0;L;;;;;N;;;;; +091C;DEVANAGARI LETTER JA;Lo;0;L;;;;;N;;;;; +091D;DEVANAGARI LETTER JHA;Lo;0;L;;;;;N;;;;; +091E;DEVANAGARI LETTER NYA;Lo;0;L;;;;;N;;;;; +091F;DEVANAGARI LETTER TTA;Lo;0;L;;;;;N;;;;; +0920;DEVANAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;; +0921;DEVANAGARI LETTER DDA;Lo;0;L;;;;;N;;;;; +0922;DEVANAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;; +0923;DEVANAGARI LETTER NNA;Lo;0;L;;;;;N;;;;; +0924;DEVANAGARI LETTER TA;Lo;0;L;;;;;N;;;;; +0925;DEVANAGARI LETTER THA;Lo;0;L;;;;;N;;;;; +0926;DEVANAGARI LETTER DA;Lo;0;L;;;;;N;;;;; +0927;DEVANAGARI LETTER DHA;Lo;0;L;;;;;N;;;;; +0928;DEVANAGARI LETTER NA;Lo;0;L;;;;;N;;;;; +0929;DEVANAGARI LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;; +092A;DEVANAGARI LETTER PA;Lo;0;L;;;;;N;;;;; +092B;DEVANAGARI LETTER PHA;Lo;0;L;;;;;N;;;;; +092C;DEVANAGARI LETTER BA;Lo;0;L;;;;;N;;;;; +092D;DEVANAGARI LETTER BHA;Lo;0;L;;;;;N;;;;; +092E;DEVANAGARI LETTER MA;Lo;0;L;;;;;N;;;;; +092F;DEVANAGARI LETTER YA;Lo;0;L;;;;;N;;;;; +0930;DEVANAGARI LETTER RA;Lo;0;L;;;;;N;;;;; +0931;DEVANAGARI LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;; +0932;DEVANAGARI LETTER LA;Lo;0;L;;;;;N;;;;; +0933;DEVANAGARI LETTER LLA;Lo;0;L;;;;;N;;;;; +0934;DEVANAGARI LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;; +0935;DEVANAGARI LETTER VA;Lo;0;L;;;;;N;;;;; +0936;DEVANAGARI LETTER SHA;Lo;0;L;;;;;N;;;;; +0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;; +0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;; +0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;; +093A;DEVANAGARI VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +093B;DEVANAGARI VOWEL SIGN OOE;Mc;0;L;;;;;N;;;;; +093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +093F;DEVANAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0940;DEVANAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0941;DEVANAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0942;DEVANAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0943;DEVANAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +0944;DEVANAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +0945;DEVANAGARI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; +0946;DEVANAGARI VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; +0947;DEVANAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +0948;DEVANAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +0949;DEVANAGARI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; +094A;DEVANAGARI VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; +094B;DEVANAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +094E;DEVANAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;; +094F;DEVANAGARI VOWEL SIGN AW;Mc;0;L;;;;;N;;;;; +0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;; +0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;; +0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;; +0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; +0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; +0955;DEVANAGARI VOWEL SIGN CANDRA LONG E;Mn;0;NSM;;;;;N;;;;; +0956;DEVANAGARI VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +0957;DEVANAGARI VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; +0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;; +0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;; +095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;; +095B;DEVANAGARI LETTER ZA;Lo;0;L;091C 093C;;;;N;;;;; +095C;DEVANAGARI LETTER DDDHA;Lo;0;L;0921 093C;;;;N;;;;; +095D;DEVANAGARI LETTER RHA;Lo;0;L;0922 093C;;;;N;;;;; +095E;DEVANAGARI LETTER FA;Lo;0;L;092B 093C;;;;N;;;;; +095F;DEVANAGARI LETTER YYA;Lo;0;L;092F 093C;;;;N;;;;; +0960;DEVANAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0961;DEVANAGARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0962;DEVANAGARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0963;DEVANAGARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0964;DEVANAGARI DANDA;Po;0;L;;;;;N;;;;; +0965;DEVANAGARI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +0966;DEVANAGARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0967;DEVANAGARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0968;DEVANAGARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0969;DEVANAGARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +096A;DEVANAGARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +096B;DEVANAGARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +096C;DEVANAGARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +096D;DEVANAGARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +096E;DEVANAGARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +096F;DEVANAGARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +0971;DEVANAGARI SIGN HIGH SPACING DOT;Lm;0;L;;;;;N;;;;; +0972;DEVANAGARI LETTER CANDRA A;Lo;0;L;;;;;N;;;;; +0973;DEVANAGARI LETTER OE;Lo;0;L;;;;;N;;;;; +0974;DEVANAGARI LETTER OOE;Lo;0;L;;;;;N;;;;; +0975;DEVANAGARI LETTER AW;Lo;0;L;;;;;N;;;;; +0976;DEVANAGARI LETTER UE;Lo;0;L;;;;;N;;;;; +0977;DEVANAGARI LETTER UUE;Lo;0;L;;;;;N;;;;; +0978;DEVANAGARI LETTER MARWARI DDA;Lo;0;L;;;;;N;;;;; +0979;DEVANAGARI LETTER ZHA;Lo;0;L;;;;;N;;;;; +097A;DEVANAGARI LETTER HEAVY YA;Lo;0;L;;;;;N;;;;; +097B;DEVANAGARI LETTER GGA;Lo;0;L;;;;;N;;;;; +097C;DEVANAGARI LETTER JJA;Lo;0;L;;;;;N;;;;; +097D;DEVANAGARI LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +097E;DEVANAGARI LETTER DDDA;Lo;0;L;;;;;N;;;;; +097F;DEVANAGARI LETTER BBA;Lo;0;L;;;;;N;;;;; +0980;BENGALI ANJI;Lo;0;L;;;;;N;;;;; +0981;BENGALI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0982;BENGALI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0983;BENGALI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0985;BENGALI LETTER A;Lo;0;L;;;;;N;;;;; +0986;BENGALI LETTER AA;Lo;0;L;;;;;N;;;;; +0987;BENGALI LETTER I;Lo;0;L;;;;;N;;;;; +0988;BENGALI LETTER II;Lo;0;L;;;;;N;;;;; +0989;BENGALI LETTER U;Lo;0;L;;;;;N;;;;; +098A;BENGALI LETTER UU;Lo;0;L;;;;;N;;;;; +098B;BENGALI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +098C;BENGALI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +098F;BENGALI LETTER E;Lo;0;L;;;;;N;;;;; +0990;BENGALI LETTER AI;Lo;0;L;;;;;N;;;;; +0993;BENGALI LETTER O;Lo;0;L;;;;;N;;;;; +0994;BENGALI LETTER AU;Lo;0;L;;;;;N;;;;; +0995;BENGALI LETTER KA;Lo;0;L;;;;;N;;;;; +0996;BENGALI LETTER KHA;Lo;0;L;;;;;N;;;;; +0997;BENGALI LETTER GA;Lo;0;L;;;;;N;;;;; +0998;BENGALI LETTER GHA;Lo;0;L;;;;;N;;;;; +0999;BENGALI LETTER NGA;Lo;0;L;;;;;N;;;;; +099A;BENGALI LETTER CA;Lo;0;L;;;;;N;;;;; +099B;BENGALI LETTER CHA;Lo;0;L;;;;;N;;;;; +099C;BENGALI LETTER JA;Lo;0;L;;;;;N;;;;; +099D;BENGALI LETTER JHA;Lo;0;L;;;;;N;;;;; +099E;BENGALI LETTER NYA;Lo;0;L;;;;;N;;;;; +099F;BENGALI LETTER TTA;Lo;0;L;;;;;N;;;;; +09A0;BENGALI LETTER TTHA;Lo;0;L;;;;;N;;;;; +09A1;BENGALI LETTER DDA;Lo;0;L;;;;;N;;;;; +09A2;BENGALI LETTER DDHA;Lo;0;L;;;;;N;;;;; +09A3;BENGALI LETTER NNA;Lo;0;L;;;;;N;;;;; +09A4;BENGALI LETTER TA;Lo;0;L;;;;;N;;;;; +09A5;BENGALI LETTER THA;Lo;0;L;;;;;N;;;;; +09A6;BENGALI LETTER DA;Lo;0;L;;;;;N;;;;; +09A7;BENGALI LETTER DHA;Lo;0;L;;;;;N;;;;; +09A8;BENGALI LETTER NA;Lo;0;L;;;;;N;;;;; +09AA;BENGALI LETTER PA;Lo;0;L;;;;;N;;;;; +09AB;BENGALI LETTER PHA;Lo;0;L;;;;;N;;;;; +09AC;BENGALI LETTER BA;Lo;0;L;;;;;N;;;;; +09AD;BENGALI LETTER BHA;Lo;0;L;;;;;N;;;;; +09AE;BENGALI LETTER MA;Lo;0;L;;;;;N;;;;; +09AF;BENGALI LETTER YA;Lo;0;L;;;;;N;;;;; +09B0;BENGALI LETTER RA;Lo;0;L;;;;;N;;;;; +09B2;BENGALI LETTER LA;Lo;0;L;;;;;N;;;;; +09B6;BENGALI LETTER SHA;Lo;0;L;;;;;N;;;;; +09B7;BENGALI LETTER SSA;Lo;0;L;;;;;N;;;;; +09B8;BENGALI LETTER SA;Lo;0;L;;;;;N;;;;; +09B9;BENGALI LETTER HA;Lo;0;L;;;;;N;;;;; +09BC;BENGALI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +09BD;BENGALI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +09BE;BENGALI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +09BF;BENGALI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +09C0;BENGALI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +09C1;BENGALI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +09C2;BENGALI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +09C3;BENGALI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +09C4;BENGALI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +09C7;BENGALI VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +09C8;BENGALI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +09CB;BENGALI VOWEL SIGN O;Mc;0;L;09C7 09BE;;;;N;;;;; +09CC;BENGALI VOWEL SIGN AU;Mc;0;L;09C7 09D7;;;;N;;;;; +09CD;BENGALI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +09CE;BENGALI LETTER KHANDA TA;Lo;0;L;;;;;N;;;;; +09D7;BENGALI AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +09DC;BENGALI LETTER RRA;Lo;0;L;09A1 09BC;;;;N;;;;; +09DD;BENGALI LETTER RHA;Lo;0;L;09A2 09BC;;;;N;;;;; +09DF;BENGALI LETTER YYA;Lo;0;L;09AF 09BC;;;;N;;;;; +09E0;BENGALI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +09E1;BENGALI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +09E2;BENGALI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +09E3;BENGALI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +09E6;BENGALI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +09E7;BENGALI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +09E8;BENGALI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +09E9;BENGALI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +09EA;BENGALI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +09EB;BENGALI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +09EC;BENGALI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +09ED;BENGALI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +09EE;BENGALI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +09EF;BENGALI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +09F0;BENGALI LETTER RA WITH MIDDLE DIAGONAL;Lo;0;L;;;;;N;;;;; +09F1;BENGALI LETTER RA WITH LOWER DIAGONAL;Lo;0;L;;;;;N;BENGALI LETTER VA WITH LOWER DIAGONAL;;;; +09F2;BENGALI RUPEE MARK;Sc;0;ET;;;;;N;;;;; +09F3;BENGALI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; +09F4;BENGALI CURRENCY NUMERATOR ONE;No;0;L;;;;1/16;N;;;;; +09F5;BENGALI CURRENCY NUMERATOR TWO;No;0;L;;;;1/8;N;;;;; +09F6;BENGALI CURRENCY NUMERATOR THREE;No;0;L;;;;3/16;N;;;;; +09F7;BENGALI CURRENCY NUMERATOR FOUR;No;0;L;;;;1/4;N;;;;; +09F8;BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR;No;0;L;;;;3/4;N;;;;; +09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; +09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; +09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;; +09FC;BENGALI LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +09FD;BENGALI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;; +0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; +0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0A05;GURMUKHI LETTER A;Lo;0;L;;;;;N;;;;; +0A06;GURMUKHI LETTER AA;Lo;0;L;;;;;N;;;;; +0A07;GURMUKHI LETTER I;Lo;0;L;;;;;N;;;;; +0A08;GURMUKHI LETTER II;Lo;0;L;;;;;N;;;;; +0A09;GURMUKHI LETTER U;Lo;0;L;;;;;N;;;;; +0A0A;GURMUKHI LETTER UU;Lo;0;L;;;;;N;;;;; +0A0F;GURMUKHI LETTER EE;Lo;0;L;;;;;N;;;;; +0A10;GURMUKHI LETTER AI;Lo;0;L;;;;;N;;;;; +0A13;GURMUKHI LETTER OO;Lo;0;L;;;;;N;;;;; +0A14;GURMUKHI LETTER AU;Lo;0;L;;;;;N;;;;; +0A15;GURMUKHI LETTER KA;Lo;0;L;;;;;N;;;;; +0A16;GURMUKHI LETTER KHA;Lo;0;L;;;;;N;;;;; +0A17;GURMUKHI LETTER GA;Lo;0;L;;;;;N;;;;; +0A18;GURMUKHI LETTER GHA;Lo;0;L;;;;;N;;;;; +0A19;GURMUKHI LETTER NGA;Lo;0;L;;;;;N;;;;; +0A1A;GURMUKHI LETTER CA;Lo;0;L;;;;;N;;;;; +0A1B;GURMUKHI LETTER CHA;Lo;0;L;;;;;N;;;;; +0A1C;GURMUKHI LETTER JA;Lo;0;L;;;;;N;;;;; +0A1D;GURMUKHI LETTER JHA;Lo;0;L;;;;;N;;;;; +0A1E;GURMUKHI LETTER NYA;Lo;0;L;;;;;N;;;;; +0A1F;GURMUKHI LETTER TTA;Lo;0;L;;;;;N;;;;; +0A20;GURMUKHI LETTER TTHA;Lo;0;L;;;;;N;;;;; +0A21;GURMUKHI LETTER DDA;Lo;0;L;;;;;N;;;;; +0A22;GURMUKHI LETTER DDHA;Lo;0;L;;;;;N;;;;; +0A23;GURMUKHI LETTER NNA;Lo;0;L;;;;;N;;;;; +0A24;GURMUKHI LETTER TA;Lo;0;L;;;;;N;;;;; +0A25;GURMUKHI LETTER THA;Lo;0;L;;;;;N;;;;; +0A26;GURMUKHI LETTER DA;Lo;0;L;;;;;N;;;;; +0A27;GURMUKHI LETTER DHA;Lo;0;L;;;;;N;;;;; +0A28;GURMUKHI LETTER NA;Lo;0;L;;;;;N;;;;; +0A2A;GURMUKHI LETTER PA;Lo;0;L;;;;;N;;;;; +0A2B;GURMUKHI LETTER PHA;Lo;0;L;;;;;N;;;;; +0A2C;GURMUKHI LETTER BA;Lo;0;L;;;;;N;;;;; +0A2D;GURMUKHI LETTER BHA;Lo;0;L;;;;;N;;;;; +0A2E;GURMUKHI LETTER MA;Lo;0;L;;;;;N;;;;; +0A2F;GURMUKHI LETTER YA;Lo;0;L;;;;;N;;;;; +0A30;GURMUKHI LETTER RA;Lo;0;L;;;;;N;;;;; +0A32;GURMUKHI LETTER LA;Lo;0;L;;;;;N;;;;; +0A33;GURMUKHI LETTER LLA;Lo;0;L;0A32 0A3C;;;;N;;;;; +0A35;GURMUKHI LETTER VA;Lo;0;L;;;;;N;;;;; +0A36;GURMUKHI LETTER SHA;Lo;0;L;0A38 0A3C;;;;N;;;;; +0A38;GURMUKHI LETTER SA;Lo;0;L;;;;;N;;;;; +0A39;GURMUKHI LETTER HA;Lo;0;L;;;;;N;;;;; +0A3C;GURMUKHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0A3E;GURMUKHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0A3F;GURMUKHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0A40;GURMUKHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0A41;GURMUKHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0A42;GURMUKHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0A47;GURMUKHI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; +0A48;GURMUKHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +0A4B;GURMUKHI VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; +0A4C;GURMUKHI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +0A4D;GURMUKHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0A51;GURMUKHI SIGN UDAAT;Mn;0;NSM;;;;;N;;;;; +0A59;GURMUKHI LETTER KHHA;Lo;0;L;0A16 0A3C;;;;N;;;;; +0A5A;GURMUKHI LETTER GHHA;Lo;0;L;0A17 0A3C;;;;N;;;;; +0A5B;GURMUKHI LETTER ZA;Lo;0;L;0A1C 0A3C;;;;N;;;;; +0A5C;GURMUKHI LETTER RRA;Lo;0;L;;;;;N;;;;; +0A5E;GURMUKHI LETTER FA;Lo;0;L;0A2B 0A3C;;;;N;;;;; +0A66;GURMUKHI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0A67;GURMUKHI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0A68;GURMUKHI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0A69;GURMUKHI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0A6A;GURMUKHI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0A6B;GURMUKHI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0A6C;GURMUKHI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0A6D;GURMUKHI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0A6E;GURMUKHI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0A6F;GURMUKHI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0A70;GURMUKHI TIPPI;Mn;0;NSM;;;;;N;;;;; +0A71;GURMUKHI ADDAK;Mn;0;NSM;;;;;N;;;;; +0A72;GURMUKHI IRI;Lo;0;L;;;;;N;;;;; +0A73;GURMUKHI URA;Lo;0;L;;;;;N;;;;; +0A74;GURMUKHI EK ONKAR;Lo;0;L;;;;;N;;;;; +0A75;GURMUKHI SIGN YAKASH;Mn;0;NSM;;;;;N;;;;; +0A81;GUJARATI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0A82;GUJARATI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +0A83;GUJARATI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0A85;GUJARATI LETTER A;Lo;0;L;;;;;N;;;;; +0A86;GUJARATI LETTER AA;Lo;0;L;;;;;N;;;;; +0A87;GUJARATI LETTER I;Lo;0;L;;;;;N;;;;; +0A88;GUJARATI LETTER II;Lo;0;L;;;;;N;;;;; +0A89;GUJARATI LETTER U;Lo;0;L;;;;;N;;;;; +0A8A;GUJARATI LETTER UU;Lo;0;L;;;;;N;;;;; +0A8B;GUJARATI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0A8C;GUJARATI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0A8D;GUJARATI VOWEL CANDRA E;Lo;0;L;;;;;N;;;;; +0A8F;GUJARATI LETTER E;Lo;0;L;;;;;N;;;;; +0A90;GUJARATI LETTER AI;Lo;0;L;;;;;N;;;;; +0A91;GUJARATI VOWEL CANDRA O;Lo;0;L;;;;;N;;;;; +0A93;GUJARATI LETTER O;Lo;0;L;;;;;N;;;;; +0A94;GUJARATI LETTER AU;Lo;0;L;;;;;N;;;;; +0A95;GUJARATI LETTER KA;Lo;0;L;;;;;N;;;;; +0A96;GUJARATI LETTER KHA;Lo;0;L;;;;;N;;;;; +0A97;GUJARATI LETTER GA;Lo;0;L;;;;;N;;;;; +0A98;GUJARATI LETTER GHA;Lo;0;L;;;;;N;;;;; +0A99;GUJARATI LETTER NGA;Lo;0;L;;;;;N;;;;; +0A9A;GUJARATI LETTER CA;Lo;0;L;;;;;N;;;;; +0A9B;GUJARATI LETTER CHA;Lo;0;L;;;;;N;;;;; +0A9C;GUJARATI LETTER JA;Lo;0;L;;;;;N;;;;; +0A9D;GUJARATI LETTER JHA;Lo;0;L;;;;;N;;;;; +0A9E;GUJARATI LETTER NYA;Lo;0;L;;;;;N;;;;; +0A9F;GUJARATI LETTER TTA;Lo;0;L;;;;;N;;;;; +0AA0;GUJARATI LETTER TTHA;Lo;0;L;;;;;N;;;;; +0AA1;GUJARATI LETTER DDA;Lo;0;L;;;;;N;;;;; +0AA2;GUJARATI LETTER DDHA;Lo;0;L;;;;;N;;;;; +0AA3;GUJARATI LETTER NNA;Lo;0;L;;;;;N;;;;; +0AA4;GUJARATI LETTER TA;Lo;0;L;;;;;N;;;;; +0AA5;GUJARATI LETTER THA;Lo;0;L;;;;;N;;;;; +0AA6;GUJARATI LETTER DA;Lo;0;L;;;;;N;;;;; +0AA7;GUJARATI LETTER DHA;Lo;0;L;;;;;N;;;;; +0AA8;GUJARATI LETTER NA;Lo;0;L;;;;;N;;;;; +0AAA;GUJARATI LETTER PA;Lo;0;L;;;;;N;;;;; +0AAB;GUJARATI LETTER PHA;Lo;0;L;;;;;N;;;;; +0AAC;GUJARATI LETTER BA;Lo;0;L;;;;;N;;;;; +0AAD;GUJARATI LETTER BHA;Lo;0;L;;;;;N;;;;; +0AAE;GUJARATI LETTER MA;Lo;0;L;;;;;N;;;;; +0AAF;GUJARATI LETTER YA;Lo;0;L;;;;;N;;;;; +0AB0;GUJARATI LETTER RA;Lo;0;L;;;;;N;;;;; +0AB2;GUJARATI LETTER LA;Lo;0;L;;;;;N;;;;; +0AB3;GUJARATI LETTER LLA;Lo;0;L;;;;;N;;;;; +0AB5;GUJARATI LETTER VA;Lo;0;L;;;;;N;;;;; +0AB6;GUJARATI LETTER SHA;Lo;0;L;;;;;N;;;;; +0AB7;GUJARATI LETTER SSA;Lo;0;L;;;;;N;;;;; +0AB8;GUJARATI LETTER SA;Lo;0;L;;;;;N;;;;; +0AB9;GUJARATI LETTER HA;Lo;0;L;;;;;N;;;;; +0ABC;GUJARATI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0ABD;GUJARATI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0ABE;GUJARATI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0ABF;GUJARATI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0AC0;GUJARATI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0AC1;GUJARATI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0AC2;GUJARATI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0AC3;GUJARATI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +0AC4;GUJARATI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +0AC5;GUJARATI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; +0AC7;GUJARATI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +0AC8;GUJARATI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +0AC9;GUJARATI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; +0ACB;GUJARATI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +0ACC;GUJARATI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +0ACD;GUJARATI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0AD0;GUJARATI OM;Lo;0;L;;;;;N;;;;; +0AE0;GUJARATI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0AE1;GUJARATI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0AE2;GUJARATI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0AE3;GUJARATI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0AE6;GUJARATI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0AE7;GUJARATI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0AE8;GUJARATI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0AE9;GUJARATI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0AEA;GUJARATI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0AEB;GUJARATI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0AEC;GUJARATI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0AED;GUJARATI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0AEE;GUJARATI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; +0AF9;GUJARATI LETTER ZHA;Lo;0;L;;;;;N;;;;; +0AFA;GUJARATI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; +0AFB;GUJARATI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; +0AFC;GUJARATI SIGN MADDAH;Mn;0;NSM;;;;;N;;;;; +0AFD;GUJARATI SIGN THREE-DOT NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFE;GUJARATI SIGN CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFF;GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0B05;ORIYA LETTER A;Lo;0;L;;;;;N;;;;; +0B06;ORIYA LETTER AA;Lo;0;L;;;;;N;;;;; +0B07;ORIYA LETTER I;Lo;0;L;;;;;N;;;;; +0B08;ORIYA LETTER II;Lo;0;L;;;;;N;;;;; +0B09;ORIYA LETTER U;Lo;0;L;;;;;N;;;;; +0B0A;ORIYA LETTER UU;Lo;0;L;;;;;N;;;;; +0B0B;ORIYA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0B0C;ORIYA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0B0F;ORIYA LETTER E;Lo;0;L;;;;;N;;;;; +0B10;ORIYA LETTER AI;Lo;0;L;;;;;N;;;;; +0B13;ORIYA LETTER O;Lo;0;L;;;;;N;;;;; +0B14;ORIYA LETTER AU;Lo;0;L;;;;;N;;;;; +0B15;ORIYA LETTER KA;Lo;0;L;;;;;N;;;;; +0B16;ORIYA LETTER KHA;Lo;0;L;;;;;N;;;;; +0B17;ORIYA LETTER GA;Lo;0;L;;;;;N;;;;; +0B18;ORIYA LETTER GHA;Lo;0;L;;;;;N;;;;; +0B19;ORIYA LETTER NGA;Lo;0;L;;;;;N;;;;; +0B1A;ORIYA LETTER CA;Lo;0;L;;;;;N;;;;; +0B1B;ORIYA LETTER CHA;Lo;0;L;;;;;N;;;;; +0B1C;ORIYA LETTER JA;Lo;0;L;;;;;N;;;;; +0B1D;ORIYA LETTER JHA;Lo;0;L;;;;;N;;;;; +0B1E;ORIYA LETTER NYA;Lo;0;L;;;;;N;;;;; +0B1F;ORIYA LETTER TTA;Lo;0;L;;;;;N;;;;; +0B20;ORIYA LETTER TTHA;Lo;0;L;;;;;N;;;;; +0B21;ORIYA LETTER DDA;Lo;0;L;;;;;N;;;;; +0B22;ORIYA LETTER DDHA;Lo;0;L;;;;;N;;;;; +0B23;ORIYA LETTER NNA;Lo;0;L;;;;;N;;;;; +0B24;ORIYA LETTER TA;Lo;0;L;;;;;N;;;;; +0B25;ORIYA LETTER THA;Lo;0;L;;;;;N;;;;; +0B26;ORIYA LETTER DA;Lo;0;L;;;;;N;;;;; +0B27;ORIYA LETTER DHA;Lo;0;L;;;;;N;;;;; +0B28;ORIYA LETTER NA;Lo;0;L;;;;;N;;;;; +0B2A;ORIYA LETTER PA;Lo;0;L;;;;;N;;;;; +0B2B;ORIYA LETTER PHA;Lo;0;L;;;;;N;;;;; +0B2C;ORIYA LETTER BA;Lo;0;L;;;;;N;;;;; +0B2D;ORIYA LETTER BHA;Lo;0;L;;;;;N;;;;; +0B2E;ORIYA LETTER MA;Lo;0;L;;;;;N;;;;; +0B2F;ORIYA LETTER YA;Lo;0;L;;;;;N;;;;; +0B30;ORIYA LETTER RA;Lo;0;L;;;;;N;;;;; +0B32;ORIYA LETTER LA;Lo;0;L;;;;;N;;;;; +0B33;ORIYA LETTER LLA;Lo;0;L;;;;;N;;;;; +0B35;ORIYA LETTER VA;Lo;0;L;;;;;N;;;;; +0B36;ORIYA LETTER SHA;Lo;0;L;;;;;N;;;;; +0B37;ORIYA LETTER SSA;Lo;0;L;;;;;N;;;;; +0B38;ORIYA LETTER SA;Lo;0;L;;;;;N;;;;; +0B39;ORIYA LETTER HA;Lo;0;L;;;;;N;;;;; +0B3C;ORIYA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0B3D;ORIYA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0B3E;ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0B3F;ORIYA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +0B40;ORIYA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0B41;ORIYA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0B42;ORIYA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0B43;ORIYA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +0B44;ORIYA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +0B47;ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +0B48;ORIYA VOWEL SIGN AI;Mc;0;L;0B47 0B56;;;;N;;;;; +0B4B;ORIYA VOWEL SIGN O;Mc;0;L;0B47 0B3E;;;;N;;;;; +0B4C;ORIYA VOWEL SIGN AU;Mc;0;L;0B47 0B57;;;;N;;;;; +0B4D;ORIYA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0B56;ORIYA AI LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +0B57;ORIYA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +0B5C;ORIYA LETTER RRA;Lo;0;L;0B21 0B3C;;;;N;;;;; +0B5D;ORIYA LETTER RHA;Lo;0;L;0B22 0B3C;;;;N;;;;; +0B5F;ORIYA LETTER YYA;Lo;0;L;;;;;N;;;;; +0B60;ORIYA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0B61;ORIYA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0B62;ORIYA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0B63;ORIYA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0B66;ORIYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0B67;ORIYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0B68;ORIYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0B69;ORIYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0B6A;ORIYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0B6B;ORIYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0B6C;ORIYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0B6D;ORIYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0B6E;ORIYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;; +0B71;ORIYA LETTER WA;Lo;0;L;;;;;N;;;;; +0B72;ORIYA FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; +0B73;ORIYA FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; +0B74;ORIYA FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +0B75;ORIYA FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; +0B76;ORIYA FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +0B77;ORIYA FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; +0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;; +0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;; +0B86;TAMIL LETTER AA;Lo;0;L;;;;;N;;;;; +0B87;TAMIL LETTER I;Lo;0;L;;;;;N;;;;; +0B88;TAMIL LETTER II;Lo;0;L;;;;;N;;;;; +0B89;TAMIL LETTER U;Lo;0;L;;;;;N;;;;; +0B8A;TAMIL LETTER UU;Lo;0;L;;;;;N;;;;; +0B8E;TAMIL LETTER E;Lo;0;L;;;;;N;;;;; +0B8F;TAMIL LETTER EE;Lo;0;L;;;;;N;;;;; +0B90;TAMIL LETTER AI;Lo;0;L;;;;;N;;;;; +0B92;TAMIL LETTER O;Lo;0;L;;;;;N;;;;; +0B93;TAMIL LETTER OO;Lo;0;L;;;;;N;;;;; +0B94;TAMIL LETTER AU;Lo;0;L;0B92 0BD7;;;;N;;;;; +0B95;TAMIL LETTER KA;Lo;0;L;;;;;N;;;;; +0B99;TAMIL LETTER NGA;Lo;0;L;;;;;N;;;;; +0B9A;TAMIL LETTER CA;Lo;0;L;;;;;N;;;;; +0B9C;TAMIL LETTER JA;Lo;0;L;;;;;N;;;;; +0B9E;TAMIL LETTER NYA;Lo;0;L;;;;;N;;;;; +0B9F;TAMIL LETTER TTA;Lo;0;L;;;;;N;;;;; +0BA3;TAMIL LETTER NNA;Lo;0;L;;;;;N;;;;; +0BA4;TAMIL LETTER TA;Lo;0;L;;;;;N;;;;; +0BA8;TAMIL LETTER NA;Lo;0;L;;;;;N;;;;; +0BA9;TAMIL LETTER NNNA;Lo;0;L;;;;;N;;;;; +0BAA;TAMIL LETTER PA;Lo;0;L;;;;;N;;;;; +0BAE;TAMIL LETTER MA;Lo;0;L;;;;;N;;;;; +0BAF;TAMIL LETTER YA;Lo;0;L;;;;;N;;;;; +0BB0;TAMIL LETTER RA;Lo;0;L;;;;;N;;;;; +0BB1;TAMIL LETTER RRA;Lo;0;L;;;;;N;;;;; +0BB2;TAMIL LETTER LA;Lo;0;L;;;;;N;;;;; +0BB3;TAMIL LETTER LLA;Lo;0;L;;;;;N;;;;; +0BB4;TAMIL LETTER LLLA;Lo;0;L;;;;;N;;;;; +0BB5;TAMIL LETTER VA;Lo;0;L;;;;;N;;;;; +0BB6;TAMIL LETTER SHA;Lo;0;L;;;;;N;;;;; +0BB7;TAMIL LETTER SSA;Lo;0;L;;;;;N;;;;; +0BB8;TAMIL LETTER SA;Lo;0;L;;;;;N;;;;; +0BB9;TAMIL LETTER HA;Lo;0;L;;;;;N;;;;; +0BBE;TAMIL VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0BBF;TAMIL VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0BC0;TAMIL VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +0BC1;TAMIL VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +0BC2;TAMIL VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +0BC6;TAMIL VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +0BC7;TAMIL VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +0BC8;TAMIL VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +0BCA;TAMIL VOWEL SIGN O;Mc;0;L;0BC6 0BBE;;;;N;;;;; +0BCB;TAMIL VOWEL SIGN OO;Mc;0;L;0BC7 0BBE;;;;N;;;;; +0BCC;TAMIL VOWEL SIGN AU;Mc;0;L;0BC6 0BD7;;;;N;;;;; +0BCD;TAMIL SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0BD0;TAMIL OM;Lo;0;L;;;;;N;;;;; +0BD7;TAMIL AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +0BE6;TAMIL DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0BE7;TAMIL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0BE8;TAMIL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0BE9;TAMIL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0BEA;TAMIL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0BEB;TAMIL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0BEC;TAMIL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0BED;TAMIL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0BEE;TAMIL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0BEF;TAMIL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0BF0;TAMIL NUMBER TEN;No;0;L;;;;10;N;;;;; +0BF1;TAMIL NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; +0BF2;TAMIL NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; +0BF3;TAMIL DAY SIGN;So;0;ON;;;;;N;;;;; +0BF4;TAMIL MONTH SIGN;So;0;ON;;;;;N;;;;; +0BF5;TAMIL YEAR SIGN;So;0;ON;;;;;N;;;;; +0BF6;TAMIL DEBIT SIGN;So;0;ON;;;;;N;;;;; +0BF7;TAMIL CREDIT SIGN;So;0;ON;;;;;N;;;;; +0BF8;TAMIL AS ABOVE SIGN;So;0;ON;;;;;N;;;;; +0BF9;TAMIL RUPEE SIGN;Sc;0;ET;;;;;N;;;;; +0BFA;TAMIL NUMBER SIGN;So;0;ON;;;;;N;;;;; +0C00;TELUGU SIGN COMBINING CANDRABINDU ABOVE;Mn;0;NSM;;;;;N;;;;; +0C01;TELUGU SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; +0C02;TELUGU SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0C03;TELUGU SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0C05;TELUGU LETTER A;Lo;0;L;;;;;N;;;;; +0C06;TELUGU LETTER AA;Lo;0;L;;;;;N;;;;; +0C07;TELUGU LETTER I;Lo;0;L;;;;;N;;;;; +0C08;TELUGU LETTER II;Lo;0;L;;;;;N;;;;; +0C09;TELUGU LETTER U;Lo;0;L;;;;;N;;;;; +0C0A;TELUGU LETTER UU;Lo;0;L;;;;;N;;;;; +0C0B;TELUGU LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0C0C;TELUGU LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0C0E;TELUGU LETTER E;Lo;0;L;;;;;N;;;;; +0C0F;TELUGU LETTER EE;Lo;0;L;;;;;N;;;;; +0C10;TELUGU LETTER AI;Lo;0;L;;;;;N;;;;; +0C12;TELUGU LETTER O;Lo;0;L;;;;;N;;;;; +0C13;TELUGU LETTER OO;Lo;0;L;;;;;N;;;;; +0C14;TELUGU LETTER AU;Lo;0;L;;;;;N;;;;; +0C15;TELUGU LETTER KA;Lo;0;L;;;;;N;;;;; +0C16;TELUGU LETTER KHA;Lo;0;L;;;;;N;;;;; +0C17;TELUGU LETTER GA;Lo;0;L;;;;;N;;;;; +0C18;TELUGU LETTER GHA;Lo;0;L;;;;;N;;;;; +0C19;TELUGU LETTER NGA;Lo;0;L;;;;;N;;;;; +0C1A;TELUGU LETTER CA;Lo;0;L;;;;;N;;;;; +0C1B;TELUGU LETTER CHA;Lo;0;L;;;;;N;;;;; +0C1C;TELUGU LETTER JA;Lo;0;L;;;;;N;;;;; +0C1D;TELUGU LETTER JHA;Lo;0;L;;;;;N;;;;; +0C1E;TELUGU LETTER NYA;Lo;0;L;;;;;N;;;;; +0C1F;TELUGU LETTER TTA;Lo;0;L;;;;;N;;;;; +0C20;TELUGU LETTER TTHA;Lo;0;L;;;;;N;;;;; +0C21;TELUGU LETTER DDA;Lo;0;L;;;;;N;;;;; +0C22;TELUGU LETTER DDHA;Lo;0;L;;;;;N;;;;; +0C23;TELUGU LETTER NNA;Lo;0;L;;;;;N;;;;; +0C24;TELUGU LETTER TA;Lo;0;L;;;;;N;;;;; +0C25;TELUGU LETTER THA;Lo;0;L;;;;;N;;;;; +0C26;TELUGU LETTER DA;Lo;0;L;;;;;N;;;;; +0C27;TELUGU LETTER DHA;Lo;0;L;;;;;N;;;;; +0C28;TELUGU LETTER NA;Lo;0;L;;;;;N;;;;; +0C2A;TELUGU LETTER PA;Lo;0;L;;;;;N;;;;; +0C2B;TELUGU LETTER PHA;Lo;0;L;;;;;N;;;;; +0C2C;TELUGU LETTER BA;Lo;0;L;;;;;N;;;;; +0C2D;TELUGU LETTER BHA;Lo;0;L;;;;;N;;;;; +0C2E;TELUGU LETTER MA;Lo;0;L;;;;;N;;;;; +0C2F;TELUGU LETTER YA;Lo;0;L;;;;;N;;;;; +0C30;TELUGU LETTER RA;Lo;0;L;;;;;N;;;;; +0C31;TELUGU LETTER RRA;Lo;0;L;;;;;N;;;;; +0C32;TELUGU LETTER LA;Lo;0;L;;;;;N;;;;; +0C33;TELUGU LETTER LLA;Lo;0;L;;;;;N;;;;; +0C34;TELUGU LETTER LLLA;Lo;0;L;;;;;N;;;;; +0C35;TELUGU LETTER VA;Lo;0;L;;;;;N;;;;; +0C36;TELUGU LETTER SHA;Lo;0;L;;;;;N;;;;; +0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;; +0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;; +0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;; +0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +0C40;TELUGU VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +0C41;TELUGU VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +0C42;TELUGU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +0C43;TELUGU VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +0C44;TELUGU VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +0C46;TELUGU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +0C47;TELUGU VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; +0C48;TELUGU VOWEL SIGN AI;Mn;0;NSM;0C46 0C56;;;;N;;;;; +0C4A;TELUGU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +0C4B;TELUGU VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; +0C4C;TELUGU VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +0C4D;TELUGU SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0C55;TELUGU LENGTH MARK;Mn;84;NSM;;;;;N;;;;; +0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;; +0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;; +0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;; +0C5A;TELUGU LETTER RRRA;Lo;0;L;;;;;N;;;;; +0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0C63;TELUGU VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0C66;TELUGU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0C67;TELUGU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0C68;TELUGU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0C69;TELUGU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0C6A;TELUGU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0C6B;TELUGU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0C6C;TELUGU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0C6D;TELUGU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0C6E;TELUGU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0C6F;TELUGU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0C78;TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR;No;0;ON;;;;0;N;;;;; +0C79;TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR;No;0;ON;;;;1;N;;;;; +0C7A;TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR;No;0;ON;;;;2;N;;;;; +0C7B;TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR;No;0;ON;;;;3;N;;;;; +0C7C;TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR;No;0;ON;;;;1;N;;;;; +0C7D;TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR;No;0;ON;;;;2;N;;;;; +0C7E;TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR;No;0;ON;;;;3;N;;;;; +0C7F;TELUGU SIGN TUUMU;So;0;L;;;;;N;;;;; +0C80;KANNADA SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; +0C81;KANNADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0C85;KANNADA LETTER A;Lo;0;L;;;;;N;;;;; +0C86;KANNADA LETTER AA;Lo;0;L;;;;;N;;;;; +0C87;KANNADA LETTER I;Lo;0;L;;;;;N;;;;; +0C88;KANNADA LETTER II;Lo;0;L;;;;;N;;;;; +0C89;KANNADA LETTER U;Lo;0;L;;;;;N;;;;; +0C8A;KANNADA LETTER UU;Lo;0;L;;;;;N;;;;; +0C8B;KANNADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0C8C;KANNADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0C8E;KANNADA LETTER E;Lo;0;L;;;;;N;;;;; +0C8F;KANNADA LETTER EE;Lo;0;L;;;;;N;;;;; +0C90;KANNADA LETTER AI;Lo;0;L;;;;;N;;;;; +0C92;KANNADA LETTER O;Lo;0;L;;;;;N;;;;; +0C93;KANNADA LETTER OO;Lo;0;L;;;;;N;;;;; +0C94;KANNADA LETTER AU;Lo;0;L;;;;;N;;;;; +0C95;KANNADA LETTER KA;Lo;0;L;;;;;N;;;;; +0C96;KANNADA LETTER KHA;Lo;0;L;;;;;N;;;;; +0C97;KANNADA LETTER GA;Lo;0;L;;;;;N;;;;; +0C98;KANNADA LETTER GHA;Lo;0;L;;;;;N;;;;; +0C99;KANNADA LETTER NGA;Lo;0;L;;;;;N;;;;; +0C9A;KANNADA LETTER CA;Lo;0;L;;;;;N;;;;; +0C9B;KANNADA LETTER CHA;Lo;0;L;;;;;N;;;;; +0C9C;KANNADA LETTER JA;Lo;0;L;;;;;N;;;;; +0C9D;KANNADA LETTER JHA;Lo;0;L;;;;;N;;;;; +0C9E;KANNADA LETTER NYA;Lo;0;L;;;;;N;;;;; +0C9F;KANNADA LETTER TTA;Lo;0;L;;;;;N;;;;; +0CA0;KANNADA LETTER TTHA;Lo;0;L;;;;;N;;;;; +0CA1;KANNADA LETTER DDA;Lo;0;L;;;;;N;;;;; +0CA2;KANNADA LETTER DDHA;Lo;0;L;;;;;N;;;;; +0CA3;KANNADA LETTER NNA;Lo;0;L;;;;;N;;;;; +0CA4;KANNADA LETTER TA;Lo;0;L;;;;;N;;;;; +0CA5;KANNADA LETTER THA;Lo;0;L;;;;;N;;;;; +0CA6;KANNADA LETTER DA;Lo;0;L;;;;;N;;;;; +0CA7;KANNADA LETTER DHA;Lo;0;L;;;;;N;;;;; +0CA8;KANNADA LETTER NA;Lo;0;L;;;;;N;;;;; +0CAA;KANNADA LETTER PA;Lo;0;L;;;;;N;;;;; +0CAB;KANNADA LETTER PHA;Lo;0;L;;;;;N;;;;; +0CAC;KANNADA LETTER BA;Lo;0;L;;;;;N;;;;; +0CAD;KANNADA LETTER BHA;Lo;0;L;;;;;N;;;;; +0CAE;KANNADA LETTER MA;Lo;0;L;;;;;N;;;;; +0CAF;KANNADA LETTER YA;Lo;0;L;;;;;N;;;;; +0CB0;KANNADA LETTER RA;Lo;0;L;;;;;N;;;;; +0CB1;KANNADA LETTER RRA;Lo;0;L;;;;;N;;;;; +0CB2;KANNADA LETTER LA;Lo;0;L;;;;;N;;;;; +0CB3;KANNADA LETTER LLA;Lo;0;L;;;;;N;;;;; +0CB5;KANNADA LETTER VA;Lo;0;L;;;;;N;;;;; +0CB6;KANNADA LETTER SHA;Lo;0;L;;;;;N;;;;; +0CB7;KANNADA LETTER SSA;Lo;0;L;;;;;N;;;;; +0CB8;KANNADA LETTER SA;Lo;0;L;;;;;N;;;;; +0CB9;KANNADA LETTER HA;Lo;0;L;;;;;N;;;;; +0CBC;KANNADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0CBD;KANNADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0CBE;KANNADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0CBF;KANNADA VOWEL SIGN I;Mn;0;L;;;;;N;;;;; +0CC0;KANNADA VOWEL SIGN II;Mc;0;L;0CBF 0CD5;;;;N;;;;; +0CC1;KANNADA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +0CC2;KANNADA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +0CC3;KANNADA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +0CC4;KANNADA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +0CC6;KANNADA VOWEL SIGN E;Mn;0;L;;;;;N;;;;; +0CC7;KANNADA VOWEL SIGN EE;Mc;0;L;0CC6 0CD5;;;;N;;;;; +0CC8;KANNADA VOWEL SIGN AI;Mc;0;L;0CC6 0CD6;;;;N;;;;; +0CCA;KANNADA VOWEL SIGN O;Mc;0;L;0CC6 0CC2;;;;N;;;;; +0CCB;KANNADA VOWEL SIGN OO;Mc;0;L;0CCA 0CD5;;;;N;;;;; +0CCC;KANNADA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;; +0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;; +0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;; +0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0CE2;KANNADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0CE3;KANNADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0CE6;KANNADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0CE7;KANNADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0CE8;KANNADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0CE9;KANNADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0CEA;KANNADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0CEB;KANNADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0CEC;KANNADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +0D00;MALAYALAM SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; +0D01;MALAYALAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;; +0D06;MALAYALAM LETTER AA;Lo;0;L;;;;;N;;;;; +0D07;MALAYALAM LETTER I;Lo;0;L;;;;;N;;;;; +0D08;MALAYALAM LETTER II;Lo;0;L;;;;;N;;;;; +0D09;MALAYALAM LETTER U;Lo;0;L;;;;;N;;;;; +0D0A;MALAYALAM LETTER UU;Lo;0;L;;;;;N;;;;; +0D0B;MALAYALAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0D0C;MALAYALAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0D0E;MALAYALAM LETTER E;Lo;0;L;;;;;N;;;;; +0D0F;MALAYALAM LETTER EE;Lo;0;L;;;;;N;;;;; +0D10;MALAYALAM LETTER AI;Lo;0;L;;;;;N;;;;; +0D12;MALAYALAM LETTER O;Lo;0;L;;;;;N;;;;; +0D13;MALAYALAM LETTER OO;Lo;0;L;;;;;N;;;;; +0D14;MALAYALAM LETTER AU;Lo;0;L;;;;;N;;;;; +0D15;MALAYALAM LETTER KA;Lo;0;L;;;;;N;;;;; +0D16;MALAYALAM LETTER KHA;Lo;0;L;;;;;N;;;;; +0D17;MALAYALAM LETTER GA;Lo;0;L;;;;;N;;;;; +0D18;MALAYALAM LETTER GHA;Lo;0;L;;;;;N;;;;; +0D19;MALAYALAM LETTER NGA;Lo;0;L;;;;;N;;;;; +0D1A;MALAYALAM LETTER CA;Lo;0;L;;;;;N;;;;; +0D1B;MALAYALAM LETTER CHA;Lo;0;L;;;;;N;;;;; +0D1C;MALAYALAM LETTER JA;Lo;0;L;;;;;N;;;;; +0D1D;MALAYALAM LETTER JHA;Lo;0;L;;;;;N;;;;; +0D1E;MALAYALAM LETTER NYA;Lo;0;L;;;;;N;;;;; +0D1F;MALAYALAM LETTER TTA;Lo;0;L;;;;;N;;;;; +0D20;MALAYALAM LETTER TTHA;Lo;0;L;;;;;N;;;;; +0D21;MALAYALAM LETTER DDA;Lo;0;L;;;;;N;;;;; +0D22;MALAYALAM LETTER DDHA;Lo;0;L;;;;;N;;;;; +0D23;MALAYALAM LETTER NNA;Lo;0;L;;;;;N;;;;; +0D24;MALAYALAM LETTER TA;Lo;0;L;;;;;N;;;;; +0D25;MALAYALAM LETTER THA;Lo;0;L;;;;;N;;;;; +0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;; +0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;; +0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;; +0D29;MALAYALAM LETTER NNNA;Lo;0;L;;;;;N;;;;; +0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;; +0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;; +0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;; +0D2D;MALAYALAM LETTER BHA;Lo;0;L;;;;;N;;;;; +0D2E;MALAYALAM LETTER MA;Lo;0;L;;;;;N;;;;; +0D2F;MALAYALAM LETTER YA;Lo;0;L;;;;;N;;;;; +0D30;MALAYALAM LETTER RA;Lo;0;L;;;;;N;;;;; +0D31;MALAYALAM LETTER RRA;Lo;0;L;;;;;N;;;;; +0D32;MALAYALAM LETTER LA;Lo;0;L;;;;;N;;;;; +0D33;MALAYALAM LETTER LLA;Lo;0;L;;;;;N;;;;; +0D34;MALAYALAM LETTER LLLA;Lo;0;L;;;;;N;;;;; +0D35;MALAYALAM LETTER VA;Lo;0;L;;;;;N;;;;; +0D36;MALAYALAM LETTER SHA;Lo;0;L;;;;;N;;;;; +0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;; +0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; +0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; +0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;; +0D3B;MALAYALAM SIGN VERTICAL BAR VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D3C;MALAYALAM SIGN CIRCULAR VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0D40;MALAYALAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0D41;MALAYALAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0D42;MALAYALAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0D43;MALAYALAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +0D44;MALAYALAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +0D46;MALAYALAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +0D47;MALAYALAM VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +0D48;MALAYALAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +0D4A;MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;; +0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;; +0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;; +0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D4E;MALAYALAM LETTER DOT REPH;Lo;0;L;;;;;N;;;;; +0D4F;MALAYALAM SIGN PARA;So;0;L;;;;;N;;;;; +0D54;MALAYALAM LETTER CHILLU M;Lo;0;L;;;;;N;;;;; +0D55;MALAYALAM LETTER CHILLU Y;Lo;0;L;;;;;N;;;;; +0D56;MALAYALAM LETTER CHILLU LLL;Lo;0;L;;;;;N;;;;; +0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +0D58;MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH;No;0;L;;;;1/160;N;;;;; +0D59;MALAYALAM FRACTION ONE FORTIETH;No;0;L;;;;1/40;N;;;;; +0D5A;MALAYALAM FRACTION THREE EIGHTIETHS;No;0;L;;;;3/80;N;;;;; +0D5B;MALAYALAM FRACTION ONE TWENTIETH;No;0;L;;;;1/20;N;;;;; +0D5C;MALAYALAM FRACTION ONE TENTH;No;0;L;;;;1/10;N;;;;; +0D5D;MALAYALAM FRACTION THREE TWENTIETHS;No;0;L;;;;3/20;N;;;;; +0D5E;MALAYALAM FRACTION ONE FIFTH;No;0;L;;;;1/5;N;;;;; +0D5F;MALAYALAM LETTER ARCHAIC II;Lo;0;L;;;;;N;;;;; +0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0D62;MALAYALAM VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0D63;MALAYALAM VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0D66;MALAYALAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0D67;MALAYALAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0D68;MALAYALAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0D69;MALAYALAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0D6A;MALAYALAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0D6B;MALAYALAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0D6C;MALAYALAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0D6D;MALAYALAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0D6E;MALAYALAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0D6F;MALAYALAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0D70;MALAYALAM NUMBER TEN;No;0;L;;;;10;N;;;;; +0D71;MALAYALAM NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; +0D72;MALAYALAM NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; +0D73;MALAYALAM FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; +0D74;MALAYALAM FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; +0D75;MALAYALAM FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +0D76;MALAYALAM FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; +0D77;MALAYALAM FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +0D78;MALAYALAM FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; +0D79;MALAYALAM DATE MARK;So;0;L;;;;;N;;;;; +0D7A;MALAYALAM LETTER CHILLU NN;Lo;0;L;;;;;N;;;;; +0D7B;MALAYALAM LETTER CHILLU N;Lo;0;L;;;;;N;;;;; +0D7C;MALAYALAM LETTER CHILLU RR;Lo;0;L;;;;;N;;;;; +0D7D;MALAYALAM LETTER CHILLU L;Lo;0;L;;;;;N;;;;; +0D7E;MALAYALAM LETTER CHILLU LL;Lo;0;L;;;;;N;;;;; +0D7F;MALAYALAM LETTER CHILLU K;Lo;0;L;;;;;N;;;;; +0D82;SINHALA SIGN ANUSVARAYA;Mc;0;L;;;;;N;;;;; +0D83;SINHALA SIGN VISARGAYA;Mc;0;L;;;;;N;;;;; +0D85;SINHALA LETTER AYANNA;Lo;0;L;;;;;N;;;;; +0D86;SINHALA LETTER AAYANNA;Lo;0;L;;;;;N;;;;; +0D87;SINHALA LETTER AEYANNA;Lo;0;L;;;;;N;;;;; +0D88;SINHALA LETTER AEEYANNA;Lo;0;L;;;;;N;;;;; +0D89;SINHALA LETTER IYANNA;Lo;0;L;;;;;N;;;;; +0D8A;SINHALA LETTER IIYANNA;Lo;0;L;;;;;N;;;;; +0D8B;SINHALA LETTER UYANNA;Lo;0;L;;;;;N;;;;; +0D8C;SINHALA LETTER UUYANNA;Lo;0;L;;;;;N;;;;; +0D8D;SINHALA LETTER IRUYANNA;Lo;0;L;;;;;N;;;;; +0D8E;SINHALA LETTER IRUUYANNA;Lo;0;L;;;;;N;;;;; +0D8F;SINHALA LETTER ILUYANNA;Lo;0;L;;;;;N;;;;; +0D90;SINHALA LETTER ILUUYANNA;Lo;0;L;;;;;N;;;;; +0D91;SINHALA LETTER EYANNA;Lo;0;L;;;;;N;;;;; +0D92;SINHALA LETTER EEYANNA;Lo;0;L;;;;;N;;;;; +0D93;SINHALA LETTER AIYANNA;Lo;0;L;;;;;N;;;;; +0D94;SINHALA LETTER OYANNA;Lo;0;L;;;;;N;;;;; +0D95;SINHALA LETTER OOYANNA;Lo;0;L;;;;;N;;;;; +0D96;SINHALA LETTER AUYANNA;Lo;0;L;;;;;N;;;;; +0D9A;SINHALA LETTER ALPAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; +0D9B;SINHALA LETTER MAHAAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; +0D9C;SINHALA LETTER ALPAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; +0D9D;SINHALA LETTER MAHAAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; +0D9E;SINHALA LETTER KANTAJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; +0D9F;SINHALA LETTER SANYAKA GAYANNA;Lo;0;L;;;;;N;;;;; +0DA0;SINHALA LETTER ALPAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; +0DA1;SINHALA LETTER MAHAAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; +0DA2;SINHALA LETTER ALPAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; +0DA3;SINHALA LETTER MAHAAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; +0DA4;SINHALA LETTER TAALUJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; +0DA5;SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA;Lo;0;L;;;;;N;;;;; +0DA6;SINHALA LETTER SANYAKA JAYANNA;Lo;0;L;;;;;N;;;;; +0DA7;SINHALA LETTER ALPAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; +0DA8;SINHALA LETTER MAHAAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; +0DA9;SINHALA LETTER ALPAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; +0DAA;SINHALA LETTER MAHAAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; +0DAB;SINHALA LETTER MUURDHAJA NAYANNA;Lo;0;L;;;;;N;;;;; +0DAC;SINHALA LETTER SANYAKA DDAYANNA;Lo;0;L;;;;;N;;;;; +0DAD;SINHALA LETTER ALPAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; +0DAE;SINHALA LETTER MAHAAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; +0DAF;SINHALA LETTER ALPAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; +0DB0;SINHALA LETTER MAHAAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; +0DB1;SINHALA LETTER DANTAJA NAYANNA;Lo;0;L;;;;;N;;;;; +0DB3;SINHALA LETTER SANYAKA DAYANNA;Lo;0;L;;;;;N;;;;; +0DB4;SINHALA LETTER ALPAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; +0DB5;SINHALA LETTER MAHAAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; +0DB6;SINHALA LETTER ALPAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; +0DB7;SINHALA LETTER MAHAAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; +0DB8;SINHALA LETTER MAYANNA;Lo;0;L;;;;;N;;;;; +0DB9;SINHALA LETTER AMBA BAYANNA;Lo;0;L;;;;;N;;;;; +0DBA;SINHALA LETTER YAYANNA;Lo;0;L;;;;;N;;;;; +0DBB;SINHALA LETTER RAYANNA;Lo;0;L;;;;;N;;;;; +0DBD;SINHALA LETTER DANTAJA LAYANNA;Lo;0;L;;;;;N;;;;; +0DC0;SINHALA LETTER VAYANNA;Lo;0;L;;;;;N;;;;; +0DC1;SINHALA LETTER TAALUJA SAYANNA;Lo;0;L;;;;;N;;;;; +0DC2;SINHALA LETTER MUURDHAJA SAYANNA;Lo;0;L;;;;;N;;;;; +0DC3;SINHALA LETTER DANTAJA SAYANNA;Lo;0;L;;;;;N;;;;; +0DC4;SINHALA LETTER HAYANNA;Lo;0;L;;;;;N;;;;; +0DC5;SINHALA LETTER MUURDHAJA LAYANNA;Lo;0;L;;;;;N;;;;; +0DC6;SINHALA LETTER FAYANNA;Lo;0;L;;;;;N;;;;; +0DCA;SINHALA SIGN AL-LAKUNA;Mn;9;NSM;;;;;N;;;;; +0DCF;SINHALA VOWEL SIGN AELA-PILLA;Mc;0;L;;;;;N;;;;; +0DD0;SINHALA VOWEL SIGN KETTI AEDA-PILLA;Mc;0;L;;;;;N;;;;; +0DD1;SINHALA VOWEL SIGN DIGA AEDA-PILLA;Mc;0;L;;;;;N;;;;; +0DD2;SINHALA VOWEL SIGN KETTI IS-PILLA;Mn;0;NSM;;;;;N;;;;; +0DD3;SINHALA VOWEL SIGN DIGA IS-PILLA;Mn;0;NSM;;;;;N;;;;; +0DD4;SINHALA VOWEL SIGN KETTI PAA-PILLA;Mn;0;NSM;;;;;N;;;;; +0DD6;SINHALA VOWEL SIGN DIGA PAA-PILLA;Mn;0;NSM;;;;;N;;;;; +0DD8;SINHALA VOWEL SIGN GAETTA-PILLA;Mc;0;L;;;;;N;;;;; +0DD9;SINHALA VOWEL SIGN KOMBUVA;Mc;0;L;;;;;N;;;;; +0DDA;SINHALA VOWEL SIGN DIGA KOMBUVA;Mc;0;L;0DD9 0DCA;;;;N;;;;; +0DDB;SINHALA VOWEL SIGN KOMBU DEKA;Mc;0;L;;;;;N;;;;; +0DDC;SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA;Mc;0;L;0DD9 0DCF;;;;N;;;;; +0DDD;SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA;Mc;0;L;0DDC 0DCA;;;;N;;;;; +0DDE;SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA;Mc;0;L;0DD9 0DDF;;;;N;;;;; +0DDF;SINHALA VOWEL SIGN GAYANUKITTA;Mc;0;L;;;;;N;;;;; +0DE6;SINHALA LITH DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0DE7;SINHALA LITH DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0DE8;SINHALA LITH DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0DE9;SINHALA LITH DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0DEA;SINHALA LITH DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0DEB;SINHALA LITH DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0DEC;SINHALA LITH DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0DED;SINHALA LITH DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0DEE;SINHALA LITH DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0DEF;SINHALA LITH DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0DF2;SINHALA VOWEL SIGN DIGA GAETTA-PILLA;Mc;0;L;;;;;N;;;;; +0DF3;SINHALA VOWEL SIGN DIGA GAYANUKITTA;Mc;0;L;;;;;N;;;;; +0DF4;SINHALA PUNCTUATION KUNDDALIYA;Po;0;L;;;;;N;;;;; +0E01;THAI CHARACTER KO KAI;Lo;0;L;;;;;N;THAI LETTER KO KAI;;;; +0E02;THAI CHARACTER KHO KHAI;Lo;0;L;;;;;N;THAI LETTER KHO KHAI;;;; +0E03;THAI CHARACTER KHO KHUAT;Lo;0;L;;;;;N;THAI LETTER KHO KHUAT;;;; +0E04;THAI CHARACTER KHO KHWAI;Lo;0;L;;;;;N;THAI LETTER KHO KHWAI;;;; +0E05;THAI CHARACTER KHO KHON;Lo;0;L;;;;;N;THAI LETTER KHO KHON;;;; +0E06;THAI CHARACTER KHO RAKHANG;Lo;0;L;;;;;N;THAI LETTER KHO RAKHANG;;;; +0E07;THAI CHARACTER NGO NGU;Lo;0;L;;;;;N;THAI LETTER NGO NGU;;;; +0E08;THAI CHARACTER CHO CHAN;Lo;0;L;;;;;N;THAI LETTER CHO CHAN;;;; +0E09;THAI CHARACTER CHO CHING;Lo;0;L;;;;;N;THAI LETTER CHO CHING;;;; +0E0A;THAI CHARACTER CHO CHANG;Lo;0;L;;;;;N;THAI LETTER CHO CHANG;;;; +0E0B;THAI CHARACTER SO SO;Lo;0;L;;;;;N;THAI LETTER SO SO;;;; +0E0C;THAI CHARACTER CHO CHOE;Lo;0;L;;;;;N;THAI LETTER CHO CHOE;;;; +0E0D;THAI CHARACTER YO YING;Lo;0;L;;;;;N;THAI LETTER YO YING;;;; +0E0E;THAI CHARACTER DO CHADA;Lo;0;L;;;;;N;THAI LETTER DO CHADA;;;; +0E0F;THAI CHARACTER TO PATAK;Lo;0;L;;;;;N;THAI LETTER TO PATAK;;;; +0E10;THAI CHARACTER THO THAN;Lo;0;L;;;;;N;THAI LETTER THO THAN;;;; +0E11;THAI CHARACTER THO NANGMONTHO;Lo;0;L;;;;;N;THAI LETTER THO NANGMONTHO;;;; +0E12;THAI CHARACTER THO PHUTHAO;Lo;0;L;;;;;N;THAI LETTER THO PHUTHAO;;;; +0E13;THAI CHARACTER NO NEN;Lo;0;L;;;;;N;THAI LETTER NO NEN;;;; +0E14;THAI CHARACTER DO DEK;Lo;0;L;;;;;N;THAI LETTER DO DEK;;;; +0E15;THAI CHARACTER TO TAO;Lo;0;L;;;;;N;THAI LETTER TO TAO;;;; +0E16;THAI CHARACTER THO THUNG;Lo;0;L;;;;;N;THAI LETTER THO THUNG;;;; +0E17;THAI CHARACTER THO THAHAN;Lo;0;L;;;;;N;THAI LETTER THO THAHAN;;;; +0E18;THAI CHARACTER THO THONG;Lo;0;L;;;;;N;THAI LETTER THO THONG;;;; +0E19;THAI CHARACTER NO NU;Lo;0;L;;;;;N;THAI LETTER NO NU;;;; +0E1A;THAI CHARACTER BO BAIMAI;Lo;0;L;;;;;N;THAI LETTER BO BAIMAI;;;; +0E1B;THAI CHARACTER PO PLA;Lo;0;L;;;;;N;THAI LETTER PO PLA;;;; +0E1C;THAI CHARACTER PHO PHUNG;Lo;0;L;;;;;N;THAI LETTER PHO PHUNG;;;; +0E1D;THAI CHARACTER FO FA;Lo;0;L;;;;;N;THAI LETTER FO FA;;;; +0E1E;THAI CHARACTER PHO PHAN;Lo;0;L;;;;;N;THAI LETTER PHO PHAN;;;; +0E1F;THAI CHARACTER FO FAN;Lo;0;L;;;;;N;THAI LETTER FO FAN;;;; +0E20;THAI CHARACTER PHO SAMPHAO;Lo;0;L;;;;;N;THAI LETTER PHO SAMPHAO;;;; +0E21;THAI CHARACTER MO MA;Lo;0;L;;;;;N;THAI LETTER MO MA;;;; +0E22;THAI CHARACTER YO YAK;Lo;0;L;;;;;N;THAI LETTER YO YAK;;;; +0E23;THAI CHARACTER RO RUA;Lo;0;L;;;;;N;THAI LETTER RO RUA;;;; +0E24;THAI CHARACTER RU;Lo;0;L;;;;;N;THAI LETTER RU;;;; +0E25;THAI CHARACTER LO LING;Lo;0;L;;;;;N;THAI LETTER LO LING;;;; +0E26;THAI CHARACTER LU;Lo;0;L;;;;;N;THAI LETTER LU;;;; +0E27;THAI CHARACTER WO WAEN;Lo;0;L;;;;;N;THAI LETTER WO WAEN;;;; +0E28;THAI CHARACTER SO SALA;Lo;0;L;;;;;N;THAI LETTER SO SALA;;;; +0E29;THAI CHARACTER SO RUSI;Lo;0;L;;;;;N;THAI LETTER SO RUSI;;;; +0E2A;THAI CHARACTER SO SUA;Lo;0;L;;;;;N;THAI LETTER SO SUA;;;; +0E2B;THAI CHARACTER HO HIP;Lo;0;L;;;;;N;THAI LETTER HO HIP;;;; +0E2C;THAI CHARACTER LO CHULA;Lo;0;L;;;;;N;THAI LETTER LO CHULA;;;; +0E2D;THAI CHARACTER O ANG;Lo;0;L;;;;;N;THAI LETTER O ANG;;;; +0E2E;THAI CHARACTER HO NOKHUK;Lo;0;L;;;;;N;THAI LETTER HO NOK HUK;;;; +0E2F;THAI CHARACTER PAIYANNOI;Lo;0;L;;;;;N;THAI PAI YAN NOI;;;; +0E30;THAI CHARACTER SARA A;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA A;;;; +0E31;THAI CHARACTER MAI HAN-AKAT;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI HAN-AKAT;;;; +0E32;THAI CHARACTER SARA AA;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AA;;;; +0E33;THAI CHARACTER SARA AM;Lo;0;L;<compat> 0E4D 0E32;;;;N;THAI VOWEL SIGN SARA AM;;;; +0E34;THAI CHARACTER SARA I;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA I;;;; +0E35;THAI CHARACTER SARA II;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA II;;;; +0E36;THAI CHARACTER SARA UE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UE;;;; +0E37;THAI CHARACTER SARA UEE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UEE;;;; +0E38;THAI CHARACTER SARA U;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA U;;;; +0E39;THAI CHARACTER SARA UU;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA UU;;;; +0E3A;THAI CHARACTER PHINTHU;Mn;9;NSM;;;;;N;THAI VOWEL SIGN PHINTHU;;;; +0E3F;THAI CURRENCY SYMBOL BAHT;Sc;0;ET;;;;;N;THAI BAHT SIGN;;;; +0E40;THAI CHARACTER SARA E;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA E;;;; +0E41;THAI CHARACTER SARA AE;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AE;;;; +0E42;THAI CHARACTER SARA O;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA O;;;; +0E43;THAI CHARACTER SARA AI MAIMUAN;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MUAN;;;; +0E44;THAI CHARACTER SARA AI MAIMALAI;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MALAI;;;; +0E45;THAI CHARACTER LAKKHANGYAO;Lo;0;L;;;;;N;THAI LAK KHANG YAO;;;; +0E46;THAI CHARACTER MAIYAMOK;Lm;0;L;;;;;N;THAI MAI YAMOK;;;; +0E47;THAI CHARACTER MAITAIKHU;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI TAI KHU;;;; +0E48;THAI CHARACTER MAI EK;Mn;107;NSM;;;;;N;THAI TONE MAI EK;;;; +0E49;THAI CHARACTER MAI THO;Mn;107;NSM;;;;;N;THAI TONE MAI THO;;;; +0E4A;THAI CHARACTER MAI TRI;Mn;107;NSM;;;;;N;THAI TONE MAI TRI;;;; +0E4B;THAI CHARACTER MAI CHATTAWA;Mn;107;NSM;;;;;N;THAI TONE MAI CHATTAWA;;;; +0E4C;THAI CHARACTER THANTHAKHAT;Mn;0;NSM;;;;;N;THAI THANTHAKHAT;;;; +0E4D;THAI CHARACTER NIKHAHIT;Mn;0;NSM;;;;;N;THAI NIKKHAHIT;;;; +0E4E;THAI CHARACTER YAMAKKAN;Mn;0;NSM;;;;;N;THAI YAMAKKAN;;;; +0E4F;THAI CHARACTER FONGMAN;Po;0;L;;;;;N;THAI FONGMAN;;;; +0E50;THAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0E51;THAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0E52;THAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0E53;THAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0E54;THAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0E55;THAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0E56;THAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0E57;THAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0E58;THAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0E59;THAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0E5A;THAI CHARACTER ANGKHANKHU;Po;0;L;;;;;N;THAI ANGKHANKHU;;;; +0E5B;THAI CHARACTER KHOMUT;Po;0;L;;;;;N;THAI KHOMUT;;;; +0E81;LAO LETTER KO;Lo;0;L;;;;;N;;;;; +0E82;LAO LETTER KHO SUNG;Lo;0;L;;;;;N;;;;; +0E84;LAO LETTER KHO TAM;Lo;0;L;;;;;N;;;;; +0E87;LAO LETTER NGO;Lo;0;L;;;;;N;;;;; +0E88;LAO LETTER CO;Lo;0;L;;;;;N;;;;; +0E8A;LAO LETTER SO TAM;Lo;0;L;;;;;N;;;;; +0E8D;LAO LETTER NYO;Lo;0;L;;;;;N;;;;; +0E94;LAO LETTER DO;Lo;0;L;;;;;N;;;;; +0E95;LAO LETTER TO;Lo;0;L;;;;;N;;;;; +0E96;LAO LETTER THO SUNG;Lo;0;L;;;;;N;;;;; +0E97;LAO LETTER THO TAM;Lo;0;L;;;;;N;;;;; +0E99;LAO LETTER NO;Lo;0;L;;;;;N;;;;; +0E9A;LAO LETTER BO;Lo;0;L;;;;;N;;;;; +0E9B;LAO LETTER PO;Lo;0;L;;;;;N;;;;; +0E9C;LAO LETTER PHO SUNG;Lo;0;L;;;;;N;;;;; +0E9D;LAO LETTER FO TAM;Lo;0;L;;;;;N;;;;; +0E9E;LAO LETTER PHO TAM;Lo;0;L;;;;;N;;;;; +0E9F;LAO LETTER FO SUNG;Lo;0;L;;;;;N;;;;; +0EA1;LAO LETTER MO;Lo;0;L;;;;;N;;;;; +0EA2;LAO LETTER YO;Lo;0;L;;;;;N;;;;; +0EA3;LAO LETTER LO LING;Lo;0;L;;;;;N;;;;; +0EA5;LAO LETTER LO LOOT;Lo;0;L;;;;;N;;;;; +0EA7;LAO LETTER WO;Lo;0;L;;;;;N;;;;; +0EAA;LAO LETTER SO SUNG;Lo;0;L;;;;;N;;;;; +0EAB;LAO LETTER HO SUNG;Lo;0;L;;;;;N;;;;; +0EAD;LAO LETTER O;Lo;0;L;;;;;N;;;;; +0EAE;LAO LETTER HO TAM;Lo;0;L;;;;;N;;;;; +0EAF;LAO ELLIPSIS;Lo;0;L;;;;;N;;;;; +0EB0;LAO VOWEL SIGN A;Lo;0;L;;;;;N;;;;; +0EB1;LAO VOWEL SIGN MAI KAN;Mn;0;NSM;;;;;N;;;;; +0EB2;LAO VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; +0EB3;LAO VOWEL SIGN AM;Lo;0;L;<compat> 0ECD 0EB2;;;;N;;;;; +0EB4;LAO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +0EB5;LAO VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +0EB6;LAO VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; +0EB7;LAO VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; +0EB8;LAO VOWEL SIGN U;Mn;118;NSM;;;;;N;;;;; +0EB9;LAO VOWEL SIGN UU;Mn;118;NSM;;;;;N;;;;; +0EBB;LAO VOWEL SIGN MAI KON;Mn;0;NSM;;;;;N;;;;; +0EBC;LAO SEMIVOWEL SIGN LO;Mn;0;NSM;;;;;N;;;;; +0EBD;LAO SEMIVOWEL SIGN NYO;Lo;0;L;;;;;N;;;;; +0EC0;LAO VOWEL SIGN E;Lo;0;L;;;;;N;;;;; +0EC1;LAO VOWEL SIGN EI;Lo;0;L;;;;;N;;;;; +0EC2;LAO VOWEL SIGN O;Lo;0;L;;;;;N;;;;; +0EC3;LAO VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; +0EC4;LAO VOWEL SIGN AI;Lo;0;L;;;;;N;;;;; +0EC6;LAO KO LA;Lm;0;L;;;;;N;;;;; +0EC8;LAO TONE MAI EK;Mn;122;NSM;;;;;N;;;;; +0EC9;LAO TONE MAI THO;Mn;122;NSM;;;;;N;;;;; +0ECA;LAO TONE MAI TI;Mn;122;NSM;;;;;N;;;;; +0ECB;LAO TONE MAI CATAWA;Mn;122;NSM;;;;;N;;;;; +0ECC;LAO CANCELLATION MARK;Mn;0;NSM;;;;;N;;;;; +0ECD;LAO NIGGAHITA;Mn;0;NSM;;;;;N;;;;; +0ED0;LAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0ED1;LAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0ED2;LAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0ED3;LAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0ED4;LAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0ED5;LAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0ED6;LAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0ED7;LAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0ED8;LAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0ED9;LAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0EDC;LAO HO NO;Lo;0;L;<compat> 0EAB 0E99;;;;N;;;;; +0EDD;LAO HO MO;Lo;0;L;<compat> 0EAB 0EA1;;;;N;;;;; +0EDE;LAO LETTER KHMU GO;Lo;0;L;;;;;N;;;;; +0EDF;LAO LETTER KHMU NYO;Lo;0;L;;;;;N;;;;; +0F00;TIBETAN SYLLABLE OM;Lo;0;L;;;;;N;;;;; +0F01;TIBETAN MARK GTER YIG MGO TRUNCATED A;So;0;L;;;;;N;;;;; +0F02;TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA;So;0;L;;;;;N;;;;; +0F03;TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA;So;0;L;;;;;N;;;;; +0F04;TIBETAN MARK INITIAL YIG MGO MDUN MA;Po;0;L;;;;;N;TIBETAN SINGLE ORNAMENT;;;; +0F05;TIBETAN MARK CLOSING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; +0F06;TIBETAN MARK CARET YIG MGO PHUR SHAD MA;Po;0;L;;;;;N;;;;; +0F07;TIBETAN MARK YIG MGO TSHEG SHAD MA;Po;0;L;;;;;N;;;;; +0F08;TIBETAN MARK SBRUL SHAD;Po;0;L;;;;;N;TIBETAN RGYANSHAD;;;; +0F09;TIBETAN MARK BSKUR YIG MGO;Po;0;L;;;;;N;;;;; +0F0A;TIBETAN MARK BKA- SHOG YIG MGO;Po;0;L;;;;;N;;;;; +0F0B;TIBETAN MARK INTERSYLLABIC TSHEG;Po;0;L;;;;;N;TIBETAN TSEG;;;; +0F0C;TIBETAN MARK DELIMITER TSHEG BSTAR;Po;0;L;<noBreak> 0F0B;;;;N;;;;; +0F0D;TIBETAN MARK SHAD;Po;0;L;;;;;N;TIBETAN SHAD;;;; +0F0E;TIBETAN MARK NYIS SHAD;Po;0;L;;;;;N;TIBETAN DOUBLE SHAD;;;; +0F0F;TIBETAN MARK TSHEG SHAD;Po;0;L;;;;;N;;;;; +0F10;TIBETAN MARK NYIS TSHEG SHAD;Po;0;L;;;;;N;;;;; +0F11;TIBETAN MARK RIN CHEN SPUNGS SHAD;Po;0;L;;;;;N;TIBETAN RINCHANPHUNGSHAD;;;; +0F12;TIBETAN MARK RGYA GRAM SHAD;Po;0;L;;;;;N;;;;; +0F13;TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN;So;0;L;;;;;N;;;;; +0F14;TIBETAN MARK GTER TSHEG;Po;0;L;;;;;N;TIBETAN COMMA;;;; +0F15;TIBETAN LOGOTYPE SIGN CHAD RTAGS;So;0;L;;;;;N;;;;; +0F16;TIBETAN LOGOTYPE SIGN LHAG RTAGS;So;0;L;;;;;N;;;;; +0F17;TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS;So;0;L;;;;;N;;;;; +0F18;TIBETAN ASTROLOGICAL SIGN -KHYUD PA;Mn;220;NSM;;;;;N;;;;; +0F19;TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS;Mn;220;NSM;;;;;N;;;;; +0F1A;TIBETAN SIGN RDEL DKAR GCIG;So;0;L;;;;;N;;;;; +0F1B;TIBETAN SIGN RDEL DKAR GNYIS;So;0;L;;;;;N;;;;; +0F1C;TIBETAN SIGN RDEL DKAR GSUM;So;0;L;;;;;N;;;;; +0F1D;TIBETAN SIGN RDEL NAG GCIG;So;0;L;;;;;N;;;;; +0F1E;TIBETAN SIGN RDEL NAG GNYIS;So;0;L;;;;;N;;;;; +0F1F;TIBETAN SIGN RDEL DKAR RDEL NAG;So;0;L;;;;;N;;;;; +0F20;TIBETAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0F21;TIBETAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0F22;TIBETAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0F23;TIBETAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0F24;TIBETAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0F25;TIBETAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0F26;TIBETAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0F27;TIBETAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0F28;TIBETAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0F29;TIBETAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0F2A;TIBETAN DIGIT HALF ONE;No;0;L;;;;1/2;N;;;;; +0F2B;TIBETAN DIGIT HALF TWO;No;0;L;;;;3/2;N;;;;; +0F2C;TIBETAN DIGIT HALF THREE;No;0;L;;;;5/2;N;;;;; +0F2D;TIBETAN DIGIT HALF FOUR;No;0;L;;;;7/2;N;;;;; +0F2E;TIBETAN DIGIT HALF FIVE;No;0;L;;;;9/2;N;;;;; +0F2F;TIBETAN DIGIT HALF SIX;No;0;L;;;;11/2;N;;;;; +0F30;TIBETAN DIGIT HALF SEVEN;No;0;L;;;;13/2;N;;;;; +0F31;TIBETAN DIGIT HALF EIGHT;No;0;L;;;;15/2;N;;;;; +0F32;TIBETAN DIGIT HALF NINE;No;0;L;;;;17/2;N;;;;; +0F33;TIBETAN DIGIT HALF ZERO;No;0;L;;;;-1/2;N;;;;; +0F34;TIBETAN MARK BSDUS RTAGS;So;0;L;;;;;N;;;;; +0F35;TIBETAN MARK NGAS BZUNG NYI ZLA;Mn;220;NSM;;;;;N;TIBETAN HONORIFIC UNDER RING;;;; +0F36;TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN;So;0;L;;;;;N;;;;; +0F37;TIBETAN MARK NGAS BZUNG SGOR RTAGS;Mn;220;NSM;;;;;N;TIBETAN UNDER RING;;;; +0F38;TIBETAN MARK CHE MGO;So;0;L;;;;;N;;;;; +0F39;TIBETAN MARK TSA -PHRU;Mn;216;NSM;;;;;N;TIBETAN LENITION MARK;;;; +0F3A;TIBETAN MARK GUG RTAGS GYON;Ps;0;ON;;;;;Y;;;;; +0F3B;TIBETAN MARK GUG RTAGS GYAS;Pe;0;ON;;;;;Y;;;;; +0F3C;TIBETAN MARK ANG KHANG GYON;Ps;0;ON;;;;;Y;TIBETAN LEFT BRACE;;;; +0F3D;TIBETAN MARK ANG KHANG GYAS;Pe;0;ON;;;;;Y;TIBETAN RIGHT BRACE;;;; +0F3E;TIBETAN SIGN YAR TSHES;Mc;0;L;;;;;N;;;;; +0F3F;TIBETAN SIGN MAR TSHES;Mc;0;L;;;;;N;;;;; +0F40;TIBETAN LETTER KA;Lo;0;L;;;;;N;;;;; +0F41;TIBETAN LETTER KHA;Lo;0;L;;;;;N;;;;; +0F42;TIBETAN LETTER GA;Lo;0;L;;;;;N;;;;; +0F43;TIBETAN LETTER GHA;Lo;0;L;0F42 0FB7;;;;N;;;;; +0F44;TIBETAN LETTER NGA;Lo;0;L;;;;;N;;;;; +0F45;TIBETAN LETTER CA;Lo;0;L;;;;;N;;;;; +0F46;TIBETAN LETTER CHA;Lo;0;L;;;;;N;;;;; +0F47;TIBETAN LETTER JA;Lo;0;L;;;;;N;;;;; +0F49;TIBETAN LETTER NYA;Lo;0;L;;;;;N;;;;; +0F4A;TIBETAN LETTER TTA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED TA;;;; +0F4B;TIBETAN LETTER TTHA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED THA;;;; +0F4C;TIBETAN LETTER DDA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED DA;;;; +0F4D;TIBETAN LETTER DDHA;Lo;0;L;0F4C 0FB7;;;;N;;;;; +0F4E;TIBETAN LETTER NNA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED NA;;;; +0F4F;TIBETAN LETTER TA;Lo;0;L;;;;;N;;;;; +0F50;TIBETAN LETTER THA;Lo;0;L;;;;;N;;;;; +0F51;TIBETAN LETTER DA;Lo;0;L;;;;;N;;;;; +0F52;TIBETAN LETTER DHA;Lo;0;L;0F51 0FB7;;;;N;;;;; +0F53;TIBETAN LETTER NA;Lo;0;L;;;;;N;;;;; +0F54;TIBETAN LETTER PA;Lo;0;L;;;;;N;;;;; +0F55;TIBETAN LETTER PHA;Lo;0;L;;;;;N;;;;; +0F56;TIBETAN LETTER BA;Lo;0;L;;;;;N;;;;; +0F57;TIBETAN LETTER BHA;Lo;0;L;0F56 0FB7;;;;N;;;;; +0F58;TIBETAN LETTER MA;Lo;0;L;;;;;N;;;;; +0F59;TIBETAN LETTER TSA;Lo;0;L;;;;;N;;;;; +0F5A;TIBETAN LETTER TSHA;Lo;0;L;;;;;N;;;;; +0F5B;TIBETAN LETTER DZA;Lo;0;L;;;;;N;;;;; +0F5C;TIBETAN LETTER DZHA;Lo;0;L;0F5B 0FB7;;;;N;;;;; +0F5D;TIBETAN LETTER WA;Lo;0;L;;;;;N;;;;; +0F5E;TIBETAN LETTER ZHA;Lo;0;L;;;;;N;;;;; +0F5F;TIBETAN LETTER ZA;Lo;0;L;;;;;N;;;;; +0F60;TIBETAN LETTER -A;Lo;0;L;;;;;N;TIBETAN LETTER AA;;;; +0F61;TIBETAN LETTER YA;Lo;0;L;;;;;N;;;;; +0F62;TIBETAN LETTER RA;Lo;0;L;;;;;N;;;;; +0F63;TIBETAN LETTER LA;Lo;0;L;;;;;N;;;;; +0F64;TIBETAN LETTER SHA;Lo;0;L;;;;;N;;;;; +0F65;TIBETAN LETTER SSA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED SHA;;;; +0F66;TIBETAN LETTER SA;Lo;0;L;;;;;N;;;;; +0F67;TIBETAN LETTER HA;Lo;0;L;;;;;N;;;;; +0F68;TIBETAN LETTER A;Lo;0;L;;;;;N;;;;; +0F69;TIBETAN LETTER KSSA;Lo;0;L;0F40 0FB5;;;;N;;;;; +0F6A;TIBETAN LETTER FIXED-FORM RA;Lo;0;L;;;;;N;;;;; +0F6B;TIBETAN LETTER KKA;Lo;0;L;;;;;N;;;;; +0F6C;TIBETAN LETTER RRA;Lo;0;L;;;;;N;;;;; +0F71;TIBETAN VOWEL SIGN AA;Mn;129;NSM;;;;;N;;;;; +0F72;TIBETAN VOWEL SIGN I;Mn;130;NSM;;;;;N;;;;; +0F73;TIBETAN VOWEL SIGN II;Mn;0;NSM;0F71 0F72;;;;N;;;;; +0F74;TIBETAN VOWEL SIGN U;Mn;132;NSM;;;;;N;;;;; +0F75;TIBETAN VOWEL SIGN UU;Mn;0;NSM;0F71 0F74;;;;N;;;;; +0F76;TIBETAN VOWEL SIGN VOCALIC R;Mn;0;NSM;0FB2 0F80;;;;N;;;;; +0F77;TIBETAN VOWEL SIGN VOCALIC RR;Mn;0;NSM;<compat> 0FB2 0F81;;;;N;;;;; +0F78;TIBETAN VOWEL SIGN VOCALIC L;Mn;0;NSM;0FB3 0F80;;;;N;;;;; +0F79;TIBETAN VOWEL SIGN VOCALIC LL;Mn;0;NSM;<compat> 0FB3 0F81;;;;N;;;;; +0F7A;TIBETAN VOWEL SIGN E;Mn;130;NSM;;;;;N;;;;; +0F7B;TIBETAN VOWEL SIGN EE;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AI;;;; +0F7C;TIBETAN VOWEL SIGN O;Mn;130;NSM;;;;;N;;;;; +0F7D;TIBETAN VOWEL SIGN OO;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AU;;;; +0F7E;TIBETAN SIGN RJES SU NGA RO;Mn;0;NSM;;;;;N;TIBETAN ANUSVARA;;;; +0F7F;TIBETAN SIGN RNAM BCAD;Mc;0;L;;;;;N;TIBETAN VISARGA;;;; +0F80;TIBETAN VOWEL SIGN REVERSED I;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN SHORT I;;;; +0F81;TIBETAN VOWEL SIGN REVERSED II;Mn;0;NSM;0F71 0F80;;;;N;;;;; +0F82;TIBETAN SIGN NYI ZLA NAA DA;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU WITH ORNAMENT;;;; +0F83;TIBETAN SIGN SNA LDAN;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU;;;; +0F84;TIBETAN MARK HALANTA;Mn;9;NSM;;;;;N;TIBETAN VIRAMA;;;; +0F85;TIBETAN MARK PALUTA;Po;0;L;;;;;N;TIBETAN CHUCHENYIGE;;;; +0F86;TIBETAN SIGN LCI RTAGS;Mn;230;NSM;;;;;N;;;;; +0F87;TIBETAN SIGN YANG RTAGS;Mn;230;NSM;;;;;N;;;;; +0F88;TIBETAN SIGN LCE TSA CAN;Lo;0;L;;;;;N;;;;; +0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;;;; +0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;;;; +0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;;;; +0F8C;TIBETAN SIGN INVERTED MCHU CAN;Lo;0;L;;;;;N;;;;; +0F8D;TIBETAN SUBJOINED SIGN LCE TSA CAN;Mn;0;NSM;;;;;N;;;;; +0F8E;TIBETAN SUBJOINED SIGN MCHU CAN;Mn;0;NSM;;;;;N;;;;; +0F8F;TIBETAN SUBJOINED SIGN INVERTED MCHU CAN;Mn;0;NSM;;;;;N;;;;; +0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; +0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; +0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; +0F93;TIBETAN SUBJOINED LETTER GHA;Mn;0;NSM;0F92 0FB7;;;;N;;;;; +0F94;TIBETAN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; +0F95;TIBETAN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; +0F96;TIBETAN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; +0F97;TIBETAN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; +0F99;TIBETAN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; +0F9A;TIBETAN SUBJOINED LETTER TTA;Mn;0;NSM;;;;;N;;;;; +0F9B;TIBETAN SUBJOINED LETTER TTHA;Mn;0;NSM;;;;;N;;;;; +0F9C;TIBETAN SUBJOINED LETTER DDA;Mn;0;NSM;;;;;N;;;;; +0F9D;TIBETAN SUBJOINED LETTER DDHA;Mn;0;NSM;0F9C 0FB7;;;;N;;;;; +0F9E;TIBETAN SUBJOINED LETTER NNA;Mn;0;NSM;;;;;N;;;;; +0F9F;TIBETAN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; +0FA0;TIBETAN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; +0FA1;TIBETAN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; +0FA2;TIBETAN SUBJOINED LETTER DHA;Mn;0;NSM;0FA1 0FB7;;;;N;;;;; +0FA3;TIBETAN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; +0FA4;TIBETAN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; +0FA5;TIBETAN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; +0FA6;TIBETAN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; +0FA7;TIBETAN SUBJOINED LETTER BHA;Mn;0;NSM;0FA6 0FB7;;;;N;;;;; +0FA8;TIBETAN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; +0FA9;TIBETAN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; +0FAA;TIBETAN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; +0FAB;TIBETAN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; +0FAC;TIBETAN SUBJOINED LETTER DZHA;Mn;0;NSM;0FAB 0FB7;;;;N;;;;; +0FAD;TIBETAN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; +0FAE;TIBETAN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; +0FAF;TIBETAN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; +0FB0;TIBETAN SUBJOINED LETTER -A;Mn;0;NSM;;;;;N;;;;; +0FB1;TIBETAN SUBJOINED LETTER YA;Mn;0;NSM;;;;;N;;;;; +0FB2;TIBETAN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; +0FB3;TIBETAN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; +0FB4;TIBETAN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; +0FB5;TIBETAN SUBJOINED LETTER SSA;Mn;0;NSM;;;;;N;;;;; +0FB6;TIBETAN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; +0FB7;TIBETAN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; +0FB8;TIBETAN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; +0FB9;TIBETAN SUBJOINED LETTER KSSA;Mn;0;NSM;0F90 0FB5;;;;N;;;;; +0FBA;TIBETAN SUBJOINED LETTER FIXED-FORM WA;Mn;0;NSM;;;;;N;;;;; +0FBB;TIBETAN SUBJOINED LETTER FIXED-FORM YA;Mn;0;NSM;;;;;N;;;;; +0FBC;TIBETAN SUBJOINED LETTER FIXED-FORM RA;Mn;0;NSM;;;;;N;;;;; +0FBE;TIBETAN KU RU KHA;So;0;L;;;;;N;;;;; +0FBF;TIBETAN KU RU KHA BZHI MIG CAN;So;0;L;;;;;N;;;;; +0FC0;TIBETAN CANTILLATION SIGN HEAVY BEAT;So;0;L;;;;;N;;;;; +0FC1;TIBETAN CANTILLATION SIGN LIGHT BEAT;So;0;L;;;;;N;;;;; +0FC2;TIBETAN CANTILLATION SIGN CANG TE-U;So;0;L;;;;;N;;;;; +0FC3;TIBETAN CANTILLATION SIGN SBUB -CHAL;So;0;L;;;;;N;;;;; +0FC4;TIBETAN SYMBOL DRIL BU;So;0;L;;;;;N;;;;; +0FC5;TIBETAN SYMBOL RDO RJE;So;0;L;;;;;N;;;;; +0FC6;TIBETAN SYMBOL PADMA GDAN;Mn;220;NSM;;;;;N;;;;; +0FC7;TIBETAN SYMBOL RDO RJE RGYA GRAM;So;0;L;;;;;N;;;;; +0FC8;TIBETAN SYMBOL PHUR PA;So;0;L;;;;;N;;;;; +0FC9;TIBETAN SYMBOL NOR BU;So;0;L;;;;;N;;;;; +0FCA;TIBETAN SYMBOL NOR BU NYIS -KHYIL;So;0;L;;;;;N;;;;; +0FCB;TIBETAN SYMBOL NOR BU GSUM -KHYIL;So;0;L;;;;;N;;;;; +0FCC;TIBETAN SYMBOL NOR BU BZHI -KHYIL;So;0;L;;;;;N;;;;; +0FCE;TIBETAN SIGN RDEL NAG RDEL DKAR;So;0;L;;;;;N;;;;; +0FCF;TIBETAN SIGN RDEL NAG GSUM;So;0;L;;;;;N;;;;; +0FD0;TIBETAN MARK BSKA- SHOG GI MGO RGYAN;Po;0;L;;;;;N;;;;; +0FD1;TIBETAN MARK MNYAM YIG GI MGO RGYAN;Po;0;L;;;;;N;;;;; +0FD2;TIBETAN MARK NYIS TSHEG;Po;0;L;;;;;N;;;;; +0FD3;TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA;Po;0;L;;;;;N;;;;; +0FD4;TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; +0FD5;RIGHT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; +0FD6;LEFT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; +0FD7;RIGHT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; +0FD8;LEFT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; +0FD9;TIBETAN MARK LEADING MCHAN RTAGS;Po;0;L;;;;;N;;;;; +0FDA;TIBETAN MARK TRAILING MCHAN RTAGS;Po;0;L;;;;;N;;;;; +1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;; +1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;; +1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;; +1003;MYANMAR LETTER GHA;Lo;0;L;;;;;N;;;;; +1004;MYANMAR LETTER NGA;Lo;0;L;;;;;N;;;;; +1005;MYANMAR LETTER CA;Lo;0;L;;;;;N;;;;; +1006;MYANMAR LETTER CHA;Lo;0;L;;;;;N;;;;; +1007;MYANMAR LETTER JA;Lo;0;L;;;;;N;;;;; +1008;MYANMAR LETTER JHA;Lo;0;L;;;;;N;;;;; +1009;MYANMAR LETTER NYA;Lo;0;L;;;;;N;;;;; +100A;MYANMAR LETTER NNYA;Lo;0;L;;;;;N;;;;; +100B;MYANMAR LETTER TTA;Lo;0;L;;;;;N;;;;; +100C;MYANMAR LETTER TTHA;Lo;0;L;;;;;N;;;;; +100D;MYANMAR LETTER DDA;Lo;0;L;;;;;N;;;;; +100E;MYANMAR LETTER DDHA;Lo;0;L;;;;;N;;;;; +100F;MYANMAR LETTER NNA;Lo;0;L;;;;;N;;;;; +1010;MYANMAR LETTER TA;Lo;0;L;;;;;N;;;;; +1011;MYANMAR LETTER THA;Lo;0;L;;;;;N;;;;; +1012;MYANMAR LETTER DA;Lo;0;L;;;;;N;;;;; +1013;MYANMAR LETTER DHA;Lo;0;L;;;;;N;;;;; +1014;MYANMAR LETTER NA;Lo;0;L;;;;;N;;;;; +1015;MYANMAR LETTER PA;Lo;0;L;;;;;N;;;;; +1016;MYANMAR LETTER PHA;Lo;0;L;;;;;N;;;;; +1017;MYANMAR LETTER BA;Lo;0;L;;;;;N;;;;; +1018;MYANMAR LETTER BHA;Lo;0;L;;;;;N;;;;; +1019;MYANMAR LETTER MA;Lo;0;L;;;;;N;;;;; +101A;MYANMAR LETTER YA;Lo;0;L;;;;;N;;;;; +101B;MYANMAR LETTER RA;Lo;0;L;;;;;N;;;;; +101C;MYANMAR LETTER LA;Lo;0;L;;;;;N;;;;; +101D;MYANMAR LETTER WA;Lo;0;L;;;;;N;;;;; +101E;MYANMAR LETTER SA;Lo;0;L;;;;;N;;;;; +101F;MYANMAR LETTER HA;Lo;0;L;;;;;N;;;;; +1020;MYANMAR LETTER LLA;Lo;0;L;;;;;N;;;;; +1021;MYANMAR LETTER A;Lo;0;L;;;;;N;;;;; +1022;MYANMAR LETTER SHAN A;Lo;0;L;;;;;N;;;;; +1023;MYANMAR LETTER I;Lo;0;L;;;;;N;;;;; +1024;MYANMAR LETTER II;Lo;0;L;;;;;N;;;;; +1025;MYANMAR LETTER U;Lo;0;L;;;;;N;;;;; +1026;MYANMAR LETTER UU;Lo;0;L;1025 102E;;;;N;;;;; +1027;MYANMAR LETTER E;Lo;0;L;;;;;N;;;;; +1028;MYANMAR LETTER MON E;Lo;0;L;;;;;N;;;;; +1029;MYANMAR LETTER O;Lo;0;L;;;;;N;;;;; +102A;MYANMAR LETTER AU;Lo;0;L;;;;;N;;;;; +102B;MYANMAR VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; +102C;MYANMAR VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +102D;MYANMAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +102E;MYANMAR VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +102F;MYANMAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1030;MYANMAR VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1031;MYANMAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1032;MYANMAR VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +1033;MYANMAR VOWEL SIGN MON II;Mn;0;NSM;;;;;N;;;;; +1034;MYANMAR VOWEL SIGN MON O;Mn;0;NSM;;;;;N;;;;; +1035;MYANMAR VOWEL SIGN E ABOVE;Mn;0;NSM;;;;;N;;;;; +1036;MYANMAR SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +1037;MYANMAR SIGN DOT BELOW;Mn;7;NSM;;;;;N;;;;; +1038;MYANMAR SIGN VISARGA;Mc;0;L;;;;;N;;;;; +1039;MYANMAR SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +103A;MYANMAR SIGN ASAT;Mn;9;NSM;;;;;N;;;;; +103B;MYANMAR CONSONANT SIGN MEDIAL YA;Mc;0;L;;;;;N;;;;; +103C;MYANMAR CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; +103D;MYANMAR CONSONANT SIGN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; +103E;MYANMAR CONSONANT SIGN MEDIAL HA;Mn;0;NSM;;;;;N;;;;; +103F;MYANMAR LETTER GREAT SA;Lo;0;L;;;;;N;;;;; +1040;MYANMAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1041;MYANMAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1042;MYANMAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1043;MYANMAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1044;MYANMAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1045;MYANMAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1046;MYANMAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1047;MYANMAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1048;MYANMAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1049;MYANMAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +104A;MYANMAR SIGN LITTLE SECTION;Po;0;L;;;;;N;;;;; +104B;MYANMAR SIGN SECTION;Po;0;L;;;;;N;;;;; +104C;MYANMAR SYMBOL LOCATIVE;Po;0;L;;;;;N;;;;; +104D;MYANMAR SYMBOL COMPLETED;Po;0;L;;;;;N;;;;; +104E;MYANMAR SYMBOL AFOREMENTIONED;Po;0;L;;;;;N;;;;; +104F;MYANMAR SYMBOL GENITIVE;Po;0;L;;;;;N;;;;; +1050;MYANMAR LETTER SHA;Lo;0;L;;;;;N;;;;; +1051;MYANMAR LETTER SSA;Lo;0;L;;;;;N;;;;; +1052;MYANMAR LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1053;MYANMAR LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +1054;MYANMAR LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1055;MYANMAR LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1056;MYANMAR VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +1057;MYANMAR VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +1058;MYANMAR VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +1059;MYANMAR VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +105A;MYANMAR LETTER MON NGA;Lo;0;L;;;;;N;;;;; +105B;MYANMAR LETTER MON JHA;Lo;0;L;;;;;N;;;;; +105C;MYANMAR LETTER MON BBA;Lo;0;L;;;;;N;;;;; +105D;MYANMAR LETTER MON BBE;Lo;0;L;;;;;N;;;;; +105E;MYANMAR CONSONANT SIGN MON MEDIAL NA;Mn;0;NSM;;;;;N;;;;; +105F;MYANMAR CONSONANT SIGN MON MEDIAL MA;Mn;0;NSM;;;;;N;;;;; +1060;MYANMAR CONSONANT SIGN MON MEDIAL LA;Mn;0;NSM;;;;;N;;;;; +1061;MYANMAR LETTER SGAW KAREN SHA;Lo;0;L;;;;;N;;;;; +1062;MYANMAR VOWEL SIGN SGAW KAREN EU;Mc;0;L;;;;;N;;;;; +1063;MYANMAR TONE MARK SGAW KAREN HATHI;Mc;0;L;;;;;N;;;;; +1064;MYANMAR TONE MARK SGAW KAREN KE PHO;Mc;0;L;;;;;N;;;;; +1065;MYANMAR LETTER WESTERN PWO KAREN THA;Lo;0;L;;;;;N;;;;; +1066;MYANMAR LETTER WESTERN PWO KAREN PWA;Lo;0;L;;;;;N;;;;; +1067;MYANMAR VOWEL SIGN WESTERN PWO KAREN EU;Mc;0;L;;;;;N;;;;; +1068;MYANMAR VOWEL SIGN WESTERN PWO KAREN UE;Mc;0;L;;;;;N;;;;; +1069;MYANMAR SIGN WESTERN PWO KAREN TONE-1;Mc;0;L;;;;;N;;;;; +106A;MYANMAR SIGN WESTERN PWO KAREN TONE-2;Mc;0;L;;;;;N;;;;; +106B;MYANMAR SIGN WESTERN PWO KAREN TONE-3;Mc;0;L;;;;;N;;;;; +106C;MYANMAR SIGN WESTERN PWO KAREN TONE-4;Mc;0;L;;;;;N;;;;; +106D;MYANMAR SIGN WESTERN PWO KAREN TONE-5;Mc;0;L;;;;;N;;;;; +106E;MYANMAR LETTER EASTERN PWO KAREN NNA;Lo;0;L;;;;;N;;;;; +106F;MYANMAR LETTER EASTERN PWO KAREN YWA;Lo;0;L;;;;;N;;;;; +1070;MYANMAR LETTER EASTERN PWO KAREN GHWA;Lo;0;L;;;;;N;;;;; +1071;MYANMAR VOWEL SIGN GEBA KAREN I;Mn;0;NSM;;;;;N;;;;; +1072;MYANMAR VOWEL SIGN KAYAH OE;Mn;0;NSM;;;;;N;;;;; +1073;MYANMAR VOWEL SIGN KAYAH U;Mn;0;NSM;;;;;N;;;;; +1074;MYANMAR VOWEL SIGN KAYAH EE;Mn;0;NSM;;;;;N;;;;; +1075;MYANMAR LETTER SHAN KA;Lo;0;L;;;;;N;;;;; +1076;MYANMAR LETTER SHAN KHA;Lo;0;L;;;;;N;;;;; +1077;MYANMAR LETTER SHAN GA;Lo;0;L;;;;;N;;;;; +1078;MYANMAR LETTER SHAN CA;Lo;0;L;;;;;N;;;;; +1079;MYANMAR LETTER SHAN ZA;Lo;0;L;;;;;N;;;;; +107A;MYANMAR LETTER SHAN NYA;Lo;0;L;;;;;N;;;;; +107B;MYANMAR LETTER SHAN DA;Lo;0;L;;;;;N;;;;; +107C;MYANMAR LETTER SHAN NA;Lo;0;L;;;;;N;;;;; +107D;MYANMAR LETTER SHAN PHA;Lo;0;L;;;;;N;;;;; +107E;MYANMAR LETTER SHAN FA;Lo;0;L;;;;;N;;;;; +107F;MYANMAR LETTER SHAN BA;Lo;0;L;;;;;N;;;;; +1080;MYANMAR LETTER SHAN THA;Lo;0;L;;;;;N;;;;; +1081;MYANMAR LETTER SHAN HA;Lo;0;L;;;;;N;;;;; +1082;MYANMAR CONSONANT SIGN SHAN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; +1083;MYANMAR VOWEL SIGN SHAN AA;Mc;0;L;;;;;N;;;;; +1084;MYANMAR VOWEL SIGN SHAN E;Mc;0;L;;;;;N;;;;; +1085;MYANMAR VOWEL SIGN SHAN E ABOVE;Mn;0;NSM;;;;;N;;;;; +1086;MYANMAR VOWEL SIGN SHAN FINAL Y;Mn;0;NSM;;;;;N;;;;; +1087;MYANMAR SIGN SHAN TONE-2;Mc;0;L;;;;;N;;;;; +1088;MYANMAR SIGN SHAN TONE-3;Mc;0;L;;;;;N;;;;; +1089;MYANMAR SIGN SHAN TONE-5;Mc;0;L;;;;;N;;;;; +108A;MYANMAR SIGN SHAN TONE-6;Mc;0;L;;;;;N;;;;; +108B;MYANMAR SIGN SHAN COUNCIL TONE-2;Mc;0;L;;;;;N;;;;; +108C;MYANMAR SIGN SHAN COUNCIL TONE-3;Mc;0;L;;;;;N;;;;; +108D;MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE;Mn;220;NSM;;;;;N;;;;; +108E;MYANMAR LETTER RUMAI PALAUNG FA;Lo;0;L;;;;;N;;;;; +108F;MYANMAR SIGN RUMAI PALAUNG TONE-5;Mc;0;L;;;;;N;;;;; +1090;MYANMAR SHAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1091;MYANMAR SHAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1092;MYANMAR SHAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1093;MYANMAR SHAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1094;MYANMAR SHAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1095;MYANMAR SHAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1096;MYANMAR SHAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1097;MYANMAR SHAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1098;MYANMAR SHAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1099;MYANMAR SHAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +109A;MYANMAR SIGN KHAMTI TONE-1;Mc;0;L;;;;;N;;;;; +109B;MYANMAR SIGN KHAMTI TONE-3;Mc;0;L;;;;;N;;;;; +109C;MYANMAR VOWEL SIGN AITON A;Mc;0;L;;;;;N;;;;; +109D;MYANMAR VOWEL SIGN AITON AI;Mn;0;NSM;;;;;N;;;;; +109E;MYANMAR SYMBOL SHAN ONE;So;0;L;;;;;N;;;;; +109F;MYANMAR SYMBOL SHAN EXCLAMATION;So;0;L;;;;;N;;;;; +10A0;GEORGIAN CAPITAL LETTER AN;Lu;0;L;;;;;N;;;;2D00; +10A1;GEORGIAN CAPITAL LETTER BAN;Lu;0;L;;;;;N;;;;2D01; +10A2;GEORGIAN CAPITAL LETTER GAN;Lu;0;L;;;;;N;;;;2D02; +10A3;GEORGIAN CAPITAL LETTER DON;Lu;0;L;;;;;N;;;;2D03; +10A4;GEORGIAN CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;2D04; +10A5;GEORGIAN CAPITAL LETTER VIN;Lu;0;L;;;;;N;;;;2D05; +10A6;GEORGIAN CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;;;2D06; +10A7;GEORGIAN CAPITAL LETTER TAN;Lu;0;L;;;;;N;;;;2D07; +10A8;GEORGIAN CAPITAL LETTER IN;Lu;0;L;;;;;N;;;;2D08; +10A9;GEORGIAN CAPITAL LETTER KAN;Lu;0;L;;;;;N;;;;2D09; +10AA;GEORGIAN CAPITAL LETTER LAS;Lu;0;L;;;;;N;;;;2D0A; +10AB;GEORGIAN CAPITAL LETTER MAN;Lu;0;L;;;;;N;;;;2D0B; +10AC;GEORGIAN CAPITAL LETTER NAR;Lu;0;L;;;;;N;;;;2D0C; +10AD;GEORGIAN CAPITAL LETTER ON;Lu;0;L;;;;;N;;;;2D0D; +10AE;GEORGIAN CAPITAL LETTER PAR;Lu;0;L;;;;;N;;;;2D0E; +10AF;GEORGIAN CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;;;2D0F; +10B0;GEORGIAN CAPITAL LETTER RAE;Lu;0;L;;;;;N;;;;2D10; +10B1;GEORGIAN CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;2D11; +10B2;GEORGIAN CAPITAL LETTER TAR;Lu;0;L;;;;;N;;;;2D12; +10B3;GEORGIAN CAPITAL LETTER UN;Lu;0;L;;;;;N;;;;2D13; +10B4;GEORGIAN CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;;;2D14; +10B5;GEORGIAN CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;;;2D15; +10B6;GEORGIAN CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;;;2D16; +10B7;GEORGIAN CAPITAL LETTER QAR;Lu;0;L;;;;;N;;;;2D17; +10B8;GEORGIAN CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;;;2D18; +10B9;GEORGIAN CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;;;2D19; +10BA;GEORGIAN CAPITAL LETTER CAN;Lu;0;L;;;;;N;;;;2D1A; +10BB;GEORGIAN CAPITAL LETTER JIL;Lu;0;L;;;;;N;;;;2D1B; +10BC;GEORGIAN CAPITAL LETTER CIL;Lu;0;L;;;;;N;;;;2D1C; +10BD;GEORGIAN CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;;;2D1D; +10BE;GEORGIAN CAPITAL LETTER XAN;Lu;0;L;;;;;N;;;;2D1E; +10BF;GEORGIAN CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;;;2D1F; +10C0;GEORGIAN CAPITAL LETTER HAE;Lu;0;L;;;;;N;;;;2D20; +10C1;GEORGIAN CAPITAL LETTER HE;Lu;0;L;;;;;N;;;;2D21; +10C2;GEORGIAN CAPITAL LETTER HIE;Lu;0;L;;;;;N;;;;2D22; +10C3;GEORGIAN CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;2D23; +10C4;GEORGIAN CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;2D24; +10C5;GEORGIAN CAPITAL LETTER HOE;Lu;0;L;;;;;N;;;;2D25; +10C7;GEORGIAN CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;2D27; +10CD;GEORGIAN CAPITAL LETTER AEN;Lu;0;L;;;;;N;;;;2D2D; +10D0;GEORGIAN LETTER AN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER AN;;;; +10D1;GEORGIAN LETTER BAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER BAN;;;; +10D2;GEORGIAN LETTER GAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GAN;;;; +10D3;GEORGIAN LETTER DON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER DON;;;; +10D4;GEORGIAN LETTER EN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER EN;;;; +10D5;GEORGIAN LETTER VIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER VIN;;;; +10D6;GEORGIAN LETTER ZEN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZEN;;;; +10D7;GEORGIAN LETTER TAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAN;;;; +10D8;GEORGIAN LETTER IN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER IN;;;; +10D9;GEORGIAN LETTER KAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KAN;;;; +10DA;GEORGIAN LETTER LAS;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER LAS;;;; +10DB;GEORGIAN LETTER MAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER MAN;;;; +10DC;GEORGIAN LETTER NAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER NAR;;;; +10DD;GEORGIAN LETTER ON;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ON;;;; +10DE;GEORGIAN LETTER PAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PAR;;;; +10DF;GEORGIAN LETTER ZHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER ZHAR;;;; +10E0;GEORGIAN LETTER RAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER RAE;;;; +10E1;GEORGIAN LETTER SAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SAN;;;; +10E2;GEORGIAN LETTER TAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER TAR;;;; +10E3;GEORGIAN LETTER UN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER UN;;;; +10E4;GEORGIAN LETTER PHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER PHAR;;;; +10E5;GEORGIAN LETTER KHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER KHAR;;;; +10E6;GEORGIAN LETTER GHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER GHAN;;;; +10E7;GEORGIAN LETTER QAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER QAR;;;; +10E8;GEORGIAN LETTER SHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER SHIN;;;; +10E9;GEORGIAN LETTER CHIN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHIN;;;; +10EA;GEORGIAN LETTER CAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CAN;;;; +10EB;GEORGIAN LETTER JIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JIL;;;; +10EC;GEORGIAN LETTER CIL;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CIL;;;; +10ED;GEORGIAN LETTER CHAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER CHAR;;;; +10EE;GEORGIAN LETTER XAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER XAN;;;; +10EF;GEORGIAN LETTER JHAN;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER JHAN;;;; +10F0;GEORGIAN LETTER HAE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAE;;;; +10F1;GEORGIAN LETTER HE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HE;;;; +10F2;GEORGIAN LETTER HIE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HIE;;;; +10F3;GEORGIAN LETTER WE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER WE;;;; +10F4;GEORGIAN LETTER HAR;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HAR;;;; +10F5;GEORGIAN LETTER HOE;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER HOE;;;; +10F6;GEORGIAN LETTER FI;Lo;0;L;;;;;N;GEORGIAN SMALL LETTER FI;;;; +10F7;GEORGIAN LETTER YN;Lo;0;L;;;;;N;;;;; +10F8;GEORGIAN LETTER ELIFI;Lo;0;L;;;;;N;;;;; +10F9;GEORGIAN LETTER TURNED GAN;Lo;0;L;;;;;N;;;;; +10FA;GEORGIAN LETTER AIN;Lo;0;L;;;;;N;;;;; +10FB;GEORGIAN PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; +10FC;MODIFIER LETTER GEORGIAN NAR;Lm;0;L;<super> 10DC;;;;N;;;;; +10FD;GEORGIAN LETTER AEN;Lo;0;L;;;;;N;;;;; +10FE;GEORGIAN LETTER HARD SIGN;Lo;0;L;;;;;N;;;;; +10FF;GEORGIAN LETTER LABIAL SIGN;Lo;0;L;;;;;N;;;;; +1100;HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;; +1101;HANGUL CHOSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +1102;HANGUL CHOSEONG NIEUN;Lo;0;L;;;;;N;;;;; +1103;HANGUL CHOSEONG TIKEUT;Lo;0;L;;;;;N;;;;; +1104;HANGUL CHOSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; +1105;HANGUL CHOSEONG RIEUL;Lo;0;L;;;;;N;;;;; +1106;HANGUL CHOSEONG MIEUM;Lo;0;L;;;;;N;;;;; +1107;HANGUL CHOSEONG PIEUP;Lo;0;L;;;;;N;;;;; +1108;HANGUL CHOSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; +1109;HANGUL CHOSEONG SIOS;Lo;0;L;;;;;N;;;;; +110A;HANGUL CHOSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; +110B;HANGUL CHOSEONG IEUNG;Lo;0;L;;;;;N;;;;; +110C;HANGUL CHOSEONG CIEUC;Lo;0;L;;;;;N;;;;; +110D;HANGUL CHOSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; +110E;HANGUL CHOSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; +110F;HANGUL CHOSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; +1110;HANGUL CHOSEONG THIEUTH;Lo;0;L;;;;;N;;;;; +1111;HANGUL CHOSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; +1112;HANGUL CHOSEONG HIEUH;Lo;0;L;;;;;N;;;;; +1113;HANGUL CHOSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; +1114;HANGUL CHOSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; +1115;HANGUL CHOSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; +1116;HANGUL CHOSEONG NIEUN-PIEUP;Lo;0;L;;;;;N;;;;; +1117;HANGUL CHOSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; +1118;HANGUL CHOSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; +1119;HANGUL CHOSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; +111A;HANGUL CHOSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; +111B;HANGUL CHOSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; +111C;HANGUL CHOSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; +111D;HANGUL CHOSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; +111E;HANGUL CHOSEONG PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; +111F;HANGUL CHOSEONG PIEUP-NIEUN;Lo;0;L;;;;;N;;;;; +1120;HANGUL CHOSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; +1121;HANGUL CHOSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; +1122;HANGUL CHOSEONG PIEUP-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +1123;HANGUL CHOSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +1124;HANGUL CHOSEONG PIEUP-SIOS-PIEUP;Lo;0;L;;;;;N;;;;; +1125;HANGUL CHOSEONG PIEUP-SSANGSIOS;Lo;0;L;;;;;N;;;;; +1126;HANGUL CHOSEONG PIEUP-SIOS-CIEUC;Lo;0;L;;;;;N;;;;; +1127;HANGUL CHOSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; +1128;HANGUL CHOSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; +1129;HANGUL CHOSEONG PIEUP-THIEUTH;Lo;0;L;;;;;N;;;;; +112A;HANGUL CHOSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; +112B;HANGUL CHOSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +112C;HANGUL CHOSEONG KAPYEOUNSSANGPIEUP;Lo;0;L;;;;;N;;;;; +112D;HANGUL CHOSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +112E;HANGUL CHOSEONG SIOS-NIEUN;Lo;0;L;;;;;N;;;;; +112F;HANGUL CHOSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +1130;HANGUL CHOSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; +1131;HANGUL CHOSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; +1132;HANGUL CHOSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; +1133;HANGUL CHOSEONG SIOS-PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; +1134;HANGUL CHOSEONG SIOS-SSANGSIOS;Lo;0;L;;;;;N;;;;; +1135;HANGUL CHOSEONG SIOS-IEUNG;Lo;0;L;;;;;N;;;;; +1136;HANGUL CHOSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; +1137;HANGUL CHOSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; +1138;HANGUL CHOSEONG SIOS-KHIEUKH;Lo;0;L;;;;;N;;;;; +1139;HANGUL CHOSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; +113A;HANGUL CHOSEONG SIOS-PHIEUPH;Lo;0;L;;;;;N;;;;; +113B;HANGUL CHOSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; +113C;HANGUL CHOSEONG CHITUEUMSIOS;Lo;0;L;;;;;N;;;;; +113D;HANGUL CHOSEONG CHITUEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; +113E;HANGUL CHOSEONG CEONGCHIEUMSIOS;Lo;0;L;;;;;N;;;;; +113F;HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; +1140;HANGUL CHOSEONG PANSIOS;Lo;0;L;;;;;N;;;;; +1141;HANGUL CHOSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; +1142;HANGUL CHOSEONG IEUNG-TIKEUT;Lo;0;L;;;;;N;;;;; +1143;HANGUL CHOSEONG IEUNG-MIEUM;Lo;0;L;;;;;N;;;;; +1144;HANGUL CHOSEONG IEUNG-PIEUP;Lo;0;L;;;;;N;;;;; +1145;HANGUL CHOSEONG IEUNG-SIOS;Lo;0;L;;;;;N;;;;; +1146;HANGUL CHOSEONG IEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; +1147;HANGUL CHOSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; +1148;HANGUL CHOSEONG IEUNG-CIEUC;Lo;0;L;;;;;N;;;;; +1149;HANGUL CHOSEONG IEUNG-CHIEUCH;Lo;0;L;;;;;N;;;;; +114A;HANGUL CHOSEONG IEUNG-THIEUTH;Lo;0;L;;;;;N;;;;; +114B;HANGUL CHOSEONG IEUNG-PHIEUPH;Lo;0;L;;;;;N;;;;; +114C;HANGUL CHOSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; +114D;HANGUL CHOSEONG CIEUC-IEUNG;Lo;0;L;;;;;N;;;;; +114E;HANGUL CHOSEONG CHITUEUMCIEUC;Lo;0;L;;;;;N;;;;; +114F;HANGUL CHOSEONG CHITUEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; +1150;HANGUL CHOSEONG CEONGCHIEUMCIEUC;Lo;0;L;;;;;N;;;;; +1151;HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; +1152;HANGUL CHOSEONG CHIEUCH-KHIEUKH;Lo;0;L;;;;;N;;;;; +1153;HANGUL CHOSEONG CHIEUCH-HIEUH;Lo;0;L;;;;;N;;;;; +1154;HANGUL CHOSEONG CHITUEUMCHIEUCH;Lo;0;L;;;;;N;;;;; +1155;HANGUL CHOSEONG CEONGCHIEUMCHIEUCH;Lo;0;L;;;;;N;;;;; +1156;HANGUL CHOSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; +1157;HANGUL CHOSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; +1158;HANGUL CHOSEONG SSANGHIEUH;Lo;0;L;;;;;N;;;;; +1159;HANGUL CHOSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; +115A;HANGUL CHOSEONG KIYEOK-TIKEUT;Lo;0;L;;;;;N;;;;; +115B;HANGUL CHOSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; +115C;HANGUL CHOSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; +115D;HANGUL CHOSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; +115E;HANGUL CHOSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; +115F;HANGUL CHOSEONG FILLER;Lo;0;L;;;;;N;;;;; +1160;HANGUL JUNGSEONG FILLER;Lo;0;L;;;;;N;;;;; +1161;HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;; +1162;HANGUL JUNGSEONG AE;Lo;0;L;;;;;N;;;;; +1163;HANGUL JUNGSEONG YA;Lo;0;L;;;;;N;;;;; +1164;HANGUL JUNGSEONG YAE;Lo;0;L;;;;;N;;;;; +1165;HANGUL JUNGSEONG EO;Lo;0;L;;;;;N;;;;; +1166;HANGUL JUNGSEONG E;Lo;0;L;;;;;N;;;;; +1167;HANGUL JUNGSEONG YEO;Lo;0;L;;;;;N;;;;; +1168;HANGUL JUNGSEONG YE;Lo;0;L;;;;;N;;;;; +1169;HANGUL JUNGSEONG O;Lo;0;L;;;;;N;;;;; +116A;HANGUL JUNGSEONG WA;Lo;0;L;;;;;N;;;;; +116B;HANGUL JUNGSEONG WAE;Lo;0;L;;;;;N;;;;; +116C;HANGUL JUNGSEONG OE;Lo;0;L;;;;;N;;;;; +116D;HANGUL JUNGSEONG YO;Lo;0;L;;;;;N;;;;; +116E;HANGUL JUNGSEONG U;Lo;0;L;;;;;N;;;;; +116F;HANGUL JUNGSEONG WEO;Lo;0;L;;;;;N;;;;; +1170;HANGUL JUNGSEONG WE;Lo;0;L;;;;;N;;;;; +1171;HANGUL JUNGSEONG WI;Lo;0;L;;;;;N;;;;; +1172;HANGUL JUNGSEONG YU;Lo;0;L;;;;;N;;;;; +1173;HANGUL JUNGSEONG EU;Lo;0;L;;;;;N;;;;; +1174;HANGUL JUNGSEONG YI;Lo;0;L;;;;;N;;;;; +1175;HANGUL JUNGSEONG I;Lo;0;L;;;;;N;;;;; +1176;HANGUL JUNGSEONG A-O;Lo;0;L;;;;;N;;;;; +1177;HANGUL JUNGSEONG A-U;Lo;0;L;;;;;N;;;;; +1178;HANGUL JUNGSEONG YA-O;Lo;0;L;;;;;N;;;;; +1179;HANGUL JUNGSEONG YA-YO;Lo;0;L;;;;;N;;;;; +117A;HANGUL JUNGSEONG EO-O;Lo;0;L;;;;;N;;;;; +117B;HANGUL JUNGSEONG EO-U;Lo;0;L;;;;;N;;;;; +117C;HANGUL JUNGSEONG EO-EU;Lo;0;L;;;;;N;;;;; +117D;HANGUL JUNGSEONG YEO-O;Lo;0;L;;;;;N;;;;; +117E;HANGUL JUNGSEONG YEO-U;Lo;0;L;;;;;N;;;;; +117F;HANGUL JUNGSEONG O-EO;Lo;0;L;;;;;N;;;;; +1180;HANGUL JUNGSEONG O-E;Lo;0;L;;;;;N;;;;; +1181;HANGUL JUNGSEONG O-YE;Lo;0;L;;;;;N;;;;; +1182;HANGUL JUNGSEONG O-O;Lo;0;L;;;;;N;;;;; +1183;HANGUL JUNGSEONG O-U;Lo;0;L;;;;;N;;;;; +1184;HANGUL JUNGSEONG YO-YA;Lo;0;L;;;;;N;;;;; +1185;HANGUL JUNGSEONG YO-YAE;Lo;0;L;;;;;N;;;;; +1186;HANGUL JUNGSEONG YO-YEO;Lo;0;L;;;;;N;;;;; +1187;HANGUL JUNGSEONG YO-O;Lo;0;L;;;;;N;;;;; +1188;HANGUL JUNGSEONG YO-I;Lo;0;L;;;;;N;;;;; +1189;HANGUL JUNGSEONG U-A;Lo;0;L;;;;;N;;;;; +118A;HANGUL JUNGSEONG U-AE;Lo;0;L;;;;;N;;;;; +118B;HANGUL JUNGSEONG U-EO-EU;Lo;0;L;;;;;N;;;;; +118C;HANGUL JUNGSEONG U-YE;Lo;0;L;;;;;N;;;;; +118D;HANGUL JUNGSEONG U-U;Lo;0;L;;;;;N;;;;; +118E;HANGUL JUNGSEONG YU-A;Lo;0;L;;;;;N;;;;; +118F;HANGUL JUNGSEONG YU-EO;Lo;0;L;;;;;N;;;;; +1190;HANGUL JUNGSEONG YU-E;Lo;0;L;;;;;N;;;;; +1191;HANGUL JUNGSEONG YU-YEO;Lo;0;L;;;;;N;;;;; +1192;HANGUL JUNGSEONG YU-YE;Lo;0;L;;;;;N;;;;; +1193;HANGUL JUNGSEONG YU-U;Lo;0;L;;;;;N;;;;; +1194;HANGUL JUNGSEONG YU-I;Lo;0;L;;;;;N;;;;; +1195;HANGUL JUNGSEONG EU-U;Lo;0;L;;;;;N;;;;; +1196;HANGUL JUNGSEONG EU-EU;Lo;0;L;;;;;N;;;;; +1197;HANGUL JUNGSEONG YI-U;Lo;0;L;;;;;N;;;;; +1198;HANGUL JUNGSEONG I-A;Lo;0;L;;;;;N;;;;; +1199;HANGUL JUNGSEONG I-YA;Lo;0;L;;;;;N;;;;; +119A;HANGUL JUNGSEONG I-O;Lo;0;L;;;;;N;;;;; +119B;HANGUL JUNGSEONG I-U;Lo;0;L;;;;;N;;;;; +119C;HANGUL JUNGSEONG I-EU;Lo;0;L;;;;;N;;;;; +119D;HANGUL JUNGSEONG I-ARAEA;Lo;0;L;;;;;N;;;;; +119E;HANGUL JUNGSEONG ARAEA;Lo;0;L;;;;;N;;;;; +119F;HANGUL JUNGSEONG ARAEA-EO;Lo;0;L;;;;;N;;;;; +11A0;HANGUL JUNGSEONG ARAEA-U;Lo;0;L;;;;;N;;;;; +11A1;HANGUL JUNGSEONG ARAEA-I;Lo;0;L;;;;;N;;;;; +11A2;HANGUL JUNGSEONG SSANGARAEA;Lo;0;L;;;;;N;;;;; +11A3;HANGUL JUNGSEONG A-EU;Lo;0;L;;;;;N;;;;; +11A4;HANGUL JUNGSEONG YA-U;Lo;0;L;;;;;N;;;;; +11A5;HANGUL JUNGSEONG YEO-YA;Lo;0;L;;;;;N;;;;; +11A6;HANGUL JUNGSEONG O-YA;Lo;0;L;;;;;N;;;;; +11A7;HANGUL JUNGSEONG O-YAE;Lo;0;L;;;;;N;;;;; +11A8;HANGUL JONGSEONG KIYEOK;Lo;0;L;;;;;N;;;;; +11A9;HANGUL JONGSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +11AA;HANGUL JONGSEONG KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; +11AB;HANGUL JONGSEONG NIEUN;Lo;0;L;;;;;N;;;;; +11AC;HANGUL JONGSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; +11AD;HANGUL JONGSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; +11AE;HANGUL JONGSEONG TIKEUT;Lo;0;L;;;;;N;;;;; +11AF;HANGUL JONGSEONG RIEUL;Lo;0;L;;;;;N;;;;; +11B0;HANGUL JONGSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; +11B1;HANGUL JONGSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; +11B2;HANGUL JONGSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; +11B3;HANGUL JONGSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; +11B4;HANGUL JONGSEONG RIEUL-THIEUTH;Lo;0;L;;;;;N;;;;; +11B5;HANGUL JONGSEONG RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; +11B6;HANGUL JONGSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; +11B7;HANGUL JONGSEONG MIEUM;Lo;0;L;;;;;N;;;;; +11B8;HANGUL JONGSEONG PIEUP;Lo;0;L;;;;;N;;;;; +11B9;HANGUL JONGSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; +11BA;HANGUL JONGSEONG SIOS;Lo;0;L;;;;;N;;;;; +11BB;HANGUL JONGSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; +11BC;HANGUL JONGSEONG IEUNG;Lo;0;L;;;;;N;;;;; +11BD;HANGUL JONGSEONG CIEUC;Lo;0;L;;;;;N;;;;; +11BE;HANGUL JONGSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; +11BF;HANGUL JONGSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; +11C0;HANGUL JONGSEONG THIEUTH;Lo;0;L;;;;;N;;;;; +11C1;HANGUL JONGSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; +11C2;HANGUL JONGSEONG HIEUH;Lo;0;L;;;;;N;;;;; +11C3;HANGUL JONGSEONG KIYEOK-RIEUL;Lo;0;L;;;;;N;;;;; +11C4;HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +11C5;HANGUL JONGSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; +11C6;HANGUL JONGSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; +11C7;HANGUL JONGSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; +11C8;HANGUL JONGSEONG NIEUN-PANSIOS;Lo;0;L;;;;;N;;;;; +11C9;HANGUL JONGSEONG NIEUN-THIEUTH;Lo;0;L;;;;;N;;;;; +11CA;HANGUL JONGSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; +11CB;HANGUL JONGSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; +11CC;HANGUL JONGSEONG RIEUL-KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; +11CD;HANGUL JONGSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; +11CE;HANGUL JONGSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; +11CF;HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH;Lo;0;L;;;;;N;;;;; +11D0;HANGUL JONGSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; +11D1;HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; +11D2;HANGUL JONGSEONG RIEUL-MIEUM-SIOS;Lo;0;L;;;;;N;;;;; +11D3;HANGUL JONGSEONG RIEUL-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; +11D4;HANGUL JONGSEONG RIEUL-PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; +11D5;HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +11D6;HANGUL JONGSEONG RIEUL-SSANGSIOS;Lo;0;L;;;;;N;;;;; +11D7;HANGUL JONGSEONG RIEUL-PANSIOS;Lo;0;L;;;;;N;;;;; +11D8;HANGUL JONGSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; +11D9;HANGUL JONGSEONG RIEUL-YEORINHIEUH;Lo;0;L;;;;;N;;;;; +11DA;HANGUL JONGSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; +11DB;HANGUL JONGSEONG MIEUM-RIEUL;Lo;0;L;;;;;N;;;;; +11DC;HANGUL JONGSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; +11DD;HANGUL JONGSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; +11DE;HANGUL JONGSEONG MIEUM-SSANGSIOS;Lo;0;L;;;;;N;;;;; +11DF;HANGUL JONGSEONG MIEUM-PANSIOS;Lo;0;L;;;;;N;;;;; +11E0;HANGUL JONGSEONG MIEUM-CHIEUCH;Lo;0;L;;;;;N;;;;; +11E1;HANGUL JONGSEONG MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; +11E2;HANGUL JONGSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; +11E3;HANGUL JONGSEONG PIEUP-RIEUL;Lo;0;L;;;;;N;;;;; +11E4;HANGUL JONGSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; +11E5;HANGUL JONGSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; +11E6;HANGUL JONGSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +11E7;HANGUL JONGSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +11E8;HANGUL JONGSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +11E9;HANGUL JONGSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; +11EA;HANGUL JONGSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; +11EB;HANGUL JONGSEONG PANSIOS;Lo;0;L;;;;;N;;;;; +11EC;HANGUL JONGSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; +11ED;HANGUL JONGSEONG IEUNG-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +11EE;HANGUL JONGSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; +11EF;HANGUL JONGSEONG IEUNG-KHIEUKH;Lo;0;L;;;;;N;;;;; +11F0;HANGUL JONGSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; +11F1;HANGUL JONGSEONG YESIEUNG-SIOS;Lo;0;L;;;;;N;;;;; +11F2;HANGUL JONGSEONG YESIEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; +11F3;HANGUL JONGSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; +11F4;HANGUL JONGSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; +11F5;HANGUL JONGSEONG HIEUH-NIEUN;Lo;0;L;;;;;N;;;;; +11F6;HANGUL JONGSEONG HIEUH-RIEUL;Lo;0;L;;;;;N;;;;; +11F7;HANGUL JONGSEONG HIEUH-MIEUM;Lo;0;L;;;;;N;;;;; +11F8;HANGUL JONGSEONG HIEUH-PIEUP;Lo;0;L;;;;;N;;;;; +11F9;HANGUL JONGSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; +11FA;HANGUL JONGSEONG KIYEOK-NIEUN;Lo;0;L;;;;;N;;;;; +11FB;HANGUL JONGSEONG KIYEOK-PIEUP;Lo;0;L;;;;;N;;;;; +11FC;HANGUL JONGSEONG KIYEOK-CHIEUCH;Lo;0;L;;;;;N;;;;; +11FD;HANGUL JONGSEONG KIYEOK-KHIEUKH;Lo;0;L;;;;;N;;;;; +11FE;HANGUL JONGSEONG KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; +11FF;HANGUL JONGSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; +1200;ETHIOPIC SYLLABLE HA;Lo;0;L;;;;;N;;;;; +1201;ETHIOPIC SYLLABLE HU;Lo;0;L;;;;;N;;;;; +1202;ETHIOPIC SYLLABLE HI;Lo;0;L;;;;;N;;;;; +1203;ETHIOPIC SYLLABLE HAA;Lo;0;L;;;;;N;;;;; +1204;ETHIOPIC SYLLABLE HEE;Lo;0;L;;;;;N;;;;; +1205;ETHIOPIC SYLLABLE HE;Lo;0;L;;;;;N;;;;; +1206;ETHIOPIC SYLLABLE HO;Lo;0;L;;;;;N;;;;; +1207;ETHIOPIC SYLLABLE HOA;Lo;0;L;;;;;N;;;;; +1208;ETHIOPIC SYLLABLE LA;Lo;0;L;;;;;N;;;;; +1209;ETHIOPIC SYLLABLE LU;Lo;0;L;;;;;N;;;;; +120A;ETHIOPIC SYLLABLE LI;Lo;0;L;;;;;N;;;;; +120B;ETHIOPIC SYLLABLE LAA;Lo;0;L;;;;;N;;;;; +120C;ETHIOPIC SYLLABLE LEE;Lo;0;L;;;;;N;;;;; +120D;ETHIOPIC SYLLABLE LE;Lo;0;L;;;;;N;;;;; +120E;ETHIOPIC SYLLABLE LO;Lo;0;L;;;;;N;;;;; +120F;ETHIOPIC SYLLABLE LWA;Lo;0;L;;;;;N;;;;; +1210;ETHIOPIC SYLLABLE HHA;Lo;0;L;;;;;N;;;;; +1211;ETHIOPIC SYLLABLE HHU;Lo;0;L;;;;;N;;;;; +1212;ETHIOPIC SYLLABLE HHI;Lo;0;L;;;;;N;;;;; +1213;ETHIOPIC SYLLABLE HHAA;Lo;0;L;;;;;N;;;;; +1214;ETHIOPIC SYLLABLE HHEE;Lo;0;L;;;;;N;;;;; +1215;ETHIOPIC SYLLABLE HHE;Lo;0;L;;;;;N;;;;; +1216;ETHIOPIC SYLLABLE HHO;Lo;0;L;;;;;N;;;;; +1217;ETHIOPIC SYLLABLE HHWA;Lo;0;L;;;;;N;;;;; +1218;ETHIOPIC SYLLABLE MA;Lo;0;L;;;;;N;;;;; +1219;ETHIOPIC SYLLABLE MU;Lo;0;L;;;;;N;;;;; +121A;ETHIOPIC SYLLABLE MI;Lo;0;L;;;;;N;;;;; +121B;ETHIOPIC SYLLABLE MAA;Lo;0;L;;;;;N;;;;; +121C;ETHIOPIC SYLLABLE MEE;Lo;0;L;;;;;N;;;;; +121D;ETHIOPIC SYLLABLE ME;Lo;0;L;;;;;N;;;;; +121E;ETHIOPIC SYLLABLE MO;Lo;0;L;;;;;N;;;;; +121F;ETHIOPIC SYLLABLE MWA;Lo;0;L;;;;;N;;;;; +1220;ETHIOPIC SYLLABLE SZA;Lo;0;L;;;;;N;;;;; +1221;ETHIOPIC SYLLABLE SZU;Lo;0;L;;;;;N;;;;; +1222;ETHIOPIC SYLLABLE SZI;Lo;0;L;;;;;N;;;;; +1223;ETHIOPIC SYLLABLE SZAA;Lo;0;L;;;;;N;;;;; +1224;ETHIOPIC SYLLABLE SZEE;Lo;0;L;;;;;N;;;;; +1225;ETHIOPIC SYLLABLE SZE;Lo;0;L;;;;;N;;;;; +1226;ETHIOPIC SYLLABLE SZO;Lo;0;L;;;;;N;;;;; +1227;ETHIOPIC SYLLABLE SZWA;Lo;0;L;;;;;N;;;;; +1228;ETHIOPIC SYLLABLE RA;Lo;0;L;;;;;N;;;;; +1229;ETHIOPIC SYLLABLE RU;Lo;0;L;;;;;N;;;;; +122A;ETHIOPIC SYLLABLE RI;Lo;0;L;;;;;N;;;;; +122B;ETHIOPIC SYLLABLE RAA;Lo;0;L;;;;;N;;;;; +122C;ETHIOPIC SYLLABLE REE;Lo;0;L;;;;;N;;;;; +122D;ETHIOPIC SYLLABLE RE;Lo;0;L;;;;;N;;;;; +122E;ETHIOPIC SYLLABLE RO;Lo;0;L;;;;;N;;;;; +122F;ETHIOPIC SYLLABLE RWA;Lo;0;L;;;;;N;;;;; +1230;ETHIOPIC SYLLABLE SA;Lo;0;L;;;;;N;;;;; +1231;ETHIOPIC SYLLABLE SU;Lo;0;L;;;;;N;;;;; +1232;ETHIOPIC SYLLABLE SI;Lo;0;L;;;;;N;;;;; +1233;ETHIOPIC SYLLABLE SAA;Lo;0;L;;;;;N;;;;; +1234;ETHIOPIC SYLLABLE SEE;Lo;0;L;;;;;N;;;;; +1235;ETHIOPIC SYLLABLE SE;Lo;0;L;;;;;N;;;;; +1236;ETHIOPIC SYLLABLE SO;Lo;0;L;;;;;N;;;;; +1237;ETHIOPIC SYLLABLE SWA;Lo;0;L;;;;;N;;;;; +1238;ETHIOPIC SYLLABLE SHA;Lo;0;L;;;;;N;;;;; +1239;ETHIOPIC SYLLABLE SHU;Lo;0;L;;;;;N;;;;; +123A;ETHIOPIC SYLLABLE SHI;Lo;0;L;;;;;N;;;;; +123B;ETHIOPIC SYLLABLE SHAA;Lo;0;L;;;;;N;;;;; +123C;ETHIOPIC SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; +123D;ETHIOPIC SYLLABLE SHE;Lo;0;L;;;;;N;;;;; +123E;ETHIOPIC SYLLABLE SHO;Lo;0;L;;;;;N;;;;; +123F;ETHIOPIC SYLLABLE SHWA;Lo;0;L;;;;;N;;;;; +1240;ETHIOPIC SYLLABLE QA;Lo;0;L;;;;;N;;;;; +1241;ETHIOPIC SYLLABLE QU;Lo;0;L;;;;;N;;;;; +1242;ETHIOPIC SYLLABLE QI;Lo;0;L;;;;;N;;;;; +1243;ETHIOPIC SYLLABLE QAA;Lo;0;L;;;;;N;;;;; +1244;ETHIOPIC SYLLABLE QEE;Lo;0;L;;;;;N;;;;; +1245;ETHIOPIC SYLLABLE QE;Lo;0;L;;;;;N;;;;; +1246;ETHIOPIC SYLLABLE QO;Lo;0;L;;;;;N;;;;; +1247;ETHIOPIC SYLLABLE QOA;Lo;0;L;;;;;N;;;;; +1248;ETHIOPIC SYLLABLE QWA;Lo;0;L;;;;;N;;;;; +124A;ETHIOPIC SYLLABLE QWI;Lo;0;L;;;;;N;;;;; +124B;ETHIOPIC SYLLABLE QWAA;Lo;0;L;;;;;N;;;;; +124C;ETHIOPIC SYLLABLE QWEE;Lo;0;L;;;;;N;;;;; +124D;ETHIOPIC SYLLABLE QWE;Lo;0;L;;;;;N;;;;; +1250;ETHIOPIC SYLLABLE QHA;Lo;0;L;;;;;N;;;;; +1251;ETHIOPIC SYLLABLE QHU;Lo;0;L;;;;;N;;;;; +1252;ETHIOPIC SYLLABLE QHI;Lo;0;L;;;;;N;;;;; +1253;ETHIOPIC SYLLABLE QHAA;Lo;0;L;;;;;N;;;;; +1254;ETHIOPIC SYLLABLE QHEE;Lo;0;L;;;;;N;;;;; +1255;ETHIOPIC SYLLABLE QHE;Lo;0;L;;;;;N;;;;; +1256;ETHIOPIC SYLLABLE QHO;Lo;0;L;;;;;N;;;;; +1258;ETHIOPIC SYLLABLE QHWA;Lo;0;L;;;;;N;;;;; +125A;ETHIOPIC SYLLABLE QHWI;Lo;0;L;;;;;N;;;;; +125B;ETHIOPIC SYLLABLE QHWAA;Lo;0;L;;;;;N;;;;; +125C;ETHIOPIC SYLLABLE QHWEE;Lo;0;L;;;;;N;;;;; +125D;ETHIOPIC SYLLABLE QHWE;Lo;0;L;;;;;N;;;;; +1260;ETHIOPIC SYLLABLE BA;Lo;0;L;;;;;N;;;;; +1261;ETHIOPIC SYLLABLE BU;Lo;0;L;;;;;N;;;;; +1262;ETHIOPIC SYLLABLE BI;Lo;0;L;;;;;N;;;;; +1263;ETHIOPIC SYLLABLE BAA;Lo;0;L;;;;;N;;;;; +1264;ETHIOPIC SYLLABLE BEE;Lo;0;L;;;;;N;;;;; +1265;ETHIOPIC SYLLABLE BE;Lo;0;L;;;;;N;;;;; +1266;ETHIOPIC SYLLABLE BO;Lo;0;L;;;;;N;;;;; +1267;ETHIOPIC SYLLABLE BWA;Lo;0;L;;;;;N;;;;; +1268;ETHIOPIC SYLLABLE VA;Lo;0;L;;;;;N;;;;; +1269;ETHIOPIC SYLLABLE VU;Lo;0;L;;;;;N;;;;; +126A;ETHIOPIC SYLLABLE VI;Lo;0;L;;;;;N;;;;; +126B;ETHIOPIC SYLLABLE VAA;Lo;0;L;;;;;N;;;;; +126C;ETHIOPIC SYLLABLE VEE;Lo;0;L;;;;;N;;;;; +126D;ETHIOPIC SYLLABLE VE;Lo;0;L;;;;;N;;;;; +126E;ETHIOPIC SYLLABLE VO;Lo;0;L;;;;;N;;;;; +126F;ETHIOPIC SYLLABLE VWA;Lo;0;L;;;;;N;;;;; +1270;ETHIOPIC SYLLABLE TA;Lo;0;L;;;;;N;;;;; +1271;ETHIOPIC SYLLABLE TU;Lo;0;L;;;;;N;;;;; +1272;ETHIOPIC SYLLABLE TI;Lo;0;L;;;;;N;;;;; +1273;ETHIOPIC SYLLABLE TAA;Lo;0;L;;;;;N;;;;; +1274;ETHIOPIC SYLLABLE TEE;Lo;0;L;;;;;N;;;;; +1275;ETHIOPIC SYLLABLE TE;Lo;0;L;;;;;N;;;;; +1276;ETHIOPIC SYLLABLE TO;Lo;0;L;;;;;N;;;;; +1277;ETHIOPIC SYLLABLE TWA;Lo;0;L;;;;;N;;;;; +1278;ETHIOPIC SYLLABLE CA;Lo;0;L;;;;;N;;;;; +1279;ETHIOPIC SYLLABLE CU;Lo;0;L;;;;;N;;;;; +127A;ETHIOPIC SYLLABLE CI;Lo;0;L;;;;;N;;;;; +127B;ETHIOPIC SYLLABLE CAA;Lo;0;L;;;;;N;;;;; +127C;ETHIOPIC SYLLABLE CEE;Lo;0;L;;;;;N;;;;; +127D;ETHIOPIC SYLLABLE CE;Lo;0;L;;;;;N;;;;; +127E;ETHIOPIC SYLLABLE CO;Lo;0;L;;;;;N;;;;; +127F;ETHIOPIC SYLLABLE CWA;Lo;0;L;;;;;N;;;;; +1280;ETHIOPIC SYLLABLE XA;Lo;0;L;;;;;N;;;;; +1281;ETHIOPIC SYLLABLE XU;Lo;0;L;;;;;N;;;;; +1282;ETHIOPIC SYLLABLE XI;Lo;0;L;;;;;N;;;;; +1283;ETHIOPIC SYLLABLE XAA;Lo;0;L;;;;;N;;;;; +1284;ETHIOPIC SYLLABLE XEE;Lo;0;L;;;;;N;;;;; +1285;ETHIOPIC SYLLABLE XE;Lo;0;L;;;;;N;;;;; +1286;ETHIOPIC SYLLABLE XO;Lo;0;L;;;;;N;;;;; +1287;ETHIOPIC SYLLABLE XOA;Lo;0;L;;;;;N;;;;; +1288;ETHIOPIC SYLLABLE XWA;Lo;0;L;;;;;N;;;;; +128A;ETHIOPIC SYLLABLE XWI;Lo;0;L;;;;;N;;;;; +128B;ETHIOPIC SYLLABLE XWAA;Lo;0;L;;;;;N;;;;; +128C;ETHIOPIC SYLLABLE XWEE;Lo;0;L;;;;;N;;;;; +128D;ETHIOPIC SYLLABLE XWE;Lo;0;L;;;;;N;;;;; +1290;ETHIOPIC SYLLABLE NA;Lo;0;L;;;;;N;;;;; +1291;ETHIOPIC SYLLABLE NU;Lo;0;L;;;;;N;;;;; +1292;ETHIOPIC SYLLABLE NI;Lo;0;L;;;;;N;;;;; +1293;ETHIOPIC SYLLABLE NAA;Lo;0;L;;;;;N;;;;; +1294;ETHIOPIC SYLLABLE NEE;Lo;0;L;;;;;N;;;;; +1295;ETHIOPIC SYLLABLE NE;Lo;0;L;;;;;N;;;;; +1296;ETHIOPIC SYLLABLE NO;Lo;0;L;;;;;N;;;;; +1297;ETHIOPIC SYLLABLE NWA;Lo;0;L;;;;;N;;;;; +1298;ETHIOPIC SYLLABLE NYA;Lo;0;L;;;;;N;;;;; +1299;ETHIOPIC SYLLABLE NYU;Lo;0;L;;;;;N;;;;; +129A;ETHIOPIC SYLLABLE NYI;Lo;0;L;;;;;N;;;;; +129B;ETHIOPIC SYLLABLE NYAA;Lo;0;L;;;;;N;;;;; +129C;ETHIOPIC SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; +129D;ETHIOPIC SYLLABLE NYE;Lo;0;L;;;;;N;;;;; +129E;ETHIOPIC SYLLABLE NYO;Lo;0;L;;;;;N;;;;; +129F;ETHIOPIC SYLLABLE NYWA;Lo;0;L;;;;;N;;;;; +12A0;ETHIOPIC SYLLABLE GLOTTAL A;Lo;0;L;;;;;N;;;;; +12A1;ETHIOPIC SYLLABLE GLOTTAL U;Lo;0;L;;;;;N;;;;; +12A2;ETHIOPIC SYLLABLE GLOTTAL I;Lo;0;L;;;;;N;;;;; +12A3;ETHIOPIC SYLLABLE GLOTTAL AA;Lo;0;L;;;;;N;;;;; +12A4;ETHIOPIC SYLLABLE GLOTTAL EE;Lo;0;L;;;;;N;;;;; +12A5;ETHIOPIC SYLLABLE GLOTTAL E;Lo;0;L;;;;;N;;;;; +12A6;ETHIOPIC SYLLABLE GLOTTAL O;Lo;0;L;;;;;N;;;;; +12A7;ETHIOPIC SYLLABLE GLOTTAL WA;Lo;0;L;;;;;N;;;;; +12A8;ETHIOPIC SYLLABLE KA;Lo;0;L;;;;;N;;;;; +12A9;ETHIOPIC SYLLABLE KU;Lo;0;L;;;;;N;;;;; +12AA;ETHIOPIC SYLLABLE KI;Lo;0;L;;;;;N;;;;; +12AB;ETHIOPIC SYLLABLE KAA;Lo;0;L;;;;;N;;;;; +12AC;ETHIOPIC SYLLABLE KEE;Lo;0;L;;;;;N;;;;; +12AD;ETHIOPIC SYLLABLE KE;Lo;0;L;;;;;N;;;;; +12AE;ETHIOPIC SYLLABLE KO;Lo;0;L;;;;;N;;;;; +12AF;ETHIOPIC SYLLABLE KOA;Lo;0;L;;;;;N;;;;; +12B0;ETHIOPIC SYLLABLE KWA;Lo;0;L;;;;;N;;;;; +12B2;ETHIOPIC SYLLABLE KWI;Lo;0;L;;;;;N;;;;; +12B3;ETHIOPIC SYLLABLE KWAA;Lo;0;L;;;;;N;;;;; +12B4;ETHIOPIC SYLLABLE KWEE;Lo;0;L;;;;;N;;;;; +12B5;ETHIOPIC SYLLABLE KWE;Lo;0;L;;;;;N;;;;; +12B8;ETHIOPIC SYLLABLE KXA;Lo;0;L;;;;;N;;;;; +12B9;ETHIOPIC SYLLABLE KXU;Lo;0;L;;;;;N;;;;; +12BA;ETHIOPIC SYLLABLE KXI;Lo;0;L;;;;;N;;;;; +12BB;ETHIOPIC SYLLABLE KXAA;Lo;0;L;;;;;N;;;;; +12BC;ETHIOPIC SYLLABLE KXEE;Lo;0;L;;;;;N;;;;; +12BD;ETHIOPIC SYLLABLE KXE;Lo;0;L;;;;;N;;;;; +12BE;ETHIOPIC SYLLABLE KXO;Lo;0;L;;;;;N;;;;; +12C0;ETHIOPIC SYLLABLE KXWA;Lo;0;L;;;;;N;;;;; +12C2;ETHIOPIC SYLLABLE KXWI;Lo;0;L;;;;;N;;;;; +12C3;ETHIOPIC SYLLABLE KXWAA;Lo;0;L;;;;;N;;;;; +12C4;ETHIOPIC SYLLABLE KXWEE;Lo;0;L;;;;;N;;;;; +12C5;ETHIOPIC SYLLABLE KXWE;Lo;0;L;;;;;N;;;;; +12C8;ETHIOPIC SYLLABLE WA;Lo;0;L;;;;;N;;;;; +12C9;ETHIOPIC SYLLABLE WU;Lo;0;L;;;;;N;;;;; +12CA;ETHIOPIC SYLLABLE WI;Lo;0;L;;;;;N;;;;; +12CB;ETHIOPIC SYLLABLE WAA;Lo;0;L;;;;;N;;;;; +12CC;ETHIOPIC SYLLABLE WEE;Lo;0;L;;;;;N;;;;; +12CD;ETHIOPIC SYLLABLE WE;Lo;0;L;;;;;N;;;;; +12CE;ETHIOPIC SYLLABLE WO;Lo;0;L;;;;;N;;;;; +12CF;ETHIOPIC SYLLABLE WOA;Lo;0;L;;;;;N;;;;; +12D0;ETHIOPIC SYLLABLE PHARYNGEAL A;Lo;0;L;;;;;N;;;;; +12D1;ETHIOPIC SYLLABLE PHARYNGEAL U;Lo;0;L;;;;;N;;;;; +12D2;ETHIOPIC SYLLABLE PHARYNGEAL I;Lo;0;L;;;;;N;;;;; +12D3;ETHIOPIC SYLLABLE PHARYNGEAL AA;Lo;0;L;;;;;N;;;;; +12D4;ETHIOPIC SYLLABLE PHARYNGEAL EE;Lo;0;L;;;;;N;;;;; +12D5;ETHIOPIC SYLLABLE PHARYNGEAL E;Lo;0;L;;;;;N;;;;; +12D6;ETHIOPIC SYLLABLE PHARYNGEAL O;Lo;0;L;;;;;N;;;;; +12D8;ETHIOPIC SYLLABLE ZA;Lo;0;L;;;;;N;;;;; +12D9;ETHIOPIC SYLLABLE ZU;Lo;0;L;;;;;N;;;;; +12DA;ETHIOPIC SYLLABLE ZI;Lo;0;L;;;;;N;;;;; +12DB;ETHIOPIC SYLLABLE ZAA;Lo;0;L;;;;;N;;;;; +12DC;ETHIOPIC SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; +12DD;ETHIOPIC SYLLABLE ZE;Lo;0;L;;;;;N;;;;; +12DE;ETHIOPIC SYLLABLE ZO;Lo;0;L;;;;;N;;;;; +12DF;ETHIOPIC SYLLABLE ZWA;Lo;0;L;;;;;N;;;;; +12E0;ETHIOPIC SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; +12E1;ETHIOPIC SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; +12E2;ETHIOPIC SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; +12E3;ETHIOPIC SYLLABLE ZHAA;Lo;0;L;;;;;N;;;;; +12E4;ETHIOPIC SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; +12E5;ETHIOPIC SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; +12E6;ETHIOPIC SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; +12E7;ETHIOPIC SYLLABLE ZHWA;Lo;0;L;;;;;N;;;;; +12E8;ETHIOPIC SYLLABLE YA;Lo;0;L;;;;;N;;;;; +12E9;ETHIOPIC SYLLABLE YU;Lo;0;L;;;;;N;;;;; +12EA;ETHIOPIC SYLLABLE YI;Lo;0;L;;;;;N;;;;; +12EB;ETHIOPIC SYLLABLE YAA;Lo;0;L;;;;;N;;;;; +12EC;ETHIOPIC SYLLABLE YEE;Lo;0;L;;;;;N;;;;; +12ED;ETHIOPIC SYLLABLE YE;Lo;0;L;;;;;N;;;;; +12EE;ETHIOPIC SYLLABLE YO;Lo;0;L;;;;;N;;;;; +12EF;ETHIOPIC SYLLABLE YOA;Lo;0;L;;;;;N;;;;; +12F0;ETHIOPIC SYLLABLE DA;Lo;0;L;;;;;N;;;;; +12F1;ETHIOPIC SYLLABLE DU;Lo;0;L;;;;;N;;;;; +12F2;ETHIOPIC SYLLABLE DI;Lo;0;L;;;;;N;;;;; +12F3;ETHIOPIC SYLLABLE DAA;Lo;0;L;;;;;N;;;;; +12F4;ETHIOPIC SYLLABLE DEE;Lo;0;L;;;;;N;;;;; +12F5;ETHIOPIC SYLLABLE DE;Lo;0;L;;;;;N;;;;; +12F6;ETHIOPIC SYLLABLE DO;Lo;0;L;;;;;N;;;;; +12F7;ETHIOPIC SYLLABLE DWA;Lo;0;L;;;;;N;;;;; +12F8;ETHIOPIC SYLLABLE DDA;Lo;0;L;;;;;N;;;;; +12F9;ETHIOPIC SYLLABLE DDU;Lo;0;L;;;;;N;;;;; +12FA;ETHIOPIC SYLLABLE DDI;Lo;0;L;;;;;N;;;;; +12FB;ETHIOPIC SYLLABLE DDAA;Lo;0;L;;;;;N;;;;; +12FC;ETHIOPIC SYLLABLE DDEE;Lo;0;L;;;;;N;;;;; +12FD;ETHIOPIC SYLLABLE DDE;Lo;0;L;;;;;N;;;;; +12FE;ETHIOPIC SYLLABLE DDO;Lo;0;L;;;;;N;;;;; +12FF;ETHIOPIC SYLLABLE DDWA;Lo;0;L;;;;;N;;;;; +1300;ETHIOPIC SYLLABLE JA;Lo;0;L;;;;;N;;;;; +1301;ETHIOPIC SYLLABLE JU;Lo;0;L;;;;;N;;;;; +1302;ETHIOPIC SYLLABLE JI;Lo;0;L;;;;;N;;;;; +1303;ETHIOPIC SYLLABLE JAA;Lo;0;L;;;;;N;;;;; +1304;ETHIOPIC SYLLABLE JEE;Lo;0;L;;;;;N;;;;; +1305;ETHIOPIC SYLLABLE JE;Lo;0;L;;;;;N;;;;; +1306;ETHIOPIC SYLLABLE JO;Lo;0;L;;;;;N;;;;; +1307;ETHIOPIC SYLLABLE JWA;Lo;0;L;;;;;N;;;;; +1308;ETHIOPIC SYLLABLE GA;Lo;0;L;;;;;N;;;;; +1309;ETHIOPIC SYLLABLE GU;Lo;0;L;;;;;N;;;;; +130A;ETHIOPIC SYLLABLE GI;Lo;0;L;;;;;N;;;;; +130B;ETHIOPIC SYLLABLE GAA;Lo;0;L;;;;;N;;;;; +130C;ETHIOPIC SYLLABLE GEE;Lo;0;L;;;;;N;;;;; +130D;ETHIOPIC SYLLABLE GE;Lo;0;L;;;;;N;;;;; +130E;ETHIOPIC SYLLABLE GO;Lo;0;L;;;;;N;;;;; +130F;ETHIOPIC SYLLABLE GOA;Lo;0;L;;;;;N;;;;; +1310;ETHIOPIC SYLLABLE GWA;Lo;0;L;;;;;N;;;;; +1312;ETHIOPIC SYLLABLE GWI;Lo;0;L;;;;;N;;;;; +1313;ETHIOPIC SYLLABLE GWAA;Lo;0;L;;;;;N;;;;; +1314;ETHIOPIC SYLLABLE GWEE;Lo;0;L;;;;;N;;;;; +1315;ETHIOPIC SYLLABLE GWE;Lo;0;L;;;;;N;;;;; +1318;ETHIOPIC SYLLABLE GGA;Lo;0;L;;;;;N;;;;; +1319;ETHIOPIC SYLLABLE GGU;Lo;0;L;;;;;N;;;;; +131A;ETHIOPIC SYLLABLE GGI;Lo;0;L;;;;;N;;;;; +131B;ETHIOPIC SYLLABLE GGAA;Lo;0;L;;;;;N;;;;; +131C;ETHIOPIC SYLLABLE GGEE;Lo;0;L;;;;;N;;;;; +131D;ETHIOPIC SYLLABLE GGE;Lo;0;L;;;;;N;;;;; +131E;ETHIOPIC SYLLABLE GGO;Lo;0;L;;;;;N;;;;; +131F;ETHIOPIC SYLLABLE GGWAA;Lo;0;L;;;;;N;;;;; +1320;ETHIOPIC SYLLABLE THA;Lo;0;L;;;;;N;;;;; +1321;ETHIOPIC SYLLABLE THU;Lo;0;L;;;;;N;;;;; +1322;ETHIOPIC SYLLABLE THI;Lo;0;L;;;;;N;;;;; +1323;ETHIOPIC SYLLABLE THAA;Lo;0;L;;;;;N;;;;; +1324;ETHIOPIC SYLLABLE THEE;Lo;0;L;;;;;N;;;;; +1325;ETHIOPIC SYLLABLE THE;Lo;0;L;;;;;N;;;;; +1326;ETHIOPIC SYLLABLE THO;Lo;0;L;;;;;N;;;;; +1327;ETHIOPIC SYLLABLE THWA;Lo;0;L;;;;;N;;;;; +1328;ETHIOPIC SYLLABLE CHA;Lo;0;L;;;;;N;;;;; +1329;ETHIOPIC SYLLABLE CHU;Lo;0;L;;;;;N;;;;; +132A;ETHIOPIC SYLLABLE CHI;Lo;0;L;;;;;N;;;;; +132B;ETHIOPIC SYLLABLE CHAA;Lo;0;L;;;;;N;;;;; +132C;ETHIOPIC SYLLABLE CHEE;Lo;0;L;;;;;N;;;;; +132D;ETHIOPIC SYLLABLE CHE;Lo;0;L;;;;;N;;;;; +132E;ETHIOPIC SYLLABLE CHO;Lo;0;L;;;;;N;;;;; +132F;ETHIOPIC SYLLABLE CHWA;Lo;0;L;;;;;N;;;;; +1330;ETHIOPIC SYLLABLE PHA;Lo;0;L;;;;;N;;;;; +1331;ETHIOPIC SYLLABLE PHU;Lo;0;L;;;;;N;;;;; +1332;ETHIOPIC SYLLABLE PHI;Lo;0;L;;;;;N;;;;; +1333;ETHIOPIC SYLLABLE PHAA;Lo;0;L;;;;;N;;;;; +1334;ETHIOPIC SYLLABLE PHEE;Lo;0;L;;;;;N;;;;; +1335;ETHIOPIC SYLLABLE PHE;Lo;0;L;;;;;N;;;;; +1336;ETHIOPIC SYLLABLE PHO;Lo;0;L;;;;;N;;;;; +1337;ETHIOPIC SYLLABLE PHWA;Lo;0;L;;;;;N;;;;; +1338;ETHIOPIC SYLLABLE TSA;Lo;0;L;;;;;N;;;;; +1339;ETHIOPIC SYLLABLE TSU;Lo;0;L;;;;;N;;;;; +133A;ETHIOPIC SYLLABLE TSI;Lo;0;L;;;;;N;;;;; +133B;ETHIOPIC SYLLABLE TSAA;Lo;0;L;;;;;N;;;;; +133C;ETHIOPIC SYLLABLE TSEE;Lo;0;L;;;;;N;;;;; +133D;ETHIOPIC SYLLABLE TSE;Lo;0;L;;;;;N;;;;; +133E;ETHIOPIC SYLLABLE TSO;Lo;0;L;;;;;N;;;;; +133F;ETHIOPIC SYLLABLE TSWA;Lo;0;L;;;;;N;;;;; +1340;ETHIOPIC SYLLABLE TZA;Lo;0;L;;;;;N;;;;; +1341;ETHIOPIC SYLLABLE TZU;Lo;0;L;;;;;N;;;;; +1342;ETHIOPIC SYLLABLE TZI;Lo;0;L;;;;;N;;;;; +1343;ETHIOPIC SYLLABLE TZAA;Lo;0;L;;;;;N;;;;; +1344;ETHIOPIC SYLLABLE TZEE;Lo;0;L;;;;;N;;;;; +1345;ETHIOPIC SYLLABLE TZE;Lo;0;L;;;;;N;;;;; +1346;ETHIOPIC SYLLABLE TZO;Lo;0;L;;;;;N;;;;; +1347;ETHIOPIC SYLLABLE TZOA;Lo;0;L;;;;;N;;;;; +1348;ETHIOPIC SYLLABLE FA;Lo;0;L;;;;;N;;;;; +1349;ETHIOPIC SYLLABLE FU;Lo;0;L;;;;;N;;;;; +134A;ETHIOPIC SYLLABLE FI;Lo;0;L;;;;;N;;;;; +134B;ETHIOPIC SYLLABLE FAA;Lo;0;L;;;;;N;;;;; +134C;ETHIOPIC SYLLABLE FEE;Lo;0;L;;;;;N;;;;; +134D;ETHIOPIC SYLLABLE FE;Lo;0;L;;;;;N;;;;; +134E;ETHIOPIC SYLLABLE FO;Lo;0;L;;;;;N;;;;; +134F;ETHIOPIC SYLLABLE FWA;Lo;0;L;;;;;N;;;;; +1350;ETHIOPIC SYLLABLE PA;Lo;0;L;;;;;N;;;;; +1351;ETHIOPIC SYLLABLE PU;Lo;0;L;;;;;N;;;;; +1352;ETHIOPIC SYLLABLE PI;Lo;0;L;;;;;N;;;;; +1353;ETHIOPIC SYLLABLE PAA;Lo;0;L;;;;;N;;;;; +1354;ETHIOPIC SYLLABLE PEE;Lo;0;L;;;;;N;;;;; +1355;ETHIOPIC SYLLABLE PE;Lo;0;L;;;;;N;;;;; +1356;ETHIOPIC SYLLABLE PO;Lo;0;L;;;;;N;;;;; +1357;ETHIOPIC SYLLABLE PWA;Lo;0;L;;;;;N;;;;; +1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;; +1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;; +135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;; +135D;ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; +135E;ETHIOPIC COMBINING VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; +135F;ETHIOPIC COMBINING GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; +1360;ETHIOPIC SECTION MARK;Po;0;L;;;;;N;;;;; +1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;; +1362;ETHIOPIC FULL STOP;Po;0;L;;;;;N;;;;; +1363;ETHIOPIC COMMA;Po;0;L;;;;;N;;;;; +1364;ETHIOPIC SEMICOLON;Po;0;L;;;;;N;;;;; +1365;ETHIOPIC COLON;Po;0;L;;;;;N;;;;; +1366;ETHIOPIC PREFACE COLON;Po;0;L;;;;;N;;;;; +1367;ETHIOPIC QUESTION MARK;Po;0;L;;;;;N;;;;; +1368;ETHIOPIC PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; +1369;ETHIOPIC DIGIT ONE;No;0;L;;;1;1;N;;;;; +136A;ETHIOPIC DIGIT TWO;No;0;L;;;2;2;N;;;;; +136B;ETHIOPIC DIGIT THREE;No;0;L;;;3;3;N;;;;; +136C;ETHIOPIC DIGIT FOUR;No;0;L;;;4;4;N;;;;; +136D;ETHIOPIC DIGIT FIVE;No;0;L;;;5;5;N;;;;; +136E;ETHIOPIC DIGIT SIX;No;0;L;;;6;6;N;;;;; +136F;ETHIOPIC DIGIT SEVEN;No;0;L;;;7;7;N;;;;; +1370;ETHIOPIC DIGIT EIGHT;No;0;L;;;8;8;N;;;;; +1371;ETHIOPIC DIGIT NINE;No;0;L;;;9;9;N;;;;; +1372;ETHIOPIC NUMBER TEN;No;0;L;;;;10;N;;;;; +1373;ETHIOPIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; +1374;ETHIOPIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; +1375;ETHIOPIC NUMBER FORTY;No;0;L;;;;40;N;;;;; +1376;ETHIOPIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; +1377;ETHIOPIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; +1378;ETHIOPIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +1379;ETHIOPIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +137A;ETHIOPIC NUMBER NINETY;No;0;L;;;;90;N;;;;; +137B;ETHIOPIC NUMBER HUNDRED;No;0;L;;;;100;N;;;;; +137C;ETHIOPIC NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; +1380;ETHIOPIC SYLLABLE SEBATBEIT MWA;Lo;0;L;;;;;N;;;;; +1381;ETHIOPIC SYLLABLE MWI;Lo;0;L;;;;;N;;;;; +1382;ETHIOPIC SYLLABLE MWEE;Lo;0;L;;;;;N;;;;; +1383;ETHIOPIC SYLLABLE MWE;Lo;0;L;;;;;N;;;;; +1384;ETHIOPIC SYLLABLE SEBATBEIT BWA;Lo;0;L;;;;;N;;;;; +1385;ETHIOPIC SYLLABLE BWI;Lo;0;L;;;;;N;;;;; +1386;ETHIOPIC SYLLABLE BWEE;Lo;0;L;;;;;N;;;;; +1387;ETHIOPIC SYLLABLE BWE;Lo;0;L;;;;;N;;;;; +1388;ETHIOPIC SYLLABLE SEBATBEIT FWA;Lo;0;L;;;;;N;;;;; +1389;ETHIOPIC SYLLABLE FWI;Lo;0;L;;;;;N;;;;; +138A;ETHIOPIC SYLLABLE FWEE;Lo;0;L;;;;;N;;;;; +138B;ETHIOPIC SYLLABLE FWE;Lo;0;L;;;;;N;;;;; +138C;ETHIOPIC SYLLABLE SEBATBEIT PWA;Lo;0;L;;;;;N;;;;; +138D;ETHIOPIC SYLLABLE PWI;Lo;0;L;;;;;N;;;;; +138E;ETHIOPIC SYLLABLE PWEE;Lo;0;L;;;;;N;;;;; +138F;ETHIOPIC SYLLABLE PWE;Lo;0;L;;;;;N;;;;; +1390;ETHIOPIC TONAL MARK YIZET;So;0;ON;;;;;N;;;;; +1391;ETHIOPIC TONAL MARK DERET;So;0;ON;;;;;N;;;;; +1392;ETHIOPIC TONAL MARK RIKRIK;So;0;ON;;;;;N;;;;; +1393;ETHIOPIC TONAL MARK SHORT RIKRIK;So;0;ON;;;;;N;;;;; +1394;ETHIOPIC TONAL MARK DIFAT;So;0;ON;;;;;N;;;;; +1395;ETHIOPIC TONAL MARK KENAT;So;0;ON;;;;;N;;;;; +1396;ETHIOPIC TONAL MARK CHIRET;So;0;ON;;;;;N;;;;; +1397;ETHIOPIC TONAL MARK HIDET;So;0;ON;;;;;N;;;;; +1398;ETHIOPIC TONAL MARK DERET-HIDET;So;0;ON;;;;;N;;;;; +1399;ETHIOPIC TONAL MARK KURT;So;0;ON;;;;;N;;;;; +13A0;CHEROKEE LETTER A;Lu;0;L;;;;;N;;;;AB70; +13A1;CHEROKEE LETTER E;Lu;0;L;;;;;N;;;;AB71; +13A2;CHEROKEE LETTER I;Lu;0;L;;;;;N;;;;AB72; +13A3;CHEROKEE LETTER O;Lu;0;L;;;;;N;;;;AB73; +13A4;CHEROKEE LETTER U;Lu;0;L;;;;;N;;;;AB74; +13A5;CHEROKEE LETTER V;Lu;0;L;;;;;N;;;;AB75; +13A6;CHEROKEE LETTER GA;Lu;0;L;;;;;N;;;;AB76; +13A7;CHEROKEE LETTER KA;Lu;0;L;;;;;N;;;;AB77; +13A8;CHEROKEE LETTER GE;Lu;0;L;;;;;N;;;;AB78; +13A9;CHEROKEE LETTER GI;Lu;0;L;;;;;N;;;;AB79; +13AA;CHEROKEE LETTER GO;Lu;0;L;;;;;N;;;;AB7A; +13AB;CHEROKEE LETTER GU;Lu;0;L;;;;;N;;;;AB7B; +13AC;CHEROKEE LETTER GV;Lu;0;L;;;;;N;;;;AB7C; +13AD;CHEROKEE LETTER HA;Lu;0;L;;;;;N;;;;AB7D; +13AE;CHEROKEE LETTER HE;Lu;0;L;;;;;N;;;;AB7E; +13AF;CHEROKEE LETTER HI;Lu;0;L;;;;;N;;;;AB7F; +13B0;CHEROKEE LETTER HO;Lu;0;L;;;;;N;;;;AB80; +13B1;CHEROKEE LETTER HU;Lu;0;L;;;;;N;;;;AB81; +13B2;CHEROKEE LETTER HV;Lu;0;L;;;;;N;;;;AB82; +13B3;CHEROKEE LETTER LA;Lu;0;L;;;;;N;;;;AB83; +13B4;CHEROKEE LETTER LE;Lu;0;L;;;;;N;;;;AB84; +13B5;CHEROKEE LETTER LI;Lu;0;L;;;;;N;;;;AB85; +13B6;CHEROKEE LETTER LO;Lu;0;L;;;;;N;;;;AB86; +13B7;CHEROKEE LETTER LU;Lu;0;L;;;;;N;;;;AB87; +13B8;CHEROKEE LETTER LV;Lu;0;L;;;;;N;;;;AB88; +13B9;CHEROKEE LETTER MA;Lu;0;L;;;;;N;;;;AB89; +13BA;CHEROKEE LETTER ME;Lu;0;L;;;;;N;;;;AB8A; +13BB;CHEROKEE LETTER MI;Lu;0;L;;;;;N;;;;AB8B; +13BC;CHEROKEE LETTER MO;Lu;0;L;;;;;N;;;;AB8C; +13BD;CHEROKEE LETTER MU;Lu;0;L;;;;;N;;;;AB8D; +13BE;CHEROKEE LETTER NA;Lu;0;L;;;;;N;;;;AB8E; +13BF;CHEROKEE LETTER HNA;Lu;0;L;;;;;N;;;;AB8F; +13C0;CHEROKEE LETTER NAH;Lu;0;L;;;;;N;;;;AB90; +13C1;CHEROKEE LETTER NE;Lu;0;L;;;;;N;;;;AB91; +13C2;CHEROKEE LETTER NI;Lu;0;L;;;;;N;;;;AB92; +13C3;CHEROKEE LETTER NO;Lu;0;L;;;;;N;;;;AB93; +13C4;CHEROKEE LETTER NU;Lu;0;L;;;;;N;;;;AB94; +13C5;CHEROKEE LETTER NV;Lu;0;L;;;;;N;;;;AB95; +13C6;CHEROKEE LETTER QUA;Lu;0;L;;;;;N;;;;AB96; +13C7;CHEROKEE LETTER QUE;Lu;0;L;;;;;N;;;;AB97; +13C8;CHEROKEE LETTER QUI;Lu;0;L;;;;;N;;;;AB98; +13C9;CHEROKEE LETTER QUO;Lu;0;L;;;;;N;;;;AB99; +13CA;CHEROKEE LETTER QUU;Lu;0;L;;;;;N;;;;AB9A; +13CB;CHEROKEE LETTER QUV;Lu;0;L;;;;;N;;;;AB9B; +13CC;CHEROKEE LETTER SA;Lu;0;L;;;;;N;;;;AB9C; +13CD;CHEROKEE LETTER S;Lu;0;L;;;;;N;;;;AB9D; +13CE;CHEROKEE LETTER SE;Lu;0;L;;;;;N;;;;AB9E; +13CF;CHEROKEE LETTER SI;Lu;0;L;;;;;N;;;;AB9F; +13D0;CHEROKEE LETTER SO;Lu;0;L;;;;;N;;;;ABA0; +13D1;CHEROKEE LETTER SU;Lu;0;L;;;;;N;;;;ABA1; +13D2;CHEROKEE LETTER SV;Lu;0;L;;;;;N;;;;ABA2; +13D3;CHEROKEE LETTER DA;Lu;0;L;;;;;N;;;;ABA3; +13D4;CHEROKEE LETTER TA;Lu;0;L;;;;;N;;;;ABA4; +13D5;CHEROKEE LETTER DE;Lu;0;L;;;;;N;;;;ABA5; +13D6;CHEROKEE LETTER TE;Lu;0;L;;;;;N;;;;ABA6; +13D7;CHEROKEE LETTER DI;Lu;0;L;;;;;N;;;;ABA7; +13D8;CHEROKEE LETTER TI;Lu;0;L;;;;;N;;;;ABA8; +13D9;CHEROKEE LETTER DO;Lu;0;L;;;;;N;;;;ABA9; +13DA;CHEROKEE LETTER DU;Lu;0;L;;;;;N;;;;ABAA; +13DB;CHEROKEE LETTER DV;Lu;0;L;;;;;N;;;;ABAB; +13DC;CHEROKEE LETTER DLA;Lu;0;L;;;;;N;;;;ABAC; +13DD;CHEROKEE LETTER TLA;Lu;0;L;;;;;N;;;;ABAD; +13DE;CHEROKEE LETTER TLE;Lu;0;L;;;;;N;;;;ABAE; +13DF;CHEROKEE LETTER TLI;Lu;0;L;;;;;N;;;;ABAF; +13E0;CHEROKEE LETTER TLO;Lu;0;L;;;;;N;;;;ABB0; +13E1;CHEROKEE LETTER TLU;Lu;0;L;;;;;N;;;;ABB1; +13E2;CHEROKEE LETTER TLV;Lu;0;L;;;;;N;;;;ABB2; +13E3;CHEROKEE LETTER TSA;Lu;0;L;;;;;N;;;;ABB3; +13E4;CHEROKEE LETTER TSE;Lu;0;L;;;;;N;;;;ABB4; +13E5;CHEROKEE LETTER TSI;Lu;0;L;;;;;N;;;;ABB5; +13E6;CHEROKEE LETTER TSO;Lu;0;L;;;;;N;;;;ABB6; +13E7;CHEROKEE LETTER TSU;Lu;0;L;;;;;N;;;;ABB7; +13E8;CHEROKEE LETTER TSV;Lu;0;L;;;;;N;;;;ABB8; +13E9;CHEROKEE LETTER WA;Lu;0;L;;;;;N;;;;ABB9; +13EA;CHEROKEE LETTER WE;Lu;0;L;;;;;N;;;;ABBA; +13EB;CHEROKEE LETTER WI;Lu;0;L;;;;;N;;;;ABBB; +13EC;CHEROKEE LETTER WO;Lu;0;L;;;;;N;;;;ABBC; +13ED;CHEROKEE LETTER WU;Lu;0;L;;;;;N;;;;ABBD; +13EE;CHEROKEE LETTER WV;Lu;0;L;;;;;N;;;;ABBE; +13EF;CHEROKEE LETTER YA;Lu;0;L;;;;;N;;;;ABBF; +13F0;CHEROKEE LETTER YE;Lu;0;L;;;;;N;;;;13F8; +13F1;CHEROKEE LETTER YI;Lu;0;L;;;;;N;;;;13F9; +13F2;CHEROKEE LETTER YO;Lu;0;L;;;;;N;;;;13FA; +13F3;CHEROKEE LETTER YU;Lu;0;L;;;;;N;;;;13FB; +13F4;CHEROKEE LETTER YV;Lu;0;L;;;;;N;;;;13FC; +13F5;CHEROKEE LETTER MV;Lu;0;L;;;;;N;;;;13FD; +13F8;CHEROKEE SMALL LETTER YE;Ll;0;L;;;;;N;;;13F0;;13F0 +13F9;CHEROKEE SMALL LETTER YI;Ll;0;L;;;;;N;;;13F1;;13F1 +13FA;CHEROKEE SMALL LETTER YO;Ll;0;L;;;;;N;;;13F2;;13F2 +13FB;CHEROKEE SMALL LETTER YU;Ll;0;L;;;;;N;;;13F3;;13F3 +13FC;CHEROKEE SMALL LETTER YV;Ll;0;L;;;;;N;;;13F4;;13F4 +13FD;CHEROKEE SMALL LETTER MV;Ll;0;L;;;;;N;;;13F5;;13F5 +1400;CANADIAN SYLLABICS HYPHEN;Pd;0;ON;;;;;N;;;;; +1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;; +1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;; +1403;CANADIAN SYLLABICS I;Lo;0;L;;;;;N;;;;; +1404;CANADIAN SYLLABICS II;Lo;0;L;;;;;N;;;;; +1405;CANADIAN SYLLABICS O;Lo;0;L;;;;;N;;;;; +1406;CANADIAN SYLLABICS OO;Lo;0;L;;;;;N;;;;; +1407;CANADIAN SYLLABICS Y-CREE OO;Lo;0;L;;;;;N;;;;; +1408;CANADIAN SYLLABICS CARRIER EE;Lo;0;L;;;;;N;;;;; +1409;CANADIAN SYLLABICS CARRIER I;Lo;0;L;;;;;N;;;;; +140A;CANADIAN SYLLABICS A;Lo;0;L;;;;;N;;;;; +140B;CANADIAN SYLLABICS AA;Lo;0;L;;;;;N;;;;; +140C;CANADIAN SYLLABICS WE;Lo;0;L;;;;;N;;;;; +140D;CANADIAN SYLLABICS WEST-CREE WE;Lo;0;L;;;;;N;;;;; +140E;CANADIAN SYLLABICS WI;Lo;0;L;;;;;N;;;;; +140F;CANADIAN SYLLABICS WEST-CREE WI;Lo;0;L;;;;;N;;;;; +1410;CANADIAN SYLLABICS WII;Lo;0;L;;;;;N;;;;; +1411;CANADIAN SYLLABICS WEST-CREE WII;Lo;0;L;;;;;N;;;;; +1412;CANADIAN SYLLABICS WO;Lo;0;L;;;;;N;;;;; +1413;CANADIAN SYLLABICS WEST-CREE WO;Lo;0;L;;;;;N;;;;; +1414;CANADIAN SYLLABICS WOO;Lo;0;L;;;;;N;;;;; +1415;CANADIAN SYLLABICS WEST-CREE WOO;Lo;0;L;;;;;N;;;;; +1416;CANADIAN SYLLABICS NASKAPI WOO;Lo;0;L;;;;;N;;;;; +1417;CANADIAN SYLLABICS WA;Lo;0;L;;;;;N;;;;; +1418;CANADIAN SYLLABICS WEST-CREE WA;Lo;0;L;;;;;N;;;;; +1419;CANADIAN SYLLABICS WAA;Lo;0;L;;;;;N;;;;; +141A;CANADIAN SYLLABICS WEST-CREE WAA;Lo;0;L;;;;;N;;;;; +141B;CANADIAN SYLLABICS NASKAPI WAA;Lo;0;L;;;;;N;;;;; +141C;CANADIAN SYLLABICS AI;Lo;0;L;;;;;N;;;;; +141D;CANADIAN SYLLABICS Y-CREE W;Lo;0;L;;;;;N;;;;; +141E;CANADIAN SYLLABICS GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +141F;CANADIAN SYLLABICS FINAL ACUTE;Lo;0;L;;;;;N;;;;; +1420;CANADIAN SYLLABICS FINAL GRAVE;Lo;0;L;;;;;N;;;;; +1421;CANADIAN SYLLABICS FINAL BOTTOM HALF RING;Lo;0;L;;;;;N;;;;; +1422;CANADIAN SYLLABICS FINAL TOP HALF RING;Lo;0;L;;;;;N;;;;; +1423;CANADIAN SYLLABICS FINAL RIGHT HALF RING;Lo;0;L;;;;;N;;;;; +1424;CANADIAN SYLLABICS FINAL RING;Lo;0;L;;;;;N;;;;; +1425;CANADIAN SYLLABICS FINAL DOUBLE ACUTE;Lo;0;L;;;;;N;;;;; +1426;CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES;Lo;0;L;;;;;N;;;;; +1427;CANADIAN SYLLABICS FINAL MIDDLE DOT;Lo;0;L;;;;;N;;;;; +1428;CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE;Lo;0;L;;;;;N;;;;; +1429;CANADIAN SYLLABICS FINAL PLUS;Lo;0;L;;;;;N;;;;; +142A;CANADIAN SYLLABICS FINAL DOWN TACK;Lo;0;L;;;;;N;;;;; +142B;CANADIAN SYLLABICS EN;Lo;0;L;;;;;N;;;;; +142C;CANADIAN SYLLABICS IN;Lo;0;L;;;;;N;;;;; +142D;CANADIAN SYLLABICS ON;Lo;0;L;;;;;N;;;;; +142E;CANADIAN SYLLABICS AN;Lo;0;L;;;;;N;;;;; +142F;CANADIAN SYLLABICS PE;Lo;0;L;;;;;N;;;;; +1430;CANADIAN SYLLABICS PAAI;Lo;0;L;;;;;N;;;;; +1431;CANADIAN SYLLABICS PI;Lo;0;L;;;;;N;;;;; +1432;CANADIAN SYLLABICS PII;Lo;0;L;;;;;N;;;;; +1433;CANADIAN SYLLABICS PO;Lo;0;L;;;;;N;;;;; +1434;CANADIAN SYLLABICS POO;Lo;0;L;;;;;N;;;;; +1435;CANADIAN SYLLABICS Y-CREE POO;Lo;0;L;;;;;N;;;;; +1436;CANADIAN SYLLABICS CARRIER HEE;Lo;0;L;;;;;N;;;;; +1437;CANADIAN SYLLABICS CARRIER HI;Lo;0;L;;;;;N;;;;; +1438;CANADIAN SYLLABICS PA;Lo;0;L;;;;;N;;;;; +1439;CANADIAN SYLLABICS PAA;Lo;0;L;;;;;N;;;;; +143A;CANADIAN SYLLABICS PWE;Lo;0;L;;;;;N;;;;; +143B;CANADIAN SYLLABICS WEST-CREE PWE;Lo;0;L;;;;;N;;;;; +143C;CANADIAN SYLLABICS PWI;Lo;0;L;;;;;N;;;;; +143D;CANADIAN SYLLABICS WEST-CREE PWI;Lo;0;L;;;;;N;;;;; +143E;CANADIAN SYLLABICS PWII;Lo;0;L;;;;;N;;;;; +143F;CANADIAN SYLLABICS WEST-CREE PWII;Lo;0;L;;;;;N;;;;; +1440;CANADIAN SYLLABICS PWO;Lo;0;L;;;;;N;;;;; +1441;CANADIAN SYLLABICS WEST-CREE PWO;Lo;0;L;;;;;N;;;;; +1442;CANADIAN SYLLABICS PWOO;Lo;0;L;;;;;N;;;;; +1443;CANADIAN SYLLABICS WEST-CREE PWOO;Lo;0;L;;;;;N;;;;; +1444;CANADIAN SYLLABICS PWA;Lo;0;L;;;;;N;;;;; +1445;CANADIAN SYLLABICS WEST-CREE PWA;Lo;0;L;;;;;N;;;;; +1446;CANADIAN SYLLABICS PWAA;Lo;0;L;;;;;N;;;;; +1447;CANADIAN SYLLABICS WEST-CREE PWAA;Lo;0;L;;;;;N;;;;; +1448;CANADIAN SYLLABICS Y-CREE PWAA;Lo;0;L;;;;;N;;;;; +1449;CANADIAN SYLLABICS P;Lo;0;L;;;;;N;;;;; +144A;CANADIAN SYLLABICS WEST-CREE P;Lo;0;L;;;;;N;;;;; +144B;CANADIAN SYLLABICS CARRIER H;Lo;0;L;;;;;N;;;;; +144C;CANADIAN SYLLABICS TE;Lo;0;L;;;;;N;;;;; +144D;CANADIAN SYLLABICS TAAI;Lo;0;L;;;;;N;;;;; +144E;CANADIAN SYLLABICS TI;Lo;0;L;;;;;N;;;;; +144F;CANADIAN SYLLABICS TII;Lo;0;L;;;;;N;;;;; +1450;CANADIAN SYLLABICS TO;Lo;0;L;;;;;N;;;;; +1451;CANADIAN SYLLABICS TOO;Lo;0;L;;;;;N;;;;; +1452;CANADIAN SYLLABICS Y-CREE TOO;Lo;0;L;;;;;N;;;;; +1453;CANADIAN SYLLABICS CARRIER DEE;Lo;0;L;;;;;N;;;;; +1454;CANADIAN SYLLABICS CARRIER DI;Lo;0;L;;;;;N;;;;; +1455;CANADIAN SYLLABICS TA;Lo;0;L;;;;;N;;;;; +1456;CANADIAN SYLLABICS TAA;Lo;0;L;;;;;N;;;;; +1457;CANADIAN SYLLABICS TWE;Lo;0;L;;;;;N;;;;; +1458;CANADIAN SYLLABICS WEST-CREE TWE;Lo;0;L;;;;;N;;;;; +1459;CANADIAN SYLLABICS TWI;Lo;0;L;;;;;N;;;;; +145A;CANADIAN SYLLABICS WEST-CREE TWI;Lo;0;L;;;;;N;;;;; +145B;CANADIAN SYLLABICS TWII;Lo;0;L;;;;;N;;;;; +145C;CANADIAN SYLLABICS WEST-CREE TWII;Lo;0;L;;;;;N;;;;; +145D;CANADIAN SYLLABICS TWO;Lo;0;L;;;;;N;;;;; +145E;CANADIAN SYLLABICS WEST-CREE TWO;Lo;0;L;;;;;N;;;;; +145F;CANADIAN SYLLABICS TWOO;Lo;0;L;;;;;N;;;;; +1460;CANADIAN SYLLABICS WEST-CREE TWOO;Lo;0;L;;;;;N;;;;; +1461;CANADIAN SYLLABICS TWA;Lo;0;L;;;;;N;;;;; +1462;CANADIAN SYLLABICS WEST-CREE TWA;Lo;0;L;;;;;N;;;;; +1463;CANADIAN SYLLABICS TWAA;Lo;0;L;;;;;N;;;;; +1464;CANADIAN SYLLABICS WEST-CREE TWAA;Lo;0;L;;;;;N;;;;; +1465;CANADIAN SYLLABICS NASKAPI TWAA;Lo;0;L;;;;;N;;;;; +1466;CANADIAN SYLLABICS T;Lo;0;L;;;;;N;;;;; +1467;CANADIAN SYLLABICS TTE;Lo;0;L;;;;;N;;;;; +1468;CANADIAN SYLLABICS TTI;Lo;0;L;;;;;N;;;;; +1469;CANADIAN SYLLABICS TTO;Lo;0;L;;;;;N;;;;; +146A;CANADIAN SYLLABICS TTA;Lo;0;L;;;;;N;;;;; +146B;CANADIAN SYLLABICS KE;Lo;0;L;;;;;N;;;;; +146C;CANADIAN SYLLABICS KAAI;Lo;0;L;;;;;N;;;;; +146D;CANADIAN SYLLABICS KI;Lo;0;L;;;;;N;;;;; +146E;CANADIAN SYLLABICS KII;Lo;0;L;;;;;N;;;;; +146F;CANADIAN SYLLABICS KO;Lo;0;L;;;;;N;;;;; +1470;CANADIAN SYLLABICS KOO;Lo;0;L;;;;;N;;;;; +1471;CANADIAN SYLLABICS Y-CREE KOO;Lo;0;L;;;;;N;;;;; +1472;CANADIAN SYLLABICS KA;Lo;0;L;;;;;N;;;;; +1473;CANADIAN SYLLABICS KAA;Lo;0;L;;;;;N;;;;; +1474;CANADIAN SYLLABICS KWE;Lo;0;L;;;;;N;;;;; +1475;CANADIAN SYLLABICS WEST-CREE KWE;Lo;0;L;;;;;N;;;;; +1476;CANADIAN SYLLABICS KWI;Lo;0;L;;;;;N;;;;; +1477;CANADIAN SYLLABICS WEST-CREE KWI;Lo;0;L;;;;;N;;;;; +1478;CANADIAN SYLLABICS KWII;Lo;0;L;;;;;N;;;;; +1479;CANADIAN SYLLABICS WEST-CREE KWII;Lo;0;L;;;;;N;;;;; +147A;CANADIAN SYLLABICS KWO;Lo;0;L;;;;;N;;;;; +147B;CANADIAN SYLLABICS WEST-CREE KWO;Lo;0;L;;;;;N;;;;; +147C;CANADIAN SYLLABICS KWOO;Lo;0;L;;;;;N;;;;; +147D;CANADIAN SYLLABICS WEST-CREE KWOO;Lo;0;L;;;;;N;;;;; +147E;CANADIAN SYLLABICS KWA;Lo;0;L;;;;;N;;;;; +147F;CANADIAN SYLLABICS WEST-CREE KWA;Lo;0;L;;;;;N;;;;; +1480;CANADIAN SYLLABICS KWAA;Lo;0;L;;;;;N;;;;; +1481;CANADIAN SYLLABICS WEST-CREE KWAA;Lo;0;L;;;;;N;;;;; +1482;CANADIAN SYLLABICS NASKAPI KWAA;Lo;0;L;;;;;N;;;;; +1483;CANADIAN SYLLABICS K;Lo;0;L;;;;;N;;;;; +1484;CANADIAN SYLLABICS KW;Lo;0;L;;;;;N;;;;; +1485;CANADIAN SYLLABICS SOUTH-SLAVEY KEH;Lo;0;L;;;;;N;;;;; +1486;CANADIAN SYLLABICS SOUTH-SLAVEY KIH;Lo;0;L;;;;;N;;;;; +1487;CANADIAN SYLLABICS SOUTH-SLAVEY KOH;Lo;0;L;;;;;N;;;;; +1488;CANADIAN SYLLABICS SOUTH-SLAVEY KAH;Lo;0;L;;;;;N;;;;; +1489;CANADIAN SYLLABICS CE;Lo;0;L;;;;;N;;;;; +148A;CANADIAN SYLLABICS CAAI;Lo;0;L;;;;;N;;;;; +148B;CANADIAN SYLLABICS CI;Lo;0;L;;;;;N;;;;; +148C;CANADIAN SYLLABICS CII;Lo;0;L;;;;;N;;;;; +148D;CANADIAN SYLLABICS CO;Lo;0;L;;;;;N;;;;; +148E;CANADIAN SYLLABICS COO;Lo;0;L;;;;;N;;;;; +148F;CANADIAN SYLLABICS Y-CREE COO;Lo;0;L;;;;;N;;;;; +1490;CANADIAN SYLLABICS CA;Lo;0;L;;;;;N;;;;; +1491;CANADIAN SYLLABICS CAA;Lo;0;L;;;;;N;;;;; +1492;CANADIAN SYLLABICS CWE;Lo;0;L;;;;;N;;;;; +1493;CANADIAN SYLLABICS WEST-CREE CWE;Lo;0;L;;;;;N;;;;; +1494;CANADIAN SYLLABICS CWI;Lo;0;L;;;;;N;;;;; +1495;CANADIAN SYLLABICS WEST-CREE CWI;Lo;0;L;;;;;N;;;;; +1496;CANADIAN SYLLABICS CWII;Lo;0;L;;;;;N;;;;; +1497;CANADIAN SYLLABICS WEST-CREE CWII;Lo;0;L;;;;;N;;;;; +1498;CANADIAN SYLLABICS CWO;Lo;0;L;;;;;N;;;;; +1499;CANADIAN SYLLABICS WEST-CREE CWO;Lo;0;L;;;;;N;;;;; +149A;CANADIAN SYLLABICS CWOO;Lo;0;L;;;;;N;;;;; +149B;CANADIAN SYLLABICS WEST-CREE CWOO;Lo;0;L;;;;;N;;;;; +149C;CANADIAN SYLLABICS CWA;Lo;0;L;;;;;N;;;;; +149D;CANADIAN SYLLABICS WEST-CREE CWA;Lo;0;L;;;;;N;;;;; +149E;CANADIAN SYLLABICS CWAA;Lo;0;L;;;;;N;;;;; +149F;CANADIAN SYLLABICS WEST-CREE CWAA;Lo;0;L;;;;;N;;;;; +14A0;CANADIAN SYLLABICS NASKAPI CWAA;Lo;0;L;;;;;N;;;;; +14A1;CANADIAN SYLLABICS C;Lo;0;L;;;;;N;;;;; +14A2;CANADIAN SYLLABICS SAYISI TH;Lo;0;L;;;;;N;;;;; +14A3;CANADIAN SYLLABICS ME;Lo;0;L;;;;;N;;;;; +14A4;CANADIAN SYLLABICS MAAI;Lo;0;L;;;;;N;;;;; +14A5;CANADIAN SYLLABICS MI;Lo;0;L;;;;;N;;;;; +14A6;CANADIAN SYLLABICS MII;Lo;0;L;;;;;N;;;;; +14A7;CANADIAN SYLLABICS MO;Lo;0;L;;;;;N;;;;; +14A8;CANADIAN SYLLABICS MOO;Lo;0;L;;;;;N;;;;; +14A9;CANADIAN SYLLABICS Y-CREE MOO;Lo;0;L;;;;;N;;;;; +14AA;CANADIAN SYLLABICS MA;Lo;0;L;;;;;N;;;;; +14AB;CANADIAN SYLLABICS MAA;Lo;0;L;;;;;N;;;;; +14AC;CANADIAN SYLLABICS MWE;Lo;0;L;;;;;N;;;;; +14AD;CANADIAN SYLLABICS WEST-CREE MWE;Lo;0;L;;;;;N;;;;; +14AE;CANADIAN SYLLABICS MWI;Lo;0;L;;;;;N;;;;; +14AF;CANADIAN SYLLABICS WEST-CREE MWI;Lo;0;L;;;;;N;;;;; +14B0;CANADIAN SYLLABICS MWII;Lo;0;L;;;;;N;;;;; +14B1;CANADIAN SYLLABICS WEST-CREE MWII;Lo;0;L;;;;;N;;;;; +14B2;CANADIAN SYLLABICS MWO;Lo;0;L;;;;;N;;;;; +14B3;CANADIAN SYLLABICS WEST-CREE MWO;Lo;0;L;;;;;N;;;;; +14B4;CANADIAN SYLLABICS MWOO;Lo;0;L;;;;;N;;;;; +14B5;CANADIAN SYLLABICS WEST-CREE MWOO;Lo;0;L;;;;;N;;;;; +14B6;CANADIAN SYLLABICS MWA;Lo;0;L;;;;;N;;;;; +14B7;CANADIAN SYLLABICS WEST-CREE MWA;Lo;0;L;;;;;N;;;;; +14B8;CANADIAN SYLLABICS MWAA;Lo;0;L;;;;;N;;;;; +14B9;CANADIAN SYLLABICS WEST-CREE MWAA;Lo;0;L;;;;;N;;;;; +14BA;CANADIAN SYLLABICS NASKAPI MWAA;Lo;0;L;;;;;N;;;;; +14BB;CANADIAN SYLLABICS M;Lo;0;L;;;;;N;;;;; +14BC;CANADIAN SYLLABICS WEST-CREE M;Lo;0;L;;;;;N;;;;; +14BD;CANADIAN SYLLABICS MH;Lo;0;L;;;;;N;;;;; +14BE;CANADIAN SYLLABICS ATHAPASCAN M;Lo;0;L;;;;;N;;;;; +14BF;CANADIAN SYLLABICS SAYISI M;Lo;0;L;;;;;N;;;;; +14C0;CANADIAN SYLLABICS NE;Lo;0;L;;;;;N;;;;; +14C1;CANADIAN SYLLABICS NAAI;Lo;0;L;;;;;N;;;;; +14C2;CANADIAN SYLLABICS NI;Lo;0;L;;;;;N;;;;; +14C3;CANADIAN SYLLABICS NII;Lo;0;L;;;;;N;;;;; +14C4;CANADIAN SYLLABICS NO;Lo;0;L;;;;;N;;;;; +14C5;CANADIAN SYLLABICS NOO;Lo;0;L;;;;;N;;;;; +14C6;CANADIAN SYLLABICS Y-CREE NOO;Lo;0;L;;;;;N;;;;; +14C7;CANADIAN SYLLABICS NA;Lo;0;L;;;;;N;;;;; +14C8;CANADIAN SYLLABICS NAA;Lo;0;L;;;;;N;;;;; +14C9;CANADIAN SYLLABICS NWE;Lo;0;L;;;;;N;;;;; +14CA;CANADIAN SYLLABICS WEST-CREE NWE;Lo;0;L;;;;;N;;;;; +14CB;CANADIAN SYLLABICS NWA;Lo;0;L;;;;;N;;;;; +14CC;CANADIAN SYLLABICS WEST-CREE NWA;Lo;0;L;;;;;N;;;;; +14CD;CANADIAN SYLLABICS NWAA;Lo;0;L;;;;;N;;;;; +14CE;CANADIAN SYLLABICS WEST-CREE NWAA;Lo;0;L;;;;;N;;;;; +14CF;CANADIAN SYLLABICS NASKAPI NWAA;Lo;0;L;;;;;N;;;;; +14D0;CANADIAN SYLLABICS N;Lo;0;L;;;;;N;;;;; +14D1;CANADIAN SYLLABICS CARRIER NG;Lo;0;L;;;;;N;;;;; +14D2;CANADIAN SYLLABICS NH;Lo;0;L;;;;;N;;;;; +14D3;CANADIAN SYLLABICS LE;Lo;0;L;;;;;N;;;;; +14D4;CANADIAN SYLLABICS LAAI;Lo;0;L;;;;;N;;;;; +14D5;CANADIAN SYLLABICS LI;Lo;0;L;;;;;N;;;;; +14D6;CANADIAN SYLLABICS LII;Lo;0;L;;;;;N;;;;; +14D7;CANADIAN SYLLABICS LO;Lo;0;L;;;;;N;;;;; +14D8;CANADIAN SYLLABICS LOO;Lo;0;L;;;;;N;;;;; +14D9;CANADIAN SYLLABICS Y-CREE LOO;Lo;0;L;;;;;N;;;;; +14DA;CANADIAN SYLLABICS LA;Lo;0;L;;;;;N;;;;; +14DB;CANADIAN SYLLABICS LAA;Lo;0;L;;;;;N;;;;; +14DC;CANADIAN SYLLABICS LWE;Lo;0;L;;;;;N;;;;; +14DD;CANADIAN SYLLABICS WEST-CREE LWE;Lo;0;L;;;;;N;;;;; +14DE;CANADIAN SYLLABICS LWI;Lo;0;L;;;;;N;;;;; +14DF;CANADIAN SYLLABICS WEST-CREE LWI;Lo;0;L;;;;;N;;;;; +14E0;CANADIAN SYLLABICS LWII;Lo;0;L;;;;;N;;;;; +14E1;CANADIAN SYLLABICS WEST-CREE LWII;Lo;0;L;;;;;N;;;;; +14E2;CANADIAN SYLLABICS LWO;Lo;0;L;;;;;N;;;;; +14E3;CANADIAN SYLLABICS WEST-CREE LWO;Lo;0;L;;;;;N;;;;; +14E4;CANADIAN SYLLABICS LWOO;Lo;0;L;;;;;N;;;;; +14E5;CANADIAN SYLLABICS WEST-CREE LWOO;Lo;0;L;;;;;N;;;;; +14E6;CANADIAN SYLLABICS LWA;Lo;0;L;;;;;N;;;;; +14E7;CANADIAN SYLLABICS WEST-CREE LWA;Lo;0;L;;;;;N;;;;; +14E8;CANADIAN SYLLABICS LWAA;Lo;0;L;;;;;N;;;;; +14E9;CANADIAN SYLLABICS WEST-CREE LWAA;Lo;0;L;;;;;N;;;;; +14EA;CANADIAN SYLLABICS L;Lo;0;L;;;;;N;;;;; +14EB;CANADIAN SYLLABICS WEST-CREE L;Lo;0;L;;;;;N;;;;; +14EC;CANADIAN SYLLABICS MEDIAL L;Lo;0;L;;;;;N;;;;; +14ED;CANADIAN SYLLABICS SE;Lo;0;L;;;;;N;;;;; +14EE;CANADIAN SYLLABICS SAAI;Lo;0;L;;;;;N;;;;; +14EF;CANADIAN SYLLABICS SI;Lo;0;L;;;;;N;;;;; +14F0;CANADIAN SYLLABICS SII;Lo;0;L;;;;;N;;;;; +14F1;CANADIAN SYLLABICS SO;Lo;0;L;;;;;N;;;;; +14F2;CANADIAN SYLLABICS SOO;Lo;0;L;;;;;N;;;;; +14F3;CANADIAN SYLLABICS Y-CREE SOO;Lo;0;L;;;;;N;;;;; +14F4;CANADIAN SYLLABICS SA;Lo;0;L;;;;;N;;;;; +14F5;CANADIAN SYLLABICS SAA;Lo;0;L;;;;;N;;;;; +14F6;CANADIAN SYLLABICS SWE;Lo;0;L;;;;;N;;;;; +14F7;CANADIAN SYLLABICS WEST-CREE SWE;Lo;0;L;;;;;N;;;;; +14F8;CANADIAN SYLLABICS SWI;Lo;0;L;;;;;N;;;;; +14F9;CANADIAN SYLLABICS WEST-CREE SWI;Lo;0;L;;;;;N;;;;; +14FA;CANADIAN SYLLABICS SWII;Lo;0;L;;;;;N;;;;; +14FB;CANADIAN SYLLABICS WEST-CREE SWII;Lo;0;L;;;;;N;;;;; +14FC;CANADIAN SYLLABICS SWO;Lo;0;L;;;;;N;;;;; +14FD;CANADIAN SYLLABICS WEST-CREE SWO;Lo;0;L;;;;;N;;;;; +14FE;CANADIAN SYLLABICS SWOO;Lo;0;L;;;;;N;;;;; +14FF;CANADIAN SYLLABICS WEST-CREE SWOO;Lo;0;L;;;;;N;;;;; +1500;CANADIAN SYLLABICS SWA;Lo;0;L;;;;;N;;;;; +1501;CANADIAN SYLLABICS WEST-CREE SWA;Lo;0;L;;;;;N;;;;; +1502;CANADIAN SYLLABICS SWAA;Lo;0;L;;;;;N;;;;; +1503;CANADIAN SYLLABICS WEST-CREE SWAA;Lo;0;L;;;;;N;;;;; +1504;CANADIAN SYLLABICS NASKAPI SWAA;Lo;0;L;;;;;N;;;;; +1505;CANADIAN SYLLABICS S;Lo;0;L;;;;;N;;;;; +1506;CANADIAN SYLLABICS ATHAPASCAN S;Lo;0;L;;;;;N;;;;; +1507;CANADIAN SYLLABICS SW;Lo;0;L;;;;;N;;;;; +1508;CANADIAN SYLLABICS BLACKFOOT S;Lo;0;L;;;;;N;;;;; +1509;CANADIAN SYLLABICS MOOSE-CREE SK;Lo;0;L;;;;;N;;;;; +150A;CANADIAN SYLLABICS NASKAPI SKW;Lo;0;L;;;;;N;;;;; +150B;CANADIAN SYLLABICS NASKAPI S-W;Lo;0;L;;;;;N;;;;; +150C;CANADIAN SYLLABICS NASKAPI SPWA;Lo;0;L;;;;;N;;;;; +150D;CANADIAN SYLLABICS NASKAPI STWA;Lo;0;L;;;;;N;;;;; +150E;CANADIAN SYLLABICS NASKAPI SKWA;Lo;0;L;;;;;N;;;;; +150F;CANADIAN SYLLABICS NASKAPI SCWA;Lo;0;L;;;;;N;;;;; +1510;CANADIAN SYLLABICS SHE;Lo;0;L;;;;;N;;;;; +1511;CANADIAN SYLLABICS SHI;Lo;0;L;;;;;N;;;;; +1512;CANADIAN SYLLABICS SHII;Lo;0;L;;;;;N;;;;; +1513;CANADIAN SYLLABICS SHO;Lo;0;L;;;;;N;;;;; +1514;CANADIAN SYLLABICS SHOO;Lo;0;L;;;;;N;;;;; +1515;CANADIAN SYLLABICS SHA;Lo;0;L;;;;;N;;;;; +1516;CANADIAN SYLLABICS SHAA;Lo;0;L;;;;;N;;;;; +1517;CANADIAN SYLLABICS SHWE;Lo;0;L;;;;;N;;;;; +1518;CANADIAN SYLLABICS WEST-CREE SHWE;Lo;0;L;;;;;N;;;;; +1519;CANADIAN SYLLABICS SHWI;Lo;0;L;;;;;N;;;;; +151A;CANADIAN SYLLABICS WEST-CREE SHWI;Lo;0;L;;;;;N;;;;; +151B;CANADIAN SYLLABICS SHWII;Lo;0;L;;;;;N;;;;; +151C;CANADIAN SYLLABICS WEST-CREE SHWII;Lo;0;L;;;;;N;;;;; +151D;CANADIAN SYLLABICS SHWO;Lo;0;L;;;;;N;;;;; +151E;CANADIAN SYLLABICS WEST-CREE SHWO;Lo;0;L;;;;;N;;;;; +151F;CANADIAN SYLLABICS SHWOO;Lo;0;L;;;;;N;;;;; +1520;CANADIAN SYLLABICS WEST-CREE SHWOO;Lo;0;L;;;;;N;;;;; +1521;CANADIAN SYLLABICS SHWA;Lo;0;L;;;;;N;;;;; +1522;CANADIAN SYLLABICS WEST-CREE SHWA;Lo;0;L;;;;;N;;;;; +1523;CANADIAN SYLLABICS SHWAA;Lo;0;L;;;;;N;;;;; +1524;CANADIAN SYLLABICS WEST-CREE SHWAA;Lo;0;L;;;;;N;;;;; +1525;CANADIAN SYLLABICS SH;Lo;0;L;;;;;N;;;;; +1526;CANADIAN SYLLABICS YE;Lo;0;L;;;;;N;;;;; +1527;CANADIAN SYLLABICS YAAI;Lo;0;L;;;;;N;;;;; +1528;CANADIAN SYLLABICS YI;Lo;0;L;;;;;N;;;;; +1529;CANADIAN SYLLABICS YII;Lo;0;L;;;;;N;;;;; +152A;CANADIAN SYLLABICS YO;Lo;0;L;;;;;N;;;;; +152B;CANADIAN SYLLABICS YOO;Lo;0;L;;;;;N;;;;; +152C;CANADIAN SYLLABICS Y-CREE YOO;Lo;0;L;;;;;N;;;;; +152D;CANADIAN SYLLABICS YA;Lo;0;L;;;;;N;;;;; +152E;CANADIAN SYLLABICS YAA;Lo;0;L;;;;;N;;;;; +152F;CANADIAN SYLLABICS YWE;Lo;0;L;;;;;N;;;;; +1530;CANADIAN SYLLABICS WEST-CREE YWE;Lo;0;L;;;;;N;;;;; +1531;CANADIAN SYLLABICS YWI;Lo;0;L;;;;;N;;;;; +1532;CANADIAN SYLLABICS WEST-CREE YWI;Lo;0;L;;;;;N;;;;; +1533;CANADIAN SYLLABICS YWII;Lo;0;L;;;;;N;;;;; +1534;CANADIAN SYLLABICS WEST-CREE YWII;Lo;0;L;;;;;N;;;;; +1535;CANADIAN SYLLABICS YWO;Lo;0;L;;;;;N;;;;; +1536;CANADIAN SYLLABICS WEST-CREE YWO;Lo;0;L;;;;;N;;;;; +1537;CANADIAN SYLLABICS YWOO;Lo;0;L;;;;;N;;;;; +1538;CANADIAN SYLLABICS WEST-CREE YWOO;Lo;0;L;;;;;N;;;;; +1539;CANADIAN SYLLABICS YWA;Lo;0;L;;;;;N;;;;; +153A;CANADIAN SYLLABICS WEST-CREE YWA;Lo;0;L;;;;;N;;;;; +153B;CANADIAN SYLLABICS YWAA;Lo;0;L;;;;;N;;;;; +153C;CANADIAN SYLLABICS WEST-CREE YWAA;Lo;0;L;;;;;N;;;;; +153D;CANADIAN SYLLABICS NASKAPI YWAA;Lo;0;L;;;;;N;;;;; +153E;CANADIAN SYLLABICS Y;Lo;0;L;;;;;N;;;;; +153F;CANADIAN SYLLABICS BIBLE-CREE Y;Lo;0;L;;;;;N;;;;; +1540;CANADIAN SYLLABICS WEST-CREE Y;Lo;0;L;;;;;N;;;;; +1541;CANADIAN SYLLABICS SAYISI YI;Lo;0;L;;;;;N;;;;; +1542;CANADIAN SYLLABICS RE;Lo;0;L;;;;;N;;;;; +1543;CANADIAN SYLLABICS R-CREE RE;Lo;0;L;;;;;N;;;;; +1544;CANADIAN SYLLABICS WEST-CREE LE;Lo;0;L;;;;;N;;;;; +1545;CANADIAN SYLLABICS RAAI;Lo;0;L;;;;;N;;;;; +1546;CANADIAN SYLLABICS RI;Lo;0;L;;;;;N;;;;; +1547;CANADIAN SYLLABICS RII;Lo;0;L;;;;;N;;;;; +1548;CANADIAN SYLLABICS RO;Lo;0;L;;;;;N;;;;; +1549;CANADIAN SYLLABICS ROO;Lo;0;L;;;;;N;;;;; +154A;CANADIAN SYLLABICS WEST-CREE LO;Lo;0;L;;;;;N;;;;; +154B;CANADIAN SYLLABICS RA;Lo;0;L;;;;;N;;;;; +154C;CANADIAN SYLLABICS RAA;Lo;0;L;;;;;N;;;;; +154D;CANADIAN SYLLABICS WEST-CREE LA;Lo;0;L;;;;;N;;;;; +154E;CANADIAN SYLLABICS RWAA;Lo;0;L;;;;;N;;;;; +154F;CANADIAN SYLLABICS WEST-CREE RWAA;Lo;0;L;;;;;N;;;;; +1550;CANADIAN SYLLABICS R;Lo;0;L;;;;;N;;;;; +1551;CANADIAN SYLLABICS WEST-CREE R;Lo;0;L;;;;;N;;;;; +1552;CANADIAN SYLLABICS MEDIAL R;Lo;0;L;;;;;N;;;;; +1553;CANADIAN SYLLABICS FE;Lo;0;L;;;;;N;;;;; +1554;CANADIAN SYLLABICS FAAI;Lo;0;L;;;;;N;;;;; +1555;CANADIAN SYLLABICS FI;Lo;0;L;;;;;N;;;;; +1556;CANADIAN SYLLABICS FII;Lo;0;L;;;;;N;;;;; +1557;CANADIAN SYLLABICS FO;Lo;0;L;;;;;N;;;;; +1558;CANADIAN SYLLABICS FOO;Lo;0;L;;;;;N;;;;; +1559;CANADIAN SYLLABICS FA;Lo;0;L;;;;;N;;;;; +155A;CANADIAN SYLLABICS FAA;Lo;0;L;;;;;N;;;;; +155B;CANADIAN SYLLABICS FWAA;Lo;0;L;;;;;N;;;;; +155C;CANADIAN SYLLABICS WEST-CREE FWAA;Lo;0;L;;;;;N;;;;; +155D;CANADIAN SYLLABICS F;Lo;0;L;;;;;N;;;;; +155E;CANADIAN SYLLABICS THE;Lo;0;L;;;;;N;;;;; +155F;CANADIAN SYLLABICS N-CREE THE;Lo;0;L;;;;;N;;;;; +1560;CANADIAN SYLLABICS THI;Lo;0;L;;;;;N;;;;; +1561;CANADIAN SYLLABICS N-CREE THI;Lo;0;L;;;;;N;;;;; +1562;CANADIAN SYLLABICS THII;Lo;0;L;;;;;N;;;;; +1563;CANADIAN SYLLABICS N-CREE THII;Lo;0;L;;;;;N;;;;; +1564;CANADIAN SYLLABICS THO;Lo;0;L;;;;;N;;;;; +1565;CANADIAN SYLLABICS THOO;Lo;0;L;;;;;N;;;;; +1566;CANADIAN SYLLABICS THA;Lo;0;L;;;;;N;;;;; +1567;CANADIAN SYLLABICS THAA;Lo;0;L;;;;;N;;;;; +1568;CANADIAN SYLLABICS THWAA;Lo;0;L;;;;;N;;;;; +1569;CANADIAN SYLLABICS WEST-CREE THWAA;Lo;0;L;;;;;N;;;;; +156A;CANADIAN SYLLABICS TH;Lo;0;L;;;;;N;;;;; +156B;CANADIAN SYLLABICS TTHE;Lo;0;L;;;;;N;;;;; +156C;CANADIAN SYLLABICS TTHI;Lo;0;L;;;;;N;;;;; +156D;CANADIAN SYLLABICS TTHO;Lo;0;L;;;;;N;;;;; +156E;CANADIAN SYLLABICS TTHA;Lo;0;L;;;;;N;;;;; +156F;CANADIAN SYLLABICS TTH;Lo;0;L;;;;;N;;;;; +1570;CANADIAN SYLLABICS TYE;Lo;0;L;;;;;N;;;;; +1571;CANADIAN SYLLABICS TYI;Lo;0;L;;;;;N;;;;; +1572;CANADIAN SYLLABICS TYO;Lo;0;L;;;;;N;;;;; +1573;CANADIAN SYLLABICS TYA;Lo;0;L;;;;;N;;;;; +1574;CANADIAN SYLLABICS NUNAVIK HE;Lo;0;L;;;;;N;;;;; +1575;CANADIAN SYLLABICS NUNAVIK HI;Lo;0;L;;;;;N;;;;; +1576;CANADIAN SYLLABICS NUNAVIK HII;Lo;0;L;;;;;N;;;;; +1577;CANADIAN SYLLABICS NUNAVIK HO;Lo;0;L;;;;;N;;;;; +1578;CANADIAN SYLLABICS NUNAVIK HOO;Lo;0;L;;;;;N;;;;; +1579;CANADIAN SYLLABICS NUNAVIK HA;Lo;0;L;;;;;N;;;;; +157A;CANADIAN SYLLABICS NUNAVIK HAA;Lo;0;L;;;;;N;;;;; +157B;CANADIAN SYLLABICS NUNAVIK H;Lo;0;L;;;;;N;;;;; +157C;CANADIAN SYLLABICS NUNAVUT H;Lo;0;L;;;;;N;;;;; +157D;CANADIAN SYLLABICS HK;Lo;0;L;;;;;N;;;;; +157E;CANADIAN SYLLABICS QAAI;Lo;0;L;;;;;N;;;;; +157F;CANADIAN SYLLABICS QI;Lo;0;L;;;;;N;;;;; +1580;CANADIAN SYLLABICS QII;Lo;0;L;;;;;N;;;;; +1581;CANADIAN SYLLABICS QO;Lo;0;L;;;;;N;;;;; +1582;CANADIAN SYLLABICS QOO;Lo;0;L;;;;;N;;;;; +1583;CANADIAN SYLLABICS QA;Lo;0;L;;;;;N;;;;; +1584;CANADIAN SYLLABICS QAA;Lo;0;L;;;;;N;;;;; +1585;CANADIAN SYLLABICS Q;Lo;0;L;;;;;N;;;;; +1586;CANADIAN SYLLABICS TLHE;Lo;0;L;;;;;N;;;;; +1587;CANADIAN SYLLABICS TLHI;Lo;0;L;;;;;N;;;;; +1588;CANADIAN SYLLABICS TLHO;Lo;0;L;;;;;N;;;;; +1589;CANADIAN SYLLABICS TLHA;Lo;0;L;;;;;N;;;;; +158A;CANADIAN SYLLABICS WEST-CREE RE;Lo;0;L;;;;;N;;;;; +158B;CANADIAN SYLLABICS WEST-CREE RI;Lo;0;L;;;;;N;;;;; +158C;CANADIAN SYLLABICS WEST-CREE RO;Lo;0;L;;;;;N;;;;; +158D;CANADIAN SYLLABICS WEST-CREE RA;Lo;0;L;;;;;N;;;;; +158E;CANADIAN SYLLABICS NGAAI;Lo;0;L;;;;;N;;;;; +158F;CANADIAN SYLLABICS NGI;Lo;0;L;;;;;N;;;;; +1590;CANADIAN SYLLABICS NGII;Lo;0;L;;;;;N;;;;; +1591;CANADIAN SYLLABICS NGO;Lo;0;L;;;;;N;;;;; +1592;CANADIAN SYLLABICS NGOO;Lo;0;L;;;;;N;;;;; +1593;CANADIAN SYLLABICS NGA;Lo;0;L;;;;;N;;;;; +1594;CANADIAN SYLLABICS NGAA;Lo;0;L;;;;;N;;;;; +1595;CANADIAN SYLLABICS NG;Lo;0;L;;;;;N;;;;; +1596;CANADIAN SYLLABICS NNG;Lo;0;L;;;;;N;;;;; +1597;CANADIAN SYLLABICS SAYISI SHE;Lo;0;L;;;;;N;;;;; +1598;CANADIAN SYLLABICS SAYISI SHI;Lo;0;L;;;;;N;;;;; +1599;CANADIAN SYLLABICS SAYISI SHO;Lo;0;L;;;;;N;;;;; +159A;CANADIAN SYLLABICS SAYISI SHA;Lo;0;L;;;;;N;;;;; +159B;CANADIAN SYLLABICS WOODS-CREE THE;Lo;0;L;;;;;N;;;;; +159C;CANADIAN SYLLABICS WOODS-CREE THI;Lo;0;L;;;;;N;;;;; +159D;CANADIAN SYLLABICS WOODS-CREE THO;Lo;0;L;;;;;N;;;;; +159E;CANADIAN SYLLABICS WOODS-CREE THA;Lo;0;L;;;;;N;;;;; +159F;CANADIAN SYLLABICS WOODS-CREE TH;Lo;0;L;;;;;N;;;;; +15A0;CANADIAN SYLLABICS LHI;Lo;0;L;;;;;N;;;;; +15A1;CANADIAN SYLLABICS LHII;Lo;0;L;;;;;N;;;;; +15A2;CANADIAN SYLLABICS LHO;Lo;0;L;;;;;N;;;;; +15A3;CANADIAN SYLLABICS LHOO;Lo;0;L;;;;;N;;;;; +15A4;CANADIAN SYLLABICS LHA;Lo;0;L;;;;;N;;;;; +15A5;CANADIAN SYLLABICS LHAA;Lo;0;L;;;;;N;;;;; +15A6;CANADIAN SYLLABICS LH;Lo;0;L;;;;;N;;;;; +15A7;CANADIAN SYLLABICS TH-CREE THE;Lo;0;L;;;;;N;;;;; +15A8;CANADIAN SYLLABICS TH-CREE THI;Lo;0;L;;;;;N;;;;; +15A9;CANADIAN SYLLABICS TH-CREE THII;Lo;0;L;;;;;N;;;;; +15AA;CANADIAN SYLLABICS TH-CREE THO;Lo;0;L;;;;;N;;;;; +15AB;CANADIAN SYLLABICS TH-CREE THOO;Lo;0;L;;;;;N;;;;; +15AC;CANADIAN SYLLABICS TH-CREE THA;Lo;0;L;;;;;N;;;;; +15AD;CANADIAN SYLLABICS TH-CREE THAA;Lo;0;L;;;;;N;;;;; +15AE;CANADIAN SYLLABICS TH-CREE TH;Lo;0;L;;;;;N;;;;; +15AF;CANADIAN SYLLABICS AIVILIK B;Lo;0;L;;;;;N;;;;; +15B0;CANADIAN SYLLABICS BLACKFOOT E;Lo;0;L;;;;;N;;;;; +15B1;CANADIAN SYLLABICS BLACKFOOT I;Lo;0;L;;;;;N;;;;; +15B2;CANADIAN SYLLABICS BLACKFOOT O;Lo;0;L;;;;;N;;;;; +15B3;CANADIAN SYLLABICS BLACKFOOT A;Lo;0;L;;;;;N;;;;; +15B4;CANADIAN SYLLABICS BLACKFOOT WE;Lo;0;L;;;;;N;;;;; +15B5;CANADIAN SYLLABICS BLACKFOOT WI;Lo;0;L;;;;;N;;;;; +15B6;CANADIAN SYLLABICS BLACKFOOT WO;Lo;0;L;;;;;N;;;;; +15B7;CANADIAN SYLLABICS BLACKFOOT WA;Lo;0;L;;;;;N;;;;; +15B8;CANADIAN SYLLABICS BLACKFOOT NE;Lo;0;L;;;;;N;;;;; +15B9;CANADIAN SYLLABICS BLACKFOOT NI;Lo;0;L;;;;;N;;;;; +15BA;CANADIAN SYLLABICS BLACKFOOT NO;Lo;0;L;;;;;N;;;;; +15BB;CANADIAN SYLLABICS BLACKFOOT NA;Lo;0;L;;;;;N;;;;; +15BC;CANADIAN SYLLABICS BLACKFOOT KE;Lo;0;L;;;;;N;;;;; +15BD;CANADIAN SYLLABICS BLACKFOOT KI;Lo;0;L;;;;;N;;;;; +15BE;CANADIAN SYLLABICS BLACKFOOT KO;Lo;0;L;;;;;N;;;;; +15BF;CANADIAN SYLLABICS BLACKFOOT KA;Lo;0;L;;;;;N;;;;; +15C0;CANADIAN SYLLABICS SAYISI HE;Lo;0;L;;;;;N;;;;; +15C1;CANADIAN SYLLABICS SAYISI HI;Lo;0;L;;;;;N;;;;; +15C2;CANADIAN SYLLABICS SAYISI HO;Lo;0;L;;;;;N;;;;; +15C3;CANADIAN SYLLABICS SAYISI HA;Lo;0;L;;;;;N;;;;; +15C4;CANADIAN SYLLABICS CARRIER GHU;Lo;0;L;;;;;N;;;;; +15C5;CANADIAN SYLLABICS CARRIER GHO;Lo;0;L;;;;;N;;;;; +15C6;CANADIAN SYLLABICS CARRIER GHE;Lo;0;L;;;;;N;;;;; +15C7;CANADIAN SYLLABICS CARRIER GHEE;Lo;0;L;;;;;N;;;;; +15C8;CANADIAN SYLLABICS CARRIER GHI;Lo;0;L;;;;;N;;;;; +15C9;CANADIAN SYLLABICS CARRIER GHA;Lo;0;L;;;;;N;;;;; +15CA;CANADIAN SYLLABICS CARRIER RU;Lo;0;L;;;;;N;;;;; +15CB;CANADIAN SYLLABICS CARRIER RO;Lo;0;L;;;;;N;;;;; +15CC;CANADIAN SYLLABICS CARRIER RE;Lo;0;L;;;;;N;;;;; +15CD;CANADIAN SYLLABICS CARRIER REE;Lo;0;L;;;;;N;;;;; +15CE;CANADIAN SYLLABICS CARRIER RI;Lo;0;L;;;;;N;;;;; +15CF;CANADIAN SYLLABICS CARRIER RA;Lo;0;L;;;;;N;;;;; +15D0;CANADIAN SYLLABICS CARRIER WU;Lo;0;L;;;;;N;;;;; +15D1;CANADIAN SYLLABICS CARRIER WO;Lo;0;L;;;;;N;;;;; +15D2;CANADIAN SYLLABICS CARRIER WE;Lo;0;L;;;;;N;;;;; +15D3;CANADIAN SYLLABICS CARRIER WEE;Lo;0;L;;;;;N;;;;; +15D4;CANADIAN SYLLABICS CARRIER WI;Lo;0;L;;;;;N;;;;; +15D5;CANADIAN SYLLABICS CARRIER WA;Lo;0;L;;;;;N;;;;; +15D6;CANADIAN SYLLABICS CARRIER HWU;Lo;0;L;;;;;N;;;;; +15D7;CANADIAN SYLLABICS CARRIER HWO;Lo;0;L;;;;;N;;;;; +15D8;CANADIAN SYLLABICS CARRIER HWE;Lo;0;L;;;;;N;;;;; +15D9;CANADIAN SYLLABICS CARRIER HWEE;Lo;0;L;;;;;N;;;;; +15DA;CANADIAN SYLLABICS CARRIER HWI;Lo;0;L;;;;;N;;;;; +15DB;CANADIAN SYLLABICS CARRIER HWA;Lo;0;L;;;;;N;;;;; +15DC;CANADIAN SYLLABICS CARRIER THU;Lo;0;L;;;;;N;;;;; +15DD;CANADIAN SYLLABICS CARRIER THO;Lo;0;L;;;;;N;;;;; +15DE;CANADIAN SYLLABICS CARRIER THE;Lo;0;L;;;;;N;;;;; +15DF;CANADIAN SYLLABICS CARRIER THEE;Lo;0;L;;;;;N;;;;; +15E0;CANADIAN SYLLABICS CARRIER THI;Lo;0;L;;;;;N;;;;; +15E1;CANADIAN SYLLABICS CARRIER THA;Lo;0;L;;;;;N;;;;; +15E2;CANADIAN SYLLABICS CARRIER TTU;Lo;0;L;;;;;N;;;;; +15E3;CANADIAN SYLLABICS CARRIER TTO;Lo;0;L;;;;;N;;;;; +15E4;CANADIAN SYLLABICS CARRIER TTE;Lo;0;L;;;;;N;;;;; +15E5;CANADIAN SYLLABICS CARRIER TTEE;Lo;0;L;;;;;N;;;;; +15E6;CANADIAN SYLLABICS CARRIER TTI;Lo;0;L;;;;;N;;;;; +15E7;CANADIAN SYLLABICS CARRIER TTA;Lo;0;L;;;;;N;;;;; +15E8;CANADIAN SYLLABICS CARRIER PU;Lo;0;L;;;;;N;;;;; +15E9;CANADIAN SYLLABICS CARRIER PO;Lo;0;L;;;;;N;;;;; +15EA;CANADIAN SYLLABICS CARRIER PE;Lo;0;L;;;;;N;;;;; +15EB;CANADIAN SYLLABICS CARRIER PEE;Lo;0;L;;;;;N;;;;; +15EC;CANADIAN SYLLABICS CARRIER PI;Lo;0;L;;;;;N;;;;; +15ED;CANADIAN SYLLABICS CARRIER PA;Lo;0;L;;;;;N;;;;; +15EE;CANADIAN SYLLABICS CARRIER P;Lo;0;L;;;;;N;;;;; +15EF;CANADIAN SYLLABICS CARRIER GU;Lo;0;L;;;;;N;;;;; +15F0;CANADIAN SYLLABICS CARRIER GO;Lo;0;L;;;;;N;;;;; +15F1;CANADIAN SYLLABICS CARRIER GE;Lo;0;L;;;;;N;;;;; +15F2;CANADIAN SYLLABICS CARRIER GEE;Lo;0;L;;;;;N;;;;; +15F3;CANADIAN SYLLABICS CARRIER GI;Lo;0;L;;;;;N;;;;; +15F4;CANADIAN SYLLABICS CARRIER GA;Lo;0;L;;;;;N;;;;; +15F5;CANADIAN SYLLABICS CARRIER KHU;Lo;0;L;;;;;N;;;;; +15F6;CANADIAN SYLLABICS CARRIER KHO;Lo;0;L;;;;;N;;;;; +15F7;CANADIAN SYLLABICS CARRIER KHE;Lo;0;L;;;;;N;;;;; +15F8;CANADIAN SYLLABICS CARRIER KHEE;Lo;0;L;;;;;N;;;;; +15F9;CANADIAN SYLLABICS CARRIER KHI;Lo;0;L;;;;;N;;;;; +15FA;CANADIAN SYLLABICS CARRIER KHA;Lo;0;L;;;;;N;;;;; +15FB;CANADIAN SYLLABICS CARRIER KKU;Lo;0;L;;;;;N;;;;; +15FC;CANADIAN SYLLABICS CARRIER KKO;Lo;0;L;;;;;N;;;;; +15FD;CANADIAN SYLLABICS CARRIER KKE;Lo;0;L;;;;;N;;;;; +15FE;CANADIAN SYLLABICS CARRIER KKEE;Lo;0;L;;;;;N;;;;; +15FF;CANADIAN SYLLABICS CARRIER KKI;Lo;0;L;;;;;N;;;;; +1600;CANADIAN SYLLABICS CARRIER KKA;Lo;0;L;;;;;N;;;;; +1601;CANADIAN SYLLABICS CARRIER KK;Lo;0;L;;;;;N;;;;; +1602;CANADIAN SYLLABICS CARRIER NU;Lo;0;L;;;;;N;;;;; +1603;CANADIAN SYLLABICS CARRIER NO;Lo;0;L;;;;;N;;;;; +1604;CANADIAN SYLLABICS CARRIER NE;Lo;0;L;;;;;N;;;;; +1605;CANADIAN SYLLABICS CARRIER NEE;Lo;0;L;;;;;N;;;;; +1606;CANADIAN SYLLABICS CARRIER NI;Lo;0;L;;;;;N;;;;; +1607;CANADIAN SYLLABICS CARRIER NA;Lo;0;L;;;;;N;;;;; +1608;CANADIAN SYLLABICS CARRIER MU;Lo;0;L;;;;;N;;;;; +1609;CANADIAN SYLLABICS CARRIER MO;Lo;0;L;;;;;N;;;;; +160A;CANADIAN SYLLABICS CARRIER ME;Lo;0;L;;;;;N;;;;; +160B;CANADIAN SYLLABICS CARRIER MEE;Lo;0;L;;;;;N;;;;; +160C;CANADIAN SYLLABICS CARRIER MI;Lo;0;L;;;;;N;;;;; +160D;CANADIAN SYLLABICS CARRIER MA;Lo;0;L;;;;;N;;;;; +160E;CANADIAN SYLLABICS CARRIER YU;Lo;0;L;;;;;N;;;;; +160F;CANADIAN SYLLABICS CARRIER YO;Lo;0;L;;;;;N;;;;; +1610;CANADIAN SYLLABICS CARRIER YE;Lo;0;L;;;;;N;;;;; +1611;CANADIAN SYLLABICS CARRIER YEE;Lo;0;L;;;;;N;;;;; +1612;CANADIAN SYLLABICS CARRIER YI;Lo;0;L;;;;;N;;;;; +1613;CANADIAN SYLLABICS CARRIER YA;Lo;0;L;;;;;N;;;;; +1614;CANADIAN SYLLABICS CARRIER JU;Lo;0;L;;;;;N;;;;; +1615;CANADIAN SYLLABICS SAYISI JU;Lo;0;L;;;;;N;;;;; +1616;CANADIAN SYLLABICS CARRIER JO;Lo;0;L;;;;;N;;;;; +1617;CANADIAN SYLLABICS CARRIER JE;Lo;0;L;;;;;N;;;;; +1618;CANADIAN SYLLABICS CARRIER JEE;Lo;0;L;;;;;N;;;;; +1619;CANADIAN SYLLABICS CARRIER JI;Lo;0;L;;;;;N;;;;; +161A;CANADIAN SYLLABICS SAYISI JI;Lo;0;L;;;;;N;;;;; +161B;CANADIAN SYLLABICS CARRIER JA;Lo;0;L;;;;;N;;;;; +161C;CANADIAN SYLLABICS CARRIER JJU;Lo;0;L;;;;;N;;;;; +161D;CANADIAN SYLLABICS CARRIER JJO;Lo;0;L;;;;;N;;;;; +161E;CANADIAN SYLLABICS CARRIER JJE;Lo;0;L;;;;;N;;;;; +161F;CANADIAN SYLLABICS CARRIER JJEE;Lo;0;L;;;;;N;;;;; +1620;CANADIAN SYLLABICS CARRIER JJI;Lo;0;L;;;;;N;;;;; +1621;CANADIAN SYLLABICS CARRIER JJA;Lo;0;L;;;;;N;;;;; +1622;CANADIAN SYLLABICS CARRIER LU;Lo;0;L;;;;;N;;;;; +1623;CANADIAN SYLLABICS CARRIER LO;Lo;0;L;;;;;N;;;;; +1624;CANADIAN SYLLABICS CARRIER LE;Lo;0;L;;;;;N;;;;; +1625;CANADIAN SYLLABICS CARRIER LEE;Lo;0;L;;;;;N;;;;; +1626;CANADIAN SYLLABICS CARRIER LI;Lo;0;L;;;;;N;;;;; +1627;CANADIAN SYLLABICS CARRIER LA;Lo;0;L;;;;;N;;;;; +1628;CANADIAN SYLLABICS CARRIER DLU;Lo;0;L;;;;;N;;;;; +1629;CANADIAN SYLLABICS CARRIER DLO;Lo;0;L;;;;;N;;;;; +162A;CANADIAN SYLLABICS CARRIER DLE;Lo;0;L;;;;;N;;;;; +162B;CANADIAN SYLLABICS CARRIER DLEE;Lo;0;L;;;;;N;;;;; +162C;CANADIAN SYLLABICS CARRIER DLI;Lo;0;L;;;;;N;;;;; +162D;CANADIAN SYLLABICS CARRIER DLA;Lo;0;L;;;;;N;;;;; +162E;CANADIAN SYLLABICS CARRIER LHU;Lo;0;L;;;;;N;;;;; +162F;CANADIAN SYLLABICS CARRIER LHO;Lo;0;L;;;;;N;;;;; +1630;CANADIAN SYLLABICS CARRIER LHE;Lo;0;L;;;;;N;;;;; +1631;CANADIAN SYLLABICS CARRIER LHEE;Lo;0;L;;;;;N;;;;; +1632;CANADIAN SYLLABICS CARRIER LHI;Lo;0;L;;;;;N;;;;; +1633;CANADIAN SYLLABICS CARRIER LHA;Lo;0;L;;;;;N;;;;; +1634;CANADIAN SYLLABICS CARRIER TLHU;Lo;0;L;;;;;N;;;;; +1635;CANADIAN SYLLABICS CARRIER TLHO;Lo;0;L;;;;;N;;;;; +1636;CANADIAN SYLLABICS CARRIER TLHE;Lo;0;L;;;;;N;;;;; +1637;CANADIAN SYLLABICS CARRIER TLHEE;Lo;0;L;;;;;N;;;;; +1638;CANADIAN SYLLABICS CARRIER TLHI;Lo;0;L;;;;;N;;;;; +1639;CANADIAN SYLLABICS CARRIER TLHA;Lo;0;L;;;;;N;;;;; +163A;CANADIAN SYLLABICS CARRIER TLU;Lo;0;L;;;;;N;;;;; +163B;CANADIAN SYLLABICS CARRIER TLO;Lo;0;L;;;;;N;;;;; +163C;CANADIAN SYLLABICS CARRIER TLE;Lo;0;L;;;;;N;;;;; +163D;CANADIAN SYLLABICS CARRIER TLEE;Lo;0;L;;;;;N;;;;; +163E;CANADIAN SYLLABICS CARRIER TLI;Lo;0;L;;;;;N;;;;; +163F;CANADIAN SYLLABICS CARRIER TLA;Lo;0;L;;;;;N;;;;; +1640;CANADIAN SYLLABICS CARRIER ZU;Lo;0;L;;;;;N;;;;; +1641;CANADIAN SYLLABICS CARRIER ZO;Lo;0;L;;;;;N;;;;; +1642;CANADIAN SYLLABICS CARRIER ZE;Lo;0;L;;;;;N;;;;; +1643;CANADIAN SYLLABICS CARRIER ZEE;Lo;0;L;;;;;N;;;;; +1644;CANADIAN SYLLABICS CARRIER ZI;Lo;0;L;;;;;N;;;;; +1645;CANADIAN SYLLABICS CARRIER ZA;Lo;0;L;;;;;N;;;;; +1646;CANADIAN SYLLABICS CARRIER Z;Lo;0;L;;;;;N;;;;; +1647;CANADIAN SYLLABICS CARRIER INITIAL Z;Lo;0;L;;;;;N;;;;; +1648;CANADIAN SYLLABICS CARRIER DZU;Lo;0;L;;;;;N;;;;; +1649;CANADIAN SYLLABICS CARRIER DZO;Lo;0;L;;;;;N;;;;; +164A;CANADIAN SYLLABICS CARRIER DZE;Lo;0;L;;;;;N;;;;; +164B;CANADIAN SYLLABICS CARRIER DZEE;Lo;0;L;;;;;N;;;;; +164C;CANADIAN SYLLABICS CARRIER DZI;Lo;0;L;;;;;N;;;;; +164D;CANADIAN SYLLABICS CARRIER DZA;Lo;0;L;;;;;N;;;;; +164E;CANADIAN SYLLABICS CARRIER SU;Lo;0;L;;;;;N;;;;; +164F;CANADIAN SYLLABICS CARRIER SO;Lo;0;L;;;;;N;;;;; +1650;CANADIAN SYLLABICS CARRIER SE;Lo;0;L;;;;;N;;;;; +1651;CANADIAN SYLLABICS CARRIER SEE;Lo;0;L;;;;;N;;;;; +1652;CANADIAN SYLLABICS CARRIER SI;Lo;0;L;;;;;N;;;;; +1653;CANADIAN SYLLABICS CARRIER SA;Lo;0;L;;;;;N;;;;; +1654;CANADIAN SYLLABICS CARRIER SHU;Lo;0;L;;;;;N;;;;; +1655;CANADIAN SYLLABICS CARRIER SHO;Lo;0;L;;;;;N;;;;; +1656;CANADIAN SYLLABICS CARRIER SHE;Lo;0;L;;;;;N;;;;; +1657;CANADIAN SYLLABICS CARRIER SHEE;Lo;0;L;;;;;N;;;;; +1658;CANADIAN SYLLABICS CARRIER SHI;Lo;0;L;;;;;N;;;;; +1659;CANADIAN SYLLABICS CARRIER SHA;Lo;0;L;;;;;N;;;;; +165A;CANADIAN SYLLABICS CARRIER SH;Lo;0;L;;;;;N;;;;; +165B;CANADIAN SYLLABICS CARRIER TSU;Lo;0;L;;;;;N;;;;; +165C;CANADIAN SYLLABICS CARRIER TSO;Lo;0;L;;;;;N;;;;; +165D;CANADIAN SYLLABICS CARRIER TSE;Lo;0;L;;;;;N;;;;; +165E;CANADIAN SYLLABICS CARRIER TSEE;Lo;0;L;;;;;N;;;;; +165F;CANADIAN SYLLABICS CARRIER TSI;Lo;0;L;;;;;N;;;;; +1660;CANADIAN SYLLABICS CARRIER TSA;Lo;0;L;;;;;N;;;;; +1661;CANADIAN SYLLABICS CARRIER CHU;Lo;0;L;;;;;N;;;;; +1662;CANADIAN SYLLABICS CARRIER CHO;Lo;0;L;;;;;N;;;;; +1663;CANADIAN SYLLABICS CARRIER CHE;Lo;0;L;;;;;N;;;;; +1664;CANADIAN SYLLABICS CARRIER CHEE;Lo;0;L;;;;;N;;;;; +1665;CANADIAN SYLLABICS CARRIER CHI;Lo;0;L;;;;;N;;;;; +1666;CANADIAN SYLLABICS CARRIER CHA;Lo;0;L;;;;;N;;;;; +1667;CANADIAN SYLLABICS CARRIER TTSU;Lo;0;L;;;;;N;;;;; +1668;CANADIAN SYLLABICS CARRIER TTSO;Lo;0;L;;;;;N;;;;; +1669;CANADIAN SYLLABICS CARRIER TTSE;Lo;0;L;;;;;N;;;;; +166A;CANADIAN SYLLABICS CARRIER TTSEE;Lo;0;L;;;;;N;;;;; +166B;CANADIAN SYLLABICS CARRIER TTSI;Lo;0;L;;;;;N;;;;; +166C;CANADIAN SYLLABICS CARRIER TTSA;Lo;0;L;;;;;N;;;;; +166D;CANADIAN SYLLABICS CHI SIGN;Po;0;L;;;;;N;;;;; +166E;CANADIAN SYLLABICS FULL STOP;Po;0;L;;;;;N;;;;; +166F;CANADIAN SYLLABICS QAI;Lo;0;L;;;;;N;;;;; +1670;CANADIAN SYLLABICS NGAI;Lo;0;L;;;;;N;;;;; +1671;CANADIAN SYLLABICS NNGI;Lo;0;L;;;;;N;;;;; +1672;CANADIAN SYLLABICS NNGII;Lo;0;L;;;;;N;;;;; +1673;CANADIAN SYLLABICS NNGO;Lo;0;L;;;;;N;;;;; +1674;CANADIAN SYLLABICS NNGOO;Lo;0;L;;;;;N;;;;; +1675;CANADIAN SYLLABICS NNGA;Lo;0;L;;;;;N;;;;; +1676;CANADIAN SYLLABICS NNGAA;Lo;0;L;;;;;N;;;;; +1677;CANADIAN SYLLABICS WOODS-CREE THWEE;Lo;0;L;;;;;N;;;;; +1678;CANADIAN SYLLABICS WOODS-CREE THWI;Lo;0;L;;;;;N;;;;; +1679;CANADIAN SYLLABICS WOODS-CREE THWII;Lo;0;L;;;;;N;;;;; +167A;CANADIAN SYLLABICS WOODS-CREE THWO;Lo;0;L;;;;;N;;;;; +167B;CANADIAN SYLLABICS WOODS-CREE THWOO;Lo;0;L;;;;;N;;;;; +167C;CANADIAN SYLLABICS WOODS-CREE THWA;Lo;0;L;;;;;N;;;;; +167D;CANADIAN SYLLABICS WOODS-CREE THWAA;Lo;0;L;;;;;N;;;;; +167E;CANADIAN SYLLABICS WOODS-CREE FINAL TH;Lo;0;L;;;;;N;;;;; +167F;CANADIAN SYLLABICS BLACKFOOT W;Lo;0;L;;;;;N;;;;; +1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;; +1681;OGHAM LETTER BEITH;Lo;0;L;;;;;N;;;;; +1682;OGHAM LETTER LUIS;Lo;0;L;;;;;N;;;;; +1683;OGHAM LETTER FEARN;Lo;0;L;;;;;N;;;;; +1684;OGHAM LETTER SAIL;Lo;0;L;;;;;N;;;;; +1685;OGHAM LETTER NION;Lo;0;L;;;;;N;;;;; +1686;OGHAM LETTER UATH;Lo;0;L;;;;;N;;;;; +1687;OGHAM LETTER DAIR;Lo;0;L;;;;;N;;;;; +1688;OGHAM LETTER TINNE;Lo;0;L;;;;;N;;;;; +1689;OGHAM LETTER COLL;Lo;0;L;;;;;N;;;;; +168A;OGHAM LETTER CEIRT;Lo;0;L;;;;;N;;;;; +168B;OGHAM LETTER MUIN;Lo;0;L;;;;;N;;;;; +168C;OGHAM LETTER GORT;Lo;0;L;;;;;N;;;;; +168D;OGHAM LETTER NGEADAL;Lo;0;L;;;;;N;;;;; +168E;OGHAM LETTER STRAIF;Lo;0;L;;;;;N;;;;; +168F;OGHAM LETTER RUIS;Lo;0;L;;;;;N;;;;; +1690;OGHAM LETTER AILM;Lo;0;L;;;;;N;;;;; +1691;OGHAM LETTER ONN;Lo;0;L;;;;;N;;;;; +1692;OGHAM LETTER UR;Lo;0;L;;;;;N;;;;; +1693;OGHAM LETTER EADHADH;Lo;0;L;;;;;N;;;;; +1694;OGHAM LETTER IODHADH;Lo;0;L;;;;;N;;;;; +1695;OGHAM LETTER EABHADH;Lo;0;L;;;;;N;;;;; +1696;OGHAM LETTER OR;Lo;0;L;;;;;N;;;;; +1697;OGHAM LETTER UILLEANN;Lo;0;L;;;;;N;;;;; +1698;OGHAM LETTER IFIN;Lo;0;L;;;;;N;;;;; +1699;OGHAM LETTER EAMHANCHOLL;Lo;0;L;;;;;N;;;;; +169A;OGHAM LETTER PEITH;Lo;0;L;;;;;N;;;;; +169B;OGHAM FEATHER MARK;Ps;0;ON;;;;;Y;;;;; +169C;OGHAM REVERSED FEATHER MARK;Pe;0;ON;;;;;Y;;;;; +16A0;RUNIC LETTER FEHU FEOH FE F;Lo;0;L;;;;;N;;;;; +16A1;RUNIC LETTER V;Lo;0;L;;;;;N;;;;; +16A2;RUNIC LETTER URUZ UR U;Lo;0;L;;;;;N;;;;; +16A3;RUNIC LETTER YR;Lo;0;L;;;;;N;;;;; +16A4;RUNIC LETTER Y;Lo;0;L;;;;;N;;;;; +16A5;RUNIC LETTER W;Lo;0;L;;;;;N;;;;; +16A6;RUNIC LETTER THURISAZ THURS THORN;Lo;0;L;;;;;N;;;;; +16A7;RUNIC LETTER ETH;Lo;0;L;;;;;N;;;;; +16A8;RUNIC LETTER ANSUZ A;Lo;0;L;;;;;N;;;;; +16A9;RUNIC LETTER OS O;Lo;0;L;;;;;N;;;;; +16AA;RUNIC LETTER AC A;Lo;0;L;;;;;N;;;;; +16AB;RUNIC LETTER AESC;Lo;0;L;;;;;N;;;;; +16AC;RUNIC LETTER LONG-BRANCH-OSS O;Lo;0;L;;;;;N;;;;; +16AD;RUNIC LETTER SHORT-TWIG-OSS O;Lo;0;L;;;;;N;;;;; +16AE;RUNIC LETTER O;Lo;0;L;;;;;N;;;;; +16AF;RUNIC LETTER OE;Lo;0;L;;;;;N;;;;; +16B0;RUNIC LETTER ON;Lo;0;L;;;;;N;;;;; +16B1;RUNIC LETTER RAIDO RAD REID R;Lo;0;L;;;;;N;;;;; +16B2;RUNIC LETTER KAUNA;Lo;0;L;;;;;N;;;;; +16B3;RUNIC LETTER CEN;Lo;0;L;;;;;N;;;;; +16B4;RUNIC LETTER KAUN K;Lo;0;L;;;;;N;;;;; +16B5;RUNIC LETTER G;Lo;0;L;;;;;N;;;;; +16B6;RUNIC LETTER ENG;Lo;0;L;;;;;N;;;;; +16B7;RUNIC LETTER GEBO GYFU G;Lo;0;L;;;;;N;;;;; +16B8;RUNIC LETTER GAR;Lo;0;L;;;;;N;;;;; +16B9;RUNIC LETTER WUNJO WYNN W;Lo;0;L;;;;;N;;;;; +16BA;RUNIC LETTER HAGLAZ H;Lo;0;L;;;;;N;;;;; +16BB;RUNIC LETTER HAEGL H;Lo;0;L;;;;;N;;;;; +16BC;RUNIC LETTER LONG-BRANCH-HAGALL H;Lo;0;L;;;;;N;;;;; +16BD;RUNIC LETTER SHORT-TWIG-HAGALL H;Lo;0;L;;;;;N;;;;; +16BE;RUNIC LETTER NAUDIZ NYD NAUD N;Lo;0;L;;;;;N;;;;; +16BF;RUNIC LETTER SHORT-TWIG-NAUD N;Lo;0;L;;;;;N;;;;; +16C0;RUNIC LETTER DOTTED-N;Lo;0;L;;;;;N;;;;; +16C1;RUNIC LETTER ISAZ IS ISS I;Lo;0;L;;;;;N;;;;; +16C2;RUNIC LETTER E;Lo;0;L;;;;;N;;;;; +16C3;RUNIC LETTER JERAN J;Lo;0;L;;;;;N;;;;; +16C4;RUNIC LETTER GER;Lo;0;L;;;;;N;;;;; +16C5;RUNIC LETTER LONG-BRANCH-AR AE;Lo;0;L;;;;;N;;;;; +16C6;RUNIC LETTER SHORT-TWIG-AR A;Lo;0;L;;;;;N;;;;; +16C7;RUNIC LETTER IWAZ EOH;Lo;0;L;;;;;N;;;;; +16C8;RUNIC LETTER PERTHO PEORTH P;Lo;0;L;;;;;N;;;;; +16C9;RUNIC LETTER ALGIZ EOLHX;Lo;0;L;;;;;N;;;;; +16CA;RUNIC LETTER SOWILO S;Lo;0;L;;;;;N;;;;; +16CB;RUNIC LETTER SIGEL LONG-BRANCH-SOL S;Lo;0;L;;;;;N;;;;; +16CC;RUNIC LETTER SHORT-TWIG-SOL S;Lo;0;L;;;;;N;;;;; +16CD;RUNIC LETTER C;Lo;0;L;;;;;N;;;;; +16CE;RUNIC LETTER Z;Lo;0;L;;;;;N;;;;; +16CF;RUNIC LETTER TIWAZ TIR TYR T;Lo;0;L;;;;;N;;;;; +16D0;RUNIC LETTER SHORT-TWIG-TYR T;Lo;0;L;;;;;N;;;;; +16D1;RUNIC LETTER D;Lo;0;L;;;;;N;;;;; +16D2;RUNIC LETTER BERKANAN BEORC BJARKAN B;Lo;0;L;;;;;N;;;;; +16D3;RUNIC LETTER SHORT-TWIG-BJARKAN B;Lo;0;L;;;;;N;;;;; +16D4;RUNIC LETTER DOTTED-P;Lo;0;L;;;;;N;;;;; +16D5;RUNIC LETTER OPEN-P;Lo;0;L;;;;;N;;;;; +16D6;RUNIC LETTER EHWAZ EH E;Lo;0;L;;;;;N;;;;; +16D7;RUNIC LETTER MANNAZ MAN M;Lo;0;L;;;;;N;;;;; +16D8;RUNIC LETTER LONG-BRANCH-MADR M;Lo;0;L;;;;;N;;;;; +16D9;RUNIC LETTER SHORT-TWIG-MADR M;Lo;0;L;;;;;N;;;;; +16DA;RUNIC LETTER LAUKAZ LAGU LOGR L;Lo;0;L;;;;;N;;;;; +16DB;RUNIC LETTER DOTTED-L;Lo;0;L;;;;;N;;;;; +16DC;RUNIC LETTER INGWAZ;Lo;0;L;;;;;N;;;;; +16DD;RUNIC LETTER ING;Lo;0;L;;;;;N;;;;; +16DE;RUNIC LETTER DAGAZ DAEG D;Lo;0;L;;;;;N;;;;; +16DF;RUNIC LETTER OTHALAN ETHEL O;Lo;0;L;;;;;N;;;;; +16E0;RUNIC LETTER EAR;Lo;0;L;;;;;N;;;;; +16E1;RUNIC LETTER IOR;Lo;0;L;;;;;N;;;;; +16E2;RUNIC LETTER CWEORTH;Lo;0;L;;;;;N;;;;; +16E3;RUNIC LETTER CALC;Lo;0;L;;;;;N;;;;; +16E4;RUNIC LETTER CEALC;Lo;0;L;;;;;N;;;;; +16E5;RUNIC LETTER STAN;Lo;0;L;;;;;N;;;;; +16E6;RUNIC LETTER LONG-BRANCH-YR;Lo;0;L;;;;;N;;;;; +16E7;RUNIC LETTER SHORT-TWIG-YR;Lo;0;L;;;;;N;;;;; +16E8;RUNIC LETTER ICELANDIC-YR;Lo;0;L;;;;;N;;;;; +16E9;RUNIC LETTER Q;Lo;0;L;;;;;N;;;;; +16EA;RUNIC LETTER X;Lo;0;L;;;;;N;;;;; +16EB;RUNIC SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; +16EC;RUNIC MULTIPLE PUNCTUATION;Po;0;L;;;;;N;;;;; +16ED;RUNIC CROSS PUNCTUATION;Po;0;L;;;;;N;;;;; +16EE;RUNIC ARLAUG SYMBOL;Nl;0;L;;;;17;N;;;;; +16EF;RUNIC TVIMADUR SYMBOL;Nl;0;L;;;;18;N;;;;; +16F0;RUNIC BELGTHOR SYMBOL;Nl;0;L;;;;19;N;;;;; +16F1;RUNIC LETTER K;Lo;0;L;;;;;N;;;;; +16F2;RUNIC LETTER SH;Lo;0;L;;;;;N;;;;; +16F3;RUNIC LETTER OO;Lo;0;L;;;;;N;;;;; +16F4;RUNIC LETTER FRANKS CASKET OS;Lo;0;L;;;;;N;;;;; +16F5;RUNIC LETTER FRANKS CASKET IS;Lo;0;L;;;;;N;;;;; +16F6;RUNIC LETTER FRANKS CASKET EH;Lo;0;L;;;;;N;;;;; +16F7;RUNIC LETTER FRANKS CASKET AC;Lo;0;L;;;;;N;;;;; +16F8;RUNIC LETTER FRANKS CASKET AESC;Lo;0;L;;;;;N;;;;; +1700;TAGALOG LETTER A;Lo;0;L;;;;;N;;;;; +1701;TAGALOG LETTER I;Lo;0;L;;;;;N;;;;; +1702;TAGALOG LETTER U;Lo;0;L;;;;;N;;;;; +1703;TAGALOG LETTER KA;Lo;0;L;;;;;N;;;;; +1704;TAGALOG LETTER GA;Lo;0;L;;;;;N;;;;; +1705;TAGALOG LETTER NGA;Lo;0;L;;;;;N;;;;; +1706;TAGALOG LETTER TA;Lo;0;L;;;;;N;;;;; +1707;TAGALOG LETTER DA;Lo;0;L;;;;;N;;;;; +1708;TAGALOG LETTER NA;Lo;0;L;;;;;N;;;;; +1709;TAGALOG LETTER PA;Lo;0;L;;;;;N;;;;; +170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;; +170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;; +170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;; +170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;; +170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;; +1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;; +1711;TAGALOG LETTER HA;Lo;0;L;;;;;N;;;;; +1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;; +1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;; +1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;; +1723;HANUNOO LETTER KA;Lo;0;L;;;;;N;;;;; +1724;HANUNOO LETTER GA;Lo;0;L;;;;;N;;;;; +1725;HANUNOO LETTER NGA;Lo;0;L;;;;;N;;;;; +1726;HANUNOO LETTER TA;Lo;0;L;;;;;N;;;;; +1727;HANUNOO LETTER DA;Lo;0;L;;;;;N;;;;; +1728;HANUNOO LETTER NA;Lo;0;L;;;;;N;;;;; +1729;HANUNOO LETTER PA;Lo;0;L;;;;;N;;;;; +172A;HANUNOO LETTER BA;Lo;0;L;;;;;N;;;;; +172B;HANUNOO LETTER MA;Lo;0;L;;;;;N;;;;; +172C;HANUNOO LETTER YA;Lo;0;L;;;;;N;;;;; +172D;HANUNOO LETTER RA;Lo;0;L;;;;;N;;;;; +172E;HANUNOO LETTER LA;Lo;0;L;;;;;N;;;;; +172F;HANUNOO LETTER WA;Lo;0;L;;;;;N;;;;; +1730;HANUNOO LETTER SA;Lo;0;L;;;;;N;;;;; +1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;; +1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;; +1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; +1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;; +1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;; +1741;BUHID LETTER I;Lo;0;L;;;;;N;;;;; +1742;BUHID LETTER U;Lo;0;L;;;;;N;;;;; +1743;BUHID LETTER KA;Lo;0;L;;;;;N;;;;; +1744;BUHID LETTER GA;Lo;0;L;;;;;N;;;;; +1745;BUHID LETTER NGA;Lo;0;L;;;;;N;;;;; +1746;BUHID LETTER TA;Lo;0;L;;;;;N;;;;; +1747;BUHID LETTER DA;Lo;0;L;;;;;N;;;;; +1748;BUHID LETTER NA;Lo;0;L;;;;;N;;;;; +1749;BUHID LETTER PA;Lo;0;L;;;;;N;;;;; +174A;BUHID LETTER BA;Lo;0;L;;;;;N;;;;; +174B;BUHID LETTER MA;Lo;0;L;;;;;N;;;;; +174C;BUHID LETTER YA;Lo;0;L;;;;;N;;;;; +174D;BUHID LETTER RA;Lo;0;L;;;;;N;;;;; +174E;BUHID LETTER LA;Lo;0;L;;;;;N;;;;; +174F;BUHID LETTER WA;Lo;0;L;;;;;N;;;;; +1750;BUHID LETTER SA;Lo;0;L;;;;;N;;;;; +1751;BUHID LETTER HA;Lo;0;L;;;;;N;;;;; +1752;BUHID VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1753;BUHID VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1760;TAGBANWA LETTER A;Lo;0;L;;;;;N;;;;; +1761;TAGBANWA LETTER I;Lo;0;L;;;;;N;;;;; +1762;TAGBANWA LETTER U;Lo;0;L;;;;;N;;;;; +1763;TAGBANWA LETTER KA;Lo;0;L;;;;;N;;;;; +1764;TAGBANWA LETTER GA;Lo;0;L;;;;;N;;;;; +1765;TAGBANWA LETTER NGA;Lo;0;L;;;;;N;;;;; +1766;TAGBANWA LETTER TA;Lo;0;L;;;;;N;;;;; +1767;TAGBANWA LETTER DA;Lo;0;L;;;;;N;;;;; +1768;TAGBANWA LETTER NA;Lo;0;L;;;;;N;;;;; +1769;TAGBANWA LETTER PA;Lo;0;L;;;;;N;;;;; +176A;TAGBANWA LETTER BA;Lo;0;L;;;;;N;;;;; +176B;TAGBANWA LETTER MA;Lo;0;L;;;;;N;;;;; +176C;TAGBANWA LETTER YA;Lo;0;L;;;;;N;;;;; +176E;TAGBANWA LETTER LA;Lo;0;L;;;;;N;;;;; +176F;TAGBANWA LETTER WA;Lo;0;L;;;;;N;;;;; +1770;TAGBANWA LETTER SA;Lo;0;L;;;;;N;;;;; +1772;TAGBANWA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1773;TAGBANWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1780;KHMER LETTER KA;Lo;0;L;;;;;N;;;;; +1781;KHMER LETTER KHA;Lo;0;L;;;;;N;;;;; +1782;KHMER LETTER KO;Lo;0;L;;;;;N;;;;; +1783;KHMER LETTER KHO;Lo;0;L;;;;;N;;;;; +1784;KHMER LETTER NGO;Lo;0;L;;;;;N;;;;; +1785;KHMER LETTER CA;Lo;0;L;;;;;N;;;;; +1786;KHMER LETTER CHA;Lo;0;L;;;;;N;;;;; +1787;KHMER LETTER CO;Lo;0;L;;;;;N;;;;; +1788;KHMER LETTER CHO;Lo;0;L;;;;;N;;;;; +1789;KHMER LETTER NYO;Lo;0;L;;;;;N;;;;; +178A;KHMER LETTER DA;Lo;0;L;;;;;N;;;;; +178B;KHMER LETTER TTHA;Lo;0;L;;;;;N;;;;; +178C;KHMER LETTER DO;Lo;0;L;;;;;N;;;;; +178D;KHMER LETTER TTHO;Lo;0;L;;;;;N;;;;; +178E;KHMER LETTER NNO;Lo;0;L;;;;;N;;;;; +178F;KHMER LETTER TA;Lo;0;L;;;;;N;;;;; +1790;KHMER LETTER THA;Lo;0;L;;;;;N;;;;; +1791;KHMER LETTER TO;Lo;0;L;;;;;N;;;;; +1792;KHMER LETTER THO;Lo;0;L;;;;;N;;;;; +1793;KHMER LETTER NO;Lo;0;L;;;;;N;;;;; +1794;KHMER LETTER BA;Lo;0;L;;;;;N;;;;; +1795;KHMER LETTER PHA;Lo;0;L;;;;;N;;;;; +1796;KHMER LETTER PO;Lo;0;L;;;;;N;;;;; +1797;KHMER LETTER PHO;Lo;0;L;;;;;N;;;;; +1798;KHMER LETTER MO;Lo;0;L;;;;;N;;;;; +1799;KHMER LETTER YO;Lo;0;L;;;;;N;;;;; +179A;KHMER LETTER RO;Lo;0;L;;;;;N;;;;; +179B;KHMER LETTER LO;Lo;0;L;;;;;N;;;;; +179C;KHMER LETTER VO;Lo;0;L;;;;;N;;;;; +179D;KHMER LETTER SHA;Lo;0;L;;;;;N;;;;; +179E;KHMER LETTER SSO;Lo;0;L;;;;;N;;;;; +179F;KHMER LETTER SA;Lo;0;L;;;;;N;;;;; +17A0;KHMER LETTER HA;Lo;0;L;;;;;N;;;;; +17A1;KHMER LETTER LA;Lo;0;L;;;;;N;;;;; +17A2;KHMER LETTER QA;Lo;0;L;;;;;N;;;;; +17A3;KHMER INDEPENDENT VOWEL QAQ;Lo;0;L;;;;;N;;;;; +17A4;KHMER INDEPENDENT VOWEL QAA;Lo;0;L;;;;;N;;;;; +17A5;KHMER INDEPENDENT VOWEL QI;Lo;0;L;;;;;N;;;;; +17A6;KHMER INDEPENDENT VOWEL QII;Lo;0;L;;;;;N;;;;; +17A7;KHMER INDEPENDENT VOWEL QU;Lo;0;L;;;;;N;;;;; +17A8;KHMER INDEPENDENT VOWEL QUK;Lo;0;L;;;;;N;;;;; +17A9;KHMER INDEPENDENT VOWEL QUU;Lo;0;L;;;;;N;;;;; +17AA;KHMER INDEPENDENT VOWEL QUUV;Lo;0;L;;;;;N;;;;; +17AB;KHMER INDEPENDENT VOWEL RY;Lo;0;L;;;;;N;;;;; +17AC;KHMER INDEPENDENT VOWEL RYY;Lo;0;L;;;;;N;;;;; +17AD;KHMER INDEPENDENT VOWEL LY;Lo;0;L;;;;;N;;;;; +17AE;KHMER INDEPENDENT VOWEL LYY;Lo;0;L;;;;;N;;;;; +17AF;KHMER INDEPENDENT VOWEL QE;Lo;0;L;;;;;N;;;;; +17B0;KHMER INDEPENDENT VOWEL QAI;Lo;0;L;;;;;N;;;;; +17B1;KHMER INDEPENDENT VOWEL QOO TYPE ONE;Lo;0;L;;;;;N;;;;; +17B2;KHMER INDEPENDENT VOWEL QOO TYPE TWO;Lo;0;L;;;;;N;;;;; +17B3;KHMER INDEPENDENT VOWEL QAU;Lo;0;L;;;;;N;;;;; +17B4;KHMER VOWEL INHERENT AQ;Mn;0;NSM;;;;;N;;;;; +17B5;KHMER VOWEL INHERENT AA;Mn;0;NSM;;;;;N;;;;; +17B6;KHMER VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +17B7;KHMER VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +17B8;KHMER VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +17B9;KHMER VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; +17BA;KHMER VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; +17BB;KHMER VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +17BC;KHMER VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +17BD;KHMER VOWEL SIGN UA;Mn;0;NSM;;;;;N;;;;; +17BE;KHMER VOWEL SIGN OE;Mc;0;L;;;;;N;;;;; +17BF;KHMER VOWEL SIGN YA;Mc;0;L;;;;;N;;;;; +17C0;KHMER VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; +17C1;KHMER VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +17C2;KHMER VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; +17C3;KHMER VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +17C4;KHMER VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +17C5;KHMER VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +17C6;KHMER SIGN NIKAHIT;Mn;0;NSM;;;;;N;;;;; +17C7;KHMER SIGN REAHMUK;Mc;0;L;;;;;N;;;;; +17C8;KHMER SIGN YUUKALEAPINTU;Mc;0;L;;;;;N;;;;; +17C9;KHMER SIGN MUUSIKATOAN;Mn;0;NSM;;;;;N;;;;; +17CA;KHMER SIGN TRIISAP;Mn;0;NSM;;;;;N;;;;; +17CB;KHMER SIGN BANTOC;Mn;0;NSM;;;;;N;;;;; +17CC;KHMER SIGN ROBAT;Mn;0;NSM;;;;;N;;;;; +17CD;KHMER SIGN TOANDAKHIAT;Mn;0;NSM;;;;;N;;;;; +17CE;KHMER SIGN KAKABAT;Mn;0;NSM;;;;;N;;;;; +17CF;KHMER SIGN AHSDA;Mn;0;NSM;;;;;N;;;;; +17D0;KHMER SIGN SAMYOK SANNYA;Mn;0;NSM;;;;;N;;;;; +17D1;KHMER SIGN VIRIAM;Mn;0;NSM;;;;;N;;;;; +17D2;KHMER SIGN COENG;Mn;9;NSM;;;;;N;;;;; +17D3;KHMER SIGN BATHAMASAT;Mn;0;NSM;;;;;N;;;;; +17D4;KHMER SIGN KHAN;Po;0;L;;;;;N;;;;; +17D5;KHMER SIGN BARIYOOSAN;Po;0;L;;;;;N;;;;; +17D6;KHMER SIGN CAMNUC PII KUUH;Po;0;L;;;;;N;;;;; +17D7;KHMER SIGN LEK TOO;Lm;0;L;;;;;N;;;;; +17D8;KHMER SIGN BEYYAL;Po;0;L;;;;;N;;;;; +17D9;KHMER SIGN PHNAEK MUAN;Po;0;L;;;;;N;;;;; +17DA;KHMER SIGN KOOMUUT;Po;0;L;;;;;N;;;;; +17DB;KHMER CURRENCY SYMBOL RIEL;Sc;0;ET;;;;;N;;;;; +17DC;KHMER SIGN AVAKRAHASANYA;Lo;0;L;;;;;N;;;;; +17DD;KHMER SIGN ATTHACAN;Mn;230;NSM;;;;;N;;;;; +17E0;KHMER DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +17E1;KHMER DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +17E2;KHMER DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +17E3;KHMER DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +17E4;KHMER DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +17E5;KHMER DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +17E6;KHMER DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +17E7;KHMER DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +17E8;KHMER DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +17E9;KHMER DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +17F0;KHMER SYMBOL LEK ATTAK SON;No;0;ON;;;;0;N;;;;; +17F1;KHMER SYMBOL LEK ATTAK MUOY;No;0;ON;;;;1;N;;;;; +17F2;KHMER SYMBOL LEK ATTAK PII;No;0;ON;;;;2;N;;;;; +17F3;KHMER SYMBOL LEK ATTAK BEI;No;0;ON;;;;3;N;;;;; +17F4;KHMER SYMBOL LEK ATTAK BUON;No;0;ON;;;;4;N;;;;; +17F5;KHMER SYMBOL LEK ATTAK PRAM;No;0;ON;;;;5;N;;;;; +17F6;KHMER SYMBOL LEK ATTAK PRAM-MUOY;No;0;ON;;;;6;N;;;;; +17F7;KHMER SYMBOL LEK ATTAK PRAM-PII;No;0;ON;;;;7;N;;;;; +17F8;KHMER SYMBOL LEK ATTAK PRAM-BEI;No;0;ON;;;;8;N;;;;; +17F9;KHMER SYMBOL LEK ATTAK PRAM-BUON;No;0;ON;;;;9;N;;;;; +1800;MONGOLIAN BIRGA;Po;0;ON;;;;;N;;;;; +1801;MONGOLIAN ELLIPSIS;Po;0;ON;;;;;N;;;;; +1802;MONGOLIAN COMMA;Po;0;ON;;;;;N;;;;; +1803;MONGOLIAN FULL STOP;Po;0;ON;;;;;N;;;;; +1804;MONGOLIAN COLON;Po;0;ON;;;;;N;;;;; +1805;MONGOLIAN FOUR DOTS;Po;0;ON;;;;;N;;;;; +1806;MONGOLIAN TODO SOFT HYPHEN;Pd;0;ON;;;;;N;;;;; +1807;MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER;Po;0;ON;;;;;N;;;;; +1808;MONGOLIAN MANCHU COMMA;Po;0;ON;;;;;N;;;;; +1809;MONGOLIAN MANCHU FULL STOP;Po;0;ON;;;;;N;;;;; +180A;MONGOLIAN NIRUGU;Po;0;ON;;;;;N;;;;; +180B;MONGOLIAN FREE VARIATION SELECTOR ONE;Mn;0;NSM;;;;;N;;;;; +180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;; +180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;; +180E;MONGOLIAN VOWEL SEPARATOR;Cf;0;BN;;;;;N;;;;; +1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1813;MONGOLIAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1814;MONGOLIAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1815;MONGOLIAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1816;MONGOLIAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1817;MONGOLIAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1818;MONGOLIAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1819;MONGOLIAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1820;MONGOLIAN LETTER A;Lo;0;L;;;;;N;;;;; +1821;MONGOLIAN LETTER E;Lo;0;L;;;;;N;;;;; +1822;MONGOLIAN LETTER I;Lo;0;L;;;;;N;;;;; +1823;MONGOLIAN LETTER O;Lo;0;L;;;;;N;;;;; +1824;MONGOLIAN LETTER U;Lo;0;L;;;;;N;;;;; +1825;MONGOLIAN LETTER OE;Lo;0;L;;;;;N;;;;; +1826;MONGOLIAN LETTER UE;Lo;0;L;;;;;N;;;;; +1827;MONGOLIAN LETTER EE;Lo;0;L;;;;;N;;;;; +1828;MONGOLIAN LETTER NA;Lo;0;L;;;;;N;;;;; +1829;MONGOLIAN LETTER ANG;Lo;0;L;;;;;N;;;;; +182A;MONGOLIAN LETTER BA;Lo;0;L;;;;;N;;;;; +182B;MONGOLIAN LETTER PA;Lo;0;L;;;;;N;;;;; +182C;MONGOLIAN LETTER QA;Lo;0;L;;;;;N;;;;; +182D;MONGOLIAN LETTER GA;Lo;0;L;;;;;N;;;;; +182E;MONGOLIAN LETTER MA;Lo;0;L;;;;;N;;;;; +182F;MONGOLIAN LETTER LA;Lo;0;L;;;;;N;;;;; +1830;MONGOLIAN LETTER SA;Lo;0;L;;;;;N;;;;; +1831;MONGOLIAN LETTER SHA;Lo;0;L;;;;;N;;;;; +1832;MONGOLIAN LETTER TA;Lo;0;L;;;;;N;;;;; +1833;MONGOLIAN LETTER DA;Lo;0;L;;;;;N;;;;; +1834;MONGOLIAN LETTER CHA;Lo;0;L;;;;;N;;;;; +1835;MONGOLIAN LETTER JA;Lo;0;L;;;;;N;;;;; +1836;MONGOLIAN LETTER YA;Lo;0;L;;;;;N;;;;; +1837;MONGOLIAN LETTER RA;Lo;0;L;;;;;N;;;;; +1838;MONGOLIAN LETTER WA;Lo;0;L;;;;;N;;;;; +1839;MONGOLIAN LETTER FA;Lo;0;L;;;;;N;;;;; +183A;MONGOLIAN LETTER KA;Lo;0;L;;;;;N;;;;; +183B;MONGOLIAN LETTER KHA;Lo;0;L;;;;;N;;;;; +183C;MONGOLIAN LETTER TSA;Lo;0;L;;;;;N;;;;; +183D;MONGOLIAN LETTER ZA;Lo;0;L;;;;;N;;;;; +183E;MONGOLIAN LETTER HAA;Lo;0;L;;;;;N;;;;; +183F;MONGOLIAN LETTER ZRA;Lo;0;L;;;;;N;;;;; +1840;MONGOLIAN LETTER LHA;Lo;0;L;;;;;N;;;;; +1841;MONGOLIAN LETTER ZHI;Lo;0;L;;;;;N;;;;; +1842;MONGOLIAN LETTER CHI;Lo;0;L;;;;;N;;;;; +1843;MONGOLIAN LETTER TODO LONG VOWEL SIGN;Lm;0;L;;;;;N;;;;; +1844;MONGOLIAN LETTER TODO E;Lo;0;L;;;;;N;;;;; +1845;MONGOLIAN LETTER TODO I;Lo;0;L;;;;;N;;;;; +1846;MONGOLIAN LETTER TODO O;Lo;0;L;;;;;N;;;;; +1847;MONGOLIAN LETTER TODO U;Lo;0;L;;;;;N;;;;; +1848;MONGOLIAN LETTER TODO OE;Lo;0;L;;;;;N;;;;; +1849;MONGOLIAN LETTER TODO UE;Lo;0;L;;;;;N;;;;; +184A;MONGOLIAN LETTER TODO ANG;Lo;0;L;;;;;N;;;;; +184B;MONGOLIAN LETTER TODO BA;Lo;0;L;;;;;N;;;;; +184C;MONGOLIAN LETTER TODO PA;Lo;0;L;;;;;N;;;;; +184D;MONGOLIAN LETTER TODO QA;Lo;0;L;;;;;N;;;;; +184E;MONGOLIAN LETTER TODO GA;Lo;0;L;;;;;N;;;;; +184F;MONGOLIAN LETTER TODO MA;Lo;0;L;;;;;N;;;;; +1850;MONGOLIAN LETTER TODO TA;Lo;0;L;;;;;N;;;;; +1851;MONGOLIAN LETTER TODO DA;Lo;0;L;;;;;N;;;;; +1852;MONGOLIAN LETTER TODO CHA;Lo;0;L;;;;;N;;;;; +1853;MONGOLIAN LETTER TODO JA;Lo;0;L;;;;;N;;;;; +1854;MONGOLIAN LETTER TODO TSA;Lo;0;L;;;;;N;;;;; +1855;MONGOLIAN LETTER TODO YA;Lo;0;L;;;;;N;;;;; +1856;MONGOLIAN LETTER TODO WA;Lo;0;L;;;;;N;;;;; +1857;MONGOLIAN LETTER TODO KA;Lo;0;L;;;;;N;;;;; +1858;MONGOLIAN LETTER TODO GAA;Lo;0;L;;;;;N;;;;; +1859;MONGOLIAN LETTER TODO HAA;Lo;0;L;;;;;N;;;;; +185A;MONGOLIAN LETTER TODO JIA;Lo;0;L;;;;;N;;;;; +185B;MONGOLIAN LETTER TODO NIA;Lo;0;L;;;;;N;;;;; +185C;MONGOLIAN LETTER TODO DZA;Lo;0;L;;;;;N;;;;; +185D;MONGOLIAN LETTER SIBE E;Lo;0;L;;;;;N;;;;; +185E;MONGOLIAN LETTER SIBE I;Lo;0;L;;;;;N;;;;; +185F;MONGOLIAN LETTER SIBE IY;Lo;0;L;;;;;N;;;;; +1860;MONGOLIAN LETTER SIBE UE;Lo;0;L;;;;;N;;;;; +1861;MONGOLIAN LETTER SIBE U;Lo;0;L;;;;;N;;;;; +1862;MONGOLIAN LETTER SIBE ANG;Lo;0;L;;;;;N;;;;; +1863;MONGOLIAN LETTER SIBE KA;Lo;0;L;;;;;N;;;;; +1864;MONGOLIAN LETTER SIBE GA;Lo;0;L;;;;;N;;;;; +1865;MONGOLIAN LETTER SIBE HA;Lo;0;L;;;;;N;;;;; +1866;MONGOLIAN LETTER SIBE PA;Lo;0;L;;;;;N;;;;; +1867;MONGOLIAN LETTER SIBE SHA;Lo;0;L;;;;;N;;;;; +1868;MONGOLIAN LETTER SIBE TA;Lo;0;L;;;;;N;;;;; +1869;MONGOLIAN LETTER SIBE DA;Lo;0;L;;;;;N;;;;; +186A;MONGOLIAN LETTER SIBE JA;Lo;0;L;;;;;N;;;;; +186B;MONGOLIAN LETTER SIBE FA;Lo;0;L;;;;;N;;;;; +186C;MONGOLIAN LETTER SIBE GAA;Lo;0;L;;;;;N;;;;; +186D;MONGOLIAN LETTER SIBE HAA;Lo;0;L;;;;;N;;;;; +186E;MONGOLIAN LETTER SIBE TSA;Lo;0;L;;;;;N;;;;; +186F;MONGOLIAN LETTER SIBE ZA;Lo;0;L;;;;;N;;;;; +1870;MONGOLIAN LETTER SIBE RAA;Lo;0;L;;;;;N;;;;; +1871;MONGOLIAN LETTER SIBE CHA;Lo;0;L;;;;;N;;;;; +1872;MONGOLIAN LETTER SIBE ZHA;Lo;0;L;;;;;N;;;;; +1873;MONGOLIAN LETTER MANCHU I;Lo;0;L;;;;;N;;;;; +1874;MONGOLIAN LETTER MANCHU KA;Lo;0;L;;;;;N;;;;; +1875;MONGOLIAN LETTER MANCHU RA;Lo;0;L;;;;;N;;;;; +1876;MONGOLIAN LETTER MANCHU FA;Lo;0;L;;;;;N;;;;; +1877;MONGOLIAN LETTER MANCHU ZHA;Lo;0;L;;;;;N;;;;; +1880;MONGOLIAN LETTER ALI GALI ANUSVARA ONE;Lo;0;L;;;;;N;;;;; +1881;MONGOLIAN LETTER ALI GALI VISARGA ONE;Lo;0;L;;;;;N;;;;; +1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;; +1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;; +1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;; +1885;MONGOLIAN LETTER ALI GALI BALUDA;Mn;0;NSM;;;;;N;;;;; +1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Mn;0;NSM;;;;;N;;;;; +1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;; +1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;; +1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;; +188A;MONGOLIAN LETTER ALI GALI NGA;Lo;0;L;;;;;N;;;;; +188B;MONGOLIAN LETTER ALI GALI CA;Lo;0;L;;;;;N;;;;; +188C;MONGOLIAN LETTER ALI GALI TTA;Lo;0;L;;;;;N;;;;; +188D;MONGOLIAN LETTER ALI GALI TTHA;Lo;0;L;;;;;N;;;;; +188E;MONGOLIAN LETTER ALI GALI DDA;Lo;0;L;;;;;N;;;;; +188F;MONGOLIAN LETTER ALI GALI NNA;Lo;0;L;;;;;N;;;;; +1890;MONGOLIAN LETTER ALI GALI TA;Lo;0;L;;;;;N;;;;; +1891;MONGOLIAN LETTER ALI GALI DA;Lo;0;L;;;;;N;;;;; +1892;MONGOLIAN LETTER ALI GALI PA;Lo;0;L;;;;;N;;;;; +1893;MONGOLIAN LETTER ALI GALI PHA;Lo;0;L;;;;;N;;;;; +1894;MONGOLIAN LETTER ALI GALI SSA;Lo;0;L;;;;;N;;;;; +1895;MONGOLIAN LETTER ALI GALI ZHA;Lo;0;L;;;;;N;;;;; +1896;MONGOLIAN LETTER ALI GALI ZA;Lo;0;L;;;;;N;;;;; +1897;MONGOLIAN LETTER ALI GALI AH;Lo;0;L;;;;;N;;;;; +1898;MONGOLIAN LETTER TODO ALI GALI TA;Lo;0;L;;;;;N;;;;; +1899;MONGOLIAN LETTER TODO ALI GALI ZHA;Lo;0;L;;;;;N;;;;; +189A;MONGOLIAN LETTER MANCHU ALI GALI GHA;Lo;0;L;;;;;N;;;;; +189B;MONGOLIAN LETTER MANCHU ALI GALI NGA;Lo;0;L;;;;;N;;;;; +189C;MONGOLIAN LETTER MANCHU ALI GALI CA;Lo;0;L;;;;;N;;;;; +189D;MONGOLIAN LETTER MANCHU ALI GALI JHA;Lo;0;L;;;;;N;;;;; +189E;MONGOLIAN LETTER MANCHU ALI GALI TTA;Lo;0;L;;;;;N;;;;; +189F;MONGOLIAN LETTER MANCHU ALI GALI DDHA;Lo;0;L;;;;;N;;;;; +18A0;MONGOLIAN LETTER MANCHU ALI GALI TA;Lo;0;L;;;;;N;;;;; +18A1;MONGOLIAN LETTER MANCHU ALI GALI DHA;Lo;0;L;;;;;N;;;;; +18A2;MONGOLIAN LETTER MANCHU ALI GALI SSA;Lo;0;L;;;;;N;;;;; +18A3;MONGOLIAN LETTER MANCHU ALI GALI CYA;Lo;0;L;;;;;N;;;;; +18A4;MONGOLIAN LETTER MANCHU ALI GALI ZHA;Lo;0;L;;;;;N;;;;; +18A5;MONGOLIAN LETTER MANCHU ALI GALI ZA;Lo;0;L;;;;;N;;;;; +18A6;MONGOLIAN LETTER ALI GALI HALF U;Lo;0;L;;;;;N;;;;; +18A7;MONGOLIAN LETTER ALI GALI HALF YA;Lo;0;L;;;;;N;;;;; +18A8;MONGOLIAN LETTER MANCHU ALI GALI BHA;Lo;0;L;;;;;N;;;;; +18A9;MONGOLIAN LETTER ALI GALI DAGALGA;Mn;228;NSM;;;;;N;;;;; +18AA;MONGOLIAN LETTER MANCHU ALI GALI LHA;Lo;0;L;;;;;N;;;;; +18B0;CANADIAN SYLLABICS OY;Lo;0;L;;;;;N;;;;; +18B1;CANADIAN SYLLABICS AY;Lo;0;L;;;;;N;;;;; +18B2;CANADIAN SYLLABICS AAY;Lo;0;L;;;;;N;;;;; +18B3;CANADIAN SYLLABICS WAY;Lo;0;L;;;;;N;;;;; +18B4;CANADIAN SYLLABICS POY;Lo;0;L;;;;;N;;;;; +18B5;CANADIAN SYLLABICS PAY;Lo;0;L;;;;;N;;;;; +18B6;CANADIAN SYLLABICS PWOY;Lo;0;L;;;;;N;;;;; +18B7;CANADIAN SYLLABICS TAY;Lo;0;L;;;;;N;;;;; +18B8;CANADIAN SYLLABICS KAY;Lo;0;L;;;;;N;;;;; +18B9;CANADIAN SYLLABICS KWAY;Lo;0;L;;;;;N;;;;; +18BA;CANADIAN SYLLABICS MAY;Lo;0;L;;;;;N;;;;; +18BB;CANADIAN SYLLABICS NOY;Lo;0;L;;;;;N;;;;; +18BC;CANADIAN SYLLABICS NAY;Lo;0;L;;;;;N;;;;; +18BD;CANADIAN SYLLABICS LAY;Lo;0;L;;;;;N;;;;; +18BE;CANADIAN SYLLABICS SOY;Lo;0;L;;;;;N;;;;; +18BF;CANADIAN SYLLABICS SAY;Lo;0;L;;;;;N;;;;; +18C0;CANADIAN SYLLABICS SHOY;Lo;0;L;;;;;N;;;;; +18C1;CANADIAN SYLLABICS SHAY;Lo;0;L;;;;;N;;;;; +18C2;CANADIAN SYLLABICS SHWOY;Lo;0;L;;;;;N;;;;; +18C3;CANADIAN SYLLABICS YOY;Lo;0;L;;;;;N;;;;; +18C4;CANADIAN SYLLABICS YAY;Lo;0;L;;;;;N;;;;; +18C5;CANADIAN SYLLABICS RAY;Lo;0;L;;;;;N;;;;; +18C6;CANADIAN SYLLABICS NWI;Lo;0;L;;;;;N;;;;; +18C7;CANADIAN SYLLABICS OJIBWAY NWI;Lo;0;L;;;;;N;;;;; +18C8;CANADIAN SYLLABICS NWII;Lo;0;L;;;;;N;;;;; +18C9;CANADIAN SYLLABICS OJIBWAY NWII;Lo;0;L;;;;;N;;;;; +18CA;CANADIAN SYLLABICS NWO;Lo;0;L;;;;;N;;;;; +18CB;CANADIAN SYLLABICS OJIBWAY NWO;Lo;0;L;;;;;N;;;;; +18CC;CANADIAN SYLLABICS NWOO;Lo;0;L;;;;;N;;;;; +18CD;CANADIAN SYLLABICS OJIBWAY NWOO;Lo;0;L;;;;;N;;;;; +18CE;CANADIAN SYLLABICS RWEE;Lo;0;L;;;;;N;;;;; +18CF;CANADIAN SYLLABICS RWI;Lo;0;L;;;;;N;;;;; +18D0;CANADIAN SYLLABICS RWII;Lo;0;L;;;;;N;;;;; +18D1;CANADIAN SYLLABICS RWO;Lo;0;L;;;;;N;;;;; +18D2;CANADIAN SYLLABICS RWOO;Lo;0;L;;;;;N;;;;; +18D3;CANADIAN SYLLABICS RWA;Lo;0;L;;;;;N;;;;; +18D4;CANADIAN SYLLABICS OJIBWAY P;Lo;0;L;;;;;N;;;;; +18D5;CANADIAN SYLLABICS OJIBWAY T;Lo;0;L;;;;;N;;;;; +18D6;CANADIAN SYLLABICS OJIBWAY K;Lo;0;L;;;;;N;;;;; +18D7;CANADIAN SYLLABICS OJIBWAY C;Lo;0;L;;;;;N;;;;; +18D8;CANADIAN SYLLABICS OJIBWAY M;Lo;0;L;;;;;N;;;;; +18D9;CANADIAN SYLLABICS OJIBWAY N;Lo;0;L;;;;;N;;;;; +18DA;CANADIAN SYLLABICS OJIBWAY S;Lo;0;L;;;;;N;;;;; +18DB;CANADIAN SYLLABICS OJIBWAY SH;Lo;0;L;;;;;N;;;;; +18DC;CANADIAN SYLLABICS EASTERN W;Lo;0;L;;;;;N;;;;; +18DD;CANADIAN SYLLABICS WESTERN W;Lo;0;L;;;;;N;;;;; +18DE;CANADIAN SYLLABICS FINAL SMALL RING;Lo;0;L;;;;;N;;;;; +18DF;CANADIAN SYLLABICS FINAL RAISED DOT;Lo;0;L;;;;;N;;;;; +18E0;CANADIAN SYLLABICS R-CREE RWE;Lo;0;L;;;;;N;;;;; +18E1;CANADIAN SYLLABICS WEST-CREE LOO;Lo;0;L;;;;;N;;;;; +18E2;CANADIAN SYLLABICS WEST-CREE LAA;Lo;0;L;;;;;N;;;;; +18E3;CANADIAN SYLLABICS THWE;Lo;0;L;;;;;N;;;;; +18E4;CANADIAN SYLLABICS THWA;Lo;0;L;;;;;N;;;;; +18E5;CANADIAN SYLLABICS TTHWE;Lo;0;L;;;;;N;;;;; +18E6;CANADIAN SYLLABICS TTHOO;Lo;0;L;;;;;N;;;;; +18E7;CANADIAN SYLLABICS TTHAA;Lo;0;L;;;;;N;;;;; +18E8;CANADIAN SYLLABICS TLHWE;Lo;0;L;;;;;N;;;;; +18E9;CANADIAN SYLLABICS TLHOO;Lo;0;L;;;;;N;;;;; +18EA;CANADIAN SYLLABICS SAYISI SHWE;Lo;0;L;;;;;N;;;;; +18EB;CANADIAN SYLLABICS SAYISI SHOO;Lo;0;L;;;;;N;;;;; +18EC;CANADIAN SYLLABICS SAYISI HOO;Lo;0;L;;;;;N;;;;; +18ED;CANADIAN SYLLABICS CARRIER GWU;Lo;0;L;;;;;N;;;;; +18EE;CANADIAN SYLLABICS CARRIER DENE GEE;Lo;0;L;;;;;N;;;;; +18EF;CANADIAN SYLLABICS CARRIER GAA;Lo;0;L;;;;;N;;;;; +18F0;CANADIAN SYLLABICS CARRIER GWA;Lo;0;L;;;;;N;;;;; +18F1;CANADIAN SYLLABICS SAYISI JUU;Lo;0;L;;;;;N;;;;; +18F2;CANADIAN SYLLABICS CARRIER JWA;Lo;0;L;;;;;N;;;;; +18F3;CANADIAN SYLLABICS BEAVER DENE L;Lo;0;L;;;;;N;;;;; +18F4;CANADIAN SYLLABICS BEAVER DENE R;Lo;0;L;;;;;N;;;;; +18F5;CANADIAN SYLLABICS CARRIER DENTAL S;Lo;0;L;;;;;N;;;;; +1900;LIMBU VOWEL-CARRIER LETTER;Lo;0;L;;;;;N;;;;; +1901;LIMBU LETTER KA;Lo;0;L;;;;;N;;;;; +1902;LIMBU LETTER KHA;Lo;0;L;;;;;N;;;;; +1903;LIMBU LETTER GA;Lo;0;L;;;;;N;;;;; +1904;LIMBU LETTER GHA;Lo;0;L;;;;;N;;;;; +1905;LIMBU LETTER NGA;Lo;0;L;;;;;N;;;;; +1906;LIMBU LETTER CA;Lo;0;L;;;;;N;;;;; +1907;LIMBU LETTER CHA;Lo;0;L;;;;;N;;;;; +1908;LIMBU LETTER JA;Lo;0;L;;;;;N;;;;; +1909;LIMBU LETTER JHA;Lo;0;L;;;;;N;;;;; +190A;LIMBU LETTER YAN;Lo;0;L;;;;;N;;;;; +190B;LIMBU LETTER TA;Lo;0;L;;;;;N;;;;; +190C;LIMBU LETTER THA;Lo;0;L;;;;;N;;;;; +190D;LIMBU LETTER DA;Lo;0;L;;;;;N;;;;; +190E;LIMBU LETTER DHA;Lo;0;L;;;;;N;;;;; +190F;LIMBU LETTER NA;Lo;0;L;;;;;N;;;;; +1910;LIMBU LETTER PA;Lo;0;L;;;;;N;;;;; +1911;LIMBU LETTER PHA;Lo;0;L;;;;;N;;;;; +1912;LIMBU LETTER BA;Lo;0;L;;;;;N;;;;; +1913;LIMBU LETTER BHA;Lo;0;L;;;;;N;;;;; +1914;LIMBU LETTER MA;Lo;0;L;;;;;N;;;;; +1915;LIMBU LETTER YA;Lo;0;L;;;;;N;;;;; +1916;LIMBU LETTER RA;Lo;0;L;;;;;N;;;;; +1917;LIMBU LETTER LA;Lo;0;L;;;;;N;;;;; +1918;LIMBU LETTER WA;Lo;0;L;;;;;N;;;;; +1919;LIMBU LETTER SHA;Lo;0;L;;;;;N;;;;; +191A;LIMBU LETTER SSA;Lo;0;L;;;;;N;;;;; +191B;LIMBU LETTER SA;Lo;0;L;;;;;N;;;;; +191C;LIMBU LETTER HA;Lo;0;L;;;;;N;;;;; +191D;LIMBU LETTER GYAN;Lo;0;L;;;;;N;;;;; +191E;LIMBU LETTER TRA;Lo;0;L;;;;;N;;;;; +1920;LIMBU VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; +1921;LIMBU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1922;LIMBU VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1923;LIMBU VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +1924;LIMBU VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +1925;LIMBU VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +1926;LIMBU VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +1927;LIMBU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1928;LIMBU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +1929;LIMBU SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; +192A;LIMBU SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; +192B;LIMBU SUBJOINED LETTER WA;Mc;0;L;;;;;N;;;;; +1930;LIMBU SMALL LETTER KA;Mc;0;L;;;;;N;;;;; +1931;LIMBU SMALL LETTER NGA;Mc;0;L;;;;;N;;;;; +1932;LIMBU SMALL LETTER ANUSVARA;Mn;0;NSM;;;;;N;;;;; +1933;LIMBU SMALL LETTER TA;Mc;0;L;;;;;N;;;;; +1934;LIMBU SMALL LETTER NA;Mc;0;L;;;;;N;;;;; +1935;LIMBU SMALL LETTER PA;Mc;0;L;;;;;N;;;;; +1936;LIMBU SMALL LETTER MA;Mc;0;L;;;;;N;;;;; +1937;LIMBU SMALL LETTER RA;Mc;0;L;;;;;N;;;;; +1938;LIMBU SMALL LETTER LA;Mc;0;L;;;;;N;;;;; +1939;LIMBU SIGN MUKPHRENG;Mn;222;NSM;;;;;N;;;;; +193A;LIMBU SIGN KEMPHRENG;Mn;230;NSM;;;;;N;;;;; +193B;LIMBU SIGN SA-I;Mn;220;NSM;;;;;N;;;;; +1940;LIMBU SIGN LOO;So;0;ON;;;;;N;;;;; +1944;LIMBU EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +1945;LIMBU QUESTION MARK;Po;0;ON;;;;;N;;;;; +1946;LIMBU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1947;LIMBU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1948;LIMBU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1949;LIMBU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +194A;LIMBU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +194B;LIMBU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +194C;LIMBU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +194D;LIMBU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +194E;LIMBU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +194F;LIMBU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1950;TAI LE LETTER KA;Lo;0;L;;;;;N;;;;; +1951;TAI LE LETTER XA;Lo;0;L;;;;;N;;;;; +1952;TAI LE LETTER NGA;Lo;0;L;;;;;N;;;;; +1953;TAI LE LETTER TSA;Lo;0;L;;;;;N;;;;; +1954;TAI LE LETTER SA;Lo;0;L;;;;;N;;;;; +1955;TAI LE LETTER YA;Lo;0;L;;;;;N;;;;; +1956;TAI LE LETTER TA;Lo;0;L;;;;;N;;;;; +1957;TAI LE LETTER THA;Lo;0;L;;;;;N;;;;; +1958;TAI LE LETTER LA;Lo;0;L;;;;;N;;;;; +1959;TAI LE LETTER PA;Lo;0;L;;;;;N;;;;; +195A;TAI LE LETTER PHA;Lo;0;L;;;;;N;;;;; +195B;TAI LE LETTER MA;Lo;0;L;;;;;N;;;;; +195C;TAI LE LETTER FA;Lo;0;L;;;;;N;;;;; +195D;TAI LE LETTER VA;Lo;0;L;;;;;N;;;;; +195E;TAI LE LETTER HA;Lo;0;L;;;;;N;;;;; +195F;TAI LE LETTER QA;Lo;0;L;;;;;N;;;;; +1960;TAI LE LETTER KHA;Lo;0;L;;;;;N;;;;; +1961;TAI LE LETTER TSHA;Lo;0;L;;;;;N;;;;; +1962;TAI LE LETTER NA;Lo;0;L;;;;;N;;;;; +1963;TAI LE LETTER A;Lo;0;L;;;;;N;;;;; +1964;TAI LE LETTER I;Lo;0;L;;;;;N;;;;; +1965;TAI LE LETTER EE;Lo;0;L;;;;;N;;;;; +1966;TAI LE LETTER EH;Lo;0;L;;;;;N;;;;; +1967;TAI LE LETTER U;Lo;0;L;;;;;N;;;;; +1968;TAI LE LETTER OO;Lo;0;L;;;;;N;;;;; +1969;TAI LE LETTER O;Lo;0;L;;;;;N;;;;; +196A;TAI LE LETTER UE;Lo;0;L;;;;;N;;;;; +196B;TAI LE LETTER E;Lo;0;L;;;;;N;;;;; +196C;TAI LE LETTER AUE;Lo;0;L;;;;;N;;;;; +196D;TAI LE LETTER AI;Lo;0;L;;;;;N;;;;; +1970;TAI LE LETTER TONE-2;Lo;0;L;;;;;N;;;;; +1971;TAI LE LETTER TONE-3;Lo;0;L;;;;;N;;;;; +1972;TAI LE LETTER TONE-4;Lo;0;L;;;;;N;;;;; +1973;TAI LE LETTER TONE-5;Lo;0;L;;;;;N;;;;; +1974;TAI LE LETTER TONE-6;Lo;0;L;;;;;N;;;;; +1980;NEW TAI LUE LETTER HIGH QA;Lo;0;L;;;;;N;;;;; +1981;NEW TAI LUE LETTER LOW QA;Lo;0;L;;;;;N;;;;; +1982;NEW TAI LUE LETTER HIGH KA;Lo;0;L;;;;;N;;;;; +1983;NEW TAI LUE LETTER HIGH XA;Lo;0;L;;;;;N;;;;; +1984;NEW TAI LUE LETTER HIGH NGA;Lo;0;L;;;;;N;;;;; +1985;NEW TAI LUE LETTER LOW KA;Lo;0;L;;;;;N;;;;; +1986;NEW TAI LUE LETTER LOW XA;Lo;0;L;;;;;N;;;;; +1987;NEW TAI LUE LETTER LOW NGA;Lo;0;L;;;;;N;;;;; +1988;NEW TAI LUE LETTER HIGH TSA;Lo;0;L;;;;;N;;;;; +1989;NEW TAI LUE LETTER HIGH SA;Lo;0;L;;;;;N;;;;; +198A;NEW TAI LUE LETTER HIGH YA;Lo;0;L;;;;;N;;;;; +198B;NEW TAI LUE LETTER LOW TSA;Lo;0;L;;;;;N;;;;; +198C;NEW TAI LUE LETTER LOW SA;Lo;0;L;;;;;N;;;;; +198D;NEW TAI LUE LETTER LOW YA;Lo;0;L;;;;;N;;;;; +198E;NEW TAI LUE LETTER HIGH TA;Lo;0;L;;;;;N;;;;; +198F;NEW TAI LUE LETTER HIGH THA;Lo;0;L;;;;;N;;;;; +1990;NEW TAI LUE LETTER HIGH NA;Lo;0;L;;;;;N;;;;; +1991;NEW TAI LUE LETTER LOW TA;Lo;0;L;;;;;N;;;;; +1992;NEW TAI LUE LETTER LOW THA;Lo;0;L;;;;;N;;;;; +1993;NEW TAI LUE LETTER LOW NA;Lo;0;L;;;;;N;;;;; +1994;NEW TAI LUE LETTER HIGH PA;Lo;0;L;;;;;N;;;;; +1995;NEW TAI LUE LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; +1996;NEW TAI LUE LETTER HIGH MA;Lo;0;L;;;;;N;;;;; +1997;NEW TAI LUE LETTER LOW PA;Lo;0;L;;;;;N;;;;; +1998;NEW TAI LUE LETTER LOW PHA;Lo;0;L;;;;;N;;;;; +1999;NEW TAI LUE LETTER LOW MA;Lo;0;L;;;;;N;;;;; +199A;NEW TAI LUE LETTER HIGH FA;Lo;0;L;;;;;N;;;;; +199B;NEW TAI LUE LETTER HIGH VA;Lo;0;L;;;;;N;;;;; +199C;NEW TAI LUE LETTER HIGH LA;Lo;0;L;;;;;N;;;;; +199D;NEW TAI LUE LETTER LOW FA;Lo;0;L;;;;;N;;;;; +199E;NEW TAI LUE LETTER LOW VA;Lo;0;L;;;;;N;;;;; +199F;NEW TAI LUE LETTER LOW LA;Lo;0;L;;;;;N;;;;; +19A0;NEW TAI LUE LETTER HIGH HA;Lo;0;L;;;;;N;;;;; +19A1;NEW TAI LUE LETTER HIGH DA;Lo;0;L;;;;;N;;;;; +19A2;NEW TAI LUE LETTER HIGH BA;Lo;0;L;;;;;N;;;;; +19A3;NEW TAI LUE LETTER LOW HA;Lo;0;L;;;;;N;;;;; +19A4;NEW TAI LUE LETTER LOW DA;Lo;0;L;;;;;N;;;;; +19A5;NEW TAI LUE LETTER LOW BA;Lo;0;L;;;;;N;;;;; +19A6;NEW TAI LUE LETTER HIGH KVA;Lo;0;L;;;;;N;;;;; +19A7;NEW TAI LUE LETTER HIGH XVA;Lo;0;L;;;;;N;;;;; +19A8;NEW TAI LUE LETTER LOW KVA;Lo;0;L;;;;;N;;;;; +19A9;NEW TAI LUE LETTER LOW XVA;Lo;0;L;;;;;N;;;;; +19AA;NEW TAI LUE LETTER HIGH SUA;Lo;0;L;;;;;N;;;;; +19AB;NEW TAI LUE LETTER LOW SUA;Lo;0;L;;;;;N;;;;; +19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Lo;0;L;;;;;N;;;;; +19B1;NEW TAI LUE VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; +19B2;NEW TAI LUE VOWEL SIGN II;Lo;0;L;;;;;N;;;;; +19B3;NEW TAI LUE VOWEL SIGN U;Lo;0;L;;;;;N;;;;; +19B4;NEW TAI LUE VOWEL SIGN UU;Lo;0;L;;;;;N;;;;; +19B5;NEW TAI LUE VOWEL SIGN E;Lo;0;L;;;;;N;;;;; +19B6;NEW TAI LUE VOWEL SIGN AE;Lo;0;L;;;;;N;;;;; +19B7;NEW TAI LUE VOWEL SIGN O;Lo;0;L;;;;;N;;;;; +19B8;NEW TAI LUE VOWEL SIGN OA;Lo;0;L;;;;;N;;;;; +19B9;NEW TAI LUE VOWEL SIGN UE;Lo;0;L;;;;;N;;;;; +19BA;NEW TAI LUE VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; +19BB;NEW TAI LUE VOWEL SIGN AAY;Lo;0;L;;;;;N;;;;; +19BC;NEW TAI LUE VOWEL SIGN UY;Lo;0;L;;;;;N;;;;; +19BD;NEW TAI LUE VOWEL SIGN OY;Lo;0;L;;;;;N;;;;; +19BE;NEW TAI LUE VOWEL SIGN OAY;Lo;0;L;;;;;N;;;;; +19BF;NEW TAI LUE VOWEL SIGN UEY;Lo;0;L;;;;;N;;;;; +19C0;NEW TAI LUE VOWEL SIGN IY;Lo;0;L;;;;;N;;;;; +19C1;NEW TAI LUE LETTER FINAL V;Lo;0;L;;;;;N;;;;; +19C2;NEW TAI LUE LETTER FINAL NG;Lo;0;L;;;;;N;;;;; +19C3;NEW TAI LUE LETTER FINAL N;Lo;0;L;;;;;N;;;;; +19C4;NEW TAI LUE LETTER FINAL M;Lo;0;L;;;;;N;;;;; +19C5;NEW TAI LUE LETTER FINAL K;Lo;0;L;;;;;N;;;;; +19C6;NEW TAI LUE LETTER FINAL D;Lo;0;L;;;;;N;;;;; +19C7;NEW TAI LUE LETTER FINAL B;Lo;0;L;;;;;N;;;;; +19C8;NEW TAI LUE TONE MARK-1;Lo;0;L;;;;;N;;;;; +19C9;NEW TAI LUE TONE MARK-2;Lo;0;L;;;;;N;;;;; +19D0;NEW TAI LUE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +19D1;NEW TAI LUE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +19D2;NEW TAI LUE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +19D3;NEW TAI LUE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +19D4;NEW TAI LUE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +19D5;NEW TAI LUE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +19D6;NEW TAI LUE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +19D7;NEW TAI LUE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +19D8;NEW TAI LUE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +19D9;NEW TAI LUE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +19DA;NEW TAI LUE THAM DIGIT ONE;No;0;L;;;1;1;N;;;;; +19DE;NEW TAI LUE SIGN LAE;So;0;ON;;;;;N;;;;; +19DF;NEW TAI LUE SIGN LAEV;So;0;ON;;;;;N;;;;; +19E0;KHMER SYMBOL PATHAMASAT;So;0;ON;;;;;N;;;;; +19E1;KHMER SYMBOL MUOY KOET;So;0;ON;;;;;N;;;;; +19E2;KHMER SYMBOL PII KOET;So;0;ON;;;;;N;;;;; +19E3;KHMER SYMBOL BEI KOET;So;0;ON;;;;;N;;;;; +19E4;KHMER SYMBOL BUON KOET;So;0;ON;;;;;N;;;;; +19E5;KHMER SYMBOL PRAM KOET;So;0;ON;;;;;N;;;;; +19E6;KHMER SYMBOL PRAM-MUOY KOET;So;0;ON;;;;;N;;;;; +19E7;KHMER SYMBOL PRAM-PII KOET;So;0;ON;;;;;N;;;;; +19E8;KHMER SYMBOL PRAM-BEI KOET;So;0;ON;;;;;N;;;;; +19E9;KHMER SYMBOL PRAM-BUON KOET;So;0;ON;;;;;N;;;;; +19EA;KHMER SYMBOL DAP KOET;So;0;ON;;;;;N;;;;; +19EB;KHMER SYMBOL DAP-MUOY KOET;So;0;ON;;;;;N;;;;; +19EC;KHMER SYMBOL DAP-PII KOET;So;0;ON;;;;;N;;;;; +19ED;KHMER SYMBOL DAP-BEI KOET;So;0;ON;;;;;N;;;;; +19EE;KHMER SYMBOL DAP-BUON KOET;So;0;ON;;;;;N;;;;; +19EF;KHMER SYMBOL DAP-PRAM KOET;So;0;ON;;;;;N;;;;; +19F0;KHMER SYMBOL TUTEYASAT;So;0;ON;;;;;N;;;;; +19F1;KHMER SYMBOL MUOY ROC;So;0;ON;;;;;N;;;;; +19F2;KHMER SYMBOL PII ROC;So;0;ON;;;;;N;;;;; +19F3;KHMER SYMBOL BEI ROC;So;0;ON;;;;;N;;;;; +19F4;KHMER SYMBOL BUON ROC;So;0;ON;;;;;N;;;;; +19F5;KHMER SYMBOL PRAM ROC;So;0;ON;;;;;N;;;;; +19F6;KHMER SYMBOL PRAM-MUOY ROC;So;0;ON;;;;;N;;;;; +19F7;KHMER SYMBOL PRAM-PII ROC;So;0;ON;;;;;N;;;;; +19F8;KHMER SYMBOL PRAM-BEI ROC;So;0;ON;;;;;N;;;;; +19F9;KHMER SYMBOL PRAM-BUON ROC;So;0;ON;;;;;N;;;;; +19FA;KHMER SYMBOL DAP ROC;So;0;ON;;;;;N;;;;; +19FB;KHMER SYMBOL DAP-MUOY ROC;So;0;ON;;;;;N;;;;; +19FC;KHMER SYMBOL DAP-PII ROC;So;0;ON;;;;;N;;;;; +19FD;KHMER SYMBOL DAP-BEI ROC;So;0;ON;;;;;N;;;;; +19FE;KHMER SYMBOL DAP-BUON ROC;So;0;ON;;;;;N;;;;; +19FF;KHMER SYMBOL DAP-PRAM ROC;So;0;ON;;;;;N;;;;; +1A00;BUGINESE LETTER KA;Lo;0;L;;;;;N;;;;; +1A01;BUGINESE LETTER GA;Lo;0;L;;;;;N;;;;; +1A02;BUGINESE LETTER NGA;Lo;0;L;;;;;N;;;;; +1A03;BUGINESE LETTER NGKA;Lo;0;L;;;;;N;;;;; +1A04;BUGINESE LETTER PA;Lo;0;L;;;;;N;;;;; +1A05;BUGINESE LETTER BA;Lo;0;L;;;;;N;;;;; +1A06;BUGINESE LETTER MA;Lo;0;L;;;;;N;;;;; +1A07;BUGINESE LETTER MPA;Lo;0;L;;;;;N;;;;; +1A08;BUGINESE LETTER TA;Lo;0;L;;;;;N;;;;; +1A09;BUGINESE LETTER DA;Lo;0;L;;;;;N;;;;; +1A0A;BUGINESE LETTER NA;Lo;0;L;;;;;N;;;;; +1A0B;BUGINESE LETTER NRA;Lo;0;L;;;;;N;;;;; +1A0C;BUGINESE LETTER CA;Lo;0;L;;;;;N;;;;; +1A0D;BUGINESE LETTER JA;Lo;0;L;;;;;N;;;;; +1A0E;BUGINESE LETTER NYA;Lo;0;L;;;;;N;;;;; +1A0F;BUGINESE LETTER NYCA;Lo;0;L;;;;;N;;;;; +1A10;BUGINESE LETTER YA;Lo;0;L;;;;;N;;;;; +1A11;BUGINESE LETTER RA;Lo;0;L;;;;;N;;;;; +1A12;BUGINESE LETTER LA;Lo;0;L;;;;;N;;;;; +1A13;BUGINESE LETTER VA;Lo;0;L;;;;;N;;;;; +1A14;BUGINESE LETTER SA;Lo;0;L;;;;;N;;;;; +1A15;BUGINESE LETTER A;Lo;0;L;;;;;N;;;;; +1A16;BUGINESE LETTER HA;Lo;0;L;;;;;N;;;;; +1A17;BUGINESE VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; +1A18;BUGINESE VOWEL SIGN U;Mn;220;NSM;;;;;N;;;;; +1A19;BUGINESE VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1A1A;BUGINESE VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1A1B;BUGINESE VOWEL SIGN AE;Mn;0;NSM;;;;;N;;;;; +1A1E;BUGINESE PALLAWA;Po;0;L;;;;;N;;;;; +1A1F;BUGINESE END OF SECTION;Po;0;L;;;;;N;;;;; +1A20;TAI THAM LETTER HIGH KA;Lo;0;L;;;;;N;;;;; +1A21;TAI THAM LETTER HIGH KHA;Lo;0;L;;;;;N;;;;; +1A22;TAI THAM LETTER HIGH KXA;Lo;0;L;;;;;N;;;;; +1A23;TAI THAM LETTER LOW KA;Lo;0;L;;;;;N;;;;; +1A24;TAI THAM LETTER LOW KXA;Lo;0;L;;;;;N;;;;; +1A25;TAI THAM LETTER LOW KHA;Lo;0;L;;;;;N;;;;; +1A26;TAI THAM LETTER NGA;Lo;0;L;;;;;N;;;;; +1A27;TAI THAM LETTER HIGH CA;Lo;0;L;;;;;N;;;;; +1A28;TAI THAM LETTER HIGH CHA;Lo;0;L;;;;;N;;;;; +1A29;TAI THAM LETTER LOW CA;Lo;0;L;;;;;N;;;;; +1A2A;TAI THAM LETTER LOW SA;Lo;0;L;;;;;N;;;;; +1A2B;TAI THAM LETTER LOW CHA;Lo;0;L;;;;;N;;;;; +1A2C;TAI THAM LETTER NYA;Lo;0;L;;;;;N;;;;; +1A2D;TAI THAM LETTER RATA;Lo;0;L;;;;;N;;;;; +1A2E;TAI THAM LETTER HIGH RATHA;Lo;0;L;;;;;N;;;;; +1A2F;TAI THAM LETTER DA;Lo;0;L;;;;;N;;;;; +1A30;TAI THAM LETTER LOW RATHA;Lo;0;L;;;;;N;;;;; +1A31;TAI THAM LETTER RANA;Lo;0;L;;;;;N;;;;; +1A32;TAI THAM LETTER HIGH TA;Lo;0;L;;;;;N;;;;; +1A33;TAI THAM LETTER HIGH THA;Lo;0;L;;;;;N;;;;; +1A34;TAI THAM LETTER LOW TA;Lo;0;L;;;;;N;;;;; +1A35;TAI THAM LETTER LOW THA;Lo;0;L;;;;;N;;;;; +1A36;TAI THAM LETTER NA;Lo;0;L;;;;;N;;;;; +1A37;TAI THAM LETTER BA;Lo;0;L;;;;;N;;;;; +1A38;TAI THAM LETTER HIGH PA;Lo;0;L;;;;;N;;;;; +1A39;TAI THAM LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; +1A3A;TAI THAM LETTER HIGH FA;Lo;0;L;;;;;N;;;;; +1A3B;TAI THAM LETTER LOW PA;Lo;0;L;;;;;N;;;;; +1A3C;TAI THAM LETTER LOW FA;Lo;0;L;;;;;N;;;;; +1A3D;TAI THAM LETTER LOW PHA;Lo;0;L;;;;;N;;;;; +1A3E;TAI THAM LETTER MA;Lo;0;L;;;;;N;;;;; +1A3F;TAI THAM LETTER LOW YA;Lo;0;L;;;;;N;;;;; +1A40;TAI THAM LETTER HIGH YA;Lo;0;L;;;;;N;;;;; +1A41;TAI THAM LETTER RA;Lo;0;L;;;;;N;;;;; +1A42;TAI THAM LETTER RUE;Lo;0;L;;;;;N;;;;; +1A43;TAI THAM LETTER LA;Lo;0;L;;;;;N;;;;; +1A44;TAI THAM LETTER LUE;Lo;0;L;;;;;N;;;;; +1A45;TAI THAM LETTER WA;Lo;0;L;;;;;N;;;;; +1A46;TAI THAM LETTER HIGH SHA;Lo;0;L;;;;;N;;;;; +1A47;TAI THAM LETTER HIGH SSA;Lo;0;L;;;;;N;;;;; +1A48;TAI THAM LETTER HIGH SA;Lo;0;L;;;;;N;;;;; +1A49;TAI THAM LETTER HIGH HA;Lo;0;L;;;;;N;;;;; +1A4A;TAI THAM LETTER LLA;Lo;0;L;;;;;N;;;;; +1A4B;TAI THAM LETTER A;Lo;0;L;;;;;N;;;;; +1A4C;TAI THAM LETTER LOW HA;Lo;0;L;;;;;N;;;;; +1A4D;TAI THAM LETTER I;Lo;0;L;;;;;N;;;;; +1A4E;TAI THAM LETTER II;Lo;0;L;;;;;N;;;;; +1A4F;TAI THAM LETTER U;Lo;0;L;;;;;N;;;;; +1A50;TAI THAM LETTER UU;Lo;0;L;;;;;N;;;;; +1A51;TAI THAM LETTER EE;Lo;0;L;;;;;N;;;;; +1A52;TAI THAM LETTER OO;Lo;0;L;;;;;N;;;;; +1A53;TAI THAM LETTER LAE;Lo;0;L;;;;;N;;;;; +1A54;TAI THAM LETTER GREAT SA;Lo;0;L;;;;;N;;;;; +1A55;TAI THAM CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; +1A56;TAI THAM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;; +1A57;TAI THAM CONSONANT SIGN LA TANG LAI;Mc;0;L;;;;;N;;;;; +1A58;TAI THAM SIGN MAI KANG LAI;Mn;0;NSM;;;;;N;;;;; +1A59;TAI THAM CONSONANT SIGN FINAL NGA;Mn;0;NSM;;;;;N;;;;; +1A5A;TAI THAM CONSONANT SIGN LOW PA;Mn;0;NSM;;;;;N;;;;; +1A5B;TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA;Mn;0;NSM;;;;;N;;;;; +1A5C;TAI THAM CONSONANT SIGN MA;Mn;0;NSM;;;;;N;;;;; +1A5D;TAI THAM CONSONANT SIGN BA;Mn;0;NSM;;;;;N;;;;; +1A5E;TAI THAM CONSONANT SIGN SA;Mn;0;NSM;;;;;N;;;;; +1A60;TAI THAM SIGN SAKOT;Mn;9;NSM;;;;;N;;;;; +1A61;TAI THAM VOWEL SIGN A;Mc;0;L;;;;;N;;;;; +1A62;TAI THAM VOWEL SIGN MAI SAT;Mn;0;NSM;;;;;N;;;;; +1A63;TAI THAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1A64;TAI THAM VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; +1A65;TAI THAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1A66;TAI THAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +1A67;TAI THAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +1A68;TAI THAM VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; +1A69;TAI THAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1A6A;TAI THAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1A6B;TAI THAM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +1A6C;TAI THAM VOWEL SIGN OA BELOW;Mn;0;NSM;;;;;N;;;;; +1A6D;TAI THAM VOWEL SIGN OY;Mc;0;L;;;;;N;;;;; +1A6E;TAI THAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1A6F;TAI THAM VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; +1A70;TAI THAM VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +1A71;TAI THAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +1A72;TAI THAM VOWEL SIGN THAM AI;Mc;0;L;;;;;N;;;;; +1A73;TAI THAM VOWEL SIGN OA ABOVE;Mn;0;NSM;;;;;N;;;;; +1A74;TAI THAM SIGN MAI KANG;Mn;0;NSM;;;;;N;;;;; +1A75;TAI THAM SIGN TONE-1;Mn;230;NSM;;;;;N;;;;; +1A76;TAI THAM SIGN TONE-2;Mn;230;NSM;;;;;N;;;;; +1A77;TAI THAM SIGN KHUEN TONE-3;Mn;230;NSM;;;;;N;;;;; +1A78;TAI THAM SIGN KHUEN TONE-4;Mn;230;NSM;;;;;N;;;;; +1A79;TAI THAM SIGN KHUEN TONE-5;Mn;230;NSM;;;;;N;;;;; +1A7A;TAI THAM SIGN RA HAAM;Mn;230;NSM;;;;;N;;;;; +1A7B;TAI THAM SIGN MAI SAM;Mn;230;NSM;;;;;N;;;;; +1A7C;TAI THAM SIGN KHUEN-LUE KARAN;Mn;230;NSM;;;;;N;;;;; +1A7F;TAI THAM COMBINING CRYPTOGRAMMIC DOT;Mn;220;NSM;;;;;N;;;;; +1A80;TAI THAM HORA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1A81;TAI THAM HORA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1A82;TAI THAM HORA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1A83;TAI THAM HORA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1A84;TAI THAM HORA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1A85;TAI THAM HORA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1A86;TAI THAM HORA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1A87;TAI THAM HORA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1A88;TAI THAM HORA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1A89;TAI THAM HORA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1A90;TAI THAM THAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1A91;TAI THAM THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1A92;TAI THAM THAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1A93;TAI THAM THAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1A94;TAI THAM THAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1A95;TAI THAM THAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1A96;TAI THAM THAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1A97;TAI THAM THAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1A98;TAI THAM THAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1A99;TAI THAM THAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1AA0;TAI THAM SIGN WIANG;Po;0;L;;;;;N;;;;; +1AA1;TAI THAM SIGN WIANGWAAK;Po;0;L;;;;;N;;;;; +1AA2;TAI THAM SIGN SAWAN;Po;0;L;;;;;N;;;;; +1AA3;TAI THAM SIGN KEOW;Po;0;L;;;;;N;;;;; +1AA4;TAI THAM SIGN HOY;Po;0;L;;;;;N;;;;; +1AA5;TAI THAM SIGN DOKMAI;Po;0;L;;;;;N;;;;; +1AA6;TAI THAM SIGN REVERSED ROTATED RANA;Po;0;L;;;;;N;;;;; +1AA7;TAI THAM SIGN MAI YAMOK;Lm;0;L;;;;;N;;;;; +1AA8;TAI THAM SIGN KAAN;Po;0;L;;;;;N;;;;; +1AA9;TAI THAM SIGN KAANKUU;Po;0;L;;;;;N;;;;; +1AAA;TAI THAM SIGN SATKAAN;Po;0;L;;;;;N;;;;; +1AAB;TAI THAM SIGN SATKAANKUU;Po;0;L;;;;;N;;;;; +1AAC;TAI THAM SIGN HANG;Po;0;L;;;;;N;;;;; +1AAD;TAI THAM SIGN CAANG;Po;0;L;;;;;N;;;;; +1AB0;COMBINING DOUBLED CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;;;;; +1AB1;COMBINING DIAERESIS-RING;Mn;230;NSM;;;;;N;;;;; +1AB2;COMBINING INFINITY;Mn;230;NSM;;;;;N;;;;; +1AB3;COMBINING DOWNWARDS ARROW;Mn;230;NSM;;;;;N;;;;; +1AB4;COMBINING TRIPLE DOT;Mn;230;NSM;;;;;N;;;;; +1AB5;COMBINING X-X BELOW;Mn;220;NSM;;;;;N;;;;; +1AB6;COMBINING WIGGLY LINE BELOW;Mn;220;NSM;;;;;N;;;;; +1AB7;COMBINING OPEN MARK BELOW;Mn;220;NSM;;;;;N;;;;; +1AB8;COMBINING DOUBLE OPEN MARK BELOW;Mn;220;NSM;;;;;N;;;;; +1AB9;COMBINING LIGHT CENTRALIZATION STROKE BELOW;Mn;220;NSM;;;;;N;;;;; +1ABA;COMBINING STRONG CENTRALIZATION STROKE BELOW;Mn;220;NSM;;;;;N;;;;; +1ABB;COMBINING PARENTHESES ABOVE;Mn;230;NSM;;;;;N;;;;; +1ABC;COMBINING DOUBLE PARENTHESES ABOVE;Mn;230;NSM;;;;;N;;;;; +1ABD;COMBINING PARENTHESES BELOW;Mn;220;NSM;;;;;N;;;;; +1ABE;COMBINING PARENTHESES OVERLAY;Me;0;NSM;;;;;N;;;;; +1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;; +1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;; +1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;; +1B03;BALINESE SIGN SURANG;Mn;0;NSM;;;;;N;;;;; +1B04;BALINESE SIGN BISAH;Mc;0;L;;;;;N;;;;; +1B05;BALINESE LETTER AKARA;Lo;0;L;;;;;N;;;;; +1B06;BALINESE LETTER AKARA TEDUNG;Lo;0;L;1B05 1B35;;;;N;;;;; +1B07;BALINESE LETTER IKARA;Lo;0;L;;;;;N;;;;; +1B08;BALINESE LETTER IKARA TEDUNG;Lo;0;L;1B07 1B35;;;;N;;;;; +1B09;BALINESE LETTER UKARA;Lo;0;L;;;;;N;;;;; +1B0A;BALINESE LETTER UKARA TEDUNG;Lo;0;L;1B09 1B35;;;;N;;;;; +1B0B;BALINESE LETTER RA REPA;Lo;0;L;;;;;N;;;;; +1B0C;BALINESE LETTER RA REPA TEDUNG;Lo;0;L;1B0B 1B35;;;;N;;;;; +1B0D;BALINESE LETTER LA LENGA;Lo;0;L;;;;;N;;;;; +1B0E;BALINESE LETTER LA LENGA TEDUNG;Lo;0;L;1B0D 1B35;;;;N;;;;; +1B0F;BALINESE LETTER EKARA;Lo;0;L;;;;;N;;;;; +1B10;BALINESE LETTER AIKARA;Lo;0;L;;;;;N;;;;; +1B11;BALINESE LETTER OKARA;Lo;0;L;;;;;N;;;;; +1B12;BALINESE LETTER OKARA TEDUNG;Lo;0;L;1B11 1B35;;;;N;;;;; +1B13;BALINESE LETTER KA;Lo;0;L;;;;;N;;;;; +1B14;BALINESE LETTER KA MAHAPRANA;Lo;0;L;;;;;N;;;;; +1B15;BALINESE LETTER GA;Lo;0;L;;;;;N;;;;; +1B16;BALINESE LETTER GA GORA;Lo;0;L;;;;;N;;;;; +1B17;BALINESE LETTER NGA;Lo;0;L;;;;;N;;;;; +1B18;BALINESE LETTER CA;Lo;0;L;;;;;N;;;;; +1B19;BALINESE LETTER CA LACA;Lo;0;L;;;;;N;;;;; +1B1A;BALINESE LETTER JA;Lo;0;L;;;;;N;;;;; +1B1B;BALINESE LETTER JA JERA;Lo;0;L;;;;;N;;;;; +1B1C;BALINESE LETTER NYA;Lo;0;L;;;;;N;;;;; +1B1D;BALINESE LETTER TA LATIK;Lo;0;L;;;;;N;;;;; +1B1E;BALINESE LETTER TA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; +1B1F;BALINESE LETTER DA MURDA ALPAPRANA;Lo;0;L;;;;;N;;;;; +1B20;BALINESE LETTER DA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; +1B21;BALINESE LETTER NA RAMBAT;Lo;0;L;;;;;N;;;;; +1B22;BALINESE LETTER TA;Lo;0;L;;;;;N;;;;; +1B23;BALINESE LETTER TA TAWA;Lo;0;L;;;;;N;;;;; +1B24;BALINESE LETTER DA;Lo;0;L;;;;;N;;;;; +1B25;BALINESE LETTER DA MADU;Lo;0;L;;;;;N;;;;; +1B26;BALINESE LETTER NA;Lo;0;L;;;;;N;;;;; +1B27;BALINESE LETTER PA;Lo;0;L;;;;;N;;;;; +1B28;BALINESE LETTER PA KAPAL;Lo;0;L;;;;;N;;;;; +1B29;BALINESE LETTER BA;Lo;0;L;;;;;N;;;;; +1B2A;BALINESE LETTER BA KEMBANG;Lo;0;L;;;;;N;;;;; +1B2B;BALINESE LETTER MA;Lo;0;L;;;;;N;;;;; +1B2C;BALINESE LETTER YA;Lo;0;L;;;;;N;;;;; +1B2D;BALINESE LETTER RA;Lo;0;L;;;;;N;;;;; +1B2E;BALINESE LETTER LA;Lo;0;L;;;;;N;;;;; +1B2F;BALINESE LETTER WA;Lo;0;L;;;;;N;;;;; +1B30;BALINESE LETTER SA SAGA;Lo;0;L;;;;;N;;;;; +1B31;BALINESE LETTER SA SAPA;Lo;0;L;;;;;N;;;;; +1B32;BALINESE LETTER SA;Lo;0;L;;;;;N;;;;; +1B33;BALINESE LETTER HA;Lo;0;L;;;;;N;;;;; +1B34;BALINESE SIGN REREKAN;Mn;7;NSM;;;;;N;;;;; +1B35;BALINESE VOWEL SIGN TEDUNG;Mc;0;L;;;;;N;;;;; +1B36;BALINESE VOWEL SIGN ULU;Mn;0;NSM;;;;;N;;;;; +1B37;BALINESE VOWEL SIGN ULU SARI;Mn;0;NSM;;;;;N;;;;; +1B38;BALINESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; +1B39;BALINESE VOWEL SIGN SUKU ILUT;Mn;0;NSM;;;;;N;;;;; +1B3A;BALINESE VOWEL SIGN RA REPA;Mn;0;NSM;;;;;N;;;;; +1B3B;BALINESE VOWEL SIGN RA REPA TEDUNG;Mc;0;L;1B3A 1B35;;;;N;;;;; +1B3C;BALINESE VOWEL SIGN LA LENGA;Mn;0;NSM;;;;;N;;;;; +1B3D;BALINESE VOWEL SIGN LA LENGA TEDUNG;Mc;0;L;1B3C 1B35;;;;N;;;;; +1B3E;BALINESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; +1B3F;BALINESE VOWEL SIGN TALING REPA;Mc;0;L;;;;;N;;;;; +1B40;BALINESE VOWEL SIGN TALING TEDUNG;Mc;0;L;1B3E 1B35;;;;N;;;;; +1B41;BALINESE VOWEL SIGN TALING REPA TEDUNG;Mc;0;L;1B3F 1B35;;;;N;;;;; +1B42;BALINESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; +1B43;BALINESE VOWEL SIGN PEPET TEDUNG;Mc;0;L;1B42 1B35;;;;N;;;;; +1B44;BALINESE ADEG ADEG;Mc;9;L;;;;;N;;;;; +1B45;BALINESE LETTER KAF SASAK;Lo;0;L;;;;;N;;;;; +1B46;BALINESE LETTER KHOT SASAK;Lo;0;L;;;;;N;;;;; +1B47;BALINESE LETTER TZIR SASAK;Lo;0;L;;;;;N;;;;; +1B48;BALINESE LETTER EF SASAK;Lo;0;L;;;;;N;;;;; +1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;; +1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;; +1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;; +1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1B53;BALINESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1B54;BALINESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1B55;BALINESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1B56;BALINESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1B57;BALINESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1B58;BALINESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1B59;BALINESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1B5A;BALINESE PANTI;Po;0;L;;;;;N;;;;; +1B5B;BALINESE PAMADA;Po;0;L;;;;;N;;;;; +1B5C;BALINESE WINDU;Po;0;L;;;;;N;;;;; +1B5D;BALINESE CARIK PAMUNGKAH;Po;0;L;;;;;N;;;;; +1B5E;BALINESE CARIK SIKI;Po;0;L;;;;;N;;;;; +1B5F;BALINESE CARIK PAREREN;Po;0;L;;;;;N;;;;; +1B60;BALINESE PAMENENG;Po;0;L;;;;;N;;;;; +1B61;BALINESE MUSICAL SYMBOL DONG;So;0;L;;;;;N;;;;; +1B62;BALINESE MUSICAL SYMBOL DENG;So;0;L;;;;;N;;;;; +1B63;BALINESE MUSICAL SYMBOL DUNG;So;0;L;;;;;N;;;;; +1B64;BALINESE MUSICAL SYMBOL DANG;So;0;L;;;;;N;;;;; +1B65;BALINESE MUSICAL SYMBOL DANG SURANG;So;0;L;;;;;N;;;;; +1B66;BALINESE MUSICAL SYMBOL DING;So;0;L;;;;;N;;;;; +1B67;BALINESE MUSICAL SYMBOL DAENG;So;0;L;;;;;N;;;;; +1B68;BALINESE MUSICAL SYMBOL DEUNG;So;0;L;;;;;N;;;;; +1B69;BALINESE MUSICAL SYMBOL DAING;So;0;L;;;;;N;;;;; +1B6A;BALINESE MUSICAL SYMBOL DANG GEDE;So;0;L;;;;;N;;;;; +1B6B;BALINESE MUSICAL SYMBOL COMBINING TEGEH;Mn;230;NSM;;;;;N;;;;; +1B6C;BALINESE MUSICAL SYMBOL COMBINING ENDEP;Mn;220;NSM;;;;;N;;;;; +1B6D;BALINESE MUSICAL SYMBOL COMBINING KEMPUL;Mn;230;NSM;;;;;N;;;;; +1B6E;BALINESE MUSICAL SYMBOL COMBINING KEMPLI;Mn;230;NSM;;;;;N;;;;; +1B6F;BALINESE MUSICAL SYMBOL COMBINING JEGOGAN;Mn;230;NSM;;;;;N;;;;; +1B70;BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; +1B71;BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; +1B72;BALINESE MUSICAL SYMBOL COMBINING BENDE;Mn;230;NSM;;;;;N;;;;; +1B73;BALINESE MUSICAL SYMBOL COMBINING GONG;Mn;230;NSM;;;;;N;;;;; +1B74;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG;So;0;L;;;;;N;;;;; +1B75;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG;So;0;L;;;;;N;;;;; +1B76;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK;So;0;L;;;;;N;;;;; +1B77;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK;So;0;L;;;;;N;;;;; +1B78;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG;So;0;L;;;;;N;;;;; +1B79;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG;So;0;L;;;;;N;;;;; +1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;; +1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;; +1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;; +1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;; +1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;; +1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;; +1B83;SUNDANESE LETTER A;Lo;0;L;;;;;N;;;;; +1B84;SUNDANESE LETTER I;Lo;0;L;;;;;N;;;;; +1B85;SUNDANESE LETTER U;Lo;0;L;;;;;N;;;;; +1B86;SUNDANESE LETTER AE;Lo;0;L;;;;;N;;;;; +1B87;SUNDANESE LETTER O;Lo;0;L;;;;;N;;;;; +1B88;SUNDANESE LETTER E;Lo;0;L;;;;;N;;;;; +1B89;SUNDANESE LETTER EU;Lo;0;L;;;;;N;;;;; +1B8A;SUNDANESE LETTER KA;Lo;0;L;;;;;N;;;;; +1B8B;SUNDANESE LETTER QA;Lo;0;L;;;;;N;;;;; +1B8C;SUNDANESE LETTER GA;Lo;0;L;;;;;N;;;;; +1B8D;SUNDANESE LETTER NGA;Lo;0;L;;;;;N;;;;; +1B8E;SUNDANESE LETTER CA;Lo;0;L;;;;;N;;;;; +1B8F;SUNDANESE LETTER JA;Lo;0;L;;;;;N;;;;; +1B90;SUNDANESE LETTER ZA;Lo;0;L;;;;;N;;;;; +1B91;SUNDANESE LETTER NYA;Lo;0;L;;;;;N;;;;; +1B92;SUNDANESE LETTER TA;Lo;0;L;;;;;N;;;;; +1B93;SUNDANESE LETTER DA;Lo;0;L;;;;;N;;;;; +1B94;SUNDANESE LETTER NA;Lo;0;L;;;;;N;;;;; +1B95;SUNDANESE LETTER PA;Lo;0;L;;;;;N;;;;; +1B96;SUNDANESE LETTER FA;Lo;0;L;;;;;N;;;;; +1B97;SUNDANESE LETTER VA;Lo;0;L;;;;;N;;;;; +1B98;SUNDANESE LETTER BA;Lo;0;L;;;;;N;;;;; +1B99;SUNDANESE LETTER MA;Lo;0;L;;;;;N;;;;; +1B9A;SUNDANESE LETTER YA;Lo;0;L;;;;;N;;;;; +1B9B;SUNDANESE LETTER RA;Lo;0;L;;;;;N;;;;; +1B9C;SUNDANESE LETTER LA;Lo;0;L;;;;;N;;;;; +1B9D;SUNDANESE LETTER WA;Lo;0;L;;;;;N;;;;; +1B9E;SUNDANESE LETTER SA;Lo;0;L;;;;;N;;;;; +1B9F;SUNDANESE LETTER XA;Lo;0;L;;;;;N;;;;; +1BA0;SUNDANESE LETTER HA;Lo;0;L;;;;;N;;;;; +1BA1;SUNDANESE CONSONANT SIGN PAMINGKAL;Mc;0;L;;;;;N;;;;; +1BA2;SUNDANESE CONSONANT SIGN PANYAKRA;Mn;0;NSM;;;;;N;;;;; +1BA3;SUNDANESE CONSONANT SIGN PANYIKU;Mn;0;NSM;;;;;N;;;;; +1BA4;SUNDANESE VOWEL SIGN PANGHULU;Mn;0;NSM;;;;;N;;;;; +1BA5;SUNDANESE VOWEL SIGN PANYUKU;Mn;0;NSM;;;;;N;;;;; +1BA6;SUNDANESE VOWEL SIGN PANAELAENG;Mc;0;L;;;;;N;;;;; +1BA7;SUNDANESE VOWEL SIGN PANOLONG;Mc;0;L;;;;;N;;;;; +1BA8;SUNDANESE VOWEL SIGN PAMEPET;Mn;0;NSM;;;;;N;;;;; +1BA9;SUNDANESE VOWEL SIGN PANEULEUNG;Mn;0;NSM;;;;;N;;;;; +1BAA;SUNDANESE SIGN PAMAAEH;Mc;9;L;;;;;N;;;;; +1BAB;SUNDANESE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +1BAC;SUNDANESE CONSONANT SIGN PASANGAN MA;Mn;0;NSM;;;;;N;;;;; +1BAD;SUNDANESE CONSONANT SIGN PASANGAN WA;Mn;0;NSM;;;;;N;;;;; +1BAE;SUNDANESE LETTER KHA;Lo;0;L;;;;;N;;;;; +1BAF;SUNDANESE LETTER SYA;Lo;0;L;;;;;N;;;;; +1BB0;SUNDANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1BB1;SUNDANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1BB2;SUNDANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1BB3;SUNDANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1BB4;SUNDANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1BB5;SUNDANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1BB6;SUNDANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1BB7;SUNDANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1BB8;SUNDANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1BB9;SUNDANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1BBA;SUNDANESE AVAGRAHA;Lo;0;L;;;;;N;;;;; +1BBB;SUNDANESE LETTER REU;Lo;0;L;;;;;N;;;;; +1BBC;SUNDANESE LETTER LEU;Lo;0;L;;;;;N;;;;; +1BBD;SUNDANESE LETTER BHA;Lo;0;L;;;;;N;;;;; +1BBE;SUNDANESE LETTER FINAL K;Lo;0;L;;;;;N;;;;; +1BBF;SUNDANESE LETTER FINAL M;Lo;0;L;;;;;N;;;;; +1BC0;BATAK LETTER A;Lo;0;L;;;;;N;;;;; +1BC1;BATAK LETTER SIMALUNGUN A;Lo;0;L;;;;;N;;;;; +1BC2;BATAK LETTER HA;Lo;0;L;;;;;N;;;;; +1BC3;BATAK LETTER SIMALUNGUN HA;Lo;0;L;;;;;N;;;;; +1BC4;BATAK LETTER MANDAILING HA;Lo;0;L;;;;;N;;;;; +1BC5;BATAK LETTER BA;Lo;0;L;;;;;N;;;;; +1BC6;BATAK LETTER KARO BA;Lo;0;L;;;;;N;;;;; +1BC7;BATAK LETTER PA;Lo;0;L;;;;;N;;;;; +1BC8;BATAK LETTER SIMALUNGUN PA;Lo;0;L;;;;;N;;;;; +1BC9;BATAK LETTER NA;Lo;0;L;;;;;N;;;;; +1BCA;BATAK LETTER MANDAILING NA;Lo;0;L;;;;;N;;;;; +1BCB;BATAK LETTER WA;Lo;0;L;;;;;N;;;;; +1BCC;BATAK LETTER SIMALUNGUN WA;Lo;0;L;;;;;N;;;;; +1BCD;BATAK LETTER PAKPAK WA;Lo;0;L;;;;;N;;;;; +1BCE;BATAK LETTER GA;Lo;0;L;;;;;N;;;;; +1BCF;BATAK LETTER SIMALUNGUN GA;Lo;0;L;;;;;N;;;;; +1BD0;BATAK LETTER JA;Lo;0;L;;;;;N;;;;; +1BD1;BATAK LETTER DA;Lo;0;L;;;;;N;;;;; +1BD2;BATAK LETTER RA;Lo;0;L;;;;;N;;;;; +1BD3;BATAK LETTER SIMALUNGUN RA;Lo;0;L;;;;;N;;;;; +1BD4;BATAK LETTER MA;Lo;0;L;;;;;N;;;;; +1BD5;BATAK LETTER SIMALUNGUN MA;Lo;0;L;;;;;N;;;;; +1BD6;BATAK LETTER SOUTHERN TA;Lo;0;L;;;;;N;;;;; +1BD7;BATAK LETTER NORTHERN TA;Lo;0;L;;;;;N;;;;; +1BD8;BATAK LETTER SA;Lo;0;L;;;;;N;;;;; +1BD9;BATAK LETTER SIMALUNGUN SA;Lo;0;L;;;;;N;;;;; +1BDA;BATAK LETTER MANDAILING SA;Lo;0;L;;;;;N;;;;; +1BDB;BATAK LETTER YA;Lo;0;L;;;;;N;;;;; +1BDC;BATAK LETTER SIMALUNGUN YA;Lo;0;L;;;;;N;;;;; +1BDD;BATAK LETTER NGA;Lo;0;L;;;;;N;;;;; +1BDE;BATAK LETTER LA;Lo;0;L;;;;;N;;;;; +1BDF;BATAK LETTER SIMALUNGUN LA;Lo;0;L;;;;;N;;;;; +1BE0;BATAK LETTER NYA;Lo;0;L;;;;;N;;;;; +1BE1;BATAK LETTER CA;Lo;0;L;;;;;N;;;;; +1BE2;BATAK LETTER NDA;Lo;0;L;;;;;N;;;;; +1BE3;BATAK LETTER MBA;Lo;0;L;;;;;N;;;;; +1BE4;BATAK LETTER I;Lo;0;L;;;;;N;;;;; +1BE5;BATAK LETTER U;Lo;0;L;;;;;N;;;;; +1BE6;BATAK SIGN TOMPI;Mn;7;NSM;;;;;N;;;;; +1BE7;BATAK VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1BE8;BATAK VOWEL SIGN PAKPAK E;Mn;0;NSM;;;;;N;;;;; +1BE9;BATAK VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; +1BEA;BATAK VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +1BEB;BATAK VOWEL SIGN KARO I;Mc;0;L;;;;;N;;;;; +1BEC;BATAK VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1BED;BATAK VOWEL SIGN KARO O;Mn;0;NSM;;;;;N;;;;; +1BEE;BATAK VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +1BEF;BATAK VOWEL SIGN U FOR SIMALUNGUN SA;Mn;0;NSM;;;;;N;;;;; +1BF0;BATAK CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +1BF1;BATAK CONSONANT SIGN H;Mn;0;NSM;;;;;N;;;;; +1BF2;BATAK PANGOLAT;Mc;9;L;;;;;N;;;;; +1BF3;BATAK PANONGONAN;Mc;9;L;;;;;N;;;;; +1BFC;BATAK SYMBOL BINDU NA METEK;Po;0;L;;;;;N;;;;; +1BFD;BATAK SYMBOL BINDU PINARBORAS;Po;0;L;;;;;N;;;;; +1BFE;BATAK SYMBOL BINDU JUDUL;Po;0;L;;;;;N;;;;; +1BFF;BATAK SYMBOL BINDU PANGOLAT;Po;0;L;;;;;N;;;;; +1C00;LEPCHA LETTER KA;Lo;0;L;;;;;N;;;;; +1C01;LEPCHA LETTER KLA;Lo;0;L;;;;;N;;;;; +1C02;LEPCHA LETTER KHA;Lo;0;L;;;;;N;;;;; +1C03;LEPCHA LETTER GA;Lo;0;L;;;;;N;;;;; +1C04;LEPCHA LETTER GLA;Lo;0;L;;;;;N;;;;; +1C05;LEPCHA LETTER NGA;Lo;0;L;;;;;N;;;;; +1C06;LEPCHA LETTER CA;Lo;0;L;;;;;N;;;;; +1C07;LEPCHA LETTER CHA;Lo;0;L;;;;;N;;;;; +1C08;LEPCHA LETTER JA;Lo;0;L;;;;;N;;;;; +1C09;LEPCHA LETTER NYA;Lo;0;L;;;;;N;;;;; +1C0A;LEPCHA LETTER TA;Lo;0;L;;;;;N;;;;; +1C0B;LEPCHA LETTER THA;Lo;0;L;;;;;N;;;;; +1C0C;LEPCHA LETTER DA;Lo;0;L;;;;;N;;;;; +1C0D;LEPCHA LETTER NA;Lo;0;L;;;;;N;;;;; +1C0E;LEPCHA LETTER PA;Lo;0;L;;;;;N;;;;; +1C0F;LEPCHA LETTER PLA;Lo;0;L;;;;;N;;;;; +1C10;LEPCHA LETTER PHA;Lo;0;L;;;;;N;;;;; +1C11;LEPCHA LETTER FA;Lo;0;L;;;;;N;;;;; +1C12;LEPCHA LETTER FLA;Lo;0;L;;;;;N;;;;; +1C13;LEPCHA LETTER BA;Lo;0;L;;;;;N;;;;; +1C14;LEPCHA LETTER BLA;Lo;0;L;;;;;N;;;;; +1C15;LEPCHA LETTER MA;Lo;0;L;;;;;N;;;;; +1C16;LEPCHA LETTER MLA;Lo;0;L;;;;;N;;;;; +1C17;LEPCHA LETTER TSA;Lo;0;L;;;;;N;;;;; +1C18;LEPCHA LETTER TSHA;Lo;0;L;;;;;N;;;;; +1C19;LEPCHA LETTER DZA;Lo;0;L;;;;;N;;;;; +1C1A;LEPCHA LETTER YA;Lo;0;L;;;;;N;;;;; +1C1B;LEPCHA LETTER RA;Lo;0;L;;;;;N;;;;; +1C1C;LEPCHA LETTER LA;Lo;0;L;;;;;N;;;;; +1C1D;LEPCHA LETTER HA;Lo;0;L;;;;;N;;;;; +1C1E;LEPCHA LETTER HLA;Lo;0;L;;;;;N;;;;; +1C1F;LEPCHA LETTER VA;Lo;0;L;;;;;N;;;;; +1C20;LEPCHA LETTER SA;Lo;0;L;;;;;N;;;;; +1C21;LEPCHA LETTER SHA;Lo;0;L;;;;;N;;;;; +1C22;LEPCHA LETTER WA;Lo;0;L;;;;;N;;;;; +1C23;LEPCHA LETTER A;Lo;0;L;;;;;N;;;;; +1C24;LEPCHA SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; +1C25;LEPCHA SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; +1C26;LEPCHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1C27;LEPCHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +1C28;LEPCHA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1C29;LEPCHA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +1C2A;LEPCHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +1C2B;LEPCHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +1C2C;LEPCHA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1C2D;LEPCHA CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; +1C2E;LEPCHA CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; +1C2F;LEPCHA CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; +1C30;LEPCHA CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +1C31;LEPCHA CONSONANT SIGN P;Mn;0;NSM;;;;;N;;;;; +1C32;LEPCHA CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +1C33;LEPCHA CONSONANT SIGN T;Mn;0;NSM;;;;;N;;;;; +1C34;LEPCHA CONSONANT SIGN NYIN-DO;Mc;0;L;;;;;N;;;;; +1C35;LEPCHA CONSONANT SIGN KANG;Mc;0;L;;;;;N;;;;; +1C36;LEPCHA SIGN RAN;Mn;0;NSM;;;;;N;;;;; +1C37;LEPCHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +1C3B;LEPCHA PUNCTUATION TA-ROL;Po;0;L;;;;;N;;;;; +1C3C;LEPCHA PUNCTUATION NYET THYOOM TA-ROL;Po;0;L;;;;;N;;;;; +1C3D;LEPCHA PUNCTUATION CER-WA;Po;0;L;;;;;N;;;;; +1C3E;LEPCHA PUNCTUATION TSHOOK CER-WA;Po;0;L;;;;;N;;;;; +1C3F;LEPCHA PUNCTUATION TSHOOK;Po;0;L;;;;;N;;;;; +1C40;LEPCHA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1C41;LEPCHA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1C42;LEPCHA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1C43;LEPCHA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1C44;LEPCHA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1C45;LEPCHA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1C46;LEPCHA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1C47;LEPCHA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1C48;LEPCHA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1C49;LEPCHA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1C4D;LEPCHA LETTER TTA;Lo;0;L;;;;;N;;;;; +1C4E;LEPCHA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1C4F;LEPCHA LETTER DDA;Lo;0;L;;;;;N;;;;; +1C50;OL CHIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1C51;OL CHIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1C52;OL CHIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1C53;OL CHIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1C54;OL CHIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1C55;OL CHIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1C56;OL CHIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1C57;OL CHIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1C58;OL CHIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1C59;OL CHIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1C5A;OL CHIKI LETTER LA;Lo;0;L;;;;;N;;;;; +1C5B;OL CHIKI LETTER AT;Lo;0;L;;;;;N;;;;; +1C5C;OL CHIKI LETTER AG;Lo;0;L;;;;;N;;;;; +1C5D;OL CHIKI LETTER ANG;Lo;0;L;;;;;N;;;;; +1C5E;OL CHIKI LETTER AL;Lo;0;L;;;;;N;;;;; +1C5F;OL CHIKI LETTER LAA;Lo;0;L;;;;;N;;;;; +1C60;OL CHIKI LETTER AAK;Lo;0;L;;;;;N;;;;; +1C61;OL CHIKI LETTER AAJ;Lo;0;L;;;;;N;;;;; +1C62;OL CHIKI LETTER AAM;Lo;0;L;;;;;N;;;;; +1C63;OL CHIKI LETTER AAW;Lo;0;L;;;;;N;;;;; +1C64;OL CHIKI LETTER LI;Lo;0;L;;;;;N;;;;; +1C65;OL CHIKI LETTER IS;Lo;0;L;;;;;N;;;;; +1C66;OL CHIKI LETTER IH;Lo;0;L;;;;;N;;;;; +1C67;OL CHIKI LETTER INY;Lo;0;L;;;;;N;;;;; +1C68;OL CHIKI LETTER IR;Lo;0;L;;;;;N;;;;; +1C69;OL CHIKI LETTER LU;Lo;0;L;;;;;N;;;;; +1C6A;OL CHIKI LETTER UC;Lo;0;L;;;;;N;;;;; +1C6B;OL CHIKI LETTER UD;Lo;0;L;;;;;N;;;;; +1C6C;OL CHIKI LETTER UNN;Lo;0;L;;;;;N;;;;; +1C6D;OL CHIKI LETTER UY;Lo;0;L;;;;;N;;;;; +1C6E;OL CHIKI LETTER LE;Lo;0;L;;;;;N;;;;; +1C6F;OL CHIKI LETTER EP;Lo;0;L;;;;;N;;;;; +1C70;OL CHIKI LETTER EDD;Lo;0;L;;;;;N;;;;; +1C71;OL CHIKI LETTER EN;Lo;0;L;;;;;N;;;;; +1C72;OL CHIKI LETTER ERR;Lo;0;L;;;;;N;;;;; +1C73;OL CHIKI LETTER LO;Lo;0;L;;;;;N;;;;; +1C74;OL CHIKI LETTER OTT;Lo;0;L;;;;;N;;;;; +1C75;OL CHIKI LETTER OB;Lo;0;L;;;;;N;;;;; +1C76;OL CHIKI LETTER OV;Lo;0;L;;;;;N;;;;; +1C77;OL CHIKI LETTER OH;Lo;0;L;;;;;N;;;;; +1C78;OL CHIKI MU TTUDDAG;Lm;0;L;;;;;N;;;;; +1C79;OL CHIKI GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; +1C7A;OL CHIKI MU-GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; +1C7B;OL CHIKI RELAA;Lm;0;L;;;;;N;;;;; +1C7C;OL CHIKI PHAARKAA;Lm;0;L;;;;;N;;;;; +1C7D;OL CHIKI AHAD;Lm;0;L;;;;;N;;;;; +1C7E;OL CHIKI PUNCTUATION MUCAAD;Po;0;L;;;;;N;;;;; +1C7F;OL CHIKI PUNCTUATION DOUBLE MUCAAD;Po;0;L;;;;;N;;;;; +1C80;CYRILLIC SMALL LETTER ROUNDED VE;Ll;0;L;;;;;N;;;0412;;0412 +1C81;CYRILLIC SMALL LETTER LONG-LEGGED DE;Ll;0;L;;;;;N;;;0414;;0414 +1C82;CYRILLIC SMALL LETTER NARROW O;Ll;0;L;;;;;N;;;041E;;041E +1C83;CYRILLIC SMALL LETTER WIDE ES;Ll;0;L;;;;;N;;;0421;;0421 +1C84;CYRILLIC SMALL LETTER TALL TE;Ll;0;L;;;;;N;;;0422;;0422 +1C85;CYRILLIC SMALL LETTER THREE-LEGGED TE;Ll;0;L;;;;;N;;;0422;;0422 +1C86;CYRILLIC SMALL LETTER TALL HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A +1C87;CYRILLIC SMALL LETTER TALL YAT;Ll;0;L;;;;;N;;;0462;;0462 +1C88;CYRILLIC SMALL LETTER UNBLENDED UK;Ll;0;L;;;;;N;;;A64A;;A64A +1CC0;SUNDANESE PUNCTUATION BINDU SURYA;Po;0;L;;;;;N;;;;; +1CC1;SUNDANESE PUNCTUATION BINDU PANGLONG;Po;0;L;;;;;N;;;;; +1CC2;SUNDANESE PUNCTUATION BINDU PURNAMA;Po;0;L;;;;;N;;;;; +1CC3;SUNDANESE PUNCTUATION BINDU CAKRA;Po;0;L;;;;;N;;;;; +1CC4;SUNDANESE PUNCTUATION BINDU LEU SATANGA;Po;0;L;;;;;N;;;;; +1CC5;SUNDANESE PUNCTUATION BINDU KA SATANGA;Po;0;L;;;;;N;;;;; +1CC6;SUNDANESE PUNCTUATION BINDU DA SATANGA;Po;0;L;;;;;N;;;;; +1CC7;SUNDANESE PUNCTUATION BINDU BA SATANGA;Po;0;L;;;;;N;;;;; +1CD0;VEDIC TONE KARSHANA;Mn;230;NSM;;;;;N;;;;; +1CD1;VEDIC TONE SHARA;Mn;230;NSM;;;;;N;;;;; +1CD2;VEDIC TONE PRENKHA;Mn;230;NSM;;;;;N;;;;; +1CD3;VEDIC SIGN NIHSHVASA;Po;0;L;;;;;N;;;;; +1CD4;VEDIC SIGN YAJURVEDIC MIDLINE SVARITA;Mn;1;NSM;;;;;N;;;;; +1CD5;VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; +1CD6;VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; +1CD7;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; +1CD8;VEDIC TONE CANDRA BELOW;Mn;220;NSM;;;;;N;;;;; +1CD9;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER;Mn;220;NSM;;;;;N;;;;; +1CDA;VEDIC TONE DOUBLE SVARITA;Mn;230;NSM;;;;;N;;;;; +1CDB;VEDIC TONE TRIPLE SVARITA;Mn;230;NSM;;;;;N;;;;; +1CDC;VEDIC TONE KATHAKA ANUDATTA;Mn;220;NSM;;;;;N;;;;; +1CDD;VEDIC TONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; +1CDE;VEDIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +1CDF;VEDIC TONE THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +1CE0;VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA;Mn;230;NSM;;;;;N;;;;; +1CE1;VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA;Mc;0;L;;;;;N;;;;; +1CE2;VEDIC SIGN VISARGA SVARITA;Mn;1;NSM;;;;;N;;;;; +1CE3;VEDIC SIGN VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; +1CE4;VEDIC SIGN REVERSED VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; +1CE5;VEDIC SIGN VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; +1CE6;VEDIC SIGN REVERSED VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; +1CE7;VEDIC SIGN VISARGA UDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; +1CE8;VEDIC SIGN VISARGA ANUDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; +1CE9;VEDIC SIGN ANUSVARA ANTARGOMUKHA;Lo;0;L;;;;;N;;;;; +1CEA;VEDIC SIGN ANUSVARA BAHIRGOMUKHA;Lo;0;L;;;;;N;;;;; +1CEB;VEDIC SIGN ANUSVARA VAMAGOMUKHA;Lo;0;L;;;;;N;;;;; +1CEC;VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL;Lo;0;L;;;;;N;;;;; +1CED;VEDIC SIGN TIRYAK;Mn;220;NSM;;;;;N;;;;; +1CEE;VEDIC SIGN HEXIFORM LONG ANUSVARA;Lo;0;L;;;;;N;;;;; +1CEF;VEDIC SIGN LONG ANUSVARA;Lo;0;L;;;;;N;;;;; +1CF0;VEDIC SIGN RTHANG LONG ANUSVARA;Lo;0;L;;;;;N;;;;; +1CF1;VEDIC SIGN ANUSVARA UBHAYATO MUKHA;Lo;0;L;;;;;N;;;;; +1CF2;VEDIC SIGN ARDHAVISARGA;Mc;0;L;;;;;N;;;;; +1CF3;VEDIC SIGN ROTATED ARDHAVISARGA;Mc;0;L;;;;;N;;;;; +1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;; +1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +1CF7;VEDIC SIGN ATIKRAMA;Mc;0;L;;;;;N;;;;; +1CF8;VEDIC TONE RING ABOVE;Mn;230;NSM;;;;;N;;;;; +1CF9;VEDIC TONE DOUBLE RING ABOVE;Mn;230;NSM;;;;;N;;;;; +1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;; +1D01;LATIN LETTER SMALL CAPITAL AE;Ll;0;L;;;;;N;;;;; +1D02;LATIN SMALL LETTER TURNED AE;Ll;0;L;;;;;N;;;;; +1D03;LATIN LETTER SMALL CAPITAL BARRED B;Ll;0;L;;;;;N;;;;; +1D04;LATIN LETTER SMALL CAPITAL C;Ll;0;L;;;;;N;;;;; +1D05;LATIN LETTER SMALL CAPITAL D;Ll;0;L;;;;;N;;;;; +1D06;LATIN LETTER SMALL CAPITAL ETH;Ll;0;L;;;;;N;;;;; +1D07;LATIN LETTER SMALL CAPITAL E;Ll;0;L;;;;;N;;;;; +1D08;LATIN SMALL LETTER TURNED OPEN E;Ll;0;L;;;;;N;;;;; +1D09;LATIN SMALL LETTER TURNED I;Ll;0;L;;;;;N;;;;; +1D0A;LATIN LETTER SMALL CAPITAL J;Ll;0;L;;;;;N;;;;; +1D0B;LATIN LETTER SMALL CAPITAL K;Ll;0;L;;;;;N;;;;; +1D0C;LATIN LETTER SMALL CAPITAL L WITH STROKE;Ll;0;L;;;;;N;;;;; +1D0D;LATIN LETTER SMALL CAPITAL M;Ll;0;L;;;;;N;;;;; +1D0E;LATIN LETTER SMALL CAPITAL REVERSED N;Ll;0;L;;;;;N;;;;; +1D0F;LATIN LETTER SMALL CAPITAL O;Ll;0;L;;;;;N;;;;; +1D10;LATIN LETTER SMALL CAPITAL OPEN O;Ll;0;L;;;;;N;;;;; +1D11;LATIN SMALL LETTER SIDEWAYS O;Ll;0;L;;;;;N;;;;; +1D12;LATIN SMALL LETTER SIDEWAYS OPEN O;Ll;0;L;;;;;N;;;;; +1D13;LATIN SMALL LETTER SIDEWAYS O WITH STROKE;Ll;0;L;;;;;N;;;;; +1D14;LATIN SMALL LETTER TURNED OE;Ll;0;L;;;;;N;;;;; +1D15;LATIN LETTER SMALL CAPITAL OU;Ll;0;L;;;;;N;;;;; +1D16;LATIN SMALL LETTER TOP HALF O;Ll;0;L;;;;;N;;;;; +1D17;LATIN SMALL LETTER BOTTOM HALF O;Ll;0;L;;;;;N;;;;; +1D18;LATIN LETTER SMALL CAPITAL P;Ll;0;L;;;;;N;;;;; +1D19;LATIN LETTER SMALL CAPITAL REVERSED R;Ll;0;L;;;;;N;;;;; +1D1A;LATIN LETTER SMALL CAPITAL TURNED R;Ll;0;L;;;;;N;;;;; +1D1B;LATIN LETTER SMALL CAPITAL T;Ll;0;L;;;;;N;;;;; +1D1C;LATIN LETTER SMALL CAPITAL U;Ll;0;L;;;;;N;;;;; +1D1D;LATIN SMALL LETTER SIDEWAYS U;Ll;0;L;;;;;N;;;;; +1D1E;LATIN SMALL LETTER SIDEWAYS DIAERESIZED U;Ll;0;L;;;;;N;;;;; +1D1F;LATIN SMALL LETTER SIDEWAYS TURNED M;Ll;0;L;;;;;N;;;;; +1D20;LATIN LETTER SMALL CAPITAL V;Ll;0;L;;;;;N;;;;; +1D21;LATIN LETTER SMALL CAPITAL W;Ll;0;L;;;;;N;;;;; +1D22;LATIN LETTER SMALL CAPITAL Z;Ll;0;L;;;;;N;;;;; +1D23;LATIN LETTER SMALL CAPITAL EZH;Ll;0;L;;;;;N;;;;; +1D24;LATIN LETTER VOICED LARYNGEAL SPIRANT;Ll;0;L;;;;;N;;;;; +1D25;LATIN LETTER AIN;Ll;0;L;;;;;N;;;;; +1D26;GREEK LETTER SMALL CAPITAL GAMMA;Ll;0;L;;;;;N;;;;; +1D27;GREEK LETTER SMALL CAPITAL LAMDA;Ll;0;L;;;;;N;;;;; +1D28;GREEK LETTER SMALL CAPITAL PI;Ll;0;L;;;;;N;;;;; +1D29;GREEK LETTER SMALL CAPITAL RHO;Ll;0;L;;;;;N;;;;; +1D2A;GREEK LETTER SMALL CAPITAL PSI;Ll;0;L;;;;;N;;;;; +1D2B;CYRILLIC LETTER SMALL CAPITAL EL;Ll;0;L;;;;;N;;;;; +1D2C;MODIFIER LETTER CAPITAL A;Lm;0;L;<super> 0041;;;;N;;;;; +1D2D;MODIFIER LETTER CAPITAL AE;Lm;0;L;<super> 00C6;;;;N;;;;; +1D2E;MODIFIER LETTER CAPITAL B;Lm;0;L;<super> 0042;;;;N;;;;; +1D2F;MODIFIER LETTER CAPITAL BARRED B;Lm;0;L;;;;;N;;;;; +1D30;MODIFIER LETTER CAPITAL D;Lm;0;L;<super> 0044;;;;N;;;;; +1D31;MODIFIER LETTER CAPITAL E;Lm;0;L;<super> 0045;;;;N;;;;; +1D32;MODIFIER LETTER CAPITAL REVERSED E;Lm;0;L;<super> 018E;;;;N;;;;; +1D33;MODIFIER LETTER CAPITAL G;Lm;0;L;<super> 0047;;;;N;;;;; +1D34;MODIFIER LETTER CAPITAL H;Lm;0;L;<super> 0048;;;;N;;;;; +1D35;MODIFIER LETTER CAPITAL I;Lm;0;L;<super> 0049;;;;N;;;;; +1D36;MODIFIER LETTER CAPITAL J;Lm;0;L;<super> 004A;;;;N;;;;; +1D37;MODIFIER LETTER CAPITAL K;Lm;0;L;<super> 004B;;;;N;;;;; +1D38;MODIFIER LETTER CAPITAL L;Lm;0;L;<super> 004C;;;;N;;;;; +1D39;MODIFIER LETTER CAPITAL M;Lm;0;L;<super> 004D;;;;N;;;;; +1D3A;MODIFIER LETTER CAPITAL N;Lm;0;L;<super> 004E;;;;N;;;;; +1D3B;MODIFIER LETTER CAPITAL REVERSED N;Lm;0;L;;;;;N;;;;; +1D3C;MODIFIER LETTER CAPITAL O;Lm;0;L;<super> 004F;;;;N;;;;; +1D3D;MODIFIER LETTER CAPITAL OU;Lm;0;L;<super> 0222;;;;N;;;;; +1D3E;MODIFIER LETTER CAPITAL P;Lm;0;L;<super> 0050;;;;N;;;;; +1D3F;MODIFIER LETTER CAPITAL R;Lm;0;L;<super> 0052;;;;N;;;;; +1D40;MODIFIER LETTER CAPITAL T;Lm;0;L;<super> 0054;;;;N;;;;; +1D41;MODIFIER LETTER CAPITAL U;Lm;0;L;<super> 0055;;;;N;;;;; +1D42;MODIFIER LETTER CAPITAL W;Lm;0;L;<super> 0057;;;;N;;;;; +1D43;MODIFIER LETTER SMALL A;Lm;0;L;<super> 0061;;;;N;;;;; +1D44;MODIFIER LETTER SMALL TURNED A;Lm;0;L;<super> 0250;;;;N;;;;; +1D45;MODIFIER LETTER SMALL ALPHA;Lm;0;L;<super> 0251;;;;N;;;;; +1D46;MODIFIER LETTER SMALL TURNED AE;Lm;0;L;<super> 1D02;;;;N;;;;; +1D47;MODIFIER LETTER SMALL B;Lm;0;L;<super> 0062;;;;N;;;;; +1D48;MODIFIER LETTER SMALL D;Lm;0;L;<super> 0064;;;;N;;;;; +1D49;MODIFIER LETTER SMALL E;Lm;0;L;<super> 0065;;;;N;;;;; +1D4A;MODIFIER LETTER SMALL SCHWA;Lm;0;L;<super> 0259;;;;N;;;;; +1D4B;MODIFIER LETTER SMALL OPEN E;Lm;0;L;<super> 025B;;;;N;;;;; +1D4C;MODIFIER LETTER SMALL TURNED OPEN E;Lm;0;L;<super> 025C;;;;N;;;;; +1D4D;MODIFIER LETTER SMALL G;Lm;0;L;<super> 0067;;;;N;;;;; +1D4E;MODIFIER LETTER SMALL TURNED I;Lm;0;L;;;;;N;;;;; +1D4F;MODIFIER LETTER SMALL K;Lm;0;L;<super> 006B;;;;N;;;;; +1D50;MODIFIER LETTER SMALL M;Lm;0;L;<super> 006D;;;;N;;;;; +1D51;MODIFIER LETTER SMALL ENG;Lm;0;L;<super> 014B;;;;N;;;;; +1D52;MODIFIER LETTER SMALL O;Lm;0;L;<super> 006F;;;;N;;;;; +1D53;MODIFIER LETTER SMALL OPEN O;Lm;0;L;<super> 0254;;;;N;;;;; +1D54;MODIFIER LETTER SMALL TOP HALF O;Lm;0;L;<super> 1D16;;;;N;;;;; +1D55;MODIFIER LETTER SMALL BOTTOM HALF O;Lm;0;L;<super> 1D17;;;;N;;;;; +1D56;MODIFIER LETTER SMALL P;Lm;0;L;<super> 0070;;;;N;;;;; +1D57;MODIFIER LETTER SMALL T;Lm;0;L;<super> 0074;;;;N;;;;; +1D58;MODIFIER LETTER SMALL U;Lm;0;L;<super> 0075;;;;N;;;;; +1D59;MODIFIER LETTER SMALL SIDEWAYS U;Lm;0;L;<super> 1D1D;;;;N;;;;; +1D5A;MODIFIER LETTER SMALL TURNED M;Lm;0;L;<super> 026F;;;;N;;;;; +1D5B;MODIFIER LETTER SMALL V;Lm;0;L;<super> 0076;;;;N;;;;; +1D5C;MODIFIER LETTER SMALL AIN;Lm;0;L;<super> 1D25;;;;N;;;;; +1D5D;MODIFIER LETTER SMALL BETA;Lm;0;L;<super> 03B2;;;;N;;;;; +1D5E;MODIFIER LETTER SMALL GREEK GAMMA;Lm;0;L;<super> 03B3;;;;N;;;;; +1D5F;MODIFIER LETTER SMALL DELTA;Lm;0;L;<super> 03B4;;;;N;;;;; +1D60;MODIFIER LETTER SMALL GREEK PHI;Lm;0;L;<super> 03C6;;;;N;;;;; +1D61;MODIFIER LETTER SMALL CHI;Lm;0;L;<super> 03C7;;;;N;;;;; +1D62;LATIN SUBSCRIPT SMALL LETTER I;Lm;0;L;<sub> 0069;;;;N;;;;; +1D63;LATIN SUBSCRIPT SMALL LETTER R;Lm;0;L;<sub> 0072;;;;N;;;;; +1D64;LATIN SUBSCRIPT SMALL LETTER U;Lm;0;L;<sub> 0075;;;;N;;;;; +1D65;LATIN SUBSCRIPT SMALL LETTER V;Lm;0;L;<sub> 0076;;;;N;;;;; +1D66;GREEK SUBSCRIPT SMALL LETTER BETA;Lm;0;L;<sub> 03B2;;;;N;;;;; +1D67;GREEK SUBSCRIPT SMALL LETTER GAMMA;Lm;0;L;<sub> 03B3;;;;N;;;;; +1D68;GREEK SUBSCRIPT SMALL LETTER RHO;Lm;0;L;<sub> 03C1;;;;N;;;;; +1D69;GREEK SUBSCRIPT SMALL LETTER PHI;Lm;0;L;<sub> 03C6;;;;N;;;;; +1D6A;GREEK SUBSCRIPT SMALL LETTER CHI;Lm;0;L;<sub> 03C7;;;;N;;;;; +1D6B;LATIN SMALL LETTER UE;Ll;0;L;;;;;N;;;;; +1D6C;LATIN SMALL LETTER B WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D6D;LATIN SMALL LETTER D WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D6E;LATIN SMALL LETTER F WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D6F;LATIN SMALL LETTER M WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D70;LATIN SMALL LETTER N WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D71;LATIN SMALL LETTER P WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D72;LATIN SMALL LETTER R WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D73;LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D74;LATIN SMALL LETTER S WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D75;LATIN SMALL LETTER T WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D76;LATIN SMALL LETTER Z WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D77;LATIN SMALL LETTER TURNED G;Ll;0;L;;;;;N;;;;; +1D78;MODIFIER LETTER CYRILLIC EN;Lm;0;L;<super> 043D;;;;N;;;;; +1D79;LATIN SMALL LETTER INSULAR G;Ll;0;L;;;;;N;;;A77D;;A77D +1D7A;LATIN SMALL LETTER TH WITH STRIKETHROUGH;Ll;0;L;;;;;N;;;;; +1D7B;LATIN SMALL CAPITAL LETTER I WITH STROKE;Ll;0;L;;;;;N;;;;; +1D7C;LATIN SMALL LETTER IOTA WITH STROKE;Ll;0;L;;;;;N;;;;; +1D7D;LATIN SMALL LETTER P WITH STROKE;Ll;0;L;;;;;N;;;2C63;;2C63 +1D7E;LATIN SMALL CAPITAL LETTER U WITH STROKE;Ll;0;L;;;;;N;;;;; +1D7F;LATIN SMALL LETTER UPSILON WITH STROKE;Ll;0;L;;;;;N;;;;; +1D80;LATIN SMALL LETTER B WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D81;LATIN SMALL LETTER D WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D82;LATIN SMALL LETTER F WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D83;LATIN SMALL LETTER G WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D84;LATIN SMALL LETTER K WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D85;LATIN SMALL LETTER L WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D86;LATIN SMALL LETTER M WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D87;LATIN SMALL LETTER N WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D88;LATIN SMALL LETTER P WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D89;LATIN SMALL LETTER R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8A;LATIN SMALL LETTER S WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8B;LATIN SMALL LETTER ESH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8C;LATIN SMALL LETTER V WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8D;LATIN SMALL LETTER X WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8E;LATIN SMALL LETTER Z WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8F;LATIN SMALL LETTER A WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D90;LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D91;LATIN SMALL LETTER D WITH HOOK AND TAIL;Ll;0;L;;;;;N;;;;; +1D92;LATIN SMALL LETTER E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D93;LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D94;LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D95;LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D96;LATIN SMALL LETTER I WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D97;LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D98;LATIN SMALL LETTER ESH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D99;LATIN SMALL LETTER U WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D9A;LATIN SMALL LETTER EZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D9B;MODIFIER LETTER SMALL TURNED ALPHA;Lm;0;L;<super> 0252;;;;N;;;;; +1D9C;MODIFIER LETTER SMALL C;Lm;0;L;<super> 0063;;;;N;;;;; +1D9D;MODIFIER LETTER SMALL C WITH CURL;Lm;0;L;<super> 0255;;;;N;;;;; +1D9E;MODIFIER LETTER SMALL ETH;Lm;0;L;<super> 00F0;;;;N;;;;; +1D9F;MODIFIER LETTER SMALL REVERSED OPEN E;Lm;0;L;<super> 025C;;;;N;;;;; +1DA0;MODIFIER LETTER SMALL F;Lm;0;L;<super> 0066;;;;N;;;;; +1DA1;MODIFIER LETTER SMALL DOTLESS J WITH STROKE;Lm;0;L;<super> 025F;;;;N;;;;; +1DA2;MODIFIER LETTER SMALL SCRIPT G;Lm;0;L;<super> 0261;;;;N;;;;; +1DA3;MODIFIER LETTER SMALL TURNED H;Lm;0;L;<super> 0265;;;;N;;;;; +1DA4;MODIFIER LETTER SMALL I WITH STROKE;Lm;0;L;<super> 0268;;;;N;;;;; +1DA5;MODIFIER LETTER SMALL IOTA;Lm;0;L;<super> 0269;;;;N;;;;; +1DA6;MODIFIER LETTER SMALL CAPITAL I;Lm;0;L;<super> 026A;;;;N;;;;; +1DA7;MODIFIER LETTER SMALL CAPITAL I WITH STROKE;Lm;0;L;<super> 1D7B;;;;N;;;;; +1DA8;MODIFIER LETTER SMALL J WITH CROSSED-TAIL;Lm;0;L;<super> 029D;;;;N;;;;; +1DA9;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK;Lm;0;L;<super> 026D;;;;N;;;;; +1DAA;MODIFIER LETTER SMALL L WITH PALATAL HOOK;Lm;0;L;<super> 1D85;;;;N;;;;; +1DAB;MODIFIER LETTER SMALL CAPITAL L;Lm;0;L;<super> 029F;;;;N;;;;; +1DAC;MODIFIER LETTER SMALL M WITH HOOK;Lm;0;L;<super> 0271;;;;N;;;;; +1DAD;MODIFIER LETTER SMALL TURNED M WITH LONG LEG;Lm;0;L;<super> 0270;;;;N;;;;; +1DAE;MODIFIER LETTER SMALL N WITH LEFT HOOK;Lm;0;L;<super> 0272;;;;N;;;;; +1DAF;MODIFIER LETTER SMALL N WITH RETROFLEX HOOK;Lm;0;L;<super> 0273;;;;N;;;;; +1DB0;MODIFIER LETTER SMALL CAPITAL N;Lm;0;L;<super> 0274;;;;N;;;;; +1DB1;MODIFIER LETTER SMALL BARRED O;Lm;0;L;<super> 0275;;;;N;;;;; +1DB2;MODIFIER LETTER SMALL PHI;Lm;0;L;<super> 0278;;;;N;;;;; +1DB3;MODIFIER LETTER SMALL S WITH HOOK;Lm;0;L;<super> 0282;;;;N;;;;; +1DB4;MODIFIER LETTER SMALL ESH;Lm;0;L;<super> 0283;;;;N;;;;; +1DB5;MODIFIER LETTER SMALL T WITH PALATAL HOOK;Lm;0;L;<super> 01AB;;;;N;;;;; +1DB6;MODIFIER LETTER SMALL U BAR;Lm;0;L;<super> 0289;;;;N;;;;; +1DB7;MODIFIER LETTER SMALL UPSILON;Lm;0;L;<super> 028A;;;;N;;;;; +1DB8;MODIFIER LETTER SMALL CAPITAL U;Lm;0;L;<super> 1D1C;;;;N;;;;; +1DB9;MODIFIER LETTER SMALL V WITH HOOK;Lm;0;L;<super> 028B;;;;N;;;;; +1DBA;MODIFIER LETTER SMALL TURNED V;Lm;0;L;<super> 028C;;;;N;;;;; +1DBB;MODIFIER LETTER SMALL Z;Lm;0;L;<super> 007A;;;;N;;;;; +1DBC;MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK;Lm;0;L;<super> 0290;;;;N;;;;; +1DBD;MODIFIER LETTER SMALL Z WITH CURL;Lm;0;L;<super> 0291;;;;N;;;;; +1DBE;MODIFIER LETTER SMALL EZH;Lm;0;L;<super> 0292;;;;N;;;;; +1DBF;MODIFIER LETTER SMALL THETA;Lm;0;L;<super> 03B8;;;;N;;;;; +1DC0;COMBINING DOTTED GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; +1DC1;COMBINING DOTTED ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; +1DC2;COMBINING SNAKE BELOW;Mn;220;NSM;;;;;N;;;;; +1DC3;COMBINING SUSPENSION MARK;Mn;230;NSM;;;;;N;;;;; +1DC4;COMBINING MACRON-ACUTE;Mn;230;NSM;;;;;N;;;;; +1DC5;COMBINING GRAVE-MACRON;Mn;230;NSM;;;;;N;;;;; +1DC6;COMBINING MACRON-GRAVE;Mn;230;NSM;;;;;N;;;;; +1DC7;COMBINING ACUTE-MACRON;Mn;230;NSM;;;;;N;;;;; +1DC8;COMBINING GRAVE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;; +1DC9;COMBINING ACUTE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;; +1DCA;COMBINING LATIN SMALL LETTER R BELOW;Mn;220;NSM;;;;;N;;;;; +1DCB;COMBINING BREVE-MACRON;Mn;230;NSM;;;;;N;;;;; +1DCC;COMBINING MACRON-BREVE;Mn;230;NSM;;;;;N;;;;; +1DCD;COMBINING DOUBLE CIRCUMFLEX ABOVE;Mn;234;NSM;;;;;N;;;;; +1DCE;COMBINING OGONEK ABOVE;Mn;214;NSM;;;;;N;;;;; +1DCF;COMBINING ZIGZAG BELOW;Mn;220;NSM;;;;;N;;;;; +1DD0;COMBINING IS BELOW;Mn;202;NSM;;;;;N;;;;; +1DD1;COMBINING UR ABOVE;Mn;230;NSM;;;;;N;;;;; +1DD2;COMBINING US ABOVE;Mn;230;NSM;;;;;N;;;;; +1DD3;COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE;Mn;230;NSM;;;;;N;;;;; +1DD4;COMBINING LATIN SMALL LETTER AE;Mn;230;NSM;;;;;N;;;;; +1DD5;COMBINING LATIN SMALL LETTER AO;Mn;230;NSM;;;;;N;;;;; +1DD6;COMBINING LATIN SMALL LETTER AV;Mn;230;NSM;;;;;N;;;;; +1DD7;COMBINING LATIN SMALL LETTER C CEDILLA;Mn;230;NSM;;;;;N;;;;; +1DD8;COMBINING LATIN SMALL LETTER INSULAR D;Mn;230;NSM;;;;;N;;;;; +1DD9;COMBINING LATIN SMALL LETTER ETH;Mn;230;NSM;;;;;N;;;;; +1DDA;COMBINING LATIN SMALL LETTER G;Mn;230;NSM;;;;;N;;;;; +1DDB;COMBINING LATIN LETTER SMALL CAPITAL G;Mn;230;NSM;;;;;N;;;;; +1DDC;COMBINING LATIN SMALL LETTER K;Mn;230;NSM;;;;;N;;;;; +1DDD;COMBINING LATIN SMALL LETTER L;Mn;230;NSM;;;;;N;;;;; +1DDE;COMBINING LATIN LETTER SMALL CAPITAL L;Mn;230;NSM;;;;;N;;;;; +1DDF;COMBINING LATIN LETTER SMALL CAPITAL M;Mn;230;NSM;;;;;N;;;;; +1DE0;COMBINING LATIN SMALL LETTER N;Mn;230;NSM;;;;;N;;;;; +1DE1;COMBINING LATIN LETTER SMALL CAPITAL N;Mn;230;NSM;;;;;N;;;;; +1DE2;COMBINING LATIN LETTER SMALL CAPITAL R;Mn;230;NSM;;;;;N;;;;; +1DE3;COMBINING LATIN SMALL LETTER R ROTUNDA;Mn;230;NSM;;;;;N;;;;; +1DE4;COMBINING LATIN SMALL LETTER S;Mn;230;NSM;;;;;N;;;;; +1DE5;COMBINING LATIN SMALL LETTER LONG S;Mn;230;NSM;;;;;N;;;;; +1DE6;COMBINING LATIN SMALL LETTER Z;Mn;230;NSM;;;;;N;;;;; +1DE7;COMBINING LATIN SMALL LETTER ALPHA;Mn;230;NSM;;;;;N;;;;; +1DE8;COMBINING LATIN SMALL LETTER B;Mn;230;NSM;;;;;N;;;;; +1DE9;COMBINING LATIN SMALL LETTER BETA;Mn;230;NSM;;;;;N;;;;; +1DEA;COMBINING LATIN SMALL LETTER SCHWA;Mn;230;NSM;;;;;N;;;;; +1DEB;COMBINING LATIN SMALL LETTER F;Mn;230;NSM;;;;;N;;;;; +1DEC;COMBINING LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE;Mn;230;NSM;;;;;N;;;;; +1DED;COMBINING LATIN SMALL LETTER O WITH LIGHT CENTRALIZATION STROKE;Mn;230;NSM;;;;;N;;;;; +1DEE;COMBINING LATIN SMALL LETTER P;Mn;230;NSM;;;;;N;;;;; +1DEF;COMBINING LATIN SMALL LETTER ESH;Mn;230;NSM;;;;;N;;;;; +1DF0;COMBINING LATIN SMALL LETTER U WITH LIGHT CENTRALIZATION STROKE;Mn;230;NSM;;;;;N;;;;; +1DF1;COMBINING LATIN SMALL LETTER W;Mn;230;NSM;;;;;N;;;;; +1DF2;COMBINING LATIN SMALL LETTER A WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; +1DF3;COMBINING LATIN SMALL LETTER O WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; +1DF4;COMBINING LATIN SMALL LETTER U WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; +1DF5;COMBINING UP TACK ABOVE;Mn;230;NSM;;;;;N;;;;; +1DF6;COMBINING KAVYKA ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; +1DF7;COMBINING KAVYKA ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF8;COMBINING DOT ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF9;COMBINING WIDE INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;;;;; +1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;; +1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; +1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; +1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +1DFF;COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +1E00;LATIN CAPITAL LETTER A WITH RING BELOW;Lu;0;L;0041 0325;;;;N;;;;1E01; +1E01;LATIN SMALL LETTER A WITH RING BELOW;Ll;0;L;0061 0325;;;;N;;;1E00;;1E00 +1E02;LATIN CAPITAL LETTER B WITH DOT ABOVE;Lu;0;L;0042 0307;;;;N;;;;1E03; +1E03;LATIN SMALL LETTER B WITH DOT ABOVE;Ll;0;L;0062 0307;;;;N;;;1E02;;1E02 +1E04;LATIN CAPITAL LETTER B WITH DOT BELOW;Lu;0;L;0042 0323;;;;N;;;;1E05; +1E05;LATIN SMALL LETTER B WITH DOT BELOW;Ll;0;L;0062 0323;;;;N;;;1E04;;1E04 +1E06;LATIN CAPITAL LETTER B WITH LINE BELOW;Lu;0;L;0042 0331;;;;N;;;;1E07; +1E07;LATIN SMALL LETTER B WITH LINE BELOW;Ll;0;L;0062 0331;;;;N;;;1E06;;1E06 +1E08;LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE;Lu;0;L;00C7 0301;;;;N;;;;1E09; +1E09;LATIN SMALL LETTER C WITH CEDILLA AND ACUTE;Ll;0;L;00E7 0301;;;;N;;;1E08;;1E08 +1E0A;LATIN CAPITAL LETTER D WITH DOT ABOVE;Lu;0;L;0044 0307;;;;N;;;;1E0B; +1E0B;LATIN SMALL LETTER D WITH DOT ABOVE;Ll;0;L;0064 0307;;;;N;;;1E0A;;1E0A +1E0C;LATIN CAPITAL LETTER D WITH DOT BELOW;Lu;0;L;0044 0323;;;;N;;;;1E0D; +1E0D;LATIN SMALL LETTER D WITH DOT BELOW;Ll;0;L;0064 0323;;;;N;;;1E0C;;1E0C +1E0E;LATIN CAPITAL LETTER D WITH LINE BELOW;Lu;0;L;0044 0331;;;;N;;;;1E0F; +1E0F;LATIN SMALL LETTER D WITH LINE BELOW;Ll;0;L;0064 0331;;;;N;;;1E0E;;1E0E +1E10;LATIN CAPITAL LETTER D WITH CEDILLA;Lu;0;L;0044 0327;;;;N;;;;1E11; +1E11;LATIN SMALL LETTER D WITH CEDILLA;Ll;0;L;0064 0327;;;;N;;;1E10;;1E10 +1E12;LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW;Lu;0;L;0044 032D;;;;N;;;;1E13; +1E13;LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW;Ll;0;L;0064 032D;;;;N;;;1E12;;1E12 +1E14;LATIN CAPITAL LETTER E WITH MACRON AND GRAVE;Lu;0;L;0112 0300;;;;N;;;;1E15; +1E15;LATIN SMALL LETTER E WITH MACRON AND GRAVE;Ll;0;L;0113 0300;;;;N;;;1E14;;1E14 +1E16;LATIN CAPITAL LETTER E WITH MACRON AND ACUTE;Lu;0;L;0112 0301;;;;N;;;;1E17; +1E17;LATIN SMALL LETTER E WITH MACRON AND ACUTE;Ll;0;L;0113 0301;;;;N;;;1E16;;1E16 +1E18;LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW;Lu;0;L;0045 032D;;;;N;;;;1E19; +1E19;LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW;Ll;0;L;0065 032D;;;;N;;;1E18;;1E18 +1E1A;LATIN CAPITAL LETTER E WITH TILDE BELOW;Lu;0;L;0045 0330;;;;N;;;;1E1B; +1E1B;LATIN SMALL LETTER E WITH TILDE BELOW;Ll;0;L;0065 0330;;;;N;;;1E1A;;1E1A +1E1C;LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE;Lu;0;L;0228 0306;;;;N;;;;1E1D; +1E1D;LATIN SMALL LETTER E WITH CEDILLA AND BREVE;Ll;0;L;0229 0306;;;;N;;;1E1C;;1E1C +1E1E;LATIN CAPITAL LETTER F WITH DOT ABOVE;Lu;0;L;0046 0307;;;;N;;;;1E1F; +1E1F;LATIN SMALL LETTER F WITH DOT ABOVE;Ll;0;L;0066 0307;;;;N;;;1E1E;;1E1E +1E20;LATIN CAPITAL LETTER G WITH MACRON;Lu;0;L;0047 0304;;;;N;;;;1E21; +1E21;LATIN SMALL LETTER G WITH MACRON;Ll;0;L;0067 0304;;;;N;;;1E20;;1E20 +1E22;LATIN CAPITAL LETTER H WITH DOT ABOVE;Lu;0;L;0048 0307;;;;N;;;;1E23; +1E23;LATIN SMALL LETTER H WITH DOT ABOVE;Ll;0;L;0068 0307;;;;N;;;1E22;;1E22 +1E24;LATIN CAPITAL LETTER H WITH DOT BELOW;Lu;0;L;0048 0323;;;;N;;;;1E25; +1E25;LATIN SMALL LETTER H WITH DOT BELOW;Ll;0;L;0068 0323;;;;N;;;1E24;;1E24 +1E26;LATIN CAPITAL LETTER H WITH DIAERESIS;Lu;0;L;0048 0308;;;;N;;;;1E27; +1E27;LATIN SMALL LETTER H WITH DIAERESIS;Ll;0;L;0068 0308;;;;N;;;1E26;;1E26 +1E28;LATIN CAPITAL LETTER H WITH CEDILLA;Lu;0;L;0048 0327;;;;N;;;;1E29; +1E29;LATIN SMALL LETTER H WITH CEDILLA;Ll;0;L;0068 0327;;;;N;;;1E28;;1E28 +1E2A;LATIN CAPITAL LETTER H WITH BREVE BELOW;Lu;0;L;0048 032E;;;;N;;;;1E2B; +1E2B;LATIN SMALL LETTER H WITH BREVE BELOW;Ll;0;L;0068 032E;;;;N;;;1E2A;;1E2A +1E2C;LATIN CAPITAL LETTER I WITH TILDE BELOW;Lu;0;L;0049 0330;;;;N;;;;1E2D; +1E2D;LATIN SMALL LETTER I WITH TILDE BELOW;Ll;0;L;0069 0330;;;;N;;;1E2C;;1E2C +1E2E;LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE;Lu;0;L;00CF 0301;;;;N;;;;1E2F; +1E2F;LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE;Ll;0;L;00EF 0301;;;;N;;;1E2E;;1E2E +1E30;LATIN CAPITAL LETTER K WITH ACUTE;Lu;0;L;004B 0301;;;;N;;;;1E31; +1E31;LATIN SMALL LETTER K WITH ACUTE;Ll;0;L;006B 0301;;;;N;;;1E30;;1E30 +1E32;LATIN CAPITAL LETTER K WITH DOT BELOW;Lu;0;L;004B 0323;;;;N;;;;1E33; +1E33;LATIN SMALL LETTER K WITH DOT BELOW;Ll;0;L;006B 0323;;;;N;;;1E32;;1E32 +1E34;LATIN CAPITAL LETTER K WITH LINE BELOW;Lu;0;L;004B 0331;;;;N;;;;1E35; +1E35;LATIN SMALL LETTER K WITH LINE BELOW;Ll;0;L;006B 0331;;;;N;;;1E34;;1E34 +1E36;LATIN CAPITAL LETTER L WITH DOT BELOW;Lu;0;L;004C 0323;;;;N;;;;1E37; +1E37;LATIN SMALL LETTER L WITH DOT BELOW;Ll;0;L;006C 0323;;;;N;;;1E36;;1E36 +1E38;LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON;Lu;0;L;1E36 0304;;;;N;;;;1E39; +1E39;LATIN SMALL LETTER L WITH DOT BELOW AND MACRON;Ll;0;L;1E37 0304;;;;N;;;1E38;;1E38 +1E3A;LATIN CAPITAL LETTER L WITH LINE BELOW;Lu;0;L;004C 0331;;;;N;;;;1E3B; +1E3B;LATIN SMALL LETTER L WITH LINE BELOW;Ll;0;L;006C 0331;;;;N;;;1E3A;;1E3A +1E3C;LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW;Lu;0;L;004C 032D;;;;N;;;;1E3D; +1E3D;LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW;Ll;0;L;006C 032D;;;;N;;;1E3C;;1E3C +1E3E;LATIN CAPITAL LETTER M WITH ACUTE;Lu;0;L;004D 0301;;;;N;;;;1E3F; +1E3F;LATIN SMALL LETTER M WITH ACUTE;Ll;0;L;006D 0301;;;;N;;;1E3E;;1E3E +1E40;LATIN CAPITAL LETTER M WITH DOT ABOVE;Lu;0;L;004D 0307;;;;N;;;;1E41; +1E41;LATIN SMALL LETTER M WITH DOT ABOVE;Ll;0;L;006D 0307;;;;N;;;1E40;;1E40 +1E42;LATIN CAPITAL LETTER M WITH DOT BELOW;Lu;0;L;004D 0323;;;;N;;;;1E43; +1E43;LATIN SMALL LETTER M WITH DOT BELOW;Ll;0;L;006D 0323;;;;N;;;1E42;;1E42 +1E44;LATIN CAPITAL LETTER N WITH DOT ABOVE;Lu;0;L;004E 0307;;;;N;;;;1E45; +1E45;LATIN SMALL LETTER N WITH DOT ABOVE;Ll;0;L;006E 0307;;;;N;;;1E44;;1E44 +1E46;LATIN CAPITAL LETTER N WITH DOT BELOW;Lu;0;L;004E 0323;;;;N;;;;1E47; +1E47;LATIN SMALL LETTER N WITH DOT BELOW;Ll;0;L;006E 0323;;;;N;;;1E46;;1E46 +1E48;LATIN CAPITAL LETTER N WITH LINE BELOW;Lu;0;L;004E 0331;;;;N;;;;1E49; +1E49;LATIN SMALL LETTER N WITH LINE BELOW;Ll;0;L;006E 0331;;;;N;;;1E48;;1E48 +1E4A;LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW;Lu;0;L;004E 032D;;;;N;;;;1E4B; +1E4B;LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW;Ll;0;L;006E 032D;;;;N;;;1E4A;;1E4A +1E4C;LATIN CAPITAL LETTER O WITH TILDE AND ACUTE;Lu;0;L;00D5 0301;;;;N;;;;1E4D; +1E4D;LATIN SMALL LETTER O WITH TILDE AND ACUTE;Ll;0;L;00F5 0301;;;;N;;;1E4C;;1E4C +1E4E;LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS;Lu;0;L;00D5 0308;;;;N;;;;1E4F; +1E4F;LATIN SMALL LETTER O WITH TILDE AND DIAERESIS;Ll;0;L;00F5 0308;;;;N;;;1E4E;;1E4E +1E50;LATIN CAPITAL LETTER O WITH MACRON AND GRAVE;Lu;0;L;014C 0300;;;;N;;;;1E51; +1E51;LATIN SMALL LETTER O WITH MACRON AND GRAVE;Ll;0;L;014D 0300;;;;N;;;1E50;;1E50 +1E52;LATIN CAPITAL LETTER O WITH MACRON AND ACUTE;Lu;0;L;014C 0301;;;;N;;;;1E53; +1E53;LATIN SMALL LETTER O WITH MACRON AND ACUTE;Ll;0;L;014D 0301;;;;N;;;1E52;;1E52 +1E54;LATIN CAPITAL LETTER P WITH ACUTE;Lu;0;L;0050 0301;;;;N;;;;1E55; +1E55;LATIN SMALL LETTER P WITH ACUTE;Ll;0;L;0070 0301;;;;N;;;1E54;;1E54 +1E56;LATIN CAPITAL LETTER P WITH DOT ABOVE;Lu;0;L;0050 0307;;;;N;;;;1E57; +1E57;LATIN SMALL LETTER P WITH DOT ABOVE;Ll;0;L;0070 0307;;;;N;;;1E56;;1E56 +1E58;LATIN CAPITAL LETTER R WITH DOT ABOVE;Lu;0;L;0052 0307;;;;N;;;;1E59; +1E59;LATIN SMALL LETTER R WITH DOT ABOVE;Ll;0;L;0072 0307;;;;N;;;1E58;;1E58 +1E5A;LATIN CAPITAL LETTER R WITH DOT BELOW;Lu;0;L;0052 0323;;;;N;;;;1E5B; +1E5B;LATIN SMALL LETTER R WITH DOT BELOW;Ll;0;L;0072 0323;;;;N;;;1E5A;;1E5A +1E5C;LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON;Lu;0;L;1E5A 0304;;;;N;;;;1E5D; +1E5D;LATIN SMALL LETTER R WITH DOT BELOW AND MACRON;Ll;0;L;1E5B 0304;;;;N;;;1E5C;;1E5C +1E5E;LATIN CAPITAL LETTER R WITH LINE BELOW;Lu;0;L;0052 0331;;;;N;;;;1E5F; +1E5F;LATIN SMALL LETTER R WITH LINE BELOW;Ll;0;L;0072 0331;;;;N;;;1E5E;;1E5E +1E60;LATIN CAPITAL LETTER S WITH DOT ABOVE;Lu;0;L;0053 0307;;;;N;;;;1E61; +1E61;LATIN SMALL LETTER S WITH DOT ABOVE;Ll;0;L;0073 0307;;;;N;;;1E60;;1E60 +1E62;LATIN CAPITAL LETTER S WITH DOT BELOW;Lu;0;L;0053 0323;;;;N;;;;1E63; +1E63;LATIN SMALL LETTER S WITH DOT BELOW;Ll;0;L;0073 0323;;;;N;;;1E62;;1E62 +1E64;LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE;Lu;0;L;015A 0307;;;;N;;;;1E65; +1E65;LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE;Ll;0;L;015B 0307;;;;N;;;1E64;;1E64 +1E66;LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE;Lu;0;L;0160 0307;;;;N;;;;1E67; +1E67;LATIN SMALL LETTER S WITH CARON AND DOT ABOVE;Ll;0;L;0161 0307;;;;N;;;1E66;;1E66 +1E68;LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE;Lu;0;L;1E62 0307;;;;N;;;;1E69; +1E69;LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE;Ll;0;L;1E63 0307;;;;N;;;1E68;;1E68 +1E6A;LATIN CAPITAL LETTER T WITH DOT ABOVE;Lu;0;L;0054 0307;;;;N;;;;1E6B; +1E6B;LATIN SMALL LETTER T WITH DOT ABOVE;Ll;0;L;0074 0307;;;;N;;;1E6A;;1E6A +1E6C;LATIN CAPITAL LETTER T WITH DOT BELOW;Lu;0;L;0054 0323;;;;N;;;;1E6D; +1E6D;LATIN SMALL LETTER T WITH DOT BELOW;Ll;0;L;0074 0323;;;;N;;;1E6C;;1E6C +1E6E;LATIN CAPITAL LETTER T WITH LINE BELOW;Lu;0;L;0054 0331;;;;N;;;;1E6F; +1E6F;LATIN SMALL LETTER T WITH LINE BELOW;Ll;0;L;0074 0331;;;;N;;;1E6E;;1E6E +1E70;LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW;Lu;0;L;0054 032D;;;;N;;;;1E71; +1E71;LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW;Ll;0;L;0074 032D;;;;N;;;1E70;;1E70 +1E72;LATIN CAPITAL LETTER U WITH DIAERESIS BELOW;Lu;0;L;0055 0324;;;;N;;;;1E73; +1E73;LATIN SMALL LETTER U WITH DIAERESIS BELOW;Ll;0;L;0075 0324;;;;N;;;1E72;;1E72 +1E74;LATIN CAPITAL LETTER U WITH TILDE BELOW;Lu;0;L;0055 0330;;;;N;;;;1E75; +1E75;LATIN SMALL LETTER U WITH TILDE BELOW;Ll;0;L;0075 0330;;;;N;;;1E74;;1E74 +1E76;LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW;Lu;0;L;0055 032D;;;;N;;;;1E77; +1E77;LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW;Ll;0;L;0075 032D;;;;N;;;1E76;;1E76 +1E78;LATIN CAPITAL LETTER U WITH TILDE AND ACUTE;Lu;0;L;0168 0301;;;;N;;;;1E79; +1E79;LATIN SMALL LETTER U WITH TILDE AND ACUTE;Ll;0;L;0169 0301;;;;N;;;1E78;;1E78 +1E7A;LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS;Lu;0;L;016A 0308;;;;N;;;;1E7B; +1E7B;LATIN SMALL LETTER U WITH MACRON AND DIAERESIS;Ll;0;L;016B 0308;;;;N;;;1E7A;;1E7A +1E7C;LATIN CAPITAL LETTER V WITH TILDE;Lu;0;L;0056 0303;;;;N;;;;1E7D; +1E7D;LATIN SMALL LETTER V WITH TILDE;Ll;0;L;0076 0303;;;;N;;;1E7C;;1E7C +1E7E;LATIN CAPITAL LETTER V WITH DOT BELOW;Lu;0;L;0056 0323;;;;N;;;;1E7F; +1E7F;LATIN SMALL LETTER V WITH DOT BELOW;Ll;0;L;0076 0323;;;;N;;;1E7E;;1E7E +1E80;LATIN CAPITAL LETTER W WITH GRAVE;Lu;0;L;0057 0300;;;;N;;;;1E81; +1E81;LATIN SMALL LETTER W WITH GRAVE;Ll;0;L;0077 0300;;;;N;;;1E80;;1E80 +1E82;LATIN CAPITAL LETTER W WITH ACUTE;Lu;0;L;0057 0301;;;;N;;;;1E83; +1E83;LATIN SMALL LETTER W WITH ACUTE;Ll;0;L;0077 0301;;;;N;;;1E82;;1E82 +1E84;LATIN CAPITAL LETTER W WITH DIAERESIS;Lu;0;L;0057 0308;;;;N;;;;1E85; +1E85;LATIN SMALL LETTER W WITH DIAERESIS;Ll;0;L;0077 0308;;;;N;;;1E84;;1E84 +1E86;LATIN CAPITAL LETTER W WITH DOT ABOVE;Lu;0;L;0057 0307;;;;N;;;;1E87; +1E87;LATIN SMALL LETTER W WITH DOT ABOVE;Ll;0;L;0077 0307;;;;N;;;1E86;;1E86 +1E88;LATIN CAPITAL LETTER W WITH DOT BELOW;Lu;0;L;0057 0323;;;;N;;;;1E89; +1E89;LATIN SMALL LETTER W WITH DOT BELOW;Ll;0;L;0077 0323;;;;N;;;1E88;;1E88 +1E8A;LATIN CAPITAL LETTER X WITH DOT ABOVE;Lu;0;L;0058 0307;;;;N;;;;1E8B; +1E8B;LATIN SMALL LETTER X WITH DOT ABOVE;Ll;0;L;0078 0307;;;;N;;;1E8A;;1E8A +1E8C;LATIN CAPITAL LETTER X WITH DIAERESIS;Lu;0;L;0058 0308;;;;N;;;;1E8D; +1E8D;LATIN SMALL LETTER X WITH DIAERESIS;Ll;0;L;0078 0308;;;;N;;;1E8C;;1E8C +1E8E;LATIN CAPITAL LETTER Y WITH DOT ABOVE;Lu;0;L;0059 0307;;;;N;;;;1E8F; +1E8F;LATIN SMALL LETTER Y WITH DOT ABOVE;Ll;0;L;0079 0307;;;;N;;;1E8E;;1E8E +1E90;LATIN CAPITAL LETTER Z WITH CIRCUMFLEX;Lu;0;L;005A 0302;;;;N;;;;1E91; +1E91;LATIN SMALL LETTER Z WITH CIRCUMFLEX;Ll;0;L;007A 0302;;;;N;;;1E90;;1E90 +1E92;LATIN CAPITAL LETTER Z WITH DOT BELOW;Lu;0;L;005A 0323;;;;N;;;;1E93; +1E93;LATIN SMALL LETTER Z WITH DOT BELOW;Ll;0;L;007A 0323;;;;N;;;1E92;;1E92 +1E94;LATIN CAPITAL LETTER Z WITH LINE BELOW;Lu;0;L;005A 0331;;;;N;;;;1E95; +1E95;LATIN SMALL LETTER Z WITH LINE BELOW;Ll;0;L;007A 0331;;;;N;;;1E94;;1E94 +1E96;LATIN SMALL LETTER H WITH LINE BELOW;Ll;0;L;0068 0331;;;;N;;;;; +1E97;LATIN SMALL LETTER T WITH DIAERESIS;Ll;0;L;0074 0308;;;;N;;;;; +1E98;LATIN SMALL LETTER W WITH RING ABOVE;Ll;0;L;0077 030A;;;;N;;;;; +1E99;LATIN SMALL LETTER Y WITH RING ABOVE;Ll;0;L;0079 030A;;;;N;;;;; +1E9A;LATIN SMALL LETTER A WITH RIGHT HALF RING;Ll;0;L;<compat> 0061 02BE;;;;N;;;;; +1E9B;LATIN SMALL LETTER LONG S WITH DOT ABOVE;Ll;0;L;017F 0307;;;;N;;;1E60;;1E60 +1E9C;LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;;; +1E9D;LATIN SMALL LETTER LONG S WITH HIGH STROKE;Ll;0;L;;;;;N;;;;; +1E9E;LATIN CAPITAL LETTER SHARP S;Lu;0;L;;;;;N;;;;00DF; +1E9F;LATIN SMALL LETTER DELTA;Ll;0;L;;;;;N;;;;; +1EA0;LATIN CAPITAL LETTER A WITH DOT BELOW;Lu;0;L;0041 0323;;;;N;;;;1EA1; +1EA1;LATIN SMALL LETTER A WITH DOT BELOW;Ll;0;L;0061 0323;;;;N;;;1EA0;;1EA0 +1EA2;LATIN CAPITAL LETTER A WITH HOOK ABOVE;Lu;0;L;0041 0309;;;;N;;;;1EA3; +1EA3;LATIN SMALL LETTER A WITH HOOK ABOVE;Ll;0;L;0061 0309;;;;N;;;1EA2;;1EA2 +1EA4;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00C2 0301;;;;N;;;;1EA5; +1EA5;LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00E2 0301;;;;N;;;1EA4;;1EA4 +1EA6;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00C2 0300;;;;N;;;;1EA7; +1EA7;LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00E2 0300;;;;N;;;1EA6;;1EA6 +1EA8;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00C2 0309;;;;N;;;;1EA9; +1EA9;LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00E2 0309;;;;N;;;1EA8;;1EA8 +1EAA;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE;Lu;0;L;00C2 0303;;;;N;;;;1EAB; +1EAB;LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE;Ll;0;L;00E2 0303;;;;N;;;1EAA;;1EAA +1EAC;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EA0 0302;;;;N;;;;1EAD; +1EAD;LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EA1 0302;;;;N;;;1EAC;;1EAC +1EAE;LATIN CAPITAL LETTER A WITH BREVE AND ACUTE;Lu;0;L;0102 0301;;;;N;;;;1EAF; +1EAF;LATIN SMALL LETTER A WITH BREVE AND ACUTE;Ll;0;L;0103 0301;;;;N;;;1EAE;;1EAE +1EB0;LATIN CAPITAL LETTER A WITH BREVE AND GRAVE;Lu;0;L;0102 0300;;;;N;;;;1EB1; +1EB1;LATIN SMALL LETTER A WITH BREVE AND GRAVE;Ll;0;L;0103 0300;;;;N;;;1EB0;;1EB0 +1EB2;LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE;Lu;0;L;0102 0309;;;;N;;;;1EB3; +1EB3;LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE;Ll;0;L;0103 0309;;;;N;;;1EB2;;1EB2 +1EB4;LATIN CAPITAL LETTER A WITH BREVE AND TILDE;Lu;0;L;0102 0303;;;;N;;;;1EB5; +1EB5;LATIN SMALL LETTER A WITH BREVE AND TILDE;Ll;0;L;0103 0303;;;;N;;;1EB4;;1EB4 +1EB6;LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW;Lu;0;L;1EA0 0306;;;;N;;;;1EB7; +1EB7;LATIN SMALL LETTER A WITH BREVE AND DOT BELOW;Ll;0;L;1EA1 0306;;;;N;;;1EB6;;1EB6 +1EB8;LATIN CAPITAL LETTER E WITH DOT BELOW;Lu;0;L;0045 0323;;;;N;;;;1EB9; +1EB9;LATIN SMALL LETTER E WITH DOT BELOW;Ll;0;L;0065 0323;;;;N;;;1EB8;;1EB8 +1EBA;LATIN CAPITAL LETTER E WITH HOOK ABOVE;Lu;0;L;0045 0309;;;;N;;;;1EBB; +1EBB;LATIN SMALL LETTER E WITH HOOK ABOVE;Ll;0;L;0065 0309;;;;N;;;1EBA;;1EBA +1EBC;LATIN CAPITAL LETTER E WITH TILDE;Lu;0;L;0045 0303;;;;N;;;;1EBD; +1EBD;LATIN SMALL LETTER E WITH TILDE;Ll;0;L;0065 0303;;;;N;;;1EBC;;1EBC +1EBE;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00CA 0301;;;;N;;;;1EBF; +1EBF;LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00EA 0301;;;;N;;;1EBE;;1EBE +1EC0;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00CA 0300;;;;N;;;;1EC1; +1EC1;LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00EA 0300;;;;N;;;1EC0;;1EC0 +1EC2;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00CA 0309;;;;N;;;;1EC3; +1EC3;LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00EA 0309;;;;N;;;1EC2;;1EC2 +1EC4;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE;Lu;0;L;00CA 0303;;;;N;;;;1EC5; +1EC5;LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE;Ll;0;L;00EA 0303;;;;N;;;1EC4;;1EC4 +1EC6;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EB8 0302;;;;N;;;;1EC7; +1EC7;LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EB9 0302;;;;N;;;1EC6;;1EC6 +1EC8;LATIN CAPITAL LETTER I WITH HOOK ABOVE;Lu;0;L;0049 0309;;;;N;;;;1EC9; +1EC9;LATIN SMALL LETTER I WITH HOOK ABOVE;Ll;0;L;0069 0309;;;;N;;;1EC8;;1EC8 +1ECA;LATIN CAPITAL LETTER I WITH DOT BELOW;Lu;0;L;0049 0323;;;;N;;;;1ECB; +1ECB;LATIN SMALL LETTER I WITH DOT BELOW;Ll;0;L;0069 0323;;;;N;;;1ECA;;1ECA +1ECC;LATIN CAPITAL LETTER O WITH DOT BELOW;Lu;0;L;004F 0323;;;;N;;;;1ECD; +1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC +1ECE;LATIN CAPITAL LETTER O WITH HOOK ABOVE;Lu;0;L;004F 0309;;;;N;;;;1ECF; +1ECF;LATIN SMALL LETTER O WITH HOOK ABOVE;Ll;0;L;006F 0309;;;;N;;;1ECE;;1ECE +1ED0;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00D4 0301;;;;N;;;;1ED1; +1ED1;LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00F4 0301;;;;N;;;1ED0;;1ED0 +1ED2;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00D4 0300;;;;N;;;;1ED3; +1ED3;LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00F4 0300;;;;N;;;1ED2;;1ED2 +1ED4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00D4 0309;;;;N;;;;1ED5; +1ED5;LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00F4 0309;;;;N;;;1ED4;;1ED4 +1ED6;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE;Lu;0;L;00D4 0303;;;;N;;;;1ED7; +1ED7;LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE;Ll;0;L;00F4 0303;;;;N;;;1ED6;;1ED6 +1ED8;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1ECC 0302;;;;N;;;;1ED9; +1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8 +1EDA;LATIN CAPITAL LETTER O WITH HORN AND ACUTE;Lu;0;L;01A0 0301;;;;N;;;;1EDB; +1EDB;LATIN SMALL LETTER O WITH HORN AND ACUTE;Ll;0;L;01A1 0301;;;;N;;;1EDA;;1EDA +1EDC;LATIN CAPITAL LETTER O WITH HORN AND GRAVE;Lu;0;L;01A0 0300;;;;N;;;;1EDD; +1EDD;LATIN SMALL LETTER O WITH HORN AND GRAVE;Ll;0;L;01A1 0300;;;;N;;;1EDC;;1EDC +1EDE;LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE;Lu;0;L;01A0 0309;;;;N;;;;1EDF; +1EDF;LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE;Ll;0;L;01A1 0309;;;;N;;;1EDE;;1EDE +1EE0;LATIN CAPITAL LETTER O WITH HORN AND TILDE;Lu;0;L;01A0 0303;;;;N;;;;1EE1; +1EE1;LATIN SMALL LETTER O WITH HORN AND TILDE;Ll;0;L;01A1 0303;;;;N;;;1EE0;;1EE0 +1EE2;LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW;Lu;0;L;01A0 0323;;;;N;;;;1EE3; +1EE3;LATIN SMALL LETTER O WITH HORN AND DOT BELOW;Ll;0;L;01A1 0323;;;;N;;;1EE2;;1EE2 +1EE4;LATIN CAPITAL LETTER U WITH DOT BELOW;Lu;0;L;0055 0323;;;;N;;;;1EE5; +1EE5;LATIN SMALL LETTER U WITH DOT BELOW;Ll;0;L;0075 0323;;;;N;;;1EE4;;1EE4 +1EE6;LATIN CAPITAL LETTER U WITH HOOK ABOVE;Lu;0;L;0055 0309;;;;N;;;;1EE7; +1EE7;LATIN SMALL LETTER U WITH HOOK ABOVE;Ll;0;L;0075 0309;;;;N;;;1EE6;;1EE6 +1EE8;LATIN CAPITAL LETTER U WITH HORN AND ACUTE;Lu;0;L;01AF 0301;;;;N;;;;1EE9; +1EE9;LATIN SMALL LETTER U WITH HORN AND ACUTE;Ll;0;L;01B0 0301;;;;N;;;1EE8;;1EE8 +1EEA;LATIN CAPITAL LETTER U WITH HORN AND GRAVE;Lu;0;L;01AF 0300;;;;N;;;;1EEB; +1EEB;LATIN SMALL LETTER U WITH HORN AND GRAVE;Ll;0;L;01B0 0300;;;;N;;;1EEA;;1EEA +1EEC;LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE;Lu;0;L;01AF 0309;;;;N;;;;1EED; +1EED;LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE;Ll;0;L;01B0 0309;;;;N;;;1EEC;;1EEC +1EEE;LATIN CAPITAL LETTER U WITH HORN AND TILDE;Lu;0;L;01AF 0303;;;;N;;;;1EEF; +1EEF;LATIN SMALL LETTER U WITH HORN AND TILDE;Ll;0;L;01B0 0303;;;;N;;;1EEE;;1EEE +1EF0;LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW;Lu;0;L;01AF 0323;;;;N;;;;1EF1; +1EF1;LATIN SMALL LETTER U WITH HORN AND DOT BELOW;Ll;0;L;01B0 0323;;;;N;;;1EF0;;1EF0 +1EF2;LATIN CAPITAL LETTER Y WITH GRAVE;Lu;0;L;0059 0300;;;;N;;;;1EF3; +1EF3;LATIN SMALL LETTER Y WITH GRAVE;Ll;0;L;0079 0300;;;;N;;;1EF2;;1EF2 +1EF4;LATIN CAPITAL LETTER Y WITH DOT BELOW;Lu;0;L;0059 0323;;;;N;;;;1EF5; +1EF5;LATIN SMALL LETTER Y WITH DOT BELOW;Ll;0;L;0079 0323;;;;N;;;1EF4;;1EF4 +1EF6;LATIN CAPITAL LETTER Y WITH HOOK ABOVE;Lu;0;L;0059 0309;;;;N;;;;1EF7; +1EF7;LATIN SMALL LETTER Y WITH HOOK ABOVE;Ll;0;L;0079 0309;;;;N;;;1EF6;;1EF6 +1EF8;LATIN CAPITAL LETTER Y WITH TILDE;Lu;0;L;0059 0303;;;;N;;;;1EF9; +1EF9;LATIN SMALL LETTER Y WITH TILDE;Ll;0;L;0079 0303;;;;N;;;1EF8;;1EF8 +1EFA;LATIN CAPITAL LETTER MIDDLE-WELSH LL;Lu;0;L;;;;;N;;;;1EFB; +1EFB;LATIN SMALL LETTER MIDDLE-WELSH LL;Ll;0;L;;;;;N;;;1EFA;;1EFA +1EFC;LATIN CAPITAL LETTER MIDDLE-WELSH V;Lu;0;L;;;;;N;;;;1EFD; +1EFD;LATIN SMALL LETTER MIDDLE-WELSH V;Ll;0;L;;;;;N;;;1EFC;;1EFC +1EFE;LATIN CAPITAL LETTER Y WITH LOOP;Lu;0;L;;;;;N;;;;1EFF; +1EFF;LATIN SMALL LETTER Y WITH LOOP;Ll;0;L;;;;;N;;;1EFE;;1EFE +1F00;GREEK SMALL LETTER ALPHA WITH PSILI;Ll;0;L;03B1 0313;;;;N;;;1F08;;1F08 +1F01;GREEK SMALL LETTER ALPHA WITH DASIA;Ll;0;L;03B1 0314;;;;N;;;1F09;;1F09 +1F02;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA;Ll;0;L;1F00 0300;;;;N;;;1F0A;;1F0A +1F03;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA;Ll;0;L;1F01 0300;;;;N;;;1F0B;;1F0B +1F04;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA;Ll;0;L;1F00 0301;;;;N;;;1F0C;;1F0C +1F05;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA;Ll;0;L;1F01 0301;;;;N;;;1F0D;;1F0D +1F06;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI;Ll;0;L;1F00 0342;;;;N;;;1F0E;;1F0E +1F07;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI;Ll;0;L;1F01 0342;;;;N;;;1F0F;;1F0F +1F08;GREEK CAPITAL LETTER ALPHA WITH PSILI;Lu;0;L;0391 0313;;;;N;;;;1F00; +1F09;GREEK CAPITAL LETTER ALPHA WITH DASIA;Lu;0;L;0391 0314;;;;N;;;;1F01; +1F0A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA;Lu;0;L;1F08 0300;;;;N;;;;1F02; +1F0B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA;Lu;0;L;1F09 0300;;;;N;;;;1F03; +1F0C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA;Lu;0;L;1F08 0301;;;;N;;;;1F04; +1F0D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA;Lu;0;L;1F09 0301;;;;N;;;;1F05; +1F0E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI;Lu;0;L;1F08 0342;;;;N;;;;1F06; +1F0F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI;Lu;0;L;1F09 0342;;;;N;;;;1F07; +1F10;GREEK SMALL LETTER EPSILON WITH PSILI;Ll;0;L;03B5 0313;;;;N;;;1F18;;1F18 +1F11;GREEK SMALL LETTER EPSILON WITH DASIA;Ll;0;L;03B5 0314;;;;N;;;1F19;;1F19 +1F12;GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA;Ll;0;L;1F10 0300;;;;N;;;1F1A;;1F1A +1F13;GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA;Ll;0;L;1F11 0300;;;;N;;;1F1B;;1F1B +1F14;GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA;Ll;0;L;1F10 0301;;;;N;;;1F1C;;1F1C +1F15;GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA;Ll;0;L;1F11 0301;;;;N;;;1F1D;;1F1D +1F18;GREEK CAPITAL LETTER EPSILON WITH PSILI;Lu;0;L;0395 0313;;;;N;;;;1F10; +1F19;GREEK CAPITAL LETTER EPSILON WITH DASIA;Lu;0;L;0395 0314;;;;N;;;;1F11; +1F1A;GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA;Lu;0;L;1F18 0300;;;;N;;;;1F12; +1F1B;GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA;Lu;0;L;1F19 0300;;;;N;;;;1F13; +1F1C;GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA;Lu;0;L;1F18 0301;;;;N;;;;1F14; +1F1D;GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA;Lu;0;L;1F19 0301;;;;N;;;;1F15; +1F20;GREEK SMALL LETTER ETA WITH PSILI;Ll;0;L;03B7 0313;;;;N;;;1F28;;1F28 +1F21;GREEK SMALL LETTER ETA WITH DASIA;Ll;0;L;03B7 0314;;;;N;;;1F29;;1F29 +1F22;GREEK SMALL LETTER ETA WITH PSILI AND VARIA;Ll;0;L;1F20 0300;;;;N;;;1F2A;;1F2A +1F23;GREEK SMALL LETTER ETA WITH DASIA AND VARIA;Ll;0;L;1F21 0300;;;;N;;;1F2B;;1F2B +1F24;GREEK SMALL LETTER ETA WITH PSILI AND OXIA;Ll;0;L;1F20 0301;;;;N;;;1F2C;;1F2C +1F25;GREEK SMALL LETTER ETA WITH DASIA AND OXIA;Ll;0;L;1F21 0301;;;;N;;;1F2D;;1F2D +1F26;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI;Ll;0;L;1F20 0342;;;;N;;;1F2E;;1F2E +1F27;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI;Ll;0;L;1F21 0342;;;;N;;;1F2F;;1F2F +1F28;GREEK CAPITAL LETTER ETA WITH PSILI;Lu;0;L;0397 0313;;;;N;;;;1F20; +1F29;GREEK CAPITAL LETTER ETA WITH DASIA;Lu;0;L;0397 0314;;;;N;;;;1F21; +1F2A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA;Lu;0;L;1F28 0300;;;;N;;;;1F22; +1F2B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA;Lu;0;L;1F29 0300;;;;N;;;;1F23; +1F2C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA;Lu;0;L;1F28 0301;;;;N;;;;1F24; +1F2D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA;Lu;0;L;1F29 0301;;;;N;;;;1F25; +1F2E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI;Lu;0;L;1F28 0342;;;;N;;;;1F26; +1F2F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI;Lu;0;L;1F29 0342;;;;N;;;;1F27; +1F30;GREEK SMALL LETTER IOTA WITH PSILI;Ll;0;L;03B9 0313;;;;N;;;1F38;;1F38 +1F31;GREEK SMALL LETTER IOTA WITH DASIA;Ll;0;L;03B9 0314;;;;N;;;1F39;;1F39 +1F32;GREEK SMALL LETTER IOTA WITH PSILI AND VARIA;Ll;0;L;1F30 0300;;;;N;;;1F3A;;1F3A +1F33;GREEK SMALL LETTER IOTA WITH DASIA AND VARIA;Ll;0;L;1F31 0300;;;;N;;;1F3B;;1F3B +1F34;GREEK SMALL LETTER IOTA WITH PSILI AND OXIA;Ll;0;L;1F30 0301;;;;N;;;1F3C;;1F3C +1F35;GREEK SMALL LETTER IOTA WITH DASIA AND OXIA;Ll;0;L;1F31 0301;;;;N;;;1F3D;;1F3D +1F36;GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI;Ll;0;L;1F30 0342;;;;N;;;1F3E;;1F3E +1F37;GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI;Ll;0;L;1F31 0342;;;;N;;;1F3F;;1F3F +1F38;GREEK CAPITAL LETTER IOTA WITH PSILI;Lu;0;L;0399 0313;;;;N;;;;1F30; +1F39;GREEK CAPITAL LETTER IOTA WITH DASIA;Lu;0;L;0399 0314;;;;N;;;;1F31; +1F3A;GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA;Lu;0;L;1F38 0300;;;;N;;;;1F32; +1F3B;GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA;Lu;0;L;1F39 0300;;;;N;;;;1F33; +1F3C;GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA;Lu;0;L;1F38 0301;;;;N;;;;1F34; +1F3D;GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA;Lu;0;L;1F39 0301;;;;N;;;;1F35; +1F3E;GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI;Lu;0;L;1F38 0342;;;;N;;;;1F36; +1F3F;GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI;Lu;0;L;1F39 0342;;;;N;;;;1F37; +1F40;GREEK SMALL LETTER OMICRON WITH PSILI;Ll;0;L;03BF 0313;;;;N;;;1F48;;1F48 +1F41;GREEK SMALL LETTER OMICRON WITH DASIA;Ll;0;L;03BF 0314;;;;N;;;1F49;;1F49 +1F42;GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA;Ll;0;L;1F40 0300;;;;N;;;1F4A;;1F4A +1F43;GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA;Ll;0;L;1F41 0300;;;;N;;;1F4B;;1F4B +1F44;GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA;Ll;0;L;1F40 0301;;;;N;;;1F4C;;1F4C +1F45;GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA;Ll;0;L;1F41 0301;;;;N;;;1F4D;;1F4D +1F48;GREEK CAPITAL LETTER OMICRON WITH PSILI;Lu;0;L;039F 0313;;;;N;;;;1F40; +1F49;GREEK CAPITAL LETTER OMICRON WITH DASIA;Lu;0;L;039F 0314;;;;N;;;;1F41; +1F4A;GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA;Lu;0;L;1F48 0300;;;;N;;;;1F42; +1F4B;GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA;Lu;0;L;1F49 0300;;;;N;;;;1F43; +1F4C;GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA;Lu;0;L;1F48 0301;;;;N;;;;1F44; +1F4D;GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA;Lu;0;L;1F49 0301;;;;N;;;;1F45; +1F50;GREEK SMALL LETTER UPSILON WITH PSILI;Ll;0;L;03C5 0313;;;;N;;;;; +1F51;GREEK SMALL LETTER UPSILON WITH DASIA;Ll;0;L;03C5 0314;;;;N;;;1F59;;1F59 +1F52;GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA;Ll;0;L;1F50 0300;;;;N;;;;; +1F53;GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA;Ll;0;L;1F51 0300;;;;N;;;1F5B;;1F5B +1F54;GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA;Ll;0;L;1F50 0301;;;;N;;;;; +1F55;GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA;Ll;0;L;1F51 0301;;;;N;;;1F5D;;1F5D +1F56;GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI;Ll;0;L;1F50 0342;;;;N;;;;; +1F57;GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI;Ll;0;L;1F51 0342;;;;N;;;1F5F;;1F5F +1F59;GREEK CAPITAL LETTER UPSILON WITH DASIA;Lu;0;L;03A5 0314;;;;N;;;;1F51; +1F5B;GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA;Lu;0;L;1F59 0300;;;;N;;;;1F53; +1F5D;GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA;Lu;0;L;1F59 0301;;;;N;;;;1F55; +1F5F;GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI;Lu;0;L;1F59 0342;;;;N;;;;1F57; +1F60;GREEK SMALL LETTER OMEGA WITH PSILI;Ll;0;L;03C9 0313;;;;N;;;1F68;;1F68 +1F61;GREEK SMALL LETTER OMEGA WITH DASIA;Ll;0;L;03C9 0314;;;;N;;;1F69;;1F69 +1F62;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA;Ll;0;L;1F60 0300;;;;N;;;1F6A;;1F6A +1F63;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA;Ll;0;L;1F61 0300;;;;N;;;1F6B;;1F6B +1F64;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA;Ll;0;L;1F60 0301;;;;N;;;1F6C;;1F6C +1F65;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA;Ll;0;L;1F61 0301;;;;N;;;1F6D;;1F6D +1F66;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI;Ll;0;L;1F60 0342;;;;N;;;1F6E;;1F6E +1F67;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI;Ll;0;L;1F61 0342;;;;N;;;1F6F;;1F6F +1F68;GREEK CAPITAL LETTER OMEGA WITH PSILI;Lu;0;L;03A9 0313;;;;N;;;;1F60; +1F69;GREEK CAPITAL LETTER OMEGA WITH DASIA;Lu;0;L;03A9 0314;;;;N;;;;1F61; +1F6A;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA;Lu;0;L;1F68 0300;;;;N;;;;1F62; +1F6B;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA;Lu;0;L;1F69 0300;;;;N;;;;1F63; +1F6C;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA;Lu;0;L;1F68 0301;;;;N;;;;1F64; +1F6D;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA;Lu;0;L;1F69 0301;;;;N;;;;1F65; +1F6E;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI;Lu;0;L;1F68 0342;;;;N;;;;1F66; +1F6F;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI;Lu;0;L;1F69 0342;;;;N;;;;1F67; +1F70;GREEK SMALL LETTER ALPHA WITH VARIA;Ll;0;L;03B1 0300;;;;N;;;1FBA;;1FBA +1F71;GREEK SMALL LETTER ALPHA WITH OXIA;Ll;0;L;03AC;;;;N;;;1FBB;;1FBB +1F72;GREEK SMALL LETTER EPSILON WITH VARIA;Ll;0;L;03B5 0300;;;;N;;;1FC8;;1FC8 +1F73;GREEK SMALL LETTER EPSILON WITH OXIA;Ll;0;L;03AD;;;;N;;;1FC9;;1FC9 +1F74;GREEK SMALL LETTER ETA WITH VARIA;Ll;0;L;03B7 0300;;;;N;;;1FCA;;1FCA +1F75;GREEK SMALL LETTER ETA WITH OXIA;Ll;0;L;03AE;;;;N;;;1FCB;;1FCB +1F76;GREEK SMALL LETTER IOTA WITH VARIA;Ll;0;L;03B9 0300;;;;N;;;1FDA;;1FDA +1F77;GREEK SMALL LETTER IOTA WITH OXIA;Ll;0;L;03AF;;;;N;;;1FDB;;1FDB +1F78;GREEK SMALL LETTER OMICRON WITH VARIA;Ll;0;L;03BF 0300;;;;N;;;1FF8;;1FF8 +1F79;GREEK SMALL LETTER OMICRON WITH OXIA;Ll;0;L;03CC;;;;N;;;1FF9;;1FF9 +1F7A;GREEK SMALL LETTER UPSILON WITH VARIA;Ll;0;L;03C5 0300;;;;N;;;1FEA;;1FEA +1F7B;GREEK SMALL LETTER UPSILON WITH OXIA;Ll;0;L;03CD;;;;N;;;1FEB;;1FEB +1F7C;GREEK SMALL LETTER OMEGA WITH VARIA;Ll;0;L;03C9 0300;;;;N;;;1FFA;;1FFA +1F7D;GREEK SMALL LETTER OMEGA WITH OXIA;Ll;0;L;03CE;;;;N;;;1FFB;;1FFB +1F80;GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F00 0345;;;;N;;;1F88;;1F88 +1F81;GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F01 0345;;;;N;;;1F89;;1F89 +1F82;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F02 0345;;;;N;;;1F8A;;1F8A +1F83;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F03 0345;;;;N;;;1F8B;;1F8B +1F84;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F04 0345;;;;N;;;1F8C;;1F8C +1F85;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F05 0345;;;;N;;;1F8D;;1F8D +1F86;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F06 0345;;;;N;;;1F8E;;1F8E +1F87;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F07 0345;;;;N;;;1F8F;;1F8F +1F88;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F08 0345;;;;N;;;;1F80; +1F89;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F09 0345;;;;N;;;;1F81; +1F8A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0A 0345;;;;N;;;;1F82; +1F8B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0B 0345;;;;N;;;;1F83; +1F8C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0C 0345;;;;N;;;;1F84; +1F8D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0D 0345;;;;N;;;;1F85; +1F8E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0E 0345;;;;N;;;;1F86; +1F8F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0F 0345;;;;N;;;;1F87; +1F90;GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F20 0345;;;;N;;;1F98;;1F98 +1F91;GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F21 0345;;;;N;;;1F99;;1F99 +1F92;GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F22 0345;;;;N;;;1F9A;;1F9A +1F93;GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F23 0345;;;;N;;;1F9B;;1F9B +1F94;GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F24 0345;;;;N;;;1F9C;;1F9C +1F95;GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F25 0345;;;;N;;;1F9D;;1F9D +1F96;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F26 0345;;;;N;;;1F9E;;1F9E +1F97;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F27 0345;;;;N;;;1F9F;;1F9F +1F98;GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F28 0345;;;;N;;;;1F90; +1F99;GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F29 0345;;;;N;;;;1F91; +1F9A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2A 0345;;;;N;;;;1F92; +1F9B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2B 0345;;;;N;;;;1F93; +1F9C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2C 0345;;;;N;;;;1F94; +1F9D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2D 0345;;;;N;;;;1F95; +1F9E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2E 0345;;;;N;;;;1F96; +1F9F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2F 0345;;;;N;;;;1F97; +1FA0;GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F60 0345;;;;N;;;1FA8;;1FA8 +1FA1;GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F61 0345;;;;N;;;1FA9;;1FA9 +1FA2;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F62 0345;;;;N;;;1FAA;;1FAA +1FA3;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F63 0345;;;;N;;;1FAB;;1FAB +1FA4;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F64 0345;;;;N;;;1FAC;;1FAC +1FA5;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F65 0345;;;;N;;;1FAD;;1FAD +1FA6;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F66 0345;;;;N;;;1FAE;;1FAE +1FA7;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F67 0345;;;;N;;;1FAF;;1FAF +1FA8;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F68 0345;;;;N;;;;1FA0; +1FA9;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F69 0345;;;;N;;;;1FA1; +1FAA;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6A 0345;;;;N;;;;1FA2; +1FAB;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6B 0345;;;;N;;;;1FA3; +1FAC;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6C 0345;;;;N;;;;1FA4; +1FAD;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6D 0345;;;;N;;;;1FA5; +1FAE;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6E 0345;;;;N;;;;1FA6; +1FAF;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6F 0345;;;;N;;;;1FA7; +1FB0;GREEK SMALL LETTER ALPHA WITH VRACHY;Ll;0;L;03B1 0306;;;;N;;;1FB8;;1FB8 +1FB1;GREEK SMALL LETTER ALPHA WITH MACRON;Ll;0;L;03B1 0304;;;;N;;;1FB9;;1FB9 +1FB2;GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F70 0345;;;;N;;;;; +1FB3;GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI;Ll;0;L;03B1 0345;;;;N;;;1FBC;;1FBC +1FB4;GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AC 0345;;;;N;;;;; +1FB6;GREEK SMALL LETTER ALPHA WITH PERISPOMENI;Ll;0;L;03B1 0342;;;;N;;;;; +1FB7;GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FB6 0345;;;;N;;;;; +1FB8;GREEK CAPITAL LETTER ALPHA WITH VRACHY;Lu;0;L;0391 0306;;;;N;;;;1FB0; +1FB9;GREEK CAPITAL LETTER ALPHA WITH MACRON;Lu;0;L;0391 0304;;;;N;;;;1FB1; +1FBA;GREEK CAPITAL LETTER ALPHA WITH VARIA;Lu;0;L;0391 0300;;;;N;;;;1F70; +1FBB;GREEK CAPITAL LETTER ALPHA WITH OXIA;Lu;0;L;0386;;;;N;;;;1F71; +1FBC;GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI;Lt;0;L;0391 0345;;;;N;;;;1FB3; +1FBD;GREEK KORONIS;Sk;0;ON;<compat> 0020 0313;;;;N;;;;; +1FBE;GREEK PROSGEGRAMMENI;Ll;0;L;03B9;;;;N;;;0399;;0399 +1FBF;GREEK PSILI;Sk;0;ON;<compat> 0020 0313;;;;N;;;;; +1FC0;GREEK PERISPOMENI;Sk;0;ON;<compat> 0020 0342;;;;N;;;;; +1FC1;GREEK DIALYTIKA AND PERISPOMENI;Sk;0;ON;00A8 0342;;;;N;;;;; +1FC2;GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F74 0345;;;;N;;;;; +1FC3;GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI;Ll;0;L;03B7 0345;;;;N;;;1FCC;;1FCC +1FC4;GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AE 0345;;;;N;;;;; +1FC6;GREEK SMALL LETTER ETA WITH PERISPOMENI;Ll;0;L;03B7 0342;;;;N;;;;; +1FC7;GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FC6 0345;;;;N;;;;; +1FC8;GREEK CAPITAL LETTER EPSILON WITH VARIA;Lu;0;L;0395 0300;;;;N;;;;1F72; +1FC9;GREEK CAPITAL LETTER EPSILON WITH OXIA;Lu;0;L;0388;;;;N;;;;1F73; +1FCA;GREEK CAPITAL LETTER ETA WITH VARIA;Lu;0;L;0397 0300;;;;N;;;;1F74; +1FCB;GREEK CAPITAL LETTER ETA WITH OXIA;Lu;0;L;0389;;;;N;;;;1F75; +1FCC;GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI;Lt;0;L;0397 0345;;;;N;;;;1FC3; +1FCD;GREEK PSILI AND VARIA;Sk;0;ON;1FBF 0300;;;;N;;;;; +1FCE;GREEK PSILI AND OXIA;Sk;0;ON;1FBF 0301;;;;N;;;;; +1FCF;GREEK PSILI AND PERISPOMENI;Sk;0;ON;1FBF 0342;;;;N;;;;; +1FD0;GREEK SMALL LETTER IOTA WITH VRACHY;Ll;0;L;03B9 0306;;;;N;;;1FD8;;1FD8 +1FD1;GREEK SMALL LETTER IOTA WITH MACRON;Ll;0;L;03B9 0304;;;;N;;;1FD9;;1FD9 +1FD2;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA;Ll;0;L;03CA 0300;;;;N;;;;; +1FD3;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA;Ll;0;L;0390;;;;N;;;;; +1FD6;GREEK SMALL LETTER IOTA WITH PERISPOMENI;Ll;0;L;03B9 0342;;;;N;;;;; +1FD7;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CA 0342;;;;N;;;;; +1FD8;GREEK CAPITAL LETTER IOTA WITH VRACHY;Lu;0;L;0399 0306;;;;N;;;;1FD0; +1FD9;GREEK CAPITAL LETTER IOTA WITH MACRON;Lu;0;L;0399 0304;;;;N;;;;1FD1; +1FDA;GREEK CAPITAL LETTER IOTA WITH VARIA;Lu;0;L;0399 0300;;;;N;;;;1F76; +1FDB;GREEK CAPITAL LETTER IOTA WITH OXIA;Lu;0;L;038A;;;;N;;;;1F77; +1FDD;GREEK DASIA AND VARIA;Sk;0;ON;1FFE 0300;;;;N;;;;; +1FDE;GREEK DASIA AND OXIA;Sk;0;ON;1FFE 0301;;;;N;;;;; +1FDF;GREEK DASIA AND PERISPOMENI;Sk;0;ON;1FFE 0342;;;;N;;;;; +1FE0;GREEK SMALL LETTER UPSILON WITH VRACHY;Ll;0;L;03C5 0306;;;;N;;;1FE8;;1FE8 +1FE1;GREEK SMALL LETTER UPSILON WITH MACRON;Ll;0;L;03C5 0304;;;;N;;;1FE9;;1FE9 +1FE2;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA;Ll;0;L;03CB 0300;;;;N;;;;; +1FE3;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA;Ll;0;L;03B0;;;;N;;;;; +1FE4;GREEK SMALL LETTER RHO WITH PSILI;Ll;0;L;03C1 0313;;;;N;;;;; +1FE5;GREEK SMALL LETTER RHO WITH DASIA;Ll;0;L;03C1 0314;;;;N;;;1FEC;;1FEC +1FE6;GREEK SMALL LETTER UPSILON WITH PERISPOMENI;Ll;0;L;03C5 0342;;;;N;;;;; +1FE7;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CB 0342;;;;N;;;;; +1FE8;GREEK CAPITAL LETTER UPSILON WITH VRACHY;Lu;0;L;03A5 0306;;;;N;;;;1FE0; +1FE9;GREEK CAPITAL LETTER UPSILON WITH MACRON;Lu;0;L;03A5 0304;;;;N;;;;1FE1; +1FEA;GREEK CAPITAL LETTER UPSILON WITH VARIA;Lu;0;L;03A5 0300;;;;N;;;;1F7A; +1FEB;GREEK CAPITAL LETTER UPSILON WITH OXIA;Lu;0;L;038E;;;;N;;;;1F7B; +1FEC;GREEK CAPITAL LETTER RHO WITH DASIA;Lu;0;L;03A1 0314;;;;N;;;;1FE5; +1FED;GREEK DIALYTIKA AND VARIA;Sk;0;ON;00A8 0300;;;;N;;;;; +1FEE;GREEK DIALYTIKA AND OXIA;Sk;0;ON;0385;;;;N;;;;; +1FEF;GREEK VARIA;Sk;0;ON;0060;;;;N;;;;; +1FF2;GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F7C 0345;;;;N;;;;; +1FF3;GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI;Ll;0;L;03C9 0345;;;;N;;;1FFC;;1FFC +1FF4;GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03CE 0345;;;;N;;;;; +1FF6;GREEK SMALL LETTER OMEGA WITH PERISPOMENI;Ll;0;L;03C9 0342;;;;N;;;;; +1FF7;GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FF6 0345;;;;N;;;;; +1FF8;GREEK CAPITAL LETTER OMICRON WITH VARIA;Lu;0;L;039F 0300;;;;N;;;;1F78; +1FF9;GREEK CAPITAL LETTER OMICRON WITH OXIA;Lu;0;L;038C;;;;N;;;;1F79; +1FFA;GREEK CAPITAL LETTER OMEGA WITH VARIA;Lu;0;L;03A9 0300;;;;N;;;;1F7C; +1FFB;GREEK CAPITAL LETTER OMEGA WITH OXIA;Lu;0;L;038F;;;;N;;;;1F7D; +1FFC;GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI;Lt;0;L;03A9 0345;;;;N;;;;1FF3; +1FFD;GREEK OXIA;Sk;0;ON;00B4;;;;N;;;;; +1FFE;GREEK DASIA;Sk;0;ON;<compat> 0020 0314;;;;N;;;;; +2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;; +2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;; +2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;; +2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +200B;ZERO WIDTH SPACE;Cf;0;BN;;;;;N;;;;; +200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;; +200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;; +200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;; +200F;RIGHT-TO-LEFT MARK;Cf;0;R;;;;;N;;;;; +2010;HYPHEN;Pd;0;ON;;;;;N;;;;; +2011;NON-BREAKING HYPHEN;Pd;0;ON;<noBreak> 2010;;;;N;;;;; +2012;FIGURE DASH;Pd;0;ON;;;;;N;;;;; +2013;EN DASH;Pd;0;ON;;;;;N;;;;; +2014;EM DASH;Pd;0;ON;;;;;N;;;;; +2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;; +2016;DOUBLE VERTICAL LINE;Po;0;ON;;;;;N;DOUBLE VERTICAL BAR;;;; +2017;DOUBLE LOW LINE;Po;0;ON;<compat> 0020 0333;;;;N;SPACING DOUBLE UNDERSCORE;;;; +2018;LEFT SINGLE QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE TURNED COMMA QUOTATION MARK;;;; +2019;RIGHT SINGLE QUOTATION MARK;Pf;0;ON;;;;;N;SINGLE COMMA QUOTATION MARK;;;; +201A;SINGLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW SINGLE COMMA QUOTATION MARK;;;; +201B;SINGLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE REVERSED COMMA QUOTATION MARK;;;; +201C;LEFT DOUBLE QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE TURNED COMMA QUOTATION MARK;;;; +201D;RIGHT DOUBLE QUOTATION MARK;Pf;0;ON;;;;;N;DOUBLE COMMA QUOTATION MARK;;;; +201E;DOUBLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW DOUBLE COMMA QUOTATION MARK;;;; +201F;DOUBLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE REVERSED COMMA QUOTATION MARK;;;; +2020;DAGGER;Po;0;ON;;;;;N;;;;; +2021;DOUBLE DAGGER;Po;0;ON;;;;;N;;;;; +2022;BULLET;Po;0;ON;;;;;N;;;;; +2023;TRIANGULAR BULLET;Po;0;ON;;;;;N;;;;; +2024;ONE DOT LEADER;Po;0;ON;<compat> 002E;;;;N;;;;; +2025;TWO DOT LEADER;Po;0;ON;<compat> 002E 002E;;;;N;;;;; +2026;HORIZONTAL ELLIPSIS;Po;0;ON;<compat> 002E 002E 002E;;;;N;;;;; +2027;HYPHENATION POINT;Po;0;ON;;;;;N;;;;; +2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; +2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; +202A;LEFT-TO-RIGHT EMBEDDING;Cf;0;LRE;;;;;N;;;;; +202B;RIGHT-TO-LEFT EMBEDDING;Cf;0;RLE;;;;;N;;;;; +202C;POP DIRECTIONAL FORMATTING;Cf;0;PDF;;;;;N;;;;; +202D;LEFT-TO-RIGHT OVERRIDE;Cf;0;LRO;;;;;N;;;;; +202E;RIGHT-TO-LEFT OVERRIDE;Cf;0;RLO;;;;;N;;;;; +202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;; +2030;PER MILLE SIGN;Po;0;ET;;;;;N;;;;; +2031;PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; +2032;PRIME;Po;0;ET;;;;;N;;;;; +2033;DOUBLE PRIME;Po;0;ET;<compat> 2032 2032;;;;N;;;;; +2034;TRIPLE PRIME;Po;0;ET;<compat> 2032 2032 2032;;;;N;;;;; +2035;REVERSED PRIME;Po;0;ON;;;;;N;;;;; +2036;REVERSED DOUBLE PRIME;Po;0;ON;<compat> 2035 2035;;;;N;;;;; +2037;REVERSED TRIPLE PRIME;Po;0;ON;<compat> 2035 2035 2035;;;;N;;;;; +2038;CARET;Po;0;ON;;;;;N;;;;; +2039;SINGLE LEFT-POINTING ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING SINGLE GUILLEMET;;;; +203A;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING SINGLE GUILLEMET;;;; +203B;REFERENCE MARK;Po;0;ON;;;;;N;;;;; +203C;DOUBLE EXCLAMATION MARK;Po;0;ON;<compat> 0021 0021;;;;N;;;;; +203D;INTERROBANG;Po;0;ON;;;;;N;;;;; +203E;OVERLINE;Po;0;ON;<compat> 0020 0305;;;;N;SPACING OVERSCORE;;;; +203F;UNDERTIE;Pc;0;ON;;;;;N;;;;; +2040;CHARACTER TIE;Pc;0;ON;;;;;N;;;;; +2041;CARET INSERTION POINT;Po;0;ON;;;;;N;;;;; +2042;ASTERISM;Po;0;ON;;;;;N;;;;; +2043;HYPHEN BULLET;Po;0;ON;;;;;N;;;;; +2044;FRACTION SLASH;Sm;0;CS;;;;;N;;;;; +2045;LEFT SQUARE BRACKET WITH QUILL;Ps;0;ON;;;;;Y;;;;; +2046;RIGHT SQUARE BRACKET WITH QUILL;Pe;0;ON;;;;;Y;;;;; +2047;DOUBLE QUESTION MARK;Po;0;ON;<compat> 003F 003F;;;;N;;;;; +2048;QUESTION EXCLAMATION MARK;Po;0;ON;<compat> 003F 0021;;;;N;;;;; +2049;EXCLAMATION QUESTION MARK;Po;0;ON;<compat> 0021 003F;;;;N;;;;; +204A;TIRONIAN SIGN ET;Po;0;ON;;;;;N;;;;; +204B;REVERSED PILCROW SIGN;Po;0;ON;;;;;N;;;;; +204C;BLACK LEFTWARDS BULLET;Po;0;ON;;;;;N;;;;; +204D;BLACK RIGHTWARDS BULLET;Po;0;ON;;;;;N;;;;; +204E;LOW ASTERISK;Po;0;ON;;;;;N;;;;; +204F;REVERSED SEMICOLON;Po;0;ON;;;;;N;;;;; +2050;CLOSE UP;Po;0;ON;;;;;N;;;;; +2051;TWO ASTERISKS ALIGNED VERTICALLY;Po;0;ON;;;;;N;;;;; +2052;COMMERCIAL MINUS SIGN;Sm;0;ON;;;;;N;;;;; +2053;SWUNG DASH;Po;0;ON;;;;;N;;;;; +2054;INVERTED UNDERTIE;Pc;0;ON;;;;;N;;;;; +2055;FLOWER PUNCTUATION MARK;Po;0;ON;;;;;N;;;;; +2056;THREE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +2057;QUADRUPLE PRIME;Po;0;ON;<compat> 2032 2032 2032 2032;;;;N;;;;; +2058;FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +2059;FIVE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +205A;TWO DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +205B;FOUR DOT MARK;Po;0;ON;;;;;N;;;;; +205C;DOTTED CROSS;Po;0;ON;;;;;N;;;;; +205D;TRICOLON;Po;0;ON;;;;;N;;;;; +205E;VERTICAL FOUR DOTS;Po;0;ON;;;;;N;;;;; +205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;; +2060;WORD JOINER;Cf;0;BN;;;;;N;;;;; +2061;FUNCTION APPLICATION;Cf;0;BN;;;;;N;;;;; +2062;INVISIBLE TIMES;Cf;0;BN;;;;;N;;;;; +2063;INVISIBLE SEPARATOR;Cf;0;BN;;;;;N;;;;; +2064;INVISIBLE PLUS;Cf;0;BN;;;;;N;;;;; +2066;LEFT-TO-RIGHT ISOLATE;Cf;0;LRI;;;;;N;;;;; +2067;RIGHT-TO-LEFT ISOLATE;Cf;0;RLI;;;;;N;;;;; +2068;FIRST STRONG ISOLATE;Cf;0;FSI;;;;;N;;;;; +2069;POP DIRECTIONAL ISOLATE;Cf;0;PDI;;;;;N;;;;; +206A;INHIBIT SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; +206B;ACTIVATE SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; +206C;INHIBIT ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; +206D;ACTIVATE ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; +206E;NATIONAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; +206F;NOMINAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; +2070;SUPERSCRIPT ZERO;No;0;EN;<super> 0030;;0;0;N;SUPERSCRIPT DIGIT ZERO;;;; +2071;SUPERSCRIPT LATIN SMALL LETTER I;Lm;0;L;<super> 0069;;;;N;;;;; +2074;SUPERSCRIPT FOUR;No;0;EN;<super> 0034;;4;4;N;SUPERSCRIPT DIGIT FOUR;;;; +2075;SUPERSCRIPT FIVE;No;0;EN;<super> 0035;;5;5;N;SUPERSCRIPT DIGIT FIVE;;;; +2076;SUPERSCRIPT SIX;No;0;EN;<super> 0036;;6;6;N;SUPERSCRIPT DIGIT SIX;;;; +2077;SUPERSCRIPT SEVEN;No;0;EN;<super> 0037;;7;7;N;SUPERSCRIPT DIGIT SEVEN;;;; +2078;SUPERSCRIPT EIGHT;No;0;EN;<super> 0038;;8;8;N;SUPERSCRIPT DIGIT EIGHT;;;; +2079;SUPERSCRIPT NINE;No;0;EN;<super> 0039;;9;9;N;SUPERSCRIPT DIGIT NINE;;;; +207A;SUPERSCRIPT PLUS SIGN;Sm;0;ES;<super> 002B;;;;N;;;;; +207B;SUPERSCRIPT MINUS;Sm;0;ES;<super> 2212;;;;N;SUPERSCRIPT HYPHEN-MINUS;;;; +207C;SUPERSCRIPT EQUALS SIGN;Sm;0;ON;<super> 003D;;;;N;;;;; +207D;SUPERSCRIPT LEFT PARENTHESIS;Ps;0;ON;<super> 0028;;;;Y;SUPERSCRIPT OPENING PARENTHESIS;;;; +207E;SUPERSCRIPT RIGHT PARENTHESIS;Pe;0;ON;<super> 0029;;;;Y;SUPERSCRIPT CLOSING PARENTHESIS;;;; +207F;SUPERSCRIPT LATIN SMALL LETTER N;Lm;0;L;<super> 006E;;;;N;;;;; +2080;SUBSCRIPT ZERO;No;0;EN;<sub> 0030;;0;0;N;SUBSCRIPT DIGIT ZERO;;;; +2081;SUBSCRIPT ONE;No;0;EN;<sub> 0031;;1;1;N;SUBSCRIPT DIGIT ONE;;;; +2082;SUBSCRIPT TWO;No;0;EN;<sub> 0032;;2;2;N;SUBSCRIPT DIGIT TWO;;;; +2083;SUBSCRIPT THREE;No;0;EN;<sub> 0033;;3;3;N;SUBSCRIPT DIGIT THREE;;;; +2084;SUBSCRIPT FOUR;No;0;EN;<sub> 0034;;4;4;N;SUBSCRIPT DIGIT FOUR;;;; +2085;SUBSCRIPT FIVE;No;0;EN;<sub> 0035;;5;5;N;SUBSCRIPT DIGIT FIVE;;;; +2086;SUBSCRIPT SIX;No;0;EN;<sub> 0036;;6;6;N;SUBSCRIPT DIGIT SIX;;;; +2087;SUBSCRIPT SEVEN;No;0;EN;<sub> 0037;;7;7;N;SUBSCRIPT DIGIT SEVEN;;;; +2088;SUBSCRIPT EIGHT;No;0;EN;<sub> 0038;;8;8;N;SUBSCRIPT DIGIT EIGHT;;;; +2089;SUBSCRIPT NINE;No;0;EN;<sub> 0039;;9;9;N;SUBSCRIPT DIGIT NINE;;;; +208A;SUBSCRIPT PLUS SIGN;Sm;0;ES;<sub> 002B;;;;N;;;;; +208B;SUBSCRIPT MINUS;Sm;0;ES;<sub> 2212;;;;N;SUBSCRIPT HYPHEN-MINUS;;;; +208C;SUBSCRIPT EQUALS SIGN;Sm;0;ON;<sub> 003D;;;;N;;;;; +208D;SUBSCRIPT LEFT PARENTHESIS;Ps;0;ON;<sub> 0028;;;;Y;SUBSCRIPT OPENING PARENTHESIS;;;; +208E;SUBSCRIPT RIGHT PARENTHESIS;Pe;0;ON;<sub> 0029;;;;Y;SUBSCRIPT CLOSING PARENTHESIS;;;; +2090;LATIN SUBSCRIPT SMALL LETTER A;Lm;0;L;<sub> 0061;;;;N;;;;; +2091;LATIN SUBSCRIPT SMALL LETTER E;Lm;0;L;<sub> 0065;;;;N;;;;; +2092;LATIN SUBSCRIPT SMALL LETTER O;Lm;0;L;<sub> 006F;;;;N;;;;; +2093;LATIN SUBSCRIPT SMALL LETTER X;Lm;0;L;<sub> 0078;;;;N;;;;; +2094;LATIN SUBSCRIPT SMALL LETTER SCHWA;Lm;0;L;<sub> 0259;;;;N;;;;; +2095;LATIN SUBSCRIPT SMALL LETTER H;Lm;0;L;<sub> 0068;;;;N;;;;; +2096;LATIN SUBSCRIPT SMALL LETTER K;Lm;0;L;<sub> 006B;;;;N;;;;; +2097;LATIN SUBSCRIPT SMALL LETTER L;Lm;0;L;<sub> 006C;;;;N;;;;; +2098;LATIN SUBSCRIPT SMALL LETTER M;Lm;0;L;<sub> 006D;;;;N;;;;; +2099;LATIN SUBSCRIPT SMALL LETTER N;Lm;0;L;<sub> 006E;;;;N;;;;; +209A;LATIN SUBSCRIPT SMALL LETTER P;Lm;0;L;<sub> 0070;;;;N;;;;; +209B;LATIN SUBSCRIPT SMALL LETTER S;Lm;0;L;<sub> 0073;;;;N;;;;; +209C;LATIN SUBSCRIPT SMALL LETTER T;Lm;0;L;<sub> 0074;;;;N;;;;; +20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; +20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;; +20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;; +20A3;FRENCH FRANC SIGN;Sc;0;ET;;;;;N;;;;; +20A4;LIRA SIGN;Sc;0;ET;;;;;N;;;;; +20A5;MILL SIGN;Sc;0;ET;;;;;N;;;;; +20A6;NAIRA SIGN;Sc;0;ET;;;;;N;;;;; +20A7;PESETA SIGN;Sc;0;ET;;;;;N;;;;; +20A8;RUPEE SIGN;Sc;0;ET;<compat> 0052 0073;;;;N;;;;; +20A9;WON SIGN;Sc;0;ET;;;;;N;;;;; +20AA;NEW SHEQEL SIGN;Sc;0;ET;;;;;N;;;;; +20AB;DONG SIGN;Sc;0;ET;;;;;N;;;;; +20AC;EURO SIGN;Sc;0;ET;;;;;N;;;;; +20AD;KIP SIGN;Sc;0;ET;;;;;N;;;;; +20AE;TUGRIK SIGN;Sc;0;ET;;;;;N;;;;; +20AF;DRACHMA SIGN;Sc;0;ET;;;;;N;;;;; +20B0;GERMAN PENNY SIGN;Sc;0;ET;;;;;N;;;;; +20B1;PESO SIGN;Sc;0;ET;;;;;N;;;;; +20B2;GUARANI SIGN;Sc;0;ET;;;;;N;;;;; +20B3;AUSTRAL SIGN;Sc;0;ET;;;;;N;;;;; +20B4;HRYVNIA SIGN;Sc;0;ET;;;;;N;;;;; +20B5;CEDI SIGN;Sc;0;ET;;;;;N;;;;; +20B6;LIVRE TOURNOIS SIGN;Sc;0;ET;;;;;N;;;;; +20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;; +20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;; +20B9;INDIAN RUPEE SIGN;Sc;0;ET;;;;;N;;;;; +20BA;TURKISH LIRA SIGN;Sc;0;ET;;;;;N;;;;; +20BB;NORDIC MARK SIGN;Sc;0;ET;;;;;N;;;;; +20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;; +20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;; +20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;; +20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;; +20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; +20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; +20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; +20D3;COMBINING SHORT VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT VERTICAL BAR OVERLAY;;;; +20D4;COMBINING ANTICLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING ANTICLOCKWISE ARROW ABOVE;;;; +20D5;COMBINING CLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING CLOCKWISE ARROW ABOVE;;;; +20D6;COMBINING LEFT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT ARROW ABOVE;;;; +20D7;COMBINING RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT ARROW ABOVE;;;; +20D8;COMBINING RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING RING OVERLAY;;;; +20D9;COMBINING CLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING CLOCKWISE RING OVERLAY;;;; +20DA;COMBINING ANTICLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING ANTICLOCKWISE RING OVERLAY;;;; +20DB;COMBINING THREE DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING THREE DOTS ABOVE;;;; +20DC;COMBINING FOUR DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING FOUR DOTS ABOVE;;;; +20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;; +20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;; +20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;; +20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;; +20E1;COMBINING LEFT RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT RIGHT ARROW ABOVE;;;; +20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;; +20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;; +20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;; +20E5;COMBINING REVERSE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; +20E6;COMBINING DOUBLE VERTICAL STROKE OVERLAY;Mn;1;NSM;;;;;N;;;;; +20E7;COMBINING ANNUITY SYMBOL;Mn;230;NSM;;;;;N;;;;; +20E8;COMBINING TRIPLE UNDERDOT;Mn;220;NSM;;;;;N;;;;; +20E9;COMBINING WIDE BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; +20EA;COMBINING LEFTWARDS ARROW OVERLAY;Mn;1;NSM;;;;;N;;;;; +20EB;COMBINING LONG DOUBLE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; +20EC;COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; +20ED;COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; +20EE;COMBINING LEFT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; +20EF;COMBINING RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; +20F0;COMBINING ASTERISK ABOVE;Mn;230;NSM;;;;;N;;;;; +2100;ACCOUNT OF;So;0;ON;<compat> 0061 002F 0063;;;;N;;;;; +2101;ADDRESSED TO THE SUBJECT;So;0;ON;<compat> 0061 002F 0073;;;;N;;;;; +2102;DOUBLE-STRUCK CAPITAL C;Lu;0;L;<font> 0043;;;;N;DOUBLE-STRUCK C;;;; +2103;DEGREE CELSIUS;So;0;ON;<compat> 00B0 0043;;;;N;DEGREES CENTIGRADE;;;; +2104;CENTRE LINE SYMBOL;So;0;ON;;;;;N;C L SYMBOL;;;; +2105;CARE OF;So;0;ON;<compat> 0063 002F 006F;;;;N;;;;; +2106;CADA UNA;So;0;ON;<compat> 0063 002F 0075;;;;N;;;;; +2107;EULER CONSTANT;Lu;0;L;<compat> 0190;;;;N;EULERS;;;; +2108;SCRUPLE;So;0;ON;;;;;N;;;;; +2109;DEGREE FAHRENHEIT;So;0;ON;<compat> 00B0 0046;;;;N;DEGREES FAHRENHEIT;;;; +210A;SCRIPT SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +210B;SCRIPT CAPITAL H;Lu;0;L;<font> 0048;;;;N;SCRIPT H;;;; +210C;BLACK-LETTER CAPITAL H;Lu;0;L;<font> 0048;;;;N;BLACK-LETTER H;;;; +210D;DOUBLE-STRUCK CAPITAL H;Lu;0;L;<font> 0048;;;;N;DOUBLE-STRUCK H;;;; +210E;PLANCK CONSTANT;Ll;0;L;<font> 0068;;;;N;;;;; +210F;PLANCK CONSTANT OVER TWO PI;Ll;0;L;<font> 0127;;;;N;PLANCK CONSTANT OVER 2 PI;;;; +2110;SCRIPT CAPITAL I;Lu;0;L;<font> 0049;;;;N;SCRIPT I;;;; +2111;BLACK-LETTER CAPITAL I;Lu;0;L;<font> 0049;;;;N;BLACK-LETTER I;;;; +2112;SCRIPT CAPITAL L;Lu;0;L;<font> 004C;;;;N;SCRIPT L;;;; +2113;SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +2114;L B BAR SYMBOL;So;0;ON;;;;;N;;;;; +2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L;<font> 004E;;;;N;DOUBLE-STRUCK N;;;; +2116;NUMERO SIGN;So;0;ON;<compat> 004E 006F;;;;N;NUMERO;;;; +2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;; +2118;SCRIPT CAPITAL P;Sm;0;ON;;;;;N;SCRIPT P;;;; +2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L;<font> 0050;;;;N;DOUBLE-STRUCK P;;;; +211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L;<font> 0051;;;;N;DOUBLE-STRUCK Q;;;; +211B;SCRIPT CAPITAL R;Lu;0;L;<font> 0052;;;;N;SCRIPT R;;;; +211C;BLACK-LETTER CAPITAL R;Lu;0;L;<font> 0052;;;;N;BLACK-LETTER R;;;; +211D;DOUBLE-STRUCK CAPITAL R;Lu;0;L;<font> 0052;;;;N;DOUBLE-STRUCK R;;;; +211E;PRESCRIPTION TAKE;So;0;ON;;;;;N;;;;; +211F;RESPONSE;So;0;ON;;;;;N;;;;; +2120;SERVICE MARK;So;0;ON;<super> 0053 004D;;;;N;;;;; +2121;TELEPHONE SIGN;So;0;ON;<compat> 0054 0045 004C;;;;N;T E L SYMBOL;;;; +2122;TRADE MARK SIGN;So;0;ON;<super> 0054 004D;;;;N;TRADEMARK;;;; +2123;VERSICLE;So;0;ON;;;;;N;;;;; +2124;DOUBLE-STRUCK CAPITAL Z;Lu;0;L;<font> 005A;;;;N;DOUBLE-STRUCK Z;;;; +2125;OUNCE SIGN;So;0;ON;;;;;N;OUNCE;;;; +2126;OHM SIGN;Lu;0;L;03A9;;;;N;OHM;;;03C9; +2127;INVERTED OHM SIGN;So;0;ON;;;;;N;MHO;;;; +2128;BLACK-LETTER CAPITAL Z;Lu;0;L;<font> 005A;;;;N;BLACK-LETTER Z;;;; +2129;TURNED GREEK SMALL LETTER IOTA;So;0;ON;;;;;N;;;;; +212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B; +212B;ANGSTROM SIGN;Lu;0;L;00C5;;;;N;ANGSTROM UNIT;;;00E5; +212C;SCRIPT CAPITAL B;Lu;0;L;<font> 0042;;;;N;SCRIPT B;;;; +212D;BLACK-LETTER CAPITAL C;Lu;0;L;<font> 0043;;;;N;BLACK-LETTER C;;;; +212E;ESTIMATED SYMBOL;So;0;ET;;;;;N;;;;; +212F;SCRIPT SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +2130;SCRIPT CAPITAL E;Lu;0;L;<font> 0045;;;;N;SCRIPT E;;;; +2131;SCRIPT CAPITAL F;Lu;0;L;<font> 0046;;;;N;SCRIPT F;;;; +2132;TURNED CAPITAL F;Lu;0;L;;;;;N;TURNED F;;;214E; +2133;SCRIPT CAPITAL M;Lu;0;L;<font> 004D;;;;N;SCRIPT M;;;; +2134;SCRIPT SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +2135;ALEF SYMBOL;Lo;0;L;<compat> 05D0;;;;N;FIRST TRANSFINITE CARDINAL;;;; +2136;BET SYMBOL;Lo;0;L;<compat> 05D1;;;;N;SECOND TRANSFINITE CARDINAL;;;; +2137;GIMEL SYMBOL;Lo;0;L;<compat> 05D2;;;;N;THIRD TRANSFINITE CARDINAL;;;; +2138;DALET SYMBOL;Lo;0;L;<compat> 05D3;;;;N;FOURTH TRANSFINITE CARDINAL;;;; +2139;INFORMATION SOURCE;Ll;0;L;<font> 0069;;;;N;;;;; +213A;ROTATED CAPITAL Q;So;0;ON;;;;;N;;;;; +213B;FACSIMILE SIGN;So;0;ON;<compat> 0046 0041 0058;;;;N;;;;; +213C;DOUBLE-STRUCK SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; +213D;DOUBLE-STRUCK SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; +213E;DOUBLE-STRUCK CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; +213F;DOUBLE-STRUCK CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; +2140;DOUBLE-STRUCK N-ARY SUMMATION;Sm;0;ON;<font> 2211;;;;Y;;;;; +2141;TURNED SANS-SERIF CAPITAL G;Sm;0;ON;;;;;N;;;;; +2142;TURNED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; +2143;REVERSED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; +2144;TURNED SANS-SERIF CAPITAL Y;Sm;0;ON;;;;;N;;;;; +2145;DOUBLE-STRUCK ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +2146;DOUBLE-STRUCK ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +2147;DOUBLE-STRUCK ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +2148;DOUBLE-STRUCK ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +2149;DOUBLE-STRUCK ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +214A;PROPERTY LINE;So;0;ON;;;;;N;;;;; +214B;TURNED AMPERSAND;Sm;0;ON;;;;;N;;;;; +214C;PER SIGN;So;0;ON;;;;;N;;;;; +214D;AKTIESELSKAB;So;0;ON;;;;;N;;;;; +214E;TURNED SMALL F;Ll;0;L;;;;;N;;;2132;;2132 +214F;SYMBOL FOR SAMARITAN SOURCE;So;0;L;;;;;N;;;;; +2150;VULGAR FRACTION ONE SEVENTH;No;0;ON;<fraction> 0031 2044 0037;;;1/7;N;;;;; +2151;VULGAR FRACTION ONE NINTH;No;0;ON;<fraction> 0031 2044 0039;;;1/9;N;;;;; +2152;VULGAR FRACTION ONE TENTH;No;0;ON;<fraction> 0031 2044 0031 0030;;;1/10;N;;;;; +2153;VULGAR FRACTION ONE THIRD;No;0;ON;<fraction> 0031 2044 0033;;;1/3;N;FRACTION ONE THIRD;;;; +2154;VULGAR FRACTION TWO THIRDS;No;0;ON;<fraction> 0032 2044 0033;;;2/3;N;FRACTION TWO THIRDS;;;; +2155;VULGAR FRACTION ONE FIFTH;No;0;ON;<fraction> 0031 2044 0035;;;1/5;N;FRACTION ONE FIFTH;;;; +2156;VULGAR FRACTION TWO FIFTHS;No;0;ON;<fraction> 0032 2044 0035;;;2/5;N;FRACTION TWO FIFTHS;;;; +2157;VULGAR FRACTION THREE FIFTHS;No;0;ON;<fraction> 0033 2044 0035;;;3/5;N;FRACTION THREE FIFTHS;;;; +2158;VULGAR FRACTION FOUR FIFTHS;No;0;ON;<fraction> 0034 2044 0035;;;4/5;N;FRACTION FOUR FIFTHS;;;; +2159;VULGAR FRACTION ONE SIXTH;No;0;ON;<fraction> 0031 2044 0036;;;1/6;N;FRACTION ONE SIXTH;;;; +215A;VULGAR FRACTION FIVE SIXTHS;No;0;ON;<fraction> 0035 2044 0036;;;5/6;N;FRACTION FIVE SIXTHS;;;; +215B;VULGAR FRACTION ONE EIGHTH;No;0;ON;<fraction> 0031 2044 0038;;;1/8;N;FRACTION ONE EIGHTH;;;; +215C;VULGAR FRACTION THREE EIGHTHS;No;0;ON;<fraction> 0033 2044 0038;;;3/8;N;FRACTION THREE EIGHTHS;;;; +215D;VULGAR FRACTION FIVE EIGHTHS;No;0;ON;<fraction> 0035 2044 0038;;;5/8;N;FRACTION FIVE EIGHTHS;;;; +215E;VULGAR FRACTION SEVEN EIGHTHS;No;0;ON;<fraction> 0037 2044 0038;;;7/8;N;FRACTION SEVEN EIGHTHS;;;; +215F;FRACTION NUMERATOR ONE;No;0;ON;<fraction> 0031 2044;;;1;N;;;;; +2160;ROMAN NUMERAL ONE;Nl;0;L;<compat> 0049;;;1;N;;;;2170; +2161;ROMAN NUMERAL TWO;Nl;0;L;<compat> 0049 0049;;;2;N;;;;2171; +2162;ROMAN NUMERAL THREE;Nl;0;L;<compat> 0049 0049 0049;;;3;N;;;;2172; +2163;ROMAN NUMERAL FOUR;Nl;0;L;<compat> 0049 0056;;;4;N;;;;2173; +2164;ROMAN NUMERAL FIVE;Nl;0;L;<compat> 0056;;;5;N;;;;2174; +2165;ROMAN NUMERAL SIX;Nl;0;L;<compat> 0056 0049;;;6;N;;;;2175; +2166;ROMAN NUMERAL SEVEN;Nl;0;L;<compat> 0056 0049 0049;;;7;N;;;;2176; +2167;ROMAN NUMERAL EIGHT;Nl;0;L;<compat> 0056 0049 0049 0049;;;8;N;;;;2177; +2168;ROMAN NUMERAL NINE;Nl;0;L;<compat> 0049 0058;;;9;N;;;;2178; +2169;ROMAN NUMERAL TEN;Nl;0;L;<compat> 0058;;;10;N;;;;2179; +216A;ROMAN NUMERAL ELEVEN;Nl;0;L;<compat> 0058 0049;;;11;N;;;;217A; +216B;ROMAN NUMERAL TWELVE;Nl;0;L;<compat> 0058 0049 0049;;;12;N;;;;217B; +216C;ROMAN NUMERAL FIFTY;Nl;0;L;<compat> 004C;;;50;N;;;;217C; +216D;ROMAN NUMERAL ONE HUNDRED;Nl;0;L;<compat> 0043;;;100;N;;;;217D; +216E;ROMAN NUMERAL FIVE HUNDRED;Nl;0;L;<compat> 0044;;;500;N;;;;217E; +216F;ROMAN NUMERAL ONE THOUSAND;Nl;0;L;<compat> 004D;;;1000;N;;;;217F; +2170;SMALL ROMAN NUMERAL ONE;Nl;0;L;<compat> 0069;;;1;N;;;2160;;2160 +2171;SMALL ROMAN NUMERAL TWO;Nl;0;L;<compat> 0069 0069;;;2;N;;;2161;;2161 +2172;SMALL ROMAN NUMERAL THREE;Nl;0;L;<compat> 0069 0069 0069;;;3;N;;;2162;;2162 +2173;SMALL ROMAN NUMERAL FOUR;Nl;0;L;<compat> 0069 0076;;;4;N;;;2163;;2163 +2174;SMALL ROMAN NUMERAL FIVE;Nl;0;L;<compat> 0076;;;5;N;;;2164;;2164 +2175;SMALL ROMAN NUMERAL SIX;Nl;0;L;<compat> 0076 0069;;;6;N;;;2165;;2165 +2176;SMALL ROMAN NUMERAL SEVEN;Nl;0;L;<compat> 0076 0069 0069;;;7;N;;;2166;;2166 +2177;SMALL ROMAN NUMERAL EIGHT;Nl;0;L;<compat> 0076 0069 0069 0069;;;8;N;;;2167;;2167 +2178;SMALL ROMAN NUMERAL NINE;Nl;0;L;<compat> 0069 0078;;;9;N;;;2168;;2168 +2179;SMALL ROMAN NUMERAL TEN;Nl;0;L;<compat> 0078;;;10;N;;;2169;;2169 +217A;SMALL ROMAN NUMERAL ELEVEN;Nl;0;L;<compat> 0078 0069;;;11;N;;;216A;;216A +217B;SMALL ROMAN NUMERAL TWELVE;Nl;0;L;<compat> 0078 0069 0069;;;12;N;;;216B;;216B +217C;SMALL ROMAN NUMERAL FIFTY;Nl;0;L;<compat> 006C;;;50;N;;;216C;;216C +217D;SMALL ROMAN NUMERAL ONE HUNDRED;Nl;0;L;<compat> 0063;;;100;N;;;216D;;216D +217E;SMALL ROMAN NUMERAL FIVE HUNDRED;Nl;0;L;<compat> 0064;;;500;N;;;216E;;216E +217F;SMALL ROMAN NUMERAL ONE THOUSAND;Nl;0;L;<compat> 006D;;;1000;N;;;216F;;216F +2180;ROMAN NUMERAL ONE THOUSAND C D;Nl;0;L;;;;1000;N;;;;; +2181;ROMAN NUMERAL FIVE THOUSAND;Nl;0;L;;;;5000;N;;;;; +2182;ROMAN NUMERAL TEN THOUSAND;Nl;0;L;;;;10000;N;;;;; +2183;ROMAN NUMERAL REVERSED ONE HUNDRED;Lu;0;L;;;;;N;;;;2184; +2184;LATIN SMALL LETTER REVERSED C;Ll;0;L;;;;;N;;;2183;;2183 +2185;ROMAN NUMERAL SIX LATE FORM;Nl;0;L;;;;6;N;;;;; +2186;ROMAN NUMERAL FIFTY EARLY FORM;Nl;0;L;;;;50;N;;;;; +2187;ROMAN NUMERAL FIFTY THOUSAND;Nl;0;L;;;;50000;N;;;;; +2188;ROMAN NUMERAL ONE HUNDRED THOUSAND;Nl;0;L;;;;100000;N;;;;; +2189;VULGAR FRACTION ZERO THIRDS;No;0;ON;<fraction> 0030 2044 0033;;;0;N;;;;; +218A;TURNED DIGIT TWO;So;0;ON;;;;;N;;;;; +218B;TURNED DIGIT THREE;So;0;ON;;;;;N;;;;; +2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;; +2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;; +2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;; +2193;DOWNWARDS ARROW;Sm;0;ON;;;;;N;DOWN ARROW;;;; +2194;LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; +2195;UP DOWN ARROW;So;0;ON;;;;;N;;;;; +2196;NORTH WEST ARROW;So;0;ON;;;;;N;UPPER LEFT ARROW;;;; +2197;NORTH EAST ARROW;So;0;ON;;;;;N;UPPER RIGHT ARROW;;;; +2198;SOUTH EAST ARROW;So;0;ON;;;;;N;LOWER RIGHT ARROW;;;; +2199;SOUTH WEST ARROW;So;0;ON;;;;;N;LOWER LEFT ARROW;;;; +219A;LEFTWARDS ARROW WITH STROKE;Sm;0;ON;2190 0338;;;;N;LEFT ARROW WITH STROKE;;;; +219B;RIGHTWARDS ARROW WITH STROKE;Sm;0;ON;2192 0338;;;;N;RIGHT ARROW WITH STROKE;;;; +219C;LEFTWARDS WAVE ARROW;So;0;ON;;;;;N;LEFT WAVE ARROW;;;; +219D;RIGHTWARDS WAVE ARROW;So;0;ON;;;;;N;RIGHT WAVE ARROW;;;; +219E;LEFTWARDS TWO HEADED ARROW;So;0;ON;;;;;N;LEFT TWO HEADED ARROW;;;; +219F;UPWARDS TWO HEADED ARROW;So;0;ON;;;;;N;UP TWO HEADED ARROW;;;; +21A0;RIGHTWARDS TWO HEADED ARROW;Sm;0;ON;;;;;N;RIGHT TWO HEADED ARROW;;;; +21A1;DOWNWARDS TWO HEADED ARROW;So;0;ON;;;;;N;DOWN TWO HEADED ARROW;;;; +21A2;LEFTWARDS ARROW WITH TAIL;So;0;ON;;;;;N;LEFT ARROW WITH TAIL;;;; +21A3;RIGHTWARDS ARROW WITH TAIL;Sm;0;ON;;;;;N;RIGHT ARROW WITH TAIL;;;; +21A4;LEFTWARDS ARROW FROM BAR;So;0;ON;;;;;N;LEFT ARROW FROM BAR;;;; +21A5;UPWARDS ARROW FROM BAR;So;0;ON;;;;;N;UP ARROW FROM BAR;;;; +21A6;RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;RIGHT ARROW FROM BAR;;;; +21A7;DOWNWARDS ARROW FROM BAR;So;0;ON;;;;;N;DOWN ARROW FROM BAR;;;; +21A8;UP DOWN ARROW WITH BASE;So;0;ON;;;;;N;;;;; +21A9;LEFTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;LEFT ARROW WITH HOOK;;;; +21AA;RIGHTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;RIGHT ARROW WITH HOOK;;;; +21AB;LEFTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;LEFT ARROW WITH LOOP;;;; +21AC;RIGHTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;RIGHT ARROW WITH LOOP;;;; +21AD;LEFT RIGHT WAVE ARROW;So;0;ON;;;;;N;;;;; +21AE;LEFT RIGHT ARROW WITH STROKE;Sm;0;ON;2194 0338;;;;N;;;;; +21AF;DOWNWARDS ZIGZAG ARROW;So;0;ON;;;;;N;DOWN ZIGZAG ARROW;;;; +21B0;UPWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP LEFT;;;; +21B1;UPWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP RIGHT;;;; +21B2;DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP LEFT;;;; +21B3;DOWNWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP RIGHT;;;; +21B4;RIGHTWARDS ARROW WITH CORNER DOWNWARDS;So;0;ON;;;;;N;RIGHT ARROW WITH CORNER DOWN;;;; +21B5;DOWNWARDS ARROW WITH CORNER LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH CORNER LEFT;;;; +21B6;ANTICLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; +21B7;CLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; +21B8;NORTH WEST ARROW TO LONG BAR;So;0;ON;;;;;N;UPPER LEFT ARROW TO LONG BAR;;;; +21B9;LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR;;;; +21BA;ANTICLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; +21BB;CLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; +21BC;LEFTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB UP;;;; +21BD;LEFTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB DOWN;;;; +21BE;UPWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB RIGHT;;;; +21BF;UPWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB LEFT;;;; +21C0;RIGHTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB UP;;;; +21C1;RIGHTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB DOWN;;;; +21C2;DOWNWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB RIGHT;;;; +21C3;DOWNWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB LEFT;;;; +21C4;RIGHTWARDS ARROW OVER LEFTWARDS ARROW;So;0;ON;;;;;N;RIGHT ARROW OVER LEFT ARROW;;;; +21C5;UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW;So;0;ON;;;;;N;UP ARROW LEFT OF DOWN ARROW;;;; +21C6;LEFTWARDS ARROW OVER RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT ARROW OVER RIGHT ARROW;;;; +21C7;LEFTWARDS PAIRED ARROWS;So;0;ON;;;;;N;LEFT PAIRED ARROWS;;;; +21C8;UPWARDS PAIRED ARROWS;So;0;ON;;;;;N;UP PAIRED ARROWS;;;; +21C9;RIGHTWARDS PAIRED ARROWS;So;0;ON;;;;;N;RIGHT PAIRED ARROWS;;;; +21CA;DOWNWARDS PAIRED ARROWS;So;0;ON;;;;;N;DOWN PAIRED ARROWS;;;; +21CB;LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON;So;0;ON;;;;;N;LEFT HARPOON OVER RIGHT HARPOON;;;; +21CC;RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON;So;0;ON;;;;;N;RIGHT HARPOON OVER LEFT HARPOON;;;; +21CD;LEFTWARDS DOUBLE ARROW WITH STROKE;So;0;ON;21D0 0338;;;;N;LEFT DOUBLE ARROW WITH STROKE;;;; +21CE;LEFT RIGHT DOUBLE ARROW WITH STROKE;Sm;0;ON;21D4 0338;;;;N;;;;; +21CF;RIGHTWARDS DOUBLE ARROW WITH STROKE;Sm;0;ON;21D2 0338;;;;N;RIGHT DOUBLE ARROW WITH STROKE;;;; +21D0;LEFTWARDS DOUBLE ARROW;So;0;ON;;;;;N;LEFT DOUBLE ARROW;;;; +21D1;UPWARDS DOUBLE ARROW;So;0;ON;;;;;N;UP DOUBLE ARROW;;;; +21D2;RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;RIGHT DOUBLE ARROW;;;; +21D3;DOWNWARDS DOUBLE ARROW;So;0;ON;;;;;N;DOWN DOUBLE ARROW;;;; +21D4;LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; +21D5;UP DOWN DOUBLE ARROW;So;0;ON;;;;;N;;;;; +21D6;NORTH WEST DOUBLE ARROW;So;0;ON;;;;;N;UPPER LEFT DOUBLE ARROW;;;; +21D7;NORTH EAST DOUBLE ARROW;So;0;ON;;;;;N;UPPER RIGHT DOUBLE ARROW;;;; +21D8;SOUTH EAST DOUBLE ARROW;So;0;ON;;;;;N;LOWER RIGHT DOUBLE ARROW;;;; +21D9;SOUTH WEST DOUBLE ARROW;So;0;ON;;;;;N;LOWER LEFT DOUBLE ARROW;;;; +21DA;LEFTWARDS TRIPLE ARROW;So;0;ON;;;;;N;LEFT TRIPLE ARROW;;;; +21DB;RIGHTWARDS TRIPLE ARROW;So;0;ON;;;;;N;RIGHT TRIPLE ARROW;;;; +21DC;LEFTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;LEFT SQUIGGLE ARROW;;;; +21DD;RIGHTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;RIGHT SQUIGGLE ARROW;;;; +21DE;UPWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;UP ARROW WITH DOUBLE STROKE;;;; +21DF;DOWNWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;DOWN ARROW WITH DOUBLE STROKE;;;; +21E0;LEFTWARDS DASHED ARROW;So;0;ON;;;;;N;LEFT DASHED ARROW;;;; +21E1;UPWARDS DASHED ARROW;So;0;ON;;;;;N;UP DASHED ARROW;;;; +21E2;RIGHTWARDS DASHED ARROW;So;0;ON;;;;;N;RIGHT DASHED ARROW;;;; +21E3;DOWNWARDS DASHED ARROW;So;0;ON;;;;;N;DOWN DASHED ARROW;;;; +21E4;LEFTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR;;;; +21E5;RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;RIGHT ARROW TO BAR;;;; +21E6;LEFTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE LEFT ARROW;;;; +21E7;UPWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE UP ARROW;;;; +21E8;RIGHTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE RIGHT ARROW;;;; +21E9;DOWNWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE DOWN ARROW;;;; +21EA;UPWARDS WHITE ARROW FROM BAR;So;0;ON;;;;;N;WHITE UP ARROW FROM BAR;;;; +21EB;UPWARDS WHITE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; +21EC;UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; +21ED;UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; +21EE;UPWARDS WHITE DOUBLE ARROW;So;0;ON;;;;;N;;;;; +21EF;UPWARDS WHITE DOUBLE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; +21F0;RIGHTWARDS WHITE ARROW FROM WALL;So;0;ON;;;;;N;;;;; +21F1;NORTH WEST ARROW TO CORNER;So;0;ON;;;;;N;;;;; +21F2;SOUTH EAST ARROW TO CORNER;So;0;ON;;;;;N;;;;; +21F3;UP DOWN WHITE ARROW;So;0;ON;;;;;N;;;;; +21F4;RIGHT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +21F5;DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW;Sm;0;ON;;;;;N;;;;; +21F6;THREE RIGHTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; +21F7;LEFTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21F8;RIGHTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21F9;LEFT RIGHT ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21FA;LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21FB;RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21FC;LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21FD;LEFTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; +21FE;RIGHTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; +21FF;LEFT RIGHT OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; +2200;FOR ALL;Sm;0;ON;;;;;N;;;;; +2201;COMPLEMENT;Sm;0;ON;;;;;Y;;;;; +2202;PARTIAL DIFFERENTIAL;Sm;0;ON;;;;;Y;;;;; +2203;THERE EXISTS;Sm;0;ON;;;;;Y;;;;; +2204;THERE DOES NOT EXIST;Sm;0;ON;2203 0338;;;;Y;;;;; +2205;EMPTY SET;Sm;0;ON;;;;;N;;;;; +2206;INCREMENT;Sm;0;ON;;;;;N;;;;; +2207;NABLA;Sm;0;ON;;;;;N;;;;; +2208;ELEMENT OF;Sm;0;ON;;;;;Y;;;;; +2209;NOT AN ELEMENT OF;Sm;0;ON;2208 0338;;;;Y;;;;; +220A;SMALL ELEMENT OF;Sm;0;ON;;;;;Y;;;;; +220B;CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; +220C;DOES NOT CONTAIN AS MEMBER;Sm;0;ON;220B 0338;;;;Y;;;;; +220D;SMALL CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; +220E;END OF PROOF;Sm;0;ON;;;;;N;;;;; +220F;N-ARY PRODUCT;Sm;0;ON;;;;;N;;;;; +2210;N-ARY COPRODUCT;Sm;0;ON;;;;;N;;;;; +2211;N-ARY SUMMATION;Sm;0;ON;;;;;Y;;;;; +2212;MINUS SIGN;Sm;0;ES;;;;;N;;;;; +2213;MINUS-OR-PLUS SIGN;Sm;0;ET;;;;;N;;;;; +2214;DOT PLUS;Sm;0;ON;;;;;N;;;;; +2215;DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; +2216;SET MINUS;Sm;0;ON;;;;;Y;;;;; +2217;ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; +2218;RING OPERATOR;Sm;0;ON;;;;;N;;;;; +2219;BULLET OPERATOR;Sm;0;ON;;;;;N;;;;; +221A;SQUARE ROOT;Sm;0;ON;;;;;Y;;;;; +221B;CUBE ROOT;Sm;0;ON;;;;;Y;;;;; +221C;FOURTH ROOT;Sm;0;ON;;;;;Y;;;;; +221D;PROPORTIONAL TO;Sm;0;ON;;;;;Y;;;;; +221E;INFINITY;Sm;0;ON;;;;;N;;;;; +221F;RIGHT ANGLE;Sm;0;ON;;;;;Y;;;;; +2220;ANGLE;Sm;0;ON;;;;;Y;;;;; +2221;MEASURED ANGLE;Sm;0;ON;;;;;Y;;;;; +2222;SPHERICAL ANGLE;Sm;0;ON;;;;;Y;;;;; +2223;DIVIDES;Sm;0;ON;;;;;N;;;;; +2224;DOES NOT DIVIDE;Sm;0;ON;2223 0338;;;;Y;;;;; +2225;PARALLEL TO;Sm;0;ON;;;;;N;;;;; +2226;NOT PARALLEL TO;Sm;0;ON;2225 0338;;;;Y;;;;; +2227;LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2228;LOGICAL OR;Sm;0;ON;;;;;N;;;;; +2229;INTERSECTION;Sm;0;ON;;;;;N;;;;; +222A;UNION;Sm;0;ON;;;;;N;;;;; +222B;INTEGRAL;Sm;0;ON;;;;;Y;;;;; +222C;DOUBLE INTEGRAL;Sm;0;ON;<compat> 222B 222B;;;;Y;;;;; +222D;TRIPLE INTEGRAL;Sm;0;ON;<compat> 222B 222B 222B;;;;Y;;;;; +222E;CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; +222F;SURFACE INTEGRAL;Sm;0;ON;<compat> 222E 222E;;;;Y;;;;; +2230;VOLUME INTEGRAL;Sm;0;ON;<compat> 222E 222E 222E;;;;Y;;;;; +2231;CLOCKWISE INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2232;CLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2233;ANTICLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2234;THEREFORE;Sm;0;ON;;;;;N;;;;; +2235;BECAUSE;Sm;0;ON;;;;;N;;;;; +2236;RATIO;Sm;0;ON;;;;;N;;;;; +2237;PROPORTION;Sm;0;ON;;;;;N;;;;; +2238;DOT MINUS;Sm;0;ON;;;;;N;;;;; +2239;EXCESS;Sm;0;ON;;;;;Y;;;;; +223A;GEOMETRIC PROPORTION;Sm;0;ON;;;;;N;;;;; +223B;HOMOTHETIC;Sm;0;ON;;;;;Y;;;;; +223C;TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +223D;REVERSED TILDE;Sm;0;ON;;;;;Y;;;;; +223E;INVERTED LAZY S;Sm;0;ON;;;;;Y;;;;; +223F;SINE WAVE;Sm;0;ON;;;;;Y;;;;; +2240;WREATH PRODUCT;Sm;0;ON;;;;;Y;;;;; +2241;NOT TILDE;Sm;0;ON;223C 0338;;;;Y;;;;; +2242;MINUS TILDE;Sm;0;ON;;;;;Y;;;;; +2243;ASYMPTOTICALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2244;NOT ASYMPTOTICALLY EQUAL TO;Sm;0;ON;2243 0338;;;;Y;;;;; +2245;APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2246;APPROXIMATELY BUT NOT ACTUALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2247;NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO;Sm;0;ON;2245 0338;;;;Y;;;;; +2248;ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2249;NOT ALMOST EQUAL TO;Sm;0;ON;2248 0338;;;;Y;;;;; +224A;ALMOST EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +224B;TRIPLE TILDE;Sm;0;ON;;;;;Y;;;;; +224C;ALL EQUAL TO;Sm;0;ON;;;;;Y;;;;; +224D;EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; +224E;GEOMETRICALLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; +224F;DIFFERENCE BETWEEN;Sm;0;ON;;;;;N;;;;; +2250;APPROACHES THE LIMIT;Sm;0;ON;;;;;N;;;;; +2251;GEOMETRICALLY EQUAL TO;Sm;0;ON;;;;;N;;;;; +2252;APPROXIMATELY EQUAL TO OR THE IMAGE OF;Sm;0;ON;;;;;Y;;;;; +2253;IMAGE OF OR APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2254;COLON EQUALS;Sm;0;ON;;;;;Y;COLON EQUAL;;;; +2255;EQUALS COLON;Sm;0;ON;;;;;Y;EQUAL COLON;;;; +2256;RING IN EQUAL TO;Sm;0;ON;;;;;N;;;;; +2257;RING EQUAL TO;Sm;0;ON;;;;;N;;;;; +2258;CORRESPONDS TO;Sm;0;ON;;;;;N;;;;; +2259;ESTIMATES;Sm;0;ON;;;;;N;;;;; +225A;EQUIANGULAR TO;Sm;0;ON;;;;;N;;;;; +225B;STAR EQUALS;Sm;0;ON;;;;;N;;;;; +225C;DELTA EQUAL TO;Sm;0;ON;;;;;N;;;;; +225D;EQUAL TO BY DEFINITION;Sm;0;ON;;;;;N;;;;; +225E;MEASURED BY;Sm;0;ON;;;;;N;;;;; +225F;QUESTIONED EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2260;NOT EQUAL TO;Sm;0;ON;003D 0338;;;;Y;;;;; +2261;IDENTICAL TO;Sm;0;ON;;;;;N;;;;; +2262;NOT IDENTICAL TO;Sm;0;ON;2261 0338;;;;Y;;;;; +2263;STRICTLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; +2264;LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUAL TO;;;; +2265;GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUAL TO;;;; +2266;LESS-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OVER EQUAL TO;;;; +2267;GREATER-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OVER EQUAL TO;;;; +2268;LESS-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUAL TO;;;; +2269;GREATER-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUAL TO;;;; +226A;MUCH LESS-THAN;Sm;0;ON;;;;;Y;MUCH LESS THAN;;;; +226B;MUCH GREATER-THAN;Sm;0;ON;;;;;Y;MUCH GREATER THAN;;;; +226C;BETWEEN;Sm;0;ON;;;;;N;;;;; +226D;NOT EQUIVALENT TO;Sm;0;ON;224D 0338;;;;N;;;;; +226E;NOT LESS-THAN;Sm;0;ON;003C 0338;;;;Y;NOT LESS THAN;;;; +226F;NOT GREATER-THAN;Sm;0;ON;003E 0338;;;;Y;NOT GREATER THAN;;;; +2270;NEITHER LESS-THAN NOR EQUAL TO;Sm;0;ON;2264 0338;;;;Y;NEITHER LESS THAN NOR EQUAL TO;;;; +2271;NEITHER GREATER-THAN NOR EQUAL TO;Sm;0;ON;2265 0338;;;;Y;NEITHER GREATER THAN NOR EQUAL TO;;;; +2272;LESS-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUIVALENT TO;;;; +2273;GREATER-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUIVALENT TO;;;; +2274;NEITHER LESS-THAN NOR EQUIVALENT TO;Sm;0;ON;2272 0338;;;;Y;NEITHER LESS THAN NOR EQUIVALENT TO;;;; +2275;NEITHER GREATER-THAN NOR EQUIVALENT TO;Sm;0;ON;2273 0338;;;;Y;NEITHER GREATER THAN NOR EQUIVALENT TO;;;; +2276;LESS-THAN OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN OR GREATER THAN;;;; +2277;GREATER-THAN OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN OR LESS THAN;;;; +2278;NEITHER LESS-THAN NOR GREATER-THAN;Sm;0;ON;2276 0338;;;;Y;NEITHER LESS THAN NOR GREATER THAN;;;; +2279;NEITHER GREATER-THAN NOR LESS-THAN;Sm;0;ON;2277 0338;;;;Y;NEITHER GREATER THAN NOR LESS THAN;;;; +227A;PRECEDES;Sm;0;ON;;;;;Y;;;;; +227B;SUCCEEDS;Sm;0;ON;;;;;Y;;;;; +227C;PRECEDES OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +227D;SUCCEEDS OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +227E;PRECEDES OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; +227F;SUCCEEDS OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; +2280;DOES NOT PRECEDE;Sm;0;ON;227A 0338;;;;Y;;;;; +2281;DOES NOT SUCCEED;Sm;0;ON;227B 0338;;;;Y;;;;; +2282;SUBSET OF;Sm;0;ON;;;;;Y;;;;; +2283;SUPERSET OF;Sm;0;ON;;;;;Y;;;;; +2284;NOT A SUBSET OF;Sm;0;ON;2282 0338;;;;Y;;;;; +2285;NOT A SUPERSET OF;Sm;0;ON;2283 0338;;;;Y;;;;; +2286;SUBSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2287;SUPERSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2288;NEITHER A SUBSET OF NOR EQUAL TO;Sm;0;ON;2286 0338;;;;Y;;;;; +2289;NEITHER A SUPERSET OF NOR EQUAL TO;Sm;0;ON;2287 0338;;;;Y;;;;; +228A;SUBSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUBSET OF OR NOT EQUAL TO;;;; +228B;SUPERSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUPERSET OF OR NOT EQUAL TO;;;; +228C;MULTISET;Sm;0;ON;;;;;Y;;;;; +228D;MULTISET MULTIPLICATION;Sm;0;ON;;;;;N;;;;; +228E;MULTISET UNION;Sm;0;ON;;;;;N;;;;; +228F;SQUARE IMAGE OF;Sm;0;ON;;;;;Y;;;;; +2290;SQUARE ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; +2291;SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2292;SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2293;SQUARE CAP;Sm;0;ON;;;;;N;;;;; +2294;SQUARE CUP;Sm;0;ON;;;;;N;;;;; +2295;CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; +2296;CIRCLED MINUS;Sm;0;ON;;;;;N;;;;; +2297;CIRCLED TIMES;Sm;0;ON;;;;;N;;;;; +2298;CIRCLED DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; +2299;CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; +229A;CIRCLED RING OPERATOR;Sm;0;ON;;;;;N;;;;; +229B;CIRCLED ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; +229C;CIRCLED EQUALS;Sm;0;ON;;;;;N;;;;; +229D;CIRCLED DASH;Sm;0;ON;;;;;N;;;;; +229E;SQUARED PLUS;Sm;0;ON;;;;;N;;;;; +229F;SQUARED MINUS;Sm;0;ON;;;;;N;;;;; +22A0;SQUARED TIMES;Sm;0;ON;;;;;N;;;;; +22A1;SQUARED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; +22A2;RIGHT TACK;Sm;0;ON;;;;;Y;;;;; +22A3;LEFT TACK;Sm;0;ON;;;;;Y;;;;; +22A4;DOWN TACK;Sm;0;ON;;;;;N;;;;; +22A5;UP TACK;Sm;0;ON;;;;;N;;;;; +22A6;ASSERTION;Sm;0;ON;;;;;Y;;;;; +22A7;MODELS;Sm;0;ON;;;;;Y;;;;; +22A8;TRUE;Sm;0;ON;;;;;Y;;;;; +22A9;FORCES;Sm;0;ON;;;;;Y;;;;; +22AA;TRIPLE VERTICAL BAR RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +22AB;DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +22AC;DOES NOT PROVE;Sm;0;ON;22A2 0338;;;;Y;;;;; +22AD;NOT TRUE;Sm;0;ON;22A8 0338;;;;Y;;;;; +22AE;DOES NOT FORCE;Sm;0;ON;22A9 0338;;;;Y;;;;; +22AF;NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;22AB 0338;;;;Y;;;;; +22B0;PRECEDES UNDER RELATION;Sm;0;ON;;;;;Y;;;;; +22B1;SUCCEEDS UNDER RELATION;Sm;0;ON;;;;;Y;;;;; +22B2;NORMAL SUBGROUP OF;Sm;0;ON;;;;;Y;;;;; +22B3;CONTAINS AS NORMAL SUBGROUP;Sm;0;ON;;;;;Y;;;;; +22B4;NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +22B5;CONTAINS AS NORMAL SUBGROUP OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +22B6;ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; +22B7;IMAGE OF;Sm;0;ON;;;;;Y;;;;; +22B8;MULTIMAP;Sm;0;ON;;;;;Y;;;;; +22B9;HERMITIAN CONJUGATE MATRIX;Sm;0;ON;;;;;N;;;;; +22BA;INTERCALATE;Sm;0;ON;;;;;N;;;;; +22BB;XOR;Sm;0;ON;;;;;N;;;;; +22BC;NAND;Sm;0;ON;;;;;N;;;;; +22BD;NOR;Sm;0;ON;;;;;N;;;;; +22BE;RIGHT ANGLE WITH ARC;Sm;0;ON;;;;;Y;;;;; +22BF;RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; +22C0;N-ARY LOGICAL AND;Sm;0;ON;;;;;N;;;;; +22C1;N-ARY LOGICAL OR;Sm;0;ON;;;;;N;;;;; +22C2;N-ARY INTERSECTION;Sm;0;ON;;;;;N;;;;; +22C3;N-ARY UNION;Sm;0;ON;;;;;N;;;;; +22C4;DIAMOND OPERATOR;Sm;0;ON;;;;;N;;;;; +22C5;DOT OPERATOR;Sm;0;ON;;;;;N;;;;; +22C6;STAR OPERATOR;Sm;0;ON;;;;;N;;;;; +22C7;DIVISION TIMES;Sm;0;ON;;;;;N;;;;; +22C8;BOWTIE;Sm;0;ON;;;;;N;;;;; +22C9;LEFT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; +22CA;RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; +22CB;LEFT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; +22CC;RIGHT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; +22CD;REVERSED TILDE EQUALS;Sm;0;ON;;;;;Y;;;;; +22CE;CURLY LOGICAL OR;Sm;0;ON;;;;;N;;;;; +22CF;CURLY LOGICAL AND;Sm;0;ON;;;;;N;;;;; +22D0;DOUBLE SUBSET;Sm;0;ON;;;;;Y;;;;; +22D1;DOUBLE SUPERSET;Sm;0;ON;;;;;Y;;;;; +22D2;DOUBLE INTERSECTION;Sm;0;ON;;;;;N;;;;; +22D3;DOUBLE UNION;Sm;0;ON;;;;;N;;;;; +22D4;PITCHFORK;Sm;0;ON;;;;;N;;;;; +22D5;EQUAL AND PARALLEL TO;Sm;0;ON;;;;;N;;;;; +22D6;LESS-THAN WITH DOT;Sm;0;ON;;;;;Y;LESS THAN WITH DOT;;;; +22D7;GREATER-THAN WITH DOT;Sm;0;ON;;;;;Y;GREATER THAN WITH DOT;;;; +22D8;VERY MUCH LESS-THAN;Sm;0;ON;;;;;Y;VERY MUCH LESS THAN;;;; +22D9;VERY MUCH GREATER-THAN;Sm;0;ON;;;;;Y;VERY MUCH GREATER THAN;;;; +22DA;LESS-THAN EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN EQUAL TO OR GREATER THAN;;;; +22DB;GREATER-THAN EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN EQUAL TO OR LESS THAN;;;; +22DC;EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR LESS THAN;;;; +22DD;EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR GREATER THAN;;;; +22DE;EQUAL TO OR PRECEDES;Sm;0;ON;;;;;Y;;;;; +22DF;EQUAL TO OR SUCCEEDS;Sm;0;ON;;;;;Y;;;;; +22E0;DOES NOT PRECEDE OR EQUAL;Sm;0;ON;227C 0338;;;;Y;;;;; +22E1;DOES NOT SUCCEED OR EQUAL;Sm;0;ON;227D 0338;;;;Y;;;;; +22E2;NOT SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;2291 0338;;;;Y;;;;; +22E3;NOT SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;2292 0338;;;;Y;;;;; +22E4;SQUARE IMAGE OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +22E5;SQUARE ORIGINAL OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +22E6;LESS-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUIVALENT TO;;;; +22E7;GREATER-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUIVALENT TO;;;; +22E8;PRECEDES BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; +22E9;SUCCEEDS BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; +22EA;NOT NORMAL SUBGROUP OF;Sm;0;ON;22B2 0338;;;;Y;;;;; +22EB;DOES NOT CONTAIN AS NORMAL SUBGROUP;Sm;0;ON;22B3 0338;;;;Y;;;;; +22EC;NOT NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;22B4 0338;;;;Y;;;;; +22ED;DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL;Sm;0;ON;22B5 0338;;;;Y;;;;; +22EE;VERTICAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; +22EF;MIDLINE HORIZONTAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; +22F0;UP RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; +22F1;DOWN RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; +22F2;ELEMENT OF WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22F3;ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22F4;SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22F5;ELEMENT OF WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +22F6;ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +22F7;SMALL ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +22F8;ELEMENT OF WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +22F9;ELEMENT OF WITH TWO HORIZONTAL STROKES;Sm;0;ON;;;;;Y;;;;; +22FA;CONTAINS WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22FB;CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22FC;SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22FD;CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +22FE;SMALL CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +22FF;Z NOTATION BAG MEMBERSHIP;Sm;0;ON;;;;;Y;;;;; +2300;DIAMETER SIGN;So;0;ON;;;;;N;;;;; +2301;ELECTRIC ARROW;So;0;ON;;;;;N;;;;; +2302;HOUSE;So;0;ON;;;;;N;;;;; +2303;UP ARROWHEAD;So;0;ON;;;;;N;;;;; +2304;DOWN ARROWHEAD;So;0;ON;;;;;N;;;;; +2305;PROJECTIVE;So;0;ON;;;;;N;;;;; +2306;PERSPECTIVE;So;0;ON;;;;;N;;;;; +2307;WAVY LINE;So;0;ON;;;;;N;;;;; +2308;LEFT CEILING;Ps;0;ON;;;;;Y;;;;; +2309;RIGHT CEILING;Pe;0;ON;;;;;Y;;;;; +230A;LEFT FLOOR;Ps;0;ON;;;;;Y;;;;; +230B;RIGHT FLOOR;Pe;0;ON;;;;;Y;;;;; +230C;BOTTOM RIGHT CROP;So;0;ON;;;;;N;;;;; +230D;BOTTOM LEFT CROP;So;0;ON;;;;;N;;;;; +230E;TOP RIGHT CROP;So;0;ON;;;;;N;;;;; +230F;TOP LEFT CROP;So;0;ON;;;;;N;;;;; +2310;REVERSED NOT SIGN;So;0;ON;;;;;N;;;;; +2311;SQUARE LOZENGE;So;0;ON;;;;;N;;;;; +2312;ARC;So;0;ON;;;;;N;;;;; +2313;SEGMENT;So;0;ON;;;;;N;;;;; +2314;SECTOR;So;0;ON;;;;;N;;;;; +2315;TELEPHONE RECORDER;So;0;ON;;;;;N;;;;; +2316;POSITION INDICATOR;So;0;ON;;;;;N;;;;; +2317;VIEWDATA SQUARE;So;0;ON;;;;;N;;;;; +2318;PLACE OF INTEREST SIGN;So;0;ON;;;;;N;COMMAND KEY;;;; +2319;TURNED NOT SIGN;So;0;ON;;;;;N;;;;; +231A;WATCH;So;0;ON;;;;;N;;;;; +231B;HOURGLASS;So;0;ON;;;;;N;;;;; +231C;TOP LEFT CORNER;So;0;ON;;;;;N;;;;; +231D;TOP RIGHT CORNER;So;0;ON;;;;;N;;;;; +231E;BOTTOM LEFT CORNER;So;0;ON;;;;;N;;;;; +231F;BOTTOM RIGHT CORNER;So;0;ON;;;;;N;;;;; +2320;TOP HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2321;BOTTOM HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2322;FROWN;So;0;ON;;;;;N;;;;; +2323;SMILE;So;0;ON;;;;;N;;;;; +2324;UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS;So;0;ON;;;;;N;ENTER KEY;;;; +2325;OPTION KEY;So;0;ON;;;;;N;;;;; +2326;ERASE TO THE RIGHT;So;0;ON;;;;;N;DELETE TO THE RIGHT KEY;;;; +2327;X IN A RECTANGLE BOX;So;0;ON;;;;;N;CLEAR KEY;;;; +2328;KEYBOARD;So;0;ON;;;;;N;;;;; +2329;LEFT-POINTING ANGLE BRACKET;Ps;0;ON;3008;;;;Y;BRA;;;; +232A;RIGHT-POINTING ANGLE BRACKET;Pe;0;ON;3009;;;;Y;KET;;;; +232B;ERASE TO THE LEFT;So;0;ON;;;;;N;DELETE TO THE LEFT KEY;;;; +232C;BENZENE RING;So;0;ON;;;;;N;;;;; +232D;CYLINDRICITY;So;0;ON;;;;;N;;;;; +232E;ALL AROUND-PROFILE;So;0;ON;;;;;N;;;;; +232F;SYMMETRY;So;0;ON;;;;;N;;;;; +2330;TOTAL RUNOUT;So;0;ON;;;;;N;;;;; +2331;DIMENSION ORIGIN;So;0;ON;;;;;N;;;;; +2332;CONICAL TAPER;So;0;ON;;;;;N;;;;; +2333;SLOPE;So;0;ON;;;;;N;;;;; +2334;COUNTERBORE;So;0;ON;;;;;N;;;;; +2335;COUNTERSINK;So;0;ON;;;;;N;;;;; +2336;APL FUNCTIONAL SYMBOL I-BEAM;So;0;L;;;;;N;;;;; +2337;APL FUNCTIONAL SYMBOL SQUISH QUAD;So;0;L;;;;;N;;;;; +2338;APL FUNCTIONAL SYMBOL QUAD EQUAL;So;0;L;;;;;N;;;;; +2339;APL FUNCTIONAL SYMBOL QUAD DIVIDE;So;0;L;;;;;N;;;;; +233A;APL FUNCTIONAL SYMBOL QUAD DIAMOND;So;0;L;;;;;N;;;;; +233B;APL FUNCTIONAL SYMBOL QUAD JOT;So;0;L;;;;;N;;;;; +233C;APL FUNCTIONAL SYMBOL QUAD CIRCLE;So;0;L;;;;;N;;;;; +233D;APL FUNCTIONAL SYMBOL CIRCLE STILE;So;0;L;;;;;N;;;;; +233E;APL FUNCTIONAL SYMBOL CIRCLE JOT;So;0;L;;;;;N;;;;; +233F;APL FUNCTIONAL SYMBOL SLASH BAR;So;0;L;;;;;N;;;;; +2340;APL FUNCTIONAL SYMBOL BACKSLASH BAR;So;0;L;;;;;N;;;;; +2341;APL FUNCTIONAL SYMBOL QUAD SLASH;So;0;L;;;;;N;;;;; +2342;APL FUNCTIONAL SYMBOL QUAD BACKSLASH;So;0;L;;;;;N;;;;; +2343;APL FUNCTIONAL SYMBOL QUAD LESS-THAN;So;0;L;;;;;N;;;;; +2344;APL FUNCTIONAL SYMBOL QUAD GREATER-THAN;So;0;L;;;;;N;;;;; +2345;APL FUNCTIONAL SYMBOL LEFTWARDS VANE;So;0;L;;;;;N;;;;; +2346;APL FUNCTIONAL SYMBOL RIGHTWARDS VANE;So;0;L;;;;;N;;;;; +2347;APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW;So;0;L;;;;;N;;;;; +2348;APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW;So;0;L;;;;;N;;;;; +2349;APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH;So;0;L;;;;;N;;;;; +234A;APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR;So;0;L;;;;;N;;;;; +234B;APL FUNCTIONAL SYMBOL DELTA STILE;So;0;L;;;;;N;;;;; +234C;APL FUNCTIONAL SYMBOL QUAD DOWN CARET;So;0;L;;;;;N;;;;; +234D;APL FUNCTIONAL SYMBOL QUAD DELTA;So;0;L;;;;;N;;;;; +234E;APL FUNCTIONAL SYMBOL DOWN TACK JOT;So;0;L;;;;;N;;;;; +234F;APL FUNCTIONAL SYMBOL UPWARDS VANE;So;0;L;;;;;N;;;;; +2350;APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW;So;0;L;;;;;N;;;;; +2351;APL FUNCTIONAL SYMBOL UP TACK OVERBAR;So;0;L;;;;;N;;;;; +2352;APL FUNCTIONAL SYMBOL DEL STILE;So;0;L;;;;;N;;;;; +2353;APL FUNCTIONAL SYMBOL QUAD UP CARET;So;0;L;;;;;N;;;;; +2354;APL FUNCTIONAL SYMBOL QUAD DEL;So;0;L;;;;;N;;;;; +2355;APL FUNCTIONAL SYMBOL UP TACK JOT;So;0;L;;;;;N;;;;; +2356;APL FUNCTIONAL SYMBOL DOWNWARDS VANE;So;0;L;;;;;N;;;;; +2357;APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW;So;0;L;;;;;N;;;;; +2358;APL FUNCTIONAL SYMBOL QUOTE UNDERBAR;So;0;L;;;;;N;;;;; +2359;APL FUNCTIONAL SYMBOL DELTA UNDERBAR;So;0;L;;;;;N;;;;; +235A;APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR;So;0;L;;;;;N;;;;; +235B;APL FUNCTIONAL SYMBOL JOT UNDERBAR;So;0;L;;;;;N;;;;; +235C;APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR;So;0;L;;;;;N;;;;; +235D;APL FUNCTIONAL SYMBOL UP SHOE JOT;So;0;L;;;;;N;;;;; +235E;APL FUNCTIONAL SYMBOL QUOTE QUAD;So;0;L;;;;;N;;;;; +235F;APL FUNCTIONAL SYMBOL CIRCLE STAR;So;0;L;;;;;N;;;;; +2360;APL FUNCTIONAL SYMBOL QUAD COLON;So;0;L;;;;;N;;;;; +2361;APL FUNCTIONAL SYMBOL UP TACK DIAERESIS;So;0;L;;;;;N;;;;; +2362;APL FUNCTIONAL SYMBOL DEL DIAERESIS;So;0;L;;;;;N;;;;; +2363;APL FUNCTIONAL SYMBOL STAR DIAERESIS;So;0;L;;;;;N;;;;; +2364;APL FUNCTIONAL SYMBOL JOT DIAERESIS;So;0;L;;;;;N;;;;; +2365;APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS;So;0;L;;;;;N;;;;; +2366;APL FUNCTIONAL SYMBOL DOWN SHOE STILE;So;0;L;;;;;N;;;;; +2367;APL FUNCTIONAL SYMBOL LEFT SHOE STILE;So;0;L;;;;;N;;;;; +2368;APL FUNCTIONAL SYMBOL TILDE DIAERESIS;So;0;L;;;;;N;;;;; +2369;APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS;So;0;L;;;;;N;;;;; +236A;APL FUNCTIONAL SYMBOL COMMA BAR;So;0;L;;;;;N;;;;; +236B;APL FUNCTIONAL SYMBOL DEL TILDE;So;0;L;;;;;N;;;;; +236C;APL FUNCTIONAL SYMBOL ZILDE;So;0;L;;;;;N;;;;; +236D;APL FUNCTIONAL SYMBOL STILE TILDE;So;0;L;;;;;N;;;;; +236E;APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR;So;0;L;;;;;N;;;;; +236F;APL FUNCTIONAL SYMBOL QUAD NOT EQUAL;So;0;L;;;;;N;;;;; +2370;APL FUNCTIONAL SYMBOL QUAD QUESTION;So;0;L;;;;;N;;;;; +2371;APL FUNCTIONAL SYMBOL DOWN CARET TILDE;So;0;L;;;;;N;;;;; +2372;APL FUNCTIONAL SYMBOL UP CARET TILDE;So;0;L;;;;;N;;;;; +2373;APL FUNCTIONAL SYMBOL IOTA;So;0;L;;;;;N;;;;; +2374;APL FUNCTIONAL SYMBOL RHO;So;0;L;;;;;N;;;;; +2375;APL FUNCTIONAL SYMBOL OMEGA;So;0;L;;;;;N;;;;; +2376;APL FUNCTIONAL SYMBOL ALPHA UNDERBAR;So;0;L;;;;;N;;;;; +2377;APL FUNCTIONAL SYMBOL EPSILON UNDERBAR;So;0;L;;;;;N;;;;; +2378;APL FUNCTIONAL SYMBOL IOTA UNDERBAR;So;0;L;;;;;N;;;;; +2379;APL FUNCTIONAL SYMBOL OMEGA UNDERBAR;So;0;L;;;;;N;;;;; +237A;APL FUNCTIONAL SYMBOL ALPHA;So;0;L;;;;;N;;;;; +237B;NOT CHECK MARK;So;0;ON;;;;;N;;;;; +237C;RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW;Sm;0;ON;;;;;N;;;;; +237D;SHOULDERED OPEN BOX;So;0;ON;;;;;N;;;;; +237E;BELL SYMBOL;So;0;ON;;;;;N;;;;; +237F;VERTICAL LINE WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; +2380;INSERTION SYMBOL;So;0;ON;;;;;N;;;;; +2381;CONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; +2382;DISCONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; +2383;EMPHASIS SYMBOL;So;0;ON;;;;;N;;;;; +2384;COMPOSITION SYMBOL;So;0;ON;;;;;N;;;;; +2385;WHITE SQUARE WITH CENTRE VERTICAL LINE;So;0;ON;;;;;N;;;;; +2386;ENTER SYMBOL;So;0;ON;;;;;N;;;;; +2387;ALTERNATIVE KEY SYMBOL;So;0;ON;;;;;N;;;;; +2388;HELM SYMBOL;So;0;ON;;;;;N;;;;; +2389;CIRCLED HORIZONTAL BAR WITH NOTCH;So;0;ON;;;;;N;;;;; +238A;CIRCLED TRIANGLE DOWN;So;0;ON;;;;;N;;;;; +238B;BROKEN CIRCLE WITH NORTHWEST ARROW;So;0;ON;;;;;N;;;;; +238C;UNDO SYMBOL;So;0;ON;;;;;N;;;;; +238D;MONOSTABLE SYMBOL;So;0;ON;;;;;N;;;;; +238E;HYSTERESIS SYMBOL;So;0;ON;;;;;N;;;;; +238F;OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL;So;0;ON;;;;;N;;;;; +2390;OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL;So;0;ON;;;;;N;;;;; +2391;PASSIVE-PULL-DOWN-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; +2392;PASSIVE-PULL-UP-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; +2393;DIRECT CURRENT SYMBOL FORM TWO;So;0;ON;;;;;N;;;;; +2394;SOFTWARE-FUNCTION SYMBOL;So;0;ON;;;;;N;;;;; +2395;APL FUNCTIONAL SYMBOL QUAD;So;0;L;;;;;N;;;;; +2396;DECIMAL SEPARATOR KEY SYMBOL;So;0;ON;;;;;N;;;;; +2397;PREVIOUS PAGE;So;0;ON;;;;;N;;;;; +2398;NEXT PAGE;So;0;ON;;;;;N;;;;; +2399;PRINT SCREEN SYMBOL;So;0;ON;;;;;N;;;;; +239A;CLEAR SCREEN SYMBOL;So;0;ON;;;;;N;;;;; +239B;LEFT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; +239C;LEFT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; +239D;LEFT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; +239E;RIGHT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; +239F;RIGHT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; +23A0;RIGHT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; +23A1;LEFT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; +23A2;LEFT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; +23A3;LEFT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; +23A4;RIGHT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; +23A5;RIGHT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; +23A6;RIGHT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; +23A7;LEFT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; +23A8;LEFT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; +23A9;LEFT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; +23AA;CURLY BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; +23AB;RIGHT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; +23AC;RIGHT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; +23AD;RIGHT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; +23AE;INTEGRAL EXTENSION;Sm;0;ON;;;;;N;;;;; +23AF;HORIZONTAL LINE EXTENSION;Sm;0;ON;;;;;N;;;;; +23B0;UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; +23B1;UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; +23B2;SUMMATION TOP;Sm;0;ON;;;;;N;;;;; +23B3;SUMMATION BOTTOM;Sm;0;ON;;;;;N;;;;; +23B4;TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; +23B5;BOTTOM SQUARE BRACKET;So;0;ON;;;;;N;;;;; +23B6;BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; +23B7;RADICAL SYMBOL BOTTOM;So;0;ON;;;;;N;;;;; +23B8;LEFT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; +23B9;RIGHT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; +23BA;HORIZONTAL SCAN LINE-1;So;0;ON;;;;;N;;;;; +23BB;HORIZONTAL SCAN LINE-3;So;0;ON;;;;;N;;;;; +23BC;HORIZONTAL SCAN LINE-7;So;0;ON;;;;;N;;;;; +23BD;HORIZONTAL SCAN LINE-9;So;0;ON;;;;;N;;;;; +23BE;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;; +23BF;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;; +23C0;DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE;So;0;ON;;;;;N;;;;; +23C1;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; +23C2;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; +23C3;DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; +23C4;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; +23C5;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; +23C6;DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE;So;0;ON;;;;;N;;;;; +23C7;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; +23C8;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; +23C9;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;;;;; +23CA;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;;;;; +23CB;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;; +23CC;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;; +23CD;SQUARE FOOT;So;0;ON;;;;;N;;;;; +23CE;RETURN SYMBOL;So;0;ON;;;;;N;;;;; +23CF;EJECT SYMBOL;So;0;ON;;;;;N;;;;; +23D0;VERTICAL LINE EXTENSION;So;0;ON;;;;;N;;;;; +23D1;METRICAL BREVE;So;0;ON;;;;;N;;;;; +23D2;METRICAL LONG OVER SHORT;So;0;ON;;;;;N;;;;; +23D3;METRICAL SHORT OVER LONG;So;0;ON;;;;;N;;;;; +23D4;METRICAL LONG OVER TWO SHORTS;So;0;ON;;;;;N;;;;; +23D5;METRICAL TWO SHORTS OVER LONG;So;0;ON;;;;;N;;;;; +23D6;METRICAL TWO SHORTS JOINED;So;0;ON;;;;;N;;;;; +23D7;METRICAL TRISEME;So;0;ON;;;;;N;;;;; +23D8;METRICAL TETRASEME;So;0;ON;;;;;N;;;;; +23D9;METRICAL PENTASEME;So;0;ON;;;;;N;;;;; +23DA;EARTH GROUND;So;0;ON;;;;;N;;;;; +23DB;FUSE;So;0;ON;;;;;N;;;;; +23DC;TOP PARENTHESIS;Sm;0;ON;;;;;N;;;;; +23DD;BOTTOM PARENTHESIS;Sm;0;ON;;;;;N;;;;; +23DE;TOP CURLY BRACKET;Sm;0;ON;;;;;N;;;;; +23DF;BOTTOM CURLY BRACKET;Sm;0;ON;;;;;N;;;;; +23E0;TOP TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; +23E1;BOTTOM TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; +23E2;WHITE TRAPEZIUM;So;0;ON;;;;;N;;;;; +23E3;BENZENE RING WITH CIRCLE;So;0;ON;;;;;N;;;;; +23E4;STRAIGHTNESS;So;0;ON;;;;;N;;;;; +23E5;FLATNESS;So;0;ON;;;;;N;;;;; +23E6;AC CURRENT;So;0;ON;;;;;N;;;;; +23E7;ELECTRICAL INTERSECTION;So;0;ON;;;;;N;;;;; +23E8;DECIMAL EXPONENT SYMBOL;So;0;ON;;;;;N;;;;; +23E9;BLACK RIGHT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EA;BLACK LEFT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EB;BLACK UP-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EC;BLACK DOWN-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23ED;BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; +23EE;BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; +23EF;BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; +23F0;ALARM CLOCK;So;0;ON;;;;;N;;;;; +23F1;STOPWATCH;So;0;ON;;;;;N;;;;; +23F2;TIMER CLOCK;So;0;ON;;;;;N;;;;; +23F3;HOURGLASS WITH FLOWING SAND;So;0;ON;;;;;N;;;;; +23F4;BLACK MEDIUM LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +23F5;BLACK MEDIUM RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +23F6;BLACK MEDIUM UP-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +23F7;BLACK MEDIUM DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +23F8;DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; +23F9;BLACK SQUARE FOR STOP;So;0;ON;;;;;N;;;;; +23FA;BLACK CIRCLE FOR RECORD;So;0;ON;;;;;N;;;;; +23FB;POWER SYMBOL;So;0;ON;;;;;N;;;;; +23FC;POWER ON-OFF SYMBOL;So;0;ON;;;;;N;;;;; +23FD;POWER ON SYMBOL;So;0;ON;;;;;N;;;;; +23FE;POWER SLEEP SYMBOL;So;0;ON;;;;;N;;;;; +23FF;OBSERVER EYE SYMBOL;So;0;ON;;;;;N;;;;; +2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; +2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; +2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; +2403;SYMBOL FOR END OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR END OF TEXT;;;; +2404;SYMBOL FOR END OF TRANSMISSION;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION;;;; +2405;SYMBOL FOR ENQUIRY;So;0;ON;;;;;N;GRAPHIC FOR ENQUIRY;;;; +2406;SYMBOL FOR ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR ACKNOWLEDGE;;;; +2407;SYMBOL FOR BELL;So;0;ON;;;;;N;GRAPHIC FOR BELL;;;; +2408;SYMBOL FOR BACKSPACE;So;0;ON;;;;;N;GRAPHIC FOR BACKSPACE;;;; +2409;SYMBOL FOR HORIZONTAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR HORIZONTAL TABULATION;;;; +240A;SYMBOL FOR LINE FEED;So;0;ON;;;;;N;GRAPHIC FOR LINE FEED;;;; +240B;SYMBOL FOR VERTICAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR VERTICAL TABULATION;;;; +240C;SYMBOL FOR FORM FEED;So;0;ON;;;;;N;GRAPHIC FOR FORM FEED;;;; +240D;SYMBOL FOR CARRIAGE RETURN;So;0;ON;;;;;N;GRAPHIC FOR CARRIAGE RETURN;;;; +240E;SYMBOL FOR SHIFT OUT;So;0;ON;;;;;N;GRAPHIC FOR SHIFT OUT;;;; +240F;SYMBOL FOR SHIFT IN;So;0;ON;;;;;N;GRAPHIC FOR SHIFT IN;;;; +2410;SYMBOL FOR DATA LINK ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR DATA LINK ESCAPE;;;; +2411;SYMBOL FOR DEVICE CONTROL ONE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL ONE;;;; +2412;SYMBOL FOR DEVICE CONTROL TWO;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL TWO;;;; +2413;SYMBOL FOR DEVICE CONTROL THREE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL THREE;;;; +2414;SYMBOL FOR DEVICE CONTROL FOUR;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL FOUR;;;; +2415;SYMBOL FOR NEGATIVE ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR NEGATIVE ACKNOWLEDGE;;;; +2416;SYMBOL FOR SYNCHRONOUS IDLE;So;0;ON;;;;;N;GRAPHIC FOR SYNCHRONOUS IDLE;;;; +2417;SYMBOL FOR END OF TRANSMISSION BLOCK;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION BLOCK;;;; +2418;SYMBOL FOR CANCEL;So;0;ON;;;;;N;GRAPHIC FOR CANCEL;;;; +2419;SYMBOL FOR END OF MEDIUM;So;0;ON;;;;;N;GRAPHIC FOR END OF MEDIUM;;;; +241A;SYMBOL FOR SUBSTITUTE;So;0;ON;;;;;N;GRAPHIC FOR SUBSTITUTE;;;; +241B;SYMBOL FOR ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR ESCAPE;;;; +241C;SYMBOL FOR FILE SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR FILE SEPARATOR;;;; +241D;SYMBOL FOR GROUP SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR GROUP SEPARATOR;;;; +241E;SYMBOL FOR RECORD SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR RECORD SEPARATOR;;;; +241F;SYMBOL FOR UNIT SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR UNIT SEPARATOR;;;; +2420;SYMBOL FOR SPACE;So;0;ON;;;;;N;GRAPHIC FOR SPACE;;;; +2421;SYMBOL FOR DELETE;So;0;ON;;;;;N;GRAPHIC FOR DELETE;;;; +2422;BLANK SYMBOL;So;0;ON;;;;;N;BLANK;;;; +2423;OPEN BOX;So;0;ON;;;;;N;;;;; +2424;SYMBOL FOR NEWLINE;So;0;ON;;;;;N;GRAPHIC FOR NEWLINE;;;; +2425;SYMBOL FOR DELETE FORM TWO;So;0;ON;;;;;N;;;;; +2426;SYMBOL FOR SUBSTITUTE FORM TWO;So;0;ON;;;;;N;;;;; +2440;OCR HOOK;So;0;ON;;;;;N;;;;; +2441;OCR CHAIR;So;0;ON;;;;;N;;;;; +2442;OCR FORK;So;0;ON;;;;;N;;;;; +2443;OCR INVERTED FORK;So;0;ON;;;;;N;;;;; +2444;OCR BELT BUCKLE;So;0;ON;;;;;N;;;;; +2445;OCR BOW TIE;So;0;ON;;;;;N;;;;; +2446;OCR BRANCH BANK IDENTIFICATION;So;0;ON;;;;;N;;;;; +2447;OCR AMOUNT OF CHECK;So;0;ON;;;;;N;;;;; +2448;OCR DASH;So;0;ON;;;;;N;;;;; +2449;OCR CUSTOMER ACCOUNT NUMBER;So;0;ON;;;;;N;;;;; +244A;OCR DOUBLE BACKSLASH;So;0;ON;;;;;N;;;;; +2460;CIRCLED DIGIT ONE;No;0;ON;<circle> 0031;;1;1;N;;;;; +2461;CIRCLED DIGIT TWO;No;0;ON;<circle> 0032;;2;2;N;;;;; +2462;CIRCLED DIGIT THREE;No;0;ON;<circle> 0033;;3;3;N;;;;; +2463;CIRCLED DIGIT FOUR;No;0;ON;<circle> 0034;;4;4;N;;;;; +2464;CIRCLED DIGIT FIVE;No;0;ON;<circle> 0035;;5;5;N;;;;; +2465;CIRCLED DIGIT SIX;No;0;ON;<circle> 0036;;6;6;N;;;;; +2466;CIRCLED DIGIT SEVEN;No;0;ON;<circle> 0037;;7;7;N;;;;; +2467;CIRCLED DIGIT EIGHT;No;0;ON;<circle> 0038;;8;8;N;;;;; +2468;CIRCLED DIGIT NINE;No;0;ON;<circle> 0039;;9;9;N;;;;; +2469;CIRCLED NUMBER TEN;No;0;ON;<circle> 0031 0030;;;10;N;;;;; +246A;CIRCLED NUMBER ELEVEN;No;0;ON;<circle> 0031 0031;;;11;N;;;;; +246B;CIRCLED NUMBER TWELVE;No;0;ON;<circle> 0031 0032;;;12;N;;;;; +246C;CIRCLED NUMBER THIRTEEN;No;0;ON;<circle> 0031 0033;;;13;N;;;;; +246D;CIRCLED NUMBER FOURTEEN;No;0;ON;<circle> 0031 0034;;;14;N;;;;; +246E;CIRCLED NUMBER FIFTEEN;No;0;ON;<circle> 0031 0035;;;15;N;;;;; +246F;CIRCLED NUMBER SIXTEEN;No;0;ON;<circle> 0031 0036;;;16;N;;;;; +2470;CIRCLED NUMBER SEVENTEEN;No;0;ON;<circle> 0031 0037;;;17;N;;;;; +2471;CIRCLED NUMBER EIGHTEEN;No;0;ON;<circle> 0031 0038;;;18;N;;;;; +2472;CIRCLED NUMBER NINETEEN;No;0;ON;<circle> 0031 0039;;;19;N;;;;; +2473;CIRCLED NUMBER TWENTY;No;0;ON;<circle> 0032 0030;;;20;N;;;;; +2474;PARENTHESIZED DIGIT ONE;No;0;ON;<compat> 0028 0031 0029;;1;1;N;;;;; +2475;PARENTHESIZED DIGIT TWO;No;0;ON;<compat> 0028 0032 0029;;2;2;N;;;;; +2476;PARENTHESIZED DIGIT THREE;No;0;ON;<compat> 0028 0033 0029;;3;3;N;;;;; +2477;PARENTHESIZED DIGIT FOUR;No;0;ON;<compat> 0028 0034 0029;;4;4;N;;;;; +2478;PARENTHESIZED DIGIT FIVE;No;0;ON;<compat> 0028 0035 0029;;5;5;N;;;;; +2479;PARENTHESIZED DIGIT SIX;No;0;ON;<compat> 0028 0036 0029;;6;6;N;;;;; +247A;PARENTHESIZED DIGIT SEVEN;No;0;ON;<compat> 0028 0037 0029;;7;7;N;;;;; +247B;PARENTHESIZED DIGIT EIGHT;No;0;ON;<compat> 0028 0038 0029;;8;8;N;;;;; +247C;PARENTHESIZED DIGIT NINE;No;0;ON;<compat> 0028 0039 0029;;9;9;N;;;;; +247D;PARENTHESIZED NUMBER TEN;No;0;ON;<compat> 0028 0031 0030 0029;;;10;N;;;;; +247E;PARENTHESIZED NUMBER ELEVEN;No;0;ON;<compat> 0028 0031 0031 0029;;;11;N;;;;; +247F;PARENTHESIZED NUMBER TWELVE;No;0;ON;<compat> 0028 0031 0032 0029;;;12;N;;;;; +2480;PARENTHESIZED NUMBER THIRTEEN;No;0;ON;<compat> 0028 0031 0033 0029;;;13;N;;;;; +2481;PARENTHESIZED NUMBER FOURTEEN;No;0;ON;<compat> 0028 0031 0034 0029;;;14;N;;;;; +2482;PARENTHESIZED NUMBER FIFTEEN;No;0;ON;<compat> 0028 0031 0035 0029;;;15;N;;;;; +2483;PARENTHESIZED NUMBER SIXTEEN;No;0;ON;<compat> 0028 0031 0036 0029;;;16;N;;;;; +2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;ON;<compat> 0028 0031 0037 0029;;;17;N;;;;; +2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;ON;<compat> 0028 0031 0038 0029;;;18;N;;;;; +2486;PARENTHESIZED NUMBER NINETEEN;No;0;ON;<compat> 0028 0031 0039 0029;;;19;N;;;;; +2487;PARENTHESIZED NUMBER TWENTY;No;0;ON;<compat> 0028 0032 0030 0029;;;20;N;;;;; +2488;DIGIT ONE FULL STOP;No;0;EN;<compat> 0031 002E;;1;1;N;DIGIT ONE PERIOD;;;; +2489;DIGIT TWO FULL STOP;No;0;EN;<compat> 0032 002E;;2;2;N;DIGIT TWO PERIOD;;;; +248A;DIGIT THREE FULL STOP;No;0;EN;<compat> 0033 002E;;3;3;N;DIGIT THREE PERIOD;;;; +248B;DIGIT FOUR FULL STOP;No;0;EN;<compat> 0034 002E;;4;4;N;DIGIT FOUR PERIOD;;;; +248C;DIGIT FIVE FULL STOP;No;0;EN;<compat> 0035 002E;;5;5;N;DIGIT FIVE PERIOD;;;; +248D;DIGIT SIX FULL STOP;No;0;EN;<compat> 0036 002E;;6;6;N;DIGIT SIX PERIOD;;;; +248E;DIGIT SEVEN FULL STOP;No;0;EN;<compat> 0037 002E;;7;7;N;DIGIT SEVEN PERIOD;;;; +248F;DIGIT EIGHT FULL STOP;No;0;EN;<compat> 0038 002E;;8;8;N;DIGIT EIGHT PERIOD;;;; +2490;DIGIT NINE FULL STOP;No;0;EN;<compat> 0039 002E;;9;9;N;DIGIT NINE PERIOD;;;; +2491;NUMBER TEN FULL STOP;No;0;EN;<compat> 0031 0030 002E;;;10;N;NUMBER TEN PERIOD;;;; +2492;NUMBER ELEVEN FULL STOP;No;0;EN;<compat> 0031 0031 002E;;;11;N;NUMBER ELEVEN PERIOD;;;; +2493;NUMBER TWELVE FULL STOP;No;0;EN;<compat> 0031 0032 002E;;;12;N;NUMBER TWELVE PERIOD;;;; +2494;NUMBER THIRTEEN FULL STOP;No;0;EN;<compat> 0031 0033 002E;;;13;N;NUMBER THIRTEEN PERIOD;;;; +2495;NUMBER FOURTEEN FULL STOP;No;0;EN;<compat> 0031 0034 002E;;;14;N;NUMBER FOURTEEN PERIOD;;;; +2496;NUMBER FIFTEEN FULL STOP;No;0;EN;<compat> 0031 0035 002E;;;15;N;NUMBER FIFTEEN PERIOD;;;; +2497;NUMBER SIXTEEN FULL STOP;No;0;EN;<compat> 0031 0036 002E;;;16;N;NUMBER SIXTEEN PERIOD;;;; +2498;NUMBER SEVENTEEN FULL STOP;No;0;EN;<compat> 0031 0037 002E;;;17;N;NUMBER SEVENTEEN PERIOD;;;; +2499;NUMBER EIGHTEEN FULL STOP;No;0;EN;<compat> 0031 0038 002E;;;18;N;NUMBER EIGHTEEN PERIOD;;;; +249A;NUMBER NINETEEN FULL STOP;No;0;EN;<compat> 0031 0039 002E;;;19;N;NUMBER NINETEEN PERIOD;;;; +249B;NUMBER TWENTY FULL STOP;No;0;EN;<compat> 0032 0030 002E;;;20;N;NUMBER TWENTY PERIOD;;;; +249C;PARENTHESIZED LATIN SMALL LETTER A;So;0;L;<compat> 0028 0061 0029;;;;N;;;;; +249D;PARENTHESIZED LATIN SMALL LETTER B;So;0;L;<compat> 0028 0062 0029;;;;N;;;;; +249E;PARENTHESIZED LATIN SMALL LETTER C;So;0;L;<compat> 0028 0063 0029;;;;N;;;;; +249F;PARENTHESIZED LATIN SMALL LETTER D;So;0;L;<compat> 0028 0064 0029;;;;N;;;;; +24A0;PARENTHESIZED LATIN SMALL LETTER E;So;0;L;<compat> 0028 0065 0029;;;;N;;;;; +24A1;PARENTHESIZED LATIN SMALL LETTER F;So;0;L;<compat> 0028 0066 0029;;;;N;;;;; +24A2;PARENTHESIZED LATIN SMALL LETTER G;So;0;L;<compat> 0028 0067 0029;;;;N;;;;; +24A3;PARENTHESIZED LATIN SMALL LETTER H;So;0;L;<compat> 0028 0068 0029;;;;N;;;;; +24A4;PARENTHESIZED LATIN SMALL LETTER I;So;0;L;<compat> 0028 0069 0029;;;;N;;;;; +24A5;PARENTHESIZED LATIN SMALL LETTER J;So;0;L;<compat> 0028 006A 0029;;;;N;;;;; +24A6;PARENTHESIZED LATIN SMALL LETTER K;So;0;L;<compat> 0028 006B 0029;;;;N;;;;; +24A7;PARENTHESIZED LATIN SMALL LETTER L;So;0;L;<compat> 0028 006C 0029;;;;N;;;;; +24A8;PARENTHESIZED LATIN SMALL LETTER M;So;0;L;<compat> 0028 006D 0029;;;;N;;;;; +24A9;PARENTHESIZED LATIN SMALL LETTER N;So;0;L;<compat> 0028 006E 0029;;;;N;;;;; +24AA;PARENTHESIZED LATIN SMALL LETTER O;So;0;L;<compat> 0028 006F 0029;;;;N;;;;; +24AB;PARENTHESIZED LATIN SMALL LETTER P;So;0;L;<compat> 0028 0070 0029;;;;N;;;;; +24AC;PARENTHESIZED LATIN SMALL LETTER Q;So;0;L;<compat> 0028 0071 0029;;;;N;;;;; +24AD;PARENTHESIZED LATIN SMALL LETTER R;So;0;L;<compat> 0028 0072 0029;;;;N;;;;; +24AE;PARENTHESIZED LATIN SMALL LETTER S;So;0;L;<compat> 0028 0073 0029;;;;N;;;;; +24AF;PARENTHESIZED LATIN SMALL LETTER T;So;0;L;<compat> 0028 0074 0029;;;;N;;;;; +24B0;PARENTHESIZED LATIN SMALL LETTER U;So;0;L;<compat> 0028 0075 0029;;;;N;;;;; +24B1;PARENTHESIZED LATIN SMALL LETTER V;So;0;L;<compat> 0028 0076 0029;;;;N;;;;; +24B2;PARENTHESIZED LATIN SMALL LETTER W;So;0;L;<compat> 0028 0077 0029;;;;N;;;;; +24B3;PARENTHESIZED LATIN SMALL LETTER X;So;0;L;<compat> 0028 0078 0029;;;;N;;;;; +24B4;PARENTHESIZED LATIN SMALL LETTER Y;So;0;L;<compat> 0028 0079 0029;;;;N;;;;; +24B5;PARENTHESIZED LATIN SMALL LETTER Z;So;0;L;<compat> 0028 007A 0029;;;;N;;;;; +24B6;CIRCLED LATIN CAPITAL LETTER A;So;0;L;<circle> 0041;;;;N;;;;24D0; +24B7;CIRCLED LATIN CAPITAL LETTER B;So;0;L;<circle> 0042;;;;N;;;;24D1; +24B8;CIRCLED LATIN CAPITAL LETTER C;So;0;L;<circle> 0043;;;;N;;;;24D2; +24B9;CIRCLED LATIN CAPITAL LETTER D;So;0;L;<circle> 0044;;;;N;;;;24D3; +24BA;CIRCLED LATIN CAPITAL LETTER E;So;0;L;<circle> 0045;;;;N;;;;24D4; +24BB;CIRCLED LATIN CAPITAL LETTER F;So;0;L;<circle> 0046;;;;N;;;;24D5; +24BC;CIRCLED LATIN CAPITAL LETTER G;So;0;L;<circle> 0047;;;;N;;;;24D6; +24BD;CIRCLED LATIN CAPITAL LETTER H;So;0;L;<circle> 0048;;;;N;;;;24D7; +24BE;CIRCLED LATIN CAPITAL LETTER I;So;0;L;<circle> 0049;;;;N;;;;24D8; +24BF;CIRCLED LATIN CAPITAL LETTER J;So;0;L;<circle> 004A;;;;N;;;;24D9; +24C0;CIRCLED LATIN CAPITAL LETTER K;So;0;L;<circle> 004B;;;;N;;;;24DA; +24C1;CIRCLED LATIN CAPITAL LETTER L;So;0;L;<circle> 004C;;;;N;;;;24DB; +24C2;CIRCLED LATIN CAPITAL LETTER M;So;0;L;<circle> 004D;;;;N;;;;24DC; +24C3;CIRCLED LATIN CAPITAL LETTER N;So;0;L;<circle> 004E;;;;N;;;;24DD; +24C4;CIRCLED LATIN CAPITAL LETTER O;So;0;L;<circle> 004F;;;;N;;;;24DE; +24C5;CIRCLED LATIN CAPITAL LETTER P;So;0;L;<circle> 0050;;;;N;;;;24DF; +24C6;CIRCLED LATIN CAPITAL LETTER Q;So;0;L;<circle> 0051;;;;N;;;;24E0; +24C7;CIRCLED LATIN CAPITAL LETTER R;So;0;L;<circle> 0052;;;;N;;;;24E1; +24C8;CIRCLED LATIN CAPITAL LETTER S;So;0;L;<circle> 0053;;;;N;;;;24E2; +24C9;CIRCLED LATIN CAPITAL LETTER T;So;0;L;<circle> 0054;;;;N;;;;24E3; +24CA;CIRCLED LATIN CAPITAL LETTER U;So;0;L;<circle> 0055;;;;N;;;;24E4; +24CB;CIRCLED LATIN CAPITAL LETTER V;So;0;L;<circle> 0056;;;;N;;;;24E5; +24CC;CIRCLED LATIN CAPITAL LETTER W;So;0;L;<circle> 0057;;;;N;;;;24E6; +24CD;CIRCLED LATIN CAPITAL LETTER X;So;0;L;<circle> 0058;;;;N;;;;24E7; +24CE;CIRCLED LATIN CAPITAL LETTER Y;So;0;L;<circle> 0059;;;;N;;;;24E8; +24CF;CIRCLED LATIN CAPITAL LETTER Z;So;0;L;<circle> 005A;;;;N;;;;24E9; +24D0;CIRCLED LATIN SMALL LETTER A;So;0;L;<circle> 0061;;;;N;;;24B6;;24B6 +24D1;CIRCLED LATIN SMALL LETTER B;So;0;L;<circle> 0062;;;;N;;;24B7;;24B7 +24D2;CIRCLED LATIN SMALL LETTER C;So;0;L;<circle> 0063;;;;N;;;24B8;;24B8 +24D3;CIRCLED LATIN SMALL LETTER D;So;0;L;<circle> 0064;;;;N;;;24B9;;24B9 +24D4;CIRCLED LATIN SMALL LETTER E;So;0;L;<circle> 0065;;;;N;;;24BA;;24BA +24D5;CIRCLED LATIN SMALL LETTER F;So;0;L;<circle> 0066;;;;N;;;24BB;;24BB +24D6;CIRCLED LATIN SMALL LETTER G;So;0;L;<circle> 0067;;;;N;;;24BC;;24BC +24D7;CIRCLED LATIN SMALL LETTER H;So;0;L;<circle> 0068;;;;N;;;24BD;;24BD +24D8;CIRCLED LATIN SMALL LETTER I;So;0;L;<circle> 0069;;;;N;;;24BE;;24BE +24D9;CIRCLED LATIN SMALL LETTER J;So;0;L;<circle> 006A;;;;N;;;24BF;;24BF +24DA;CIRCLED LATIN SMALL LETTER K;So;0;L;<circle> 006B;;;;N;;;24C0;;24C0 +24DB;CIRCLED LATIN SMALL LETTER L;So;0;L;<circle> 006C;;;;N;;;24C1;;24C1 +24DC;CIRCLED LATIN SMALL LETTER M;So;0;L;<circle> 006D;;;;N;;;24C2;;24C2 +24DD;CIRCLED LATIN SMALL LETTER N;So;0;L;<circle> 006E;;;;N;;;24C3;;24C3 +24DE;CIRCLED LATIN SMALL LETTER O;So;0;L;<circle> 006F;;;;N;;;24C4;;24C4 +24DF;CIRCLED LATIN SMALL LETTER P;So;0;L;<circle> 0070;;;;N;;;24C5;;24C5 +24E0;CIRCLED LATIN SMALL LETTER Q;So;0;L;<circle> 0071;;;;N;;;24C6;;24C6 +24E1;CIRCLED LATIN SMALL LETTER R;So;0;L;<circle> 0072;;;;N;;;24C7;;24C7 +24E2;CIRCLED LATIN SMALL LETTER S;So;0;L;<circle> 0073;;;;N;;;24C8;;24C8 +24E3;CIRCLED LATIN SMALL LETTER T;So;0;L;<circle> 0074;;;;N;;;24C9;;24C9 +24E4;CIRCLED LATIN SMALL LETTER U;So;0;L;<circle> 0075;;;;N;;;24CA;;24CA +24E5;CIRCLED LATIN SMALL LETTER V;So;0;L;<circle> 0076;;;;N;;;24CB;;24CB +24E6;CIRCLED LATIN SMALL LETTER W;So;0;L;<circle> 0077;;;;N;;;24CC;;24CC +24E7;CIRCLED LATIN SMALL LETTER X;So;0;L;<circle> 0078;;;;N;;;24CD;;24CD +24E8;CIRCLED LATIN SMALL LETTER Y;So;0;L;<circle> 0079;;;;N;;;24CE;;24CE +24E9;CIRCLED LATIN SMALL LETTER Z;So;0;L;<circle> 007A;;;;N;;;24CF;;24CF +24EA;CIRCLED DIGIT ZERO;No;0;ON;<circle> 0030;;0;0;N;;;;; +24EB;NEGATIVE CIRCLED NUMBER ELEVEN;No;0;ON;;;;11;N;;;;; +24EC;NEGATIVE CIRCLED NUMBER TWELVE;No;0;ON;;;;12;N;;;;; +24ED;NEGATIVE CIRCLED NUMBER THIRTEEN;No;0;ON;;;;13;N;;;;; +24EE;NEGATIVE CIRCLED NUMBER FOURTEEN;No;0;ON;;;;14;N;;;;; +24EF;NEGATIVE CIRCLED NUMBER FIFTEEN;No;0;ON;;;;15;N;;;;; +24F0;NEGATIVE CIRCLED NUMBER SIXTEEN;No;0;ON;;;;16;N;;;;; +24F1;NEGATIVE CIRCLED NUMBER SEVENTEEN;No;0;ON;;;;17;N;;;;; +24F2;NEGATIVE CIRCLED NUMBER EIGHTEEN;No;0;ON;;;;18;N;;;;; +24F3;NEGATIVE CIRCLED NUMBER NINETEEN;No;0;ON;;;;19;N;;;;; +24F4;NEGATIVE CIRCLED NUMBER TWENTY;No;0;ON;;;;20;N;;;;; +24F5;DOUBLE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;;;;; +24F6;DOUBLE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;;;;; +24F7;DOUBLE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;;;;; +24F8;DOUBLE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;;;;; +24F9;DOUBLE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;;;;; +24FA;DOUBLE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;;;;; +24FB;DOUBLE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;;;;; +24FC;DOUBLE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;;;;; +24FD;DOUBLE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;;;;; +24FE;DOUBLE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;;;;; +24FF;NEGATIVE CIRCLED DIGIT ZERO;No;0;ON;;;0;0;N;;;;; +2500;BOX DRAWINGS LIGHT HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT HORIZONTAL;;;; +2501;BOX DRAWINGS HEAVY HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY HORIZONTAL;;;; +2502;BOX DRAWINGS LIGHT VERTICAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL;;;; +2503;BOX DRAWINGS HEAVY VERTICAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL;;;; +2504;BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH HORIZONTAL;;;; +2505;BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH HORIZONTAL;;;; +2506;BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH VERTICAL;;;; +2507;BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH VERTICAL;;;; +2508;BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH HORIZONTAL;;;; +2509;BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH HORIZONTAL;;;; +250A;BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH VERTICAL;;;; +250B;BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH VERTICAL;;;; +250C;BOX DRAWINGS LIGHT DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND RIGHT;;;; +250D;BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT HEAVY;;;; +250E;BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT LIGHT;;;; +250F;BOX DRAWINGS HEAVY DOWN AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND RIGHT;;;; +2510;BOX DRAWINGS LIGHT DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND LEFT;;;; +2511;BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT HEAVY;;;; +2512;BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT LIGHT;;;; +2513;BOX DRAWINGS HEAVY DOWN AND LEFT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND LEFT;;;; +2514;BOX DRAWINGS LIGHT UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT UP AND RIGHT;;;; +2515;BOX DRAWINGS UP LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT HEAVY;;;; +2516;BOX DRAWINGS UP HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT LIGHT;;;; +2517;BOX DRAWINGS HEAVY UP AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY UP AND RIGHT;;;; +2518;BOX DRAWINGS LIGHT UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT UP AND LEFT;;;; +2519;BOX DRAWINGS UP LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT HEAVY;;;; +251A;BOX DRAWINGS UP HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT LIGHT;;;; +251B;BOX DRAWINGS HEAVY UP AND LEFT;So;0;ON;;;;;N;FORMS HEAVY UP AND LEFT;;;; +251C;BOX DRAWINGS LIGHT VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND RIGHT;;;; +251D;BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND RIGHT HEAVY;;;; +251E;BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT DOWN LIGHT;;;; +251F;BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT UP LIGHT;;;; +2520;BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND RIGHT LIGHT;;;; +2521;BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT UP HEAVY;;;; +2522;BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT DOWN HEAVY;;;; +2523;BOX DRAWINGS HEAVY VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND RIGHT;;;; +2524;BOX DRAWINGS LIGHT VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND LEFT;;;; +2525;BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND LEFT HEAVY;;;; +2526;BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT DOWN LIGHT;;;; +2527;BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT UP LIGHT;;;; +2528;BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND LEFT LIGHT;;;; +2529;BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT UP HEAVY;;;; +252A;BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT DOWN HEAVY;;;; +252B;BOX DRAWINGS HEAVY VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND LEFT;;;; +252C;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOWN AND HORIZONTAL;;;; +252D;BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT DOWN LIGHT;;;; +252E;BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT DOWN LIGHT;;;; +252F;BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND HORIZONTAL HEAVY;;;; +2530;BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND HORIZONTAL LIGHT;;;; +2531;BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT DOWN HEAVY;;;; +2532;BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT DOWN HEAVY;;;; +2533;BOX DRAWINGS HEAVY DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOWN AND HORIZONTAL;;;; +2534;BOX DRAWINGS LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT UP AND HORIZONTAL;;;; +2535;BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT UP LIGHT;;;; +2536;BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT UP LIGHT;;;; +2537;BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND HORIZONTAL HEAVY;;;; +2538;BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND HORIZONTAL LIGHT;;;; +2539;BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT UP HEAVY;;;; +253A;BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT UP HEAVY;;;; +253B;BOX DRAWINGS HEAVY UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY UP AND HORIZONTAL;;;; +253C;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND HORIZONTAL;;;; +253D;BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT;;;; +253E;BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT;;;; +253F;BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY;;;; +2540;BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT;;;; +2541;BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT;;;; +2542;BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT;;;; +2543;BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT;;;; +2544;BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT;;;; +2545;BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT;;;; +2546;BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT;;;; +2547;BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY;;;; +2548;BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY;;;; +2549;BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY;;;; +254A;BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY;;;; +254B;BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND HORIZONTAL;;;; +254C;BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH HORIZONTAL;;;; +254D;BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH HORIZONTAL;;;; +254E;BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH VERTICAL;;;; +254F;BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH VERTICAL;;;; +2550;BOX DRAWINGS DOUBLE HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE HORIZONTAL;;;; +2551;BOX DRAWINGS DOUBLE VERTICAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL;;;; +2552;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND RIGHT DOUBLE;;;; +2553;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND RIGHT SINGLE;;;; +2554;BOX DRAWINGS DOUBLE DOWN AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND RIGHT;;;; +2555;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND LEFT DOUBLE;;;; +2556;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND LEFT SINGLE;;;; +2557;BOX DRAWINGS DOUBLE DOWN AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND LEFT;;;; +2558;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND RIGHT DOUBLE;;;; +2559;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND RIGHT SINGLE;;;; +255A;BOX DRAWINGS DOUBLE UP AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE UP AND RIGHT;;;; +255B;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND LEFT DOUBLE;;;; +255C;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND LEFT SINGLE;;;; +255D;BOX DRAWINGS DOUBLE UP AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE UP AND LEFT;;;; +255E;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND RIGHT DOUBLE;;;; +255F;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND RIGHT SINGLE;;;; +2560;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND RIGHT;;;; +2561;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND LEFT DOUBLE;;;; +2562;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND LEFT SINGLE;;;; +2563;BOX DRAWINGS DOUBLE VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND LEFT;;;; +2564;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND HORIZONTAL DOUBLE;;;; +2565;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND HORIZONTAL SINGLE;;;; +2566;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND HORIZONTAL;;;; +2567;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND HORIZONTAL DOUBLE;;;; +2568;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND HORIZONTAL SINGLE;;;; +2569;BOX DRAWINGS DOUBLE UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE UP AND HORIZONTAL;;;; +256A;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE;;;; +256B;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE;;;; +256C;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND HORIZONTAL;;;; +256D;BOX DRAWINGS LIGHT ARC DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND RIGHT;;;; +256E;BOX DRAWINGS LIGHT ARC DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND LEFT;;;; +256F;BOX DRAWINGS LIGHT ARC UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND LEFT;;;; +2570;BOX DRAWINGS LIGHT ARC UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND RIGHT;;;; +2571;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;;;; +2572;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;;;; +2573;BOX DRAWINGS LIGHT DIAGONAL CROSS;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL CROSS;;;; +2574;BOX DRAWINGS LIGHT LEFT;So;0;ON;;;;;N;FORMS LIGHT LEFT;;;; +2575;BOX DRAWINGS LIGHT UP;So;0;ON;;;;;N;FORMS LIGHT UP;;;; +2576;BOX DRAWINGS LIGHT RIGHT;So;0;ON;;;;;N;FORMS LIGHT RIGHT;;;; +2577;BOX DRAWINGS LIGHT DOWN;So;0;ON;;;;;N;FORMS LIGHT DOWN;;;; +2578;BOX DRAWINGS HEAVY LEFT;So;0;ON;;;;;N;FORMS HEAVY LEFT;;;; +2579;BOX DRAWINGS HEAVY UP;So;0;ON;;;;;N;FORMS HEAVY UP;;;; +257A;BOX DRAWINGS HEAVY RIGHT;So;0;ON;;;;;N;FORMS HEAVY RIGHT;;;; +257B;BOX DRAWINGS HEAVY DOWN;So;0;ON;;;;;N;FORMS HEAVY DOWN;;;; +257C;BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT;So;0;ON;;;;;N;FORMS LIGHT LEFT AND HEAVY RIGHT;;;; +257D;BOX DRAWINGS LIGHT UP AND HEAVY DOWN;So;0;ON;;;;;N;FORMS LIGHT UP AND HEAVY DOWN;;;; +257E;BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT;So;0;ON;;;;;N;FORMS HEAVY LEFT AND LIGHT RIGHT;;;; +257F;BOX DRAWINGS HEAVY UP AND LIGHT DOWN;So;0;ON;;;;;N;FORMS HEAVY UP AND LIGHT DOWN;;;; +2580;UPPER HALF BLOCK;So;0;ON;;;;;N;;;;; +2581;LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +2582;LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +2583;LOWER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +2584;LOWER HALF BLOCK;So;0;ON;;;;;N;;;;; +2585;LOWER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +2586;LOWER THREE QUARTERS BLOCK;So;0;ON;;;;;N;LOWER THREE QUARTER BLOCK;;;; +2587;LOWER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +2588;FULL BLOCK;So;0;ON;;;;;N;;;;; +2589;LEFT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +258A;LEFT THREE QUARTERS BLOCK;So;0;ON;;;;;N;LEFT THREE QUARTER BLOCK;;;; +258B;LEFT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +258C;LEFT HALF BLOCK;So;0;ON;;;;;N;;;;; +258D;LEFT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +258E;LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +258F;LEFT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +2590;RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;; +2591;LIGHT SHADE;So;0;ON;;;;;N;;;;; +2592;MEDIUM SHADE;So;0;ON;;;;;N;;;;; +2593;DARK SHADE;So;0;ON;;;;;N;;;;; +2594;UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +2595;RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +2596;QUADRANT LOWER LEFT;So;0;ON;;;;;N;;;;; +2597;QUADRANT LOWER RIGHT;So;0;ON;;;;;N;;;;; +2598;QUADRANT UPPER LEFT;So;0;ON;;;;;N;;;;; +2599;QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +259A;QUADRANT UPPER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +259B;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; +259C;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +259D;QUADRANT UPPER RIGHT;So;0;ON;;;;;N;;;;; +259E;QUADRANT UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; +259F;QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +25A0;BLACK SQUARE;So;0;ON;;;;;N;;;;; +25A1;WHITE SQUARE;So;0;ON;;;;;N;;;;; +25A2;WHITE SQUARE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; +25A3;WHITE SQUARE CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; +25A4;SQUARE WITH HORIZONTAL FILL;So;0;ON;;;;;N;;;;; +25A5;SQUARE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; +25A6;SQUARE WITH ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; +25A7;SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;; +25A8;SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;; +25A9;SQUARE WITH DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; +25AA;BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; +25AB;WHITE SMALL SQUARE;So;0;ON;;;;;N;;;;; +25AC;BLACK RECTANGLE;So;0;ON;;;;;N;;;;; +25AD;WHITE RECTANGLE;So;0;ON;;;;;N;;;;; +25AE;BLACK VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; +25AF;WHITE VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; +25B0;BLACK PARALLELOGRAM;So;0;ON;;;;;N;;;;; +25B1;WHITE PARALLELOGRAM;So;0;ON;;;;;N;;;;; +25B2;BLACK UP-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING TRIANGLE;;;; +25B3;WHITE UP-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE;;;; +25B4;BLACK UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING SMALL TRIANGLE;;;; +25B5;WHITE UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING SMALL TRIANGLE;;;; +25B6;BLACK RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING TRIANGLE;;;; +25B7;WHITE RIGHT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE RIGHT POINTING TRIANGLE;;;; +25B8;BLACK RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING SMALL TRIANGLE;;;; +25B9;WHITE RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE RIGHT POINTING SMALL TRIANGLE;;;; +25BA;BLACK RIGHT-POINTING POINTER;So;0;ON;;;;;N;BLACK RIGHT POINTING POINTER;;;; +25BB;WHITE RIGHT-POINTING POINTER;So;0;ON;;;;;N;WHITE RIGHT POINTING POINTER;;;; +25BC;BLACK DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING TRIANGLE;;;; +25BD;WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING TRIANGLE;;;; +25BE;BLACK DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING SMALL TRIANGLE;;;; +25BF;WHITE DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING SMALL TRIANGLE;;;; +25C0;BLACK LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING TRIANGLE;;;; +25C1;WHITE LEFT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE LEFT POINTING TRIANGLE;;;; +25C2;BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING SMALL TRIANGLE;;;; +25C3;WHITE LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE LEFT POINTING SMALL TRIANGLE;;;; +25C4;BLACK LEFT-POINTING POINTER;So;0;ON;;;;;N;BLACK LEFT POINTING POINTER;;;; +25C5;WHITE LEFT-POINTING POINTER;So;0;ON;;;;;N;WHITE LEFT POINTING POINTER;;;; +25C6;BLACK DIAMOND;So;0;ON;;;;;N;;;;; +25C7;WHITE DIAMOND;So;0;ON;;;;;N;;;;; +25C8;WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; +25C9;FISHEYE;So;0;ON;;;;;N;;;;; +25CA;LOZENGE;So;0;ON;;;;;N;;;;; +25CB;WHITE CIRCLE;So;0;ON;;;;;N;;;;; +25CC;DOTTED CIRCLE;So;0;ON;;;;;N;;;;; +25CD;CIRCLE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; +25CE;BULLSEYE;So;0;ON;;;;;N;;;;; +25CF;BLACK CIRCLE;So;0;ON;;;;;N;;;;; +25D0;CIRCLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; +25D1;CIRCLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; +25D2;CIRCLE WITH LOWER HALF BLACK;So;0;ON;;;;;N;;;;; +25D3;CIRCLE WITH UPPER HALF BLACK;So;0;ON;;;;;N;;;;; +25D4;CIRCLE WITH UPPER RIGHT QUADRANT BLACK;So;0;ON;;;;;N;;;;; +25D5;CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK;So;0;ON;;;;;N;;;;; +25D6;LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +25D7;RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +25D8;INVERSE BULLET;So;0;ON;;;;;N;;;;; +25D9;INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; +25DA;UPPER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; +25DB;LOWER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; +25DC;UPPER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; +25DD;UPPER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; +25DE;LOWER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; +25DF;LOWER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; +25E0;UPPER HALF CIRCLE;So;0;ON;;;;;N;;;;; +25E1;LOWER HALF CIRCLE;So;0;ON;;;;;N;;;;; +25E2;BLACK LOWER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +25E3;BLACK LOWER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; +25E4;BLACK UPPER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; +25E5;BLACK UPPER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +25E6;WHITE BULLET;So;0;ON;;;;;N;;;;; +25E7;SQUARE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; +25E8;SQUARE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; +25E9;SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; +25EA;SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; +25EB;WHITE SQUARE WITH VERTICAL BISECTING LINE;So;0;ON;;;;;N;;;;; +25EC;WHITE UP-POINTING TRIANGLE WITH DOT;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE WITH DOT;;;; +25ED;UP-POINTING TRIANGLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH LEFT HALF BLACK;;;; +25EE;UP-POINTING TRIANGLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH RIGHT HALF BLACK;;;; +25EF;LARGE CIRCLE;So;0;ON;;;;;N;;;;; +25F0;WHITE SQUARE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; +25F1;WHITE SQUARE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; +25F2;WHITE SQUARE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; +25F3;WHITE SQUARE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; +25F4;WHITE CIRCLE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; +25F5;WHITE CIRCLE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; +25F6;WHITE CIRCLE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; +25F7;WHITE CIRCLE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; +25F8;UPPER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; +25F9;UPPER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; +25FA;LOWER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; +25FB;WHITE MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; +25FC;BLACK MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; +25FD;WHITE MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; +25FE;BLACK MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; +25FF;LOWER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; +2600;BLACK SUN WITH RAYS;So;0;ON;;;;;N;;;;; +2601;CLOUD;So;0;ON;;;;;N;;;;; +2602;UMBRELLA;So;0;ON;;;;;N;;;;; +2603;SNOWMAN;So;0;ON;;;;;N;;;;; +2604;COMET;So;0;ON;;;;;N;;;;; +2605;BLACK STAR;So;0;ON;;;;;N;;;;; +2606;WHITE STAR;So;0;ON;;;;;N;;;;; +2607;LIGHTNING;So;0;ON;;;;;N;;;;; +2608;THUNDERSTORM;So;0;ON;;;;;N;;;;; +2609;SUN;So;0;ON;;;;;N;;;;; +260A;ASCENDING NODE;So;0;ON;;;;;N;;;;; +260B;DESCENDING NODE;So;0;ON;;;;;N;;;;; +260C;CONJUNCTION;So;0;ON;;;;;N;;;;; +260D;OPPOSITION;So;0;ON;;;;;N;;;;; +260E;BLACK TELEPHONE;So;0;ON;;;;;N;;;;; +260F;WHITE TELEPHONE;So;0;ON;;;;;N;;;;; +2610;BALLOT BOX;So;0;ON;;;;;N;;;;; +2611;BALLOT BOX WITH CHECK;So;0;ON;;;;;N;;;;; +2612;BALLOT BOX WITH X;So;0;ON;;;;;N;;;;; +2613;SALTIRE;So;0;ON;;;;;N;;;;; +2614;UMBRELLA WITH RAIN DROPS;So;0;ON;;;;;N;;;;; +2615;HOT BEVERAGE;So;0;ON;;;;;N;;;;; +2616;WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; +2617;BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; +2618;SHAMROCK;So;0;ON;;;;;N;;;;; +2619;REVERSED ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; +261A;BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; +261B;BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +261C;WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; +261D;WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; +261E;WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +261F;WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; +2620;SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; +2621;CAUTION SIGN;So;0;ON;;;;;N;;;;; +2622;RADIOACTIVE SIGN;So;0;ON;;;;;N;;;;; +2623;BIOHAZARD SIGN;So;0;ON;;;;;N;;;;; +2624;CADUCEUS;So;0;ON;;;;;N;;;;; +2625;ANKH;So;0;ON;;;;;N;;;;; +2626;ORTHODOX CROSS;So;0;ON;;;;;N;;;;; +2627;CHI RHO;So;0;ON;;;;;N;;;;; +2628;CROSS OF LORRAINE;So;0;ON;;;;;N;;;;; +2629;CROSS OF JERUSALEM;So;0;ON;;;;;N;;;;; +262A;STAR AND CRESCENT;So;0;ON;;;;;N;;;;; +262B;FARSI SYMBOL;So;0;ON;;;;;N;SYMBOL OF IRAN;;;; +262C;ADI SHAKTI;So;0;ON;;;;;N;;;;; +262D;HAMMER AND SICKLE;So;0;ON;;;;;N;;;;; +262E;PEACE SYMBOL;So;0;ON;;;;;N;;;;; +262F;YIN YANG;So;0;ON;;;;;N;;;;; +2630;TRIGRAM FOR HEAVEN;So;0;ON;;;;;N;;;;; +2631;TRIGRAM FOR LAKE;So;0;ON;;;;;N;;;;; +2632;TRIGRAM FOR FIRE;So;0;ON;;;;;N;;;;; +2633;TRIGRAM FOR THUNDER;So;0;ON;;;;;N;;;;; +2634;TRIGRAM FOR WIND;So;0;ON;;;;;N;;;;; +2635;TRIGRAM FOR WATER;So;0;ON;;;;;N;;;;; +2636;TRIGRAM FOR MOUNTAIN;So;0;ON;;;;;N;;;;; +2637;TRIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; +2638;WHEEL OF DHARMA;So;0;ON;;;;;N;;;;; +2639;WHITE FROWNING FACE;So;0;ON;;;;;N;;;;; +263A;WHITE SMILING FACE;So;0;ON;;;;;N;;;;; +263B;BLACK SMILING FACE;So;0;ON;;;;;N;;;;; +263C;WHITE SUN WITH RAYS;So;0;ON;;;;;N;;;;; +263D;FIRST QUARTER MOON;So;0;ON;;;;;N;;;;; +263E;LAST QUARTER MOON;So;0;ON;;;;;N;;;;; +263F;MERCURY;So;0;ON;;;;;N;;;;; +2640;FEMALE SIGN;So;0;ON;;;;;N;;;;; +2641;EARTH;So;0;ON;;;;;N;;;;; +2642;MALE SIGN;So;0;ON;;;;;N;;;;; +2643;JUPITER;So;0;ON;;;;;N;;;;; +2644;SATURN;So;0;ON;;;;;N;;;;; +2645;URANUS;So;0;ON;;;;;N;;;;; +2646;NEPTUNE;So;0;ON;;;;;N;;;;; +2647;PLUTO;So;0;ON;;;;;N;;;;; +2648;ARIES;So;0;ON;;;;;N;;;;; +2649;TAURUS;So;0;ON;;;;;N;;;;; +264A;GEMINI;So;0;ON;;;;;N;;;;; +264B;CANCER;So;0;ON;;;;;N;;;;; +264C;LEO;So;0;ON;;;;;N;;;;; +264D;VIRGO;So;0;ON;;;;;N;;;;; +264E;LIBRA;So;0;ON;;;;;N;;;;; +264F;SCORPIUS;So;0;ON;;;;;N;;;;; +2650;SAGITTARIUS;So;0;ON;;;;;N;;;;; +2651;CAPRICORN;So;0;ON;;;;;N;;;;; +2652;AQUARIUS;So;0;ON;;;;;N;;;;; +2653;PISCES;So;0;ON;;;;;N;;;;; +2654;WHITE CHESS KING;So;0;ON;;;;;N;;;;; +2655;WHITE CHESS QUEEN;So;0;ON;;;;;N;;;;; +2656;WHITE CHESS ROOK;So;0;ON;;;;;N;;;;; +2657;WHITE CHESS BISHOP;So;0;ON;;;;;N;;;;; +2658;WHITE CHESS KNIGHT;So;0;ON;;;;;N;;;;; +2659;WHITE CHESS PAWN;So;0;ON;;;;;N;;;;; +265A;BLACK CHESS KING;So;0;ON;;;;;N;;;;; +265B;BLACK CHESS QUEEN;So;0;ON;;;;;N;;;;; +265C;BLACK CHESS ROOK;So;0;ON;;;;;N;;;;; +265D;BLACK CHESS BISHOP;So;0;ON;;;;;N;;;;; +265E;BLACK CHESS KNIGHT;So;0;ON;;;;;N;;;;; +265F;BLACK CHESS PAWN;So;0;ON;;;;;N;;;;; +2660;BLACK SPADE SUIT;So;0;ON;;;;;N;;;;; +2661;WHITE HEART SUIT;So;0;ON;;;;;N;;;;; +2662;WHITE DIAMOND SUIT;So;0;ON;;;;;N;;;;; +2663;BLACK CLUB SUIT;So;0;ON;;;;;N;;;;; +2664;WHITE SPADE SUIT;So;0;ON;;;;;N;;;;; +2665;BLACK HEART SUIT;So;0;ON;;;;;N;;;;; +2666;BLACK DIAMOND SUIT;So;0;ON;;;;;N;;;;; +2667;WHITE CLUB SUIT;So;0;ON;;;;;N;;;;; +2668;HOT SPRINGS;So;0;ON;;;;;N;;;;; +2669;QUARTER NOTE;So;0;ON;;;;;N;;;;; +266A;EIGHTH NOTE;So;0;ON;;;;;N;;;;; +266B;BEAMED EIGHTH NOTES;So;0;ON;;;;;N;BARRED EIGHTH NOTES;;;; +266C;BEAMED SIXTEENTH NOTES;So;0;ON;;;;;N;BARRED SIXTEENTH NOTES;;;; +266D;MUSIC FLAT SIGN;So;0;ON;;;;;N;FLAT;;;; +266E;MUSIC NATURAL SIGN;So;0;ON;;;;;N;NATURAL;;;; +266F;MUSIC SHARP SIGN;Sm;0;ON;;;;;N;SHARP;;;; +2670;WEST SYRIAC CROSS;So;0;ON;;;;;N;;;;; +2671;EAST SYRIAC CROSS;So;0;ON;;;;;N;;;;; +2672;UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; +2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;;;; +2674;RECYCLING SYMBOL FOR TYPE-2 PLASTICS;So;0;ON;;;;;N;;;;; +2675;RECYCLING SYMBOL FOR TYPE-3 PLASTICS;So;0;ON;;;;;N;;;;; +2676;RECYCLING SYMBOL FOR TYPE-4 PLASTICS;So;0;ON;;;;;N;;;;; +2677;RECYCLING SYMBOL FOR TYPE-5 PLASTICS;So;0;ON;;;;;N;;;;; +2678;RECYCLING SYMBOL FOR TYPE-6 PLASTICS;So;0;ON;;;;;N;;;;; +2679;RECYCLING SYMBOL FOR TYPE-7 PLASTICS;So;0;ON;;;;;N;;;;; +267A;RECYCLING SYMBOL FOR GENERIC MATERIALS;So;0;ON;;;;;N;;;;; +267B;BLACK UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; +267C;RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; +267D;PARTIALLY-RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; +267E;PERMANENT PAPER SIGN;So;0;ON;;;;;N;;;;; +267F;WHEELCHAIR SYMBOL;So;0;ON;;;;;N;;;;; +2680;DIE FACE-1;So;0;ON;;;;;N;;;;; +2681;DIE FACE-2;So;0;ON;;;;;N;;;;; +2682;DIE FACE-3;So;0;ON;;;;;N;;;;; +2683;DIE FACE-4;So;0;ON;;;;;N;;;;; +2684;DIE FACE-5;So;0;ON;;;;;N;;;;; +2685;DIE FACE-6;So;0;ON;;;;;N;;;;; +2686;WHITE CIRCLE WITH DOT RIGHT;So;0;ON;;;;;N;;;;; +2687;WHITE CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +2688;BLACK CIRCLE WITH WHITE DOT RIGHT;So;0;ON;;;;;N;;;;; +2689;BLACK CIRCLE WITH TWO WHITE DOTS;So;0;ON;;;;;N;;;;; +268A;MONOGRAM FOR YANG;So;0;ON;;;;;N;;;;; +268B;MONOGRAM FOR YIN;So;0;ON;;;;;N;;;;; +268C;DIGRAM FOR GREATER YANG;So;0;ON;;;;;N;;;;; +268D;DIGRAM FOR LESSER YIN;So;0;ON;;;;;N;;;;; +268E;DIGRAM FOR LESSER YANG;So;0;ON;;;;;N;;;;; +268F;DIGRAM FOR GREATER YIN;So;0;ON;;;;;N;;;;; +2690;WHITE FLAG;So;0;ON;;;;;N;;;;; +2691;BLACK FLAG;So;0;ON;;;;;N;;;;; +2692;HAMMER AND PICK;So;0;ON;;;;;N;;;;; +2693;ANCHOR;So;0;ON;;;;;N;;;;; +2694;CROSSED SWORDS;So;0;ON;;;;;N;;;;; +2695;STAFF OF AESCULAPIUS;So;0;ON;;;;;N;;;;; +2696;SCALES;So;0;ON;;;;;N;;;;; +2697;ALEMBIC;So;0;ON;;;;;N;;;;; +2698;FLOWER;So;0;ON;;;;;N;;;;; +2699;GEAR;So;0;ON;;;;;N;;;;; +269A;STAFF OF HERMES;So;0;ON;;;;;N;;;;; +269B;ATOM SYMBOL;So;0;ON;;;;;N;;;;; +269C;FLEUR-DE-LIS;So;0;ON;;;;;N;;;;; +269D;OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; +269E;THREE LINES CONVERGING RIGHT;So;0;ON;;;;;N;;;;; +269F;THREE LINES CONVERGING LEFT;So;0;ON;;;;;N;;;;; +26A0;WARNING SIGN;So;0;ON;;;;;N;;;;; +26A1;HIGH VOLTAGE SIGN;So;0;ON;;;;;N;;;;; +26A2;DOUBLED FEMALE SIGN;So;0;ON;;;;;N;;;;; +26A3;DOUBLED MALE SIGN;So;0;ON;;;;;N;;;;; +26A4;INTERLOCKED FEMALE AND MALE SIGN;So;0;ON;;;;;N;;;;; +26A5;MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; +26A6;MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; +26A7;MALE WITH STROKE AND MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; +26A8;VERTICAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; +26A9;HORIZONTAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; +26AA;MEDIUM WHITE CIRCLE;So;0;ON;;;;;N;;;;; +26AB;MEDIUM BLACK CIRCLE;So;0;ON;;;;;N;;;;; +26AC;MEDIUM SMALL WHITE CIRCLE;So;0;L;;;;;N;;;;; +26AD;MARRIAGE SYMBOL;So;0;ON;;;;;N;;;;; +26AE;DIVORCE SYMBOL;So;0;ON;;;;;N;;;;; +26AF;UNMARRIED PARTNERSHIP SYMBOL;So;0;ON;;;;;N;;;;; +26B0;COFFIN;So;0;ON;;;;;N;;;;; +26B1;FUNERAL URN;So;0;ON;;;;;N;;;;; +26B2;NEUTER;So;0;ON;;;;;N;;;;; +26B3;CERES;So;0;ON;;;;;N;;;;; +26B4;PALLAS;So;0;ON;;;;;N;;;;; +26B5;JUNO;So;0;ON;;;;;N;;;;; +26B6;VESTA;So;0;ON;;;;;N;;;;; +26B7;CHIRON;So;0;ON;;;;;N;;;;; +26B8;BLACK MOON LILITH;So;0;ON;;;;;N;;;;; +26B9;SEXTILE;So;0;ON;;;;;N;;;;; +26BA;SEMISEXTILE;So;0;ON;;;;;N;;;;; +26BB;QUINCUNX;So;0;ON;;;;;N;;;;; +26BC;SESQUIQUADRATE;So;0;ON;;;;;N;;;;; +26BD;SOCCER BALL;So;0;ON;;;;;N;;;;; +26BE;BASEBALL;So;0;ON;;;;;N;;;;; +26BF;SQUARED KEY;So;0;ON;;;;;N;;;;; +26C0;WHITE DRAUGHTS MAN;So;0;ON;;;;;N;;;;; +26C1;WHITE DRAUGHTS KING;So;0;ON;;;;;N;;;;; +26C2;BLACK DRAUGHTS MAN;So;0;ON;;;;;N;;;;; +26C3;BLACK DRAUGHTS KING;So;0;ON;;;;;N;;;;; +26C4;SNOWMAN WITHOUT SNOW;So;0;ON;;;;;N;;;;; +26C5;SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; +26C6;RAIN;So;0;ON;;;;;N;;;;; +26C7;BLACK SNOWMAN;So;0;ON;;;;;N;;;;; +26C8;THUNDER CLOUD AND RAIN;So;0;ON;;;;;N;;;;; +26C9;TURNED WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; +26CA;TURNED BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; +26CB;WHITE DIAMOND IN SQUARE;So;0;ON;;;;;N;;;;; +26CC;CROSSING LANES;So;0;ON;;;;;N;;;;; +26CD;DISABLED CAR;So;0;ON;;;;;N;;;;; +26CE;OPHIUCHUS;So;0;ON;;;;;N;;;;; +26CF;PICK;So;0;ON;;;;;N;;;;; +26D0;CAR SLIDING;So;0;ON;;;;;N;;;;; +26D1;HELMET WITH WHITE CROSS;So;0;ON;;;;;N;;;;; +26D2;CIRCLED CROSSING LANES;So;0;ON;;;;;N;;;;; +26D3;CHAINS;So;0;ON;;;;;N;;;;; +26D4;NO ENTRY;So;0;ON;;;;;N;;;;; +26D5;ALTERNATE ONE-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; +26D6;BLACK TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; +26D7;WHITE TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; +26D8;BLACK LEFT LANE MERGE;So;0;ON;;;;;N;;;;; +26D9;WHITE LEFT LANE MERGE;So;0;ON;;;;;N;;;;; +26DA;DRIVE SLOW SIGN;So;0;ON;;;;;N;;;;; +26DB;HEAVY WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +26DC;LEFT CLOSED ENTRY;So;0;ON;;;;;N;;;;; +26DD;SQUARED SALTIRE;So;0;ON;;;;;N;;;;; +26DE;FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE;So;0;ON;;;;;N;;;;; +26DF;BLACK TRUCK;So;0;ON;;;;;N;;;;; +26E0;RESTRICTED LEFT ENTRY-1;So;0;ON;;;;;N;;;;; +26E1;RESTRICTED LEFT ENTRY-2;So;0;ON;;;;;N;;;;; +26E2;ASTRONOMICAL SYMBOL FOR URANUS;So;0;ON;;;;;N;;;;; +26E3;HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE;So;0;ON;;;;;N;;;;; +26E4;PENTAGRAM;So;0;ON;;;;;N;;;;; +26E5;RIGHT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; +26E6;LEFT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; +26E7;INVERTED PENTAGRAM;So;0;ON;;;;;N;;;;; +26E8;BLACK CROSS ON SHIELD;So;0;ON;;;;;N;;;;; +26E9;SHINTO SHRINE;So;0;ON;;;;;N;;;;; +26EA;CHURCH;So;0;ON;;;;;N;;;;; +26EB;CASTLE;So;0;ON;;;;;N;;;;; +26EC;HISTORIC SITE;So;0;ON;;;;;N;;;;; +26ED;GEAR WITHOUT HUB;So;0;ON;;;;;N;;;;; +26EE;GEAR WITH HANDLES;So;0;ON;;;;;N;;;;; +26EF;MAP SYMBOL FOR LIGHTHOUSE;So;0;ON;;;;;N;;;;; +26F0;MOUNTAIN;So;0;ON;;;;;N;;;;; +26F1;UMBRELLA ON GROUND;So;0;ON;;;;;N;;;;; +26F2;FOUNTAIN;So;0;ON;;;;;N;;;;; +26F3;FLAG IN HOLE;So;0;ON;;;;;N;;;;; +26F4;FERRY;So;0;ON;;;;;N;;;;; +26F5;SAILBOAT;So;0;ON;;;;;N;;;;; +26F6;SQUARE FOUR CORNERS;So;0;ON;;;;;N;;;;; +26F7;SKIER;So;0;ON;;;;;N;;;;; +26F8;ICE SKATE;So;0;ON;;;;;N;;;;; +26F9;PERSON WITH BALL;So;0;ON;;;;;N;;;;; +26FA;TENT;So;0;ON;;;;;N;;;;; +26FB;JAPANESE BANK SYMBOL;So;0;ON;;;;;N;;;;; +26FC;HEADSTONE GRAVEYARD SYMBOL;So;0;ON;;;;;N;;;;; +26FD;FUEL PUMP;So;0;ON;;;;;N;;;;; +26FE;CUP ON BLACK SQUARE;So;0;ON;;;;;N;;;;; +26FF;WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE;So;0;ON;;;;;N;;;;; +2700;BLACK SAFETY SCISSORS;So;0;ON;;;;;N;;;;; +2701;UPPER BLADE SCISSORS;So;0;ON;;;;;N;;;;; +2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;; +2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;; +2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;; +2705;WHITE HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; +2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;; +2707;TAPE DRIVE;So;0;ON;;;;;N;;;;; +2708;AIRPLANE;So;0;ON;;;;;N;;;;; +2709;ENVELOPE;So;0;ON;;;;;N;;;;; +270A;RAISED FIST;So;0;ON;;;;;N;;;;; +270B;RAISED HAND;So;0;ON;;;;;N;;;;; +270C;VICTORY HAND;So;0;ON;;;;;N;;;;; +270D;WRITING HAND;So;0;ON;;;;;N;;;;; +270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;; +270F;PENCIL;So;0;ON;;;;;N;;;;; +2710;UPPER RIGHT PENCIL;So;0;ON;;;;;N;;;;; +2711;WHITE NIB;So;0;ON;;;;;N;;;;; +2712;BLACK NIB;So;0;ON;;;;;N;;;;; +2713;CHECK MARK;So;0;ON;;;;;N;;;;; +2714;HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; +2715;MULTIPLICATION X;So;0;ON;;;;;N;;;;; +2716;HEAVY MULTIPLICATION X;So;0;ON;;;;;N;;;;; +2717;BALLOT X;So;0;ON;;;;;N;;;;; +2718;HEAVY BALLOT X;So;0;ON;;;;;N;;;;; +2719;OUTLINED GREEK CROSS;So;0;ON;;;;;N;;;;; +271A;HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; +271B;OPEN CENTRE CROSS;So;0;ON;;;;;N;OPEN CENTER CROSS;;;; +271C;HEAVY OPEN CENTRE CROSS;So;0;ON;;;;;N;HEAVY OPEN CENTER CROSS;;;; +271D;LATIN CROSS;So;0;ON;;;;;N;;;;; +271E;SHADOWED WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; +271F;OUTLINED LATIN CROSS;So;0;ON;;;;;N;;;;; +2720;MALTESE CROSS;So;0;ON;;;;;N;;;;; +2721;STAR OF DAVID;So;0;ON;;;;;N;;;;; +2722;FOUR TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2723;FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2724;HEAVY FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;; +2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;; +2728;SPARKLES;So;0;ON;;;;;N;;;;; +2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; +272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;; +272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;; +272C;BLACK CENTRE WHITE STAR;So;0;ON;;;;;N;BLACK CENTER WHITE STAR;;;; +272D;OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; +272E;HEAVY OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; +272F;PINWHEEL STAR;So;0;ON;;;;;N;;;;; +2730;SHADOWED WHITE STAR;So;0;ON;;;;;N;;;;; +2731;HEAVY ASTERISK;So;0;ON;;;;;N;;;;; +2732;OPEN CENTRE ASTERISK;So;0;ON;;;;;N;OPEN CENTER ASTERISK;;;; +2733;EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2734;EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +2735;EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +2736;SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +2737;EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; +2738;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; +2739;TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +273A;SIXTEEN POINTED ASTERISK;So;0;ON;;;;;N;;;;; +273B;TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +273C;OPEN CENTRE TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;OPEN CENTER TEARDROP-SPOKED ASTERISK;;;; +273D;HEAVY TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +273E;SIX PETALLED BLACK AND WHITE FLORETTE;So;0;ON;;;;;N;;;;; +273F;BLACK FLORETTE;So;0;ON;;;;;N;;;;; +2740;WHITE FLORETTE;So;0;ON;;;;;N;;;;; +2741;EIGHT PETALLED OUTLINED BLACK FLORETTE;So;0;ON;;;;;N;;;;; +2742;CIRCLED OPEN CENTRE EIGHT POINTED STAR;So;0;ON;;;;;N;CIRCLED OPEN CENTER EIGHT POINTED STAR;;;; +2743;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK;So;0;ON;;;;;N;;;;; +2744;SNOWFLAKE;So;0;ON;;;;;N;;;;; +2745;TIGHT TRIFOLIATE SNOWFLAKE;So;0;ON;;;;;N;;;;; +2746;HEAVY CHEVRON SNOWFLAKE;So;0;ON;;;;;N;;;;; +2747;SPARKLE;So;0;ON;;;;;N;;;;; +2748;HEAVY SPARKLE;So;0;ON;;;;;N;;;;; +2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; +274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; +274C;CROSS MARK;So;0;ON;;;;;N;;;;; +274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; +274E;NEGATIVE SQUARED CROSS MARK;So;0;ON;;;;;N;;;;; +274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2753;BLACK QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2754;WHITE QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2755;WHITE EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;; +2757;HEAVY EXCLAMATION MARK SYMBOL;So;0;ON;;;;;N;;;;; +2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;; +2759;MEDIUM VERTICAL BAR;So;0;ON;;;;;N;;;;; +275A;HEAVY VERTICAL BAR;So;0;ON;;;;;N;;;;; +275B;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275F;HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2760;HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;; +2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;; +2765;ROTATED HEAVY BLACK HEART BULLET;So;0;ON;;;;;N;;;;; +2766;FLORAL HEART;So;0;ON;;;;;N;;;;; +2767;ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; +2768;MEDIUM LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; +2769;MEDIUM RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; +276A;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; +276B;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; +276C;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; +276D;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; +276E;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT;Ps;0;ON;;;;;Y;;;;; +276F;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT;Pe;0;ON;;;;;Y;;;;; +2770;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; +2771;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; +2772;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; +2773;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; +2774;MEDIUM LEFT CURLY BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; +2775;MEDIUM RIGHT CURLY BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; +2776;DINGBAT NEGATIVE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED DIGIT ONE;;;; +2777;DINGBAT NEGATIVE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED DIGIT TWO;;;; +2778;DINGBAT NEGATIVE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED DIGIT THREE;;;; +2779;DINGBAT NEGATIVE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED DIGIT FOUR;;;; +277A;DINGBAT NEGATIVE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED DIGIT FIVE;;;; +277B;DINGBAT NEGATIVE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED DIGIT SIX;;;; +277C;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED DIGIT SEVEN;;;; +277D;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED DIGIT EIGHT;;;; +277E;DINGBAT NEGATIVE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED DIGIT NINE;;;; +277F;DINGBAT NEGATIVE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED NUMBER TEN;;;; +2780;DINGBAT CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;CIRCLED SANS-SERIF DIGIT ONE;;;; +2781;DINGBAT CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;CIRCLED SANS-SERIF DIGIT TWO;;;; +2782;DINGBAT CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;CIRCLED SANS-SERIF DIGIT THREE;;;; +2783;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;CIRCLED SANS-SERIF DIGIT FOUR;;;; +2784;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;CIRCLED SANS-SERIF DIGIT FIVE;;;; +2785;DINGBAT CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;CIRCLED SANS-SERIF DIGIT SIX;;;; +2786;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;CIRCLED SANS-SERIF DIGIT SEVEN;;;; +2787;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;CIRCLED SANS-SERIF DIGIT EIGHT;;;; +2788;DINGBAT CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;CIRCLED SANS-SERIF DIGIT NINE;;;; +2789;DINGBAT CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;CIRCLED SANS-SERIF NUMBER TEN;;;; +278A;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED SANS-SERIF DIGIT ONE;;;; +278B;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED SANS-SERIF DIGIT TWO;;;; +278C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED SANS-SERIF DIGIT THREE;;;; +278D;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED SANS-SERIF DIGIT FOUR;;;; +278E;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED SANS-SERIF DIGIT FIVE;;;; +278F;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED SANS-SERIF DIGIT SIX;;;; +2790;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED SANS-SERIF DIGIT SEVEN;;;; +2791;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED SANS-SERIF DIGIT EIGHT;;;; +2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;; +2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;; +2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;; +2795;HEAVY PLUS SIGN;So;0;ON;;;;;N;;;;; +2796;HEAVY MINUS SIGN;So;0;ON;;;;;N;;;;; +2797;HEAVY DIVISION SIGN;So;0;ON;;;;;N;;;;; +2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;; +2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;; +279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;; +279B;DRAFTING POINT RIGHTWARDS ARROW;So;0;ON;;;;;N;DRAFTING POINT RIGHT ARROW;;;; +279C;HEAVY ROUND-TIPPED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY ROUND-TIPPED RIGHT ARROW;;;; +279D;TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;TRIANGLE-HEADED RIGHT ARROW;;;; +279E;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TRIANGLE-HEADED RIGHT ARROW;;;; +279F;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;DASHED TRIANGLE-HEADED RIGHT ARROW;;;; +27A0;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW;;;; +27A1;BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK RIGHT ARROW;;;; +27A2;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D TOP-LIGHTED RIGHT ARROWHEAD;;;; +27A3;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD;;;; +27A4;BLACK RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;BLACK RIGHT ARROWHEAD;;;; +27A5;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED DOWN AND RIGHT ARROW;;;; +27A6;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED UP AND RIGHT ARROW;;;; +27A7;SQUAT BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;SQUAT BLACK RIGHT ARROW;;;; +27A8;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY CONCAVE-POINTED BLACK RIGHT ARROW;;;; +27A9;RIGHT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;RIGHT-SHADED WHITE RIGHT ARROW;;;; +27AA;LEFT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT-SHADED WHITE RIGHT ARROW;;;; +27AB;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;BACK-TILTED SHADOWED WHITE RIGHT ARROW;;;; +27AC;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;FRONT-TILTED SHADOWED WHITE RIGHT ARROW;;;; +27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27B0;CURLY LOOP;So;0;ON;;;;;N;;;;; +27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;; +27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;; +27B4;BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED LOWER RIGHT ARROW;;;; +27B5;BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK-FEATHERED RIGHT ARROW;;;; +27B6;BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED UPPER RIGHT ARROW;;;; +27B7;HEAVY BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED LOWER RIGHT ARROW;;;; +27B8;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED RIGHT ARROW;;;; +27B9;HEAVY BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED UPPER RIGHT ARROW;;;; +27BA;TEARDROP-BARBED RIGHTWARDS ARROW;So;0;ON;;;;;N;TEARDROP-BARBED RIGHT ARROW;;;; +27BB;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TEARDROP-SHANKED RIGHT ARROW;;;; +27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;; +27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;; +27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;; +27BF;DOUBLE CURLY LOOP;So;0;ON;;;;;N;;;;; +27C0;THREE DIMENSIONAL ANGLE;Sm;0;ON;;;;;Y;;;;; +27C1;WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE;Sm;0;ON;;;;;N;;;;; +27C2;PERPENDICULAR;Sm;0;ON;;;;;N;;;;; +27C3;OPEN SUBSET;Sm;0;ON;;;;;Y;;;;; +27C4;OPEN SUPERSET;Sm;0;ON;;;;;Y;;;;; +27C5;LEFT S-SHAPED BAG DELIMITER;Ps;0;ON;;;;;Y;;;;; +27C6;RIGHT S-SHAPED BAG DELIMITER;Pe;0;ON;;;;;Y;;;;; +27C7;OR WITH DOT INSIDE;Sm;0;ON;;;;;N;;;;; +27C8;REVERSE SOLIDUS PRECEDING SUBSET;Sm;0;ON;;;;;Y;;;;; +27C9;SUPERSET PRECEDING SOLIDUS;Sm;0;ON;;;;;Y;;;;; +27CA;VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +27CB;MATHEMATICAL RISING DIAGONAL;Sm;0;ON;;;;;Y;;;;; +27CC;LONG DIVISION;Sm;0;ON;;;;;Y;;;;; +27CD;MATHEMATICAL FALLING DIAGONAL;Sm;0;ON;;;;;Y;;;;; +27CE;SQUARED LOGICAL AND;Sm;0;ON;;;;;N;;;;; +27CF;SQUARED LOGICAL OR;Sm;0;ON;;;;;N;;;;; +27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;; +27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;; +27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;; +27D3;LOWER RIGHT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; +27D4;UPPER LEFT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; +27D5;LEFT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; +27D6;RIGHT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; +27D7;FULL OUTER JOIN;Sm;0;ON;;;;;N;;;;; +27D8;LARGE UP TACK;Sm;0;ON;;;;;N;;;;; +27D9;LARGE DOWN TACK;Sm;0;ON;;;;;N;;;;; +27DA;LEFT AND RIGHT DOUBLE TURNSTILE;Sm;0;ON;;;;;N;;;;; +27DB;LEFT AND RIGHT TACK;Sm;0;ON;;;;;N;;;;; +27DC;LEFT MULTIMAP;Sm;0;ON;;;;;Y;;;;; +27DD;LONG RIGHT TACK;Sm;0;ON;;;;;Y;;;;; +27DE;LONG LEFT TACK;Sm;0;ON;;;;;Y;;;;; +27DF;UP TACK WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; +27E0;LOZENGE DIVIDED BY HORIZONTAL RULE;Sm;0;ON;;;;;N;;;;; +27E1;WHITE CONCAVE-SIDED DIAMOND;Sm;0;ON;;;;;N;;;;; +27E2;WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; +27E3;WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; +27E4;WHITE SQUARE WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; +27E5;WHITE SQUARE WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; +27E6;MATHEMATICAL LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;;;;; +27E7;MATHEMATICAL RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;;;;; +27E8;MATHEMATICAL LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; +27E9;MATHEMATICAL RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; +27EA;MATHEMATICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; +27EB;MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; +27EC;MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; +27ED;MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; +27EE;MATHEMATICAL LEFT FLATTENED PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +27EF;MATHEMATICAL RIGHT FLATTENED PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +27F0;UPWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; +27F1;DOWNWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; +27F2;ANTICLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; +27F3;CLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; +27F4;RIGHT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; +27F5;LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +27F6;LONG RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +27F7;LONG LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; +27F8;LONG LEFTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; +27F9;LONG RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; +27FA;LONG LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; +27FB;LONG LEFTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +27FC;LONG RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +27FD;LONG LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +27FE;LONG RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +27FF;LONG RIGHTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; +2800;BRAILLE PATTERN BLANK;So;0;L;;;;;N;;;;; +2801;BRAILLE PATTERN DOTS-1;So;0;L;;;;;N;;;;; +2802;BRAILLE PATTERN DOTS-2;So;0;L;;;;;N;;;;; +2803;BRAILLE PATTERN DOTS-12;So;0;L;;;;;N;;;;; +2804;BRAILLE PATTERN DOTS-3;So;0;L;;;;;N;;;;; +2805;BRAILLE PATTERN DOTS-13;So;0;L;;;;;N;;;;; +2806;BRAILLE PATTERN DOTS-23;So;0;L;;;;;N;;;;; +2807;BRAILLE PATTERN DOTS-123;So;0;L;;;;;N;;;;; +2808;BRAILLE PATTERN DOTS-4;So;0;L;;;;;N;;;;; +2809;BRAILLE PATTERN DOTS-14;So;0;L;;;;;N;;;;; +280A;BRAILLE PATTERN DOTS-24;So;0;L;;;;;N;;;;; +280B;BRAILLE PATTERN DOTS-124;So;0;L;;;;;N;;;;; +280C;BRAILLE PATTERN DOTS-34;So;0;L;;;;;N;;;;; +280D;BRAILLE PATTERN DOTS-134;So;0;L;;;;;N;;;;; +280E;BRAILLE PATTERN DOTS-234;So;0;L;;;;;N;;;;; +280F;BRAILLE PATTERN DOTS-1234;So;0;L;;;;;N;;;;; +2810;BRAILLE PATTERN DOTS-5;So;0;L;;;;;N;;;;; +2811;BRAILLE PATTERN DOTS-15;So;0;L;;;;;N;;;;; +2812;BRAILLE PATTERN DOTS-25;So;0;L;;;;;N;;;;; +2813;BRAILLE PATTERN DOTS-125;So;0;L;;;;;N;;;;; +2814;BRAILLE PATTERN DOTS-35;So;0;L;;;;;N;;;;; +2815;BRAILLE PATTERN DOTS-135;So;0;L;;;;;N;;;;; +2816;BRAILLE PATTERN DOTS-235;So;0;L;;;;;N;;;;; +2817;BRAILLE PATTERN DOTS-1235;So;0;L;;;;;N;;;;; +2818;BRAILLE PATTERN DOTS-45;So;0;L;;;;;N;;;;; +2819;BRAILLE PATTERN DOTS-145;So;0;L;;;;;N;;;;; +281A;BRAILLE PATTERN DOTS-245;So;0;L;;;;;N;;;;; +281B;BRAILLE PATTERN DOTS-1245;So;0;L;;;;;N;;;;; +281C;BRAILLE PATTERN DOTS-345;So;0;L;;;;;N;;;;; +281D;BRAILLE PATTERN DOTS-1345;So;0;L;;;;;N;;;;; +281E;BRAILLE PATTERN DOTS-2345;So;0;L;;;;;N;;;;; +281F;BRAILLE PATTERN DOTS-12345;So;0;L;;;;;N;;;;; +2820;BRAILLE PATTERN DOTS-6;So;0;L;;;;;N;;;;; +2821;BRAILLE PATTERN DOTS-16;So;0;L;;;;;N;;;;; +2822;BRAILLE PATTERN DOTS-26;So;0;L;;;;;N;;;;; +2823;BRAILLE PATTERN DOTS-126;So;0;L;;;;;N;;;;; +2824;BRAILLE PATTERN DOTS-36;So;0;L;;;;;N;;;;; +2825;BRAILLE PATTERN DOTS-136;So;0;L;;;;;N;;;;; +2826;BRAILLE PATTERN DOTS-236;So;0;L;;;;;N;;;;; +2827;BRAILLE PATTERN DOTS-1236;So;0;L;;;;;N;;;;; +2828;BRAILLE PATTERN DOTS-46;So;0;L;;;;;N;;;;; +2829;BRAILLE PATTERN DOTS-146;So;0;L;;;;;N;;;;; +282A;BRAILLE PATTERN DOTS-246;So;0;L;;;;;N;;;;; +282B;BRAILLE PATTERN DOTS-1246;So;0;L;;;;;N;;;;; +282C;BRAILLE PATTERN DOTS-346;So;0;L;;;;;N;;;;; +282D;BRAILLE PATTERN DOTS-1346;So;0;L;;;;;N;;;;; +282E;BRAILLE PATTERN DOTS-2346;So;0;L;;;;;N;;;;; +282F;BRAILLE PATTERN DOTS-12346;So;0;L;;;;;N;;;;; +2830;BRAILLE PATTERN DOTS-56;So;0;L;;;;;N;;;;; +2831;BRAILLE PATTERN DOTS-156;So;0;L;;;;;N;;;;; +2832;BRAILLE PATTERN DOTS-256;So;0;L;;;;;N;;;;; +2833;BRAILLE PATTERN DOTS-1256;So;0;L;;;;;N;;;;; +2834;BRAILLE PATTERN DOTS-356;So;0;L;;;;;N;;;;; +2835;BRAILLE PATTERN DOTS-1356;So;0;L;;;;;N;;;;; +2836;BRAILLE PATTERN DOTS-2356;So;0;L;;;;;N;;;;; +2837;BRAILLE PATTERN DOTS-12356;So;0;L;;;;;N;;;;; +2838;BRAILLE PATTERN DOTS-456;So;0;L;;;;;N;;;;; +2839;BRAILLE PATTERN DOTS-1456;So;0;L;;;;;N;;;;; +283A;BRAILLE PATTERN DOTS-2456;So;0;L;;;;;N;;;;; +283B;BRAILLE PATTERN DOTS-12456;So;0;L;;;;;N;;;;; +283C;BRAILLE PATTERN DOTS-3456;So;0;L;;;;;N;;;;; +283D;BRAILLE PATTERN DOTS-13456;So;0;L;;;;;N;;;;; +283E;BRAILLE PATTERN DOTS-23456;So;0;L;;;;;N;;;;; +283F;BRAILLE PATTERN DOTS-123456;So;0;L;;;;;N;;;;; +2840;BRAILLE PATTERN DOTS-7;So;0;L;;;;;N;;;;; +2841;BRAILLE PATTERN DOTS-17;So;0;L;;;;;N;;;;; +2842;BRAILLE PATTERN DOTS-27;So;0;L;;;;;N;;;;; +2843;BRAILLE PATTERN DOTS-127;So;0;L;;;;;N;;;;; +2844;BRAILLE PATTERN DOTS-37;So;0;L;;;;;N;;;;; +2845;BRAILLE PATTERN DOTS-137;So;0;L;;;;;N;;;;; +2846;BRAILLE PATTERN DOTS-237;So;0;L;;;;;N;;;;; +2847;BRAILLE PATTERN DOTS-1237;So;0;L;;;;;N;;;;; +2848;BRAILLE PATTERN DOTS-47;So;0;L;;;;;N;;;;; +2849;BRAILLE PATTERN DOTS-147;So;0;L;;;;;N;;;;; +284A;BRAILLE PATTERN DOTS-247;So;0;L;;;;;N;;;;; +284B;BRAILLE PATTERN DOTS-1247;So;0;L;;;;;N;;;;; +284C;BRAILLE PATTERN DOTS-347;So;0;L;;;;;N;;;;; +284D;BRAILLE PATTERN DOTS-1347;So;0;L;;;;;N;;;;; +284E;BRAILLE PATTERN DOTS-2347;So;0;L;;;;;N;;;;; +284F;BRAILLE PATTERN DOTS-12347;So;0;L;;;;;N;;;;; +2850;BRAILLE PATTERN DOTS-57;So;0;L;;;;;N;;;;; +2851;BRAILLE PATTERN DOTS-157;So;0;L;;;;;N;;;;; +2852;BRAILLE PATTERN DOTS-257;So;0;L;;;;;N;;;;; +2853;BRAILLE PATTERN DOTS-1257;So;0;L;;;;;N;;;;; +2854;BRAILLE PATTERN DOTS-357;So;0;L;;;;;N;;;;; +2855;BRAILLE PATTERN DOTS-1357;So;0;L;;;;;N;;;;; +2856;BRAILLE PATTERN DOTS-2357;So;0;L;;;;;N;;;;; +2857;BRAILLE PATTERN DOTS-12357;So;0;L;;;;;N;;;;; +2858;BRAILLE PATTERN DOTS-457;So;0;L;;;;;N;;;;; +2859;BRAILLE PATTERN DOTS-1457;So;0;L;;;;;N;;;;; +285A;BRAILLE PATTERN DOTS-2457;So;0;L;;;;;N;;;;; +285B;BRAILLE PATTERN DOTS-12457;So;0;L;;;;;N;;;;; +285C;BRAILLE PATTERN DOTS-3457;So;0;L;;;;;N;;;;; +285D;BRAILLE PATTERN DOTS-13457;So;0;L;;;;;N;;;;; +285E;BRAILLE PATTERN DOTS-23457;So;0;L;;;;;N;;;;; +285F;BRAILLE PATTERN DOTS-123457;So;0;L;;;;;N;;;;; +2860;BRAILLE PATTERN DOTS-67;So;0;L;;;;;N;;;;; +2861;BRAILLE PATTERN DOTS-167;So;0;L;;;;;N;;;;; +2862;BRAILLE PATTERN DOTS-267;So;0;L;;;;;N;;;;; +2863;BRAILLE PATTERN DOTS-1267;So;0;L;;;;;N;;;;; +2864;BRAILLE PATTERN DOTS-367;So;0;L;;;;;N;;;;; +2865;BRAILLE PATTERN DOTS-1367;So;0;L;;;;;N;;;;; +2866;BRAILLE PATTERN DOTS-2367;So;0;L;;;;;N;;;;; +2867;BRAILLE PATTERN DOTS-12367;So;0;L;;;;;N;;;;; +2868;BRAILLE PATTERN DOTS-467;So;0;L;;;;;N;;;;; +2869;BRAILLE PATTERN DOTS-1467;So;0;L;;;;;N;;;;; +286A;BRAILLE PATTERN DOTS-2467;So;0;L;;;;;N;;;;; +286B;BRAILLE PATTERN DOTS-12467;So;0;L;;;;;N;;;;; +286C;BRAILLE PATTERN DOTS-3467;So;0;L;;;;;N;;;;; +286D;BRAILLE PATTERN DOTS-13467;So;0;L;;;;;N;;;;; +286E;BRAILLE PATTERN DOTS-23467;So;0;L;;;;;N;;;;; +286F;BRAILLE PATTERN DOTS-123467;So;0;L;;;;;N;;;;; +2870;BRAILLE PATTERN DOTS-567;So;0;L;;;;;N;;;;; +2871;BRAILLE PATTERN DOTS-1567;So;0;L;;;;;N;;;;; +2872;BRAILLE PATTERN DOTS-2567;So;0;L;;;;;N;;;;; +2873;BRAILLE PATTERN DOTS-12567;So;0;L;;;;;N;;;;; +2874;BRAILLE PATTERN DOTS-3567;So;0;L;;;;;N;;;;; +2875;BRAILLE PATTERN DOTS-13567;So;0;L;;;;;N;;;;; +2876;BRAILLE PATTERN DOTS-23567;So;0;L;;;;;N;;;;; +2877;BRAILLE PATTERN DOTS-123567;So;0;L;;;;;N;;;;; +2878;BRAILLE PATTERN DOTS-4567;So;0;L;;;;;N;;;;; +2879;BRAILLE PATTERN DOTS-14567;So;0;L;;;;;N;;;;; +287A;BRAILLE PATTERN DOTS-24567;So;0;L;;;;;N;;;;; +287B;BRAILLE PATTERN DOTS-124567;So;0;L;;;;;N;;;;; +287C;BRAILLE PATTERN DOTS-34567;So;0;L;;;;;N;;;;; +287D;BRAILLE PATTERN DOTS-134567;So;0;L;;;;;N;;;;; +287E;BRAILLE PATTERN DOTS-234567;So;0;L;;;;;N;;;;; +287F;BRAILLE PATTERN DOTS-1234567;So;0;L;;;;;N;;;;; +2880;BRAILLE PATTERN DOTS-8;So;0;L;;;;;N;;;;; +2881;BRAILLE PATTERN DOTS-18;So;0;L;;;;;N;;;;; +2882;BRAILLE PATTERN DOTS-28;So;0;L;;;;;N;;;;; +2883;BRAILLE PATTERN DOTS-128;So;0;L;;;;;N;;;;; +2884;BRAILLE PATTERN DOTS-38;So;0;L;;;;;N;;;;; +2885;BRAILLE PATTERN DOTS-138;So;0;L;;;;;N;;;;; +2886;BRAILLE PATTERN DOTS-238;So;0;L;;;;;N;;;;; +2887;BRAILLE PATTERN DOTS-1238;So;0;L;;;;;N;;;;; +2888;BRAILLE PATTERN DOTS-48;So;0;L;;;;;N;;;;; +2889;BRAILLE PATTERN DOTS-148;So;0;L;;;;;N;;;;; +288A;BRAILLE PATTERN DOTS-248;So;0;L;;;;;N;;;;; +288B;BRAILLE PATTERN DOTS-1248;So;0;L;;;;;N;;;;; +288C;BRAILLE PATTERN DOTS-348;So;0;L;;;;;N;;;;; +288D;BRAILLE PATTERN DOTS-1348;So;0;L;;;;;N;;;;; +288E;BRAILLE PATTERN DOTS-2348;So;0;L;;;;;N;;;;; +288F;BRAILLE PATTERN DOTS-12348;So;0;L;;;;;N;;;;; +2890;BRAILLE PATTERN DOTS-58;So;0;L;;;;;N;;;;; +2891;BRAILLE PATTERN DOTS-158;So;0;L;;;;;N;;;;; +2892;BRAILLE PATTERN DOTS-258;So;0;L;;;;;N;;;;; +2893;BRAILLE PATTERN DOTS-1258;So;0;L;;;;;N;;;;; +2894;BRAILLE PATTERN DOTS-358;So;0;L;;;;;N;;;;; +2895;BRAILLE PATTERN DOTS-1358;So;0;L;;;;;N;;;;; +2896;BRAILLE PATTERN DOTS-2358;So;0;L;;;;;N;;;;; +2897;BRAILLE PATTERN DOTS-12358;So;0;L;;;;;N;;;;; +2898;BRAILLE PATTERN DOTS-458;So;0;L;;;;;N;;;;; +2899;BRAILLE PATTERN DOTS-1458;So;0;L;;;;;N;;;;; +289A;BRAILLE PATTERN DOTS-2458;So;0;L;;;;;N;;;;; +289B;BRAILLE PATTERN DOTS-12458;So;0;L;;;;;N;;;;; +289C;BRAILLE PATTERN DOTS-3458;So;0;L;;;;;N;;;;; +289D;BRAILLE PATTERN DOTS-13458;So;0;L;;;;;N;;;;; +289E;BRAILLE PATTERN DOTS-23458;So;0;L;;;;;N;;;;; +289F;BRAILLE PATTERN DOTS-123458;So;0;L;;;;;N;;;;; +28A0;BRAILLE PATTERN DOTS-68;So;0;L;;;;;N;;;;; +28A1;BRAILLE PATTERN DOTS-168;So;0;L;;;;;N;;;;; +28A2;BRAILLE PATTERN DOTS-268;So;0;L;;;;;N;;;;; +28A3;BRAILLE PATTERN DOTS-1268;So;0;L;;;;;N;;;;; +28A4;BRAILLE PATTERN DOTS-368;So;0;L;;;;;N;;;;; +28A5;BRAILLE PATTERN DOTS-1368;So;0;L;;;;;N;;;;; +28A6;BRAILLE PATTERN DOTS-2368;So;0;L;;;;;N;;;;; +28A7;BRAILLE PATTERN DOTS-12368;So;0;L;;;;;N;;;;; +28A8;BRAILLE PATTERN DOTS-468;So;0;L;;;;;N;;;;; +28A9;BRAILLE PATTERN DOTS-1468;So;0;L;;;;;N;;;;; +28AA;BRAILLE PATTERN DOTS-2468;So;0;L;;;;;N;;;;; +28AB;BRAILLE PATTERN DOTS-12468;So;0;L;;;;;N;;;;; +28AC;BRAILLE PATTERN DOTS-3468;So;0;L;;;;;N;;;;; +28AD;BRAILLE PATTERN DOTS-13468;So;0;L;;;;;N;;;;; +28AE;BRAILLE PATTERN DOTS-23468;So;0;L;;;;;N;;;;; +28AF;BRAILLE PATTERN DOTS-123468;So;0;L;;;;;N;;;;; +28B0;BRAILLE PATTERN DOTS-568;So;0;L;;;;;N;;;;; +28B1;BRAILLE PATTERN DOTS-1568;So;0;L;;;;;N;;;;; +28B2;BRAILLE PATTERN DOTS-2568;So;0;L;;;;;N;;;;; +28B3;BRAILLE PATTERN DOTS-12568;So;0;L;;;;;N;;;;; +28B4;BRAILLE PATTERN DOTS-3568;So;0;L;;;;;N;;;;; +28B5;BRAILLE PATTERN DOTS-13568;So;0;L;;;;;N;;;;; +28B6;BRAILLE PATTERN DOTS-23568;So;0;L;;;;;N;;;;; +28B7;BRAILLE PATTERN DOTS-123568;So;0;L;;;;;N;;;;; +28B8;BRAILLE PATTERN DOTS-4568;So;0;L;;;;;N;;;;; +28B9;BRAILLE PATTERN DOTS-14568;So;0;L;;;;;N;;;;; +28BA;BRAILLE PATTERN DOTS-24568;So;0;L;;;;;N;;;;; +28BB;BRAILLE PATTERN DOTS-124568;So;0;L;;;;;N;;;;; +28BC;BRAILLE PATTERN DOTS-34568;So;0;L;;;;;N;;;;; +28BD;BRAILLE PATTERN DOTS-134568;So;0;L;;;;;N;;;;; +28BE;BRAILLE PATTERN DOTS-234568;So;0;L;;;;;N;;;;; +28BF;BRAILLE PATTERN DOTS-1234568;So;0;L;;;;;N;;;;; +28C0;BRAILLE PATTERN DOTS-78;So;0;L;;;;;N;;;;; +28C1;BRAILLE PATTERN DOTS-178;So;0;L;;;;;N;;;;; +28C2;BRAILLE PATTERN DOTS-278;So;0;L;;;;;N;;;;; +28C3;BRAILLE PATTERN DOTS-1278;So;0;L;;;;;N;;;;; +28C4;BRAILLE PATTERN DOTS-378;So;0;L;;;;;N;;;;; +28C5;BRAILLE PATTERN DOTS-1378;So;0;L;;;;;N;;;;; +28C6;BRAILLE PATTERN DOTS-2378;So;0;L;;;;;N;;;;; +28C7;BRAILLE PATTERN DOTS-12378;So;0;L;;;;;N;;;;; +28C8;BRAILLE PATTERN DOTS-478;So;0;L;;;;;N;;;;; +28C9;BRAILLE PATTERN DOTS-1478;So;0;L;;;;;N;;;;; +28CA;BRAILLE PATTERN DOTS-2478;So;0;L;;;;;N;;;;; +28CB;BRAILLE PATTERN DOTS-12478;So;0;L;;;;;N;;;;; +28CC;BRAILLE PATTERN DOTS-3478;So;0;L;;;;;N;;;;; +28CD;BRAILLE PATTERN DOTS-13478;So;0;L;;;;;N;;;;; +28CE;BRAILLE PATTERN DOTS-23478;So;0;L;;;;;N;;;;; +28CF;BRAILLE PATTERN DOTS-123478;So;0;L;;;;;N;;;;; +28D0;BRAILLE PATTERN DOTS-578;So;0;L;;;;;N;;;;; +28D1;BRAILLE PATTERN DOTS-1578;So;0;L;;;;;N;;;;; +28D2;BRAILLE PATTERN DOTS-2578;So;0;L;;;;;N;;;;; +28D3;BRAILLE PATTERN DOTS-12578;So;0;L;;;;;N;;;;; +28D4;BRAILLE PATTERN DOTS-3578;So;0;L;;;;;N;;;;; +28D5;BRAILLE PATTERN DOTS-13578;So;0;L;;;;;N;;;;; +28D6;BRAILLE PATTERN DOTS-23578;So;0;L;;;;;N;;;;; +28D7;BRAILLE PATTERN DOTS-123578;So;0;L;;;;;N;;;;; +28D8;BRAILLE PATTERN DOTS-4578;So;0;L;;;;;N;;;;; +28D9;BRAILLE PATTERN DOTS-14578;So;0;L;;;;;N;;;;; +28DA;BRAILLE PATTERN DOTS-24578;So;0;L;;;;;N;;;;; +28DB;BRAILLE PATTERN DOTS-124578;So;0;L;;;;;N;;;;; +28DC;BRAILLE PATTERN DOTS-34578;So;0;L;;;;;N;;;;; +28DD;BRAILLE PATTERN DOTS-134578;So;0;L;;;;;N;;;;; +28DE;BRAILLE PATTERN DOTS-234578;So;0;L;;;;;N;;;;; +28DF;BRAILLE PATTERN DOTS-1234578;So;0;L;;;;;N;;;;; +28E0;BRAILLE PATTERN DOTS-678;So;0;L;;;;;N;;;;; +28E1;BRAILLE PATTERN DOTS-1678;So;0;L;;;;;N;;;;; +28E2;BRAILLE PATTERN DOTS-2678;So;0;L;;;;;N;;;;; +28E3;BRAILLE PATTERN DOTS-12678;So;0;L;;;;;N;;;;; +28E4;BRAILLE PATTERN DOTS-3678;So;0;L;;;;;N;;;;; +28E5;BRAILLE PATTERN DOTS-13678;So;0;L;;;;;N;;;;; +28E6;BRAILLE PATTERN DOTS-23678;So;0;L;;;;;N;;;;; +28E7;BRAILLE PATTERN DOTS-123678;So;0;L;;;;;N;;;;; +28E8;BRAILLE PATTERN DOTS-4678;So;0;L;;;;;N;;;;; +28E9;BRAILLE PATTERN DOTS-14678;So;0;L;;;;;N;;;;; +28EA;BRAILLE PATTERN DOTS-24678;So;0;L;;;;;N;;;;; +28EB;BRAILLE PATTERN DOTS-124678;So;0;L;;;;;N;;;;; +28EC;BRAILLE PATTERN DOTS-34678;So;0;L;;;;;N;;;;; +28ED;BRAILLE PATTERN DOTS-134678;So;0;L;;;;;N;;;;; +28EE;BRAILLE PATTERN DOTS-234678;So;0;L;;;;;N;;;;; +28EF;BRAILLE PATTERN DOTS-1234678;So;0;L;;;;;N;;;;; +28F0;BRAILLE PATTERN DOTS-5678;So;0;L;;;;;N;;;;; +28F1;BRAILLE PATTERN DOTS-15678;So;0;L;;;;;N;;;;; +28F2;BRAILLE PATTERN DOTS-25678;So;0;L;;;;;N;;;;; +28F3;BRAILLE PATTERN DOTS-125678;So;0;L;;;;;N;;;;; +28F4;BRAILLE PATTERN DOTS-35678;So;0;L;;;;;N;;;;; +28F5;BRAILLE PATTERN DOTS-135678;So;0;L;;;;;N;;;;; +28F6;BRAILLE PATTERN DOTS-235678;So;0;L;;;;;N;;;;; +28F7;BRAILLE PATTERN DOTS-1235678;So;0;L;;;;;N;;;;; +28F8;BRAILLE PATTERN DOTS-45678;So;0;L;;;;;N;;;;; +28F9;BRAILLE PATTERN DOTS-145678;So;0;L;;;;;N;;;;; +28FA;BRAILLE PATTERN DOTS-245678;So;0;L;;;;;N;;;;; +28FB;BRAILLE PATTERN DOTS-1245678;So;0;L;;;;;N;;;;; +28FC;BRAILLE PATTERN DOTS-345678;So;0;L;;;;;N;;;;; +28FD;BRAILLE PATTERN DOTS-1345678;So;0;L;;;;;N;;;;; +28FE;BRAILLE PATTERN DOTS-2345678;So;0;L;;;;;N;;;;; +28FF;BRAILLE PATTERN DOTS-12345678;So;0;L;;;;;N;;;;; +2900;RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2901;RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2902;LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2903;RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2904;LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2905;RIGHTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +2906;LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +2907;RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +2908;DOWNWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +2909;UPWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +290A;UPWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; +290B;DOWNWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; +290C;LEFTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +290D;RIGHTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +290E;LEFTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +290F;RIGHTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +2910;RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +2911;RIGHTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; +2912;UPWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; +2913;DOWNWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; +2914;RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2915;RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2916;RIGHTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; +2917;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2918;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2919;LEFTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; +291A;RIGHTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; +291B;LEFTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; +291C;RIGHTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; +291D;LEFTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +291E;RIGHTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +291F;LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +2920;RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +2921;NORTH WEST AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2922;NORTH EAST AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; +2923;NORTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; +2924;NORTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; +2925;SOUTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; +2926;SOUTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; +2927;NORTH WEST ARROW AND NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2928;NORTH EAST ARROW AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2929;SOUTH EAST ARROW AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; +292A;SOUTH WEST ARROW AND NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; +292B;RISING DIAGONAL CROSSING FALLING DIAGONAL;Sm;0;ON;;;;;N;;;;; +292C;FALLING DIAGONAL CROSSING RISING DIAGONAL;Sm;0;ON;;;;;N;;;;; +292D;SOUTH EAST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +292E;NORTH EAST ARROW CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +292F;FALLING DIAGONAL CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2930;RISING DIAGONAL CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2931;NORTH EAST ARROW CROSSING NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; +2932;NORTH WEST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2933;WAVE ARROW POINTING DIRECTLY RIGHT;Sm;0;ON;;;;;N;;;;; +2934;ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS;Sm;0;ON;;;;;N;;;;; +2935;ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS;Sm;0;ON;;;;;N;;;;; +2936;ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS;Sm;0;ON;;;;;N;;;;; +2937;ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS;Sm;0;ON;;;;;N;;;;; +2938;RIGHT-SIDE ARC CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +2939;LEFT-SIDE ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +293A;TOP ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +293B;BOTTOM ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +293C;TOP ARC CLOCKWISE ARROW WITH MINUS;Sm;0;ON;;;;;N;;;;; +293D;TOP ARC ANTICLOCKWISE ARROW WITH PLUS;Sm;0;ON;;;;;N;;;;; +293E;LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +293F;LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +2940;ANTICLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; +2941;CLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; +2942;RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2943;LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2944;SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2945;RIGHTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; +2946;LEFTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; +2947;RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; +2948;LEFT RIGHT ARROW THROUGH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +2949;UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +294A;LEFT BARB UP RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; +294B;LEFT BARB DOWN RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; +294C;UP BARB RIGHT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; +294D;UP BARB LEFT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; +294E;LEFT BARB UP RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; +294F;UP BARB RIGHT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; +2950;LEFT BARB DOWN RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; +2951;UP BARB LEFT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; +2952;LEFTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; +2953;RIGHTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; +2954;UPWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; +2955;DOWNWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; +2956;LEFTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; +2957;RIGHTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; +2958;UPWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; +2959;DOWNWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; +295A;LEFTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; +295B;RIGHTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; +295C;UPWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; +295D;DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; +295E;LEFTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; +295F;RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; +2960;UPWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; +2961;DOWNWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; +2962;LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; +2963;UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; +2964;RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; +2965;DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; +2966;LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; +2967;LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; +2968;RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; +2969;RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; +296A;LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; +296B;LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; +296C;RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; +296D;RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; +296E;UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; +296F;DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; +2970;RIGHT DOUBLE ARROW WITH ROUNDED HEAD;Sm;0;ON;;;;;N;;;;; +2971;EQUALS SIGN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2972;TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2973;LEFTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; +2974;RIGHTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; +2975;RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; +2976;LESS-THAN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2977;LEFTWARDS ARROW THROUGH LESS-THAN;Sm;0;ON;;;;;N;;;;; +2978;GREATER-THAN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2979;SUBSET ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +297A;LEFTWARDS ARROW THROUGH SUBSET;Sm;0;ON;;;;;N;;;;; +297B;SUPERSET ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +297C;LEFT FISH TAIL;Sm;0;ON;;;;;N;;;;; +297D;RIGHT FISH TAIL;Sm;0;ON;;;;;N;;;;; +297E;UP FISH TAIL;Sm;0;ON;;;;;N;;;;; +297F;DOWN FISH TAIL;Sm;0;ON;;;;;N;;;;; +2980;TRIPLE VERTICAL BAR DELIMITER;Sm;0;ON;;;;;N;;;;; +2981;Z NOTATION SPOT;Sm;0;ON;;;;;N;;;;; +2982;Z NOTATION TYPE COLON;Sm;0;ON;;;;;N;;;;; +2983;LEFT WHITE CURLY BRACKET;Ps;0;ON;;;;;Y;;;;; +2984;RIGHT WHITE CURLY BRACKET;Pe;0;ON;;;;;Y;;;;; +2985;LEFT WHITE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +2986;RIGHT WHITE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +2987;Z NOTATION LEFT IMAGE BRACKET;Ps;0;ON;;;;;Y;;;;; +2988;Z NOTATION RIGHT IMAGE BRACKET;Pe;0;ON;;;;;Y;;;;; +2989;Z NOTATION LEFT BINDING BRACKET;Ps;0;ON;;;;;Y;;;;; +298A;Z NOTATION RIGHT BINDING BRACKET;Pe;0;ON;;;;;Y;;;;; +298B;LEFT SQUARE BRACKET WITH UNDERBAR;Ps;0;ON;;;;;Y;;;;; +298C;RIGHT SQUARE BRACKET WITH UNDERBAR;Pe;0;ON;;;;;Y;;;;; +298D;LEFT SQUARE BRACKET WITH TICK IN TOP CORNER;Ps;0;ON;;;;;Y;;;;; +298E;RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Pe;0;ON;;;;;Y;;;;; +298F;LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Ps;0;ON;;;;;Y;;;;; +2990;RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER;Pe;0;ON;;;;;Y;;;;; +2991;LEFT ANGLE BRACKET WITH DOT;Ps;0;ON;;;;;Y;;;;; +2992;RIGHT ANGLE BRACKET WITH DOT;Pe;0;ON;;;;;Y;;;;; +2993;LEFT ARC LESS-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; +2994;RIGHT ARC GREATER-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; +2995;DOUBLE LEFT ARC GREATER-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; +2996;DOUBLE RIGHT ARC LESS-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; +2997;LEFT BLACK TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; +2998;RIGHT BLACK TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; +2999;DOTTED FENCE;Sm;0;ON;;;;;N;;;;; +299A;VERTICAL ZIGZAG LINE;Sm;0;ON;;;;;N;;;;; +299B;MEASURED ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; +299C;RIGHT ANGLE VARIANT WITH SQUARE;Sm;0;ON;;;;;Y;;;;; +299D;MEASURED RIGHT ANGLE WITH DOT;Sm;0;ON;;;;;Y;;;;; +299E;ANGLE WITH S INSIDE;Sm;0;ON;;;;;Y;;;;; +299F;ACUTE ANGLE;Sm;0;ON;;;;;Y;;;;; +29A0;SPHERICAL ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; +29A1;SPHERICAL ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; +29A2;TURNED ANGLE;Sm;0;ON;;;;;Y;;;;; +29A3;REVERSED ANGLE;Sm;0;ON;;;;;Y;;;;; +29A4;ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +29A5;REVERSED ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +29A6;OBLIQUE ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; +29A7;OBLIQUE ANGLE OPENING DOWN;Sm;0;ON;;;;;Y;;;;; +29A8;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT;Sm;0;ON;;;;;Y;;;;; +29A9;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT;Sm;0;ON;;;;;Y;;;;; +29AA;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT;Sm;0;ON;;;;;Y;;;;; +29AB;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT;Sm;0;ON;;;;;Y;;;;; +29AC;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP;Sm;0;ON;;;;;Y;;;;; +29AD;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP;Sm;0;ON;;;;;Y;;;;; +29AE;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN;Sm;0;ON;;;;;Y;;;;; +29AF;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN;Sm;0;ON;;;;;Y;;;;; +29B0;REVERSED EMPTY SET;Sm;0;ON;;;;;N;;;;; +29B1;EMPTY SET WITH OVERBAR;Sm;0;ON;;;;;N;;;;; +29B2;EMPTY SET WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; +29B3;EMPTY SET WITH RIGHT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; +29B4;EMPTY SET WITH LEFT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; +29B5;CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;; +29B6;CIRCLED VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +29B7;CIRCLED PARALLEL;Sm;0;ON;;;;;N;;;;; +29B8;CIRCLED REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; +29B9;CIRCLED PERPENDICULAR;Sm;0;ON;;;;;N;;;;; +29BA;CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +29BB;CIRCLE WITH SUPERIMPOSED X;Sm;0;ON;;;;;N;;;;; +29BC;CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; +29BD;UP ARROW THROUGH CIRCLE;Sm;0;ON;;;;;N;;;;; +29BE;CIRCLED WHITE BULLET;Sm;0;ON;;;;;N;;;;; +29BF;CIRCLED BULLET;Sm;0;ON;;;;;N;;;;; +29C0;CIRCLED LESS-THAN;Sm;0;ON;;;;;Y;;;;; +29C1;CIRCLED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +29C2;CIRCLE WITH SMALL CIRCLE TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; +29C3;CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; +29C4;SQUARED RISING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; +29C5;SQUARED FALLING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; +29C6;SQUARED ASTERISK;Sm;0;ON;;;;;N;;;;; +29C7;SQUARED SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +29C8;SQUARED SQUARE;Sm;0;ON;;;;;N;;;;; +29C9;TWO JOINED SQUARES;Sm;0;ON;;;;;Y;;;;; +29CA;TRIANGLE WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +29CB;TRIANGLE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +29CC;S IN TRIANGLE;Sm;0;ON;;;;;N;;;;; +29CD;TRIANGLE WITH SERIFS AT BOTTOM;Sm;0;ON;;;;;N;;;;; +29CE;RIGHT TRIANGLE ABOVE LEFT TRIANGLE;Sm;0;ON;;;;;Y;;;;; +29CF;LEFT TRIANGLE BESIDE VERTICAL BAR;Sm;0;ON;;;;;Y;;;;; +29D0;VERTICAL BAR BESIDE RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; +29D1;BOWTIE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29D2;BOWTIE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29D3;BLACK BOWTIE;Sm;0;ON;;;;;N;;;;; +29D4;TIMES WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29D5;TIMES WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29D6;WHITE HOURGLASS;Sm;0;ON;;;;;N;;;;; +29D7;BLACK HOURGLASS;Sm;0;ON;;;;;N;;;;; +29D8;LEFT WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; +29D9;RIGHT WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; +29DA;LEFT DOUBLE WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; +29DB;RIGHT DOUBLE WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; +29DC;INCOMPLETE INFINITY;Sm;0;ON;;;;;Y;;;;; +29DD;TIE OVER INFINITY;Sm;0;ON;;;;;N;;;;; +29DE;INFINITY NEGATED WITH VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +29DF;DOUBLE-ENDED MULTIMAP;Sm;0;ON;;;;;N;;;;; +29E0;SQUARE WITH CONTOURED OUTLINE;Sm;0;ON;;;;;N;;;;; +29E1;INCREASES AS;Sm;0;ON;;;;;Y;;;;; +29E2;SHUFFLE PRODUCT;Sm;0;ON;;;;;N;;;;; +29E3;EQUALS SIGN AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; +29E4;EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; +29E5;IDENTICAL TO AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; +29E6;GLEICH STARK;Sm;0;ON;;;;;N;;;;; +29E7;THERMODYNAMIC;Sm;0;ON;;;;;N;;;;; +29E8;DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29E9;DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29EA;BLACK DIAMOND WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; +29EB;BLACK LOZENGE;Sm;0;ON;;;;;N;;;;; +29EC;WHITE CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; +29ED;BLACK CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; +29EE;ERROR-BARRED WHITE SQUARE;Sm;0;ON;;;;;N;;;;; +29EF;ERROR-BARRED BLACK SQUARE;Sm;0;ON;;;;;N;;;;; +29F0;ERROR-BARRED WHITE DIAMOND;Sm;0;ON;;;;;N;;;;; +29F1;ERROR-BARRED BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +29F2;ERROR-BARRED WHITE CIRCLE;Sm;0;ON;;;;;N;;;;; +29F3;ERROR-BARRED BLACK CIRCLE;Sm;0;ON;;;;;N;;;;; +29F4;RULE-DELAYED;Sm;0;ON;;;;;Y;;;;; +29F5;REVERSE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; +29F6;SOLIDUS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +29F7;REVERSE SOLIDUS WITH HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +29F8;BIG SOLIDUS;Sm;0;ON;;;;;Y;;;;; +29F9;BIG REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; +29FA;DOUBLE PLUS;Sm;0;ON;;;;;N;;;;; +29FB;TRIPLE PLUS;Sm;0;ON;;;;;N;;;;; +29FC;LEFT-POINTING CURVED ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; +29FD;RIGHT-POINTING CURVED ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; +29FE;TINY;Sm;0;ON;;;;;N;;;;; +29FF;MINY;Sm;0;ON;;;;;N;;;;; +2A00;N-ARY CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; +2A01;N-ARY CIRCLED PLUS OPERATOR;Sm;0;ON;;;;;N;;;;; +2A02;N-ARY CIRCLED TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; +2A03;N-ARY UNION OPERATOR WITH DOT;Sm;0;ON;;;;;N;;;;; +2A04;N-ARY UNION OPERATOR WITH PLUS;Sm;0;ON;;;;;N;;;;; +2A05;N-ARY SQUARE INTERSECTION OPERATOR;Sm;0;ON;;;;;N;;;;; +2A06;N-ARY SQUARE UNION OPERATOR;Sm;0;ON;;;;;N;;;;; +2A07;TWO LOGICAL AND OPERATOR;Sm;0;ON;;;;;N;;;;; +2A08;TWO LOGICAL OR OPERATOR;Sm;0;ON;;;;;N;;;;; +2A09;N-ARY TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; +2A0A;MODULO TWO SUM;Sm;0;ON;;;;;Y;;;;; +2A0B;SUMMATION WITH INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2A0C;QUADRUPLE INTEGRAL OPERATOR;Sm;0;ON;<compat> 222B 222B 222B 222B;;;;Y;;;;; +2A0D;FINITE PART INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2A0E;INTEGRAL WITH DOUBLE STROKE;Sm;0;ON;;;;;Y;;;;; +2A0F;INTEGRAL AVERAGE WITH SLASH;Sm;0;ON;;;;;Y;;;;; +2A10;CIRCULATION FUNCTION;Sm;0;ON;;;;;Y;;;;; +2A11;ANTICLOCKWISE INTEGRATION;Sm;0;ON;;;;;Y;;;;; +2A12;LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; +2A13;LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; +2A14;LINE INTEGRATION NOT INCLUDING THE POLE;Sm;0;ON;;;;;Y;;;;; +2A15;INTEGRAL AROUND A POINT OPERATOR;Sm;0;ON;;;;;Y;;;;; +2A16;QUATERNION INTEGRAL OPERATOR;Sm;0;ON;;;;;Y;;;;; +2A17;INTEGRAL WITH LEFTWARDS ARROW WITH HOOK;Sm;0;ON;;;;;Y;;;;; +2A18;INTEGRAL WITH TIMES SIGN;Sm;0;ON;;;;;Y;;;;; +2A19;INTEGRAL WITH INTERSECTION;Sm;0;ON;;;;;Y;;;;; +2A1A;INTEGRAL WITH UNION;Sm;0;ON;;;;;Y;;;;; +2A1B;INTEGRAL WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +2A1C;INTEGRAL WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +2A1D;JOIN;Sm;0;ON;;;;;N;;;;; +2A1E;LARGE LEFT TRIANGLE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2A1F;Z NOTATION SCHEMA COMPOSITION;Sm;0;ON;;;;;Y;;;;; +2A20;Z NOTATION SCHEMA PIPING;Sm;0;ON;;;;;Y;;;;; +2A21;Z NOTATION SCHEMA PROJECTION;Sm;0;ON;;;;;Y;;;;; +2A22;PLUS SIGN WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; +2A23;PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE;Sm;0;ON;;;;;N;;;;; +2A24;PLUS SIGN WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; +2A25;PLUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; +2A26;PLUS SIGN WITH TILDE BELOW;Sm;0;ON;;;;;Y;;;;; +2A27;PLUS SIGN WITH SUBSCRIPT TWO;Sm;0;ON;;;;;N;;;;; +2A28;PLUS SIGN WITH BLACK TRIANGLE;Sm;0;ON;;;;;N;;;;; +2A29;MINUS SIGN WITH COMMA ABOVE;Sm;0;ON;;;;;Y;;;;; +2A2A;MINUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; +2A2B;MINUS SIGN WITH FALLING DOTS;Sm;0;ON;;;;;Y;;;;; +2A2C;MINUS SIGN WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; +2A2D;PLUS SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; +2A2E;PLUS SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; +2A2F;VECTOR OR CROSS PRODUCT;Sm;0;ON;;;;;N;;;;; +2A30;MULTIPLICATION SIGN WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +2A31;MULTIPLICATION SIGN WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A32;SEMIDIRECT PRODUCT WITH BOTTOM CLOSED;Sm;0;ON;;;;;N;;;;; +2A33;SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; +2A34;MULTIPLICATION SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; +2A35;MULTIPLICATION SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; +2A36;CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;N;;;;; +2A37;MULTIPLICATION SIGN IN DOUBLE CIRCLE;Sm;0;ON;;;;;N;;;;; +2A38;CIRCLED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; +2A39;PLUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; +2A3A;MINUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; +2A3B;MULTIPLICATION SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; +2A3C;INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; +2A3D;RIGHTHAND INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; +2A3E;Z NOTATION RELATIONAL COMPOSITION;Sm;0;ON;;;;;Y;;;;; +2A3F;AMALGAMATION OR COPRODUCT;Sm;0;ON;;;;;N;;;;; +2A40;INTERSECTION WITH DOT;Sm;0;ON;;;;;N;;;;; +2A41;UNION WITH MINUS SIGN;Sm;0;ON;;;;;N;;;;; +2A42;UNION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; +2A43;INTERSECTION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; +2A44;INTERSECTION WITH LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2A45;UNION WITH LOGICAL OR;Sm;0;ON;;;;;N;;;;; +2A46;UNION ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; +2A47;INTERSECTION ABOVE UNION;Sm;0;ON;;;;;N;;;;; +2A48;UNION ABOVE BAR ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; +2A49;INTERSECTION ABOVE BAR ABOVE UNION;Sm;0;ON;;;;;N;;;;; +2A4A;UNION BESIDE AND JOINED WITH UNION;Sm;0;ON;;;;;N;;;;; +2A4B;INTERSECTION BESIDE AND JOINED WITH INTERSECTION;Sm;0;ON;;;;;N;;;;; +2A4C;CLOSED UNION WITH SERIFS;Sm;0;ON;;;;;N;;;;; +2A4D;CLOSED INTERSECTION WITH SERIFS;Sm;0;ON;;;;;N;;;;; +2A4E;DOUBLE SQUARE INTERSECTION;Sm;0;ON;;;;;N;;;;; +2A4F;DOUBLE SQUARE UNION;Sm;0;ON;;;;;N;;;;; +2A50;CLOSED UNION WITH SERIFS AND SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; +2A51;LOGICAL AND WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +2A52;LOGICAL OR WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +2A53;DOUBLE LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2A54;DOUBLE LOGICAL OR;Sm;0;ON;;;;;N;;;;; +2A55;TWO INTERSECTING LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2A56;TWO INTERSECTING LOGICAL OR;Sm;0;ON;;;;;N;;;;; +2A57;SLOPING LARGE OR;Sm;0;ON;;;;;Y;;;;; +2A58;SLOPING LARGE AND;Sm;0;ON;;;;;Y;;;;; +2A59;LOGICAL OR OVERLAPPING LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2A5A;LOGICAL AND WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; +2A5B;LOGICAL OR WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; +2A5C;LOGICAL AND WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; +2A5D;LOGICAL OR WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; +2A5E;LOGICAL AND WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; +2A5F;LOGICAL AND WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A60;LOGICAL AND WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A61;SMALL VEE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A62;LOGICAL OR WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; +2A63;LOGICAL OR WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A64;Z NOTATION DOMAIN ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; +2A65;Z NOTATION RANGE ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; +2A66;EQUALS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; +2A67;IDENTICAL WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +2A68;TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2A69;TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2A6A;TILDE OPERATOR WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2A6B;TILDE OPERATOR WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; +2A6C;SIMILAR MINUS SIMILAR;Sm;0;ON;;;;;Y;;;;; +2A6D;CONGRUENT WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2A6E;EQUALS WITH ASTERISK;Sm;0;ON;;;;;N;;;;; +2A6F;ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;Y;;;;; +2A70;APPROXIMATELY EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A71;EQUALS SIGN ABOVE PLUS SIGN;Sm;0;ON;;;;;N;;;;; +2A72;PLUS SIGN ABOVE EQUALS SIGN;Sm;0;ON;;;;;N;;;;; +2A73;EQUALS SIGN ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2A74;DOUBLE COLON EQUAL;Sm;0;ON;<compat> 003A 003A 003D;;;;Y;;;;; +2A75;TWO CONSECUTIVE EQUALS SIGNS;Sm;0;ON;<compat> 003D 003D;;;;N;;;;; +2A76;THREE CONSECUTIVE EQUALS SIGNS;Sm;0;ON;<compat> 003D 003D 003D;;;;N;;;;; +2A77;EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW;Sm;0;ON;;;;;N;;;;; +2A78;EQUIVALENT WITH FOUR DOTS ABOVE;Sm;0;ON;;;;;N;;;;; +2A79;LESS-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; +2A7A;GREATER-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; +2A7B;LESS-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; +2A7C;GREATER-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; +2A7D;LESS-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A7E;GREATER-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A7F;LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; +2A80;GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; +2A81;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2A82;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2A83;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT;Sm;0;ON;;;;;Y;;;;; +2A84;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT;Sm;0;ON;;;;;Y;;;;; +2A85;LESS-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; +2A86;GREATER-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; +2A87;LESS-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A88;GREATER-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A89;LESS-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; +2A8A;GREATER-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; +2A8B;LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A8C;GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A8D;LESS-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; +2A8E;GREATER-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; +2A8F;LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A90;GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A91;LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; +2A92;GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; +2A93;LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; +2A94;GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; +2A95;SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A96;SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A97;SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; +2A98;SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; +2A99;DOUBLE-LINE EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A9A;DOUBLE-LINE EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A9B;DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A9C;DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A9D;SIMILAR OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A9E;SIMILAR OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A9F;SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AA0;SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AA1;DOUBLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2AA2;DOUBLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2AA3;DOUBLE NESTED LESS-THAN WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +2AA4;GREATER-THAN OVERLAPPING LESS-THAN;Sm;0;ON;;;;;N;;;;; +2AA5;GREATER-THAN BESIDE LESS-THAN;Sm;0;ON;;;;;N;;;;; +2AA6;LESS-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; +2AA7;GREATER-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; +2AA8;LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; +2AA9;GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; +2AAA;SMALLER THAN;Sm;0;ON;;;;;Y;;;;; +2AAB;LARGER THAN;Sm;0;ON;;;;;Y;;;;; +2AAC;SMALLER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AAD;LARGER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AAE;EQUALS SIGN WITH BUMPY ABOVE;Sm;0;ON;;;;;N;;;;; +2AAF;PRECEDES ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AB0;SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AB1;PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB2;SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB3;PRECEDES ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AB4;SUCCEEDS ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AB5;PRECEDES ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB6;SUCCEEDS ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB7;PRECEDES ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB8;SUCCEEDS ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB9;PRECEDES ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ABA;SUCCEEDS ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ABB;DOUBLE PRECEDES;Sm;0;ON;;;;;Y;;;;; +2ABC;DOUBLE SUCCEEDS;Sm;0;ON;;;;;Y;;;;; +2ABD;SUBSET WITH DOT;Sm;0;ON;;;;;Y;;;;; +2ABE;SUPERSET WITH DOT;Sm;0;ON;;;;;Y;;;;; +2ABF;SUBSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; +2AC0;SUPERSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; +2AC1;SUBSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; +2AC2;SUPERSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; +2AC3;SUBSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2AC4;SUPERSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2AC5;SUBSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AC6;SUPERSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AC7;SUBSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2AC8;SUPERSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2AC9;SUBSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ACA;SUPERSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ACB;SUBSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ACC;SUPERSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ACD;SQUARE LEFT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; +2ACE;SQUARE RIGHT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; +2ACF;CLOSED SUBSET;Sm;0;ON;;;;;Y;;;;; +2AD0;CLOSED SUPERSET;Sm;0;ON;;;;;Y;;;;; +2AD1;CLOSED SUBSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AD2;CLOSED SUPERSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AD3;SUBSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; +2AD4;SUPERSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; +2AD5;SUBSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; +2AD6;SUPERSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; +2AD7;SUPERSET BESIDE SUBSET;Sm;0;ON;;;;;N;;;;; +2AD8;SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET;Sm;0;ON;;;;;N;;;;; +2AD9;ELEMENT OF OPENING DOWNWARDS;Sm;0;ON;;;;;N;;;;; +2ADA;PITCHFORK WITH TEE TOP;Sm;0;ON;;;;;N;;;;; +2ADB;TRANSVERSAL INTERSECTION;Sm;0;ON;;;;;N;;;;; +2ADC;FORKING;Sm;0;ON;2ADD 0338;;;;Y;;;;; +2ADD;NONFORKING;Sm;0;ON;;;;;N;;;;; +2ADE;SHORT LEFT TACK;Sm;0;ON;;;;;Y;;;;; +2ADF;SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; +2AE0;SHORT UP TACK;Sm;0;ON;;;;;N;;;;; +2AE1;PERPENDICULAR WITH S;Sm;0;ON;;;;;N;;;;; +2AE2;VERTICAL BAR TRIPLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +2AE3;DOUBLE VERTICAL BAR LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +2AE4;VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +2AE5;DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +2AE6;LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL;Sm;0;ON;;;;;Y;;;;; +2AE7;SHORT DOWN TACK WITH OVERBAR;Sm;0;ON;;;;;N;;;;; +2AE8;SHORT UP TACK WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +2AE9;SHORT UP TACK ABOVE SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; +2AEA;DOUBLE DOWN TACK;Sm;0;ON;;;;;N;;;;; +2AEB;DOUBLE UP TACK;Sm;0;ON;;;;;N;;;;; +2AEC;DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; +2AED;REVERSED DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; +2AEE;DOES NOT DIVIDE WITH REVERSED NEGATION SLASH;Sm;0;ON;;;;;Y;;;;; +2AEF;VERTICAL LINE WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; +2AF0;VERTICAL LINE WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; +2AF1;DOWN TACK WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; +2AF2;PARALLEL WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +2AF3;PARALLEL WITH TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2AF4;TRIPLE VERTICAL BAR BINARY RELATION;Sm;0;ON;;;;;N;;;;; +2AF5;TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +2AF6;TRIPLE COLON OPERATOR;Sm;0;ON;;;;;N;;;;; +2AF7;TRIPLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2AF8;TRIPLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2AF9;DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AFA;DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AFB;TRIPLE SOLIDUS BINARY RELATION;Sm;0;ON;;;;;Y;;;;; +2AFC;LARGE TRIPLE VERTICAL BAR OPERATOR;Sm;0;ON;;;;;N;;;;; +2AFD;DOUBLE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; +2AFE;WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +2AFF;N-ARY WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +2B00;NORTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; +2B01;NORTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; +2B02;SOUTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; +2B03;SOUTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; +2B04;LEFT RIGHT WHITE ARROW;So;0;ON;;;;;N;;;;; +2B05;LEFTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; +2B06;UPWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; +2B07;DOWNWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; +2B08;NORTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; +2B09;NORTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0A;SOUTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0B;SOUTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0C;LEFT RIGHT BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0D;UP DOWN BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0E;RIGHTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; +2B0F;RIGHTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; +2B10;LEFTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; +2B11;LEFTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; +2B12;SQUARE WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; +2B13;SQUARE WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; +2B14;SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; +2B15;SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; +2B16;DIAMOND WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; +2B17;DIAMOND WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; +2B18;DIAMOND WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; +2B19;DIAMOND WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; +2B1A;DOTTED SQUARE;So;0;ON;;;;;N;;;;; +2B1B;BLACK LARGE SQUARE;So;0;ON;;;;;N;;;;; +2B1C;WHITE LARGE SQUARE;So;0;ON;;;;;N;;;;; +2B1D;BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; +2B1E;WHITE VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; +2B1F;BLACK PENTAGON;So;0;ON;;;;;N;;;;; +2B20;WHITE PENTAGON;So;0;ON;;;;;N;;;;; +2B21;WHITE HEXAGON;So;0;ON;;;;;N;;;;; +2B22;BLACK HEXAGON;So;0;ON;;;;;N;;;;; +2B23;HORIZONTAL BLACK HEXAGON;So;0;ON;;;;;N;;;;; +2B24;BLACK LARGE CIRCLE;So;0;ON;;;;;N;;;;; +2B25;BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; +2B26;WHITE MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; +2B27;BLACK MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; +2B28;WHITE MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; +2B29;BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; +2B2A;BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; +2B2B;WHITE SMALL LOZENGE;So;0;ON;;;;;N;;;;; +2B2C;BLACK HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; +2B2D;WHITE HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; +2B2E;BLACK VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; +2B2F;WHITE VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; +2B30;LEFT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +2B31;THREE LEFTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; +2B32;LEFT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; +2B33;LONG LEFTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; +2B34;LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B35;LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B36;LEFTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +2B37;LEFTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +2B38;LEFTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; +2B39;LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B3A;LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B3B;LEFTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; +2B3C;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B3D;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B3E;LEFTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; +2B3F;WAVE ARROW POINTING DIRECTLY LEFT;Sm;0;ON;;;;;N;;;;; +2B40;EQUALS SIGN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2B41;REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2B42;LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; +2B43;RIGHTWARDS ARROW THROUGH GREATER-THAN;Sm;0;ON;;;;;N;;;;; +2B44;RIGHTWARDS ARROW THROUGH SUPERSET;Sm;0;ON;;;;;N;;;;; +2B45;LEFTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; +2B46;RIGHTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; +2B47;REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2B48;RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; +2B49;TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2B4A;LEFTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; +2B4B;LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; +2B4C;RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; +2B4D;DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW;So;0;ON;;;;;N;;;;; +2B4E;SHORT SLANTED NORTH ARROW;So;0;ON;;;;;N;;;;; +2B4F;SHORT BACKSLANTED SOUTH ARROW;So;0;ON;;;;;N;;;;; +2B50;WHITE MEDIUM STAR;So;0;ON;;;;;N;;;;; +2B51;BLACK SMALL STAR;So;0;ON;;;;;N;;;;; +2B52;WHITE SMALL STAR;So;0;ON;;;;;N;;;;; +2B53;BLACK RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; +2B54;WHITE RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; +2B55;HEAVY LARGE CIRCLE;So;0;ON;;;;;N;;;;; +2B56;HEAVY OVAL WITH OVAL INSIDE;So;0;ON;;;;;N;;;;; +2B57;HEAVY CIRCLE WITH CIRCLE INSIDE;So;0;ON;;;;;N;;;;; +2B58;HEAVY CIRCLE;So;0;ON;;;;;N;;;;; +2B59;HEAVY CIRCLED SALTIRE;So;0;ON;;;;;N;;;;; +2B5A;SLANTED NORTH ARROW WITH HOOKED HEAD;So;0;ON;;;;;N;;;;; +2B5B;BACKSLANTED SOUTH ARROW WITH HOOKED TAIL;So;0;ON;;;;;N;;;;; +2B5C;SLANTED NORTH ARROW WITH HORIZONTAL TAIL;So;0;ON;;;;;N;;;;; +2B5D;BACKSLANTED SOUTH ARROW WITH HORIZONTAL TAIL;So;0;ON;;;;;N;;;;; +2B5E;BENT ARROW POINTING DOWNWARDS THEN NORTH EAST;So;0;ON;;;;;N;;;;; +2B5F;SHORT BENT ARROW POINTING DOWNWARDS THEN NORTH EAST;So;0;ON;;;;;N;;;;; +2B60;LEFTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B61;UPWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B62;RIGHTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B63;DOWNWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B64;LEFT RIGHT TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B65;UP DOWN TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B66;NORTH WEST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B67;NORTH EAST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B68;SOUTH EAST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B69;SOUTH WEST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B6A;LEFTWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; +2B6B;UPWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; +2B6C;RIGHTWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; +2B6D;DOWNWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; +2B6E;CLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; +2B6F;ANTICLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; +2B70;LEFTWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B71;UPWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B72;RIGHTWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B73;DOWNWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B76;NORTH WEST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B77;NORTH EAST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B78;SOUTH EAST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B79;SOUTH WEST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B7A;LEFTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; +2B7B;UPWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; +2B7C;RIGHTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; +2B7D;DOWNWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; +2B7E;HORIZONTAL TAB KEY;So;0;ON;;;;;N;;;;; +2B7F;VERTICAL TAB KEY;So;0;ON;;;;;N;;;;; +2B80;LEFTWARDS TRIANGLE-HEADED ARROW OVER RIGHTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B81;UPWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF DOWNWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B82;RIGHTWARDS TRIANGLE-HEADED ARROW OVER LEFTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B83;DOWNWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF UPWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B84;LEFTWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; +2B85;UPWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; +2B86;RIGHTWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; +2B87;DOWNWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; +2B88;LEFTWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; +2B89;UPWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; +2B8A;RIGHTWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; +2B8B;DOWNWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; +2B8C;ANTICLOCKWISE TRIANGLE-HEADED RIGHT U-SHAPED ARROW;So;0;ON;;;;;N;;;;; +2B8D;ANTICLOCKWISE TRIANGLE-HEADED BOTTOM U-SHAPED ARROW;So;0;ON;;;;;N;;;;; +2B8E;ANTICLOCKWISE TRIANGLE-HEADED LEFT U-SHAPED ARROW;So;0;ON;;;;;N;;;;; +2B8F;ANTICLOCKWISE TRIANGLE-HEADED TOP U-SHAPED ARROW;So;0;ON;;;;;N;;;;; +2B90;RETURN LEFT;So;0;ON;;;;;N;;;;; +2B91;RETURN RIGHT;So;0;ON;;;;;N;;;;; +2B92;NEWLINE LEFT;So;0;ON;;;;;N;;;;; +2B93;NEWLINE RIGHT;So;0;ON;;;;;N;;;;; +2B94;FOUR CORNER ARROWS CIRCLING ANTICLOCKWISE;So;0;ON;;;;;N;;;;; +2B95;RIGHTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; +2B98;THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B99;THREE-D RIGHT-LIGHTED UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9A;THREE-D TOP-LIGHTED RIGHTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9B;THREE-D LEFT-LIGHTED DOWNWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9C;BLACK LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9D;BLACK UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9E;BLACK RIGHTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9F;BLACK DOWNWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2BA0;DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS;So;0;ON;;;;;N;;;;; +2BA1;DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS;So;0;ON;;;;;N;;;;; +2BA2;UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS;So;0;ON;;;;;N;;;;; +2BA3;UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS;So;0;ON;;;;;N;;;;; +2BA4;LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS;So;0;ON;;;;;N;;;;; +2BA5;RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS;So;0;ON;;;;;N;;;;; +2BA6;LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS;So;0;ON;;;;;N;;;;; +2BA7;RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS;So;0;ON;;;;;N;;;;; +2BA8;BLACK CURVED DOWNWARDS AND LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; +2BA9;BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAA;BLACK CURVED UPWARDS AND LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAB;BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAC;BLACK CURVED LEFTWARDS AND UPWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAD;BLACK CURVED RIGHTWARDS AND UPWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAE;BLACK CURVED LEFTWARDS AND DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAF;BLACK CURVED RIGHTWARDS AND DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; +2BB0;RIBBON ARROW DOWN LEFT;So;0;ON;;;;;N;;;;; +2BB1;RIBBON ARROW DOWN RIGHT;So;0;ON;;;;;N;;;;; +2BB2;RIBBON ARROW UP LEFT;So;0;ON;;;;;N;;;;; +2BB3;RIBBON ARROW UP RIGHT;So;0;ON;;;;;N;;;;; +2BB4;RIBBON ARROW LEFT UP;So;0;ON;;;;;N;;;;; +2BB5;RIBBON ARROW RIGHT UP;So;0;ON;;;;;N;;;;; +2BB6;RIBBON ARROW LEFT DOWN;So;0;ON;;;;;N;;;;; +2BB7;RIBBON ARROW RIGHT DOWN;So;0;ON;;;;;N;;;;; +2BB8;UPWARDS WHITE ARROW FROM BAR WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; +2BB9;UP ARROWHEAD IN A RECTANGLE BOX;So;0;ON;;;;;N;;;;; +2BBD;BALLOT BOX WITH LIGHT X;So;0;ON;;;;;N;;;;; +2BBE;CIRCLED X;So;0;ON;;;;;N;;;;; +2BBF;CIRCLED BOLD X;So;0;ON;;;;;N;;;;; +2BC0;BLACK SQUARE CENTRED;So;0;ON;;;;;N;;;;; +2BC1;BLACK DIAMOND CENTRED;So;0;ON;;;;;N;;;;; +2BC2;TURNED BLACK PENTAGON;So;0;ON;;;;;N;;;;; +2BC3;HORIZONTAL BLACK OCTAGON;So;0;ON;;;;;N;;;;; +2BC4;BLACK OCTAGON;So;0;ON;;;;;N;;;;; +2BC5;BLACK MEDIUM UP-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; +2BC6;BLACK MEDIUM DOWN-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; +2BC7;BLACK MEDIUM LEFT-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; +2BC8;BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; +2BCA;TOP HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +2BCB;BOTTOM HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +2BCC;LIGHT FOUR POINTED BLACK CUSP;So;0;ON;;;;;N;;;;; +2BCD;ROTATED LIGHT FOUR POINTED BLACK CUSP;So;0;ON;;;;;N;;;;; +2BCE;WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; +2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; +2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;; +2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;; +2BD2;GROUP MARK;So;0;ON;;;;;N;;;;; +2BEC;LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; +2BED;UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; +2BEE;RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; +2BEF;DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; +2C00;GLAGOLITIC CAPITAL LETTER AZU;Lu;0;L;;;;;N;;;;2C30; +2C01;GLAGOLITIC CAPITAL LETTER BUKY;Lu;0;L;;;;;N;;;;2C31; +2C02;GLAGOLITIC CAPITAL LETTER VEDE;Lu;0;L;;;;;N;;;;2C32; +2C03;GLAGOLITIC CAPITAL LETTER GLAGOLI;Lu;0;L;;;;;N;;;;2C33; +2C04;GLAGOLITIC CAPITAL LETTER DOBRO;Lu;0;L;;;;;N;;;;2C34; +2C05;GLAGOLITIC CAPITAL LETTER YESTU;Lu;0;L;;;;;N;;;;2C35; +2C06;GLAGOLITIC CAPITAL LETTER ZHIVETE;Lu;0;L;;;;;N;;;;2C36; +2C07;GLAGOLITIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;2C37; +2C08;GLAGOLITIC CAPITAL LETTER ZEMLJA;Lu;0;L;;;;;N;;;;2C38; +2C09;GLAGOLITIC CAPITAL LETTER IZHE;Lu;0;L;;;;;N;;;;2C39; +2C0A;GLAGOLITIC CAPITAL LETTER INITIAL IZHE;Lu;0;L;;;;;N;;;;2C3A; +2C0B;GLAGOLITIC CAPITAL LETTER I;Lu;0;L;;;;;N;;;;2C3B; +2C0C;GLAGOLITIC CAPITAL LETTER DJERVI;Lu;0;L;;;;;N;;;;2C3C; +2C0D;GLAGOLITIC CAPITAL LETTER KAKO;Lu;0;L;;;;;N;;;;2C3D; +2C0E;GLAGOLITIC CAPITAL LETTER LJUDIJE;Lu;0;L;;;;;N;;;;2C3E; +2C0F;GLAGOLITIC CAPITAL LETTER MYSLITE;Lu;0;L;;;;;N;;;;2C3F; +2C10;GLAGOLITIC CAPITAL LETTER NASHI;Lu;0;L;;;;;N;;;;2C40; +2C11;GLAGOLITIC CAPITAL LETTER ONU;Lu;0;L;;;;;N;;;;2C41; +2C12;GLAGOLITIC CAPITAL LETTER POKOJI;Lu;0;L;;;;;N;;;;2C42; +2C13;GLAGOLITIC CAPITAL LETTER RITSI;Lu;0;L;;;;;N;;;;2C43; +2C14;GLAGOLITIC CAPITAL LETTER SLOVO;Lu;0;L;;;;;N;;;;2C44; +2C15;GLAGOLITIC CAPITAL LETTER TVRIDO;Lu;0;L;;;;;N;;;;2C45; +2C16;GLAGOLITIC CAPITAL LETTER UKU;Lu;0;L;;;;;N;;;;2C46; +2C17;GLAGOLITIC CAPITAL LETTER FRITU;Lu;0;L;;;;;N;;;;2C47; +2C18;GLAGOLITIC CAPITAL LETTER HERU;Lu;0;L;;;;;N;;;;2C48; +2C19;GLAGOLITIC CAPITAL LETTER OTU;Lu;0;L;;;;;N;;;;2C49; +2C1A;GLAGOLITIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;2C4A; +2C1B;GLAGOLITIC CAPITAL LETTER SHTA;Lu;0;L;;;;;N;;;;2C4B; +2C1C;GLAGOLITIC CAPITAL LETTER TSI;Lu;0;L;;;;;N;;;;2C4C; +2C1D;GLAGOLITIC CAPITAL LETTER CHRIVI;Lu;0;L;;;;;N;;;;2C4D; +2C1E;GLAGOLITIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;2C4E; +2C1F;GLAGOLITIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;;;;2C4F; +2C20;GLAGOLITIC CAPITAL LETTER YERI;Lu;0;L;;;;;N;;;;2C50; +2C21;GLAGOLITIC CAPITAL LETTER YATI;Lu;0;L;;;;;N;;;;2C51; +2C22;GLAGOLITIC CAPITAL LETTER SPIDERY HA;Lu;0;L;;;;;N;;;;2C52; +2C23;GLAGOLITIC CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;2C53; +2C24;GLAGOLITIC CAPITAL LETTER SMALL YUS;Lu;0;L;;;;;N;;;;2C54; +2C25;GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL;Lu;0;L;;;;;N;;;;2C55; +2C26;GLAGOLITIC CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;2C56; +2C27;GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS;Lu;0;L;;;;;N;;;;2C57; +2C28;GLAGOLITIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;2C58; +2C29;GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS;Lu;0;L;;;;;N;;;;2C59; +2C2A;GLAGOLITIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;2C5A; +2C2B;GLAGOLITIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;2C5B; +2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C; +2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D; +2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E; +2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00 +2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01 +2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02 +2C33;GLAGOLITIC SMALL LETTER GLAGOLI;Ll;0;L;;;;;N;;;2C03;;2C03 +2C34;GLAGOLITIC SMALL LETTER DOBRO;Ll;0;L;;;;;N;;;2C04;;2C04 +2C35;GLAGOLITIC SMALL LETTER YESTU;Ll;0;L;;;;;N;;;2C05;;2C05 +2C36;GLAGOLITIC SMALL LETTER ZHIVETE;Ll;0;L;;;;;N;;;2C06;;2C06 +2C37;GLAGOLITIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;2C07;;2C07 +2C38;GLAGOLITIC SMALL LETTER ZEMLJA;Ll;0;L;;;;;N;;;2C08;;2C08 +2C39;GLAGOLITIC SMALL LETTER IZHE;Ll;0;L;;;;;N;;;2C09;;2C09 +2C3A;GLAGOLITIC SMALL LETTER INITIAL IZHE;Ll;0;L;;;;;N;;;2C0A;;2C0A +2C3B;GLAGOLITIC SMALL LETTER I;Ll;0;L;;;;;N;;;2C0B;;2C0B +2C3C;GLAGOLITIC SMALL LETTER DJERVI;Ll;0;L;;;;;N;;;2C0C;;2C0C +2C3D;GLAGOLITIC SMALL LETTER KAKO;Ll;0;L;;;;;N;;;2C0D;;2C0D +2C3E;GLAGOLITIC SMALL LETTER LJUDIJE;Ll;0;L;;;;;N;;;2C0E;;2C0E +2C3F;GLAGOLITIC SMALL LETTER MYSLITE;Ll;0;L;;;;;N;;;2C0F;;2C0F +2C40;GLAGOLITIC SMALL LETTER NASHI;Ll;0;L;;;;;N;;;2C10;;2C10 +2C41;GLAGOLITIC SMALL LETTER ONU;Ll;0;L;;;;;N;;;2C11;;2C11 +2C42;GLAGOLITIC SMALL LETTER POKOJI;Ll;0;L;;;;;N;;;2C12;;2C12 +2C43;GLAGOLITIC SMALL LETTER RITSI;Ll;0;L;;;;;N;;;2C13;;2C13 +2C44;GLAGOLITIC SMALL LETTER SLOVO;Ll;0;L;;;;;N;;;2C14;;2C14 +2C45;GLAGOLITIC SMALL LETTER TVRIDO;Ll;0;L;;;;;N;;;2C15;;2C15 +2C46;GLAGOLITIC SMALL LETTER UKU;Ll;0;L;;;;;N;;;2C16;;2C16 +2C47;GLAGOLITIC SMALL LETTER FRITU;Ll;0;L;;;;;N;;;2C17;;2C17 +2C48;GLAGOLITIC SMALL LETTER HERU;Ll;0;L;;;;;N;;;2C18;;2C18 +2C49;GLAGOLITIC SMALL LETTER OTU;Ll;0;L;;;;;N;;;2C19;;2C19 +2C4A;GLAGOLITIC SMALL LETTER PE;Ll;0;L;;;;;N;;;2C1A;;2C1A +2C4B;GLAGOLITIC SMALL LETTER SHTA;Ll;0;L;;;;;N;;;2C1B;;2C1B +2C4C;GLAGOLITIC SMALL LETTER TSI;Ll;0;L;;;;;N;;;2C1C;;2C1C +2C4D;GLAGOLITIC SMALL LETTER CHRIVI;Ll;0;L;;;;;N;;;2C1D;;2C1D +2C4E;GLAGOLITIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;2C1E;;2C1E +2C4F;GLAGOLITIC SMALL LETTER YERU;Ll;0;L;;;;;N;;;2C1F;;2C1F +2C50;GLAGOLITIC SMALL LETTER YERI;Ll;0;L;;;;;N;;;2C20;;2C20 +2C51;GLAGOLITIC SMALL LETTER YATI;Ll;0;L;;;;;N;;;2C21;;2C21 +2C52;GLAGOLITIC SMALL LETTER SPIDERY HA;Ll;0;L;;;;;N;;;2C22;;2C22 +2C53;GLAGOLITIC SMALL LETTER YU;Ll;0;L;;;;;N;;;2C23;;2C23 +2C54;GLAGOLITIC SMALL LETTER SMALL YUS;Ll;0;L;;;;;N;;;2C24;;2C24 +2C55;GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL;Ll;0;L;;;;;N;;;2C25;;2C25 +2C56;GLAGOLITIC SMALL LETTER YO;Ll;0;L;;;;;N;;;2C26;;2C26 +2C57;GLAGOLITIC SMALL LETTER IOTATED SMALL YUS;Ll;0;L;;;;;N;;;2C27;;2C27 +2C58;GLAGOLITIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;2C28;;2C28 +2C59;GLAGOLITIC SMALL LETTER IOTATED BIG YUS;Ll;0;L;;;;;N;;;2C29;;2C29 +2C5A;GLAGOLITIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;2C2A;;2C2A +2C5B;GLAGOLITIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;2C2B;;2C2B +2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C +2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D +2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E +2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61; +2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60 +2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B; +2C63;LATIN CAPITAL LETTER P WITH STROKE;Lu;0;L;;;;;N;;;;1D7D; +2C64;LATIN CAPITAL LETTER R WITH TAIL;Lu;0;L;;;;;N;;;;027D; +2C65;LATIN SMALL LETTER A WITH STROKE;Ll;0;L;;;;;N;;;023A;;023A +2C66;LATIN SMALL LETTER T WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;023E;;023E +2C67;LATIN CAPITAL LETTER H WITH DESCENDER;Lu;0;L;;;;;N;;;;2C68; +2C68;LATIN SMALL LETTER H WITH DESCENDER;Ll;0;L;;;;;N;;;2C67;;2C67 +2C69;LATIN CAPITAL LETTER K WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6A; +2C6A;LATIN SMALL LETTER K WITH DESCENDER;Ll;0;L;;;;;N;;;2C69;;2C69 +2C6B;LATIN CAPITAL LETTER Z WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6C; +2C6C;LATIN SMALL LETTER Z WITH DESCENDER;Ll;0;L;;;;;N;;;2C6B;;2C6B +2C6D;LATIN CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;0251; +2C6E;LATIN CAPITAL LETTER M WITH HOOK;Lu;0;L;;;;;N;;;;0271; +2C6F;LATIN CAPITAL LETTER TURNED A;Lu;0;L;;;;;N;;;;0250; +2C70;LATIN CAPITAL LETTER TURNED ALPHA;Lu;0;L;;;;;N;;;;0252; +2C71;LATIN SMALL LETTER V WITH RIGHT HOOK;Ll;0;L;;;;;N;;;;; +2C72;LATIN CAPITAL LETTER W WITH HOOK;Lu;0;L;;;;;N;;;;2C73; +2C73;LATIN SMALL LETTER W WITH HOOK;Ll;0;L;;;;;N;;;2C72;;2C72 +2C74;LATIN SMALL LETTER V WITH CURL;Ll;0;L;;;;;N;;;;; +2C75;LATIN CAPITAL LETTER HALF H;Lu;0;L;;;;;N;;;;2C76; +2C76;LATIN SMALL LETTER HALF H;Ll;0;L;;;;;N;;;2C75;;2C75 +2C77;LATIN SMALL LETTER TAILLESS PHI;Ll;0;L;;;;;N;;;;; +2C78;LATIN SMALL LETTER E WITH NOTCH;Ll;0;L;;;;;N;;;;; +2C79;LATIN SMALL LETTER TURNED R WITH TAIL;Ll;0;L;;;;;N;;;;; +2C7A;LATIN SMALL LETTER O WITH LOW RING INSIDE;Ll;0;L;;;;;N;;;;; +2C7B;LATIN LETTER SMALL CAPITAL TURNED E;Ll;0;L;;;;;N;;;;; +2C7C;LATIN SUBSCRIPT SMALL LETTER J;Lm;0;L;<sub> 006A;;;;N;;;;; +2C7D;MODIFIER LETTER CAPITAL V;Lm;0;L;<super> 0056;;;;N;;;;; +2C7E;LATIN CAPITAL LETTER S WITH SWASH TAIL;Lu;0;L;;;;;N;;;;023F; +2C7F;LATIN CAPITAL LETTER Z WITH SWASH TAIL;Lu;0;L;;;;;N;;;;0240; +2C80;COPTIC CAPITAL LETTER ALFA;Lu;0;L;;;;;N;;;;2C81; +2C81;COPTIC SMALL LETTER ALFA;Ll;0;L;;;;;N;;;2C80;;2C80 +2C82;COPTIC CAPITAL LETTER VIDA;Lu;0;L;;;;;N;;;;2C83; +2C83;COPTIC SMALL LETTER VIDA;Ll;0;L;;;;;N;;;2C82;;2C82 +2C84;COPTIC CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;2C85; +2C85;COPTIC SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;2C84;;2C84 +2C86;COPTIC CAPITAL LETTER DALDA;Lu;0;L;;;;;N;;;;2C87; +2C87;COPTIC SMALL LETTER DALDA;Ll;0;L;;;;;N;;;2C86;;2C86 +2C88;COPTIC CAPITAL LETTER EIE;Lu;0;L;;;;;N;;;;2C89; +2C89;COPTIC SMALL LETTER EIE;Ll;0;L;;;;;N;;;2C88;;2C88 +2C8A;COPTIC CAPITAL LETTER SOU;Lu;0;L;;;;;N;;;;2C8B; +2C8B;COPTIC SMALL LETTER SOU;Ll;0;L;;;;;N;;;2C8A;;2C8A +2C8C;COPTIC CAPITAL LETTER ZATA;Lu;0;L;;;;;N;;;;2C8D; +2C8D;COPTIC SMALL LETTER ZATA;Ll;0;L;;;;;N;;;2C8C;;2C8C +2C8E;COPTIC CAPITAL LETTER HATE;Lu;0;L;;;;;N;;;;2C8F; +2C8F;COPTIC SMALL LETTER HATE;Ll;0;L;;;;;N;;;2C8E;;2C8E +2C90;COPTIC CAPITAL LETTER THETHE;Lu;0;L;;;;;N;;;;2C91; +2C91;COPTIC SMALL LETTER THETHE;Ll;0;L;;;;;N;;;2C90;;2C90 +2C92;COPTIC CAPITAL LETTER IAUDA;Lu;0;L;;;;;N;;;;2C93; +2C93;COPTIC SMALL LETTER IAUDA;Ll;0;L;;;;;N;;;2C92;;2C92 +2C94;COPTIC CAPITAL LETTER KAPA;Lu;0;L;;;;;N;;;;2C95; +2C95;COPTIC SMALL LETTER KAPA;Ll;0;L;;;;;N;;;2C94;;2C94 +2C96;COPTIC CAPITAL LETTER LAULA;Lu;0;L;;;;;N;;;;2C97; +2C97;COPTIC SMALL LETTER LAULA;Ll;0;L;;;;;N;;;2C96;;2C96 +2C98;COPTIC CAPITAL LETTER MI;Lu;0;L;;;;;N;;;;2C99; +2C99;COPTIC SMALL LETTER MI;Ll;0;L;;;;;N;;;2C98;;2C98 +2C9A;COPTIC CAPITAL LETTER NI;Lu;0;L;;;;;N;;;;2C9B; +2C9B;COPTIC SMALL LETTER NI;Ll;0;L;;;;;N;;;2C9A;;2C9A +2C9C;COPTIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;2C9D; +2C9D;COPTIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;2C9C;;2C9C +2C9E;COPTIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;2C9F; +2C9F;COPTIC SMALL LETTER O;Ll;0;L;;;;;N;;;2C9E;;2C9E +2CA0;COPTIC CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;2CA1; +2CA1;COPTIC SMALL LETTER PI;Ll;0;L;;;;;N;;;2CA0;;2CA0 +2CA2;COPTIC CAPITAL LETTER RO;Lu;0;L;;;;;N;;;;2CA3; +2CA3;COPTIC SMALL LETTER RO;Ll;0;L;;;;;N;;;2CA2;;2CA2 +2CA4;COPTIC CAPITAL LETTER SIMA;Lu;0;L;;;;;N;;;;2CA5; +2CA5;COPTIC SMALL LETTER SIMA;Ll;0;L;;;;;N;;;2CA4;;2CA4 +2CA6;COPTIC CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;2CA7; +2CA7;COPTIC SMALL LETTER TAU;Ll;0;L;;;;;N;;;2CA6;;2CA6 +2CA8;COPTIC CAPITAL LETTER UA;Lu;0;L;;;;;N;;;;2CA9; +2CA9;COPTIC SMALL LETTER UA;Ll;0;L;;;;;N;;;2CA8;;2CA8 +2CAA;COPTIC CAPITAL LETTER FI;Lu;0;L;;;;;N;;;;2CAB; +2CAB;COPTIC SMALL LETTER FI;Ll;0;L;;;;;N;;;2CAA;;2CAA +2CAC;COPTIC CAPITAL LETTER KHI;Lu;0;L;;;;;N;;;;2CAD; +2CAD;COPTIC SMALL LETTER KHI;Ll;0;L;;;;;N;;;2CAC;;2CAC +2CAE;COPTIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;2CAF; +2CAF;COPTIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;2CAE;;2CAE +2CB0;COPTIC CAPITAL LETTER OOU;Lu;0;L;;;;;N;;;;2CB1; +2CB1;COPTIC SMALL LETTER OOU;Ll;0;L;;;;;N;;;2CB0;;2CB0 +2CB2;COPTIC CAPITAL LETTER DIALECT-P ALEF;Lu;0;L;;;;;N;;;;2CB3; +2CB3;COPTIC SMALL LETTER DIALECT-P ALEF;Ll;0;L;;;;;N;;;2CB2;;2CB2 +2CB4;COPTIC CAPITAL LETTER OLD COPTIC AIN;Lu;0;L;;;;;N;;;;2CB5; +2CB5;COPTIC SMALL LETTER OLD COPTIC AIN;Ll;0;L;;;;;N;;;2CB4;;2CB4 +2CB6;COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE;Lu;0;L;;;;;N;;;;2CB7; +2CB7;COPTIC SMALL LETTER CRYPTOGRAMMIC EIE;Ll;0;L;;;;;N;;;2CB6;;2CB6 +2CB8;COPTIC CAPITAL LETTER DIALECT-P KAPA;Lu;0;L;;;;;N;;;;2CB9; +2CB9;COPTIC SMALL LETTER DIALECT-P KAPA;Ll;0;L;;;;;N;;;2CB8;;2CB8 +2CBA;COPTIC CAPITAL LETTER DIALECT-P NI;Lu;0;L;;;;;N;;;;2CBB; +2CBB;COPTIC SMALL LETTER DIALECT-P NI;Ll;0;L;;;;;N;;;2CBA;;2CBA +2CBC;COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI;Lu;0;L;;;;;N;;;;2CBD; +2CBD;COPTIC SMALL LETTER CRYPTOGRAMMIC NI;Ll;0;L;;;;;N;;;2CBC;;2CBC +2CBE;COPTIC CAPITAL LETTER OLD COPTIC OOU;Lu;0;L;;;;;N;;;;2CBF; +2CBF;COPTIC SMALL LETTER OLD COPTIC OOU;Ll;0;L;;;;;N;;;2CBE;;2CBE +2CC0;COPTIC CAPITAL LETTER SAMPI;Lu;0;L;;;;;N;;;;2CC1; +2CC1;COPTIC SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;2CC0;;2CC0 +2CC2;COPTIC CAPITAL LETTER CROSSED SHEI;Lu;0;L;;;;;N;;;;2CC3; +2CC3;COPTIC SMALL LETTER CROSSED SHEI;Ll;0;L;;;;;N;;;2CC2;;2CC2 +2CC4;COPTIC CAPITAL LETTER OLD COPTIC SHEI;Lu;0;L;;;;;N;;;;2CC5; +2CC5;COPTIC SMALL LETTER OLD COPTIC SHEI;Ll;0;L;;;;;N;;;2CC4;;2CC4 +2CC6;COPTIC CAPITAL LETTER OLD COPTIC ESH;Lu;0;L;;;;;N;;;;2CC7; +2CC7;COPTIC SMALL LETTER OLD COPTIC ESH;Ll;0;L;;;;;N;;;2CC6;;2CC6 +2CC8;COPTIC CAPITAL LETTER AKHMIMIC KHEI;Lu;0;L;;;;;N;;;;2CC9; +2CC9;COPTIC SMALL LETTER AKHMIMIC KHEI;Ll;0;L;;;;;N;;;2CC8;;2CC8 +2CCA;COPTIC CAPITAL LETTER DIALECT-P HORI;Lu;0;L;;;;;N;;;;2CCB; +2CCB;COPTIC SMALL LETTER DIALECT-P HORI;Ll;0;L;;;;;N;;;2CCA;;2CCA +2CCC;COPTIC CAPITAL LETTER OLD COPTIC HORI;Lu;0;L;;;;;N;;;;2CCD; +2CCD;COPTIC SMALL LETTER OLD COPTIC HORI;Ll;0;L;;;;;N;;;2CCC;;2CCC +2CCE;COPTIC CAPITAL LETTER OLD COPTIC HA;Lu;0;L;;;;;N;;;;2CCF; +2CCF;COPTIC SMALL LETTER OLD COPTIC HA;Ll;0;L;;;;;N;;;2CCE;;2CCE +2CD0;COPTIC CAPITAL LETTER L-SHAPED HA;Lu;0;L;;;;;N;;;;2CD1; +2CD1;COPTIC SMALL LETTER L-SHAPED HA;Ll;0;L;;;;;N;;;2CD0;;2CD0 +2CD2;COPTIC CAPITAL LETTER OLD COPTIC HEI;Lu;0;L;;;;;N;;;;2CD3; +2CD3;COPTIC SMALL LETTER OLD COPTIC HEI;Ll;0;L;;;;;N;;;2CD2;;2CD2 +2CD4;COPTIC CAPITAL LETTER OLD COPTIC HAT;Lu;0;L;;;;;N;;;;2CD5; +2CD5;COPTIC SMALL LETTER OLD COPTIC HAT;Ll;0;L;;;;;N;;;2CD4;;2CD4 +2CD6;COPTIC CAPITAL LETTER OLD COPTIC GANGIA;Lu;0;L;;;;;N;;;;2CD7; +2CD7;COPTIC SMALL LETTER OLD COPTIC GANGIA;Ll;0;L;;;;;N;;;2CD6;;2CD6 +2CD8;COPTIC CAPITAL LETTER OLD COPTIC DJA;Lu;0;L;;;;;N;;;;2CD9; +2CD9;COPTIC SMALL LETTER OLD COPTIC DJA;Ll;0;L;;;;;N;;;2CD8;;2CD8 +2CDA;COPTIC CAPITAL LETTER OLD COPTIC SHIMA;Lu;0;L;;;;;N;;;;2CDB; +2CDB;COPTIC SMALL LETTER OLD COPTIC SHIMA;Ll;0;L;;;;;N;;;2CDA;;2CDA +2CDC;COPTIC CAPITAL LETTER OLD NUBIAN SHIMA;Lu;0;L;;;;;N;;;;2CDD; +2CDD;COPTIC SMALL LETTER OLD NUBIAN SHIMA;Ll;0;L;;;;;N;;;2CDC;;2CDC +2CDE;COPTIC CAPITAL LETTER OLD NUBIAN NGI;Lu;0;L;;;;;N;;;;2CDF; +2CDF;COPTIC SMALL LETTER OLD NUBIAN NGI;Ll;0;L;;;;;N;;;2CDE;;2CDE +2CE0;COPTIC CAPITAL LETTER OLD NUBIAN NYI;Lu;0;L;;;;;N;;;;2CE1; +2CE1;COPTIC SMALL LETTER OLD NUBIAN NYI;Ll;0;L;;;;;N;;;2CE0;;2CE0 +2CE2;COPTIC CAPITAL LETTER OLD NUBIAN WAU;Lu;0;L;;;;;N;;;;2CE3; +2CE3;COPTIC SMALL LETTER OLD NUBIAN WAU;Ll;0;L;;;;;N;;;2CE2;;2CE2 +2CE4;COPTIC SYMBOL KAI;Ll;0;L;;;;;N;;;;; +2CE5;COPTIC SYMBOL MI RO;So;0;ON;;;;;N;;;;; +2CE6;COPTIC SYMBOL PI RO;So;0;ON;;;;;N;;;;; +2CE7;COPTIC SYMBOL STAUROS;So;0;ON;;;;;N;;;;; +2CE8;COPTIC SYMBOL TAU RO;So;0;ON;;;;;N;;;;; +2CE9;COPTIC SYMBOL KHI RO;So;0;ON;;;;;N;;;;; +2CEA;COPTIC SYMBOL SHIMA SIMA;So;0;ON;;;;;N;;;;; +2CEB;COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI;Lu;0;L;;;;;N;;;;2CEC; +2CEC;COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI;Ll;0;L;;;;;N;;;2CEB;;2CEB +2CED;COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA;Lu;0;L;;;;;N;;;;2CEE; +2CEE;COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA;Ll;0;L;;;;;N;;;2CED;;2CED +2CEF;COPTIC COMBINING NI ABOVE;Mn;230;NSM;;;;;N;;;;; +2CF0;COPTIC COMBINING SPIRITUS ASPER;Mn;230;NSM;;;;;N;;;;; +2CF1;COPTIC COMBINING SPIRITUS LENIS;Mn;230;NSM;;;;;N;;;;; +2CF2;COPTIC CAPITAL LETTER BOHAIRIC KHEI;Lu;0;L;;;;;N;;;;2CF3; +2CF3;COPTIC SMALL LETTER BOHAIRIC KHEI;Ll;0;L;;;;;N;;;2CF2;;2CF2 +2CF9;COPTIC OLD NUBIAN FULL STOP;Po;0;ON;;;;;N;;;;; +2CFA;COPTIC OLD NUBIAN DIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; +2CFB;COPTIC OLD NUBIAN INDIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; +2CFC;COPTIC OLD NUBIAN VERSE DIVIDER;Po;0;ON;;;;;N;;;;; +2CFD;COPTIC FRACTION ONE HALF;No;0;ON;;;;1/2;N;;;;; +2CFE;COPTIC FULL STOP;Po;0;ON;;;;;N;;;;; +2CFF;COPTIC MORPHOLOGICAL DIVIDER;Po;0;ON;;;;;N;;;;; +2D00;GEORGIAN SMALL LETTER AN;Ll;0;L;;;;;N;;;10A0;;10A0 +2D01;GEORGIAN SMALL LETTER BAN;Ll;0;L;;;;;N;;;10A1;;10A1 +2D02;GEORGIAN SMALL LETTER GAN;Ll;0;L;;;;;N;;;10A2;;10A2 +2D03;GEORGIAN SMALL LETTER DON;Ll;0;L;;;;;N;;;10A3;;10A3 +2D04;GEORGIAN SMALL LETTER EN;Ll;0;L;;;;;N;;;10A4;;10A4 +2D05;GEORGIAN SMALL LETTER VIN;Ll;0;L;;;;;N;;;10A5;;10A5 +2D06;GEORGIAN SMALL LETTER ZEN;Ll;0;L;;;;;N;;;10A6;;10A6 +2D07;GEORGIAN SMALL LETTER TAN;Ll;0;L;;;;;N;;;10A7;;10A7 +2D08;GEORGIAN SMALL LETTER IN;Ll;0;L;;;;;N;;;10A8;;10A8 +2D09;GEORGIAN SMALL LETTER KAN;Ll;0;L;;;;;N;;;10A9;;10A9 +2D0A;GEORGIAN SMALL LETTER LAS;Ll;0;L;;;;;N;;;10AA;;10AA +2D0B;GEORGIAN SMALL LETTER MAN;Ll;0;L;;;;;N;;;10AB;;10AB +2D0C;GEORGIAN SMALL LETTER NAR;Ll;0;L;;;;;N;;;10AC;;10AC +2D0D;GEORGIAN SMALL LETTER ON;Ll;0;L;;;;;N;;;10AD;;10AD +2D0E;GEORGIAN SMALL LETTER PAR;Ll;0;L;;;;;N;;;10AE;;10AE +2D0F;GEORGIAN SMALL LETTER ZHAR;Ll;0;L;;;;;N;;;10AF;;10AF +2D10;GEORGIAN SMALL LETTER RAE;Ll;0;L;;;;;N;;;10B0;;10B0 +2D11;GEORGIAN SMALL LETTER SAN;Ll;0;L;;;;;N;;;10B1;;10B1 +2D12;GEORGIAN SMALL LETTER TAR;Ll;0;L;;;;;N;;;10B2;;10B2 +2D13;GEORGIAN SMALL LETTER UN;Ll;0;L;;;;;N;;;10B3;;10B3 +2D14;GEORGIAN SMALL LETTER PHAR;Ll;0;L;;;;;N;;;10B4;;10B4 +2D15;GEORGIAN SMALL LETTER KHAR;Ll;0;L;;;;;N;;;10B5;;10B5 +2D16;GEORGIAN SMALL LETTER GHAN;Ll;0;L;;;;;N;;;10B6;;10B6 +2D17;GEORGIAN SMALL LETTER QAR;Ll;0;L;;;;;N;;;10B7;;10B7 +2D18;GEORGIAN SMALL LETTER SHIN;Ll;0;L;;;;;N;;;10B8;;10B8 +2D19;GEORGIAN SMALL LETTER CHIN;Ll;0;L;;;;;N;;;10B9;;10B9 +2D1A;GEORGIAN SMALL LETTER CAN;Ll;0;L;;;;;N;;;10BA;;10BA +2D1B;GEORGIAN SMALL LETTER JIL;Ll;0;L;;;;;N;;;10BB;;10BB +2D1C;GEORGIAN SMALL LETTER CIL;Ll;0;L;;;;;N;;;10BC;;10BC +2D1D;GEORGIAN SMALL LETTER CHAR;Ll;0;L;;;;;N;;;10BD;;10BD +2D1E;GEORGIAN SMALL LETTER XAN;Ll;0;L;;;;;N;;;10BE;;10BE +2D1F;GEORGIAN SMALL LETTER JHAN;Ll;0;L;;;;;N;;;10BF;;10BF +2D20;GEORGIAN SMALL LETTER HAE;Ll;0;L;;;;;N;;;10C0;;10C0 +2D21;GEORGIAN SMALL LETTER HE;Ll;0;L;;;;;N;;;10C1;;10C1 +2D22;GEORGIAN SMALL LETTER HIE;Ll;0;L;;;;;N;;;10C2;;10C2 +2D23;GEORGIAN SMALL LETTER WE;Ll;0;L;;;;;N;;;10C3;;10C3 +2D24;GEORGIAN SMALL LETTER HAR;Ll;0;L;;;;;N;;;10C4;;10C4 +2D25;GEORGIAN SMALL LETTER HOE;Ll;0;L;;;;;N;;;10C5;;10C5 +2D27;GEORGIAN SMALL LETTER YN;Ll;0;L;;;;;N;;;10C7;;10C7 +2D2D;GEORGIAN SMALL LETTER AEN;Ll;0;L;;;;;N;;;10CD;;10CD +2D30;TIFINAGH LETTER YA;Lo;0;L;;;;;N;;;;; +2D31;TIFINAGH LETTER YAB;Lo;0;L;;;;;N;;;;; +2D32;TIFINAGH LETTER YABH;Lo;0;L;;;;;N;;;;; +2D33;TIFINAGH LETTER YAG;Lo;0;L;;;;;N;;;;; +2D34;TIFINAGH LETTER YAGHH;Lo;0;L;;;;;N;;;;; +2D35;TIFINAGH LETTER BERBER ACADEMY YAJ;Lo;0;L;;;;;N;;;;; +2D36;TIFINAGH LETTER YAJ;Lo;0;L;;;;;N;;;;; +2D37;TIFINAGH LETTER YAD;Lo;0;L;;;;;N;;;;; +2D38;TIFINAGH LETTER YADH;Lo;0;L;;;;;N;;;;; +2D39;TIFINAGH LETTER YADD;Lo;0;L;;;;;N;;;;; +2D3A;TIFINAGH LETTER YADDH;Lo;0;L;;;;;N;;;;; +2D3B;TIFINAGH LETTER YEY;Lo;0;L;;;;;N;;;;; +2D3C;TIFINAGH LETTER YAF;Lo;0;L;;;;;N;;;;; +2D3D;TIFINAGH LETTER YAK;Lo;0;L;;;;;N;;;;; +2D3E;TIFINAGH LETTER TUAREG YAK;Lo;0;L;;;;;N;;;;; +2D3F;TIFINAGH LETTER YAKHH;Lo;0;L;;;;;N;;;;; +2D40;TIFINAGH LETTER YAH;Lo;0;L;;;;;N;;;;; +2D41;TIFINAGH LETTER BERBER ACADEMY YAH;Lo;0;L;;;;;N;;;;; +2D42;TIFINAGH LETTER TUAREG YAH;Lo;0;L;;;;;N;;;;; +2D43;TIFINAGH LETTER YAHH;Lo;0;L;;;;;N;;;;; +2D44;TIFINAGH LETTER YAA;Lo;0;L;;;;;N;;;;; +2D45;TIFINAGH LETTER YAKH;Lo;0;L;;;;;N;;;;; +2D46;TIFINAGH LETTER TUAREG YAKH;Lo;0;L;;;;;N;;;;; +2D47;TIFINAGH LETTER YAQ;Lo;0;L;;;;;N;;;;; +2D48;TIFINAGH LETTER TUAREG YAQ;Lo;0;L;;;;;N;;;;; +2D49;TIFINAGH LETTER YI;Lo;0;L;;;;;N;;;;; +2D4A;TIFINAGH LETTER YAZH;Lo;0;L;;;;;N;;;;; +2D4B;TIFINAGH LETTER AHAGGAR YAZH;Lo;0;L;;;;;N;;;;; +2D4C;TIFINAGH LETTER TUAREG YAZH;Lo;0;L;;;;;N;;;;; +2D4D;TIFINAGH LETTER YAL;Lo;0;L;;;;;N;;;;; +2D4E;TIFINAGH LETTER YAM;Lo;0;L;;;;;N;;;;; +2D4F;TIFINAGH LETTER YAN;Lo;0;L;;;;;N;;;;; +2D50;TIFINAGH LETTER TUAREG YAGN;Lo;0;L;;;;;N;;;;; +2D51;TIFINAGH LETTER TUAREG YANG;Lo;0;L;;;;;N;;;;; +2D52;TIFINAGH LETTER YAP;Lo;0;L;;;;;N;;;;; +2D53;TIFINAGH LETTER YU;Lo;0;L;;;;;N;;;;; +2D54;TIFINAGH LETTER YAR;Lo;0;L;;;;;N;;;;; +2D55;TIFINAGH LETTER YARR;Lo;0;L;;;;;N;;;;; +2D56;TIFINAGH LETTER YAGH;Lo;0;L;;;;;N;;;;; +2D57;TIFINAGH LETTER TUAREG YAGH;Lo;0;L;;;;;N;;;;; +2D58;TIFINAGH LETTER AYER YAGH;Lo;0;L;;;;;N;;;;; +2D59;TIFINAGH LETTER YAS;Lo;0;L;;;;;N;;;;; +2D5A;TIFINAGH LETTER YASS;Lo;0;L;;;;;N;;;;; +2D5B;TIFINAGH LETTER YASH;Lo;0;L;;;;;N;;;;; +2D5C;TIFINAGH LETTER YAT;Lo;0;L;;;;;N;;;;; +2D5D;TIFINAGH LETTER YATH;Lo;0;L;;;;;N;;;;; +2D5E;TIFINAGH LETTER YACH;Lo;0;L;;;;;N;;;;; +2D5F;TIFINAGH LETTER YATT;Lo;0;L;;;;;N;;;;; +2D60;TIFINAGH LETTER YAV;Lo;0;L;;;;;N;;;;; +2D61;TIFINAGH LETTER YAW;Lo;0;L;;;;;N;;;;; +2D62;TIFINAGH LETTER YAY;Lo;0;L;;;;;N;;;;; +2D63;TIFINAGH LETTER YAZ;Lo;0;L;;;;;N;;;;; +2D64;TIFINAGH LETTER TAWELLEMET YAZ;Lo;0;L;;;;;N;;;;; +2D65;TIFINAGH LETTER YAZZ;Lo;0;L;;;;;N;;;;; +2D66;TIFINAGH LETTER YE;Lo;0;L;;;;;N;;;;; +2D67;TIFINAGH LETTER YO;Lo;0;L;;;;;N;;;;; +2D6F;TIFINAGH MODIFIER LETTER LABIALIZATION MARK;Lm;0;L;<super> 2D61;;;;N;;;;; +2D70;TIFINAGH SEPARATOR MARK;Po;0;L;;;;;N;;;;; +2D7F;TIFINAGH CONSONANT JOINER;Mn;9;NSM;;;;;N;;;;; +2D80;ETHIOPIC SYLLABLE LOA;Lo;0;L;;;;;N;;;;; +2D81;ETHIOPIC SYLLABLE MOA;Lo;0;L;;;;;N;;;;; +2D82;ETHIOPIC SYLLABLE ROA;Lo;0;L;;;;;N;;;;; +2D83;ETHIOPIC SYLLABLE SOA;Lo;0;L;;;;;N;;;;; +2D84;ETHIOPIC SYLLABLE SHOA;Lo;0;L;;;;;N;;;;; +2D85;ETHIOPIC SYLLABLE BOA;Lo;0;L;;;;;N;;;;; +2D86;ETHIOPIC SYLLABLE TOA;Lo;0;L;;;;;N;;;;; +2D87;ETHIOPIC SYLLABLE COA;Lo;0;L;;;;;N;;;;; +2D88;ETHIOPIC SYLLABLE NOA;Lo;0;L;;;;;N;;;;; +2D89;ETHIOPIC SYLLABLE NYOA;Lo;0;L;;;;;N;;;;; +2D8A;ETHIOPIC SYLLABLE GLOTTAL OA;Lo;0;L;;;;;N;;;;; +2D8B;ETHIOPIC SYLLABLE ZOA;Lo;0;L;;;;;N;;;;; +2D8C;ETHIOPIC SYLLABLE DOA;Lo;0;L;;;;;N;;;;; +2D8D;ETHIOPIC SYLLABLE DDOA;Lo;0;L;;;;;N;;;;; +2D8E;ETHIOPIC SYLLABLE JOA;Lo;0;L;;;;;N;;;;; +2D8F;ETHIOPIC SYLLABLE THOA;Lo;0;L;;;;;N;;;;; +2D90;ETHIOPIC SYLLABLE CHOA;Lo;0;L;;;;;N;;;;; +2D91;ETHIOPIC SYLLABLE PHOA;Lo;0;L;;;;;N;;;;; +2D92;ETHIOPIC SYLLABLE POA;Lo;0;L;;;;;N;;;;; +2D93;ETHIOPIC SYLLABLE GGWA;Lo;0;L;;;;;N;;;;; +2D94;ETHIOPIC SYLLABLE GGWI;Lo;0;L;;;;;N;;;;; +2D95;ETHIOPIC SYLLABLE GGWEE;Lo;0;L;;;;;N;;;;; +2D96;ETHIOPIC SYLLABLE GGWE;Lo;0;L;;;;;N;;;;; +2DA0;ETHIOPIC SYLLABLE SSA;Lo;0;L;;;;;N;;;;; +2DA1;ETHIOPIC SYLLABLE SSU;Lo;0;L;;;;;N;;;;; +2DA2;ETHIOPIC SYLLABLE SSI;Lo;0;L;;;;;N;;;;; +2DA3;ETHIOPIC SYLLABLE SSAA;Lo;0;L;;;;;N;;;;; +2DA4;ETHIOPIC SYLLABLE SSEE;Lo;0;L;;;;;N;;;;; +2DA5;ETHIOPIC SYLLABLE SSE;Lo;0;L;;;;;N;;;;; +2DA6;ETHIOPIC SYLLABLE SSO;Lo;0;L;;;;;N;;;;; +2DA8;ETHIOPIC SYLLABLE CCA;Lo;0;L;;;;;N;;;;; +2DA9;ETHIOPIC SYLLABLE CCU;Lo;0;L;;;;;N;;;;; +2DAA;ETHIOPIC SYLLABLE CCI;Lo;0;L;;;;;N;;;;; +2DAB;ETHIOPIC SYLLABLE CCAA;Lo;0;L;;;;;N;;;;; +2DAC;ETHIOPIC SYLLABLE CCEE;Lo;0;L;;;;;N;;;;; +2DAD;ETHIOPIC SYLLABLE CCE;Lo;0;L;;;;;N;;;;; +2DAE;ETHIOPIC SYLLABLE CCO;Lo;0;L;;;;;N;;;;; +2DB0;ETHIOPIC SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; +2DB1;ETHIOPIC SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; +2DB2;ETHIOPIC SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; +2DB3;ETHIOPIC SYLLABLE ZZAA;Lo;0;L;;;;;N;;;;; +2DB4;ETHIOPIC SYLLABLE ZZEE;Lo;0;L;;;;;N;;;;; +2DB5;ETHIOPIC SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; +2DB6;ETHIOPIC SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; +2DB8;ETHIOPIC SYLLABLE CCHA;Lo;0;L;;;;;N;;;;; +2DB9;ETHIOPIC SYLLABLE CCHU;Lo;0;L;;;;;N;;;;; +2DBA;ETHIOPIC SYLLABLE CCHI;Lo;0;L;;;;;N;;;;; +2DBB;ETHIOPIC SYLLABLE CCHAA;Lo;0;L;;;;;N;;;;; +2DBC;ETHIOPIC SYLLABLE CCHEE;Lo;0;L;;;;;N;;;;; +2DBD;ETHIOPIC SYLLABLE CCHE;Lo;0;L;;;;;N;;;;; +2DBE;ETHIOPIC SYLLABLE CCHO;Lo;0;L;;;;;N;;;;; +2DC0;ETHIOPIC SYLLABLE QYA;Lo;0;L;;;;;N;;;;; +2DC1;ETHIOPIC SYLLABLE QYU;Lo;0;L;;;;;N;;;;; +2DC2;ETHIOPIC SYLLABLE QYI;Lo;0;L;;;;;N;;;;; +2DC3;ETHIOPIC SYLLABLE QYAA;Lo;0;L;;;;;N;;;;; +2DC4;ETHIOPIC SYLLABLE QYEE;Lo;0;L;;;;;N;;;;; +2DC5;ETHIOPIC SYLLABLE QYE;Lo;0;L;;;;;N;;;;; +2DC6;ETHIOPIC SYLLABLE QYO;Lo;0;L;;;;;N;;;;; +2DC8;ETHIOPIC SYLLABLE KYA;Lo;0;L;;;;;N;;;;; +2DC9;ETHIOPIC SYLLABLE KYU;Lo;0;L;;;;;N;;;;; +2DCA;ETHIOPIC SYLLABLE KYI;Lo;0;L;;;;;N;;;;; +2DCB;ETHIOPIC SYLLABLE KYAA;Lo;0;L;;;;;N;;;;; +2DCC;ETHIOPIC SYLLABLE KYEE;Lo;0;L;;;;;N;;;;; +2DCD;ETHIOPIC SYLLABLE KYE;Lo;0;L;;;;;N;;;;; +2DCE;ETHIOPIC SYLLABLE KYO;Lo;0;L;;;;;N;;;;; +2DD0;ETHIOPIC SYLLABLE XYA;Lo;0;L;;;;;N;;;;; +2DD1;ETHIOPIC SYLLABLE XYU;Lo;0;L;;;;;N;;;;; +2DD2;ETHIOPIC SYLLABLE XYI;Lo;0;L;;;;;N;;;;; +2DD3;ETHIOPIC SYLLABLE XYAA;Lo;0;L;;;;;N;;;;; +2DD4;ETHIOPIC SYLLABLE XYEE;Lo;0;L;;;;;N;;;;; +2DD5;ETHIOPIC SYLLABLE XYE;Lo;0;L;;;;;N;;;;; +2DD6;ETHIOPIC SYLLABLE XYO;Lo;0;L;;;;;N;;;;; +2DD8;ETHIOPIC SYLLABLE GYA;Lo;0;L;;;;;N;;;;; +2DD9;ETHIOPIC SYLLABLE GYU;Lo;0;L;;;;;N;;;;; +2DDA;ETHIOPIC SYLLABLE GYI;Lo;0;L;;;;;N;;;;; +2DDB;ETHIOPIC SYLLABLE GYAA;Lo;0;L;;;;;N;;;;; +2DDC;ETHIOPIC SYLLABLE GYEE;Lo;0;L;;;;;N;;;;; +2DDD;ETHIOPIC SYLLABLE GYE;Lo;0;L;;;;;N;;;;; +2DDE;ETHIOPIC SYLLABLE GYO;Lo;0;L;;;;;N;;;;; +2DE0;COMBINING CYRILLIC LETTER BE;Mn;230;NSM;;;;;N;;;;; +2DE1;COMBINING CYRILLIC LETTER VE;Mn;230;NSM;;;;;N;;;;; +2DE2;COMBINING CYRILLIC LETTER GHE;Mn;230;NSM;;;;;N;;;;; +2DE3;COMBINING CYRILLIC LETTER DE;Mn;230;NSM;;;;;N;;;;; +2DE4;COMBINING CYRILLIC LETTER ZHE;Mn;230;NSM;;;;;N;;;;; +2DE5;COMBINING CYRILLIC LETTER ZE;Mn;230;NSM;;;;;N;;;;; +2DE6;COMBINING CYRILLIC LETTER KA;Mn;230;NSM;;;;;N;;;;; +2DE7;COMBINING CYRILLIC LETTER EL;Mn;230;NSM;;;;;N;;;;; +2DE8;COMBINING CYRILLIC LETTER EM;Mn;230;NSM;;;;;N;;;;; +2DE9;COMBINING CYRILLIC LETTER EN;Mn;230;NSM;;;;;N;;;;; +2DEA;COMBINING CYRILLIC LETTER O;Mn;230;NSM;;;;;N;;;;; +2DEB;COMBINING CYRILLIC LETTER PE;Mn;230;NSM;;;;;N;;;;; +2DEC;COMBINING CYRILLIC LETTER ER;Mn;230;NSM;;;;;N;;;;; +2DED;COMBINING CYRILLIC LETTER ES;Mn;230;NSM;;;;;N;;;;; +2DEE;COMBINING CYRILLIC LETTER TE;Mn;230;NSM;;;;;N;;;;; +2DEF;COMBINING CYRILLIC LETTER HA;Mn;230;NSM;;;;;N;;;;; +2DF0;COMBINING CYRILLIC LETTER TSE;Mn;230;NSM;;;;;N;;;;; +2DF1;COMBINING CYRILLIC LETTER CHE;Mn;230;NSM;;;;;N;;;;; +2DF2;COMBINING CYRILLIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; +2DF3;COMBINING CYRILLIC LETTER SHCHA;Mn;230;NSM;;;;;N;;;;; +2DF4;COMBINING CYRILLIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; +2DF5;COMBINING CYRILLIC LETTER ES-TE;Mn;230;NSM;;;;;N;;;;; +2DF6;COMBINING CYRILLIC LETTER A;Mn;230;NSM;;;;;N;;;;; +2DF7;COMBINING CYRILLIC LETTER IE;Mn;230;NSM;;;;;N;;;;; +2DF8;COMBINING CYRILLIC LETTER DJERV;Mn;230;NSM;;;;;N;;;;; +2DF9;COMBINING CYRILLIC LETTER MONOGRAPH UK;Mn;230;NSM;;;;;N;;;;; +2DFA;COMBINING CYRILLIC LETTER YAT;Mn;230;NSM;;;;;N;;;;; +2DFB;COMBINING CYRILLIC LETTER YU;Mn;230;NSM;;;;;N;;;;; +2DFC;COMBINING CYRILLIC LETTER IOTIFIED A;Mn;230;NSM;;;;;N;;;;; +2DFD;COMBINING CYRILLIC LETTER LITTLE YUS;Mn;230;NSM;;;;;N;;;;; +2DFE;COMBINING CYRILLIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; +2DFF;COMBINING CYRILLIC LETTER IOTIFIED BIG YUS;Mn;230;NSM;;;;;N;;;;; +2E00;RIGHT ANGLE SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; +2E01;RIGHT ANGLE DOTTED SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; +2E02;LEFT SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; +2E03;RIGHT SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; +2E04;LEFT DOTTED SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; +2E05;RIGHT DOTTED SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; +2E06;RAISED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; +2E07;RAISED DOTTED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; +2E08;DOTTED TRANSPOSITION MARKER;Po;0;ON;;;;;N;;;;; +2E09;LEFT TRANSPOSITION BRACKET;Pi;0;ON;;;;;Y;;;;; +2E0A;RIGHT TRANSPOSITION BRACKET;Pf;0;ON;;;;;Y;;;;; +2E0B;RAISED SQUARE;Po;0;ON;;;;;N;;;;; +2E0C;LEFT RAISED OMISSION BRACKET;Pi;0;ON;;;;;Y;;;;; +2E0D;RIGHT RAISED OMISSION BRACKET;Pf;0;ON;;;;;Y;;;;; +2E0E;EDITORIAL CORONIS;Po;0;ON;;;;;N;;;;; +2E0F;PARAGRAPHOS;Po;0;ON;;;;;N;;;;; +2E10;FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; +2E11;REVERSED FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; +2E12;HYPODIASTOLE;Po;0;ON;;;;;N;;;;; +2E13;DOTTED OBELOS;Po;0;ON;;;;;N;;;;; +2E14;DOWNWARDS ANCORA;Po;0;ON;;;;;N;;;;; +2E15;UPWARDS ANCORA;Po;0;ON;;;;;N;;;;; +2E16;DOTTED RIGHT-POINTING ANGLE;Po;0;ON;;;;;N;;;;; +2E17;DOUBLE OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;; +2E18;INVERTED INTERROBANG;Po;0;ON;;;;;N;;;;; +2E19;PALM BRANCH;Po;0;ON;;;;;N;;;;; +2E1A;HYPHEN WITH DIAERESIS;Pd;0;ON;;;;;N;;;;; +2E1B;TILDE WITH RING ABOVE;Po;0;ON;;;;;N;;;;; +2E1C;LEFT LOW PARAPHRASE BRACKET;Pi;0;ON;;;;;Y;;;;; +2E1D;RIGHT LOW PARAPHRASE BRACKET;Pf;0;ON;;;;;Y;;;;; +2E1E;TILDE WITH DOT ABOVE;Po;0;ON;;;;;N;;;;; +2E1F;TILDE WITH DOT BELOW;Po;0;ON;;;;;N;;;;; +2E20;LEFT VERTICAL BAR WITH QUILL;Pi;0;ON;;;;;Y;;;;; +2E21;RIGHT VERTICAL BAR WITH QUILL;Pf;0;ON;;;;;Y;;;;; +2E22;TOP LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; +2E23;TOP RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; +2E24;BOTTOM LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; +2E25;BOTTOM RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; +2E26;LEFT SIDEWAYS U BRACKET;Ps;0;ON;;;;;Y;;;;; +2E27;RIGHT SIDEWAYS U BRACKET;Pe;0;ON;;;;;Y;;;;; +2E28;LEFT DOUBLE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +2E29;RIGHT DOUBLE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +2E2A;TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +2E2B;ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; +2E2C;SQUARED FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +2E2D;FIVE DOT MARK;Po;0;ON;;;;;N;;;;; +2E2E;REVERSED QUESTION MARK;Po;0;ON;;;;;N;;;;; +2E2F;VERTICAL TILDE;Lm;0;ON;;;;;N;;;;; +2E30;RING POINT;Po;0;ON;;;;;N;;;;; +2E31;WORD SEPARATOR MIDDLE DOT;Po;0;ON;;;;;N;;;;; +2E32;TURNED COMMA;Po;0;ON;;;;;N;;;;; +2E33;RAISED DOT;Po;0;ON;;;;;N;;;;; +2E34;RAISED COMMA;Po;0;ON;;;;;N;;;;; +2E35;TURNED SEMICOLON;Po;0;ON;;;;;N;;;;; +2E36;DAGGER WITH LEFT GUARD;Po;0;ON;;;;;N;;;;; +2E37;DAGGER WITH RIGHT GUARD;Po;0;ON;;;;;N;;;;; +2E38;TURNED DAGGER;Po;0;ON;;;;;N;;;;; +2E39;TOP HALF SECTION SIGN;Po;0;ON;;;;;N;;;;; +2E3A;TWO-EM DASH;Pd;0;ON;;;;;N;;;;; +2E3B;THREE-EM DASH;Pd;0;ON;;;;;N;;;;; +2E3C;STENOGRAPHIC FULL STOP;Po;0;ON;;;;;N;;;;; +2E3D;VERTICAL SIX DOTS;Po;0;ON;;;;;N;;;;; +2E3E;WIGGLY VERTICAL LINE;Po;0;ON;;;;;N;;;;; +2E3F;CAPITULUM;Po;0;ON;;;;;N;;;;; +2E40;DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; +2E41;REVERSED COMMA;Po;0;ON;;;;;N;;;;; +2E42;DOUBLE LOW-REVERSED-9 QUOTATION MARK;Ps;0;ON;;;;;N;;;;; +2E43;DASH WITH LEFT UPTURN;Po;0;ON;;;;;N;;;;; +2E44;DOUBLE SUSPENSION MARK;Po;0;ON;;;;;N;;;;; +2E45;INVERTED LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E46;INVERTED LOW KAVYKA WITH KAVYKA ABOVE;Po;0;ON;;;;;N;;;;; +2E47;LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E48;LOW KAVYKA WITH DOT;Po;0;ON;;;;;N;;;;; +2E49;DOUBLE STACKED COMMA;Po;0;ON;;;;;N;;;;; +2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; +2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; +2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; +2E83;CJK RADICAL SECOND TWO;So;0;ON;;;;;N;;;;; +2E84;CJK RADICAL SECOND THREE;So;0;ON;;;;;N;;;;; +2E85;CJK RADICAL PERSON;So;0;ON;;;;;N;;;;; +2E86;CJK RADICAL BOX;So;0;ON;;;;;N;;;;; +2E87;CJK RADICAL TABLE;So;0;ON;;;;;N;;;;; +2E88;CJK RADICAL KNIFE ONE;So;0;ON;;;;;N;;;;; +2E89;CJK RADICAL KNIFE TWO;So;0;ON;;;;;N;;;;; +2E8A;CJK RADICAL DIVINATION;So;0;ON;;;;;N;;;;; +2E8B;CJK RADICAL SEAL;So;0;ON;;;;;N;;;;; +2E8C;CJK RADICAL SMALL ONE;So;0;ON;;;;;N;;;;; +2E8D;CJK RADICAL SMALL TWO;So;0;ON;;;;;N;;;;; +2E8E;CJK RADICAL LAME ONE;So;0;ON;;;;;N;;;;; +2E8F;CJK RADICAL LAME TWO;So;0;ON;;;;;N;;;;; +2E90;CJK RADICAL LAME THREE;So;0;ON;;;;;N;;;;; +2E91;CJK RADICAL LAME FOUR;So;0;ON;;;;;N;;;;; +2E92;CJK RADICAL SNAKE;So;0;ON;;;;;N;;;;; +2E93;CJK RADICAL THREAD;So;0;ON;;;;;N;;;;; +2E94;CJK RADICAL SNOUT ONE;So;0;ON;;;;;N;;;;; +2E95;CJK RADICAL SNOUT TWO;So;0;ON;;;;;N;;;;; +2E96;CJK RADICAL HEART ONE;So;0;ON;;;;;N;;;;; +2E97;CJK RADICAL HEART TWO;So;0;ON;;;;;N;;;;; +2E98;CJK RADICAL HAND;So;0;ON;;;;;N;;;;; +2E99;CJK RADICAL RAP;So;0;ON;;;;;N;;;;; +2E9B;CJK RADICAL CHOKE;So;0;ON;;;;;N;;;;; +2E9C;CJK RADICAL SUN;So;0;ON;;;;;N;;;;; +2E9D;CJK RADICAL MOON;So;0;ON;;;;;N;;;;; +2E9E;CJK RADICAL DEATH;So;0;ON;;;;;N;;;;; +2E9F;CJK RADICAL MOTHER;So;0;ON;<compat> 6BCD;;;;N;;;;; +2EA0;CJK RADICAL CIVILIAN;So;0;ON;;;;;N;;;;; +2EA1;CJK RADICAL WATER ONE;So;0;ON;;;;;N;;;;; +2EA2;CJK RADICAL WATER TWO;So;0;ON;;;;;N;;;;; +2EA3;CJK RADICAL FIRE;So;0;ON;;;;;N;;;;; +2EA4;CJK RADICAL PAW ONE;So;0;ON;;;;;N;;;;; +2EA5;CJK RADICAL PAW TWO;So;0;ON;;;;;N;;;;; +2EA6;CJK RADICAL SIMPLIFIED HALF TREE TRUNK;So;0;ON;;;;;N;;;;; +2EA7;CJK RADICAL COW;So;0;ON;;;;;N;;;;; +2EA8;CJK RADICAL DOG;So;0;ON;;;;;N;;;;; +2EA9;CJK RADICAL JADE;So;0;ON;;;;;N;;;;; +2EAA;CJK RADICAL BOLT OF CLOTH;So;0;ON;;;;;N;;;;; +2EAB;CJK RADICAL EYE;So;0;ON;;;;;N;;;;; +2EAC;CJK RADICAL SPIRIT ONE;So;0;ON;;;;;N;;;;; +2EAD;CJK RADICAL SPIRIT TWO;So;0;ON;;;;;N;;;;; +2EAE;CJK RADICAL BAMBOO;So;0;ON;;;;;N;;;;; +2EAF;CJK RADICAL SILK;So;0;ON;;;;;N;;;;; +2EB0;CJK RADICAL C-SIMPLIFIED SILK;So;0;ON;;;;;N;;;;; +2EB1;CJK RADICAL NET ONE;So;0;ON;;;;;N;;;;; +2EB2;CJK RADICAL NET TWO;So;0;ON;;;;;N;;;;; +2EB3;CJK RADICAL NET THREE;So;0;ON;;;;;N;;;;; +2EB4;CJK RADICAL NET FOUR;So;0;ON;;;;;N;;;;; +2EB5;CJK RADICAL MESH;So;0;ON;;;;;N;;;;; +2EB6;CJK RADICAL SHEEP;So;0;ON;;;;;N;;;;; +2EB7;CJK RADICAL RAM;So;0;ON;;;;;N;;;;; +2EB8;CJK RADICAL EWE;So;0;ON;;;;;N;;;;; +2EB9;CJK RADICAL OLD;So;0;ON;;;;;N;;;;; +2EBA;CJK RADICAL BRUSH ONE;So;0;ON;;;;;N;;;;; +2EBB;CJK RADICAL BRUSH TWO;So;0;ON;;;;;N;;;;; +2EBC;CJK RADICAL MEAT;So;0;ON;;;;;N;;;;; +2EBD;CJK RADICAL MORTAR;So;0;ON;;;;;N;;;;; +2EBE;CJK RADICAL GRASS ONE;So;0;ON;;;;;N;;;;; +2EBF;CJK RADICAL GRASS TWO;So;0;ON;;;;;N;;;;; +2EC0;CJK RADICAL GRASS THREE;So;0;ON;;;;;N;;;;; +2EC1;CJK RADICAL TIGER;So;0;ON;;;;;N;;;;; +2EC2;CJK RADICAL CLOTHES;So;0;ON;;;;;N;;;;; +2EC3;CJK RADICAL WEST ONE;So;0;ON;;;;;N;;;;; +2EC4;CJK RADICAL WEST TWO;So;0;ON;;;;;N;;;;; +2EC5;CJK RADICAL C-SIMPLIFIED SEE;So;0;ON;;;;;N;;;;; +2EC6;CJK RADICAL SIMPLIFIED HORN;So;0;ON;;;;;N;;;;; +2EC7;CJK RADICAL HORN;So;0;ON;;;;;N;;;;; +2EC8;CJK RADICAL C-SIMPLIFIED SPEECH;So;0;ON;;;;;N;;;;; +2EC9;CJK RADICAL C-SIMPLIFIED SHELL;So;0;ON;;;;;N;;;;; +2ECA;CJK RADICAL FOOT;So;0;ON;;;;;N;;;;; +2ECB;CJK RADICAL C-SIMPLIFIED CART;So;0;ON;;;;;N;;;;; +2ECC;CJK RADICAL SIMPLIFIED WALK;So;0;ON;;;;;N;;;;; +2ECD;CJK RADICAL WALK ONE;So;0;ON;;;;;N;;;;; +2ECE;CJK RADICAL WALK TWO;So;0;ON;;;;;N;;;;; +2ECF;CJK RADICAL CITY;So;0;ON;;;;;N;;;;; +2ED0;CJK RADICAL C-SIMPLIFIED GOLD;So;0;ON;;;;;N;;;;; +2ED1;CJK RADICAL LONG ONE;So;0;ON;;;;;N;;;;; +2ED2;CJK RADICAL LONG TWO;So;0;ON;;;;;N;;;;; +2ED3;CJK RADICAL C-SIMPLIFIED LONG;So;0;ON;;;;;N;;;;; +2ED4;CJK RADICAL C-SIMPLIFIED GATE;So;0;ON;;;;;N;;;;; +2ED5;CJK RADICAL MOUND ONE;So;0;ON;;;;;N;;;;; +2ED6;CJK RADICAL MOUND TWO;So;0;ON;;;;;N;;;;; +2ED7;CJK RADICAL RAIN;So;0;ON;;;;;N;;;;; +2ED8;CJK RADICAL BLUE;So;0;ON;;;;;N;;;;; +2ED9;CJK RADICAL C-SIMPLIFIED TANNED LEATHER;So;0;ON;;;;;N;;;;; +2EDA;CJK RADICAL C-SIMPLIFIED LEAF;So;0;ON;;;;;N;;;;; +2EDB;CJK RADICAL C-SIMPLIFIED WIND;So;0;ON;;;;;N;;;;; +2EDC;CJK RADICAL C-SIMPLIFIED FLY;So;0;ON;;;;;N;;;;; +2EDD;CJK RADICAL EAT ONE;So;0;ON;;;;;N;;;;; +2EDE;CJK RADICAL EAT TWO;So;0;ON;;;;;N;;;;; +2EDF;CJK RADICAL EAT THREE;So;0;ON;;;;;N;;;;; +2EE0;CJK RADICAL C-SIMPLIFIED EAT;So;0;ON;;;;;N;;;;; +2EE1;CJK RADICAL HEAD;So;0;ON;;;;;N;;;;; +2EE2;CJK RADICAL C-SIMPLIFIED HORSE;So;0;ON;;;;;N;;;;; +2EE3;CJK RADICAL BONE;So;0;ON;;;;;N;;;;; +2EE4;CJK RADICAL GHOST;So;0;ON;;;;;N;;;;; +2EE5;CJK RADICAL C-SIMPLIFIED FISH;So;0;ON;;;;;N;;;;; +2EE6;CJK RADICAL C-SIMPLIFIED BIRD;So;0;ON;;;;;N;;;;; +2EE7;CJK RADICAL C-SIMPLIFIED SALT;So;0;ON;;;;;N;;;;; +2EE8;CJK RADICAL SIMPLIFIED WHEAT;So;0;ON;;;;;N;;;;; +2EE9;CJK RADICAL SIMPLIFIED YELLOW;So;0;ON;;;;;N;;;;; +2EEA;CJK RADICAL C-SIMPLIFIED FROG;So;0;ON;;;;;N;;;;; +2EEB;CJK RADICAL J-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; +2EEC;CJK RADICAL C-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; +2EED;CJK RADICAL J-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; +2EEE;CJK RADICAL C-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; +2EEF;CJK RADICAL J-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; +2EF0;CJK RADICAL C-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; +2EF1;CJK RADICAL TURTLE;So;0;ON;;;;;N;;;;; +2EF2;CJK RADICAL J-SIMPLIFIED TURTLE;So;0;ON;;;;;N;;;;; +2EF3;CJK RADICAL C-SIMPLIFIED TURTLE;So;0;ON;<compat> 9F9F;;;;N;;;;; +2F00;KANGXI RADICAL ONE;So;0;ON;<compat> 4E00;;;;N;;;;; +2F01;KANGXI RADICAL LINE;So;0;ON;<compat> 4E28;;;;N;;;;; +2F02;KANGXI RADICAL DOT;So;0;ON;<compat> 4E36;;;;N;;;;; +2F03;KANGXI RADICAL SLASH;So;0;ON;<compat> 4E3F;;;;N;;;;; +2F04;KANGXI RADICAL SECOND;So;0;ON;<compat> 4E59;;;;N;;;;; +2F05;KANGXI RADICAL HOOK;So;0;ON;<compat> 4E85;;;;N;;;;; +2F06;KANGXI RADICAL TWO;So;0;ON;<compat> 4E8C;;;;N;;;;; +2F07;KANGXI RADICAL LID;So;0;ON;<compat> 4EA0;;;;N;;;;; +2F08;KANGXI RADICAL MAN;So;0;ON;<compat> 4EBA;;;;N;;;;; +2F09;KANGXI RADICAL LEGS;So;0;ON;<compat> 513F;;;;N;;;;; +2F0A;KANGXI RADICAL ENTER;So;0;ON;<compat> 5165;;;;N;;;;; +2F0B;KANGXI RADICAL EIGHT;So;0;ON;<compat> 516B;;;;N;;;;; +2F0C;KANGXI RADICAL DOWN BOX;So;0;ON;<compat> 5182;;;;N;;;;; +2F0D;KANGXI RADICAL COVER;So;0;ON;<compat> 5196;;;;N;;;;; +2F0E;KANGXI RADICAL ICE;So;0;ON;<compat> 51AB;;;;N;;;;; +2F0F;KANGXI RADICAL TABLE;So;0;ON;<compat> 51E0;;;;N;;;;; +2F10;KANGXI RADICAL OPEN BOX;So;0;ON;<compat> 51F5;;;;N;;;;; +2F11;KANGXI RADICAL KNIFE;So;0;ON;<compat> 5200;;;;N;;;;; +2F12;KANGXI RADICAL POWER;So;0;ON;<compat> 529B;;;;N;;;;; +2F13;KANGXI RADICAL WRAP;So;0;ON;<compat> 52F9;;;;N;;;;; +2F14;KANGXI RADICAL SPOON;So;0;ON;<compat> 5315;;;;N;;;;; +2F15;KANGXI RADICAL RIGHT OPEN BOX;So;0;ON;<compat> 531A;;;;N;;;;; +2F16;KANGXI RADICAL HIDING ENCLOSURE;So;0;ON;<compat> 5338;;;;N;;;;; +2F17;KANGXI RADICAL TEN;So;0;ON;<compat> 5341;;;;N;;;;; +2F18;KANGXI RADICAL DIVINATION;So;0;ON;<compat> 535C;;;;N;;;;; +2F19;KANGXI RADICAL SEAL;So;0;ON;<compat> 5369;;;;N;;;;; +2F1A;KANGXI RADICAL CLIFF;So;0;ON;<compat> 5382;;;;N;;;;; +2F1B;KANGXI RADICAL PRIVATE;So;0;ON;<compat> 53B6;;;;N;;;;; +2F1C;KANGXI RADICAL AGAIN;So;0;ON;<compat> 53C8;;;;N;;;;; +2F1D;KANGXI RADICAL MOUTH;So;0;ON;<compat> 53E3;;;;N;;;;; +2F1E;KANGXI RADICAL ENCLOSURE;So;0;ON;<compat> 56D7;;;;N;;;;; +2F1F;KANGXI RADICAL EARTH;So;0;ON;<compat> 571F;;;;N;;;;; +2F20;KANGXI RADICAL SCHOLAR;So;0;ON;<compat> 58EB;;;;N;;;;; +2F21;KANGXI RADICAL GO;So;0;ON;<compat> 5902;;;;N;;;;; +2F22;KANGXI RADICAL GO SLOWLY;So;0;ON;<compat> 590A;;;;N;;;;; +2F23;KANGXI RADICAL EVENING;So;0;ON;<compat> 5915;;;;N;;;;; +2F24;KANGXI RADICAL BIG;So;0;ON;<compat> 5927;;;;N;;;;; +2F25;KANGXI RADICAL WOMAN;So;0;ON;<compat> 5973;;;;N;;;;; +2F26;KANGXI RADICAL CHILD;So;0;ON;<compat> 5B50;;;;N;;;;; +2F27;KANGXI RADICAL ROOF;So;0;ON;<compat> 5B80;;;;N;;;;; +2F28;KANGXI RADICAL INCH;So;0;ON;<compat> 5BF8;;;;N;;;;; +2F29;KANGXI RADICAL SMALL;So;0;ON;<compat> 5C0F;;;;N;;;;; +2F2A;KANGXI RADICAL LAME;So;0;ON;<compat> 5C22;;;;N;;;;; +2F2B;KANGXI RADICAL CORPSE;So;0;ON;<compat> 5C38;;;;N;;;;; +2F2C;KANGXI RADICAL SPROUT;So;0;ON;<compat> 5C6E;;;;N;;;;; +2F2D;KANGXI RADICAL MOUNTAIN;So;0;ON;<compat> 5C71;;;;N;;;;; +2F2E;KANGXI RADICAL RIVER;So;0;ON;<compat> 5DDB;;;;N;;;;; +2F2F;KANGXI RADICAL WORK;So;0;ON;<compat> 5DE5;;;;N;;;;; +2F30;KANGXI RADICAL ONESELF;So;0;ON;<compat> 5DF1;;;;N;;;;; +2F31;KANGXI RADICAL TURBAN;So;0;ON;<compat> 5DFE;;;;N;;;;; +2F32;KANGXI RADICAL DRY;So;0;ON;<compat> 5E72;;;;N;;;;; +2F33;KANGXI RADICAL SHORT THREAD;So;0;ON;<compat> 5E7A;;;;N;;;;; +2F34;KANGXI RADICAL DOTTED CLIFF;So;0;ON;<compat> 5E7F;;;;N;;;;; +2F35;KANGXI RADICAL LONG STRIDE;So;0;ON;<compat> 5EF4;;;;N;;;;; +2F36;KANGXI RADICAL TWO HANDS;So;0;ON;<compat> 5EFE;;;;N;;;;; +2F37;KANGXI RADICAL SHOOT;So;0;ON;<compat> 5F0B;;;;N;;;;; +2F38;KANGXI RADICAL BOW;So;0;ON;<compat> 5F13;;;;N;;;;; +2F39;KANGXI RADICAL SNOUT;So;0;ON;<compat> 5F50;;;;N;;;;; +2F3A;KANGXI RADICAL BRISTLE;So;0;ON;<compat> 5F61;;;;N;;;;; +2F3B;KANGXI RADICAL STEP;So;0;ON;<compat> 5F73;;;;N;;;;; +2F3C;KANGXI RADICAL HEART;So;0;ON;<compat> 5FC3;;;;N;;;;; +2F3D;KANGXI RADICAL HALBERD;So;0;ON;<compat> 6208;;;;N;;;;; +2F3E;KANGXI RADICAL DOOR;So;0;ON;<compat> 6236;;;;N;;;;; +2F3F;KANGXI RADICAL HAND;So;0;ON;<compat> 624B;;;;N;;;;; +2F40;KANGXI RADICAL BRANCH;So;0;ON;<compat> 652F;;;;N;;;;; +2F41;KANGXI RADICAL RAP;So;0;ON;<compat> 6534;;;;N;;;;; +2F42;KANGXI RADICAL SCRIPT;So;0;ON;<compat> 6587;;;;N;;;;; +2F43;KANGXI RADICAL DIPPER;So;0;ON;<compat> 6597;;;;N;;;;; +2F44;KANGXI RADICAL AXE;So;0;ON;<compat> 65A4;;;;N;;;;; +2F45;KANGXI RADICAL SQUARE;So;0;ON;<compat> 65B9;;;;N;;;;; +2F46;KANGXI RADICAL NOT;So;0;ON;<compat> 65E0;;;;N;;;;; +2F47;KANGXI RADICAL SUN;So;0;ON;<compat> 65E5;;;;N;;;;; +2F48;KANGXI RADICAL SAY;So;0;ON;<compat> 66F0;;;;N;;;;; +2F49;KANGXI RADICAL MOON;So;0;ON;<compat> 6708;;;;N;;;;; +2F4A;KANGXI RADICAL TREE;So;0;ON;<compat> 6728;;;;N;;;;; +2F4B;KANGXI RADICAL LACK;So;0;ON;<compat> 6B20;;;;N;;;;; +2F4C;KANGXI RADICAL STOP;So;0;ON;<compat> 6B62;;;;N;;;;; +2F4D;KANGXI RADICAL DEATH;So;0;ON;<compat> 6B79;;;;N;;;;; +2F4E;KANGXI RADICAL WEAPON;So;0;ON;<compat> 6BB3;;;;N;;;;; +2F4F;KANGXI RADICAL DO NOT;So;0;ON;<compat> 6BCB;;;;N;;;;; +2F50;KANGXI RADICAL COMPARE;So;0;ON;<compat> 6BD4;;;;N;;;;; +2F51;KANGXI RADICAL FUR;So;0;ON;<compat> 6BDB;;;;N;;;;; +2F52;KANGXI RADICAL CLAN;So;0;ON;<compat> 6C0F;;;;N;;;;; +2F53;KANGXI RADICAL STEAM;So;0;ON;<compat> 6C14;;;;N;;;;; +2F54;KANGXI RADICAL WATER;So;0;ON;<compat> 6C34;;;;N;;;;; +2F55;KANGXI RADICAL FIRE;So;0;ON;<compat> 706B;;;;N;;;;; +2F56;KANGXI RADICAL CLAW;So;0;ON;<compat> 722A;;;;N;;;;; +2F57;KANGXI RADICAL FATHER;So;0;ON;<compat> 7236;;;;N;;;;; +2F58;KANGXI RADICAL DOUBLE X;So;0;ON;<compat> 723B;;;;N;;;;; +2F59;KANGXI RADICAL HALF TREE TRUNK;So;0;ON;<compat> 723F;;;;N;;;;; +2F5A;KANGXI RADICAL SLICE;So;0;ON;<compat> 7247;;;;N;;;;; +2F5B;KANGXI RADICAL FANG;So;0;ON;<compat> 7259;;;;N;;;;; +2F5C;KANGXI RADICAL COW;So;0;ON;<compat> 725B;;;;N;;;;; +2F5D;KANGXI RADICAL DOG;So;0;ON;<compat> 72AC;;;;N;;;;; +2F5E;KANGXI RADICAL PROFOUND;So;0;ON;<compat> 7384;;;;N;;;;; +2F5F;KANGXI RADICAL JADE;So;0;ON;<compat> 7389;;;;N;;;;; +2F60;KANGXI RADICAL MELON;So;0;ON;<compat> 74DC;;;;N;;;;; +2F61;KANGXI RADICAL TILE;So;0;ON;<compat> 74E6;;;;N;;;;; +2F62;KANGXI RADICAL SWEET;So;0;ON;<compat> 7518;;;;N;;;;; +2F63;KANGXI RADICAL LIFE;So;0;ON;<compat> 751F;;;;N;;;;; +2F64;KANGXI RADICAL USE;So;0;ON;<compat> 7528;;;;N;;;;; +2F65;KANGXI RADICAL FIELD;So;0;ON;<compat> 7530;;;;N;;;;; +2F66;KANGXI RADICAL BOLT OF CLOTH;So;0;ON;<compat> 758B;;;;N;;;;; +2F67;KANGXI RADICAL SICKNESS;So;0;ON;<compat> 7592;;;;N;;;;; +2F68;KANGXI RADICAL DOTTED TENT;So;0;ON;<compat> 7676;;;;N;;;;; +2F69;KANGXI RADICAL WHITE;So;0;ON;<compat> 767D;;;;N;;;;; +2F6A;KANGXI RADICAL SKIN;So;0;ON;<compat> 76AE;;;;N;;;;; +2F6B;KANGXI RADICAL DISH;So;0;ON;<compat> 76BF;;;;N;;;;; +2F6C;KANGXI RADICAL EYE;So;0;ON;<compat> 76EE;;;;N;;;;; +2F6D;KANGXI RADICAL SPEAR;So;0;ON;<compat> 77DB;;;;N;;;;; +2F6E;KANGXI RADICAL ARROW;So;0;ON;<compat> 77E2;;;;N;;;;; +2F6F;KANGXI RADICAL STONE;So;0;ON;<compat> 77F3;;;;N;;;;; +2F70;KANGXI RADICAL SPIRIT;So;0;ON;<compat> 793A;;;;N;;;;; +2F71;KANGXI RADICAL TRACK;So;0;ON;<compat> 79B8;;;;N;;;;; +2F72;KANGXI RADICAL GRAIN;So;0;ON;<compat> 79BE;;;;N;;;;; +2F73;KANGXI RADICAL CAVE;So;0;ON;<compat> 7A74;;;;N;;;;; +2F74;KANGXI RADICAL STAND;So;0;ON;<compat> 7ACB;;;;N;;;;; +2F75;KANGXI RADICAL BAMBOO;So;0;ON;<compat> 7AF9;;;;N;;;;; +2F76;KANGXI RADICAL RICE;So;0;ON;<compat> 7C73;;;;N;;;;; +2F77;KANGXI RADICAL SILK;So;0;ON;<compat> 7CF8;;;;N;;;;; +2F78;KANGXI RADICAL JAR;So;0;ON;<compat> 7F36;;;;N;;;;; +2F79;KANGXI RADICAL NET;So;0;ON;<compat> 7F51;;;;N;;;;; +2F7A;KANGXI RADICAL SHEEP;So;0;ON;<compat> 7F8A;;;;N;;;;; +2F7B;KANGXI RADICAL FEATHER;So;0;ON;<compat> 7FBD;;;;N;;;;; +2F7C;KANGXI RADICAL OLD;So;0;ON;<compat> 8001;;;;N;;;;; +2F7D;KANGXI RADICAL AND;So;0;ON;<compat> 800C;;;;N;;;;; +2F7E;KANGXI RADICAL PLOW;So;0;ON;<compat> 8012;;;;N;;;;; +2F7F;KANGXI RADICAL EAR;So;0;ON;<compat> 8033;;;;N;;;;; +2F80;KANGXI RADICAL BRUSH;So;0;ON;<compat> 807F;;;;N;;;;; +2F81;KANGXI RADICAL MEAT;So;0;ON;<compat> 8089;;;;N;;;;; +2F82;KANGXI RADICAL MINISTER;So;0;ON;<compat> 81E3;;;;N;;;;; +2F83;KANGXI RADICAL SELF;So;0;ON;<compat> 81EA;;;;N;;;;; +2F84;KANGXI RADICAL ARRIVE;So;0;ON;<compat> 81F3;;;;N;;;;; +2F85;KANGXI RADICAL MORTAR;So;0;ON;<compat> 81FC;;;;N;;;;; +2F86;KANGXI RADICAL TONGUE;So;0;ON;<compat> 820C;;;;N;;;;; +2F87;KANGXI RADICAL OPPOSE;So;0;ON;<compat> 821B;;;;N;;;;; +2F88;KANGXI RADICAL BOAT;So;0;ON;<compat> 821F;;;;N;;;;; +2F89;KANGXI RADICAL STOPPING;So;0;ON;<compat> 826E;;;;N;;;;; +2F8A;KANGXI RADICAL COLOR;So;0;ON;<compat> 8272;;;;N;;;;; +2F8B;KANGXI RADICAL GRASS;So;0;ON;<compat> 8278;;;;N;;;;; +2F8C;KANGXI RADICAL TIGER;So;0;ON;<compat> 864D;;;;N;;;;; +2F8D;KANGXI RADICAL INSECT;So;0;ON;<compat> 866B;;;;N;;;;; +2F8E;KANGXI RADICAL BLOOD;So;0;ON;<compat> 8840;;;;N;;;;; +2F8F;KANGXI RADICAL WALK ENCLOSURE;So;0;ON;<compat> 884C;;;;N;;;;; +2F90;KANGXI RADICAL CLOTHES;So;0;ON;<compat> 8863;;;;N;;;;; +2F91;KANGXI RADICAL WEST;So;0;ON;<compat> 897E;;;;N;;;;; +2F92;KANGXI RADICAL SEE;So;0;ON;<compat> 898B;;;;N;;;;; +2F93;KANGXI RADICAL HORN;So;0;ON;<compat> 89D2;;;;N;;;;; +2F94;KANGXI RADICAL SPEECH;So;0;ON;<compat> 8A00;;;;N;;;;; +2F95;KANGXI RADICAL VALLEY;So;0;ON;<compat> 8C37;;;;N;;;;; +2F96;KANGXI RADICAL BEAN;So;0;ON;<compat> 8C46;;;;N;;;;; +2F97;KANGXI RADICAL PIG;So;0;ON;<compat> 8C55;;;;N;;;;; +2F98;KANGXI RADICAL BADGER;So;0;ON;<compat> 8C78;;;;N;;;;; +2F99;KANGXI RADICAL SHELL;So;0;ON;<compat> 8C9D;;;;N;;;;; +2F9A;KANGXI RADICAL RED;So;0;ON;<compat> 8D64;;;;N;;;;; +2F9B;KANGXI RADICAL RUN;So;0;ON;<compat> 8D70;;;;N;;;;; +2F9C;KANGXI RADICAL FOOT;So;0;ON;<compat> 8DB3;;;;N;;;;; +2F9D;KANGXI RADICAL BODY;So;0;ON;<compat> 8EAB;;;;N;;;;; +2F9E;KANGXI RADICAL CART;So;0;ON;<compat> 8ECA;;;;N;;;;; +2F9F;KANGXI RADICAL BITTER;So;0;ON;<compat> 8F9B;;;;N;;;;; +2FA0;KANGXI RADICAL MORNING;So;0;ON;<compat> 8FB0;;;;N;;;;; +2FA1;KANGXI RADICAL WALK;So;0;ON;<compat> 8FB5;;;;N;;;;; +2FA2;KANGXI RADICAL CITY;So;0;ON;<compat> 9091;;;;N;;;;; +2FA3;KANGXI RADICAL WINE;So;0;ON;<compat> 9149;;;;N;;;;; +2FA4;KANGXI RADICAL DISTINGUISH;So;0;ON;<compat> 91C6;;;;N;;;;; +2FA5;KANGXI RADICAL VILLAGE;So;0;ON;<compat> 91CC;;;;N;;;;; +2FA6;KANGXI RADICAL GOLD;So;0;ON;<compat> 91D1;;;;N;;;;; +2FA7;KANGXI RADICAL LONG;So;0;ON;<compat> 9577;;;;N;;;;; +2FA8;KANGXI RADICAL GATE;So;0;ON;<compat> 9580;;;;N;;;;; +2FA9;KANGXI RADICAL MOUND;So;0;ON;<compat> 961C;;;;N;;;;; +2FAA;KANGXI RADICAL SLAVE;So;0;ON;<compat> 96B6;;;;N;;;;; +2FAB;KANGXI RADICAL SHORT TAILED BIRD;So;0;ON;<compat> 96B9;;;;N;;;;; +2FAC;KANGXI RADICAL RAIN;So;0;ON;<compat> 96E8;;;;N;;;;; +2FAD;KANGXI RADICAL BLUE;So;0;ON;<compat> 9751;;;;N;;;;; +2FAE;KANGXI RADICAL WRONG;So;0;ON;<compat> 975E;;;;N;;;;; +2FAF;KANGXI RADICAL FACE;So;0;ON;<compat> 9762;;;;N;;;;; +2FB0;KANGXI RADICAL LEATHER;So;0;ON;<compat> 9769;;;;N;;;;; +2FB1;KANGXI RADICAL TANNED LEATHER;So;0;ON;<compat> 97CB;;;;N;;;;; +2FB2;KANGXI RADICAL LEEK;So;0;ON;<compat> 97ED;;;;N;;;;; +2FB3;KANGXI RADICAL SOUND;So;0;ON;<compat> 97F3;;;;N;;;;; +2FB4;KANGXI RADICAL LEAF;So;0;ON;<compat> 9801;;;;N;;;;; +2FB5;KANGXI RADICAL WIND;So;0;ON;<compat> 98A8;;;;N;;;;; +2FB6;KANGXI RADICAL FLY;So;0;ON;<compat> 98DB;;;;N;;;;; +2FB7;KANGXI RADICAL EAT;So;0;ON;<compat> 98DF;;;;N;;;;; +2FB8;KANGXI RADICAL HEAD;So;0;ON;<compat> 9996;;;;N;;;;; +2FB9;KANGXI RADICAL FRAGRANT;So;0;ON;<compat> 9999;;;;N;;;;; +2FBA;KANGXI RADICAL HORSE;So;0;ON;<compat> 99AC;;;;N;;;;; +2FBB;KANGXI RADICAL BONE;So;0;ON;<compat> 9AA8;;;;N;;;;; +2FBC;KANGXI RADICAL TALL;So;0;ON;<compat> 9AD8;;;;N;;;;; +2FBD;KANGXI RADICAL HAIR;So;0;ON;<compat> 9ADF;;;;N;;;;; +2FBE;KANGXI RADICAL FIGHT;So;0;ON;<compat> 9B25;;;;N;;;;; +2FBF;KANGXI RADICAL SACRIFICIAL WINE;So;0;ON;<compat> 9B2F;;;;N;;;;; +2FC0;KANGXI RADICAL CAULDRON;So;0;ON;<compat> 9B32;;;;N;;;;; +2FC1;KANGXI RADICAL GHOST;So;0;ON;<compat> 9B3C;;;;N;;;;; +2FC2;KANGXI RADICAL FISH;So;0;ON;<compat> 9B5A;;;;N;;;;; +2FC3;KANGXI RADICAL BIRD;So;0;ON;<compat> 9CE5;;;;N;;;;; +2FC4;KANGXI RADICAL SALT;So;0;ON;<compat> 9E75;;;;N;;;;; +2FC5;KANGXI RADICAL DEER;So;0;ON;<compat> 9E7F;;;;N;;;;; +2FC6;KANGXI RADICAL WHEAT;So;0;ON;<compat> 9EA5;;;;N;;;;; +2FC7;KANGXI RADICAL HEMP;So;0;ON;<compat> 9EBB;;;;N;;;;; +2FC8;KANGXI RADICAL YELLOW;So;0;ON;<compat> 9EC3;;;;N;;;;; +2FC9;KANGXI RADICAL MILLET;So;0;ON;<compat> 9ECD;;;;N;;;;; +2FCA;KANGXI RADICAL BLACK;So;0;ON;<compat> 9ED1;;;;N;;;;; +2FCB;KANGXI RADICAL EMBROIDERY;So;0;ON;<compat> 9EF9;;;;N;;;;; +2FCC;KANGXI RADICAL FROG;So;0;ON;<compat> 9EFD;;;;N;;;;; +2FCD;KANGXI RADICAL TRIPOD;So;0;ON;<compat> 9F0E;;;;N;;;;; +2FCE;KANGXI RADICAL DRUM;So;0;ON;<compat> 9F13;;;;N;;;;; +2FCF;KANGXI RADICAL RAT;So;0;ON;<compat> 9F20;;;;N;;;;; +2FD0;KANGXI RADICAL NOSE;So;0;ON;<compat> 9F3B;;;;N;;;;; +2FD1;KANGXI RADICAL EVEN;So;0;ON;<compat> 9F4A;;;;N;;;;; +2FD2;KANGXI RADICAL TOOTH;So;0;ON;<compat> 9F52;;;;N;;;;; +2FD3;KANGXI RADICAL DRAGON;So;0;ON;<compat> 9F8D;;;;N;;;;; +2FD4;KANGXI RADICAL TURTLE;So;0;ON;<compat> 9F9C;;;;N;;;;; +2FD5;KANGXI RADICAL FLUTE;So;0;ON;<compat> 9FA0;;;;N;;;;; +2FF0;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT;So;0;ON;;;;;N;;;;; +2FF1;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW;So;0;ON;;;;;N;;;;; +2FF2;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT;So;0;ON;;;;;N;;;;; +2FF3;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW;So;0;ON;;;;;N;;;;; +2FF4;IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND;So;0;ON;;;;;N;;;;; +2FF5;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE;So;0;ON;;;;;N;;;;; +2FF6;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW;So;0;ON;;;;;N;;;;; +2FF7;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT;So;0;ON;;;;;N;;;;; +2FF8;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT;So;0;ON;;;;;N;;;;; +2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;; +2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;; +2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;; +3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;; +3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;; +3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;; +3003;DITTO MARK;Po;0;ON;;;;;N;;;;; +3004;JAPANESE INDUSTRIAL STANDARD SYMBOL;So;0;ON;;;;;N;;;;; +3005;IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; +3006;IDEOGRAPHIC CLOSING MARK;Lo;0;L;;;;;N;;;;; +3007;IDEOGRAPHIC NUMBER ZERO;Nl;0;L;;;;0;N;;;;; +3008;LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING ANGLE BRACKET;;;; +3009;RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING ANGLE BRACKET;;;; +300A;LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING DOUBLE ANGLE BRACKET;;;; +300B;RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING DOUBLE ANGLE BRACKET;;;; +300C;LEFT CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING CORNER BRACKET;;;; +300D;RIGHT CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING CORNER BRACKET;;;; +300E;LEFT WHITE CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE CORNER BRACKET;;;; +300F;RIGHT WHITE CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE CORNER BRACKET;;;; +3010;LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING BLACK LENTICULAR BRACKET;;;; +3011;RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING BLACK LENTICULAR BRACKET;;;; +3012;POSTAL MARK;So;0;ON;;;;;N;;;;; +3013;GETA MARK;So;0;ON;;;;;N;;;;; +3014;LEFT TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING TORTOISE SHELL BRACKET;;;; +3015;RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING TORTOISE SHELL BRACKET;;;; +3016;LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE LENTICULAR BRACKET;;;; +3017;RIGHT WHITE LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE LENTICULAR BRACKET;;;; +3018;LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE TORTOISE SHELL BRACKET;;;; +3019;RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE TORTOISE SHELL BRACKET;;;; +301A;LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE SQUARE BRACKET;;;; +301B;RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE SQUARE BRACKET;;;; +301C;WAVE DASH;Pd;0;ON;;;;;N;;;;; +301D;REVERSED DOUBLE PRIME QUOTATION MARK;Ps;0;ON;;;;;N;;;;; +301E;DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; +301F;LOW DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; +3020;POSTAL MARK FACE;So;0;ON;;;;;N;;;;; +3021;HANGZHOU NUMERAL ONE;Nl;0;L;;;;1;N;;;;; +3022;HANGZHOU NUMERAL TWO;Nl;0;L;;;;2;N;;;;; +3023;HANGZHOU NUMERAL THREE;Nl;0;L;;;;3;N;;;;; +3024;HANGZHOU NUMERAL FOUR;Nl;0;L;;;;4;N;;;;; +3025;HANGZHOU NUMERAL FIVE;Nl;0;L;;;;5;N;;;;; +3026;HANGZHOU NUMERAL SIX;Nl;0;L;;;;6;N;;;;; +3027;HANGZHOU NUMERAL SEVEN;Nl;0;L;;;;7;N;;;;; +3028;HANGZHOU NUMERAL EIGHT;Nl;0;L;;;;8;N;;;;; +3029;HANGZHOU NUMERAL NINE;Nl;0;L;;;;9;N;;;;; +302A;IDEOGRAPHIC LEVEL TONE MARK;Mn;218;NSM;;;;;N;;;;; +302B;IDEOGRAPHIC RISING TONE MARK;Mn;228;NSM;;;;;N;;;;; +302C;IDEOGRAPHIC DEPARTING TONE MARK;Mn;232;NSM;;;;;N;;;;; +302D;IDEOGRAPHIC ENTERING TONE MARK;Mn;222;NSM;;;;;N;;;;; +302E;HANGUL SINGLE DOT TONE MARK;Mc;224;L;;;;;N;;;;; +302F;HANGUL DOUBLE DOT TONE MARK;Mc;224;L;;;;;N;;;;; +3030;WAVY DASH;Pd;0;ON;;;;;N;;;;; +3031;VERTICAL KANA REPEAT MARK;Lm;0;L;;;;;N;;;;; +3032;VERTICAL KANA REPEAT WITH VOICED SOUND MARK;Lm;0;L;;;;;N;;;;; +3033;VERTICAL KANA REPEAT MARK UPPER HALF;Lm;0;L;;;;;N;;;;; +3034;VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF;Lm;0;L;;;;;N;;;;; +3035;VERTICAL KANA REPEAT MARK LOWER HALF;Lm;0;L;;;;;N;;;;; +3036;CIRCLED POSTAL MARK;So;0;ON;<compat> 3012;;;;N;;;;; +3037;IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL;So;0;ON;;;;;N;;;;; +3038;HANGZHOU NUMERAL TEN;Nl;0;L;<compat> 5341;;;10;N;;;;; +3039;HANGZHOU NUMERAL TWENTY;Nl;0;L;<compat> 5344;;;20;N;;;;; +303A;HANGZHOU NUMERAL THIRTY;Nl;0;L;<compat> 5345;;;30;N;;;;; +303B;VERTICAL IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; +303C;MASU MARK;Lo;0;L;;;;;N;;;;; +303D;PART ALTERNATION MARK;Po;0;ON;;;;;N;;;;; +303E;IDEOGRAPHIC VARIATION INDICATOR;So;0;ON;;;;;N;;;;; +303F;IDEOGRAPHIC HALF FILL SPACE;So;0;ON;;;;;N;;;;; +3041;HIRAGANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; +3042;HIRAGANA LETTER A;Lo;0;L;;;;;N;;;;; +3043;HIRAGANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; +3044;HIRAGANA LETTER I;Lo;0;L;;;;;N;;;;; +3045;HIRAGANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; +3046;HIRAGANA LETTER U;Lo;0;L;;;;;N;;;;; +3047;HIRAGANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; +3048;HIRAGANA LETTER E;Lo;0;L;;;;;N;;;;; +3049;HIRAGANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; +304A;HIRAGANA LETTER O;Lo;0;L;;;;;N;;;;; +304B;HIRAGANA LETTER KA;Lo;0;L;;;;;N;;;;; +304C;HIRAGANA LETTER GA;Lo;0;L;304B 3099;;;;N;;;;; +304D;HIRAGANA LETTER KI;Lo;0;L;;;;;N;;;;; +304E;HIRAGANA LETTER GI;Lo;0;L;304D 3099;;;;N;;;;; +304F;HIRAGANA LETTER KU;Lo;0;L;;;;;N;;;;; +3050;HIRAGANA LETTER GU;Lo;0;L;304F 3099;;;;N;;;;; +3051;HIRAGANA LETTER KE;Lo;0;L;;;;;N;;;;; +3052;HIRAGANA LETTER GE;Lo;0;L;3051 3099;;;;N;;;;; +3053;HIRAGANA LETTER KO;Lo;0;L;;;;;N;;;;; +3054;HIRAGANA LETTER GO;Lo;0;L;3053 3099;;;;N;;;;; +3055;HIRAGANA LETTER SA;Lo;0;L;;;;;N;;;;; +3056;HIRAGANA LETTER ZA;Lo;0;L;3055 3099;;;;N;;;;; +3057;HIRAGANA LETTER SI;Lo;0;L;;;;;N;;;;; +3058;HIRAGANA LETTER ZI;Lo;0;L;3057 3099;;;;N;;;;; +3059;HIRAGANA LETTER SU;Lo;0;L;;;;;N;;;;; +305A;HIRAGANA LETTER ZU;Lo;0;L;3059 3099;;;;N;;;;; +305B;HIRAGANA LETTER SE;Lo;0;L;;;;;N;;;;; +305C;HIRAGANA LETTER ZE;Lo;0;L;305B 3099;;;;N;;;;; +305D;HIRAGANA LETTER SO;Lo;0;L;;;;;N;;;;; +305E;HIRAGANA LETTER ZO;Lo;0;L;305D 3099;;;;N;;;;; +305F;HIRAGANA LETTER TA;Lo;0;L;;;;;N;;;;; +3060;HIRAGANA LETTER DA;Lo;0;L;305F 3099;;;;N;;;;; +3061;HIRAGANA LETTER TI;Lo;0;L;;;;;N;;;;; +3062;HIRAGANA LETTER DI;Lo;0;L;3061 3099;;;;N;;;;; +3063;HIRAGANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; +3064;HIRAGANA LETTER TU;Lo;0;L;;;;;N;;;;; +3065;HIRAGANA LETTER DU;Lo;0;L;3064 3099;;;;N;;;;; +3066;HIRAGANA LETTER TE;Lo;0;L;;;;;N;;;;; +3067;HIRAGANA LETTER DE;Lo;0;L;3066 3099;;;;N;;;;; +3068;HIRAGANA LETTER TO;Lo;0;L;;;;;N;;;;; +3069;HIRAGANA LETTER DO;Lo;0;L;3068 3099;;;;N;;;;; +306A;HIRAGANA LETTER NA;Lo;0;L;;;;;N;;;;; +306B;HIRAGANA LETTER NI;Lo;0;L;;;;;N;;;;; +306C;HIRAGANA LETTER NU;Lo;0;L;;;;;N;;;;; +306D;HIRAGANA LETTER NE;Lo;0;L;;;;;N;;;;; +306E;HIRAGANA LETTER NO;Lo;0;L;;;;;N;;;;; +306F;HIRAGANA LETTER HA;Lo;0;L;;;;;N;;;;; +3070;HIRAGANA LETTER BA;Lo;0;L;306F 3099;;;;N;;;;; +3071;HIRAGANA LETTER PA;Lo;0;L;306F 309A;;;;N;;;;; +3072;HIRAGANA LETTER HI;Lo;0;L;;;;;N;;;;; +3073;HIRAGANA LETTER BI;Lo;0;L;3072 3099;;;;N;;;;; +3074;HIRAGANA LETTER PI;Lo;0;L;3072 309A;;;;N;;;;; +3075;HIRAGANA LETTER HU;Lo;0;L;;;;;N;;;;; +3076;HIRAGANA LETTER BU;Lo;0;L;3075 3099;;;;N;;;;; +3077;HIRAGANA LETTER PU;Lo;0;L;3075 309A;;;;N;;;;; +3078;HIRAGANA LETTER HE;Lo;0;L;;;;;N;;;;; +3079;HIRAGANA LETTER BE;Lo;0;L;3078 3099;;;;N;;;;; +307A;HIRAGANA LETTER PE;Lo;0;L;3078 309A;;;;N;;;;; +307B;HIRAGANA LETTER HO;Lo;0;L;;;;;N;;;;; +307C;HIRAGANA LETTER BO;Lo;0;L;307B 3099;;;;N;;;;; +307D;HIRAGANA LETTER PO;Lo;0;L;307B 309A;;;;N;;;;; +307E;HIRAGANA LETTER MA;Lo;0;L;;;;;N;;;;; +307F;HIRAGANA LETTER MI;Lo;0;L;;;;;N;;;;; +3080;HIRAGANA LETTER MU;Lo;0;L;;;;;N;;;;; +3081;HIRAGANA LETTER ME;Lo;0;L;;;;;N;;;;; +3082;HIRAGANA LETTER MO;Lo;0;L;;;;;N;;;;; +3083;HIRAGANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; +3084;HIRAGANA LETTER YA;Lo;0;L;;;;;N;;;;; +3085;HIRAGANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; +3086;HIRAGANA LETTER YU;Lo;0;L;;;;;N;;;;; +3087;HIRAGANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; +3088;HIRAGANA LETTER YO;Lo;0;L;;;;;N;;;;; +3089;HIRAGANA LETTER RA;Lo;0;L;;;;;N;;;;; +308A;HIRAGANA LETTER RI;Lo;0;L;;;;;N;;;;; +308B;HIRAGANA LETTER RU;Lo;0;L;;;;;N;;;;; +308C;HIRAGANA LETTER RE;Lo;0;L;;;;;N;;;;; +308D;HIRAGANA LETTER RO;Lo;0;L;;;;;N;;;;; +308E;HIRAGANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; +308F;HIRAGANA LETTER WA;Lo;0;L;;;;;N;;;;; +3090;HIRAGANA LETTER WI;Lo;0;L;;;;;N;;;;; +3091;HIRAGANA LETTER WE;Lo;0;L;;;;;N;;;;; +3092;HIRAGANA LETTER WO;Lo;0;L;;;;;N;;;;; +3093;HIRAGANA LETTER N;Lo;0;L;;;;;N;;;;; +3094;HIRAGANA LETTER VU;Lo;0;L;3046 3099;;;;N;;;;; +3095;HIRAGANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; +3096;HIRAGANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; +3099;COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA VOICED SOUND MARK;;;; +309A;COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;;;; +309B;KATAKANA-HIRAGANA VOICED SOUND MARK;Sk;0;ON;<compat> 0020 3099;;;;N;;;;; +309C;KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Sk;0;ON;<compat> 0020 309A;;;;N;;;;; +309D;HIRAGANA ITERATION MARK;Lm;0;L;;;;;N;;;;; +309E;HIRAGANA VOICED ITERATION MARK;Lm;0;L;309D 3099;;;;N;;;;; +309F;HIRAGANA DIGRAPH YORI;Lo;0;L;<vertical> 3088 308A;;;;N;;;;; +30A0;KATAKANA-HIRAGANA DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; +30A1;KATAKANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; +30A2;KATAKANA LETTER A;Lo;0;L;;;;;N;;;;; +30A3;KATAKANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; +30A4;KATAKANA LETTER I;Lo;0;L;;;;;N;;;;; +30A5;KATAKANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; +30A6;KATAKANA LETTER U;Lo;0;L;;;;;N;;;;; +30A7;KATAKANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; +30A8;KATAKANA LETTER E;Lo;0;L;;;;;N;;;;; +30A9;KATAKANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; +30AA;KATAKANA LETTER O;Lo;0;L;;;;;N;;;;; +30AB;KATAKANA LETTER KA;Lo;0;L;;;;;N;;;;; +30AC;KATAKANA LETTER GA;Lo;0;L;30AB 3099;;;;N;;;;; +30AD;KATAKANA LETTER KI;Lo;0;L;;;;;N;;;;; +30AE;KATAKANA LETTER GI;Lo;0;L;30AD 3099;;;;N;;;;; +30AF;KATAKANA LETTER KU;Lo;0;L;;;;;N;;;;; +30B0;KATAKANA LETTER GU;Lo;0;L;30AF 3099;;;;N;;;;; +30B1;KATAKANA LETTER KE;Lo;0;L;;;;;N;;;;; +30B2;KATAKANA LETTER GE;Lo;0;L;30B1 3099;;;;N;;;;; +30B3;KATAKANA LETTER KO;Lo;0;L;;;;;N;;;;; +30B4;KATAKANA LETTER GO;Lo;0;L;30B3 3099;;;;N;;;;; +30B5;KATAKANA LETTER SA;Lo;0;L;;;;;N;;;;; +30B6;KATAKANA LETTER ZA;Lo;0;L;30B5 3099;;;;N;;;;; +30B7;KATAKANA LETTER SI;Lo;0;L;;;;;N;;;;; +30B8;KATAKANA LETTER ZI;Lo;0;L;30B7 3099;;;;N;;;;; +30B9;KATAKANA LETTER SU;Lo;0;L;;;;;N;;;;; +30BA;KATAKANA LETTER ZU;Lo;0;L;30B9 3099;;;;N;;;;; +30BB;KATAKANA LETTER SE;Lo;0;L;;;;;N;;;;; +30BC;KATAKANA LETTER ZE;Lo;0;L;30BB 3099;;;;N;;;;; +30BD;KATAKANA LETTER SO;Lo;0;L;;;;;N;;;;; +30BE;KATAKANA LETTER ZO;Lo;0;L;30BD 3099;;;;N;;;;; +30BF;KATAKANA LETTER TA;Lo;0;L;;;;;N;;;;; +30C0;KATAKANA LETTER DA;Lo;0;L;30BF 3099;;;;N;;;;; +30C1;KATAKANA LETTER TI;Lo;0;L;;;;;N;;;;; +30C2;KATAKANA LETTER DI;Lo;0;L;30C1 3099;;;;N;;;;; +30C3;KATAKANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; +30C4;KATAKANA LETTER TU;Lo;0;L;;;;;N;;;;; +30C5;KATAKANA LETTER DU;Lo;0;L;30C4 3099;;;;N;;;;; +30C6;KATAKANA LETTER TE;Lo;0;L;;;;;N;;;;; +30C7;KATAKANA LETTER DE;Lo;0;L;30C6 3099;;;;N;;;;; +30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;; +30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;; +30CA;KATAKANA LETTER NA;Lo;0;L;;;;;N;;;;; +30CB;KATAKANA LETTER NI;Lo;0;L;;;;;N;;;;; +30CC;KATAKANA LETTER NU;Lo;0;L;;;;;N;;;;; +30CD;KATAKANA LETTER NE;Lo;0;L;;;;;N;;;;; +30CE;KATAKANA LETTER NO;Lo;0;L;;;;;N;;;;; +30CF;KATAKANA LETTER HA;Lo;0;L;;;;;N;;;;; +30D0;KATAKANA LETTER BA;Lo;0;L;30CF 3099;;;;N;;;;; +30D1;KATAKANA LETTER PA;Lo;0;L;30CF 309A;;;;N;;;;; +30D2;KATAKANA LETTER HI;Lo;0;L;;;;;N;;;;; +30D3;KATAKANA LETTER BI;Lo;0;L;30D2 3099;;;;N;;;;; +30D4;KATAKANA LETTER PI;Lo;0;L;30D2 309A;;;;N;;;;; +30D5;KATAKANA LETTER HU;Lo;0;L;;;;;N;;;;; +30D6;KATAKANA LETTER BU;Lo;0;L;30D5 3099;;;;N;;;;; +30D7;KATAKANA LETTER PU;Lo;0;L;30D5 309A;;;;N;;;;; +30D8;KATAKANA LETTER HE;Lo;0;L;;;;;N;;;;; +30D9;KATAKANA LETTER BE;Lo;0;L;30D8 3099;;;;N;;;;; +30DA;KATAKANA LETTER PE;Lo;0;L;30D8 309A;;;;N;;;;; +30DB;KATAKANA LETTER HO;Lo;0;L;;;;;N;;;;; +30DC;KATAKANA LETTER BO;Lo;0;L;30DB 3099;;;;N;;;;; +30DD;KATAKANA LETTER PO;Lo;0;L;30DB 309A;;;;N;;;;; +30DE;KATAKANA LETTER MA;Lo;0;L;;;;;N;;;;; +30DF;KATAKANA LETTER MI;Lo;0;L;;;;;N;;;;; +30E0;KATAKANA LETTER MU;Lo;0;L;;;;;N;;;;; +30E1;KATAKANA LETTER ME;Lo;0;L;;;;;N;;;;; +30E2;KATAKANA LETTER MO;Lo;0;L;;;;;N;;;;; +30E3;KATAKANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; +30E4;KATAKANA LETTER YA;Lo;0;L;;;;;N;;;;; +30E5;KATAKANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; +30E6;KATAKANA LETTER YU;Lo;0;L;;;;;N;;;;; +30E7;KATAKANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; +30E8;KATAKANA LETTER YO;Lo;0;L;;;;;N;;;;; +30E9;KATAKANA LETTER RA;Lo;0;L;;;;;N;;;;; +30EA;KATAKANA LETTER RI;Lo;0;L;;;;;N;;;;; +30EB;KATAKANA LETTER RU;Lo;0;L;;;;;N;;;;; +30EC;KATAKANA LETTER RE;Lo;0;L;;;;;N;;;;; +30ED;KATAKANA LETTER RO;Lo;0;L;;;;;N;;;;; +30EE;KATAKANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; +30EF;KATAKANA LETTER WA;Lo;0;L;;;;;N;;;;; +30F0;KATAKANA LETTER WI;Lo;0;L;;;;;N;;;;; +30F1;KATAKANA LETTER WE;Lo;0;L;;;;;N;;;;; +30F2;KATAKANA LETTER WO;Lo;0;L;;;;;N;;;;; +30F3;KATAKANA LETTER N;Lo;0;L;;;;;N;;;;; +30F4;KATAKANA LETTER VU;Lo;0;L;30A6 3099;;;;N;;;;; +30F5;KATAKANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; +30F6;KATAKANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; +30F7;KATAKANA LETTER VA;Lo;0;L;30EF 3099;;;;N;;;;; +30F8;KATAKANA LETTER VI;Lo;0;L;30F0 3099;;;;N;;;;; +30F9;KATAKANA LETTER VE;Lo;0;L;30F1 3099;;;;N;;;;; +30FA;KATAKANA LETTER VO;Lo;0;L;30F2 3099;;;;N;;;;; +30FB;KATAKANA MIDDLE DOT;Po;0;ON;;;;;N;;;;; +30FC;KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;;;;;N;;;;; +30FD;KATAKANA ITERATION MARK;Lm;0;L;;;;;N;;;;; +30FE;KATAKANA VOICED ITERATION MARK;Lm;0;L;30FD 3099;;;;N;;;;; +30FF;KATAKANA DIGRAPH KOTO;Lo;0;L;<vertical> 30B3 30C8;;;;N;;;;; +3105;BOPOMOFO LETTER B;Lo;0;L;;;;;N;;;;; +3106;BOPOMOFO LETTER P;Lo;0;L;;;;;N;;;;; +3107;BOPOMOFO LETTER M;Lo;0;L;;;;;N;;;;; +3108;BOPOMOFO LETTER F;Lo;0;L;;;;;N;;;;; +3109;BOPOMOFO LETTER D;Lo;0;L;;;;;N;;;;; +310A;BOPOMOFO LETTER T;Lo;0;L;;;;;N;;;;; +310B;BOPOMOFO LETTER N;Lo;0;L;;;;;N;;;;; +310C;BOPOMOFO LETTER L;Lo;0;L;;;;;N;;;;; +310D;BOPOMOFO LETTER G;Lo;0;L;;;;;N;;;;; +310E;BOPOMOFO LETTER K;Lo;0;L;;;;;N;;;;; +310F;BOPOMOFO LETTER H;Lo;0;L;;;;;N;;;;; +3110;BOPOMOFO LETTER J;Lo;0;L;;;;;N;;;;; +3111;BOPOMOFO LETTER Q;Lo;0;L;;;;;N;;;;; +3112;BOPOMOFO LETTER X;Lo;0;L;;;;;N;;;;; +3113;BOPOMOFO LETTER ZH;Lo;0;L;;;;;N;;;;; +3114;BOPOMOFO LETTER CH;Lo;0;L;;;;;N;;;;; +3115;BOPOMOFO LETTER SH;Lo;0;L;;;;;N;;;;; +3116;BOPOMOFO LETTER R;Lo;0;L;;;;;N;;;;; +3117;BOPOMOFO LETTER Z;Lo;0;L;;;;;N;;;;; +3118;BOPOMOFO LETTER C;Lo;0;L;;;;;N;;;;; +3119;BOPOMOFO LETTER S;Lo;0;L;;;;;N;;;;; +311A;BOPOMOFO LETTER A;Lo;0;L;;;;;N;;;;; +311B;BOPOMOFO LETTER O;Lo;0;L;;;;;N;;;;; +311C;BOPOMOFO LETTER E;Lo;0;L;;;;;N;;;;; +311D;BOPOMOFO LETTER EH;Lo;0;L;;;;;N;;;;; +311E;BOPOMOFO LETTER AI;Lo;0;L;;;;;N;;;;; +311F;BOPOMOFO LETTER EI;Lo;0;L;;;;;N;;;;; +3120;BOPOMOFO LETTER AU;Lo;0;L;;;;;N;;;;; +3121;BOPOMOFO LETTER OU;Lo;0;L;;;;;N;;;;; +3122;BOPOMOFO LETTER AN;Lo;0;L;;;;;N;;;;; +3123;BOPOMOFO LETTER EN;Lo;0;L;;;;;N;;;;; +3124;BOPOMOFO LETTER ANG;Lo;0;L;;;;;N;;;;; +3125;BOPOMOFO LETTER ENG;Lo;0;L;;;;;N;;;;; +3126;BOPOMOFO LETTER ER;Lo;0;L;;;;;N;;;;; +3127;BOPOMOFO LETTER I;Lo;0;L;;;;;N;;;;; +3128;BOPOMOFO LETTER U;Lo;0;L;;;;;N;;;;; +3129;BOPOMOFO LETTER IU;Lo;0;L;;;;;N;;;;; +312A;BOPOMOFO LETTER V;Lo;0;L;;;;;N;;;;; +312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; +312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; +312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;; +312E;BOPOMOFO LETTER O WITH DOT ABOVE;Lo;0;L;;;;;N;;;;; +3131;HANGUL LETTER KIYEOK;Lo;0;L;<compat> 1100;;;;N;HANGUL LETTER GIYEOG;;;; +3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L;<compat> 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; +3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; +3134;HANGUL LETTER NIEUN;Lo;0;L;<compat> 1102;;;;N;;;;; +3135;HANGUL LETTER NIEUN-CIEUC;Lo;0;L;<compat> 11AC;;;;N;HANGUL LETTER NIEUN JIEUJ;;;; +3136;HANGUL LETTER NIEUN-HIEUH;Lo;0;L;<compat> 11AD;;;;N;HANGUL LETTER NIEUN HIEUH;;;; +3137;HANGUL LETTER TIKEUT;Lo;0;L;<compat> 1103;;;;N;HANGUL LETTER DIGEUD;;;; +3138;HANGUL LETTER SSANGTIKEUT;Lo;0;L;<compat> 1104;;;;N;HANGUL LETTER SSANG DIGEUD;;;; +3139;HANGUL LETTER RIEUL;Lo;0;L;<compat> 1105;;;;N;HANGUL LETTER LIEUL;;;; +313A;HANGUL LETTER RIEUL-KIYEOK;Lo;0;L;<compat> 11B0;;;;N;HANGUL LETTER LIEUL GIYEOG;;;; +313B;HANGUL LETTER RIEUL-MIEUM;Lo;0;L;<compat> 11B1;;;;N;HANGUL LETTER LIEUL MIEUM;;;; +313C;HANGUL LETTER RIEUL-PIEUP;Lo;0;L;<compat> 11B2;;;;N;HANGUL LETTER LIEUL BIEUB;;;; +313D;HANGUL LETTER RIEUL-SIOS;Lo;0;L;<compat> 11B3;;;;N;HANGUL LETTER LIEUL SIOS;;;; +313E;HANGUL LETTER RIEUL-THIEUTH;Lo;0;L;<compat> 11B4;;;;N;HANGUL LETTER LIEUL TIEUT;;;; +313F;HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L;<compat> 11B5;;;;N;HANGUL LETTER LIEUL PIEUP;;;; +3140;HANGUL LETTER RIEUL-HIEUH;Lo;0;L;<compat> 111A;;;;N;HANGUL LETTER LIEUL HIEUH;;;; +3141;HANGUL LETTER MIEUM;Lo;0;L;<compat> 1106;;;;N;;;;; +3142;HANGUL LETTER PIEUP;Lo;0;L;<compat> 1107;;;;N;HANGUL LETTER BIEUB;;;; +3143;HANGUL LETTER SSANGPIEUP;Lo;0;L;<compat> 1108;;;;N;HANGUL LETTER SSANG BIEUB;;;; +3144;HANGUL LETTER PIEUP-SIOS;Lo;0;L;<compat> 1121;;;;N;HANGUL LETTER BIEUB SIOS;;;; +3145;HANGUL LETTER SIOS;Lo;0;L;<compat> 1109;;;;N;;;;; +3146;HANGUL LETTER SSANGSIOS;Lo;0;L;<compat> 110A;;;;N;HANGUL LETTER SSANG SIOS;;;; +3147;HANGUL LETTER IEUNG;Lo;0;L;<compat> 110B;;;;N;;;;; +3148;HANGUL LETTER CIEUC;Lo;0;L;<compat> 110C;;;;N;HANGUL LETTER JIEUJ;;;; +3149;HANGUL LETTER SSANGCIEUC;Lo;0;L;<compat> 110D;;;;N;HANGUL LETTER SSANG JIEUJ;;;; +314A;HANGUL LETTER CHIEUCH;Lo;0;L;<compat> 110E;;;;N;HANGUL LETTER CIEUC;;;; +314B;HANGUL LETTER KHIEUKH;Lo;0;L;<compat> 110F;;;;N;HANGUL LETTER KIYEOK;;;; +314C;HANGUL LETTER THIEUTH;Lo;0;L;<compat> 1110;;;;N;HANGUL LETTER TIEUT;;;; +314D;HANGUL LETTER PHIEUPH;Lo;0;L;<compat> 1111;;;;N;HANGUL LETTER PIEUP;;;; +314E;HANGUL LETTER HIEUH;Lo;0;L;<compat> 1112;;;;N;;;;; +314F;HANGUL LETTER A;Lo;0;L;<compat> 1161;;;;N;;;;; +3150;HANGUL LETTER AE;Lo;0;L;<compat> 1162;;;;N;;;;; +3151;HANGUL LETTER YA;Lo;0;L;<compat> 1163;;;;N;;;;; +3152;HANGUL LETTER YAE;Lo;0;L;<compat> 1164;;;;N;;;;; +3153;HANGUL LETTER EO;Lo;0;L;<compat> 1165;;;;N;;;;; +3154;HANGUL LETTER E;Lo;0;L;<compat> 1166;;;;N;;;;; +3155;HANGUL LETTER YEO;Lo;0;L;<compat> 1167;;;;N;;;;; +3156;HANGUL LETTER YE;Lo;0;L;<compat> 1168;;;;N;;;;; +3157;HANGUL LETTER O;Lo;0;L;<compat> 1169;;;;N;;;;; +3158;HANGUL LETTER WA;Lo;0;L;<compat> 116A;;;;N;;;;; +3159;HANGUL LETTER WAE;Lo;0;L;<compat> 116B;;;;N;;;;; +315A;HANGUL LETTER OE;Lo;0;L;<compat> 116C;;;;N;;;;; +315B;HANGUL LETTER YO;Lo;0;L;<compat> 116D;;;;N;;;;; +315C;HANGUL LETTER U;Lo;0;L;<compat> 116E;;;;N;;;;; +315D;HANGUL LETTER WEO;Lo;0;L;<compat> 116F;;;;N;;;;; +315E;HANGUL LETTER WE;Lo;0;L;<compat> 1170;;;;N;;;;; +315F;HANGUL LETTER WI;Lo;0;L;<compat> 1171;;;;N;;;;; +3160;HANGUL LETTER YU;Lo;0;L;<compat> 1172;;;;N;;;;; +3161;HANGUL LETTER EU;Lo;0;L;<compat> 1173;;;;N;;;;; +3162;HANGUL LETTER YI;Lo;0;L;<compat> 1174;;;;N;;;;; +3163;HANGUL LETTER I;Lo;0;L;<compat> 1175;;;;N;;;;; +3164;HANGUL FILLER;Lo;0;L;<compat> 1160;;;;N;HANGUL CAE OM;;;; +3165;HANGUL LETTER SSANGNIEUN;Lo;0;L;<compat> 1114;;;;N;HANGUL LETTER SSANG NIEUN;;;; +3166;HANGUL LETTER NIEUN-TIKEUT;Lo;0;L;<compat> 1115;;;;N;HANGUL LETTER NIEUN DIGEUD;;;; +3167;HANGUL LETTER NIEUN-SIOS;Lo;0;L;<compat> 11C7;;;;N;HANGUL LETTER NIEUN SIOS;;;; +3168;HANGUL LETTER NIEUN-PANSIOS;Lo;0;L;<compat> 11C8;;;;N;HANGUL LETTER NIEUN BAN CHI EUM;;;; +3169;HANGUL LETTER RIEUL-KIYEOK-SIOS;Lo;0;L;<compat> 11CC;;;;N;HANGUL LETTER LIEUL GIYEOG SIOS;;;; +316A;HANGUL LETTER RIEUL-TIKEUT;Lo;0;L;<compat> 11CE;;;;N;HANGUL LETTER LIEUL DIGEUD;;;; +316B;HANGUL LETTER RIEUL-PIEUP-SIOS;Lo;0;L;<compat> 11D3;;;;N;HANGUL LETTER LIEUL BIEUB SIOS;;;; +316C;HANGUL LETTER RIEUL-PANSIOS;Lo;0;L;<compat> 11D7;;;;N;HANGUL LETTER LIEUL BAN CHI EUM;;;; +316D;HANGUL LETTER RIEUL-YEORINHIEUH;Lo;0;L;<compat> 11D9;;;;N;HANGUL LETTER LIEUL YEOLIN HIEUH;;;; +316E;HANGUL LETTER MIEUM-PIEUP;Lo;0;L;<compat> 111C;;;;N;HANGUL LETTER MIEUM BIEUB;;;; +316F;HANGUL LETTER MIEUM-SIOS;Lo;0;L;<compat> 11DD;;;;N;HANGUL LETTER MIEUM SIOS;;;; +3170;HANGUL LETTER MIEUM-PANSIOS;Lo;0;L;<compat> 11DF;;;;N;HANGUL LETTER BIEUB BAN CHI EUM;;;; +3171;HANGUL LETTER KAPYEOUNMIEUM;Lo;0;L;<compat> 111D;;;;N;HANGUL LETTER MIEUM SUN GYEONG EUM;;;; +3172;HANGUL LETTER PIEUP-KIYEOK;Lo;0;L;<compat> 111E;;;;N;HANGUL LETTER BIEUB GIYEOG;;;; +3173;HANGUL LETTER PIEUP-TIKEUT;Lo;0;L;<compat> 1120;;;;N;HANGUL LETTER BIEUB DIGEUD;;;; +3174;HANGUL LETTER PIEUP-SIOS-KIYEOK;Lo;0;L;<compat> 1122;;;;N;HANGUL LETTER BIEUB SIOS GIYEOG;;;; +3175;HANGUL LETTER PIEUP-SIOS-TIKEUT;Lo;0;L;<compat> 1123;;;;N;HANGUL LETTER BIEUB SIOS DIGEUD;;;; +3176;HANGUL LETTER PIEUP-CIEUC;Lo;0;L;<compat> 1127;;;;N;HANGUL LETTER BIEUB JIEUJ;;;; +3177;HANGUL LETTER PIEUP-THIEUTH;Lo;0;L;<compat> 1129;;;;N;HANGUL LETTER BIEUB TIEUT;;;; +3178;HANGUL LETTER KAPYEOUNPIEUP;Lo;0;L;<compat> 112B;;;;N;HANGUL LETTER BIEUB SUN GYEONG EUM;;;; +3179;HANGUL LETTER KAPYEOUNSSANGPIEUP;Lo;0;L;<compat> 112C;;;;N;HANGUL LETTER SSANG BIEUB SUN GYEONG EUM;;;; +317A;HANGUL LETTER SIOS-KIYEOK;Lo;0;L;<compat> 112D;;;;N;HANGUL LETTER SIOS GIYEOG;;;; +317B;HANGUL LETTER SIOS-NIEUN;Lo;0;L;<compat> 112E;;;;N;HANGUL LETTER SIOS NIEUN;;;; +317C;HANGUL LETTER SIOS-TIKEUT;Lo;0;L;<compat> 112F;;;;N;HANGUL LETTER SIOS DIGEUD;;;; +317D;HANGUL LETTER SIOS-PIEUP;Lo;0;L;<compat> 1132;;;;N;HANGUL LETTER SIOS BIEUB;;;; +317E;HANGUL LETTER SIOS-CIEUC;Lo;0;L;<compat> 1136;;;;N;HANGUL LETTER SIOS JIEUJ;;;; +317F;HANGUL LETTER PANSIOS;Lo;0;L;<compat> 1140;;;;N;HANGUL LETTER BAN CHI EUM;;;; +3180;HANGUL LETTER SSANGIEUNG;Lo;0;L;<compat> 1147;;;;N;HANGUL LETTER SSANG IEUNG;;;; +3181;HANGUL LETTER YESIEUNG;Lo;0;L;<compat> 114C;;;;N;HANGUL LETTER NGIEUNG;;;; +3182;HANGUL LETTER YESIEUNG-SIOS;Lo;0;L;<compat> 11F1;;;;N;HANGUL LETTER NGIEUNG SIOS;;;; +3183;HANGUL LETTER YESIEUNG-PANSIOS;Lo;0;L;<compat> 11F2;;;;N;HANGUL LETTER NGIEUNG BAN CHI EUM;;;; +3184;HANGUL LETTER KAPYEOUNPHIEUPH;Lo;0;L;<compat> 1157;;;;N;HANGUL LETTER PIEUP SUN GYEONG EUM;;;; +3185;HANGUL LETTER SSANGHIEUH;Lo;0;L;<compat> 1158;;;;N;HANGUL LETTER SSANG HIEUH;;;; +3186;HANGUL LETTER YEORINHIEUH;Lo;0;L;<compat> 1159;;;;N;HANGUL LETTER YEOLIN HIEUH;;;; +3187;HANGUL LETTER YO-YA;Lo;0;L;<compat> 1184;;;;N;HANGUL LETTER YOYA;;;; +3188;HANGUL LETTER YO-YAE;Lo;0;L;<compat> 1185;;;;N;HANGUL LETTER YOYAE;;;; +3189;HANGUL LETTER YO-I;Lo;0;L;<compat> 1188;;;;N;HANGUL LETTER YOI;;;; +318A;HANGUL LETTER YU-YEO;Lo;0;L;<compat> 1191;;;;N;HANGUL LETTER YUYEO;;;; +318B;HANGUL LETTER YU-YE;Lo;0;L;<compat> 1192;;;;N;HANGUL LETTER YUYE;;;; +318C;HANGUL LETTER YU-I;Lo;0;L;<compat> 1194;;;;N;HANGUL LETTER YUI;;;; +318D;HANGUL LETTER ARAEA;Lo;0;L;<compat> 119E;;;;N;HANGUL LETTER ALAE A;;;; +318E;HANGUL LETTER ARAEAE;Lo;0;L;<compat> 11A1;;;;N;HANGUL LETTER ALAE AE;;;; +3190;IDEOGRAPHIC ANNOTATION LINKING MARK;So;0;L;;;;;N;KANBUN TATETEN;;;; +3191;IDEOGRAPHIC ANNOTATION REVERSE MARK;So;0;L;;;;;N;KAERITEN RE;;;; +3192;IDEOGRAPHIC ANNOTATION ONE MARK;No;0;L;<super> 4E00;;;1;N;KAERITEN ITI;;;; +3193;IDEOGRAPHIC ANNOTATION TWO MARK;No;0;L;<super> 4E8C;;;2;N;KAERITEN NI;;;; +3194;IDEOGRAPHIC ANNOTATION THREE MARK;No;0;L;<super> 4E09;;;3;N;KAERITEN SAN;;;; +3195;IDEOGRAPHIC ANNOTATION FOUR MARK;No;0;L;<super> 56DB;;;4;N;KAERITEN SI;;;; +3196;IDEOGRAPHIC ANNOTATION TOP MARK;So;0;L;<super> 4E0A;;;;N;KAERITEN ZYOU;;;; +3197;IDEOGRAPHIC ANNOTATION MIDDLE MARK;So;0;L;<super> 4E2D;;;;N;KAERITEN TYUU;;;; +3198;IDEOGRAPHIC ANNOTATION BOTTOM MARK;So;0;L;<super> 4E0B;;;;N;KAERITEN GE;;;; +3199;IDEOGRAPHIC ANNOTATION FIRST MARK;So;0;L;<super> 7532;;;;N;KAERITEN KOU;;;; +319A;IDEOGRAPHIC ANNOTATION SECOND MARK;So;0;L;<super> 4E59;;;;N;KAERITEN OTU;;;; +319B;IDEOGRAPHIC ANNOTATION THIRD MARK;So;0;L;<super> 4E19;;;;N;KAERITEN HEI;;;; +319C;IDEOGRAPHIC ANNOTATION FOURTH MARK;So;0;L;<super> 4E01;;;;N;KAERITEN TEI;;;; +319D;IDEOGRAPHIC ANNOTATION HEAVEN MARK;So;0;L;<super> 5929;;;;N;KAERITEN TEN;;;; +319E;IDEOGRAPHIC ANNOTATION EARTH MARK;So;0;L;<super> 5730;;;;N;KAERITEN TI;;;; +319F;IDEOGRAPHIC ANNOTATION MAN MARK;So;0;L;<super> 4EBA;;;;N;KAERITEN ZIN;;;; +31A0;BOPOMOFO LETTER BU;Lo;0;L;;;;;N;;;;; +31A1;BOPOMOFO LETTER ZI;Lo;0;L;;;;;N;;;;; +31A2;BOPOMOFO LETTER JI;Lo;0;L;;;;;N;;;;; +31A3;BOPOMOFO LETTER GU;Lo;0;L;;;;;N;;;;; +31A4;BOPOMOFO LETTER EE;Lo;0;L;;;;;N;;;;; +31A5;BOPOMOFO LETTER ENN;Lo;0;L;;;;;N;;;;; +31A6;BOPOMOFO LETTER OO;Lo;0;L;;;;;N;;;;; +31A7;BOPOMOFO LETTER ONN;Lo;0;L;;;;;N;;;;; +31A8;BOPOMOFO LETTER IR;Lo;0;L;;;;;N;;;;; +31A9;BOPOMOFO LETTER ANN;Lo;0;L;;;;;N;;;;; +31AA;BOPOMOFO LETTER INN;Lo;0;L;;;;;N;;;;; +31AB;BOPOMOFO LETTER UNN;Lo;0;L;;;;;N;;;;; +31AC;BOPOMOFO LETTER IM;Lo;0;L;;;;;N;;;;; +31AD;BOPOMOFO LETTER NGG;Lo;0;L;;;;;N;;;;; +31AE;BOPOMOFO LETTER AINN;Lo;0;L;;;;;N;;;;; +31AF;BOPOMOFO LETTER AUNN;Lo;0;L;;;;;N;;;;; +31B0;BOPOMOFO LETTER AM;Lo;0;L;;;;;N;;;;; +31B1;BOPOMOFO LETTER OM;Lo;0;L;;;;;N;;;;; +31B2;BOPOMOFO LETTER ONG;Lo;0;L;;;;;N;;;;; +31B3;BOPOMOFO LETTER INNN;Lo;0;L;;;;;N;;;;; +31B4;BOPOMOFO FINAL LETTER P;Lo;0;L;;;;;N;;;;; +31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;; +31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;; +31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;; +31B8;BOPOMOFO LETTER GH;Lo;0;L;;;;;N;;;;; +31B9;BOPOMOFO LETTER LH;Lo;0;L;;;;;N;;;;; +31BA;BOPOMOFO LETTER ZY;Lo;0;L;;;;;N;;;;; +31C0;CJK STROKE T;So;0;ON;;;;;N;;;;; +31C1;CJK STROKE WG;So;0;ON;;;;;N;;;;; +31C2;CJK STROKE XG;So;0;ON;;;;;N;;;;; +31C3;CJK STROKE BXG;So;0;ON;;;;;N;;;;; +31C4;CJK STROKE SW;So;0;ON;;;;;N;;;;; +31C5;CJK STROKE HZZ;So;0;ON;;;;;N;;;;; +31C6;CJK STROKE HZG;So;0;ON;;;;;N;;;;; +31C7;CJK STROKE HP;So;0;ON;;;;;N;;;;; +31C8;CJK STROKE HZWG;So;0;ON;;;;;N;;;;; +31C9;CJK STROKE SZWG;So;0;ON;;;;;N;;;;; +31CA;CJK STROKE HZT;So;0;ON;;;;;N;;;;; +31CB;CJK STROKE HZZP;So;0;ON;;;;;N;;;;; +31CC;CJK STROKE HPWG;So;0;ON;;;;;N;;;;; +31CD;CJK STROKE HZW;So;0;ON;;;;;N;;;;; +31CE;CJK STROKE HZZZ;So;0;ON;;;;;N;;;;; +31CF;CJK STROKE N;So;0;ON;;;;;N;;;;; +31D0;CJK STROKE H;So;0;ON;;;;;N;;;;; +31D1;CJK STROKE S;So;0;ON;;;;;N;;;;; +31D2;CJK STROKE P;So;0;ON;;;;;N;;;;; +31D3;CJK STROKE SP;So;0;ON;;;;;N;;;;; +31D4;CJK STROKE D;So;0;ON;;;;;N;;;;; +31D5;CJK STROKE HZ;So;0;ON;;;;;N;;;;; +31D6;CJK STROKE HG;So;0;ON;;;;;N;;;;; +31D7;CJK STROKE SZ;So;0;ON;;;;;N;;;;; +31D8;CJK STROKE SWZ;So;0;ON;;;;;N;;;;; +31D9;CJK STROKE ST;So;0;ON;;;;;N;;;;; +31DA;CJK STROKE SG;So;0;ON;;;;;N;;;;; +31DB;CJK STROKE PD;So;0;ON;;;;;N;;;;; +31DC;CJK STROKE PZ;So;0;ON;;;;;N;;;;; +31DD;CJK STROKE TN;So;0;ON;;;;;N;;;;; +31DE;CJK STROKE SZZ;So;0;ON;;;;;N;;;;; +31DF;CJK STROKE SWG;So;0;ON;;;;;N;;;;; +31E0;CJK STROKE HXWG;So;0;ON;;;;;N;;;;; +31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;; +31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;; +31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;; +31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;; +31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;; +31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;; +31F3;KATAKANA LETTER SMALL TO;Lo;0;L;;;;;N;;;;; +31F4;KATAKANA LETTER SMALL NU;Lo;0;L;;;;;N;;;;; +31F5;KATAKANA LETTER SMALL HA;Lo;0;L;;;;;N;;;;; +31F6;KATAKANA LETTER SMALL HI;Lo;0;L;;;;;N;;;;; +31F7;KATAKANA LETTER SMALL HU;Lo;0;L;;;;;N;;;;; +31F8;KATAKANA LETTER SMALL HE;Lo;0;L;;;;;N;;;;; +31F9;KATAKANA LETTER SMALL HO;Lo;0;L;;;;;N;;;;; +31FA;KATAKANA LETTER SMALL MU;Lo;0;L;;;;;N;;;;; +31FB;KATAKANA LETTER SMALL RA;Lo;0;L;;;;;N;;;;; +31FC;KATAKANA LETTER SMALL RI;Lo;0;L;;;;;N;;;;; +31FD;KATAKANA LETTER SMALL RU;Lo;0;L;;;;;N;;;;; +31FE;KATAKANA LETTER SMALL RE;Lo;0;L;;;;;N;;;;; +31FF;KATAKANA LETTER SMALL RO;Lo;0;L;;;;;N;;;;; +3200;PARENTHESIZED HANGUL KIYEOK;So;0;L;<compat> 0028 1100 0029;;;;N;PARENTHESIZED HANGUL GIYEOG;;;; +3201;PARENTHESIZED HANGUL NIEUN;So;0;L;<compat> 0028 1102 0029;;;;N;;;;; +3202;PARENTHESIZED HANGUL TIKEUT;So;0;L;<compat> 0028 1103 0029;;;;N;PARENTHESIZED HANGUL DIGEUD;;;; +3203;PARENTHESIZED HANGUL RIEUL;So;0;L;<compat> 0028 1105 0029;;;;N;PARENTHESIZED HANGUL LIEUL;;;; +3204;PARENTHESIZED HANGUL MIEUM;So;0;L;<compat> 0028 1106 0029;;;;N;;;;; +3205;PARENTHESIZED HANGUL PIEUP;So;0;L;<compat> 0028 1107 0029;;;;N;PARENTHESIZED HANGUL BIEUB;;;; +3206;PARENTHESIZED HANGUL SIOS;So;0;L;<compat> 0028 1109 0029;;;;N;;;;; +3207;PARENTHESIZED HANGUL IEUNG;So;0;L;<compat> 0028 110B 0029;;;;N;;;;; +3208;PARENTHESIZED HANGUL CIEUC;So;0;L;<compat> 0028 110C 0029;;;;N;PARENTHESIZED HANGUL JIEUJ;;;; +3209;PARENTHESIZED HANGUL CHIEUCH;So;0;L;<compat> 0028 110E 0029;;;;N;PARENTHESIZED HANGUL CIEUC;;;; +320A;PARENTHESIZED HANGUL KHIEUKH;So;0;L;<compat> 0028 110F 0029;;;;N;PARENTHESIZED HANGUL KIYEOK;;;; +320B;PARENTHESIZED HANGUL THIEUTH;So;0;L;<compat> 0028 1110 0029;;;;N;PARENTHESIZED HANGUL TIEUT;;;; +320C;PARENTHESIZED HANGUL PHIEUPH;So;0;L;<compat> 0028 1111 0029;;;;N;PARENTHESIZED HANGUL PIEUP;;;; +320D;PARENTHESIZED HANGUL HIEUH;So;0;L;<compat> 0028 1112 0029;;;;N;;;;; +320E;PARENTHESIZED HANGUL KIYEOK A;So;0;L;<compat> 0028 1100 1161 0029;;;;N;PARENTHESIZED HANGUL GA;;;; +320F;PARENTHESIZED HANGUL NIEUN A;So;0;L;<compat> 0028 1102 1161 0029;;;;N;PARENTHESIZED HANGUL NA;;;; +3210;PARENTHESIZED HANGUL TIKEUT A;So;0;L;<compat> 0028 1103 1161 0029;;;;N;PARENTHESIZED HANGUL DA;;;; +3211;PARENTHESIZED HANGUL RIEUL A;So;0;L;<compat> 0028 1105 1161 0029;;;;N;PARENTHESIZED HANGUL LA;;;; +3212;PARENTHESIZED HANGUL MIEUM A;So;0;L;<compat> 0028 1106 1161 0029;;;;N;PARENTHESIZED HANGUL MA;;;; +3213;PARENTHESIZED HANGUL PIEUP A;So;0;L;<compat> 0028 1107 1161 0029;;;;N;PARENTHESIZED HANGUL BA;;;; +3214;PARENTHESIZED HANGUL SIOS A;So;0;L;<compat> 0028 1109 1161 0029;;;;N;PARENTHESIZED HANGUL SA;;;; +3215;PARENTHESIZED HANGUL IEUNG A;So;0;L;<compat> 0028 110B 1161 0029;;;;N;PARENTHESIZED HANGUL A;;;; +3216;PARENTHESIZED HANGUL CIEUC A;So;0;L;<compat> 0028 110C 1161 0029;;;;N;PARENTHESIZED HANGUL JA;;;; +3217;PARENTHESIZED HANGUL CHIEUCH A;So;0;L;<compat> 0028 110E 1161 0029;;;;N;PARENTHESIZED HANGUL CA;;;; +3218;PARENTHESIZED HANGUL KHIEUKH A;So;0;L;<compat> 0028 110F 1161 0029;;;;N;PARENTHESIZED HANGUL KA;;;; +3219;PARENTHESIZED HANGUL THIEUTH A;So;0;L;<compat> 0028 1110 1161 0029;;;;N;PARENTHESIZED HANGUL TA;;;; +321A;PARENTHESIZED HANGUL PHIEUPH A;So;0;L;<compat> 0028 1111 1161 0029;;;;N;PARENTHESIZED HANGUL PA;;;; +321B;PARENTHESIZED HANGUL HIEUH A;So;0;L;<compat> 0028 1112 1161 0029;;;;N;PARENTHESIZED HANGUL HA;;;; +321C;PARENTHESIZED HANGUL CIEUC U;So;0;L;<compat> 0028 110C 116E 0029;;;;N;PARENTHESIZED HANGUL JU;;;; +321D;PARENTHESIZED KOREAN CHARACTER OJEON;So;0;ON;<compat> 0028 110B 1169 110C 1165 11AB 0029;;;;N;;;;; +321E;PARENTHESIZED KOREAN CHARACTER O HU;So;0;ON;<compat> 0028 110B 1169 1112 116E 0029;;;;N;;;;; +3220;PARENTHESIZED IDEOGRAPH ONE;No;0;L;<compat> 0028 4E00 0029;;;1;N;;;;; +3221;PARENTHESIZED IDEOGRAPH TWO;No;0;L;<compat> 0028 4E8C 0029;;;2;N;;;;; +3222;PARENTHESIZED IDEOGRAPH THREE;No;0;L;<compat> 0028 4E09 0029;;;3;N;;;;; +3223;PARENTHESIZED IDEOGRAPH FOUR;No;0;L;<compat> 0028 56DB 0029;;;4;N;;;;; +3224;PARENTHESIZED IDEOGRAPH FIVE;No;0;L;<compat> 0028 4E94 0029;;;5;N;;;;; +3225;PARENTHESIZED IDEOGRAPH SIX;No;0;L;<compat> 0028 516D 0029;;;6;N;;;;; +3226;PARENTHESIZED IDEOGRAPH SEVEN;No;0;L;<compat> 0028 4E03 0029;;;7;N;;;;; +3227;PARENTHESIZED IDEOGRAPH EIGHT;No;0;L;<compat> 0028 516B 0029;;;8;N;;;;; +3228;PARENTHESIZED IDEOGRAPH NINE;No;0;L;<compat> 0028 4E5D 0029;;;9;N;;;;; +3229;PARENTHESIZED IDEOGRAPH TEN;No;0;L;<compat> 0028 5341 0029;;;10;N;;;;; +322A;PARENTHESIZED IDEOGRAPH MOON;So;0;L;<compat> 0028 6708 0029;;;;N;;;;; +322B;PARENTHESIZED IDEOGRAPH FIRE;So;0;L;<compat> 0028 706B 0029;;;;N;;;;; +322C;PARENTHESIZED IDEOGRAPH WATER;So;0;L;<compat> 0028 6C34 0029;;;;N;;;;; +322D;PARENTHESIZED IDEOGRAPH WOOD;So;0;L;<compat> 0028 6728 0029;;;;N;;;;; +322E;PARENTHESIZED IDEOGRAPH METAL;So;0;L;<compat> 0028 91D1 0029;;;;N;;;;; +322F;PARENTHESIZED IDEOGRAPH EARTH;So;0;L;<compat> 0028 571F 0029;;;;N;;;;; +3230;PARENTHESIZED IDEOGRAPH SUN;So;0;L;<compat> 0028 65E5 0029;;;;N;;;;; +3231;PARENTHESIZED IDEOGRAPH STOCK;So;0;L;<compat> 0028 682A 0029;;;;N;;;;; +3232;PARENTHESIZED IDEOGRAPH HAVE;So;0;L;<compat> 0028 6709 0029;;;;N;;;;; +3233;PARENTHESIZED IDEOGRAPH SOCIETY;So;0;L;<compat> 0028 793E 0029;;;;N;;;;; +3234;PARENTHESIZED IDEOGRAPH NAME;So;0;L;<compat> 0028 540D 0029;;;;N;;;;; +3235;PARENTHESIZED IDEOGRAPH SPECIAL;So;0;L;<compat> 0028 7279 0029;;;;N;;;;; +3236;PARENTHESIZED IDEOGRAPH FINANCIAL;So;0;L;<compat> 0028 8CA1 0029;;;;N;;;;; +3237;PARENTHESIZED IDEOGRAPH CONGRATULATION;So;0;L;<compat> 0028 795D 0029;;;;N;;;;; +3238;PARENTHESIZED IDEOGRAPH LABOR;So;0;L;<compat> 0028 52B4 0029;;;;N;;;;; +3239;PARENTHESIZED IDEOGRAPH REPRESENT;So;0;L;<compat> 0028 4EE3 0029;;;;N;;;;; +323A;PARENTHESIZED IDEOGRAPH CALL;So;0;L;<compat> 0028 547C 0029;;;;N;;;;; +323B;PARENTHESIZED IDEOGRAPH STUDY;So;0;L;<compat> 0028 5B66 0029;;;;N;;;;; +323C;PARENTHESIZED IDEOGRAPH SUPERVISE;So;0;L;<compat> 0028 76E3 0029;;;;N;;;;; +323D;PARENTHESIZED IDEOGRAPH ENTERPRISE;So;0;L;<compat> 0028 4F01 0029;;;;N;;;;; +323E;PARENTHESIZED IDEOGRAPH RESOURCE;So;0;L;<compat> 0028 8CC7 0029;;;;N;;;;; +323F;PARENTHESIZED IDEOGRAPH ALLIANCE;So;0;L;<compat> 0028 5354 0029;;;;N;;;;; +3240;PARENTHESIZED IDEOGRAPH FESTIVAL;So;0;L;<compat> 0028 796D 0029;;;;N;;;;; +3241;PARENTHESIZED IDEOGRAPH REST;So;0;L;<compat> 0028 4F11 0029;;;;N;;;;; +3242;PARENTHESIZED IDEOGRAPH SELF;So;0;L;<compat> 0028 81EA 0029;;;;N;;;;; +3243;PARENTHESIZED IDEOGRAPH REACH;So;0;L;<compat> 0028 81F3 0029;;;;N;;;;; +3244;CIRCLED IDEOGRAPH QUESTION;So;0;L;<circle> 554F;;;;N;;;;; +3245;CIRCLED IDEOGRAPH KINDERGARTEN;So;0;L;<circle> 5E7C;;;;N;;;;; +3246;CIRCLED IDEOGRAPH SCHOOL;So;0;L;<circle> 6587;;;;N;;;;; +3247;CIRCLED IDEOGRAPH KOTO;So;0;L;<circle> 7B8F;;;;N;;;;; +3248;CIRCLED NUMBER TEN ON BLACK SQUARE;No;0;L;;;;10;N;;;;; +3249;CIRCLED NUMBER TWENTY ON BLACK SQUARE;No;0;L;;;;20;N;;;;; +324A;CIRCLED NUMBER THIRTY ON BLACK SQUARE;No;0;L;;;;30;N;;;;; +324B;CIRCLED NUMBER FORTY ON BLACK SQUARE;No;0;L;;;;40;N;;;;; +324C;CIRCLED NUMBER FIFTY ON BLACK SQUARE;No;0;L;;;;50;N;;;;; +324D;CIRCLED NUMBER SIXTY ON BLACK SQUARE;No;0;L;;;;60;N;;;;; +324E;CIRCLED NUMBER SEVENTY ON BLACK SQUARE;No;0;L;;;;70;N;;;;; +324F;CIRCLED NUMBER EIGHTY ON BLACK SQUARE;No;0;L;;;;80;N;;;;; +3250;PARTNERSHIP SIGN;So;0;ON;<square> 0050 0054 0045;;;;N;;;;; +3251;CIRCLED NUMBER TWENTY ONE;No;0;ON;<circle> 0032 0031;;;21;N;;;;; +3252;CIRCLED NUMBER TWENTY TWO;No;0;ON;<circle> 0032 0032;;;22;N;;;;; +3253;CIRCLED NUMBER TWENTY THREE;No;0;ON;<circle> 0032 0033;;;23;N;;;;; +3254;CIRCLED NUMBER TWENTY FOUR;No;0;ON;<circle> 0032 0034;;;24;N;;;;; +3255;CIRCLED NUMBER TWENTY FIVE;No;0;ON;<circle> 0032 0035;;;25;N;;;;; +3256;CIRCLED NUMBER TWENTY SIX;No;0;ON;<circle> 0032 0036;;;26;N;;;;; +3257;CIRCLED NUMBER TWENTY SEVEN;No;0;ON;<circle> 0032 0037;;;27;N;;;;; +3258;CIRCLED NUMBER TWENTY EIGHT;No;0;ON;<circle> 0032 0038;;;28;N;;;;; +3259;CIRCLED NUMBER TWENTY NINE;No;0;ON;<circle> 0032 0039;;;29;N;;;;; +325A;CIRCLED NUMBER THIRTY;No;0;ON;<circle> 0033 0030;;;30;N;;;;; +325B;CIRCLED NUMBER THIRTY ONE;No;0;ON;<circle> 0033 0031;;;31;N;;;;; +325C;CIRCLED NUMBER THIRTY TWO;No;0;ON;<circle> 0033 0032;;;32;N;;;;; +325D;CIRCLED NUMBER THIRTY THREE;No;0;ON;<circle> 0033 0033;;;33;N;;;;; +325E;CIRCLED NUMBER THIRTY FOUR;No;0;ON;<circle> 0033 0034;;;34;N;;;;; +325F;CIRCLED NUMBER THIRTY FIVE;No;0;ON;<circle> 0033 0035;;;35;N;;;;; +3260;CIRCLED HANGUL KIYEOK;So;0;L;<circle> 1100;;;;N;CIRCLED HANGUL GIYEOG;;;; +3261;CIRCLED HANGUL NIEUN;So;0;L;<circle> 1102;;;;N;;;;; +3262;CIRCLED HANGUL TIKEUT;So;0;L;<circle> 1103;;;;N;CIRCLED HANGUL DIGEUD;;;; +3263;CIRCLED HANGUL RIEUL;So;0;L;<circle> 1105;;;;N;CIRCLED HANGUL LIEUL;;;; +3264;CIRCLED HANGUL MIEUM;So;0;L;<circle> 1106;;;;N;;;;; +3265;CIRCLED HANGUL PIEUP;So;0;L;<circle> 1107;;;;N;CIRCLED HANGUL BIEUB;;;; +3266;CIRCLED HANGUL SIOS;So;0;L;<circle> 1109;;;;N;;;;; +3267;CIRCLED HANGUL IEUNG;So;0;L;<circle> 110B;;;;N;;;;; +3268;CIRCLED HANGUL CIEUC;So;0;L;<circle> 110C;;;;N;CIRCLED HANGUL JIEUJ;;;; +3269;CIRCLED HANGUL CHIEUCH;So;0;L;<circle> 110E;;;;N;CIRCLED HANGUL CIEUC;;;; +326A;CIRCLED HANGUL KHIEUKH;So;0;L;<circle> 110F;;;;N;CIRCLED HANGUL KIYEOK;;;; +326B;CIRCLED HANGUL THIEUTH;So;0;L;<circle> 1110;;;;N;CIRCLED HANGUL TIEUT;;;; +326C;CIRCLED HANGUL PHIEUPH;So;0;L;<circle> 1111;;;;N;CIRCLED HANGUL PIEUP;;;; +326D;CIRCLED HANGUL HIEUH;So;0;L;<circle> 1112;;;;N;;;;; +326E;CIRCLED HANGUL KIYEOK A;So;0;L;<circle> 1100 1161;;;;N;CIRCLED HANGUL GA;;;; +326F;CIRCLED HANGUL NIEUN A;So;0;L;<circle> 1102 1161;;;;N;CIRCLED HANGUL NA;;;; +3270;CIRCLED HANGUL TIKEUT A;So;0;L;<circle> 1103 1161;;;;N;CIRCLED HANGUL DA;;;; +3271;CIRCLED HANGUL RIEUL A;So;0;L;<circle> 1105 1161;;;;N;CIRCLED HANGUL LA;;;; +3272;CIRCLED HANGUL MIEUM A;So;0;L;<circle> 1106 1161;;;;N;CIRCLED HANGUL MA;;;; +3273;CIRCLED HANGUL PIEUP A;So;0;L;<circle> 1107 1161;;;;N;CIRCLED HANGUL BA;;;; +3274;CIRCLED HANGUL SIOS A;So;0;L;<circle> 1109 1161;;;;N;CIRCLED HANGUL SA;;;; +3275;CIRCLED HANGUL IEUNG A;So;0;L;<circle> 110B 1161;;;;N;CIRCLED HANGUL A;;;; +3276;CIRCLED HANGUL CIEUC A;So;0;L;<circle> 110C 1161;;;;N;CIRCLED HANGUL JA;;;; +3277;CIRCLED HANGUL CHIEUCH A;So;0;L;<circle> 110E 1161;;;;N;CIRCLED HANGUL CA;;;; +3278;CIRCLED HANGUL KHIEUKH A;So;0;L;<circle> 110F 1161;;;;N;CIRCLED HANGUL KA;;;; +3279;CIRCLED HANGUL THIEUTH A;So;0;L;<circle> 1110 1161;;;;N;CIRCLED HANGUL TA;;;; +327A;CIRCLED HANGUL PHIEUPH A;So;0;L;<circle> 1111 1161;;;;N;CIRCLED HANGUL PA;;;; +327B;CIRCLED HANGUL HIEUH A;So;0;L;<circle> 1112 1161;;;;N;CIRCLED HANGUL HA;;;; +327C;CIRCLED KOREAN CHARACTER CHAMKO;So;0;ON;<circle> 110E 1161 11B7 1100 1169;;;;N;;;;; +327D;CIRCLED KOREAN CHARACTER JUEUI;So;0;ON;<circle> 110C 116E 110B 1174;;;;N;;;;; +327E;CIRCLED HANGUL IEUNG U;So;0;ON;<circle> 110B 116E;;;;N;;;;; +327F;KOREAN STANDARD SYMBOL;So;0;L;;;;;N;;;;; +3280;CIRCLED IDEOGRAPH ONE;No;0;L;<circle> 4E00;;;1;N;;;;; +3281;CIRCLED IDEOGRAPH TWO;No;0;L;<circle> 4E8C;;;2;N;;;;; +3282;CIRCLED IDEOGRAPH THREE;No;0;L;<circle> 4E09;;;3;N;;;;; +3283;CIRCLED IDEOGRAPH FOUR;No;0;L;<circle> 56DB;;;4;N;;;;; +3284;CIRCLED IDEOGRAPH FIVE;No;0;L;<circle> 4E94;;;5;N;;;;; +3285;CIRCLED IDEOGRAPH SIX;No;0;L;<circle> 516D;;;6;N;;;;; +3286;CIRCLED IDEOGRAPH SEVEN;No;0;L;<circle> 4E03;;;7;N;;;;; +3287;CIRCLED IDEOGRAPH EIGHT;No;0;L;<circle> 516B;;;8;N;;;;; +3288;CIRCLED IDEOGRAPH NINE;No;0;L;<circle> 4E5D;;;9;N;;;;; +3289;CIRCLED IDEOGRAPH TEN;No;0;L;<circle> 5341;;;10;N;;;;; +328A;CIRCLED IDEOGRAPH MOON;So;0;L;<circle> 6708;;;;N;;;;; +328B;CIRCLED IDEOGRAPH FIRE;So;0;L;<circle> 706B;;;;N;;;;; +328C;CIRCLED IDEOGRAPH WATER;So;0;L;<circle> 6C34;;;;N;;;;; +328D;CIRCLED IDEOGRAPH WOOD;So;0;L;<circle> 6728;;;;N;;;;; +328E;CIRCLED IDEOGRAPH METAL;So;0;L;<circle> 91D1;;;;N;;;;; +328F;CIRCLED IDEOGRAPH EARTH;So;0;L;<circle> 571F;;;;N;;;;; +3290;CIRCLED IDEOGRAPH SUN;So;0;L;<circle> 65E5;;;;N;;;;; +3291;CIRCLED IDEOGRAPH STOCK;So;0;L;<circle> 682A;;;;N;;;;; +3292;CIRCLED IDEOGRAPH HAVE;So;0;L;<circle> 6709;;;;N;;;;; +3293;CIRCLED IDEOGRAPH SOCIETY;So;0;L;<circle> 793E;;;;N;;;;; +3294;CIRCLED IDEOGRAPH NAME;So;0;L;<circle> 540D;;;;N;;;;; +3295;CIRCLED IDEOGRAPH SPECIAL;So;0;L;<circle> 7279;;;;N;;;;; +3296;CIRCLED IDEOGRAPH FINANCIAL;So;0;L;<circle> 8CA1;;;;N;;;;; +3297;CIRCLED IDEOGRAPH CONGRATULATION;So;0;L;<circle> 795D;;;;N;;;;; +3298;CIRCLED IDEOGRAPH LABOR;So;0;L;<circle> 52B4;;;;N;;;;; +3299;CIRCLED IDEOGRAPH SECRET;So;0;L;<circle> 79D8;;;;N;;;;; +329A;CIRCLED IDEOGRAPH MALE;So;0;L;<circle> 7537;;;;N;;;;; +329B;CIRCLED IDEOGRAPH FEMALE;So;0;L;<circle> 5973;;;;N;;;;; +329C;CIRCLED IDEOGRAPH SUITABLE;So;0;L;<circle> 9069;;;;N;;;;; +329D;CIRCLED IDEOGRAPH EXCELLENT;So;0;L;<circle> 512A;;;;N;;;;; +329E;CIRCLED IDEOGRAPH PRINT;So;0;L;<circle> 5370;;;;N;;;;; +329F;CIRCLED IDEOGRAPH ATTENTION;So;0;L;<circle> 6CE8;;;;N;;;;; +32A0;CIRCLED IDEOGRAPH ITEM;So;0;L;<circle> 9805;;;;N;;;;; +32A1;CIRCLED IDEOGRAPH REST;So;0;L;<circle> 4F11;;;;N;;;;; +32A2;CIRCLED IDEOGRAPH COPY;So;0;L;<circle> 5199;;;;N;;;;; +32A3;CIRCLED IDEOGRAPH CORRECT;So;0;L;<circle> 6B63;;;;N;;;;; +32A4;CIRCLED IDEOGRAPH HIGH;So;0;L;<circle> 4E0A;;;;N;;;;; +32A5;CIRCLED IDEOGRAPH CENTRE;So;0;L;<circle> 4E2D;;;;N;CIRCLED IDEOGRAPH CENTER;;;; +32A6;CIRCLED IDEOGRAPH LOW;So;0;L;<circle> 4E0B;;;;N;;;;; +32A7;CIRCLED IDEOGRAPH LEFT;So;0;L;<circle> 5DE6;;;;N;;;;; +32A8;CIRCLED IDEOGRAPH RIGHT;So;0;L;<circle> 53F3;;;;N;;;;; +32A9;CIRCLED IDEOGRAPH MEDICINE;So;0;L;<circle> 533B;;;;N;;;;; +32AA;CIRCLED IDEOGRAPH RELIGION;So;0;L;<circle> 5B97;;;;N;;;;; +32AB;CIRCLED IDEOGRAPH STUDY;So;0;L;<circle> 5B66;;;;N;;;;; +32AC;CIRCLED IDEOGRAPH SUPERVISE;So;0;L;<circle> 76E3;;;;N;;;;; +32AD;CIRCLED IDEOGRAPH ENTERPRISE;So;0;L;<circle> 4F01;;;;N;;;;; +32AE;CIRCLED IDEOGRAPH RESOURCE;So;0;L;<circle> 8CC7;;;;N;;;;; +32AF;CIRCLED IDEOGRAPH ALLIANCE;So;0;L;<circle> 5354;;;;N;;;;; +32B0;CIRCLED IDEOGRAPH NIGHT;So;0;L;<circle> 591C;;;;N;;;;; +32B1;CIRCLED NUMBER THIRTY SIX;No;0;ON;<circle> 0033 0036;;;36;N;;;;; +32B2;CIRCLED NUMBER THIRTY SEVEN;No;0;ON;<circle> 0033 0037;;;37;N;;;;; +32B3;CIRCLED NUMBER THIRTY EIGHT;No;0;ON;<circle> 0033 0038;;;38;N;;;;; +32B4;CIRCLED NUMBER THIRTY NINE;No;0;ON;<circle> 0033 0039;;;39;N;;;;; +32B5;CIRCLED NUMBER FORTY;No;0;ON;<circle> 0034 0030;;;40;N;;;;; +32B6;CIRCLED NUMBER FORTY ONE;No;0;ON;<circle> 0034 0031;;;41;N;;;;; +32B7;CIRCLED NUMBER FORTY TWO;No;0;ON;<circle> 0034 0032;;;42;N;;;;; +32B8;CIRCLED NUMBER FORTY THREE;No;0;ON;<circle> 0034 0033;;;43;N;;;;; +32B9;CIRCLED NUMBER FORTY FOUR;No;0;ON;<circle> 0034 0034;;;44;N;;;;; +32BA;CIRCLED NUMBER FORTY FIVE;No;0;ON;<circle> 0034 0035;;;45;N;;;;; +32BB;CIRCLED NUMBER FORTY SIX;No;0;ON;<circle> 0034 0036;;;46;N;;;;; +32BC;CIRCLED NUMBER FORTY SEVEN;No;0;ON;<circle> 0034 0037;;;47;N;;;;; +32BD;CIRCLED NUMBER FORTY EIGHT;No;0;ON;<circle> 0034 0038;;;48;N;;;;; +32BE;CIRCLED NUMBER FORTY NINE;No;0;ON;<circle> 0034 0039;;;49;N;;;;; +32BF;CIRCLED NUMBER FIFTY;No;0;ON;<circle> 0035 0030;;;50;N;;;;; +32C0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY;So;0;L;<compat> 0031 6708;;;;N;;;;; +32C1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY;So;0;L;<compat> 0032 6708;;;;N;;;;; +32C2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH;So;0;L;<compat> 0033 6708;;;;N;;;;; +32C3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL;So;0;L;<compat> 0034 6708;;;;N;;;;; +32C4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY;So;0;L;<compat> 0035 6708;;;;N;;;;; +32C5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE;So;0;L;<compat> 0036 6708;;;;N;;;;; +32C6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY;So;0;L;<compat> 0037 6708;;;;N;;;;; +32C7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST;So;0;L;<compat> 0038 6708;;;;N;;;;; +32C8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER;So;0;L;<compat> 0039 6708;;;;N;;;;; +32C9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER;So;0;L;<compat> 0031 0030 6708;;;;N;;;;; +32CA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER;So;0;L;<compat> 0031 0031 6708;;;;N;;;;; +32CB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER;So;0;L;<compat> 0031 0032 6708;;;;N;;;;; +32CC;SQUARE HG;So;0;ON;<square> 0048 0067;;;;N;;;;; +32CD;SQUARE ERG;So;0;ON;<square> 0065 0072 0067;;;;N;;;;; +32CE;SQUARE EV;So;0;ON;<square> 0065 0056;;;;N;;;;; +32CF;LIMITED LIABILITY SIGN;So;0;ON;<square> 004C 0054 0044;;;;N;;;;; +32D0;CIRCLED KATAKANA A;So;0;L;<circle> 30A2;;;;N;;;;; +32D1;CIRCLED KATAKANA I;So;0;L;<circle> 30A4;;;;N;;;;; +32D2;CIRCLED KATAKANA U;So;0;L;<circle> 30A6;;;;N;;;;; +32D3;CIRCLED KATAKANA E;So;0;L;<circle> 30A8;;;;N;;;;; +32D4;CIRCLED KATAKANA O;So;0;L;<circle> 30AA;;;;N;;;;; +32D5;CIRCLED KATAKANA KA;So;0;L;<circle> 30AB;;;;N;;;;; +32D6;CIRCLED KATAKANA KI;So;0;L;<circle> 30AD;;;;N;;;;; +32D7;CIRCLED KATAKANA KU;So;0;L;<circle> 30AF;;;;N;;;;; +32D8;CIRCLED KATAKANA KE;So;0;L;<circle> 30B1;;;;N;;;;; +32D9;CIRCLED KATAKANA KO;So;0;L;<circle> 30B3;;;;N;;;;; +32DA;CIRCLED KATAKANA SA;So;0;L;<circle> 30B5;;;;N;;;;; +32DB;CIRCLED KATAKANA SI;So;0;L;<circle> 30B7;;;;N;;;;; +32DC;CIRCLED KATAKANA SU;So;0;L;<circle> 30B9;;;;N;;;;; +32DD;CIRCLED KATAKANA SE;So;0;L;<circle> 30BB;;;;N;;;;; +32DE;CIRCLED KATAKANA SO;So;0;L;<circle> 30BD;;;;N;;;;; +32DF;CIRCLED KATAKANA TA;So;0;L;<circle> 30BF;;;;N;;;;; +32E0;CIRCLED KATAKANA TI;So;0;L;<circle> 30C1;;;;N;;;;; +32E1;CIRCLED KATAKANA TU;So;0;L;<circle> 30C4;;;;N;;;;; +32E2;CIRCLED KATAKANA TE;So;0;L;<circle> 30C6;;;;N;;;;; +32E3;CIRCLED KATAKANA TO;So;0;L;<circle> 30C8;;;;N;;;;; +32E4;CIRCLED KATAKANA NA;So;0;L;<circle> 30CA;;;;N;;;;; +32E5;CIRCLED KATAKANA NI;So;0;L;<circle> 30CB;;;;N;;;;; +32E6;CIRCLED KATAKANA NU;So;0;L;<circle> 30CC;;;;N;;;;; +32E7;CIRCLED KATAKANA NE;So;0;L;<circle> 30CD;;;;N;;;;; +32E8;CIRCLED KATAKANA NO;So;0;L;<circle> 30CE;;;;N;;;;; +32E9;CIRCLED KATAKANA HA;So;0;L;<circle> 30CF;;;;N;;;;; +32EA;CIRCLED KATAKANA HI;So;0;L;<circle> 30D2;;;;N;;;;; +32EB;CIRCLED KATAKANA HU;So;0;L;<circle> 30D5;;;;N;;;;; +32EC;CIRCLED KATAKANA HE;So;0;L;<circle> 30D8;;;;N;;;;; +32ED;CIRCLED KATAKANA HO;So;0;L;<circle> 30DB;;;;N;;;;; +32EE;CIRCLED KATAKANA MA;So;0;L;<circle> 30DE;;;;N;;;;; +32EF;CIRCLED KATAKANA MI;So;0;L;<circle> 30DF;;;;N;;;;; +32F0;CIRCLED KATAKANA MU;So;0;L;<circle> 30E0;;;;N;;;;; +32F1;CIRCLED KATAKANA ME;So;0;L;<circle> 30E1;;;;N;;;;; +32F2;CIRCLED KATAKANA MO;So;0;L;<circle> 30E2;;;;N;;;;; +32F3;CIRCLED KATAKANA YA;So;0;L;<circle> 30E4;;;;N;;;;; +32F4;CIRCLED KATAKANA YU;So;0;L;<circle> 30E6;;;;N;;;;; +32F5;CIRCLED KATAKANA YO;So;0;L;<circle> 30E8;;;;N;;;;; +32F6;CIRCLED KATAKANA RA;So;0;L;<circle> 30E9;;;;N;;;;; +32F7;CIRCLED KATAKANA RI;So;0;L;<circle> 30EA;;;;N;;;;; +32F8;CIRCLED KATAKANA RU;So;0;L;<circle> 30EB;;;;N;;;;; +32F9;CIRCLED KATAKANA RE;So;0;L;<circle> 30EC;;;;N;;;;; +32FA;CIRCLED KATAKANA RO;So;0;L;<circle> 30ED;;;;N;;;;; +32FB;CIRCLED KATAKANA WA;So;0;L;<circle> 30EF;;;;N;;;;; +32FC;CIRCLED KATAKANA WI;So;0;L;<circle> 30F0;;;;N;;;;; +32FD;CIRCLED KATAKANA WE;So;0;L;<circle> 30F1;;;;N;;;;; +32FE;CIRCLED KATAKANA WO;So;0;L;<circle> 30F2;;;;N;;;;; +3300;SQUARE APAATO;So;0;L;<square> 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;; +3301;SQUARE ARUHUA;So;0;L;<square> 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;; +3302;SQUARE ANPEA;So;0;L;<square> 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;; +3303;SQUARE AARU;So;0;L;<square> 30A2 30FC 30EB;;;;N;SQUARED AARU;;;; +3304;SQUARE ININGU;So;0;L;<square> 30A4 30CB 30F3 30B0;;;;N;SQUARED ININGU;;;; +3305;SQUARE INTI;So;0;L;<square> 30A4 30F3 30C1;;;;N;SQUARED INTI;;;; +3306;SQUARE UON;So;0;L;<square> 30A6 30A9 30F3;;;;N;SQUARED UON;;;; +3307;SQUARE ESUKUUDO;So;0;L;<square> 30A8 30B9 30AF 30FC 30C9;;;;N;SQUARED ESUKUUDO;;;; +3308;SQUARE EEKAA;So;0;L;<square> 30A8 30FC 30AB 30FC;;;;N;SQUARED EEKAA;;;; +3309;SQUARE ONSU;So;0;L;<square> 30AA 30F3 30B9;;;;N;SQUARED ONSU;;;; +330A;SQUARE OOMU;So;0;L;<square> 30AA 30FC 30E0;;;;N;SQUARED OOMU;;;; +330B;SQUARE KAIRI;So;0;L;<square> 30AB 30A4 30EA;;;;N;SQUARED KAIRI;;;; +330C;SQUARE KARATTO;So;0;L;<square> 30AB 30E9 30C3 30C8;;;;N;SQUARED KARATTO;;;; +330D;SQUARE KARORII;So;0;L;<square> 30AB 30ED 30EA 30FC;;;;N;SQUARED KARORII;;;; +330E;SQUARE GARON;So;0;L;<square> 30AC 30ED 30F3;;;;N;SQUARED GARON;;;; +330F;SQUARE GANMA;So;0;L;<square> 30AC 30F3 30DE;;;;N;SQUARED GANMA;;;; +3310;SQUARE GIGA;So;0;L;<square> 30AE 30AC;;;;N;SQUARED GIGA;;;; +3311;SQUARE GINII;So;0;L;<square> 30AE 30CB 30FC;;;;N;SQUARED GINII;;;; +3312;SQUARE KYURII;So;0;L;<square> 30AD 30E5 30EA 30FC;;;;N;SQUARED KYURII;;;; +3313;SQUARE GIRUDAA;So;0;L;<square> 30AE 30EB 30C0 30FC;;;;N;SQUARED GIRUDAA;;;; +3314;SQUARE KIRO;So;0;L;<square> 30AD 30ED;;;;N;SQUARED KIRO;;;; +3315;SQUARE KIROGURAMU;So;0;L;<square> 30AD 30ED 30B0 30E9 30E0;;;;N;SQUARED KIROGURAMU;;;; +3316;SQUARE KIROMEETORU;So;0;L;<square> 30AD 30ED 30E1 30FC 30C8 30EB;;;;N;SQUARED KIROMEETORU;;;; +3317;SQUARE KIROWATTO;So;0;L;<square> 30AD 30ED 30EF 30C3 30C8;;;;N;SQUARED KIROWATTO;;;; +3318;SQUARE GURAMU;So;0;L;<square> 30B0 30E9 30E0;;;;N;SQUARED GURAMU;;;; +3319;SQUARE GURAMUTON;So;0;L;<square> 30B0 30E9 30E0 30C8 30F3;;;;N;SQUARED GURAMUTON;;;; +331A;SQUARE KURUZEIRO;So;0;L;<square> 30AF 30EB 30BC 30A4 30ED;;;;N;SQUARED KURUZEIRO;;;; +331B;SQUARE KUROONE;So;0;L;<square> 30AF 30ED 30FC 30CD;;;;N;SQUARED KUROONE;;;; +331C;SQUARE KEESU;So;0;L;<square> 30B1 30FC 30B9;;;;N;SQUARED KEESU;;;; +331D;SQUARE KORUNA;So;0;L;<square> 30B3 30EB 30CA;;;;N;SQUARED KORUNA;;;; +331E;SQUARE KOOPO;So;0;L;<square> 30B3 30FC 30DD;;;;N;SQUARED KOOPO;;;; +331F;SQUARE SAIKURU;So;0;L;<square> 30B5 30A4 30AF 30EB;;;;N;SQUARED SAIKURU;;;; +3320;SQUARE SANTIIMU;So;0;L;<square> 30B5 30F3 30C1 30FC 30E0;;;;N;SQUARED SANTIIMU;;;; +3321;SQUARE SIRINGU;So;0;L;<square> 30B7 30EA 30F3 30B0;;;;N;SQUARED SIRINGU;;;; +3322;SQUARE SENTI;So;0;L;<square> 30BB 30F3 30C1;;;;N;SQUARED SENTI;;;; +3323;SQUARE SENTO;So;0;L;<square> 30BB 30F3 30C8;;;;N;SQUARED SENTO;;;; +3324;SQUARE DAASU;So;0;L;<square> 30C0 30FC 30B9;;;;N;SQUARED DAASU;;;; +3325;SQUARE DESI;So;0;L;<square> 30C7 30B7;;;;N;SQUARED DESI;;;; +3326;SQUARE DORU;So;0;L;<square> 30C9 30EB;;;;N;SQUARED DORU;;;; +3327;SQUARE TON;So;0;L;<square> 30C8 30F3;;;;N;SQUARED TON;;;; +3328;SQUARE NANO;So;0;L;<square> 30CA 30CE;;;;N;SQUARED NANO;;;; +3329;SQUARE NOTTO;So;0;L;<square> 30CE 30C3 30C8;;;;N;SQUARED NOTTO;;;; +332A;SQUARE HAITU;So;0;L;<square> 30CF 30A4 30C4;;;;N;SQUARED HAITU;;;; +332B;SQUARE PAASENTO;So;0;L;<square> 30D1 30FC 30BB 30F3 30C8;;;;N;SQUARED PAASENTO;;;; +332C;SQUARE PAATU;So;0;L;<square> 30D1 30FC 30C4;;;;N;SQUARED PAATU;;;; +332D;SQUARE BAARERU;So;0;L;<square> 30D0 30FC 30EC 30EB;;;;N;SQUARED BAARERU;;;; +332E;SQUARE PIASUTORU;So;0;L;<square> 30D4 30A2 30B9 30C8 30EB;;;;N;SQUARED PIASUTORU;;;; +332F;SQUARE PIKURU;So;0;L;<square> 30D4 30AF 30EB;;;;N;SQUARED PIKURU;;;; +3330;SQUARE PIKO;So;0;L;<square> 30D4 30B3;;;;N;SQUARED PIKO;;;; +3331;SQUARE BIRU;So;0;L;<square> 30D3 30EB;;;;N;SQUARED BIRU;;;; +3332;SQUARE HUARADDO;So;0;L;<square> 30D5 30A1 30E9 30C3 30C9;;;;N;SQUARED HUARADDO;;;; +3333;SQUARE HUIITO;So;0;L;<square> 30D5 30A3 30FC 30C8;;;;N;SQUARED HUIITO;;;; +3334;SQUARE BUSSYERU;So;0;L;<square> 30D6 30C3 30B7 30A7 30EB;;;;N;SQUARED BUSSYERU;;;; +3335;SQUARE HURAN;So;0;L;<square> 30D5 30E9 30F3;;;;N;SQUARED HURAN;;;; +3336;SQUARE HEKUTAARU;So;0;L;<square> 30D8 30AF 30BF 30FC 30EB;;;;N;SQUARED HEKUTAARU;;;; +3337;SQUARE PESO;So;0;L;<square> 30DA 30BD;;;;N;SQUARED PESO;;;; +3338;SQUARE PENIHI;So;0;L;<square> 30DA 30CB 30D2;;;;N;SQUARED PENIHI;;;; +3339;SQUARE HERUTU;So;0;L;<square> 30D8 30EB 30C4;;;;N;SQUARED HERUTU;;;; +333A;SQUARE PENSU;So;0;L;<square> 30DA 30F3 30B9;;;;N;SQUARED PENSU;;;; +333B;SQUARE PEEZI;So;0;L;<square> 30DA 30FC 30B8;;;;N;SQUARED PEEZI;;;; +333C;SQUARE BEETA;So;0;L;<square> 30D9 30FC 30BF;;;;N;SQUARED BEETA;;;; +333D;SQUARE POINTO;So;0;L;<square> 30DD 30A4 30F3 30C8;;;;N;SQUARED POINTO;;;; +333E;SQUARE BORUTO;So;0;L;<square> 30DC 30EB 30C8;;;;N;SQUARED BORUTO;;;; +333F;SQUARE HON;So;0;L;<square> 30DB 30F3;;;;N;SQUARED HON;;;; +3340;SQUARE PONDO;So;0;L;<square> 30DD 30F3 30C9;;;;N;SQUARED PONDO;;;; +3341;SQUARE HOORU;So;0;L;<square> 30DB 30FC 30EB;;;;N;SQUARED HOORU;;;; +3342;SQUARE HOON;So;0;L;<square> 30DB 30FC 30F3;;;;N;SQUARED HOON;;;; +3343;SQUARE MAIKURO;So;0;L;<square> 30DE 30A4 30AF 30ED;;;;N;SQUARED MAIKURO;;;; +3344;SQUARE MAIRU;So;0;L;<square> 30DE 30A4 30EB;;;;N;SQUARED MAIRU;;;; +3345;SQUARE MAHHA;So;0;L;<square> 30DE 30C3 30CF;;;;N;SQUARED MAHHA;;;; +3346;SQUARE MARUKU;So;0;L;<square> 30DE 30EB 30AF;;;;N;SQUARED MARUKU;;;; +3347;SQUARE MANSYON;So;0;L;<square> 30DE 30F3 30B7 30E7 30F3;;;;N;SQUARED MANSYON;;;; +3348;SQUARE MIKURON;So;0;L;<square> 30DF 30AF 30ED 30F3;;;;N;SQUARED MIKURON;;;; +3349;SQUARE MIRI;So;0;L;<square> 30DF 30EA;;;;N;SQUARED MIRI;;;; +334A;SQUARE MIRIBAARU;So;0;L;<square> 30DF 30EA 30D0 30FC 30EB;;;;N;SQUARED MIRIBAARU;;;; +334B;SQUARE MEGA;So;0;L;<square> 30E1 30AC;;;;N;SQUARED MEGA;;;; +334C;SQUARE MEGATON;So;0;L;<square> 30E1 30AC 30C8 30F3;;;;N;SQUARED MEGATON;;;; +334D;SQUARE MEETORU;So;0;L;<square> 30E1 30FC 30C8 30EB;;;;N;SQUARED MEETORU;;;; +334E;SQUARE YAADO;So;0;L;<square> 30E4 30FC 30C9;;;;N;SQUARED YAADO;;;; +334F;SQUARE YAARU;So;0;L;<square> 30E4 30FC 30EB;;;;N;SQUARED YAARU;;;; +3350;SQUARE YUAN;So;0;L;<square> 30E6 30A2 30F3;;;;N;SQUARED YUAN;;;; +3351;SQUARE RITTORU;So;0;L;<square> 30EA 30C3 30C8 30EB;;;;N;SQUARED RITTORU;;;; +3352;SQUARE RIRA;So;0;L;<square> 30EA 30E9;;;;N;SQUARED RIRA;;;; +3353;SQUARE RUPII;So;0;L;<square> 30EB 30D4 30FC;;;;N;SQUARED RUPII;;;; +3354;SQUARE RUUBURU;So;0;L;<square> 30EB 30FC 30D6 30EB;;;;N;SQUARED RUUBURU;;;; +3355;SQUARE REMU;So;0;L;<square> 30EC 30E0;;;;N;SQUARED REMU;;;; +3356;SQUARE RENTOGEN;So;0;L;<square> 30EC 30F3 30C8 30B2 30F3;;;;N;SQUARED RENTOGEN;;;; +3357;SQUARE WATTO;So;0;L;<square> 30EF 30C3 30C8;;;;N;SQUARED WATTO;;;; +3358;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO;So;0;L;<compat> 0030 70B9;;;;N;;;;; +3359;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE;So;0;L;<compat> 0031 70B9;;;;N;;;;; +335A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO;So;0;L;<compat> 0032 70B9;;;;N;;;;; +335B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE;So;0;L;<compat> 0033 70B9;;;;N;;;;; +335C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR;So;0;L;<compat> 0034 70B9;;;;N;;;;; +335D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE;So;0;L;<compat> 0035 70B9;;;;N;;;;; +335E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX;So;0;L;<compat> 0036 70B9;;;;N;;;;; +335F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN;So;0;L;<compat> 0037 70B9;;;;N;;;;; +3360;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT;So;0;L;<compat> 0038 70B9;;;;N;;;;; +3361;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE;So;0;L;<compat> 0039 70B9;;;;N;;;;; +3362;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN;So;0;L;<compat> 0031 0030 70B9;;;;N;;;;; +3363;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN;So;0;L;<compat> 0031 0031 70B9;;;;N;;;;; +3364;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE;So;0;L;<compat> 0031 0032 70B9;;;;N;;;;; +3365;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN;So;0;L;<compat> 0031 0033 70B9;;;;N;;;;; +3366;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN;So;0;L;<compat> 0031 0034 70B9;;;;N;;;;; +3367;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN;So;0;L;<compat> 0031 0035 70B9;;;;N;;;;; +3368;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN;So;0;L;<compat> 0031 0036 70B9;;;;N;;;;; +3369;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN;So;0;L;<compat> 0031 0037 70B9;;;;N;;;;; +336A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN;So;0;L;<compat> 0031 0038 70B9;;;;N;;;;; +336B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN;So;0;L;<compat> 0031 0039 70B9;;;;N;;;;; +336C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY;So;0;L;<compat> 0032 0030 70B9;;;;N;;;;; +336D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE;So;0;L;<compat> 0032 0031 70B9;;;;N;;;;; +336E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO;So;0;L;<compat> 0032 0032 70B9;;;;N;;;;; +336F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE;So;0;L;<compat> 0032 0033 70B9;;;;N;;;;; +3370;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR;So;0;L;<compat> 0032 0034 70B9;;;;N;;;;; +3371;SQUARE HPA;So;0;L;<square> 0068 0050 0061;;;;N;;;;; +3372;SQUARE DA;So;0;L;<square> 0064 0061;;;;N;;;;; +3373;SQUARE AU;So;0;L;<square> 0041 0055;;;;N;;;;; +3374;SQUARE BAR;So;0;L;<square> 0062 0061 0072;;;;N;;;;; +3375;SQUARE OV;So;0;L;<square> 006F 0056;;;;N;;;;; +3376;SQUARE PC;So;0;L;<square> 0070 0063;;;;N;;;;; +3377;SQUARE DM;So;0;ON;<square> 0064 006D;;;;N;;;;; +3378;SQUARE DM SQUARED;So;0;ON;<square> 0064 006D 00B2;;;;N;;;;; +3379;SQUARE DM CUBED;So;0;ON;<square> 0064 006D 00B3;;;;N;;;;; +337A;SQUARE IU;So;0;ON;<square> 0049 0055;;;;N;;;;; +337B;SQUARE ERA NAME HEISEI;So;0;L;<square> 5E73 6210;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME HEISEI;;;; +337C;SQUARE ERA NAME SYOUWA;So;0;L;<square> 662D 548C;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME SYOUWA;;;; +337D;SQUARE ERA NAME TAISYOU;So;0;L;<square> 5927 6B63;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME TAISYOU;;;; +337E;SQUARE ERA NAME MEIZI;So;0;L;<square> 660E 6CBB;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME MEIZI;;;; +337F;SQUARE CORPORATION;So;0;L;<square> 682A 5F0F 4F1A 793E;;;;N;SQUARED FOUR IDEOGRAPHS CORPORATION;;;; +3380;SQUARE PA AMPS;So;0;L;<square> 0070 0041;;;;N;SQUARED PA AMPS;;;; +3381;SQUARE NA;So;0;L;<square> 006E 0041;;;;N;SQUARED NA;;;; +3382;SQUARE MU A;So;0;L;<square> 03BC 0041;;;;N;SQUARED MU A;;;; +3383;SQUARE MA;So;0;L;<square> 006D 0041;;;;N;SQUARED MA;;;; +3384;SQUARE KA;So;0;L;<square> 006B 0041;;;;N;SQUARED KA;;;; +3385;SQUARE KB;So;0;L;<square> 004B 0042;;;;N;SQUARED KB;;;; +3386;SQUARE MB;So;0;L;<square> 004D 0042;;;;N;SQUARED MB;;;; +3387;SQUARE GB;So;0;L;<square> 0047 0042;;;;N;SQUARED GB;;;; +3388;SQUARE CAL;So;0;L;<square> 0063 0061 006C;;;;N;SQUARED CAL;;;; +3389;SQUARE KCAL;So;0;L;<square> 006B 0063 0061 006C;;;;N;SQUARED KCAL;;;; +338A;SQUARE PF;So;0;L;<square> 0070 0046;;;;N;SQUARED PF;;;; +338B;SQUARE NF;So;0;L;<square> 006E 0046;;;;N;SQUARED NF;;;; +338C;SQUARE MU F;So;0;L;<square> 03BC 0046;;;;N;SQUARED MU F;;;; +338D;SQUARE MU G;So;0;L;<square> 03BC 0067;;;;N;SQUARED MU G;;;; +338E;SQUARE MG;So;0;L;<square> 006D 0067;;;;N;SQUARED MG;;;; +338F;SQUARE KG;So;0;L;<square> 006B 0067;;;;N;SQUARED KG;;;; +3390;SQUARE HZ;So;0;L;<square> 0048 007A;;;;N;SQUARED HZ;;;; +3391;SQUARE KHZ;So;0;L;<square> 006B 0048 007A;;;;N;SQUARED KHZ;;;; +3392;SQUARE MHZ;So;0;L;<square> 004D 0048 007A;;;;N;SQUARED MHZ;;;; +3393;SQUARE GHZ;So;0;L;<square> 0047 0048 007A;;;;N;SQUARED GHZ;;;; +3394;SQUARE THZ;So;0;L;<square> 0054 0048 007A;;;;N;SQUARED THZ;;;; +3395;SQUARE MU L;So;0;L;<square> 03BC 2113;;;;N;SQUARED MU L;;;; +3396;SQUARE ML;So;0;L;<square> 006D 2113;;;;N;SQUARED ML;;;; +3397;SQUARE DL;So;0;L;<square> 0064 2113;;;;N;SQUARED DL;;;; +3398;SQUARE KL;So;0;L;<square> 006B 2113;;;;N;SQUARED KL;;;; +3399;SQUARE FM;So;0;L;<square> 0066 006D;;;;N;SQUARED FM;;;; +339A;SQUARE NM;So;0;L;<square> 006E 006D;;;;N;SQUARED NM;;;; +339B;SQUARE MU M;So;0;L;<square> 03BC 006D;;;;N;SQUARED MU M;;;; +339C;SQUARE MM;So;0;L;<square> 006D 006D;;;;N;SQUARED MM;;;; +339D;SQUARE CM;So;0;L;<square> 0063 006D;;;;N;SQUARED CM;;;; +339E;SQUARE KM;So;0;L;<square> 006B 006D;;;;N;SQUARED KM;;;; +339F;SQUARE MM SQUARED;So;0;L;<square> 006D 006D 00B2;;;;N;SQUARED MM SQUARED;;;; +33A0;SQUARE CM SQUARED;So;0;L;<square> 0063 006D 00B2;;;;N;SQUARED CM SQUARED;;;; +33A1;SQUARE M SQUARED;So;0;L;<square> 006D 00B2;;;;N;SQUARED M SQUARED;;;; +33A2;SQUARE KM SQUARED;So;0;L;<square> 006B 006D 00B2;;;;N;SQUARED KM SQUARED;;;; +33A3;SQUARE MM CUBED;So;0;L;<square> 006D 006D 00B3;;;;N;SQUARED MM CUBED;;;; +33A4;SQUARE CM CUBED;So;0;L;<square> 0063 006D 00B3;;;;N;SQUARED CM CUBED;;;; +33A5;SQUARE M CUBED;So;0;L;<square> 006D 00B3;;;;N;SQUARED M CUBED;;;; +33A6;SQUARE KM CUBED;So;0;L;<square> 006B 006D 00B3;;;;N;SQUARED KM CUBED;;;; +33A7;SQUARE M OVER S;So;0;L;<square> 006D 2215 0073;;;;N;SQUARED M OVER S;;;; +33A8;SQUARE M OVER S SQUARED;So;0;L;<square> 006D 2215 0073 00B2;;;;N;SQUARED M OVER S SQUARED;;;; +33A9;SQUARE PA;So;0;L;<square> 0050 0061;;;;N;SQUARED PA;;;; +33AA;SQUARE KPA;So;0;L;<square> 006B 0050 0061;;;;N;SQUARED KPA;;;; +33AB;SQUARE MPA;So;0;L;<square> 004D 0050 0061;;;;N;SQUARED MPA;;;; +33AC;SQUARE GPA;So;0;L;<square> 0047 0050 0061;;;;N;SQUARED GPA;;;; +33AD;SQUARE RAD;So;0;L;<square> 0072 0061 0064;;;;N;SQUARED RAD;;;; +33AE;SQUARE RAD OVER S;So;0;L;<square> 0072 0061 0064 2215 0073;;;;N;SQUARED RAD OVER S;;;; +33AF;SQUARE RAD OVER S SQUARED;So;0;L;<square> 0072 0061 0064 2215 0073 00B2;;;;N;SQUARED RAD OVER S SQUARED;;;; +33B0;SQUARE PS;So;0;L;<square> 0070 0073;;;;N;SQUARED PS;;;; +33B1;SQUARE NS;So;0;L;<square> 006E 0073;;;;N;SQUARED NS;;;; +33B2;SQUARE MU S;So;0;L;<square> 03BC 0073;;;;N;SQUARED MU S;;;; +33B3;SQUARE MS;So;0;L;<square> 006D 0073;;;;N;SQUARED MS;;;; +33B4;SQUARE PV;So;0;L;<square> 0070 0056;;;;N;SQUARED PV;;;; +33B5;SQUARE NV;So;0;L;<square> 006E 0056;;;;N;SQUARED NV;;;; +33B6;SQUARE MU V;So;0;L;<square> 03BC 0056;;;;N;SQUARED MU V;;;; +33B7;SQUARE MV;So;0;L;<square> 006D 0056;;;;N;SQUARED MV;;;; +33B8;SQUARE KV;So;0;L;<square> 006B 0056;;;;N;SQUARED KV;;;; +33B9;SQUARE MV MEGA;So;0;L;<square> 004D 0056;;;;N;SQUARED MV MEGA;;;; +33BA;SQUARE PW;So;0;L;<square> 0070 0057;;;;N;SQUARED PW;;;; +33BB;SQUARE NW;So;0;L;<square> 006E 0057;;;;N;SQUARED NW;;;; +33BC;SQUARE MU W;So;0;L;<square> 03BC 0057;;;;N;SQUARED MU W;;;; +33BD;SQUARE MW;So;0;L;<square> 006D 0057;;;;N;SQUARED MW;;;; +33BE;SQUARE KW;So;0;L;<square> 006B 0057;;;;N;SQUARED KW;;;; +33BF;SQUARE MW MEGA;So;0;L;<square> 004D 0057;;;;N;SQUARED MW MEGA;;;; +33C0;SQUARE K OHM;So;0;L;<square> 006B 03A9;;;;N;SQUARED K OHM;;;; +33C1;SQUARE M OHM;So;0;L;<square> 004D 03A9;;;;N;SQUARED M OHM;;;; +33C2;SQUARE AM;So;0;L;<square> 0061 002E 006D 002E;;;;N;SQUARED AM;;;; +33C3;SQUARE BQ;So;0;L;<square> 0042 0071;;;;N;SQUARED BQ;;;; +33C4;SQUARE CC;So;0;L;<square> 0063 0063;;;;N;SQUARED CC;;;; +33C5;SQUARE CD;So;0;L;<square> 0063 0064;;;;N;SQUARED CD;;;; +33C6;SQUARE C OVER KG;So;0;L;<square> 0043 2215 006B 0067;;;;N;SQUARED C OVER KG;;;; +33C7;SQUARE CO;So;0;L;<square> 0043 006F 002E;;;;N;SQUARED CO;;;; +33C8;SQUARE DB;So;0;L;<square> 0064 0042;;;;N;SQUARED DB;;;; +33C9;SQUARE GY;So;0;L;<square> 0047 0079;;;;N;SQUARED GY;;;; +33CA;SQUARE HA;So;0;L;<square> 0068 0061;;;;N;SQUARED HA;;;; +33CB;SQUARE HP;So;0;L;<square> 0048 0050;;;;N;SQUARED HP;;;; +33CC;SQUARE IN;So;0;L;<square> 0069 006E;;;;N;SQUARED IN;;;; +33CD;SQUARE KK;So;0;L;<square> 004B 004B;;;;N;SQUARED KK;;;; +33CE;SQUARE KM CAPITAL;So;0;L;<square> 004B 004D;;;;N;SQUARED KM CAPITAL;;;; +33CF;SQUARE KT;So;0;L;<square> 006B 0074;;;;N;SQUARED KT;;;; +33D0;SQUARE LM;So;0;L;<square> 006C 006D;;;;N;SQUARED LM;;;; +33D1;SQUARE LN;So;0;L;<square> 006C 006E;;;;N;SQUARED LN;;;; +33D2;SQUARE LOG;So;0;L;<square> 006C 006F 0067;;;;N;SQUARED LOG;;;; +33D3;SQUARE LX;So;0;L;<square> 006C 0078;;;;N;SQUARED LX;;;; +33D4;SQUARE MB SMALL;So;0;L;<square> 006D 0062;;;;N;SQUARED MB SMALL;;;; +33D5;SQUARE MIL;So;0;L;<square> 006D 0069 006C;;;;N;SQUARED MIL;;;; +33D6;SQUARE MOL;So;0;L;<square> 006D 006F 006C;;;;N;SQUARED MOL;;;; +33D7;SQUARE PH;So;0;L;<square> 0050 0048;;;;N;SQUARED PH;;;; +33D8;SQUARE PM;So;0;L;<square> 0070 002E 006D 002E;;;;N;SQUARED PM;;;; +33D9;SQUARE PPM;So;0;L;<square> 0050 0050 004D;;;;N;SQUARED PPM;;;; +33DA;SQUARE PR;So;0;L;<square> 0050 0052;;;;N;SQUARED PR;;;; +33DB;SQUARE SR;So;0;L;<square> 0073 0072;;;;N;SQUARED SR;;;; +33DC;SQUARE SV;So;0;L;<square> 0053 0076;;;;N;SQUARED SV;;;; +33DD;SQUARE WB;So;0;L;<square> 0057 0062;;;;N;SQUARED WB;;;; +33DE;SQUARE V OVER M;So;0;ON;<square> 0056 2215 006D;;;;N;;;;; +33DF;SQUARE A OVER M;So;0;ON;<square> 0041 2215 006D;;;;N;;;;; +33E0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE;So;0;L;<compat> 0031 65E5;;;;N;;;;; +33E1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO;So;0;L;<compat> 0032 65E5;;;;N;;;;; +33E2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE;So;0;L;<compat> 0033 65E5;;;;N;;;;; +33E3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR;So;0;L;<compat> 0034 65E5;;;;N;;;;; +33E4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE;So;0;L;<compat> 0035 65E5;;;;N;;;;; +33E5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX;So;0;L;<compat> 0036 65E5;;;;N;;;;; +33E6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN;So;0;L;<compat> 0037 65E5;;;;N;;;;; +33E7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT;So;0;L;<compat> 0038 65E5;;;;N;;;;; +33E8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE;So;0;L;<compat> 0039 65E5;;;;N;;;;; +33E9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN;So;0;L;<compat> 0031 0030 65E5;;;;N;;;;; +33EA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN;So;0;L;<compat> 0031 0031 65E5;;;;N;;;;; +33EB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE;So;0;L;<compat> 0031 0032 65E5;;;;N;;;;; +33EC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN;So;0;L;<compat> 0031 0033 65E5;;;;N;;;;; +33ED;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN;So;0;L;<compat> 0031 0034 65E5;;;;N;;;;; +33EE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN;So;0;L;<compat> 0031 0035 65E5;;;;N;;;;; +33EF;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN;So;0;L;<compat> 0031 0036 65E5;;;;N;;;;; +33F0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN;So;0;L;<compat> 0031 0037 65E5;;;;N;;;;; +33F1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN;So;0;L;<compat> 0031 0038 65E5;;;;N;;;;; +33F2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN;So;0;L;<compat> 0031 0039 65E5;;;;N;;;;; +33F3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY;So;0;L;<compat> 0032 0030 65E5;;;;N;;;;; +33F4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE;So;0;L;<compat> 0032 0031 65E5;;;;N;;;;; +33F5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO;So;0;L;<compat> 0032 0032 65E5;;;;N;;;;; +33F6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE;So;0;L;<compat> 0032 0033 65E5;;;;N;;;;; +33F7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR;So;0;L;<compat> 0032 0034 65E5;;;;N;;;;; +33F8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE;So;0;L;<compat> 0032 0035 65E5;;;;N;;;;; +33F9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX;So;0;L;<compat> 0032 0036 65E5;;;;N;;;;; +33FA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN;So;0;L;<compat> 0032 0037 65E5;;;;N;;;;; +33FB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT;So;0;L;<compat> 0032 0038 65E5;;;;N;;;;; +33FC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE;So;0;L;<compat> 0032 0039 65E5;;;;N;;;;; +33FD;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY;So;0;L;<compat> 0033 0030 65E5;;;;N;;;;; +33FE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE;So;0;L;<compat> 0033 0031 65E5;;;;N;;;;; +33FF;SQUARE GAL;So;0;ON;<square> 0067 0061 006C;;;;N;;;;; +3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;; +4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;; +4DC0;HEXAGRAM FOR THE CREATIVE HEAVEN;So;0;ON;;;;;N;;;;; +4DC1;HEXAGRAM FOR THE RECEPTIVE EARTH;So;0;ON;;;;;N;;;;; +4DC2;HEXAGRAM FOR DIFFICULTY AT THE BEGINNING;So;0;ON;;;;;N;;;;; +4DC3;HEXAGRAM FOR YOUTHFUL FOLLY;So;0;ON;;;;;N;;;;; +4DC4;HEXAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; +4DC5;HEXAGRAM FOR CONFLICT;So;0;ON;;;;;N;;;;; +4DC6;HEXAGRAM FOR THE ARMY;So;0;ON;;;;;N;;;;; +4DC7;HEXAGRAM FOR HOLDING TOGETHER;So;0;ON;;;;;N;;;;; +4DC8;HEXAGRAM FOR SMALL TAMING;So;0;ON;;;;;N;;;;; +4DC9;HEXAGRAM FOR TREADING;So;0;ON;;;;;N;;;;; +4DCA;HEXAGRAM FOR PEACE;So;0;ON;;;;;N;;;;; +4DCB;HEXAGRAM FOR STANDSTILL;So;0;ON;;;;;N;;;;; +4DCC;HEXAGRAM FOR FELLOWSHIP;So;0;ON;;;;;N;;;;; +4DCD;HEXAGRAM FOR GREAT POSSESSION;So;0;ON;;;;;N;;;;; +4DCE;HEXAGRAM FOR MODESTY;So;0;ON;;;;;N;;;;; +4DCF;HEXAGRAM FOR ENTHUSIASM;So;0;ON;;;;;N;;;;; +4DD0;HEXAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; +4DD1;HEXAGRAM FOR WORK ON THE DECAYED;So;0;ON;;;;;N;;;;; +4DD2;HEXAGRAM FOR APPROACH;So;0;ON;;;;;N;;;;; +4DD3;HEXAGRAM FOR CONTEMPLATION;So;0;ON;;;;;N;;;;; +4DD4;HEXAGRAM FOR BITING THROUGH;So;0;ON;;;;;N;;;;; +4DD5;HEXAGRAM FOR GRACE;So;0;ON;;;;;N;;;;; +4DD6;HEXAGRAM FOR SPLITTING APART;So;0;ON;;;;;N;;;;; +4DD7;HEXAGRAM FOR RETURN;So;0;ON;;;;;N;;;;; +4DD8;HEXAGRAM FOR INNOCENCE;So;0;ON;;;;;N;;;;; +4DD9;HEXAGRAM FOR GREAT TAMING;So;0;ON;;;;;N;;;;; +4DDA;HEXAGRAM FOR MOUTH CORNERS;So;0;ON;;;;;N;;;;; +4DDB;HEXAGRAM FOR GREAT PREPONDERANCE;So;0;ON;;;;;N;;;;; +4DDC;HEXAGRAM FOR THE ABYSMAL WATER;So;0;ON;;;;;N;;;;; +4DDD;HEXAGRAM FOR THE CLINGING FIRE;So;0;ON;;;;;N;;;;; +4DDE;HEXAGRAM FOR INFLUENCE;So;0;ON;;;;;N;;;;; +4DDF;HEXAGRAM FOR DURATION;So;0;ON;;;;;N;;;;; +4DE0;HEXAGRAM FOR RETREAT;So;0;ON;;;;;N;;;;; +4DE1;HEXAGRAM FOR GREAT POWER;So;0;ON;;;;;N;;;;; +4DE2;HEXAGRAM FOR PROGRESS;So;0;ON;;;;;N;;;;; +4DE3;HEXAGRAM FOR DARKENING OF THE LIGHT;So;0;ON;;;;;N;;;;; +4DE4;HEXAGRAM FOR THE FAMILY;So;0;ON;;;;;N;;;;; +4DE5;HEXAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; +4DE6;HEXAGRAM FOR OBSTRUCTION;So;0;ON;;;;;N;;;;; +4DE7;HEXAGRAM FOR DELIVERANCE;So;0;ON;;;;;N;;;;; +4DE8;HEXAGRAM FOR DECREASE;So;0;ON;;;;;N;;;;; +4DE9;HEXAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; +4DEA;HEXAGRAM FOR BREAKTHROUGH;So;0;ON;;;;;N;;;;; +4DEB;HEXAGRAM FOR COMING TO MEET;So;0;ON;;;;;N;;;;; +4DEC;HEXAGRAM FOR GATHERING TOGETHER;So;0;ON;;;;;N;;;;; +4DED;HEXAGRAM FOR PUSHING UPWARD;So;0;ON;;;;;N;;;;; +4DEE;HEXAGRAM FOR OPPRESSION;So;0;ON;;;;;N;;;;; +4DEF;HEXAGRAM FOR THE WELL;So;0;ON;;;;;N;;;;; +4DF0;HEXAGRAM FOR REVOLUTION;So;0;ON;;;;;N;;;;; +4DF1;HEXAGRAM FOR THE CAULDRON;So;0;ON;;;;;N;;;;; +4DF2;HEXAGRAM FOR THE AROUSING THUNDER;So;0;ON;;;;;N;;;;; +4DF3;HEXAGRAM FOR THE KEEPING STILL MOUNTAIN;So;0;ON;;;;;N;;;;; +4DF4;HEXAGRAM FOR DEVELOPMENT;So;0;ON;;;;;N;;;;; +4DF5;HEXAGRAM FOR THE MARRYING MAIDEN;So;0;ON;;;;;N;;;;; +4DF6;HEXAGRAM FOR ABUNDANCE;So;0;ON;;;;;N;;;;; +4DF7;HEXAGRAM FOR THE WANDERER;So;0;ON;;;;;N;;;;; +4DF8;HEXAGRAM FOR THE GENTLE WIND;So;0;ON;;;;;N;;;;; +4DF9;HEXAGRAM FOR THE JOYOUS LAKE;So;0;ON;;;;;N;;;;; +4DFA;HEXAGRAM FOR DISPERSION;So;0;ON;;;;;N;;;;; +4DFB;HEXAGRAM FOR LIMITATION;So;0;ON;;;;;N;;;;; +4DFC;HEXAGRAM FOR INNER TRUTH;So;0;ON;;;;;N;;;;; +4DFD;HEXAGRAM FOR SMALL PREPONDERANCE;So;0;ON;;;;;N;;;;; +4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; +4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; +4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;; +9FEA;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;; +A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; +A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; +A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; +A003;YI SYLLABLE IP;Lo;0;L;;;;;N;;;;; +A004;YI SYLLABLE IET;Lo;0;L;;;;;N;;;;; +A005;YI SYLLABLE IEX;Lo;0;L;;;;;N;;;;; +A006;YI SYLLABLE IE;Lo;0;L;;;;;N;;;;; +A007;YI SYLLABLE IEP;Lo;0;L;;;;;N;;;;; +A008;YI SYLLABLE AT;Lo;0;L;;;;;N;;;;; +A009;YI SYLLABLE AX;Lo;0;L;;;;;N;;;;; +A00A;YI SYLLABLE A;Lo;0;L;;;;;N;;;;; +A00B;YI SYLLABLE AP;Lo;0;L;;;;;N;;;;; +A00C;YI SYLLABLE UOX;Lo;0;L;;;;;N;;;;; +A00D;YI SYLLABLE UO;Lo;0;L;;;;;N;;;;; +A00E;YI SYLLABLE UOP;Lo;0;L;;;;;N;;;;; +A00F;YI SYLLABLE OT;Lo;0;L;;;;;N;;;;; +A010;YI SYLLABLE OX;Lo;0;L;;;;;N;;;;; +A011;YI SYLLABLE O;Lo;0;L;;;;;N;;;;; +A012;YI SYLLABLE OP;Lo;0;L;;;;;N;;;;; +A013;YI SYLLABLE EX;Lo;0;L;;;;;N;;;;; +A014;YI SYLLABLE E;Lo;0;L;;;;;N;;;;; +A015;YI SYLLABLE WU;Lm;0;L;;;;;N;;;;; +A016;YI SYLLABLE BIT;Lo;0;L;;;;;N;;;;; +A017;YI SYLLABLE BIX;Lo;0;L;;;;;N;;;;; +A018;YI SYLLABLE BI;Lo;0;L;;;;;N;;;;; +A019;YI SYLLABLE BIP;Lo;0;L;;;;;N;;;;; +A01A;YI SYLLABLE BIET;Lo;0;L;;;;;N;;;;; +A01B;YI SYLLABLE BIEX;Lo;0;L;;;;;N;;;;; +A01C;YI SYLLABLE BIE;Lo;0;L;;;;;N;;;;; +A01D;YI SYLLABLE BIEP;Lo;0;L;;;;;N;;;;; +A01E;YI SYLLABLE BAT;Lo;0;L;;;;;N;;;;; +A01F;YI SYLLABLE BAX;Lo;0;L;;;;;N;;;;; +A020;YI SYLLABLE BA;Lo;0;L;;;;;N;;;;; +A021;YI SYLLABLE BAP;Lo;0;L;;;;;N;;;;; +A022;YI SYLLABLE BUOX;Lo;0;L;;;;;N;;;;; +A023;YI SYLLABLE BUO;Lo;0;L;;;;;N;;;;; +A024;YI SYLLABLE BUOP;Lo;0;L;;;;;N;;;;; +A025;YI SYLLABLE BOT;Lo;0;L;;;;;N;;;;; +A026;YI SYLLABLE BOX;Lo;0;L;;;;;N;;;;; +A027;YI SYLLABLE BO;Lo;0;L;;;;;N;;;;; +A028;YI SYLLABLE BOP;Lo;0;L;;;;;N;;;;; +A029;YI SYLLABLE BEX;Lo;0;L;;;;;N;;;;; +A02A;YI SYLLABLE BE;Lo;0;L;;;;;N;;;;; +A02B;YI SYLLABLE BEP;Lo;0;L;;;;;N;;;;; +A02C;YI SYLLABLE BUT;Lo;0;L;;;;;N;;;;; +A02D;YI SYLLABLE BUX;Lo;0;L;;;;;N;;;;; +A02E;YI SYLLABLE BU;Lo;0;L;;;;;N;;;;; +A02F;YI SYLLABLE BUP;Lo;0;L;;;;;N;;;;; +A030;YI SYLLABLE BURX;Lo;0;L;;;;;N;;;;; +A031;YI SYLLABLE BUR;Lo;0;L;;;;;N;;;;; +A032;YI SYLLABLE BYT;Lo;0;L;;;;;N;;;;; +A033;YI SYLLABLE BYX;Lo;0;L;;;;;N;;;;; +A034;YI SYLLABLE BY;Lo;0;L;;;;;N;;;;; +A035;YI SYLLABLE BYP;Lo;0;L;;;;;N;;;;; +A036;YI SYLLABLE BYRX;Lo;0;L;;;;;N;;;;; +A037;YI SYLLABLE BYR;Lo;0;L;;;;;N;;;;; +A038;YI SYLLABLE PIT;Lo;0;L;;;;;N;;;;; +A039;YI SYLLABLE PIX;Lo;0;L;;;;;N;;;;; +A03A;YI SYLLABLE PI;Lo;0;L;;;;;N;;;;; +A03B;YI SYLLABLE PIP;Lo;0;L;;;;;N;;;;; +A03C;YI SYLLABLE PIEX;Lo;0;L;;;;;N;;;;; +A03D;YI SYLLABLE PIE;Lo;0;L;;;;;N;;;;; +A03E;YI SYLLABLE PIEP;Lo;0;L;;;;;N;;;;; +A03F;YI SYLLABLE PAT;Lo;0;L;;;;;N;;;;; +A040;YI SYLLABLE PAX;Lo;0;L;;;;;N;;;;; +A041;YI SYLLABLE PA;Lo;0;L;;;;;N;;;;; +A042;YI SYLLABLE PAP;Lo;0;L;;;;;N;;;;; +A043;YI SYLLABLE PUOX;Lo;0;L;;;;;N;;;;; +A044;YI SYLLABLE PUO;Lo;0;L;;;;;N;;;;; +A045;YI SYLLABLE PUOP;Lo;0;L;;;;;N;;;;; +A046;YI SYLLABLE POT;Lo;0;L;;;;;N;;;;; +A047;YI SYLLABLE POX;Lo;0;L;;;;;N;;;;; +A048;YI SYLLABLE PO;Lo;0;L;;;;;N;;;;; +A049;YI SYLLABLE POP;Lo;0;L;;;;;N;;;;; +A04A;YI SYLLABLE PUT;Lo;0;L;;;;;N;;;;; +A04B;YI SYLLABLE PUX;Lo;0;L;;;;;N;;;;; +A04C;YI SYLLABLE PU;Lo;0;L;;;;;N;;;;; +A04D;YI SYLLABLE PUP;Lo;0;L;;;;;N;;;;; +A04E;YI SYLLABLE PURX;Lo;0;L;;;;;N;;;;; +A04F;YI SYLLABLE PUR;Lo;0;L;;;;;N;;;;; +A050;YI SYLLABLE PYT;Lo;0;L;;;;;N;;;;; +A051;YI SYLLABLE PYX;Lo;0;L;;;;;N;;;;; +A052;YI SYLLABLE PY;Lo;0;L;;;;;N;;;;; +A053;YI SYLLABLE PYP;Lo;0;L;;;;;N;;;;; +A054;YI SYLLABLE PYRX;Lo;0;L;;;;;N;;;;; +A055;YI SYLLABLE PYR;Lo;0;L;;;;;N;;;;; +A056;YI SYLLABLE BBIT;Lo;0;L;;;;;N;;;;; +A057;YI SYLLABLE BBIX;Lo;0;L;;;;;N;;;;; +A058;YI SYLLABLE BBI;Lo;0;L;;;;;N;;;;; +A059;YI SYLLABLE BBIP;Lo;0;L;;;;;N;;;;; +A05A;YI SYLLABLE BBIET;Lo;0;L;;;;;N;;;;; +A05B;YI SYLLABLE BBIEX;Lo;0;L;;;;;N;;;;; +A05C;YI SYLLABLE BBIE;Lo;0;L;;;;;N;;;;; +A05D;YI SYLLABLE BBIEP;Lo;0;L;;;;;N;;;;; +A05E;YI SYLLABLE BBAT;Lo;0;L;;;;;N;;;;; +A05F;YI SYLLABLE BBAX;Lo;0;L;;;;;N;;;;; +A060;YI SYLLABLE BBA;Lo;0;L;;;;;N;;;;; +A061;YI SYLLABLE BBAP;Lo;0;L;;;;;N;;;;; +A062;YI SYLLABLE BBUOX;Lo;0;L;;;;;N;;;;; +A063;YI SYLLABLE BBUO;Lo;0;L;;;;;N;;;;; +A064;YI SYLLABLE BBUOP;Lo;0;L;;;;;N;;;;; +A065;YI SYLLABLE BBOT;Lo;0;L;;;;;N;;;;; +A066;YI SYLLABLE BBOX;Lo;0;L;;;;;N;;;;; +A067;YI SYLLABLE BBO;Lo;0;L;;;;;N;;;;; +A068;YI SYLLABLE BBOP;Lo;0;L;;;;;N;;;;; +A069;YI SYLLABLE BBEX;Lo;0;L;;;;;N;;;;; +A06A;YI SYLLABLE BBE;Lo;0;L;;;;;N;;;;; +A06B;YI SYLLABLE BBEP;Lo;0;L;;;;;N;;;;; +A06C;YI SYLLABLE BBUT;Lo;0;L;;;;;N;;;;; +A06D;YI SYLLABLE BBUX;Lo;0;L;;;;;N;;;;; +A06E;YI SYLLABLE BBU;Lo;0;L;;;;;N;;;;; +A06F;YI SYLLABLE BBUP;Lo;0;L;;;;;N;;;;; +A070;YI SYLLABLE BBURX;Lo;0;L;;;;;N;;;;; +A071;YI SYLLABLE BBUR;Lo;0;L;;;;;N;;;;; +A072;YI SYLLABLE BBYT;Lo;0;L;;;;;N;;;;; +A073;YI SYLLABLE BBYX;Lo;0;L;;;;;N;;;;; +A074;YI SYLLABLE BBY;Lo;0;L;;;;;N;;;;; +A075;YI SYLLABLE BBYP;Lo;0;L;;;;;N;;;;; +A076;YI SYLLABLE NBIT;Lo;0;L;;;;;N;;;;; +A077;YI SYLLABLE NBIX;Lo;0;L;;;;;N;;;;; +A078;YI SYLLABLE NBI;Lo;0;L;;;;;N;;;;; +A079;YI SYLLABLE NBIP;Lo;0;L;;;;;N;;;;; +A07A;YI SYLLABLE NBIEX;Lo;0;L;;;;;N;;;;; +A07B;YI SYLLABLE NBIE;Lo;0;L;;;;;N;;;;; +A07C;YI SYLLABLE NBIEP;Lo;0;L;;;;;N;;;;; +A07D;YI SYLLABLE NBAT;Lo;0;L;;;;;N;;;;; +A07E;YI SYLLABLE NBAX;Lo;0;L;;;;;N;;;;; +A07F;YI SYLLABLE NBA;Lo;0;L;;;;;N;;;;; +A080;YI SYLLABLE NBAP;Lo;0;L;;;;;N;;;;; +A081;YI SYLLABLE NBOT;Lo;0;L;;;;;N;;;;; +A082;YI SYLLABLE NBOX;Lo;0;L;;;;;N;;;;; +A083;YI SYLLABLE NBO;Lo;0;L;;;;;N;;;;; +A084;YI SYLLABLE NBOP;Lo;0;L;;;;;N;;;;; +A085;YI SYLLABLE NBUT;Lo;0;L;;;;;N;;;;; +A086;YI SYLLABLE NBUX;Lo;0;L;;;;;N;;;;; +A087;YI SYLLABLE NBU;Lo;0;L;;;;;N;;;;; +A088;YI SYLLABLE NBUP;Lo;0;L;;;;;N;;;;; +A089;YI SYLLABLE NBURX;Lo;0;L;;;;;N;;;;; +A08A;YI SYLLABLE NBUR;Lo;0;L;;;;;N;;;;; +A08B;YI SYLLABLE NBYT;Lo;0;L;;;;;N;;;;; +A08C;YI SYLLABLE NBYX;Lo;0;L;;;;;N;;;;; +A08D;YI SYLLABLE NBY;Lo;0;L;;;;;N;;;;; +A08E;YI SYLLABLE NBYP;Lo;0;L;;;;;N;;;;; +A08F;YI SYLLABLE NBYRX;Lo;0;L;;;;;N;;;;; +A090;YI SYLLABLE NBYR;Lo;0;L;;;;;N;;;;; +A091;YI SYLLABLE HMIT;Lo;0;L;;;;;N;;;;; +A092;YI SYLLABLE HMIX;Lo;0;L;;;;;N;;;;; +A093;YI SYLLABLE HMI;Lo;0;L;;;;;N;;;;; +A094;YI SYLLABLE HMIP;Lo;0;L;;;;;N;;;;; +A095;YI SYLLABLE HMIEX;Lo;0;L;;;;;N;;;;; +A096;YI SYLLABLE HMIE;Lo;0;L;;;;;N;;;;; +A097;YI SYLLABLE HMIEP;Lo;0;L;;;;;N;;;;; +A098;YI SYLLABLE HMAT;Lo;0;L;;;;;N;;;;; +A099;YI SYLLABLE HMAX;Lo;0;L;;;;;N;;;;; +A09A;YI SYLLABLE HMA;Lo;0;L;;;;;N;;;;; +A09B;YI SYLLABLE HMAP;Lo;0;L;;;;;N;;;;; +A09C;YI SYLLABLE HMUOX;Lo;0;L;;;;;N;;;;; +A09D;YI SYLLABLE HMUO;Lo;0;L;;;;;N;;;;; +A09E;YI SYLLABLE HMUOP;Lo;0;L;;;;;N;;;;; +A09F;YI SYLLABLE HMOT;Lo;0;L;;;;;N;;;;; +A0A0;YI SYLLABLE HMOX;Lo;0;L;;;;;N;;;;; +A0A1;YI SYLLABLE HMO;Lo;0;L;;;;;N;;;;; +A0A2;YI SYLLABLE HMOP;Lo;0;L;;;;;N;;;;; +A0A3;YI SYLLABLE HMUT;Lo;0;L;;;;;N;;;;; +A0A4;YI SYLLABLE HMUX;Lo;0;L;;;;;N;;;;; +A0A5;YI SYLLABLE HMU;Lo;0;L;;;;;N;;;;; +A0A6;YI SYLLABLE HMUP;Lo;0;L;;;;;N;;;;; +A0A7;YI SYLLABLE HMURX;Lo;0;L;;;;;N;;;;; +A0A8;YI SYLLABLE HMUR;Lo;0;L;;;;;N;;;;; +A0A9;YI SYLLABLE HMYX;Lo;0;L;;;;;N;;;;; +A0AA;YI SYLLABLE HMY;Lo;0;L;;;;;N;;;;; +A0AB;YI SYLLABLE HMYP;Lo;0;L;;;;;N;;;;; +A0AC;YI SYLLABLE HMYRX;Lo;0;L;;;;;N;;;;; +A0AD;YI SYLLABLE HMYR;Lo;0;L;;;;;N;;;;; +A0AE;YI SYLLABLE MIT;Lo;0;L;;;;;N;;;;; +A0AF;YI SYLLABLE MIX;Lo;0;L;;;;;N;;;;; +A0B0;YI SYLLABLE MI;Lo;0;L;;;;;N;;;;; +A0B1;YI SYLLABLE MIP;Lo;0;L;;;;;N;;;;; +A0B2;YI SYLLABLE MIEX;Lo;0;L;;;;;N;;;;; +A0B3;YI SYLLABLE MIE;Lo;0;L;;;;;N;;;;; +A0B4;YI SYLLABLE MIEP;Lo;0;L;;;;;N;;;;; +A0B5;YI SYLLABLE MAT;Lo;0;L;;;;;N;;;;; +A0B6;YI SYLLABLE MAX;Lo;0;L;;;;;N;;;;; +A0B7;YI SYLLABLE MA;Lo;0;L;;;;;N;;;;; +A0B8;YI SYLLABLE MAP;Lo;0;L;;;;;N;;;;; +A0B9;YI SYLLABLE MUOT;Lo;0;L;;;;;N;;;;; +A0BA;YI SYLLABLE MUOX;Lo;0;L;;;;;N;;;;; +A0BB;YI SYLLABLE MUO;Lo;0;L;;;;;N;;;;; +A0BC;YI SYLLABLE MUOP;Lo;0;L;;;;;N;;;;; +A0BD;YI SYLLABLE MOT;Lo;0;L;;;;;N;;;;; +A0BE;YI SYLLABLE MOX;Lo;0;L;;;;;N;;;;; +A0BF;YI SYLLABLE MO;Lo;0;L;;;;;N;;;;; +A0C0;YI SYLLABLE MOP;Lo;0;L;;;;;N;;;;; +A0C1;YI SYLLABLE MEX;Lo;0;L;;;;;N;;;;; +A0C2;YI SYLLABLE ME;Lo;0;L;;;;;N;;;;; +A0C3;YI SYLLABLE MUT;Lo;0;L;;;;;N;;;;; +A0C4;YI SYLLABLE MUX;Lo;0;L;;;;;N;;;;; +A0C5;YI SYLLABLE MU;Lo;0;L;;;;;N;;;;; +A0C6;YI SYLLABLE MUP;Lo;0;L;;;;;N;;;;; +A0C7;YI SYLLABLE MURX;Lo;0;L;;;;;N;;;;; +A0C8;YI SYLLABLE MUR;Lo;0;L;;;;;N;;;;; +A0C9;YI SYLLABLE MYT;Lo;0;L;;;;;N;;;;; +A0CA;YI SYLLABLE MYX;Lo;0;L;;;;;N;;;;; +A0CB;YI SYLLABLE MY;Lo;0;L;;;;;N;;;;; +A0CC;YI SYLLABLE MYP;Lo;0;L;;;;;N;;;;; +A0CD;YI SYLLABLE FIT;Lo;0;L;;;;;N;;;;; +A0CE;YI SYLLABLE FIX;Lo;0;L;;;;;N;;;;; +A0CF;YI SYLLABLE FI;Lo;0;L;;;;;N;;;;; +A0D0;YI SYLLABLE FIP;Lo;0;L;;;;;N;;;;; +A0D1;YI SYLLABLE FAT;Lo;0;L;;;;;N;;;;; +A0D2;YI SYLLABLE FAX;Lo;0;L;;;;;N;;;;; +A0D3;YI SYLLABLE FA;Lo;0;L;;;;;N;;;;; +A0D4;YI SYLLABLE FAP;Lo;0;L;;;;;N;;;;; +A0D5;YI SYLLABLE FOX;Lo;0;L;;;;;N;;;;; +A0D6;YI SYLLABLE FO;Lo;0;L;;;;;N;;;;; +A0D7;YI SYLLABLE FOP;Lo;0;L;;;;;N;;;;; +A0D8;YI SYLLABLE FUT;Lo;0;L;;;;;N;;;;; +A0D9;YI SYLLABLE FUX;Lo;0;L;;;;;N;;;;; +A0DA;YI SYLLABLE FU;Lo;0;L;;;;;N;;;;; +A0DB;YI SYLLABLE FUP;Lo;0;L;;;;;N;;;;; +A0DC;YI SYLLABLE FURX;Lo;0;L;;;;;N;;;;; +A0DD;YI SYLLABLE FUR;Lo;0;L;;;;;N;;;;; +A0DE;YI SYLLABLE FYT;Lo;0;L;;;;;N;;;;; +A0DF;YI SYLLABLE FYX;Lo;0;L;;;;;N;;;;; +A0E0;YI SYLLABLE FY;Lo;0;L;;;;;N;;;;; +A0E1;YI SYLLABLE FYP;Lo;0;L;;;;;N;;;;; +A0E2;YI SYLLABLE VIT;Lo;0;L;;;;;N;;;;; +A0E3;YI SYLLABLE VIX;Lo;0;L;;;;;N;;;;; +A0E4;YI SYLLABLE VI;Lo;0;L;;;;;N;;;;; +A0E5;YI SYLLABLE VIP;Lo;0;L;;;;;N;;;;; +A0E6;YI SYLLABLE VIET;Lo;0;L;;;;;N;;;;; +A0E7;YI SYLLABLE VIEX;Lo;0;L;;;;;N;;;;; +A0E8;YI SYLLABLE VIE;Lo;0;L;;;;;N;;;;; +A0E9;YI SYLLABLE VIEP;Lo;0;L;;;;;N;;;;; +A0EA;YI SYLLABLE VAT;Lo;0;L;;;;;N;;;;; +A0EB;YI SYLLABLE VAX;Lo;0;L;;;;;N;;;;; +A0EC;YI SYLLABLE VA;Lo;0;L;;;;;N;;;;; +A0ED;YI SYLLABLE VAP;Lo;0;L;;;;;N;;;;; +A0EE;YI SYLLABLE VOT;Lo;0;L;;;;;N;;;;; +A0EF;YI SYLLABLE VOX;Lo;0;L;;;;;N;;;;; +A0F0;YI SYLLABLE VO;Lo;0;L;;;;;N;;;;; +A0F1;YI SYLLABLE VOP;Lo;0;L;;;;;N;;;;; +A0F2;YI SYLLABLE VEX;Lo;0;L;;;;;N;;;;; +A0F3;YI SYLLABLE VEP;Lo;0;L;;;;;N;;;;; +A0F4;YI SYLLABLE VUT;Lo;0;L;;;;;N;;;;; +A0F5;YI SYLLABLE VUX;Lo;0;L;;;;;N;;;;; +A0F6;YI SYLLABLE VU;Lo;0;L;;;;;N;;;;; +A0F7;YI SYLLABLE VUP;Lo;0;L;;;;;N;;;;; +A0F8;YI SYLLABLE VURX;Lo;0;L;;;;;N;;;;; +A0F9;YI SYLLABLE VUR;Lo;0;L;;;;;N;;;;; +A0FA;YI SYLLABLE VYT;Lo;0;L;;;;;N;;;;; +A0FB;YI SYLLABLE VYX;Lo;0;L;;;;;N;;;;; +A0FC;YI SYLLABLE VY;Lo;0;L;;;;;N;;;;; +A0FD;YI SYLLABLE VYP;Lo;0;L;;;;;N;;;;; +A0FE;YI SYLLABLE VYRX;Lo;0;L;;;;;N;;;;; +A0FF;YI SYLLABLE VYR;Lo;0;L;;;;;N;;;;; +A100;YI SYLLABLE DIT;Lo;0;L;;;;;N;;;;; +A101;YI SYLLABLE DIX;Lo;0;L;;;;;N;;;;; +A102;YI SYLLABLE DI;Lo;0;L;;;;;N;;;;; +A103;YI SYLLABLE DIP;Lo;0;L;;;;;N;;;;; +A104;YI SYLLABLE DIEX;Lo;0;L;;;;;N;;;;; +A105;YI SYLLABLE DIE;Lo;0;L;;;;;N;;;;; +A106;YI SYLLABLE DIEP;Lo;0;L;;;;;N;;;;; +A107;YI SYLLABLE DAT;Lo;0;L;;;;;N;;;;; +A108;YI SYLLABLE DAX;Lo;0;L;;;;;N;;;;; +A109;YI SYLLABLE DA;Lo;0;L;;;;;N;;;;; +A10A;YI SYLLABLE DAP;Lo;0;L;;;;;N;;;;; +A10B;YI SYLLABLE DUOX;Lo;0;L;;;;;N;;;;; +A10C;YI SYLLABLE DUO;Lo;0;L;;;;;N;;;;; +A10D;YI SYLLABLE DOT;Lo;0;L;;;;;N;;;;; +A10E;YI SYLLABLE DOX;Lo;0;L;;;;;N;;;;; +A10F;YI SYLLABLE DO;Lo;0;L;;;;;N;;;;; +A110;YI SYLLABLE DOP;Lo;0;L;;;;;N;;;;; +A111;YI SYLLABLE DEX;Lo;0;L;;;;;N;;;;; +A112;YI SYLLABLE DE;Lo;0;L;;;;;N;;;;; +A113;YI SYLLABLE DEP;Lo;0;L;;;;;N;;;;; +A114;YI SYLLABLE DUT;Lo;0;L;;;;;N;;;;; +A115;YI SYLLABLE DUX;Lo;0;L;;;;;N;;;;; +A116;YI SYLLABLE DU;Lo;0;L;;;;;N;;;;; +A117;YI SYLLABLE DUP;Lo;0;L;;;;;N;;;;; +A118;YI SYLLABLE DURX;Lo;0;L;;;;;N;;;;; +A119;YI SYLLABLE DUR;Lo;0;L;;;;;N;;;;; +A11A;YI SYLLABLE TIT;Lo;0;L;;;;;N;;;;; +A11B;YI SYLLABLE TIX;Lo;0;L;;;;;N;;;;; +A11C;YI SYLLABLE TI;Lo;0;L;;;;;N;;;;; +A11D;YI SYLLABLE TIP;Lo;0;L;;;;;N;;;;; +A11E;YI SYLLABLE TIEX;Lo;0;L;;;;;N;;;;; +A11F;YI SYLLABLE TIE;Lo;0;L;;;;;N;;;;; +A120;YI SYLLABLE TIEP;Lo;0;L;;;;;N;;;;; +A121;YI SYLLABLE TAT;Lo;0;L;;;;;N;;;;; +A122;YI SYLLABLE TAX;Lo;0;L;;;;;N;;;;; +A123;YI SYLLABLE TA;Lo;0;L;;;;;N;;;;; +A124;YI SYLLABLE TAP;Lo;0;L;;;;;N;;;;; +A125;YI SYLLABLE TUOT;Lo;0;L;;;;;N;;;;; +A126;YI SYLLABLE TUOX;Lo;0;L;;;;;N;;;;; +A127;YI SYLLABLE TUO;Lo;0;L;;;;;N;;;;; +A128;YI SYLLABLE TUOP;Lo;0;L;;;;;N;;;;; +A129;YI SYLLABLE TOT;Lo;0;L;;;;;N;;;;; +A12A;YI SYLLABLE TOX;Lo;0;L;;;;;N;;;;; +A12B;YI SYLLABLE TO;Lo;0;L;;;;;N;;;;; +A12C;YI SYLLABLE TOP;Lo;0;L;;;;;N;;;;; +A12D;YI SYLLABLE TEX;Lo;0;L;;;;;N;;;;; +A12E;YI SYLLABLE TE;Lo;0;L;;;;;N;;;;; +A12F;YI SYLLABLE TEP;Lo;0;L;;;;;N;;;;; +A130;YI SYLLABLE TUT;Lo;0;L;;;;;N;;;;; +A131;YI SYLLABLE TUX;Lo;0;L;;;;;N;;;;; +A132;YI SYLLABLE TU;Lo;0;L;;;;;N;;;;; +A133;YI SYLLABLE TUP;Lo;0;L;;;;;N;;;;; +A134;YI SYLLABLE TURX;Lo;0;L;;;;;N;;;;; +A135;YI SYLLABLE TUR;Lo;0;L;;;;;N;;;;; +A136;YI SYLLABLE DDIT;Lo;0;L;;;;;N;;;;; +A137;YI SYLLABLE DDIX;Lo;0;L;;;;;N;;;;; +A138;YI SYLLABLE DDI;Lo;0;L;;;;;N;;;;; +A139;YI SYLLABLE DDIP;Lo;0;L;;;;;N;;;;; +A13A;YI SYLLABLE DDIEX;Lo;0;L;;;;;N;;;;; +A13B;YI SYLLABLE DDIE;Lo;0;L;;;;;N;;;;; +A13C;YI SYLLABLE DDIEP;Lo;0;L;;;;;N;;;;; +A13D;YI SYLLABLE DDAT;Lo;0;L;;;;;N;;;;; +A13E;YI SYLLABLE DDAX;Lo;0;L;;;;;N;;;;; +A13F;YI SYLLABLE DDA;Lo;0;L;;;;;N;;;;; +A140;YI SYLLABLE DDAP;Lo;0;L;;;;;N;;;;; +A141;YI SYLLABLE DDUOX;Lo;0;L;;;;;N;;;;; +A142;YI SYLLABLE DDUO;Lo;0;L;;;;;N;;;;; +A143;YI SYLLABLE DDUOP;Lo;0;L;;;;;N;;;;; +A144;YI SYLLABLE DDOT;Lo;0;L;;;;;N;;;;; +A145;YI SYLLABLE DDOX;Lo;0;L;;;;;N;;;;; +A146;YI SYLLABLE DDO;Lo;0;L;;;;;N;;;;; +A147;YI SYLLABLE DDOP;Lo;0;L;;;;;N;;;;; +A148;YI SYLLABLE DDEX;Lo;0;L;;;;;N;;;;; +A149;YI SYLLABLE DDE;Lo;0;L;;;;;N;;;;; +A14A;YI SYLLABLE DDEP;Lo;0;L;;;;;N;;;;; +A14B;YI SYLLABLE DDUT;Lo;0;L;;;;;N;;;;; +A14C;YI SYLLABLE DDUX;Lo;0;L;;;;;N;;;;; +A14D;YI SYLLABLE DDU;Lo;0;L;;;;;N;;;;; +A14E;YI SYLLABLE DDUP;Lo;0;L;;;;;N;;;;; +A14F;YI SYLLABLE DDURX;Lo;0;L;;;;;N;;;;; +A150;YI SYLLABLE DDUR;Lo;0;L;;;;;N;;;;; +A151;YI SYLLABLE NDIT;Lo;0;L;;;;;N;;;;; +A152;YI SYLLABLE NDIX;Lo;0;L;;;;;N;;;;; +A153;YI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; +A154;YI SYLLABLE NDIP;Lo;0;L;;;;;N;;;;; +A155;YI SYLLABLE NDIEX;Lo;0;L;;;;;N;;;;; +A156;YI SYLLABLE NDIE;Lo;0;L;;;;;N;;;;; +A157;YI SYLLABLE NDAT;Lo;0;L;;;;;N;;;;; +A158;YI SYLLABLE NDAX;Lo;0;L;;;;;N;;;;; +A159;YI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; +A15A;YI SYLLABLE NDAP;Lo;0;L;;;;;N;;;;; +A15B;YI SYLLABLE NDOT;Lo;0;L;;;;;N;;;;; +A15C;YI SYLLABLE NDOX;Lo;0;L;;;;;N;;;;; +A15D;YI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; +A15E;YI SYLLABLE NDOP;Lo;0;L;;;;;N;;;;; +A15F;YI SYLLABLE NDEX;Lo;0;L;;;;;N;;;;; +A160;YI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; +A161;YI SYLLABLE NDEP;Lo;0;L;;;;;N;;;;; +A162;YI SYLLABLE NDUT;Lo;0;L;;;;;N;;;;; +A163;YI SYLLABLE NDUX;Lo;0;L;;;;;N;;;;; +A164;YI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; +A165;YI SYLLABLE NDUP;Lo;0;L;;;;;N;;;;; +A166;YI SYLLABLE NDURX;Lo;0;L;;;;;N;;;;; +A167;YI SYLLABLE NDUR;Lo;0;L;;;;;N;;;;; +A168;YI SYLLABLE HNIT;Lo;0;L;;;;;N;;;;; +A169;YI SYLLABLE HNIX;Lo;0;L;;;;;N;;;;; +A16A;YI SYLLABLE HNI;Lo;0;L;;;;;N;;;;; +A16B;YI SYLLABLE HNIP;Lo;0;L;;;;;N;;;;; +A16C;YI SYLLABLE HNIET;Lo;0;L;;;;;N;;;;; +A16D;YI SYLLABLE HNIEX;Lo;0;L;;;;;N;;;;; +A16E;YI SYLLABLE HNIE;Lo;0;L;;;;;N;;;;; +A16F;YI SYLLABLE HNIEP;Lo;0;L;;;;;N;;;;; +A170;YI SYLLABLE HNAT;Lo;0;L;;;;;N;;;;; +A171;YI SYLLABLE HNAX;Lo;0;L;;;;;N;;;;; +A172;YI SYLLABLE HNA;Lo;0;L;;;;;N;;;;; +A173;YI SYLLABLE HNAP;Lo;0;L;;;;;N;;;;; +A174;YI SYLLABLE HNUOX;Lo;0;L;;;;;N;;;;; +A175;YI SYLLABLE HNUO;Lo;0;L;;;;;N;;;;; +A176;YI SYLLABLE HNOT;Lo;0;L;;;;;N;;;;; +A177;YI SYLLABLE HNOX;Lo;0;L;;;;;N;;;;; +A178;YI SYLLABLE HNOP;Lo;0;L;;;;;N;;;;; +A179;YI SYLLABLE HNEX;Lo;0;L;;;;;N;;;;; +A17A;YI SYLLABLE HNE;Lo;0;L;;;;;N;;;;; +A17B;YI SYLLABLE HNEP;Lo;0;L;;;;;N;;;;; +A17C;YI SYLLABLE HNUT;Lo;0;L;;;;;N;;;;; +A17D;YI SYLLABLE NIT;Lo;0;L;;;;;N;;;;; +A17E;YI SYLLABLE NIX;Lo;0;L;;;;;N;;;;; +A17F;YI SYLLABLE NI;Lo;0;L;;;;;N;;;;; +A180;YI SYLLABLE NIP;Lo;0;L;;;;;N;;;;; +A181;YI SYLLABLE NIEX;Lo;0;L;;;;;N;;;;; +A182;YI SYLLABLE NIE;Lo;0;L;;;;;N;;;;; +A183;YI SYLLABLE NIEP;Lo;0;L;;;;;N;;;;; +A184;YI SYLLABLE NAX;Lo;0;L;;;;;N;;;;; +A185;YI SYLLABLE NA;Lo;0;L;;;;;N;;;;; +A186;YI SYLLABLE NAP;Lo;0;L;;;;;N;;;;; +A187;YI SYLLABLE NUOX;Lo;0;L;;;;;N;;;;; +A188;YI SYLLABLE NUO;Lo;0;L;;;;;N;;;;; +A189;YI SYLLABLE NUOP;Lo;0;L;;;;;N;;;;; +A18A;YI SYLLABLE NOT;Lo;0;L;;;;;N;;;;; +A18B;YI SYLLABLE NOX;Lo;0;L;;;;;N;;;;; +A18C;YI SYLLABLE NO;Lo;0;L;;;;;N;;;;; +A18D;YI SYLLABLE NOP;Lo;0;L;;;;;N;;;;; +A18E;YI SYLLABLE NEX;Lo;0;L;;;;;N;;;;; +A18F;YI SYLLABLE NE;Lo;0;L;;;;;N;;;;; +A190;YI SYLLABLE NEP;Lo;0;L;;;;;N;;;;; +A191;YI SYLLABLE NUT;Lo;0;L;;;;;N;;;;; +A192;YI SYLLABLE NUX;Lo;0;L;;;;;N;;;;; +A193;YI SYLLABLE NU;Lo;0;L;;;;;N;;;;; +A194;YI SYLLABLE NUP;Lo;0;L;;;;;N;;;;; +A195;YI SYLLABLE NURX;Lo;0;L;;;;;N;;;;; +A196;YI SYLLABLE NUR;Lo;0;L;;;;;N;;;;; +A197;YI SYLLABLE HLIT;Lo;0;L;;;;;N;;;;; +A198;YI SYLLABLE HLIX;Lo;0;L;;;;;N;;;;; +A199;YI SYLLABLE HLI;Lo;0;L;;;;;N;;;;; +A19A;YI SYLLABLE HLIP;Lo;0;L;;;;;N;;;;; +A19B;YI SYLLABLE HLIEX;Lo;0;L;;;;;N;;;;; +A19C;YI SYLLABLE HLIE;Lo;0;L;;;;;N;;;;; +A19D;YI SYLLABLE HLIEP;Lo;0;L;;;;;N;;;;; +A19E;YI SYLLABLE HLAT;Lo;0;L;;;;;N;;;;; +A19F;YI SYLLABLE HLAX;Lo;0;L;;;;;N;;;;; +A1A0;YI SYLLABLE HLA;Lo;0;L;;;;;N;;;;; +A1A1;YI SYLLABLE HLAP;Lo;0;L;;;;;N;;;;; +A1A2;YI SYLLABLE HLUOX;Lo;0;L;;;;;N;;;;; +A1A3;YI SYLLABLE HLUO;Lo;0;L;;;;;N;;;;; +A1A4;YI SYLLABLE HLUOP;Lo;0;L;;;;;N;;;;; +A1A5;YI SYLLABLE HLOX;Lo;0;L;;;;;N;;;;; +A1A6;YI SYLLABLE HLO;Lo;0;L;;;;;N;;;;; +A1A7;YI SYLLABLE HLOP;Lo;0;L;;;;;N;;;;; +A1A8;YI SYLLABLE HLEX;Lo;0;L;;;;;N;;;;; +A1A9;YI SYLLABLE HLE;Lo;0;L;;;;;N;;;;; +A1AA;YI SYLLABLE HLEP;Lo;0;L;;;;;N;;;;; +A1AB;YI SYLLABLE HLUT;Lo;0;L;;;;;N;;;;; +A1AC;YI SYLLABLE HLUX;Lo;0;L;;;;;N;;;;; +A1AD;YI SYLLABLE HLU;Lo;0;L;;;;;N;;;;; +A1AE;YI SYLLABLE HLUP;Lo;0;L;;;;;N;;;;; +A1AF;YI SYLLABLE HLURX;Lo;0;L;;;;;N;;;;; +A1B0;YI SYLLABLE HLUR;Lo;0;L;;;;;N;;;;; +A1B1;YI SYLLABLE HLYT;Lo;0;L;;;;;N;;;;; +A1B2;YI SYLLABLE HLYX;Lo;0;L;;;;;N;;;;; +A1B3;YI SYLLABLE HLY;Lo;0;L;;;;;N;;;;; +A1B4;YI SYLLABLE HLYP;Lo;0;L;;;;;N;;;;; +A1B5;YI SYLLABLE HLYRX;Lo;0;L;;;;;N;;;;; +A1B6;YI SYLLABLE HLYR;Lo;0;L;;;;;N;;;;; +A1B7;YI SYLLABLE LIT;Lo;0;L;;;;;N;;;;; +A1B8;YI SYLLABLE LIX;Lo;0;L;;;;;N;;;;; +A1B9;YI SYLLABLE LI;Lo;0;L;;;;;N;;;;; +A1BA;YI SYLLABLE LIP;Lo;0;L;;;;;N;;;;; +A1BB;YI SYLLABLE LIET;Lo;0;L;;;;;N;;;;; +A1BC;YI SYLLABLE LIEX;Lo;0;L;;;;;N;;;;; +A1BD;YI SYLLABLE LIE;Lo;0;L;;;;;N;;;;; +A1BE;YI SYLLABLE LIEP;Lo;0;L;;;;;N;;;;; +A1BF;YI SYLLABLE LAT;Lo;0;L;;;;;N;;;;; +A1C0;YI SYLLABLE LAX;Lo;0;L;;;;;N;;;;; +A1C1;YI SYLLABLE LA;Lo;0;L;;;;;N;;;;; +A1C2;YI SYLLABLE LAP;Lo;0;L;;;;;N;;;;; +A1C3;YI SYLLABLE LUOT;Lo;0;L;;;;;N;;;;; +A1C4;YI SYLLABLE LUOX;Lo;0;L;;;;;N;;;;; +A1C5;YI SYLLABLE LUO;Lo;0;L;;;;;N;;;;; +A1C6;YI SYLLABLE LUOP;Lo;0;L;;;;;N;;;;; +A1C7;YI SYLLABLE LOT;Lo;0;L;;;;;N;;;;; +A1C8;YI SYLLABLE LOX;Lo;0;L;;;;;N;;;;; +A1C9;YI SYLLABLE LO;Lo;0;L;;;;;N;;;;; +A1CA;YI SYLLABLE LOP;Lo;0;L;;;;;N;;;;; +A1CB;YI SYLLABLE LEX;Lo;0;L;;;;;N;;;;; +A1CC;YI SYLLABLE LE;Lo;0;L;;;;;N;;;;; +A1CD;YI SYLLABLE LEP;Lo;0;L;;;;;N;;;;; +A1CE;YI SYLLABLE LUT;Lo;0;L;;;;;N;;;;; +A1CF;YI SYLLABLE LUX;Lo;0;L;;;;;N;;;;; +A1D0;YI SYLLABLE LU;Lo;0;L;;;;;N;;;;; +A1D1;YI SYLLABLE LUP;Lo;0;L;;;;;N;;;;; +A1D2;YI SYLLABLE LURX;Lo;0;L;;;;;N;;;;; +A1D3;YI SYLLABLE LUR;Lo;0;L;;;;;N;;;;; +A1D4;YI SYLLABLE LYT;Lo;0;L;;;;;N;;;;; +A1D5;YI SYLLABLE LYX;Lo;0;L;;;;;N;;;;; +A1D6;YI SYLLABLE LY;Lo;0;L;;;;;N;;;;; +A1D7;YI SYLLABLE LYP;Lo;0;L;;;;;N;;;;; +A1D8;YI SYLLABLE LYRX;Lo;0;L;;;;;N;;;;; +A1D9;YI SYLLABLE LYR;Lo;0;L;;;;;N;;;;; +A1DA;YI SYLLABLE GIT;Lo;0;L;;;;;N;;;;; +A1DB;YI SYLLABLE GIX;Lo;0;L;;;;;N;;;;; +A1DC;YI SYLLABLE GI;Lo;0;L;;;;;N;;;;; +A1DD;YI SYLLABLE GIP;Lo;0;L;;;;;N;;;;; +A1DE;YI SYLLABLE GIET;Lo;0;L;;;;;N;;;;; +A1DF;YI SYLLABLE GIEX;Lo;0;L;;;;;N;;;;; +A1E0;YI SYLLABLE GIE;Lo;0;L;;;;;N;;;;; +A1E1;YI SYLLABLE GIEP;Lo;0;L;;;;;N;;;;; +A1E2;YI SYLLABLE GAT;Lo;0;L;;;;;N;;;;; +A1E3;YI SYLLABLE GAX;Lo;0;L;;;;;N;;;;; +A1E4;YI SYLLABLE GA;Lo;0;L;;;;;N;;;;; +A1E5;YI SYLLABLE GAP;Lo;0;L;;;;;N;;;;; +A1E6;YI SYLLABLE GUOT;Lo;0;L;;;;;N;;;;; +A1E7;YI SYLLABLE GUOX;Lo;0;L;;;;;N;;;;; +A1E8;YI SYLLABLE GUO;Lo;0;L;;;;;N;;;;; +A1E9;YI SYLLABLE GUOP;Lo;0;L;;;;;N;;;;; +A1EA;YI SYLLABLE GOT;Lo;0;L;;;;;N;;;;; +A1EB;YI SYLLABLE GOX;Lo;0;L;;;;;N;;;;; +A1EC;YI SYLLABLE GO;Lo;0;L;;;;;N;;;;; +A1ED;YI SYLLABLE GOP;Lo;0;L;;;;;N;;;;; +A1EE;YI SYLLABLE GET;Lo;0;L;;;;;N;;;;; +A1EF;YI SYLLABLE GEX;Lo;0;L;;;;;N;;;;; +A1F0;YI SYLLABLE GE;Lo;0;L;;;;;N;;;;; +A1F1;YI SYLLABLE GEP;Lo;0;L;;;;;N;;;;; +A1F2;YI SYLLABLE GUT;Lo;0;L;;;;;N;;;;; +A1F3;YI SYLLABLE GUX;Lo;0;L;;;;;N;;;;; +A1F4;YI SYLLABLE GU;Lo;0;L;;;;;N;;;;; +A1F5;YI SYLLABLE GUP;Lo;0;L;;;;;N;;;;; +A1F6;YI SYLLABLE GURX;Lo;0;L;;;;;N;;;;; +A1F7;YI SYLLABLE GUR;Lo;0;L;;;;;N;;;;; +A1F8;YI SYLLABLE KIT;Lo;0;L;;;;;N;;;;; +A1F9;YI SYLLABLE KIX;Lo;0;L;;;;;N;;;;; +A1FA;YI SYLLABLE KI;Lo;0;L;;;;;N;;;;; +A1FB;YI SYLLABLE KIP;Lo;0;L;;;;;N;;;;; +A1FC;YI SYLLABLE KIEX;Lo;0;L;;;;;N;;;;; +A1FD;YI SYLLABLE KIE;Lo;0;L;;;;;N;;;;; +A1FE;YI SYLLABLE KIEP;Lo;0;L;;;;;N;;;;; +A1FF;YI SYLLABLE KAT;Lo;0;L;;;;;N;;;;; +A200;YI SYLLABLE KAX;Lo;0;L;;;;;N;;;;; +A201;YI SYLLABLE KA;Lo;0;L;;;;;N;;;;; +A202;YI SYLLABLE KAP;Lo;0;L;;;;;N;;;;; +A203;YI SYLLABLE KUOX;Lo;0;L;;;;;N;;;;; +A204;YI SYLLABLE KUO;Lo;0;L;;;;;N;;;;; +A205;YI SYLLABLE KUOP;Lo;0;L;;;;;N;;;;; +A206;YI SYLLABLE KOT;Lo;0;L;;;;;N;;;;; +A207;YI SYLLABLE KOX;Lo;0;L;;;;;N;;;;; +A208;YI SYLLABLE KO;Lo;0;L;;;;;N;;;;; +A209;YI SYLLABLE KOP;Lo;0;L;;;;;N;;;;; +A20A;YI SYLLABLE KET;Lo;0;L;;;;;N;;;;; +A20B;YI SYLLABLE KEX;Lo;0;L;;;;;N;;;;; +A20C;YI SYLLABLE KE;Lo;0;L;;;;;N;;;;; +A20D;YI SYLLABLE KEP;Lo;0;L;;;;;N;;;;; +A20E;YI SYLLABLE KUT;Lo;0;L;;;;;N;;;;; +A20F;YI SYLLABLE KUX;Lo;0;L;;;;;N;;;;; +A210;YI SYLLABLE KU;Lo;0;L;;;;;N;;;;; +A211;YI SYLLABLE KUP;Lo;0;L;;;;;N;;;;; +A212;YI SYLLABLE KURX;Lo;0;L;;;;;N;;;;; +A213;YI SYLLABLE KUR;Lo;0;L;;;;;N;;;;; +A214;YI SYLLABLE GGIT;Lo;0;L;;;;;N;;;;; +A215;YI SYLLABLE GGIX;Lo;0;L;;;;;N;;;;; +A216;YI SYLLABLE GGI;Lo;0;L;;;;;N;;;;; +A217;YI SYLLABLE GGIEX;Lo;0;L;;;;;N;;;;; +A218;YI SYLLABLE GGIE;Lo;0;L;;;;;N;;;;; +A219;YI SYLLABLE GGIEP;Lo;0;L;;;;;N;;;;; +A21A;YI SYLLABLE GGAT;Lo;0;L;;;;;N;;;;; +A21B;YI SYLLABLE GGAX;Lo;0;L;;;;;N;;;;; +A21C;YI SYLLABLE GGA;Lo;0;L;;;;;N;;;;; +A21D;YI SYLLABLE GGAP;Lo;0;L;;;;;N;;;;; +A21E;YI SYLLABLE GGUOT;Lo;0;L;;;;;N;;;;; +A21F;YI SYLLABLE GGUOX;Lo;0;L;;;;;N;;;;; +A220;YI SYLLABLE GGUO;Lo;0;L;;;;;N;;;;; +A221;YI SYLLABLE GGUOP;Lo;0;L;;;;;N;;;;; +A222;YI SYLLABLE GGOT;Lo;0;L;;;;;N;;;;; +A223;YI SYLLABLE GGOX;Lo;0;L;;;;;N;;;;; +A224;YI SYLLABLE GGO;Lo;0;L;;;;;N;;;;; +A225;YI SYLLABLE GGOP;Lo;0;L;;;;;N;;;;; +A226;YI SYLLABLE GGET;Lo;0;L;;;;;N;;;;; +A227;YI SYLLABLE GGEX;Lo;0;L;;;;;N;;;;; +A228;YI SYLLABLE GGE;Lo;0;L;;;;;N;;;;; +A229;YI SYLLABLE GGEP;Lo;0;L;;;;;N;;;;; +A22A;YI SYLLABLE GGUT;Lo;0;L;;;;;N;;;;; +A22B;YI SYLLABLE GGUX;Lo;0;L;;;;;N;;;;; +A22C;YI SYLLABLE GGU;Lo;0;L;;;;;N;;;;; +A22D;YI SYLLABLE GGUP;Lo;0;L;;;;;N;;;;; +A22E;YI SYLLABLE GGURX;Lo;0;L;;;;;N;;;;; +A22F;YI SYLLABLE GGUR;Lo;0;L;;;;;N;;;;; +A230;YI SYLLABLE MGIEX;Lo;0;L;;;;;N;;;;; +A231;YI SYLLABLE MGIE;Lo;0;L;;;;;N;;;;; +A232;YI SYLLABLE MGAT;Lo;0;L;;;;;N;;;;; +A233;YI SYLLABLE MGAX;Lo;0;L;;;;;N;;;;; +A234;YI SYLLABLE MGA;Lo;0;L;;;;;N;;;;; +A235;YI SYLLABLE MGAP;Lo;0;L;;;;;N;;;;; +A236;YI SYLLABLE MGUOX;Lo;0;L;;;;;N;;;;; +A237;YI SYLLABLE MGUO;Lo;0;L;;;;;N;;;;; +A238;YI SYLLABLE MGUOP;Lo;0;L;;;;;N;;;;; +A239;YI SYLLABLE MGOT;Lo;0;L;;;;;N;;;;; +A23A;YI SYLLABLE MGOX;Lo;0;L;;;;;N;;;;; +A23B;YI SYLLABLE MGO;Lo;0;L;;;;;N;;;;; +A23C;YI SYLLABLE MGOP;Lo;0;L;;;;;N;;;;; +A23D;YI SYLLABLE MGEX;Lo;0;L;;;;;N;;;;; +A23E;YI SYLLABLE MGE;Lo;0;L;;;;;N;;;;; +A23F;YI SYLLABLE MGEP;Lo;0;L;;;;;N;;;;; +A240;YI SYLLABLE MGUT;Lo;0;L;;;;;N;;;;; +A241;YI SYLLABLE MGUX;Lo;0;L;;;;;N;;;;; +A242;YI SYLLABLE MGU;Lo;0;L;;;;;N;;;;; +A243;YI SYLLABLE MGUP;Lo;0;L;;;;;N;;;;; +A244;YI SYLLABLE MGURX;Lo;0;L;;;;;N;;;;; +A245;YI SYLLABLE MGUR;Lo;0;L;;;;;N;;;;; +A246;YI SYLLABLE HXIT;Lo;0;L;;;;;N;;;;; +A247;YI SYLLABLE HXIX;Lo;0;L;;;;;N;;;;; +A248;YI SYLLABLE HXI;Lo;0;L;;;;;N;;;;; +A249;YI SYLLABLE HXIP;Lo;0;L;;;;;N;;;;; +A24A;YI SYLLABLE HXIET;Lo;0;L;;;;;N;;;;; +A24B;YI SYLLABLE HXIEX;Lo;0;L;;;;;N;;;;; +A24C;YI SYLLABLE HXIE;Lo;0;L;;;;;N;;;;; +A24D;YI SYLLABLE HXIEP;Lo;0;L;;;;;N;;;;; +A24E;YI SYLLABLE HXAT;Lo;0;L;;;;;N;;;;; +A24F;YI SYLLABLE HXAX;Lo;0;L;;;;;N;;;;; +A250;YI SYLLABLE HXA;Lo;0;L;;;;;N;;;;; +A251;YI SYLLABLE HXAP;Lo;0;L;;;;;N;;;;; +A252;YI SYLLABLE HXUOT;Lo;0;L;;;;;N;;;;; +A253;YI SYLLABLE HXUOX;Lo;0;L;;;;;N;;;;; +A254;YI SYLLABLE HXUO;Lo;0;L;;;;;N;;;;; +A255;YI SYLLABLE HXUOP;Lo;0;L;;;;;N;;;;; +A256;YI SYLLABLE HXOT;Lo;0;L;;;;;N;;;;; +A257;YI SYLLABLE HXOX;Lo;0;L;;;;;N;;;;; +A258;YI SYLLABLE HXO;Lo;0;L;;;;;N;;;;; +A259;YI SYLLABLE HXOP;Lo;0;L;;;;;N;;;;; +A25A;YI SYLLABLE HXEX;Lo;0;L;;;;;N;;;;; +A25B;YI SYLLABLE HXE;Lo;0;L;;;;;N;;;;; +A25C;YI SYLLABLE HXEP;Lo;0;L;;;;;N;;;;; +A25D;YI SYLLABLE NGIEX;Lo;0;L;;;;;N;;;;; +A25E;YI SYLLABLE NGIE;Lo;0;L;;;;;N;;;;; +A25F;YI SYLLABLE NGIEP;Lo;0;L;;;;;N;;;;; +A260;YI SYLLABLE NGAT;Lo;0;L;;;;;N;;;;; +A261;YI SYLLABLE NGAX;Lo;0;L;;;;;N;;;;; +A262;YI SYLLABLE NGA;Lo;0;L;;;;;N;;;;; +A263;YI SYLLABLE NGAP;Lo;0;L;;;;;N;;;;; +A264;YI SYLLABLE NGUOT;Lo;0;L;;;;;N;;;;; +A265;YI SYLLABLE NGUOX;Lo;0;L;;;;;N;;;;; +A266;YI SYLLABLE NGUO;Lo;0;L;;;;;N;;;;; +A267;YI SYLLABLE NGOT;Lo;0;L;;;;;N;;;;; +A268;YI SYLLABLE NGOX;Lo;0;L;;;;;N;;;;; +A269;YI SYLLABLE NGO;Lo;0;L;;;;;N;;;;; +A26A;YI SYLLABLE NGOP;Lo;0;L;;;;;N;;;;; +A26B;YI SYLLABLE NGEX;Lo;0;L;;;;;N;;;;; +A26C;YI SYLLABLE NGE;Lo;0;L;;;;;N;;;;; +A26D;YI SYLLABLE NGEP;Lo;0;L;;;;;N;;;;; +A26E;YI SYLLABLE HIT;Lo;0;L;;;;;N;;;;; +A26F;YI SYLLABLE HIEX;Lo;0;L;;;;;N;;;;; +A270;YI SYLLABLE HIE;Lo;0;L;;;;;N;;;;; +A271;YI SYLLABLE HAT;Lo;0;L;;;;;N;;;;; +A272;YI SYLLABLE HAX;Lo;0;L;;;;;N;;;;; +A273;YI SYLLABLE HA;Lo;0;L;;;;;N;;;;; +A274;YI SYLLABLE HAP;Lo;0;L;;;;;N;;;;; +A275;YI SYLLABLE HUOT;Lo;0;L;;;;;N;;;;; +A276;YI SYLLABLE HUOX;Lo;0;L;;;;;N;;;;; +A277;YI SYLLABLE HUO;Lo;0;L;;;;;N;;;;; +A278;YI SYLLABLE HUOP;Lo;0;L;;;;;N;;;;; +A279;YI SYLLABLE HOT;Lo;0;L;;;;;N;;;;; +A27A;YI SYLLABLE HOX;Lo;0;L;;;;;N;;;;; +A27B;YI SYLLABLE HO;Lo;0;L;;;;;N;;;;; +A27C;YI SYLLABLE HOP;Lo;0;L;;;;;N;;;;; +A27D;YI SYLLABLE HEX;Lo;0;L;;;;;N;;;;; +A27E;YI SYLLABLE HE;Lo;0;L;;;;;N;;;;; +A27F;YI SYLLABLE HEP;Lo;0;L;;;;;N;;;;; +A280;YI SYLLABLE WAT;Lo;0;L;;;;;N;;;;; +A281;YI SYLLABLE WAX;Lo;0;L;;;;;N;;;;; +A282;YI SYLLABLE WA;Lo;0;L;;;;;N;;;;; +A283;YI SYLLABLE WAP;Lo;0;L;;;;;N;;;;; +A284;YI SYLLABLE WUOX;Lo;0;L;;;;;N;;;;; +A285;YI SYLLABLE WUO;Lo;0;L;;;;;N;;;;; +A286;YI SYLLABLE WUOP;Lo;0;L;;;;;N;;;;; +A287;YI SYLLABLE WOX;Lo;0;L;;;;;N;;;;; +A288;YI SYLLABLE WO;Lo;0;L;;;;;N;;;;; +A289;YI SYLLABLE WOP;Lo;0;L;;;;;N;;;;; +A28A;YI SYLLABLE WEX;Lo;0;L;;;;;N;;;;; +A28B;YI SYLLABLE WE;Lo;0;L;;;;;N;;;;; +A28C;YI SYLLABLE WEP;Lo;0;L;;;;;N;;;;; +A28D;YI SYLLABLE ZIT;Lo;0;L;;;;;N;;;;; +A28E;YI SYLLABLE ZIX;Lo;0;L;;;;;N;;;;; +A28F;YI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; +A290;YI SYLLABLE ZIP;Lo;0;L;;;;;N;;;;; +A291;YI SYLLABLE ZIEX;Lo;0;L;;;;;N;;;;; +A292;YI SYLLABLE ZIE;Lo;0;L;;;;;N;;;;; +A293;YI SYLLABLE ZIEP;Lo;0;L;;;;;N;;;;; +A294;YI SYLLABLE ZAT;Lo;0;L;;;;;N;;;;; +A295;YI SYLLABLE ZAX;Lo;0;L;;;;;N;;;;; +A296;YI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; +A297;YI SYLLABLE ZAP;Lo;0;L;;;;;N;;;;; +A298;YI SYLLABLE ZUOX;Lo;0;L;;;;;N;;;;; +A299;YI SYLLABLE ZUO;Lo;0;L;;;;;N;;;;; +A29A;YI SYLLABLE ZUOP;Lo;0;L;;;;;N;;;;; +A29B;YI SYLLABLE ZOT;Lo;0;L;;;;;N;;;;; +A29C;YI SYLLABLE ZOX;Lo;0;L;;;;;N;;;;; +A29D;YI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; +A29E;YI SYLLABLE ZOP;Lo;0;L;;;;;N;;;;; +A29F;YI SYLLABLE ZEX;Lo;0;L;;;;;N;;;;; +A2A0;YI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; +A2A1;YI SYLLABLE ZEP;Lo;0;L;;;;;N;;;;; +A2A2;YI SYLLABLE ZUT;Lo;0;L;;;;;N;;;;; +A2A3;YI SYLLABLE ZUX;Lo;0;L;;;;;N;;;;; +A2A4;YI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; +A2A5;YI SYLLABLE ZUP;Lo;0;L;;;;;N;;;;; +A2A6;YI SYLLABLE ZURX;Lo;0;L;;;;;N;;;;; +A2A7;YI SYLLABLE ZUR;Lo;0;L;;;;;N;;;;; +A2A8;YI SYLLABLE ZYT;Lo;0;L;;;;;N;;;;; +A2A9;YI SYLLABLE ZYX;Lo;0;L;;;;;N;;;;; +A2AA;YI SYLLABLE ZY;Lo;0;L;;;;;N;;;;; +A2AB;YI SYLLABLE ZYP;Lo;0;L;;;;;N;;;;; +A2AC;YI SYLLABLE ZYRX;Lo;0;L;;;;;N;;;;; +A2AD;YI SYLLABLE ZYR;Lo;0;L;;;;;N;;;;; +A2AE;YI SYLLABLE CIT;Lo;0;L;;;;;N;;;;; +A2AF;YI SYLLABLE CIX;Lo;0;L;;;;;N;;;;; +A2B0;YI SYLLABLE CI;Lo;0;L;;;;;N;;;;; +A2B1;YI SYLLABLE CIP;Lo;0;L;;;;;N;;;;; +A2B2;YI SYLLABLE CIET;Lo;0;L;;;;;N;;;;; +A2B3;YI SYLLABLE CIEX;Lo;0;L;;;;;N;;;;; +A2B4;YI SYLLABLE CIE;Lo;0;L;;;;;N;;;;; +A2B5;YI SYLLABLE CIEP;Lo;0;L;;;;;N;;;;; +A2B6;YI SYLLABLE CAT;Lo;0;L;;;;;N;;;;; +A2B7;YI SYLLABLE CAX;Lo;0;L;;;;;N;;;;; +A2B8;YI SYLLABLE CA;Lo;0;L;;;;;N;;;;; +A2B9;YI SYLLABLE CAP;Lo;0;L;;;;;N;;;;; +A2BA;YI SYLLABLE CUOX;Lo;0;L;;;;;N;;;;; +A2BB;YI SYLLABLE CUO;Lo;0;L;;;;;N;;;;; +A2BC;YI SYLLABLE CUOP;Lo;0;L;;;;;N;;;;; +A2BD;YI SYLLABLE COT;Lo;0;L;;;;;N;;;;; +A2BE;YI SYLLABLE COX;Lo;0;L;;;;;N;;;;; +A2BF;YI SYLLABLE CO;Lo;0;L;;;;;N;;;;; +A2C0;YI SYLLABLE COP;Lo;0;L;;;;;N;;;;; +A2C1;YI SYLLABLE CEX;Lo;0;L;;;;;N;;;;; +A2C2;YI SYLLABLE CE;Lo;0;L;;;;;N;;;;; +A2C3;YI SYLLABLE CEP;Lo;0;L;;;;;N;;;;; +A2C4;YI SYLLABLE CUT;Lo;0;L;;;;;N;;;;; +A2C5;YI SYLLABLE CUX;Lo;0;L;;;;;N;;;;; +A2C6;YI SYLLABLE CU;Lo;0;L;;;;;N;;;;; +A2C7;YI SYLLABLE CUP;Lo;0;L;;;;;N;;;;; +A2C8;YI SYLLABLE CURX;Lo;0;L;;;;;N;;;;; +A2C9;YI SYLLABLE CUR;Lo;0;L;;;;;N;;;;; +A2CA;YI SYLLABLE CYT;Lo;0;L;;;;;N;;;;; +A2CB;YI SYLLABLE CYX;Lo;0;L;;;;;N;;;;; +A2CC;YI SYLLABLE CY;Lo;0;L;;;;;N;;;;; +A2CD;YI SYLLABLE CYP;Lo;0;L;;;;;N;;;;; +A2CE;YI SYLLABLE CYRX;Lo;0;L;;;;;N;;;;; +A2CF;YI SYLLABLE CYR;Lo;0;L;;;;;N;;;;; +A2D0;YI SYLLABLE ZZIT;Lo;0;L;;;;;N;;;;; +A2D1;YI SYLLABLE ZZIX;Lo;0;L;;;;;N;;;;; +A2D2;YI SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; +A2D3;YI SYLLABLE ZZIP;Lo;0;L;;;;;N;;;;; +A2D4;YI SYLLABLE ZZIET;Lo;0;L;;;;;N;;;;; +A2D5;YI SYLLABLE ZZIEX;Lo;0;L;;;;;N;;;;; +A2D6;YI SYLLABLE ZZIE;Lo;0;L;;;;;N;;;;; +A2D7;YI SYLLABLE ZZIEP;Lo;0;L;;;;;N;;;;; +A2D8;YI SYLLABLE ZZAT;Lo;0;L;;;;;N;;;;; +A2D9;YI SYLLABLE ZZAX;Lo;0;L;;;;;N;;;;; +A2DA;YI SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; +A2DB;YI SYLLABLE ZZAP;Lo;0;L;;;;;N;;;;; +A2DC;YI SYLLABLE ZZOX;Lo;0;L;;;;;N;;;;; +A2DD;YI SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; +A2DE;YI SYLLABLE ZZOP;Lo;0;L;;;;;N;;;;; +A2DF;YI SYLLABLE ZZEX;Lo;0;L;;;;;N;;;;; +A2E0;YI SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; +A2E1;YI SYLLABLE ZZEP;Lo;0;L;;;;;N;;;;; +A2E2;YI SYLLABLE ZZUX;Lo;0;L;;;;;N;;;;; +A2E3;YI SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; +A2E4;YI SYLLABLE ZZUP;Lo;0;L;;;;;N;;;;; +A2E5;YI SYLLABLE ZZURX;Lo;0;L;;;;;N;;;;; +A2E6;YI SYLLABLE ZZUR;Lo;0;L;;;;;N;;;;; +A2E7;YI SYLLABLE ZZYT;Lo;0;L;;;;;N;;;;; +A2E8;YI SYLLABLE ZZYX;Lo;0;L;;;;;N;;;;; +A2E9;YI SYLLABLE ZZY;Lo;0;L;;;;;N;;;;; +A2EA;YI SYLLABLE ZZYP;Lo;0;L;;;;;N;;;;; +A2EB;YI SYLLABLE ZZYRX;Lo;0;L;;;;;N;;;;; +A2EC;YI SYLLABLE ZZYR;Lo;0;L;;;;;N;;;;; +A2ED;YI SYLLABLE NZIT;Lo;0;L;;;;;N;;;;; +A2EE;YI SYLLABLE NZIX;Lo;0;L;;;;;N;;;;; +A2EF;YI SYLLABLE NZI;Lo;0;L;;;;;N;;;;; +A2F0;YI SYLLABLE NZIP;Lo;0;L;;;;;N;;;;; +A2F1;YI SYLLABLE NZIEX;Lo;0;L;;;;;N;;;;; +A2F2;YI SYLLABLE NZIE;Lo;0;L;;;;;N;;;;; +A2F3;YI SYLLABLE NZIEP;Lo;0;L;;;;;N;;;;; +A2F4;YI SYLLABLE NZAT;Lo;0;L;;;;;N;;;;; +A2F5;YI SYLLABLE NZAX;Lo;0;L;;;;;N;;;;; +A2F6;YI SYLLABLE NZA;Lo;0;L;;;;;N;;;;; +A2F7;YI SYLLABLE NZAP;Lo;0;L;;;;;N;;;;; +A2F8;YI SYLLABLE NZUOX;Lo;0;L;;;;;N;;;;; +A2F9;YI SYLLABLE NZUO;Lo;0;L;;;;;N;;;;; +A2FA;YI SYLLABLE NZOX;Lo;0;L;;;;;N;;;;; +A2FB;YI SYLLABLE NZOP;Lo;0;L;;;;;N;;;;; +A2FC;YI SYLLABLE NZEX;Lo;0;L;;;;;N;;;;; +A2FD;YI SYLLABLE NZE;Lo;0;L;;;;;N;;;;; +A2FE;YI SYLLABLE NZUX;Lo;0;L;;;;;N;;;;; +A2FF;YI SYLLABLE NZU;Lo;0;L;;;;;N;;;;; +A300;YI SYLLABLE NZUP;Lo;0;L;;;;;N;;;;; +A301;YI SYLLABLE NZURX;Lo;0;L;;;;;N;;;;; +A302;YI SYLLABLE NZUR;Lo;0;L;;;;;N;;;;; +A303;YI SYLLABLE NZYT;Lo;0;L;;;;;N;;;;; +A304;YI SYLLABLE NZYX;Lo;0;L;;;;;N;;;;; +A305;YI SYLLABLE NZY;Lo;0;L;;;;;N;;;;; +A306;YI SYLLABLE NZYP;Lo;0;L;;;;;N;;;;; +A307;YI SYLLABLE NZYRX;Lo;0;L;;;;;N;;;;; +A308;YI SYLLABLE NZYR;Lo;0;L;;;;;N;;;;; +A309;YI SYLLABLE SIT;Lo;0;L;;;;;N;;;;; +A30A;YI SYLLABLE SIX;Lo;0;L;;;;;N;;;;; +A30B;YI SYLLABLE SI;Lo;0;L;;;;;N;;;;; +A30C;YI SYLLABLE SIP;Lo;0;L;;;;;N;;;;; +A30D;YI SYLLABLE SIEX;Lo;0;L;;;;;N;;;;; +A30E;YI SYLLABLE SIE;Lo;0;L;;;;;N;;;;; +A30F;YI SYLLABLE SIEP;Lo;0;L;;;;;N;;;;; +A310;YI SYLLABLE SAT;Lo;0;L;;;;;N;;;;; +A311;YI SYLLABLE SAX;Lo;0;L;;;;;N;;;;; +A312;YI SYLLABLE SA;Lo;0;L;;;;;N;;;;; +A313;YI SYLLABLE SAP;Lo;0;L;;;;;N;;;;; +A314;YI SYLLABLE SUOX;Lo;0;L;;;;;N;;;;; +A315;YI SYLLABLE SUO;Lo;0;L;;;;;N;;;;; +A316;YI SYLLABLE SUOP;Lo;0;L;;;;;N;;;;; +A317;YI SYLLABLE SOT;Lo;0;L;;;;;N;;;;; +A318;YI SYLLABLE SOX;Lo;0;L;;;;;N;;;;; +A319;YI SYLLABLE SO;Lo;0;L;;;;;N;;;;; +A31A;YI SYLLABLE SOP;Lo;0;L;;;;;N;;;;; +A31B;YI SYLLABLE SEX;Lo;0;L;;;;;N;;;;; +A31C;YI SYLLABLE SE;Lo;0;L;;;;;N;;;;; +A31D;YI SYLLABLE SEP;Lo;0;L;;;;;N;;;;; +A31E;YI SYLLABLE SUT;Lo;0;L;;;;;N;;;;; +A31F;YI SYLLABLE SUX;Lo;0;L;;;;;N;;;;; +A320;YI SYLLABLE SU;Lo;0;L;;;;;N;;;;; +A321;YI SYLLABLE SUP;Lo;0;L;;;;;N;;;;; +A322;YI SYLLABLE SURX;Lo;0;L;;;;;N;;;;; +A323;YI SYLLABLE SUR;Lo;0;L;;;;;N;;;;; +A324;YI SYLLABLE SYT;Lo;0;L;;;;;N;;;;; +A325;YI SYLLABLE SYX;Lo;0;L;;;;;N;;;;; +A326;YI SYLLABLE SY;Lo;0;L;;;;;N;;;;; +A327;YI SYLLABLE SYP;Lo;0;L;;;;;N;;;;; +A328;YI SYLLABLE SYRX;Lo;0;L;;;;;N;;;;; +A329;YI SYLLABLE SYR;Lo;0;L;;;;;N;;;;; +A32A;YI SYLLABLE SSIT;Lo;0;L;;;;;N;;;;; +A32B;YI SYLLABLE SSIX;Lo;0;L;;;;;N;;;;; +A32C;YI SYLLABLE SSI;Lo;0;L;;;;;N;;;;; +A32D;YI SYLLABLE SSIP;Lo;0;L;;;;;N;;;;; +A32E;YI SYLLABLE SSIEX;Lo;0;L;;;;;N;;;;; +A32F;YI SYLLABLE SSIE;Lo;0;L;;;;;N;;;;; +A330;YI SYLLABLE SSIEP;Lo;0;L;;;;;N;;;;; +A331;YI SYLLABLE SSAT;Lo;0;L;;;;;N;;;;; +A332;YI SYLLABLE SSAX;Lo;0;L;;;;;N;;;;; +A333;YI SYLLABLE SSA;Lo;0;L;;;;;N;;;;; +A334;YI SYLLABLE SSAP;Lo;0;L;;;;;N;;;;; +A335;YI SYLLABLE SSOT;Lo;0;L;;;;;N;;;;; +A336;YI SYLLABLE SSOX;Lo;0;L;;;;;N;;;;; +A337;YI SYLLABLE SSO;Lo;0;L;;;;;N;;;;; +A338;YI SYLLABLE SSOP;Lo;0;L;;;;;N;;;;; +A339;YI SYLLABLE SSEX;Lo;0;L;;;;;N;;;;; +A33A;YI SYLLABLE SSE;Lo;0;L;;;;;N;;;;; +A33B;YI SYLLABLE SSEP;Lo;0;L;;;;;N;;;;; +A33C;YI SYLLABLE SSUT;Lo;0;L;;;;;N;;;;; +A33D;YI SYLLABLE SSUX;Lo;0;L;;;;;N;;;;; +A33E;YI SYLLABLE SSU;Lo;0;L;;;;;N;;;;; +A33F;YI SYLLABLE SSUP;Lo;0;L;;;;;N;;;;; +A340;YI SYLLABLE SSYT;Lo;0;L;;;;;N;;;;; +A341;YI SYLLABLE SSYX;Lo;0;L;;;;;N;;;;; +A342;YI SYLLABLE SSY;Lo;0;L;;;;;N;;;;; +A343;YI SYLLABLE SSYP;Lo;0;L;;;;;N;;;;; +A344;YI SYLLABLE SSYRX;Lo;0;L;;;;;N;;;;; +A345;YI SYLLABLE SSYR;Lo;0;L;;;;;N;;;;; +A346;YI SYLLABLE ZHAT;Lo;0;L;;;;;N;;;;; +A347;YI SYLLABLE ZHAX;Lo;0;L;;;;;N;;;;; +A348;YI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; +A349;YI SYLLABLE ZHAP;Lo;0;L;;;;;N;;;;; +A34A;YI SYLLABLE ZHUOX;Lo;0;L;;;;;N;;;;; +A34B;YI SYLLABLE ZHUO;Lo;0;L;;;;;N;;;;; +A34C;YI SYLLABLE ZHUOP;Lo;0;L;;;;;N;;;;; +A34D;YI SYLLABLE ZHOT;Lo;0;L;;;;;N;;;;; +A34E;YI SYLLABLE ZHOX;Lo;0;L;;;;;N;;;;; +A34F;YI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; +A350;YI SYLLABLE ZHOP;Lo;0;L;;;;;N;;;;; +A351;YI SYLLABLE ZHET;Lo;0;L;;;;;N;;;;; +A352;YI SYLLABLE ZHEX;Lo;0;L;;;;;N;;;;; +A353;YI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; +A354;YI SYLLABLE ZHEP;Lo;0;L;;;;;N;;;;; +A355;YI SYLLABLE ZHUT;Lo;0;L;;;;;N;;;;; +A356;YI SYLLABLE ZHUX;Lo;0;L;;;;;N;;;;; +A357;YI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; +A358;YI SYLLABLE ZHUP;Lo;0;L;;;;;N;;;;; +A359;YI SYLLABLE ZHURX;Lo;0;L;;;;;N;;;;; +A35A;YI SYLLABLE ZHUR;Lo;0;L;;;;;N;;;;; +A35B;YI SYLLABLE ZHYT;Lo;0;L;;;;;N;;;;; +A35C;YI SYLLABLE ZHYX;Lo;0;L;;;;;N;;;;; +A35D;YI SYLLABLE ZHY;Lo;0;L;;;;;N;;;;; +A35E;YI SYLLABLE ZHYP;Lo;0;L;;;;;N;;;;; +A35F;YI SYLLABLE ZHYRX;Lo;0;L;;;;;N;;;;; +A360;YI SYLLABLE ZHYR;Lo;0;L;;;;;N;;;;; +A361;YI SYLLABLE CHAT;Lo;0;L;;;;;N;;;;; +A362;YI SYLLABLE CHAX;Lo;0;L;;;;;N;;;;; +A363;YI SYLLABLE CHA;Lo;0;L;;;;;N;;;;; +A364;YI SYLLABLE CHAP;Lo;0;L;;;;;N;;;;; +A365;YI SYLLABLE CHUOT;Lo;0;L;;;;;N;;;;; +A366;YI SYLLABLE CHUOX;Lo;0;L;;;;;N;;;;; +A367;YI SYLLABLE CHUO;Lo;0;L;;;;;N;;;;; +A368;YI SYLLABLE CHUOP;Lo;0;L;;;;;N;;;;; +A369;YI SYLLABLE CHOT;Lo;0;L;;;;;N;;;;; +A36A;YI SYLLABLE CHOX;Lo;0;L;;;;;N;;;;; +A36B;YI SYLLABLE CHO;Lo;0;L;;;;;N;;;;; +A36C;YI SYLLABLE CHOP;Lo;0;L;;;;;N;;;;; +A36D;YI SYLLABLE CHET;Lo;0;L;;;;;N;;;;; +A36E;YI SYLLABLE CHEX;Lo;0;L;;;;;N;;;;; +A36F;YI SYLLABLE CHE;Lo;0;L;;;;;N;;;;; +A370;YI SYLLABLE CHEP;Lo;0;L;;;;;N;;;;; +A371;YI SYLLABLE CHUX;Lo;0;L;;;;;N;;;;; +A372;YI SYLLABLE CHU;Lo;0;L;;;;;N;;;;; +A373;YI SYLLABLE CHUP;Lo;0;L;;;;;N;;;;; +A374;YI SYLLABLE CHURX;Lo;0;L;;;;;N;;;;; +A375;YI SYLLABLE CHUR;Lo;0;L;;;;;N;;;;; +A376;YI SYLLABLE CHYT;Lo;0;L;;;;;N;;;;; +A377;YI SYLLABLE CHYX;Lo;0;L;;;;;N;;;;; +A378;YI SYLLABLE CHY;Lo;0;L;;;;;N;;;;; +A379;YI SYLLABLE CHYP;Lo;0;L;;;;;N;;;;; +A37A;YI SYLLABLE CHYRX;Lo;0;L;;;;;N;;;;; +A37B;YI SYLLABLE CHYR;Lo;0;L;;;;;N;;;;; +A37C;YI SYLLABLE RRAX;Lo;0;L;;;;;N;;;;; +A37D;YI SYLLABLE RRA;Lo;0;L;;;;;N;;;;; +A37E;YI SYLLABLE RRUOX;Lo;0;L;;;;;N;;;;; +A37F;YI SYLLABLE RRUO;Lo;0;L;;;;;N;;;;; +A380;YI SYLLABLE RROT;Lo;0;L;;;;;N;;;;; +A381;YI SYLLABLE RROX;Lo;0;L;;;;;N;;;;; +A382;YI SYLLABLE RRO;Lo;0;L;;;;;N;;;;; +A383;YI SYLLABLE RROP;Lo;0;L;;;;;N;;;;; +A384;YI SYLLABLE RRET;Lo;0;L;;;;;N;;;;; +A385;YI SYLLABLE RREX;Lo;0;L;;;;;N;;;;; +A386;YI SYLLABLE RRE;Lo;0;L;;;;;N;;;;; +A387;YI SYLLABLE RREP;Lo;0;L;;;;;N;;;;; +A388;YI SYLLABLE RRUT;Lo;0;L;;;;;N;;;;; +A389;YI SYLLABLE RRUX;Lo;0;L;;;;;N;;;;; +A38A;YI SYLLABLE RRU;Lo;0;L;;;;;N;;;;; +A38B;YI SYLLABLE RRUP;Lo;0;L;;;;;N;;;;; +A38C;YI SYLLABLE RRURX;Lo;0;L;;;;;N;;;;; +A38D;YI SYLLABLE RRUR;Lo;0;L;;;;;N;;;;; +A38E;YI SYLLABLE RRYT;Lo;0;L;;;;;N;;;;; +A38F;YI SYLLABLE RRYX;Lo;0;L;;;;;N;;;;; +A390;YI SYLLABLE RRY;Lo;0;L;;;;;N;;;;; +A391;YI SYLLABLE RRYP;Lo;0;L;;;;;N;;;;; +A392;YI SYLLABLE RRYRX;Lo;0;L;;;;;N;;;;; +A393;YI SYLLABLE RRYR;Lo;0;L;;;;;N;;;;; +A394;YI SYLLABLE NRAT;Lo;0;L;;;;;N;;;;; +A395;YI SYLLABLE NRAX;Lo;0;L;;;;;N;;;;; +A396;YI SYLLABLE NRA;Lo;0;L;;;;;N;;;;; +A397;YI SYLLABLE NRAP;Lo;0;L;;;;;N;;;;; +A398;YI SYLLABLE NROX;Lo;0;L;;;;;N;;;;; +A399;YI SYLLABLE NRO;Lo;0;L;;;;;N;;;;; +A39A;YI SYLLABLE NROP;Lo;0;L;;;;;N;;;;; +A39B;YI SYLLABLE NRET;Lo;0;L;;;;;N;;;;; +A39C;YI SYLLABLE NREX;Lo;0;L;;;;;N;;;;; +A39D;YI SYLLABLE NRE;Lo;0;L;;;;;N;;;;; +A39E;YI SYLLABLE NREP;Lo;0;L;;;;;N;;;;; +A39F;YI SYLLABLE NRUT;Lo;0;L;;;;;N;;;;; +A3A0;YI SYLLABLE NRUX;Lo;0;L;;;;;N;;;;; +A3A1;YI SYLLABLE NRU;Lo;0;L;;;;;N;;;;; +A3A2;YI SYLLABLE NRUP;Lo;0;L;;;;;N;;;;; +A3A3;YI SYLLABLE NRURX;Lo;0;L;;;;;N;;;;; +A3A4;YI SYLLABLE NRUR;Lo;0;L;;;;;N;;;;; +A3A5;YI SYLLABLE NRYT;Lo;0;L;;;;;N;;;;; +A3A6;YI SYLLABLE NRYX;Lo;0;L;;;;;N;;;;; +A3A7;YI SYLLABLE NRY;Lo;0;L;;;;;N;;;;; +A3A8;YI SYLLABLE NRYP;Lo;0;L;;;;;N;;;;; +A3A9;YI SYLLABLE NRYRX;Lo;0;L;;;;;N;;;;; +A3AA;YI SYLLABLE NRYR;Lo;0;L;;;;;N;;;;; +A3AB;YI SYLLABLE SHAT;Lo;0;L;;;;;N;;;;; +A3AC;YI SYLLABLE SHAX;Lo;0;L;;;;;N;;;;; +A3AD;YI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; +A3AE;YI SYLLABLE SHAP;Lo;0;L;;;;;N;;;;; +A3AF;YI SYLLABLE SHUOX;Lo;0;L;;;;;N;;;;; +A3B0;YI SYLLABLE SHUO;Lo;0;L;;;;;N;;;;; +A3B1;YI SYLLABLE SHUOP;Lo;0;L;;;;;N;;;;; +A3B2;YI SYLLABLE SHOT;Lo;0;L;;;;;N;;;;; +A3B3;YI SYLLABLE SHOX;Lo;0;L;;;;;N;;;;; +A3B4;YI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; +A3B5;YI SYLLABLE SHOP;Lo;0;L;;;;;N;;;;; +A3B6;YI SYLLABLE SHET;Lo;0;L;;;;;N;;;;; +A3B7;YI SYLLABLE SHEX;Lo;0;L;;;;;N;;;;; +A3B8;YI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; +A3B9;YI SYLLABLE SHEP;Lo;0;L;;;;;N;;;;; +A3BA;YI SYLLABLE SHUT;Lo;0;L;;;;;N;;;;; +A3BB;YI SYLLABLE SHUX;Lo;0;L;;;;;N;;;;; +A3BC;YI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; +A3BD;YI SYLLABLE SHUP;Lo;0;L;;;;;N;;;;; +A3BE;YI SYLLABLE SHURX;Lo;0;L;;;;;N;;;;; +A3BF;YI SYLLABLE SHUR;Lo;0;L;;;;;N;;;;; +A3C0;YI SYLLABLE SHYT;Lo;0;L;;;;;N;;;;; +A3C1;YI SYLLABLE SHYX;Lo;0;L;;;;;N;;;;; +A3C2;YI SYLLABLE SHY;Lo;0;L;;;;;N;;;;; +A3C3;YI SYLLABLE SHYP;Lo;0;L;;;;;N;;;;; +A3C4;YI SYLLABLE SHYRX;Lo;0;L;;;;;N;;;;; +A3C5;YI SYLLABLE SHYR;Lo;0;L;;;;;N;;;;; +A3C6;YI SYLLABLE RAT;Lo;0;L;;;;;N;;;;; +A3C7;YI SYLLABLE RAX;Lo;0;L;;;;;N;;;;; +A3C8;YI SYLLABLE RA;Lo;0;L;;;;;N;;;;; +A3C9;YI SYLLABLE RAP;Lo;0;L;;;;;N;;;;; +A3CA;YI SYLLABLE RUOX;Lo;0;L;;;;;N;;;;; +A3CB;YI SYLLABLE RUO;Lo;0;L;;;;;N;;;;; +A3CC;YI SYLLABLE RUOP;Lo;0;L;;;;;N;;;;; +A3CD;YI SYLLABLE ROT;Lo;0;L;;;;;N;;;;; +A3CE;YI SYLLABLE ROX;Lo;0;L;;;;;N;;;;; +A3CF;YI SYLLABLE RO;Lo;0;L;;;;;N;;;;; +A3D0;YI SYLLABLE ROP;Lo;0;L;;;;;N;;;;; +A3D1;YI SYLLABLE REX;Lo;0;L;;;;;N;;;;; +A3D2;YI SYLLABLE RE;Lo;0;L;;;;;N;;;;; +A3D3;YI SYLLABLE REP;Lo;0;L;;;;;N;;;;; +A3D4;YI SYLLABLE RUT;Lo;0;L;;;;;N;;;;; +A3D5;YI SYLLABLE RUX;Lo;0;L;;;;;N;;;;; +A3D6;YI SYLLABLE RU;Lo;0;L;;;;;N;;;;; +A3D7;YI SYLLABLE RUP;Lo;0;L;;;;;N;;;;; +A3D8;YI SYLLABLE RURX;Lo;0;L;;;;;N;;;;; +A3D9;YI SYLLABLE RUR;Lo;0;L;;;;;N;;;;; +A3DA;YI SYLLABLE RYT;Lo;0;L;;;;;N;;;;; +A3DB;YI SYLLABLE RYX;Lo;0;L;;;;;N;;;;; +A3DC;YI SYLLABLE RY;Lo;0;L;;;;;N;;;;; +A3DD;YI SYLLABLE RYP;Lo;0;L;;;;;N;;;;; +A3DE;YI SYLLABLE RYRX;Lo;0;L;;;;;N;;;;; +A3DF;YI SYLLABLE RYR;Lo;0;L;;;;;N;;;;; +A3E0;YI SYLLABLE JIT;Lo;0;L;;;;;N;;;;; +A3E1;YI SYLLABLE JIX;Lo;0;L;;;;;N;;;;; +A3E2;YI SYLLABLE JI;Lo;0;L;;;;;N;;;;; +A3E3;YI SYLLABLE JIP;Lo;0;L;;;;;N;;;;; +A3E4;YI SYLLABLE JIET;Lo;0;L;;;;;N;;;;; +A3E5;YI SYLLABLE JIEX;Lo;0;L;;;;;N;;;;; +A3E6;YI SYLLABLE JIE;Lo;0;L;;;;;N;;;;; +A3E7;YI SYLLABLE JIEP;Lo;0;L;;;;;N;;;;; +A3E8;YI SYLLABLE JUOT;Lo;0;L;;;;;N;;;;; +A3E9;YI SYLLABLE JUOX;Lo;0;L;;;;;N;;;;; +A3EA;YI SYLLABLE JUO;Lo;0;L;;;;;N;;;;; +A3EB;YI SYLLABLE JUOP;Lo;0;L;;;;;N;;;;; +A3EC;YI SYLLABLE JOT;Lo;0;L;;;;;N;;;;; +A3ED;YI SYLLABLE JOX;Lo;0;L;;;;;N;;;;; +A3EE;YI SYLLABLE JO;Lo;0;L;;;;;N;;;;; +A3EF;YI SYLLABLE JOP;Lo;0;L;;;;;N;;;;; +A3F0;YI SYLLABLE JUT;Lo;0;L;;;;;N;;;;; +A3F1;YI SYLLABLE JUX;Lo;0;L;;;;;N;;;;; +A3F2;YI SYLLABLE JU;Lo;0;L;;;;;N;;;;; +A3F3;YI SYLLABLE JUP;Lo;0;L;;;;;N;;;;; +A3F4;YI SYLLABLE JURX;Lo;0;L;;;;;N;;;;; +A3F5;YI SYLLABLE JUR;Lo;0;L;;;;;N;;;;; +A3F6;YI SYLLABLE JYT;Lo;0;L;;;;;N;;;;; +A3F7;YI SYLLABLE JYX;Lo;0;L;;;;;N;;;;; +A3F8;YI SYLLABLE JY;Lo;0;L;;;;;N;;;;; +A3F9;YI SYLLABLE JYP;Lo;0;L;;;;;N;;;;; +A3FA;YI SYLLABLE JYRX;Lo;0;L;;;;;N;;;;; +A3FB;YI SYLLABLE JYR;Lo;0;L;;;;;N;;;;; +A3FC;YI SYLLABLE QIT;Lo;0;L;;;;;N;;;;; +A3FD;YI SYLLABLE QIX;Lo;0;L;;;;;N;;;;; +A3FE;YI SYLLABLE QI;Lo;0;L;;;;;N;;;;; +A3FF;YI SYLLABLE QIP;Lo;0;L;;;;;N;;;;; +A400;YI SYLLABLE QIET;Lo;0;L;;;;;N;;;;; +A401;YI SYLLABLE QIEX;Lo;0;L;;;;;N;;;;; +A402;YI SYLLABLE QIE;Lo;0;L;;;;;N;;;;; +A403;YI SYLLABLE QIEP;Lo;0;L;;;;;N;;;;; +A404;YI SYLLABLE QUOT;Lo;0;L;;;;;N;;;;; +A405;YI SYLLABLE QUOX;Lo;0;L;;;;;N;;;;; +A406;YI SYLLABLE QUO;Lo;0;L;;;;;N;;;;; +A407;YI SYLLABLE QUOP;Lo;0;L;;;;;N;;;;; +A408;YI SYLLABLE QOT;Lo;0;L;;;;;N;;;;; +A409;YI SYLLABLE QOX;Lo;0;L;;;;;N;;;;; +A40A;YI SYLLABLE QO;Lo;0;L;;;;;N;;;;; +A40B;YI SYLLABLE QOP;Lo;0;L;;;;;N;;;;; +A40C;YI SYLLABLE QUT;Lo;0;L;;;;;N;;;;; +A40D;YI SYLLABLE QUX;Lo;0;L;;;;;N;;;;; +A40E;YI SYLLABLE QU;Lo;0;L;;;;;N;;;;; +A40F;YI SYLLABLE QUP;Lo;0;L;;;;;N;;;;; +A410;YI SYLLABLE QURX;Lo;0;L;;;;;N;;;;; +A411;YI SYLLABLE QUR;Lo;0;L;;;;;N;;;;; +A412;YI SYLLABLE QYT;Lo;0;L;;;;;N;;;;; +A413;YI SYLLABLE QYX;Lo;0;L;;;;;N;;;;; +A414;YI SYLLABLE QY;Lo;0;L;;;;;N;;;;; +A415;YI SYLLABLE QYP;Lo;0;L;;;;;N;;;;; +A416;YI SYLLABLE QYRX;Lo;0;L;;;;;N;;;;; +A417;YI SYLLABLE QYR;Lo;0;L;;;;;N;;;;; +A418;YI SYLLABLE JJIT;Lo;0;L;;;;;N;;;;; +A419;YI SYLLABLE JJIX;Lo;0;L;;;;;N;;;;; +A41A;YI SYLLABLE JJI;Lo;0;L;;;;;N;;;;; +A41B;YI SYLLABLE JJIP;Lo;0;L;;;;;N;;;;; +A41C;YI SYLLABLE JJIET;Lo;0;L;;;;;N;;;;; +A41D;YI SYLLABLE JJIEX;Lo;0;L;;;;;N;;;;; +A41E;YI SYLLABLE JJIE;Lo;0;L;;;;;N;;;;; +A41F;YI SYLLABLE JJIEP;Lo;0;L;;;;;N;;;;; +A420;YI SYLLABLE JJUOX;Lo;0;L;;;;;N;;;;; +A421;YI SYLLABLE JJUO;Lo;0;L;;;;;N;;;;; +A422;YI SYLLABLE JJUOP;Lo;0;L;;;;;N;;;;; +A423;YI SYLLABLE JJOT;Lo;0;L;;;;;N;;;;; +A424;YI SYLLABLE JJOX;Lo;0;L;;;;;N;;;;; +A425;YI SYLLABLE JJO;Lo;0;L;;;;;N;;;;; +A426;YI SYLLABLE JJOP;Lo;0;L;;;;;N;;;;; +A427;YI SYLLABLE JJUT;Lo;0;L;;;;;N;;;;; +A428;YI SYLLABLE JJUX;Lo;0;L;;;;;N;;;;; +A429;YI SYLLABLE JJU;Lo;0;L;;;;;N;;;;; +A42A;YI SYLLABLE JJUP;Lo;0;L;;;;;N;;;;; +A42B;YI SYLLABLE JJURX;Lo;0;L;;;;;N;;;;; +A42C;YI SYLLABLE JJUR;Lo;0;L;;;;;N;;;;; +A42D;YI SYLLABLE JJYT;Lo;0;L;;;;;N;;;;; +A42E;YI SYLLABLE JJYX;Lo;0;L;;;;;N;;;;; +A42F;YI SYLLABLE JJY;Lo;0;L;;;;;N;;;;; +A430;YI SYLLABLE JJYP;Lo;0;L;;;;;N;;;;; +A431;YI SYLLABLE NJIT;Lo;0;L;;;;;N;;;;; +A432;YI SYLLABLE NJIX;Lo;0;L;;;;;N;;;;; +A433;YI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; +A434;YI SYLLABLE NJIP;Lo;0;L;;;;;N;;;;; +A435;YI SYLLABLE NJIET;Lo;0;L;;;;;N;;;;; +A436;YI SYLLABLE NJIEX;Lo;0;L;;;;;N;;;;; +A437;YI SYLLABLE NJIE;Lo;0;L;;;;;N;;;;; +A438;YI SYLLABLE NJIEP;Lo;0;L;;;;;N;;;;; +A439;YI SYLLABLE NJUOX;Lo;0;L;;;;;N;;;;; +A43A;YI SYLLABLE NJUO;Lo;0;L;;;;;N;;;;; +A43B;YI SYLLABLE NJOT;Lo;0;L;;;;;N;;;;; +A43C;YI SYLLABLE NJOX;Lo;0;L;;;;;N;;;;; +A43D;YI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; +A43E;YI SYLLABLE NJOP;Lo;0;L;;;;;N;;;;; +A43F;YI SYLLABLE NJUX;Lo;0;L;;;;;N;;;;; +A440;YI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; +A441;YI SYLLABLE NJUP;Lo;0;L;;;;;N;;;;; +A442;YI SYLLABLE NJURX;Lo;0;L;;;;;N;;;;; +A443;YI SYLLABLE NJUR;Lo;0;L;;;;;N;;;;; +A444;YI SYLLABLE NJYT;Lo;0;L;;;;;N;;;;; +A445;YI SYLLABLE NJYX;Lo;0;L;;;;;N;;;;; +A446;YI SYLLABLE NJY;Lo;0;L;;;;;N;;;;; +A447;YI SYLLABLE NJYP;Lo;0;L;;;;;N;;;;; +A448;YI SYLLABLE NJYRX;Lo;0;L;;;;;N;;;;; +A449;YI SYLLABLE NJYR;Lo;0;L;;;;;N;;;;; +A44A;YI SYLLABLE NYIT;Lo;0;L;;;;;N;;;;; +A44B;YI SYLLABLE NYIX;Lo;0;L;;;;;N;;;;; +A44C;YI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; +A44D;YI SYLLABLE NYIP;Lo;0;L;;;;;N;;;;; +A44E;YI SYLLABLE NYIET;Lo;0;L;;;;;N;;;;; +A44F;YI SYLLABLE NYIEX;Lo;0;L;;;;;N;;;;; +A450;YI SYLLABLE NYIE;Lo;0;L;;;;;N;;;;; +A451;YI SYLLABLE NYIEP;Lo;0;L;;;;;N;;;;; +A452;YI SYLLABLE NYUOX;Lo;0;L;;;;;N;;;;; +A453;YI SYLLABLE NYUO;Lo;0;L;;;;;N;;;;; +A454;YI SYLLABLE NYUOP;Lo;0;L;;;;;N;;;;; +A455;YI SYLLABLE NYOT;Lo;0;L;;;;;N;;;;; +A456;YI SYLLABLE NYOX;Lo;0;L;;;;;N;;;;; +A457;YI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; +A458;YI SYLLABLE NYOP;Lo;0;L;;;;;N;;;;; +A459;YI SYLLABLE NYUT;Lo;0;L;;;;;N;;;;; +A45A;YI SYLLABLE NYUX;Lo;0;L;;;;;N;;;;; +A45B;YI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; +A45C;YI SYLLABLE NYUP;Lo;0;L;;;;;N;;;;; +A45D;YI SYLLABLE XIT;Lo;0;L;;;;;N;;;;; +A45E;YI SYLLABLE XIX;Lo;0;L;;;;;N;;;;; +A45F;YI SYLLABLE XI;Lo;0;L;;;;;N;;;;; +A460;YI SYLLABLE XIP;Lo;0;L;;;;;N;;;;; +A461;YI SYLLABLE XIET;Lo;0;L;;;;;N;;;;; +A462;YI SYLLABLE XIEX;Lo;0;L;;;;;N;;;;; +A463;YI SYLLABLE XIE;Lo;0;L;;;;;N;;;;; +A464;YI SYLLABLE XIEP;Lo;0;L;;;;;N;;;;; +A465;YI SYLLABLE XUOX;Lo;0;L;;;;;N;;;;; +A466;YI SYLLABLE XUO;Lo;0;L;;;;;N;;;;; +A467;YI SYLLABLE XOT;Lo;0;L;;;;;N;;;;; +A468;YI SYLLABLE XOX;Lo;0;L;;;;;N;;;;; +A469;YI SYLLABLE XO;Lo;0;L;;;;;N;;;;; +A46A;YI SYLLABLE XOP;Lo;0;L;;;;;N;;;;; +A46B;YI SYLLABLE XYT;Lo;0;L;;;;;N;;;;; +A46C;YI SYLLABLE XYX;Lo;0;L;;;;;N;;;;; +A46D;YI SYLLABLE XY;Lo;0;L;;;;;N;;;;; +A46E;YI SYLLABLE XYP;Lo;0;L;;;;;N;;;;; +A46F;YI SYLLABLE XYRX;Lo;0;L;;;;;N;;;;; +A470;YI SYLLABLE XYR;Lo;0;L;;;;;N;;;;; +A471;YI SYLLABLE YIT;Lo;0;L;;;;;N;;;;; +A472;YI SYLLABLE YIX;Lo;0;L;;;;;N;;;;; +A473;YI SYLLABLE YI;Lo;0;L;;;;;N;;;;; +A474;YI SYLLABLE YIP;Lo;0;L;;;;;N;;;;; +A475;YI SYLLABLE YIET;Lo;0;L;;;;;N;;;;; +A476;YI SYLLABLE YIEX;Lo;0;L;;;;;N;;;;; +A477;YI SYLLABLE YIE;Lo;0;L;;;;;N;;;;; +A478;YI SYLLABLE YIEP;Lo;0;L;;;;;N;;;;; +A479;YI SYLLABLE YUOT;Lo;0;L;;;;;N;;;;; +A47A;YI SYLLABLE YUOX;Lo;0;L;;;;;N;;;;; +A47B;YI SYLLABLE YUO;Lo;0;L;;;;;N;;;;; +A47C;YI SYLLABLE YUOP;Lo;0;L;;;;;N;;;;; +A47D;YI SYLLABLE YOT;Lo;0;L;;;;;N;;;;; +A47E;YI SYLLABLE YOX;Lo;0;L;;;;;N;;;;; +A47F;YI SYLLABLE YO;Lo;0;L;;;;;N;;;;; +A480;YI SYLLABLE YOP;Lo;0;L;;;;;N;;;;; +A481;YI SYLLABLE YUT;Lo;0;L;;;;;N;;;;; +A482;YI SYLLABLE YUX;Lo;0;L;;;;;N;;;;; +A483;YI SYLLABLE YU;Lo;0;L;;;;;N;;;;; +A484;YI SYLLABLE YUP;Lo;0;L;;;;;N;;;;; +A485;YI SYLLABLE YURX;Lo;0;L;;;;;N;;;;; +A486;YI SYLLABLE YUR;Lo;0;L;;;;;N;;;;; +A487;YI SYLLABLE YYT;Lo;0;L;;;;;N;;;;; +A488;YI SYLLABLE YYX;Lo;0;L;;;;;N;;;;; +A489;YI SYLLABLE YY;Lo;0;L;;;;;N;;;;; +A48A;YI SYLLABLE YYP;Lo;0;L;;;;;N;;;;; +A48B;YI SYLLABLE YYRX;Lo;0;L;;;;;N;;;;; +A48C;YI SYLLABLE YYR;Lo;0;L;;;;;N;;;;; +A490;YI RADICAL QOT;So;0;ON;;;;;N;;;;; +A491;YI RADICAL LI;So;0;ON;;;;;N;;;;; +A492;YI RADICAL KIT;So;0;ON;;;;;N;;;;; +A493;YI RADICAL NYIP;So;0;ON;;;;;N;;;;; +A494;YI RADICAL CYP;So;0;ON;;;;;N;;;;; +A495;YI RADICAL SSI;So;0;ON;;;;;N;;;;; +A496;YI RADICAL GGOP;So;0;ON;;;;;N;;;;; +A497;YI RADICAL GEP;So;0;ON;;;;;N;;;;; +A498;YI RADICAL MI;So;0;ON;;;;;N;;;;; +A499;YI RADICAL HXIT;So;0;ON;;;;;N;;;;; +A49A;YI RADICAL LYR;So;0;ON;;;;;N;;;;; +A49B;YI RADICAL BBUT;So;0;ON;;;;;N;;;;; +A49C;YI RADICAL MOP;So;0;ON;;;;;N;;;;; +A49D;YI RADICAL YO;So;0;ON;;;;;N;;;;; +A49E;YI RADICAL PUT;So;0;ON;;;;;N;;;;; +A49F;YI RADICAL HXUO;So;0;ON;;;;;N;;;;; +A4A0;YI RADICAL TAT;So;0;ON;;;;;N;;;;; +A4A1;YI RADICAL GA;So;0;ON;;;;;N;;;;; +A4A2;YI RADICAL ZUP;So;0;ON;;;;;N;;;;; +A4A3;YI RADICAL CYT;So;0;ON;;;;;N;;;;; +A4A4;YI RADICAL DDUR;So;0;ON;;;;;N;;;;; +A4A5;YI RADICAL BUR;So;0;ON;;;;;N;;;;; +A4A6;YI RADICAL GGUO;So;0;ON;;;;;N;;;;; +A4A7;YI RADICAL NYOP;So;0;ON;;;;;N;;;;; +A4A8;YI RADICAL TU;So;0;ON;;;;;N;;;;; +A4A9;YI RADICAL OP;So;0;ON;;;;;N;;;;; +A4AA;YI RADICAL JJUT;So;0;ON;;;;;N;;;;; +A4AB;YI RADICAL ZOT;So;0;ON;;;;;N;;;;; +A4AC;YI RADICAL PYT;So;0;ON;;;;;N;;;;; +A4AD;YI RADICAL HMO;So;0;ON;;;;;N;;;;; +A4AE;YI RADICAL YIT;So;0;ON;;;;;N;;;;; +A4AF;YI RADICAL VUR;So;0;ON;;;;;N;;;;; +A4B0;YI RADICAL SHY;So;0;ON;;;;;N;;;;; +A4B1;YI RADICAL VEP;So;0;ON;;;;;N;;;;; +A4B2;YI RADICAL ZA;So;0;ON;;;;;N;;;;; +A4B3;YI RADICAL JO;So;0;ON;;;;;N;;;;; +A4B4;YI RADICAL NZUP;So;0;ON;;;;;N;;;;; +A4B5;YI RADICAL JJY;So;0;ON;;;;;N;;;;; +A4B6;YI RADICAL GOT;So;0;ON;;;;;N;;;;; +A4B7;YI RADICAL JJIE;So;0;ON;;;;;N;;;;; +A4B8;YI RADICAL WO;So;0;ON;;;;;N;;;;; +A4B9;YI RADICAL DU;So;0;ON;;;;;N;;;;; +A4BA;YI RADICAL SHUR;So;0;ON;;;;;N;;;;; +A4BB;YI RADICAL LIE;So;0;ON;;;;;N;;;;; +A4BC;YI RADICAL CY;So;0;ON;;;;;N;;;;; +A4BD;YI RADICAL CUOP;So;0;ON;;;;;N;;;;; +A4BE;YI RADICAL CIP;So;0;ON;;;;;N;;;;; +A4BF;YI RADICAL HXOP;So;0;ON;;;;;N;;;;; +A4C0;YI RADICAL SHAT;So;0;ON;;;;;N;;;;; +A4C1;YI RADICAL ZUR;So;0;ON;;;;;N;;;;; +A4C2;YI RADICAL SHOP;So;0;ON;;;;;N;;;;; +A4C3;YI RADICAL CHE;So;0;ON;;;;;N;;;;; +A4C4;YI RADICAL ZZIET;So;0;ON;;;;;N;;;;; +A4C5;YI RADICAL NBIE;So;0;ON;;;;;N;;;;; +A4C6;YI RADICAL KE;So;0;ON;;;;;N;;;;; +A4D0;LISU LETTER BA;Lo;0;L;;;;;N;;;;; +A4D1;LISU LETTER PA;Lo;0;L;;;;;N;;;;; +A4D2;LISU LETTER PHA;Lo;0;L;;;;;N;;;;; +A4D3;LISU LETTER DA;Lo;0;L;;;;;N;;;;; +A4D4;LISU LETTER TA;Lo;0;L;;;;;N;;;;; +A4D5;LISU LETTER THA;Lo;0;L;;;;;N;;;;; +A4D6;LISU LETTER GA;Lo;0;L;;;;;N;;;;; +A4D7;LISU LETTER KA;Lo;0;L;;;;;N;;;;; +A4D8;LISU LETTER KHA;Lo;0;L;;;;;N;;;;; +A4D9;LISU LETTER JA;Lo;0;L;;;;;N;;;;; +A4DA;LISU LETTER CA;Lo;0;L;;;;;N;;;;; +A4DB;LISU LETTER CHA;Lo;0;L;;;;;N;;;;; +A4DC;LISU LETTER DZA;Lo;0;L;;;;;N;;;;; +A4DD;LISU LETTER TSA;Lo;0;L;;;;;N;;;;; +A4DE;LISU LETTER TSHA;Lo;0;L;;;;;N;;;;; +A4DF;LISU LETTER MA;Lo;0;L;;;;;N;;;;; +A4E0;LISU LETTER NA;Lo;0;L;;;;;N;;;;; +A4E1;LISU LETTER LA;Lo;0;L;;;;;N;;;;; +A4E2;LISU LETTER SA;Lo;0;L;;;;;N;;;;; +A4E3;LISU LETTER ZHA;Lo;0;L;;;;;N;;;;; +A4E4;LISU LETTER ZA;Lo;0;L;;;;;N;;;;; +A4E5;LISU LETTER NGA;Lo;0;L;;;;;N;;;;; +A4E6;LISU LETTER HA;Lo;0;L;;;;;N;;;;; +A4E7;LISU LETTER XA;Lo;0;L;;;;;N;;;;; +A4E8;LISU LETTER HHA;Lo;0;L;;;;;N;;;;; +A4E9;LISU LETTER FA;Lo;0;L;;;;;N;;;;; +A4EA;LISU LETTER WA;Lo;0;L;;;;;N;;;;; +A4EB;LISU LETTER SHA;Lo;0;L;;;;;N;;;;; +A4EC;LISU LETTER YA;Lo;0;L;;;;;N;;;;; +A4ED;LISU LETTER GHA;Lo;0;L;;;;;N;;;;; +A4EE;LISU LETTER A;Lo;0;L;;;;;N;;;;; +A4EF;LISU LETTER AE;Lo;0;L;;;;;N;;;;; +A4F0;LISU LETTER E;Lo;0;L;;;;;N;;;;; +A4F1;LISU LETTER EU;Lo;0;L;;;;;N;;;;; +A4F2;LISU LETTER I;Lo;0;L;;;;;N;;;;; +A4F3;LISU LETTER O;Lo;0;L;;;;;N;;;;; +A4F4;LISU LETTER U;Lo;0;L;;;;;N;;;;; +A4F5;LISU LETTER UE;Lo;0;L;;;;;N;;;;; +A4F6;LISU LETTER UH;Lo;0;L;;;;;N;;;;; +A4F7;LISU LETTER OE;Lo;0;L;;;;;N;;;;; +A4F8;LISU LETTER TONE MYA TI;Lm;0;L;;;;;N;;;;; +A4F9;LISU LETTER TONE NA PO;Lm;0;L;;;;;N;;;;; +A4FA;LISU LETTER TONE MYA CYA;Lm;0;L;;;;;N;;;;; +A4FB;LISU LETTER TONE MYA BO;Lm;0;L;;;;;N;;;;; +A4FC;LISU LETTER TONE MYA NA;Lm;0;L;;;;;N;;;;; +A4FD;LISU LETTER TONE MYA JEU;Lm;0;L;;;;;N;;;;; +A4FE;LISU PUNCTUATION COMMA;Po;0;L;;;;;N;;;;; +A4FF;LISU PUNCTUATION FULL STOP;Po;0;L;;;;;N;;;;; +A500;VAI SYLLABLE EE;Lo;0;L;;;;;N;;;;; +A501;VAI SYLLABLE EEN;Lo;0;L;;;;;N;;;;; +A502;VAI SYLLABLE HEE;Lo;0;L;;;;;N;;;;; +A503;VAI SYLLABLE WEE;Lo;0;L;;;;;N;;;;; +A504;VAI SYLLABLE WEEN;Lo;0;L;;;;;N;;;;; +A505;VAI SYLLABLE PEE;Lo;0;L;;;;;N;;;;; +A506;VAI SYLLABLE BHEE;Lo;0;L;;;;;N;;;;; +A507;VAI SYLLABLE BEE;Lo;0;L;;;;;N;;;;; +A508;VAI SYLLABLE MBEE;Lo;0;L;;;;;N;;;;; +A509;VAI SYLLABLE KPEE;Lo;0;L;;;;;N;;;;; +A50A;VAI SYLLABLE MGBEE;Lo;0;L;;;;;N;;;;; +A50B;VAI SYLLABLE GBEE;Lo;0;L;;;;;N;;;;; +A50C;VAI SYLLABLE FEE;Lo;0;L;;;;;N;;;;; +A50D;VAI SYLLABLE VEE;Lo;0;L;;;;;N;;;;; +A50E;VAI SYLLABLE TEE;Lo;0;L;;;;;N;;;;; +A50F;VAI SYLLABLE THEE;Lo;0;L;;;;;N;;;;; +A510;VAI SYLLABLE DHEE;Lo;0;L;;;;;N;;;;; +A511;VAI SYLLABLE DHHEE;Lo;0;L;;;;;N;;;;; +A512;VAI SYLLABLE LEE;Lo;0;L;;;;;N;;;;; +A513;VAI SYLLABLE REE;Lo;0;L;;;;;N;;;;; +A514;VAI SYLLABLE DEE;Lo;0;L;;;;;N;;;;; +A515;VAI SYLLABLE NDEE;Lo;0;L;;;;;N;;;;; +A516;VAI SYLLABLE SEE;Lo;0;L;;;;;N;;;;; +A517;VAI SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; +A518;VAI SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; +A519;VAI SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; +A51A;VAI SYLLABLE CEE;Lo;0;L;;;;;N;;;;; +A51B;VAI SYLLABLE JEE;Lo;0;L;;;;;N;;;;; +A51C;VAI SYLLABLE NJEE;Lo;0;L;;;;;N;;;;; +A51D;VAI SYLLABLE YEE;Lo;0;L;;;;;N;;;;; +A51E;VAI SYLLABLE KEE;Lo;0;L;;;;;N;;;;; +A51F;VAI SYLLABLE NGGEE;Lo;0;L;;;;;N;;;;; +A520;VAI SYLLABLE GEE;Lo;0;L;;;;;N;;;;; +A521;VAI SYLLABLE MEE;Lo;0;L;;;;;N;;;;; +A522;VAI SYLLABLE NEE;Lo;0;L;;;;;N;;;;; +A523;VAI SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; +A524;VAI SYLLABLE I;Lo;0;L;;;;;N;;;;; +A525;VAI SYLLABLE IN;Lo;0;L;;;;;N;;;;; +A526;VAI SYLLABLE HI;Lo;0;L;;;;;N;;;;; +A527;VAI SYLLABLE HIN;Lo;0;L;;;;;N;;;;; +A528;VAI SYLLABLE WI;Lo;0;L;;;;;N;;;;; +A529;VAI SYLLABLE WIN;Lo;0;L;;;;;N;;;;; +A52A;VAI SYLLABLE PI;Lo;0;L;;;;;N;;;;; +A52B;VAI SYLLABLE BHI;Lo;0;L;;;;;N;;;;; +A52C;VAI SYLLABLE BI;Lo;0;L;;;;;N;;;;; +A52D;VAI SYLLABLE MBI;Lo;0;L;;;;;N;;;;; +A52E;VAI SYLLABLE KPI;Lo;0;L;;;;;N;;;;; +A52F;VAI SYLLABLE MGBI;Lo;0;L;;;;;N;;;;; +A530;VAI SYLLABLE GBI;Lo;0;L;;;;;N;;;;; +A531;VAI SYLLABLE FI;Lo;0;L;;;;;N;;;;; +A532;VAI SYLLABLE VI;Lo;0;L;;;;;N;;;;; +A533;VAI SYLLABLE TI;Lo;0;L;;;;;N;;;;; +A534;VAI SYLLABLE THI;Lo;0;L;;;;;N;;;;; +A535;VAI SYLLABLE DHI;Lo;0;L;;;;;N;;;;; +A536;VAI SYLLABLE DHHI;Lo;0;L;;;;;N;;;;; +A537;VAI SYLLABLE LI;Lo;0;L;;;;;N;;;;; +A538;VAI SYLLABLE RI;Lo;0;L;;;;;N;;;;; +A539;VAI SYLLABLE DI;Lo;0;L;;;;;N;;;;; +A53A;VAI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; +A53B;VAI SYLLABLE SI;Lo;0;L;;;;;N;;;;; +A53C;VAI SYLLABLE SHI;Lo;0;L;;;;;N;;;;; +A53D;VAI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; +A53E;VAI SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; +A53F;VAI SYLLABLE CI;Lo;0;L;;;;;N;;;;; +A540;VAI SYLLABLE JI;Lo;0;L;;;;;N;;;;; +A541;VAI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; +A542;VAI SYLLABLE YI;Lo;0;L;;;;;N;;;;; +A543;VAI SYLLABLE KI;Lo;0;L;;;;;N;;;;; +A544;VAI SYLLABLE NGGI;Lo;0;L;;;;;N;;;;; +A545;VAI SYLLABLE GI;Lo;0;L;;;;;N;;;;; +A546;VAI SYLLABLE MI;Lo;0;L;;;;;N;;;;; +A547;VAI SYLLABLE NI;Lo;0;L;;;;;N;;;;; +A548;VAI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; +A549;VAI SYLLABLE A;Lo;0;L;;;;;N;;;;; +A54A;VAI SYLLABLE AN;Lo;0;L;;;;;N;;;;; +A54B;VAI SYLLABLE NGAN;Lo;0;L;;;;;N;;;;; +A54C;VAI SYLLABLE HA;Lo;0;L;;;;;N;;;;; +A54D;VAI SYLLABLE HAN;Lo;0;L;;;;;N;;;;; +A54E;VAI SYLLABLE WA;Lo;0;L;;;;;N;;;;; +A54F;VAI SYLLABLE WAN;Lo;0;L;;;;;N;;;;; +A550;VAI SYLLABLE PA;Lo;0;L;;;;;N;;;;; +A551;VAI SYLLABLE BHA;Lo;0;L;;;;;N;;;;; +A552;VAI SYLLABLE BA;Lo;0;L;;;;;N;;;;; +A553;VAI SYLLABLE MBA;Lo;0;L;;;;;N;;;;; +A554;VAI SYLLABLE KPA;Lo;0;L;;;;;N;;;;; +A555;VAI SYLLABLE KPAN;Lo;0;L;;;;;N;;;;; +A556;VAI SYLLABLE MGBA;Lo;0;L;;;;;N;;;;; +A557;VAI SYLLABLE GBA;Lo;0;L;;;;;N;;;;; +A558;VAI SYLLABLE FA;Lo;0;L;;;;;N;;;;; +A559;VAI SYLLABLE VA;Lo;0;L;;;;;N;;;;; +A55A;VAI SYLLABLE TA;Lo;0;L;;;;;N;;;;; +A55B;VAI SYLLABLE THA;Lo;0;L;;;;;N;;;;; +A55C;VAI SYLLABLE DHA;Lo;0;L;;;;;N;;;;; +A55D;VAI SYLLABLE DHHA;Lo;0;L;;;;;N;;;;; +A55E;VAI SYLLABLE LA;Lo;0;L;;;;;N;;;;; +A55F;VAI SYLLABLE RA;Lo;0;L;;;;;N;;;;; +A560;VAI SYLLABLE DA;Lo;0;L;;;;;N;;;;; +A561;VAI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; +A562;VAI SYLLABLE SA;Lo;0;L;;;;;N;;;;; +A563;VAI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; +A564;VAI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; +A565;VAI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; +A566;VAI SYLLABLE CA;Lo;0;L;;;;;N;;;;; +A567;VAI SYLLABLE JA;Lo;0;L;;;;;N;;;;; +A568;VAI SYLLABLE NJA;Lo;0;L;;;;;N;;;;; +A569;VAI SYLLABLE YA;Lo;0;L;;;;;N;;;;; +A56A;VAI SYLLABLE KA;Lo;0;L;;;;;N;;;;; +A56B;VAI SYLLABLE KAN;Lo;0;L;;;;;N;;;;; +A56C;VAI SYLLABLE NGGA;Lo;0;L;;;;;N;;;;; +A56D;VAI SYLLABLE GA;Lo;0;L;;;;;N;;;;; +A56E;VAI SYLLABLE MA;Lo;0;L;;;;;N;;;;; +A56F;VAI SYLLABLE NA;Lo;0;L;;;;;N;;;;; +A570;VAI SYLLABLE NYA;Lo;0;L;;;;;N;;;;; +A571;VAI SYLLABLE OO;Lo;0;L;;;;;N;;;;; +A572;VAI SYLLABLE OON;Lo;0;L;;;;;N;;;;; +A573;VAI SYLLABLE HOO;Lo;0;L;;;;;N;;;;; +A574;VAI SYLLABLE WOO;Lo;0;L;;;;;N;;;;; +A575;VAI SYLLABLE WOON;Lo;0;L;;;;;N;;;;; +A576;VAI SYLLABLE POO;Lo;0;L;;;;;N;;;;; +A577;VAI SYLLABLE BHOO;Lo;0;L;;;;;N;;;;; +A578;VAI SYLLABLE BOO;Lo;0;L;;;;;N;;;;; +A579;VAI SYLLABLE MBOO;Lo;0;L;;;;;N;;;;; +A57A;VAI SYLLABLE KPOO;Lo;0;L;;;;;N;;;;; +A57B;VAI SYLLABLE MGBOO;Lo;0;L;;;;;N;;;;; +A57C;VAI SYLLABLE GBOO;Lo;0;L;;;;;N;;;;; +A57D;VAI SYLLABLE FOO;Lo;0;L;;;;;N;;;;; +A57E;VAI SYLLABLE VOO;Lo;0;L;;;;;N;;;;; +A57F;VAI SYLLABLE TOO;Lo;0;L;;;;;N;;;;; +A580;VAI SYLLABLE THOO;Lo;0;L;;;;;N;;;;; +A581;VAI SYLLABLE DHOO;Lo;0;L;;;;;N;;;;; +A582;VAI SYLLABLE DHHOO;Lo;0;L;;;;;N;;;;; +A583;VAI SYLLABLE LOO;Lo;0;L;;;;;N;;;;; +A584;VAI SYLLABLE ROO;Lo;0;L;;;;;N;;;;; +A585;VAI SYLLABLE DOO;Lo;0;L;;;;;N;;;;; +A586;VAI SYLLABLE NDOO;Lo;0;L;;;;;N;;;;; +A587;VAI SYLLABLE SOO;Lo;0;L;;;;;N;;;;; +A588;VAI SYLLABLE SHOO;Lo;0;L;;;;;N;;;;; +A589;VAI SYLLABLE ZOO;Lo;0;L;;;;;N;;;;; +A58A;VAI SYLLABLE ZHOO;Lo;0;L;;;;;N;;;;; +A58B;VAI SYLLABLE COO;Lo;0;L;;;;;N;;;;; +A58C;VAI SYLLABLE JOO;Lo;0;L;;;;;N;;;;; +A58D;VAI SYLLABLE NJOO;Lo;0;L;;;;;N;;;;; +A58E;VAI SYLLABLE YOO;Lo;0;L;;;;;N;;;;; +A58F;VAI SYLLABLE KOO;Lo;0;L;;;;;N;;;;; +A590;VAI SYLLABLE NGGOO;Lo;0;L;;;;;N;;;;; +A591;VAI SYLLABLE GOO;Lo;0;L;;;;;N;;;;; +A592;VAI SYLLABLE MOO;Lo;0;L;;;;;N;;;;; +A593;VAI SYLLABLE NOO;Lo;0;L;;;;;N;;;;; +A594;VAI SYLLABLE NYOO;Lo;0;L;;;;;N;;;;; +A595;VAI SYLLABLE U;Lo;0;L;;;;;N;;;;; +A596;VAI SYLLABLE UN;Lo;0;L;;;;;N;;;;; +A597;VAI SYLLABLE HU;Lo;0;L;;;;;N;;;;; +A598;VAI SYLLABLE HUN;Lo;0;L;;;;;N;;;;; +A599;VAI SYLLABLE WU;Lo;0;L;;;;;N;;;;; +A59A;VAI SYLLABLE WUN;Lo;0;L;;;;;N;;;;; +A59B;VAI SYLLABLE PU;Lo;0;L;;;;;N;;;;; +A59C;VAI SYLLABLE BHU;Lo;0;L;;;;;N;;;;; +A59D;VAI SYLLABLE BU;Lo;0;L;;;;;N;;;;; +A59E;VAI SYLLABLE MBU;Lo;0;L;;;;;N;;;;; +A59F;VAI SYLLABLE KPU;Lo;0;L;;;;;N;;;;; +A5A0;VAI SYLLABLE MGBU;Lo;0;L;;;;;N;;;;; +A5A1;VAI SYLLABLE GBU;Lo;0;L;;;;;N;;;;; +A5A2;VAI SYLLABLE FU;Lo;0;L;;;;;N;;;;; +A5A3;VAI SYLLABLE VU;Lo;0;L;;;;;N;;;;; +A5A4;VAI SYLLABLE TU;Lo;0;L;;;;;N;;;;; +A5A5;VAI SYLLABLE THU;Lo;0;L;;;;;N;;;;; +A5A6;VAI SYLLABLE DHU;Lo;0;L;;;;;N;;;;; +A5A7;VAI SYLLABLE DHHU;Lo;0;L;;;;;N;;;;; +A5A8;VAI SYLLABLE LU;Lo;0;L;;;;;N;;;;; +A5A9;VAI SYLLABLE RU;Lo;0;L;;;;;N;;;;; +A5AA;VAI SYLLABLE DU;Lo;0;L;;;;;N;;;;; +A5AB;VAI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; +A5AC;VAI SYLLABLE SU;Lo;0;L;;;;;N;;;;; +A5AD;VAI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; +A5AE;VAI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; +A5AF;VAI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; +A5B0;VAI SYLLABLE CU;Lo;0;L;;;;;N;;;;; +A5B1;VAI SYLLABLE JU;Lo;0;L;;;;;N;;;;; +A5B2;VAI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; +A5B3;VAI SYLLABLE YU;Lo;0;L;;;;;N;;;;; +A5B4;VAI SYLLABLE KU;Lo;0;L;;;;;N;;;;; +A5B5;VAI SYLLABLE NGGU;Lo;0;L;;;;;N;;;;; +A5B6;VAI SYLLABLE GU;Lo;0;L;;;;;N;;;;; +A5B7;VAI SYLLABLE MU;Lo;0;L;;;;;N;;;;; +A5B8;VAI SYLLABLE NU;Lo;0;L;;;;;N;;;;; +A5B9;VAI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; +A5BA;VAI SYLLABLE O;Lo;0;L;;;;;N;;;;; +A5BB;VAI SYLLABLE ON;Lo;0;L;;;;;N;;;;; +A5BC;VAI SYLLABLE NGON;Lo;0;L;;;;;N;;;;; +A5BD;VAI SYLLABLE HO;Lo;0;L;;;;;N;;;;; +A5BE;VAI SYLLABLE HON;Lo;0;L;;;;;N;;;;; +A5BF;VAI SYLLABLE WO;Lo;0;L;;;;;N;;;;; +A5C0;VAI SYLLABLE WON;Lo;0;L;;;;;N;;;;; +A5C1;VAI SYLLABLE PO;Lo;0;L;;;;;N;;;;; +A5C2;VAI SYLLABLE BHO;Lo;0;L;;;;;N;;;;; +A5C3;VAI SYLLABLE BO;Lo;0;L;;;;;N;;;;; +A5C4;VAI SYLLABLE MBO;Lo;0;L;;;;;N;;;;; +A5C5;VAI SYLLABLE KPO;Lo;0;L;;;;;N;;;;; +A5C6;VAI SYLLABLE MGBO;Lo;0;L;;;;;N;;;;; +A5C7;VAI SYLLABLE GBO;Lo;0;L;;;;;N;;;;; +A5C8;VAI SYLLABLE GBON;Lo;0;L;;;;;N;;;;; +A5C9;VAI SYLLABLE FO;Lo;0;L;;;;;N;;;;; +A5CA;VAI SYLLABLE VO;Lo;0;L;;;;;N;;;;; +A5CB;VAI SYLLABLE TO;Lo;0;L;;;;;N;;;;; +A5CC;VAI SYLLABLE THO;Lo;0;L;;;;;N;;;;; +A5CD;VAI SYLLABLE DHO;Lo;0;L;;;;;N;;;;; +A5CE;VAI SYLLABLE DHHO;Lo;0;L;;;;;N;;;;; +A5CF;VAI SYLLABLE LO;Lo;0;L;;;;;N;;;;; +A5D0;VAI SYLLABLE RO;Lo;0;L;;;;;N;;;;; +A5D1;VAI SYLLABLE DO;Lo;0;L;;;;;N;;;;; +A5D2;VAI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; +A5D3;VAI SYLLABLE SO;Lo;0;L;;;;;N;;;;; +A5D4;VAI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; +A5D5;VAI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; +A5D6;VAI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; +A5D7;VAI SYLLABLE CO;Lo;0;L;;;;;N;;;;; +A5D8;VAI SYLLABLE JO;Lo;0;L;;;;;N;;;;; +A5D9;VAI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; +A5DA;VAI SYLLABLE YO;Lo;0;L;;;;;N;;;;; +A5DB;VAI SYLLABLE KO;Lo;0;L;;;;;N;;;;; +A5DC;VAI SYLLABLE NGGO;Lo;0;L;;;;;N;;;;; +A5DD;VAI SYLLABLE GO;Lo;0;L;;;;;N;;;;; +A5DE;VAI SYLLABLE MO;Lo;0;L;;;;;N;;;;; +A5DF;VAI SYLLABLE NO;Lo;0;L;;;;;N;;;;; +A5E0;VAI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; +A5E1;VAI SYLLABLE E;Lo;0;L;;;;;N;;;;; +A5E2;VAI SYLLABLE EN;Lo;0;L;;;;;N;;;;; +A5E3;VAI SYLLABLE NGEN;Lo;0;L;;;;;N;;;;; +A5E4;VAI SYLLABLE HE;Lo;0;L;;;;;N;;;;; +A5E5;VAI SYLLABLE HEN;Lo;0;L;;;;;N;;;;; +A5E6;VAI SYLLABLE WE;Lo;0;L;;;;;N;;;;; +A5E7;VAI SYLLABLE WEN;Lo;0;L;;;;;N;;;;; +A5E8;VAI SYLLABLE PE;Lo;0;L;;;;;N;;;;; +A5E9;VAI SYLLABLE BHE;Lo;0;L;;;;;N;;;;; +A5EA;VAI SYLLABLE BE;Lo;0;L;;;;;N;;;;; +A5EB;VAI SYLLABLE MBE;Lo;0;L;;;;;N;;;;; +A5EC;VAI SYLLABLE KPE;Lo;0;L;;;;;N;;;;; +A5ED;VAI SYLLABLE KPEN;Lo;0;L;;;;;N;;;;; +A5EE;VAI SYLLABLE MGBE;Lo;0;L;;;;;N;;;;; +A5EF;VAI SYLLABLE GBE;Lo;0;L;;;;;N;;;;; +A5F0;VAI SYLLABLE GBEN;Lo;0;L;;;;;N;;;;; +A5F1;VAI SYLLABLE FE;Lo;0;L;;;;;N;;;;; +A5F2;VAI SYLLABLE VE;Lo;0;L;;;;;N;;;;; +A5F3;VAI SYLLABLE TE;Lo;0;L;;;;;N;;;;; +A5F4;VAI SYLLABLE THE;Lo;0;L;;;;;N;;;;; +A5F5;VAI SYLLABLE DHE;Lo;0;L;;;;;N;;;;; +A5F6;VAI SYLLABLE DHHE;Lo;0;L;;;;;N;;;;; +A5F7;VAI SYLLABLE LE;Lo;0;L;;;;;N;;;;; +A5F8;VAI SYLLABLE RE;Lo;0;L;;;;;N;;;;; +A5F9;VAI SYLLABLE DE;Lo;0;L;;;;;N;;;;; +A5FA;VAI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; +A5FB;VAI SYLLABLE SE;Lo;0;L;;;;;N;;;;; +A5FC;VAI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; +A5FD;VAI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; +A5FE;VAI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; +A5FF;VAI SYLLABLE CE;Lo;0;L;;;;;N;;;;; +A600;VAI SYLLABLE JE;Lo;0;L;;;;;N;;;;; +A601;VAI SYLLABLE NJE;Lo;0;L;;;;;N;;;;; +A602;VAI SYLLABLE YE;Lo;0;L;;;;;N;;;;; +A603;VAI SYLLABLE KE;Lo;0;L;;;;;N;;;;; +A604;VAI SYLLABLE NGGE;Lo;0;L;;;;;N;;;;; +A605;VAI SYLLABLE NGGEN;Lo;0;L;;;;;N;;;;; +A606;VAI SYLLABLE GE;Lo;0;L;;;;;N;;;;; +A607;VAI SYLLABLE GEN;Lo;0;L;;;;;N;;;;; +A608;VAI SYLLABLE ME;Lo;0;L;;;;;N;;;;; +A609;VAI SYLLABLE NE;Lo;0;L;;;;;N;;;;; +A60A;VAI SYLLABLE NYE;Lo;0;L;;;;;N;;;;; +A60B;VAI SYLLABLE NG;Lo;0;L;;;;;N;;;;; +A60C;VAI SYLLABLE LENGTHENER;Lm;0;L;;;;;N;;;;; +A60D;VAI COMMA;Po;0;ON;;;;;N;;;;; +A60E;VAI FULL STOP;Po;0;ON;;;;;N;;;;; +A60F;VAI QUESTION MARK;Po;0;ON;;;;;N;;;;; +A610;VAI SYLLABLE NDOLE FA;Lo;0;L;;;;;N;;;;; +A611;VAI SYLLABLE NDOLE KA;Lo;0;L;;;;;N;;;;; +A612;VAI SYLLABLE NDOLE SOO;Lo;0;L;;;;;N;;;;; +A613;VAI SYMBOL FEENG;Lo;0;L;;;;;N;;;;; +A614;VAI SYMBOL KEENG;Lo;0;L;;;;;N;;;;; +A615;VAI SYMBOL TING;Lo;0;L;;;;;N;;;;; +A616;VAI SYMBOL NII;Lo;0;L;;;;;N;;;;; +A617;VAI SYMBOL BANG;Lo;0;L;;;;;N;;;;; +A618;VAI SYMBOL FAA;Lo;0;L;;;;;N;;;;; +A619;VAI SYMBOL TAA;Lo;0;L;;;;;N;;;;; +A61A;VAI SYMBOL DANG;Lo;0;L;;;;;N;;;;; +A61B;VAI SYMBOL DOONG;Lo;0;L;;;;;N;;;;; +A61C;VAI SYMBOL KUNG;Lo;0;L;;;;;N;;;;; +A61D;VAI SYMBOL TONG;Lo;0;L;;;;;N;;;;; +A61E;VAI SYMBOL DO-O;Lo;0;L;;;;;N;;;;; +A61F;VAI SYMBOL JONG;Lo;0;L;;;;;N;;;;; +A620;VAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A621;VAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A622;VAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A623;VAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A624;VAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A625;VAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A626;VAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A627;VAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A628;VAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A629;VAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A62A;VAI SYLLABLE NDOLE MA;Lo;0;L;;;;;N;;;;; +A62B;VAI SYLLABLE NDOLE DO;Lo;0;L;;;;;N;;;;; +A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641; +A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640 +A642;CYRILLIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;A643; +A643;CYRILLIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;A642;;A642 +A644;CYRILLIC CAPITAL LETTER REVERSED DZE;Lu;0;L;;;;;N;;;;A645; +A645;CYRILLIC SMALL LETTER REVERSED DZE;Ll;0;L;;;;;N;;;A644;;A644 +A646;CYRILLIC CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;A647; +A647;CYRILLIC SMALL LETTER IOTA;Ll;0;L;;;;;N;;;A646;;A646 +A648;CYRILLIC CAPITAL LETTER DJERV;Lu;0;L;;;;;N;;;;A649; +A649;CYRILLIC SMALL LETTER DJERV;Ll;0;L;;;;;N;;;A648;;A648 +A64A;CYRILLIC CAPITAL LETTER MONOGRAPH UK;Lu;0;L;;;;;N;;;;A64B; +A64B;CYRILLIC SMALL LETTER MONOGRAPH UK;Ll;0;L;;;;;N;;;A64A;;A64A +A64C;CYRILLIC CAPITAL LETTER BROAD OMEGA;Lu;0;L;;;;;N;;;;A64D; +A64D;CYRILLIC SMALL LETTER BROAD OMEGA;Ll;0;L;;;;;N;;;A64C;;A64C +A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F; +A64F;CYRILLIC SMALL LETTER NEUTRAL YER;Ll;0;L;;;;;N;;;A64E;;A64E +A650;CYRILLIC CAPITAL LETTER YERU WITH BACK YER;Lu;0;L;;;;;N;;;;A651; +A651;CYRILLIC SMALL LETTER YERU WITH BACK YER;Ll;0;L;;;;;N;;;A650;;A650 +A652;CYRILLIC CAPITAL LETTER IOTIFIED YAT;Lu;0;L;;;;;N;;;;A653; +A653;CYRILLIC SMALL LETTER IOTIFIED YAT;Ll;0;L;;;;;N;;;A652;;A652 +A654;CYRILLIC CAPITAL LETTER REVERSED YU;Lu;0;L;;;;;N;;;;A655; +A655;CYRILLIC SMALL LETTER REVERSED YU;Ll;0;L;;;;;N;;;A654;;A654 +A656;CYRILLIC CAPITAL LETTER IOTIFIED A;Lu;0;L;;;;;N;;;;A657; +A657;CYRILLIC SMALL LETTER IOTIFIED A;Ll;0;L;;;;;N;;;A656;;A656 +A658;CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A659; +A659;CYRILLIC SMALL LETTER CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A658;;A658 +A65A;CYRILLIC CAPITAL LETTER BLENDED YUS;Lu;0;L;;;;;N;;;;A65B; +A65B;CYRILLIC SMALL LETTER BLENDED YUS;Ll;0;L;;;;;N;;;A65A;;A65A +A65C;CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A65D; +A65D;CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A65C;;A65C +A65E;CYRILLIC CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;A65F; +A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E +A660;CYRILLIC CAPITAL LETTER REVERSED TSE;Lu;0;L;;;;;N;;;;A661; +A661;CYRILLIC SMALL LETTER REVERSED TSE;Ll;0;L;;;;;N;;;A660;;A660 +A662;CYRILLIC CAPITAL LETTER SOFT DE;Lu;0;L;;;;;N;;;;A663; +A663;CYRILLIC SMALL LETTER SOFT DE;Ll;0;L;;;;;N;;;A662;;A662 +A664;CYRILLIC CAPITAL LETTER SOFT EL;Lu;0;L;;;;;N;;;;A665; +A665;CYRILLIC SMALL LETTER SOFT EL;Ll;0;L;;;;;N;;;A664;;A664 +A666;CYRILLIC CAPITAL LETTER SOFT EM;Lu;0;L;;;;;N;;;;A667; +A667;CYRILLIC SMALL LETTER SOFT EM;Ll;0;L;;;;;N;;;A666;;A666 +A668;CYRILLIC CAPITAL LETTER MONOCULAR O;Lu;0;L;;;;;N;;;;A669; +A669;CYRILLIC SMALL LETTER MONOCULAR O;Ll;0;L;;;;;N;;;A668;;A668 +A66A;CYRILLIC CAPITAL LETTER BINOCULAR O;Lu;0;L;;;;;N;;;;A66B; +A66B;CYRILLIC SMALL LETTER BINOCULAR O;Ll;0;L;;;;;N;;;A66A;;A66A +A66C;CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O;Lu;0;L;;;;;N;;;;A66D; +A66D;CYRILLIC SMALL LETTER DOUBLE MONOCULAR O;Ll;0;L;;;;;N;;;A66C;;A66C +A66E;CYRILLIC LETTER MULTIOCULAR O;Lo;0;L;;;;;N;;;;; +A66F;COMBINING CYRILLIC VZMET;Mn;230;NSM;;;;;N;;;;; +A670;COMBINING CYRILLIC TEN MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; +A671;COMBINING CYRILLIC HUNDRED MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; +A672;COMBINING CYRILLIC THOUSAND MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; +A673;SLAVONIC ASTERISK;Po;0;ON;;;;;N;;;;; +A674;COMBINING CYRILLIC LETTER UKRAINIAN IE;Mn;230;NSM;;;;;N;;;;; +A675;COMBINING CYRILLIC LETTER I;Mn;230;NSM;;;;;N;;;;; +A676;COMBINING CYRILLIC LETTER YI;Mn;230;NSM;;;;;N;;;;; +A677;COMBINING CYRILLIC LETTER U;Mn;230;NSM;;;;;N;;;;; +A678;COMBINING CYRILLIC LETTER HARD SIGN;Mn;230;NSM;;;;;N;;;;; +A679;COMBINING CYRILLIC LETTER YERU;Mn;230;NSM;;;;;N;;;;; +A67A;COMBINING CYRILLIC LETTER SOFT SIGN;Mn;230;NSM;;;;;N;;;;; +A67B;COMBINING CYRILLIC LETTER OMEGA;Mn;230;NSM;;;;;N;;;;; +A67C;COMBINING CYRILLIC KAVYKA;Mn;230;NSM;;;;;N;;;;; +A67D;COMBINING CYRILLIC PAYEROK;Mn;230;NSM;;;;;N;;;;; +A67E;CYRILLIC KAVYKA;Po;0;ON;;;;;N;;;;; +A67F;CYRILLIC PAYEROK;Lm;0;ON;;;;;N;;;;; +A680;CYRILLIC CAPITAL LETTER DWE;Lu;0;L;;;;;N;;;;A681; +A681;CYRILLIC SMALL LETTER DWE;Ll;0;L;;;;;N;;;A680;;A680 +A682;CYRILLIC CAPITAL LETTER DZWE;Lu;0;L;;;;;N;;;;A683; +A683;CYRILLIC SMALL LETTER DZWE;Ll;0;L;;;;;N;;;A682;;A682 +A684;CYRILLIC CAPITAL LETTER ZHWE;Lu;0;L;;;;;N;;;;A685; +A685;CYRILLIC SMALL LETTER ZHWE;Ll;0;L;;;;;N;;;A684;;A684 +A686;CYRILLIC CAPITAL LETTER CCHE;Lu;0;L;;;;;N;;;;A687; +A687;CYRILLIC SMALL LETTER CCHE;Ll;0;L;;;;;N;;;A686;;A686 +A688;CYRILLIC CAPITAL LETTER DZZE;Lu;0;L;;;;;N;;;;A689; +A689;CYRILLIC SMALL LETTER DZZE;Ll;0;L;;;;;N;;;A688;;A688 +A68A;CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;A68B; +A68B;CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;A68A;;A68A +A68C;CYRILLIC CAPITAL LETTER TWE;Lu;0;L;;;;;N;;;;A68D; +A68D;CYRILLIC SMALL LETTER TWE;Ll;0;L;;;;;N;;;A68C;;A68C +A68E;CYRILLIC CAPITAL LETTER TSWE;Lu;0;L;;;;;N;;;;A68F; +A68F;CYRILLIC SMALL LETTER TSWE;Ll;0;L;;;;;N;;;A68E;;A68E +A690;CYRILLIC CAPITAL LETTER TSSE;Lu;0;L;;;;;N;;;;A691; +A691;CYRILLIC SMALL LETTER TSSE;Ll;0;L;;;;;N;;;A690;;A690 +A692;CYRILLIC CAPITAL LETTER TCHE;Lu;0;L;;;;;N;;;;A693; +A693;CYRILLIC SMALL LETTER TCHE;Ll;0;L;;;;;N;;;A692;;A692 +A694;CYRILLIC CAPITAL LETTER HWE;Lu;0;L;;;;;N;;;;A695; +A695;CYRILLIC SMALL LETTER HWE;Ll;0;L;;;;;N;;;A694;;A694 +A696;CYRILLIC CAPITAL LETTER SHWE;Lu;0;L;;;;;N;;;;A697; +A697;CYRILLIC SMALL LETTER SHWE;Ll;0;L;;;;;N;;;A696;;A696 +A698;CYRILLIC CAPITAL LETTER DOUBLE O;Lu;0;L;;;;;N;;;;A699; +A699;CYRILLIC SMALL LETTER DOUBLE O;Ll;0;L;;;;;N;;;A698;;A698 +A69A;CYRILLIC CAPITAL LETTER CROSSED O;Lu;0;L;;;;;N;;;;A69B; +A69B;CYRILLIC SMALL LETTER CROSSED O;Ll;0;L;;;;;N;;;A69A;;A69A +A69C;MODIFIER LETTER CYRILLIC HARD SIGN;Lm;0;L;<super> 044A;;;;N;;;;; +A69D;MODIFIER LETTER CYRILLIC SOFT SIGN;Lm;0;L;<super> 044C;;;;N;;;;; +A69E;COMBINING CYRILLIC LETTER EF;Mn;230;NSM;;;;;N;;;;; +A69F;COMBINING CYRILLIC LETTER IOTIFIED E;Mn;230;NSM;;;;;N;;;;; +A6A0;BAMUM LETTER A;Lo;0;L;;;;;N;;;;; +A6A1;BAMUM LETTER KA;Lo;0;L;;;;;N;;;;; +A6A2;BAMUM LETTER U;Lo;0;L;;;;;N;;;;; +A6A3;BAMUM LETTER KU;Lo;0;L;;;;;N;;;;; +A6A4;BAMUM LETTER EE;Lo;0;L;;;;;N;;;;; +A6A5;BAMUM LETTER REE;Lo;0;L;;;;;N;;;;; +A6A6;BAMUM LETTER TAE;Lo;0;L;;;;;N;;;;; +A6A7;BAMUM LETTER O;Lo;0;L;;;;;N;;;;; +A6A8;BAMUM LETTER NYI;Lo;0;L;;;;;N;;;;; +A6A9;BAMUM LETTER I;Lo;0;L;;;;;N;;;;; +A6AA;BAMUM LETTER LA;Lo;0;L;;;;;N;;;;; +A6AB;BAMUM LETTER PA;Lo;0;L;;;;;N;;;;; +A6AC;BAMUM LETTER RII;Lo;0;L;;;;;N;;;;; +A6AD;BAMUM LETTER RIEE;Lo;0;L;;;;;N;;;;; +A6AE;BAMUM LETTER LEEEE;Lo;0;L;;;;;N;;;;; +A6AF;BAMUM LETTER MEEEE;Lo;0;L;;;;;N;;;;; +A6B0;BAMUM LETTER TAA;Lo;0;L;;;;;N;;;;; +A6B1;BAMUM LETTER NDAA;Lo;0;L;;;;;N;;;;; +A6B2;BAMUM LETTER NJAEM;Lo;0;L;;;;;N;;;;; +A6B3;BAMUM LETTER M;Lo;0;L;;;;;N;;;;; +A6B4;BAMUM LETTER SUU;Lo;0;L;;;;;N;;;;; +A6B5;BAMUM LETTER MU;Lo;0;L;;;;;N;;;;; +A6B6;BAMUM LETTER SHII;Lo;0;L;;;;;N;;;;; +A6B7;BAMUM LETTER SI;Lo;0;L;;;;;N;;;;; +A6B8;BAMUM LETTER SHEUX;Lo;0;L;;;;;N;;;;; +A6B9;BAMUM LETTER SEUX;Lo;0;L;;;;;N;;;;; +A6BA;BAMUM LETTER KYEE;Lo;0;L;;;;;N;;;;; +A6BB;BAMUM LETTER KET;Lo;0;L;;;;;N;;;;; +A6BC;BAMUM LETTER NUAE;Lo;0;L;;;;;N;;;;; +A6BD;BAMUM LETTER NU;Lo;0;L;;;;;N;;;;; +A6BE;BAMUM LETTER NJUAE;Lo;0;L;;;;;N;;;;; +A6BF;BAMUM LETTER YOQ;Lo;0;L;;;;;N;;;;; +A6C0;BAMUM LETTER SHU;Lo;0;L;;;;;N;;;;; +A6C1;BAMUM LETTER YUQ;Lo;0;L;;;;;N;;;;; +A6C2;BAMUM LETTER YA;Lo;0;L;;;;;N;;;;; +A6C3;BAMUM LETTER NSHA;Lo;0;L;;;;;N;;;;; +A6C4;BAMUM LETTER KEUX;Lo;0;L;;;;;N;;;;; +A6C5;BAMUM LETTER PEUX;Lo;0;L;;;;;N;;;;; +A6C6;BAMUM LETTER NJEE;Lo;0;L;;;;;N;;;;; +A6C7;BAMUM LETTER NTEE;Lo;0;L;;;;;N;;;;; +A6C8;BAMUM LETTER PUE;Lo;0;L;;;;;N;;;;; +A6C9;BAMUM LETTER WUE;Lo;0;L;;;;;N;;;;; +A6CA;BAMUM LETTER PEE;Lo;0;L;;;;;N;;;;; +A6CB;BAMUM LETTER FEE;Lo;0;L;;;;;N;;;;; +A6CC;BAMUM LETTER RU;Lo;0;L;;;;;N;;;;; +A6CD;BAMUM LETTER LU;Lo;0;L;;;;;N;;;;; +A6CE;BAMUM LETTER MI;Lo;0;L;;;;;N;;;;; +A6CF;BAMUM LETTER NI;Lo;0;L;;;;;N;;;;; +A6D0;BAMUM LETTER REUX;Lo;0;L;;;;;N;;;;; +A6D1;BAMUM LETTER RAE;Lo;0;L;;;;;N;;;;; +A6D2;BAMUM LETTER KEN;Lo;0;L;;;;;N;;;;; +A6D3;BAMUM LETTER NGKWAEN;Lo;0;L;;;;;N;;;;; +A6D4;BAMUM LETTER NGGA;Lo;0;L;;;;;N;;;;; +A6D5;BAMUM LETTER NGA;Lo;0;L;;;;;N;;;;; +A6D6;BAMUM LETTER SHO;Lo;0;L;;;;;N;;;;; +A6D7;BAMUM LETTER PUAE;Lo;0;L;;;;;N;;;;; +A6D8;BAMUM LETTER FU;Lo;0;L;;;;;N;;;;; +A6D9;BAMUM LETTER FOM;Lo;0;L;;;;;N;;;;; +A6DA;BAMUM LETTER WA;Lo;0;L;;;;;N;;;;; +A6DB;BAMUM LETTER NA;Lo;0;L;;;;;N;;;;; +A6DC;BAMUM LETTER LI;Lo;0;L;;;;;N;;;;; +A6DD;BAMUM LETTER PI;Lo;0;L;;;;;N;;;;; +A6DE;BAMUM LETTER LOQ;Lo;0;L;;;;;N;;;;; +A6DF;BAMUM LETTER KO;Lo;0;L;;;;;N;;;;; +A6E0;BAMUM LETTER MBEN;Lo;0;L;;;;;N;;;;; +A6E1;BAMUM LETTER REN;Lo;0;L;;;;;N;;;;; +A6E2;BAMUM LETTER MEN;Lo;0;L;;;;;N;;;;; +A6E3;BAMUM LETTER MA;Lo;0;L;;;;;N;;;;; +A6E4;BAMUM LETTER TI;Lo;0;L;;;;;N;;;;; +A6E5;BAMUM LETTER KI;Lo;0;L;;;;;N;;;;; +A6E6;BAMUM LETTER MO;Nl;0;L;;;;1;N;;;;; +A6E7;BAMUM LETTER MBAA;Nl;0;L;;;;2;N;;;;; +A6E8;BAMUM LETTER TET;Nl;0;L;;;;3;N;;;;; +A6E9;BAMUM LETTER KPA;Nl;0;L;;;;4;N;;;;; +A6EA;BAMUM LETTER TEN;Nl;0;L;;;;5;N;;;;; +A6EB;BAMUM LETTER NTUU;Nl;0;L;;;;6;N;;;;; +A6EC;BAMUM LETTER SAMBA;Nl;0;L;;;;7;N;;;;; +A6ED;BAMUM LETTER FAAMAE;Nl;0;L;;;;8;N;;;;; +A6EE;BAMUM LETTER KOVUU;Nl;0;L;;;;9;N;;;;; +A6EF;BAMUM LETTER KOGHOM;Nl;0;L;;;;0;N;;;;; +A6F0;BAMUM COMBINING MARK KOQNDON;Mn;230;NSM;;;;;N;;;;; +A6F1;BAMUM COMBINING MARK TUKWENTIS;Mn;230;NSM;;;;;N;;;;; +A6F2;BAMUM NJAEMLI;Po;0;L;;;;;N;;;;; +A6F3;BAMUM FULL STOP;Po;0;L;;;;;N;;;;; +A6F4;BAMUM COLON;Po;0;L;;;;;N;;;;; +A6F5;BAMUM COMMA;Po;0;L;;;;;N;;;;; +A6F6;BAMUM SEMICOLON;Po;0;L;;;;;N;;;;; +A6F7;BAMUM QUESTION MARK;Po;0;L;;;;;N;;;;; +A700;MODIFIER LETTER CHINESE TONE YIN PING;Sk;0;ON;;;;;N;;;;; +A701;MODIFIER LETTER CHINESE TONE YANG PING;Sk;0;ON;;;;;N;;;;; +A702;MODIFIER LETTER CHINESE TONE YIN SHANG;Sk;0;ON;;;;;N;;;;; +A703;MODIFIER LETTER CHINESE TONE YANG SHANG;Sk;0;ON;;;;;N;;;;; +A704;MODIFIER LETTER CHINESE TONE YIN QU;Sk;0;ON;;;;;N;;;;; +A705;MODIFIER LETTER CHINESE TONE YANG QU;Sk;0;ON;;;;;N;;;;; +A706;MODIFIER LETTER CHINESE TONE YIN RU;Sk;0;ON;;;;;N;;;;; +A707;MODIFIER LETTER CHINESE TONE YANG RU;Sk;0;ON;;;;;N;;;;; +A708;MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A709;MODIFIER LETTER HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A70A;MODIFIER LETTER MID DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A70B;MODIFIER LETTER LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A70C;MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A70D;MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A70E;MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A70F;MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A710;MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A711;MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A712;MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A713;MODIFIER LETTER HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A714;MODIFIER LETTER MID LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A715;MODIFIER LETTER LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A716;MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A717;MODIFIER LETTER DOT VERTICAL BAR;Lm;0;ON;;;;;N;;;;; +A718;MODIFIER LETTER DOT SLASH;Lm;0;ON;;;;;N;;;;; +A719;MODIFIER LETTER DOT HORIZONTAL BAR;Lm;0;ON;;;;;N;;;;; +A71A;MODIFIER LETTER LOWER RIGHT CORNER ANGLE;Lm;0;ON;;;;;N;;;;; +A71B;MODIFIER LETTER RAISED UP ARROW;Lm;0;ON;;;;;N;;;;; +A71C;MODIFIER LETTER RAISED DOWN ARROW;Lm;0;ON;;;;;N;;;;; +A71D;MODIFIER LETTER RAISED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; +A71E;MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; +A71F;MODIFIER LETTER LOW INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; +A720;MODIFIER LETTER STRESS AND HIGH TONE;Sk;0;ON;;;;;N;;;;; +A721;MODIFIER LETTER STRESS AND LOW TONE;Sk;0;ON;;;;;N;;;;; +A722;LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF;Lu;0;L;;;;;N;;;;A723; +A723;LATIN SMALL LETTER EGYPTOLOGICAL ALEF;Ll;0;L;;;;;N;;;A722;;A722 +A724;LATIN CAPITAL LETTER EGYPTOLOGICAL AIN;Lu;0;L;;;;;N;;;;A725; +A725;LATIN SMALL LETTER EGYPTOLOGICAL AIN;Ll;0;L;;;;;N;;;A724;;A724 +A726;LATIN CAPITAL LETTER HENG;Lu;0;L;;;;;N;;;;A727; +A727;LATIN SMALL LETTER HENG;Ll;0;L;;;;;N;;;A726;;A726 +A728;LATIN CAPITAL LETTER TZ;Lu;0;L;;;;;N;;;;A729; +A729;LATIN SMALL LETTER TZ;Ll;0;L;;;;;N;;;A728;;A728 +A72A;LATIN CAPITAL LETTER TRESILLO;Lu;0;L;;;;;N;;;;A72B; +A72B;LATIN SMALL LETTER TRESILLO;Ll;0;L;;;;;N;;;A72A;;A72A +A72C;LATIN CAPITAL LETTER CUATRILLO;Lu;0;L;;;;;N;;;;A72D; +A72D;LATIN SMALL LETTER CUATRILLO;Ll;0;L;;;;;N;;;A72C;;A72C +A72E;LATIN CAPITAL LETTER CUATRILLO WITH COMMA;Lu;0;L;;;;;N;;;;A72F; +A72F;LATIN SMALL LETTER CUATRILLO WITH COMMA;Ll;0;L;;;;;N;;;A72E;;A72E +A730;LATIN LETTER SMALL CAPITAL F;Ll;0;L;;;;;N;;;;; +A731;LATIN LETTER SMALL CAPITAL S;Ll;0;L;;;;;N;;;;; +A732;LATIN CAPITAL LETTER AA;Lu;0;L;;;;;N;;;;A733; +A733;LATIN SMALL LETTER AA;Ll;0;L;;;;;N;;;A732;;A732 +A734;LATIN CAPITAL LETTER AO;Lu;0;L;;;;;N;;;;A735; +A735;LATIN SMALL LETTER AO;Ll;0;L;;;;;N;;;A734;;A734 +A736;LATIN CAPITAL LETTER AU;Lu;0;L;;;;;N;;;;A737; +A737;LATIN SMALL LETTER AU;Ll;0;L;;;;;N;;;A736;;A736 +A738;LATIN CAPITAL LETTER AV;Lu;0;L;;;;;N;;;;A739; +A739;LATIN SMALL LETTER AV;Ll;0;L;;;;;N;;;A738;;A738 +A73A;LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR;Lu;0;L;;;;;N;;;;A73B; +A73B;LATIN SMALL LETTER AV WITH HORIZONTAL BAR;Ll;0;L;;;;;N;;;A73A;;A73A +A73C;LATIN CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;A73D; +A73D;LATIN SMALL LETTER AY;Ll;0;L;;;;;N;;;A73C;;A73C +A73E;LATIN CAPITAL LETTER REVERSED C WITH DOT;Lu;0;L;;;;;N;;;;A73F; +A73F;LATIN SMALL LETTER REVERSED C WITH DOT;Ll;0;L;;;;;N;;;A73E;;A73E +A740;LATIN CAPITAL LETTER K WITH STROKE;Lu;0;L;;;;;N;;;;A741; +A741;LATIN SMALL LETTER K WITH STROKE;Ll;0;L;;;;;N;;;A740;;A740 +A742;LATIN CAPITAL LETTER K WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A743; +A743;LATIN SMALL LETTER K WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A742;;A742 +A744;LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A745; +A745;LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE;Ll;0;L;;;;;N;;;A744;;A744 +A746;LATIN CAPITAL LETTER BROKEN L;Lu;0;L;;;;;N;;;;A747; +A747;LATIN SMALL LETTER BROKEN L;Ll;0;L;;;;;N;;;A746;;A746 +A748;LATIN CAPITAL LETTER L WITH HIGH STROKE;Lu;0;L;;;;;N;;;;A749; +A749;LATIN SMALL LETTER L WITH HIGH STROKE;Ll;0;L;;;;;N;;;A748;;A748 +A74A;LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY;Lu;0;L;;;;;N;;;;A74B; +A74B;LATIN SMALL LETTER O WITH LONG STROKE OVERLAY;Ll;0;L;;;;;N;;;A74A;;A74A +A74C;LATIN CAPITAL LETTER O WITH LOOP;Lu;0;L;;;;;N;;;;A74D; +A74D;LATIN SMALL LETTER O WITH LOOP;Ll;0;L;;;;;N;;;A74C;;A74C +A74E;LATIN CAPITAL LETTER OO;Lu;0;L;;;;;N;;;;A74F; +A74F;LATIN SMALL LETTER OO;Ll;0;L;;;;;N;;;A74E;;A74E +A750;LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A751; +A751;LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A750;;A750 +A752;LATIN CAPITAL LETTER P WITH FLOURISH;Lu;0;L;;;;;N;;;;A753; +A753;LATIN SMALL LETTER P WITH FLOURISH;Ll;0;L;;;;;N;;;A752;;A752 +A754;LATIN CAPITAL LETTER P WITH SQUIRREL TAIL;Lu;0;L;;;;;N;;;;A755; +A755;LATIN SMALL LETTER P WITH SQUIRREL TAIL;Ll;0;L;;;;;N;;;A754;;A754 +A756;LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A757; +A757;LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A756;;A756 +A758;LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A759; +A759;LATIN SMALL LETTER Q WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A758;;A758 +A75A;LATIN CAPITAL LETTER R ROTUNDA;Lu;0;L;;;;;N;;;;A75B; +A75B;LATIN SMALL LETTER R ROTUNDA;Ll;0;L;;;;;N;;;A75A;;A75A +A75C;LATIN CAPITAL LETTER RUM ROTUNDA;Lu;0;L;;;;;N;;;;A75D; +A75D;LATIN SMALL LETTER RUM ROTUNDA;Ll;0;L;;;;;N;;;A75C;;A75C +A75E;LATIN CAPITAL LETTER V WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A75F; +A75F;LATIN SMALL LETTER V WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A75E;;A75E +A760;LATIN CAPITAL LETTER VY;Lu;0;L;;;;;N;;;;A761; +A761;LATIN SMALL LETTER VY;Ll;0;L;;;;;N;;;A760;;A760 +A762;LATIN CAPITAL LETTER VISIGOTHIC Z;Lu;0;L;;;;;N;;;;A763; +A763;LATIN SMALL LETTER VISIGOTHIC Z;Ll;0;L;;;;;N;;;A762;;A762 +A764;LATIN CAPITAL LETTER THORN WITH STROKE;Lu;0;L;;;;;N;;;;A765; +A765;LATIN SMALL LETTER THORN WITH STROKE;Ll;0;L;;;;;N;;;A764;;A764 +A766;LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A767; +A767;LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A766;;A766 +A768;LATIN CAPITAL LETTER VEND;Lu;0;L;;;;;N;;;;A769; +A769;LATIN SMALL LETTER VEND;Ll;0;L;;;;;N;;;A768;;A768 +A76A;LATIN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;A76B; +A76B;LATIN SMALL LETTER ET;Ll;0;L;;;;;N;;;A76A;;A76A +A76C;LATIN CAPITAL LETTER IS;Lu;0;L;;;;;N;;;;A76D; +A76D;LATIN SMALL LETTER IS;Ll;0;L;;;;;N;;;A76C;;A76C +A76E;LATIN CAPITAL LETTER CON;Lu;0;L;;;;;N;;;;A76F; +A76F;LATIN SMALL LETTER CON;Ll;0;L;;;;;N;;;A76E;;A76E +A770;MODIFIER LETTER US;Lm;0;L;<super> A76F;;;;N;;;;; +A771;LATIN SMALL LETTER DUM;Ll;0;L;;;;;N;;;;; +A772;LATIN SMALL LETTER LUM;Ll;0;L;;;;;N;;;;; +A773;LATIN SMALL LETTER MUM;Ll;0;L;;;;;N;;;;; +A774;LATIN SMALL LETTER NUM;Ll;0;L;;;;;N;;;;; +A775;LATIN SMALL LETTER RUM;Ll;0;L;;;;;N;;;;; +A776;LATIN LETTER SMALL CAPITAL RUM;Ll;0;L;;;;;N;;;;; +A777;LATIN SMALL LETTER TUM;Ll;0;L;;;;;N;;;;; +A778;LATIN SMALL LETTER UM;Ll;0;L;;;;;N;;;;; +A779;LATIN CAPITAL LETTER INSULAR D;Lu;0;L;;;;;N;;;;A77A; +A77A;LATIN SMALL LETTER INSULAR D;Ll;0;L;;;;;N;;;A779;;A779 +A77B;LATIN CAPITAL LETTER INSULAR F;Lu;0;L;;;;;N;;;;A77C; +A77C;LATIN SMALL LETTER INSULAR F;Ll;0;L;;;;;N;;;A77B;;A77B +A77D;LATIN CAPITAL LETTER INSULAR G;Lu;0;L;;;;;N;;;;1D79; +A77E;LATIN CAPITAL LETTER TURNED INSULAR G;Lu;0;L;;;;;N;;;;A77F; +A77F;LATIN SMALL LETTER TURNED INSULAR G;Ll;0;L;;;;;N;;;A77E;;A77E +A780;LATIN CAPITAL LETTER TURNED L;Lu;0;L;;;;;N;;;;A781; +A781;LATIN SMALL LETTER TURNED L;Ll;0;L;;;;;N;;;A780;;A780 +A782;LATIN CAPITAL LETTER INSULAR R;Lu;0;L;;;;;N;;;;A783; +A783;LATIN SMALL LETTER INSULAR R;Ll;0;L;;;;;N;;;A782;;A782 +A784;LATIN CAPITAL LETTER INSULAR S;Lu;0;L;;;;;N;;;;A785; +A785;LATIN SMALL LETTER INSULAR S;Ll;0;L;;;;;N;;;A784;;A784 +A786;LATIN CAPITAL LETTER INSULAR T;Lu;0;L;;;;;N;;;;A787; +A787;LATIN SMALL LETTER INSULAR T;Ll;0;L;;;;;N;;;A786;;A786 +A788;MODIFIER LETTER LOW CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;;;;; +A789;MODIFIER LETTER COLON;Sk;0;L;;;;;N;;;;; +A78A;MODIFIER LETTER SHORT EQUALS SIGN;Sk;0;L;;;;;N;;;;; +A78B;LATIN CAPITAL LETTER SALTILLO;Lu;0;L;;;;;N;;;;A78C; +A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B +A78D;LATIN CAPITAL LETTER TURNED H;Lu;0;L;;;;;N;;;;0265; +A78E;LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT;Ll;0;L;;;;;N;;;;; +A78F;LATIN LETTER SINOLOGICAL DOT;Lo;0;L;;;;;N;;;;; +A790;LATIN CAPITAL LETTER N WITH DESCENDER;Lu;0;L;;;;;N;;;;A791; +A791;LATIN SMALL LETTER N WITH DESCENDER;Ll;0;L;;;;;N;;;A790;;A790 +A792;LATIN CAPITAL LETTER C WITH BAR;Lu;0;L;;;;;N;;;;A793; +A793;LATIN SMALL LETTER C WITH BAR;Ll;0;L;;;;;N;;;A792;;A792 +A794;LATIN SMALL LETTER C WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +A795;LATIN SMALL LETTER H WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +A796;LATIN CAPITAL LETTER B WITH FLOURISH;Lu;0;L;;;;;N;;;;A797; +A797;LATIN SMALL LETTER B WITH FLOURISH;Ll;0;L;;;;;N;;;A796;;A796 +A798;LATIN CAPITAL LETTER F WITH STROKE;Lu;0;L;;;;;N;;;;A799; +A799;LATIN SMALL LETTER F WITH STROKE;Ll;0;L;;;;;N;;;A798;;A798 +A79A;LATIN CAPITAL LETTER VOLAPUK AE;Lu;0;L;;;;;N;;;;A79B; +A79B;LATIN SMALL LETTER VOLAPUK AE;Ll;0;L;;;;;N;;;A79A;;A79A +A79C;LATIN CAPITAL LETTER VOLAPUK OE;Lu;0;L;;;;;N;;;;A79D; +A79D;LATIN SMALL LETTER VOLAPUK OE;Ll;0;L;;;;;N;;;A79C;;A79C +A79E;LATIN CAPITAL LETTER VOLAPUK UE;Lu;0;L;;;;;N;;;;A79F; +A79F;LATIN SMALL LETTER VOLAPUK UE;Ll;0;L;;;;;N;;;A79E;;A79E +A7A0;LATIN CAPITAL LETTER G WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A1; +A7A1;LATIN SMALL LETTER G WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A0;;A7A0 +A7A2;LATIN CAPITAL LETTER K WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A3; +A7A3;LATIN SMALL LETTER K WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A2;;A7A2 +A7A4;LATIN CAPITAL LETTER N WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A5; +A7A5;LATIN SMALL LETTER N WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A4;;A7A4 +A7A6;LATIN CAPITAL LETTER R WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A7; +A7A7;LATIN SMALL LETTER R WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A6;;A7A6 +A7A8;LATIN CAPITAL LETTER S WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A9; +A7A9;LATIN SMALL LETTER S WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A8;;A7A8 +A7AA;LATIN CAPITAL LETTER H WITH HOOK;Lu;0;L;;;;;N;;;;0266; +A7AB;LATIN CAPITAL LETTER REVERSED OPEN E;Lu;0;L;;;;;N;;;;025C; +A7AC;LATIN CAPITAL LETTER SCRIPT G;Lu;0;L;;;;;N;;;;0261; +A7AD;LATIN CAPITAL LETTER L WITH BELT;Lu;0;L;;;;;N;;;;026C; +A7AE;LATIN CAPITAL LETTER SMALL CAPITAL I;Lu;0;L;;;;;N;;;;026A; +A7B0;LATIN CAPITAL LETTER TURNED K;Lu;0;L;;;;;N;;;;029E; +A7B1;LATIN CAPITAL LETTER TURNED T;Lu;0;L;;;;;N;;;;0287; +A7B2;LATIN CAPITAL LETTER J WITH CROSSED-TAIL;Lu;0;L;;;;;N;;;;029D; +A7B3;LATIN CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;AB53; +A7B4;LATIN CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;A7B5; +A7B5;LATIN SMALL LETTER BETA;Ll;0;L;;;;;N;;;A7B4;;A7B4 +A7B6;LATIN CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;A7B7; +A7B7;LATIN SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;A7B6;;A7B6 +A7F7;LATIN EPIGRAPHIC LETTER SIDEWAYS I;Lo;0;L;;;;;N;;;;; +A7F8;MODIFIER LETTER CAPITAL H WITH STROKE;Lm;0;L;<super> 0126;;;;N;;;;; +A7F9;MODIFIER LETTER SMALL LIGATURE OE;Lm;0;L;<super> 0153;;;;N;;;;; +A7FA;LATIN LETTER SMALL CAPITAL TURNED M;Ll;0;L;;;;;N;;;;; +A7FB;LATIN EPIGRAPHIC LETTER REVERSED F;Lo;0;L;;;;;N;;;;; +A7FC;LATIN EPIGRAPHIC LETTER REVERSED P;Lo;0;L;;;;;N;;;;; +A7FD;LATIN EPIGRAPHIC LETTER INVERTED M;Lo;0;L;;;;;N;;;;; +A7FE;LATIN EPIGRAPHIC LETTER I LONGA;Lo;0;L;;;;;N;;;;; +A7FF;LATIN EPIGRAPHIC LETTER ARCHAIC M;Lo;0;L;;;;;N;;;;; +A800;SYLOTI NAGRI LETTER A;Lo;0;L;;;;;N;;;;; +A801;SYLOTI NAGRI LETTER I;Lo;0;L;;;;;N;;;;; +A802;SYLOTI NAGRI SIGN DVISVARA;Mn;0;NSM;;;;;N;;;;; +A803;SYLOTI NAGRI LETTER U;Lo;0;L;;;;;N;;;;; +A804;SYLOTI NAGRI LETTER E;Lo;0;L;;;;;N;;;;; +A805;SYLOTI NAGRI LETTER O;Lo;0;L;;;;;N;;;;; +A806;SYLOTI NAGRI SIGN HASANTA;Mn;9;NSM;;;;;N;;;;; +A807;SYLOTI NAGRI LETTER KO;Lo;0;L;;;;;N;;;;; +A808;SYLOTI NAGRI LETTER KHO;Lo;0;L;;;;;N;;;;; +A809;SYLOTI NAGRI LETTER GO;Lo;0;L;;;;;N;;;;; +A80A;SYLOTI NAGRI LETTER GHO;Lo;0;L;;;;;N;;;;; +A80B;SYLOTI NAGRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +A80C;SYLOTI NAGRI LETTER CO;Lo;0;L;;;;;N;;;;; +A80D;SYLOTI NAGRI LETTER CHO;Lo;0;L;;;;;N;;;;; +A80E;SYLOTI NAGRI LETTER JO;Lo;0;L;;;;;N;;;;; +A80F;SYLOTI NAGRI LETTER JHO;Lo;0;L;;;;;N;;;;; +A810;SYLOTI NAGRI LETTER TTO;Lo;0;L;;;;;N;;;;; +A811;SYLOTI NAGRI LETTER TTHO;Lo;0;L;;;;;N;;;;; +A812;SYLOTI NAGRI LETTER DDO;Lo;0;L;;;;;N;;;;; +A813;SYLOTI NAGRI LETTER DDHO;Lo;0;L;;;;;N;;;;; +A814;SYLOTI NAGRI LETTER TO;Lo;0;L;;;;;N;;;;; +A815;SYLOTI NAGRI LETTER THO;Lo;0;L;;;;;N;;;;; +A816;SYLOTI NAGRI LETTER DO;Lo;0;L;;;;;N;;;;; +A817;SYLOTI NAGRI LETTER DHO;Lo;0;L;;;;;N;;;;; +A818;SYLOTI NAGRI LETTER NO;Lo;0;L;;;;;N;;;;; +A819;SYLOTI NAGRI LETTER PO;Lo;0;L;;;;;N;;;;; +A81A;SYLOTI NAGRI LETTER PHO;Lo;0;L;;;;;N;;;;; +A81B;SYLOTI NAGRI LETTER BO;Lo;0;L;;;;;N;;;;; +A81C;SYLOTI NAGRI LETTER BHO;Lo;0;L;;;;;N;;;;; +A81D;SYLOTI NAGRI LETTER MO;Lo;0;L;;;;;N;;;;; +A81E;SYLOTI NAGRI LETTER RO;Lo;0;L;;;;;N;;;;; +A81F;SYLOTI NAGRI LETTER LO;Lo;0;L;;;;;N;;;;; +A820;SYLOTI NAGRI LETTER RRO;Lo;0;L;;;;;N;;;;; +A821;SYLOTI NAGRI LETTER SO;Lo;0;L;;;;;N;;;;; +A822;SYLOTI NAGRI LETTER HO;Lo;0;L;;;;;N;;;;; +A823;SYLOTI NAGRI VOWEL SIGN A;Mc;0;L;;;;;N;;;;; +A824;SYLOTI NAGRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +A825;SYLOTI NAGRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +A826;SYLOTI NAGRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +A827;SYLOTI NAGRI VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +A828;SYLOTI NAGRI POETRY MARK-1;So;0;ON;;;;;N;;;;; +A829;SYLOTI NAGRI POETRY MARK-2;So;0;ON;;;;;N;;;;; +A82A;SYLOTI NAGRI POETRY MARK-3;So;0;ON;;;;;N;;;;; +A82B;SYLOTI NAGRI POETRY MARK-4;So;0;ON;;;;;N;;;;; +A830;NORTH INDIC FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; +A831;NORTH INDIC FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; +A832;NORTH INDIC FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +A833;NORTH INDIC FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; +A834;NORTH INDIC FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +A835;NORTH INDIC FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; +A836;NORTH INDIC QUARTER MARK;So;0;L;;;;;N;;;;; +A837;NORTH INDIC PLACEHOLDER MARK;So;0;L;;;;;N;;;;; +A838;NORTH INDIC RUPEE MARK;Sc;0;ET;;;;;N;;;;; +A839;NORTH INDIC QUANTITY MARK;So;0;ET;;;;;N;;;;; +A840;PHAGS-PA LETTER KA;Lo;0;L;;;;;N;;;;; +A841;PHAGS-PA LETTER KHA;Lo;0;L;;;;;N;;;;; +A842;PHAGS-PA LETTER GA;Lo;0;L;;;;;N;;;;; +A843;PHAGS-PA LETTER NGA;Lo;0;L;;;;;N;;;;; +A844;PHAGS-PA LETTER CA;Lo;0;L;;;;;N;;;;; +A845;PHAGS-PA LETTER CHA;Lo;0;L;;;;;N;;;;; +A846;PHAGS-PA LETTER JA;Lo;0;L;;;;;N;;;;; +A847;PHAGS-PA LETTER NYA;Lo;0;L;;;;;N;;;;; +A848;PHAGS-PA LETTER TA;Lo;0;L;;;;;N;;;;; +A849;PHAGS-PA LETTER THA;Lo;0;L;;;;;N;;;;; +A84A;PHAGS-PA LETTER DA;Lo;0;L;;;;;N;;;;; +A84B;PHAGS-PA LETTER NA;Lo;0;L;;;;;N;;;;; +A84C;PHAGS-PA LETTER PA;Lo;0;L;;;;;N;;;;; +A84D;PHAGS-PA LETTER PHA;Lo;0;L;;;;;N;;;;; +A84E;PHAGS-PA LETTER BA;Lo;0;L;;;;;N;;;;; +A84F;PHAGS-PA LETTER MA;Lo;0;L;;;;;N;;;;; +A850;PHAGS-PA LETTER TSA;Lo;0;L;;;;;N;;;;; +A851;PHAGS-PA LETTER TSHA;Lo;0;L;;;;;N;;;;; +A852;PHAGS-PA LETTER DZA;Lo;0;L;;;;;N;;;;; +A853;PHAGS-PA LETTER WA;Lo;0;L;;;;;N;;;;; +A854;PHAGS-PA LETTER ZHA;Lo;0;L;;;;;N;;;;; +A855;PHAGS-PA LETTER ZA;Lo;0;L;;;;;N;;;;; +A856;PHAGS-PA LETTER SMALL A;Lo;0;L;;;;;N;;;;; +A857;PHAGS-PA LETTER YA;Lo;0;L;;;;;N;;;;; +A858;PHAGS-PA LETTER RA;Lo;0;L;;;;;N;;;;; +A859;PHAGS-PA LETTER LA;Lo;0;L;;;;;N;;;;; +A85A;PHAGS-PA LETTER SHA;Lo;0;L;;;;;N;;;;; +A85B;PHAGS-PA LETTER SA;Lo;0;L;;;;;N;;;;; +A85C;PHAGS-PA LETTER HA;Lo;0;L;;;;;N;;;;; +A85D;PHAGS-PA LETTER A;Lo;0;L;;;;;N;;;;; +A85E;PHAGS-PA LETTER I;Lo;0;L;;;;;N;;;;; +A85F;PHAGS-PA LETTER U;Lo;0;L;;;;;N;;;;; +A860;PHAGS-PA LETTER E;Lo;0;L;;;;;N;;;;; +A861;PHAGS-PA LETTER O;Lo;0;L;;;;;N;;;;; +A862;PHAGS-PA LETTER QA;Lo;0;L;;;;;N;;;;; +A863;PHAGS-PA LETTER XA;Lo;0;L;;;;;N;;;;; +A864;PHAGS-PA LETTER FA;Lo;0;L;;;;;N;;;;; +A865;PHAGS-PA LETTER GGA;Lo;0;L;;;;;N;;;;; +A866;PHAGS-PA LETTER EE;Lo;0;L;;;;;N;;;;; +A867;PHAGS-PA SUBJOINED LETTER WA;Lo;0;L;;;;;N;;;;; +A868;PHAGS-PA SUBJOINED LETTER YA;Lo;0;L;;;;;N;;;;; +A869;PHAGS-PA LETTER TTA;Lo;0;L;;;;;N;;;;; +A86A;PHAGS-PA LETTER TTHA;Lo;0;L;;;;;N;;;;; +A86B;PHAGS-PA LETTER DDA;Lo;0;L;;;;;N;;;;; +A86C;PHAGS-PA LETTER NNA;Lo;0;L;;;;;N;;;;; +A86D;PHAGS-PA LETTER ALTERNATE YA;Lo;0;L;;;;;N;;;;; +A86E;PHAGS-PA LETTER VOICELESS SHA;Lo;0;L;;;;;N;;;;; +A86F;PHAGS-PA LETTER VOICED HA;Lo;0;L;;;;;N;;;;; +A870;PHAGS-PA LETTER ASPIRATED FA;Lo;0;L;;;;;N;;;;; +A871;PHAGS-PA SUBJOINED LETTER RA;Lo;0;L;;;;;N;;;;; +A872;PHAGS-PA SUPERFIXED LETTER RA;Lo;0;L;;;;;N;;;;; +A873;PHAGS-PA LETTER CANDRABINDU;Lo;0;L;;;;;N;;;;; +A874;PHAGS-PA SINGLE HEAD MARK;Po;0;ON;;;;;N;;;;; +A875;PHAGS-PA DOUBLE HEAD MARK;Po;0;ON;;;;;N;;;;; +A876;PHAGS-PA MARK SHAD;Po;0;ON;;;;;N;;;;; +A877;PHAGS-PA MARK DOUBLE SHAD;Po;0;ON;;;;;N;;;;; +A880;SAURASHTRA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +A881;SAURASHTRA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +A882;SAURASHTRA LETTER A;Lo;0;L;;;;;N;;;;; +A883;SAURASHTRA LETTER AA;Lo;0;L;;;;;N;;;;; +A884;SAURASHTRA LETTER I;Lo;0;L;;;;;N;;;;; +A885;SAURASHTRA LETTER II;Lo;0;L;;;;;N;;;;; +A886;SAURASHTRA LETTER U;Lo;0;L;;;;;N;;;;; +A887;SAURASHTRA LETTER UU;Lo;0;L;;;;;N;;;;; +A888;SAURASHTRA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +A889;SAURASHTRA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +A88A;SAURASHTRA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +A88B;SAURASHTRA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +A88C;SAURASHTRA LETTER E;Lo;0;L;;;;;N;;;;; +A88D;SAURASHTRA LETTER EE;Lo;0;L;;;;;N;;;;; +A88E;SAURASHTRA LETTER AI;Lo;0;L;;;;;N;;;;; +A88F;SAURASHTRA LETTER O;Lo;0;L;;;;;N;;;;; +A890;SAURASHTRA LETTER OO;Lo;0;L;;;;;N;;;;; +A891;SAURASHTRA LETTER AU;Lo;0;L;;;;;N;;;;; +A892;SAURASHTRA LETTER KA;Lo;0;L;;;;;N;;;;; +A893;SAURASHTRA LETTER KHA;Lo;0;L;;;;;N;;;;; +A894;SAURASHTRA LETTER GA;Lo;0;L;;;;;N;;;;; +A895;SAURASHTRA LETTER GHA;Lo;0;L;;;;;N;;;;; +A896;SAURASHTRA LETTER NGA;Lo;0;L;;;;;N;;;;; +A897;SAURASHTRA LETTER CA;Lo;0;L;;;;;N;;;;; +A898;SAURASHTRA LETTER CHA;Lo;0;L;;;;;N;;;;; +A899;SAURASHTRA LETTER JA;Lo;0;L;;;;;N;;;;; +A89A;SAURASHTRA LETTER JHA;Lo;0;L;;;;;N;;;;; +A89B;SAURASHTRA LETTER NYA;Lo;0;L;;;;;N;;;;; +A89C;SAURASHTRA LETTER TTA;Lo;0;L;;;;;N;;;;; +A89D;SAURASHTRA LETTER TTHA;Lo;0;L;;;;;N;;;;; +A89E;SAURASHTRA LETTER DDA;Lo;0;L;;;;;N;;;;; +A89F;SAURASHTRA LETTER DDHA;Lo;0;L;;;;;N;;;;; +A8A0;SAURASHTRA LETTER NNA;Lo;0;L;;;;;N;;;;; +A8A1;SAURASHTRA LETTER TA;Lo;0;L;;;;;N;;;;; +A8A2;SAURASHTRA LETTER THA;Lo;0;L;;;;;N;;;;; +A8A3;SAURASHTRA LETTER DA;Lo;0;L;;;;;N;;;;; +A8A4;SAURASHTRA LETTER DHA;Lo;0;L;;;;;N;;;;; +A8A5;SAURASHTRA LETTER NA;Lo;0;L;;;;;N;;;;; +A8A6;SAURASHTRA LETTER PA;Lo;0;L;;;;;N;;;;; +A8A7;SAURASHTRA LETTER PHA;Lo;0;L;;;;;N;;;;; +A8A8;SAURASHTRA LETTER BA;Lo;0;L;;;;;N;;;;; +A8A9;SAURASHTRA LETTER BHA;Lo;0;L;;;;;N;;;;; +A8AA;SAURASHTRA LETTER MA;Lo;0;L;;;;;N;;;;; +A8AB;SAURASHTRA LETTER YA;Lo;0;L;;;;;N;;;;; +A8AC;SAURASHTRA LETTER RA;Lo;0;L;;;;;N;;;;; +A8AD;SAURASHTRA LETTER LA;Lo;0;L;;;;;N;;;;; +A8AE;SAURASHTRA LETTER VA;Lo;0;L;;;;;N;;;;; +A8AF;SAURASHTRA LETTER SHA;Lo;0;L;;;;;N;;;;; +A8B0;SAURASHTRA LETTER SSA;Lo;0;L;;;;;N;;;;; +A8B1;SAURASHTRA LETTER SA;Lo;0;L;;;;;N;;;;; +A8B2;SAURASHTRA LETTER HA;Lo;0;L;;;;;N;;;;; +A8B3;SAURASHTRA LETTER LLA;Lo;0;L;;;;;N;;;;; +A8B4;SAURASHTRA CONSONANT SIGN HAARU;Mc;0;L;;;;;N;;;;; +A8B5;SAURASHTRA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +A8B6;SAURASHTRA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +A8B7;SAURASHTRA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +A8B8;SAURASHTRA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +A8B9;SAURASHTRA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +A8BA;SAURASHTRA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +A8BB;SAURASHTRA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +A8BC;SAURASHTRA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; +A8BD;SAURASHTRA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; +A8BE;SAURASHTRA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +A8BF;SAURASHTRA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +A8C0;SAURASHTRA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +A8C1;SAURASHTRA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +A8C2;SAURASHTRA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +A8C3;SAURASHTRA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +A8C4;SAURASHTRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +A8C5;SAURASHTRA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +A8CE;SAURASHTRA DANDA;Po;0;L;;;;;N;;;;; +A8CF;SAURASHTRA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +A8D0;SAURASHTRA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A8D1;SAURASHTRA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A8D2;SAURASHTRA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A8D3;SAURASHTRA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A8D4;SAURASHTRA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A8D5;SAURASHTRA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A8D6;SAURASHTRA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A8D7;SAURASHTRA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A8D8;SAURASHTRA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A8D9;SAURASHTRA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A8E0;COMBINING DEVANAGARI DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; +A8E1;COMBINING DEVANAGARI DIGIT ONE;Mn;230;NSM;;;;;N;;;;; +A8E2;COMBINING DEVANAGARI DIGIT TWO;Mn;230;NSM;;;;;N;;;;; +A8E3;COMBINING DEVANAGARI DIGIT THREE;Mn;230;NSM;;;;;N;;;;; +A8E4;COMBINING DEVANAGARI DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; +A8E5;COMBINING DEVANAGARI DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; +A8E6;COMBINING DEVANAGARI DIGIT SIX;Mn;230;NSM;;;;;N;;;;; +A8E7;COMBINING DEVANAGARI DIGIT SEVEN;Mn;230;NSM;;;;;N;;;;; +A8E8;COMBINING DEVANAGARI DIGIT EIGHT;Mn;230;NSM;;;;;N;;;;; +A8E9;COMBINING DEVANAGARI DIGIT NINE;Mn;230;NSM;;;;;N;;;;; +A8EA;COMBINING DEVANAGARI LETTER A;Mn;230;NSM;;;;;N;;;;; +A8EB;COMBINING DEVANAGARI LETTER U;Mn;230;NSM;;;;;N;;;;; +A8EC;COMBINING DEVANAGARI LETTER KA;Mn;230;NSM;;;;;N;;;;; +A8ED;COMBINING DEVANAGARI LETTER NA;Mn;230;NSM;;;;;N;;;;; +A8EE;COMBINING DEVANAGARI LETTER PA;Mn;230;NSM;;;;;N;;;;; +A8EF;COMBINING DEVANAGARI LETTER RA;Mn;230;NSM;;;;;N;;;;; +A8F0;COMBINING DEVANAGARI LETTER VI;Mn;230;NSM;;;;;N;;;;; +A8F1;COMBINING DEVANAGARI SIGN AVAGRAHA;Mn;230;NSM;;;;;N;;;;; +A8F2;DEVANAGARI SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; +A8F3;DEVANAGARI SIGN CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; +A8F4;DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; +A8F5;DEVANAGARI SIGN CANDRABINDU TWO;Lo;0;L;;;;;N;;;;; +A8F6;DEVANAGARI SIGN CANDRABINDU THREE;Lo;0;L;;;;;N;;;;; +A8F7;DEVANAGARI SIGN CANDRABINDU AVAGRAHA;Lo;0;L;;;;;N;;;;; +A8F8;DEVANAGARI SIGN PUSHPIKA;Po;0;L;;;;;N;;;;; +A8F9;DEVANAGARI GAP FILLER;Po;0;L;;;;;N;;;;; +A8FA;DEVANAGARI CARET;Po;0;L;;;;;N;;;;; +A8FB;DEVANAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;; +A8FC;DEVANAGARI SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +A8FD;DEVANAGARI JAIN OM;Lo;0;L;;;;;N;;;;; +A900;KAYAH LI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A901;KAYAH LI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A902;KAYAH LI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A903;KAYAH LI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A904;KAYAH LI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A905;KAYAH LI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A906;KAYAH LI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A907;KAYAH LI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A908;KAYAH LI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A909;KAYAH LI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A90A;KAYAH LI LETTER KA;Lo;0;L;;;;;N;;;;; +A90B;KAYAH LI LETTER KHA;Lo;0;L;;;;;N;;;;; +A90C;KAYAH LI LETTER GA;Lo;0;L;;;;;N;;;;; +A90D;KAYAH LI LETTER NGA;Lo;0;L;;;;;N;;;;; +A90E;KAYAH LI LETTER SA;Lo;0;L;;;;;N;;;;; +A90F;KAYAH LI LETTER SHA;Lo;0;L;;;;;N;;;;; +A910;KAYAH LI LETTER ZA;Lo;0;L;;;;;N;;;;; +A911;KAYAH LI LETTER NYA;Lo;0;L;;;;;N;;;;; +A912;KAYAH LI LETTER TA;Lo;0;L;;;;;N;;;;; +A913;KAYAH LI LETTER HTA;Lo;0;L;;;;;N;;;;; +A914;KAYAH LI LETTER NA;Lo;0;L;;;;;N;;;;; +A915;KAYAH LI LETTER PA;Lo;0;L;;;;;N;;;;; +A916;KAYAH LI LETTER PHA;Lo;0;L;;;;;N;;;;; +A917;KAYAH LI LETTER MA;Lo;0;L;;;;;N;;;;; +A918;KAYAH LI LETTER DA;Lo;0;L;;;;;N;;;;; +A919;KAYAH LI LETTER BA;Lo;0;L;;;;;N;;;;; +A91A;KAYAH LI LETTER RA;Lo;0;L;;;;;N;;;;; +A91B;KAYAH LI LETTER YA;Lo;0;L;;;;;N;;;;; +A91C;KAYAH LI LETTER LA;Lo;0;L;;;;;N;;;;; +A91D;KAYAH LI LETTER WA;Lo;0;L;;;;;N;;;;; +A91E;KAYAH LI LETTER THA;Lo;0;L;;;;;N;;;;; +A91F;KAYAH LI LETTER HA;Lo;0;L;;;;;N;;;;; +A920;KAYAH LI LETTER VA;Lo;0;L;;;;;N;;;;; +A921;KAYAH LI LETTER CA;Lo;0;L;;;;;N;;;;; +A922;KAYAH LI LETTER A;Lo;0;L;;;;;N;;;;; +A923;KAYAH LI LETTER OE;Lo;0;L;;;;;N;;;;; +A924;KAYAH LI LETTER I;Lo;0;L;;;;;N;;;;; +A925;KAYAH LI LETTER OO;Lo;0;L;;;;;N;;;;; +A926;KAYAH LI VOWEL UE;Mn;0;NSM;;;;;N;;;;; +A927;KAYAH LI VOWEL E;Mn;0;NSM;;;;;N;;;;; +A928;KAYAH LI VOWEL U;Mn;0;NSM;;;;;N;;;;; +A929;KAYAH LI VOWEL EE;Mn;0;NSM;;;;;N;;;;; +A92A;KAYAH LI VOWEL O;Mn;0;NSM;;;;;N;;;;; +A92B;KAYAH LI TONE PLOPHU;Mn;220;NSM;;;;;N;;;;; +A92C;KAYAH LI TONE CALYA;Mn;220;NSM;;;;;N;;;;; +A92D;KAYAH LI TONE CALYA PLOPHU;Mn;220;NSM;;;;;N;;;;; +A92E;KAYAH LI SIGN CWI;Po;0;L;;;;;N;;;;; +A92F;KAYAH LI SIGN SHYA;Po;0;L;;;;;N;;;;; +A930;REJANG LETTER KA;Lo;0;L;;;;;N;;;;; +A931;REJANG LETTER GA;Lo;0;L;;;;;N;;;;; +A932;REJANG LETTER NGA;Lo;0;L;;;;;N;;;;; +A933;REJANG LETTER TA;Lo;0;L;;;;;N;;;;; +A934;REJANG LETTER DA;Lo;0;L;;;;;N;;;;; +A935;REJANG LETTER NA;Lo;0;L;;;;;N;;;;; +A936;REJANG LETTER PA;Lo;0;L;;;;;N;;;;; +A937;REJANG LETTER BA;Lo;0;L;;;;;N;;;;; +A938;REJANG LETTER MA;Lo;0;L;;;;;N;;;;; +A939;REJANG LETTER CA;Lo;0;L;;;;;N;;;;; +A93A;REJANG LETTER JA;Lo;0;L;;;;;N;;;;; +A93B;REJANG LETTER NYA;Lo;0;L;;;;;N;;;;; +A93C;REJANG LETTER SA;Lo;0;L;;;;;N;;;;; +A93D;REJANG LETTER RA;Lo;0;L;;;;;N;;;;; +A93E;REJANG LETTER LA;Lo;0;L;;;;;N;;;;; +A93F;REJANG LETTER YA;Lo;0;L;;;;;N;;;;; +A940;REJANG LETTER WA;Lo;0;L;;;;;N;;;;; +A941;REJANG LETTER HA;Lo;0;L;;;;;N;;;;; +A942;REJANG LETTER MBA;Lo;0;L;;;;;N;;;;; +A943;REJANG LETTER NGGA;Lo;0;L;;;;;N;;;;; +A944;REJANG LETTER NDA;Lo;0;L;;;;;N;;;;; +A945;REJANG LETTER NYJA;Lo;0;L;;;;;N;;;;; +A946;REJANG LETTER A;Lo;0;L;;;;;N;;;;; +A947;REJANG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +A948;REJANG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +A949;REJANG VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +A94A;REJANG VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +A94B;REJANG VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +A94C;REJANG VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +A94D;REJANG VOWEL SIGN EU;Mn;0;NSM;;;;;N;;;;; +A94E;REJANG VOWEL SIGN EA;Mn;0;NSM;;;;;N;;;;; +A94F;REJANG CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +A950;REJANG CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +A951;REJANG CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +A952;REJANG CONSONANT SIGN H;Mc;0;L;;;;;N;;;;; +A953;REJANG VIRAMA;Mc;9;L;;;;;N;;;;; +A95F;REJANG SECTION MARK;Po;0;L;;;;;N;;;;; +A960;HANGUL CHOSEONG TIKEUT-MIEUM;Lo;0;L;;;;;N;;;;; +A961;HANGUL CHOSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; +A962;HANGUL CHOSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; +A963;HANGUL CHOSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; +A964;HANGUL CHOSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; +A965;HANGUL CHOSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +A966;HANGUL CHOSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; +A967;HANGUL CHOSEONG RIEUL-SSANGTIKEUT;Lo;0;L;;;;;N;;;;; +A968;HANGUL CHOSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; +A969;HANGUL CHOSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; +A96A;HANGUL CHOSEONG RIEUL-SSANGPIEUP;Lo;0;L;;;;;N;;;;; +A96B;HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +A96C;HANGUL CHOSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; +A96D;HANGUL CHOSEONG RIEUL-CIEUC;Lo;0;L;;;;;N;;;;; +A96E;HANGUL CHOSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; +A96F;HANGUL CHOSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; +A970;HANGUL CHOSEONG MIEUM-TIKEUT;Lo;0;L;;;;;N;;;;; +A971;HANGUL CHOSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; +A972;HANGUL CHOSEONG PIEUP-SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; +A973;HANGUL CHOSEONG PIEUP-KHIEUKH;Lo;0;L;;;;;N;;;;; +A974;HANGUL CHOSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; +A975;HANGUL CHOSEONG SSANGSIOS-PIEUP;Lo;0;L;;;;;N;;;;; +A976;HANGUL CHOSEONG IEUNG-RIEUL;Lo;0;L;;;;;N;;;;; +A977;HANGUL CHOSEONG IEUNG-HIEUH;Lo;0;L;;;;;N;;;;; +A978;HANGUL CHOSEONG SSANGCIEUC-HIEUH;Lo;0;L;;;;;N;;;;; +A979;HANGUL CHOSEONG SSANGTHIEUTH;Lo;0;L;;;;;N;;;;; +A97A;HANGUL CHOSEONG PHIEUPH-HIEUH;Lo;0;L;;;;;N;;;;; +A97B;HANGUL CHOSEONG HIEUH-SIOS;Lo;0;L;;;;;N;;;;; +A97C;HANGUL CHOSEONG SSANGYEORINHIEUH;Lo;0;L;;;;;N;;;;; +A980;JAVANESE SIGN PANYANGGA;Mn;0;NSM;;;;;N;;;;; +A981;JAVANESE SIGN CECAK;Mn;0;NSM;;;;;N;;;;; +A982;JAVANESE SIGN LAYAR;Mn;0;NSM;;;;;N;;;;; +A983;JAVANESE SIGN WIGNYAN;Mc;0;L;;;;;N;;;;; +A984;JAVANESE LETTER A;Lo;0;L;;;;;N;;;;; +A985;JAVANESE LETTER I KAWI;Lo;0;L;;;;;N;;;;; +A986;JAVANESE LETTER I;Lo;0;L;;;;;N;;;;; +A987;JAVANESE LETTER II;Lo;0;L;;;;;N;;;;; +A988;JAVANESE LETTER U;Lo;0;L;;;;;N;;;;; +A989;JAVANESE LETTER PA CEREK;Lo;0;L;;;;;N;;;;; +A98A;JAVANESE LETTER NGA LELET;Lo;0;L;;;;;N;;;;; +A98B;JAVANESE LETTER NGA LELET RASWADI;Lo;0;L;;;;;N;;;;; +A98C;JAVANESE LETTER E;Lo;0;L;;;;;N;;;;; +A98D;JAVANESE LETTER AI;Lo;0;L;;;;;N;;;;; +A98E;JAVANESE LETTER O;Lo;0;L;;;;;N;;;;; +A98F;JAVANESE LETTER KA;Lo;0;L;;;;;N;;;;; +A990;JAVANESE LETTER KA SASAK;Lo;0;L;;;;;N;;;;; +A991;JAVANESE LETTER KA MURDA;Lo;0;L;;;;;N;;;;; +A992;JAVANESE LETTER GA;Lo;0;L;;;;;N;;;;; +A993;JAVANESE LETTER GA MURDA;Lo;0;L;;;;;N;;;;; +A994;JAVANESE LETTER NGA;Lo;0;L;;;;;N;;;;; +A995;JAVANESE LETTER CA;Lo;0;L;;;;;N;;;;; +A996;JAVANESE LETTER CA MURDA;Lo;0;L;;;;;N;;;;; +A997;JAVANESE LETTER JA;Lo;0;L;;;;;N;;;;; +A998;JAVANESE LETTER NYA MURDA;Lo;0;L;;;;;N;;;;; +A999;JAVANESE LETTER JA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A99A;JAVANESE LETTER NYA;Lo;0;L;;;;;N;;;;; +A99B;JAVANESE LETTER TTA;Lo;0;L;;;;;N;;;;; +A99C;JAVANESE LETTER TTA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A99D;JAVANESE LETTER DDA;Lo;0;L;;;;;N;;;;; +A99E;JAVANESE LETTER DDA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A99F;JAVANESE LETTER NA MURDA;Lo;0;L;;;;;N;;;;; +A9A0;JAVANESE LETTER TA;Lo;0;L;;;;;N;;;;; +A9A1;JAVANESE LETTER TA MURDA;Lo;0;L;;;;;N;;;;; +A9A2;JAVANESE LETTER DA;Lo;0;L;;;;;N;;;;; +A9A3;JAVANESE LETTER DA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A9A4;JAVANESE LETTER NA;Lo;0;L;;;;;N;;;;; +A9A5;JAVANESE LETTER PA;Lo;0;L;;;;;N;;;;; +A9A6;JAVANESE LETTER PA MURDA;Lo;0;L;;;;;N;;;;; +A9A7;JAVANESE LETTER BA;Lo;0;L;;;;;N;;;;; +A9A8;JAVANESE LETTER BA MURDA;Lo;0;L;;;;;N;;;;; +A9A9;JAVANESE LETTER MA;Lo;0;L;;;;;N;;;;; +A9AA;JAVANESE LETTER YA;Lo;0;L;;;;;N;;;;; +A9AB;JAVANESE LETTER RA;Lo;0;L;;;;;N;;;;; +A9AC;JAVANESE LETTER RA AGUNG;Lo;0;L;;;;;N;;;;; +A9AD;JAVANESE LETTER LA;Lo;0;L;;;;;N;;;;; +A9AE;JAVANESE LETTER WA;Lo;0;L;;;;;N;;;;; +A9AF;JAVANESE LETTER SA MURDA;Lo;0;L;;;;;N;;;;; +A9B0;JAVANESE LETTER SA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A9B1;JAVANESE LETTER SA;Lo;0;L;;;;;N;;;;; +A9B2;JAVANESE LETTER HA;Lo;0;L;;;;;N;;;;; +A9B3;JAVANESE SIGN CECAK TELU;Mn;7;NSM;;;;;N;;;;; +A9B4;JAVANESE VOWEL SIGN TARUNG;Mc;0;L;;;;;N;;;;; +A9B5;JAVANESE VOWEL SIGN TOLONG;Mc;0;L;;;;;N;;;;; +A9B6;JAVANESE VOWEL SIGN WULU;Mn;0;NSM;;;;;N;;;;; +A9B7;JAVANESE VOWEL SIGN WULU MELIK;Mn;0;NSM;;;;;N;;;;; +A9B8;JAVANESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; +A9B9;JAVANESE VOWEL SIGN SUKU MENDUT;Mn;0;NSM;;;;;N;;;;; +A9BA;JAVANESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; +A9BB;JAVANESE VOWEL SIGN DIRGA MURE;Mc;0;L;;;;;N;;;;; +A9BC;JAVANESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; +A9BD;JAVANESE CONSONANT SIGN KERET;Mc;0;L;;;;;N;;;;; +A9BE;JAVANESE CONSONANT SIGN PENGKAL;Mc;0;L;;;;;N;;;;; +A9BF;JAVANESE CONSONANT SIGN CAKRA;Mc;0;L;;;;;N;;;;; +A9C0;JAVANESE PANGKON;Mc;9;L;;;;;N;;;;; +A9C1;JAVANESE LEFT RERENGGAN;Po;0;L;;;;;N;;;;; +A9C2;JAVANESE RIGHT RERENGGAN;Po;0;L;;;;;N;;;;; +A9C3;JAVANESE PADA ANDAP;Po;0;L;;;;;N;;;;; +A9C4;JAVANESE PADA MADYA;Po;0;L;;;;;N;;;;; +A9C5;JAVANESE PADA LUHUR;Po;0;L;;;;;N;;;;; +A9C6;JAVANESE PADA WINDU;Po;0;L;;;;;N;;;;; +A9C7;JAVANESE PADA PANGKAT;Po;0;L;;;;;N;;;;; +A9C8;JAVANESE PADA LINGSA;Po;0;L;;;;;N;;;;; +A9C9;JAVANESE PADA LUNGSI;Po;0;L;;;;;N;;;;; +A9CA;JAVANESE PADA ADEG;Po;0;L;;;;;N;;;;; +A9CB;JAVANESE PADA ADEG ADEG;Po;0;L;;;;;N;;;;; +A9CC;JAVANESE PADA PISELEH;Po;0;L;;;;;N;;;;; +A9CD;JAVANESE TURNED PADA PISELEH;Po;0;L;;;;;N;;;;; +A9CF;JAVANESE PANGRANGKEP;Lm;0;L;;;;;N;;;;; +A9D0;JAVANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A9D1;JAVANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A9D2;JAVANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A9D3;JAVANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A9D4;JAVANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A9D5;JAVANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A9D6;JAVANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A9D7;JAVANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A9D8;JAVANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A9D9;JAVANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A9DE;JAVANESE PADA TIRTA TUMETES;Po;0;L;;;;;N;;;;; +A9DF;JAVANESE PADA ISEN-ISEN;Po;0;L;;;;;N;;;;; +A9E0;MYANMAR LETTER SHAN GHA;Lo;0;L;;;;;N;;;;; +A9E1;MYANMAR LETTER SHAN CHA;Lo;0;L;;;;;N;;;;; +A9E2;MYANMAR LETTER SHAN JHA;Lo;0;L;;;;;N;;;;; +A9E3;MYANMAR LETTER SHAN NNA;Lo;0;L;;;;;N;;;;; +A9E4;MYANMAR LETTER SHAN BHA;Lo;0;L;;;;;N;;;;; +A9E5;MYANMAR SIGN SHAN SAW;Mn;0;NSM;;;;;N;;;;; +A9E6;MYANMAR MODIFIER LETTER SHAN REDUPLICATION;Lm;0;L;;;;;N;;;;; +A9E7;MYANMAR LETTER TAI LAING NYA;Lo;0;L;;;;;N;;;;; +A9E8;MYANMAR LETTER TAI LAING FA;Lo;0;L;;;;;N;;;;; +A9E9;MYANMAR LETTER TAI LAING GA;Lo;0;L;;;;;N;;;;; +A9EA;MYANMAR LETTER TAI LAING GHA;Lo;0;L;;;;;N;;;;; +A9EB;MYANMAR LETTER TAI LAING JA;Lo;0;L;;;;;N;;;;; +A9EC;MYANMAR LETTER TAI LAING JHA;Lo;0;L;;;;;N;;;;; +A9ED;MYANMAR LETTER TAI LAING DDA;Lo;0;L;;;;;N;;;;; +A9EE;MYANMAR LETTER TAI LAING DDHA;Lo;0;L;;;;;N;;;;; +A9EF;MYANMAR LETTER TAI LAING NNA;Lo;0;L;;;;;N;;;;; +A9F0;MYANMAR TAI LAING DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A9F1;MYANMAR TAI LAING DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A9F2;MYANMAR TAI LAING DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A9F3;MYANMAR TAI LAING DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A9F4;MYANMAR TAI LAING DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A9F5;MYANMAR TAI LAING DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A9F6;MYANMAR TAI LAING DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A9F7;MYANMAR TAI LAING DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A9F8;MYANMAR TAI LAING DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A9F9;MYANMAR TAI LAING DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A9FA;MYANMAR LETTER TAI LAING LLA;Lo;0;L;;;;;N;;;;; +A9FB;MYANMAR LETTER TAI LAING DA;Lo;0;L;;;;;N;;;;; +A9FC;MYANMAR LETTER TAI LAING DHA;Lo;0;L;;;;;N;;;;; +A9FD;MYANMAR LETTER TAI LAING BA;Lo;0;L;;;;;N;;;;; +A9FE;MYANMAR LETTER TAI LAING BHA;Lo;0;L;;;;;N;;;;; +AA00;CHAM LETTER A;Lo;0;L;;;;;N;;;;; +AA01;CHAM LETTER I;Lo;0;L;;;;;N;;;;; +AA02;CHAM LETTER U;Lo;0;L;;;;;N;;;;; +AA03;CHAM LETTER E;Lo;0;L;;;;;N;;;;; +AA04;CHAM LETTER AI;Lo;0;L;;;;;N;;;;; +AA05;CHAM LETTER O;Lo;0;L;;;;;N;;;;; +AA06;CHAM LETTER KA;Lo;0;L;;;;;N;;;;; +AA07;CHAM LETTER KHA;Lo;0;L;;;;;N;;;;; +AA08;CHAM LETTER GA;Lo;0;L;;;;;N;;;;; +AA09;CHAM LETTER GHA;Lo;0;L;;;;;N;;;;; +AA0A;CHAM LETTER NGUE;Lo;0;L;;;;;N;;;;; +AA0B;CHAM LETTER NGA;Lo;0;L;;;;;N;;;;; +AA0C;CHAM LETTER CHA;Lo;0;L;;;;;N;;;;; +AA0D;CHAM LETTER CHHA;Lo;0;L;;;;;N;;;;; +AA0E;CHAM LETTER JA;Lo;0;L;;;;;N;;;;; +AA0F;CHAM LETTER JHA;Lo;0;L;;;;;N;;;;; +AA10;CHAM LETTER NHUE;Lo;0;L;;;;;N;;;;; +AA11;CHAM LETTER NHA;Lo;0;L;;;;;N;;;;; +AA12;CHAM LETTER NHJA;Lo;0;L;;;;;N;;;;; +AA13;CHAM LETTER TA;Lo;0;L;;;;;N;;;;; +AA14;CHAM LETTER THA;Lo;0;L;;;;;N;;;;; +AA15;CHAM LETTER DA;Lo;0;L;;;;;N;;;;; +AA16;CHAM LETTER DHA;Lo;0;L;;;;;N;;;;; +AA17;CHAM LETTER NUE;Lo;0;L;;;;;N;;;;; +AA18;CHAM LETTER NA;Lo;0;L;;;;;N;;;;; +AA19;CHAM LETTER DDA;Lo;0;L;;;;;N;;;;; +AA1A;CHAM LETTER PA;Lo;0;L;;;;;N;;;;; +AA1B;CHAM LETTER PPA;Lo;0;L;;;;;N;;;;; +AA1C;CHAM LETTER PHA;Lo;0;L;;;;;N;;;;; +AA1D;CHAM LETTER BA;Lo;0;L;;;;;N;;;;; +AA1E;CHAM LETTER BHA;Lo;0;L;;;;;N;;;;; +AA1F;CHAM LETTER MUE;Lo;0;L;;;;;N;;;;; +AA20;CHAM LETTER MA;Lo;0;L;;;;;N;;;;; +AA21;CHAM LETTER BBA;Lo;0;L;;;;;N;;;;; +AA22;CHAM LETTER YA;Lo;0;L;;;;;N;;;;; +AA23;CHAM LETTER RA;Lo;0;L;;;;;N;;;;; +AA24;CHAM LETTER LA;Lo;0;L;;;;;N;;;;; +AA25;CHAM LETTER VA;Lo;0;L;;;;;N;;;;; +AA26;CHAM LETTER SSA;Lo;0;L;;;;;N;;;;; +AA27;CHAM LETTER SA;Lo;0;L;;;;;N;;;;; +AA28;CHAM LETTER HA;Lo;0;L;;;;;N;;;;; +AA29;CHAM VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +AA2A;CHAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +AA2B;CHAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +AA2C;CHAM VOWEL SIGN EI;Mn;0;NSM;;;;;N;;;;; +AA2D;CHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +AA2E;CHAM VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +AA2F;CHAM VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +AA30;CHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +AA31;CHAM VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +AA32;CHAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +AA33;CHAM CONSONANT SIGN YA;Mc;0;L;;;;;N;;;;; +AA34;CHAM CONSONANT SIGN RA;Mc;0;L;;;;;N;;;;; +AA35;CHAM CONSONANT SIGN LA;Mn;0;NSM;;;;;N;;;;; +AA36;CHAM CONSONANT SIGN WA;Mn;0;NSM;;;;;N;;;;; +AA40;CHAM LETTER FINAL K;Lo;0;L;;;;;N;;;;; +AA41;CHAM LETTER FINAL G;Lo;0;L;;;;;N;;;;; +AA42;CHAM LETTER FINAL NG;Lo;0;L;;;;;N;;;;; +AA43;CHAM CONSONANT SIGN FINAL NG;Mn;0;NSM;;;;;N;;;;; +AA44;CHAM LETTER FINAL CH;Lo;0;L;;;;;N;;;;; +AA45;CHAM LETTER FINAL T;Lo;0;L;;;;;N;;;;; +AA46;CHAM LETTER FINAL N;Lo;0;L;;;;;N;;;;; +AA47;CHAM LETTER FINAL P;Lo;0;L;;;;;N;;;;; +AA48;CHAM LETTER FINAL Y;Lo;0;L;;;;;N;;;;; +AA49;CHAM LETTER FINAL R;Lo;0;L;;;;;N;;;;; +AA4A;CHAM LETTER FINAL L;Lo;0;L;;;;;N;;;;; +AA4B;CHAM LETTER FINAL SS;Lo;0;L;;;;;N;;;;; +AA4C;CHAM CONSONANT SIGN FINAL M;Mn;0;NSM;;;;;N;;;;; +AA4D;CHAM CONSONANT SIGN FINAL H;Mc;0;L;;;;;N;;;;; +AA50;CHAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +AA51;CHAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +AA52;CHAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +AA53;CHAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +AA54;CHAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +AA55;CHAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +AA56;CHAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +AA57;CHAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +AA58;CHAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +AA59;CHAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +AA5C;CHAM PUNCTUATION SPIRAL;Po;0;L;;;;;N;;;;; +AA5D;CHAM PUNCTUATION DANDA;Po;0;L;;;;;N;;;;; +AA5E;CHAM PUNCTUATION DOUBLE DANDA;Po;0;L;;;;;N;;;;; +AA5F;CHAM PUNCTUATION TRIPLE DANDA;Po;0;L;;;;;N;;;;; +AA60;MYANMAR LETTER KHAMTI GA;Lo;0;L;;;;;N;;;;; +AA61;MYANMAR LETTER KHAMTI CA;Lo;0;L;;;;;N;;;;; +AA62;MYANMAR LETTER KHAMTI CHA;Lo;0;L;;;;;N;;;;; +AA63;MYANMAR LETTER KHAMTI JA;Lo;0;L;;;;;N;;;;; +AA64;MYANMAR LETTER KHAMTI JHA;Lo;0;L;;;;;N;;;;; +AA65;MYANMAR LETTER KHAMTI NYA;Lo;0;L;;;;;N;;;;; +AA66;MYANMAR LETTER KHAMTI TTA;Lo;0;L;;;;;N;;;;; +AA67;MYANMAR LETTER KHAMTI TTHA;Lo;0;L;;;;;N;;;;; +AA68;MYANMAR LETTER KHAMTI DDA;Lo;0;L;;;;;N;;;;; +AA69;MYANMAR LETTER KHAMTI DDHA;Lo;0;L;;;;;N;;;;; +AA6A;MYANMAR LETTER KHAMTI DHA;Lo;0;L;;;;;N;;;;; +AA6B;MYANMAR LETTER KHAMTI NA;Lo;0;L;;;;;N;;;;; +AA6C;MYANMAR LETTER KHAMTI SA;Lo;0;L;;;;;N;;;;; +AA6D;MYANMAR LETTER KHAMTI HA;Lo;0;L;;;;;N;;;;; +AA6E;MYANMAR LETTER KHAMTI HHA;Lo;0;L;;;;;N;;;;; +AA6F;MYANMAR LETTER KHAMTI FA;Lo;0;L;;;;;N;;;;; +AA70;MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION;Lm;0;L;;;;;N;;;;; +AA71;MYANMAR LETTER KHAMTI XA;Lo;0;L;;;;;N;;;;; +AA72;MYANMAR LETTER KHAMTI ZA;Lo;0;L;;;;;N;;;;; +AA73;MYANMAR LETTER KHAMTI RA;Lo;0;L;;;;;N;;;;; +AA74;MYANMAR LOGOGRAM KHAMTI OAY;Lo;0;L;;;;;N;;;;; +AA75;MYANMAR LOGOGRAM KHAMTI QN;Lo;0;L;;;;;N;;;;; +AA76;MYANMAR LOGOGRAM KHAMTI HM;Lo;0;L;;;;;N;;;;; +AA77;MYANMAR SYMBOL AITON EXCLAMATION;So;0;L;;;;;N;;;;; +AA78;MYANMAR SYMBOL AITON ONE;So;0;L;;;;;N;;;;; +AA79;MYANMAR SYMBOL AITON TWO;So;0;L;;;;;N;;;;; +AA7A;MYANMAR LETTER AITON RA;Lo;0;L;;;;;N;;;;; +AA7B;MYANMAR SIGN PAO KAREN TONE;Mc;0;L;;;;;N;;;;; +AA7C;MYANMAR SIGN TAI LAING TONE-2;Mn;0;NSM;;;;;N;;;;; +AA7D;MYANMAR SIGN TAI LAING TONE-5;Mc;0;L;;;;;N;;;;; +AA7E;MYANMAR LETTER SHWE PALAUNG CHA;Lo;0;L;;;;;N;;;;; +AA7F;MYANMAR LETTER SHWE PALAUNG SHA;Lo;0;L;;;;;N;;;;; +AA80;TAI VIET LETTER LOW KO;Lo;0;L;;;;;N;;;;; +AA81;TAI VIET LETTER HIGH KO;Lo;0;L;;;;;N;;;;; +AA82;TAI VIET LETTER LOW KHO;Lo;0;L;;;;;N;;;;; +AA83;TAI VIET LETTER HIGH KHO;Lo;0;L;;;;;N;;;;; +AA84;TAI VIET LETTER LOW KHHO;Lo;0;L;;;;;N;;;;; +AA85;TAI VIET LETTER HIGH KHHO;Lo;0;L;;;;;N;;;;; +AA86;TAI VIET LETTER LOW GO;Lo;0;L;;;;;N;;;;; +AA87;TAI VIET LETTER HIGH GO;Lo;0;L;;;;;N;;;;; +AA88;TAI VIET LETTER LOW NGO;Lo;0;L;;;;;N;;;;; +AA89;TAI VIET LETTER HIGH NGO;Lo;0;L;;;;;N;;;;; +AA8A;TAI VIET LETTER LOW CO;Lo;0;L;;;;;N;;;;; +AA8B;TAI VIET LETTER HIGH CO;Lo;0;L;;;;;N;;;;; +AA8C;TAI VIET LETTER LOW CHO;Lo;0;L;;;;;N;;;;; +AA8D;TAI VIET LETTER HIGH CHO;Lo;0;L;;;;;N;;;;; +AA8E;TAI VIET LETTER LOW SO;Lo;0;L;;;;;N;;;;; +AA8F;TAI VIET LETTER HIGH SO;Lo;0;L;;;;;N;;;;; +AA90;TAI VIET LETTER LOW NYO;Lo;0;L;;;;;N;;;;; +AA91;TAI VIET LETTER HIGH NYO;Lo;0;L;;;;;N;;;;; +AA92;TAI VIET LETTER LOW DO;Lo;0;L;;;;;N;;;;; +AA93;TAI VIET LETTER HIGH DO;Lo;0;L;;;;;N;;;;; +AA94;TAI VIET LETTER LOW TO;Lo;0;L;;;;;N;;;;; +AA95;TAI VIET LETTER HIGH TO;Lo;0;L;;;;;N;;;;; +AA96;TAI VIET LETTER LOW THO;Lo;0;L;;;;;N;;;;; +AA97;TAI VIET LETTER HIGH THO;Lo;0;L;;;;;N;;;;; +AA98;TAI VIET LETTER LOW NO;Lo;0;L;;;;;N;;;;; +AA99;TAI VIET LETTER HIGH NO;Lo;0;L;;;;;N;;;;; +AA9A;TAI VIET LETTER LOW BO;Lo;0;L;;;;;N;;;;; +AA9B;TAI VIET LETTER HIGH BO;Lo;0;L;;;;;N;;;;; +AA9C;TAI VIET LETTER LOW PO;Lo;0;L;;;;;N;;;;; +AA9D;TAI VIET LETTER HIGH PO;Lo;0;L;;;;;N;;;;; +AA9E;TAI VIET LETTER LOW PHO;Lo;0;L;;;;;N;;;;; +AA9F;TAI VIET LETTER HIGH PHO;Lo;0;L;;;;;N;;;;; +AAA0;TAI VIET LETTER LOW FO;Lo;0;L;;;;;N;;;;; +AAA1;TAI VIET LETTER HIGH FO;Lo;0;L;;;;;N;;;;; +AAA2;TAI VIET LETTER LOW MO;Lo;0;L;;;;;N;;;;; +AAA3;TAI VIET LETTER HIGH MO;Lo;0;L;;;;;N;;;;; +AAA4;TAI VIET LETTER LOW YO;Lo;0;L;;;;;N;;;;; +AAA5;TAI VIET LETTER HIGH YO;Lo;0;L;;;;;N;;;;; +AAA6;TAI VIET LETTER LOW RO;Lo;0;L;;;;;N;;;;; +AAA7;TAI VIET LETTER HIGH RO;Lo;0;L;;;;;N;;;;; +AAA8;TAI VIET LETTER LOW LO;Lo;0;L;;;;;N;;;;; +AAA9;TAI VIET LETTER HIGH LO;Lo;0;L;;;;;N;;;;; +AAAA;TAI VIET LETTER LOW VO;Lo;0;L;;;;;N;;;;; +AAAB;TAI VIET LETTER HIGH VO;Lo;0;L;;;;;N;;;;; +AAAC;TAI VIET LETTER LOW HO;Lo;0;L;;;;;N;;;;; +AAAD;TAI VIET LETTER HIGH HO;Lo;0;L;;;;;N;;;;; +AAAE;TAI VIET LETTER LOW O;Lo;0;L;;;;;N;;;;; +AAAF;TAI VIET LETTER HIGH O;Lo;0;L;;;;;N;;;;; +AAB0;TAI VIET MAI KANG;Mn;230;NSM;;;;;N;;;;; +AAB1;TAI VIET VOWEL AA;Lo;0;L;;;;;N;;;;; +AAB2;TAI VIET VOWEL I;Mn;230;NSM;;;;;N;;;;; +AAB3;TAI VIET VOWEL UE;Mn;230;NSM;;;;;N;;;;; +AAB4;TAI VIET VOWEL U;Mn;220;NSM;;;;;N;;;;; +AAB5;TAI VIET VOWEL E;Lo;0;L;;;;;N;;;;; +AAB6;TAI VIET VOWEL O;Lo;0;L;;;;;N;;;;; +AAB7;TAI VIET MAI KHIT;Mn;230;NSM;;;;;N;;;;; +AAB8;TAI VIET VOWEL IA;Mn;230;NSM;;;;;N;;;;; +AAB9;TAI VIET VOWEL UEA;Lo;0;L;;;;;N;;;;; +AABA;TAI VIET VOWEL UA;Lo;0;L;;;;;N;;;;; +AABB;TAI VIET VOWEL AUE;Lo;0;L;;;;;N;;;;; +AABC;TAI VIET VOWEL AY;Lo;0;L;;;;;N;;;;; +AABD;TAI VIET VOWEL AN;Lo;0;L;;;;;N;;;;; +AABE;TAI VIET VOWEL AM;Mn;230;NSM;;;;;N;;;;; +AABF;TAI VIET TONE MAI EK;Mn;230;NSM;;;;;N;;;;; +AAC0;TAI VIET TONE MAI NUENG;Lo;0;L;;;;;N;;;;; +AAC1;TAI VIET TONE MAI THO;Mn;230;NSM;;;;;N;;;;; +AAC2;TAI VIET TONE MAI SONG;Lo;0;L;;;;;N;;;;; +AADB;TAI VIET SYMBOL KON;Lo;0;L;;;;;N;;;;; +AADC;TAI VIET SYMBOL NUENG;Lo;0;L;;;;;N;;;;; +AADD;TAI VIET SYMBOL SAM;Lm;0;L;;;;;N;;;;; +AADE;TAI VIET SYMBOL HO HOI;Po;0;L;;;;;N;;;;; +AADF;TAI VIET SYMBOL KOI KOI;Po;0;L;;;;;N;;;;; +AAE0;MEETEI MAYEK LETTER E;Lo;0;L;;;;;N;;;;; +AAE1;MEETEI MAYEK LETTER O;Lo;0;L;;;;;N;;;;; +AAE2;MEETEI MAYEK LETTER CHA;Lo;0;L;;;;;N;;;;; +AAE3;MEETEI MAYEK LETTER NYA;Lo;0;L;;;;;N;;;;; +AAE4;MEETEI MAYEK LETTER TTA;Lo;0;L;;;;;N;;;;; +AAE5;MEETEI MAYEK LETTER TTHA;Lo;0;L;;;;;N;;;;; +AAE6;MEETEI MAYEK LETTER DDA;Lo;0;L;;;;;N;;;;; +AAE7;MEETEI MAYEK LETTER DDHA;Lo;0;L;;;;;N;;;;; +AAE8;MEETEI MAYEK LETTER NNA;Lo;0;L;;;;;N;;;;; +AAE9;MEETEI MAYEK LETTER SHA;Lo;0;L;;;;;N;;;;; +AAEA;MEETEI MAYEK LETTER SSA;Lo;0;L;;;;;N;;;;; +AAEB;MEETEI MAYEK VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +AAEC;MEETEI MAYEK VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +AAED;MEETEI MAYEK VOWEL SIGN AAI;Mn;0;NSM;;;;;N;;;;; +AAEE;MEETEI MAYEK VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +AAEF;MEETEI MAYEK VOWEL SIGN AAU;Mc;0;L;;;;;N;;;;; +AAF0;MEETEI MAYEK CHEIKHAN;Po;0;L;;;;;N;;;;; +AAF1;MEETEI MAYEK AHANG KHUDAM;Po;0;L;;;;;N;;;;; +AAF2;MEETEI MAYEK ANJI;Lo;0;L;;;;;N;;;;; +AAF3;MEETEI MAYEK SYLLABLE REPETITION MARK;Lm;0;L;;;;;N;;;;; +AAF4;MEETEI MAYEK WORD REPETITION MARK;Lm;0;L;;;;;N;;;;; +AAF5;MEETEI MAYEK VOWEL SIGN VISARGA;Mc;0;L;;;;;N;;;;; +AAF6;MEETEI MAYEK VIRAMA;Mn;9;NSM;;;;;N;;;;; +AB01;ETHIOPIC SYLLABLE TTHU;Lo;0;L;;;;;N;;;;; +AB02;ETHIOPIC SYLLABLE TTHI;Lo;0;L;;;;;N;;;;; +AB03;ETHIOPIC SYLLABLE TTHAA;Lo;0;L;;;;;N;;;;; +AB04;ETHIOPIC SYLLABLE TTHEE;Lo;0;L;;;;;N;;;;; +AB05;ETHIOPIC SYLLABLE TTHE;Lo;0;L;;;;;N;;;;; +AB06;ETHIOPIC SYLLABLE TTHO;Lo;0;L;;;;;N;;;;; +AB09;ETHIOPIC SYLLABLE DDHU;Lo;0;L;;;;;N;;;;; +AB0A;ETHIOPIC SYLLABLE DDHI;Lo;0;L;;;;;N;;;;; +AB0B;ETHIOPIC SYLLABLE DDHAA;Lo;0;L;;;;;N;;;;; +AB0C;ETHIOPIC SYLLABLE DDHEE;Lo;0;L;;;;;N;;;;; +AB0D;ETHIOPIC SYLLABLE DDHE;Lo;0;L;;;;;N;;;;; +AB0E;ETHIOPIC SYLLABLE DDHO;Lo;0;L;;;;;N;;;;; +AB11;ETHIOPIC SYLLABLE DZU;Lo;0;L;;;;;N;;;;; +AB12;ETHIOPIC SYLLABLE DZI;Lo;0;L;;;;;N;;;;; +AB13;ETHIOPIC SYLLABLE DZAA;Lo;0;L;;;;;N;;;;; +AB14;ETHIOPIC SYLLABLE DZEE;Lo;0;L;;;;;N;;;;; +AB15;ETHIOPIC SYLLABLE DZE;Lo;0;L;;;;;N;;;;; +AB16;ETHIOPIC SYLLABLE DZO;Lo;0;L;;;;;N;;;;; +AB20;ETHIOPIC SYLLABLE CCHHA;Lo;0;L;;;;;N;;;;; +AB21;ETHIOPIC SYLLABLE CCHHU;Lo;0;L;;;;;N;;;;; +AB22;ETHIOPIC SYLLABLE CCHHI;Lo;0;L;;;;;N;;;;; +AB23;ETHIOPIC SYLLABLE CCHHAA;Lo;0;L;;;;;N;;;;; +AB24;ETHIOPIC SYLLABLE CCHHEE;Lo;0;L;;;;;N;;;;; +AB25;ETHIOPIC SYLLABLE CCHHE;Lo;0;L;;;;;N;;;;; +AB26;ETHIOPIC SYLLABLE CCHHO;Lo;0;L;;;;;N;;;;; +AB28;ETHIOPIC SYLLABLE BBA;Lo;0;L;;;;;N;;;;; +AB29;ETHIOPIC SYLLABLE BBU;Lo;0;L;;;;;N;;;;; +AB2A;ETHIOPIC SYLLABLE BBI;Lo;0;L;;;;;N;;;;; +AB2B;ETHIOPIC SYLLABLE BBAA;Lo;0;L;;;;;N;;;;; +AB2C;ETHIOPIC SYLLABLE BBEE;Lo;0;L;;;;;N;;;;; +AB2D;ETHIOPIC SYLLABLE BBE;Lo;0;L;;;;;N;;;;; +AB2E;ETHIOPIC SYLLABLE BBO;Lo;0;L;;;;;N;;;;; +AB30;LATIN SMALL LETTER BARRED ALPHA;Ll;0;L;;;;;N;;;;; +AB31;LATIN SMALL LETTER A REVERSED-SCHWA;Ll;0;L;;;;;N;;;;; +AB32;LATIN SMALL LETTER BLACKLETTER E;Ll;0;L;;;;;N;;;;; +AB33;LATIN SMALL LETTER BARRED E;Ll;0;L;;;;;N;;;;; +AB34;LATIN SMALL LETTER E WITH FLOURISH;Ll;0;L;;;;;N;;;;; +AB35;LATIN SMALL LETTER LENIS F;Ll;0;L;;;;;N;;;;; +AB36;LATIN SMALL LETTER SCRIPT G WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB37;LATIN SMALL LETTER L WITH INVERTED LAZY S;Ll;0;L;;;;;N;;;;; +AB38;LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +AB39;LATIN SMALL LETTER L WITH MIDDLE RING;Ll;0;L;;;;;N;;;;; +AB3A;LATIN SMALL LETTER M WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB3B;LATIN SMALL LETTER N WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB3C;LATIN SMALL LETTER ENG WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB3D;LATIN SMALL LETTER BLACKLETTER O;Ll;0;L;;;;;N;;;;; +AB3E;LATIN SMALL LETTER BLACKLETTER O WITH STROKE;Ll;0;L;;;;;N;;;;; +AB3F;LATIN SMALL LETTER OPEN O WITH STROKE;Ll;0;L;;;;;N;;;;; +AB40;LATIN SMALL LETTER INVERTED OE;Ll;0;L;;;;;N;;;;; +AB41;LATIN SMALL LETTER TURNED OE WITH STROKE;Ll;0;L;;;;;N;;;;; +AB42;LATIN SMALL LETTER TURNED OE WITH HORIZONTAL STROKE;Ll;0;L;;;;;N;;;;; +AB43;LATIN SMALL LETTER TURNED O OPEN-O;Ll;0;L;;;;;N;;;;; +AB44;LATIN SMALL LETTER TURNED O OPEN-O WITH STROKE;Ll;0;L;;;;;N;;;;; +AB45;LATIN SMALL LETTER STIRRUP R;Ll;0;L;;;;;N;;;;; +AB46;LATIN LETTER SMALL CAPITAL R WITH RIGHT LEG;Ll;0;L;;;;;N;;;;; +AB47;LATIN SMALL LETTER R WITHOUT HANDLE;Ll;0;L;;;;;N;;;;; +AB48;LATIN SMALL LETTER DOUBLE R;Ll;0;L;;;;;N;;;;; +AB49;LATIN SMALL LETTER R WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB4A;LATIN SMALL LETTER DOUBLE R WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB4B;LATIN SMALL LETTER SCRIPT R;Ll;0;L;;;;;N;;;;; +AB4C;LATIN SMALL LETTER SCRIPT R WITH RING;Ll;0;L;;;;;N;;;;; +AB4D;LATIN SMALL LETTER BASELINE ESH;Ll;0;L;;;;;N;;;;; +AB4E;LATIN SMALL LETTER U WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; +AB4F;LATIN SMALL LETTER U BAR WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; +AB50;LATIN SMALL LETTER UI;Ll;0;L;;;;;N;;;;; +AB51;LATIN SMALL LETTER TURNED UI;Ll;0;L;;;;;N;;;;; +AB52;LATIN SMALL LETTER U WITH LEFT HOOK;Ll;0;L;;;;;N;;;;; +AB53;LATIN SMALL LETTER CHI;Ll;0;L;;;;;N;;;A7B3;;A7B3 +AB54;LATIN SMALL LETTER CHI WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;; +AB55;LATIN SMALL LETTER CHI WITH LOW LEFT SERIF;Ll;0;L;;;;;N;;;;; +AB56;LATIN SMALL LETTER X WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;; +AB57;LATIN SMALL LETTER X WITH LONG LEFT LEG;Ll;0;L;;;;;N;;;;; +AB58;LATIN SMALL LETTER X WITH LONG LEFT LEG AND LOW RIGHT RING;Ll;0;L;;;;;N;;;;; +AB59;LATIN SMALL LETTER X WITH LONG LEFT LEG WITH SERIF;Ll;0;L;;;;;N;;;;; +AB5A;LATIN SMALL LETTER Y WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; +AB5B;MODIFIER BREVE WITH INVERTED BREVE;Sk;0;L;;;;;N;;;;; +AB5C;MODIFIER LETTER SMALL HENG;Lm;0;L;<super> A727;;;;N;;;;; +AB5D;MODIFIER LETTER SMALL L WITH INVERTED LAZY S;Lm;0;L;<super> AB37;;;;N;;;;; +AB5E;MODIFIER LETTER SMALL L WITH MIDDLE TILDE;Lm;0;L;<super> 026B;;;;N;;;;; +AB5F;MODIFIER LETTER SMALL U WITH LEFT HOOK;Lm;0;L;<super> AB52;;;;N;;;;; +AB60;LATIN SMALL LETTER SAKHA YAT;Ll;0;L;;;;;N;;;;; +AB61;LATIN SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;;; +AB62;LATIN SMALL LETTER OPEN OE;Ll;0;L;;;;;N;;;;; +AB63;LATIN SMALL LETTER UO;Ll;0;L;;;;;N;;;;; +AB64;LATIN SMALL LETTER INVERTED ALPHA;Ll;0;L;;;;;N;;;;; +AB65;GREEK LETTER SMALL CAPITAL OMEGA;Ll;0;L;;;;;N;;;;; +AB70;CHEROKEE SMALL LETTER A;Ll;0;L;;;;;N;;;13A0;;13A0 +AB71;CHEROKEE SMALL LETTER E;Ll;0;L;;;;;N;;;13A1;;13A1 +AB72;CHEROKEE SMALL LETTER I;Ll;0;L;;;;;N;;;13A2;;13A2 +AB73;CHEROKEE SMALL LETTER O;Ll;0;L;;;;;N;;;13A3;;13A3 +AB74;CHEROKEE SMALL LETTER U;Ll;0;L;;;;;N;;;13A4;;13A4 +AB75;CHEROKEE SMALL LETTER V;Ll;0;L;;;;;N;;;13A5;;13A5 +AB76;CHEROKEE SMALL LETTER GA;Ll;0;L;;;;;N;;;13A6;;13A6 +AB77;CHEROKEE SMALL LETTER KA;Ll;0;L;;;;;N;;;13A7;;13A7 +AB78;CHEROKEE SMALL LETTER GE;Ll;0;L;;;;;N;;;13A8;;13A8 +AB79;CHEROKEE SMALL LETTER GI;Ll;0;L;;;;;N;;;13A9;;13A9 +AB7A;CHEROKEE SMALL LETTER GO;Ll;0;L;;;;;N;;;13AA;;13AA +AB7B;CHEROKEE SMALL LETTER GU;Ll;0;L;;;;;N;;;13AB;;13AB +AB7C;CHEROKEE SMALL LETTER GV;Ll;0;L;;;;;N;;;13AC;;13AC +AB7D;CHEROKEE SMALL LETTER HA;Ll;0;L;;;;;N;;;13AD;;13AD +AB7E;CHEROKEE SMALL LETTER HE;Ll;0;L;;;;;N;;;13AE;;13AE +AB7F;CHEROKEE SMALL LETTER HI;Ll;0;L;;;;;N;;;13AF;;13AF +AB80;CHEROKEE SMALL LETTER HO;Ll;0;L;;;;;N;;;13B0;;13B0 +AB81;CHEROKEE SMALL LETTER HU;Ll;0;L;;;;;N;;;13B1;;13B1 +AB82;CHEROKEE SMALL LETTER HV;Ll;0;L;;;;;N;;;13B2;;13B2 +AB83;CHEROKEE SMALL LETTER LA;Ll;0;L;;;;;N;;;13B3;;13B3 +AB84;CHEROKEE SMALL LETTER LE;Ll;0;L;;;;;N;;;13B4;;13B4 +AB85;CHEROKEE SMALL LETTER LI;Ll;0;L;;;;;N;;;13B5;;13B5 +AB86;CHEROKEE SMALL LETTER LO;Ll;0;L;;;;;N;;;13B6;;13B6 +AB87;CHEROKEE SMALL LETTER LU;Ll;0;L;;;;;N;;;13B7;;13B7 +AB88;CHEROKEE SMALL LETTER LV;Ll;0;L;;;;;N;;;13B8;;13B8 +AB89;CHEROKEE SMALL LETTER MA;Ll;0;L;;;;;N;;;13B9;;13B9 +AB8A;CHEROKEE SMALL LETTER ME;Ll;0;L;;;;;N;;;13BA;;13BA +AB8B;CHEROKEE SMALL LETTER MI;Ll;0;L;;;;;N;;;13BB;;13BB +AB8C;CHEROKEE SMALL LETTER MO;Ll;0;L;;;;;N;;;13BC;;13BC +AB8D;CHEROKEE SMALL LETTER MU;Ll;0;L;;;;;N;;;13BD;;13BD +AB8E;CHEROKEE SMALL LETTER NA;Ll;0;L;;;;;N;;;13BE;;13BE +AB8F;CHEROKEE SMALL LETTER HNA;Ll;0;L;;;;;N;;;13BF;;13BF +AB90;CHEROKEE SMALL LETTER NAH;Ll;0;L;;;;;N;;;13C0;;13C0 +AB91;CHEROKEE SMALL LETTER NE;Ll;0;L;;;;;N;;;13C1;;13C1 +AB92;CHEROKEE SMALL LETTER NI;Ll;0;L;;;;;N;;;13C2;;13C2 +AB93;CHEROKEE SMALL LETTER NO;Ll;0;L;;;;;N;;;13C3;;13C3 +AB94;CHEROKEE SMALL LETTER NU;Ll;0;L;;;;;N;;;13C4;;13C4 +AB95;CHEROKEE SMALL LETTER NV;Ll;0;L;;;;;N;;;13C5;;13C5 +AB96;CHEROKEE SMALL LETTER QUA;Ll;0;L;;;;;N;;;13C6;;13C6 +AB97;CHEROKEE SMALL LETTER QUE;Ll;0;L;;;;;N;;;13C7;;13C7 +AB98;CHEROKEE SMALL LETTER QUI;Ll;0;L;;;;;N;;;13C8;;13C8 +AB99;CHEROKEE SMALL LETTER QUO;Ll;0;L;;;;;N;;;13C9;;13C9 +AB9A;CHEROKEE SMALL LETTER QUU;Ll;0;L;;;;;N;;;13CA;;13CA +AB9B;CHEROKEE SMALL LETTER QUV;Ll;0;L;;;;;N;;;13CB;;13CB +AB9C;CHEROKEE SMALL LETTER SA;Ll;0;L;;;;;N;;;13CC;;13CC +AB9D;CHEROKEE SMALL LETTER S;Ll;0;L;;;;;N;;;13CD;;13CD +AB9E;CHEROKEE SMALL LETTER SE;Ll;0;L;;;;;N;;;13CE;;13CE +AB9F;CHEROKEE SMALL LETTER SI;Ll;0;L;;;;;N;;;13CF;;13CF +ABA0;CHEROKEE SMALL LETTER SO;Ll;0;L;;;;;N;;;13D0;;13D0 +ABA1;CHEROKEE SMALL LETTER SU;Ll;0;L;;;;;N;;;13D1;;13D1 +ABA2;CHEROKEE SMALL LETTER SV;Ll;0;L;;;;;N;;;13D2;;13D2 +ABA3;CHEROKEE SMALL LETTER DA;Ll;0;L;;;;;N;;;13D3;;13D3 +ABA4;CHEROKEE SMALL LETTER TA;Ll;0;L;;;;;N;;;13D4;;13D4 +ABA5;CHEROKEE SMALL LETTER DE;Ll;0;L;;;;;N;;;13D5;;13D5 +ABA6;CHEROKEE SMALL LETTER TE;Ll;0;L;;;;;N;;;13D6;;13D6 +ABA7;CHEROKEE SMALL LETTER DI;Ll;0;L;;;;;N;;;13D7;;13D7 +ABA8;CHEROKEE SMALL LETTER TI;Ll;0;L;;;;;N;;;13D8;;13D8 +ABA9;CHEROKEE SMALL LETTER DO;Ll;0;L;;;;;N;;;13D9;;13D9 +ABAA;CHEROKEE SMALL LETTER DU;Ll;0;L;;;;;N;;;13DA;;13DA +ABAB;CHEROKEE SMALL LETTER DV;Ll;0;L;;;;;N;;;13DB;;13DB +ABAC;CHEROKEE SMALL LETTER DLA;Ll;0;L;;;;;N;;;13DC;;13DC +ABAD;CHEROKEE SMALL LETTER TLA;Ll;0;L;;;;;N;;;13DD;;13DD +ABAE;CHEROKEE SMALL LETTER TLE;Ll;0;L;;;;;N;;;13DE;;13DE +ABAF;CHEROKEE SMALL LETTER TLI;Ll;0;L;;;;;N;;;13DF;;13DF +ABB0;CHEROKEE SMALL LETTER TLO;Ll;0;L;;;;;N;;;13E0;;13E0 +ABB1;CHEROKEE SMALL LETTER TLU;Ll;0;L;;;;;N;;;13E1;;13E1 +ABB2;CHEROKEE SMALL LETTER TLV;Ll;0;L;;;;;N;;;13E2;;13E2 +ABB3;CHEROKEE SMALL LETTER TSA;Ll;0;L;;;;;N;;;13E3;;13E3 +ABB4;CHEROKEE SMALL LETTER TSE;Ll;0;L;;;;;N;;;13E4;;13E4 +ABB5;CHEROKEE SMALL LETTER TSI;Ll;0;L;;;;;N;;;13E5;;13E5 +ABB6;CHEROKEE SMALL LETTER TSO;Ll;0;L;;;;;N;;;13E6;;13E6 +ABB7;CHEROKEE SMALL LETTER TSU;Ll;0;L;;;;;N;;;13E7;;13E7 +ABB8;CHEROKEE SMALL LETTER TSV;Ll;0;L;;;;;N;;;13E8;;13E8 +ABB9;CHEROKEE SMALL LETTER WA;Ll;0;L;;;;;N;;;13E9;;13E9 +ABBA;CHEROKEE SMALL LETTER WE;Ll;0;L;;;;;N;;;13EA;;13EA +ABBB;CHEROKEE SMALL LETTER WI;Ll;0;L;;;;;N;;;13EB;;13EB +ABBC;CHEROKEE SMALL LETTER WO;Ll;0;L;;;;;N;;;13EC;;13EC +ABBD;CHEROKEE SMALL LETTER WU;Ll;0;L;;;;;N;;;13ED;;13ED +ABBE;CHEROKEE SMALL LETTER WV;Ll;0;L;;;;;N;;;13EE;;13EE +ABBF;CHEROKEE SMALL LETTER YA;Ll;0;L;;;;;N;;;13EF;;13EF +ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;; +ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;; +ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;; +ABC3;MEETEI MAYEK LETTER MIT;Lo;0;L;;;;;N;;;;; +ABC4;MEETEI MAYEK LETTER PA;Lo;0;L;;;;;N;;;;; +ABC5;MEETEI MAYEK LETTER NA;Lo;0;L;;;;;N;;;;; +ABC6;MEETEI MAYEK LETTER CHIL;Lo;0;L;;;;;N;;;;; +ABC7;MEETEI MAYEK LETTER TIL;Lo;0;L;;;;;N;;;;; +ABC8;MEETEI MAYEK LETTER KHOU;Lo;0;L;;;;;N;;;;; +ABC9;MEETEI MAYEK LETTER NGOU;Lo;0;L;;;;;N;;;;; +ABCA;MEETEI MAYEK LETTER THOU;Lo;0;L;;;;;N;;;;; +ABCB;MEETEI MAYEK LETTER WAI;Lo;0;L;;;;;N;;;;; +ABCC;MEETEI MAYEK LETTER YANG;Lo;0;L;;;;;N;;;;; +ABCD;MEETEI MAYEK LETTER HUK;Lo;0;L;;;;;N;;;;; +ABCE;MEETEI MAYEK LETTER UN;Lo;0;L;;;;;N;;;;; +ABCF;MEETEI MAYEK LETTER I;Lo;0;L;;;;;N;;;;; +ABD0;MEETEI MAYEK LETTER PHAM;Lo;0;L;;;;;N;;;;; +ABD1;MEETEI MAYEK LETTER ATIYA;Lo;0;L;;;;;N;;;;; +ABD2;MEETEI MAYEK LETTER GOK;Lo;0;L;;;;;N;;;;; +ABD3;MEETEI MAYEK LETTER JHAM;Lo;0;L;;;;;N;;;;; +ABD4;MEETEI MAYEK LETTER RAI;Lo;0;L;;;;;N;;;;; +ABD5;MEETEI MAYEK LETTER BA;Lo;0;L;;;;;N;;;;; +ABD6;MEETEI MAYEK LETTER JIL;Lo;0;L;;;;;N;;;;; +ABD7;MEETEI MAYEK LETTER DIL;Lo;0;L;;;;;N;;;;; +ABD8;MEETEI MAYEK LETTER GHOU;Lo;0;L;;;;;N;;;;; +ABD9;MEETEI MAYEK LETTER DHOU;Lo;0;L;;;;;N;;;;; +ABDA;MEETEI MAYEK LETTER BHAM;Lo;0;L;;;;;N;;;;; +ABDB;MEETEI MAYEK LETTER KOK LONSUM;Lo;0;L;;;;;N;;;;; +ABDC;MEETEI MAYEK LETTER LAI LONSUM;Lo;0;L;;;;;N;;;;; +ABDD;MEETEI MAYEK LETTER MIT LONSUM;Lo;0;L;;;;;N;;;;; +ABDE;MEETEI MAYEK LETTER PA LONSUM;Lo;0;L;;;;;N;;;;; +ABDF;MEETEI MAYEK LETTER NA LONSUM;Lo;0;L;;;;;N;;;;; +ABE0;MEETEI MAYEK LETTER TIL LONSUM;Lo;0;L;;;;;N;;;;; +ABE1;MEETEI MAYEK LETTER NGOU LONSUM;Lo;0;L;;;;;N;;;;; +ABE2;MEETEI MAYEK LETTER I LONSUM;Lo;0;L;;;;;N;;;;; +ABE3;MEETEI MAYEK VOWEL SIGN ONAP;Mc;0;L;;;;;N;;;;; +ABE4;MEETEI MAYEK VOWEL SIGN INAP;Mc;0;L;;;;;N;;;;; +ABE5;MEETEI MAYEK VOWEL SIGN ANAP;Mn;0;NSM;;;;;N;;;;; +ABE6;MEETEI MAYEK VOWEL SIGN YENAP;Mc;0;L;;;;;N;;;;; +ABE7;MEETEI MAYEK VOWEL SIGN SOUNAP;Mc;0;L;;;;;N;;;;; +ABE8;MEETEI MAYEK VOWEL SIGN UNAP;Mn;0;NSM;;;;;N;;;;; +ABE9;MEETEI MAYEK VOWEL SIGN CHEINAP;Mc;0;L;;;;;N;;;;; +ABEA;MEETEI MAYEK VOWEL SIGN NUNG;Mc;0;L;;;;;N;;;;; +ABEB;MEETEI MAYEK CHEIKHEI;Po;0;L;;;;;N;;;;; +ABEC;MEETEI MAYEK LUM IYEK;Mc;0;L;;;;;N;;;;; +ABED;MEETEI MAYEK APUN IYEK;Mn;9;NSM;;;;;N;;;;; +ABF0;MEETEI MAYEK DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +ABF1;MEETEI MAYEK DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +ABF2;MEETEI MAYEK DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +ABF3;MEETEI MAYEK DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +ABF4;MEETEI MAYEK DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +ABF5;MEETEI MAYEK DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +ABF6;MEETEI MAYEK DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +ABF7;MEETEI MAYEK DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +ABF8;MEETEI MAYEK DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +ABF9;MEETEI MAYEK DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +AC00;<Hangul Syllable, First>;Lo;0;L;;;;;N;;;;; +D7A3;<Hangul Syllable, Last>;Lo;0;L;;;;;N;;;;; +D7B0;HANGUL JUNGSEONG O-YEO;Lo;0;L;;;;;N;;;;; +D7B1;HANGUL JUNGSEONG O-O-I;Lo;0;L;;;;;N;;;;; +D7B2;HANGUL JUNGSEONG YO-A;Lo;0;L;;;;;N;;;;; +D7B3;HANGUL JUNGSEONG YO-AE;Lo;0;L;;;;;N;;;;; +D7B4;HANGUL JUNGSEONG YO-EO;Lo;0;L;;;;;N;;;;; +D7B5;HANGUL JUNGSEONG U-YEO;Lo;0;L;;;;;N;;;;; +D7B6;HANGUL JUNGSEONG U-I-I;Lo;0;L;;;;;N;;;;; +D7B7;HANGUL JUNGSEONG YU-AE;Lo;0;L;;;;;N;;;;; +D7B8;HANGUL JUNGSEONG YU-O;Lo;0;L;;;;;N;;;;; +D7B9;HANGUL JUNGSEONG EU-A;Lo;0;L;;;;;N;;;;; +D7BA;HANGUL JUNGSEONG EU-EO;Lo;0;L;;;;;N;;;;; +D7BB;HANGUL JUNGSEONG EU-E;Lo;0;L;;;;;N;;;;; +D7BC;HANGUL JUNGSEONG EU-O;Lo;0;L;;;;;N;;;;; +D7BD;HANGUL JUNGSEONG I-YA-O;Lo;0;L;;;;;N;;;;; +D7BE;HANGUL JUNGSEONG I-YAE;Lo;0;L;;;;;N;;;;; +D7BF;HANGUL JUNGSEONG I-YEO;Lo;0;L;;;;;N;;;;; +D7C0;HANGUL JUNGSEONG I-YE;Lo;0;L;;;;;N;;;;; +D7C1;HANGUL JUNGSEONG I-O-I;Lo;0;L;;;;;N;;;;; +D7C2;HANGUL JUNGSEONG I-YO;Lo;0;L;;;;;N;;;;; +D7C3;HANGUL JUNGSEONG I-YU;Lo;0;L;;;;;N;;;;; +D7C4;HANGUL JUNGSEONG I-I;Lo;0;L;;;;;N;;;;; +D7C5;HANGUL JUNGSEONG ARAEA-A;Lo;0;L;;;;;N;;;;; +D7C6;HANGUL JUNGSEONG ARAEA-E;Lo;0;L;;;;;N;;;;; +D7CB;HANGUL JONGSEONG NIEUN-RIEUL;Lo;0;L;;;;;N;;;;; +D7CC;HANGUL JONGSEONG NIEUN-CHIEUCH;Lo;0;L;;;;;N;;;;; +D7CD;HANGUL JONGSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; +D7CE;HANGUL JONGSEONG SSANGTIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; +D7CF;HANGUL JONGSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; +D7D0;HANGUL JONGSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; +D7D1;HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +D7D2;HANGUL JONGSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; +D7D3;HANGUL JONGSEONG TIKEUT-CHIEUCH;Lo;0;L;;;;;N;;;;; +D7D4;HANGUL JONGSEONG TIKEUT-THIEUTH;Lo;0;L;;;;;N;;;;; +D7D5;HANGUL JONGSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +D7D6;HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; +D7D7;HANGUL JONGSEONG SSANGRIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; +D7D8;HANGUL JONGSEONG RIEUL-MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; +D7D9;HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; +D7DA;HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; +D7DB;HANGUL JONGSEONG RIEUL-YESIEUNG;Lo;0;L;;;;;N;;;;; +D7DC;HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH;Lo;0;L;;;;;N;;;;; +D7DD;HANGUL JONGSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; +D7DE;HANGUL JONGSEONG MIEUM-NIEUN;Lo;0;L;;;;;N;;;;; +D7DF;HANGUL JONGSEONG MIEUM-SSANGNIEUN;Lo;0;L;;;;;N;;;;; +D7E0;HANGUL JONGSEONG SSANGMIEUM;Lo;0;L;;;;;N;;;;; +D7E1;HANGUL JONGSEONG MIEUM-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; +D7E2;HANGUL JONGSEONG MIEUM-CIEUC;Lo;0;L;;;;;N;;;;; +D7E3;HANGUL JONGSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; +D7E4;HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; +D7E5;HANGUL JONGSEONG PIEUP-MIEUM;Lo;0;L;;;;;N;;;;; +D7E6;HANGUL JONGSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; +D7E7;HANGUL JONGSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +D7E8;HANGUL JONGSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; +D7E9;HANGUL JONGSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; +D7EA;HANGUL JONGSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; +D7EB;HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +D7EC;HANGUL JONGSEONG SSANGSIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +D7ED;HANGUL JONGSEONG SSANGSIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +D7EE;HANGUL JONGSEONG SIOS-PANSIOS;Lo;0;L;;;;;N;;;;; +D7EF;HANGUL JONGSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; +D7F0;HANGUL JONGSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; +D7F1;HANGUL JONGSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; +D7F2;HANGUL JONGSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; +D7F3;HANGUL JONGSEONG PANSIOS-PIEUP;Lo;0;L;;;;;N;;;;; +D7F4;HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +D7F5;HANGUL JONGSEONG YESIEUNG-MIEUM;Lo;0;L;;;;;N;;;;; +D7F6;HANGUL JONGSEONG YESIEUNG-HIEUH;Lo;0;L;;;;;N;;;;; +D7F7;HANGUL JONGSEONG CIEUC-PIEUP;Lo;0;L;;;;;N;;;;; +D7F8;HANGUL JONGSEONG CIEUC-SSANGPIEUP;Lo;0;L;;;;;N;;;;; +D7F9;HANGUL JONGSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; +D7FA;HANGUL JONGSEONG PHIEUPH-SIOS;Lo;0;L;;;;;N;;;;; +D7FB;HANGUL JONGSEONG PHIEUPH-THIEUTH;Lo;0;L;;;;;N;;;;; +D800;<Non Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;; +DB7F;<Non Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;; +DB80;<Private Use High Surrogate, First>;Cs;0;L;;;;;N;;;;; +DBFF;<Private Use High Surrogate, Last>;Cs;0;L;;;;;N;;;;; +DC00;<Low Surrogate, First>;Cs;0;L;;;;;N;;;;; +DFFF;<Low Surrogate, Last>;Cs;0;L;;;;;N;;;;; +E000;<Private Use, First>;Co;0;L;;;;;N;;;;; +F8FF;<Private Use, Last>;Co;0;L;;;;;N;;;;; +F900;CJK COMPATIBILITY IDEOGRAPH-F900;Lo;0;L;8C48;;;;N;;;;; +F901;CJK COMPATIBILITY IDEOGRAPH-F901;Lo;0;L;66F4;;;;N;;;;; +F902;CJK COMPATIBILITY IDEOGRAPH-F902;Lo;0;L;8ECA;;;;N;;;;; +F903;CJK COMPATIBILITY IDEOGRAPH-F903;Lo;0;L;8CC8;;;;N;;;;; +F904;CJK COMPATIBILITY IDEOGRAPH-F904;Lo;0;L;6ED1;;;;N;;;;; +F905;CJK COMPATIBILITY IDEOGRAPH-F905;Lo;0;L;4E32;;;;N;;;;; +F906;CJK COMPATIBILITY IDEOGRAPH-F906;Lo;0;L;53E5;;;;N;;;;; +F907;CJK COMPATIBILITY IDEOGRAPH-F907;Lo;0;L;9F9C;;;;N;;;;; +F908;CJK COMPATIBILITY IDEOGRAPH-F908;Lo;0;L;9F9C;;;;N;;;;; +F909;CJK COMPATIBILITY IDEOGRAPH-F909;Lo;0;L;5951;;;;N;;;;; +F90A;CJK COMPATIBILITY IDEOGRAPH-F90A;Lo;0;L;91D1;;;;N;;;;; +F90B;CJK COMPATIBILITY IDEOGRAPH-F90B;Lo;0;L;5587;;;;N;;;;; +F90C;CJK COMPATIBILITY IDEOGRAPH-F90C;Lo;0;L;5948;;;;N;;;;; +F90D;CJK COMPATIBILITY IDEOGRAPH-F90D;Lo;0;L;61F6;;;;N;;;;; +F90E;CJK COMPATIBILITY IDEOGRAPH-F90E;Lo;0;L;7669;;;;N;;;;; +F90F;CJK COMPATIBILITY IDEOGRAPH-F90F;Lo;0;L;7F85;;;;N;;;;; +F910;CJK COMPATIBILITY IDEOGRAPH-F910;Lo;0;L;863F;;;;N;;;;; +F911;CJK COMPATIBILITY IDEOGRAPH-F911;Lo;0;L;87BA;;;;N;;;;; +F912;CJK COMPATIBILITY IDEOGRAPH-F912;Lo;0;L;88F8;;;;N;;;;; +F913;CJK COMPATIBILITY IDEOGRAPH-F913;Lo;0;L;908F;;;;N;;;;; +F914;CJK COMPATIBILITY IDEOGRAPH-F914;Lo;0;L;6A02;;;;N;;;;; +F915;CJK COMPATIBILITY IDEOGRAPH-F915;Lo;0;L;6D1B;;;;N;;;;; +F916;CJK COMPATIBILITY IDEOGRAPH-F916;Lo;0;L;70D9;;;;N;;;;; +F917;CJK COMPATIBILITY IDEOGRAPH-F917;Lo;0;L;73DE;;;;N;;;;; +F918;CJK COMPATIBILITY IDEOGRAPH-F918;Lo;0;L;843D;;;;N;;;;; +F919;CJK COMPATIBILITY IDEOGRAPH-F919;Lo;0;L;916A;;;;N;;;;; +F91A;CJK COMPATIBILITY IDEOGRAPH-F91A;Lo;0;L;99F1;;;;N;;;;; +F91B;CJK COMPATIBILITY IDEOGRAPH-F91B;Lo;0;L;4E82;;;;N;;;;; +F91C;CJK COMPATIBILITY IDEOGRAPH-F91C;Lo;0;L;5375;;;;N;;;;; +F91D;CJK COMPATIBILITY IDEOGRAPH-F91D;Lo;0;L;6B04;;;;N;;;;; +F91E;CJK COMPATIBILITY IDEOGRAPH-F91E;Lo;0;L;721B;;;;N;;;;; +F91F;CJK COMPATIBILITY IDEOGRAPH-F91F;Lo;0;L;862D;;;;N;;;;; +F920;CJK COMPATIBILITY IDEOGRAPH-F920;Lo;0;L;9E1E;;;;N;;;;; +F921;CJK COMPATIBILITY IDEOGRAPH-F921;Lo;0;L;5D50;;;;N;;;;; +F922;CJK COMPATIBILITY IDEOGRAPH-F922;Lo;0;L;6FEB;;;;N;;;;; +F923;CJK COMPATIBILITY IDEOGRAPH-F923;Lo;0;L;85CD;;;;N;;;;; +F924;CJK COMPATIBILITY IDEOGRAPH-F924;Lo;0;L;8964;;;;N;;;;; +F925;CJK COMPATIBILITY IDEOGRAPH-F925;Lo;0;L;62C9;;;;N;;;;; +F926;CJK COMPATIBILITY IDEOGRAPH-F926;Lo;0;L;81D8;;;;N;;;;; +F927;CJK COMPATIBILITY IDEOGRAPH-F927;Lo;0;L;881F;;;;N;;;;; +F928;CJK COMPATIBILITY IDEOGRAPH-F928;Lo;0;L;5ECA;;;;N;;;;; +F929;CJK COMPATIBILITY IDEOGRAPH-F929;Lo;0;L;6717;;;;N;;;;; +F92A;CJK COMPATIBILITY IDEOGRAPH-F92A;Lo;0;L;6D6A;;;;N;;;;; +F92B;CJK COMPATIBILITY IDEOGRAPH-F92B;Lo;0;L;72FC;;;;N;;;;; +F92C;CJK COMPATIBILITY IDEOGRAPH-F92C;Lo;0;L;90CE;;;;N;;;;; +F92D;CJK COMPATIBILITY IDEOGRAPH-F92D;Lo;0;L;4F86;;;;N;;;;; +F92E;CJK COMPATIBILITY IDEOGRAPH-F92E;Lo;0;L;51B7;;;;N;;;;; +F92F;CJK COMPATIBILITY IDEOGRAPH-F92F;Lo;0;L;52DE;;;;N;;;;; +F930;CJK COMPATIBILITY IDEOGRAPH-F930;Lo;0;L;64C4;;;;N;;;;; +F931;CJK COMPATIBILITY IDEOGRAPH-F931;Lo;0;L;6AD3;;;;N;;;;; +F932;CJK COMPATIBILITY IDEOGRAPH-F932;Lo;0;L;7210;;;;N;;;;; +F933;CJK COMPATIBILITY IDEOGRAPH-F933;Lo;0;L;76E7;;;;N;;;;; +F934;CJK COMPATIBILITY IDEOGRAPH-F934;Lo;0;L;8001;;;;N;;;;; +F935;CJK COMPATIBILITY IDEOGRAPH-F935;Lo;0;L;8606;;;;N;;;;; +F936;CJK COMPATIBILITY IDEOGRAPH-F936;Lo;0;L;865C;;;;N;;;;; +F937;CJK COMPATIBILITY IDEOGRAPH-F937;Lo;0;L;8DEF;;;;N;;;;; +F938;CJK COMPATIBILITY IDEOGRAPH-F938;Lo;0;L;9732;;;;N;;;;; +F939;CJK COMPATIBILITY IDEOGRAPH-F939;Lo;0;L;9B6F;;;;N;;;;; +F93A;CJK COMPATIBILITY IDEOGRAPH-F93A;Lo;0;L;9DFA;;;;N;;;;; +F93B;CJK COMPATIBILITY IDEOGRAPH-F93B;Lo;0;L;788C;;;;N;;;;; +F93C;CJK COMPATIBILITY IDEOGRAPH-F93C;Lo;0;L;797F;;;;N;;;;; +F93D;CJK COMPATIBILITY IDEOGRAPH-F93D;Lo;0;L;7DA0;;;;N;;;;; +F93E;CJK COMPATIBILITY IDEOGRAPH-F93E;Lo;0;L;83C9;;;;N;;;;; +F93F;CJK COMPATIBILITY IDEOGRAPH-F93F;Lo;0;L;9304;;;;N;;;;; +F940;CJK COMPATIBILITY IDEOGRAPH-F940;Lo;0;L;9E7F;;;;N;;;;; +F941;CJK COMPATIBILITY IDEOGRAPH-F941;Lo;0;L;8AD6;;;;N;;;;; +F942;CJK COMPATIBILITY IDEOGRAPH-F942;Lo;0;L;58DF;;;;N;;;;; +F943;CJK COMPATIBILITY IDEOGRAPH-F943;Lo;0;L;5F04;;;;N;;;;; +F944;CJK COMPATIBILITY IDEOGRAPH-F944;Lo;0;L;7C60;;;;N;;;;; +F945;CJK COMPATIBILITY IDEOGRAPH-F945;Lo;0;L;807E;;;;N;;;;; +F946;CJK COMPATIBILITY IDEOGRAPH-F946;Lo;0;L;7262;;;;N;;;;; +F947;CJK COMPATIBILITY IDEOGRAPH-F947;Lo;0;L;78CA;;;;N;;;;; +F948;CJK COMPATIBILITY IDEOGRAPH-F948;Lo;0;L;8CC2;;;;N;;;;; +F949;CJK COMPATIBILITY IDEOGRAPH-F949;Lo;0;L;96F7;;;;N;;;;; +F94A;CJK COMPATIBILITY IDEOGRAPH-F94A;Lo;0;L;58D8;;;;N;;;;; +F94B;CJK COMPATIBILITY IDEOGRAPH-F94B;Lo;0;L;5C62;;;;N;;;;; +F94C;CJK COMPATIBILITY IDEOGRAPH-F94C;Lo;0;L;6A13;;;;N;;;;; +F94D;CJK COMPATIBILITY IDEOGRAPH-F94D;Lo;0;L;6DDA;;;;N;;;;; +F94E;CJK COMPATIBILITY IDEOGRAPH-F94E;Lo;0;L;6F0F;;;;N;;;;; +F94F;CJK COMPATIBILITY IDEOGRAPH-F94F;Lo;0;L;7D2F;;;;N;;;;; +F950;CJK COMPATIBILITY IDEOGRAPH-F950;Lo;0;L;7E37;;;;N;;;;; +F951;CJK COMPATIBILITY IDEOGRAPH-F951;Lo;0;L;964B;;;;N;;;;; +F952;CJK COMPATIBILITY IDEOGRAPH-F952;Lo;0;L;52D2;;;;N;;;;; +F953;CJK COMPATIBILITY IDEOGRAPH-F953;Lo;0;L;808B;;;;N;;;;; +F954;CJK COMPATIBILITY IDEOGRAPH-F954;Lo;0;L;51DC;;;;N;;;;; +F955;CJK COMPATIBILITY IDEOGRAPH-F955;Lo;0;L;51CC;;;;N;;;;; +F956;CJK COMPATIBILITY IDEOGRAPH-F956;Lo;0;L;7A1C;;;;N;;;;; +F957;CJK COMPATIBILITY IDEOGRAPH-F957;Lo;0;L;7DBE;;;;N;;;;; +F958;CJK COMPATIBILITY IDEOGRAPH-F958;Lo;0;L;83F1;;;;N;;;;; +F959;CJK COMPATIBILITY IDEOGRAPH-F959;Lo;0;L;9675;;;;N;;;;; +F95A;CJK COMPATIBILITY IDEOGRAPH-F95A;Lo;0;L;8B80;;;;N;;;;; +F95B;CJK COMPATIBILITY IDEOGRAPH-F95B;Lo;0;L;62CF;;;;N;;;;; +F95C;CJK COMPATIBILITY IDEOGRAPH-F95C;Lo;0;L;6A02;;;;N;;;;; +F95D;CJK COMPATIBILITY IDEOGRAPH-F95D;Lo;0;L;8AFE;;;;N;;;;; +F95E;CJK COMPATIBILITY IDEOGRAPH-F95E;Lo;0;L;4E39;;;;N;;;;; +F95F;CJK COMPATIBILITY IDEOGRAPH-F95F;Lo;0;L;5BE7;;;;N;;;;; +F960;CJK COMPATIBILITY IDEOGRAPH-F960;Lo;0;L;6012;;;;N;;;;; +F961;CJK COMPATIBILITY IDEOGRAPH-F961;Lo;0;L;7387;;;;N;;;;; +F962;CJK COMPATIBILITY IDEOGRAPH-F962;Lo;0;L;7570;;;;N;;;;; +F963;CJK COMPATIBILITY IDEOGRAPH-F963;Lo;0;L;5317;;;;N;;;;; +F964;CJK COMPATIBILITY IDEOGRAPH-F964;Lo;0;L;78FB;;;;N;;;;; +F965;CJK COMPATIBILITY IDEOGRAPH-F965;Lo;0;L;4FBF;;;;N;;;;; +F966;CJK COMPATIBILITY IDEOGRAPH-F966;Lo;0;L;5FA9;;;;N;;;;; +F967;CJK COMPATIBILITY IDEOGRAPH-F967;Lo;0;L;4E0D;;;;N;;;;; +F968;CJK COMPATIBILITY IDEOGRAPH-F968;Lo;0;L;6CCC;;;;N;;;;; +F969;CJK COMPATIBILITY IDEOGRAPH-F969;Lo;0;L;6578;;;;N;;;;; +F96A;CJK COMPATIBILITY IDEOGRAPH-F96A;Lo;0;L;7D22;;;;N;;;;; +F96B;CJK COMPATIBILITY IDEOGRAPH-F96B;Lo;0;L;53C3;;;3;N;;;;; +F96C;CJK COMPATIBILITY IDEOGRAPH-F96C;Lo;0;L;585E;;;;N;;;;; +F96D;CJK COMPATIBILITY IDEOGRAPH-F96D;Lo;0;L;7701;;;;N;;;;; +F96E;CJK COMPATIBILITY IDEOGRAPH-F96E;Lo;0;L;8449;;;;N;;;;; +F96F;CJK COMPATIBILITY IDEOGRAPH-F96F;Lo;0;L;8AAA;;;;N;;;;; +F970;CJK COMPATIBILITY IDEOGRAPH-F970;Lo;0;L;6BBA;;;;N;;;;; +F971;CJK COMPATIBILITY IDEOGRAPH-F971;Lo;0;L;8FB0;;;;N;;;;; +F972;CJK COMPATIBILITY IDEOGRAPH-F972;Lo;0;L;6C88;;;;N;;;;; +F973;CJK COMPATIBILITY IDEOGRAPH-F973;Lo;0;L;62FE;;;10;N;;;;; +F974;CJK COMPATIBILITY IDEOGRAPH-F974;Lo;0;L;82E5;;;;N;;;;; +F975;CJK COMPATIBILITY IDEOGRAPH-F975;Lo;0;L;63A0;;;;N;;;;; +F976;CJK COMPATIBILITY IDEOGRAPH-F976;Lo;0;L;7565;;;;N;;;;; +F977;CJK COMPATIBILITY IDEOGRAPH-F977;Lo;0;L;4EAE;;;;N;;;;; +F978;CJK COMPATIBILITY IDEOGRAPH-F978;Lo;0;L;5169;;;2;N;;;;; +F979;CJK COMPATIBILITY IDEOGRAPH-F979;Lo;0;L;51C9;;;;N;;;;; +F97A;CJK COMPATIBILITY IDEOGRAPH-F97A;Lo;0;L;6881;;;;N;;;;; +F97B;CJK COMPATIBILITY IDEOGRAPH-F97B;Lo;0;L;7CE7;;;;N;;;;; +F97C;CJK COMPATIBILITY IDEOGRAPH-F97C;Lo;0;L;826F;;;;N;;;;; +F97D;CJK COMPATIBILITY IDEOGRAPH-F97D;Lo;0;L;8AD2;;;;N;;;;; +F97E;CJK COMPATIBILITY IDEOGRAPH-F97E;Lo;0;L;91CF;;;;N;;;;; +F97F;CJK COMPATIBILITY IDEOGRAPH-F97F;Lo;0;L;52F5;;;;N;;;;; +F980;CJK COMPATIBILITY IDEOGRAPH-F980;Lo;0;L;5442;;;;N;;;;; +F981;CJK COMPATIBILITY IDEOGRAPH-F981;Lo;0;L;5973;;;;N;;;;; +F982;CJK COMPATIBILITY IDEOGRAPH-F982;Lo;0;L;5EEC;;;;N;;;;; +F983;CJK COMPATIBILITY IDEOGRAPH-F983;Lo;0;L;65C5;;;;N;;;;; +F984;CJK COMPATIBILITY IDEOGRAPH-F984;Lo;0;L;6FFE;;;;N;;;;; +F985;CJK COMPATIBILITY IDEOGRAPH-F985;Lo;0;L;792A;;;;N;;;;; +F986;CJK COMPATIBILITY IDEOGRAPH-F986;Lo;0;L;95AD;;;;N;;;;; +F987;CJK COMPATIBILITY IDEOGRAPH-F987;Lo;0;L;9A6A;;;;N;;;;; +F988;CJK COMPATIBILITY IDEOGRAPH-F988;Lo;0;L;9E97;;;;N;;;;; +F989;CJK COMPATIBILITY IDEOGRAPH-F989;Lo;0;L;9ECE;;;;N;;;;; +F98A;CJK COMPATIBILITY IDEOGRAPH-F98A;Lo;0;L;529B;;;;N;;;;; +F98B;CJK COMPATIBILITY IDEOGRAPH-F98B;Lo;0;L;66C6;;;;N;;;;; +F98C;CJK COMPATIBILITY IDEOGRAPH-F98C;Lo;0;L;6B77;;;;N;;;;; +F98D;CJK COMPATIBILITY IDEOGRAPH-F98D;Lo;0;L;8F62;;;;N;;;;; +F98E;CJK COMPATIBILITY IDEOGRAPH-F98E;Lo;0;L;5E74;;;;N;;;;; +F98F;CJK COMPATIBILITY IDEOGRAPH-F98F;Lo;0;L;6190;;;;N;;;;; +F990;CJK COMPATIBILITY IDEOGRAPH-F990;Lo;0;L;6200;;;;N;;;;; +F991;CJK COMPATIBILITY IDEOGRAPH-F991;Lo;0;L;649A;;;;N;;;;; +F992;CJK COMPATIBILITY IDEOGRAPH-F992;Lo;0;L;6F23;;;;N;;;;; +F993;CJK COMPATIBILITY IDEOGRAPH-F993;Lo;0;L;7149;;;;N;;;;; +F994;CJK COMPATIBILITY IDEOGRAPH-F994;Lo;0;L;7489;;;;N;;;;; +F995;CJK COMPATIBILITY IDEOGRAPH-F995;Lo;0;L;79CA;;;;N;;;;; +F996;CJK COMPATIBILITY IDEOGRAPH-F996;Lo;0;L;7DF4;;;;N;;;;; +F997;CJK COMPATIBILITY IDEOGRAPH-F997;Lo;0;L;806F;;;;N;;;;; +F998;CJK COMPATIBILITY IDEOGRAPH-F998;Lo;0;L;8F26;;;;N;;;;; +F999;CJK COMPATIBILITY IDEOGRAPH-F999;Lo;0;L;84EE;;;;N;;;;; +F99A;CJK COMPATIBILITY IDEOGRAPH-F99A;Lo;0;L;9023;;;;N;;;;; +F99B;CJK COMPATIBILITY IDEOGRAPH-F99B;Lo;0;L;934A;;;;N;;;;; +F99C;CJK COMPATIBILITY IDEOGRAPH-F99C;Lo;0;L;5217;;;;N;;;;; +F99D;CJK COMPATIBILITY IDEOGRAPH-F99D;Lo;0;L;52A3;;;;N;;;;; +F99E;CJK COMPATIBILITY IDEOGRAPH-F99E;Lo;0;L;54BD;;;;N;;;;; +F99F;CJK COMPATIBILITY IDEOGRAPH-F99F;Lo;0;L;70C8;;;;N;;;;; +F9A0;CJK COMPATIBILITY IDEOGRAPH-F9A0;Lo;0;L;88C2;;;;N;;;;; +F9A1;CJK COMPATIBILITY IDEOGRAPH-F9A1;Lo;0;L;8AAA;;;;N;;;;; +F9A2;CJK COMPATIBILITY IDEOGRAPH-F9A2;Lo;0;L;5EC9;;;;N;;;;; +F9A3;CJK COMPATIBILITY IDEOGRAPH-F9A3;Lo;0;L;5FF5;;;;N;;;;; +F9A4;CJK COMPATIBILITY IDEOGRAPH-F9A4;Lo;0;L;637B;;;;N;;;;; +F9A5;CJK COMPATIBILITY IDEOGRAPH-F9A5;Lo;0;L;6BAE;;;;N;;;;; +F9A6;CJK COMPATIBILITY IDEOGRAPH-F9A6;Lo;0;L;7C3E;;;;N;;;;; +F9A7;CJK COMPATIBILITY IDEOGRAPH-F9A7;Lo;0;L;7375;;;;N;;;;; +F9A8;CJK COMPATIBILITY IDEOGRAPH-F9A8;Lo;0;L;4EE4;;;;N;;;;; +F9A9;CJK COMPATIBILITY IDEOGRAPH-F9A9;Lo;0;L;56F9;;;;N;;;;; +F9AA;CJK COMPATIBILITY IDEOGRAPH-F9AA;Lo;0;L;5BE7;;;;N;;;;; +F9AB;CJK COMPATIBILITY IDEOGRAPH-F9AB;Lo;0;L;5DBA;;;;N;;;;; +F9AC;CJK COMPATIBILITY IDEOGRAPH-F9AC;Lo;0;L;601C;;;;N;;;;; +F9AD;CJK COMPATIBILITY IDEOGRAPH-F9AD;Lo;0;L;73B2;;;;N;;;;; +F9AE;CJK COMPATIBILITY IDEOGRAPH-F9AE;Lo;0;L;7469;;;;N;;;;; +F9AF;CJK COMPATIBILITY IDEOGRAPH-F9AF;Lo;0;L;7F9A;;;;N;;;;; +F9B0;CJK COMPATIBILITY IDEOGRAPH-F9B0;Lo;0;L;8046;;;;N;;;;; +F9B1;CJK COMPATIBILITY IDEOGRAPH-F9B1;Lo;0;L;9234;;;;N;;;;; +F9B2;CJK COMPATIBILITY IDEOGRAPH-F9B2;Lo;0;L;96F6;;;0;N;;;;; +F9B3;CJK COMPATIBILITY IDEOGRAPH-F9B3;Lo;0;L;9748;;;;N;;;;; +F9B4;CJK COMPATIBILITY IDEOGRAPH-F9B4;Lo;0;L;9818;;;;N;;;;; +F9B5;CJK COMPATIBILITY IDEOGRAPH-F9B5;Lo;0;L;4F8B;;;;N;;;;; +F9B6;CJK COMPATIBILITY IDEOGRAPH-F9B6;Lo;0;L;79AE;;;;N;;;;; +F9B7;CJK COMPATIBILITY IDEOGRAPH-F9B7;Lo;0;L;91B4;;;;N;;;;; +F9B8;CJK COMPATIBILITY IDEOGRAPH-F9B8;Lo;0;L;96B8;;;;N;;;;; +F9B9;CJK COMPATIBILITY IDEOGRAPH-F9B9;Lo;0;L;60E1;;;;N;;;;; +F9BA;CJK COMPATIBILITY IDEOGRAPH-F9BA;Lo;0;L;4E86;;;;N;;;;; +F9BB;CJK COMPATIBILITY IDEOGRAPH-F9BB;Lo;0;L;50DA;;;;N;;;;; +F9BC;CJK COMPATIBILITY IDEOGRAPH-F9BC;Lo;0;L;5BEE;;;;N;;;;; +F9BD;CJK COMPATIBILITY IDEOGRAPH-F9BD;Lo;0;L;5C3F;;;;N;;;;; +F9BE;CJK COMPATIBILITY IDEOGRAPH-F9BE;Lo;0;L;6599;;;;N;;;;; +F9BF;CJK COMPATIBILITY IDEOGRAPH-F9BF;Lo;0;L;6A02;;;;N;;;;; +F9C0;CJK COMPATIBILITY IDEOGRAPH-F9C0;Lo;0;L;71CE;;;;N;;;;; +F9C1;CJK COMPATIBILITY IDEOGRAPH-F9C1;Lo;0;L;7642;;;;N;;;;; +F9C2;CJK COMPATIBILITY IDEOGRAPH-F9C2;Lo;0;L;84FC;;;;N;;;;; +F9C3;CJK COMPATIBILITY IDEOGRAPH-F9C3;Lo;0;L;907C;;;;N;;;;; +F9C4;CJK COMPATIBILITY IDEOGRAPH-F9C4;Lo;0;L;9F8D;;;;N;;;;; +F9C5;CJK COMPATIBILITY IDEOGRAPH-F9C5;Lo;0;L;6688;;;;N;;;;; +F9C6;CJK COMPATIBILITY IDEOGRAPH-F9C6;Lo;0;L;962E;;;;N;;;;; +F9C7;CJK COMPATIBILITY IDEOGRAPH-F9C7;Lo;0;L;5289;;;;N;;;;; +F9C8;CJK COMPATIBILITY IDEOGRAPH-F9C8;Lo;0;L;677B;;;;N;;;;; +F9C9;CJK COMPATIBILITY IDEOGRAPH-F9C9;Lo;0;L;67F3;;;;N;;;;; +F9CA;CJK COMPATIBILITY IDEOGRAPH-F9CA;Lo;0;L;6D41;;;;N;;;;; +F9CB;CJK COMPATIBILITY IDEOGRAPH-F9CB;Lo;0;L;6E9C;;;;N;;;;; +F9CC;CJK COMPATIBILITY IDEOGRAPH-F9CC;Lo;0;L;7409;;;;N;;;;; +F9CD;CJK COMPATIBILITY IDEOGRAPH-F9CD;Lo;0;L;7559;;;;N;;;;; +F9CE;CJK COMPATIBILITY IDEOGRAPH-F9CE;Lo;0;L;786B;;;;N;;;;; +F9CF;CJK COMPATIBILITY IDEOGRAPH-F9CF;Lo;0;L;7D10;;;;N;;;;; +F9D0;CJK COMPATIBILITY IDEOGRAPH-F9D0;Lo;0;L;985E;;;;N;;;;; +F9D1;CJK COMPATIBILITY IDEOGRAPH-F9D1;Lo;0;L;516D;;;6;N;;;;; +F9D2;CJK COMPATIBILITY IDEOGRAPH-F9D2;Lo;0;L;622E;;;;N;;;;; +F9D3;CJK COMPATIBILITY IDEOGRAPH-F9D3;Lo;0;L;9678;;;6;N;;;;; +F9D4;CJK COMPATIBILITY IDEOGRAPH-F9D4;Lo;0;L;502B;;;;N;;;;; +F9D5;CJK COMPATIBILITY IDEOGRAPH-F9D5;Lo;0;L;5D19;;;;N;;;;; +F9D6;CJK COMPATIBILITY IDEOGRAPH-F9D6;Lo;0;L;6DEA;;;;N;;;;; +F9D7;CJK COMPATIBILITY IDEOGRAPH-F9D7;Lo;0;L;8F2A;;;;N;;;;; +F9D8;CJK COMPATIBILITY IDEOGRAPH-F9D8;Lo;0;L;5F8B;;;;N;;;;; +F9D9;CJK COMPATIBILITY IDEOGRAPH-F9D9;Lo;0;L;6144;;;;N;;;;; +F9DA;CJK COMPATIBILITY IDEOGRAPH-F9DA;Lo;0;L;6817;;;;N;;;;; +F9DB;CJK COMPATIBILITY IDEOGRAPH-F9DB;Lo;0;L;7387;;;;N;;;;; +F9DC;CJK COMPATIBILITY IDEOGRAPH-F9DC;Lo;0;L;9686;;;;N;;;;; +F9DD;CJK COMPATIBILITY IDEOGRAPH-F9DD;Lo;0;L;5229;;;;N;;;;; +F9DE;CJK COMPATIBILITY IDEOGRAPH-F9DE;Lo;0;L;540F;;;;N;;;;; +F9DF;CJK COMPATIBILITY IDEOGRAPH-F9DF;Lo;0;L;5C65;;;;N;;;;; +F9E0;CJK COMPATIBILITY IDEOGRAPH-F9E0;Lo;0;L;6613;;;;N;;;;; +F9E1;CJK COMPATIBILITY IDEOGRAPH-F9E1;Lo;0;L;674E;;;;N;;;;; +F9E2;CJK COMPATIBILITY IDEOGRAPH-F9E2;Lo;0;L;68A8;;;;N;;;;; +F9E3;CJK COMPATIBILITY IDEOGRAPH-F9E3;Lo;0;L;6CE5;;;;N;;;;; +F9E4;CJK COMPATIBILITY IDEOGRAPH-F9E4;Lo;0;L;7406;;;;N;;;;; +F9E5;CJK COMPATIBILITY IDEOGRAPH-F9E5;Lo;0;L;75E2;;;;N;;;;; +F9E6;CJK COMPATIBILITY IDEOGRAPH-F9E6;Lo;0;L;7F79;;;;N;;;;; +F9E7;CJK COMPATIBILITY IDEOGRAPH-F9E7;Lo;0;L;88CF;;;;N;;;;; +F9E8;CJK COMPATIBILITY IDEOGRAPH-F9E8;Lo;0;L;88E1;;;;N;;;;; +F9E9;CJK COMPATIBILITY IDEOGRAPH-F9E9;Lo;0;L;91CC;;;;N;;;;; +F9EA;CJK COMPATIBILITY IDEOGRAPH-F9EA;Lo;0;L;96E2;;;;N;;;;; +F9EB;CJK COMPATIBILITY IDEOGRAPH-F9EB;Lo;0;L;533F;;;;N;;;;; +F9EC;CJK COMPATIBILITY IDEOGRAPH-F9EC;Lo;0;L;6EBA;;;;N;;;;; +F9ED;CJK COMPATIBILITY IDEOGRAPH-F9ED;Lo;0;L;541D;;;;N;;;;; +F9EE;CJK COMPATIBILITY IDEOGRAPH-F9EE;Lo;0;L;71D0;;;;N;;;;; +F9EF;CJK COMPATIBILITY IDEOGRAPH-F9EF;Lo;0;L;7498;;;;N;;;;; +F9F0;CJK COMPATIBILITY IDEOGRAPH-F9F0;Lo;0;L;85FA;;;;N;;;;; +F9F1;CJK COMPATIBILITY IDEOGRAPH-F9F1;Lo;0;L;96A3;;;;N;;;;; +F9F2;CJK COMPATIBILITY IDEOGRAPH-F9F2;Lo;0;L;9C57;;;;N;;;;; +F9F3;CJK COMPATIBILITY IDEOGRAPH-F9F3;Lo;0;L;9E9F;;;;N;;;;; +F9F4;CJK COMPATIBILITY IDEOGRAPH-F9F4;Lo;0;L;6797;;;;N;;;;; +F9F5;CJK COMPATIBILITY IDEOGRAPH-F9F5;Lo;0;L;6DCB;;;;N;;;;; +F9F6;CJK COMPATIBILITY IDEOGRAPH-F9F6;Lo;0;L;81E8;;;;N;;;;; +F9F7;CJK COMPATIBILITY IDEOGRAPH-F9F7;Lo;0;L;7ACB;;;;N;;;;; +F9F8;CJK COMPATIBILITY IDEOGRAPH-F9F8;Lo;0;L;7B20;;;;N;;;;; +F9F9;CJK COMPATIBILITY IDEOGRAPH-F9F9;Lo;0;L;7C92;;;;N;;;;; +F9FA;CJK COMPATIBILITY IDEOGRAPH-F9FA;Lo;0;L;72C0;;;;N;;;;; +F9FB;CJK COMPATIBILITY IDEOGRAPH-F9FB;Lo;0;L;7099;;;;N;;;;; +F9FC;CJK COMPATIBILITY IDEOGRAPH-F9FC;Lo;0;L;8B58;;;;N;;;;; +F9FD;CJK COMPATIBILITY IDEOGRAPH-F9FD;Lo;0;L;4EC0;;;10;N;;;;; +F9FE;CJK COMPATIBILITY IDEOGRAPH-F9FE;Lo;0;L;8336;;;;N;;;;; +F9FF;CJK COMPATIBILITY IDEOGRAPH-F9FF;Lo;0;L;523A;;;;N;;;;; +FA00;CJK COMPATIBILITY IDEOGRAPH-FA00;Lo;0;L;5207;;;;N;;;;; +FA01;CJK COMPATIBILITY IDEOGRAPH-FA01;Lo;0;L;5EA6;;;;N;;;;; +FA02;CJK COMPATIBILITY IDEOGRAPH-FA02;Lo;0;L;62D3;;;;N;;;;; +FA03;CJK COMPATIBILITY IDEOGRAPH-FA03;Lo;0;L;7CD6;;;;N;;;;; +FA04;CJK COMPATIBILITY IDEOGRAPH-FA04;Lo;0;L;5B85;;;;N;;;;; +FA05;CJK COMPATIBILITY IDEOGRAPH-FA05;Lo;0;L;6D1E;;;;N;;;;; +FA06;CJK COMPATIBILITY IDEOGRAPH-FA06;Lo;0;L;66B4;;;;N;;;;; +FA07;CJK COMPATIBILITY IDEOGRAPH-FA07;Lo;0;L;8F3B;;;;N;;;;; +FA08;CJK COMPATIBILITY IDEOGRAPH-FA08;Lo;0;L;884C;;;;N;;;;; +FA09;CJK COMPATIBILITY IDEOGRAPH-FA09;Lo;0;L;964D;;;;N;;;;; +FA0A;CJK COMPATIBILITY IDEOGRAPH-FA0A;Lo;0;L;898B;;;;N;;;;; +FA0B;CJK COMPATIBILITY IDEOGRAPH-FA0B;Lo;0;L;5ED3;;;;N;;;;; +FA0C;CJK COMPATIBILITY IDEOGRAPH-FA0C;Lo;0;L;5140;;;;N;;;;; +FA0D;CJK COMPATIBILITY IDEOGRAPH-FA0D;Lo;0;L;55C0;;;;N;;;;; +FA0E;CJK COMPATIBILITY IDEOGRAPH-FA0E;Lo;0;L;;;;;N;;;;; +FA0F;CJK COMPATIBILITY IDEOGRAPH-FA0F;Lo;0;L;;;;;N;;;;; +FA10;CJK COMPATIBILITY IDEOGRAPH-FA10;Lo;0;L;585A;;;;N;;;;; +FA11;CJK COMPATIBILITY IDEOGRAPH-FA11;Lo;0;L;;;;;N;;;;; +FA12;CJK COMPATIBILITY IDEOGRAPH-FA12;Lo;0;L;6674;;;;N;;;;; +FA13;CJK COMPATIBILITY IDEOGRAPH-FA13;Lo;0;L;;;;;N;;;;; +FA14;CJK COMPATIBILITY IDEOGRAPH-FA14;Lo;0;L;;;;;N;;;;; +FA15;CJK COMPATIBILITY IDEOGRAPH-FA15;Lo;0;L;51DE;;;;N;;;;; +FA16;CJK COMPATIBILITY IDEOGRAPH-FA16;Lo;0;L;732A;;;;N;;;;; +FA17;CJK COMPATIBILITY IDEOGRAPH-FA17;Lo;0;L;76CA;;;;N;;;;; +FA18;CJK COMPATIBILITY IDEOGRAPH-FA18;Lo;0;L;793C;;;;N;;;;; +FA19;CJK COMPATIBILITY IDEOGRAPH-FA19;Lo;0;L;795E;;;;N;;;;; +FA1A;CJK COMPATIBILITY IDEOGRAPH-FA1A;Lo;0;L;7965;;;;N;;;;; +FA1B;CJK COMPATIBILITY IDEOGRAPH-FA1B;Lo;0;L;798F;;;;N;;;;; +FA1C;CJK COMPATIBILITY IDEOGRAPH-FA1C;Lo;0;L;9756;;;;N;;;;; +FA1D;CJK COMPATIBILITY IDEOGRAPH-FA1D;Lo;0;L;7CBE;;;;N;;;;; +FA1E;CJK COMPATIBILITY IDEOGRAPH-FA1E;Lo;0;L;7FBD;;;;N;;;;; +FA1F;CJK COMPATIBILITY IDEOGRAPH-FA1F;Lo;0;L;;;;;N;;;;; +FA20;CJK COMPATIBILITY IDEOGRAPH-FA20;Lo;0;L;8612;;;;N;;;;; +FA21;CJK COMPATIBILITY IDEOGRAPH-FA21;Lo;0;L;;;;;N;;;;; +FA22;CJK COMPATIBILITY IDEOGRAPH-FA22;Lo;0;L;8AF8;;;;N;;;;; +FA23;CJK COMPATIBILITY IDEOGRAPH-FA23;Lo;0;L;;;;;N;;;;; +FA24;CJK COMPATIBILITY IDEOGRAPH-FA24;Lo;0;L;;;;;N;;;;; +FA25;CJK COMPATIBILITY IDEOGRAPH-FA25;Lo;0;L;9038;;;;N;;;;; +FA26;CJK COMPATIBILITY IDEOGRAPH-FA26;Lo;0;L;90FD;;;;N;;;;; +FA27;CJK COMPATIBILITY IDEOGRAPH-FA27;Lo;0;L;;;;;N;;;;; +FA28;CJK COMPATIBILITY IDEOGRAPH-FA28;Lo;0;L;;;;;N;;;;; +FA29;CJK COMPATIBILITY IDEOGRAPH-FA29;Lo;0;L;;;;;N;;;;; +FA2A;CJK COMPATIBILITY IDEOGRAPH-FA2A;Lo;0;L;98EF;;;;N;;;;; +FA2B;CJK COMPATIBILITY IDEOGRAPH-FA2B;Lo;0;L;98FC;;;;N;;;;; +FA2C;CJK COMPATIBILITY IDEOGRAPH-FA2C;Lo;0;L;9928;;;;N;;;;; +FA2D;CJK COMPATIBILITY IDEOGRAPH-FA2D;Lo;0;L;9DB4;;;;N;;;;; +FA2E;CJK COMPATIBILITY IDEOGRAPH-FA2E;Lo;0;L;90DE;;;;N;;;;; +FA2F;CJK COMPATIBILITY IDEOGRAPH-FA2F;Lo;0;L;96B7;;;;N;;;;; +FA30;CJK COMPATIBILITY IDEOGRAPH-FA30;Lo;0;L;4FAE;;;;N;;;;; +FA31;CJK COMPATIBILITY IDEOGRAPH-FA31;Lo;0;L;50E7;;;;N;;;;; +FA32;CJK COMPATIBILITY IDEOGRAPH-FA32;Lo;0;L;514D;;;;N;;;;; +FA33;CJK COMPATIBILITY IDEOGRAPH-FA33;Lo;0;L;52C9;;;;N;;;;; +FA34;CJK COMPATIBILITY IDEOGRAPH-FA34;Lo;0;L;52E4;;;;N;;;;; +FA35;CJK COMPATIBILITY IDEOGRAPH-FA35;Lo;0;L;5351;;;;N;;;;; +FA36;CJK COMPATIBILITY IDEOGRAPH-FA36;Lo;0;L;559D;;;;N;;;;; +FA37;CJK COMPATIBILITY IDEOGRAPH-FA37;Lo;0;L;5606;;;;N;;;;; +FA38;CJK COMPATIBILITY IDEOGRAPH-FA38;Lo;0;L;5668;;;;N;;;;; +FA39;CJK COMPATIBILITY IDEOGRAPH-FA39;Lo;0;L;5840;;;;N;;;;; +FA3A;CJK COMPATIBILITY IDEOGRAPH-FA3A;Lo;0;L;58A8;;;;N;;;;; +FA3B;CJK COMPATIBILITY IDEOGRAPH-FA3B;Lo;0;L;5C64;;;;N;;;;; +FA3C;CJK COMPATIBILITY IDEOGRAPH-FA3C;Lo;0;L;5C6E;;;;N;;;;; +FA3D;CJK COMPATIBILITY IDEOGRAPH-FA3D;Lo;0;L;6094;;;;N;;;;; +FA3E;CJK COMPATIBILITY IDEOGRAPH-FA3E;Lo;0;L;6168;;;;N;;;;; +FA3F;CJK COMPATIBILITY IDEOGRAPH-FA3F;Lo;0;L;618E;;;;N;;;;; +FA40;CJK COMPATIBILITY IDEOGRAPH-FA40;Lo;0;L;61F2;;;;N;;;;; +FA41;CJK COMPATIBILITY IDEOGRAPH-FA41;Lo;0;L;654F;;;;N;;;;; +FA42;CJK COMPATIBILITY IDEOGRAPH-FA42;Lo;0;L;65E2;;;;N;;;;; +FA43;CJK COMPATIBILITY IDEOGRAPH-FA43;Lo;0;L;6691;;;;N;;;;; +FA44;CJK COMPATIBILITY IDEOGRAPH-FA44;Lo;0;L;6885;;;;N;;;;; +FA45;CJK COMPATIBILITY IDEOGRAPH-FA45;Lo;0;L;6D77;;;;N;;;;; +FA46;CJK COMPATIBILITY IDEOGRAPH-FA46;Lo;0;L;6E1A;;;;N;;;;; +FA47;CJK COMPATIBILITY IDEOGRAPH-FA47;Lo;0;L;6F22;;;;N;;;;; +FA48;CJK COMPATIBILITY IDEOGRAPH-FA48;Lo;0;L;716E;;;;N;;;;; +FA49;CJK COMPATIBILITY IDEOGRAPH-FA49;Lo;0;L;722B;;;;N;;;;; +FA4A;CJK COMPATIBILITY IDEOGRAPH-FA4A;Lo;0;L;7422;;;;N;;;;; +FA4B;CJK COMPATIBILITY IDEOGRAPH-FA4B;Lo;0;L;7891;;;;N;;;;; +FA4C;CJK COMPATIBILITY IDEOGRAPH-FA4C;Lo;0;L;793E;;;;N;;;;; +FA4D;CJK COMPATIBILITY IDEOGRAPH-FA4D;Lo;0;L;7949;;;;N;;;;; +FA4E;CJK COMPATIBILITY IDEOGRAPH-FA4E;Lo;0;L;7948;;;;N;;;;; +FA4F;CJK COMPATIBILITY IDEOGRAPH-FA4F;Lo;0;L;7950;;;;N;;;;; +FA50;CJK COMPATIBILITY IDEOGRAPH-FA50;Lo;0;L;7956;;;;N;;;;; +FA51;CJK COMPATIBILITY IDEOGRAPH-FA51;Lo;0;L;795D;;;;N;;;;; +FA52;CJK COMPATIBILITY IDEOGRAPH-FA52;Lo;0;L;798D;;;;N;;;;; +FA53;CJK COMPATIBILITY IDEOGRAPH-FA53;Lo;0;L;798E;;;;N;;;;; +FA54;CJK COMPATIBILITY IDEOGRAPH-FA54;Lo;0;L;7A40;;;;N;;;;; +FA55;CJK COMPATIBILITY IDEOGRAPH-FA55;Lo;0;L;7A81;;;;N;;;;; +FA56;CJK COMPATIBILITY IDEOGRAPH-FA56;Lo;0;L;7BC0;;;;N;;;;; +FA57;CJK COMPATIBILITY IDEOGRAPH-FA57;Lo;0;L;7DF4;;;;N;;;;; +FA58;CJK COMPATIBILITY IDEOGRAPH-FA58;Lo;0;L;7E09;;;;N;;;;; +FA59;CJK COMPATIBILITY IDEOGRAPH-FA59;Lo;0;L;7E41;;;;N;;;;; +FA5A;CJK COMPATIBILITY IDEOGRAPH-FA5A;Lo;0;L;7F72;;;;N;;;;; +FA5B;CJK COMPATIBILITY IDEOGRAPH-FA5B;Lo;0;L;8005;;;;N;;;;; +FA5C;CJK COMPATIBILITY IDEOGRAPH-FA5C;Lo;0;L;81ED;;;;N;;;;; +FA5D;CJK COMPATIBILITY IDEOGRAPH-FA5D;Lo;0;L;8279;;;;N;;;;; +FA5E;CJK COMPATIBILITY IDEOGRAPH-FA5E;Lo;0;L;8279;;;;N;;;;; +FA5F;CJK COMPATIBILITY IDEOGRAPH-FA5F;Lo;0;L;8457;;;;N;;;;; +FA60;CJK COMPATIBILITY IDEOGRAPH-FA60;Lo;0;L;8910;;;;N;;;;; +FA61;CJK COMPATIBILITY IDEOGRAPH-FA61;Lo;0;L;8996;;;;N;;;;; +FA62;CJK COMPATIBILITY IDEOGRAPH-FA62;Lo;0;L;8B01;;;;N;;;;; +FA63;CJK COMPATIBILITY IDEOGRAPH-FA63;Lo;0;L;8B39;;;;N;;;;; +FA64;CJK COMPATIBILITY IDEOGRAPH-FA64;Lo;0;L;8CD3;;;;N;;;;; +FA65;CJK COMPATIBILITY IDEOGRAPH-FA65;Lo;0;L;8D08;;;;N;;;;; +FA66;CJK COMPATIBILITY IDEOGRAPH-FA66;Lo;0;L;8FB6;;;;N;;;;; +FA67;CJK COMPATIBILITY IDEOGRAPH-FA67;Lo;0;L;9038;;;;N;;;;; +FA68;CJK COMPATIBILITY IDEOGRAPH-FA68;Lo;0;L;96E3;;;;N;;;;; +FA69;CJK COMPATIBILITY IDEOGRAPH-FA69;Lo;0;L;97FF;;;;N;;;;; +FA6A;CJK COMPATIBILITY IDEOGRAPH-FA6A;Lo;0;L;983B;;;;N;;;;; +FA6B;CJK COMPATIBILITY IDEOGRAPH-FA6B;Lo;0;L;6075;;;;N;;;;; +FA6C;CJK COMPATIBILITY IDEOGRAPH-FA6C;Lo;0;L;242EE;;;;N;;;;; +FA6D;CJK COMPATIBILITY IDEOGRAPH-FA6D;Lo;0;L;8218;;;;N;;;;; +FA70;CJK COMPATIBILITY IDEOGRAPH-FA70;Lo;0;L;4E26;;;;N;;;;; +FA71;CJK COMPATIBILITY IDEOGRAPH-FA71;Lo;0;L;51B5;;;;N;;;;; +FA72;CJK COMPATIBILITY IDEOGRAPH-FA72;Lo;0;L;5168;;;;N;;;;; +FA73;CJK COMPATIBILITY IDEOGRAPH-FA73;Lo;0;L;4F80;;;;N;;;;; +FA74;CJK COMPATIBILITY IDEOGRAPH-FA74;Lo;0;L;5145;;;;N;;;;; +FA75;CJK COMPATIBILITY IDEOGRAPH-FA75;Lo;0;L;5180;;;;N;;;;; +FA76;CJK COMPATIBILITY IDEOGRAPH-FA76;Lo;0;L;52C7;;;;N;;;;; +FA77;CJK COMPATIBILITY IDEOGRAPH-FA77;Lo;0;L;52FA;;;;N;;;;; +FA78;CJK COMPATIBILITY IDEOGRAPH-FA78;Lo;0;L;559D;;;;N;;;;; +FA79;CJK COMPATIBILITY IDEOGRAPH-FA79;Lo;0;L;5555;;;;N;;;;; +FA7A;CJK COMPATIBILITY IDEOGRAPH-FA7A;Lo;0;L;5599;;;;N;;;;; +FA7B;CJK COMPATIBILITY IDEOGRAPH-FA7B;Lo;0;L;55E2;;;;N;;;;; +FA7C;CJK COMPATIBILITY IDEOGRAPH-FA7C;Lo;0;L;585A;;;;N;;;;; +FA7D;CJK COMPATIBILITY IDEOGRAPH-FA7D;Lo;0;L;58B3;;;;N;;;;; +FA7E;CJK COMPATIBILITY IDEOGRAPH-FA7E;Lo;0;L;5944;;;;N;;;;; +FA7F;CJK COMPATIBILITY IDEOGRAPH-FA7F;Lo;0;L;5954;;;;N;;;;; +FA80;CJK COMPATIBILITY IDEOGRAPH-FA80;Lo;0;L;5A62;;;;N;;;;; +FA81;CJK COMPATIBILITY IDEOGRAPH-FA81;Lo;0;L;5B28;;;;N;;;;; +FA82;CJK COMPATIBILITY IDEOGRAPH-FA82;Lo;0;L;5ED2;;;;N;;;;; +FA83;CJK COMPATIBILITY IDEOGRAPH-FA83;Lo;0;L;5ED9;;;;N;;;;; +FA84;CJK COMPATIBILITY IDEOGRAPH-FA84;Lo;0;L;5F69;;;;N;;;;; +FA85;CJK COMPATIBILITY IDEOGRAPH-FA85;Lo;0;L;5FAD;;;;N;;;;; +FA86;CJK COMPATIBILITY IDEOGRAPH-FA86;Lo;0;L;60D8;;;;N;;;;; +FA87;CJK COMPATIBILITY IDEOGRAPH-FA87;Lo;0;L;614E;;;;N;;;;; +FA88;CJK COMPATIBILITY IDEOGRAPH-FA88;Lo;0;L;6108;;;;N;;;;; +FA89;CJK COMPATIBILITY IDEOGRAPH-FA89;Lo;0;L;618E;;;;N;;;;; +FA8A;CJK COMPATIBILITY IDEOGRAPH-FA8A;Lo;0;L;6160;;;;N;;;;; +FA8B;CJK COMPATIBILITY IDEOGRAPH-FA8B;Lo;0;L;61F2;;;;N;;;;; +FA8C;CJK COMPATIBILITY IDEOGRAPH-FA8C;Lo;0;L;6234;;;;N;;;;; +FA8D;CJK COMPATIBILITY IDEOGRAPH-FA8D;Lo;0;L;63C4;;;;N;;;;; +FA8E;CJK COMPATIBILITY IDEOGRAPH-FA8E;Lo;0;L;641C;;;;N;;;;; +FA8F;CJK COMPATIBILITY IDEOGRAPH-FA8F;Lo;0;L;6452;;;;N;;;;; +FA90;CJK COMPATIBILITY IDEOGRAPH-FA90;Lo;0;L;6556;;;;N;;;;; +FA91;CJK COMPATIBILITY IDEOGRAPH-FA91;Lo;0;L;6674;;;;N;;;;; +FA92;CJK COMPATIBILITY IDEOGRAPH-FA92;Lo;0;L;6717;;;;N;;;;; +FA93;CJK COMPATIBILITY IDEOGRAPH-FA93;Lo;0;L;671B;;;;N;;;;; +FA94;CJK COMPATIBILITY IDEOGRAPH-FA94;Lo;0;L;6756;;;;N;;;;; +FA95;CJK COMPATIBILITY IDEOGRAPH-FA95;Lo;0;L;6B79;;;;N;;;;; +FA96;CJK COMPATIBILITY IDEOGRAPH-FA96;Lo;0;L;6BBA;;;;N;;;;; +FA97;CJK COMPATIBILITY IDEOGRAPH-FA97;Lo;0;L;6D41;;;;N;;;;; +FA98;CJK COMPATIBILITY IDEOGRAPH-FA98;Lo;0;L;6EDB;;;;N;;;;; +FA99;CJK COMPATIBILITY IDEOGRAPH-FA99;Lo;0;L;6ECB;;;;N;;;;; +FA9A;CJK COMPATIBILITY IDEOGRAPH-FA9A;Lo;0;L;6F22;;;;N;;;;; +FA9B;CJK COMPATIBILITY IDEOGRAPH-FA9B;Lo;0;L;701E;;;;N;;;;; +FA9C;CJK COMPATIBILITY IDEOGRAPH-FA9C;Lo;0;L;716E;;;;N;;;;; +FA9D;CJK COMPATIBILITY IDEOGRAPH-FA9D;Lo;0;L;77A7;;;;N;;;;; +FA9E;CJK COMPATIBILITY IDEOGRAPH-FA9E;Lo;0;L;7235;;;;N;;;;; +FA9F;CJK COMPATIBILITY IDEOGRAPH-FA9F;Lo;0;L;72AF;;;;N;;;;; +FAA0;CJK COMPATIBILITY IDEOGRAPH-FAA0;Lo;0;L;732A;;;;N;;;;; +FAA1;CJK COMPATIBILITY IDEOGRAPH-FAA1;Lo;0;L;7471;;;;N;;;;; +FAA2;CJK COMPATIBILITY IDEOGRAPH-FAA2;Lo;0;L;7506;;;;N;;;;; +FAA3;CJK COMPATIBILITY IDEOGRAPH-FAA3;Lo;0;L;753B;;;;N;;;;; +FAA4;CJK COMPATIBILITY IDEOGRAPH-FAA4;Lo;0;L;761D;;;;N;;;;; +FAA5;CJK COMPATIBILITY IDEOGRAPH-FAA5;Lo;0;L;761F;;;;N;;;;; +FAA6;CJK COMPATIBILITY IDEOGRAPH-FAA6;Lo;0;L;76CA;;;;N;;;;; +FAA7;CJK COMPATIBILITY IDEOGRAPH-FAA7;Lo;0;L;76DB;;;;N;;;;; +FAA8;CJK COMPATIBILITY IDEOGRAPH-FAA8;Lo;0;L;76F4;;;;N;;;;; +FAA9;CJK COMPATIBILITY IDEOGRAPH-FAA9;Lo;0;L;774A;;;;N;;;;; +FAAA;CJK COMPATIBILITY IDEOGRAPH-FAAA;Lo;0;L;7740;;;;N;;;;; +FAAB;CJK COMPATIBILITY IDEOGRAPH-FAAB;Lo;0;L;78CC;;;;N;;;;; +FAAC;CJK COMPATIBILITY IDEOGRAPH-FAAC;Lo;0;L;7AB1;;;;N;;;;; +FAAD;CJK COMPATIBILITY IDEOGRAPH-FAAD;Lo;0;L;7BC0;;;;N;;;;; +FAAE;CJK COMPATIBILITY IDEOGRAPH-FAAE;Lo;0;L;7C7B;;;;N;;;;; +FAAF;CJK COMPATIBILITY IDEOGRAPH-FAAF;Lo;0;L;7D5B;;;;N;;;;; +FAB0;CJK COMPATIBILITY IDEOGRAPH-FAB0;Lo;0;L;7DF4;;;;N;;;;; +FAB1;CJK COMPATIBILITY IDEOGRAPH-FAB1;Lo;0;L;7F3E;;;;N;;;;; +FAB2;CJK COMPATIBILITY IDEOGRAPH-FAB2;Lo;0;L;8005;;;;N;;;;; +FAB3;CJK COMPATIBILITY IDEOGRAPH-FAB3;Lo;0;L;8352;;;;N;;;;; +FAB4;CJK COMPATIBILITY IDEOGRAPH-FAB4;Lo;0;L;83EF;;;;N;;;;; +FAB5;CJK COMPATIBILITY IDEOGRAPH-FAB5;Lo;0;L;8779;;;;N;;;;; +FAB6;CJK COMPATIBILITY IDEOGRAPH-FAB6;Lo;0;L;8941;;;;N;;;;; +FAB7;CJK COMPATIBILITY IDEOGRAPH-FAB7;Lo;0;L;8986;;;;N;;;;; +FAB8;CJK COMPATIBILITY IDEOGRAPH-FAB8;Lo;0;L;8996;;;;N;;;;; +FAB9;CJK COMPATIBILITY IDEOGRAPH-FAB9;Lo;0;L;8ABF;;;;N;;;;; +FABA;CJK COMPATIBILITY IDEOGRAPH-FABA;Lo;0;L;8AF8;;;;N;;;;; +FABB;CJK COMPATIBILITY IDEOGRAPH-FABB;Lo;0;L;8ACB;;;;N;;;;; +FABC;CJK COMPATIBILITY IDEOGRAPH-FABC;Lo;0;L;8B01;;;;N;;;;; +FABD;CJK COMPATIBILITY IDEOGRAPH-FABD;Lo;0;L;8AFE;;;;N;;;;; +FABE;CJK COMPATIBILITY IDEOGRAPH-FABE;Lo;0;L;8AED;;;;N;;;;; +FABF;CJK COMPATIBILITY IDEOGRAPH-FABF;Lo;0;L;8B39;;;;N;;;;; +FAC0;CJK COMPATIBILITY IDEOGRAPH-FAC0;Lo;0;L;8B8A;;;;N;;;;; +FAC1;CJK COMPATIBILITY IDEOGRAPH-FAC1;Lo;0;L;8D08;;;;N;;;;; +FAC2;CJK COMPATIBILITY IDEOGRAPH-FAC2;Lo;0;L;8F38;;;;N;;;;; +FAC3;CJK COMPATIBILITY IDEOGRAPH-FAC3;Lo;0;L;9072;;;;N;;;;; +FAC4;CJK COMPATIBILITY IDEOGRAPH-FAC4;Lo;0;L;9199;;;;N;;;;; +FAC5;CJK COMPATIBILITY IDEOGRAPH-FAC5;Lo;0;L;9276;;;;N;;;;; +FAC6;CJK COMPATIBILITY IDEOGRAPH-FAC6;Lo;0;L;967C;;;;N;;;;; +FAC7;CJK COMPATIBILITY IDEOGRAPH-FAC7;Lo;0;L;96E3;;;;N;;;;; +FAC8;CJK COMPATIBILITY IDEOGRAPH-FAC8;Lo;0;L;9756;;;;N;;;;; +FAC9;CJK COMPATIBILITY IDEOGRAPH-FAC9;Lo;0;L;97DB;;;;N;;;;; +FACA;CJK COMPATIBILITY IDEOGRAPH-FACA;Lo;0;L;97FF;;;;N;;;;; +FACB;CJK COMPATIBILITY IDEOGRAPH-FACB;Lo;0;L;980B;;;;N;;;;; +FACC;CJK COMPATIBILITY IDEOGRAPH-FACC;Lo;0;L;983B;;;;N;;;;; +FACD;CJK COMPATIBILITY IDEOGRAPH-FACD;Lo;0;L;9B12;;;;N;;;;; +FACE;CJK COMPATIBILITY IDEOGRAPH-FACE;Lo;0;L;9F9C;;;;N;;;;; +FACF;CJK COMPATIBILITY IDEOGRAPH-FACF;Lo;0;L;2284A;;;;N;;;;; +FAD0;CJK COMPATIBILITY IDEOGRAPH-FAD0;Lo;0;L;22844;;;;N;;;;; +FAD1;CJK COMPATIBILITY IDEOGRAPH-FAD1;Lo;0;L;233D5;;;;N;;;;; +FAD2;CJK COMPATIBILITY IDEOGRAPH-FAD2;Lo;0;L;3B9D;;;;N;;;;; +FAD3;CJK COMPATIBILITY IDEOGRAPH-FAD3;Lo;0;L;4018;;;;N;;;;; +FAD4;CJK COMPATIBILITY IDEOGRAPH-FAD4;Lo;0;L;4039;;;;N;;;;; +FAD5;CJK COMPATIBILITY IDEOGRAPH-FAD5;Lo;0;L;25249;;;;N;;;;; +FAD6;CJK COMPATIBILITY IDEOGRAPH-FAD6;Lo;0;L;25CD0;;;;N;;;;; +FAD7;CJK COMPATIBILITY IDEOGRAPH-FAD7;Lo;0;L;27ED3;;;;N;;;;; +FAD8;CJK COMPATIBILITY IDEOGRAPH-FAD8;Lo;0;L;9F43;;;;N;;;;; +FAD9;CJK COMPATIBILITY IDEOGRAPH-FAD9;Lo;0;L;9F8E;;;;N;;;;; +FB00;LATIN SMALL LIGATURE FF;Ll;0;L;<compat> 0066 0066;;;;N;;;;; +FB01;LATIN SMALL LIGATURE FI;Ll;0;L;<compat> 0066 0069;;;;N;;;;; +FB02;LATIN SMALL LIGATURE FL;Ll;0;L;<compat> 0066 006C;;;;N;;;;; +FB03;LATIN SMALL LIGATURE FFI;Ll;0;L;<compat> 0066 0066 0069;;;;N;;;;; +FB04;LATIN SMALL LIGATURE FFL;Ll;0;L;<compat> 0066 0066 006C;;;;N;;;;; +FB05;LATIN SMALL LIGATURE LONG S T;Ll;0;L;<compat> 017F 0074;;;;N;;;;; +FB06;LATIN SMALL LIGATURE ST;Ll;0;L;<compat> 0073 0074;;;;N;;;;; +FB13;ARMENIAN SMALL LIGATURE MEN NOW;Ll;0;L;<compat> 0574 0576;;;;N;;;;; +FB14;ARMENIAN SMALL LIGATURE MEN ECH;Ll;0;L;<compat> 0574 0565;;;;N;;;;; +FB15;ARMENIAN SMALL LIGATURE MEN INI;Ll;0;L;<compat> 0574 056B;;;;N;;;;; +FB16;ARMENIAN SMALL LIGATURE VEW NOW;Ll;0;L;<compat> 057E 0576;;;;N;;;;; +FB17;ARMENIAN SMALL LIGATURE MEN XEH;Ll;0;L;<compat> 0574 056D;;;;N;;;;; +FB1D;HEBREW LETTER YOD WITH HIRIQ;Lo;0;R;05D9 05B4;;;;N;;;;; +FB1E;HEBREW POINT JUDEO-SPANISH VARIKA;Mn;26;NSM;;;;;N;HEBREW POINT VARIKA;;;; +FB1F;HEBREW LIGATURE YIDDISH YOD YOD PATAH;Lo;0;R;05F2 05B7;;;;N;;;;; +FB20;HEBREW LETTER ALTERNATIVE AYIN;Lo;0;R;<font> 05E2;;;;N;;;;; +FB21;HEBREW LETTER WIDE ALEF;Lo;0;R;<font> 05D0;;;;N;;;;; +FB22;HEBREW LETTER WIDE DALET;Lo;0;R;<font> 05D3;;;;N;;;;; +FB23;HEBREW LETTER WIDE HE;Lo;0;R;<font> 05D4;;;;N;;;;; +FB24;HEBREW LETTER WIDE KAF;Lo;0;R;<font> 05DB;;;;N;;;;; +FB25;HEBREW LETTER WIDE LAMED;Lo;0;R;<font> 05DC;;;;N;;;;; +FB26;HEBREW LETTER WIDE FINAL MEM;Lo;0;R;<font> 05DD;;;;N;;;;; +FB27;HEBREW LETTER WIDE RESH;Lo;0;R;<font> 05E8;;;;N;;;;; +FB28;HEBREW LETTER WIDE TAV;Lo;0;R;<font> 05EA;;;;N;;;;; +FB29;HEBREW LETTER ALTERNATIVE PLUS SIGN;Sm;0;ES;<font> 002B;;;;N;;;;; +FB2A;HEBREW LETTER SHIN WITH SHIN DOT;Lo;0;R;05E9 05C1;;;;N;;;;; +FB2B;HEBREW LETTER SHIN WITH SIN DOT;Lo;0;R;05E9 05C2;;;;N;;;;; +FB2C;HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT;Lo;0;R;FB49 05C1;;;;N;;;;; +FB2D;HEBREW LETTER SHIN WITH DAGESH AND SIN DOT;Lo;0;R;FB49 05C2;;;;N;;;;; +FB2E;HEBREW LETTER ALEF WITH PATAH;Lo;0;R;05D0 05B7;;;;N;;;;; +FB2F;HEBREW LETTER ALEF WITH QAMATS;Lo;0;R;05D0 05B8;;;;N;;;;; +FB30;HEBREW LETTER ALEF WITH MAPIQ;Lo;0;R;05D0 05BC;;;;N;;;;; +FB31;HEBREW LETTER BET WITH DAGESH;Lo;0;R;05D1 05BC;;;;N;;;;; +FB32;HEBREW LETTER GIMEL WITH DAGESH;Lo;0;R;05D2 05BC;;;;N;;;;; +FB33;HEBREW LETTER DALET WITH DAGESH;Lo;0;R;05D3 05BC;;;;N;;;;; +FB34;HEBREW LETTER HE WITH MAPIQ;Lo;0;R;05D4 05BC;;;;N;;;;; +FB35;HEBREW LETTER VAV WITH DAGESH;Lo;0;R;05D5 05BC;;;;N;;;;; +FB36;HEBREW LETTER ZAYIN WITH DAGESH;Lo;0;R;05D6 05BC;;;;N;;;;; +FB38;HEBREW LETTER TET WITH DAGESH;Lo;0;R;05D8 05BC;;;;N;;;;; +FB39;HEBREW LETTER YOD WITH DAGESH;Lo;0;R;05D9 05BC;;;;N;;;;; +FB3A;HEBREW LETTER FINAL KAF WITH DAGESH;Lo;0;R;05DA 05BC;;;;N;;;;; +FB3B;HEBREW LETTER KAF WITH DAGESH;Lo;0;R;05DB 05BC;;;;N;;;;; +FB3C;HEBREW LETTER LAMED WITH DAGESH;Lo;0;R;05DC 05BC;;;;N;;;;; +FB3E;HEBREW LETTER MEM WITH DAGESH;Lo;0;R;05DE 05BC;;;;N;;;;; +FB40;HEBREW LETTER NUN WITH DAGESH;Lo;0;R;05E0 05BC;;;;N;;;;; +FB41;HEBREW LETTER SAMEKH WITH DAGESH;Lo;0;R;05E1 05BC;;;;N;;;;; +FB43;HEBREW LETTER FINAL PE WITH DAGESH;Lo;0;R;05E3 05BC;;;;N;;;;; +FB44;HEBREW LETTER PE WITH DAGESH;Lo;0;R;05E4 05BC;;;;N;;;;; +FB46;HEBREW LETTER TSADI WITH DAGESH;Lo;0;R;05E6 05BC;;;;N;;;;; +FB47;HEBREW LETTER QOF WITH DAGESH;Lo;0;R;05E7 05BC;;;;N;;;;; +FB48;HEBREW LETTER RESH WITH DAGESH;Lo;0;R;05E8 05BC;;;;N;;;;; +FB49;HEBREW LETTER SHIN WITH DAGESH;Lo;0;R;05E9 05BC;;;;N;;;;; +FB4A;HEBREW LETTER TAV WITH DAGESH;Lo;0;R;05EA 05BC;;;;N;;;;; +FB4B;HEBREW LETTER VAV WITH HOLAM;Lo;0;R;05D5 05B9;;;;N;;;;; +FB4C;HEBREW LETTER BET WITH RAFE;Lo;0;R;05D1 05BF;;;;N;;;;; +FB4D;HEBREW LETTER KAF WITH RAFE;Lo;0;R;05DB 05BF;;;;N;;;;; +FB4E;HEBREW LETTER PE WITH RAFE;Lo;0;R;05E4 05BF;;;;N;;;;; +FB4F;HEBREW LIGATURE ALEF LAMED;Lo;0;R;<compat> 05D0 05DC;;;;N;;;;; +FB50;ARABIC LETTER ALEF WASLA ISOLATED FORM;Lo;0;AL;<isolated> 0671;;;;N;;;;; +FB51;ARABIC LETTER ALEF WASLA FINAL FORM;Lo;0;AL;<final> 0671;;;;N;;;;; +FB52;ARABIC LETTER BEEH ISOLATED FORM;Lo;0;AL;<isolated> 067B;;;;N;;;;; +FB53;ARABIC LETTER BEEH FINAL FORM;Lo;0;AL;<final> 067B;;;;N;;;;; +FB54;ARABIC LETTER BEEH INITIAL FORM;Lo;0;AL;<initial> 067B;;;;N;;;;; +FB55;ARABIC LETTER BEEH MEDIAL FORM;Lo;0;AL;<medial> 067B;;;;N;;;;; +FB56;ARABIC LETTER PEH ISOLATED FORM;Lo;0;AL;<isolated> 067E;;;;N;;;;; +FB57;ARABIC LETTER PEH FINAL FORM;Lo;0;AL;<final> 067E;;;;N;;;;; +FB58;ARABIC LETTER PEH INITIAL FORM;Lo;0;AL;<initial> 067E;;;;N;;;;; +FB59;ARABIC LETTER PEH MEDIAL FORM;Lo;0;AL;<medial> 067E;;;;N;;;;; +FB5A;ARABIC LETTER BEHEH ISOLATED FORM;Lo;0;AL;<isolated> 0680;;;;N;;;;; +FB5B;ARABIC LETTER BEHEH FINAL FORM;Lo;0;AL;<final> 0680;;;;N;;;;; +FB5C;ARABIC LETTER BEHEH INITIAL FORM;Lo;0;AL;<initial> 0680;;;;N;;;;; +FB5D;ARABIC LETTER BEHEH MEDIAL FORM;Lo;0;AL;<medial> 0680;;;;N;;;;; +FB5E;ARABIC LETTER TTEHEH ISOLATED FORM;Lo;0;AL;<isolated> 067A;;;;N;;;;; +FB5F;ARABIC LETTER TTEHEH FINAL FORM;Lo;0;AL;<final> 067A;;;;N;;;;; +FB60;ARABIC LETTER TTEHEH INITIAL FORM;Lo;0;AL;<initial> 067A;;;;N;;;;; +FB61;ARABIC LETTER TTEHEH MEDIAL FORM;Lo;0;AL;<medial> 067A;;;;N;;;;; +FB62;ARABIC LETTER TEHEH ISOLATED FORM;Lo;0;AL;<isolated> 067F;;;;N;;;;; +FB63;ARABIC LETTER TEHEH FINAL FORM;Lo;0;AL;<final> 067F;;;;N;;;;; +FB64;ARABIC LETTER TEHEH INITIAL FORM;Lo;0;AL;<initial> 067F;;;;N;;;;; +FB65;ARABIC LETTER TEHEH MEDIAL FORM;Lo;0;AL;<medial> 067F;;;;N;;;;; +FB66;ARABIC LETTER TTEH ISOLATED FORM;Lo;0;AL;<isolated> 0679;;;;N;;;;; +FB67;ARABIC LETTER TTEH FINAL FORM;Lo;0;AL;<final> 0679;;;;N;;;;; +FB68;ARABIC LETTER TTEH INITIAL FORM;Lo;0;AL;<initial> 0679;;;;N;;;;; +FB69;ARABIC LETTER TTEH MEDIAL FORM;Lo;0;AL;<medial> 0679;;;;N;;;;; +FB6A;ARABIC LETTER VEH ISOLATED FORM;Lo;0;AL;<isolated> 06A4;;;;N;;;;; +FB6B;ARABIC LETTER VEH FINAL FORM;Lo;0;AL;<final> 06A4;;;;N;;;;; +FB6C;ARABIC LETTER VEH INITIAL FORM;Lo;0;AL;<initial> 06A4;;;;N;;;;; +FB6D;ARABIC LETTER VEH MEDIAL FORM;Lo;0;AL;<medial> 06A4;;;;N;;;;; +FB6E;ARABIC LETTER PEHEH ISOLATED FORM;Lo;0;AL;<isolated> 06A6;;;;N;;;;; +FB6F;ARABIC LETTER PEHEH FINAL FORM;Lo;0;AL;<final> 06A6;;;;N;;;;; +FB70;ARABIC LETTER PEHEH INITIAL FORM;Lo;0;AL;<initial> 06A6;;;;N;;;;; +FB71;ARABIC LETTER PEHEH MEDIAL FORM;Lo;0;AL;<medial> 06A6;;;;N;;;;; +FB72;ARABIC LETTER DYEH ISOLATED FORM;Lo;0;AL;<isolated> 0684;;;;N;;;;; +FB73;ARABIC LETTER DYEH FINAL FORM;Lo;0;AL;<final> 0684;;;;N;;;;; +FB74;ARABIC LETTER DYEH INITIAL FORM;Lo;0;AL;<initial> 0684;;;;N;;;;; +FB75;ARABIC LETTER DYEH MEDIAL FORM;Lo;0;AL;<medial> 0684;;;;N;;;;; +FB76;ARABIC LETTER NYEH ISOLATED FORM;Lo;0;AL;<isolated> 0683;;;;N;;;;; +FB77;ARABIC LETTER NYEH FINAL FORM;Lo;0;AL;<final> 0683;;;;N;;;;; +FB78;ARABIC LETTER NYEH INITIAL FORM;Lo;0;AL;<initial> 0683;;;;N;;;;; +FB79;ARABIC LETTER NYEH MEDIAL FORM;Lo;0;AL;<medial> 0683;;;;N;;;;; +FB7A;ARABIC LETTER TCHEH ISOLATED FORM;Lo;0;AL;<isolated> 0686;;;;N;;;;; +FB7B;ARABIC LETTER TCHEH FINAL FORM;Lo;0;AL;<final> 0686;;;;N;;;;; +FB7C;ARABIC LETTER TCHEH INITIAL FORM;Lo;0;AL;<initial> 0686;;;;N;;;;; +FB7D;ARABIC LETTER TCHEH MEDIAL FORM;Lo;0;AL;<medial> 0686;;;;N;;;;; +FB7E;ARABIC LETTER TCHEHEH ISOLATED FORM;Lo;0;AL;<isolated> 0687;;;;N;;;;; +FB7F;ARABIC LETTER TCHEHEH FINAL FORM;Lo;0;AL;<final> 0687;;;;N;;;;; +FB80;ARABIC LETTER TCHEHEH INITIAL FORM;Lo;0;AL;<initial> 0687;;;;N;;;;; +FB81;ARABIC LETTER TCHEHEH MEDIAL FORM;Lo;0;AL;<medial> 0687;;;;N;;;;; +FB82;ARABIC LETTER DDAHAL ISOLATED FORM;Lo;0;AL;<isolated> 068D;;;;N;;;;; +FB83;ARABIC LETTER DDAHAL FINAL FORM;Lo;0;AL;<final> 068D;;;;N;;;;; +FB84;ARABIC LETTER DAHAL ISOLATED FORM;Lo;0;AL;<isolated> 068C;;;;N;;;;; +FB85;ARABIC LETTER DAHAL FINAL FORM;Lo;0;AL;<final> 068C;;;;N;;;;; +FB86;ARABIC LETTER DUL ISOLATED FORM;Lo;0;AL;<isolated> 068E;;;;N;;;;; +FB87;ARABIC LETTER DUL FINAL FORM;Lo;0;AL;<final> 068E;;;;N;;;;; +FB88;ARABIC LETTER DDAL ISOLATED FORM;Lo;0;AL;<isolated> 0688;;;;N;;;;; +FB89;ARABIC LETTER DDAL FINAL FORM;Lo;0;AL;<final> 0688;;;;N;;;;; +FB8A;ARABIC LETTER JEH ISOLATED FORM;Lo;0;AL;<isolated> 0698;;;;N;;;;; +FB8B;ARABIC LETTER JEH FINAL FORM;Lo;0;AL;<final> 0698;;;;N;;;;; +FB8C;ARABIC LETTER RREH ISOLATED FORM;Lo;0;AL;<isolated> 0691;;;;N;;;;; +FB8D;ARABIC LETTER RREH FINAL FORM;Lo;0;AL;<final> 0691;;;;N;;;;; +FB8E;ARABIC LETTER KEHEH ISOLATED FORM;Lo;0;AL;<isolated> 06A9;;;;N;;;;; +FB8F;ARABIC LETTER KEHEH FINAL FORM;Lo;0;AL;<final> 06A9;;;;N;;;;; +FB90;ARABIC LETTER KEHEH INITIAL FORM;Lo;0;AL;<initial> 06A9;;;;N;;;;; +FB91;ARABIC LETTER KEHEH MEDIAL FORM;Lo;0;AL;<medial> 06A9;;;;N;;;;; +FB92;ARABIC LETTER GAF ISOLATED FORM;Lo;0;AL;<isolated> 06AF;;;;N;;;;; +FB93;ARABIC LETTER GAF FINAL FORM;Lo;0;AL;<final> 06AF;;;;N;;;;; +FB94;ARABIC LETTER GAF INITIAL FORM;Lo;0;AL;<initial> 06AF;;;;N;;;;; +FB95;ARABIC LETTER GAF MEDIAL FORM;Lo;0;AL;<medial> 06AF;;;;N;;;;; +FB96;ARABIC LETTER GUEH ISOLATED FORM;Lo;0;AL;<isolated> 06B3;;;;N;;;;; +FB97;ARABIC LETTER GUEH FINAL FORM;Lo;0;AL;<final> 06B3;;;;N;;;;; +FB98;ARABIC LETTER GUEH INITIAL FORM;Lo;0;AL;<initial> 06B3;;;;N;;;;; +FB99;ARABIC LETTER GUEH MEDIAL FORM;Lo;0;AL;<medial> 06B3;;;;N;;;;; +FB9A;ARABIC LETTER NGOEH ISOLATED FORM;Lo;0;AL;<isolated> 06B1;;;;N;;;;; +FB9B;ARABIC LETTER NGOEH FINAL FORM;Lo;0;AL;<final> 06B1;;;;N;;;;; +FB9C;ARABIC LETTER NGOEH INITIAL FORM;Lo;0;AL;<initial> 06B1;;;;N;;;;; +FB9D;ARABIC LETTER NGOEH MEDIAL FORM;Lo;0;AL;<medial> 06B1;;;;N;;;;; +FB9E;ARABIC LETTER NOON GHUNNA ISOLATED FORM;Lo;0;AL;<isolated> 06BA;;;;N;;;;; +FB9F;ARABIC LETTER NOON GHUNNA FINAL FORM;Lo;0;AL;<final> 06BA;;;;N;;;;; +FBA0;ARABIC LETTER RNOON ISOLATED FORM;Lo;0;AL;<isolated> 06BB;;;;N;;;;; +FBA1;ARABIC LETTER RNOON FINAL FORM;Lo;0;AL;<final> 06BB;;;;N;;;;; +FBA2;ARABIC LETTER RNOON INITIAL FORM;Lo;0;AL;<initial> 06BB;;;;N;;;;; +FBA3;ARABIC LETTER RNOON MEDIAL FORM;Lo;0;AL;<medial> 06BB;;;;N;;;;; +FBA4;ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 06C0;;;;N;;;;; +FBA5;ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM;Lo;0;AL;<final> 06C0;;;;N;;;;; +FBA6;ARABIC LETTER HEH GOAL ISOLATED FORM;Lo;0;AL;<isolated> 06C1;;;;N;;;;; +FBA7;ARABIC LETTER HEH GOAL FINAL FORM;Lo;0;AL;<final> 06C1;;;;N;;;;; +FBA8;ARABIC LETTER HEH GOAL INITIAL FORM;Lo;0;AL;<initial> 06C1;;;;N;;;;; +FBA9;ARABIC LETTER HEH GOAL MEDIAL FORM;Lo;0;AL;<medial> 06C1;;;;N;;;;; +FBAA;ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM;Lo;0;AL;<isolated> 06BE;;;;N;;;;; +FBAB;ARABIC LETTER HEH DOACHASHMEE FINAL FORM;Lo;0;AL;<final> 06BE;;;;N;;;;; +FBAC;ARABIC LETTER HEH DOACHASHMEE INITIAL FORM;Lo;0;AL;<initial> 06BE;;;;N;;;;; +FBAD;ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM;Lo;0;AL;<medial> 06BE;;;;N;;;;; +FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL;<isolated> 06D2;;;;N;;;;; +FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL;<final> 06D2;;;;N;;;;; +FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 06D3;;;;N;;;;; +FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 06D3;;;;N;;;;; +FBB2;ARABIC SYMBOL DOT ABOVE;Sk;0;AL;;;;;N;;;;; +FBB3;ARABIC SYMBOL DOT BELOW;Sk;0;AL;;;;;N;;;;; +FBB4;ARABIC SYMBOL TWO DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB5;ARABIC SYMBOL TWO DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBB6;ARABIC SYMBOL THREE DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB7;ARABIC SYMBOL THREE DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBB8;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB9;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW;Sk;0;AL;;;;;N;;;;; +FBBA;ARABIC SYMBOL FOUR DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBBB;ARABIC SYMBOL FOUR DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBBC;ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW;Sk;0;AL;;;;;N;;;;; +FBBD;ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE;Sk;0;AL;;;;;N;;;;; +FBBE;ARABIC SYMBOL TWO DOTS VERTICALLY BELOW;Sk;0;AL;;;;;N;;;;; +FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;; +FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;; +FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;; +FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL;<isolated> 06AD;;;;N;;;;; +FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL;<final> 06AD;;;;N;;;;; +FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL;<initial> 06AD;;;;N;;;;; +FBD6;ARABIC LETTER NG MEDIAL FORM;Lo;0;AL;<medial> 06AD;;;;N;;;;; +FBD7;ARABIC LETTER U ISOLATED FORM;Lo;0;AL;<isolated> 06C7;;;;N;;;;; +FBD8;ARABIC LETTER U FINAL FORM;Lo;0;AL;<final> 06C7;;;;N;;;;; +FBD9;ARABIC LETTER OE ISOLATED FORM;Lo;0;AL;<isolated> 06C6;;;;N;;;;; +FBDA;ARABIC LETTER OE FINAL FORM;Lo;0;AL;<final> 06C6;;;;N;;;;; +FBDB;ARABIC LETTER YU ISOLATED FORM;Lo;0;AL;<isolated> 06C8;;;;N;;;;; +FBDC;ARABIC LETTER YU FINAL FORM;Lo;0;AL;<final> 06C8;;;;N;;;;; +FBDD;ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0677;;;;N;;;;; +FBDE;ARABIC LETTER VE ISOLATED FORM;Lo;0;AL;<isolated> 06CB;;;;N;;;;; +FBDF;ARABIC LETTER VE FINAL FORM;Lo;0;AL;<final> 06CB;;;;N;;;;; +FBE0;ARABIC LETTER KIRGHIZ OE ISOLATED FORM;Lo;0;AL;<isolated> 06C5;;;;N;;;;; +FBE1;ARABIC LETTER KIRGHIZ OE FINAL FORM;Lo;0;AL;<final> 06C5;;;;N;;;;; +FBE2;ARABIC LETTER KIRGHIZ YU ISOLATED FORM;Lo;0;AL;<isolated> 06C9;;;;N;;;;; +FBE3;ARABIC LETTER KIRGHIZ YU FINAL FORM;Lo;0;AL;<final> 06C9;;;;N;;;;; +FBE4;ARABIC LETTER E ISOLATED FORM;Lo;0;AL;<isolated> 06D0;;;;N;;;;; +FBE5;ARABIC LETTER E FINAL FORM;Lo;0;AL;<final> 06D0;;;;N;;;;; +FBE6;ARABIC LETTER E INITIAL FORM;Lo;0;AL;<initial> 06D0;;;;N;;;;; +FBE7;ARABIC LETTER E MEDIAL FORM;Lo;0;AL;<medial> 06D0;;;;N;;;;; +FBE8;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM;Lo;0;AL;<initial> 0649;;;;N;;;;; +FBE9;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM;Lo;0;AL;<medial> 0649;;;;N;;;;; +FBEA;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0626 0627;;;;N;;;;; +FBEB;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM;Lo;0;AL;<final> 0626 0627;;;;N;;;;; +FBEC;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM;Lo;0;AL;<isolated> 0626 06D5;;;;N;;;;; +FBED;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM;Lo;0;AL;<final> 0626 06D5;;;;N;;;;; +FBEE;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM;Lo;0;AL;<isolated> 0626 0648;;;;N;;;;; +FBEF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM;Lo;0;AL;<final> 0626 0648;;;;N;;;;; +FBF0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C7;;;;N;;;;; +FBF1;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM;Lo;0;AL;<final> 0626 06C7;;;;N;;;;; +FBF2;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C6;;;;N;;;;; +FBF3;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM;Lo;0;AL;<final> 0626 06C6;;;;N;;;;; +FBF4;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM;Lo;0;AL;<isolated> 0626 06C8;;;;N;;;;; +FBF5;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM;Lo;0;AL;<final> 0626 06C8;;;;N;;;;; +FBF6;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM;Lo;0;AL;<isolated> 0626 06D0;;;;N;;;;; +FBF7;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM;Lo;0;AL;<final> 0626 06D0;;;;N;;;;; +FBF8;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM;Lo;0;AL;<initial> 0626 06D0;;;;N;;;;; +FBF9;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0626 0649;;;;N;;;;; +FBFA;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0626 0649;;;;N;;;;; +FBFB;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM;Lo;0;AL;<initial> 0626 0649;;;;N;;;;; +FBFC;ARABIC LETTER FARSI YEH ISOLATED FORM;Lo;0;AL;<isolated> 06CC;;;;N;;;;; +FBFD;ARABIC LETTER FARSI YEH FINAL FORM;Lo;0;AL;<final> 06CC;;;;N;;;;; +FBFE;ARABIC LETTER FARSI YEH INITIAL FORM;Lo;0;AL;<initial> 06CC;;;;N;;;;; +FBFF;ARABIC LETTER FARSI YEH MEDIAL FORM;Lo;0;AL;<medial> 06CC;;;;N;;;;; +FC00;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0626 062C;;;;N;;;;; +FC01;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0626 062D;;;;N;;;;; +FC02;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0626 0645;;;;N;;;;; +FC03;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0626 0649;;;;N;;;;; +FC04;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0626 064A;;;;N;;;;; +FC05;ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0628 062C;;;;N;;;;; +FC06;ARABIC LIGATURE BEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0628 062D;;;;N;;;;; +FC07;ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0628 062E;;;;N;;;;; +FC08;ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0628 0645;;;;N;;;;; +FC09;ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0628 0649;;;;N;;;;; +FC0A;ARABIC LIGATURE BEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0628 064A;;;;N;;;;; +FC0B;ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062A 062C;;;;N;;;;; +FC0C;ARABIC LIGATURE TEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062A 062D;;;;N;;;;; +FC0D;ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 062A 062E;;;;N;;;;; +FC0E;ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062A 0645;;;;N;;;;; +FC0F;ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062A 0649;;;;N;;;;; +FC10;ARABIC LIGATURE TEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062A 064A;;;;N;;;;; +FC11;ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062B 062C;;;;N;;;;; +FC12;ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062B 0645;;;;N;;;;; +FC13;ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062B 0649;;;;N;;;;; +FC14;ARABIC LIGATURE THEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062B 064A;;;;N;;;;; +FC15;ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062C 062D;;;;N;;;;; +FC16;ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062C 0645;;;;N;;;;; +FC17;ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062D 062C;;;;N;;;;; +FC18;ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062D 0645;;;;N;;;;; +FC19;ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062E 062C;;;;N;;;;; +FC1A;ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 062E 062D;;;;N;;;;; +FC1B;ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 062E 0645;;;;N;;;;; +FC1C;ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0633 062C;;;;N;;;;; +FC1D;ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0633 062D;;;;N;;;;; +FC1E;ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0633 062E;;;;N;;;;; +FC1F;ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0633 0645;;;;N;;;;; +FC20;ARABIC LIGATURE SAD WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0635 062D;;;;N;;;;; +FC21;ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0635 0645;;;;N;;;;; +FC22;ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0636 062C;;;;N;;;;; +FC23;ARABIC LIGATURE DAD WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0636 062D;;;;N;;;;; +FC24;ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0636 062E;;;;N;;;;; +FC25;ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0636 0645;;;;N;;;;; +FC26;ARABIC LIGATURE TAH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0637 062D;;;;N;;;;; +FC27;ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0637 0645;;;;N;;;;; +FC28;ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0638 0645;;;;N;;;;; +FC29;ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0639 062C;;;;N;;;;; +FC2A;ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0639 0645;;;;N;;;;; +FC2B;ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 063A 062C;;;;N;;;;; +FC2C;ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 063A 0645;;;;N;;;;; +FC2D;ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0641 062C;;;;N;;;;; +FC2E;ARABIC LIGATURE FEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0641 062D;;;;N;;;;; +FC2F;ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0641 062E;;;;N;;;;; +FC30;ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0641 0645;;;;N;;;;; +FC31;ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0641 0649;;;;N;;;;; +FC32;ARABIC LIGATURE FEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0641 064A;;;;N;;;;; +FC33;ARABIC LIGATURE QAF WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0642 062D;;;;N;;;;; +FC34;ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0642 0645;;;;N;;;;; +FC35;ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0642 0649;;;;N;;;;; +FC36;ARABIC LIGATURE QAF WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0642 064A;;;;N;;;;; +FC37;ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0643 0627;;;;N;;;;; +FC38;ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0643 062C;;;;N;;;;; +FC39;ARABIC LIGATURE KAF WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0643 062D;;;;N;;;;; +FC3A;ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0643 062E;;;;N;;;;; +FC3B;ARABIC LIGATURE KAF WITH LAM ISOLATED FORM;Lo;0;AL;<isolated> 0643 0644;;;;N;;;;; +FC3C;ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0643 0645;;;;N;;;;; +FC3D;ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0643 0649;;;;N;;;;; +FC3E;ARABIC LIGATURE KAF WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0643 064A;;;;N;;;;; +FC3F;ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0644 062C;;;;N;;;;; +FC40;ARABIC LIGATURE LAM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0644 062D;;;;N;;;;; +FC41;ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0644 062E;;;;N;;;;; +FC42;ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0644 0645;;;;N;;;;; +FC43;ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0644 0649;;;;N;;;;; +FC44;ARABIC LIGATURE LAM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0644 064A;;;;N;;;;; +FC45;ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645 062C;;;;N;;;;; +FC46;ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0645 062D;;;;N;;;;; +FC47;ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0645 062E;;;;N;;;;; +FC48;ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645 0645;;;;N;;;;; +FC49;ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0645 0649;;;;N;;;;; +FC4A;ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0645 064A;;;;N;;;;; +FC4B;ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0646 062C;;;;N;;;;; +FC4C;ARABIC LIGATURE NOON WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0646 062D;;;;N;;;;; +FC4D;ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0646 062E;;;;N;;;;; +FC4E;ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0646 0645;;;;N;;;;; +FC4F;ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0646 0649;;;;N;;;;; +FC50;ARABIC LIGATURE NOON WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0646 064A;;;;N;;;;; +FC51;ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0647 062C;;;;N;;;;; +FC52;ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0647 0645;;;;N;;;;; +FC53;ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0647 0649;;;;N;;;;; +FC54;ARABIC LIGATURE HEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0647 064A;;;;N;;;;; +FC55;ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 064A 062C;;;;N;;;;; +FC56;ARABIC LIGATURE YEH WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 064A 062D;;;;N;;;;; +FC57;ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 064A 062E;;;;N;;;;; +FC58;ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 064A 0645;;;;N;;;;; +FC59;ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 064A 0649;;;;N;;;;; +FC5A;ARABIC LIGATURE YEH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 064A 064A;;;;N;;;;; +FC5B;ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0630 0670;;;;N;;;;; +FC5C;ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0631 0670;;;;N;;;;; +FC5D;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0649 0670;;;;N;;;;; +FC5E;ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064C 0651;;;;N;;;;; +FC5F;ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064D 0651;;;;N;;;;; +FC60;ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064E 0651;;;;N;;;;; +FC61;ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064F 0651;;;;N;;;;; +FC62;ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0650 0651;;;;N;;;;; +FC63;ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0020 0651 0670;;;;N;;;;; +FC64;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM;Lo;0;AL;<final> 0626 0631;;;;N;;;;; +FC65;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0626 0632;;;;N;;;;; +FC66;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM;Lo;0;AL;<final> 0626 0645;;;;N;;;;; +FC67;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM;Lo;0;AL;<final> 0626 0646;;;;N;;;;; +FC68;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0626 0649;;;;N;;;;; +FC69;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM;Lo;0;AL;<final> 0626 064A;;;;N;;;;; +FC6A;ARABIC LIGATURE BEH WITH REH FINAL FORM;Lo;0;AL;<final> 0628 0631;;;;N;;;;; +FC6B;ARABIC LIGATURE BEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0628 0632;;;;N;;;;; +FC6C;ARABIC LIGATURE BEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0628 0645;;;;N;;;;; +FC6D;ARABIC LIGATURE BEH WITH NOON FINAL FORM;Lo;0;AL;<final> 0628 0646;;;;N;;;;; +FC6E;ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0628 0649;;;;N;;;;; +FC6F;ARABIC LIGATURE BEH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 064A;;;;N;;;;; +FC70;ARABIC LIGATURE TEH WITH REH FINAL FORM;Lo;0;AL;<final> 062A 0631;;;;N;;;;; +FC71;ARABIC LIGATURE TEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 062A 0632;;;;N;;;;; +FC72;ARABIC LIGATURE TEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 062A 0645;;;;N;;;;; +FC73;ARABIC LIGATURE TEH WITH NOON FINAL FORM;Lo;0;AL;<final> 062A 0646;;;;N;;;;; +FC74;ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 0649;;;;N;;;;; +FC75;ARABIC LIGATURE TEH WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 064A;;;;N;;;;; +FC76;ARABIC LIGATURE THEH WITH REH FINAL FORM;Lo;0;AL;<final> 062B 0631;;;;N;;;;; +FC77;ARABIC LIGATURE THEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 062B 0632;;;;N;;;;; +FC78;ARABIC LIGATURE THEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 062B 0645;;;;N;;;;; +FC79;ARABIC LIGATURE THEH WITH NOON FINAL FORM;Lo;0;AL;<final> 062B 0646;;;;N;;;;; +FC7A;ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062B 0649;;;;N;;;;; +FC7B;ARABIC LIGATURE THEH WITH YEH FINAL FORM;Lo;0;AL;<final> 062B 064A;;;;N;;;;; +FC7C;ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0641 0649;;;;N;;;;; +FC7D;ARABIC LIGATURE FEH WITH YEH FINAL FORM;Lo;0;AL;<final> 0641 064A;;;;N;;;;; +FC7E;ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0642 0649;;;;N;;;;; +FC7F;ARABIC LIGATURE QAF WITH YEH FINAL FORM;Lo;0;AL;<final> 0642 064A;;;;N;;;;; +FC80;ARABIC LIGATURE KAF WITH ALEF FINAL FORM;Lo;0;AL;<final> 0643 0627;;;;N;;;;; +FC81;ARABIC LIGATURE KAF WITH LAM FINAL FORM;Lo;0;AL;<final> 0643 0644;;;;N;;;;; +FC82;ARABIC LIGATURE KAF WITH MEEM FINAL FORM;Lo;0;AL;<final> 0643 0645;;;;N;;;;; +FC83;ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0643 0649;;;;N;;;;; +FC84;ARABIC LIGATURE KAF WITH YEH FINAL FORM;Lo;0;AL;<final> 0643 064A;;;;N;;;;; +FC85;ARABIC LIGATURE LAM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 0645;;;;N;;;;; +FC86;ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0644 0649;;;;N;;;;; +FC87;ARABIC LIGATURE LAM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 064A;;;;N;;;;; +FC88;ARABIC LIGATURE MEEM WITH ALEF FINAL FORM;Lo;0;AL;<final> 0645 0627;;;;N;;;;; +FC89;ARABIC LIGATURE MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0645 0645;;;;N;;;;; +FC8A;ARABIC LIGATURE NOON WITH REH FINAL FORM;Lo;0;AL;<final> 0646 0631;;;;N;;;;; +FC8B;ARABIC LIGATURE NOON WITH ZAIN FINAL FORM;Lo;0;AL;<final> 0646 0632;;;;N;;;;; +FC8C;ARABIC LIGATURE NOON WITH MEEM FINAL FORM;Lo;0;AL;<final> 0646 0645;;;;N;;;;; +FC8D;ARABIC LIGATURE NOON WITH NOON FINAL FORM;Lo;0;AL;<final> 0646 0646;;;;N;;;;; +FC8E;ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 0649;;;;N;;;;; +FC8F;ARABIC LIGATURE NOON WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 064A;;;;N;;;;; +FC90;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM;Lo;0;AL;<final> 0649 0670;;;;N;;;;; +FC91;ARABIC LIGATURE YEH WITH REH FINAL FORM;Lo;0;AL;<final> 064A 0631;;;;N;;;;; +FC92;ARABIC LIGATURE YEH WITH ZAIN FINAL FORM;Lo;0;AL;<final> 064A 0632;;;;N;;;;; +FC93;ARABIC LIGATURE YEH WITH MEEM FINAL FORM;Lo;0;AL;<final> 064A 0645;;;;N;;;;; +FC94;ARABIC LIGATURE YEH WITH NOON FINAL FORM;Lo;0;AL;<final> 064A 0646;;;;N;;;;; +FC95;ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 064A 0649;;;;N;;;;; +FC96;ARABIC LIGATURE YEH WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 064A;;;;N;;;;; +FC97;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0626 062C;;;;N;;;;; +FC98;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0626 062D;;;;N;;;;; +FC99;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0626 062E;;;;N;;;;; +FC9A;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0626 0645;;;;N;;;;; +FC9B;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0626 0647;;;;N;;;;; +FC9C;ARABIC LIGATURE BEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0628 062C;;;;N;;;;; +FC9D;ARABIC LIGATURE BEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0628 062D;;;;N;;;;; +FC9E;ARABIC LIGATURE BEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0628 062E;;;;N;;;;; +FC9F;ARABIC LIGATURE BEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0628 0645;;;;N;;;;; +FCA0;ARABIC LIGATURE BEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0628 0647;;;;N;;;;; +FCA1;ARABIC LIGATURE TEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C;;;;N;;;;; +FCA2;ARABIC LIGATURE TEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062A 062D;;;;N;;;;; +FCA3;ARABIC LIGATURE TEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 062A 062E;;;;N;;;;; +FCA4;ARABIC LIGATURE TEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 0645;;;;N;;;;; +FCA5;ARABIC LIGATURE TEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 062A 0647;;;;N;;;;; +FCA6;ARABIC LIGATURE THEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062B 0645;;;;N;;;;; +FCA7;ARABIC LIGATURE JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062C 062D;;;;N;;;;; +FCA8;ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062C 0645;;;;N;;;;; +FCA9;ARABIC LIGATURE HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062D 062C;;;;N;;;;; +FCAA;ARABIC LIGATURE HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062D 0645;;;;N;;;;; +FCAB;ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062E 062C;;;;N;;;;; +FCAC;ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062E 0645;;;;N;;;;; +FCAD;ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 062C;;;;N;;;;; +FCAE;ARABIC LIGATURE SEEN WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 062D;;;;N;;;;; +FCAF;ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0633 062E;;;;N;;;;; +FCB0;ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645;;;;N;;;;; +FCB1;ARABIC LIGATURE SAD WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0635 062D;;;;N;;;;; +FCB2;ARABIC LIGATURE SAD WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0635 062E;;;;N;;;;; +FCB3;ARABIC LIGATURE SAD WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645;;;;N;;;;; +FCB4;ARABIC LIGATURE DAD WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0636 062C;;;;N;;;;; +FCB5;ARABIC LIGATURE DAD WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0636 062D;;;;N;;;;; +FCB6;ARABIC LIGATURE DAD WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0636 062E;;;;N;;;;; +FCB7;ARABIC LIGATURE DAD WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0636 0645;;;;N;;;;; +FCB8;ARABIC LIGATURE TAH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0637 062D;;;;N;;;;; +FCB9;ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0638 0645;;;;N;;;;; +FCBA;ARABIC LIGATURE AIN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0639 062C;;;;N;;;;; +FCBB;ARABIC LIGATURE AIN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 0645;;;;N;;;;; +FCBC;ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 063A 062C;;;;N;;;;; +FCBD;ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 063A 0645;;;;N;;;;; +FCBE;ARABIC LIGATURE FEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0641 062C;;;;N;;;;; +FCBF;ARABIC LIGATURE FEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0641 062D;;;;N;;;;; +FCC0;ARABIC LIGATURE FEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0641 062E;;;;N;;;;; +FCC1;ARABIC LIGATURE FEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0641 0645;;;;N;;;;; +FCC2;ARABIC LIGATURE QAF WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0642 062D;;;;N;;;;; +FCC3;ARABIC LIGATURE QAF WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0642 0645;;;;N;;;;; +FCC4;ARABIC LIGATURE KAF WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0643 062C;;;;N;;;;; +FCC5;ARABIC LIGATURE KAF WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0643 062D;;;;N;;;;; +FCC6;ARABIC LIGATURE KAF WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0643 062E;;;;N;;;;; +FCC7;ARABIC LIGATURE KAF WITH LAM INITIAL FORM;Lo;0;AL;<initial> 0643 0644;;;;N;;;;; +FCC8;ARABIC LIGATURE KAF WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0643 0645;;;;N;;;;; +FCC9;ARABIC LIGATURE LAM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C;;;;N;;;;; +FCCA;ARABIC LIGATURE LAM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0644 062D;;;;N;;;;; +FCCB;ARABIC LIGATURE LAM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0644 062E;;;;N;;;;; +FCCC;ARABIC LIGATURE LAM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 0645;;;;N;;;;; +FCCD;ARABIC LIGATURE LAM WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0644 0647;;;;N;;;;; +FCCE;ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C;;;;N;;;;; +FCCF;ARABIC LIGATURE MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645 062D;;;;N;;;;; +FCD0;ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062E;;;;N;;;;; +FCD1;ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 0645;;;;N;;;;; +FCD2;ARABIC LIGATURE NOON WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062C;;;;N;;;;; +FCD3;ARABIC LIGATURE NOON WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0646 062D;;;;N;;;;; +FCD4;ARABIC LIGATURE NOON WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0646 062E;;;;N;;;;; +FCD5;ARABIC LIGATURE NOON WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 0645;;;;N;;;;; +FCD6;ARABIC LIGATURE NOON WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0646 0647;;;;N;;;;; +FCD7;ARABIC LIGATURE HEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 062C;;;;N;;;;; +FCD8;ARABIC LIGATURE HEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645;;;;N;;;;; +FCD9;ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM;Lo;0;AL;<initial> 0647 0670;;;;N;;;;; +FCDA;ARABIC LIGATURE YEH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 064A 062C;;;;N;;;;; +FCDB;ARABIC LIGATURE YEH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 064A 062D;;;;N;;;;; +FCDC;ARABIC LIGATURE YEH WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 064A 062E;;;;N;;;;; +FCDD;ARABIC LIGATURE YEH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 064A 0645;;;;N;;;;; +FCDE;ARABIC LIGATURE YEH WITH HEH INITIAL FORM;Lo;0;AL;<initial> 064A 0647;;;;N;;;;; +FCDF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0626 0645;;;;N;;;;; +FCE0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0626 0647;;;;N;;;;; +FCE1;ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0628 0645;;;;N;;;;; +FCE2;ARABIC LIGATURE BEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0628 0647;;;;N;;;;; +FCE3;ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 062A 0645;;;;N;;;;; +FCE4;ARABIC LIGATURE TEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 062A 0647;;;;N;;;;; +FCE5;ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 062B 0645;;;;N;;;;; +FCE6;ARABIC LIGATURE THEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 062B 0647;;;;N;;;;; +FCE7;ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0633 0645;;;;N;;;;; +FCE8;ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0633 0647;;;;N;;;;; +FCE9;ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0634 0645;;;;N;;;;; +FCEA;ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0634 0647;;;;N;;;;; +FCEB;ARABIC LIGATURE KAF WITH LAM MEDIAL FORM;Lo;0;AL;<medial> 0643 0644;;;;N;;;;; +FCEC;ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0643 0645;;;;N;;;;; +FCED;ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0644 0645;;;;N;;;;; +FCEE;ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0646 0645;;;;N;;;;; +FCEF;ARABIC LIGATURE NOON WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 0646 0647;;;;N;;;;; +FCF0;ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 064A 0645;;;;N;;;;; +FCF1;ARABIC LIGATURE YEH WITH HEH MEDIAL FORM;Lo;0;AL;<medial> 064A 0647;;;;N;;;;; +FCF2;ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM;Lo;0;AL;<medial> 0640 064E 0651;;;;N;;;;; +FCF3;ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM;Lo;0;AL;<medial> 0640 064F 0651;;;;N;;;;; +FCF4;ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM;Lo;0;AL;<medial> 0640 0650 0651;;;;N;;;;; +FCF5;ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0637 0649;;;;N;;;;; +FCF6;ARABIC LIGATURE TAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0637 064A;;;;N;;;;; +FCF7;ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0639 0649;;;;N;;;;; +FCF8;ARABIC LIGATURE AIN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0639 064A;;;;N;;;;; +FCF9;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 063A 0649;;;;N;;;;; +FCFA;ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 063A 064A;;;;N;;;;; +FCFB;ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0633 0649;;;;N;;;;; +FCFC;ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0633 064A;;;;N;;;;; +FCFD;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0634 0649;;;;N;;;;; +FCFE;ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0634 064A;;;;N;;;;; +FCFF;ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062D 0649;;;;N;;;;; +FD00;ARABIC LIGATURE HAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062D 064A;;;;N;;;;; +FD01;ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062C 0649;;;;N;;;;; +FD02;ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062C 064A;;;;N;;;;; +FD03;ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 062E 0649;;;;N;;;;; +FD04;ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 062E 064A;;;;N;;;;; +FD05;ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0635 0649;;;;N;;;;; +FD06;ARABIC LIGATURE SAD WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0635 064A;;;;N;;;;; +FD07;ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0636 0649;;;;N;;;;; +FD08;ARABIC LIGATURE DAD WITH YEH ISOLATED FORM;Lo;0;AL;<isolated> 0636 064A;;;;N;;;;; +FD09;ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM;Lo;0;AL;<isolated> 0634 062C;;;;N;;;;; +FD0A;ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM;Lo;0;AL;<isolated> 0634 062D;;;;N;;;;; +FD0B;ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM;Lo;0;AL;<isolated> 0634 062E;;;;N;;;;; +FD0C;ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0634 0645;;;;N;;;;; +FD0D;ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0634 0631;;;;N;;;;; +FD0E;ARABIC LIGATURE SEEN WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0633 0631;;;;N;;;;; +FD0F;ARABIC LIGATURE SAD WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0635 0631;;;;N;;;;; +FD10;ARABIC LIGATURE DAD WITH REH ISOLATED FORM;Lo;0;AL;<isolated> 0636 0631;;;;N;;;;; +FD11;ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0637 0649;;;;N;;;;; +FD12;ARABIC LIGATURE TAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0637 064A;;;;N;;;;; +FD13;ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0639 0649;;;;N;;;;; +FD14;ARABIC LIGATURE AIN WITH YEH FINAL FORM;Lo;0;AL;<final> 0639 064A;;;;N;;;;; +FD15;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 063A 0649;;;;N;;;;; +FD16;ARABIC LIGATURE GHAIN WITH YEH FINAL FORM;Lo;0;AL;<final> 063A 064A;;;;N;;;;; +FD17;ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 0649;;;;N;;;;; +FD18;ARABIC LIGATURE SEEN WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 064A;;;;N;;;;; +FD19;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0634 0649;;;;N;;;;; +FD1A;ARABIC LIGATURE SHEEN WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 064A;;;;N;;;;; +FD1B;ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062D 0649;;;;N;;;;; +FD1C;ARABIC LIGATURE HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 064A;;;;N;;;;; +FD1D;ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 0649;;;;N;;;;; +FD1E;ARABIC LIGATURE JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 064A;;;;N;;;;; +FD1F;ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062E 0649;;;;N;;;;; +FD20;ARABIC LIGATURE KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062E 064A;;;;N;;;;; +FD21;ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0635 0649;;;;N;;;;; +FD22;ARABIC LIGATURE SAD WITH YEH FINAL FORM;Lo;0;AL;<final> 0635 064A;;;;N;;;;; +FD23;ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0636 0649;;;;N;;;;; +FD24;ARABIC LIGATURE DAD WITH YEH FINAL FORM;Lo;0;AL;<final> 0636 064A;;;;N;;;;; +FD25;ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM;Lo;0;AL;<final> 0634 062C;;;;N;;;;; +FD26;ARABIC LIGATURE SHEEN WITH HAH FINAL FORM;Lo;0;AL;<final> 0634 062D;;;;N;;;;; +FD27;ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM;Lo;0;AL;<final> 0634 062E;;;;N;;;;; +FD28;ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 0645;;;;N;;;;; +FD29;ARABIC LIGATURE SHEEN WITH REH FINAL FORM;Lo;0;AL;<final> 0634 0631;;;;N;;;;; +FD2A;ARABIC LIGATURE SEEN WITH REH FINAL FORM;Lo;0;AL;<final> 0633 0631;;;;N;;;;; +FD2B;ARABIC LIGATURE SAD WITH REH FINAL FORM;Lo;0;AL;<final> 0635 0631;;;;N;;;;; +FD2C;ARABIC LIGATURE DAD WITH REH FINAL FORM;Lo;0;AL;<final> 0636 0631;;;;N;;;;; +FD2D;ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0634 062C;;;;N;;;;; +FD2E;ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0634 062D;;;;N;;;;; +FD2F;ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0634 062E;;;;N;;;;; +FD30;ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 0645;;;;N;;;;; +FD31;ARABIC LIGATURE SEEN WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0633 0647;;;;N;;;;; +FD32;ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM;Lo;0;AL;<initial> 0634 0647;;;;N;;;;; +FD33;ARABIC LIGATURE TAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0637 0645;;;;N;;;;; +FD34;ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM;Lo;0;AL;<medial> 0633 062C;;;;N;;;;; +FD35;ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM;Lo;0;AL;<medial> 0633 062D;;;;N;;;;; +FD36;ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM;Lo;0;AL;<medial> 0633 062E;;;;N;;;;; +FD37;ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM;Lo;0;AL;<medial> 0634 062C;;;;N;;;;; +FD38;ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM;Lo;0;AL;<medial> 0634 062D;;;;N;;;;; +FD39;ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM;Lo;0;AL;<medial> 0634 062E;;;;N;;;;; +FD3A;ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0637 0645;;;;N;;;;; +FD3B;ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM;Lo;0;AL;<medial> 0638 0645;;;;N;;;;; +FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL;<final> 0627 064B;;;;N;;;;; +FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0627 064B;;;;N;;;;; +FD3E;ORNATE LEFT PARENTHESIS;Pe;0;ON;;;;;N;;;;; +FD3F;ORNATE RIGHT PARENTHESIS;Ps;0;ON;;;;;N;;;;; +FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C 0645;;;;N;;;;; +FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL;<final> 062A 062D 062C;;;;N;;;;; +FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 062C;;;;N;;;;; +FD53;ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 0645;;;;N;;;;; +FD54;ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062E 0645;;;;N;;;;; +FD55;ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062C;;;;N;;;;; +FD56;ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062D;;;;N;;;;; +FD57;ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 062A 0645 062E;;;;N;;;;; +FD58;ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 062C 0645 062D;;;;N;;;;; +FD59;ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 062C 0645 062D;;;;N;;;;; +FD5A;ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 0645 064A;;;;N;;;;; +FD5B;ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062D 0645 0649;;;;N;;;;; +FD5C;ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 062D 062C;;;;N;;;;; +FD5D;ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 062C 062D;;;;N;;;;; +FD5E;ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 062C 0649;;;;N;;;;; +FD5F;ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0633 0645 062D;;;;N;;;;; +FD60;ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0633 0645 062D;;;;N;;;;; +FD61;ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645 062C;;;;N;;;;; +FD62;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0633 0645 0645;;;;N;;;;; +FD63;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0633 0645 0645;;;;N;;;;; +FD64;ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM;Lo;0;AL;<final> 0635 062D 062D;;;;N;;;;; +FD65;ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0635 062D 062D;;;;N;;;;; +FD66;ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0635 0645 0645;;;;N;;;;; +FD67;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 062D 0645;;;;N;;;;; +FD68;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 062D 0645;;;;N;;;;; +FD69;ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 062C 064A;;;;N;;;;; +FD6A;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM;Lo;0;AL;<final> 0634 0645 062E;;;;N;;;;; +FD6B;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0634 0645 062E;;;;N;;;;; +FD6C;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0634 0645 0645;;;;N;;;;; +FD6D;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0634 0645 0645;;;;N;;;;; +FD6E;ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0636 062D 0649;;;;N;;;;; +FD6F;ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0636 062E 0645;;;;N;;;;; +FD70;ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0636 062E 0645;;;;N;;;;; +FD71;ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0637 0645 062D;;;;N;;;;; +FD72;ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0637 0645 062D;;;;N;;;;; +FD73;ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0637 0645 0645;;;;N;;;;; +FD74;ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0637 0645 064A;;;;N;;;;; +FD75;ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0639 062C 0645;;;;N;;;;; +FD76;ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0639 0645 0645;;;;N;;;;; +FD77;ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 0645 0645;;;;N;;;;; +FD78;ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0639 0645 0649;;;;N;;;;; +FD79;ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 063A 0645 0645;;;;N;;;;; +FD7A;ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 063A 0645 064A;;;;N;;;;; +FD7B;ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 063A 0645 0649;;;;N;;;;; +FD7C;ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0641 062E 0645;;;;N;;;;; +FD7D;ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0641 062E 0645;;;;N;;;;; +FD7E;ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0642 0645 062D;;;;N;;;;; +FD7F;ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0642 0645 0645;;;;N;;;;; +FD80;ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062D 0645;;;;N;;;;; +FD81;ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 062D 064A;;;;N;;;;; +FD82;ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0644 062D 0649;;;;N;;;;; +FD83;ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C 062C;;;;N;;;;; +FD84;ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM;Lo;0;AL;<final> 0644 062C 062C;;;;N;;;;; +FD85;ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062E 0645;;;;N;;;;; +FD86;ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062E 0645;;;;N;;;;; +FD87;ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0644 0645 062D;;;;N;;;;; +FD88;ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0644 0645 062D;;;;N;;;;; +FD89;ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062D 062C;;;;N;;;;; +FD8A;ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062D 0645;;;;N;;;;; +FD8B;ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062D 064A;;;;N;;;;; +FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062D;;;;N;;;;; +FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062C 0645;;;;N;;;;; +FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 062C;;;;N;;;;; +FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0645 062E 0645;;;;N;;;;; +FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL;<initial> 0645 062C 062E;;;;N;;;;; +FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 062C;;;;N;;;;; +FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0647 0645 0645;;;;N;;;;; +FD95;ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062D 0645;;;;N;;;;; +FD96;ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 062D 0649;;;;N;;;;; +FD97;ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0646 062C 0645;;;;N;;;;; +FD98;ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0646 062C 0645;;;;N;;;;; +FD99;ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 062C 0649;;;;N;;;;; +FD9A;ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 0645 064A;;;;N;;;;; +FD9B;ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0646 0645 0649;;;;N;;;;; +FD9C;ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 064A 0645 0645;;;;N;;;;; +FD9D;ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 064A 0645 0645;;;;N;;;;; +FD9E;ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 062E 064A;;;;N;;;;; +FD9F;ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 062C 064A;;;;N;;;;; +FDA0;ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 062C 0649;;;;N;;;;; +FDA1;ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 062E 064A;;;;N;;;;; +FDA2;ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 062E 0649;;;;N;;;;; +FDA3;ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062A 0645 064A;;;;N;;;;; +FDA4;ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062A 0645 0649;;;;N;;;;; +FDA5;ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 0645 064A;;;;N;;;;; +FDA6;ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 062D 0649;;;;N;;;;; +FDA7;ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 062C 0645 0649;;;;N;;;;; +FDA8;ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0633 062E 0649;;;;N;;;;; +FDA9;ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0635 062D 064A;;;;N;;;;; +FDAA;ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0634 062D 064A;;;;N;;;;; +FDAB;ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0636 062D 064A;;;;N;;;;; +FDAC;ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 062C 064A;;;;N;;;;; +FDAD;ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0644 0645 064A;;;;N;;;;; +FDAE;ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 062D 064A;;;;N;;;;; +FDAF;ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 062C 064A;;;;N;;;;; +FDB0;ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 064A 0645 064A;;;;N;;;;; +FDB1;ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 0645 064A;;;;N;;;;; +FDB2;ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0642 0645 064A;;;;N;;;;; +FDB3;ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062D 064A;;;;N;;;;; +FDB4;ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0642 0645 062D;;;;N;;;;; +FDB5;ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062D 0645;;;;N;;;;; +FDB6;ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0639 0645 064A;;;;N;;;;; +FDB7;ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0643 0645 064A;;;;N;;;;; +FDB8;ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL;<initial> 0646 062C 062D;;;;N;;;;; +FDB9;ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062E 064A;;;;N;;;;; +FDBA;ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0644 062C 0645;;;;N;;;;; +FDBB;ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0643 0645 0645;;;;N;;;;; +FDBC;ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL;<final> 0644 062C 0645;;;;N;;;;; +FDBD;ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM;Lo;0;AL;<final> 0646 062C 062D;;;;N;;;;; +FDBE;ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 062C 062D 064A;;;;N;;;;; +FDBF;ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 062D 062C 064A;;;;N;;;;; +FDC0;ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0645 062C 064A;;;;N;;;;; +FDC1;ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0641 0645 064A;;;;N;;;;; +FDC2;ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0628 062D 064A;;;;N;;;;; +FDC3;ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0643 0645 0645;;;;N;;;;; +FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639 062C 0645;;;;N;;;;; +FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645 0645;;;;N;;;;; +FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 062E 064A;;;;N;;;;; +FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062C 064A;;;;N;;;;; +FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 06D2;;;;N;;;;; +FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0642 0644 06D2;;;;N;;;;; +FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL;<isolated> 0627 0644 0644 0647;;;;N;;;;; +FDF3;ARABIC LIGATURE AKBAR ISOLATED FORM;Lo;0;AL;<isolated> 0627 0643 0628 0631;;;;N;;;;; +FDF4;ARABIC LIGATURE MOHAMMAD ISOLATED FORM;Lo;0;AL;<isolated> 0645 062D 0645 062F;;;;N;;;;; +FDF5;ARABIC LIGATURE SALAM ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 0639 0645;;;;N;;;;; +FDF6;ARABIC LIGATURE RASOUL ISOLATED FORM;Lo;0;AL;<isolated> 0631 0633 0648 0644;;;;N;;;;; +FDF7;ARABIC LIGATURE ALAYHE ISOLATED FORM;Lo;0;AL;<isolated> 0639 0644 064A 0647;;;;N;;;;; +FDF8;ARABIC LIGATURE WASALLAM ISOLATED FORM;Lo;0;AL;<isolated> 0648 0633 0644 0645;;;;N;;;;; +FDF9;ARABIC LIGATURE SALLA ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 0649;;;;N;;;;; +FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL;<isolated> 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645;;;;N;ARABIC LETTER SALLALLAHOU ALAYHE WASALLAM;;;; +FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL;<isolated> 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;; +FDFC;RIAL SIGN;Sc;0;AL;<isolated> 0631 06CC 0627 0644;;;;N;;;;; +FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;; +FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;; +FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;; +FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;; +FE03;VARIATION SELECTOR-4;Mn;0;NSM;;;;;N;;;;; +FE04;VARIATION SELECTOR-5;Mn;0;NSM;;;;;N;;;;; +FE05;VARIATION SELECTOR-6;Mn;0;NSM;;;;;N;;;;; +FE06;VARIATION SELECTOR-7;Mn;0;NSM;;;;;N;;;;; +FE07;VARIATION SELECTOR-8;Mn;0;NSM;;;;;N;;;;; +FE08;VARIATION SELECTOR-9;Mn;0;NSM;;;;;N;;;;; +FE09;VARIATION SELECTOR-10;Mn;0;NSM;;;;;N;;;;; +FE0A;VARIATION SELECTOR-11;Mn;0;NSM;;;;;N;;;;; +FE0B;VARIATION SELECTOR-12;Mn;0;NSM;;;;;N;;;;; +FE0C;VARIATION SELECTOR-13;Mn;0;NSM;;;;;N;;;;; +FE0D;VARIATION SELECTOR-14;Mn;0;NSM;;;;;N;;;;; +FE0E;VARIATION SELECTOR-15;Mn;0;NSM;;;;;N;;;;; +FE0F;VARIATION SELECTOR-16;Mn;0;NSM;;;;;N;;;;; +FE10;PRESENTATION FORM FOR VERTICAL COMMA;Po;0;ON;<vertical> 002C;;;;N;;;;; +FE11;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA;Po;0;ON;<vertical> 3001;;;;N;;;;; +FE12;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP;Po;0;ON;<vertical> 3002;;;;N;;;;; +FE13;PRESENTATION FORM FOR VERTICAL COLON;Po;0;ON;<vertical> 003A;;;;N;;;;; +FE14;PRESENTATION FORM FOR VERTICAL SEMICOLON;Po;0;ON;<vertical> 003B;;;;N;;;;; +FE15;PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK;Po;0;ON;<vertical> 0021;;;;N;;;;; +FE16;PRESENTATION FORM FOR VERTICAL QUESTION MARK;Po;0;ON;<vertical> 003F;;;;N;;;;; +FE17;PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;<vertical> 3016;;;;N;;;;; +FE18;PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET;Pe;0;ON;<vertical> 3017;;;;N;;;;; +FE19;PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS;Po;0;ON;<vertical> 2026;;;;N;;;;; +FE20;COMBINING LIGATURE LEFT HALF;Mn;230;NSM;;;;;N;;;;; +FE21;COMBINING LIGATURE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; +FE22;COMBINING DOUBLE TILDE LEFT HALF;Mn;230;NSM;;;;;N;;;;; +FE23;COMBINING DOUBLE TILDE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; +FE24;COMBINING MACRON LEFT HALF;Mn;230;NSM;;;;;N;;;;; +FE25;COMBINING MACRON RIGHT HALF;Mn;230;NSM;;;;;N;;;;; +FE26;COMBINING CONJOINING MACRON;Mn;230;NSM;;;;;N;;;;; +FE27;COMBINING LIGATURE LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE28;COMBINING LIGATURE RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE29;COMBINING TILDE LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE2A;COMBINING TILDE RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE2B;COMBINING MACRON LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE2C;COMBINING MACRON RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE2D;COMBINING CONJOINING MACRON BELOW;Mn;220;NSM;;;;;N;;;;; +FE2E;COMBINING CYRILLIC TITLO LEFT HALF;Mn;230;NSM;;;;;N;;;;; +FE2F;COMBINING CYRILLIC TITLO RIGHT HALF;Mn;230;NSM;;;;;N;;;;; +FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON;<vertical> 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;; +FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON;<vertical> 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;; +FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON;<vertical> 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;; +FE33;PRESENTATION FORM FOR VERTICAL LOW LINE;Pc;0;ON;<vertical> 005F;;;;N;GLYPH FOR VERTICAL SPACING UNDERSCORE;;;; +FE34;PRESENTATION FORM FOR VERTICAL WAVY LOW LINE;Pc;0;ON;<vertical> 005F;;;;N;GLYPH FOR VERTICAL SPACING WAVY UNDERSCORE;;;; +FE35;PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS;Ps;0;ON;<vertical> 0028;;;;N;GLYPH FOR VERTICAL OPENING PARENTHESIS;;;; +FE36;PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS;Pe;0;ON;<vertical> 0029;;;;N;GLYPH FOR VERTICAL CLOSING PARENTHESIS;;;; +FE37;PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET;Ps;0;ON;<vertical> 007B;;;;N;GLYPH FOR VERTICAL OPENING CURLY BRACKET;;;; +FE38;PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET;Pe;0;ON;<vertical> 007D;;;;N;GLYPH FOR VERTICAL CLOSING CURLY BRACKET;;;; +FE39;PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET;Ps;0;ON;<vertical> 3014;;;;N;GLYPH FOR VERTICAL OPENING TORTOISE SHELL BRACKET;;;; +FE3A;PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;<vertical> 3015;;;;N;GLYPH FOR VERTICAL CLOSING TORTOISE SHELL BRACKET;;;; +FE3B;PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;<vertical> 3010;;;;N;GLYPH FOR VERTICAL OPENING BLACK LENTICULAR BRACKET;;;; +FE3C;PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;<vertical> 3011;;;;N;GLYPH FOR VERTICAL CLOSING BLACK LENTICULAR BRACKET;;;; +FE3D;PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;<vertical> 300A;;;;N;GLYPH FOR VERTICAL OPENING DOUBLE ANGLE BRACKET;;;; +FE3E;PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;<vertical> 300B;;;;N;GLYPH FOR VERTICAL CLOSING DOUBLE ANGLE BRACKET;;;; +FE3F;PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET;Ps;0;ON;<vertical> 3008;;;;N;GLYPH FOR VERTICAL OPENING ANGLE BRACKET;;;; +FE40;PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET;Pe;0;ON;<vertical> 3009;;;;N;GLYPH FOR VERTICAL CLOSING ANGLE BRACKET;;;; +FE41;PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET;Ps;0;ON;<vertical> 300C;;;;N;GLYPH FOR VERTICAL OPENING CORNER BRACKET;;;; +FE42;PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET;Pe;0;ON;<vertical> 300D;;;;N;GLYPH FOR VERTICAL CLOSING CORNER BRACKET;;;; +FE43;PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET;Ps;0;ON;<vertical> 300E;;;;N;GLYPH FOR VERTICAL OPENING WHITE CORNER BRACKET;;;; +FE44;PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET;Pe;0;ON;<vertical> 300F;;;;N;GLYPH FOR VERTICAL CLOSING WHITE CORNER BRACKET;;;; +FE45;SESAME DOT;Po;0;ON;;;;;N;;;;; +FE46;WHITE SESAME DOT;Po;0;ON;;;;;N;;;;; +FE47;PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET;Ps;0;ON;<vertical> 005B;;;;N;;;;; +FE48;PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET;Pe;0;ON;<vertical> 005D;;;;N;;;;; +FE49;DASHED OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING DASHED OVERSCORE;;;; +FE4A;CENTRELINE OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING CENTERLINE OVERSCORE;;;; +FE4B;WAVY OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING WAVY OVERSCORE;;;; +FE4C;DOUBLE WAVY OVERLINE;Po;0;ON;<compat> 203E;;;;N;SPACING DOUBLE WAVY OVERSCORE;;;; +FE4D;DASHED LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING DASHED UNDERSCORE;;;; +FE4E;CENTRELINE LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING CENTERLINE UNDERSCORE;;;; +FE4F;WAVY LOW LINE;Pc;0;ON;<compat> 005F;;;;N;SPACING WAVY UNDERSCORE;;;; +FE50;SMALL COMMA;Po;0;CS;<small> 002C;;;;N;;;;; +FE51;SMALL IDEOGRAPHIC COMMA;Po;0;ON;<small> 3001;;;;N;;;;; +FE52;SMALL FULL STOP;Po;0;CS;<small> 002E;;;;N;SMALL PERIOD;;;; +FE54;SMALL SEMICOLON;Po;0;ON;<small> 003B;;;;N;;;;; +FE55;SMALL COLON;Po;0;CS;<small> 003A;;;;N;;;;; +FE56;SMALL QUESTION MARK;Po;0;ON;<small> 003F;;;;N;;;;; +FE57;SMALL EXCLAMATION MARK;Po;0;ON;<small> 0021;;;;N;;;;; +FE58;SMALL EM DASH;Pd;0;ON;<small> 2014;;;;N;;;;; +FE59;SMALL LEFT PARENTHESIS;Ps;0;ON;<small> 0028;;;;Y;SMALL OPENING PARENTHESIS;;;; +FE5A;SMALL RIGHT PARENTHESIS;Pe;0;ON;<small> 0029;;;;Y;SMALL CLOSING PARENTHESIS;;;; +FE5B;SMALL LEFT CURLY BRACKET;Ps;0;ON;<small> 007B;;;;Y;SMALL OPENING CURLY BRACKET;;;; +FE5C;SMALL RIGHT CURLY BRACKET;Pe;0;ON;<small> 007D;;;;Y;SMALL CLOSING CURLY BRACKET;;;; +FE5D;SMALL LEFT TORTOISE SHELL BRACKET;Ps;0;ON;<small> 3014;;;;Y;SMALL OPENING TORTOISE SHELL BRACKET;;;; +FE5E;SMALL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;<small> 3015;;;;Y;SMALL CLOSING TORTOISE SHELL BRACKET;;;; +FE5F;SMALL NUMBER SIGN;Po;0;ET;<small> 0023;;;;N;;;;; +FE60;SMALL AMPERSAND;Po;0;ON;<small> 0026;;;;N;;;;; +FE61;SMALL ASTERISK;Po;0;ON;<small> 002A;;;;N;;;;; +FE62;SMALL PLUS SIGN;Sm;0;ES;<small> 002B;;;;N;;;;; +FE63;SMALL HYPHEN-MINUS;Pd;0;ES;<small> 002D;;;;N;;;;; +FE64;SMALL LESS-THAN SIGN;Sm;0;ON;<small> 003C;;;;Y;;;;; +FE65;SMALL GREATER-THAN SIGN;Sm;0;ON;<small> 003E;;;;Y;;;;; +FE66;SMALL EQUALS SIGN;Sm;0;ON;<small> 003D;;;;N;;;;; +FE68;SMALL REVERSE SOLIDUS;Po;0;ON;<small> 005C;;;;N;SMALL BACKSLASH;;;; +FE69;SMALL DOLLAR SIGN;Sc;0;ET;<small> 0024;;;;N;;;;; +FE6A;SMALL PERCENT SIGN;Po;0;ET;<small> 0025;;;;N;;;;; +FE6B;SMALL COMMERCIAL AT;Po;0;ON;<small> 0040;;;;N;;;;; +FE70;ARABIC FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064B;;;;N;ARABIC SPACING FATHATAN;;;; +FE71;ARABIC TATWEEL WITH FATHATAN ABOVE;Lo;0;AL;<medial> 0640 064B;;;;N;ARABIC FATHATAN ON TATWEEL;;;; +FE72;ARABIC DAMMATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064C;;;;N;ARABIC SPACING DAMMATAN;;;; +FE73;ARABIC TAIL FRAGMENT;Lo;0;AL;;;;;N;;;;; +FE74;ARABIC KASRATAN ISOLATED FORM;Lo;0;AL;<isolated> 0020 064D;;;;N;ARABIC SPACING KASRATAN;;;; +FE76;ARABIC FATHA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064E;;;;N;ARABIC SPACING FATHAH;;;; +FE77;ARABIC FATHA MEDIAL FORM;Lo;0;AL;<medial> 0640 064E;;;;N;ARABIC FATHAH ON TATWEEL;;;; +FE78;ARABIC DAMMA ISOLATED FORM;Lo;0;AL;<isolated> 0020 064F;;;;N;ARABIC SPACING DAMMAH;;;; +FE79;ARABIC DAMMA MEDIAL FORM;Lo;0;AL;<medial> 0640 064F;;;;N;ARABIC DAMMAH ON TATWEEL;;;; +FE7A;ARABIC KASRA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0650;;;;N;ARABIC SPACING KASRAH;;;; +FE7B;ARABIC KASRA MEDIAL FORM;Lo;0;AL;<medial> 0640 0650;;;;N;ARABIC KASRAH ON TATWEEL;;;; +FE7C;ARABIC SHADDA ISOLATED FORM;Lo;0;AL;<isolated> 0020 0651;;;;N;ARABIC SPACING SHADDAH;;;; +FE7D;ARABIC SHADDA MEDIAL FORM;Lo;0;AL;<medial> 0640 0651;;;;N;ARABIC SHADDAH ON TATWEEL;;;; +FE7E;ARABIC SUKUN ISOLATED FORM;Lo;0;AL;<isolated> 0020 0652;;;;N;ARABIC SPACING SUKUN;;;; +FE7F;ARABIC SUKUN MEDIAL FORM;Lo;0;AL;<medial> 0640 0652;;;;N;ARABIC SUKUN ON TATWEEL;;;; +FE80;ARABIC LETTER HAMZA ISOLATED FORM;Lo;0;AL;<isolated> 0621;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH;;;; +FE81;ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON ALEF;;;; +FE82;ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL;<final> 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON ALEF;;;; +FE83;ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON ALEF;;;; +FE84;ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON ALEF;;;; +FE85;ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0624;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON WAW;;;; +FE86;ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0624;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON WAW;;;; +FE87;ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL;<isolated> 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER ALEF;;;; +FE88;ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL;<final> 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER ALEF;;;; +FE89;ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0626;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON YA;;;; +FE8A;ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0626;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON YA;;;; +FE8B;ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM;Lo;0;AL;<initial> 0626;;;;N;GLYPH FOR INITIAL ARABIC HAMZAH ON YA;;;; +FE8C;ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM;Lo;0;AL;<medial> 0626;;;;N;GLYPH FOR MEDIAL ARABIC HAMZAH ON YA;;;; +FE8D;ARABIC LETTER ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0627;;;;N;GLYPH FOR ISOLATE ARABIC ALEF;;;; +FE8E;ARABIC LETTER ALEF FINAL FORM;Lo;0;AL;<final> 0627;;;;N;GLYPH FOR FINAL ARABIC ALEF;;;; +FE8F;ARABIC LETTER BEH ISOLATED FORM;Lo;0;AL;<isolated> 0628;;;;N;GLYPH FOR ISOLATE ARABIC BAA;;;; +FE90;ARABIC LETTER BEH FINAL FORM;Lo;0;AL;<final> 0628;;;;N;GLYPH FOR FINAL ARABIC BAA;;;; +FE91;ARABIC LETTER BEH INITIAL FORM;Lo;0;AL;<initial> 0628;;;;N;GLYPH FOR INITIAL ARABIC BAA;;;; +FE92;ARABIC LETTER BEH MEDIAL FORM;Lo;0;AL;<medial> 0628;;;;N;GLYPH FOR MEDIAL ARABIC BAA;;;; +FE93;ARABIC LETTER TEH MARBUTA ISOLATED FORM;Lo;0;AL;<isolated> 0629;;;;N;GLYPH FOR ISOLATE ARABIC TAA MARBUTAH;;;; +FE94;ARABIC LETTER TEH MARBUTA FINAL FORM;Lo;0;AL;<final> 0629;;;;N;GLYPH FOR FINAL ARABIC TAA MARBUTAH;;;; +FE95;ARABIC LETTER TEH ISOLATED FORM;Lo;0;AL;<isolated> 062A;;;;N;GLYPH FOR ISOLATE ARABIC TAA;;;; +FE96;ARABIC LETTER TEH FINAL FORM;Lo;0;AL;<final> 062A;;;;N;GLYPH FOR FINAL ARABIC TAA;;;; +FE97;ARABIC LETTER TEH INITIAL FORM;Lo;0;AL;<initial> 062A;;;;N;GLYPH FOR INITIAL ARABIC TAA;;;; +FE98;ARABIC LETTER TEH MEDIAL FORM;Lo;0;AL;<medial> 062A;;;;N;GLYPH FOR MEDIAL ARABIC TAA;;;; +FE99;ARABIC LETTER THEH ISOLATED FORM;Lo;0;AL;<isolated> 062B;;;;N;GLYPH FOR ISOLATE ARABIC THAA;;;; +FE9A;ARABIC LETTER THEH FINAL FORM;Lo;0;AL;<final> 062B;;;;N;GLYPH FOR FINAL ARABIC THAA;;;; +FE9B;ARABIC LETTER THEH INITIAL FORM;Lo;0;AL;<initial> 062B;;;;N;GLYPH FOR INITIAL ARABIC THAA;;;; +FE9C;ARABIC LETTER THEH MEDIAL FORM;Lo;0;AL;<medial> 062B;;;;N;GLYPH FOR MEDIAL ARABIC THAA;;;; +FE9D;ARABIC LETTER JEEM ISOLATED FORM;Lo;0;AL;<isolated> 062C;;;;N;GLYPH FOR ISOLATE ARABIC JEEM;;;; +FE9E;ARABIC LETTER JEEM FINAL FORM;Lo;0;AL;<final> 062C;;;;N;GLYPH FOR FINAL ARABIC JEEM;;;; +FE9F;ARABIC LETTER JEEM INITIAL FORM;Lo;0;AL;<initial> 062C;;;;N;GLYPH FOR INITIAL ARABIC JEEM;;;; +FEA0;ARABIC LETTER JEEM MEDIAL FORM;Lo;0;AL;<medial> 062C;;;;N;GLYPH FOR MEDIAL ARABIC JEEM;;;; +FEA1;ARABIC LETTER HAH ISOLATED FORM;Lo;0;AL;<isolated> 062D;;;;N;GLYPH FOR ISOLATE ARABIC HAA;;;; +FEA2;ARABIC LETTER HAH FINAL FORM;Lo;0;AL;<final> 062D;;;;N;GLYPH FOR FINAL ARABIC HAA;;;; +FEA3;ARABIC LETTER HAH INITIAL FORM;Lo;0;AL;<initial> 062D;;;;N;GLYPH FOR INITIAL ARABIC HAA;;;; +FEA4;ARABIC LETTER HAH MEDIAL FORM;Lo;0;AL;<medial> 062D;;;;N;GLYPH FOR MEDIAL ARABIC HAA;;;; +FEA5;ARABIC LETTER KHAH ISOLATED FORM;Lo;0;AL;<isolated> 062E;;;;N;GLYPH FOR ISOLATE ARABIC KHAA;;;; +FEA6;ARABIC LETTER KHAH FINAL FORM;Lo;0;AL;<final> 062E;;;;N;GLYPH FOR FINAL ARABIC KHAA;;;; +FEA7;ARABIC LETTER KHAH INITIAL FORM;Lo;0;AL;<initial> 062E;;;;N;GLYPH FOR INITIAL ARABIC KHAA;;;; +FEA8;ARABIC LETTER KHAH MEDIAL FORM;Lo;0;AL;<medial> 062E;;;;N;GLYPH FOR MEDIAL ARABIC KHAA;;;; +FEA9;ARABIC LETTER DAL ISOLATED FORM;Lo;0;AL;<isolated> 062F;;;;N;GLYPH FOR ISOLATE ARABIC DAL;;;; +FEAA;ARABIC LETTER DAL FINAL FORM;Lo;0;AL;<final> 062F;;;;N;GLYPH FOR FINAL ARABIC DAL;;;; +FEAB;ARABIC LETTER THAL ISOLATED FORM;Lo;0;AL;<isolated> 0630;;;;N;GLYPH FOR ISOLATE ARABIC THAL;;;; +FEAC;ARABIC LETTER THAL FINAL FORM;Lo;0;AL;<final> 0630;;;;N;GLYPH FOR FINAL ARABIC THAL;;;; +FEAD;ARABIC LETTER REH ISOLATED FORM;Lo;0;AL;<isolated> 0631;;;;N;GLYPH FOR ISOLATE ARABIC RA;;;; +FEAE;ARABIC LETTER REH FINAL FORM;Lo;0;AL;<final> 0631;;;;N;GLYPH FOR FINAL ARABIC RA;;;; +FEAF;ARABIC LETTER ZAIN ISOLATED FORM;Lo;0;AL;<isolated> 0632;;;;N;GLYPH FOR ISOLATE ARABIC ZAIN;;;; +FEB0;ARABIC LETTER ZAIN FINAL FORM;Lo;0;AL;<final> 0632;;;;N;GLYPH FOR FINAL ARABIC ZAIN;;;; +FEB1;ARABIC LETTER SEEN ISOLATED FORM;Lo;0;AL;<isolated> 0633;;;;N;GLYPH FOR ISOLATE ARABIC SEEN;;;; +FEB2;ARABIC LETTER SEEN FINAL FORM;Lo;0;AL;<final> 0633;;;;N;GLYPH FOR FINAL ARABIC SEEN;;;; +FEB3;ARABIC LETTER SEEN INITIAL FORM;Lo;0;AL;<initial> 0633;;;;N;GLYPH FOR INITIAL ARABIC SEEN;;;; +FEB4;ARABIC LETTER SEEN MEDIAL FORM;Lo;0;AL;<medial> 0633;;;;N;GLYPH FOR MEDIAL ARABIC SEEN;;;; +FEB5;ARABIC LETTER SHEEN ISOLATED FORM;Lo;0;AL;<isolated> 0634;;;;N;GLYPH FOR ISOLATE ARABIC SHEEN;;;; +FEB6;ARABIC LETTER SHEEN FINAL FORM;Lo;0;AL;<final> 0634;;;;N;GLYPH FOR FINAL ARABIC SHEEN;;;; +FEB7;ARABIC LETTER SHEEN INITIAL FORM;Lo;0;AL;<initial> 0634;;;;N;GLYPH FOR INITIAL ARABIC SHEEN;;;; +FEB8;ARABIC LETTER SHEEN MEDIAL FORM;Lo;0;AL;<medial> 0634;;;;N;GLYPH FOR MEDIAL ARABIC SHEEN;;;; +FEB9;ARABIC LETTER SAD ISOLATED FORM;Lo;0;AL;<isolated> 0635;;;;N;GLYPH FOR ISOLATE ARABIC SAD;;;; +FEBA;ARABIC LETTER SAD FINAL FORM;Lo;0;AL;<final> 0635;;;;N;GLYPH FOR FINAL ARABIC SAD;;;; +FEBB;ARABIC LETTER SAD INITIAL FORM;Lo;0;AL;<initial> 0635;;;;N;GLYPH FOR INITIAL ARABIC SAD;;;; +FEBC;ARABIC LETTER SAD MEDIAL FORM;Lo;0;AL;<medial> 0635;;;;N;GLYPH FOR MEDIAL ARABIC SAD;;;; +FEBD;ARABIC LETTER DAD ISOLATED FORM;Lo;0;AL;<isolated> 0636;;;;N;GLYPH FOR ISOLATE ARABIC DAD;;;; +FEBE;ARABIC LETTER DAD FINAL FORM;Lo;0;AL;<final> 0636;;;;N;GLYPH FOR FINAL ARABIC DAD;;;; +FEBF;ARABIC LETTER DAD INITIAL FORM;Lo;0;AL;<initial> 0636;;;;N;GLYPH FOR INITIAL ARABIC DAD;;;; +FEC0;ARABIC LETTER DAD MEDIAL FORM;Lo;0;AL;<medial> 0636;;;;N;GLYPH FOR MEDIAL ARABIC DAD;;;; +FEC1;ARABIC LETTER TAH ISOLATED FORM;Lo;0;AL;<isolated> 0637;;;;N;GLYPH FOR ISOLATE ARABIC TAH;;;; +FEC2;ARABIC LETTER TAH FINAL FORM;Lo;0;AL;<final> 0637;;;;N;GLYPH FOR FINAL ARABIC TAH;;;; +FEC3;ARABIC LETTER TAH INITIAL FORM;Lo;0;AL;<initial> 0637;;;;N;GLYPH FOR INITIAL ARABIC TAH;;;; +FEC4;ARABIC LETTER TAH MEDIAL FORM;Lo;0;AL;<medial> 0637;;;;N;GLYPH FOR MEDIAL ARABIC TAH;;;; +FEC5;ARABIC LETTER ZAH ISOLATED FORM;Lo;0;AL;<isolated> 0638;;;;N;GLYPH FOR ISOLATE ARABIC DHAH;;;; +FEC6;ARABIC LETTER ZAH FINAL FORM;Lo;0;AL;<final> 0638;;;;N;GLYPH FOR FINAL ARABIC DHAH;;;; +FEC7;ARABIC LETTER ZAH INITIAL FORM;Lo;0;AL;<initial> 0638;;;;N;GLYPH FOR INITIAL ARABIC DHAH;;;; +FEC8;ARABIC LETTER ZAH MEDIAL FORM;Lo;0;AL;<medial> 0638;;;;N;GLYPH FOR MEDIAL ARABIC DHAH;;;; +FEC9;ARABIC LETTER AIN ISOLATED FORM;Lo;0;AL;<isolated> 0639;;;;N;GLYPH FOR ISOLATE ARABIC AIN;;;; +FECA;ARABIC LETTER AIN FINAL FORM;Lo;0;AL;<final> 0639;;;;N;GLYPH FOR FINAL ARABIC AIN;;;; +FECB;ARABIC LETTER AIN INITIAL FORM;Lo;0;AL;<initial> 0639;;;;N;GLYPH FOR INITIAL ARABIC AIN;;;; +FECC;ARABIC LETTER AIN MEDIAL FORM;Lo;0;AL;<medial> 0639;;;;N;GLYPH FOR MEDIAL ARABIC AIN;;;; +FECD;ARABIC LETTER GHAIN ISOLATED FORM;Lo;0;AL;<isolated> 063A;;;;N;GLYPH FOR ISOLATE ARABIC GHAIN;;;; +FECE;ARABIC LETTER GHAIN FINAL FORM;Lo;0;AL;<final> 063A;;;;N;GLYPH FOR FINAL ARABIC GHAIN;;;; +FECF;ARABIC LETTER GHAIN INITIAL FORM;Lo;0;AL;<initial> 063A;;;;N;GLYPH FOR INITIAL ARABIC GHAIN;;;; +FED0;ARABIC LETTER GHAIN MEDIAL FORM;Lo;0;AL;<medial> 063A;;;;N;GLYPH FOR MEDIAL ARABIC GHAIN;;;; +FED1;ARABIC LETTER FEH ISOLATED FORM;Lo;0;AL;<isolated> 0641;;;;N;GLYPH FOR ISOLATE ARABIC FA;;;; +FED2;ARABIC LETTER FEH FINAL FORM;Lo;0;AL;<final> 0641;;;;N;GLYPH FOR FINAL ARABIC FA;;;; +FED3;ARABIC LETTER FEH INITIAL FORM;Lo;0;AL;<initial> 0641;;;;N;GLYPH FOR INITIAL ARABIC FA;;;; +FED4;ARABIC LETTER FEH MEDIAL FORM;Lo;0;AL;<medial> 0641;;;;N;GLYPH FOR MEDIAL ARABIC FA;;;; +FED5;ARABIC LETTER QAF ISOLATED FORM;Lo;0;AL;<isolated> 0642;;;;N;GLYPH FOR ISOLATE ARABIC QAF;;;; +FED6;ARABIC LETTER QAF FINAL FORM;Lo;0;AL;<final> 0642;;;;N;GLYPH FOR FINAL ARABIC QAF;;;; +FED7;ARABIC LETTER QAF INITIAL FORM;Lo;0;AL;<initial> 0642;;;;N;GLYPH FOR INITIAL ARABIC QAF;;;; +FED8;ARABIC LETTER QAF MEDIAL FORM;Lo;0;AL;<medial> 0642;;;;N;GLYPH FOR MEDIAL ARABIC QAF;;;; +FED9;ARABIC LETTER KAF ISOLATED FORM;Lo;0;AL;<isolated> 0643;;;;N;GLYPH FOR ISOLATE ARABIC CAF;;;; +FEDA;ARABIC LETTER KAF FINAL FORM;Lo;0;AL;<final> 0643;;;;N;GLYPH FOR FINAL ARABIC CAF;;;; +FEDB;ARABIC LETTER KAF INITIAL FORM;Lo;0;AL;<initial> 0643;;;;N;GLYPH FOR INITIAL ARABIC CAF;;;; +FEDC;ARABIC LETTER KAF MEDIAL FORM;Lo;0;AL;<medial> 0643;;;;N;GLYPH FOR MEDIAL ARABIC CAF;;;; +FEDD;ARABIC LETTER LAM ISOLATED FORM;Lo;0;AL;<isolated> 0644;;;;N;GLYPH FOR ISOLATE ARABIC LAM;;;; +FEDE;ARABIC LETTER LAM FINAL FORM;Lo;0;AL;<final> 0644;;;;N;GLYPH FOR FINAL ARABIC LAM;;;; +FEDF;ARABIC LETTER LAM INITIAL FORM;Lo;0;AL;<initial> 0644;;;;N;GLYPH FOR INITIAL ARABIC LAM;;;; +FEE0;ARABIC LETTER LAM MEDIAL FORM;Lo;0;AL;<medial> 0644;;;;N;GLYPH FOR MEDIAL ARABIC LAM;;;; +FEE1;ARABIC LETTER MEEM ISOLATED FORM;Lo;0;AL;<isolated> 0645;;;;N;GLYPH FOR ISOLATE ARABIC MEEM;;;; +FEE2;ARABIC LETTER MEEM FINAL FORM;Lo;0;AL;<final> 0645;;;;N;GLYPH FOR FINAL ARABIC MEEM;;;; +FEE3;ARABIC LETTER MEEM INITIAL FORM;Lo;0;AL;<initial> 0645;;;;N;GLYPH FOR INITIAL ARABIC MEEM;;;; +FEE4;ARABIC LETTER MEEM MEDIAL FORM;Lo;0;AL;<medial> 0645;;;;N;GLYPH FOR MEDIAL ARABIC MEEM;;;; +FEE5;ARABIC LETTER NOON ISOLATED FORM;Lo;0;AL;<isolated> 0646;;;;N;GLYPH FOR ISOLATE ARABIC NOON;;;; +FEE6;ARABIC LETTER NOON FINAL FORM;Lo;0;AL;<final> 0646;;;;N;GLYPH FOR FINAL ARABIC NOON;;;; +FEE7;ARABIC LETTER NOON INITIAL FORM;Lo;0;AL;<initial> 0646;;;;N;GLYPH FOR INITIAL ARABIC NOON;;;; +FEE8;ARABIC LETTER NOON MEDIAL FORM;Lo;0;AL;<medial> 0646;;;;N;GLYPH FOR MEDIAL ARABIC NOON;;;; +FEE9;ARABIC LETTER HEH ISOLATED FORM;Lo;0;AL;<isolated> 0647;;;;N;GLYPH FOR ISOLATE ARABIC HA;;;; +FEEA;ARABIC LETTER HEH FINAL FORM;Lo;0;AL;<final> 0647;;;;N;GLYPH FOR FINAL ARABIC HA;;;; +FEEB;ARABIC LETTER HEH INITIAL FORM;Lo;0;AL;<initial> 0647;;;;N;GLYPH FOR INITIAL ARABIC HA;;;; +FEEC;ARABIC LETTER HEH MEDIAL FORM;Lo;0;AL;<medial> 0647;;;;N;GLYPH FOR MEDIAL ARABIC HA;;;; +FEED;ARABIC LETTER WAW ISOLATED FORM;Lo;0;AL;<isolated> 0648;;;;N;GLYPH FOR ISOLATE ARABIC WAW;;;; +FEEE;ARABIC LETTER WAW FINAL FORM;Lo;0;AL;<final> 0648;;;;N;GLYPH FOR FINAL ARABIC WAW;;;; +FEEF;ARABIC LETTER ALEF MAKSURA ISOLATED FORM;Lo;0;AL;<isolated> 0649;;;;N;GLYPH FOR ISOLATE ARABIC ALEF MAQSURAH;;;; +FEF0;ARABIC LETTER ALEF MAKSURA FINAL FORM;Lo;0;AL;<final> 0649;;;;N;GLYPH FOR FINAL ARABIC ALEF MAQSURAH;;;; +FEF1;ARABIC LETTER YEH ISOLATED FORM;Lo;0;AL;<isolated> 064A;;;;N;GLYPH FOR ISOLATE ARABIC YA;;;; +FEF2;ARABIC LETTER YEH FINAL FORM;Lo;0;AL;<final> 064A;;;;N;GLYPH FOR FINAL ARABIC YA;;;; +FEF3;ARABIC LETTER YEH INITIAL FORM;Lo;0;AL;<initial> 064A;;;;N;GLYPH FOR INITIAL ARABIC YA;;;; +FEF4;ARABIC LETTER YEH MEDIAL FORM;Lo;0;AL;<medial> 064A;;;;N;GLYPH FOR MEDIAL ARABIC YA;;;; +FEF5;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0644 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON LIGATURE LAM ALEF;;;; +FEF6;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL;<final> 0644 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON LIGATURE LAM ALEF;;;; +FEF7;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL;<isolated> 0644 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; +FEF8;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL;<final> 0644 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; +FEF9;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL;<isolated> 0644 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; +FEFA;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL;<final> 0644 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; +FEFB;ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM;Lo;0;AL;<isolated> 0644 0627;;;;N;GLYPH FOR ISOLATE ARABIC LIGATURE LAM ALEF;;;; +FEFC;ARABIC LIGATURE LAM WITH ALEF FINAL FORM;Lo;0;AL;<final> 0644 0627;;;;N;GLYPH FOR FINAL ARABIC LIGATURE LAM ALEF;;;; +FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; +FF01;FULLWIDTH EXCLAMATION MARK;Po;0;ON;<wide> 0021;;;;N;;;;; +FF02;FULLWIDTH QUOTATION MARK;Po;0;ON;<wide> 0022;;;;N;;;;; +FF03;FULLWIDTH NUMBER SIGN;Po;0;ET;<wide> 0023;;;;N;;;;; +FF04;FULLWIDTH DOLLAR SIGN;Sc;0;ET;<wide> 0024;;;;N;;;;; +FF05;FULLWIDTH PERCENT SIGN;Po;0;ET;<wide> 0025;;;;N;;;;; +FF06;FULLWIDTH AMPERSAND;Po;0;ON;<wide> 0026;;;;N;;;;; +FF07;FULLWIDTH APOSTROPHE;Po;0;ON;<wide> 0027;;;;N;;;;; +FF08;FULLWIDTH LEFT PARENTHESIS;Ps;0;ON;<wide> 0028;;;;Y;FULLWIDTH OPENING PARENTHESIS;;;; +FF09;FULLWIDTH RIGHT PARENTHESIS;Pe;0;ON;<wide> 0029;;;;Y;FULLWIDTH CLOSING PARENTHESIS;;;; +FF0A;FULLWIDTH ASTERISK;Po;0;ON;<wide> 002A;;;;N;;;;; +FF0B;FULLWIDTH PLUS SIGN;Sm;0;ES;<wide> 002B;;;;N;;;;; +FF0C;FULLWIDTH COMMA;Po;0;CS;<wide> 002C;;;;N;;;;; +FF0D;FULLWIDTH HYPHEN-MINUS;Pd;0;ES;<wide> 002D;;;;N;;;;; +FF0E;FULLWIDTH FULL STOP;Po;0;CS;<wide> 002E;;;;N;FULLWIDTH PERIOD;;;; +FF0F;FULLWIDTH SOLIDUS;Po;0;CS;<wide> 002F;;;;N;FULLWIDTH SLASH;;;; +FF10;FULLWIDTH DIGIT ZERO;Nd;0;EN;<wide> 0030;0;0;0;N;;;;; +FF11;FULLWIDTH DIGIT ONE;Nd;0;EN;<wide> 0031;1;1;1;N;;;;; +FF12;FULLWIDTH DIGIT TWO;Nd;0;EN;<wide> 0032;2;2;2;N;;;;; +FF13;FULLWIDTH DIGIT THREE;Nd;0;EN;<wide> 0033;3;3;3;N;;;;; +FF14;FULLWIDTH DIGIT FOUR;Nd;0;EN;<wide> 0034;4;4;4;N;;;;; +FF15;FULLWIDTH DIGIT FIVE;Nd;0;EN;<wide> 0035;5;5;5;N;;;;; +FF16;FULLWIDTH DIGIT SIX;Nd;0;EN;<wide> 0036;6;6;6;N;;;;; +FF17;FULLWIDTH DIGIT SEVEN;Nd;0;EN;<wide> 0037;7;7;7;N;;;;; +FF18;FULLWIDTH DIGIT EIGHT;Nd;0;EN;<wide> 0038;8;8;8;N;;;;; +FF19;FULLWIDTH DIGIT NINE;Nd;0;EN;<wide> 0039;9;9;9;N;;;;; +FF1A;FULLWIDTH COLON;Po;0;CS;<wide> 003A;;;;N;;;;; +FF1B;FULLWIDTH SEMICOLON;Po;0;ON;<wide> 003B;;;;N;;;;; +FF1C;FULLWIDTH LESS-THAN SIGN;Sm;0;ON;<wide> 003C;;;;Y;;;;; +FF1D;FULLWIDTH EQUALS SIGN;Sm;0;ON;<wide> 003D;;;;N;;;;; +FF1E;FULLWIDTH GREATER-THAN SIGN;Sm;0;ON;<wide> 003E;;;;Y;;;;; +FF1F;FULLWIDTH QUESTION MARK;Po;0;ON;<wide> 003F;;;;N;;;;; +FF20;FULLWIDTH COMMERCIAL AT;Po;0;ON;<wide> 0040;;;;N;;;;; +FF21;FULLWIDTH LATIN CAPITAL LETTER A;Lu;0;L;<wide> 0041;;;;N;;;;FF41; +FF22;FULLWIDTH LATIN CAPITAL LETTER B;Lu;0;L;<wide> 0042;;;;N;;;;FF42; +FF23;FULLWIDTH LATIN CAPITAL LETTER C;Lu;0;L;<wide> 0043;;;;N;;;;FF43; +FF24;FULLWIDTH LATIN CAPITAL LETTER D;Lu;0;L;<wide> 0044;;;;N;;;;FF44; +FF25;FULLWIDTH LATIN CAPITAL LETTER E;Lu;0;L;<wide> 0045;;;;N;;;;FF45; +FF26;FULLWIDTH LATIN CAPITAL LETTER F;Lu;0;L;<wide> 0046;;;;N;;;;FF46; +FF27;FULLWIDTH LATIN CAPITAL LETTER G;Lu;0;L;<wide> 0047;;;;N;;;;FF47; +FF28;FULLWIDTH LATIN CAPITAL LETTER H;Lu;0;L;<wide> 0048;;;;N;;;;FF48; +FF29;FULLWIDTH LATIN CAPITAL LETTER I;Lu;0;L;<wide> 0049;;;;N;;;;FF49; +FF2A;FULLWIDTH LATIN CAPITAL LETTER J;Lu;0;L;<wide> 004A;;;;N;;;;FF4A; +FF2B;FULLWIDTH LATIN CAPITAL LETTER K;Lu;0;L;<wide> 004B;;;;N;;;;FF4B; +FF2C;FULLWIDTH LATIN CAPITAL LETTER L;Lu;0;L;<wide> 004C;;;;N;;;;FF4C; +FF2D;FULLWIDTH LATIN CAPITAL LETTER M;Lu;0;L;<wide> 004D;;;;N;;;;FF4D; +FF2E;FULLWIDTH LATIN CAPITAL LETTER N;Lu;0;L;<wide> 004E;;;;N;;;;FF4E; +FF2F;FULLWIDTH LATIN CAPITAL LETTER O;Lu;0;L;<wide> 004F;;;;N;;;;FF4F; +FF30;FULLWIDTH LATIN CAPITAL LETTER P;Lu;0;L;<wide> 0050;;;;N;;;;FF50; +FF31;FULLWIDTH LATIN CAPITAL LETTER Q;Lu;0;L;<wide> 0051;;;;N;;;;FF51; +FF32;FULLWIDTH LATIN CAPITAL LETTER R;Lu;0;L;<wide> 0052;;;;N;;;;FF52; +FF33;FULLWIDTH LATIN CAPITAL LETTER S;Lu;0;L;<wide> 0053;;;;N;;;;FF53; +FF34;FULLWIDTH LATIN CAPITAL LETTER T;Lu;0;L;<wide> 0054;;;;N;;;;FF54; +FF35;FULLWIDTH LATIN CAPITAL LETTER U;Lu;0;L;<wide> 0055;;;;N;;;;FF55; +FF36;FULLWIDTH LATIN CAPITAL LETTER V;Lu;0;L;<wide> 0056;;;;N;;;;FF56; +FF37;FULLWIDTH LATIN CAPITAL LETTER W;Lu;0;L;<wide> 0057;;;;N;;;;FF57; +FF38;FULLWIDTH LATIN CAPITAL LETTER X;Lu;0;L;<wide> 0058;;;;N;;;;FF58; +FF39;FULLWIDTH LATIN CAPITAL LETTER Y;Lu;0;L;<wide> 0059;;;;N;;;;FF59; +FF3A;FULLWIDTH LATIN CAPITAL LETTER Z;Lu;0;L;<wide> 005A;;;;N;;;;FF5A; +FF3B;FULLWIDTH LEFT SQUARE BRACKET;Ps;0;ON;<wide> 005B;;;;Y;FULLWIDTH OPENING SQUARE BRACKET;;;; +FF3C;FULLWIDTH REVERSE SOLIDUS;Po;0;ON;<wide> 005C;;;;N;FULLWIDTH BACKSLASH;;;; +FF3D;FULLWIDTH RIGHT SQUARE BRACKET;Pe;0;ON;<wide> 005D;;;;Y;FULLWIDTH CLOSING SQUARE BRACKET;;;; +FF3E;FULLWIDTH CIRCUMFLEX ACCENT;Sk;0;ON;<wide> 005E;;;;N;FULLWIDTH SPACING CIRCUMFLEX;;;; +FF3F;FULLWIDTH LOW LINE;Pc;0;ON;<wide> 005F;;;;N;FULLWIDTH SPACING UNDERSCORE;;;; +FF40;FULLWIDTH GRAVE ACCENT;Sk;0;ON;<wide> 0060;;;;N;FULLWIDTH SPACING GRAVE;;;; +FF41;FULLWIDTH LATIN SMALL LETTER A;Ll;0;L;<wide> 0061;;;;N;;;FF21;;FF21 +FF42;FULLWIDTH LATIN SMALL LETTER B;Ll;0;L;<wide> 0062;;;;N;;;FF22;;FF22 +FF43;FULLWIDTH LATIN SMALL LETTER C;Ll;0;L;<wide> 0063;;;;N;;;FF23;;FF23 +FF44;FULLWIDTH LATIN SMALL LETTER D;Ll;0;L;<wide> 0064;;;;N;;;FF24;;FF24 +FF45;FULLWIDTH LATIN SMALL LETTER E;Ll;0;L;<wide> 0065;;;;N;;;FF25;;FF25 +FF46;FULLWIDTH LATIN SMALL LETTER F;Ll;0;L;<wide> 0066;;;;N;;;FF26;;FF26 +FF47;FULLWIDTH LATIN SMALL LETTER G;Ll;0;L;<wide> 0067;;;;N;;;FF27;;FF27 +FF48;FULLWIDTH LATIN SMALL LETTER H;Ll;0;L;<wide> 0068;;;;N;;;FF28;;FF28 +FF49;FULLWIDTH LATIN SMALL LETTER I;Ll;0;L;<wide> 0069;;;;N;;;FF29;;FF29 +FF4A;FULLWIDTH LATIN SMALL LETTER J;Ll;0;L;<wide> 006A;;;;N;;;FF2A;;FF2A +FF4B;FULLWIDTH LATIN SMALL LETTER K;Ll;0;L;<wide> 006B;;;;N;;;FF2B;;FF2B +FF4C;FULLWIDTH LATIN SMALL LETTER L;Ll;0;L;<wide> 006C;;;;N;;;FF2C;;FF2C +FF4D;FULLWIDTH LATIN SMALL LETTER M;Ll;0;L;<wide> 006D;;;;N;;;FF2D;;FF2D +FF4E;FULLWIDTH LATIN SMALL LETTER N;Ll;0;L;<wide> 006E;;;;N;;;FF2E;;FF2E +FF4F;FULLWIDTH LATIN SMALL LETTER O;Ll;0;L;<wide> 006F;;;;N;;;FF2F;;FF2F +FF50;FULLWIDTH LATIN SMALL LETTER P;Ll;0;L;<wide> 0070;;;;N;;;FF30;;FF30 +FF51;FULLWIDTH LATIN SMALL LETTER Q;Ll;0;L;<wide> 0071;;;;N;;;FF31;;FF31 +FF52;FULLWIDTH LATIN SMALL LETTER R;Ll;0;L;<wide> 0072;;;;N;;;FF32;;FF32 +FF53;FULLWIDTH LATIN SMALL LETTER S;Ll;0;L;<wide> 0073;;;;N;;;FF33;;FF33 +FF54;FULLWIDTH LATIN SMALL LETTER T;Ll;0;L;<wide> 0074;;;;N;;;FF34;;FF34 +FF55;FULLWIDTH LATIN SMALL LETTER U;Ll;0;L;<wide> 0075;;;;N;;;FF35;;FF35 +FF56;FULLWIDTH LATIN SMALL LETTER V;Ll;0;L;<wide> 0076;;;;N;;;FF36;;FF36 +FF57;FULLWIDTH LATIN SMALL LETTER W;Ll;0;L;<wide> 0077;;;;N;;;FF37;;FF37 +FF58;FULLWIDTH LATIN SMALL LETTER X;Ll;0;L;<wide> 0078;;;;N;;;FF38;;FF38 +FF59;FULLWIDTH LATIN SMALL LETTER Y;Ll;0;L;<wide> 0079;;;;N;;;FF39;;FF39 +FF5A;FULLWIDTH LATIN SMALL LETTER Z;Ll;0;L;<wide> 007A;;;;N;;;FF3A;;FF3A +FF5B;FULLWIDTH LEFT CURLY BRACKET;Ps;0;ON;<wide> 007B;;;;Y;FULLWIDTH OPENING CURLY BRACKET;;;; +FF5C;FULLWIDTH VERTICAL LINE;Sm;0;ON;<wide> 007C;;;;N;FULLWIDTH VERTICAL BAR;;;; +FF5D;FULLWIDTH RIGHT CURLY BRACKET;Pe;0;ON;<wide> 007D;;;;Y;FULLWIDTH CLOSING CURLY BRACKET;;;; +FF5E;FULLWIDTH TILDE;Sm;0;ON;<wide> 007E;;;;N;FULLWIDTH SPACING TILDE;;;; +FF5F;FULLWIDTH LEFT WHITE PARENTHESIS;Ps;0;ON;<wide> 2985;;;;Y;;;;; +FF60;FULLWIDTH RIGHT WHITE PARENTHESIS;Pe;0;ON;<wide> 2986;;;;Y;;;;; +FF61;HALFWIDTH IDEOGRAPHIC FULL STOP;Po;0;ON;<narrow> 3002;;;;N;HALFWIDTH IDEOGRAPHIC PERIOD;;;; +FF62;HALFWIDTH LEFT CORNER BRACKET;Ps;0;ON;<narrow> 300C;;;;Y;HALFWIDTH OPENING CORNER BRACKET;;;; +FF63;HALFWIDTH RIGHT CORNER BRACKET;Pe;0;ON;<narrow> 300D;;;;Y;HALFWIDTH CLOSING CORNER BRACKET;;;; +FF64;HALFWIDTH IDEOGRAPHIC COMMA;Po;0;ON;<narrow> 3001;;;;N;;;;; +FF65;HALFWIDTH KATAKANA MIDDLE DOT;Po;0;ON;<narrow> 30FB;;;;N;;;;; +FF66;HALFWIDTH KATAKANA LETTER WO;Lo;0;L;<narrow> 30F2;;;;N;;;;; +FF67;HALFWIDTH KATAKANA LETTER SMALL A;Lo;0;L;<narrow> 30A1;;;;N;;;;; +FF68;HALFWIDTH KATAKANA LETTER SMALL I;Lo;0;L;<narrow> 30A3;;;;N;;;;; +FF69;HALFWIDTH KATAKANA LETTER SMALL U;Lo;0;L;<narrow> 30A5;;;;N;;;;; +FF6A;HALFWIDTH KATAKANA LETTER SMALL E;Lo;0;L;<narrow> 30A7;;;;N;;;;; +FF6B;HALFWIDTH KATAKANA LETTER SMALL O;Lo;0;L;<narrow> 30A9;;;;N;;;;; +FF6C;HALFWIDTH KATAKANA LETTER SMALL YA;Lo;0;L;<narrow> 30E3;;;;N;;;;; +FF6D;HALFWIDTH KATAKANA LETTER SMALL YU;Lo;0;L;<narrow> 30E5;;;;N;;;;; +FF6E;HALFWIDTH KATAKANA LETTER SMALL YO;Lo;0;L;<narrow> 30E7;;;;N;;;;; +FF6F;HALFWIDTH KATAKANA LETTER SMALL TU;Lo;0;L;<narrow> 30C3;;;;N;;;;; +FF70;HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;<narrow> 30FC;;;;N;;;;; +FF71;HALFWIDTH KATAKANA LETTER A;Lo;0;L;<narrow> 30A2;;;;N;;;;; +FF72;HALFWIDTH KATAKANA LETTER I;Lo;0;L;<narrow> 30A4;;;;N;;;;; +FF73;HALFWIDTH KATAKANA LETTER U;Lo;0;L;<narrow> 30A6;;;;N;;;;; +FF74;HALFWIDTH KATAKANA LETTER E;Lo;0;L;<narrow> 30A8;;;;N;;;;; +FF75;HALFWIDTH KATAKANA LETTER O;Lo;0;L;<narrow> 30AA;;;;N;;;;; +FF76;HALFWIDTH KATAKANA LETTER KA;Lo;0;L;<narrow> 30AB;;;;N;;;;; +FF77;HALFWIDTH KATAKANA LETTER KI;Lo;0;L;<narrow> 30AD;;;;N;;;;; +FF78;HALFWIDTH KATAKANA LETTER KU;Lo;0;L;<narrow> 30AF;;;;N;;;;; +FF79;HALFWIDTH KATAKANA LETTER KE;Lo;0;L;<narrow> 30B1;;;;N;;;;; +FF7A;HALFWIDTH KATAKANA LETTER KO;Lo;0;L;<narrow> 30B3;;;;N;;;;; +FF7B;HALFWIDTH KATAKANA LETTER SA;Lo;0;L;<narrow> 30B5;;;;N;;;;; +FF7C;HALFWIDTH KATAKANA LETTER SI;Lo;0;L;<narrow> 30B7;;;;N;;;;; +FF7D;HALFWIDTH KATAKANA LETTER SU;Lo;0;L;<narrow> 30B9;;;;N;;;;; +FF7E;HALFWIDTH KATAKANA LETTER SE;Lo;0;L;<narrow> 30BB;;;;N;;;;; +FF7F;HALFWIDTH KATAKANA LETTER SO;Lo;0;L;<narrow> 30BD;;;;N;;;;; +FF80;HALFWIDTH KATAKANA LETTER TA;Lo;0;L;<narrow> 30BF;;;;N;;;;; +FF81;HALFWIDTH KATAKANA LETTER TI;Lo;0;L;<narrow> 30C1;;;;N;;;;; +FF82;HALFWIDTH KATAKANA LETTER TU;Lo;0;L;<narrow> 30C4;;;;N;;;;; +FF83;HALFWIDTH KATAKANA LETTER TE;Lo;0;L;<narrow> 30C6;;;;N;;;;; +FF84;HALFWIDTH KATAKANA LETTER TO;Lo;0;L;<narrow> 30C8;;;;N;;;;; +FF85;HALFWIDTH KATAKANA LETTER NA;Lo;0;L;<narrow> 30CA;;;;N;;;;; +FF86;HALFWIDTH KATAKANA LETTER NI;Lo;0;L;<narrow> 30CB;;;;N;;;;; +FF87;HALFWIDTH KATAKANA LETTER NU;Lo;0;L;<narrow> 30CC;;;;N;;;;; +FF88;HALFWIDTH KATAKANA LETTER NE;Lo;0;L;<narrow> 30CD;;;;N;;;;; +FF89;HALFWIDTH KATAKANA LETTER NO;Lo;0;L;<narrow> 30CE;;;;N;;;;; +FF8A;HALFWIDTH KATAKANA LETTER HA;Lo;0;L;<narrow> 30CF;;;;N;;;;; +FF8B;HALFWIDTH KATAKANA LETTER HI;Lo;0;L;<narrow> 30D2;;;;N;;;;; +FF8C;HALFWIDTH KATAKANA LETTER HU;Lo;0;L;<narrow> 30D5;;;;N;;;;; +FF8D;HALFWIDTH KATAKANA LETTER HE;Lo;0;L;<narrow> 30D8;;;;N;;;;; +FF8E;HALFWIDTH KATAKANA LETTER HO;Lo;0;L;<narrow> 30DB;;;;N;;;;; +FF8F;HALFWIDTH KATAKANA LETTER MA;Lo;0;L;<narrow> 30DE;;;;N;;;;; +FF90;HALFWIDTH KATAKANA LETTER MI;Lo;0;L;<narrow> 30DF;;;;N;;;;; +FF91;HALFWIDTH KATAKANA LETTER MU;Lo;0;L;<narrow> 30E0;;;;N;;;;; +FF92;HALFWIDTH KATAKANA LETTER ME;Lo;0;L;<narrow> 30E1;;;;N;;;;; +FF93;HALFWIDTH KATAKANA LETTER MO;Lo;0;L;<narrow> 30E2;;;;N;;;;; +FF94;HALFWIDTH KATAKANA LETTER YA;Lo;0;L;<narrow> 30E4;;;;N;;;;; +FF95;HALFWIDTH KATAKANA LETTER YU;Lo;0;L;<narrow> 30E6;;;;N;;;;; +FF96;HALFWIDTH KATAKANA LETTER YO;Lo;0;L;<narrow> 30E8;;;;N;;;;; +FF97;HALFWIDTH KATAKANA LETTER RA;Lo;0;L;<narrow> 30E9;;;;N;;;;; +FF98;HALFWIDTH KATAKANA LETTER RI;Lo;0;L;<narrow> 30EA;;;;N;;;;; +FF99;HALFWIDTH KATAKANA LETTER RU;Lo;0;L;<narrow> 30EB;;;;N;;;;; +FF9A;HALFWIDTH KATAKANA LETTER RE;Lo;0;L;<narrow> 30EC;;;;N;;;;; +FF9B;HALFWIDTH KATAKANA LETTER RO;Lo;0;L;<narrow> 30ED;;;;N;;;;; +FF9C;HALFWIDTH KATAKANA LETTER WA;Lo;0;L;<narrow> 30EF;;;;N;;;;; +FF9D;HALFWIDTH KATAKANA LETTER N;Lo;0;L;<narrow> 30F3;;;;N;;;;; +FF9E;HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L;<narrow> 3099;;;;N;;;;; +FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L;<narrow> 309A;;;;N;;;;; +FFA0;HALFWIDTH HANGUL FILLER;Lo;0;L;<narrow> 3164;;;;N;HALFWIDTH HANGUL CAE OM;;;; +FFA1;HALFWIDTH HANGUL LETTER KIYEOK;Lo;0;L;<narrow> 3131;;;;N;HALFWIDTH HANGUL LETTER GIYEOG;;;; +FFA2;HALFWIDTH HANGUL LETTER SSANGKIYEOK;Lo;0;L;<narrow> 3132;;;;N;HALFWIDTH HANGUL LETTER SSANG GIYEOG;;;; +FFA3;HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<narrow> 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; +FFA4;HALFWIDTH HANGUL LETTER NIEUN;Lo;0;L;<narrow> 3134;;;;N;;;;; +FFA5;HALFWIDTH HANGUL LETTER NIEUN-CIEUC;Lo;0;L;<narrow> 3135;;;;N;HALFWIDTH HANGUL LETTER NIEUN JIEUJ;;;; +FFA6;HALFWIDTH HANGUL LETTER NIEUN-HIEUH;Lo;0;L;<narrow> 3136;;;;N;HALFWIDTH HANGUL LETTER NIEUN HIEUH;;;; +FFA7;HALFWIDTH HANGUL LETTER TIKEUT;Lo;0;L;<narrow> 3137;;;;N;HALFWIDTH HANGUL LETTER DIGEUD;;;; +FFA8;HALFWIDTH HANGUL LETTER SSANGTIKEUT;Lo;0;L;<narrow> 3138;;;;N;HALFWIDTH HANGUL LETTER SSANG DIGEUD;;;; +FFA9;HALFWIDTH HANGUL LETTER RIEUL;Lo;0;L;<narrow> 3139;;;;N;HALFWIDTH HANGUL LETTER LIEUL;;;; +FFAA;HALFWIDTH HANGUL LETTER RIEUL-KIYEOK;Lo;0;L;<narrow> 313A;;;;N;HALFWIDTH HANGUL LETTER LIEUL GIYEOG;;;; +FFAB;HALFWIDTH HANGUL LETTER RIEUL-MIEUM;Lo;0;L;<narrow> 313B;;;;N;HALFWIDTH HANGUL LETTER LIEUL MIEUM;;;; +FFAC;HALFWIDTH HANGUL LETTER RIEUL-PIEUP;Lo;0;L;<narrow> 313C;;;;N;HALFWIDTH HANGUL LETTER LIEUL BIEUB;;;; +FFAD;HALFWIDTH HANGUL LETTER RIEUL-SIOS;Lo;0;L;<narrow> 313D;;;;N;HALFWIDTH HANGUL LETTER LIEUL SIOS;;;; +FFAE;HALFWIDTH HANGUL LETTER RIEUL-THIEUTH;Lo;0;L;<narrow> 313E;;;;N;HALFWIDTH HANGUL LETTER LIEUL TIEUT;;;; +FFAF;HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L;<narrow> 313F;;;;N;HALFWIDTH HANGUL LETTER LIEUL PIEUP;;;; +FFB0;HALFWIDTH HANGUL LETTER RIEUL-HIEUH;Lo;0;L;<narrow> 3140;;;;N;HALFWIDTH HANGUL LETTER LIEUL HIEUH;;;; +FFB1;HALFWIDTH HANGUL LETTER MIEUM;Lo;0;L;<narrow> 3141;;;;N;;;;; +FFB2;HALFWIDTH HANGUL LETTER PIEUP;Lo;0;L;<narrow> 3142;;;;N;HALFWIDTH HANGUL LETTER BIEUB;;;; +FFB3;HALFWIDTH HANGUL LETTER SSANGPIEUP;Lo;0;L;<narrow> 3143;;;;N;HALFWIDTH HANGUL LETTER SSANG BIEUB;;;; +FFB4;HALFWIDTH HANGUL LETTER PIEUP-SIOS;Lo;0;L;<narrow> 3144;;;;N;HALFWIDTH HANGUL LETTER BIEUB SIOS;;;; +FFB5;HALFWIDTH HANGUL LETTER SIOS;Lo;0;L;<narrow> 3145;;;;N;;;;; +FFB6;HALFWIDTH HANGUL LETTER SSANGSIOS;Lo;0;L;<narrow> 3146;;;;N;HALFWIDTH HANGUL LETTER SSANG SIOS;;;; +FFB7;HALFWIDTH HANGUL LETTER IEUNG;Lo;0;L;<narrow> 3147;;;;N;;;;; +FFB8;HALFWIDTH HANGUL LETTER CIEUC;Lo;0;L;<narrow> 3148;;;;N;HALFWIDTH HANGUL LETTER JIEUJ;;;; +FFB9;HALFWIDTH HANGUL LETTER SSANGCIEUC;Lo;0;L;<narrow> 3149;;;;N;HALFWIDTH HANGUL LETTER SSANG JIEUJ;;;; +FFBA;HALFWIDTH HANGUL LETTER CHIEUCH;Lo;0;L;<narrow> 314A;;;;N;HALFWIDTH HANGUL LETTER CIEUC;;;; +FFBB;HALFWIDTH HANGUL LETTER KHIEUKH;Lo;0;L;<narrow> 314B;;;;N;HALFWIDTH HANGUL LETTER KIYEOK;;;; +FFBC;HALFWIDTH HANGUL LETTER THIEUTH;Lo;0;L;<narrow> 314C;;;;N;HALFWIDTH HANGUL LETTER TIEUT;;;; +FFBD;HALFWIDTH HANGUL LETTER PHIEUPH;Lo;0;L;<narrow> 314D;;;;N;HALFWIDTH HANGUL LETTER PIEUP;;;; +FFBE;HALFWIDTH HANGUL LETTER HIEUH;Lo;0;L;<narrow> 314E;;;;N;;;;; +FFC2;HALFWIDTH HANGUL LETTER A;Lo;0;L;<narrow> 314F;;;;N;;;;; +FFC3;HALFWIDTH HANGUL LETTER AE;Lo;0;L;<narrow> 3150;;;;N;;;;; +FFC4;HALFWIDTH HANGUL LETTER YA;Lo;0;L;<narrow> 3151;;;;N;;;;; +FFC5;HALFWIDTH HANGUL LETTER YAE;Lo;0;L;<narrow> 3152;;;;N;;;;; +FFC6;HALFWIDTH HANGUL LETTER EO;Lo;0;L;<narrow> 3153;;;;N;;;;; +FFC7;HALFWIDTH HANGUL LETTER E;Lo;0;L;<narrow> 3154;;;;N;;;;; +FFCA;HALFWIDTH HANGUL LETTER YEO;Lo;0;L;<narrow> 3155;;;;N;;;;; +FFCB;HALFWIDTH HANGUL LETTER YE;Lo;0;L;<narrow> 3156;;;;N;;;;; +FFCC;HALFWIDTH HANGUL LETTER O;Lo;0;L;<narrow> 3157;;;;N;;;;; +FFCD;HALFWIDTH HANGUL LETTER WA;Lo;0;L;<narrow> 3158;;;;N;;;;; +FFCE;HALFWIDTH HANGUL LETTER WAE;Lo;0;L;<narrow> 3159;;;;N;;;;; +FFCF;HALFWIDTH HANGUL LETTER OE;Lo;0;L;<narrow> 315A;;;;N;;;;; +FFD2;HALFWIDTH HANGUL LETTER YO;Lo;0;L;<narrow> 315B;;;;N;;;;; +FFD3;HALFWIDTH HANGUL LETTER U;Lo;0;L;<narrow> 315C;;;;N;;;;; +FFD4;HALFWIDTH HANGUL LETTER WEO;Lo;0;L;<narrow> 315D;;;;N;;;;; +FFD5;HALFWIDTH HANGUL LETTER WE;Lo;0;L;<narrow> 315E;;;;N;;;;; +FFD6;HALFWIDTH HANGUL LETTER WI;Lo;0;L;<narrow> 315F;;;;N;;;;; +FFD7;HALFWIDTH HANGUL LETTER YU;Lo;0;L;<narrow> 3160;;;;N;;;;; +FFDA;HALFWIDTH HANGUL LETTER EU;Lo;0;L;<narrow> 3161;;;;N;;;;; +FFDB;HALFWIDTH HANGUL LETTER YI;Lo;0;L;<narrow> 3162;;;;N;;;;; +FFDC;HALFWIDTH HANGUL LETTER I;Lo;0;L;<narrow> 3163;;;;N;;;;; +FFE0;FULLWIDTH CENT SIGN;Sc;0;ET;<wide> 00A2;;;;N;;;;; +FFE1;FULLWIDTH POUND SIGN;Sc;0;ET;<wide> 00A3;;;;N;;;;; +FFE2;FULLWIDTH NOT SIGN;Sm;0;ON;<wide> 00AC;;;;N;;;;; +FFE3;FULLWIDTH MACRON;Sk;0;ON;<wide> 00AF;;;;N;FULLWIDTH SPACING MACRON;;;; +FFE4;FULLWIDTH BROKEN BAR;So;0;ON;<wide> 00A6;;;;N;FULLWIDTH BROKEN VERTICAL BAR;;;; +FFE5;FULLWIDTH YEN SIGN;Sc;0;ET;<wide> 00A5;;;;N;;;;; +FFE6;FULLWIDTH WON SIGN;Sc;0;ET;<wide> 20A9;;;;N;;;;; +FFE8;HALFWIDTH FORMS LIGHT VERTICAL;So;0;ON;<narrow> 2502;;;;N;;;;; +FFE9;HALFWIDTH LEFTWARDS ARROW;Sm;0;ON;<narrow> 2190;;;;N;;;;; +FFEA;HALFWIDTH UPWARDS ARROW;Sm;0;ON;<narrow> 2191;;;;N;;;;; +FFEB;HALFWIDTH RIGHTWARDS ARROW;Sm;0;ON;<narrow> 2192;;;;N;;;;; +FFEC;HALFWIDTH DOWNWARDS ARROW;Sm;0;ON;<narrow> 2193;;;;N;;;;; +FFED;HALFWIDTH BLACK SQUARE;So;0;ON;<narrow> 25A0;;;;N;;;;; +FFEE;HALFWIDTH WHITE CIRCLE;So;0;ON;<narrow> 25CB;;;;N;;;;; +FFF9;INTERLINEAR ANNOTATION ANCHOR;Cf;0;ON;;;;;N;;;;; +FFFA;INTERLINEAR ANNOTATION SEPARATOR;Cf;0;ON;;;;;N;;;;; +FFFB;INTERLINEAR ANNOTATION TERMINATOR;Cf;0;ON;;;;;N;;;;; +FFFC;OBJECT REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; +FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; +10000;LINEAR B SYLLABLE B008 A;Lo;0;L;;;;;N;;;;; +10001;LINEAR B SYLLABLE B038 E;Lo;0;L;;;;;N;;;;; +10002;LINEAR B SYLLABLE B028 I;Lo;0;L;;;;;N;;;;; +10003;LINEAR B SYLLABLE B061 O;Lo;0;L;;;;;N;;;;; +10004;LINEAR B SYLLABLE B010 U;Lo;0;L;;;;;N;;;;; +10005;LINEAR B SYLLABLE B001 DA;Lo;0;L;;;;;N;;;;; +10006;LINEAR B SYLLABLE B045 DE;Lo;0;L;;;;;N;;;;; +10007;LINEAR B SYLLABLE B007 DI;Lo;0;L;;;;;N;;;;; +10008;LINEAR B SYLLABLE B014 DO;Lo;0;L;;;;;N;;;;; +10009;LINEAR B SYLLABLE B051 DU;Lo;0;L;;;;;N;;;;; +1000A;LINEAR B SYLLABLE B057 JA;Lo;0;L;;;;;N;;;;; +1000B;LINEAR B SYLLABLE B046 JE;Lo;0;L;;;;;N;;;;; +1000D;LINEAR B SYLLABLE B036 JO;Lo;0;L;;;;;N;;;;; +1000E;LINEAR B SYLLABLE B065 JU;Lo;0;L;;;;;N;;;;; +1000F;LINEAR B SYLLABLE B077 KA;Lo;0;L;;;;;N;;;;; +10010;LINEAR B SYLLABLE B044 KE;Lo;0;L;;;;;N;;;;; +10011;LINEAR B SYLLABLE B067 KI;Lo;0;L;;;;;N;;;;; +10012;LINEAR B SYLLABLE B070 KO;Lo;0;L;;;;;N;;;;; +10013;LINEAR B SYLLABLE B081 KU;Lo;0;L;;;;;N;;;;; +10014;LINEAR B SYLLABLE B080 MA;Lo;0;L;;;;;N;;;;; +10015;LINEAR B SYLLABLE B013 ME;Lo;0;L;;;;;N;;;;; +10016;LINEAR B SYLLABLE B073 MI;Lo;0;L;;;;;N;;;;; +10017;LINEAR B SYLLABLE B015 MO;Lo;0;L;;;;;N;;;;; +10018;LINEAR B SYLLABLE B023 MU;Lo;0;L;;;;;N;;;;; +10019;LINEAR B SYLLABLE B006 NA;Lo;0;L;;;;;N;;;;; +1001A;LINEAR B SYLLABLE B024 NE;Lo;0;L;;;;;N;;;;; +1001B;LINEAR B SYLLABLE B030 NI;Lo;0;L;;;;;N;;;;; +1001C;LINEAR B SYLLABLE B052 NO;Lo;0;L;;;;;N;;;;; +1001D;LINEAR B SYLLABLE B055 NU;Lo;0;L;;;;;N;;;;; +1001E;LINEAR B SYLLABLE B003 PA;Lo;0;L;;;;;N;;;;; +1001F;LINEAR B SYLLABLE B072 PE;Lo;0;L;;;;;N;;;;; +10020;LINEAR B SYLLABLE B039 PI;Lo;0;L;;;;;N;;;;; +10021;LINEAR B SYLLABLE B011 PO;Lo;0;L;;;;;N;;;;; +10022;LINEAR B SYLLABLE B050 PU;Lo;0;L;;;;;N;;;;; +10023;LINEAR B SYLLABLE B016 QA;Lo;0;L;;;;;N;;;;; +10024;LINEAR B SYLLABLE B078 QE;Lo;0;L;;;;;N;;;;; +10025;LINEAR B SYLLABLE B021 QI;Lo;0;L;;;;;N;;;;; +10026;LINEAR B SYLLABLE B032 QO;Lo;0;L;;;;;N;;;;; +10028;LINEAR B SYLLABLE B060 RA;Lo;0;L;;;;;N;;;;; +10029;LINEAR B SYLLABLE B027 RE;Lo;0;L;;;;;N;;;;; +1002A;LINEAR B SYLLABLE B053 RI;Lo;0;L;;;;;N;;;;; +1002B;LINEAR B SYLLABLE B002 RO;Lo;0;L;;;;;N;;;;; +1002C;LINEAR B SYLLABLE B026 RU;Lo;0;L;;;;;N;;;;; +1002D;LINEAR B SYLLABLE B031 SA;Lo;0;L;;;;;N;;;;; +1002E;LINEAR B SYLLABLE B009 SE;Lo;0;L;;;;;N;;;;; +1002F;LINEAR B SYLLABLE B041 SI;Lo;0;L;;;;;N;;;;; +10030;LINEAR B SYLLABLE B012 SO;Lo;0;L;;;;;N;;;;; +10031;LINEAR B SYLLABLE B058 SU;Lo;0;L;;;;;N;;;;; +10032;LINEAR B SYLLABLE B059 TA;Lo;0;L;;;;;N;;;;; +10033;LINEAR B SYLLABLE B004 TE;Lo;0;L;;;;;N;;;;; +10034;LINEAR B SYLLABLE B037 TI;Lo;0;L;;;;;N;;;;; +10035;LINEAR B SYLLABLE B005 TO;Lo;0;L;;;;;N;;;;; +10036;LINEAR B SYLLABLE B069 TU;Lo;0;L;;;;;N;;;;; +10037;LINEAR B SYLLABLE B054 WA;Lo;0;L;;;;;N;;;;; +10038;LINEAR B SYLLABLE B075 WE;Lo;0;L;;;;;N;;;;; +10039;LINEAR B SYLLABLE B040 WI;Lo;0;L;;;;;N;;;;; +1003A;LINEAR B SYLLABLE B042 WO;Lo;0;L;;;;;N;;;;; +1003C;LINEAR B SYLLABLE B017 ZA;Lo;0;L;;;;;N;;;;; +1003D;LINEAR B SYLLABLE B074 ZE;Lo;0;L;;;;;N;;;;; +1003F;LINEAR B SYLLABLE B020 ZO;Lo;0;L;;;;;N;;;;; +10040;LINEAR B SYLLABLE B025 A2;Lo;0;L;;;;;N;;;;; +10041;LINEAR B SYLLABLE B043 A3;Lo;0;L;;;;;N;;;;; +10042;LINEAR B SYLLABLE B085 AU;Lo;0;L;;;;;N;;;;; +10043;LINEAR B SYLLABLE B071 DWE;Lo;0;L;;;;;N;;;;; +10044;LINEAR B SYLLABLE B090 DWO;Lo;0;L;;;;;N;;;;; +10045;LINEAR B SYLLABLE B048 NWA;Lo;0;L;;;;;N;;;;; +10046;LINEAR B SYLLABLE B029 PU2;Lo;0;L;;;;;N;;;;; +10047;LINEAR B SYLLABLE B062 PTE;Lo;0;L;;;;;N;;;;; +10048;LINEAR B SYLLABLE B076 RA2;Lo;0;L;;;;;N;;;;; +10049;LINEAR B SYLLABLE B033 RA3;Lo;0;L;;;;;N;;;;; +1004A;LINEAR B SYLLABLE B068 RO2;Lo;0;L;;;;;N;;;;; +1004B;LINEAR B SYLLABLE B066 TA2;Lo;0;L;;;;;N;;;;; +1004C;LINEAR B SYLLABLE B087 TWE;Lo;0;L;;;;;N;;;;; +1004D;LINEAR B SYLLABLE B091 TWO;Lo;0;L;;;;;N;;;;; +10050;LINEAR B SYMBOL B018;Lo;0;L;;;;;N;;;;; +10051;LINEAR B SYMBOL B019;Lo;0;L;;;;;N;;;;; +10052;LINEAR B SYMBOL B022;Lo;0;L;;;;;N;;;;; +10053;LINEAR B SYMBOL B034;Lo;0;L;;;;;N;;;;; +10054;LINEAR B SYMBOL B047;Lo;0;L;;;;;N;;;;; +10055;LINEAR B SYMBOL B049;Lo;0;L;;;;;N;;;;; +10056;LINEAR B SYMBOL B056;Lo;0;L;;;;;N;;;;; +10057;LINEAR B SYMBOL B063;Lo;0;L;;;;;N;;;;; +10058;LINEAR B SYMBOL B064;Lo;0;L;;;;;N;;;;; +10059;LINEAR B SYMBOL B079;Lo;0;L;;;;;N;;;;; +1005A;LINEAR B SYMBOL B082;Lo;0;L;;;;;N;;;;; +1005B;LINEAR B SYMBOL B083;Lo;0;L;;;;;N;;;;; +1005C;LINEAR B SYMBOL B086;Lo;0;L;;;;;N;;;;; +1005D;LINEAR B SYMBOL B089;Lo;0;L;;;;;N;;;;; +10080;LINEAR B IDEOGRAM B100 MAN;Lo;0;L;;;;;N;;;;; +10081;LINEAR B IDEOGRAM B102 WOMAN;Lo;0;L;;;;;N;;;;; +10082;LINEAR B IDEOGRAM B104 DEER;Lo;0;L;;;;;N;;;;; +10083;LINEAR B IDEOGRAM B105 EQUID;Lo;0;L;;;;;N;;;;; +10084;LINEAR B IDEOGRAM B105F MARE;Lo;0;L;;;;;N;;;;; +10085;LINEAR B IDEOGRAM B105M STALLION;Lo;0;L;;;;;N;;;;; +10086;LINEAR B IDEOGRAM B106F EWE;Lo;0;L;;;;;N;;;;; +10087;LINEAR B IDEOGRAM B106M RAM;Lo;0;L;;;;;N;;;;; +10088;LINEAR B IDEOGRAM B107F SHE-GOAT;Lo;0;L;;;;;N;;;;; +10089;LINEAR B IDEOGRAM B107M HE-GOAT;Lo;0;L;;;;;N;;;;; +1008A;LINEAR B IDEOGRAM B108F SOW;Lo;0;L;;;;;N;;;;; +1008B;LINEAR B IDEOGRAM B108M BOAR;Lo;0;L;;;;;N;;;;; +1008C;LINEAR B IDEOGRAM B109F COW;Lo;0;L;;;;;N;;;;; +1008D;LINEAR B IDEOGRAM B109M BULL;Lo;0;L;;;;;N;;;;; +1008E;LINEAR B IDEOGRAM B120 WHEAT;Lo;0;L;;;;;N;;;;; +1008F;LINEAR B IDEOGRAM B121 BARLEY;Lo;0;L;;;;;N;;;;; +10090;LINEAR B IDEOGRAM B122 OLIVE;Lo;0;L;;;;;N;;;;; +10091;LINEAR B IDEOGRAM B123 SPICE;Lo;0;L;;;;;N;;;;; +10092;LINEAR B IDEOGRAM B125 CYPERUS;Lo;0;L;;;;;N;;;;; +10093;LINEAR B MONOGRAM B127 KAPO;Lo;0;L;;;;;N;;;;; +10094;LINEAR B MONOGRAM B128 KANAKO;Lo;0;L;;;;;N;;;;; +10095;LINEAR B IDEOGRAM B130 OIL;Lo;0;L;;;;;N;;;;; +10096;LINEAR B IDEOGRAM B131 WINE;Lo;0;L;;;;;N;;;;; +10097;LINEAR B IDEOGRAM B132;Lo;0;L;;;;;N;;;;; +10098;LINEAR B MONOGRAM B133 AREPA;Lo;0;L;;;;;N;;;;; +10099;LINEAR B MONOGRAM B135 MERI;Lo;0;L;;;;;N;;;;; +1009A;LINEAR B IDEOGRAM B140 BRONZE;Lo;0;L;;;;;N;;;;; +1009B;LINEAR B IDEOGRAM B141 GOLD;Lo;0;L;;;;;N;;;;; +1009C;LINEAR B IDEOGRAM B142;Lo;0;L;;;;;N;;;;; +1009D;LINEAR B IDEOGRAM B145 WOOL;Lo;0;L;;;;;N;;;;; +1009E;LINEAR B IDEOGRAM B146;Lo;0;L;;;;;N;;;;; +1009F;LINEAR B IDEOGRAM B150;Lo;0;L;;;;;N;;;;; +100A0;LINEAR B IDEOGRAM B151 HORN;Lo;0;L;;;;;N;;;;; +100A1;LINEAR B IDEOGRAM B152;Lo;0;L;;;;;N;;;;; +100A2;LINEAR B IDEOGRAM B153;Lo;0;L;;;;;N;;;;; +100A3;LINEAR B IDEOGRAM B154;Lo;0;L;;;;;N;;;;; +100A4;LINEAR B MONOGRAM B156 TURO2;Lo;0;L;;;;;N;;;;; +100A5;LINEAR B IDEOGRAM B157;Lo;0;L;;;;;N;;;;; +100A6;LINEAR B IDEOGRAM B158;Lo;0;L;;;;;N;;;;; +100A7;LINEAR B IDEOGRAM B159 CLOTH;Lo;0;L;;;;;N;;;;; +100A8;LINEAR B IDEOGRAM B160;Lo;0;L;;;;;N;;;;; +100A9;LINEAR B IDEOGRAM B161;Lo;0;L;;;;;N;;;;; +100AA;LINEAR B IDEOGRAM B162 GARMENT;Lo;0;L;;;;;N;;;;; +100AB;LINEAR B IDEOGRAM B163 ARMOUR;Lo;0;L;;;;;N;;;;; +100AC;LINEAR B IDEOGRAM B164;Lo;0;L;;;;;N;;;;; +100AD;LINEAR B IDEOGRAM B165;Lo;0;L;;;;;N;;;;; +100AE;LINEAR B IDEOGRAM B166;Lo;0;L;;;;;N;;;;; +100AF;LINEAR B IDEOGRAM B167;Lo;0;L;;;;;N;;;;; +100B0;LINEAR B IDEOGRAM B168;Lo;0;L;;;;;N;;;;; +100B1;LINEAR B IDEOGRAM B169;Lo;0;L;;;;;N;;;;; +100B2;LINEAR B IDEOGRAM B170;Lo;0;L;;;;;N;;;;; +100B3;LINEAR B IDEOGRAM B171;Lo;0;L;;;;;N;;;;; +100B4;LINEAR B IDEOGRAM B172;Lo;0;L;;;;;N;;;;; +100B5;LINEAR B IDEOGRAM B173 MONTH;Lo;0;L;;;;;N;;;;; +100B6;LINEAR B IDEOGRAM B174;Lo;0;L;;;;;N;;;;; +100B7;LINEAR B IDEOGRAM B176 TREE;Lo;0;L;;;;;N;;;;; +100B8;LINEAR B IDEOGRAM B177;Lo;0;L;;;;;N;;;;; +100B9;LINEAR B IDEOGRAM B178;Lo;0;L;;;;;N;;;;; +100BA;LINEAR B IDEOGRAM B179;Lo;0;L;;;;;N;;;;; +100BB;LINEAR B IDEOGRAM B180;Lo;0;L;;;;;N;;;;; +100BC;LINEAR B IDEOGRAM B181;Lo;0;L;;;;;N;;;;; +100BD;LINEAR B IDEOGRAM B182;Lo;0;L;;;;;N;;;;; +100BE;LINEAR B IDEOGRAM B183;Lo;0;L;;;;;N;;;;; +100BF;LINEAR B IDEOGRAM B184;Lo;0;L;;;;;N;;;;; +100C0;LINEAR B IDEOGRAM B185;Lo;0;L;;;;;N;;;;; +100C1;LINEAR B IDEOGRAM B189;Lo;0;L;;;;;N;;;;; +100C2;LINEAR B IDEOGRAM B190;Lo;0;L;;;;;N;;;;; +100C3;LINEAR B IDEOGRAM B191 HELMET;Lo;0;L;;;;;N;;;;; +100C4;LINEAR B IDEOGRAM B220 FOOTSTOOL;Lo;0;L;;;;;N;;;;; +100C5;LINEAR B IDEOGRAM B225 BATHTUB;Lo;0;L;;;;;N;;;;; +100C6;LINEAR B IDEOGRAM B230 SPEAR;Lo;0;L;;;;;N;;;;; +100C7;LINEAR B IDEOGRAM B231 ARROW;Lo;0;L;;;;;N;;;;; +100C8;LINEAR B IDEOGRAM B232;Lo;0;L;;;;;N;;;;; +100C9;LINEAR B IDEOGRAM B233 SWORD;Lo;0;L;;;;;N;;;;; +100CA;LINEAR B IDEOGRAM B234;Lo;0;L;;;;;N;;;;; +100CB;LINEAR B IDEOGRAM B236;Lo;0;L;;;;;N;;;;; +100CC;LINEAR B IDEOGRAM B240 WHEELED CHARIOT;Lo;0;L;;;;;N;;;;; +100CD;LINEAR B IDEOGRAM B241 CHARIOT;Lo;0;L;;;;;N;;;;; +100CE;LINEAR B IDEOGRAM B242 CHARIOT FRAME;Lo;0;L;;;;;N;;;;; +100CF;LINEAR B IDEOGRAM B243 WHEEL;Lo;0;L;;;;;N;;;;; +100D0;LINEAR B IDEOGRAM B245;Lo;0;L;;;;;N;;;;; +100D1;LINEAR B IDEOGRAM B246;Lo;0;L;;;;;N;;;;; +100D2;LINEAR B MONOGRAM B247 DIPTE;Lo;0;L;;;;;N;;;;; +100D3;LINEAR B IDEOGRAM B248;Lo;0;L;;;;;N;;;;; +100D4;LINEAR B IDEOGRAM B249;Lo;0;L;;;;;N;;;;; +100D5;LINEAR B IDEOGRAM B251;Lo;0;L;;;;;N;;;;; +100D6;LINEAR B IDEOGRAM B252;Lo;0;L;;;;;N;;;;; +100D7;LINEAR B IDEOGRAM B253;Lo;0;L;;;;;N;;;;; +100D8;LINEAR B IDEOGRAM B254 DART;Lo;0;L;;;;;N;;;;; +100D9;LINEAR B IDEOGRAM B255;Lo;0;L;;;;;N;;;;; +100DA;LINEAR B IDEOGRAM B256;Lo;0;L;;;;;N;;;;; +100DB;LINEAR B IDEOGRAM B257;Lo;0;L;;;;;N;;;;; +100DC;LINEAR B IDEOGRAM B258;Lo;0;L;;;;;N;;;;; +100DD;LINEAR B IDEOGRAM B259;Lo;0;L;;;;;N;;;;; +100DE;LINEAR B IDEOGRAM VESSEL B155;Lo;0;L;;;;;N;;;;; +100DF;LINEAR B IDEOGRAM VESSEL B200;Lo;0;L;;;;;N;;;;; +100E0;LINEAR B IDEOGRAM VESSEL B201;Lo;0;L;;;;;N;;;;; +100E1;LINEAR B IDEOGRAM VESSEL B202;Lo;0;L;;;;;N;;;;; +100E2;LINEAR B IDEOGRAM VESSEL B203;Lo;0;L;;;;;N;;;;; +100E3;LINEAR B IDEOGRAM VESSEL B204;Lo;0;L;;;;;N;;;;; +100E4;LINEAR B IDEOGRAM VESSEL B205;Lo;0;L;;;;;N;;;;; +100E5;LINEAR B IDEOGRAM VESSEL B206;Lo;0;L;;;;;N;;;;; +100E6;LINEAR B IDEOGRAM VESSEL B207;Lo;0;L;;;;;N;;;;; +100E7;LINEAR B IDEOGRAM VESSEL B208;Lo;0;L;;;;;N;;;;; +100E8;LINEAR B IDEOGRAM VESSEL B209;Lo;0;L;;;;;N;;;;; +100E9;LINEAR B IDEOGRAM VESSEL B210;Lo;0;L;;;;;N;;;;; +100EA;LINEAR B IDEOGRAM VESSEL B211;Lo;0;L;;;;;N;;;;; +100EB;LINEAR B IDEOGRAM VESSEL B212;Lo;0;L;;;;;N;;;;; +100EC;LINEAR B IDEOGRAM VESSEL B213;Lo;0;L;;;;;N;;;;; +100ED;LINEAR B IDEOGRAM VESSEL B214;Lo;0;L;;;;;N;;;;; +100EE;LINEAR B IDEOGRAM VESSEL B215;Lo;0;L;;;;;N;;;;; +100EF;LINEAR B IDEOGRAM VESSEL B216;Lo;0;L;;;;;N;;;;; +100F0;LINEAR B IDEOGRAM VESSEL B217;Lo;0;L;;;;;N;;;;; +100F1;LINEAR B IDEOGRAM VESSEL B218;Lo;0;L;;;;;N;;;;; +100F2;LINEAR B IDEOGRAM VESSEL B219;Lo;0;L;;;;;N;;;;; +100F3;LINEAR B IDEOGRAM VESSEL B221;Lo;0;L;;;;;N;;;;; +100F4;LINEAR B IDEOGRAM VESSEL B222;Lo;0;L;;;;;N;;;;; +100F5;LINEAR B IDEOGRAM VESSEL B226;Lo;0;L;;;;;N;;;;; +100F6;LINEAR B IDEOGRAM VESSEL B227;Lo;0;L;;;;;N;;;;; +100F7;LINEAR B IDEOGRAM VESSEL B228;Lo;0;L;;;;;N;;;;; +100F8;LINEAR B IDEOGRAM VESSEL B229;Lo;0;L;;;;;N;;;;; +100F9;LINEAR B IDEOGRAM VESSEL B250;Lo;0;L;;;;;N;;;;; +100FA;LINEAR B IDEOGRAM VESSEL B305;Lo;0;L;;;;;N;;;;; +10100;AEGEAN WORD SEPARATOR LINE;Po;0;L;;;;;N;;;;; +10101;AEGEAN WORD SEPARATOR DOT;Po;0;ON;;;;;N;;;;; +10102;AEGEAN CHECK MARK;Po;0;L;;;;;N;;;;; +10107;AEGEAN NUMBER ONE;No;0;L;;;;1;N;;;;; +10108;AEGEAN NUMBER TWO;No;0;L;;;;2;N;;;;; +10109;AEGEAN NUMBER THREE;No;0;L;;;;3;N;;;;; +1010A;AEGEAN NUMBER FOUR;No;0;L;;;;4;N;;;;; +1010B;AEGEAN NUMBER FIVE;No;0;L;;;;5;N;;;;; +1010C;AEGEAN NUMBER SIX;No;0;L;;;;6;N;;;;; +1010D;AEGEAN NUMBER SEVEN;No;0;L;;;;7;N;;;;; +1010E;AEGEAN NUMBER EIGHT;No;0;L;;;;8;N;;;;; +1010F;AEGEAN NUMBER NINE;No;0;L;;;;9;N;;;;; +10110;AEGEAN NUMBER TEN;No;0;L;;;;10;N;;;;; +10111;AEGEAN NUMBER TWENTY;No;0;L;;;;20;N;;;;; +10112;AEGEAN NUMBER THIRTY;No;0;L;;;;30;N;;;;; +10113;AEGEAN NUMBER FORTY;No;0;L;;;;40;N;;;;; +10114;AEGEAN NUMBER FIFTY;No;0;L;;;;50;N;;;;; +10115;AEGEAN NUMBER SIXTY;No;0;L;;;;60;N;;;;; +10116;AEGEAN NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +10117;AEGEAN NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +10118;AEGEAN NUMBER NINETY;No;0;L;;;;90;N;;;;; +10119;AEGEAN NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; +1011A;AEGEAN NUMBER TWO HUNDRED;No;0;L;;;;200;N;;;;; +1011B;AEGEAN NUMBER THREE HUNDRED;No;0;L;;;;300;N;;;;; +1011C;AEGEAN NUMBER FOUR HUNDRED;No;0;L;;;;400;N;;;;; +1011D;AEGEAN NUMBER FIVE HUNDRED;No;0;L;;;;500;N;;;;; +1011E;AEGEAN NUMBER SIX HUNDRED;No;0;L;;;;600;N;;;;; +1011F;AEGEAN NUMBER SEVEN HUNDRED;No;0;L;;;;700;N;;;;; +10120;AEGEAN NUMBER EIGHT HUNDRED;No;0;L;;;;800;N;;;;; +10121;AEGEAN NUMBER NINE HUNDRED;No;0;L;;;;900;N;;;;; +10122;AEGEAN NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; +10123;AEGEAN NUMBER TWO THOUSAND;No;0;L;;;;2000;N;;;;; +10124;AEGEAN NUMBER THREE THOUSAND;No;0;L;;;;3000;N;;;;; +10125;AEGEAN NUMBER FOUR THOUSAND;No;0;L;;;;4000;N;;;;; +10126;AEGEAN NUMBER FIVE THOUSAND;No;0;L;;;;5000;N;;;;; +10127;AEGEAN NUMBER SIX THOUSAND;No;0;L;;;;6000;N;;;;; +10128;AEGEAN NUMBER SEVEN THOUSAND;No;0;L;;;;7000;N;;;;; +10129;AEGEAN NUMBER EIGHT THOUSAND;No;0;L;;;;8000;N;;;;; +1012A;AEGEAN NUMBER NINE THOUSAND;No;0;L;;;;9000;N;;;;; +1012B;AEGEAN NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; +1012C;AEGEAN NUMBER TWENTY THOUSAND;No;0;L;;;;20000;N;;;;; +1012D;AEGEAN NUMBER THIRTY THOUSAND;No;0;L;;;;30000;N;;;;; +1012E;AEGEAN NUMBER FORTY THOUSAND;No;0;L;;;;40000;N;;;;; +1012F;AEGEAN NUMBER FIFTY THOUSAND;No;0;L;;;;50000;N;;;;; +10130;AEGEAN NUMBER SIXTY THOUSAND;No;0;L;;;;60000;N;;;;; +10131;AEGEAN NUMBER SEVENTY THOUSAND;No;0;L;;;;70000;N;;;;; +10132;AEGEAN NUMBER EIGHTY THOUSAND;No;0;L;;;;80000;N;;;;; +10133;AEGEAN NUMBER NINETY THOUSAND;No;0;L;;;;90000;N;;;;; +10137;AEGEAN WEIGHT BASE UNIT;So;0;L;;;;;N;;;;; +10138;AEGEAN WEIGHT FIRST SUBUNIT;So;0;L;;;;;N;;;;; +10139;AEGEAN WEIGHT SECOND SUBUNIT;So;0;L;;;;;N;;;;; +1013A;AEGEAN WEIGHT THIRD SUBUNIT;So;0;L;;;;;N;;;;; +1013B;AEGEAN WEIGHT FOURTH SUBUNIT;So;0;L;;;;;N;;;;; +1013C;AEGEAN DRY MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; +1013D;AEGEAN LIQUID MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; +1013E;AEGEAN MEASURE SECOND SUBUNIT;So;0;L;;;;;N;;;;; +1013F;AEGEAN MEASURE THIRD SUBUNIT;So;0;L;;;;;N;;;;; +10140;GREEK ACROPHONIC ATTIC ONE QUARTER;Nl;0;ON;;;;1/4;N;;;;; +10141;GREEK ACROPHONIC ATTIC ONE HALF;Nl;0;ON;;;;1/2;N;;;;; +10142;GREEK ACROPHONIC ATTIC ONE DRACHMA;Nl;0;ON;;;;1;N;;;;; +10143;GREEK ACROPHONIC ATTIC FIVE;Nl;0;ON;;;;5;N;;;;; +10144;GREEK ACROPHONIC ATTIC FIFTY;Nl;0;ON;;;;50;N;;;;; +10145;GREEK ACROPHONIC ATTIC FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +10146;GREEK ACROPHONIC ATTIC FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; +10147;GREEK ACROPHONIC ATTIC FIFTY THOUSAND;Nl;0;ON;;;;50000;N;;;;; +10148;GREEK ACROPHONIC ATTIC FIVE TALENTS;Nl;0;ON;;;;5;N;;;;; +10149;GREEK ACROPHONIC ATTIC TEN TALENTS;Nl;0;ON;;;;10;N;;;;; +1014A;GREEK ACROPHONIC ATTIC FIFTY TALENTS;Nl;0;ON;;;;50;N;;;;; +1014B;GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS;Nl;0;ON;;;;100;N;;;;; +1014C;GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS;Nl;0;ON;;;;500;N;;;;; +1014D;GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS;Nl;0;ON;;;;1000;N;;;;; +1014E;GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS;Nl;0;ON;;;;5000;N;;;;; +1014F;GREEK ACROPHONIC ATTIC FIVE STATERS;Nl;0;ON;;;;5;N;;;;; +10150;GREEK ACROPHONIC ATTIC TEN STATERS;Nl;0;ON;;;;10;N;;;;; +10151;GREEK ACROPHONIC ATTIC FIFTY STATERS;Nl;0;ON;;;;50;N;;;;; +10152;GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS;Nl;0;ON;;;;100;N;;;;; +10153;GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS;Nl;0;ON;;;;500;N;;;;; +10154;GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS;Nl;0;ON;;;;1000;N;;;;; +10155;GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS;Nl;0;ON;;;;10000;N;;;;; +10156;GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS;Nl;0;ON;;;;50000;N;;;;; +10157;GREEK ACROPHONIC ATTIC TEN MNAS;Nl;0;ON;;;;10;N;;;;; +10158;GREEK ACROPHONIC HERAEUM ONE PLETHRON;Nl;0;ON;;;;1;N;;;;; +10159;GREEK ACROPHONIC THESPIAN ONE;Nl;0;ON;;;;1;N;;;;; +1015A;GREEK ACROPHONIC HERMIONIAN ONE;Nl;0;ON;;;;1;N;;;;; +1015B;GREEK ACROPHONIC EPIDAUREAN TWO;Nl;0;ON;;;;2;N;;;;; +1015C;GREEK ACROPHONIC THESPIAN TWO;Nl;0;ON;;;;2;N;;;;; +1015D;GREEK ACROPHONIC CYRENAIC TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; +1015E;GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; +1015F;GREEK ACROPHONIC TROEZENIAN FIVE;Nl;0;ON;;;;5;N;;;;; +10160;GREEK ACROPHONIC TROEZENIAN TEN;Nl;0;ON;;;;10;N;;;;; +10161;GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM;Nl;0;ON;;;;10;N;;;;; +10162;GREEK ACROPHONIC HERMIONIAN TEN;Nl;0;ON;;;;10;N;;;;; +10163;GREEK ACROPHONIC MESSENIAN TEN;Nl;0;ON;;;;10;N;;;;; +10164;GREEK ACROPHONIC THESPIAN TEN;Nl;0;ON;;;;10;N;;;;; +10165;GREEK ACROPHONIC THESPIAN THIRTY;Nl;0;ON;;;;30;N;;;;; +10166;GREEK ACROPHONIC TROEZENIAN FIFTY;Nl;0;ON;;;;50;N;;;;; +10167;GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM;Nl;0;ON;;;;50;N;;;;; +10168;GREEK ACROPHONIC HERMIONIAN FIFTY;Nl;0;ON;;;;50;N;;;;; +10169;GREEK ACROPHONIC THESPIAN FIFTY;Nl;0;ON;;;;50;N;;;;; +1016A;GREEK ACROPHONIC THESPIAN ONE HUNDRED;Nl;0;ON;;;;100;N;;;;; +1016B;GREEK ACROPHONIC THESPIAN THREE HUNDRED;Nl;0;ON;;;;300;N;;;;; +1016C;GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +1016D;GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +1016E;GREEK ACROPHONIC THESPIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +1016F;GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +10170;GREEK ACROPHONIC NAXIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +10171;GREEK ACROPHONIC THESPIAN ONE THOUSAND;Nl;0;ON;;;;1000;N;;;;; +10172;GREEK ACROPHONIC THESPIAN FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; +10173;GREEK ACROPHONIC DELPHIC FIVE MNAS;Nl;0;ON;;;;5;N;;;;; +10174;GREEK ACROPHONIC STRATIAN FIFTY MNAS;Nl;0;ON;;;;50;N;;;;; +10175;GREEK ONE HALF SIGN;No;0;ON;;;;1/2;N;;;;; +10176;GREEK ONE HALF SIGN ALTERNATE FORM;No;0;ON;;;;1/2;N;;;;; +10177;GREEK TWO THIRDS SIGN;No;0;ON;;;;2/3;N;;;;; +10178;GREEK THREE QUARTERS SIGN;No;0;ON;;;;3/4;N;;;;; +10179;GREEK YEAR SIGN;So;0;ON;;;;;N;;;;; +1017A;GREEK TALENT SIGN;So;0;ON;;;;;N;;;;; +1017B;GREEK DRACHMA SIGN;So;0;ON;;;;;N;;;;; +1017C;GREEK OBOL SIGN;So;0;ON;;;;;N;;;;; +1017D;GREEK TWO OBOLS SIGN;So;0;ON;;;;;N;;;;; +1017E;GREEK THREE OBOLS SIGN;So;0;ON;;;;;N;;;;; +1017F;GREEK FOUR OBOLS SIGN;So;0;ON;;;;;N;;;;; +10180;GREEK FIVE OBOLS SIGN;So;0;ON;;;;;N;;;;; +10181;GREEK METRETES SIGN;So;0;ON;;;;;N;;;;; +10182;GREEK KYATHOS BASE SIGN;So;0;ON;;;;;N;;;;; +10183;GREEK LITRA SIGN;So;0;ON;;;;;N;;;;; +10184;GREEK OUNKIA SIGN;So;0;ON;;;;;N;;;;; +10185;GREEK XESTES SIGN;So;0;ON;;;;;N;;;;; +10186;GREEK ARTABE SIGN;So;0;ON;;;;;N;;;;; +10187;GREEK AROURA SIGN;So;0;ON;;;;;N;;;;; +10188;GREEK GRAMMA SIGN;So;0;ON;;;;;N;;;;; +10189;GREEK TRYBLION BASE SIGN;So;0;ON;;;;;N;;;;; +1018A;GREEK ZERO SIGN;No;0;ON;;;;0;N;;;;; +1018B;GREEK ONE QUARTER SIGN;No;0;ON;;;;1/4;N;;;;; +1018C;GREEK SINUSOID SIGN;So;0;ON;;;;;N;;;;; +1018D;GREEK INDICTION SIGN;So;0;L;;;;;N;;;;; +1018E;NOMISMA SIGN;So;0;L;;;;;N;;;;; +10190;ROMAN SEXTANS SIGN;So;0;ON;;;;;N;;;;; +10191;ROMAN UNCIA SIGN;So;0;ON;;;;;N;;;;; +10192;ROMAN SEMUNCIA SIGN;So;0;ON;;;;;N;;;;; +10193;ROMAN SEXTULA SIGN;So;0;ON;;;;;N;;;;; +10194;ROMAN DIMIDIA SEXTULA SIGN;So;0;ON;;;;;N;;;;; +10195;ROMAN SILIQUA SIGN;So;0;ON;;;;;N;;;;; +10196;ROMAN DENARIUS SIGN;So;0;ON;;;;;N;;;;; +10197;ROMAN QUINARIUS SIGN;So;0;ON;;;;;N;;;;; +10198;ROMAN SESTERTIUS SIGN;So;0;ON;;;;;N;;;;; +10199;ROMAN DUPONDIUS SIGN;So;0;ON;;;;;N;;;;; +1019A;ROMAN AS SIGN;So;0;ON;;;;;N;;;;; +1019B;ROMAN CENTURIAL SIGN;So;0;ON;;;;;N;;;;; +101A0;GREEK SYMBOL TAU RHO;So;0;ON;;;;;N;;;;; +101D0;PHAISTOS DISC SIGN PEDESTRIAN;So;0;L;;;;;N;;;;; +101D1;PHAISTOS DISC SIGN PLUMED HEAD;So;0;L;;;;;N;;;;; +101D2;PHAISTOS DISC SIGN TATTOOED HEAD;So;0;L;;;;;N;;;;; +101D3;PHAISTOS DISC SIGN CAPTIVE;So;0;L;;;;;N;;;;; +101D4;PHAISTOS DISC SIGN CHILD;So;0;L;;;;;N;;;;; +101D5;PHAISTOS DISC SIGN WOMAN;So;0;L;;;;;N;;;;; +101D6;PHAISTOS DISC SIGN HELMET;So;0;L;;;;;N;;;;; +101D7;PHAISTOS DISC SIGN GAUNTLET;So;0;L;;;;;N;;;;; +101D8;PHAISTOS DISC SIGN TIARA;So;0;L;;;;;N;;;;; +101D9;PHAISTOS DISC SIGN ARROW;So;0;L;;;;;N;;;;; +101DA;PHAISTOS DISC SIGN BOW;So;0;L;;;;;N;;;;; +101DB;PHAISTOS DISC SIGN SHIELD;So;0;L;;;;;N;;;;; +101DC;PHAISTOS DISC SIGN CLUB;So;0;L;;;;;N;;;;; +101DD;PHAISTOS DISC SIGN MANACLES;So;0;L;;;;;N;;;;; +101DE;PHAISTOS DISC SIGN MATTOCK;So;0;L;;;;;N;;;;; +101DF;PHAISTOS DISC SIGN SAW;So;0;L;;;;;N;;;;; +101E0;PHAISTOS DISC SIGN LID;So;0;L;;;;;N;;;;; +101E1;PHAISTOS DISC SIGN BOOMERANG;So;0;L;;;;;N;;;;; +101E2;PHAISTOS DISC SIGN CARPENTRY PLANE;So;0;L;;;;;N;;;;; +101E3;PHAISTOS DISC SIGN DOLIUM;So;0;L;;;;;N;;;;; +101E4;PHAISTOS DISC SIGN COMB;So;0;L;;;;;N;;;;; +101E5;PHAISTOS DISC SIGN SLING;So;0;L;;;;;N;;;;; +101E6;PHAISTOS DISC SIGN COLUMN;So;0;L;;;;;N;;;;; +101E7;PHAISTOS DISC SIGN BEEHIVE;So;0;L;;;;;N;;;;; +101E8;PHAISTOS DISC SIGN SHIP;So;0;L;;;;;N;;;;; +101E9;PHAISTOS DISC SIGN HORN;So;0;L;;;;;N;;;;; +101EA;PHAISTOS DISC SIGN HIDE;So;0;L;;;;;N;;;;; +101EB;PHAISTOS DISC SIGN BULLS LEG;So;0;L;;;;;N;;;;; +101EC;PHAISTOS DISC SIGN CAT;So;0;L;;;;;N;;;;; +101ED;PHAISTOS DISC SIGN RAM;So;0;L;;;;;N;;;;; +101EE;PHAISTOS DISC SIGN EAGLE;So;0;L;;;;;N;;;;; +101EF;PHAISTOS DISC SIGN DOVE;So;0;L;;;;;N;;;;; +101F0;PHAISTOS DISC SIGN TUNNY;So;0;L;;;;;N;;;;; +101F1;PHAISTOS DISC SIGN BEE;So;0;L;;;;;N;;;;; +101F2;PHAISTOS DISC SIGN PLANE TREE;So;0;L;;;;;N;;;;; +101F3;PHAISTOS DISC SIGN VINE;So;0;L;;;;;N;;;;; +101F4;PHAISTOS DISC SIGN PAPYRUS;So;0;L;;;;;N;;;;; +101F5;PHAISTOS DISC SIGN ROSETTE;So;0;L;;;;;N;;;;; +101F6;PHAISTOS DISC SIGN LILY;So;0;L;;;;;N;;;;; +101F7;PHAISTOS DISC SIGN OX BACK;So;0;L;;;;;N;;;;; +101F8;PHAISTOS DISC SIGN FLUTE;So;0;L;;;;;N;;;;; +101F9;PHAISTOS DISC SIGN GRATER;So;0;L;;;;;N;;;;; +101FA;PHAISTOS DISC SIGN STRAINER;So;0;L;;;;;N;;;;; +101FB;PHAISTOS DISC SIGN SMALL AXE;So;0;L;;;;;N;;;;; +101FC;PHAISTOS DISC SIGN WAVY BAND;So;0;L;;;;;N;;;;; +101FD;PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE;Mn;220;NSM;;;;;N;;;;; +10280;LYCIAN LETTER A;Lo;0;L;;;;;N;;;;; +10281;LYCIAN LETTER E;Lo;0;L;;;;;N;;;;; +10282;LYCIAN LETTER B;Lo;0;L;;;;;N;;;;; +10283;LYCIAN LETTER BH;Lo;0;L;;;;;N;;;;; +10284;LYCIAN LETTER G;Lo;0;L;;;;;N;;;;; +10285;LYCIAN LETTER D;Lo;0;L;;;;;N;;;;; +10286;LYCIAN LETTER I;Lo;0;L;;;;;N;;;;; +10287;LYCIAN LETTER W;Lo;0;L;;;;;N;;;;; +10288;LYCIAN LETTER Z;Lo;0;L;;;;;N;;;;; +10289;LYCIAN LETTER TH;Lo;0;L;;;;;N;;;;; +1028A;LYCIAN LETTER J;Lo;0;L;;;;;N;;;;; +1028B;LYCIAN LETTER K;Lo;0;L;;;;;N;;;;; +1028C;LYCIAN LETTER Q;Lo;0;L;;;;;N;;;;; +1028D;LYCIAN LETTER L;Lo;0;L;;;;;N;;;;; +1028E;LYCIAN LETTER M;Lo;0;L;;;;;N;;;;; +1028F;LYCIAN LETTER N;Lo;0;L;;;;;N;;;;; +10290;LYCIAN LETTER MM;Lo;0;L;;;;;N;;;;; +10291;LYCIAN LETTER NN;Lo;0;L;;;;;N;;;;; +10292;LYCIAN LETTER U;Lo;0;L;;;;;N;;;;; +10293;LYCIAN LETTER P;Lo;0;L;;;;;N;;;;; +10294;LYCIAN LETTER KK;Lo;0;L;;;;;N;;;;; +10295;LYCIAN LETTER R;Lo;0;L;;;;;N;;;;; +10296;LYCIAN LETTER S;Lo;0;L;;;;;N;;;;; +10297;LYCIAN LETTER T;Lo;0;L;;;;;N;;;;; +10298;LYCIAN LETTER TT;Lo;0;L;;;;;N;;;;; +10299;LYCIAN LETTER AN;Lo;0;L;;;;;N;;;;; +1029A;LYCIAN LETTER EN;Lo;0;L;;;;;N;;;;; +1029B;LYCIAN LETTER H;Lo;0;L;;;;;N;;;;; +1029C;LYCIAN LETTER X;Lo;0;L;;;;;N;;;;; +102A0;CARIAN LETTER A;Lo;0;L;;;;;N;;;;; +102A1;CARIAN LETTER P2;Lo;0;L;;;;;N;;;;; +102A2;CARIAN LETTER D;Lo;0;L;;;;;N;;;;; +102A3;CARIAN LETTER L;Lo;0;L;;;;;N;;;;; +102A4;CARIAN LETTER UUU;Lo;0;L;;;;;N;;;;; +102A5;CARIAN LETTER R;Lo;0;L;;;;;N;;;;; +102A6;CARIAN LETTER LD;Lo;0;L;;;;;N;;;;; +102A7;CARIAN LETTER A2;Lo;0;L;;;;;N;;;;; +102A8;CARIAN LETTER Q;Lo;0;L;;;;;N;;;;; +102A9;CARIAN LETTER B;Lo;0;L;;;;;N;;;;; +102AA;CARIAN LETTER M;Lo;0;L;;;;;N;;;;; +102AB;CARIAN LETTER O;Lo;0;L;;;;;N;;;;; +102AC;CARIAN LETTER D2;Lo;0;L;;;;;N;;;;; +102AD;CARIAN LETTER T;Lo;0;L;;;;;N;;;;; +102AE;CARIAN LETTER SH;Lo;0;L;;;;;N;;;;; +102AF;CARIAN LETTER SH2;Lo;0;L;;;;;N;;;;; +102B0;CARIAN LETTER S;Lo;0;L;;;;;N;;;;; +102B1;CARIAN LETTER C-18;Lo;0;L;;;;;N;;;;; +102B2;CARIAN LETTER U;Lo;0;L;;;;;N;;;;; +102B3;CARIAN LETTER NN;Lo;0;L;;;;;N;;;;; +102B4;CARIAN LETTER X;Lo;0;L;;;;;N;;;;; +102B5;CARIAN LETTER N;Lo;0;L;;;;;N;;;;; +102B6;CARIAN LETTER TT2;Lo;0;L;;;;;N;;;;; +102B7;CARIAN LETTER P;Lo;0;L;;;;;N;;;;; +102B8;CARIAN LETTER SS;Lo;0;L;;;;;N;;;;; +102B9;CARIAN LETTER I;Lo;0;L;;;;;N;;;;; +102BA;CARIAN LETTER E;Lo;0;L;;;;;N;;;;; +102BB;CARIAN LETTER UUUU;Lo;0;L;;;;;N;;;;; +102BC;CARIAN LETTER K;Lo;0;L;;;;;N;;;;; +102BD;CARIAN LETTER K2;Lo;0;L;;;;;N;;;;; +102BE;CARIAN LETTER ND;Lo;0;L;;;;;N;;;;; +102BF;CARIAN LETTER UU;Lo;0;L;;;;;N;;;;; +102C0;CARIAN LETTER G;Lo;0;L;;;;;N;;;;; +102C1;CARIAN LETTER G2;Lo;0;L;;;;;N;;;;; +102C2;CARIAN LETTER ST;Lo;0;L;;;;;N;;;;; +102C3;CARIAN LETTER ST2;Lo;0;L;;;;;N;;;;; +102C4;CARIAN LETTER NG;Lo;0;L;;;;;N;;;;; +102C5;CARIAN LETTER II;Lo;0;L;;;;;N;;;;; +102C6;CARIAN LETTER C-39;Lo;0;L;;;;;N;;;;; +102C7;CARIAN LETTER TT;Lo;0;L;;;;;N;;;;; +102C8;CARIAN LETTER UUU2;Lo;0;L;;;;;N;;;;; +102C9;CARIAN LETTER RR;Lo;0;L;;;;;N;;;;; +102CA;CARIAN LETTER MB;Lo;0;L;;;;;N;;;;; +102CB;CARIAN LETTER MB2;Lo;0;L;;;;;N;;;;; +102CC;CARIAN LETTER MB3;Lo;0;L;;;;;N;;;;; +102CD;CARIAN LETTER MB4;Lo;0;L;;;;;N;;;;; +102CE;CARIAN LETTER LD2;Lo;0;L;;;;;N;;;;; +102CF;CARIAN LETTER E2;Lo;0;L;;;;;N;;;;; +102D0;CARIAN LETTER UUU3;Lo;0;L;;;;;N;;;;; +102E0;COPTIC EPACT THOUSANDS MARK;Mn;220;NSM;;;;;N;;;;; +102E1;COPTIC EPACT DIGIT ONE;No;0;EN;;;;1;N;;;;; +102E2;COPTIC EPACT DIGIT TWO;No;0;EN;;;;2;N;;;;; +102E3;COPTIC EPACT DIGIT THREE;No;0;EN;;;;3;N;;;;; +102E4;COPTIC EPACT DIGIT FOUR;No;0;EN;;;;4;N;;;;; +102E5;COPTIC EPACT DIGIT FIVE;No;0;EN;;;;5;N;;;;; +102E6;COPTIC EPACT DIGIT SIX;No;0;EN;;;;6;N;;;;; +102E7;COPTIC EPACT DIGIT SEVEN;No;0;EN;;;;7;N;;;;; +102E8;COPTIC EPACT DIGIT EIGHT;No;0;EN;;;;8;N;;;;; +102E9;COPTIC EPACT DIGIT NINE;No;0;EN;;;;9;N;;;;; +102EA;COPTIC EPACT NUMBER TEN;No;0;EN;;;;10;N;;;;; +102EB;COPTIC EPACT NUMBER TWENTY;No;0;EN;;;;20;N;;;;; +102EC;COPTIC EPACT NUMBER THIRTY;No;0;EN;;;;30;N;;;;; +102ED;COPTIC EPACT NUMBER FORTY;No;0;EN;;;;40;N;;;;; +102EE;COPTIC EPACT NUMBER FIFTY;No;0;EN;;;;50;N;;;;; +102EF;COPTIC EPACT NUMBER SIXTY;No;0;EN;;;;60;N;;;;; +102F0;COPTIC EPACT NUMBER SEVENTY;No;0;EN;;;;70;N;;;;; +102F1;COPTIC EPACT NUMBER EIGHTY;No;0;EN;;;;80;N;;;;; +102F2;COPTIC EPACT NUMBER NINETY;No;0;EN;;;;90;N;;;;; +102F3;COPTIC EPACT NUMBER ONE HUNDRED;No;0;EN;;;;100;N;;;;; +102F4;COPTIC EPACT NUMBER TWO HUNDRED;No;0;EN;;;;200;N;;;;; +102F5;COPTIC EPACT NUMBER THREE HUNDRED;No;0;EN;;;;300;N;;;;; +102F6;COPTIC EPACT NUMBER FOUR HUNDRED;No;0;EN;;;;400;N;;;;; +102F7;COPTIC EPACT NUMBER FIVE HUNDRED;No;0;EN;;;;500;N;;;;; +102F8;COPTIC EPACT NUMBER SIX HUNDRED;No;0;EN;;;;600;N;;;;; +102F9;COPTIC EPACT NUMBER SEVEN HUNDRED;No;0;EN;;;;700;N;;;;; +102FA;COPTIC EPACT NUMBER EIGHT HUNDRED;No;0;EN;;;;800;N;;;;; +102FB;COPTIC EPACT NUMBER NINE HUNDRED;No;0;EN;;;;900;N;;;;; +10300;OLD ITALIC LETTER A;Lo;0;L;;;;;N;;;;; +10301;OLD ITALIC LETTER BE;Lo;0;L;;;;;N;;;;; +10302;OLD ITALIC LETTER KE;Lo;0;L;;;;;N;;;;; +10303;OLD ITALIC LETTER DE;Lo;0;L;;;;;N;;;;; +10304;OLD ITALIC LETTER E;Lo;0;L;;;;;N;;;;; +10305;OLD ITALIC LETTER VE;Lo;0;L;;;;;N;;;;; +10306;OLD ITALIC LETTER ZE;Lo;0;L;;;;;N;;;;; +10307;OLD ITALIC LETTER HE;Lo;0;L;;;;;N;;;;; +10308;OLD ITALIC LETTER THE;Lo;0;L;;;;;N;;;;; +10309;OLD ITALIC LETTER I;Lo;0;L;;;;;N;;;;; +1030A;OLD ITALIC LETTER KA;Lo;0;L;;;;;N;;;;; +1030B;OLD ITALIC LETTER EL;Lo;0;L;;;;;N;;;;; +1030C;OLD ITALIC LETTER EM;Lo;0;L;;;;;N;;;;; +1030D;OLD ITALIC LETTER EN;Lo;0;L;;;;;N;;;;; +1030E;OLD ITALIC LETTER ESH;Lo;0;L;;;;;N;;;;; +1030F;OLD ITALIC LETTER O;Lo;0;L;;;;;N;;;;; +10310;OLD ITALIC LETTER PE;Lo;0;L;;;;;N;;;;; +10311;OLD ITALIC LETTER SHE;Lo;0;L;;;;;N;;;;; +10312;OLD ITALIC LETTER KU;Lo;0;L;;;;;N;;;;; +10313;OLD ITALIC LETTER ER;Lo;0;L;;;;;N;;;;; +10314;OLD ITALIC LETTER ES;Lo;0;L;;;;;N;;;;; +10315;OLD ITALIC LETTER TE;Lo;0;L;;;;;N;;;;; +10316;OLD ITALIC LETTER U;Lo;0;L;;;;;N;;;;; +10317;OLD ITALIC LETTER EKS;Lo;0;L;;;;;N;;;;; +10318;OLD ITALIC LETTER PHE;Lo;0;L;;;;;N;;;;; +10319;OLD ITALIC LETTER KHE;Lo;0;L;;;;;N;;;;; +1031A;OLD ITALIC LETTER EF;Lo;0;L;;;;;N;;;;; +1031B;OLD ITALIC LETTER ERS;Lo;0;L;;;;;N;;;;; +1031C;OLD ITALIC LETTER CHE;Lo;0;L;;;;;N;;;;; +1031D;OLD ITALIC LETTER II;Lo;0;L;;;;;N;;;;; +1031E;OLD ITALIC LETTER UU;Lo;0;L;;;;;N;;;;; +1031F;OLD ITALIC LETTER ESS;Lo;0;L;;;;;N;;;;; +10320;OLD ITALIC NUMERAL ONE;No;0;L;;;;1;N;;;;; +10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; +10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; +10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; +1032D;OLD ITALIC LETTER YE;Lo;0;L;;;;;N;;;;; +1032E;OLD ITALIC LETTER NORTHERN TSE;Lo;0;L;;;;;N;;;;; +1032F;OLD ITALIC LETTER SOUTHERN TSE;Lo;0;L;;;;;N;;;;; +10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; +10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; +10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; +10333;GOTHIC LETTER DAGS;Lo;0;L;;;;;N;;;;; +10334;GOTHIC LETTER AIHVUS;Lo;0;L;;;;;N;;;;; +10335;GOTHIC LETTER QAIRTHRA;Lo;0;L;;;;;N;;;;; +10336;GOTHIC LETTER IUJA;Lo;0;L;;;;;N;;;;; +10337;GOTHIC LETTER HAGL;Lo;0;L;;;;;N;;;;; +10338;GOTHIC LETTER THIUTH;Lo;0;L;;;;;N;;;;; +10339;GOTHIC LETTER EIS;Lo;0;L;;;;;N;;;;; +1033A;GOTHIC LETTER KUSMA;Lo;0;L;;;;;N;;;;; +1033B;GOTHIC LETTER LAGUS;Lo;0;L;;;;;N;;;;; +1033C;GOTHIC LETTER MANNA;Lo;0;L;;;;;N;;;;; +1033D;GOTHIC LETTER NAUTHS;Lo;0;L;;;;;N;;;;; +1033E;GOTHIC LETTER JER;Lo;0;L;;;;;N;;;;; +1033F;GOTHIC LETTER URUS;Lo;0;L;;;;;N;;;;; +10340;GOTHIC LETTER PAIRTHRA;Lo;0;L;;;;;N;;;;; +10341;GOTHIC LETTER NINETY;Nl;0;L;;;;90;N;;;;; +10342;GOTHIC LETTER RAIDA;Lo;0;L;;;;;N;;;;; +10343;GOTHIC LETTER SAUIL;Lo;0;L;;;;;N;;;;; +10344;GOTHIC LETTER TEIWS;Lo;0;L;;;;;N;;;;; +10345;GOTHIC LETTER WINJA;Lo;0;L;;;;;N;;;;; +10346;GOTHIC LETTER FAIHU;Lo;0;L;;;;;N;;;;; +10347;GOTHIC LETTER IGGWS;Lo;0;L;;;;;N;;;;; +10348;GOTHIC LETTER HWAIR;Lo;0;L;;;;;N;;;;; +10349;GOTHIC LETTER OTHAL;Lo;0;L;;;;;N;;;;; +1034A;GOTHIC LETTER NINE HUNDRED;Nl;0;L;;;;900;N;;;;; +10350;OLD PERMIC LETTER AN;Lo;0;L;;;;;N;;;;; +10351;OLD PERMIC LETTER BUR;Lo;0;L;;;;;N;;;;; +10352;OLD PERMIC LETTER GAI;Lo;0;L;;;;;N;;;;; +10353;OLD PERMIC LETTER DOI;Lo;0;L;;;;;N;;;;; +10354;OLD PERMIC LETTER E;Lo;0;L;;;;;N;;;;; +10355;OLD PERMIC LETTER ZHOI;Lo;0;L;;;;;N;;;;; +10356;OLD PERMIC LETTER DZHOI;Lo;0;L;;;;;N;;;;; +10357;OLD PERMIC LETTER ZATA;Lo;0;L;;;;;N;;;;; +10358;OLD PERMIC LETTER DZITA;Lo;0;L;;;;;N;;;;; +10359;OLD PERMIC LETTER I;Lo;0;L;;;;;N;;;;; +1035A;OLD PERMIC LETTER KOKE;Lo;0;L;;;;;N;;;;; +1035B;OLD PERMIC LETTER LEI;Lo;0;L;;;;;N;;;;; +1035C;OLD PERMIC LETTER MENOE;Lo;0;L;;;;;N;;;;; +1035D;OLD PERMIC LETTER NENOE;Lo;0;L;;;;;N;;;;; +1035E;OLD PERMIC LETTER VOOI;Lo;0;L;;;;;N;;;;; +1035F;OLD PERMIC LETTER PEEI;Lo;0;L;;;;;N;;;;; +10360;OLD PERMIC LETTER REI;Lo;0;L;;;;;N;;;;; +10361;OLD PERMIC LETTER SII;Lo;0;L;;;;;N;;;;; +10362;OLD PERMIC LETTER TAI;Lo;0;L;;;;;N;;;;; +10363;OLD PERMIC LETTER U;Lo;0;L;;;;;N;;;;; +10364;OLD PERMIC LETTER CHERY;Lo;0;L;;;;;N;;;;; +10365;OLD PERMIC LETTER SHOOI;Lo;0;L;;;;;N;;;;; +10366;OLD PERMIC LETTER SHCHOOI;Lo;0;L;;;;;N;;;;; +10367;OLD PERMIC LETTER YRY;Lo;0;L;;;;;N;;;;; +10368;OLD PERMIC LETTER YERU;Lo;0;L;;;;;N;;;;; +10369;OLD PERMIC LETTER O;Lo;0;L;;;;;N;;;;; +1036A;OLD PERMIC LETTER OO;Lo;0;L;;;;;N;;;;; +1036B;OLD PERMIC LETTER EF;Lo;0;L;;;;;N;;;;; +1036C;OLD PERMIC LETTER HA;Lo;0;L;;;;;N;;;;; +1036D;OLD PERMIC LETTER TSIU;Lo;0;L;;;;;N;;;;; +1036E;OLD PERMIC LETTER VER;Lo;0;L;;;;;N;;;;; +1036F;OLD PERMIC LETTER YER;Lo;0;L;;;;;N;;;;; +10370;OLD PERMIC LETTER YERI;Lo;0;L;;;;;N;;;;; +10371;OLD PERMIC LETTER YAT;Lo;0;L;;;;;N;;;;; +10372;OLD PERMIC LETTER IE;Lo;0;L;;;;;N;;;;; +10373;OLD PERMIC LETTER YU;Lo;0;L;;;;;N;;;;; +10374;OLD PERMIC LETTER YA;Lo;0;L;;;;;N;;;;; +10375;OLD PERMIC LETTER IA;Lo;0;L;;;;;N;;;;; +10376;COMBINING OLD PERMIC LETTER AN;Mn;230;NSM;;;;;N;;;;; +10377;COMBINING OLD PERMIC LETTER DOI;Mn;230;NSM;;;;;N;;;;; +10378;COMBINING OLD PERMIC LETTER ZATA;Mn;230;NSM;;;;;N;;;;; +10379;COMBINING OLD PERMIC LETTER NENOE;Mn;230;NSM;;;;;N;;;;; +1037A;COMBINING OLD PERMIC LETTER SII;Mn;230;NSM;;;;;N;;;;; +10380;UGARITIC LETTER ALPA;Lo;0;L;;;;;N;;;;; +10381;UGARITIC LETTER BETA;Lo;0;L;;;;;N;;;;; +10382;UGARITIC LETTER GAMLA;Lo;0;L;;;;;N;;;;; +10383;UGARITIC LETTER KHA;Lo;0;L;;;;;N;;;;; +10384;UGARITIC LETTER DELTA;Lo;0;L;;;;;N;;;;; +10385;UGARITIC LETTER HO;Lo;0;L;;;;;N;;;;; +10386;UGARITIC LETTER WO;Lo;0;L;;;;;N;;;;; +10387;UGARITIC LETTER ZETA;Lo;0;L;;;;;N;;;;; +10388;UGARITIC LETTER HOTA;Lo;0;L;;;;;N;;;;; +10389;UGARITIC LETTER TET;Lo;0;L;;;;;N;;;;; +1038A;UGARITIC LETTER YOD;Lo;0;L;;;;;N;;;;; +1038B;UGARITIC LETTER KAF;Lo;0;L;;;;;N;;;;; +1038C;UGARITIC LETTER SHIN;Lo;0;L;;;;;N;;;;; +1038D;UGARITIC LETTER LAMDA;Lo;0;L;;;;;N;;;;; +1038E;UGARITIC LETTER MEM;Lo;0;L;;;;;N;;;;; +1038F;UGARITIC LETTER DHAL;Lo;0;L;;;;;N;;;;; +10390;UGARITIC LETTER NUN;Lo;0;L;;;;;N;;;;; +10391;UGARITIC LETTER ZU;Lo;0;L;;;;;N;;;;; +10392;UGARITIC LETTER SAMKA;Lo;0;L;;;;;N;;;;; +10393;UGARITIC LETTER AIN;Lo;0;L;;;;;N;;;;; +10394;UGARITIC LETTER PU;Lo;0;L;;;;;N;;;;; +10395;UGARITIC LETTER SADE;Lo;0;L;;;;;N;;;;; +10396;UGARITIC LETTER QOPA;Lo;0;L;;;;;N;;;;; +10397;UGARITIC LETTER RASHA;Lo;0;L;;;;;N;;;;; +10398;UGARITIC LETTER THANNA;Lo;0;L;;;;;N;;;;; +10399;UGARITIC LETTER GHAIN;Lo;0;L;;;;;N;;;;; +1039A;UGARITIC LETTER TO;Lo;0;L;;;;;N;;;;; +1039B;UGARITIC LETTER I;Lo;0;L;;;;;N;;;;; +1039C;UGARITIC LETTER U;Lo;0;L;;;;;N;;;;; +1039D;UGARITIC LETTER SSU;Lo;0;L;;;;;N;;;;; +1039F;UGARITIC WORD DIVIDER;Po;0;L;;;;;N;;;;; +103A0;OLD PERSIAN SIGN A;Lo;0;L;;;;;N;;;;; +103A1;OLD PERSIAN SIGN I;Lo;0;L;;;;;N;;;;; +103A2;OLD PERSIAN SIGN U;Lo;0;L;;;;;N;;;;; +103A3;OLD PERSIAN SIGN KA;Lo;0;L;;;;;N;;;;; +103A4;OLD PERSIAN SIGN KU;Lo;0;L;;;;;N;;;;; +103A5;OLD PERSIAN SIGN GA;Lo;0;L;;;;;N;;;;; +103A6;OLD PERSIAN SIGN GU;Lo;0;L;;;;;N;;;;; +103A7;OLD PERSIAN SIGN XA;Lo;0;L;;;;;N;;;;; +103A8;OLD PERSIAN SIGN CA;Lo;0;L;;;;;N;;;;; +103A9;OLD PERSIAN SIGN JA;Lo;0;L;;;;;N;;;;; +103AA;OLD PERSIAN SIGN JI;Lo;0;L;;;;;N;;;;; +103AB;OLD PERSIAN SIGN TA;Lo;0;L;;;;;N;;;;; +103AC;OLD PERSIAN SIGN TU;Lo;0;L;;;;;N;;;;; +103AD;OLD PERSIAN SIGN DA;Lo;0;L;;;;;N;;;;; +103AE;OLD PERSIAN SIGN DI;Lo;0;L;;;;;N;;;;; +103AF;OLD PERSIAN SIGN DU;Lo;0;L;;;;;N;;;;; +103B0;OLD PERSIAN SIGN THA;Lo;0;L;;;;;N;;;;; +103B1;OLD PERSIAN SIGN PA;Lo;0;L;;;;;N;;;;; +103B2;OLD PERSIAN SIGN BA;Lo;0;L;;;;;N;;;;; +103B3;OLD PERSIAN SIGN FA;Lo;0;L;;;;;N;;;;; +103B4;OLD PERSIAN SIGN NA;Lo;0;L;;;;;N;;;;; +103B5;OLD PERSIAN SIGN NU;Lo;0;L;;;;;N;;;;; +103B6;OLD PERSIAN SIGN MA;Lo;0;L;;;;;N;;;;; +103B7;OLD PERSIAN SIGN MI;Lo;0;L;;;;;N;;;;; +103B8;OLD PERSIAN SIGN MU;Lo;0;L;;;;;N;;;;; +103B9;OLD PERSIAN SIGN YA;Lo;0;L;;;;;N;;;;; +103BA;OLD PERSIAN SIGN VA;Lo;0;L;;;;;N;;;;; +103BB;OLD PERSIAN SIGN VI;Lo;0;L;;;;;N;;;;; +103BC;OLD PERSIAN SIGN RA;Lo;0;L;;;;;N;;;;; +103BD;OLD PERSIAN SIGN RU;Lo;0;L;;;;;N;;;;; +103BE;OLD PERSIAN SIGN LA;Lo;0;L;;;;;N;;;;; +103BF;OLD PERSIAN SIGN SA;Lo;0;L;;;;;N;;;;; +103C0;OLD PERSIAN SIGN ZA;Lo;0;L;;;;;N;;;;; +103C1;OLD PERSIAN SIGN SHA;Lo;0;L;;;;;N;;;;; +103C2;OLD PERSIAN SIGN SSA;Lo;0;L;;;;;N;;;;; +103C3;OLD PERSIAN SIGN HA;Lo;0;L;;;;;N;;;;; +103C8;OLD PERSIAN SIGN AURAMAZDAA;Lo;0;L;;;;;N;;;;; +103C9;OLD PERSIAN SIGN AURAMAZDAA-2;Lo;0;L;;;;;N;;;;; +103CA;OLD PERSIAN SIGN AURAMAZDAAHA;Lo;0;L;;;;;N;;;;; +103CB;OLD PERSIAN SIGN XSHAAYATHIYA;Lo;0;L;;;;;N;;;;; +103CC;OLD PERSIAN SIGN DAHYAAUSH;Lo;0;L;;;;;N;;;;; +103CD;OLD PERSIAN SIGN DAHYAAUSH-2;Lo;0;L;;;;;N;;;;; +103CE;OLD PERSIAN SIGN BAGA;Lo;0;L;;;;;N;;;;; +103CF;OLD PERSIAN SIGN BUUMISH;Lo;0;L;;;;;N;;;;; +103D0;OLD PERSIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; +103D1;OLD PERSIAN NUMBER ONE;Nl;0;L;;;;1;N;;;;; +103D2;OLD PERSIAN NUMBER TWO;Nl;0;L;;;;2;N;;;;; +103D3;OLD PERSIAN NUMBER TEN;Nl;0;L;;;;10;N;;;;; +103D4;OLD PERSIAN NUMBER TWENTY;Nl;0;L;;;;20;N;;;;; +103D5;OLD PERSIAN NUMBER HUNDRED;Nl;0;L;;;;100;N;;;;; +10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428; +10401;DESERET CAPITAL LETTER LONG E;Lu;0;L;;;;;N;;;;10429; +10402;DESERET CAPITAL LETTER LONG A;Lu;0;L;;;;;N;;;;1042A; +10403;DESERET CAPITAL LETTER LONG AH;Lu;0;L;;;;;N;;;;1042B; +10404;DESERET CAPITAL LETTER LONG O;Lu;0;L;;;;;N;;;;1042C; +10405;DESERET CAPITAL LETTER LONG OO;Lu;0;L;;;;;N;;;;1042D; +10406;DESERET CAPITAL LETTER SHORT I;Lu;0;L;;;;;N;;;;1042E; +10407;DESERET CAPITAL LETTER SHORT E;Lu;0;L;;;;;N;;;;1042F; +10408;DESERET CAPITAL LETTER SHORT A;Lu;0;L;;;;;N;;;;10430; +10409;DESERET CAPITAL LETTER SHORT AH;Lu;0;L;;;;;N;;;;10431; +1040A;DESERET CAPITAL LETTER SHORT O;Lu;0;L;;;;;N;;;;10432; +1040B;DESERET CAPITAL LETTER SHORT OO;Lu;0;L;;;;;N;;;;10433; +1040C;DESERET CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;10434; +1040D;DESERET CAPITAL LETTER OW;Lu;0;L;;;;;N;;;;10435; +1040E;DESERET CAPITAL LETTER WU;Lu;0;L;;;;;N;;;;10436; +1040F;DESERET CAPITAL LETTER YEE;Lu;0;L;;;;;N;;;;10437; +10410;DESERET CAPITAL LETTER H;Lu;0;L;;;;;N;;;;10438; +10411;DESERET CAPITAL LETTER PEE;Lu;0;L;;;;;N;;;;10439; +10412;DESERET CAPITAL LETTER BEE;Lu;0;L;;;;;N;;;;1043A; +10413;DESERET CAPITAL LETTER TEE;Lu;0;L;;;;;N;;;;1043B; +10414;DESERET CAPITAL LETTER DEE;Lu;0;L;;;;;N;;;;1043C; +10415;DESERET CAPITAL LETTER CHEE;Lu;0;L;;;;;N;;;;1043D; +10416;DESERET CAPITAL LETTER JEE;Lu;0;L;;;;;N;;;;1043E; +10417;DESERET CAPITAL LETTER KAY;Lu;0;L;;;;;N;;;;1043F; +10418;DESERET CAPITAL LETTER GAY;Lu;0;L;;;;;N;;;;10440; +10419;DESERET CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;10441; +1041A;DESERET CAPITAL LETTER VEE;Lu;0;L;;;;;N;;;;10442; +1041B;DESERET CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;10443; +1041C;DESERET CAPITAL LETTER THEE;Lu;0;L;;;;;N;;;;10444; +1041D;DESERET CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;10445; +1041E;DESERET CAPITAL LETTER ZEE;Lu;0;L;;;;;N;;;;10446; +1041F;DESERET CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;10447; +10420;DESERET CAPITAL LETTER ZHEE;Lu;0;L;;;;;N;;;;10448; +10421;DESERET CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;10449; +10422;DESERET CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;1044A; +10423;DESERET CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;1044B; +10424;DESERET CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;1044C; +10425;DESERET CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;1044D; +10426;DESERET CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;1044E; +10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F; +10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400 +10429;DESERET SMALL LETTER LONG E;Ll;0;L;;;;;N;;;10401;;10401 +1042A;DESERET SMALL LETTER LONG A;Ll;0;L;;;;;N;;;10402;;10402 +1042B;DESERET SMALL LETTER LONG AH;Ll;0;L;;;;;N;;;10403;;10403 +1042C;DESERET SMALL LETTER LONG O;Ll;0;L;;;;;N;;;10404;;10404 +1042D;DESERET SMALL LETTER LONG OO;Ll;0;L;;;;;N;;;10405;;10405 +1042E;DESERET SMALL LETTER SHORT I;Ll;0;L;;;;;N;;;10406;;10406 +1042F;DESERET SMALL LETTER SHORT E;Ll;0;L;;;;;N;;;10407;;10407 +10430;DESERET SMALL LETTER SHORT A;Ll;0;L;;;;;N;;;10408;;10408 +10431;DESERET SMALL LETTER SHORT AH;Ll;0;L;;;;;N;;;10409;;10409 +10432;DESERET SMALL LETTER SHORT O;Ll;0;L;;;;;N;;;1040A;;1040A +10433;DESERET SMALL LETTER SHORT OO;Ll;0;L;;;;;N;;;1040B;;1040B +10434;DESERET SMALL LETTER AY;Ll;0;L;;;;;N;;;1040C;;1040C +10435;DESERET SMALL LETTER OW;Ll;0;L;;;;;N;;;1040D;;1040D +10436;DESERET SMALL LETTER WU;Ll;0;L;;;;;N;;;1040E;;1040E +10437;DESERET SMALL LETTER YEE;Ll;0;L;;;;;N;;;1040F;;1040F +10438;DESERET SMALL LETTER H;Ll;0;L;;;;;N;;;10410;;10410 +10439;DESERET SMALL LETTER PEE;Ll;0;L;;;;;N;;;10411;;10411 +1043A;DESERET SMALL LETTER BEE;Ll;0;L;;;;;N;;;10412;;10412 +1043B;DESERET SMALL LETTER TEE;Ll;0;L;;;;;N;;;10413;;10413 +1043C;DESERET SMALL LETTER DEE;Ll;0;L;;;;;N;;;10414;;10414 +1043D;DESERET SMALL LETTER CHEE;Ll;0;L;;;;;N;;;10415;;10415 +1043E;DESERET SMALL LETTER JEE;Ll;0;L;;;;;N;;;10416;;10416 +1043F;DESERET SMALL LETTER KAY;Ll;0;L;;;;;N;;;10417;;10417 +10440;DESERET SMALL LETTER GAY;Ll;0;L;;;;;N;;;10418;;10418 +10441;DESERET SMALL LETTER EF;Ll;0;L;;;;;N;;;10419;;10419 +10442;DESERET SMALL LETTER VEE;Ll;0;L;;;;;N;;;1041A;;1041A +10443;DESERET SMALL LETTER ETH;Ll;0;L;;;;;N;;;1041B;;1041B +10444;DESERET SMALL LETTER THEE;Ll;0;L;;;;;N;;;1041C;;1041C +10445;DESERET SMALL LETTER ES;Ll;0;L;;;;;N;;;1041D;;1041D +10446;DESERET SMALL LETTER ZEE;Ll;0;L;;;;;N;;;1041E;;1041E +10447;DESERET SMALL LETTER ESH;Ll;0;L;;;;;N;;;1041F;;1041F +10448;DESERET SMALL LETTER ZHEE;Ll;0;L;;;;;N;;;10420;;10420 +10449;DESERET SMALL LETTER ER;Ll;0;L;;;;;N;;;10421;;10421 +1044A;DESERET SMALL LETTER EL;Ll;0;L;;;;;N;;;10422;;10422 +1044B;DESERET SMALL LETTER EM;Ll;0;L;;;;;N;;;10423;;10423 +1044C;DESERET SMALL LETTER EN;Ll;0;L;;;;;N;;;10424;;10424 +1044D;DESERET SMALL LETTER ENG;Ll;0;L;;;;;N;;;10425;;10425 +1044E;DESERET SMALL LETTER OI;Ll;0;L;;;;;N;;;10426;;10426 +1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427 +10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;; +10451;SHAVIAN LETTER TOT;Lo;0;L;;;;;N;;;;; +10452;SHAVIAN LETTER KICK;Lo;0;L;;;;;N;;;;; +10453;SHAVIAN LETTER FEE;Lo;0;L;;;;;N;;;;; +10454;SHAVIAN LETTER THIGH;Lo;0;L;;;;;N;;;;; +10455;SHAVIAN LETTER SO;Lo;0;L;;;;;N;;;;; +10456;SHAVIAN LETTER SURE;Lo;0;L;;;;;N;;;;; +10457;SHAVIAN LETTER CHURCH;Lo;0;L;;;;;N;;;;; +10458;SHAVIAN LETTER YEA;Lo;0;L;;;;;N;;;;; +10459;SHAVIAN LETTER HUNG;Lo;0;L;;;;;N;;;;; +1045A;SHAVIAN LETTER BIB;Lo;0;L;;;;;N;;;;; +1045B;SHAVIAN LETTER DEAD;Lo;0;L;;;;;N;;;;; +1045C;SHAVIAN LETTER GAG;Lo;0;L;;;;;N;;;;; +1045D;SHAVIAN LETTER VOW;Lo;0;L;;;;;N;;;;; +1045E;SHAVIAN LETTER THEY;Lo;0;L;;;;;N;;;;; +1045F;SHAVIAN LETTER ZOO;Lo;0;L;;;;;N;;;;; +10460;SHAVIAN LETTER MEASURE;Lo;0;L;;;;;N;;;;; +10461;SHAVIAN LETTER JUDGE;Lo;0;L;;;;;N;;;;; +10462;SHAVIAN LETTER WOE;Lo;0;L;;;;;N;;;;; +10463;SHAVIAN LETTER HA-HA;Lo;0;L;;;;;N;;;;; +10464;SHAVIAN LETTER LOLL;Lo;0;L;;;;;N;;;;; +10465;SHAVIAN LETTER MIME;Lo;0;L;;;;;N;;;;; +10466;SHAVIAN LETTER IF;Lo;0;L;;;;;N;;;;; +10467;SHAVIAN LETTER EGG;Lo;0;L;;;;;N;;;;; +10468;SHAVIAN LETTER ASH;Lo;0;L;;;;;N;;;;; +10469;SHAVIAN LETTER ADO;Lo;0;L;;;;;N;;;;; +1046A;SHAVIAN LETTER ON;Lo;0;L;;;;;N;;;;; +1046B;SHAVIAN LETTER WOOL;Lo;0;L;;;;;N;;;;; +1046C;SHAVIAN LETTER OUT;Lo;0;L;;;;;N;;;;; +1046D;SHAVIAN LETTER AH;Lo;0;L;;;;;N;;;;; +1046E;SHAVIAN LETTER ROAR;Lo;0;L;;;;;N;;;;; +1046F;SHAVIAN LETTER NUN;Lo;0;L;;;;;N;;;;; +10470;SHAVIAN LETTER EAT;Lo;0;L;;;;;N;;;;; +10471;SHAVIAN LETTER AGE;Lo;0;L;;;;;N;;;;; +10472;SHAVIAN LETTER ICE;Lo;0;L;;;;;N;;;;; +10473;SHAVIAN LETTER UP;Lo;0;L;;;;;N;;;;; +10474;SHAVIAN LETTER OAK;Lo;0;L;;;;;N;;;;; +10475;SHAVIAN LETTER OOZE;Lo;0;L;;;;;N;;;;; +10476;SHAVIAN LETTER OIL;Lo;0;L;;;;;N;;;;; +10477;SHAVIAN LETTER AWE;Lo;0;L;;;;;N;;;;; +10478;SHAVIAN LETTER ARE;Lo;0;L;;;;;N;;;;; +10479;SHAVIAN LETTER OR;Lo;0;L;;;;;N;;;;; +1047A;SHAVIAN LETTER AIR;Lo;0;L;;;;;N;;;;; +1047B;SHAVIAN LETTER ERR;Lo;0;L;;;;;N;;;;; +1047C;SHAVIAN LETTER ARRAY;Lo;0;L;;;;;N;;;;; +1047D;SHAVIAN LETTER EAR;Lo;0;L;;;;;N;;;;; +1047E;SHAVIAN LETTER IAN;Lo;0;L;;;;;N;;;;; +1047F;SHAVIAN LETTER YEW;Lo;0;L;;;;;N;;;;; +10480;OSMANYA LETTER ALEF;Lo;0;L;;;;;N;;;;; +10481;OSMANYA LETTER BA;Lo;0;L;;;;;N;;;;; +10482;OSMANYA LETTER TA;Lo;0;L;;;;;N;;;;; +10483;OSMANYA LETTER JA;Lo;0;L;;;;;N;;;;; +10484;OSMANYA LETTER XA;Lo;0;L;;;;;N;;;;; +10485;OSMANYA LETTER KHA;Lo;0;L;;;;;N;;;;; +10486;OSMANYA LETTER DEEL;Lo;0;L;;;;;N;;;;; +10487;OSMANYA LETTER RA;Lo;0;L;;;;;N;;;;; +10488;OSMANYA LETTER SA;Lo;0;L;;;;;N;;;;; +10489;OSMANYA LETTER SHIIN;Lo;0;L;;;;;N;;;;; +1048A;OSMANYA LETTER DHA;Lo;0;L;;;;;N;;;;; +1048B;OSMANYA LETTER CAYN;Lo;0;L;;;;;N;;;;; +1048C;OSMANYA LETTER GA;Lo;0;L;;;;;N;;;;; +1048D;OSMANYA LETTER FA;Lo;0;L;;;;;N;;;;; +1048E;OSMANYA LETTER QAAF;Lo;0;L;;;;;N;;;;; +1048F;OSMANYA LETTER KAAF;Lo;0;L;;;;;N;;;;; +10490;OSMANYA LETTER LAAN;Lo;0;L;;;;;N;;;;; +10491;OSMANYA LETTER MIIN;Lo;0;L;;;;;N;;;;; +10492;OSMANYA LETTER NUUN;Lo;0;L;;;;;N;;;;; +10493;OSMANYA LETTER WAW;Lo;0;L;;;;;N;;;;; +10494;OSMANYA LETTER HA;Lo;0;L;;;;;N;;;;; +10495;OSMANYA LETTER YA;Lo;0;L;;;;;N;;;;; +10496;OSMANYA LETTER A;Lo;0;L;;;;;N;;;;; +10497;OSMANYA LETTER E;Lo;0;L;;;;;N;;;;; +10498;OSMANYA LETTER I;Lo;0;L;;;;;N;;;;; +10499;OSMANYA LETTER O;Lo;0;L;;;;;N;;;;; +1049A;OSMANYA LETTER U;Lo;0;L;;;;;N;;;;; +1049B;OSMANYA LETTER AA;Lo;0;L;;;;;N;;;;; +1049C;OSMANYA LETTER EE;Lo;0;L;;;;;N;;;;; +1049D;OSMANYA LETTER OO;Lo;0;L;;;;;N;;;;; +104A0;OSMANYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +104A1;OSMANYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +104A2;OSMANYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +104A3;OSMANYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +104A4;OSMANYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +104A5;OSMANYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +104A6;OSMANYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +104A7;OSMANYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +104A8;OSMANYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +104A9;OSMANYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +104B0;OSAGE CAPITAL LETTER A;Lu;0;L;;;;;N;;;;104D8; +104B1;OSAGE CAPITAL LETTER AI;Lu;0;L;;;;;N;;;;104D9; +104B2;OSAGE CAPITAL LETTER AIN;Lu;0;L;;;;;N;;;;104DA; +104B3;OSAGE CAPITAL LETTER AH;Lu;0;L;;;;;N;;;;104DB; +104B4;OSAGE CAPITAL LETTER BRA;Lu;0;L;;;;;N;;;;104DC; +104B5;OSAGE CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;104DD; +104B6;OSAGE CAPITAL LETTER EHCHA;Lu;0;L;;;;;N;;;;104DE; +104B7;OSAGE CAPITAL LETTER E;Lu;0;L;;;;;N;;;;104DF; +104B8;OSAGE CAPITAL LETTER EIN;Lu;0;L;;;;;N;;;;104E0; +104B9;OSAGE CAPITAL LETTER HA;Lu;0;L;;;;;N;;;;104E1; +104BA;OSAGE CAPITAL LETTER HYA;Lu;0;L;;;;;N;;;;104E2; +104BB;OSAGE CAPITAL LETTER I;Lu;0;L;;;;;N;;;;104E3; +104BC;OSAGE CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;104E4; +104BD;OSAGE CAPITAL LETTER EHKA;Lu;0;L;;;;;N;;;;104E5; +104BE;OSAGE CAPITAL LETTER KYA;Lu;0;L;;;;;N;;;;104E6; +104BF;OSAGE CAPITAL LETTER LA;Lu;0;L;;;;;N;;;;104E7; +104C0;OSAGE CAPITAL LETTER MA;Lu;0;L;;;;;N;;;;104E8; +104C1;OSAGE CAPITAL LETTER NA;Lu;0;L;;;;;N;;;;104E9; +104C2;OSAGE CAPITAL LETTER O;Lu;0;L;;;;;N;;;;104EA; +104C3;OSAGE CAPITAL LETTER OIN;Lu;0;L;;;;;N;;;;104EB; +104C4;OSAGE CAPITAL LETTER PA;Lu;0;L;;;;;N;;;;104EC; +104C5;OSAGE CAPITAL LETTER EHPA;Lu;0;L;;;;;N;;;;104ED; +104C6;OSAGE CAPITAL LETTER SA;Lu;0;L;;;;;N;;;;104EE; +104C7;OSAGE CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;104EF; +104C8;OSAGE CAPITAL LETTER TA;Lu;0;L;;;;;N;;;;104F0; +104C9;OSAGE CAPITAL LETTER EHTA;Lu;0;L;;;;;N;;;;104F1; +104CA;OSAGE CAPITAL LETTER TSA;Lu;0;L;;;;;N;;;;104F2; +104CB;OSAGE CAPITAL LETTER EHTSA;Lu;0;L;;;;;N;;;;104F3; +104CC;OSAGE CAPITAL LETTER TSHA;Lu;0;L;;;;;N;;;;104F4; +104CD;OSAGE CAPITAL LETTER DHA;Lu;0;L;;;;;N;;;;104F5; +104CE;OSAGE CAPITAL LETTER U;Lu;0;L;;;;;N;;;;104F6; +104CF;OSAGE CAPITAL LETTER WA;Lu;0;L;;;;;N;;;;104F7; +104D0;OSAGE CAPITAL LETTER KHA;Lu;0;L;;;;;N;;;;104F8; +104D1;OSAGE CAPITAL LETTER GHA;Lu;0;L;;;;;N;;;;104F9; +104D2;OSAGE CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;104FA; +104D3;OSAGE CAPITAL LETTER ZHA;Lu;0;L;;;;;N;;;;104FB; +104D8;OSAGE SMALL LETTER A;Ll;0;L;;;;;N;;;104B0;;104B0 +104D9;OSAGE SMALL LETTER AI;Ll;0;L;;;;;N;;;104B1;;104B1 +104DA;OSAGE SMALL LETTER AIN;Ll;0;L;;;;;N;;;104B2;;104B2 +104DB;OSAGE SMALL LETTER AH;Ll;0;L;;;;;N;;;104B3;;104B3 +104DC;OSAGE SMALL LETTER BRA;Ll;0;L;;;;;N;;;104B4;;104B4 +104DD;OSAGE SMALL LETTER CHA;Ll;0;L;;;;;N;;;104B5;;104B5 +104DE;OSAGE SMALL LETTER EHCHA;Ll;0;L;;;;;N;;;104B6;;104B6 +104DF;OSAGE SMALL LETTER E;Ll;0;L;;;;;N;;;104B7;;104B7 +104E0;OSAGE SMALL LETTER EIN;Ll;0;L;;;;;N;;;104B8;;104B8 +104E1;OSAGE SMALL LETTER HA;Ll;0;L;;;;;N;;;104B9;;104B9 +104E2;OSAGE SMALL LETTER HYA;Ll;0;L;;;;;N;;;104BA;;104BA +104E3;OSAGE SMALL LETTER I;Ll;0;L;;;;;N;;;104BB;;104BB +104E4;OSAGE SMALL LETTER KA;Ll;0;L;;;;;N;;;104BC;;104BC +104E5;OSAGE SMALL LETTER EHKA;Ll;0;L;;;;;N;;;104BD;;104BD +104E6;OSAGE SMALL LETTER KYA;Ll;0;L;;;;;N;;;104BE;;104BE +104E7;OSAGE SMALL LETTER LA;Ll;0;L;;;;;N;;;104BF;;104BF +104E8;OSAGE SMALL LETTER MA;Ll;0;L;;;;;N;;;104C0;;104C0 +104E9;OSAGE SMALL LETTER NA;Ll;0;L;;;;;N;;;104C1;;104C1 +104EA;OSAGE SMALL LETTER O;Ll;0;L;;;;;N;;;104C2;;104C2 +104EB;OSAGE SMALL LETTER OIN;Ll;0;L;;;;;N;;;104C3;;104C3 +104EC;OSAGE SMALL LETTER PA;Ll;0;L;;;;;N;;;104C4;;104C4 +104ED;OSAGE SMALL LETTER EHPA;Ll;0;L;;;;;N;;;104C5;;104C5 +104EE;OSAGE SMALL LETTER SA;Ll;0;L;;;;;N;;;104C6;;104C6 +104EF;OSAGE SMALL LETTER SHA;Ll;0;L;;;;;N;;;104C7;;104C7 +104F0;OSAGE SMALL LETTER TA;Ll;0;L;;;;;N;;;104C8;;104C8 +104F1;OSAGE SMALL LETTER EHTA;Ll;0;L;;;;;N;;;104C9;;104C9 +104F2;OSAGE SMALL LETTER TSA;Ll;0;L;;;;;N;;;104CA;;104CA +104F3;OSAGE SMALL LETTER EHTSA;Ll;0;L;;;;;N;;;104CB;;104CB +104F4;OSAGE SMALL LETTER TSHA;Ll;0;L;;;;;N;;;104CC;;104CC +104F5;OSAGE SMALL LETTER DHA;Ll;0;L;;;;;N;;;104CD;;104CD +104F6;OSAGE SMALL LETTER U;Ll;0;L;;;;;N;;;104CE;;104CE +104F7;OSAGE SMALL LETTER WA;Ll;0;L;;;;;N;;;104CF;;104CF +104F8;OSAGE SMALL LETTER KHA;Ll;0;L;;;;;N;;;104D0;;104D0 +104F9;OSAGE SMALL LETTER GHA;Ll;0;L;;;;;N;;;104D1;;104D1 +104FA;OSAGE SMALL LETTER ZA;Ll;0;L;;;;;N;;;104D2;;104D2 +104FB;OSAGE SMALL LETTER ZHA;Ll;0;L;;;;;N;;;104D3;;104D3 +10500;ELBASAN LETTER A;Lo;0;L;;;;;N;;;;; +10501;ELBASAN LETTER BE;Lo;0;L;;;;;N;;;;; +10502;ELBASAN LETTER CE;Lo;0;L;;;;;N;;;;; +10503;ELBASAN LETTER CHE;Lo;0;L;;;;;N;;;;; +10504;ELBASAN LETTER DE;Lo;0;L;;;;;N;;;;; +10505;ELBASAN LETTER NDE;Lo;0;L;;;;;N;;;;; +10506;ELBASAN LETTER DHE;Lo;0;L;;;;;N;;;;; +10507;ELBASAN LETTER EI;Lo;0;L;;;;;N;;;;; +10508;ELBASAN LETTER E;Lo;0;L;;;;;N;;;;; +10509;ELBASAN LETTER FE;Lo;0;L;;;;;N;;;;; +1050A;ELBASAN LETTER GE;Lo;0;L;;;;;N;;;;; +1050B;ELBASAN LETTER GJE;Lo;0;L;;;;;N;;;;; +1050C;ELBASAN LETTER HE;Lo;0;L;;;;;N;;;;; +1050D;ELBASAN LETTER I;Lo;0;L;;;;;N;;;;; +1050E;ELBASAN LETTER JE;Lo;0;L;;;;;N;;;;; +1050F;ELBASAN LETTER KE;Lo;0;L;;;;;N;;;;; +10510;ELBASAN LETTER LE;Lo;0;L;;;;;N;;;;; +10511;ELBASAN LETTER LLE;Lo;0;L;;;;;N;;;;; +10512;ELBASAN LETTER ME;Lo;0;L;;;;;N;;;;; +10513;ELBASAN LETTER NE;Lo;0;L;;;;;N;;;;; +10514;ELBASAN LETTER NA;Lo;0;L;;;;;N;;;;; +10515;ELBASAN LETTER NJE;Lo;0;L;;;;;N;;;;; +10516;ELBASAN LETTER O;Lo;0;L;;;;;N;;;;; +10517;ELBASAN LETTER PE;Lo;0;L;;;;;N;;;;; +10518;ELBASAN LETTER QE;Lo;0;L;;;;;N;;;;; +10519;ELBASAN LETTER RE;Lo;0;L;;;;;N;;;;; +1051A;ELBASAN LETTER RRE;Lo;0;L;;;;;N;;;;; +1051B;ELBASAN LETTER SE;Lo;0;L;;;;;N;;;;; +1051C;ELBASAN LETTER SHE;Lo;0;L;;;;;N;;;;; +1051D;ELBASAN LETTER TE;Lo;0;L;;;;;N;;;;; +1051E;ELBASAN LETTER THE;Lo;0;L;;;;;N;;;;; +1051F;ELBASAN LETTER U;Lo;0;L;;;;;N;;;;; +10520;ELBASAN LETTER VE;Lo;0;L;;;;;N;;;;; +10521;ELBASAN LETTER XE;Lo;0;L;;;;;N;;;;; +10522;ELBASAN LETTER Y;Lo;0;L;;;;;N;;;;; +10523;ELBASAN LETTER ZE;Lo;0;L;;;;;N;;;;; +10524;ELBASAN LETTER ZHE;Lo;0;L;;;;;N;;;;; +10525;ELBASAN LETTER GHE;Lo;0;L;;;;;N;;;;; +10526;ELBASAN LETTER GHAMMA;Lo;0;L;;;;;N;;;;; +10527;ELBASAN LETTER KHE;Lo;0;L;;;;;N;;;;; +10530;CAUCASIAN ALBANIAN LETTER ALT;Lo;0;L;;;;;N;;;;; +10531;CAUCASIAN ALBANIAN LETTER BET;Lo;0;L;;;;;N;;;;; +10532;CAUCASIAN ALBANIAN LETTER GIM;Lo;0;L;;;;;N;;;;; +10533;CAUCASIAN ALBANIAN LETTER DAT;Lo;0;L;;;;;N;;;;; +10534;CAUCASIAN ALBANIAN LETTER EB;Lo;0;L;;;;;N;;;;; +10535;CAUCASIAN ALBANIAN LETTER ZARL;Lo;0;L;;;;;N;;;;; +10536;CAUCASIAN ALBANIAN LETTER EYN;Lo;0;L;;;;;N;;;;; +10537;CAUCASIAN ALBANIAN LETTER ZHIL;Lo;0;L;;;;;N;;;;; +10538;CAUCASIAN ALBANIAN LETTER TAS;Lo;0;L;;;;;N;;;;; +10539;CAUCASIAN ALBANIAN LETTER CHA;Lo;0;L;;;;;N;;;;; +1053A;CAUCASIAN ALBANIAN LETTER YOWD;Lo;0;L;;;;;N;;;;; +1053B;CAUCASIAN ALBANIAN LETTER ZHA;Lo;0;L;;;;;N;;;;; +1053C;CAUCASIAN ALBANIAN LETTER IRB;Lo;0;L;;;;;N;;;;; +1053D;CAUCASIAN ALBANIAN LETTER SHA;Lo;0;L;;;;;N;;;;; +1053E;CAUCASIAN ALBANIAN LETTER LAN;Lo;0;L;;;;;N;;;;; +1053F;CAUCASIAN ALBANIAN LETTER INYA;Lo;0;L;;;;;N;;;;; +10540;CAUCASIAN ALBANIAN LETTER XEYN;Lo;0;L;;;;;N;;;;; +10541;CAUCASIAN ALBANIAN LETTER DYAN;Lo;0;L;;;;;N;;;;; +10542;CAUCASIAN ALBANIAN LETTER CAR;Lo;0;L;;;;;N;;;;; +10543;CAUCASIAN ALBANIAN LETTER JHOX;Lo;0;L;;;;;N;;;;; +10544;CAUCASIAN ALBANIAN LETTER KAR;Lo;0;L;;;;;N;;;;; +10545;CAUCASIAN ALBANIAN LETTER LYIT;Lo;0;L;;;;;N;;;;; +10546;CAUCASIAN ALBANIAN LETTER HEYT;Lo;0;L;;;;;N;;;;; +10547;CAUCASIAN ALBANIAN LETTER QAY;Lo;0;L;;;;;N;;;;; +10548;CAUCASIAN ALBANIAN LETTER AOR;Lo;0;L;;;;;N;;;;; +10549;CAUCASIAN ALBANIAN LETTER CHOY;Lo;0;L;;;;;N;;;;; +1054A;CAUCASIAN ALBANIAN LETTER CHI;Lo;0;L;;;;;N;;;;; +1054B;CAUCASIAN ALBANIAN LETTER CYAY;Lo;0;L;;;;;N;;;;; +1054C;CAUCASIAN ALBANIAN LETTER MAQ;Lo;0;L;;;;;N;;;;; +1054D;CAUCASIAN ALBANIAN LETTER QAR;Lo;0;L;;;;;N;;;;; +1054E;CAUCASIAN ALBANIAN LETTER NOWC;Lo;0;L;;;;;N;;;;; +1054F;CAUCASIAN ALBANIAN LETTER DZYAY;Lo;0;L;;;;;N;;;;; +10550;CAUCASIAN ALBANIAN LETTER SHAK;Lo;0;L;;;;;N;;;;; +10551;CAUCASIAN ALBANIAN LETTER JAYN;Lo;0;L;;;;;N;;;;; +10552;CAUCASIAN ALBANIAN LETTER ON;Lo;0;L;;;;;N;;;;; +10553;CAUCASIAN ALBANIAN LETTER TYAY;Lo;0;L;;;;;N;;;;; +10554;CAUCASIAN ALBANIAN LETTER FAM;Lo;0;L;;;;;N;;;;; +10555;CAUCASIAN ALBANIAN LETTER DZAY;Lo;0;L;;;;;N;;;;; +10556;CAUCASIAN ALBANIAN LETTER CHAT;Lo;0;L;;;;;N;;;;; +10557;CAUCASIAN ALBANIAN LETTER PEN;Lo;0;L;;;;;N;;;;; +10558;CAUCASIAN ALBANIAN LETTER GHEYS;Lo;0;L;;;;;N;;;;; +10559;CAUCASIAN ALBANIAN LETTER RAT;Lo;0;L;;;;;N;;;;; +1055A;CAUCASIAN ALBANIAN LETTER SEYK;Lo;0;L;;;;;N;;;;; +1055B;CAUCASIAN ALBANIAN LETTER VEYZ;Lo;0;L;;;;;N;;;;; +1055C;CAUCASIAN ALBANIAN LETTER TIWR;Lo;0;L;;;;;N;;;;; +1055D;CAUCASIAN ALBANIAN LETTER SHOY;Lo;0;L;;;;;N;;;;; +1055E;CAUCASIAN ALBANIAN LETTER IWN;Lo;0;L;;;;;N;;;;; +1055F;CAUCASIAN ALBANIAN LETTER CYAW;Lo;0;L;;;;;N;;;;; +10560;CAUCASIAN ALBANIAN LETTER CAYN;Lo;0;L;;;;;N;;;;; +10561;CAUCASIAN ALBANIAN LETTER YAYD;Lo;0;L;;;;;N;;;;; +10562;CAUCASIAN ALBANIAN LETTER PIWR;Lo;0;L;;;;;N;;;;; +10563;CAUCASIAN ALBANIAN LETTER KIW;Lo;0;L;;;;;N;;;;; +1056F;CAUCASIAN ALBANIAN CITATION MARK;Po;0;L;;;;;N;;;;; +10600;LINEAR A SIGN AB001;Lo;0;L;;;;;N;;;;; +10601;LINEAR A SIGN AB002;Lo;0;L;;;;;N;;;;; +10602;LINEAR A SIGN AB003;Lo;0;L;;;;;N;;;;; +10603;LINEAR A SIGN AB004;Lo;0;L;;;;;N;;;;; +10604;LINEAR A SIGN AB005;Lo;0;L;;;;;N;;;;; +10605;LINEAR A SIGN AB006;Lo;0;L;;;;;N;;;;; +10606;LINEAR A SIGN AB007;Lo;0;L;;;;;N;;;;; +10607;LINEAR A SIGN AB008;Lo;0;L;;;;;N;;;;; +10608;LINEAR A SIGN AB009;Lo;0;L;;;;;N;;;;; +10609;LINEAR A SIGN AB010;Lo;0;L;;;;;N;;;;; +1060A;LINEAR A SIGN AB011;Lo;0;L;;;;;N;;;;; +1060B;LINEAR A SIGN AB013;Lo;0;L;;;;;N;;;;; +1060C;LINEAR A SIGN AB016;Lo;0;L;;;;;N;;;;; +1060D;LINEAR A SIGN AB017;Lo;0;L;;;;;N;;;;; +1060E;LINEAR A SIGN AB020;Lo;0;L;;;;;N;;;;; +1060F;LINEAR A SIGN AB021;Lo;0;L;;;;;N;;;;; +10610;LINEAR A SIGN AB021F;Lo;0;L;;;;;N;;;;; +10611;LINEAR A SIGN AB021M;Lo;0;L;;;;;N;;;;; +10612;LINEAR A SIGN AB022;Lo;0;L;;;;;N;;;;; +10613;LINEAR A SIGN AB022F;Lo;0;L;;;;;N;;;;; +10614;LINEAR A SIGN AB022M;Lo;0;L;;;;;N;;;;; +10615;LINEAR A SIGN AB023;Lo;0;L;;;;;N;;;;; +10616;LINEAR A SIGN AB023M;Lo;0;L;;;;;N;;;;; +10617;LINEAR A SIGN AB024;Lo;0;L;;;;;N;;;;; +10618;LINEAR A SIGN AB026;Lo;0;L;;;;;N;;;;; +10619;LINEAR A SIGN AB027;Lo;0;L;;;;;N;;;;; +1061A;LINEAR A SIGN AB028;Lo;0;L;;;;;N;;;;; +1061B;LINEAR A SIGN A028B;Lo;0;L;;;;;N;;;;; +1061C;LINEAR A SIGN AB029;Lo;0;L;;;;;N;;;;; +1061D;LINEAR A SIGN AB030;Lo;0;L;;;;;N;;;;; +1061E;LINEAR A SIGN AB031;Lo;0;L;;;;;N;;;;; +1061F;LINEAR A SIGN AB034;Lo;0;L;;;;;N;;;;; +10620;LINEAR A SIGN AB037;Lo;0;L;;;;;N;;;;; +10621;LINEAR A SIGN AB038;Lo;0;L;;;;;N;;;;; +10622;LINEAR A SIGN AB039;Lo;0;L;;;;;N;;;;; +10623;LINEAR A SIGN AB040;Lo;0;L;;;;;N;;;;; +10624;LINEAR A SIGN AB041;Lo;0;L;;;;;N;;;;; +10625;LINEAR A SIGN AB044;Lo;0;L;;;;;N;;;;; +10626;LINEAR A SIGN AB045;Lo;0;L;;;;;N;;;;; +10627;LINEAR A SIGN AB046;Lo;0;L;;;;;N;;;;; +10628;LINEAR A SIGN AB047;Lo;0;L;;;;;N;;;;; +10629;LINEAR A SIGN AB048;Lo;0;L;;;;;N;;;;; +1062A;LINEAR A SIGN AB049;Lo;0;L;;;;;N;;;;; +1062B;LINEAR A SIGN AB050;Lo;0;L;;;;;N;;;;; +1062C;LINEAR A SIGN AB051;Lo;0;L;;;;;N;;;;; +1062D;LINEAR A SIGN AB053;Lo;0;L;;;;;N;;;;; +1062E;LINEAR A SIGN AB054;Lo;0;L;;;;;N;;;;; +1062F;LINEAR A SIGN AB055;Lo;0;L;;;;;N;;;;; +10630;LINEAR A SIGN AB056;Lo;0;L;;;;;N;;;;; +10631;LINEAR A SIGN AB057;Lo;0;L;;;;;N;;;;; +10632;LINEAR A SIGN AB058;Lo;0;L;;;;;N;;;;; +10633;LINEAR A SIGN AB059;Lo;0;L;;;;;N;;;;; +10634;LINEAR A SIGN AB060;Lo;0;L;;;;;N;;;;; +10635;LINEAR A SIGN AB061;Lo;0;L;;;;;N;;;;; +10636;LINEAR A SIGN AB065;Lo;0;L;;;;;N;;;;; +10637;LINEAR A SIGN AB066;Lo;0;L;;;;;N;;;;; +10638;LINEAR A SIGN AB067;Lo;0;L;;;;;N;;;;; +10639;LINEAR A SIGN AB069;Lo;0;L;;;;;N;;;;; +1063A;LINEAR A SIGN AB070;Lo;0;L;;;;;N;;;;; +1063B;LINEAR A SIGN AB073;Lo;0;L;;;;;N;;;;; +1063C;LINEAR A SIGN AB074;Lo;0;L;;;;;N;;;;; +1063D;LINEAR A SIGN AB076;Lo;0;L;;;;;N;;;;; +1063E;LINEAR A SIGN AB077;Lo;0;L;;;;;N;;;;; +1063F;LINEAR A SIGN AB078;Lo;0;L;;;;;N;;;;; +10640;LINEAR A SIGN AB079;Lo;0;L;;;;;N;;;;; +10641;LINEAR A SIGN AB080;Lo;0;L;;;;;N;;;;; +10642;LINEAR A SIGN AB081;Lo;0;L;;;;;N;;;;; +10643;LINEAR A SIGN AB082;Lo;0;L;;;;;N;;;;; +10644;LINEAR A SIGN AB085;Lo;0;L;;;;;N;;;;; +10645;LINEAR A SIGN AB086;Lo;0;L;;;;;N;;;;; +10646;LINEAR A SIGN AB087;Lo;0;L;;;;;N;;;;; +10647;LINEAR A SIGN A100-102;Lo;0;L;;;;;N;;;;; +10648;LINEAR A SIGN AB118;Lo;0;L;;;;;N;;;;; +10649;LINEAR A SIGN AB120;Lo;0;L;;;;;N;;;;; +1064A;LINEAR A SIGN A120B;Lo;0;L;;;;;N;;;;; +1064B;LINEAR A SIGN AB122;Lo;0;L;;;;;N;;;;; +1064C;LINEAR A SIGN AB123;Lo;0;L;;;;;N;;;;; +1064D;LINEAR A SIGN AB131A;Lo;0;L;;;;;N;;;;; +1064E;LINEAR A SIGN AB131B;Lo;0;L;;;;;N;;;;; +1064F;LINEAR A SIGN A131C;Lo;0;L;;;;;N;;;;; +10650;LINEAR A SIGN AB164;Lo;0;L;;;;;N;;;;; +10651;LINEAR A SIGN AB171;Lo;0;L;;;;;N;;;;; +10652;LINEAR A SIGN AB180;Lo;0;L;;;;;N;;;;; +10653;LINEAR A SIGN AB188;Lo;0;L;;;;;N;;;;; +10654;LINEAR A SIGN AB191;Lo;0;L;;;;;N;;;;; +10655;LINEAR A SIGN A301;Lo;0;L;;;;;N;;;;; +10656;LINEAR A SIGN A302;Lo;0;L;;;;;N;;;;; +10657;LINEAR A SIGN A303;Lo;0;L;;;;;N;;;;; +10658;LINEAR A SIGN A304;Lo;0;L;;;;;N;;;;; +10659;LINEAR A SIGN A305;Lo;0;L;;;;;N;;;;; +1065A;LINEAR A SIGN A306;Lo;0;L;;;;;N;;;;; +1065B;LINEAR A SIGN A307;Lo;0;L;;;;;N;;;;; +1065C;LINEAR A SIGN A308;Lo;0;L;;;;;N;;;;; +1065D;LINEAR A SIGN A309A;Lo;0;L;;;;;N;;;;; +1065E;LINEAR A SIGN A309B;Lo;0;L;;;;;N;;;;; +1065F;LINEAR A SIGN A309C;Lo;0;L;;;;;N;;;;; +10660;LINEAR A SIGN A310;Lo;0;L;;;;;N;;;;; +10661;LINEAR A SIGN A311;Lo;0;L;;;;;N;;;;; +10662;LINEAR A SIGN A312;Lo;0;L;;;;;N;;;;; +10663;LINEAR A SIGN A313A;Lo;0;L;;;;;N;;;;; +10664;LINEAR A SIGN A313B;Lo;0;L;;;;;N;;;;; +10665;LINEAR A SIGN A313C;Lo;0;L;;;;;N;;;;; +10666;LINEAR A SIGN A314;Lo;0;L;;;;;N;;;;; +10667;LINEAR A SIGN A315;Lo;0;L;;;;;N;;;;; +10668;LINEAR A SIGN A316;Lo;0;L;;;;;N;;;;; +10669;LINEAR A SIGN A317;Lo;0;L;;;;;N;;;;; +1066A;LINEAR A SIGN A318;Lo;0;L;;;;;N;;;;; +1066B;LINEAR A SIGN A319;Lo;0;L;;;;;N;;;;; +1066C;LINEAR A SIGN A320;Lo;0;L;;;;;N;;;;; +1066D;LINEAR A SIGN A321;Lo;0;L;;;;;N;;;;; +1066E;LINEAR A SIGN A322;Lo;0;L;;;;;N;;;;; +1066F;LINEAR A SIGN A323;Lo;0;L;;;;;N;;;;; +10670;LINEAR A SIGN A324;Lo;0;L;;;;;N;;;;; +10671;LINEAR A SIGN A325;Lo;0;L;;;;;N;;;;; +10672;LINEAR A SIGN A326;Lo;0;L;;;;;N;;;;; +10673;LINEAR A SIGN A327;Lo;0;L;;;;;N;;;;; +10674;LINEAR A SIGN A328;Lo;0;L;;;;;N;;;;; +10675;LINEAR A SIGN A329;Lo;0;L;;;;;N;;;;; +10676;LINEAR A SIGN A330;Lo;0;L;;;;;N;;;;; +10677;LINEAR A SIGN A331;Lo;0;L;;;;;N;;;;; +10678;LINEAR A SIGN A332;Lo;0;L;;;;;N;;;;; +10679;LINEAR A SIGN A333;Lo;0;L;;;;;N;;;;; +1067A;LINEAR A SIGN A334;Lo;0;L;;;;;N;;;;; +1067B;LINEAR A SIGN A335;Lo;0;L;;;;;N;;;;; +1067C;LINEAR A SIGN A336;Lo;0;L;;;;;N;;;;; +1067D;LINEAR A SIGN A337;Lo;0;L;;;;;N;;;;; +1067E;LINEAR A SIGN A338;Lo;0;L;;;;;N;;;;; +1067F;LINEAR A SIGN A339;Lo;0;L;;;;;N;;;;; +10680;LINEAR A SIGN A340;Lo;0;L;;;;;N;;;;; +10681;LINEAR A SIGN A341;Lo;0;L;;;;;N;;;;; +10682;LINEAR A SIGN A342;Lo;0;L;;;;;N;;;;; +10683;LINEAR A SIGN A343;Lo;0;L;;;;;N;;;;; +10684;LINEAR A SIGN A344;Lo;0;L;;;;;N;;;;; +10685;LINEAR A SIGN A345;Lo;0;L;;;;;N;;;;; +10686;LINEAR A SIGN A346;Lo;0;L;;;;;N;;;;; +10687;LINEAR A SIGN A347;Lo;0;L;;;;;N;;;;; +10688;LINEAR A SIGN A348;Lo;0;L;;;;;N;;;;; +10689;LINEAR A SIGN A349;Lo;0;L;;;;;N;;;;; +1068A;LINEAR A SIGN A350;Lo;0;L;;;;;N;;;;; +1068B;LINEAR A SIGN A351;Lo;0;L;;;;;N;;;;; +1068C;LINEAR A SIGN A352;Lo;0;L;;;;;N;;;;; +1068D;LINEAR A SIGN A353;Lo;0;L;;;;;N;;;;; +1068E;LINEAR A SIGN A354;Lo;0;L;;;;;N;;;;; +1068F;LINEAR A SIGN A355;Lo;0;L;;;;;N;;;;; +10690;LINEAR A SIGN A356;Lo;0;L;;;;;N;;;;; +10691;LINEAR A SIGN A357;Lo;0;L;;;;;N;;;;; +10692;LINEAR A SIGN A358;Lo;0;L;;;;;N;;;;; +10693;LINEAR A SIGN A359;Lo;0;L;;;;;N;;;;; +10694;LINEAR A SIGN A360;Lo;0;L;;;;;N;;;;; +10695;LINEAR A SIGN A361;Lo;0;L;;;;;N;;;;; +10696;LINEAR A SIGN A362;Lo;0;L;;;;;N;;;;; +10697;LINEAR A SIGN A363;Lo;0;L;;;;;N;;;;; +10698;LINEAR A SIGN A364;Lo;0;L;;;;;N;;;;; +10699;LINEAR A SIGN A365;Lo;0;L;;;;;N;;;;; +1069A;LINEAR A SIGN A366;Lo;0;L;;;;;N;;;;; +1069B;LINEAR A SIGN A367;Lo;0;L;;;;;N;;;;; +1069C;LINEAR A SIGN A368;Lo;0;L;;;;;N;;;;; +1069D;LINEAR A SIGN A369;Lo;0;L;;;;;N;;;;; +1069E;LINEAR A SIGN A370;Lo;0;L;;;;;N;;;;; +1069F;LINEAR A SIGN A371;Lo;0;L;;;;;N;;;;; +106A0;LINEAR A SIGN A400-VAS;Lo;0;L;;;;;N;;;;; +106A1;LINEAR A SIGN A401-VAS;Lo;0;L;;;;;N;;;;; +106A2;LINEAR A SIGN A402-VAS;Lo;0;L;;;;;N;;;;; +106A3;LINEAR A SIGN A403-VAS;Lo;0;L;;;;;N;;;;; +106A4;LINEAR A SIGN A404-VAS;Lo;0;L;;;;;N;;;;; +106A5;LINEAR A SIGN A405-VAS;Lo;0;L;;;;;N;;;;; +106A6;LINEAR A SIGN A406-VAS;Lo;0;L;;;;;N;;;;; +106A7;LINEAR A SIGN A407-VAS;Lo;0;L;;;;;N;;;;; +106A8;LINEAR A SIGN A408-VAS;Lo;0;L;;;;;N;;;;; +106A9;LINEAR A SIGN A409-VAS;Lo;0;L;;;;;N;;;;; +106AA;LINEAR A SIGN A410-VAS;Lo;0;L;;;;;N;;;;; +106AB;LINEAR A SIGN A411-VAS;Lo;0;L;;;;;N;;;;; +106AC;LINEAR A SIGN A412-VAS;Lo;0;L;;;;;N;;;;; +106AD;LINEAR A SIGN A413-VAS;Lo;0;L;;;;;N;;;;; +106AE;LINEAR A SIGN A414-VAS;Lo;0;L;;;;;N;;;;; +106AF;LINEAR A SIGN A415-VAS;Lo;0;L;;;;;N;;;;; +106B0;LINEAR A SIGN A416-VAS;Lo;0;L;;;;;N;;;;; +106B1;LINEAR A SIGN A417-VAS;Lo;0;L;;;;;N;;;;; +106B2;LINEAR A SIGN A418-VAS;Lo;0;L;;;;;N;;;;; +106B3;LINEAR A SIGN A501;Lo;0;L;;;;;N;;;;; +106B4;LINEAR A SIGN A502;Lo;0;L;;;;;N;;;;; +106B5;LINEAR A SIGN A503;Lo;0;L;;;;;N;;;;; +106B6;LINEAR A SIGN A504;Lo;0;L;;;;;N;;;;; +106B7;LINEAR A SIGN A505;Lo;0;L;;;;;N;;;;; +106B8;LINEAR A SIGN A506;Lo;0;L;;;;;N;;;;; +106B9;LINEAR A SIGN A508;Lo;0;L;;;;;N;;;;; +106BA;LINEAR A SIGN A509;Lo;0;L;;;;;N;;;;; +106BB;LINEAR A SIGN A510;Lo;0;L;;;;;N;;;;; +106BC;LINEAR A SIGN A511;Lo;0;L;;;;;N;;;;; +106BD;LINEAR A SIGN A512;Lo;0;L;;;;;N;;;;; +106BE;LINEAR A SIGN A513;Lo;0;L;;;;;N;;;;; +106BF;LINEAR A SIGN A515;Lo;0;L;;;;;N;;;;; +106C0;LINEAR A SIGN A516;Lo;0;L;;;;;N;;;;; +106C1;LINEAR A SIGN A520;Lo;0;L;;;;;N;;;;; +106C2;LINEAR A SIGN A521;Lo;0;L;;;;;N;;;;; +106C3;LINEAR A SIGN A523;Lo;0;L;;;;;N;;;;; +106C4;LINEAR A SIGN A524;Lo;0;L;;;;;N;;;;; +106C5;LINEAR A SIGN A525;Lo;0;L;;;;;N;;;;; +106C6;LINEAR A SIGN A526;Lo;0;L;;;;;N;;;;; +106C7;LINEAR A SIGN A527;Lo;0;L;;;;;N;;;;; +106C8;LINEAR A SIGN A528;Lo;0;L;;;;;N;;;;; +106C9;LINEAR A SIGN A529;Lo;0;L;;;;;N;;;;; +106CA;LINEAR A SIGN A530;Lo;0;L;;;;;N;;;;; +106CB;LINEAR A SIGN A531;Lo;0;L;;;;;N;;;;; +106CC;LINEAR A SIGN A532;Lo;0;L;;;;;N;;;;; +106CD;LINEAR A SIGN A534;Lo;0;L;;;;;N;;;;; +106CE;LINEAR A SIGN A535;Lo;0;L;;;;;N;;;;; +106CF;LINEAR A SIGN A536;Lo;0;L;;;;;N;;;;; +106D0;LINEAR A SIGN A537;Lo;0;L;;;;;N;;;;; +106D1;LINEAR A SIGN A538;Lo;0;L;;;;;N;;;;; +106D2;LINEAR A SIGN A539;Lo;0;L;;;;;N;;;;; +106D3;LINEAR A SIGN A540;Lo;0;L;;;;;N;;;;; +106D4;LINEAR A SIGN A541;Lo;0;L;;;;;N;;;;; +106D5;LINEAR A SIGN A542;Lo;0;L;;;;;N;;;;; +106D6;LINEAR A SIGN A545;Lo;0;L;;;;;N;;;;; +106D7;LINEAR A SIGN A547;Lo;0;L;;;;;N;;;;; +106D8;LINEAR A SIGN A548;Lo;0;L;;;;;N;;;;; +106D9;LINEAR A SIGN A549;Lo;0;L;;;;;N;;;;; +106DA;LINEAR A SIGN A550;Lo;0;L;;;;;N;;;;; +106DB;LINEAR A SIGN A551;Lo;0;L;;;;;N;;;;; +106DC;LINEAR A SIGN A552;Lo;0;L;;;;;N;;;;; +106DD;LINEAR A SIGN A553;Lo;0;L;;;;;N;;;;; +106DE;LINEAR A SIGN A554;Lo;0;L;;;;;N;;;;; +106DF;LINEAR A SIGN A555;Lo;0;L;;;;;N;;;;; +106E0;LINEAR A SIGN A556;Lo;0;L;;;;;N;;;;; +106E1;LINEAR A SIGN A557;Lo;0;L;;;;;N;;;;; +106E2;LINEAR A SIGN A559;Lo;0;L;;;;;N;;;;; +106E3;LINEAR A SIGN A563;Lo;0;L;;;;;N;;;;; +106E4;LINEAR A SIGN A564;Lo;0;L;;;;;N;;;;; +106E5;LINEAR A SIGN A565;Lo;0;L;;;;;N;;;;; +106E6;LINEAR A SIGN A566;Lo;0;L;;;;;N;;;;; +106E7;LINEAR A SIGN A568;Lo;0;L;;;;;N;;;;; +106E8;LINEAR A SIGN A569;Lo;0;L;;;;;N;;;;; +106E9;LINEAR A SIGN A570;Lo;0;L;;;;;N;;;;; +106EA;LINEAR A SIGN A571;Lo;0;L;;;;;N;;;;; +106EB;LINEAR A SIGN A572;Lo;0;L;;;;;N;;;;; +106EC;LINEAR A SIGN A573;Lo;0;L;;;;;N;;;;; +106ED;LINEAR A SIGN A574;Lo;0;L;;;;;N;;;;; +106EE;LINEAR A SIGN A575;Lo;0;L;;;;;N;;;;; +106EF;LINEAR A SIGN A576;Lo;0;L;;;;;N;;;;; +106F0;LINEAR A SIGN A577;Lo;0;L;;;;;N;;;;; +106F1;LINEAR A SIGN A578;Lo;0;L;;;;;N;;;;; +106F2;LINEAR A SIGN A579;Lo;0;L;;;;;N;;;;; +106F3;LINEAR A SIGN A580;Lo;0;L;;;;;N;;;;; +106F4;LINEAR A SIGN A581;Lo;0;L;;;;;N;;;;; +106F5;LINEAR A SIGN A582;Lo;0;L;;;;;N;;;;; +106F6;LINEAR A SIGN A583;Lo;0;L;;;;;N;;;;; +106F7;LINEAR A SIGN A584;Lo;0;L;;;;;N;;;;; +106F8;LINEAR A SIGN A585;Lo;0;L;;;;;N;;;;; +106F9;LINEAR A SIGN A586;Lo;0;L;;;;;N;;;;; +106FA;LINEAR A SIGN A587;Lo;0;L;;;;;N;;;;; +106FB;LINEAR A SIGN A588;Lo;0;L;;;;;N;;;;; +106FC;LINEAR A SIGN A589;Lo;0;L;;;;;N;;;;; +106FD;LINEAR A SIGN A591;Lo;0;L;;;;;N;;;;; +106FE;LINEAR A SIGN A592;Lo;0;L;;;;;N;;;;; +106FF;LINEAR A SIGN A594;Lo;0;L;;;;;N;;;;; +10700;LINEAR A SIGN A595;Lo;0;L;;;;;N;;;;; +10701;LINEAR A SIGN A596;Lo;0;L;;;;;N;;;;; +10702;LINEAR A SIGN A598;Lo;0;L;;;;;N;;;;; +10703;LINEAR A SIGN A600;Lo;0;L;;;;;N;;;;; +10704;LINEAR A SIGN A601;Lo;0;L;;;;;N;;;;; +10705;LINEAR A SIGN A602;Lo;0;L;;;;;N;;;;; +10706;LINEAR A SIGN A603;Lo;0;L;;;;;N;;;;; +10707;LINEAR A SIGN A604;Lo;0;L;;;;;N;;;;; +10708;LINEAR A SIGN A606;Lo;0;L;;;;;N;;;;; +10709;LINEAR A SIGN A608;Lo;0;L;;;;;N;;;;; +1070A;LINEAR A SIGN A609;Lo;0;L;;;;;N;;;;; +1070B;LINEAR A SIGN A610;Lo;0;L;;;;;N;;;;; +1070C;LINEAR A SIGN A611;Lo;0;L;;;;;N;;;;; +1070D;LINEAR A SIGN A612;Lo;0;L;;;;;N;;;;; +1070E;LINEAR A SIGN A613;Lo;0;L;;;;;N;;;;; +1070F;LINEAR A SIGN A614;Lo;0;L;;;;;N;;;;; +10710;LINEAR A SIGN A615;Lo;0;L;;;;;N;;;;; +10711;LINEAR A SIGN A616;Lo;0;L;;;;;N;;;;; +10712;LINEAR A SIGN A617;Lo;0;L;;;;;N;;;;; +10713;LINEAR A SIGN A618;Lo;0;L;;;;;N;;;;; +10714;LINEAR A SIGN A619;Lo;0;L;;;;;N;;;;; +10715;LINEAR A SIGN A620;Lo;0;L;;;;;N;;;;; +10716;LINEAR A SIGN A621;Lo;0;L;;;;;N;;;;; +10717;LINEAR A SIGN A622;Lo;0;L;;;;;N;;;;; +10718;LINEAR A SIGN A623;Lo;0;L;;;;;N;;;;; +10719;LINEAR A SIGN A624;Lo;0;L;;;;;N;;;;; +1071A;LINEAR A SIGN A626;Lo;0;L;;;;;N;;;;; +1071B;LINEAR A SIGN A627;Lo;0;L;;;;;N;;;;; +1071C;LINEAR A SIGN A628;Lo;0;L;;;;;N;;;;; +1071D;LINEAR A SIGN A629;Lo;0;L;;;;;N;;;;; +1071E;LINEAR A SIGN A634;Lo;0;L;;;;;N;;;;; +1071F;LINEAR A SIGN A637;Lo;0;L;;;;;N;;;;; +10720;LINEAR A SIGN A638;Lo;0;L;;;;;N;;;;; +10721;LINEAR A SIGN A640;Lo;0;L;;;;;N;;;;; +10722;LINEAR A SIGN A642;Lo;0;L;;;;;N;;;;; +10723;LINEAR A SIGN A643;Lo;0;L;;;;;N;;;;; +10724;LINEAR A SIGN A644;Lo;0;L;;;;;N;;;;; +10725;LINEAR A SIGN A645;Lo;0;L;;;;;N;;;;; +10726;LINEAR A SIGN A646;Lo;0;L;;;;;N;;;;; +10727;LINEAR A SIGN A648;Lo;0;L;;;;;N;;;;; +10728;LINEAR A SIGN A649;Lo;0;L;;;;;N;;;;; +10729;LINEAR A SIGN A651;Lo;0;L;;;;;N;;;;; +1072A;LINEAR A SIGN A652;Lo;0;L;;;;;N;;;;; +1072B;LINEAR A SIGN A653;Lo;0;L;;;;;N;;;;; +1072C;LINEAR A SIGN A654;Lo;0;L;;;;;N;;;;; +1072D;LINEAR A SIGN A655;Lo;0;L;;;;;N;;;;; +1072E;LINEAR A SIGN A656;Lo;0;L;;;;;N;;;;; +1072F;LINEAR A SIGN A657;Lo;0;L;;;;;N;;;;; +10730;LINEAR A SIGN A658;Lo;0;L;;;;;N;;;;; +10731;LINEAR A SIGN A659;Lo;0;L;;;;;N;;;;; +10732;LINEAR A SIGN A660;Lo;0;L;;;;;N;;;;; +10733;LINEAR A SIGN A661;Lo;0;L;;;;;N;;;;; +10734;LINEAR A SIGN A662;Lo;0;L;;;;;N;;;;; +10735;LINEAR A SIGN A663;Lo;0;L;;;;;N;;;;; +10736;LINEAR A SIGN A664;Lo;0;L;;;;;N;;;;; +10740;LINEAR A SIGN A701 A;Lo;0;L;;;;;N;;;;; +10741;LINEAR A SIGN A702 B;Lo;0;L;;;;;N;;;;; +10742;LINEAR A SIGN A703 D;Lo;0;L;;;;;N;;;;; +10743;LINEAR A SIGN A704 E;Lo;0;L;;;;;N;;;;; +10744;LINEAR A SIGN A705 F;Lo;0;L;;;;;N;;;;; +10745;LINEAR A SIGN A706 H;Lo;0;L;;;;;N;;;;; +10746;LINEAR A SIGN A707 J;Lo;0;L;;;;;N;;;;; +10747;LINEAR A SIGN A708 K;Lo;0;L;;;;;N;;;;; +10748;LINEAR A SIGN A709 L;Lo;0;L;;;;;N;;;;; +10749;LINEAR A SIGN A709-2 L2;Lo;0;L;;;;;N;;;;; +1074A;LINEAR A SIGN A709-3 L3;Lo;0;L;;;;;N;;;;; +1074B;LINEAR A SIGN A709-4 L4;Lo;0;L;;;;;N;;;;; +1074C;LINEAR A SIGN A709-6 L6;Lo;0;L;;;;;N;;;;; +1074D;LINEAR A SIGN A710 W;Lo;0;L;;;;;N;;;;; +1074E;LINEAR A SIGN A711 X;Lo;0;L;;;;;N;;;;; +1074F;LINEAR A SIGN A712 Y;Lo;0;L;;;;;N;;;;; +10750;LINEAR A SIGN A713 OMEGA;Lo;0;L;;;;;N;;;;; +10751;LINEAR A SIGN A714 ABB;Lo;0;L;;;;;N;;;;; +10752;LINEAR A SIGN A715 BB;Lo;0;L;;;;;N;;;;; +10753;LINEAR A SIGN A717 DD;Lo;0;L;;;;;N;;;;; +10754;LINEAR A SIGN A726 EYYY;Lo;0;L;;;;;N;;;;; +10755;LINEAR A SIGN A732 JE;Lo;0;L;;;;;N;;;;; +10760;LINEAR A SIGN A800;Lo;0;L;;;;;N;;;;; +10761;LINEAR A SIGN A801;Lo;0;L;;;;;N;;;;; +10762;LINEAR A SIGN A802;Lo;0;L;;;;;N;;;;; +10763;LINEAR A SIGN A803;Lo;0;L;;;;;N;;;;; +10764;LINEAR A SIGN A804;Lo;0;L;;;;;N;;;;; +10765;LINEAR A SIGN A805;Lo;0;L;;;;;N;;;;; +10766;LINEAR A SIGN A806;Lo;0;L;;;;;N;;;;; +10767;LINEAR A SIGN A807;Lo;0;L;;;;;N;;;;; +10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;; +10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;; +10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;; +10803;CYPRIOT SYLLABLE O;Lo;0;R;;;;;N;;;;; +10804;CYPRIOT SYLLABLE U;Lo;0;R;;;;;N;;;;; +10805;CYPRIOT SYLLABLE JA;Lo;0;R;;;;;N;;;;; +10808;CYPRIOT SYLLABLE JO;Lo;0;R;;;;;N;;;;; +1080A;CYPRIOT SYLLABLE KA;Lo;0;R;;;;;N;;;;; +1080B;CYPRIOT SYLLABLE KE;Lo;0;R;;;;;N;;;;; +1080C;CYPRIOT SYLLABLE KI;Lo;0;R;;;;;N;;;;; +1080D;CYPRIOT SYLLABLE KO;Lo;0;R;;;;;N;;;;; +1080E;CYPRIOT SYLLABLE KU;Lo;0;R;;;;;N;;;;; +1080F;CYPRIOT SYLLABLE LA;Lo;0;R;;;;;N;;;;; +10810;CYPRIOT SYLLABLE LE;Lo;0;R;;;;;N;;;;; +10811;CYPRIOT SYLLABLE LI;Lo;0;R;;;;;N;;;;; +10812;CYPRIOT SYLLABLE LO;Lo;0;R;;;;;N;;;;; +10813;CYPRIOT SYLLABLE LU;Lo;0;R;;;;;N;;;;; +10814;CYPRIOT SYLLABLE MA;Lo;0;R;;;;;N;;;;; +10815;CYPRIOT SYLLABLE ME;Lo;0;R;;;;;N;;;;; +10816;CYPRIOT SYLLABLE MI;Lo;0;R;;;;;N;;;;; +10817;CYPRIOT SYLLABLE MO;Lo;0;R;;;;;N;;;;; +10818;CYPRIOT SYLLABLE MU;Lo;0;R;;;;;N;;;;; +10819;CYPRIOT SYLLABLE NA;Lo;0;R;;;;;N;;;;; +1081A;CYPRIOT SYLLABLE NE;Lo;0;R;;;;;N;;;;; +1081B;CYPRIOT SYLLABLE NI;Lo;0;R;;;;;N;;;;; +1081C;CYPRIOT SYLLABLE NO;Lo;0;R;;;;;N;;;;; +1081D;CYPRIOT SYLLABLE NU;Lo;0;R;;;;;N;;;;; +1081E;CYPRIOT SYLLABLE PA;Lo;0;R;;;;;N;;;;; +1081F;CYPRIOT SYLLABLE PE;Lo;0;R;;;;;N;;;;; +10820;CYPRIOT SYLLABLE PI;Lo;0;R;;;;;N;;;;; +10821;CYPRIOT SYLLABLE PO;Lo;0;R;;;;;N;;;;; +10822;CYPRIOT SYLLABLE PU;Lo;0;R;;;;;N;;;;; +10823;CYPRIOT SYLLABLE RA;Lo;0;R;;;;;N;;;;; +10824;CYPRIOT SYLLABLE RE;Lo;0;R;;;;;N;;;;; +10825;CYPRIOT SYLLABLE RI;Lo;0;R;;;;;N;;;;; +10826;CYPRIOT SYLLABLE RO;Lo;0;R;;;;;N;;;;; +10827;CYPRIOT SYLLABLE RU;Lo;0;R;;;;;N;;;;; +10828;CYPRIOT SYLLABLE SA;Lo;0;R;;;;;N;;;;; +10829;CYPRIOT SYLLABLE SE;Lo;0;R;;;;;N;;;;; +1082A;CYPRIOT SYLLABLE SI;Lo;0;R;;;;;N;;;;; +1082B;CYPRIOT SYLLABLE SO;Lo;0;R;;;;;N;;;;; +1082C;CYPRIOT SYLLABLE SU;Lo;0;R;;;;;N;;;;; +1082D;CYPRIOT SYLLABLE TA;Lo;0;R;;;;;N;;;;; +1082E;CYPRIOT SYLLABLE TE;Lo;0;R;;;;;N;;;;; +1082F;CYPRIOT SYLLABLE TI;Lo;0;R;;;;;N;;;;; +10830;CYPRIOT SYLLABLE TO;Lo;0;R;;;;;N;;;;; +10831;CYPRIOT SYLLABLE TU;Lo;0;R;;;;;N;;;;; +10832;CYPRIOT SYLLABLE WA;Lo;0;R;;;;;N;;;;; +10833;CYPRIOT SYLLABLE WE;Lo;0;R;;;;;N;;;;; +10834;CYPRIOT SYLLABLE WI;Lo;0;R;;;;;N;;;;; +10835;CYPRIOT SYLLABLE WO;Lo;0;R;;;;;N;;;;; +10837;CYPRIOT SYLLABLE XA;Lo;0;R;;;;;N;;;;; +10838;CYPRIOT SYLLABLE XE;Lo;0;R;;;;;N;;;;; +1083C;CYPRIOT SYLLABLE ZA;Lo;0;R;;;;;N;;;;; +1083F;CYPRIOT SYLLABLE ZO;Lo;0;R;;;;;N;;;;; +10840;IMPERIAL ARAMAIC LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10841;IMPERIAL ARAMAIC LETTER BETH;Lo;0;R;;;;;N;;;;; +10842;IMPERIAL ARAMAIC LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10843;IMPERIAL ARAMAIC LETTER DALETH;Lo;0;R;;;;;N;;;;; +10844;IMPERIAL ARAMAIC LETTER HE;Lo;0;R;;;;;N;;;;; +10845;IMPERIAL ARAMAIC LETTER WAW;Lo;0;R;;;;;N;;;;; +10846;IMPERIAL ARAMAIC LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10847;IMPERIAL ARAMAIC LETTER HETH;Lo;0;R;;;;;N;;;;; +10848;IMPERIAL ARAMAIC LETTER TETH;Lo;0;R;;;;;N;;;;; +10849;IMPERIAL ARAMAIC LETTER YODH;Lo;0;R;;;;;N;;;;; +1084A;IMPERIAL ARAMAIC LETTER KAPH;Lo;0;R;;;;;N;;;;; +1084B;IMPERIAL ARAMAIC LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +1084C;IMPERIAL ARAMAIC LETTER MEM;Lo;0;R;;;;;N;;;;; +1084D;IMPERIAL ARAMAIC LETTER NUN;Lo;0;R;;;;;N;;;;; +1084E;IMPERIAL ARAMAIC LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +1084F;IMPERIAL ARAMAIC LETTER AYIN;Lo;0;R;;;;;N;;;;; +10850;IMPERIAL ARAMAIC LETTER PE;Lo;0;R;;;;;N;;;;; +10851;IMPERIAL ARAMAIC LETTER SADHE;Lo;0;R;;;;;N;;;;; +10852;IMPERIAL ARAMAIC LETTER QOPH;Lo;0;R;;;;;N;;;;; +10853;IMPERIAL ARAMAIC LETTER RESH;Lo;0;R;;;;;N;;;;; +10854;IMPERIAL ARAMAIC LETTER SHIN;Lo;0;R;;;;;N;;;;; +10855;IMPERIAL ARAMAIC LETTER TAW;Lo;0;R;;;;;N;;;;; +10857;IMPERIAL ARAMAIC SECTION SIGN;Po;0;R;;;;;N;;;;; +10858;IMPERIAL ARAMAIC NUMBER ONE;No;0;R;;;;1;N;;;;; +10859;IMPERIAL ARAMAIC NUMBER TWO;No;0;R;;;;2;N;;;;; +1085A;IMPERIAL ARAMAIC NUMBER THREE;No;0;R;;;;3;N;;;;; +1085B;IMPERIAL ARAMAIC NUMBER TEN;No;0;R;;;;10;N;;;;; +1085C;IMPERIAL ARAMAIC NUMBER TWENTY;No;0;R;;;;20;N;;;;; +1085D;IMPERIAL ARAMAIC NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +1085E;IMPERIAL ARAMAIC NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +1085F;IMPERIAL ARAMAIC NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;; +10860;PALMYRENE LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10861;PALMYRENE LETTER BETH;Lo;0;R;;;;;N;;;;; +10862;PALMYRENE LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10863;PALMYRENE LETTER DALETH;Lo;0;R;;;;;N;;;;; +10864;PALMYRENE LETTER HE;Lo;0;R;;;;;N;;;;; +10865;PALMYRENE LETTER WAW;Lo;0;R;;;;;N;;;;; +10866;PALMYRENE LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10867;PALMYRENE LETTER HETH;Lo;0;R;;;;;N;;;;; +10868;PALMYRENE LETTER TETH;Lo;0;R;;;;;N;;;;; +10869;PALMYRENE LETTER YODH;Lo;0;R;;;;;N;;;;; +1086A;PALMYRENE LETTER KAPH;Lo;0;R;;;;;N;;;;; +1086B;PALMYRENE LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +1086C;PALMYRENE LETTER MEM;Lo;0;R;;;;;N;;;;; +1086D;PALMYRENE LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; +1086E;PALMYRENE LETTER NUN;Lo;0;R;;;;;N;;;;; +1086F;PALMYRENE LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10870;PALMYRENE LETTER AYIN;Lo;0;R;;;;;N;;;;; +10871;PALMYRENE LETTER PE;Lo;0;R;;;;;N;;;;; +10872;PALMYRENE LETTER SADHE;Lo;0;R;;;;;N;;;;; +10873;PALMYRENE LETTER QOPH;Lo;0;R;;;;;N;;;;; +10874;PALMYRENE LETTER RESH;Lo;0;R;;;;;N;;;;; +10875;PALMYRENE LETTER SHIN;Lo;0;R;;;;;N;;;;; +10876;PALMYRENE LETTER TAW;Lo;0;R;;;;;N;;;;; +10877;PALMYRENE LEFT-POINTING FLEURON;So;0;R;;;;;N;;;;; +10878;PALMYRENE RIGHT-POINTING FLEURON;So;0;R;;;;;N;;;;; +10879;PALMYRENE NUMBER ONE;No;0;R;;;;1;N;;;;; +1087A;PALMYRENE NUMBER TWO;No;0;R;;;;2;N;;;;; +1087B;PALMYRENE NUMBER THREE;No;0;R;;;;3;N;;;;; +1087C;PALMYRENE NUMBER FOUR;No;0;R;;;;4;N;;;;; +1087D;PALMYRENE NUMBER FIVE;No;0;R;;;;5;N;;;;; +1087E;PALMYRENE NUMBER TEN;No;0;R;;;;10;N;;;;; +1087F;PALMYRENE NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10880;NABATAEAN LETTER FINAL ALEPH;Lo;0;R;;;;;N;;;;; +10881;NABATAEAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10882;NABATAEAN LETTER FINAL BETH;Lo;0;R;;;;;N;;;;; +10883;NABATAEAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10884;NABATAEAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10885;NABATAEAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10886;NABATAEAN LETTER FINAL HE;Lo;0;R;;;;;N;;;;; +10887;NABATAEAN LETTER HE;Lo;0;R;;;;;N;;;;; +10888;NABATAEAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10889;NABATAEAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +1088A;NABATAEAN LETTER HETH;Lo;0;R;;;;;N;;;;; +1088B;NABATAEAN LETTER TETH;Lo;0;R;;;;;N;;;;; +1088C;NABATAEAN LETTER FINAL YODH;Lo;0;R;;;;;N;;;;; +1088D;NABATAEAN LETTER YODH;Lo;0;R;;;;;N;;;;; +1088E;NABATAEAN LETTER FINAL KAPH;Lo;0;R;;;;;N;;;;; +1088F;NABATAEAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10890;NABATAEAN LETTER FINAL LAMEDH;Lo;0;R;;;;;N;;;;; +10891;NABATAEAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10892;NABATAEAN LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; +10893;NABATAEAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10894;NABATAEAN LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; +10895;NABATAEAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10896;NABATAEAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10897;NABATAEAN LETTER AYIN;Lo;0;R;;;;;N;;;;; +10898;NABATAEAN LETTER PE;Lo;0;R;;;;;N;;;;; +10899;NABATAEAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +1089A;NABATAEAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +1089B;NABATAEAN LETTER RESH;Lo;0;R;;;;;N;;;;; +1089C;NABATAEAN LETTER FINAL SHIN;Lo;0;R;;;;;N;;;;; +1089D;NABATAEAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +1089E;NABATAEAN LETTER TAW;Lo;0;R;;;;;N;;;;; +108A7;NABATAEAN NUMBER ONE;No;0;R;;;;1;N;;;;; +108A8;NABATAEAN NUMBER TWO;No;0;R;;;;2;N;;;;; +108A9;NABATAEAN NUMBER THREE;No;0;R;;;;3;N;;;;; +108AA;NABATAEAN NUMBER FOUR;No;0;R;;;;4;N;;;;; +108AB;NABATAEAN CRUCIFORM NUMBER FOUR;No;0;R;;;;4;N;;;;; +108AC;NABATAEAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +108AD;NABATAEAN NUMBER TEN;No;0;R;;;;10;N;;;;; +108AE;NABATAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +108AF;NABATAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +108E0;HATRAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +108E1;HATRAN LETTER BETH;Lo;0;R;;;;;N;;;;; +108E2;HATRAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +108E3;HATRAN LETTER DALETH-RESH;Lo;0;R;;;;;N;;;;; +108E4;HATRAN LETTER HE;Lo;0;R;;;;;N;;;;; +108E5;HATRAN LETTER WAW;Lo;0;R;;;;;N;;;;; +108E6;HATRAN LETTER ZAYN;Lo;0;R;;;;;N;;;;; +108E7;HATRAN LETTER HETH;Lo;0;R;;;;;N;;;;; +108E8;HATRAN LETTER TETH;Lo;0;R;;;;;N;;;;; +108E9;HATRAN LETTER YODH;Lo;0;R;;;;;N;;;;; +108EA;HATRAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +108EB;HATRAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +108EC;HATRAN LETTER MEM;Lo;0;R;;;;;N;;;;; +108ED;HATRAN LETTER NUN;Lo;0;R;;;;;N;;;;; +108EE;HATRAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +108EF;HATRAN LETTER AYN;Lo;0;R;;;;;N;;;;; +108F0;HATRAN LETTER PE;Lo;0;R;;;;;N;;;;; +108F1;HATRAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +108F2;HATRAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +108F4;HATRAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +108F5;HATRAN LETTER TAW;Lo;0;R;;;;;N;;;;; +108FB;HATRAN NUMBER ONE;No;0;R;;;;1;N;;;;; +108FC;HATRAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +108FD;HATRAN NUMBER TEN;No;0;R;;;;10;N;;;;; +108FE;HATRAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +108FF;HATRAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10900;PHOENICIAN LETTER ALF;Lo;0;R;;;;;N;;;;; +10901;PHOENICIAN LETTER BET;Lo;0;R;;;;;N;;;;; +10902;PHOENICIAN LETTER GAML;Lo;0;R;;;;;N;;;;; +10903;PHOENICIAN LETTER DELT;Lo;0;R;;;;;N;;;;; +10904;PHOENICIAN LETTER HE;Lo;0;R;;;;;N;;;;; +10905;PHOENICIAN LETTER WAU;Lo;0;R;;;;;N;;;;; +10906;PHOENICIAN LETTER ZAI;Lo;0;R;;;;;N;;;;; +10907;PHOENICIAN LETTER HET;Lo;0;R;;;;;N;;;;; +10908;PHOENICIAN LETTER TET;Lo;0;R;;;;;N;;;;; +10909;PHOENICIAN LETTER YOD;Lo;0;R;;;;;N;;;;; +1090A;PHOENICIAN LETTER KAF;Lo;0;R;;;;;N;;;;; +1090B;PHOENICIAN LETTER LAMD;Lo;0;R;;;;;N;;;;; +1090C;PHOENICIAN LETTER MEM;Lo;0;R;;;;;N;;;;; +1090D;PHOENICIAN LETTER NUN;Lo;0;R;;;;;N;;;;; +1090E;PHOENICIAN LETTER SEMK;Lo;0;R;;;;;N;;;;; +1090F;PHOENICIAN LETTER AIN;Lo;0;R;;;;;N;;;;; +10910;PHOENICIAN LETTER PE;Lo;0;R;;;;;N;;;;; +10911;PHOENICIAN LETTER SADE;Lo;0;R;;;;;N;;;;; +10912;PHOENICIAN LETTER QOF;Lo;0;R;;;;;N;;;;; +10913;PHOENICIAN LETTER ROSH;Lo;0;R;;;;;N;;;;; +10914;PHOENICIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10915;PHOENICIAN LETTER TAU;Lo;0;R;;;;;N;;;;; +10916;PHOENICIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10917;PHOENICIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10918;PHOENICIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10919;PHOENICIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +1091A;PHOENICIAN NUMBER TWO;No;0;R;;;;2;N;;;;; +1091B;PHOENICIAN NUMBER THREE;No;0;R;;;;3;N;;;;; +1091F;PHOENICIAN WORD SEPARATOR;Po;0;ON;;;;;N;;;;; +10920;LYDIAN LETTER A;Lo;0;R;;;;;N;;;;; +10921;LYDIAN LETTER B;Lo;0;R;;;;;N;;;;; +10922;LYDIAN LETTER G;Lo;0;R;;;;;N;;;;; +10923;LYDIAN LETTER D;Lo;0;R;;;;;N;;;;; +10924;LYDIAN LETTER E;Lo;0;R;;;;;N;;;;; +10925;LYDIAN LETTER V;Lo;0;R;;;;;N;;;;; +10926;LYDIAN LETTER I;Lo;0;R;;;;;N;;;;; +10927;LYDIAN LETTER Y;Lo;0;R;;;;;N;;;;; +10928;LYDIAN LETTER K;Lo;0;R;;;;;N;;;;; +10929;LYDIAN LETTER L;Lo;0;R;;;;;N;;;;; +1092A;LYDIAN LETTER M;Lo;0;R;;;;;N;;;;; +1092B;LYDIAN LETTER N;Lo;0;R;;;;;N;;;;; +1092C;LYDIAN LETTER O;Lo;0;R;;;;;N;;;;; +1092D;LYDIAN LETTER R;Lo;0;R;;;;;N;;;;; +1092E;LYDIAN LETTER SS;Lo;0;R;;;;;N;;;;; +1092F;LYDIAN LETTER T;Lo;0;R;;;;;N;;;;; +10930;LYDIAN LETTER U;Lo;0;R;;;;;N;;;;; +10931;LYDIAN LETTER F;Lo;0;R;;;;;N;;;;; +10932;LYDIAN LETTER Q;Lo;0;R;;;;;N;;;;; +10933;LYDIAN LETTER S;Lo;0;R;;;;;N;;;;; +10934;LYDIAN LETTER TT;Lo;0;R;;;;;N;;;;; +10935;LYDIAN LETTER AN;Lo;0;R;;;;;N;;;;; +10936;LYDIAN LETTER EN;Lo;0;R;;;;;N;;;;; +10937;LYDIAN LETTER LY;Lo;0;R;;;;;N;;;;; +10938;LYDIAN LETTER NN;Lo;0;R;;;;;N;;;;; +10939;LYDIAN LETTER C;Lo;0;R;;;;;N;;;;; +1093F;LYDIAN TRIANGULAR MARK;Po;0;R;;;;;N;;;;; +10980;MEROITIC HIEROGLYPHIC LETTER A;Lo;0;R;;;;;N;;;;; +10981;MEROITIC HIEROGLYPHIC LETTER E;Lo;0;R;;;;;N;;;;; +10982;MEROITIC HIEROGLYPHIC LETTER I;Lo;0;R;;;;;N;;;;; +10983;MEROITIC HIEROGLYPHIC LETTER O;Lo;0;R;;;;;N;;;;; +10984;MEROITIC HIEROGLYPHIC LETTER YA;Lo;0;R;;;;;N;;;;; +10985;MEROITIC HIEROGLYPHIC LETTER WA;Lo;0;R;;;;;N;;;;; +10986;MEROITIC HIEROGLYPHIC LETTER BA;Lo;0;R;;;;;N;;;;; +10987;MEROITIC HIEROGLYPHIC LETTER BA-2;Lo;0;R;;;;;N;;;;; +10988;MEROITIC HIEROGLYPHIC LETTER PA;Lo;0;R;;;;;N;;;;; +10989;MEROITIC HIEROGLYPHIC LETTER MA;Lo;0;R;;;;;N;;;;; +1098A;MEROITIC HIEROGLYPHIC LETTER NA;Lo;0;R;;;;;N;;;;; +1098B;MEROITIC HIEROGLYPHIC LETTER NA-2;Lo;0;R;;;;;N;;;;; +1098C;MEROITIC HIEROGLYPHIC LETTER NE;Lo;0;R;;;;;N;;;;; +1098D;MEROITIC HIEROGLYPHIC LETTER NE-2;Lo;0;R;;;;;N;;;;; +1098E;MEROITIC HIEROGLYPHIC LETTER RA;Lo;0;R;;;;;N;;;;; +1098F;MEROITIC HIEROGLYPHIC LETTER RA-2;Lo;0;R;;;;;N;;;;; +10990;MEROITIC HIEROGLYPHIC LETTER LA;Lo;0;R;;;;;N;;;;; +10991;MEROITIC HIEROGLYPHIC LETTER KHA;Lo;0;R;;;;;N;;;;; +10992;MEROITIC HIEROGLYPHIC LETTER HHA;Lo;0;R;;;;;N;;;;; +10993;MEROITIC HIEROGLYPHIC LETTER SA;Lo;0;R;;;;;N;;;;; +10994;MEROITIC HIEROGLYPHIC LETTER SA-2;Lo;0;R;;;;;N;;;;; +10995;MEROITIC HIEROGLYPHIC LETTER SE;Lo;0;R;;;;;N;;;;; +10996;MEROITIC HIEROGLYPHIC LETTER KA;Lo;0;R;;;;;N;;;;; +10997;MEROITIC HIEROGLYPHIC LETTER QA;Lo;0;R;;;;;N;;;;; +10998;MEROITIC HIEROGLYPHIC LETTER TA;Lo;0;R;;;;;N;;;;; +10999;MEROITIC HIEROGLYPHIC LETTER TA-2;Lo;0;R;;;;;N;;;;; +1099A;MEROITIC HIEROGLYPHIC LETTER TE;Lo;0;R;;;;;N;;;;; +1099B;MEROITIC HIEROGLYPHIC LETTER TE-2;Lo;0;R;;;;;N;;;;; +1099C;MEROITIC HIEROGLYPHIC LETTER TO;Lo;0;R;;;;;N;;;;; +1099D;MEROITIC HIEROGLYPHIC LETTER DA;Lo;0;R;;;;;N;;;;; +1099E;MEROITIC HIEROGLYPHIC SYMBOL VIDJ;Lo;0;R;;;;;N;;;;; +1099F;MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2;Lo;0;R;;;;;N;;;;; +109A0;MEROITIC CURSIVE LETTER A;Lo;0;R;;;;;N;;;;; +109A1;MEROITIC CURSIVE LETTER E;Lo;0;R;;;;;N;;;;; +109A2;MEROITIC CURSIVE LETTER I;Lo;0;R;;;;;N;;;;; +109A3;MEROITIC CURSIVE LETTER O;Lo;0;R;;;;;N;;;;; +109A4;MEROITIC CURSIVE LETTER YA;Lo;0;R;;;;;N;;;;; +109A5;MEROITIC CURSIVE LETTER WA;Lo;0;R;;;;;N;;;;; +109A6;MEROITIC CURSIVE LETTER BA;Lo;0;R;;;;;N;;;;; +109A7;MEROITIC CURSIVE LETTER PA;Lo;0;R;;;;;N;;;;; +109A8;MEROITIC CURSIVE LETTER MA;Lo;0;R;;;;;N;;;;; +109A9;MEROITIC CURSIVE LETTER NA;Lo;0;R;;;;;N;;;;; +109AA;MEROITIC CURSIVE LETTER NE;Lo;0;R;;;;;N;;;;; +109AB;MEROITIC CURSIVE LETTER RA;Lo;0;R;;;;;N;;;;; +109AC;MEROITIC CURSIVE LETTER LA;Lo;0;R;;;;;N;;;;; +109AD;MEROITIC CURSIVE LETTER KHA;Lo;0;R;;;;;N;;;;; +109AE;MEROITIC CURSIVE LETTER HHA;Lo;0;R;;;;;N;;;;; +109AF;MEROITIC CURSIVE LETTER SA;Lo;0;R;;;;;N;;;;; +109B0;MEROITIC CURSIVE LETTER ARCHAIC SA;Lo;0;R;;;;;N;;;;; +109B1;MEROITIC CURSIVE LETTER SE;Lo;0;R;;;;;N;;;;; +109B2;MEROITIC CURSIVE LETTER KA;Lo;0;R;;;;;N;;;;; +109B3;MEROITIC CURSIVE LETTER QA;Lo;0;R;;;;;N;;;;; +109B4;MEROITIC CURSIVE LETTER TA;Lo;0;R;;;;;N;;;;; +109B5;MEROITIC CURSIVE LETTER TE;Lo;0;R;;;;;N;;;;; +109B6;MEROITIC CURSIVE LETTER TO;Lo;0;R;;;;;N;;;;; +109B7;MEROITIC CURSIVE LETTER DA;Lo;0;R;;;;;N;;;;; +109BC;MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS;No;0;R;;;;11/12;N;;;;; +109BD;MEROITIC CURSIVE FRACTION ONE HALF;No;0;R;;;;1/2;N;;;;; +109BE;MEROITIC CURSIVE LOGOGRAM RMT;Lo;0;R;;;;;N;;;;; +109BF;MEROITIC CURSIVE LOGOGRAM IMN;Lo;0;R;;;;;N;;;;; +109C0;MEROITIC CURSIVE NUMBER ONE;No;0;R;;;;1;N;;;;; +109C1;MEROITIC CURSIVE NUMBER TWO;No;0;R;;;;2;N;;;;; +109C2;MEROITIC CURSIVE NUMBER THREE;No;0;R;;;;3;N;;;;; +109C3;MEROITIC CURSIVE NUMBER FOUR;No;0;R;;;;4;N;;;;; +109C4;MEROITIC CURSIVE NUMBER FIVE;No;0;R;;;;5;N;;;;; +109C5;MEROITIC CURSIVE NUMBER SIX;No;0;R;;;;6;N;;;;; +109C6;MEROITIC CURSIVE NUMBER SEVEN;No;0;R;;;;7;N;;;;; +109C7;MEROITIC CURSIVE NUMBER EIGHT;No;0;R;;;;8;N;;;;; +109C8;MEROITIC CURSIVE NUMBER NINE;No;0;R;;;;9;N;;;;; +109C9;MEROITIC CURSIVE NUMBER TEN;No;0;R;;;;10;N;;;;; +109CA;MEROITIC CURSIVE NUMBER TWENTY;No;0;R;;;;20;N;;;;; +109CB;MEROITIC CURSIVE NUMBER THIRTY;No;0;R;;;;30;N;;;;; +109CC;MEROITIC CURSIVE NUMBER FORTY;No;0;R;;;;40;N;;;;; +109CD;MEROITIC CURSIVE NUMBER FIFTY;No;0;R;;;;50;N;;;;; +109CE;MEROITIC CURSIVE NUMBER SIXTY;No;0;R;;;;60;N;;;;; +109CF;MEROITIC CURSIVE NUMBER SEVENTY;No;0;R;;;;70;N;;;;; +109D2;MEROITIC CURSIVE NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +109D3;MEROITIC CURSIVE NUMBER TWO HUNDRED;No;0;R;;;;200;N;;;;; +109D4;MEROITIC CURSIVE NUMBER THREE HUNDRED;No;0;R;;;;300;N;;;;; +109D5;MEROITIC CURSIVE NUMBER FOUR HUNDRED;No;0;R;;;;400;N;;;;; +109D6;MEROITIC CURSIVE NUMBER FIVE HUNDRED;No;0;R;;;;500;N;;;;; +109D7;MEROITIC CURSIVE NUMBER SIX HUNDRED;No;0;R;;;;600;N;;;;; +109D8;MEROITIC CURSIVE NUMBER SEVEN HUNDRED;No;0;R;;;;700;N;;;;; +109D9;MEROITIC CURSIVE NUMBER EIGHT HUNDRED;No;0;R;;;;800;N;;;;; +109DA;MEROITIC CURSIVE NUMBER NINE HUNDRED;No;0;R;;;;900;N;;;;; +109DB;MEROITIC CURSIVE NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +109DC;MEROITIC CURSIVE NUMBER TWO THOUSAND;No;0;R;;;;2000;N;;;;; +109DD;MEROITIC CURSIVE NUMBER THREE THOUSAND;No;0;R;;;;3000;N;;;;; +109DE;MEROITIC CURSIVE NUMBER FOUR THOUSAND;No;0;R;;;;4000;N;;;;; +109DF;MEROITIC CURSIVE NUMBER FIVE THOUSAND;No;0;R;;;;5000;N;;;;; +109E0;MEROITIC CURSIVE NUMBER SIX THOUSAND;No;0;R;;;;6000;N;;;;; +109E1;MEROITIC CURSIVE NUMBER SEVEN THOUSAND;No;0;R;;;;7000;N;;;;; +109E2;MEROITIC CURSIVE NUMBER EIGHT THOUSAND;No;0;R;;;;8000;N;;;;; +109E3;MEROITIC CURSIVE NUMBER NINE THOUSAND;No;0;R;;;;9000;N;;;;; +109E4;MEROITIC CURSIVE NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;; +109E5;MEROITIC CURSIVE NUMBER TWENTY THOUSAND;No;0;R;;;;20000;N;;;;; +109E6;MEROITIC CURSIVE NUMBER THIRTY THOUSAND;No;0;R;;;;30000;N;;;;; +109E7;MEROITIC CURSIVE NUMBER FORTY THOUSAND;No;0;R;;;;40000;N;;;;; +109E8;MEROITIC CURSIVE NUMBER FIFTY THOUSAND;No;0;R;;;;50000;N;;;;; +109E9;MEROITIC CURSIVE NUMBER SIXTY THOUSAND;No;0;R;;;;60000;N;;;;; +109EA;MEROITIC CURSIVE NUMBER SEVENTY THOUSAND;No;0;R;;;;70000;N;;;;; +109EB;MEROITIC CURSIVE NUMBER EIGHTY THOUSAND;No;0;R;;;;80000;N;;;;; +109EC;MEROITIC CURSIVE NUMBER NINETY THOUSAND;No;0;R;;;;90000;N;;;;; +109ED;MEROITIC CURSIVE NUMBER ONE HUNDRED THOUSAND;No;0;R;;;;100000;N;;;;; +109EE;MEROITIC CURSIVE NUMBER TWO HUNDRED THOUSAND;No;0;R;;;;200000;N;;;;; +109EF;MEROITIC CURSIVE NUMBER THREE HUNDRED THOUSAND;No;0;R;;;;300000;N;;;;; +109F0;MEROITIC CURSIVE NUMBER FOUR HUNDRED THOUSAND;No;0;R;;;;400000;N;;;;; +109F1;MEROITIC CURSIVE NUMBER FIVE HUNDRED THOUSAND;No;0;R;;;;500000;N;;;;; +109F2;MEROITIC CURSIVE NUMBER SIX HUNDRED THOUSAND;No;0;R;;;;600000;N;;;;; +109F3;MEROITIC CURSIVE NUMBER SEVEN HUNDRED THOUSAND;No;0;R;;;;700000;N;;;;; +109F4;MEROITIC CURSIVE NUMBER EIGHT HUNDRED THOUSAND;No;0;R;;;;800000;N;;;;; +109F5;MEROITIC CURSIVE NUMBER NINE HUNDRED THOUSAND;No;0;R;;;;900000;N;;;;; +109F6;MEROITIC CURSIVE FRACTION ONE TWELFTH;No;0;R;;;;1/12;N;;;;; +109F7;MEROITIC CURSIVE FRACTION TWO TWELFTHS;No;0;R;;;;2/12;N;;;;; +109F8;MEROITIC CURSIVE FRACTION THREE TWELFTHS;No;0;R;;;;3/12;N;;;;; +109F9;MEROITIC CURSIVE FRACTION FOUR TWELFTHS;No;0;R;;;;4/12;N;;;;; +109FA;MEROITIC CURSIVE FRACTION FIVE TWELFTHS;No;0;R;;;;5/12;N;;;;; +109FB;MEROITIC CURSIVE FRACTION SIX TWELFTHS;No;0;R;;;;6/12;N;;;;; +109FC;MEROITIC CURSIVE FRACTION SEVEN TWELFTHS;No;0;R;;;;7/12;N;;;;; +109FD;MEROITIC CURSIVE FRACTION EIGHT TWELFTHS;No;0;R;;;;8/12;N;;;;; +109FE;MEROITIC CURSIVE FRACTION NINE TWELFTHS;No;0;R;;;;9/12;N;;;;; +109FF;MEROITIC CURSIVE FRACTION TEN TWELFTHS;No;0;R;;;;10/12;N;;;;; +10A00;KHAROSHTHI LETTER A;Lo;0;R;;;;;N;;;;; +10A01;KHAROSHTHI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +10A02;KHAROSHTHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +10A03;KHAROSHTHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +10A05;KHAROSHTHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +10A06;KHAROSHTHI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +10A0C;KHAROSHTHI VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +10A0D;KHAROSHTHI SIGN DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; +10A0E;KHAROSHTHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +10A0F;KHAROSHTHI SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; +10A10;KHAROSHTHI LETTER KA;Lo;0;R;;;;;N;;;;; +10A11;KHAROSHTHI LETTER KHA;Lo;0;R;;;;;N;;;;; +10A12;KHAROSHTHI LETTER GA;Lo;0;R;;;;;N;;;;; +10A13;KHAROSHTHI LETTER GHA;Lo;0;R;;;;;N;;;;; +10A15;KHAROSHTHI LETTER CA;Lo;0;R;;;;;N;;;;; +10A16;KHAROSHTHI LETTER CHA;Lo;0;R;;;;;N;;;;; +10A17;KHAROSHTHI LETTER JA;Lo;0;R;;;;;N;;;;; +10A19;KHAROSHTHI LETTER NYA;Lo;0;R;;;;;N;;;;; +10A1A;KHAROSHTHI LETTER TTA;Lo;0;R;;;;;N;;;;; +10A1B;KHAROSHTHI LETTER TTHA;Lo;0;R;;;;;N;;;;; +10A1C;KHAROSHTHI LETTER DDA;Lo;0;R;;;;;N;;;;; +10A1D;KHAROSHTHI LETTER DDHA;Lo;0;R;;;;;N;;;;; +10A1E;KHAROSHTHI LETTER NNA;Lo;0;R;;;;;N;;;;; +10A1F;KHAROSHTHI LETTER TA;Lo;0;R;;;;;N;;;;; +10A20;KHAROSHTHI LETTER THA;Lo;0;R;;;;;N;;;;; +10A21;KHAROSHTHI LETTER DA;Lo;0;R;;;;;N;;;;; +10A22;KHAROSHTHI LETTER DHA;Lo;0;R;;;;;N;;;;; +10A23;KHAROSHTHI LETTER NA;Lo;0;R;;;;;N;;;;; +10A24;KHAROSHTHI LETTER PA;Lo;0;R;;;;;N;;;;; +10A25;KHAROSHTHI LETTER PHA;Lo;0;R;;;;;N;;;;; +10A26;KHAROSHTHI LETTER BA;Lo;0;R;;;;;N;;;;; +10A27;KHAROSHTHI LETTER BHA;Lo;0;R;;;;;N;;;;; +10A28;KHAROSHTHI LETTER MA;Lo;0;R;;;;;N;;;;; +10A29;KHAROSHTHI LETTER YA;Lo;0;R;;;;;N;;;;; +10A2A;KHAROSHTHI LETTER RA;Lo;0;R;;;;;N;;;;; +10A2B;KHAROSHTHI LETTER LA;Lo;0;R;;;;;N;;;;; +10A2C;KHAROSHTHI LETTER VA;Lo;0;R;;;;;N;;;;; +10A2D;KHAROSHTHI LETTER SHA;Lo;0;R;;;;;N;;;;; +10A2E;KHAROSHTHI LETTER SSA;Lo;0;R;;;;;N;;;;; +10A2F;KHAROSHTHI LETTER SA;Lo;0;R;;;;;N;;;;; +10A30;KHAROSHTHI LETTER ZA;Lo;0;R;;;;;N;;;;; +10A31;KHAROSHTHI LETTER HA;Lo;0;R;;;;;N;;;;; +10A32;KHAROSHTHI LETTER KKA;Lo;0;R;;;;;N;;;;; +10A33;KHAROSHTHI LETTER TTTHA;Lo;0;R;;;;;N;;;;; +10A38;KHAROSHTHI SIGN BAR ABOVE;Mn;230;NSM;;;;;N;;;;; +10A39;KHAROSHTHI SIGN CAUDA;Mn;1;NSM;;;;;N;;;;; +10A3A;KHAROSHTHI SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; +10A3F;KHAROSHTHI VIRAMA;Mn;9;NSM;;;;;N;;;;; +10A40;KHAROSHTHI DIGIT ONE;No;0;R;;;1;1;N;;;;; +10A41;KHAROSHTHI DIGIT TWO;No;0;R;;;2;2;N;;;;; +10A42;KHAROSHTHI DIGIT THREE;No;0;R;;;3;3;N;;;;; +10A43;KHAROSHTHI DIGIT FOUR;No;0;R;;;4;4;N;;;;; +10A44;KHAROSHTHI NUMBER TEN;No;0;R;;;;10;N;;;;; +10A45;KHAROSHTHI NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10A46;KHAROSHTHI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10A47;KHAROSHTHI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +10A50;KHAROSHTHI PUNCTUATION DOT;Po;0;R;;;;;N;;;;; +10A51;KHAROSHTHI PUNCTUATION SMALL CIRCLE;Po;0;R;;;;;N;;;;; +10A52;KHAROSHTHI PUNCTUATION CIRCLE;Po;0;R;;;;;N;;;;; +10A53;KHAROSHTHI PUNCTUATION CRESCENT BAR;Po;0;R;;;;;N;;;;; +10A54;KHAROSHTHI PUNCTUATION MANGALAM;Po;0;R;;;;;N;;;;; +10A55;KHAROSHTHI PUNCTUATION LOTUS;Po;0;R;;;;;N;;;;; +10A56;KHAROSHTHI PUNCTUATION DANDA;Po;0;R;;;;;N;;;;; +10A57;KHAROSHTHI PUNCTUATION DOUBLE DANDA;Po;0;R;;;;;N;;;;; +10A58;KHAROSHTHI PUNCTUATION LINES;Po;0;R;;;;;N;;;;; +10A60;OLD SOUTH ARABIAN LETTER HE;Lo;0;R;;;;;N;;;;; +10A61;OLD SOUTH ARABIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10A62;OLD SOUTH ARABIAN LETTER HETH;Lo;0;R;;;;;N;;;;; +10A63;OLD SOUTH ARABIAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10A64;OLD SOUTH ARABIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +10A65;OLD SOUTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10A66;OLD SOUTH ARABIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10A67;OLD SOUTH ARABIAN LETTER RESH;Lo;0;R;;;;;N;;;;; +10A68;OLD SOUTH ARABIAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10A69;OLD SOUTH ARABIAN LETTER TAW;Lo;0;R;;;;;N;;;;; +10A6A;OLD SOUTH ARABIAN LETTER SAT;Lo;0;R;;;;;N;;;;; +10A6B;OLD SOUTH ARABIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10A6C;OLD SOUTH ARABIAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10A6D;OLD SOUTH ARABIAN LETTER KHETH;Lo;0;R;;;;;N;;;;; +10A6E;OLD SOUTH ARABIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +10A6F;OLD SOUTH ARABIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10A70;OLD SOUTH ARABIAN LETTER FE;Lo;0;R;;;;;N;;;;; +10A71;OLD SOUTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; +10A72;OLD SOUTH ARABIAN LETTER AYN;Lo;0;R;;;;;N;;;;; +10A73;OLD SOUTH ARABIAN LETTER DHADHE;Lo;0;R;;;;;N;;;;; +10A74;OLD SOUTH ARABIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10A75;OLD SOUTH ARABIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10A76;OLD SOUTH ARABIAN LETTER GHAYN;Lo;0;R;;;;;N;;;;; +10A77;OLD SOUTH ARABIAN LETTER TETH;Lo;0;R;;;;;N;;;;; +10A78;OLD SOUTH ARABIAN LETTER ZAYN;Lo;0;R;;;;;N;;;;; +10A79;OLD SOUTH ARABIAN LETTER DHALETH;Lo;0;R;;;;;N;;;;; +10A7A;OLD SOUTH ARABIAN LETTER YODH;Lo;0;R;;;;;N;;;;; +10A7B;OLD SOUTH ARABIAN LETTER THAW;Lo;0;R;;;;;N;;;;; +10A7C;OLD SOUTH ARABIAN LETTER THETH;Lo;0;R;;;;;N;;;;; +10A7D;OLD SOUTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10A7E;OLD SOUTH ARABIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;; +10A7F;OLD SOUTH ARABIAN NUMERIC INDICATOR;Po;0;R;;;;;N;;;;; +10A80;OLD NORTH ARABIAN LETTER HEH;Lo;0;R;;;;;N;;;;; +10A81;OLD NORTH ARABIAN LETTER LAM;Lo;0;R;;;;;N;;;;; +10A82;OLD NORTH ARABIAN LETTER HAH;Lo;0;R;;;;;N;;;;; +10A83;OLD NORTH ARABIAN LETTER MEEM;Lo;0;R;;;;;N;;;;; +10A84;OLD NORTH ARABIAN LETTER QAF;Lo;0;R;;;;;N;;;;; +10A85;OLD NORTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10A86;OLD NORTH ARABIAN LETTER ES-2;Lo;0;R;;;;;N;;;;; +10A87;OLD NORTH ARABIAN LETTER REH;Lo;0;R;;;;;N;;;;; +10A88;OLD NORTH ARABIAN LETTER BEH;Lo;0;R;;;;;N;;;;; +10A89;OLD NORTH ARABIAN LETTER TEH;Lo;0;R;;;;;N;;;;; +10A8A;OLD NORTH ARABIAN LETTER ES-1;Lo;0;R;;;;;N;;;;; +10A8B;OLD NORTH ARABIAN LETTER KAF;Lo;0;R;;;;;N;;;;; +10A8C;OLD NORTH ARABIAN LETTER NOON;Lo;0;R;;;;;N;;;;; +10A8D;OLD NORTH ARABIAN LETTER KHAH;Lo;0;R;;;;;N;;;;; +10A8E;OLD NORTH ARABIAN LETTER SAD;Lo;0;R;;;;;N;;;;; +10A8F;OLD NORTH ARABIAN LETTER ES-3;Lo;0;R;;;;;N;;;;; +10A90;OLD NORTH ARABIAN LETTER FEH;Lo;0;R;;;;;N;;;;; +10A91;OLD NORTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; +10A92;OLD NORTH ARABIAN LETTER AIN;Lo;0;R;;;;;N;;;;; +10A93;OLD NORTH ARABIAN LETTER DAD;Lo;0;R;;;;;N;;;;; +10A94;OLD NORTH ARABIAN LETTER GEEM;Lo;0;R;;;;;N;;;;; +10A95;OLD NORTH ARABIAN LETTER DAL;Lo;0;R;;;;;N;;;;; +10A96;OLD NORTH ARABIAN LETTER GHAIN;Lo;0;R;;;;;N;;;;; +10A97;OLD NORTH ARABIAN LETTER TAH;Lo;0;R;;;;;N;;;;; +10A98;OLD NORTH ARABIAN LETTER ZAIN;Lo;0;R;;;;;N;;;;; +10A99;OLD NORTH ARABIAN LETTER THAL;Lo;0;R;;;;;N;;;;; +10A9A;OLD NORTH ARABIAN LETTER YEH;Lo;0;R;;;;;N;;;;; +10A9B;OLD NORTH ARABIAN LETTER THEH;Lo;0;R;;;;;N;;;;; +10A9C;OLD NORTH ARABIAN LETTER ZAH;Lo;0;R;;;;;N;;;;; +10A9D;OLD NORTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10A9E;OLD NORTH ARABIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10A9F;OLD NORTH ARABIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10AC0;MANICHAEAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10AC1;MANICHAEAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10AC2;MANICHAEAN LETTER BHETH;Lo;0;R;;;;;N;;;;; +10AC3;MANICHAEAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10AC4;MANICHAEAN LETTER GHIMEL;Lo;0;R;;;;;N;;;;; +10AC5;MANICHAEAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10AC6;MANICHAEAN LETTER HE;Lo;0;R;;;;;N;;;;; +10AC7;MANICHAEAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10AC8;MANICHAEAN SIGN UD;So;0;R;;;;;N;;;;; +10AC9;MANICHAEAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10ACA;MANICHAEAN LETTER ZHAYIN;Lo;0;R;;;;;N;;;;; +10ACB;MANICHAEAN LETTER JAYIN;Lo;0;R;;;;;N;;;;; +10ACC;MANICHAEAN LETTER JHAYIN;Lo;0;R;;;;;N;;;;; +10ACD;MANICHAEAN LETTER HETH;Lo;0;R;;;;;N;;;;; +10ACE;MANICHAEAN LETTER TETH;Lo;0;R;;;;;N;;;;; +10ACF;MANICHAEAN LETTER YODH;Lo;0;R;;;;;N;;;;; +10AD0;MANICHAEAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10AD1;MANICHAEAN LETTER XAPH;Lo;0;R;;;;;N;;;;; +10AD2;MANICHAEAN LETTER KHAPH;Lo;0;R;;;;;N;;;;; +10AD3;MANICHAEAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10AD4;MANICHAEAN LETTER DHAMEDH;Lo;0;R;;;;;N;;;;; +10AD5;MANICHAEAN LETTER THAMEDH;Lo;0;R;;;;;N;;;;; +10AD6;MANICHAEAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10AD7;MANICHAEAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10AD8;MANICHAEAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10AD9;MANICHAEAN LETTER AYIN;Lo;0;R;;;;;N;;;;; +10ADA;MANICHAEAN LETTER AAYIN;Lo;0;R;;;;;N;;;;; +10ADB;MANICHAEAN LETTER PE;Lo;0;R;;;;;N;;;;; +10ADC;MANICHAEAN LETTER FE;Lo;0;R;;;;;N;;;;; +10ADD;MANICHAEAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +10ADE;MANICHAEAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +10ADF;MANICHAEAN LETTER XOPH;Lo;0;R;;;;;N;;;;; +10AE0;MANICHAEAN LETTER QHOPH;Lo;0;R;;;;;N;;;;; +10AE1;MANICHAEAN LETTER RESH;Lo;0;R;;;;;N;;;;; +10AE2;MANICHAEAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10AE3;MANICHAEAN LETTER SSHIN;Lo;0;R;;;;;N;;;;; +10AE4;MANICHAEAN LETTER TAW;Lo;0;R;;;;;N;;;;; +10AE5;MANICHAEAN ABBREVIATION MARK ABOVE;Mn;230;NSM;;;;;N;;;;; +10AE6;MANICHAEAN ABBREVIATION MARK BELOW;Mn;220;NSM;;;;;N;;;;; +10AEB;MANICHAEAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10AEC;MANICHAEAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +10AED;MANICHAEAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10AEE;MANICHAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10AEF;MANICHAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10AF0;MANICHAEAN PUNCTUATION STAR;Po;0;R;;;;;N;;;;; +10AF1;MANICHAEAN PUNCTUATION FLEURON;Po;0;R;;;;;N;;;;; +10AF2;MANICHAEAN PUNCTUATION DOUBLE DOT WITHIN DOT;Po;0;R;;;;;N;;;;; +10AF3;MANICHAEAN PUNCTUATION DOT WITHIN DOT;Po;0;R;;;;;N;;;;; +10AF4;MANICHAEAN PUNCTUATION DOT;Po;0;R;;;;;N;;;;; +10AF5;MANICHAEAN PUNCTUATION TWO DOTS;Po;0;R;;;;;N;;;;; +10AF6;MANICHAEAN PUNCTUATION LINE FILLER;Po;0;R;;;;;N;;;;; +10B00;AVESTAN LETTER A;Lo;0;R;;;;;N;;;;; +10B01;AVESTAN LETTER AA;Lo;0;R;;;;;N;;;;; +10B02;AVESTAN LETTER AO;Lo;0;R;;;;;N;;;;; +10B03;AVESTAN LETTER AAO;Lo;0;R;;;;;N;;;;; +10B04;AVESTAN LETTER AN;Lo;0;R;;;;;N;;;;; +10B05;AVESTAN LETTER AAN;Lo;0;R;;;;;N;;;;; +10B06;AVESTAN LETTER AE;Lo;0;R;;;;;N;;;;; +10B07;AVESTAN LETTER AEE;Lo;0;R;;;;;N;;;;; +10B08;AVESTAN LETTER E;Lo;0;R;;;;;N;;;;; +10B09;AVESTAN LETTER EE;Lo;0;R;;;;;N;;;;; +10B0A;AVESTAN LETTER O;Lo;0;R;;;;;N;;;;; +10B0B;AVESTAN LETTER OO;Lo;0;R;;;;;N;;;;; +10B0C;AVESTAN LETTER I;Lo;0;R;;;;;N;;;;; +10B0D;AVESTAN LETTER II;Lo;0;R;;;;;N;;;;; +10B0E;AVESTAN LETTER U;Lo;0;R;;;;;N;;;;; +10B0F;AVESTAN LETTER UU;Lo;0;R;;;;;N;;;;; +10B10;AVESTAN LETTER KE;Lo;0;R;;;;;N;;;;; +10B11;AVESTAN LETTER XE;Lo;0;R;;;;;N;;;;; +10B12;AVESTAN LETTER XYE;Lo;0;R;;;;;N;;;;; +10B13;AVESTAN LETTER XVE;Lo;0;R;;;;;N;;;;; +10B14;AVESTAN LETTER GE;Lo;0;R;;;;;N;;;;; +10B15;AVESTAN LETTER GGE;Lo;0;R;;;;;N;;;;; +10B16;AVESTAN LETTER GHE;Lo;0;R;;;;;N;;;;; +10B17;AVESTAN LETTER CE;Lo;0;R;;;;;N;;;;; +10B18;AVESTAN LETTER JE;Lo;0;R;;;;;N;;;;; +10B19;AVESTAN LETTER TE;Lo;0;R;;;;;N;;;;; +10B1A;AVESTAN LETTER THE;Lo;0;R;;;;;N;;;;; +10B1B;AVESTAN LETTER DE;Lo;0;R;;;;;N;;;;; +10B1C;AVESTAN LETTER DHE;Lo;0;R;;;;;N;;;;; +10B1D;AVESTAN LETTER TTE;Lo;0;R;;;;;N;;;;; +10B1E;AVESTAN LETTER PE;Lo;0;R;;;;;N;;;;; +10B1F;AVESTAN LETTER FE;Lo;0;R;;;;;N;;;;; +10B20;AVESTAN LETTER BE;Lo;0;R;;;;;N;;;;; +10B21;AVESTAN LETTER BHE;Lo;0;R;;;;;N;;;;; +10B22;AVESTAN LETTER NGE;Lo;0;R;;;;;N;;;;; +10B23;AVESTAN LETTER NGYE;Lo;0;R;;;;;N;;;;; +10B24;AVESTAN LETTER NGVE;Lo;0;R;;;;;N;;;;; +10B25;AVESTAN LETTER NE;Lo;0;R;;;;;N;;;;; +10B26;AVESTAN LETTER NYE;Lo;0;R;;;;;N;;;;; +10B27;AVESTAN LETTER NNE;Lo;0;R;;;;;N;;;;; +10B28;AVESTAN LETTER ME;Lo;0;R;;;;;N;;;;; +10B29;AVESTAN LETTER HME;Lo;0;R;;;;;N;;;;; +10B2A;AVESTAN LETTER YYE;Lo;0;R;;;;;N;;;;; +10B2B;AVESTAN LETTER YE;Lo;0;R;;;;;N;;;;; +10B2C;AVESTAN LETTER VE;Lo;0;R;;;;;N;;;;; +10B2D;AVESTAN LETTER RE;Lo;0;R;;;;;N;;;;; +10B2E;AVESTAN LETTER LE;Lo;0;R;;;;;N;;;;; +10B2F;AVESTAN LETTER SE;Lo;0;R;;;;;N;;;;; +10B30;AVESTAN LETTER ZE;Lo;0;R;;;;;N;;;;; +10B31;AVESTAN LETTER SHE;Lo;0;R;;;;;N;;;;; +10B32;AVESTAN LETTER ZHE;Lo;0;R;;;;;N;;;;; +10B33;AVESTAN LETTER SHYE;Lo;0;R;;;;;N;;;;; +10B34;AVESTAN LETTER SSHE;Lo;0;R;;;;;N;;;;; +10B35;AVESTAN LETTER HE;Lo;0;R;;;;;N;;;;; +10B39;AVESTAN ABBREVIATION MARK;Po;0;ON;;;;;N;;;;; +10B3A;TINY TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3B;SMALL TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3C;LARGE TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3D;LARGE ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3E;LARGE TWO RINGS OVER ONE RING PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3F;LARGE ONE RING OVER TWO RINGS PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B40;INSCRIPTIONAL PARTHIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10B41;INSCRIPTIONAL PARTHIAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10B42;INSCRIPTIONAL PARTHIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10B43;INSCRIPTIONAL PARTHIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10B44;INSCRIPTIONAL PARTHIAN LETTER HE;Lo;0;R;;;;;N;;;;; +10B45;INSCRIPTIONAL PARTHIAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10B46;INSCRIPTIONAL PARTHIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10B47;INSCRIPTIONAL PARTHIAN LETTER HETH;Lo;0;R;;;;;N;;;;; +10B48;INSCRIPTIONAL PARTHIAN LETTER TETH;Lo;0;R;;;;;N;;;;; +10B49;INSCRIPTIONAL PARTHIAN LETTER YODH;Lo;0;R;;;;;N;;;;; +10B4A;INSCRIPTIONAL PARTHIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10B4B;INSCRIPTIONAL PARTHIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10B4C;INSCRIPTIONAL PARTHIAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10B4D;INSCRIPTIONAL PARTHIAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10B4E;INSCRIPTIONAL PARTHIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10B4F;INSCRIPTIONAL PARTHIAN LETTER AYIN;Lo;0;R;;;;;N;;;;; +10B50;INSCRIPTIONAL PARTHIAN LETTER PE;Lo;0;R;;;;;N;;;;; +10B51;INSCRIPTIONAL PARTHIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +10B52;INSCRIPTIONAL PARTHIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +10B53;INSCRIPTIONAL PARTHIAN LETTER RESH;Lo;0;R;;;;;N;;;;; +10B54;INSCRIPTIONAL PARTHIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10B55;INSCRIPTIONAL PARTHIAN LETTER TAW;Lo;0;R;;;;;N;;;;; +10B58;INSCRIPTIONAL PARTHIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10B59;INSCRIPTIONAL PARTHIAN NUMBER TWO;No;0;R;;;;2;N;;;;; +10B5A;INSCRIPTIONAL PARTHIAN NUMBER THREE;No;0;R;;;;3;N;;;;; +10B5B;INSCRIPTIONAL PARTHIAN NUMBER FOUR;No;0;R;;;;4;N;;;;; +10B5C;INSCRIPTIONAL PARTHIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10B5D;INSCRIPTIONAL PARTHIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10B5E;INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10B5F;INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +10B60;INSCRIPTIONAL PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10B61;INSCRIPTIONAL PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; +10B62;INSCRIPTIONAL PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10B63;INSCRIPTIONAL PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; +10B64;INSCRIPTIONAL PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; +10B65;INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; +10B66;INSCRIPTIONAL PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10B67;INSCRIPTIONAL PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; +10B68;INSCRIPTIONAL PAHLAVI LETTER TETH;Lo;0;R;;;;;N;;;;; +10B69;INSCRIPTIONAL PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; +10B6A;INSCRIPTIONAL PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; +10B6B;INSCRIPTIONAL PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10B6C;INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; +10B6D;INSCRIPTIONAL PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; +10B6E;INSCRIPTIONAL PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10B6F;INSCRIPTIONAL PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; +10B70;INSCRIPTIONAL PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; +10B71;INSCRIPTIONAL PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; +10B72;INSCRIPTIONAL PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; +10B78;INSCRIPTIONAL PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; +10B79;INSCRIPTIONAL PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; +10B7A;INSCRIPTIONAL PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; +10B7B;INSCRIPTIONAL PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; +10B7C;INSCRIPTIONAL PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; +10B7D;INSCRIPTIONAL PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10B7E;INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10B7F;INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +10B80;PSALTER PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10B81;PSALTER PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; +10B82;PSALTER PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10B83;PSALTER PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; +10B84;PSALTER PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; +10B85;PSALTER PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; +10B86;PSALTER PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10B87;PSALTER PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; +10B88;PSALTER PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; +10B89;PSALTER PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; +10B8A;PSALTER PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10B8B;PSALTER PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; +10B8C;PSALTER PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; +10B8D;PSALTER PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10B8E;PSALTER PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; +10B8F;PSALTER PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; +10B90;PSALTER PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; +10B91;PSALTER PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; +10B99;PSALTER PAHLAVI SECTION MARK;Po;0;R;;;;;N;;;;; +10B9A;PSALTER PAHLAVI TURNED SECTION MARK;Po;0;R;;;;;N;;;;; +10B9B;PSALTER PAHLAVI FOUR DOTS WITH CROSS;Po;0;R;;;;;N;;;;; +10B9C;PSALTER PAHLAVI FOUR DOTS WITH DOT;Po;0;R;;;;;N;;;;; +10BA9;PSALTER PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; +10BAA;PSALTER PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; +10BAB;PSALTER PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; +10BAC;PSALTER PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; +10BAD;PSALTER PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; +10BAE;PSALTER PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10BAF;PSALTER PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10C00;OLD TURKIC LETTER ORKHON A;Lo;0;R;;;;;N;;;;; +10C01;OLD TURKIC LETTER YENISEI A;Lo;0;R;;;;;N;;;;; +10C02;OLD TURKIC LETTER YENISEI AE;Lo;0;R;;;;;N;;;;; +10C03;OLD TURKIC LETTER ORKHON I;Lo;0;R;;;;;N;;;;; +10C04;OLD TURKIC LETTER YENISEI I;Lo;0;R;;;;;N;;;;; +10C05;OLD TURKIC LETTER YENISEI E;Lo;0;R;;;;;N;;;;; +10C06;OLD TURKIC LETTER ORKHON O;Lo;0;R;;;;;N;;;;; +10C07;OLD TURKIC LETTER ORKHON OE;Lo;0;R;;;;;N;;;;; +10C08;OLD TURKIC LETTER YENISEI OE;Lo;0;R;;;;;N;;;;; +10C09;OLD TURKIC LETTER ORKHON AB;Lo;0;R;;;;;N;;;;; +10C0A;OLD TURKIC LETTER YENISEI AB;Lo;0;R;;;;;N;;;;; +10C0B;OLD TURKIC LETTER ORKHON AEB;Lo;0;R;;;;;N;;;;; +10C0C;OLD TURKIC LETTER YENISEI AEB;Lo;0;R;;;;;N;;;;; +10C0D;OLD TURKIC LETTER ORKHON AG;Lo;0;R;;;;;N;;;;; +10C0E;OLD TURKIC LETTER YENISEI AG;Lo;0;R;;;;;N;;;;; +10C0F;OLD TURKIC LETTER ORKHON AEG;Lo;0;R;;;;;N;;;;; +10C10;OLD TURKIC LETTER YENISEI AEG;Lo;0;R;;;;;N;;;;; +10C11;OLD TURKIC LETTER ORKHON AD;Lo;0;R;;;;;N;;;;; +10C12;OLD TURKIC LETTER YENISEI AD;Lo;0;R;;;;;N;;;;; +10C13;OLD TURKIC LETTER ORKHON AED;Lo;0;R;;;;;N;;;;; +10C14;OLD TURKIC LETTER ORKHON EZ;Lo;0;R;;;;;N;;;;; +10C15;OLD TURKIC LETTER YENISEI EZ;Lo;0;R;;;;;N;;;;; +10C16;OLD TURKIC LETTER ORKHON AY;Lo;0;R;;;;;N;;;;; +10C17;OLD TURKIC LETTER YENISEI AY;Lo;0;R;;;;;N;;;;; +10C18;OLD TURKIC LETTER ORKHON AEY;Lo;0;R;;;;;N;;;;; +10C19;OLD TURKIC LETTER YENISEI AEY;Lo;0;R;;;;;N;;;;; +10C1A;OLD TURKIC LETTER ORKHON AEK;Lo;0;R;;;;;N;;;;; +10C1B;OLD TURKIC LETTER YENISEI AEK;Lo;0;R;;;;;N;;;;; +10C1C;OLD TURKIC LETTER ORKHON OEK;Lo;0;R;;;;;N;;;;; +10C1D;OLD TURKIC LETTER YENISEI OEK;Lo;0;R;;;;;N;;;;; +10C1E;OLD TURKIC LETTER ORKHON AL;Lo;0;R;;;;;N;;;;; +10C1F;OLD TURKIC LETTER YENISEI AL;Lo;0;R;;;;;N;;;;; +10C20;OLD TURKIC LETTER ORKHON AEL;Lo;0;R;;;;;N;;;;; +10C21;OLD TURKIC LETTER ORKHON ELT;Lo;0;R;;;;;N;;;;; +10C22;OLD TURKIC LETTER ORKHON EM;Lo;0;R;;;;;N;;;;; +10C23;OLD TURKIC LETTER ORKHON AN;Lo;0;R;;;;;N;;;;; +10C24;OLD TURKIC LETTER ORKHON AEN;Lo;0;R;;;;;N;;;;; +10C25;OLD TURKIC LETTER YENISEI AEN;Lo;0;R;;;;;N;;;;; +10C26;OLD TURKIC LETTER ORKHON ENT;Lo;0;R;;;;;N;;;;; +10C27;OLD TURKIC LETTER YENISEI ENT;Lo;0;R;;;;;N;;;;; +10C28;OLD TURKIC LETTER ORKHON ENC;Lo;0;R;;;;;N;;;;; +10C29;OLD TURKIC LETTER YENISEI ENC;Lo;0;R;;;;;N;;;;; +10C2A;OLD TURKIC LETTER ORKHON ENY;Lo;0;R;;;;;N;;;;; +10C2B;OLD TURKIC LETTER YENISEI ENY;Lo;0;R;;;;;N;;;;; +10C2C;OLD TURKIC LETTER YENISEI ANG;Lo;0;R;;;;;N;;;;; +10C2D;OLD TURKIC LETTER ORKHON ENG;Lo;0;R;;;;;N;;;;; +10C2E;OLD TURKIC LETTER YENISEI AENG;Lo;0;R;;;;;N;;;;; +10C2F;OLD TURKIC LETTER ORKHON EP;Lo;0;R;;;;;N;;;;; +10C30;OLD TURKIC LETTER ORKHON OP;Lo;0;R;;;;;N;;;;; +10C31;OLD TURKIC LETTER ORKHON IC;Lo;0;R;;;;;N;;;;; +10C32;OLD TURKIC LETTER ORKHON EC;Lo;0;R;;;;;N;;;;; +10C33;OLD TURKIC LETTER YENISEI EC;Lo;0;R;;;;;N;;;;; +10C34;OLD TURKIC LETTER ORKHON AQ;Lo;0;R;;;;;N;;;;; +10C35;OLD TURKIC LETTER YENISEI AQ;Lo;0;R;;;;;N;;;;; +10C36;OLD TURKIC LETTER ORKHON IQ;Lo;0;R;;;;;N;;;;; +10C37;OLD TURKIC LETTER YENISEI IQ;Lo;0;R;;;;;N;;;;; +10C38;OLD TURKIC LETTER ORKHON OQ;Lo;0;R;;;;;N;;;;; +10C39;OLD TURKIC LETTER YENISEI OQ;Lo;0;R;;;;;N;;;;; +10C3A;OLD TURKIC LETTER ORKHON AR;Lo;0;R;;;;;N;;;;; +10C3B;OLD TURKIC LETTER YENISEI AR;Lo;0;R;;;;;N;;;;; +10C3C;OLD TURKIC LETTER ORKHON AER;Lo;0;R;;;;;N;;;;; +10C3D;OLD TURKIC LETTER ORKHON AS;Lo;0;R;;;;;N;;;;; +10C3E;OLD TURKIC LETTER ORKHON AES;Lo;0;R;;;;;N;;;;; +10C3F;OLD TURKIC LETTER ORKHON ASH;Lo;0;R;;;;;N;;;;; +10C40;OLD TURKIC LETTER YENISEI ASH;Lo;0;R;;;;;N;;;;; +10C41;OLD TURKIC LETTER ORKHON ESH;Lo;0;R;;;;;N;;;;; +10C42;OLD TURKIC LETTER YENISEI ESH;Lo;0;R;;;;;N;;;;; +10C43;OLD TURKIC LETTER ORKHON AT;Lo;0;R;;;;;N;;;;; +10C44;OLD TURKIC LETTER YENISEI AT;Lo;0;R;;;;;N;;;;; +10C45;OLD TURKIC LETTER ORKHON AET;Lo;0;R;;;;;N;;;;; +10C46;OLD TURKIC LETTER YENISEI AET;Lo;0;R;;;;;N;;;;; +10C47;OLD TURKIC LETTER ORKHON OT;Lo;0;R;;;;;N;;;;; +10C48;OLD TURKIC LETTER ORKHON BASH;Lo;0;R;;;;;N;;;;; +10C80;OLD HUNGARIAN CAPITAL LETTER A;Lu;0;R;;;;;N;;;;10CC0; +10C81;OLD HUNGARIAN CAPITAL LETTER AA;Lu;0;R;;;;;N;;;;10CC1; +10C82;OLD HUNGARIAN CAPITAL LETTER EB;Lu;0;R;;;;;N;;;;10CC2; +10C83;OLD HUNGARIAN CAPITAL LETTER AMB;Lu;0;R;;;;;N;;;;10CC3; +10C84;OLD HUNGARIAN CAPITAL LETTER EC;Lu;0;R;;;;;N;;;;10CC4; +10C85;OLD HUNGARIAN CAPITAL LETTER ENC;Lu;0;R;;;;;N;;;;10CC5; +10C86;OLD HUNGARIAN CAPITAL LETTER ECS;Lu;0;R;;;;;N;;;;10CC6; +10C87;OLD HUNGARIAN CAPITAL LETTER ED;Lu;0;R;;;;;N;;;;10CC7; +10C88;OLD HUNGARIAN CAPITAL LETTER AND;Lu;0;R;;;;;N;;;;10CC8; +10C89;OLD HUNGARIAN CAPITAL LETTER E;Lu;0;R;;;;;N;;;;10CC9; +10C8A;OLD HUNGARIAN CAPITAL LETTER CLOSE E;Lu;0;R;;;;;N;;;;10CCA; +10C8B;OLD HUNGARIAN CAPITAL LETTER EE;Lu;0;R;;;;;N;;;;10CCB; +10C8C;OLD HUNGARIAN CAPITAL LETTER EF;Lu;0;R;;;;;N;;;;10CCC; +10C8D;OLD HUNGARIAN CAPITAL LETTER EG;Lu;0;R;;;;;N;;;;10CCD; +10C8E;OLD HUNGARIAN CAPITAL LETTER EGY;Lu;0;R;;;;;N;;;;10CCE; +10C8F;OLD HUNGARIAN CAPITAL LETTER EH;Lu;0;R;;;;;N;;;;10CCF; +10C90;OLD HUNGARIAN CAPITAL LETTER I;Lu;0;R;;;;;N;;;;10CD0; +10C91;OLD HUNGARIAN CAPITAL LETTER II;Lu;0;R;;;;;N;;;;10CD1; +10C92;OLD HUNGARIAN CAPITAL LETTER EJ;Lu;0;R;;;;;N;;;;10CD2; +10C93;OLD HUNGARIAN CAPITAL LETTER EK;Lu;0;R;;;;;N;;;;10CD3; +10C94;OLD HUNGARIAN CAPITAL LETTER AK;Lu;0;R;;;;;N;;;;10CD4; +10C95;OLD HUNGARIAN CAPITAL LETTER UNK;Lu;0;R;;;;;N;;;;10CD5; +10C96;OLD HUNGARIAN CAPITAL LETTER EL;Lu;0;R;;;;;N;;;;10CD6; +10C97;OLD HUNGARIAN CAPITAL LETTER ELY;Lu;0;R;;;;;N;;;;10CD7; +10C98;OLD HUNGARIAN CAPITAL LETTER EM;Lu;0;R;;;;;N;;;;10CD8; +10C99;OLD HUNGARIAN CAPITAL LETTER EN;Lu;0;R;;;;;N;;;;10CD9; +10C9A;OLD HUNGARIAN CAPITAL LETTER ENY;Lu;0;R;;;;;N;;;;10CDA; +10C9B;OLD HUNGARIAN CAPITAL LETTER O;Lu;0;R;;;;;N;;;;10CDB; +10C9C;OLD HUNGARIAN CAPITAL LETTER OO;Lu;0;R;;;;;N;;;;10CDC; +10C9D;OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE;Lu;0;R;;;;;N;;;;10CDD; +10C9E;OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE;Lu;0;R;;;;;N;;;;10CDE; +10C9F;OLD HUNGARIAN CAPITAL LETTER OEE;Lu;0;R;;;;;N;;;;10CDF; +10CA0;OLD HUNGARIAN CAPITAL LETTER EP;Lu;0;R;;;;;N;;;;10CE0; +10CA1;OLD HUNGARIAN CAPITAL LETTER EMP;Lu;0;R;;;;;N;;;;10CE1; +10CA2;OLD HUNGARIAN CAPITAL LETTER ER;Lu;0;R;;;;;N;;;;10CE2; +10CA3;OLD HUNGARIAN CAPITAL LETTER SHORT ER;Lu;0;R;;;;;N;;;;10CE3; +10CA4;OLD HUNGARIAN CAPITAL LETTER ES;Lu;0;R;;;;;N;;;;10CE4; +10CA5;OLD HUNGARIAN CAPITAL LETTER ESZ;Lu;0;R;;;;;N;;;;10CE5; +10CA6;OLD HUNGARIAN CAPITAL LETTER ET;Lu;0;R;;;;;N;;;;10CE6; +10CA7;OLD HUNGARIAN CAPITAL LETTER ENT;Lu;0;R;;;;;N;;;;10CE7; +10CA8;OLD HUNGARIAN CAPITAL LETTER ETY;Lu;0;R;;;;;N;;;;10CE8; +10CA9;OLD HUNGARIAN CAPITAL LETTER ECH;Lu;0;R;;;;;N;;;;10CE9; +10CAA;OLD HUNGARIAN CAPITAL LETTER U;Lu;0;R;;;;;N;;;;10CEA; +10CAB;OLD HUNGARIAN CAPITAL LETTER UU;Lu;0;R;;;;;N;;;;10CEB; +10CAC;OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE;Lu;0;R;;;;;N;;;;10CEC; +10CAD;OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE;Lu;0;R;;;;;N;;;;10CED; +10CAE;OLD HUNGARIAN CAPITAL LETTER EV;Lu;0;R;;;;;N;;;;10CEE; +10CAF;OLD HUNGARIAN CAPITAL LETTER EZ;Lu;0;R;;;;;N;;;;10CEF; +10CB0;OLD HUNGARIAN CAPITAL LETTER EZS;Lu;0;R;;;;;N;;;;10CF0; +10CB1;OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN;Lu;0;R;;;;;N;;;;10CF1; +10CB2;OLD HUNGARIAN CAPITAL LETTER US;Lu;0;R;;;;;N;;;;10CF2; +10CC0;OLD HUNGARIAN SMALL LETTER A;Ll;0;R;;;;;N;;;10C80;;10C80 +10CC1;OLD HUNGARIAN SMALL LETTER AA;Ll;0;R;;;;;N;;;10C81;;10C81 +10CC2;OLD HUNGARIAN SMALL LETTER EB;Ll;0;R;;;;;N;;;10C82;;10C82 +10CC3;OLD HUNGARIAN SMALL LETTER AMB;Ll;0;R;;;;;N;;;10C83;;10C83 +10CC4;OLD HUNGARIAN SMALL LETTER EC;Ll;0;R;;;;;N;;;10C84;;10C84 +10CC5;OLD HUNGARIAN SMALL LETTER ENC;Ll;0;R;;;;;N;;;10C85;;10C85 +10CC6;OLD HUNGARIAN SMALL LETTER ECS;Ll;0;R;;;;;N;;;10C86;;10C86 +10CC7;OLD HUNGARIAN SMALL LETTER ED;Ll;0;R;;;;;N;;;10C87;;10C87 +10CC8;OLD HUNGARIAN SMALL LETTER AND;Ll;0;R;;;;;N;;;10C88;;10C88 +10CC9;OLD HUNGARIAN SMALL LETTER E;Ll;0;R;;;;;N;;;10C89;;10C89 +10CCA;OLD HUNGARIAN SMALL LETTER CLOSE E;Ll;0;R;;;;;N;;;10C8A;;10C8A +10CCB;OLD HUNGARIAN SMALL LETTER EE;Ll;0;R;;;;;N;;;10C8B;;10C8B +10CCC;OLD HUNGARIAN SMALL LETTER EF;Ll;0;R;;;;;N;;;10C8C;;10C8C +10CCD;OLD HUNGARIAN SMALL LETTER EG;Ll;0;R;;;;;N;;;10C8D;;10C8D +10CCE;OLD HUNGARIAN SMALL LETTER EGY;Ll;0;R;;;;;N;;;10C8E;;10C8E +10CCF;OLD HUNGARIAN SMALL LETTER EH;Ll;0;R;;;;;N;;;10C8F;;10C8F +10CD0;OLD HUNGARIAN SMALL LETTER I;Ll;0;R;;;;;N;;;10C90;;10C90 +10CD1;OLD HUNGARIAN SMALL LETTER II;Ll;0;R;;;;;N;;;10C91;;10C91 +10CD2;OLD HUNGARIAN SMALL LETTER EJ;Ll;0;R;;;;;N;;;10C92;;10C92 +10CD3;OLD HUNGARIAN SMALL LETTER EK;Ll;0;R;;;;;N;;;10C93;;10C93 +10CD4;OLD HUNGARIAN SMALL LETTER AK;Ll;0;R;;;;;N;;;10C94;;10C94 +10CD5;OLD HUNGARIAN SMALL LETTER UNK;Ll;0;R;;;;;N;;;10C95;;10C95 +10CD6;OLD HUNGARIAN SMALL LETTER EL;Ll;0;R;;;;;N;;;10C96;;10C96 +10CD7;OLD HUNGARIAN SMALL LETTER ELY;Ll;0;R;;;;;N;;;10C97;;10C97 +10CD8;OLD HUNGARIAN SMALL LETTER EM;Ll;0;R;;;;;N;;;10C98;;10C98 +10CD9;OLD HUNGARIAN SMALL LETTER EN;Ll;0;R;;;;;N;;;10C99;;10C99 +10CDA;OLD HUNGARIAN SMALL LETTER ENY;Ll;0;R;;;;;N;;;10C9A;;10C9A +10CDB;OLD HUNGARIAN SMALL LETTER O;Ll;0;R;;;;;N;;;10C9B;;10C9B +10CDC;OLD HUNGARIAN SMALL LETTER OO;Ll;0;R;;;;;N;;;10C9C;;10C9C +10CDD;OLD HUNGARIAN SMALL LETTER NIKOLSBURG OE;Ll;0;R;;;;;N;;;10C9D;;10C9D +10CDE;OLD HUNGARIAN SMALL LETTER RUDIMENTA OE;Ll;0;R;;;;;N;;;10C9E;;10C9E +10CDF;OLD HUNGARIAN SMALL LETTER OEE;Ll;0;R;;;;;N;;;10C9F;;10C9F +10CE0;OLD HUNGARIAN SMALL LETTER EP;Ll;0;R;;;;;N;;;10CA0;;10CA0 +10CE1;OLD HUNGARIAN SMALL LETTER EMP;Ll;0;R;;;;;N;;;10CA1;;10CA1 +10CE2;OLD HUNGARIAN SMALL LETTER ER;Ll;0;R;;;;;N;;;10CA2;;10CA2 +10CE3;OLD HUNGARIAN SMALL LETTER SHORT ER;Ll;0;R;;;;;N;;;10CA3;;10CA3 +10CE4;OLD HUNGARIAN SMALL LETTER ES;Ll;0;R;;;;;N;;;10CA4;;10CA4 +10CE5;OLD HUNGARIAN SMALL LETTER ESZ;Ll;0;R;;;;;N;;;10CA5;;10CA5 +10CE6;OLD HUNGARIAN SMALL LETTER ET;Ll;0;R;;;;;N;;;10CA6;;10CA6 +10CE7;OLD HUNGARIAN SMALL LETTER ENT;Ll;0;R;;;;;N;;;10CA7;;10CA7 +10CE8;OLD HUNGARIAN SMALL LETTER ETY;Ll;0;R;;;;;N;;;10CA8;;10CA8 +10CE9;OLD HUNGARIAN SMALL LETTER ECH;Ll;0;R;;;;;N;;;10CA9;;10CA9 +10CEA;OLD HUNGARIAN SMALL LETTER U;Ll;0;R;;;;;N;;;10CAA;;10CAA +10CEB;OLD HUNGARIAN SMALL LETTER UU;Ll;0;R;;;;;N;;;10CAB;;10CAB +10CEC;OLD HUNGARIAN SMALL LETTER NIKOLSBURG UE;Ll;0;R;;;;;N;;;10CAC;;10CAC +10CED;OLD HUNGARIAN SMALL LETTER RUDIMENTA UE;Ll;0;R;;;;;N;;;10CAD;;10CAD +10CEE;OLD HUNGARIAN SMALL LETTER EV;Ll;0;R;;;;;N;;;10CAE;;10CAE +10CEF;OLD HUNGARIAN SMALL LETTER EZ;Ll;0;R;;;;;N;;;10CAF;;10CAF +10CF0;OLD HUNGARIAN SMALL LETTER EZS;Ll;0;R;;;;;N;;;10CB0;;10CB0 +10CF1;OLD HUNGARIAN SMALL LETTER ENT-SHAPED SIGN;Ll;0;R;;;;;N;;;10CB1;;10CB1 +10CF2;OLD HUNGARIAN SMALL LETTER US;Ll;0;R;;;;;N;;;10CB2;;10CB2 +10CFA;OLD HUNGARIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10CFB;OLD HUNGARIAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +10CFC;OLD HUNGARIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10CFD;OLD HUNGARIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;; +10CFE;OLD HUNGARIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10CFF;OLD HUNGARIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +10E60;RUMI DIGIT ONE;No;0;AN;;;1;1;N;;;;; +10E61;RUMI DIGIT TWO;No;0;AN;;;2;2;N;;;;; +10E62;RUMI DIGIT THREE;No;0;AN;;;3;3;N;;;;; +10E63;RUMI DIGIT FOUR;No;0;AN;;;4;4;N;;;;; +10E64;RUMI DIGIT FIVE;No;0;AN;;;5;5;N;;;;; +10E65;RUMI DIGIT SIX;No;0;AN;;;6;6;N;;;;; +10E66;RUMI DIGIT SEVEN;No;0;AN;;;7;7;N;;;;; +10E67;RUMI DIGIT EIGHT;No;0;AN;;;8;8;N;;;;; +10E68;RUMI DIGIT NINE;No;0;AN;;;9;9;N;;;;; +10E69;RUMI NUMBER TEN;No;0;AN;;;;10;N;;;;; +10E6A;RUMI NUMBER TWENTY;No;0;AN;;;;20;N;;;;; +10E6B;RUMI NUMBER THIRTY;No;0;AN;;;;30;N;;;;; +10E6C;RUMI NUMBER FORTY;No;0;AN;;;;40;N;;;;; +10E6D;RUMI NUMBER FIFTY;No;0;AN;;;;50;N;;;;; +10E6E;RUMI NUMBER SIXTY;No;0;AN;;;;60;N;;;;; +10E6F;RUMI NUMBER SEVENTY;No;0;AN;;;;70;N;;;;; +10E70;RUMI NUMBER EIGHTY;No;0;AN;;;;80;N;;;;; +10E71;RUMI NUMBER NINETY;No;0;AN;;;;90;N;;;;; +10E72;RUMI NUMBER ONE HUNDRED;No;0;AN;;;;100;N;;;;; +10E73;RUMI NUMBER TWO HUNDRED;No;0;AN;;;;200;N;;;;; +10E74;RUMI NUMBER THREE HUNDRED;No;0;AN;;;;300;N;;;;; +10E75;RUMI NUMBER FOUR HUNDRED;No;0;AN;;;;400;N;;;;; +10E76;RUMI NUMBER FIVE HUNDRED;No;0;AN;;;;500;N;;;;; +10E77;RUMI NUMBER SIX HUNDRED;No;0;AN;;;;600;N;;;;; +10E78;RUMI NUMBER SEVEN HUNDRED;No;0;AN;;;;700;N;;;;; +10E79;RUMI NUMBER EIGHT HUNDRED;No;0;AN;;;;800;N;;;;; +10E7A;RUMI NUMBER NINE HUNDRED;No;0;AN;;;;900;N;;;;; +10E7B;RUMI FRACTION ONE HALF;No;0;AN;;;;1/2;N;;;;; +10E7C;RUMI FRACTION ONE QUARTER;No;0;AN;;;;1/4;N;;;;; +10E7D;RUMI FRACTION ONE THIRD;No;0;AN;;;;1/3;N;;;;; +10E7E;RUMI FRACTION TWO THIRDS;No;0;AN;;;;2/3;N;;;;; +11000;BRAHMI SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; +11001;BRAHMI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11002;BRAHMI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11003;BRAHMI SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +11004;BRAHMI SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +11005;BRAHMI LETTER A;Lo;0;L;;;;;N;;;;; +11006;BRAHMI LETTER AA;Lo;0;L;;;;;N;;;;; +11007;BRAHMI LETTER I;Lo;0;L;;;;;N;;;;; +11008;BRAHMI LETTER II;Lo;0;L;;;;;N;;;;; +11009;BRAHMI LETTER U;Lo;0;L;;;;;N;;;;; +1100A;BRAHMI LETTER UU;Lo;0;L;;;;;N;;;;; +1100B;BRAHMI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1100C;BRAHMI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +1100D;BRAHMI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1100E;BRAHMI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1100F;BRAHMI LETTER E;Lo;0;L;;;;;N;;;;; +11010;BRAHMI LETTER AI;Lo;0;L;;;;;N;;;;; +11011;BRAHMI LETTER O;Lo;0;L;;;;;N;;;;; +11012;BRAHMI LETTER AU;Lo;0;L;;;;;N;;;;; +11013;BRAHMI LETTER KA;Lo;0;L;;;;;N;;;;; +11014;BRAHMI LETTER KHA;Lo;0;L;;;;;N;;;;; +11015;BRAHMI LETTER GA;Lo;0;L;;;;;N;;;;; +11016;BRAHMI LETTER GHA;Lo;0;L;;;;;N;;;;; +11017;BRAHMI LETTER NGA;Lo;0;L;;;;;N;;;;; +11018;BRAHMI LETTER CA;Lo;0;L;;;;;N;;;;; +11019;BRAHMI LETTER CHA;Lo;0;L;;;;;N;;;;; +1101A;BRAHMI LETTER JA;Lo;0;L;;;;;N;;;;; +1101B;BRAHMI LETTER JHA;Lo;0;L;;;;;N;;;;; +1101C;BRAHMI LETTER NYA;Lo;0;L;;;;;N;;;;; +1101D;BRAHMI LETTER TTA;Lo;0;L;;;;;N;;;;; +1101E;BRAHMI LETTER TTHA;Lo;0;L;;;;;N;;;;; +1101F;BRAHMI LETTER DDA;Lo;0;L;;;;;N;;;;; +11020;BRAHMI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11021;BRAHMI LETTER NNA;Lo;0;L;;;;;N;;;;; +11022;BRAHMI LETTER TA;Lo;0;L;;;;;N;;;;; +11023;BRAHMI LETTER THA;Lo;0;L;;;;;N;;;;; +11024;BRAHMI LETTER DA;Lo;0;L;;;;;N;;;;; +11025;BRAHMI LETTER DHA;Lo;0;L;;;;;N;;;;; +11026;BRAHMI LETTER NA;Lo;0;L;;;;;N;;;;; +11027;BRAHMI LETTER PA;Lo;0;L;;;;;N;;;;; +11028;BRAHMI LETTER PHA;Lo;0;L;;;;;N;;;;; +11029;BRAHMI LETTER BA;Lo;0;L;;;;;N;;;;; +1102A;BRAHMI LETTER BHA;Lo;0;L;;;;;N;;;;; +1102B;BRAHMI LETTER MA;Lo;0;L;;;;;N;;;;; +1102C;BRAHMI LETTER YA;Lo;0;L;;;;;N;;;;; +1102D;BRAHMI LETTER RA;Lo;0;L;;;;;N;;;;; +1102E;BRAHMI LETTER LA;Lo;0;L;;;;;N;;;;; +1102F;BRAHMI LETTER VA;Lo;0;L;;;;;N;;;;; +11030;BRAHMI LETTER SHA;Lo;0;L;;;;;N;;;;; +11031;BRAHMI LETTER SSA;Lo;0;L;;;;;N;;;;; +11032;BRAHMI LETTER SA;Lo;0;L;;;;;N;;;;; +11033;BRAHMI LETTER HA;Lo;0;L;;;;;N;;;;; +11034;BRAHMI LETTER LLA;Lo;0;L;;;;;N;;;;; +11035;BRAHMI LETTER OLD TAMIL LLLA;Lo;0;L;;;;;N;;;;; +11036;BRAHMI LETTER OLD TAMIL RRA;Lo;0;L;;;;;N;;;;; +11037;BRAHMI LETTER OLD TAMIL NNNA;Lo;0;L;;;;;N;;;;; +11038;BRAHMI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11039;BRAHMI VOWEL SIGN BHATTIPROLU AA;Mn;0;NSM;;;;;N;;;;; +1103A;BRAHMI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1103B;BRAHMI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +1103C;BRAHMI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1103D;BRAHMI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1103E;BRAHMI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +1103F;BRAHMI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11040;BRAHMI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11041;BRAHMI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +11042;BRAHMI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11043;BRAHMI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11044;BRAHMI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11045;BRAHMI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11046;BRAHMI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11047;BRAHMI DANDA;Po;0;L;;;;;N;;;;; +11048;BRAHMI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11049;BRAHMI PUNCTUATION DOT;Po;0;L;;;;;N;;;;; +1104A;BRAHMI PUNCTUATION DOUBLE DOT;Po;0;L;;;;;N;;;;; +1104B;BRAHMI PUNCTUATION LINE;Po;0;L;;;;;N;;;;; +1104C;BRAHMI PUNCTUATION CRESCENT BAR;Po;0;L;;;;;N;;;;; +1104D;BRAHMI PUNCTUATION LOTUS;Po;0;L;;;;;N;;;;; +11052;BRAHMI NUMBER ONE;No;0;ON;;;1;1;N;;;;; +11053;BRAHMI NUMBER TWO;No;0;ON;;;2;2;N;;;;; +11054;BRAHMI NUMBER THREE;No;0;ON;;;3;3;N;;;;; +11055;BRAHMI NUMBER FOUR;No;0;ON;;;4;4;N;;;;; +11056;BRAHMI NUMBER FIVE;No;0;ON;;;5;5;N;;;;; +11057;BRAHMI NUMBER SIX;No;0;ON;;;6;6;N;;;;; +11058;BRAHMI NUMBER SEVEN;No;0;ON;;;7;7;N;;;;; +11059;BRAHMI NUMBER EIGHT;No;0;ON;;;8;8;N;;;;; +1105A;BRAHMI NUMBER NINE;No;0;ON;;;9;9;N;;;;; +1105B;BRAHMI NUMBER TEN;No;0;ON;;;;10;N;;;;; +1105C;BRAHMI NUMBER TWENTY;No;0;ON;;;;20;N;;;;; +1105D;BRAHMI NUMBER THIRTY;No;0;ON;;;;30;N;;;;; +1105E;BRAHMI NUMBER FORTY;No;0;ON;;;;40;N;;;;; +1105F;BRAHMI NUMBER FIFTY;No;0;ON;;;;50;N;;;;; +11060;BRAHMI NUMBER SIXTY;No;0;ON;;;;60;N;;;;; +11061;BRAHMI NUMBER SEVENTY;No;0;ON;;;;70;N;;;;; +11062;BRAHMI NUMBER EIGHTY;No;0;ON;;;;80;N;;;;; +11063;BRAHMI NUMBER NINETY;No;0;ON;;;;90;N;;;;; +11064;BRAHMI NUMBER ONE HUNDRED;No;0;ON;;;;100;N;;;;; +11065;BRAHMI NUMBER ONE THOUSAND;No;0;ON;;;;1000;N;;;;; +11066;BRAHMI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11067;BRAHMI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11068;BRAHMI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11069;BRAHMI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1106A;BRAHMI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1106B;BRAHMI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1106C;BRAHMI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1106D;BRAHMI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1106E;BRAHMI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1106F;BRAHMI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1107F;BRAHMI NUMBER JOINER;Mn;9;NSM;;;;;N;;;;; +11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11082;KAITHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11083;KAITHI LETTER A;Lo;0;L;;;;;N;;;;; +11084;KAITHI LETTER AA;Lo;0;L;;;;;N;;;;; +11085;KAITHI LETTER I;Lo;0;L;;;;;N;;;;; +11086;KAITHI LETTER II;Lo;0;L;;;;;N;;;;; +11087;KAITHI LETTER U;Lo;0;L;;;;;N;;;;; +11088;KAITHI LETTER UU;Lo;0;L;;;;;N;;;;; +11089;KAITHI LETTER E;Lo;0;L;;;;;N;;;;; +1108A;KAITHI LETTER AI;Lo;0;L;;;;;N;;;;; +1108B;KAITHI LETTER O;Lo;0;L;;;;;N;;;;; +1108C;KAITHI LETTER AU;Lo;0;L;;;;;N;;;;; +1108D;KAITHI LETTER KA;Lo;0;L;;;;;N;;;;; +1108E;KAITHI LETTER KHA;Lo;0;L;;;;;N;;;;; +1108F;KAITHI LETTER GA;Lo;0;L;;;;;N;;;;; +11090;KAITHI LETTER GHA;Lo;0;L;;;;;N;;;;; +11091;KAITHI LETTER NGA;Lo;0;L;;;;;N;;;;; +11092;KAITHI LETTER CA;Lo;0;L;;;;;N;;;;; +11093;KAITHI LETTER CHA;Lo;0;L;;;;;N;;;;; +11094;KAITHI LETTER JA;Lo;0;L;;;;;N;;;;; +11095;KAITHI LETTER JHA;Lo;0;L;;;;;N;;;;; +11096;KAITHI LETTER NYA;Lo;0;L;;;;;N;;;;; +11097;KAITHI LETTER TTA;Lo;0;L;;;;;N;;;;; +11098;KAITHI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11099;KAITHI LETTER DDA;Lo;0;L;;;;;N;;;;; +1109A;KAITHI LETTER DDDHA;Lo;0;L;11099 110BA;;;;N;;;;; +1109B;KAITHI LETTER DDHA;Lo;0;L;;;;;N;;;;; +1109C;KAITHI LETTER RHA;Lo;0;L;1109B 110BA;;;;N;;;;; +1109D;KAITHI LETTER NNA;Lo;0;L;;;;;N;;;;; +1109E;KAITHI LETTER TA;Lo;0;L;;;;;N;;;;; +1109F;KAITHI LETTER THA;Lo;0;L;;;;;N;;;;; +110A0;KAITHI LETTER DA;Lo;0;L;;;;;N;;;;; +110A1;KAITHI LETTER DHA;Lo;0;L;;;;;N;;;;; +110A2;KAITHI LETTER NA;Lo;0;L;;;;;N;;;;; +110A3;KAITHI LETTER PA;Lo;0;L;;;;;N;;;;; +110A4;KAITHI LETTER PHA;Lo;0;L;;;;;N;;;;; +110A5;KAITHI LETTER BA;Lo;0;L;;;;;N;;;;; +110A6;KAITHI LETTER BHA;Lo;0;L;;;;;N;;;;; +110A7;KAITHI LETTER MA;Lo;0;L;;;;;N;;;;; +110A8;KAITHI LETTER YA;Lo;0;L;;;;;N;;;;; +110A9;KAITHI LETTER RA;Lo;0;L;;;;;N;;;;; +110AA;KAITHI LETTER LA;Lo;0;L;;;;;N;;;;; +110AB;KAITHI LETTER VA;Lo;0;L;110A5 110BA;;;;N;;;;; +110AC;KAITHI LETTER SHA;Lo;0;L;;;;;N;;;;; +110AD;KAITHI LETTER SSA;Lo;0;L;;;;;N;;;;; +110AE;KAITHI LETTER SA;Lo;0;L;;;;;N;;;;; +110AF;KAITHI LETTER HA;Lo;0;L;;;;;N;;;;; +110B0;KAITHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +110B1;KAITHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +110B2;KAITHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +110B3;KAITHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +110B4;KAITHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +110B5;KAITHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +110B6;KAITHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +110B7;KAITHI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +110B8;KAITHI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +110B9;KAITHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +110BA;KAITHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +110BB;KAITHI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +110BC;KAITHI ENUMERATION SIGN;Po;0;L;;;;;N;;;;; +110BD;KAITHI NUMBER SIGN;Cf;0;L;;;;;N;;;;; +110BE;KAITHI SECTION MARK;Po;0;L;;;;;N;;;;; +110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; +110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;; +110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +110D0;SORA SOMPENG LETTER SAH;Lo;0;L;;;;;N;;;;; +110D1;SORA SOMPENG LETTER TAH;Lo;0;L;;;;;N;;;;; +110D2;SORA SOMPENG LETTER BAH;Lo;0;L;;;;;N;;;;; +110D3;SORA SOMPENG LETTER CAH;Lo;0;L;;;;;N;;;;; +110D4;SORA SOMPENG LETTER DAH;Lo;0;L;;;;;N;;;;; +110D5;SORA SOMPENG LETTER GAH;Lo;0;L;;;;;N;;;;; +110D6;SORA SOMPENG LETTER MAH;Lo;0;L;;;;;N;;;;; +110D7;SORA SOMPENG LETTER NGAH;Lo;0;L;;;;;N;;;;; +110D8;SORA SOMPENG LETTER LAH;Lo;0;L;;;;;N;;;;; +110D9;SORA SOMPENG LETTER NAH;Lo;0;L;;;;;N;;;;; +110DA;SORA SOMPENG LETTER VAH;Lo;0;L;;;;;N;;;;; +110DB;SORA SOMPENG LETTER PAH;Lo;0;L;;;;;N;;;;; +110DC;SORA SOMPENG LETTER YAH;Lo;0;L;;;;;N;;;;; +110DD;SORA SOMPENG LETTER RAH;Lo;0;L;;;;;N;;;;; +110DE;SORA SOMPENG LETTER HAH;Lo;0;L;;;;;N;;;;; +110DF;SORA SOMPENG LETTER KAH;Lo;0;L;;;;;N;;;;; +110E0;SORA SOMPENG LETTER JAH;Lo;0;L;;;;;N;;;;; +110E1;SORA SOMPENG LETTER NYAH;Lo;0;L;;;;;N;;;;; +110E2;SORA SOMPENG LETTER AH;Lo;0;L;;;;;N;;;;; +110E3;SORA SOMPENG LETTER EEH;Lo;0;L;;;;;N;;;;; +110E4;SORA SOMPENG LETTER IH;Lo;0;L;;;;;N;;;;; +110E5;SORA SOMPENG LETTER UH;Lo;0;L;;;;;N;;;;; +110E6;SORA SOMPENG LETTER OH;Lo;0;L;;;;;N;;;;; +110E7;SORA SOMPENG LETTER EH;Lo;0;L;;;;;N;;;;; +110E8;SORA SOMPENG LETTER MAE;Lo;0;L;;;;;N;;;;; +110F0;SORA SOMPENG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +110F1;SORA SOMPENG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +110F2;SORA SOMPENG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +110F3;SORA SOMPENG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +110F4;SORA SOMPENG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +110F5;SORA SOMPENG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +110F6;SORA SOMPENG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +110F7;SORA SOMPENG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +110F8;SORA SOMPENG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +110F9;SORA SOMPENG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11100;CHAKMA SIGN CANDRABINDU;Mn;230;NSM;;;;;N;;;;; +11101;CHAKMA SIGN ANUSVARA;Mn;230;NSM;;;;;N;;;;; +11102;CHAKMA SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; +11103;CHAKMA LETTER AA;Lo;0;L;;;;;N;;;;; +11104;CHAKMA LETTER I;Lo;0;L;;;;;N;;;;; +11105;CHAKMA LETTER U;Lo;0;L;;;;;N;;;;; +11106;CHAKMA LETTER E;Lo;0;L;;;;;N;;;;; +11107;CHAKMA LETTER KAA;Lo;0;L;;;;;N;;;;; +11108;CHAKMA LETTER KHAA;Lo;0;L;;;;;N;;;;; +11109;CHAKMA LETTER GAA;Lo;0;L;;;;;N;;;;; +1110A;CHAKMA LETTER GHAA;Lo;0;L;;;;;N;;;;; +1110B;CHAKMA LETTER NGAA;Lo;0;L;;;;;N;;;;; +1110C;CHAKMA LETTER CAA;Lo;0;L;;;;;N;;;;; +1110D;CHAKMA LETTER CHAA;Lo;0;L;;;;;N;;;;; +1110E;CHAKMA LETTER JAA;Lo;0;L;;;;;N;;;;; +1110F;CHAKMA LETTER JHAA;Lo;0;L;;;;;N;;;;; +11110;CHAKMA LETTER NYAA;Lo;0;L;;;;;N;;;;; +11111;CHAKMA LETTER TTAA;Lo;0;L;;;;;N;;;;; +11112;CHAKMA LETTER TTHAA;Lo;0;L;;;;;N;;;;; +11113;CHAKMA LETTER DDAA;Lo;0;L;;;;;N;;;;; +11114;CHAKMA LETTER DDHAA;Lo;0;L;;;;;N;;;;; +11115;CHAKMA LETTER NNAA;Lo;0;L;;;;;N;;;;; +11116;CHAKMA LETTER TAA;Lo;0;L;;;;;N;;;;; +11117;CHAKMA LETTER THAA;Lo;0;L;;;;;N;;;;; +11118;CHAKMA LETTER DAA;Lo;0;L;;;;;N;;;;; +11119;CHAKMA LETTER DHAA;Lo;0;L;;;;;N;;;;; +1111A;CHAKMA LETTER NAA;Lo;0;L;;;;;N;;;;; +1111B;CHAKMA LETTER PAA;Lo;0;L;;;;;N;;;;; +1111C;CHAKMA LETTER PHAA;Lo;0;L;;;;;N;;;;; +1111D;CHAKMA LETTER BAA;Lo;0;L;;;;;N;;;;; +1111E;CHAKMA LETTER BHAA;Lo;0;L;;;;;N;;;;; +1111F;CHAKMA LETTER MAA;Lo;0;L;;;;;N;;;;; +11120;CHAKMA LETTER YYAA;Lo;0;L;;;;;N;;;;; +11121;CHAKMA LETTER YAA;Lo;0;L;;;;;N;;;;; +11122;CHAKMA LETTER RAA;Lo;0;L;;;;;N;;;;; +11123;CHAKMA LETTER LAA;Lo;0;L;;;;;N;;;;; +11124;CHAKMA LETTER WAA;Lo;0;L;;;;;N;;;;; +11125;CHAKMA LETTER SAA;Lo;0;L;;;;;N;;;;; +11126;CHAKMA LETTER HAA;Lo;0;L;;;;;N;;;;; +11127;CHAKMA VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; +11128;CHAKMA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11129;CHAKMA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +1112A;CHAKMA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1112B;CHAKMA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1112C;CHAKMA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1112D;CHAKMA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +1112E;CHAKMA VOWEL SIGN O;Mn;0;NSM;11131 11127;;;;N;;;;; +1112F;CHAKMA VOWEL SIGN AU;Mn;0;NSM;11132 11127;;;;N;;;;; +11130;CHAKMA VOWEL SIGN OI;Mn;0;NSM;;;;;N;;;;; +11131;CHAKMA O MARK;Mn;0;NSM;;;;;N;;;;; +11132;CHAKMA AU MARK;Mn;0;NSM;;;;;N;;;;; +11133;CHAKMA VIRAMA;Mn;9;NSM;;;;;N;;;;; +11134;CHAKMA MAAYYAA;Mn;9;NSM;;;;;N;;;;; +11136;CHAKMA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11137;CHAKMA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11138;CHAKMA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11139;CHAKMA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1113A;CHAKMA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1113B;CHAKMA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1113C;CHAKMA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1113D;CHAKMA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1113E;CHAKMA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1113F;CHAKMA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11140;CHAKMA SECTION MARK;Po;0;L;;;;;N;;;;; +11141;CHAKMA DANDA;Po;0;L;;;;;N;;;;; +11142;CHAKMA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11143;CHAKMA QUESTION MARK;Po;0;L;;;;;N;;;;; +11150;MAHAJANI LETTER A;Lo;0;L;;;;;N;;;;; +11151;MAHAJANI LETTER I;Lo;0;L;;;;;N;;;;; +11152;MAHAJANI LETTER U;Lo;0;L;;;;;N;;;;; +11153;MAHAJANI LETTER E;Lo;0;L;;;;;N;;;;; +11154;MAHAJANI LETTER O;Lo;0;L;;;;;N;;;;; +11155;MAHAJANI LETTER KA;Lo;0;L;;;;;N;;;;; +11156;MAHAJANI LETTER KHA;Lo;0;L;;;;;N;;;;; +11157;MAHAJANI LETTER GA;Lo;0;L;;;;;N;;;;; +11158;MAHAJANI LETTER GHA;Lo;0;L;;;;;N;;;;; +11159;MAHAJANI LETTER CA;Lo;0;L;;;;;N;;;;; +1115A;MAHAJANI LETTER CHA;Lo;0;L;;;;;N;;;;; +1115B;MAHAJANI LETTER JA;Lo;0;L;;;;;N;;;;; +1115C;MAHAJANI LETTER JHA;Lo;0;L;;;;;N;;;;; +1115D;MAHAJANI LETTER NYA;Lo;0;L;;;;;N;;;;; +1115E;MAHAJANI LETTER TTA;Lo;0;L;;;;;N;;;;; +1115F;MAHAJANI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11160;MAHAJANI LETTER DDA;Lo;0;L;;;;;N;;;;; +11161;MAHAJANI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11162;MAHAJANI LETTER NNA;Lo;0;L;;;;;N;;;;; +11163;MAHAJANI LETTER TA;Lo;0;L;;;;;N;;;;; +11164;MAHAJANI LETTER THA;Lo;0;L;;;;;N;;;;; +11165;MAHAJANI LETTER DA;Lo;0;L;;;;;N;;;;; +11166;MAHAJANI LETTER DHA;Lo;0;L;;;;;N;;;;; +11167;MAHAJANI LETTER NA;Lo;0;L;;;;;N;;;;; +11168;MAHAJANI LETTER PA;Lo;0;L;;;;;N;;;;; +11169;MAHAJANI LETTER PHA;Lo;0;L;;;;;N;;;;; +1116A;MAHAJANI LETTER BA;Lo;0;L;;;;;N;;;;; +1116B;MAHAJANI LETTER BHA;Lo;0;L;;;;;N;;;;; +1116C;MAHAJANI LETTER MA;Lo;0;L;;;;;N;;;;; +1116D;MAHAJANI LETTER RA;Lo;0;L;;;;;N;;;;; +1116E;MAHAJANI LETTER LA;Lo;0;L;;;;;N;;;;; +1116F;MAHAJANI LETTER VA;Lo;0;L;;;;;N;;;;; +11170;MAHAJANI LETTER SA;Lo;0;L;;;;;N;;;;; +11171;MAHAJANI LETTER HA;Lo;0;L;;;;;N;;;;; +11172;MAHAJANI LETTER RRA;Lo;0;L;;;;;N;;;;; +11173;MAHAJANI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11174;MAHAJANI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +11175;MAHAJANI SECTION MARK;Po;0;L;;;;;N;;;;; +11176;MAHAJANI LIGATURE SHRI;Lo;0;L;;;;;N;;;;; +11180;SHARADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11181;SHARADA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11182;SHARADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11183;SHARADA LETTER A;Lo;0;L;;;;;N;;;;; +11184;SHARADA LETTER AA;Lo;0;L;;;;;N;;;;; +11185;SHARADA LETTER I;Lo;0;L;;;;;N;;;;; +11186;SHARADA LETTER II;Lo;0;L;;;;;N;;;;; +11187;SHARADA LETTER U;Lo;0;L;;;;;N;;;;; +11188;SHARADA LETTER UU;Lo;0;L;;;;;N;;;;; +11189;SHARADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1118A;SHARADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +1118B;SHARADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1118C;SHARADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1118D;SHARADA LETTER E;Lo;0;L;;;;;N;;;;; +1118E;SHARADA LETTER AI;Lo;0;L;;;;;N;;;;; +1118F;SHARADA LETTER O;Lo;0;L;;;;;N;;;;; +11190;SHARADA LETTER AU;Lo;0;L;;;;;N;;;;; +11191;SHARADA LETTER KA;Lo;0;L;;;;;N;;;;; +11192;SHARADA LETTER KHA;Lo;0;L;;;;;N;;;;; +11193;SHARADA LETTER GA;Lo;0;L;;;;;N;;;;; +11194;SHARADA LETTER GHA;Lo;0;L;;;;;N;;;;; +11195;SHARADA LETTER NGA;Lo;0;L;;;;;N;;;;; +11196;SHARADA LETTER CA;Lo;0;L;;;;;N;;;;; +11197;SHARADA LETTER CHA;Lo;0;L;;;;;N;;;;; +11198;SHARADA LETTER JA;Lo;0;L;;;;;N;;;;; +11199;SHARADA LETTER JHA;Lo;0;L;;;;;N;;;;; +1119A;SHARADA LETTER NYA;Lo;0;L;;;;;N;;;;; +1119B;SHARADA LETTER TTA;Lo;0;L;;;;;N;;;;; +1119C;SHARADA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1119D;SHARADA LETTER DDA;Lo;0;L;;;;;N;;;;; +1119E;SHARADA LETTER DDHA;Lo;0;L;;;;;N;;;;; +1119F;SHARADA LETTER NNA;Lo;0;L;;;;;N;;;;; +111A0;SHARADA LETTER TA;Lo;0;L;;;;;N;;;;; +111A1;SHARADA LETTER THA;Lo;0;L;;;;;N;;;;; +111A2;SHARADA LETTER DA;Lo;0;L;;;;;N;;;;; +111A3;SHARADA LETTER DHA;Lo;0;L;;;;;N;;;;; +111A4;SHARADA LETTER NA;Lo;0;L;;;;;N;;;;; +111A5;SHARADA LETTER PA;Lo;0;L;;;;;N;;;;; +111A6;SHARADA LETTER PHA;Lo;0;L;;;;;N;;;;; +111A7;SHARADA LETTER BA;Lo;0;L;;;;;N;;;;; +111A8;SHARADA LETTER BHA;Lo;0;L;;;;;N;;;;; +111A9;SHARADA LETTER MA;Lo;0;L;;;;;N;;;;; +111AA;SHARADA LETTER YA;Lo;0;L;;;;;N;;;;; +111AB;SHARADA LETTER RA;Lo;0;L;;;;;N;;;;; +111AC;SHARADA LETTER LA;Lo;0;L;;;;;N;;;;; +111AD;SHARADA LETTER LLA;Lo;0;L;;;;;N;;;;; +111AE;SHARADA LETTER VA;Lo;0;L;;;;;N;;;;; +111AF;SHARADA LETTER SHA;Lo;0;L;;;;;N;;;;; +111B0;SHARADA LETTER SSA;Lo;0;L;;;;;N;;;;; +111B1;SHARADA LETTER SA;Lo;0;L;;;;;N;;;;; +111B2;SHARADA LETTER HA;Lo;0;L;;;;;N;;;;; +111B3;SHARADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +111B4;SHARADA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +111B5;SHARADA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +111B6;SHARADA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +111B7;SHARADA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +111B8;SHARADA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +111B9;SHARADA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +111BA;SHARADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +111BB;SHARADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +111BC;SHARADA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +111BD;SHARADA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +111BE;SHARADA VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +111BF;SHARADA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +111C0;SHARADA SIGN VIRAMA;Mc;9;L;;;;;N;;;;; +111C1;SHARADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +111C2;SHARADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +111C3;SHARADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +111C4;SHARADA OM;Lo;0;L;;;;;N;;;;; +111C5;SHARADA DANDA;Po;0;L;;;;;N;;;;; +111C6;SHARADA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +111C7;SHARADA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +111C8;SHARADA SEPARATOR;Po;0;L;;;;;N;;;;; +111C9;SHARADA SANDHI MARK;Po;0;L;;;;;N;;;;; +111CA;SHARADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +111CB;SHARADA VOWEL MODIFIER MARK;Mn;0;NSM;;;;;N;;;;; +111CC;SHARADA EXTRA SHORT VOWEL MARK;Mn;0;NSM;;;;;N;;;;; +111CD;SHARADA SUTRA MARK;Po;0;L;;;;;N;;;;; +111D0;SHARADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +111D1;SHARADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +111D2;SHARADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +111D3;SHARADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +111D4;SHARADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +111D5;SHARADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +111D6;SHARADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +111D7;SHARADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +111D8;SHARADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +111D9;SHARADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +111DA;SHARADA EKAM;Lo;0;L;;;;;N;;;;; +111DB;SHARADA SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +111DC;SHARADA HEADSTROKE;Lo;0;L;;;;;N;;;;; +111DD;SHARADA CONTINUATION SIGN;Po;0;L;;;;;N;;;;; +111DE;SHARADA SECTION MARK-1;Po;0;L;;;;;N;;;;; +111DF;SHARADA SECTION MARK-2;Po;0;L;;;;;N;;;;; +111E1;SINHALA ARCHAIC DIGIT ONE;No;0;L;;;;1;N;;;;; +111E2;SINHALA ARCHAIC DIGIT TWO;No;0;L;;;;2;N;;;;; +111E3;SINHALA ARCHAIC DIGIT THREE;No;0;L;;;;3;N;;;;; +111E4;SINHALA ARCHAIC DIGIT FOUR;No;0;L;;;;4;N;;;;; +111E5;SINHALA ARCHAIC DIGIT FIVE;No;0;L;;;;5;N;;;;; +111E6;SINHALA ARCHAIC DIGIT SIX;No;0;L;;;;6;N;;;;; +111E7;SINHALA ARCHAIC DIGIT SEVEN;No;0;L;;;;7;N;;;;; +111E8;SINHALA ARCHAIC DIGIT EIGHT;No;0;L;;;;8;N;;;;; +111E9;SINHALA ARCHAIC DIGIT NINE;No;0;L;;;;9;N;;;;; +111EA;SINHALA ARCHAIC NUMBER TEN;No;0;L;;;;10;N;;;;; +111EB;SINHALA ARCHAIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; +111EC;SINHALA ARCHAIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; +111ED;SINHALA ARCHAIC NUMBER FORTY;No;0;L;;;;40;N;;;;; +111EE;SINHALA ARCHAIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; +111EF;SINHALA ARCHAIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; +111F0;SINHALA ARCHAIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +111F1;SINHALA ARCHAIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +111F2;SINHALA ARCHAIC NUMBER NINETY;No;0;L;;;;90;N;;;;; +111F3;SINHALA ARCHAIC NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; +111F4;SINHALA ARCHAIC NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; +11200;KHOJKI LETTER A;Lo;0;L;;;;;N;;;;; +11201;KHOJKI LETTER AA;Lo;0;L;;;;;N;;;;; +11202;KHOJKI LETTER I;Lo;0;L;;;;;N;;;;; +11203;KHOJKI LETTER U;Lo;0;L;;;;;N;;;;; +11204;KHOJKI LETTER E;Lo;0;L;;;;;N;;;;; +11205;KHOJKI LETTER AI;Lo;0;L;;;;;N;;;;; +11206;KHOJKI LETTER O;Lo;0;L;;;;;N;;;;; +11207;KHOJKI LETTER AU;Lo;0;L;;;;;N;;;;; +11208;KHOJKI LETTER KA;Lo;0;L;;;;;N;;;;; +11209;KHOJKI LETTER KHA;Lo;0;L;;;;;N;;;;; +1120A;KHOJKI LETTER GA;Lo;0;L;;;;;N;;;;; +1120B;KHOJKI LETTER GGA;Lo;0;L;;;;;N;;;;; +1120C;KHOJKI LETTER GHA;Lo;0;L;;;;;N;;;;; +1120D;KHOJKI LETTER NGA;Lo;0;L;;;;;N;;;;; +1120E;KHOJKI LETTER CA;Lo;0;L;;;;;N;;;;; +1120F;KHOJKI LETTER CHA;Lo;0;L;;;;;N;;;;; +11210;KHOJKI LETTER JA;Lo;0;L;;;;;N;;;;; +11211;KHOJKI LETTER JJA;Lo;0;L;;;;;N;;;;; +11213;KHOJKI LETTER NYA;Lo;0;L;;;;;N;;;;; +11214;KHOJKI LETTER TTA;Lo;0;L;;;;;N;;;;; +11215;KHOJKI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11216;KHOJKI LETTER DDA;Lo;0;L;;;;;N;;;;; +11217;KHOJKI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11218;KHOJKI LETTER NNA;Lo;0;L;;;;;N;;;;; +11219;KHOJKI LETTER TA;Lo;0;L;;;;;N;;;;; +1121A;KHOJKI LETTER THA;Lo;0;L;;;;;N;;;;; +1121B;KHOJKI LETTER DA;Lo;0;L;;;;;N;;;;; +1121C;KHOJKI LETTER DDDA;Lo;0;L;;;;;N;;;;; +1121D;KHOJKI LETTER DHA;Lo;0;L;;;;;N;;;;; +1121E;KHOJKI LETTER NA;Lo;0;L;;;;;N;;;;; +1121F;KHOJKI LETTER PA;Lo;0;L;;;;;N;;;;; +11220;KHOJKI LETTER PHA;Lo;0;L;;;;;N;;;;; +11221;KHOJKI LETTER BA;Lo;0;L;;;;;N;;;;; +11222;KHOJKI LETTER BBA;Lo;0;L;;;;;N;;;;; +11223;KHOJKI LETTER BHA;Lo;0;L;;;;;N;;;;; +11224;KHOJKI LETTER MA;Lo;0;L;;;;;N;;;;; +11225;KHOJKI LETTER YA;Lo;0;L;;;;;N;;;;; +11226;KHOJKI LETTER RA;Lo;0;L;;;;;N;;;;; +11227;KHOJKI LETTER LA;Lo;0;L;;;;;N;;;;; +11228;KHOJKI LETTER VA;Lo;0;L;;;;;N;;;;; +11229;KHOJKI LETTER SA;Lo;0;L;;;;;N;;;;; +1122A;KHOJKI LETTER HA;Lo;0;L;;;;;N;;;;; +1122B;KHOJKI LETTER LLA;Lo;0;L;;;;;N;;;;; +1122C;KHOJKI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1122D;KHOJKI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +1122E;KHOJKI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +1122F;KHOJKI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11230;KHOJKI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11231;KHOJKI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11232;KHOJKI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11233;KHOJKI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11234;KHOJKI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11235;KHOJKI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; +11236;KHOJKI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11237;KHOJKI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; +11238;KHOJKI DANDA;Po;0;L;;;;;N;;;;; +11239;KHOJKI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +1123A;KHOJKI WORD SEPARATOR;Po;0;L;;;;;N;;;;; +1123B;KHOJKI SECTION MARK;Po;0;L;;;;;N;;;;; +1123C;KHOJKI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; +1123D;KHOJKI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +1123E;KHOJKI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; +11280;MULTANI LETTER A;Lo;0;L;;;;;N;;;;; +11281;MULTANI LETTER I;Lo;0;L;;;;;N;;;;; +11282;MULTANI LETTER U;Lo;0;L;;;;;N;;;;; +11283;MULTANI LETTER E;Lo;0;L;;;;;N;;;;; +11284;MULTANI LETTER KA;Lo;0;L;;;;;N;;;;; +11285;MULTANI LETTER KHA;Lo;0;L;;;;;N;;;;; +11286;MULTANI LETTER GA;Lo;0;L;;;;;N;;;;; +11288;MULTANI LETTER GHA;Lo;0;L;;;;;N;;;;; +1128A;MULTANI LETTER CA;Lo;0;L;;;;;N;;;;; +1128B;MULTANI LETTER CHA;Lo;0;L;;;;;N;;;;; +1128C;MULTANI LETTER JA;Lo;0;L;;;;;N;;;;; +1128D;MULTANI LETTER JJA;Lo;0;L;;;;;N;;;;; +1128F;MULTANI LETTER NYA;Lo;0;L;;;;;N;;;;; +11290;MULTANI LETTER TTA;Lo;0;L;;;;;N;;;;; +11291;MULTANI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11292;MULTANI LETTER DDA;Lo;0;L;;;;;N;;;;; +11293;MULTANI LETTER DDDA;Lo;0;L;;;;;N;;;;; +11294;MULTANI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11295;MULTANI LETTER NNA;Lo;0;L;;;;;N;;;;; +11296;MULTANI LETTER TA;Lo;0;L;;;;;N;;;;; +11297;MULTANI LETTER THA;Lo;0;L;;;;;N;;;;; +11298;MULTANI LETTER DA;Lo;0;L;;;;;N;;;;; +11299;MULTANI LETTER DHA;Lo;0;L;;;;;N;;;;; +1129A;MULTANI LETTER NA;Lo;0;L;;;;;N;;;;; +1129B;MULTANI LETTER PA;Lo;0;L;;;;;N;;;;; +1129C;MULTANI LETTER PHA;Lo;0;L;;;;;N;;;;; +1129D;MULTANI LETTER BA;Lo;0;L;;;;;N;;;;; +1129F;MULTANI LETTER BHA;Lo;0;L;;;;;N;;;;; +112A0;MULTANI LETTER MA;Lo;0;L;;;;;N;;;;; +112A1;MULTANI LETTER YA;Lo;0;L;;;;;N;;;;; +112A2;MULTANI LETTER RA;Lo;0;L;;;;;N;;;;; +112A3;MULTANI LETTER LA;Lo;0;L;;;;;N;;;;; +112A4;MULTANI LETTER VA;Lo;0;L;;;;;N;;;;; +112A5;MULTANI LETTER SA;Lo;0;L;;;;;N;;;;; +112A6;MULTANI LETTER HA;Lo;0;L;;;;;N;;;;; +112A7;MULTANI LETTER RRA;Lo;0;L;;;;;N;;;;; +112A8;MULTANI LETTER RHA;Lo;0;L;;;;;N;;;;; +112A9;MULTANI SECTION MARK;Po;0;L;;;;;N;;;;; +112B0;KHUDAWADI LETTER A;Lo;0;L;;;;;N;;;;; +112B1;KHUDAWADI LETTER AA;Lo;0;L;;;;;N;;;;; +112B2;KHUDAWADI LETTER I;Lo;0;L;;;;;N;;;;; +112B3;KHUDAWADI LETTER II;Lo;0;L;;;;;N;;;;; +112B4;KHUDAWADI LETTER U;Lo;0;L;;;;;N;;;;; +112B5;KHUDAWADI LETTER UU;Lo;0;L;;;;;N;;;;; +112B6;KHUDAWADI LETTER E;Lo;0;L;;;;;N;;;;; +112B7;KHUDAWADI LETTER AI;Lo;0;L;;;;;N;;;;; +112B8;KHUDAWADI LETTER O;Lo;0;L;;;;;N;;;;; +112B9;KHUDAWADI LETTER AU;Lo;0;L;;;;;N;;;;; +112BA;KHUDAWADI LETTER KA;Lo;0;L;;;;;N;;;;; +112BB;KHUDAWADI LETTER KHA;Lo;0;L;;;;;N;;;;; +112BC;KHUDAWADI LETTER GA;Lo;0;L;;;;;N;;;;; +112BD;KHUDAWADI LETTER GGA;Lo;0;L;;;;;N;;;;; +112BE;KHUDAWADI LETTER GHA;Lo;0;L;;;;;N;;;;; +112BF;KHUDAWADI LETTER NGA;Lo;0;L;;;;;N;;;;; +112C0;KHUDAWADI LETTER CA;Lo;0;L;;;;;N;;;;; +112C1;KHUDAWADI LETTER CHA;Lo;0;L;;;;;N;;;;; +112C2;KHUDAWADI LETTER JA;Lo;0;L;;;;;N;;;;; +112C3;KHUDAWADI LETTER JJA;Lo;0;L;;;;;N;;;;; +112C4;KHUDAWADI LETTER JHA;Lo;0;L;;;;;N;;;;; +112C5;KHUDAWADI LETTER NYA;Lo;0;L;;;;;N;;;;; +112C6;KHUDAWADI LETTER TTA;Lo;0;L;;;;;N;;;;; +112C7;KHUDAWADI LETTER TTHA;Lo;0;L;;;;;N;;;;; +112C8;KHUDAWADI LETTER DDA;Lo;0;L;;;;;N;;;;; +112C9;KHUDAWADI LETTER DDDA;Lo;0;L;;;;;N;;;;; +112CA;KHUDAWADI LETTER RRA;Lo;0;L;;;;;N;;;;; +112CB;KHUDAWADI LETTER DDHA;Lo;0;L;;;;;N;;;;; +112CC;KHUDAWADI LETTER NNA;Lo;0;L;;;;;N;;;;; +112CD;KHUDAWADI LETTER TA;Lo;0;L;;;;;N;;;;; +112CE;KHUDAWADI LETTER THA;Lo;0;L;;;;;N;;;;; +112CF;KHUDAWADI LETTER DA;Lo;0;L;;;;;N;;;;; +112D0;KHUDAWADI LETTER DHA;Lo;0;L;;;;;N;;;;; +112D1;KHUDAWADI LETTER NA;Lo;0;L;;;;;N;;;;; +112D2;KHUDAWADI LETTER PA;Lo;0;L;;;;;N;;;;; +112D3;KHUDAWADI LETTER PHA;Lo;0;L;;;;;N;;;;; +112D4;KHUDAWADI LETTER BA;Lo;0;L;;;;;N;;;;; +112D5;KHUDAWADI LETTER BBA;Lo;0;L;;;;;N;;;;; +112D6;KHUDAWADI LETTER BHA;Lo;0;L;;;;;N;;;;; +112D7;KHUDAWADI LETTER MA;Lo;0;L;;;;;N;;;;; +112D8;KHUDAWADI LETTER YA;Lo;0;L;;;;;N;;;;; +112D9;KHUDAWADI LETTER RA;Lo;0;L;;;;;N;;;;; +112DA;KHUDAWADI LETTER LA;Lo;0;L;;;;;N;;;;; +112DB;KHUDAWADI LETTER VA;Lo;0;L;;;;;N;;;;; +112DC;KHUDAWADI LETTER SHA;Lo;0;L;;;;;N;;;;; +112DD;KHUDAWADI LETTER SA;Lo;0;L;;;;;N;;;;; +112DE;KHUDAWADI LETTER HA;Lo;0;L;;;;;N;;;;; +112DF;KHUDAWADI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +112E0;KHUDAWADI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +112E1;KHUDAWADI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +112E2;KHUDAWADI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +112E3;KHUDAWADI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +112E4;KHUDAWADI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +112E5;KHUDAWADI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +112E6;KHUDAWADI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +112E7;KHUDAWADI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +112E8;KHUDAWADI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +112E9;KHUDAWADI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +112EA;KHUDAWADI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +112F0;KHUDAWADI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +112F1;KHUDAWADI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +112F2;KHUDAWADI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +112F3;KHUDAWADI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +112F4;KHUDAWADI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +112F5;KHUDAWADI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +112F6;KHUDAWADI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +112F7;KHUDAWADI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +112F8;KHUDAWADI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +112F9;KHUDAWADI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11300;GRANTHA SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; +11301;GRANTHA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11302;GRANTHA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +11303;GRANTHA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11305;GRANTHA LETTER A;Lo;0;L;;;;;N;;;;; +11306;GRANTHA LETTER AA;Lo;0;L;;;;;N;;;;; +11307;GRANTHA LETTER I;Lo;0;L;;;;;N;;;;; +11308;GRANTHA LETTER II;Lo;0;L;;;;;N;;;;; +11309;GRANTHA LETTER U;Lo;0;L;;;;;N;;;;; +1130A;GRANTHA LETTER UU;Lo;0;L;;;;;N;;;;; +1130B;GRANTHA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1130C;GRANTHA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1130F;GRANTHA LETTER EE;Lo;0;L;;;;;N;;;;; +11310;GRANTHA LETTER AI;Lo;0;L;;;;;N;;;;; +11313;GRANTHA LETTER OO;Lo;0;L;;;;;N;;;;; +11314;GRANTHA LETTER AU;Lo;0;L;;;;;N;;;;; +11315;GRANTHA LETTER KA;Lo;0;L;;;;;N;;;;; +11316;GRANTHA LETTER KHA;Lo;0;L;;;;;N;;;;; +11317;GRANTHA LETTER GA;Lo;0;L;;;;;N;;;;; +11318;GRANTHA LETTER GHA;Lo;0;L;;;;;N;;;;; +11319;GRANTHA LETTER NGA;Lo;0;L;;;;;N;;;;; +1131A;GRANTHA LETTER CA;Lo;0;L;;;;;N;;;;; +1131B;GRANTHA LETTER CHA;Lo;0;L;;;;;N;;;;; +1131C;GRANTHA LETTER JA;Lo;0;L;;;;;N;;;;; +1131D;GRANTHA LETTER JHA;Lo;0;L;;;;;N;;;;; +1131E;GRANTHA LETTER NYA;Lo;0;L;;;;;N;;;;; +1131F;GRANTHA LETTER TTA;Lo;0;L;;;;;N;;;;; +11320;GRANTHA LETTER TTHA;Lo;0;L;;;;;N;;;;; +11321;GRANTHA LETTER DDA;Lo;0;L;;;;;N;;;;; +11322;GRANTHA LETTER DDHA;Lo;0;L;;;;;N;;;;; +11323;GRANTHA LETTER NNA;Lo;0;L;;;;;N;;;;; +11324;GRANTHA LETTER TA;Lo;0;L;;;;;N;;;;; +11325;GRANTHA LETTER THA;Lo;0;L;;;;;N;;;;; +11326;GRANTHA LETTER DA;Lo;0;L;;;;;N;;;;; +11327;GRANTHA LETTER DHA;Lo;0;L;;;;;N;;;;; +11328;GRANTHA LETTER NA;Lo;0;L;;;;;N;;;;; +1132A;GRANTHA LETTER PA;Lo;0;L;;;;;N;;;;; +1132B;GRANTHA LETTER PHA;Lo;0;L;;;;;N;;;;; +1132C;GRANTHA LETTER BA;Lo;0;L;;;;;N;;;;; +1132D;GRANTHA LETTER BHA;Lo;0;L;;;;;N;;;;; +1132E;GRANTHA LETTER MA;Lo;0;L;;;;;N;;;;; +1132F;GRANTHA LETTER YA;Lo;0;L;;;;;N;;;;; +11330;GRANTHA LETTER RA;Lo;0;L;;;;;N;;;;; +11332;GRANTHA LETTER LA;Lo;0;L;;;;;N;;;;; +11333;GRANTHA LETTER LLA;Lo;0;L;;;;;N;;;;; +11335;GRANTHA LETTER VA;Lo;0;L;;;;;N;;;;; +11336;GRANTHA LETTER SHA;Lo;0;L;;;;;N;;;;; +11337;GRANTHA LETTER SSA;Lo;0;L;;;;;N;;;;; +11338;GRANTHA LETTER SA;Lo;0;L;;;;;N;;;;; +11339;GRANTHA LETTER HA;Lo;0;L;;;;;N;;;;; +1133C;GRANTHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +1133D;GRANTHA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +1133E;GRANTHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1133F;GRANTHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11340;GRANTHA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11341;GRANTHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +11342;GRANTHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +11343;GRANTHA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +11344;GRANTHA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +11347;GRANTHA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +11348;GRANTHA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +1134B;GRANTHA VOWEL SIGN OO;Mc;0;L;11347 1133E;;;;N;;;;; +1134C;GRANTHA VOWEL SIGN AU;Mc;0;L;11347 11357;;;;N;;;;; +1134D;GRANTHA SIGN VIRAMA;Mc;9;L;;;;;N;;;;; +11350;GRANTHA OM;Lo;0;L;;;;;N;;;;; +11357;GRANTHA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +1135D;GRANTHA SIGN PLUTA;Lo;0;L;;;;;N;;;;; +1135E;GRANTHA LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +1135F;GRANTHA LETTER VEDIC DOUBLE ANUSVARA;Lo;0;L;;;;;N;;;;; +11360;GRANTHA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11361;GRANTHA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +11362;GRANTHA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; +11363;GRANTHA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; +11366;COMBINING GRANTHA DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; +11367;COMBINING GRANTHA DIGIT ONE;Mn;230;NSM;;;;;N;;;;; +11368;COMBINING GRANTHA DIGIT TWO;Mn;230;NSM;;;;;N;;;;; +11369;COMBINING GRANTHA DIGIT THREE;Mn;230;NSM;;;;;N;;;;; +1136A;COMBINING GRANTHA DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; +1136B;COMBINING GRANTHA DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; +1136C;COMBINING GRANTHA DIGIT SIX;Mn;230;NSM;;;;;N;;;;; +11370;COMBINING GRANTHA LETTER A;Mn;230;NSM;;;;;N;;;;; +11371;COMBINING GRANTHA LETTER KA;Mn;230;NSM;;;;;N;;;;; +11372;COMBINING GRANTHA LETTER NA;Mn;230;NSM;;;;;N;;;;; +11373;COMBINING GRANTHA LETTER VI;Mn;230;NSM;;;;;N;;;;; +11374;COMBINING GRANTHA LETTER PA;Mn;230;NSM;;;;;N;;;;; +11400;NEWA LETTER A;Lo;0;L;;;;;N;;;;; +11401;NEWA LETTER AA;Lo;0;L;;;;;N;;;;; +11402;NEWA LETTER I;Lo;0;L;;;;;N;;;;; +11403;NEWA LETTER II;Lo;0;L;;;;;N;;;;; +11404;NEWA LETTER U;Lo;0;L;;;;;N;;;;; +11405;NEWA LETTER UU;Lo;0;L;;;;;N;;;;; +11406;NEWA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11407;NEWA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11408;NEWA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11409;NEWA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1140A;NEWA LETTER E;Lo;0;L;;;;;N;;;;; +1140B;NEWA LETTER AI;Lo;0;L;;;;;N;;;;; +1140C;NEWA LETTER O;Lo;0;L;;;;;N;;;;; +1140D;NEWA LETTER AU;Lo;0;L;;;;;N;;;;; +1140E;NEWA LETTER KA;Lo;0;L;;;;;N;;;;; +1140F;NEWA LETTER KHA;Lo;0;L;;;;;N;;;;; +11410;NEWA LETTER GA;Lo;0;L;;;;;N;;;;; +11411;NEWA LETTER GHA;Lo;0;L;;;;;N;;;;; +11412;NEWA LETTER NGA;Lo;0;L;;;;;N;;;;; +11413;NEWA LETTER NGHA;Lo;0;L;;;;;N;;;;; +11414;NEWA LETTER CA;Lo;0;L;;;;;N;;;;; +11415;NEWA LETTER CHA;Lo;0;L;;;;;N;;;;; +11416;NEWA LETTER JA;Lo;0;L;;;;;N;;;;; +11417;NEWA LETTER JHA;Lo;0;L;;;;;N;;;;; +11418;NEWA LETTER NYA;Lo;0;L;;;;;N;;;;; +11419;NEWA LETTER NYHA;Lo;0;L;;;;;N;;;;; +1141A;NEWA LETTER TTA;Lo;0;L;;;;;N;;;;; +1141B;NEWA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1141C;NEWA LETTER DDA;Lo;0;L;;;;;N;;;;; +1141D;NEWA LETTER DDHA;Lo;0;L;;;;;N;;;;; +1141E;NEWA LETTER NNA;Lo;0;L;;;;;N;;;;; +1141F;NEWA LETTER TA;Lo;0;L;;;;;N;;;;; +11420;NEWA LETTER THA;Lo;0;L;;;;;N;;;;; +11421;NEWA LETTER DA;Lo;0;L;;;;;N;;;;; +11422;NEWA LETTER DHA;Lo;0;L;;;;;N;;;;; +11423;NEWA LETTER NA;Lo;0;L;;;;;N;;;;; +11424;NEWA LETTER NHA;Lo;0;L;;;;;N;;;;; +11425;NEWA LETTER PA;Lo;0;L;;;;;N;;;;; +11426;NEWA LETTER PHA;Lo;0;L;;;;;N;;;;; +11427;NEWA LETTER BA;Lo;0;L;;;;;N;;;;; +11428;NEWA LETTER BHA;Lo;0;L;;;;;N;;;;; +11429;NEWA LETTER MA;Lo;0;L;;;;;N;;;;; +1142A;NEWA LETTER MHA;Lo;0;L;;;;;N;;;;; +1142B;NEWA LETTER YA;Lo;0;L;;;;;N;;;;; +1142C;NEWA LETTER RA;Lo;0;L;;;;;N;;;;; +1142D;NEWA LETTER RHA;Lo;0;L;;;;;N;;;;; +1142E;NEWA LETTER LA;Lo;0;L;;;;;N;;;;; +1142F;NEWA LETTER LHA;Lo;0;L;;;;;N;;;;; +11430;NEWA LETTER WA;Lo;0;L;;;;;N;;;;; +11431;NEWA LETTER SHA;Lo;0;L;;;;;N;;;;; +11432;NEWA LETTER SSA;Lo;0;L;;;;;N;;;;; +11433;NEWA LETTER SA;Lo;0;L;;;;;N;;;;; +11434;NEWA LETTER HA;Lo;0;L;;;;;N;;;;; +11435;NEWA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11436;NEWA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11437;NEWA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +11438;NEWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11439;NEWA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1143A;NEWA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +1143B;NEWA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +1143C;NEWA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +1143D;NEWA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +1143E;NEWA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1143F;NEWA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11440;NEWA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11441;NEWA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11442;NEWA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11443;NEWA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11444;NEWA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11445;NEWA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11446;NEWA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11447;NEWA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +11448;NEWA SIGN FINAL ANUSVARA;Lo;0;L;;;;;N;;;;; +11449;NEWA OM;Lo;0;L;;;;;N;;;;; +1144A;NEWA SIDDHI;Lo;0;L;;;;;N;;;;; +1144B;NEWA DANDA;Po;0;L;;;;;N;;;;; +1144C;NEWA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +1144D;NEWA COMMA;Po;0;L;;;;;N;;;;; +1144E;NEWA GAP FILLER;Po;0;L;;;;;N;;;;; +1144F;NEWA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +11450;NEWA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11451;NEWA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11452;NEWA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11453;NEWA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11454;NEWA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11455;NEWA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11456;NEWA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11457;NEWA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11458;NEWA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11459;NEWA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1145B;NEWA PLACEHOLDER MARK;Po;0;L;;;;;N;;;;; +1145D;NEWA INSERTION SIGN;Po;0;L;;;;;N;;;;; +11480;TIRHUTA ANJI;Lo;0;L;;;;;N;;;;; +11481;TIRHUTA LETTER A;Lo;0;L;;;;;N;;;;; +11482;TIRHUTA LETTER AA;Lo;0;L;;;;;N;;;;; +11483;TIRHUTA LETTER I;Lo;0;L;;;;;N;;;;; +11484;TIRHUTA LETTER II;Lo;0;L;;;;;N;;;;; +11485;TIRHUTA LETTER U;Lo;0;L;;;;;N;;;;; +11486;TIRHUTA LETTER UU;Lo;0;L;;;;;N;;;;; +11487;TIRHUTA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11488;TIRHUTA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11489;TIRHUTA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1148A;TIRHUTA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1148B;TIRHUTA LETTER E;Lo;0;L;;;;;N;;;;; +1148C;TIRHUTA LETTER AI;Lo;0;L;;;;;N;;;;; +1148D;TIRHUTA LETTER O;Lo;0;L;;;;;N;;;;; +1148E;TIRHUTA LETTER AU;Lo;0;L;;;;;N;;;;; +1148F;TIRHUTA LETTER KA;Lo;0;L;;;;;N;;;;; +11490;TIRHUTA LETTER KHA;Lo;0;L;;;;;N;;;;; +11491;TIRHUTA LETTER GA;Lo;0;L;;;;;N;;;;; +11492;TIRHUTA LETTER GHA;Lo;0;L;;;;;N;;;;; +11493;TIRHUTA LETTER NGA;Lo;0;L;;;;;N;;;;; +11494;TIRHUTA LETTER CA;Lo;0;L;;;;;N;;;;; +11495;TIRHUTA LETTER CHA;Lo;0;L;;;;;N;;;;; +11496;TIRHUTA LETTER JA;Lo;0;L;;;;;N;;;;; +11497;TIRHUTA LETTER JHA;Lo;0;L;;;;;N;;;;; +11498;TIRHUTA LETTER NYA;Lo;0;L;;;;;N;;;;; +11499;TIRHUTA LETTER TTA;Lo;0;L;;;;;N;;;;; +1149A;TIRHUTA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1149B;TIRHUTA LETTER DDA;Lo;0;L;;;;;N;;;;; +1149C;TIRHUTA LETTER DDHA;Lo;0;L;;;;;N;;;;; +1149D;TIRHUTA LETTER NNA;Lo;0;L;;;;;N;;;;; +1149E;TIRHUTA LETTER TA;Lo;0;L;;;;;N;;;;; +1149F;TIRHUTA LETTER THA;Lo;0;L;;;;;N;;;;; +114A0;TIRHUTA LETTER DA;Lo;0;L;;;;;N;;;;; +114A1;TIRHUTA LETTER DHA;Lo;0;L;;;;;N;;;;; +114A2;TIRHUTA LETTER NA;Lo;0;L;;;;;N;;;;; +114A3;TIRHUTA LETTER PA;Lo;0;L;;;;;N;;;;; +114A4;TIRHUTA LETTER PHA;Lo;0;L;;;;;N;;;;; +114A5;TIRHUTA LETTER BA;Lo;0;L;;;;;N;;;;; +114A6;TIRHUTA LETTER BHA;Lo;0;L;;;;;N;;;;; +114A7;TIRHUTA LETTER MA;Lo;0;L;;;;;N;;;;; +114A8;TIRHUTA LETTER YA;Lo;0;L;;;;;N;;;;; +114A9;TIRHUTA LETTER RA;Lo;0;L;;;;;N;;;;; +114AA;TIRHUTA LETTER LA;Lo;0;L;;;;;N;;;;; +114AB;TIRHUTA LETTER VA;Lo;0;L;;;;;N;;;;; +114AC;TIRHUTA LETTER SHA;Lo;0;L;;;;;N;;;;; +114AD;TIRHUTA LETTER SSA;Lo;0;L;;;;;N;;;;; +114AE;TIRHUTA LETTER SA;Lo;0;L;;;;;N;;;;; +114AF;TIRHUTA LETTER HA;Lo;0;L;;;;;N;;;;; +114B0;TIRHUTA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +114B1;TIRHUTA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +114B2;TIRHUTA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +114B3;TIRHUTA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +114B4;TIRHUTA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +114B5;TIRHUTA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +114B6;TIRHUTA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +114B7;TIRHUTA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +114B8;TIRHUTA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +114B9;TIRHUTA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +114BA;TIRHUTA VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; +114BB;TIRHUTA VOWEL SIGN AI;Mc;0;L;114B9 114BA;;;;N;;;;; +114BC;TIRHUTA VOWEL SIGN O;Mc;0;L;114B9 114B0;;;;N;;;;; +114BD;TIRHUTA VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; +114BE;TIRHUTA VOWEL SIGN AU;Mc;0;L;114B9 114BD;;;;N;;;;; +114BF;TIRHUTA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +114C0;TIRHUTA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +114C1;TIRHUTA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +114C2;TIRHUTA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +114C3;TIRHUTA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +114C4;TIRHUTA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +114C5;TIRHUTA GVANG;Lo;0;L;;;;;N;;;;; +114C6;TIRHUTA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +114C7;TIRHUTA OM;Lo;0;L;;;;;N;;;;; +114D0;TIRHUTA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +114D1;TIRHUTA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +114D2;TIRHUTA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +114D3;TIRHUTA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +114D4;TIRHUTA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +114D5;TIRHUTA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +114D6;TIRHUTA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +114D7;TIRHUTA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +114D8;TIRHUTA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +114D9;TIRHUTA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11580;SIDDHAM LETTER A;Lo;0;L;;;;;N;;;;; +11581;SIDDHAM LETTER AA;Lo;0;L;;;;;N;;;;; +11582;SIDDHAM LETTER I;Lo;0;L;;;;;N;;;;; +11583;SIDDHAM LETTER II;Lo;0;L;;;;;N;;;;; +11584;SIDDHAM LETTER U;Lo;0;L;;;;;N;;;;; +11585;SIDDHAM LETTER UU;Lo;0;L;;;;;N;;;;; +11586;SIDDHAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11587;SIDDHAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11588;SIDDHAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11589;SIDDHAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1158A;SIDDHAM LETTER E;Lo;0;L;;;;;N;;;;; +1158B;SIDDHAM LETTER AI;Lo;0;L;;;;;N;;;;; +1158C;SIDDHAM LETTER O;Lo;0;L;;;;;N;;;;; +1158D;SIDDHAM LETTER AU;Lo;0;L;;;;;N;;;;; +1158E;SIDDHAM LETTER KA;Lo;0;L;;;;;N;;;;; +1158F;SIDDHAM LETTER KHA;Lo;0;L;;;;;N;;;;; +11590;SIDDHAM LETTER GA;Lo;0;L;;;;;N;;;;; +11591;SIDDHAM LETTER GHA;Lo;0;L;;;;;N;;;;; +11592;SIDDHAM LETTER NGA;Lo;0;L;;;;;N;;;;; +11593;SIDDHAM LETTER CA;Lo;0;L;;;;;N;;;;; +11594;SIDDHAM LETTER CHA;Lo;0;L;;;;;N;;;;; +11595;SIDDHAM LETTER JA;Lo;0;L;;;;;N;;;;; +11596;SIDDHAM LETTER JHA;Lo;0;L;;;;;N;;;;; +11597;SIDDHAM LETTER NYA;Lo;0;L;;;;;N;;;;; +11598;SIDDHAM LETTER TTA;Lo;0;L;;;;;N;;;;; +11599;SIDDHAM LETTER TTHA;Lo;0;L;;;;;N;;;;; +1159A;SIDDHAM LETTER DDA;Lo;0;L;;;;;N;;;;; +1159B;SIDDHAM LETTER DDHA;Lo;0;L;;;;;N;;;;; +1159C;SIDDHAM LETTER NNA;Lo;0;L;;;;;N;;;;; +1159D;SIDDHAM LETTER TA;Lo;0;L;;;;;N;;;;; +1159E;SIDDHAM LETTER THA;Lo;0;L;;;;;N;;;;; +1159F;SIDDHAM LETTER DA;Lo;0;L;;;;;N;;;;; +115A0;SIDDHAM LETTER DHA;Lo;0;L;;;;;N;;;;; +115A1;SIDDHAM LETTER NA;Lo;0;L;;;;;N;;;;; +115A2;SIDDHAM LETTER PA;Lo;0;L;;;;;N;;;;; +115A3;SIDDHAM LETTER PHA;Lo;0;L;;;;;N;;;;; +115A4;SIDDHAM LETTER BA;Lo;0;L;;;;;N;;;;; +115A5;SIDDHAM LETTER BHA;Lo;0;L;;;;;N;;;;; +115A6;SIDDHAM LETTER MA;Lo;0;L;;;;;N;;;;; +115A7;SIDDHAM LETTER YA;Lo;0;L;;;;;N;;;;; +115A8;SIDDHAM LETTER RA;Lo;0;L;;;;;N;;;;; +115A9;SIDDHAM LETTER LA;Lo;0;L;;;;;N;;;;; +115AA;SIDDHAM LETTER VA;Lo;0;L;;;;;N;;;;; +115AB;SIDDHAM LETTER SHA;Lo;0;L;;;;;N;;;;; +115AC;SIDDHAM LETTER SSA;Lo;0;L;;;;;N;;;;; +115AD;SIDDHAM LETTER SA;Lo;0;L;;;;;N;;;;; +115AE;SIDDHAM LETTER HA;Lo;0;L;;;;;N;;;;; +115AF;SIDDHAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +115B0;SIDDHAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +115B1;SIDDHAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +115B2;SIDDHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +115B3;SIDDHAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +115B4;SIDDHAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +115B5;SIDDHAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +115B8;SIDDHAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +115B9;SIDDHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +115BA;SIDDHAM VOWEL SIGN O;Mc;0;L;115B8 115AF;;;;N;;;;; +115BB;SIDDHAM VOWEL SIGN AU;Mc;0;L;115B9 115AF;;;;N;;;;; +115BC;SIDDHAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +115BD;SIDDHAM SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +115BE;SIDDHAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; +115BF;SIDDHAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +115C0;SIDDHAM SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +115C1;SIDDHAM SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +115C2;SIDDHAM DANDA;Po;0;L;;;;;N;;;;; +115C3;SIDDHAM DOUBLE DANDA;Po;0;L;;;;;N;;;;; +115C4;SIDDHAM SEPARATOR DOT;Po;0;L;;;;;N;;;;; +115C5;SIDDHAM SEPARATOR BAR;Po;0;L;;;;;N;;;;; +115C6;SIDDHAM REPETITION MARK-1;Po;0;L;;;;;N;;;;; +115C7;SIDDHAM REPETITION MARK-2;Po;0;L;;;;;N;;;;; +115C8;SIDDHAM REPETITION MARK-3;Po;0;L;;;;;N;;;;; +115C9;SIDDHAM END OF TEXT MARK;Po;0;L;;;;;N;;;;; +115CA;SIDDHAM SECTION MARK WITH TRIDENT AND U-SHAPED ORNAMENTS;Po;0;L;;;;;N;;;;; +115CB;SIDDHAM SECTION MARK WITH TRIDENT AND DOTTED CRESCENTS;Po;0;L;;;;;N;;;;; +115CC;SIDDHAM SECTION MARK WITH RAYS AND DOTTED CRESCENTS;Po;0;L;;;;;N;;;;; +115CD;SIDDHAM SECTION MARK WITH RAYS AND DOTTED DOUBLE CRESCENTS;Po;0;L;;;;;N;;;;; +115CE;SIDDHAM SECTION MARK WITH RAYS AND DOTTED TRIPLE CRESCENTS;Po;0;L;;;;;N;;;;; +115CF;SIDDHAM SECTION MARK DOUBLE RING;Po;0;L;;;;;N;;;;; +115D0;SIDDHAM SECTION MARK DOUBLE RING WITH RAYS;Po;0;L;;;;;N;;;;; +115D1;SIDDHAM SECTION MARK WITH DOUBLE CRESCENTS;Po;0;L;;;;;N;;;;; +115D2;SIDDHAM SECTION MARK WITH TRIPLE CRESCENTS;Po;0;L;;;;;N;;;;; +115D3;SIDDHAM SECTION MARK WITH QUADRUPLE CRESCENTS;Po;0;L;;;;;N;;;;; +115D4;SIDDHAM SECTION MARK WITH SEPTUPLE CRESCENTS;Po;0;L;;;;;N;;;;; +115D5;SIDDHAM SECTION MARK WITH CIRCLES AND RAYS;Po;0;L;;;;;N;;;;; +115D6;SIDDHAM SECTION MARK WITH CIRCLES AND TWO ENCLOSURES;Po;0;L;;;;;N;;;;; +115D7;SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES;Po;0;L;;;;;N;;;;; +115D8;SIDDHAM LETTER THREE-CIRCLE ALTERNATE I;Lo;0;L;;;;;N;;;;; +115D9;SIDDHAM LETTER TWO-CIRCLE ALTERNATE I;Lo;0;L;;;;;N;;;;; +115DA;SIDDHAM LETTER TWO-CIRCLE ALTERNATE II;Lo;0;L;;;;;N;;;;; +115DB;SIDDHAM LETTER ALTERNATE U;Lo;0;L;;;;;N;;;;; +115DC;SIDDHAM VOWEL SIGN ALTERNATE U;Mn;0;NSM;;;;;N;;;;; +115DD;SIDDHAM VOWEL SIGN ALTERNATE UU;Mn;0;NSM;;;;;N;;;;; +11600;MODI LETTER A;Lo;0;L;;;;;N;;;;; +11601;MODI LETTER AA;Lo;0;L;;;;;N;;;;; +11602;MODI LETTER I;Lo;0;L;;;;;N;;;;; +11603;MODI LETTER II;Lo;0;L;;;;;N;;;;; +11604;MODI LETTER U;Lo;0;L;;;;;N;;;;; +11605;MODI LETTER UU;Lo;0;L;;;;;N;;;;; +11606;MODI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11607;MODI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11608;MODI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11609;MODI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1160A;MODI LETTER E;Lo;0;L;;;;;N;;;;; +1160B;MODI LETTER AI;Lo;0;L;;;;;N;;;;; +1160C;MODI LETTER O;Lo;0;L;;;;;N;;;;; +1160D;MODI LETTER AU;Lo;0;L;;;;;N;;;;; +1160E;MODI LETTER KA;Lo;0;L;;;;;N;;;;; +1160F;MODI LETTER KHA;Lo;0;L;;;;;N;;;;; +11610;MODI LETTER GA;Lo;0;L;;;;;N;;;;; +11611;MODI LETTER GHA;Lo;0;L;;;;;N;;;;; +11612;MODI LETTER NGA;Lo;0;L;;;;;N;;;;; +11613;MODI LETTER CA;Lo;0;L;;;;;N;;;;; +11614;MODI LETTER CHA;Lo;0;L;;;;;N;;;;; +11615;MODI LETTER JA;Lo;0;L;;;;;N;;;;; +11616;MODI LETTER JHA;Lo;0;L;;;;;N;;;;; +11617;MODI LETTER NYA;Lo;0;L;;;;;N;;;;; +11618;MODI LETTER TTA;Lo;0;L;;;;;N;;;;; +11619;MODI LETTER TTHA;Lo;0;L;;;;;N;;;;; +1161A;MODI LETTER DDA;Lo;0;L;;;;;N;;;;; +1161B;MODI LETTER DDHA;Lo;0;L;;;;;N;;;;; +1161C;MODI LETTER NNA;Lo;0;L;;;;;N;;;;; +1161D;MODI LETTER TA;Lo;0;L;;;;;N;;;;; +1161E;MODI LETTER THA;Lo;0;L;;;;;N;;;;; +1161F;MODI LETTER DA;Lo;0;L;;;;;N;;;;; +11620;MODI LETTER DHA;Lo;0;L;;;;;N;;;;; +11621;MODI LETTER NA;Lo;0;L;;;;;N;;;;; +11622;MODI LETTER PA;Lo;0;L;;;;;N;;;;; +11623;MODI LETTER PHA;Lo;0;L;;;;;N;;;;; +11624;MODI LETTER BA;Lo;0;L;;;;;N;;;;; +11625;MODI LETTER BHA;Lo;0;L;;;;;N;;;;; +11626;MODI LETTER MA;Lo;0;L;;;;;N;;;;; +11627;MODI LETTER YA;Lo;0;L;;;;;N;;;;; +11628;MODI LETTER RA;Lo;0;L;;;;;N;;;;; +11629;MODI LETTER LA;Lo;0;L;;;;;N;;;;; +1162A;MODI LETTER VA;Lo;0;L;;;;;N;;;;; +1162B;MODI LETTER SHA;Lo;0;L;;;;;N;;;;; +1162C;MODI LETTER SSA;Lo;0;L;;;;;N;;;;; +1162D;MODI LETTER SA;Lo;0;L;;;;;N;;;;; +1162E;MODI LETTER HA;Lo;0;L;;;;;N;;;;; +1162F;MODI LETTER LLA;Lo;0;L;;;;;N;;;;; +11630;MODI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11631;MODI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11632;MODI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +11633;MODI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11634;MODI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11635;MODI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11636;MODI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11637;MODI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11638;MODI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +11639;MODI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1163A;MODI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +1163B;MODI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1163C;MODI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +1163D;MODI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +1163E;MODI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +1163F;MODI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11640;MODI SIGN ARDHACANDRA;Mn;0;NSM;;;;;N;;;;; +11641;MODI DANDA;Po;0;L;;;;;N;;;;; +11642;MODI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11643;MODI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +11644;MODI SIGN HUVA;Lo;0;L;;;;;N;;;;; +11650;MODI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11651;MODI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11652;MODI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11653;MODI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11654;MODI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11655;MODI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11656;MODI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11657;MODI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11658;MODI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11659;MODI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11660;MONGOLIAN BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11661;MONGOLIAN ROTATED BIRGA;Po;0;ON;;;;;N;;;;; +11662;MONGOLIAN DOUBLE BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11663;MONGOLIAN TRIPLE BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11664;MONGOLIAN BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11665;MONGOLIAN ROTATED BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11666;MONGOLIAN ROTATED BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11667;MONGOLIAN INVERTED BIRGA;Po;0;ON;;;;;N;;;;; +11668;MONGOLIAN INVERTED BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11669;MONGOLIAN SWIRL BIRGA;Po;0;ON;;;;;N;;;;; +1166A;MONGOLIAN SWIRL BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +1166B;MONGOLIAN SWIRL BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +1166C;MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11680;TAKRI LETTER A;Lo;0;L;;;;;N;;;;; +11681;TAKRI LETTER AA;Lo;0;L;;;;;N;;;;; +11682;TAKRI LETTER I;Lo;0;L;;;;;N;;;;; +11683;TAKRI LETTER II;Lo;0;L;;;;;N;;;;; +11684;TAKRI LETTER U;Lo;0;L;;;;;N;;;;; +11685;TAKRI LETTER UU;Lo;0;L;;;;;N;;;;; +11686;TAKRI LETTER E;Lo;0;L;;;;;N;;;;; +11687;TAKRI LETTER AI;Lo;0;L;;;;;N;;;;; +11688;TAKRI LETTER O;Lo;0;L;;;;;N;;;;; +11689;TAKRI LETTER AU;Lo;0;L;;;;;N;;;;; +1168A;TAKRI LETTER KA;Lo;0;L;;;;;N;;;;; +1168B;TAKRI LETTER KHA;Lo;0;L;;;;;N;;;;; +1168C;TAKRI LETTER GA;Lo;0;L;;;;;N;;;;; +1168D;TAKRI LETTER GHA;Lo;0;L;;;;;N;;;;; +1168E;TAKRI LETTER NGA;Lo;0;L;;;;;N;;;;; +1168F;TAKRI LETTER CA;Lo;0;L;;;;;N;;;;; +11690;TAKRI LETTER CHA;Lo;0;L;;;;;N;;;;; +11691;TAKRI LETTER JA;Lo;0;L;;;;;N;;;;; +11692;TAKRI LETTER JHA;Lo;0;L;;;;;N;;;;; +11693;TAKRI LETTER NYA;Lo;0;L;;;;;N;;;;; +11694;TAKRI LETTER TTA;Lo;0;L;;;;;N;;;;; +11695;TAKRI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11696;TAKRI LETTER DDA;Lo;0;L;;;;;N;;;;; +11697;TAKRI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11698;TAKRI LETTER NNA;Lo;0;L;;;;;N;;;;; +11699;TAKRI LETTER TA;Lo;0;L;;;;;N;;;;; +1169A;TAKRI LETTER THA;Lo;0;L;;;;;N;;;;; +1169B;TAKRI LETTER DA;Lo;0;L;;;;;N;;;;; +1169C;TAKRI LETTER DHA;Lo;0;L;;;;;N;;;;; +1169D;TAKRI LETTER NA;Lo;0;L;;;;;N;;;;; +1169E;TAKRI LETTER PA;Lo;0;L;;;;;N;;;;; +1169F;TAKRI LETTER PHA;Lo;0;L;;;;;N;;;;; +116A0;TAKRI LETTER BA;Lo;0;L;;;;;N;;;;; +116A1;TAKRI LETTER BHA;Lo;0;L;;;;;N;;;;; +116A2;TAKRI LETTER MA;Lo;0;L;;;;;N;;;;; +116A3;TAKRI LETTER YA;Lo;0;L;;;;;N;;;;; +116A4;TAKRI LETTER RA;Lo;0;L;;;;;N;;;;; +116A5;TAKRI LETTER LA;Lo;0;L;;;;;N;;;;; +116A6;TAKRI LETTER VA;Lo;0;L;;;;;N;;;;; +116A7;TAKRI LETTER SHA;Lo;0;L;;;;;N;;;;; +116A8;TAKRI LETTER SA;Lo;0;L;;;;;N;;;;; +116A9;TAKRI LETTER HA;Lo;0;L;;;;;N;;;;; +116AA;TAKRI LETTER RRA;Lo;0;L;;;;;N;;;;; +116AB;TAKRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +116AC;TAKRI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +116AD;TAKRI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +116AE;TAKRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +116AF;TAKRI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +116B0;TAKRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +116B1;TAKRI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +116B2;TAKRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +116B3;TAKRI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +116B4;TAKRI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +116B5;TAKRI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +116B6;TAKRI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; +116B7;TAKRI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +116C0;TAKRI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +116C1;TAKRI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +116C2;TAKRI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +116C3;TAKRI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +116C4;TAKRI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +116C5;TAKRI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +116C6;TAKRI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +116C7;TAKRI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +116C8;TAKRI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +116C9;TAKRI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11700;AHOM LETTER KA;Lo;0;L;;;;;N;;;;; +11701;AHOM LETTER KHA;Lo;0;L;;;;;N;;;;; +11702;AHOM LETTER NGA;Lo;0;L;;;;;N;;;;; +11703;AHOM LETTER NA;Lo;0;L;;;;;N;;;;; +11704;AHOM LETTER TA;Lo;0;L;;;;;N;;;;; +11705;AHOM LETTER ALTERNATE TA;Lo;0;L;;;;;N;;;;; +11706;AHOM LETTER PA;Lo;0;L;;;;;N;;;;; +11707;AHOM LETTER PHA;Lo;0;L;;;;;N;;;;; +11708;AHOM LETTER BA;Lo;0;L;;;;;N;;;;; +11709;AHOM LETTER MA;Lo;0;L;;;;;N;;;;; +1170A;AHOM LETTER JA;Lo;0;L;;;;;N;;;;; +1170B;AHOM LETTER CHA;Lo;0;L;;;;;N;;;;; +1170C;AHOM LETTER THA;Lo;0;L;;;;;N;;;;; +1170D;AHOM LETTER RA;Lo;0;L;;;;;N;;;;; +1170E;AHOM LETTER LA;Lo;0;L;;;;;N;;;;; +1170F;AHOM LETTER SA;Lo;0;L;;;;;N;;;;; +11710;AHOM LETTER NYA;Lo;0;L;;;;;N;;;;; +11711;AHOM LETTER HA;Lo;0;L;;;;;N;;;;; +11712;AHOM LETTER A;Lo;0;L;;;;;N;;;;; +11713;AHOM LETTER DA;Lo;0;L;;;;;N;;;;; +11714;AHOM LETTER DHA;Lo;0;L;;;;;N;;;;; +11715;AHOM LETTER GA;Lo;0;L;;;;;N;;;;; +11716;AHOM LETTER ALTERNATE GA;Lo;0;L;;;;;N;;;;; +11717;AHOM LETTER GHA;Lo;0;L;;;;;N;;;;; +11718;AHOM LETTER BHA;Lo;0;L;;;;;N;;;;; +11719;AHOM LETTER JHA;Lo;0;L;;;;;N;;;;; +1171D;AHOM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;; +1171E;AHOM CONSONANT SIGN MEDIAL RA;Mn;0;NSM;;;;;N;;;;; +1171F;AHOM CONSONANT SIGN MEDIAL LIGATING RA;Mn;0;NSM;;;;;N;;;;; +11720;AHOM VOWEL SIGN A;Mc;0;L;;;;;N;;;;; +11721;AHOM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11722;AHOM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11723;AHOM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11724;AHOM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11725;AHOM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11726;AHOM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +11727;AHOM VOWEL SIGN AW;Mn;0;NSM;;;;;N;;;;; +11728;AHOM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11729;AHOM VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +1172A;AHOM VOWEL SIGN AM;Mn;0;NSM;;;;;N;;;;; +1172B;AHOM SIGN KILLER;Mn;9;NSM;;;;;N;;;;; +11730;AHOM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11731;AHOM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11732;AHOM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11733;AHOM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11734;AHOM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11735;AHOM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11736;AHOM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11737;AHOM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11738;AHOM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11739;AHOM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1173A;AHOM NUMBER TEN;No;0;L;;;;10;N;;;;; +1173B;AHOM NUMBER TWENTY;No;0;L;;;;20;N;;;;; +1173C;AHOM SIGN SMALL SECTION;Po;0;L;;;;;N;;;;; +1173D;AHOM SIGN SECTION;Po;0;L;;;;;N;;;;; +1173E;AHOM SIGN RULAI;Po;0;L;;;;;N;;;;; +1173F;AHOM SYMBOL VI;So;0;L;;;;;N;;;;; +118A0;WARANG CITI CAPITAL LETTER NGAA;Lu;0;L;;;;;N;;;;118C0; +118A1;WARANG CITI CAPITAL LETTER A;Lu;0;L;;;;;N;;;;118C1; +118A2;WARANG CITI CAPITAL LETTER WI;Lu;0;L;;;;;N;;;;118C2; +118A3;WARANG CITI CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;118C3; +118A4;WARANG CITI CAPITAL LETTER YA;Lu;0;L;;;;;N;;;;118C4; +118A5;WARANG CITI CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;118C5; +118A6;WARANG CITI CAPITAL LETTER II;Lu;0;L;;;;;N;;;;118C6; +118A7;WARANG CITI CAPITAL LETTER UU;Lu;0;L;;;;;N;;;;118C7; +118A8;WARANG CITI CAPITAL LETTER E;Lu;0;L;;;;;N;;;;118C8; +118A9;WARANG CITI CAPITAL LETTER O;Lu;0;L;;;;;N;;;;118C9; +118AA;WARANG CITI CAPITAL LETTER ANG;Lu;0;L;;;;;N;;;;118CA; +118AB;WARANG CITI CAPITAL LETTER GA;Lu;0;L;;;;;N;;;;118CB; +118AC;WARANG CITI CAPITAL LETTER KO;Lu;0;L;;;;;N;;;;118CC; +118AD;WARANG CITI CAPITAL LETTER ENY;Lu;0;L;;;;;N;;;;118CD; +118AE;WARANG CITI CAPITAL LETTER YUJ;Lu;0;L;;;;;N;;;;118CE; +118AF;WARANG CITI CAPITAL LETTER UC;Lu;0;L;;;;;N;;;;118CF; +118B0;WARANG CITI CAPITAL LETTER ENN;Lu;0;L;;;;;N;;;;118D0; +118B1;WARANG CITI CAPITAL LETTER ODD;Lu;0;L;;;;;N;;;;118D1; +118B2;WARANG CITI CAPITAL LETTER TTE;Lu;0;L;;;;;N;;;;118D2; +118B3;WARANG CITI CAPITAL LETTER NUNG;Lu;0;L;;;;;N;;;;118D3; +118B4;WARANG CITI CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;118D4; +118B5;WARANG CITI CAPITAL LETTER AT;Lu;0;L;;;;;N;;;;118D5; +118B6;WARANG CITI CAPITAL LETTER AM;Lu;0;L;;;;;N;;;;118D6; +118B7;WARANG CITI CAPITAL LETTER BU;Lu;0;L;;;;;N;;;;118D7; +118B8;WARANG CITI CAPITAL LETTER PU;Lu;0;L;;;;;N;;;;118D8; +118B9;WARANG CITI CAPITAL LETTER HIYO;Lu;0;L;;;;;N;;;;118D9; +118BA;WARANG CITI CAPITAL LETTER HOLO;Lu;0;L;;;;;N;;;;118DA; +118BB;WARANG CITI CAPITAL LETTER HORR;Lu;0;L;;;;;N;;;;118DB; +118BC;WARANG CITI CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;118DC; +118BD;WARANG CITI CAPITAL LETTER SSUU;Lu;0;L;;;;;N;;;;118DD; +118BE;WARANG CITI CAPITAL LETTER SII;Lu;0;L;;;;;N;;;;118DE; +118BF;WARANG CITI CAPITAL LETTER VIYO;Lu;0;L;;;;;N;;;;118DF; +118C0;WARANG CITI SMALL LETTER NGAA;Ll;0;L;;;;;N;;;118A0;;118A0 +118C1;WARANG CITI SMALL LETTER A;Ll;0;L;;;;;N;;;118A1;;118A1 +118C2;WARANG CITI SMALL LETTER WI;Ll;0;L;;;;;N;;;118A2;;118A2 +118C3;WARANG CITI SMALL LETTER YU;Ll;0;L;;;;;N;;;118A3;;118A3 +118C4;WARANG CITI SMALL LETTER YA;Ll;0;L;;;;;N;;;118A4;;118A4 +118C5;WARANG CITI SMALL LETTER YO;Ll;0;L;;;;;N;;;118A5;;118A5 +118C6;WARANG CITI SMALL LETTER II;Ll;0;L;;;;;N;;;118A6;;118A6 +118C7;WARANG CITI SMALL LETTER UU;Ll;0;L;;;;;N;;;118A7;;118A7 +118C8;WARANG CITI SMALL LETTER E;Ll;0;L;;;;;N;;;118A8;;118A8 +118C9;WARANG CITI SMALL LETTER O;Ll;0;L;;;;;N;;;118A9;;118A9 +118CA;WARANG CITI SMALL LETTER ANG;Ll;0;L;;;;;N;;;118AA;;118AA +118CB;WARANG CITI SMALL LETTER GA;Ll;0;L;;;;;N;;;118AB;;118AB +118CC;WARANG CITI SMALL LETTER KO;Ll;0;L;;;;;N;;;118AC;;118AC +118CD;WARANG CITI SMALL LETTER ENY;Ll;0;L;;;;;N;;;118AD;;118AD +118CE;WARANG CITI SMALL LETTER YUJ;Ll;0;L;;;;;N;;;118AE;;118AE +118CF;WARANG CITI SMALL LETTER UC;Ll;0;L;;;;;N;;;118AF;;118AF +118D0;WARANG CITI SMALL LETTER ENN;Ll;0;L;;;;;N;;;118B0;;118B0 +118D1;WARANG CITI SMALL LETTER ODD;Ll;0;L;;;;;N;;;118B1;;118B1 +118D2;WARANG CITI SMALL LETTER TTE;Ll;0;L;;;;;N;;;118B2;;118B2 +118D3;WARANG CITI SMALL LETTER NUNG;Ll;0;L;;;;;N;;;118B3;;118B3 +118D4;WARANG CITI SMALL LETTER DA;Ll;0;L;;;;;N;;;118B4;;118B4 +118D5;WARANG CITI SMALL LETTER AT;Ll;0;L;;;;;N;;;118B5;;118B5 +118D6;WARANG CITI SMALL LETTER AM;Ll;0;L;;;;;N;;;118B6;;118B6 +118D7;WARANG CITI SMALL LETTER BU;Ll;0;L;;;;;N;;;118B7;;118B7 +118D8;WARANG CITI SMALL LETTER PU;Ll;0;L;;;;;N;;;118B8;;118B8 +118D9;WARANG CITI SMALL LETTER HIYO;Ll;0;L;;;;;N;;;118B9;;118B9 +118DA;WARANG CITI SMALL LETTER HOLO;Ll;0;L;;;;;N;;;118BA;;118BA +118DB;WARANG CITI SMALL LETTER HORR;Ll;0;L;;;;;N;;;118BB;;118BB +118DC;WARANG CITI SMALL LETTER HAR;Ll;0;L;;;;;N;;;118BC;;118BC +118DD;WARANG CITI SMALL LETTER SSUU;Ll;0;L;;;;;N;;;118BD;;118BD +118DE;WARANG CITI SMALL LETTER SII;Ll;0;L;;;;;N;;;118BE;;118BE +118DF;WARANG CITI SMALL LETTER VIYO;Ll;0;L;;;;;N;;;118BF;;118BF +118E0;WARANG CITI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +118E1;WARANG CITI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +118E2;WARANG CITI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +118E3;WARANG CITI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +118E4;WARANG CITI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +118E5;WARANG CITI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +118E6;WARANG CITI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +118E7;WARANG CITI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +118E8;WARANG CITI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +118E9;WARANG CITI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +118EA;WARANG CITI NUMBER TEN;No;0;L;;;;10;N;;;;; +118EB;WARANG CITI NUMBER TWENTY;No;0;L;;;;20;N;;;;; +118EC;WARANG CITI NUMBER THIRTY;No;0;L;;;;30;N;;;;; +118ED;WARANG CITI NUMBER FORTY;No;0;L;;;;40;N;;;;; +118EE;WARANG CITI NUMBER FIFTY;No;0;L;;;;50;N;;;;; +118EF;WARANG CITI NUMBER SIXTY;No;0;L;;;;60;N;;;;; +118F0;WARANG CITI NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +118F1;WARANG CITI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +118F2;WARANG CITI NUMBER NINETY;No;0;L;;;;90;N;;;;; +118FF;WARANG CITI OM;Lo;0;L;;;;;N;;;;; +11A00;ZANABAZAR SQUARE LETTER A;Lo;0;L;;;;;N;;;;; +11A01;ZANABAZAR SQUARE VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A02;ZANABAZAR SQUARE VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A03;ZANABAZAR SQUARE VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A04;ZANABAZAR SQUARE VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A05;ZANABAZAR SQUARE VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A06;ZANABAZAR SQUARE VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A07;ZANABAZAR SQUARE VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A08;ZANABAZAR SQUARE VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A09;ZANABAZAR SQUARE VOWEL SIGN REVERSED I;Mn;0;NSM;;;;;N;;;;; +11A0A;ZANABAZAR SQUARE VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A0B;ZANABAZAR SQUARE LETTER KA;Lo;0;L;;;;;N;;;;; +11A0C;ZANABAZAR SQUARE LETTER KHA;Lo;0;L;;;;;N;;;;; +11A0D;ZANABAZAR SQUARE LETTER GA;Lo;0;L;;;;;N;;;;; +11A0E;ZANABAZAR SQUARE LETTER GHA;Lo;0;L;;;;;N;;;;; +11A0F;ZANABAZAR SQUARE LETTER NGA;Lo;0;L;;;;;N;;;;; +11A10;ZANABAZAR SQUARE LETTER CA;Lo;0;L;;;;;N;;;;; +11A11;ZANABAZAR SQUARE LETTER CHA;Lo;0;L;;;;;N;;;;; +11A12;ZANABAZAR SQUARE LETTER JA;Lo;0;L;;;;;N;;;;; +11A13;ZANABAZAR SQUARE LETTER NYA;Lo;0;L;;;;;N;;;;; +11A14;ZANABAZAR SQUARE LETTER TTA;Lo;0;L;;;;;N;;;;; +11A15;ZANABAZAR SQUARE LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A16;ZANABAZAR SQUARE LETTER DDA;Lo;0;L;;;;;N;;;;; +11A17;ZANABAZAR SQUARE LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A18;ZANABAZAR SQUARE LETTER NNA;Lo;0;L;;;;;N;;;;; +11A19;ZANABAZAR SQUARE LETTER TA;Lo;0;L;;;;;N;;;;; +11A1A;ZANABAZAR SQUARE LETTER THA;Lo;0;L;;;;;N;;;;; +11A1B;ZANABAZAR SQUARE LETTER DA;Lo;0;L;;;;;N;;;;; +11A1C;ZANABAZAR SQUARE LETTER DHA;Lo;0;L;;;;;N;;;;; +11A1D;ZANABAZAR SQUARE LETTER NA;Lo;0;L;;;;;N;;;;; +11A1E;ZANABAZAR SQUARE LETTER PA;Lo;0;L;;;;;N;;;;; +11A1F;ZANABAZAR SQUARE LETTER PHA;Lo;0;L;;;;;N;;;;; +11A20;ZANABAZAR SQUARE LETTER BA;Lo;0;L;;;;;N;;;;; +11A21;ZANABAZAR SQUARE LETTER BHA;Lo;0;L;;;;;N;;;;; +11A22;ZANABAZAR SQUARE LETTER MA;Lo;0;L;;;;;N;;;;; +11A23;ZANABAZAR SQUARE LETTER TSA;Lo;0;L;;;;;N;;;;; +11A24;ZANABAZAR SQUARE LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A25;ZANABAZAR SQUARE LETTER DZA;Lo;0;L;;;;;N;;;;; +11A26;ZANABAZAR SQUARE LETTER DZHA;Lo;0;L;;;;;N;;;;; +11A27;ZANABAZAR SQUARE LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A28;ZANABAZAR SQUARE LETTER ZA;Lo;0;L;;;;;N;;;;; +11A29;ZANABAZAR SQUARE LETTER -A;Lo;0;L;;;;;N;;;;; +11A2A;ZANABAZAR SQUARE LETTER YA;Lo;0;L;;;;;N;;;;; +11A2B;ZANABAZAR SQUARE LETTER RA;Lo;0;L;;;;;N;;;;; +11A2C;ZANABAZAR SQUARE LETTER LA;Lo;0;L;;;;;N;;;;; +11A2D;ZANABAZAR SQUARE LETTER VA;Lo;0;L;;;;;N;;;;; +11A2E;ZANABAZAR SQUARE LETTER SHA;Lo;0;L;;;;;N;;;;; +11A2F;ZANABAZAR SQUARE LETTER SSA;Lo;0;L;;;;;N;;;;; +11A30;ZANABAZAR SQUARE LETTER SA;Lo;0;L;;;;;N;;;;; +11A31;ZANABAZAR SQUARE LETTER HA;Lo;0;L;;;;;N;;;;; +11A32;ZANABAZAR SQUARE LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A33;ZANABAZAR SQUARE FINAL CONSONANT MARK;Mn;0;NSM;;;;;N;;;;; +11A34;ZANABAZAR SQUARE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11A35;ZANABAZAR SQUARE SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11A36;ZANABAZAR SQUARE SIGN CANDRABINDU WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A37;ZANABAZAR SQUARE SIGN CANDRA WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A38;ZANABAZAR SQUARE SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A39;ZANABAZAR SQUARE SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A3A;ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A3B;ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA;Mn;0;NSM;;;;;N;;;;; +11A3C;ZANABAZAR SQUARE CLUSTER-FINAL LETTER RA;Mn;0;NSM;;;;;N;;;;; +11A3D;ZANABAZAR SQUARE CLUSTER-FINAL LETTER LA;Mn;0;NSM;;;;;N;;;;; +11A3E;ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA;Mn;0;NSM;;;;;N;;;;; +11A3F;ZANABAZAR SQUARE INITIAL HEAD MARK;Po;0;L;;;;;N;;;;; +11A40;ZANABAZAR SQUARE CLOSING HEAD MARK;Po;0;L;;;;;N;;;;; +11A41;ZANABAZAR SQUARE MARK TSHEG;Po;0;L;;;;;N;;;;; +11A42;ZANABAZAR SQUARE MARK SHAD;Po;0;L;;;;;N;;;;; +11A43;ZANABAZAR SQUARE MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A44;ZANABAZAR SQUARE MARK LONG TSHEG;Po;0;L;;;;;N;;;;; +11A45;ZANABAZAR SQUARE INITIAL DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A46;ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A47;ZANABAZAR SQUARE SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A50;SOYOMBO LETTER A;Lo;0;L;;;;;N;;;;; +11A51;SOYOMBO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A52;SOYOMBO VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A53;SOYOMBO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A54;SOYOMBO VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A55;SOYOMBO VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A56;SOYOMBO VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A57;SOYOMBO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A58;SOYOMBO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A59;SOYOMBO VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11A5A;SOYOMBO VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11A5B;SOYOMBO VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A5C;SOYOMBO LETTER KA;Lo;0;L;;;;;N;;;;; +11A5D;SOYOMBO LETTER KHA;Lo;0;L;;;;;N;;;;; +11A5E;SOYOMBO LETTER GA;Lo;0;L;;;;;N;;;;; +11A5F;SOYOMBO LETTER GHA;Lo;0;L;;;;;N;;;;; +11A60;SOYOMBO LETTER NGA;Lo;0;L;;;;;N;;;;; +11A61;SOYOMBO LETTER CA;Lo;0;L;;;;;N;;;;; +11A62;SOYOMBO LETTER CHA;Lo;0;L;;;;;N;;;;; +11A63;SOYOMBO LETTER JA;Lo;0;L;;;;;N;;;;; +11A64;SOYOMBO LETTER JHA;Lo;0;L;;;;;N;;;;; +11A65;SOYOMBO LETTER NYA;Lo;0;L;;;;;N;;;;; +11A66;SOYOMBO LETTER TTA;Lo;0;L;;;;;N;;;;; +11A67;SOYOMBO LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A68;SOYOMBO LETTER DDA;Lo;0;L;;;;;N;;;;; +11A69;SOYOMBO LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A6A;SOYOMBO LETTER NNA;Lo;0;L;;;;;N;;;;; +11A6B;SOYOMBO LETTER TA;Lo;0;L;;;;;N;;;;; +11A6C;SOYOMBO LETTER THA;Lo;0;L;;;;;N;;;;; +11A6D;SOYOMBO LETTER DA;Lo;0;L;;;;;N;;;;; +11A6E;SOYOMBO LETTER DHA;Lo;0;L;;;;;N;;;;; +11A6F;SOYOMBO LETTER NA;Lo;0;L;;;;;N;;;;; +11A70;SOYOMBO LETTER PA;Lo;0;L;;;;;N;;;;; +11A71;SOYOMBO LETTER PHA;Lo;0;L;;;;;N;;;;; +11A72;SOYOMBO LETTER BA;Lo;0;L;;;;;N;;;;; +11A73;SOYOMBO LETTER BHA;Lo;0;L;;;;;N;;;;; +11A74;SOYOMBO LETTER MA;Lo;0;L;;;;;N;;;;; +11A75;SOYOMBO LETTER TSA;Lo;0;L;;;;;N;;;;; +11A76;SOYOMBO LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A77;SOYOMBO LETTER DZA;Lo;0;L;;;;;N;;;;; +11A78;SOYOMBO LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A79;SOYOMBO LETTER ZA;Lo;0;L;;;;;N;;;;; +11A7A;SOYOMBO LETTER -A;Lo;0;L;;;;;N;;;;; +11A7B;SOYOMBO LETTER YA;Lo;0;L;;;;;N;;;;; +11A7C;SOYOMBO LETTER RA;Lo;0;L;;;;;N;;;;; +11A7D;SOYOMBO LETTER LA;Lo;0;L;;;;;N;;;;; +11A7E;SOYOMBO LETTER VA;Lo;0;L;;;;;N;;;;; +11A7F;SOYOMBO LETTER SHA;Lo;0;L;;;;;N;;;;; +11A80;SOYOMBO LETTER SSA;Lo;0;L;;;;;N;;;;; +11A81;SOYOMBO LETTER SA;Lo;0;L;;;;;N;;;;; +11A82;SOYOMBO LETTER HA;Lo;0;L;;;;;N;;;;; +11A83;SOYOMBO LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A86;SOYOMBO CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A87;SOYOMBO CLUSTER-INITIAL LETTER LA;Lo;0;L;;;;;N;;;;; +11A88;SOYOMBO CLUSTER-INITIAL LETTER SHA;Lo;0;L;;;;;N;;;;; +11A89;SOYOMBO CLUSTER-INITIAL LETTER SA;Lo;0;L;;;;;N;;;;; +11A8A;SOYOMBO FINAL CONSONANT SIGN G;Mn;0;NSM;;;;;N;;;;; +11A8B;SOYOMBO FINAL CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; +11A8C;SOYOMBO FINAL CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +11A8D;SOYOMBO FINAL CONSONANT SIGN D;Mn;0;NSM;;;;;N;;;;; +11A8E;SOYOMBO FINAL CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +11A8F;SOYOMBO FINAL CONSONANT SIGN B;Mn;0;NSM;;;;;N;;;;; +11A90;SOYOMBO FINAL CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; +11A91;SOYOMBO FINAL CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +11A92;SOYOMBO FINAL CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; +11A93;SOYOMBO FINAL CONSONANT SIGN SH;Mn;0;NSM;;;;;N;;;;; +11A94;SOYOMBO FINAL CONSONANT SIGN S;Mn;0;NSM;;;;;N;;;;; +11A95;SOYOMBO FINAL CONSONANT SIGN -A;Mn;0;NSM;;;;;N;;;;; +11A96;SOYOMBO SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A97;SOYOMBO SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A98;SOYOMBO GEMINATION MARK;Mn;0;NSM;;;;;N;;;;; +11A99;SOYOMBO SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A9A;SOYOMBO MARK TSHEG;Po;0;L;;;;;N;;;;; +11A9B;SOYOMBO MARK SHAD;Po;0;L;;;;;N;;;;; +11A9C;SOYOMBO MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A9E;SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME;Po;0;L;;;;;N;;;;; +11A9F;SOYOMBO HEAD MARK WITH MOON AND SUN AND FLAME;Po;0;L;;;;;N;;;;; +11AA0;SOYOMBO HEAD MARK WITH MOON AND SUN;Po;0;L;;;;;N;;;;; +11AA1;SOYOMBO TERMINAL MARK-1;Po;0;L;;;;;N;;;;; +11AA2;SOYOMBO TERMINAL MARK-2;Po;0;L;;;;;N;;;;; +11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;; +11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;; +11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;; +11AC3;PAU CIN HAU LETTER MA;Lo;0;L;;;;;N;;;;; +11AC4;PAU CIN HAU LETTER DA;Lo;0;L;;;;;N;;;;; +11AC5;PAU CIN HAU LETTER ZA;Lo;0;L;;;;;N;;;;; +11AC6;PAU CIN HAU LETTER VA;Lo;0;L;;;;;N;;;;; +11AC7;PAU CIN HAU LETTER NGA;Lo;0;L;;;;;N;;;;; +11AC8;PAU CIN HAU LETTER HA;Lo;0;L;;;;;N;;;;; +11AC9;PAU CIN HAU LETTER GA;Lo;0;L;;;;;N;;;;; +11ACA;PAU CIN HAU LETTER KHA;Lo;0;L;;;;;N;;;;; +11ACB;PAU CIN HAU LETTER SA;Lo;0;L;;;;;N;;;;; +11ACC;PAU CIN HAU LETTER BA;Lo;0;L;;;;;N;;;;; +11ACD;PAU CIN HAU LETTER CA;Lo;0;L;;;;;N;;;;; +11ACE;PAU CIN HAU LETTER TA;Lo;0;L;;;;;N;;;;; +11ACF;PAU CIN HAU LETTER THA;Lo;0;L;;;;;N;;;;; +11AD0;PAU CIN HAU LETTER NA;Lo;0;L;;;;;N;;;;; +11AD1;PAU CIN HAU LETTER PHA;Lo;0;L;;;;;N;;;;; +11AD2;PAU CIN HAU LETTER RA;Lo;0;L;;;;;N;;;;; +11AD3;PAU CIN HAU LETTER FA;Lo;0;L;;;;;N;;;;; +11AD4;PAU CIN HAU LETTER CHA;Lo;0;L;;;;;N;;;;; +11AD5;PAU CIN HAU LETTER A;Lo;0;L;;;;;N;;;;; +11AD6;PAU CIN HAU LETTER E;Lo;0;L;;;;;N;;;;; +11AD7;PAU CIN HAU LETTER I;Lo;0;L;;;;;N;;;;; +11AD8;PAU CIN HAU LETTER O;Lo;0;L;;;;;N;;;;; +11AD9;PAU CIN HAU LETTER U;Lo;0;L;;;;;N;;;;; +11ADA;PAU CIN HAU LETTER UA;Lo;0;L;;;;;N;;;;; +11ADB;PAU CIN HAU LETTER IA;Lo;0;L;;;;;N;;;;; +11ADC;PAU CIN HAU LETTER FINAL P;Lo;0;L;;;;;N;;;;; +11ADD;PAU CIN HAU LETTER FINAL K;Lo;0;L;;;;;N;;;;; +11ADE;PAU CIN HAU LETTER FINAL T;Lo;0;L;;;;;N;;;;; +11ADF;PAU CIN HAU LETTER FINAL M;Lo;0;L;;;;;N;;;;; +11AE0;PAU CIN HAU LETTER FINAL N;Lo;0;L;;;;;N;;;;; +11AE1;PAU CIN HAU LETTER FINAL L;Lo;0;L;;;;;N;;;;; +11AE2;PAU CIN HAU LETTER FINAL W;Lo;0;L;;;;;N;;;;; +11AE3;PAU CIN HAU LETTER FINAL NG;Lo;0;L;;;;;N;;;;; +11AE4;PAU CIN HAU LETTER FINAL Y;Lo;0;L;;;;;N;;;;; +11AE5;PAU CIN HAU RISING TONE LONG;Lo;0;L;;;;;N;;;;; +11AE6;PAU CIN HAU RISING TONE;Lo;0;L;;;;;N;;;;; +11AE7;PAU CIN HAU SANDHI GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +11AE8;PAU CIN HAU RISING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; +11AE9;PAU CIN HAU RISING TONE FINAL;Lo;0;L;;;;;N;;;;; +11AEA;PAU CIN HAU SANDHI GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; +11AEB;PAU CIN HAU SANDHI TONE LONG;Lo;0;L;;;;;N;;;;; +11AEC;PAU CIN HAU SANDHI TONE;Lo;0;L;;;;;N;;;;; +11AED;PAU CIN HAU SANDHI TONE LONG FINAL;Lo;0;L;;;;;N;;;;; +11AEE;PAU CIN HAU SANDHI TONE FINAL;Lo;0;L;;;;;N;;;;; +11AEF;PAU CIN HAU MID-LEVEL TONE;Lo;0;L;;;;;N;;;;; +11AF0;PAU CIN HAU GLOTTAL STOP VARIANT;Lo;0;L;;;;;N;;;;; +11AF1;PAU CIN HAU MID-LEVEL TONE LONG FINAL;Lo;0;L;;;;;N;;;;; +11AF2;PAU CIN HAU MID-LEVEL TONE FINAL;Lo;0;L;;;;;N;;;;; +11AF3;PAU CIN HAU LOW-FALLING TONE LONG;Lo;0;L;;;;;N;;;;; +11AF4;PAU CIN HAU LOW-FALLING TONE;Lo;0;L;;;;;N;;;;; +11AF5;PAU CIN HAU GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +11AF6;PAU CIN HAU LOW-FALLING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; +11AF7;PAU CIN HAU LOW-FALLING TONE FINAL;Lo;0;L;;;;;N;;;;; +11AF8;PAU CIN HAU GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; +11C00;BHAIKSUKI LETTER A;Lo;0;L;;;;;N;;;;; +11C01;BHAIKSUKI LETTER AA;Lo;0;L;;;;;N;;;;; +11C02;BHAIKSUKI LETTER I;Lo;0;L;;;;;N;;;;; +11C03;BHAIKSUKI LETTER II;Lo;0;L;;;;;N;;;;; +11C04;BHAIKSUKI LETTER U;Lo;0;L;;;;;N;;;;; +11C05;BHAIKSUKI LETTER UU;Lo;0;L;;;;;N;;;;; +11C06;BHAIKSUKI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11C07;BHAIKSUKI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11C08;BHAIKSUKI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11C0A;BHAIKSUKI LETTER E;Lo;0;L;;;;;N;;;;; +11C0B;BHAIKSUKI LETTER AI;Lo;0;L;;;;;N;;;;; +11C0C;BHAIKSUKI LETTER O;Lo;0;L;;;;;N;;;;; +11C0D;BHAIKSUKI LETTER AU;Lo;0;L;;;;;N;;;;; +11C0E;BHAIKSUKI LETTER KA;Lo;0;L;;;;;N;;;;; +11C0F;BHAIKSUKI LETTER KHA;Lo;0;L;;;;;N;;;;; +11C10;BHAIKSUKI LETTER GA;Lo;0;L;;;;;N;;;;; +11C11;BHAIKSUKI LETTER GHA;Lo;0;L;;;;;N;;;;; +11C12;BHAIKSUKI LETTER NGA;Lo;0;L;;;;;N;;;;; +11C13;BHAIKSUKI LETTER CA;Lo;0;L;;;;;N;;;;; +11C14;BHAIKSUKI LETTER CHA;Lo;0;L;;;;;N;;;;; +11C15;BHAIKSUKI LETTER JA;Lo;0;L;;;;;N;;;;; +11C16;BHAIKSUKI LETTER JHA;Lo;0;L;;;;;N;;;;; +11C17;BHAIKSUKI LETTER NYA;Lo;0;L;;;;;N;;;;; +11C18;BHAIKSUKI LETTER TTA;Lo;0;L;;;;;N;;;;; +11C19;BHAIKSUKI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11C1A;BHAIKSUKI LETTER DDA;Lo;0;L;;;;;N;;;;; +11C1B;BHAIKSUKI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11C1C;BHAIKSUKI LETTER NNA;Lo;0;L;;;;;N;;;;; +11C1D;BHAIKSUKI LETTER TA;Lo;0;L;;;;;N;;;;; +11C1E;BHAIKSUKI LETTER THA;Lo;0;L;;;;;N;;;;; +11C1F;BHAIKSUKI LETTER DA;Lo;0;L;;;;;N;;;;; +11C20;BHAIKSUKI LETTER DHA;Lo;0;L;;;;;N;;;;; +11C21;BHAIKSUKI LETTER NA;Lo;0;L;;;;;N;;;;; +11C22;BHAIKSUKI LETTER PA;Lo;0;L;;;;;N;;;;; +11C23;BHAIKSUKI LETTER PHA;Lo;0;L;;;;;N;;;;; +11C24;BHAIKSUKI LETTER BA;Lo;0;L;;;;;N;;;;; +11C25;BHAIKSUKI LETTER BHA;Lo;0;L;;;;;N;;;;; +11C26;BHAIKSUKI LETTER MA;Lo;0;L;;;;;N;;;;; +11C27;BHAIKSUKI LETTER YA;Lo;0;L;;;;;N;;;;; +11C28;BHAIKSUKI LETTER RA;Lo;0;L;;;;;N;;;;; +11C29;BHAIKSUKI LETTER LA;Lo;0;L;;;;;N;;;;; +11C2A;BHAIKSUKI LETTER VA;Lo;0;L;;;;;N;;;;; +11C2B;BHAIKSUKI LETTER SHA;Lo;0;L;;;;;N;;;;; +11C2C;BHAIKSUKI LETTER SSA;Lo;0;L;;;;;N;;;;; +11C2D;BHAIKSUKI LETTER SA;Lo;0;L;;;;;N;;;;; +11C2E;BHAIKSUKI LETTER HA;Lo;0;L;;;;;N;;;;; +11C2F;BHAIKSUKI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11C30;BHAIKSUKI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11C31;BHAIKSUKI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11C32;BHAIKSUKI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11C33;BHAIKSUKI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11C34;BHAIKSUKI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11C35;BHAIKSUKI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11C36;BHAIKSUKI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11C38;BHAIKSUKI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11C39;BHAIKSUKI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11C3A;BHAIKSUKI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11C3B;BHAIKSUKI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11C3C;BHAIKSUKI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11C3D;BHAIKSUKI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11C3E;BHAIKSUKI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11C3F;BHAIKSUKI SIGN VIRAMA;Mn;9;L;;;;;N;;;;; +11C40;BHAIKSUKI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +11C41;BHAIKSUKI DANDA;Po;0;L;;;;;N;;;;; +11C42;BHAIKSUKI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11C43;BHAIKSUKI WORD SEPARATOR;Po;0;L;;;;;N;;;;; +11C44;BHAIKSUKI GAP FILLER-1;Po;0;L;;;;;N;;;;; +11C45;BHAIKSUKI GAP FILLER-2;Po;0;L;;;;;N;;;;; +11C50;BHAIKSUKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11C51;BHAIKSUKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11C52;BHAIKSUKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11C53;BHAIKSUKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11C54;BHAIKSUKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11C55;BHAIKSUKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11C56;BHAIKSUKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11C57;BHAIKSUKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11C58;BHAIKSUKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11C59;BHAIKSUKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11C5A;BHAIKSUKI NUMBER ONE;No;0;L;;;;1;N;;;;; +11C5B;BHAIKSUKI NUMBER TWO;No;0;L;;;;2;N;;;;; +11C5C;BHAIKSUKI NUMBER THREE;No;0;L;;;;3;N;;;;; +11C5D;BHAIKSUKI NUMBER FOUR;No;0;L;;;;4;N;;;;; +11C5E;BHAIKSUKI NUMBER FIVE;No;0;L;;;;5;N;;;;; +11C5F;BHAIKSUKI NUMBER SIX;No;0;L;;;;6;N;;;;; +11C60;BHAIKSUKI NUMBER SEVEN;No;0;L;;;;7;N;;;;; +11C61;BHAIKSUKI NUMBER EIGHT;No;0;L;;;;8;N;;;;; +11C62;BHAIKSUKI NUMBER NINE;No;0;L;;;;9;N;;;;; +11C63;BHAIKSUKI NUMBER TEN;No;0;L;;;;10;N;;;;; +11C64;BHAIKSUKI NUMBER TWENTY;No;0;L;;;;20;N;;;;; +11C65;BHAIKSUKI NUMBER THIRTY;No;0;L;;;;30;N;;;;; +11C66;BHAIKSUKI NUMBER FORTY;No;0;L;;;;40;N;;;;; +11C67;BHAIKSUKI NUMBER FIFTY;No;0;L;;;;50;N;;;;; +11C68;BHAIKSUKI NUMBER SIXTY;No;0;L;;;;60;N;;;;; +11C69;BHAIKSUKI NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +11C6A;BHAIKSUKI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +11C6B;BHAIKSUKI NUMBER NINETY;No;0;L;;;;90;N;;;;; +11C6C;BHAIKSUKI HUNDREDS UNIT MARK;No;0;L;;;;100;N;;;;; +11C70;MARCHEN HEAD MARK;Po;0;L;;;;;N;;;;; +11C71;MARCHEN MARK SHAD;Po;0;L;;;;;N;;;;; +11C72;MARCHEN LETTER KA;Lo;0;L;;;;;N;;;;; +11C73;MARCHEN LETTER KHA;Lo;0;L;;;;;N;;;;; +11C74;MARCHEN LETTER GA;Lo;0;L;;;;;N;;;;; +11C75;MARCHEN LETTER NGA;Lo;0;L;;;;;N;;;;; +11C76;MARCHEN LETTER CA;Lo;0;L;;;;;N;;;;; +11C77;MARCHEN LETTER CHA;Lo;0;L;;;;;N;;;;; +11C78;MARCHEN LETTER JA;Lo;0;L;;;;;N;;;;; +11C79;MARCHEN LETTER NYA;Lo;0;L;;;;;N;;;;; +11C7A;MARCHEN LETTER TA;Lo;0;L;;;;;N;;;;; +11C7B;MARCHEN LETTER THA;Lo;0;L;;;;;N;;;;; +11C7C;MARCHEN LETTER DA;Lo;0;L;;;;;N;;;;; +11C7D;MARCHEN LETTER NA;Lo;0;L;;;;;N;;;;; +11C7E;MARCHEN LETTER PA;Lo;0;L;;;;;N;;;;; +11C7F;MARCHEN LETTER PHA;Lo;0;L;;;;;N;;;;; +11C80;MARCHEN LETTER BA;Lo;0;L;;;;;N;;;;; +11C81;MARCHEN LETTER MA;Lo;0;L;;;;;N;;;;; +11C82;MARCHEN LETTER TSA;Lo;0;L;;;;;N;;;;; +11C83;MARCHEN LETTER TSHA;Lo;0;L;;;;;N;;;;; +11C84;MARCHEN LETTER DZA;Lo;0;L;;;;;N;;;;; +11C85;MARCHEN LETTER WA;Lo;0;L;;;;;N;;;;; +11C86;MARCHEN LETTER ZHA;Lo;0;L;;;;;N;;;;; +11C87;MARCHEN LETTER ZA;Lo;0;L;;;;;N;;;;; +11C88;MARCHEN LETTER -A;Lo;0;L;;;;;N;;;;; +11C89;MARCHEN LETTER YA;Lo;0;L;;;;;N;;;;; +11C8A;MARCHEN LETTER RA;Lo;0;L;;;;;N;;;;; +11C8B;MARCHEN LETTER LA;Lo;0;L;;;;;N;;;;; +11C8C;MARCHEN LETTER SHA;Lo;0;L;;;;;N;;;;; +11C8D;MARCHEN LETTER SA;Lo;0;L;;;;;N;;;;; +11C8E;MARCHEN LETTER HA;Lo;0;L;;;;;N;;;;; +11C8F;MARCHEN LETTER A;Lo;0;L;;;;;N;;;;; +11C92;MARCHEN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; +11C93;MARCHEN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; +11C94;MARCHEN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; +11C95;MARCHEN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; +11C96;MARCHEN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; +11C97;MARCHEN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; +11C98;MARCHEN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; +11C99;MARCHEN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; +11C9A;MARCHEN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; +11C9B;MARCHEN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; +11C9C;MARCHEN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; +11C9D;MARCHEN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; +11C9E;MARCHEN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; +11C9F;MARCHEN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; +11CA0;MARCHEN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; +11CA1;MARCHEN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; +11CA2;MARCHEN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; +11CA3;MARCHEN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; +11CA4;MARCHEN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; +11CA5;MARCHEN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; +11CA6;MARCHEN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; +11CA7;MARCHEN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; +11CA9;MARCHEN SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; +11CAA;MARCHEN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; +11CAB;MARCHEN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; +11CAC;MARCHEN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; +11CAD;MARCHEN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; +11CAE;MARCHEN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; +11CAF;MARCHEN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; +11CB0;MARCHEN VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11CB1;MARCHEN VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11CB2;MARCHEN VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11CB3;MARCHEN VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11CB4;MARCHEN VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11CB5;MARCHEN SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11CB6;MARCHEN SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11D00;MASARAM GONDI LETTER A;Lo;0;L;;;;;N;;;;; +11D01;MASARAM GONDI LETTER AA;Lo;0;L;;;;;N;;;;; +11D02;MASARAM GONDI LETTER I;Lo;0;L;;;;;N;;;;; +11D03;MASARAM GONDI LETTER II;Lo;0;L;;;;;N;;;;; +11D04;MASARAM GONDI LETTER U;Lo;0;L;;;;;N;;;;; +11D05;MASARAM GONDI LETTER UU;Lo;0;L;;;;;N;;;;; +11D06;MASARAM GONDI LETTER E;Lo;0;L;;;;;N;;;;; +11D08;MASARAM GONDI LETTER AI;Lo;0;L;;;;;N;;;;; +11D09;MASARAM GONDI LETTER O;Lo;0;L;;;;;N;;;;; +11D0B;MASARAM GONDI LETTER AU;Lo;0;L;;;;;N;;;;; +11D0C;MASARAM GONDI LETTER KA;Lo;0;L;;;;;N;;;;; +11D0D;MASARAM GONDI LETTER KHA;Lo;0;L;;;;;N;;;;; +11D0E;MASARAM GONDI LETTER GA;Lo;0;L;;;;;N;;;;; +11D0F;MASARAM GONDI LETTER GHA;Lo;0;L;;;;;N;;;;; +11D10;MASARAM GONDI LETTER NGA;Lo;0;L;;;;;N;;;;; +11D11;MASARAM GONDI LETTER CA;Lo;0;L;;;;;N;;;;; +11D12;MASARAM GONDI LETTER CHA;Lo;0;L;;;;;N;;;;; +11D13;MASARAM GONDI LETTER JA;Lo;0;L;;;;;N;;;;; +11D14;MASARAM GONDI LETTER JHA;Lo;0;L;;;;;N;;;;; +11D15;MASARAM GONDI LETTER NYA;Lo;0;L;;;;;N;;;;; +11D16;MASARAM GONDI LETTER TTA;Lo;0;L;;;;;N;;;;; +11D17;MASARAM GONDI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11D18;MASARAM GONDI LETTER DDA;Lo;0;L;;;;;N;;;;; +11D19;MASARAM GONDI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11D1A;MASARAM GONDI LETTER NNA;Lo;0;L;;;;;N;;;;; +11D1B;MASARAM GONDI LETTER TA;Lo;0;L;;;;;N;;;;; +11D1C;MASARAM GONDI LETTER THA;Lo;0;L;;;;;N;;;;; +11D1D;MASARAM GONDI LETTER DA;Lo;0;L;;;;;N;;;;; +11D1E;MASARAM GONDI LETTER DHA;Lo;0;L;;;;;N;;;;; +11D1F;MASARAM GONDI LETTER NA;Lo;0;L;;;;;N;;;;; +11D20;MASARAM GONDI LETTER PA;Lo;0;L;;;;;N;;;;; +11D21;MASARAM GONDI LETTER PHA;Lo;0;L;;;;;N;;;;; +11D22;MASARAM GONDI LETTER BA;Lo;0;L;;;;;N;;;;; +11D23;MASARAM GONDI LETTER BHA;Lo;0;L;;;;;N;;;;; +11D24;MASARAM GONDI LETTER MA;Lo;0;L;;;;;N;;;;; +11D25;MASARAM GONDI LETTER YA;Lo;0;L;;;;;N;;;;; +11D26;MASARAM GONDI LETTER RA;Lo;0;L;;;;;N;;;;; +11D27;MASARAM GONDI LETTER LA;Lo;0;L;;;;;N;;;;; +11D28;MASARAM GONDI LETTER VA;Lo;0;L;;;;;N;;;;; +11D29;MASARAM GONDI LETTER SHA;Lo;0;L;;;;;N;;;;; +11D2A;MASARAM GONDI LETTER SSA;Lo;0;L;;;;;N;;;;; +11D2B;MASARAM GONDI LETTER SA;Lo;0;L;;;;;N;;;;; +11D2C;MASARAM GONDI LETTER HA;Lo;0;L;;;;;N;;;;; +11D2D;MASARAM GONDI LETTER LLA;Lo;0;L;;;;;N;;;;; +11D2E;MASARAM GONDI LETTER KSSA;Lo;0;L;;;;;N;;;;; +11D2F;MASARAM GONDI LETTER JNYA;Lo;0;L;;;;;N;;;;; +11D30;MASARAM GONDI LETTER TRA;Lo;0;L;;;;;N;;;;; +11D31;MASARAM GONDI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11D32;MASARAM GONDI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11D33;MASARAM GONDI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11D34;MASARAM GONDI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11D35;MASARAM GONDI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11D36;MASARAM GONDI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11D3A;MASARAM GONDI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11D3C;MASARAM GONDI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11D3D;MASARAM GONDI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11D3F;MASARAM GONDI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11D40;MASARAM GONDI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11D41;MASARAM GONDI SIGN VISARGA;Mn;0;NSM;;;;;N;;;;; +11D42;MASARAM GONDI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11D43;MASARAM GONDI SIGN CANDRA;Mn;0;NSM;;;;;N;;;;; +11D44;MASARAM GONDI SIGN HALANTA;Mn;9;NSM;;;;;N;;;;; +11D45;MASARAM GONDI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11D46;MASARAM GONDI REPHA;Lo;0;L;;;;;N;;;;; +11D47;MASARAM GONDI RA-KARA;Mn;0;NSM;;;;;N;;;;; +11D50;MASARAM GONDI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11D51;MASARAM GONDI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11D52;MASARAM GONDI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11D53;MASARAM GONDI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11D54;MASARAM GONDI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11D55;MASARAM GONDI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11D56;MASARAM GONDI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11D57;MASARAM GONDI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11D58;MASARAM GONDI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11D59;MASARAM GONDI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;; +12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;; +12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;; +12003;CUNEIFORM SIGN A TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12004;CUNEIFORM SIGN A TIMES HA;Lo;0;L;;;;;N;;;;; +12005;CUNEIFORM SIGN A TIMES IGI;Lo;0;L;;;;;N;;;;; +12006;CUNEIFORM SIGN A TIMES LAGAR GUNU;Lo;0;L;;;;;N;;;;; +12007;CUNEIFORM SIGN A TIMES MUSH;Lo;0;L;;;;;N;;;;; +12008;CUNEIFORM SIGN A TIMES SAG;Lo;0;L;;;;;N;;;;; +12009;CUNEIFORM SIGN A2;Lo;0;L;;;;;N;;;;; +1200A;CUNEIFORM SIGN AB;Lo;0;L;;;;;N;;;;; +1200B;CUNEIFORM SIGN AB TIMES ASH2;Lo;0;L;;;;;N;;;;; +1200C;CUNEIFORM SIGN AB TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; +1200D;CUNEIFORM SIGN AB TIMES GAL;Lo;0;L;;;;;N;;;;; +1200E;CUNEIFORM SIGN AB TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1200F;CUNEIFORM SIGN AB TIMES HA;Lo;0;L;;;;;N;;;;; +12010;CUNEIFORM SIGN AB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12011;CUNEIFORM SIGN AB TIMES IMIN;Lo;0;L;;;;;N;;;;; +12012;CUNEIFORM SIGN AB TIMES LAGAB;Lo;0;L;;;;;N;;;;; +12013;CUNEIFORM SIGN AB TIMES SHESH;Lo;0;L;;;;;N;;;;; +12014;CUNEIFORM SIGN AB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; +12015;CUNEIFORM SIGN AB GUNU;Lo;0;L;;;;;N;;;;; +12016;CUNEIFORM SIGN AB2;Lo;0;L;;;;;N;;;;; +12017;CUNEIFORM SIGN AB2 TIMES BALAG;Lo;0;L;;;;;N;;;;; +12018;CUNEIFORM SIGN AB2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12019;CUNEIFORM SIGN AB2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; +1201A;CUNEIFORM SIGN AB2 TIMES SHA3;Lo;0;L;;;;;N;;;;; +1201B;CUNEIFORM SIGN AB2 TIMES TAK4;Lo;0;L;;;;;N;;;;; +1201C;CUNEIFORM SIGN AD;Lo;0;L;;;;;N;;;;; +1201D;CUNEIFORM SIGN AK;Lo;0;L;;;;;N;;;;; +1201E;CUNEIFORM SIGN AK TIMES ERIN2;Lo;0;L;;;;;N;;;;; +1201F;CUNEIFORM SIGN AK TIMES SHITA PLUS GISH;Lo;0;L;;;;;N;;;;; +12020;CUNEIFORM SIGN AL;Lo;0;L;;;;;N;;;;; +12021;CUNEIFORM SIGN AL TIMES AL;Lo;0;L;;;;;N;;;;; +12022;CUNEIFORM SIGN AL TIMES DIM2;Lo;0;L;;;;;N;;;;; +12023;CUNEIFORM SIGN AL TIMES GISH;Lo;0;L;;;;;N;;;;; +12024;CUNEIFORM SIGN AL TIMES HA;Lo;0;L;;;;;N;;;;; +12025;CUNEIFORM SIGN AL TIMES KAD3;Lo;0;L;;;;;N;;;;; +12026;CUNEIFORM SIGN AL TIMES KI;Lo;0;L;;;;;N;;;;; +12027;CUNEIFORM SIGN AL TIMES SHE;Lo;0;L;;;;;N;;;;; +12028;CUNEIFORM SIGN AL TIMES USH;Lo;0;L;;;;;N;;;;; +12029;CUNEIFORM SIGN ALAN;Lo;0;L;;;;;N;;;;; +1202A;CUNEIFORM SIGN ALEPH;Lo;0;L;;;;;N;;;;; +1202B;CUNEIFORM SIGN AMAR;Lo;0;L;;;;;N;;;;; +1202C;CUNEIFORM SIGN AMAR TIMES SHE;Lo;0;L;;;;;N;;;;; +1202D;CUNEIFORM SIGN AN;Lo;0;L;;;;;N;;;;; +1202E;CUNEIFORM SIGN AN OVER AN;Lo;0;L;;;;;N;;;;; +1202F;CUNEIFORM SIGN AN THREE TIMES;Lo;0;L;;;;;N;;;;; +12030;CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA;Lo;0;L;;;;;N;;;;; +12031;CUNEIFORM SIGN AN PLUS NAGA SQUARED;Lo;0;L;;;;;N;;;;; +12032;CUNEIFORM SIGN ANSHE;Lo;0;L;;;;;N;;;;; +12033;CUNEIFORM SIGN APIN;Lo;0;L;;;;;N;;;;; +12034;CUNEIFORM SIGN ARAD;Lo;0;L;;;;;N;;;;; +12035;CUNEIFORM SIGN ARAD TIMES KUR;Lo;0;L;;;;;N;;;;; +12036;CUNEIFORM SIGN ARKAB;Lo;0;L;;;;;N;;;;; +12037;CUNEIFORM SIGN ASAL2;Lo;0;L;;;;;N;;;;; +12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;;N;;;;; +12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; +1203A;CUNEIFORM SIGN ASH KABA TENU;Lo;0;L;;;;;N;;;;; +1203B;CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP;Lo;0;L;;;;;N;;;;; +1203C;CUNEIFORM SIGN ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; +1203D;CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; +1203E;CUNEIFORM SIGN ASH2;Lo;0;L;;;;;N;;;;; +1203F;CUNEIFORM SIGN ASHGAB;Lo;0;L;;;;;N;;;;; +12040;CUNEIFORM SIGN BA;Lo;0;L;;;;;N;;;;; +12041;CUNEIFORM SIGN BAD;Lo;0;L;;;;;N;;;;; +12042;CUNEIFORM SIGN BAG3;Lo;0;L;;;;;N;;;;; +12043;CUNEIFORM SIGN BAHAR2;Lo;0;L;;;;;N;;;;; +12044;CUNEIFORM SIGN BAL;Lo;0;L;;;;;N;;;;; +12045;CUNEIFORM SIGN BAL OVER BAL;Lo;0;L;;;;;N;;;;; +12046;CUNEIFORM SIGN BALAG;Lo;0;L;;;;;N;;;;; +12047;CUNEIFORM SIGN BAR;Lo;0;L;;;;;N;;;;; +12048;CUNEIFORM SIGN BARA2;Lo;0;L;;;;;N;;;;; +12049;CUNEIFORM SIGN BI;Lo;0;L;;;;;N;;;;; +1204A;CUNEIFORM SIGN BI TIMES A;Lo;0;L;;;;;N;;;;; +1204B;CUNEIFORM SIGN BI TIMES GAR;Lo;0;L;;;;;N;;;;; +1204C;CUNEIFORM SIGN BI TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +1204D;CUNEIFORM SIGN BU;Lo;0;L;;;;;N;;;;; +1204E;CUNEIFORM SIGN BU OVER BU AB;Lo;0;L;;;;;N;;;;; +1204F;CUNEIFORM SIGN BU OVER BU UN;Lo;0;L;;;;;N;;;;; +12050;CUNEIFORM SIGN BU CROSSING BU;Lo;0;L;;;;;N;;;;; +12051;CUNEIFORM SIGN BULUG;Lo;0;L;;;;;N;;;;; +12052;CUNEIFORM SIGN BULUG OVER BULUG;Lo;0;L;;;;;N;;;;; +12053;CUNEIFORM SIGN BUR;Lo;0;L;;;;;N;;;;; +12054;CUNEIFORM SIGN BUR2;Lo;0;L;;;;;N;;;;; +12055;CUNEIFORM SIGN DA;Lo;0;L;;;;;N;;;;; +12056;CUNEIFORM SIGN DAG;Lo;0;L;;;;;N;;;;; +12057;CUNEIFORM SIGN DAG KISIM5 TIMES A PLUS MASH;Lo;0;L;;;;;N;;;;; +12058;CUNEIFORM SIGN DAG KISIM5 TIMES AMAR;Lo;0;L;;;;;N;;;;; +12059;CUNEIFORM SIGN DAG KISIM5 TIMES BALAG;Lo;0;L;;;;;N;;;;; +1205A;CUNEIFORM SIGN DAG KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; +1205B;CUNEIFORM SIGN DAG KISIM5 TIMES GA;Lo;0;L;;;;;N;;;;; +1205C;CUNEIFORM SIGN DAG KISIM5 TIMES GA PLUS MASH;Lo;0;L;;;;;N;;;;; +1205D;CUNEIFORM SIGN DAG KISIM5 TIMES GI;Lo;0;L;;;;;N;;;;; +1205E;CUNEIFORM SIGN DAG KISIM5 TIMES GIR2;Lo;0;L;;;;;N;;;;; +1205F;CUNEIFORM SIGN DAG KISIM5 TIMES GUD;Lo;0;L;;;;;N;;;;; +12060;CUNEIFORM SIGN DAG KISIM5 TIMES HA;Lo;0;L;;;;;N;;;;; +12061;CUNEIFORM SIGN DAG KISIM5 TIMES IR;Lo;0;L;;;;;N;;;;; +12062;CUNEIFORM SIGN DAG KISIM5 TIMES IR PLUS LU;Lo;0;L;;;;;N;;;;; +12063;CUNEIFORM SIGN DAG KISIM5 TIMES KAK;Lo;0;L;;;;;N;;;;; +12064;CUNEIFORM SIGN DAG KISIM5 TIMES LA;Lo;0;L;;;;;N;;;;; +12065;CUNEIFORM SIGN DAG KISIM5 TIMES LU;Lo;0;L;;;;;N;;;;; +12066;CUNEIFORM SIGN DAG KISIM5 TIMES LU PLUS MASH2;Lo;0;L;;;;;N;;;;; +12067;CUNEIFORM SIGN DAG KISIM5 TIMES LUM;Lo;0;L;;;;;N;;;;; +12068;CUNEIFORM SIGN DAG KISIM5 TIMES NE;Lo;0;L;;;;;N;;;;; +12069;CUNEIFORM SIGN DAG KISIM5 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;; +1206A;CUNEIFORM SIGN DAG KISIM5 TIMES SI;Lo;0;L;;;;;N;;;;; +1206B;CUNEIFORM SIGN DAG KISIM5 TIMES TAK4;Lo;0;L;;;;;N;;;;; +1206C;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS GIR2;Lo;0;L;;;;;N;;;;; +1206D;CUNEIFORM SIGN DAG KISIM5 TIMES USH;Lo;0;L;;;;;N;;;;; +1206E;CUNEIFORM SIGN DAM;Lo;0;L;;;;;N;;;;; +1206F;CUNEIFORM SIGN DAR;Lo;0;L;;;;;N;;;;; +12070;CUNEIFORM SIGN DARA3;Lo;0;L;;;;;N;;;;; +12071;CUNEIFORM SIGN DARA4;Lo;0;L;;;;;N;;;;; +12072;CUNEIFORM SIGN DI;Lo;0;L;;;;;N;;;;; +12073;CUNEIFORM SIGN DIB;Lo;0;L;;;;;N;;;;; +12074;CUNEIFORM SIGN DIM;Lo;0;L;;;;;N;;;;; +12075;CUNEIFORM SIGN DIM TIMES SHE;Lo;0;L;;;;;N;;;;; +12076;CUNEIFORM SIGN DIM2;Lo;0;L;;;;;N;;;;; +12077;CUNEIFORM SIGN DIN;Lo;0;L;;;;;N;;;;; +12078;CUNEIFORM SIGN DIN KASKAL U GUNU DISH;Lo;0;L;;;;;N;;;;; +12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;;N;;;;; +1207A;CUNEIFORM SIGN DU;Lo;0;L;;;;;N;;;;; +1207B;CUNEIFORM SIGN DU OVER DU;Lo;0;L;;;;;N;;;;; +1207C;CUNEIFORM SIGN DU GUNU;Lo;0;L;;;;;N;;;;; +1207D;CUNEIFORM SIGN DU SHESHIG;Lo;0;L;;;;;N;;;;; +1207E;CUNEIFORM SIGN DUB;Lo;0;L;;;;;N;;;;; +1207F;CUNEIFORM SIGN DUB TIMES ESH2;Lo;0;L;;;;;N;;;;; +12080;CUNEIFORM SIGN DUB2;Lo;0;L;;;;;N;;;;; +12081;CUNEIFORM SIGN DUG;Lo;0;L;;;;;N;;;;; +12082;CUNEIFORM SIGN DUGUD;Lo;0;L;;;;;N;;;;; +12083;CUNEIFORM SIGN DUH;Lo;0;L;;;;;N;;;;; +12084;CUNEIFORM SIGN DUN;Lo;0;L;;;;;N;;;;; +12085;CUNEIFORM SIGN DUN3;Lo;0;L;;;;;N;;;;; +12086;CUNEIFORM SIGN DUN3 GUNU;Lo;0;L;;;;;N;;;;; +12087;CUNEIFORM SIGN DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; +12088;CUNEIFORM SIGN DUN4;Lo;0;L;;;;;N;;;;; +12089;CUNEIFORM SIGN DUR2;Lo;0;L;;;;;N;;;;; +1208A;CUNEIFORM SIGN E;Lo;0;L;;;;;N;;;;; +1208B;CUNEIFORM SIGN E TIMES PAP;Lo;0;L;;;;;N;;;;; +1208C;CUNEIFORM SIGN E OVER E NUN OVER NUN;Lo;0;L;;;;;N;;;;; +1208D;CUNEIFORM SIGN E2;Lo;0;L;;;;;N;;;;; +1208E;CUNEIFORM SIGN E2 TIMES A PLUS HA PLUS DA;Lo;0;L;;;;;N;;;;; +1208F;CUNEIFORM SIGN E2 TIMES GAR;Lo;0;L;;;;;N;;;;; +12090;CUNEIFORM SIGN E2 TIMES MI;Lo;0;L;;;;;N;;;;; +12091;CUNEIFORM SIGN E2 TIMES SAL;Lo;0;L;;;;;N;;;;; +12092;CUNEIFORM SIGN E2 TIMES SHE;Lo;0;L;;;;;N;;;;; +12093;CUNEIFORM SIGN E2 TIMES U;Lo;0;L;;;;;N;;;;; +12094;CUNEIFORM SIGN EDIN;Lo;0;L;;;;;N;;;;; +12095;CUNEIFORM SIGN EGIR;Lo;0;L;;;;;N;;;;; +12096;CUNEIFORM SIGN EL;Lo;0;L;;;;;N;;;;; +12097;CUNEIFORM SIGN EN;Lo;0;L;;;;;N;;;;; +12098;CUNEIFORM SIGN EN TIMES GAN2;Lo;0;L;;;;;N;;;;; +12099;CUNEIFORM SIGN EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1209A;CUNEIFORM SIGN EN TIMES ME;Lo;0;L;;;;;N;;;;; +1209B;CUNEIFORM SIGN EN CROSSING EN;Lo;0;L;;;;;N;;;;; +1209C;CUNEIFORM SIGN EN OPPOSING EN;Lo;0;L;;;;;N;;;;; +1209D;CUNEIFORM SIGN EN SQUARED;Lo;0;L;;;;;N;;;;; +1209E;CUNEIFORM SIGN EREN;Lo;0;L;;;;;N;;;;; +1209F;CUNEIFORM SIGN ERIN2;Lo;0;L;;;;;N;;;;; +120A0;CUNEIFORM SIGN ESH2;Lo;0;L;;;;;N;;;;; +120A1;CUNEIFORM SIGN EZEN;Lo;0;L;;;;;N;;;;; +120A2;CUNEIFORM SIGN EZEN TIMES A;Lo;0;L;;;;;N;;;;; +120A3;CUNEIFORM SIGN EZEN TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; +120A4;CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL;Lo;0;L;;;;;N;;;;; +120A5;CUNEIFORM SIGN EZEN TIMES AN;Lo;0;L;;;;;N;;;;; +120A6;CUNEIFORM SIGN EZEN TIMES BAD;Lo;0;L;;;;;N;;;;; +120A7;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; +120A8;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; +120A9;CUNEIFORM SIGN EZEN TIMES HA;Lo;0;L;;;;;N;;;;; +120AA;CUNEIFORM SIGN EZEN TIMES HA GUNU;Lo;0;L;;;;;N;;;;; +120AB;CUNEIFORM SIGN EZEN TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +120AC;CUNEIFORM SIGN EZEN TIMES KASKAL;Lo;0;L;;;;;N;;;;; +120AD;CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED;Lo;0;L;;;;;N;;;;; +120AE;CUNEIFORM SIGN EZEN TIMES KU3;Lo;0;L;;;;;N;;;;; +120AF;CUNEIFORM SIGN EZEN TIMES LA;Lo;0;L;;;;;N;;;;; +120B0;CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL;Lo;0;L;;;;;N;;;;; +120B1;CUNEIFORM SIGN EZEN TIMES LI;Lo;0;L;;;;;N;;;;; +120B2;CUNEIFORM SIGN EZEN TIMES LU;Lo;0;L;;;;;N;;;;; +120B3;CUNEIFORM SIGN EZEN TIMES U2;Lo;0;L;;;;;N;;;;; +120B4;CUNEIFORM SIGN EZEN TIMES UD;Lo;0;L;;;;;N;;;;; +120B5;CUNEIFORM SIGN GA;Lo;0;L;;;;;N;;;;; +120B6;CUNEIFORM SIGN GA GUNU;Lo;0;L;;;;;N;;;;; +120B7;CUNEIFORM SIGN GA2;Lo;0;L;;;;;N;;;;; +120B8;CUNEIFORM SIGN GA2 TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; +120B9;CUNEIFORM SIGN GA2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; +120BA;CUNEIFORM SIGN GA2 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; +120BB;CUNEIFORM SIGN GA2 TIMES AB2 TENU PLUS TAB;Lo;0;L;;;;;N;;;;; +120BC;CUNEIFORM SIGN GA2 TIMES AN;Lo;0;L;;;;;N;;;;; +120BD;CUNEIFORM SIGN GA2 TIMES ASH;Lo;0;L;;;;;N;;;;; +120BE;CUNEIFORM SIGN GA2 TIMES ASH2 PLUS GAL;Lo;0;L;;;;;N;;;;; +120BF;CUNEIFORM SIGN GA2 TIMES BAD;Lo;0;L;;;;;N;;;;; +120C0;CUNEIFORM SIGN GA2 TIMES BAR PLUS RA;Lo;0;L;;;;;N;;;;; +120C1;CUNEIFORM SIGN GA2 TIMES BUR;Lo;0;L;;;;;N;;;;; +120C2;CUNEIFORM SIGN GA2 TIMES BUR PLUS RA;Lo;0;L;;;;;N;;;;; +120C3;CUNEIFORM SIGN GA2 TIMES DA;Lo;0;L;;;;;N;;;;; +120C4;CUNEIFORM SIGN GA2 TIMES DI;Lo;0;L;;;;;N;;;;; +120C5;CUNEIFORM SIGN GA2 TIMES DIM TIMES SHE;Lo;0;L;;;;;N;;;;; +120C6;CUNEIFORM SIGN GA2 TIMES DUB;Lo;0;L;;;;;N;;;;; +120C7;CUNEIFORM SIGN GA2 TIMES EL;Lo;0;L;;;;;N;;;;; +120C8;CUNEIFORM SIGN GA2 TIMES EL PLUS LA;Lo;0;L;;;;;N;;;;; +120C9;CUNEIFORM SIGN GA2 TIMES EN;Lo;0;L;;;;;N;;;;; +120CA;CUNEIFORM SIGN GA2 TIMES EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +120CB;CUNEIFORM SIGN GA2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +120CC;CUNEIFORM SIGN GA2 TIMES GAR;Lo;0;L;;;;;N;;;;; +120CD;CUNEIFORM SIGN GA2 TIMES GI;Lo;0;L;;;;;N;;;;; +120CE;CUNEIFORM SIGN GA2 TIMES GI4;Lo;0;L;;;;;N;;;;; +120CF;CUNEIFORM SIGN GA2 TIMES GI4 PLUS A;Lo;0;L;;;;;N;;;;; +120D0;CUNEIFORM SIGN GA2 TIMES GIR2 PLUS SU;Lo;0;L;;;;;N;;;;; +120D1;CUNEIFORM SIGN GA2 TIMES HA PLUS LU PLUS ESH2;Lo;0;L;;;;;N;;;;; +120D2;CUNEIFORM SIGN GA2 TIMES HAL;Lo;0;L;;;;;N;;;;; +120D3;CUNEIFORM SIGN GA2 TIMES HAL PLUS LA;Lo;0;L;;;;;N;;;;; +120D4;CUNEIFORM SIGN GA2 TIMES HI PLUS LI;Lo;0;L;;;;;N;;;;; +120D5;CUNEIFORM SIGN GA2 TIMES HUB2;Lo;0;L;;;;;N;;;;; +120D6;CUNEIFORM SIGN GA2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +120D7;CUNEIFORM SIGN GA2 TIMES ISH PLUS HU PLUS ASH;Lo;0;L;;;;;N;;;;; +120D8;CUNEIFORM SIGN GA2 TIMES KAK;Lo;0;L;;;;;N;;;;; +120D9;CUNEIFORM SIGN GA2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; +120DA;CUNEIFORM SIGN GA2 TIMES KID;Lo;0;L;;;;;N;;;;; +120DB;CUNEIFORM SIGN GA2 TIMES KID PLUS LAL;Lo;0;L;;;;;N;;;;; +120DC;CUNEIFORM SIGN GA2 TIMES KU3 PLUS AN;Lo;0;L;;;;;N;;;;; +120DD;CUNEIFORM SIGN GA2 TIMES LA;Lo;0;L;;;;;N;;;;; +120DE;CUNEIFORM SIGN GA2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; +120DF;CUNEIFORM SIGN GA2 TIMES MI;Lo;0;L;;;;;N;;;;; +120E0;CUNEIFORM SIGN GA2 TIMES NUN;Lo;0;L;;;;;N;;;;; +120E1;CUNEIFORM SIGN GA2 TIMES NUN OVER NUN;Lo;0;L;;;;;N;;;;; +120E2;CUNEIFORM SIGN GA2 TIMES PA;Lo;0;L;;;;;N;;;;; +120E3;CUNEIFORM SIGN GA2 TIMES SAL;Lo;0;L;;;;;N;;;;; +120E4;CUNEIFORM SIGN GA2 TIMES SAR;Lo;0;L;;;;;N;;;;; +120E5;CUNEIFORM SIGN GA2 TIMES SHE;Lo;0;L;;;;;N;;;;; +120E6;CUNEIFORM SIGN GA2 TIMES SHE PLUS TUR;Lo;0;L;;;;;N;;;;; +120E7;CUNEIFORM SIGN GA2 TIMES SHID;Lo;0;L;;;;;N;;;;; +120E8;CUNEIFORM SIGN GA2 TIMES SUM;Lo;0;L;;;;;N;;;;; +120E9;CUNEIFORM SIGN GA2 TIMES TAK4;Lo;0;L;;;;;N;;;;; +120EA;CUNEIFORM SIGN GA2 TIMES U;Lo;0;L;;;;;N;;;;; +120EB;CUNEIFORM SIGN GA2 TIMES UD;Lo;0;L;;;;;N;;;;; +120EC;CUNEIFORM SIGN GA2 TIMES UD PLUS DU;Lo;0;L;;;;;N;;;;; +120ED;CUNEIFORM SIGN GA2 OVER GA2;Lo;0;L;;;;;N;;;;; +120EE;CUNEIFORM SIGN GABA;Lo;0;L;;;;;N;;;;; +120EF;CUNEIFORM SIGN GABA CROSSING GABA;Lo;0;L;;;;;N;;;;; +120F0;CUNEIFORM SIGN GAD;Lo;0;L;;;;;N;;;;; +120F1;CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; +120F2;CUNEIFORM SIGN GAL;Lo;0;L;;;;;N;;;;; +120F3;CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; +120F4;CUNEIFORM SIGN GALAM;Lo;0;L;;;;;N;;;;; +120F5;CUNEIFORM SIGN GAM;Lo;0;L;;;;;N;;;;; +120F6;CUNEIFORM SIGN GAN;Lo;0;L;;;;;N;;;;; +120F7;CUNEIFORM SIGN GAN2;Lo;0;L;;;;;N;;;;; +120F8;CUNEIFORM SIGN GAN2 TENU;Lo;0;L;;;;;N;;;;; +120F9;CUNEIFORM SIGN GAN2 OVER GAN2;Lo;0;L;;;;;N;;;;; +120FA;CUNEIFORM SIGN GAN2 CROSSING GAN2;Lo;0;L;;;;;N;;;;; +120FB;CUNEIFORM SIGN GAR;Lo;0;L;;;;;N;;;;; +120FC;CUNEIFORM SIGN GAR3;Lo;0;L;;;;;N;;;;; +120FD;CUNEIFORM SIGN GASHAN;Lo;0;L;;;;;N;;;;; +120FE;CUNEIFORM SIGN GESHTIN;Lo;0;L;;;;;N;;;;; +120FF;CUNEIFORM SIGN GESHTIN TIMES KUR;Lo;0;L;;;;;N;;;;; +12100;CUNEIFORM SIGN GI;Lo;0;L;;;;;N;;;;; +12101;CUNEIFORM SIGN GI TIMES E;Lo;0;L;;;;;N;;;;; +12102;CUNEIFORM SIGN GI TIMES U;Lo;0;L;;;;;N;;;;; +12103;CUNEIFORM SIGN GI CROSSING GI;Lo;0;L;;;;;N;;;;; +12104;CUNEIFORM SIGN GI4;Lo;0;L;;;;;N;;;;; +12105;CUNEIFORM SIGN GI4 OVER GI4;Lo;0;L;;;;;N;;;;; +12106;CUNEIFORM SIGN GI4 CROSSING GI4;Lo;0;L;;;;;N;;;;; +12107;CUNEIFORM SIGN GIDIM;Lo;0;L;;;;;N;;;;; +12108;CUNEIFORM SIGN GIR2;Lo;0;L;;;;;N;;;;; +12109;CUNEIFORM SIGN GIR2 GUNU;Lo;0;L;;;;;N;;;;; +1210A;CUNEIFORM SIGN GIR3;Lo;0;L;;;;;N;;;;; +1210B;CUNEIFORM SIGN GIR3 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; +1210C;CUNEIFORM SIGN GIR3 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1210D;CUNEIFORM SIGN GIR3 TIMES IGI;Lo;0;L;;;;;N;;;;; +1210E;CUNEIFORM SIGN GIR3 TIMES LU PLUS IGI;Lo;0;L;;;;;N;;;;; +1210F;CUNEIFORM SIGN GIR3 TIMES PA;Lo;0;L;;;;;N;;;;; +12110;CUNEIFORM SIGN GISAL;Lo;0;L;;;;;N;;;;; +12111;CUNEIFORM SIGN GISH;Lo;0;L;;;;;N;;;;; +12112;CUNEIFORM SIGN GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; +12113;CUNEIFORM SIGN GISH TIMES BAD;Lo;0;L;;;;;N;;;;; +12114;CUNEIFORM SIGN GISH TIMES TAK4;Lo;0;L;;;;;N;;;;; +12115;CUNEIFORM SIGN GISH TENU;Lo;0;L;;;;;N;;;;; +12116;CUNEIFORM SIGN GU;Lo;0;L;;;;;N;;;;; +12117;CUNEIFORM SIGN GU CROSSING GU;Lo;0;L;;;;;N;;;;; +12118;CUNEIFORM SIGN GU2;Lo;0;L;;;;;N;;;;; +12119;CUNEIFORM SIGN GU2 TIMES KAK;Lo;0;L;;;;;N;;;;; +1211A;CUNEIFORM SIGN GU2 TIMES KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +1211B;CUNEIFORM SIGN GU2 TIMES NUN;Lo;0;L;;;;;N;;;;; +1211C;CUNEIFORM SIGN GU2 TIMES SAL PLUS TUG2;Lo;0;L;;;;;N;;;;; +1211D;CUNEIFORM SIGN GU2 GUNU;Lo;0;L;;;;;N;;;;; +1211E;CUNEIFORM SIGN GUD;Lo;0;L;;;;;N;;;;; +1211F;CUNEIFORM SIGN GUD TIMES A PLUS KUR;Lo;0;L;;;;;N;;;;; +12120;CUNEIFORM SIGN GUD TIMES KUR;Lo;0;L;;;;;N;;;;; +12121;CUNEIFORM SIGN GUD OVER GUD LUGAL;Lo;0;L;;;;;N;;;;; +12122;CUNEIFORM SIGN GUL;Lo;0;L;;;;;N;;;;; +12123;CUNEIFORM SIGN GUM;Lo;0;L;;;;;N;;;;; +12124;CUNEIFORM SIGN GUM TIMES SHE;Lo;0;L;;;;;N;;;;; +12125;CUNEIFORM SIGN GUR;Lo;0;L;;;;;N;;;;; +12126;CUNEIFORM SIGN GUR7;Lo;0;L;;;;;N;;;;; +12127;CUNEIFORM SIGN GURUN;Lo;0;L;;;;;N;;;;; +12128;CUNEIFORM SIGN GURUSH;Lo;0;L;;;;;N;;;;; +12129;CUNEIFORM SIGN HA;Lo;0;L;;;;;N;;;;; +1212A;CUNEIFORM SIGN HA TENU;Lo;0;L;;;;;N;;;;; +1212B;CUNEIFORM SIGN HA GUNU;Lo;0;L;;;;;N;;;;; +1212C;CUNEIFORM SIGN HAL;Lo;0;L;;;;;N;;;;; +1212D;CUNEIFORM SIGN HI;Lo;0;L;;;;;N;;;;; +1212E;CUNEIFORM SIGN HI TIMES ASH;Lo;0;L;;;;;N;;;;; +1212F;CUNEIFORM SIGN HI TIMES ASH2;Lo;0;L;;;;;N;;;;; +12130;CUNEIFORM SIGN HI TIMES BAD;Lo;0;L;;;;;N;;;;; +12131;CUNEIFORM SIGN HI TIMES DISH;Lo;0;L;;;;;N;;;;; +12132;CUNEIFORM SIGN HI TIMES GAD;Lo;0;L;;;;;N;;;;; +12133;CUNEIFORM SIGN HI TIMES KIN;Lo;0;L;;;;;N;;;;; +12134;CUNEIFORM SIGN HI TIMES NUN;Lo;0;L;;;;;N;;;;; +12135;CUNEIFORM SIGN HI TIMES SHE;Lo;0;L;;;;;N;;;;; +12136;CUNEIFORM SIGN HI TIMES U;Lo;0;L;;;;;N;;;;; +12137;CUNEIFORM SIGN HU;Lo;0;L;;;;;N;;;;; +12138;CUNEIFORM SIGN HUB2;Lo;0;L;;;;;N;;;;; +12139;CUNEIFORM SIGN HUB2 TIMES AN;Lo;0;L;;;;;N;;;;; +1213A;CUNEIFORM SIGN HUB2 TIMES HAL;Lo;0;L;;;;;N;;;;; +1213B;CUNEIFORM SIGN HUB2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; +1213C;CUNEIFORM SIGN HUB2 TIMES LISH;Lo;0;L;;;;;N;;;;; +1213D;CUNEIFORM SIGN HUB2 TIMES UD;Lo;0;L;;;;;N;;;;; +1213E;CUNEIFORM SIGN HUL2;Lo;0;L;;;;;N;;;;; +1213F;CUNEIFORM SIGN I;Lo;0;L;;;;;N;;;;; +12140;CUNEIFORM SIGN I A;Lo;0;L;;;;;N;;;;; +12141;CUNEIFORM SIGN IB;Lo;0;L;;;;;N;;;;; +12142;CUNEIFORM SIGN IDIM;Lo;0;L;;;;;N;;;;; +12143;CUNEIFORM SIGN IDIM OVER IDIM BUR;Lo;0;L;;;;;N;;;;; +12144;CUNEIFORM SIGN IDIM OVER IDIM SQUARED;Lo;0;L;;;;;N;;;;; +12145;CUNEIFORM SIGN IG;Lo;0;L;;;;;N;;;;; +12146;CUNEIFORM SIGN IGI;Lo;0;L;;;;;N;;;;; +12147;CUNEIFORM SIGN IGI DIB;Lo;0;L;;;;;N;;;;; +12148;CUNEIFORM SIGN IGI RI;Lo;0;L;;;;;N;;;;; +12149;CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD;Lo;0;L;;;;;N;;;;; +1214A;CUNEIFORM SIGN IGI GUNU;Lo;0;L;;;;;N;;;;; +1214B;CUNEIFORM SIGN IL;Lo;0;L;;;;;N;;;;; +1214C;CUNEIFORM SIGN IL TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1214D;CUNEIFORM SIGN IL2;Lo;0;L;;;;;N;;;;; +1214E;CUNEIFORM SIGN IM;Lo;0;L;;;;;N;;;;; +1214F;CUNEIFORM SIGN IM TIMES TAK4;Lo;0;L;;;;;N;;;;; +12150;CUNEIFORM SIGN IM CROSSING IM;Lo;0;L;;;;;N;;;;; +12151;CUNEIFORM SIGN IM OPPOSING IM;Lo;0;L;;;;;N;;;;; +12152;CUNEIFORM SIGN IM SQUARED;Lo;0;L;;;;;N;;;;; +12153;CUNEIFORM SIGN IMIN;Lo;0;L;;;;;N;;;;; +12154;CUNEIFORM SIGN IN;Lo;0;L;;;;;N;;;;; +12155;CUNEIFORM SIGN IR;Lo;0;L;;;;;N;;;;; +12156;CUNEIFORM SIGN ISH;Lo;0;L;;;;;N;;;;; +12157;CUNEIFORM SIGN KA;Lo;0;L;;;;;N;;;;; +12158;CUNEIFORM SIGN KA TIMES A;Lo;0;L;;;;;N;;;;; +12159;CUNEIFORM SIGN KA TIMES AD;Lo;0;L;;;;;N;;;;; +1215A;CUNEIFORM SIGN KA TIMES AD PLUS KU3;Lo;0;L;;;;;N;;;;; +1215B;CUNEIFORM SIGN KA TIMES ASH2;Lo;0;L;;;;;N;;;;; +1215C;CUNEIFORM SIGN KA TIMES BAD;Lo;0;L;;;;;N;;;;; +1215D;CUNEIFORM SIGN KA TIMES BALAG;Lo;0;L;;;;;N;;;;; +1215E;CUNEIFORM SIGN KA TIMES BAR;Lo;0;L;;;;;N;;;;; +1215F;CUNEIFORM SIGN KA TIMES BI;Lo;0;L;;;;;N;;;;; +12160;CUNEIFORM SIGN KA TIMES ERIN2;Lo;0;L;;;;;N;;;;; +12161;CUNEIFORM SIGN KA TIMES ESH2;Lo;0;L;;;;;N;;;;; +12162;CUNEIFORM SIGN KA TIMES GA;Lo;0;L;;;;;N;;;;; +12163;CUNEIFORM SIGN KA TIMES GAL;Lo;0;L;;;;;N;;;;; +12164;CUNEIFORM SIGN KA TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12165;CUNEIFORM SIGN KA TIMES GAR;Lo;0;L;;;;;N;;;;; +12166;CUNEIFORM SIGN KA TIMES GAR PLUS SHA3 PLUS A;Lo;0;L;;;;;N;;;;; +12167;CUNEIFORM SIGN KA TIMES GI;Lo;0;L;;;;;N;;;;; +12168;CUNEIFORM SIGN KA TIMES GIR2;Lo;0;L;;;;;N;;;;; +12169;CUNEIFORM SIGN KA TIMES GISH PLUS SAR;Lo;0;L;;;;;N;;;;; +1216A;CUNEIFORM SIGN KA TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; +1216B;CUNEIFORM SIGN KA TIMES GU;Lo;0;L;;;;;N;;;;; +1216C;CUNEIFORM SIGN KA TIMES GUR7;Lo;0;L;;;;;N;;;;; +1216D;CUNEIFORM SIGN KA TIMES IGI;Lo;0;L;;;;;N;;;;; +1216E;CUNEIFORM SIGN KA TIMES IM;Lo;0;L;;;;;N;;;;; +1216F;CUNEIFORM SIGN KA TIMES KAK;Lo;0;L;;;;;N;;;;; +12170;CUNEIFORM SIGN KA TIMES KI;Lo;0;L;;;;;N;;;;; +12171;CUNEIFORM SIGN KA TIMES KID;Lo;0;L;;;;;N;;;;; +12172;CUNEIFORM SIGN KA TIMES LI;Lo;0;L;;;;;N;;;;; +12173;CUNEIFORM SIGN KA TIMES LU;Lo;0;L;;;;;N;;;;; +12174;CUNEIFORM SIGN KA TIMES ME;Lo;0;L;;;;;N;;;;; +12175;CUNEIFORM SIGN KA TIMES ME PLUS DU;Lo;0;L;;;;;N;;;;; +12176;CUNEIFORM SIGN KA TIMES ME PLUS GI;Lo;0;L;;;;;N;;;;; +12177;CUNEIFORM SIGN KA TIMES ME PLUS TE;Lo;0;L;;;;;N;;;;; +12178;CUNEIFORM SIGN KA TIMES MI;Lo;0;L;;;;;N;;;;; +12179;CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ;Lo;0;L;;;;;N;;;;; +1217A;CUNEIFORM SIGN KA TIMES NE;Lo;0;L;;;;;N;;;;; +1217B;CUNEIFORM SIGN KA TIMES NUN;Lo;0;L;;;;;N;;;;; +1217C;CUNEIFORM SIGN KA TIMES PI;Lo;0;L;;;;;N;;;;; +1217D;CUNEIFORM SIGN KA TIMES RU;Lo;0;L;;;;;N;;;;; +1217E;CUNEIFORM SIGN KA TIMES SA;Lo;0;L;;;;;N;;;;; +1217F;CUNEIFORM SIGN KA TIMES SAR;Lo;0;L;;;;;N;;;;; +12180;CUNEIFORM SIGN KA TIMES SHA;Lo;0;L;;;;;N;;;;; +12181;CUNEIFORM SIGN KA TIMES SHE;Lo;0;L;;;;;N;;;;; +12182;CUNEIFORM SIGN KA TIMES SHID;Lo;0;L;;;;;N;;;;; +12183;CUNEIFORM SIGN KA TIMES SHU;Lo;0;L;;;;;N;;;;; +12184;CUNEIFORM SIGN KA TIMES SIG;Lo;0;L;;;;;N;;;;; +12185;CUNEIFORM SIGN KA TIMES SUHUR;Lo;0;L;;;;;N;;;;; +12186;CUNEIFORM SIGN KA TIMES TAR;Lo;0;L;;;;;N;;;;; +12187;CUNEIFORM SIGN KA TIMES U;Lo;0;L;;;;;N;;;;; +12188;CUNEIFORM SIGN KA TIMES U2;Lo;0;L;;;;;N;;;;; +12189;CUNEIFORM SIGN KA TIMES UD;Lo;0;L;;;;;N;;;;; +1218A;CUNEIFORM SIGN KA TIMES UMUM TIMES PA;Lo;0;L;;;;;N;;;;; +1218B;CUNEIFORM SIGN KA TIMES USH;Lo;0;L;;;;;N;;;;; +1218C;CUNEIFORM SIGN KA TIMES ZI;Lo;0;L;;;;;N;;;;; +1218D;CUNEIFORM SIGN KA2;Lo;0;L;;;;;N;;;;; +1218E;CUNEIFORM SIGN KA2 CROSSING KA2;Lo;0;L;;;;;N;;;;; +1218F;CUNEIFORM SIGN KAB;Lo;0;L;;;;;N;;;;; +12190;CUNEIFORM SIGN KAD2;Lo;0;L;;;;;N;;;;; +12191;CUNEIFORM SIGN KAD3;Lo;0;L;;;;;N;;;;; +12192;CUNEIFORM SIGN KAD4;Lo;0;L;;;;;N;;;;; +12193;CUNEIFORM SIGN KAD5;Lo;0;L;;;;;N;;;;; +12194;CUNEIFORM SIGN KAD5 OVER KAD5;Lo;0;L;;;;;N;;;;; +12195;CUNEIFORM SIGN KAK;Lo;0;L;;;;;N;;;;; +12196;CUNEIFORM SIGN KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12197;CUNEIFORM SIGN KAL;Lo;0;L;;;;;N;;;;; +12198;CUNEIFORM SIGN KAL TIMES BAD;Lo;0;L;;;;;N;;;;; +12199;CUNEIFORM SIGN KAL CROSSING KAL;Lo;0;L;;;;;N;;;;; +1219A;CUNEIFORM SIGN KAM2;Lo;0;L;;;;;N;;;;; +1219B;CUNEIFORM SIGN KAM4;Lo;0;L;;;;;N;;;;; +1219C;CUNEIFORM SIGN KASKAL;Lo;0;L;;;;;N;;;;; +1219D;CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; +1219E;CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; +1219F;CUNEIFORM SIGN KESH2;Lo;0;L;;;;;N;;;;; +121A0;CUNEIFORM SIGN KI;Lo;0;L;;;;;N;;;;; +121A1;CUNEIFORM SIGN KI TIMES BAD;Lo;0;L;;;;;N;;;;; +121A2;CUNEIFORM SIGN KI TIMES U;Lo;0;L;;;;;N;;;;; +121A3;CUNEIFORM SIGN KI TIMES UD;Lo;0;L;;;;;N;;;;; +121A4;CUNEIFORM SIGN KID;Lo;0;L;;;;;N;;;;; +121A5;CUNEIFORM SIGN KIN;Lo;0;L;;;;;N;;;;; +121A6;CUNEIFORM SIGN KISAL;Lo;0;L;;;;;N;;;;; +121A7;CUNEIFORM SIGN KISH;Lo;0;L;;;;;N;;;;; +121A8;CUNEIFORM SIGN KISIM5;Lo;0;L;;;;;N;;;;; +121A9;CUNEIFORM SIGN KISIM5 OVER KISIM5;Lo;0;L;;;;;N;;;;; +121AA;CUNEIFORM SIGN KU;Lo;0;L;;;;;N;;;;; +121AB;CUNEIFORM SIGN KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2;Lo;0;L;;;;;N;;;;; +121AC;CUNEIFORM SIGN KU3;Lo;0;L;;;;;N;;;;; +121AD;CUNEIFORM SIGN KU4;Lo;0;L;;;;;N;;;;; +121AE;CUNEIFORM SIGN KU4 VARIANT FORM;Lo;0;L;;;;;N;;;;; +121AF;CUNEIFORM SIGN KU7;Lo;0;L;;;;;N;;;;; +121B0;CUNEIFORM SIGN KUL;Lo;0;L;;;;;N;;;;; +121B1;CUNEIFORM SIGN KUL GUNU;Lo;0;L;;;;;N;;;;; +121B2;CUNEIFORM SIGN KUN;Lo;0;L;;;;;N;;;;; +121B3;CUNEIFORM SIGN KUR;Lo;0;L;;;;;N;;;;; +121B4;CUNEIFORM SIGN KUR OPPOSING KUR;Lo;0;L;;;;;N;;;;; +121B5;CUNEIFORM SIGN KUSHU2;Lo;0;L;;;;;N;;;;; +121B6;CUNEIFORM SIGN KWU318;Lo;0;L;;;;;N;;;;; +121B7;CUNEIFORM SIGN LA;Lo;0;L;;;;;N;;;;; +121B8;CUNEIFORM SIGN LAGAB;Lo;0;L;;;;;N;;;;; +121B9;CUNEIFORM SIGN LAGAB TIMES A;Lo;0;L;;;;;N;;;;; +121BA;CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; +121BB;CUNEIFORM SIGN LAGAB TIMES A PLUS GAR;Lo;0;L;;;;;N;;;;; +121BC;CUNEIFORM SIGN LAGAB TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; +121BD;CUNEIFORM SIGN LAGAB TIMES AL;Lo;0;L;;;;;N;;;;; +121BE;CUNEIFORM SIGN LAGAB TIMES AN;Lo;0;L;;;;;N;;;;; +121BF;CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; +121C0;CUNEIFORM SIGN LAGAB TIMES BAD;Lo;0;L;;;;;N;;;;; +121C1;CUNEIFORM SIGN LAGAB TIMES BI;Lo;0;L;;;;;N;;;;; +121C2;CUNEIFORM SIGN LAGAB TIMES DAR;Lo;0;L;;;;;N;;;;; +121C3;CUNEIFORM SIGN LAGAB TIMES EN;Lo;0;L;;;;;N;;;;; +121C4;CUNEIFORM SIGN LAGAB TIMES GA;Lo;0;L;;;;;N;;;;; +121C5;CUNEIFORM SIGN LAGAB TIMES GAR;Lo;0;L;;;;;N;;;;; +121C6;CUNEIFORM SIGN LAGAB TIMES GUD;Lo;0;L;;;;;N;;;;; +121C7;CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD;Lo;0;L;;;;;N;;;;; +121C8;CUNEIFORM SIGN LAGAB TIMES HA;Lo;0;L;;;;;N;;;;; +121C9;CUNEIFORM SIGN LAGAB TIMES HAL;Lo;0;L;;;;;N;;;;; +121CA;CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN;Lo;0;L;;;;;N;;;;; +121CB;CUNEIFORM SIGN LAGAB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +121CC;CUNEIFORM SIGN LAGAB TIMES IM;Lo;0;L;;;;;N;;;;; +121CD;CUNEIFORM SIGN LAGAB TIMES IM PLUS HA;Lo;0;L;;;;;N;;;;; +121CE;CUNEIFORM SIGN LAGAB TIMES IM PLUS LU;Lo;0;L;;;;;N;;;;; +121CF;CUNEIFORM SIGN LAGAB TIMES KI;Lo;0;L;;;;;N;;;;; +121D0;CUNEIFORM SIGN LAGAB TIMES KIN;Lo;0;L;;;;;N;;;;; +121D1;CUNEIFORM SIGN LAGAB TIMES KU3;Lo;0;L;;;;;N;;;;; +121D2;CUNEIFORM SIGN LAGAB TIMES KUL;Lo;0;L;;;;;N;;;;; +121D3;CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A;Lo;0;L;;;;;N;;;;; +121D4;CUNEIFORM SIGN LAGAB TIMES LAGAB;Lo;0;L;;;;;N;;;;; +121D5;CUNEIFORM SIGN LAGAB TIMES LISH;Lo;0;L;;;;;N;;;;; +121D6;CUNEIFORM SIGN LAGAB TIMES LU;Lo;0;L;;;;;N;;;;; +121D7;CUNEIFORM SIGN LAGAB TIMES LUL;Lo;0;L;;;;;N;;;;; +121D8;CUNEIFORM SIGN LAGAB TIMES ME;Lo;0;L;;;;;N;;;;; +121D9;CUNEIFORM SIGN LAGAB TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; +121DA;CUNEIFORM SIGN LAGAB TIMES MUSH;Lo;0;L;;;;;N;;;;; +121DB;CUNEIFORM SIGN LAGAB TIMES NE;Lo;0;L;;;;;N;;;;; +121DC;CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; +121DD;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN2;Lo;0;L;;;;;N;;;;; +121DE;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU;Lo;0;L;;;;;N;;;;; +121DF;CUNEIFORM SIGN LAGAB TIMES SHU2;Lo;0;L;;;;;N;;;;; +121E0;CUNEIFORM SIGN LAGAB TIMES SHU2 PLUS SHU2;Lo;0;L;;;;;N;;;;; +121E1;CUNEIFORM SIGN LAGAB TIMES SUM;Lo;0;L;;;;;N;;;;; +121E2;CUNEIFORM SIGN LAGAB TIMES TAG;Lo;0;L;;;;;N;;;;; +121E3;CUNEIFORM SIGN LAGAB TIMES TAK4;Lo;0;L;;;;;N;;;;; +121E4;CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA;Lo;0;L;;;;;N;;;;; +121E5;CUNEIFORM SIGN LAGAB TIMES U;Lo;0;L;;;;;N;;;;; +121E6;CUNEIFORM SIGN LAGAB TIMES U PLUS A;Lo;0;L;;;;;N;;;;; +121E7;CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; +121E8;CUNEIFORM SIGN LAGAB TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; +121E9;CUNEIFORM SIGN LAGAB TIMES UD;Lo;0;L;;;;;N;;;;; +121EA;CUNEIFORM SIGN LAGAB TIMES USH;Lo;0;L;;;;;N;;;;; +121EB;CUNEIFORM SIGN LAGAB SQUARED;Lo;0;L;;;;;N;;;;; +121EC;CUNEIFORM SIGN LAGAR;Lo;0;L;;;;;N;;;;; +121ED;CUNEIFORM SIGN LAGAR TIMES SHE;Lo;0;L;;;;;N;;;;; +121EE;CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; +121EF;CUNEIFORM SIGN LAGAR GUNU;Lo;0;L;;;;;N;;;;; +121F0;CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE;Lo;0;L;;;;;N;;;;; +121F1;CUNEIFORM SIGN LAHSHU;Lo;0;L;;;;;N;;;;; +121F2;CUNEIFORM SIGN LAL;Lo;0;L;;;;;N;;;;; +121F3;CUNEIFORM SIGN LAL TIMES LAL;Lo;0;L;;;;;N;;;;; +121F4;CUNEIFORM SIGN LAM;Lo;0;L;;;;;N;;;;; +121F5;CUNEIFORM SIGN LAM TIMES KUR;Lo;0;L;;;;;N;;;;; +121F6;CUNEIFORM SIGN LAM TIMES KUR PLUS RU;Lo;0;L;;;;;N;;;;; +121F7;CUNEIFORM SIGN LI;Lo;0;L;;;;;N;;;;; +121F8;CUNEIFORM SIGN LIL;Lo;0;L;;;;;N;;;;; +121F9;CUNEIFORM SIGN LIMMU2;Lo;0;L;;;;;N;;;;; +121FA;CUNEIFORM SIGN LISH;Lo;0;L;;;;;N;;;;; +121FB;CUNEIFORM SIGN LU;Lo;0;L;;;;;N;;;;; +121FC;CUNEIFORM SIGN LU TIMES BAD;Lo;0;L;;;;;N;;;;; +121FD;CUNEIFORM SIGN LU2;Lo;0;L;;;;;N;;;;; +121FE;CUNEIFORM SIGN LU2 TIMES AL;Lo;0;L;;;;;N;;;;; +121FF;CUNEIFORM SIGN LU2 TIMES BAD;Lo;0;L;;;;;N;;;;; +12200;CUNEIFORM SIGN LU2 TIMES ESH2;Lo;0;L;;;;;N;;;;; +12201;CUNEIFORM SIGN LU2 TIMES ESH2 TENU;Lo;0;L;;;;;N;;;;; +12202;CUNEIFORM SIGN LU2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12203;CUNEIFORM SIGN LU2 TIMES HI TIMES BAD;Lo;0;L;;;;;N;;;;; +12204;CUNEIFORM SIGN LU2 TIMES IM;Lo;0;L;;;;;N;;;;; +12205;CUNEIFORM SIGN LU2 TIMES KAD2;Lo;0;L;;;;;N;;;;; +12206;CUNEIFORM SIGN LU2 TIMES KAD3;Lo;0;L;;;;;N;;;;; +12207;CUNEIFORM SIGN LU2 TIMES KAD3 PLUS ASH;Lo;0;L;;;;;N;;;;; +12208;CUNEIFORM SIGN LU2 TIMES KI;Lo;0;L;;;;;N;;;;; +12209;CUNEIFORM SIGN LU2 TIMES LA PLUS ASH;Lo;0;L;;;;;N;;;;; +1220A;CUNEIFORM SIGN LU2 TIMES LAGAB;Lo;0;L;;;;;N;;;;; +1220B;CUNEIFORM SIGN LU2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; +1220C;CUNEIFORM SIGN LU2 TIMES NE;Lo;0;L;;;;;N;;;;; +1220D;CUNEIFORM SIGN LU2 TIMES NU;Lo;0;L;;;;;N;;;;; +1220E;CUNEIFORM SIGN LU2 TIMES SI PLUS ASH;Lo;0;L;;;;;N;;;;; +1220F;CUNEIFORM SIGN LU2 TIMES SIK2 PLUS BU;Lo;0;L;;;;;N;;;;; +12210;CUNEIFORM SIGN LU2 TIMES TUG2;Lo;0;L;;;;;N;;;;; +12211;CUNEIFORM SIGN LU2 TENU;Lo;0;L;;;;;N;;;;; +12212;CUNEIFORM SIGN LU2 CROSSING LU2;Lo;0;L;;;;;N;;;;; +12213;CUNEIFORM SIGN LU2 OPPOSING LU2;Lo;0;L;;;;;N;;;;; +12214;CUNEIFORM SIGN LU2 SQUARED;Lo;0;L;;;;;N;;;;; +12215;CUNEIFORM SIGN LU2 SHESHIG;Lo;0;L;;;;;N;;;;; +12216;CUNEIFORM SIGN LU3;Lo;0;L;;;;;N;;;;; +12217;CUNEIFORM SIGN LUGAL;Lo;0;L;;;;;N;;;;; +12218;CUNEIFORM SIGN LUGAL OVER LUGAL;Lo;0;L;;;;;N;;;;; +12219;CUNEIFORM SIGN LUGAL OPPOSING LUGAL;Lo;0;L;;;;;N;;;;; +1221A;CUNEIFORM SIGN LUGAL SHESHIG;Lo;0;L;;;;;N;;;;; +1221B;CUNEIFORM SIGN LUH;Lo;0;L;;;;;N;;;;; +1221C;CUNEIFORM SIGN LUL;Lo;0;L;;;;;N;;;;; +1221D;CUNEIFORM SIGN LUM;Lo;0;L;;;;;N;;;;; +1221E;CUNEIFORM SIGN LUM OVER LUM;Lo;0;L;;;;;N;;;;; +1221F;CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR;Lo;0;L;;;;;N;;;;; +12220;CUNEIFORM SIGN MA;Lo;0;L;;;;;N;;;;; +12221;CUNEIFORM SIGN MA TIMES TAK4;Lo;0;L;;;;;N;;;;; +12222;CUNEIFORM SIGN MA GUNU;Lo;0;L;;;;;N;;;;; +12223;CUNEIFORM SIGN MA2;Lo;0;L;;;;;N;;;;; +12224;CUNEIFORM SIGN MAH;Lo;0;L;;;;;N;;;;; +12225;CUNEIFORM SIGN MAR;Lo;0;L;;;;;N;;;;; +12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;;N;;;;; +12227;CUNEIFORM SIGN MASH2;Lo;0;L;;;;;N;;;;; +12228;CUNEIFORM SIGN ME;Lo;0;L;;;;;N;;;;; +12229;CUNEIFORM SIGN MES;Lo;0;L;;;;;N;;;;; +1222A;CUNEIFORM SIGN MI;Lo;0;L;;;;;N;;;;; +1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;;N;;;;; +1222C;CUNEIFORM SIGN MU;Lo;0;L;;;;;N;;;;; +1222D;CUNEIFORM SIGN MU OVER MU;Lo;0;L;;;;;N;;;;; +1222E;CUNEIFORM SIGN MUG;Lo;0;L;;;;;N;;;;; +1222F;CUNEIFORM SIGN MUG GUNU;Lo;0;L;;;;;N;;;;; +12230;CUNEIFORM SIGN MUNSUB;Lo;0;L;;;;;N;;;;; +12231;CUNEIFORM SIGN MURGU2;Lo;0;L;;;;;N;;;;; +12232;CUNEIFORM SIGN MUSH;Lo;0;L;;;;;N;;;;; +12233;CUNEIFORM SIGN MUSH TIMES A;Lo;0;L;;;;;N;;;;; +12234;CUNEIFORM SIGN MUSH TIMES KUR;Lo;0;L;;;;;N;;;;; +12235;CUNEIFORM SIGN MUSH TIMES ZA;Lo;0;L;;;;;N;;;;; +12236;CUNEIFORM SIGN MUSH OVER MUSH;Lo;0;L;;;;;N;;;;; +12237;CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; +12238;CUNEIFORM SIGN MUSH CROSSING MUSH;Lo;0;L;;;;;N;;;;; +12239;CUNEIFORM SIGN MUSH3;Lo;0;L;;;;;N;;;;; +1223A;CUNEIFORM SIGN MUSH3 TIMES A;Lo;0;L;;;;;N;;;;; +1223B;CUNEIFORM SIGN MUSH3 TIMES A PLUS DI;Lo;0;L;;;;;N;;;;; +1223C;CUNEIFORM SIGN MUSH3 TIMES DI;Lo;0;L;;;;;N;;;;; +1223D;CUNEIFORM SIGN MUSH3 GUNU;Lo;0;L;;;;;N;;;;; +1223E;CUNEIFORM SIGN NA;Lo;0;L;;;;;N;;;;; +1223F;CUNEIFORM SIGN NA2;Lo;0;L;;;;;N;;;;; +12240;CUNEIFORM SIGN NAGA;Lo;0;L;;;;;N;;;;; +12241;CUNEIFORM SIGN NAGA INVERTED;Lo;0;L;;;;;N;;;;; +12242;CUNEIFORM SIGN NAGA TIMES SHU TENU;Lo;0;L;;;;;N;;;;; +12243;CUNEIFORM SIGN NAGA OPPOSING NAGA;Lo;0;L;;;;;N;;;;; +12244;CUNEIFORM SIGN NAGAR;Lo;0;L;;;;;N;;;;; +12245;CUNEIFORM SIGN NAM NUTILLU;Lo;0;L;;;;;N;;;;; +12246;CUNEIFORM SIGN NAM;Lo;0;L;;;;;N;;;;; +12247;CUNEIFORM SIGN NAM2;Lo;0;L;;;;;N;;;;; +12248;CUNEIFORM SIGN NE;Lo;0;L;;;;;N;;;;; +12249;CUNEIFORM SIGN NE TIMES A;Lo;0;L;;;;;N;;;;; +1224A;CUNEIFORM SIGN NE TIMES UD;Lo;0;L;;;;;N;;;;; +1224B;CUNEIFORM SIGN NE SHESHIG;Lo;0;L;;;;;N;;;;; +1224C;CUNEIFORM SIGN NI;Lo;0;L;;;;;N;;;;; +1224D;CUNEIFORM SIGN NI TIMES E;Lo;0;L;;;;;N;;;;; +1224E;CUNEIFORM SIGN NI2;Lo;0;L;;;;;N;;;;; +1224F;CUNEIFORM SIGN NIM;Lo;0;L;;;;;N;;;;; +12250;CUNEIFORM SIGN NIM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12251;CUNEIFORM SIGN NIM TIMES GAR PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; +12252;CUNEIFORM SIGN NINDA2;Lo;0;L;;;;;N;;;;; +12253;CUNEIFORM SIGN NINDA2 TIMES AN;Lo;0;L;;;;;N;;;;; +12254;CUNEIFORM SIGN NINDA2 TIMES ASH;Lo;0;L;;;;;N;;;;; +12255;CUNEIFORM SIGN NINDA2 TIMES ASH PLUS ASH;Lo;0;L;;;;;N;;;;; +12256;CUNEIFORM SIGN NINDA2 TIMES GUD;Lo;0;L;;;;;N;;;;; +12257;CUNEIFORM SIGN NINDA2 TIMES ME PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; +12258;CUNEIFORM SIGN NINDA2 TIMES NE;Lo;0;L;;;;;N;;;;; +12259;CUNEIFORM SIGN NINDA2 TIMES NUN;Lo;0;L;;;;;N;;;;; +1225A;CUNEIFORM SIGN NINDA2 TIMES SHE;Lo;0;L;;;;;N;;;;; +1225B;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS A AN;Lo;0;L;;;;;N;;;;; +1225C;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH;Lo;0;L;;;;;N;;;;; +1225D;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH PLUS ASH;Lo;0;L;;;;;N;;;;; +1225E;CUNEIFORM SIGN NINDA2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; +1225F;CUNEIFORM SIGN NINDA2 TIMES USH;Lo;0;L;;;;;N;;;;; +12260;CUNEIFORM SIGN NISAG;Lo;0;L;;;;;N;;;;; +12261;CUNEIFORM SIGN NU;Lo;0;L;;;;;N;;;;; +12262;CUNEIFORM SIGN NU11;Lo;0;L;;;;;N;;;;; +12263;CUNEIFORM SIGN NUN;Lo;0;L;;;;;N;;;;; +12264;CUNEIFORM SIGN NUN LAGAR TIMES GAR;Lo;0;L;;;;;N;;;;; +12265;CUNEIFORM SIGN NUN LAGAR TIMES MASH;Lo;0;L;;;;;N;;;;; +12266;CUNEIFORM SIGN NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; +12267;CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; +12268;CUNEIFORM SIGN NUN LAGAR TIMES USH;Lo;0;L;;;;;N;;;;; +12269;CUNEIFORM SIGN NUN TENU;Lo;0;L;;;;;N;;;;; +1226A;CUNEIFORM SIGN NUN OVER NUN;Lo;0;L;;;;;N;;;;; +1226B;CUNEIFORM SIGN NUN CROSSING NUN;Lo;0;L;;;;;N;;;;; +1226C;CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR;Lo;0;L;;;;;N;;;;; +1226D;CUNEIFORM SIGN NUNUZ;Lo;0;L;;;;;N;;;;; +1226E;CUNEIFORM SIGN NUNUZ AB2 TIMES ASHGAB;Lo;0;L;;;;;N;;;;; +1226F;CUNEIFORM SIGN NUNUZ AB2 TIMES BI;Lo;0;L;;;;;N;;;;; +12270;CUNEIFORM SIGN NUNUZ AB2 TIMES DUG;Lo;0;L;;;;;N;;;;; +12271;CUNEIFORM SIGN NUNUZ AB2 TIMES GUD;Lo;0;L;;;;;N;;;;; +12272;CUNEIFORM SIGN NUNUZ AB2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12273;CUNEIFORM SIGN NUNUZ AB2 TIMES KAD3;Lo;0;L;;;;;N;;;;; +12274;CUNEIFORM SIGN NUNUZ AB2 TIMES LA;Lo;0;L;;;;;N;;;;; +12275;CUNEIFORM SIGN NUNUZ AB2 TIMES NE;Lo;0;L;;;;;N;;;;; +12276;CUNEIFORM SIGN NUNUZ AB2 TIMES SILA3;Lo;0;L;;;;;N;;;;; +12277;CUNEIFORM SIGN NUNUZ AB2 TIMES U2;Lo;0;L;;;;;N;;;;; +12278;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; +12279;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI U;Lo;0;L;;;;;N;;;;; +1227A;CUNEIFORM SIGN PA;Lo;0;L;;;;;N;;;;; +1227B;CUNEIFORM SIGN PAD;Lo;0;L;;;;;N;;;;; +1227C;CUNEIFORM SIGN PAN;Lo;0;L;;;;;N;;;;; +1227D;CUNEIFORM SIGN PAP;Lo;0;L;;;;;N;;;;; +1227E;CUNEIFORM SIGN PESH2;Lo;0;L;;;;;N;;;;; +1227F;CUNEIFORM SIGN PI;Lo;0;L;;;;;N;;;;; +12280;CUNEIFORM SIGN PI TIMES A;Lo;0;L;;;;;N;;;;; +12281;CUNEIFORM SIGN PI TIMES AB;Lo;0;L;;;;;N;;;;; +12282;CUNEIFORM SIGN PI TIMES BI;Lo;0;L;;;;;N;;;;; +12283;CUNEIFORM SIGN PI TIMES BU;Lo;0;L;;;;;N;;;;; +12284;CUNEIFORM SIGN PI TIMES E;Lo;0;L;;;;;N;;;;; +12285;CUNEIFORM SIGN PI TIMES I;Lo;0;L;;;;;N;;;;; +12286;CUNEIFORM SIGN PI TIMES IB;Lo;0;L;;;;;N;;;;; +12287;CUNEIFORM SIGN PI TIMES U;Lo;0;L;;;;;N;;;;; +12288;CUNEIFORM SIGN PI TIMES U2;Lo;0;L;;;;;N;;;;; +12289;CUNEIFORM SIGN PI CROSSING PI;Lo;0;L;;;;;N;;;;; +1228A;CUNEIFORM SIGN PIRIG;Lo;0;L;;;;;N;;;;; +1228B;CUNEIFORM SIGN PIRIG TIMES KAL;Lo;0;L;;;;;N;;;;; +1228C;CUNEIFORM SIGN PIRIG TIMES UD;Lo;0;L;;;;;N;;;;; +1228D;CUNEIFORM SIGN PIRIG TIMES ZA;Lo;0;L;;;;;N;;;;; +1228E;CUNEIFORM SIGN PIRIG OPPOSING PIRIG;Lo;0;L;;;;;N;;;;; +1228F;CUNEIFORM SIGN RA;Lo;0;L;;;;;N;;;;; +12290;CUNEIFORM SIGN RAB;Lo;0;L;;;;;N;;;;; +12291;CUNEIFORM SIGN RI;Lo;0;L;;;;;N;;;;; +12292;CUNEIFORM SIGN RU;Lo;0;L;;;;;N;;;;; +12293;CUNEIFORM SIGN SA;Lo;0;L;;;;;N;;;;; +12294;CUNEIFORM SIGN SAG NUTILLU;Lo;0;L;;;;;N;;;;; +12295;CUNEIFORM SIGN SAG;Lo;0;L;;;;;N;;;;; +12296;CUNEIFORM SIGN SAG TIMES A;Lo;0;L;;;;;N;;;;; +12297;CUNEIFORM SIGN SAG TIMES DU;Lo;0;L;;;;;N;;;;; +12298;CUNEIFORM SIGN SAG TIMES DUB;Lo;0;L;;;;;N;;;;; +12299;CUNEIFORM SIGN SAG TIMES HA;Lo;0;L;;;;;N;;;;; +1229A;CUNEIFORM SIGN SAG TIMES KAK;Lo;0;L;;;;;N;;;;; +1229B;CUNEIFORM SIGN SAG TIMES KUR;Lo;0;L;;;;;N;;;;; +1229C;CUNEIFORM SIGN SAG TIMES LUM;Lo;0;L;;;;;N;;;;; +1229D;CUNEIFORM SIGN SAG TIMES MI;Lo;0;L;;;;;N;;;;; +1229E;CUNEIFORM SIGN SAG TIMES NUN;Lo;0;L;;;;;N;;;;; +1229F;CUNEIFORM SIGN SAG TIMES SAL;Lo;0;L;;;;;N;;;;; +122A0;CUNEIFORM SIGN SAG TIMES SHID;Lo;0;L;;;;;N;;;;; +122A1;CUNEIFORM SIGN SAG TIMES TAB;Lo;0;L;;;;;N;;;;; +122A2;CUNEIFORM SIGN SAG TIMES U2;Lo;0;L;;;;;N;;;;; +122A3;CUNEIFORM SIGN SAG TIMES UB;Lo;0;L;;;;;N;;;;; +122A4;CUNEIFORM SIGN SAG TIMES UM;Lo;0;L;;;;;N;;;;; +122A5;CUNEIFORM SIGN SAG TIMES UR;Lo;0;L;;;;;N;;;;; +122A6;CUNEIFORM SIGN SAG TIMES USH;Lo;0;L;;;;;N;;;;; +122A7;CUNEIFORM SIGN SAG OVER SAG;Lo;0;L;;;;;N;;;;; +122A8;CUNEIFORM SIGN SAG GUNU;Lo;0;L;;;;;N;;;;; +122A9;CUNEIFORM SIGN SAL;Lo;0;L;;;;;N;;;;; +122AA;CUNEIFORM SIGN SAL LAGAB TIMES ASH2;Lo;0;L;;;;;N;;;;; +122AB;CUNEIFORM SIGN SANGA2;Lo;0;L;;;;;N;;;;; +122AC;CUNEIFORM SIGN SAR;Lo;0;L;;;;;N;;;;; +122AD;CUNEIFORM SIGN SHA;Lo;0;L;;;;;N;;;;; +122AE;CUNEIFORM SIGN SHA3;Lo;0;L;;;;;N;;;;; +122AF;CUNEIFORM SIGN SHA3 TIMES A;Lo;0;L;;;;;N;;;;; +122B0;CUNEIFORM SIGN SHA3 TIMES BAD;Lo;0;L;;;;;N;;;;; +122B1;CUNEIFORM SIGN SHA3 TIMES GISH;Lo;0;L;;;;;N;;;;; +122B2;CUNEIFORM SIGN SHA3 TIMES NE;Lo;0;L;;;;;N;;;;; +122B3;CUNEIFORM SIGN SHA3 TIMES SHU2;Lo;0;L;;;;;N;;;;; +122B4;CUNEIFORM SIGN SHA3 TIMES TUR;Lo;0;L;;;;;N;;;;; +122B5;CUNEIFORM SIGN SHA3 TIMES U;Lo;0;L;;;;;N;;;;; +122B6;CUNEIFORM SIGN SHA3 TIMES U PLUS A;Lo;0;L;;;;;N;;;;; +122B7;CUNEIFORM SIGN SHA6;Lo;0;L;;;;;N;;;;; +122B8;CUNEIFORM SIGN SHAB6;Lo;0;L;;;;;N;;;;; +122B9;CUNEIFORM SIGN SHAR2;Lo;0;L;;;;;N;;;;; +122BA;CUNEIFORM SIGN SHE;Lo;0;L;;;;;N;;;;; +122BB;CUNEIFORM SIGN SHE HU;Lo;0;L;;;;;N;;;;; +122BC;CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; +122BD;CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR;Lo;0;L;;;;;N;;;;; +122BE;CUNEIFORM SIGN SHEG9;Lo;0;L;;;;;N;;;;; +122BF;CUNEIFORM SIGN SHEN;Lo;0;L;;;;;N;;;;; +122C0;CUNEIFORM SIGN SHESH;Lo;0;L;;;;;N;;;;; +122C1;CUNEIFORM SIGN SHESH2;Lo;0;L;;;;;N;;;;; +122C2;CUNEIFORM SIGN SHESHLAM;Lo;0;L;;;;;N;;;;; +122C3;CUNEIFORM SIGN SHID;Lo;0;L;;;;;N;;;;; +122C4;CUNEIFORM SIGN SHID TIMES A;Lo;0;L;;;;;N;;;;; +122C5;CUNEIFORM SIGN SHID TIMES IM;Lo;0;L;;;;;N;;;;; +122C6;CUNEIFORM SIGN SHIM;Lo;0;L;;;;;N;;;;; +122C7;CUNEIFORM SIGN SHIM TIMES A;Lo;0;L;;;;;N;;;;; +122C8;CUNEIFORM SIGN SHIM TIMES BAL;Lo;0;L;;;;;N;;;;; +122C9;CUNEIFORM SIGN SHIM TIMES BULUG;Lo;0;L;;;;;N;;;;; +122CA;CUNEIFORM SIGN SHIM TIMES DIN;Lo;0;L;;;;;N;;;;; +122CB;CUNEIFORM SIGN SHIM TIMES GAR;Lo;0;L;;;;;N;;;;; +122CC;CUNEIFORM SIGN SHIM TIMES IGI;Lo;0;L;;;;;N;;;;; +122CD;CUNEIFORM SIGN SHIM TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +122CE;CUNEIFORM SIGN SHIM TIMES KUSHU2;Lo;0;L;;;;;N;;;;; +122CF;CUNEIFORM SIGN SHIM TIMES LUL;Lo;0;L;;;;;N;;;;; +122D0;CUNEIFORM SIGN SHIM TIMES MUG;Lo;0;L;;;;;N;;;;; +122D1;CUNEIFORM SIGN SHIM TIMES SAL;Lo;0;L;;;;;N;;;;; +122D2;CUNEIFORM SIGN SHINIG;Lo;0;L;;;;;N;;;;; +122D3;CUNEIFORM SIGN SHIR;Lo;0;L;;;;;N;;;;; +122D4;CUNEIFORM SIGN SHIR TENU;Lo;0;L;;;;;N;;;;; +122D5;CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR;Lo;0;L;;;;;N;;;;; +122D6;CUNEIFORM SIGN SHITA;Lo;0;L;;;;;N;;;;; +122D7;CUNEIFORM SIGN SHU;Lo;0;L;;;;;N;;;;; +122D8;CUNEIFORM SIGN SHU OVER INVERTED SHU;Lo;0;L;;;;;N;;;;; +122D9;CUNEIFORM SIGN SHU2;Lo;0;L;;;;;N;;;;; +122DA;CUNEIFORM SIGN SHUBUR;Lo;0;L;;;;;N;;;;; +122DB;CUNEIFORM SIGN SI;Lo;0;L;;;;;N;;;;; +122DC;CUNEIFORM SIGN SI GUNU;Lo;0;L;;;;;N;;;;; +122DD;CUNEIFORM SIGN SIG;Lo;0;L;;;;;N;;;;; +122DE;CUNEIFORM SIGN SIG4;Lo;0;L;;;;;N;;;;; +122DF;CUNEIFORM SIGN SIG4 OVER SIG4 SHU2;Lo;0;L;;;;;N;;;;; +122E0;CUNEIFORM SIGN SIK2;Lo;0;L;;;;;N;;;;; +122E1;CUNEIFORM SIGN SILA3;Lo;0;L;;;;;N;;;;; +122E2;CUNEIFORM SIGN SU;Lo;0;L;;;;;N;;;;; +122E3;CUNEIFORM SIGN SU OVER SU;Lo;0;L;;;;;N;;;;; +122E4;CUNEIFORM SIGN SUD;Lo;0;L;;;;;N;;;;; +122E5;CUNEIFORM SIGN SUD2;Lo;0;L;;;;;N;;;;; +122E6;CUNEIFORM SIGN SUHUR;Lo;0;L;;;;;N;;;;; +122E7;CUNEIFORM SIGN SUM;Lo;0;L;;;;;N;;;;; +122E8;CUNEIFORM SIGN SUMASH;Lo;0;L;;;;;N;;;;; +122E9;CUNEIFORM SIGN SUR;Lo;0;L;;;;;N;;;;; +122EA;CUNEIFORM SIGN SUR9;Lo;0;L;;;;;N;;;;; +122EB;CUNEIFORM SIGN TA;Lo;0;L;;;;;N;;;;; +122EC;CUNEIFORM SIGN TA ASTERISK;Lo;0;L;;;;;N;;;;; +122ED;CUNEIFORM SIGN TA TIMES HI;Lo;0;L;;;;;N;;;;; +122EE;CUNEIFORM SIGN TA TIMES MI;Lo;0;L;;;;;N;;;;; +122EF;CUNEIFORM SIGN TA GUNU;Lo;0;L;;;;;N;;;;; +122F0;CUNEIFORM SIGN TAB;Lo;0;L;;;;;N;;;;; +122F1;CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH;Lo;0;L;;;;;N;;;;; +122F2;CUNEIFORM SIGN TAB SQUARED;Lo;0;L;;;;;N;;;;; +122F3;CUNEIFORM SIGN TAG;Lo;0;L;;;;;N;;;;; +122F4;CUNEIFORM SIGN TAG TIMES BI;Lo;0;L;;;;;N;;;;; +122F5;CUNEIFORM SIGN TAG TIMES GUD;Lo;0;L;;;;;N;;;;; +122F6;CUNEIFORM SIGN TAG TIMES SHE;Lo;0;L;;;;;N;;;;; +122F7;CUNEIFORM SIGN TAG TIMES SHU;Lo;0;L;;;;;N;;;;; +122F8;CUNEIFORM SIGN TAG TIMES TUG2;Lo;0;L;;;;;N;;;;; +122F9;CUNEIFORM SIGN TAG TIMES UD;Lo;0;L;;;;;N;;;;; +122FA;CUNEIFORM SIGN TAK4;Lo;0;L;;;;;N;;;;; +122FB;CUNEIFORM SIGN TAR;Lo;0;L;;;;;N;;;;; +122FC;CUNEIFORM SIGN TE;Lo;0;L;;;;;N;;;;; +122FD;CUNEIFORM SIGN TE GUNU;Lo;0;L;;;;;N;;;;; +122FE;CUNEIFORM SIGN TI;Lo;0;L;;;;;N;;;;; +122FF;CUNEIFORM SIGN TI TENU;Lo;0;L;;;;;N;;;;; +12300;CUNEIFORM SIGN TIL;Lo;0;L;;;;;N;;;;; +12301;CUNEIFORM SIGN TIR;Lo;0;L;;;;;N;;;;; +12302;CUNEIFORM SIGN TIR TIMES TAK4;Lo;0;L;;;;;N;;;;; +12303;CUNEIFORM SIGN TIR OVER TIR;Lo;0;L;;;;;N;;;;; +12304;CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; +12305;CUNEIFORM SIGN TU;Lo;0;L;;;;;N;;;;; +12306;CUNEIFORM SIGN TUG2;Lo;0;L;;;;;N;;;;; +12307;CUNEIFORM SIGN TUK;Lo;0;L;;;;;N;;;;; +12308;CUNEIFORM SIGN TUM;Lo;0;L;;;;;N;;;;; +12309;CUNEIFORM SIGN TUR;Lo;0;L;;;;;N;;;;; +1230A;CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA;Lo;0;L;;;;;N;;;;; +1230B;CUNEIFORM SIGN U;Lo;0;L;;;;;N;;;;; +1230C;CUNEIFORM SIGN U GUD;Lo;0;L;;;;;N;;;;; +1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;;N;;;;; +1230E;CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR;Lo;0;L;;;;;N;;;;; +1230F;CUNEIFORM SIGN U OVER U SUR OVER SUR;Lo;0;L;;;;;N;;;;; +12310;CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED;Lo;0;L;;;;;N;;;;; +12311;CUNEIFORM SIGN U2;Lo;0;L;;;;;N;;;;; +12312;CUNEIFORM SIGN UB;Lo;0;L;;;;;N;;;;; +12313;CUNEIFORM SIGN UD;Lo;0;L;;;;;N;;;;; +12314;CUNEIFORM SIGN UD KUSHU2;Lo;0;L;;;;;N;;;;; +12315;CUNEIFORM SIGN UD TIMES BAD;Lo;0;L;;;;;N;;;;; +12316;CUNEIFORM SIGN UD TIMES MI;Lo;0;L;;;;;N;;;;; +12317;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; +12318;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU;Lo;0;L;;;;;N;;;;; +12319;CUNEIFORM SIGN UD GUNU;Lo;0;L;;;;;N;;;;; +1231A;CUNEIFORM SIGN UD SHESHIG;Lo;0;L;;;;;N;;;;; +1231B;CUNEIFORM SIGN UD SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; +1231C;CUNEIFORM SIGN UDUG;Lo;0;L;;;;;N;;;;; +1231D;CUNEIFORM SIGN UM;Lo;0;L;;;;;N;;;;; +1231E;CUNEIFORM SIGN UM TIMES LAGAB;Lo;0;L;;;;;N;;;;; +1231F;CUNEIFORM SIGN UM TIMES ME PLUS DA;Lo;0;L;;;;;N;;;;; +12320;CUNEIFORM SIGN UM TIMES SHA3;Lo;0;L;;;;;N;;;;; +12321;CUNEIFORM SIGN UM TIMES U;Lo;0;L;;;;;N;;;;; +12322;CUNEIFORM SIGN UMBIN;Lo;0;L;;;;;N;;;;; +12323;CUNEIFORM SIGN UMUM;Lo;0;L;;;;;N;;;;; +12324;CUNEIFORM SIGN UMUM TIMES KASKAL;Lo;0;L;;;;;N;;;;; +12325;CUNEIFORM SIGN UMUM TIMES PA;Lo;0;L;;;;;N;;;;; +12326;CUNEIFORM SIGN UN;Lo;0;L;;;;;N;;;;; +12327;CUNEIFORM SIGN UN GUNU;Lo;0;L;;;;;N;;;;; +12328;CUNEIFORM SIGN UR;Lo;0;L;;;;;N;;;;; +12329;CUNEIFORM SIGN UR CROSSING UR;Lo;0;L;;;;;N;;;;; +1232A;CUNEIFORM SIGN UR SHESHIG;Lo;0;L;;;;;N;;;;; +1232B;CUNEIFORM SIGN UR2;Lo;0;L;;;;;N;;;;; +1232C;CUNEIFORM SIGN UR2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; +1232D;CUNEIFORM SIGN UR2 TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; +1232E;CUNEIFORM SIGN UR2 TIMES AL;Lo;0;L;;;;;N;;;;; +1232F;CUNEIFORM SIGN UR2 TIMES HA;Lo;0;L;;;;;N;;;;; +12330;CUNEIFORM SIGN UR2 TIMES NUN;Lo;0;L;;;;;N;;;;; +12331;CUNEIFORM SIGN UR2 TIMES U2;Lo;0;L;;;;;N;;;;; +12332;CUNEIFORM SIGN UR2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; +12333;CUNEIFORM SIGN UR2 TIMES U2 PLUS BI;Lo;0;L;;;;;N;;;;; +12334;CUNEIFORM SIGN UR4;Lo;0;L;;;;;N;;;;; +12335;CUNEIFORM SIGN URI;Lo;0;L;;;;;N;;;;; +12336;CUNEIFORM SIGN URI3;Lo;0;L;;;;;N;;;;; +12337;CUNEIFORM SIGN URU;Lo;0;L;;;;;N;;;;; +12338;CUNEIFORM SIGN URU TIMES A;Lo;0;L;;;;;N;;;;; +12339;CUNEIFORM SIGN URU TIMES ASHGAB;Lo;0;L;;;;;N;;;;; +1233A;CUNEIFORM SIGN URU TIMES BAR;Lo;0;L;;;;;N;;;;; +1233B;CUNEIFORM SIGN URU TIMES DUN;Lo;0;L;;;;;N;;;;; +1233C;CUNEIFORM SIGN URU TIMES GA;Lo;0;L;;;;;N;;;;; +1233D;CUNEIFORM SIGN URU TIMES GAL;Lo;0;L;;;;;N;;;;; +1233E;CUNEIFORM SIGN URU TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1233F;CUNEIFORM SIGN URU TIMES GAR;Lo;0;L;;;;;N;;;;; +12340;CUNEIFORM SIGN URU TIMES GU;Lo;0;L;;;;;N;;;;; +12341;CUNEIFORM SIGN URU TIMES HA;Lo;0;L;;;;;N;;;;; +12342;CUNEIFORM SIGN URU TIMES IGI;Lo;0;L;;;;;N;;;;; +12343;CUNEIFORM SIGN URU TIMES IM;Lo;0;L;;;;;N;;;;; +12344;CUNEIFORM SIGN URU TIMES ISH;Lo;0;L;;;;;N;;;;; +12345;CUNEIFORM SIGN URU TIMES KI;Lo;0;L;;;;;N;;;;; +12346;CUNEIFORM SIGN URU TIMES LUM;Lo;0;L;;;;;N;;;;; +12347;CUNEIFORM SIGN URU TIMES MIN;Lo;0;L;;;;;N;;;;; +12348;CUNEIFORM SIGN URU TIMES PA;Lo;0;L;;;;;N;;;;; +12349;CUNEIFORM SIGN URU TIMES SHE;Lo;0;L;;;;;N;;;;; +1234A;CUNEIFORM SIGN URU TIMES SIG4;Lo;0;L;;;;;N;;;;; +1234B;CUNEIFORM SIGN URU TIMES TU;Lo;0;L;;;;;N;;;;; +1234C;CUNEIFORM SIGN URU TIMES U PLUS GUD;Lo;0;L;;;;;N;;;;; +1234D;CUNEIFORM SIGN URU TIMES UD;Lo;0;L;;;;;N;;;;; +1234E;CUNEIFORM SIGN URU TIMES URUDA;Lo;0;L;;;;;N;;;;; +1234F;CUNEIFORM SIGN URUDA;Lo;0;L;;;;;N;;;;; +12350;CUNEIFORM SIGN URUDA TIMES U;Lo;0;L;;;;;N;;;;; +12351;CUNEIFORM SIGN USH;Lo;0;L;;;;;N;;;;; +12352;CUNEIFORM SIGN USH TIMES A;Lo;0;L;;;;;N;;;;; +12353;CUNEIFORM SIGN USH TIMES KU;Lo;0;L;;;;;N;;;;; +12354;CUNEIFORM SIGN USH TIMES KUR;Lo;0;L;;;;;N;;;;; +12355;CUNEIFORM SIGN USH TIMES TAK4;Lo;0;L;;;;;N;;;;; +12356;CUNEIFORM SIGN USHX;Lo;0;L;;;;;N;;;;; +12357;CUNEIFORM SIGN USH2;Lo;0;L;;;;;N;;;;; +12358;CUNEIFORM SIGN USHUMX;Lo;0;L;;;;;N;;;;; +12359;CUNEIFORM SIGN UTUKI;Lo;0;L;;;;;N;;;;; +1235A;CUNEIFORM SIGN UZ3;Lo;0;L;;;;;N;;;;; +1235B;CUNEIFORM SIGN UZ3 TIMES KASKAL;Lo;0;L;;;;;N;;;;; +1235C;CUNEIFORM SIGN UZU;Lo;0;L;;;;;N;;;;; +1235D;CUNEIFORM SIGN ZA;Lo;0;L;;;;;N;;;;; +1235E;CUNEIFORM SIGN ZA TENU;Lo;0;L;;;;;N;;;;; +1235F;CUNEIFORM SIGN ZA SQUARED TIMES KUR;Lo;0;L;;;;;N;;;;; +12360;CUNEIFORM SIGN ZAG;Lo;0;L;;;;;N;;;;; +12361;CUNEIFORM SIGN ZAMX;Lo;0;L;;;;;N;;;;; +12362;CUNEIFORM SIGN ZE2;Lo;0;L;;;;;N;;;;; +12363;CUNEIFORM SIGN ZI;Lo;0;L;;;;;N;;;;; +12364;CUNEIFORM SIGN ZI OVER ZI;Lo;0;L;;;;;N;;;;; +12365;CUNEIFORM SIGN ZI3;Lo;0;L;;;;;N;;;;; +12366;CUNEIFORM SIGN ZIB;Lo;0;L;;;;;N;;;;; +12367;CUNEIFORM SIGN ZIB KABA TENU;Lo;0;L;;;;;N;;;;; +12368;CUNEIFORM SIGN ZIG;Lo;0;L;;;;;N;;;;; +12369;CUNEIFORM SIGN ZIZ2;Lo;0;L;;;;;N;;;;; +1236A;CUNEIFORM SIGN ZU;Lo;0;L;;;;;N;;;;; +1236B;CUNEIFORM SIGN ZU5;Lo;0;L;;;;;N;;;;; +1236C;CUNEIFORM SIGN ZU5 TIMES A;Lo;0;L;;;;;N;;;;; +1236D;CUNEIFORM SIGN ZUBUR;Lo;0;L;;;;;N;;;;; +1236E;CUNEIFORM SIGN ZUM;Lo;0;L;;;;;N;;;;; +1236F;CUNEIFORM SIGN KAP ELAMITE;Lo;0;L;;;;;N;;;;; +12370;CUNEIFORM SIGN AB TIMES NUN;Lo;0;L;;;;;N;;;;; +12371;CUNEIFORM SIGN AB2 TIMES A;Lo;0;L;;;;;N;;;;; +12372;CUNEIFORM SIGN AMAR TIMES KUG;Lo;0;L;;;;;N;;;;; +12373;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS MASH;Lo;0;L;;;;;N;;;;; +12374;CUNEIFORM SIGN DAG3;Lo;0;L;;;;;N;;;;; +12375;CUNEIFORM SIGN DISH PLUS SHU;Lo;0;L;;;;;N;;;;; +12376;CUNEIFORM SIGN DUB TIMES SHE;Lo;0;L;;;;;N;;;;; +12377;CUNEIFORM SIGN EZEN TIMES GUD;Lo;0;L;;;;;N;;;;; +12378;CUNEIFORM SIGN EZEN TIMES SHE;Lo;0;L;;;;;N;;;;; +12379;CUNEIFORM SIGN GA2 TIMES AN PLUS KAK PLUS A;Lo;0;L;;;;;N;;;;; +1237A;CUNEIFORM SIGN GA2 TIMES ASH2;Lo;0;L;;;;;N;;;;; +1237B;CUNEIFORM SIGN GE22;Lo;0;L;;;;;N;;;;; +1237C;CUNEIFORM SIGN GIG;Lo;0;L;;;;;N;;;;; +1237D;CUNEIFORM SIGN HUSH;Lo;0;L;;;;;N;;;;; +1237E;CUNEIFORM SIGN KA TIMES ANSHE;Lo;0;L;;;;;N;;;;; +1237F;CUNEIFORM SIGN KA TIMES ASH3;Lo;0;L;;;;;N;;;;; +12380;CUNEIFORM SIGN KA TIMES GISH;Lo;0;L;;;;;N;;;;; +12381;CUNEIFORM SIGN KA TIMES GUD;Lo;0;L;;;;;N;;;;; +12382;CUNEIFORM SIGN KA TIMES HI TIMES ASH2;Lo;0;L;;;;;N;;;;; +12383;CUNEIFORM SIGN KA TIMES LUM;Lo;0;L;;;;;N;;;;; +12384;CUNEIFORM SIGN KA TIMES PA;Lo;0;L;;;;;N;;;;; +12385;CUNEIFORM SIGN KA TIMES SHUL;Lo;0;L;;;;;N;;;;; +12386;CUNEIFORM SIGN KA TIMES TU;Lo;0;L;;;;;N;;;;; +12387;CUNEIFORM SIGN KA TIMES UR2;Lo;0;L;;;;;N;;;;; +12388;CUNEIFORM SIGN LAGAB TIMES GI;Lo;0;L;;;;;N;;;;; +12389;CUNEIFORM SIGN LU2 SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; +1238A;CUNEIFORM SIGN LU2 TIMES ESH2 PLUS LAL;Lo;0;L;;;;;N;;;;; +1238B;CUNEIFORM SIGN LU2 TIMES SHU;Lo;0;L;;;;;N;;;;; +1238C;CUNEIFORM SIGN MESH;Lo;0;L;;;;;N;;;;; +1238D;CUNEIFORM SIGN MUSH3 TIMES ZA;Lo;0;L;;;;;N;;;;; +1238E;CUNEIFORM SIGN NA4;Lo;0;L;;;;;N;;;;; +1238F;CUNEIFORM SIGN NIN;Lo;0;L;;;;;N;;;;; +12390;CUNEIFORM SIGN NIN9;Lo;0;L;;;;;N;;;;; +12391;CUNEIFORM SIGN NINDA2 TIMES BAL;Lo;0;L;;;;;N;;;;; +12392;CUNEIFORM SIGN NINDA2 TIMES GI;Lo;0;L;;;;;N;;;;; +12393;CUNEIFORM SIGN NU11 ROTATED NINETY DEGREES;Lo;0;L;;;;;N;;;;; +12394;CUNEIFORM SIGN PESH2 ASTERISK;Lo;0;L;;;;;N;;;;; +12395;CUNEIFORM SIGN PIR2;Lo;0;L;;;;;N;;;;; +12396;CUNEIFORM SIGN SAG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12397;CUNEIFORM SIGN TI2;Lo;0;L;;;;;N;;;;; +12398;CUNEIFORM SIGN UM TIMES ME;Lo;0;L;;;;;N;;;;; +12399;CUNEIFORM SIGN U U;Lo;0;L;;;;;N;;;;; +12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;; +12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;; +12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;; +12403;CUNEIFORM NUMERIC SIGN FIVE ASH;Nl;0;L;;;;5;N;;;;; +12404;CUNEIFORM NUMERIC SIGN SIX ASH;Nl;0;L;;;;6;N;;;;; +12405;CUNEIFORM NUMERIC SIGN SEVEN ASH;Nl;0;L;;;;7;N;;;;; +12406;CUNEIFORM NUMERIC SIGN EIGHT ASH;Nl;0;L;;;;8;N;;;;; +12407;CUNEIFORM NUMERIC SIGN NINE ASH;Nl;0;L;;;;9;N;;;;; +12408;CUNEIFORM NUMERIC SIGN THREE DISH;Nl;0;L;;;;3;N;;;;; +12409;CUNEIFORM NUMERIC SIGN FOUR DISH;Nl;0;L;;;;4;N;;;;; +1240A;CUNEIFORM NUMERIC SIGN FIVE DISH;Nl;0;L;;;;5;N;;;;; +1240B;CUNEIFORM NUMERIC SIGN SIX DISH;Nl;0;L;;;;6;N;;;;; +1240C;CUNEIFORM NUMERIC SIGN SEVEN DISH;Nl;0;L;;;;7;N;;;;; +1240D;CUNEIFORM NUMERIC SIGN EIGHT DISH;Nl;0;L;;;;8;N;;;;; +1240E;CUNEIFORM NUMERIC SIGN NINE DISH;Nl;0;L;;;;9;N;;;;; +1240F;CUNEIFORM NUMERIC SIGN FOUR U;Nl;0;L;;;;4;N;;;;; +12410;CUNEIFORM NUMERIC SIGN FIVE U;Nl;0;L;;;;5;N;;;;; +12411;CUNEIFORM NUMERIC SIGN SIX U;Nl;0;L;;;;6;N;;;;; +12412;CUNEIFORM NUMERIC SIGN SEVEN U;Nl;0;L;;;;7;N;;;;; +12413;CUNEIFORM NUMERIC SIGN EIGHT U;Nl;0;L;;;;8;N;;;;; +12414;CUNEIFORM NUMERIC SIGN NINE U;Nl;0;L;;;;9;N;;;;; +12415;CUNEIFORM NUMERIC SIGN ONE GESH2;Nl;0;L;;;;1;N;;;;; +12416;CUNEIFORM NUMERIC SIGN TWO GESH2;Nl;0;L;;;;2;N;;;;; +12417;CUNEIFORM NUMERIC SIGN THREE GESH2;Nl;0;L;;;;3;N;;;;; +12418;CUNEIFORM NUMERIC SIGN FOUR GESH2;Nl;0;L;;;;4;N;;;;; +12419;CUNEIFORM NUMERIC SIGN FIVE GESH2;Nl;0;L;;;;5;N;;;;; +1241A;CUNEIFORM NUMERIC SIGN SIX GESH2;Nl;0;L;;;;6;N;;;;; +1241B;CUNEIFORM NUMERIC SIGN SEVEN GESH2;Nl;0;L;;;;7;N;;;;; +1241C;CUNEIFORM NUMERIC SIGN EIGHT GESH2;Nl;0;L;;;;8;N;;;;; +1241D;CUNEIFORM NUMERIC SIGN NINE GESH2;Nl;0;L;;;;9;N;;;;; +1241E;CUNEIFORM NUMERIC SIGN ONE GESHU;Nl;0;L;;;;1;N;;;;; +1241F;CUNEIFORM NUMERIC SIGN TWO GESHU;Nl;0;L;;;;2;N;;;;; +12420;CUNEIFORM NUMERIC SIGN THREE GESHU;Nl;0;L;;;;3;N;;;;; +12421;CUNEIFORM NUMERIC SIGN FOUR GESHU;Nl;0;L;;;;4;N;;;;; +12422;CUNEIFORM NUMERIC SIGN FIVE GESHU;Nl;0;L;;;;5;N;;;;; +12423;CUNEIFORM NUMERIC SIGN TWO SHAR2;Nl;0;L;;;;2;N;;;;; +12424;CUNEIFORM NUMERIC SIGN THREE SHAR2;Nl;0;L;;;;3;N;;;;; +12425;CUNEIFORM NUMERIC SIGN THREE SHAR2 VARIANT FORM;Nl;0;L;;;;3;N;;;;; +12426;CUNEIFORM NUMERIC SIGN FOUR SHAR2;Nl;0;L;;;;4;N;;;;; +12427;CUNEIFORM NUMERIC SIGN FIVE SHAR2;Nl;0;L;;;;5;N;;;;; +12428;CUNEIFORM NUMERIC SIGN SIX SHAR2;Nl;0;L;;;;6;N;;;;; +12429;CUNEIFORM NUMERIC SIGN SEVEN SHAR2;Nl;0;L;;;;7;N;;;;; +1242A;CUNEIFORM NUMERIC SIGN EIGHT SHAR2;Nl;0;L;;;;8;N;;;;; +1242B;CUNEIFORM NUMERIC SIGN NINE SHAR2;Nl;0;L;;;;9;N;;;;; +1242C;CUNEIFORM NUMERIC SIGN ONE SHARU;Nl;0;L;;;;1;N;;;;; +1242D;CUNEIFORM NUMERIC SIGN TWO SHARU;Nl;0;L;;;;2;N;;;;; +1242E;CUNEIFORM NUMERIC SIGN THREE SHARU;Nl;0;L;;;;3;N;;;;; +1242F;CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM;Nl;0;L;;;;3;N;;;;; +12430;CUNEIFORM NUMERIC SIGN FOUR SHARU;Nl;0;L;;;;4;N;;;;; +12431;CUNEIFORM NUMERIC SIGN FIVE SHARU;Nl;0;L;;;;5;N;;;;; +12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;216000;N;;;;; +12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;432000;N;;;;; +12434;CUNEIFORM NUMERIC SIGN ONE BURU;Nl;0;L;;;;1;N;;;;; +12435;CUNEIFORM NUMERIC SIGN TWO BURU;Nl;0;L;;;;2;N;;;;; +12436;CUNEIFORM NUMERIC SIGN THREE BURU;Nl;0;L;;;;3;N;;;;; +12437;CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM;Nl;0;L;;;;3;N;;;;; +12438;CUNEIFORM NUMERIC SIGN FOUR BURU;Nl;0;L;;;;4;N;;;;; +12439;CUNEIFORM NUMERIC SIGN FIVE BURU;Nl;0;L;;;;5;N;;;;; +1243A;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH16;Nl;0;L;;;;3;N;;;;; +1243B;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH21;Nl;0;L;;;;3;N;;;;; +1243C;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU;Nl;0;L;;;;4;N;;;;; +1243D;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU4;Nl;0;L;;;;4;N;;;;; +1243E;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A;Nl;0;L;;;;4;N;;;;; +1243F;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B;Nl;0;L;;;;4;N;;;;; +12440;CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH9;Nl;0;L;;;;6;N;;;;; +12441;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN3;Nl;0;L;;;;7;N;;;;; +12442;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A;Nl;0;L;;;;7;N;;;;; +12443;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B;Nl;0;L;;;;7;N;;;;; +12444;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU;Nl;0;L;;;;8;N;;;;; +12445;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU3;Nl;0;L;;;;8;N;;;;; +12446;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU;Nl;0;L;;;;9;N;;;;; +12447;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU3;Nl;0;L;;;;9;N;;;;; +12448;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU4;Nl;0;L;;;;9;N;;;;; +12449;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A;Nl;0;L;;;;9;N;;;;; +1244A;CUNEIFORM NUMERIC SIGN TWO ASH TENU;Nl;0;L;;;;2;N;;;;; +1244B;CUNEIFORM NUMERIC SIGN THREE ASH TENU;Nl;0;L;;;;3;N;;;;; +1244C;CUNEIFORM NUMERIC SIGN FOUR ASH TENU;Nl;0;L;;;;4;N;;;;; +1244D;CUNEIFORM NUMERIC SIGN FIVE ASH TENU;Nl;0;L;;;;5;N;;;;; +1244E;CUNEIFORM NUMERIC SIGN SIX ASH TENU;Nl;0;L;;;;6;N;;;;; +1244F;CUNEIFORM NUMERIC SIGN ONE BAN2;Nl;0;L;;;;1;N;;;;; +12450;CUNEIFORM NUMERIC SIGN TWO BAN2;Nl;0;L;;;;2;N;;;;; +12451;CUNEIFORM NUMERIC SIGN THREE BAN2;Nl;0;L;;;;3;N;;;;; +12452;CUNEIFORM NUMERIC SIGN FOUR BAN2;Nl;0;L;;;;4;N;;;;; +12453;CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM;Nl;0;L;;;;4;N;;;;; +12454;CUNEIFORM NUMERIC SIGN FIVE BAN2;Nl;0;L;;;;5;N;;;;; +12455;CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM;Nl;0;L;;;;5;N;;;;; +12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;2;N;;;;; +12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;3;N;;;;; +12458;CUNEIFORM NUMERIC SIGN ONE ESHE3;Nl;0;L;;;;1;N;;;;; +12459;CUNEIFORM NUMERIC SIGN TWO ESHE3;Nl;0;L;;;;2;N;;;;; +1245A;CUNEIFORM NUMERIC SIGN ONE THIRD DISH;Nl;0;L;;;;1/3;N;;;;; +1245B;CUNEIFORM NUMERIC SIGN TWO THIRDS DISH;Nl;0;L;;;;2/3;N;;;;; +1245C;CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH;Nl;0;L;;;;5/6;N;;;;; +1245D;CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A;Nl;0;L;;;;1/3;N;;;;; +1245E;CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A;Nl;0;L;;;;2/3;N;;;;; +1245F;CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH;Nl;0;L;;;;1/8;N;;;;; +12460;CUNEIFORM NUMERIC SIGN ONE QUARTER ASH;Nl;0;L;;;;1/4;N;;;;; +12461;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH;Nl;0;L;;;;1/6;N;;;;; +12462;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER;Nl;0;L;;;;1/4;N;;;;; +12463;CUNEIFORM NUMERIC SIGN ONE QUARTER GUR;Nl;0;L;;;;1/4;N;;;;; +12464;CUNEIFORM NUMERIC SIGN ONE HALF GUR;Nl;0;L;;;;1/2;N;;;;; +12465;CUNEIFORM NUMERIC SIGN ELAMITE ONE THIRD;Nl;0;L;;;;1/3;N;;;;; +12466;CUNEIFORM NUMERIC SIGN ELAMITE TWO THIRDS;Nl;0;L;;;;2/3;N;;;;; +12467;CUNEIFORM NUMERIC SIGN ELAMITE FORTY;Nl;0;L;;;;40;N;;;;; +12468;CUNEIFORM NUMERIC SIGN ELAMITE FIFTY;Nl;0;L;;;;50;N;;;;; +12469;CUNEIFORM NUMERIC SIGN FOUR U VARIANT FORM;Nl;0;L;;;;4;N;;;;; +1246A;CUNEIFORM NUMERIC SIGN FIVE U VARIANT FORM;Nl;0;L;;;;5;N;;;;; +1246B;CUNEIFORM NUMERIC SIGN SIX U VARIANT FORM;Nl;0;L;;;;6;N;;;;; +1246C;CUNEIFORM NUMERIC SIGN SEVEN U VARIANT FORM;Nl;0;L;;;;7;N;;;;; +1246D;CUNEIFORM NUMERIC SIGN EIGHT U VARIANT FORM;Nl;0;L;;;;8;N;;;;; +1246E;CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM;Nl;0;L;;;;9;N;;;;; +12470;CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; +12471;CUNEIFORM PUNCTUATION SIGN VERTICAL COLON;Po;0;L;;;;;N;;;;; +12472;CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON;Po;0;L;;;;;N;;;;; +12473;CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON;Po;0;L;;;;;N;;;;; +12474;CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON;Po;0;L;;;;;N;;;;; +12480;CUNEIFORM SIGN AB TIMES NUN TENU;Lo;0;L;;;;;N;;;;; +12481;CUNEIFORM SIGN AB TIMES SHU2;Lo;0;L;;;;;N;;;;; +12482;CUNEIFORM SIGN AD TIMES ESH2;Lo;0;L;;;;;N;;;;; +12483;CUNEIFORM SIGN BAD TIMES DISH TENU;Lo;0;L;;;;;N;;;;; +12484;CUNEIFORM SIGN BAHAR2 TIMES AB2;Lo;0;L;;;;;N;;;;; +12485;CUNEIFORM SIGN BAHAR2 TIMES NI;Lo;0;L;;;;;N;;;;; +12486;CUNEIFORM SIGN BAHAR2 TIMES ZA;Lo;0;L;;;;;N;;;;; +12487;CUNEIFORM SIGN BU OVER BU TIMES NA2;Lo;0;L;;;;;N;;;;; +12488;CUNEIFORM SIGN DA TIMES TAK4;Lo;0;L;;;;;N;;;;; +12489;CUNEIFORM SIGN DAG TIMES KUR;Lo;0;L;;;;;N;;;;; +1248A;CUNEIFORM SIGN DIM TIMES IGI;Lo;0;L;;;;;N;;;;; +1248B;CUNEIFORM SIGN DIM TIMES U U U;Lo;0;L;;;;;N;;;;; +1248C;CUNEIFORM SIGN DIM2 TIMES UD;Lo;0;L;;;;;N;;;;; +1248D;CUNEIFORM SIGN DUG TIMES ANSHE;Lo;0;L;;;;;N;;;;; +1248E;CUNEIFORM SIGN DUG TIMES ASH;Lo;0;L;;;;;N;;;;; +1248F;CUNEIFORM SIGN DUG TIMES ASH AT LEFT;Lo;0;L;;;;;N;;;;; +12490;CUNEIFORM SIGN DUG TIMES DIN;Lo;0;L;;;;;N;;;;; +12491;CUNEIFORM SIGN DUG TIMES DUN;Lo;0;L;;;;;N;;;;; +12492;CUNEIFORM SIGN DUG TIMES ERIN2;Lo;0;L;;;;;N;;;;; +12493;CUNEIFORM SIGN DUG TIMES GA;Lo;0;L;;;;;N;;;;; +12494;CUNEIFORM SIGN DUG TIMES GI;Lo;0;L;;;;;N;;;;; +12495;CUNEIFORM SIGN DUG TIMES GIR2 GUNU;Lo;0;L;;;;;N;;;;; +12496;CUNEIFORM SIGN DUG TIMES GISH;Lo;0;L;;;;;N;;;;; +12497;CUNEIFORM SIGN DUG TIMES HA;Lo;0;L;;;;;N;;;;; +12498;CUNEIFORM SIGN DUG TIMES HI;Lo;0;L;;;;;N;;;;; +12499;CUNEIFORM SIGN DUG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +1249A;CUNEIFORM SIGN DUG TIMES KASKAL;Lo;0;L;;;;;N;;;;; +1249B;CUNEIFORM SIGN DUG TIMES KUR;Lo;0;L;;;;;N;;;;; +1249C;CUNEIFORM SIGN DUG TIMES KUSHU2;Lo;0;L;;;;;N;;;;; +1249D;CUNEIFORM SIGN DUG TIMES KUSHU2 PLUS KASKAL;Lo;0;L;;;;;N;;;;; +1249E;CUNEIFORM SIGN DUG TIMES LAK-020;Lo;0;L;;;;;N;;;;; +1249F;CUNEIFORM SIGN DUG TIMES LAM;Lo;0;L;;;;;N;;;;; +124A0;CUNEIFORM SIGN DUG TIMES LAM TIMES KUR;Lo;0;L;;;;;N;;;;; +124A1;CUNEIFORM SIGN DUG TIMES LUH PLUS GISH;Lo;0;L;;;;;N;;;;; +124A2;CUNEIFORM SIGN DUG TIMES MASH;Lo;0;L;;;;;N;;;;; +124A3;CUNEIFORM SIGN DUG TIMES MES;Lo;0;L;;;;;N;;;;; +124A4;CUNEIFORM SIGN DUG TIMES MI;Lo;0;L;;;;;N;;;;; +124A5;CUNEIFORM SIGN DUG TIMES NI;Lo;0;L;;;;;N;;;;; +124A6;CUNEIFORM SIGN DUG TIMES PI;Lo;0;L;;;;;N;;;;; +124A7;CUNEIFORM SIGN DUG TIMES SHE;Lo;0;L;;;;;N;;;;; +124A8;CUNEIFORM SIGN DUG TIMES SI GUNU;Lo;0;L;;;;;N;;;;; +124A9;CUNEIFORM SIGN E2 TIMES KUR;Lo;0;L;;;;;N;;;;; +124AA;CUNEIFORM SIGN E2 TIMES PAP;Lo;0;L;;;;;N;;;;; +124AB;CUNEIFORM SIGN ERIN2 X;Lo;0;L;;;;;N;;;;; +124AC;CUNEIFORM SIGN ESH2 CROSSING ESH2;Lo;0;L;;;;;N;;;;; +124AD;CUNEIFORM SIGN EZEN SHESHIG TIMES ASH;Lo;0;L;;;;;N;;;;; +124AE;CUNEIFORM SIGN EZEN SHESHIG TIMES HI;Lo;0;L;;;;;N;;;;; +124AF;CUNEIFORM SIGN EZEN SHESHIG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +124B0;CUNEIFORM SIGN EZEN SHESHIG TIMES LA;Lo;0;L;;;;;N;;;;; +124B1;CUNEIFORM SIGN EZEN SHESHIG TIMES LAL;Lo;0;L;;;;;N;;;;; +124B2;CUNEIFORM SIGN EZEN SHESHIG TIMES ME;Lo;0;L;;;;;N;;;;; +124B3;CUNEIFORM SIGN EZEN SHESHIG TIMES MES;Lo;0;L;;;;;N;;;;; +124B4;CUNEIFORM SIGN EZEN SHESHIG TIMES SU;Lo;0;L;;;;;N;;;;; +124B5;CUNEIFORM SIGN EZEN TIMES SU;Lo;0;L;;;;;N;;;;; +124B6;CUNEIFORM SIGN GA2 TIMES BAHAR2;Lo;0;L;;;;;N;;;;; +124B7;CUNEIFORM SIGN GA2 TIMES DIM GUNU;Lo;0;L;;;;;N;;;;; +124B8;CUNEIFORM SIGN GA2 TIMES DUG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +124B9;CUNEIFORM SIGN GA2 TIMES DUG TIMES KASKAL;Lo;0;L;;;;;N;;;;; +124BA;CUNEIFORM SIGN GA2 TIMES EREN;Lo;0;L;;;;;N;;;;; +124BB;CUNEIFORM SIGN GA2 TIMES GA;Lo;0;L;;;;;N;;;;; +124BC;CUNEIFORM SIGN GA2 TIMES GAR PLUS DI;Lo;0;L;;;;;N;;;;; +124BD;CUNEIFORM SIGN GA2 TIMES GAR PLUS NE;Lo;0;L;;;;;N;;;;; +124BE;CUNEIFORM SIGN GA2 TIMES HA PLUS A;Lo;0;L;;;;;N;;;;; +124BF;CUNEIFORM SIGN GA2 TIMES KUSHU2 PLUS KASKAL;Lo;0;L;;;;;N;;;;; +124C0;CUNEIFORM SIGN GA2 TIMES LAM;Lo;0;L;;;;;N;;;;; +124C1;CUNEIFORM SIGN GA2 TIMES LAM TIMES KUR;Lo;0;L;;;;;N;;;;; +124C2;CUNEIFORM SIGN GA2 TIMES LUH;Lo;0;L;;;;;N;;;;; +124C3;CUNEIFORM SIGN GA2 TIMES MUSH;Lo;0;L;;;;;N;;;;; +124C4;CUNEIFORM SIGN GA2 TIMES NE;Lo;0;L;;;;;N;;;;; +124C5;CUNEIFORM SIGN GA2 TIMES NE PLUS E2;Lo;0;L;;;;;N;;;;; +124C6;CUNEIFORM SIGN GA2 TIMES NE PLUS GI;Lo;0;L;;;;;N;;;;; +124C7;CUNEIFORM SIGN GA2 TIMES SHIM;Lo;0;L;;;;;N;;;;; +124C8;CUNEIFORM SIGN GA2 TIMES ZIZ2;Lo;0;L;;;;;N;;;;; +124C9;CUNEIFORM SIGN GABA ROTATED NINETY DEGREES;Lo;0;L;;;;;N;;;;; +124CA;CUNEIFORM SIGN GESHTIN TIMES U;Lo;0;L;;;;;N;;;;; +124CB;CUNEIFORM SIGN GISH TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; +124CC;CUNEIFORM SIGN GU2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +124CD;CUNEIFORM SIGN GUD PLUS GISH TIMES TAK4;Lo;0;L;;;;;N;;;;; +124CE;CUNEIFORM SIGN HA TENU GUNU;Lo;0;L;;;;;N;;;;; +124CF;CUNEIFORM SIGN HI TIMES ASH OVER HI TIMES ASH;Lo;0;L;;;;;N;;;;; +124D0;CUNEIFORM SIGN KA TIMES BU;Lo;0;L;;;;;N;;;;; +124D1;CUNEIFORM SIGN KA TIMES KA;Lo;0;L;;;;;N;;;;; +124D2;CUNEIFORM SIGN KA TIMES U U U;Lo;0;L;;;;;N;;;;; +124D3;CUNEIFORM SIGN KA TIMES UR;Lo;0;L;;;;;N;;;;; +124D4;CUNEIFORM SIGN LAGAB TIMES ZU OVER ZU;Lo;0;L;;;;;N;;;;; +124D5;CUNEIFORM SIGN LAK-003;Lo;0;L;;;;;N;;;;; +124D6;CUNEIFORM SIGN LAK-021;Lo;0;L;;;;;N;;;;; +124D7;CUNEIFORM SIGN LAK-025;Lo;0;L;;;;;N;;;;; +124D8;CUNEIFORM SIGN LAK-030;Lo;0;L;;;;;N;;;;; +124D9;CUNEIFORM SIGN LAK-050;Lo;0;L;;;;;N;;;;; +124DA;CUNEIFORM SIGN LAK-051;Lo;0;L;;;;;N;;;;; +124DB;CUNEIFORM SIGN LAK-062;Lo;0;L;;;;;N;;;;; +124DC;CUNEIFORM SIGN LAK-079 OVER LAK-079 GUNU;Lo;0;L;;;;;N;;;;; +124DD;CUNEIFORM SIGN LAK-080;Lo;0;L;;;;;N;;;;; +124DE;CUNEIFORM SIGN LAK-081 OVER LAK-081;Lo;0;L;;;;;N;;;;; +124DF;CUNEIFORM SIGN LAK-092;Lo;0;L;;;;;N;;;;; +124E0;CUNEIFORM SIGN LAK-130;Lo;0;L;;;;;N;;;;; +124E1;CUNEIFORM SIGN LAK-142;Lo;0;L;;;;;N;;;;; +124E2;CUNEIFORM SIGN LAK-210;Lo;0;L;;;;;N;;;;; +124E3;CUNEIFORM SIGN LAK-219;Lo;0;L;;;;;N;;;;; +124E4;CUNEIFORM SIGN LAK-220;Lo;0;L;;;;;N;;;;; +124E5;CUNEIFORM SIGN LAK-225;Lo;0;L;;;;;N;;;;; +124E6;CUNEIFORM SIGN LAK-228;Lo;0;L;;;;;N;;;;; +124E7;CUNEIFORM SIGN LAK-238;Lo;0;L;;;;;N;;;;; +124E8;CUNEIFORM SIGN LAK-265;Lo;0;L;;;;;N;;;;; +124E9;CUNEIFORM SIGN LAK-266;Lo;0;L;;;;;N;;;;; +124EA;CUNEIFORM SIGN LAK-343;Lo;0;L;;;;;N;;;;; +124EB;CUNEIFORM SIGN LAK-347;Lo;0;L;;;;;N;;;;; +124EC;CUNEIFORM SIGN LAK-348;Lo;0;L;;;;;N;;;;; +124ED;CUNEIFORM SIGN LAK-383;Lo;0;L;;;;;N;;;;; +124EE;CUNEIFORM SIGN LAK-384;Lo;0;L;;;;;N;;;;; +124EF;CUNEIFORM SIGN LAK-390;Lo;0;L;;;;;N;;;;; +124F0;CUNEIFORM SIGN LAK-441;Lo;0;L;;;;;N;;;;; +124F1;CUNEIFORM SIGN LAK-449;Lo;0;L;;;;;N;;;;; +124F2;CUNEIFORM SIGN LAK-449 TIMES GU;Lo;0;L;;;;;N;;;;; +124F3;CUNEIFORM SIGN LAK-449 TIMES IGI;Lo;0;L;;;;;N;;;;; +124F4;CUNEIFORM SIGN LAK-449 TIMES PAP PLUS LU3;Lo;0;L;;;;;N;;;;; +124F5;CUNEIFORM SIGN LAK-449 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; +124F6;CUNEIFORM SIGN LAK-449 TIMES U2 PLUS BA;Lo;0;L;;;;;N;;;;; +124F7;CUNEIFORM SIGN LAK-450;Lo;0;L;;;;;N;;;;; +124F8;CUNEIFORM SIGN LAK-457;Lo;0;L;;;;;N;;;;; +124F9;CUNEIFORM SIGN LAK-470;Lo;0;L;;;;;N;;;;; +124FA;CUNEIFORM SIGN LAK-483;Lo;0;L;;;;;N;;;;; +124FB;CUNEIFORM SIGN LAK-490;Lo;0;L;;;;;N;;;;; +124FC;CUNEIFORM SIGN LAK-492;Lo;0;L;;;;;N;;;;; +124FD;CUNEIFORM SIGN LAK-493;Lo;0;L;;;;;N;;;;; +124FE;CUNEIFORM SIGN LAK-495;Lo;0;L;;;;;N;;;;; +124FF;CUNEIFORM SIGN LAK-550;Lo;0;L;;;;;N;;;;; +12500;CUNEIFORM SIGN LAK-608;Lo;0;L;;;;;N;;;;; +12501;CUNEIFORM SIGN LAK-617;Lo;0;L;;;;;N;;;;; +12502;CUNEIFORM SIGN LAK-617 TIMES ASH;Lo;0;L;;;;;N;;;;; +12503;CUNEIFORM SIGN LAK-617 TIMES BAD;Lo;0;L;;;;;N;;;;; +12504;CUNEIFORM SIGN LAK-617 TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; +12505;CUNEIFORM SIGN LAK-617 TIMES KU3;Lo;0;L;;;;;N;;;;; +12506;CUNEIFORM SIGN LAK-617 TIMES LA;Lo;0;L;;;;;N;;;;; +12507;CUNEIFORM SIGN LAK-617 TIMES TAR;Lo;0;L;;;;;N;;;;; +12508;CUNEIFORM SIGN LAK-617 TIMES TE;Lo;0;L;;;;;N;;;;; +12509;CUNEIFORM SIGN LAK-617 TIMES U2;Lo;0;L;;;;;N;;;;; +1250A;CUNEIFORM SIGN LAK-617 TIMES UD;Lo;0;L;;;;;N;;;;; +1250B;CUNEIFORM SIGN LAK-617 TIMES URUDA;Lo;0;L;;;;;N;;;;; +1250C;CUNEIFORM SIGN LAK-636;Lo;0;L;;;;;N;;;;; +1250D;CUNEIFORM SIGN LAK-648;Lo;0;L;;;;;N;;;;; +1250E;CUNEIFORM SIGN LAK-648 TIMES DUB;Lo;0;L;;;;;N;;;;; +1250F;CUNEIFORM SIGN LAK-648 TIMES GA;Lo;0;L;;;;;N;;;;; +12510;CUNEIFORM SIGN LAK-648 TIMES IGI;Lo;0;L;;;;;N;;;;; +12511;CUNEIFORM SIGN LAK-648 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12512;CUNEIFORM SIGN LAK-648 TIMES NI;Lo;0;L;;;;;N;;;;; +12513;CUNEIFORM SIGN LAK-648 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; +12514;CUNEIFORM SIGN LAK-648 TIMES SHESH PLUS KI;Lo;0;L;;;;;N;;;;; +12515;CUNEIFORM SIGN LAK-648 TIMES UD;Lo;0;L;;;;;N;;;;; +12516;CUNEIFORM SIGN LAK-648 TIMES URUDA;Lo;0;L;;;;;N;;;;; +12517;CUNEIFORM SIGN LAK-724;Lo;0;L;;;;;N;;;;; +12518;CUNEIFORM SIGN LAK-749;Lo;0;L;;;;;N;;;;; +12519;CUNEIFORM SIGN LU2 GUNU TIMES ASH;Lo;0;L;;;;;N;;;;; +1251A;CUNEIFORM SIGN LU2 TIMES DISH;Lo;0;L;;;;;N;;;;; +1251B;CUNEIFORM SIGN LU2 TIMES HAL;Lo;0;L;;;;;N;;;;; +1251C;CUNEIFORM SIGN LU2 TIMES PAP;Lo;0;L;;;;;N;;;;; +1251D;CUNEIFORM SIGN LU2 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; +1251E;CUNEIFORM SIGN LU2 TIMES TAK4;Lo;0;L;;;;;N;;;;; +1251F;CUNEIFORM SIGN MI PLUS ZA7;Lo;0;L;;;;;N;;;;; +12520;CUNEIFORM SIGN MUSH OVER MUSH TIMES GA;Lo;0;L;;;;;N;;;;; +12521;CUNEIFORM SIGN MUSH OVER MUSH TIMES KAK;Lo;0;L;;;;;N;;;;; +12522;CUNEIFORM SIGN NINDA2 TIMES DIM GUNU;Lo;0;L;;;;;N;;;;; +12523;CUNEIFORM SIGN NINDA2 TIMES GISH;Lo;0;L;;;;;N;;;;; +12524;CUNEIFORM SIGN NINDA2 TIMES GUL;Lo;0;L;;;;;N;;;;; +12525;CUNEIFORM SIGN NINDA2 TIMES HI;Lo;0;L;;;;;N;;;;; +12526;CUNEIFORM SIGN NINDA2 TIMES KESH2;Lo;0;L;;;;;N;;;;; +12527;CUNEIFORM SIGN NINDA2 TIMES LAK-050;Lo;0;L;;;;;N;;;;; +12528;CUNEIFORM SIGN NINDA2 TIMES MASH;Lo;0;L;;;;;N;;;;; +12529;CUNEIFORM SIGN NINDA2 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;; +1252A;CUNEIFORM SIGN NINDA2 TIMES U;Lo;0;L;;;;;N;;;;; +1252B;CUNEIFORM SIGN NINDA2 TIMES U PLUS U;Lo;0;L;;;;;N;;;;; +1252C;CUNEIFORM SIGN NINDA2 TIMES URUDA;Lo;0;L;;;;;N;;;;; +1252D;CUNEIFORM SIGN SAG GUNU TIMES HA;Lo;0;L;;;;;N;;;;; +1252E;CUNEIFORM SIGN SAG TIMES EN;Lo;0;L;;;;;N;;;;; +1252F;CUNEIFORM SIGN SAG TIMES SHE AT LEFT;Lo;0;L;;;;;N;;;;; +12530;CUNEIFORM SIGN SAG TIMES TAK4;Lo;0;L;;;;;N;;;;; +12531;CUNEIFORM SIGN SHA6 TENU;Lo;0;L;;;;;N;;;;; +12532;CUNEIFORM SIGN SHE OVER SHE;Lo;0;L;;;;;N;;;;; +12533;CUNEIFORM SIGN SHE PLUS HUB2;Lo;0;L;;;;;N;;;;; +12534;CUNEIFORM SIGN SHE PLUS NAM2;Lo;0;L;;;;;N;;;;; +12535;CUNEIFORM SIGN SHE PLUS SAR;Lo;0;L;;;;;N;;;;; +12536;CUNEIFORM SIGN SHU2 PLUS DUG TIMES NI;Lo;0;L;;;;;N;;;;; +12537;CUNEIFORM SIGN SHU2 PLUS E2 TIMES AN;Lo;0;L;;;;;N;;;;; +12538;CUNEIFORM SIGN SI TIMES TAK4;Lo;0;L;;;;;N;;;;; +12539;CUNEIFORM SIGN TAK4 PLUS SAG;Lo;0;L;;;;;N;;;;; +1253A;CUNEIFORM SIGN TUM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1253B;CUNEIFORM SIGN TUM TIMES THREE DISH;Lo;0;L;;;;;N;;;;; +1253C;CUNEIFORM SIGN UR2 INVERTED;Lo;0;L;;;;;N;;;;; +1253D;CUNEIFORM SIGN UR2 TIMES UD;Lo;0;L;;;;;N;;;;; +1253E;CUNEIFORM SIGN URU TIMES DARA3;Lo;0;L;;;;;N;;;;; +1253F;CUNEIFORM SIGN URU TIMES LAK-668;Lo;0;L;;;;;N;;;;; +12540;CUNEIFORM SIGN URU TIMES LU3;Lo;0;L;;;;;N;;;;; +12541;CUNEIFORM SIGN ZA7;Lo;0;L;;;;;N;;;;; +12542;CUNEIFORM SIGN ZU OVER ZU PLUS SAR;Lo;0;L;;;;;N;;;;; +12543;CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU;Lo;0;L;;;;;N;;;;; +13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; +13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; +13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; +13003;EGYPTIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;; +13004;EGYPTIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;; +13005;EGYPTIAN HIEROGLYPH A005A;Lo;0;L;;;;;N;;;;; +13006;EGYPTIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;; +13007;EGYPTIAN HIEROGLYPH A006A;Lo;0;L;;;;;N;;;;; +13008;EGYPTIAN HIEROGLYPH A006B;Lo;0;L;;;;;N;;;;; +13009;EGYPTIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;; +1300A;EGYPTIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;; +1300B;EGYPTIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;; +1300C;EGYPTIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;; +1300D;EGYPTIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;; +1300E;EGYPTIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;; +1300F;EGYPTIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;; +13010;EGYPTIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;; +13011;EGYPTIAN HIEROGLYPH A014A;Lo;0;L;;;;;N;;;;; +13012;EGYPTIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;; +13013;EGYPTIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;; +13014;EGYPTIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;; +13015;EGYPTIAN HIEROGLYPH A017A;Lo;0;L;;;;;N;;;;; +13016;EGYPTIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;; +13017;EGYPTIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;; +13018;EGYPTIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;; +13019;EGYPTIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;; +1301A;EGYPTIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;; +1301B;EGYPTIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;; +1301C;EGYPTIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;; +1301D;EGYPTIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;; +1301E;EGYPTIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;; +1301F;EGYPTIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;; +13020;EGYPTIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;; +13021;EGYPTIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;; +13022;EGYPTIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;; +13023;EGYPTIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;; +13024;EGYPTIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;; +13025;EGYPTIAN HIEROGLYPH A032A;Lo;0;L;;;;;N;;;;; +13026;EGYPTIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;; +13027;EGYPTIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;; +13028;EGYPTIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;; +13029;EGYPTIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;; +1302A;EGYPTIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;; +1302B;EGYPTIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;; +1302C;EGYPTIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;; +1302D;EGYPTIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;; +1302E;EGYPTIAN HIEROGLYPH A040A;Lo;0;L;;;;;N;;;;; +1302F;EGYPTIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;; +13030;EGYPTIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;; +13031;EGYPTIAN HIEROGLYPH A042A;Lo;0;L;;;;;N;;;;; +13032;EGYPTIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;; +13033;EGYPTIAN HIEROGLYPH A043A;Lo;0;L;;;;;N;;;;; +13034;EGYPTIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;; +13035;EGYPTIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;; +13036;EGYPTIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;; +13037;EGYPTIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;; +13038;EGYPTIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;; +13039;EGYPTIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;; +1303A;EGYPTIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;; +1303B;EGYPTIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;; +1303C;EGYPTIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;; +1303D;EGYPTIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;; +1303E;EGYPTIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;; +1303F;EGYPTIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;; +13040;EGYPTIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;; +13041;EGYPTIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;; +13042;EGYPTIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;; +13043;EGYPTIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;; +13044;EGYPTIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;; +13045;EGYPTIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;; +13046;EGYPTIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;; +13047;EGYPTIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;; +13048;EGYPTIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;; +13049;EGYPTIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;; +1304A;EGYPTIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;; +1304B;EGYPTIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;; +1304C;EGYPTIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;; +1304D;EGYPTIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;; +1304E;EGYPTIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;; +1304F;EGYPTIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;; +13050;EGYPTIAN HIEROGLYPH B001;Lo;0;L;;;;;N;;;;; +13051;EGYPTIAN HIEROGLYPH B002;Lo;0;L;;;;;N;;;;; +13052;EGYPTIAN HIEROGLYPH B003;Lo;0;L;;;;;N;;;;; +13053;EGYPTIAN HIEROGLYPH B004;Lo;0;L;;;;;N;;;;; +13054;EGYPTIAN HIEROGLYPH B005;Lo;0;L;;;;;N;;;;; +13055;EGYPTIAN HIEROGLYPH B005A;Lo;0;L;;;;;N;;;;; +13056;EGYPTIAN HIEROGLYPH B006;Lo;0;L;;;;;N;;;;; +13057;EGYPTIAN HIEROGLYPH B007;Lo;0;L;;;;;N;;;;; +13058;EGYPTIAN HIEROGLYPH B008;Lo;0;L;;;;;N;;;;; +13059;EGYPTIAN HIEROGLYPH B009;Lo;0;L;;;;;N;;;;; +1305A;EGYPTIAN HIEROGLYPH C001;Lo;0;L;;;;;N;;;;; +1305B;EGYPTIAN HIEROGLYPH C002;Lo;0;L;;;;;N;;;;; +1305C;EGYPTIAN HIEROGLYPH C002A;Lo;0;L;;;;;N;;;;; +1305D;EGYPTIAN HIEROGLYPH C002B;Lo;0;L;;;;;N;;;;; +1305E;EGYPTIAN HIEROGLYPH C002C;Lo;0;L;;;;;N;;;;; +1305F;EGYPTIAN HIEROGLYPH C003;Lo;0;L;;;;;N;;;;; +13060;EGYPTIAN HIEROGLYPH C004;Lo;0;L;;;;;N;;;;; +13061;EGYPTIAN HIEROGLYPH C005;Lo;0;L;;;;;N;;;;; +13062;EGYPTIAN HIEROGLYPH C006;Lo;0;L;;;;;N;;;;; +13063;EGYPTIAN HIEROGLYPH C007;Lo;0;L;;;;;N;;;;; +13064;EGYPTIAN HIEROGLYPH C008;Lo;0;L;;;;;N;;;;; +13065;EGYPTIAN HIEROGLYPH C009;Lo;0;L;;;;;N;;;;; +13066;EGYPTIAN HIEROGLYPH C010;Lo;0;L;;;;;N;;;;; +13067;EGYPTIAN HIEROGLYPH C010A;Lo;0;L;;;;;N;;;;; +13068;EGYPTIAN HIEROGLYPH C011;Lo;0;L;;;;;N;;;;; +13069;EGYPTIAN HIEROGLYPH C012;Lo;0;L;;;;;N;;;;; +1306A;EGYPTIAN HIEROGLYPH C013;Lo;0;L;;;;;N;;;;; +1306B;EGYPTIAN HIEROGLYPH C014;Lo;0;L;;;;;N;;;;; +1306C;EGYPTIAN HIEROGLYPH C015;Lo;0;L;;;;;N;;;;; +1306D;EGYPTIAN HIEROGLYPH C016;Lo;0;L;;;;;N;;;;; +1306E;EGYPTIAN HIEROGLYPH C017;Lo;0;L;;;;;N;;;;; +1306F;EGYPTIAN HIEROGLYPH C018;Lo;0;L;;;;;N;;;;; +13070;EGYPTIAN HIEROGLYPH C019;Lo;0;L;;;;;N;;;;; +13071;EGYPTIAN HIEROGLYPH C020;Lo;0;L;;;;;N;;;;; +13072;EGYPTIAN HIEROGLYPH C021;Lo;0;L;;;;;N;;;;; +13073;EGYPTIAN HIEROGLYPH C022;Lo;0;L;;;;;N;;;;; +13074;EGYPTIAN HIEROGLYPH C023;Lo;0;L;;;;;N;;;;; +13075;EGYPTIAN HIEROGLYPH C024;Lo;0;L;;;;;N;;;;; +13076;EGYPTIAN HIEROGLYPH D001;Lo;0;L;;;;;N;;;;; +13077;EGYPTIAN HIEROGLYPH D002;Lo;0;L;;;;;N;;;;; +13078;EGYPTIAN HIEROGLYPH D003;Lo;0;L;;;;;N;;;;; +13079;EGYPTIAN HIEROGLYPH D004;Lo;0;L;;;;;N;;;;; +1307A;EGYPTIAN HIEROGLYPH D005;Lo;0;L;;;;;N;;;;; +1307B;EGYPTIAN HIEROGLYPH D006;Lo;0;L;;;;;N;;;;; +1307C;EGYPTIAN HIEROGLYPH D007;Lo;0;L;;;;;N;;;;; +1307D;EGYPTIAN HIEROGLYPH D008;Lo;0;L;;;;;N;;;;; +1307E;EGYPTIAN HIEROGLYPH D008A;Lo;0;L;;;;;N;;;;; +1307F;EGYPTIAN HIEROGLYPH D009;Lo;0;L;;;;;N;;;;; +13080;EGYPTIAN HIEROGLYPH D010;Lo;0;L;;;;;N;;;;; +13081;EGYPTIAN HIEROGLYPH D011;Lo;0;L;;;;;N;;;;; +13082;EGYPTIAN HIEROGLYPH D012;Lo;0;L;;;;;N;;;;; +13083;EGYPTIAN HIEROGLYPH D013;Lo;0;L;;;;;N;;;;; +13084;EGYPTIAN HIEROGLYPH D014;Lo;0;L;;;;;N;;;;; +13085;EGYPTIAN HIEROGLYPH D015;Lo;0;L;;;;;N;;;;; +13086;EGYPTIAN HIEROGLYPH D016;Lo;0;L;;;;;N;;;;; +13087;EGYPTIAN HIEROGLYPH D017;Lo;0;L;;;;;N;;;;; +13088;EGYPTIAN HIEROGLYPH D018;Lo;0;L;;;;;N;;;;; +13089;EGYPTIAN HIEROGLYPH D019;Lo;0;L;;;;;N;;;;; +1308A;EGYPTIAN HIEROGLYPH D020;Lo;0;L;;;;;N;;;;; +1308B;EGYPTIAN HIEROGLYPH D021;Lo;0;L;;;;;N;;;;; +1308C;EGYPTIAN HIEROGLYPH D022;Lo;0;L;;;;;N;;;;; +1308D;EGYPTIAN HIEROGLYPH D023;Lo;0;L;;;;;N;;;;; +1308E;EGYPTIAN HIEROGLYPH D024;Lo;0;L;;;;;N;;;;; +1308F;EGYPTIAN HIEROGLYPH D025;Lo;0;L;;;;;N;;;;; +13090;EGYPTIAN HIEROGLYPH D026;Lo;0;L;;;;;N;;;;; +13091;EGYPTIAN HIEROGLYPH D027;Lo;0;L;;;;;N;;;;; +13092;EGYPTIAN HIEROGLYPH D027A;Lo;0;L;;;;;N;;;;; +13093;EGYPTIAN HIEROGLYPH D028;Lo;0;L;;;;;N;;;;; +13094;EGYPTIAN HIEROGLYPH D029;Lo;0;L;;;;;N;;;;; +13095;EGYPTIAN HIEROGLYPH D030;Lo;0;L;;;;;N;;;;; +13096;EGYPTIAN HIEROGLYPH D031;Lo;0;L;;;;;N;;;;; +13097;EGYPTIAN HIEROGLYPH D031A;Lo;0;L;;;;;N;;;;; +13098;EGYPTIAN HIEROGLYPH D032;Lo;0;L;;;;;N;;;;; +13099;EGYPTIAN HIEROGLYPH D033;Lo;0;L;;;;;N;;;;; +1309A;EGYPTIAN HIEROGLYPH D034;Lo;0;L;;;;;N;;;;; +1309B;EGYPTIAN HIEROGLYPH D034A;Lo;0;L;;;;;N;;;;; +1309C;EGYPTIAN HIEROGLYPH D035;Lo;0;L;;;;;N;;;;; +1309D;EGYPTIAN HIEROGLYPH D036;Lo;0;L;;;;;N;;;;; +1309E;EGYPTIAN HIEROGLYPH D037;Lo;0;L;;;;;N;;;;; +1309F;EGYPTIAN HIEROGLYPH D038;Lo;0;L;;;;;N;;;;; +130A0;EGYPTIAN HIEROGLYPH D039;Lo;0;L;;;;;N;;;;; +130A1;EGYPTIAN HIEROGLYPH D040;Lo;0;L;;;;;N;;;;; +130A2;EGYPTIAN HIEROGLYPH D041;Lo;0;L;;;;;N;;;;; +130A3;EGYPTIAN HIEROGLYPH D042;Lo;0;L;;;;;N;;;;; +130A4;EGYPTIAN HIEROGLYPH D043;Lo;0;L;;;;;N;;;;; +130A5;EGYPTIAN HIEROGLYPH D044;Lo;0;L;;;;;N;;;;; +130A6;EGYPTIAN HIEROGLYPH D045;Lo;0;L;;;;;N;;;;; +130A7;EGYPTIAN HIEROGLYPH D046;Lo;0;L;;;;;N;;;;; +130A8;EGYPTIAN HIEROGLYPH D046A;Lo;0;L;;;;;N;;;;; +130A9;EGYPTIAN HIEROGLYPH D047;Lo;0;L;;;;;N;;;;; +130AA;EGYPTIAN HIEROGLYPH D048;Lo;0;L;;;;;N;;;;; +130AB;EGYPTIAN HIEROGLYPH D048A;Lo;0;L;;;;;N;;;;; +130AC;EGYPTIAN HIEROGLYPH D049;Lo;0;L;;;;;N;;;;; +130AD;EGYPTIAN HIEROGLYPH D050;Lo;0;L;;;;;N;;;;; +130AE;EGYPTIAN HIEROGLYPH D050A;Lo;0;L;;;;;N;;;;; +130AF;EGYPTIAN HIEROGLYPH D050B;Lo;0;L;;;;;N;;;;; +130B0;EGYPTIAN HIEROGLYPH D050C;Lo;0;L;;;;;N;;;;; +130B1;EGYPTIAN HIEROGLYPH D050D;Lo;0;L;;;;;N;;;;; +130B2;EGYPTIAN HIEROGLYPH D050E;Lo;0;L;;;;;N;;;;; +130B3;EGYPTIAN HIEROGLYPH D050F;Lo;0;L;;;;;N;;;;; +130B4;EGYPTIAN HIEROGLYPH D050G;Lo;0;L;;;;;N;;;;; +130B5;EGYPTIAN HIEROGLYPH D050H;Lo;0;L;;;;;N;;;;; +130B6;EGYPTIAN HIEROGLYPH D050I;Lo;0;L;;;;;N;;;;; +130B7;EGYPTIAN HIEROGLYPH D051;Lo;0;L;;;;;N;;;;; +130B8;EGYPTIAN HIEROGLYPH D052;Lo;0;L;;;;;N;;;;; +130B9;EGYPTIAN HIEROGLYPH D052A;Lo;0;L;;;;;N;;;;; +130BA;EGYPTIAN HIEROGLYPH D053;Lo;0;L;;;;;N;;;;; +130BB;EGYPTIAN HIEROGLYPH D054;Lo;0;L;;;;;N;;;;; +130BC;EGYPTIAN HIEROGLYPH D054A;Lo;0;L;;;;;N;;;;; +130BD;EGYPTIAN HIEROGLYPH D055;Lo;0;L;;;;;N;;;;; +130BE;EGYPTIAN HIEROGLYPH D056;Lo;0;L;;;;;N;;;;; +130BF;EGYPTIAN HIEROGLYPH D057;Lo;0;L;;;;;N;;;;; +130C0;EGYPTIAN HIEROGLYPH D058;Lo;0;L;;;;;N;;;;; +130C1;EGYPTIAN HIEROGLYPH D059;Lo;0;L;;;;;N;;;;; +130C2;EGYPTIAN HIEROGLYPH D060;Lo;0;L;;;;;N;;;;; +130C3;EGYPTIAN HIEROGLYPH D061;Lo;0;L;;;;;N;;;;; +130C4;EGYPTIAN HIEROGLYPH D062;Lo;0;L;;;;;N;;;;; +130C5;EGYPTIAN HIEROGLYPH D063;Lo;0;L;;;;;N;;;;; +130C6;EGYPTIAN HIEROGLYPH D064;Lo;0;L;;;;;N;;;;; +130C7;EGYPTIAN HIEROGLYPH D065;Lo;0;L;;;;;N;;;;; +130C8;EGYPTIAN HIEROGLYPH D066;Lo;0;L;;;;;N;;;;; +130C9;EGYPTIAN HIEROGLYPH D067;Lo;0;L;;;;;N;;;;; +130CA;EGYPTIAN HIEROGLYPH D067A;Lo;0;L;;;;;N;;;;; +130CB;EGYPTIAN HIEROGLYPH D067B;Lo;0;L;;;;;N;;;;; +130CC;EGYPTIAN HIEROGLYPH D067C;Lo;0;L;;;;;N;;;;; +130CD;EGYPTIAN HIEROGLYPH D067D;Lo;0;L;;;;;N;;;;; +130CE;EGYPTIAN HIEROGLYPH D067E;Lo;0;L;;;;;N;;;;; +130CF;EGYPTIAN HIEROGLYPH D067F;Lo;0;L;;;;;N;;;;; +130D0;EGYPTIAN HIEROGLYPH D067G;Lo;0;L;;;;;N;;;;; +130D1;EGYPTIAN HIEROGLYPH D067H;Lo;0;L;;;;;N;;;;; +130D2;EGYPTIAN HIEROGLYPH E001;Lo;0;L;;;;;N;;;;; +130D3;EGYPTIAN HIEROGLYPH E002;Lo;0;L;;;;;N;;;;; +130D4;EGYPTIAN HIEROGLYPH E003;Lo;0;L;;;;;N;;;;; +130D5;EGYPTIAN HIEROGLYPH E004;Lo;0;L;;;;;N;;;;; +130D6;EGYPTIAN HIEROGLYPH E005;Lo;0;L;;;;;N;;;;; +130D7;EGYPTIAN HIEROGLYPH E006;Lo;0;L;;;;;N;;;;; +130D8;EGYPTIAN HIEROGLYPH E007;Lo;0;L;;;;;N;;;;; +130D9;EGYPTIAN HIEROGLYPH E008;Lo;0;L;;;;;N;;;;; +130DA;EGYPTIAN HIEROGLYPH E008A;Lo;0;L;;;;;N;;;;; +130DB;EGYPTIAN HIEROGLYPH E009;Lo;0;L;;;;;N;;;;; +130DC;EGYPTIAN HIEROGLYPH E009A;Lo;0;L;;;;;N;;;;; +130DD;EGYPTIAN HIEROGLYPH E010;Lo;0;L;;;;;N;;;;; +130DE;EGYPTIAN HIEROGLYPH E011;Lo;0;L;;;;;N;;;;; +130DF;EGYPTIAN HIEROGLYPH E012;Lo;0;L;;;;;N;;;;; +130E0;EGYPTIAN HIEROGLYPH E013;Lo;0;L;;;;;N;;;;; +130E1;EGYPTIAN HIEROGLYPH E014;Lo;0;L;;;;;N;;;;; +130E2;EGYPTIAN HIEROGLYPH E015;Lo;0;L;;;;;N;;;;; +130E3;EGYPTIAN HIEROGLYPH E016;Lo;0;L;;;;;N;;;;; +130E4;EGYPTIAN HIEROGLYPH E016A;Lo;0;L;;;;;N;;;;; +130E5;EGYPTIAN HIEROGLYPH E017;Lo;0;L;;;;;N;;;;; +130E6;EGYPTIAN HIEROGLYPH E017A;Lo;0;L;;;;;N;;;;; +130E7;EGYPTIAN HIEROGLYPH E018;Lo;0;L;;;;;N;;;;; +130E8;EGYPTIAN HIEROGLYPH E019;Lo;0;L;;;;;N;;;;; +130E9;EGYPTIAN HIEROGLYPH E020;Lo;0;L;;;;;N;;;;; +130EA;EGYPTIAN HIEROGLYPH E020A;Lo;0;L;;;;;N;;;;; +130EB;EGYPTIAN HIEROGLYPH E021;Lo;0;L;;;;;N;;;;; +130EC;EGYPTIAN HIEROGLYPH E022;Lo;0;L;;;;;N;;;;; +130ED;EGYPTIAN HIEROGLYPH E023;Lo;0;L;;;;;N;;;;; +130EE;EGYPTIAN HIEROGLYPH E024;Lo;0;L;;;;;N;;;;; +130EF;EGYPTIAN HIEROGLYPH E025;Lo;0;L;;;;;N;;;;; +130F0;EGYPTIAN HIEROGLYPH E026;Lo;0;L;;;;;N;;;;; +130F1;EGYPTIAN HIEROGLYPH E027;Lo;0;L;;;;;N;;;;; +130F2;EGYPTIAN HIEROGLYPH E028;Lo;0;L;;;;;N;;;;; +130F3;EGYPTIAN HIEROGLYPH E028A;Lo;0;L;;;;;N;;;;; +130F4;EGYPTIAN HIEROGLYPH E029;Lo;0;L;;;;;N;;;;; +130F5;EGYPTIAN HIEROGLYPH E030;Lo;0;L;;;;;N;;;;; +130F6;EGYPTIAN HIEROGLYPH E031;Lo;0;L;;;;;N;;;;; +130F7;EGYPTIAN HIEROGLYPH E032;Lo;0;L;;;;;N;;;;; +130F8;EGYPTIAN HIEROGLYPH E033;Lo;0;L;;;;;N;;;;; +130F9;EGYPTIAN HIEROGLYPH E034;Lo;0;L;;;;;N;;;;; +130FA;EGYPTIAN HIEROGLYPH E034A;Lo;0;L;;;;;N;;;;; +130FB;EGYPTIAN HIEROGLYPH E036;Lo;0;L;;;;;N;;;;; +130FC;EGYPTIAN HIEROGLYPH E037;Lo;0;L;;;;;N;;;;; +130FD;EGYPTIAN HIEROGLYPH E038;Lo;0;L;;;;;N;;;;; +130FE;EGYPTIAN HIEROGLYPH F001;Lo;0;L;;;;;N;;;;; +130FF;EGYPTIAN HIEROGLYPH F001A;Lo;0;L;;;;;N;;;;; +13100;EGYPTIAN HIEROGLYPH F002;Lo;0;L;;;;;N;;;;; +13101;EGYPTIAN HIEROGLYPH F003;Lo;0;L;;;;;N;;;;; +13102;EGYPTIAN HIEROGLYPH F004;Lo;0;L;;;;;N;;;;; +13103;EGYPTIAN HIEROGLYPH F005;Lo;0;L;;;;;N;;;;; +13104;EGYPTIAN HIEROGLYPH F006;Lo;0;L;;;;;N;;;;; +13105;EGYPTIAN HIEROGLYPH F007;Lo;0;L;;;;;N;;;;; +13106;EGYPTIAN HIEROGLYPH F008;Lo;0;L;;;;;N;;;;; +13107;EGYPTIAN HIEROGLYPH F009;Lo;0;L;;;;;N;;;;; +13108;EGYPTIAN HIEROGLYPH F010;Lo;0;L;;;;;N;;;;; +13109;EGYPTIAN HIEROGLYPH F011;Lo;0;L;;;;;N;;;;; +1310A;EGYPTIAN HIEROGLYPH F012;Lo;0;L;;;;;N;;;;; +1310B;EGYPTIAN HIEROGLYPH F013;Lo;0;L;;;;;N;;;;; +1310C;EGYPTIAN HIEROGLYPH F013A;Lo;0;L;;;;;N;;;;; +1310D;EGYPTIAN HIEROGLYPH F014;Lo;0;L;;;;;N;;;;; +1310E;EGYPTIAN HIEROGLYPH F015;Lo;0;L;;;;;N;;;;; +1310F;EGYPTIAN HIEROGLYPH F016;Lo;0;L;;;;;N;;;;; +13110;EGYPTIAN HIEROGLYPH F017;Lo;0;L;;;;;N;;;;; +13111;EGYPTIAN HIEROGLYPH F018;Lo;0;L;;;;;N;;;;; +13112;EGYPTIAN HIEROGLYPH F019;Lo;0;L;;;;;N;;;;; +13113;EGYPTIAN HIEROGLYPH F020;Lo;0;L;;;;;N;;;;; +13114;EGYPTIAN HIEROGLYPH F021;Lo;0;L;;;;;N;;;;; +13115;EGYPTIAN HIEROGLYPH F021A;Lo;0;L;;;;;N;;;;; +13116;EGYPTIAN HIEROGLYPH F022;Lo;0;L;;;;;N;;;;; +13117;EGYPTIAN HIEROGLYPH F023;Lo;0;L;;;;;N;;;;; +13118;EGYPTIAN HIEROGLYPH F024;Lo;0;L;;;;;N;;;;; +13119;EGYPTIAN HIEROGLYPH F025;Lo;0;L;;;;;N;;;;; +1311A;EGYPTIAN HIEROGLYPH F026;Lo;0;L;;;;;N;;;;; +1311B;EGYPTIAN HIEROGLYPH F027;Lo;0;L;;;;;N;;;;; +1311C;EGYPTIAN HIEROGLYPH F028;Lo;0;L;;;;;N;;;;; +1311D;EGYPTIAN HIEROGLYPH F029;Lo;0;L;;;;;N;;;;; +1311E;EGYPTIAN HIEROGLYPH F030;Lo;0;L;;;;;N;;;;; +1311F;EGYPTIAN HIEROGLYPH F031;Lo;0;L;;;;;N;;;;; +13120;EGYPTIAN HIEROGLYPH F031A;Lo;0;L;;;;;N;;;;; +13121;EGYPTIAN HIEROGLYPH F032;Lo;0;L;;;;;N;;;;; +13122;EGYPTIAN HIEROGLYPH F033;Lo;0;L;;;;;N;;;;; +13123;EGYPTIAN HIEROGLYPH F034;Lo;0;L;;;;;N;;;;; +13124;EGYPTIAN HIEROGLYPH F035;Lo;0;L;;;;;N;;;;; +13125;EGYPTIAN HIEROGLYPH F036;Lo;0;L;;;;;N;;;;; +13126;EGYPTIAN HIEROGLYPH F037;Lo;0;L;;;;;N;;;;; +13127;EGYPTIAN HIEROGLYPH F037A;Lo;0;L;;;;;N;;;;; +13128;EGYPTIAN HIEROGLYPH F038;Lo;0;L;;;;;N;;;;; +13129;EGYPTIAN HIEROGLYPH F038A;Lo;0;L;;;;;N;;;;; +1312A;EGYPTIAN HIEROGLYPH F039;Lo;0;L;;;;;N;;;;; +1312B;EGYPTIAN HIEROGLYPH F040;Lo;0;L;;;;;N;;;;; +1312C;EGYPTIAN HIEROGLYPH F041;Lo;0;L;;;;;N;;;;; +1312D;EGYPTIAN HIEROGLYPH F042;Lo;0;L;;;;;N;;;;; +1312E;EGYPTIAN HIEROGLYPH F043;Lo;0;L;;;;;N;;;;; +1312F;EGYPTIAN HIEROGLYPH F044;Lo;0;L;;;;;N;;;;; +13130;EGYPTIAN HIEROGLYPH F045;Lo;0;L;;;;;N;;;;; +13131;EGYPTIAN HIEROGLYPH F045A;Lo;0;L;;;;;N;;;;; +13132;EGYPTIAN HIEROGLYPH F046;Lo;0;L;;;;;N;;;;; +13133;EGYPTIAN HIEROGLYPH F046A;Lo;0;L;;;;;N;;;;; +13134;EGYPTIAN HIEROGLYPH F047;Lo;0;L;;;;;N;;;;; +13135;EGYPTIAN HIEROGLYPH F047A;Lo;0;L;;;;;N;;;;; +13136;EGYPTIAN HIEROGLYPH F048;Lo;0;L;;;;;N;;;;; +13137;EGYPTIAN HIEROGLYPH F049;Lo;0;L;;;;;N;;;;; +13138;EGYPTIAN HIEROGLYPH F050;Lo;0;L;;;;;N;;;;; +13139;EGYPTIAN HIEROGLYPH F051;Lo;0;L;;;;;N;;;;; +1313A;EGYPTIAN HIEROGLYPH F051A;Lo;0;L;;;;;N;;;;; +1313B;EGYPTIAN HIEROGLYPH F051B;Lo;0;L;;;;;N;;;;; +1313C;EGYPTIAN HIEROGLYPH F051C;Lo;0;L;;;;;N;;;;; +1313D;EGYPTIAN HIEROGLYPH F052;Lo;0;L;;;;;N;;;;; +1313E;EGYPTIAN HIEROGLYPH F053;Lo;0;L;;;;;N;;;;; +1313F;EGYPTIAN HIEROGLYPH G001;Lo;0;L;;;;;N;;;;; +13140;EGYPTIAN HIEROGLYPH G002;Lo;0;L;;;;;N;;;;; +13141;EGYPTIAN HIEROGLYPH G003;Lo;0;L;;;;;N;;;;; +13142;EGYPTIAN HIEROGLYPH G004;Lo;0;L;;;;;N;;;;; +13143;EGYPTIAN HIEROGLYPH G005;Lo;0;L;;;;;N;;;;; +13144;EGYPTIAN HIEROGLYPH G006;Lo;0;L;;;;;N;;;;; +13145;EGYPTIAN HIEROGLYPH G006A;Lo;0;L;;;;;N;;;;; +13146;EGYPTIAN HIEROGLYPH G007;Lo;0;L;;;;;N;;;;; +13147;EGYPTIAN HIEROGLYPH G007A;Lo;0;L;;;;;N;;;;; +13148;EGYPTIAN HIEROGLYPH G007B;Lo;0;L;;;;;N;;;;; +13149;EGYPTIAN HIEROGLYPH G008;Lo;0;L;;;;;N;;;;; +1314A;EGYPTIAN HIEROGLYPH G009;Lo;0;L;;;;;N;;;;; +1314B;EGYPTIAN HIEROGLYPH G010;Lo;0;L;;;;;N;;;;; +1314C;EGYPTIAN HIEROGLYPH G011;Lo;0;L;;;;;N;;;;; +1314D;EGYPTIAN HIEROGLYPH G011A;Lo;0;L;;;;;N;;;;; +1314E;EGYPTIAN HIEROGLYPH G012;Lo;0;L;;;;;N;;;;; +1314F;EGYPTIAN HIEROGLYPH G013;Lo;0;L;;;;;N;;;;; +13150;EGYPTIAN HIEROGLYPH G014;Lo;0;L;;;;;N;;;;; +13151;EGYPTIAN HIEROGLYPH G015;Lo;0;L;;;;;N;;;;; +13152;EGYPTIAN HIEROGLYPH G016;Lo;0;L;;;;;N;;;;; +13153;EGYPTIAN HIEROGLYPH G017;Lo;0;L;;;;;N;;;;; +13154;EGYPTIAN HIEROGLYPH G018;Lo;0;L;;;;;N;;;;; +13155;EGYPTIAN HIEROGLYPH G019;Lo;0;L;;;;;N;;;;; +13156;EGYPTIAN HIEROGLYPH G020;Lo;0;L;;;;;N;;;;; +13157;EGYPTIAN HIEROGLYPH G020A;Lo;0;L;;;;;N;;;;; +13158;EGYPTIAN HIEROGLYPH G021;Lo;0;L;;;;;N;;;;; +13159;EGYPTIAN HIEROGLYPH G022;Lo;0;L;;;;;N;;;;; +1315A;EGYPTIAN HIEROGLYPH G023;Lo;0;L;;;;;N;;;;; +1315B;EGYPTIAN HIEROGLYPH G024;Lo;0;L;;;;;N;;;;; +1315C;EGYPTIAN HIEROGLYPH G025;Lo;0;L;;;;;N;;;;; +1315D;EGYPTIAN HIEROGLYPH G026;Lo;0;L;;;;;N;;;;; +1315E;EGYPTIAN HIEROGLYPH G026A;Lo;0;L;;;;;N;;;;; +1315F;EGYPTIAN HIEROGLYPH G027;Lo;0;L;;;;;N;;;;; +13160;EGYPTIAN HIEROGLYPH G028;Lo;0;L;;;;;N;;;;; +13161;EGYPTIAN HIEROGLYPH G029;Lo;0;L;;;;;N;;;;; +13162;EGYPTIAN HIEROGLYPH G030;Lo;0;L;;;;;N;;;;; +13163;EGYPTIAN HIEROGLYPH G031;Lo;0;L;;;;;N;;;;; +13164;EGYPTIAN HIEROGLYPH G032;Lo;0;L;;;;;N;;;;; +13165;EGYPTIAN HIEROGLYPH G033;Lo;0;L;;;;;N;;;;; +13166;EGYPTIAN HIEROGLYPH G034;Lo;0;L;;;;;N;;;;; +13167;EGYPTIAN HIEROGLYPH G035;Lo;0;L;;;;;N;;;;; +13168;EGYPTIAN HIEROGLYPH G036;Lo;0;L;;;;;N;;;;; +13169;EGYPTIAN HIEROGLYPH G036A;Lo;0;L;;;;;N;;;;; +1316A;EGYPTIAN HIEROGLYPH G037;Lo;0;L;;;;;N;;;;; +1316B;EGYPTIAN HIEROGLYPH G037A;Lo;0;L;;;;;N;;;;; +1316C;EGYPTIAN HIEROGLYPH G038;Lo;0;L;;;;;N;;;;; +1316D;EGYPTIAN HIEROGLYPH G039;Lo;0;L;;;;;N;;;;; +1316E;EGYPTIAN HIEROGLYPH G040;Lo;0;L;;;;;N;;;;; +1316F;EGYPTIAN HIEROGLYPH G041;Lo;0;L;;;;;N;;;;; +13170;EGYPTIAN HIEROGLYPH G042;Lo;0;L;;;;;N;;;;; +13171;EGYPTIAN HIEROGLYPH G043;Lo;0;L;;;;;N;;;;; +13172;EGYPTIAN HIEROGLYPH G043A;Lo;0;L;;;;;N;;;;; +13173;EGYPTIAN HIEROGLYPH G044;Lo;0;L;;;;;N;;;;; +13174;EGYPTIAN HIEROGLYPH G045;Lo;0;L;;;;;N;;;;; +13175;EGYPTIAN HIEROGLYPH G045A;Lo;0;L;;;;;N;;;;; +13176;EGYPTIAN HIEROGLYPH G046;Lo;0;L;;;;;N;;;;; +13177;EGYPTIAN HIEROGLYPH G047;Lo;0;L;;;;;N;;;;; +13178;EGYPTIAN HIEROGLYPH G048;Lo;0;L;;;;;N;;;;; +13179;EGYPTIAN HIEROGLYPH G049;Lo;0;L;;;;;N;;;;; +1317A;EGYPTIAN HIEROGLYPH G050;Lo;0;L;;;;;N;;;;; +1317B;EGYPTIAN HIEROGLYPH G051;Lo;0;L;;;;;N;;;;; +1317C;EGYPTIAN HIEROGLYPH G052;Lo;0;L;;;;;N;;;;; +1317D;EGYPTIAN HIEROGLYPH G053;Lo;0;L;;;;;N;;;;; +1317E;EGYPTIAN HIEROGLYPH G054;Lo;0;L;;;;;N;;;;; +1317F;EGYPTIAN HIEROGLYPH H001;Lo;0;L;;;;;N;;;;; +13180;EGYPTIAN HIEROGLYPH H002;Lo;0;L;;;;;N;;;;; +13181;EGYPTIAN HIEROGLYPH H003;Lo;0;L;;;;;N;;;;; +13182;EGYPTIAN HIEROGLYPH H004;Lo;0;L;;;;;N;;;;; +13183;EGYPTIAN HIEROGLYPH H005;Lo;0;L;;;;;N;;;;; +13184;EGYPTIAN HIEROGLYPH H006;Lo;0;L;;;;;N;;;;; +13185;EGYPTIAN HIEROGLYPH H006A;Lo;0;L;;;;;N;;;;; +13186;EGYPTIAN HIEROGLYPH H007;Lo;0;L;;;;;N;;;;; +13187;EGYPTIAN HIEROGLYPH H008;Lo;0;L;;;;;N;;;;; +13188;EGYPTIAN HIEROGLYPH I001;Lo;0;L;;;;;N;;;;; +13189;EGYPTIAN HIEROGLYPH I002;Lo;0;L;;;;;N;;;;; +1318A;EGYPTIAN HIEROGLYPH I003;Lo;0;L;;;;;N;;;;; +1318B;EGYPTIAN HIEROGLYPH I004;Lo;0;L;;;;;N;;;;; +1318C;EGYPTIAN HIEROGLYPH I005;Lo;0;L;;;;;N;;;;; +1318D;EGYPTIAN HIEROGLYPH I005A;Lo;0;L;;;;;N;;;;; +1318E;EGYPTIAN HIEROGLYPH I006;Lo;0;L;;;;;N;;;;; +1318F;EGYPTIAN HIEROGLYPH I007;Lo;0;L;;;;;N;;;;; +13190;EGYPTIAN HIEROGLYPH I008;Lo;0;L;;;;;N;;;;; +13191;EGYPTIAN HIEROGLYPH I009;Lo;0;L;;;;;N;;;;; +13192;EGYPTIAN HIEROGLYPH I009A;Lo;0;L;;;;;N;;;;; +13193;EGYPTIAN HIEROGLYPH I010;Lo;0;L;;;;;N;;;;; +13194;EGYPTIAN HIEROGLYPH I010A;Lo;0;L;;;;;N;;;;; +13195;EGYPTIAN HIEROGLYPH I011;Lo;0;L;;;;;N;;;;; +13196;EGYPTIAN HIEROGLYPH I011A;Lo;0;L;;;;;N;;;;; +13197;EGYPTIAN HIEROGLYPH I012;Lo;0;L;;;;;N;;;;; +13198;EGYPTIAN HIEROGLYPH I013;Lo;0;L;;;;;N;;;;; +13199;EGYPTIAN HIEROGLYPH I014;Lo;0;L;;;;;N;;;;; +1319A;EGYPTIAN HIEROGLYPH I015;Lo;0;L;;;;;N;;;;; +1319B;EGYPTIAN HIEROGLYPH K001;Lo;0;L;;;;;N;;;;; +1319C;EGYPTIAN HIEROGLYPH K002;Lo;0;L;;;;;N;;;;; +1319D;EGYPTIAN HIEROGLYPH K003;Lo;0;L;;;;;N;;;;; +1319E;EGYPTIAN HIEROGLYPH K004;Lo;0;L;;;;;N;;;;; +1319F;EGYPTIAN HIEROGLYPH K005;Lo;0;L;;;;;N;;;;; +131A0;EGYPTIAN HIEROGLYPH K006;Lo;0;L;;;;;N;;;;; +131A1;EGYPTIAN HIEROGLYPH K007;Lo;0;L;;;;;N;;;;; +131A2;EGYPTIAN HIEROGLYPH K008;Lo;0;L;;;;;N;;;;; +131A3;EGYPTIAN HIEROGLYPH L001;Lo;0;L;;;;;N;;;;; +131A4;EGYPTIAN HIEROGLYPH L002;Lo;0;L;;;;;N;;;;; +131A5;EGYPTIAN HIEROGLYPH L002A;Lo;0;L;;;;;N;;;;; +131A6;EGYPTIAN HIEROGLYPH L003;Lo;0;L;;;;;N;;;;; +131A7;EGYPTIAN HIEROGLYPH L004;Lo;0;L;;;;;N;;;;; +131A8;EGYPTIAN HIEROGLYPH L005;Lo;0;L;;;;;N;;;;; +131A9;EGYPTIAN HIEROGLYPH L006;Lo;0;L;;;;;N;;;;; +131AA;EGYPTIAN HIEROGLYPH L006A;Lo;0;L;;;;;N;;;;; +131AB;EGYPTIAN HIEROGLYPH L007;Lo;0;L;;;;;N;;;;; +131AC;EGYPTIAN HIEROGLYPH L008;Lo;0;L;;;;;N;;;;; +131AD;EGYPTIAN HIEROGLYPH M001;Lo;0;L;;;;;N;;;;; +131AE;EGYPTIAN HIEROGLYPH M001A;Lo;0;L;;;;;N;;;;; +131AF;EGYPTIAN HIEROGLYPH M001B;Lo;0;L;;;;;N;;;;; +131B0;EGYPTIAN HIEROGLYPH M002;Lo;0;L;;;;;N;;;;; +131B1;EGYPTIAN HIEROGLYPH M003;Lo;0;L;;;;;N;;;;; +131B2;EGYPTIAN HIEROGLYPH M003A;Lo;0;L;;;;;N;;;;; +131B3;EGYPTIAN HIEROGLYPH M004;Lo;0;L;;;;;N;;;;; +131B4;EGYPTIAN HIEROGLYPH M005;Lo;0;L;;;;;N;;;;; +131B5;EGYPTIAN HIEROGLYPH M006;Lo;0;L;;;;;N;;;;; +131B6;EGYPTIAN HIEROGLYPH M007;Lo;0;L;;;;;N;;;;; +131B7;EGYPTIAN HIEROGLYPH M008;Lo;0;L;;;;;N;;;;; +131B8;EGYPTIAN HIEROGLYPH M009;Lo;0;L;;;;;N;;;;; +131B9;EGYPTIAN HIEROGLYPH M010;Lo;0;L;;;;;N;;;;; +131BA;EGYPTIAN HIEROGLYPH M010A;Lo;0;L;;;;;N;;;;; +131BB;EGYPTIAN HIEROGLYPH M011;Lo;0;L;;;;;N;;;;; +131BC;EGYPTIAN HIEROGLYPH M012;Lo;0;L;;;;;N;;;;; +131BD;EGYPTIAN HIEROGLYPH M012A;Lo;0;L;;;;;N;;;;; +131BE;EGYPTIAN HIEROGLYPH M012B;Lo;0;L;;;;;N;;;;; +131BF;EGYPTIAN HIEROGLYPH M012C;Lo;0;L;;;;;N;;;;; +131C0;EGYPTIAN HIEROGLYPH M012D;Lo;0;L;;;;;N;;;;; +131C1;EGYPTIAN HIEROGLYPH M012E;Lo;0;L;;;;;N;;;;; +131C2;EGYPTIAN HIEROGLYPH M012F;Lo;0;L;;;;;N;;;;; +131C3;EGYPTIAN HIEROGLYPH M012G;Lo;0;L;;;;;N;;;;; +131C4;EGYPTIAN HIEROGLYPH M012H;Lo;0;L;;;;;N;;;;; +131C5;EGYPTIAN HIEROGLYPH M013;Lo;0;L;;;;;N;;;;; +131C6;EGYPTIAN HIEROGLYPH M014;Lo;0;L;;;;;N;;;;; +131C7;EGYPTIAN HIEROGLYPH M015;Lo;0;L;;;;;N;;;;; +131C8;EGYPTIAN HIEROGLYPH M015A;Lo;0;L;;;;;N;;;;; +131C9;EGYPTIAN HIEROGLYPH M016;Lo;0;L;;;;;N;;;;; +131CA;EGYPTIAN HIEROGLYPH M016A;Lo;0;L;;;;;N;;;;; +131CB;EGYPTIAN HIEROGLYPH M017;Lo;0;L;;;;;N;;;;; +131CC;EGYPTIAN HIEROGLYPH M017A;Lo;0;L;;;;;N;;;;; +131CD;EGYPTIAN HIEROGLYPH M018;Lo;0;L;;;;;N;;;;; +131CE;EGYPTIAN HIEROGLYPH M019;Lo;0;L;;;;;N;;;;; +131CF;EGYPTIAN HIEROGLYPH M020;Lo;0;L;;;;;N;;;;; +131D0;EGYPTIAN HIEROGLYPH M021;Lo;0;L;;;;;N;;;;; +131D1;EGYPTIAN HIEROGLYPH M022;Lo;0;L;;;;;N;;;;; +131D2;EGYPTIAN HIEROGLYPH M022A;Lo;0;L;;;;;N;;;;; +131D3;EGYPTIAN HIEROGLYPH M023;Lo;0;L;;;;;N;;;;; +131D4;EGYPTIAN HIEROGLYPH M024;Lo;0;L;;;;;N;;;;; +131D5;EGYPTIAN HIEROGLYPH M024A;Lo;0;L;;;;;N;;;;; +131D6;EGYPTIAN HIEROGLYPH M025;Lo;0;L;;;;;N;;;;; +131D7;EGYPTIAN HIEROGLYPH M026;Lo;0;L;;;;;N;;;;; +131D8;EGYPTIAN HIEROGLYPH M027;Lo;0;L;;;;;N;;;;; +131D9;EGYPTIAN HIEROGLYPH M028;Lo;0;L;;;;;N;;;;; +131DA;EGYPTIAN HIEROGLYPH M028A;Lo;0;L;;;;;N;;;;; +131DB;EGYPTIAN HIEROGLYPH M029;Lo;0;L;;;;;N;;;;; +131DC;EGYPTIAN HIEROGLYPH M030;Lo;0;L;;;;;N;;;;; +131DD;EGYPTIAN HIEROGLYPH M031;Lo;0;L;;;;;N;;;;; +131DE;EGYPTIAN HIEROGLYPH M031A;Lo;0;L;;;;;N;;;;; +131DF;EGYPTIAN HIEROGLYPH M032;Lo;0;L;;;;;N;;;;; +131E0;EGYPTIAN HIEROGLYPH M033;Lo;0;L;;;;;N;;;;; +131E1;EGYPTIAN HIEROGLYPH M033A;Lo;0;L;;;;;N;;;;; +131E2;EGYPTIAN HIEROGLYPH M033B;Lo;0;L;;;;;N;;;;; +131E3;EGYPTIAN HIEROGLYPH M034;Lo;0;L;;;;;N;;;;; +131E4;EGYPTIAN HIEROGLYPH M035;Lo;0;L;;;;;N;;;;; +131E5;EGYPTIAN HIEROGLYPH M036;Lo;0;L;;;;;N;;;;; +131E6;EGYPTIAN HIEROGLYPH M037;Lo;0;L;;;;;N;;;;; +131E7;EGYPTIAN HIEROGLYPH M038;Lo;0;L;;;;;N;;;;; +131E8;EGYPTIAN HIEROGLYPH M039;Lo;0;L;;;;;N;;;;; +131E9;EGYPTIAN HIEROGLYPH M040;Lo;0;L;;;;;N;;;;; +131EA;EGYPTIAN HIEROGLYPH M040A;Lo;0;L;;;;;N;;;;; +131EB;EGYPTIAN HIEROGLYPH M041;Lo;0;L;;;;;N;;;;; +131EC;EGYPTIAN HIEROGLYPH M042;Lo;0;L;;;;;N;;;;; +131ED;EGYPTIAN HIEROGLYPH M043;Lo;0;L;;;;;N;;;;; +131EE;EGYPTIAN HIEROGLYPH M044;Lo;0;L;;;;;N;;;;; +131EF;EGYPTIAN HIEROGLYPH N001;Lo;0;L;;;;;N;;;;; +131F0;EGYPTIAN HIEROGLYPH N002;Lo;0;L;;;;;N;;;;; +131F1;EGYPTIAN HIEROGLYPH N003;Lo;0;L;;;;;N;;;;; +131F2;EGYPTIAN HIEROGLYPH N004;Lo;0;L;;;;;N;;;;; +131F3;EGYPTIAN HIEROGLYPH N005;Lo;0;L;;;;;N;;;;; +131F4;EGYPTIAN HIEROGLYPH N006;Lo;0;L;;;;;N;;;;; +131F5;EGYPTIAN HIEROGLYPH N007;Lo;0;L;;;;;N;;;;; +131F6;EGYPTIAN HIEROGLYPH N008;Lo;0;L;;;;;N;;;;; +131F7;EGYPTIAN HIEROGLYPH N009;Lo;0;L;;;;;N;;;;; +131F8;EGYPTIAN HIEROGLYPH N010;Lo;0;L;;;;;N;;;;; +131F9;EGYPTIAN HIEROGLYPH N011;Lo;0;L;;;;;N;;;;; +131FA;EGYPTIAN HIEROGLYPH N012;Lo;0;L;;;;;N;;;;; +131FB;EGYPTIAN HIEROGLYPH N013;Lo;0;L;;;;;N;;;;; +131FC;EGYPTIAN HIEROGLYPH N014;Lo;0;L;;;;;N;;;;; +131FD;EGYPTIAN HIEROGLYPH N015;Lo;0;L;;;;;N;;;;; +131FE;EGYPTIAN HIEROGLYPH N016;Lo;0;L;;;;;N;;;;; +131FF;EGYPTIAN HIEROGLYPH N017;Lo;0;L;;;;;N;;;;; +13200;EGYPTIAN HIEROGLYPH N018;Lo;0;L;;;;;N;;;;; +13201;EGYPTIAN HIEROGLYPH N018A;Lo;0;L;;;;;N;;;;; +13202;EGYPTIAN HIEROGLYPH N018B;Lo;0;L;;;;;N;;;;; +13203;EGYPTIAN HIEROGLYPH N019;Lo;0;L;;;;;N;;;;; +13204;EGYPTIAN HIEROGLYPH N020;Lo;0;L;;;;;N;;;;; +13205;EGYPTIAN HIEROGLYPH N021;Lo;0;L;;;;;N;;;;; +13206;EGYPTIAN HIEROGLYPH N022;Lo;0;L;;;;;N;;;;; +13207;EGYPTIAN HIEROGLYPH N023;Lo;0;L;;;;;N;;;;; +13208;EGYPTIAN HIEROGLYPH N024;Lo;0;L;;;;;N;;;;; +13209;EGYPTIAN HIEROGLYPH N025;Lo;0;L;;;;;N;;;;; +1320A;EGYPTIAN HIEROGLYPH N025A;Lo;0;L;;;;;N;;;;; +1320B;EGYPTIAN HIEROGLYPH N026;Lo;0;L;;;;;N;;;;; +1320C;EGYPTIAN HIEROGLYPH N027;Lo;0;L;;;;;N;;;;; +1320D;EGYPTIAN HIEROGLYPH N028;Lo;0;L;;;;;N;;;;; +1320E;EGYPTIAN HIEROGLYPH N029;Lo;0;L;;;;;N;;;;; +1320F;EGYPTIAN HIEROGLYPH N030;Lo;0;L;;;;;N;;;;; +13210;EGYPTIAN HIEROGLYPH N031;Lo;0;L;;;;;N;;;;; +13211;EGYPTIAN HIEROGLYPH N032;Lo;0;L;;;;;N;;;;; +13212;EGYPTIAN HIEROGLYPH N033;Lo;0;L;;;;;N;;;;; +13213;EGYPTIAN HIEROGLYPH N033A;Lo;0;L;;;;;N;;;;; +13214;EGYPTIAN HIEROGLYPH N034;Lo;0;L;;;;;N;;;;; +13215;EGYPTIAN HIEROGLYPH N034A;Lo;0;L;;;;;N;;;;; +13216;EGYPTIAN HIEROGLYPH N035;Lo;0;L;;;;;N;;;;; +13217;EGYPTIAN HIEROGLYPH N035A;Lo;0;L;;;;;N;;;;; +13218;EGYPTIAN HIEROGLYPH N036;Lo;0;L;;;;;N;;;;; +13219;EGYPTIAN HIEROGLYPH N037;Lo;0;L;;;;;N;;;;; +1321A;EGYPTIAN HIEROGLYPH N037A;Lo;0;L;;;;;N;;;;; +1321B;EGYPTIAN HIEROGLYPH N038;Lo;0;L;;;;;N;;;;; +1321C;EGYPTIAN HIEROGLYPH N039;Lo;0;L;;;;;N;;;;; +1321D;EGYPTIAN HIEROGLYPH N040;Lo;0;L;;;;;N;;;;; +1321E;EGYPTIAN HIEROGLYPH N041;Lo;0;L;;;;;N;;;;; +1321F;EGYPTIAN HIEROGLYPH N042;Lo;0;L;;;;;N;;;;; +13220;EGYPTIAN HIEROGLYPH NL001;Lo;0;L;;;;;N;;;;; +13221;EGYPTIAN HIEROGLYPH NL002;Lo;0;L;;;;;N;;;;; +13222;EGYPTIAN HIEROGLYPH NL003;Lo;0;L;;;;;N;;;;; +13223;EGYPTIAN HIEROGLYPH NL004;Lo;0;L;;;;;N;;;;; +13224;EGYPTIAN HIEROGLYPH NL005;Lo;0;L;;;;;N;;;;; +13225;EGYPTIAN HIEROGLYPH NL005A;Lo;0;L;;;;;N;;;;; +13226;EGYPTIAN HIEROGLYPH NL006;Lo;0;L;;;;;N;;;;; +13227;EGYPTIAN HIEROGLYPH NL007;Lo;0;L;;;;;N;;;;; +13228;EGYPTIAN HIEROGLYPH NL008;Lo;0;L;;;;;N;;;;; +13229;EGYPTIAN HIEROGLYPH NL009;Lo;0;L;;;;;N;;;;; +1322A;EGYPTIAN HIEROGLYPH NL010;Lo;0;L;;;;;N;;;;; +1322B;EGYPTIAN HIEROGLYPH NL011;Lo;0;L;;;;;N;;;;; +1322C;EGYPTIAN HIEROGLYPH NL012;Lo;0;L;;;;;N;;;;; +1322D;EGYPTIAN HIEROGLYPH NL013;Lo;0;L;;;;;N;;;;; +1322E;EGYPTIAN HIEROGLYPH NL014;Lo;0;L;;;;;N;;;;; +1322F;EGYPTIAN HIEROGLYPH NL015;Lo;0;L;;;;;N;;;;; +13230;EGYPTIAN HIEROGLYPH NL016;Lo;0;L;;;;;N;;;;; +13231;EGYPTIAN HIEROGLYPH NL017;Lo;0;L;;;;;N;;;;; +13232;EGYPTIAN HIEROGLYPH NL017A;Lo;0;L;;;;;N;;;;; +13233;EGYPTIAN HIEROGLYPH NL018;Lo;0;L;;;;;N;;;;; +13234;EGYPTIAN HIEROGLYPH NL019;Lo;0;L;;;;;N;;;;; +13235;EGYPTIAN HIEROGLYPH NL020;Lo;0;L;;;;;N;;;;; +13236;EGYPTIAN HIEROGLYPH NU001;Lo;0;L;;;;;N;;;;; +13237;EGYPTIAN HIEROGLYPH NU002;Lo;0;L;;;;;N;;;;; +13238;EGYPTIAN HIEROGLYPH NU003;Lo;0;L;;;;;N;;;;; +13239;EGYPTIAN HIEROGLYPH NU004;Lo;0;L;;;;;N;;;;; +1323A;EGYPTIAN HIEROGLYPH NU005;Lo;0;L;;;;;N;;;;; +1323B;EGYPTIAN HIEROGLYPH NU006;Lo;0;L;;;;;N;;;;; +1323C;EGYPTIAN HIEROGLYPH NU007;Lo;0;L;;;;;N;;;;; +1323D;EGYPTIAN HIEROGLYPH NU008;Lo;0;L;;;;;N;;;;; +1323E;EGYPTIAN HIEROGLYPH NU009;Lo;0;L;;;;;N;;;;; +1323F;EGYPTIAN HIEROGLYPH NU010;Lo;0;L;;;;;N;;;;; +13240;EGYPTIAN HIEROGLYPH NU010A;Lo;0;L;;;;;N;;;;; +13241;EGYPTIAN HIEROGLYPH NU011;Lo;0;L;;;;;N;;;;; +13242;EGYPTIAN HIEROGLYPH NU011A;Lo;0;L;;;;;N;;;;; +13243;EGYPTIAN HIEROGLYPH NU012;Lo;0;L;;;;;N;;;;; +13244;EGYPTIAN HIEROGLYPH NU013;Lo;0;L;;;;;N;;;;; +13245;EGYPTIAN HIEROGLYPH NU014;Lo;0;L;;;;;N;;;;; +13246;EGYPTIAN HIEROGLYPH NU015;Lo;0;L;;;;;N;;;;; +13247;EGYPTIAN HIEROGLYPH NU016;Lo;0;L;;;;;N;;;;; +13248;EGYPTIAN HIEROGLYPH NU017;Lo;0;L;;;;;N;;;;; +13249;EGYPTIAN HIEROGLYPH NU018;Lo;0;L;;;;;N;;;;; +1324A;EGYPTIAN HIEROGLYPH NU018A;Lo;0;L;;;;;N;;;;; +1324B;EGYPTIAN HIEROGLYPH NU019;Lo;0;L;;;;;N;;;;; +1324C;EGYPTIAN HIEROGLYPH NU020;Lo;0;L;;;;;N;;;;; +1324D;EGYPTIAN HIEROGLYPH NU021;Lo;0;L;;;;;N;;;;; +1324E;EGYPTIAN HIEROGLYPH NU022;Lo;0;L;;;;;N;;;;; +1324F;EGYPTIAN HIEROGLYPH NU022A;Lo;0;L;;;;;N;;;;; +13250;EGYPTIAN HIEROGLYPH O001;Lo;0;L;;;;;N;;;;; +13251;EGYPTIAN HIEROGLYPH O001A;Lo;0;L;;;;;N;;;;; +13252;EGYPTIAN HIEROGLYPH O002;Lo;0;L;;;;;N;;;;; +13253;EGYPTIAN HIEROGLYPH O003;Lo;0;L;;;;;N;;;;; +13254;EGYPTIAN HIEROGLYPH O004;Lo;0;L;;;;;N;;;;; +13255;EGYPTIAN HIEROGLYPH O005;Lo;0;L;;;;;N;;;;; +13256;EGYPTIAN HIEROGLYPH O005A;Lo;0;L;;;;;N;;;;; +13257;EGYPTIAN HIEROGLYPH O006;Lo;0;L;;;;;N;;;;; +13258;EGYPTIAN HIEROGLYPH O006A;Lo;0;L;;;;;N;;;;; +13259;EGYPTIAN HIEROGLYPH O006B;Lo;0;L;;;;;N;;;;; +1325A;EGYPTIAN HIEROGLYPH O006C;Lo;0;L;;;;;N;;;;; +1325B;EGYPTIAN HIEROGLYPH O006D;Lo;0;L;;;;;N;;;;; +1325C;EGYPTIAN HIEROGLYPH O006E;Lo;0;L;;;;;N;;;;; +1325D;EGYPTIAN HIEROGLYPH O006F;Lo;0;L;;;;;N;;;;; +1325E;EGYPTIAN HIEROGLYPH O007;Lo;0;L;;;;;N;;;;; +1325F;EGYPTIAN HIEROGLYPH O008;Lo;0;L;;;;;N;;;;; +13260;EGYPTIAN HIEROGLYPH O009;Lo;0;L;;;;;N;;;;; +13261;EGYPTIAN HIEROGLYPH O010;Lo;0;L;;;;;N;;;;; +13262;EGYPTIAN HIEROGLYPH O010A;Lo;0;L;;;;;N;;;;; +13263;EGYPTIAN HIEROGLYPH O010B;Lo;0;L;;;;;N;;;;; +13264;EGYPTIAN HIEROGLYPH O010C;Lo;0;L;;;;;N;;;;; +13265;EGYPTIAN HIEROGLYPH O011;Lo;0;L;;;;;N;;;;; +13266;EGYPTIAN HIEROGLYPH O012;Lo;0;L;;;;;N;;;;; +13267;EGYPTIAN HIEROGLYPH O013;Lo;0;L;;;;;N;;;;; +13268;EGYPTIAN HIEROGLYPH O014;Lo;0;L;;;;;N;;;;; +13269;EGYPTIAN HIEROGLYPH O015;Lo;0;L;;;;;N;;;;; +1326A;EGYPTIAN HIEROGLYPH O016;Lo;0;L;;;;;N;;;;; +1326B;EGYPTIAN HIEROGLYPH O017;Lo;0;L;;;;;N;;;;; +1326C;EGYPTIAN HIEROGLYPH O018;Lo;0;L;;;;;N;;;;; +1326D;EGYPTIAN HIEROGLYPH O019;Lo;0;L;;;;;N;;;;; +1326E;EGYPTIAN HIEROGLYPH O019A;Lo;0;L;;;;;N;;;;; +1326F;EGYPTIAN HIEROGLYPH O020;Lo;0;L;;;;;N;;;;; +13270;EGYPTIAN HIEROGLYPH O020A;Lo;0;L;;;;;N;;;;; +13271;EGYPTIAN HIEROGLYPH O021;Lo;0;L;;;;;N;;;;; +13272;EGYPTIAN HIEROGLYPH O022;Lo;0;L;;;;;N;;;;; +13273;EGYPTIAN HIEROGLYPH O023;Lo;0;L;;;;;N;;;;; +13274;EGYPTIAN HIEROGLYPH O024;Lo;0;L;;;;;N;;;;; +13275;EGYPTIAN HIEROGLYPH O024A;Lo;0;L;;;;;N;;;;; +13276;EGYPTIAN HIEROGLYPH O025;Lo;0;L;;;;;N;;;;; +13277;EGYPTIAN HIEROGLYPH O025A;Lo;0;L;;;;;N;;;;; +13278;EGYPTIAN HIEROGLYPH O026;Lo;0;L;;;;;N;;;;; +13279;EGYPTIAN HIEROGLYPH O027;Lo;0;L;;;;;N;;;;; +1327A;EGYPTIAN HIEROGLYPH O028;Lo;0;L;;;;;N;;;;; +1327B;EGYPTIAN HIEROGLYPH O029;Lo;0;L;;;;;N;;;;; +1327C;EGYPTIAN HIEROGLYPH O029A;Lo;0;L;;;;;N;;;;; +1327D;EGYPTIAN HIEROGLYPH O030;Lo;0;L;;;;;N;;;;; +1327E;EGYPTIAN HIEROGLYPH O030A;Lo;0;L;;;;;N;;;;; +1327F;EGYPTIAN HIEROGLYPH O031;Lo;0;L;;;;;N;;;;; +13280;EGYPTIAN HIEROGLYPH O032;Lo;0;L;;;;;N;;;;; +13281;EGYPTIAN HIEROGLYPH O033;Lo;0;L;;;;;N;;;;; +13282;EGYPTIAN HIEROGLYPH O033A;Lo;0;L;;;;;N;;;;; +13283;EGYPTIAN HIEROGLYPH O034;Lo;0;L;;;;;N;;;;; +13284;EGYPTIAN HIEROGLYPH O035;Lo;0;L;;;;;N;;;;; +13285;EGYPTIAN HIEROGLYPH O036;Lo;0;L;;;;;N;;;;; +13286;EGYPTIAN HIEROGLYPH O036A;Lo;0;L;;;;;N;;;;; +13287;EGYPTIAN HIEROGLYPH O036B;Lo;0;L;;;;;N;;;;; +13288;EGYPTIAN HIEROGLYPH O036C;Lo;0;L;;;;;N;;;;; +13289;EGYPTIAN HIEROGLYPH O036D;Lo;0;L;;;;;N;;;;; +1328A;EGYPTIAN HIEROGLYPH O037;Lo;0;L;;;;;N;;;;; +1328B;EGYPTIAN HIEROGLYPH O038;Lo;0;L;;;;;N;;;;; +1328C;EGYPTIAN HIEROGLYPH O039;Lo;0;L;;;;;N;;;;; +1328D;EGYPTIAN HIEROGLYPH O040;Lo;0;L;;;;;N;;;;; +1328E;EGYPTIAN HIEROGLYPH O041;Lo;0;L;;;;;N;;;;; +1328F;EGYPTIAN HIEROGLYPH O042;Lo;0;L;;;;;N;;;;; +13290;EGYPTIAN HIEROGLYPH O043;Lo;0;L;;;;;N;;;;; +13291;EGYPTIAN HIEROGLYPH O044;Lo;0;L;;;;;N;;;;; +13292;EGYPTIAN HIEROGLYPH O045;Lo;0;L;;;;;N;;;;; +13293;EGYPTIAN HIEROGLYPH O046;Lo;0;L;;;;;N;;;;; +13294;EGYPTIAN HIEROGLYPH O047;Lo;0;L;;;;;N;;;;; +13295;EGYPTIAN HIEROGLYPH O048;Lo;0;L;;;;;N;;;;; +13296;EGYPTIAN HIEROGLYPH O049;Lo;0;L;;;;;N;;;;; +13297;EGYPTIAN HIEROGLYPH O050;Lo;0;L;;;;;N;;;;; +13298;EGYPTIAN HIEROGLYPH O050A;Lo;0;L;;;;;N;;;;; +13299;EGYPTIAN HIEROGLYPH O050B;Lo;0;L;;;;;N;;;;; +1329A;EGYPTIAN HIEROGLYPH O051;Lo;0;L;;;;;N;;;;; +1329B;EGYPTIAN HIEROGLYPH P001;Lo;0;L;;;;;N;;;;; +1329C;EGYPTIAN HIEROGLYPH P001A;Lo;0;L;;;;;N;;;;; +1329D;EGYPTIAN HIEROGLYPH P002;Lo;0;L;;;;;N;;;;; +1329E;EGYPTIAN HIEROGLYPH P003;Lo;0;L;;;;;N;;;;; +1329F;EGYPTIAN HIEROGLYPH P003A;Lo;0;L;;;;;N;;;;; +132A0;EGYPTIAN HIEROGLYPH P004;Lo;0;L;;;;;N;;;;; +132A1;EGYPTIAN HIEROGLYPH P005;Lo;0;L;;;;;N;;;;; +132A2;EGYPTIAN HIEROGLYPH P006;Lo;0;L;;;;;N;;;;; +132A3;EGYPTIAN HIEROGLYPH P007;Lo;0;L;;;;;N;;;;; +132A4;EGYPTIAN HIEROGLYPH P008;Lo;0;L;;;;;N;;;;; +132A5;EGYPTIAN HIEROGLYPH P009;Lo;0;L;;;;;N;;;;; +132A6;EGYPTIAN HIEROGLYPH P010;Lo;0;L;;;;;N;;;;; +132A7;EGYPTIAN HIEROGLYPH P011;Lo;0;L;;;;;N;;;;; +132A8;EGYPTIAN HIEROGLYPH Q001;Lo;0;L;;;;;N;;;;; +132A9;EGYPTIAN HIEROGLYPH Q002;Lo;0;L;;;;;N;;;;; +132AA;EGYPTIAN HIEROGLYPH Q003;Lo;0;L;;;;;N;;;;; +132AB;EGYPTIAN HIEROGLYPH Q004;Lo;0;L;;;;;N;;;;; +132AC;EGYPTIAN HIEROGLYPH Q005;Lo;0;L;;;;;N;;;;; +132AD;EGYPTIAN HIEROGLYPH Q006;Lo;0;L;;;;;N;;;;; +132AE;EGYPTIAN HIEROGLYPH Q007;Lo;0;L;;;;;N;;;;; +132AF;EGYPTIAN HIEROGLYPH R001;Lo;0;L;;;;;N;;;;; +132B0;EGYPTIAN HIEROGLYPH R002;Lo;0;L;;;;;N;;;;; +132B1;EGYPTIAN HIEROGLYPH R002A;Lo;0;L;;;;;N;;;;; +132B2;EGYPTIAN HIEROGLYPH R003;Lo;0;L;;;;;N;;;;; +132B3;EGYPTIAN HIEROGLYPH R003A;Lo;0;L;;;;;N;;;;; +132B4;EGYPTIAN HIEROGLYPH R003B;Lo;0;L;;;;;N;;;;; +132B5;EGYPTIAN HIEROGLYPH R004;Lo;0;L;;;;;N;;;;; +132B6;EGYPTIAN HIEROGLYPH R005;Lo;0;L;;;;;N;;;;; +132B7;EGYPTIAN HIEROGLYPH R006;Lo;0;L;;;;;N;;;;; +132B8;EGYPTIAN HIEROGLYPH R007;Lo;0;L;;;;;N;;;;; +132B9;EGYPTIAN HIEROGLYPH R008;Lo;0;L;;;;;N;;;;; +132BA;EGYPTIAN HIEROGLYPH R009;Lo;0;L;;;;;N;;;;; +132BB;EGYPTIAN HIEROGLYPH R010;Lo;0;L;;;;;N;;;;; +132BC;EGYPTIAN HIEROGLYPH R010A;Lo;0;L;;;;;N;;;;; +132BD;EGYPTIAN HIEROGLYPH R011;Lo;0;L;;;;;N;;;;; +132BE;EGYPTIAN HIEROGLYPH R012;Lo;0;L;;;;;N;;;;; +132BF;EGYPTIAN HIEROGLYPH R013;Lo;0;L;;;;;N;;;;; +132C0;EGYPTIAN HIEROGLYPH R014;Lo;0;L;;;;;N;;;;; +132C1;EGYPTIAN HIEROGLYPH R015;Lo;0;L;;;;;N;;;;; +132C2;EGYPTIAN HIEROGLYPH R016;Lo;0;L;;;;;N;;;;; +132C3;EGYPTIAN HIEROGLYPH R016A;Lo;0;L;;;;;N;;;;; +132C4;EGYPTIAN HIEROGLYPH R017;Lo;0;L;;;;;N;;;;; +132C5;EGYPTIAN HIEROGLYPH R018;Lo;0;L;;;;;N;;;;; +132C6;EGYPTIAN HIEROGLYPH R019;Lo;0;L;;;;;N;;;;; +132C7;EGYPTIAN HIEROGLYPH R020;Lo;0;L;;;;;N;;;;; +132C8;EGYPTIAN HIEROGLYPH R021;Lo;0;L;;;;;N;;;;; +132C9;EGYPTIAN HIEROGLYPH R022;Lo;0;L;;;;;N;;;;; +132CA;EGYPTIAN HIEROGLYPH R023;Lo;0;L;;;;;N;;;;; +132CB;EGYPTIAN HIEROGLYPH R024;Lo;0;L;;;;;N;;;;; +132CC;EGYPTIAN HIEROGLYPH R025;Lo;0;L;;;;;N;;;;; +132CD;EGYPTIAN HIEROGLYPH R026;Lo;0;L;;;;;N;;;;; +132CE;EGYPTIAN HIEROGLYPH R027;Lo;0;L;;;;;N;;;;; +132CF;EGYPTIAN HIEROGLYPH R028;Lo;0;L;;;;;N;;;;; +132D0;EGYPTIAN HIEROGLYPH R029;Lo;0;L;;;;;N;;;;; +132D1;EGYPTIAN HIEROGLYPH S001;Lo;0;L;;;;;N;;;;; +132D2;EGYPTIAN HIEROGLYPH S002;Lo;0;L;;;;;N;;;;; +132D3;EGYPTIAN HIEROGLYPH S002A;Lo;0;L;;;;;N;;;;; +132D4;EGYPTIAN HIEROGLYPH S003;Lo;0;L;;;;;N;;;;; +132D5;EGYPTIAN HIEROGLYPH S004;Lo;0;L;;;;;N;;;;; +132D6;EGYPTIAN HIEROGLYPH S005;Lo;0;L;;;;;N;;;;; +132D7;EGYPTIAN HIEROGLYPH S006;Lo;0;L;;;;;N;;;;; +132D8;EGYPTIAN HIEROGLYPH S006A;Lo;0;L;;;;;N;;;;; +132D9;EGYPTIAN HIEROGLYPH S007;Lo;0;L;;;;;N;;;;; +132DA;EGYPTIAN HIEROGLYPH S008;Lo;0;L;;;;;N;;;;; +132DB;EGYPTIAN HIEROGLYPH S009;Lo;0;L;;;;;N;;;;; +132DC;EGYPTIAN HIEROGLYPH S010;Lo;0;L;;;;;N;;;;; +132DD;EGYPTIAN HIEROGLYPH S011;Lo;0;L;;;;;N;;;;; +132DE;EGYPTIAN HIEROGLYPH S012;Lo;0;L;;;;;N;;;;; +132DF;EGYPTIAN HIEROGLYPH S013;Lo;0;L;;;;;N;;;;; +132E0;EGYPTIAN HIEROGLYPH S014;Lo;0;L;;;;;N;;;;; +132E1;EGYPTIAN HIEROGLYPH S014A;Lo;0;L;;;;;N;;;;; +132E2;EGYPTIAN HIEROGLYPH S014B;Lo;0;L;;;;;N;;;;; +132E3;EGYPTIAN HIEROGLYPH S015;Lo;0;L;;;;;N;;;;; +132E4;EGYPTIAN HIEROGLYPH S016;Lo;0;L;;;;;N;;;;; +132E5;EGYPTIAN HIEROGLYPH S017;Lo;0;L;;;;;N;;;;; +132E6;EGYPTIAN HIEROGLYPH S017A;Lo;0;L;;;;;N;;;;; +132E7;EGYPTIAN HIEROGLYPH S018;Lo;0;L;;;;;N;;;;; +132E8;EGYPTIAN HIEROGLYPH S019;Lo;0;L;;;;;N;;;;; +132E9;EGYPTIAN HIEROGLYPH S020;Lo;0;L;;;;;N;;;;; +132EA;EGYPTIAN HIEROGLYPH S021;Lo;0;L;;;;;N;;;;; +132EB;EGYPTIAN HIEROGLYPH S022;Lo;0;L;;;;;N;;;;; +132EC;EGYPTIAN HIEROGLYPH S023;Lo;0;L;;;;;N;;;;; +132ED;EGYPTIAN HIEROGLYPH S024;Lo;0;L;;;;;N;;;;; +132EE;EGYPTIAN HIEROGLYPH S025;Lo;0;L;;;;;N;;;;; +132EF;EGYPTIAN HIEROGLYPH S026;Lo;0;L;;;;;N;;;;; +132F0;EGYPTIAN HIEROGLYPH S026A;Lo;0;L;;;;;N;;;;; +132F1;EGYPTIAN HIEROGLYPH S026B;Lo;0;L;;;;;N;;;;; +132F2;EGYPTIAN HIEROGLYPH S027;Lo;0;L;;;;;N;;;;; +132F3;EGYPTIAN HIEROGLYPH S028;Lo;0;L;;;;;N;;;;; +132F4;EGYPTIAN HIEROGLYPH S029;Lo;0;L;;;;;N;;;;; +132F5;EGYPTIAN HIEROGLYPH S030;Lo;0;L;;;;;N;;;;; +132F6;EGYPTIAN HIEROGLYPH S031;Lo;0;L;;;;;N;;;;; +132F7;EGYPTIAN HIEROGLYPH S032;Lo;0;L;;;;;N;;;;; +132F8;EGYPTIAN HIEROGLYPH S033;Lo;0;L;;;;;N;;;;; +132F9;EGYPTIAN HIEROGLYPH S034;Lo;0;L;;;;;N;;;;; +132FA;EGYPTIAN HIEROGLYPH S035;Lo;0;L;;;;;N;;;;; +132FB;EGYPTIAN HIEROGLYPH S035A;Lo;0;L;;;;;N;;;;; +132FC;EGYPTIAN HIEROGLYPH S036;Lo;0;L;;;;;N;;;;; +132FD;EGYPTIAN HIEROGLYPH S037;Lo;0;L;;;;;N;;;;; +132FE;EGYPTIAN HIEROGLYPH S038;Lo;0;L;;;;;N;;;;; +132FF;EGYPTIAN HIEROGLYPH S039;Lo;0;L;;;;;N;;;;; +13300;EGYPTIAN HIEROGLYPH S040;Lo;0;L;;;;;N;;;;; +13301;EGYPTIAN HIEROGLYPH S041;Lo;0;L;;;;;N;;;;; +13302;EGYPTIAN HIEROGLYPH S042;Lo;0;L;;;;;N;;;;; +13303;EGYPTIAN HIEROGLYPH S043;Lo;0;L;;;;;N;;;;; +13304;EGYPTIAN HIEROGLYPH S044;Lo;0;L;;;;;N;;;;; +13305;EGYPTIAN HIEROGLYPH S045;Lo;0;L;;;;;N;;;;; +13306;EGYPTIAN HIEROGLYPH S046;Lo;0;L;;;;;N;;;;; +13307;EGYPTIAN HIEROGLYPH T001;Lo;0;L;;;;;N;;;;; +13308;EGYPTIAN HIEROGLYPH T002;Lo;0;L;;;;;N;;;;; +13309;EGYPTIAN HIEROGLYPH T003;Lo;0;L;;;;;N;;;;; +1330A;EGYPTIAN HIEROGLYPH T003A;Lo;0;L;;;;;N;;;;; +1330B;EGYPTIAN HIEROGLYPH T004;Lo;0;L;;;;;N;;;;; +1330C;EGYPTIAN HIEROGLYPH T005;Lo;0;L;;;;;N;;;;; +1330D;EGYPTIAN HIEROGLYPH T006;Lo;0;L;;;;;N;;;;; +1330E;EGYPTIAN HIEROGLYPH T007;Lo;0;L;;;;;N;;;;; +1330F;EGYPTIAN HIEROGLYPH T007A;Lo;0;L;;;;;N;;;;; +13310;EGYPTIAN HIEROGLYPH T008;Lo;0;L;;;;;N;;;;; +13311;EGYPTIAN HIEROGLYPH T008A;Lo;0;L;;;;;N;;;;; +13312;EGYPTIAN HIEROGLYPH T009;Lo;0;L;;;;;N;;;;; +13313;EGYPTIAN HIEROGLYPH T009A;Lo;0;L;;;;;N;;;;; +13314;EGYPTIAN HIEROGLYPH T010;Lo;0;L;;;;;N;;;;; +13315;EGYPTIAN HIEROGLYPH T011;Lo;0;L;;;;;N;;;;; +13316;EGYPTIAN HIEROGLYPH T011A;Lo;0;L;;;;;N;;;;; +13317;EGYPTIAN HIEROGLYPH T012;Lo;0;L;;;;;N;;;;; +13318;EGYPTIAN HIEROGLYPH T013;Lo;0;L;;;;;N;;;;; +13319;EGYPTIAN HIEROGLYPH T014;Lo;0;L;;;;;N;;;;; +1331A;EGYPTIAN HIEROGLYPH T015;Lo;0;L;;;;;N;;;;; +1331B;EGYPTIAN HIEROGLYPH T016;Lo;0;L;;;;;N;;;;; +1331C;EGYPTIAN HIEROGLYPH T016A;Lo;0;L;;;;;N;;;;; +1331D;EGYPTIAN HIEROGLYPH T017;Lo;0;L;;;;;N;;;;; +1331E;EGYPTIAN HIEROGLYPH T018;Lo;0;L;;;;;N;;;;; +1331F;EGYPTIAN HIEROGLYPH T019;Lo;0;L;;;;;N;;;;; +13320;EGYPTIAN HIEROGLYPH T020;Lo;0;L;;;;;N;;;;; +13321;EGYPTIAN HIEROGLYPH T021;Lo;0;L;;;;;N;;;;; +13322;EGYPTIAN HIEROGLYPH T022;Lo;0;L;;;;;N;;;;; +13323;EGYPTIAN HIEROGLYPH T023;Lo;0;L;;;;;N;;;;; +13324;EGYPTIAN HIEROGLYPH T024;Lo;0;L;;;;;N;;;;; +13325;EGYPTIAN HIEROGLYPH T025;Lo;0;L;;;;;N;;;;; +13326;EGYPTIAN HIEROGLYPH T026;Lo;0;L;;;;;N;;;;; +13327;EGYPTIAN HIEROGLYPH T027;Lo;0;L;;;;;N;;;;; +13328;EGYPTIAN HIEROGLYPH T028;Lo;0;L;;;;;N;;;;; +13329;EGYPTIAN HIEROGLYPH T029;Lo;0;L;;;;;N;;;;; +1332A;EGYPTIAN HIEROGLYPH T030;Lo;0;L;;;;;N;;;;; +1332B;EGYPTIAN HIEROGLYPH T031;Lo;0;L;;;;;N;;;;; +1332C;EGYPTIAN HIEROGLYPH T032;Lo;0;L;;;;;N;;;;; +1332D;EGYPTIAN HIEROGLYPH T032A;Lo;0;L;;;;;N;;;;; +1332E;EGYPTIAN HIEROGLYPH T033;Lo;0;L;;;;;N;;;;; +1332F;EGYPTIAN HIEROGLYPH T033A;Lo;0;L;;;;;N;;;;; +13330;EGYPTIAN HIEROGLYPH T034;Lo;0;L;;;;;N;;;;; +13331;EGYPTIAN HIEROGLYPH T035;Lo;0;L;;;;;N;;;;; +13332;EGYPTIAN HIEROGLYPH T036;Lo;0;L;;;;;N;;;;; +13333;EGYPTIAN HIEROGLYPH U001;Lo;0;L;;;;;N;;;;; +13334;EGYPTIAN HIEROGLYPH U002;Lo;0;L;;;;;N;;;;; +13335;EGYPTIAN HIEROGLYPH U003;Lo;0;L;;;;;N;;;;; +13336;EGYPTIAN HIEROGLYPH U004;Lo;0;L;;;;;N;;;;; +13337;EGYPTIAN HIEROGLYPH U005;Lo;0;L;;;;;N;;;;; +13338;EGYPTIAN HIEROGLYPH U006;Lo;0;L;;;;;N;;;;; +13339;EGYPTIAN HIEROGLYPH U006A;Lo;0;L;;;;;N;;;;; +1333A;EGYPTIAN HIEROGLYPH U006B;Lo;0;L;;;;;N;;;;; +1333B;EGYPTIAN HIEROGLYPH U007;Lo;0;L;;;;;N;;;;; +1333C;EGYPTIAN HIEROGLYPH U008;Lo;0;L;;;;;N;;;;; +1333D;EGYPTIAN HIEROGLYPH U009;Lo;0;L;;;;;N;;;;; +1333E;EGYPTIAN HIEROGLYPH U010;Lo;0;L;;;;;N;;;;; +1333F;EGYPTIAN HIEROGLYPH U011;Lo;0;L;;;;;N;;;;; +13340;EGYPTIAN HIEROGLYPH U012;Lo;0;L;;;;;N;;;;; +13341;EGYPTIAN HIEROGLYPH U013;Lo;0;L;;;;;N;;;;; +13342;EGYPTIAN HIEROGLYPH U014;Lo;0;L;;;;;N;;;;; +13343;EGYPTIAN HIEROGLYPH U015;Lo;0;L;;;;;N;;;;; +13344;EGYPTIAN HIEROGLYPH U016;Lo;0;L;;;;;N;;;;; +13345;EGYPTIAN HIEROGLYPH U017;Lo;0;L;;;;;N;;;;; +13346;EGYPTIAN HIEROGLYPH U018;Lo;0;L;;;;;N;;;;; +13347;EGYPTIAN HIEROGLYPH U019;Lo;0;L;;;;;N;;;;; +13348;EGYPTIAN HIEROGLYPH U020;Lo;0;L;;;;;N;;;;; +13349;EGYPTIAN HIEROGLYPH U021;Lo;0;L;;;;;N;;;;; +1334A;EGYPTIAN HIEROGLYPH U022;Lo;0;L;;;;;N;;;;; +1334B;EGYPTIAN HIEROGLYPH U023;Lo;0;L;;;;;N;;;;; +1334C;EGYPTIAN HIEROGLYPH U023A;Lo;0;L;;;;;N;;;;; +1334D;EGYPTIAN HIEROGLYPH U024;Lo;0;L;;;;;N;;;;; +1334E;EGYPTIAN HIEROGLYPH U025;Lo;0;L;;;;;N;;;;; +1334F;EGYPTIAN HIEROGLYPH U026;Lo;0;L;;;;;N;;;;; +13350;EGYPTIAN HIEROGLYPH U027;Lo;0;L;;;;;N;;;;; +13351;EGYPTIAN HIEROGLYPH U028;Lo;0;L;;;;;N;;;;; +13352;EGYPTIAN HIEROGLYPH U029;Lo;0;L;;;;;N;;;;; +13353;EGYPTIAN HIEROGLYPH U029A;Lo;0;L;;;;;N;;;;; +13354;EGYPTIAN HIEROGLYPH U030;Lo;0;L;;;;;N;;;;; +13355;EGYPTIAN HIEROGLYPH U031;Lo;0;L;;;;;N;;;;; +13356;EGYPTIAN HIEROGLYPH U032;Lo;0;L;;;;;N;;;;; +13357;EGYPTIAN HIEROGLYPH U032A;Lo;0;L;;;;;N;;;;; +13358;EGYPTIAN HIEROGLYPH U033;Lo;0;L;;;;;N;;;;; +13359;EGYPTIAN HIEROGLYPH U034;Lo;0;L;;;;;N;;;;; +1335A;EGYPTIAN HIEROGLYPH U035;Lo;0;L;;;;;N;;;;; +1335B;EGYPTIAN HIEROGLYPH U036;Lo;0;L;;;;;N;;;;; +1335C;EGYPTIAN HIEROGLYPH U037;Lo;0;L;;;;;N;;;;; +1335D;EGYPTIAN HIEROGLYPH U038;Lo;0;L;;;;;N;;;;; +1335E;EGYPTIAN HIEROGLYPH U039;Lo;0;L;;;;;N;;;;; +1335F;EGYPTIAN HIEROGLYPH U040;Lo;0;L;;;;;N;;;;; +13360;EGYPTIAN HIEROGLYPH U041;Lo;0;L;;;;;N;;;;; +13361;EGYPTIAN HIEROGLYPH U042;Lo;0;L;;;;;N;;;;; +13362;EGYPTIAN HIEROGLYPH V001;Lo;0;L;;;;;N;;;;; +13363;EGYPTIAN HIEROGLYPH V001A;Lo;0;L;;;;;N;;;;; +13364;EGYPTIAN HIEROGLYPH V001B;Lo;0;L;;;;;N;;;;; +13365;EGYPTIAN HIEROGLYPH V001C;Lo;0;L;;;;;N;;;;; +13366;EGYPTIAN HIEROGLYPH V001D;Lo;0;L;;;;;N;;;;; +13367;EGYPTIAN HIEROGLYPH V001E;Lo;0;L;;;;;N;;;;; +13368;EGYPTIAN HIEROGLYPH V001F;Lo;0;L;;;;;N;;;;; +13369;EGYPTIAN HIEROGLYPH V001G;Lo;0;L;;;;;N;;;;; +1336A;EGYPTIAN HIEROGLYPH V001H;Lo;0;L;;;;;N;;;;; +1336B;EGYPTIAN HIEROGLYPH V001I;Lo;0;L;;;;;N;;;;; +1336C;EGYPTIAN HIEROGLYPH V002;Lo;0;L;;;;;N;;;;; +1336D;EGYPTIAN HIEROGLYPH V002A;Lo;0;L;;;;;N;;;;; +1336E;EGYPTIAN HIEROGLYPH V003;Lo;0;L;;;;;N;;;;; +1336F;EGYPTIAN HIEROGLYPH V004;Lo;0;L;;;;;N;;;;; +13370;EGYPTIAN HIEROGLYPH V005;Lo;0;L;;;;;N;;;;; +13371;EGYPTIAN HIEROGLYPH V006;Lo;0;L;;;;;N;;;;; +13372;EGYPTIAN HIEROGLYPH V007;Lo;0;L;;;;;N;;;;; +13373;EGYPTIAN HIEROGLYPH V007A;Lo;0;L;;;;;N;;;;; +13374;EGYPTIAN HIEROGLYPH V007B;Lo;0;L;;;;;N;;;;; +13375;EGYPTIAN HIEROGLYPH V008;Lo;0;L;;;;;N;;;;; +13376;EGYPTIAN HIEROGLYPH V009;Lo;0;L;;;;;N;;;;; +13377;EGYPTIAN HIEROGLYPH V010;Lo;0;L;;;;;N;;;;; +13378;EGYPTIAN HIEROGLYPH V011;Lo;0;L;;;;;N;;;;; +13379;EGYPTIAN HIEROGLYPH V011A;Lo;0;L;;;;;N;;;;; +1337A;EGYPTIAN HIEROGLYPH V011B;Lo;0;L;;;;;N;;;;; +1337B;EGYPTIAN HIEROGLYPH V011C;Lo;0;L;;;;;N;;;;; +1337C;EGYPTIAN HIEROGLYPH V012;Lo;0;L;;;;;N;;;;; +1337D;EGYPTIAN HIEROGLYPH V012A;Lo;0;L;;;;;N;;;;; +1337E;EGYPTIAN HIEROGLYPH V012B;Lo;0;L;;;;;N;;;;; +1337F;EGYPTIAN HIEROGLYPH V013;Lo;0;L;;;;;N;;;;; +13380;EGYPTIAN HIEROGLYPH V014;Lo;0;L;;;;;N;;;;; +13381;EGYPTIAN HIEROGLYPH V015;Lo;0;L;;;;;N;;;;; +13382;EGYPTIAN HIEROGLYPH V016;Lo;0;L;;;;;N;;;;; +13383;EGYPTIAN HIEROGLYPH V017;Lo;0;L;;;;;N;;;;; +13384;EGYPTIAN HIEROGLYPH V018;Lo;0;L;;;;;N;;;;; +13385;EGYPTIAN HIEROGLYPH V019;Lo;0;L;;;;;N;;;;; +13386;EGYPTIAN HIEROGLYPH V020;Lo;0;L;;;;;N;;;;; +13387;EGYPTIAN HIEROGLYPH V020A;Lo;0;L;;;;;N;;;;; +13388;EGYPTIAN HIEROGLYPH V020B;Lo;0;L;;;;;N;;;;; +13389;EGYPTIAN HIEROGLYPH V020C;Lo;0;L;;;;;N;;;;; +1338A;EGYPTIAN HIEROGLYPH V020D;Lo;0;L;;;;;N;;;;; +1338B;EGYPTIAN HIEROGLYPH V020E;Lo;0;L;;;;;N;;;;; +1338C;EGYPTIAN HIEROGLYPH V020F;Lo;0;L;;;;;N;;;;; +1338D;EGYPTIAN HIEROGLYPH V020G;Lo;0;L;;;;;N;;;;; +1338E;EGYPTIAN HIEROGLYPH V020H;Lo;0;L;;;;;N;;;;; +1338F;EGYPTIAN HIEROGLYPH V020I;Lo;0;L;;;;;N;;;;; +13390;EGYPTIAN HIEROGLYPH V020J;Lo;0;L;;;;;N;;;;; +13391;EGYPTIAN HIEROGLYPH V020K;Lo;0;L;;;;;N;;;;; +13392;EGYPTIAN HIEROGLYPH V020L;Lo;0;L;;;;;N;;;;; +13393;EGYPTIAN HIEROGLYPH V021;Lo;0;L;;;;;N;;;;; +13394;EGYPTIAN HIEROGLYPH V022;Lo;0;L;;;;;N;;;;; +13395;EGYPTIAN HIEROGLYPH V023;Lo;0;L;;;;;N;;;;; +13396;EGYPTIAN HIEROGLYPH V023A;Lo;0;L;;;;;N;;;;; +13397;EGYPTIAN HIEROGLYPH V024;Lo;0;L;;;;;N;;;;; +13398;EGYPTIAN HIEROGLYPH V025;Lo;0;L;;;;;N;;;;; +13399;EGYPTIAN HIEROGLYPH V026;Lo;0;L;;;;;N;;;;; +1339A;EGYPTIAN HIEROGLYPH V027;Lo;0;L;;;;;N;;;;; +1339B;EGYPTIAN HIEROGLYPH V028;Lo;0;L;;;;;N;;;;; +1339C;EGYPTIAN HIEROGLYPH V028A;Lo;0;L;;;;;N;;;;; +1339D;EGYPTIAN HIEROGLYPH V029;Lo;0;L;;;;;N;;;;; +1339E;EGYPTIAN HIEROGLYPH V029A;Lo;0;L;;;;;N;;;;; +1339F;EGYPTIAN HIEROGLYPH V030;Lo;0;L;;;;;N;;;;; +133A0;EGYPTIAN HIEROGLYPH V030A;Lo;0;L;;;;;N;;;;; +133A1;EGYPTIAN HIEROGLYPH V031;Lo;0;L;;;;;N;;;;; +133A2;EGYPTIAN HIEROGLYPH V031A;Lo;0;L;;;;;N;;;;; +133A3;EGYPTIAN HIEROGLYPH V032;Lo;0;L;;;;;N;;;;; +133A4;EGYPTIAN HIEROGLYPH V033;Lo;0;L;;;;;N;;;;; +133A5;EGYPTIAN HIEROGLYPH V033A;Lo;0;L;;;;;N;;;;; +133A6;EGYPTIAN HIEROGLYPH V034;Lo;0;L;;;;;N;;;;; +133A7;EGYPTIAN HIEROGLYPH V035;Lo;0;L;;;;;N;;;;; +133A8;EGYPTIAN HIEROGLYPH V036;Lo;0;L;;;;;N;;;;; +133A9;EGYPTIAN HIEROGLYPH V037;Lo;0;L;;;;;N;;;;; +133AA;EGYPTIAN HIEROGLYPH V037A;Lo;0;L;;;;;N;;;;; +133AB;EGYPTIAN HIEROGLYPH V038;Lo;0;L;;;;;N;;;;; +133AC;EGYPTIAN HIEROGLYPH V039;Lo;0;L;;;;;N;;;;; +133AD;EGYPTIAN HIEROGLYPH V040;Lo;0;L;;;;;N;;;;; +133AE;EGYPTIAN HIEROGLYPH V040A;Lo;0;L;;;;;N;;;;; +133AF;EGYPTIAN HIEROGLYPH W001;Lo;0;L;;;;;N;;;;; +133B0;EGYPTIAN HIEROGLYPH W002;Lo;0;L;;;;;N;;;;; +133B1;EGYPTIAN HIEROGLYPH W003;Lo;0;L;;;;;N;;;;; +133B2;EGYPTIAN HIEROGLYPH W003A;Lo;0;L;;;;;N;;;;; +133B3;EGYPTIAN HIEROGLYPH W004;Lo;0;L;;;;;N;;;;; +133B4;EGYPTIAN HIEROGLYPH W005;Lo;0;L;;;;;N;;;;; +133B5;EGYPTIAN HIEROGLYPH W006;Lo;0;L;;;;;N;;;;; +133B6;EGYPTIAN HIEROGLYPH W007;Lo;0;L;;;;;N;;;;; +133B7;EGYPTIAN HIEROGLYPH W008;Lo;0;L;;;;;N;;;;; +133B8;EGYPTIAN HIEROGLYPH W009;Lo;0;L;;;;;N;;;;; +133B9;EGYPTIAN HIEROGLYPH W009A;Lo;0;L;;;;;N;;;;; +133BA;EGYPTIAN HIEROGLYPH W010;Lo;0;L;;;;;N;;;;; +133BB;EGYPTIAN HIEROGLYPH W010A;Lo;0;L;;;;;N;;;;; +133BC;EGYPTIAN HIEROGLYPH W011;Lo;0;L;;;;;N;;;;; +133BD;EGYPTIAN HIEROGLYPH W012;Lo;0;L;;;;;N;;;;; +133BE;EGYPTIAN HIEROGLYPH W013;Lo;0;L;;;;;N;;;;; +133BF;EGYPTIAN HIEROGLYPH W014;Lo;0;L;;;;;N;;;;; +133C0;EGYPTIAN HIEROGLYPH W014A;Lo;0;L;;;;;N;;;;; +133C1;EGYPTIAN HIEROGLYPH W015;Lo;0;L;;;;;N;;;;; +133C2;EGYPTIAN HIEROGLYPH W016;Lo;0;L;;;;;N;;;;; +133C3;EGYPTIAN HIEROGLYPH W017;Lo;0;L;;;;;N;;;;; +133C4;EGYPTIAN HIEROGLYPH W017A;Lo;0;L;;;;;N;;;;; +133C5;EGYPTIAN HIEROGLYPH W018;Lo;0;L;;;;;N;;;;; +133C6;EGYPTIAN HIEROGLYPH W018A;Lo;0;L;;;;;N;;;;; +133C7;EGYPTIAN HIEROGLYPH W019;Lo;0;L;;;;;N;;;;; +133C8;EGYPTIAN HIEROGLYPH W020;Lo;0;L;;;;;N;;;;; +133C9;EGYPTIAN HIEROGLYPH W021;Lo;0;L;;;;;N;;;;; +133CA;EGYPTIAN HIEROGLYPH W022;Lo;0;L;;;;;N;;;;; +133CB;EGYPTIAN HIEROGLYPH W023;Lo;0;L;;;;;N;;;;; +133CC;EGYPTIAN HIEROGLYPH W024;Lo;0;L;;;;;N;;;;; +133CD;EGYPTIAN HIEROGLYPH W024A;Lo;0;L;;;;;N;;;;; +133CE;EGYPTIAN HIEROGLYPH W025;Lo;0;L;;;;;N;;;;; +133CF;EGYPTIAN HIEROGLYPH X001;Lo;0;L;;;;;N;;;;; +133D0;EGYPTIAN HIEROGLYPH X002;Lo;0;L;;;;;N;;;;; +133D1;EGYPTIAN HIEROGLYPH X003;Lo;0;L;;;;;N;;;;; +133D2;EGYPTIAN HIEROGLYPH X004;Lo;0;L;;;;;N;;;;; +133D3;EGYPTIAN HIEROGLYPH X004A;Lo;0;L;;;;;N;;;;; +133D4;EGYPTIAN HIEROGLYPH X004B;Lo;0;L;;;;;N;;;;; +133D5;EGYPTIAN HIEROGLYPH X005;Lo;0;L;;;;;N;;;;; +133D6;EGYPTIAN HIEROGLYPH X006;Lo;0;L;;;;;N;;;;; +133D7;EGYPTIAN HIEROGLYPH X006A;Lo;0;L;;;;;N;;;;; +133D8;EGYPTIAN HIEROGLYPH X007;Lo;0;L;;;;;N;;;;; +133D9;EGYPTIAN HIEROGLYPH X008;Lo;0;L;;;;;N;;;;; +133DA;EGYPTIAN HIEROGLYPH X008A;Lo;0;L;;;;;N;;;;; +133DB;EGYPTIAN HIEROGLYPH Y001;Lo;0;L;;;;;N;;;;; +133DC;EGYPTIAN HIEROGLYPH Y001A;Lo;0;L;;;;;N;;;;; +133DD;EGYPTIAN HIEROGLYPH Y002;Lo;0;L;;;;;N;;;;; +133DE;EGYPTIAN HIEROGLYPH Y003;Lo;0;L;;;;;N;;;;; +133DF;EGYPTIAN HIEROGLYPH Y004;Lo;0;L;;;;;N;;;;; +133E0;EGYPTIAN HIEROGLYPH Y005;Lo;0;L;;;;;N;;;;; +133E1;EGYPTIAN HIEROGLYPH Y006;Lo;0;L;;;;;N;;;;; +133E2;EGYPTIAN HIEROGLYPH Y007;Lo;0;L;;;;;N;;;;; +133E3;EGYPTIAN HIEROGLYPH Y008;Lo;0;L;;;;;N;;;;; +133E4;EGYPTIAN HIEROGLYPH Z001;Lo;0;L;;;;;N;;;;; +133E5;EGYPTIAN HIEROGLYPH Z002;Lo;0;L;;;;;N;;;;; +133E6;EGYPTIAN HIEROGLYPH Z002A;Lo;0;L;;;;;N;;;;; +133E7;EGYPTIAN HIEROGLYPH Z002B;Lo;0;L;;;;;N;;;;; +133E8;EGYPTIAN HIEROGLYPH Z002C;Lo;0;L;;;;;N;;;;; +133E9;EGYPTIAN HIEROGLYPH Z002D;Lo;0;L;;;;;N;;;;; +133EA;EGYPTIAN HIEROGLYPH Z003;Lo;0;L;;;;;N;;;;; +133EB;EGYPTIAN HIEROGLYPH Z003A;Lo;0;L;;;;;N;;;;; +133EC;EGYPTIAN HIEROGLYPH Z003B;Lo;0;L;;;;;N;;;;; +133ED;EGYPTIAN HIEROGLYPH Z004;Lo;0;L;;;;;N;;;;; +133EE;EGYPTIAN HIEROGLYPH Z004A;Lo;0;L;;;;;N;;;;; +133EF;EGYPTIAN HIEROGLYPH Z005;Lo;0;L;;;;;N;;;;; +133F0;EGYPTIAN HIEROGLYPH Z005A;Lo;0;L;;;;;N;;;;; +133F1;EGYPTIAN HIEROGLYPH Z006;Lo;0;L;;;;;N;;;;; +133F2;EGYPTIAN HIEROGLYPH Z007;Lo;0;L;;;;;N;;;;; +133F3;EGYPTIAN HIEROGLYPH Z008;Lo;0;L;;;;;N;;;;; +133F4;EGYPTIAN HIEROGLYPH Z009;Lo;0;L;;;;;N;;;;; +133F5;EGYPTIAN HIEROGLYPH Z010;Lo;0;L;;;;;N;;;;; +133F6;EGYPTIAN HIEROGLYPH Z011;Lo;0;L;;;;;N;;;;; +133F7;EGYPTIAN HIEROGLYPH Z012;Lo;0;L;;;;;N;;;;; +133F8;EGYPTIAN HIEROGLYPH Z013;Lo;0;L;;;;;N;;;;; +133F9;EGYPTIAN HIEROGLYPH Z014;Lo;0;L;;;;;N;;;;; +133FA;EGYPTIAN HIEROGLYPH Z015;Lo;0;L;;;;;N;;;;; +133FB;EGYPTIAN HIEROGLYPH Z015A;Lo;0;L;;;;;N;;;;; +133FC;EGYPTIAN HIEROGLYPH Z015B;Lo;0;L;;;;;N;;;;; +133FD;EGYPTIAN HIEROGLYPH Z015C;Lo;0;L;;;;;N;;;;; +133FE;EGYPTIAN HIEROGLYPH Z015D;Lo;0;L;;;;;N;;;;; +133FF;EGYPTIAN HIEROGLYPH Z015E;Lo;0;L;;;;;N;;;;; +13400;EGYPTIAN HIEROGLYPH Z015F;Lo;0;L;;;;;N;;;;; +13401;EGYPTIAN HIEROGLYPH Z015G;Lo;0;L;;;;;N;;;;; +13402;EGYPTIAN HIEROGLYPH Z015H;Lo;0;L;;;;;N;;;;; +13403;EGYPTIAN HIEROGLYPH Z015I;Lo;0;L;;;;;N;;;;; +13404;EGYPTIAN HIEROGLYPH Z016;Lo;0;L;;;;;N;;;;; +13405;EGYPTIAN HIEROGLYPH Z016A;Lo;0;L;;;;;N;;;;; +13406;EGYPTIAN HIEROGLYPH Z016B;Lo;0;L;;;;;N;;;;; +13407;EGYPTIAN HIEROGLYPH Z016C;Lo;0;L;;;;;N;;;;; +13408;EGYPTIAN HIEROGLYPH Z016D;Lo;0;L;;;;;N;;;;; +13409;EGYPTIAN HIEROGLYPH Z016E;Lo;0;L;;;;;N;;;;; +1340A;EGYPTIAN HIEROGLYPH Z016F;Lo;0;L;;;;;N;;;;; +1340B;EGYPTIAN HIEROGLYPH Z016G;Lo;0;L;;;;;N;;;;; +1340C;EGYPTIAN HIEROGLYPH Z016H;Lo;0;L;;;;;N;;;;; +1340D;EGYPTIAN HIEROGLYPH AA001;Lo;0;L;;;;;N;;;;; +1340E;EGYPTIAN HIEROGLYPH AA002;Lo;0;L;;;;;N;;;;; +1340F;EGYPTIAN HIEROGLYPH AA003;Lo;0;L;;;;;N;;;;; +13410;EGYPTIAN HIEROGLYPH AA004;Lo;0;L;;;;;N;;;;; +13411;EGYPTIAN HIEROGLYPH AA005;Lo;0;L;;;;;N;;;;; +13412;EGYPTIAN HIEROGLYPH AA006;Lo;0;L;;;;;N;;;;; +13413;EGYPTIAN HIEROGLYPH AA007;Lo;0;L;;;;;N;;;;; +13414;EGYPTIAN HIEROGLYPH AA007A;Lo;0;L;;;;;N;;;;; +13415;EGYPTIAN HIEROGLYPH AA007B;Lo;0;L;;;;;N;;;;; +13416;EGYPTIAN HIEROGLYPH AA008;Lo;0;L;;;;;N;;;;; +13417;EGYPTIAN HIEROGLYPH AA009;Lo;0;L;;;;;N;;;;; +13418;EGYPTIAN HIEROGLYPH AA010;Lo;0;L;;;;;N;;;;; +13419;EGYPTIAN HIEROGLYPH AA011;Lo;0;L;;;;;N;;;;; +1341A;EGYPTIAN HIEROGLYPH AA012;Lo;0;L;;;;;N;;;;; +1341B;EGYPTIAN HIEROGLYPH AA013;Lo;0;L;;;;;N;;;;; +1341C;EGYPTIAN HIEROGLYPH AA014;Lo;0;L;;;;;N;;;;; +1341D;EGYPTIAN HIEROGLYPH AA015;Lo;0;L;;;;;N;;;;; +1341E;EGYPTIAN HIEROGLYPH AA016;Lo;0;L;;;;;N;;;;; +1341F;EGYPTIAN HIEROGLYPH AA017;Lo;0;L;;;;;N;;;;; +13420;EGYPTIAN HIEROGLYPH AA018;Lo;0;L;;;;;N;;;;; +13421;EGYPTIAN HIEROGLYPH AA019;Lo;0;L;;;;;N;;;;; +13422;EGYPTIAN HIEROGLYPH AA020;Lo;0;L;;;;;N;;;;; +13423;EGYPTIAN HIEROGLYPH AA021;Lo;0;L;;;;;N;;;;; +13424;EGYPTIAN HIEROGLYPH AA022;Lo;0;L;;;;;N;;;;; +13425;EGYPTIAN HIEROGLYPH AA023;Lo;0;L;;;;;N;;;;; +13426;EGYPTIAN HIEROGLYPH AA024;Lo;0;L;;;;;N;;;;; +13427;EGYPTIAN HIEROGLYPH AA025;Lo;0;L;;;;;N;;;;; +13428;EGYPTIAN HIEROGLYPH AA026;Lo;0;L;;;;;N;;;;; +13429;EGYPTIAN HIEROGLYPH AA027;Lo;0;L;;;;;N;;;;; +1342A;EGYPTIAN HIEROGLYPH AA028;Lo;0;L;;;;;N;;;;; +1342B;EGYPTIAN HIEROGLYPH AA029;Lo;0;L;;;;;N;;;;; +1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;; +1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;; +1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;; +14400;ANATOLIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; +14401;ANATOLIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; +14402;ANATOLIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; +14403;ANATOLIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;; +14404;ANATOLIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;; +14405;ANATOLIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;; +14406;ANATOLIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;; +14407;ANATOLIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;; +14408;ANATOLIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;; +14409;ANATOLIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;; +1440A;ANATOLIAN HIEROGLYPH A010A;Lo;0;L;;;;;N;;;;; +1440B;ANATOLIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;; +1440C;ANATOLIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;; +1440D;ANATOLIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;; +1440E;ANATOLIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;; +1440F;ANATOLIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;; +14410;ANATOLIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;; +14411;ANATOLIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;; +14412;ANATOLIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;; +14413;ANATOLIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;; +14414;ANATOLIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;; +14415;ANATOLIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;; +14416;ANATOLIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;; +14417;ANATOLIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;; +14418;ANATOLIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;; +14419;ANATOLIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;; +1441A;ANATOLIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;; +1441B;ANATOLIAN HIEROGLYPH A026A;Lo;0;L;;;;;N;;;;; +1441C;ANATOLIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;; +1441D;ANATOLIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;; +1441E;ANATOLIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;; +1441F;ANATOLIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;; +14420;ANATOLIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;; +14421;ANATOLIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;; +14422;ANATOLIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;; +14423;ANATOLIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;; +14424;ANATOLIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;; +14425;ANATOLIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;; +14426;ANATOLIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;; +14427;ANATOLIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;; +14428;ANATOLIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;; +14429;ANATOLIAN HIEROGLYPH A039A;Lo;0;L;;;;;N;;;;; +1442A;ANATOLIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;; +1442B;ANATOLIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;; +1442C;ANATOLIAN HIEROGLYPH A041A;Lo;0;L;;;;;N;;;;; +1442D;ANATOLIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;; +1442E;ANATOLIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;; +1442F;ANATOLIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;; +14430;ANATOLIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;; +14431;ANATOLIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;; +14432;ANATOLIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;; +14433;ANATOLIAN HIEROGLYPH A046A;Lo;0;L;;;;;N;;;;; +14434;ANATOLIAN HIEROGLYPH A046B;Lo;0;L;;;;;N;;;;; +14435;ANATOLIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;; +14436;ANATOLIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;; +14437;ANATOLIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;; +14438;ANATOLIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;; +14439;ANATOLIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;; +1443A;ANATOLIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;; +1443B;ANATOLIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;; +1443C;ANATOLIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;; +1443D;ANATOLIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;; +1443E;ANATOLIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;; +1443F;ANATOLIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;; +14440;ANATOLIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;; +14441;ANATOLIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;; +14442;ANATOLIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;; +14443;ANATOLIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;; +14444;ANATOLIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;; +14445;ANATOLIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;; +14446;ANATOLIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;; +14447;ANATOLIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;; +14448;ANATOLIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;; +14449;ANATOLIAN HIEROGLYPH A066A;Lo;0;L;;;;;N;;;;; +1444A;ANATOLIAN HIEROGLYPH A066B;Lo;0;L;;;;;N;;;;; +1444B;ANATOLIAN HIEROGLYPH A066C;Lo;0;L;;;;;N;;;;; +1444C;ANATOLIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;; +1444D;ANATOLIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;; +1444E;ANATOLIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;; +1444F;ANATOLIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;; +14450;ANATOLIAN HIEROGLYPH A071;Lo;0;L;;;;;N;;;;; +14451;ANATOLIAN HIEROGLYPH A072;Lo;0;L;;;;;N;;;;; +14452;ANATOLIAN HIEROGLYPH A073;Lo;0;L;;;;;N;;;;; +14453;ANATOLIAN HIEROGLYPH A074;Lo;0;L;;;;;N;;;;; +14454;ANATOLIAN HIEROGLYPH A075;Lo;0;L;;;;;N;;;;; +14455;ANATOLIAN HIEROGLYPH A076;Lo;0;L;;;;;N;;;;; +14456;ANATOLIAN HIEROGLYPH A077;Lo;0;L;;;;;N;;;;; +14457;ANATOLIAN HIEROGLYPH A078;Lo;0;L;;;;;N;;;;; +14458;ANATOLIAN HIEROGLYPH A079;Lo;0;L;;;;;N;;;;; +14459;ANATOLIAN HIEROGLYPH A080;Lo;0;L;;;;;N;;;;; +1445A;ANATOLIAN HIEROGLYPH A081;Lo;0;L;;;;;N;;;;; +1445B;ANATOLIAN HIEROGLYPH A082;Lo;0;L;;;;;N;;;;; +1445C;ANATOLIAN HIEROGLYPH A083;Lo;0;L;;;;;N;;;;; +1445D;ANATOLIAN HIEROGLYPH A084;Lo;0;L;;;;;N;;;;; +1445E;ANATOLIAN HIEROGLYPH A085;Lo;0;L;;;;;N;;;;; +1445F;ANATOLIAN HIEROGLYPH A086;Lo;0;L;;;;;N;;;;; +14460;ANATOLIAN HIEROGLYPH A087;Lo;0;L;;;;;N;;;;; +14461;ANATOLIAN HIEROGLYPH A088;Lo;0;L;;;;;N;;;;; +14462;ANATOLIAN HIEROGLYPH A089;Lo;0;L;;;;;N;;;;; +14463;ANATOLIAN HIEROGLYPH A090;Lo;0;L;;;;;N;;;;; +14464;ANATOLIAN HIEROGLYPH A091;Lo;0;L;;;;;N;;;;; +14465;ANATOLIAN HIEROGLYPH A092;Lo;0;L;;;;;N;;;;; +14466;ANATOLIAN HIEROGLYPH A093;Lo;0;L;;;;;N;;;;; +14467;ANATOLIAN HIEROGLYPH A094;Lo;0;L;;;;;N;;;;; +14468;ANATOLIAN HIEROGLYPH A095;Lo;0;L;;;;;N;;;;; +14469;ANATOLIAN HIEROGLYPH A096;Lo;0;L;;;;;N;;;;; +1446A;ANATOLIAN HIEROGLYPH A097;Lo;0;L;;;;;N;;;;; +1446B;ANATOLIAN HIEROGLYPH A097A;Lo;0;L;;;;;N;;;;; +1446C;ANATOLIAN HIEROGLYPH A098;Lo;0;L;;;;;N;;;;; +1446D;ANATOLIAN HIEROGLYPH A098A;Lo;0;L;;;;;N;;;;; +1446E;ANATOLIAN HIEROGLYPH A099;Lo;0;L;;;;;N;;;;; +1446F;ANATOLIAN HIEROGLYPH A100;Lo;0;L;;;;;N;;;;; +14470;ANATOLIAN HIEROGLYPH A100A;Lo;0;L;;;;;N;;;;; +14471;ANATOLIAN HIEROGLYPH A101;Lo;0;L;;;;;N;;;;; +14472;ANATOLIAN HIEROGLYPH A101A;Lo;0;L;;;;;N;;;;; +14473;ANATOLIAN HIEROGLYPH A102;Lo;0;L;;;;;N;;;;; +14474;ANATOLIAN HIEROGLYPH A102A;Lo;0;L;;;;;N;;;;; +14475;ANATOLIAN HIEROGLYPH A103;Lo;0;L;;;;;N;;;;; +14476;ANATOLIAN HIEROGLYPH A104;Lo;0;L;;;;;N;;;;; +14477;ANATOLIAN HIEROGLYPH A104A;Lo;0;L;;;;;N;;;;; +14478;ANATOLIAN HIEROGLYPH A104B;Lo;0;L;;;;;N;;;;; +14479;ANATOLIAN HIEROGLYPH A104C;Lo;0;L;;;;;N;;;;; +1447A;ANATOLIAN HIEROGLYPH A105;Lo;0;L;;;;;N;;;;; +1447B;ANATOLIAN HIEROGLYPH A105A;Lo;0;L;;;;;N;;;;; +1447C;ANATOLIAN HIEROGLYPH A105B;Lo;0;L;;;;;N;;;;; +1447D;ANATOLIAN HIEROGLYPH A106;Lo;0;L;;;;;N;;;;; +1447E;ANATOLIAN HIEROGLYPH A107;Lo;0;L;;;;;N;;;;; +1447F;ANATOLIAN HIEROGLYPH A107A;Lo;0;L;;;;;N;;;;; +14480;ANATOLIAN HIEROGLYPH A107B;Lo;0;L;;;;;N;;;;; +14481;ANATOLIAN HIEROGLYPH A107C;Lo;0;L;;;;;N;;;;; +14482;ANATOLIAN HIEROGLYPH A108;Lo;0;L;;;;;N;;;;; +14483;ANATOLIAN HIEROGLYPH A109;Lo;0;L;;;;;N;;;;; +14484;ANATOLIAN HIEROGLYPH A110;Lo;0;L;;;;;N;;;;; +14485;ANATOLIAN HIEROGLYPH A110A;Lo;0;L;;;;;N;;;;; +14486;ANATOLIAN HIEROGLYPH A110B;Lo;0;L;;;;;N;;;;; +14487;ANATOLIAN HIEROGLYPH A111;Lo;0;L;;;;;N;;;;; +14488;ANATOLIAN HIEROGLYPH A112;Lo;0;L;;;;;N;;;;; +14489;ANATOLIAN HIEROGLYPH A113;Lo;0;L;;;;;N;;;;; +1448A;ANATOLIAN HIEROGLYPH A114;Lo;0;L;;;;;N;;;;; +1448B;ANATOLIAN HIEROGLYPH A115;Lo;0;L;;;;;N;;;;; +1448C;ANATOLIAN HIEROGLYPH A115A;Lo;0;L;;;;;N;;;;; +1448D;ANATOLIAN HIEROGLYPH A116;Lo;0;L;;;;;N;;;;; +1448E;ANATOLIAN HIEROGLYPH A117;Lo;0;L;;;;;N;;;;; +1448F;ANATOLIAN HIEROGLYPH A118;Lo;0;L;;;;;N;;;;; +14490;ANATOLIAN HIEROGLYPH A119;Lo;0;L;;;;;N;;;;; +14491;ANATOLIAN HIEROGLYPH A120;Lo;0;L;;;;;N;;;;; +14492;ANATOLIAN HIEROGLYPH A121;Lo;0;L;;;;;N;;;;; +14493;ANATOLIAN HIEROGLYPH A122;Lo;0;L;;;;;N;;;;; +14494;ANATOLIAN HIEROGLYPH A123;Lo;0;L;;;;;N;;;;; +14495;ANATOLIAN HIEROGLYPH A124;Lo;0;L;;;;;N;;;;; +14496;ANATOLIAN HIEROGLYPH A125;Lo;0;L;;;;;N;;;;; +14497;ANATOLIAN HIEROGLYPH A125A;Lo;0;L;;;;;N;;;;; +14498;ANATOLIAN HIEROGLYPH A126;Lo;0;L;;;;;N;;;;; +14499;ANATOLIAN HIEROGLYPH A127;Lo;0;L;;;;;N;;;;; +1449A;ANATOLIAN HIEROGLYPH A128;Lo;0;L;;;;;N;;;;; +1449B;ANATOLIAN HIEROGLYPH A129;Lo;0;L;;;;;N;;;;; +1449C;ANATOLIAN HIEROGLYPH A130;Lo;0;L;;;;;N;;;;; +1449D;ANATOLIAN HIEROGLYPH A131;Lo;0;L;;;;;N;;;;; +1449E;ANATOLIAN HIEROGLYPH A132;Lo;0;L;;;;;N;;;;; +1449F;ANATOLIAN HIEROGLYPH A133;Lo;0;L;;;;;N;;;;; +144A0;ANATOLIAN HIEROGLYPH A134;Lo;0;L;;;;;N;;;;; +144A1;ANATOLIAN HIEROGLYPH A135;Lo;0;L;;;;;N;;;;; +144A2;ANATOLIAN HIEROGLYPH A135A;Lo;0;L;;;;;N;;;;; +144A3;ANATOLIAN HIEROGLYPH A136;Lo;0;L;;;;;N;;;;; +144A4;ANATOLIAN HIEROGLYPH A137;Lo;0;L;;;;;N;;;;; +144A5;ANATOLIAN HIEROGLYPH A138;Lo;0;L;;;;;N;;;;; +144A6;ANATOLIAN HIEROGLYPH A139;Lo;0;L;;;;;N;;;;; +144A7;ANATOLIAN HIEROGLYPH A140;Lo;0;L;;;;;N;;;;; +144A8;ANATOLIAN HIEROGLYPH A141;Lo;0;L;;;;;N;;;;; +144A9;ANATOLIAN HIEROGLYPH A142;Lo;0;L;;;;;N;;;;; +144AA;ANATOLIAN HIEROGLYPH A143;Lo;0;L;;;;;N;;;;; +144AB;ANATOLIAN HIEROGLYPH A144;Lo;0;L;;;;;N;;;;; +144AC;ANATOLIAN HIEROGLYPH A145;Lo;0;L;;;;;N;;;;; +144AD;ANATOLIAN HIEROGLYPH A146;Lo;0;L;;;;;N;;;;; +144AE;ANATOLIAN HIEROGLYPH A147;Lo;0;L;;;;;N;;;;; +144AF;ANATOLIAN HIEROGLYPH A148;Lo;0;L;;;;;N;;;;; +144B0;ANATOLIAN HIEROGLYPH A149;Lo;0;L;;;;;N;;;;; +144B1;ANATOLIAN HIEROGLYPH A150;Lo;0;L;;;;;N;;;;; +144B2;ANATOLIAN HIEROGLYPH A151;Lo;0;L;;;;;N;;;;; +144B3;ANATOLIAN HIEROGLYPH A152;Lo;0;L;;;;;N;;;;; +144B4;ANATOLIAN HIEROGLYPH A153;Lo;0;L;;;;;N;;;;; +144B5;ANATOLIAN HIEROGLYPH A154;Lo;0;L;;;;;N;;;;; +144B6;ANATOLIAN HIEROGLYPH A155;Lo;0;L;;;;;N;;;;; +144B7;ANATOLIAN HIEROGLYPH A156;Lo;0;L;;;;;N;;;;; +144B8;ANATOLIAN HIEROGLYPH A157;Lo;0;L;;;;;N;;;;; +144B9;ANATOLIAN HIEROGLYPH A158;Lo;0;L;;;;;N;;;;; +144BA;ANATOLIAN HIEROGLYPH A159;Lo;0;L;;;;;N;;;;; +144BB;ANATOLIAN HIEROGLYPH A160;Lo;0;L;;;;;N;;;;; +144BC;ANATOLIAN HIEROGLYPH A161;Lo;0;L;;;;;N;;;;; +144BD;ANATOLIAN HIEROGLYPH A162;Lo;0;L;;;;;N;;;;; +144BE;ANATOLIAN HIEROGLYPH A163;Lo;0;L;;;;;N;;;;; +144BF;ANATOLIAN HIEROGLYPH A164;Lo;0;L;;;;;N;;;;; +144C0;ANATOLIAN HIEROGLYPH A165;Lo;0;L;;;;;N;;;;; +144C1;ANATOLIAN HIEROGLYPH A166;Lo;0;L;;;;;N;;;;; +144C2;ANATOLIAN HIEROGLYPH A167;Lo;0;L;;;;;N;;;;; +144C3;ANATOLIAN HIEROGLYPH A168;Lo;0;L;;;;;N;;;;; +144C4;ANATOLIAN HIEROGLYPH A169;Lo;0;L;;;;;N;;;;; +144C5;ANATOLIAN HIEROGLYPH A170;Lo;0;L;;;;;N;;;;; +144C6;ANATOLIAN HIEROGLYPH A171;Lo;0;L;;;;;N;;;;; +144C7;ANATOLIAN HIEROGLYPH A172;Lo;0;L;;;;;N;;;;; +144C8;ANATOLIAN HIEROGLYPH A173;Lo;0;L;;;;;N;;;;; +144C9;ANATOLIAN HIEROGLYPH A174;Lo;0;L;;;;;N;;;;; +144CA;ANATOLIAN HIEROGLYPH A175;Lo;0;L;;;;;N;;;;; +144CB;ANATOLIAN HIEROGLYPH A176;Lo;0;L;;;;;N;;;;; +144CC;ANATOLIAN HIEROGLYPH A177;Lo;0;L;;;;;N;;;;; +144CD;ANATOLIAN HIEROGLYPH A178;Lo;0;L;;;;;N;;;;; +144CE;ANATOLIAN HIEROGLYPH A179;Lo;0;L;;;;;N;;;;; +144CF;ANATOLIAN HIEROGLYPH A180;Lo;0;L;;;;;N;;;;; +144D0;ANATOLIAN HIEROGLYPH A181;Lo;0;L;;;;;N;;;;; +144D1;ANATOLIAN HIEROGLYPH A182;Lo;0;L;;;;;N;;;;; +144D2;ANATOLIAN HIEROGLYPH A183;Lo;0;L;;;;;N;;;;; +144D3;ANATOLIAN HIEROGLYPH A184;Lo;0;L;;;;;N;;;;; +144D4;ANATOLIAN HIEROGLYPH A185;Lo;0;L;;;;;N;;;;; +144D5;ANATOLIAN HIEROGLYPH A186;Lo;0;L;;;;;N;;;;; +144D6;ANATOLIAN HIEROGLYPH A187;Lo;0;L;;;;;N;;;;; +144D7;ANATOLIAN HIEROGLYPH A188;Lo;0;L;;;;;N;;;;; +144D8;ANATOLIAN HIEROGLYPH A189;Lo;0;L;;;;;N;;;;; +144D9;ANATOLIAN HIEROGLYPH A190;Lo;0;L;;;;;N;;;;; +144DA;ANATOLIAN HIEROGLYPH A191;Lo;0;L;;;;;N;;;;; +144DB;ANATOLIAN HIEROGLYPH A192;Lo;0;L;;;;;N;;;;; +144DC;ANATOLIAN HIEROGLYPH A193;Lo;0;L;;;;;N;;;;; +144DD;ANATOLIAN HIEROGLYPH A194;Lo;0;L;;;;;N;;;;; +144DE;ANATOLIAN HIEROGLYPH A195;Lo;0;L;;;;;N;;;;; +144DF;ANATOLIAN HIEROGLYPH A196;Lo;0;L;;;;;N;;;;; +144E0;ANATOLIAN HIEROGLYPH A197;Lo;0;L;;;;;N;;;;; +144E1;ANATOLIAN HIEROGLYPH A198;Lo;0;L;;;;;N;;;;; +144E2;ANATOLIAN HIEROGLYPH A199;Lo;0;L;;;;;N;;;;; +144E3;ANATOLIAN HIEROGLYPH A200;Lo;0;L;;;;;N;;;;; +144E4;ANATOLIAN HIEROGLYPH A201;Lo;0;L;;;;;N;;;;; +144E5;ANATOLIAN HIEROGLYPH A202;Lo;0;L;;;;;N;;;;; +144E6;ANATOLIAN HIEROGLYPH A202A;Lo;0;L;;;;;N;;;;; +144E7;ANATOLIAN HIEROGLYPH A202B;Lo;0;L;;;;;N;;;;; +144E8;ANATOLIAN HIEROGLYPH A203;Lo;0;L;;;;;N;;;;; +144E9;ANATOLIAN HIEROGLYPH A204;Lo;0;L;;;;;N;;;;; +144EA;ANATOLIAN HIEROGLYPH A205;Lo;0;L;;;;;N;;;;; +144EB;ANATOLIAN HIEROGLYPH A206;Lo;0;L;;;;;N;;;;; +144EC;ANATOLIAN HIEROGLYPH A207;Lo;0;L;;;;;N;;;;; +144ED;ANATOLIAN HIEROGLYPH A207A;Lo;0;L;;;;;N;;;;; +144EE;ANATOLIAN HIEROGLYPH A208;Lo;0;L;;;;;N;;;;; +144EF;ANATOLIAN HIEROGLYPH A209;Lo;0;L;;;;;N;;;;; +144F0;ANATOLIAN HIEROGLYPH A209A;Lo;0;L;;;;;N;;;;; +144F1;ANATOLIAN HIEROGLYPH A210;Lo;0;L;;;;;N;;;;; +144F2;ANATOLIAN HIEROGLYPH A211;Lo;0;L;;;;;N;;;;; +144F3;ANATOLIAN HIEROGLYPH A212;Lo;0;L;;;;;N;;;;; +144F4;ANATOLIAN HIEROGLYPH A213;Lo;0;L;;;;;N;;;;; +144F5;ANATOLIAN HIEROGLYPH A214;Lo;0;L;;;;;N;;;;; +144F6;ANATOLIAN HIEROGLYPH A215;Lo;0;L;;;;;N;;;;; +144F7;ANATOLIAN HIEROGLYPH A215A;Lo;0;L;;;;;N;;;;; +144F8;ANATOLIAN HIEROGLYPH A216;Lo;0;L;;;;;N;;;;; +144F9;ANATOLIAN HIEROGLYPH A216A;Lo;0;L;;;;;N;;;;; +144FA;ANATOLIAN HIEROGLYPH A217;Lo;0;L;;;;;N;;;;; +144FB;ANATOLIAN HIEROGLYPH A218;Lo;0;L;;;;;N;;;;; +144FC;ANATOLIAN HIEROGLYPH A219;Lo;0;L;;;;;N;;;;; +144FD;ANATOLIAN HIEROGLYPH A220;Lo;0;L;;;;;N;;;;; +144FE;ANATOLIAN HIEROGLYPH A221;Lo;0;L;;;;;N;;;;; +144FF;ANATOLIAN HIEROGLYPH A222;Lo;0;L;;;;;N;;;;; +14500;ANATOLIAN HIEROGLYPH A223;Lo;0;L;;;;;N;;;;; +14501;ANATOLIAN HIEROGLYPH A224;Lo;0;L;;;;;N;;;;; +14502;ANATOLIAN HIEROGLYPH A225;Lo;0;L;;;;;N;;;;; +14503;ANATOLIAN HIEROGLYPH A226;Lo;0;L;;;;;N;;;;; +14504;ANATOLIAN HIEROGLYPH A227;Lo;0;L;;;;;N;;;;; +14505;ANATOLIAN HIEROGLYPH A227A;Lo;0;L;;;;;N;;;;; +14506;ANATOLIAN HIEROGLYPH A228;Lo;0;L;;;;;N;;;;; +14507;ANATOLIAN HIEROGLYPH A229;Lo;0;L;;;;;N;;;;; +14508;ANATOLIAN HIEROGLYPH A230;Lo;0;L;;;;;N;;;;; +14509;ANATOLIAN HIEROGLYPH A231;Lo;0;L;;;;;N;;;;; +1450A;ANATOLIAN HIEROGLYPH A232;Lo;0;L;;;;;N;;;;; +1450B;ANATOLIAN HIEROGLYPH A233;Lo;0;L;;;;;N;;;;; +1450C;ANATOLIAN HIEROGLYPH A234;Lo;0;L;;;;;N;;;;; +1450D;ANATOLIAN HIEROGLYPH A235;Lo;0;L;;;;;N;;;;; +1450E;ANATOLIAN HIEROGLYPH A236;Lo;0;L;;;;;N;;;;; +1450F;ANATOLIAN HIEROGLYPH A237;Lo;0;L;;;;;N;;;;; +14510;ANATOLIAN HIEROGLYPH A238;Lo;0;L;;;;;N;;;;; +14511;ANATOLIAN HIEROGLYPH A239;Lo;0;L;;;;;N;;;;; +14512;ANATOLIAN HIEROGLYPH A240;Lo;0;L;;;;;N;;;;; +14513;ANATOLIAN HIEROGLYPH A241;Lo;0;L;;;;;N;;;;; +14514;ANATOLIAN HIEROGLYPH A242;Lo;0;L;;;;;N;;;;; +14515;ANATOLIAN HIEROGLYPH A243;Lo;0;L;;;;;N;;;;; +14516;ANATOLIAN HIEROGLYPH A244;Lo;0;L;;;;;N;;;;; +14517;ANATOLIAN HIEROGLYPH A245;Lo;0;L;;;;;N;;;;; +14518;ANATOLIAN HIEROGLYPH A246;Lo;0;L;;;;;N;;;;; +14519;ANATOLIAN HIEROGLYPH A247;Lo;0;L;;;;;N;;;;; +1451A;ANATOLIAN HIEROGLYPH A248;Lo;0;L;;;;;N;;;;; +1451B;ANATOLIAN HIEROGLYPH A249;Lo;0;L;;;;;N;;;;; +1451C;ANATOLIAN HIEROGLYPH A250;Lo;0;L;;;;;N;;;;; +1451D;ANATOLIAN HIEROGLYPH A251;Lo;0;L;;;;;N;;;;; +1451E;ANATOLIAN HIEROGLYPH A252;Lo;0;L;;;;;N;;;;; +1451F;ANATOLIAN HIEROGLYPH A253;Lo;0;L;;;;;N;;;;; +14520;ANATOLIAN HIEROGLYPH A254;Lo;0;L;;;;;N;;;;; +14521;ANATOLIAN HIEROGLYPH A255;Lo;0;L;;;;;N;;;;; +14522;ANATOLIAN HIEROGLYPH A256;Lo;0;L;;;;;N;;;;; +14523;ANATOLIAN HIEROGLYPH A257;Lo;0;L;;;;;N;;;;; +14524;ANATOLIAN HIEROGLYPH A258;Lo;0;L;;;;;N;;;;; +14525;ANATOLIAN HIEROGLYPH A259;Lo;0;L;;;;;N;;;;; +14526;ANATOLIAN HIEROGLYPH A260;Lo;0;L;;;;;N;;;;; +14527;ANATOLIAN HIEROGLYPH A261;Lo;0;L;;;;;N;;;;; +14528;ANATOLIAN HIEROGLYPH A262;Lo;0;L;;;;;N;;;;; +14529;ANATOLIAN HIEROGLYPH A263;Lo;0;L;;;;;N;;;;; +1452A;ANATOLIAN HIEROGLYPH A264;Lo;0;L;;;;;N;;;;; +1452B;ANATOLIAN HIEROGLYPH A265;Lo;0;L;;;;;N;;;;; +1452C;ANATOLIAN HIEROGLYPH A266;Lo;0;L;;;;;N;;;;; +1452D;ANATOLIAN HIEROGLYPH A267;Lo;0;L;;;;;N;;;;; +1452E;ANATOLIAN HIEROGLYPH A267A;Lo;0;L;;;;;N;;;;; +1452F;ANATOLIAN HIEROGLYPH A268;Lo;0;L;;;;;N;;;;; +14530;ANATOLIAN HIEROGLYPH A269;Lo;0;L;;;;;N;;;;; +14531;ANATOLIAN HIEROGLYPH A270;Lo;0;L;;;;;N;;;;; +14532;ANATOLIAN HIEROGLYPH A271;Lo;0;L;;;;;N;;;;; +14533;ANATOLIAN HIEROGLYPH A272;Lo;0;L;;;;;N;;;;; +14534;ANATOLIAN HIEROGLYPH A273;Lo;0;L;;;;;N;;;;; +14535;ANATOLIAN HIEROGLYPH A274;Lo;0;L;;;;;N;;;;; +14536;ANATOLIAN HIEROGLYPH A275;Lo;0;L;;;;;N;;;;; +14537;ANATOLIAN HIEROGLYPH A276;Lo;0;L;;;;;N;;;;; +14538;ANATOLIAN HIEROGLYPH A277;Lo;0;L;;;;;N;;;;; +14539;ANATOLIAN HIEROGLYPH A278;Lo;0;L;;;;;N;;;;; +1453A;ANATOLIAN HIEROGLYPH A279;Lo;0;L;;;;;N;;;;; +1453B;ANATOLIAN HIEROGLYPH A280;Lo;0;L;;;;;N;;;;; +1453C;ANATOLIAN HIEROGLYPH A281;Lo;0;L;;;;;N;;;;; +1453D;ANATOLIAN HIEROGLYPH A282;Lo;0;L;;;;;N;;;;; +1453E;ANATOLIAN HIEROGLYPH A283;Lo;0;L;;;;;N;;;;; +1453F;ANATOLIAN HIEROGLYPH A284;Lo;0;L;;;;;N;;;;; +14540;ANATOLIAN HIEROGLYPH A285;Lo;0;L;;;;;N;;;;; +14541;ANATOLIAN HIEROGLYPH A286;Lo;0;L;;;;;N;;;;; +14542;ANATOLIAN HIEROGLYPH A287;Lo;0;L;;;;;N;;;;; +14543;ANATOLIAN HIEROGLYPH A288;Lo;0;L;;;;;N;;;;; +14544;ANATOLIAN HIEROGLYPH A289;Lo;0;L;;;;;N;;;;; +14545;ANATOLIAN HIEROGLYPH A289A;Lo;0;L;;;;;N;;;;; +14546;ANATOLIAN HIEROGLYPH A290;Lo;0;L;;;;;N;;;;; +14547;ANATOLIAN HIEROGLYPH A291;Lo;0;L;;;;;N;;;;; +14548;ANATOLIAN HIEROGLYPH A292;Lo;0;L;;;;;N;;;;; +14549;ANATOLIAN HIEROGLYPH A293;Lo;0;L;;;;;N;;;;; +1454A;ANATOLIAN HIEROGLYPH A294;Lo;0;L;;;;;N;;;;; +1454B;ANATOLIAN HIEROGLYPH A294A;Lo;0;L;;;;;N;;;;; +1454C;ANATOLIAN HIEROGLYPH A295;Lo;0;L;;;;;N;;;;; +1454D;ANATOLIAN HIEROGLYPH A296;Lo;0;L;;;;;N;;;;; +1454E;ANATOLIAN HIEROGLYPH A297;Lo;0;L;;;;;N;;;;; +1454F;ANATOLIAN HIEROGLYPH A298;Lo;0;L;;;;;N;;;;; +14550;ANATOLIAN HIEROGLYPH A299;Lo;0;L;;;;;N;;;;; +14551;ANATOLIAN HIEROGLYPH A299A;Lo;0;L;;;;;N;;;;; +14552;ANATOLIAN HIEROGLYPH A300;Lo;0;L;;;;;N;;;;; +14553;ANATOLIAN HIEROGLYPH A301;Lo;0;L;;;;;N;;;;; +14554;ANATOLIAN HIEROGLYPH A302;Lo;0;L;;;;;N;;;;; +14555;ANATOLIAN HIEROGLYPH A303;Lo;0;L;;;;;N;;;;; +14556;ANATOLIAN HIEROGLYPH A304;Lo;0;L;;;;;N;;;;; +14557;ANATOLIAN HIEROGLYPH A305;Lo;0;L;;;;;N;;;;; +14558;ANATOLIAN HIEROGLYPH A306;Lo;0;L;;;;;N;;;;; +14559;ANATOLIAN HIEROGLYPH A307;Lo;0;L;;;;;N;;;;; +1455A;ANATOLIAN HIEROGLYPH A308;Lo;0;L;;;;;N;;;;; +1455B;ANATOLIAN HIEROGLYPH A309;Lo;0;L;;;;;N;;;;; +1455C;ANATOLIAN HIEROGLYPH A309A;Lo;0;L;;;;;N;;;;; +1455D;ANATOLIAN HIEROGLYPH A310;Lo;0;L;;;;;N;;;;; +1455E;ANATOLIAN HIEROGLYPH A311;Lo;0;L;;;;;N;;;;; +1455F;ANATOLIAN HIEROGLYPH A312;Lo;0;L;;;;;N;;;;; +14560;ANATOLIAN HIEROGLYPH A313;Lo;0;L;;;;;N;;;;; +14561;ANATOLIAN HIEROGLYPH A314;Lo;0;L;;;;;N;;;;; +14562;ANATOLIAN HIEROGLYPH A315;Lo;0;L;;;;;N;;;;; +14563;ANATOLIAN HIEROGLYPH A316;Lo;0;L;;;;;N;;;;; +14564;ANATOLIAN HIEROGLYPH A317;Lo;0;L;;;;;N;;;;; +14565;ANATOLIAN HIEROGLYPH A318;Lo;0;L;;;;;N;;;;; +14566;ANATOLIAN HIEROGLYPH A319;Lo;0;L;;;;;N;;;;; +14567;ANATOLIAN HIEROGLYPH A320;Lo;0;L;;;;;N;;;;; +14568;ANATOLIAN HIEROGLYPH A321;Lo;0;L;;;;;N;;;;; +14569;ANATOLIAN HIEROGLYPH A322;Lo;0;L;;;;;N;;;;; +1456A;ANATOLIAN HIEROGLYPH A323;Lo;0;L;;;;;N;;;;; +1456B;ANATOLIAN HIEROGLYPH A324;Lo;0;L;;;;;N;;;;; +1456C;ANATOLIAN HIEROGLYPH A325;Lo;0;L;;;;;N;;;;; +1456D;ANATOLIAN HIEROGLYPH A326;Lo;0;L;;;;;N;;;;; +1456E;ANATOLIAN HIEROGLYPH A327;Lo;0;L;;;;;N;;;;; +1456F;ANATOLIAN HIEROGLYPH A328;Lo;0;L;;;;;N;;;;; +14570;ANATOLIAN HIEROGLYPH A329;Lo;0;L;;;;;N;;;;; +14571;ANATOLIAN HIEROGLYPH A329A;Lo;0;L;;;;;N;;;;; +14572;ANATOLIAN HIEROGLYPH A330;Lo;0;L;;;;;N;;;;; +14573;ANATOLIAN HIEROGLYPH A331;Lo;0;L;;;;;N;;;;; +14574;ANATOLIAN HIEROGLYPH A332A;Lo;0;L;;;;;N;;;;; +14575;ANATOLIAN HIEROGLYPH A332B;Lo;0;L;;;;;N;;;;; +14576;ANATOLIAN HIEROGLYPH A332C;Lo;0;L;;;;;N;;;;; +14577;ANATOLIAN HIEROGLYPH A333;Lo;0;L;;;;;N;;;;; +14578;ANATOLIAN HIEROGLYPH A334;Lo;0;L;;;;;N;;;;; +14579;ANATOLIAN HIEROGLYPH A335;Lo;0;L;;;;;N;;;;; +1457A;ANATOLIAN HIEROGLYPH A336;Lo;0;L;;;;;N;;;;; +1457B;ANATOLIAN HIEROGLYPH A336A;Lo;0;L;;;;;N;;;;; +1457C;ANATOLIAN HIEROGLYPH A336B;Lo;0;L;;;;;N;;;;; +1457D;ANATOLIAN HIEROGLYPH A336C;Lo;0;L;;;;;N;;;;; +1457E;ANATOLIAN HIEROGLYPH A337;Lo;0;L;;;;;N;;;;; +1457F;ANATOLIAN HIEROGLYPH A338;Lo;0;L;;;;;N;;;;; +14580;ANATOLIAN HIEROGLYPH A339;Lo;0;L;;;;;N;;;;; +14581;ANATOLIAN HIEROGLYPH A340;Lo;0;L;;;;;N;;;;; +14582;ANATOLIAN HIEROGLYPH A341;Lo;0;L;;;;;N;;;;; +14583;ANATOLIAN HIEROGLYPH A342;Lo;0;L;;;;;N;;;;; +14584;ANATOLIAN HIEROGLYPH A343;Lo;0;L;;;;;N;;;;; +14585;ANATOLIAN HIEROGLYPH A344;Lo;0;L;;;;;N;;;;; +14586;ANATOLIAN HIEROGLYPH A345;Lo;0;L;;;;;N;;;;; +14587;ANATOLIAN HIEROGLYPH A346;Lo;0;L;;;;;N;;;;; +14588;ANATOLIAN HIEROGLYPH A347;Lo;0;L;;;;;N;;;;; +14589;ANATOLIAN HIEROGLYPH A348;Lo;0;L;;;;;N;;;;; +1458A;ANATOLIAN HIEROGLYPH A349;Lo;0;L;;;;;N;;;;; +1458B;ANATOLIAN HIEROGLYPH A350;Lo;0;L;;;;;N;;;;; +1458C;ANATOLIAN HIEROGLYPH A351;Lo;0;L;;;;;N;;;;; +1458D;ANATOLIAN HIEROGLYPH A352;Lo;0;L;;;;;N;;;;; +1458E;ANATOLIAN HIEROGLYPH A353;Lo;0;L;;;;;N;;;;; +1458F;ANATOLIAN HIEROGLYPH A354;Lo;0;L;;;;;N;;;;; +14590;ANATOLIAN HIEROGLYPH A355;Lo;0;L;;;;;N;;;;; +14591;ANATOLIAN HIEROGLYPH A356;Lo;0;L;;;;;N;;;;; +14592;ANATOLIAN HIEROGLYPH A357;Lo;0;L;;;;;N;;;;; +14593;ANATOLIAN HIEROGLYPH A358;Lo;0;L;;;;;N;;;;; +14594;ANATOLIAN HIEROGLYPH A359;Lo;0;L;;;;;N;;;;; +14595;ANATOLIAN HIEROGLYPH A359A;Lo;0;L;;;;;N;;;;; +14596;ANATOLIAN HIEROGLYPH A360;Lo;0;L;;;;;N;;;;; +14597;ANATOLIAN HIEROGLYPH A361;Lo;0;L;;;;;N;;;;; +14598;ANATOLIAN HIEROGLYPH A362;Lo;0;L;;;;;N;;;;; +14599;ANATOLIAN HIEROGLYPH A363;Lo;0;L;;;;;N;;;;; +1459A;ANATOLIAN HIEROGLYPH A364;Lo;0;L;;;;;N;;;;; +1459B;ANATOLIAN HIEROGLYPH A364A;Lo;0;L;;;;;N;;;;; +1459C;ANATOLIAN HIEROGLYPH A365;Lo;0;L;;;;;N;;;;; +1459D;ANATOLIAN HIEROGLYPH A366;Lo;0;L;;;;;N;;;;; +1459E;ANATOLIAN HIEROGLYPH A367;Lo;0;L;;;;;N;;;;; +1459F;ANATOLIAN HIEROGLYPH A368;Lo;0;L;;;;;N;;;;; +145A0;ANATOLIAN HIEROGLYPH A368A;Lo;0;L;;;;;N;;;;; +145A1;ANATOLIAN HIEROGLYPH A369;Lo;0;L;;;;;N;;;;; +145A2;ANATOLIAN HIEROGLYPH A370;Lo;0;L;;;;;N;;;;; +145A3;ANATOLIAN HIEROGLYPH A371;Lo;0;L;;;;;N;;;;; +145A4;ANATOLIAN HIEROGLYPH A371A;Lo;0;L;;;;;N;;;;; +145A5;ANATOLIAN HIEROGLYPH A372;Lo;0;L;;;;;N;;;;; +145A6;ANATOLIAN HIEROGLYPH A373;Lo;0;L;;;;;N;;;;; +145A7;ANATOLIAN HIEROGLYPH A374;Lo;0;L;;;;;N;;;;; +145A8;ANATOLIAN HIEROGLYPH A375;Lo;0;L;;;;;N;;;;; +145A9;ANATOLIAN HIEROGLYPH A376;Lo;0;L;;;;;N;;;;; +145AA;ANATOLIAN HIEROGLYPH A377;Lo;0;L;;;;;N;;;;; +145AB;ANATOLIAN HIEROGLYPH A378;Lo;0;L;;;;;N;;;;; +145AC;ANATOLIAN HIEROGLYPH A379;Lo;0;L;;;;;N;;;;; +145AD;ANATOLIAN HIEROGLYPH A380;Lo;0;L;;;;;N;;;;; +145AE;ANATOLIAN HIEROGLYPH A381;Lo;0;L;;;;;N;;;;; +145AF;ANATOLIAN HIEROGLYPH A381A;Lo;0;L;;;;;N;;;;; +145B0;ANATOLIAN HIEROGLYPH A382;Lo;0;L;;;;;N;;;;; +145B1;ANATOLIAN HIEROGLYPH A383 RA OR RI;Lo;0;L;;;;;N;;;;; +145B2;ANATOLIAN HIEROGLYPH A383A;Lo;0;L;;;;;N;;;;; +145B3;ANATOLIAN HIEROGLYPH A384;Lo;0;L;;;;;N;;;;; +145B4;ANATOLIAN HIEROGLYPH A385;Lo;0;L;;;;;N;;;;; +145B5;ANATOLIAN HIEROGLYPH A386;Lo;0;L;;;;;N;;;;; +145B6;ANATOLIAN HIEROGLYPH A386A;Lo;0;L;;;;;N;;;;; +145B7;ANATOLIAN HIEROGLYPH A387;Lo;0;L;;;;;N;;;;; +145B8;ANATOLIAN HIEROGLYPH A388;Lo;0;L;;;;;N;;;;; +145B9;ANATOLIAN HIEROGLYPH A389;Lo;0;L;;;;;N;;;;; +145BA;ANATOLIAN HIEROGLYPH A390;Lo;0;L;;;;;N;;;;; +145BB;ANATOLIAN HIEROGLYPH A391;Lo;0;L;;;;;N;;;;; +145BC;ANATOLIAN HIEROGLYPH A392;Lo;0;L;;;;;N;;;;; +145BD;ANATOLIAN HIEROGLYPH A393 EIGHT;Lo;0;L;;;;;N;;;;; +145BE;ANATOLIAN HIEROGLYPH A394;Lo;0;L;;;;;N;;;;; +145BF;ANATOLIAN HIEROGLYPH A395;Lo;0;L;;;;;N;;;;; +145C0;ANATOLIAN HIEROGLYPH A396;Lo;0;L;;;;;N;;;;; +145C1;ANATOLIAN HIEROGLYPH A397;Lo;0;L;;;;;N;;;;; +145C2;ANATOLIAN HIEROGLYPH A398;Lo;0;L;;;;;N;;;;; +145C3;ANATOLIAN HIEROGLYPH A399;Lo;0;L;;;;;N;;;;; +145C4;ANATOLIAN HIEROGLYPH A400;Lo;0;L;;;;;N;;;;; +145C5;ANATOLIAN HIEROGLYPH A401;Lo;0;L;;;;;N;;;;; +145C6;ANATOLIAN HIEROGLYPH A402;Lo;0;L;;;;;N;;;;; +145C7;ANATOLIAN HIEROGLYPH A403;Lo;0;L;;;;;N;;;;; +145C8;ANATOLIAN HIEROGLYPH A404;Lo;0;L;;;;;N;;;;; +145C9;ANATOLIAN HIEROGLYPH A405;Lo;0;L;;;;;N;;;;; +145CA;ANATOLIAN HIEROGLYPH A406;Lo;0;L;;;;;N;;;;; +145CB;ANATOLIAN HIEROGLYPH A407;Lo;0;L;;;;;N;;;;; +145CC;ANATOLIAN HIEROGLYPH A408;Lo;0;L;;;;;N;;;;; +145CD;ANATOLIAN HIEROGLYPH A409;Lo;0;L;;;;;N;;;;; +145CE;ANATOLIAN HIEROGLYPH A410 BEGIN LOGOGRAM MARK;Lo;0;L;;;;;N;;;;; +145CF;ANATOLIAN HIEROGLYPH A410A END LOGOGRAM MARK;Lo;0;L;;;;;N;;;;; +145D0;ANATOLIAN HIEROGLYPH A411;Lo;0;L;;;;;N;;;;; +145D1;ANATOLIAN HIEROGLYPH A412;Lo;0;L;;;;;N;;;;; +145D2;ANATOLIAN HIEROGLYPH A413;Lo;0;L;;;;;N;;;;; +145D3;ANATOLIAN HIEROGLYPH A414;Lo;0;L;;;;;N;;;;; +145D4;ANATOLIAN HIEROGLYPH A415;Lo;0;L;;;;;N;;;;; +145D5;ANATOLIAN HIEROGLYPH A416;Lo;0;L;;;;;N;;;;; +145D6;ANATOLIAN HIEROGLYPH A417;Lo;0;L;;;;;N;;;;; +145D7;ANATOLIAN HIEROGLYPH A418;Lo;0;L;;;;;N;;;;; +145D8;ANATOLIAN HIEROGLYPH A419;Lo;0;L;;;;;N;;;;; +145D9;ANATOLIAN HIEROGLYPH A420;Lo;0;L;;;;;N;;;;; +145DA;ANATOLIAN HIEROGLYPH A421;Lo;0;L;;;;;N;;;;; +145DB;ANATOLIAN HIEROGLYPH A422;Lo;0;L;;;;;N;;;;; +145DC;ANATOLIAN HIEROGLYPH A423;Lo;0;L;;;;;N;;;;; +145DD;ANATOLIAN HIEROGLYPH A424;Lo;0;L;;;;;N;;;;; +145DE;ANATOLIAN HIEROGLYPH A425;Lo;0;L;;;;;N;;;;; +145DF;ANATOLIAN HIEROGLYPH A426;Lo;0;L;;;;;N;;;;; +145E0;ANATOLIAN HIEROGLYPH A427;Lo;0;L;;;;;N;;;;; +145E1;ANATOLIAN HIEROGLYPH A428;Lo;0;L;;;;;N;;;;; +145E2;ANATOLIAN HIEROGLYPH A429;Lo;0;L;;;;;N;;;;; +145E3;ANATOLIAN HIEROGLYPH A430;Lo;0;L;;;;;N;;;;; +145E4;ANATOLIAN HIEROGLYPH A431;Lo;0;L;;;;;N;;;;; +145E5;ANATOLIAN HIEROGLYPH A432;Lo;0;L;;;;;N;;;;; +145E6;ANATOLIAN HIEROGLYPH A433;Lo;0;L;;;;;N;;;;; +145E7;ANATOLIAN HIEROGLYPH A434;Lo;0;L;;;;;N;;;;; +145E8;ANATOLIAN HIEROGLYPH A435;Lo;0;L;;;;;N;;;;; +145E9;ANATOLIAN HIEROGLYPH A436;Lo;0;L;;;;;N;;;;; +145EA;ANATOLIAN HIEROGLYPH A437;Lo;0;L;;;;;N;;;;; +145EB;ANATOLIAN HIEROGLYPH A438;Lo;0;L;;;;;N;;;;; +145EC;ANATOLIAN HIEROGLYPH A439;Lo;0;L;;;;;N;;;;; +145ED;ANATOLIAN HIEROGLYPH A440;Lo;0;L;;;;;N;;;;; +145EE;ANATOLIAN HIEROGLYPH A441;Lo;0;L;;;;;N;;;;; +145EF;ANATOLIAN HIEROGLYPH A442;Lo;0;L;;;;;N;;;;; +145F0;ANATOLIAN HIEROGLYPH A443;Lo;0;L;;;;;N;;;;; +145F1;ANATOLIAN HIEROGLYPH A444;Lo;0;L;;;;;N;;;;; +145F2;ANATOLIAN HIEROGLYPH A445;Lo;0;L;;;;;N;;;;; +145F3;ANATOLIAN HIEROGLYPH A446;Lo;0;L;;;;;N;;;;; +145F4;ANATOLIAN HIEROGLYPH A447;Lo;0;L;;;;;N;;;;; +145F5;ANATOLIAN HIEROGLYPH A448;Lo;0;L;;;;;N;;;;; +145F6;ANATOLIAN HIEROGLYPH A449;Lo;0;L;;;;;N;;;;; +145F7;ANATOLIAN HIEROGLYPH A450;Lo;0;L;;;;;N;;;;; +145F8;ANATOLIAN HIEROGLYPH A450A;Lo;0;L;;;;;N;;;;; +145F9;ANATOLIAN HIEROGLYPH A451;Lo;0;L;;;;;N;;;;; +145FA;ANATOLIAN HIEROGLYPH A452;Lo;0;L;;;;;N;;;;; +145FB;ANATOLIAN HIEROGLYPH A453;Lo;0;L;;;;;N;;;;; +145FC;ANATOLIAN HIEROGLYPH A454;Lo;0;L;;;;;N;;;;; +145FD;ANATOLIAN HIEROGLYPH A455;Lo;0;L;;;;;N;;;;; +145FE;ANATOLIAN HIEROGLYPH A456;Lo;0;L;;;;;N;;;;; +145FF;ANATOLIAN HIEROGLYPH A457;Lo;0;L;;;;;N;;;;; +14600;ANATOLIAN HIEROGLYPH A457A;Lo;0;L;;;;;N;;;;; +14601;ANATOLIAN HIEROGLYPH A458;Lo;0;L;;;;;N;;;;; +14602;ANATOLIAN HIEROGLYPH A459;Lo;0;L;;;;;N;;;;; +14603;ANATOLIAN HIEROGLYPH A460;Lo;0;L;;;;;N;;;;; +14604;ANATOLIAN HIEROGLYPH A461;Lo;0;L;;;;;N;;;;; +14605;ANATOLIAN HIEROGLYPH A462;Lo;0;L;;;;;N;;;;; +14606;ANATOLIAN HIEROGLYPH A463;Lo;0;L;;;;;N;;;;; +14607;ANATOLIAN HIEROGLYPH A464;Lo;0;L;;;;;N;;;;; +14608;ANATOLIAN HIEROGLYPH A465;Lo;0;L;;;;;N;;;;; +14609;ANATOLIAN HIEROGLYPH A466;Lo;0;L;;;;;N;;;;; +1460A;ANATOLIAN HIEROGLYPH A467;Lo;0;L;;;;;N;;;;; +1460B;ANATOLIAN HIEROGLYPH A468;Lo;0;L;;;;;N;;;;; +1460C;ANATOLIAN HIEROGLYPH A469;Lo;0;L;;;;;N;;;;; +1460D;ANATOLIAN HIEROGLYPH A470;Lo;0;L;;;;;N;;;;; +1460E;ANATOLIAN HIEROGLYPH A471;Lo;0;L;;;;;N;;;;; +1460F;ANATOLIAN HIEROGLYPH A472;Lo;0;L;;;;;N;;;;; +14610;ANATOLIAN HIEROGLYPH A473;Lo;0;L;;;;;N;;;;; +14611;ANATOLIAN HIEROGLYPH A474;Lo;0;L;;;;;N;;;;; +14612;ANATOLIAN HIEROGLYPH A475;Lo;0;L;;;;;N;;;;; +14613;ANATOLIAN HIEROGLYPH A476;Lo;0;L;;;;;N;;;;; +14614;ANATOLIAN HIEROGLYPH A477;Lo;0;L;;;;;N;;;;; +14615;ANATOLIAN HIEROGLYPH A478;Lo;0;L;;;;;N;;;;; +14616;ANATOLIAN HIEROGLYPH A479;Lo;0;L;;;;;N;;;;; +14617;ANATOLIAN HIEROGLYPH A480;Lo;0;L;;;;;N;;;;; +14618;ANATOLIAN HIEROGLYPH A481;Lo;0;L;;;;;N;;;;; +14619;ANATOLIAN HIEROGLYPH A482;Lo;0;L;;;;;N;;;;; +1461A;ANATOLIAN HIEROGLYPH A483;Lo;0;L;;;;;N;;;;; +1461B;ANATOLIAN HIEROGLYPH A484;Lo;0;L;;;;;N;;;;; +1461C;ANATOLIAN HIEROGLYPH A485;Lo;0;L;;;;;N;;;;; +1461D;ANATOLIAN HIEROGLYPH A486;Lo;0;L;;;;;N;;;;; +1461E;ANATOLIAN HIEROGLYPH A487;Lo;0;L;;;;;N;;;;; +1461F;ANATOLIAN HIEROGLYPH A488;Lo;0;L;;;;;N;;;;; +14620;ANATOLIAN HIEROGLYPH A489;Lo;0;L;;;;;N;;;;; +14621;ANATOLIAN HIEROGLYPH A490;Lo;0;L;;;;;N;;;;; +14622;ANATOLIAN HIEROGLYPH A491;Lo;0;L;;;;;N;;;;; +14623;ANATOLIAN HIEROGLYPH A492;Lo;0;L;;;;;N;;;;; +14624;ANATOLIAN HIEROGLYPH A493;Lo;0;L;;;;;N;;;;; +14625;ANATOLIAN HIEROGLYPH A494;Lo;0;L;;;;;N;;;;; +14626;ANATOLIAN HIEROGLYPH A495;Lo;0;L;;;;;N;;;;; +14627;ANATOLIAN HIEROGLYPH A496;Lo;0;L;;;;;N;;;;; +14628;ANATOLIAN HIEROGLYPH A497;Lo;0;L;;;;;N;;;;; +14629;ANATOLIAN HIEROGLYPH A501;Lo;0;L;;;;;N;;;;; +1462A;ANATOLIAN HIEROGLYPH A502;Lo;0;L;;;;;N;;;;; +1462B;ANATOLIAN HIEROGLYPH A503;Lo;0;L;;;;;N;;;;; +1462C;ANATOLIAN HIEROGLYPH A504;Lo;0;L;;;;;N;;;;; +1462D;ANATOLIAN HIEROGLYPH A505;Lo;0;L;;;;;N;;;;; +1462E;ANATOLIAN HIEROGLYPH A506;Lo;0;L;;;;;N;;;;; +1462F;ANATOLIAN HIEROGLYPH A507;Lo;0;L;;;;;N;;;;; +14630;ANATOLIAN HIEROGLYPH A508;Lo;0;L;;;;;N;;;;; +14631;ANATOLIAN HIEROGLYPH A509;Lo;0;L;;;;;N;;;;; +14632;ANATOLIAN HIEROGLYPH A510;Lo;0;L;;;;;N;;;;; +14633;ANATOLIAN HIEROGLYPH A511;Lo;0;L;;;;;N;;;;; +14634;ANATOLIAN HIEROGLYPH A512;Lo;0;L;;;;;N;;;;; +14635;ANATOLIAN HIEROGLYPH A513;Lo;0;L;;;;;N;;;;; +14636;ANATOLIAN HIEROGLYPH A514;Lo;0;L;;;;;N;;;;; +14637;ANATOLIAN HIEROGLYPH A515;Lo;0;L;;;;;N;;;;; +14638;ANATOLIAN HIEROGLYPH A516;Lo;0;L;;;;;N;;;;; +14639;ANATOLIAN HIEROGLYPH A517;Lo;0;L;;;;;N;;;;; +1463A;ANATOLIAN HIEROGLYPH A518;Lo;0;L;;;;;N;;;;; +1463B;ANATOLIAN HIEROGLYPH A519;Lo;0;L;;;;;N;;;;; +1463C;ANATOLIAN HIEROGLYPH A520;Lo;0;L;;;;;N;;;;; +1463D;ANATOLIAN HIEROGLYPH A521;Lo;0;L;;;;;N;;;;; +1463E;ANATOLIAN HIEROGLYPH A522;Lo;0;L;;;;;N;;;;; +1463F;ANATOLIAN HIEROGLYPH A523;Lo;0;L;;;;;N;;;;; +14640;ANATOLIAN HIEROGLYPH A524;Lo;0;L;;;;;N;;;;; +14641;ANATOLIAN HIEROGLYPH A525;Lo;0;L;;;;;N;;;;; +14642;ANATOLIAN HIEROGLYPH A526;Lo;0;L;;;;;N;;;;; +14643;ANATOLIAN HIEROGLYPH A527;Lo;0;L;;;;;N;;;;; +14644;ANATOLIAN HIEROGLYPH A528;Lo;0;L;;;;;N;;;;; +14645;ANATOLIAN HIEROGLYPH A529;Lo;0;L;;;;;N;;;;; +14646;ANATOLIAN HIEROGLYPH A530;Lo;0;L;;;;;N;;;;; +16800;BAMUM LETTER PHASE-A NGKUE MFON;Lo;0;L;;;;;N;;;;; +16801;BAMUM LETTER PHASE-A GBIEE FON;Lo;0;L;;;;;N;;;;; +16802;BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; +16803;BAMUM LETTER PHASE-A PON MFON PIPAEMBA;Lo;0;L;;;;;N;;;;; +16804;BAMUM LETTER PHASE-A NAA MFON;Lo;0;L;;;;;N;;;;; +16805;BAMUM LETTER PHASE-A SHUENSHUET;Lo;0;L;;;;;N;;;;; +16806;BAMUM LETTER PHASE-A TITA MFON;Lo;0;L;;;;;N;;;;; +16807;BAMUM LETTER PHASE-A NZA MFON;Lo;0;L;;;;;N;;;;; +16808;BAMUM LETTER PHASE-A SHINDA PA NJI;Lo;0;L;;;;;N;;;;; +16809;BAMUM LETTER PHASE-A PON PA NJI PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; +1680A;BAMUM LETTER PHASE-A PON PA NJI PIPAEMBA;Lo;0;L;;;;;N;;;;; +1680B;BAMUM LETTER PHASE-A MAEMBGBIEE;Lo;0;L;;;;;N;;;;; +1680C;BAMUM LETTER PHASE-A TU MAEMBA;Lo;0;L;;;;;N;;;;; +1680D;BAMUM LETTER PHASE-A NGANGU;Lo;0;L;;;;;N;;;;; +1680E;BAMUM LETTER PHASE-A MAEMVEUX;Lo;0;L;;;;;N;;;;; +1680F;BAMUM LETTER PHASE-A MANSUAE;Lo;0;L;;;;;N;;;;; +16810;BAMUM LETTER PHASE-A MVEUAENGAM;Lo;0;L;;;;;N;;;;; +16811;BAMUM LETTER PHASE-A SEUNYAM;Lo;0;L;;;;;N;;;;; +16812;BAMUM LETTER PHASE-A NTOQPEN;Lo;0;L;;;;;N;;;;; +16813;BAMUM LETTER PHASE-A KEUKEUTNDA;Lo;0;L;;;;;N;;;;; +16814;BAMUM LETTER PHASE-A NKINDI;Lo;0;L;;;;;N;;;;; +16815;BAMUM LETTER PHASE-A SUU;Lo;0;L;;;;;N;;;;; +16816;BAMUM LETTER PHASE-A NGKUENZEUM;Lo;0;L;;;;;N;;;;; +16817;BAMUM LETTER PHASE-A LAPAQ;Lo;0;L;;;;;N;;;;; +16818;BAMUM LETTER PHASE-A LET KUT;Lo;0;L;;;;;N;;;;; +16819;BAMUM LETTER PHASE-A NTAP MFAA;Lo;0;L;;;;;N;;;;; +1681A;BAMUM LETTER PHASE-A MAEKEUP;Lo;0;L;;;;;N;;;;; +1681B;BAMUM LETTER PHASE-A PASHAE;Lo;0;L;;;;;N;;;;; +1681C;BAMUM LETTER PHASE-A GHEUAERAE;Lo;0;L;;;;;N;;;;; +1681D;BAMUM LETTER PHASE-A PAMSHAE;Lo;0;L;;;;;N;;;;; +1681E;BAMUM LETTER PHASE-A MON NGGEUAET;Lo;0;L;;;;;N;;;;; +1681F;BAMUM LETTER PHASE-A NZUN MEUT;Lo;0;L;;;;;N;;;;; +16820;BAMUM LETTER PHASE-A U YUQ NAE;Lo;0;L;;;;;N;;;;; +16821;BAMUM LETTER PHASE-A GHEUAEGHEUAE;Lo;0;L;;;;;N;;;;; +16822;BAMUM LETTER PHASE-A NTAP NTAA;Lo;0;L;;;;;N;;;;; +16823;BAMUM LETTER PHASE-A SISA;Lo;0;L;;;;;N;;;;; +16824;BAMUM LETTER PHASE-A MGBASA;Lo;0;L;;;;;N;;;;; +16825;BAMUM LETTER PHASE-A MEUNJOMNDEUQ;Lo;0;L;;;;;N;;;;; +16826;BAMUM LETTER PHASE-A MOOMPUQ;Lo;0;L;;;;;N;;;;; +16827;BAMUM LETTER PHASE-A KAFA;Lo;0;L;;;;;N;;;;; +16828;BAMUM LETTER PHASE-A PA LEERAEWA;Lo;0;L;;;;;N;;;;; +16829;BAMUM LETTER PHASE-A NDA LEERAEWA;Lo;0;L;;;;;N;;;;; +1682A;BAMUM LETTER PHASE-A PET;Lo;0;L;;;;;N;;;;; +1682B;BAMUM LETTER PHASE-A MAEMKPEN;Lo;0;L;;;;;N;;;;; +1682C;BAMUM LETTER PHASE-A NIKA;Lo;0;L;;;;;N;;;;; +1682D;BAMUM LETTER PHASE-A PUP;Lo;0;L;;;;;N;;;;; +1682E;BAMUM LETTER PHASE-A TUAEP;Lo;0;L;;;;;N;;;;; +1682F;BAMUM LETTER PHASE-A LUAEP;Lo;0;L;;;;;N;;;;; +16830;BAMUM LETTER PHASE-A SONJAM;Lo;0;L;;;;;N;;;;; +16831;BAMUM LETTER PHASE-A TEUTEUWEN;Lo;0;L;;;;;N;;;;; +16832;BAMUM LETTER PHASE-A MAENYI;Lo;0;L;;;;;N;;;;; +16833;BAMUM LETTER PHASE-A KET;Lo;0;L;;;;;N;;;;; +16834;BAMUM LETTER PHASE-A NDAANGGEUAET;Lo;0;L;;;;;N;;;;; +16835;BAMUM LETTER PHASE-A KUOQ;Lo;0;L;;;;;N;;;;; +16836;BAMUM LETTER PHASE-A MOOMEUT;Lo;0;L;;;;;N;;;;; +16837;BAMUM LETTER PHASE-A SHUM;Lo;0;L;;;;;N;;;;; +16838;BAMUM LETTER PHASE-A LOMMAE;Lo;0;L;;;;;N;;;;; +16839;BAMUM LETTER PHASE-A FIRI;Lo;0;L;;;;;N;;;;; +1683A;BAMUM LETTER PHASE-A ROM;Lo;0;L;;;;;N;;;;; +1683B;BAMUM LETTER PHASE-A KPOQ;Lo;0;L;;;;;N;;;;; +1683C;BAMUM LETTER PHASE-A SOQ;Lo;0;L;;;;;N;;;;; +1683D;BAMUM LETTER PHASE-A MAP PIEET;Lo;0;L;;;;;N;;;;; +1683E;BAMUM LETTER PHASE-A SHIRAE;Lo;0;L;;;;;N;;;;; +1683F;BAMUM LETTER PHASE-A NTAP;Lo;0;L;;;;;N;;;;; +16840;BAMUM LETTER PHASE-A SHOQ NSHUT YUM;Lo;0;L;;;;;N;;;;; +16841;BAMUM LETTER PHASE-A NYIT MONGKEUAEQ;Lo;0;L;;;;;N;;;;; +16842;BAMUM LETTER PHASE-A PAARAE;Lo;0;L;;;;;N;;;;; +16843;BAMUM LETTER PHASE-A NKAARAE;Lo;0;L;;;;;N;;;;; +16844;BAMUM LETTER PHASE-A UNKNOWN;Lo;0;L;;;;;N;;;;; +16845;BAMUM LETTER PHASE-A NGGEN;Lo;0;L;;;;;N;;;;; +16846;BAMUM LETTER PHASE-A MAESI;Lo;0;L;;;;;N;;;;; +16847;BAMUM LETTER PHASE-A NJAM;Lo;0;L;;;;;N;;;;; +16848;BAMUM LETTER PHASE-A MBANYI;Lo;0;L;;;;;N;;;;; +16849;BAMUM LETTER PHASE-A NYET;Lo;0;L;;;;;N;;;;; +1684A;BAMUM LETTER PHASE-A TEUAEN;Lo;0;L;;;;;N;;;;; +1684B;BAMUM LETTER PHASE-A SOT;Lo;0;L;;;;;N;;;;; +1684C;BAMUM LETTER PHASE-A PAAM;Lo;0;L;;;;;N;;;;; +1684D;BAMUM LETTER PHASE-A NSHIEE;Lo;0;L;;;;;N;;;;; +1684E;BAMUM LETTER PHASE-A MAEM;Lo;0;L;;;;;N;;;;; +1684F;BAMUM LETTER PHASE-A NYI;Lo;0;L;;;;;N;;;;; +16850;BAMUM LETTER PHASE-A KAQ;Lo;0;L;;;;;N;;;;; +16851;BAMUM LETTER PHASE-A NSHA;Lo;0;L;;;;;N;;;;; +16852;BAMUM LETTER PHASE-A VEE;Lo;0;L;;;;;N;;;;; +16853;BAMUM LETTER PHASE-A LU;Lo;0;L;;;;;N;;;;; +16854;BAMUM LETTER PHASE-A NEN;Lo;0;L;;;;;N;;;;; +16855;BAMUM LETTER PHASE-A NAQ;Lo;0;L;;;;;N;;;;; +16856;BAMUM LETTER PHASE-A MBAQ;Lo;0;L;;;;;N;;;;; +16857;BAMUM LETTER PHASE-B NSHUET;Lo;0;L;;;;;N;;;;; +16858;BAMUM LETTER PHASE-B TU MAEMGBIEE;Lo;0;L;;;;;N;;;;; +16859;BAMUM LETTER PHASE-B SIEE;Lo;0;L;;;;;N;;;;; +1685A;BAMUM LETTER PHASE-B SET TU;Lo;0;L;;;;;N;;;;; +1685B;BAMUM LETTER PHASE-B LOM NTEUM;Lo;0;L;;;;;N;;;;; +1685C;BAMUM LETTER PHASE-B MBA MAELEE;Lo;0;L;;;;;N;;;;; +1685D;BAMUM LETTER PHASE-B KIEEM;Lo;0;L;;;;;N;;;;; +1685E;BAMUM LETTER PHASE-B YEURAE;Lo;0;L;;;;;N;;;;; +1685F;BAMUM LETTER PHASE-B MBAARAE;Lo;0;L;;;;;N;;;;; +16860;BAMUM LETTER PHASE-B KAM;Lo;0;L;;;;;N;;;;; +16861;BAMUM LETTER PHASE-B PEESHI;Lo;0;L;;;;;N;;;;; +16862;BAMUM LETTER PHASE-B YAFU LEERAEWA;Lo;0;L;;;;;N;;;;; +16863;BAMUM LETTER PHASE-B LAM NSHUT NYAM;Lo;0;L;;;;;N;;;;; +16864;BAMUM LETTER PHASE-B NTIEE SHEUOQ;Lo;0;L;;;;;N;;;;; +16865;BAMUM LETTER PHASE-B NDU NJAA;Lo;0;L;;;;;N;;;;; +16866;BAMUM LETTER PHASE-B GHEUGHEUAEM;Lo;0;L;;;;;N;;;;; +16867;BAMUM LETTER PHASE-B PIT;Lo;0;L;;;;;N;;;;; +16868;BAMUM LETTER PHASE-B TU NSIEE;Lo;0;L;;;;;N;;;;; +16869;BAMUM LETTER PHASE-B SHET NJAQ;Lo;0;L;;;;;N;;;;; +1686A;BAMUM LETTER PHASE-B SHEUAEQTU;Lo;0;L;;;;;N;;;;; +1686B;BAMUM LETTER PHASE-B MFON TEUAEQ;Lo;0;L;;;;;N;;;;; +1686C;BAMUM LETTER PHASE-B MBIT MBAAKET;Lo;0;L;;;;;N;;;;; +1686D;BAMUM LETTER PHASE-B NYI NTEUM;Lo;0;L;;;;;N;;;;; +1686E;BAMUM LETTER PHASE-B KEUPUQ;Lo;0;L;;;;;N;;;;; +1686F;BAMUM LETTER PHASE-B GHEUGHEN;Lo;0;L;;;;;N;;;;; +16870;BAMUM LETTER PHASE-B KEUYEUX;Lo;0;L;;;;;N;;;;; +16871;BAMUM LETTER PHASE-B LAANAE;Lo;0;L;;;;;N;;;;; +16872;BAMUM LETTER PHASE-B PARUM;Lo;0;L;;;;;N;;;;; +16873;BAMUM LETTER PHASE-B VEUM;Lo;0;L;;;;;N;;;;; +16874;BAMUM LETTER PHASE-B NGKINDI MVOP;Lo;0;L;;;;;N;;;;; +16875;BAMUM LETTER PHASE-B NGGEU MBU;Lo;0;L;;;;;N;;;;; +16876;BAMUM LETTER PHASE-B WUAET;Lo;0;L;;;;;N;;;;; +16877;BAMUM LETTER PHASE-B SAKEUAE;Lo;0;L;;;;;N;;;;; +16878;BAMUM LETTER PHASE-B TAAM;Lo;0;L;;;;;N;;;;; +16879;BAMUM LETTER PHASE-B MEUQ;Lo;0;L;;;;;N;;;;; +1687A;BAMUM LETTER PHASE-B NGGUOQ;Lo;0;L;;;;;N;;;;; +1687B;BAMUM LETTER PHASE-B NGGUOQ LARGE;Lo;0;L;;;;;N;;;;; +1687C;BAMUM LETTER PHASE-B MFIYAQ;Lo;0;L;;;;;N;;;;; +1687D;BAMUM LETTER PHASE-B SUE;Lo;0;L;;;;;N;;;;; +1687E;BAMUM LETTER PHASE-B MBEURI;Lo;0;L;;;;;N;;;;; +1687F;BAMUM LETTER PHASE-B MONTIEEN;Lo;0;L;;;;;N;;;;; +16880;BAMUM LETTER PHASE-B NYAEMAE;Lo;0;L;;;;;N;;;;; +16881;BAMUM LETTER PHASE-B PUNGAAM;Lo;0;L;;;;;N;;;;; +16882;BAMUM LETTER PHASE-B MEUT NGGEET;Lo;0;L;;;;;N;;;;; +16883;BAMUM LETTER PHASE-B FEUX;Lo;0;L;;;;;N;;;;; +16884;BAMUM LETTER PHASE-B MBUOQ;Lo;0;L;;;;;N;;;;; +16885;BAMUM LETTER PHASE-B FEE;Lo;0;L;;;;;N;;;;; +16886;BAMUM LETTER PHASE-B KEUAEM;Lo;0;L;;;;;N;;;;; +16887;BAMUM LETTER PHASE-B MA NJEUAENA;Lo;0;L;;;;;N;;;;; +16888;BAMUM LETTER PHASE-B MA NJUQA;Lo;0;L;;;;;N;;;;; +16889;BAMUM LETTER PHASE-B LET;Lo;0;L;;;;;N;;;;; +1688A;BAMUM LETTER PHASE-B NGGAAM;Lo;0;L;;;;;N;;;;; +1688B;BAMUM LETTER PHASE-B NSEN;Lo;0;L;;;;;N;;;;; +1688C;BAMUM LETTER PHASE-B MA;Lo;0;L;;;;;N;;;;; +1688D;BAMUM LETTER PHASE-B KIQ;Lo;0;L;;;;;N;;;;; +1688E;BAMUM LETTER PHASE-B NGOM;Lo;0;L;;;;;N;;;;; +1688F;BAMUM LETTER PHASE-C NGKUE MAEMBA;Lo;0;L;;;;;N;;;;; +16890;BAMUM LETTER PHASE-C NZA;Lo;0;L;;;;;N;;;;; +16891;BAMUM LETTER PHASE-C YUM;Lo;0;L;;;;;N;;;;; +16892;BAMUM LETTER PHASE-C WANGKUOQ;Lo;0;L;;;;;N;;;;; +16893;BAMUM LETTER PHASE-C NGGEN;Lo;0;L;;;;;N;;;;; +16894;BAMUM LETTER PHASE-C NDEUAEREE;Lo;0;L;;;;;N;;;;; +16895;BAMUM LETTER PHASE-C NGKAQ;Lo;0;L;;;;;N;;;;; +16896;BAMUM LETTER PHASE-C GHARAE;Lo;0;L;;;;;N;;;;; +16897;BAMUM LETTER PHASE-C MBEEKEET;Lo;0;L;;;;;N;;;;; +16898;BAMUM LETTER PHASE-C GBAYI;Lo;0;L;;;;;N;;;;; +16899;BAMUM LETTER PHASE-C NYIR MKPARAQ MEUN;Lo;0;L;;;;;N;;;;; +1689A;BAMUM LETTER PHASE-C NTU MBIT;Lo;0;L;;;;;N;;;;; +1689B;BAMUM LETTER PHASE-C MBEUM;Lo;0;L;;;;;N;;;;; +1689C;BAMUM LETTER PHASE-C PIRIEEN;Lo;0;L;;;;;N;;;;; +1689D;BAMUM LETTER PHASE-C NDOMBU;Lo;0;L;;;;;N;;;;; +1689E;BAMUM LETTER PHASE-C MBAA CABBAGE-TREE;Lo;0;L;;;;;N;;;;; +1689F;BAMUM LETTER PHASE-C KEUSHEUAEP;Lo;0;L;;;;;N;;;;; +168A0;BAMUM LETTER PHASE-C GHAP;Lo;0;L;;;;;N;;;;; +168A1;BAMUM LETTER PHASE-C KEUKAQ;Lo;0;L;;;;;N;;;;; +168A2;BAMUM LETTER PHASE-C YU MUOMAE;Lo;0;L;;;;;N;;;;; +168A3;BAMUM LETTER PHASE-C NZEUM;Lo;0;L;;;;;N;;;;; +168A4;BAMUM LETTER PHASE-C MBUE;Lo;0;L;;;;;N;;;;; +168A5;BAMUM LETTER PHASE-C NSEUAEN;Lo;0;L;;;;;N;;;;; +168A6;BAMUM LETTER PHASE-C MBIT;Lo;0;L;;;;;N;;;;; +168A7;BAMUM LETTER PHASE-C YEUQ;Lo;0;L;;;;;N;;;;; +168A8;BAMUM LETTER PHASE-C KPARAQ;Lo;0;L;;;;;N;;;;; +168A9;BAMUM LETTER PHASE-C KAA;Lo;0;L;;;;;N;;;;; +168AA;BAMUM LETTER PHASE-C SEUX;Lo;0;L;;;;;N;;;;; +168AB;BAMUM LETTER PHASE-C NDIDA;Lo;0;L;;;;;N;;;;; +168AC;BAMUM LETTER PHASE-C TAASHAE;Lo;0;L;;;;;N;;;;; +168AD;BAMUM LETTER PHASE-C NJUEQ;Lo;0;L;;;;;N;;;;; +168AE;BAMUM LETTER PHASE-C TITA YUE;Lo;0;L;;;;;N;;;;; +168AF;BAMUM LETTER PHASE-C SUAET;Lo;0;L;;;;;N;;;;; +168B0;BAMUM LETTER PHASE-C NGGUAEN NYAM;Lo;0;L;;;;;N;;;;; +168B1;BAMUM LETTER PHASE-C VEUX;Lo;0;L;;;;;N;;;;; +168B2;BAMUM LETTER PHASE-C NANSANAQ;Lo;0;L;;;;;N;;;;; +168B3;BAMUM LETTER PHASE-C MA KEUAERI;Lo;0;L;;;;;N;;;;; +168B4;BAMUM LETTER PHASE-C NTAA;Lo;0;L;;;;;N;;;;; +168B5;BAMUM LETTER PHASE-C NGGUON;Lo;0;L;;;;;N;;;;; +168B6;BAMUM LETTER PHASE-C LAP;Lo;0;L;;;;;N;;;;; +168B7;BAMUM LETTER PHASE-C MBIRIEEN;Lo;0;L;;;;;N;;;;; +168B8;BAMUM LETTER PHASE-C MGBASAQ;Lo;0;L;;;;;N;;;;; +168B9;BAMUM LETTER PHASE-C NTEUNGBA;Lo;0;L;;;;;N;;;;; +168BA;BAMUM LETTER PHASE-C TEUTEUX;Lo;0;L;;;;;N;;;;; +168BB;BAMUM LETTER PHASE-C NGGUM;Lo;0;L;;;;;N;;;;; +168BC;BAMUM LETTER PHASE-C FUE;Lo;0;L;;;;;N;;;;; +168BD;BAMUM LETTER PHASE-C NDEUT;Lo;0;L;;;;;N;;;;; +168BE;BAMUM LETTER PHASE-C NSA;Lo;0;L;;;;;N;;;;; +168BF;BAMUM LETTER PHASE-C NSHAQ;Lo;0;L;;;;;N;;;;; +168C0;BAMUM LETTER PHASE-C BUNG;Lo;0;L;;;;;N;;;;; +168C1;BAMUM LETTER PHASE-C VEUAEPEN;Lo;0;L;;;;;N;;;;; +168C2;BAMUM LETTER PHASE-C MBERAE;Lo;0;L;;;;;N;;;;; +168C3;BAMUM LETTER PHASE-C RU;Lo;0;L;;;;;N;;;;; +168C4;BAMUM LETTER PHASE-C NJAEM;Lo;0;L;;;;;N;;;;; +168C5;BAMUM LETTER PHASE-C LAM;Lo;0;L;;;;;N;;;;; +168C6;BAMUM LETTER PHASE-C TITUAEP;Lo;0;L;;;;;N;;;;; +168C7;BAMUM LETTER PHASE-C NSUOT NGOM;Lo;0;L;;;;;N;;;;; +168C8;BAMUM LETTER PHASE-C NJEEEE;Lo;0;L;;;;;N;;;;; +168C9;BAMUM LETTER PHASE-C KET;Lo;0;L;;;;;N;;;;; +168CA;BAMUM LETTER PHASE-C NGGU;Lo;0;L;;;;;N;;;;; +168CB;BAMUM LETTER PHASE-C MAESI;Lo;0;L;;;;;N;;;;; +168CC;BAMUM LETTER PHASE-C MBUAEM;Lo;0;L;;;;;N;;;;; +168CD;BAMUM LETTER PHASE-C LU;Lo;0;L;;;;;N;;;;; +168CE;BAMUM LETTER PHASE-C KUT;Lo;0;L;;;;;N;;;;; +168CF;BAMUM LETTER PHASE-C NJAM;Lo;0;L;;;;;N;;;;; +168D0;BAMUM LETTER PHASE-C NGOM;Lo;0;L;;;;;N;;;;; +168D1;BAMUM LETTER PHASE-C WUP;Lo;0;L;;;;;N;;;;; +168D2;BAMUM LETTER PHASE-C NGGUEET;Lo;0;L;;;;;N;;;;; +168D3;BAMUM LETTER PHASE-C NSOM;Lo;0;L;;;;;N;;;;; +168D4;BAMUM LETTER PHASE-C NTEN;Lo;0;L;;;;;N;;;;; +168D5;BAMUM LETTER PHASE-C KUOP NKAARAE;Lo;0;L;;;;;N;;;;; +168D6;BAMUM LETTER PHASE-C NSUN;Lo;0;L;;;;;N;;;;; +168D7;BAMUM LETTER PHASE-C NDAM;Lo;0;L;;;;;N;;;;; +168D8;BAMUM LETTER PHASE-C MA NSIEE;Lo;0;L;;;;;N;;;;; +168D9;BAMUM LETTER PHASE-C YAA;Lo;0;L;;;;;N;;;;; +168DA;BAMUM LETTER PHASE-C NDAP;Lo;0;L;;;;;N;;;;; +168DB;BAMUM LETTER PHASE-C SHUEQ;Lo;0;L;;;;;N;;;;; +168DC;BAMUM LETTER PHASE-C SETFON;Lo;0;L;;;;;N;;;;; +168DD;BAMUM LETTER PHASE-C MBI;Lo;0;L;;;;;N;;;;; +168DE;BAMUM LETTER PHASE-C MAEMBA;Lo;0;L;;;;;N;;;;; +168DF;BAMUM LETTER PHASE-C MBANYI;Lo;0;L;;;;;N;;;;; +168E0;BAMUM LETTER PHASE-C KEUSEUX;Lo;0;L;;;;;N;;;;; +168E1;BAMUM LETTER PHASE-C MBEUX;Lo;0;L;;;;;N;;;;; +168E2;BAMUM LETTER PHASE-C KEUM;Lo;0;L;;;;;N;;;;; +168E3;BAMUM LETTER PHASE-C MBAA PICKET;Lo;0;L;;;;;N;;;;; +168E4;BAMUM LETTER PHASE-C YUWOQ;Lo;0;L;;;;;N;;;;; +168E5;BAMUM LETTER PHASE-C NJEUX;Lo;0;L;;;;;N;;;;; +168E6;BAMUM LETTER PHASE-C MIEE;Lo;0;L;;;;;N;;;;; +168E7;BAMUM LETTER PHASE-C MUAE;Lo;0;L;;;;;N;;;;; +168E8;BAMUM LETTER PHASE-C SHIQ;Lo;0;L;;;;;N;;;;; +168E9;BAMUM LETTER PHASE-C KEN LAW;Lo;0;L;;;;;N;;;;; +168EA;BAMUM LETTER PHASE-C KEN FATIGUE;Lo;0;L;;;;;N;;;;; +168EB;BAMUM LETTER PHASE-C NGAQ;Lo;0;L;;;;;N;;;;; +168EC;BAMUM LETTER PHASE-C NAQ;Lo;0;L;;;;;N;;;;; +168ED;BAMUM LETTER PHASE-C LIQ;Lo;0;L;;;;;N;;;;; +168EE;BAMUM LETTER PHASE-C PIN;Lo;0;L;;;;;N;;;;; +168EF;BAMUM LETTER PHASE-C PEN;Lo;0;L;;;;;N;;;;; +168F0;BAMUM LETTER PHASE-C TET;Lo;0;L;;;;;N;;;;; +168F1;BAMUM LETTER PHASE-D MBUO;Lo;0;L;;;;;N;;;;; +168F2;BAMUM LETTER PHASE-D WAP;Lo;0;L;;;;;N;;;;; +168F3;BAMUM LETTER PHASE-D NJI;Lo;0;L;;;;;N;;;;; +168F4;BAMUM LETTER PHASE-D MFON;Lo;0;L;;;;;N;;;;; +168F5;BAMUM LETTER PHASE-D NJIEE;Lo;0;L;;;;;N;;;;; +168F6;BAMUM LETTER PHASE-D LIEE;Lo;0;L;;;;;N;;;;; +168F7;BAMUM LETTER PHASE-D NJEUT;Lo;0;L;;;;;N;;;;; +168F8;BAMUM LETTER PHASE-D NSHEE;Lo;0;L;;;;;N;;;;; +168F9;BAMUM LETTER PHASE-D NGGAAMAE;Lo;0;L;;;;;N;;;;; +168FA;BAMUM LETTER PHASE-D NYAM;Lo;0;L;;;;;N;;;;; +168FB;BAMUM LETTER PHASE-D WUAEN;Lo;0;L;;;;;N;;;;; +168FC;BAMUM LETTER PHASE-D NGKUN;Lo;0;L;;;;;N;;;;; +168FD;BAMUM LETTER PHASE-D SHEE;Lo;0;L;;;;;N;;;;; +168FE;BAMUM LETTER PHASE-D NGKAP;Lo;0;L;;;;;N;;;;; +168FF;BAMUM LETTER PHASE-D KEUAETMEUN;Lo;0;L;;;;;N;;;;; +16900;BAMUM LETTER PHASE-D TEUT;Lo;0;L;;;;;N;;;;; +16901;BAMUM LETTER PHASE-D SHEUAE;Lo;0;L;;;;;N;;;;; +16902;BAMUM LETTER PHASE-D NJAP;Lo;0;L;;;;;N;;;;; +16903;BAMUM LETTER PHASE-D SUE;Lo;0;L;;;;;N;;;;; +16904;BAMUM LETTER PHASE-D KET;Lo;0;L;;;;;N;;;;; +16905;BAMUM LETTER PHASE-D YAEMMAE;Lo;0;L;;;;;N;;;;; +16906;BAMUM LETTER PHASE-D KUOM;Lo;0;L;;;;;N;;;;; +16907;BAMUM LETTER PHASE-D SAP;Lo;0;L;;;;;N;;;;; +16908;BAMUM LETTER PHASE-D MFEUT;Lo;0;L;;;;;N;;;;; +16909;BAMUM LETTER PHASE-D NDEUX;Lo;0;L;;;;;N;;;;; +1690A;BAMUM LETTER PHASE-D MALEERI;Lo;0;L;;;;;N;;;;; +1690B;BAMUM LETTER PHASE-D MEUT;Lo;0;L;;;;;N;;;;; +1690C;BAMUM LETTER PHASE-D SEUAEQ;Lo;0;L;;;;;N;;;;; +1690D;BAMUM LETTER PHASE-D YEN;Lo;0;L;;;;;N;;;;; +1690E;BAMUM LETTER PHASE-D NJEUAEM;Lo;0;L;;;;;N;;;;; +1690F;BAMUM LETTER PHASE-D KEUOT MBUAE;Lo;0;L;;;;;N;;;;; +16910;BAMUM LETTER PHASE-D NGKEURI;Lo;0;L;;;;;N;;;;; +16911;BAMUM LETTER PHASE-D TU;Lo;0;L;;;;;N;;;;; +16912;BAMUM LETTER PHASE-D GHAA;Lo;0;L;;;;;N;;;;; +16913;BAMUM LETTER PHASE-D NGKYEE;Lo;0;L;;;;;N;;;;; +16914;BAMUM LETTER PHASE-D FEUFEUAET;Lo;0;L;;;;;N;;;;; +16915;BAMUM LETTER PHASE-D NDEE;Lo;0;L;;;;;N;;;;; +16916;BAMUM LETTER PHASE-D MGBOFUM;Lo;0;L;;;;;N;;;;; +16917;BAMUM LETTER PHASE-D LEUAEP;Lo;0;L;;;;;N;;;;; +16918;BAMUM LETTER PHASE-D NDON;Lo;0;L;;;;;N;;;;; +16919;BAMUM LETTER PHASE-D MONI;Lo;0;L;;;;;N;;;;; +1691A;BAMUM LETTER PHASE-D MGBEUN;Lo;0;L;;;;;N;;;;; +1691B;BAMUM LETTER PHASE-D PUUT;Lo;0;L;;;;;N;;;;; +1691C;BAMUM LETTER PHASE-D MGBIEE;Lo;0;L;;;;;N;;;;; +1691D;BAMUM LETTER PHASE-D MFO;Lo;0;L;;;;;N;;;;; +1691E;BAMUM LETTER PHASE-D LUM;Lo;0;L;;;;;N;;;;; +1691F;BAMUM LETTER PHASE-D NSIEEP;Lo;0;L;;;;;N;;;;; +16920;BAMUM LETTER PHASE-D MBAA;Lo;0;L;;;;;N;;;;; +16921;BAMUM LETTER PHASE-D KWAET;Lo;0;L;;;;;N;;;;; +16922;BAMUM LETTER PHASE-D NYET;Lo;0;L;;;;;N;;;;; +16923;BAMUM LETTER PHASE-D TEUAEN;Lo;0;L;;;;;N;;;;; +16924;BAMUM LETTER PHASE-D SOT;Lo;0;L;;;;;N;;;;; +16925;BAMUM LETTER PHASE-D YUWOQ;Lo;0;L;;;;;N;;;;; +16926;BAMUM LETTER PHASE-D KEUM;Lo;0;L;;;;;N;;;;; +16927;BAMUM LETTER PHASE-D RAEM;Lo;0;L;;;;;N;;;;; +16928;BAMUM LETTER PHASE-D TEEEE;Lo;0;L;;;;;N;;;;; +16929;BAMUM LETTER PHASE-D NGKEUAEQ;Lo;0;L;;;;;N;;;;; +1692A;BAMUM LETTER PHASE-D MFEUAE;Lo;0;L;;;;;N;;;;; +1692B;BAMUM LETTER PHASE-D NSIEET;Lo;0;L;;;;;N;;;;; +1692C;BAMUM LETTER PHASE-D KEUP;Lo;0;L;;;;;N;;;;; +1692D;BAMUM LETTER PHASE-D PIP;Lo;0;L;;;;;N;;;;; +1692E;BAMUM LETTER PHASE-D PEUTAE;Lo;0;L;;;;;N;;;;; +1692F;BAMUM LETTER PHASE-D NYUE;Lo;0;L;;;;;N;;;;; +16930;BAMUM LETTER PHASE-D LET;Lo;0;L;;;;;N;;;;; +16931;BAMUM LETTER PHASE-D NGGAAM;Lo;0;L;;;;;N;;;;; +16932;BAMUM LETTER PHASE-D MFIEE;Lo;0;L;;;;;N;;;;; +16933;BAMUM LETTER PHASE-D NGGWAEN;Lo;0;L;;;;;N;;;;; +16934;BAMUM LETTER PHASE-D YUOM;Lo;0;L;;;;;N;;;;; +16935;BAMUM LETTER PHASE-D PAP;Lo;0;L;;;;;N;;;;; +16936;BAMUM LETTER PHASE-D YUOP;Lo;0;L;;;;;N;;;;; +16937;BAMUM LETTER PHASE-D NDAM;Lo;0;L;;;;;N;;;;; +16938;BAMUM LETTER PHASE-D NTEUM;Lo;0;L;;;;;N;;;;; +16939;BAMUM LETTER PHASE-D SUAE;Lo;0;L;;;;;N;;;;; +1693A;BAMUM LETTER PHASE-D KUN;Lo;0;L;;;;;N;;;;; +1693B;BAMUM LETTER PHASE-D NGGEUX;Lo;0;L;;;;;N;;;;; +1693C;BAMUM LETTER PHASE-D NGKIEE;Lo;0;L;;;;;N;;;;; +1693D;BAMUM LETTER PHASE-D TUOT;Lo;0;L;;;;;N;;;;; +1693E;BAMUM LETTER PHASE-D MEUN;Lo;0;L;;;;;N;;;;; +1693F;BAMUM LETTER PHASE-D KUQ;Lo;0;L;;;;;N;;;;; +16940;BAMUM LETTER PHASE-D NSUM;Lo;0;L;;;;;N;;;;; +16941;BAMUM LETTER PHASE-D TEUN;Lo;0;L;;;;;N;;;;; +16942;BAMUM LETTER PHASE-D MAENJET;Lo;0;L;;;;;N;;;;; +16943;BAMUM LETTER PHASE-D NGGAP;Lo;0;L;;;;;N;;;;; +16944;BAMUM LETTER PHASE-D LEUM;Lo;0;L;;;;;N;;;;; +16945;BAMUM LETTER PHASE-D NGGUOM;Lo;0;L;;;;;N;;;;; +16946;BAMUM LETTER PHASE-D NSHUT;Lo;0;L;;;;;N;;;;; +16947;BAMUM LETTER PHASE-D NJUEQ;Lo;0;L;;;;;N;;;;; +16948;BAMUM LETTER PHASE-D GHEUAE;Lo;0;L;;;;;N;;;;; +16949;BAMUM LETTER PHASE-D KU;Lo;0;L;;;;;N;;;;; +1694A;BAMUM LETTER PHASE-D REN OLD;Lo;0;L;;;;;N;;;;; +1694B;BAMUM LETTER PHASE-D TAE;Lo;0;L;;;;;N;;;;; +1694C;BAMUM LETTER PHASE-D TOQ;Lo;0;L;;;;;N;;;;; +1694D;BAMUM LETTER PHASE-D NYI;Lo;0;L;;;;;N;;;;; +1694E;BAMUM LETTER PHASE-D RII;Lo;0;L;;;;;N;;;;; +1694F;BAMUM LETTER PHASE-D LEEEE;Lo;0;L;;;;;N;;;;; +16950;BAMUM LETTER PHASE-D MEEEE;Lo;0;L;;;;;N;;;;; +16951;BAMUM LETTER PHASE-D M;Lo;0;L;;;;;N;;;;; +16952;BAMUM LETTER PHASE-D SUU;Lo;0;L;;;;;N;;;;; +16953;BAMUM LETTER PHASE-D MU;Lo;0;L;;;;;N;;;;; +16954;BAMUM LETTER PHASE-D SHII;Lo;0;L;;;;;N;;;;; +16955;BAMUM LETTER PHASE-D SHEUX;Lo;0;L;;;;;N;;;;; +16956;BAMUM LETTER PHASE-D KYEE;Lo;0;L;;;;;N;;;;; +16957;BAMUM LETTER PHASE-D NU;Lo;0;L;;;;;N;;;;; +16958;BAMUM LETTER PHASE-D SHU;Lo;0;L;;;;;N;;;;; +16959;BAMUM LETTER PHASE-D NTEE;Lo;0;L;;;;;N;;;;; +1695A;BAMUM LETTER PHASE-D PEE;Lo;0;L;;;;;N;;;;; +1695B;BAMUM LETTER PHASE-D NI;Lo;0;L;;;;;N;;;;; +1695C;BAMUM LETTER PHASE-D SHOQ;Lo;0;L;;;;;N;;;;; +1695D;BAMUM LETTER PHASE-D PUQ;Lo;0;L;;;;;N;;;;; +1695E;BAMUM LETTER PHASE-D MVOP;Lo;0;L;;;;;N;;;;; +1695F;BAMUM LETTER PHASE-D LOQ;Lo;0;L;;;;;N;;;;; +16960;BAMUM LETTER PHASE-D REN MUCH;Lo;0;L;;;;;N;;;;; +16961;BAMUM LETTER PHASE-D TI;Lo;0;L;;;;;N;;;;; +16962;BAMUM LETTER PHASE-D NTUU;Lo;0;L;;;;;N;;;;; +16963;BAMUM LETTER PHASE-D MBAA SEVEN;Lo;0;L;;;;;N;;;;; +16964;BAMUM LETTER PHASE-D SAQ;Lo;0;L;;;;;N;;;;; +16965;BAMUM LETTER PHASE-D FAA;Lo;0;L;;;;;N;;;;; +16966;BAMUM LETTER PHASE-E NDAP;Lo;0;L;;;;;N;;;;; +16967;BAMUM LETTER PHASE-E TOON;Lo;0;L;;;;;N;;;;; +16968;BAMUM LETTER PHASE-E MBEUM;Lo;0;L;;;;;N;;;;; +16969;BAMUM LETTER PHASE-E LAP;Lo;0;L;;;;;N;;;;; +1696A;BAMUM LETTER PHASE-E VOM;Lo;0;L;;;;;N;;;;; +1696B;BAMUM LETTER PHASE-E LOON;Lo;0;L;;;;;N;;;;; +1696C;BAMUM LETTER PHASE-E PAA;Lo;0;L;;;;;N;;;;; +1696D;BAMUM LETTER PHASE-E SOM;Lo;0;L;;;;;N;;;;; +1696E;BAMUM LETTER PHASE-E RAQ;Lo;0;L;;;;;N;;;;; +1696F;BAMUM LETTER PHASE-E NSHUOP;Lo;0;L;;;;;N;;;;; +16970;BAMUM LETTER PHASE-E NDUN;Lo;0;L;;;;;N;;;;; +16971;BAMUM LETTER PHASE-E PUAE;Lo;0;L;;;;;N;;;;; +16972;BAMUM LETTER PHASE-E TAM;Lo;0;L;;;;;N;;;;; +16973;BAMUM LETTER PHASE-E NGKA;Lo;0;L;;;;;N;;;;; +16974;BAMUM LETTER PHASE-E KPEUX;Lo;0;L;;;;;N;;;;; +16975;BAMUM LETTER PHASE-E WUO;Lo;0;L;;;;;N;;;;; +16976;BAMUM LETTER PHASE-E SEE;Lo;0;L;;;;;N;;;;; +16977;BAMUM LETTER PHASE-E NGGEUAET;Lo;0;L;;;;;N;;;;; +16978;BAMUM LETTER PHASE-E PAAM;Lo;0;L;;;;;N;;;;; +16979;BAMUM LETTER PHASE-E TOO;Lo;0;L;;;;;N;;;;; +1697A;BAMUM LETTER PHASE-E KUOP;Lo;0;L;;;;;N;;;;; +1697B;BAMUM LETTER PHASE-E LOM;Lo;0;L;;;;;N;;;;; +1697C;BAMUM LETTER PHASE-E NSHIEE;Lo;0;L;;;;;N;;;;; +1697D;BAMUM LETTER PHASE-E NGOP;Lo;0;L;;;;;N;;;;; +1697E;BAMUM LETTER PHASE-E MAEM;Lo;0;L;;;;;N;;;;; +1697F;BAMUM LETTER PHASE-E NGKEUX;Lo;0;L;;;;;N;;;;; +16980;BAMUM LETTER PHASE-E NGOQ;Lo;0;L;;;;;N;;;;; +16981;BAMUM LETTER PHASE-E NSHUE;Lo;0;L;;;;;N;;;;; +16982;BAMUM LETTER PHASE-E RIMGBA;Lo;0;L;;;;;N;;;;; +16983;BAMUM LETTER PHASE-E NJEUX;Lo;0;L;;;;;N;;;;; +16984;BAMUM LETTER PHASE-E PEEM;Lo;0;L;;;;;N;;;;; +16985;BAMUM LETTER PHASE-E SAA;Lo;0;L;;;;;N;;;;; +16986;BAMUM LETTER PHASE-E NGGURAE;Lo;0;L;;;;;N;;;;; +16987;BAMUM LETTER PHASE-E MGBA;Lo;0;L;;;;;N;;;;; +16988;BAMUM LETTER PHASE-E GHEUX;Lo;0;L;;;;;N;;;;; +16989;BAMUM LETTER PHASE-E NGKEUAEM;Lo;0;L;;;;;N;;;;; +1698A;BAMUM LETTER PHASE-E NJAEMLI;Lo;0;L;;;;;N;;;;; +1698B;BAMUM LETTER PHASE-E MAP;Lo;0;L;;;;;N;;;;; +1698C;BAMUM LETTER PHASE-E LOOT;Lo;0;L;;;;;N;;;;; +1698D;BAMUM LETTER PHASE-E NGGEEEE;Lo;0;L;;;;;N;;;;; +1698E;BAMUM LETTER PHASE-E NDIQ;Lo;0;L;;;;;N;;;;; +1698F;BAMUM LETTER PHASE-E TAEN NTEUM;Lo;0;L;;;;;N;;;;; +16990;BAMUM LETTER PHASE-E SET;Lo;0;L;;;;;N;;;;; +16991;BAMUM LETTER PHASE-E PUM;Lo;0;L;;;;;N;;;;; +16992;BAMUM LETTER PHASE-E NDAA SOFTNESS;Lo;0;L;;;;;N;;;;; +16993;BAMUM LETTER PHASE-E NGGUAESHAE NYAM;Lo;0;L;;;;;N;;;;; +16994;BAMUM LETTER PHASE-E YIEE;Lo;0;L;;;;;N;;;;; +16995;BAMUM LETTER PHASE-E GHEUN;Lo;0;L;;;;;N;;;;; +16996;BAMUM LETTER PHASE-E TUAE;Lo;0;L;;;;;N;;;;; +16997;BAMUM LETTER PHASE-E YEUAE;Lo;0;L;;;;;N;;;;; +16998;BAMUM LETTER PHASE-E PO;Lo;0;L;;;;;N;;;;; +16999;BAMUM LETTER PHASE-E TUMAE;Lo;0;L;;;;;N;;;;; +1699A;BAMUM LETTER PHASE-E KEUAE;Lo;0;L;;;;;N;;;;; +1699B;BAMUM LETTER PHASE-E SUAEN;Lo;0;L;;;;;N;;;;; +1699C;BAMUM LETTER PHASE-E TEUAEQ;Lo;0;L;;;;;N;;;;; +1699D;BAMUM LETTER PHASE-E VEUAE;Lo;0;L;;;;;N;;;;; +1699E;BAMUM LETTER PHASE-E WEUX;Lo;0;L;;;;;N;;;;; +1699F;BAMUM LETTER PHASE-E LAAM;Lo;0;L;;;;;N;;;;; +169A0;BAMUM LETTER PHASE-E PU;Lo;0;L;;;;;N;;;;; +169A1;BAMUM LETTER PHASE-E TAAQ;Lo;0;L;;;;;N;;;;; +169A2;BAMUM LETTER PHASE-E GHAAMAE;Lo;0;L;;;;;N;;;;; +169A3;BAMUM LETTER PHASE-E NGEUREUT;Lo;0;L;;;;;N;;;;; +169A4;BAMUM LETTER PHASE-E SHEUAEQ;Lo;0;L;;;;;N;;;;; +169A5;BAMUM LETTER PHASE-E MGBEN;Lo;0;L;;;;;N;;;;; +169A6;BAMUM LETTER PHASE-E MBEE;Lo;0;L;;;;;N;;;;; +169A7;BAMUM LETTER PHASE-E NZAQ;Lo;0;L;;;;;N;;;;; +169A8;BAMUM LETTER PHASE-E NKOM;Lo;0;L;;;;;N;;;;; +169A9;BAMUM LETTER PHASE-E GBET;Lo;0;L;;;;;N;;;;; +169AA;BAMUM LETTER PHASE-E TUM;Lo;0;L;;;;;N;;;;; +169AB;BAMUM LETTER PHASE-E KUET;Lo;0;L;;;;;N;;;;; +169AC;BAMUM LETTER PHASE-E YAP;Lo;0;L;;;;;N;;;;; +169AD;BAMUM LETTER PHASE-E NYI CLEAVER;Lo;0;L;;;;;N;;;;; +169AE;BAMUM LETTER PHASE-E YIT;Lo;0;L;;;;;N;;;;; +169AF;BAMUM LETTER PHASE-E MFEUQ;Lo;0;L;;;;;N;;;;; +169B0;BAMUM LETTER PHASE-E NDIAQ;Lo;0;L;;;;;N;;;;; +169B1;BAMUM LETTER PHASE-E PIEEQ;Lo;0;L;;;;;N;;;;; +169B2;BAMUM LETTER PHASE-E YUEQ;Lo;0;L;;;;;N;;;;; +169B3;BAMUM LETTER PHASE-E LEUAEM;Lo;0;L;;;;;N;;;;; +169B4;BAMUM LETTER PHASE-E FUE;Lo;0;L;;;;;N;;;;; +169B5;BAMUM LETTER PHASE-E GBEUX;Lo;0;L;;;;;N;;;;; +169B6;BAMUM LETTER PHASE-E NGKUP;Lo;0;L;;;;;N;;;;; +169B7;BAMUM LETTER PHASE-E KET;Lo;0;L;;;;;N;;;;; +169B8;BAMUM LETTER PHASE-E MAE;Lo;0;L;;;;;N;;;;; +169B9;BAMUM LETTER PHASE-E NGKAAMI;Lo;0;L;;;;;N;;;;; +169BA;BAMUM LETTER PHASE-E GHET;Lo;0;L;;;;;N;;;;; +169BB;BAMUM LETTER PHASE-E FA;Lo;0;L;;;;;N;;;;; +169BC;BAMUM LETTER PHASE-E NTUM;Lo;0;L;;;;;N;;;;; +169BD;BAMUM LETTER PHASE-E PEUT;Lo;0;L;;;;;N;;;;; +169BE;BAMUM LETTER PHASE-E YEUM;Lo;0;L;;;;;N;;;;; +169BF;BAMUM LETTER PHASE-E NGGEUAE;Lo;0;L;;;;;N;;;;; +169C0;BAMUM LETTER PHASE-E NYI BETWEEN;Lo;0;L;;;;;N;;;;; +169C1;BAMUM LETTER PHASE-E NZUQ;Lo;0;L;;;;;N;;;;; +169C2;BAMUM LETTER PHASE-E POON;Lo;0;L;;;;;N;;;;; +169C3;BAMUM LETTER PHASE-E MIEE;Lo;0;L;;;;;N;;;;; +169C4;BAMUM LETTER PHASE-E FUET;Lo;0;L;;;;;N;;;;; +169C5;BAMUM LETTER PHASE-E NAE;Lo;0;L;;;;;N;;;;; +169C6;BAMUM LETTER PHASE-E MUAE;Lo;0;L;;;;;N;;;;; +169C7;BAMUM LETTER PHASE-E GHEUAE;Lo;0;L;;;;;N;;;;; +169C8;BAMUM LETTER PHASE-E FU I;Lo;0;L;;;;;N;;;;; +169C9;BAMUM LETTER PHASE-E MVI;Lo;0;L;;;;;N;;;;; +169CA;BAMUM LETTER PHASE-E PUAQ;Lo;0;L;;;;;N;;;;; +169CB;BAMUM LETTER PHASE-E NGKUM;Lo;0;L;;;;;N;;;;; +169CC;BAMUM LETTER PHASE-E KUT;Lo;0;L;;;;;N;;;;; +169CD;BAMUM LETTER PHASE-E PIET;Lo;0;L;;;;;N;;;;; +169CE;BAMUM LETTER PHASE-E NTAP;Lo;0;L;;;;;N;;;;; +169CF;BAMUM LETTER PHASE-E YEUAET;Lo;0;L;;;;;N;;;;; +169D0;BAMUM LETTER PHASE-E NGGUP;Lo;0;L;;;;;N;;;;; +169D1;BAMUM LETTER PHASE-E PA PEOPLE;Lo;0;L;;;;;N;;;;; +169D2;BAMUM LETTER PHASE-E FU CALL;Lo;0;L;;;;;N;;;;; +169D3;BAMUM LETTER PHASE-E FOM;Lo;0;L;;;;;N;;;;; +169D4;BAMUM LETTER PHASE-E NJEE;Lo;0;L;;;;;N;;;;; +169D5;BAMUM LETTER PHASE-E A;Lo;0;L;;;;;N;;;;; +169D6;BAMUM LETTER PHASE-E TOQ;Lo;0;L;;;;;N;;;;; +169D7;BAMUM LETTER PHASE-E O;Lo;0;L;;;;;N;;;;; +169D8;BAMUM LETTER PHASE-E I;Lo;0;L;;;;;N;;;;; +169D9;BAMUM LETTER PHASE-E LAQ;Lo;0;L;;;;;N;;;;; +169DA;BAMUM LETTER PHASE-E PA PLURAL;Lo;0;L;;;;;N;;;;; +169DB;BAMUM LETTER PHASE-E TAA;Lo;0;L;;;;;N;;;;; +169DC;BAMUM LETTER PHASE-E TAQ;Lo;0;L;;;;;N;;;;; +169DD;BAMUM LETTER PHASE-E NDAA MY HOUSE;Lo;0;L;;;;;N;;;;; +169DE;BAMUM LETTER PHASE-E SHIQ;Lo;0;L;;;;;N;;;;; +169DF;BAMUM LETTER PHASE-E YEUX;Lo;0;L;;;;;N;;;;; +169E0;BAMUM LETTER PHASE-E NGUAE;Lo;0;L;;;;;N;;;;; +169E1;BAMUM LETTER PHASE-E YUAEN;Lo;0;L;;;;;N;;;;; +169E2;BAMUM LETTER PHASE-E YOQ SWIMMING;Lo;0;L;;;;;N;;;;; +169E3;BAMUM LETTER PHASE-E YOQ COVER;Lo;0;L;;;;;N;;;;; +169E4;BAMUM LETTER PHASE-E YUQ;Lo;0;L;;;;;N;;;;; +169E5;BAMUM LETTER PHASE-E YUN;Lo;0;L;;;;;N;;;;; +169E6;BAMUM LETTER PHASE-E KEUX;Lo;0;L;;;;;N;;;;; +169E7;BAMUM LETTER PHASE-E PEUX;Lo;0;L;;;;;N;;;;; +169E8;BAMUM LETTER PHASE-E NJEE EPOCH;Lo;0;L;;;;;N;;;;; +169E9;BAMUM LETTER PHASE-E PUE;Lo;0;L;;;;;N;;;;; +169EA;BAMUM LETTER PHASE-E WUE;Lo;0;L;;;;;N;;;;; +169EB;BAMUM LETTER PHASE-E FEE;Lo;0;L;;;;;N;;;;; +169EC;BAMUM LETTER PHASE-E VEE;Lo;0;L;;;;;N;;;;; +169ED;BAMUM LETTER PHASE-E LU;Lo;0;L;;;;;N;;;;; +169EE;BAMUM LETTER PHASE-E MI;Lo;0;L;;;;;N;;;;; +169EF;BAMUM LETTER PHASE-E REUX;Lo;0;L;;;;;N;;;;; +169F0;BAMUM LETTER PHASE-E RAE;Lo;0;L;;;;;N;;;;; +169F1;BAMUM LETTER PHASE-E NGUAET;Lo;0;L;;;;;N;;;;; +169F2;BAMUM LETTER PHASE-E NGA;Lo;0;L;;;;;N;;;;; +169F3;BAMUM LETTER PHASE-E SHO;Lo;0;L;;;;;N;;;;; +169F4;BAMUM LETTER PHASE-E SHOQ;Lo;0;L;;;;;N;;;;; +169F5;BAMUM LETTER PHASE-E FU REMEDY;Lo;0;L;;;;;N;;;;; +169F6;BAMUM LETTER PHASE-E NA;Lo;0;L;;;;;N;;;;; +169F7;BAMUM LETTER PHASE-E PI;Lo;0;L;;;;;N;;;;; +169F8;BAMUM LETTER PHASE-E LOQ;Lo;0;L;;;;;N;;;;; +169F9;BAMUM LETTER PHASE-E KO;Lo;0;L;;;;;N;;;;; +169FA;BAMUM LETTER PHASE-E MEN;Lo;0;L;;;;;N;;;;; +169FB;BAMUM LETTER PHASE-E MA;Lo;0;L;;;;;N;;;;; +169FC;BAMUM LETTER PHASE-E MAQ;Lo;0;L;;;;;N;;;;; +169FD;BAMUM LETTER PHASE-E TEU;Lo;0;L;;;;;N;;;;; +169FE;BAMUM LETTER PHASE-E KI;Lo;0;L;;;;;N;;;;; +169FF;BAMUM LETTER PHASE-E MON;Lo;0;L;;;;;N;;;;; +16A00;BAMUM LETTER PHASE-E TEN;Lo;0;L;;;;;N;;;;; +16A01;BAMUM LETTER PHASE-E FAQ;Lo;0;L;;;;;N;;;;; +16A02;BAMUM LETTER PHASE-E GHOM;Lo;0;L;;;;;N;;;;; +16A03;BAMUM LETTER PHASE-F KA;Lo;0;L;;;;;N;;;;; +16A04;BAMUM LETTER PHASE-F U;Lo;0;L;;;;;N;;;;; +16A05;BAMUM LETTER PHASE-F KU;Lo;0;L;;;;;N;;;;; +16A06;BAMUM LETTER PHASE-F EE;Lo;0;L;;;;;N;;;;; +16A07;BAMUM LETTER PHASE-F REE;Lo;0;L;;;;;N;;;;; +16A08;BAMUM LETTER PHASE-F TAE;Lo;0;L;;;;;N;;;;; +16A09;BAMUM LETTER PHASE-F NYI;Lo;0;L;;;;;N;;;;; +16A0A;BAMUM LETTER PHASE-F LA;Lo;0;L;;;;;N;;;;; +16A0B;BAMUM LETTER PHASE-F RII;Lo;0;L;;;;;N;;;;; +16A0C;BAMUM LETTER PHASE-F RIEE;Lo;0;L;;;;;N;;;;; +16A0D;BAMUM LETTER PHASE-F MEEEE;Lo;0;L;;;;;N;;;;; +16A0E;BAMUM LETTER PHASE-F TAA;Lo;0;L;;;;;N;;;;; +16A0F;BAMUM LETTER PHASE-F NDAA;Lo;0;L;;;;;N;;;;; +16A10;BAMUM LETTER PHASE-F NJAEM;Lo;0;L;;;;;N;;;;; +16A11;BAMUM LETTER PHASE-F M;Lo;0;L;;;;;N;;;;; +16A12;BAMUM LETTER PHASE-F SUU;Lo;0;L;;;;;N;;;;; +16A13;BAMUM LETTER PHASE-F SHII;Lo;0;L;;;;;N;;;;; +16A14;BAMUM LETTER PHASE-F SI;Lo;0;L;;;;;N;;;;; +16A15;BAMUM LETTER PHASE-F SEUX;Lo;0;L;;;;;N;;;;; +16A16;BAMUM LETTER PHASE-F KYEE;Lo;0;L;;;;;N;;;;; +16A17;BAMUM LETTER PHASE-F KET;Lo;0;L;;;;;N;;;;; +16A18;BAMUM LETTER PHASE-F NUAE;Lo;0;L;;;;;N;;;;; +16A19;BAMUM LETTER PHASE-F NU;Lo;0;L;;;;;N;;;;; +16A1A;BAMUM LETTER PHASE-F NJUAE;Lo;0;L;;;;;N;;;;; +16A1B;BAMUM LETTER PHASE-F YOQ;Lo;0;L;;;;;N;;;;; +16A1C;BAMUM LETTER PHASE-F SHU;Lo;0;L;;;;;N;;;;; +16A1D;BAMUM LETTER PHASE-F YA;Lo;0;L;;;;;N;;;;; +16A1E;BAMUM LETTER PHASE-F NSHA;Lo;0;L;;;;;N;;;;; +16A1F;BAMUM LETTER PHASE-F PEUX;Lo;0;L;;;;;N;;;;; +16A20;BAMUM LETTER PHASE-F NTEE;Lo;0;L;;;;;N;;;;; +16A21;BAMUM LETTER PHASE-F WUE;Lo;0;L;;;;;N;;;;; +16A22;BAMUM LETTER PHASE-F PEE;Lo;0;L;;;;;N;;;;; +16A23;BAMUM LETTER PHASE-F RU;Lo;0;L;;;;;N;;;;; +16A24;BAMUM LETTER PHASE-F NI;Lo;0;L;;;;;N;;;;; +16A25;BAMUM LETTER PHASE-F REUX;Lo;0;L;;;;;N;;;;; +16A26;BAMUM LETTER PHASE-F KEN;Lo;0;L;;;;;N;;;;; +16A27;BAMUM LETTER PHASE-F NGKWAEN;Lo;0;L;;;;;N;;;;; +16A28;BAMUM LETTER PHASE-F NGGA;Lo;0;L;;;;;N;;;;; +16A29;BAMUM LETTER PHASE-F SHO;Lo;0;L;;;;;N;;;;; +16A2A;BAMUM LETTER PHASE-F PUAE;Lo;0;L;;;;;N;;;;; +16A2B;BAMUM LETTER PHASE-F FOM;Lo;0;L;;;;;N;;;;; +16A2C;BAMUM LETTER PHASE-F WA;Lo;0;L;;;;;N;;;;; +16A2D;BAMUM LETTER PHASE-F LI;Lo;0;L;;;;;N;;;;; +16A2E;BAMUM LETTER PHASE-F LOQ;Lo;0;L;;;;;N;;;;; +16A2F;BAMUM LETTER PHASE-F KO;Lo;0;L;;;;;N;;;;; +16A30;BAMUM LETTER PHASE-F MBEN;Lo;0;L;;;;;N;;;;; +16A31;BAMUM LETTER PHASE-F REN;Lo;0;L;;;;;N;;;;; +16A32;BAMUM LETTER PHASE-F MA;Lo;0;L;;;;;N;;;;; +16A33;BAMUM LETTER PHASE-F MO;Lo;0;L;;;;;N;;;;; +16A34;BAMUM LETTER PHASE-F MBAA;Lo;0;L;;;;;N;;;;; +16A35;BAMUM LETTER PHASE-F TET;Lo;0;L;;;;;N;;;;; +16A36;BAMUM LETTER PHASE-F KPA;Lo;0;L;;;;;N;;;;; +16A37;BAMUM LETTER PHASE-F SAMBA;Lo;0;L;;;;;N;;;;; +16A38;BAMUM LETTER PHASE-F VUEQ;Lo;0;L;;;;;N;;;;; +16A40;MRO LETTER TA;Lo;0;L;;;;;N;;;;; +16A41;MRO LETTER NGI;Lo;0;L;;;;;N;;;;; +16A42;MRO LETTER YO;Lo;0;L;;;;;N;;;;; +16A43;MRO LETTER MIM;Lo;0;L;;;;;N;;;;; +16A44;MRO LETTER BA;Lo;0;L;;;;;N;;;;; +16A45;MRO LETTER DA;Lo;0;L;;;;;N;;;;; +16A46;MRO LETTER A;Lo;0;L;;;;;N;;;;; +16A47;MRO LETTER PHI;Lo;0;L;;;;;N;;;;; +16A48;MRO LETTER KHAI;Lo;0;L;;;;;N;;;;; +16A49;MRO LETTER HAO;Lo;0;L;;;;;N;;;;; +16A4A;MRO LETTER DAI;Lo;0;L;;;;;N;;;;; +16A4B;MRO LETTER CHU;Lo;0;L;;;;;N;;;;; +16A4C;MRO LETTER KEAAE;Lo;0;L;;;;;N;;;;; +16A4D;MRO LETTER OL;Lo;0;L;;;;;N;;;;; +16A4E;MRO LETTER MAEM;Lo;0;L;;;;;N;;;;; +16A4F;MRO LETTER NIN;Lo;0;L;;;;;N;;;;; +16A50;MRO LETTER PA;Lo;0;L;;;;;N;;;;; +16A51;MRO LETTER OO;Lo;0;L;;;;;N;;;;; +16A52;MRO LETTER O;Lo;0;L;;;;;N;;;;; +16A53;MRO LETTER RO;Lo;0;L;;;;;N;;;;; +16A54;MRO LETTER SHI;Lo;0;L;;;;;N;;;;; +16A55;MRO LETTER THEA;Lo;0;L;;;;;N;;;;; +16A56;MRO LETTER EA;Lo;0;L;;;;;N;;;;; +16A57;MRO LETTER WA;Lo;0;L;;;;;N;;;;; +16A58;MRO LETTER E;Lo;0;L;;;;;N;;;;; +16A59;MRO LETTER KO;Lo;0;L;;;;;N;;;;; +16A5A;MRO LETTER LAN;Lo;0;L;;;;;N;;;;; +16A5B;MRO LETTER LA;Lo;0;L;;;;;N;;;;; +16A5C;MRO LETTER HAI;Lo;0;L;;;;;N;;;;; +16A5D;MRO LETTER RI;Lo;0;L;;;;;N;;;;; +16A5E;MRO LETTER TEK;Lo;0;L;;;;;N;;;;; +16A60;MRO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +16A61;MRO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +16A62;MRO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +16A63;MRO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +16A64;MRO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +16A65;MRO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +16A66;MRO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +16A67;MRO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +16A68;MRO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +16A69;MRO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +16A6E;MRO DANDA;Po;0;L;;;;;N;;;;; +16A6F;MRO DOUBLE DANDA;Po;0;L;;;;;N;;;;; +16AD0;BASSA VAH LETTER ENNI;Lo;0;L;;;;;N;;;;; +16AD1;BASSA VAH LETTER KA;Lo;0;L;;;;;N;;;;; +16AD2;BASSA VAH LETTER SE;Lo;0;L;;;;;N;;;;; +16AD3;BASSA VAH LETTER FA;Lo;0;L;;;;;N;;;;; +16AD4;BASSA VAH LETTER MBE;Lo;0;L;;;;;N;;;;; +16AD5;BASSA VAH LETTER YIE;Lo;0;L;;;;;N;;;;; +16AD6;BASSA VAH LETTER GAH;Lo;0;L;;;;;N;;;;; +16AD7;BASSA VAH LETTER DHII;Lo;0;L;;;;;N;;;;; +16AD8;BASSA VAH LETTER KPAH;Lo;0;L;;;;;N;;;;; +16AD9;BASSA VAH LETTER JO;Lo;0;L;;;;;N;;;;; +16ADA;BASSA VAH LETTER HWAH;Lo;0;L;;;;;N;;;;; +16ADB;BASSA VAH LETTER WA;Lo;0;L;;;;;N;;;;; +16ADC;BASSA VAH LETTER ZO;Lo;0;L;;;;;N;;;;; +16ADD;BASSA VAH LETTER GBU;Lo;0;L;;;;;N;;;;; +16ADE;BASSA VAH LETTER DO;Lo;0;L;;;;;N;;;;; +16ADF;BASSA VAH LETTER CE;Lo;0;L;;;;;N;;;;; +16AE0;BASSA VAH LETTER UWU;Lo;0;L;;;;;N;;;;; +16AE1;BASSA VAH LETTER TO;Lo;0;L;;;;;N;;;;; +16AE2;BASSA VAH LETTER BA;Lo;0;L;;;;;N;;;;; +16AE3;BASSA VAH LETTER VU;Lo;0;L;;;;;N;;;;; +16AE4;BASSA VAH LETTER YEIN;Lo;0;L;;;;;N;;;;; +16AE5;BASSA VAH LETTER PA;Lo;0;L;;;;;N;;;;; +16AE6;BASSA VAH LETTER WADDA;Lo;0;L;;;;;N;;;;; +16AE7;BASSA VAH LETTER A;Lo;0;L;;;;;N;;;;; +16AE8;BASSA VAH LETTER O;Lo;0;L;;;;;N;;;;; +16AE9;BASSA VAH LETTER OO;Lo;0;L;;;;;N;;;;; +16AEA;BASSA VAH LETTER U;Lo;0;L;;;;;N;;;;; +16AEB;BASSA VAH LETTER EE;Lo;0;L;;;;;N;;;;; +16AEC;BASSA VAH LETTER E;Lo;0;L;;;;;N;;;;; +16AED;BASSA VAH LETTER I;Lo;0;L;;;;;N;;;;; +16AF0;BASSA VAH COMBINING HIGH TONE;Mn;1;NSM;;;;;N;;;;; +16AF1;BASSA VAH COMBINING LOW TONE;Mn;1;NSM;;;;;N;;;;; +16AF2;BASSA VAH COMBINING MID TONE;Mn;1;NSM;;;;;N;;;;; +16AF3;BASSA VAH COMBINING LOW-MID TONE;Mn;1;NSM;;;;;N;;;;; +16AF4;BASSA VAH COMBINING HIGH-LOW TONE;Mn;1;NSM;;;;;N;;;;; +16AF5;BASSA VAH FULL STOP;Po;0;L;;;;;N;;;;; +16B00;PAHAWH HMONG VOWEL KEEB;Lo;0;L;;;;;N;;;;; +16B01;PAHAWH HMONG VOWEL KEEV;Lo;0;L;;;;;N;;;;; +16B02;PAHAWH HMONG VOWEL KIB;Lo;0;L;;;;;N;;;;; +16B03;PAHAWH HMONG VOWEL KIV;Lo;0;L;;;;;N;;;;; +16B04;PAHAWH HMONG VOWEL KAUB;Lo;0;L;;;;;N;;;;; +16B05;PAHAWH HMONG VOWEL KAUV;Lo;0;L;;;;;N;;;;; +16B06;PAHAWH HMONG VOWEL KUB;Lo;0;L;;;;;N;;;;; +16B07;PAHAWH HMONG VOWEL KUV;Lo;0;L;;;;;N;;;;; +16B08;PAHAWH HMONG VOWEL KEB;Lo;0;L;;;;;N;;;;; +16B09;PAHAWH HMONG VOWEL KEV;Lo;0;L;;;;;N;;;;; +16B0A;PAHAWH HMONG VOWEL KAIB;Lo;0;L;;;;;N;;;;; +16B0B;PAHAWH HMONG VOWEL KAIV;Lo;0;L;;;;;N;;;;; +16B0C;PAHAWH HMONG VOWEL KOOB;Lo;0;L;;;;;N;;;;; +16B0D;PAHAWH HMONG VOWEL KOOV;Lo;0;L;;;;;N;;;;; +16B0E;PAHAWH HMONG VOWEL KAWB;Lo;0;L;;;;;N;;;;; +16B0F;PAHAWH HMONG VOWEL KAWV;Lo;0;L;;;;;N;;;;; +16B10;PAHAWH HMONG VOWEL KUAB;Lo;0;L;;;;;N;;;;; +16B11;PAHAWH HMONG VOWEL KUAV;Lo;0;L;;;;;N;;;;; +16B12;PAHAWH HMONG VOWEL KOB;Lo;0;L;;;;;N;;;;; +16B13;PAHAWH HMONG VOWEL KOV;Lo;0;L;;;;;N;;;;; +16B14;PAHAWH HMONG VOWEL KIAB;Lo;0;L;;;;;N;;;;; +16B15;PAHAWH HMONG VOWEL KIAV;Lo;0;L;;;;;N;;;;; +16B16;PAHAWH HMONG VOWEL KAB;Lo;0;L;;;;;N;;;;; +16B17;PAHAWH HMONG VOWEL KAV;Lo;0;L;;;;;N;;;;; +16B18;PAHAWH HMONG VOWEL KWB;Lo;0;L;;;;;N;;;;; +16B19;PAHAWH HMONG VOWEL KWV;Lo;0;L;;;;;N;;;;; +16B1A;PAHAWH HMONG VOWEL KAAB;Lo;0;L;;;;;N;;;;; +16B1B;PAHAWH HMONG VOWEL KAAV;Lo;0;L;;;;;N;;;;; +16B1C;PAHAWH HMONG CONSONANT VAU;Lo;0;L;;;;;N;;;;; +16B1D;PAHAWH HMONG CONSONANT NTSAU;Lo;0;L;;;;;N;;;;; +16B1E;PAHAWH HMONG CONSONANT LAU;Lo;0;L;;;;;N;;;;; +16B1F;PAHAWH HMONG CONSONANT HAU;Lo;0;L;;;;;N;;;;; +16B20;PAHAWH HMONG CONSONANT NLAU;Lo;0;L;;;;;N;;;;; +16B21;PAHAWH HMONG CONSONANT RAU;Lo;0;L;;;;;N;;;;; +16B22;PAHAWH HMONG CONSONANT NKAU;Lo;0;L;;;;;N;;;;; +16B23;PAHAWH HMONG CONSONANT QHAU;Lo;0;L;;;;;N;;;;; +16B24;PAHAWH HMONG CONSONANT YAU;Lo;0;L;;;;;N;;;;; +16B25;PAHAWH HMONG CONSONANT HLAU;Lo;0;L;;;;;N;;;;; +16B26;PAHAWH HMONG CONSONANT MAU;Lo;0;L;;;;;N;;;;; +16B27;PAHAWH HMONG CONSONANT CHAU;Lo;0;L;;;;;N;;;;; +16B28;PAHAWH HMONG CONSONANT NCHAU;Lo;0;L;;;;;N;;;;; +16B29;PAHAWH HMONG CONSONANT HNAU;Lo;0;L;;;;;N;;;;; +16B2A;PAHAWH HMONG CONSONANT PLHAU;Lo;0;L;;;;;N;;;;; +16B2B;PAHAWH HMONG CONSONANT NTHAU;Lo;0;L;;;;;N;;;;; +16B2C;PAHAWH HMONG CONSONANT NAU;Lo;0;L;;;;;N;;;;; +16B2D;PAHAWH HMONG CONSONANT AU;Lo;0;L;;;;;N;;;;; +16B2E;PAHAWH HMONG CONSONANT XAU;Lo;0;L;;;;;N;;;;; +16B2F;PAHAWH HMONG CONSONANT CAU;Lo;0;L;;;;;N;;;;; +16B30;PAHAWH HMONG MARK CIM TUB;Mn;230;NSM;;;;;N;;;;; +16B31;PAHAWH HMONG MARK CIM SO;Mn;230;NSM;;;;;N;;;;; +16B32;PAHAWH HMONG MARK CIM KES;Mn;230;NSM;;;;;N;;;;; +16B33;PAHAWH HMONG MARK CIM KHAV;Mn;230;NSM;;;;;N;;;;; +16B34;PAHAWH HMONG MARK CIM SUAM;Mn;230;NSM;;;;;N;;;;; +16B35;PAHAWH HMONG MARK CIM HOM;Mn;230;NSM;;;;;N;;;;; +16B36;PAHAWH HMONG MARK CIM TAUM;Mn;230;NSM;;;;;N;;;;; +16B37;PAHAWH HMONG SIGN VOS THOM;Po;0;L;;;;;N;;;;; +16B38;PAHAWH HMONG SIGN VOS TSHAB CEEB;Po;0;L;;;;;N;;;;; +16B39;PAHAWH HMONG SIGN CIM CHEEM;Po;0;L;;;;;N;;;;; +16B3A;PAHAWH HMONG SIGN VOS THIAB;Po;0;L;;;;;N;;;;; +16B3B;PAHAWH HMONG SIGN VOS FEEM;Po;0;L;;;;;N;;;;; +16B3C;PAHAWH HMONG SIGN XYEEM NTXIV;So;0;L;;;;;N;;;;; +16B3D;PAHAWH HMONG SIGN XYEEM RHO;So;0;L;;;;;N;;;;; +16B3E;PAHAWH HMONG SIGN XYEEM TOV;So;0;L;;;;;N;;;;; +16B3F;PAHAWH HMONG SIGN XYEEM FAIB;So;0;L;;;;;N;;;;; +16B40;PAHAWH HMONG SIGN VOS SEEV;Lm;0;L;;;;;N;;;;; +16B41;PAHAWH HMONG SIGN MEEJ SUAB;Lm;0;L;;;;;N;;;;; +16B42;PAHAWH HMONG SIGN VOS NRUA;Lm;0;L;;;;;N;;;;; +16B43;PAHAWH HMONG SIGN IB YAM;Lm;0;L;;;;;N;;;;; +16B44;PAHAWH HMONG SIGN XAUS;Po;0;L;;;;;N;;;;; +16B45;PAHAWH HMONG SIGN CIM TSOV ROG;So;0;L;;;;;N;;;;; +16B50;PAHAWH HMONG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +16B51;PAHAWH HMONG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +16B52;PAHAWH HMONG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +16B53;PAHAWH HMONG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +16B54;PAHAWH HMONG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +16B55;PAHAWH HMONG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +16B56;PAHAWH HMONG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +16B57;PAHAWH HMONG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +16B58;PAHAWH HMONG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +16B59;PAHAWH HMONG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +16B5B;PAHAWH HMONG NUMBER TENS;No;0;L;;;;10;N;;;;; +16B5C;PAHAWH HMONG NUMBER HUNDREDS;No;0;L;;;;100;N;;;;; +16B5D;PAHAWH HMONG NUMBER TEN THOUSANDS;No;0;L;;;;10000;N;;;;; +16B5E;PAHAWH HMONG NUMBER MILLIONS;No;0;L;;;;1000000;N;;;;; +16B5F;PAHAWH HMONG NUMBER HUNDRED MILLIONS;No;0;L;;;;100000000;N;;;;; +16B60;PAHAWH HMONG NUMBER TEN BILLIONS;No;0;L;;;;10000000000;N;;;;; +16B61;PAHAWH HMONG NUMBER TRILLIONS;No;0;L;;;;1000000000000;N;;;;; +16B63;PAHAWH HMONG SIGN VOS LUB;Lo;0;L;;;;;N;;;;; +16B64;PAHAWH HMONG SIGN XYOO;Lo;0;L;;;;;N;;;;; +16B65;PAHAWH HMONG SIGN HLI;Lo;0;L;;;;;N;;;;; +16B66;PAHAWH HMONG SIGN THIRD-STAGE HLI;Lo;0;L;;;;;N;;;;; +16B67;PAHAWH HMONG SIGN ZWJ THAJ;Lo;0;L;;;;;N;;;;; +16B68;PAHAWH HMONG SIGN HNUB;Lo;0;L;;;;;N;;;;; +16B69;PAHAWH HMONG SIGN NQIG;Lo;0;L;;;;;N;;;;; +16B6A;PAHAWH HMONG SIGN XIAB;Lo;0;L;;;;;N;;;;; +16B6B;PAHAWH HMONG SIGN NTUJ;Lo;0;L;;;;;N;;;;; +16B6C;PAHAWH HMONG SIGN AV;Lo;0;L;;;;;N;;;;; +16B6D;PAHAWH HMONG SIGN TXHEEJ CEEV;Lo;0;L;;;;;N;;;;; +16B6E;PAHAWH HMONG SIGN MEEJ TSEEB;Lo;0;L;;;;;N;;;;; +16B6F;PAHAWH HMONG SIGN TAU;Lo;0;L;;;;;N;;;;; +16B70;PAHAWH HMONG SIGN LOS;Lo;0;L;;;;;N;;;;; +16B71;PAHAWH HMONG SIGN MUS;Lo;0;L;;;;;N;;;;; +16B72;PAHAWH HMONG SIGN CIM HAIS LUS NTOG NTOG;Lo;0;L;;;;;N;;;;; +16B73;PAHAWH HMONG SIGN CIM CUAM TSHOOJ;Lo;0;L;;;;;N;;;;; +16B74;PAHAWH HMONG SIGN CIM TXWV;Lo;0;L;;;;;N;;;;; +16B75;PAHAWH HMONG SIGN CIM TXWV CHWV;Lo;0;L;;;;;N;;;;; +16B76;PAHAWH HMONG SIGN CIM PUB DAWB;Lo;0;L;;;;;N;;;;; +16B77;PAHAWH HMONG SIGN CIM NRES TOS;Lo;0;L;;;;;N;;;;; +16B7D;PAHAWH HMONG CLAN SIGN TSHEEJ;Lo;0;L;;;;;N;;;;; +16B7E;PAHAWH HMONG CLAN SIGN YEEG;Lo;0;L;;;;;N;;;;; +16B7F;PAHAWH HMONG CLAN SIGN LIS;Lo;0;L;;;;;N;;;;; +16B80;PAHAWH HMONG CLAN SIGN LAUJ;Lo;0;L;;;;;N;;;;; +16B81;PAHAWH HMONG CLAN SIGN XYOOJ;Lo;0;L;;;;;N;;;;; +16B82;PAHAWH HMONG CLAN SIGN KOO;Lo;0;L;;;;;N;;;;; +16B83;PAHAWH HMONG CLAN SIGN HAWJ;Lo;0;L;;;;;N;;;;; +16B84;PAHAWH HMONG CLAN SIGN MUAS;Lo;0;L;;;;;N;;;;; +16B85;PAHAWH HMONG CLAN SIGN THOJ;Lo;0;L;;;;;N;;;;; +16B86;PAHAWH HMONG CLAN SIGN TSAB;Lo;0;L;;;;;N;;;;; +16B87;PAHAWH HMONG CLAN SIGN PHAB;Lo;0;L;;;;;N;;;;; +16B88;PAHAWH HMONG CLAN SIGN KHAB;Lo;0;L;;;;;N;;;;; +16B89;PAHAWH HMONG CLAN SIGN HAM;Lo;0;L;;;;;N;;;;; +16B8A;PAHAWH HMONG CLAN SIGN VAJ;Lo;0;L;;;;;N;;;;; +16B8B;PAHAWH HMONG CLAN SIGN FAJ;Lo;0;L;;;;;N;;;;; +16B8C;PAHAWH HMONG CLAN SIGN YAJ;Lo;0;L;;;;;N;;;;; +16B8D;PAHAWH HMONG CLAN SIGN TSWB;Lo;0;L;;;;;N;;;;; +16B8E;PAHAWH HMONG CLAN SIGN KWM;Lo;0;L;;;;;N;;;;; +16B8F;PAHAWH HMONG CLAN SIGN VWJ;Lo;0;L;;;;;N;;;;; +16F00;MIAO LETTER PA;Lo;0;L;;;;;N;;;;; +16F01;MIAO LETTER BA;Lo;0;L;;;;;N;;;;; +16F02;MIAO LETTER YI PA;Lo;0;L;;;;;N;;;;; +16F03;MIAO LETTER PLA;Lo;0;L;;;;;N;;;;; +16F04;MIAO LETTER MA;Lo;0;L;;;;;N;;;;; +16F05;MIAO LETTER MHA;Lo;0;L;;;;;N;;;;; +16F06;MIAO LETTER ARCHAIC MA;Lo;0;L;;;;;N;;;;; +16F07;MIAO LETTER FA;Lo;0;L;;;;;N;;;;; +16F08;MIAO LETTER VA;Lo;0;L;;;;;N;;;;; +16F09;MIAO LETTER VFA;Lo;0;L;;;;;N;;;;; +16F0A;MIAO LETTER TA;Lo;0;L;;;;;N;;;;; +16F0B;MIAO LETTER DA;Lo;0;L;;;;;N;;;;; +16F0C;MIAO LETTER YI TTA;Lo;0;L;;;;;N;;;;; +16F0D;MIAO LETTER YI TA;Lo;0;L;;;;;N;;;;; +16F0E;MIAO LETTER TTA;Lo;0;L;;;;;N;;;;; +16F0F;MIAO LETTER DDA;Lo;0;L;;;;;N;;;;; +16F10;MIAO LETTER NA;Lo;0;L;;;;;N;;;;; +16F11;MIAO LETTER NHA;Lo;0;L;;;;;N;;;;; +16F12;MIAO LETTER YI NNA;Lo;0;L;;;;;N;;;;; +16F13;MIAO LETTER ARCHAIC NA;Lo;0;L;;;;;N;;;;; +16F14;MIAO LETTER NNA;Lo;0;L;;;;;N;;;;; +16F15;MIAO LETTER NNHA;Lo;0;L;;;;;N;;;;; +16F16;MIAO LETTER LA;Lo;0;L;;;;;N;;;;; +16F17;MIAO LETTER LYA;Lo;0;L;;;;;N;;;;; +16F18;MIAO LETTER LHA;Lo;0;L;;;;;N;;;;; +16F19;MIAO LETTER LHYA;Lo;0;L;;;;;N;;;;; +16F1A;MIAO LETTER TLHA;Lo;0;L;;;;;N;;;;; +16F1B;MIAO LETTER DLHA;Lo;0;L;;;;;N;;;;; +16F1C;MIAO LETTER TLHYA;Lo;0;L;;;;;N;;;;; +16F1D;MIAO LETTER DLHYA;Lo;0;L;;;;;N;;;;; +16F1E;MIAO LETTER KA;Lo;0;L;;;;;N;;;;; +16F1F;MIAO LETTER GA;Lo;0;L;;;;;N;;;;; +16F20;MIAO LETTER YI KA;Lo;0;L;;;;;N;;;;; +16F21;MIAO LETTER QA;Lo;0;L;;;;;N;;;;; +16F22;MIAO LETTER QGA;Lo;0;L;;;;;N;;;;; +16F23;MIAO LETTER NGA;Lo;0;L;;;;;N;;;;; +16F24;MIAO LETTER NGHA;Lo;0;L;;;;;N;;;;; +16F25;MIAO LETTER ARCHAIC NGA;Lo;0;L;;;;;N;;;;; +16F26;MIAO LETTER HA;Lo;0;L;;;;;N;;;;; +16F27;MIAO LETTER XA;Lo;0;L;;;;;N;;;;; +16F28;MIAO LETTER GHA;Lo;0;L;;;;;N;;;;; +16F29;MIAO LETTER GHHA;Lo;0;L;;;;;N;;;;; +16F2A;MIAO LETTER TSSA;Lo;0;L;;;;;N;;;;; +16F2B;MIAO LETTER DZZA;Lo;0;L;;;;;N;;;;; +16F2C;MIAO LETTER NYA;Lo;0;L;;;;;N;;;;; +16F2D;MIAO LETTER NYHA;Lo;0;L;;;;;N;;;;; +16F2E;MIAO LETTER TSHA;Lo;0;L;;;;;N;;;;; +16F2F;MIAO LETTER DZHA;Lo;0;L;;;;;N;;;;; +16F30;MIAO LETTER YI TSHA;Lo;0;L;;;;;N;;;;; +16F31;MIAO LETTER YI DZHA;Lo;0;L;;;;;N;;;;; +16F32;MIAO LETTER REFORMED TSHA;Lo;0;L;;;;;N;;;;; +16F33;MIAO LETTER SHA;Lo;0;L;;;;;N;;;;; +16F34;MIAO LETTER SSA;Lo;0;L;;;;;N;;;;; +16F35;MIAO LETTER ZHA;Lo;0;L;;;;;N;;;;; +16F36;MIAO LETTER ZSHA;Lo;0;L;;;;;N;;;;; +16F37;MIAO LETTER TSA;Lo;0;L;;;;;N;;;;; +16F38;MIAO LETTER DZA;Lo;0;L;;;;;N;;;;; +16F39;MIAO LETTER YI TSA;Lo;0;L;;;;;N;;;;; +16F3A;MIAO LETTER SA;Lo;0;L;;;;;N;;;;; +16F3B;MIAO LETTER ZA;Lo;0;L;;;;;N;;;;; +16F3C;MIAO LETTER ZSA;Lo;0;L;;;;;N;;;;; +16F3D;MIAO LETTER ZZA;Lo;0;L;;;;;N;;;;; +16F3E;MIAO LETTER ZZSA;Lo;0;L;;;;;N;;;;; +16F3F;MIAO LETTER ARCHAIC ZZA;Lo;0;L;;;;;N;;;;; +16F40;MIAO LETTER ZZYA;Lo;0;L;;;;;N;;;;; +16F41;MIAO LETTER ZZSYA;Lo;0;L;;;;;N;;;;; +16F42;MIAO LETTER WA;Lo;0;L;;;;;N;;;;; +16F43;MIAO LETTER AH;Lo;0;L;;;;;N;;;;; +16F44;MIAO LETTER HHA;Lo;0;L;;;;;N;;;;; +16F50;MIAO LETTER NASALIZATION;Lo;0;L;;;;;N;;;;; +16F51;MIAO SIGN ASPIRATION;Mc;0;L;;;;;N;;;;; +16F52;MIAO SIGN REFORMED VOICING;Mc;0;L;;;;;N;;;;; +16F53;MIAO SIGN REFORMED ASPIRATION;Mc;0;L;;;;;N;;;;; +16F54;MIAO VOWEL SIGN A;Mc;0;L;;;;;N;;;;; +16F55;MIAO VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +16F56;MIAO VOWEL SIGN AHH;Mc;0;L;;;;;N;;;;; +16F57;MIAO VOWEL SIGN AN;Mc;0;L;;;;;N;;;;; +16F58;MIAO VOWEL SIGN ANG;Mc;0;L;;;;;N;;;;; +16F59;MIAO VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +16F5A;MIAO VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +16F5B;MIAO VOWEL SIGN WO;Mc;0;L;;;;;N;;;;; +16F5C;MIAO VOWEL SIGN W;Mc;0;L;;;;;N;;;;; +16F5D;MIAO VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +16F5E;MIAO VOWEL SIGN EN;Mc;0;L;;;;;N;;;;; +16F5F;MIAO VOWEL SIGN ENG;Mc;0;L;;;;;N;;;;; +16F60;MIAO VOWEL SIGN OEY;Mc;0;L;;;;;N;;;;; +16F61;MIAO VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +16F62;MIAO VOWEL SIGN IA;Mc;0;L;;;;;N;;;;; +16F63;MIAO VOWEL SIGN IAN;Mc;0;L;;;;;N;;;;; +16F64;MIAO VOWEL SIGN IANG;Mc;0;L;;;;;N;;;;; +16F65;MIAO VOWEL SIGN IO;Mc;0;L;;;;;N;;;;; +16F66;MIAO VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; +16F67;MIAO VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +16F68;MIAO VOWEL SIGN IU;Mc;0;L;;;;;N;;;;; +16F69;MIAO VOWEL SIGN ING;Mc;0;L;;;;;N;;;;; +16F6A;MIAO VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +16F6B;MIAO VOWEL SIGN UA;Mc;0;L;;;;;N;;;;; +16F6C;MIAO VOWEL SIGN UAN;Mc;0;L;;;;;N;;;;; +16F6D;MIAO VOWEL SIGN UANG;Mc;0;L;;;;;N;;;;; +16F6E;MIAO VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +16F6F;MIAO VOWEL SIGN UEI;Mc;0;L;;;;;N;;;;; +16F70;MIAO VOWEL SIGN UNG;Mc;0;L;;;;;N;;;;; +16F71;MIAO VOWEL SIGN Y;Mc;0;L;;;;;N;;;;; +16F72;MIAO VOWEL SIGN YI;Mc;0;L;;;;;N;;;;; +16F73;MIAO VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; +16F74;MIAO VOWEL SIGN AEE;Mc;0;L;;;;;N;;;;; +16F75;MIAO VOWEL SIGN ERR;Mc;0;L;;;;;N;;;;; +16F76;MIAO VOWEL SIGN ROUNDED ERR;Mc;0;L;;;;;N;;;;; +16F77;MIAO VOWEL SIGN ER;Mc;0;L;;;;;N;;;;; +16F78;MIAO VOWEL SIGN ROUNDED ER;Mc;0;L;;;;;N;;;;; +16F79;MIAO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +16F7A;MIAO VOWEL SIGN EI;Mc;0;L;;;;;N;;;;; +16F7B;MIAO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +16F7C;MIAO VOWEL SIGN OU;Mc;0;L;;;;;N;;;;; +16F7D;MIAO VOWEL SIGN N;Mc;0;L;;;;;N;;;;; +16F7E;MIAO VOWEL SIGN NG;Mc;0;L;;;;;N;;;;; +16F8F;MIAO TONE RIGHT;Mn;0;NSM;;;;;N;;;;; +16F90;MIAO TONE TOP RIGHT;Mn;0;NSM;;;;;N;;;;; +16F91;MIAO TONE ABOVE;Mn;0;NSM;;;;;N;;;;; +16F92;MIAO TONE BELOW;Mn;0;NSM;;;;;N;;;;; +16F93;MIAO LETTER TONE-2;Lm;0;L;;;;;N;;;;; +16F94;MIAO LETTER TONE-3;Lm;0;L;;;;;N;;;;; +16F95;MIAO LETTER TONE-4;Lm;0;L;;;;;N;;;;; +16F96;MIAO LETTER TONE-5;Lm;0;L;;;;;N;;;;; +16F97;MIAO LETTER TONE-6;Lm;0;L;;;;;N;;;;; +16F98;MIAO LETTER TONE-7;Lm;0;L;;;;;N;;;;; +16F99;MIAO LETTER TONE-8;Lm;0;L;;;;;N;;;;; +16F9A;MIAO LETTER REFORMED TONE-1;Lm;0;L;;;;;N;;;;; +16F9B;MIAO LETTER REFORMED TONE-2;Lm;0;L;;;;;N;;;;; +16F9C;MIAO LETTER REFORMED TONE-4;Lm;0;L;;;;;N;;;;; +16F9D;MIAO LETTER REFORMED TONE-5;Lm;0;L;;;;;N;;;;; +16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;; +16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;; +16FE0;TANGUT ITERATION MARK;Lm;0;L;;;;;N;;;;; +16FE1;NUSHU ITERATION MARK;Lm;0;L;;;;;N;;;;; +17000;<Tangut Ideograph, First>;Lo;0;L;;;;;N;;;;; +187EC;<Tangut Ideograph, Last>;Lo;0;L;;;;;N;;;;; +18800;TANGUT COMPONENT-001;Lo;0;L;;;;;N;;;;; +18801;TANGUT COMPONENT-002;Lo;0;L;;;;;N;;;;; +18802;TANGUT COMPONENT-003;Lo;0;L;;;;;N;;;;; +18803;TANGUT COMPONENT-004;Lo;0;L;;;;;N;;;;; +18804;TANGUT COMPONENT-005;Lo;0;L;;;;;N;;;;; +18805;TANGUT COMPONENT-006;Lo;0;L;;;;;N;;;;; +18806;TANGUT COMPONENT-007;Lo;0;L;;;;;N;;;;; +18807;TANGUT COMPONENT-008;Lo;0;L;;;;;N;;;;; +18808;TANGUT COMPONENT-009;Lo;0;L;;;;;N;;;;; +18809;TANGUT COMPONENT-010;Lo;0;L;;;;;N;;;;; +1880A;TANGUT COMPONENT-011;Lo;0;L;;;;;N;;;;; +1880B;TANGUT COMPONENT-012;Lo;0;L;;;;;N;;;;; +1880C;TANGUT COMPONENT-013;Lo;0;L;;;;;N;;;;; +1880D;TANGUT COMPONENT-014;Lo;0;L;;;;;N;;;;; +1880E;TANGUT COMPONENT-015;Lo;0;L;;;;;N;;;;; +1880F;TANGUT COMPONENT-016;Lo;0;L;;;;;N;;;;; +18810;TANGUT COMPONENT-017;Lo;0;L;;;;;N;;;;; +18811;TANGUT COMPONENT-018;Lo;0;L;;;;;N;;;;; +18812;TANGUT COMPONENT-019;Lo;0;L;;;;;N;;;;; +18813;TANGUT COMPONENT-020;Lo;0;L;;;;;N;;;;; +18814;TANGUT COMPONENT-021;Lo;0;L;;;;;N;;;;; +18815;TANGUT COMPONENT-022;Lo;0;L;;;;;N;;;;; +18816;TANGUT COMPONENT-023;Lo;0;L;;;;;N;;;;; +18817;TANGUT COMPONENT-024;Lo;0;L;;;;;N;;;;; +18818;TANGUT COMPONENT-025;Lo;0;L;;;;;N;;;;; +18819;TANGUT COMPONENT-026;Lo;0;L;;;;;N;;;;; +1881A;TANGUT COMPONENT-027;Lo;0;L;;;;;N;;;;; +1881B;TANGUT COMPONENT-028;Lo;0;L;;;;;N;;;;; +1881C;TANGUT COMPONENT-029;Lo;0;L;;;;;N;;;;; +1881D;TANGUT COMPONENT-030;Lo;0;L;;;;;N;;;;; +1881E;TANGUT COMPONENT-031;Lo;0;L;;;;;N;;;;; +1881F;TANGUT COMPONENT-032;Lo;0;L;;;;;N;;;;; +18820;TANGUT COMPONENT-033;Lo;0;L;;;;;N;;;;; +18821;TANGUT COMPONENT-034;Lo;0;L;;;;;N;;;;; +18822;TANGUT COMPONENT-035;Lo;0;L;;;;;N;;;;; +18823;TANGUT COMPONENT-036;Lo;0;L;;;;;N;;;;; +18824;TANGUT COMPONENT-037;Lo;0;L;;;;;N;;;;; +18825;TANGUT COMPONENT-038;Lo;0;L;;;;;N;;;;; +18826;TANGUT COMPONENT-039;Lo;0;L;;;;;N;;;;; +18827;TANGUT COMPONENT-040;Lo;0;L;;;;;N;;;;; +18828;TANGUT COMPONENT-041;Lo;0;L;;;;;N;;;;; +18829;TANGUT COMPONENT-042;Lo;0;L;;;;;N;;;;; +1882A;TANGUT COMPONENT-043;Lo;0;L;;;;;N;;;;; +1882B;TANGUT COMPONENT-044;Lo;0;L;;;;;N;;;;; +1882C;TANGUT COMPONENT-045;Lo;0;L;;;;;N;;;;; +1882D;TANGUT COMPONENT-046;Lo;0;L;;;;;N;;;;; +1882E;TANGUT COMPONENT-047;Lo;0;L;;;;;N;;;;; +1882F;TANGUT COMPONENT-048;Lo;0;L;;;;;N;;;;; +18830;TANGUT COMPONENT-049;Lo;0;L;;;;;N;;;;; +18831;TANGUT COMPONENT-050;Lo;0;L;;;;;N;;;;; +18832;TANGUT COMPONENT-051;Lo;0;L;;;;;N;;;;; +18833;TANGUT COMPONENT-052;Lo;0;L;;;;;N;;;;; +18834;TANGUT COMPONENT-053;Lo;0;L;;;;;N;;;;; +18835;TANGUT COMPONENT-054;Lo;0;L;;;;;N;;;;; +18836;TANGUT COMPONENT-055;Lo;0;L;;;;;N;;;;; +18837;TANGUT COMPONENT-056;Lo;0;L;;;;;N;;;;; +18838;TANGUT COMPONENT-057;Lo;0;L;;;;;N;;;;; +18839;TANGUT COMPONENT-058;Lo;0;L;;;;;N;;;;; +1883A;TANGUT COMPONENT-059;Lo;0;L;;;;;N;;;;; +1883B;TANGUT COMPONENT-060;Lo;0;L;;;;;N;;;;; +1883C;TANGUT COMPONENT-061;Lo;0;L;;;;;N;;;;; +1883D;TANGUT COMPONENT-062;Lo;0;L;;;;;N;;;;; +1883E;TANGUT COMPONENT-063;Lo;0;L;;;;;N;;;;; +1883F;TANGUT COMPONENT-064;Lo;0;L;;;;;N;;;;; +18840;TANGUT COMPONENT-065;Lo;0;L;;;;;N;;;;; +18841;TANGUT COMPONENT-066;Lo;0;L;;;;;N;;;;; +18842;TANGUT COMPONENT-067;Lo;0;L;;;;;N;;;;; +18843;TANGUT COMPONENT-068;Lo;0;L;;;;;N;;;;; +18844;TANGUT COMPONENT-069;Lo;0;L;;;;;N;;;;; +18845;TANGUT COMPONENT-070;Lo;0;L;;;;;N;;;;; +18846;TANGUT COMPONENT-071;Lo;0;L;;;;;N;;;;; +18847;TANGUT COMPONENT-072;Lo;0;L;;;;;N;;;;; +18848;TANGUT COMPONENT-073;Lo;0;L;;;;;N;;;;; +18849;TANGUT COMPONENT-074;Lo;0;L;;;;;N;;;;; +1884A;TANGUT COMPONENT-075;Lo;0;L;;;;;N;;;;; +1884B;TANGUT COMPONENT-076;Lo;0;L;;;;;N;;;;; +1884C;TANGUT COMPONENT-077;Lo;0;L;;;;;N;;;;; +1884D;TANGUT COMPONENT-078;Lo;0;L;;;;;N;;;;; +1884E;TANGUT COMPONENT-079;Lo;0;L;;;;;N;;;;; +1884F;TANGUT COMPONENT-080;Lo;0;L;;;;;N;;;;; +18850;TANGUT COMPONENT-081;Lo;0;L;;;;;N;;;;; +18851;TANGUT COMPONENT-082;Lo;0;L;;;;;N;;;;; +18852;TANGUT COMPONENT-083;Lo;0;L;;;;;N;;;;; +18853;TANGUT COMPONENT-084;Lo;0;L;;;;;N;;;;; +18854;TANGUT COMPONENT-085;Lo;0;L;;;;;N;;;;; +18855;TANGUT COMPONENT-086;Lo;0;L;;;;;N;;;;; +18856;TANGUT COMPONENT-087;Lo;0;L;;;;;N;;;;; +18857;TANGUT COMPONENT-088;Lo;0;L;;;;;N;;;;; +18858;TANGUT COMPONENT-089;Lo;0;L;;;;;N;;;;; +18859;TANGUT COMPONENT-090;Lo;0;L;;;;;N;;;;; +1885A;TANGUT COMPONENT-091;Lo;0;L;;;;;N;;;;; +1885B;TANGUT COMPONENT-092;Lo;0;L;;;;;N;;;;; +1885C;TANGUT COMPONENT-093;Lo;0;L;;;;;N;;;;; +1885D;TANGUT COMPONENT-094;Lo;0;L;;;;;N;;;;; +1885E;TANGUT COMPONENT-095;Lo;0;L;;;;;N;;;;; +1885F;TANGUT COMPONENT-096;Lo;0;L;;;;;N;;;;; +18860;TANGUT COMPONENT-097;Lo;0;L;;;;;N;;;;; +18861;TANGUT COMPONENT-098;Lo;0;L;;;;;N;;;;; +18862;TANGUT COMPONENT-099;Lo;0;L;;;;;N;;;;; +18863;TANGUT COMPONENT-100;Lo;0;L;;;;;N;;;;; +18864;TANGUT COMPONENT-101;Lo;0;L;;;;;N;;;;; +18865;TANGUT COMPONENT-102;Lo;0;L;;;;;N;;;;; +18866;TANGUT COMPONENT-103;Lo;0;L;;;;;N;;;;; +18867;TANGUT COMPONENT-104;Lo;0;L;;;;;N;;;;; +18868;TANGUT COMPONENT-105;Lo;0;L;;;;;N;;;;; +18869;TANGUT COMPONENT-106;Lo;0;L;;;;;N;;;;; +1886A;TANGUT COMPONENT-107;Lo;0;L;;;;;N;;;;; +1886B;TANGUT COMPONENT-108;Lo;0;L;;;;;N;;;;; +1886C;TANGUT COMPONENT-109;Lo;0;L;;;;;N;;;;; +1886D;TANGUT COMPONENT-110;Lo;0;L;;;;;N;;;;; +1886E;TANGUT COMPONENT-111;Lo;0;L;;;;;N;;;;; +1886F;TANGUT COMPONENT-112;Lo;0;L;;;;;N;;;;; +18870;TANGUT COMPONENT-113;Lo;0;L;;;;;N;;;;; +18871;TANGUT COMPONENT-114;Lo;0;L;;;;;N;;;;; +18872;TANGUT COMPONENT-115;Lo;0;L;;;;;N;;;;; +18873;TANGUT COMPONENT-116;Lo;0;L;;;;;N;;;;; +18874;TANGUT COMPONENT-117;Lo;0;L;;;;;N;;;;; +18875;TANGUT COMPONENT-118;Lo;0;L;;;;;N;;;;; +18876;TANGUT COMPONENT-119;Lo;0;L;;;;;N;;;;; +18877;TANGUT COMPONENT-120;Lo;0;L;;;;;N;;;;; +18878;TANGUT COMPONENT-121;Lo;0;L;;;;;N;;;;; +18879;TANGUT COMPONENT-122;Lo;0;L;;;;;N;;;;; +1887A;TANGUT COMPONENT-123;Lo;0;L;;;;;N;;;;; +1887B;TANGUT COMPONENT-124;Lo;0;L;;;;;N;;;;; +1887C;TANGUT COMPONENT-125;Lo;0;L;;;;;N;;;;; +1887D;TANGUT COMPONENT-126;Lo;0;L;;;;;N;;;;; +1887E;TANGUT COMPONENT-127;Lo;0;L;;;;;N;;;;; +1887F;TANGUT COMPONENT-128;Lo;0;L;;;;;N;;;;; +18880;TANGUT COMPONENT-129;Lo;0;L;;;;;N;;;;; +18881;TANGUT COMPONENT-130;Lo;0;L;;;;;N;;;;; +18882;TANGUT COMPONENT-131;Lo;0;L;;;;;N;;;;; +18883;TANGUT COMPONENT-132;Lo;0;L;;;;;N;;;;; +18884;TANGUT COMPONENT-133;Lo;0;L;;;;;N;;;;; +18885;TANGUT COMPONENT-134;Lo;0;L;;;;;N;;;;; +18886;TANGUT COMPONENT-135;Lo;0;L;;;;;N;;;;; +18887;TANGUT COMPONENT-136;Lo;0;L;;;;;N;;;;; +18888;TANGUT COMPONENT-137;Lo;0;L;;;;;N;;;;; +18889;TANGUT COMPONENT-138;Lo;0;L;;;;;N;;;;; +1888A;TANGUT COMPONENT-139;Lo;0;L;;;;;N;;;;; +1888B;TANGUT COMPONENT-140;Lo;0;L;;;;;N;;;;; +1888C;TANGUT COMPONENT-141;Lo;0;L;;;;;N;;;;; +1888D;TANGUT COMPONENT-142;Lo;0;L;;;;;N;;;;; +1888E;TANGUT COMPONENT-143;Lo;0;L;;;;;N;;;;; +1888F;TANGUT COMPONENT-144;Lo;0;L;;;;;N;;;;; +18890;TANGUT COMPONENT-145;Lo;0;L;;;;;N;;;;; +18891;TANGUT COMPONENT-146;Lo;0;L;;;;;N;;;;; +18892;TANGUT COMPONENT-147;Lo;0;L;;;;;N;;;;; +18893;TANGUT COMPONENT-148;Lo;0;L;;;;;N;;;;; +18894;TANGUT COMPONENT-149;Lo;0;L;;;;;N;;;;; +18895;TANGUT COMPONENT-150;Lo;0;L;;;;;N;;;;; +18896;TANGUT COMPONENT-151;Lo;0;L;;;;;N;;;;; +18897;TANGUT COMPONENT-152;Lo;0;L;;;;;N;;;;; +18898;TANGUT COMPONENT-153;Lo;0;L;;;;;N;;;;; +18899;TANGUT COMPONENT-154;Lo;0;L;;;;;N;;;;; +1889A;TANGUT COMPONENT-155;Lo;0;L;;;;;N;;;;; +1889B;TANGUT COMPONENT-156;Lo;0;L;;;;;N;;;;; +1889C;TANGUT COMPONENT-157;Lo;0;L;;;;;N;;;;; +1889D;TANGUT COMPONENT-158;Lo;0;L;;;;;N;;;;; +1889E;TANGUT COMPONENT-159;Lo;0;L;;;;;N;;;;; +1889F;TANGUT COMPONENT-160;Lo;0;L;;;;;N;;;;; +188A0;TANGUT COMPONENT-161;Lo;0;L;;;;;N;;;;; +188A1;TANGUT COMPONENT-162;Lo;0;L;;;;;N;;;;; +188A2;TANGUT COMPONENT-163;Lo;0;L;;;;;N;;;;; +188A3;TANGUT COMPONENT-164;Lo;0;L;;;;;N;;;;; +188A4;TANGUT COMPONENT-165;Lo;0;L;;;;;N;;;;; +188A5;TANGUT COMPONENT-166;Lo;0;L;;;;;N;;;;; +188A6;TANGUT COMPONENT-167;Lo;0;L;;;;;N;;;;; +188A7;TANGUT COMPONENT-168;Lo;0;L;;;;;N;;;;; +188A8;TANGUT COMPONENT-169;Lo;0;L;;;;;N;;;;; +188A9;TANGUT COMPONENT-170;Lo;0;L;;;;;N;;;;; +188AA;TANGUT COMPONENT-171;Lo;0;L;;;;;N;;;;; +188AB;TANGUT COMPONENT-172;Lo;0;L;;;;;N;;;;; +188AC;TANGUT COMPONENT-173;Lo;0;L;;;;;N;;;;; +188AD;TANGUT COMPONENT-174;Lo;0;L;;;;;N;;;;; +188AE;TANGUT COMPONENT-175;Lo;0;L;;;;;N;;;;; +188AF;TANGUT COMPONENT-176;Lo;0;L;;;;;N;;;;; +188B0;TANGUT COMPONENT-177;Lo;0;L;;;;;N;;;;; +188B1;TANGUT COMPONENT-178;Lo;0;L;;;;;N;;;;; +188B2;TANGUT COMPONENT-179;Lo;0;L;;;;;N;;;;; +188B3;TANGUT COMPONENT-180;Lo;0;L;;;;;N;;;;; +188B4;TANGUT COMPONENT-181;Lo;0;L;;;;;N;;;;; +188B5;TANGUT COMPONENT-182;Lo;0;L;;;;;N;;;;; +188B6;TANGUT COMPONENT-183;Lo;0;L;;;;;N;;;;; +188B7;TANGUT COMPONENT-184;Lo;0;L;;;;;N;;;;; +188B8;TANGUT COMPONENT-185;Lo;0;L;;;;;N;;;;; +188B9;TANGUT COMPONENT-186;Lo;0;L;;;;;N;;;;; +188BA;TANGUT COMPONENT-187;Lo;0;L;;;;;N;;;;; +188BB;TANGUT COMPONENT-188;Lo;0;L;;;;;N;;;;; +188BC;TANGUT COMPONENT-189;Lo;0;L;;;;;N;;;;; +188BD;TANGUT COMPONENT-190;Lo;0;L;;;;;N;;;;; +188BE;TANGUT COMPONENT-191;Lo;0;L;;;;;N;;;;; +188BF;TANGUT COMPONENT-192;Lo;0;L;;;;;N;;;;; +188C0;TANGUT COMPONENT-193;Lo;0;L;;;;;N;;;;; +188C1;TANGUT COMPONENT-194;Lo;0;L;;;;;N;;;;; +188C2;TANGUT COMPONENT-195;Lo;0;L;;;;;N;;;;; +188C3;TANGUT COMPONENT-196;Lo;0;L;;;;;N;;;;; +188C4;TANGUT COMPONENT-197;Lo;0;L;;;;;N;;;;; +188C5;TANGUT COMPONENT-198;Lo;0;L;;;;;N;;;;; +188C6;TANGUT COMPONENT-199;Lo;0;L;;;;;N;;;;; +188C7;TANGUT COMPONENT-200;Lo;0;L;;;;;N;;;;; +188C8;TANGUT COMPONENT-201;Lo;0;L;;;;;N;;;;; +188C9;TANGUT COMPONENT-202;Lo;0;L;;;;;N;;;;; +188CA;TANGUT COMPONENT-203;Lo;0;L;;;;;N;;;;; +188CB;TANGUT COMPONENT-204;Lo;0;L;;;;;N;;;;; +188CC;TANGUT COMPONENT-205;Lo;0;L;;;;;N;;;;; +188CD;TANGUT COMPONENT-206;Lo;0;L;;;;;N;;;;; +188CE;TANGUT COMPONENT-207;Lo;0;L;;;;;N;;;;; +188CF;TANGUT COMPONENT-208;Lo;0;L;;;;;N;;;;; +188D0;TANGUT COMPONENT-209;Lo;0;L;;;;;N;;;;; +188D1;TANGUT COMPONENT-210;Lo;0;L;;;;;N;;;;; +188D2;TANGUT COMPONENT-211;Lo;0;L;;;;;N;;;;; +188D3;TANGUT COMPONENT-212;Lo;0;L;;;;;N;;;;; +188D4;TANGUT COMPONENT-213;Lo;0;L;;;;;N;;;;; +188D5;TANGUT COMPONENT-214;Lo;0;L;;;;;N;;;;; +188D6;TANGUT COMPONENT-215;Lo;0;L;;;;;N;;;;; +188D7;TANGUT COMPONENT-216;Lo;0;L;;;;;N;;;;; +188D8;TANGUT COMPONENT-217;Lo;0;L;;;;;N;;;;; +188D9;TANGUT COMPONENT-218;Lo;0;L;;;;;N;;;;; +188DA;TANGUT COMPONENT-219;Lo;0;L;;;;;N;;;;; +188DB;TANGUT COMPONENT-220;Lo;0;L;;;;;N;;;;; +188DC;TANGUT COMPONENT-221;Lo;0;L;;;;;N;;;;; +188DD;TANGUT COMPONENT-222;Lo;0;L;;;;;N;;;;; +188DE;TANGUT COMPONENT-223;Lo;0;L;;;;;N;;;;; +188DF;TANGUT COMPONENT-224;Lo;0;L;;;;;N;;;;; +188E0;TANGUT COMPONENT-225;Lo;0;L;;;;;N;;;;; +188E1;TANGUT COMPONENT-226;Lo;0;L;;;;;N;;;;; +188E2;TANGUT COMPONENT-227;Lo;0;L;;;;;N;;;;; +188E3;TANGUT COMPONENT-228;Lo;0;L;;;;;N;;;;; +188E4;TANGUT COMPONENT-229;Lo;0;L;;;;;N;;;;; +188E5;TANGUT COMPONENT-230;Lo;0;L;;;;;N;;;;; +188E6;TANGUT COMPONENT-231;Lo;0;L;;;;;N;;;;; +188E7;TANGUT COMPONENT-232;Lo;0;L;;;;;N;;;;; +188E8;TANGUT COMPONENT-233;Lo;0;L;;;;;N;;;;; +188E9;TANGUT COMPONENT-234;Lo;0;L;;;;;N;;;;; +188EA;TANGUT COMPONENT-235;Lo;0;L;;;;;N;;;;; +188EB;TANGUT COMPONENT-236;Lo;0;L;;;;;N;;;;; +188EC;TANGUT COMPONENT-237;Lo;0;L;;;;;N;;;;; +188ED;TANGUT COMPONENT-238;Lo;0;L;;;;;N;;;;; +188EE;TANGUT COMPONENT-239;Lo;0;L;;;;;N;;;;; +188EF;TANGUT COMPONENT-240;Lo;0;L;;;;;N;;;;; +188F0;TANGUT COMPONENT-241;Lo;0;L;;;;;N;;;;; +188F1;TANGUT COMPONENT-242;Lo;0;L;;;;;N;;;;; +188F2;TANGUT COMPONENT-243;Lo;0;L;;;;;N;;;;; +188F3;TANGUT COMPONENT-244;Lo;0;L;;;;;N;;;;; +188F4;TANGUT COMPONENT-245;Lo;0;L;;;;;N;;;;; +188F5;TANGUT COMPONENT-246;Lo;0;L;;;;;N;;;;; +188F6;TANGUT COMPONENT-247;Lo;0;L;;;;;N;;;;; +188F7;TANGUT COMPONENT-248;Lo;0;L;;;;;N;;;;; +188F8;TANGUT COMPONENT-249;Lo;0;L;;;;;N;;;;; +188F9;TANGUT COMPONENT-250;Lo;0;L;;;;;N;;;;; +188FA;TANGUT COMPONENT-251;Lo;0;L;;;;;N;;;;; +188FB;TANGUT COMPONENT-252;Lo;0;L;;;;;N;;;;; +188FC;TANGUT COMPONENT-253;Lo;0;L;;;;;N;;;;; +188FD;TANGUT COMPONENT-254;Lo;0;L;;;;;N;;;;; +188FE;TANGUT COMPONENT-255;Lo;0;L;;;;;N;;;;; +188FF;TANGUT COMPONENT-256;Lo;0;L;;;;;N;;;;; +18900;TANGUT COMPONENT-257;Lo;0;L;;;;;N;;;;; +18901;TANGUT COMPONENT-258;Lo;0;L;;;;;N;;;;; +18902;TANGUT COMPONENT-259;Lo;0;L;;;;;N;;;;; +18903;TANGUT COMPONENT-260;Lo;0;L;;;;;N;;;;; +18904;TANGUT COMPONENT-261;Lo;0;L;;;;;N;;;;; +18905;TANGUT COMPONENT-262;Lo;0;L;;;;;N;;;;; +18906;TANGUT COMPONENT-263;Lo;0;L;;;;;N;;;;; +18907;TANGUT COMPONENT-264;Lo;0;L;;;;;N;;;;; +18908;TANGUT COMPONENT-265;Lo;0;L;;;;;N;;;;; +18909;TANGUT COMPONENT-266;Lo;0;L;;;;;N;;;;; +1890A;TANGUT COMPONENT-267;Lo;0;L;;;;;N;;;;; +1890B;TANGUT COMPONENT-268;Lo;0;L;;;;;N;;;;; +1890C;TANGUT COMPONENT-269;Lo;0;L;;;;;N;;;;; +1890D;TANGUT COMPONENT-270;Lo;0;L;;;;;N;;;;; +1890E;TANGUT COMPONENT-271;Lo;0;L;;;;;N;;;;; +1890F;TANGUT COMPONENT-272;Lo;0;L;;;;;N;;;;; +18910;TANGUT COMPONENT-273;Lo;0;L;;;;;N;;;;; +18911;TANGUT COMPONENT-274;Lo;0;L;;;;;N;;;;; +18912;TANGUT COMPONENT-275;Lo;0;L;;;;;N;;;;; +18913;TANGUT COMPONENT-276;Lo;0;L;;;;;N;;;;; +18914;TANGUT COMPONENT-277;Lo;0;L;;;;;N;;;;; +18915;TANGUT COMPONENT-278;Lo;0;L;;;;;N;;;;; +18916;TANGUT COMPONENT-279;Lo;0;L;;;;;N;;;;; +18917;TANGUT COMPONENT-280;Lo;0;L;;;;;N;;;;; +18918;TANGUT COMPONENT-281;Lo;0;L;;;;;N;;;;; +18919;TANGUT COMPONENT-282;Lo;0;L;;;;;N;;;;; +1891A;TANGUT COMPONENT-283;Lo;0;L;;;;;N;;;;; +1891B;TANGUT COMPONENT-284;Lo;0;L;;;;;N;;;;; +1891C;TANGUT COMPONENT-285;Lo;0;L;;;;;N;;;;; +1891D;TANGUT COMPONENT-286;Lo;0;L;;;;;N;;;;; +1891E;TANGUT COMPONENT-287;Lo;0;L;;;;;N;;;;; +1891F;TANGUT COMPONENT-288;Lo;0;L;;;;;N;;;;; +18920;TANGUT COMPONENT-289;Lo;0;L;;;;;N;;;;; +18921;TANGUT COMPONENT-290;Lo;0;L;;;;;N;;;;; +18922;TANGUT COMPONENT-291;Lo;0;L;;;;;N;;;;; +18923;TANGUT COMPONENT-292;Lo;0;L;;;;;N;;;;; +18924;TANGUT COMPONENT-293;Lo;0;L;;;;;N;;;;; +18925;TANGUT COMPONENT-294;Lo;0;L;;;;;N;;;;; +18926;TANGUT COMPONENT-295;Lo;0;L;;;;;N;;;;; +18927;TANGUT COMPONENT-296;Lo;0;L;;;;;N;;;;; +18928;TANGUT COMPONENT-297;Lo;0;L;;;;;N;;;;; +18929;TANGUT COMPONENT-298;Lo;0;L;;;;;N;;;;; +1892A;TANGUT COMPONENT-299;Lo;0;L;;;;;N;;;;; +1892B;TANGUT COMPONENT-300;Lo;0;L;;;;;N;;;;; +1892C;TANGUT COMPONENT-301;Lo;0;L;;;;;N;;;;; +1892D;TANGUT COMPONENT-302;Lo;0;L;;;;;N;;;;; +1892E;TANGUT COMPONENT-303;Lo;0;L;;;;;N;;;;; +1892F;TANGUT COMPONENT-304;Lo;0;L;;;;;N;;;;; +18930;TANGUT COMPONENT-305;Lo;0;L;;;;;N;;;;; +18931;TANGUT COMPONENT-306;Lo;0;L;;;;;N;;;;; +18932;TANGUT COMPONENT-307;Lo;0;L;;;;;N;;;;; +18933;TANGUT COMPONENT-308;Lo;0;L;;;;;N;;;;; +18934;TANGUT COMPONENT-309;Lo;0;L;;;;;N;;;;; +18935;TANGUT COMPONENT-310;Lo;0;L;;;;;N;;;;; +18936;TANGUT COMPONENT-311;Lo;0;L;;;;;N;;;;; +18937;TANGUT COMPONENT-312;Lo;0;L;;;;;N;;;;; +18938;TANGUT COMPONENT-313;Lo;0;L;;;;;N;;;;; +18939;TANGUT COMPONENT-314;Lo;0;L;;;;;N;;;;; +1893A;TANGUT COMPONENT-315;Lo;0;L;;;;;N;;;;; +1893B;TANGUT COMPONENT-316;Lo;0;L;;;;;N;;;;; +1893C;TANGUT COMPONENT-317;Lo;0;L;;;;;N;;;;; +1893D;TANGUT COMPONENT-318;Lo;0;L;;;;;N;;;;; +1893E;TANGUT COMPONENT-319;Lo;0;L;;;;;N;;;;; +1893F;TANGUT COMPONENT-320;Lo;0;L;;;;;N;;;;; +18940;TANGUT COMPONENT-321;Lo;0;L;;;;;N;;;;; +18941;TANGUT COMPONENT-322;Lo;0;L;;;;;N;;;;; +18942;TANGUT COMPONENT-323;Lo;0;L;;;;;N;;;;; +18943;TANGUT COMPONENT-324;Lo;0;L;;;;;N;;;;; +18944;TANGUT COMPONENT-325;Lo;0;L;;;;;N;;;;; +18945;TANGUT COMPONENT-326;Lo;0;L;;;;;N;;;;; +18946;TANGUT COMPONENT-327;Lo;0;L;;;;;N;;;;; +18947;TANGUT COMPONENT-328;Lo;0;L;;;;;N;;;;; +18948;TANGUT COMPONENT-329;Lo;0;L;;;;;N;;;;; +18949;TANGUT COMPONENT-330;Lo;0;L;;;;;N;;;;; +1894A;TANGUT COMPONENT-331;Lo;0;L;;;;;N;;;;; +1894B;TANGUT COMPONENT-332;Lo;0;L;;;;;N;;;;; +1894C;TANGUT COMPONENT-333;Lo;0;L;;;;;N;;;;; +1894D;TANGUT COMPONENT-334;Lo;0;L;;;;;N;;;;; +1894E;TANGUT COMPONENT-335;Lo;0;L;;;;;N;;;;; +1894F;TANGUT COMPONENT-336;Lo;0;L;;;;;N;;;;; +18950;TANGUT COMPONENT-337;Lo;0;L;;;;;N;;;;; +18951;TANGUT COMPONENT-338;Lo;0;L;;;;;N;;;;; +18952;TANGUT COMPONENT-339;Lo;0;L;;;;;N;;;;; +18953;TANGUT COMPONENT-340;Lo;0;L;;;;;N;;;;; +18954;TANGUT COMPONENT-341;Lo;0;L;;;;;N;;;;; +18955;TANGUT COMPONENT-342;Lo;0;L;;;;;N;;;;; +18956;TANGUT COMPONENT-343;Lo;0;L;;;;;N;;;;; +18957;TANGUT COMPONENT-344;Lo;0;L;;;;;N;;;;; +18958;TANGUT COMPONENT-345;Lo;0;L;;;;;N;;;;; +18959;TANGUT COMPONENT-346;Lo;0;L;;;;;N;;;;; +1895A;TANGUT COMPONENT-347;Lo;0;L;;;;;N;;;;; +1895B;TANGUT COMPONENT-348;Lo;0;L;;;;;N;;;;; +1895C;TANGUT COMPONENT-349;Lo;0;L;;;;;N;;;;; +1895D;TANGUT COMPONENT-350;Lo;0;L;;;;;N;;;;; +1895E;TANGUT COMPONENT-351;Lo;0;L;;;;;N;;;;; +1895F;TANGUT COMPONENT-352;Lo;0;L;;;;;N;;;;; +18960;TANGUT COMPONENT-353;Lo;0;L;;;;;N;;;;; +18961;TANGUT COMPONENT-354;Lo;0;L;;;;;N;;;;; +18962;TANGUT COMPONENT-355;Lo;0;L;;;;;N;;;;; +18963;TANGUT COMPONENT-356;Lo;0;L;;;;;N;;;;; +18964;TANGUT COMPONENT-357;Lo;0;L;;;;;N;;;;; +18965;TANGUT COMPONENT-358;Lo;0;L;;;;;N;;;;; +18966;TANGUT COMPONENT-359;Lo;0;L;;;;;N;;;;; +18967;TANGUT COMPONENT-360;Lo;0;L;;;;;N;;;;; +18968;TANGUT COMPONENT-361;Lo;0;L;;;;;N;;;;; +18969;TANGUT COMPONENT-362;Lo;0;L;;;;;N;;;;; +1896A;TANGUT COMPONENT-363;Lo;0;L;;;;;N;;;;; +1896B;TANGUT COMPONENT-364;Lo;0;L;;;;;N;;;;; +1896C;TANGUT COMPONENT-365;Lo;0;L;;;;;N;;;;; +1896D;TANGUT COMPONENT-366;Lo;0;L;;;;;N;;;;; +1896E;TANGUT COMPONENT-367;Lo;0;L;;;;;N;;;;; +1896F;TANGUT COMPONENT-368;Lo;0;L;;;;;N;;;;; +18970;TANGUT COMPONENT-369;Lo;0;L;;;;;N;;;;; +18971;TANGUT COMPONENT-370;Lo;0;L;;;;;N;;;;; +18972;TANGUT COMPONENT-371;Lo;0;L;;;;;N;;;;; +18973;TANGUT COMPONENT-372;Lo;0;L;;;;;N;;;;; +18974;TANGUT COMPONENT-373;Lo;0;L;;;;;N;;;;; +18975;TANGUT COMPONENT-374;Lo;0;L;;;;;N;;;;; +18976;TANGUT COMPONENT-375;Lo;0;L;;;;;N;;;;; +18977;TANGUT COMPONENT-376;Lo;0;L;;;;;N;;;;; +18978;TANGUT COMPONENT-377;Lo;0;L;;;;;N;;;;; +18979;TANGUT COMPONENT-378;Lo;0;L;;;;;N;;;;; +1897A;TANGUT COMPONENT-379;Lo;0;L;;;;;N;;;;; +1897B;TANGUT COMPONENT-380;Lo;0;L;;;;;N;;;;; +1897C;TANGUT COMPONENT-381;Lo;0;L;;;;;N;;;;; +1897D;TANGUT COMPONENT-382;Lo;0;L;;;;;N;;;;; +1897E;TANGUT COMPONENT-383;Lo;0;L;;;;;N;;;;; +1897F;TANGUT COMPONENT-384;Lo;0;L;;;;;N;;;;; +18980;TANGUT COMPONENT-385;Lo;0;L;;;;;N;;;;; +18981;TANGUT COMPONENT-386;Lo;0;L;;;;;N;;;;; +18982;TANGUT COMPONENT-387;Lo;0;L;;;;;N;;;;; +18983;TANGUT COMPONENT-388;Lo;0;L;;;;;N;;;;; +18984;TANGUT COMPONENT-389;Lo;0;L;;;;;N;;;;; +18985;TANGUT COMPONENT-390;Lo;0;L;;;;;N;;;;; +18986;TANGUT COMPONENT-391;Lo;0;L;;;;;N;;;;; +18987;TANGUT COMPONENT-392;Lo;0;L;;;;;N;;;;; +18988;TANGUT COMPONENT-393;Lo;0;L;;;;;N;;;;; +18989;TANGUT COMPONENT-394;Lo;0;L;;;;;N;;;;; +1898A;TANGUT COMPONENT-395;Lo;0;L;;;;;N;;;;; +1898B;TANGUT COMPONENT-396;Lo;0;L;;;;;N;;;;; +1898C;TANGUT COMPONENT-397;Lo;0;L;;;;;N;;;;; +1898D;TANGUT COMPONENT-398;Lo;0;L;;;;;N;;;;; +1898E;TANGUT COMPONENT-399;Lo;0;L;;;;;N;;;;; +1898F;TANGUT COMPONENT-400;Lo;0;L;;;;;N;;;;; +18990;TANGUT COMPONENT-401;Lo;0;L;;;;;N;;;;; +18991;TANGUT COMPONENT-402;Lo;0;L;;;;;N;;;;; +18992;TANGUT COMPONENT-403;Lo;0;L;;;;;N;;;;; +18993;TANGUT COMPONENT-404;Lo;0;L;;;;;N;;;;; +18994;TANGUT COMPONENT-405;Lo;0;L;;;;;N;;;;; +18995;TANGUT COMPONENT-406;Lo;0;L;;;;;N;;;;; +18996;TANGUT COMPONENT-407;Lo;0;L;;;;;N;;;;; +18997;TANGUT COMPONENT-408;Lo;0;L;;;;;N;;;;; +18998;TANGUT COMPONENT-409;Lo;0;L;;;;;N;;;;; +18999;TANGUT COMPONENT-410;Lo;0;L;;;;;N;;;;; +1899A;TANGUT COMPONENT-411;Lo;0;L;;;;;N;;;;; +1899B;TANGUT COMPONENT-412;Lo;0;L;;;;;N;;;;; +1899C;TANGUT COMPONENT-413;Lo;0;L;;;;;N;;;;; +1899D;TANGUT COMPONENT-414;Lo;0;L;;;;;N;;;;; +1899E;TANGUT COMPONENT-415;Lo;0;L;;;;;N;;;;; +1899F;TANGUT COMPONENT-416;Lo;0;L;;;;;N;;;;; +189A0;TANGUT COMPONENT-417;Lo;0;L;;;;;N;;;;; +189A1;TANGUT COMPONENT-418;Lo;0;L;;;;;N;;;;; +189A2;TANGUT COMPONENT-419;Lo;0;L;;;;;N;;;;; +189A3;TANGUT COMPONENT-420;Lo;0;L;;;;;N;;;;; +189A4;TANGUT COMPONENT-421;Lo;0;L;;;;;N;;;;; +189A5;TANGUT COMPONENT-422;Lo;0;L;;;;;N;;;;; +189A6;TANGUT COMPONENT-423;Lo;0;L;;;;;N;;;;; +189A7;TANGUT COMPONENT-424;Lo;0;L;;;;;N;;;;; +189A8;TANGUT COMPONENT-425;Lo;0;L;;;;;N;;;;; +189A9;TANGUT COMPONENT-426;Lo;0;L;;;;;N;;;;; +189AA;TANGUT COMPONENT-427;Lo;0;L;;;;;N;;;;; +189AB;TANGUT COMPONENT-428;Lo;0;L;;;;;N;;;;; +189AC;TANGUT COMPONENT-429;Lo;0;L;;;;;N;;;;; +189AD;TANGUT COMPONENT-430;Lo;0;L;;;;;N;;;;; +189AE;TANGUT COMPONENT-431;Lo;0;L;;;;;N;;;;; +189AF;TANGUT COMPONENT-432;Lo;0;L;;;;;N;;;;; +189B0;TANGUT COMPONENT-433;Lo;0;L;;;;;N;;;;; +189B1;TANGUT COMPONENT-434;Lo;0;L;;;;;N;;;;; +189B2;TANGUT COMPONENT-435;Lo;0;L;;;;;N;;;;; +189B3;TANGUT COMPONENT-436;Lo;0;L;;;;;N;;;;; +189B4;TANGUT COMPONENT-437;Lo;0;L;;;;;N;;;;; +189B5;TANGUT COMPONENT-438;Lo;0;L;;;;;N;;;;; +189B6;TANGUT COMPONENT-439;Lo;0;L;;;;;N;;;;; +189B7;TANGUT COMPONENT-440;Lo;0;L;;;;;N;;;;; +189B8;TANGUT COMPONENT-441;Lo;0;L;;;;;N;;;;; +189B9;TANGUT COMPONENT-442;Lo;0;L;;;;;N;;;;; +189BA;TANGUT COMPONENT-443;Lo;0;L;;;;;N;;;;; +189BB;TANGUT COMPONENT-444;Lo;0;L;;;;;N;;;;; +189BC;TANGUT COMPONENT-445;Lo;0;L;;;;;N;;;;; +189BD;TANGUT COMPONENT-446;Lo;0;L;;;;;N;;;;; +189BE;TANGUT COMPONENT-447;Lo;0;L;;;;;N;;;;; +189BF;TANGUT COMPONENT-448;Lo;0;L;;;;;N;;;;; +189C0;TANGUT COMPONENT-449;Lo;0;L;;;;;N;;;;; +189C1;TANGUT COMPONENT-450;Lo;0;L;;;;;N;;;;; +189C2;TANGUT COMPONENT-451;Lo;0;L;;;;;N;;;;; +189C3;TANGUT COMPONENT-452;Lo;0;L;;;;;N;;;;; +189C4;TANGUT COMPONENT-453;Lo;0;L;;;;;N;;;;; +189C5;TANGUT COMPONENT-454;Lo;0;L;;;;;N;;;;; +189C6;TANGUT COMPONENT-455;Lo;0;L;;;;;N;;;;; +189C7;TANGUT COMPONENT-456;Lo;0;L;;;;;N;;;;; +189C8;TANGUT COMPONENT-457;Lo;0;L;;;;;N;;;;; +189C9;TANGUT COMPONENT-458;Lo;0;L;;;;;N;;;;; +189CA;TANGUT COMPONENT-459;Lo;0;L;;;;;N;;;;; +189CB;TANGUT COMPONENT-460;Lo;0;L;;;;;N;;;;; +189CC;TANGUT COMPONENT-461;Lo;0;L;;;;;N;;;;; +189CD;TANGUT COMPONENT-462;Lo;0;L;;;;;N;;;;; +189CE;TANGUT COMPONENT-463;Lo;0;L;;;;;N;;;;; +189CF;TANGUT COMPONENT-464;Lo;0;L;;;;;N;;;;; +189D0;TANGUT COMPONENT-465;Lo;0;L;;;;;N;;;;; +189D1;TANGUT COMPONENT-466;Lo;0;L;;;;;N;;;;; +189D2;TANGUT COMPONENT-467;Lo;0;L;;;;;N;;;;; +189D3;TANGUT COMPONENT-468;Lo;0;L;;;;;N;;;;; +189D4;TANGUT COMPONENT-469;Lo;0;L;;;;;N;;;;; +189D5;TANGUT COMPONENT-470;Lo;0;L;;;;;N;;;;; +189D6;TANGUT COMPONENT-471;Lo;0;L;;;;;N;;;;; +189D7;TANGUT COMPONENT-472;Lo;0;L;;;;;N;;;;; +189D8;TANGUT COMPONENT-473;Lo;0;L;;;;;N;;;;; +189D9;TANGUT COMPONENT-474;Lo;0;L;;;;;N;;;;; +189DA;TANGUT COMPONENT-475;Lo;0;L;;;;;N;;;;; +189DB;TANGUT COMPONENT-476;Lo;0;L;;;;;N;;;;; +189DC;TANGUT COMPONENT-477;Lo;0;L;;;;;N;;;;; +189DD;TANGUT COMPONENT-478;Lo;0;L;;;;;N;;;;; +189DE;TANGUT COMPONENT-479;Lo;0;L;;;;;N;;;;; +189DF;TANGUT COMPONENT-480;Lo;0;L;;;;;N;;;;; +189E0;TANGUT COMPONENT-481;Lo;0;L;;;;;N;;;;; +189E1;TANGUT COMPONENT-482;Lo;0;L;;;;;N;;;;; +189E2;TANGUT COMPONENT-483;Lo;0;L;;;;;N;;;;; +189E3;TANGUT COMPONENT-484;Lo;0;L;;;;;N;;;;; +189E4;TANGUT COMPONENT-485;Lo;0;L;;;;;N;;;;; +189E5;TANGUT COMPONENT-486;Lo;0;L;;;;;N;;;;; +189E6;TANGUT COMPONENT-487;Lo;0;L;;;;;N;;;;; +189E7;TANGUT COMPONENT-488;Lo;0;L;;;;;N;;;;; +189E8;TANGUT COMPONENT-489;Lo;0;L;;;;;N;;;;; +189E9;TANGUT COMPONENT-490;Lo;0;L;;;;;N;;;;; +189EA;TANGUT COMPONENT-491;Lo;0;L;;;;;N;;;;; +189EB;TANGUT COMPONENT-492;Lo;0;L;;;;;N;;;;; +189EC;TANGUT COMPONENT-493;Lo;0;L;;;;;N;;;;; +189ED;TANGUT COMPONENT-494;Lo;0;L;;;;;N;;;;; +189EE;TANGUT COMPONENT-495;Lo;0;L;;;;;N;;;;; +189EF;TANGUT COMPONENT-496;Lo;0;L;;;;;N;;;;; +189F0;TANGUT COMPONENT-497;Lo;0;L;;;;;N;;;;; +189F1;TANGUT COMPONENT-498;Lo;0;L;;;;;N;;;;; +189F2;TANGUT COMPONENT-499;Lo;0;L;;;;;N;;;;; +189F3;TANGUT COMPONENT-500;Lo;0;L;;;;;N;;;;; +189F4;TANGUT COMPONENT-501;Lo;0;L;;;;;N;;;;; +189F5;TANGUT COMPONENT-502;Lo;0;L;;;;;N;;;;; +189F6;TANGUT COMPONENT-503;Lo;0;L;;;;;N;;;;; +189F7;TANGUT COMPONENT-504;Lo;0;L;;;;;N;;;;; +189F8;TANGUT COMPONENT-505;Lo;0;L;;;;;N;;;;; +189F9;TANGUT COMPONENT-506;Lo;0;L;;;;;N;;;;; +189FA;TANGUT COMPONENT-507;Lo;0;L;;;;;N;;;;; +189FB;TANGUT COMPONENT-508;Lo;0;L;;;;;N;;;;; +189FC;TANGUT COMPONENT-509;Lo;0;L;;;;;N;;;;; +189FD;TANGUT COMPONENT-510;Lo;0;L;;;;;N;;;;; +189FE;TANGUT COMPONENT-511;Lo;0;L;;;;;N;;;;; +189FF;TANGUT COMPONENT-512;Lo;0;L;;;;;N;;;;; +18A00;TANGUT COMPONENT-513;Lo;0;L;;;;;N;;;;; +18A01;TANGUT COMPONENT-514;Lo;0;L;;;;;N;;;;; +18A02;TANGUT COMPONENT-515;Lo;0;L;;;;;N;;;;; +18A03;TANGUT COMPONENT-516;Lo;0;L;;;;;N;;;;; +18A04;TANGUT COMPONENT-517;Lo;0;L;;;;;N;;;;; +18A05;TANGUT COMPONENT-518;Lo;0;L;;;;;N;;;;; +18A06;TANGUT COMPONENT-519;Lo;0;L;;;;;N;;;;; +18A07;TANGUT COMPONENT-520;Lo;0;L;;;;;N;;;;; +18A08;TANGUT COMPONENT-521;Lo;0;L;;;;;N;;;;; +18A09;TANGUT COMPONENT-522;Lo;0;L;;;;;N;;;;; +18A0A;TANGUT COMPONENT-523;Lo;0;L;;;;;N;;;;; +18A0B;TANGUT COMPONENT-524;Lo;0;L;;;;;N;;;;; +18A0C;TANGUT COMPONENT-525;Lo;0;L;;;;;N;;;;; +18A0D;TANGUT COMPONENT-526;Lo;0;L;;;;;N;;;;; +18A0E;TANGUT COMPONENT-527;Lo;0;L;;;;;N;;;;; +18A0F;TANGUT COMPONENT-528;Lo;0;L;;;;;N;;;;; +18A10;TANGUT COMPONENT-529;Lo;0;L;;;;;N;;;;; +18A11;TANGUT COMPONENT-530;Lo;0;L;;;;;N;;;;; +18A12;TANGUT COMPONENT-531;Lo;0;L;;;;;N;;;;; +18A13;TANGUT COMPONENT-532;Lo;0;L;;;;;N;;;;; +18A14;TANGUT COMPONENT-533;Lo;0;L;;;;;N;;;;; +18A15;TANGUT COMPONENT-534;Lo;0;L;;;;;N;;;;; +18A16;TANGUT COMPONENT-535;Lo;0;L;;;;;N;;;;; +18A17;TANGUT COMPONENT-536;Lo;0;L;;;;;N;;;;; +18A18;TANGUT COMPONENT-537;Lo;0;L;;;;;N;;;;; +18A19;TANGUT COMPONENT-538;Lo;0;L;;;;;N;;;;; +18A1A;TANGUT COMPONENT-539;Lo;0;L;;;;;N;;;;; +18A1B;TANGUT COMPONENT-540;Lo;0;L;;;;;N;;;;; +18A1C;TANGUT COMPONENT-541;Lo;0;L;;;;;N;;;;; +18A1D;TANGUT COMPONENT-542;Lo;0;L;;;;;N;;;;; +18A1E;TANGUT COMPONENT-543;Lo;0;L;;;;;N;;;;; +18A1F;TANGUT COMPONENT-544;Lo;0;L;;;;;N;;;;; +18A20;TANGUT COMPONENT-545;Lo;0;L;;;;;N;;;;; +18A21;TANGUT COMPONENT-546;Lo;0;L;;;;;N;;;;; +18A22;TANGUT COMPONENT-547;Lo;0;L;;;;;N;;;;; +18A23;TANGUT COMPONENT-548;Lo;0;L;;;;;N;;;;; +18A24;TANGUT COMPONENT-549;Lo;0;L;;;;;N;;;;; +18A25;TANGUT COMPONENT-550;Lo;0;L;;;;;N;;;;; +18A26;TANGUT COMPONENT-551;Lo;0;L;;;;;N;;;;; +18A27;TANGUT COMPONENT-552;Lo;0;L;;;;;N;;;;; +18A28;TANGUT COMPONENT-553;Lo;0;L;;;;;N;;;;; +18A29;TANGUT COMPONENT-554;Lo;0;L;;;;;N;;;;; +18A2A;TANGUT COMPONENT-555;Lo;0;L;;;;;N;;;;; +18A2B;TANGUT COMPONENT-556;Lo;0;L;;;;;N;;;;; +18A2C;TANGUT COMPONENT-557;Lo;0;L;;;;;N;;;;; +18A2D;TANGUT COMPONENT-558;Lo;0;L;;;;;N;;;;; +18A2E;TANGUT COMPONENT-559;Lo;0;L;;;;;N;;;;; +18A2F;TANGUT COMPONENT-560;Lo;0;L;;;;;N;;;;; +18A30;TANGUT COMPONENT-561;Lo;0;L;;;;;N;;;;; +18A31;TANGUT COMPONENT-562;Lo;0;L;;;;;N;;;;; +18A32;TANGUT COMPONENT-563;Lo;0;L;;;;;N;;;;; +18A33;TANGUT COMPONENT-564;Lo;0;L;;;;;N;;;;; +18A34;TANGUT COMPONENT-565;Lo;0;L;;;;;N;;;;; +18A35;TANGUT COMPONENT-566;Lo;0;L;;;;;N;;;;; +18A36;TANGUT COMPONENT-567;Lo;0;L;;;;;N;;;;; +18A37;TANGUT COMPONENT-568;Lo;0;L;;;;;N;;;;; +18A38;TANGUT COMPONENT-569;Lo;0;L;;;;;N;;;;; +18A39;TANGUT COMPONENT-570;Lo;0;L;;;;;N;;;;; +18A3A;TANGUT COMPONENT-571;Lo;0;L;;;;;N;;;;; +18A3B;TANGUT COMPONENT-572;Lo;0;L;;;;;N;;;;; +18A3C;TANGUT COMPONENT-573;Lo;0;L;;;;;N;;;;; +18A3D;TANGUT COMPONENT-574;Lo;0;L;;;;;N;;;;; +18A3E;TANGUT COMPONENT-575;Lo;0;L;;;;;N;;;;; +18A3F;TANGUT COMPONENT-576;Lo;0;L;;;;;N;;;;; +18A40;TANGUT COMPONENT-577;Lo;0;L;;;;;N;;;;; +18A41;TANGUT COMPONENT-578;Lo;0;L;;;;;N;;;;; +18A42;TANGUT COMPONENT-579;Lo;0;L;;;;;N;;;;; +18A43;TANGUT COMPONENT-580;Lo;0;L;;;;;N;;;;; +18A44;TANGUT COMPONENT-581;Lo;0;L;;;;;N;;;;; +18A45;TANGUT COMPONENT-582;Lo;0;L;;;;;N;;;;; +18A46;TANGUT COMPONENT-583;Lo;0;L;;;;;N;;;;; +18A47;TANGUT COMPONENT-584;Lo;0;L;;;;;N;;;;; +18A48;TANGUT COMPONENT-585;Lo;0;L;;;;;N;;;;; +18A49;TANGUT COMPONENT-586;Lo;0;L;;;;;N;;;;; +18A4A;TANGUT COMPONENT-587;Lo;0;L;;;;;N;;;;; +18A4B;TANGUT COMPONENT-588;Lo;0;L;;;;;N;;;;; +18A4C;TANGUT COMPONENT-589;Lo;0;L;;;;;N;;;;; +18A4D;TANGUT COMPONENT-590;Lo;0;L;;;;;N;;;;; +18A4E;TANGUT COMPONENT-591;Lo;0;L;;;;;N;;;;; +18A4F;TANGUT COMPONENT-592;Lo;0;L;;;;;N;;;;; +18A50;TANGUT COMPONENT-593;Lo;0;L;;;;;N;;;;; +18A51;TANGUT COMPONENT-594;Lo;0;L;;;;;N;;;;; +18A52;TANGUT COMPONENT-595;Lo;0;L;;;;;N;;;;; +18A53;TANGUT COMPONENT-596;Lo;0;L;;;;;N;;;;; +18A54;TANGUT COMPONENT-597;Lo;0;L;;;;;N;;;;; +18A55;TANGUT COMPONENT-598;Lo;0;L;;;;;N;;;;; +18A56;TANGUT COMPONENT-599;Lo;0;L;;;;;N;;;;; +18A57;TANGUT COMPONENT-600;Lo;0;L;;;;;N;;;;; +18A58;TANGUT COMPONENT-601;Lo;0;L;;;;;N;;;;; +18A59;TANGUT COMPONENT-602;Lo;0;L;;;;;N;;;;; +18A5A;TANGUT COMPONENT-603;Lo;0;L;;;;;N;;;;; +18A5B;TANGUT COMPONENT-604;Lo;0;L;;;;;N;;;;; +18A5C;TANGUT COMPONENT-605;Lo;0;L;;;;;N;;;;; +18A5D;TANGUT COMPONENT-606;Lo;0;L;;;;;N;;;;; +18A5E;TANGUT COMPONENT-607;Lo;0;L;;;;;N;;;;; +18A5F;TANGUT COMPONENT-608;Lo;0;L;;;;;N;;;;; +18A60;TANGUT COMPONENT-609;Lo;0;L;;;;;N;;;;; +18A61;TANGUT COMPONENT-610;Lo;0;L;;;;;N;;;;; +18A62;TANGUT COMPONENT-611;Lo;0;L;;;;;N;;;;; +18A63;TANGUT COMPONENT-612;Lo;0;L;;;;;N;;;;; +18A64;TANGUT COMPONENT-613;Lo;0;L;;;;;N;;;;; +18A65;TANGUT COMPONENT-614;Lo;0;L;;;;;N;;;;; +18A66;TANGUT COMPONENT-615;Lo;0;L;;;;;N;;;;; +18A67;TANGUT COMPONENT-616;Lo;0;L;;;;;N;;;;; +18A68;TANGUT COMPONENT-617;Lo;0;L;;;;;N;;;;; +18A69;TANGUT COMPONENT-618;Lo;0;L;;;;;N;;;;; +18A6A;TANGUT COMPONENT-619;Lo;0;L;;;;;N;;;;; +18A6B;TANGUT COMPONENT-620;Lo;0;L;;;;;N;;;;; +18A6C;TANGUT COMPONENT-621;Lo;0;L;;;;;N;;;;; +18A6D;TANGUT COMPONENT-622;Lo;0;L;;;;;N;;;;; +18A6E;TANGUT COMPONENT-623;Lo;0;L;;;;;N;;;;; +18A6F;TANGUT COMPONENT-624;Lo;0;L;;;;;N;;;;; +18A70;TANGUT COMPONENT-625;Lo;0;L;;;;;N;;;;; +18A71;TANGUT COMPONENT-626;Lo;0;L;;;;;N;;;;; +18A72;TANGUT COMPONENT-627;Lo;0;L;;;;;N;;;;; +18A73;TANGUT COMPONENT-628;Lo;0;L;;;;;N;;;;; +18A74;TANGUT COMPONENT-629;Lo;0;L;;;;;N;;;;; +18A75;TANGUT COMPONENT-630;Lo;0;L;;;;;N;;;;; +18A76;TANGUT COMPONENT-631;Lo;0;L;;;;;N;;;;; +18A77;TANGUT COMPONENT-632;Lo;0;L;;;;;N;;;;; +18A78;TANGUT COMPONENT-633;Lo;0;L;;;;;N;;;;; +18A79;TANGUT COMPONENT-634;Lo;0;L;;;;;N;;;;; +18A7A;TANGUT COMPONENT-635;Lo;0;L;;;;;N;;;;; +18A7B;TANGUT COMPONENT-636;Lo;0;L;;;;;N;;;;; +18A7C;TANGUT COMPONENT-637;Lo;0;L;;;;;N;;;;; +18A7D;TANGUT COMPONENT-638;Lo;0;L;;;;;N;;;;; +18A7E;TANGUT COMPONENT-639;Lo;0;L;;;;;N;;;;; +18A7F;TANGUT COMPONENT-640;Lo;0;L;;;;;N;;;;; +18A80;TANGUT COMPONENT-641;Lo;0;L;;;;;N;;;;; +18A81;TANGUT COMPONENT-642;Lo;0;L;;;;;N;;;;; +18A82;TANGUT COMPONENT-643;Lo;0;L;;;;;N;;;;; +18A83;TANGUT COMPONENT-644;Lo;0;L;;;;;N;;;;; +18A84;TANGUT COMPONENT-645;Lo;0;L;;;;;N;;;;; +18A85;TANGUT COMPONENT-646;Lo;0;L;;;;;N;;;;; +18A86;TANGUT COMPONENT-647;Lo;0;L;;;;;N;;;;; +18A87;TANGUT COMPONENT-648;Lo;0;L;;;;;N;;;;; +18A88;TANGUT COMPONENT-649;Lo;0;L;;;;;N;;;;; +18A89;TANGUT COMPONENT-650;Lo;0;L;;;;;N;;;;; +18A8A;TANGUT COMPONENT-651;Lo;0;L;;;;;N;;;;; +18A8B;TANGUT COMPONENT-652;Lo;0;L;;;;;N;;;;; +18A8C;TANGUT COMPONENT-653;Lo;0;L;;;;;N;;;;; +18A8D;TANGUT COMPONENT-654;Lo;0;L;;;;;N;;;;; +18A8E;TANGUT COMPONENT-655;Lo;0;L;;;;;N;;;;; +18A8F;TANGUT COMPONENT-656;Lo;0;L;;;;;N;;;;; +18A90;TANGUT COMPONENT-657;Lo;0;L;;;;;N;;;;; +18A91;TANGUT COMPONENT-658;Lo;0;L;;;;;N;;;;; +18A92;TANGUT COMPONENT-659;Lo;0;L;;;;;N;;;;; +18A93;TANGUT COMPONENT-660;Lo;0;L;;;;;N;;;;; +18A94;TANGUT COMPONENT-661;Lo;0;L;;;;;N;;;;; +18A95;TANGUT COMPONENT-662;Lo;0;L;;;;;N;;;;; +18A96;TANGUT COMPONENT-663;Lo;0;L;;;;;N;;;;; +18A97;TANGUT COMPONENT-664;Lo;0;L;;;;;N;;;;; +18A98;TANGUT COMPONENT-665;Lo;0;L;;;;;N;;;;; +18A99;TANGUT COMPONENT-666;Lo;0;L;;;;;N;;;;; +18A9A;TANGUT COMPONENT-667;Lo;0;L;;;;;N;;;;; +18A9B;TANGUT COMPONENT-668;Lo;0;L;;;;;N;;;;; +18A9C;TANGUT COMPONENT-669;Lo;0;L;;;;;N;;;;; +18A9D;TANGUT COMPONENT-670;Lo;0;L;;;;;N;;;;; +18A9E;TANGUT COMPONENT-671;Lo;0;L;;;;;N;;;;; +18A9F;TANGUT COMPONENT-672;Lo;0;L;;;;;N;;;;; +18AA0;TANGUT COMPONENT-673;Lo;0;L;;;;;N;;;;; +18AA1;TANGUT COMPONENT-674;Lo;0;L;;;;;N;;;;; +18AA2;TANGUT COMPONENT-675;Lo;0;L;;;;;N;;;;; +18AA3;TANGUT COMPONENT-676;Lo;0;L;;;;;N;;;;; +18AA4;TANGUT COMPONENT-677;Lo;0;L;;;;;N;;;;; +18AA5;TANGUT COMPONENT-678;Lo;0;L;;;;;N;;;;; +18AA6;TANGUT COMPONENT-679;Lo;0;L;;;;;N;;;;; +18AA7;TANGUT COMPONENT-680;Lo;0;L;;;;;N;;;;; +18AA8;TANGUT COMPONENT-681;Lo;0;L;;;;;N;;;;; +18AA9;TANGUT COMPONENT-682;Lo;0;L;;;;;N;;;;; +18AAA;TANGUT COMPONENT-683;Lo;0;L;;;;;N;;;;; +18AAB;TANGUT COMPONENT-684;Lo;0;L;;;;;N;;;;; +18AAC;TANGUT COMPONENT-685;Lo;0;L;;;;;N;;;;; +18AAD;TANGUT COMPONENT-686;Lo;0;L;;;;;N;;;;; +18AAE;TANGUT COMPONENT-687;Lo;0;L;;;;;N;;;;; +18AAF;TANGUT COMPONENT-688;Lo;0;L;;;;;N;;;;; +18AB0;TANGUT COMPONENT-689;Lo;0;L;;;;;N;;;;; +18AB1;TANGUT COMPONENT-690;Lo;0;L;;;;;N;;;;; +18AB2;TANGUT COMPONENT-691;Lo;0;L;;;;;N;;;;; +18AB3;TANGUT COMPONENT-692;Lo;0;L;;;;;N;;;;; +18AB4;TANGUT COMPONENT-693;Lo;0;L;;;;;N;;;;; +18AB5;TANGUT COMPONENT-694;Lo;0;L;;;;;N;;;;; +18AB6;TANGUT COMPONENT-695;Lo;0;L;;;;;N;;;;; +18AB7;TANGUT COMPONENT-696;Lo;0;L;;;;;N;;;;; +18AB8;TANGUT COMPONENT-697;Lo;0;L;;;;;N;;;;; +18AB9;TANGUT COMPONENT-698;Lo;0;L;;;;;N;;;;; +18ABA;TANGUT COMPONENT-699;Lo;0;L;;;;;N;;;;; +18ABB;TANGUT COMPONENT-700;Lo;0;L;;;;;N;;;;; +18ABC;TANGUT COMPONENT-701;Lo;0;L;;;;;N;;;;; +18ABD;TANGUT COMPONENT-702;Lo;0;L;;;;;N;;;;; +18ABE;TANGUT COMPONENT-703;Lo;0;L;;;;;N;;;;; +18ABF;TANGUT COMPONENT-704;Lo;0;L;;;;;N;;;;; +18AC0;TANGUT COMPONENT-705;Lo;0;L;;;;;N;;;;; +18AC1;TANGUT COMPONENT-706;Lo;0;L;;;;;N;;;;; +18AC2;TANGUT COMPONENT-707;Lo;0;L;;;;;N;;;;; +18AC3;TANGUT COMPONENT-708;Lo;0;L;;;;;N;;;;; +18AC4;TANGUT COMPONENT-709;Lo;0;L;;;;;N;;;;; +18AC5;TANGUT COMPONENT-710;Lo;0;L;;;;;N;;;;; +18AC6;TANGUT COMPONENT-711;Lo;0;L;;;;;N;;;;; +18AC7;TANGUT COMPONENT-712;Lo;0;L;;;;;N;;;;; +18AC8;TANGUT COMPONENT-713;Lo;0;L;;;;;N;;;;; +18AC9;TANGUT COMPONENT-714;Lo;0;L;;;;;N;;;;; +18ACA;TANGUT COMPONENT-715;Lo;0;L;;;;;N;;;;; +18ACB;TANGUT COMPONENT-716;Lo;0;L;;;;;N;;;;; +18ACC;TANGUT COMPONENT-717;Lo;0;L;;;;;N;;;;; +18ACD;TANGUT COMPONENT-718;Lo;0;L;;;;;N;;;;; +18ACE;TANGUT COMPONENT-719;Lo;0;L;;;;;N;;;;; +18ACF;TANGUT COMPONENT-720;Lo;0;L;;;;;N;;;;; +18AD0;TANGUT COMPONENT-721;Lo;0;L;;;;;N;;;;; +18AD1;TANGUT COMPONENT-722;Lo;0;L;;;;;N;;;;; +18AD2;TANGUT COMPONENT-723;Lo;0;L;;;;;N;;;;; +18AD3;TANGUT COMPONENT-724;Lo;0;L;;;;;N;;;;; +18AD4;TANGUT COMPONENT-725;Lo;0;L;;;;;N;;;;; +18AD5;TANGUT COMPONENT-726;Lo;0;L;;;;;N;;;;; +18AD6;TANGUT COMPONENT-727;Lo;0;L;;;;;N;;;;; +18AD7;TANGUT COMPONENT-728;Lo;0;L;;;;;N;;;;; +18AD8;TANGUT COMPONENT-729;Lo;0;L;;;;;N;;;;; +18AD9;TANGUT COMPONENT-730;Lo;0;L;;;;;N;;;;; +18ADA;TANGUT COMPONENT-731;Lo;0;L;;;;;N;;;;; +18ADB;TANGUT COMPONENT-732;Lo;0;L;;;;;N;;;;; +18ADC;TANGUT COMPONENT-733;Lo;0;L;;;;;N;;;;; +18ADD;TANGUT COMPONENT-734;Lo;0;L;;;;;N;;;;; +18ADE;TANGUT COMPONENT-735;Lo;0;L;;;;;N;;;;; +18ADF;TANGUT COMPONENT-736;Lo;0;L;;;;;N;;;;; +18AE0;TANGUT COMPONENT-737;Lo;0;L;;;;;N;;;;; +18AE1;TANGUT COMPONENT-738;Lo;0;L;;;;;N;;;;; +18AE2;TANGUT COMPONENT-739;Lo;0;L;;;;;N;;;;; +18AE3;TANGUT COMPONENT-740;Lo;0;L;;;;;N;;;;; +18AE4;TANGUT COMPONENT-741;Lo;0;L;;;;;N;;;;; +18AE5;TANGUT COMPONENT-742;Lo;0;L;;;;;N;;;;; +18AE6;TANGUT COMPONENT-743;Lo;0;L;;;;;N;;;;; +18AE7;TANGUT COMPONENT-744;Lo;0;L;;;;;N;;;;; +18AE8;TANGUT COMPONENT-745;Lo;0;L;;;;;N;;;;; +18AE9;TANGUT COMPONENT-746;Lo;0;L;;;;;N;;;;; +18AEA;TANGUT COMPONENT-747;Lo;0;L;;;;;N;;;;; +18AEB;TANGUT COMPONENT-748;Lo;0;L;;;;;N;;;;; +18AEC;TANGUT COMPONENT-749;Lo;0;L;;;;;N;;;;; +18AED;TANGUT COMPONENT-750;Lo;0;L;;;;;N;;;;; +18AEE;TANGUT COMPONENT-751;Lo;0;L;;;;;N;;;;; +18AEF;TANGUT COMPONENT-752;Lo;0;L;;;;;N;;;;; +18AF0;TANGUT COMPONENT-753;Lo;0;L;;;;;N;;;;; +18AF1;TANGUT COMPONENT-754;Lo;0;L;;;;;N;;;;; +18AF2;TANGUT COMPONENT-755;Lo;0;L;;;;;N;;;;; +1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; +1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; +1B002;HENTAIGANA LETTER A-1;Lo;0;L;;;;;N;;;;; +1B003;HENTAIGANA LETTER A-2;Lo;0;L;;;;;N;;;;; +1B004;HENTAIGANA LETTER A-3;Lo;0;L;;;;;N;;;;; +1B005;HENTAIGANA LETTER A-WO;Lo;0;L;;;;;N;;;;; +1B006;HENTAIGANA LETTER I-1;Lo;0;L;;;;;N;;;;; +1B007;HENTAIGANA LETTER I-2;Lo;0;L;;;;;N;;;;; +1B008;HENTAIGANA LETTER I-3;Lo;0;L;;;;;N;;;;; +1B009;HENTAIGANA LETTER I-4;Lo;0;L;;;;;N;;;;; +1B00A;HENTAIGANA LETTER U-1;Lo;0;L;;;;;N;;;;; +1B00B;HENTAIGANA LETTER U-2;Lo;0;L;;;;;N;;;;; +1B00C;HENTAIGANA LETTER U-3;Lo;0;L;;;;;N;;;;; +1B00D;HENTAIGANA LETTER U-4;Lo;0;L;;;;;N;;;;; +1B00E;HENTAIGANA LETTER U-5;Lo;0;L;;;;;N;;;;; +1B00F;HENTAIGANA LETTER E-2;Lo;0;L;;;;;N;;;;; +1B010;HENTAIGANA LETTER E-3;Lo;0;L;;;;;N;;;;; +1B011;HENTAIGANA LETTER E-4;Lo;0;L;;;;;N;;;;; +1B012;HENTAIGANA LETTER E-5;Lo;0;L;;;;;N;;;;; +1B013;HENTAIGANA LETTER E-6;Lo;0;L;;;;;N;;;;; +1B014;HENTAIGANA LETTER O-1;Lo;0;L;;;;;N;;;;; +1B015;HENTAIGANA LETTER O-2;Lo;0;L;;;;;N;;;;; +1B016;HENTAIGANA LETTER O-3;Lo;0;L;;;;;N;;;;; +1B017;HENTAIGANA LETTER KA-1;Lo;0;L;;;;;N;;;;; +1B018;HENTAIGANA LETTER KA-2;Lo;0;L;;;;;N;;;;; +1B019;HENTAIGANA LETTER KA-3;Lo;0;L;;;;;N;;;;; +1B01A;HENTAIGANA LETTER KA-4;Lo;0;L;;;;;N;;;;; +1B01B;HENTAIGANA LETTER KA-5;Lo;0;L;;;;;N;;;;; +1B01C;HENTAIGANA LETTER KA-6;Lo;0;L;;;;;N;;;;; +1B01D;HENTAIGANA LETTER KA-7;Lo;0;L;;;;;N;;;;; +1B01E;HENTAIGANA LETTER KA-8;Lo;0;L;;;;;N;;;;; +1B01F;HENTAIGANA LETTER KA-9;Lo;0;L;;;;;N;;;;; +1B020;HENTAIGANA LETTER KA-10;Lo;0;L;;;;;N;;;;; +1B021;HENTAIGANA LETTER KA-11;Lo;0;L;;;;;N;;;;; +1B022;HENTAIGANA LETTER KA-KE;Lo;0;L;;;;;N;;;;; +1B023;HENTAIGANA LETTER KI-1;Lo;0;L;;;;;N;;;;; +1B024;HENTAIGANA LETTER KI-2;Lo;0;L;;;;;N;;;;; +1B025;HENTAIGANA LETTER KI-3;Lo;0;L;;;;;N;;;;; +1B026;HENTAIGANA LETTER KI-4;Lo;0;L;;;;;N;;;;; +1B027;HENTAIGANA LETTER KI-5;Lo;0;L;;;;;N;;;;; +1B028;HENTAIGANA LETTER KI-6;Lo;0;L;;;;;N;;;;; +1B029;HENTAIGANA LETTER KI-7;Lo;0;L;;;;;N;;;;; +1B02A;HENTAIGANA LETTER KI-8;Lo;0;L;;;;;N;;;;; +1B02B;HENTAIGANA LETTER KU-1;Lo;0;L;;;;;N;;;;; +1B02C;HENTAIGANA LETTER KU-2;Lo;0;L;;;;;N;;;;; +1B02D;HENTAIGANA LETTER KU-3;Lo;0;L;;;;;N;;;;; +1B02E;HENTAIGANA LETTER KU-4;Lo;0;L;;;;;N;;;;; +1B02F;HENTAIGANA LETTER KU-5;Lo;0;L;;;;;N;;;;; +1B030;HENTAIGANA LETTER KU-6;Lo;0;L;;;;;N;;;;; +1B031;HENTAIGANA LETTER KU-7;Lo;0;L;;;;;N;;;;; +1B032;HENTAIGANA LETTER KE-1;Lo;0;L;;;;;N;;;;; +1B033;HENTAIGANA LETTER KE-2;Lo;0;L;;;;;N;;;;; +1B034;HENTAIGANA LETTER KE-3;Lo;0;L;;;;;N;;;;; +1B035;HENTAIGANA LETTER KE-4;Lo;0;L;;;;;N;;;;; +1B036;HENTAIGANA LETTER KE-5;Lo;0;L;;;;;N;;;;; +1B037;HENTAIGANA LETTER KE-6;Lo;0;L;;;;;N;;;;; +1B038;HENTAIGANA LETTER KO-1;Lo;0;L;;;;;N;;;;; +1B039;HENTAIGANA LETTER KO-2;Lo;0;L;;;;;N;;;;; +1B03A;HENTAIGANA LETTER KO-3;Lo;0;L;;;;;N;;;;; +1B03B;HENTAIGANA LETTER KO-KI;Lo;0;L;;;;;N;;;;; +1B03C;HENTAIGANA LETTER SA-1;Lo;0;L;;;;;N;;;;; +1B03D;HENTAIGANA LETTER SA-2;Lo;0;L;;;;;N;;;;; +1B03E;HENTAIGANA LETTER SA-3;Lo;0;L;;;;;N;;;;; +1B03F;HENTAIGANA LETTER SA-4;Lo;0;L;;;;;N;;;;; +1B040;HENTAIGANA LETTER SA-5;Lo;0;L;;;;;N;;;;; +1B041;HENTAIGANA LETTER SA-6;Lo;0;L;;;;;N;;;;; +1B042;HENTAIGANA LETTER SA-7;Lo;0;L;;;;;N;;;;; +1B043;HENTAIGANA LETTER SA-8;Lo;0;L;;;;;N;;;;; +1B044;HENTAIGANA LETTER SI-1;Lo;0;L;;;;;N;;;;; +1B045;HENTAIGANA LETTER SI-2;Lo;0;L;;;;;N;;;;; +1B046;HENTAIGANA LETTER SI-3;Lo;0;L;;;;;N;;;;; +1B047;HENTAIGANA LETTER SI-4;Lo;0;L;;;;;N;;;;; +1B048;HENTAIGANA LETTER SI-5;Lo;0;L;;;;;N;;;;; +1B049;HENTAIGANA LETTER SI-6;Lo;0;L;;;;;N;;;;; +1B04A;HENTAIGANA LETTER SU-1;Lo;0;L;;;;;N;;;;; +1B04B;HENTAIGANA LETTER SU-2;Lo;0;L;;;;;N;;;;; +1B04C;HENTAIGANA LETTER SU-3;Lo;0;L;;;;;N;;;;; +1B04D;HENTAIGANA LETTER SU-4;Lo;0;L;;;;;N;;;;; +1B04E;HENTAIGANA LETTER SU-5;Lo;0;L;;;;;N;;;;; +1B04F;HENTAIGANA LETTER SU-6;Lo;0;L;;;;;N;;;;; +1B050;HENTAIGANA LETTER SU-7;Lo;0;L;;;;;N;;;;; +1B051;HENTAIGANA LETTER SU-8;Lo;0;L;;;;;N;;;;; +1B052;HENTAIGANA LETTER SE-1;Lo;0;L;;;;;N;;;;; +1B053;HENTAIGANA LETTER SE-2;Lo;0;L;;;;;N;;;;; +1B054;HENTAIGANA LETTER SE-3;Lo;0;L;;;;;N;;;;; +1B055;HENTAIGANA LETTER SE-4;Lo;0;L;;;;;N;;;;; +1B056;HENTAIGANA LETTER SE-5;Lo;0;L;;;;;N;;;;; +1B057;HENTAIGANA LETTER SO-1;Lo;0;L;;;;;N;;;;; +1B058;HENTAIGANA LETTER SO-2;Lo;0;L;;;;;N;;;;; +1B059;HENTAIGANA LETTER SO-3;Lo;0;L;;;;;N;;;;; +1B05A;HENTAIGANA LETTER SO-4;Lo;0;L;;;;;N;;;;; +1B05B;HENTAIGANA LETTER SO-5;Lo;0;L;;;;;N;;;;; +1B05C;HENTAIGANA LETTER SO-6;Lo;0;L;;;;;N;;;;; +1B05D;HENTAIGANA LETTER SO-7;Lo;0;L;;;;;N;;;;; +1B05E;HENTAIGANA LETTER TA-1;Lo;0;L;;;;;N;;;;; +1B05F;HENTAIGANA LETTER TA-2;Lo;0;L;;;;;N;;;;; +1B060;HENTAIGANA LETTER TA-3;Lo;0;L;;;;;N;;;;; +1B061;HENTAIGANA LETTER TA-4;Lo;0;L;;;;;N;;;;; +1B062;HENTAIGANA LETTER TI-1;Lo;0;L;;;;;N;;;;; +1B063;HENTAIGANA LETTER TI-2;Lo;0;L;;;;;N;;;;; +1B064;HENTAIGANA LETTER TI-3;Lo;0;L;;;;;N;;;;; +1B065;HENTAIGANA LETTER TI-4;Lo;0;L;;;;;N;;;;; +1B066;HENTAIGANA LETTER TI-5;Lo;0;L;;;;;N;;;;; +1B067;HENTAIGANA LETTER TI-6;Lo;0;L;;;;;N;;;;; +1B068;HENTAIGANA LETTER TI-7;Lo;0;L;;;;;N;;;;; +1B069;HENTAIGANA LETTER TU-1;Lo;0;L;;;;;N;;;;; +1B06A;HENTAIGANA LETTER TU-2;Lo;0;L;;;;;N;;;;; +1B06B;HENTAIGANA LETTER TU-3;Lo;0;L;;;;;N;;;;; +1B06C;HENTAIGANA LETTER TU-4;Lo;0;L;;;;;N;;;;; +1B06D;HENTAIGANA LETTER TU-TO;Lo;0;L;;;;;N;;;;; +1B06E;HENTAIGANA LETTER TE-1;Lo;0;L;;;;;N;;;;; +1B06F;HENTAIGANA LETTER TE-2;Lo;0;L;;;;;N;;;;; +1B070;HENTAIGANA LETTER TE-3;Lo;0;L;;;;;N;;;;; +1B071;HENTAIGANA LETTER TE-4;Lo;0;L;;;;;N;;;;; +1B072;HENTAIGANA LETTER TE-5;Lo;0;L;;;;;N;;;;; +1B073;HENTAIGANA LETTER TE-6;Lo;0;L;;;;;N;;;;; +1B074;HENTAIGANA LETTER TE-7;Lo;0;L;;;;;N;;;;; +1B075;HENTAIGANA LETTER TE-8;Lo;0;L;;;;;N;;;;; +1B076;HENTAIGANA LETTER TE-9;Lo;0;L;;;;;N;;;;; +1B077;HENTAIGANA LETTER TO-1;Lo;0;L;;;;;N;;;;; +1B078;HENTAIGANA LETTER TO-2;Lo;0;L;;;;;N;;;;; +1B079;HENTAIGANA LETTER TO-3;Lo;0;L;;;;;N;;;;; +1B07A;HENTAIGANA LETTER TO-4;Lo;0;L;;;;;N;;;;; +1B07B;HENTAIGANA LETTER TO-5;Lo;0;L;;;;;N;;;;; +1B07C;HENTAIGANA LETTER TO-6;Lo;0;L;;;;;N;;;;; +1B07D;HENTAIGANA LETTER TO-RA;Lo;0;L;;;;;N;;;;; +1B07E;HENTAIGANA LETTER NA-1;Lo;0;L;;;;;N;;;;; +1B07F;HENTAIGANA LETTER NA-2;Lo;0;L;;;;;N;;;;; +1B080;HENTAIGANA LETTER NA-3;Lo;0;L;;;;;N;;;;; +1B081;HENTAIGANA LETTER NA-4;Lo;0;L;;;;;N;;;;; +1B082;HENTAIGANA LETTER NA-5;Lo;0;L;;;;;N;;;;; +1B083;HENTAIGANA LETTER NA-6;Lo;0;L;;;;;N;;;;; +1B084;HENTAIGANA LETTER NA-7;Lo;0;L;;;;;N;;;;; +1B085;HENTAIGANA LETTER NA-8;Lo;0;L;;;;;N;;;;; +1B086;HENTAIGANA LETTER NA-9;Lo;0;L;;;;;N;;;;; +1B087;HENTAIGANA LETTER NI-1;Lo;0;L;;;;;N;;;;; +1B088;HENTAIGANA LETTER NI-2;Lo;0;L;;;;;N;;;;; +1B089;HENTAIGANA LETTER NI-3;Lo;0;L;;;;;N;;;;; +1B08A;HENTAIGANA LETTER NI-4;Lo;0;L;;;;;N;;;;; +1B08B;HENTAIGANA LETTER NI-5;Lo;0;L;;;;;N;;;;; +1B08C;HENTAIGANA LETTER NI-6;Lo;0;L;;;;;N;;;;; +1B08D;HENTAIGANA LETTER NI-7;Lo;0;L;;;;;N;;;;; +1B08E;HENTAIGANA LETTER NI-TE;Lo;0;L;;;;;N;;;;; +1B08F;HENTAIGANA LETTER NU-1;Lo;0;L;;;;;N;;;;; +1B090;HENTAIGANA LETTER NU-2;Lo;0;L;;;;;N;;;;; +1B091;HENTAIGANA LETTER NU-3;Lo;0;L;;;;;N;;;;; +1B092;HENTAIGANA LETTER NE-1;Lo;0;L;;;;;N;;;;; +1B093;HENTAIGANA LETTER NE-2;Lo;0;L;;;;;N;;;;; +1B094;HENTAIGANA LETTER NE-3;Lo;0;L;;;;;N;;;;; +1B095;HENTAIGANA LETTER NE-4;Lo;0;L;;;;;N;;;;; +1B096;HENTAIGANA LETTER NE-5;Lo;0;L;;;;;N;;;;; +1B097;HENTAIGANA LETTER NE-6;Lo;0;L;;;;;N;;;;; +1B098;HENTAIGANA LETTER NE-KO;Lo;0;L;;;;;N;;;;; +1B099;HENTAIGANA LETTER NO-1;Lo;0;L;;;;;N;;;;; +1B09A;HENTAIGANA LETTER NO-2;Lo;0;L;;;;;N;;;;; +1B09B;HENTAIGANA LETTER NO-3;Lo;0;L;;;;;N;;;;; +1B09C;HENTAIGANA LETTER NO-4;Lo;0;L;;;;;N;;;;; +1B09D;HENTAIGANA LETTER NO-5;Lo;0;L;;;;;N;;;;; +1B09E;HENTAIGANA LETTER HA-1;Lo;0;L;;;;;N;;;;; +1B09F;HENTAIGANA LETTER HA-2;Lo;0;L;;;;;N;;;;; +1B0A0;HENTAIGANA LETTER HA-3;Lo;0;L;;;;;N;;;;; +1B0A1;HENTAIGANA LETTER HA-4;Lo;0;L;;;;;N;;;;; +1B0A2;HENTAIGANA LETTER HA-5;Lo;0;L;;;;;N;;;;; +1B0A3;HENTAIGANA LETTER HA-6;Lo;0;L;;;;;N;;;;; +1B0A4;HENTAIGANA LETTER HA-7;Lo;0;L;;;;;N;;;;; +1B0A5;HENTAIGANA LETTER HA-8;Lo;0;L;;;;;N;;;;; +1B0A6;HENTAIGANA LETTER HA-9;Lo;0;L;;;;;N;;;;; +1B0A7;HENTAIGANA LETTER HA-10;Lo;0;L;;;;;N;;;;; +1B0A8;HENTAIGANA LETTER HA-11;Lo;0;L;;;;;N;;;;; +1B0A9;HENTAIGANA LETTER HI-1;Lo;0;L;;;;;N;;;;; +1B0AA;HENTAIGANA LETTER HI-2;Lo;0;L;;;;;N;;;;; +1B0AB;HENTAIGANA LETTER HI-3;Lo;0;L;;;;;N;;;;; +1B0AC;HENTAIGANA LETTER HI-4;Lo;0;L;;;;;N;;;;; +1B0AD;HENTAIGANA LETTER HI-5;Lo;0;L;;;;;N;;;;; +1B0AE;HENTAIGANA LETTER HI-6;Lo;0;L;;;;;N;;;;; +1B0AF;HENTAIGANA LETTER HI-7;Lo;0;L;;;;;N;;;;; +1B0B0;HENTAIGANA LETTER HU-1;Lo;0;L;;;;;N;;;;; +1B0B1;HENTAIGANA LETTER HU-2;Lo;0;L;;;;;N;;;;; +1B0B2;HENTAIGANA LETTER HU-3;Lo;0;L;;;;;N;;;;; +1B0B3;HENTAIGANA LETTER HE-1;Lo;0;L;;;;;N;;;;; +1B0B4;HENTAIGANA LETTER HE-2;Lo;0;L;;;;;N;;;;; +1B0B5;HENTAIGANA LETTER HE-3;Lo;0;L;;;;;N;;;;; +1B0B6;HENTAIGANA LETTER HE-4;Lo;0;L;;;;;N;;;;; +1B0B7;HENTAIGANA LETTER HE-5;Lo;0;L;;;;;N;;;;; +1B0B8;HENTAIGANA LETTER HE-6;Lo;0;L;;;;;N;;;;; +1B0B9;HENTAIGANA LETTER HE-7;Lo;0;L;;;;;N;;;;; +1B0BA;HENTAIGANA LETTER HO-1;Lo;0;L;;;;;N;;;;; +1B0BB;HENTAIGANA LETTER HO-2;Lo;0;L;;;;;N;;;;; +1B0BC;HENTAIGANA LETTER HO-3;Lo;0;L;;;;;N;;;;; +1B0BD;HENTAIGANA LETTER HO-4;Lo;0;L;;;;;N;;;;; +1B0BE;HENTAIGANA LETTER HO-5;Lo;0;L;;;;;N;;;;; +1B0BF;HENTAIGANA LETTER HO-6;Lo;0;L;;;;;N;;;;; +1B0C0;HENTAIGANA LETTER HO-7;Lo;0;L;;;;;N;;;;; +1B0C1;HENTAIGANA LETTER HO-8;Lo;0;L;;;;;N;;;;; +1B0C2;HENTAIGANA LETTER MA-1;Lo;0;L;;;;;N;;;;; +1B0C3;HENTAIGANA LETTER MA-2;Lo;0;L;;;;;N;;;;; +1B0C4;HENTAIGANA LETTER MA-3;Lo;0;L;;;;;N;;;;; +1B0C5;HENTAIGANA LETTER MA-4;Lo;0;L;;;;;N;;;;; +1B0C6;HENTAIGANA LETTER MA-5;Lo;0;L;;;;;N;;;;; +1B0C7;HENTAIGANA LETTER MA-6;Lo;0;L;;;;;N;;;;; +1B0C8;HENTAIGANA LETTER MA-7;Lo;0;L;;;;;N;;;;; +1B0C9;HENTAIGANA LETTER MI-1;Lo;0;L;;;;;N;;;;; +1B0CA;HENTAIGANA LETTER MI-2;Lo;0;L;;;;;N;;;;; +1B0CB;HENTAIGANA LETTER MI-3;Lo;0;L;;;;;N;;;;; +1B0CC;HENTAIGANA LETTER MI-4;Lo;0;L;;;;;N;;;;; +1B0CD;HENTAIGANA LETTER MI-5;Lo;0;L;;;;;N;;;;; +1B0CE;HENTAIGANA LETTER MI-6;Lo;0;L;;;;;N;;;;; +1B0CF;HENTAIGANA LETTER MI-7;Lo;0;L;;;;;N;;;;; +1B0D0;HENTAIGANA LETTER MU-1;Lo;0;L;;;;;N;;;;; +1B0D1;HENTAIGANA LETTER MU-2;Lo;0;L;;;;;N;;;;; +1B0D2;HENTAIGANA LETTER MU-3;Lo;0;L;;;;;N;;;;; +1B0D3;HENTAIGANA LETTER MU-4;Lo;0;L;;;;;N;;;;; +1B0D4;HENTAIGANA LETTER ME-1;Lo;0;L;;;;;N;;;;; +1B0D5;HENTAIGANA LETTER ME-2;Lo;0;L;;;;;N;;;;; +1B0D6;HENTAIGANA LETTER ME-MA;Lo;0;L;;;;;N;;;;; +1B0D7;HENTAIGANA LETTER MO-1;Lo;0;L;;;;;N;;;;; +1B0D8;HENTAIGANA LETTER MO-2;Lo;0;L;;;;;N;;;;; +1B0D9;HENTAIGANA LETTER MO-3;Lo;0;L;;;;;N;;;;; +1B0DA;HENTAIGANA LETTER MO-4;Lo;0;L;;;;;N;;;;; +1B0DB;HENTAIGANA LETTER MO-5;Lo;0;L;;;;;N;;;;; +1B0DC;HENTAIGANA LETTER MO-6;Lo;0;L;;;;;N;;;;; +1B0DD;HENTAIGANA LETTER YA-1;Lo;0;L;;;;;N;;;;; +1B0DE;HENTAIGANA LETTER YA-2;Lo;0;L;;;;;N;;;;; +1B0DF;HENTAIGANA LETTER YA-3;Lo;0;L;;;;;N;;;;; +1B0E0;HENTAIGANA LETTER YA-4;Lo;0;L;;;;;N;;;;; +1B0E1;HENTAIGANA LETTER YA-5;Lo;0;L;;;;;N;;;;; +1B0E2;HENTAIGANA LETTER YA-YO;Lo;0;L;;;;;N;;;;; +1B0E3;HENTAIGANA LETTER YU-1;Lo;0;L;;;;;N;;;;; +1B0E4;HENTAIGANA LETTER YU-2;Lo;0;L;;;;;N;;;;; +1B0E5;HENTAIGANA LETTER YU-3;Lo;0;L;;;;;N;;;;; +1B0E6;HENTAIGANA LETTER YU-4;Lo;0;L;;;;;N;;;;; +1B0E7;HENTAIGANA LETTER YO-1;Lo;0;L;;;;;N;;;;; +1B0E8;HENTAIGANA LETTER YO-2;Lo;0;L;;;;;N;;;;; +1B0E9;HENTAIGANA LETTER YO-3;Lo;0;L;;;;;N;;;;; +1B0EA;HENTAIGANA LETTER YO-4;Lo;0;L;;;;;N;;;;; +1B0EB;HENTAIGANA LETTER YO-5;Lo;0;L;;;;;N;;;;; +1B0EC;HENTAIGANA LETTER YO-6;Lo;0;L;;;;;N;;;;; +1B0ED;HENTAIGANA LETTER RA-1;Lo;0;L;;;;;N;;;;; +1B0EE;HENTAIGANA LETTER RA-2;Lo;0;L;;;;;N;;;;; +1B0EF;HENTAIGANA LETTER RA-3;Lo;0;L;;;;;N;;;;; +1B0F0;HENTAIGANA LETTER RA-4;Lo;0;L;;;;;N;;;;; +1B0F1;HENTAIGANA LETTER RI-1;Lo;0;L;;;;;N;;;;; +1B0F2;HENTAIGANA LETTER RI-2;Lo;0;L;;;;;N;;;;; +1B0F3;HENTAIGANA LETTER RI-3;Lo;0;L;;;;;N;;;;; +1B0F4;HENTAIGANA LETTER RI-4;Lo;0;L;;;;;N;;;;; +1B0F5;HENTAIGANA LETTER RI-5;Lo;0;L;;;;;N;;;;; +1B0F6;HENTAIGANA LETTER RI-6;Lo;0;L;;;;;N;;;;; +1B0F7;HENTAIGANA LETTER RI-7;Lo;0;L;;;;;N;;;;; +1B0F8;HENTAIGANA LETTER RU-1;Lo;0;L;;;;;N;;;;; +1B0F9;HENTAIGANA LETTER RU-2;Lo;0;L;;;;;N;;;;; +1B0FA;HENTAIGANA LETTER RU-3;Lo;0;L;;;;;N;;;;; +1B0FB;HENTAIGANA LETTER RU-4;Lo;0;L;;;;;N;;;;; +1B0FC;HENTAIGANA LETTER RU-5;Lo;0;L;;;;;N;;;;; +1B0FD;HENTAIGANA LETTER RU-6;Lo;0;L;;;;;N;;;;; +1B0FE;HENTAIGANA LETTER RE-1;Lo;0;L;;;;;N;;;;; +1B0FF;HENTAIGANA LETTER RE-2;Lo;0;L;;;;;N;;;;; +1B100;HENTAIGANA LETTER RE-3;Lo;0;L;;;;;N;;;;; +1B101;HENTAIGANA LETTER RE-4;Lo;0;L;;;;;N;;;;; +1B102;HENTAIGANA LETTER RO-1;Lo;0;L;;;;;N;;;;; +1B103;HENTAIGANA LETTER RO-2;Lo;0;L;;;;;N;;;;; +1B104;HENTAIGANA LETTER RO-3;Lo;0;L;;;;;N;;;;; +1B105;HENTAIGANA LETTER RO-4;Lo;0;L;;;;;N;;;;; +1B106;HENTAIGANA LETTER RO-5;Lo;0;L;;;;;N;;;;; +1B107;HENTAIGANA LETTER RO-6;Lo;0;L;;;;;N;;;;; +1B108;HENTAIGANA LETTER WA-1;Lo;0;L;;;;;N;;;;; +1B109;HENTAIGANA LETTER WA-2;Lo;0;L;;;;;N;;;;; +1B10A;HENTAIGANA LETTER WA-3;Lo;0;L;;;;;N;;;;; +1B10B;HENTAIGANA LETTER WA-4;Lo;0;L;;;;;N;;;;; +1B10C;HENTAIGANA LETTER WA-5;Lo;0;L;;;;;N;;;;; +1B10D;HENTAIGANA LETTER WI-1;Lo;0;L;;;;;N;;;;; +1B10E;HENTAIGANA LETTER WI-2;Lo;0;L;;;;;N;;;;; +1B10F;HENTAIGANA LETTER WI-3;Lo;0;L;;;;;N;;;;; +1B110;HENTAIGANA LETTER WI-4;Lo;0;L;;;;;N;;;;; +1B111;HENTAIGANA LETTER WI-5;Lo;0;L;;;;;N;;;;; +1B112;HENTAIGANA LETTER WE-1;Lo;0;L;;;;;N;;;;; +1B113;HENTAIGANA LETTER WE-2;Lo;0;L;;;;;N;;;;; +1B114;HENTAIGANA LETTER WE-3;Lo;0;L;;;;;N;;;;; +1B115;HENTAIGANA LETTER WE-4;Lo;0;L;;;;;N;;;;; +1B116;HENTAIGANA LETTER WO-1;Lo;0;L;;;;;N;;;;; +1B117;HENTAIGANA LETTER WO-2;Lo;0;L;;;;;N;;;;; +1B118;HENTAIGANA LETTER WO-3;Lo;0;L;;;;;N;;;;; +1B119;HENTAIGANA LETTER WO-4;Lo;0;L;;;;;N;;;;; +1B11A;HENTAIGANA LETTER WO-5;Lo;0;L;;;;;N;;;;; +1B11B;HENTAIGANA LETTER WO-6;Lo;0;L;;;;;N;;;;; +1B11C;HENTAIGANA LETTER WO-7;Lo;0;L;;;;;N;;;;; +1B11D;HENTAIGANA LETTER N-MU-MO-1;Lo;0;L;;;;;N;;;;; +1B11E;HENTAIGANA LETTER N-MU-MO-2;Lo;0;L;;;;;N;;;;; +1B170;NUSHU CHARACTER-1B170;Lo;0;L;;;;;N;;;;; +1B171;NUSHU CHARACTER-1B171;Lo;0;L;;;;;N;;;;; +1B172;NUSHU CHARACTER-1B172;Lo;0;L;;;;;N;;;;; +1B173;NUSHU CHARACTER-1B173;Lo;0;L;;;;;N;;;;; +1B174;NUSHU CHARACTER-1B174;Lo;0;L;;;;;N;;;;; +1B175;NUSHU CHARACTER-1B175;Lo;0;L;;;;;N;;;;; +1B176;NUSHU CHARACTER-1B176;Lo;0;L;;;;;N;;;;; +1B177;NUSHU CHARACTER-1B177;Lo;0;L;;;;;N;;;;; +1B178;NUSHU CHARACTER-1B178;Lo;0;L;;;;;N;;;;; +1B179;NUSHU CHARACTER-1B179;Lo;0;L;;;;;N;;;;; +1B17A;NUSHU CHARACTER-1B17A;Lo;0;L;;;;;N;;;;; +1B17B;NUSHU CHARACTER-1B17B;Lo;0;L;;;;;N;;;;; +1B17C;NUSHU CHARACTER-1B17C;Lo;0;L;;;;;N;;;;; +1B17D;NUSHU CHARACTER-1B17D;Lo;0;L;;;;;N;;;;; +1B17E;NUSHU CHARACTER-1B17E;Lo;0;L;;;;;N;;;;; +1B17F;NUSHU CHARACTER-1B17F;Lo;0;L;;;;;N;;;;; +1B180;NUSHU CHARACTER-1B180;Lo;0;L;;;;;N;;;;; +1B181;NUSHU CHARACTER-1B181;Lo;0;L;;;;;N;;;;; +1B182;NUSHU CHARACTER-1B182;Lo;0;L;;;;;N;;;;; +1B183;NUSHU CHARACTER-1B183;Lo;0;L;;;;;N;;;;; +1B184;NUSHU CHARACTER-1B184;Lo;0;L;;;;;N;;;;; +1B185;NUSHU CHARACTER-1B185;Lo;0;L;;;;;N;;;;; +1B186;NUSHU CHARACTER-1B186;Lo;0;L;;;;;N;;;;; +1B187;NUSHU CHARACTER-1B187;Lo;0;L;;;;;N;;;;; +1B188;NUSHU CHARACTER-1B188;Lo;0;L;;;;;N;;;;; +1B189;NUSHU CHARACTER-1B189;Lo;0;L;;;;;N;;;;; +1B18A;NUSHU CHARACTER-1B18A;Lo;0;L;;;;;N;;;;; +1B18B;NUSHU CHARACTER-1B18B;Lo;0;L;;;;;N;;;;; +1B18C;NUSHU CHARACTER-1B18C;Lo;0;L;;;;;N;;;;; +1B18D;NUSHU CHARACTER-1B18D;Lo;0;L;;;;;N;;;;; +1B18E;NUSHU CHARACTER-1B18E;Lo;0;L;;;;;N;;;;; +1B18F;NUSHU CHARACTER-1B18F;Lo;0;L;;;;;N;;;;; +1B190;NUSHU CHARACTER-1B190;Lo;0;L;;;;;N;;;;; +1B191;NUSHU CHARACTER-1B191;Lo;0;L;;;;;N;;;;; +1B192;NUSHU CHARACTER-1B192;Lo;0;L;;;;;N;;;;; +1B193;NUSHU CHARACTER-1B193;Lo;0;L;;;;;N;;;;; +1B194;NUSHU CHARACTER-1B194;Lo;0;L;;;;;N;;;;; +1B195;NUSHU CHARACTER-1B195;Lo;0;L;;;;;N;;;;; +1B196;NUSHU CHARACTER-1B196;Lo;0;L;;;;;N;;;;; +1B197;NUSHU CHARACTER-1B197;Lo;0;L;;;;;N;;;;; +1B198;NUSHU CHARACTER-1B198;Lo;0;L;;;;;N;;;;; +1B199;NUSHU CHARACTER-1B199;Lo;0;L;;;;;N;;;;; +1B19A;NUSHU CHARACTER-1B19A;Lo;0;L;;;;;N;;;;; +1B19B;NUSHU CHARACTER-1B19B;Lo;0;L;;;;;N;;;;; +1B19C;NUSHU CHARACTER-1B19C;Lo;0;L;;;;;N;;;;; +1B19D;NUSHU CHARACTER-1B19D;Lo;0;L;;;;;N;;;;; +1B19E;NUSHU CHARACTER-1B19E;Lo;0;L;;;;;N;;;;; +1B19F;NUSHU CHARACTER-1B19F;Lo;0;L;;;;;N;;;;; +1B1A0;NUSHU CHARACTER-1B1A0;Lo;0;L;;;;;N;;;;; +1B1A1;NUSHU CHARACTER-1B1A1;Lo;0;L;;;;;N;;;;; +1B1A2;NUSHU CHARACTER-1B1A2;Lo;0;L;;;;;N;;;;; +1B1A3;NUSHU CHARACTER-1B1A3;Lo;0;L;;;;;N;;;;; +1B1A4;NUSHU CHARACTER-1B1A4;Lo;0;L;;;;;N;;;;; +1B1A5;NUSHU CHARACTER-1B1A5;Lo;0;L;;;;;N;;;;; +1B1A6;NUSHU CHARACTER-1B1A6;Lo;0;L;;;;;N;;;;; +1B1A7;NUSHU CHARACTER-1B1A7;Lo;0;L;;;;;N;;;;; +1B1A8;NUSHU CHARACTER-1B1A8;Lo;0;L;;;;;N;;;;; +1B1A9;NUSHU CHARACTER-1B1A9;Lo;0;L;;;;;N;;;;; +1B1AA;NUSHU CHARACTER-1B1AA;Lo;0;L;;;;;N;;;;; +1B1AB;NUSHU CHARACTER-1B1AB;Lo;0;L;;;;;N;;;;; +1B1AC;NUSHU CHARACTER-1B1AC;Lo;0;L;;;;;N;;;;; +1B1AD;NUSHU CHARACTER-1B1AD;Lo;0;L;;;;;N;;;;; +1B1AE;NUSHU CHARACTER-1B1AE;Lo;0;L;;;;;N;;;;; +1B1AF;NUSHU CHARACTER-1B1AF;Lo;0;L;;;;;N;;;;; +1B1B0;NUSHU CHARACTER-1B1B0;Lo;0;L;;;;;N;;;;; +1B1B1;NUSHU CHARACTER-1B1B1;Lo;0;L;;;;;N;;;;; +1B1B2;NUSHU CHARACTER-1B1B2;Lo;0;L;;;;;N;;;;; +1B1B3;NUSHU CHARACTER-1B1B3;Lo;0;L;;;;;N;;;;; +1B1B4;NUSHU CHARACTER-1B1B4;Lo;0;L;;;;;N;;;;; +1B1B5;NUSHU CHARACTER-1B1B5;Lo;0;L;;;;;N;;;;; +1B1B6;NUSHU CHARACTER-1B1B6;Lo;0;L;;;;;N;;;;; +1B1B7;NUSHU CHARACTER-1B1B7;Lo;0;L;;;;;N;;;;; +1B1B8;NUSHU CHARACTER-1B1B8;Lo;0;L;;;;;N;;;;; +1B1B9;NUSHU CHARACTER-1B1B9;Lo;0;L;;;;;N;;;;; +1B1BA;NUSHU CHARACTER-1B1BA;Lo;0;L;;;;;N;;;;; +1B1BB;NUSHU CHARACTER-1B1BB;Lo;0;L;;;;;N;;;;; +1B1BC;NUSHU CHARACTER-1B1BC;Lo;0;L;;;;;N;;;;; +1B1BD;NUSHU CHARACTER-1B1BD;Lo;0;L;;;;;N;;;;; +1B1BE;NUSHU CHARACTER-1B1BE;Lo;0;L;;;;;N;;;;; +1B1BF;NUSHU CHARACTER-1B1BF;Lo;0;L;;;;;N;;;;; +1B1C0;NUSHU CHARACTER-1B1C0;Lo;0;L;;;;;N;;;;; +1B1C1;NUSHU CHARACTER-1B1C1;Lo;0;L;;;;;N;;;;; +1B1C2;NUSHU CHARACTER-1B1C2;Lo;0;L;;;;;N;;;;; +1B1C3;NUSHU CHARACTER-1B1C3;Lo;0;L;;;;;N;;;;; +1B1C4;NUSHU CHARACTER-1B1C4;Lo;0;L;;;;;N;;;;; +1B1C5;NUSHU CHARACTER-1B1C5;Lo;0;L;;;;;N;;;;; +1B1C6;NUSHU CHARACTER-1B1C6;Lo;0;L;;;;;N;;;;; +1B1C7;NUSHU CHARACTER-1B1C7;Lo;0;L;;;;;N;;;;; +1B1C8;NUSHU CHARACTER-1B1C8;Lo;0;L;;;;;N;;;;; +1B1C9;NUSHU CHARACTER-1B1C9;Lo;0;L;;;;;N;;;;; +1B1CA;NUSHU CHARACTER-1B1CA;Lo;0;L;;;;;N;;;;; +1B1CB;NUSHU CHARACTER-1B1CB;Lo;0;L;;;;;N;;;;; +1B1CC;NUSHU CHARACTER-1B1CC;Lo;0;L;;;;;N;;;;; +1B1CD;NUSHU CHARACTER-1B1CD;Lo;0;L;;;;;N;;;;; +1B1CE;NUSHU CHARACTER-1B1CE;Lo;0;L;;;;;N;;;;; +1B1CF;NUSHU CHARACTER-1B1CF;Lo;0;L;;;;;N;;;;; +1B1D0;NUSHU CHARACTER-1B1D0;Lo;0;L;;;;;N;;;;; +1B1D1;NUSHU CHARACTER-1B1D1;Lo;0;L;;;;;N;;;;; +1B1D2;NUSHU CHARACTER-1B1D2;Lo;0;L;;;;;N;;;;; +1B1D3;NUSHU CHARACTER-1B1D3;Lo;0;L;;;;;N;;;;; +1B1D4;NUSHU CHARACTER-1B1D4;Lo;0;L;;;;;N;;;;; +1B1D5;NUSHU CHARACTER-1B1D5;Lo;0;L;;;;;N;;;;; +1B1D6;NUSHU CHARACTER-1B1D6;Lo;0;L;;;;;N;;;;; +1B1D7;NUSHU CHARACTER-1B1D7;Lo;0;L;;;;;N;;;;; +1B1D8;NUSHU CHARACTER-1B1D8;Lo;0;L;;;;;N;;;;; +1B1D9;NUSHU CHARACTER-1B1D9;Lo;0;L;;;;;N;;;;; +1B1DA;NUSHU CHARACTER-1B1DA;Lo;0;L;;;;;N;;;;; +1B1DB;NUSHU CHARACTER-1B1DB;Lo;0;L;;;;;N;;;;; +1B1DC;NUSHU CHARACTER-1B1DC;Lo;0;L;;;;;N;;;;; +1B1DD;NUSHU CHARACTER-1B1DD;Lo;0;L;;;;;N;;;;; +1B1DE;NUSHU CHARACTER-1B1DE;Lo;0;L;;;;;N;;;;; +1B1DF;NUSHU CHARACTER-1B1DF;Lo;0;L;;;;;N;;;;; +1B1E0;NUSHU CHARACTER-1B1E0;Lo;0;L;;;;;N;;;;; +1B1E1;NUSHU CHARACTER-1B1E1;Lo;0;L;;;;;N;;;;; +1B1E2;NUSHU CHARACTER-1B1E2;Lo;0;L;;;;;N;;;;; +1B1E3;NUSHU CHARACTER-1B1E3;Lo;0;L;;;;;N;;;;; +1B1E4;NUSHU CHARACTER-1B1E4;Lo;0;L;;;;;N;;;;; +1B1E5;NUSHU CHARACTER-1B1E5;Lo;0;L;;;;;N;;;;; +1B1E6;NUSHU CHARACTER-1B1E6;Lo;0;L;;;;;N;;;;; +1B1E7;NUSHU CHARACTER-1B1E7;Lo;0;L;;;;;N;;;;; +1B1E8;NUSHU CHARACTER-1B1E8;Lo;0;L;;;;;N;;;;; +1B1E9;NUSHU CHARACTER-1B1E9;Lo;0;L;;;;;N;;;;; +1B1EA;NUSHU CHARACTER-1B1EA;Lo;0;L;;;;;N;;;;; +1B1EB;NUSHU CHARACTER-1B1EB;Lo;0;L;;;;;N;;;;; +1B1EC;NUSHU CHARACTER-1B1EC;Lo;0;L;;;;;N;;;;; +1B1ED;NUSHU CHARACTER-1B1ED;Lo;0;L;;;;;N;;;;; +1B1EE;NUSHU CHARACTER-1B1EE;Lo;0;L;;;;;N;;;;; +1B1EF;NUSHU CHARACTER-1B1EF;Lo;0;L;;;;;N;;;;; +1B1F0;NUSHU CHARACTER-1B1F0;Lo;0;L;;;;;N;;;;; +1B1F1;NUSHU CHARACTER-1B1F1;Lo;0;L;;;;;N;;;;; +1B1F2;NUSHU CHARACTER-1B1F2;Lo;0;L;;;;;N;;;;; +1B1F3;NUSHU CHARACTER-1B1F3;Lo;0;L;;;;;N;;;;; +1B1F4;NUSHU CHARACTER-1B1F4;Lo;0;L;;;;;N;;;;; +1B1F5;NUSHU CHARACTER-1B1F5;Lo;0;L;;;;;N;;;;; +1B1F6;NUSHU CHARACTER-1B1F6;Lo;0;L;;;;;N;;;;; +1B1F7;NUSHU CHARACTER-1B1F7;Lo;0;L;;;;;N;;;;; +1B1F8;NUSHU CHARACTER-1B1F8;Lo;0;L;;;;;N;;;;; +1B1F9;NUSHU CHARACTER-1B1F9;Lo;0;L;;;;;N;;;;; +1B1FA;NUSHU CHARACTER-1B1FA;Lo;0;L;;;;;N;;;;; +1B1FB;NUSHU CHARACTER-1B1FB;Lo;0;L;;;;;N;;;;; +1B1FC;NUSHU CHARACTER-1B1FC;Lo;0;L;;;;;N;;;;; +1B1FD;NUSHU CHARACTER-1B1FD;Lo;0;L;;;;;N;;;;; +1B1FE;NUSHU CHARACTER-1B1FE;Lo;0;L;;;;;N;;;;; +1B1FF;NUSHU CHARACTER-1B1FF;Lo;0;L;;;;;N;;;;; +1B200;NUSHU CHARACTER-1B200;Lo;0;L;;;;;N;;;;; +1B201;NUSHU CHARACTER-1B201;Lo;0;L;;;;;N;;;;; +1B202;NUSHU CHARACTER-1B202;Lo;0;L;;;;;N;;;;; +1B203;NUSHU CHARACTER-1B203;Lo;0;L;;;;;N;;;;; +1B204;NUSHU CHARACTER-1B204;Lo;0;L;;;;;N;;;;; +1B205;NUSHU CHARACTER-1B205;Lo;0;L;;;;;N;;;;; +1B206;NUSHU CHARACTER-1B206;Lo;0;L;;;;;N;;;;; +1B207;NUSHU CHARACTER-1B207;Lo;0;L;;;;;N;;;;; +1B208;NUSHU CHARACTER-1B208;Lo;0;L;;;;;N;;;;; +1B209;NUSHU CHARACTER-1B209;Lo;0;L;;;;;N;;;;; +1B20A;NUSHU CHARACTER-1B20A;Lo;0;L;;;;;N;;;;; +1B20B;NUSHU CHARACTER-1B20B;Lo;0;L;;;;;N;;;;; +1B20C;NUSHU CHARACTER-1B20C;Lo;0;L;;;;;N;;;;; +1B20D;NUSHU CHARACTER-1B20D;Lo;0;L;;;;;N;;;;; +1B20E;NUSHU CHARACTER-1B20E;Lo;0;L;;;;;N;;;;; +1B20F;NUSHU CHARACTER-1B20F;Lo;0;L;;;;;N;;;;; +1B210;NUSHU CHARACTER-1B210;Lo;0;L;;;;;N;;;;; +1B211;NUSHU CHARACTER-1B211;Lo;0;L;;;;;N;;;;; +1B212;NUSHU CHARACTER-1B212;Lo;0;L;;;;;N;;;;; +1B213;NUSHU CHARACTER-1B213;Lo;0;L;;;;;N;;;;; +1B214;NUSHU CHARACTER-1B214;Lo;0;L;;;;;N;;;;; +1B215;NUSHU CHARACTER-1B215;Lo;0;L;;;;;N;;;;; +1B216;NUSHU CHARACTER-1B216;Lo;0;L;;;;;N;;;;; +1B217;NUSHU CHARACTER-1B217;Lo;0;L;;;;;N;;;;; +1B218;NUSHU CHARACTER-1B218;Lo;0;L;;;;;N;;;;; +1B219;NUSHU CHARACTER-1B219;Lo;0;L;;;;;N;;;;; +1B21A;NUSHU CHARACTER-1B21A;Lo;0;L;;;;;N;;;;; +1B21B;NUSHU CHARACTER-1B21B;Lo;0;L;;;;;N;;;;; +1B21C;NUSHU CHARACTER-1B21C;Lo;0;L;;;;;N;;;;; +1B21D;NUSHU CHARACTER-1B21D;Lo;0;L;;;;;N;;;;; +1B21E;NUSHU CHARACTER-1B21E;Lo;0;L;;;;;N;;;;; +1B21F;NUSHU CHARACTER-1B21F;Lo;0;L;;;;;N;;;;; +1B220;NUSHU CHARACTER-1B220;Lo;0;L;;;;;N;;;;; +1B221;NUSHU CHARACTER-1B221;Lo;0;L;;;;;N;;;;; +1B222;NUSHU CHARACTER-1B222;Lo;0;L;;;;;N;;;;; +1B223;NUSHU CHARACTER-1B223;Lo;0;L;;;;;N;;;;; +1B224;NUSHU CHARACTER-1B224;Lo;0;L;;;;;N;;;;; +1B225;NUSHU CHARACTER-1B225;Lo;0;L;;;;;N;;;;; +1B226;NUSHU CHARACTER-1B226;Lo;0;L;;;;;N;;;;; +1B227;NUSHU CHARACTER-1B227;Lo;0;L;;;;;N;;;;; +1B228;NUSHU CHARACTER-1B228;Lo;0;L;;;;;N;;;;; +1B229;NUSHU CHARACTER-1B229;Lo;0;L;;;;;N;;;;; +1B22A;NUSHU CHARACTER-1B22A;Lo;0;L;;;;;N;;;;; +1B22B;NUSHU CHARACTER-1B22B;Lo;0;L;;;;;N;;;;; +1B22C;NUSHU CHARACTER-1B22C;Lo;0;L;;;;;N;;;;; +1B22D;NUSHU CHARACTER-1B22D;Lo;0;L;;;;;N;;;;; +1B22E;NUSHU CHARACTER-1B22E;Lo;0;L;;;;;N;;;;; +1B22F;NUSHU CHARACTER-1B22F;Lo;0;L;;;;;N;;;;; +1B230;NUSHU CHARACTER-1B230;Lo;0;L;;;;;N;;;;; +1B231;NUSHU CHARACTER-1B231;Lo;0;L;;;;;N;;;;; +1B232;NUSHU CHARACTER-1B232;Lo;0;L;;;;;N;;;;; +1B233;NUSHU CHARACTER-1B233;Lo;0;L;;;;;N;;;;; +1B234;NUSHU CHARACTER-1B234;Lo;0;L;;;;;N;;;;; +1B235;NUSHU CHARACTER-1B235;Lo;0;L;;;;;N;;;;; +1B236;NUSHU CHARACTER-1B236;Lo;0;L;;;;;N;;;;; +1B237;NUSHU CHARACTER-1B237;Lo;0;L;;;;;N;;;;; +1B238;NUSHU CHARACTER-1B238;Lo;0;L;;;;;N;;;;; +1B239;NUSHU CHARACTER-1B239;Lo;0;L;;;;;N;;;;; +1B23A;NUSHU CHARACTER-1B23A;Lo;0;L;;;;;N;;;;; +1B23B;NUSHU CHARACTER-1B23B;Lo;0;L;;;;;N;;;;; +1B23C;NUSHU CHARACTER-1B23C;Lo;0;L;;;;;N;;;;; +1B23D;NUSHU CHARACTER-1B23D;Lo;0;L;;;;;N;;;;; +1B23E;NUSHU CHARACTER-1B23E;Lo;0;L;;;;;N;;;;; +1B23F;NUSHU CHARACTER-1B23F;Lo;0;L;;;;;N;;;;; +1B240;NUSHU CHARACTER-1B240;Lo;0;L;;;;;N;;;;; +1B241;NUSHU CHARACTER-1B241;Lo;0;L;;;;;N;;;;; +1B242;NUSHU CHARACTER-1B242;Lo;0;L;;;;;N;;;;; +1B243;NUSHU CHARACTER-1B243;Lo;0;L;;;;;N;;;;; +1B244;NUSHU CHARACTER-1B244;Lo;0;L;;;;;N;;;;; +1B245;NUSHU CHARACTER-1B245;Lo;0;L;;;;;N;;;;; +1B246;NUSHU CHARACTER-1B246;Lo;0;L;;;;;N;;;;; +1B247;NUSHU CHARACTER-1B247;Lo;0;L;;;;;N;;;;; +1B248;NUSHU CHARACTER-1B248;Lo;0;L;;;;;N;;;;; +1B249;NUSHU CHARACTER-1B249;Lo;0;L;;;;;N;;;;; +1B24A;NUSHU CHARACTER-1B24A;Lo;0;L;;;;;N;;;;; +1B24B;NUSHU CHARACTER-1B24B;Lo;0;L;;;;;N;;;;; +1B24C;NUSHU CHARACTER-1B24C;Lo;0;L;;;;;N;;;;; +1B24D;NUSHU CHARACTER-1B24D;Lo;0;L;;;;;N;;;;; +1B24E;NUSHU CHARACTER-1B24E;Lo;0;L;;;;;N;;;;; +1B24F;NUSHU CHARACTER-1B24F;Lo;0;L;;;;;N;;;;; +1B250;NUSHU CHARACTER-1B250;Lo;0;L;;;;;N;;;;; +1B251;NUSHU CHARACTER-1B251;Lo;0;L;;;;;N;;;;; +1B252;NUSHU CHARACTER-1B252;Lo;0;L;;;;;N;;;;; +1B253;NUSHU CHARACTER-1B253;Lo;0;L;;;;;N;;;;; +1B254;NUSHU CHARACTER-1B254;Lo;0;L;;;;;N;;;;; +1B255;NUSHU CHARACTER-1B255;Lo;0;L;;;;;N;;;;; +1B256;NUSHU CHARACTER-1B256;Lo;0;L;;;;;N;;;;; +1B257;NUSHU CHARACTER-1B257;Lo;0;L;;;;;N;;;;; +1B258;NUSHU CHARACTER-1B258;Lo;0;L;;;;;N;;;;; +1B259;NUSHU CHARACTER-1B259;Lo;0;L;;;;;N;;;;; +1B25A;NUSHU CHARACTER-1B25A;Lo;0;L;;;;;N;;;;; +1B25B;NUSHU CHARACTER-1B25B;Lo;0;L;;;;;N;;;;; +1B25C;NUSHU CHARACTER-1B25C;Lo;0;L;;;;;N;;;;; +1B25D;NUSHU CHARACTER-1B25D;Lo;0;L;;;;;N;;;;; +1B25E;NUSHU CHARACTER-1B25E;Lo;0;L;;;;;N;;;;; +1B25F;NUSHU CHARACTER-1B25F;Lo;0;L;;;;;N;;;;; +1B260;NUSHU CHARACTER-1B260;Lo;0;L;;;;;N;;;;; +1B261;NUSHU CHARACTER-1B261;Lo;0;L;;;;;N;;;;; +1B262;NUSHU CHARACTER-1B262;Lo;0;L;;;;;N;;;;; +1B263;NUSHU CHARACTER-1B263;Lo;0;L;;;;;N;;;;; +1B264;NUSHU CHARACTER-1B264;Lo;0;L;;;;;N;;;;; +1B265;NUSHU CHARACTER-1B265;Lo;0;L;;;;;N;;;;; +1B266;NUSHU CHARACTER-1B266;Lo;0;L;;;;;N;;;;; +1B267;NUSHU CHARACTER-1B267;Lo;0;L;;;;;N;;;;; +1B268;NUSHU CHARACTER-1B268;Lo;0;L;;;;;N;;;;; +1B269;NUSHU CHARACTER-1B269;Lo;0;L;;;;;N;;;;; +1B26A;NUSHU CHARACTER-1B26A;Lo;0;L;;;;;N;;;;; +1B26B;NUSHU CHARACTER-1B26B;Lo;0;L;;;;;N;;;;; +1B26C;NUSHU CHARACTER-1B26C;Lo;0;L;;;;;N;;;;; +1B26D;NUSHU CHARACTER-1B26D;Lo;0;L;;;;;N;;;;; +1B26E;NUSHU CHARACTER-1B26E;Lo;0;L;;;;;N;;;;; +1B26F;NUSHU CHARACTER-1B26F;Lo;0;L;;;;;N;;;;; +1B270;NUSHU CHARACTER-1B270;Lo;0;L;;;;;N;;;;; +1B271;NUSHU CHARACTER-1B271;Lo;0;L;;;;;N;;;;; +1B272;NUSHU CHARACTER-1B272;Lo;0;L;;;;;N;;;;; +1B273;NUSHU CHARACTER-1B273;Lo;0;L;;;;;N;;;;; +1B274;NUSHU CHARACTER-1B274;Lo;0;L;;;;;N;;;;; +1B275;NUSHU CHARACTER-1B275;Lo;0;L;;;;;N;;;;; +1B276;NUSHU CHARACTER-1B276;Lo;0;L;;;;;N;;;;; +1B277;NUSHU CHARACTER-1B277;Lo;0;L;;;;;N;;;;; +1B278;NUSHU CHARACTER-1B278;Lo;0;L;;;;;N;;;;; +1B279;NUSHU CHARACTER-1B279;Lo;0;L;;;;;N;;;;; +1B27A;NUSHU CHARACTER-1B27A;Lo;0;L;;;;;N;;;;; +1B27B;NUSHU CHARACTER-1B27B;Lo;0;L;;;;;N;;;;; +1B27C;NUSHU CHARACTER-1B27C;Lo;0;L;;;;;N;;;;; +1B27D;NUSHU CHARACTER-1B27D;Lo;0;L;;;;;N;;;;; +1B27E;NUSHU CHARACTER-1B27E;Lo;0;L;;;;;N;;;;; +1B27F;NUSHU CHARACTER-1B27F;Lo;0;L;;;;;N;;;;; +1B280;NUSHU CHARACTER-1B280;Lo;0;L;;;;;N;;;;; +1B281;NUSHU CHARACTER-1B281;Lo;0;L;;;;;N;;;;; +1B282;NUSHU CHARACTER-1B282;Lo;0;L;;;;;N;;;;; +1B283;NUSHU CHARACTER-1B283;Lo;0;L;;;;;N;;;;; +1B284;NUSHU CHARACTER-1B284;Lo;0;L;;;;;N;;;;; +1B285;NUSHU CHARACTER-1B285;Lo;0;L;;;;;N;;;;; +1B286;NUSHU CHARACTER-1B286;Lo;0;L;;;;;N;;;;; +1B287;NUSHU CHARACTER-1B287;Lo;0;L;;;;;N;;;;; +1B288;NUSHU CHARACTER-1B288;Lo;0;L;;;;;N;;;;; +1B289;NUSHU CHARACTER-1B289;Lo;0;L;;;;;N;;;;; +1B28A;NUSHU CHARACTER-1B28A;Lo;0;L;;;;;N;;;;; +1B28B;NUSHU CHARACTER-1B28B;Lo;0;L;;;;;N;;;;; +1B28C;NUSHU CHARACTER-1B28C;Lo;0;L;;;;;N;;;;; +1B28D;NUSHU CHARACTER-1B28D;Lo;0;L;;;;;N;;;;; +1B28E;NUSHU CHARACTER-1B28E;Lo;0;L;;;;;N;;;;; +1B28F;NUSHU CHARACTER-1B28F;Lo;0;L;;;;;N;;;;; +1B290;NUSHU CHARACTER-1B290;Lo;0;L;;;;;N;;;;; +1B291;NUSHU CHARACTER-1B291;Lo;0;L;;;;;N;;;;; +1B292;NUSHU CHARACTER-1B292;Lo;0;L;;;;;N;;;;; +1B293;NUSHU CHARACTER-1B293;Lo;0;L;;;;;N;;;;; +1B294;NUSHU CHARACTER-1B294;Lo;0;L;;;;;N;;;;; +1B295;NUSHU CHARACTER-1B295;Lo;0;L;;;;;N;;;;; +1B296;NUSHU CHARACTER-1B296;Lo;0;L;;;;;N;;;;; +1B297;NUSHU CHARACTER-1B297;Lo;0;L;;;;;N;;;;; +1B298;NUSHU CHARACTER-1B298;Lo;0;L;;;;;N;;;;; +1B299;NUSHU CHARACTER-1B299;Lo;0;L;;;;;N;;;;; +1B29A;NUSHU CHARACTER-1B29A;Lo;0;L;;;;;N;;;;; +1B29B;NUSHU CHARACTER-1B29B;Lo;0;L;;;;;N;;;;; +1B29C;NUSHU CHARACTER-1B29C;Lo;0;L;;;;;N;;;;; +1B29D;NUSHU CHARACTER-1B29D;Lo;0;L;;;;;N;;;;; +1B29E;NUSHU CHARACTER-1B29E;Lo;0;L;;;;;N;;;;; +1B29F;NUSHU CHARACTER-1B29F;Lo;0;L;;;;;N;;;;; +1B2A0;NUSHU CHARACTER-1B2A0;Lo;0;L;;;;;N;;;;; +1B2A1;NUSHU CHARACTER-1B2A1;Lo;0;L;;;;;N;;;;; +1B2A2;NUSHU CHARACTER-1B2A2;Lo;0;L;;;;;N;;;;; +1B2A3;NUSHU CHARACTER-1B2A3;Lo;0;L;;;;;N;;;;; +1B2A4;NUSHU CHARACTER-1B2A4;Lo;0;L;;;;;N;;;;; +1B2A5;NUSHU CHARACTER-1B2A5;Lo;0;L;;;;;N;;;;; +1B2A6;NUSHU CHARACTER-1B2A6;Lo;0;L;;;;;N;;;;; +1B2A7;NUSHU CHARACTER-1B2A7;Lo;0;L;;;;;N;;;;; +1B2A8;NUSHU CHARACTER-1B2A8;Lo;0;L;;;;;N;;;;; +1B2A9;NUSHU CHARACTER-1B2A9;Lo;0;L;;;;;N;;;;; +1B2AA;NUSHU CHARACTER-1B2AA;Lo;0;L;;;;;N;;;;; +1B2AB;NUSHU CHARACTER-1B2AB;Lo;0;L;;;;;N;;;;; +1B2AC;NUSHU CHARACTER-1B2AC;Lo;0;L;;;;;N;;;;; +1B2AD;NUSHU CHARACTER-1B2AD;Lo;0;L;;;;;N;;;;; +1B2AE;NUSHU CHARACTER-1B2AE;Lo;0;L;;;;;N;;;;; +1B2AF;NUSHU CHARACTER-1B2AF;Lo;0;L;;;;;N;;;;; +1B2B0;NUSHU CHARACTER-1B2B0;Lo;0;L;;;;;N;;;;; +1B2B1;NUSHU CHARACTER-1B2B1;Lo;0;L;;;;;N;;;;; +1B2B2;NUSHU CHARACTER-1B2B2;Lo;0;L;;;;;N;;;;; +1B2B3;NUSHU CHARACTER-1B2B3;Lo;0;L;;;;;N;;;;; +1B2B4;NUSHU CHARACTER-1B2B4;Lo;0;L;;;;;N;;;;; +1B2B5;NUSHU CHARACTER-1B2B5;Lo;0;L;;;;;N;;;;; +1B2B6;NUSHU CHARACTER-1B2B6;Lo;0;L;;;;;N;;;;; +1B2B7;NUSHU CHARACTER-1B2B7;Lo;0;L;;;;;N;;;;; +1B2B8;NUSHU CHARACTER-1B2B8;Lo;0;L;;;;;N;;;;; +1B2B9;NUSHU CHARACTER-1B2B9;Lo;0;L;;;;;N;;;;; +1B2BA;NUSHU CHARACTER-1B2BA;Lo;0;L;;;;;N;;;;; +1B2BB;NUSHU CHARACTER-1B2BB;Lo;0;L;;;;;N;;;;; +1B2BC;NUSHU CHARACTER-1B2BC;Lo;0;L;;;;;N;;;;; +1B2BD;NUSHU CHARACTER-1B2BD;Lo;0;L;;;;;N;;;;; +1B2BE;NUSHU CHARACTER-1B2BE;Lo;0;L;;;;;N;;;;; +1B2BF;NUSHU CHARACTER-1B2BF;Lo;0;L;;;;;N;;;;; +1B2C0;NUSHU CHARACTER-1B2C0;Lo;0;L;;;;;N;;;;; +1B2C1;NUSHU CHARACTER-1B2C1;Lo;0;L;;;;;N;;;;; +1B2C2;NUSHU CHARACTER-1B2C2;Lo;0;L;;;;;N;;;;; +1B2C3;NUSHU CHARACTER-1B2C3;Lo;0;L;;;;;N;;;;; +1B2C4;NUSHU CHARACTER-1B2C4;Lo;0;L;;;;;N;;;;; +1B2C5;NUSHU CHARACTER-1B2C5;Lo;0;L;;;;;N;;;;; +1B2C6;NUSHU CHARACTER-1B2C6;Lo;0;L;;;;;N;;;;; +1B2C7;NUSHU CHARACTER-1B2C7;Lo;0;L;;;;;N;;;;; +1B2C8;NUSHU CHARACTER-1B2C8;Lo;0;L;;;;;N;;;;; +1B2C9;NUSHU CHARACTER-1B2C9;Lo;0;L;;;;;N;;;;; +1B2CA;NUSHU CHARACTER-1B2CA;Lo;0;L;;;;;N;;;;; +1B2CB;NUSHU CHARACTER-1B2CB;Lo;0;L;;;;;N;;;;; +1B2CC;NUSHU CHARACTER-1B2CC;Lo;0;L;;;;;N;;;;; +1B2CD;NUSHU CHARACTER-1B2CD;Lo;0;L;;;;;N;;;;; +1B2CE;NUSHU CHARACTER-1B2CE;Lo;0;L;;;;;N;;;;; +1B2CF;NUSHU CHARACTER-1B2CF;Lo;0;L;;;;;N;;;;; +1B2D0;NUSHU CHARACTER-1B2D0;Lo;0;L;;;;;N;;;;; +1B2D1;NUSHU CHARACTER-1B2D1;Lo;0;L;;;;;N;;;;; +1B2D2;NUSHU CHARACTER-1B2D2;Lo;0;L;;;;;N;;;;; +1B2D3;NUSHU CHARACTER-1B2D3;Lo;0;L;;;;;N;;;;; +1B2D4;NUSHU CHARACTER-1B2D4;Lo;0;L;;;;;N;;;;; +1B2D5;NUSHU CHARACTER-1B2D5;Lo;0;L;;;;;N;;;;; +1B2D6;NUSHU CHARACTER-1B2D6;Lo;0;L;;;;;N;;;;; +1B2D7;NUSHU CHARACTER-1B2D7;Lo;0;L;;;;;N;;;;; +1B2D8;NUSHU CHARACTER-1B2D8;Lo;0;L;;;;;N;;;;; +1B2D9;NUSHU CHARACTER-1B2D9;Lo;0;L;;;;;N;;;;; +1B2DA;NUSHU CHARACTER-1B2DA;Lo;0;L;;;;;N;;;;; +1B2DB;NUSHU CHARACTER-1B2DB;Lo;0;L;;;;;N;;;;; +1B2DC;NUSHU CHARACTER-1B2DC;Lo;0;L;;;;;N;;;;; +1B2DD;NUSHU CHARACTER-1B2DD;Lo;0;L;;;;;N;;;;; +1B2DE;NUSHU CHARACTER-1B2DE;Lo;0;L;;;;;N;;;;; +1B2DF;NUSHU CHARACTER-1B2DF;Lo;0;L;;;;;N;;;;; +1B2E0;NUSHU CHARACTER-1B2E0;Lo;0;L;;;;;N;;;;; +1B2E1;NUSHU CHARACTER-1B2E1;Lo;0;L;;;;;N;;;;; +1B2E2;NUSHU CHARACTER-1B2E2;Lo;0;L;;;;;N;;;;; +1B2E3;NUSHU CHARACTER-1B2E3;Lo;0;L;;;;;N;;;;; +1B2E4;NUSHU CHARACTER-1B2E4;Lo;0;L;;;;;N;;;;; +1B2E5;NUSHU CHARACTER-1B2E5;Lo;0;L;;;;;N;;;;; +1B2E6;NUSHU CHARACTER-1B2E6;Lo;0;L;;;;;N;;;;; +1B2E7;NUSHU CHARACTER-1B2E7;Lo;0;L;;;;;N;;;;; +1B2E8;NUSHU CHARACTER-1B2E8;Lo;0;L;;;;;N;;;;; +1B2E9;NUSHU CHARACTER-1B2E9;Lo;0;L;;;;;N;;;;; +1B2EA;NUSHU CHARACTER-1B2EA;Lo;0;L;;;;;N;;;;; +1B2EB;NUSHU CHARACTER-1B2EB;Lo;0;L;;;;;N;;;;; +1B2EC;NUSHU CHARACTER-1B2EC;Lo;0;L;;;;;N;;;;; +1B2ED;NUSHU CHARACTER-1B2ED;Lo;0;L;;;;;N;;;;; +1B2EE;NUSHU CHARACTER-1B2EE;Lo;0;L;;;;;N;;;;; +1B2EF;NUSHU CHARACTER-1B2EF;Lo;0;L;;;;;N;;;;; +1B2F0;NUSHU CHARACTER-1B2F0;Lo;0;L;;;;;N;;;;; +1B2F1;NUSHU CHARACTER-1B2F1;Lo;0;L;;;;;N;;;;; +1B2F2;NUSHU CHARACTER-1B2F2;Lo;0;L;;;;;N;;;;; +1B2F3;NUSHU CHARACTER-1B2F3;Lo;0;L;;;;;N;;;;; +1B2F4;NUSHU CHARACTER-1B2F4;Lo;0;L;;;;;N;;;;; +1B2F5;NUSHU CHARACTER-1B2F5;Lo;0;L;;;;;N;;;;; +1B2F6;NUSHU CHARACTER-1B2F6;Lo;0;L;;;;;N;;;;; +1B2F7;NUSHU CHARACTER-1B2F7;Lo;0;L;;;;;N;;;;; +1B2F8;NUSHU CHARACTER-1B2F8;Lo;0;L;;;;;N;;;;; +1B2F9;NUSHU CHARACTER-1B2F9;Lo;0;L;;;;;N;;;;; +1B2FA;NUSHU CHARACTER-1B2FA;Lo;0;L;;;;;N;;;;; +1B2FB;NUSHU CHARACTER-1B2FB;Lo;0;L;;;;;N;;;;; +1BC00;DUPLOYAN LETTER H;Lo;0;L;;;;;N;;;;; +1BC01;DUPLOYAN LETTER X;Lo;0;L;;;;;N;;;;; +1BC02;DUPLOYAN LETTER P;Lo;0;L;;;;;N;;;;; +1BC03;DUPLOYAN LETTER T;Lo;0;L;;;;;N;;;;; +1BC04;DUPLOYAN LETTER F;Lo;0;L;;;;;N;;;;; +1BC05;DUPLOYAN LETTER K;Lo;0;L;;;;;N;;;;; +1BC06;DUPLOYAN LETTER L;Lo;0;L;;;;;N;;;;; +1BC07;DUPLOYAN LETTER B;Lo;0;L;;;;;N;;;;; +1BC08;DUPLOYAN LETTER D;Lo;0;L;;;;;N;;;;; +1BC09;DUPLOYAN LETTER V;Lo;0;L;;;;;N;;;;; +1BC0A;DUPLOYAN LETTER G;Lo;0;L;;;;;N;;;;; +1BC0B;DUPLOYAN LETTER R;Lo;0;L;;;;;N;;;;; +1BC0C;DUPLOYAN LETTER P N;Lo;0;L;;;;;N;;;;; +1BC0D;DUPLOYAN LETTER D S;Lo;0;L;;;;;N;;;;; +1BC0E;DUPLOYAN LETTER F N;Lo;0;L;;;;;N;;;;; +1BC0F;DUPLOYAN LETTER K M;Lo;0;L;;;;;N;;;;; +1BC10;DUPLOYAN LETTER R S;Lo;0;L;;;;;N;;;;; +1BC11;DUPLOYAN LETTER TH;Lo;0;L;;;;;N;;;;; +1BC12;DUPLOYAN LETTER SLOAN DH;Lo;0;L;;;;;N;;;;; +1BC13;DUPLOYAN LETTER DH;Lo;0;L;;;;;N;;;;; +1BC14;DUPLOYAN LETTER KK;Lo;0;L;;;;;N;;;;; +1BC15;DUPLOYAN LETTER SLOAN J;Lo;0;L;;;;;N;;;;; +1BC16;DUPLOYAN LETTER HL;Lo;0;L;;;;;N;;;;; +1BC17;DUPLOYAN LETTER LH;Lo;0;L;;;;;N;;;;; +1BC18;DUPLOYAN LETTER RH;Lo;0;L;;;;;N;;;;; +1BC19;DUPLOYAN LETTER M;Lo;0;L;;;;;N;;;;; +1BC1A;DUPLOYAN LETTER N;Lo;0;L;;;;;N;;;;; +1BC1B;DUPLOYAN LETTER J;Lo;0;L;;;;;N;;;;; +1BC1C;DUPLOYAN LETTER S;Lo;0;L;;;;;N;;;;; +1BC1D;DUPLOYAN LETTER M N;Lo;0;L;;;;;N;;;;; +1BC1E;DUPLOYAN LETTER N M;Lo;0;L;;;;;N;;;;; +1BC1F;DUPLOYAN LETTER J M;Lo;0;L;;;;;N;;;;; +1BC20;DUPLOYAN LETTER S J;Lo;0;L;;;;;N;;;;; +1BC21;DUPLOYAN LETTER M WITH DOT;Lo;0;L;;;;;N;;;;; +1BC22;DUPLOYAN LETTER N WITH DOT;Lo;0;L;;;;;N;;;;; +1BC23;DUPLOYAN LETTER J WITH DOT;Lo;0;L;;;;;N;;;;; +1BC24;DUPLOYAN LETTER J WITH DOTS INSIDE AND ABOVE;Lo;0;L;;;;;N;;;;; +1BC25;DUPLOYAN LETTER S WITH DOT;Lo;0;L;;;;;N;;;;; +1BC26;DUPLOYAN LETTER S WITH DOT BELOW;Lo;0;L;;;;;N;;;;; +1BC27;DUPLOYAN LETTER M S;Lo;0;L;;;;;N;;;;; +1BC28;DUPLOYAN LETTER N S;Lo;0;L;;;;;N;;;;; +1BC29;DUPLOYAN LETTER J S;Lo;0;L;;;;;N;;;;; +1BC2A;DUPLOYAN LETTER S S;Lo;0;L;;;;;N;;;;; +1BC2B;DUPLOYAN LETTER M N S;Lo;0;L;;;;;N;;;;; +1BC2C;DUPLOYAN LETTER N M S;Lo;0;L;;;;;N;;;;; +1BC2D;DUPLOYAN LETTER J M S;Lo;0;L;;;;;N;;;;; +1BC2E;DUPLOYAN LETTER S J S;Lo;0;L;;;;;N;;;;; +1BC2F;DUPLOYAN LETTER J S WITH DOT;Lo;0;L;;;;;N;;;;; +1BC30;DUPLOYAN LETTER J N;Lo;0;L;;;;;N;;;;; +1BC31;DUPLOYAN LETTER J N S;Lo;0;L;;;;;N;;;;; +1BC32;DUPLOYAN LETTER S T;Lo;0;L;;;;;N;;;;; +1BC33;DUPLOYAN LETTER S T R;Lo;0;L;;;;;N;;;;; +1BC34;DUPLOYAN LETTER S P;Lo;0;L;;;;;N;;;;; +1BC35;DUPLOYAN LETTER S P R;Lo;0;L;;;;;N;;;;; +1BC36;DUPLOYAN LETTER T S;Lo;0;L;;;;;N;;;;; +1BC37;DUPLOYAN LETTER T R S;Lo;0;L;;;;;N;;;;; +1BC38;DUPLOYAN LETTER W;Lo;0;L;;;;;N;;;;; +1BC39;DUPLOYAN LETTER WH;Lo;0;L;;;;;N;;;;; +1BC3A;DUPLOYAN LETTER W R;Lo;0;L;;;;;N;;;;; +1BC3B;DUPLOYAN LETTER S N;Lo;0;L;;;;;N;;;;; +1BC3C;DUPLOYAN LETTER S M;Lo;0;L;;;;;N;;;;; +1BC3D;DUPLOYAN LETTER K R S;Lo;0;L;;;;;N;;;;; +1BC3E;DUPLOYAN LETTER G R S;Lo;0;L;;;;;N;;;;; +1BC3F;DUPLOYAN LETTER S K;Lo;0;L;;;;;N;;;;; +1BC40;DUPLOYAN LETTER S K R;Lo;0;L;;;;;N;;;;; +1BC41;DUPLOYAN LETTER A;Lo;0;L;;;;;N;;;;; +1BC42;DUPLOYAN LETTER SLOAN OW;Lo;0;L;;;;;N;;;;; +1BC43;DUPLOYAN LETTER OA;Lo;0;L;;;;;N;;;;; +1BC44;DUPLOYAN LETTER O;Lo;0;L;;;;;N;;;;; +1BC45;DUPLOYAN LETTER AOU;Lo;0;L;;;;;N;;;;; +1BC46;DUPLOYAN LETTER I;Lo;0;L;;;;;N;;;;; +1BC47;DUPLOYAN LETTER E;Lo;0;L;;;;;N;;;;; +1BC48;DUPLOYAN LETTER IE;Lo;0;L;;;;;N;;;;; +1BC49;DUPLOYAN LETTER SHORT I;Lo;0;L;;;;;N;;;;; +1BC4A;DUPLOYAN LETTER UI;Lo;0;L;;;;;N;;;;; +1BC4B;DUPLOYAN LETTER EE;Lo;0;L;;;;;N;;;;; +1BC4C;DUPLOYAN LETTER SLOAN EH;Lo;0;L;;;;;N;;;;; +1BC4D;DUPLOYAN LETTER ROMANIAN I;Lo;0;L;;;;;N;;;;; +1BC4E;DUPLOYAN LETTER SLOAN EE;Lo;0;L;;;;;N;;;;; +1BC4F;DUPLOYAN LETTER LONG I;Lo;0;L;;;;;N;;;;; +1BC50;DUPLOYAN LETTER YE;Lo;0;L;;;;;N;;;;; +1BC51;DUPLOYAN LETTER U;Lo;0;L;;;;;N;;;;; +1BC52;DUPLOYAN LETTER EU;Lo;0;L;;;;;N;;;;; +1BC53;DUPLOYAN LETTER XW;Lo;0;L;;;;;N;;;;; +1BC54;DUPLOYAN LETTER U N;Lo;0;L;;;;;N;;;;; +1BC55;DUPLOYAN LETTER LONG U;Lo;0;L;;;;;N;;;;; +1BC56;DUPLOYAN LETTER ROMANIAN U;Lo;0;L;;;;;N;;;;; +1BC57;DUPLOYAN LETTER UH;Lo;0;L;;;;;N;;;;; +1BC58;DUPLOYAN LETTER SLOAN U;Lo;0;L;;;;;N;;;;; +1BC59;DUPLOYAN LETTER OOH;Lo;0;L;;;;;N;;;;; +1BC5A;DUPLOYAN LETTER OW;Lo;0;L;;;;;N;;;;; +1BC5B;DUPLOYAN LETTER OU;Lo;0;L;;;;;N;;;;; +1BC5C;DUPLOYAN LETTER WA;Lo;0;L;;;;;N;;;;; +1BC5D;DUPLOYAN LETTER WO;Lo;0;L;;;;;N;;;;; +1BC5E;DUPLOYAN LETTER WI;Lo;0;L;;;;;N;;;;; +1BC5F;DUPLOYAN LETTER WEI;Lo;0;L;;;;;N;;;;; +1BC60;DUPLOYAN LETTER WOW;Lo;0;L;;;;;N;;;;; +1BC61;DUPLOYAN LETTER NASAL U;Lo;0;L;;;;;N;;;;; +1BC62;DUPLOYAN LETTER NASAL O;Lo;0;L;;;;;N;;;;; +1BC63;DUPLOYAN LETTER NASAL I;Lo;0;L;;;;;N;;;;; +1BC64;DUPLOYAN LETTER NASAL A;Lo;0;L;;;;;N;;;;; +1BC65;DUPLOYAN LETTER PERNIN AN;Lo;0;L;;;;;N;;;;; +1BC66;DUPLOYAN LETTER PERNIN AM;Lo;0;L;;;;;N;;;;; +1BC67;DUPLOYAN LETTER SLOAN EN;Lo;0;L;;;;;N;;;;; +1BC68;DUPLOYAN LETTER SLOAN AN;Lo;0;L;;;;;N;;;;; +1BC69;DUPLOYAN LETTER SLOAN ON;Lo;0;L;;;;;N;;;;; +1BC6A;DUPLOYAN LETTER VOCALIC M;Lo;0;L;;;;;N;;;;; +1BC70;DUPLOYAN AFFIX LEFT HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; +1BC71;DUPLOYAN AFFIX MID HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; +1BC72;DUPLOYAN AFFIX RIGHT HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; +1BC73;DUPLOYAN AFFIX LOW VERTICAL SECANT;Lo;0;L;;;;;N;;;;; +1BC74;DUPLOYAN AFFIX MID VERTICAL SECANT;Lo;0;L;;;;;N;;;;; +1BC75;DUPLOYAN AFFIX HIGH VERTICAL SECANT;Lo;0;L;;;;;N;;;;; +1BC76;DUPLOYAN AFFIX ATTACHED SECANT;Lo;0;L;;;;;N;;;;; +1BC77;DUPLOYAN AFFIX ATTACHED LEFT-TO-RIGHT SECANT;Lo;0;L;;;;;N;;;;; +1BC78;DUPLOYAN AFFIX ATTACHED TANGENT;Lo;0;L;;;;;N;;;;; +1BC79;DUPLOYAN AFFIX ATTACHED TAIL;Lo;0;L;;;;;N;;;;; +1BC7A;DUPLOYAN AFFIX ATTACHED E HOOK;Lo;0;L;;;;;N;;;;; +1BC7B;DUPLOYAN AFFIX ATTACHED I HOOK;Lo;0;L;;;;;N;;;;; +1BC7C;DUPLOYAN AFFIX ATTACHED TANGENT HOOK;Lo;0;L;;;;;N;;;;; +1BC80;DUPLOYAN AFFIX HIGH ACUTE;Lo;0;L;;;;;N;;;;; +1BC81;DUPLOYAN AFFIX HIGH TIGHT ACUTE;Lo;0;L;;;;;N;;;;; +1BC82;DUPLOYAN AFFIX HIGH GRAVE;Lo;0;L;;;;;N;;;;; +1BC83;DUPLOYAN AFFIX HIGH LONG GRAVE;Lo;0;L;;;;;N;;;;; +1BC84;DUPLOYAN AFFIX HIGH DOT;Lo;0;L;;;;;N;;;;; +1BC85;DUPLOYAN AFFIX HIGH CIRCLE;Lo;0;L;;;;;N;;;;; +1BC86;DUPLOYAN AFFIX HIGH LINE;Lo;0;L;;;;;N;;;;; +1BC87;DUPLOYAN AFFIX HIGH WAVE;Lo;0;L;;;;;N;;;;; +1BC88;DUPLOYAN AFFIX HIGH VERTICAL;Lo;0;L;;;;;N;;;;; +1BC90;DUPLOYAN AFFIX LOW ACUTE;Lo;0;L;;;;;N;;;;; +1BC91;DUPLOYAN AFFIX LOW TIGHT ACUTE;Lo;0;L;;;;;N;;;;; +1BC92;DUPLOYAN AFFIX LOW GRAVE;Lo;0;L;;;;;N;;;;; +1BC93;DUPLOYAN AFFIX LOW LONG GRAVE;Lo;0;L;;;;;N;;;;; +1BC94;DUPLOYAN AFFIX LOW DOT;Lo;0;L;;;;;N;;;;; +1BC95;DUPLOYAN AFFIX LOW CIRCLE;Lo;0;L;;;;;N;;;;; +1BC96;DUPLOYAN AFFIX LOW LINE;Lo;0;L;;;;;N;;;;; +1BC97;DUPLOYAN AFFIX LOW WAVE;Lo;0;L;;;;;N;;;;; +1BC98;DUPLOYAN AFFIX LOW VERTICAL;Lo;0;L;;;;;N;;;;; +1BC99;DUPLOYAN AFFIX LOW ARROW;Lo;0;L;;;;;N;;;;; +1BC9C;DUPLOYAN SIGN O WITH CROSS;So;0;L;;;;;N;;;;; +1BC9D;DUPLOYAN THICK LETTER SELECTOR;Mn;0;NSM;;;;;N;;;;; +1BC9E;DUPLOYAN DOUBLE MARK;Mn;1;NSM;;;;;N;;;;; +1BC9F;DUPLOYAN PUNCTUATION CHINOOK FULL STOP;Po;0;L;;;;;N;;;;; +1BCA0;SHORTHAND FORMAT LETTER OVERLAP;Cf;0;BN;;;;;N;;;;; +1BCA1;SHORTHAND FORMAT CONTINUING OVERLAP;Cf;0;BN;;;;;N;;;;; +1BCA2;SHORTHAND FORMAT DOWN STEP;Cf;0;BN;;;;;N;;;;; +1BCA3;SHORTHAND FORMAT UP STEP;Cf;0;BN;;;;;N;;;;; +1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;; +1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;; +1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;; +1D003;BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON;So;0;L;;;;;N;;;;; +1D004;BYZANTINE MUSICAL SYMBOL OXEIA DIPLI;So;0;L;;;;;N;;;;; +1D005;BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON;So;0;L;;;;;N;;;;; +1D006;BYZANTINE MUSICAL SYMBOL VAREIA DIPLI;So;0;L;;;;;N;;;;; +1D007;BYZANTINE MUSICAL SYMBOL KATHISTI;So;0;L;;;;;N;;;;; +1D008;BYZANTINE MUSICAL SYMBOL SYRMATIKI;So;0;L;;;;;N;;;;; +1D009;BYZANTINE MUSICAL SYMBOL PARAKLITIKI;So;0;L;;;;;N;;;;; +1D00A;BYZANTINE MUSICAL SYMBOL YPOKRISIS;So;0;L;;;;;N;;;;; +1D00B;BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI;So;0;L;;;;;N;;;;; +1D00C;BYZANTINE MUSICAL SYMBOL KREMASTI;So;0;L;;;;;N;;;;; +1D00D;BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON;So;0;L;;;;;N;;;;; +1D00E;BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON;So;0;L;;;;;N;;;;; +1D00F;BYZANTINE MUSICAL SYMBOL TELEIA;So;0;L;;;;;N;;;;; +1D010;BYZANTINE MUSICAL SYMBOL KENTIMATA;So;0;L;;;;;N;;;;; +1D011;BYZANTINE MUSICAL SYMBOL APOSTROFOS;So;0;L;;;;;N;;;;; +1D012;BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI;So;0;L;;;;;N;;;;; +1D013;BYZANTINE MUSICAL SYMBOL SYNEVMA;So;0;L;;;;;N;;;;; +1D014;BYZANTINE MUSICAL SYMBOL THITA;So;0;L;;;;;N;;;;; +1D015;BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION;So;0;L;;;;;N;;;;; +1D016;BYZANTINE MUSICAL SYMBOL GORGON ARCHAION;So;0;L;;;;;N;;;;; +1D017;BYZANTINE MUSICAL SYMBOL PSILON;So;0;L;;;;;N;;;;; +1D018;BYZANTINE MUSICAL SYMBOL CHAMILON;So;0;L;;;;;N;;;;; +1D019;BYZANTINE MUSICAL SYMBOL VATHY;So;0;L;;;;;N;;;;; +1D01A;BYZANTINE MUSICAL SYMBOL ISON ARCHAION;So;0;L;;;;;N;;;;; +1D01B;BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION;So;0;L;;;;;N;;;;; +1D01C;BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION;So;0;L;;;;;N;;;;; +1D01D;BYZANTINE MUSICAL SYMBOL SAXIMATA;So;0;L;;;;;N;;;;; +1D01E;BYZANTINE MUSICAL SYMBOL PARICHON;So;0;L;;;;;N;;;;; +1D01F;BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA;So;0;L;;;;;N;;;;; +1D020;BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION;So;0;L;;;;;N;;;;; +1D021;BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION;So;0;L;;;;;N;;;;; +1D022;BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION;So;0;L;;;;;N;;;;; +1D023;BYZANTINE MUSICAL SYMBOL APOTHEMA;So;0;L;;;;;N;;;;; +1D024;BYZANTINE MUSICAL SYMBOL KLASMA;So;0;L;;;;;N;;;;; +1D025;BYZANTINE MUSICAL SYMBOL REVMA;So;0;L;;;;;N;;;;; +1D026;BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION;So;0;L;;;;;N;;;;; +1D027;BYZANTINE MUSICAL SYMBOL TINAGMA;So;0;L;;;;;N;;;;; +1D028;BYZANTINE MUSICAL SYMBOL ANATRICHISMA;So;0;L;;;;;N;;;;; +1D029;BYZANTINE MUSICAL SYMBOL SEISMA;So;0;L;;;;;N;;;;; +1D02A;BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION;So;0;L;;;;;N;;;;; +1D02B;BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU;So;0;L;;;;;N;;;;; +1D02C;BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION;So;0;L;;;;;N;;;;; +1D02D;BYZANTINE MUSICAL SYMBOL THEMA;So;0;L;;;;;N;;;;; +1D02E;BYZANTINE MUSICAL SYMBOL LEMOI;So;0;L;;;;;N;;;;; +1D02F;BYZANTINE MUSICAL SYMBOL DYO;So;0;L;;;;;N;;;;; +1D030;BYZANTINE MUSICAL SYMBOL TRIA;So;0;L;;;;;N;;;;; +1D031;BYZANTINE MUSICAL SYMBOL TESSERA;So;0;L;;;;;N;;;;; +1D032;BYZANTINE MUSICAL SYMBOL KRATIMATA;So;0;L;;;;;N;;;;; +1D033;BYZANTINE MUSICAL SYMBOL APESO EXO NEO;So;0;L;;;;;N;;;;; +1D034;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION;So;0;L;;;;;N;;;;; +1D035;BYZANTINE MUSICAL SYMBOL IMIFTHORA;So;0;L;;;;;N;;;;; +1D036;BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION;So;0;L;;;;;N;;;;; +1D037;BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON;So;0;L;;;;;N;;;;; +1D038;BYZANTINE MUSICAL SYMBOL PELASTON;So;0;L;;;;;N;;;;; +1D039;BYZANTINE MUSICAL SYMBOL PSIFISTON;So;0;L;;;;;N;;;;; +1D03A;BYZANTINE MUSICAL SYMBOL KONTEVMA;So;0;L;;;;;N;;;;; +1D03B;BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION;So;0;L;;;;;N;;;;; +1D03C;BYZANTINE MUSICAL SYMBOL RAPISMA;So;0;L;;;;;N;;;;; +1D03D;BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION;So;0;L;;;;;N;;;;; +1D03E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION;So;0;L;;;;;N;;;;; +1D03F;BYZANTINE MUSICAL SYMBOL ICHADIN;So;0;L;;;;;N;;;;; +1D040;BYZANTINE MUSICAL SYMBOL NANA;So;0;L;;;;;N;;;;; +1D041;BYZANTINE MUSICAL SYMBOL PETASMA;So;0;L;;;;;N;;;;; +1D042;BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO;So;0;L;;;;;N;;;;; +1D043;BYZANTINE MUSICAL SYMBOL TROMIKON ALLO;So;0;L;;;;;N;;;;; +1D044;BYZANTINE MUSICAL SYMBOL STRAGGISMATA;So;0;L;;;;;N;;;;; +1D045;BYZANTINE MUSICAL SYMBOL GRONTHISMATA;So;0;L;;;;;N;;;;; +1D046;BYZANTINE MUSICAL SYMBOL ISON NEO;So;0;L;;;;;N;;;;; +1D047;BYZANTINE MUSICAL SYMBOL OLIGON NEO;So;0;L;;;;;N;;;;; +1D048;BYZANTINE MUSICAL SYMBOL OXEIA NEO;So;0;L;;;;;N;;;;; +1D049;BYZANTINE MUSICAL SYMBOL PETASTI;So;0;L;;;;;N;;;;; +1D04A;BYZANTINE MUSICAL SYMBOL KOUFISMA;So;0;L;;;;;N;;;;; +1D04B;BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA;So;0;L;;;;;N;;;;; +1D04C;BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA;So;0;L;;;;;N;;;;; +1D04D;BYZANTINE MUSICAL SYMBOL PELASTON NEO;So;0;L;;;;;N;;;;; +1D04E;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO;So;0;L;;;;;N;;;;; +1D04F;BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO;So;0;L;;;;;N;;;;; +1D050;BYZANTINE MUSICAL SYMBOL YPSILI;So;0;L;;;;;N;;;;; +1D051;BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO;So;0;L;;;;;N;;;;; +1D052;BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO;So;0;L;;;;;N;;;;; +1D053;BYZANTINE MUSICAL SYMBOL YPORROI;So;0;L;;;;;N;;;;; +1D054;BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON;So;0;L;;;;;N;;;;; +1D055;BYZANTINE MUSICAL SYMBOL ELAFRON;So;0;L;;;;;N;;;;; +1D056;BYZANTINE MUSICAL SYMBOL CHAMILI;So;0;L;;;;;N;;;;; +1D057;BYZANTINE MUSICAL SYMBOL MIKRON ISON;So;0;L;;;;;N;;;;; +1D058;BYZANTINE MUSICAL SYMBOL VAREIA NEO;So;0;L;;;;;N;;;;; +1D059;BYZANTINE MUSICAL SYMBOL PIASMA NEO;So;0;L;;;;;N;;;;; +1D05A;BYZANTINE MUSICAL SYMBOL PSIFISTON NEO;So;0;L;;;;;N;;;;; +1D05B;BYZANTINE MUSICAL SYMBOL OMALON;So;0;L;;;;;N;;;;; +1D05C;BYZANTINE MUSICAL SYMBOL ANTIKENOMA;So;0;L;;;;;N;;;;; +1D05D;BYZANTINE MUSICAL SYMBOL LYGISMA;So;0;L;;;;;N;;;;; +1D05E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO;So;0;L;;;;;N;;;;; +1D05F;BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO;So;0;L;;;;;N;;;;; +1D060;BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA;So;0;L;;;;;N;;;;; +1D061;BYZANTINE MUSICAL SYMBOL KYLISMA;So;0;L;;;;;N;;;;; +1D062;BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA;So;0;L;;;;;N;;;;; +1D063;BYZANTINE MUSICAL SYMBOL TROMIKON NEO;So;0;L;;;;;N;;;;; +1D064;BYZANTINE MUSICAL SYMBOL EKSTREPTON;So;0;L;;;;;N;;;;; +1D065;BYZANTINE MUSICAL SYMBOL SYNAGMA NEO;So;0;L;;;;;N;;;;; +1D066;BYZANTINE MUSICAL SYMBOL SYRMA;So;0;L;;;;;N;;;;; +1D067;BYZANTINE MUSICAL SYMBOL CHOREVMA NEO;So;0;L;;;;;N;;;;; +1D068;BYZANTINE MUSICAL SYMBOL EPEGERMA;So;0;L;;;;;N;;;;; +1D069;BYZANTINE MUSICAL SYMBOL SEISMA NEO;So;0;L;;;;;N;;;;; +1D06A;BYZANTINE MUSICAL SYMBOL XIRON KLASMA;So;0;L;;;;;N;;;;; +1D06B;BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON;So;0;L;;;;;N;;;;; +1D06C;BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA;So;0;L;;;;;N;;;;; +1D06D;BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA;So;0;L;;;;;N;;;;; +1D06E;BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA;So;0;L;;;;;N;;;;; +1D06F;BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA;So;0;L;;;;;N;;;;; +1D070;BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA;So;0;L;;;;;N;;;;; +1D071;BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA;So;0;L;;;;;N;;;;; +1D072;BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON;So;0;L;;;;;N;;;;; +1D073;BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON;So;0;L;;;;;N;;;;; +1D074;BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON;So;0;L;;;;;N;;;;; +1D075;BYZANTINE MUSICAL SYMBOL OYRANISMA NEO;So;0;L;;;;;N;;;;; +1D076;BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO;So;0;L;;;;;N;;;;; +1D077;BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO;So;0;L;;;;;N;;;;; +1D078;BYZANTINE MUSICAL SYMBOL THEMA APLOUN;So;0;L;;;;;N;;;;; +1D079;BYZANTINE MUSICAL SYMBOL THES KAI APOTHES;So;0;L;;;;;N;;;;; +1D07A;BYZANTINE MUSICAL SYMBOL KATAVASMA;So;0;L;;;;;N;;;;; +1D07B;BYZANTINE MUSICAL SYMBOL ENDOFONON;So;0;L;;;;;N;;;;; +1D07C;BYZANTINE MUSICAL SYMBOL YFEN KATO;So;0;L;;;;;N;;;;; +1D07D;BYZANTINE MUSICAL SYMBOL YFEN ANO;So;0;L;;;;;N;;;;; +1D07E;BYZANTINE MUSICAL SYMBOL STAVROS;So;0;L;;;;;N;;;;; +1D07F;BYZANTINE MUSICAL SYMBOL KLASMA ANO;So;0;L;;;;;N;;;;; +1D080;BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION;So;0;L;;;;;N;;;;; +1D081;BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION;So;0;L;;;;;N;;;;; +1D082;BYZANTINE MUSICAL SYMBOL KRATIMA ALLO;So;0;L;;;;;N;;;;; +1D083;BYZANTINE MUSICAL SYMBOL KRATIMA NEO;So;0;L;;;;;N;;;;; +1D084;BYZANTINE MUSICAL SYMBOL APODERMA NEO;So;0;L;;;;;N;;;;; +1D085;BYZANTINE MUSICAL SYMBOL APLI;So;0;L;;;;;N;;;;; +1D086;BYZANTINE MUSICAL SYMBOL DIPLI;So;0;L;;;;;N;;;;; +1D087;BYZANTINE MUSICAL SYMBOL TRIPLI;So;0;L;;;;;N;;;;; +1D088;BYZANTINE MUSICAL SYMBOL TETRAPLI;So;0;L;;;;;N;;;;; +1D089;BYZANTINE MUSICAL SYMBOL KORONIS;So;0;L;;;;;N;;;;; +1D08A;BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU;So;0;L;;;;;N;;;;; +1D08B;BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON;So;0;L;;;;;N;;;;; +1D08C;BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON;So;0;L;;;;;N;;;;; +1D08D;BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON;So;0;L;;;;;N;;;;; +1D08E;BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU;So;0;L;;;;;N;;;;; +1D08F;BYZANTINE MUSICAL SYMBOL GORGON NEO ANO;So;0;L;;;;;N;;;;; +1D090;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA;So;0;L;;;;;N;;;;; +1D091;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; +1D092;BYZANTINE MUSICAL SYMBOL DIGORGON;So;0;L;;;;;N;;;;; +1D093;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO;So;0;L;;;;;N;;;;; +1D094;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO;So;0;L;;;;;N;;;;; +1D095;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; +1D096;BYZANTINE MUSICAL SYMBOL TRIGORGON;So;0;L;;;;;N;;;;; +1D097;BYZANTINE MUSICAL SYMBOL ARGON;So;0;L;;;;;N;;;;; +1D098;BYZANTINE MUSICAL SYMBOL IMIDIARGON;So;0;L;;;;;N;;;;; +1D099;BYZANTINE MUSICAL SYMBOL DIARGON;So;0;L;;;;;N;;;;; +1D09A;BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI;So;0;L;;;;;N;;;;; +1D09B;BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI;So;0;L;;;;;N;;;;; +1D09C;BYZANTINE MUSICAL SYMBOL AGOGI ARGI;So;0;L;;;;;N;;;;; +1D09D;BYZANTINE MUSICAL SYMBOL AGOGI METRIA;So;0;L;;;;;N;;;;; +1D09E;BYZANTINE MUSICAL SYMBOL AGOGI MESI;So;0;L;;;;;N;;;;; +1D09F;BYZANTINE MUSICAL SYMBOL AGOGI GORGI;So;0;L;;;;;N;;;;; +1D0A0;BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI;So;0;L;;;;;N;;;;; +1D0A1;BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI;So;0;L;;;;;N;;;;; +1D0A2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS;So;0;L;;;;;N;;;;; +1D0A3;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS;So;0;L;;;;;N;;;;; +1D0A4;BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS;So;0;L;;;;;N;;;;; +1D0A5;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS;So;0;L;;;;;N;;;;; +1D0A6;BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS;So;0;L;;;;;N;;;;; +1D0A7;BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS;So;0;L;;;;;N;;;;; +1D0A8;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS;So;0;L;;;;;N;;;;; +1D0A9;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS;So;0;L;;;;;N;;;;; +1D0AA;BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS;So;0;L;;;;;N;;;;; +1D0AB;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS;So;0;L;;;;;N;;;;; +1D0AC;BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; +1D0AD;BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; +1D0AE;BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS;So;0;L;;;;;N;;;;; +1D0AF;BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS;So;0;L;;;;;N;;;;; +1D0B0;BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS;So;0;L;;;;;N;;;;; +1D0B1;BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS;So;0;L;;;;;N;;;;; +1D0B2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS;So;0;L;;;;;N;;;;; +1D0B3;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS;So;0;L;;;;;N;;;;; +1D0B4;BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN;So;0;L;;;;;N;;;;; +1D0B5;BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN;So;0;L;;;;;N;;;;; +1D0B6;BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU;So;0;L;;;;;N;;;;; +1D0B7;BYZANTINE MUSICAL SYMBOL IMIFONON;So;0;L;;;;;N;;;;; +1D0B8;BYZANTINE MUSICAL SYMBOL IMIFTHORON;So;0;L;;;;;N;;;;; +1D0B9;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU;So;0;L;;;;;N;;;;; +1D0BA;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA;So;0;L;;;;;N;;;;; +1D0BB;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA;So;0;L;;;;;N;;;;; +1D0BC;BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS;So;0;L;;;;;N;;;;; +1D0BD;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI;So;0;L;;;;;N;;;;; +1D0BE;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI;So;0;L;;;;;N;;;;; +1D0BF;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE;So;0;L;;;;;N;;;;; +1D0C0;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO;So;0;L;;;;;N;;;;; +1D0C1;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO;So;0;L;;;;;N;;;;; +1D0C2;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO;So;0;L;;;;;N;;;;; +1D0C3;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS;So;0;L;;;;;N;;;;; +1D0C4;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS;So;0;L;;;;;N;;;;; +1D0C5;BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS;So;0;L;;;;;N;;;;; +1D0C6;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI;So;0;L;;;;;N;;;;; +1D0C7;BYZANTINE MUSICAL SYMBOL FTHORA NENANO;So;0;L;;;;;N;;;;; +1D0C8;BYZANTINE MUSICAL SYMBOL CHROA ZYGOS;So;0;L;;;;;N;;;;; +1D0C9;BYZANTINE MUSICAL SYMBOL CHROA KLITON;So;0;L;;;;;N;;;;; +1D0CA;BYZANTINE MUSICAL SYMBOL CHROA SPATHI;So;0;L;;;;;N;;;;; +1D0CB;BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION;So;0;L;;;;;N;;;;; +1D0CC;BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA;So;0;L;;;;;N;;;;; +1D0CD;BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION;So;0;L;;;;;N;;;;; +1D0CE;BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION;So;0;L;;;;;N;;;;; +1D0CF;BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION;So;0;L;;;;;N;;;;; +1D0D0;BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; +1D0D1;BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; +1D0D2;BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; +1D0D3;BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; +1D0D4;BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; +1D0D5;BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; +1D0D6;BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; +1D0D7;BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; +1D0D8;BYZANTINE MUSICAL SYMBOL GENIKI DIESIS;So;0;L;;;;;N;;;;; +1D0D9;BYZANTINE MUSICAL SYMBOL GENIKI YFESIS;So;0;L;;;;;N;;;;; +1D0DA;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI;So;0;L;;;;;N;;;;; +1D0DB;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI;So;0;L;;;;;N;;;;; +1D0DC;BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI;So;0;L;;;;;N;;;;; +1D0DD;BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS;So;0;L;;;;;N;;;;; +1D0DE;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS;So;0;L;;;;;N;;;;; +1D0DF;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU;So;0;L;;;;;N;;;;; +1D0E0;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU;So;0;L;;;;;N;;;;; +1D0E1;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU;So;0;L;;;;;N;;;;; +1D0E2;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS;So;0;L;;;;;N;;;;; +1D0E3;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU;So;0;L;;;;;N;;;;; +1D0E4;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU;So;0;L;;;;;N;;;;; +1D0E5;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU;So;0;L;;;;;N;;;;; +1D0E6;BYZANTINE MUSICAL SYMBOL DIGRAMMA GG;So;0;L;;;;;N;;;;; +1D0E7;BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU;So;0;L;;;;;N;;;;; +1D0E8;BYZANTINE MUSICAL SYMBOL STIGMA;So;0;L;;;;;N;;;;; +1D0E9;BYZANTINE MUSICAL SYMBOL ARKTIKO PA;So;0;L;;;;;N;;;;; +1D0EA;BYZANTINE MUSICAL SYMBOL ARKTIKO VOU;So;0;L;;;;;N;;;;; +1D0EB;BYZANTINE MUSICAL SYMBOL ARKTIKO GA;So;0;L;;;;;N;;;;; +1D0EC;BYZANTINE MUSICAL SYMBOL ARKTIKO DI;So;0;L;;;;;N;;;;; +1D0ED;BYZANTINE MUSICAL SYMBOL ARKTIKO KE;So;0;L;;;;;N;;;;; +1D0EE;BYZANTINE MUSICAL SYMBOL ARKTIKO ZO;So;0;L;;;;;N;;;;; +1D0EF;BYZANTINE MUSICAL SYMBOL ARKTIKO NI;So;0;L;;;;;N;;;;; +1D0F0;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO;So;0;L;;;;;N;;;;; +1D0F1;BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO;So;0;L;;;;;N;;;;; +1D0F2;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO;So;0;L;;;;;N;;;;; +1D0F3;BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO;So;0;L;;;;;N;;;;; +1D0F4;BYZANTINE MUSICAL SYMBOL KLASMA KATO;So;0;L;;;;;N;;;;; +1D0F5;BYZANTINE MUSICAL SYMBOL GORGON NEO KATO;So;0;L;;;;;N;;;;; +1D100;MUSICAL SYMBOL SINGLE BARLINE;So;0;L;;;;;N;;;;; +1D101;MUSICAL SYMBOL DOUBLE BARLINE;So;0;L;;;;;N;;;;; +1D102;MUSICAL SYMBOL FINAL BARLINE;So;0;L;;;;;N;;;;; +1D103;MUSICAL SYMBOL REVERSE FINAL BARLINE;So;0;L;;;;;N;;;;; +1D104;MUSICAL SYMBOL DASHED BARLINE;So;0;L;;;;;N;;;;; +1D105;MUSICAL SYMBOL SHORT BARLINE;So;0;L;;;;;N;;;;; +1D106;MUSICAL SYMBOL LEFT REPEAT SIGN;So;0;L;;;;;N;;;;; +1D107;MUSICAL SYMBOL RIGHT REPEAT SIGN;So;0;L;;;;;N;;;;; +1D108;MUSICAL SYMBOL REPEAT DOTS;So;0;L;;;;;N;;;;; +1D109;MUSICAL SYMBOL DAL SEGNO;So;0;L;;;;;N;;;;; +1D10A;MUSICAL SYMBOL DA CAPO;So;0;L;;;;;N;;;;; +1D10B;MUSICAL SYMBOL SEGNO;So;0;L;;;;;N;;;;; +1D10C;MUSICAL SYMBOL CODA;So;0;L;;;;;N;;;;; +1D10D;MUSICAL SYMBOL REPEATED FIGURE-1;So;0;L;;;;;N;;;;; +1D10E;MUSICAL SYMBOL REPEATED FIGURE-2;So;0;L;;;;;N;;;;; +1D10F;MUSICAL SYMBOL REPEATED FIGURE-3;So;0;L;;;;;N;;;;; +1D110;MUSICAL SYMBOL FERMATA;So;0;L;;;;;N;;;;; +1D111;MUSICAL SYMBOL FERMATA BELOW;So;0;L;;;;;N;;;;; +1D112;MUSICAL SYMBOL BREATH MARK;So;0;L;;;;;N;;;;; +1D113;MUSICAL SYMBOL CAESURA;So;0;L;;;;;N;;;;; +1D114;MUSICAL SYMBOL BRACE;So;0;L;;;;;N;;;;; +1D115;MUSICAL SYMBOL BRACKET;So;0;L;;;;;N;;;;; +1D116;MUSICAL SYMBOL ONE-LINE STAFF;So;0;L;;;;;N;;;;; +1D117;MUSICAL SYMBOL TWO-LINE STAFF;So;0;L;;;;;N;;;;; +1D118;MUSICAL SYMBOL THREE-LINE STAFF;So;0;L;;;;;N;;;;; +1D119;MUSICAL SYMBOL FOUR-LINE STAFF;So;0;L;;;;;N;;;;; +1D11A;MUSICAL SYMBOL FIVE-LINE STAFF;So;0;L;;;;;N;;;;; +1D11B;MUSICAL SYMBOL SIX-LINE STAFF;So;0;L;;;;;N;;;;; +1D11C;MUSICAL SYMBOL SIX-STRING FRETBOARD;So;0;L;;;;;N;;;;; +1D11D;MUSICAL SYMBOL FOUR-STRING FRETBOARD;So;0;L;;;;;N;;;;; +1D11E;MUSICAL SYMBOL G CLEF;So;0;L;;;;;N;;;;; +1D11F;MUSICAL SYMBOL G CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; +1D120;MUSICAL SYMBOL G CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; +1D121;MUSICAL SYMBOL C CLEF;So;0;L;;;;;N;;;;; +1D122;MUSICAL SYMBOL F CLEF;So;0;L;;;;;N;;;;; +1D123;MUSICAL SYMBOL F CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; +1D124;MUSICAL SYMBOL F CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; +1D125;MUSICAL SYMBOL DRUM CLEF-1;So;0;L;;;;;N;;;;; +1D126;MUSICAL SYMBOL DRUM CLEF-2;So;0;L;;;;;N;;;;; +1D129;MUSICAL SYMBOL MULTIPLE MEASURE REST;So;0;L;;;;;N;;;;; +1D12A;MUSICAL SYMBOL DOUBLE SHARP;So;0;L;;;;;N;;;;; +1D12B;MUSICAL SYMBOL DOUBLE FLAT;So;0;L;;;;;N;;;;; +1D12C;MUSICAL SYMBOL FLAT UP;So;0;L;;;;;N;;;;; +1D12D;MUSICAL SYMBOL FLAT DOWN;So;0;L;;;;;N;;;;; +1D12E;MUSICAL SYMBOL NATURAL UP;So;0;L;;;;;N;;;;; +1D12F;MUSICAL SYMBOL NATURAL DOWN;So;0;L;;;;;N;;;;; +1D130;MUSICAL SYMBOL SHARP UP;So;0;L;;;;;N;;;;; +1D131;MUSICAL SYMBOL SHARP DOWN;So;0;L;;;;;N;;;;; +1D132;MUSICAL SYMBOL QUARTER TONE SHARP;So;0;L;;;;;N;;;;; +1D133;MUSICAL SYMBOL QUARTER TONE FLAT;So;0;L;;;;;N;;;;; +1D134;MUSICAL SYMBOL COMMON TIME;So;0;L;;;;;N;;;;; +1D135;MUSICAL SYMBOL CUT TIME;So;0;L;;;;;N;;;;; +1D136;MUSICAL SYMBOL OTTAVA ALTA;So;0;L;;;;;N;;;;; +1D137;MUSICAL SYMBOL OTTAVA BASSA;So;0;L;;;;;N;;;;; +1D138;MUSICAL SYMBOL QUINDICESIMA ALTA;So;0;L;;;;;N;;;;; +1D139;MUSICAL SYMBOL QUINDICESIMA BASSA;So;0;L;;;;;N;;;;; +1D13A;MUSICAL SYMBOL MULTI REST;So;0;L;;;;;N;;;;; +1D13B;MUSICAL SYMBOL WHOLE REST;So;0;L;;;;;N;;;;; +1D13C;MUSICAL SYMBOL HALF REST;So;0;L;;;;;N;;;;; +1D13D;MUSICAL SYMBOL QUARTER REST;So;0;L;;;;;N;;;;; +1D13E;MUSICAL SYMBOL EIGHTH REST;So;0;L;;;;;N;;;;; +1D13F;MUSICAL SYMBOL SIXTEENTH REST;So;0;L;;;;;N;;;;; +1D140;MUSICAL SYMBOL THIRTY-SECOND REST;So;0;L;;;;;N;;;;; +1D141;MUSICAL SYMBOL SIXTY-FOURTH REST;So;0;L;;;;;N;;;;; +1D142;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST;So;0;L;;;;;N;;;;; +1D143;MUSICAL SYMBOL X NOTEHEAD;So;0;L;;;;;N;;;;; +1D144;MUSICAL SYMBOL PLUS NOTEHEAD;So;0;L;;;;;N;;;;; +1D145;MUSICAL SYMBOL CIRCLE X NOTEHEAD;So;0;L;;;;;N;;;;; +1D146;MUSICAL SYMBOL SQUARE NOTEHEAD WHITE;So;0;L;;;;;N;;;;; +1D147;MUSICAL SYMBOL SQUARE NOTEHEAD BLACK;So;0;L;;;;;N;;;;; +1D148;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE;So;0;L;;;;;N;;;;; +1D149;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK;So;0;L;;;;;N;;;;; +1D14A;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE;So;0;L;;;;;N;;;;; +1D14B;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK;So;0;L;;;;;N;;;;; +1D14C;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE;So;0;L;;;;;N;;;;; +1D14D;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK;So;0;L;;;;;N;;;;; +1D14E;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; +1D14F;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; +1D150;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE;So;0;L;;;;;N;;;;; +1D151;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK;So;0;L;;;;;N;;;;; +1D152;MUSICAL SYMBOL MOON NOTEHEAD WHITE;So;0;L;;;;;N;;;;; +1D153;MUSICAL SYMBOL MOON NOTEHEAD BLACK;So;0;L;;;;;N;;;;; +1D154;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; +1D155;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; +1D156;MUSICAL SYMBOL PARENTHESIS NOTEHEAD;So;0;L;;;;;N;;;;; +1D157;MUSICAL SYMBOL VOID NOTEHEAD;So;0;L;;;;;N;;;;; +1D158;MUSICAL SYMBOL NOTEHEAD BLACK;So;0;L;;;;;N;;;;; +1D159;MUSICAL SYMBOL NULL NOTEHEAD;So;0;L;;;;;N;;;;; +1D15A;MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE;So;0;L;;;;;N;;;;; +1D15B;MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK;So;0;L;;;;;N;;;;; +1D15C;MUSICAL SYMBOL BREVE;So;0;L;;;;;N;;;;; +1D15D;MUSICAL SYMBOL WHOLE NOTE;So;0;L;;;;;N;;;;; +1D15E;MUSICAL SYMBOL HALF NOTE;So;0;L;1D157 1D165;;;;N;;;;; +1D15F;MUSICAL SYMBOL QUARTER NOTE;So;0;L;1D158 1D165;;;;N;;;;; +1D160;MUSICAL SYMBOL EIGHTH NOTE;So;0;L;1D15F 1D16E;;;;N;;;;; +1D161;MUSICAL SYMBOL SIXTEENTH NOTE;So;0;L;1D15F 1D16F;;;;N;;;;; +1D162;MUSICAL SYMBOL THIRTY-SECOND NOTE;So;0;L;1D15F 1D170;;;;N;;;;; +1D163;MUSICAL SYMBOL SIXTY-FOURTH NOTE;So;0;L;1D15F 1D171;;;;N;;;;; +1D164;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE;So;0;L;1D15F 1D172;;;;N;;;;; +1D165;MUSICAL SYMBOL COMBINING STEM;Mc;216;L;;;;;N;;;;; +1D166;MUSICAL SYMBOL COMBINING SPRECHGESANG STEM;Mc;216;L;;;;;N;;;;; +1D167;MUSICAL SYMBOL COMBINING TREMOLO-1;Mn;1;NSM;;;;;N;;;;; +1D168;MUSICAL SYMBOL COMBINING TREMOLO-2;Mn;1;NSM;;;;;N;;;;; +1D169;MUSICAL SYMBOL COMBINING TREMOLO-3;Mn;1;NSM;;;;;N;;;;; +1D16A;MUSICAL SYMBOL FINGERED TREMOLO-1;So;0;L;;;;;N;;;;; +1D16B;MUSICAL SYMBOL FINGERED TREMOLO-2;So;0;L;;;;;N;;;;; +1D16C;MUSICAL SYMBOL FINGERED TREMOLO-3;So;0;L;;;;;N;;;;; +1D16D;MUSICAL SYMBOL COMBINING AUGMENTATION DOT;Mc;226;L;;;;;N;;;;; +1D16E;MUSICAL SYMBOL COMBINING FLAG-1;Mc;216;L;;;;;N;;;;; +1D16F;MUSICAL SYMBOL COMBINING FLAG-2;Mc;216;L;;;;;N;;;;; +1D170;MUSICAL SYMBOL COMBINING FLAG-3;Mc;216;L;;;;;N;;;;; +1D171;MUSICAL SYMBOL COMBINING FLAG-4;Mc;216;L;;;;;N;;;;; +1D172;MUSICAL SYMBOL COMBINING FLAG-5;Mc;216;L;;;;;N;;;;; +1D173;MUSICAL SYMBOL BEGIN BEAM;Cf;0;BN;;;;;N;;;;; +1D174;MUSICAL SYMBOL END BEAM;Cf;0;BN;;;;;N;;;;; +1D175;MUSICAL SYMBOL BEGIN TIE;Cf;0;BN;;;;;N;;;;; +1D176;MUSICAL SYMBOL END TIE;Cf;0;BN;;;;;N;;;;; +1D177;MUSICAL SYMBOL BEGIN SLUR;Cf;0;BN;;;;;N;;;;; +1D178;MUSICAL SYMBOL END SLUR;Cf;0;BN;;;;;N;;;;; +1D179;MUSICAL SYMBOL BEGIN PHRASE;Cf;0;BN;;;;;N;;;;; +1D17A;MUSICAL SYMBOL END PHRASE;Cf;0;BN;;;;;N;;;;; +1D17B;MUSICAL SYMBOL COMBINING ACCENT;Mn;220;NSM;;;;;N;;;;; +1D17C;MUSICAL SYMBOL COMBINING STACCATO;Mn;220;NSM;;;;;N;;;;; +1D17D;MUSICAL SYMBOL COMBINING TENUTO;Mn;220;NSM;;;;;N;;;;; +1D17E;MUSICAL SYMBOL COMBINING STACCATISSIMO;Mn;220;NSM;;;;;N;;;;; +1D17F;MUSICAL SYMBOL COMBINING MARCATO;Mn;220;NSM;;;;;N;;;;; +1D180;MUSICAL SYMBOL COMBINING MARCATO-STACCATO;Mn;220;NSM;;;;;N;;;;; +1D181;MUSICAL SYMBOL COMBINING ACCENT-STACCATO;Mn;220;NSM;;;;;N;;;;; +1D182;MUSICAL SYMBOL COMBINING LOURE;Mn;220;NSM;;;;;N;;;;; +1D183;MUSICAL SYMBOL ARPEGGIATO UP;So;0;L;;;;;N;;;;; +1D184;MUSICAL SYMBOL ARPEGGIATO DOWN;So;0;L;;;;;N;;;;; +1D185;MUSICAL SYMBOL COMBINING DOIT;Mn;230;NSM;;;;;N;;;;; +1D186;MUSICAL SYMBOL COMBINING RIP;Mn;230;NSM;;;;;N;;;;; +1D187;MUSICAL SYMBOL COMBINING FLIP;Mn;230;NSM;;;;;N;;;;; +1D188;MUSICAL SYMBOL COMBINING SMEAR;Mn;230;NSM;;;;;N;;;;; +1D189;MUSICAL SYMBOL COMBINING BEND;Mn;230;NSM;;;;;N;;;;; +1D18A;MUSICAL SYMBOL COMBINING DOUBLE TONGUE;Mn;220;NSM;;;;;N;;;;; +1D18B;MUSICAL SYMBOL COMBINING TRIPLE TONGUE;Mn;220;NSM;;;;;N;;;;; +1D18C;MUSICAL SYMBOL RINFORZANDO;So;0;L;;;;;N;;;;; +1D18D;MUSICAL SYMBOL SUBITO;So;0;L;;;;;N;;;;; +1D18E;MUSICAL SYMBOL Z;So;0;L;;;;;N;;;;; +1D18F;MUSICAL SYMBOL PIANO;So;0;L;;;;;N;;;;; +1D190;MUSICAL SYMBOL MEZZO;So;0;L;;;;;N;;;;; +1D191;MUSICAL SYMBOL FORTE;So;0;L;;;;;N;;;;; +1D192;MUSICAL SYMBOL CRESCENDO;So;0;L;;;;;N;;;;; +1D193;MUSICAL SYMBOL DECRESCENDO;So;0;L;;;;;N;;;;; +1D194;MUSICAL SYMBOL GRACE NOTE SLASH;So;0;L;;;;;N;;;;; +1D195;MUSICAL SYMBOL GRACE NOTE NO SLASH;So;0;L;;;;;N;;;;; +1D196;MUSICAL SYMBOL TR;So;0;L;;;;;N;;;;; +1D197;MUSICAL SYMBOL TURN;So;0;L;;;;;N;;;;; +1D198;MUSICAL SYMBOL INVERTED TURN;So;0;L;;;;;N;;;;; +1D199;MUSICAL SYMBOL TURN SLASH;So;0;L;;;;;N;;;;; +1D19A;MUSICAL SYMBOL TURN UP;So;0;L;;;;;N;;;;; +1D19B;MUSICAL SYMBOL ORNAMENT STROKE-1;So;0;L;;;;;N;;;;; +1D19C;MUSICAL SYMBOL ORNAMENT STROKE-2;So;0;L;;;;;N;;;;; +1D19D;MUSICAL SYMBOL ORNAMENT STROKE-3;So;0;L;;;;;N;;;;; +1D19E;MUSICAL SYMBOL ORNAMENT STROKE-4;So;0;L;;;;;N;;;;; +1D19F;MUSICAL SYMBOL ORNAMENT STROKE-5;So;0;L;;;;;N;;;;; +1D1A0;MUSICAL SYMBOL ORNAMENT STROKE-6;So;0;L;;;;;N;;;;; +1D1A1;MUSICAL SYMBOL ORNAMENT STROKE-7;So;0;L;;;;;N;;;;; +1D1A2;MUSICAL SYMBOL ORNAMENT STROKE-8;So;0;L;;;;;N;;;;; +1D1A3;MUSICAL SYMBOL ORNAMENT STROKE-9;So;0;L;;;;;N;;;;; +1D1A4;MUSICAL SYMBOL ORNAMENT STROKE-10;So;0;L;;;;;N;;;;; +1D1A5;MUSICAL SYMBOL ORNAMENT STROKE-11;So;0;L;;;;;N;;;;; +1D1A6;MUSICAL SYMBOL HAUPTSTIMME;So;0;L;;;;;N;;;;; +1D1A7;MUSICAL SYMBOL NEBENSTIMME;So;0;L;;;;;N;;;;; +1D1A8;MUSICAL SYMBOL END OF STIMME;So;0;L;;;;;N;;;;; +1D1A9;MUSICAL SYMBOL DEGREE SLASH;So;0;L;;;;;N;;;;; +1D1AA;MUSICAL SYMBOL COMBINING DOWN BOW;Mn;230;NSM;;;;;N;;;;; +1D1AB;MUSICAL SYMBOL COMBINING UP BOW;Mn;230;NSM;;;;;N;;;;; +1D1AC;MUSICAL SYMBOL COMBINING HARMONIC;Mn;230;NSM;;;;;N;;;;; +1D1AD;MUSICAL SYMBOL COMBINING SNAP PIZZICATO;Mn;230;NSM;;;;;N;;;;; +1D1AE;MUSICAL SYMBOL PEDAL MARK;So;0;L;;;;;N;;;;; +1D1AF;MUSICAL SYMBOL PEDAL UP MARK;So;0;L;;;;;N;;;;; +1D1B0;MUSICAL SYMBOL HALF PEDAL MARK;So;0;L;;;;;N;;;;; +1D1B1;MUSICAL SYMBOL GLISSANDO UP;So;0;L;;;;;N;;;;; +1D1B2;MUSICAL SYMBOL GLISSANDO DOWN;So;0;L;;;;;N;;;;; +1D1B3;MUSICAL SYMBOL WITH FINGERNAILS;So;0;L;;;;;N;;;;; +1D1B4;MUSICAL SYMBOL DAMP;So;0;L;;;;;N;;;;; +1D1B5;MUSICAL SYMBOL DAMP ALL;So;0;L;;;;;N;;;;; +1D1B6;MUSICAL SYMBOL MAXIMA;So;0;L;;;;;N;;;;; +1D1B7;MUSICAL SYMBOL LONGA;So;0;L;;;;;N;;;;; +1D1B8;MUSICAL SYMBOL BREVIS;So;0;L;;;;;N;;;;; +1D1B9;MUSICAL SYMBOL SEMIBREVIS WHITE;So;0;L;;;;;N;;;;; +1D1BA;MUSICAL SYMBOL SEMIBREVIS BLACK;So;0;L;;;;;N;;;;; +1D1BB;MUSICAL SYMBOL MINIMA;So;0;L;1D1B9 1D165;;;;N;;;;; +1D1BC;MUSICAL SYMBOL MINIMA BLACK;So;0;L;1D1BA 1D165;;;;N;;;;; +1D1BD;MUSICAL SYMBOL SEMIMINIMA WHITE;So;0;L;1D1BB 1D16E;;;;N;;;;; +1D1BE;MUSICAL SYMBOL SEMIMINIMA BLACK;So;0;L;1D1BC 1D16E;;;;N;;;;; +1D1BF;MUSICAL SYMBOL FUSA WHITE;So;0;L;1D1BB 1D16F;;;;N;;;;; +1D1C0;MUSICAL SYMBOL FUSA BLACK;So;0;L;1D1BC 1D16F;;;;N;;;;; +1D1C1;MUSICAL SYMBOL LONGA PERFECTA REST;So;0;L;;;;;N;;;;; +1D1C2;MUSICAL SYMBOL LONGA IMPERFECTA REST;So;0;L;;;;;N;;;;; +1D1C3;MUSICAL SYMBOL BREVIS REST;So;0;L;;;;;N;;;;; +1D1C4;MUSICAL SYMBOL SEMIBREVIS REST;So;0;L;;;;;N;;;;; +1D1C5;MUSICAL SYMBOL MINIMA REST;So;0;L;;;;;N;;;;; +1D1C6;MUSICAL SYMBOL SEMIMINIMA REST;So;0;L;;;;;N;;;;; +1D1C7;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; +1D1C8;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; +1D1C9;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; +1D1CA;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; +1D1CB;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; +1D1CC;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; +1D1CD;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2;So;0;L;;;;;N;;;;; +1D1CE;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3;So;0;L;;;;;N;;;;; +1D1CF;MUSICAL SYMBOL CROIX;So;0;L;;;;;N;;;;; +1D1D0;MUSICAL SYMBOL GREGORIAN C CLEF;So;0;L;;;;;N;;;;; +1D1D1;MUSICAL SYMBOL GREGORIAN F CLEF;So;0;L;;;;;N;;;;; +1D1D2;MUSICAL SYMBOL SQUARE B;So;0;L;;;;;N;;;;; +1D1D3;MUSICAL SYMBOL VIRGA;So;0;L;;;;;N;;;;; +1D1D4;MUSICAL SYMBOL PODATUS;So;0;L;;;;;N;;;;; +1D1D5;MUSICAL SYMBOL CLIVIS;So;0;L;;;;;N;;;;; +1D1D6;MUSICAL SYMBOL SCANDICUS;So;0;L;;;;;N;;;;; +1D1D7;MUSICAL SYMBOL CLIMACUS;So;0;L;;;;;N;;;;; +1D1D8;MUSICAL SYMBOL TORCULUS;So;0;L;;;;;N;;;;; +1D1D9;MUSICAL SYMBOL PORRECTUS;So;0;L;;;;;N;;;;; +1D1DA;MUSICAL SYMBOL PORRECTUS FLEXUS;So;0;L;;;;;N;;;;; +1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;; +1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;; +1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;; +1D1DE;MUSICAL SYMBOL KIEVAN C CLEF;So;0;L;;;;;N;;;;; +1D1DF;MUSICAL SYMBOL KIEVAN END OF PIECE;So;0;L;;;;;N;;;;; +1D1E0;MUSICAL SYMBOL KIEVAN FINAL NOTE;So;0;L;;;;;N;;;;; +1D1E1;MUSICAL SYMBOL KIEVAN RECITATIVE MARK;So;0;L;;;;;N;;;;; +1D1E2;MUSICAL SYMBOL KIEVAN WHOLE NOTE;So;0;L;;;;;N;;;;; +1D1E3;MUSICAL SYMBOL KIEVAN HALF NOTE;So;0;L;;;;;N;;;;; +1D1E4;MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM DOWN;So;0;L;;;;;N;;;;; +1D1E5;MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM UP;So;0;L;;;;;N;;;;; +1D1E6;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM DOWN;So;0;L;;;;;N;;;;; +1D1E7;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM UP;So;0;L;;;;;N;;;;; +1D1E8;MUSICAL SYMBOL KIEVAN FLAT SIGN;So;0;L;;;;;N;;;;; +1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; +1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; +1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;; +1D203;GREEK VOCAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; +1D204;GREEK VOCAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; +1D205;GREEK VOCAL NOTATION SYMBOL-6;So;0;ON;;;;;N;;;;; +1D206;GREEK VOCAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; +1D207;GREEK VOCAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; +1D208;GREEK VOCAL NOTATION SYMBOL-9;So;0;ON;;;;;N;;;;; +1D209;GREEK VOCAL NOTATION SYMBOL-10;So;0;ON;;;;;N;;;;; +1D20A;GREEK VOCAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; +1D20B;GREEK VOCAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; +1D20C;GREEK VOCAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; +1D20D;GREEK VOCAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; +1D20E;GREEK VOCAL NOTATION SYMBOL-15;So;0;ON;;;;;N;;;;; +1D20F;GREEK VOCAL NOTATION SYMBOL-16;So;0;ON;;;;;N;;;;; +1D210;GREEK VOCAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; +1D211;GREEK VOCAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; +1D212;GREEK VOCAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; +1D213;GREEK VOCAL NOTATION SYMBOL-20;So;0;ON;;;;;N;;;;; +1D214;GREEK VOCAL NOTATION SYMBOL-21;So;0;ON;;;;;N;;;;; +1D215;GREEK VOCAL NOTATION SYMBOL-22;So;0;ON;;;;;N;;;;; +1D216;GREEK VOCAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; +1D217;GREEK VOCAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; +1D218;GREEK VOCAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; +1D219;GREEK VOCAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; +1D21A;GREEK VOCAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; +1D21B;GREEK VOCAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; +1D21C;GREEK VOCAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; +1D21D;GREEK INSTRUMENTAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; +1D21E;GREEK INSTRUMENTAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; +1D21F;GREEK INSTRUMENTAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; +1D220;GREEK INSTRUMENTAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; +1D221;GREEK INSTRUMENTAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; +1D222;GREEK INSTRUMENTAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; +1D223;GREEK INSTRUMENTAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; +1D224;GREEK INSTRUMENTAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; +1D225;GREEK INSTRUMENTAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; +1D226;GREEK INSTRUMENTAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; +1D227;GREEK INSTRUMENTAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; +1D228;GREEK INSTRUMENTAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; +1D229;GREEK INSTRUMENTAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; +1D22A;GREEK INSTRUMENTAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; +1D22B;GREEK INSTRUMENTAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; +1D22C;GREEK INSTRUMENTAL NOTATION SYMBOL-25;So;0;ON;;;;;N;;;;; +1D22D;GREEK INSTRUMENTAL NOTATION SYMBOL-26;So;0;ON;;;;;N;;;;; +1D22E;GREEK INSTRUMENTAL NOTATION SYMBOL-27;So;0;ON;;;;;N;;;;; +1D22F;GREEK INSTRUMENTAL NOTATION SYMBOL-29;So;0;ON;;;;;N;;;;; +1D230;GREEK INSTRUMENTAL NOTATION SYMBOL-30;So;0;ON;;;;;N;;;;; +1D231;GREEK INSTRUMENTAL NOTATION SYMBOL-32;So;0;ON;;;;;N;;;;; +1D232;GREEK INSTRUMENTAL NOTATION SYMBOL-36;So;0;ON;;;;;N;;;;; +1D233;GREEK INSTRUMENTAL NOTATION SYMBOL-37;So;0;ON;;;;;N;;;;; +1D234;GREEK INSTRUMENTAL NOTATION SYMBOL-38;So;0;ON;;;;;N;;;;; +1D235;GREEK INSTRUMENTAL NOTATION SYMBOL-39;So;0;ON;;;;;N;;;;; +1D236;GREEK INSTRUMENTAL NOTATION SYMBOL-40;So;0;ON;;;;;N;;;;; +1D237;GREEK INSTRUMENTAL NOTATION SYMBOL-42;So;0;ON;;;;;N;;;;; +1D238;GREEK INSTRUMENTAL NOTATION SYMBOL-43;So;0;ON;;;;;N;;;;; +1D239;GREEK INSTRUMENTAL NOTATION SYMBOL-45;So;0;ON;;;;;N;;;;; +1D23A;GREEK INSTRUMENTAL NOTATION SYMBOL-47;So;0;ON;;;;;N;;;;; +1D23B;GREEK INSTRUMENTAL NOTATION SYMBOL-48;So;0;ON;;;;;N;;;;; +1D23C;GREEK INSTRUMENTAL NOTATION SYMBOL-49;So;0;ON;;;;;N;;;;; +1D23D;GREEK INSTRUMENTAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; +1D23E;GREEK INSTRUMENTAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; +1D23F;GREEK INSTRUMENTAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; +1D240;GREEK INSTRUMENTAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; +1D241;GREEK INSTRUMENTAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; +1D242;COMBINING GREEK MUSICAL TRISEME;Mn;230;NSM;;;;;N;;;;; +1D243;COMBINING GREEK MUSICAL TETRASEME;Mn;230;NSM;;;;;N;;;;; +1D244;COMBINING GREEK MUSICAL PENTASEME;Mn;230;NSM;;;;;N;;;;; +1D245;GREEK MUSICAL LEIMMA;So;0;ON;;;;;N;;;;; +1D300;MONOGRAM FOR EARTH;So;0;ON;;;;;N;;;;; +1D301;DIGRAM FOR HEAVENLY EARTH;So;0;ON;;;;;N;;;;; +1D302;DIGRAM FOR HUMAN EARTH;So;0;ON;;;;;N;;;;; +1D303;DIGRAM FOR EARTHLY HEAVEN;So;0;ON;;;;;N;;;;; +1D304;DIGRAM FOR EARTHLY HUMAN;So;0;ON;;;;;N;;;;; +1D305;DIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; +1D306;TETRAGRAM FOR CENTRE;So;0;ON;;;;;N;;;;; +1D307;TETRAGRAM FOR FULL CIRCLE;So;0;ON;;;;;N;;;;; +1D308;TETRAGRAM FOR MIRED;So;0;ON;;;;;N;;;;; +1D309;TETRAGRAM FOR BARRIER;So;0;ON;;;;;N;;;;; +1D30A;TETRAGRAM FOR KEEPING SMALL;So;0;ON;;;;;N;;;;; +1D30B;TETRAGRAM FOR CONTRARIETY;So;0;ON;;;;;N;;;;; +1D30C;TETRAGRAM FOR ASCENT;So;0;ON;;;;;N;;;;; +1D30D;TETRAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; +1D30E;TETRAGRAM FOR BRANCHING OUT;So;0;ON;;;;;N;;;;; +1D30F;TETRAGRAM FOR DEFECTIVENESS OR DISTORTION;So;0;ON;;;;;N;;;;; +1D310;TETRAGRAM FOR DIVERGENCE;So;0;ON;;;;;N;;;;; +1D311;TETRAGRAM FOR YOUTHFULNESS;So;0;ON;;;;;N;;;;; +1D312;TETRAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; +1D313;TETRAGRAM FOR PENETRATION;So;0;ON;;;;;N;;;;; +1D314;TETRAGRAM FOR REACH;So;0;ON;;;;;N;;;;; +1D315;TETRAGRAM FOR CONTACT;So;0;ON;;;;;N;;;;; +1D316;TETRAGRAM FOR HOLDING BACK;So;0;ON;;;;;N;;;;; +1D317;TETRAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; +1D318;TETRAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; +1D319;TETRAGRAM FOR ADVANCE;So;0;ON;;;;;N;;;;; +1D31A;TETRAGRAM FOR RELEASE;So;0;ON;;;;;N;;;;; +1D31B;TETRAGRAM FOR RESISTANCE;So;0;ON;;;;;N;;;;; +1D31C;TETRAGRAM FOR EASE;So;0;ON;;;;;N;;;;; +1D31D;TETRAGRAM FOR JOY;So;0;ON;;;;;N;;;;; +1D31E;TETRAGRAM FOR CONTENTION;So;0;ON;;;;;N;;;;; +1D31F;TETRAGRAM FOR ENDEAVOUR;So;0;ON;;;;;N;;;;; +1D320;TETRAGRAM FOR DUTIES;So;0;ON;;;;;N;;;;; +1D321;TETRAGRAM FOR CHANGE;So;0;ON;;;;;N;;;;; +1D322;TETRAGRAM FOR DECISIVENESS;So;0;ON;;;;;N;;;;; +1D323;TETRAGRAM FOR BOLD RESOLUTION;So;0;ON;;;;;N;;;;; +1D324;TETRAGRAM FOR PACKING;So;0;ON;;;;;N;;;;; +1D325;TETRAGRAM FOR LEGION;So;0;ON;;;;;N;;;;; +1D326;TETRAGRAM FOR CLOSENESS;So;0;ON;;;;;N;;;;; +1D327;TETRAGRAM FOR KINSHIP;So;0;ON;;;;;N;;;;; +1D328;TETRAGRAM FOR GATHERING;So;0;ON;;;;;N;;;;; +1D329;TETRAGRAM FOR STRENGTH;So;0;ON;;;;;N;;;;; +1D32A;TETRAGRAM FOR PURITY;So;0;ON;;;;;N;;;;; +1D32B;TETRAGRAM FOR FULLNESS;So;0;ON;;;;;N;;;;; +1D32C;TETRAGRAM FOR RESIDENCE;So;0;ON;;;;;N;;;;; +1D32D;TETRAGRAM FOR LAW OR MODEL;So;0;ON;;;;;N;;;;; +1D32E;TETRAGRAM FOR RESPONSE;So;0;ON;;;;;N;;;;; +1D32F;TETRAGRAM FOR GOING TO MEET;So;0;ON;;;;;N;;;;; +1D330;TETRAGRAM FOR ENCOUNTERS;So;0;ON;;;;;N;;;;; +1D331;TETRAGRAM FOR STOVE;So;0;ON;;;;;N;;;;; +1D332;TETRAGRAM FOR GREATNESS;So;0;ON;;;;;N;;;;; +1D333;TETRAGRAM FOR ENLARGEMENT;So;0;ON;;;;;N;;;;; +1D334;TETRAGRAM FOR PATTERN;So;0;ON;;;;;N;;;;; +1D335;TETRAGRAM FOR RITUAL;So;0;ON;;;;;N;;;;; +1D336;TETRAGRAM FOR FLIGHT;So;0;ON;;;;;N;;;;; +1D337;TETRAGRAM FOR VASTNESS OR WASTING;So;0;ON;;;;;N;;;;; +1D338;TETRAGRAM FOR CONSTANCY;So;0;ON;;;;;N;;;;; +1D339;TETRAGRAM FOR MEASURE;So;0;ON;;;;;N;;;;; +1D33A;TETRAGRAM FOR ETERNITY;So;0;ON;;;;;N;;;;; +1D33B;TETRAGRAM FOR UNITY;So;0;ON;;;;;N;;;;; +1D33C;TETRAGRAM FOR DIMINISHMENT;So;0;ON;;;;;N;;;;; +1D33D;TETRAGRAM FOR CLOSED MOUTH;So;0;ON;;;;;N;;;;; +1D33E;TETRAGRAM FOR GUARDEDNESS;So;0;ON;;;;;N;;;;; +1D33F;TETRAGRAM FOR GATHERING IN;So;0;ON;;;;;N;;;;; +1D340;TETRAGRAM FOR MASSING;So;0;ON;;;;;N;;;;; +1D341;TETRAGRAM FOR ACCUMULATION;So;0;ON;;;;;N;;;;; +1D342;TETRAGRAM FOR EMBELLISHMENT;So;0;ON;;;;;N;;;;; +1D343;TETRAGRAM FOR DOUBT;So;0;ON;;;;;N;;;;; +1D344;TETRAGRAM FOR WATCH;So;0;ON;;;;;N;;;;; +1D345;TETRAGRAM FOR SINKING;So;0;ON;;;;;N;;;;; +1D346;TETRAGRAM FOR INNER;So;0;ON;;;;;N;;;;; +1D347;TETRAGRAM FOR DEPARTURE;So;0;ON;;;;;N;;;;; +1D348;TETRAGRAM FOR DARKENING;So;0;ON;;;;;N;;;;; +1D349;TETRAGRAM FOR DIMMING;So;0;ON;;;;;N;;;;; +1D34A;TETRAGRAM FOR EXHAUSTION;So;0;ON;;;;;N;;;;; +1D34B;TETRAGRAM FOR SEVERANCE;So;0;ON;;;;;N;;;;; +1D34C;TETRAGRAM FOR STOPPAGE;So;0;ON;;;;;N;;;;; +1D34D;TETRAGRAM FOR HARDNESS;So;0;ON;;;;;N;;;;; +1D34E;TETRAGRAM FOR COMPLETION;So;0;ON;;;;;N;;;;; +1D34F;TETRAGRAM FOR CLOSURE;So;0;ON;;;;;N;;;;; +1D350;TETRAGRAM FOR FAILURE;So;0;ON;;;;;N;;;;; +1D351;TETRAGRAM FOR AGGRAVATION;So;0;ON;;;;;N;;;;; +1D352;TETRAGRAM FOR COMPLIANCE;So;0;ON;;;;;N;;;;; +1D353;TETRAGRAM FOR ON THE VERGE;So;0;ON;;;;;N;;;;; +1D354;TETRAGRAM FOR DIFFICULTIES;So;0;ON;;;;;N;;;;; +1D355;TETRAGRAM FOR LABOURING;So;0;ON;;;;;N;;;;; +1D356;TETRAGRAM FOR FOSTERING;So;0;ON;;;;;N;;;;; +1D360;COUNTING ROD UNIT DIGIT ONE;No;0;L;;;;1;N;;;;; +1D361;COUNTING ROD UNIT DIGIT TWO;No;0;L;;;;2;N;;;;; +1D362;COUNTING ROD UNIT DIGIT THREE;No;0;L;;;;3;N;;;;; +1D363;COUNTING ROD UNIT DIGIT FOUR;No;0;L;;;;4;N;;;;; +1D364;COUNTING ROD UNIT DIGIT FIVE;No;0;L;;;;5;N;;;;; +1D365;COUNTING ROD UNIT DIGIT SIX;No;0;L;;;;6;N;;;;; +1D366;COUNTING ROD UNIT DIGIT SEVEN;No;0;L;;;;7;N;;;;; +1D367;COUNTING ROD UNIT DIGIT EIGHT;No;0;L;;;;8;N;;;;; +1D368;COUNTING ROD UNIT DIGIT NINE;No;0;L;;;;9;N;;;;; +1D369;COUNTING ROD TENS DIGIT ONE;No;0;L;;;;10;N;;;;; +1D36A;COUNTING ROD TENS DIGIT TWO;No;0;L;;;;20;N;;;;; +1D36B;COUNTING ROD TENS DIGIT THREE;No;0;L;;;;30;N;;;;; +1D36C;COUNTING ROD TENS DIGIT FOUR;No;0;L;;;;40;N;;;;; +1D36D;COUNTING ROD TENS DIGIT FIVE;No;0;L;;;;50;N;;;;; +1D36E;COUNTING ROD TENS DIGIT SIX;No;0;L;;;;60;N;;;;; +1D36F;COUNTING ROD TENS DIGIT SEVEN;No;0;L;;;;70;N;;;;; +1D370;COUNTING ROD TENS DIGIT EIGHT;No;0;L;;;;80;N;;;;; +1D371;COUNTING ROD TENS DIGIT NINE;No;0;L;;;;90;N;;;;; +1D400;MATHEMATICAL BOLD CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D401;MATHEMATICAL BOLD CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D402;MATHEMATICAL BOLD CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D403;MATHEMATICAL BOLD CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D404;MATHEMATICAL BOLD CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D405;MATHEMATICAL BOLD CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D406;MATHEMATICAL BOLD CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D407;MATHEMATICAL BOLD CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D408;MATHEMATICAL BOLD CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D409;MATHEMATICAL BOLD CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D40A;MATHEMATICAL BOLD CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D40B;MATHEMATICAL BOLD CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D40C;MATHEMATICAL BOLD CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D40D;MATHEMATICAL BOLD CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D40E;MATHEMATICAL BOLD CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D40F;MATHEMATICAL BOLD CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D410;MATHEMATICAL BOLD CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D411;MATHEMATICAL BOLD CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D412;MATHEMATICAL BOLD CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D413;MATHEMATICAL BOLD CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D414;MATHEMATICAL BOLD CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D415;MATHEMATICAL BOLD CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D416;MATHEMATICAL BOLD CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D417;MATHEMATICAL BOLD CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D418;MATHEMATICAL BOLD CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D419;MATHEMATICAL BOLD CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D41A;MATHEMATICAL BOLD SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D41B;MATHEMATICAL BOLD SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D41C;MATHEMATICAL BOLD SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D41D;MATHEMATICAL BOLD SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D41E;MATHEMATICAL BOLD SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D41F;MATHEMATICAL BOLD SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D420;MATHEMATICAL BOLD SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D421;MATHEMATICAL BOLD SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D422;MATHEMATICAL BOLD SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D423;MATHEMATICAL BOLD SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D424;MATHEMATICAL BOLD SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D425;MATHEMATICAL BOLD SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D426;MATHEMATICAL BOLD SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D427;MATHEMATICAL BOLD SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D428;MATHEMATICAL BOLD SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D429;MATHEMATICAL BOLD SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D42A;MATHEMATICAL BOLD SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D42B;MATHEMATICAL BOLD SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D42C;MATHEMATICAL BOLD SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D42D;MATHEMATICAL BOLD SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D42E;MATHEMATICAL BOLD SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D42F;MATHEMATICAL BOLD SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D430;MATHEMATICAL BOLD SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D431;MATHEMATICAL BOLD SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D432;MATHEMATICAL BOLD SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D433;MATHEMATICAL BOLD SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D434;MATHEMATICAL ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D435;MATHEMATICAL ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D436;MATHEMATICAL ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D437;MATHEMATICAL ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D438;MATHEMATICAL ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D439;MATHEMATICAL ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D43A;MATHEMATICAL ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D43B;MATHEMATICAL ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D43C;MATHEMATICAL ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D43D;MATHEMATICAL ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D43E;MATHEMATICAL ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D43F;MATHEMATICAL ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D440;MATHEMATICAL ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D441;MATHEMATICAL ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D442;MATHEMATICAL ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D443;MATHEMATICAL ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D444;MATHEMATICAL ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D445;MATHEMATICAL ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D446;MATHEMATICAL ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D447;MATHEMATICAL ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D448;MATHEMATICAL ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D449;MATHEMATICAL ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D44A;MATHEMATICAL ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D44B;MATHEMATICAL ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D44C;MATHEMATICAL ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D44D;MATHEMATICAL ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D44E;MATHEMATICAL ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D44F;MATHEMATICAL ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D450;MATHEMATICAL ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D451;MATHEMATICAL ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D452;MATHEMATICAL ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D453;MATHEMATICAL ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D454;MATHEMATICAL ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D456;MATHEMATICAL ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D457;MATHEMATICAL ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D458;MATHEMATICAL ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D459;MATHEMATICAL ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D45A;MATHEMATICAL ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D45B;MATHEMATICAL ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D45C;MATHEMATICAL ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D45D;MATHEMATICAL ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D45E;MATHEMATICAL ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D45F;MATHEMATICAL ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D460;MATHEMATICAL ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D461;MATHEMATICAL ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D462;MATHEMATICAL ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D463;MATHEMATICAL ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D464;MATHEMATICAL ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D465;MATHEMATICAL ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D466;MATHEMATICAL ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D467;MATHEMATICAL ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D468;MATHEMATICAL BOLD ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D469;MATHEMATICAL BOLD ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D46A;MATHEMATICAL BOLD ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D46B;MATHEMATICAL BOLD ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D46C;MATHEMATICAL BOLD ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D46D;MATHEMATICAL BOLD ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D46E;MATHEMATICAL BOLD ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D46F;MATHEMATICAL BOLD ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D470;MATHEMATICAL BOLD ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D471;MATHEMATICAL BOLD ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D472;MATHEMATICAL BOLD ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D473;MATHEMATICAL BOLD ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D474;MATHEMATICAL BOLD ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D475;MATHEMATICAL BOLD ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D476;MATHEMATICAL BOLD ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D477;MATHEMATICAL BOLD ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D478;MATHEMATICAL BOLD ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D479;MATHEMATICAL BOLD ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D47A;MATHEMATICAL BOLD ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D47B;MATHEMATICAL BOLD ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D47C;MATHEMATICAL BOLD ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D47D;MATHEMATICAL BOLD ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D47E;MATHEMATICAL BOLD ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D47F;MATHEMATICAL BOLD ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D480;MATHEMATICAL BOLD ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D481;MATHEMATICAL BOLD ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D482;MATHEMATICAL BOLD ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D483;MATHEMATICAL BOLD ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D484;MATHEMATICAL BOLD ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D485;MATHEMATICAL BOLD ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D486;MATHEMATICAL BOLD ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D487;MATHEMATICAL BOLD ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D488;MATHEMATICAL BOLD ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D489;MATHEMATICAL BOLD ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D48A;MATHEMATICAL BOLD ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D48B;MATHEMATICAL BOLD ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D48C;MATHEMATICAL BOLD ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D48D;MATHEMATICAL BOLD ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D48E;MATHEMATICAL BOLD ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D48F;MATHEMATICAL BOLD ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D490;MATHEMATICAL BOLD ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D491;MATHEMATICAL BOLD ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D492;MATHEMATICAL BOLD ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D493;MATHEMATICAL BOLD ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D494;MATHEMATICAL BOLD ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D495;MATHEMATICAL BOLD ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D496;MATHEMATICAL BOLD ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D497;MATHEMATICAL BOLD ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D498;MATHEMATICAL BOLD ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D499;MATHEMATICAL BOLD ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D49A;MATHEMATICAL BOLD ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D49B;MATHEMATICAL BOLD ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D49C;MATHEMATICAL SCRIPT CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D49E;MATHEMATICAL SCRIPT CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D49F;MATHEMATICAL SCRIPT CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D4A2;MATHEMATICAL SCRIPT CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D4A5;MATHEMATICAL SCRIPT CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D4A6;MATHEMATICAL SCRIPT CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D4A9;MATHEMATICAL SCRIPT CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D4AA;MATHEMATICAL SCRIPT CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D4AB;MATHEMATICAL SCRIPT CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D4AC;MATHEMATICAL SCRIPT CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D4AE;MATHEMATICAL SCRIPT CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D4AF;MATHEMATICAL SCRIPT CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D4B0;MATHEMATICAL SCRIPT CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D4B1;MATHEMATICAL SCRIPT CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D4B2;MATHEMATICAL SCRIPT CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D4B3;MATHEMATICAL SCRIPT CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D4B4;MATHEMATICAL SCRIPT CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D4B5;MATHEMATICAL SCRIPT CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D4B6;MATHEMATICAL SCRIPT SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D4B7;MATHEMATICAL SCRIPT SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D4B8;MATHEMATICAL SCRIPT SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D4B9;MATHEMATICAL SCRIPT SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D4BB;MATHEMATICAL SCRIPT SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D4BD;MATHEMATICAL SCRIPT SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D4BE;MATHEMATICAL SCRIPT SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D4BF;MATHEMATICAL SCRIPT SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D4C0;MATHEMATICAL SCRIPT SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D4C1;MATHEMATICAL SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D4C2;MATHEMATICAL SCRIPT SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D4C3;MATHEMATICAL SCRIPT SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D4C5;MATHEMATICAL SCRIPT SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D4C6;MATHEMATICAL SCRIPT SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D4C7;MATHEMATICAL SCRIPT SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D4C8;MATHEMATICAL SCRIPT SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D4C9;MATHEMATICAL SCRIPT SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D4CA;MATHEMATICAL SCRIPT SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D4CB;MATHEMATICAL SCRIPT SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D4CC;MATHEMATICAL SCRIPT SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D4CD;MATHEMATICAL SCRIPT SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D4CE;MATHEMATICAL SCRIPT SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D4CF;MATHEMATICAL SCRIPT SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D4D0;MATHEMATICAL BOLD SCRIPT CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D4D1;MATHEMATICAL BOLD SCRIPT CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D4D2;MATHEMATICAL BOLD SCRIPT CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D4D3;MATHEMATICAL BOLD SCRIPT CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D4D4;MATHEMATICAL BOLD SCRIPT CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D4D5;MATHEMATICAL BOLD SCRIPT CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D4D6;MATHEMATICAL BOLD SCRIPT CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D4D7;MATHEMATICAL BOLD SCRIPT CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D4D8;MATHEMATICAL BOLD SCRIPT CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D4D9;MATHEMATICAL BOLD SCRIPT CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D4DA;MATHEMATICAL BOLD SCRIPT CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D4DB;MATHEMATICAL BOLD SCRIPT CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D4DC;MATHEMATICAL BOLD SCRIPT CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D4DD;MATHEMATICAL BOLD SCRIPT CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D4DE;MATHEMATICAL BOLD SCRIPT CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D4DF;MATHEMATICAL BOLD SCRIPT CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D4E0;MATHEMATICAL BOLD SCRIPT CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D4E1;MATHEMATICAL BOLD SCRIPT CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D4E2;MATHEMATICAL BOLD SCRIPT CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D4E3;MATHEMATICAL BOLD SCRIPT CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D4E4;MATHEMATICAL BOLD SCRIPT CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D4E5;MATHEMATICAL BOLD SCRIPT CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D4E6;MATHEMATICAL BOLD SCRIPT CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D4E7;MATHEMATICAL BOLD SCRIPT CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D4E8;MATHEMATICAL BOLD SCRIPT CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D4E9;MATHEMATICAL BOLD SCRIPT CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D4EA;MATHEMATICAL BOLD SCRIPT SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D4EB;MATHEMATICAL BOLD SCRIPT SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D4EC;MATHEMATICAL BOLD SCRIPT SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D4ED;MATHEMATICAL BOLD SCRIPT SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D4EE;MATHEMATICAL BOLD SCRIPT SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D4EF;MATHEMATICAL BOLD SCRIPT SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D4F0;MATHEMATICAL BOLD SCRIPT SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D4F1;MATHEMATICAL BOLD SCRIPT SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D4F2;MATHEMATICAL BOLD SCRIPT SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D4F3;MATHEMATICAL BOLD SCRIPT SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D4F4;MATHEMATICAL BOLD SCRIPT SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D4F5;MATHEMATICAL BOLD SCRIPT SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D4F6;MATHEMATICAL BOLD SCRIPT SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D4F7;MATHEMATICAL BOLD SCRIPT SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D4F8;MATHEMATICAL BOLD SCRIPT SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D4F9;MATHEMATICAL BOLD SCRIPT SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D4FA;MATHEMATICAL BOLD SCRIPT SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D4FB;MATHEMATICAL BOLD SCRIPT SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D4FC;MATHEMATICAL BOLD SCRIPT SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D4FD;MATHEMATICAL BOLD SCRIPT SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D4FE;MATHEMATICAL BOLD SCRIPT SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D4FF;MATHEMATICAL BOLD SCRIPT SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D500;MATHEMATICAL BOLD SCRIPT SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D501;MATHEMATICAL BOLD SCRIPT SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D502;MATHEMATICAL BOLD SCRIPT SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D503;MATHEMATICAL BOLD SCRIPT SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D504;MATHEMATICAL FRAKTUR CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D505;MATHEMATICAL FRAKTUR CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D507;MATHEMATICAL FRAKTUR CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D508;MATHEMATICAL FRAKTUR CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D509;MATHEMATICAL FRAKTUR CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D50A;MATHEMATICAL FRAKTUR CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D50D;MATHEMATICAL FRAKTUR CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D50E;MATHEMATICAL FRAKTUR CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D50F;MATHEMATICAL FRAKTUR CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D510;MATHEMATICAL FRAKTUR CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D511;MATHEMATICAL FRAKTUR CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D512;MATHEMATICAL FRAKTUR CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D513;MATHEMATICAL FRAKTUR CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D514;MATHEMATICAL FRAKTUR CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D516;MATHEMATICAL FRAKTUR CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D517;MATHEMATICAL FRAKTUR CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D518;MATHEMATICAL FRAKTUR CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D519;MATHEMATICAL FRAKTUR CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D51A;MATHEMATICAL FRAKTUR CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D51B;MATHEMATICAL FRAKTUR CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D51C;MATHEMATICAL FRAKTUR CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D51E;MATHEMATICAL FRAKTUR SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D51F;MATHEMATICAL FRAKTUR SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D520;MATHEMATICAL FRAKTUR SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D521;MATHEMATICAL FRAKTUR SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D522;MATHEMATICAL FRAKTUR SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D523;MATHEMATICAL FRAKTUR SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D524;MATHEMATICAL FRAKTUR SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D525;MATHEMATICAL FRAKTUR SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D526;MATHEMATICAL FRAKTUR SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D527;MATHEMATICAL FRAKTUR SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D528;MATHEMATICAL FRAKTUR SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D529;MATHEMATICAL FRAKTUR SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D52A;MATHEMATICAL FRAKTUR SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D52B;MATHEMATICAL FRAKTUR SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D52C;MATHEMATICAL FRAKTUR SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D52D;MATHEMATICAL FRAKTUR SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D52E;MATHEMATICAL FRAKTUR SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D52F;MATHEMATICAL FRAKTUR SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D530;MATHEMATICAL FRAKTUR SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D531;MATHEMATICAL FRAKTUR SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D532;MATHEMATICAL FRAKTUR SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D533;MATHEMATICAL FRAKTUR SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D534;MATHEMATICAL FRAKTUR SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D535;MATHEMATICAL FRAKTUR SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D536;MATHEMATICAL FRAKTUR SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D537;MATHEMATICAL FRAKTUR SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D538;MATHEMATICAL DOUBLE-STRUCK CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D539;MATHEMATICAL DOUBLE-STRUCK CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D53B;MATHEMATICAL DOUBLE-STRUCK CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D53C;MATHEMATICAL DOUBLE-STRUCK CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D53D;MATHEMATICAL DOUBLE-STRUCK CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D53E;MATHEMATICAL DOUBLE-STRUCK CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D540;MATHEMATICAL DOUBLE-STRUCK CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D541;MATHEMATICAL DOUBLE-STRUCK CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D542;MATHEMATICAL DOUBLE-STRUCK CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D543;MATHEMATICAL DOUBLE-STRUCK CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D544;MATHEMATICAL DOUBLE-STRUCK CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D546;MATHEMATICAL DOUBLE-STRUCK CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D54A;MATHEMATICAL DOUBLE-STRUCK CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D54B;MATHEMATICAL DOUBLE-STRUCK CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D54C;MATHEMATICAL DOUBLE-STRUCK CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D54D;MATHEMATICAL DOUBLE-STRUCK CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D54E;MATHEMATICAL DOUBLE-STRUCK CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D54F;MATHEMATICAL DOUBLE-STRUCK CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D550;MATHEMATICAL DOUBLE-STRUCK CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D552;MATHEMATICAL DOUBLE-STRUCK SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D553;MATHEMATICAL DOUBLE-STRUCK SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D554;MATHEMATICAL DOUBLE-STRUCK SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D555;MATHEMATICAL DOUBLE-STRUCK SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D556;MATHEMATICAL DOUBLE-STRUCK SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D557;MATHEMATICAL DOUBLE-STRUCK SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D558;MATHEMATICAL DOUBLE-STRUCK SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D559;MATHEMATICAL DOUBLE-STRUCK SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D55A;MATHEMATICAL DOUBLE-STRUCK SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D55B;MATHEMATICAL DOUBLE-STRUCK SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D55C;MATHEMATICAL DOUBLE-STRUCK SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D55D;MATHEMATICAL DOUBLE-STRUCK SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D55E;MATHEMATICAL DOUBLE-STRUCK SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D55F;MATHEMATICAL DOUBLE-STRUCK SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D560;MATHEMATICAL DOUBLE-STRUCK SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D561;MATHEMATICAL DOUBLE-STRUCK SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D562;MATHEMATICAL DOUBLE-STRUCK SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D563;MATHEMATICAL DOUBLE-STRUCK SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D564;MATHEMATICAL DOUBLE-STRUCK SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D565;MATHEMATICAL DOUBLE-STRUCK SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D566;MATHEMATICAL DOUBLE-STRUCK SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D567;MATHEMATICAL DOUBLE-STRUCK SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D568;MATHEMATICAL DOUBLE-STRUCK SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D569;MATHEMATICAL DOUBLE-STRUCK SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D56A;MATHEMATICAL DOUBLE-STRUCK SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D56B;MATHEMATICAL DOUBLE-STRUCK SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D56C;MATHEMATICAL BOLD FRAKTUR CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D56D;MATHEMATICAL BOLD FRAKTUR CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D56E;MATHEMATICAL BOLD FRAKTUR CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D56F;MATHEMATICAL BOLD FRAKTUR CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D570;MATHEMATICAL BOLD FRAKTUR CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D571;MATHEMATICAL BOLD FRAKTUR CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D572;MATHEMATICAL BOLD FRAKTUR CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D573;MATHEMATICAL BOLD FRAKTUR CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D574;MATHEMATICAL BOLD FRAKTUR CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D575;MATHEMATICAL BOLD FRAKTUR CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D576;MATHEMATICAL BOLD FRAKTUR CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D577;MATHEMATICAL BOLD FRAKTUR CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D578;MATHEMATICAL BOLD FRAKTUR CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D579;MATHEMATICAL BOLD FRAKTUR CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D57A;MATHEMATICAL BOLD FRAKTUR CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D57B;MATHEMATICAL BOLD FRAKTUR CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D57C;MATHEMATICAL BOLD FRAKTUR CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D57D;MATHEMATICAL BOLD FRAKTUR CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D57E;MATHEMATICAL BOLD FRAKTUR CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D57F;MATHEMATICAL BOLD FRAKTUR CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D580;MATHEMATICAL BOLD FRAKTUR CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D581;MATHEMATICAL BOLD FRAKTUR CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D582;MATHEMATICAL BOLD FRAKTUR CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D583;MATHEMATICAL BOLD FRAKTUR CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D584;MATHEMATICAL BOLD FRAKTUR CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D585;MATHEMATICAL BOLD FRAKTUR CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D586;MATHEMATICAL BOLD FRAKTUR SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D587;MATHEMATICAL BOLD FRAKTUR SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D588;MATHEMATICAL BOLD FRAKTUR SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D589;MATHEMATICAL BOLD FRAKTUR SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D58A;MATHEMATICAL BOLD FRAKTUR SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D58B;MATHEMATICAL BOLD FRAKTUR SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D58C;MATHEMATICAL BOLD FRAKTUR SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D58D;MATHEMATICAL BOLD FRAKTUR SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D58E;MATHEMATICAL BOLD FRAKTUR SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D58F;MATHEMATICAL BOLD FRAKTUR SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D590;MATHEMATICAL BOLD FRAKTUR SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D591;MATHEMATICAL BOLD FRAKTUR SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D592;MATHEMATICAL BOLD FRAKTUR SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D593;MATHEMATICAL BOLD FRAKTUR SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D594;MATHEMATICAL BOLD FRAKTUR SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D595;MATHEMATICAL BOLD FRAKTUR SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D596;MATHEMATICAL BOLD FRAKTUR SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D597;MATHEMATICAL BOLD FRAKTUR SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D598;MATHEMATICAL BOLD FRAKTUR SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D599;MATHEMATICAL BOLD FRAKTUR SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D59A;MATHEMATICAL BOLD FRAKTUR SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D59B;MATHEMATICAL BOLD FRAKTUR SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D59C;MATHEMATICAL BOLD FRAKTUR SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D59D;MATHEMATICAL BOLD FRAKTUR SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D59E;MATHEMATICAL BOLD FRAKTUR SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D59F;MATHEMATICAL BOLD FRAKTUR SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D5A0;MATHEMATICAL SANS-SERIF CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D5A1;MATHEMATICAL SANS-SERIF CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D5A2;MATHEMATICAL SANS-SERIF CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D5A3;MATHEMATICAL SANS-SERIF CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D5A4;MATHEMATICAL SANS-SERIF CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D5A5;MATHEMATICAL SANS-SERIF CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D5A6;MATHEMATICAL SANS-SERIF CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D5A7;MATHEMATICAL SANS-SERIF CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D5A8;MATHEMATICAL SANS-SERIF CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D5A9;MATHEMATICAL SANS-SERIF CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D5AA;MATHEMATICAL SANS-SERIF CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D5AB;MATHEMATICAL SANS-SERIF CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D5AC;MATHEMATICAL SANS-SERIF CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D5AD;MATHEMATICAL SANS-SERIF CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D5AE;MATHEMATICAL SANS-SERIF CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D5AF;MATHEMATICAL SANS-SERIF CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D5B0;MATHEMATICAL SANS-SERIF CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D5B1;MATHEMATICAL SANS-SERIF CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D5B2;MATHEMATICAL SANS-SERIF CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D5B3;MATHEMATICAL SANS-SERIF CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D5B4;MATHEMATICAL SANS-SERIF CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D5B5;MATHEMATICAL SANS-SERIF CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D5B6;MATHEMATICAL SANS-SERIF CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D5B7;MATHEMATICAL SANS-SERIF CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D5B8;MATHEMATICAL SANS-SERIF CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D5B9;MATHEMATICAL SANS-SERIF CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D5BA;MATHEMATICAL SANS-SERIF SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D5BB;MATHEMATICAL SANS-SERIF SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D5BC;MATHEMATICAL SANS-SERIF SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D5BD;MATHEMATICAL SANS-SERIF SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D5BE;MATHEMATICAL SANS-SERIF SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D5BF;MATHEMATICAL SANS-SERIF SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D5C0;MATHEMATICAL SANS-SERIF SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D5C1;MATHEMATICAL SANS-SERIF SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D5C2;MATHEMATICAL SANS-SERIF SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D5C3;MATHEMATICAL SANS-SERIF SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D5C4;MATHEMATICAL SANS-SERIF SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D5C5;MATHEMATICAL SANS-SERIF SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D5C6;MATHEMATICAL SANS-SERIF SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D5C7;MATHEMATICAL SANS-SERIF SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D5C8;MATHEMATICAL SANS-SERIF SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D5C9;MATHEMATICAL SANS-SERIF SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D5CA;MATHEMATICAL SANS-SERIF SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D5CB;MATHEMATICAL SANS-SERIF SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D5CC;MATHEMATICAL SANS-SERIF SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D5CD;MATHEMATICAL SANS-SERIF SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D5CE;MATHEMATICAL SANS-SERIF SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D5CF;MATHEMATICAL SANS-SERIF SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D5D0;MATHEMATICAL SANS-SERIF SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D5D1;MATHEMATICAL SANS-SERIF SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D5D2;MATHEMATICAL SANS-SERIF SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D5D3;MATHEMATICAL SANS-SERIF SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D5D4;MATHEMATICAL SANS-SERIF BOLD CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D5D5;MATHEMATICAL SANS-SERIF BOLD CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D5D6;MATHEMATICAL SANS-SERIF BOLD CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D5D7;MATHEMATICAL SANS-SERIF BOLD CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D5D8;MATHEMATICAL SANS-SERIF BOLD CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D5D9;MATHEMATICAL SANS-SERIF BOLD CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D5DA;MATHEMATICAL SANS-SERIF BOLD CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D5DB;MATHEMATICAL SANS-SERIF BOLD CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D5DC;MATHEMATICAL SANS-SERIF BOLD CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D5DD;MATHEMATICAL SANS-SERIF BOLD CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D5DE;MATHEMATICAL SANS-SERIF BOLD CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D5DF;MATHEMATICAL SANS-SERIF BOLD CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D5E0;MATHEMATICAL SANS-SERIF BOLD CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D5E1;MATHEMATICAL SANS-SERIF BOLD CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D5E2;MATHEMATICAL SANS-SERIF BOLD CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D5E3;MATHEMATICAL SANS-SERIF BOLD CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D5E4;MATHEMATICAL SANS-SERIF BOLD CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D5E5;MATHEMATICAL SANS-SERIF BOLD CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D5E6;MATHEMATICAL SANS-SERIF BOLD CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D5E7;MATHEMATICAL SANS-SERIF BOLD CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D5E8;MATHEMATICAL SANS-SERIF BOLD CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D5E9;MATHEMATICAL SANS-SERIF BOLD CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D5EA;MATHEMATICAL SANS-SERIF BOLD CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D5EB;MATHEMATICAL SANS-SERIF BOLD CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D5EC;MATHEMATICAL SANS-SERIF BOLD CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D5ED;MATHEMATICAL SANS-SERIF BOLD CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D5EE;MATHEMATICAL SANS-SERIF BOLD SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D5EF;MATHEMATICAL SANS-SERIF BOLD SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D5F0;MATHEMATICAL SANS-SERIF BOLD SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D5F1;MATHEMATICAL SANS-SERIF BOLD SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D5F2;MATHEMATICAL SANS-SERIF BOLD SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D5F3;MATHEMATICAL SANS-SERIF BOLD SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D5F4;MATHEMATICAL SANS-SERIF BOLD SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D5F5;MATHEMATICAL SANS-SERIF BOLD SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D5F6;MATHEMATICAL SANS-SERIF BOLD SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D5F7;MATHEMATICAL SANS-SERIF BOLD SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D5F8;MATHEMATICAL SANS-SERIF BOLD SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D5F9;MATHEMATICAL SANS-SERIF BOLD SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D5FA;MATHEMATICAL SANS-SERIF BOLD SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D5FB;MATHEMATICAL SANS-SERIF BOLD SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D5FC;MATHEMATICAL SANS-SERIF BOLD SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D5FD;MATHEMATICAL SANS-SERIF BOLD SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D5FE;MATHEMATICAL SANS-SERIF BOLD SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D5FF;MATHEMATICAL SANS-SERIF BOLD SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D600;MATHEMATICAL SANS-SERIF BOLD SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D601;MATHEMATICAL SANS-SERIF BOLD SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D602;MATHEMATICAL SANS-SERIF BOLD SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D603;MATHEMATICAL SANS-SERIF BOLD SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D604;MATHEMATICAL SANS-SERIF BOLD SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D605;MATHEMATICAL SANS-SERIF BOLD SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D606;MATHEMATICAL SANS-SERIF BOLD SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D607;MATHEMATICAL SANS-SERIF BOLD SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D608;MATHEMATICAL SANS-SERIF ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D609;MATHEMATICAL SANS-SERIF ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D60A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D60B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D60C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D60D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D60E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D60F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D610;MATHEMATICAL SANS-SERIF ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D611;MATHEMATICAL SANS-SERIF ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D612;MATHEMATICAL SANS-SERIF ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D613;MATHEMATICAL SANS-SERIF ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D614;MATHEMATICAL SANS-SERIF ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D615;MATHEMATICAL SANS-SERIF ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D616;MATHEMATICAL SANS-SERIF ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D617;MATHEMATICAL SANS-SERIF ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D618;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D619;MATHEMATICAL SANS-SERIF ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D61A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D61B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D61C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D61D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D61E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D61F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D620;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D621;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D622;MATHEMATICAL SANS-SERIF ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D623;MATHEMATICAL SANS-SERIF ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D624;MATHEMATICAL SANS-SERIF ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D625;MATHEMATICAL SANS-SERIF ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D626;MATHEMATICAL SANS-SERIF ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D627;MATHEMATICAL SANS-SERIF ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D628;MATHEMATICAL SANS-SERIF ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D629;MATHEMATICAL SANS-SERIF ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D62A;MATHEMATICAL SANS-SERIF ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D62B;MATHEMATICAL SANS-SERIF ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D62C;MATHEMATICAL SANS-SERIF ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D62D;MATHEMATICAL SANS-SERIF ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D62E;MATHEMATICAL SANS-SERIF ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D62F;MATHEMATICAL SANS-SERIF ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D630;MATHEMATICAL SANS-SERIF ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D631;MATHEMATICAL SANS-SERIF ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D632;MATHEMATICAL SANS-SERIF ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D633;MATHEMATICAL SANS-SERIF ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D634;MATHEMATICAL SANS-SERIF ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D635;MATHEMATICAL SANS-SERIF ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D636;MATHEMATICAL SANS-SERIF ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D637;MATHEMATICAL SANS-SERIF ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D638;MATHEMATICAL SANS-SERIF ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D639;MATHEMATICAL SANS-SERIF ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D63A;MATHEMATICAL SANS-SERIF ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D63B;MATHEMATICAL SANS-SERIF ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D63C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D63D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D63E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D63F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D640;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D641;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D642;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D643;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D644;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D645;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D646;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D647;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D648;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D649;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D64A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D64B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D64C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D64D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D64E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D64F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D650;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D651;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D652;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D653;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D654;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D655;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D656;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D657;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D658;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D659;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D65A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D65B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D65C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D65D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D65E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D65F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D660;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D661;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D662;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D663;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D664;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D665;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D666;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D667;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D668;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D669;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D66A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D66B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D66C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D66D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D66E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D66F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D670;MATHEMATICAL MONOSPACE CAPITAL A;Lu;0;L;<font> 0041;;;;N;;;;; +1D671;MATHEMATICAL MONOSPACE CAPITAL B;Lu;0;L;<font> 0042;;;;N;;;;; +1D672;MATHEMATICAL MONOSPACE CAPITAL C;Lu;0;L;<font> 0043;;;;N;;;;; +1D673;MATHEMATICAL MONOSPACE CAPITAL D;Lu;0;L;<font> 0044;;;;N;;;;; +1D674;MATHEMATICAL MONOSPACE CAPITAL E;Lu;0;L;<font> 0045;;;;N;;;;; +1D675;MATHEMATICAL MONOSPACE CAPITAL F;Lu;0;L;<font> 0046;;;;N;;;;; +1D676;MATHEMATICAL MONOSPACE CAPITAL G;Lu;0;L;<font> 0047;;;;N;;;;; +1D677;MATHEMATICAL MONOSPACE CAPITAL H;Lu;0;L;<font> 0048;;;;N;;;;; +1D678;MATHEMATICAL MONOSPACE CAPITAL I;Lu;0;L;<font> 0049;;;;N;;;;; +1D679;MATHEMATICAL MONOSPACE CAPITAL J;Lu;0;L;<font> 004A;;;;N;;;;; +1D67A;MATHEMATICAL MONOSPACE CAPITAL K;Lu;0;L;<font> 004B;;;;N;;;;; +1D67B;MATHEMATICAL MONOSPACE CAPITAL L;Lu;0;L;<font> 004C;;;;N;;;;; +1D67C;MATHEMATICAL MONOSPACE CAPITAL M;Lu;0;L;<font> 004D;;;;N;;;;; +1D67D;MATHEMATICAL MONOSPACE CAPITAL N;Lu;0;L;<font> 004E;;;;N;;;;; +1D67E;MATHEMATICAL MONOSPACE CAPITAL O;Lu;0;L;<font> 004F;;;;N;;;;; +1D67F;MATHEMATICAL MONOSPACE CAPITAL P;Lu;0;L;<font> 0050;;;;N;;;;; +1D680;MATHEMATICAL MONOSPACE CAPITAL Q;Lu;0;L;<font> 0051;;;;N;;;;; +1D681;MATHEMATICAL MONOSPACE CAPITAL R;Lu;0;L;<font> 0052;;;;N;;;;; +1D682;MATHEMATICAL MONOSPACE CAPITAL S;Lu;0;L;<font> 0053;;;;N;;;;; +1D683;MATHEMATICAL MONOSPACE CAPITAL T;Lu;0;L;<font> 0054;;;;N;;;;; +1D684;MATHEMATICAL MONOSPACE CAPITAL U;Lu;0;L;<font> 0055;;;;N;;;;; +1D685;MATHEMATICAL MONOSPACE CAPITAL V;Lu;0;L;<font> 0056;;;;N;;;;; +1D686;MATHEMATICAL MONOSPACE CAPITAL W;Lu;0;L;<font> 0057;;;;N;;;;; +1D687;MATHEMATICAL MONOSPACE CAPITAL X;Lu;0;L;<font> 0058;;;;N;;;;; +1D688;MATHEMATICAL MONOSPACE CAPITAL Y;Lu;0;L;<font> 0059;;;;N;;;;; +1D689;MATHEMATICAL MONOSPACE CAPITAL Z;Lu;0;L;<font> 005A;;;;N;;;;; +1D68A;MATHEMATICAL MONOSPACE SMALL A;Ll;0;L;<font> 0061;;;;N;;;;; +1D68B;MATHEMATICAL MONOSPACE SMALL B;Ll;0;L;<font> 0062;;;;N;;;;; +1D68C;MATHEMATICAL MONOSPACE SMALL C;Ll;0;L;<font> 0063;;;;N;;;;; +1D68D;MATHEMATICAL MONOSPACE SMALL D;Ll;0;L;<font> 0064;;;;N;;;;; +1D68E;MATHEMATICAL MONOSPACE SMALL E;Ll;0;L;<font> 0065;;;;N;;;;; +1D68F;MATHEMATICAL MONOSPACE SMALL F;Ll;0;L;<font> 0066;;;;N;;;;; +1D690;MATHEMATICAL MONOSPACE SMALL G;Ll;0;L;<font> 0067;;;;N;;;;; +1D691;MATHEMATICAL MONOSPACE SMALL H;Ll;0;L;<font> 0068;;;;N;;;;; +1D692;MATHEMATICAL MONOSPACE SMALL I;Ll;0;L;<font> 0069;;;;N;;;;; +1D693;MATHEMATICAL MONOSPACE SMALL J;Ll;0;L;<font> 006A;;;;N;;;;; +1D694;MATHEMATICAL MONOSPACE SMALL K;Ll;0;L;<font> 006B;;;;N;;;;; +1D695;MATHEMATICAL MONOSPACE SMALL L;Ll;0;L;<font> 006C;;;;N;;;;; +1D696;MATHEMATICAL MONOSPACE SMALL M;Ll;0;L;<font> 006D;;;;N;;;;; +1D697;MATHEMATICAL MONOSPACE SMALL N;Ll;0;L;<font> 006E;;;;N;;;;; +1D698;MATHEMATICAL MONOSPACE SMALL O;Ll;0;L;<font> 006F;;;;N;;;;; +1D699;MATHEMATICAL MONOSPACE SMALL P;Ll;0;L;<font> 0070;;;;N;;;;; +1D69A;MATHEMATICAL MONOSPACE SMALL Q;Ll;0;L;<font> 0071;;;;N;;;;; +1D69B;MATHEMATICAL MONOSPACE SMALL R;Ll;0;L;<font> 0072;;;;N;;;;; +1D69C;MATHEMATICAL MONOSPACE SMALL S;Ll;0;L;<font> 0073;;;;N;;;;; +1D69D;MATHEMATICAL MONOSPACE SMALL T;Ll;0;L;<font> 0074;;;;N;;;;; +1D69E;MATHEMATICAL MONOSPACE SMALL U;Ll;0;L;<font> 0075;;;;N;;;;; +1D69F;MATHEMATICAL MONOSPACE SMALL V;Ll;0;L;<font> 0076;;;;N;;;;; +1D6A0;MATHEMATICAL MONOSPACE SMALL W;Ll;0;L;<font> 0077;;;;N;;;;; +1D6A1;MATHEMATICAL MONOSPACE SMALL X;Ll;0;L;<font> 0078;;;;N;;;;; +1D6A2;MATHEMATICAL MONOSPACE SMALL Y;Ll;0;L;<font> 0079;;;;N;;;;; +1D6A3;MATHEMATICAL MONOSPACE SMALL Z;Ll;0;L;<font> 007A;;;;N;;;;; +1D6A4;MATHEMATICAL ITALIC SMALL DOTLESS I;Ll;0;L;<font> 0131;;;;N;;;;; +1D6A5;MATHEMATICAL ITALIC SMALL DOTLESS J;Ll;0;L;<font> 0237;;;;N;;;;; +1D6A8;MATHEMATICAL BOLD CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; +1D6A9;MATHEMATICAL BOLD CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; +1D6AA;MATHEMATICAL BOLD CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; +1D6AB;MATHEMATICAL BOLD CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; +1D6AC;MATHEMATICAL BOLD CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; +1D6AD;MATHEMATICAL BOLD CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; +1D6AE;MATHEMATICAL BOLD CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; +1D6AF;MATHEMATICAL BOLD CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; +1D6B0;MATHEMATICAL BOLD CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; +1D6B1;MATHEMATICAL BOLD CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; +1D6B2;MATHEMATICAL BOLD CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; +1D6B3;MATHEMATICAL BOLD CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; +1D6B4;MATHEMATICAL BOLD CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; +1D6B5;MATHEMATICAL BOLD CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; +1D6B6;MATHEMATICAL BOLD CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; +1D6B7;MATHEMATICAL BOLD CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; +1D6B8;MATHEMATICAL BOLD CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; +1D6B9;MATHEMATICAL BOLD CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; +1D6BA;MATHEMATICAL BOLD CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; +1D6BB;MATHEMATICAL BOLD CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; +1D6BC;MATHEMATICAL BOLD CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; +1D6BD;MATHEMATICAL BOLD CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; +1D6BE;MATHEMATICAL BOLD CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; +1D6BF;MATHEMATICAL BOLD CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; +1D6C0;MATHEMATICAL BOLD CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; +1D6C1;MATHEMATICAL BOLD NABLA;Sm;0;L;<font> 2207;;;;N;;;;; +1D6C2;MATHEMATICAL BOLD SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; +1D6C3;MATHEMATICAL BOLD SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; +1D6C4;MATHEMATICAL BOLD SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; +1D6C5;MATHEMATICAL BOLD SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; +1D6C6;MATHEMATICAL BOLD SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; +1D6C7;MATHEMATICAL BOLD SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; +1D6C8;MATHEMATICAL BOLD SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; +1D6C9;MATHEMATICAL BOLD SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; +1D6CA;MATHEMATICAL BOLD SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; +1D6CB;MATHEMATICAL BOLD SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; +1D6CC;MATHEMATICAL BOLD SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; +1D6CD;MATHEMATICAL BOLD SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; +1D6CE;MATHEMATICAL BOLD SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; +1D6CF;MATHEMATICAL BOLD SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; +1D6D0;MATHEMATICAL BOLD SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; +1D6D1;MATHEMATICAL BOLD SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; +1D6D2;MATHEMATICAL BOLD SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; +1D6D3;MATHEMATICAL BOLD SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; +1D6D4;MATHEMATICAL BOLD SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; +1D6D5;MATHEMATICAL BOLD SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; +1D6D6;MATHEMATICAL BOLD SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; +1D6D7;MATHEMATICAL BOLD SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; +1D6D8;MATHEMATICAL BOLD SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; +1D6D9;MATHEMATICAL BOLD SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; +1D6DA;MATHEMATICAL BOLD SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; +1D6DB;MATHEMATICAL BOLD PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; +1D6DC;MATHEMATICAL BOLD EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; +1D6DD;MATHEMATICAL BOLD THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; +1D6DE;MATHEMATICAL BOLD KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; +1D6DF;MATHEMATICAL BOLD PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; +1D6E0;MATHEMATICAL BOLD RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; +1D6E1;MATHEMATICAL BOLD PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; +1D6E2;MATHEMATICAL ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; +1D6E3;MATHEMATICAL ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; +1D6E4;MATHEMATICAL ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; +1D6E5;MATHEMATICAL ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; +1D6E6;MATHEMATICAL ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; +1D6E7;MATHEMATICAL ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; +1D6E8;MATHEMATICAL ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; +1D6E9;MATHEMATICAL ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; +1D6EA;MATHEMATICAL ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; +1D6EB;MATHEMATICAL ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; +1D6EC;MATHEMATICAL ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; +1D6ED;MATHEMATICAL ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; +1D6EE;MATHEMATICAL ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; +1D6EF;MATHEMATICAL ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; +1D6F0;MATHEMATICAL ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; +1D6F1;MATHEMATICAL ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; +1D6F2;MATHEMATICAL ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; +1D6F3;MATHEMATICAL ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; +1D6F4;MATHEMATICAL ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; +1D6F5;MATHEMATICAL ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; +1D6F6;MATHEMATICAL ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; +1D6F7;MATHEMATICAL ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; +1D6F8;MATHEMATICAL ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; +1D6F9;MATHEMATICAL ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; +1D6FA;MATHEMATICAL ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; +1D6FB;MATHEMATICAL ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;; +1D6FC;MATHEMATICAL ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; +1D6FD;MATHEMATICAL ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; +1D6FE;MATHEMATICAL ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; +1D6FF;MATHEMATICAL ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; +1D700;MATHEMATICAL ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; +1D701;MATHEMATICAL ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; +1D702;MATHEMATICAL ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; +1D703;MATHEMATICAL ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; +1D704;MATHEMATICAL ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; +1D705;MATHEMATICAL ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; +1D706;MATHEMATICAL ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; +1D707;MATHEMATICAL ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; +1D708;MATHEMATICAL ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; +1D709;MATHEMATICAL ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; +1D70A;MATHEMATICAL ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; +1D70B;MATHEMATICAL ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; +1D70C;MATHEMATICAL ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; +1D70D;MATHEMATICAL ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; +1D70E;MATHEMATICAL ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; +1D70F;MATHEMATICAL ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; +1D710;MATHEMATICAL ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; +1D711;MATHEMATICAL ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; +1D712;MATHEMATICAL ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; +1D713;MATHEMATICAL ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; +1D714;MATHEMATICAL ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; +1D715;MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; +1D716;MATHEMATICAL ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; +1D717;MATHEMATICAL ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; +1D718;MATHEMATICAL ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; +1D719;MATHEMATICAL ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; +1D71A;MATHEMATICAL ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; +1D71B;MATHEMATICAL ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; +1D71C;MATHEMATICAL BOLD ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; +1D71D;MATHEMATICAL BOLD ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; +1D71E;MATHEMATICAL BOLD ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; +1D71F;MATHEMATICAL BOLD ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; +1D720;MATHEMATICAL BOLD ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; +1D721;MATHEMATICAL BOLD ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; +1D722;MATHEMATICAL BOLD ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; +1D723;MATHEMATICAL BOLD ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; +1D724;MATHEMATICAL BOLD ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; +1D725;MATHEMATICAL BOLD ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; +1D726;MATHEMATICAL BOLD ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; +1D727;MATHEMATICAL BOLD ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; +1D728;MATHEMATICAL BOLD ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; +1D729;MATHEMATICAL BOLD ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; +1D72A;MATHEMATICAL BOLD ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; +1D72B;MATHEMATICAL BOLD ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; +1D72C;MATHEMATICAL BOLD ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; +1D72D;MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; +1D72E;MATHEMATICAL BOLD ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; +1D72F;MATHEMATICAL BOLD ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; +1D730;MATHEMATICAL BOLD ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; +1D731;MATHEMATICAL BOLD ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; +1D732;MATHEMATICAL BOLD ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; +1D733;MATHEMATICAL BOLD ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; +1D734;MATHEMATICAL BOLD ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; +1D735;MATHEMATICAL BOLD ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;; +1D736;MATHEMATICAL BOLD ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; +1D737;MATHEMATICAL BOLD ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; +1D738;MATHEMATICAL BOLD ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; +1D739;MATHEMATICAL BOLD ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; +1D73A;MATHEMATICAL BOLD ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; +1D73B;MATHEMATICAL BOLD ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; +1D73C;MATHEMATICAL BOLD ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; +1D73D;MATHEMATICAL BOLD ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; +1D73E;MATHEMATICAL BOLD ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; +1D73F;MATHEMATICAL BOLD ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; +1D740;MATHEMATICAL BOLD ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; +1D741;MATHEMATICAL BOLD ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; +1D742;MATHEMATICAL BOLD ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; +1D743;MATHEMATICAL BOLD ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; +1D744;MATHEMATICAL BOLD ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; +1D745;MATHEMATICAL BOLD ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; +1D746;MATHEMATICAL BOLD ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; +1D747;MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; +1D748;MATHEMATICAL BOLD ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; +1D749;MATHEMATICAL BOLD ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; +1D74A;MATHEMATICAL BOLD ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; +1D74B;MATHEMATICAL BOLD ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; +1D74C;MATHEMATICAL BOLD ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; +1D74D;MATHEMATICAL BOLD ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; +1D74E;MATHEMATICAL BOLD ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; +1D74F;MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; +1D750;MATHEMATICAL BOLD ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; +1D751;MATHEMATICAL BOLD ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; +1D752;MATHEMATICAL BOLD ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; +1D753;MATHEMATICAL BOLD ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; +1D754;MATHEMATICAL BOLD ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; +1D755;MATHEMATICAL BOLD ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; +1D756;MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; +1D757;MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; +1D758;MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; +1D759;MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; +1D75A;MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; +1D75B;MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; +1D75C;MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; +1D75D;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; +1D75E;MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; +1D75F;MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; +1D760;MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; +1D761;MATHEMATICAL SANS-SERIF BOLD CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; +1D762;MATHEMATICAL SANS-SERIF BOLD CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; +1D763;MATHEMATICAL SANS-SERIF BOLD CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; +1D764;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; +1D765;MATHEMATICAL SANS-SERIF BOLD CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; +1D766;MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; +1D767;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; +1D768;MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; +1D769;MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; +1D76A;MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; +1D76B;MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; +1D76C;MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; +1D76D;MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; +1D76E;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; +1D76F;MATHEMATICAL SANS-SERIF BOLD NABLA;Sm;0;L;<font> 2207;;;;N;;;;; +1D770;MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; +1D771;MATHEMATICAL SANS-SERIF BOLD SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; +1D772;MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; +1D773;MATHEMATICAL SANS-SERIF BOLD SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; +1D774;MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; +1D775;MATHEMATICAL SANS-SERIF BOLD SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; +1D776;MATHEMATICAL SANS-SERIF BOLD SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; +1D777;MATHEMATICAL SANS-SERIF BOLD SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; +1D778;MATHEMATICAL SANS-SERIF BOLD SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; +1D779;MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; +1D77A;MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; +1D77B;MATHEMATICAL SANS-SERIF BOLD SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; +1D77C;MATHEMATICAL SANS-SERIF BOLD SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; +1D77D;MATHEMATICAL SANS-SERIF BOLD SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; +1D77E;MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; +1D77F;MATHEMATICAL SANS-SERIF BOLD SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; +1D780;MATHEMATICAL SANS-SERIF BOLD SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; +1D781;MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; +1D782;MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; +1D783;MATHEMATICAL SANS-SERIF BOLD SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; +1D784;MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; +1D785;MATHEMATICAL SANS-SERIF BOLD SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; +1D786;MATHEMATICAL SANS-SERIF BOLD SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; +1D787;MATHEMATICAL SANS-SERIF BOLD SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; +1D788;MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; +1D789;MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; +1D78A;MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; +1D78B;MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; +1D78C;MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; +1D78D;MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; +1D78E;MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; +1D78F;MATHEMATICAL SANS-SERIF BOLD PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; +1D790;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA;Lu;0;L;<font> 0391;;;;N;;;;; +1D791;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA;Lu;0;L;<font> 0392;;;;N;;;;; +1D792;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA;Lu;0;L;<font> 0393;;;;N;;;;; +1D793;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA;Lu;0;L;<font> 0394;;;;N;;;;; +1D794;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON;Lu;0;L;<font> 0395;;;;N;;;;; +1D795;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA;Lu;0;L;<font> 0396;;;;N;;;;; +1D796;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA;Lu;0;L;<font> 0397;;;;N;;;;; +1D797;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA;Lu;0;L;<font> 0398;;;;N;;;;; +1D798;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA;Lu;0;L;<font> 0399;;;;N;;;;; +1D799;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA;Lu;0;L;<font> 039A;;;;N;;;;; +1D79A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA;Lu;0;L;<font> 039B;;;;N;;;;; +1D79B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU;Lu;0;L;<font> 039C;;;;N;;;;; +1D79C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU;Lu;0;L;<font> 039D;;;;N;;;;; +1D79D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI;Lu;0;L;<font> 039E;;;;N;;;;; +1D79E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON;Lu;0;L;<font> 039F;;;;N;;;;; +1D79F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI;Lu;0;L;<font> 03A0;;;;N;;;;; +1D7A0;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO;Lu;0;L;<font> 03A1;;;;N;;;;; +1D7A1;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L;<font> 03F4;;;;N;;;;; +1D7A2;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA;Lu;0;L;<font> 03A3;;;;N;;;;; +1D7A3;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU;Lu;0;L;<font> 03A4;;;;N;;;;; +1D7A4;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON;Lu;0;L;<font> 03A5;;;;N;;;;; +1D7A5;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI;Lu;0;L;<font> 03A6;;;;N;;;;; +1D7A6;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI;Lu;0;L;<font> 03A7;;;;N;;;;; +1D7A7;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI;Lu;0;L;<font> 03A8;;;;N;;;;; +1D7A8;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA;Lu;0;L;<font> 03A9;;;;N;;;;; +1D7A9;MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA;Sm;0;L;<font> 2207;;;;N;;;;; +1D7AA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA;Ll;0;L;<font> 03B1;;;;N;;;;; +1D7AB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA;Ll;0;L;<font> 03B2;;;;N;;;;; +1D7AC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA;Ll;0;L;<font> 03B3;;;;N;;;;; +1D7AD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA;Ll;0;L;<font> 03B4;;;;N;;;;; +1D7AE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON;Ll;0;L;<font> 03B5;;;;N;;;;; +1D7AF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA;Ll;0;L;<font> 03B6;;;;N;;;;; +1D7B0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA;Ll;0;L;<font> 03B7;;;;N;;;;; +1D7B1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA;Ll;0;L;<font> 03B8;;;;N;;;;; +1D7B2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA;Ll;0;L;<font> 03B9;;;;N;;;;; +1D7B3;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA;Ll;0;L;<font> 03BA;;;;N;;;;; +1D7B4;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA;Ll;0;L;<font> 03BB;;;;N;;;;; +1D7B5;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU;Ll;0;L;<font> 03BC;;;;N;;;;; +1D7B6;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU;Ll;0;L;<font> 03BD;;;;N;;;;; +1D7B7;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI;Ll;0;L;<font> 03BE;;;;N;;;;; +1D7B8;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON;Ll;0;L;<font> 03BF;;;;N;;;;; +1D7B9;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI;Ll;0;L;<font> 03C0;;;;N;;;;; +1D7BA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO;Ll;0;L;<font> 03C1;;;;N;;;;; +1D7BB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L;<font> 03C2;;;;N;;;;; +1D7BC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA;Ll;0;L;<font> 03C3;;;;N;;;;; +1D7BD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU;Ll;0;L;<font> 03C4;;;;N;;;;; +1D7BE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON;Ll;0;L;<font> 03C5;;;;N;;;;; +1D7BF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI;Ll;0;L;<font> 03C6;;;;N;;;;; +1D7C0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI;Ll;0;L;<font> 03C7;;;;N;;;;; +1D7C1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI;Ll;0;L;<font> 03C8;;;;N;;;;; +1D7C2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA;Ll;0;L;<font> 03C9;;;;N;;;;; +1D7C3;MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON;<font> 2202;;;;Y;;;;; +1D7C4;MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL;Ll;0;L;<font> 03F5;;;;N;;;;; +1D7C5;MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL;Ll;0;L;<font> 03D1;;;;N;;;;; +1D7C6;MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL;Ll;0;L;<font> 03F0;;;;N;;;;; +1D7C7;MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL;Ll;0;L;<font> 03D5;;;;N;;;;; +1D7C8;MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL;Ll;0;L;<font> 03F1;;;;N;;;;; +1D7C9;MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL;Ll;0;L;<font> 03D6;;;;N;;;;; +1D7CA;MATHEMATICAL BOLD CAPITAL DIGAMMA;Lu;0;L;<font> 03DC;;;;N;;;;; +1D7CB;MATHEMATICAL BOLD SMALL DIGAMMA;Ll;0;L;<font> 03DD;;;;N;;;;; +1D7CE;MATHEMATICAL BOLD DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; +1D7CF;MATHEMATICAL BOLD DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; +1D7D0;MATHEMATICAL BOLD DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; +1D7D1;MATHEMATICAL BOLD DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; +1D7D2;MATHEMATICAL BOLD DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; +1D7D3;MATHEMATICAL BOLD DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; +1D7D4;MATHEMATICAL BOLD DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; +1D7D5;MATHEMATICAL BOLD DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; +1D7D6;MATHEMATICAL BOLD DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; +1D7D7;MATHEMATICAL BOLD DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; +1D7D8;MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; +1D7D9;MATHEMATICAL DOUBLE-STRUCK DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; +1D7DA;MATHEMATICAL DOUBLE-STRUCK DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; +1D7DB;MATHEMATICAL DOUBLE-STRUCK DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; +1D7DC;MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; +1D7DD;MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; +1D7DE;MATHEMATICAL DOUBLE-STRUCK DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; +1D7DF;MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; +1D7E0;MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; +1D7E1;MATHEMATICAL DOUBLE-STRUCK DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; +1D7E2;MATHEMATICAL SANS-SERIF DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; +1D7E3;MATHEMATICAL SANS-SERIF DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; +1D7E4;MATHEMATICAL SANS-SERIF DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; +1D7E5;MATHEMATICAL SANS-SERIF DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; +1D7E6;MATHEMATICAL SANS-SERIF DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; +1D7E7;MATHEMATICAL SANS-SERIF DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; +1D7E8;MATHEMATICAL SANS-SERIF DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; +1D7E9;MATHEMATICAL SANS-SERIF DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; +1D7EA;MATHEMATICAL SANS-SERIF DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; +1D7EB;MATHEMATICAL SANS-SERIF DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; +1D7EC;MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; +1D7ED;MATHEMATICAL SANS-SERIF BOLD DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; +1D7EE;MATHEMATICAL SANS-SERIF BOLD DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; +1D7EF;MATHEMATICAL SANS-SERIF BOLD DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; +1D7F0;MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; +1D7F1;MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; +1D7F2;MATHEMATICAL SANS-SERIF BOLD DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; +1D7F3;MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; +1D7F4;MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; +1D7F5;MATHEMATICAL SANS-SERIF BOLD DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; +1D7F6;MATHEMATICAL MONOSPACE DIGIT ZERO;Nd;0;EN;<font> 0030;0;0;0;N;;;;; +1D7F7;MATHEMATICAL MONOSPACE DIGIT ONE;Nd;0;EN;<font> 0031;1;1;1;N;;;;; +1D7F8;MATHEMATICAL MONOSPACE DIGIT TWO;Nd;0;EN;<font> 0032;2;2;2;N;;;;; +1D7F9;MATHEMATICAL MONOSPACE DIGIT THREE;Nd;0;EN;<font> 0033;3;3;3;N;;;;; +1D7FA;MATHEMATICAL MONOSPACE DIGIT FOUR;Nd;0;EN;<font> 0034;4;4;4;N;;;;; +1D7FB;MATHEMATICAL MONOSPACE DIGIT FIVE;Nd;0;EN;<font> 0035;5;5;5;N;;;;; +1D7FC;MATHEMATICAL MONOSPACE DIGIT SIX;Nd;0;EN;<font> 0036;6;6;6;N;;;;; +1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;; +1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;; +1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;; +1D800;SIGNWRITING HAND-FIST INDEX;So;0;L;;;;;N;;;;; +1D801;SIGNWRITING HAND-CIRCLE INDEX;So;0;L;;;;;N;;;;; +1D802;SIGNWRITING HAND-CUP INDEX;So;0;L;;;;;N;;;;; +1D803;SIGNWRITING HAND-OVAL INDEX;So;0;L;;;;;N;;;;; +1D804;SIGNWRITING HAND-HINGE INDEX;So;0;L;;;;;N;;;;; +1D805;SIGNWRITING HAND-ANGLE INDEX;So;0;L;;;;;N;;;;; +1D806;SIGNWRITING HAND-FIST INDEX BENT;So;0;L;;;;;N;;;;; +1D807;SIGNWRITING HAND-CIRCLE INDEX BENT;So;0;L;;;;;N;;;;; +1D808;SIGNWRITING HAND-FIST THUMB UNDER INDEX BENT;So;0;L;;;;;N;;;;; +1D809;SIGNWRITING HAND-FIST INDEX RAISED KNUCKLE;So;0;L;;;;;N;;;;; +1D80A;SIGNWRITING HAND-FIST INDEX CUPPED;So;0;L;;;;;N;;;;; +1D80B;SIGNWRITING HAND-FIST INDEX HINGED;So;0;L;;;;;N;;;;; +1D80C;SIGNWRITING HAND-FIST INDEX HINGED LOW;So;0;L;;;;;N;;;;; +1D80D;SIGNWRITING HAND-CIRCLE INDEX HINGE;So;0;L;;;;;N;;;;; +1D80E;SIGNWRITING HAND-FIST INDEX MIDDLE;So;0;L;;;;;N;;;;; +1D80F;SIGNWRITING HAND-CIRCLE INDEX MIDDLE;So;0;L;;;;;N;;;;; +1D810;SIGNWRITING HAND-FIST INDEX MIDDLE BENT;So;0;L;;;;;N;;;;; +1D811;SIGNWRITING HAND-FIST INDEX MIDDLE RAISED KNUCKLES;So;0;L;;;;;N;;;;; +1D812;SIGNWRITING HAND-FIST INDEX MIDDLE HINGED;So;0;L;;;;;N;;;;; +1D813;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED;So;0;L;;;;;N;;;;; +1D814;SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP;So;0;L;;;;;N;;;;; +1D815;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED;So;0;L;;;;;N;;;;; +1D816;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED INDEX BENT;So;0;L;;;;;N;;;;; +1D817;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED MIDDLE BENT;So;0;L;;;;;N;;;;; +1D818;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED;So;0;L;;;;;N;;;;; +1D819;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED;So;0;L;;;;;N;;;;; +1D81A;SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED;So;0;L;;;;;N;;;;; +1D81B;SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSSED;So;0;L;;;;;N;;;;; +1D81C;SIGNWRITING HAND-FIST MIDDLE BENT OVER INDEX;So;0;L;;;;;N;;;;; +1D81D;SIGNWRITING HAND-FIST INDEX BENT OVER MIDDLE;So;0;L;;;;;N;;;;; +1D81E;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB;So;0;L;;;;;N;;;;; +1D81F;SIGNWRITING HAND-CIRCLE INDEX MIDDLE THUMB;So;0;L;;;;;N;;;;; +1D820;SIGNWRITING HAND-FIST INDEX MIDDLE STRAIGHT THUMB BENT;So;0;L;;;;;N;;;;; +1D821;SIGNWRITING HAND-FIST INDEX MIDDLE BENT THUMB STRAIGHT;So;0;L;;;;;N;;;;; +1D822;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB BENT;So;0;L;;;;;N;;;;; +1D823;SIGNWRITING HAND-FIST INDEX MIDDLE HINGED SPREAD THUMB SIDE;So;0;L;;;;;N;;;;; +1D824;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB SIDE;So;0;L;;;;;N;;;;; +1D825;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB CONJOINED;So;0;L;;;;;N;;;;; +1D826;SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP THUMB SIDE;So;0;L;;;;;N;;;;; +1D827;SIGNWRITING HAND-FIST INDEX MIDDLE UP SPREAD THUMB FORWARD;So;0;L;;;;;N;;;;; +1D828;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CUPPED;So;0;L;;;;;N;;;;; +1D829;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CIRCLED;So;0;L;;;;;N;;;;; +1D82A;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HOOKED;So;0;L;;;;;N;;;;; +1D82B;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HINGED;So;0;L;;;;;N;;;;; +1D82C;SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE STRAIGHT;So;0;L;;;;;N;;;;; +1D82D;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE;So;0;L;;;;;N;;;;; +1D82E;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE CONJOINED;So;0;L;;;;;N;;;;; +1D82F;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE BENT;So;0;L;;;;;N;;;;; +1D830;SIGNWRITING HAND-FIST MIDDLE THUMB HOOKED INDEX UP;So;0;L;;;;;N;;;;; +1D831;SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE UP;So;0;L;;;;;N;;;;; +1D832;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED THUMB SIDE;So;0;L;;;;;N;;;;; +1D833;SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED THUMB SIDE;So;0;L;;;;;N;;;;; +1D834;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB FORWARD;So;0;L;;;;;N;;;;; +1D835;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED THUMB FORWARD;So;0;L;;;;;N;;;;; +1D836;SIGNWRITING HAND-FIST MIDDLE THUMB CUPPED INDEX UP;So;0;L;;;;;N;;;;; +1D837;SIGNWRITING HAND-FIST INDEX THUMB CUPPED MIDDLE UP;So;0;L;;;;;N;;;;; +1D838;SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX UP;So;0;L;;;;;N;;;;; +1D839;SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX HINGED;So;0;L;;;;;N;;;;; +1D83A;SIGNWRITING HAND-FIST INDEX THUMB ANGLED OUT MIDDLE UP;So;0;L;;;;;N;;;;; +1D83B;SIGNWRITING HAND-FIST INDEX THUMB ANGLED IN MIDDLE UP;So;0;L;;;;;N;;;;; +1D83C;SIGNWRITING HAND-FIST INDEX THUMB CIRCLED MIDDLE UP;So;0;L;;;;;N;;;;; +1D83D;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CONJOINED HINGED;So;0;L;;;;;N;;;;; +1D83E;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED OUT;So;0;L;;;;;N;;;;; +1D83F;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED;So;0;L;;;;;N;;;;; +1D840;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX UP;So;0;L;;;;;N;;;;; +1D841;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX CROSSED;So;0;L;;;;;N;;;;; +1D842;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED INDEX UP;So;0;L;;;;;N;;;;; +1D843;SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE HINGED;So;0;L;;;;;N;;;;; +1D844;SIGNWRITING HAND-FLAT FOUR FINGERS;So;0;L;;;;;N;;;;; +1D845;SIGNWRITING HAND-FLAT FOUR FINGERS BENT;So;0;L;;;;;N;;;;; +1D846;SIGNWRITING HAND-FLAT FOUR FINGERS HINGED;So;0;L;;;;;N;;;;; +1D847;SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; +1D848;SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED SPLIT;So;0;L;;;;;N;;;;; +1D849;SIGNWRITING HAND-CLAW FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; +1D84A;SIGNWRITING HAND-FIST FOUR FINGERS CONJOINED BENT;So;0;L;;;;;N;;;;; +1D84B;SIGNWRITING HAND-HINGE FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; +1D84C;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; +1D84D;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; +1D84E;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD FOUR BENT;So;0;L;;;;;N;;;;; +1D84F;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD FOUR BENT;So;0;L;;;;;N;;;;; +1D850;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD BENT;So;0;L;;;;;N;;;;; +1D851;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD BENT;So;0;L;;;;;N;;;;; +1D852;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD THUMB FORWARD;So;0;L;;;;;N;;;;; +1D853;SIGNWRITING HAND-CUP FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; +1D854;SIGNWRITING HAND-CUP FIVE FINGERS SPREAD OPEN;So;0;L;;;;;N;;;;; +1D855;SIGNWRITING HAND-HINGE FIVE FINGERS SPREAD OPEN;So;0;L;;;;;N;;;;; +1D856;SIGNWRITING HAND-OVAL FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; +1D857;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED;So;0;L;;;;;N;;;;; +1D858;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED THUMB SIDE;So;0;L;;;;;N;;;;; +1D859;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED NO THUMB;So;0;L;;;;;N;;;;; +1D85A;SIGNWRITING HAND-FLAT;So;0;L;;;;;N;;;;; +1D85B;SIGNWRITING HAND-FLAT BETWEEN PALM FACINGS;So;0;L;;;;;N;;;;; +1D85C;SIGNWRITING HAND-FLAT HEEL;So;0;L;;;;;N;;;;; +1D85D;SIGNWRITING HAND-FLAT THUMB SIDE;So;0;L;;;;;N;;;;; +1D85E;SIGNWRITING HAND-FLAT HEEL THUMB SIDE;So;0;L;;;;;N;;;;; +1D85F;SIGNWRITING HAND-FLAT THUMB BENT;So;0;L;;;;;N;;;;; +1D860;SIGNWRITING HAND-FLAT THUMB FORWARD;So;0;L;;;;;N;;;;; +1D861;SIGNWRITING HAND-FLAT SPLIT INDEX THUMB SIDE;So;0;L;;;;;N;;;;; +1D862;SIGNWRITING HAND-FLAT SPLIT CENTRE;So;0;L;;;;;N;;;;; +1D863;SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE;So;0;L;;;;;N;;;;; +1D864;SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE BENT;So;0;L;;;;;N;;;;; +1D865;SIGNWRITING HAND-FLAT SPLIT LITTLE;So;0;L;;;;;N;;;;; +1D866;SIGNWRITING HAND-CLAW;So;0;L;;;;;N;;;;; +1D867;SIGNWRITING HAND-CLAW THUMB SIDE;So;0;L;;;;;N;;;;; +1D868;SIGNWRITING HAND-CLAW NO THUMB;So;0;L;;;;;N;;;;; +1D869;SIGNWRITING HAND-CLAW THUMB FORWARD;So;0;L;;;;;N;;;;; +1D86A;SIGNWRITING HAND-HOOK CURLICUE;So;0;L;;;;;N;;;;; +1D86B;SIGNWRITING HAND-HOOK;So;0;L;;;;;N;;;;; +1D86C;SIGNWRITING HAND-CUP OPEN;So;0;L;;;;;N;;;;; +1D86D;SIGNWRITING HAND-CUP;So;0;L;;;;;N;;;;; +1D86E;SIGNWRITING HAND-CUP OPEN THUMB SIDE;So;0;L;;;;;N;;;;; +1D86F;SIGNWRITING HAND-CUP THUMB SIDE;So;0;L;;;;;N;;;;; +1D870;SIGNWRITING HAND-CUP OPEN NO THUMB;So;0;L;;;;;N;;;;; +1D871;SIGNWRITING HAND-CUP NO THUMB;So;0;L;;;;;N;;;;; +1D872;SIGNWRITING HAND-CUP OPEN THUMB FORWARD;So;0;L;;;;;N;;;;; +1D873;SIGNWRITING HAND-CUP THUMB FORWARD;So;0;L;;;;;N;;;;; +1D874;SIGNWRITING HAND-CURLICUE OPEN;So;0;L;;;;;N;;;;; +1D875;SIGNWRITING HAND-CURLICUE;So;0;L;;;;;N;;;;; +1D876;SIGNWRITING HAND-CIRCLE;So;0;L;;;;;N;;;;; +1D877;SIGNWRITING HAND-OVAL;So;0;L;;;;;N;;;;; +1D878;SIGNWRITING HAND-OVAL THUMB SIDE;So;0;L;;;;;N;;;;; +1D879;SIGNWRITING HAND-OVAL NO THUMB;So;0;L;;;;;N;;;;; +1D87A;SIGNWRITING HAND-OVAL THUMB FORWARD;So;0;L;;;;;N;;;;; +1D87B;SIGNWRITING HAND-HINGE OPEN;So;0;L;;;;;N;;;;; +1D87C;SIGNWRITING HAND-HINGE OPEN THUMB FORWARD;So;0;L;;;;;N;;;;; +1D87D;SIGNWRITING HAND-HINGE;So;0;L;;;;;N;;;;; +1D87E;SIGNWRITING HAND-HINGE SMALL;So;0;L;;;;;N;;;;; +1D87F;SIGNWRITING HAND-HINGE OPEN THUMB SIDE;So;0;L;;;;;N;;;;; +1D880;SIGNWRITING HAND-HINGE THUMB SIDE;So;0;L;;;;;N;;;;; +1D881;SIGNWRITING HAND-HINGE OPEN NO THUMB;So;0;L;;;;;N;;;;; +1D882;SIGNWRITING HAND-HINGE NO THUMB;So;0;L;;;;;N;;;;; +1D883;SIGNWRITING HAND-HINGE THUMB SIDE TOUCHING INDEX;So;0;L;;;;;N;;;;; +1D884;SIGNWRITING HAND-HINGE THUMB BETWEEN MIDDLE RING;So;0;L;;;;;N;;;;; +1D885;SIGNWRITING HAND-ANGLE;So;0;L;;;;;N;;;;; +1D886;SIGNWRITING HAND-FIST INDEX MIDDLE RING;So;0;L;;;;;N;;;;; +1D887;SIGNWRITING HAND-CIRCLE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; +1D888;SIGNWRITING HAND-HINGE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; +1D889;SIGNWRITING HAND-ANGLE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; +1D88A;SIGNWRITING HAND-HINGE LITTLE;So;0;L;;;;;N;;;;; +1D88B;SIGNWRITING HAND-FIST INDEX MIDDLE RING BENT;So;0;L;;;;;N;;;;; +1D88C;SIGNWRITING HAND-FIST INDEX MIDDLE RING CONJOINED;So;0;L;;;;;N;;;;; +1D88D;SIGNWRITING HAND-HINGE INDEX MIDDLE RING CONJOINED;So;0;L;;;;;N;;;;; +1D88E;SIGNWRITING HAND-FIST LITTLE DOWN;So;0;L;;;;;N;;;;; +1D88F;SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE STRAIGHT;So;0;L;;;;;N;;;;; +1D890;SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE CURVED;So;0;L;;;;;N;;;;; +1D891;SIGNWRITING HAND-FIST LITTLE DOWN OTHERS CIRCLED;So;0;L;;;;;N;;;;; +1D892;SIGNWRITING HAND-FIST LITTLE UP;So;0;L;;;;;N;;;;; +1D893;SIGNWRITING HAND-FIST THUMB UNDER LITTLE UP;So;0;L;;;;;N;;;;; +1D894;SIGNWRITING HAND-CIRCLE LITTLE UP;So;0;L;;;;;N;;;;; +1D895;SIGNWRITING HAND-OVAL LITTLE UP;So;0;L;;;;;N;;;;; +1D896;SIGNWRITING HAND-ANGLE LITTLE UP;So;0;L;;;;;N;;;;; +1D897;SIGNWRITING HAND-FIST LITTLE RAISED KNUCKLE;So;0;L;;;;;N;;;;; +1D898;SIGNWRITING HAND-FIST LITTLE BENT;So;0;L;;;;;N;;;;; +1D899;SIGNWRITING HAND-FIST LITTLE TOUCHES THUMB;So;0;L;;;;;N;;;;; +1D89A;SIGNWRITING HAND-FIST LITTLE THUMB;So;0;L;;;;;N;;;;; +1D89B;SIGNWRITING HAND-HINGE LITTLE THUMB;So;0;L;;;;;N;;;;; +1D89C;SIGNWRITING HAND-FIST LITTLE INDEX THUMB;So;0;L;;;;;N;;;;; +1D89D;SIGNWRITING HAND-HINGE LITTLE INDEX THUMB;So;0;L;;;;;N;;;;; +1D89E;SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB OUT;So;0;L;;;;;N;;;;; +1D89F;SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB;So;0;L;;;;;N;;;;; +1D8A0;SIGNWRITING HAND-FIST LITTLE INDEX;So;0;L;;;;;N;;;;; +1D8A1;SIGNWRITING HAND-CIRCLE LITTLE INDEX;So;0;L;;;;;N;;;;; +1D8A2;SIGNWRITING HAND-HINGE LITTLE INDEX;So;0;L;;;;;N;;;;; +1D8A3;SIGNWRITING HAND-ANGLE LITTLE INDEX;So;0;L;;;;;N;;;;; +1D8A4;SIGNWRITING HAND-FIST INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8A5;SIGNWRITING HAND-CIRCLE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8A6;SIGNWRITING HAND-HINGE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8A7;SIGNWRITING HAND-HINGE RING;So;0;L;;;;;N;;;;; +1D8A8;SIGNWRITING HAND-ANGLE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8A9;SIGNWRITING HAND-FIST INDEX MIDDLE CROSS LITTLE;So;0;L;;;;;N;;;;; +1D8AA;SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSS LITTLE;So;0;L;;;;;N;;;;; +1D8AB;SIGNWRITING HAND-FIST RING DOWN;So;0;L;;;;;N;;;;; +1D8AC;SIGNWRITING HAND-HINGE RING DOWN INDEX THUMB HOOK MIDDLE;So;0;L;;;;;N;;;;; +1D8AD;SIGNWRITING HAND-ANGLE RING DOWN MIDDLE THUMB INDEX CROSS;So;0;L;;;;;N;;;;; +1D8AE;SIGNWRITING HAND-FIST RING UP;So;0;L;;;;;N;;;;; +1D8AF;SIGNWRITING HAND-FIST RING RAISED KNUCKLE;So;0;L;;;;;N;;;;; +1D8B0;SIGNWRITING HAND-FIST RING LITTLE;So;0;L;;;;;N;;;;; +1D8B1;SIGNWRITING HAND-CIRCLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8B2;SIGNWRITING HAND-OVAL RING LITTLE;So;0;L;;;;;N;;;;; +1D8B3;SIGNWRITING HAND-ANGLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8B4;SIGNWRITING HAND-FIST RING MIDDLE;So;0;L;;;;;N;;;;; +1D8B5;SIGNWRITING HAND-FIST RING MIDDLE CONJOINED;So;0;L;;;;;N;;;;; +1D8B6;SIGNWRITING HAND-FIST RING MIDDLE RAISED KNUCKLES;So;0;L;;;;;N;;;;; +1D8B7;SIGNWRITING HAND-FIST RING INDEX;So;0;L;;;;;N;;;;; +1D8B8;SIGNWRITING HAND-FIST RING THUMB;So;0;L;;;;;N;;;;; +1D8B9;SIGNWRITING HAND-HOOK RING THUMB;So;0;L;;;;;N;;;;; +1D8BA;SIGNWRITING HAND-FIST INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8BB;SIGNWRITING HAND-CIRCLE INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8BC;SIGNWRITING HAND-CURLICUE INDEX RING LITTLE ON;So;0;L;;;;;N;;;;; +1D8BD;SIGNWRITING HAND-HOOK INDEX RING LITTLE OUT;So;0;L;;;;;N;;;;; +1D8BE;SIGNWRITING HAND-HOOK INDEX RING LITTLE IN;So;0;L;;;;;N;;;;; +1D8BF;SIGNWRITING HAND-HOOK INDEX RING LITTLE UNDER;So;0;L;;;;;N;;;;; +1D8C0;SIGNWRITING HAND-CUP INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8C1;SIGNWRITING HAND-HINGE INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8C2;SIGNWRITING HAND-ANGLE INDEX RING LITTLE OUT;So;0;L;;;;;N;;;;; +1D8C3;SIGNWRITING HAND-ANGLE INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8C4;SIGNWRITING HAND-FIST MIDDLE DOWN;So;0;L;;;;;N;;;;; +1D8C5;SIGNWRITING HAND-HINGE MIDDLE;So;0;L;;;;;N;;;;; +1D8C6;SIGNWRITING HAND-FIST MIDDLE UP;So;0;L;;;;;N;;;;; +1D8C7;SIGNWRITING HAND-CIRCLE MIDDLE UP;So;0;L;;;;;N;;;;; +1D8C8;SIGNWRITING HAND-FIST MIDDLE RAISED KNUCKLE;So;0;L;;;;;N;;;;; +1D8C9;SIGNWRITING HAND-FIST MIDDLE UP THUMB SIDE;So;0;L;;;;;N;;;;; +1D8CA;SIGNWRITING HAND-HOOK MIDDLE THUMB;So;0;L;;;;;N;;;;; +1D8CB;SIGNWRITING HAND-FIST MIDDLE THUMB LITTLE;So;0;L;;;;;N;;;;; +1D8CC;SIGNWRITING HAND-FIST MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8CD;SIGNWRITING HAND-FIST MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8CE;SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8CF;SIGNWRITING HAND-CURLICUE MIDDLE RING LITTLE ON;So;0;L;;;;;N;;;;; +1D8D0;SIGNWRITING HAND-CUP MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8D1;SIGNWRITING HAND-HINGE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8D2;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE OUT;So;0;L;;;;;N;;;;; +1D8D3;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE IN;So;0;L;;;;;N;;;;; +1D8D4;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8D5;SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE BENT;So;0;L;;;;;N;;;;; +1D8D6;SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED;So;0;L;;;;;N;;;;; +1D8D7;SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED SIDE;So;0;L;;;;;N;;;;; +1D8D8;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED OUT;So;0;L;;;;;N;;;;; +1D8D9;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED IN;So;0;L;;;;;N;;;;; +1D8DA;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED;So;0;L;;;;;N;;;;; +1D8DB;SIGNWRITING HAND-HINGE INDEX HINGED;So;0;L;;;;;N;;;;; +1D8DC;SIGNWRITING HAND-FIST INDEX THUMB SIDE;So;0;L;;;;;N;;;;; +1D8DD;SIGNWRITING HAND-HINGE INDEX THUMB SIDE;So;0;L;;;;;N;;;;; +1D8DE;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB DIAGONAL;So;0;L;;;;;N;;;;; +1D8DF;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB CONJOINED;So;0;L;;;;;N;;;;; +1D8E0;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB BENT;So;0;L;;;;;N;;;;; +1D8E1;SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX BENT;So;0;L;;;;;N;;;;; +1D8E2;SIGNWRITING HAND-FIST INDEX THUMB SIDE BOTH BENT;So;0;L;;;;;N;;;;; +1D8E3;SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX HINGE;So;0;L;;;;;N;;;;; +1D8E4;SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX STRAIGHT;So;0;L;;;;;N;;;;; +1D8E5;SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX BENT;So;0;L;;;;;N;;;;; +1D8E6;SIGNWRITING HAND-FIST INDEX THUMB HOOK;So;0;L;;;;;N;;;;; +1D8E7;SIGNWRITING HAND-FIST INDEX THUMB CURLICUE;So;0;L;;;;;N;;;;; +1D8E8;SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB INSIDE;So;0;L;;;;;N;;;;; +1D8E9;SIGNWRITING HAND-CLAW INDEX THUMB CURVE THUMB INSIDE;So;0;L;;;;;N;;;;; +1D8EA;SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB UNDER;So;0;L;;;;;N;;;;; +1D8EB;SIGNWRITING HAND-FIST INDEX THUMB CIRCLE;So;0;L;;;;;N;;;;; +1D8EC;SIGNWRITING HAND-CUP INDEX THUMB;So;0;L;;;;;N;;;;; +1D8ED;SIGNWRITING HAND-CUP INDEX THUMB OPEN;So;0;L;;;;;N;;;;; +1D8EE;SIGNWRITING HAND-HINGE INDEX THUMB OPEN;So;0;L;;;;;N;;;;; +1D8EF;SIGNWRITING HAND-HINGE INDEX THUMB LARGE;So;0;L;;;;;N;;;;; +1D8F0;SIGNWRITING HAND-HINGE INDEX THUMB;So;0;L;;;;;N;;;;; +1D8F1;SIGNWRITING HAND-HINGE INDEX THUMB SMALL;So;0;L;;;;;N;;;;; +1D8F2;SIGNWRITING HAND-ANGLE INDEX THUMB OUT;So;0;L;;;;;N;;;;; +1D8F3;SIGNWRITING HAND-ANGLE INDEX THUMB IN;So;0;L;;;;;N;;;;; +1D8F4;SIGNWRITING HAND-ANGLE INDEX THUMB;So;0;L;;;;;N;;;;; +1D8F5;SIGNWRITING HAND-FIST THUMB;So;0;L;;;;;N;;;;; +1D8F6;SIGNWRITING HAND-FIST THUMB HEEL;So;0;L;;;;;N;;;;; +1D8F7;SIGNWRITING HAND-FIST THUMB SIDE DIAGONAL;So;0;L;;;;;N;;;;; +1D8F8;SIGNWRITING HAND-FIST THUMB SIDE CONJOINED;So;0;L;;;;;N;;;;; +1D8F9;SIGNWRITING HAND-FIST THUMB SIDE BENT;So;0;L;;;;;N;;;;; +1D8FA;SIGNWRITING HAND-FIST THUMB FORWARD;So;0;L;;;;;N;;;;; +1D8FB;SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE;So;0;L;;;;;N;;;;; +1D8FC;SIGNWRITING HAND-FIST THUMB BETWEEN MIDDLE RING;So;0;L;;;;;N;;;;; +1D8FD;SIGNWRITING HAND-FIST THUMB BETWEEN RING LITTLE;So;0;L;;;;;N;;;;; +1D8FE;SIGNWRITING HAND-FIST THUMB UNDER TWO FINGERS;So;0;L;;;;;N;;;;; +1D8FF;SIGNWRITING HAND-FIST THUMB OVER TWO FINGERS;So;0;L;;;;;N;;;;; +1D900;SIGNWRITING HAND-FIST THUMB UNDER THREE FINGERS;So;0;L;;;;;N;;;;; +1D901;SIGNWRITING HAND-FIST THUMB UNDER FOUR FINGERS;So;0;L;;;;;N;;;;; +1D902;SIGNWRITING HAND-FIST THUMB OVER FOUR RAISED KNUCKLES;So;0;L;;;;;N;;;;; +1D903;SIGNWRITING HAND-FIST;So;0;L;;;;;N;;;;; +1D904;SIGNWRITING HAND-FIST HEEL;So;0;L;;;;;N;;;;; +1D905;SIGNWRITING TOUCH SINGLE;So;0;L;;;;;N;;;;; +1D906;SIGNWRITING TOUCH MULTIPLE;So;0;L;;;;;N;;;;; +1D907;SIGNWRITING TOUCH BETWEEN;So;0;L;;;;;N;;;;; +1D908;SIGNWRITING GRASP SINGLE;So;0;L;;;;;N;;;;; +1D909;SIGNWRITING GRASP MULTIPLE;So;0;L;;;;;N;;;;; +1D90A;SIGNWRITING GRASP BETWEEN;So;0;L;;;;;N;;;;; +1D90B;SIGNWRITING STRIKE SINGLE;So;0;L;;;;;N;;;;; +1D90C;SIGNWRITING STRIKE MULTIPLE;So;0;L;;;;;N;;;;; +1D90D;SIGNWRITING STRIKE BETWEEN;So;0;L;;;;;N;;;;; +1D90E;SIGNWRITING BRUSH SINGLE;So;0;L;;;;;N;;;;; +1D90F;SIGNWRITING BRUSH MULTIPLE;So;0;L;;;;;N;;;;; +1D910;SIGNWRITING BRUSH BETWEEN;So;0;L;;;;;N;;;;; +1D911;SIGNWRITING RUB SINGLE;So;0;L;;;;;N;;;;; +1D912;SIGNWRITING RUB MULTIPLE;So;0;L;;;;;N;;;;; +1D913;SIGNWRITING RUB BETWEEN;So;0;L;;;;;N;;;;; +1D914;SIGNWRITING SURFACE SYMBOLS;So;0;L;;;;;N;;;;; +1D915;SIGNWRITING SURFACE BETWEEN;So;0;L;;;;;N;;;;; +1D916;SIGNWRITING SQUEEZE LARGE SINGLE;So;0;L;;;;;N;;;;; +1D917;SIGNWRITING SQUEEZE SMALL SINGLE;So;0;L;;;;;N;;;;; +1D918;SIGNWRITING SQUEEZE LARGE MULTIPLE;So;0;L;;;;;N;;;;; +1D919;SIGNWRITING SQUEEZE SMALL MULTIPLE;So;0;L;;;;;N;;;;; +1D91A;SIGNWRITING SQUEEZE SEQUENTIAL;So;0;L;;;;;N;;;;; +1D91B;SIGNWRITING FLICK LARGE SINGLE;So;0;L;;;;;N;;;;; +1D91C;SIGNWRITING FLICK SMALL SINGLE;So;0;L;;;;;N;;;;; +1D91D;SIGNWRITING FLICK LARGE MULTIPLE;So;0;L;;;;;N;;;;; +1D91E;SIGNWRITING FLICK SMALL MULTIPLE;So;0;L;;;;;N;;;;; +1D91F;SIGNWRITING FLICK SEQUENTIAL;So;0;L;;;;;N;;;;; +1D920;SIGNWRITING SQUEEZE FLICK ALTERNATING;So;0;L;;;;;N;;;;; +1D921;SIGNWRITING MOVEMENT-HINGE UP DOWN LARGE;So;0;L;;;;;N;;;;; +1D922;SIGNWRITING MOVEMENT-HINGE UP DOWN SMALL;So;0;L;;;;;N;;;;; +1D923;SIGNWRITING MOVEMENT-HINGE UP SEQUENTIAL;So;0;L;;;;;N;;;;; +1D924;SIGNWRITING MOVEMENT-HINGE DOWN SEQUENTIAL;So;0;L;;;;;N;;;;; +1D925;SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING LARGE;So;0;L;;;;;N;;;;; +1D926;SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING SMALL;So;0;L;;;;;N;;;;; +1D927;SIGNWRITING MOVEMENT-HINGE SIDE TO SIDE SCISSORS;So;0;L;;;;;N;;;;; +1D928;SIGNWRITING MOVEMENT-WALLPLANE FINGER CONTACT;So;0;L;;;;;N;;;;; +1D929;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CONTACT;So;0;L;;;;;N;;;;; +1D92A;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT SMALL;So;0;L;;;;;N;;;;; +1D92B;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT MEDIUM;So;0;L;;;;;N;;;;; +1D92C;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGE;So;0;L;;;;;N;;;;; +1D92D;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGEST;So;0;L;;;;;N;;;;; +1D92E;SIGNWRITING MOVEMENT-WALLPLANE SINGLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D92F;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE STRAIGHT;So;0;L;;;;;N;;;;; +1D930;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D931;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING;So;0;L;;;;;N;;;;; +1D932;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; +1D933;SIGNWRITING MOVEMENT-WALLPLANE CROSS;So;0;L;;;;;N;;;;; +1D934;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE STRAIGHT MOVEMENT;So;0;L;;;;;N;;;;; +1D935;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D936;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING;So;0;L;;;;;N;;;;; +1D937;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; +1D938;SIGNWRITING MOVEMENT-WALLPLANE BEND SMALL;So;0;L;;;;;N;;;;; +1D939;SIGNWRITING MOVEMENT-WALLPLANE BEND MEDIUM;So;0;L;;;;;N;;;;; +1D93A;SIGNWRITING MOVEMENT-WALLPLANE BEND LARGE;So;0;L;;;;;N;;;;; +1D93B;SIGNWRITING MOVEMENT-WALLPLANE CORNER SMALL;So;0;L;;;;;N;;;;; +1D93C;SIGNWRITING MOVEMENT-WALLPLANE CORNER MEDIUM;So;0;L;;;;;N;;;;; +1D93D;SIGNWRITING MOVEMENT-WALLPLANE CORNER LARGE;So;0;L;;;;;N;;;;; +1D93E;SIGNWRITING MOVEMENT-WALLPLANE CORNER ROTATION;So;0;L;;;;;N;;;;; +1D93F;SIGNWRITING MOVEMENT-WALLPLANE CHECK SMALL;So;0;L;;;;;N;;;;; +1D940;SIGNWRITING MOVEMENT-WALLPLANE CHECK MEDIUM;So;0;L;;;;;N;;;;; +1D941;SIGNWRITING MOVEMENT-WALLPLANE CHECK LARGE;So;0;L;;;;;N;;;;; +1D942;SIGNWRITING MOVEMENT-WALLPLANE BOX SMALL;So;0;L;;;;;N;;;;; +1D943;SIGNWRITING MOVEMENT-WALLPLANE BOX MEDIUM;So;0;L;;;;;N;;;;; +1D944;SIGNWRITING MOVEMENT-WALLPLANE BOX LARGE;So;0;L;;;;;N;;;;; +1D945;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG SMALL;So;0;L;;;;;N;;;;; +1D946;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG MEDIUM;So;0;L;;;;;N;;;;; +1D947;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG LARGE;So;0;L;;;;;N;;;;; +1D948;SIGNWRITING MOVEMENT-WALLPLANE PEAKS SMALL;So;0;L;;;;;N;;;;; +1D949;SIGNWRITING MOVEMENT-WALLPLANE PEAKS MEDIUM;So;0;L;;;;;N;;;;; +1D94A;SIGNWRITING MOVEMENT-WALLPLANE PEAKS LARGE;So;0;L;;;;;N;;;;; +1D94B;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; +1D94C;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D94D;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D94E;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; +1D94F;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D950;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D951;SIGNWRITING TRAVEL-WALLPLANE SHAKING;So;0;L;;;;;N;;;;; +1D952;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL SINGLE;So;0;L;;;;;N;;;;; +1D953;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL DOUBLE;So;0;L;;;;;N;;;;; +1D954;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL TRIPLE;So;0;L;;;;;N;;;;; +1D955;SIGNWRITING MOVEMENT-DIAGONAL AWAY SMALL;So;0;L;;;;;N;;;;; +1D956;SIGNWRITING MOVEMENT-DIAGONAL AWAY MEDIUM;So;0;L;;;;;N;;;;; +1D957;SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGE;So;0;L;;;;;N;;;;; +1D958;SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGEST;So;0;L;;;;;N;;;;; +1D959;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS SMALL;So;0;L;;;;;N;;;;; +1D95A;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS MEDIUM;So;0;L;;;;;N;;;;; +1D95B;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGE;So;0;L;;;;;N;;;;; +1D95C;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGEST;So;0;L;;;;;N;;;;; +1D95D;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY SMALL;So;0;L;;;;;N;;;;; +1D95E;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY MEDIUM;So;0;L;;;;;N;;;;; +1D95F;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGE;So;0;L;;;;;N;;;;; +1D960;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGEST;So;0;L;;;;;N;;;;; +1D961;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS SMALL;So;0;L;;;;;N;;;;; +1D962;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS MEDIUM;So;0;L;;;;;N;;;;; +1D963;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGE;So;0;L;;;;;N;;;;; +1D964;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGEST;So;0;L;;;;;N;;;;; +1D965;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT SMALL;So;0;L;;;;;N;;;;; +1D966;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT MEDIUM;So;0;L;;;;;N;;;;; +1D967;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGE;So;0;L;;;;;N;;;;; +1D968;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGEST;So;0;L;;;;;N;;;;; +1D969;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D96A;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE STRAIGHT;So;0;L;;;;;N;;;;; +1D96B;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D96C;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING;So;0;L;;;;;N;;;;; +1D96D;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; +1D96E;SIGNWRITING MOVEMENT-FLOORPLANE CROSS;So;0;L;;;;;N;;;;; +1D96F;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE STRAIGHT MOVEMENT;So;0;L;;;;;N;;;;; +1D970;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D971;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING MOVEMENT;So;0;L;;;;;N;;;;; +1D972;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; +1D973;SIGNWRITING MOVEMENT-FLOORPLANE BEND;So;0;L;;;;;N;;;;; +1D974;SIGNWRITING MOVEMENT-FLOORPLANE CORNER SMALL;So;0;L;;;;;N;;;;; +1D975;SIGNWRITING MOVEMENT-FLOORPLANE CORNER MEDIUM;So;0;L;;;;;N;;;;; +1D976;SIGNWRITING MOVEMENT-FLOORPLANE CORNER LARGE;So;0;L;;;;;N;;;;; +1D977;SIGNWRITING MOVEMENT-FLOORPLANE CHECK;So;0;L;;;;;N;;;;; +1D978;SIGNWRITING MOVEMENT-FLOORPLANE BOX SMALL;So;0;L;;;;;N;;;;; +1D979;SIGNWRITING MOVEMENT-FLOORPLANE BOX MEDIUM;So;0;L;;;;;N;;;;; +1D97A;SIGNWRITING MOVEMENT-FLOORPLANE BOX LARGE;So;0;L;;;;;N;;;;; +1D97B;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG SMALL;So;0;L;;;;;N;;;;; +1D97C;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG MEDIUM;So;0;L;;;;;N;;;;; +1D97D;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG LARGE;So;0;L;;;;;N;;;;; +1D97E;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS SMALL;So;0;L;;;;;N;;;;; +1D97F;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS MEDIUM;So;0;L;;;;;N;;;;; +1D980;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS LARGE;So;0;L;;;;;N;;;;; +1D981;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; +1D982;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D983;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D984;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; +1D985;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D986;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D987;SIGNWRITING TRAVEL-FLOORPLANE SHAKING;So;0;L;;;;;N;;;;; +1D988;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER SMALL;So;0;L;;;;;N;;;;; +1D989;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER MEDIUM;So;0;L;;;;;N;;;;; +1D98A;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGE;So;0;L;;;;;N;;;;; +1D98B;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGEST;So;0;L;;;;;N;;;;; +1D98C;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE SMALL;So;0;L;;;;;N;;;;; +1D98D;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE MEDIUM;So;0;L;;;;;N;;;;; +1D98E;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGE;So;0;L;;;;;N;;;;; +1D98F;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGEST;So;0;L;;;;;N;;;;; +1D990;SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE SMALL;So;0;L;;;;;N;;;;; +1D991;SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE MEDIUM;So;0;L;;;;;N;;;;; +1D992;SIGNWRITING MOVEMENT-WALLPLANE HUMP SMALL;So;0;L;;;;;N;;;;; +1D993;SIGNWRITING MOVEMENT-WALLPLANE HUMP MEDIUM;So;0;L;;;;;N;;;;; +1D994;SIGNWRITING MOVEMENT-WALLPLANE HUMP LARGE;So;0;L;;;;;N;;;;; +1D995;SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL;So;0;L;;;;;N;;;;; +1D996;SIGNWRITING MOVEMENT-WALLPLANE LOOP MEDIUM;So;0;L;;;;;N;;;;; +1D997;SIGNWRITING MOVEMENT-WALLPLANE LOOP LARGE;So;0;L;;;;;N;;;;; +1D998;SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D999;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE SMALL;So;0;L;;;;;N;;;;; +1D99A;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE MEDIUM;So;0;L;;;;;N;;;;; +1D99B;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE LARGE;So;0;L;;;;;N;;;;; +1D99C;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE SMALL;So;0;L;;;;;N;;;;; +1D99D;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE MEDIUM;So;0;L;;;;;N;;;;; +1D99E;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE LARGE;So;0;L;;;;;N;;;;; +1D99F;SIGNWRITING MOVEMENT-WALLPLANE CURVE THEN STRAIGHT;So;0;L;;;;;N;;;;; +1D9A0;SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS SMALL;So;0;L;;;;;N;;;;; +1D9A1;SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS MEDIUM;So;0;L;;;;;N;;;;; +1D9A2;SIGNWRITING ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; +1D9A3;SIGNWRITING ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D9A4;SIGNWRITING ROTATION-WALLPLANE ALTERNATE;So;0;L;;;;;N;;;;; +1D9A5;SIGNWRITING MOVEMENT-WALLPLANE SHAKING;So;0;L;;;;;N;;;;; +1D9A6;SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9A7;SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9A8;SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9A9;SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9AA;SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9AB;SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9AC;SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9AD;SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING CHEST;So;0;L;;;;;N;;;;; +1D9AE;SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING CHEST;So;0;L;;;;;N;;;;; +1D9AF;SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B0;SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B1;SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B2;SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B3;SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B4;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH SMALL;So;0;L;;;;;N;;;;; +1D9B5;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH MEDIUM;So;0;L;;;;;N;;;;; +1D9B6;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH LARGE;So;0;L;;;;;N;;;;; +1D9B7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING SMALL;So;0;L;;;;;N;;;;; +1D9B8;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING LARGE;So;0;L;;;;;N;;;;; +1D9B9;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9BA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9BB;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL TRIPLE;So;0;L;;;;;N;;;;; +1D9BC;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE TRIPLE;So;0;L;;;;;N;;;;; +1D9BD;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL SINGLE;So;0;L;;;;;N;;;;; +1D9BE;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE SINGLE;So;0;L;;;;;N;;;;; +1D9BF;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9C0;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9C1;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING SMALL;So;0;L;;;;;N;;;;; +1D9C2;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING LARGE;So;0;L;;;;;N;;;;; +1D9C3;SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING CEILING;So;0;L;;;;;N;;;;; +1D9C4;SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING CEILING;So;0;L;;;;;N;;;;; +1D9C5;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING CEILING;So;0;L;;;;;N;;;;; +1D9C6;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR SMALL;So;0;L;;;;;N;;;;; +1D9C7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR LARGE;So;0;L;;;;;N;;;;; +1D9C8;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9C9;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9CA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE SMALL TRIPLE;So;0;L;;;;;N;;;;; +1D9CB;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE LARGE TRIPLE;So;0;L;;;;;N;;;;; +1D9CC;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL SINGLE;So;0;L;;;;;N;;;;; +1D9CD;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE SINGLE;So;0;L;;;;;N;;;;; +1D9CE;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9CF;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9D0;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR SMALL;So;0;L;;;;;N;;;;; +1D9D1;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR LARGE;So;0;L;;;;;N;;;;; +1D9D2;SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING FLOOR;So;0;L;;;;;N;;;;; +1D9D3;SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING FLOOR;So;0;L;;;;;N;;;;; +1D9D4;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING FLOOR;So;0;L;;;;;N;;;;; +1D9D5;SIGNWRITING MOVEMENT-FLOORPLANE CURVE SMALL;So;0;L;;;;;N;;;;; +1D9D6;SIGNWRITING MOVEMENT-FLOORPLANE CURVE MEDIUM;So;0;L;;;;;N;;;;; +1D9D7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGE;So;0;L;;;;;N;;;;; +1D9D8;SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGEST;So;0;L;;;;;N;;;;; +1D9D9;SIGNWRITING MOVEMENT-FLOORPLANE CURVE COMBINED;So;0;L;;;;;N;;;;; +1D9DA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP SMALL;So;0;L;;;;;N;;;;; +1D9DB;SIGNWRITING MOVEMENT-FLOORPLANE LOOP SMALL;So;0;L;;;;;N;;;;; +1D9DC;SIGNWRITING MOVEMENT-FLOORPLANE WAVE SNAKE;So;0;L;;;;;N;;;;; +1D9DD;SIGNWRITING MOVEMENT-FLOORPLANE WAVE SMALL;So;0;L;;;;;N;;;;; +1D9DE;SIGNWRITING MOVEMENT-FLOORPLANE WAVE LARGE;So;0;L;;;;;N;;;;; +1D9DF;SIGNWRITING ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; +1D9E0;SIGNWRITING ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D9E1;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D9E2;SIGNWRITING MOVEMENT-FLOORPLANE SHAKING PARALLEL;So;0;L;;;;;N;;;;; +1D9E3;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL SINGLE;So;0;L;;;;;N;;;;; +1D9E4;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM SINGLE;So;0;L;;;;;N;;;;; +1D9E5;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9E6;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM DOUBLE;So;0;L;;;;;N;;;;; +1D9E7;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL SINGLE;So;0;L;;;;;N;;;;; +1D9E8;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM SINGLE;So;0;L;;;;;N;;;;; +1D9E9;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE SINGLE;So;0;L;;;;;N;;;;; +1D9EA;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9EB;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM DOUBLE;So;0;L;;;;;N;;;;; +1D9EC;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9ED;SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT SINGLE;So;0;L;;;;;N;;;;; +1D9EE;SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT DOUBLE;So;0;L;;;;;N;;;;; +1D9EF;SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL SINGLE;So;0;L;;;;;N;;;;; +1D9F0;SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL DOUBLE;So;0;L;;;;;N;;;;; +1D9F1;SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES SINGLE;So;0;L;;;;;N;;;;; +1D9F2;SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES DOUBLE;So;0;L;;;;;N;;;;; +1D9F3;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL SINGLE;So;0;L;;;;;N;;;;; +1D9F4;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL DOUBLE;So;0;L;;;;;N;;;;; +1D9F5;SIGNWRITING DYNAMIC ARROWHEAD SMALL;So;0;L;;;;;N;;;;; +1D9F6;SIGNWRITING DYNAMIC ARROWHEAD LARGE;So;0;L;;;;;N;;;;; +1D9F7;SIGNWRITING DYNAMIC FAST;So;0;L;;;;;N;;;;; +1D9F8;SIGNWRITING DYNAMIC SLOW;So;0;L;;;;;N;;;;; +1D9F9;SIGNWRITING DYNAMIC TENSE;So;0;L;;;;;N;;;;; +1D9FA;SIGNWRITING DYNAMIC RELAXED;So;0;L;;;;;N;;;;; +1D9FB;SIGNWRITING DYNAMIC SIMULTANEOUS;So;0;L;;;;;N;;;;; +1D9FC;SIGNWRITING DYNAMIC SIMULTANEOUS ALTERNATING;So;0;L;;;;;N;;;;; +1D9FD;SIGNWRITING DYNAMIC EVERY OTHER TIME;So;0;L;;;;;N;;;;; +1D9FE;SIGNWRITING DYNAMIC GRADUAL;So;0;L;;;;;N;;;;; +1D9FF;SIGNWRITING HEAD;So;0;L;;;;;N;;;;; +1DA00;SIGNWRITING HEAD RIM;Mn;0;NSM;;;;;N;;;;; +1DA01;SIGNWRITING HEAD MOVEMENT-WALLPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; +1DA02;SIGNWRITING HEAD MOVEMENT-WALLPLANE TILT;Mn;0;NSM;;;;;N;;;;; +1DA03;SIGNWRITING HEAD MOVEMENT-FLOORPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; +1DA04;SIGNWRITING HEAD MOVEMENT-WALLPLANE CURVE;Mn;0;NSM;;;;;N;;;;; +1DA05;SIGNWRITING HEAD MOVEMENT-FLOORPLANE CURVE;Mn;0;NSM;;;;;N;;;;; +1DA06;SIGNWRITING HEAD MOVEMENT CIRCLE;Mn;0;NSM;;;;;N;;;;; +1DA07;SIGNWRITING FACE DIRECTION POSITION NOSE FORWARD TILTING;Mn;0;NSM;;;;;N;;;;; +1DA08;SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN;Mn;0;NSM;;;;;N;;;;; +1DA09;SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN TILTING;Mn;0;NSM;;;;;N;;;;; +1DA0A;SIGNWRITING EYEBROWS STRAIGHT UP;Mn;0;NSM;;;;;N;;;;; +1DA0B;SIGNWRITING EYEBROWS STRAIGHT NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA0C;SIGNWRITING EYEBROWS STRAIGHT DOWN;Mn;0;NSM;;;;;N;;;;; +1DA0D;SIGNWRITING DREAMY EYEBROWS NEUTRAL DOWN;Mn;0;NSM;;;;;N;;;;; +1DA0E;SIGNWRITING DREAMY EYEBROWS DOWN NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA0F;SIGNWRITING DREAMY EYEBROWS UP NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA10;SIGNWRITING DREAMY EYEBROWS NEUTRAL UP;Mn;0;NSM;;;;;N;;;;; +1DA11;SIGNWRITING FOREHEAD NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA12;SIGNWRITING FOREHEAD CONTACT;Mn;0;NSM;;;;;N;;;;; +1DA13;SIGNWRITING FOREHEAD WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA14;SIGNWRITING EYES OPEN;Mn;0;NSM;;;;;N;;;;; +1DA15;SIGNWRITING EYES SQUEEZED;Mn;0;NSM;;;;;N;;;;; +1DA16;SIGNWRITING EYES CLOSED;Mn;0;NSM;;;;;N;;;;; +1DA17;SIGNWRITING EYE BLINK SINGLE;Mn;0;NSM;;;;;N;;;;; +1DA18;SIGNWRITING EYE BLINK MULTIPLE;Mn;0;NSM;;;;;N;;;;; +1DA19;SIGNWRITING EYES HALF OPEN;Mn;0;NSM;;;;;N;;;;; +1DA1A;SIGNWRITING EYES WIDE OPEN;Mn;0;NSM;;;;;N;;;;; +1DA1B;SIGNWRITING EYES HALF CLOSED;Mn;0;NSM;;;;;N;;;;; +1DA1C;SIGNWRITING EYES WIDENING MOVEMENT;Mn;0;NSM;;;;;N;;;;; +1DA1D;SIGNWRITING EYE WINK;Mn;0;NSM;;;;;N;;;;; +1DA1E;SIGNWRITING EYELASHES UP;Mn;0;NSM;;;;;N;;;;; +1DA1F;SIGNWRITING EYELASHES DOWN;Mn;0;NSM;;;;;N;;;;; +1DA20;SIGNWRITING EYELASHES FLUTTERING;Mn;0;NSM;;;;;N;;;;; +1DA21;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; +1DA22;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT DOUBLE;Mn;0;NSM;;;;;N;;;;; +1DA23;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT ALTERNATING;Mn;0;NSM;;;;;N;;;;; +1DA24;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; +1DA25;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT DOUBLE;Mn;0;NSM;;;;;N;;;;; +1DA26;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT ALTERNATING;Mn;0;NSM;;;;;N;;;;; +1DA27;SIGNWRITING EYEGAZE-WALLPLANE CURVED;Mn;0;NSM;;;;;N;;;;; +1DA28;SIGNWRITING EYEGAZE-FLOORPLANE CURVED;Mn;0;NSM;;;;;N;;;;; +1DA29;SIGNWRITING EYEGAZE-WALLPLANE CIRCLING;Mn;0;NSM;;;;;N;;;;; +1DA2A;SIGNWRITING CHEEKS PUFFED;Mn;0;NSM;;;;;N;;;;; +1DA2B;SIGNWRITING CHEEKS NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA2C;SIGNWRITING CHEEKS SUCKED;Mn;0;NSM;;;;;N;;;;; +1DA2D;SIGNWRITING TENSE CHEEKS HIGH;Mn;0;NSM;;;;;N;;;;; +1DA2E;SIGNWRITING TENSE CHEEKS MIDDLE;Mn;0;NSM;;;;;N;;;;; +1DA2F;SIGNWRITING TENSE CHEEKS LOW;Mn;0;NSM;;;;;N;;;;; +1DA30;SIGNWRITING EARS;Mn;0;NSM;;;;;N;;;;; +1DA31;SIGNWRITING NOSE NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA32;SIGNWRITING NOSE CONTACT;Mn;0;NSM;;;;;N;;;;; +1DA33;SIGNWRITING NOSE WRINKLES;Mn;0;NSM;;;;;N;;;;; +1DA34;SIGNWRITING NOSE WIGGLES;Mn;0;NSM;;;;;N;;;;; +1DA35;SIGNWRITING AIR BLOWING OUT;Mn;0;NSM;;;;;N;;;;; +1DA36;SIGNWRITING AIR SUCKING IN;Mn;0;NSM;;;;;N;;;;; +1DA37;SIGNWRITING AIR BLOW SMALL ROTATIONS;So;0;L;;;;;N;;;;; +1DA38;SIGNWRITING AIR SUCK SMALL ROTATIONS;So;0;L;;;;;N;;;;; +1DA39;SIGNWRITING BREATH INHALE;So;0;L;;;;;N;;;;; +1DA3A;SIGNWRITING BREATH EXHALE;So;0;L;;;;;N;;;;; +1DA3B;SIGNWRITING MOUTH CLOSED NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA3C;SIGNWRITING MOUTH CLOSED FORWARD;Mn;0;NSM;;;;;N;;;;; +1DA3D;SIGNWRITING MOUTH CLOSED CONTACT;Mn;0;NSM;;;;;N;;;;; +1DA3E;SIGNWRITING MOUTH SMILE;Mn;0;NSM;;;;;N;;;;; +1DA3F;SIGNWRITING MOUTH SMILE WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA40;SIGNWRITING MOUTH SMILE OPEN;Mn;0;NSM;;;;;N;;;;; +1DA41;SIGNWRITING MOUTH FROWN;Mn;0;NSM;;;;;N;;;;; +1DA42;SIGNWRITING MOUTH FROWN WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA43;SIGNWRITING MOUTH FROWN OPEN;Mn;0;NSM;;;;;N;;;;; +1DA44;SIGNWRITING MOUTH OPEN CIRCLE;Mn;0;NSM;;;;;N;;;;; +1DA45;SIGNWRITING MOUTH OPEN FORWARD;Mn;0;NSM;;;;;N;;;;; +1DA46;SIGNWRITING MOUTH OPEN WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA47;SIGNWRITING MOUTH OPEN OVAL;Mn;0;NSM;;;;;N;;;;; +1DA48;SIGNWRITING MOUTH OPEN OVAL WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA49;SIGNWRITING MOUTH OPEN OVAL YAWN;Mn;0;NSM;;;;;N;;;;; +1DA4A;SIGNWRITING MOUTH OPEN RECTANGLE;Mn;0;NSM;;;;;N;;;;; +1DA4B;SIGNWRITING MOUTH OPEN RECTANGLE WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA4C;SIGNWRITING MOUTH OPEN RECTANGLE YAWN;Mn;0;NSM;;;;;N;;;;; +1DA4D;SIGNWRITING MOUTH KISS;Mn;0;NSM;;;;;N;;;;; +1DA4E;SIGNWRITING MOUTH KISS FORWARD;Mn;0;NSM;;;;;N;;;;; +1DA4F;SIGNWRITING MOUTH KISS WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA50;SIGNWRITING MOUTH TENSE;Mn;0;NSM;;;;;N;;;;; +1DA51;SIGNWRITING MOUTH TENSE FORWARD;Mn;0;NSM;;;;;N;;;;; +1DA52;SIGNWRITING MOUTH TENSE SUCKED;Mn;0;NSM;;;;;N;;;;; +1DA53;SIGNWRITING LIPS PRESSED TOGETHER;Mn;0;NSM;;;;;N;;;;; +1DA54;SIGNWRITING LIP LOWER OVER UPPER;Mn;0;NSM;;;;;N;;;;; +1DA55;SIGNWRITING LIP UPPER OVER LOWER;Mn;0;NSM;;;;;N;;;;; +1DA56;SIGNWRITING MOUTH CORNERS;Mn;0;NSM;;;;;N;;;;; +1DA57;SIGNWRITING MOUTH WRINKLES SINGLE;Mn;0;NSM;;;;;N;;;;; +1DA58;SIGNWRITING MOUTH WRINKLES DOUBLE;Mn;0;NSM;;;;;N;;;;; +1DA59;SIGNWRITING TONGUE STICKING OUT FAR;Mn;0;NSM;;;;;N;;;;; +1DA5A;SIGNWRITING TONGUE LICKING LIPS;Mn;0;NSM;;;;;N;;;;; +1DA5B;SIGNWRITING TONGUE TIP BETWEEN LIPS;Mn;0;NSM;;;;;N;;;;; +1DA5C;SIGNWRITING TONGUE TIP TOUCHING INSIDE MOUTH;Mn;0;NSM;;;;;N;;;;; +1DA5D;SIGNWRITING TONGUE INSIDE MOUTH RELAXED;Mn;0;NSM;;;;;N;;;;; +1DA5E;SIGNWRITING TONGUE MOVES AGAINST CHEEK;Mn;0;NSM;;;;;N;;;;; +1DA5F;SIGNWRITING TONGUE CENTRE STICKING OUT;Mn;0;NSM;;;;;N;;;;; +1DA60;SIGNWRITING TONGUE CENTRE INSIDE MOUTH;Mn;0;NSM;;;;;N;;;;; +1DA61;SIGNWRITING TEETH;Mn;0;NSM;;;;;N;;;;; +1DA62;SIGNWRITING TEETH MOVEMENT;Mn;0;NSM;;;;;N;;;;; +1DA63;SIGNWRITING TEETH ON TONGUE;Mn;0;NSM;;;;;N;;;;; +1DA64;SIGNWRITING TEETH ON TONGUE MOVEMENT;Mn;0;NSM;;;;;N;;;;; +1DA65;SIGNWRITING TEETH ON LIPS;Mn;0;NSM;;;;;N;;;;; +1DA66;SIGNWRITING TEETH ON LIPS MOVEMENT;Mn;0;NSM;;;;;N;;;;; +1DA67;SIGNWRITING TEETH BITE LIPS;Mn;0;NSM;;;;;N;;;;; +1DA68;SIGNWRITING MOVEMENT-WALLPLANE JAW;Mn;0;NSM;;;;;N;;;;; +1DA69;SIGNWRITING MOVEMENT-FLOORPLANE JAW;Mn;0;NSM;;;;;N;;;;; +1DA6A;SIGNWRITING NECK;Mn;0;NSM;;;;;N;;;;; +1DA6B;SIGNWRITING HAIR;Mn;0;NSM;;;;;N;;;;; +1DA6C;SIGNWRITING EXCITEMENT;Mn;0;NSM;;;;;N;;;;; +1DA6D;SIGNWRITING SHOULDER HIP SPINE;So;0;L;;;;;N;;;;; +1DA6E;SIGNWRITING SHOULDER HIP POSITIONS;So;0;L;;;;;N;;;;; +1DA6F;SIGNWRITING WALLPLANE SHOULDER HIP MOVE;So;0;L;;;;;N;;;;; +1DA70;SIGNWRITING FLOORPLANE SHOULDER HIP MOVE;So;0;L;;;;;N;;;;; +1DA71;SIGNWRITING SHOULDER TILTING FROM WAIST;So;0;L;;;;;N;;;;; +1DA72;SIGNWRITING TORSO-WALLPLANE STRAIGHT STRETCH;So;0;L;;;;;N;;;;; +1DA73;SIGNWRITING TORSO-WALLPLANE CURVED BEND;So;0;L;;;;;N;;;;; +1DA74;SIGNWRITING TORSO-FLOORPLANE TWISTING;So;0;L;;;;;N;;;;; +1DA75;SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS;Mn;0;NSM;;;;;N;;;;; +1DA76;SIGNWRITING LIMB COMBINATION;So;0;L;;;;;N;;;;; +1DA77;SIGNWRITING LIMB LENGTH-1;So;0;L;;;;;N;;;;; +1DA78;SIGNWRITING LIMB LENGTH-2;So;0;L;;;;;N;;;;; +1DA79;SIGNWRITING LIMB LENGTH-3;So;0;L;;;;;N;;;;; +1DA7A;SIGNWRITING LIMB LENGTH-4;So;0;L;;;;;N;;;;; +1DA7B;SIGNWRITING LIMB LENGTH-5;So;0;L;;;;;N;;;;; +1DA7C;SIGNWRITING LIMB LENGTH-6;So;0;L;;;;;N;;;;; +1DA7D;SIGNWRITING LIMB LENGTH-7;So;0;L;;;;;N;;;;; +1DA7E;SIGNWRITING FINGER;So;0;L;;;;;N;;;;; +1DA7F;SIGNWRITING LOCATION-WALLPLANE SPACE;So;0;L;;;;;N;;;;; +1DA80;SIGNWRITING LOCATION-FLOORPLANE SPACE;So;0;L;;;;;N;;;;; +1DA81;SIGNWRITING LOCATION HEIGHT;So;0;L;;;;;N;;;;; +1DA82;SIGNWRITING LOCATION WIDTH;So;0;L;;;;;N;;;;; +1DA83;SIGNWRITING LOCATION DEPTH;So;0;L;;;;;N;;;;; +1DA84;SIGNWRITING LOCATION HEAD NECK;Mn;0;NSM;;;;;N;;;;; +1DA85;SIGNWRITING LOCATION TORSO;So;0;L;;;;;N;;;;; +1DA86;SIGNWRITING LOCATION LIMBS DIGITS;So;0;L;;;;;N;;;;; +1DA87;SIGNWRITING COMMA;Po;0;L;;;;;N;;;;; +1DA88;SIGNWRITING FULL STOP;Po;0;L;;;;;N;;;;; +1DA89;SIGNWRITING SEMICOLON;Po;0;L;;;;;N;;;;; +1DA8A;SIGNWRITING COLON;Po;0;L;;;;;N;;;;; +1DA8B;SIGNWRITING PARENTHESIS;Po;0;L;;;;;N;;;;; +1DA9B;SIGNWRITING FILL MODIFIER-2;Mn;0;NSM;;;;;N;;;;; +1DA9C;SIGNWRITING FILL MODIFIER-3;Mn;0;NSM;;;;;N;;;;; +1DA9D;SIGNWRITING FILL MODIFIER-4;Mn;0;NSM;;;;;N;;;;; +1DA9E;SIGNWRITING FILL MODIFIER-5;Mn;0;NSM;;;;;N;;;;; +1DA9F;SIGNWRITING FILL MODIFIER-6;Mn;0;NSM;;;;;N;;;;; +1DAA1;SIGNWRITING ROTATION MODIFIER-2;Mn;0;NSM;;;;;N;;;;; +1DAA2;SIGNWRITING ROTATION MODIFIER-3;Mn;0;NSM;;;;;N;;;;; +1DAA3;SIGNWRITING ROTATION MODIFIER-4;Mn;0;NSM;;;;;N;;;;; +1DAA4;SIGNWRITING ROTATION MODIFIER-5;Mn;0;NSM;;;;;N;;;;; +1DAA5;SIGNWRITING ROTATION MODIFIER-6;Mn;0;NSM;;;;;N;;;;; +1DAA6;SIGNWRITING ROTATION MODIFIER-7;Mn;0;NSM;;;;;N;;;;; +1DAA7;SIGNWRITING ROTATION MODIFIER-8;Mn;0;NSM;;;;;N;;;;; +1DAA8;SIGNWRITING ROTATION MODIFIER-9;Mn;0;NSM;;;;;N;;;;; +1DAA9;SIGNWRITING ROTATION MODIFIER-10;Mn;0;NSM;;;;;N;;;;; +1DAAA;SIGNWRITING ROTATION MODIFIER-11;Mn;0;NSM;;;;;N;;;;; +1DAAB;SIGNWRITING ROTATION MODIFIER-12;Mn;0;NSM;;;;;N;;;;; +1DAAC;SIGNWRITING ROTATION MODIFIER-13;Mn;0;NSM;;;;;N;;;;; +1DAAD;SIGNWRITING ROTATION MODIFIER-14;Mn;0;NSM;;;;;N;;;;; +1DAAE;SIGNWRITING ROTATION MODIFIER-15;Mn;0;NSM;;;;;N;;;;; +1DAAF;SIGNWRITING ROTATION MODIFIER-16;Mn;0;NSM;;;;;N;;;;; +1E000;COMBINING GLAGOLITIC LETTER AZU;Mn;230;NSM;;;;;N;;;;; +1E001;COMBINING GLAGOLITIC LETTER BUKY;Mn;230;NSM;;;;;N;;;;; +1E002;COMBINING GLAGOLITIC LETTER VEDE;Mn;230;NSM;;;;;N;;;;; +1E003;COMBINING GLAGOLITIC LETTER GLAGOLI;Mn;230;NSM;;;;;N;;;;; +1E004;COMBINING GLAGOLITIC LETTER DOBRO;Mn;230;NSM;;;;;N;;;;; +1E005;COMBINING GLAGOLITIC LETTER YESTU;Mn;230;NSM;;;;;N;;;;; +1E006;COMBINING GLAGOLITIC LETTER ZHIVETE;Mn;230;NSM;;;;;N;;;;; +1E008;COMBINING GLAGOLITIC LETTER ZEMLJA;Mn;230;NSM;;;;;N;;;;; +1E009;COMBINING GLAGOLITIC LETTER IZHE;Mn;230;NSM;;;;;N;;;;; +1E00A;COMBINING GLAGOLITIC LETTER INITIAL IZHE;Mn;230;NSM;;;;;N;;;;; +1E00B;COMBINING GLAGOLITIC LETTER I;Mn;230;NSM;;;;;N;;;;; +1E00C;COMBINING GLAGOLITIC LETTER DJERVI;Mn;230;NSM;;;;;N;;;;; +1E00D;COMBINING GLAGOLITIC LETTER KAKO;Mn;230;NSM;;;;;N;;;;; +1E00E;COMBINING GLAGOLITIC LETTER LJUDIJE;Mn;230;NSM;;;;;N;;;;; +1E00F;COMBINING GLAGOLITIC LETTER MYSLITE;Mn;230;NSM;;;;;N;;;;; +1E010;COMBINING GLAGOLITIC LETTER NASHI;Mn;230;NSM;;;;;N;;;;; +1E011;COMBINING GLAGOLITIC LETTER ONU;Mn;230;NSM;;;;;N;;;;; +1E012;COMBINING GLAGOLITIC LETTER POKOJI;Mn;230;NSM;;;;;N;;;;; +1E013;COMBINING GLAGOLITIC LETTER RITSI;Mn;230;NSM;;;;;N;;;;; +1E014;COMBINING GLAGOLITIC LETTER SLOVO;Mn;230;NSM;;;;;N;;;;; +1E015;COMBINING GLAGOLITIC LETTER TVRIDO;Mn;230;NSM;;;;;N;;;;; +1E016;COMBINING GLAGOLITIC LETTER UKU;Mn;230;NSM;;;;;N;;;;; +1E017;COMBINING GLAGOLITIC LETTER FRITU;Mn;230;NSM;;;;;N;;;;; +1E018;COMBINING GLAGOLITIC LETTER HERU;Mn;230;NSM;;;;;N;;;;; +1E01B;COMBINING GLAGOLITIC LETTER SHTA;Mn;230;NSM;;;;;N;;;;; +1E01C;COMBINING GLAGOLITIC LETTER TSI;Mn;230;NSM;;;;;N;;;;; +1E01D;COMBINING GLAGOLITIC LETTER CHRIVI;Mn;230;NSM;;;;;N;;;;; +1E01E;COMBINING GLAGOLITIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; +1E01F;COMBINING GLAGOLITIC LETTER YERU;Mn;230;NSM;;;;;N;;;;; +1E020;COMBINING GLAGOLITIC LETTER YERI;Mn;230;NSM;;;;;N;;;;; +1E021;COMBINING GLAGOLITIC LETTER YATI;Mn;230;NSM;;;;;N;;;;; +1E023;COMBINING GLAGOLITIC LETTER YU;Mn;230;NSM;;;;;N;;;;; +1E024;COMBINING GLAGOLITIC LETTER SMALL YUS;Mn;230;NSM;;;;;N;;;;; +1E026;COMBINING GLAGOLITIC LETTER YO;Mn;230;NSM;;;;;N;;;;; +1E027;COMBINING GLAGOLITIC LETTER IOTATED SMALL YUS;Mn;230;NSM;;;;;N;;;;; +1E028;COMBINING GLAGOLITIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; +1E029;COMBINING GLAGOLITIC LETTER IOTATED BIG YUS;Mn;230;NSM;;;;;N;;;;; +1E02A;COMBINING GLAGOLITIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; +1E800;MENDE KIKAKUI SYLLABLE M001 KI;Lo;0;R;;;;;N;;;;; +1E801;MENDE KIKAKUI SYLLABLE M002 KA;Lo;0;R;;;;;N;;;;; +1E802;MENDE KIKAKUI SYLLABLE M003 KU;Lo;0;R;;;;;N;;;;; +1E803;MENDE KIKAKUI SYLLABLE M065 KEE;Lo;0;R;;;;;N;;;;; +1E804;MENDE KIKAKUI SYLLABLE M095 KE;Lo;0;R;;;;;N;;;;; +1E805;MENDE KIKAKUI SYLLABLE M076 KOO;Lo;0;R;;;;;N;;;;; +1E806;MENDE KIKAKUI SYLLABLE M048 KO;Lo;0;R;;;;;N;;;;; +1E807;MENDE KIKAKUI SYLLABLE M179 KUA;Lo;0;R;;;;;N;;;;; +1E808;MENDE KIKAKUI SYLLABLE M004 WI;Lo;0;R;;;;;N;;;;; +1E809;MENDE KIKAKUI SYLLABLE M005 WA;Lo;0;R;;;;;N;;;;; +1E80A;MENDE KIKAKUI SYLLABLE M006 WU;Lo;0;R;;;;;N;;;;; +1E80B;MENDE KIKAKUI SYLLABLE M126 WEE;Lo;0;R;;;;;N;;;;; +1E80C;MENDE KIKAKUI SYLLABLE M118 WE;Lo;0;R;;;;;N;;;;; +1E80D;MENDE KIKAKUI SYLLABLE M114 WOO;Lo;0;R;;;;;N;;;;; +1E80E;MENDE KIKAKUI SYLLABLE M045 WO;Lo;0;R;;;;;N;;;;; +1E80F;MENDE KIKAKUI SYLLABLE M194 WUI;Lo;0;R;;;;;N;;;;; +1E810;MENDE KIKAKUI SYLLABLE M143 WEI;Lo;0;R;;;;;N;;;;; +1E811;MENDE KIKAKUI SYLLABLE M061 WVI;Lo;0;R;;;;;N;;;;; +1E812;MENDE KIKAKUI SYLLABLE M049 WVA;Lo;0;R;;;;;N;;;;; +1E813;MENDE KIKAKUI SYLLABLE M139 WVE;Lo;0;R;;;;;N;;;;; +1E814;MENDE KIKAKUI SYLLABLE M007 MIN;Lo;0;R;;;;;N;;;;; +1E815;MENDE KIKAKUI SYLLABLE M008 MAN;Lo;0;R;;;;;N;;;;; +1E816;MENDE KIKAKUI SYLLABLE M009 MUN;Lo;0;R;;;;;N;;;;; +1E817;MENDE KIKAKUI SYLLABLE M059 MEN;Lo;0;R;;;;;N;;;;; +1E818;MENDE KIKAKUI SYLLABLE M094 MON;Lo;0;R;;;;;N;;;;; +1E819;MENDE KIKAKUI SYLLABLE M154 MUAN;Lo;0;R;;;;;N;;;;; +1E81A;MENDE KIKAKUI SYLLABLE M189 MUEN;Lo;0;R;;;;;N;;;;; +1E81B;MENDE KIKAKUI SYLLABLE M010 BI;Lo;0;R;;;;;N;;;;; +1E81C;MENDE KIKAKUI SYLLABLE M011 BA;Lo;0;R;;;;;N;;;;; +1E81D;MENDE KIKAKUI SYLLABLE M012 BU;Lo;0;R;;;;;N;;;;; +1E81E;MENDE KIKAKUI SYLLABLE M150 BEE;Lo;0;R;;;;;N;;;;; +1E81F;MENDE KIKAKUI SYLLABLE M097 BE;Lo;0;R;;;;;N;;;;; +1E820;MENDE KIKAKUI SYLLABLE M103 BOO;Lo;0;R;;;;;N;;;;; +1E821;MENDE KIKAKUI SYLLABLE M138 BO;Lo;0;R;;;;;N;;;;; +1E822;MENDE KIKAKUI SYLLABLE M013 I;Lo;0;R;;;;;N;;;;; +1E823;MENDE KIKAKUI SYLLABLE M014 A;Lo;0;R;;;;;N;;;;; +1E824;MENDE KIKAKUI SYLLABLE M015 U;Lo;0;R;;;;;N;;;;; +1E825;MENDE KIKAKUI SYLLABLE M163 EE;Lo;0;R;;;;;N;;;;; +1E826;MENDE KIKAKUI SYLLABLE M100 E;Lo;0;R;;;;;N;;;;; +1E827;MENDE KIKAKUI SYLLABLE M165 OO;Lo;0;R;;;;;N;;;;; +1E828;MENDE KIKAKUI SYLLABLE M147 O;Lo;0;R;;;;;N;;;;; +1E829;MENDE KIKAKUI SYLLABLE M137 EI;Lo;0;R;;;;;N;;;;; +1E82A;MENDE KIKAKUI SYLLABLE M131 IN;Lo;0;R;;;;;N;;;;; +1E82B;MENDE KIKAKUI SYLLABLE M135 IN;Lo;0;R;;;;;N;;;;; +1E82C;MENDE KIKAKUI SYLLABLE M195 AN;Lo;0;R;;;;;N;;;;; +1E82D;MENDE KIKAKUI SYLLABLE M178 EN;Lo;0;R;;;;;N;;;;; +1E82E;MENDE KIKAKUI SYLLABLE M019 SI;Lo;0;R;;;;;N;;;;; +1E82F;MENDE KIKAKUI SYLLABLE M020 SA;Lo;0;R;;;;;N;;;;; +1E830;MENDE KIKAKUI SYLLABLE M021 SU;Lo;0;R;;;;;N;;;;; +1E831;MENDE KIKAKUI SYLLABLE M162 SEE;Lo;0;R;;;;;N;;;;; +1E832;MENDE KIKAKUI SYLLABLE M116 SE;Lo;0;R;;;;;N;;;;; +1E833;MENDE KIKAKUI SYLLABLE M136 SOO;Lo;0;R;;;;;N;;;;; +1E834;MENDE KIKAKUI SYLLABLE M079 SO;Lo;0;R;;;;;N;;;;; +1E835;MENDE KIKAKUI SYLLABLE M196 SIA;Lo;0;R;;;;;N;;;;; +1E836;MENDE KIKAKUI SYLLABLE M025 LI;Lo;0;R;;;;;N;;;;; +1E837;MENDE KIKAKUI SYLLABLE M026 LA;Lo;0;R;;;;;N;;;;; +1E838;MENDE KIKAKUI SYLLABLE M027 LU;Lo;0;R;;;;;N;;;;; +1E839;MENDE KIKAKUI SYLLABLE M084 LEE;Lo;0;R;;;;;N;;;;; +1E83A;MENDE KIKAKUI SYLLABLE M073 LE;Lo;0;R;;;;;N;;;;; +1E83B;MENDE KIKAKUI SYLLABLE M054 LOO;Lo;0;R;;;;;N;;;;; +1E83C;MENDE KIKAKUI SYLLABLE M153 LO;Lo;0;R;;;;;N;;;;; +1E83D;MENDE KIKAKUI SYLLABLE M110 LONG LE;Lo;0;R;;;;;N;;;;; +1E83E;MENDE KIKAKUI SYLLABLE M016 DI;Lo;0;R;;;;;N;;;;; +1E83F;MENDE KIKAKUI SYLLABLE M017 DA;Lo;0;R;;;;;N;;;;; +1E840;MENDE KIKAKUI SYLLABLE M018 DU;Lo;0;R;;;;;N;;;;; +1E841;MENDE KIKAKUI SYLLABLE M089 DEE;Lo;0;R;;;;;N;;;;; +1E842;MENDE KIKAKUI SYLLABLE M180 DOO;Lo;0;R;;;;;N;;;;; +1E843;MENDE KIKAKUI SYLLABLE M181 DO;Lo;0;R;;;;;N;;;;; +1E844;MENDE KIKAKUI SYLLABLE M022 TI;Lo;0;R;;;;;N;;;;; +1E845;MENDE KIKAKUI SYLLABLE M023 TA;Lo;0;R;;;;;N;;;;; +1E846;MENDE KIKAKUI SYLLABLE M024 TU;Lo;0;R;;;;;N;;;;; +1E847;MENDE KIKAKUI SYLLABLE M091 TEE;Lo;0;R;;;;;N;;;;; +1E848;MENDE KIKAKUI SYLLABLE M055 TE;Lo;0;R;;;;;N;;;;; +1E849;MENDE KIKAKUI SYLLABLE M104 TOO;Lo;0;R;;;;;N;;;;; +1E84A;MENDE KIKAKUI SYLLABLE M069 TO;Lo;0;R;;;;;N;;;;; +1E84B;MENDE KIKAKUI SYLLABLE M028 JI;Lo;0;R;;;;;N;;;;; +1E84C;MENDE KIKAKUI SYLLABLE M029 JA;Lo;0;R;;;;;N;;;;; +1E84D;MENDE KIKAKUI SYLLABLE M030 JU;Lo;0;R;;;;;N;;;;; +1E84E;MENDE KIKAKUI SYLLABLE M157 JEE;Lo;0;R;;;;;N;;;;; +1E84F;MENDE KIKAKUI SYLLABLE M113 JE;Lo;0;R;;;;;N;;;;; +1E850;MENDE KIKAKUI SYLLABLE M160 JOO;Lo;0;R;;;;;N;;;;; +1E851;MENDE KIKAKUI SYLLABLE M063 JO;Lo;0;R;;;;;N;;;;; +1E852;MENDE KIKAKUI SYLLABLE M175 LONG JO;Lo;0;R;;;;;N;;;;; +1E853;MENDE KIKAKUI SYLLABLE M031 YI;Lo;0;R;;;;;N;;;;; +1E854;MENDE KIKAKUI SYLLABLE M032 YA;Lo;0;R;;;;;N;;;;; +1E855;MENDE KIKAKUI SYLLABLE M033 YU;Lo;0;R;;;;;N;;;;; +1E856;MENDE KIKAKUI SYLLABLE M109 YEE;Lo;0;R;;;;;N;;;;; +1E857;MENDE KIKAKUI SYLLABLE M080 YE;Lo;0;R;;;;;N;;;;; +1E858;MENDE KIKAKUI SYLLABLE M141 YOO;Lo;0;R;;;;;N;;;;; +1E859;MENDE KIKAKUI SYLLABLE M121 YO;Lo;0;R;;;;;N;;;;; +1E85A;MENDE KIKAKUI SYLLABLE M034 FI;Lo;0;R;;;;;N;;;;; +1E85B;MENDE KIKAKUI SYLLABLE M035 FA;Lo;0;R;;;;;N;;;;; +1E85C;MENDE KIKAKUI SYLLABLE M036 FU;Lo;0;R;;;;;N;;;;; +1E85D;MENDE KIKAKUI SYLLABLE M078 FEE;Lo;0;R;;;;;N;;;;; +1E85E;MENDE KIKAKUI SYLLABLE M075 FE;Lo;0;R;;;;;N;;;;; +1E85F;MENDE KIKAKUI SYLLABLE M133 FOO;Lo;0;R;;;;;N;;;;; +1E860;MENDE KIKAKUI SYLLABLE M088 FO;Lo;0;R;;;;;N;;;;; +1E861;MENDE KIKAKUI SYLLABLE M197 FUA;Lo;0;R;;;;;N;;;;; +1E862;MENDE KIKAKUI SYLLABLE M101 FAN;Lo;0;R;;;;;N;;;;; +1E863;MENDE KIKAKUI SYLLABLE M037 NIN;Lo;0;R;;;;;N;;;;; +1E864;MENDE KIKAKUI SYLLABLE M038 NAN;Lo;0;R;;;;;N;;;;; +1E865;MENDE KIKAKUI SYLLABLE M039 NUN;Lo;0;R;;;;;N;;;;; +1E866;MENDE KIKAKUI SYLLABLE M117 NEN;Lo;0;R;;;;;N;;;;; +1E867;MENDE KIKAKUI SYLLABLE M169 NON;Lo;0;R;;;;;N;;;;; +1E868;MENDE KIKAKUI SYLLABLE M176 HI;Lo;0;R;;;;;N;;;;; +1E869;MENDE KIKAKUI SYLLABLE M041 HA;Lo;0;R;;;;;N;;;;; +1E86A;MENDE KIKAKUI SYLLABLE M186 HU;Lo;0;R;;;;;N;;;;; +1E86B;MENDE KIKAKUI SYLLABLE M040 HEE;Lo;0;R;;;;;N;;;;; +1E86C;MENDE KIKAKUI SYLLABLE M096 HE;Lo;0;R;;;;;N;;;;; +1E86D;MENDE KIKAKUI SYLLABLE M042 HOO;Lo;0;R;;;;;N;;;;; +1E86E;MENDE KIKAKUI SYLLABLE M140 HO;Lo;0;R;;;;;N;;;;; +1E86F;MENDE KIKAKUI SYLLABLE M083 HEEI;Lo;0;R;;;;;N;;;;; +1E870;MENDE KIKAKUI SYLLABLE M128 HOOU;Lo;0;R;;;;;N;;;;; +1E871;MENDE KIKAKUI SYLLABLE M053 HIN;Lo;0;R;;;;;N;;;;; +1E872;MENDE KIKAKUI SYLLABLE M130 HAN;Lo;0;R;;;;;N;;;;; +1E873;MENDE KIKAKUI SYLLABLE M087 HUN;Lo;0;R;;;;;N;;;;; +1E874;MENDE KIKAKUI SYLLABLE M052 HEN;Lo;0;R;;;;;N;;;;; +1E875;MENDE KIKAKUI SYLLABLE M193 HON;Lo;0;R;;;;;N;;;;; +1E876;MENDE KIKAKUI SYLLABLE M046 HUAN;Lo;0;R;;;;;N;;;;; +1E877;MENDE KIKAKUI SYLLABLE M090 NGGI;Lo;0;R;;;;;N;;;;; +1E878;MENDE KIKAKUI SYLLABLE M043 NGGA;Lo;0;R;;;;;N;;;;; +1E879;MENDE KIKAKUI SYLLABLE M082 NGGU;Lo;0;R;;;;;N;;;;; +1E87A;MENDE KIKAKUI SYLLABLE M115 NGGEE;Lo;0;R;;;;;N;;;;; +1E87B;MENDE KIKAKUI SYLLABLE M146 NGGE;Lo;0;R;;;;;N;;;;; +1E87C;MENDE KIKAKUI SYLLABLE M156 NGGOO;Lo;0;R;;;;;N;;;;; +1E87D;MENDE KIKAKUI SYLLABLE M120 NGGO;Lo;0;R;;;;;N;;;;; +1E87E;MENDE KIKAKUI SYLLABLE M159 NGGAA;Lo;0;R;;;;;N;;;;; +1E87F;MENDE KIKAKUI SYLLABLE M127 NGGUA;Lo;0;R;;;;;N;;;;; +1E880;MENDE KIKAKUI SYLLABLE M086 LONG NGGE;Lo;0;R;;;;;N;;;;; +1E881;MENDE KIKAKUI SYLLABLE M106 LONG NGGOO;Lo;0;R;;;;;N;;;;; +1E882;MENDE KIKAKUI SYLLABLE M183 LONG NGGO;Lo;0;R;;;;;N;;;;; +1E883;MENDE KIKAKUI SYLLABLE M155 GI;Lo;0;R;;;;;N;;;;; +1E884;MENDE KIKAKUI SYLLABLE M111 GA;Lo;0;R;;;;;N;;;;; +1E885;MENDE KIKAKUI SYLLABLE M168 GU;Lo;0;R;;;;;N;;;;; +1E886;MENDE KIKAKUI SYLLABLE M190 GEE;Lo;0;R;;;;;N;;;;; +1E887;MENDE KIKAKUI SYLLABLE M166 GUEI;Lo;0;R;;;;;N;;;;; +1E888;MENDE KIKAKUI SYLLABLE M167 GUAN;Lo;0;R;;;;;N;;;;; +1E889;MENDE KIKAKUI SYLLABLE M184 NGEN;Lo;0;R;;;;;N;;;;; +1E88A;MENDE KIKAKUI SYLLABLE M057 NGON;Lo;0;R;;;;;N;;;;; +1E88B;MENDE KIKAKUI SYLLABLE M177 NGUAN;Lo;0;R;;;;;N;;;;; +1E88C;MENDE KIKAKUI SYLLABLE M068 PI;Lo;0;R;;;;;N;;;;; +1E88D;MENDE KIKAKUI SYLLABLE M099 PA;Lo;0;R;;;;;N;;;;; +1E88E;MENDE KIKAKUI SYLLABLE M050 PU;Lo;0;R;;;;;N;;;;; +1E88F;MENDE KIKAKUI SYLLABLE M081 PEE;Lo;0;R;;;;;N;;;;; +1E890;MENDE KIKAKUI SYLLABLE M051 PE;Lo;0;R;;;;;N;;;;; +1E891;MENDE KIKAKUI SYLLABLE M102 POO;Lo;0;R;;;;;N;;;;; +1E892;MENDE KIKAKUI SYLLABLE M066 PO;Lo;0;R;;;;;N;;;;; +1E893;MENDE KIKAKUI SYLLABLE M145 MBI;Lo;0;R;;;;;N;;;;; +1E894;MENDE KIKAKUI SYLLABLE M062 MBA;Lo;0;R;;;;;N;;;;; +1E895;MENDE KIKAKUI SYLLABLE M122 MBU;Lo;0;R;;;;;N;;;;; +1E896;MENDE KIKAKUI SYLLABLE M047 MBEE;Lo;0;R;;;;;N;;;;; +1E897;MENDE KIKAKUI SYLLABLE M188 MBEE;Lo;0;R;;;;;N;;;;; +1E898;MENDE KIKAKUI SYLLABLE M072 MBE;Lo;0;R;;;;;N;;;;; +1E899;MENDE KIKAKUI SYLLABLE M172 MBOO;Lo;0;R;;;;;N;;;;; +1E89A;MENDE KIKAKUI SYLLABLE M174 MBO;Lo;0;R;;;;;N;;;;; +1E89B;MENDE KIKAKUI SYLLABLE M187 MBUU;Lo;0;R;;;;;N;;;;; +1E89C;MENDE KIKAKUI SYLLABLE M161 LONG MBE;Lo;0;R;;;;;N;;;;; +1E89D;MENDE KIKAKUI SYLLABLE M105 LONG MBOO;Lo;0;R;;;;;N;;;;; +1E89E;MENDE KIKAKUI SYLLABLE M142 LONG MBO;Lo;0;R;;;;;N;;;;; +1E89F;MENDE KIKAKUI SYLLABLE M132 KPI;Lo;0;R;;;;;N;;;;; +1E8A0;MENDE KIKAKUI SYLLABLE M092 KPA;Lo;0;R;;;;;N;;;;; +1E8A1;MENDE KIKAKUI SYLLABLE M074 KPU;Lo;0;R;;;;;N;;;;; +1E8A2;MENDE KIKAKUI SYLLABLE M044 KPEE;Lo;0;R;;;;;N;;;;; +1E8A3;MENDE KIKAKUI SYLLABLE M108 KPE;Lo;0;R;;;;;N;;;;; +1E8A4;MENDE KIKAKUI SYLLABLE M112 KPOO;Lo;0;R;;;;;N;;;;; +1E8A5;MENDE KIKAKUI SYLLABLE M158 KPO;Lo;0;R;;;;;N;;;;; +1E8A6;MENDE KIKAKUI SYLLABLE M124 GBI;Lo;0;R;;;;;N;;;;; +1E8A7;MENDE KIKAKUI SYLLABLE M056 GBA;Lo;0;R;;;;;N;;;;; +1E8A8;MENDE KIKAKUI SYLLABLE M148 GBU;Lo;0;R;;;;;N;;;;; +1E8A9;MENDE KIKAKUI SYLLABLE M093 GBEE;Lo;0;R;;;;;N;;;;; +1E8AA;MENDE KIKAKUI SYLLABLE M107 GBE;Lo;0;R;;;;;N;;;;; +1E8AB;MENDE KIKAKUI SYLLABLE M071 GBOO;Lo;0;R;;;;;N;;;;; +1E8AC;MENDE KIKAKUI SYLLABLE M070 GBO;Lo;0;R;;;;;N;;;;; +1E8AD;MENDE KIKAKUI SYLLABLE M171 RA;Lo;0;R;;;;;N;;;;; +1E8AE;MENDE KIKAKUI SYLLABLE M123 NDI;Lo;0;R;;;;;N;;;;; +1E8AF;MENDE KIKAKUI SYLLABLE M129 NDA;Lo;0;R;;;;;N;;;;; +1E8B0;MENDE KIKAKUI SYLLABLE M125 NDU;Lo;0;R;;;;;N;;;;; +1E8B1;MENDE KIKAKUI SYLLABLE M191 NDEE;Lo;0;R;;;;;N;;;;; +1E8B2;MENDE KIKAKUI SYLLABLE M119 NDE;Lo;0;R;;;;;N;;;;; +1E8B3;MENDE KIKAKUI SYLLABLE M067 NDOO;Lo;0;R;;;;;N;;;;; +1E8B4;MENDE KIKAKUI SYLLABLE M064 NDO;Lo;0;R;;;;;N;;;;; +1E8B5;MENDE KIKAKUI SYLLABLE M152 NJA;Lo;0;R;;;;;N;;;;; +1E8B6;MENDE KIKAKUI SYLLABLE M192 NJU;Lo;0;R;;;;;N;;;;; +1E8B7;MENDE KIKAKUI SYLLABLE M149 NJEE;Lo;0;R;;;;;N;;;;; +1E8B8;MENDE KIKAKUI SYLLABLE M134 NJOO;Lo;0;R;;;;;N;;;;; +1E8B9;MENDE KIKAKUI SYLLABLE M182 VI;Lo;0;R;;;;;N;;;;; +1E8BA;MENDE KIKAKUI SYLLABLE M185 VA;Lo;0;R;;;;;N;;;;; +1E8BB;MENDE KIKAKUI SYLLABLE M151 VU;Lo;0;R;;;;;N;;;;; +1E8BC;MENDE KIKAKUI SYLLABLE M173 VEE;Lo;0;R;;;;;N;;;;; +1E8BD;MENDE KIKAKUI SYLLABLE M085 VE;Lo;0;R;;;;;N;;;;; +1E8BE;MENDE KIKAKUI SYLLABLE M144 VOO;Lo;0;R;;;;;N;;;;; +1E8BF;MENDE KIKAKUI SYLLABLE M077 VO;Lo;0;R;;;;;N;;;;; +1E8C0;MENDE KIKAKUI SYLLABLE M164 NYIN;Lo;0;R;;;;;N;;;;; +1E8C1;MENDE KIKAKUI SYLLABLE M058 NYAN;Lo;0;R;;;;;N;;;;; +1E8C2;MENDE KIKAKUI SYLLABLE M170 NYUN;Lo;0;R;;;;;N;;;;; +1E8C3;MENDE KIKAKUI SYLLABLE M098 NYEN;Lo;0;R;;;;;N;;;;; +1E8C4;MENDE KIKAKUI SYLLABLE M060 NYON;Lo;0;R;;;;;N;;;;; +1E8C7;MENDE KIKAKUI DIGIT ONE;No;0;R;;;;1;N;;;;; +1E8C8;MENDE KIKAKUI DIGIT TWO;No;0;R;;;;2;N;;;;; +1E8C9;MENDE KIKAKUI DIGIT THREE;No;0;R;;;;3;N;;;;; +1E8CA;MENDE KIKAKUI DIGIT FOUR;No;0;R;;;;4;N;;;;; +1E8CB;MENDE KIKAKUI DIGIT FIVE;No;0;R;;;;5;N;;;;; +1E8CC;MENDE KIKAKUI DIGIT SIX;No;0;R;;;;6;N;;;;; +1E8CD;MENDE KIKAKUI DIGIT SEVEN;No;0;R;;;;7;N;;;;; +1E8CE;MENDE KIKAKUI DIGIT EIGHT;No;0;R;;;;8;N;;;;; +1E8CF;MENDE KIKAKUI DIGIT NINE;No;0;R;;;;9;N;;;;; +1E8D0;MENDE KIKAKUI COMBINING NUMBER TEENS;Mn;220;NSM;;;;;N;;;;; +1E8D1;MENDE KIKAKUI COMBINING NUMBER TENS;Mn;220;NSM;;;;;N;;;;; +1E8D2;MENDE KIKAKUI COMBINING NUMBER HUNDREDS;Mn;220;NSM;;;;;N;;;;; +1E8D3;MENDE KIKAKUI COMBINING NUMBER THOUSANDS;Mn;220;NSM;;;;;N;;;;; +1E8D4;MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS;Mn;220;NSM;;;;;N;;;;; +1E8D5;MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS;Mn;220;NSM;;;;;N;;;;; +1E8D6;MENDE KIKAKUI COMBINING NUMBER MILLIONS;Mn;220;NSM;;;;;N;;;;; +1E900;ADLAM CAPITAL LETTER ALIF;Lu;0;R;;;;;N;;;;1E922; +1E901;ADLAM CAPITAL LETTER DAALI;Lu;0;R;;;;;N;;;;1E923; +1E902;ADLAM CAPITAL LETTER LAAM;Lu;0;R;;;;;N;;;;1E924; +1E903;ADLAM CAPITAL LETTER MIIM;Lu;0;R;;;;;N;;;;1E925; +1E904;ADLAM CAPITAL LETTER BA;Lu;0;R;;;;;N;;;;1E926; +1E905;ADLAM CAPITAL LETTER SINNYIIYHE;Lu;0;R;;;;;N;;;;1E927; +1E906;ADLAM CAPITAL LETTER PE;Lu;0;R;;;;;N;;;;1E928; +1E907;ADLAM CAPITAL LETTER BHE;Lu;0;R;;;;;N;;;;1E929; +1E908;ADLAM CAPITAL LETTER RA;Lu;0;R;;;;;N;;;;1E92A; +1E909;ADLAM CAPITAL LETTER E;Lu;0;R;;;;;N;;;;1E92B; +1E90A;ADLAM CAPITAL LETTER FA;Lu;0;R;;;;;N;;;;1E92C; +1E90B;ADLAM CAPITAL LETTER I;Lu;0;R;;;;;N;;;;1E92D; +1E90C;ADLAM CAPITAL LETTER O;Lu;0;R;;;;;N;;;;1E92E; +1E90D;ADLAM CAPITAL LETTER DHA;Lu;0;R;;;;;N;;;;1E92F; +1E90E;ADLAM CAPITAL LETTER YHE;Lu;0;R;;;;;N;;;;1E930; +1E90F;ADLAM CAPITAL LETTER WAW;Lu;0;R;;;;;N;;;;1E931; +1E910;ADLAM CAPITAL LETTER NUN;Lu;0;R;;;;;N;;;;1E932; +1E911;ADLAM CAPITAL LETTER KAF;Lu;0;R;;;;;N;;;;1E933; +1E912;ADLAM CAPITAL LETTER YA;Lu;0;R;;;;;N;;;;1E934; +1E913;ADLAM CAPITAL LETTER U;Lu;0;R;;;;;N;;;;1E935; +1E914;ADLAM CAPITAL LETTER JIIM;Lu;0;R;;;;;N;;;;1E936; +1E915;ADLAM CAPITAL LETTER CHI;Lu;0;R;;;;;N;;;;1E937; +1E916;ADLAM CAPITAL LETTER HA;Lu;0;R;;;;;N;;;;1E938; +1E917;ADLAM CAPITAL LETTER QAAF;Lu;0;R;;;;;N;;;;1E939; +1E918;ADLAM CAPITAL LETTER GA;Lu;0;R;;;;;N;;;;1E93A; +1E919;ADLAM CAPITAL LETTER NYA;Lu;0;R;;;;;N;;;;1E93B; +1E91A;ADLAM CAPITAL LETTER TU;Lu;0;R;;;;;N;;;;1E93C; +1E91B;ADLAM CAPITAL LETTER NHA;Lu;0;R;;;;;N;;;;1E93D; +1E91C;ADLAM CAPITAL LETTER VA;Lu;0;R;;;;;N;;;;1E93E; +1E91D;ADLAM CAPITAL LETTER KHA;Lu;0;R;;;;;N;;;;1E93F; +1E91E;ADLAM CAPITAL LETTER GBE;Lu;0;R;;;;;N;;;;1E940; +1E91F;ADLAM CAPITAL LETTER ZAL;Lu;0;R;;;;;N;;;;1E941; +1E920;ADLAM CAPITAL LETTER KPO;Lu;0;R;;;;;N;;;;1E942; +1E921;ADLAM CAPITAL LETTER SHA;Lu;0;R;;;;;N;;;;1E943; +1E922;ADLAM SMALL LETTER ALIF;Ll;0;R;;;;;N;;;1E900;;1E900 +1E923;ADLAM SMALL LETTER DAALI;Ll;0;R;;;;;N;;;1E901;;1E901 +1E924;ADLAM SMALL LETTER LAAM;Ll;0;R;;;;;N;;;1E902;;1E902 +1E925;ADLAM SMALL LETTER MIIM;Ll;0;R;;;;;N;;;1E903;;1E903 +1E926;ADLAM SMALL LETTER BA;Ll;0;R;;;;;N;;;1E904;;1E904 +1E927;ADLAM SMALL LETTER SINNYIIYHE;Ll;0;R;;;;;N;;;1E905;;1E905 +1E928;ADLAM SMALL LETTER PE;Ll;0;R;;;;;N;;;1E906;;1E906 +1E929;ADLAM SMALL LETTER BHE;Ll;0;R;;;;;N;;;1E907;;1E907 +1E92A;ADLAM SMALL LETTER RA;Ll;0;R;;;;;N;;;1E908;;1E908 +1E92B;ADLAM SMALL LETTER E;Ll;0;R;;;;;N;;;1E909;;1E909 +1E92C;ADLAM SMALL LETTER FA;Ll;0;R;;;;;N;;;1E90A;;1E90A +1E92D;ADLAM SMALL LETTER I;Ll;0;R;;;;;N;;;1E90B;;1E90B +1E92E;ADLAM SMALL LETTER O;Ll;0;R;;;;;N;;;1E90C;;1E90C +1E92F;ADLAM SMALL LETTER DHA;Ll;0;R;;;;;N;;;1E90D;;1E90D +1E930;ADLAM SMALL LETTER YHE;Ll;0;R;;;;;N;;;1E90E;;1E90E +1E931;ADLAM SMALL LETTER WAW;Ll;0;R;;;;;N;;;1E90F;;1E90F +1E932;ADLAM SMALL LETTER NUN;Ll;0;R;;;;;N;;;1E910;;1E910 +1E933;ADLAM SMALL LETTER KAF;Ll;0;R;;;;;N;;;1E911;;1E911 +1E934;ADLAM SMALL LETTER YA;Ll;0;R;;;;;N;;;1E912;;1E912 +1E935;ADLAM SMALL LETTER U;Ll;0;R;;;;;N;;;1E913;;1E913 +1E936;ADLAM SMALL LETTER JIIM;Ll;0;R;;;;;N;;;1E914;;1E914 +1E937;ADLAM SMALL LETTER CHI;Ll;0;R;;;;;N;;;1E915;;1E915 +1E938;ADLAM SMALL LETTER HA;Ll;0;R;;;;;N;;;1E916;;1E916 +1E939;ADLAM SMALL LETTER QAAF;Ll;0;R;;;;;N;;;1E917;;1E917 +1E93A;ADLAM SMALL LETTER GA;Ll;0;R;;;;;N;;;1E918;;1E918 +1E93B;ADLAM SMALL LETTER NYA;Ll;0;R;;;;;N;;;1E919;;1E919 +1E93C;ADLAM SMALL LETTER TU;Ll;0;R;;;;;N;;;1E91A;;1E91A +1E93D;ADLAM SMALL LETTER NHA;Ll;0;R;;;;;N;;;1E91B;;1E91B +1E93E;ADLAM SMALL LETTER VA;Ll;0;R;;;;;N;;;1E91C;;1E91C +1E93F;ADLAM SMALL LETTER KHA;Ll;0;R;;;;;N;;;1E91D;;1E91D +1E940;ADLAM SMALL LETTER GBE;Ll;0;R;;;;;N;;;1E91E;;1E91E +1E941;ADLAM SMALL LETTER ZAL;Ll;0;R;;;;;N;;;1E91F;;1E91F +1E942;ADLAM SMALL LETTER KPO;Ll;0;R;;;;;N;;;1E920;;1E920 +1E943;ADLAM SMALL LETTER SHA;Ll;0;R;;;;;N;;;1E921;;1E921 +1E944;ADLAM ALIF LENGTHENER;Mn;230;NSM;;;;;N;;;;; +1E945;ADLAM VOWEL LENGTHENER;Mn;230;NSM;;;;;N;;;;; +1E946;ADLAM GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; +1E947;ADLAM HAMZA;Mn;230;NSM;;;;;N;;;;; +1E948;ADLAM CONSONANT MODIFIER;Mn;230;NSM;;;;;N;;;;; +1E949;ADLAM GEMINATE CONSONANT MODIFIER;Mn;230;NSM;;;;;N;;;;; +1E94A;ADLAM NUKTA;Mn;7;NSM;;;;;N;;;;; +1E950;ADLAM DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; +1E951;ADLAM DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; +1E952;ADLAM DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; +1E953;ADLAM DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; +1E954;ADLAM DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; +1E955;ADLAM DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; +1E956;ADLAM DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; +1E957;ADLAM DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; +1E958;ADLAM DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; +1E959;ADLAM DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; +1E95E;ADLAM INITIAL EXCLAMATION MARK;Po;0;R;;;;;N;;;;; +1E95F;ADLAM INITIAL QUESTION MARK;Po;0;R;;;;;N;;;;; +1EE00;ARABIC MATHEMATICAL ALEF;Lo;0;AL;<font> 0627;;;;N;;;;; +1EE01;ARABIC MATHEMATICAL BEH;Lo;0;AL;<font> 0628;;;;N;;;;; +1EE02;ARABIC MATHEMATICAL JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; +1EE03;ARABIC MATHEMATICAL DAL;Lo;0;AL;<font> 062F;;;;N;;;;; +1EE05;ARABIC MATHEMATICAL WAW;Lo;0;AL;<font> 0648;;;;N;;;;; +1EE06;ARABIC MATHEMATICAL ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;; +1EE07;ARABIC MATHEMATICAL HAH;Lo;0;AL;<font> 062D;;;;N;;;;; +1EE08;ARABIC MATHEMATICAL TAH;Lo;0;AL;<font> 0637;;;;N;;;;; +1EE09;ARABIC MATHEMATICAL YEH;Lo;0;AL;<font> 064A;;;;N;;;;; +1EE0A;ARABIC MATHEMATICAL KAF;Lo;0;AL;<font> 0643;;;;N;;;;; +1EE0B;ARABIC MATHEMATICAL LAM;Lo;0;AL;<font> 0644;;;;N;;;;; +1EE0C;ARABIC MATHEMATICAL MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; +1EE0D;ARABIC MATHEMATICAL NOON;Lo;0;AL;<font> 0646;;;;N;;;;; +1EE0E;ARABIC MATHEMATICAL SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; +1EE0F;ARABIC MATHEMATICAL AIN;Lo;0;AL;<font> 0639;;;;N;;;;; +1EE10;ARABIC MATHEMATICAL FEH;Lo;0;AL;<font> 0641;;;;N;;;;; +1EE11;ARABIC MATHEMATICAL SAD;Lo;0;AL;<font> 0635;;;;N;;;;; +1EE12;ARABIC MATHEMATICAL QAF;Lo;0;AL;<font> 0642;;;;N;;;;; +1EE13;ARABIC MATHEMATICAL REH;Lo;0;AL;<font> 0631;;;;N;;;;; +1EE14;ARABIC MATHEMATICAL SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; +1EE15;ARABIC MATHEMATICAL TEH;Lo;0;AL;<font> 062A;;;;N;;;;; +1EE16;ARABIC MATHEMATICAL THEH;Lo;0;AL;<font> 062B;;;;N;;;;; +1EE17;ARABIC MATHEMATICAL KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; +1EE18;ARABIC MATHEMATICAL THAL;Lo;0;AL;<font> 0630;;;;N;;;;; +1EE19;ARABIC MATHEMATICAL DAD;Lo;0;AL;<font> 0636;;;;N;;;;; +1EE1A;ARABIC MATHEMATICAL ZAH;Lo;0;AL;<font> 0638;;;;N;;;;; +1EE1B;ARABIC MATHEMATICAL GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; +1EE1C;ARABIC MATHEMATICAL DOTLESS BEH;Lo;0;AL;<font> 066E;;;;N;;;;; +1EE1D;ARABIC MATHEMATICAL DOTLESS NOON;Lo;0;AL;<font> 06BA;;;;N;;;;; +1EE1E;ARABIC MATHEMATICAL DOTLESS FEH;Lo;0;AL;<font> 06A1;;;;N;;;;; +1EE1F;ARABIC MATHEMATICAL DOTLESS QAF;Lo;0;AL;<font> 066F;;;;N;;;;; +1EE21;ARABIC MATHEMATICAL INITIAL BEH;Lo;0;AL;<font> 0628;;;;N;;;;; +1EE22;ARABIC MATHEMATICAL INITIAL JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; +1EE24;ARABIC MATHEMATICAL INITIAL HEH;Lo;0;AL;<font> 0647;;;;N;;;;; +1EE27;ARABIC MATHEMATICAL INITIAL HAH;Lo;0;AL;<font> 062D;;;;N;;;;; +1EE29;ARABIC MATHEMATICAL INITIAL YEH;Lo;0;AL;<font> 064A;;;;N;;;;; +1EE2A;ARABIC MATHEMATICAL INITIAL KAF;Lo;0;AL;<font> 0643;;;;N;;;;; +1EE2B;ARABIC MATHEMATICAL INITIAL LAM;Lo;0;AL;<font> 0644;;;;N;;;;; +1EE2C;ARABIC MATHEMATICAL INITIAL MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; +1EE2D;ARABIC MATHEMATICAL INITIAL NOON;Lo;0;AL;<font> 0646;;;;N;;;;; +1EE2E;ARABIC MATHEMATICAL INITIAL SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; +1EE2F;ARABIC MATHEMATICAL INITIAL AIN;Lo;0;AL;<font> 0639;;;;N;;;;; +1EE30;ARABIC MATHEMATICAL INITIAL FEH;Lo;0;AL;<font> 0641;;;;N;;;;; +1EE31;ARABIC MATHEMATICAL INITIAL SAD;Lo;0;AL;<font> 0635;;;;N;;;;; +1EE32;ARABIC MATHEMATICAL INITIAL QAF;Lo;0;AL;<font> 0642;;;;N;;;;; +1EE34;ARABIC MATHEMATICAL INITIAL SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; +1EE35;ARABIC MATHEMATICAL INITIAL TEH;Lo;0;AL;<font> 062A;;;;N;;;;; +1EE36;ARABIC MATHEMATICAL INITIAL THEH;Lo;0;AL;<font> 062B;;;;N;;;;; +1EE37;ARABIC MATHEMATICAL INITIAL KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; +1EE39;ARABIC MATHEMATICAL INITIAL DAD;Lo;0;AL;<font> 0636;;;;N;;;;; +1EE3B;ARABIC MATHEMATICAL INITIAL GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; +1EE42;ARABIC MATHEMATICAL TAILED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; +1EE47;ARABIC MATHEMATICAL TAILED HAH;Lo;0;AL;<font> 062D;;;;N;;;;; +1EE49;ARABIC MATHEMATICAL TAILED YEH;Lo;0;AL;<font> 064A;;;;N;;;;; +1EE4B;ARABIC MATHEMATICAL TAILED LAM;Lo;0;AL;<font> 0644;;;;N;;;;; +1EE4D;ARABIC MATHEMATICAL TAILED NOON;Lo;0;AL;<font> 0646;;;;N;;;;; +1EE4E;ARABIC MATHEMATICAL TAILED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; +1EE4F;ARABIC MATHEMATICAL TAILED AIN;Lo;0;AL;<font> 0639;;;;N;;;;; +1EE51;ARABIC MATHEMATICAL TAILED SAD;Lo;0;AL;<font> 0635;;;;N;;;;; +1EE52;ARABIC MATHEMATICAL TAILED QAF;Lo;0;AL;<font> 0642;;;;N;;;;; +1EE54;ARABIC MATHEMATICAL TAILED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; +1EE57;ARABIC MATHEMATICAL TAILED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; +1EE59;ARABIC MATHEMATICAL TAILED DAD;Lo;0;AL;<font> 0636;;;;N;;;;; +1EE5B;ARABIC MATHEMATICAL TAILED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; +1EE5D;ARABIC MATHEMATICAL TAILED DOTLESS NOON;Lo;0;AL;<font> 06BA;;;;N;;;;; +1EE5F;ARABIC MATHEMATICAL TAILED DOTLESS QAF;Lo;0;AL;<font> 066F;;;;N;;;;; +1EE61;ARABIC MATHEMATICAL STRETCHED BEH;Lo;0;AL;<font> 0628;;;;N;;;;; +1EE62;ARABIC MATHEMATICAL STRETCHED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; +1EE64;ARABIC MATHEMATICAL STRETCHED HEH;Lo;0;AL;<font> 0647;;;;N;;;;; +1EE67;ARABIC MATHEMATICAL STRETCHED HAH;Lo;0;AL;<font> 062D;;;;N;;;;; +1EE68;ARABIC MATHEMATICAL STRETCHED TAH;Lo;0;AL;<font> 0637;;;;N;;;;; +1EE69;ARABIC MATHEMATICAL STRETCHED YEH;Lo;0;AL;<font> 064A;;;;N;;;;; +1EE6A;ARABIC MATHEMATICAL STRETCHED KAF;Lo;0;AL;<font> 0643;;;;N;;;;; +1EE6C;ARABIC MATHEMATICAL STRETCHED MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; +1EE6D;ARABIC MATHEMATICAL STRETCHED NOON;Lo;0;AL;<font> 0646;;;;N;;;;; +1EE6E;ARABIC MATHEMATICAL STRETCHED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; +1EE6F;ARABIC MATHEMATICAL STRETCHED AIN;Lo;0;AL;<font> 0639;;;;N;;;;; +1EE70;ARABIC MATHEMATICAL STRETCHED FEH;Lo;0;AL;<font> 0641;;;;N;;;;; +1EE71;ARABIC MATHEMATICAL STRETCHED SAD;Lo;0;AL;<font> 0635;;;;N;;;;; +1EE72;ARABIC MATHEMATICAL STRETCHED QAF;Lo;0;AL;<font> 0642;;;;N;;;;; +1EE74;ARABIC MATHEMATICAL STRETCHED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; +1EE75;ARABIC MATHEMATICAL STRETCHED TEH;Lo;0;AL;<font> 062A;;;;N;;;;; +1EE76;ARABIC MATHEMATICAL STRETCHED THEH;Lo;0;AL;<font> 062B;;;;N;;;;; +1EE77;ARABIC MATHEMATICAL STRETCHED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; +1EE79;ARABIC MATHEMATICAL STRETCHED DAD;Lo;0;AL;<font> 0636;;;;N;;;;; +1EE7A;ARABIC MATHEMATICAL STRETCHED ZAH;Lo;0;AL;<font> 0638;;;;N;;;;; +1EE7B;ARABIC MATHEMATICAL STRETCHED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; +1EE7C;ARABIC MATHEMATICAL STRETCHED DOTLESS BEH;Lo;0;AL;<font> 066E;;;;N;;;;; +1EE7E;ARABIC MATHEMATICAL STRETCHED DOTLESS FEH;Lo;0;AL;<font> 06A1;;;;N;;;;; +1EE80;ARABIC MATHEMATICAL LOOPED ALEF;Lo;0;AL;<font> 0627;;;;N;;;;; +1EE81;ARABIC MATHEMATICAL LOOPED BEH;Lo;0;AL;<font> 0628;;;;N;;;;; +1EE82;ARABIC MATHEMATICAL LOOPED JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; +1EE83;ARABIC MATHEMATICAL LOOPED DAL;Lo;0;AL;<font> 062F;;;;N;;;;; +1EE84;ARABIC MATHEMATICAL LOOPED HEH;Lo;0;AL;<font> 0647;;;;N;;;;; +1EE85;ARABIC MATHEMATICAL LOOPED WAW;Lo;0;AL;<font> 0648;;;;N;;;;; +1EE86;ARABIC MATHEMATICAL LOOPED ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;; +1EE87;ARABIC MATHEMATICAL LOOPED HAH;Lo;0;AL;<font> 062D;;;;N;;;;; +1EE88;ARABIC MATHEMATICAL LOOPED TAH;Lo;0;AL;<font> 0637;;;;N;;;;; +1EE89;ARABIC MATHEMATICAL LOOPED YEH;Lo;0;AL;<font> 064A;;;;N;;;;; +1EE8B;ARABIC MATHEMATICAL LOOPED LAM;Lo;0;AL;<font> 0644;;;;N;;;;; +1EE8C;ARABIC MATHEMATICAL LOOPED MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; +1EE8D;ARABIC MATHEMATICAL LOOPED NOON;Lo;0;AL;<font> 0646;;;;N;;;;; +1EE8E;ARABIC MATHEMATICAL LOOPED SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; +1EE8F;ARABIC MATHEMATICAL LOOPED AIN;Lo;0;AL;<font> 0639;;;;N;;;;; +1EE90;ARABIC MATHEMATICAL LOOPED FEH;Lo;0;AL;<font> 0641;;;;N;;;;; +1EE91;ARABIC MATHEMATICAL LOOPED SAD;Lo;0;AL;<font> 0635;;;;N;;;;; +1EE92;ARABIC MATHEMATICAL LOOPED QAF;Lo;0;AL;<font> 0642;;;;N;;;;; +1EE93;ARABIC MATHEMATICAL LOOPED REH;Lo;0;AL;<font> 0631;;;;N;;;;; +1EE94;ARABIC MATHEMATICAL LOOPED SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; +1EE95;ARABIC MATHEMATICAL LOOPED TEH;Lo;0;AL;<font> 062A;;;;N;;;;; +1EE96;ARABIC MATHEMATICAL LOOPED THEH;Lo;0;AL;<font> 062B;;;;N;;;;; +1EE97;ARABIC MATHEMATICAL LOOPED KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; +1EE98;ARABIC MATHEMATICAL LOOPED THAL;Lo;0;AL;<font> 0630;;;;N;;;;; +1EE99;ARABIC MATHEMATICAL LOOPED DAD;Lo;0;AL;<font> 0636;;;;N;;;;; +1EE9A;ARABIC MATHEMATICAL LOOPED ZAH;Lo;0;AL;<font> 0638;;;;N;;;;; +1EE9B;ARABIC MATHEMATICAL LOOPED GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; +1EEA1;ARABIC MATHEMATICAL DOUBLE-STRUCK BEH;Lo;0;AL;<font> 0628;;;;N;;;;; +1EEA2;ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM;Lo;0;AL;<font> 062C;;;;N;;;;; +1EEA3;ARABIC MATHEMATICAL DOUBLE-STRUCK DAL;Lo;0;AL;<font> 062F;;;;N;;;;; +1EEA5;ARABIC MATHEMATICAL DOUBLE-STRUCK WAW;Lo;0;AL;<font> 0648;;;;N;;;;; +1EEA6;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN;Lo;0;AL;<font> 0632;;;;N;;;;; +1EEA7;ARABIC MATHEMATICAL DOUBLE-STRUCK HAH;Lo;0;AL;<font> 062D;;;;N;;;;; +1EEA8;ARABIC MATHEMATICAL DOUBLE-STRUCK TAH;Lo;0;AL;<font> 0637;;;;N;;;;; +1EEA9;ARABIC MATHEMATICAL DOUBLE-STRUCK YEH;Lo;0;AL;<font> 064A;;;;N;;;;; +1EEAB;ARABIC MATHEMATICAL DOUBLE-STRUCK LAM;Lo;0;AL;<font> 0644;;;;N;;;;; +1EEAC;ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM;Lo;0;AL;<font> 0645;;;;N;;;;; +1EEAD;ARABIC MATHEMATICAL DOUBLE-STRUCK NOON;Lo;0;AL;<font> 0646;;;;N;;;;; +1EEAE;ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN;Lo;0;AL;<font> 0633;;;;N;;;;; +1EEAF;ARABIC MATHEMATICAL DOUBLE-STRUCK AIN;Lo;0;AL;<font> 0639;;;;N;;;;; +1EEB0;ARABIC MATHEMATICAL DOUBLE-STRUCK FEH;Lo;0;AL;<font> 0641;;;;N;;;;; +1EEB1;ARABIC MATHEMATICAL DOUBLE-STRUCK SAD;Lo;0;AL;<font> 0635;;;;N;;;;; +1EEB2;ARABIC MATHEMATICAL DOUBLE-STRUCK QAF;Lo;0;AL;<font> 0642;;;;N;;;;; +1EEB3;ARABIC MATHEMATICAL DOUBLE-STRUCK REH;Lo;0;AL;<font> 0631;;;;N;;;;; +1EEB4;ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN;Lo;0;AL;<font> 0634;;;;N;;;;; +1EEB5;ARABIC MATHEMATICAL DOUBLE-STRUCK TEH;Lo;0;AL;<font> 062A;;;;N;;;;; +1EEB6;ARABIC MATHEMATICAL DOUBLE-STRUCK THEH;Lo;0;AL;<font> 062B;;;;N;;;;; +1EEB7;ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH;Lo;0;AL;<font> 062E;;;;N;;;;; +1EEB8;ARABIC MATHEMATICAL DOUBLE-STRUCK THAL;Lo;0;AL;<font> 0630;;;;N;;;;; +1EEB9;ARABIC MATHEMATICAL DOUBLE-STRUCK DAD;Lo;0;AL;<font> 0636;;;;N;;;;; +1EEBA;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH;Lo;0;AL;<font> 0638;;;;N;;;;; +1EEBB;ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN;Lo;0;AL;<font> 063A;;;;N;;;;; +1EEF0;ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL;Sm;0;ON;;;;;N;;;;; +1EEF1;ARABIC MATHEMATICAL OPERATOR HAH WITH DAL;Sm;0;ON;;;;;N;;;;; +1F000;MAHJONG TILE EAST WIND;So;0;ON;;;;;N;;;;; +1F001;MAHJONG TILE SOUTH WIND;So;0;ON;;;;;N;;;;; +1F002;MAHJONG TILE WEST WIND;So;0;ON;;;;;N;;;;; +1F003;MAHJONG TILE NORTH WIND;So;0;ON;;;;;N;;;;; +1F004;MAHJONG TILE RED DRAGON;So;0;ON;;;;;N;;;;; +1F005;MAHJONG TILE GREEN DRAGON;So;0;ON;;;;;N;;;;; +1F006;MAHJONG TILE WHITE DRAGON;So;0;ON;;;;;N;;;;; +1F007;MAHJONG TILE ONE OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F008;MAHJONG TILE TWO OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F009;MAHJONG TILE THREE OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00A;MAHJONG TILE FOUR OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00B;MAHJONG TILE FIVE OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00C;MAHJONG TILE SIX OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00D;MAHJONG TILE SEVEN OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00E;MAHJONG TILE EIGHT OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00F;MAHJONG TILE NINE OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F010;MAHJONG TILE ONE OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F011;MAHJONG TILE TWO OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F012;MAHJONG TILE THREE OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F013;MAHJONG TILE FOUR OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F014;MAHJONG TILE FIVE OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F015;MAHJONG TILE SIX OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F016;MAHJONG TILE SEVEN OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F017;MAHJONG TILE EIGHT OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F018;MAHJONG TILE NINE OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F019;MAHJONG TILE ONE OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01A;MAHJONG TILE TWO OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01B;MAHJONG TILE THREE OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01C;MAHJONG TILE FOUR OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01D;MAHJONG TILE FIVE OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01E;MAHJONG TILE SIX OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01F;MAHJONG TILE SEVEN OF CIRCLES;So;0;ON;;;;;N;;;;; +1F020;MAHJONG TILE EIGHT OF CIRCLES;So;0;ON;;;;;N;;;;; +1F021;MAHJONG TILE NINE OF CIRCLES;So;0;ON;;;;;N;;;;; +1F022;MAHJONG TILE PLUM;So;0;ON;;;;;N;;;;; +1F023;MAHJONG TILE ORCHID;So;0;ON;;;;;N;;;;; +1F024;MAHJONG TILE BAMBOO;So;0;ON;;;;;N;;;;; +1F025;MAHJONG TILE CHRYSANTHEMUM;So;0;ON;;;;;N;;;;; +1F026;MAHJONG TILE SPRING;So;0;ON;;;;;N;;;;; +1F027;MAHJONG TILE SUMMER;So;0;ON;;;;;N;;;;; +1F028;MAHJONG TILE AUTUMN;So;0;ON;;;;;N;;;;; +1F029;MAHJONG TILE WINTER;So;0;ON;;;;;N;;;;; +1F02A;MAHJONG TILE JOKER;So;0;ON;;;;;N;;;;; +1F02B;MAHJONG TILE BACK;So;0;ON;;;;;N;;;;; +1F030;DOMINO TILE HORIZONTAL BACK;So;0;ON;;;;;N;;;;; +1F031;DOMINO TILE HORIZONTAL-00-00;So;0;ON;;;;;N;;;;; +1F032;DOMINO TILE HORIZONTAL-00-01;So;0;ON;;;;;N;;;;; +1F033;DOMINO TILE HORIZONTAL-00-02;So;0;ON;;;;;N;;;;; +1F034;DOMINO TILE HORIZONTAL-00-03;So;0;ON;;;;;N;;;;; +1F035;DOMINO TILE HORIZONTAL-00-04;So;0;ON;;;;;N;;;;; +1F036;DOMINO TILE HORIZONTAL-00-05;So;0;ON;;;;;N;;;;; +1F037;DOMINO TILE HORIZONTAL-00-06;So;0;ON;;;;;N;;;;; +1F038;DOMINO TILE HORIZONTAL-01-00;So;0;ON;;;;;N;;;;; +1F039;DOMINO TILE HORIZONTAL-01-01;So;0;ON;;;;;N;;;;; +1F03A;DOMINO TILE HORIZONTAL-01-02;So;0;ON;;;;;N;;;;; +1F03B;DOMINO TILE HORIZONTAL-01-03;So;0;ON;;;;;N;;;;; +1F03C;DOMINO TILE HORIZONTAL-01-04;So;0;ON;;;;;N;;;;; +1F03D;DOMINO TILE HORIZONTAL-01-05;So;0;ON;;;;;N;;;;; +1F03E;DOMINO TILE HORIZONTAL-01-06;So;0;ON;;;;;N;;;;; +1F03F;DOMINO TILE HORIZONTAL-02-00;So;0;ON;;;;;N;;;;; +1F040;DOMINO TILE HORIZONTAL-02-01;So;0;ON;;;;;N;;;;; +1F041;DOMINO TILE HORIZONTAL-02-02;So;0;ON;;;;;N;;;;; +1F042;DOMINO TILE HORIZONTAL-02-03;So;0;ON;;;;;N;;;;; +1F043;DOMINO TILE HORIZONTAL-02-04;So;0;ON;;;;;N;;;;; +1F044;DOMINO TILE HORIZONTAL-02-05;So;0;ON;;;;;N;;;;; +1F045;DOMINO TILE HORIZONTAL-02-06;So;0;ON;;;;;N;;;;; +1F046;DOMINO TILE HORIZONTAL-03-00;So;0;ON;;;;;N;;;;; +1F047;DOMINO TILE HORIZONTAL-03-01;So;0;ON;;;;;N;;;;; +1F048;DOMINO TILE HORIZONTAL-03-02;So;0;ON;;;;;N;;;;; +1F049;DOMINO TILE HORIZONTAL-03-03;So;0;ON;;;;;N;;;;; +1F04A;DOMINO TILE HORIZONTAL-03-04;So;0;ON;;;;;N;;;;; +1F04B;DOMINO TILE HORIZONTAL-03-05;So;0;ON;;;;;N;;;;; +1F04C;DOMINO TILE HORIZONTAL-03-06;So;0;ON;;;;;N;;;;; +1F04D;DOMINO TILE HORIZONTAL-04-00;So;0;ON;;;;;N;;;;; +1F04E;DOMINO TILE HORIZONTAL-04-01;So;0;ON;;;;;N;;;;; +1F04F;DOMINO TILE HORIZONTAL-04-02;So;0;ON;;;;;N;;;;; +1F050;DOMINO TILE HORIZONTAL-04-03;So;0;ON;;;;;N;;;;; +1F051;DOMINO TILE HORIZONTAL-04-04;So;0;ON;;;;;N;;;;; +1F052;DOMINO TILE HORIZONTAL-04-05;So;0;ON;;;;;N;;;;; +1F053;DOMINO TILE HORIZONTAL-04-06;So;0;ON;;;;;N;;;;; +1F054;DOMINO TILE HORIZONTAL-05-00;So;0;ON;;;;;N;;;;; +1F055;DOMINO TILE HORIZONTAL-05-01;So;0;ON;;;;;N;;;;; +1F056;DOMINO TILE HORIZONTAL-05-02;So;0;ON;;;;;N;;;;; +1F057;DOMINO TILE HORIZONTAL-05-03;So;0;ON;;;;;N;;;;; +1F058;DOMINO TILE HORIZONTAL-05-04;So;0;ON;;;;;N;;;;; +1F059;DOMINO TILE HORIZONTAL-05-05;So;0;ON;;;;;N;;;;; +1F05A;DOMINO TILE HORIZONTAL-05-06;So;0;ON;;;;;N;;;;; +1F05B;DOMINO TILE HORIZONTAL-06-00;So;0;ON;;;;;N;;;;; +1F05C;DOMINO TILE HORIZONTAL-06-01;So;0;ON;;;;;N;;;;; +1F05D;DOMINO TILE HORIZONTAL-06-02;So;0;ON;;;;;N;;;;; +1F05E;DOMINO TILE HORIZONTAL-06-03;So;0;ON;;;;;N;;;;; +1F05F;DOMINO TILE HORIZONTAL-06-04;So;0;ON;;;;;N;;;;; +1F060;DOMINO TILE HORIZONTAL-06-05;So;0;ON;;;;;N;;;;; +1F061;DOMINO TILE HORIZONTAL-06-06;So;0;ON;;;;;N;;;;; +1F062;DOMINO TILE VERTICAL BACK;So;0;ON;;;;;N;;;;; +1F063;DOMINO TILE VERTICAL-00-00;So;0;ON;;;;;N;;;;; +1F064;DOMINO TILE VERTICAL-00-01;So;0;ON;;;;;N;;;;; +1F065;DOMINO TILE VERTICAL-00-02;So;0;ON;;;;;N;;;;; +1F066;DOMINO TILE VERTICAL-00-03;So;0;ON;;;;;N;;;;; +1F067;DOMINO TILE VERTICAL-00-04;So;0;ON;;;;;N;;;;; +1F068;DOMINO TILE VERTICAL-00-05;So;0;ON;;;;;N;;;;; +1F069;DOMINO TILE VERTICAL-00-06;So;0;ON;;;;;N;;;;; +1F06A;DOMINO TILE VERTICAL-01-00;So;0;ON;;;;;N;;;;; +1F06B;DOMINO TILE VERTICAL-01-01;So;0;ON;;;;;N;;;;; +1F06C;DOMINO TILE VERTICAL-01-02;So;0;ON;;;;;N;;;;; +1F06D;DOMINO TILE VERTICAL-01-03;So;0;ON;;;;;N;;;;; +1F06E;DOMINO TILE VERTICAL-01-04;So;0;ON;;;;;N;;;;; +1F06F;DOMINO TILE VERTICAL-01-05;So;0;ON;;;;;N;;;;; +1F070;DOMINO TILE VERTICAL-01-06;So;0;ON;;;;;N;;;;; +1F071;DOMINO TILE VERTICAL-02-00;So;0;ON;;;;;N;;;;; +1F072;DOMINO TILE VERTICAL-02-01;So;0;ON;;;;;N;;;;; +1F073;DOMINO TILE VERTICAL-02-02;So;0;ON;;;;;N;;;;; +1F074;DOMINO TILE VERTICAL-02-03;So;0;ON;;;;;N;;;;; +1F075;DOMINO TILE VERTICAL-02-04;So;0;ON;;;;;N;;;;; +1F076;DOMINO TILE VERTICAL-02-05;So;0;ON;;;;;N;;;;; +1F077;DOMINO TILE VERTICAL-02-06;So;0;ON;;;;;N;;;;; +1F078;DOMINO TILE VERTICAL-03-00;So;0;ON;;;;;N;;;;; +1F079;DOMINO TILE VERTICAL-03-01;So;0;ON;;;;;N;;;;; +1F07A;DOMINO TILE VERTICAL-03-02;So;0;ON;;;;;N;;;;; +1F07B;DOMINO TILE VERTICAL-03-03;So;0;ON;;;;;N;;;;; +1F07C;DOMINO TILE VERTICAL-03-04;So;0;ON;;;;;N;;;;; +1F07D;DOMINO TILE VERTICAL-03-05;So;0;ON;;;;;N;;;;; +1F07E;DOMINO TILE VERTICAL-03-06;So;0;ON;;;;;N;;;;; +1F07F;DOMINO TILE VERTICAL-04-00;So;0;ON;;;;;N;;;;; +1F080;DOMINO TILE VERTICAL-04-01;So;0;ON;;;;;N;;;;; +1F081;DOMINO TILE VERTICAL-04-02;So;0;ON;;;;;N;;;;; +1F082;DOMINO TILE VERTICAL-04-03;So;0;ON;;;;;N;;;;; +1F083;DOMINO TILE VERTICAL-04-04;So;0;ON;;;;;N;;;;; +1F084;DOMINO TILE VERTICAL-04-05;So;0;ON;;;;;N;;;;; +1F085;DOMINO TILE VERTICAL-04-06;So;0;ON;;;;;N;;;;; +1F086;DOMINO TILE VERTICAL-05-00;So;0;ON;;;;;N;;;;; +1F087;DOMINO TILE VERTICAL-05-01;So;0;ON;;;;;N;;;;; +1F088;DOMINO TILE VERTICAL-05-02;So;0;ON;;;;;N;;;;; +1F089;DOMINO TILE VERTICAL-05-03;So;0;ON;;;;;N;;;;; +1F08A;DOMINO TILE VERTICAL-05-04;So;0;ON;;;;;N;;;;; +1F08B;DOMINO TILE VERTICAL-05-05;So;0;ON;;;;;N;;;;; +1F08C;DOMINO TILE VERTICAL-05-06;So;0;ON;;;;;N;;;;; +1F08D;DOMINO TILE VERTICAL-06-00;So;0;ON;;;;;N;;;;; +1F08E;DOMINO TILE VERTICAL-06-01;So;0;ON;;;;;N;;;;; +1F08F;DOMINO TILE VERTICAL-06-02;So;0;ON;;;;;N;;;;; +1F090;DOMINO TILE VERTICAL-06-03;So;0;ON;;;;;N;;;;; +1F091;DOMINO TILE VERTICAL-06-04;So;0;ON;;;;;N;;;;; +1F092;DOMINO TILE VERTICAL-06-05;So;0;ON;;;;;N;;;;; +1F093;DOMINO TILE VERTICAL-06-06;So;0;ON;;;;;N;;;;; +1F0A0;PLAYING CARD BACK;So;0;ON;;;;;N;;;;; +1F0A1;PLAYING CARD ACE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A2;PLAYING CARD TWO OF SPADES;So;0;ON;;;;;N;;;;; +1F0A3;PLAYING CARD THREE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A4;PLAYING CARD FOUR OF SPADES;So;0;ON;;;;;N;;;;; +1F0A5;PLAYING CARD FIVE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A6;PLAYING CARD SIX OF SPADES;So;0;ON;;;;;N;;;;; +1F0A7;PLAYING CARD SEVEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0A8;PLAYING CARD EIGHT OF SPADES;So;0;ON;;;;;N;;;;; +1F0A9;PLAYING CARD NINE OF SPADES;So;0;ON;;;;;N;;;;; +1F0AA;PLAYING CARD TEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0AB;PLAYING CARD JACK OF SPADES;So;0;ON;;;;;N;;;;; +1F0AC;PLAYING CARD KNIGHT OF SPADES;So;0;ON;;;;;N;;;;; +1F0AD;PLAYING CARD QUEEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0AE;PLAYING CARD KING OF SPADES;So;0;ON;;;;;N;;;;; +1F0B1;PLAYING CARD ACE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B2;PLAYING CARD TWO OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B3;PLAYING CARD THREE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B4;PLAYING CARD FOUR OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B5;PLAYING CARD FIVE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B6;PLAYING CARD SIX OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B7;PLAYING CARD SEVEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B8;PLAYING CARD EIGHT OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B9;PLAYING CARD NINE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BA;PLAYING CARD TEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BB;PLAYING CARD JACK OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BC;PLAYING CARD KNIGHT OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BD;PLAYING CARD QUEEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BE;PLAYING CARD KING OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BF;PLAYING CARD RED JOKER;So;0;ON;;;;;N;;;;; +1F0C1;PLAYING CARD ACE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C2;PLAYING CARD TWO OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C3;PLAYING CARD THREE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C4;PLAYING CARD FOUR OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C5;PLAYING CARD FIVE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C6;PLAYING CARD SIX OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C7;PLAYING CARD SEVEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C8;PLAYING CARD EIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C9;PLAYING CARD NINE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CA;PLAYING CARD TEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CB;PLAYING CARD JACK OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CC;PLAYING CARD KNIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CD;PLAYING CARD QUEEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CE;PLAYING CARD KING OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CF;PLAYING CARD BLACK JOKER;So;0;ON;;;;;N;;;;; +1F0D1;PLAYING CARD ACE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D2;PLAYING CARD TWO OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D3;PLAYING CARD THREE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D4;PLAYING CARD FOUR OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D5;PLAYING CARD FIVE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D6;PLAYING CARD SIX OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D7;PLAYING CARD SEVEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D8;PLAYING CARD EIGHT OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D9;PLAYING CARD NINE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DA;PLAYING CARD TEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DB;PLAYING CARD JACK OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DC;PLAYING CARD KNIGHT OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DD;PLAYING CARD QUEEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DE;PLAYING CARD KING OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DF;PLAYING CARD WHITE JOKER;So;0;ON;;;;;N;;;;; +1F0E0;PLAYING CARD FOOL;So;0;ON;;;;;N;;;;; +1F0E1;PLAYING CARD TRUMP-1;So;0;ON;;;;;N;;;;; +1F0E2;PLAYING CARD TRUMP-2;So;0;ON;;;;;N;;;;; +1F0E3;PLAYING CARD TRUMP-3;So;0;ON;;;;;N;;;;; +1F0E4;PLAYING CARD TRUMP-4;So;0;ON;;;;;N;;;;; +1F0E5;PLAYING CARD TRUMP-5;So;0;ON;;;;;N;;;;; +1F0E6;PLAYING CARD TRUMP-6;So;0;ON;;;;;N;;;;; +1F0E7;PLAYING CARD TRUMP-7;So;0;ON;;;;;N;;;;; +1F0E8;PLAYING CARD TRUMP-8;So;0;ON;;;;;N;;;;; +1F0E9;PLAYING CARD TRUMP-9;So;0;ON;;;;;N;;;;; +1F0EA;PLAYING CARD TRUMP-10;So;0;ON;;;;;N;;;;; +1F0EB;PLAYING CARD TRUMP-11;So;0;ON;;;;;N;;;;; +1F0EC;PLAYING CARD TRUMP-12;So;0;ON;;;;;N;;;;; +1F0ED;PLAYING CARD TRUMP-13;So;0;ON;;;;;N;;;;; +1F0EE;PLAYING CARD TRUMP-14;So;0;ON;;;;;N;;;;; +1F0EF;PLAYING CARD TRUMP-15;So;0;ON;;;;;N;;;;; +1F0F0;PLAYING CARD TRUMP-16;So;0;ON;;;;;N;;;;; +1F0F1;PLAYING CARD TRUMP-17;So;0;ON;;;;;N;;;;; +1F0F2;PLAYING CARD TRUMP-18;So;0;ON;;;;;N;;;;; +1F0F3;PLAYING CARD TRUMP-19;So;0;ON;;;;;N;;;;; +1F0F4;PLAYING CARD TRUMP-20;So;0;ON;;;;;N;;;;; +1F0F5;PLAYING CARD TRUMP-21;So;0;ON;;;;;N;;;;; +1F100;DIGIT ZERO FULL STOP;No;0;EN;<compat> 0030 002E;;0;0;N;;;;; +1F101;DIGIT ZERO COMMA;No;0;EN;<compat> 0030 002C;;0;0;N;;;;; +1F102;DIGIT ONE COMMA;No;0;EN;<compat> 0031 002C;;1;1;N;;;;; +1F103;DIGIT TWO COMMA;No;0;EN;<compat> 0032 002C;;2;2;N;;;;; +1F104;DIGIT THREE COMMA;No;0;EN;<compat> 0033 002C;;3;3;N;;;;; +1F105;DIGIT FOUR COMMA;No;0;EN;<compat> 0034 002C;;4;4;N;;;;; +1F106;DIGIT FIVE COMMA;No;0;EN;<compat> 0035 002C;;5;5;N;;;;; +1F107;DIGIT SIX COMMA;No;0;EN;<compat> 0036 002C;;6;6;N;;;;; +1F108;DIGIT SEVEN COMMA;No;0;EN;<compat> 0037 002C;;7;7;N;;;;; +1F109;DIGIT EIGHT COMMA;No;0;EN;<compat> 0038 002C;;8;8;N;;;;; +1F10A;DIGIT NINE COMMA;No;0;EN;<compat> 0039 002C;;9;9;N;;;;; +1F10B;DINGBAT CIRCLED SANS-SERIF DIGIT ZERO;No;0;ON;;;;0;N;;;;; +1F10C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO;No;0;ON;;;;0;N;;;;; +1F110;PARENTHESIZED LATIN CAPITAL LETTER A;So;0;L;<compat> 0028 0041 0029;;;;N;;;;; +1F111;PARENTHESIZED LATIN CAPITAL LETTER B;So;0;L;<compat> 0028 0042 0029;;;;N;;;;; +1F112;PARENTHESIZED LATIN CAPITAL LETTER C;So;0;L;<compat> 0028 0043 0029;;;;N;;;;; +1F113;PARENTHESIZED LATIN CAPITAL LETTER D;So;0;L;<compat> 0028 0044 0029;;;;N;;;;; +1F114;PARENTHESIZED LATIN CAPITAL LETTER E;So;0;L;<compat> 0028 0045 0029;;;;N;;;;; +1F115;PARENTHESIZED LATIN CAPITAL LETTER F;So;0;L;<compat> 0028 0046 0029;;;;N;;;;; +1F116;PARENTHESIZED LATIN CAPITAL LETTER G;So;0;L;<compat> 0028 0047 0029;;;;N;;;;; +1F117;PARENTHESIZED LATIN CAPITAL LETTER H;So;0;L;<compat> 0028 0048 0029;;;;N;;;;; +1F118;PARENTHESIZED LATIN CAPITAL LETTER I;So;0;L;<compat> 0028 0049 0029;;;;N;;;;; +1F119;PARENTHESIZED LATIN CAPITAL LETTER J;So;0;L;<compat> 0028 004A 0029;;;;N;;;;; +1F11A;PARENTHESIZED LATIN CAPITAL LETTER K;So;0;L;<compat> 0028 004B 0029;;;;N;;;;; +1F11B;PARENTHESIZED LATIN CAPITAL LETTER L;So;0;L;<compat> 0028 004C 0029;;;;N;;;;; +1F11C;PARENTHESIZED LATIN CAPITAL LETTER M;So;0;L;<compat> 0028 004D 0029;;;;N;;;;; +1F11D;PARENTHESIZED LATIN CAPITAL LETTER N;So;0;L;<compat> 0028 004E 0029;;;;N;;;;; +1F11E;PARENTHESIZED LATIN CAPITAL LETTER O;So;0;L;<compat> 0028 004F 0029;;;;N;;;;; +1F11F;PARENTHESIZED LATIN CAPITAL LETTER P;So;0;L;<compat> 0028 0050 0029;;;;N;;;;; +1F120;PARENTHESIZED LATIN CAPITAL LETTER Q;So;0;L;<compat> 0028 0051 0029;;;;N;;;;; +1F121;PARENTHESIZED LATIN CAPITAL LETTER R;So;0;L;<compat> 0028 0052 0029;;;;N;;;;; +1F122;PARENTHESIZED LATIN CAPITAL LETTER S;So;0;L;<compat> 0028 0053 0029;;;;N;;;;; +1F123;PARENTHESIZED LATIN CAPITAL LETTER T;So;0;L;<compat> 0028 0054 0029;;;;N;;;;; +1F124;PARENTHESIZED LATIN CAPITAL LETTER U;So;0;L;<compat> 0028 0055 0029;;;;N;;;;; +1F125;PARENTHESIZED LATIN CAPITAL LETTER V;So;0;L;<compat> 0028 0056 0029;;;;N;;;;; +1F126;PARENTHESIZED LATIN CAPITAL LETTER W;So;0;L;<compat> 0028 0057 0029;;;;N;;;;; +1F127;PARENTHESIZED LATIN CAPITAL LETTER X;So;0;L;<compat> 0028 0058 0029;;;;N;;;;; +1F128;PARENTHESIZED LATIN CAPITAL LETTER Y;So;0;L;<compat> 0028 0059 0029;;;;N;;;;; +1F129;PARENTHESIZED LATIN CAPITAL LETTER Z;So;0;L;<compat> 0028 005A 0029;;;;N;;;;; +1F12A;TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S;So;0;L;<compat> 3014 0053 3015;;;;N;;;;; +1F12B;CIRCLED ITALIC LATIN CAPITAL LETTER C;So;0;L;<circle> 0043;;;;N;;;;; +1F12C;CIRCLED ITALIC LATIN CAPITAL LETTER R;So;0;L;<circle> 0052;;;;N;;;;; +1F12D;CIRCLED CD;So;0;L;<circle> 0043 0044;;;;N;;;;; +1F12E;CIRCLED WZ;So;0;L;<circle> 0057 005A;;;;N;;;;; +1F130;SQUARED LATIN CAPITAL LETTER A;So;0;L;<square> 0041;;;;N;;;;; +1F131;SQUARED LATIN CAPITAL LETTER B;So;0;L;<square> 0042;;;;N;;;;; +1F132;SQUARED LATIN CAPITAL LETTER C;So;0;L;<square> 0043;;;;N;;;;; +1F133;SQUARED LATIN CAPITAL LETTER D;So;0;L;<square> 0044;;;;N;;;;; +1F134;SQUARED LATIN CAPITAL LETTER E;So;0;L;<square> 0045;;;;N;;;;; +1F135;SQUARED LATIN CAPITAL LETTER F;So;0;L;<square> 0046;;;;N;;;;; +1F136;SQUARED LATIN CAPITAL LETTER G;So;0;L;<square> 0047;;;;N;;;;; +1F137;SQUARED LATIN CAPITAL LETTER H;So;0;L;<square> 0048;;;;N;;;;; +1F138;SQUARED LATIN CAPITAL LETTER I;So;0;L;<square> 0049;;;;N;;;;; +1F139;SQUARED LATIN CAPITAL LETTER J;So;0;L;<square> 004A;;;;N;;;;; +1F13A;SQUARED LATIN CAPITAL LETTER K;So;0;L;<square> 004B;;;;N;;;;; +1F13B;SQUARED LATIN CAPITAL LETTER L;So;0;L;<square> 004C;;;;N;;;;; +1F13C;SQUARED LATIN CAPITAL LETTER M;So;0;L;<square> 004D;;;;N;;;;; +1F13D;SQUARED LATIN CAPITAL LETTER N;So;0;L;<square> 004E;;;;N;;;;; +1F13E;SQUARED LATIN CAPITAL LETTER O;So;0;L;<square> 004F;;;;N;;;;; +1F13F;SQUARED LATIN CAPITAL LETTER P;So;0;L;<square> 0050;;;;N;;;;; +1F140;SQUARED LATIN CAPITAL LETTER Q;So;0;L;<square> 0051;;;;N;;;;; +1F141;SQUARED LATIN CAPITAL LETTER R;So;0;L;<square> 0052;;;;N;;;;; +1F142;SQUARED LATIN CAPITAL LETTER S;So;0;L;<square> 0053;;;;N;;;;; +1F143;SQUARED LATIN CAPITAL LETTER T;So;0;L;<square> 0054;;;;N;;;;; +1F144;SQUARED LATIN CAPITAL LETTER U;So;0;L;<square> 0055;;;;N;;;;; +1F145;SQUARED LATIN CAPITAL LETTER V;So;0;L;<square> 0056;;;;N;;;;; +1F146;SQUARED LATIN CAPITAL LETTER W;So;0;L;<square> 0057;;;;N;;;;; +1F147;SQUARED LATIN CAPITAL LETTER X;So;0;L;<square> 0058;;;;N;;;;; +1F148;SQUARED LATIN CAPITAL LETTER Y;So;0;L;<square> 0059;;;;N;;;;; +1F149;SQUARED LATIN CAPITAL LETTER Z;So;0;L;<square> 005A;;;;N;;;;; +1F14A;SQUARED HV;So;0;L;<square> 0048 0056;;;;N;;;;; +1F14B;SQUARED MV;So;0;L;<square> 004D 0056;;;;N;;;;; +1F14C;SQUARED SD;So;0;L;<square> 0053 0044;;;;N;;;;; +1F14D;SQUARED SS;So;0;L;<square> 0053 0053;;;;N;;;;; +1F14E;SQUARED PPV;So;0;L;<square> 0050 0050 0056;;;;N;;;;; +1F14F;SQUARED WC;So;0;L;<square> 0057 0043;;;;N;;;;; +1F150;NEGATIVE CIRCLED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; +1F151;NEGATIVE CIRCLED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; +1F152;NEGATIVE CIRCLED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; +1F153;NEGATIVE CIRCLED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; +1F154;NEGATIVE CIRCLED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; +1F155;NEGATIVE CIRCLED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; +1F156;NEGATIVE CIRCLED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; +1F157;NEGATIVE CIRCLED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; +1F158;NEGATIVE CIRCLED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; +1F159;NEGATIVE CIRCLED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; +1F15A;NEGATIVE CIRCLED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; +1F15B;NEGATIVE CIRCLED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; +1F15C;NEGATIVE CIRCLED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; +1F15D;NEGATIVE CIRCLED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; +1F15E;NEGATIVE CIRCLED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; +1F15F;NEGATIVE CIRCLED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; +1F160;NEGATIVE CIRCLED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; +1F161;NEGATIVE CIRCLED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; +1F162;NEGATIVE CIRCLED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; +1F163;NEGATIVE CIRCLED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; +1F164;NEGATIVE CIRCLED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; +1F165;NEGATIVE CIRCLED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; +1F166;NEGATIVE CIRCLED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; +1F167;NEGATIVE CIRCLED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; +1F168;NEGATIVE CIRCLED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; +1F169;NEGATIVE CIRCLED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; +1F16A;RAISED MC SIGN;So;0;ON;<super> 004D 0043;;;;N;;;;; +1F16B;RAISED MD SIGN;So;0;ON;<super> 004D 0044;;;;N;;;;; +1F170;NEGATIVE SQUARED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; +1F171;NEGATIVE SQUARED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; +1F172;NEGATIVE SQUARED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; +1F173;NEGATIVE SQUARED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; +1F174;NEGATIVE SQUARED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; +1F175;NEGATIVE SQUARED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; +1F176;NEGATIVE SQUARED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; +1F177;NEGATIVE SQUARED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; +1F178;NEGATIVE SQUARED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; +1F179;NEGATIVE SQUARED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; +1F17A;NEGATIVE SQUARED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; +1F17B;NEGATIVE SQUARED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; +1F17C;NEGATIVE SQUARED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; +1F17D;NEGATIVE SQUARED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; +1F17E;NEGATIVE SQUARED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; +1F17F;NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; +1F180;NEGATIVE SQUARED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; +1F181;NEGATIVE SQUARED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; +1F182;NEGATIVE SQUARED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; +1F183;NEGATIVE SQUARED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; +1F184;NEGATIVE SQUARED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; +1F185;NEGATIVE SQUARED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; +1F186;NEGATIVE SQUARED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; +1F187;NEGATIVE SQUARED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; +1F188;NEGATIVE SQUARED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; +1F189;NEGATIVE SQUARED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; +1F18A;CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; +1F18B;NEGATIVE SQUARED IC;So;0;L;;;;;N;;;;; +1F18C;NEGATIVE SQUARED PA;So;0;L;;;;;N;;;;; +1F18D;NEGATIVE SQUARED SA;So;0;L;;;;;N;;;;; +1F18E;NEGATIVE SQUARED AB;So;0;L;;;;;N;;;;; +1F18F;NEGATIVE SQUARED WC;So;0;L;;;;;N;;;;; +1F190;SQUARE DJ;So;0;L;<square> 0044 004A;;;;N;;;;; +1F191;SQUARED CL;So;0;L;;;;;N;;;;; +1F192;SQUARED COOL;So;0;L;;;;;N;;;;; +1F193;SQUARED FREE;So;0;L;;;;;N;;;;; +1F194;SQUARED ID;So;0;L;;;;;N;;;;; +1F195;SQUARED NEW;So;0;L;;;;;N;;;;; +1F196;SQUARED NG;So;0;L;;;;;N;;;;; +1F197;SQUARED OK;So;0;L;;;;;N;;;;; +1F198;SQUARED SOS;So;0;L;;;;;N;;;;; +1F199;SQUARED UP WITH EXCLAMATION MARK;So;0;L;;;;;N;;;;; +1F19A;SQUARED VS;So;0;L;;;;;N;;;;; +1F19B;SQUARED THREE D;So;0;L;;;;;N;;;;; +1F19C;SQUARED SECOND SCREEN;So;0;L;;;;;N;;;;; +1F19D;SQUARED TWO K;So;0;L;;;;;N;;;;; +1F19E;SQUARED FOUR K;So;0;L;;;;;N;;;;; +1F19F;SQUARED EIGHT K;So;0;L;;;;;N;;;;; +1F1A0;SQUARED FIVE POINT ONE;So;0;L;;;;;N;;;;; +1F1A1;SQUARED SEVEN POINT ONE;So;0;L;;;;;N;;;;; +1F1A2;SQUARED TWENTY-TWO POINT TWO;So;0;L;;;;;N;;;;; +1F1A3;SQUARED SIXTY P;So;0;L;;;;;N;;;;; +1F1A4;SQUARED ONE HUNDRED TWENTY P;So;0;L;;;;;N;;;;; +1F1A5;SQUARED LATIN SMALL LETTER D;So;0;L;;;;;N;;;;; +1F1A6;SQUARED HC;So;0;L;;;;;N;;;;; +1F1A7;SQUARED HDR;So;0;L;;;;;N;;;;; +1F1A8;SQUARED HI-RES;So;0;L;;;;;N;;;;; +1F1A9;SQUARED LOSSLESS;So;0;L;;;;;N;;;;; +1F1AA;SQUARED SHV;So;0;L;;;;;N;;;;; +1F1AB;SQUARED UHD;So;0;L;;;;;N;;;;; +1F1AC;SQUARED VOD;So;0;L;;;;;N;;;;; +1F1E6;REGIONAL INDICATOR SYMBOL LETTER A;So;0;L;;;;;N;;;;; +1F1E7;REGIONAL INDICATOR SYMBOL LETTER B;So;0;L;;;;;N;;;;; +1F1E8;REGIONAL INDICATOR SYMBOL LETTER C;So;0;L;;;;;N;;;;; +1F1E9;REGIONAL INDICATOR SYMBOL LETTER D;So;0;L;;;;;N;;;;; +1F1EA;REGIONAL INDICATOR SYMBOL LETTER E;So;0;L;;;;;N;;;;; +1F1EB;REGIONAL INDICATOR SYMBOL LETTER F;So;0;L;;;;;N;;;;; +1F1EC;REGIONAL INDICATOR SYMBOL LETTER G;So;0;L;;;;;N;;;;; +1F1ED;REGIONAL INDICATOR SYMBOL LETTER H;So;0;L;;;;;N;;;;; +1F1EE;REGIONAL INDICATOR SYMBOL LETTER I;So;0;L;;;;;N;;;;; +1F1EF;REGIONAL INDICATOR SYMBOL LETTER J;So;0;L;;;;;N;;;;; +1F1F0;REGIONAL INDICATOR SYMBOL LETTER K;So;0;L;;;;;N;;;;; +1F1F1;REGIONAL INDICATOR SYMBOL LETTER L;So;0;L;;;;;N;;;;; +1F1F2;REGIONAL INDICATOR SYMBOL LETTER M;So;0;L;;;;;N;;;;; +1F1F3;REGIONAL INDICATOR SYMBOL LETTER N;So;0;L;;;;;N;;;;; +1F1F4;REGIONAL INDICATOR SYMBOL LETTER O;So;0;L;;;;;N;;;;; +1F1F5;REGIONAL INDICATOR SYMBOL LETTER P;So;0;L;;;;;N;;;;; +1F1F6;REGIONAL INDICATOR SYMBOL LETTER Q;So;0;L;;;;;N;;;;; +1F1F7;REGIONAL INDICATOR SYMBOL LETTER R;So;0;L;;;;;N;;;;; +1F1F8;REGIONAL INDICATOR SYMBOL LETTER S;So;0;L;;;;;N;;;;; +1F1F9;REGIONAL INDICATOR SYMBOL LETTER T;So;0;L;;;;;N;;;;; +1F1FA;REGIONAL INDICATOR SYMBOL LETTER U;So;0;L;;;;;N;;;;; +1F1FB;REGIONAL INDICATOR SYMBOL LETTER V;So;0;L;;;;;N;;;;; +1F1FC;REGIONAL INDICATOR SYMBOL LETTER W;So;0;L;;;;;N;;;;; +1F1FD;REGIONAL INDICATOR SYMBOL LETTER X;So;0;L;;;;;N;;;;; +1F1FE;REGIONAL INDICATOR SYMBOL LETTER Y;So;0;L;;;;;N;;;;; +1F1FF;REGIONAL INDICATOR SYMBOL LETTER Z;So;0;L;;;;;N;;;;; +1F200;SQUARE HIRAGANA HOKA;So;0;L;<square> 307B 304B;;;;N;;;;; +1F201;SQUARED KATAKANA KOKO;So;0;L;<square> 30B3 30B3;;;;N;;;;; +1F202;SQUARED KATAKANA SA;So;0;L;<square> 30B5;;;;N;;;;; +1F210;SQUARED CJK UNIFIED IDEOGRAPH-624B;So;0;L;<square> 624B;;;;N;;;;; +1F211;SQUARED CJK UNIFIED IDEOGRAPH-5B57;So;0;L;<square> 5B57;;;;N;;;;; +1F212;SQUARED CJK UNIFIED IDEOGRAPH-53CC;So;0;L;<square> 53CC;;;;N;;;;; +1F213;SQUARED KATAKANA DE;So;0;L;<square> 30C7;;;;N;;;;; +1F214;SQUARED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L;<square> 4E8C;;;;N;;;;; +1F215;SQUARED CJK UNIFIED IDEOGRAPH-591A;So;0;L;<square> 591A;;;;N;;;;; +1F216;SQUARED CJK UNIFIED IDEOGRAPH-89E3;So;0;L;<square> 89E3;;;;N;;;;; +1F217;SQUARED CJK UNIFIED IDEOGRAPH-5929;So;0;L;<square> 5929;;;;N;;;;; +1F218;SQUARED CJK UNIFIED IDEOGRAPH-4EA4;So;0;L;<square> 4EA4;;;;N;;;;; +1F219;SQUARED CJK UNIFIED IDEOGRAPH-6620;So;0;L;<square> 6620;;;;N;;;;; +1F21A;SQUARED CJK UNIFIED IDEOGRAPH-7121;So;0;L;<square> 7121;;;;N;;;;; +1F21B;SQUARED CJK UNIFIED IDEOGRAPH-6599;So;0;L;<square> 6599;;;;N;;;;; +1F21C;SQUARED CJK UNIFIED IDEOGRAPH-524D;So;0;L;<square> 524D;;;;N;;;;; +1F21D;SQUARED CJK UNIFIED IDEOGRAPH-5F8C;So;0;L;<square> 5F8C;;;;N;;;;; +1F21E;SQUARED CJK UNIFIED IDEOGRAPH-518D;So;0;L;<square> 518D;;;;N;;;;; +1F21F;SQUARED CJK UNIFIED IDEOGRAPH-65B0;So;0;L;<square> 65B0;;;;N;;;;; +1F220;SQUARED CJK UNIFIED IDEOGRAPH-521D;So;0;L;<square> 521D;;;;N;;;;; +1F221;SQUARED CJK UNIFIED IDEOGRAPH-7D42;So;0;L;<square> 7D42;;;;N;;;;; +1F222;SQUARED CJK UNIFIED IDEOGRAPH-751F;So;0;L;<square> 751F;;;;N;;;;; +1F223;SQUARED CJK UNIFIED IDEOGRAPH-8CA9;So;0;L;<square> 8CA9;;;;N;;;;; +1F224;SQUARED CJK UNIFIED IDEOGRAPH-58F0;So;0;L;<square> 58F0;;;;N;;;;; +1F225;SQUARED CJK UNIFIED IDEOGRAPH-5439;So;0;L;<square> 5439;;;;N;;;;; +1F226;SQUARED CJK UNIFIED IDEOGRAPH-6F14;So;0;L;<square> 6F14;;;;N;;;;; +1F227;SQUARED CJK UNIFIED IDEOGRAPH-6295;So;0;L;<square> 6295;;;;N;;;;; +1F228;SQUARED CJK UNIFIED IDEOGRAPH-6355;So;0;L;<square> 6355;;;;N;;;;; +1F229;SQUARED CJK UNIFIED IDEOGRAPH-4E00;So;0;L;<square> 4E00;;;;N;;;;; +1F22A;SQUARED CJK UNIFIED IDEOGRAPH-4E09;So;0;L;<square> 4E09;;;;N;;;;; +1F22B;SQUARED CJK UNIFIED IDEOGRAPH-904A;So;0;L;<square> 904A;;;;N;;;;; +1F22C;SQUARED CJK UNIFIED IDEOGRAPH-5DE6;So;0;L;<square> 5DE6;;;;N;;;;; +1F22D;SQUARED CJK UNIFIED IDEOGRAPH-4E2D;So;0;L;<square> 4E2D;;;;N;;;;; +1F22E;SQUARED CJK UNIFIED IDEOGRAPH-53F3;So;0;L;<square> 53F3;;;;N;;;;; +1F22F;SQUARED CJK UNIFIED IDEOGRAPH-6307;So;0;L;<square> 6307;;;;N;;;;; +1F230;SQUARED CJK UNIFIED IDEOGRAPH-8D70;So;0;L;<square> 8D70;;;;N;;;;; +1F231;SQUARED CJK UNIFIED IDEOGRAPH-6253;So;0;L;<square> 6253;;;;N;;;;; +1F232;SQUARED CJK UNIFIED IDEOGRAPH-7981;So;0;L;<square> 7981;;;;N;;;;; +1F233;SQUARED CJK UNIFIED IDEOGRAPH-7A7A;So;0;L;<square> 7A7A;;;;N;;;;; +1F234;SQUARED CJK UNIFIED IDEOGRAPH-5408;So;0;L;<square> 5408;;;;N;;;;; +1F235;SQUARED CJK UNIFIED IDEOGRAPH-6E80;So;0;L;<square> 6E80;;;;N;;;;; +1F236;SQUARED CJK UNIFIED IDEOGRAPH-6709;So;0;L;<square> 6709;;;;N;;;;; +1F237;SQUARED CJK UNIFIED IDEOGRAPH-6708;So;0;L;<square> 6708;;;;N;;;;; +1F238;SQUARED CJK UNIFIED IDEOGRAPH-7533;So;0;L;<square> 7533;;;;N;;;;; +1F239;SQUARED CJK UNIFIED IDEOGRAPH-5272;So;0;L;<square> 5272;;;;N;;;;; +1F23A;SQUARED CJK UNIFIED IDEOGRAPH-55B6;So;0;L;<square> 55B6;;;;N;;;;; +1F23B;SQUARED CJK UNIFIED IDEOGRAPH-914D;So;0;L;<square> 914D;;;;N;;;;; +1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L;<compat> 3014 672C 3015;;;;N;;;;; +1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L;<compat> 3014 4E09 3015;;;;N;;;;; +1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L;<compat> 3014 4E8C 3015;;;;N;;;;; +1F243;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89;So;0;L;<compat> 3014 5B89 3015;;;;N;;;;; +1F244;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9;So;0;L;<compat> 3014 70B9 3015;;;;N;;;;; +1F245;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253;So;0;L;<compat> 3014 6253 3015;;;;N;;;;; +1F246;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7;So;0;L;<compat> 3014 76D7 3015;;;;N;;;;; +1F247;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD;So;0;L;<compat> 3014 52DD 3015;;;;N;;;;; +1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L;<compat> 3014 6557 3015;;;;N;;;;; +1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L;<circle> 5F97;;;;N;;;;; +1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L;<circle> 53EF;;;;N;;;;; +1F260;ROUNDED SYMBOL FOR FU;So;0;ON;;;;;N;;;;; +1F261;ROUNDED SYMBOL FOR LU;So;0;ON;;;;;N;;;;; +1F262;ROUNDED SYMBOL FOR SHOU;So;0;ON;;;;;N;;;;; +1F263;ROUNDED SYMBOL FOR XI;So;0;ON;;;;;N;;;;; +1F264;ROUNDED SYMBOL FOR SHUANGXI;So;0;ON;;;;;N;;;;; +1F265;ROUNDED SYMBOL FOR CAI;So;0;ON;;;;;N;;;;; +1F300;CYCLONE;So;0;ON;;;;;N;;;;; +1F301;FOGGY;So;0;ON;;;;;N;;;;; +1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;; +1F303;NIGHT WITH STARS;So;0;ON;;;;;N;;;;; +1F304;SUNRISE OVER MOUNTAINS;So;0;ON;;;;;N;;;;; +1F305;SUNRISE;So;0;ON;;;;;N;;;;; +1F306;CITYSCAPE AT DUSK;So;0;ON;;;;;N;;;;; +1F307;SUNSET OVER BUILDINGS;So;0;ON;;;;;N;;;;; +1F308;RAINBOW;So;0;ON;;;;;N;;;;; +1F309;BRIDGE AT NIGHT;So;0;ON;;;;;N;;;;; +1F30A;WATER WAVE;So;0;ON;;;;;N;;;;; +1F30B;VOLCANO;So;0;ON;;;;;N;;;;; +1F30C;MILKY WAY;So;0;ON;;;;;N;;;;; +1F30D;EARTH GLOBE EUROPE-AFRICA;So;0;ON;;;;;N;;;;; +1F30E;EARTH GLOBE AMERICAS;So;0;ON;;;;;N;;;;; +1F30F;EARTH GLOBE ASIA-AUSTRALIA;So;0;ON;;;;;N;;;;; +1F310;GLOBE WITH MERIDIANS;So;0;ON;;;;;N;;;;; +1F311;NEW MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F312;WAXING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F313;FIRST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F314;WAXING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F315;FULL MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F316;WANING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F317;LAST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F318;WANING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F319;CRESCENT MOON;So;0;ON;;;;;N;;;;; +1F31A;NEW MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31B;FIRST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31C;LAST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31D;FULL MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31E;SUN WITH FACE;So;0;ON;;;;;N;;;;; +1F31F;GLOWING STAR;So;0;ON;;;;;N;;;;; +1F320;SHOOTING STAR;So;0;ON;;;;;N;;;;; +1F321;THERMOMETER;So;0;ON;;;;;N;;;;; +1F322;BLACK DROPLET;So;0;ON;;;;;N;;;;; +1F323;WHITE SUN;So;0;ON;;;;;N;;;;; +1F324;WHITE SUN WITH SMALL CLOUD;So;0;ON;;;;;N;;;;; +1F325;WHITE SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; +1F326;WHITE SUN BEHIND CLOUD WITH RAIN;So;0;ON;;;;;N;;;;; +1F327;CLOUD WITH RAIN;So;0;ON;;;;;N;;;;; +1F328;CLOUD WITH SNOW;So;0;ON;;;;;N;;;;; +1F329;CLOUD WITH LIGHTNING;So;0;ON;;;;;N;;;;; +1F32A;CLOUD WITH TORNADO;So;0;ON;;;;;N;;;;; +1F32B;FOG;So;0;ON;;;;;N;;;;; +1F32C;WIND BLOWING FACE;So;0;ON;;;;;N;;;;; +1F32D;HOT DOG;So;0;ON;;;;;N;;;;; +1F32E;TACO;So;0;ON;;;;;N;;;;; +1F32F;BURRITO;So;0;ON;;;;;N;;;;; +1F330;CHESTNUT;So;0;ON;;;;;N;;;;; +1F331;SEEDLING;So;0;ON;;;;;N;;;;; +1F332;EVERGREEN TREE;So;0;ON;;;;;N;;;;; +1F333;DECIDUOUS TREE;So;0;ON;;;;;N;;;;; +1F334;PALM TREE;So;0;ON;;;;;N;;;;; +1F335;CACTUS;So;0;ON;;;;;N;;;;; +1F336;HOT PEPPER;So;0;ON;;;;;N;;;;; +1F337;TULIP;So;0;ON;;;;;N;;;;; +1F338;CHERRY BLOSSOM;So;0;ON;;;;;N;;;;; +1F339;ROSE;So;0;ON;;;;;N;;;;; +1F33A;HIBISCUS;So;0;ON;;;;;N;;;;; +1F33B;SUNFLOWER;So;0;ON;;;;;N;;;;; +1F33C;BLOSSOM;So;0;ON;;;;;N;;;;; +1F33D;EAR OF MAIZE;So;0;ON;;;;;N;;;;; +1F33E;EAR OF RICE;So;0;ON;;;;;N;;;;; +1F33F;HERB;So;0;ON;;;;;N;;;;; +1F340;FOUR LEAF CLOVER;So;0;ON;;;;;N;;;;; +1F341;MAPLE LEAF;So;0;ON;;;;;N;;;;; +1F342;FALLEN LEAF;So;0;ON;;;;;N;;;;; +1F343;LEAF FLUTTERING IN WIND;So;0;ON;;;;;N;;;;; +1F344;MUSHROOM;So;0;ON;;;;;N;;;;; +1F345;TOMATO;So;0;ON;;;;;N;;;;; +1F346;AUBERGINE;So;0;ON;;;;;N;;;;; +1F347;GRAPES;So;0;ON;;;;;N;;;;; +1F348;MELON;So;0;ON;;;;;N;;;;; +1F349;WATERMELON;So;0;ON;;;;;N;;;;; +1F34A;TANGERINE;So;0;ON;;;;;N;;;;; +1F34B;LEMON;So;0;ON;;;;;N;;;;; +1F34C;BANANA;So;0;ON;;;;;N;;;;; +1F34D;PINEAPPLE;So;0;ON;;;;;N;;;;; +1F34E;RED APPLE;So;0;ON;;;;;N;;;;; +1F34F;GREEN APPLE;So;0;ON;;;;;N;;;;; +1F350;PEAR;So;0;ON;;;;;N;;;;; +1F351;PEACH;So;0;ON;;;;;N;;;;; +1F352;CHERRIES;So;0;ON;;;;;N;;;;; +1F353;STRAWBERRY;So;0;ON;;;;;N;;;;; +1F354;HAMBURGER;So;0;ON;;;;;N;;;;; +1F355;SLICE OF PIZZA;So;0;ON;;;;;N;;;;; +1F356;MEAT ON BONE;So;0;ON;;;;;N;;;;; +1F357;POULTRY LEG;So;0;ON;;;;;N;;;;; +1F358;RICE CRACKER;So;0;ON;;;;;N;;;;; +1F359;RICE BALL;So;0;ON;;;;;N;;;;; +1F35A;COOKED RICE;So;0;ON;;;;;N;;;;; +1F35B;CURRY AND RICE;So;0;ON;;;;;N;;;;; +1F35C;STEAMING BOWL;So;0;ON;;;;;N;;;;; +1F35D;SPAGHETTI;So;0;ON;;;;;N;;;;; +1F35E;BREAD;So;0;ON;;;;;N;;;;; +1F35F;FRENCH FRIES;So;0;ON;;;;;N;;;;; +1F360;ROASTED SWEET POTATO;So;0;ON;;;;;N;;;;; +1F361;DANGO;So;0;ON;;;;;N;;;;; +1F362;ODEN;So;0;ON;;;;;N;;;;; +1F363;SUSHI;So;0;ON;;;;;N;;;;; +1F364;FRIED SHRIMP;So;0;ON;;;;;N;;;;; +1F365;FISH CAKE WITH SWIRL DESIGN;So;0;ON;;;;;N;;;;; +1F366;SOFT ICE CREAM;So;0;ON;;;;;N;;;;; +1F367;SHAVED ICE;So;0;ON;;;;;N;;;;; +1F368;ICE CREAM;So;0;ON;;;;;N;;;;; +1F369;DOUGHNUT;So;0;ON;;;;;N;;;;; +1F36A;COOKIE;So;0;ON;;;;;N;;;;; +1F36B;CHOCOLATE BAR;So;0;ON;;;;;N;;;;; +1F36C;CANDY;So;0;ON;;;;;N;;;;; +1F36D;LOLLIPOP;So;0;ON;;;;;N;;;;; +1F36E;CUSTARD;So;0;ON;;;;;N;;;;; +1F36F;HONEY POT;So;0;ON;;;;;N;;;;; +1F370;SHORTCAKE;So;0;ON;;;;;N;;;;; +1F371;BENTO BOX;So;0;ON;;;;;N;;;;; +1F372;POT OF FOOD;So;0;ON;;;;;N;;;;; +1F373;COOKING;So;0;ON;;;;;N;;;;; +1F374;FORK AND KNIFE;So;0;ON;;;;;N;;;;; +1F375;TEACUP WITHOUT HANDLE;So;0;ON;;;;;N;;;;; +1F376;SAKE BOTTLE AND CUP;So;0;ON;;;;;N;;;;; +1F377;WINE GLASS;So;0;ON;;;;;N;;;;; +1F378;COCKTAIL GLASS;So;0;ON;;;;;N;;;;; +1F379;TROPICAL DRINK;So;0;ON;;;;;N;;;;; +1F37A;BEER MUG;So;0;ON;;;;;N;;;;; +1F37B;CLINKING BEER MUGS;So;0;ON;;;;;N;;;;; +1F37C;BABY BOTTLE;So;0;ON;;;;;N;;;;; +1F37D;FORK AND KNIFE WITH PLATE;So;0;ON;;;;;N;;;;; +1F37E;BOTTLE WITH POPPING CORK;So;0;ON;;;;;N;;;;; +1F37F;POPCORN;So;0;ON;;;;;N;;;;; +1F380;RIBBON;So;0;ON;;;;;N;;;;; +1F381;WRAPPED PRESENT;So;0;ON;;;;;N;;;;; +1F382;BIRTHDAY CAKE;So;0;ON;;;;;N;;;;; +1F383;JACK-O-LANTERN;So;0;ON;;;;;N;;;;; +1F384;CHRISTMAS TREE;So;0;ON;;;;;N;;;;; +1F385;FATHER CHRISTMAS;So;0;ON;;;;;N;;;;; +1F386;FIREWORKS;So;0;ON;;;;;N;;;;; +1F387;FIREWORK SPARKLER;So;0;ON;;;;;N;;;;; +1F388;BALLOON;So;0;ON;;;;;N;;;;; +1F389;PARTY POPPER;So;0;ON;;;;;N;;;;; +1F38A;CONFETTI BALL;So;0;ON;;;;;N;;;;; +1F38B;TANABATA TREE;So;0;ON;;;;;N;;;;; +1F38C;CROSSED FLAGS;So;0;ON;;;;;N;;;;; +1F38D;PINE DECORATION;So;0;ON;;;;;N;;;;; +1F38E;JAPANESE DOLLS;So;0;ON;;;;;N;;;;; +1F38F;CARP STREAMER;So;0;ON;;;;;N;;;;; +1F390;WIND CHIME;So;0;ON;;;;;N;;;;; +1F391;MOON VIEWING CEREMONY;So;0;ON;;;;;N;;;;; +1F392;SCHOOL SATCHEL;So;0;ON;;;;;N;;;;; +1F393;GRADUATION CAP;So;0;ON;;;;;N;;;;; +1F394;HEART WITH TIP ON THE LEFT;So;0;ON;;;;;N;;;;; +1F395;BOUQUET OF FLOWERS;So;0;ON;;;;;N;;;;; +1F396;MILITARY MEDAL;So;0;ON;;;;;N;;;;; +1F397;REMINDER RIBBON;So;0;ON;;;;;N;;;;; +1F398;MUSICAL KEYBOARD WITH JACKS;So;0;ON;;;;;N;;;;; +1F399;STUDIO MICROPHONE;So;0;ON;;;;;N;;;;; +1F39A;LEVEL SLIDER;So;0;ON;;;;;N;;;;; +1F39B;CONTROL KNOBS;So;0;ON;;;;;N;;;;; +1F39C;BEAMED ASCENDING MUSICAL NOTES;So;0;ON;;;;;N;;;;; +1F39D;BEAMED DESCENDING MUSICAL NOTES;So;0;ON;;;;;N;;;;; +1F39E;FILM FRAMES;So;0;ON;;;;;N;;;;; +1F39F;ADMISSION TICKETS;So;0;ON;;;;;N;;;;; +1F3A0;CAROUSEL HORSE;So;0;ON;;;;;N;;;;; +1F3A1;FERRIS WHEEL;So;0;ON;;;;;N;;;;; +1F3A2;ROLLER COASTER;So;0;ON;;;;;N;;;;; +1F3A3;FISHING POLE AND FISH;So;0;ON;;;;;N;;;;; +1F3A4;MICROPHONE;So;0;ON;;;;;N;;;;; +1F3A5;MOVIE CAMERA;So;0;ON;;;;;N;;;;; +1F3A6;CINEMA;So;0;ON;;;;;N;;;;; +1F3A7;HEADPHONE;So;0;ON;;;;;N;;;;; +1F3A8;ARTIST PALETTE;So;0;ON;;;;;N;;;;; +1F3A9;TOP HAT;So;0;ON;;;;;N;;;;; +1F3AA;CIRCUS TENT;So;0;ON;;;;;N;;;;; +1F3AB;TICKET;So;0;ON;;;;;N;;;;; +1F3AC;CLAPPER BOARD;So;0;ON;;;;;N;;;;; +1F3AD;PERFORMING ARTS;So;0;ON;;;;;N;;;;; +1F3AE;VIDEO GAME;So;0;ON;;;;;N;;;;; +1F3AF;DIRECT HIT;So;0;ON;;;;;N;;;;; +1F3B0;SLOT MACHINE;So;0;ON;;;;;N;;;;; +1F3B1;BILLIARDS;So;0;ON;;;;;N;;;;; +1F3B2;GAME DIE;So;0;ON;;;;;N;;;;; +1F3B3;BOWLING;So;0;ON;;;;;N;;;;; +1F3B4;FLOWER PLAYING CARDS;So;0;ON;;;;;N;;;;; +1F3B5;MUSICAL NOTE;So;0;ON;;;;;N;;;;; +1F3B6;MULTIPLE MUSICAL NOTES;So;0;ON;;;;;N;;;;; +1F3B7;SAXOPHONE;So;0;ON;;;;;N;;;;; +1F3B8;GUITAR;So;0;ON;;;;;N;;;;; +1F3B9;MUSICAL KEYBOARD;So;0;ON;;;;;N;;;;; +1F3BA;TRUMPET;So;0;ON;;;;;N;;;;; +1F3BB;VIOLIN;So;0;ON;;;;;N;;;;; +1F3BC;MUSICAL SCORE;So;0;ON;;;;;N;;;;; +1F3BD;RUNNING SHIRT WITH SASH;So;0;ON;;;;;N;;;;; +1F3BE;TENNIS RACQUET AND BALL;So;0;ON;;;;;N;;;;; +1F3BF;SKI AND SKI BOOT;So;0;ON;;;;;N;;;;; +1F3C0;BASKETBALL AND HOOP;So;0;ON;;;;;N;;;;; +1F3C1;CHEQUERED FLAG;So;0;ON;;;;;N;;;;; +1F3C2;SNOWBOARDER;So;0;ON;;;;;N;;;;; +1F3C3;RUNNER;So;0;ON;;;;;N;;;;; +1F3C4;SURFER;So;0;ON;;;;;N;;;;; +1F3C5;SPORTS MEDAL;So;0;ON;;;;;N;;;;; +1F3C6;TROPHY;So;0;ON;;;;;N;;;;; +1F3C7;HORSE RACING;So;0;ON;;;;;N;;;;; +1F3C8;AMERICAN FOOTBALL;So;0;ON;;;;;N;;;;; +1F3C9;RUGBY FOOTBALL;So;0;ON;;;;;N;;;;; +1F3CA;SWIMMER;So;0;ON;;;;;N;;;;; +1F3CB;WEIGHT LIFTER;So;0;ON;;;;;N;;;;; +1F3CC;GOLFER;So;0;ON;;;;;N;;;;; +1F3CD;RACING MOTORCYCLE;So;0;ON;;;;;N;;;;; +1F3CE;RACING CAR;So;0;ON;;;;;N;;;;; +1F3CF;CRICKET BAT AND BALL;So;0;ON;;;;;N;;;;; +1F3D0;VOLLEYBALL;So;0;ON;;;;;N;;;;; +1F3D1;FIELD HOCKEY STICK AND BALL;So;0;ON;;;;;N;;;;; +1F3D2;ICE HOCKEY STICK AND PUCK;So;0;ON;;;;;N;;;;; +1F3D3;TABLE TENNIS PADDLE AND BALL;So;0;ON;;;;;N;;;;; +1F3D4;SNOW CAPPED MOUNTAIN;So;0;ON;;;;;N;;;;; +1F3D5;CAMPING;So;0;ON;;;;;N;;;;; +1F3D6;BEACH WITH UMBRELLA;So;0;ON;;;;;N;;;;; +1F3D7;BUILDING CONSTRUCTION;So;0;ON;;;;;N;;;;; +1F3D8;HOUSE BUILDINGS;So;0;ON;;;;;N;;;;; +1F3D9;CITYSCAPE;So;0;ON;;;;;N;;;;; +1F3DA;DERELICT HOUSE BUILDING;So;0;ON;;;;;N;;;;; +1F3DB;CLASSICAL BUILDING;So;0;ON;;;;;N;;;;; +1F3DC;DESERT;So;0;ON;;;;;N;;;;; +1F3DD;DESERT ISLAND;So;0;ON;;;;;N;;;;; +1F3DE;NATIONAL PARK;So;0;ON;;;;;N;;;;; +1F3DF;STADIUM;So;0;ON;;;;;N;;;;; +1F3E0;HOUSE BUILDING;So;0;ON;;;;;N;;;;; +1F3E1;HOUSE WITH GARDEN;So;0;ON;;;;;N;;;;; +1F3E2;OFFICE BUILDING;So;0;ON;;;;;N;;;;; +1F3E3;JAPANESE POST OFFICE;So;0;ON;;;;;N;;;;; +1F3E4;EUROPEAN POST OFFICE;So;0;ON;;;;;N;;;;; +1F3E5;HOSPITAL;So;0;ON;;;;;N;;;;; +1F3E6;BANK;So;0;ON;;;;;N;;;;; +1F3E7;AUTOMATED TELLER MACHINE;So;0;ON;;;;;N;;;;; +1F3E8;HOTEL;So;0;ON;;;;;N;;;;; +1F3E9;LOVE HOTEL;So;0;ON;;;;;N;;;;; +1F3EA;CONVENIENCE STORE;So;0;ON;;;;;N;;;;; +1F3EB;SCHOOL;So;0;ON;;;;;N;;;;; +1F3EC;DEPARTMENT STORE;So;0;ON;;;;;N;;;;; +1F3ED;FACTORY;So;0;ON;;;;;N;;;;; +1F3EE;IZAKAYA LANTERN;So;0;ON;;;;;N;;;;; +1F3EF;JAPANESE CASTLE;So;0;ON;;;;;N;;;;; +1F3F0;EUROPEAN CASTLE;So;0;ON;;;;;N;;;;; +1F3F1;WHITE PENNANT;So;0;ON;;;;;N;;;;; +1F3F2;BLACK PENNANT;So;0;ON;;;;;N;;;;; +1F3F3;WAVING WHITE FLAG;So;0;ON;;;;;N;;;;; +1F3F4;WAVING BLACK FLAG;So;0;ON;;;;;N;;;;; +1F3F5;ROSETTE;So;0;ON;;;;;N;;;;; +1F3F6;BLACK ROSETTE;So;0;ON;;;;;N;;;;; +1F3F7;LABEL;So;0;ON;;;;;N;;;;; +1F3F8;BADMINTON RACQUET AND SHUTTLECOCK;So;0;ON;;;;;N;;;;; +1F3F9;BOW AND ARROW;So;0;ON;;;;;N;;;;; +1F3FA;AMPHORA;So;0;ON;;;;;N;;;;; +1F3FB;EMOJI MODIFIER FITZPATRICK TYPE-1-2;Sk;0;ON;;;;;N;;;;; +1F3FC;EMOJI MODIFIER FITZPATRICK TYPE-3;Sk;0;ON;;;;;N;;;;; +1F3FD;EMOJI MODIFIER FITZPATRICK TYPE-4;Sk;0;ON;;;;;N;;;;; +1F3FE;EMOJI MODIFIER FITZPATRICK TYPE-5;Sk;0;ON;;;;;N;;;;; +1F3FF;EMOJI MODIFIER FITZPATRICK TYPE-6;Sk;0;ON;;;;;N;;;;; +1F400;RAT;So;0;ON;;;;;N;;;;; +1F401;MOUSE;So;0;ON;;;;;N;;;;; +1F402;OX;So;0;ON;;;;;N;;;;; +1F403;WATER BUFFALO;So;0;ON;;;;;N;;;;; +1F404;COW;So;0;ON;;;;;N;;;;; +1F405;TIGER;So;0;ON;;;;;N;;;;; +1F406;LEOPARD;So;0;ON;;;;;N;;;;; +1F407;RABBIT;So;0;ON;;;;;N;;;;; +1F408;CAT;So;0;ON;;;;;N;;;;; +1F409;DRAGON;So;0;ON;;;;;N;;;;; +1F40A;CROCODILE;So;0;ON;;;;;N;;;;; +1F40B;WHALE;So;0;ON;;;;;N;;;;; +1F40C;SNAIL;So;0;ON;;;;;N;;;;; +1F40D;SNAKE;So;0;ON;;;;;N;;;;; +1F40E;HORSE;So;0;ON;;;;;N;;;;; +1F40F;RAM;So;0;ON;;;;;N;;;;; +1F410;GOAT;So;0;ON;;;;;N;;;;; +1F411;SHEEP;So;0;ON;;;;;N;;;;; +1F412;MONKEY;So;0;ON;;;;;N;;;;; +1F413;ROOSTER;So;0;ON;;;;;N;;;;; +1F414;CHICKEN;So;0;ON;;;;;N;;;;; +1F415;DOG;So;0;ON;;;;;N;;;;; +1F416;PIG;So;0;ON;;;;;N;;;;; +1F417;BOAR;So;0;ON;;;;;N;;;;; +1F418;ELEPHANT;So;0;ON;;;;;N;;;;; +1F419;OCTOPUS;So;0;ON;;;;;N;;;;; +1F41A;SPIRAL SHELL;So;0;ON;;;;;N;;;;; +1F41B;BUG;So;0;ON;;;;;N;;;;; +1F41C;ANT;So;0;ON;;;;;N;;;;; +1F41D;HONEYBEE;So;0;ON;;;;;N;;;;; +1F41E;LADY BEETLE;So;0;ON;;;;;N;;;;; +1F41F;FISH;So;0;ON;;;;;N;;;;; +1F420;TROPICAL FISH;So;0;ON;;;;;N;;;;; +1F421;BLOWFISH;So;0;ON;;;;;N;;;;; +1F422;TURTLE;So;0;ON;;;;;N;;;;; +1F423;HATCHING CHICK;So;0;ON;;;;;N;;;;; +1F424;BABY CHICK;So;0;ON;;;;;N;;;;; +1F425;FRONT-FACING BABY CHICK;So;0;ON;;;;;N;;;;; +1F426;BIRD;So;0;ON;;;;;N;;;;; +1F427;PENGUIN;So;0;ON;;;;;N;;;;; +1F428;KOALA;So;0;ON;;;;;N;;;;; +1F429;POODLE;So;0;ON;;;;;N;;;;; +1F42A;DROMEDARY CAMEL;So;0;ON;;;;;N;;;;; +1F42B;BACTRIAN CAMEL;So;0;ON;;;;;N;;;;; +1F42C;DOLPHIN;So;0;ON;;;;;N;;;;; +1F42D;MOUSE FACE;So;0;ON;;;;;N;;;;; +1F42E;COW FACE;So;0;ON;;;;;N;;;;; +1F42F;TIGER FACE;So;0;ON;;;;;N;;;;; +1F430;RABBIT FACE;So;0;ON;;;;;N;;;;; +1F431;CAT FACE;So;0;ON;;;;;N;;;;; +1F432;DRAGON FACE;So;0;ON;;;;;N;;;;; +1F433;SPOUTING WHALE;So;0;ON;;;;;N;;;;; +1F434;HORSE FACE;So;0;ON;;;;;N;;;;; +1F435;MONKEY FACE;So;0;ON;;;;;N;;;;; +1F436;DOG FACE;So;0;ON;;;;;N;;;;; +1F437;PIG FACE;So;0;ON;;;;;N;;;;; +1F438;FROG FACE;So;0;ON;;;;;N;;;;; +1F439;HAMSTER FACE;So;0;ON;;;;;N;;;;; +1F43A;WOLF FACE;So;0;ON;;;;;N;;;;; +1F43B;BEAR FACE;So;0;ON;;;;;N;;;;; +1F43C;PANDA FACE;So;0;ON;;;;;N;;;;; +1F43D;PIG NOSE;So;0;ON;;;;;N;;;;; +1F43E;PAW PRINTS;So;0;ON;;;;;N;;;;; +1F43F;CHIPMUNK;So;0;ON;;;;;N;;;;; +1F440;EYES;So;0;ON;;;;;N;;;;; +1F441;EYE;So;0;ON;;;;;N;;;;; +1F442;EAR;So;0;ON;;;;;N;;;;; +1F443;NOSE;So;0;ON;;;;;N;;;;; +1F444;MOUTH;So;0;ON;;;;;N;;;;; +1F445;TONGUE;So;0;ON;;;;;N;;;;; +1F446;WHITE UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F447;WHITE DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F448;WHITE LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F449;WHITE RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F44A;FISTED HAND SIGN;So;0;ON;;;;;N;;;;; +1F44B;WAVING HAND SIGN;So;0;ON;;;;;N;;;;; +1F44C;OK HAND SIGN;So;0;ON;;;;;N;;;;; +1F44D;THUMBS UP SIGN;So;0;ON;;;;;N;;;;; +1F44E;THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; +1F44F;CLAPPING HANDS SIGN;So;0;ON;;;;;N;;;;; +1F450;OPEN HANDS SIGN;So;0;ON;;;;;N;;;;; +1F451;CROWN;So;0;ON;;;;;N;;;;; +1F452;WOMANS HAT;So;0;ON;;;;;N;;;;; +1F453;EYEGLASSES;So;0;ON;;;;;N;;;;; +1F454;NECKTIE;So;0;ON;;;;;N;;;;; +1F455;T-SHIRT;So;0;ON;;;;;N;;;;; +1F456;JEANS;So;0;ON;;;;;N;;;;; +1F457;DRESS;So;0;ON;;;;;N;;;;; +1F458;KIMONO;So;0;ON;;;;;N;;;;; +1F459;BIKINI;So;0;ON;;;;;N;;;;; +1F45A;WOMANS CLOTHES;So;0;ON;;;;;N;;;;; +1F45B;PURSE;So;0;ON;;;;;N;;;;; +1F45C;HANDBAG;So;0;ON;;;;;N;;;;; +1F45D;POUCH;So;0;ON;;;;;N;;;;; +1F45E;MANS SHOE;So;0;ON;;;;;N;;;;; +1F45F;ATHLETIC SHOE;So;0;ON;;;;;N;;;;; +1F460;HIGH-HEELED SHOE;So;0;ON;;;;;N;;;;; +1F461;WOMANS SANDAL;So;0;ON;;;;;N;;;;; +1F462;WOMANS BOOTS;So;0;ON;;;;;N;;;;; +1F463;FOOTPRINTS;So;0;ON;;;;;N;;;;; +1F464;BUST IN SILHOUETTE;So;0;ON;;;;;N;;;;; +1F465;BUSTS IN SILHOUETTE;So;0;ON;;;;;N;;;;; +1F466;BOY;So;0;ON;;;;;N;;;;; +1F467;GIRL;So;0;ON;;;;;N;;;;; +1F468;MAN;So;0;ON;;;;;N;;;;; +1F469;WOMAN;So;0;ON;;;;;N;;;;; +1F46A;FAMILY;So;0;ON;;;;;N;;;;; +1F46B;MAN AND WOMAN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46C;TWO MEN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46D;TWO WOMEN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46E;POLICE OFFICER;So;0;ON;;;;;N;;;;; +1F46F;WOMAN WITH BUNNY EARS;So;0;ON;;;;;N;;;;; +1F470;BRIDE WITH VEIL;So;0;ON;;;;;N;;;;; +1F471;PERSON WITH BLOND HAIR;So;0;ON;;;;;N;;;;; +1F472;MAN WITH GUA PI MAO;So;0;ON;;;;;N;;;;; +1F473;MAN WITH TURBAN;So;0;ON;;;;;N;;;;; +1F474;OLDER MAN;So;0;ON;;;;;N;;;;; +1F475;OLDER WOMAN;So;0;ON;;;;;N;;;;; +1F476;BABY;So;0;ON;;;;;N;;;;; +1F477;CONSTRUCTION WORKER;So;0;ON;;;;;N;;;;; +1F478;PRINCESS;So;0;ON;;;;;N;;;;; +1F479;JAPANESE OGRE;So;0;ON;;;;;N;;;;; +1F47A;JAPANESE GOBLIN;So;0;ON;;;;;N;;;;; +1F47B;GHOST;So;0;ON;;;;;N;;;;; +1F47C;BABY ANGEL;So;0;ON;;;;;N;;;;; +1F47D;EXTRATERRESTRIAL ALIEN;So;0;ON;;;;;N;;;;; +1F47E;ALIEN MONSTER;So;0;ON;;;;;N;;;;; +1F47F;IMP;So;0;ON;;;;;N;;;;; +1F480;SKULL;So;0;ON;;;;;N;;;;; +1F481;INFORMATION DESK PERSON;So;0;ON;;;;;N;;;;; +1F482;GUARDSMAN;So;0;ON;;;;;N;;;;; +1F483;DANCER;So;0;ON;;;;;N;;;;; +1F484;LIPSTICK;So;0;ON;;;;;N;;;;; +1F485;NAIL POLISH;So;0;ON;;;;;N;;;;; +1F486;FACE MASSAGE;So;0;ON;;;;;N;;;;; +1F487;HAIRCUT;So;0;ON;;;;;N;;;;; +1F488;BARBER POLE;So;0;ON;;;;;N;;;;; +1F489;SYRINGE;So;0;ON;;;;;N;;;;; +1F48A;PILL;So;0;ON;;;;;N;;;;; +1F48B;KISS MARK;So;0;ON;;;;;N;;;;; +1F48C;LOVE LETTER;So;0;ON;;;;;N;;;;; +1F48D;RING;So;0;ON;;;;;N;;;;; +1F48E;GEM STONE;So;0;ON;;;;;N;;;;; +1F48F;KISS;So;0;ON;;;;;N;;;;; +1F490;BOUQUET;So;0;ON;;;;;N;;;;; +1F491;COUPLE WITH HEART;So;0;ON;;;;;N;;;;; +1F492;WEDDING;So;0;ON;;;;;N;;;;; +1F493;BEATING HEART;So;0;ON;;;;;N;;;;; +1F494;BROKEN HEART;So;0;ON;;;;;N;;;;; +1F495;TWO HEARTS;So;0;ON;;;;;N;;;;; +1F496;SPARKLING HEART;So;0;ON;;;;;N;;;;; +1F497;GROWING HEART;So;0;ON;;;;;N;;;;; +1F498;HEART WITH ARROW;So;0;ON;;;;;N;;;;; +1F499;BLUE HEART;So;0;ON;;;;;N;;;;; +1F49A;GREEN HEART;So;0;ON;;;;;N;;;;; +1F49B;YELLOW HEART;So;0;ON;;;;;N;;;;; +1F49C;PURPLE HEART;So;0;ON;;;;;N;;;;; +1F49D;HEART WITH RIBBON;So;0;ON;;;;;N;;;;; +1F49E;REVOLVING HEARTS;So;0;ON;;;;;N;;;;; +1F49F;HEART DECORATION;So;0;ON;;;;;N;;;;; +1F4A0;DIAMOND SHAPE WITH A DOT INSIDE;So;0;ON;;;;;N;;;;; +1F4A1;ELECTRIC LIGHT BULB;So;0;ON;;;;;N;;;;; +1F4A2;ANGER SYMBOL;So;0;ON;;;;;N;;;;; +1F4A3;BOMB;So;0;ON;;;;;N;;;;; +1F4A4;SLEEPING SYMBOL;So;0;ON;;;;;N;;;;; +1F4A5;COLLISION SYMBOL;So;0;ON;;;;;N;;;;; +1F4A6;SPLASHING SWEAT SYMBOL;So;0;ON;;;;;N;;;;; +1F4A7;DROPLET;So;0;ON;;;;;N;;;;; +1F4A8;DASH SYMBOL;So;0;ON;;;;;N;;;;; +1F4A9;PILE OF POO;So;0;ON;;;;;N;;;;; +1F4AA;FLEXED BICEPS;So;0;ON;;;;;N;;;;; +1F4AB;DIZZY SYMBOL;So;0;ON;;;;;N;;;;; +1F4AC;SPEECH BALLOON;So;0;ON;;;;;N;;;;; +1F4AD;THOUGHT BALLOON;So;0;ON;;;;;N;;;;; +1F4AE;WHITE FLOWER;So;0;ON;;;;;N;;;;; +1F4AF;HUNDRED POINTS SYMBOL;So;0;ON;;;;;N;;;;; +1F4B0;MONEY BAG;So;0;ON;;;;;N;;;;; +1F4B1;CURRENCY EXCHANGE;So;0;ON;;;;;N;;;;; +1F4B2;HEAVY DOLLAR SIGN;So;0;ON;;;;;N;;;;; +1F4B3;CREDIT CARD;So;0;ON;;;;;N;;;;; +1F4B4;BANKNOTE WITH YEN SIGN;So;0;ON;;;;;N;;;;; +1F4B5;BANKNOTE WITH DOLLAR SIGN;So;0;ON;;;;;N;;;;; +1F4B6;BANKNOTE WITH EURO SIGN;So;0;ON;;;;;N;;;;; +1F4B7;BANKNOTE WITH POUND SIGN;So;0;ON;;;;;N;;;;; +1F4B8;MONEY WITH WINGS;So;0;ON;;;;;N;;;;; +1F4B9;CHART WITH UPWARDS TREND AND YEN SIGN;So;0;ON;;;;;N;;;;; +1F4BA;SEAT;So;0;ON;;;;;N;;;;; +1F4BB;PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; +1F4BC;BRIEFCASE;So;0;ON;;;;;N;;;;; +1F4BD;MINIDISC;So;0;ON;;;;;N;;;;; +1F4BE;FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F4BF;OPTICAL DISC;So;0;ON;;;;;N;;;;; +1F4C0;DVD;So;0;ON;;;;;N;;;;; +1F4C1;FILE FOLDER;So;0;ON;;;;;N;;;;; +1F4C2;OPEN FILE FOLDER;So;0;ON;;;;;N;;;;; +1F4C3;PAGE WITH CURL;So;0;ON;;;;;N;;;;; +1F4C4;PAGE FACING UP;So;0;ON;;;;;N;;;;; +1F4C5;CALENDAR;So;0;ON;;;;;N;;;;; +1F4C6;TEAR-OFF CALENDAR;So;0;ON;;;;;N;;;;; +1F4C7;CARD INDEX;So;0;ON;;;;;N;;;;; +1F4C8;CHART WITH UPWARDS TREND;So;0;ON;;;;;N;;;;; +1F4C9;CHART WITH DOWNWARDS TREND;So;0;ON;;;;;N;;;;; +1F4CA;BAR CHART;So;0;ON;;;;;N;;;;; +1F4CB;CLIPBOARD;So;0;ON;;;;;N;;;;; +1F4CC;PUSHPIN;So;0;ON;;;;;N;;;;; +1F4CD;ROUND PUSHPIN;So;0;ON;;;;;N;;;;; +1F4CE;PAPERCLIP;So;0;ON;;;;;N;;;;; +1F4CF;STRAIGHT RULER;So;0;ON;;;;;N;;;;; +1F4D0;TRIANGULAR RULER;So;0;ON;;;;;N;;;;; +1F4D1;BOOKMARK TABS;So;0;ON;;;;;N;;;;; +1F4D2;LEDGER;So;0;ON;;;;;N;;;;; +1F4D3;NOTEBOOK;So;0;ON;;;;;N;;;;; +1F4D4;NOTEBOOK WITH DECORATIVE COVER;So;0;ON;;;;;N;;;;; +1F4D5;CLOSED BOOK;So;0;ON;;;;;N;;;;; +1F4D6;OPEN BOOK;So;0;ON;;;;;N;;;;; +1F4D7;GREEN BOOK;So;0;ON;;;;;N;;;;; +1F4D8;BLUE BOOK;So;0;ON;;;;;N;;;;; +1F4D9;ORANGE BOOK;So;0;ON;;;;;N;;;;; +1F4DA;BOOKS;So;0;ON;;;;;N;;;;; +1F4DB;NAME BADGE;So;0;ON;;;;;N;;;;; +1F4DC;SCROLL;So;0;ON;;;;;N;;;;; +1F4DD;MEMO;So;0;ON;;;;;N;;;;; +1F4DE;TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; +1F4DF;PAGER;So;0;ON;;;;;N;;;;; +1F4E0;FAX MACHINE;So;0;ON;;;;;N;;;;; +1F4E1;SATELLITE ANTENNA;So;0;ON;;;;;N;;;;; +1F4E2;PUBLIC ADDRESS LOUDSPEAKER;So;0;ON;;;;;N;;;;; +1F4E3;CHEERING MEGAPHONE;So;0;ON;;;;;N;;;;; +1F4E4;OUTBOX TRAY;So;0;ON;;;;;N;;;;; +1F4E5;INBOX TRAY;So;0;ON;;;;;N;;;;; +1F4E6;PACKAGE;So;0;ON;;;;;N;;;;; +1F4E7;E-MAIL SYMBOL;So;0;ON;;;;;N;;;;; +1F4E8;INCOMING ENVELOPE;So;0;ON;;;;;N;;;;; +1F4E9;ENVELOPE WITH DOWNWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F4EA;CLOSED MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; +1F4EB;CLOSED MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; +1F4EC;OPEN MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; +1F4ED;OPEN MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; +1F4EE;POSTBOX;So;0;ON;;;;;N;;;;; +1F4EF;POSTAL HORN;So;0;ON;;;;;N;;;;; +1F4F0;NEWSPAPER;So;0;ON;;;;;N;;;;; +1F4F1;MOBILE PHONE;So;0;ON;;;;;N;;;;; +1F4F2;MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT;So;0;ON;;;;;N;;;;; +1F4F3;VIBRATION MODE;So;0;ON;;;;;N;;;;; +1F4F4;MOBILE PHONE OFF;So;0;ON;;;;;N;;;;; +1F4F5;NO MOBILE PHONES;So;0;ON;;;;;N;;;;; +1F4F6;ANTENNA WITH BARS;So;0;ON;;;;;N;;;;; +1F4F7;CAMERA;So;0;ON;;;;;N;;;;; +1F4F8;CAMERA WITH FLASH;So;0;ON;;;;;N;;;;; +1F4F9;VIDEO CAMERA;So;0;ON;;;;;N;;;;; +1F4FA;TELEVISION;So;0;ON;;;;;N;;;;; +1F4FB;RADIO;So;0;ON;;;;;N;;;;; +1F4FC;VIDEOCASSETTE;So;0;ON;;;;;N;;;;; +1F4FD;FILM PROJECTOR;So;0;ON;;;;;N;;;;; +1F4FE;PORTABLE STEREO;So;0;ON;;;;;N;;;;; +1F4FF;PRAYER BEADS;So;0;ON;;;;;N;;;;; +1F500;TWISTED RIGHTWARDS ARROWS;So;0;ON;;;;;N;;;;; +1F501;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F502;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY;So;0;ON;;;;;N;;;;; +1F503;CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F504;ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F505;LOW BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; +1F506;HIGH BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; +1F507;SPEAKER WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; +1F508;SPEAKER;So;0;ON;;;;;N;;;;; +1F509;SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; +1F50A;SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; +1F50B;BATTERY;So;0;ON;;;;;N;;;;; +1F50C;ELECTRIC PLUG;So;0;ON;;;;;N;;;;; +1F50D;LEFT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; +1F50E;RIGHT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; +1F50F;LOCK WITH INK PEN;So;0;ON;;;;;N;;;;; +1F510;CLOSED LOCK WITH KEY;So;0;ON;;;;;N;;;;; +1F511;KEY;So;0;ON;;;;;N;;;;; +1F512;LOCK;So;0;ON;;;;;N;;;;; +1F513;OPEN LOCK;So;0;ON;;;;;N;;;;; +1F514;BELL;So;0;ON;;;;;N;;;;; +1F515;BELL WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; +1F516;BOOKMARK;So;0;ON;;;;;N;;;;; +1F517;LINK SYMBOL;So;0;ON;;;;;N;;;;; +1F518;RADIO BUTTON;So;0;ON;;;;;N;;;;; +1F519;BACK WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51A;END WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51B;ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51C;SOON WITH RIGHTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51D;TOP WITH UPWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51E;NO ONE UNDER EIGHTEEN SYMBOL;So;0;ON;;;;;N;;;;; +1F51F;KEYCAP TEN;So;0;ON;;;;;N;;;;; +1F520;INPUT SYMBOL FOR LATIN CAPITAL LETTERS;So;0;ON;;;;;N;;;;; +1F521;INPUT SYMBOL FOR LATIN SMALL LETTERS;So;0;ON;;;;;N;;;;; +1F522;INPUT SYMBOL FOR NUMBERS;So;0;ON;;;;;N;;;;; +1F523;INPUT SYMBOL FOR SYMBOLS;So;0;ON;;;;;N;;;;; +1F524;INPUT SYMBOL FOR LATIN LETTERS;So;0;ON;;;;;N;;;;; +1F525;FIRE;So;0;ON;;;;;N;;;;; +1F526;ELECTRIC TORCH;So;0;ON;;;;;N;;;;; +1F527;WRENCH;So;0;ON;;;;;N;;;;; +1F528;HAMMER;So;0;ON;;;;;N;;;;; +1F529;NUT AND BOLT;So;0;ON;;;;;N;;;;; +1F52A;HOCHO;So;0;ON;;;;;N;;;;; +1F52B;PISTOL;So;0;ON;;;;;N;;;;; +1F52C;MICROSCOPE;So;0;ON;;;;;N;;;;; +1F52D;TELESCOPE;So;0;ON;;;;;N;;;;; +1F52E;CRYSTAL BALL;So;0;ON;;;;;N;;;;; +1F52F;SIX POINTED STAR WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; +1F530;JAPANESE SYMBOL FOR BEGINNER;So;0;ON;;;;;N;;;;; +1F531;TRIDENT EMBLEM;So;0;ON;;;;;N;;;;; +1F532;BLACK SQUARE BUTTON;So;0;ON;;;;;N;;;;; +1F533;WHITE SQUARE BUTTON;So;0;ON;;;;;N;;;;; +1F534;LARGE RED CIRCLE;So;0;ON;;;;;N;;;;; +1F535;LARGE BLUE CIRCLE;So;0;ON;;;;;N;;;;; +1F536;LARGE ORANGE DIAMOND;So;0;ON;;;;;N;;;;; +1F537;LARGE BLUE DIAMOND;So;0;ON;;;;;N;;;;; +1F538;SMALL ORANGE DIAMOND;So;0;ON;;;;;N;;;;; +1F539;SMALL BLUE DIAMOND;So;0;ON;;;;;N;;;;; +1F53A;UP-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53B;DOWN-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53C;UP-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53D;DOWN-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53E;LOWER RIGHT SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F53F;UPPER RIGHT SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F540;CIRCLED CROSS POMMEE;So;0;ON;;;;;N;;;;; +1F541;CROSS POMMEE WITH HALF-CIRCLE BELOW;So;0;ON;;;;;N;;;;; +1F542;CROSS POMMEE;So;0;ON;;;;;N;;;;; +1F543;NOTCHED LEFT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F544;NOTCHED RIGHT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F545;SYMBOL FOR MARKS CHAPTER;So;0;ON;;;;;N;;;;; +1F546;WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; +1F547;HEAVY LATIN CROSS;So;0;ON;;;;;N;;;;; +1F548;CELTIC CROSS;So;0;ON;;;;;N;;;;; +1F549;OM SYMBOL;So;0;ON;;;;;N;;;;; +1F54A;DOVE OF PEACE;So;0;ON;;;;;N;;;;; +1F54B;KAABA;So;0;ON;;;;;N;;;;; +1F54C;MOSQUE;So;0;ON;;;;;N;;;;; +1F54D;SYNAGOGUE;So;0;ON;;;;;N;;;;; +1F54E;MENORAH WITH NINE BRANCHES;So;0;ON;;;;;N;;;;; +1F54F;BOWL OF HYGIEIA;So;0;ON;;;;;N;;;;; +1F550;CLOCK FACE ONE OCLOCK;So;0;ON;;;;;N;;;;; +1F551;CLOCK FACE TWO OCLOCK;So;0;ON;;;;;N;;;;; +1F552;CLOCK FACE THREE OCLOCK;So;0;ON;;;;;N;;;;; +1F553;CLOCK FACE FOUR OCLOCK;So;0;ON;;;;;N;;;;; +1F554;CLOCK FACE FIVE OCLOCK;So;0;ON;;;;;N;;;;; +1F555;CLOCK FACE SIX OCLOCK;So;0;ON;;;;;N;;;;; +1F556;CLOCK FACE SEVEN OCLOCK;So;0;ON;;;;;N;;;;; +1F557;CLOCK FACE EIGHT OCLOCK;So;0;ON;;;;;N;;;;; +1F558;CLOCK FACE NINE OCLOCK;So;0;ON;;;;;N;;;;; +1F559;CLOCK FACE TEN OCLOCK;So;0;ON;;;;;N;;;;; +1F55A;CLOCK FACE ELEVEN OCLOCK;So;0;ON;;;;;N;;;;; +1F55B;CLOCK FACE TWELVE OCLOCK;So;0;ON;;;;;N;;;;; +1F55C;CLOCK FACE ONE-THIRTY;So;0;ON;;;;;N;;;;; +1F55D;CLOCK FACE TWO-THIRTY;So;0;ON;;;;;N;;;;; +1F55E;CLOCK FACE THREE-THIRTY;So;0;ON;;;;;N;;;;; +1F55F;CLOCK FACE FOUR-THIRTY;So;0;ON;;;;;N;;;;; +1F560;CLOCK FACE FIVE-THIRTY;So;0;ON;;;;;N;;;;; +1F561;CLOCK FACE SIX-THIRTY;So;0;ON;;;;;N;;;;; +1F562;CLOCK FACE SEVEN-THIRTY;So;0;ON;;;;;N;;;;; +1F563;CLOCK FACE EIGHT-THIRTY;So;0;ON;;;;;N;;;;; +1F564;CLOCK FACE NINE-THIRTY;So;0;ON;;;;;N;;;;; +1F565;CLOCK FACE TEN-THIRTY;So;0;ON;;;;;N;;;;; +1F566;CLOCK FACE ELEVEN-THIRTY;So;0;ON;;;;;N;;;;; +1F567;CLOCK FACE TWELVE-THIRTY;So;0;ON;;;;;N;;;;; +1F568;RIGHT SPEAKER;So;0;ON;;;;;N;;;;; +1F569;RIGHT SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; +1F56A;RIGHT SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; +1F56B;BULLHORN;So;0;ON;;;;;N;;;;; +1F56C;BULLHORN WITH SOUND WAVES;So;0;ON;;;;;N;;;;; +1F56D;RINGING BELL;So;0;ON;;;;;N;;;;; +1F56E;BOOK;So;0;ON;;;;;N;;;;; +1F56F;CANDLE;So;0;ON;;;;;N;;;;; +1F570;MANTELPIECE CLOCK;So;0;ON;;;;;N;;;;; +1F571;BLACK SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; +1F572;NO PIRACY;So;0;ON;;;;;N;;;;; +1F573;HOLE;So;0;ON;;;;;N;;;;; +1F574;MAN IN BUSINESS SUIT LEVITATING;So;0;ON;;;;;N;;;;; +1F575;SLEUTH OR SPY;So;0;ON;;;;;N;;;;; +1F576;DARK SUNGLASSES;So;0;ON;;;;;N;;;;; +1F577;SPIDER;So;0;ON;;;;;N;;;;; +1F578;SPIDER WEB;So;0;ON;;;;;N;;;;; +1F579;JOYSTICK;So;0;ON;;;;;N;;;;; +1F57A;MAN DANCING;So;0;ON;;;;;N;;;;; +1F57B;LEFT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; +1F57C;TELEPHONE RECEIVER WITH PAGE;So;0;ON;;;;;N;;;;; +1F57D;RIGHT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; +1F57E;WHITE TOUCHTONE TELEPHONE;So;0;ON;;;;;N;;;;; +1F57F;BLACK TOUCHTONE TELEPHONE;So;0;ON;;;;;N;;;;; +1F580;TELEPHONE ON TOP OF MODEM;So;0;ON;;;;;N;;;;; +1F581;CLAMSHELL MOBILE PHONE;So;0;ON;;;;;N;;;;; +1F582;BACK OF ENVELOPE;So;0;ON;;;;;N;;;;; +1F583;STAMPED ENVELOPE;So;0;ON;;;;;N;;;;; +1F584;ENVELOPE WITH LIGHTNING;So;0;ON;;;;;N;;;;; +1F585;FLYING ENVELOPE;So;0;ON;;;;;N;;;;; +1F586;PEN OVER STAMPED ENVELOPE;So;0;ON;;;;;N;;;;; +1F587;LINKED PAPERCLIPS;So;0;ON;;;;;N;;;;; +1F588;BLACK PUSHPIN;So;0;ON;;;;;N;;;;; +1F589;LOWER LEFT PENCIL;So;0;ON;;;;;N;;;;; +1F58A;LOWER LEFT BALLPOINT PEN;So;0;ON;;;;;N;;;;; +1F58B;LOWER LEFT FOUNTAIN PEN;So;0;ON;;;;;N;;;;; +1F58C;LOWER LEFT PAINTBRUSH;So;0;ON;;;;;N;;;;; +1F58D;LOWER LEFT CRAYON;So;0;ON;;;;;N;;;;; +1F58E;LEFT WRITING HAND;So;0;ON;;;;;N;;;;; +1F58F;TURNED OK HAND SIGN;So;0;ON;;;;;N;;;;; +1F590;RAISED HAND WITH FINGERS SPLAYED;So;0;ON;;;;;N;;;;; +1F591;REVERSED RAISED HAND WITH FINGERS SPLAYED;So;0;ON;;;;;N;;;;; +1F592;REVERSED THUMBS UP SIGN;So;0;ON;;;;;N;;;;; +1F593;REVERSED THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; +1F594;REVERSED VICTORY HAND;So;0;ON;;;;;N;;;;; +1F595;REVERSED HAND WITH MIDDLE FINGER EXTENDED;So;0;ON;;;;;N;;;;; +1F596;RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS;So;0;ON;;;;;N;;;;; +1F597;WHITE DOWN POINTING LEFT HAND INDEX;So;0;ON;;;;;N;;;;; +1F598;SIDEWAYS WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; +1F599;SIDEWAYS WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +1F59A;SIDEWAYS BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; +1F59B;SIDEWAYS BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +1F59C;BLACK LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F59D;BLACK RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F59E;SIDEWAYS WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; +1F59F;SIDEWAYS WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; +1F5A0;SIDEWAYS BLACK UP POINTING INDEX;So;0;ON;;;;;N;;;;; +1F5A1;SIDEWAYS BLACK DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; +1F5A2;BLACK UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F5A3;BLACK DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F5A4;BLACK HEART;So;0;ON;;;;;N;;;;; +1F5A5;DESKTOP COMPUTER;So;0;ON;;;;;N;;;;; +1F5A6;KEYBOARD AND MOUSE;So;0;ON;;;;;N;;;;; +1F5A7;THREE NETWORKED COMPUTERS;So;0;ON;;;;;N;;;;; +1F5A8;PRINTER;So;0;ON;;;;;N;;;;; +1F5A9;POCKET CALCULATOR;So;0;ON;;;;;N;;;;; +1F5AA;BLACK HARD SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F5AB;WHITE HARD SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F5AC;SOFT SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F5AD;TAPE CARTRIDGE;So;0;ON;;;;;N;;;;; +1F5AE;WIRED KEYBOARD;So;0;ON;;;;;N;;;;; +1F5AF;ONE BUTTON MOUSE;So;0;ON;;;;;N;;;;; +1F5B0;TWO BUTTON MOUSE;So;0;ON;;;;;N;;;;; +1F5B1;THREE BUTTON MOUSE;So;0;ON;;;;;N;;;;; +1F5B2;TRACKBALL;So;0;ON;;;;;N;;;;; +1F5B3;OLD PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; +1F5B4;HARD DISK;So;0;ON;;;;;N;;;;; +1F5B5;SCREEN;So;0;ON;;;;;N;;;;; +1F5B6;PRINTER ICON;So;0;ON;;;;;N;;;;; +1F5B7;FAX ICON;So;0;ON;;;;;N;;;;; +1F5B8;OPTICAL DISC ICON;So;0;ON;;;;;N;;;;; +1F5B9;DOCUMENT WITH TEXT;So;0;ON;;;;;N;;;;; +1F5BA;DOCUMENT WITH TEXT AND PICTURE;So;0;ON;;;;;N;;;;; +1F5BB;DOCUMENT WITH PICTURE;So;0;ON;;;;;N;;;;; +1F5BC;FRAME WITH PICTURE;So;0;ON;;;;;N;;;;; +1F5BD;FRAME WITH TILES;So;0;ON;;;;;N;;;;; +1F5BE;FRAME WITH AN X;So;0;ON;;;;;N;;;;; +1F5BF;BLACK FOLDER;So;0;ON;;;;;N;;;;; +1F5C0;FOLDER;So;0;ON;;;;;N;;;;; +1F5C1;OPEN FOLDER;So;0;ON;;;;;N;;;;; +1F5C2;CARD INDEX DIVIDERS;So;0;ON;;;;;N;;;;; +1F5C3;CARD FILE BOX;So;0;ON;;;;;N;;;;; +1F5C4;FILE CABINET;So;0;ON;;;;;N;;;;; +1F5C5;EMPTY NOTE;So;0;ON;;;;;N;;;;; +1F5C6;EMPTY NOTE PAGE;So;0;ON;;;;;N;;;;; +1F5C7;EMPTY NOTE PAD;So;0;ON;;;;;N;;;;; +1F5C8;NOTE;So;0;ON;;;;;N;;;;; +1F5C9;NOTE PAGE;So;0;ON;;;;;N;;;;; +1F5CA;NOTE PAD;So;0;ON;;;;;N;;;;; +1F5CB;EMPTY DOCUMENT;So;0;ON;;;;;N;;;;; +1F5CC;EMPTY PAGE;So;0;ON;;;;;N;;;;; +1F5CD;EMPTY PAGES;So;0;ON;;;;;N;;;;; +1F5CE;DOCUMENT;So;0;ON;;;;;N;;;;; +1F5CF;PAGE;So;0;ON;;;;;N;;;;; +1F5D0;PAGES;So;0;ON;;;;;N;;;;; +1F5D1;WASTEBASKET;So;0;ON;;;;;N;;;;; +1F5D2;SPIRAL NOTE PAD;So;0;ON;;;;;N;;;;; +1F5D3;SPIRAL CALENDAR PAD;So;0;ON;;;;;N;;;;; +1F5D4;DESKTOP WINDOW;So;0;ON;;;;;N;;;;; +1F5D5;MINIMIZE;So;0;ON;;;;;N;;;;; +1F5D6;MAXIMIZE;So;0;ON;;;;;N;;;;; +1F5D7;OVERLAP;So;0;ON;;;;;N;;;;; +1F5D8;CLOCKWISE RIGHT AND LEFT SEMICIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F5D9;CANCELLATION X;So;0;ON;;;;;N;;;;; +1F5DA;INCREASE FONT SIZE SYMBOL;So;0;ON;;;;;N;;;;; +1F5DB;DECREASE FONT SIZE SYMBOL;So;0;ON;;;;;N;;;;; +1F5DC;COMPRESSION;So;0;ON;;;;;N;;;;; +1F5DD;OLD KEY;So;0;ON;;;;;N;;;;; +1F5DE;ROLLED-UP NEWSPAPER;So;0;ON;;;;;N;;;;; +1F5DF;PAGE WITH CIRCLED TEXT;So;0;ON;;;;;N;;;;; +1F5E0;STOCK CHART;So;0;ON;;;;;N;;;;; +1F5E1;DAGGER KNIFE;So;0;ON;;;;;N;;;;; +1F5E2;LIPS;So;0;ON;;;;;N;;;;; +1F5E3;SPEAKING HEAD IN SILHOUETTE;So;0;ON;;;;;N;;;;; +1F5E4;THREE RAYS ABOVE;So;0;ON;;;;;N;;;;; +1F5E5;THREE RAYS BELOW;So;0;ON;;;;;N;;;;; +1F5E6;THREE RAYS LEFT;So;0;ON;;;;;N;;;;; +1F5E7;THREE RAYS RIGHT;So;0;ON;;;;;N;;;;; +1F5E8;LEFT SPEECH BUBBLE;So;0;ON;;;;;N;;;;; +1F5E9;RIGHT SPEECH BUBBLE;So;0;ON;;;;;N;;;;; +1F5EA;TWO SPEECH BUBBLES;So;0;ON;;;;;N;;;;; +1F5EB;THREE SPEECH BUBBLES;So;0;ON;;;;;N;;;;; +1F5EC;LEFT THOUGHT BUBBLE;So;0;ON;;;;;N;;;;; +1F5ED;RIGHT THOUGHT BUBBLE;So;0;ON;;;;;N;;;;; +1F5EE;LEFT ANGER BUBBLE;So;0;ON;;;;;N;;;;; +1F5EF;RIGHT ANGER BUBBLE;So;0;ON;;;;;N;;;;; +1F5F0;MOOD BUBBLE;So;0;ON;;;;;N;;;;; +1F5F1;LIGHTNING MOOD BUBBLE;So;0;ON;;;;;N;;;;; +1F5F2;LIGHTNING MOOD;So;0;ON;;;;;N;;;;; +1F5F3;BALLOT BOX WITH BALLOT;So;0;ON;;;;;N;;;;; +1F5F4;BALLOT SCRIPT X;So;0;ON;;;;;N;;;;; +1F5F5;BALLOT BOX WITH SCRIPT X;So;0;ON;;;;;N;;;;; +1F5F6;BALLOT BOLD SCRIPT X;So;0;ON;;;;;N;;;;; +1F5F7;BALLOT BOX WITH BOLD SCRIPT X;So;0;ON;;;;;N;;;;; +1F5F8;LIGHT CHECK MARK;So;0;ON;;;;;N;;;;; +1F5F9;BALLOT BOX WITH BOLD CHECK;So;0;ON;;;;;N;;;;; +1F5FA;WORLD MAP;So;0;ON;;;;;N;;;;; +1F5FB;MOUNT FUJI;So;0;ON;;;;;N;;;;; +1F5FC;TOKYO TOWER;So;0;ON;;;;;N;;;;; +1F5FD;STATUE OF LIBERTY;So;0;ON;;;;;N;;;;; +1F5FE;SILHOUETTE OF JAPAN;So;0;ON;;;;;N;;;;; +1F5FF;MOYAI;So;0;ON;;;;;N;;;;; +1F600;GRINNING FACE;So;0;ON;;;;;N;;;;; +1F601;GRINNING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F602;FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; +1F603;SMILING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F604;SMILING FACE WITH OPEN MOUTH AND SMILING EYES;So;0;ON;;;;;N;;;;; +1F605;SMILING FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; +1F606;SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; +1F607;SMILING FACE WITH HALO;So;0;ON;;;;;N;;;;; +1F608;SMILING FACE WITH HORNS;So;0;ON;;;;;N;;;;; +1F609;WINKING FACE;So;0;ON;;;;;N;;;;; +1F60A;SMILING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F60B;FACE SAVOURING DELICIOUS FOOD;So;0;ON;;;;;N;;;;; +1F60C;RELIEVED FACE;So;0;ON;;;;;N;;;;; +1F60D;SMILING FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; +1F60E;SMILING FACE WITH SUNGLASSES;So;0;ON;;;;;N;;;;; +1F60F;SMIRKING FACE;So;0;ON;;;;;N;;;;; +1F610;NEUTRAL FACE;So;0;ON;;;;;N;;;;; +1F611;EXPRESSIONLESS FACE;So;0;ON;;;;;N;;;;; +1F612;UNAMUSED FACE;So;0;ON;;;;;N;;;;; +1F613;FACE WITH COLD SWEAT;So;0;ON;;;;;N;;;;; +1F614;PENSIVE FACE;So;0;ON;;;;;N;;;;; +1F615;CONFUSED FACE;So;0;ON;;;;;N;;;;; +1F616;CONFOUNDED FACE;So;0;ON;;;;;N;;;;; +1F617;KISSING FACE;So;0;ON;;;;;N;;;;; +1F618;FACE THROWING A KISS;So;0;ON;;;;;N;;;;; +1F619;KISSING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F61A;KISSING FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; +1F61B;FACE WITH STUCK-OUT TONGUE;So;0;ON;;;;;N;;;;; +1F61C;FACE WITH STUCK-OUT TONGUE AND WINKING EYE;So;0;ON;;;;;N;;;;; +1F61D;FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; +1F61E;DISAPPOINTED FACE;So;0;ON;;;;;N;;;;; +1F61F;WORRIED FACE;So;0;ON;;;;;N;;;;; +1F620;ANGRY FACE;So;0;ON;;;;;N;;;;; +1F621;POUTING FACE;So;0;ON;;;;;N;;;;; +1F622;CRYING FACE;So;0;ON;;;;;N;;;;; +1F623;PERSEVERING FACE;So;0;ON;;;;;N;;;;; +1F624;FACE WITH LOOK OF TRIUMPH;So;0;ON;;;;;N;;;;; +1F625;DISAPPOINTED BUT RELIEVED FACE;So;0;ON;;;;;N;;;;; +1F626;FROWNING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F627;ANGUISHED FACE;So;0;ON;;;;;N;;;;; +1F628;FEARFUL FACE;So;0;ON;;;;;N;;;;; +1F629;WEARY FACE;So;0;ON;;;;;N;;;;; +1F62A;SLEEPY FACE;So;0;ON;;;;;N;;;;; +1F62B;TIRED FACE;So;0;ON;;;;;N;;;;; +1F62C;GRIMACING FACE;So;0;ON;;;;;N;;;;; +1F62D;LOUDLY CRYING FACE;So;0;ON;;;;;N;;;;; +1F62E;FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F62F;HUSHED FACE;So;0;ON;;;;;N;;;;; +1F630;FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; +1F631;FACE SCREAMING IN FEAR;So;0;ON;;;;;N;;;;; +1F632;ASTONISHED FACE;So;0;ON;;;;;N;;;;; +1F633;FLUSHED FACE;So;0;ON;;;;;N;;;;; +1F634;SLEEPING FACE;So;0;ON;;;;;N;;;;; +1F635;DIZZY FACE;So;0;ON;;;;;N;;;;; +1F636;FACE WITHOUT MOUTH;So;0;ON;;;;;N;;;;; +1F637;FACE WITH MEDICAL MASK;So;0;ON;;;;;N;;;;; +1F638;GRINNING CAT FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F639;CAT FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; +1F63A;SMILING CAT FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; +1F63C;CAT FACE WITH WRY SMILE;So;0;ON;;;;;N;;;;; +1F63D;KISSING CAT FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; +1F63E;POUTING CAT FACE;So;0;ON;;;;;N;;;;; +1F63F;CRYING CAT FACE;So;0;ON;;;;;N;;;;; +1F640;WEARY CAT FACE;So;0;ON;;;;;N;;;;; +1F641;SLIGHTLY FROWNING FACE;So;0;ON;;;;;N;;;;; +1F642;SLIGHTLY SMILING FACE;So;0;ON;;;;;N;;;;; +1F643;UPSIDE-DOWN FACE;So;0;ON;;;;;N;;;;; +1F644;FACE WITH ROLLING EYES;So;0;ON;;;;;N;;;;; +1F645;FACE WITH NO GOOD GESTURE;So;0;ON;;;;;N;;;;; +1F646;FACE WITH OK GESTURE;So;0;ON;;;;;N;;;;; +1F647;PERSON BOWING DEEPLY;So;0;ON;;;;;N;;;;; +1F648;SEE-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F649;HEAR-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F64A;SPEAK-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F64B;HAPPY PERSON RAISING ONE HAND;So;0;ON;;;;;N;;;;; +1F64C;PERSON RAISING BOTH HANDS IN CELEBRATION;So;0;ON;;;;;N;;;;; +1F64D;PERSON FROWNING;So;0;ON;;;;;N;;;;; +1F64E;PERSON WITH POUTING FACE;So;0;ON;;;;;N;;;;; +1F64F;PERSON WITH FOLDED HANDS;So;0;ON;;;;;N;;;;; +1F650;NORTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F651;SOUTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F652;NORTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F653;SOUTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F654;TURNED NORTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F655;TURNED SOUTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F656;TURNED NORTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F657;TURNED SOUTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F658;NORTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F659;SOUTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65A;NORTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65B;SOUTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65C;HEAVY NORTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65D;HEAVY SOUTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65E;HEAVY NORTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65F;HEAVY SOUTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F660;NORTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; +1F661;SOUTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; +1F662;NORTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; +1F663;SOUTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; +1F664;HEAVY NORTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; +1F665;HEAVY SOUTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; +1F666;HEAVY NORTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; +1F667;HEAVY SOUTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; +1F668;HOLLOW QUILT SQUARE ORNAMENT;So;0;ON;;;;;N;;;;; +1F669;HOLLOW QUILT SQUARE ORNAMENT IN BLACK SQUARE;So;0;ON;;;;;N;;;;; +1F66A;SOLID QUILT SQUARE ORNAMENT;So;0;ON;;;;;N;;;;; +1F66B;SOLID QUILT SQUARE ORNAMENT IN BLACK SQUARE;So;0;ON;;;;;N;;;;; +1F66C;LEFTWARDS ROCKET;So;0;ON;;;;;N;;;;; +1F66D;UPWARDS ROCKET;So;0;ON;;;;;N;;;;; +1F66E;RIGHTWARDS ROCKET;So;0;ON;;;;;N;;;;; +1F66F;DOWNWARDS ROCKET;So;0;ON;;;;;N;;;;; +1F670;SCRIPT LIGATURE ET ORNAMENT;So;0;ON;;;;;N;;;;; +1F671;HEAVY SCRIPT LIGATURE ET ORNAMENT;So;0;ON;;;;;N;;;;; +1F672;LIGATURE OPEN ET ORNAMENT;So;0;ON;;;;;N;;;;; +1F673;HEAVY LIGATURE OPEN ET ORNAMENT;So;0;ON;;;;;N;;;;; +1F674;HEAVY AMPERSAND ORNAMENT;So;0;ON;;;;;N;;;;; +1F675;SWASH AMPERSAND ORNAMENT;So;0;ON;;;;;N;;;;; +1F676;SANS-SERIF HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +1F677;SANS-SERIF HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +1F678;SANS-SERIF HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +1F679;HEAVY INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; +1F67A;SANS-SERIF INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; +1F67B;HEAVY SANS-SERIF INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; +1F67C;VERY HEAVY SOLIDUS;So;0;ON;;;;;N;;;;; +1F67D;VERY HEAVY REVERSE SOLIDUS;So;0;ON;;;;;N;;;;; +1F67E;CHECKER BOARD;So;0;ON;;;;;N;;;;; +1F67F;REVERSE CHECKER BOARD;So;0;ON;;;;;N;;;;; +1F680;ROCKET;So;0;ON;;;;;N;;;;; +1F681;HELICOPTER;So;0;ON;;;;;N;;;;; +1F682;STEAM LOCOMOTIVE;So;0;ON;;;;;N;;;;; +1F683;RAILWAY CAR;So;0;ON;;;;;N;;;;; +1F684;HIGH-SPEED TRAIN;So;0;ON;;;;;N;;;;; +1F685;HIGH-SPEED TRAIN WITH BULLET NOSE;So;0;ON;;;;;N;;;;; +1F686;TRAIN;So;0;ON;;;;;N;;;;; +1F687;METRO;So;0;ON;;;;;N;;;;; +1F688;LIGHT RAIL;So;0;ON;;;;;N;;;;; +1F689;STATION;So;0;ON;;;;;N;;;;; +1F68A;TRAM;So;0;ON;;;;;N;;;;; +1F68B;TRAM CAR;So;0;ON;;;;;N;;;;; +1F68C;BUS;So;0;ON;;;;;N;;;;; +1F68D;ONCOMING BUS;So;0;ON;;;;;N;;;;; +1F68E;TROLLEYBUS;So;0;ON;;;;;N;;;;; +1F68F;BUS STOP;So;0;ON;;;;;N;;;;; +1F690;MINIBUS;So;0;ON;;;;;N;;;;; +1F691;AMBULANCE;So;0;ON;;;;;N;;;;; +1F692;FIRE ENGINE;So;0;ON;;;;;N;;;;; +1F693;POLICE CAR;So;0;ON;;;;;N;;;;; +1F694;ONCOMING POLICE CAR;So;0;ON;;;;;N;;;;; +1F695;TAXI;So;0;ON;;;;;N;;;;; +1F696;ONCOMING TAXI;So;0;ON;;;;;N;;;;; +1F697;AUTOMOBILE;So;0;ON;;;;;N;;;;; +1F698;ONCOMING AUTOMOBILE;So;0;ON;;;;;N;;;;; +1F699;RECREATIONAL VEHICLE;So;0;ON;;;;;N;;;;; +1F69A;DELIVERY TRUCK;So;0;ON;;;;;N;;;;; +1F69B;ARTICULATED LORRY;So;0;ON;;;;;N;;;;; +1F69C;TRACTOR;So;0;ON;;;;;N;;;;; +1F69D;MONORAIL;So;0;ON;;;;;N;;;;; +1F69E;MOUNTAIN RAILWAY;So;0;ON;;;;;N;;;;; +1F69F;SUSPENSION RAILWAY;So;0;ON;;;;;N;;;;; +1F6A0;MOUNTAIN CABLEWAY;So;0;ON;;;;;N;;;;; +1F6A1;AERIAL TRAMWAY;So;0;ON;;;;;N;;;;; +1F6A2;SHIP;So;0;ON;;;;;N;;;;; +1F6A3;ROWBOAT;So;0;ON;;;;;N;;;;; +1F6A4;SPEEDBOAT;So;0;ON;;;;;N;;;;; +1F6A5;HORIZONTAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; +1F6A6;VERTICAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; +1F6A7;CONSTRUCTION SIGN;So;0;ON;;;;;N;;;;; +1F6A8;POLICE CARS REVOLVING LIGHT;So;0;ON;;;;;N;;;;; +1F6A9;TRIANGULAR FLAG ON POST;So;0;ON;;;;;N;;;;; +1F6AA;DOOR;So;0;ON;;;;;N;;;;; +1F6AB;NO ENTRY SIGN;So;0;ON;;;;;N;;;;; +1F6AC;SMOKING SYMBOL;So;0;ON;;;;;N;;;;; +1F6AD;NO SMOKING SYMBOL;So;0;ON;;;;;N;;;;; +1F6AE;PUT LITTER IN ITS PLACE SYMBOL;So;0;ON;;;;;N;;;;; +1F6AF;DO NOT LITTER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B0;POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B1;NON-POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B2;BICYCLE;So;0;ON;;;;;N;;;;; +1F6B3;NO BICYCLES;So;0;ON;;;;;N;;;;; +1F6B4;BICYCLIST;So;0;ON;;;;;N;;;;; +1F6B5;MOUNTAIN BICYCLIST;So;0;ON;;;;;N;;;;; +1F6B6;PEDESTRIAN;So;0;ON;;;;;N;;;;; +1F6B7;NO PEDESTRIANS;So;0;ON;;;;;N;;;;; +1F6B8;CHILDREN CROSSING;So;0;ON;;;;;N;;;;; +1F6B9;MENS SYMBOL;So;0;ON;;;;;N;;;;; +1F6BA;WOMENS SYMBOL;So;0;ON;;;;;N;;;;; +1F6BB;RESTROOM;So;0;ON;;;;;N;;;;; +1F6BC;BABY SYMBOL;So;0;ON;;;;;N;;;;; +1F6BD;TOILET;So;0;ON;;;;;N;;;;; +1F6BE;WATER CLOSET;So;0;ON;;;;;N;;;;; +1F6BF;SHOWER;So;0;ON;;;;;N;;;;; +1F6C0;BATH;So;0;ON;;;;;N;;;;; +1F6C1;BATHTUB;So;0;ON;;;;;N;;;;; +1F6C2;PASSPORT CONTROL;So;0;ON;;;;;N;;;;; +1F6C3;CUSTOMS;So;0;ON;;;;;N;;;;; +1F6C4;BAGGAGE CLAIM;So;0;ON;;;;;N;;;;; +1F6C5;LEFT LUGGAGE;So;0;ON;;;;;N;;;;; +1F6C6;TRIANGLE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; +1F6C7;PROHIBITED SIGN;So;0;ON;;;;;N;;;;; +1F6C8;CIRCLED INFORMATION SOURCE;So;0;ON;;;;;N;;;;; +1F6C9;BOYS SYMBOL;So;0;ON;;;;;N;;;;; +1F6CA;GIRLS SYMBOL;So;0;ON;;;;;N;;;;; +1F6CB;COUCH AND LAMP;So;0;ON;;;;;N;;;;; +1F6CC;SLEEPING ACCOMMODATION;So;0;ON;;;;;N;;;;; +1F6CD;SHOPPING BAGS;So;0;ON;;;;;N;;;;; +1F6CE;BELLHOP BELL;So;0;ON;;;;;N;;;;; +1F6CF;BED;So;0;ON;;;;;N;;;;; +1F6D0;PLACE OF WORSHIP;So;0;ON;;;;;N;;;;; +1F6D1;OCTAGONAL SIGN;So;0;ON;;;;;N;;;;; +1F6D2;SHOPPING TROLLEY;So;0;ON;;;;;N;;;;; +1F6D3;STUPA;So;0;ON;;;;;N;;;;; +1F6D4;PAGODA;So;0;ON;;;;;N;;;;; +1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;; +1F6E1;SHIELD;So;0;ON;;;;;N;;;;; +1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;; +1F6E3;MOTORWAY;So;0;ON;;;;;N;;;;; +1F6E4;RAILWAY TRACK;So;0;ON;;;;;N;;;;; +1F6E5;MOTOR BOAT;So;0;ON;;;;;N;;;;; +1F6E6;UP-POINTING MILITARY AIRPLANE;So;0;ON;;;;;N;;;;; +1F6E7;UP-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; +1F6E8;UP-POINTING SMALL AIRPLANE;So;0;ON;;;;;N;;;;; +1F6E9;SMALL AIRPLANE;So;0;ON;;;;;N;;;;; +1F6EA;NORTHEAST-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; +1F6EB;AIRPLANE DEPARTURE;So;0;ON;;;;;N;;;;; +1F6EC;AIRPLANE ARRIVING;So;0;ON;;;;;N;;;;; +1F6F0;SATELLITE;So;0;ON;;;;;N;;;;; +1F6F1;ONCOMING FIRE ENGINE;So;0;ON;;;;;N;;;;; +1F6F2;DIESEL LOCOMOTIVE;So;0;ON;;;;;N;;;;; +1F6F3;PASSENGER SHIP;So;0;ON;;;;;N;;;;; +1F6F4;SCOOTER;So;0;ON;;;;;N;;;;; +1F6F5;MOTOR SCOOTER;So;0;ON;;;;;N;;;;; +1F6F6;CANOE;So;0;ON;;;;;N;;;;; +1F6F7;SLED;So;0;ON;;;;;N;;;;; +1F6F8;FLYING SAUCER;So;0;ON;;;;;N;;;;; +1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;; +1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;; +1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;; +1F703;ALCHEMICAL SYMBOL FOR EARTH;So;0;ON;;;;;N;;;;; +1F704;ALCHEMICAL SYMBOL FOR WATER;So;0;ON;;;;;N;;;;; +1F705;ALCHEMICAL SYMBOL FOR AQUAFORTIS;So;0;ON;;;;;N;;;;; +1F706;ALCHEMICAL SYMBOL FOR AQUA REGIA;So;0;ON;;;;;N;;;;; +1F707;ALCHEMICAL SYMBOL FOR AQUA REGIA-2;So;0;ON;;;;;N;;;;; +1F708;ALCHEMICAL SYMBOL FOR AQUA VITAE;So;0;ON;;;;;N;;;;; +1F709;ALCHEMICAL SYMBOL FOR AQUA VITAE-2;So;0;ON;;;;;N;;;;; +1F70A;ALCHEMICAL SYMBOL FOR VINEGAR;So;0;ON;;;;;N;;;;; +1F70B;ALCHEMICAL SYMBOL FOR VINEGAR-2;So;0;ON;;;;;N;;;;; +1F70C;ALCHEMICAL SYMBOL FOR VINEGAR-3;So;0;ON;;;;;N;;;;; +1F70D;ALCHEMICAL SYMBOL FOR SULFUR;So;0;ON;;;;;N;;;;; +1F70E;ALCHEMICAL SYMBOL FOR PHILOSOPHERS SULFUR;So;0;ON;;;;;N;;;;; +1F70F;ALCHEMICAL SYMBOL FOR BLACK SULFUR;So;0;ON;;;;;N;;;;; +1F710;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE;So;0;ON;;;;;N;;;;; +1F711;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-2;So;0;ON;;;;;N;;;;; +1F712;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-3;So;0;ON;;;;;N;;;;; +1F713;ALCHEMICAL SYMBOL FOR CINNABAR;So;0;ON;;;;;N;;;;; +1F714;ALCHEMICAL SYMBOL FOR SALT;So;0;ON;;;;;N;;;;; +1F715;ALCHEMICAL SYMBOL FOR NITRE;So;0;ON;;;;;N;;;;; +1F716;ALCHEMICAL SYMBOL FOR VITRIOL;So;0;ON;;;;;N;;;;; +1F717;ALCHEMICAL SYMBOL FOR VITRIOL-2;So;0;ON;;;;;N;;;;; +1F718;ALCHEMICAL SYMBOL FOR ROCK SALT;So;0;ON;;;;;N;;;;; +1F719;ALCHEMICAL SYMBOL FOR ROCK SALT-2;So;0;ON;;;;;N;;;;; +1F71A;ALCHEMICAL SYMBOL FOR GOLD;So;0;ON;;;;;N;;;;; +1F71B;ALCHEMICAL SYMBOL FOR SILVER;So;0;ON;;;;;N;;;;; +1F71C;ALCHEMICAL SYMBOL FOR IRON ORE;So;0;ON;;;;;N;;;;; +1F71D;ALCHEMICAL SYMBOL FOR IRON ORE-2;So;0;ON;;;;;N;;;;; +1F71E;ALCHEMICAL SYMBOL FOR CROCUS OF IRON;So;0;ON;;;;;N;;;;; +1F71F;ALCHEMICAL SYMBOL FOR REGULUS OF IRON;So;0;ON;;;;;N;;;;; +1F720;ALCHEMICAL SYMBOL FOR COPPER ORE;So;0;ON;;;;;N;;;;; +1F721;ALCHEMICAL SYMBOL FOR IRON-COPPER ORE;So;0;ON;;;;;N;;;;; +1F722;ALCHEMICAL SYMBOL FOR SUBLIMATE OF COPPER;So;0;ON;;;;;N;;;;; +1F723;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER;So;0;ON;;;;;N;;;;; +1F724;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER-2;So;0;ON;;;;;N;;;;; +1F725;ALCHEMICAL SYMBOL FOR COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; +1F726;ALCHEMICAL SYMBOL FOR SALT OF COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; +1F727;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF COPPER;So;0;ON;;;;;N;;;;; +1F728;ALCHEMICAL SYMBOL FOR VERDIGRIS;So;0;ON;;;;;N;;;;; +1F729;ALCHEMICAL SYMBOL FOR TIN ORE;So;0;ON;;;;;N;;;;; +1F72A;ALCHEMICAL SYMBOL FOR LEAD ORE;So;0;ON;;;;;N;;;;; +1F72B;ALCHEMICAL SYMBOL FOR ANTIMONY ORE;So;0;ON;;;;;N;;;;; +1F72C;ALCHEMICAL SYMBOL FOR SUBLIMATE OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72D;ALCHEMICAL SYMBOL FOR SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72E;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72F;ALCHEMICAL SYMBOL FOR VINEGAR OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F730;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F731;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY-2;So;0;ON;;;;;N;;;;; +1F732;ALCHEMICAL SYMBOL FOR REGULUS;So;0;ON;;;;;N;;;;; +1F733;ALCHEMICAL SYMBOL FOR REGULUS-2;So;0;ON;;;;;N;;;;; +1F734;ALCHEMICAL SYMBOL FOR REGULUS-3;So;0;ON;;;;;N;;;;; +1F735;ALCHEMICAL SYMBOL FOR REGULUS-4;So;0;ON;;;;;N;;;;; +1F736;ALCHEMICAL SYMBOL FOR ALKALI;So;0;ON;;;;;N;;;;; +1F737;ALCHEMICAL SYMBOL FOR ALKALI-2;So;0;ON;;;;;N;;;;; +1F738;ALCHEMICAL SYMBOL FOR MARCASITE;So;0;ON;;;;;N;;;;; +1F739;ALCHEMICAL SYMBOL FOR SAL-AMMONIAC;So;0;ON;;;;;N;;;;; +1F73A;ALCHEMICAL SYMBOL FOR ARSENIC;So;0;ON;;;;;N;;;;; +1F73B;ALCHEMICAL SYMBOL FOR REALGAR;So;0;ON;;;;;N;;;;; +1F73C;ALCHEMICAL SYMBOL FOR REALGAR-2;So;0;ON;;;;;N;;;;; +1F73D;ALCHEMICAL SYMBOL FOR AURIPIGMENT;So;0;ON;;;;;N;;;;; +1F73E;ALCHEMICAL SYMBOL FOR BISMUTH ORE;So;0;ON;;;;;N;;;;; +1F73F;ALCHEMICAL SYMBOL FOR TARTAR;So;0;ON;;;;;N;;;;; +1F740;ALCHEMICAL SYMBOL FOR TARTAR-2;So;0;ON;;;;;N;;;;; +1F741;ALCHEMICAL SYMBOL FOR QUICK LIME;So;0;ON;;;;;N;;;;; +1F742;ALCHEMICAL SYMBOL FOR BORAX;So;0;ON;;;;;N;;;;; +1F743;ALCHEMICAL SYMBOL FOR BORAX-2;So;0;ON;;;;;N;;;;; +1F744;ALCHEMICAL SYMBOL FOR BORAX-3;So;0;ON;;;;;N;;;;; +1F745;ALCHEMICAL SYMBOL FOR ALUM;So;0;ON;;;;;N;;;;; +1F746;ALCHEMICAL SYMBOL FOR OIL;So;0;ON;;;;;N;;;;; +1F747;ALCHEMICAL SYMBOL FOR SPIRIT;So;0;ON;;;;;N;;;;; +1F748;ALCHEMICAL SYMBOL FOR TINCTURE;So;0;ON;;;;;N;;;;; +1F749;ALCHEMICAL SYMBOL FOR GUM;So;0;ON;;;;;N;;;;; +1F74A;ALCHEMICAL SYMBOL FOR WAX;So;0;ON;;;;;N;;;;; +1F74B;ALCHEMICAL SYMBOL FOR POWDER;So;0;ON;;;;;N;;;;; +1F74C;ALCHEMICAL SYMBOL FOR CALX;So;0;ON;;;;;N;;;;; +1F74D;ALCHEMICAL SYMBOL FOR TUTTY;So;0;ON;;;;;N;;;;; +1F74E;ALCHEMICAL SYMBOL FOR CAPUT MORTUUM;So;0;ON;;;;;N;;;;; +1F74F;ALCHEMICAL SYMBOL FOR SCEPTER OF JOVE;So;0;ON;;;;;N;;;;; +1F750;ALCHEMICAL SYMBOL FOR CADUCEUS;So;0;ON;;;;;N;;;;; +1F751;ALCHEMICAL SYMBOL FOR TRIDENT;So;0;ON;;;;;N;;;;; +1F752;ALCHEMICAL SYMBOL FOR STARRED TRIDENT;So;0;ON;;;;;N;;;;; +1F753;ALCHEMICAL SYMBOL FOR LODESTONE;So;0;ON;;;;;N;;;;; +1F754;ALCHEMICAL SYMBOL FOR SOAP;So;0;ON;;;;;N;;;;; +1F755;ALCHEMICAL SYMBOL FOR URINE;So;0;ON;;;;;N;;;;; +1F756;ALCHEMICAL SYMBOL FOR HORSE DUNG;So;0;ON;;;;;N;;;;; +1F757;ALCHEMICAL SYMBOL FOR ASHES;So;0;ON;;;;;N;;;;; +1F758;ALCHEMICAL SYMBOL FOR POT ASHES;So;0;ON;;;;;N;;;;; +1F759;ALCHEMICAL SYMBOL FOR BRICK;So;0;ON;;;;;N;;;;; +1F75A;ALCHEMICAL SYMBOL FOR POWDERED BRICK;So;0;ON;;;;;N;;;;; +1F75B;ALCHEMICAL SYMBOL FOR AMALGAM;So;0;ON;;;;;N;;;;; +1F75C;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM;So;0;ON;;;;;N;;;;; +1F75D;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM-2;So;0;ON;;;;;N;;;;; +1F75E;ALCHEMICAL SYMBOL FOR SUBLIMATION;So;0;ON;;;;;N;;;;; +1F75F;ALCHEMICAL SYMBOL FOR PRECIPITATE;So;0;ON;;;;;N;;;;; +1F760;ALCHEMICAL SYMBOL FOR DISTILL;So;0;ON;;;;;N;;;;; +1F761;ALCHEMICAL SYMBOL FOR DISSOLVE;So;0;ON;;;;;N;;;;; +1F762;ALCHEMICAL SYMBOL FOR DISSOLVE-2;So;0;ON;;;;;N;;;;; +1F763;ALCHEMICAL SYMBOL FOR PURIFY;So;0;ON;;;;;N;;;;; +1F764;ALCHEMICAL SYMBOL FOR PUTREFACTION;So;0;ON;;;;;N;;;;; +1F765;ALCHEMICAL SYMBOL FOR CRUCIBLE;So;0;ON;;;;;N;;;;; +1F766;ALCHEMICAL SYMBOL FOR CRUCIBLE-2;So;0;ON;;;;;N;;;;; +1F767;ALCHEMICAL SYMBOL FOR CRUCIBLE-3;So;0;ON;;;;;N;;;;; +1F768;ALCHEMICAL SYMBOL FOR CRUCIBLE-4;So;0;ON;;;;;N;;;;; +1F769;ALCHEMICAL SYMBOL FOR CRUCIBLE-5;So;0;ON;;;;;N;;;;; +1F76A;ALCHEMICAL SYMBOL FOR ALEMBIC;So;0;ON;;;;;N;;;;; +1F76B;ALCHEMICAL SYMBOL FOR BATH OF MARY;So;0;ON;;;;;N;;;;; +1F76C;ALCHEMICAL SYMBOL FOR BATH OF VAPOURS;So;0;ON;;;;;N;;;;; +1F76D;ALCHEMICAL SYMBOL FOR RETORT;So;0;ON;;;;;N;;;;; +1F76E;ALCHEMICAL SYMBOL FOR HOUR;So;0;ON;;;;;N;;;;; +1F76F;ALCHEMICAL SYMBOL FOR NIGHT;So;0;ON;;;;;N;;;;; +1F770;ALCHEMICAL SYMBOL FOR DAY-NIGHT;So;0;ON;;;;;N;;;;; +1F771;ALCHEMICAL SYMBOL FOR MONTH;So;0;ON;;;;;N;;;;; +1F772;ALCHEMICAL SYMBOL FOR HALF DRAM;So;0;ON;;;;;N;;;;; +1F773;ALCHEMICAL SYMBOL FOR HALF OUNCE;So;0;ON;;;;;N;;;;; +1F780;BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +1F781;BLACK UP-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +1F782;BLACK RIGHT-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +1F783;BLACK DOWN-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +1F784;BLACK SLIGHTLY SMALL CIRCLE;So;0;ON;;;;;N;;;;; +1F785;MEDIUM BOLD WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F786;BOLD WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F787;HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F788;VERY HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F789;EXTREMELY HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F78A;WHITE CIRCLE CONTAINING BLACK SMALL CIRCLE;So;0;ON;;;;;N;;;;; +1F78B;ROUND TARGET;So;0;ON;;;;;N;;;;; +1F78C;BLACK TINY SQUARE;So;0;ON;;;;;N;;;;; +1F78D;BLACK SLIGHTLY SMALL SQUARE;So;0;ON;;;;;N;;;;; +1F78E;LIGHT WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F78F;MEDIUM WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F790;BOLD WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F791;HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F792;VERY HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F793;EXTREMELY HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F794;WHITE SQUARE CONTAINING BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; +1F795;WHITE SQUARE CONTAINING BLACK MEDIUM SQUARE;So;0;ON;;;;;N;;;;; +1F796;SQUARE TARGET;So;0;ON;;;;;N;;;;; +1F797;BLACK TINY DIAMOND;So;0;ON;;;;;N;;;;; +1F798;BLACK VERY SMALL DIAMOND;So;0;ON;;;;;N;;;;; +1F799;BLACK MEDIUM SMALL DIAMOND;So;0;ON;;;;;N;;;;; +1F79A;WHITE DIAMOND CONTAINING BLACK VERY SMALL DIAMOND;So;0;ON;;;;;N;;;;; +1F79B;WHITE DIAMOND CONTAINING BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; +1F79C;DIAMOND TARGET;So;0;ON;;;;;N;;;;; +1F79D;BLACK TINY LOZENGE;So;0;ON;;;;;N;;;;; +1F79E;BLACK VERY SMALL LOZENGE;So;0;ON;;;;;N;;;;; +1F79F;BLACK MEDIUM SMALL LOZENGE;So;0;ON;;;;;N;;;;; +1F7A0;WHITE LOZENGE CONTAINING BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; +1F7A1;THIN GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A2;LIGHT GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A3;MEDIUM GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A4;BOLD GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A5;VERY BOLD GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A6;VERY HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A7;EXTREMELY HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A8;THIN SALTIRE;So;0;ON;;;;;N;;;;; +1F7A9;LIGHT SALTIRE;So;0;ON;;;;;N;;;;; +1F7AA;MEDIUM SALTIRE;So;0;ON;;;;;N;;;;; +1F7AB;BOLD SALTIRE;So;0;ON;;;;;N;;;;; +1F7AC;HEAVY SALTIRE;So;0;ON;;;;;N;;;;; +1F7AD;VERY HEAVY SALTIRE;So;0;ON;;;;;N;;;;; +1F7AE;EXTREMELY HEAVY SALTIRE;So;0;ON;;;;;N;;;;; +1F7AF;LIGHT FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B0;MEDIUM FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B1;BOLD FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B2;HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B3;VERY HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B4;EXTREMELY HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B5;LIGHT SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B6;MEDIUM SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B7;BOLD SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B8;HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B9;VERY HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BA;EXTREMELY HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BB;LIGHT EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BC;MEDIUM EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BD;BOLD EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BE;HEAVY EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BF;VERY HEAVY EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7C0;LIGHT THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C1;MEDIUM THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C2;THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C3;MEDIUM THREE POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7C4;LIGHT FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C5;MEDIUM FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C6;FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C7;MEDIUM FOUR POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7C8;REVERSE LIGHT FOUR POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7C9;LIGHT FIVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CA;HEAVY FIVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CB;MEDIUM SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CC;HEAVY SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CD;SIX POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7CE;MEDIUM EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CF;HEAVY EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7D0;VERY HEAVY EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7D1;HEAVY EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7D2;LIGHT TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7D3;HEAVY TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7D4;HEAVY TWELVE POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F800;LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F801;UPWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F802;RIGHTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F803;DOWNWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F804;LEFTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F805;UPWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F806;RIGHTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F807;DOWNWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F808;LEFTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F809;UPWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F80A;RIGHTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F80B;DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F810;LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F811;UPWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F812;RIGHTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F813;DOWNWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F814;LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F815;UPWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F816;RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F817;DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F818;HEAVY LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F819;HEAVY UPWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81A;HEAVY RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81B;HEAVY DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81C;HEAVY LEFTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81D;HEAVY UPWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81E;HEAVY RIGHTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81F;HEAVY DOWNWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F820;LEFTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; +1F821;UPWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; +1F822;RIGHTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; +1F823;DOWNWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; +1F824;LEFTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; +1F825;UPWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; +1F826;RIGHTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; +1F827;DOWNWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; +1F828;LEFTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; +1F829;UPWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; +1F82A;RIGHTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; +1F82B;DOWNWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; +1F82C;LEFTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F82D;UPWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F82E;RIGHTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F82F;DOWNWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F830;LEFTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F831;UPWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F832;RIGHTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F833;DOWNWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F834;LEFTWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; +1F835;UPWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; +1F836;RIGHTWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; +1F837;DOWNWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; +1F838;LEFTWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; +1F839;UPWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; +1F83A;RIGHTWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; +1F83B;DOWNWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; +1F83C;LEFTWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F83D;UPWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F83E;RIGHTWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F83F;DOWNWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F840;LEFTWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F841;UPWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F842;RIGHTWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F843;DOWNWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F844;LEFTWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; +1F845;UPWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; +1F846;RIGHTWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; +1F847;DOWNWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; +1F850;LEFTWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F851;UPWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F852;RIGHTWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F853;DOWNWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F854;NORTH WEST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F855;NORTH EAST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F856;SOUTH EAST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F857;SOUTH WEST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F858;LEFT RIGHT SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F859;UP DOWN SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F860;WIDE-HEADED LEFTWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F861;WIDE-HEADED UPWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F862;WIDE-HEADED RIGHTWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F863;WIDE-HEADED DOWNWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F864;WIDE-HEADED NORTH WEST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F865;WIDE-HEADED NORTH EAST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F866;WIDE-HEADED SOUTH EAST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F867;WIDE-HEADED SOUTH WEST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F868;WIDE-HEADED LEFTWARDS BARB ARROW;So;0;ON;;;;;N;;;;; +1F869;WIDE-HEADED UPWARDS BARB ARROW;So;0;ON;;;;;N;;;;; +1F86A;WIDE-HEADED RIGHTWARDS BARB ARROW;So;0;ON;;;;;N;;;;; +1F86B;WIDE-HEADED DOWNWARDS BARB ARROW;So;0;ON;;;;;N;;;;; +1F86C;WIDE-HEADED NORTH WEST BARB ARROW;So;0;ON;;;;;N;;;;; +1F86D;WIDE-HEADED NORTH EAST BARB ARROW;So;0;ON;;;;;N;;;;; +1F86E;WIDE-HEADED SOUTH EAST BARB ARROW;So;0;ON;;;;;N;;;;; +1F86F;WIDE-HEADED SOUTH WEST BARB ARROW;So;0;ON;;;;;N;;;;; +1F870;WIDE-HEADED LEFTWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F871;WIDE-HEADED UPWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F872;WIDE-HEADED RIGHTWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F873;WIDE-HEADED DOWNWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F874;WIDE-HEADED NORTH WEST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F875;WIDE-HEADED NORTH EAST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F876;WIDE-HEADED SOUTH EAST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F877;WIDE-HEADED SOUTH WEST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F878;WIDE-HEADED LEFTWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F879;WIDE-HEADED UPWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87A;WIDE-HEADED RIGHTWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87B;WIDE-HEADED DOWNWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87C;WIDE-HEADED NORTH WEST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87D;WIDE-HEADED NORTH EAST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87E;WIDE-HEADED SOUTH EAST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87F;WIDE-HEADED SOUTH WEST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F880;WIDE-HEADED LEFTWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F881;WIDE-HEADED UPWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F882;WIDE-HEADED RIGHTWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F883;WIDE-HEADED DOWNWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F884;WIDE-HEADED NORTH WEST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F885;WIDE-HEADED NORTH EAST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F886;WIDE-HEADED SOUTH EAST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F887;WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F890;LEFTWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F891;UPWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F892;RIGHTWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F893;DOWNWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F894;LEFTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F895;UPWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F896;RIGHTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F897;DOWNWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F898;LEFTWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; +1F899;UPWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; +1F89A;RIGHTWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; +1F89B;DOWNWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; +1F89C;HEAVY ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; +1F89D;HEAVY ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; +1F89E;HEAVY ARROW SHAFT WIDTH ONE HALF;So;0;ON;;;;;N;;;;; +1F89F;HEAVY ARROW SHAFT WIDTH ONE THIRD;So;0;ON;;;;;N;;;;; +1F8A0;LEFTWARDS BOTTOM-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A1;RIGHTWARDS BOTTOM SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A2;LEFTWARDS TOP SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A3;RIGHTWARDS TOP SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A4;LEFTWARDS LEFT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A5;RIGHTWARDS RIGHT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A6;LEFTWARDS RIGHT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A7;RIGHTWARDS LEFT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A8;LEFTWARDS BACK-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A9;RIGHTWARDS BACK-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8AA;LEFTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; +1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; +1F900;CIRCLED CROSS FORMEE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F901;CIRCLED CROSS FORMEE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F902;CIRCLED CROSS FORMEE;So;0;ON;;;;;N;;;;; +1F903;LEFT HALF CIRCLE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F904;LEFT HALF CIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F905;LEFT HALF CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F906;LEFT HALF CIRCLE WITH DOT;So;0;ON;;;;;N;;;;; +1F907;LEFT HALF CIRCLE;So;0;ON;;;;;N;;;;; +1F908;DOWNWARD FACING HOOK;So;0;ON;;;;;N;;;;; +1F909;DOWNWARD FACING NOTCHED HOOK;So;0;ON;;;;;N;;;;; +1F90A;DOWNWARD FACING HOOK WITH DOT;So;0;ON;;;;;N;;;;; +1F90B;DOWNWARD FACING NOTCHED HOOK WITH DOT;So;0;ON;;;;;N;;;;; +1F910;ZIPPER-MOUTH FACE;So;0;ON;;;;;N;;;;; +1F911;MONEY-MOUTH FACE;So;0;ON;;;;;N;;;;; +1F912;FACE WITH THERMOMETER;So;0;ON;;;;;N;;;;; +1F913;NERD FACE;So;0;ON;;;;;N;;;;; +1F914;THINKING FACE;So;0;ON;;;;;N;;;;; +1F915;FACE WITH HEAD-BANDAGE;So;0;ON;;;;;N;;;;; +1F916;ROBOT FACE;So;0;ON;;;;;N;;;;; +1F917;HUGGING FACE;So;0;ON;;;;;N;;;;; +1F918;SIGN OF THE HORNS;So;0;ON;;;;;N;;;;; +1F919;CALL ME HAND;So;0;ON;;;;;N;;;;; +1F91A;RAISED BACK OF HAND;So;0;ON;;;;;N;;;;; +1F91B;LEFT-FACING FIST;So;0;ON;;;;;N;;;;; +1F91C;RIGHT-FACING FIST;So;0;ON;;;;;N;;;;; +1F91D;HANDSHAKE;So;0;ON;;;;;N;;;;; +1F91E;HAND WITH INDEX AND MIDDLE FINGERS CROSSED;So;0;ON;;;;;N;;;;; +1F91F;I LOVE YOU HAND SIGN;So;0;ON;;;;;N;;;;; +1F920;FACE WITH COWBOY HAT;So;0;ON;;;;;N;;;;; +1F921;CLOWN FACE;So;0;ON;;;;;N;;;;; +1F922;NAUSEATED FACE;So;0;ON;;;;;N;;;;; +1F923;ROLLING ON THE FLOOR LAUGHING;So;0;ON;;;;;N;;;;; +1F924;DROOLING FACE;So;0;ON;;;;;N;;;;; +1F925;LYING FACE;So;0;ON;;;;;N;;;;; +1F926;FACE PALM;So;0;ON;;;;;N;;;;; +1F927;SNEEZING FACE;So;0;ON;;;;;N;;;;; +1F928;FACE WITH ONE EYEBROW RAISED;So;0;ON;;;;;N;;;;; +1F929;GRINNING FACE WITH STAR EYES;So;0;ON;;;;;N;;;;; +1F92A;GRINNING FACE WITH ONE LARGE AND ONE SMALL EYE;So;0;ON;;;;;N;;;;; +1F92B;FACE WITH FINGER COVERING CLOSED LIPS;So;0;ON;;;;;N;;;;; +1F92C;SERIOUS FACE WITH SYMBOLS COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92D;SMILING FACE WITH SMILING EYES AND HAND COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92E;FACE WITH OPEN MOUTH VOMITING;So;0;ON;;;;;N;;;;; +1F92F;SHOCKED FACE WITH EXPLODING HEAD;So;0;ON;;;;;N;;;;; +1F930;PREGNANT WOMAN;So;0;ON;;;;;N;;;;; +1F931;BREAST-FEEDING;So;0;ON;;;;;N;;;;; +1F932;PALMS UP TOGETHER;So;0;ON;;;;;N;;;;; +1F933;SELFIE;So;0;ON;;;;;N;;;;; +1F934;PRINCE;So;0;ON;;;;;N;;;;; +1F935;MAN IN TUXEDO;So;0;ON;;;;;N;;;;; +1F936;MOTHER CHRISTMAS;So;0;ON;;;;;N;;;;; +1F937;SHRUG;So;0;ON;;;;;N;;;;; +1F938;PERSON DOING CARTWHEEL;So;0;ON;;;;;N;;;;; +1F939;JUGGLING;So;0;ON;;;;;N;;;;; +1F93A;FENCER;So;0;ON;;;;;N;;;;; +1F93B;MODERN PENTATHLON;So;0;ON;;;;;N;;;;; +1F93C;WRESTLERS;So;0;ON;;;;;N;;;;; +1F93D;WATER POLO;So;0;ON;;;;;N;;;;; +1F93E;HANDBALL;So;0;ON;;;;;N;;;;; +1F940;WILTED FLOWER;So;0;ON;;;;;N;;;;; +1F941;DRUM WITH DRUMSTICKS;So;0;ON;;;;;N;;;;; +1F942;CLINKING GLASSES;So;0;ON;;;;;N;;;;; +1F943;TUMBLER GLASS;So;0;ON;;;;;N;;;;; +1F944;SPOON;So;0;ON;;;;;N;;;;; +1F945;GOAL NET;So;0;ON;;;;;N;;;;; +1F946;RIFLE;So;0;ON;;;;;N;;;;; +1F947;FIRST PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F948;SECOND PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F949;THIRD PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F94A;BOXING GLOVE;So;0;ON;;;;;N;;;;; +1F94B;MARTIAL ARTS UNIFORM;So;0;ON;;;;;N;;;;; +1F94C;CURLING STONE;So;0;ON;;;;;N;;;;; +1F950;CROISSANT;So;0;ON;;;;;N;;;;; +1F951;AVOCADO;So;0;ON;;;;;N;;;;; +1F952;CUCUMBER;So;0;ON;;;;;N;;;;; +1F953;BACON;So;0;ON;;;;;N;;;;; +1F954;POTATO;So;0;ON;;;;;N;;;;; +1F955;CARROT;So;0;ON;;;;;N;;;;; +1F956;BAGUETTE BREAD;So;0;ON;;;;;N;;;;; +1F957;GREEN SALAD;So;0;ON;;;;;N;;;;; +1F958;SHALLOW PAN OF FOOD;So;0;ON;;;;;N;;;;; +1F959;STUFFED FLATBREAD;So;0;ON;;;;;N;;;;; +1F95A;EGG;So;0;ON;;;;;N;;;;; +1F95B;GLASS OF MILK;So;0;ON;;;;;N;;;;; +1F95C;PEANUTS;So;0;ON;;;;;N;;;;; +1F95D;KIWIFRUIT;So;0;ON;;;;;N;;;;; +1F95E;PANCAKES;So;0;ON;;;;;N;;;;; +1F95F;DUMPLING;So;0;ON;;;;;N;;;;; +1F960;FORTUNE COOKIE;So;0;ON;;;;;N;;;;; +1F961;TAKEOUT BOX;So;0;ON;;;;;N;;;;; +1F962;CHOPSTICKS;So;0;ON;;;;;N;;;;; +1F963;BOWL WITH SPOON;So;0;ON;;;;;N;;;;; +1F964;CUP WITH STRAW;So;0;ON;;;;;N;;;;; +1F965;COCONUT;So;0;ON;;;;;N;;;;; +1F966;BROCCOLI;So;0;ON;;;;;N;;;;; +1F967;PIE;So;0;ON;;;;;N;;;;; +1F968;PRETZEL;So;0;ON;;;;;N;;;;; +1F969;CUT OF MEAT;So;0;ON;;;;;N;;;;; +1F96A;SANDWICH;So;0;ON;;;;;N;;;;; +1F96B;CANNED FOOD;So;0;ON;;;;;N;;;;; +1F980;CRAB;So;0;ON;;;;;N;;;;; +1F981;LION FACE;So;0;ON;;;;;N;;;;; +1F982;SCORPION;So;0;ON;;;;;N;;;;; +1F983;TURKEY;So;0;ON;;;;;N;;;;; +1F984;UNICORN FACE;So;0;ON;;;;;N;;;;; +1F985;EAGLE;So;0;ON;;;;;N;;;;; +1F986;DUCK;So;0;ON;;;;;N;;;;; +1F987;BAT;So;0;ON;;;;;N;;;;; +1F988;SHARK;So;0;ON;;;;;N;;;;; +1F989;OWL;So;0;ON;;;;;N;;;;; +1F98A;FOX FACE;So;0;ON;;;;;N;;;;; +1F98B;BUTTERFLY;So;0;ON;;;;;N;;;;; +1F98C;DEER;So;0;ON;;;;;N;;;;; +1F98D;GORILLA;So;0;ON;;;;;N;;;;; +1F98E;LIZARD;So;0;ON;;;;;N;;;;; +1F98F;RHINOCEROS;So;0;ON;;;;;N;;;;; +1F990;SHRIMP;So;0;ON;;;;;N;;;;; +1F991;SQUID;So;0;ON;;;;;N;;;;; +1F992;GIRAFFE FACE;So;0;ON;;;;;N;;;;; +1F993;ZEBRA FACE;So;0;ON;;;;;N;;;;; +1F994;HEDGEHOG;So;0;ON;;;;;N;;;;; +1F995;SAUROPOD;So;0;ON;;;;;N;;;;; +1F996;T-REX;So;0;ON;;;;;N;;;;; +1F997;CRICKET;So;0;ON;;;;;N;;;;; +1F9C0;CHEESE WEDGE;So;0;ON;;;;;N;;;;; +1F9D0;FACE WITH MONOCLE;So;0;ON;;;;;N;;;;; +1F9D1;ADULT;So;0;ON;;;;;N;;;;; +1F9D2;CHILD;So;0;ON;;;;;N;;;;; +1F9D3;OLDER ADULT;So;0;ON;;;;;N;;;;; +1F9D4;BEARDED PERSON;So;0;ON;;;;;N;;;;; +1F9D5;PERSON WITH HEADSCARF;So;0;ON;;;;;N;;;;; +1F9D6;PERSON IN STEAMY ROOM;So;0;ON;;;;;N;;;;; +1F9D7;PERSON CLIMBING;So;0;ON;;;;;N;;;;; +1F9D8;PERSON IN LOTUS POSITION;So;0;ON;;;;;N;;;;; +1F9D9;MAGE;So;0;ON;;;;;N;;;;; +1F9DA;FAIRY;So;0;ON;;;;;N;;;;; +1F9DB;VAMPIRE;So;0;ON;;;;;N;;;;; +1F9DC;MERPERSON;So;0;ON;;;;;N;;;;; +1F9DD;ELF;So;0;ON;;;;;N;;;;; +1F9DE;GENIE;So;0;ON;;;;;N;;;;; +1F9DF;ZOMBIE;So;0;ON;;;;;N;;;;; +1F9E0;BRAIN;So;0;ON;;;;;N;;;;; +1F9E1;ORANGE HEART;So;0;ON;;;;;N;;;;; +1F9E2;BILLED CAP;So;0;ON;;;;;N;;;;; +1F9E3;SCARF;So;0;ON;;;;;N;;;;; +1F9E4;GLOVES;So;0;ON;;;;;N;;;;; +1F9E5;COAT;So;0;ON;;;;;N;;;;; +1F9E6;SOCKS;So;0;ON;;;;;N;;;;; +20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;; +2A6D6;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;; +2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;; +2B734;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;; +2B740;<CJK Ideograph Extension D, First>;Lo;0;L;;;;;N;;;;; +2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;; +2B820;<CJK Ideograph Extension E, First>;Lo;0;L;;;;;N;;;;; +2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;; +2CEB0;<CJK Ideograph Extension F, First>;Lo;0;L;;;;;N;;;;; +2EBE0;<CJK Ideograph Extension F, Last>;Lo;0;L;;;;;N;;;;; +2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; +2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; +2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; +2F803;CJK COMPATIBILITY IDEOGRAPH-2F803;Lo;0;L;20122;;;;N;;;;; +2F804;CJK COMPATIBILITY IDEOGRAPH-2F804;Lo;0;L;4F60;;;;N;;;;; +2F805;CJK COMPATIBILITY IDEOGRAPH-2F805;Lo;0;L;4FAE;;;;N;;;;; +2F806;CJK COMPATIBILITY IDEOGRAPH-2F806;Lo;0;L;4FBB;;;;N;;;;; +2F807;CJK COMPATIBILITY IDEOGRAPH-2F807;Lo;0;L;5002;;;;N;;;;; +2F808;CJK COMPATIBILITY IDEOGRAPH-2F808;Lo;0;L;507A;;;;N;;;;; +2F809;CJK COMPATIBILITY IDEOGRAPH-2F809;Lo;0;L;5099;;;;N;;;;; +2F80A;CJK COMPATIBILITY IDEOGRAPH-2F80A;Lo;0;L;50E7;;;;N;;;;; +2F80B;CJK COMPATIBILITY IDEOGRAPH-2F80B;Lo;0;L;50CF;;;;N;;;;; +2F80C;CJK COMPATIBILITY IDEOGRAPH-2F80C;Lo;0;L;349E;;;;N;;;;; +2F80D;CJK COMPATIBILITY IDEOGRAPH-2F80D;Lo;0;L;2063A;;;;N;;;;; +2F80E;CJK COMPATIBILITY IDEOGRAPH-2F80E;Lo;0;L;514D;;;;N;;;;; +2F80F;CJK COMPATIBILITY IDEOGRAPH-2F80F;Lo;0;L;5154;;;;N;;;;; +2F810;CJK COMPATIBILITY IDEOGRAPH-2F810;Lo;0;L;5164;;;;N;;;;; +2F811;CJK COMPATIBILITY IDEOGRAPH-2F811;Lo;0;L;5177;;;;N;;;;; +2F812;CJK COMPATIBILITY IDEOGRAPH-2F812;Lo;0;L;2051C;;;;N;;;;; +2F813;CJK COMPATIBILITY IDEOGRAPH-2F813;Lo;0;L;34B9;;;;N;;;;; +2F814;CJK COMPATIBILITY IDEOGRAPH-2F814;Lo;0;L;5167;;;;N;;;;; +2F815;CJK COMPATIBILITY IDEOGRAPH-2F815;Lo;0;L;518D;;;;N;;;;; +2F816;CJK COMPATIBILITY IDEOGRAPH-2F816;Lo;0;L;2054B;;;;N;;;;; +2F817;CJK COMPATIBILITY IDEOGRAPH-2F817;Lo;0;L;5197;;;;N;;;;; +2F818;CJK COMPATIBILITY IDEOGRAPH-2F818;Lo;0;L;51A4;;;;N;;;;; +2F819;CJK COMPATIBILITY IDEOGRAPH-2F819;Lo;0;L;4ECC;;;;N;;;;; +2F81A;CJK COMPATIBILITY IDEOGRAPH-2F81A;Lo;0;L;51AC;;;;N;;;;; +2F81B;CJK COMPATIBILITY IDEOGRAPH-2F81B;Lo;0;L;51B5;;;;N;;;;; +2F81C;CJK COMPATIBILITY IDEOGRAPH-2F81C;Lo;0;L;291DF;;;;N;;;;; +2F81D;CJK COMPATIBILITY IDEOGRAPH-2F81D;Lo;0;L;51F5;;;;N;;;;; +2F81E;CJK COMPATIBILITY IDEOGRAPH-2F81E;Lo;0;L;5203;;;;N;;;;; +2F81F;CJK COMPATIBILITY IDEOGRAPH-2F81F;Lo;0;L;34DF;;;;N;;;;; +2F820;CJK COMPATIBILITY IDEOGRAPH-2F820;Lo;0;L;523B;;;;N;;;;; +2F821;CJK COMPATIBILITY IDEOGRAPH-2F821;Lo;0;L;5246;;;;N;;;;; +2F822;CJK COMPATIBILITY IDEOGRAPH-2F822;Lo;0;L;5272;;;;N;;;;; +2F823;CJK COMPATIBILITY IDEOGRAPH-2F823;Lo;0;L;5277;;;;N;;;;; +2F824;CJK COMPATIBILITY IDEOGRAPH-2F824;Lo;0;L;3515;;;;N;;;;; +2F825;CJK COMPATIBILITY IDEOGRAPH-2F825;Lo;0;L;52C7;;;;N;;;;; +2F826;CJK COMPATIBILITY IDEOGRAPH-2F826;Lo;0;L;52C9;;;;N;;;;; +2F827;CJK COMPATIBILITY IDEOGRAPH-2F827;Lo;0;L;52E4;;;;N;;;;; +2F828;CJK COMPATIBILITY IDEOGRAPH-2F828;Lo;0;L;52FA;;;;N;;;;; +2F829;CJK COMPATIBILITY IDEOGRAPH-2F829;Lo;0;L;5305;;;;N;;;;; +2F82A;CJK COMPATIBILITY IDEOGRAPH-2F82A;Lo;0;L;5306;;;;N;;;;; +2F82B;CJK COMPATIBILITY IDEOGRAPH-2F82B;Lo;0;L;5317;;;;N;;;;; +2F82C;CJK COMPATIBILITY IDEOGRAPH-2F82C;Lo;0;L;5349;;;;N;;;;; +2F82D;CJK COMPATIBILITY IDEOGRAPH-2F82D;Lo;0;L;5351;;;;N;;;;; +2F82E;CJK COMPATIBILITY IDEOGRAPH-2F82E;Lo;0;L;535A;;;;N;;;;; +2F82F;CJK COMPATIBILITY IDEOGRAPH-2F82F;Lo;0;L;5373;;;;N;;;;; +2F830;CJK COMPATIBILITY IDEOGRAPH-2F830;Lo;0;L;537D;;;;N;;;;; +2F831;CJK COMPATIBILITY IDEOGRAPH-2F831;Lo;0;L;537F;;;;N;;;;; +2F832;CJK COMPATIBILITY IDEOGRAPH-2F832;Lo;0;L;537F;;;;N;;;;; +2F833;CJK COMPATIBILITY IDEOGRAPH-2F833;Lo;0;L;537F;;;;N;;;;; +2F834;CJK COMPATIBILITY IDEOGRAPH-2F834;Lo;0;L;20A2C;;;;N;;;;; +2F835;CJK COMPATIBILITY IDEOGRAPH-2F835;Lo;0;L;7070;;;;N;;;;; +2F836;CJK COMPATIBILITY IDEOGRAPH-2F836;Lo;0;L;53CA;;;;N;;;;; +2F837;CJK COMPATIBILITY IDEOGRAPH-2F837;Lo;0;L;53DF;;;;N;;;;; +2F838;CJK COMPATIBILITY IDEOGRAPH-2F838;Lo;0;L;20B63;;;;N;;;;; +2F839;CJK COMPATIBILITY IDEOGRAPH-2F839;Lo;0;L;53EB;;;;N;;;;; +2F83A;CJK COMPATIBILITY IDEOGRAPH-2F83A;Lo;0;L;53F1;;;;N;;;;; +2F83B;CJK COMPATIBILITY IDEOGRAPH-2F83B;Lo;0;L;5406;;;;N;;;;; +2F83C;CJK COMPATIBILITY IDEOGRAPH-2F83C;Lo;0;L;549E;;;;N;;;;; +2F83D;CJK COMPATIBILITY IDEOGRAPH-2F83D;Lo;0;L;5438;;;;N;;;;; +2F83E;CJK COMPATIBILITY IDEOGRAPH-2F83E;Lo;0;L;5448;;;;N;;;;; +2F83F;CJK COMPATIBILITY IDEOGRAPH-2F83F;Lo;0;L;5468;;;;N;;;;; +2F840;CJK COMPATIBILITY IDEOGRAPH-2F840;Lo;0;L;54A2;;;;N;;;;; +2F841;CJK COMPATIBILITY IDEOGRAPH-2F841;Lo;0;L;54F6;;;;N;;;;; +2F842;CJK COMPATIBILITY IDEOGRAPH-2F842;Lo;0;L;5510;;;;N;;;;; +2F843;CJK COMPATIBILITY IDEOGRAPH-2F843;Lo;0;L;5553;;;;N;;;;; +2F844;CJK COMPATIBILITY IDEOGRAPH-2F844;Lo;0;L;5563;;;;N;;;;; +2F845;CJK COMPATIBILITY IDEOGRAPH-2F845;Lo;0;L;5584;;;;N;;;;; +2F846;CJK COMPATIBILITY IDEOGRAPH-2F846;Lo;0;L;5584;;;;N;;;;; +2F847;CJK COMPATIBILITY IDEOGRAPH-2F847;Lo;0;L;5599;;;;N;;;;; +2F848;CJK COMPATIBILITY IDEOGRAPH-2F848;Lo;0;L;55AB;;;;N;;;;; +2F849;CJK COMPATIBILITY IDEOGRAPH-2F849;Lo;0;L;55B3;;;;N;;;;; +2F84A;CJK COMPATIBILITY IDEOGRAPH-2F84A;Lo;0;L;55C2;;;;N;;;;; +2F84B;CJK COMPATIBILITY IDEOGRAPH-2F84B;Lo;0;L;5716;;;;N;;;;; +2F84C;CJK COMPATIBILITY IDEOGRAPH-2F84C;Lo;0;L;5606;;;;N;;;;; +2F84D;CJK COMPATIBILITY IDEOGRAPH-2F84D;Lo;0;L;5717;;;;N;;;;; +2F84E;CJK COMPATIBILITY IDEOGRAPH-2F84E;Lo;0;L;5651;;;;N;;;;; +2F84F;CJK COMPATIBILITY IDEOGRAPH-2F84F;Lo;0;L;5674;;;;N;;;;; +2F850;CJK COMPATIBILITY IDEOGRAPH-2F850;Lo;0;L;5207;;;;N;;;;; +2F851;CJK COMPATIBILITY IDEOGRAPH-2F851;Lo;0;L;58EE;;;;N;;;;; +2F852;CJK COMPATIBILITY IDEOGRAPH-2F852;Lo;0;L;57CE;;;;N;;;;; +2F853;CJK COMPATIBILITY IDEOGRAPH-2F853;Lo;0;L;57F4;;;;N;;;;; +2F854;CJK COMPATIBILITY IDEOGRAPH-2F854;Lo;0;L;580D;;;;N;;;;; +2F855;CJK COMPATIBILITY IDEOGRAPH-2F855;Lo;0;L;578B;;;;N;;;;; +2F856;CJK COMPATIBILITY IDEOGRAPH-2F856;Lo;0;L;5832;;;;N;;;;; +2F857;CJK COMPATIBILITY IDEOGRAPH-2F857;Lo;0;L;5831;;;;N;;;;; +2F858;CJK COMPATIBILITY IDEOGRAPH-2F858;Lo;0;L;58AC;;;;N;;;;; +2F859;CJK COMPATIBILITY IDEOGRAPH-2F859;Lo;0;L;214E4;;;;N;;;;; +2F85A;CJK COMPATIBILITY IDEOGRAPH-2F85A;Lo;0;L;58F2;;;;N;;;;; +2F85B;CJK COMPATIBILITY IDEOGRAPH-2F85B;Lo;0;L;58F7;;;;N;;;;; +2F85C;CJK COMPATIBILITY IDEOGRAPH-2F85C;Lo;0;L;5906;;;;N;;;;; +2F85D;CJK COMPATIBILITY IDEOGRAPH-2F85D;Lo;0;L;591A;;;;N;;;;; +2F85E;CJK COMPATIBILITY IDEOGRAPH-2F85E;Lo;0;L;5922;;;;N;;;;; +2F85F;CJK COMPATIBILITY IDEOGRAPH-2F85F;Lo;0;L;5962;;;;N;;;;; +2F860;CJK COMPATIBILITY IDEOGRAPH-2F860;Lo;0;L;216A8;;;;N;;;;; +2F861;CJK COMPATIBILITY IDEOGRAPH-2F861;Lo;0;L;216EA;;;;N;;;;; +2F862;CJK COMPATIBILITY IDEOGRAPH-2F862;Lo;0;L;59EC;;;;N;;;;; +2F863;CJK COMPATIBILITY IDEOGRAPH-2F863;Lo;0;L;5A1B;;;;N;;;;; +2F864;CJK COMPATIBILITY IDEOGRAPH-2F864;Lo;0;L;5A27;;;;N;;;;; +2F865;CJK COMPATIBILITY IDEOGRAPH-2F865;Lo;0;L;59D8;;;;N;;;;; +2F866;CJK COMPATIBILITY IDEOGRAPH-2F866;Lo;0;L;5A66;;;;N;;;;; +2F867;CJK COMPATIBILITY IDEOGRAPH-2F867;Lo;0;L;36EE;;;;N;;;;; +2F868;CJK COMPATIBILITY IDEOGRAPH-2F868;Lo;0;L;36FC;;;;N;;;;; +2F869;CJK COMPATIBILITY IDEOGRAPH-2F869;Lo;0;L;5B08;;;;N;;;;; +2F86A;CJK COMPATIBILITY IDEOGRAPH-2F86A;Lo;0;L;5B3E;;;;N;;;;; +2F86B;CJK COMPATIBILITY IDEOGRAPH-2F86B;Lo;0;L;5B3E;;;;N;;;;; +2F86C;CJK COMPATIBILITY IDEOGRAPH-2F86C;Lo;0;L;219C8;;;;N;;;;; +2F86D;CJK COMPATIBILITY IDEOGRAPH-2F86D;Lo;0;L;5BC3;;;;N;;;;; +2F86E;CJK COMPATIBILITY IDEOGRAPH-2F86E;Lo;0;L;5BD8;;;;N;;;;; +2F86F;CJK COMPATIBILITY IDEOGRAPH-2F86F;Lo;0;L;5BE7;;;;N;;;;; +2F870;CJK COMPATIBILITY IDEOGRAPH-2F870;Lo;0;L;5BF3;;;;N;;;;; +2F871;CJK COMPATIBILITY IDEOGRAPH-2F871;Lo;0;L;21B18;;;;N;;;;; +2F872;CJK COMPATIBILITY IDEOGRAPH-2F872;Lo;0;L;5BFF;;;;N;;;;; +2F873;CJK COMPATIBILITY IDEOGRAPH-2F873;Lo;0;L;5C06;;;;N;;;;; +2F874;CJK COMPATIBILITY IDEOGRAPH-2F874;Lo;0;L;5F53;;;;N;;;;; +2F875;CJK COMPATIBILITY IDEOGRAPH-2F875;Lo;0;L;5C22;;;;N;;;;; +2F876;CJK COMPATIBILITY IDEOGRAPH-2F876;Lo;0;L;3781;;;;N;;;;; +2F877;CJK COMPATIBILITY IDEOGRAPH-2F877;Lo;0;L;5C60;;;;N;;;;; +2F878;CJK COMPATIBILITY IDEOGRAPH-2F878;Lo;0;L;5C6E;;;;N;;;;; +2F879;CJK COMPATIBILITY IDEOGRAPH-2F879;Lo;0;L;5CC0;;;;N;;;;; +2F87A;CJK COMPATIBILITY IDEOGRAPH-2F87A;Lo;0;L;5C8D;;;;N;;;;; +2F87B;CJK COMPATIBILITY IDEOGRAPH-2F87B;Lo;0;L;21DE4;;;;N;;;;; +2F87C;CJK COMPATIBILITY IDEOGRAPH-2F87C;Lo;0;L;5D43;;;;N;;;;; +2F87D;CJK COMPATIBILITY IDEOGRAPH-2F87D;Lo;0;L;21DE6;;;;N;;;;; +2F87E;CJK COMPATIBILITY IDEOGRAPH-2F87E;Lo;0;L;5D6E;;;;N;;;;; +2F87F;CJK COMPATIBILITY IDEOGRAPH-2F87F;Lo;0;L;5D6B;;;;N;;;;; +2F880;CJK COMPATIBILITY IDEOGRAPH-2F880;Lo;0;L;5D7C;;;;N;;;;; +2F881;CJK COMPATIBILITY IDEOGRAPH-2F881;Lo;0;L;5DE1;;;;N;;;;; +2F882;CJK COMPATIBILITY IDEOGRAPH-2F882;Lo;0;L;5DE2;;;;N;;;;; +2F883;CJK COMPATIBILITY IDEOGRAPH-2F883;Lo;0;L;382F;;;;N;;;;; +2F884;CJK COMPATIBILITY IDEOGRAPH-2F884;Lo;0;L;5DFD;;;;N;;;;; +2F885;CJK COMPATIBILITY IDEOGRAPH-2F885;Lo;0;L;5E28;;;;N;;;;; +2F886;CJK COMPATIBILITY IDEOGRAPH-2F886;Lo;0;L;5E3D;;;;N;;;;; +2F887;CJK COMPATIBILITY IDEOGRAPH-2F887;Lo;0;L;5E69;;;;N;;;;; +2F888;CJK COMPATIBILITY IDEOGRAPH-2F888;Lo;0;L;3862;;;;N;;;;; +2F889;CJK COMPATIBILITY IDEOGRAPH-2F889;Lo;0;L;22183;;;;N;;;;; +2F88A;CJK COMPATIBILITY IDEOGRAPH-2F88A;Lo;0;L;387C;;;;N;;;;; +2F88B;CJK COMPATIBILITY IDEOGRAPH-2F88B;Lo;0;L;5EB0;;;;N;;;;; +2F88C;CJK COMPATIBILITY IDEOGRAPH-2F88C;Lo;0;L;5EB3;;;;N;;;;; +2F88D;CJK COMPATIBILITY IDEOGRAPH-2F88D;Lo;0;L;5EB6;;;;N;;;;; +2F88E;CJK COMPATIBILITY IDEOGRAPH-2F88E;Lo;0;L;5ECA;;;;N;;;;; +2F88F;CJK COMPATIBILITY IDEOGRAPH-2F88F;Lo;0;L;2A392;;;;N;;;;; +2F890;CJK COMPATIBILITY IDEOGRAPH-2F890;Lo;0;L;5EFE;;;9;N;;;;; +2F891;CJK COMPATIBILITY IDEOGRAPH-2F891;Lo;0;L;22331;;;;N;;;;; +2F892;CJK COMPATIBILITY IDEOGRAPH-2F892;Lo;0;L;22331;;;;N;;;;; +2F893;CJK COMPATIBILITY IDEOGRAPH-2F893;Lo;0;L;8201;;;;N;;;;; +2F894;CJK COMPATIBILITY IDEOGRAPH-2F894;Lo;0;L;5F22;;;;N;;;;; +2F895;CJK COMPATIBILITY IDEOGRAPH-2F895;Lo;0;L;5F22;;;;N;;;;; +2F896;CJK COMPATIBILITY IDEOGRAPH-2F896;Lo;0;L;38C7;;;;N;;;;; +2F897;CJK COMPATIBILITY IDEOGRAPH-2F897;Lo;0;L;232B8;;;;N;;;;; +2F898;CJK COMPATIBILITY IDEOGRAPH-2F898;Lo;0;L;261DA;;;;N;;;;; +2F899;CJK COMPATIBILITY IDEOGRAPH-2F899;Lo;0;L;5F62;;;;N;;;;; +2F89A;CJK COMPATIBILITY IDEOGRAPH-2F89A;Lo;0;L;5F6B;;;;N;;;;; +2F89B;CJK COMPATIBILITY IDEOGRAPH-2F89B;Lo;0;L;38E3;;;;N;;;;; +2F89C;CJK COMPATIBILITY IDEOGRAPH-2F89C;Lo;0;L;5F9A;;;;N;;;;; +2F89D;CJK COMPATIBILITY IDEOGRAPH-2F89D;Lo;0;L;5FCD;;;;N;;;;; +2F89E;CJK COMPATIBILITY IDEOGRAPH-2F89E;Lo;0;L;5FD7;;;;N;;;;; +2F89F;CJK COMPATIBILITY IDEOGRAPH-2F89F;Lo;0;L;5FF9;;;;N;;;;; +2F8A0;CJK COMPATIBILITY IDEOGRAPH-2F8A0;Lo;0;L;6081;;;;N;;;;; +2F8A1;CJK COMPATIBILITY IDEOGRAPH-2F8A1;Lo;0;L;393A;;;;N;;;;; +2F8A2;CJK COMPATIBILITY IDEOGRAPH-2F8A2;Lo;0;L;391C;;;;N;;;;; +2F8A3;CJK COMPATIBILITY IDEOGRAPH-2F8A3;Lo;0;L;6094;;;;N;;;;; +2F8A4;CJK COMPATIBILITY IDEOGRAPH-2F8A4;Lo;0;L;226D4;;;;N;;;;; +2F8A5;CJK COMPATIBILITY IDEOGRAPH-2F8A5;Lo;0;L;60C7;;;;N;;;;; +2F8A6;CJK COMPATIBILITY IDEOGRAPH-2F8A6;Lo;0;L;6148;;;;N;;;;; +2F8A7;CJK COMPATIBILITY IDEOGRAPH-2F8A7;Lo;0;L;614C;;;;N;;;;; +2F8A8;CJK COMPATIBILITY IDEOGRAPH-2F8A8;Lo;0;L;614E;;;;N;;;;; +2F8A9;CJK COMPATIBILITY IDEOGRAPH-2F8A9;Lo;0;L;614C;;;;N;;;;; +2F8AA;CJK COMPATIBILITY IDEOGRAPH-2F8AA;Lo;0;L;617A;;;;N;;;;; +2F8AB;CJK COMPATIBILITY IDEOGRAPH-2F8AB;Lo;0;L;618E;;;;N;;;;; +2F8AC;CJK COMPATIBILITY IDEOGRAPH-2F8AC;Lo;0;L;61B2;;;;N;;;;; +2F8AD;CJK COMPATIBILITY IDEOGRAPH-2F8AD;Lo;0;L;61A4;;;;N;;;;; +2F8AE;CJK COMPATIBILITY IDEOGRAPH-2F8AE;Lo;0;L;61AF;;;;N;;;;; +2F8AF;CJK COMPATIBILITY IDEOGRAPH-2F8AF;Lo;0;L;61DE;;;;N;;;;; +2F8B0;CJK COMPATIBILITY IDEOGRAPH-2F8B0;Lo;0;L;61F2;;;;N;;;;; +2F8B1;CJK COMPATIBILITY IDEOGRAPH-2F8B1;Lo;0;L;61F6;;;;N;;;;; +2F8B2;CJK COMPATIBILITY IDEOGRAPH-2F8B2;Lo;0;L;6210;;;;N;;;;; +2F8B3;CJK COMPATIBILITY IDEOGRAPH-2F8B3;Lo;0;L;621B;;;;N;;;;; +2F8B4;CJK COMPATIBILITY IDEOGRAPH-2F8B4;Lo;0;L;625D;;;;N;;;;; +2F8B5;CJK COMPATIBILITY IDEOGRAPH-2F8B5;Lo;0;L;62B1;;;;N;;;;; +2F8B6;CJK COMPATIBILITY IDEOGRAPH-2F8B6;Lo;0;L;62D4;;;;N;;;;; +2F8B7;CJK COMPATIBILITY IDEOGRAPH-2F8B7;Lo;0;L;6350;;;;N;;;;; +2F8B8;CJK COMPATIBILITY IDEOGRAPH-2F8B8;Lo;0;L;22B0C;;;;N;;;;; +2F8B9;CJK COMPATIBILITY IDEOGRAPH-2F8B9;Lo;0;L;633D;;;;N;;;;; +2F8BA;CJK COMPATIBILITY IDEOGRAPH-2F8BA;Lo;0;L;62FC;;;;N;;;;; +2F8BB;CJK COMPATIBILITY IDEOGRAPH-2F8BB;Lo;0;L;6368;;;;N;;;;; +2F8BC;CJK COMPATIBILITY IDEOGRAPH-2F8BC;Lo;0;L;6383;;;;N;;;;; +2F8BD;CJK COMPATIBILITY IDEOGRAPH-2F8BD;Lo;0;L;63E4;;;;N;;;;; +2F8BE;CJK COMPATIBILITY IDEOGRAPH-2F8BE;Lo;0;L;22BF1;;;;N;;;;; +2F8BF;CJK COMPATIBILITY IDEOGRAPH-2F8BF;Lo;0;L;6422;;;;N;;;;; +2F8C0;CJK COMPATIBILITY IDEOGRAPH-2F8C0;Lo;0;L;63C5;;;;N;;;;; +2F8C1;CJK COMPATIBILITY IDEOGRAPH-2F8C1;Lo;0;L;63A9;;;;N;;;;; +2F8C2;CJK COMPATIBILITY IDEOGRAPH-2F8C2;Lo;0;L;3A2E;;;;N;;;;; +2F8C3;CJK COMPATIBILITY IDEOGRAPH-2F8C3;Lo;0;L;6469;;;;N;;;;; +2F8C4;CJK COMPATIBILITY IDEOGRAPH-2F8C4;Lo;0;L;647E;;;;N;;;;; +2F8C5;CJK COMPATIBILITY IDEOGRAPH-2F8C5;Lo;0;L;649D;;;;N;;;;; +2F8C6;CJK COMPATIBILITY IDEOGRAPH-2F8C6;Lo;0;L;6477;;;;N;;;;; +2F8C7;CJK COMPATIBILITY IDEOGRAPH-2F8C7;Lo;0;L;3A6C;;;;N;;;;; +2F8C8;CJK COMPATIBILITY IDEOGRAPH-2F8C8;Lo;0;L;654F;;;;N;;;;; +2F8C9;CJK COMPATIBILITY IDEOGRAPH-2F8C9;Lo;0;L;656C;;;;N;;;;; +2F8CA;CJK COMPATIBILITY IDEOGRAPH-2F8CA;Lo;0;L;2300A;;;;N;;;;; +2F8CB;CJK COMPATIBILITY IDEOGRAPH-2F8CB;Lo;0;L;65E3;;;;N;;;;; +2F8CC;CJK COMPATIBILITY IDEOGRAPH-2F8CC;Lo;0;L;66F8;;;;N;;;;; +2F8CD;CJK COMPATIBILITY IDEOGRAPH-2F8CD;Lo;0;L;6649;;;;N;;;;; +2F8CE;CJK COMPATIBILITY IDEOGRAPH-2F8CE;Lo;0;L;3B19;;;;N;;;;; +2F8CF;CJK COMPATIBILITY IDEOGRAPH-2F8CF;Lo;0;L;6691;;;;N;;;;; +2F8D0;CJK COMPATIBILITY IDEOGRAPH-2F8D0;Lo;0;L;3B08;;;;N;;;;; +2F8D1;CJK COMPATIBILITY IDEOGRAPH-2F8D1;Lo;0;L;3AE4;;;;N;;;;; +2F8D2;CJK COMPATIBILITY IDEOGRAPH-2F8D2;Lo;0;L;5192;;;;N;;;;; +2F8D3;CJK COMPATIBILITY IDEOGRAPH-2F8D3;Lo;0;L;5195;;;;N;;;;; +2F8D4;CJK COMPATIBILITY IDEOGRAPH-2F8D4;Lo;0;L;6700;;;;N;;;;; +2F8D5;CJK COMPATIBILITY IDEOGRAPH-2F8D5;Lo;0;L;669C;;;;N;;;;; +2F8D6;CJK COMPATIBILITY IDEOGRAPH-2F8D6;Lo;0;L;80AD;;;;N;;;;; +2F8D7;CJK COMPATIBILITY IDEOGRAPH-2F8D7;Lo;0;L;43D9;;;;N;;;;; +2F8D8;CJK COMPATIBILITY IDEOGRAPH-2F8D8;Lo;0;L;6717;;;;N;;;;; +2F8D9;CJK COMPATIBILITY IDEOGRAPH-2F8D9;Lo;0;L;671B;;;;N;;;;; +2F8DA;CJK COMPATIBILITY IDEOGRAPH-2F8DA;Lo;0;L;6721;;;;N;;;;; +2F8DB;CJK COMPATIBILITY IDEOGRAPH-2F8DB;Lo;0;L;675E;;;;N;;;;; +2F8DC;CJK COMPATIBILITY IDEOGRAPH-2F8DC;Lo;0;L;6753;;;;N;;;;; +2F8DD;CJK COMPATIBILITY IDEOGRAPH-2F8DD;Lo;0;L;233C3;;;;N;;;;; +2F8DE;CJK COMPATIBILITY IDEOGRAPH-2F8DE;Lo;0;L;3B49;;;;N;;;;; +2F8DF;CJK COMPATIBILITY IDEOGRAPH-2F8DF;Lo;0;L;67FA;;;;N;;;;; +2F8E0;CJK COMPATIBILITY IDEOGRAPH-2F8E0;Lo;0;L;6785;;;;N;;;;; +2F8E1;CJK COMPATIBILITY IDEOGRAPH-2F8E1;Lo;0;L;6852;;;;N;;;;; +2F8E2;CJK COMPATIBILITY IDEOGRAPH-2F8E2;Lo;0;L;6885;;;;N;;;;; +2F8E3;CJK COMPATIBILITY IDEOGRAPH-2F8E3;Lo;0;L;2346D;;;;N;;;;; +2F8E4;CJK COMPATIBILITY IDEOGRAPH-2F8E4;Lo;0;L;688E;;;;N;;;;; +2F8E5;CJK COMPATIBILITY IDEOGRAPH-2F8E5;Lo;0;L;681F;;;;N;;;;; +2F8E6;CJK COMPATIBILITY IDEOGRAPH-2F8E6;Lo;0;L;6914;;;;N;;;;; +2F8E7;CJK COMPATIBILITY IDEOGRAPH-2F8E7;Lo;0;L;3B9D;;;;N;;;;; +2F8E8;CJK COMPATIBILITY IDEOGRAPH-2F8E8;Lo;0;L;6942;;;;N;;;;; +2F8E9;CJK COMPATIBILITY IDEOGRAPH-2F8E9;Lo;0;L;69A3;;;;N;;;;; +2F8EA;CJK COMPATIBILITY IDEOGRAPH-2F8EA;Lo;0;L;69EA;;;;N;;;;; +2F8EB;CJK COMPATIBILITY IDEOGRAPH-2F8EB;Lo;0;L;6AA8;;;;N;;;;; +2F8EC;CJK COMPATIBILITY IDEOGRAPH-2F8EC;Lo;0;L;236A3;;;;N;;;;; +2F8ED;CJK COMPATIBILITY IDEOGRAPH-2F8ED;Lo;0;L;6ADB;;;;N;;;;; +2F8EE;CJK COMPATIBILITY IDEOGRAPH-2F8EE;Lo;0;L;3C18;;;;N;;;;; +2F8EF;CJK COMPATIBILITY IDEOGRAPH-2F8EF;Lo;0;L;6B21;;;;N;;;;; +2F8F0;CJK COMPATIBILITY IDEOGRAPH-2F8F0;Lo;0;L;238A7;;;;N;;;;; +2F8F1;CJK COMPATIBILITY IDEOGRAPH-2F8F1;Lo;0;L;6B54;;;;N;;;;; +2F8F2;CJK COMPATIBILITY IDEOGRAPH-2F8F2;Lo;0;L;3C4E;;;;N;;;;; +2F8F3;CJK COMPATIBILITY IDEOGRAPH-2F8F3;Lo;0;L;6B72;;;;N;;;;; +2F8F4;CJK COMPATIBILITY IDEOGRAPH-2F8F4;Lo;0;L;6B9F;;;;N;;;;; +2F8F5;CJK COMPATIBILITY IDEOGRAPH-2F8F5;Lo;0;L;6BBA;;;;N;;;;; +2F8F6;CJK COMPATIBILITY IDEOGRAPH-2F8F6;Lo;0;L;6BBB;;;;N;;;;; +2F8F7;CJK COMPATIBILITY IDEOGRAPH-2F8F7;Lo;0;L;23A8D;;;;N;;;;; +2F8F8;CJK COMPATIBILITY IDEOGRAPH-2F8F8;Lo;0;L;21D0B;;;;N;;;;; +2F8F9;CJK COMPATIBILITY IDEOGRAPH-2F8F9;Lo;0;L;23AFA;;;;N;;;;; +2F8FA;CJK COMPATIBILITY IDEOGRAPH-2F8FA;Lo;0;L;6C4E;;;;N;;;;; +2F8FB;CJK COMPATIBILITY IDEOGRAPH-2F8FB;Lo;0;L;23CBC;;;;N;;;;; +2F8FC;CJK COMPATIBILITY IDEOGRAPH-2F8FC;Lo;0;L;6CBF;;;;N;;;;; +2F8FD;CJK COMPATIBILITY IDEOGRAPH-2F8FD;Lo;0;L;6CCD;;;;N;;;;; +2F8FE;CJK COMPATIBILITY IDEOGRAPH-2F8FE;Lo;0;L;6C67;;;;N;;;;; +2F8FF;CJK COMPATIBILITY IDEOGRAPH-2F8FF;Lo;0;L;6D16;;;;N;;;;; +2F900;CJK COMPATIBILITY IDEOGRAPH-2F900;Lo;0;L;6D3E;;;;N;;;;; +2F901;CJK COMPATIBILITY IDEOGRAPH-2F901;Lo;0;L;6D77;;;;N;;;;; +2F902;CJK COMPATIBILITY IDEOGRAPH-2F902;Lo;0;L;6D41;;;;N;;;;; +2F903;CJK COMPATIBILITY IDEOGRAPH-2F903;Lo;0;L;6D69;;;;N;;;;; +2F904;CJK COMPATIBILITY IDEOGRAPH-2F904;Lo;0;L;6D78;;;;N;;;;; +2F905;CJK COMPATIBILITY IDEOGRAPH-2F905;Lo;0;L;6D85;;;;N;;;;; +2F906;CJK COMPATIBILITY IDEOGRAPH-2F906;Lo;0;L;23D1E;;;;N;;;;; +2F907;CJK COMPATIBILITY IDEOGRAPH-2F907;Lo;0;L;6D34;;;;N;;;;; +2F908;CJK COMPATIBILITY IDEOGRAPH-2F908;Lo;0;L;6E2F;;;;N;;;;; +2F909;CJK COMPATIBILITY IDEOGRAPH-2F909;Lo;0;L;6E6E;;;;N;;;;; +2F90A;CJK COMPATIBILITY IDEOGRAPH-2F90A;Lo;0;L;3D33;;;;N;;;;; +2F90B;CJK COMPATIBILITY IDEOGRAPH-2F90B;Lo;0;L;6ECB;;;;N;;;;; +2F90C;CJK COMPATIBILITY IDEOGRAPH-2F90C;Lo;0;L;6EC7;;;;N;;;;; +2F90D;CJK COMPATIBILITY IDEOGRAPH-2F90D;Lo;0;L;23ED1;;;;N;;;;; +2F90E;CJK COMPATIBILITY IDEOGRAPH-2F90E;Lo;0;L;6DF9;;;;N;;;;; +2F90F;CJK COMPATIBILITY IDEOGRAPH-2F90F;Lo;0;L;6F6E;;;;N;;;;; +2F910;CJK COMPATIBILITY IDEOGRAPH-2F910;Lo;0;L;23F5E;;;;N;;;;; +2F911;CJK COMPATIBILITY IDEOGRAPH-2F911;Lo;0;L;23F8E;;;;N;;;;; +2F912;CJK COMPATIBILITY IDEOGRAPH-2F912;Lo;0;L;6FC6;;;;N;;;;; +2F913;CJK COMPATIBILITY IDEOGRAPH-2F913;Lo;0;L;7039;;;;N;;;;; +2F914;CJK COMPATIBILITY IDEOGRAPH-2F914;Lo;0;L;701E;;;;N;;;;; +2F915;CJK COMPATIBILITY IDEOGRAPH-2F915;Lo;0;L;701B;;;;N;;;;; +2F916;CJK COMPATIBILITY IDEOGRAPH-2F916;Lo;0;L;3D96;;;;N;;;;; +2F917;CJK COMPATIBILITY IDEOGRAPH-2F917;Lo;0;L;704A;;;;N;;;;; +2F918;CJK COMPATIBILITY IDEOGRAPH-2F918;Lo;0;L;707D;;;;N;;;;; +2F919;CJK COMPATIBILITY IDEOGRAPH-2F919;Lo;0;L;7077;;;;N;;;;; +2F91A;CJK COMPATIBILITY IDEOGRAPH-2F91A;Lo;0;L;70AD;;;;N;;;;; +2F91B;CJK COMPATIBILITY IDEOGRAPH-2F91B;Lo;0;L;20525;;;;N;;;;; +2F91C;CJK COMPATIBILITY IDEOGRAPH-2F91C;Lo;0;L;7145;;;;N;;;;; +2F91D;CJK COMPATIBILITY IDEOGRAPH-2F91D;Lo;0;L;24263;;;;N;;;;; +2F91E;CJK COMPATIBILITY IDEOGRAPH-2F91E;Lo;0;L;719C;;;;N;;;;; +2F91F;CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo;0;L;243AB;;;;N;;;;; +2F920;CJK COMPATIBILITY IDEOGRAPH-2F920;Lo;0;L;7228;;;;N;;;;; +2F921;CJK COMPATIBILITY IDEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;; +2F922;CJK COMPATIBILITY IDEOGRAPH-2F922;Lo;0;L;7250;;;;N;;;;; +2F923;CJK COMPATIBILITY IDEOGRAPH-2F923;Lo;0;L;24608;;;;N;;;;; +2F924;CJK COMPATIBILITY IDEOGRAPH-2F924;Lo;0;L;7280;;;;N;;;;; +2F925;CJK COMPATIBILITY IDEOGRAPH-2F925;Lo;0;L;7295;;;;N;;;;; +2F926;CJK COMPATIBILITY IDEOGRAPH-2F926;Lo;0;L;24735;;;;N;;;;; +2F927;CJK COMPATIBILITY IDEOGRAPH-2F927;Lo;0;L;24814;;;;N;;;;; +2F928;CJK COMPATIBILITY IDEOGRAPH-2F928;Lo;0;L;737A;;;;N;;;;; +2F929;CJK COMPATIBILITY IDEOGRAPH-2F929;Lo;0;L;738B;;;;N;;;;; +2F92A;CJK COMPATIBILITY IDEOGRAPH-2F92A;Lo;0;L;3EAC;;;;N;;;;; +2F92B;CJK COMPATIBILITY IDEOGRAPH-2F92B;Lo;0;L;73A5;;;;N;;;;; +2F92C;CJK COMPATIBILITY IDEOGRAPH-2F92C;Lo;0;L;3EB8;;;;N;;;;; +2F92D;CJK COMPATIBILITY IDEOGRAPH-2F92D;Lo;0;L;3EB8;;;;N;;;;; +2F92E;CJK COMPATIBILITY IDEOGRAPH-2F92E;Lo;0;L;7447;;;;N;;;;; +2F92F;CJK COMPATIBILITY IDEOGRAPH-2F92F;Lo;0;L;745C;;;;N;;;;; +2F930;CJK COMPATIBILITY IDEOGRAPH-2F930;Lo;0;L;7471;;;;N;;;;; +2F931;CJK COMPATIBILITY IDEOGRAPH-2F931;Lo;0;L;7485;;;;N;;;;; +2F932;CJK COMPATIBILITY IDEOGRAPH-2F932;Lo;0;L;74CA;;;;N;;;;; +2F933;CJK COMPATIBILITY IDEOGRAPH-2F933;Lo;0;L;3F1B;;;;N;;;;; +2F934;CJK COMPATIBILITY IDEOGRAPH-2F934;Lo;0;L;7524;;;;N;;;;; +2F935;CJK COMPATIBILITY IDEOGRAPH-2F935;Lo;0;L;24C36;;;;N;;;;; +2F936;CJK COMPATIBILITY IDEOGRAPH-2F936;Lo;0;L;753E;;;;N;;;;; +2F937;CJK COMPATIBILITY IDEOGRAPH-2F937;Lo;0;L;24C92;;;;N;;;;; +2F938;CJK COMPATIBILITY IDEOGRAPH-2F938;Lo;0;L;7570;;;;N;;;;; +2F939;CJK COMPATIBILITY IDEOGRAPH-2F939;Lo;0;L;2219F;;;;N;;;;; +2F93A;CJK COMPATIBILITY IDEOGRAPH-2F93A;Lo;0;L;7610;;;;N;;;;; +2F93B;CJK COMPATIBILITY IDEOGRAPH-2F93B;Lo;0;L;24FA1;;;;N;;;;; +2F93C;CJK COMPATIBILITY IDEOGRAPH-2F93C;Lo;0;L;24FB8;;;;N;;;;; +2F93D;CJK COMPATIBILITY IDEOGRAPH-2F93D;Lo;0;L;25044;;;;N;;;;; +2F93E;CJK COMPATIBILITY IDEOGRAPH-2F93E;Lo;0;L;3FFC;;;;N;;;;; +2F93F;CJK COMPATIBILITY IDEOGRAPH-2F93F;Lo;0;L;4008;;;;N;;;;; +2F940;CJK COMPATIBILITY IDEOGRAPH-2F940;Lo;0;L;76F4;;;;N;;;;; +2F941;CJK COMPATIBILITY IDEOGRAPH-2F941;Lo;0;L;250F3;;;;N;;;;; +2F942;CJK COMPATIBILITY IDEOGRAPH-2F942;Lo;0;L;250F2;;;;N;;;;; +2F943;CJK COMPATIBILITY IDEOGRAPH-2F943;Lo;0;L;25119;;;;N;;;;; +2F944;CJK COMPATIBILITY IDEOGRAPH-2F944;Lo;0;L;25133;;;;N;;;;; +2F945;CJK COMPATIBILITY IDEOGRAPH-2F945;Lo;0;L;771E;;;;N;;;;; +2F946;CJK COMPATIBILITY IDEOGRAPH-2F946;Lo;0;L;771F;;;;N;;;;; +2F947;CJK COMPATIBILITY IDEOGRAPH-2F947;Lo;0;L;771F;;;;N;;;;; +2F948;CJK COMPATIBILITY IDEOGRAPH-2F948;Lo;0;L;774A;;;;N;;;;; +2F949;CJK COMPATIBILITY IDEOGRAPH-2F949;Lo;0;L;4039;;;;N;;;;; +2F94A;CJK COMPATIBILITY IDEOGRAPH-2F94A;Lo;0;L;778B;;;;N;;;;; +2F94B;CJK COMPATIBILITY IDEOGRAPH-2F94B;Lo;0;L;4046;;;;N;;;;; +2F94C;CJK COMPATIBILITY IDEOGRAPH-2F94C;Lo;0;L;4096;;;;N;;;;; +2F94D;CJK COMPATIBILITY IDEOGRAPH-2F94D;Lo;0;L;2541D;;;;N;;;;; +2F94E;CJK COMPATIBILITY IDEOGRAPH-2F94E;Lo;0;L;784E;;;;N;;;;; +2F94F;CJK COMPATIBILITY IDEOGRAPH-2F94F;Lo;0;L;788C;;;;N;;;;; +2F950;CJK COMPATIBILITY IDEOGRAPH-2F950;Lo;0;L;78CC;;;;N;;;;; +2F951;CJK COMPATIBILITY IDEOGRAPH-2F951;Lo;0;L;40E3;;;;N;;;;; +2F952;CJK COMPATIBILITY IDEOGRAPH-2F952;Lo;0;L;25626;;;;N;;;;; +2F953;CJK COMPATIBILITY IDEOGRAPH-2F953;Lo;0;L;7956;;;;N;;;;; +2F954;CJK COMPATIBILITY IDEOGRAPH-2F954;Lo;0;L;2569A;;;;N;;;;; +2F955;CJK COMPATIBILITY IDEOGRAPH-2F955;Lo;0;L;256C5;;;;N;;;;; +2F956;CJK COMPATIBILITY IDEOGRAPH-2F956;Lo;0;L;798F;;;;N;;;;; +2F957;CJK COMPATIBILITY IDEOGRAPH-2F957;Lo;0;L;79EB;;;;N;;;;; +2F958;CJK COMPATIBILITY IDEOGRAPH-2F958;Lo;0;L;412F;;;;N;;;;; +2F959;CJK COMPATIBILITY IDEOGRAPH-2F959;Lo;0;L;7A40;;;;N;;;;; +2F95A;CJK COMPATIBILITY IDEOGRAPH-2F95A;Lo;0;L;7A4A;;;;N;;;;; +2F95B;CJK COMPATIBILITY IDEOGRAPH-2F95B;Lo;0;L;7A4F;;;;N;;;;; +2F95C;CJK COMPATIBILITY IDEOGRAPH-2F95C;Lo;0;L;2597C;;;;N;;;;; +2F95D;CJK COMPATIBILITY IDEOGRAPH-2F95D;Lo;0;L;25AA7;;;;N;;;;; +2F95E;CJK COMPATIBILITY IDEOGRAPH-2F95E;Lo;0;L;25AA7;;;;N;;;;; +2F95F;CJK COMPATIBILITY IDEOGRAPH-2F95F;Lo;0;L;7AEE;;;;N;;;;; +2F960;CJK COMPATIBILITY IDEOGRAPH-2F960;Lo;0;L;4202;;;;N;;;;; +2F961;CJK COMPATIBILITY IDEOGRAPH-2F961;Lo;0;L;25BAB;;;;N;;;;; +2F962;CJK COMPATIBILITY IDEOGRAPH-2F962;Lo;0;L;7BC6;;;;N;;;;; +2F963;CJK COMPATIBILITY IDEOGRAPH-2F963;Lo;0;L;7BC9;;;;N;;;;; +2F964;CJK COMPATIBILITY IDEOGRAPH-2F964;Lo;0;L;4227;;;;N;;;;; +2F965;CJK COMPATIBILITY IDEOGRAPH-2F965;Lo;0;L;25C80;;;;N;;;;; +2F966;CJK COMPATIBILITY IDEOGRAPH-2F966;Lo;0;L;7CD2;;;;N;;;;; +2F967;CJK COMPATIBILITY IDEOGRAPH-2F967;Lo;0;L;42A0;;;;N;;;;; +2F968;CJK COMPATIBILITY IDEOGRAPH-2F968;Lo;0;L;7CE8;;;;N;;;;; +2F969;CJK COMPATIBILITY IDEOGRAPH-2F969;Lo;0;L;7CE3;;;;N;;;;; +2F96A;CJK COMPATIBILITY IDEOGRAPH-2F96A;Lo;0;L;7D00;;;;N;;;;; +2F96B;CJK COMPATIBILITY IDEOGRAPH-2F96B;Lo;0;L;25F86;;;;N;;;;; +2F96C;CJK COMPATIBILITY IDEOGRAPH-2F96C;Lo;0;L;7D63;;;;N;;;;; +2F96D;CJK COMPATIBILITY IDEOGRAPH-2F96D;Lo;0;L;4301;;;;N;;;;; +2F96E;CJK COMPATIBILITY IDEOGRAPH-2F96E;Lo;0;L;7DC7;;;;N;;;;; +2F96F;CJK COMPATIBILITY IDEOGRAPH-2F96F;Lo;0;L;7E02;;;;N;;;;; +2F970;CJK COMPATIBILITY IDEOGRAPH-2F970;Lo;0;L;7E45;;;;N;;;;; +2F971;CJK COMPATIBILITY IDEOGRAPH-2F971;Lo;0;L;4334;;;;N;;;;; +2F972;CJK COMPATIBILITY IDEOGRAPH-2F972;Lo;0;L;26228;;;;N;;;;; +2F973;CJK COMPATIBILITY IDEOGRAPH-2F973;Lo;0;L;26247;;;;N;;;;; +2F974;CJK COMPATIBILITY IDEOGRAPH-2F974;Lo;0;L;4359;;;;N;;;;; +2F975;CJK COMPATIBILITY IDEOGRAPH-2F975;Lo;0;L;262D9;;;;N;;;;; +2F976;CJK COMPATIBILITY IDEOGRAPH-2F976;Lo;0;L;7F7A;;;;N;;;;; +2F977;CJK COMPATIBILITY IDEOGRAPH-2F977;Lo;0;L;2633E;;;;N;;;;; +2F978;CJK COMPATIBILITY IDEOGRAPH-2F978;Lo;0;L;7F95;;;;N;;;;; +2F979;CJK COMPATIBILITY IDEOGRAPH-2F979;Lo;0;L;7FFA;;;;N;;;;; +2F97A;CJK COMPATIBILITY IDEOGRAPH-2F97A;Lo;0;L;8005;;;;N;;;;; +2F97B;CJK COMPATIBILITY IDEOGRAPH-2F97B;Lo;0;L;264DA;;;;N;;;;; +2F97C;CJK COMPATIBILITY IDEOGRAPH-2F97C;Lo;0;L;26523;;;;N;;;;; +2F97D;CJK COMPATIBILITY IDEOGRAPH-2F97D;Lo;0;L;8060;;;;N;;;;; +2F97E;CJK COMPATIBILITY IDEOGRAPH-2F97E;Lo;0;L;265A8;;;;N;;;;; +2F97F;CJK COMPATIBILITY IDEOGRAPH-2F97F;Lo;0;L;8070;;;;N;;;;; +2F980;CJK COMPATIBILITY IDEOGRAPH-2F980;Lo;0;L;2335F;;;;N;;;;; +2F981;CJK COMPATIBILITY IDEOGRAPH-2F981;Lo;0;L;43D5;;;;N;;;;; +2F982;CJK COMPATIBILITY IDEOGRAPH-2F982;Lo;0;L;80B2;;;;N;;;;; +2F983;CJK COMPATIBILITY IDEOGRAPH-2F983;Lo;0;L;8103;;;;N;;;;; +2F984;CJK COMPATIBILITY IDEOGRAPH-2F984;Lo;0;L;440B;;;;N;;;;; +2F985;CJK COMPATIBILITY IDEOGRAPH-2F985;Lo;0;L;813E;;;;N;;;;; +2F986;CJK COMPATIBILITY IDEOGRAPH-2F986;Lo;0;L;5AB5;;;;N;;;;; +2F987;CJK COMPATIBILITY IDEOGRAPH-2F987;Lo;0;L;267A7;;;;N;;;;; +2F988;CJK COMPATIBILITY IDEOGRAPH-2F988;Lo;0;L;267B5;;;;N;;;;; +2F989;CJK COMPATIBILITY IDEOGRAPH-2F989;Lo;0;L;23393;;;;N;;;;; +2F98A;CJK COMPATIBILITY IDEOGRAPH-2F98A;Lo;0;L;2339C;;;;N;;;;; +2F98B;CJK COMPATIBILITY IDEOGRAPH-2F98B;Lo;0;L;8201;;;;N;;;;; +2F98C;CJK COMPATIBILITY IDEOGRAPH-2F98C;Lo;0;L;8204;;;;N;;;;; +2F98D;CJK COMPATIBILITY IDEOGRAPH-2F98D;Lo;0;L;8F9E;;;;N;;;;; +2F98E;CJK COMPATIBILITY IDEOGRAPH-2F98E;Lo;0;L;446B;;;;N;;;;; +2F98F;CJK COMPATIBILITY IDEOGRAPH-2F98F;Lo;0;L;8291;;;;N;;;;; +2F990;CJK COMPATIBILITY IDEOGRAPH-2F990;Lo;0;L;828B;;;;N;;;;; +2F991;CJK COMPATIBILITY IDEOGRAPH-2F991;Lo;0;L;829D;;;;N;;;;; +2F992;CJK COMPATIBILITY IDEOGRAPH-2F992;Lo;0;L;52B3;;;;N;;;;; +2F993;CJK COMPATIBILITY IDEOGRAPH-2F993;Lo;0;L;82B1;;;;N;;;;; +2F994;CJK COMPATIBILITY IDEOGRAPH-2F994;Lo;0;L;82B3;;;;N;;;;; +2F995;CJK COMPATIBILITY IDEOGRAPH-2F995;Lo;0;L;82BD;;;;N;;;;; +2F996;CJK COMPATIBILITY IDEOGRAPH-2F996;Lo;0;L;82E6;;;;N;;;;; +2F997;CJK COMPATIBILITY IDEOGRAPH-2F997;Lo;0;L;26B3C;;;;N;;;;; +2F998;CJK COMPATIBILITY IDEOGRAPH-2F998;Lo;0;L;82E5;;;;N;;;;; +2F999;CJK COMPATIBILITY IDEOGRAPH-2F999;Lo;0;L;831D;;;;N;;;;; +2F99A;CJK COMPATIBILITY IDEOGRAPH-2F99A;Lo;0;L;8363;;;;N;;;;; +2F99B;CJK COMPATIBILITY IDEOGRAPH-2F99B;Lo;0;L;83AD;;;;N;;;;; +2F99C;CJK COMPATIBILITY IDEOGRAPH-2F99C;Lo;0;L;8323;;;;N;;;;; +2F99D;CJK COMPATIBILITY IDEOGRAPH-2F99D;Lo;0;L;83BD;;;;N;;;;; +2F99E;CJK COMPATIBILITY IDEOGRAPH-2F99E;Lo;0;L;83E7;;;;N;;;;; +2F99F;CJK COMPATIBILITY IDEOGRAPH-2F99F;Lo;0;L;8457;;;;N;;;;; +2F9A0;CJK COMPATIBILITY IDEOGRAPH-2F9A0;Lo;0;L;8353;;;;N;;;;; +2F9A1;CJK COMPATIBILITY IDEOGRAPH-2F9A1;Lo;0;L;83CA;;;;N;;;;; +2F9A2;CJK COMPATIBILITY IDEOGRAPH-2F9A2;Lo;0;L;83CC;;;;N;;;;; +2F9A3;CJK COMPATIBILITY IDEOGRAPH-2F9A3;Lo;0;L;83DC;;;;N;;;;; +2F9A4;CJK COMPATIBILITY IDEOGRAPH-2F9A4;Lo;0;L;26C36;;;;N;;;;; +2F9A5;CJK COMPATIBILITY IDEOGRAPH-2F9A5;Lo;0;L;26D6B;;;;N;;;;; +2F9A6;CJK COMPATIBILITY IDEOGRAPH-2F9A6;Lo;0;L;26CD5;;;;N;;;;; +2F9A7;CJK COMPATIBILITY IDEOGRAPH-2F9A7;Lo;0;L;452B;;;;N;;;;; +2F9A8;CJK COMPATIBILITY IDEOGRAPH-2F9A8;Lo;0;L;84F1;;;;N;;;;; +2F9A9;CJK COMPATIBILITY IDEOGRAPH-2F9A9;Lo;0;L;84F3;;;;N;;;;; +2F9AA;CJK COMPATIBILITY IDEOGRAPH-2F9AA;Lo;0;L;8516;;;;N;;;;; +2F9AB;CJK COMPATIBILITY IDEOGRAPH-2F9AB;Lo;0;L;273CA;;;;N;;;;; +2F9AC;CJK COMPATIBILITY IDEOGRAPH-2F9AC;Lo;0;L;8564;;;;N;;;;; +2F9AD;CJK COMPATIBILITY IDEOGRAPH-2F9AD;Lo;0;L;26F2C;;;;N;;;;; +2F9AE;CJK COMPATIBILITY IDEOGRAPH-2F9AE;Lo;0;L;455D;;;;N;;;;; +2F9AF;CJK COMPATIBILITY IDEOGRAPH-2F9AF;Lo;0;L;4561;;;;N;;;;; +2F9B0;CJK COMPATIBILITY IDEOGRAPH-2F9B0;Lo;0;L;26FB1;;;;N;;;;; +2F9B1;CJK COMPATIBILITY IDEOGRAPH-2F9B1;Lo;0;L;270D2;;;;N;;;;; +2F9B2;CJK COMPATIBILITY IDEOGRAPH-2F9B2;Lo;0;L;456B;;;;N;;;;; +2F9B3;CJK COMPATIBILITY IDEOGRAPH-2F9B3;Lo;0;L;8650;;;;N;;;;; +2F9B4;CJK COMPATIBILITY IDEOGRAPH-2F9B4;Lo;0;L;865C;;;;N;;;;; +2F9B5;CJK COMPATIBILITY IDEOGRAPH-2F9B5;Lo;0;L;8667;;;;N;;;;; +2F9B6;CJK COMPATIBILITY IDEOGRAPH-2F9B6;Lo;0;L;8669;;;;N;;;;; +2F9B7;CJK COMPATIBILITY IDEOGRAPH-2F9B7;Lo;0;L;86A9;;;;N;;;;; +2F9B8;CJK COMPATIBILITY IDEOGRAPH-2F9B8;Lo;0;L;8688;;;;N;;;;; +2F9B9;CJK COMPATIBILITY IDEOGRAPH-2F9B9;Lo;0;L;870E;;;;N;;;;; +2F9BA;CJK COMPATIBILITY IDEOGRAPH-2F9BA;Lo;0;L;86E2;;;;N;;;;; +2F9BB;CJK COMPATIBILITY IDEOGRAPH-2F9BB;Lo;0;L;8779;;;;N;;;;; +2F9BC;CJK COMPATIBILITY IDEOGRAPH-2F9BC;Lo;0;L;8728;;;;N;;;;; +2F9BD;CJK COMPATIBILITY IDEOGRAPH-2F9BD;Lo;0;L;876B;;;;N;;;;; +2F9BE;CJK COMPATIBILITY IDEOGRAPH-2F9BE;Lo;0;L;8786;;;;N;;;;; +2F9BF;CJK COMPATIBILITY IDEOGRAPH-2F9BF;Lo;0;L;45D7;;;;N;;;;; +2F9C0;CJK COMPATIBILITY IDEOGRAPH-2F9C0;Lo;0;L;87E1;;;;N;;;;; +2F9C1;CJK COMPATIBILITY IDEOGRAPH-2F9C1;Lo;0;L;8801;;;;N;;;;; +2F9C2;CJK COMPATIBILITY IDEOGRAPH-2F9C2;Lo;0;L;45F9;;;;N;;;;; +2F9C3;CJK COMPATIBILITY IDEOGRAPH-2F9C3;Lo;0;L;8860;;;;N;;;;; +2F9C4;CJK COMPATIBILITY IDEOGRAPH-2F9C4;Lo;0;L;8863;;;;N;;;;; +2F9C5;CJK COMPATIBILITY IDEOGRAPH-2F9C5;Lo;0;L;27667;;;;N;;;;; +2F9C6;CJK COMPATIBILITY IDEOGRAPH-2F9C6;Lo;0;L;88D7;;;;N;;;;; +2F9C7;CJK COMPATIBILITY IDEOGRAPH-2F9C7;Lo;0;L;88DE;;;;N;;;;; +2F9C8;CJK COMPATIBILITY IDEOGRAPH-2F9C8;Lo;0;L;4635;;;;N;;;;; +2F9C9;CJK COMPATIBILITY IDEOGRAPH-2F9C9;Lo;0;L;88FA;;;;N;;;;; +2F9CA;CJK COMPATIBILITY IDEOGRAPH-2F9CA;Lo;0;L;34BB;;;;N;;;;; +2F9CB;CJK COMPATIBILITY IDEOGRAPH-2F9CB;Lo;0;L;278AE;;;;N;;;;; +2F9CC;CJK COMPATIBILITY IDEOGRAPH-2F9CC;Lo;0;L;27966;;;;N;;;;; +2F9CD;CJK COMPATIBILITY IDEOGRAPH-2F9CD;Lo;0;L;46BE;;;;N;;;;; +2F9CE;CJK COMPATIBILITY IDEOGRAPH-2F9CE;Lo;0;L;46C7;;;;N;;;;; +2F9CF;CJK COMPATIBILITY IDEOGRAPH-2F9CF;Lo;0;L;8AA0;;;;N;;;;; +2F9D0;CJK COMPATIBILITY IDEOGRAPH-2F9D0;Lo;0;L;8AED;;;;N;;;;; +2F9D1;CJK COMPATIBILITY IDEOGRAPH-2F9D1;Lo;0;L;8B8A;;;;N;;;;; +2F9D2;CJK COMPATIBILITY IDEOGRAPH-2F9D2;Lo;0;L;8C55;;;;N;;;;; +2F9D3;CJK COMPATIBILITY IDEOGRAPH-2F9D3;Lo;0;L;27CA8;;;;N;;;;; +2F9D4;CJK COMPATIBILITY IDEOGRAPH-2F9D4;Lo;0;L;8CAB;;;;N;;;;; +2F9D5;CJK COMPATIBILITY IDEOGRAPH-2F9D5;Lo;0;L;8CC1;;;;N;;;;; +2F9D6;CJK COMPATIBILITY IDEOGRAPH-2F9D6;Lo;0;L;8D1B;;;;N;;;;; +2F9D7;CJK COMPATIBILITY IDEOGRAPH-2F9D7;Lo;0;L;8D77;;;;N;;;;; +2F9D8;CJK COMPATIBILITY IDEOGRAPH-2F9D8;Lo;0;L;27F2F;;;;N;;;;; +2F9D9;CJK COMPATIBILITY IDEOGRAPH-2F9D9;Lo;0;L;20804;;;;N;;;;; +2F9DA;CJK COMPATIBILITY IDEOGRAPH-2F9DA;Lo;0;L;8DCB;;;;N;;;;; +2F9DB;CJK COMPATIBILITY IDEOGRAPH-2F9DB;Lo;0;L;8DBC;;;;N;;;;; +2F9DC;CJK COMPATIBILITY IDEOGRAPH-2F9DC;Lo;0;L;8DF0;;;;N;;;;; +2F9DD;CJK COMPATIBILITY IDEOGRAPH-2F9DD;Lo;0;L;208DE;;;;N;;;;; +2F9DE;CJK COMPATIBILITY IDEOGRAPH-2F9DE;Lo;0;L;8ED4;;;;N;;;;; +2F9DF;CJK COMPATIBILITY IDEOGRAPH-2F9DF;Lo;0;L;8F38;;;;N;;;;; +2F9E0;CJK COMPATIBILITY IDEOGRAPH-2F9E0;Lo;0;L;285D2;;;;N;;;;; +2F9E1;CJK COMPATIBILITY IDEOGRAPH-2F9E1;Lo;0;L;285ED;;;;N;;;;; +2F9E2;CJK COMPATIBILITY IDEOGRAPH-2F9E2;Lo;0;L;9094;;;;N;;;;; +2F9E3;CJK COMPATIBILITY IDEOGRAPH-2F9E3;Lo;0;L;90F1;;;;N;;;;; +2F9E4;CJK COMPATIBILITY IDEOGRAPH-2F9E4;Lo;0;L;9111;;;;N;;;;; +2F9E5;CJK COMPATIBILITY IDEOGRAPH-2F9E5;Lo;0;L;2872E;;;;N;;;;; +2F9E6;CJK COMPATIBILITY IDEOGRAPH-2F9E6;Lo;0;L;911B;;;;N;;;;; +2F9E7;CJK COMPATIBILITY IDEOGRAPH-2F9E7;Lo;0;L;9238;;;;N;;;;; +2F9E8;CJK COMPATIBILITY IDEOGRAPH-2F9E8;Lo;0;L;92D7;;;;N;;;;; +2F9E9;CJK COMPATIBILITY IDEOGRAPH-2F9E9;Lo;0;L;92D8;;;;N;;;;; +2F9EA;CJK COMPATIBILITY IDEOGRAPH-2F9EA;Lo;0;L;927C;;;;N;;;;; +2F9EB;CJK COMPATIBILITY IDEOGRAPH-2F9EB;Lo;0;L;93F9;;;;N;;;;; +2F9EC;CJK COMPATIBILITY IDEOGRAPH-2F9EC;Lo;0;L;9415;;;;N;;;;; +2F9ED;CJK COMPATIBILITY IDEOGRAPH-2F9ED;Lo;0;L;28BFA;;;;N;;;;; +2F9EE;CJK COMPATIBILITY IDEOGRAPH-2F9EE;Lo;0;L;958B;;;;N;;;;; +2F9EF;CJK COMPATIBILITY IDEOGRAPH-2F9EF;Lo;0;L;4995;;;;N;;;;; +2F9F0;CJK COMPATIBILITY IDEOGRAPH-2F9F0;Lo;0;L;95B7;;;;N;;;;; +2F9F1;CJK COMPATIBILITY IDEOGRAPH-2F9F1;Lo;0;L;28D77;;;;N;;;;; +2F9F2;CJK COMPATIBILITY IDEOGRAPH-2F9F2;Lo;0;L;49E6;;;;N;;;;; +2F9F3;CJK COMPATIBILITY IDEOGRAPH-2F9F3;Lo;0;L;96C3;;;;N;;;;; +2F9F4;CJK COMPATIBILITY IDEOGRAPH-2F9F4;Lo;0;L;5DB2;;;;N;;;;; +2F9F5;CJK COMPATIBILITY IDEOGRAPH-2F9F5;Lo;0;L;9723;;;;N;;;;; +2F9F6;CJK COMPATIBILITY IDEOGRAPH-2F9F6;Lo;0;L;29145;;;;N;;;;; +2F9F7;CJK COMPATIBILITY IDEOGRAPH-2F9F7;Lo;0;L;2921A;;;;N;;;;; +2F9F8;CJK COMPATIBILITY IDEOGRAPH-2F9F8;Lo;0;L;4A6E;;;;N;;;;; +2F9F9;CJK COMPATIBILITY IDEOGRAPH-2F9F9;Lo;0;L;4A76;;;;N;;;;; +2F9FA;CJK COMPATIBILITY IDEOGRAPH-2F9FA;Lo;0;L;97E0;;;;N;;;;; +2F9FB;CJK COMPATIBILITY IDEOGRAPH-2F9FB;Lo;0;L;2940A;;;;N;;;;; +2F9FC;CJK COMPATIBILITY IDEOGRAPH-2F9FC;Lo;0;L;4AB2;;;;N;;;;; +2F9FD;CJK COMPATIBILITY IDEOGRAPH-2F9FD;Lo;0;L;29496;;;;N;;;;; +2F9FE;CJK COMPATIBILITY IDEOGRAPH-2F9FE;Lo;0;L;980B;;;;N;;;;; +2F9FF;CJK COMPATIBILITY IDEOGRAPH-2F9FF;Lo;0;L;980B;;;;N;;;;; +2FA00;CJK COMPATIBILITY IDEOGRAPH-2FA00;Lo;0;L;9829;;;;N;;;;; +2FA01;CJK COMPATIBILITY IDEOGRAPH-2FA01;Lo;0;L;295B6;;;;N;;;;; +2FA02;CJK COMPATIBILITY IDEOGRAPH-2FA02;Lo;0;L;98E2;;;;N;;;;; +2FA03;CJK COMPATIBILITY IDEOGRAPH-2FA03;Lo;0;L;4B33;;;;N;;;;; +2FA04;CJK COMPATIBILITY IDEOGRAPH-2FA04;Lo;0;L;9929;;;;N;;;;; +2FA05;CJK COMPATIBILITY IDEOGRAPH-2FA05;Lo;0;L;99A7;;;;N;;;;; +2FA06;CJK COMPATIBILITY IDEOGRAPH-2FA06;Lo;0;L;99C2;;;;N;;;;; +2FA07;CJK COMPATIBILITY IDEOGRAPH-2FA07;Lo;0;L;99FE;;;;N;;;;; +2FA08;CJK COMPATIBILITY IDEOGRAPH-2FA08;Lo;0;L;4BCE;;;;N;;;;; +2FA09;CJK COMPATIBILITY IDEOGRAPH-2FA09;Lo;0;L;29B30;;;;N;;;;; +2FA0A;CJK COMPATIBILITY IDEOGRAPH-2FA0A;Lo;0;L;9B12;;;;N;;;;; +2FA0B;CJK COMPATIBILITY IDEOGRAPH-2FA0B;Lo;0;L;9C40;;;;N;;;;; +2FA0C;CJK COMPATIBILITY IDEOGRAPH-2FA0C;Lo;0;L;9CFD;;;;N;;;;; +2FA0D;CJK COMPATIBILITY IDEOGRAPH-2FA0D;Lo;0;L;4CCE;;;;N;;;;; +2FA0E;CJK COMPATIBILITY IDEOGRAPH-2FA0E;Lo;0;L;4CED;;;;N;;;;; +2FA0F;CJK COMPATIBILITY IDEOGRAPH-2FA0F;Lo;0;L;9D67;;;;N;;;;; +2FA10;CJK COMPATIBILITY IDEOGRAPH-2FA10;Lo;0;L;2A0CE;;;;N;;;;; +2FA11;CJK COMPATIBILITY IDEOGRAPH-2FA11;Lo;0;L;4CF8;;;;N;;;;; +2FA12;CJK COMPATIBILITY IDEOGRAPH-2FA12;Lo;0;L;2A105;;;;N;;;;; +2FA13;CJK COMPATIBILITY IDEOGRAPH-2FA13;Lo;0;L;2A20E;;;;N;;;;; +2FA14;CJK COMPATIBILITY IDEOGRAPH-2FA14;Lo;0;L;2A291;;;;N;;;;; +2FA15;CJK COMPATIBILITY IDEOGRAPH-2FA15;Lo;0;L;9EBB;;;;N;;;;; +2FA16;CJK COMPATIBILITY IDEOGRAPH-2FA16;Lo;0;L;4D56;;;;N;;;;; +2FA17;CJK COMPATIBILITY IDEOGRAPH-2FA17;Lo;0;L;9EF9;;;;N;;;;; +2FA18;CJK COMPATIBILITY IDEOGRAPH-2FA18;Lo;0;L;9EFE;;;;N;;;;; +2FA19;CJK COMPATIBILITY IDEOGRAPH-2FA19;Lo;0;L;9F05;;;;N;;;;; +2FA1A;CJK COMPATIBILITY IDEOGRAPH-2FA1A;Lo;0;L;9F0F;;;;N;;;;; +2FA1B;CJK COMPATIBILITY IDEOGRAPH-2FA1B;Lo;0;L;9F16;;;;N;;;;; +2FA1C;CJK COMPATIBILITY IDEOGRAPH-2FA1C;Lo;0;L;9F3B;;;;N;;;;; +2FA1D;CJK COMPATIBILITY IDEOGRAPH-2FA1D;Lo;0;L;2A600;;;;N;;;;; +E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;; +E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;; +E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;; +E0022;TAG QUOTATION MARK;Cf;0;BN;;;;;N;;;;; +E0023;TAG NUMBER SIGN;Cf;0;BN;;;;;N;;;;; +E0024;TAG DOLLAR SIGN;Cf;0;BN;;;;;N;;;;; +E0025;TAG PERCENT SIGN;Cf;0;BN;;;;;N;;;;; +E0026;TAG AMPERSAND;Cf;0;BN;;;;;N;;;;; +E0027;TAG APOSTROPHE;Cf;0;BN;;;;;N;;;;; +E0028;TAG LEFT PARENTHESIS;Cf;0;BN;;;;;N;;;;; +E0029;TAG RIGHT PARENTHESIS;Cf;0;BN;;;;;N;;;;; +E002A;TAG ASTERISK;Cf;0;BN;;;;;N;;;;; +E002B;TAG PLUS SIGN;Cf;0;BN;;;;;N;;;;; +E002C;TAG COMMA;Cf;0;BN;;;;;N;;;;; +E002D;TAG HYPHEN-MINUS;Cf;0;BN;;;;;N;;;;; +E002E;TAG FULL STOP;Cf;0;BN;;;;;N;;;;; +E002F;TAG SOLIDUS;Cf;0;BN;;;;;N;;;;; +E0030;TAG DIGIT ZERO;Cf;0;BN;;;;;N;;;;; +E0031;TAG DIGIT ONE;Cf;0;BN;;;;;N;;;;; +E0032;TAG DIGIT TWO;Cf;0;BN;;;;;N;;;;; +E0033;TAG DIGIT THREE;Cf;0;BN;;;;;N;;;;; +E0034;TAG DIGIT FOUR;Cf;0;BN;;;;;N;;;;; +E0035;TAG DIGIT FIVE;Cf;0;BN;;;;;N;;;;; +E0036;TAG DIGIT SIX;Cf;0;BN;;;;;N;;;;; +E0037;TAG DIGIT SEVEN;Cf;0;BN;;;;;N;;;;; +E0038;TAG DIGIT EIGHT;Cf;0;BN;;;;;N;;;;; +E0039;TAG DIGIT NINE;Cf;0;BN;;;;;N;;;;; +E003A;TAG COLON;Cf;0;BN;;;;;N;;;;; +E003B;TAG SEMICOLON;Cf;0;BN;;;;;N;;;;; +E003C;TAG LESS-THAN SIGN;Cf;0;BN;;;;;N;;;;; +E003D;TAG EQUALS SIGN;Cf;0;BN;;;;;N;;;;; +E003E;TAG GREATER-THAN SIGN;Cf;0;BN;;;;;N;;;;; +E003F;TAG QUESTION MARK;Cf;0;BN;;;;;N;;;;; +E0040;TAG COMMERCIAL AT;Cf;0;BN;;;;;N;;;;; +E0041;TAG LATIN CAPITAL LETTER A;Cf;0;BN;;;;;N;;;;; +E0042;TAG LATIN CAPITAL LETTER B;Cf;0;BN;;;;;N;;;;; +E0043;TAG LATIN CAPITAL LETTER C;Cf;0;BN;;;;;N;;;;; +E0044;TAG LATIN CAPITAL LETTER D;Cf;0;BN;;;;;N;;;;; +E0045;TAG LATIN CAPITAL LETTER E;Cf;0;BN;;;;;N;;;;; +E0046;TAG LATIN CAPITAL LETTER F;Cf;0;BN;;;;;N;;;;; +E0047;TAG LATIN CAPITAL LETTER G;Cf;0;BN;;;;;N;;;;; +E0048;TAG LATIN CAPITAL LETTER H;Cf;0;BN;;;;;N;;;;; +E0049;TAG LATIN CAPITAL LETTER I;Cf;0;BN;;;;;N;;;;; +E004A;TAG LATIN CAPITAL LETTER J;Cf;0;BN;;;;;N;;;;; +E004B;TAG LATIN CAPITAL LETTER K;Cf;0;BN;;;;;N;;;;; +E004C;TAG LATIN CAPITAL LETTER L;Cf;0;BN;;;;;N;;;;; +E004D;TAG LATIN CAPITAL LETTER M;Cf;0;BN;;;;;N;;;;; +E004E;TAG LATIN CAPITAL LETTER N;Cf;0;BN;;;;;N;;;;; +E004F;TAG LATIN CAPITAL LETTER O;Cf;0;BN;;;;;N;;;;; +E0050;TAG LATIN CAPITAL LETTER P;Cf;0;BN;;;;;N;;;;; +E0051;TAG LATIN CAPITAL LETTER Q;Cf;0;BN;;;;;N;;;;; +E0052;TAG LATIN CAPITAL LETTER R;Cf;0;BN;;;;;N;;;;; +E0053;TAG LATIN CAPITAL LETTER S;Cf;0;BN;;;;;N;;;;; +E0054;TAG LATIN CAPITAL LETTER T;Cf;0;BN;;;;;N;;;;; +E0055;TAG LATIN CAPITAL LETTER U;Cf;0;BN;;;;;N;;;;; +E0056;TAG LATIN CAPITAL LETTER V;Cf;0;BN;;;;;N;;;;; +E0057;TAG LATIN CAPITAL LETTER W;Cf;0;BN;;;;;N;;;;; +E0058;TAG LATIN CAPITAL LETTER X;Cf;0;BN;;;;;N;;;;; +E0059;TAG LATIN CAPITAL LETTER Y;Cf;0;BN;;;;;N;;;;; +E005A;TAG LATIN CAPITAL LETTER Z;Cf;0;BN;;;;;N;;;;; +E005B;TAG LEFT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; +E005C;TAG REVERSE SOLIDUS;Cf;0;BN;;;;;N;;;;; +E005D;TAG RIGHT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; +E005E;TAG CIRCUMFLEX ACCENT;Cf;0;BN;;;;;N;;;;; +E005F;TAG LOW LINE;Cf;0;BN;;;;;N;;;;; +E0060;TAG GRAVE ACCENT;Cf;0;BN;;;;;N;;;;; +E0061;TAG LATIN SMALL LETTER A;Cf;0;BN;;;;;N;;;;; +E0062;TAG LATIN SMALL LETTER B;Cf;0;BN;;;;;N;;;;; +E0063;TAG LATIN SMALL LETTER C;Cf;0;BN;;;;;N;;;;; +E0064;TAG LATIN SMALL LETTER D;Cf;0;BN;;;;;N;;;;; +E0065;TAG LATIN SMALL LETTER E;Cf;0;BN;;;;;N;;;;; +E0066;TAG LATIN SMALL LETTER F;Cf;0;BN;;;;;N;;;;; +E0067;TAG LATIN SMALL LETTER G;Cf;0;BN;;;;;N;;;;; +E0068;TAG LATIN SMALL LETTER H;Cf;0;BN;;;;;N;;;;; +E0069;TAG LATIN SMALL LETTER I;Cf;0;BN;;;;;N;;;;; +E006A;TAG LATIN SMALL LETTER J;Cf;0;BN;;;;;N;;;;; +E006B;TAG LATIN SMALL LETTER K;Cf;0;BN;;;;;N;;;;; +E006C;TAG LATIN SMALL LETTER L;Cf;0;BN;;;;;N;;;;; +E006D;TAG LATIN SMALL LETTER M;Cf;0;BN;;;;;N;;;;; +E006E;TAG LATIN SMALL LETTER N;Cf;0;BN;;;;;N;;;;; +E006F;TAG LATIN SMALL LETTER O;Cf;0;BN;;;;;N;;;;; +E0070;TAG LATIN SMALL LETTER P;Cf;0;BN;;;;;N;;;;; +E0071;TAG LATIN SMALL LETTER Q;Cf;0;BN;;;;;N;;;;; +E0072;TAG LATIN SMALL LETTER R;Cf;0;BN;;;;;N;;;;; +E0073;TAG LATIN SMALL LETTER S;Cf;0;BN;;;;;N;;;;; +E0074;TAG LATIN SMALL LETTER T;Cf;0;BN;;;;;N;;;;; +E0075;TAG LATIN SMALL LETTER U;Cf;0;BN;;;;;N;;;;; +E0076;TAG LATIN SMALL LETTER V;Cf;0;BN;;;;;N;;;;; +E0077;TAG LATIN SMALL LETTER W;Cf;0;BN;;;;;N;;;;; +E0078;TAG LATIN SMALL LETTER X;Cf;0;BN;;;;;N;;;;; +E0079;TAG LATIN SMALL LETTER Y;Cf;0;BN;;;;;N;;;;; +E007A;TAG LATIN SMALL LETTER Z;Cf;0;BN;;;;;N;;;;; +E007B;TAG LEFT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; +E007C;TAG VERTICAL LINE;Cf;0;BN;;;;;N;;;;; +E007D;TAG RIGHT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; +E007E;TAG TILDE;Cf;0;BN;;;;;N;;;;; +E007F;CANCEL TAG;Cf;0;BN;;;;;N;;;;; +E0100;VARIATION SELECTOR-17;Mn;0;NSM;;;;;N;;;;; +E0101;VARIATION SELECTOR-18;Mn;0;NSM;;;;;N;;;;; +E0102;VARIATION SELECTOR-19;Mn;0;NSM;;;;;N;;;;; +E0103;VARIATION SELECTOR-20;Mn;0;NSM;;;;;N;;;;; +E0104;VARIATION SELECTOR-21;Mn;0;NSM;;;;;N;;;;; +E0105;VARIATION SELECTOR-22;Mn;0;NSM;;;;;N;;;;; +E0106;VARIATION SELECTOR-23;Mn;0;NSM;;;;;N;;;;; +E0107;VARIATION SELECTOR-24;Mn;0;NSM;;;;;N;;;;; +E0108;VARIATION SELECTOR-25;Mn;0;NSM;;;;;N;;;;; +E0109;VARIATION SELECTOR-26;Mn;0;NSM;;;;;N;;;;; +E010A;VARIATION SELECTOR-27;Mn;0;NSM;;;;;N;;;;; +E010B;VARIATION SELECTOR-28;Mn;0;NSM;;;;;N;;;;; +E010C;VARIATION SELECTOR-29;Mn;0;NSM;;;;;N;;;;; +E010D;VARIATION SELECTOR-30;Mn;0;NSM;;;;;N;;;;; +E010E;VARIATION SELECTOR-31;Mn;0;NSM;;;;;N;;;;; +E010F;VARIATION SELECTOR-32;Mn;0;NSM;;;;;N;;;;; +E0110;VARIATION SELECTOR-33;Mn;0;NSM;;;;;N;;;;; +E0111;VARIATION SELECTOR-34;Mn;0;NSM;;;;;N;;;;; +E0112;VARIATION SELECTOR-35;Mn;0;NSM;;;;;N;;;;; +E0113;VARIATION SELECTOR-36;Mn;0;NSM;;;;;N;;;;; +E0114;VARIATION SELECTOR-37;Mn;0;NSM;;;;;N;;;;; +E0115;VARIATION SELECTOR-38;Mn;0;NSM;;;;;N;;;;; +E0116;VARIATION SELECTOR-39;Mn;0;NSM;;;;;N;;;;; +E0117;VARIATION SELECTOR-40;Mn;0;NSM;;;;;N;;;;; +E0118;VARIATION SELECTOR-41;Mn;0;NSM;;;;;N;;;;; +E0119;VARIATION SELECTOR-42;Mn;0;NSM;;;;;N;;;;; +E011A;VARIATION SELECTOR-43;Mn;0;NSM;;;;;N;;;;; +E011B;VARIATION SELECTOR-44;Mn;0;NSM;;;;;N;;;;; +E011C;VARIATION SELECTOR-45;Mn;0;NSM;;;;;N;;;;; +E011D;VARIATION SELECTOR-46;Mn;0;NSM;;;;;N;;;;; +E011E;VARIATION SELECTOR-47;Mn;0;NSM;;;;;N;;;;; +E011F;VARIATION SELECTOR-48;Mn;0;NSM;;;;;N;;;;; +E0120;VARIATION SELECTOR-49;Mn;0;NSM;;;;;N;;;;; +E0121;VARIATION SELECTOR-50;Mn;0;NSM;;;;;N;;;;; +E0122;VARIATION SELECTOR-51;Mn;0;NSM;;;;;N;;;;; +E0123;VARIATION SELECTOR-52;Mn;0;NSM;;;;;N;;;;; +E0124;VARIATION SELECTOR-53;Mn;0;NSM;;;;;N;;;;; +E0125;VARIATION SELECTOR-54;Mn;0;NSM;;;;;N;;;;; +E0126;VARIATION SELECTOR-55;Mn;0;NSM;;;;;N;;;;; +E0127;VARIATION SELECTOR-56;Mn;0;NSM;;;;;N;;;;; +E0128;VARIATION SELECTOR-57;Mn;0;NSM;;;;;N;;;;; +E0129;VARIATION SELECTOR-58;Mn;0;NSM;;;;;N;;;;; +E012A;VARIATION SELECTOR-59;Mn;0;NSM;;;;;N;;;;; +E012B;VARIATION SELECTOR-60;Mn;0;NSM;;;;;N;;;;; +E012C;VARIATION SELECTOR-61;Mn;0;NSM;;;;;N;;;;; +E012D;VARIATION SELECTOR-62;Mn;0;NSM;;;;;N;;;;; +E012E;VARIATION SELECTOR-63;Mn;0;NSM;;;;;N;;;;; +E012F;VARIATION SELECTOR-64;Mn;0;NSM;;;;;N;;;;; +E0130;VARIATION SELECTOR-65;Mn;0;NSM;;;;;N;;;;; +E0131;VARIATION SELECTOR-66;Mn;0;NSM;;;;;N;;;;; +E0132;VARIATION SELECTOR-67;Mn;0;NSM;;;;;N;;;;; +E0133;VARIATION SELECTOR-68;Mn;0;NSM;;;;;N;;;;; +E0134;VARIATION SELECTOR-69;Mn;0;NSM;;;;;N;;;;; +E0135;VARIATION SELECTOR-70;Mn;0;NSM;;;;;N;;;;; +E0136;VARIATION SELECTOR-71;Mn;0;NSM;;;;;N;;;;; +E0137;VARIATION SELECTOR-72;Mn;0;NSM;;;;;N;;;;; +E0138;VARIATION SELECTOR-73;Mn;0;NSM;;;;;N;;;;; +E0139;VARIATION SELECTOR-74;Mn;0;NSM;;;;;N;;;;; +E013A;VARIATION SELECTOR-75;Mn;0;NSM;;;;;N;;;;; +E013B;VARIATION SELECTOR-76;Mn;0;NSM;;;;;N;;;;; +E013C;VARIATION SELECTOR-77;Mn;0;NSM;;;;;N;;;;; +E013D;VARIATION SELECTOR-78;Mn;0;NSM;;;;;N;;;;; +E013E;VARIATION SELECTOR-79;Mn;0;NSM;;;;;N;;;;; +E013F;VARIATION SELECTOR-80;Mn;0;NSM;;;;;N;;;;; +E0140;VARIATION SELECTOR-81;Mn;0;NSM;;;;;N;;;;; +E0141;VARIATION SELECTOR-82;Mn;0;NSM;;;;;N;;;;; +E0142;VARIATION SELECTOR-83;Mn;0;NSM;;;;;N;;;;; +E0143;VARIATION SELECTOR-84;Mn;0;NSM;;;;;N;;;;; +E0144;VARIATION SELECTOR-85;Mn;0;NSM;;;;;N;;;;; +E0145;VARIATION SELECTOR-86;Mn;0;NSM;;;;;N;;;;; +E0146;VARIATION SELECTOR-87;Mn;0;NSM;;;;;N;;;;; +E0147;VARIATION SELECTOR-88;Mn;0;NSM;;;;;N;;;;; +E0148;VARIATION SELECTOR-89;Mn;0;NSM;;;;;N;;;;; +E0149;VARIATION SELECTOR-90;Mn;0;NSM;;;;;N;;;;; +E014A;VARIATION SELECTOR-91;Mn;0;NSM;;;;;N;;;;; +E014B;VARIATION SELECTOR-92;Mn;0;NSM;;;;;N;;;;; +E014C;VARIATION SELECTOR-93;Mn;0;NSM;;;;;N;;;;; +E014D;VARIATION SELECTOR-94;Mn;0;NSM;;;;;N;;;;; +E014E;VARIATION SELECTOR-95;Mn;0;NSM;;;;;N;;;;; +E014F;VARIATION SELECTOR-96;Mn;0;NSM;;;;;N;;;;; +E0150;VARIATION SELECTOR-97;Mn;0;NSM;;;;;N;;;;; +E0151;VARIATION SELECTOR-98;Mn;0;NSM;;;;;N;;;;; +E0152;VARIATION SELECTOR-99;Mn;0;NSM;;;;;N;;;;; +E0153;VARIATION SELECTOR-100;Mn;0;NSM;;;;;N;;;;; +E0154;VARIATION SELECTOR-101;Mn;0;NSM;;;;;N;;;;; +E0155;VARIATION SELECTOR-102;Mn;0;NSM;;;;;N;;;;; +E0156;VARIATION SELECTOR-103;Mn;0;NSM;;;;;N;;;;; +E0157;VARIATION SELECTOR-104;Mn;0;NSM;;;;;N;;;;; +E0158;VARIATION SELECTOR-105;Mn;0;NSM;;;;;N;;;;; +E0159;VARIATION SELECTOR-106;Mn;0;NSM;;;;;N;;;;; +E015A;VARIATION SELECTOR-107;Mn;0;NSM;;;;;N;;;;; +E015B;VARIATION SELECTOR-108;Mn;0;NSM;;;;;N;;;;; +E015C;VARIATION SELECTOR-109;Mn;0;NSM;;;;;N;;;;; +E015D;VARIATION SELECTOR-110;Mn;0;NSM;;;;;N;;;;; +E015E;VARIATION SELECTOR-111;Mn;0;NSM;;;;;N;;;;; +E015F;VARIATION SELECTOR-112;Mn;0;NSM;;;;;N;;;;; +E0160;VARIATION SELECTOR-113;Mn;0;NSM;;;;;N;;;;; +E0161;VARIATION SELECTOR-114;Mn;0;NSM;;;;;N;;;;; +E0162;VARIATION SELECTOR-115;Mn;0;NSM;;;;;N;;;;; +E0163;VARIATION SELECTOR-116;Mn;0;NSM;;;;;N;;;;; +E0164;VARIATION SELECTOR-117;Mn;0;NSM;;;;;N;;;;; +E0165;VARIATION SELECTOR-118;Mn;0;NSM;;;;;N;;;;; +E0166;VARIATION SELECTOR-119;Mn;0;NSM;;;;;N;;;;; +E0167;VARIATION SELECTOR-120;Mn;0;NSM;;;;;N;;;;; +E0168;VARIATION SELECTOR-121;Mn;0;NSM;;;;;N;;;;; +E0169;VARIATION SELECTOR-122;Mn;0;NSM;;;;;N;;;;; +E016A;VARIATION SELECTOR-123;Mn;0;NSM;;;;;N;;;;; +E016B;VARIATION SELECTOR-124;Mn;0;NSM;;;;;N;;;;; +E016C;VARIATION SELECTOR-125;Mn;0;NSM;;;;;N;;;;; +E016D;VARIATION SELECTOR-126;Mn;0;NSM;;;;;N;;;;; +E016E;VARIATION SELECTOR-127;Mn;0;NSM;;;;;N;;;;; +E016F;VARIATION SELECTOR-128;Mn;0;NSM;;;;;N;;;;; +E0170;VARIATION SELECTOR-129;Mn;0;NSM;;;;;N;;;;; +E0171;VARIATION SELECTOR-130;Mn;0;NSM;;;;;N;;;;; +E0172;VARIATION SELECTOR-131;Mn;0;NSM;;;;;N;;;;; +E0173;VARIATION SELECTOR-132;Mn;0;NSM;;;;;N;;;;; +E0174;VARIATION SELECTOR-133;Mn;0;NSM;;;;;N;;;;; +E0175;VARIATION SELECTOR-134;Mn;0;NSM;;;;;N;;;;; +E0176;VARIATION SELECTOR-135;Mn;0;NSM;;;;;N;;;;; +E0177;VARIATION SELECTOR-136;Mn;0;NSM;;;;;N;;;;; +E0178;VARIATION SELECTOR-137;Mn;0;NSM;;;;;N;;;;; +E0179;VARIATION SELECTOR-138;Mn;0;NSM;;;;;N;;;;; +E017A;VARIATION SELECTOR-139;Mn;0;NSM;;;;;N;;;;; +E017B;VARIATION SELECTOR-140;Mn;0;NSM;;;;;N;;;;; +E017C;VARIATION SELECTOR-141;Mn;0;NSM;;;;;N;;;;; +E017D;VARIATION SELECTOR-142;Mn;0;NSM;;;;;N;;;;; +E017E;VARIATION SELECTOR-143;Mn;0;NSM;;;;;N;;;;; +E017F;VARIATION SELECTOR-144;Mn;0;NSM;;;;;N;;;;; +E0180;VARIATION SELECTOR-145;Mn;0;NSM;;;;;N;;;;; +E0181;VARIATION SELECTOR-146;Mn;0;NSM;;;;;N;;;;; +E0182;VARIATION SELECTOR-147;Mn;0;NSM;;;;;N;;;;; +E0183;VARIATION SELECTOR-148;Mn;0;NSM;;;;;N;;;;; +E0184;VARIATION SELECTOR-149;Mn;0;NSM;;;;;N;;;;; +E0185;VARIATION SELECTOR-150;Mn;0;NSM;;;;;N;;;;; +E0186;VARIATION SELECTOR-151;Mn;0;NSM;;;;;N;;;;; +E0187;VARIATION SELECTOR-152;Mn;0;NSM;;;;;N;;;;; +E0188;VARIATION SELECTOR-153;Mn;0;NSM;;;;;N;;;;; +E0189;VARIATION SELECTOR-154;Mn;0;NSM;;;;;N;;;;; +E018A;VARIATION SELECTOR-155;Mn;0;NSM;;;;;N;;;;; +E018B;VARIATION SELECTOR-156;Mn;0;NSM;;;;;N;;;;; +E018C;VARIATION SELECTOR-157;Mn;0;NSM;;;;;N;;;;; +E018D;VARIATION SELECTOR-158;Mn;0;NSM;;;;;N;;;;; +E018E;VARIATION SELECTOR-159;Mn;0;NSM;;;;;N;;;;; +E018F;VARIATION SELECTOR-160;Mn;0;NSM;;;;;N;;;;; +E0190;VARIATION SELECTOR-161;Mn;0;NSM;;;;;N;;;;; +E0191;VARIATION SELECTOR-162;Mn;0;NSM;;;;;N;;;;; +E0192;VARIATION SELECTOR-163;Mn;0;NSM;;;;;N;;;;; +E0193;VARIATION SELECTOR-164;Mn;0;NSM;;;;;N;;;;; +E0194;VARIATION SELECTOR-165;Mn;0;NSM;;;;;N;;;;; +E0195;VARIATION SELECTOR-166;Mn;0;NSM;;;;;N;;;;; +E0196;VARIATION SELECTOR-167;Mn;0;NSM;;;;;N;;;;; +E0197;VARIATION SELECTOR-168;Mn;0;NSM;;;;;N;;;;; +E0198;VARIATION SELECTOR-169;Mn;0;NSM;;;;;N;;;;; +E0199;VARIATION SELECTOR-170;Mn;0;NSM;;;;;N;;;;; +E019A;VARIATION SELECTOR-171;Mn;0;NSM;;;;;N;;;;; +E019B;VARIATION SELECTOR-172;Mn;0;NSM;;;;;N;;;;; +E019C;VARIATION SELECTOR-173;Mn;0;NSM;;;;;N;;;;; +E019D;VARIATION SELECTOR-174;Mn;0;NSM;;;;;N;;;;; +E019E;VARIATION SELECTOR-175;Mn;0;NSM;;;;;N;;;;; +E019F;VARIATION SELECTOR-176;Mn;0;NSM;;;;;N;;;;; +E01A0;VARIATION SELECTOR-177;Mn;0;NSM;;;;;N;;;;; +E01A1;VARIATION SELECTOR-178;Mn;0;NSM;;;;;N;;;;; +E01A2;VARIATION SELECTOR-179;Mn;0;NSM;;;;;N;;;;; +E01A3;VARIATION SELECTOR-180;Mn;0;NSM;;;;;N;;;;; +E01A4;VARIATION SELECTOR-181;Mn;0;NSM;;;;;N;;;;; +E01A5;VARIATION SELECTOR-182;Mn;0;NSM;;;;;N;;;;; +E01A6;VARIATION SELECTOR-183;Mn;0;NSM;;;;;N;;;;; +E01A7;VARIATION SELECTOR-184;Mn;0;NSM;;;;;N;;;;; +E01A8;VARIATION SELECTOR-185;Mn;0;NSM;;;;;N;;;;; +E01A9;VARIATION SELECTOR-186;Mn;0;NSM;;;;;N;;;;; +E01AA;VARIATION SELECTOR-187;Mn;0;NSM;;;;;N;;;;; +E01AB;VARIATION SELECTOR-188;Mn;0;NSM;;;;;N;;;;; +E01AC;VARIATION SELECTOR-189;Mn;0;NSM;;;;;N;;;;; +E01AD;VARIATION SELECTOR-190;Mn;0;NSM;;;;;N;;;;; +E01AE;VARIATION SELECTOR-191;Mn;0;NSM;;;;;N;;;;; +E01AF;VARIATION SELECTOR-192;Mn;0;NSM;;;;;N;;;;; +E01B0;VARIATION SELECTOR-193;Mn;0;NSM;;;;;N;;;;; +E01B1;VARIATION SELECTOR-194;Mn;0;NSM;;;;;N;;;;; +E01B2;VARIATION SELECTOR-195;Mn;0;NSM;;;;;N;;;;; +E01B3;VARIATION SELECTOR-196;Mn;0;NSM;;;;;N;;;;; +E01B4;VARIATION SELECTOR-197;Mn;0;NSM;;;;;N;;;;; +E01B5;VARIATION SELECTOR-198;Mn;0;NSM;;;;;N;;;;; +E01B6;VARIATION SELECTOR-199;Mn;0;NSM;;;;;N;;;;; +E01B7;VARIATION SELECTOR-200;Mn;0;NSM;;;;;N;;;;; +E01B8;VARIATION SELECTOR-201;Mn;0;NSM;;;;;N;;;;; +E01B9;VARIATION SELECTOR-202;Mn;0;NSM;;;;;N;;;;; +E01BA;VARIATION SELECTOR-203;Mn;0;NSM;;;;;N;;;;; +E01BB;VARIATION SELECTOR-204;Mn;0;NSM;;;;;N;;;;; +E01BC;VARIATION SELECTOR-205;Mn;0;NSM;;;;;N;;;;; +E01BD;VARIATION SELECTOR-206;Mn;0;NSM;;;;;N;;;;; +E01BE;VARIATION SELECTOR-207;Mn;0;NSM;;;;;N;;;;; +E01BF;VARIATION SELECTOR-208;Mn;0;NSM;;;;;N;;;;; +E01C0;VARIATION SELECTOR-209;Mn;0;NSM;;;;;N;;;;; +E01C1;VARIATION SELECTOR-210;Mn;0;NSM;;;;;N;;;;; +E01C2;VARIATION SELECTOR-211;Mn;0;NSM;;;;;N;;;;; +E01C3;VARIATION SELECTOR-212;Mn;0;NSM;;;;;N;;;;; +E01C4;VARIATION SELECTOR-213;Mn;0;NSM;;;;;N;;;;; +E01C5;VARIATION SELECTOR-214;Mn;0;NSM;;;;;N;;;;; +E01C6;VARIATION SELECTOR-215;Mn;0;NSM;;;;;N;;;;; +E01C7;VARIATION SELECTOR-216;Mn;0;NSM;;;;;N;;;;; +E01C8;VARIATION SELECTOR-217;Mn;0;NSM;;;;;N;;;;; +E01C9;VARIATION SELECTOR-218;Mn;0;NSM;;;;;N;;;;; +E01CA;VARIATION SELECTOR-219;Mn;0;NSM;;;;;N;;;;; +E01CB;VARIATION SELECTOR-220;Mn;0;NSM;;;;;N;;;;; +E01CC;VARIATION SELECTOR-221;Mn;0;NSM;;;;;N;;;;; +E01CD;VARIATION SELECTOR-222;Mn;0;NSM;;;;;N;;;;; +E01CE;VARIATION SELECTOR-223;Mn;0;NSM;;;;;N;;;;; +E01CF;VARIATION SELECTOR-224;Mn;0;NSM;;;;;N;;;;; +E01D0;VARIATION SELECTOR-225;Mn;0;NSM;;;;;N;;;;; +E01D1;VARIATION SELECTOR-226;Mn;0;NSM;;;;;N;;;;; +E01D2;VARIATION SELECTOR-227;Mn;0;NSM;;;;;N;;;;; +E01D3;VARIATION SELECTOR-228;Mn;0;NSM;;;;;N;;;;; +E01D4;VARIATION SELECTOR-229;Mn;0;NSM;;;;;N;;;;; +E01D5;VARIATION SELECTOR-230;Mn;0;NSM;;;;;N;;;;; +E01D6;VARIATION SELECTOR-231;Mn;0;NSM;;;;;N;;;;; +E01D7;VARIATION SELECTOR-232;Mn;0;NSM;;;;;N;;;;; +E01D8;VARIATION SELECTOR-233;Mn;0;NSM;;;;;N;;;;; +E01D9;VARIATION SELECTOR-234;Mn;0;NSM;;;;;N;;;;; +E01DA;VARIATION SELECTOR-235;Mn;0;NSM;;;;;N;;;;; +E01DB;VARIATION SELECTOR-236;Mn;0;NSM;;;;;N;;;;; +E01DC;VARIATION SELECTOR-237;Mn;0;NSM;;;;;N;;;;; +E01DD;VARIATION SELECTOR-238;Mn;0;NSM;;;;;N;;;;; +E01DE;VARIATION SELECTOR-239;Mn;0;NSM;;;;;N;;;;; +E01DF;VARIATION SELECTOR-240;Mn;0;NSM;;;;;N;;;;; +E01E0;VARIATION SELECTOR-241;Mn;0;NSM;;;;;N;;;;; +E01E1;VARIATION SELECTOR-242;Mn;0;NSM;;;;;N;;;;; +E01E2;VARIATION SELECTOR-243;Mn;0;NSM;;;;;N;;;;; +E01E3;VARIATION SELECTOR-244;Mn;0;NSM;;;;;N;;;;; +E01E4;VARIATION SELECTOR-245;Mn;0;NSM;;;;;N;;;;; +E01E5;VARIATION SELECTOR-246;Mn;0;NSM;;;;;N;;;;; +E01E6;VARIATION SELECTOR-247;Mn;0;NSM;;;;;N;;;;; +E01E7;VARIATION SELECTOR-248;Mn;0;NSM;;;;;N;;;;; +E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;; +E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;; +E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;; +E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;; +E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;; +E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;; +E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;; +E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;; +F0000;<Plane 15 Private Use, First>;Co;0;L;;;;;N;;;;; +FFFFD;<Plane 15 Private Use, Last>;Co;0;L;;;;;N;;;;; +100000;<Plane 16 Private Use, First>;Co;0;L;;;;;N;;;;; +10FFFD;<Plane 16 Private Use, Last>;Co;0;L;;;;;N;;;;; diff --git a/test/jdk/java/lang/Character/UnicodeSpec.java b/test/jdk/java/lang/Character/UnicodeSpec.java new file mode 100644 index 00000000000..1c0af1e67e9 --- /dev/null +++ b/test/jdk/java/lang/Character/UnicodeSpec.java @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.File; +import java.util.regex.Pattern; +import java.util.ArrayList; + +/** + * The UnicodeSpec class provides a way to read in Unicode character + * properties from a Unicode data file. One instance of class UnicodeSpec + * holds a decoded version of one line of the data file. The file may + * be obtained from www.unicode.org. The method readSpecFile returns an array + * of UnicodeSpec objects. + * + * @author Guy Steele + * @author John O'Conner + */ + +public class UnicodeSpec { + + public UnicodeSpec() { + this(0xffff); + } + + public UnicodeSpec(int codePoint) { + this.codePoint = codePoint; + generalCategory = UNASSIGNED; + bidiCategory = DIRECTIONALITY_UNDEFINED; + mirrored = false; + titleMap = 0xFFFF; + upperMap = 0xFFFF; + lowerMap = 0xFFFF; + decimalValue = -1; + digitValue = -1; + numericValue = ""; + oldName = null; + comment = null; + name = null; + } + + public String toString() { + StringBuffer result = new StringBuffer(hex6(codePoint)); + if (getUpperMap() != 0xffff) { + result.append(", upper=").append(hex6(upperMap)); + } + if (getLowerMap() != 0xffff) { + result.append(", lower=").append(hex6(lowerMap)); + } + if (getTitleMap() != 0xffff) { + result.append(", title=").append(hex6(titleMap)); + } + return result.toString(); + } + + static String hex4(int n) { + String q = Long.toHexString(n & 0xFFFF).toUpperCase(); + return "0000".substring(Math.min(4, q.length())) + q; + } + + static String hex6(int n) { + String str = Integer.toHexString(n & 0xFFFFFF).toUpperCase(); + return "000000".substring(Math.min(6, str.length())) + str; + + } + + + /** + * Given one line of a Unicode data file as a String, parse the line + * and return a UnicodeSpec object that contains the same character information. + * + * @param s a line of the Unicode data file to be parsed + * @return a UnicodeSpec object, or null if the parsing process failed for some reason + */ + public static UnicodeSpec parse(String s) { + UnicodeSpec spec = null; + String[] tokens = null; + + try { + tokens = tokenSeparator.split(s, REQUIRED_FIELDS); + spec = new UnicodeSpec(); + spec.setCodePoint(parseCodePoint(tokens[FIELD_VALUE])); + spec.setName(parseName(tokens[FIELD_NAME])); + spec.setGeneralCategory(parseGeneralCategory(tokens[FIELD_CATEGORY])); + spec.setBidiCategory(parseBidiCategory(tokens[FIELD_BIDI])); + spec.setCombiningClass(parseCombiningClass(tokens[FIELD_CLASS])); + spec.setDecomposition(parseDecomposition(tokens[FIELD_DECOMPOSITION])); + spec.setDecimalValue(parseDecimalValue(tokens[FIELD_DECIMAL])); + spec.setDigitValue(parseDigitValue(tokens[FIELD_DIGIT])); + spec.setNumericValue(parseNumericValue(tokens[FIELD_NUMERIC])); + spec.setMirrored(parseMirrored(tokens[FIELD_MIRRORED])); + spec.setOldName(parseOldName(tokens[FIELD_OLDNAME])); + spec.setComment(parseComment(tokens[FIELD_COMMENT])); + spec.setUpperMap(parseUpperMap(tokens[FIELD_UPPERCASE])); + spec.setLowerMap(parseLowerMap(tokens[FIELD_LOWERCASE])); + spec.setTitleMap(parseTitleMap(tokens[FIELD_TITLECASE])); + } + catch(Exception e) { + spec = null; + System.out.println("Error parsing spec line."); + } + return spec; + } + + /** + * Parse the codePoint attribute for a Unicode character. If the parse succeeds, + * the codePoint field of this UnicodeSpec object is updated and false is returned. + * + * The codePoint attribute should be a four-digit hexadecimal integer. + * + * @param s the codePoint attribute extracted from a line of the Unicode data file + * @return code point if successful + * @exception NumberFormatException if unable to parse argument + */ + public static int parseCodePoint(String s) throws NumberFormatException { + return Integer.parseInt(s, 16); + } + + public static String parseName(String s) throws Exception { + if (s==null) throw new Exception("Cannot parse name."); + return s; + } + + public static byte parseGeneralCategory(String s) throws Exception { + byte category = GENERAL_CATEGORY_COUNT; + + for (byte x=0; x<generalCategoryList.length; x++) { + if (s.equals(generalCategoryList[x][SHORT])) { + category = x; + break; + } + } + if (category >= GENERAL_CATEGORY_COUNT) { + throw new Exception("Could not parse general category."); + } + return category; + } + + public static byte parseBidiCategory(String s) throws Exception { + byte category = DIRECTIONALITY_CATEGORY_COUNT; + + for (byte x=0; x<bidiCategoryList.length; x++) { + if (s.equals(bidiCategoryList[x][SHORT])) { + category = x; + break; + } + } + if (category >= DIRECTIONALITY_CATEGORY_COUNT) { + throw new Exception("Could not parse bidi category."); + } + return category; + } + + + /** + * Parse the combining attribute for a Unicode character. If there is a combining + * attribute and the parse succeeds, then the hasCombining field is set to true, + * the combining field of this UnicodeSpec object is updated, and false is returned. + * If the combining attribute is an empty string, the parse succeeds but the + * hasCombining field is set to false. (and false is returned). + * + * The combining attribute, if any, should be a nonnegative decimal integer. + * + * @param s the combining attribute extracted from a line of the Unicode data file + * @return the combining class value if any, -1 if property not defined + * @exception Exception if can't parse the combining class + */ + + public static int parseCombiningClass(String s) throws Exception { + int combining = -1; + if (s.length()>0) { + combining = Integer.parseInt(s, 10); + } + return combining; + } + + /** + * Parse the decomposition attribute for a Unicode character. If the parse succeeds, + * the decomposition field of this UnicodeSpec object is updated and false is returned. + * + * The decomposition attribute is complicated; for now, it is treated as a string. + * + * @param s the decomposition attribute extracted from a line of the Unicode data file + * @return true if the parse failed; otherwise false + */ + + public static String parseDecomposition(String s) throws Exception { + if (s==null) throw new Exception("Cannot parse decomposition."); + return s; + } + + + /** + * Parse the decimal value attribute for a Unicode character. If there is a decimal value + * attribute and the parse succeeds, then the hasDecimalValue field is set to true, + * the decimalValue field of this UnicodeSpec object is updated, and false is returned. + * If the decimal value attribute is an empty string, the parse succeeds but the + * hasDecimalValue field is set to false. (and false is returned). + * + * The decimal value attribute, if any, should be a nonnegative decimal integer. + * + * @param s the decimal value attribute extracted from a line of the Unicode data file + * @return the decimal value as an int, -1 if no decimal value defined + * @exception NumberFormatException if the parse fails + */ + public static int parseDecimalValue(String s) throws NumberFormatException { + int value = -1; + + if (s.length() > 0) { + value = Integer.parseInt(s, 10); + } + return value; + } + + /** + * Parse the digit value attribute for a Unicode character. If there is a digit value + * attribute and the parse succeeds, then the hasDigitValue field is set to true, + * the digitValue field of this UnicodeSpec object is updated, and false is returned. + * If the digit value attribute is an empty string, the parse succeeds but the + * hasDigitValue field is set to false. (and false is returned). + * + * The digit value attribute, if any, should be a nonnegative decimal integer. + * + * @param s the digit value attribute extracted from a line of the Unicode data file + * @return the digit value as an non-negative int, or -1 if no digit property defined + * @exception NumberFormatException if the parse fails + */ + public static int parseDigitValue(String s) throws NumberFormatException { + int value = -1; + + if (s.length() > 0) { + value = Integer.parseInt(s, 10); + } + return value; + } + + public static String parseNumericValue(String s) throws Exception { + if (s == null) throw new Exception("Cannot parse numeric value."); + return s; + } + + public static String parseComment(String s) throws Exception { + if (s == null) throw new Exception("Cannot parse comment."); + return s; + } + + public static boolean parseMirrored(String s) throws Exception { + boolean mirrored; + if (s.length() == 1) { + if (s.charAt(0) == 'Y') {mirrored = true;} + else if (s.charAt(0) == 'N') {mirrored = false;} + else {throw new Exception("Cannot parse mirrored property.");} + } + else { throw new Exception("Cannot parse mirrored property.");} + return mirrored; + } + + public static String parseOldName(String s) throws Exception { + if (s == null) throw new Exception("Cannot parse old name"); + return s; + } + + /** + * Parse the uppercase mapping attribute for a Unicode character. If there is a uppercase + * mapping attribute and the parse succeeds, then the hasUpperMap field is set to true, + * the upperMap field of this UnicodeSpec object is updated, and false is returned. + * If the uppercase mapping attribute is an empty string, the parse succeeds but the + * hasUpperMap field is set to false. (and false is returned). + * + * The uppercase mapping attribute should be a four-digit hexadecimal integer. + * + * @param s the uppercase mapping attribute extracted from a line of the Unicode data file + * @return uppercase char if defined, \uffff otherwise + * @exception NumberFormatException if parse fails + */ + public static int parseUpperMap(String s) throws NumberFormatException { + int upperCase = 0xFFFF; + + if (s.length() >= 4) { + upperCase = Integer.parseInt(s, 16); + } + else if (s.length() != 0) { + throw new NumberFormatException(); + } + return upperCase; + } + + /** + * Parse the lowercase mapping attribute for a Unicode character. If there is a lowercase + * mapping attribute and the parse succeeds, then the hasLowerMap field is set to true, + * the lowerMap field of this UnicodeSpec object is updated, and false is returned. + * If the lowercase mapping attribute is an empty string, the parse succeeds but the + * hasLowerMap field is set to false. (and false is returned). + * + * The lowercase mapping attribute should be a four-digit hexadecimal integer. + * + * @param s the lowercase mapping attribute extracted from a line of the Unicode data file + * @return lowercase char mapping if defined, \uFFFF otherwise + * @exception NumberFormatException if parse fails + */ + public static int parseLowerMap(String s) throws NumberFormatException { + int lowerCase = 0xFFFF; + + if (s.length() >= 4) { + lowerCase = Integer.parseInt(s, 16); + } + else if (s.length() != 0) { + throw new NumberFormatException(); + } + return lowerCase; + } + + /** + * Parse the titlecase mapping attribute for a Unicode character. If there is a titlecase + * mapping attribute and the parse succeeds, then the hasTitleMap field is set to true, + * the titleMap field of this UnicodeSpec object is updated, and false is returned. + * If the titlecase mapping attribute is an empty string, the parse succeeds but the + * hasTitleMap field is set to false. (and false is returned). + * + * The titlecase mapping attribute should be a four-digit hexadecimal integer. + * + * @param s the titlecase mapping attribute extracted from a line of the Unicode data file + * @return title case char mapping if defined, \uFFFF otherwise + * @exception NumberFormatException if parse fails + */ + public static int parseTitleMap(String s) throws NumberFormatException { + int titleCase = 0xFFFF; + + if (s.length() >= 4) { + titleCase = Integer.parseInt(s, 16); + } + else if (s.length() != 0) { + throw new NumberFormatException(); + } + return titleCase; + } + + /** + * Read and parse a Unicode data file. + * + * @param file a file specifying the Unicode data file to be read + * @return an array of UnicodeSpec objects, one for each line of the + * Unicode data file that could be successfully parsed as + * specifying Unicode character attributes + */ + + public static UnicodeSpec[] readSpecFile(File file, int plane) throws FileNotFoundException { + ArrayList<UnicodeSpec> list = new ArrayList<>(3000); + UnicodeSpec[] result = null; + int count = 0; + BufferedReader f = new BufferedReader(new FileReader(file)); + String line = null; + loop: + while(true) { + try { + line = f.readLine(); + } + catch (IOException e) { + break loop; + } + if (line == null) break loop; + UnicodeSpec item = parse(line.trim()); + int specPlane = item.getCodePoint() >>> 16; + if (specPlane < plane) continue; + if (specPlane > plane) break; + + if (item != null) { + list.add(item); + } + } + result = new UnicodeSpec[list.size()]; + list.toArray(result); + return result; + } + + void setCodePoint(int value) { + codePoint = value; + } + + /** + * Return the code point in this Unicode specification + * @return the char code point representing by the specification + */ + public int getCodePoint() { + return codePoint; + } + + void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + void setGeneralCategory(byte category) { + generalCategory = category; + } + + public byte getGeneralCategory() { + return generalCategory; + } + + void setBidiCategory(byte category) { + bidiCategory = category; + } + + public byte getBidiCategory() { + return bidiCategory; + } + + void setCombiningClass(int combiningClass) { + this.combiningClass = combiningClass; + } + + public int getCombiningClass() { + return combiningClass; + } + + void setDecomposition(String decomposition) { + this.decomposition = decomposition; + } + + public String getDecomposition() { + return decomposition; + } + + void setDecimalValue(int value) { + decimalValue = value; + } + + public int getDecimalValue() { + return decimalValue; + } + + public boolean isDecimalValue() { + return decimalValue != -1; + } + + void setDigitValue(int value) { + digitValue = value; + } + + public int getDigitValue() { + return digitValue; + } + + public boolean isDigitValue() { + return digitValue != -1; + } + + void setNumericValue(String value) { + numericValue = value; + } + + public String getNumericValue() { + return numericValue; + } + + public boolean isNumericValue() { + return numericValue.length() > 0; + } + + void setMirrored(boolean value) { + mirrored = value; + } + + public boolean isMirrored() { + return mirrored; + } + + void setOldName(String name) { + oldName = name; + } + + public String getOldName() { + return oldName; + } + + void setComment(String comment) { + this.comment = comment; + } + + public String getComment() { + return comment; + } + + void setUpperMap(int ch) { + upperMap = ch; + }; + + public int getUpperMap() { + return upperMap; + } + + public boolean hasUpperMap() { + return upperMap != 0xffff; + } + + void setLowerMap(int ch) { + lowerMap = ch; + } + + public int getLowerMap() { + return lowerMap; + } + + public boolean hasLowerMap() { + return lowerMap != 0xffff; + } + + void setTitleMap(int ch) { + titleMap = ch; + } + + public int getTitleMap() { + return titleMap; + } + + public boolean hasTitleMap() { + return titleMap != 0xffff; + } + + int codePoint; // the characters UTF-32 code value + String name; // the ASCII name + byte generalCategory; // general category, available via Characte.getType() + byte bidiCategory; // available via Character.getBidiType() + int combiningClass; // not used in Character + String decomposition; // not used in Character + int decimalValue; // decimal digit value + int digitValue; // not all digits are decimal + String numericValue; // numeric value if digit or non-digit + boolean mirrored; // + String oldName; + String comment; + int upperMap; + int lowerMap; + int titleMap; + + // this is the number of fields in one line of the UnicodeData.txt file + // each field is separated by a semicolon (a token) + static final int REQUIRED_FIELDS = 15; + + /** + * General category types + * To preserve compatibility, these values cannot be changed + */ + public static final byte + UNASSIGNED = 0, // Cn normative + UPPERCASE_LETTER = 1, // Lu normative + LOWERCASE_LETTER = 2, // Ll normative + TITLECASE_LETTER = 3, // Lt normative + MODIFIER_LETTER = 4, // Lm normative + OTHER_LETTER = 5, // Lo normative + NON_SPACING_MARK = 6, // Mn informative + ENCLOSING_MARK = 7, // Me informative + COMBINING_SPACING_MARK = 8, // Mc normative + DECIMAL_DIGIT_NUMBER = 9, // Nd normative + LETTER_NUMBER = 10, // Nl normative + OTHER_NUMBER = 11, // No normative + SPACE_SEPARATOR = 12, // Zs normative + LINE_SEPARATOR = 13, // Zl normative + PARAGRAPH_SEPARATOR = 14, // Zp normative + CONTROL = 15, // Cc normative + FORMAT = 16, // Cf normative + // 17 is unused for no apparent reason, + // but must preserve forward compatibility + PRIVATE_USE = 18, // Co normative + SURROGATE = 19, // Cs normative + DASH_PUNCTUATION = 20, // Pd informative + START_PUNCTUATION = 21, // Ps informative + END_PUNCTUATION = 22, // Pe informative + CONNECTOR_PUNCTUATION = 23, // Pc informative + OTHER_PUNCTUATION = 24, // Po informative + MATH_SYMBOL = 25, // Sm informative + CURRENCY_SYMBOL = 26, // Sc informative + MODIFIER_SYMBOL = 27, // Sk informative + OTHER_SYMBOL = 28, // So informative + INITIAL_QUOTE_PUNCTUATION = 29, // Pi informative + FINAL_QUOTE_PUNCTUATION = 30, // Pf informative + + // this value is only used in the character generation tool + // it can change to accommodate the addition of new categories. + GENERAL_CATEGORY_COUNT = 31; // sentinel value + + static final byte SHORT = 0, LONG = 1; + // general category type strings + // NOTE: The order of this category array is dependent on the assignment of + // category constants above. We want to access this array using constants above. + // [][SHORT] is the SHORT name, [][LONG] is the LONG name + static final String[][] generalCategoryList = { + {"Cn", "UNASSIGNED"}, + {"Lu", "UPPERCASE_LETTER"}, + {"Ll", "LOWERCASE_LETTER"}, + {"Lt", "TITLECASE_LETTER"}, + {"Lm", "MODIFIER_LETTER"}, + {"Lo", "OTHER_LETTER"}, + {"Mn", "NON_SPACING_MARK"}, + {"Me", "ENCLOSING_MARK"}, + {"Mc", "COMBINING_SPACING_MARK"}, + {"Nd", "DECIMAL_DIGIT_NUMBER"}, + {"Nl", "LETTER_NUMBER"}, + {"No", "OTHER_NUMBER"}, + {"Zs", "SPACE_SEPARATOR"}, + {"Zl", "LINE_SEPARATOR"}, + {"Zp", "PARAGRAPH_SEPARATOR"}, + {"Cc", "CONTROL"}, + {"Cf", "FORMAT"}, + {"xx", "unused"}, + {"Co", "PRIVATE_USE"}, + {"Cs", "SURROGATE"}, + {"Pd", "DASH_PUNCTUATION"}, + {"Ps", "START_PUNCTUATION"}, + {"Pe", "END_PUNCTUATION"}, + {"Pc", "CONNECTOR_PUNCTUATION"}, + {"Po", "OTHER_PUNCTUATION"}, + {"Sm", "MATH_SYMBOL"}, + {"Sc", "CURRENCY_SYMBOL"}, + {"Sk", "MODIFIER_SYMBOL"}, + {"So", "OTHER_SYMBOL"}, + {"Pi", "INITIAL_QUOTE_PUNCTUATION"}, + {"Pf", "FINAL_QUOTE_PUNCTUATION"} + }; + + /** + * Bidirectional categories + */ + public static final byte + DIRECTIONALITY_UNDEFINED = -1, + // Strong category + DIRECTIONALITY_LEFT_TO_RIGHT = 0, // L + DIRECTIONALITY_RIGHT_TO_LEFT = 1, // R + DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 2, // AL + // Weak category + DIRECTIONALITY_EUROPEAN_NUMBER = 3, // EN + DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 4, // ES + DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 5, // ET + DIRECTIONALITY_ARABIC_NUMBER = 6, // AN + DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 7, // CS + DIRECTIONALITY_NONSPACING_MARK = 8, // NSM + DIRECTIONALITY_BOUNDARY_NEUTRAL = 9, // BN + // Neutral category + DIRECTIONALITY_PARAGRAPH_SEPARATOR = 10, // B + DIRECTIONALITY_SEGMENT_SEPARATOR = 11, // S + DIRECTIONALITY_WHITESPACE = 12, // WS + DIRECTIONALITY_OTHER_NEUTRALS = 13, // ON + + DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 14, // LRE + DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 15, // LRO + DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 16, // RLE + DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 17, // RLO + DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 18, // PDF + + DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE = 19, // LRI + DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE = 20, // RLI + DIRECTIONALITY_FIRST_STRONG_ISOLATE = 21, // FSI + DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE = 22, // PDI + + DIRECTIONALITY_CATEGORY_COUNT = 23; // sentinel value + + // If changes are made to the above bidi category assignments, this + // list of bidi category names must be changed to keep their order in synch. + // Access this list using the bidi category constants above. + static final String[][] bidiCategoryList = { + {"L", "DIRECTIONALITY_LEFT_TO_RIGHT"}, + {"R", "DIRECTIONALITY_RIGHT_TO_LEFT"}, + {"AL", "DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC"}, + {"EN", "DIRECTIONALITY_EUROPEAN_NUMBER"}, + {"ES", "DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR"}, + {"ET", "DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR"}, + {"AN", "DIRECTIONALITY_ARABIC_NUMBER"}, + {"CS", "DIRECTIONALITY_COMMON_NUMBER_SEPARATOR"}, + {"NSM", "DIRECTIONALITY_NONSPACING_MARK"}, + {"BN", "DIRECTIONALITY_BOUNDARY_NEUTRAL"}, + {"B", "DIRECTIONALITY_PARAGRAPH_SEPARATOR"}, + {"S", "DIRECTIONALITY_SEGMENT_SEPARATOR"}, + {"WS", "DIRECTIONALITY_WHITESPACE"}, + {"ON", "DIRECTIONALITY_OTHER_NEUTRALS"}, + {"LRE", "DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING"}, + {"LRO", "DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE"}, + {"RLE", "DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING"}, + {"RLO", "DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE"}, + {"PDF", "DIRECTIONALITY_POP_DIRECTIONAL_FORMAT"}, + {"LRI", "DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE"}, + {"RLI", "DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE"}, + {"FSI", "DIRECTIONALITY_FIRST_STRONG_ISOLATE"}, + {"PDI", "DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE"}, + + }; + + // Unicode specification lines have fields in this order. + static final byte + FIELD_VALUE = 0, + FIELD_NAME = 1, + FIELD_CATEGORY = 2, + FIELD_CLASS = 3, + FIELD_BIDI = 4, + FIELD_DECOMPOSITION = 5, + FIELD_DECIMAL = 6, + FIELD_DIGIT = 7, + FIELD_NUMERIC = 8, + FIELD_MIRRORED = 9, + FIELD_OLDNAME = 10, + FIELD_COMMENT = 11, + FIELD_UPPERCASE = 12, + FIELD_LOWERCASE = 13, + FIELD_TITLECASE = 14; + + static final Pattern tokenSeparator = Pattern.compile(";"); + + public static void main(String[] args) { + UnicodeSpec[] spec = null; + if (args.length == 2 ) { + try { + File file = new File(args[0]); + int plane = Integer.parseInt(args[1]); + spec = UnicodeSpec.readSpecFile(file, plane); + System.out.println("UnicodeSpec[" + spec.length + "]:"); + for (int x=0; x<spec.length; x++) { + System.out.println(spec[x].toString()); + } + } + catch(Exception e) { + e.printStackTrace(); + } + } + + } + +} diff --git a/test/jdk/java/lang/Character/charprop00.bin b/test/jdk/java/lang/Character/charprop00.bin new file mode 100644 index 0000000000000000000000000000000000000000..fb3f2658b3aefc78ffc60ac54a6bf436bee71bfe GIT binary patch literal 1048617 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ǜJbL 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∈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 literal 0 HcmV?d00001 diff --git a/test/jdk/java/lang/Character/charprop01.bin b/test/jdk/java/lang/Character/charprop01.bin new file mode 100644 index 0000000000000000000000000000000000000000..15ea910bfd2738de80fd5e60400afc12871f064c GIT binary patch literal 1048617 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�u^(Jahqux{<Xw;jj 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 zES�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 literal 0 HcmV?d00001 diff --git a/test/jdk/java/lang/Character/charprop02.bin b/test/jdk/java/lang/Character/charprop02.bin new file mode 100644 index 0000000000000000000000000000000000000000..2493ad18a286bcf442be689abec1ce2f49c7d3d7 GIT binary patch literal 1048617 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%0A1YVTq4==cZD@SBoJNP^BjhYP0v{=x=tz8&oJU9D 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%0Al_@7DTr8t*O#+3t7`*<^d*J!PBiiT9FS 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 F{|{SHQ2GD> literal 0 HcmV?d00001 diff --git a/test/jdk/java/lang/Character/charprop03.bin b/test/jdk/java/lang/Character/charprop03.bin new file mode 100644 index 0000000000000000000000000000000000000000..cfc4d35c898154d499f21278bbaf3ce55ef065c4 GIT binary patch literal 1048617 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�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�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�u<tA!Rquf*-Xq20&BaL$N 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 b#TLK$V2i)J+G3lJw%Fy(7W;g%1$l>m!LB~! literal 0 HcmV?d00001 diff --git a/test/jdk/java/lang/Character/charprop0E.bin b/test/jdk/java/lang/Character/charprop0E.bin new file mode 100644 index 0000000000000000000000000000000000000000..14af6cda2d6dca3756dd774b18b4438e45910cdc GIT binary patch literal 1048617 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¨}-nUur|6{I}ZDC}&hV8s$uC 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 literal 0 HcmV?d00001 diff --git a/test/jdk/java/lang/Character/charprop0F.bin b/test/jdk/java/lang/Character/charprop0F.bin new file mode 100644 index 0000000000000000000000000000000000000000..3d86c4f8937462af68af8f48413b5cae60fa1ba8 GIT binary patch literal 1048617 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≧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 literal 0 HcmV?d00001 diff --git a/test/jdk/java/lang/Character/charprop10.bin b/test/jdk/java/lang/Character/charprop10.bin new file mode 100644 index 0000000000000000000000000000000000000000..91bcc3ce8c88158720edc4743cc56f4bae82aed6 GIT binary patch literal 1048617 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 S|6c&I1^xp&`B46c|NjAj0Xysf literal 0 HcmV?d00001 diff --git a/test/jdk/java/lang/String/SpecialCasingTest.java b/test/jdk/java/lang/String/SpecialCasingTest.java new file mode 100644 index 00000000000..55575346949 --- /dev/null +++ b/test/jdk/java/lang/String/SpecialCasingTest.java @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 4397357 6565620 6959267 7070436 7198195 8041791 8032446 8072600 + * @summary Confirm special case mappings are handled correctly. + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.StringTokenizer; + +public class SpecialCasingTest { + + private static boolean err = false; + + // Locales which are used for testing + private static List<Locale> locales = new ArrayList<>(); + static { + locales.add(new Locale("az", "")); + locales.addAll(java.util.Arrays.asList(Locale.getAvailableLocales())); + } + + // Default locale + private static String defaultLang; + + // True if the default language is az, lt, or tr which has locale-specific + // mappings. + private static boolean specificLocale; + + // Additional test cases + // Pseudo-locales which are used here: + // L1: locales other than lt + // L2: locales other than az and tr + // L3: locales other than az, lt and tr + private static final String[] additionalTestData = { + // Format: + // <code>; <lower>; <title>; <upper>; (<condition_list>) + + // Counterpart of Final_Sigma test case + // 03A3; 03C2; 03A3; 03A3; Final_Sigma + "03A3; 03C3; 03A3; 03A3; SunSpecific_Not_Final_Sigma1", + "03A3; 03C3; 03A3; 03A3; SunSpecific_Not_Final_Sigma2", + + // Counterpart of After_Soft_Dotted test case + // 0307; 0307; ; ; lt After_Soft_Dotted + "0307; 0307; 0307; 0307; L1 After_Soft_Dotted", + "0307; 0307; 0307; 0307; lt SunSpecific_Not_After_Soft_Dotted", + "0307; 0307; 0307; 0307; L1 SunSpecific_Not_After_Soft_Dotted", + + // Counterpart of More_Above test cases + // 0049; 0069 0307; 0049; 0049; lt More_Above + "0049; 0131 ; 0049; 0049; az More_Above", + "0049; 0131 ; 0049; 0049; tr More_Above", + "0049; 0069 ; 0049; 0049; L3 More_Above", + "0049; 0069 ; 0049; 0049; lt SunSpecific_Not_More_Above", + "0049; 0131 ; 0049; 0049; az SunSpecific_Not_More_Above", + "0049; 0131 ; 0049; 0049; tr SunSpecific_Not_More_Above", + "0049; 0069 ; 0049; 0049; L3 SunSpecific_Not_More_Above", + // 004A; 006A 0307; 004A; 004A; lt More_Above + "004A; 006A ; 004A; 004A; L1 More_Above", + "004A; 006A ; 004A; 004A; lt SunSpecific_Not_More_Above", + "004A; 006A ; 004A; 004A; L1 SunSpecific_Not_More_Above", + // 012E; 012F 0307; 012E; 012E; lt More_Above + "012E; 012F ; 012E; 012E; L1 More_Above", + "012E; 012F ; 012E; 012E; lt SunSpecific_Not_More_Above", + "012E; 012F ; 012E; 012E; L1 SunSpecific_Not_More_Above", + + // Counterpart of After_I test cases + // 0307; ; 0307; 0307; tr After_I + // 0307; ; 0307; 0307; az After_I + "0307; 0307 0307; 0307; 0307; lt After_I", + "0307; 0307 ; 0307; 0307; L3 After_I", + "0307; 0307 ; 0307; 0307; tr SunSpecific_Not_After_I", + "0307; 0307 ; 0307; 0307; az SunSpecific_Not_After_I", + "0307; 0307 ; 0307; 0307; L2 SunSpecific_Not_After_I", + + // Counterpart of Not_Before_Dot test cases + // 0049; 0131 ; 0049; 0049; tr Not_Before_Dot + // 0049; 0131 ; 0049; 0049; az Not_Before_Dot + "0049; 0069 ; 0049; 0049; L2 Not_Before_Dot", + "0049; 0069 ; 0049; 0049; tr SunSpecific_Before_Dot", + "0049; 0069 ; 0049; 0049; az SunSpecific_Before_Dot", + "0049; 0069 0307 0307; 0049; 0049; lt SunSpecific_Before_Dot", + "0049; 0069 0307 ; 0049; 0049; L3 SunSpecific_Before_Dot", + }; + + public static void main (String[] args) { + SpecialCasingTest specialCasingTest = new SpecialCasingTest(); + specialCasingTest.test(); + } + + private void test () { + Locale defaultLocale = Locale.getDefault(); + BufferedReader in = null; + + try { + int locale_num = locales.size(); + for (int l = 0; l < locale_num; l++) { + Locale locale = locales.get(l); + Locale.setDefault(locale); + System.out.println("Testing on " + locale + " locale...."); + + defaultLang = locale.getLanguage(); + if (defaultLang.equals("az") || + defaultLang.equals("lt") || + defaultLang.equals("tr")) { + specificLocale = true; + } else { + specificLocale = false; + } + in = Files.newBufferedReader(Paths.get(System.getProperty("test.src.path"), "..", "/Character/SpecialCasing.txt") + .toRealPath()); + String line; + while ((line = in.readLine()) != null) { + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + test(line); + } + in.close(); + in = null; + System.out.println("Testing with Sun original data...."); + for (String additionalTestData1 : additionalTestData) { + test(additionalTestData1); + } + } + } + catch (IOException e) { + err = true; + e.printStackTrace(); + } + finally { + if (in != null) { + try { + in.close(); + } + catch (IOException e) { + } + } + Locale.setDefault(defaultLocale); + if (err) { + throw new RuntimeException("SpecialCasingTest failed."); + } else { + System.out.println("*** SpecialCasingTest passed."); + } + } + } + + private void test(String line) { + int index = line.indexOf('#'); + if (index != -1) { + line = line.substring(0, index); + } + + String lang = null; + String condition = null; + String[] fields = line.split("; "); + + for (int i = 0; i < 4; i++) { + if (fields[i].length() != 0) { + fields[i] = convert(fields[i]); + } + } + if (fields.length != 4) { + StringTokenizer st = new StringTokenizer(fields[4]); + + while (st.hasMoreTokens()) { + String token = st.nextToken(); + + if (token.equals("Final_Sigma")) { + condition = "Final Sigma"; + fields[0] = "Abc" + fields[0]; + fields[1] = "abc" + fields[1]; + fields[3] = "ABC" + fields[3]; + } else if (token.equals("SunSpecific_Not_Final_Sigma1")) { + condition = "*Sun Specific* Not Final Sigma 1"; + fields[0] = "Abc" + fields[0] + "xyz"; + fields[1] = "abc" + fields[1] + "xyz"; + fields[3] = "ABC" + fields[3] + "XYZ"; + } else if (token.equals("SunSpecific_Not_Final_Sigma2")) { + condition = "*Sun Specific* Not Final Sigma 2"; + } else if (token.equals("After_Soft_Dotted")) { + condition = "After Soft-Dotted"; + fields[0] = "\u1E2D" + fields[0]; + fields[1] = "\u1E2D" + fields[1]; + fields[3] = "\u1E2C" + fields[3]; + } else if (token.equals("SunSpecific_Not_After_Soft_Dotted")) { + condition = "*Sun Specific* Not After Soft-Dotted"; + fields[0] = "Dot" + fields[0]; + fields[1] = "dot" + fields[1]; + fields[3] = "DOT" + fields[3]; + } else if (token.equals("More_Above")) { + condition = "More Above"; + fields[0] = fields[0] + "\u0306"; + fields[1] = fields[1] + "\u0306"; + fields[3] = fields[3] + "\u0306"; + } else if (token.equals("SunSpecific_Not_More_Above")) { + condition = "*Sun Specific* Not More Above"; + fields[0] = fields[0] + "breve"; + fields[1] = fields[1] + "breve"; + fields[3] = fields[3] + "BREVE"; + } else if (token.equals("After_I")) { + condition = "After I"; + fields[0] = "I" + fields[0]; + fields[1] = "i" + fields[1]; + fields[3] = "I" + fields[3]; + } else if (token.equals("SunSpecific_Not_After_I")) { + condition = "*Sun Specific* Not After I"; + fields[0] = "A" + fields[0]; + fields[1] = "a" + fields[1]; + fields[3] = "A" + fields[3]; + } else if (token.equals("Not_Before_Dot")) { + condition = "Not Before Dot"; + fields[0] = fields[0] + "Z"; + fields[1] = fields[1] + "z"; + fields[3] = fields[3] + "Z"; + } else if (token.equals("SunSpecific_Before_Dot")) { + condition = "*Sun Specific* Before Dot"; + fields[0] = fields[0] + "\u0307"; + fields[3] = fields[3] + "\u0307"; + } else if (token.length() == 2) { + lang = token; + + if (lang.equals("L1")) { + if (defaultLang.equals("lt")) { + lang = "en"; + } else { + lang = defaultLang; + } + } else if (lang.equals("L2")) { + if (defaultLang.equals("az") || + defaultLang.equals("tr")) { + lang = "en"; + } else { + lang = defaultLang; + } + } else if (lang.equals("L3")) { + if (defaultLang.equals("az") || + defaultLang.equals("lt") || + defaultLang.equals("tr")) { + lang = "en"; + } else { + lang = defaultLang; + } + // I want to have another test case here for double-check. + // Current implementation for Character and String considers + // only az, lt, and tr locales. I want to detect if other + // locales are specified. + } else if (!lang.equals("az") && + !lang.equals("lt") && + !lang.equals("tr")) { + throw new RuntimeException("Unsupported locale: " + + lang + ". It may need to be considered in ConditionalSpecialCasing.java. Please confirm."); + } + } else { + throw new RuntimeException("Unknown condition: " + token); + } + } + } else if (fields[0].equals("\u0130")) { + // special case for \u0130 + if (defaultLang.equals("az") || + defaultLang.equals("tr")) { + lang = "en"; + } else { + lang = defaultLang; + } + } + testLowerCase(fields[0], fields[1], lang, condition); + testUpperCase(fields[0], fields[3], lang, condition); + } + + private void testLowerCase(String orig, String expected, + String lang, String condition) { + String got = (lang == null) ? + orig.toLowerCase() : orig.toLowerCase(new Locale(lang, "")); + + if (!expected.equals(got)) { + err = true; + System.err.println("toLowerCase(lang=" + lang + + ") failed.\n\tOriginal: " + toString(orig) + + "\n\tGot: " + toString(got) + + "\n\tExpected: " + toString(expected) + + ((condition == null) ? "" : ("\n under condition(" + + condition + ")"))); + } + } + + private void testUpperCase(String orig, String expected, + String lang, String condition) { + String got = (lang == null) ? + orig.toUpperCase() : orig.toUpperCase(new Locale(lang, "")); + + if (!expected.equals(got)) { + err = true; + System.err.println("toUpperCase(lang=" + lang + + ") failed.\n\tOriginal: " + toString(orig) + + "\n\tGot: " + toString(got) + + "\n\tExpected: " + toString(expected) + + ((condition == null) ? "" : ("\n under condition(" + + condition + ")"))); + } + } + StringBuilder sb = new StringBuilder(); + + private String convert(String str) { + sb.setLength(0); + + String[] tokens = str.split(" "); + for (String token : tokens) { + sb.append((char) Integer.parseInt(token, 16)); + } + return sb.toString(); + } + + private String toString(String str) { + sb.setLength(0); + + int len = str.length(); + for (int i = 0; i < len; i++) { + sb.append("0x").append(Integer.toHexString(str.charAt(i)).toUpperCase()).append(" "); + } + return sb.toString(); + } + +} diff --git a/test/jdk/java/lang/String/UnicodeCasingTest.java b/test/jdk/java/lang/String/UnicodeCasingTest.java new file mode 100644 index 00000000000..a148b975ec0 --- /dev/null +++ b/test/jdk/java/lang/String/UnicodeCasingTest.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 4397357 6565620 6959267 7070436 7198195 8032446 8072600 + * @summary Confirm normal case mappings are handled correctly. + * @run main/timeout=200 UnicodeCasingTest + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Locale; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class UnicodeCasingTest { + + private static boolean err = false; + + // Locales which are used for testing + private static List<Locale> locales = new ArrayList<>(); + static { + locales.add(new Locale("az", "")); + locales.addAll(java.util.Arrays.asList(Locale.getAvailableLocales())); + } + + // Default locale + private static String defaultLang; + + // List for Unicode characters whose mappings are included in + // SpecialCasing.txt and mappings in UnicodeData.txt isn't applicable. + private static Map<String, String> excludeList = new HashMap<>(); + + public static void main(String[] args) { + UnicodeCasingTest specialCasingTest = new UnicodeCasingTest(); + specialCasingTest.test(); + } + + private void test() { + Locale defaultLocale = Locale.getDefault(); + BufferedReader in = null; + try { + // First, we create exlude lists of characters whose mappings exist + // in SpecialCasing.txt and mapping rules in UnicodeData.txt aren't + // applicable. + in = Files.newBufferedReader(Paths.get(System.getProperty("test.src.path"), "..", "/Character/SpecialCasing.txt") + .toRealPath()); + String line; + while ((line = in.readLine()) != null) { + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + updateExcludeList(line); + } + in.close(); + in = null; + int locale_num = locales.size(); + for (int l = 0; l < locale_num; l++) { + Locale locale = locales.get(l); + Locale.setDefault(locale); + defaultLang = locale.getLanguage(); +// System.out.println("Testing on " + locale + " locale...."); + System.err.println("Testing on " + locale + " locale...."); + in = Files.newBufferedReader(Paths.get(System.getProperty("test.src.path"), "..", "/Character/UnicodeData.txt") + .toRealPath()); + while ((line = in.readLine()) != null) { + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + test(line); + } + in.close(); + in = null; + } + } + catch (IOException e) { + err = true; + e.printStackTrace(); + } + finally { + if (in != null) { + try { + in.close(); + } + catch (IOException e) { + } + } + + Locale.setDefault(defaultLocale); + + if (err) { + throw new RuntimeException("UnicodeCasingTest failed."); + } else { + System.out.println("*** UnicodeCasingTest passed."); + } + } + } + + private void updateExcludeList(String line) { + int index = line.indexOf('#'); + if (index != -1) { + line = line.substring(0, index); + } + + String lang = null; + String condition = null; + String[] fields = line.split("; "); + + // If the given character is mapped to multiple characters under the + // normal condition, add it to the exclude list. + if (fields.length == 4) { + excludeList.put(fields[0], "all"); + } else if (fields.length == 5) { + if (fields[4].length() == 2) { /// locale + if (excludeList.get(fields[0]) == null) { + excludeList.put(fields[0], fields[4]); + } + } + } + } + + private void test(String line) { + String[] fields = line.split(";", 15); + String orig = convert(fields[0]); + + String lang = excludeList.get(fields[0]); + if (!"all".equals(lang) && !defaultLang.equals(lang)) { + if (fields[12].length() == 0) { + testUpperCase(orig, convert(fields[0])); + } else { + testUpperCase(orig, convert(fields[12])); + } + + if (fields[13].length() == 0) { + testLowerCase(orig, convert(fields[0])); + } else { + testLowerCase(orig, convert(fields[13])); + } + } + } + + private void testUpperCase(String orig, String expected) { + String got = orig.toUpperCase(); + + // Ugly workaround for special mappings for az and tr locales.... + if (orig.equals("\u0069") && + (defaultLang.equals("az") || defaultLang.equals("tr"))) { + expected = "\u0130"; + } + + if (!expected.equals(got)) { + err = true; + System.err.println("toUpperCase(" + + ") failed.\n\tOriginal: " + toString(orig) + + "\n\tGot: " + toString(got) + + "\n\tExpected: " + toString(expected)); + } + } + + private void testLowerCase(String orig, String expected) { + String got = orig.toLowerCase(); + // Ugly workaround for special mappings for az and tr locales.... + if (orig.equals("\u0049") && + (defaultLang.equals("az") || defaultLang.equals("tr"))) { + expected = "\u0131"; + } + + if (!expected.equals(got)) { + err = true; + System.err.println("toLowerCase(" + + ") failed.\n\tOriginal: " + toString(orig) + + "\n\tGot: " + toString(got) + + "\n\tExpected: " + toString(expected)); + } + } + + StringBuilder sb = new StringBuilder(); + + private String convert(String str) { + sb.setLength(0); + + String[] tokens = str.split(" "); + for (String token : tokens) { + int j = Integer.parseInt(token, 16); + if (j < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + sb.append((char)j); + } else { + sb.append(Character.toChars(j)); + } + } + + return sb.toString(); + } + + private String toString(String str) { + sb.setLength(0); + + int len = str.length(); + for (int i = 0; i < len; i++) { + sb.append("0x").append(Integer.toHexString(str.charAt(i)).toUpperCase()).append(" "); + } + + return sb.toString(); + } + +} From 4bbca4651ccd5e95925810169fa9c31bd834983f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= <hannesw@openjdk.org> Date: Tue, 8 May 2018 09:41:10 +0200 Subject: [PATCH 32/40] 8200716: Object propertyIsEnumerable buggy behavior on short integer-string key Reviewed-by: jlaskey, sundar --- .../internal/objects/NativeObject.java | 10 ++++- test/nashorn/script/basic/JDK-8200716.js | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 test/nashorn/script/basic/JDK-8200716.js diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java index 72d144f5e20..718d82b6033 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java @@ -66,6 +66,7 @@ import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.arrays.ArrayData; +import jdk.nashorn.internal.runtime.arrays.ArrayIndex; import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.InvokeByName; import jdk.nashorn.internal.runtime.linker.NashornBeansLinker; @@ -613,8 +614,13 @@ public final class NativeObject { final Object obj = Global.toObject(self); if (obj instanceof ScriptObject) { - final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str); - return property != null && property.isEnumerable(); + final ScriptObject sobj = (ScriptObject) obj; + final Property property = sobj.getProperty(str); + if (property != null) { + return property.isEnumerable(); + } else { + return (sobj.getArray().has(ArrayIndex.getArrayIndex(v))); + } } return false; diff --git a/test/nashorn/script/basic/JDK-8200716.js b/test/nashorn/script/basic/JDK-8200716.js new file mode 100644 index 00000000000..5bb2fade3f7 --- /dev/null +++ b/test/nashorn/script/basic/JDK-8200716.js @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, 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. + */ + +/** + * JDK-8200716: Object propertyIsEnumerable buggy behavior on short integer-string key + * + * @test + * @run + */ + + +var o = ({ '1': 1 }); +Assert.assertTrue(o.propertyIsEnumerable('1')); + +Object.defineProperty(o, '1', { enumerable: false, value: 1 }); +Assert.assertFalse(o.propertyIsEnumerable('1')); + +Object.defineProperty(o, '1', { enumerable: true, value: 1 }); +Assert.assertTrue(o.propertyIsEnumerable('1')); From 13ce1152a4a48818f0b7acb49f42806fd28bb6b3 Mon Sep 17 00:00:00 2001 From: Claes Redestad <redestad@openjdk.org> Date: Tue, 8 May 2018 09:52:18 +0200 Subject: [PATCH 33/40] 8202583: Remove experimental ClassForNamePlugin Reviewed-by: jlaskey, alanb, mchung --- .../internal/plugins/ClassForNamePlugin.java | 185 ------------------ src/jdk.jlink/share/classes/module-info.java | 3 +- 2 files changed, 1 insertion(+), 187 deletions(-) delete mode 100644 src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java deleted file mode 100644 index ca59c404420..00000000000 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2016, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 jdk.tools.jlink.internal.plugins; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import jdk.tools.jlink.plugin.ResourcePool; -import jdk.tools.jlink.plugin.ResourcePoolBuilder; -import jdk.tools.jlink.plugin.Plugin.Category; -import jdk.internal.org.objectweb.asm.ClassReader; -import static jdk.internal.org.objectweb.asm.ClassReader.*; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; -import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode; -import jdk.internal.org.objectweb.asm.tree.ClassNode; -import jdk.internal.org.objectweb.asm.tree.InsnList; -import jdk.internal.org.objectweb.asm.tree.LabelNode; -import jdk.internal.org.objectweb.asm.tree.LdcInsnNode; -import jdk.internal.org.objectweb.asm.tree.LineNumberNode; -import jdk.internal.org.objectweb.asm.tree.MethodInsnNode; -import jdk.internal.org.objectweb.asm.tree.MethodNode; -import jdk.tools.jlink.plugin.ResourcePoolEntry; -import jdk.tools.jlink.plugin.Plugin; - -public final class ClassForNamePlugin implements Plugin { - public static final String NAME = "class-for-name"; - - private static String binaryClassName(String path) { - return path.substring(path.indexOf('/', 1) + 1, - path.length() - ".class".length()); - } - - private static int getAccess(ResourcePoolEntry resource) { - ClassReader cr = new ClassReader(resource.contentBytes()); - - return cr.getAccess(); - } - - private static String getPackage(String binaryName) { - int index = binaryName.lastIndexOf("/"); - - return index == -1 ? "" : binaryName.substring(0, index); - } - - private ResourcePoolEntry transform(ResourcePoolEntry resource, ResourcePool pool) { - byte[] inBytes = resource.contentBytes(); - ClassReader cr = new ClassReader(inBytes); - ClassNode cn = new ClassNode(); - cr.accept(cn, EXPAND_FRAMES); - List<MethodNode> ms = cn.methods; - boolean modified = false; - LdcInsnNode ldc = null; - - String thisPackage = getPackage(binaryClassName(resource.path())); - - for (MethodNode mn : ms) { - InsnList il = mn.instructions; - Iterator<AbstractInsnNode> it = il.iterator(); - - while (it.hasNext()) { - AbstractInsnNode insn = it.next(); - - if (insn instanceof LdcInsnNode) { - ldc = (LdcInsnNode)insn; - } else if (insn instanceof MethodInsnNode && ldc != null) { - MethodInsnNode min = (MethodInsnNode)insn; - - if (min.getOpcode() == Opcodes.INVOKESTATIC && - min.name.equals("forName") && - min.owner.equals("java/lang/Class") && - min.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) { - String ldcClassName = ldc.cst.toString(); - String thatClassName = ldcClassName.replaceAll("\\.", "/"); - Optional<ResourcePoolEntry> thatClass = - pool.findEntryInContext(thatClassName + ".class", resource); - - if (thatClass.isPresent()) { - int thatAccess = getAccess(thatClass.get()); - String thatPackage = getPackage(thatClassName); - - if ((thatAccess & Opcodes.ACC_PRIVATE) != Opcodes.ACC_PRIVATE && - ((thatAccess & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC || - thisPackage.equals(thatPackage))) { - Type type = Type.getObjectType(thatClassName); - il.remove(ldc); - il.set(min, new LdcInsnNode(type)); - modified = true; - } - } - } - - ldc = null; - } else if (!(insn instanceof LabelNode) && - !(insn instanceof LineNumberNode)) { - ldc = null; - } - - } - } - - if (modified) { - ClassWriter cw = new ClassWriter(cr, 0); - cn.accept(cw); - byte[] outBytes = cw.toByteArray(); - - return resource.copyWithContent(outBytes); - } - - return resource; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { - Objects.requireNonNull(in); - Objects.requireNonNull(out); - - in.entries() - .forEach(resource -> { - String path = resource.path(); - - if (path.endsWith(".class") && !path.endsWith("/module-info.class")) { - out.add(transform(resource, in)); - } else { - out.add(resource); - } - }); - return out.build(); - } - - @Override - public Category getType() { - return Category.TRANSFORMER; - } - - @Override - public boolean hasArguments() { - return false; - } - - @Override - public String getDescription() { - return PluginsResourceBundle.getDescription(NAME); - } - - @Override - public String getArgumentsDescription() { - return PluginsResourceBundle.getArgument(NAME); - } - - @Override - public void configure(Map<String, String> config) { - - } -} diff --git a/src/jdk.jlink/share/classes/module-info.java b/src/jdk.jlink/share/classes/module-info.java index 915edd2856d..e4fac05cfad 100644 --- a/src/jdk.jlink/share/classes/module-info.java +++ b/src/jdk.jlink/share/classes/module-info.java @@ -75,6 +75,5 @@ module jdk.jlink { jdk.tools.jlink.internal.plugins.ExcludeVMPlugin, jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin, jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin, - jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin, - jdk.tools.jlink.internal.plugins.ClassForNamePlugin; + jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin; } From 59d4a62f42d80663065f279f2035aeaa0fa78daf Mon Sep 17 00:00:00 2001 From: Christoph Dreis <christoph.dreis@freenet.de> Date: Tue, 8 May 2018 09:57:45 +0200 Subject: [PATCH 34/40] 8202719: Use Collections.emptyEnumeration where possible Reviewed-by: martin, psandoz --- .../share/classes/java/util/jar/JarFile.java | 12 ++---------- .../share/classes/java/util/jar/JarVerifier.java | 12 +----------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index c4e20f357e0..ec7fdf0f06a 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -42,6 +42,7 @@ import java.security.CodeSigner; import java.security.CodeSource; import java.security.cert.Certificate; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Locale; @@ -1095,16 +1096,7 @@ class JarFile extends ZipFile { if (includeUnsigned) { return unsignedEntryNames(); } else { - return new Enumeration<>() { - - public boolean hasMoreElements() { - return false; - } - - public String nextElement() { - throw new NoSuchElementException(); - } - }; + return Collections.emptyEnumeration(); } } diff --git a/src/java.base/share/classes/java/util/jar/JarVerifier.java b/src/java.base/share/classes/java/util/jar/JarVerifier.java index 49b21e215d4..205d6e93872 100644 --- a/src/java.base/share/classes/java/util/jar/JarVerifier.java +++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java @@ -684,7 +684,7 @@ class JarVerifier { } final List<CodeSigner[]> signersReq = req; - final Enumeration<String> enum2 = (matchUnsigned) ? unsignedEntryNames(jar) : emptyEnumeration; + final Enumeration<String> enum2 = matchUnsigned ? unsignedEntryNames(jar) : Collections.emptyEnumeration(); return new Enumeration<>() { @@ -769,16 +769,6 @@ class JarVerifier { } }; } - private Enumeration<String> emptyEnumeration = new Enumeration<String>() { - - public boolean hasMoreElements() { - return false; - } - - public String nextElement() { - throw new NoSuchElementException(); - } - }; // true if file is part of the signature mechanism itself static boolean isSigningRelated(String name) { From 035d0190a379d6d8906ae01e66ac8167d6f42442 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl <tschatzl@openjdk.org> Date: Tue, 8 May 2018 10:01:29 +0200 Subject: [PATCH 35/40] 8202017: Merge Reference Enqueuing phase with phase 3 of Reference processing Do reference enqueuing work directly in phase 3 after every Reference. Reviewed-by: kbarrett, sangheki --- .../gc/cms/concurrentMarkSweepGeneration.cpp | 9 -- src/hotspot/share/gc/cms/parNewGeneration.cpp | 8 - src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 52 ++----- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 10 +- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 5 - .../g1/g1FullGCReferenceProcessorExecutor.cpp | 4 - src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 5 - src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp | 4 - src/hotspot/share/gc/parallel/psMarkSweep.cpp | 6 +- .../share/gc/parallel/psParallelCompact.cpp | 6 - src/hotspot/share/gc/parallel/psScavenge.cpp | 10 -- .../share/gc/shared/genCollectedHeap.cpp | 4 +- .../share/gc/shared/referenceProcessor.cpp | 138 +++--------------- .../share/gc/shared/referenceProcessor.hpp | 18 +-- .../shared/referenceProcessorPhaseTimes.cpp | 28 ---- .../shared/referenceProcessorPhaseTimes.hpp | 11 -- .../jtreg/gc/g1/TestGCLogMessages.java | 1 - .../jtreg/gc/logging/TestPrintReferences.java | 9 +- 18 files changed, 48 insertions(+), 280 deletions(-) diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index df7a44426e2..3812f861c7b 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -5254,16 +5254,7 @@ void CMSCollector::refProcessingWork() { restore_preserved_marks_if_any(); // done single-threaded for now rp->set_enqueuing_is_done(true); - if (rp->processing_is_mt()) { - rp->balance_all_queues(); - CMSRefProcTaskExecutor task_executor(*this); - rp->enqueue_discovered_references(&task_executor, &pt); - } else { - rp->enqueue_discovered_references(NULL, &pt); - } rp->verify_no_references_recorded(); - pt.print_enqueue_phase(); - assert(!rp->discovery_enabled(), "should have been disabled"); } #ifndef PRODUCT diff --git a/src/hotspot/share/gc/cms/parNewGeneration.cpp b/src/hotspot/share/gc/cms/parNewGeneration.cpp index 0aa8bc97628..0e9232095f7 100644 --- a/src/hotspot/share/gc/cms/parNewGeneration.cpp +++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp @@ -1054,18 +1054,10 @@ void ParNewGeneration::collect(bool full, update_time_of_last_gc(now); rp->set_enqueuing_is_done(true); - if (rp->processing_is_mt()) { - ParNewRefProcTaskExecutor task_executor(*this, *_old_gen, thread_state_set); - rp->enqueue_discovered_references(&task_executor, &pt); - } else { - rp->enqueue_discovered_references(NULL, &pt); - } rp->verify_no_references_recorded(); gch->trace_heap_after_gc(gc_tracer()); - pt.print_enqueue_phase(); - _gc_timer->register_gc_end(); _gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions()); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 4151ae46d95..63fabf97ae9 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -3879,7 +3879,6 @@ void G1STWRefProcTaskExecutor::execute(EnqueueTask& enq_task) { // End of weak reference support closures -// Weak Reference processing during an evacuation pause (part 1). void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) { double ref_proc_start = os::elapsedTime(); @@ -3939,42 +3938,15 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per // We have completed copying any necessary live referent objects. assert(pss->queue_is_empty(), "both queue and overflow should be empty"); + make_pending_list_reachable(); + + rp->verify_no_references_recorded(); + double ref_proc_time = os::elapsedTime() - ref_proc_start; g1_policy()->phase_times()->record_ref_proc_time(ref_proc_time * 1000.0); } -// Weak Reference processing during an evacuation pause (part 2). -void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states) { - double ref_enq_start = os::elapsedTime(); - - ReferenceProcessor* rp = _ref_processor_stw; - assert(!rp->discovery_enabled(), "should have been disabled as part of processing"); - - ReferenceProcessorPhaseTimes* pt = g1_policy()->phase_times()->ref_phase_times(); - - // Now enqueue any remaining on the discovered lists on to - // the pending list. - if (!rp->processing_is_mt()) { - // Serial reference processing... - rp->enqueue_discovered_references(NULL, pt); - } else { - // Parallel reference enqueueing - - uint n_workers = workers()->active_workers(); - - assert(n_workers <= rp->max_num_queues(), - "Mismatch between the number of GC workers %u and the maximum number of Reference process queues %u", - n_workers, rp->max_num_queues()); - - G1STWRefProcTaskExecutor par_task_executor(this, per_thread_states, workers(), _task_queues, n_workers); - rp->enqueue_discovered_references(&par_task_executor, pt); - } - - rp->verify_no_references_recorded(); - assert(!rp->discovery_enabled(), "should have been disabled"); - - // If during an initial mark pause we install a pending list head which is not otherwise reachable - // ensure that it is marked in the bitmap for concurrent marking to discover. +void G1CollectedHeap::make_pending_list_reachable() { if (collector_state()->in_initial_mark_gc()) { oop pll_head = Universe::reference_pending_list(); if (pll_head != NULL) { @@ -3982,14 +3954,6 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per _cm->mark_in_next_bitmap(0 /* worker_id */, pll_head); } } - - // FIXME - // CM's reference processing also cleans up the string and symbol tables. - // Should we do that here also? We could, but it is a serial operation - // and could significantly increase the pause time. - - double ref_enq_time = os::elapsedTime() - ref_enq_start; - g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0); } void G1CollectedHeap::merge_per_thread_state_info(G1ParScanThreadStateSet* per_thread_states) { @@ -4069,7 +4033,11 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in // objects (and their reachable sub-graphs) that were // not copied during the pause. process_discovered_references(per_thread_states); - enqueue_discovered_references(per_thread_states); + + // FIXME + // CM's reference processing also cleans up the string and symbol tables. + // Should we do that here also? We could, but it is a serial operation + // and could significantly increase the pause time. G1STWIsAliveClosure is_alive(this); G1KeepAliveClosure keep_alive(this); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 69d8658ab55..dd964635447 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -513,13 +513,13 @@ private: // allocated block, or else "NULL". HeapWord* expand_and_allocate(size_t word_size); - // Process any reference objects discovered during - // an incremental evacuation pause. + // Process any reference objects discovered. void process_discovered_references(G1ParScanThreadStateSet* per_thread_states); - // Enqueue any remaining discovered references - // after processing. - void enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states); + // If during an initial mark pause we may install a pending list head which is not + // otherwise reachable ensure that it is marked in the bitmap for concurrent marking + // to discover. + void make_pending_list_reachable(); // Merges the information gathered on a per-thread basis for all worker threads // during GC into global variables. diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 6bd23048332..35d4cb26620 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1677,12 +1677,7 @@ void G1ConcurrentMark::weak_refs_work(bool clear_all_soft_refs) { assert(rp->num_queues() == active_workers, "why not"); - rp->enqueue_discovered_references(executor, &pt); - rp->verify_no_references_recorded(); - - pt.print_enqueue_phase(); - assert(!rp->discovery_enabled(), "Post condition"); } diff --git a/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp b/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp index f54458f052f..1b5da52b9a7 100644 --- a/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp @@ -108,8 +108,4 @@ void G1FullGCReferenceProcessingExecutor::execute(STWGCTimer* timer, G1FullGCTra pt.print_all_references(); assert(marker->oop_stack()->is_empty(), "Should be no oops on the stack"); - - // Now enqueue the references. - _reference_processor->enqueue_discovered_references(executor, &pt); - pt.print_enqueue_phase(); } diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index c2f1d850396..50662f273a5 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -129,7 +129,6 @@ void G1GCPhaseTimes::reset() { _cur_clear_ct_time_ms = 0.0; _cur_expand_heap_time_ms = 0.0; _cur_ref_proc_time_ms = 0.0; - _cur_ref_enq_time_ms = 0.0; _cur_weak_ref_proc_time_ms = 0.0; _cur_collection_start_sec = 0.0; _root_region_scan_wait_time_ms = 0.0; @@ -383,7 +382,6 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { _recorded_preserve_cm_referents_time_ms + _cur_ref_proc_time_ms + _cur_weak_ref_proc_time_ms + - _cur_ref_enq_time_ms + _cur_clear_ct_time_ms + _recorded_merge_pss_time_ms + _cur_strong_code_root_purge_time_ms + @@ -416,9 +414,6 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { trace_time("Remove Self Forwards",_cur_evac_fail_remove_self_forwards); } - debug_time_for_reference("Reference Enqueuing", _cur_ref_enq_time_ms); - _ref_phase_times.print_enqueue_phase(2, false); - debug_time("Merge Per-Thread State", _recorded_merge_pss_time_ms); debug_time("Code Roots Purge", _cur_strong_code_root_purge_time_ms); diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index b2a9a906249..d5ec33400c0 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -261,10 +261,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> { _cur_weak_ref_proc_time_ms = ms; } - void record_ref_enq_time(double ms) { - _cur_ref_enq_time_ms = ms; - } - void record_root_region_scan_wait_time(double time_ms) { _root_region_scan_wait_time_ms = time_ms; } diff --git a/src/hotspot/share/gc/parallel/psMarkSweep.cpp b/src/hotspot/share/gc/parallel/psMarkSweep.cpp index 61afff6269a..e793ddfad71 100644 --- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp +++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp @@ -260,11 +260,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { DerivedPointerTable::update_pointers(); #endif - ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->num_queues()); - - ref_processor()->enqueue_discovered_references(NULL, &pt); - - pt.print_enqueue_phase(); + assert(!ref_processor()->discovery_enabled(), "Should have been disabled earlier"); // Update time of last GC reset_millis_since_last_gc(); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index bca79105c9b..ae5851a906a 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1038,12 +1038,6 @@ void PSParallelCompact::post_compact() DerivedPointerTable::update_pointers(); #endif - ReferenceProcessorPhaseTimes pt(&_gc_timer, ref_processor()->num_queues()); - - ref_processor()->enqueue_discovered_references(NULL, &pt); - - pt.print_enqueue_phase(); - if (ZapUnusedHeapArea) { heap->gen_mangle_unused_area(); } diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index c6f043ba110..64ff0b8a38b 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -430,16 +430,6 @@ bool PSScavenge::invoke_no_policy() { _gc_tracer.report_gc_reference_stats(stats); pt.print_all_references(); - - // Enqueue reference objects discovered during scavenge. - if (reference_processor()->processing_is_mt()) { - PSRefProcTaskExecutor task_executor; - reference_processor()->enqueue_discovered_references(&task_executor, &pt); - } else { - reference_processor()->enqueue_discovered_references(NULL, &pt); - } - - pt.print_enqueue_phase(); } assert(promotion_manager->stacks_empty(),"stacks should be empty at this point"); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index 775fa8b6609..3062e44c5dc 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -517,9 +517,7 @@ void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t siz } gen->collect(full, clear_soft_refs, size, is_tlab); if (!rp->enqueuing_is_done()) { - ReferenceProcessorPhaseTimes pt(NULL, rp->num_queues()); - rp->enqueue_discovered_references(NULL, &pt); - pt.print_enqueue_phase(); + rp->disable_discovery(); } else { rp->set_enqueuing_is_done(false); } diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index 96ecab83d8a..9bb39047ca6 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -257,113 +257,6 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references( return stats; } -void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor, - ReferenceProcessorPhaseTimes* phase_times) { - // Enqueue references that are not made active again, and - // clear the decks for the next collection (cycle). - enqueue_discovered_reflists(task_executor, phase_times); - - // Stop treating discovered references specially. - disable_discovery(); -} - -void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list) { - // Given a list of refs linked through the "discovered" field - // (java.lang.ref.Reference.discovered), self-loop their "next" field - // thus distinguishing them from active References, then - // prepend them to the pending list. - // - // The Java threads will see the Reference objects linked together through - // the discovered field. Instead of trying to do the write barrier updates - // in all places in the reference processor where we manipulate the discovered - // field we make sure to do the barrier here where we anyway iterate through - // all linked Reference objects. Note that it is important to not dirty any - // cards during reference processing since this will cause card table - // verification to fail for G1. - log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(&refs_list)); - - oop obj = NULL; - oop next_discovered = refs_list.head(); - // Walk down the list, self-looping the next field - // so that the References are not considered active. - while (obj != next_discovered) { - obj = next_discovered; - assert(obj->is_instance(), "should be an instance object"); - assert(InstanceKlass::cast(obj->klass())->is_reference_instance_klass(), "should be reference object"); - next_discovered = java_lang_ref_Reference::discovered(obj); - log_develop_trace(gc, ref)(" obj " INTPTR_FORMAT "/next_discovered " INTPTR_FORMAT, p2i(obj), p2i(next_discovered)); - assert(java_lang_ref_Reference::next(obj) == NULL, - "Reference not active; should not be discovered"); - // Self-loop next, so as to make Ref not active. - java_lang_ref_Reference::set_next_raw(obj, obj); - if (next_discovered != obj) { - HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(obj, java_lang_ref_Reference::discovered_offset, next_discovered); - } else { - // This is the last object. - // Swap refs_list into pending list and set obj's - // discovered to what we read from the pending list. - oop old = Universe::swap_reference_pending_list(refs_list.head()); - HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(obj, java_lang_ref_Reference::discovered_offset, old); - } - } -} - -// Parallel enqueue task -class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask { -public: - RefProcEnqueueTask(ReferenceProcessor& ref_processor, - DiscoveredList discovered_refs[], - int n_queues, - ReferenceProcessorPhaseTimes* phase_times) - : EnqueueTask(ref_processor, discovered_refs, n_queues, phase_times) - { } - - virtual void work(unsigned int work_id) { - RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefEnqueue, _phase_times, work_id); - - assert(work_id < (unsigned int)_ref_processor.max_num_queues(), "Index out-of-bounds"); - // Simplest first cut: static partitioning. - int index = work_id; - // The increment on "index" must correspond to the maximum number of queues - // (n_queues) with which that ReferenceProcessor was created. That - // is because of the "clever" way the discovered references lists were - // allocated and are indexed into. - assert(_n_queues == (int) _ref_processor.max_num_queues(), "Different number not expected"); - for (int j = 0; - j < ReferenceProcessor::number_of_subclasses_of_ref(); - j++, index += _n_queues) { - _ref_processor.enqueue_discovered_reflist(_refs_lists[index]); - _refs_lists[index].set_head(NULL); - _refs_lists[index].set_length(0); - } - } -}; - -// Enqueue references that are not made active again -void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor, - ReferenceProcessorPhaseTimes* phase_times) { - - ReferenceProcessorStats stats(total_count(_discoveredSoftRefs), - total_count(_discoveredWeakRefs), - total_count(_discoveredFinalRefs), - total_count(_discoveredPhantomRefs)); - - RefProcEnqueueTimeTracker tt(phase_times, stats); - - if (_processing_is_mt && task_executor != NULL) { - // Parallel code - RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_queues, phase_times); - task_executor->execute(tsk); - } else { - // Serial code: call the parent class's implementation - for (uint i = 0; i < _max_num_queues * number_of_subclasses_of_ref(); i++) { - enqueue_discovered_reflist(_discovered_refs[i]); - _discovered_refs[i].set_head(NULL); - _discovered_refs[i].set_length(0); - } - } -} - void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { _current_discovered_addr = java_lang_ref_Reference::discovered_addr_raw(_current_discovered); oop discovered = java_lang_ref_Reference::discovered(_current_discovered); @@ -409,6 +302,25 @@ void DiscoveredListIterator::clear_referent() { RawAccess<>::oop_store(_referent_addr, oop(NULL)); } +void DiscoveredListIterator::enqueue() { + // Self-loop next, so as to make Ref not active. + java_lang_ref_Reference::set_next_raw(_current_discovered, _current_discovered); + + HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(_current_discovered, + java_lang_ref_Reference::discovered_offset, + _next_discovered); +} + +void DiscoveredListIterator::complete_enqeue() { + if (_prev_discovered != NULL) { + // This is the last object. + // Swap refs_list into pending list and set obj's + // discovered to what we read from the pending list. + oop old = Universe::swap_reference_pending_list(_refs_list.head()); + HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(_prev_discovered, java_lang_ref_Reference::discovered_offset, old); + } +} + // NOTE: process_phase*() are largely similar, and at a high level // merely iterate over the extant list applying a predicate to // each of its elements and possibly removing that element from the @@ -556,13 +468,18 @@ void ReferenceProcessor::process_phase3(DiscoveredList& refs_list, // keep the referent around iter.make_referent_alive(); } + iter.enqueue(); log_develop_trace(gc, ref)("Adding %sreference (" INTPTR_FORMAT ": %s) as pending", clear_referent ? "cleared " : "", p2i(iter.obj()), iter.obj()->klass()->internal_name()); assert(oopDesc::is_oop(iter.obj(), UseConcMarkSweepGC), "Adding a bad reference"); iter.next(); } + iter.complete_enqeue(); // Close the reachable set complete_gc->do_void(); + // Clear the list. + refs_list.set_head(NULL); + refs_list.set_length(0); } void @@ -785,13 +702,6 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) #endif } -void ReferenceProcessor::balance_all_queues() { - balance_queues(_discoveredSoftRefs); - balance_queues(_discoveredWeakRefs); - balance_queues(_discoveredFinalRefs); - balance_queues(_discoveredPhantomRefs); -} - void ReferenceProcessor::process_discovered_reflist( DiscoveredList refs_lists[], ReferencePolicy* policy, diff --git a/src/hotspot/share/gc/shared/referenceProcessor.hpp b/src/hotspot/share/gc/shared/referenceProcessor.hpp index 0e1683f2bd6..86b52b42793 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.hpp @@ -143,6 +143,12 @@ public: } } + // Do enqueuing work, i.e. notifying the GC about the changed discovered pointers. + void enqueue(); + + // Move enqueued references to the reference pending list. + void complete_enqeue(); + // NULL out referent pointer. void clear_referent(); @@ -273,9 +279,6 @@ class ReferenceProcessor : public ReferenceDiscoverer { OopClosure* keep_alive, VoidClosure* complete_gc); - // Enqueue references with a certain reachability level - void enqueue_discovered_reflist(DiscoveredList& refs_list); - // "Preclean" all the discovered reference lists // by removing references with strongly reachable referents. // The first argument is a predicate on an oop that indicates @@ -295,9 +298,6 @@ class ReferenceProcessor : public ReferenceDiscoverer { // occupying the i / _num_queues slot. const char* list_name(uint i); - void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor, - ReferenceProcessorPhaseTimes* phase_times); - // "Preclean" the given discovered reference list // by removing references with strongly reachable referents. // Currently used in support of CMS only. @@ -387,8 +387,6 @@ public: // iterate over oops void weak_oops_do(OopClosure* f); // weak roots - // Balance each of the discovered lists. - void balance_all_queues(); void verify_list(DiscoveredList& ref_list); // Discover a Reference object, using appropriate discovery criteria @@ -405,10 +403,6 @@ public: AbstractRefProcTaskExecutor* task_executor, ReferenceProcessorPhaseTimes* phase_times); - // Enqueue references at end of GC (called by the garbage collector) - void enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor, - ReferenceProcessorPhaseTimes* phase_times); - // If a discovery is in process that is being superceded, abandon it: all // the discovered lists will be empty, and all the objects on them will // have NULL discovered fields. Must be called only at a safepoint. diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp index 211749095e4..d4a48134aea 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp @@ -78,8 +78,6 @@ static const char* phase_enum_2_phase_string(ReferenceProcessorPhaseTimes::RefPr case ReferenceProcessorPhaseTimes::FinalRefPhase3: case ReferenceProcessorPhaseTimes::PhantomRefPhase3: return "Phase3"; - case ReferenceProcessorPhaseTimes::RefEnqueue: - return "Reference Enqueuing"; default: ShouldNotReachHere(); return NULL; @@ -191,21 +189,6 @@ RefProcPhaseTimesTracker::~RefProcPhaseTimesTracker() { times->set_ref_cleared(ref_type, discovered - after_count); } -RefProcEnqueueTimeTracker::RefProcEnqueueTimeTracker(ReferenceProcessorPhaseTimes* phase_times, - ReferenceProcessorStats& stats) : - RefProcPhaseTimeBaseTracker("Reference Enqueuing", phase_times) { - phase_times->set_ref_enqueued(REF_SOFT, stats.soft_count()); - phase_times->set_ref_enqueued(REF_WEAK, stats.weak_count()); - phase_times->set_ref_enqueued(REF_FINAL, stats.final_count()); - phase_times->set_ref_enqueued(REF_PHANTOM, stats.phantom_count()); -} - -RefProcEnqueueTimeTracker::~RefProcEnqueueTimeTracker() { - double elapsed = elapsed_time(); - - phase_times()->set_par_phase_time_ms(ReferenceProcessorPhaseTimes::RefEnqueue, elapsed); -} - ReferenceProcessorPhaseTimes::ReferenceProcessorPhaseTimes(GCTimer* gc_timer, uint max_gc_threads) : _gc_timer(gc_timer), _processing_is_mt(false) { @@ -369,17 +352,6 @@ ReferenceProcessorPhaseTimes::par_phase(RefProcPhaseNumbers phase_number) const return (RefProcParPhases)result; } -void ReferenceProcessorPhaseTimes::print_enqueue_phase(uint base_indent, bool print_total) const { - if (print_total) { - print_phase(RefEnqueue, base_indent); - } - - log_debug(gc, phases, ref)("%sReference Counts: Soft: " SIZE_FORMAT " Weak: " SIZE_FORMAT - " Final: " SIZE_FORMAT " Phantom: " SIZE_FORMAT , - Indents[base_indent + 1], ref_enqueued(REF_SOFT), ref_enqueued(REF_WEAK), - ref_enqueued(REF_FINAL), ref_enqueued(REF_PHANTOM)); -} - #define TIME_FORMAT "%.1lfms" void ReferenceProcessorPhaseTimes::print_all_references(uint base_indent, bool print_total) const { diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp index 92e1231709c..8c85138aa1b 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp @@ -46,7 +46,6 @@ public: FinalRefPhase3, PhantomRefPhase2, PhantomRefPhase3, - RefEnqueue, RefParPhaseMax }; @@ -133,7 +132,6 @@ public: // Reset all fields. If not reset at next cycle, an assertion will fail. void reset(); - void print_enqueue_phase(uint base_indent = 0, bool print_total = true) const; void print_all_references(uint base_indent = 0, bool print_total = true) const; }; @@ -203,13 +201,4 @@ public: ~RefProcPhaseTimesTracker(); }; -// Updates enqueue time related information. -// - Enqueueing time, enqueued reference count and stats for each working thread if MT processed. -class RefProcEnqueueTimeTracker : public RefProcPhaseTimeBaseTracker { -public: - RefProcEnqueueTimeTracker(ReferenceProcessorPhaseTimes* phase_times, - ReferenceProcessorStats& stats); - ~RefProcEnqueueTimeTracker(); -}; - #endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSORPHASETIMES_HPP diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index 24f1a7622da..a10053fab01 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -141,7 +141,6 @@ public class TestGCLogMessages { new LogMessageWithLevel("Resize TLABs", Level.DEBUG), // Reference Processing new LogMessageWithLevel("Reference Processing", Level.DEBUG), - new LogMessageWithLevel("Reference Enqueuing", Level.DEBUG), // VM internal reference processing new LogMessageWithLevel("Weak Processing", Level.DEBUG), diff --git a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java index 18b89617ce9..35c780669fb 100644 --- a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java +++ b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java @@ -93,9 +93,6 @@ public class TestPrintReferences { gcLogTimeRegex + indent(8) + "Discovered: " + countRegex + "\n" + gcLogTimeRegex + indent(8) + "Cleared: " + countRegex + "\n"; String softRefDetailRegex = gcLogTimeRegex + indent(8) + phase1 + ": " + timeRegex + "\n" + refDetailRegex; - String enqueueRegex = gcLogTimeRegex + indent(4) + "Reference Enqueuing: " + timeRegex + "\n"; - String enqueueDetailRegex = gcLogTimeRegex + indent(6) + "Reference Counts: Soft: " + countRegex + - " Weak: " + countRegex + " Final: " + countRegex + " Phantom: " + countRegex + "\n"; output.shouldMatch(/* Total Reference processing time */ totalRegex + @@ -106,11 +103,7 @@ public class TestPrintReferences { /* FinalReference processing */ finalRefRegex + balanceRegex + refDetailRegex + /* PhantomReference processing */ - phantomRefRegex + balanceRegex + refDetailRegex + - /* Total Enqueuing time */ - enqueueRegex + - /* Enqueued Stats */ - enqueueDetailRegex + phantomRefRegex + balanceRegex + refDetailRegex ); } From b329be2b75e395237833e45c51a2e6815c5b032a Mon Sep 17 00:00:00 2001 From: Claes Redestad <redestad@openjdk.org> Date: Tue, 8 May 2018 10:49:59 +0200 Subject: [PATCH 36/40] 8202548: Use reservation Object when creating SpeciesData Co-authored-by: Peter Levart <peter.levart@gmail.com> Reviewed-by: psandoz, plevart --- .../java/lang/invoke/ClassSpecializer.java | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java index c20d691e6aa..9ee60001ae7 100644 --- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java +++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java @@ -68,7 +68,7 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat private final List<MemberName> transformMethods; private final MethodType baseConstructorType; private final S topSpecies; - private final ConcurrentHashMap<K, S> cache = new ConcurrentHashMap<>(); + private final ConcurrentHashMap<K, Object> cache = new ConcurrentHashMap<>(); private final Factory factory; private @Stable boolean topClassIsSuper; @@ -151,14 +151,20 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat return new IllegalArgumentException(message, cause); } + private static final Function<Object, Object> CREATE_RESERVATION = new Function<>() { + @Override + public Object apply(Object key) { + return new Object(); + } + }; + public final S findSpecies(K key) { // Note: Species instantiation may throw VirtualMachineError because of // code cache overflow. If this happens the species bytecode may be // loaded but not linked to its species metadata (with MH's etc). - // That will cause a throw out of CHM.computeIfAbsent, - // which will shut down the caller thread. + // That will cause a throw out of Factory.loadSpecies. // - // In a latter attempt to get the same species, the already-loaded + // In a later attempt to get the same species, the already-loaded // class will be present in the system dictionary, causing an // error when the species generator tries to reload it. // We try to detect this case and link the pre-existing code. @@ -168,25 +174,20 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat // (As an alternative, we might spin a new class with a new name, // or use the anonymous class mechanism.) // - // In the end, as long as everybody goes through the same CHM, - // CHM.computeIfAbsent will ensure only one SpeciesData will be set - // successfully on a concrete class if ever. + // In the end, as long as everybody goes through this findSpecies method, + // it will ensure only one SpeciesData will be set successfully on a + // concrete class if ever. // The concrete class is published via SpeciesData instance // returned here only after the class and species data are linked together. - S speciesData = cache.computeIfAbsent(key, new Function<>() { - @Override - public S apply(K key1) { - return newSpeciesData(key1); - } - }); + Object speciesDataOrReservation = cache.computeIfAbsent(key, CREATE_RESERVATION); // Separating the creation of a placeholder SpeciesData instance above // from the loading and linking a real one below ensures we can never - // accidentally call computeIfAbsent recursively. Replacing rather than - // updating the placeholder is done to ensure safe publication. - if (!speciesData.isResolved()) { - synchronized (speciesData) { - S existingSpeciesData = cache.get(key); - if (existingSpeciesData == speciesData) { // won the race + // accidentally call computeIfAbsent recursively. + S speciesData; + if (speciesDataOrReservation.getClass() == Object.class) { + synchronized (speciesDataOrReservation) { + Object existingSpeciesData = cache.get(key); + if (existingSpeciesData == speciesDataOrReservation) { // won the race // create a new SpeciesData... speciesData = newSpeciesData(key); // load and link it... @@ -195,9 +196,11 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat throw newInternalError("Concurrent loadSpecies"); } } else { // lost the race; the retrieved existingSpeciesData is the final - speciesData = existingSpeciesData; + speciesData = metaType.cast(existingSpeciesData); } } + } else { + speciesData = metaType.cast(speciesDataOrReservation); } assert(speciesData != null && speciesData.isResolved()); return speciesData; From 8139cce3e50533d26f9e6337a2294034ce70ce5b Mon Sep 17 00:00:00 2001 From: Jim Laskey <jlaskey@openjdk.org> Date: Tue, 8 May 2018 09:27:42 -0300 Subject: [PATCH 37/40] 8200372: String::trim JavaDoc should clarify meaning of space Reviewed-by: sundar --- .../share/classes/java/lang/String.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 81f057b9a87..add9c6ad2a4 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -2599,35 +2599,36 @@ public final class String } /** - * Returns a string whose value is this string, with any leading and trailing - * whitespace removed. + * Returns a string whose value is this string, with all leading + * and trailing space removed, where space is defined + * as any character whose codepoint is less than or equal to + * {@code '\u005Cu0020'} (the space character). * <p> * If this {@code String} object represents an empty character * sequence, or the first and last characters of character sequence * represented by this {@code String} object both have codes - * greater than {@code '\u005Cu0020'} (the space character), then a + * that are not space (as defined above), then a * reference to this {@code String} object is returned. * <p> - * Otherwise, if there is no character with a code greater than - * {@code '\u005Cu0020'} in the string, then a - * {@code String} object representing an empty string is - * returned. + * Otherwise, if all characters in this string are space (as + * defined above), then a {@code String} object representing an + * empty string is returned. * <p> * Otherwise, let <i>k</i> be the index of the first character in the - * string whose code is greater than {@code '\u005Cu0020'}, and let + * string whose code is not a space (as defined above) and let * <i>m</i> be the index of the last character in the string whose code - * is greater than {@code '\u005Cu0020'}. A {@code String} + * is not a space (as defined above). A {@code String} * object is returned, representing the substring of this string that * begins with the character at index <i>k</i> and ends with the * character at index <i>m</i>-that is, the result of * {@code this.substring(k, m + 1)}. * <p> - * This method may be used to trim whitespace (as defined above) from + * This method may be used to trim space (as defined above) from * the beginning and end of a string. * - * @return A string whose value is this string, with any leading and trailing white - * space removed, or this string if it has no leading or - * trailing white space. + * @return a string whose value is this string, with all leading + * and trailing space removed, or this string if it + * has no leading or trailing space. */ public String trim() { String ret = isLatin1() ? StringLatin1.trim(value) From f15ab37909c2621bef10332c9b031668bb489de9 Mon Sep 17 00:00:00 2001 From: Adam Petcher <apetcher@openjdk.org> Date: Tue, 8 May 2018 09:21:51 -0400 Subject: [PATCH 38/40] 8181594: Efficient and constant-time modular arithmetic Field arithmetic library for crypto algorithms like Poly1305 and X25519 Reviewed-by: xuelei --- .../util/math/ImmutableIntegerModuloP.java | 34 ++ .../util/math/IntegerFieldModuloP.java | 115 ++++ .../security/util/math/IntegerModuloP.java | 205 +++++++ .../util/math/MutableIntegerModuloP.java | 135 ++++ .../sun/security/util/math/SmallValue.java | 38 ++ .../util/math/intpoly/IntegerPolynomial.java | 576 ++++++++++++++++++ .../math/intpoly/IntegerPolynomial1305.java | 301 +++++++++ .../math/intpoly/IntegerPolynomial25519.java | 204 +++++++ .../math/intpoly/IntegerPolynomial448.java | 236 +++++++ .../security/util/math/BigIntegerModuloP.java | 273 +++++++++ .../util/math/TestIntegerModuloP.java | 377 ++++++++++++ 11 files changed, 2494 insertions(+) create mode 100644 src/java.base/share/classes/sun/security/util/math/ImmutableIntegerModuloP.java create mode 100644 src/java.base/share/classes/sun/security/util/math/IntegerFieldModuloP.java create mode 100644 src/java.base/share/classes/sun/security/util/math/IntegerModuloP.java create mode 100644 src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java create mode 100644 src/java.base/share/classes/sun/security/util/math/SmallValue.java create mode 100644 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java create mode 100644 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java create mode 100644 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java create mode 100644 src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java create mode 100644 test/jdk/sun/security/util/math/BigIntegerModuloP.java create mode 100644 test/jdk/sun/security/util/math/TestIntegerModuloP.java diff --git a/src/java.base/share/classes/sun/security/util/math/ImmutableIntegerModuloP.java b/src/java.base/share/classes/sun/security/util/math/ImmutableIntegerModuloP.java new file mode 100644 index 00000000000..d921dde4e46 --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/ImmutableIntegerModuloP.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math; + +/** + * An interface for immutable integers modulo a prime value. + */ + +public interface ImmutableIntegerModuloP extends IntegerModuloP { +} + diff --git a/src/java.base/share/classes/sun/security/util/math/IntegerFieldModuloP.java b/src/java.base/share/classes/sun/security/util/math/IntegerFieldModuloP.java new file mode 100644 index 00000000000..57464ee2c23 --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/IntegerFieldModuloP.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math; + +import java.math.BigInteger; + +/** + * An interface for the field of integers modulo a prime number. An + * implementation of this interface can be used to get properties of the + * field and to produce field elements of type ImmutableIntegerModuloP from + * other objects and representations of field elements. + */ + +public interface IntegerFieldModuloP { + + /** + * Get the size of the field as a BigInteger. This size is equal to the + * prime modulus used to construct the field. + * + * @return the size of the field. + */ + BigInteger getSize(); + + /** + * Get the additive identity element 0 + * + * @return the additive identity element + */ + ImmutableIntegerModuloP get0(); + + /** + * Get the multiplicative identity element 1 + * + * @return the multiplicative identity element + */ + ImmutableIntegerModuloP get1(); + + /** + * Get the field element equivalent to the supplied BigInteger value. The + * supplied value may be negative or larger than the modulus that defines + * the field. + * + * @param v a BigInteger value + * @return the field element corresponding to v + */ + ImmutableIntegerModuloP getElement(BigInteger v); + + /** + * Get a "small" value according to this implementation. This value may + * be used in optimized forms of some operations to avoid unnecessary + * calculations. For example, multiplication is much faster when it is + * known that one of the numbers fits within a single limb. + * + * The definition of "small", and the range of accepted values, is + * implementation-specific. + * + * @param v the small integer value + * @throws IllegalArgumentException when the value is not small + */ + SmallValue getSmallValue(int v); + + /** + * Get a field element from a little-endian unsigned integer stored in an + * array. The entire array will be used, and the supplied value may be + * larger than the modulus that defines the field. The array will not be + * modified. + * + * @param v an array containing a little-endian unsigned integer + * @return the field element corresponding to v + */ + default ImmutableIntegerModuloP getElement(byte[] v) { + return getElement(v, 0, v.length, (byte) 0); + } + + /** + * Get a field element from a little-endian unsigned integer stored at the + * specified position in an array. The supplied value may be + * larger than the modulus that defines the field. This method also takes + * a byte which is interpreted as an additional high-order byte of the + * number. The array will not be modified. + * + * @param v an array containing a little-endian unsigned integer + * @param offset the starting position of the integer + * @param length the number of bytes to read + * @param highByte the high-order byte of the number + * @return the field element corresponding to the bytes at the specified + * position + */ + ImmutableIntegerModuloP getElement(byte[] v, int offset, int length, + byte highByte); +} + diff --git a/src/java.base/share/classes/sun/security/util/math/IntegerModuloP.java b/src/java.base/share/classes/sun/security/util/math/IntegerModuloP.java new file mode 100644 index 00000000000..262175b837e --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/IntegerModuloP.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math; + +import java.math.BigInteger; + +/** + * The base interface for integers modulo a prime value. Objects of this + * type may be either mutable or immutable, and subinterfaces can be used + * to specify that an object is mutable or immutable. This type should never + * be used to declare local/member variables, but it may be used for + * formal parameters of a method. None of the methods in this interface + * modify the value of arguments or this. + * + * The behavior of this interface depends on the particular implementation. + * For example, some implementations only support a limited number of add + * operations before each multiply operation. See the documentation of the + * implementation for details. + * + * @see ImmutableIntegerModuloP + * @see MutableIntegerModuloP + */ +public interface IntegerModuloP { + + /** + * Get the field associated with this element. + * + * @return the field + */ + IntegerFieldModuloP getField(); + + /** + * Get the canonical value of this element as a BigInteger. This value + * will always be in the range [0, p), where p is the prime that defines + * the field. This method performs reduction and other computation to + * produce the result. + * + * @return the value as a BigInteger + */ + BigInteger asBigInteger(); + + /** + * Return this value as a fixed (immutable) element. This method will + * copy the underlying representation if the object is mutable. + * + * @return a fixed element with the same value + */ + ImmutableIntegerModuloP fixed(); + + /** + * Return this value as a mutable element. This method will always copy + * the underlying representation. + * + * @return a mutable element with the same value + */ + MutableIntegerModuloP mutable(); + + /** + * Add this field element with the supplied element and return the result. + * + * @param b the sumand + * @return this + b + */ + ImmutableIntegerModuloP add(IntegerModuloP b); + + /** + * Compute the additive inverse of the field element + * @return the addditiveInverse (0 - this) + */ + ImmutableIntegerModuloP additiveInverse(); + + /** + * Multiply this field element with the supplied element and return the + * result. + * + * @param b the multiplicand + * @return this * b + */ + ImmutableIntegerModuloP multiply(IntegerModuloP b); + + /** + * Perform an addition modulo a power of two and return the little-endian + * encoding of the result. The value is (this' + b') % 2^(8 * len), + * where this' and b' are the canonical integer values equivalent to + * this and b. + * + * @param b the sumand + * @param len the length of the desired array + * @return a byte array of length len containing the result + */ + default byte[] addModPowerTwo(IntegerModuloP b, int len) { + byte[] result = new byte[len]; + addModPowerTwo(b, result); + return result; + } + + /** + * Perform an addition modulo a power of two and store the little-endian + * encoding of the result in the supplied array. The value is + * (this' + b') % 2^(8 * result.length), where this' and b' are the + * canonical integer values equivalent to this and b. + * + * @param b the sumand + * @param result an array which stores the result upon return + */ + void addModPowerTwo(IntegerModuloP b, byte[] result); + + /** + * Returns the little-endian encoding of this' % 2^(8 * len), where this' + * is the canonical integer value equivalent to this. + * + * @param len the length of the desired array + * @return a byte array of length len containing the result + */ + default byte[] asByteArray(int len) { + byte[] result = new byte[len]; + asByteArray(result); + return result; + } + + /** + * Places the little-endian encoding of this' % 2^(8 * result.length) + * into the supplied array, where this' is the canonical integer value + * equivalent to this. + * + * @param result an array which stores the result upon return + */ + void asByteArray(byte[] result); + + /** + * Compute the multiplicative inverse of this field element. + * + * @return the multiplicative inverse (1 / this) + */ + default ImmutableIntegerModuloP multiplicativeInverse() { + return pow(getField().getSize().subtract(BigInteger.valueOf(2))); + } + + /** + * Subtract the supplied element from this one and return the result. + * @param b the subtrahend + * + * @return the difference (this - b) + */ + default ImmutableIntegerModuloP subtract(IntegerModuloP b) { + return add(b.additiveInverse()); + } + + /** + * Calculate the square of this element and return the result. This method + * should be used instead of a.multiply(a) because implementations may + * include optimizations that only apply to squaring. + * + * @return the product (this * this) + */ + default ImmutableIntegerModuloP square() { + return multiply(this); + } + + /** + * Calculate the power this^b and return the result. + * + * @param b the exponent + * @return the value of this^b + */ + default ImmutableIntegerModuloP pow(BigInteger b) { + //Default implementation is square and multiply + MutableIntegerModuloP y = getField().get1().mutable(); + MutableIntegerModuloP x = mutable(); + int bitLength = b.bitLength(); + for (int bit = 0; bit < bitLength; bit++) { + if (b.testBit(bit)) { + // odd + y.setProduct(x); + } + x.setSquare(); + } + return y.fixed(); + } + +} + diff --git a/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java b/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java new file mode 100644 index 00000000000..c3c57d68daf --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math; + +import java.nio.ByteBuffer; + +/** + * An interface for mutable integers modulo a prime value. This interface + * should be used to improve performance and avoid the allocation of a large + * number of temporary objects. + * + * Methods in this interface that modify the value also return the modified + * element. This structure enables fluent expressions like: + * a.setSum(b).setProduct(c).setDifference(d).setSquare() + * + */ + +public interface MutableIntegerModuloP extends IntegerModuloP { + + /** + * Swap the value of this with the value of b when swap has the value 1. + * No change is made to either element when swap has the value 0. The + * result is undefined when swap has a value other than 0 or 1. The swap + * parameter is an int (rather than boolean) to allow the implementation + * to perform the swap using branch-free integer arithmetic. + * + * @param b the element to conditionally swap with + * @param swap an int that determines whether to swap + */ + void conditionalSwapWith(MutableIntegerModuloP b, int swap); + + /** + * Set the value of this element equal to the value of the supplied + * element. The argument is not modified. + * + * @param v the element whose value should be copied to this + * @return this + */ + MutableIntegerModuloP setValue(IntegerModuloP v); + + /** + * Set the value equal to the little-endian unsigned integer stored at the + * specified position in an array. The range of accepted values is + * implementation-specific. This method also takes a byte which is + * interpreted as an additional high-order byte of the number. + * + * @param v an array containing a little-endian unsigned integer + * @param offset the starting position of the integer + * @param length the number of bytes to read + * @param highByte the high-order byte of the number + * @return this + */ + MutableIntegerModuloP setValue(byte[] v, int offset, int length, + byte highByte); + + /** + * Set the value equal to the little-endian unsigned integer stored in a + * buffer. The range of accepted values is implementation-specific. + * This method also takes a byte which is interpreted as an additional + * high-order byte of the number. + * + * @param buf a buffer containing a little-endian unsigned integer + * @param length the number of bytes to read + * @param highByte the high-order byte of the number + * @return this + */ + MutableIntegerModuloP setValue(ByteBuffer buf, int length, byte highByte); + + /** + * Set the value of this element equal to this * this. + * + * @return this + */ + MutableIntegerModuloP setSquare(); + + /** + * Set the value of this element equal to this + b. The argument is + * not modified. + * + * @param b the sumand + * @return this + */ + MutableIntegerModuloP setSum(IntegerModuloP b); + + /** + * Set the value of this element equal to this - b. The argument is + * not modified. + * + * @param b the subtrahend + * @return this + */ + MutableIntegerModuloP setDifference(IntegerModuloP b); + + /** + * Set the value of this element equal to this * b. The argument is + * not modified. + * + * @param b the multiplicand + * @return this + */ + MutableIntegerModuloP setProduct(IntegerModuloP b); + + /** + * Set the value of this element equal to this * v. The argument is + * not modified. + * + * @param v the small multiplicand + * @return this + */ + MutableIntegerModuloP setProduct(SmallValue v); +} + diff --git a/src/java.base/share/classes/sun/security/util/math/SmallValue.java b/src/java.base/share/classes/sun/security/util/math/SmallValue.java new file mode 100644 index 00000000000..4c24594b7cd --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/SmallValue.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math; + +/** + * A "small" value that can be used with the field arithmetic library. This + * interface enables optimizations based on the fact that certain values are + * known to be small, where the definition of small is specific to the the + * arithmetic implementation. + */ + +public interface SmallValue { +} + + diff --git a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java new file mode 100644 index 00000000000..88fb2b3a9f2 --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math.intpoly; + +import sun.security.util.math.*; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + +/** + * A large number polynomial representation using sparse limbs of signed + * long (64-bit) values. Limb values will always fit within a long, so inputs + * to multiplication must be less than 32 bits. All IntegerPolynomial + * implementations allow at most one addition before multiplication. Additions + * after that will result in an ArithmeticException. + * + * The following element operations are branch-free for all subclasses: + * + * fixed + * mutable + * add + * additiveInverse + * multiply + * square + * subtract + * conditionalSwapWith + * setValue (may branch on high-order byte parameter only) + * setSum + * setDifference + * setProduct + * setSquare + * + * All other operations may branch in some subclasses. + * + */ + +public abstract class IntegerPolynomial implements IntegerFieldModuloP { + + protected static final BigInteger TWO = BigInteger.valueOf(2); + + protected final int numLimbs; + private final BigInteger modulus; + protected final int bitsPerLimb; + + // must work when a==r + protected abstract void multByInt(long[] a, long b, long[] r); + + // must work when a==r + protected abstract void mult(long[] a, long[] b, long[] r); + + // must work when a==r + protected abstract void square(long[] a, long[] r); + + IntegerPolynomial(int bitsPerLimb, + int numLimbs, + BigInteger modulus) { + + + this.numLimbs = numLimbs; + this.modulus = modulus; + this.bitsPerLimb = bitsPerLimb; + } + + protected int getNumLimbs() { + return numLimbs; + } + + @Override + public BigInteger getSize() { + return modulus; + } + + @Override + public ImmutableElement get0() { + return new ImmutableElement(false); + } + + @Override + public ImmutableElement get1() { + return new ImmutableElement(true); + } + + @Override + public ImmutableElement getElement(BigInteger v) { + return new ImmutableElement(v); + } + + @Override + public SmallValue getSmallValue(int value) { + int maxMag = 1 << (bitsPerLimb - 1); + if (Math.abs(value) >= maxMag) { + throw new IllegalArgumentException( + "max magnitude is " + maxMag); + } + return new Limb(value); + } + + /** + * This version of encode takes a ByteBuffer that is properly ordered, and + * may extract larger values (e.g. long) from the ByteBuffer for better + * performance. The implementation below only extracts bytes from the + * buffer, but this method may be overridden in field-specific + * implementations. + */ + protected void encode(ByteBuffer buf, int length, byte highByte, + long[] result) { + int numHighBits = 32 - Integer.numberOfLeadingZeros(highByte); + int numBits = 8 * length + numHighBits; + int maxBits = bitsPerLimb * result.length; + if (numBits > maxBits) { + throw new ArithmeticException("Value is too large."); + } + + int limbIndex = 0; + long curLimbValue = 0; + int bitPos = 0; + for (int i = 0; i < length; i++) { + long curV = buf.get() & 0xFF; + + if (bitPos + 8 >= bitsPerLimb) { + int bitsThisLimb = bitsPerLimb - bitPos; + curLimbValue += (curV & (0xFF >> (8 - bitsThisLimb))) << bitPos; + result[limbIndex++] = curLimbValue; + curLimbValue = curV >> bitsThisLimb; + bitPos = 8 - bitsThisLimb; + } + else { + curLimbValue += curV << bitPos; + bitPos += 8; + } + } + + // one more for the high byte + if (highByte != 0) { + long curV = highByte & 0xFF; + if (bitPos + 8 >= bitsPerLimb) { + int bitsThisLimb = bitsPerLimb - bitPos; + curLimbValue += (curV & (0xFF >> (8 - bitsThisLimb))) << bitPos; + result[limbIndex++] = curLimbValue; + curLimbValue = curV >> bitsThisLimb; + } + else { + curLimbValue += curV << bitPos; + } + } + + if (limbIndex < numLimbs) { + result[limbIndex++] = curLimbValue; + } + Arrays.fill(result, limbIndex, numLimbs, 0); + + postEncodeCarry(result); + } + + protected void encode(byte[] v, int offset, int length, byte highByte, + long[] result) { + + ByteBuffer buf = ByteBuffer.wrap(v, offset, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + encode(buf, length, highByte, result); + } + + protected void postEncodeCarry(long[] v) { + carry(v); + } + + public ImmutableElement getElement(byte[] v, int offset, int length, + byte highByte) { + + long[] result = new long[numLimbs]; + + encode(v, offset, length, highByte, result); + + return new ImmutableElement(result, true); + } + + protected BigInteger evaluate(long[] limbs) { + BigInteger result = BigInteger.ZERO; + for (int i = limbs.length - 1; i >= 0; i--) { + result = result.shiftLeft(bitsPerLimb) + .add(BigInteger.valueOf(limbs[i])); + } + return result.mod(modulus); + } + + protected long carryValue(long x) { + // compressing carry operation + // if large positive number, carry one more to make it negative + // if large negative number (closer to zero), carry one fewer + return (x + (1 << (bitsPerLimb - 1))) >> bitsPerLimb; + } + + protected void carry(long[] limbs, int start, int end) { + + for (int i = start; i < end; i++) { + + long carry = carryOut(limbs, i); + limbs[i + 1] += carry; + } + } + + protected void carry(long[] limbs) { + + carry(limbs, 0, limbs.length - 1); + } + + // carry out of the specified position and return the carry value + protected long carryOut(long[] limbs, int index) { + long carry = carryValue(limbs[index]); + limbs[index] -= (carry << bitsPerLimb); + return carry; + } + + private void setLimbsValue(BigInteger v, long[] limbs) { + // set all limbs positive, and then carry + setLimbsValuePositive(v, limbs); + carry(limbs); + } + + protected void setLimbsValuePositive(BigInteger v, long[] limbs) { + BigInteger mod = BigInteger.valueOf(1 << bitsPerLimb); + for (int i = 0; i < limbs.length; i++) { + limbs[i] = v.mod(mod).longValue(); + v = v.shiftRight(bitsPerLimb); + } + } + + // v must be final reduced. I.e. all limbs in [0, bitsPerLimb) + // and value in [0, modulus) + protected void decode(long[] v, byte[] dst, int offset, int length) { + + int nextLimbIndex = 0; + long curLimbValue = v[nextLimbIndex++]; + int bitPos = 0; + for (int i = 0; i < length; i++) { + + int dstIndex = i + offset; + if (bitPos + 8 >= bitsPerLimb) { + dst[dstIndex] = (byte) curLimbValue; + curLimbValue = v[nextLimbIndex++]; + int bitsAdded = bitsPerLimb - bitPos; + int bitsLeft = 8 - bitsAdded; + + dst[dstIndex] += (curLimbValue & (0xFF >> bitsAdded)) + << bitsAdded; + curLimbValue >>= bitsLeft; + bitPos = bitsLeft; + } else { + dst[dstIndex] = (byte) curLimbValue; + curLimbValue >>= 8; + bitPos += 8; + } + } + } + + protected void addLimbs(long[] a, long[] b, long[] dst) { + for (int i = 0; i < dst.length; i++) { + dst[i] = a[i] + b[i]; + } + } + + protected static void conditionalSwap(int swap, long[] a, long[] b) { + int maskValue = 0 - swap; + for (int i = 0; i < a.length; i++) { + long dummyLimbs = maskValue & (a[i] ^ b[i]); + a[i] = dummyLimbs ^ a[i]; + b[i] = dummyLimbs ^ b[i]; + } + } + + private void bigIntToByteArray(BigInteger bi, byte[] result) { + byte[] biBytes = bi.toByteArray(); + // biBytes is backwards and possibly too big + // Copy the low-order bytes into result in reverse + int sourceIndex = biBytes.length - 1; + for (int i = 0; i < result.length; i++) { + if (sourceIndex >= 0) { + result[i] = biBytes[sourceIndex--]; + } + else { + result[i] = 0; + } + } + } + + protected void limbsToByteArray(long[] limbs, byte[] result) { + + bigIntToByteArray(evaluate(limbs), result); + } + + protected void addLimbsModPowerTwo(long[] limbs, long[] other, + byte[] result) { + + BigInteger bi1 = evaluate(limbs); + BigInteger bi2 = evaluate(other); + BigInteger biResult = bi1.add(bi2); + bigIntToByteArray(biResult, result); + } + + private abstract class Element implements IntegerModuloP { + + protected long[] limbs; + protected boolean summand = false; + + public Element(BigInteger v) { + limbs = new long[numLimbs]; + setValue(v); + } + + public Element(boolean v) { + limbs = new long[numLimbs]; + limbs[0] = v ? 1l : 0l; + summand = true; + } + + private Element(long[] limbs, boolean summand) { + this.limbs = limbs; + this.summand = summand; + } + + private void setValue(BigInteger v) { + setLimbsValue(v, limbs); + summand = true; + } + + @Override + public IntegerFieldModuloP getField() { + return IntegerPolynomial.this; + } + + @Override + public BigInteger asBigInteger() { + return evaluate(limbs); + } + + @Override + public MutableElement mutable() { + return new MutableElement(limbs.clone(), summand); + } + + @Override + public ImmutableElement add(IntegerModuloP genB) { + + Element b = (Element) genB; + if (!(summand && b.summand)) { + throw new ArithmeticException("Not a valid summand"); + } + + long[] newLimbs = new long[limbs.length]; + for (int i = 0; i < limbs.length; i++) { + newLimbs[i] = limbs[i] + b.limbs[i]; + } + + return new ImmutableElement(newLimbs, false); + } + + @Override + public ImmutableElement additiveInverse() { + + long[] newLimbs = new long[limbs.length]; + for (int i = 0; i < limbs.length; i++) { + newLimbs[i] = -limbs[i]; + } + + ImmutableElement result = new ImmutableElement(newLimbs, summand); + return result; + } + + protected long[] cloneLow(long[] limbs) { + long[] newLimbs = new long[numLimbs]; + copyLow(limbs, newLimbs); + return newLimbs; + } + protected void copyLow(long[] limbs, long[] out) { + System.arraycopy(limbs, 0, out, 0, out.length); + } + + @Override + public ImmutableElement multiply(IntegerModuloP genB) { + + Element b = (Element) genB; + + long[] newLimbs = new long[limbs.length]; + mult(limbs, b.limbs, newLimbs); + return new ImmutableElement(newLimbs, true); + } + + @Override + public ImmutableElement square() { + long[] newLimbs = new long[limbs.length]; + IntegerPolynomial.this.square(limbs, newLimbs); + return new ImmutableElement(newLimbs, true); + } + + public void addModPowerTwo(IntegerModuloP arg, byte[] result) { + if (!summand) { + throw new ArithmeticException("Not a valid summand"); + } + + Element other = (Element) arg; + addLimbsModPowerTwo(limbs, other.limbs, result); + } + + public void asByteArray(byte[] result) { + if (!summand) { + throw new ArithmeticException("Not a valid summand"); + } + limbsToByteArray(limbs, result); + } + } + + private class MutableElement extends Element + implements MutableIntegerModuloP { + + protected MutableElement(long[] limbs, boolean summand) { + super(limbs, summand); + } + + @Override + public ImmutableElement fixed() { + return new ImmutableElement(limbs.clone(), summand); + } + + @Override + public void conditionalSwapWith(MutableIntegerModuloP b, int swap) { + + MutableElement other = (MutableElement) b; + + conditionalSwap(swap, limbs, other.limbs); + boolean summandTemp = summand; + summand = other.summand; + other.summand = summandTemp; + } + + + @Override + public MutableElement setValue(IntegerModuloP v) { + Element other = (Element) v; + + System.arraycopy(other.limbs, 0, limbs, 0, other.limbs.length); + summand = other.summand; + return this; + } + + @Override + public MutableElement setValue(byte[] arr, int offset, + int length, byte highByte) { + + encode(arr, offset, length, highByte, limbs); + summand = true; + + return this; + } + + @Override + public MutableElement setValue(ByteBuffer buf, int length, + byte highByte) { + + encode(buf, length, highByte, limbs); + summand = true; + + return this; + } + + @Override + public MutableElement setProduct(IntegerModuloP genB) { + Element b = (Element) genB; + mult(limbs, b.limbs, limbs); + summand = true; + return this; + } + + @Override + public MutableElement setProduct(SmallValue v) { + int value = ((Limb) v).value; + multByInt(limbs, value, limbs); + summand = true; + return this; + } + + @Override + public MutableElement setSum(IntegerModuloP genB) { + + Element b = (Element) genB; + if (!(summand && b.summand)) { + throw new ArithmeticException("Not a valid summand"); + } + + for (int i = 0; i < limbs.length; i++) { + limbs[i] = limbs[i] + b.limbs[i]; + } + + summand = false; + return this; + } + + @Override + public MutableElement setDifference(IntegerModuloP genB) { + + Element b = (Element) genB; + if (!(summand && b.summand)) { + throw new ArithmeticException("Not a valid summand"); + } + + for (int i = 0; i < limbs.length; i++) { + limbs[i] = limbs[i] - b.limbs[i]; + } + + return this; + } + + @Override + public MutableElement setSquare() { + IntegerPolynomial.this.square(limbs, limbs); + summand = true; + return this; + } + + } + + class ImmutableElement extends Element implements ImmutableIntegerModuloP { + + protected ImmutableElement(BigInteger v) { + super(v); + } + + protected ImmutableElement(boolean v) { + super(v); + } + + protected ImmutableElement(long[] limbs, boolean summand) { + super(limbs, summand); + } + + @Override + public ImmutableElement fixed() { + return this; + } + + } + + class Limb implements SmallValue { + int value; + + Limb(int value) { + this.value = value; + } + } + + +} diff --git a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java new file mode 100644 index 00000000000..5bdadc4c0a0 --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math.intpoly; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.math.BigInteger; +import java.nio.*; + +/** + * An IntegerFieldModuloP designed for use with the Poly1305 authenticator. + * The representation uses 5 signed long values. + * + * In addition to the branch-free operations specified in the parent class, + * the following operations are branch-free: + * + * addModPowerTwo + * asByteArray + * + */ + +public class IntegerPolynomial1305 extends IntegerPolynomial { + + protected static final int SUBTRAHEND = 5; + protected static final int NUM_LIMBS = 5; + private static final int POWER = 130; + private static final int BITS_PER_LIMB = 26; + private static final BigInteger MODULUS + = TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND)); + + private final long[] posModLimbs; + + private long[] setPosModLimbs() { + long[] result = new long[NUM_LIMBS]; + setLimbsValuePositive(MODULUS, result); + return result; + } + + public IntegerPolynomial1305() { + super(BITS_PER_LIMB, NUM_LIMBS, MODULUS); + posModLimbs = setPosModLimbs(); + } + + protected void mult(long[] a, long[] b, long[] r) { + + // Use grade-school multiplication into primitives to avoid the + // temporary array allocation. This is equivalent to the following + // code: + // long[] c = new long[2 * NUM_LIMBS - 1]; + // for(int i = 0; i < NUM_LIMBS; i++) { + // for(int j - 0; j < NUM_LIMBS; j++) { + // c[i + j] += a[i] * b[j] + // } + // } + + long c0 = (a[0] * b[0]); + long c1 = (a[0] * b[1]) + (a[1] * b[0]); + long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]); + long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]); + long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]); + long c5 = (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]); + long c6 = (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]); + long c7 = (a[3] * b[4]) + (a[4] * b[3]); + long c8 = (a[4] * b[4]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8); + } + + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, + long c4, long c5, long c6, long c7, long c8) { + //reduce(2, 2) + r[2] = c2 + (c7 * SUBTRAHEND); + c3 += (c8 * SUBTRAHEND); + + // carry(3, 2) + long carry3 = carryValue(c3); + r[3] = c3 - (carry3 << BITS_PER_LIMB); + c4 += carry3; + + long carry4 = carryValue(c4); + r[4] = c4 - (carry4 << BITS_PER_LIMB); + c5 += carry4; + + // reduce(0, 2) + r[0] = c0 + (c5 * SUBTRAHEND); + r[1] = c1 + (c6 * SUBTRAHEND); + + // carry(0, 4) + carry(r); + } + + protected void multByInt(long[] a, long b, long[] r) { + + for (int i = 0; i < a.length; i++) { + r[i] = a[i] * b; + } + + reduce(r); + } + + @Override + protected void square(long[] a, long[] r) { + // Use grade-school multiplication with a simple squaring optimization. + // Multiply into primitives to avoid the temporary array allocation. + // This is equivalent to the following code: + // long[] c = new long[2 * NUM_LIMBS - 1]; + // for(int i = 0; i < NUM_LIMBS; i++) { + // c[2 * i] = a[i] * a[i]; + // for(int j = i + 1; j < NUM_LIMBS; j++) { + // c[i + j] += 2 * a[i] * a[j] + // } + // } + + long c0 = (a[0] * a[0]); + long c1 = 2 * (a[0] * a[1]); + long c2 = 2 * (a[0] * a[2]) + (a[1] * a[1]); + long c3 = 2 * (a[0] * a[3] + a[1] * a[2]); + long c4 = 2 * (a[0] * a[4] + a[1] * a[3]) + (a[2] * a[2]); + long c5 = 2 * (a[1] * a[4] + a[2] * a[3]); + long c6 = 2 * (a[2] * a[4]) + (a[3] * a[3]); + long c7 = 2 * (a[3] * a[4]); + long c8 = (a[4] * a[4]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8); + } + + @Override + protected void encode(ByteBuffer buf, int length, byte highByte, + long[] result) { + if (length == 16) { + long low = buf.getLong(); + long high = buf.getLong(); + encode(high, low, highByte, result); + } else { + super.encode(buf, length, highByte, result); + } + } + + protected void encode(long high, long low, byte highByte, long[] result) { + result[0] = low & 0x3FFFFFFL; + result[1] = (low >>> 26) & 0x3FFFFFFL; + result[2] = (low >>> 52) + ((high & 0x3FFFL) << 12); + result[3] = (high >>> 14) & 0x3FFFFFFL; + result[4] = (high >>> 40) + (highByte << 24L); + } + + private static final VarHandle AS_LONG_LE = MethodHandles + .byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN); + + protected void encode(byte[] v, int offset, int length, byte highByte, + long[] result) { + if (length == 16) { + long low = (long) AS_LONG_LE.get(v, offset); + long high = (long) AS_LONG_LE.get(v, offset + 8); + encode(high, low, highByte, result); + } else { + super.encode(v, offset, length, highByte, result); + } + } + + protected void modReduceIn(long[] limbs, int index, long x) { + // this only works when BITS_PER_LIMB * NUM_LIMBS = POWER exactly + long reducedValue = (x * SUBTRAHEND); + limbs[index - NUM_LIMBS] += reducedValue; + } + + protected final void modReduce(long[] limbs, int start, int end) { + + for (int i = start; i < end; i++) { + modReduceIn(limbs, i, limbs[i]); + limbs[i] = 0; + } + } + + protected void modReduce(long[] limbs) { + + modReduce(limbs, NUM_LIMBS, NUM_LIMBS - 1); + } + + @Override + protected long carryValue(long x) { + // This representation has plenty of extra space, so we can afford to + // do a simplified carry operation that is more time-efficient. + + return x >> BITS_PER_LIMB; + } + + + protected void reduce(long[] limbs) { + long carry3 = carryOut(limbs, 3); + long new4 = carry3 + limbs[4]; + + long carry4 = carryValue(new4); + limbs[4] = new4 - (carry4 << BITS_PER_LIMB); + + modReduceIn(limbs, 5, carry4); + carry(limbs); + } + + // Convert reduced limbs into a number between 0 and MODULUS-1 + private void finalReduce(long[] limbs) { + + addLimbs(limbs, posModLimbs, limbs); + // now all values are positive, so remaining operations will be unsigned + + // unsigned carry out of last position and reduce in to first position + long carry = limbs[NUM_LIMBS - 1] >> BITS_PER_LIMB; + limbs[NUM_LIMBS - 1] -= carry << BITS_PER_LIMB; + modReduceIn(limbs, NUM_LIMBS, carry); + + // unsigned carry on all positions + carry = 0; + for (int i = 0; i < NUM_LIMBS; i++) { + limbs[i] += carry; + carry = limbs[i] >> BITS_PER_LIMB; + limbs[i] -= carry << BITS_PER_LIMB; + } + // reduce final carry value back in + modReduceIn(limbs, NUM_LIMBS, carry); + // we only reduce back in a nonzero value if some value was carried out + // of the previous loop. So at least one remaining value is small. + + // One more carry is all that is necessary. Nothing will be carried out + // at the end + carry = 0; + for (int i = 0; i < NUM_LIMBS; i++) { + limbs[i] += carry; + carry = limbs[i] >> BITS_PER_LIMB; + limbs[i] -= carry << BITS_PER_LIMB; + } + + // limbs are positive and all less than 2^BITS_PER_LIMB + // but the value may be greater than the MODULUS. + // Subtract the max limb values only if all limbs end up non-negative + int smallerNonNegative = 1; + long[] smaller = new long[NUM_LIMBS]; + for (int i = NUM_LIMBS - 1; i >= 0; i--) { + smaller[i] = limbs[i] - posModLimbs[i]; + // expression on right is 1 if smaller[i] is nonnegative, + // 0 otherwise + smallerNonNegative *= (int) (smaller[i] >> 63) + 1; + } + conditionalSwap(smallerNonNegative, limbs, smaller); + + } + + @Override + protected void limbsToByteArray(long[] limbs, byte[] result) { + + long[] reducedLimbs = limbs.clone(); + finalReduce(reducedLimbs); + + decode(reducedLimbs, result, 0, result.length); + } + + @Override + protected void addLimbsModPowerTwo(long[] limbs, long[] other, + byte[] result) { + + long[] reducedOther = other.clone(); + long[] reducedLimbs = limbs.clone(); + finalReduce(reducedLimbs); + + addLimbs(reducedLimbs, reducedOther, reducedLimbs); + + // may carry out a value which can be ignored + long carry = 0; + for (int i = 0; i < NUM_LIMBS; i++) { + reducedLimbs[i] += carry; + carry = reducedLimbs[i] >> BITS_PER_LIMB; + reducedLimbs[i] -= carry << BITS_PER_LIMB; + } + + decode(reducedLimbs, result, 0, result.length); + } + +} + diff --git a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java new file mode 100644 index 00000000000..837581c47b2 --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math.intpoly; + +import java.math.BigInteger; + +public class IntegerPolynomial25519 extends IntegerPolynomial { + + private static final int POWER = 255; + private static final int SUBTRAHEND = 19; + private static final int NUM_LIMBS = 10; + private static final int BITS_PER_LIMB = 26; + public static final BigInteger MODULUS + = TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND)); + + // BITS_PER_LIMB does not divide POWER, so reduction is a bit complicated + // The constants below help split up values during reduction + private static final int BIT_OFFSET = NUM_LIMBS * BITS_PER_LIMB - POWER; + private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB); + private static final int RIGHT_BIT_OFFSET = BITS_PER_LIMB - BIT_OFFSET; + + public IntegerPolynomial25519() { + super(BITS_PER_LIMB, NUM_LIMBS, MODULUS); + } + + @Override + protected void mult(long[] a, long[] b, long[] r) { + + // Use grade-school multiplication into primitives to avoid the + // temporary array allocation. This is equivalent to the following + // code: + // long[] c = new long[2 * NUM_LIMBS - 1]; + // for(int i = 0; i < NUM_LIMBS; i++) { + // for(int j - 0; j < NUM_LIMBS; j++) { + // c[i + j] += a[i] * b[j] + // } + // } + + long c0 = (a[0] * b[0]); + long c1 = (a[0] * b[1]) + (a[1] * b[0]); + long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]); + long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]); + long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]); + long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]); + long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]); + long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]); + long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]); + long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]); + long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]); + long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]); + long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]); + long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]); + long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]); + long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]); + long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]); + long c17 = (a[8] * b[9]) + (a[9] * b[8]); + long c18 = a[9] * b[9]; + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, + c9, c10, c11, c12, c13, c14, c15, c16, c17, c18); + + } + + private void carryReduce(long[] r, long c0, long c1, long c2, + long c3, long c4, long c5, long c6, + long c7, long c8, long c9, long c10, + long c11, long c12, long c13, long c14, + long c15, long c16, long c17, long c18) { + // reduce(7,2) + long reducedValue17 = (c17 * SUBTRAHEND); + c7 += (reducedValue17 << BIT_OFFSET) & LIMB_MASK; + c8 += reducedValue17 >> RIGHT_BIT_OFFSET; + + long reducedValue18 = (c18 * SUBTRAHEND); + c8 += (reducedValue18 << BIT_OFFSET) & LIMB_MASK; + c9 += reducedValue18 >> RIGHT_BIT_OFFSET; + + // carry(8,2) + long carry8 = carryValue(c8); + r[8] = c8 - (carry8 << BITS_PER_LIMB); + c9 += carry8; + + long carry9 = carryValue(c9); + r[9] = c9 - (carry9 << BITS_PER_LIMB); + c10 += carry9; + + // reduce(0,7) + long reducedValue10 = (c10 * SUBTRAHEND); + r[0] = c0 + ((reducedValue10 << BIT_OFFSET) & LIMB_MASK); + c1 += reducedValue10 >> RIGHT_BIT_OFFSET; + + long reducedValue11 = (c11 * SUBTRAHEND); + r[1] = c1 + ((reducedValue11 << BIT_OFFSET) & LIMB_MASK); + c2 += reducedValue11 >> RIGHT_BIT_OFFSET; + + long reducedValue12 = (c12 * SUBTRAHEND); + r[2] = c2 + ((reducedValue12 << BIT_OFFSET) & LIMB_MASK); + c3 += reducedValue12 >> RIGHT_BIT_OFFSET; + + long reducedValue13 = (c13 * SUBTRAHEND); + r[3] = c3 + ((reducedValue13 << BIT_OFFSET) & LIMB_MASK); + c4 += reducedValue13 >> RIGHT_BIT_OFFSET; + + long reducedValue14 = (c14 * SUBTRAHEND); + r[4] = c4 + ((reducedValue14 << BIT_OFFSET) & LIMB_MASK); + c5 += reducedValue14 >> RIGHT_BIT_OFFSET; + + long reducedValue15 = (c15 * SUBTRAHEND); + r[5] = c5 + ((reducedValue15 << BIT_OFFSET) & LIMB_MASK); + c6 += reducedValue15 >> RIGHT_BIT_OFFSET; + + long reducedValue16 = (c16 * SUBTRAHEND); + r[6] = c6 + ((reducedValue16 << BIT_OFFSET) & LIMB_MASK); + r[7] = c7 + (reducedValue16 >> RIGHT_BIT_OFFSET); + + // carry(0,9) + carry(r, 0, 9); + } + + protected void multByInt(long[] a, long b, long[] r) { + for (int i = 0; i < a.length; i++) { + r[i] = a[i] * b; + } + + // carry(8, 2) + long carry8 = carryValue(r[8]); + r[8] -= (carry8 << BITS_PER_LIMB); + r[9] += carry8; + + long carry9 = carryValue(r[9]); + r[9] -= (carry9 << BITS_PER_LIMB); + + // reduce(0, 1) + long reducedValue10 = (carry9 * SUBTRAHEND); + r[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK); + r[1] += reducedValue10 >> RIGHT_BIT_OFFSET; + + // carry(0, 9) + carry(r, 0, 9); + } + + @Override + protected void square(long[] a, long[] r) { + + // Use grade-school multiplication with a simple squaring optimization. + // Multiply into primitives to avoid the temporary array allocation. + // This is equivalent to the following code: + // long[] c = new long[2 * NUM_LIMBS - 1]; + // for(int i = 0; i < NUM_LIMBS; i++) { + // c[2 * i] = a[i] * a[i]; + // for(int j = i + 1; j < NUM_LIMBS; j++) { + // c[i + j] += 2 * a[i] * a[j] + // } + // } + + long c0 = a[0] * a[0]; + long c1 = 2 * a[0] * a[1]; + long c2 = a[1] * a[1] + 2 * a[0] * a[2]; + long c3 = 2 * (a[0] * a[3] + a[1] * a[2]); + long c4 = a[2] * a[2] + 2 * (a[0] * a[4] + a[1] * a[3]); + long c5 = 2 * (a[0] * a[5] + a[1] * a[4] + a[2] * a[3]); + long c6 = a[3] * a[3] + 2 * (a[0] * a[6] + a[1] * a[5] + a[2] * a[4]); + long c7 = 2 * (a[0] * a[7] + a[1] * a[6] + a[2] * a[5] + a[3] * a[4]); + long c8 = a[4] * a[4] + 2 * (a[0] * a[8] + a[1] * a[7] + a[2] * a[6] + a[3] * a[5]); + long c9 = 2 * (a[0] * a[9] + a[1] * a[8] + a[2] * a[7] + a[3] * a[6] + a[4] * a[5]); + long c10 = a[5] * a[5] + 2 * (a[1] * a[9] + a[2] * a[8] + a[3] * a[7] + a[4] * a[6]); + long c11 = 2 * (a[2] * a[9] + a[3] * a[8] + a[4] * a[7] + a[5] * a[6]); + long c12 = a[6] * a[6] + 2 * (a[3] * a[9] + a[4] * a[8] + a[5] * a[7]); + long c13 = 2 * (a[4] * a[9] + a[5] * a[8] + a[6] * a[7]); + long c14 = a[7] * a[7] + 2 * (a[5] * a[9] + a[6] * a[8]); + long c15 = 2 * (a[6] * a[9] + a[7] * a[8]); + long c16 = a[8] * a[8] + 2 * a[7] * a[9]; + long c17 = 2 * a[8] * a[9]; + long c18 = a[9] * a[9]; + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, + c9, c10, c11, c12, c13, c14, c15, c16, c17, c18); + } + + +} diff --git a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java new file mode 100644 index 00000000000..da2fcf7c758 --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.util.math.intpoly; + +import java.math.BigInteger; + +public class IntegerPolynomial448 extends IntegerPolynomial { + + private static final int POWER = 448; + private static final int NUM_LIMBS = 16; + private static final int BITS_PER_LIMB = 28; + public static final BigInteger MODULUS + = TWO.pow(POWER).subtract(TWO.pow(POWER / 2)) + .subtract(BigInteger.valueOf(1)); + + public IntegerPolynomial448() { + super(BITS_PER_LIMB, NUM_LIMBS, MODULUS); + } + + @Override + protected void mult(long[] a, long[] b, long[] r) { + + // Use grade-school multiplication into primitives to avoid the + // temporary array allocation. This is equivalent to the following + // code: + // long[] c = new long[2 * NUM_LIMBS - 1]; + // for(int i = 0; i < NUM_LIMBS; i++) { + // for(int j - 0; j < NUM_LIMBS; j++) { + // c[i + j] += a[i] * b[j] + // } + // } + + long c0 = (a[0] * b[0]); + long c1 = (a[0] * b[1]) + (a[1] * b[0]); + long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]); + long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]); + long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]); + long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]); + long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]); + long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]); + long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]); + long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]); + long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]); + long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]); + long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]); + long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]); + long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]); + long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]); + long c16 = (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]); + long c17 = (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]); + long c18 = (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]); + long c19 = (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]); + long c20 = (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]); + long c21 = (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]); + long c22 = (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]); + long c23 = (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]); + long c24 = (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]); + long c25 = (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]); + long c26 = (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]); + long c27 = (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]); + long c28 = (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]); + long c29 = (a[14] * b[15]) + (a[15] * b[14]); + long c30 = (a[15] * b[15]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, + c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, + c26, c27, c28, c29, c30); + } + + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, + long c4, long c5, long c6, long c7, long c8, + long c9, long c10, long c11, long c12, long c13, + long c14, long c15, long c16, long c17, long c18, + long c19, long c20, long c21, long c22, long c23, + long c24, long c25, long c26, long c27, long c28, + long c29, long c30) { + + // reduce(8, 7) + c8 += c24; + c16 += c24; + + c9 += c25; + c17 += c25; + + c10 += c26; + c18 += c26; + + c11 += c27; + c19 += c27; + + c12 += c28; + c20 += c28; + + c13 += c29; + c21 += c29; + + c14 += c30; + c22 += c30; + + // reduce(4, 4) + r[4] = c4 + c20; + r[12] = c12 + c20; + + r[5] = c5 + c21; + r[13] = c13 + c21; + + r[6] = c6 + c22; + c14 += c22; + + r[7] = c7 + c23; + c15 += c23; + + //carry(14, 2) + long carry14 = carryValue(c14); + r[14] = c14 - (carry14 << BITS_PER_LIMB); + c15 += carry14; + + long carry15 = carryValue(c15); + r[15] = c15 - (carry15 << BITS_PER_LIMB); + c16 += carry15; + + // reduce(0, 4) + r[0] = c0 + c16; + r[8] = c8 + c16; + + r[1] = c1 + c17; + r[9] = c9 + c17; + + r[2] = c2 + c18; + r[10] = c10 + c18; + + r[3] = c3 + c19; + r[11] = c11 + c19; + + // carry(0, 15) + carry(r, 0, 15); + } + + protected void multByInt(long[] a, long b, long[] r) { + for (int i = 0; i < a.length; i++) { + r[i] = a[i] * b; + } + + // carry(14, 2) + long carry14 = carryValue(r[14]); + r[14] -= (carry14 << BITS_PER_LIMB); + r[15] += carry14; + + long carry15 = carryValue(r[15]); + r[15] -= (carry15 << BITS_PER_LIMB); + + // reduce(0, 1) + r[0] += carry15; + r[8] += carry15; + + // carry(0, 15) + carry(r, 0, 15); + } + + @Override + protected void square(long[] a, long[] r) { + + // Use grade-school multiplication with a simple squaring optimization. + // Multiply into primitives to avoid the temporary array allocation. + // This is equivalent to the following code: + // long[] c = new long[2 * NUM_LIMBS - 1]; + // for(int i = 0; i < NUM_LIMBS; i++) { + // c[2 * i] = a[i] * a[i]; + // for(int j = i + 1; j < NUM_LIMBS; j++) { + // c[i + j] += 2 * a[i] * a[j] + // } + // } + + long c0 = a[0] * a[0]; + long c1 = 2 * a[0] * a[1]; + long c2 = a[1] * a[1] + 2 * a[0] * a[2]; + long c3 = 2 * (a[0] * a[3] + a[1] * a[2]); + long c4 = a[2] * a[2] + 2 * (a[0] * a[4] + a[1] * a[3]); + long c5 = 2 * (a[0] * a[5] + a[1] * a[4] + a[2] * a[3]); + long c6 = a[3] * a[3] + 2 * (a[0] * a[6] + a[1] * a[5] + a[2] * a[4]); + long c7 = 2 * (a[0] * a[7] + a[1] * a[6] + a[2] * a[5] + a[3] * a[4]); + long c8 = a[4] * a[4] + 2 * (a[0] * a[8] + a[1] * a[7] + a[2] * a[6] + a[3] * a[5]); + long c9 = 2 * (a[0] * a[9] + a[1] * a[8] + a[2] * a[7] + a[3] * a[6] + a[4] * a[5]); + long c10 = a[5] * a[5] + 2 * (a[0] * a[10] + a[1] * a[9] + a[2] * a[8] + a[3] * a[7] + a[4] * a[6]); + long c11 = 2 * (a[0] * a[11] + a[1] * a[10] + a[2] * a[9] + a[3] * a[8] + a[4] * a[7] + a[5] * a[6]); + long c12 = a[6] * a[6] + 2 * (a[0] * a[12] + a[1] * a[11] + a[2] * a[10] + a[3] * a[9] + a[4] * a[8] + a[5] * a[7]); + long c13 = 2 * (a[0] * a[13] + a[1] * a[12] + a[2] * a[11] + a[3] * a[10] + a[4] * a[9] + a[5] * a[8] + a[6] * a[7]); + long c14 = a[7] * a[7] + 2 * (a[0] * a[14] + a[1] * a[13] + a[2] * a[12] + a[3] * a[11] + a[4] * a[10] + a[5] * a[9] + a[6] * a[8]); + long c15 = 2 * (a[0] * a[15] + a[1] * a[14] + a[2] * a[13] + a[3] * a[12] + a[4] * a[11] + a[5] * a[10] + a[6] * a[9] + a[7] * a[8]); + long c16 = a[8] * a[8] + 2 * (a[1] * a[15] + a[2] * a[14] + a[3] * a[13] + a[4] * a[12] + a[5] * a[11] + a[6] * a[10] + a[7] * a[9]); + long c17 = 2 * (a[2] * a[15] + a[3] * a[14] + a[4] * a[13] + a[5] * a[12] + a[6] * a[11] + a[7] * a[10] + a[8] * a[9]); + long c18 = a[9] * a[9] + 2 * (a[3] * a[15] + a[4] * a[14] + a[5] * a[13] + a[6] * a[12] + a[7] * a[11] + a[8] * a[10]); + long c19 = 2 * (a[4] * a[15] + a[5] * a[14] + a[6] * a[13] + a[7] * a[12] + a[8] * a[11] + a[9] * a[10]); + long c20 = a[10] * a[10] + 2 * (a[5] * a[15] + a[6] * a[14] + a[7] * a[13] + a[8] * a[12] + a[9] * a[11]); + long c21 = 2 * (a[6] * a[15] + a[7] * a[14] + a[8] * a[13] + a[9] * a[12] + a[10] * a[11]); + long c22 = a[11] * a[11] + 2 * (a[7] * a[15] + a[8] * a[14] + a[9] * a[13] + a[10] * a[12]); + long c23 = 2 * (a[8] * a[15] + a[9] * a[14] + a[10] * a[13] + a[11] * a[12]); + long c24 = a[12] * a[12] + 2 * (a[9] * a[15] + a[10] * a[14] + a[11] * a[13]); + long c25 = 2 * (a[10] * a[15] + a[11] * a[14] + a[12] * a[13]); + long c26 = a[13] * a[13] + 2 * (a[11] * a[15] + a[12] * a[14]); + long c27 = 2 * (a[12] * a[15] + a[13] * a[14]); + long c28 = a[14] * a[14] + 2 * a[13] * a[15]; + long c29 = 2 * a[14] * a[15]; + long c30 = a[15] * a[15]; + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, + c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, + c26, c27, c28, c29, c30); + + } + + +} diff --git a/test/jdk/sun/security/util/math/BigIntegerModuloP.java b/test/jdk/sun/security/util/math/BigIntegerModuloP.java new file mode 100644 index 00000000000..ec2f975dbd1 --- /dev/null +++ b/test/jdk/sun/security/util/math/BigIntegerModuloP.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +import sun.security.util.math.*; + +import java.math.BigInteger; +import java.nio.ByteBuffer; + +/** + * Arithmetic in the field of integers modulo a prime value implemented using + * BigInteger. This implementation is very versatile, but it is slow and none + * of the operations are value-independent. This class is intended for use in + * testing and prototyping, and production code should probably use a more + * specialized arithmetic implementation. + */ + +public class BigIntegerModuloP implements IntegerFieldModuloP { + + private final BigInteger p; + + public BigIntegerModuloP(BigInteger p) { + this.p = p; + } + + @Override + public BigInteger getSize() { + return p; + } + + @Override + public ImmutableElement get0() { + return new ImmutableElement(BigInteger.ZERO); + } + @Override + public ImmutableElement get1() { + return new ImmutableElement(BigInteger.ONE); + } + @Override + public ImmutableElement getElement(BigInteger v) { + return new ImmutableElement(v); + } + @Override + public ImmutableElement getElement(byte[] v, int offset, int length, + byte highByte) { + byte[] bigIntIn = new byte[length + 1]; + System.arraycopy(v, offset, bigIntIn, 0, length); + bigIntIn[length] = highByte; + reverse(bigIntIn); + return new ImmutableElement(new BigInteger(1, bigIntIn).mod(getSize())); + } + @Override + public SmallValue getSmallValue(int i) { + return new SmallElement(i); + } + + private abstract class Element implements IntegerModuloP { + + protected BigInteger v; + + protected Element(BigInteger v) { + this.v = v; + } + + protected Element(boolean v) { + this.v = BigInteger.valueOf(v ? 1 : 0); + } + + private BigInteger getModulus() { + return getField().getSize(); + } + + @Override + public IntegerFieldModuloP getField() { + return BigIntegerModuloP.this; + } + + @Override + public BigInteger asBigInteger() { + return v; + } + + @Override + public MutableElement mutable() { + return new MutableElement(v); + } + + @Override + public ImmutableElement fixed() { + return new ImmutableElement(v); + } + + @Override + public ImmutableElement add(IntegerModuloP b) { + return new ImmutableElement( + v.add(b.asBigInteger()).mod(getModulus())); + } + + @Override + public ImmutableElement additiveInverse() { + return new ImmutableElement(v.negate().mod(getModulus())); + } + + @Override + public ImmutableElement multiply(IntegerModuloP b) { + return new ImmutableElement( + v.multiply(b.asBigInteger()).mod(getModulus())); + } + + @Override + public void addModPowerTwo(IntegerModuloP arg, byte[] result) { + BigInteger biThis = asBigInteger(); + BigInteger biArg = arg.asBigInteger(); + bigIntAsByteArray(biThis.add(biArg), result); + } + + private void bigIntAsByteArray(BigInteger arg, byte[] result) { + byte[] bytes = arg.toByteArray(); + // bytes is backwards and possibly too big + // Copy the low-order bytes into result in reverse + int sourceIndex = bytes.length - 1; + for (int i = 0; i < result.length; i++) { + if (sourceIndex >= 0) { + result[i] = bytes[sourceIndex--]; + } else { + result[i] = 0; + } + } + } + + @Override + public void asByteArray(byte[] result) { + bigIntAsByteArray(v, result); + } + } + + private class ImmutableElement extends Element + implements ImmutableIntegerModuloP { + + private ImmutableElement(BigInteger v) { + super(v); + } + } + + private class MutableElement extends Element + implements MutableIntegerModuloP { + + private MutableElement(BigInteger v) { + super(v); + } + + @Override + public void conditionalSwapWith(MutableIntegerModuloP b, int swap) { + if (swap == 1) { + BigInteger temp = v; + v = b.asBigInteger(); + ((Element) b).v = temp; + } + } + + @Override + public MutableElement setValue(IntegerModuloP v) { + this.v = ((Element) v).v; + + return this; + } + + @Override + public MutableElement setValue(byte[] arr, int offset, int length, + byte highByte) { + byte[] bigIntIn = new byte[length + 1]; + System.arraycopy(arr, offset, bigIntIn, 0, length); + bigIntIn[length] = highByte; + reverse(bigIntIn); + v = new BigInteger(bigIntIn).mod(getSize()); + + return this; + } + + @Override + public MutableElement setValue(ByteBuffer buf, int length, + byte highByte) { + byte[] bigIntIn = new byte[length + 1]; + buf.get(bigIntIn, 0, length); + bigIntIn[length] = highByte; + reverse(bigIntIn); + v = new BigInteger(bigIntIn).mod(getSize()); + + return this; + } + + @Override + public MutableElement setSquare() { + v = v.multiply(v).mod(getSize()); + return this; + } + + @Override + public MutableElement setProduct(IntegerModuloP b) { + Element other = (Element) b; + v = v.multiply(other.v).mod(getSize()); + return this; + } + + @Override + public MutableElement setProduct(SmallValue value) { + BigInteger bigIntValue = ((SmallElement) value).asBigInteger(); + v = v.multiply(bigIntValue).mod(getSize()); + return this; + } + + @Override + public MutableElement setSum(IntegerModuloP b) { + Element other = (Element) b; + v = v.add(other.v).mod(getSize()); + return this; + } + + @Override + public MutableElement setDifference(IntegerModuloP b) { + Element other = (Element) b; + v = v.subtract(other.v).mod(getSize()); + return this; + } + + } + + private class SmallElement extends ImmutableElement implements SmallValue { + + public SmallElement(int v) { + super(BigInteger.valueOf(v).mod(getSize())); + } + } + + private static void swap(byte[] arr, int i, int j) { + byte tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + private static void reverse(byte [] arr) { + int i = 0; + int j = arr.length - 1; + + while (i < j) { + swap(arr, i, j); + i++; + j--; + } + } + +} diff --git a/test/jdk/sun/security/util/math/TestIntegerModuloP.java b/test/jdk/sun/security/util/math/TestIntegerModuloP.java new file mode 100644 index 00000000000..167888e2a0d --- /dev/null +++ b/test/jdk/sun/security/util/math/TestIntegerModuloP.java @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2018, 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 8181594 + * @summary Test proper operation of integer field arithmetic + * @modules java.base/sun.security.util java.base/sun.security.util.math java.base/sun.security.util.math.intpoly + * @build BigIntegerModuloP + * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial25519 32 0 + * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial448 56 1 + * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial1305 16 2 + */ + +import sun.security.util.math.*; +import java.util.function.*; + +import java.util.*; +import java.math.*; +import java.nio.*; + +public class TestIntegerModuloP { + + static BigInteger TWO = BigInteger.valueOf(2); + + // The test has a list of functions, and it selects randomly from that list + + // The function types + interface ElemFunction extends BiFunction + <MutableIntegerModuloP, IntegerModuloP, IntegerModuloP> { } + interface ElemArrayFunction extends BiFunction + <MutableIntegerModuloP, IntegerModuloP, byte[]> { } + interface TriConsumer <T, U, V> { + void accept(T t, U u, V v); + } + interface ElemSetFunction extends TriConsumer + <MutableIntegerModuloP, IntegerModuloP, byte[]> { } + + // The lists of functions. Multiple lists are needed because the test + // respects the limitations of the arithmetic implementations. + static final List<ElemFunction> ADD_FUNCTIONS = new ArrayList<>(); + static final List<ElemFunction> MULT_FUNCTIONS = new ArrayList<>(); + static final List<ElemArrayFunction> ARRAY_FUNCTIONS = new ArrayList<>(); + static final List<ElemSetFunction> SET_FUNCTIONS = new ArrayList<>(); + + static void setUpFunctions(IntegerFieldModuloP field, int length) { + + ADD_FUNCTIONS.clear(); + MULT_FUNCTIONS.clear(); + SET_FUNCTIONS.clear(); + ARRAY_FUNCTIONS.clear(); + + byte highByte = (byte) + (field.getSize().bitLength() > length * 8 ? 1 : 0); + + // add functions are (im)mutable add/subtract + ADD_FUNCTIONS.add(IntegerModuloP::add); + ADD_FUNCTIONS.add(IntegerModuloP::subtract); + ADD_FUNCTIONS.add(MutableIntegerModuloP::setSum); + ADD_FUNCTIONS.add(MutableIntegerModuloP::setDifference); + // also include functions that return the first/second argument + ADD_FUNCTIONS.add((a, b) -> a); + ADD_FUNCTIONS.add((a, b) -> b); + + // mult functions are (im)mutable multiply and square + MULT_FUNCTIONS.add(IntegerModuloP::multiply); + MULT_FUNCTIONS.add((a, b) -> a.square()); + MULT_FUNCTIONS.add((a, b) -> b.square()); + MULT_FUNCTIONS.add(MutableIntegerModuloP::setProduct); + MULT_FUNCTIONS.add((a, b) -> a.setSquare()); + // also test multiplication by a small value + MULT_FUNCTIONS.add((a, b) -> a.setProduct(b.getField().getSmallValue( + b.asBigInteger().mod(BigInteger.valueOf(262144)).intValue()))); + + // set functions are setValue with various argument types + SET_FUNCTIONS.add((a, b, c) -> a.setValue(b)); + SET_FUNCTIONS.add((a, b, c) -> + a.setValue(c, 0, c.length, (byte) 0)); + SET_FUNCTIONS.add((a, b, c) -> + a.setValue(ByteBuffer.wrap(c, 0, c.length).order(ByteOrder.LITTLE_ENDIAN), + c.length, highByte)); + + // array functions return the (possibly modified) value as byte array + ARRAY_FUNCTIONS.add((a, b ) -> a.asByteArray(length)); + ARRAY_FUNCTIONS.add((a, b) -> a.addModPowerTwo(b, length)); + } + + public static void main(String[] args) { + + String className = args[0]; + final int length = Integer.parseInt(args[1]); + int seed = Integer.parseInt(args[2]); + + Class<IntegerFieldModuloP> fieldBaseClass = IntegerFieldModuloP.class; + try { + Class<? extends IntegerFieldModuloP> clazz = + Class.forName(className).asSubclass(fieldBaseClass); + IntegerFieldModuloP field = + clazz.getDeclaredConstructor().newInstance(); + + setUpFunctions(field, length); + + runFieldTest(field, length, seed); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + + System.out.println("All tests passed"); + } + + + static void assertEqual(IntegerModuloP e1, IntegerModuloP e2) { + + if (!e1.asBigInteger().equals(e2.asBigInteger())) { + throw new RuntimeException("values not equal: " + + e1.asBigInteger() + " != " + e2.asBigInteger()); + } + } + + // A class that holds pairs of actual/expected values, and allows + // computation on these pairs. + static class TestPair<T extends IntegerModuloP> { + private final T test; + private final T baseline; + + public TestPair(T test, T baseline) { + this.test = test; + this.baseline = baseline; + } + + public T getTest() { + return test; + } + public T getBaseline() { + return baseline; + } + + private void assertEqual() { + TestIntegerModuloP.assertEqual(test, baseline); + } + + public TestPair<MutableIntegerModuloP> mutable() { + return new TestPair<>(test.mutable(), baseline.mutable()); + } + + public + <R extends IntegerModuloP, X extends IntegerModuloP> + TestPair<X> apply(BiFunction<T, R, X> func, TestPair<R> right) { + X testResult = func.apply(test, right.test); + X baselineResult = func.apply(baseline, right.baseline); + return new TestPair(testResult, baselineResult); + } + + public + <U extends IntegerModuloP, V> + void apply(TriConsumer<T, U, V> func, TestPair<U> right, V argV) { + func.accept(test, right.test, argV); + func.accept(baseline, right.baseline, argV); + } + + public + <R extends IntegerModuloP> + void applyAndCheckArray(BiFunction<T, R, byte[]> func, + TestPair<R> right) { + byte[] testResult = func.apply(test, right.test); + byte[] baselineResult = func.apply(baseline, right.baseline); + if (!Arrays.equals(testResult, baselineResult)) { + throw new RuntimeException("Array values do not match: " + + byteArrayToHexString(testResult) + " != " + + byteArrayToHexString(baselineResult)); + } + } + + } + + static String byteArrayToHexString(byte[] arr) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < arr.length; ++i) { + byte curVal = arr[i]; + result.append(Character.forDigit(curVal >> 4 & 0xF, 16)); + result.append(Character.forDigit(curVal & 0xF, 16)); + } + return result.toString(); + } + + static TestPair<IntegerModuloP> + applyAndCheck(ElemFunction func, TestPair<MutableIntegerModuloP> left, + TestPair<IntegerModuloP> right) { + + TestPair<IntegerModuloP> result = left.apply(func, right); + result.assertEqual(); + left.assertEqual(); + right.assertEqual(); + + return result; + } + + static void + setAndCheck(ElemSetFunction func, TestPair<MutableIntegerModuloP> left, + TestPair<IntegerModuloP> right, byte[] argV) { + + left.apply(func, right, argV); + left.assertEqual(); + right.assertEqual(); + } + + static TestPair<MutableIntegerModuloP> + applyAndCheckMutable(ElemFunction func, + TestPair<MutableIntegerModuloP> left, + TestPair<IntegerModuloP> right) { + + TestPair<IntegerModuloP> result = applyAndCheck(func, left, right); + + TestPair<MutableIntegerModuloP> mutableResult = result.mutable(); + mutableResult.assertEqual(); + result.assertEqual(); + left.assertEqual(); + right.assertEqual(); + + return mutableResult; + } + + static void + cswapAndCheck(int swap, TestPair<MutableIntegerModuloP> left, + TestPair<MutableIntegerModuloP> right) { + + left.getTest().conditionalSwapWith(right.getTest(), swap); + left.getBaseline().conditionalSwapWith(right.getBaseline(), swap); + + left.assertEqual(); + right.assertEqual(); + + } + + // Request arithmetic that should overflow, and ensure that overflow is + // detected. + static void runOverflowTest(TestPair<IntegerModuloP> elem) { + + TestPair<MutableIntegerModuloP> mutableElem = elem.mutable(); + + try { + for (int i = 0; i < 1000; i++) { + applyAndCheck(MutableIntegerModuloP::setSum, mutableElem, elem); + } + applyAndCheck(MutableIntegerModuloP::setProduct, mutableElem, elem); + } catch (ArithmeticException ex) { + // this is expected + } + + mutableElem = elem.mutable(); + try { + for (int i = 0; i < 1000; i++) { + elem = applyAndCheck(IntegerModuloP::add, + mutableElem, elem); + } + applyAndCheck(IntegerModuloP::multiply, mutableElem, elem); + } catch (ArithmeticException ex) { + // this is expected + } + } + + // Run a large number of random operations and ensure that + // results are correct + static void runOperationsTest(Random random, int length, + TestPair<IntegerModuloP> elem, + TestPair<IntegerModuloP> right) { + + TestPair<MutableIntegerModuloP> left = elem.mutable(); + + for (int i = 0; i < 10000; i++) { + + ElemFunction addFunc1 = + ADD_FUNCTIONS.get(random.nextInt(ADD_FUNCTIONS.size())); + TestPair<MutableIntegerModuloP> result1 = + applyAndCheckMutable(addFunc1, left, right); + + // left could have been modified, so turn it back into a summand + applyAndCheckMutable((a, b) -> a.setSquare(), left, right); + + ElemFunction addFunc2 = + ADD_FUNCTIONS.get(random.nextInt(ADD_FUNCTIONS.size())); + TestPair<IntegerModuloP> result2 = + applyAndCheck(addFunc2, left, right); + + ElemFunction multFunc2 = + MULT_FUNCTIONS.get(random.nextInt(MULT_FUNCTIONS.size())); + TestPair<MutableIntegerModuloP> multResult = + applyAndCheckMutable(multFunc2, result1, result2); + + int swap = random.nextInt(2); + cswapAndCheck(swap, left, multResult); + + ElemSetFunction setFunc = + SET_FUNCTIONS.get(random.nextInt(SET_FUNCTIONS.size())); + byte[] valueArr = new byte[length]; + random.nextBytes(valueArr); + setAndCheck(setFunc, result1, result2, valueArr); + + // left could have been modified, so to turn it back into a summand + applyAndCheckMutable((a, b) -> a.setSquare(), left, right); + + ElemArrayFunction arrayFunc = + ARRAY_FUNCTIONS.get(random.nextInt(ARRAY_FUNCTIONS.size())); + left.applyAndCheckArray(arrayFunc, right); + } + } + + // Run all the tests for a given field + static void runFieldTest(IntegerFieldModuloP testField, + int length, int seed) { + System.out.println("Testing: " + testField.getClass().getSimpleName()); + + Random random = new Random(seed); + + IntegerFieldModuloP baselineField = + new BigIntegerModuloP(testField.getSize()); + + int numBits = testField.getSize().bitLength(); + BigInteger r = + new BigInteger(numBits, random).mod(testField.getSize()); + TestPair<IntegerModuloP> rand = + new TestPair(testField.getElement(r), baselineField.getElement(r)); + + runOverflowTest(rand); + + // check combinations of operations for different kinds of elements + List<TestPair<IntegerModuloP>> testElements = new ArrayList<>(); + testElements.add(rand); + testElements.add(new TestPair(testField.get0(), baselineField.get0())); + testElements.add(new TestPair(testField.get1(), baselineField.get1())); + byte[] testArr = {121, 37, -100, -5, 76, 33}; + testElements.add(new TestPair(testField.getElement(testArr), + baselineField.getElement(testArr))); + + testArr = new byte[length]; + random.nextBytes(testArr); + testElements.add(new TestPair(testField.getElement(testArr), + baselineField.getElement(testArr))); + + random.nextBytes(testArr); + byte highByte = (byte) (numBits > length * 8 ? 1 : 0); + testElements.add( + new TestPair( + testField.getElement(testArr, 0, testArr.length, highByte), + baselineField.getElement(testArr, 0, testArr.length, highByte) + ) + ); + + for (int i = 0; i < testElements.size(); i++) { + for (int j = 0; j < testElements.size(); j++) { + runOperationsTest(random, length, testElements.get(i), + testElements.get(j)); + } + } + } +} + From f5a247a85fbe79ea7365b02b25f888dd4a760d9d Mon Sep 17 00:00:00 2001 From: Adam Petcher <apetcher@openjdk.org> Date: Tue, 8 May 2018 09:47:28 -0400 Subject: [PATCH 39/40] 8171277: Elliptic Curves for Security in Crypto Implementations of X25519 and X448 key agreement in SunEC Reviewed-by: mullan --- .../java/security/interfaces/XECKey.java | 47 + .../security/interfaces/XECPrivateKey.java | 57 + .../security/interfaces/XECPublicKey.java | 56 + .../security/spec/ECGenParameterSpec.java | 30 +- .../security/spec/NamedParameterSpec.java | 81 + .../java/security/spec/XECPrivateKeySpec.java | 82 + .../java/security/spec/XECPublicKeySpec.java | 83 + src/java.base/share/classes/module-info.java | 4 + .../share/classes/sun/security/ec/SunEC.java | 59 +- .../sun/security/ec/XDHKeyAgreement.java | 216 ++ .../sun/security/ec/XDHKeyFactory.java | 243 ++ .../sun/security/ec/XDHKeyPairGenerator.java | 132 ++ .../sun/security/ec/XDHPrivateKeyImpl.java | 91 + .../sun/security/ec/XDHPublicKeyImpl.java | 134 ++ .../sun/security/ec/XECOperations.java | 271 +++ .../sun/security/ec/XECParameters.java | 263 +++ .../provider/KeyAgreement/DHGenSecretKey.java | 72 - .../KeyAgreement/KeyAgreementTest.java | 154 ++ .../security/KeyAgreement/KeySizeTest.java | 238 ++ .../security/KeyAgreement/KeySpecTest.java | 316 +++ .../KeyAgreement/MultiThreadTest.java | 150 ++ .../security/KeyAgreement/NegativeTest.java | 408 ++++ test/jdk/sun/security/ec/xec/TestXDH.java | 490 ++++ test/jdk/sun/security/ec/xec/TestXECOps.java | 130 ++ test/jdk/sun/security/ec/xec/X25519.iter | 2002 +++++++++++++++++ test/jdk/sun/security/ec/xec/X448.iter | 2002 +++++++++++++++++ .../jdk/sun/security/ec/xec/XECIterative.java | 137 ++ test/lib/jdk/test/lib/Convert.java | 85 + 28 files changed, 7938 insertions(+), 95 deletions(-) create mode 100644 src/java.base/share/classes/java/security/interfaces/XECKey.java create mode 100644 src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java create mode 100644 src/java.base/share/classes/java/security/interfaces/XECPublicKey.java create mode 100644 src/java.base/share/classes/java/security/spec/NamedParameterSpec.java create mode 100644 src/java.base/share/classes/java/security/spec/XECPrivateKeySpec.java create mode 100644 src/java.base/share/classes/java/security/spec/XECPublicKeySpec.java create mode 100644 src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java create mode 100644 src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java create mode 100644 src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyPairGenerator.java create mode 100644 src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java create mode 100644 src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java create mode 100644 src/jdk.crypto.ec/share/classes/sun/security/ec/XECOperations.java create mode 100644 src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java delete mode 100644 test/jdk/com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java create mode 100644 test/jdk/java/security/KeyAgreement/KeyAgreementTest.java create mode 100644 test/jdk/java/security/KeyAgreement/KeySizeTest.java create mode 100644 test/jdk/java/security/KeyAgreement/KeySpecTest.java create mode 100644 test/jdk/java/security/KeyAgreement/MultiThreadTest.java create mode 100644 test/jdk/java/security/KeyAgreement/NegativeTest.java create mode 100644 test/jdk/sun/security/ec/xec/TestXDH.java create mode 100644 test/jdk/sun/security/ec/xec/TestXECOps.java create mode 100644 test/jdk/sun/security/ec/xec/X25519.iter create mode 100644 test/jdk/sun/security/ec/xec/X448.iter create mode 100644 test/jdk/sun/security/ec/xec/XECIterative.java create mode 100644 test/lib/jdk/test/lib/Convert.java diff --git a/src/java.base/share/classes/java/security/interfaces/XECKey.java b/src/java.base/share/classes/java/security/interfaces/XECKey.java new file mode 100644 index 00000000000..7412daabd07 --- /dev/null +++ b/src/java.base/share/classes/java/security/interfaces/XECKey.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.security.interfaces; + +import java.security.spec.AlgorithmParameterSpec; + +/** + * An interface for an elliptic curve public/private key as defined by + * RFC 7748. These keys are distinct from the keys represented by + * {@code ECKey}, and they are intended for use with algorithms based on RFC + * 7748 such as the XDH {@code KeyAgreement} algorithm. This interface allows + * access to the algorithm parameters associated with the key. + * + * @since 11 + */ +public interface XECKey { + /** + * Returns the algorithm parameters associated + * with the key. + * + * @return the associated algorithm parameters + */ + AlgorithmParameterSpec getParams(); +} + diff --git a/src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java b/src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java new file mode 100644 index 00000000000..547677786ae --- /dev/null +++ b/src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.security.interfaces; + +import java.security.PrivateKey; +import java.util.Optional; + +/** + * An interface for an elliptic curve private key as defined by RFC 7748. + * These keys are distinct from the keys represented by {@code ECPrivateKey}, + * and they are intended for use with algorithms based on RFC 7748 such as the + * XDH {@code KeyAgreement} algorithm. + * + * An XEC private key is an encoded scalar value as described in RFC 7748. + * The decoding procedure defined in this RFC includes an operation that forces + * certain bits of the key to either 1 or 0. This operation is known as + * "pruning" or "clamping" the private key. Arrays returned by this interface + * are unpruned, and implementations will need to prune the array before + * using it in any numerical operations. + * + * @since 11 + */ +public interface XECPrivateKey extends XECKey, PrivateKey { + + /** + * Get the scalar value encoded as an unpruned byte array. A new copy of + * the array is returned each time this method is called. + * + * @return the unpruned encoded scalar value, or an empty Optional if the + * scalar cannot be extracted (e.g. if the provider is a hardware token + * and the private key is not allowed to leave the crypto boundary). + */ + Optional<byte[]> getScalar(); +} + diff --git a/src/java.base/share/classes/java/security/interfaces/XECPublicKey.java b/src/java.base/share/classes/java/security/interfaces/XECPublicKey.java new file mode 100644 index 00000000000..6ec200beeb9 --- /dev/null +++ b/src/java.base/share/classes/java/security/interfaces/XECPublicKey.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.security.interfaces; + +import java.math.BigInteger; +import java.security.PublicKey; + +/** + * An interface for an elliptic curve public key as defined by RFC 7748. + * These keys are distinct from the keys represented by {@code ECPublicKey}, + * and they are intended for use with algorithms based on RFC 7748 such as the + * XDH {@code KeyAgreement} algorithm. + * + * An XEC public key is a particular point on the curve, which is represented + * using only its u-coordinate as described in RFC 7748. A u-coordinate is an + * element of the field of integers modulo some value that is determined by + * the algorithm parameters. This field element is represented by a BigInteger + * which may hold any value. That is, the BigInteger is not restricted to the + * range of canonical field elements. + * + * @since 11 + */ +public interface XECPublicKey extends XECKey, PublicKey { + + /** + * Get the u coordinate of the point. + * + * @return the u-coordinate, represented using a BigInteger which may hold + * any value + */ + BigInteger getU(); + +} + diff --git a/src/java.base/share/classes/java/security/spec/ECGenParameterSpec.java b/src/java.base/share/classes/java/security/spec/ECGenParameterSpec.java index 4f3f63b873a..2186a816fbf 100644 --- a/src/java.base/share/classes/java/security/spec/ECGenParameterSpec.java +++ b/src/java.base/share/classes/java/security/spec/ECGenParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -34,9 +34,7 @@ package java.security.spec; * * @since 1.5 */ -public class ECGenParameterSpec implements AlgorithmParameterSpec { - - private String name; +public class ECGenParameterSpec extends NamedParameterSpec { /** * Creates a parameter specification for EC parameter @@ -44,25 +42,15 @@ public class ECGenParameterSpec implements AlgorithmParameterSpec { * {@code stdName} in order to generate the corresponding * (precomputed) elliptic curve domain parameters. For the * list of supported names, please consult the documentation - * of provider whose implementation will be used. + * of the provider whose implementation will be used. + * * @param stdName the standard name of the to-be-generated EC - * domain parameters. - * @exception NullPointerException if {@code stdName} - * is null. + * domain parameters. + * @throws NullPointerException if {@code stdName} + * is null. */ public ECGenParameterSpec(String stdName) { - if (stdName == null) { - throw new NullPointerException("stdName is null"); - } - this.name = stdName; - } - - /** - * Returns the standard or predefined name of the - * to-be-generated EC domain parameters. - * @return the standard or predefined name. - */ - public String getName() { - return name; + super(stdName); } } + diff --git a/src/java.base/share/classes/java/security/spec/NamedParameterSpec.java b/src/java.base/share/classes/java/security/spec/NamedParameterSpec.java new file mode 100644 index 00000000000..4e61065eb35 --- /dev/null +++ b/src/java.base/share/classes/java/security/spec/NamedParameterSpec.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.security.spec; + +import java.util.Objects; + +/** + * This class is used to specify any algorithm parameters that are determined + * by a standard name. This class also holds constants for standard parameter + * set names. The names of these constants exactly match the corresponding + * parameter set name. For example, NamedParameterSpec.X25519 represents the + * parameter set identified by the string "X25519". These strings are defined + * in the <a href= + * "{@docRoot}/../specs/security/standard-names.html#parameter-spec-names"> + * Java Security Standard Algorithm Names Specification</a>. + * + * @since 11 + * + */ +public class NamedParameterSpec implements AlgorithmParameterSpec { + + /** + * The X25519 parameters + */ + public static final NamedParameterSpec X25519 + = new NamedParameterSpec("X25519"); + /** + * The X448 parameters + */ + public static final NamedParameterSpec X448 + = new NamedParameterSpec("X448"); + + private String name; + + /** + * Creates a parameter specification using a standard (or predefined) + * name {@code stdName}. For the + * list of supported names, please consult the documentation + * of the provider whose implementation will be used. + * + * @param stdName the standard name of the algorithm parameters + * + * @throws NullPointerException if {@code stdName} + * is null. + */ + public NamedParameterSpec(String stdName) { + Objects.requireNonNull(stdName, "stdName must not be null"); + + this.name = stdName; + } + + /** + * Returns the standard name that determines the algorithm parameters. + * @return the standard name. + */ + public String getName() { + return name; + } +} diff --git a/src/java.base/share/classes/java/security/spec/XECPrivateKeySpec.java b/src/java.base/share/classes/java/security/spec/XECPrivateKeySpec.java new file mode 100644 index 00000000000..02687b50a0e --- /dev/null +++ b/src/java.base/share/classes/java/security/spec/XECPrivateKeySpec.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.security.spec; + +import java.util.Objects; + +/** + * A class representing elliptic curve private keys as defined in RFC 7748, + * including the curve and other algorithm parameters. The private key is + * represented as an encoded scalar value. The decoding procedure defined in + * the RFC includes an operation that forces certain bits of the key to either + * 1 or 0. This operation is known as "pruning" or "clamping" the private key. + * All arrays in this spec are unpruned, and implementations will need to prune + * the array before using it in any numerical operations. + * + * @since 11 + */ +public class XECPrivateKeySpec implements KeySpec { + + private final AlgorithmParameterSpec params; + private final byte[] scalar; + + /** + * Construct a private key spec using the supplied parameters and + * encoded scalar value. + * + * @param params the algorithm parameters + * @param scalar the unpruned encoded scalar value. This array is copied + * to protect against subsequent modification. + * + * @throws NullPointerException if {@code params} or {@code scalar} + * is null. + */ + public XECPrivateKeySpec(AlgorithmParameterSpec params, byte[] scalar) { + Objects.requireNonNull(params, "params must not be null"); + Objects.requireNonNull(scalar, "scalar must not be null"); + + this.params = params; + this.scalar = scalar.clone(); + } + + /** + * Get the algorithm parameters that define the curve and other settings. + * + * @return the algorithm parameters + */ + public AlgorithmParameterSpec getParams() { + return params; + } + + /** + * Get the scalar value encoded as an unpruned byte array. A new copy of + * the array is returned each time this method is called. + * + * @return the unpruned encoded scalar value + */ + public byte[] getScalar() { + return scalar.clone(); + } +} diff --git a/src/java.base/share/classes/java/security/spec/XECPublicKeySpec.java b/src/java.base/share/classes/java/security/spec/XECPublicKeySpec.java new file mode 100644 index 00000000000..162cf10e9eb --- /dev/null +++ b/src/java.base/share/classes/java/security/spec/XECPublicKeySpec.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.security.spec; + +import java.math.BigInteger; +import java.util.Objects; + +/** + * A class representing elliptic curve public keys as defined in RFC 7748, + * including the curve and other algorithm parameters. The public key is a + * particular point on the curve, which is represented using only its + * u-coordinate. A u-coordinate is an element of the field of integers modulo + * some value that is determined by the algorithm parameters. This field + * element is represented by a BigInteger which may hold any value. That is, + * the BigInteger is not restricted to the range of canonical field elements. + * + * @since 11 + */ +public class XECPublicKeySpec implements KeySpec { + + private final AlgorithmParameterSpec params; + private final BigInteger u; + + /** + * Construct a public key spec using the supplied parameters and + * u coordinate. + * + * @param params the algorithm parameters + * @param u the u-coordinate of the point, represented using a BigInteger + * which may hold any value + * + * @throws NullPointerException if {@code params} or {@code u} + * is null. + */ + public XECPublicKeySpec(AlgorithmParameterSpec params, BigInteger u) { + Objects.requireNonNull(params, "params must not be null"); + Objects.requireNonNull(u, "u must not be null"); + + this.params = params; + this.u = u; + } + + /** + * Get the algorithm parameters that define the curve and other settings. + * + * @return the parameters + */ + public AlgorithmParameterSpec getParams() { + return params; + } + + /** + * Get the u coordinate of the point. + * + * @return the u-coordinate, represented using a BigInteger which may hold + * any value + */ + public BigInteger getU() { + return u; + } +} diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index a32e332efc7..e93cc4adcf9 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -289,6 +289,10 @@ module java.base { jdk.jartool, jdk.security.auth, jdk.security.jgss; + exports sun.security.util.math to + jdk.crypto.ec + exports sun.security.util.math.intpoly to + jdk.crypto.ec exports sun.security.x509 to jdk.crypto.ec, jdk.crypto.cryptoki, diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java index 84b4df581aa..09be69ecc46 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2018, 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 @@ -30,7 +30,7 @@ import java.security.*; import java.util.regex.Pattern; import sun.security.util.CurveDB; import sun.security.util.NamedCurve; -import sun.security.util.ECParameters; + import static sun.security.util.SecurityConstants.PROVIDER_VER; /** @@ -119,6 +119,12 @@ public final class SunEC extends Provider { } else if (type.equals("KeyFactory")) { if (algo.equals("EC")) { return new ECKeyFactory(); + } else if (algo.equals("XDH")) { + return new XDHKeyFactory(); + } else if (algo.equals("X25519")) { + return new XDHKeyFactory.X25519(); + } else if (algo.equals("X448")) { + return new XDHKeyFactory.X448(); } } else if (type.equals("AlgorithmParameters")) { if (algo.equals("EC")) { @@ -127,10 +133,22 @@ public final class SunEC extends Provider { } else if (type.equals("KeyPairGenerator")) { if (algo.equals("EC")) { return new ECKeyPairGenerator(); + } else if (algo.equals("XDH")) { + return new XDHKeyPairGenerator(); + } else if (algo.equals("X25519")) { + return new XDHKeyPairGenerator.X25519(); + } else if (algo.equals("X448")) { + return new XDHKeyPairGenerator.X448(); } } else if (type.equals("KeyAgreement")) { if (algo.equals("ECDH")) { return new ECDHKeyAgreement(); + } else if (algo.equals("XDH")) { + return new XDHKeyAgreement(); + } else if (algo.equals("X25519")) { + return new XDHKeyAgreement.X25519(); + } else if (algo.equals("X448")) { + return new XDHKeyAgreement.X448(); } } } catch (Exception ex) { @@ -205,6 +223,8 @@ public final class SunEC extends Provider { new String[] { "EllipticCurve", "1.2.840.10045.2.1", "OID.1.2.840.10045.2.1" }, apAttrs)); + putXDHEntries(); + /* * Register the algorithms below only when the full ECC implementation * is available @@ -272,4 +292,39 @@ public final class SunEC extends Provider { putService(new ProviderService(this, "KeyAgreement", "ECDH", "sun.security.ec.ECDHKeyAgreement", null, ATTRS)); } + + private void putXDHEntries() { + + HashMap<String, String> ATTRS = new HashMap<>(1); + ATTRS.put("ImplementedIn", "Software"); + + /* XDH does not require native implementation */ + putService(new ProviderService(this, "KeyFactory", + "XDH", "sun.security.ec.XDHKeyFactory", null, ATTRS)); + putService(new ProviderService(this, "KeyFactory", + "X25519", "sun.security.ec.XDHKeyFactory.X25519", + new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); + putService(new ProviderService(this, "KeyFactory", + "X448", "sun.security.ec.XDHKeyFactory.X448", + new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); + + putService(new ProviderService(this, "KeyPairGenerator", + "XDH", "sun.security.ec.XDHKeyPairGenerator", null, ATTRS)); + putService(new ProviderService(this, "KeyPairGenerator", + "X25519", "sun.security.ec.XDHKeyPairGenerator.X25519", + new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); + putService(new ProviderService(this, "KeyPairGenerator", + "X448", "sun.security.ec.XDHKeyPairGenerator.X448", + new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); + + putService(new ProviderService(this, "KeyAgreement", + "XDH", "sun.security.ec.XDHKeyAgreement", null, ATTRS)); + putService(new ProviderService(this, "KeyAgreement", + "X25519", "sun.security.ec.XDHKeyAgreement.X25519", + new String[]{"1.3.101.110", "OID.1.3.101.110"}, ATTRS)); + putService(new ProviderService(this, "KeyAgreement", + "X448", "sun.security.ec.XDHKeyAgreement.X448", + new String[]{"1.3.101.111", "OID.1.3.101.111"}, ATTRS)); + + } } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java new file mode 100644 index 00000000000..43da079e961 --- /dev/null +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.ec; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.Key; +import java.security.SecureRandom; +import java.security.ProviderException; +import java.security.interfaces.XECPrivateKey; +import java.security.interfaces.XECPublicKey; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; +import javax.crypto.KeyAgreementSpi; +import javax.crypto.SecretKey; +import javax.crypto.ShortBufferException; +import java.util.function.Function; + +public class XDHKeyAgreement extends KeyAgreementSpi { + + private byte[] privateKey; + private byte[] secret; + private XECOperations ops; + private XECParameters lockedParams = null; + + XDHKeyAgreement() { + // do nothing + } + + XDHKeyAgreement(AlgorithmParameterSpec paramSpec) { + lockedParams = XECParameters.get(ProviderException::new, paramSpec); + } + + @Override + protected void engineInit(Key key, SecureRandom random) + throws InvalidKeyException { + + initImpl(key); + } + + @Override + protected void engineInit(Key key, final AlgorithmParameterSpec params, + SecureRandom random) throws InvalidKeyException, + InvalidAlgorithmParameterException { + + initImpl(key); + + // the private key parameters must match params + XECParameters xecParams = XECParameters.get( + InvalidAlgorithmParameterException::new, params); + if (!xecParams.oidEquals(this.ops.getParameters())) { + throw new InvalidKeyException( + "Incorrect private key parameters" + ); + } + } + + private + <T extends Throwable> + void checkLockedParams(Function<String, T> exception, + XECParameters params) throws T { + + if (lockedParams != null && lockedParams != params) { + throw exception.apply("Parameters must be " + + lockedParams.getName()); + } + } + + private void initImpl(Key key) throws InvalidKeyException { + + if (!(key instanceof XECPrivateKey)) { + throw new InvalidKeyException + ("Unsupported key type"); + } + XECPrivateKey privateKey = (XECPrivateKey) key; + XECParameters xecParams = XECParameters.get( + InvalidKeyException::new, privateKey.getParams()); + checkLockedParams(InvalidKeyException::new, xecParams); + + this.ops = new XECOperations(xecParams); + this.privateKey = privateKey.getScalar().orElseThrow( + () -> new InvalidKeyException("No private key value") + ); + secret = null; + } + + @Override + protected Key engineDoPhase(Key key, boolean lastPhase) + throws InvalidKeyException, IllegalStateException { + + if (this.privateKey == null) { + throw new IllegalStateException("Not initialized"); + } + if (this.secret != null) { + throw new IllegalStateException("Phase already executed"); + } + if (!lastPhase) { + throw new IllegalStateException + ("Only two party agreement supported, lastPhase must be true"); + } + if (!(key instanceof XECPublicKey)) { + throw new InvalidKeyException + ("Unsupported key type"); + } + + XECPublicKey publicKey = (XECPublicKey) key; + + // Ensure public key parameters are compatible with private key + XECParameters xecParams = XECParameters.get(InvalidKeyException::new, + publicKey.getParams()); + if (!ops.getParameters().oidEquals(xecParams)) { + throw new InvalidKeyException( + "Public key parameters are not compatible with private key."); + } + + // The privateKey may be modified to a value that is equivalent for + // the purposes of this algorithm. + byte[] computedSecret = ops.encodedPointMultiply( + this.privateKey, + publicKey.getU()); + + // test for contributory behavior + if (allZero(computedSecret)) { + throw new InvalidKeyException("Point has small order"); + } + + this.secret = computedSecret; + + return null; + } + + /* + * Constant-time check for an all-zero array + */ + private boolean allZero(byte[] arr) { + byte orValue = (byte) 0; + for (int i = 0; i < arr.length; i++) { + orValue |= arr[i]; + } + + return orValue == (byte) 0; + } + + @Override + protected byte[] engineGenerateSecret() throws IllegalStateException { + if (secret == null) { + throw new IllegalStateException("Not initialized correctly"); + } + + return secret.clone(); + } + + @Override + protected int engineGenerateSecret(byte[] sharedSecret, int offset) + throws IllegalStateException, ShortBufferException { + + if (secret == null) { + throw new IllegalStateException("Not initialized correctly"); + } + int secretLen = this.secret.length; + if (offset + secretLen > sharedSecret.length) { + throw new ShortBufferException("Need " + secretLen + + " bytes, only " + (sharedSecret.length - offset) + + " available"); + } + + System.arraycopy(this.secret, 0, sharedSecret, offset, secretLen); + return secret.length; + } + + @Override + protected SecretKey engineGenerateSecret(String algorithm) + throws IllegalStateException, NoSuchAlgorithmException, + InvalidKeyException { + + throw new NoSuchAlgorithmException("Not supported"); + } + + static class X25519 extends XDHKeyAgreement { + + public X25519() { + super(NamedParameterSpec.X25519); + } + } + + static class X448 extends XDHKeyAgreement { + + public X448() { + super(NamedParameterSpec.X448); + } + } +} diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java new file mode 100644 index 00000000000..e327b9b46f0 --- /dev/null +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.ec; + +import java.security.KeyFactorySpi; +import java.security.Key; +import java.security.PublicKey; +import java.security.PrivateKey; +import java.security.InvalidKeyException; +import java.security.ProviderException; +import java.security.interfaces.XECKey; +import java.security.interfaces.XECPrivateKey; +import java.security.interfaces.XECPublicKey; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; +import java.security.spec.KeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.security.spec.XECPublicKeySpec; +import java.security.spec.XECPrivateKeySpec; +import java.util.function.Function; + +public class XDHKeyFactory extends KeyFactorySpi { + + private XECParameters lockedParams = null; + + XDHKeyFactory() { + // do nothing + } + + protected XDHKeyFactory(AlgorithmParameterSpec paramSpec) { + lockedParams = XECParameters.get(ProviderException::new, paramSpec); + } + + @Override + protected Key engineTranslateKey(Key key) throws InvalidKeyException { + + if (key == null) { + throw new InvalidKeyException("Key must not be null"); + } + + if (key instanceof XECKey) { + XECKey xecKey = (XECKey) key; + XECParameters params = XECParameters.get(InvalidKeyException::new, + xecKey.getParams()); + checkLockedParams(InvalidKeyException::new, params); + + if (xecKey instanceof XECPublicKey) { + XECPublicKey publicKey = (XECPublicKey) xecKey; + return new XDHPublicKeyImpl(params, publicKey.getU()); + } else if (xecKey instanceof XECPrivateKey) { + XECPrivateKey privateKey = (XECPrivateKey) xecKey; + byte[] scalar = privateKey.getScalar().orElseThrow( + () -> new InvalidKeyException("No private key data")); + return new XDHPrivateKeyImpl(params, scalar); + } else { + throw new InvalidKeyException("Unsupported XECKey subclass"); + } + } else if (key instanceof PublicKey && + key.getFormat().equals("X.509")) { + XDHPublicKeyImpl result = new XDHPublicKeyImpl(key.getEncoded()); + checkLockedParams(InvalidKeyException::new, result.getParams()); + return result; + } else if (key instanceof PrivateKey && + key.getFormat().equals("PKCS#8")) { + XDHPrivateKeyImpl result = new XDHPrivateKeyImpl(key.getEncoded()); + checkLockedParams(InvalidKeyException::new, result.getParams()); + return result; + } else { + throw new InvalidKeyException("Unsupported key type or format"); + } + } + + private + <T extends Throwable> + void checkLockedParams(Function<String, T> exception, + AlgorithmParameterSpec spec) throws T { + + XECParameters params = XECParameters.get(exception, spec); + checkLockedParams(exception, params); + } + + private + <T extends Throwable> + void checkLockedParams(Function<String, T> exception, + XECParameters params) throws T { + + if (lockedParams != null && lockedParams != params) { + throw exception.apply("Parameters must be " + + lockedParams.getName()); + } + } + + @Override + protected PublicKey engineGeneratePublic(KeySpec keySpec) + throws InvalidKeySpecException { + + try { + return generatePublicImpl(keySpec); + } catch (InvalidKeyException ex) { + throw new InvalidKeySpecException(ex); + } + } + + @Override + protected PrivateKey engineGeneratePrivate(KeySpec keySpec) + throws InvalidKeySpecException { + + try { + return generatePrivateImpl(keySpec); + } catch (InvalidKeyException ex) { + throw new InvalidKeySpecException(ex); + } + } + + + private PublicKey generatePublicImpl(KeySpec keySpec) + throws InvalidKeyException, InvalidKeySpecException { + + if (keySpec instanceof X509EncodedKeySpec) { + X509EncodedKeySpec x509Spec = (X509EncodedKeySpec) keySpec; + XDHPublicKeyImpl result = + new XDHPublicKeyImpl(x509Spec.getEncoded()); + checkLockedParams(InvalidKeySpecException::new, + result.getParams()); + return result; + } else if (keySpec instanceof XECPublicKeySpec) { + XECPublicKeySpec publicKeySpec = (XECPublicKeySpec) keySpec; + XECParameters params = XECParameters.get( + InvalidKeySpecException::new, publicKeySpec.getParams()); + checkLockedParams(InvalidKeySpecException::new, params); + return new XDHPublicKeyImpl(params, publicKeySpec.getU()); + } else { + throw new InvalidKeySpecException( + "Only X509EncodedKeySpec and XECPublicKeySpec are supported"); + } + } + + private PrivateKey generatePrivateImpl(KeySpec keySpec) + throws InvalidKeyException, InvalidKeySpecException { + + if (keySpec instanceof PKCS8EncodedKeySpec) { + PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec) keySpec; + XDHPrivateKeyImpl result = + new XDHPrivateKeyImpl(pkcsSpec.getEncoded()); + checkLockedParams(InvalidKeySpecException::new, + result.getParams()); + return result; + } else if (keySpec instanceof XECPrivateKeySpec) { + XECPrivateKeySpec privateKeySpec = (XECPrivateKeySpec) keySpec; + XECParameters params = XECParameters.get( + InvalidKeySpecException::new, privateKeySpec.getParams()); + checkLockedParams(InvalidKeySpecException::new, params); + return new XDHPrivateKeyImpl(params, privateKeySpec.getScalar()); + } else { + throw new InvalidKeySpecException( + "Only PKCS8EncodedKeySpec and XECPrivateKeySpec supported"); + } + } + + protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec) + throws InvalidKeySpecException { + + if (key instanceof XECPublicKey) { + checkLockedParams(InvalidKeySpecException::new, + ((XECPublicKey) key).getParams()); + + if (X509EncodedKeySpec.class.isAssignableFrom(keySpec)) { + if (!key.getFormat().equals("X.509")) { + throw new InvalidKeySpecException("Format is not X.509"); + } + return keySpec.cast(new X509EncodedKeySpec(key.getEncoded())); + } else if (XECPublicKeySpec.class.isAssignableFrom(keySpec)) { + XECPublicKey xecKey = (XECPublicKey) key; + return keySpec.cast( + new XECPublicKeySpec(xecKey.getParams(), xecKey.getU())); + } else { + throw new InvalidKeySpecException( + "KeySpec must be X509EncodedKeySpec or XECPublicKeySpec"); + } + } else if (key instanceof XECPrivateKey) { + checkLockedParams(InvalidKeySpecException::new, + ((XECPrivateKey) key).getParams()); + + if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)) { + if (!key.getFormat().equals("PKCS#8")) { + throw new InvalidKeySpecException("Format is not PKCS#8"); + } + return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded())); + } else if (XECPrivateKeySpec.class.isAssignableFrom(keySpec)) { + XECPrivateKey xecKey = (XECPrivateKey) key; + byte[] scalar = xecKey.getScalar().orElseThrow( + () -> new InvalidKeySpecException("No private key value") + ); + return keySpec.cast( + new XECPrivateKeySpec(xecKey.getParams(), scalar)); + } else { + throw new InvalidKeySpecException + ("KeySpec must be PKCS8EncodedKeySpec or XECPrivateKeySpec"); + } + } else { + throw new InvalidKeySpecException("Unsupported key type"); + } + } + + static class X25519 extends XDHKeyFactory { + + public X25519() { + super(NamedParameterSpec.X25519); + } + } + + static class X448 extends XDHKeyFactory { + + public X448() { + super(NamedParameterSpec.X448); + } + } +} diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyPairGenerator.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyPairGenerator.java new file mode 100644 index 00000000000..b2d20b52559 --- /dev/null +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyPairGenerator.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.ec; + +import java.math.BigInteger; +import java.security.KeyPairGeneratorSpi; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.ProviderException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; + +import sun.security.jca.JCAUtil; + +/** + * Key pair generator for the XDH key agreement algorithm. + */ +public class XDHKeyPairGenerator extends KeyPairGeneratorSpi { + + private static final NamedParameterSpec DEFAULT_PARAM_SPEC + = NamedParameterSpec.X25519; + + private SecureRandom random = null; + private XECOperations ops = null; + private XECParameters lockedParams = null; + + XDHKeyPairGenerator() { + tryInitialize(DEFAULT_PARAM_SPEC); + } + + private XDHKeyPairGenerator(NamedParameterSpec paramSpec) { + tryInitialize(paramSpec); + lockedParams = ops.getParameters(); + } + + private void tryInitialize(NamedParameterSpec paramSpec) { + try { + initialize(paramSpec, null); + } catch (InvalidAlgorithmParameterException ex) { + String name = paramSpec.getName(); + throw new ProviderException(name + " not supported"); + } + } + + @Override + public void initialize(int keySize, SecureRandom random) { + + XECParameters params = XECParameters.getBySize( + InvalidParameterException::new, keySize); + + initializeImpl(params, random); + } + + @Override + public void initialize(AlgorithmParameterSpec params, SecureRandom random) + throws InvalidAlgorithmParameterException { + + XECParameters xecParams = XECParameters.get( + InvalidAlgorithmParameterException::new, params); + + initializeImpl(xecParams, random); + } + + private void initializeImpl(XECParameters params, SecureRandom random) { + + if (lockedParams != null && lockedParams != params) { + throw new InvalidParameterException("Parameters must be " + + lockedParams.getName()); + } + + this.ops = new XECOperations(params); + this.random = random == null ? JCAUtil.getSecureRandom() : random; + } + + + @Override + public KeyPair generateKeyPair() { + + byte[] privateKey = ops.generatePrivate(random); + // computePublic may modify the private key, so clone it first + BigInteger publicKey = ops.computePublic(privateKey.clone()); + + try { + return new KeyPair( + new XDHPublicKeyImpl(ops.getParameters(), publicKey), + new XDHPrivateKeyImpl(ops.getParameters(), privateKey) + ); + } catch (InvalidKeyException ex) { + throw new ProviderException(ex); + } + } + + static class X25519 extends XDHKeyPairGenerator { + + public X25519() { + super(NamedParameterSpec.X25519); + } + } + + static class X448 extends XDHKeyPairGenerator { + + public X448() { + super(NamedParameterSpec.X448); + } + } +} diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java new file mode 100644 index 00000000000..2b93cfd17c7 --- /dev/null +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.ec; + +import java.security.interfaces.XECPrivateKey; +import java.util.Optional; +import java.security.InvalidKeyException; +import java.security.PrivateKey; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; + +import sun.security.pkcs.PKCS8Key; +import sun.security.x509.AlgorithmId; + +public final class XDHPrivateKeyImpl extends PKCS8Key implements XECPrivateKey { + + private static final long serialVersionUID = 1L; + + private AlgorithmParameterSpec paramSpec; + + XDHPrivateKeyImpl(XECParameters params, byte[] k) + throws InvalidKeyException { + + this.paramSpec = new NamedParameterSpec(params.getName()); + this.algid = new AlgorithmId(params.getOid()); + this.key = k.clone(); + + checkLength(params); + } + + XDHPrivateKeyImpl(byte[] encoded) throws InvalidKeyException { + + decode(encoded); + XECParameters params = XECParameters.get( + InvalidKeyException::new, algid); + paramSpec = new NamedParameterSpec(params.getName()); + + checkLength(params); + } + + void checkLength(XECParameters params) throws InvalidKeyException { + + if (params.getBytes() != this.key.length) { + throw new InvalidKeyException( + "key length must be " + params.getBytes()); + } + } + + public byte[] getK() { + return key.clone(); + } + + @Override + public String getAlgorithm() { + return "XDH"; + } + + @Override + public AlgorithmParameterSpec getParams() { + return paramSpec; + } + + @Override + public Optional<byte[]> getScalar() { + return Optional.of(getK()); + } +} + diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java new file mode 100644 index 00000000000..0b9b6d93c04 --- /dev/null +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.ec; + +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.KeyRep; +import java.security.PublicKey; +import java.security.interfaces.XECPublicKey; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; +import java.util.Arrays; + +import sun.security.util.BitArray; +import sun.security.x509.AlgorithmId; +import sun.security.x509.X509Key; + +public final class XDHPublicKeyImpl extends X509Key implements XECPublicKey { + + private static final long serialVersionUID = 1L; + + private final BigInteger u; + private final NamedParameterSpec paramSpec; + + XDHPublicKeyImpl(XECParameters params, BigInteger u) + throws InvalidKeyException { + + this.paramSpec = new NamedParameterSpec(params.getName()); + this.algid = new AlgorithmId(params.getOid()); + this.u = u.mod(params.getP()); + + byte[] u_arr = this.u.toByteArray(); + reverse(u_arr); + // u_arr may be too large or too small, depending on the value of u + u_arr = Arrays.copyOf(u_arr, params.getBytes()); + + setKey(new BitArray(u_arr.length * 8, u_arr)); + + checkLength(params); + } + + XDHPublicKeyImpl(byte[] encoded) throws InvalidKeyException { + decode(encoded); + + XECParameters params = + XECParameters.get(InvalidKeyException::new, algid); + this.paramSpec = new NamedParameterSpec(params.getName()); + // construct the BigInteger representation + byte[] u_arr = getKey().toByteArray(); + reverse(u_arr); + + // clear the extra bits + int bitsMod8 = params.getBits() % 8; + if (bitsMod8 != 0) { + int mask = (1 << bitsMod8) - 1; + u_arr[0] &= mask; + } + + this.u = new BigInteger(1, u_arr); + + checkLength(params); + } + + void checkLength(XECParameters params) throws InvalidKeyException { + + if (params.getBytes() * 8 != getKey().length()) { + throw new InvalidKeyException( + "key length must be " + params.getBytes()); + } + } + + @Override + public BigInteger getU() { + return u; + } + + @Override + public AlgorithmParameterSpec getParams() { + return paramSpec; + } + + @Override + public String getAlgorithm() { + return "XDH"; + } + + protected Object writeReplace() throws java.io.ObjectStreamException { + return new KeyRep(KeyRep.Type.PUBLIC, + getAlgorithm(), + getFormat(), + getEncoded()); + } + + private static void swap(byte[] arr, int i, int j) { + byte tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + private static void reverse(byte [] arr) { + int i = 0; + int j = arr.length - 1; + + while (i < j) { + swap(arr, i, j); + i++; + j--; + } + } +} + diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECOperations.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XECOperations.java new file mode 100644 index 00000000000..d26ec634b7a --- /dev/null +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XECOperations.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.ec; + +import sun.security.util.math.IntegerFieldModuloP; +import sun.security.util.math.ImmutableIntegerModuloP; +import sun.security.util.math.IntegerModuloP; +import sun.security.util.math.MutableIntegerModuloP; +import sun.security.util.math.SmallValue; +import sun.security.util.math.intpoly.IntegerPolynomial25519; +import sun.security.util.math.intpoly.IntegerPolynomial448; + +import java.math.BigInteger; +import java.security.ProviderException; +import java.security.SecureRandom; + +public class XECOperations { + + private final XECParameters params; + private final IntegerFieldModuloP field; + private final ImmutableIntegerModuloP zero; + private final ImmutableIntegerModuloP one; + private final SmallValue a24; + private final ImmutableIntegerModuloP basePoint; + + public XECOperations(XECParameters c) { + this.params = c; + + BigInteger p = params.getP(); + this.field = getIntegerFieldModulo(p); + this.zero = field.getElement(BigInteger.ZERO).fixed(); + this.one = field.get1().fixed(); + this.a24 = field.getSmallValue(params.getA24()); + this.basePoint = field.getElement( + BigInteger.valueOf(c.getBasePoint())); + } + + public XECParameters getParameters() { + return params; + } + + public byte[] generatePrivate(SecureRandom random) { + byte[] result = new byte[this.params.getBytes()]; + random.nextBytes(result); + return result; + } + + /** + * Compute a public key from an encoded private key. This method will + * modify the supplied array in order to prune it. + */ + public BigInteger computePublic(byte[] k) { + pruneK(k); + return pointMultiply(k, this.basePoint).asBigInteger(); + } + + /** + * + * Multiply an encoded scalar with a point as a BigInteger and return an + * encoded point. The array k holding the scalar will be pruned by + * modifying it in place. + * + * @param k an encoded scalar + * @param u the u-coordinate of a point as a BigInteger + * @return the encoded product + */ + public byte[] encodedPointMultiply(byte[] k, BigInteger u) { + pruneK(k); + ImmutableIntegerModuloP elemU = field.getElement(u); + return pointMultiply(k, elemU).asByteArray(params.getBytes()); + } + + /** + * + * Multiply an encoded scalar with an encoded point and return an encoded + * point. The array k holding the scalar will be pruned by + * modifying it in place. + * + * @param k an encoded scalar + * @param u an encoded point + * @return the encoded product + */ + public byte[] encodedPointMultiply(byte[] k, byte[] u) { + pruneK(k); + ImmutableIntegerModuloP elemU = decodeU(u); + return pointMultiply(k, elemU).asByteArray(params.getBytes()); + } + + /** + * Return the field element corresponding to an encoded u-coordinate. + * This method prunes u by modifying it in place. + * + * @param u + * @param bits + * @return + */ + private ImmutableIntegerModuloP decodeU(byte[] u, int bits) { + + maskHighOrder(u, bits); + + return field.getElement(u); + } + + /** + * Mask off the high order bits of an encoded integer in an array. The + * array is modified in place. + * + * @param arr an array containing an encoded integer + * @param bits the number of bits to keep + * @return the number, in range [1,8], of bits kept in the highest byte + */ + private static byte maskHighOrder(byte[] arr, int bits) { + + int lastByteIndex = arr.length - 1; + byte bitsMod8 = (byte) (bits % 8); + byte highBits = bitsMod8 == 0 ? 8 : bitsMod8; + byte msbMaskOff = (byte) ((1 << highBits) - 1); + arr[lastByteIndex] &= msbMaskOff; + + return highBits; + } + + /** + * Prune an encoded scalar value by modifying it in place. The extra + * high-order bits are masked off, the highest valid bit it set, and the + * number is rounded down to a multiple of the cofactor. + * + * @param k an encoded scalar value + * @param bits the number of bits in the scalar + * @param logCofactor the base-2 logarithm of the cofactor + */ + private static void pruneK(byte[] k, int bits, int logCofactor) { + + int lastByteIndex = k.length - 1; + + // mask off unused high-order bits + byte highBits = maskHighOrder(k, bits); + + // set the highest bit + byte msbMaskOn = (byte) (1 << (highBits - 1)); + k[lastByteIndex] |= msbMaskOn; + + // round down to a multiple of the cofactor + byte lsbMaskOff = (byte) (0xFF << logCofactor); + k[0] &= lsbMaskOff; + } + + private void pruneK(byte[] k) { + pruneK(k, params.getBits(), params.getLogCofactor()); + } + + private ImmutableIntegerModuloP decodeU(byte [] u) { + return decodeU(u, params.getBits()); + } + + // Constant-time conditional swap + private static void cswap(int swap, MutableIntegerModuloP x1, + MutableIntegerModuloP x2) { + + x1.conditionalSwapWith(x2, swap); + } + + private static IntegerFieldModuloP getIntegerFieldModulo(BigInteger p) { + + if (p.equals(IntegerPolynomial25519.MODULUS)) { + return new IntegerPolynomial25519(); + } + else if (p.equals(IntegerPolynomial448.MODULUS)) { + return new IntegerPolynomial448(); + } + + throw new ProviderException("Unsupported prime: " + p.toString()); + } + + private int bitAt(byte[] arr, int index) { + int byteIndex = index / 8; + int bitIndex = index % 8; + return (arr[byteIndex] & (1 << bitIndex)) >> bitIndex; + } + + /* + * Constant-time Montgomery ladder that computes k*u and returns the + * result as a field element. + */ + private IntegerModuloP pointMultiply(byte[] k, + ImmutableIntegerModuloP u) { + + ImmutableIntegerModuloP x_1 = u; + MutableIntegerModuloP x_2 = this.one.mutable(); + MutableIntegerModuloP z_2 = this.zero.mutable(); + MutableIntegerModuloP x_3 = u.mutable(); + MutableIntegerModuloP z_3 = this.one.mutable(); + int swap = 0; + + // Variables below are reused to avoid unnecessary allocation + // They will be assigned in the loop, so initial value doesn't matter + MutableIntegerModuloP m1 = this.zero.mutable(); + MutableIntegerModuloP DA = this.zero.mutable(); + MutableIntegerModuloP E = this.zero.mutable(); + MutableIntegerModuloP a24_times_E = this.zero.mutable(); + + // Comments describe the equivalent operations from RFC 7748 + // In comments, A(m1) means the variable m1 holds the value A + for (int t = params.getBits() - 1; t >= 0; t--) { + int k_t = bitAt(k, t); + swap = swap ^ k_t; + cswap(swap, x_2, x_3); + cswap(swap, z_2, z_3); + swap = k_t; + + // A(m1) = x_2 + z_2 + m1.setValue(x_2).setSum(z_2); + // D = x_3 - z_3 + // DA = D * A(m1) + DA.setValue(x_3).setDifference(z_3).setProduct(m1); + // AA(m1) = A(m1)^2 + m1.setSquare(); + // B(x_2) = x_2 - z_2 + x_2.setDifference(z_2); + // C = x_3 + z_3 + // CB(x_3) = C * B(x_2) + x_3.setSum(z_3).setProduct(x_2); + // BB(x_2) = B^2 + x_2.setSquare(); + // E = AA(m1) - BB(x_2) + E.setValue(m1).setDifference(x_2); + // compute a24 * E using SmallValue + a24_times_E.setValue(E); + a24_times_E.setProduct(this.a24); + + // assign results to x_3, z_3, x_2, z_2 + // x_2 = AA(m1) * BB + x_2.setProduct(m1); + // z_2 = E * (AA(m1) + a24 * E) + z_2.setValue(m1).setSum(a24_times_E).setProduct(E); + // z_3 = x_1*(DA - CB(x_3))^2 + z_3.setValue(DA).setDifference(x_3).setSquare().setProduct(x_1); + // x_3 = (CB(x_3) + DA)^2 + x_3.setSum(DA).setSquare(); + } + + cswap(swap, x_2, x_3); + cswap(swap, z_2, z_3); + + // return (x_2 * z_2^(p - 2)) + return x_2.setProduct(z_2.multiplicativeInverse()); + } +} diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java new file mode 100644 index 00000000000..a00b2af5ae0 --- /dev/null +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.security.ec; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; +import java.util.Collections; +import java.util.Map; +import java.util.HashMap; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; + +import sun.security.util.ObjectIdentifier; +import sun.security.x509.AlgorithmId; + +public class XECParameters { + + // Naming/identification parameters + private final ObjectIdentifier oid; + private final String name; + + // Curve/field parameters + private final int bits; + private final BigInteger p; + private final int logCofactor; + private final int a24; + private final byte basePoint; + + /** + * + * Construct an object holding the supplied parameters. No parameters are + * checked, so this method always succeeds. This method supports + * Montgomery curves of the form y^2 = x^3 + ax^2 + x. + * + * @param bits The number of relevant bits in a public/private key. + * @param p The prime that defines the finite field. + * @param a24 The value of (a - 2) / 4, where a is the second-degree curve + * coefficient. + * @param basePoint The point that generates the desired group + * @param logCofactor The base-2 logarithm of the cofactor of the curve + * @param oid + * @param name + */ + public XECParameters(int bits, BigInteger p, int a24, + byte basePoint, int logCofactor, + ObjectIdentifier oid, String name) { + + this.bits = bits; + this.logCofactor = logCofactor; + this.p = p; + this.a24 = a24; + this.basePoint = basePoint; + this.oid = oid; + this.name = name; + + } + + public int getBits() { + return bits; + } + public int getBytes() { + return (bits + 7) / 8; + } + public int getLogCofactor() { + return logCofactor; + } + public BigInteger getP() { + return p; + } + public int getA24() { + return a24; + } + public byte getBasePoint() { + return basePoint; + } + public ObjectIdentifier getOid() { + return oid; + } + public String getName() { + return name; + } + + private static final Map<Integer, XECParameters> SIZE_MAP; + private static final Map<ObjectIdentifier, XECParameters> OID_MAP; + private static final Map<String, XECParameters> NAME_MAP; + + static { + final BigInteger TWO = BigInteger.valueOf(2); + + Map<Integer, XECParameters> bySize = new HashMap<>(); + Map<ObjectIdentifier, XECParameters> byOid = new HashMap<>(); + Map<String, XECParameters> byName = new HashMap<>(); + + // set up X25519 + try { + BigInteger p = TWO.pow(255).subtract(BigInteger.valueOf(19)); + addParameters(255, p, 121665, (byte) 0x09, 3, + new int[]{1, 3, 101, 110}, NamedParameterSpec.X25519.getName(), + bySize, byOid, byName); + + } catch (IOException ex) { + // Unable to set X25519 parameters---it will be disabled + } + + // set up X448 + try { + BigInteger p = TWO.pow(448).subtract(TWO.pow(224)) + .subtract(BigInteger.ONE); + addParameters(448, p, 39081, (byte) 0x05, 2, + new int[]{1, 3, 101, 111}, NamedParameterSpec.X448.getName(), + bySize, byOid, byName); + + } catch (IOException ex) { + // Unable to set X448 parameters---it will be disabled + } + + SIZE_MAP = Collections.unmodifiableMap(bySize); + OID_MAP = Collections.unmodifiableMap(byOid); + NAME_MAP = Collections.unmodifiableMap(byName); + } + + private static void addParameters(int bits, BigInteger p, int a24, + byte basePoint, int logCofactor, int[] oidBytes, String name, + Map<Integer, XECParameters> bySize, + Map<ObjectIdentifier, XECParameters> byOid, + Map<String, XECParameters> byName) throws IOException { + + ObjectIdentifier oid = new ObjectIdentifier(oidBytes); + XECParameters params = + new XECParameters(bits, p, a24, basePoint, logCofactor, oid, name); + bySize.put(bits, params); + byOid.put(oid, params); + byName.put(name, params); + } + + public static Optional<XECParameters> getByOid(ObjectIdentifier id) { + return Optional.ofNullable(OID_MAP.get(id)); + } + public static Optional<XECParameters> getBySize(int size) { + return Optional.ofNullable(SIZE_MAP.get(size)); + } + public static Optional<XECParameters> getByName(String name) { + return Optional.ofNullable(NAME_MAP.get(name)); + } + + boolean oidEquals(XECParameters other) { + return oid.equals(other.getOid()); + } + + // Utility method that is used by the methods below to handle exception + // suppliers + private static + <A, B> Supplier<B> apply(final Function<A, B> func, final A a) { + return new Supplier<B>() { + @Override + public B get() { + return func.apply(a); + } + }; + } + + /** + * Get parameters by key size, or throw an exception if no parameters are + * defined for the specified key size. This method is used in several + * contexts that should throw different exceptions when the parameters + * are not found. The first argument is a function that produces the + * desired exception. + * + * @param exception a function that produces an exception from a string + * @param size the desired key size + * @param <T> the type of exception that is thrown + * @return the parameters for the specified key size + * @throws T when suitable parameters do not exist + */ + public static + <T extends Throwable> + XECParameters getBySize(Function<String, T> exception, + int size) throws T { + + Optional<XECParameters> xecParams = getBySize(size); + return xecParams.orElseThrow( + apply(exception, "Unsupported size: " + size)); + } + + /** + * Get parameters by algorithm ID, or throw an exception if no + * parameters are defined for the specified ID. This method is used in + * several contexts that should throw different exceptions when the + * parameters are not found. The first argument is a function that produces + * the desired exception. + * + * @param exception a function that produces an exception from a string + * @param algId the algorithm ID + * @param <T> the type of exception that is thrown + * @return the parameters for the specified algorithm ID + * @throws T when suitable parameters do not exist + */ + public static + <T extends Throwable> + XECParameters get(Function<String, T> exception, + AlgorithmId algId) throws T { + + Optional<XECParameters> xecParams = getByOid(algId.getOID()); + return xecParams.orElseThrow( + apply(exception, "Unsupported OID: " + algId.getOID())); + } + + /** + * Get parameters by algorithm parameter spec, or throw an exception if no + * parameters are defined for the spec. This method is used in + * several contexts that should throw different exceptions when the + * parameters are not found. The first argument is a function that produces + * the desired exception. + * + * @param exception a function that produces an exception from a string + * @param params the algorithm parameters spec + * @param <T> the type of exception that is thrown + * @return the parameters for the spec + * @throws T when suitable parameters do not exist + */ + public static + <T extends Throwable> + XECParameters get(Function<String, T> exception, + AlgorithmParameterSpec params) throws T { + + if (params instanceof NamedParameterSpec) { + NamedParameterSpec namedParams = (NamedParameterSpec) params; + Optional<XECParameters> xecParams = + getByName(namedParams.getName()); + return xecParams.orElseThrow( + apply(exception, "Unsupported name: " + namedParams.getName())); + } else { + throw exception.apply("Only NamedParameterSpec is supported."); + } + } +} + diff --git a/test/jdk/com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java b/test/jdk/com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java deleted file mode 100644 index d77dc6b0da9..00000000000 --- a/test/jdk/com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2005, 2017, 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 4936763 - * @summary Verify that DHKeyAgreement can generate secret key - * objects for AES algorithm - * @author Valerie Peng - * @run main/othervm -Djdk.crypto.KeyAgreement.legacyKDF=true DHGenSecretKey - */ -import java.security.*; -import java.security.interfaces.*; -import javax.crypto.*; - -public class DHGenSecretKey { - - public static void main(String[] args) throws Exception { - DHGenSecretKey test = new DHGenSecretKey(); - test.run(); - } - - public void run() throws Exception { - // generate keyPairs using parameters - KeyPairGenerator keyGen = - KeyPairGenerator.getInstance("DH", "SunJCE"); - - // Alice generates her key pairs - KeyPair keyA = keyGen.generateKeyPair(); - - // Bob generates his key pairs - KeyPair keyB = keyGen.generateKeyPair(); - - KeyAgreement bobAlice = KeyAgreement.getInstance("DH", "SunJCE"); - bobAlice.init(keyB.getPrivate()); - bobAlice.doPhase(keyA.getPublic(), true); - byte[] keyMaterial = bobAlice.generateSecret(); - - bobAlice.doPhase(keyA.getPublic(), true); - SecretKey skey = bobAlice.generateSecret("AES"); - byte[] keyVal = skey.getEncoded(); - - System.out.println("Generated " + keyVal.length*8 + - "-bit AES key"); - for (int i = 0; i < keyVal.length; i++) { - if (keyVal[i] != keyMaterial[i]) { - throw new Exception("Error: key value comparison failed!"); - } - } - System.out.println("Test Passed"); - } -} diff --git a/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java b/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java new file mode 100644 index 00000000000..8f705abd772 --- /dev/null +++ b/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018, 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 4936763 8184359 + * @summary KeyAgreement Test with all supported algorithms from JCE. + * Arguments order <KeyExchangeAlgorithm> <KeyGenAlgorithm> <Provider> + * It removes com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java + * as the same functionality for DiffieHellman is covered along with + * this test file was covered before with JDK-4936763. + * @run main/othervm -Djdk.crypto.KeyAgreement.legacyKDF=true KeyAgreementTest + * DiffieHellman DH SunJCE + * @run main KeyAgreementTest ECDH EC SunEC + * @run main KeyAgreementTest XDH XDH SunEC + */ +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.spec.NamedParameterSpec; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECGenParameterSpec; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.crypto.KeyAgreement; +import javax.crypto.spec.DHGenParameterSpec; + +public class KeyAgreementTest { + + public static void main(String[] args) throws Exception { + + String kaAlgo = args[0]; + String kpgAlgo = args[1]; + String provider = args[2]; + AlgoSpec aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgo); + List<AlgorithmParameterSpec> specs = aSpec.getAlgorithmParameterSpecs(); + for (AlgorithmParameterSpec spec : specs) { + testKeyAgreement(provider, kaAlgo, kpgAlgo, spec); + } + } + + /** + * Generate AlgorithmParameterSpec using all possible supported curve for + * KeyExchangeAlgorithm. + */ + private enum AlgoSpec { + // EC curve supported for KeyGeneration can found between intersection + // of curves define in + // "java.base/share/classes/sun/security/util/CurveDB.java" + // and + // "jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c" + ECDH( + // SEC2 prime curves + "secp112r1", "secp112r2", "secp128r1", "secp128r2", "secp160k1", + "secp160r1", "secp192k1", "secp192r1", "secp224k1", "secp224r1", + "secp256k1", "secp256r1", "secp384r1", "secp521r1", + // ANSI X9.62 prime curves + "X9.62 prime192v2", "X9.62 prime192v3", "X9.62 prime239v1", + "X9.62 prime239v2", "X9.62 prime239v3", + // SEC2 binary curves + "sect113r1", "sect113r2", "sect131r1", "sect131r2", "sect163k1", + "sect163r1", "sect163r2", "sect193r1", "sect193r2", "sect233k1", + "sect233r1", "sect239k1", "sect283k1", "sect283r1", "sect409k1", + "sect409r1", "sect571k1", "sect571r1", + // ANSI X9.62 binary curves + "X9.62 c2tnb191v1", "X9.62 c2tnb191v2", "X9.62 c2tnb191v3", + "X9.62 c2tnb239v1", "X9.62 c2tnb239v2", "X9.62 c2tnb239v3", + "X9.62 c2tnb359v1", "X9.62 c2tnb431r1" + ), + XDH("X25519", "X448"), + // There is no curve for DiffieHellman + DiffieHellman(new String[]{}); + + private final List<AlgorithmParameterSpec> specs = new ArrayList<>(); + + private AlgoSpec(String... curves) { + // Generate AlgorithmParameterSpec for each KeyExchangeAlgorithm + for (String crv : curves) { + switch (this.name()) { + case "ECDH": + specs.add(new ECGenParameterSpec(crv)); + break; + case "XDH": + specs.add(new NamedParameterSpec(crv)); + break; + case "DiffieHellman": + specs.add(new DHGenParameterSpec(512, 64)); + break; + default: + throw new RuntimeException("Invalid Algo name " + + this.name()); + } + } + } + + public List<AlgorithmParameterSpec> getAlgorithmParameterSpecs() { + return this.specs; + } + } + + /** + * Perform KeyAgreement operation using native as well as JCE provider. + */ + private static void testKeyAgreement(String provider, String kaAlgo, + String kpgAlgo, AlgorithmParameterSpec spec) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider); + kpg.initialize(spec); + KeyPair kp1 = kpg.generateKeyPair(); + KeyPair kp2 = kpg.generateKeyPair(); + + // Uses KeyAgreement based on Provider search order. + KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo); + ka1.init(kp1.getPrivate()); + ka1.doPhase(kp2.getPublic(), true); + byte[] secret1 = ka1.generateSecret(); + + // Uses SunJCE provider + KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider); + ka2.init(kp2.getPrivate()); + ka2.doPhase(kp1.getPublic(), true); + // Keeping the legacy generateSecret method for DiffieHellman as it was + // defined in removed Test file from JDK-4936763, + // com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java. + byte[] secret2 = "DiffieHellman".equals(kaAlgo) + ? ka2.generateSecret("AES").getEncoded() : ka2.generateSecret(); + + // With related keypairs, each provider should generate same + // KeyAgreement secret. + if (!Arrays.equals(secret1, secret2)) { + throw new Exception("KeyAgreement secret mismatch."); + } + } +} diff --git a/test/jdk/java/security/KeyAgreement/KeySizeTest.java b/test/jdk/java/security/KeyAgreement/KeySizeTest.java new file mode 100644 index 00000000000..fede5726754 --- /dev/null +++ b/test/jdk/java/security/KeyAgreement/KeySizeTest.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2018, 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 8184359 + * @summary KeyLength support test for DiffieHellman, EC, XDH. + * Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <keyLen> + * @library /test/lib + * @build jdk.test.lib.Convert + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 512 + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 768 + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 832 + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 1024 + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 2048 + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 3072 + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 4096 + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 6144 + * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 8192 + * @run main KeySizeTest ECDH SunEC EC 128 + * @run main KeySizeTest ECDH SunEC EC 192 + * @run main KeySizeTest ECDH SunEC EC 256 + * @run main KeySizeTest XDH SunEC XDH 255 + * @run main KeySizeTest XDH SunEC XDH 448 + */ +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.XECPrivateKey; +import java.security.interfaces.XECPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.security.spec.NamedParameterSpec; +import java.util.Arrays; +import javax.crypto.KeyAgreement; +import javax.crypto.interfaces.DHPrivateKey; +import javax.crypto.interfaces.DHPublicKey; +import jdk.test.lib.Convert; + +public class KeySizeTest { + + public static void main(String[] args) throws Exception { + + String kaAlgo = args[0]; + String provider = args[1]; + String kpgAlgo = args[2]; + int keySize = Integer.parseInt(args[3]); + testKeyAgreement(provider, kaAlgo, kpgAlgo, keySize); + } + + /** + * Perform KeyAgreement operation. + */ + private static void testKeyAgreement(String provider, String kaAlgo, + String kpgAlgo, int keySize) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider); + kpg.initialize(keySize); + KeyPair kp = kpg.generateKeyPair(); + // Test standard Key attributes. + testKeyAttributes(provider, kpgAlgo, kp, keySize); + // Test KeyAgreement. + KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider); + ka.init(kp.getPrivate()); + ka.doPhase(kp.getPublic(), true); + ka.generateSecret(); + } + + /** + * Test standard Key attributes. + */ + private static void testKeyAttributes(String provider, String kpgAlgo, + KeyPair kp, int keySize) throws Exception { + + KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider); + switch (kpgAlgo) { + case "DiffieHellman": + // Verify PrivateKey attributes. + DHPrivateKey dhPri = (DHPrivateKey) kp.getPrivate(); + BigInteger p = dhPri.getParams().getP(); + if (p.bitLength() != keySize) { + throw new Exception(String.format("Invalid modulus size: " + + "%s/%s", p.bitLength(), keySize)); + } + if (!p.isProbablePrime(128)) { + throw new Exception("The modulus is composite!"); + } + PKCS8EncodedKeySpec dhPriSpec + = new PKCS8EncodedKeySpec(dhPri.getEncoded()); + DHPrivateKey dhPriDecod + = (DHPrivateKey) kf.generatePrivate(dhPriSpec); + equals(dhPri.getX(), dhPriDecod.getX()); + equals(dhPri.getFormat(), dhPriDecod.getFormat()); + equals(dhPri.getEncoded(), dhPriDecod.getEncoded()); + equals(dhPri.getParams().getG(), dhPriDecod.getParams().getG()); + equals(dhPri.getParams().getL(), dhPriDecod.getParams().getL()); + equals(dhPri.getParams().getP(), dhPriDecod.getParams().getP()); + + // Verify PublicKey attributes. + DHPublicKey dhPub = (DHPublicKey) kp.getPublic(); + p = dhPub.getParams().getP(); + if (p.bitLength() != keySize) { + throw new Exception(String.format("Invalid modulus size: " + + "%s/%s", p.bitLength(), keySize)); + } + X509EncodedKeySpec dhPubSpec + = new X509EncodedKeySpec(dhPub.getEncoded()); + DHPublicKey dhPubDecod + = (DHPublicKey) kf.generatePublic(dhPubSpec); + equals(dhPub.getY(), dhPubDecod.getY()); + equals(dhPub.getFormat(), dhPubDecod.getFormat()); + equals(dhPub.getEncoded(), dhPubDecod.getEncoded()); + equals(dhPub.getParams().getG(), dhPubDecod.getParams().getG()); + equals(dhPub.getParams().getL(), dhPubDecod.getParams().getL()); + equals(dhPub.getParams().getP(), dhPubDecod.getParams().getP()); + + BigInteger left = BigInteger.ONE; + BigInteger right = p.subtract(BigInteger.ONE); + BigInteger x = dhPri.getX(); + if ((x.compareTo(left) <= 0) || (x.compareTo(right) >= 0)) { + throw new Exception( + "X outside range [2, p - 2]: x: " + x + " p: " + p); + } + BigInteger y = dhPub.getY(); + if ((y.compareTo(left) <= 0) || (y.compareTo(right) >= 0)) { + throw new Exception( + "Y outside range [2, p - 2]: x: " + x + " p: " + p); + } + break; + case "EC": + // Verify PrivateKey attributes. + ECPrivateKey ecPriv = (ECPrivateKey) kp.getPrivate(); + PKCS8EncodedKeySpec ecPriSpec + = new PKCS8EncodedKeySpec(ecPriv.getEncoded()); + ECPrivateKey ecPriDecod + = (ECPrivateKey) kf.generatePrivate(ecPriSpec); + equals(ecPriv.getS(), ecPriDecod.getS()); + equals(ecPriv.getFormat(), ecPriDecod.getFormat()); + equals(ecPriv.getEncoded(), ecPriDecod.getEncoded()); + equals(ecPriv.getParams().getCofactor(), + ecPriDecod.getParams().getCofactor()); + equals(ecPriv.getParams().getCurve(), + ecPriDecod.getParams().getCurve()); + equals(ecPriv.getParams().getGenerator(), + ecPriDecod.getParams().getGenerator()); + equals(ecPriv.getParams().getOrder(), + ecPriDecod.getParams().getOrder()); + + // Verify PublicKey attributes. + ECPublicKey ecPub = (ECPublicKey) kp.getPublic(); + X509EncodedKeySpec ecPubSpec + = new X509EncodedKeySpec(ecPub.getEncoded()); + ECPublicKey ecPubDecod + = (ECPublicKey) kf.generatePublic(ecPubSpec); + equals(ecPub.getW(), ecPubDecod.getW()); + equals(ecPub.getFormat(), ecPubDecod.getFormat()); + equals(ecPub.getEncoded(), ecPubDecod.getEncoded()); + equals(ecPub.getParams().getCofactor(), + ecPubDecod.getParams().getCofactor()); + equals(ecPub.getParams().getCurve(), + ecPubDecod.getParams().getCurve()); + equals(ecPub.getParams().getGenerator(), + ecPubDecod.getParams().getGenerator()); + equals(ecPub.getParams().getOrder(), + ecPubDecod.getParams().getOrder()); + break; + case "XDH": + // Verify PrivateKey attributes. + XECPrivateKey xdhPri = (XECPrivateKey) kp.getPrivate(); + PKCS8EncodedKeySpec xdhPriSpec + = new PKCS8EncodedKeySpec(xdhPri.getEncoded()); + XECPrivateKey xdhPriDec + = (XECPrivateKey) kf.generatePrivate(xdhPriSpec); + equals(xdhPri.getScalar().get(), xdhPriDec.getScalar().get()); + equals(xdhPri.getFormat(), xdhPriDec.getFormat()); + equals(xdhPri.getEncoded(), xdhPriDec.getEncoded()); + equals(((NamedParameterSpec) xdhPri.getParams()).getName(), + ((NamedParameterSpec) xdhPriDec.getParams()).getName()); + + // Verify PublicKey attributes. + XECPublicKey xdhPub = (XECPublicKey) kp.getPublic(); + X509EncodedKeySpec xdhPubSpec + = new X509EncodedKeySpec(xdhPub.getEncoded()); + XECPublicKey xdhPubDec + = (XECPublicKey) kf.generatePublic(xdhPubSpec); + equals(xdhPub.getU(), xdhPubDec.getU()); + equals(xdhPub.getFormat(), xdhPubDec.getFormat()); + equals(xdhPub.getEncoded(), xdhPubDec.getEncoded()); + equals(((NamedParameterSpec) xdhPub.getParams()).getName(), + ((NamedParameterSpec) xdhPubDec.getParams()).getName()); + break; + default: + throw new RuntimeException("Invalid Algo name " + kpgAlgo); + } + } + + private static boolean equals(Object actual, Object expected) { + boolean equals = actual.equals(expected); + if (!equals) { + throw new RuntimeException(String.format("Actual: %s, Expected: %s", + actual, expected)); + } + return equals; + } + + private static boolean equals(byte[] actual, byte[] expected) { + boolean equals = Arrays.equals(actual, expected); + if (!equals) { + throw new RuntimeException(String.format("Actual array: %s, " + + "Expected array:%s", Convert.byteArrayToHexString(actual), + Convert.byteArrayToHexString(expected))); + } + return equals; + } +} diff --git a/test/jdk/java/security/KeyAgreement/KeySpecTest.java b/test/jdk/java/security/KeyAgreement/KeySpecTest.java new file mode 100644 index 00000000000..1e8742dd796 --- /dev/null +++ b/test/jdk/java/security/KeyAgreement/KeySpecTest.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2018, 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 8184359 + * @summary Standard tests on KeySpec, KeyFactory, KeyPairs and Keys. + * Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <Curve*> + * @run main KeySpecTest DiffieHellman SunJCE DiffieHellman + * @run main KeySpecTest ECDH SunEC EC + * @run main KeySpecTest XDH SunEC XDH X25519 + * @run main KeySpecTest XDH SunEC XDH X448 + */ +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.security.spec.NamedParameterSpec; +import java.security.spec.XECPublicKeySpec; +import java.security.spec.XECPrivateKeySpec; +import java.security.spec.KeySpec; +import java.util.ArrayList; +import java.util.List; +import java.util.Arrays; +import javax.crypto.KeyAgreement; +import javax.crypto.spec.DHPrivateKeySpec; +import javax.crypto.spec.DHPublicKeySpec; + +public class KeySpecTest { + + public static void main(String[] args) throws Exception { + + String kaAlgo = args[0]; + String provider = args[1]; + String kpgAlgo = args[2]; + KeyPair kp = genKeyPair(provider, kpgAlgo, + (args.length > 3) ? args[3] : kpgAlgo); + testKeySpecs(provider, kaAlgo, kpgAlgo, kp); + testEncodedKeySpecs(provider, kaAlgo, kpgAlgo, kp); + } + + /** + * Generate keyPair based on KeyPairGenerator algorithm. + */ + private static KeyPair genKeyPair(String provider, String kpgAlgo, + String kpgInit) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider); + switch (kpgInit) { + case "DiffieHellman": + kpg.initialize(512); + break; + case "EC": + kpg.initialize(256); + break; + case "X25519": + kpg.initialize(255); + break; + case "X448": + kpg.initialize(448); + break; + default: + throw new RuntimeException("Invalid Algo name " + kpgInit); + } + return kpg.generateKeyPair(); + } + + /** + * Standard Test with Keys and the one generated through Spec. + */ + private static void testKeySpecs(String provider, String kaAlgo, + String kpgAlgo, KeyPair kp) throws Exception { + + KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider); + // For each public KeySpec supported by KeyPairGenerator + for (Class pubSpecType + : getCompatibleKeySpecs(kpgAlgo, KeyType.PUBLIC)) { + //For each private KeySpec supported by KeyPairGenerator + for (Class priSpecType + : getCompatibleKeySpecs(kpgAlgo, KeyType.PRIVATE)) { + // Transform original PublicKey through KeySpec + KeySpec pubSpec = kf.getKeySpec(kp.getPublic(), pubSpecType); + PublicKey pubKey = kf.generatePublic(pubSpec); + // Transform original PrivateKey through KeySpec + KeySpec priSpec = kf.getKeySpec(kp.getPrivate(), priSpecType); + PrivateKey priKey = kf.generatePrivate(priSpec); + + // Test the keys are equal after transformation through KeySpec. + testKeyEquals(kp, pubKey, priKey); + // Test the keys are serializable. + testSerialize(kp); + // Test Parameter name. + if (!kaAlgo.equals("DiffieHellman")) { + testParamName(priSpec, pubSpec); + } + // Compare KeyAgreement secret generated from original keys + // and by the keys after transformed through KeySpec. + if (!Arrays.equals(getKeyAgreementSecret(provider, kaAlgo, + kp.getPublic(), kp.getPrivate()), + getKeyAgreementSecret(provider, kaAlgo, + pubKey, priKey))) { + throw new RuntimeException("KeyAgreement secret mismatch."); + } + } + } + } + + /** + * Standard Test with Keys and the one generated from encoded bytes. + */ + private static void testEncodedKeySpecs(String provider, String kaAlgo, + String kpgAlgo, KeyPair kp) throws Exception { + + KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider); + PKCS8EncodedKeySpec priSpec + = new PKCS8EncodedKeySpec(kp.getPrivate().getEncoded()); + PrivateKey priKey = kf.generatePrivate(priSpec); + + X509EncodedKeySpec pubSpec + = new X509EncodedKeySpec(kp.getPublic().getEncoded()); + PublicKey pubKey = kf.generatePublic(pubSpec); + + // Test the keys are equal after transformation through KeySpec. + testKeyEquals(kp, pubKey, priKey); + // Test the keys are serializable. + testSerialize(kp); + // Test Parameter name. + if (!kaAlgo.equals("DiffieHellman")) { + testParamName(priSpec, pubSpec); + } + // Compare KeyAgreement secret generated from original keys + // and by the keys after transformed through KeySpec. + if (!Arrays.equals(getKeyAgreementSecret(provider, kaAlgo, + kp.getPublic(), kp.getPrivate()), + getKeyAgreementSecret(provider, kaAlgo, pubKey, priKey))) { + throw new RuntimeException("KeyAgreement secret mismatch."); + } + } + + private enum KeyType { + PUBLIC, PRIVATE; + } + + /** + * Provides Compatible KeySpec Type list for KeyPairGenerator algorithm. + */ + private static List<Class> getCompatibleKeySpecs(String kpgAlgo, + KeyType type) { + + List<Class> specs = new ArrayList<>(); + switch (kpgAlgo) { + case "DiffieHellman": + if (type == KeyType.PUBLIC) { + return Arrays.asList(X509EncodedKeySpec.class, + DHPublicKeySpec.class); + } else { + return Arrays.asList(PKCS8EncodedKeySpec.class, + DHPrivateKeySpec.class); + } + case "EC": + if (type == KeyType.PUBLIC) { + return Arrays.asList(X509EncodedKeySpec.class, + ECPublicKeySpec.class); + } else { + return Arrays.asList(PKCS8EncodedKeySpec.class, + ECPrivateKeySpec.class); + } + case "XDH": + if (type == KeyType.PUBLIC) { + return Arrays.asList(X509EncodedKeySpec.class, + XECPublicKeySpec.class); + } else { + return Arrays.asList(PKCS8EncodedKeySpec.class, + XECPrivateKeySpec.class); + } + } + return specs; + } + + /** + * Generate KeyAgreement Secret. + */ + private static byte[] getKeyAgreementSecret(String provider, String kaAlgo, + PublicKey pubKey, PrivateKey priKey) throws Exception { + + KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider); + ka.init(priKey); + ka.doPhase(pubKey, true); + return ka.generateSecret(); + } + + /** + * Compare original KeyPair with transformed ones. + */ + private static void testKeyEquals(KeyPair kp, PublicKey pubKey, + PrivateKey priKey) { + + if (!kp.getPrivate().equals(priKey) + && kp.getPrivate().hashCode() != priKey.hashCode()) { + throw new RuntimeException("PrivateKey is not equal with PrivateKey" + + " generated through KeySpec"); + } + if (!kp.getPublic().equals(pubKey) + && kp.getPublic().hashCode() != pubKey.hashCode()) { + throw new RuntimeException("PublicKey is not equal with PublicKey" + + " generated through KeySpec"); + } + } + + /** + * Compare the parameter names of Public/Private KeySpec from a pair. + */ + private static void testParamName(KeySpec priSpec, KeySpec pubSpec) { + + if (priSpec instanceof XECPrivateKeySpec + && pubSpec instanceof XECPublicKeySpec) { + if (((NamedParameterSpec) ((XECPrivateKeySpec) priSpec) + .getParams()).getName() + != ((NamedParameterSpec) ((XECPublicKeySpec) pubSpec) + .getParams()).getName()) { + throw new RuntimeException("Curve name mismatch found"); + } + } + } + + /** + * Test serialization of KeyPair and Keys it holds. + */ + private static void testSerialize(KeyPair keyPair) throws Exception { + + // Verify Serialized PrivateKey instance. + if (!keyPair.getPrivate().equals( + deserializedCopy(keyPair.getPrivate(), PrivateKey.class))) { + throw new RuntimeException("PrivateKey is not equal with PrivateKey" + + " generated through Serialization"); + } + // Verify Serialized PublicKey instance. + if (!keyPair.getPublic().equals( + deserializedCopy(keyPair.getPublic(), PublicKey.class))) { + throw new RuntimeException("PublicKey is not equal with PublicKey" + + " generated through Serialization"); + } + // Verify Serialized KeyPair instance. + KeyPair copy = deserializedCopy(keyPair, KeyPair.class); + if (!keyPair.getPrivate().equals(copy.getPrivate())) { + throw new RuntimeException("PrivateKey is not equal with PrivateKey" + + " generated through Serialized KeyPair"); + } + if (!keyPair.getPublic().equals(copy.getPublic())) { + throw new RuntimeException("PublicKey is not equal with PublicKey" + + " generated through Serialized KeyPair"); + } + } + + private static <T extends Object> T deserializedCopy(T orig, Class<T> type) + throws IOException, ClassNotFoundException { + return deserialize(serialize(orig), type); + } + + /** + * Deserialize the Key object. + */ + private static <T extends Object> T deserialize(byte[] serialized, + Class<T> type) throws IOException, ClassNotFoundException { + + T key = null; + try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized); + ObjectInputStream ois = new ObjectInputStream(bis)) { + key = (T) ois.readObject(); + } + return key; + } + + /** + * Serialize the given Key object. + */ + private static <T extends Object> byte[] serialize(T key) + throws IOException { + + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos)) { + oos.writeObject(key); + return bos.toByteArray(); + } + } +} diff --git a/test/jdk/java/security/KeyAgreement/MultiThreadTest.java b/test/jdk/java/security/KeyAgreement/MultiThreadTest.java new file mode 100644 index 00000000000..f53572a10b5 --- /dev/null +++ b/test/jdk/java/security/KeyAgreement/MultiThreadTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018, 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 8184359 + * @summary KeyPairGenerator Test with multiple threads. + * Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <Curve*> + * @run main MultiThreadTest DiffieHellman SunJCE DiffieHellman + * @run main MultiThreadTest ECDH SunEC EC + * @run main MultiThreadTest XDH SunEC XDH X25519 + * @run main MultiThreadTest XDH SunEC XDH X448 + */ +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.util.Arrays; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import javax.crypto.KeyAgreement; + +/** + * This test targets KeyPairGenerator API related issue in a multi threaded + * context. + */ +public class MultiThreadTest { + + // Tested a shared KeyPairGenerator with 100 number of threads. + private static final int THREAD_COUNT = 100; + + public static void main(String[] args) throws Exception { + + String kaAlgo = args[0]; + String provider = args[1]; + String kpgAlgo = args[2]; + KeyPairGenerator kpg = genKeyGenerator(provider, kpgAlgo, + (args.length > 3) ? args[3] : kpgAlgo); + new MultiThreadTest().runTest(provider, kaAlgo, kpg); + } + + /** + * Initialize KeyPairGenerator based on different algorithm names. + */ + private static KeyPairGenerator genKeyGenerator(String provider, + String kpgAlgo, String kpgInit) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider); + switch (kpgInit) { + case "DiffieHellman": + kpg.initialize(512); + break; + case "EC": + kpg.initialize(256); + break; + case "X25519": + kpg.initialize(255); + break; + case "X448": + kpg.initialize(448); + break; + default: + throw new RuntimeException("Invalid Algo name " + kpgInit); + } + return kpg; + } + + private void runTest(String provider, String kaAlgo, KeyPairGenerator kpg) + throws Exception { + + ExecutorService executor = null; + try { + executor = Executors.newCachedThreadPool(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = Executors.defaultThreadFactory().newThread(r); + t.setDaemon(true); + return t; + } + }); + CountDownLatch latch = new CountDownLatch(THREAD_COUNT); + + for (int i = 0; i < THREAD_COUNT; i++) { + executor.execute(new Runnable() { + @Override + public void run() { + try { + testKeyAgreement(provider, kaAlgo, kpg); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + // Indicate a task completed. + latch.countDown(); + } + } + }); + } + // Wait till all tasks get complete. + latch.await(); + } finally { + if (executor != null) { + executor.shutdown(); + } + } + } + + /** + * Perform KeyAgreement operation with a shared KeyPairGenerator instance. + */ + private static void testKeyAgreement(String provider, String kaAlgo, + KeyPairGenerator kpg) throws Exception { + + KeyPair kp1 = kpg.generateKeyPair(); + KeyPair kp2 = kpg.generateKeyPair(); + + KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo, provider); + ka1.init(kp1.getPrivate()); + ka1.doPhase(kp2.getPublic(), true); + byte[] secret1 = ka1.generateSecret(); + KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider); + ka2.init(kp2.getPrivate()); + ka2.doPhase(kp1.getPublic(), true); + byte[] secret2 = ka2.generateSecret(); + + // With related keypairs, generated KeyAgreement secret should be same. + if (!Arrays.equals(secret1, secret2)) { + throw new Exception("KeyAgreement secret mismatch."); + } + } +} diff --git a/test/jdk/java/security/KeyAgreement/NegativeTest.java b/test/jdk/java/security/KeyAgreement/NegativeTest.java new file mode 100644 index 00000000000..2e797e1ac5c --- /dev/null +++ b/test/jdk/java/security/KeyAgreement/NegativeTest.java @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2018, 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 8200219 + * @summary Negative tests for Key related Test with DiffieHellman, ECDH, XDH. + * It Tests, + * Use modified encoding while generating Public/Private Keys + * Short, long, unsupported keysize + * Invalid Algo names including Null + * Invalid provider names including Null + * Invalid curve names + * Invalid spec usage + * Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> + * <keySize> <Curve*> + * @library /test/lib + * @build jdk.test.lib.Convert + * @run main NegativeTest DiffieHellman SunJCE DiffieHellman 1024 + * @run main NegativeTest ECDH SunEC EC 256 + * @run main NegativeTest XDH SunEC XDH 255 X25519 + * @run main NegativeTest XDH SunEC XDH 448 X448 + */ +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.NamedParameterSpec; +import java.security.spec.KeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.security.spec.XECPrivateKeySpec; +import java.security.spec.XECPublicKeySpec; +import java.util.Arrays; +import javax.crypto.KeyAgreement; +import jdk.test.lib.Convert; + +public class NegativeTest { + + public static void main(String[] args) throws Exception { + + String kaAlgo = args[0]; + String provider = args[1]; + String kpgAlgo = args[2]; + int keySize = Integer.parseInt(args[3]); + String kpgInit = (args.length > 4) ? args[4] : args[2]; + testModifiedKeyEncodingTest(provider, kpgAlgo, kpgInit); + testInvalidKeyLen(provider, kaAlgo, kpgAlgo, kpgInit); + testInvalidKpgAlgo(provider, kaAlgo, keySize); + testInvalidKaAlgo(provider, kpgAlgo, keySize); + testInvalidProvider(kaAlgo, kpgAlgo, keySize); + if (!kaAlgo.equals("DiffieHellman")) { + testNamedParameter(provider, kpgAlgo); + } + if (kaAlgo.equals("XDH")) { + testInvalidSpec(provider, kpgAlgo, kpgInit); + testInCompatibleSpec(provider, kpgAlgo, kpgInit); + } + } + + /** + * Generate keyPair based on KeyPairGenerator algorithm. + */ + private static KeyPair genKeyPair(String provider, String kpgAlgo, + String kpgInit) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, + Security.getProvider(provider)); + switch (kpgInit) { + case "DiffieHellman": + kpg.initialize(512); + break; + case "EC": + kpg.initialize(256); + break; + case "X25519": + kpg.initialize(255); + break; + case "X448": + kpg.initialize(448); + break; + default: + throw new RuntimeException("Invalid Algo name " + kpgInit); + } + return kpg.generateKeyPair(); + } + + private static void testModifiedKeyEncodingTest(String provider, + String kpgAlgo, String kpgInit) throws Exception { + + KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider); + KeyPair kp = genKeyPair(provider, kpgAlgo, kpgInit); + // Test modified PrivateKey encoding + byte[] encoded = kp.getPrivate().getEncoded(); + byte[] modified = modifyEncoded(encoded); + PKCS8EncodedKeySpec priSpec = new PKCS8EncodedKeySpec(modified); + try { + // Generate PrivateKey with modified encoding + kf.generatePrivate(priSpec); + throw new RuntimeException( + "testModifiedKeyTest should fail but passed."); + } catch (InvalidKeySpecException e) { + System.out.printf("Expected InvalidKeySpecException for invalid " + + "PrivateKey %s%n and modified encoding: %s, %s%n", + Convert.byteArrayToHexString(encoded), + Convert.byteArrayToHexString(modified), e.getMessage()); + } + // Test modified PublicKey encoding + encoded = kp.getPublic().getEncoded(); + modified = modifyEncoded(encoded); + X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(modified); + try { + // Generate PublicKey with modified encoding + kf.generatePublic(pubSpec); + throw new RuntimeException( + "testModifiedKeyTest should fail but passed."); + } catch (InvalidKeySpecException e) { + System.out.printf("Expected InvalidKeySpecException for invalid " + + "PublicKey %s%n and modified encoding: %s, %s%n", + Convert.byteArrayToHexString(encoded), + Convert.byteArrayToHexString(modified), e.getMessage()); + } + } + + /** + * Test with all Invalid key length. + */ + private static void testInvalidKeyLen(String provider, String kaAlgo, + String kpgAlgo, String kpgInit) throws Exception { + + for (int keySize : selectInvalidKeylength(kpgInit)) { + try { + startKeyAgreement(provider, kaAlgo, kpgAlgo, keySize); + throw new RuntimeException( + "testInvalidKeyLen should fail but passed."); + } catch (InvalidParameterException e) { + System.out.printf("Expected InvalidParameterException for " + + "keyLength: %s, %s%n", keySize, e.getMessage()); + } + } + } + + /** + * Test with all Invalid KeyPairGenerator algorithms. + */ + private static void testInvalidKpgAlgo(String provider, String algo, + int keySize) throws Exception { + + for (String kpgAlgo : new String[]{null, " ", "", "NoSuchAlgorithm"}) { + try { + startKeyAgreement(provider, algo, kpgAlgo, keySize); + throw new RuntimeException( + "testInvalidKpgAlgo should fail but passed."); + } catch (NoSuchAlgorithmException e) { + System.out.printf("Expected NoSuchAlgorithmException for " + + "KeyAgreement algo: %s, %s%n", + kpgAlgo, e.getMessage()); + } catch (NullPointerException e) { + if (kpgAlgo == null) { + System.out.printf("Expected NullPointerException for " + + "KeyPairGenerator algo: %s, %s%n", + kpgAlgo, e.getMessage()); + continue; + } + throw new RuntimeException( + "Unknown failure in testInvalidKpgAlgo."); + } + } + } + + /** + * Test with all Invalid KeyAgreement algorithms. + */ + private static void testInvalidKaAlgo(String provider, String kpgAlgo, + int keySize) throws Exception { + + for (String algo : new String[]{null, " ", "", "NoSuchAlgorithm"}) { + try { + startKeyAgreement(provider, algo, kpgAlgo, keySize); + throw new RuntimeException( + "testInvalidKaAlgo should fail but passed."); + } catch (NoSuchAlgorithmException e) { + System.out.printf("Expected NoSuchAlgorithmException for " + + "KeyAgreement algo: %s, %s%n", algo, e.getMessage()); + } catch (NullPointerException e) { + if (algo == null) { + System.out.printf("Expected NullPointerException for " + + "KeyAgreement algo: %s, %s%n", + algo, e.getMessage()); + continue; + } + throw new RuntimeException( + "Unknown failure in testInvalidKaAlgo."); + } + } + } + + /** + * Test with all Invalid Provider names. + */ + private static void testInvalidProvider(String kaAlgo, String kpgAlgo, + int keySize) throws Exception { + + for (String provider : new String[]{null, " ", "", "NoSuchProvider"}) { + try { + startKeyAgreement(provider, kaAlgo, kpgAlgo, keySize); + throw new RuntimeException( + "testInvalidProvider should fail but passed."); + } catch (NoSuchProviderException e) { + System.out.printf("Expected NoSuchProviderException for " + + "Provider: %s, %s%n", provider, e.getMessage()); + } catch (IllegalArgumentException e) { + System.out.printf("Expected IllegalArgumentException for " + + "Provider: %s, %s%n", provider, e.getMessage()); + } + } + } + + /** + * Test for (in)valid curve names as argument to NamedParameterSpec + */ + private static void testNamedParameter(String provider, String kpgAlgo) + throws Exception { + + for (String name : new String[]{null, " ", "", "NoSuchCurve"}) { + try { + NamedParameterSpec spec = new NamedParameterSpec(name); + KeyPairGenerator kpg + = KeyPairGenerator.getInstance(kpgAlgo, provider); + kpg.initialize(spec); + kpg.generateKeyPair(); + throw new RuntimeException( + "testNamedParameter should fail but passed."); + } catch (NullPointerException e) { + if (name == null) { + System.out.printf("Expected NullPointerException for " + + "NamedParameterSpec name: %s, %s%n", + name, e.getMessage()); + continue; + } + throw new RuntimeException( + "Unknown failure in testNamedParameter."); + } catch (InvalidAlgorithmParameterException e) { + System.out.printf("Expected InvalidAlgorithmParameterException" + + " for NamedParameterSpec name: %s, %s%n", + name, e.getMessage()); + } + } + } + + /** + * Test to generate Public/Private keys using (in)valid coordinate/scalar. + */ + private static void testInvalidSpec(String provider, + String kpgAlgo, String curve) throws Exception { + + NamedParameterSpec spec = new NamedParameterSpec(curve); + KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider); + int validLen = curve.equalsIgnoreCase("X448") ? 56 : 32; + for (byte[] scalarBytes : new byte[][]{null, new byte[]{}, + new byte[32], new byte[56], new byte[65535]}) { + try { + KeySpec privateSpec = new XECPrivateKeySpec(spec, scalarBytes); + kf.generatePrivate(privateSpec); + if (scalarBytes.length != validLen) { + throw new RuntimeException(String.format("testInvalidSpec " + + "should fail but passed when Scalar bytes length " + + "!= %s for curve %s", validLen, curve)); + } + } catch (NullPointerException e) { + if (scalarBytes == null) { + System.out.printf("Expected NullPointerException for " + + "scalar: %s, %s%n", scalarBytes, e.getMessage()); + continue; + } + throw new RuntimeException(e); + } catch (InvalidKeySpecException e) { + if (scalarBytes.length != validLen) { + System.out.printf("Expected InvalidKeySpecException for " + + "scalar length %s and curve %s: %s%n", + scalarBytes.length, curve, e.getMessage()); + continue; + } + throw new RuntimeException(e); + } + } + for (BigInteger coordinate : new BigInteger[]{null, BigInteger.ZERO, + BigInteger.ONE, new BigInteger("2").pow(255), + new BigInteger("2").pow(448)}) { + try { + KeySpec publicSpec = new XECPublicKeySpec(spec, coordinate); + kf.generatePublic(publicSpec); + } catch (NullPointerException e) { + if (coordinate == null) { + System.out.printf("Expected NullPointerException for " + + "coordinate : %s, %s%n", coordinate, + e.getMessage()); + continue; + } + throw new RuntimeException(e); + } + } + } + + private static void testInCompatibleSpec(String provider, + String kpgAlgo, String curve) throws Exception { + + int validLen = curve.equalsIgnoreCase("X448") ? 56 : 32; + NamedParameterSpec spec = new NamedParameterSpec(curve); + KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider); + KeySpec privateSpec = new XECPrivateKeySpec(spec, new byte[validLen]); + KeySpec publicSpec = new XECPublicKeySpec(spec, BigInteger.ONE); + try { + kf.generatePrivate(publicSpec); + throw new RuntimeException( + "testInCompatibleSpec should fail but passed."); + } catch (InvalidKeySpecException e) { + System.out.printf("Expected XECPublicKeySpec to XECPrivateKeySpec :" + + " %s%n", e.getMessage()); + } + try { + kf.generatePublic(privateSpec); + throw new RuntimeException( + "testInCompatibleSpec should fail but passed."); + } catch (InvalidKeySpecException e) { + System.out.printf("Expected XECPrivateKeySpec to XECPublicKeySpec :" + + " %s%n", e.getMessage()); + } + } + + /** + * Perform KeyAgreement operation. + */ + private static void startKeyAgreement(String provider, String kaAlgo, + String kpgAlgo, int keySize) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider); + kpg.initialize(keySize); + KeyPair kp = kpg.generateKeyPair(); + KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider); + ka.init(kp.getPrivate()); + ka.doPhase(kp.getPublic(), true); + ka.generateSecret(); + } + + /** + * Return manipulated encoded bytes. + */ + private static byte[] modifyEncoded(byte[] encoded) { + + byte[] copy = Arrays.copyOf(encoded, encoded.length); + for (int i = 0; i < copy.length; i++) { + copy[i] = (byte) ~copy[i]; + } + return copy; + } + + /** + * Select invalid key sizes for different Key generation algorithms. + */ + private static int[] selectInvalidKeylength(String kpgInit) { + + int[] keySize = new int[]{}; + switch (kpgInit) { + case "DiffieHellman": + keySize = new int[]{256, 513, 1023, 2176, 4032, 6400, 8200}; + break; + case "EC": + keySize = new int[]{100, 300}; + break; + case "X25519": + keySize = new int[]{100, 300}; + break; + case "X448": + keySize = new int[]{100, 500}; + break; + default: + throw new RuntimeException("Invalid Algo name " + kpgInit); + } + return keySize; + } +} diff --git a/test/jdk/sun/security/ec/xec/TestXDH.java b/test/jdk/sun/security/ec/xec/TestXDH.java new file mode 100644 index 00000000000..135a469cba3 --- /dev/null +++ b/test/jdk/sun/security/ec/xec/TestXDH.java @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2018, 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 8171277 + * @summary Test XDH key agreement + * @library /test/lib + * @build jdk.test.lib.Convert + * @run main TestXDH + */ + +import java.security.*; +import java.security.spec.*; +import javax.crypto.*; +import java.util.Arrays; +import java.math.BigInteger; +import jdk.test.lib.Convert; + +public class TestXDH { + + public static void main(String[] args) throws Exception { + + runBasicTests(); + runKAT(); + runSmallOrderTest(); + runNonCanonicalTest(); + runCurveMixTest(); + } + + private static void runBasicTests() throws Exception { + runBasicTest("XDH", null); + runBasicTest("XDH", 255); + runBasicTest("XDH", 448); + runBasicTest("XDH", "X25519"); + runBasicTest("XDH", "X448"); + runBasicTest("X25519", null); + runBasicTest("X448", null); + runBasicTest("1.3.101.110", null); + runBasicTest("1.3.101.111", null); + runBasicTest("OID.1.3.101.110", null); + runBasicTest("OID.1.3.101.111", null); + } + + private static void runBasicTest(String name, Object param) + throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(name); + if (param instanceof Integer) { + kpg.initialize((Integer) param); + } else if (param instanceof String) { + kpg.initialize(new NamedParameterSpec((String) param)); + } + KeyPair kp = kpg.generateKeyPair(); + + KeyAgreement ka = KeyAgreement.getInstance(name); + ka.init(kp.getPrivate()); + ka.doPhase(kp.getPublic(), true); + + byte[] secret = ka.generateSecret(); + + KeyFactory kf = KeyFactory.getInstance(name); + // Test with X509 and PKCS8 key specs + X509EncodedKeySpec pubSpec = + kf.getKeySpec(kp.getPublic(), X509EncodedKeySpec.class); + PKCS8EncodedKeySpec priSpec = + kf.getKeySpec(kp.getPrivate(), PKCS8EncodedKeySpec.class); + + PublicKey pubKey = kf.generatePublic(pubSpec); + PrivateKey priKey = kf.generatePrivate(priSpec); + + ka.init(priKey); + ka.doPhase(pubKey, true); + byte[] secret2 = ka.generateSecret(); + if (!Arrays.equals(secret, secret2)) { + throw new RuntimeException("Arrays not equal"); + } + + // test with XDH key specs + XECPublicKeySpec xdhPublic = + kf.getKeySpec(kp.getPublic(), XECPublicKeySpec.class); + XECPrivateKeySpec xdhPrivate = + kf.getKeySpec(kp.getPrivate(), XECPrivateKeySpec.class); + PublicKey pubKey2 = kf.generatePublic(xdhPublic); + PrivateKey priKey2 = kf.generatePrivate(xdhPrivate); + ka.init(priKey2); + ka.doPhase(pubKey2, true); + byte[] secret3 = ka.generateSecret(); + if (!Arrays.equals(secret, secret3)) { + throw new RuntimeException("Arrays not equal"); + } + } + + private static void runSmallOrderTest() throws Exception { + // Ensure that small-order points are rejected + + // X25519 + // 0 + testSmallOrder( + "X25519", + "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000"); + // 1 and -1 + testSmallOrder( + "X25519", + "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A", + "0100000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000"); + testSmallOrder( + "X25519", + "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0000000000000000000000000000000000000000000000000000000000000000"); + + // order 8 points + testSmallOrder( + "X25519", + "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A", + "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157", + "0000000000000000000000000000000000000000000000000000000000000000"); + testSmallOrder( + "X25519", + "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A", + "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800", + "0000000000000000000000000000000000000000000000000000000000000000"); + + // X448 + // 0 + testSmallOrder( + "X448", + "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" + + "F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B", + "00000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000"); + // 1 and -1 + testSmallOrder( + "X448", + "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" + + "F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B", + "01000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000"); + testSmallOrder( + "X448", + "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BAF" + + "574A9419744897391006382A6F127AB1D9AC2D8C0A598726B", + "fefffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff" + + "fffffffffffffffffffffffffffffffffffffffffffffffff", + "000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000"); + } + + private static void testSmallOrder(String name, String a_pri, + String b_pub, String result) throws Exception { + + try { + runDiffieHellmanTest(name, a_pri, b_pub, result); + } catch (InvalidKeyException ex) { + return; + } + + throw new RuntimeException("No exception on small-order point"); + } + + private static void runNonCanonicalTest() throws Exception { + // Test non-canonical values + + // high bit of public key set + // X25519 + runDiffieHellmanTest( + "X25519", + "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A", + "DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B8F", + "954e472439316f118ae158b65619eecff9e6bcf51ab29add66f3fd088681e233"); + + runDiffieHellmanTest( + "302e020100300706032b656e0500042077076d0a7318a57d3c16c17251b266" + + "45df4c2f87ebc0992ab177fba51db92c2a", + "302c300706032b656e0500032100de9edb7d7b7dc1b4d35b61c2ece435373f" + + "8343c85b78674dadfc7e146f882b8f", + "954e472439316f118ae158b65619eecff9e6bcf51ab29add66f3fd088681e233"); + + // large public key + + // X25519 + // public key value is 2^255-2 + runDiffieHellmanTest( + "X25519", + "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A", + "FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F", + "81a02a45014594332261085128959869fc0540c6b12380f51db4b41380de2c2c"); + + runDiffieHellmanTest( + "302e020100300706032b656e0500042077076d0a7318a57d3c16c17251b266" + + "45df4c2f87ebc0992ab177fba51db92c2a", + "302c300706032b656e0500032100FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF7F", + "81a02a45014594332261085128959869fc0540c6b12380f51db4b41380de2c2c"); + + // X448 + // public key value is 2^448-2 + runDiffieHellmanTest( + "X448", + "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" + + "F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B", + "FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "66e2e682b1f8e68c809f1bb3e406bd826921d9c1a5bfbfcbab7ae72feecee6" + + "3660eabd54934f3382061d17607f581a90bdac917a064959fb"); + + runDiffieHellmanTest( + "3046020100300706032B656F050004389A8F4925D1519F5775CF46B04B5800" + + "D4EE9EE8BAE8BC5565D498C28DD9C9BAF574A9419744897391006382A6F127" + + "AB1D9AC2D8C0A598726B", + "3044300706032B656F0500033900FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + + "FFFFFFFFFFFFFFFF", + "66e2e682b1f8e68c809f1bb3e406bd826921d9c1a5bfbfcbab7ae72feecee6" + + "3660eabd54934f3382061d17607f581a90bdac917a064959fb"); + + } + + private static void runKAT() throws Exception { + // Test both sides of the key exchange using vectors in RFC 7748 + + // X25519 + // raw + runDiffieHellmanTest( + "X25519", + "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A", + "DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B4F", + "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); + + runDiffieHellmanTest( + "X25519", + "5DAB087E624A8A4B79E17F8B83800EE66F3BB1292618B6FD1C2F8B27FF88E0EB", + "8520F0098930A754748B7DDCB43EF75A0DBF3A0D26381AF4EBA4A98EAA9B4E6A", + "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); + + // encoded + runDiffieHellmanTest( + "302E020100300706032B656E0500042077076D0A7318A57D3C16C17251B266" + + "45DF4C2F87EBC0992AB177FBA51DB92C2A", + "302C300706032B656E0500032100DE9EDB7D7B7DC1B4D35B61C2ECE435373F" + + "8343C85B78674DADFC7E146F882B4F", + "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); + + runDiffieHellmanTest( + "302E020100300706032B656E050004205DAB087E624A8A4B79E17F8B83800E" + + "E66F3BB1292618B6FD1C2F8B27FF88E0EB", + "302C300706032B656E05000321008520F0098930A754748B7DDCB43EF75A0D" + + "BF3A0D26381AF4EBA4A98EAA9B4E6A", + "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); + + // X448 + //raw + runDiffieHellmanTest( + "X448", + "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" + + "F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B", + "3EB7A829B0CD20F5BCFC0B599B6FECCF6DA4627107BDB0D4F345B43027D8B9" + + "72FC3E34FB4232A13CA706DCB57AEC3DAE07BDC1C67BF33609", + "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" + + "56fd2464c335543936521c24403085d59a449a5037514a879d"); + + runDiffieHellmanTest( + "X448", + "1C306A7AC2A0E2E0990B294470CBA339E6453772B075811D8FAD0D1D6927C1" + + "20BB5EE8972B0D3E21374C9C921B09D1B0366F10B65173992D", + "9B08F7CC31B7E3E67D22D5AEA121074A273BD2B83DE09C63FAA73D2C22C5D9" + + "BBC836647241D953D40C5B12DA88120D53177F80E532C41FA0", + "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" + + "56fd2464c335543936521c24403085d59a449a5037514a879d"); + + //encoded + runDiffieHellmanTest( + "3046020100300706032B656F050004389A8F4925D1519F5775CF46B04B5800" + + "D4EE9EE8BAE8BC5565D498C28DD9C9BAF574A9419744897391006382A6F127" + + "AB1D9AC2D8C0A598726B", + "3044300706032B656F05000339003EB7A829B0CD20F5BCFC0B599B6FECCF6D" + + "A4627107BDB0D4F345B43027D8B972FC3E34FB4232A13CA706DCB57AEC3DAE" + + "07BDC1C67BF33609", + "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" + + "56fd2464c335543936521c24403085d59a449a5037514a879d"); + + runDiffieHellmanTest( + "3046020100300706032B656F050004381C306A7AC2A0E2E0990B294470CBA3" + + "39E6453772B075811D8FAD0D1D6927C120BB5EE8972B0D3E21374C9C921B09" + + "D1B0366F10B65173992D", + "3044300706032B656F05000339009B08F7CC31B7E3E67D22D5AEA121074A27" + + "3BD2B83DE09C63FAA73D2C22C5D9BBC836647241D953D40C5B12DA88120D53" + + "177F80E532C41FA0", + "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" + + "56fd2464c335543936521c24403085d59a449a5037514a879d"); + } + + private static void runDiffieHellmanTest(String a_pri, + String b_pub, String result) throws Exception { + + KeyFactory kf = KeyFactory.getInstance("XDH"); + byte[] a_pri_ba = Convert.hexStringToByteArray(a_pri); + KeySpec privateSpec = new PKCS8EncodedKeySpec(a_pri_ba); + PrivateKey privateKey = kf.generatePrivate(privateSpec); + byte[] b_pub_ba = Convert.hexStringToByteArray(b_pub); + KeySpec publicSpec = new X509EncodedKeySpec(b_pub_ba); + PublicKey publicKey = kf.generatePublic(publicSpec); + + KeyAgreement ka = KeyAgreement.getInstance("XDH"); + ka.init(privateKey); + ka.doPhase(publicKey, true); + + byte[] sharedSecret = ka.generateSecret(); + byte[] expectedResult = Convert.hexStringToByteArray(result); + if (!Arrays.equals(sharedSecret, expectedResult)) { + throw new RuntimeException("fail: expected=" + result + ", actual=" + + Convert.byteArrayToHexString(sharedSecret)); + } + + } + + private static void runDiffieHellmanTest(String curveName, String a_pri, + String b_pub, String result) throws Exception { + + NamedParameterSpec paramSpec = new NamedParameterSpec(curveName); + KeyFactory kf = KeyFactory.getInstance("XDH"); + KeySpec privateSpec = new XECPrivateKeySpec(paramSpec, + Convert.hexStringToByteArray(a_pri)); + PrivateKey privateKey = kf.generatePrivate(privateSpec); + boolean clearHighBit = curveName.equals("X25519"); + KeySpec publicSpec = new XECPublicKeySpec(paramSpec, + Convert.hexStringToBigInteger(clearHighBit, b_pub)); + PublicKey publicKey = kf.generatePublic(publicSpec); + + byte[] encodedPrivateKey = privateKey.getEncoded(); + System.out.println("Encoded private: " + + Convert.byteArrayToHexString(encodedPrivateKey)); + byte[] encodedPublicKey = publicKey.getEncoded(); + System.out.println("Encoded public: " + + Convert.byteArrayToHexString(encodedPublicKey)); + + KeyAgreement ka = KeyAgreement.getInstance("XDH"); + ka.init(privateKey); + ka.doPhase(publicKey, true); + + byte[] sharedSecret = ka.generateSecret(); + byte[] expectedResult = Convert.hexStringToByteArray(result); + if (!Arrays.equals(sharedSecret, expectedResult)) { + throw new RuntimeException("fail: expected=" + result + ", actual=" + + Convert.byteArrayToHexString(sharedSecret)); + } + } + + /* + * Ensure that SunEC rejects parameters/points for the wrong curve + * when the algorithm ID for a specific curve is specified. + */ + private static void runCurveMixTest() throws Exception { + runCurveMixTest("SunEC", "X25519", 448); + runCurveMixTest("SunEC", "X25519", "X448"); + runCurveMixTest("SunEC", "X448", 255); + runCurveMixTest("SunEC", "X448", "X25519"); + } + + private static void runCurveMixTest(String providerName, String name, + Object param) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, + providerName); + + try { + if (param instanceof Integer) { + kpg.initialize((Integer) param); + } else if (param instanceof String) { + kpg.initialize(new NamedParameterSpec((String) param)); + } + throw new RuntimeException(name + " KeyPairGenerator accepted " + + param.toString() + " parameters"); + } catch (InvalidParameterException ex) { + // expected + } + + // the rest of the test uses the parameter as an algorithm name to + // produce keys + if (param instanceof Integer) { + return; + } + String otherName = (String) param; + KeyPairGenerator otherKpg = KeyPairGenerator.getInstance(otherName, + providerName); + KeyPair otherKp = otherKpg.generateKeyPair(); + + // ensure the KeyFactory rejects incorrect keys + KeyFactory kf = KeyFactory.getInstance(name, providerName); + try { + kf.getKeySpec(otherKp.getPublic(), XECPublicKeySpec.class); + throw new RuntimeException(name + " KeyFactory accepted " + + param.toString() + " key"); + } catch (InvalidKeySpecException ex) { + // expected + } + try { + kf.getKeySpec(otherKp.getPrivate(), XECPrivateKeySpec.class); + throw new RuntimeException(name + " KeyFactory accepted " + + param.toString() + " key"); + } catch (InvalidKeySpecException ex) { + // expected + } + + try { + kf.translateKey(otherKp.getPublic()); + throw new RuntimeException(name + " KeyFactory accepted " + + param.toString() + " key"); + } catch (InvalidKeyException ex) { + // expected + } + try { + kf.translateKey(otherKp.getPrivate()); + throw new RuntimeException(name + " KeyFactory accepted " + + param.toString() + " key"); + } catch (InvalidKeyException ex) { + // expected + } + + KeyFactory otherKf = KeyFactory.getInstance(otherName, providerName); + XECPublicKeySpec otherPubSpec = otherKf.getKeySpec(otherKp.getPublic(), + XECPublicKeySpec.class); + try { + kf.generatePublic(otherPubSpec); + throw new RuntimeException(name + " KeyFactory accepted " + + param.toString() + " key"); + } catch (InvalidKeySpecException ex) { + // expected + } + XECPrivateKeySpec otherPriSpec = + otherKf.getKeySpec(otherKp.getPrivate(), XECPrivateKeySpec.class); + try { + kf.generatePrivate(otherPriSpec); + throw new RuntimeException(name + " KeyFactory accepted " + + param.toString() + " key"); + } catch (InvalidKeySpecException ex) { + // expected + } + + // ensure the KeyAgreement rejects incorrect keys + KeyAgreement ka = KeyAgreement.getInstance(name, providerName); + try { + ka.init(otherKp.getPrivate()); + throw new RuntimeException(name + " KeyAgreement accepted " + + param.toString() + " key"); + } catch (InvalidKeyException ex) { + // expected + } + KeyPair kp = kpg.generateKeyPair(); + ka.init(kp.getPrivate()); + try { + // This should always be rejected because it doesn't match the key + // passed to init, but it is tested here for good measure. + ka.doPhase(otherKp.getPublic(), true); + throw new RuntimeException(name + " KeyAgreement accepted " + + param.toString() + " key"); + } catch (InvalidKeyException ex) { + // expected + } + } +} + diff --git a/test/jdk/sun/security/ec/xec/TestXECOps.java b/test/jdk/sun/security/ec/xec/TestXECOps.java new file mode 100644 index 00000000000..58f175391df --- /dev/null +++ b/test/jdk/sun/security/ec/xec/TestXECOps.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2018, 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 8171277 + * @summary Test XEC curve operations + * @modules jdk.crypto.ec/sun.security.ec + * @library /test/lib + * @build jdk.test.lib.Convert + * @run main TestXECOps + */ + +import sun.security.ec.*; +import java.util.*; +import jdk.test.lib.Convert; + +// Test vectors are from RFC 7748 + +public class TestXECOps { + + public static void main(String[] args) { + TestXECOps m = new TestXECOps(); + + m.runTest("X25519", + "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", + "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", + "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"); + + m.runTest("X25519", + "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", + "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", + "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957"); + + m.runDiffieHellmanTest("X25519", + "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", + "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb", + "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"); + + + m.runTest("X448", + "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a77" + + "9c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", + "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc0" + + "31ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", + "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fba" + + "adeb445fc66a01b0779d98223961111e21766282f73dd96b6f"); + + m.runTest("X448", + "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345d" + + "d77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", + "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d01" + + "5894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", + "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3e" + + "e3a5700df34321d62077e63633c575c1c954514e99da7c179d"); + + m.runDiffieHellmanTest("X448", + "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9ba" + + "f574a9419744897391006382a6f127ab1d9ac2d8c0a598726b", + "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c1" + + "20bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d", + "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" + + "56fd2464c335543936521c24403085d59a449a5037514a879d"); + } + + private void runDiffieHellmanTest(String opName, String a_str, + String b_str, String result_str) { + + XECParameters settings = XECParameters.getByName(opName).get(); + XECOperations ops = new XECOperations(settings); + + byte[] basePoint = Convert.byteToByteArray(settings.getBasePoint(), + settings.getBytes()); + byte[] a = Convert.hexStringToByteArray(a_str); + byte[] b = Convert.hexStringToByteArray(b_str); + byte[] expectedResult = Convert.hexStringToByteArray(result_str); + + byte[] a_copy = Arrays.copyOf(a, a.length); + byte[] b_copy = Arrays.copyOf(b, b.length); + byte[] basePoint_copy = Arrays.copyOf(basePoint, basePoint.length); + + byte[] resultA = ops.encodedPointMultiply(b, + ops.encodedPointMultiply(a, basePoint)); + byte[] resultB = ops.encodedPointMultiply(a_copy, + ops.encodedPointMultiply(b_copy, basePoint_copy)); + if (!Arrays.equals(resultA, expectedResult)) { + throw new RuntimeException("fail"); + } + if (!Arrays.equals(resultB, expectedResult)) { + throw new RuntimeException("fail"); + } + } + + private void runTest(String opName, String k_in_str, + String u_in_str, String u_out_str) { + + byte[] k_in = Convert.hexStringToByteArray(k_in_str); + byte[] u_in = Convert.hexStringToByteArray(u_in_str); + byte[] u_out_expected = Convert.hexStringToByteArray(u_out_str); + + XECParameters settings = XECParameters.getByName(opName).get(); + XECOperations ops = new XECOperations(settings); + byte[] u_out = ops.encodedPointMultiply(k_in, u_in); + + if (!Arrays.equals(u_out, u_out_expected)) { + throw new RuntimeException("fail"); + } + } +} + diff --git a/test/jdk/sun/security/ec/xec/X25519.iter b/test/jdk/sun/security/ec/xec/X25519.iter new file mode 100644 index 00000000000..239b2cb0cb1 --- /dev/null +++ b/test/jdk/sun/security/ec/xec/X25519.iter @@ -0,0 +1,2002 @@ +0,k,0900000000000000000000000000000000000000000000000000000000000000 +0,u,0900000000000000000000000000000000000000000000000000000000000000 +1000,k,684CF59BA83309552800EF566F2F4D3C1C3887C49360E3875F2EB94D99532C51 +1000,u,E4BA7DF230E7574D397D88E1E18069D405DD71C6A286086DDA6CC54D04F69A18 +2000,k,DBAF93A66BBE098551040FBEA14B5FF3EF4DF696F1A55BB44749265DCDF5DE3D +2000,u,2611734027FED424184FAC583DAFDA42CB089655DE50C84BB703EC8E98A50B10 +3000,k,CE14DEA80A92A944C215915A4ABEE253B2FBA7ED7874EBB0AF34F903D397BA33 +3000,u,1BCC668626936CCBE8890F4442EDF3FEC2A72E7689B4C00075C6BB102321F647 +4000,k,1A8C16163A394975E98CAA730CDEF215778684AC3D19A249D4487B1763A97B49 +4000,u,D50599172794263E7D35A3096867074042C643D82F2A835476A75F1387FE8E5E +5000,k,90ACA1C8DAB080CCCF82D3E972F2DBAC319E1A1424A77852A8B57A5957458353 +5000,u,29C4B177223CB60BA995EE2F5E3E556DEFE3D79743FE2D83B2ADA17DA1B85D1A +6000,k,BCFF817ACA4621993B9927C2E6F8FE9C2A292842001DACFAE358CC47A40B166D +6000,u,18D50EF8C25F117F4A5B54282FA52BB4C76BDAAF9E7B175EA4B21C22219BD74E +7000,k,7087B0343D6A878E498541516BA953EF83D956A2FE25D54F792FCEDDD52C1365 +7000,u,C7B11D99ADA1E5C9F49BE5728BB67CF6A29095DB6B1588D9E6D6FF8DA0AD5757 +8000,k,1D94A1C031421A883CE8767563946FEA343806D035B1705DC042BB2068A29311 +8000,u,5CC6ED6699ECFCD97D1C7198F828431AAB8AF1DBF628A5F7959B384AC01EE75C +9000,k,AF982B810595122705E73AFE142C16946C74FB2DB13E46AB928A0F431049612B +9000,u,7CDFFBCA7286187233C7D62ACE0FD09500595197D309E2DA7F324D767955A263 +10000,k,2C125A20F639D504A7703D2E223C79A79DE48C4EE8C23379AA19A62ECD211815 +10000,u,6ACC9309A5CC14E183DC85DC8C836A0CA2877A753AFBBDE0CF93A86303EA4E7C +11000,k,C4E6F26C29C5B0EBB6AF8424B52A3A344D4CC1C88688BE30DE470C8365D4F172 +11000,u,C6164460467B405E3070F0875C5CFFFB0B2EA45C35D7180F6B50AEBDE9E4A833 +12000,k,5E4B725BFE2E1D9B28DD63C94EF4316E0BD8E573265929716F2AD2A1224A7E60 +12000,u,FFE119058D2C17DBB54A62ACB2019C3F979D0093FAABE9C13512D272F04FBE3D +13000,k,C89B8104D3A34752054FF5388CA29D16F774FAAD089F7F420D3DE3580C82852E +13000,u,5269E0A26661DB2BBFD5617E1C69F38DC01D5668E8D19C08AFD36ADAA07FB911 +14000,k,83D255FAEFD850EC7DA5472607250FEC1E2ABAD0B155E7C7472E5F5F23556A3A +14000,u,0A7D73FFDA2AA9B986A07A1823BA412F5ACFBF1D01E3DA7E93502ACE5D862264 +15000,k,EA0E0194B81C833B2DCBC095837E38C5F73EE9E6A628DDDECBB441894B299E7E +15000,u,9F5BA6574A39F46D0912910D03D38279A511591A7D788F185A1915A77AFD0723 +16000,k,05E8938C734A5A17D1B61902C98C5DAFEB1A380489DE253B83B2626DEEDD7325 +16000,u,D5DA6049A9CA1DA64BC5239AD53BD3D20489EB9427CF8628E95C44BC6FF20162 +17000,k,C2EF62DF60959AB818E24FAFAFDF986206EB70C236973E3F2FAFD176CFDFDB32 +17000,u,AD41989C464001732C8840784264DCA13081035F2AA6D06059A0EDA14D486644 +18000,k,26B58D28F6E5320C09EE471A68EFDD0EF48DB378B776DD2D337567ED6405073A +18000,u,24061DBCB41E42A82BAF92EA526CE28B9B33E71C9825C014397DF6791C28EE01 +19000,k,825251693275AE5E523743061C31AACBFB90A17CD206DF1AE3D07DE11D031C32 +19000,u,697305DDB3C2A15C5255BCE0E59CD203FE274DA8FF9EDD9D0E0E4EEFEFD95240 +20000,k,D4AB9827C52324822CC439FFA27107B9824569EBCFAC15BD490F732F90E0B13A +20000,u,7072DDE149F9852704AFF14D64E438B89D6C00724E524D8FB31B6EE11079667F +21000,k,1A5111535180DF903E723CBD64C7C960AC3491F6BA0620E0283395FE60AC9F0B +21000,u,E77127E3657A4989BBDE6D7D923304AF58B3DD3DE376542D5D88835BF2DB6104 +22000,k,CC18D1C57D0E7FD8B8F977FF1BDBCD957FF9CA0FC87635A5ABF39DFFF6D7D538 +22000,u,C8C16D8086D4EC46AB4E198672050DA1D7CE645031F8FCD76313181BAB66844C +23000,k,FA716F22996C9B1ABF7B0F5511289198B32CBA05266BC684B3B73EFEE9272A6F +23000,u,566812D78EC7B648CCAF21FA36C1553B2672A5E66E5F233BF2D69E1BB84ADB03 +24000,k,460C0430698422EF91D1E66DF4812F3F561B5539D453DEE0DDB97D00E143CD7F +24000,u,94F86BC176145A4CA1774B12398956D1B3926C46FC3992808B564CA9531CFB1B +25000,k,3D2318858E8F4068C51BE1FF0BCF7752BEE04E91D147597B4FF3AAC2301EFB3A +25000,u,1F6F66591E2D5ED239E1CB94EBE39D4118757D1355394519700F6CD47DF53826 +26000,k,D10C565CF35C183381EA9F2FA7DC953A517970F63401D79F979A47FA38B0DD28 +26000,u,1E3D11E601614D5472352133CF684560FF9962CBF88911B5D439E2A00D8D9807 +27000,k,D736F4E57270CA7C88B89BD351EF603AC6036D43303BBAA81D252A484380DF02 +27000,u,9FAD30E3B3DD8A1818B8698D219B6E81641BADDD3B614F0610AA11DB01C55F06 +28000,k,40C4E27F8C31E513B16B105DB6D565DE590B2CEEEF1D461B3807C38F100C0C45 +28000,u,C1ABD6DCD238F50ECD656561C6154148C6B5B40D99C0584FDEA6872BC6F8A935 +29000,k,E04C7CEE2145E25B828048995C9EEEA93739524ADDF2269D915BAB8CD31E352D +29000,u,A48DFE1499ACB3EEF428BC538401C697BC8EBFA213786A9D028D9182309C2C09 +30000,k,7BEC00362BE91E93D3157888A7A69D6AAF56DCD31703C64629C07FE1CAD6A769 +30000,u,3A8E96AA2FBF376E8E84437E6AE29721485866E92AA2011D5E7857BBF2E7714B +31000,k,B2AD33A0062E8B0210FD0B9466C4E69855C42DA8CDEB51839FFB205C247FF810 +31000,u,12E3A58CED72FF896678ED067911979871F01FC0F825BF50303CB7B893680B46 +32000,k,7767AD25FB29AB74585C798383911A1AB8EABA96CFD2B7C49CF38DF75631E565 +32000,u,1DBCB69D897C2DF04413529BDD1ED957D3FE3C09DC0B7BDC935541A99E4C9A35 +33000,k,E0D9BB103F2C311AC1A12D657AE48EC995048EDE3617332FD588932ACA7ECD7A +33000,u,6422DEB8AFBE10C82C1BD59DE5A1C008E7C7788AC1586A836E48C232A8FAF97B +34000,k,47ED96A302CC9026F63907308A4701195B5205C936E90F605003C648546C1774 +34000,u,29DD859788D2D5C9C0B9EC4DB787DC499711D3A0E15F487F45AC59216865324F +35000,k,53C4039E42479CA8F4325363C5E6D001C38F6644598EE89E4A001B1EB987480D +35000,u,049F7707038BD7ED081DE2BFA476B27AFFA96F6CE68DF3B30BCBBB164E77632A +36000,k,57776ECD6439E18A904A4B6E499AE12D80B3CA0C18B3C98B4647768FC7190D0A +36000,u,016F35C5C89F01BAC3217222CB37AA21297282A2AF647209A48CC1233D37044D +37000,k,6F322C979C44EAF6713912F64EA3DCCCFB96A7E56CA8FF377272D6BA1C4CD418 +37000,u,C2D59C3BD6F85E5C28C585478B778EAAE2F3E700BB5248AC09BA3FA811B7EF2C +38000,k,99E258131078603922C705C6CE9F731C3CDF51F41F838A2DDD771FDF13B30B1A +38000,u,F6CB3493075223B49ECB18BAEB16267CE34E8BC9189FC705DFEB8746329FB25C +39000,k,9DAE24C03BC0D602166608E9E71AA3059601660DDBBA2577920EB345AB8EF354 +39000,u,247C4617ACC6434F7CB3A0CB6B6202F0CFEEC6A2F157B3EAFD4B813418DD206A +40000,k,3355456F77EADB57CF1A4B5ACFCDC04079CDAA25A780E4CF49F4B5A1EE97A476 +40000,u,46BDE8169C0079FB6B39288CF3F07FFD9AD2D0A3B3DB0DD83C7C6666168AAC15 +41000,k,6E6ED2B1FF4F0D4C3BCC146767398517A3A6B5A1B0ECEE9509DD38407C725716 +41000,u,230FAE801154F9035FC6641902F14B7CA06095975D0A3148F685A7F804E94C6C +42000,k,55E911DC3BD54AA3F1CA6065CF8D25C7D07C9E4FB4BAA8CFDF4D4F33C81BF74F +42000,u,07D4BDA4DB042EE7BD1BE3BA823CD90C49AED986AB667FAA5B0BE3B76DFA3B0D +43000,k,CF19918515842FEB774E685671157A3F9DE4794FA96F89EFF954C6D1AAB2981B +43000,u,9DE722697FD40F7C74DE44BB85C22C78E475D4A9B38F98A6C5AD245CCF28DB7D +44000,k,CCA2BE3CC8E1A01F6533D847C99843E18FCAF9CD0EB9605C46B5481DB0376207 +44000,u,3BF0A66E59F277F721D052C400CC798271D521B69880F94A7EFED33624B02D78 +45000,k,3182A4666FB1A70281792F98B829F2FD7C40379833536EFA6F513FD2EEC8760B +45000,u,0BAC348AD6A7DACC520822D23038333B1108FE76B7C7782B5616A8F1251E047A +46000,k,5CDD71E8BB2F7542566C6E42CD45E3E7CDB9238BAA4E96461E1F5C9B035F1405 +46000,u,B11D53A0DD18B2FF5A5AB0082F8471809B996E8565BF4B61D4AFF141EE2F1D47 +47000,k,69DBFBD1FAD63A15D34F3CABD5B4CBF42AA9C29F3D27A1CD2C568BB5E6E39559 +47000,u,852F7F6A41413ABA1E0188FD328988F952BBA7298023B8BEBD3233329F23AE46 +48000,k,A2A6184A1DEC235A4D1A1795C8BA0E8C186C2335D67A75973868CAD11EEC363B +48000,u,89F441E56333107CDFDEC5DE38FB31DBA5A7C5FC59961838CA5B50A0DE659F4A +49000,k,D827CA567E6ED98E761823A8E02DF2C03A3CB403F27DE427A424338C6866497A +49000,u,4E9B5A2E2031EA4D964CB8BE0617CC0F669B6D528D199EC48FF1E6314A5E996C +50000,k,1670488F039B8DE4310A4D66AC713C9A59FE4E1375E38BED432D5AC232A18676 +50000,u,7FD865D809E8E47F308C68BCCBF2CA9451EAF49319CCB2FE362C83FC5C11C743 +51000,k,41D9A07A8A2E9B403F8577C67565EF6DAD4862ED0FE8469B8742185EE333F377 +51000,u,A07535E8BC108A135C0CC9441CD38F44DB89A24B66A5C8396713401F2F60545A +52000,k,594D0199A47A45A2F447D722053E2DE8B30E1A234EDF3AB56F7721787F5B3E68 +52000,u,D686D468AA9BC461CED3864E3E99694B9C893BF421AA31771FB3F811E0A2E863 +53000,k,39015CBF722FC40E4C4174C0E2D3010A5D844E8747F7034674EF4F6DB36D860E +53000,u,B6F96213A32591B26EE7E925C578513A82146FDD756A18904E2F223F63908433 +54000,k,E7B84E0ADBB5FDD8CBB7C3760DD7B3A239424E74DCCF3BD3EEDE8E834D69F707 +54000,u,55EDAF4587E8F64B8F47A74490D4E1B3F51F62904C8EFB1E8C0154CBB3F8FC12 +55000,k,5E308C20E59BF534312A6814290009CB38FBC2A3E5B9CE0133FCD4F23EC8457B +55000,u,125E06B78416F05664E7896BF9A0DE40D2B49A04B537D220E8FF3209FB1E0169 +56000,k,AA3B9ABBD0CEEEA33BC20999556C5CA45D4C564FBCEFBF98F20BFF4D8DBF8970 +56000,u,F2481EC74E6D93358EB0F260412437B282AB035DD34465DE88A19D8929E93254 +57000,k,D90BF9BB2DCCBDDD1AC55CE7B09590EE45C54C0B55C9A9F5BC18232E7759D80C +57000,u,8DB1286CACAEF34FB19CBA7068265B4E2DE6C90B0DB98C5DA4695AAA9FAA864F +58000,k,AD9D880CE60264C715AF696A389D609C64C27AC064F58631F4C2165E5FB8E62F +58000,u,852BD6F572E7A828DD777E7A423FBAB25E1F32DFC9603852A2CD2ED7C714735B +59000,k,24A2E5BE4F1D2908984E62D324EAAFC748C3B339C9DB893C40261C515109A815 +59000,u,917CFB5DE8258C989ECA0F1C47D35ED93F6D5ED7CD82E1A963E3A7F5E1499802 +60000,k,C3837E8A9EBDB1CB53A8A22B5E0813AF948692FD0B6E12CBA8DE6720DA31752A +60000,u,5226429B3505C6763B97F95F4DD4668400FD754D0471569190596D8E4B963274 +61000,k,1A8B466BAD74C0BD61FD40604692364BF6F80F70611E10939888B63917AD690F +61000,u,DCB93232378B30CD996536D385DC196248D2A2F232E6148A1827C399ECBEAB32 +62000,k,7729594689384016C678A1C2776A7C9BAD1BFB448FEECE549707570B011D7E25 +62000,u,E13406D64DEAD6EA75DF3BCC869A7C83A12A502237BD858AB4C31740FD2CCB63 +63000,k,D6A2B9E6BEEA5DBA89552480C4CC25B3CDA8F160DFBC2D01DE92D4F61D36DC46 +63000,u,6026354144B74F2DDD52D0B5C64629F1929A0B6E261F5D9D915CD8BB98F9301A +64000,k,0944798F67950748E231EA78285E5D43C6034B557A6486288400DD83CC840521 +64000,u,4359D36946AF525931B37A61895521644F14655299EDEF22E92BD15E20BEA11A +65000,k,512454D18396A744612E61F6AE4F0642ADBF34BB1A727037B489A51ACB3F396C +65000,u,4B102C3615964024B50FBAA5884D5876312AD60F02681B2E892B1B83315BCC3E +66000,k,BDB47EF6BF2DAF2985B8D22F767EEBCD8B91E6C9B27FF23FEDE528E412B22A6D +66000,u,970028923DA15BD75DF19D435A93C771A6FDBE18890652AD5DF968731FCABA35 +67000,k,75991576E82058347E0FEC4AEB319D40929CBB3200C859D7B5C2BD9ED0DD383D +67000,u,EDFBA1B230E802C2FAE53E8B8A3FCAE8D739330BE8811E56EFB3BE85D4256F02 +68000,k,2A965836CEBB7138008A470393B2F37C635326B7E8DF7DB894114E19E294E905 +68000,u,48A66EBBF1F0030E0B98C9E9E56B4CCB2D35477B7E4B6055BE3448004BF0921F +69000,k,99C080CB7CBF4E803284083EE02623045535671367E5E6DB170C4C9FDF07605A +69000,u,BA3AED98D637D99FBE6BB03CEA6AF9D29ED3D7EFE7245A9CDD43B689CB2A3C5D +70000,k,56B5FE84D2432D649C00A5E1CB2F7CDAC2E4C2754D49EB80AA77E239838BBA23 +70000,u,20D0B187CDC6B97247422E9349BD155EC5BD55CDC992BAEA60225704626C0D77 +71000,k,8E4BC06B142D5F4438655CA2944777DE7A06F10B0FC31EC36716825EB678C50E +71000,u,DAE1AC0DAC80364B7960F03155B3A5B81885F2DAADA89CBB1BE894AEF48D4C34 +72000,k,1515A390FAC8B37ABA600D62D93465F57AF80D4D2A64F8AF4BBE46EC7C14682D +72000,u,BCECEC2B80CC74393D2640DD3C6E92A003E78626D919BBF25B3D9153B5DF2277 +73000,k,2190845A178A117D4A13C9192B047C1DA399DA826E60BB732DC16CBB2020E655 +73000,u,F64E9CB66BADB712E1FA219E7E3A281E896A0B0EB4AC53F205CAEC180A079418 +74000,k,C218BBBE5E6783E43B82E8354602E2A852E217AFECF701686345F62662204F18 +74000,u,2E85BC5F3D20F40567B04113E3309F49A0E8CF9FB9EC5A4BBA328D74A82C6131 +75000,k,3456B940880EAE561031ECCF0516495434BC02C77F641C308C1F5D8ED0FBB813 +75000,u,874435971C8EF0565B4CDA5690F8306601E67DCC09CE216FACEEB00C0393FE71 +76000,k,ECED5E21BB7AC4B719176FAFDE65E90727C46E6B422758D3FEB97B15BEE3152B +76000,u,BF0D98ABE680D1781EE51B16A1BDA5F1A99DABD1963C9CACB803552023174511 +77000,k,6D9F2384CE504DF4B67E2394958F087FDEE070F5C73671FA4A1E1AD8704BCA5B +77000,u,1C3CC7713907E9FC8EACF48676A131B9DCF79DF3CA56EA72EC231C570C030D2D +78000,k,61F7389E665FA57DF529BE08D958CABA6E1FF730BA93FC5D5F677BD60487BD4A +78000,u,10F8F735D23AEAE9DE83F324D54A9C0CA030A9E6D1A3754C4905E993060AC03F +79000,k,1087F8B7CD345164943CA995A895321B9F47D97D26A3BC321AE652ECDA81433B +79000,u,5C1DE67529C3A145433436054493E17C164E984A4AFEB24A4DB21BF70FD02B62 +80000,k,D82E9FAE3F6F9F8674AB20C5D1FF204A2F39E3F46BC6F3D6E0299E6EF4A0707D +80000,u,B7C9D2D56B9D1B692164EE82CDC06E22FCA56C50CC506704D63F51F36191283C +81000,k,7022A6DAC0EC0B8157BD7BBFC4B5639B026E139C88D0BC10F9D336BF58628E0D +81000,u,6923B80BA00181C79A5DFAF2E30EC396BEDB210BE92D812451F824652D937A1D +82000,k,4CB8CDAE80A8A63EE6024A44A965CE414AC343F11F102BEEB9FBCB950358227A +82000,u,6D3166CA1F6703DA0C181D873F87542D7BD3863AEA1AB826F54738C64A495918 +83000,k,64F3B4892DAEA7F237FEB9233DB504BCCB5C3F696BB8997D74DA7A6636646D58 +83000,u,A0DBBB2F53FD4EC76E9C2B845EE5C41BF615BD9B8D5B9D230F4FB696D56A320B +84000,k,B66E2B87B30A4DBD803D7E6CF27C80981D149FBBB4A6489147AB93F362825553 +84000,u,2FA45E24D13781E79AC25D33EF9878206D904E8A36A9E6B5EA652C81589DD233 +85000,k,E8961108853C11B6428C5B7C7DDD94E80F5A752ABE0658CB31A1A7B3437DAD6F +85000,u,B0CACF772890B6428C23406D2228CAE171BCFA5F0696BAC6AED0594E52993468 +86000,k,47854F1CB0C9582CD0FC903B282F597BFD2347A26F74C35CAFEB727F84F81A6F +86000,u,9C7ED575787C1D9882070AC3B8374575BEC33B06ECD9DBE835811BDDA0EB7734 +87000,k,E127EF63813FE0BAB0BE7DCF57EF0DC8CF22750257A56F726105761B5400752C +87000,u,252BFDDC3E61903F9EED3110543B3BE8D48E3C8378C67687CD132A55D924C45C +88000,k,C238456092AA788B80DB0B49F676834496386B5E101B7C9DC52394658887E933 +88000,u,098D844AF222CB5D7455A3326FE96B74B837E4BE8E478F7D66E3D89EC6EEE862 +89000,k,F71BED16476B1C0142BEE96EA28C4C4531E7ED5E17294BB8C36D329D93CC8509 +89000,u,AAF8E47856A9070D4DBBFBE8BB2532355459EC649AD9BD5A9FCACD829ED1E20D +90000,k,594BFC44E59E093EAFF191B2213FFBEECC11B86F3A99D6BBBF6E7B04C83FFC75 +90000,u,5C9A9489F64832D4C465456FEFFF545F4B06A5E36BE2EB9DA0431772DF6E976C +91000,k,2C4565F3EAB68E93A9D88AE17C8CF82B7AAAB88D184867CD9B0BA3D6DCA0A859 +91000,u,784BCD70F52645C190EDB095822F549DD01C08266F6BB18C0E6EF90B9F376D7D +92000,k,E130D55CA100A809423C6B07AA43BD32906BB102CD7915AE16541055CDF3571D +92000,u,31E2BE333664769E33BFD323802F35C4DA50DA4771BD55171E1820E0AACCE32F +93000,k,7B7CA1DE6ED5883776F5D7D23C701259B505643CA73F8FC37E1BFBA3E1E4C31A +93000,u,C0064E1F4E6937BB6E15F440DE8D6518FCFAC0BBC83520448116E69EF68C4503 +94000,k,672D6157F57429E734B62655F89FDA8FECAFAF8FD680B640289499F473E2947D +94000,u,DC9693725D7C27D78518BDC9C1DB31120C6BC147AE4A92153E99B54A53277001 +95000,k,20E324148EDE19A6CB1FE79854EADF81CC893D3E3CFCCB7F5210142CAFBF6844 +95000,u,EAC38B042F246C33DBDC5341F6ACA985C6F4138ABD4D0DA88BE33F7C17BF4F5E +96000,k,1B6DD33A4D7A442B2EFC86365165DEEE48440952EA4628F1FECAC54244039440 +96000,u,1BE7ABA79AF1695F66109CD06C652B8420AD3F8C7F112946A871297DC8EE3F63 +97000,k,9EC88ADD1BD17C1F5DD0F8D66404118EFABC040E9FCBE3D0C2C80B6C5471D25B +97000,u,09F48BDD69F68D59DBEA177101DC79BEA438C4259BB278D302D8B052A3EF0766 +98000,k,F683B4432899A130C3E2537EBB5F51DF4AA9E76923B474FDA07C41CDA2CC904D +98000,u,A9C1CC5918F4408B9600AE466CCF20722E7D7D3B47E62D1A2ED19748A7422737 +99000,k,6A9CC95849379F9AF97A8B52FACBBCAA77FC668562B3BEDE487B20893F72164B +99000,u,ED755781CE6E4C143F82C4CD16EBB38D162E6C1515D7CE89598038682D2FBD77 +100000,k,58698A8C126B120405697D7B449257F249ED4EBD8B3E5478FBF6A23C7FF17529 +100000,u,BC41FCED43BC8050CBAC264C413175B97D043CF9D1477A2F18BBC36687E2276E +101000,k,55AEDFE326A5379114FE47098DBFEE50CD2E4E2910E91ACEC9475C1EB396E308 +101000,u,84C93CBCF7BD1177DFAC136C02E9E6D540EC9EEFE7FD94263AA33F7F55EA2B46 +102000,k,6BB209724357F641A9886EFC1ACE0415D5FA9C654813BD927EAF48E5BBE2774A +102000,u,C2A880B8B0DEDD2787DAAB8405D367C5C66BCF894DB63F7DC080B70450737C29 +103000,k,7CFFFD12304E346E8F319E6162E0A56D6130460FF813DC257FF8663011FFB47D +103000,u,EB5D06A20250A56E6DCF4E54A24D07A8D32A9320F4C9DD0ED2E7CC7F49F4616C +104000,k,609CF91D0A5CE81547841A179139363B294C73246AB53CD3B3660BFBE6BFE034 +104000,u,0547D6694F9ABE2E41B443877ED990A24E7C3D4175A39A6ECC76790DAE3BAF62 +105000,k,F62E7D6A3A0DCF3F467F48E3565C411B2C00CB237BDC4668947C74D96627B946 +105000,u,F9DDFACC6AA93188BD504E244F82C674562EF5B581652BE909AA35DDCC511F3B +106000,k,0A469CDB734D596639BE93B22C83EBA52FB36C806AEDB80422ECE12079B3B267 +106000,u,8F2AEC9EBCCF282EAAE270E58F1F579B31DA7ACD82FF31981F21180CD352EE39 +107000,k,3CC78899D528A6830FB9695D9CC0022A6821277441EF3856999A9F5D6AF32945 +107000,u,6293AA53092A584E9179CD86DE39B211ED91C1EF69815D2C49897CCE29AA8A46 +108000,k,CD48CCBB30F2B321DEA5A52C473C5A2D94E4E8FF6308554CFDFB66C8CB4FA763 +108000,u,3F96C469F3EC2BC8F48C32CF0BF7D4B5C8C2163FC6C8B4DEE9D51BA3EEC07A75 +109000,k,746C4EFED958D0FBAA152F32CE89D47DD50FDA699E82D4EBFDC6E46E85471826 +109000,u,71672B4EA648790C0C589762F7C7A2572D1273C8655B986DCB498665DE737249 +110000,k,68480BDCA4BB97143D2804CDFE243620ACA83D607E2A72BF7255E9F2764E9C7C +110000,u,104677450A3032E0AF7BF084AB136C85EE5E93A77A739BCBA0D3839AF5D26932 +111000,k,FE32B2A585878493698AA22EDB898886A1BBAE16A2C10289401FCF9A6DB4FD5E +111000,u,F7B6427BA2A9F2D68B8BBA42C1FBD4A36C8CF751933A9078D8999EC8BDDFCC51 +112000,k,BB1B056873C344D1A982BB5AE4AAD767B685011CC287D0FC38209108C6CA5411 +112000,u,3D3A3680D0A71E0D5A14006CE3751C8CCC6E570C9D35FDF9135A3AF19126406B +113000,k,CC4C65C17F2BB2F1C14AE066E7A88E8A0B6F2C545E1FEB83584B7DDD2B49271C +113000,u,69D7469C45C868B6E1A4B1F3734C43062D8EE327C87A36D349CC22C62C8C3936 +114000,k,067D9D282CC76CE93B6EEFC112DFB2398767B48CB4B67AC64983D3D538A4EF02 +114000,u,9CAD8BD8D5AE41EF5B80C4E7204B1361DEB2F38274448FB3D1CF6937B538991E +115000,k,4E86F6383BFB01313FF84239F2CD491DFBEF54E9F8EE9B59BEC8568E5D2B3745 +115000,u,7713F87A23E8FB4EAE836FBB7750A458786BE32EE421046A42852ADC27F3F528 +116000,k,99B8CE336C718B92F068E34A928326689679B99DD871DB290E46D6F283FAA477 +116000,u,66E221AABEC4CB843490ADA04C64D6AE7ECF9D70AF5DCBE925B4ABA978CEC44A +117000,k,04858FA45AAA5E806B5044256B7A3F274DDF7CB4AB0A2FD46D4F874525359B07 +117000,u,D55B0AC9DA95A3A53D3418CB3F4235794FA84C27F913052060FF300BEA55094C +118000,k,4447483E3E8AB2942ECADEDA0362F2BA548FD847DE27141403A742DB7DD1FA74 +118000,u,BE748636C3AC0D450F77B179B0E0E4FC7503FC4BB42B656438A21102808EB572 +119000,k,EB2F125BF60C320BA40361B39F29BBE400CF0B56275623C380516C20EF9B6E34 +119000,u,0DC627AC6957198E36D54A9E7381D4D3688DFE569BB05078C6B3AEAAD77A1933 +120000,k,A80BAC80AD01B888638BB60F3003DA6C10A9322658C35F346A7DA119EFA4835C +120000,u,5D36DC34AF3BE11813C062D58FEE11170696D8B661D361201C5A0E354254EE56 +121000,k,37AD1CF225DDFAD78EB120E48F948C4F3C138EECDE19603FC6BFBD7F43EFAE44 +121000,u,6831D37A6A9CA32FEA2C18E308AFC9B69AD55C1463A1B41A8BBA86B2293E5031 +122000,k,CF44E1B7F425CCC2BFFFA7492027AFD092252D9BB39523DBE2FC1331117DCD48 +122000,u,311F3D85BEA8C0E7E89E075C52DAB1A20AE481E084C1C672742D70A82E0F786E +123000,k,43E7585E535250D2A5C93FC737CDA0436501A51FE924E932E82A80A3CCE79B7D +123000,u,BF377A17F4EF16059655608D37EBE25A6B2FB44BA2260A53DCF306842F2D555F +124000,k,189938D1A9F248A436BC1F1BC2737CCA88DA3281BC7ACF332CED6BA4F9A8E201 +124000,u,C96DC9A4A9607EC18E1208265F3C260EC1369FEEBBF8BD575D7305804918B917 +125000,k,DA7A1454EF8295172F03A6AB5E0EA745DE89FEC2A87773FA111AE6D5C874031C +125000,u,DA21AB9B27A62786F42F73E0691C5B69410543F1046C32E0298721ED0F15740F +126000,k,D23B20FA3B55ED567C9F91537D5F977C53E903A1C17BA848BADFBDE787CD3D24 +126000,u,99E457C31EE73FE0B60C9BD87427A0FB05B701DAAC2386B1E98AFDF78D8E6B35 +127000,k,53E93FDB40D098BAEC38D6FD8C15DB6ACC49ED12C49203BD10EBAD71D7231B7D +127000,u,7015D4D3A25593F6AD8B78B8AAB1469BB7A88A9089F06950D9760C9567723C5A +128000,k,FA4CBE819FAE3575C171DE481DDC2F0C1655A697E62CD749EB294A3C610E9654 +128000,u,767CA68A655003AC61368B0F6536AF7AA2F54D7DFD0F0F15EBE9E904CD851F34 +129000,k,4AE8A2782CC60EBC8A9B8A3BA58BC6CADF9567CEB181691F17C4FCA1D96FF61C +129000,u,B1D1CBF6630293D2C081B4955CB6D9D7F66E83B18DC22E8532F18F856D890254 +130000,k,365038A918BF7F3F7DD69B4008A2941BF49EDD1BA0C8F7E515AEFA0CD1432D3B +130000,u,06D73DB1698379FB6AEA47B9B7E3D9345D94C2DAA8BE54E0B8736053CBB62472 +131000,k,C87433D70696372F30B52C2172A7276EFBD470B2DB5C990B3C59201F2D56C846 +131000,u,229D3BC617A05427B4C4A8EE302EB7AECC45BDE970E168AF259C8F41A48DD13C +132000,k,0300FFE1CEFB30928F76C84113429D319C355DC951C24B5DA6AB8F4638BFE715 +132000,u,255F174A918B217A945C14794CC8768C0A887FBC26AB8EDB00FB4D16006AE628 +133000,k,C72D083EED37B4CBCC1D44C88CC101435BF8D62306B470547B62B655C034AE12 +133000,u,6FCD28026F826E193CBF91F65DBE05D32FB4D6CAEEA7501DD06404C76D6EDA34 +134000,k,D3C83AB32A36FB102B5A69FAEBAC206D287455CCC9BEB8FB84E577CB68A7903F +134000,u,18B1DDD20A52D0D1EBDF973917A174FA5DEEF591E445F2A322ACD121FBDCF07D +135000,k,A19B2BD57C79280FF6C677B2C01293B74BAE28CE0F39111402D412EF8D8E1226 +135000,u,24FD05876ACDB84C83EE4DA01AFBE82B935AE626721619120FB3DAE27F5E1676 +136000,k,2CFF8F105327CA38C1E0E364DA33335D50D7981937C8F11C9A4AC9D23A687E2A +136000,u,01DDC5347D77E5D3783E8035F285C7270A7E74582C6251A36D67EAA54DBCE67C +137000,k,7DA2BB0A5F6E2E1A044BDDF91CF5FB9708BC3C3A9E311847986125242DB83449 +137000,u,643C29608F0CAFF1A4FA3B05C011B9C6479C50A464A53179D969427D0170B774 +138000,k,D2294682F8A23B639F37672237C64F428566986BCE635ED9208120A7EE463823 +138000,u,184B968EDE1B5096BFF612F672693C4916C238FA36F56FEE9D4A31BAB3A15A2C +139000,k,8B51CFF5449D35F9A3F391CC14D16034A1C5083155AF8E1612C929CB0BAE5375 +139000,u,26827B6F41817D7C454401C669CBE90CCC816065DE4210E624050A9DBA96FC27 +140000,k,5CB3F2B4E990FBC757F1C4860CE72C3613E00CC677BF7B2CAB92AFF5C812E42C +140000,u,1E90CFD8ABC9D50D42B3676EB55E42D22B0C3EB9E155F272A316505412ED2432 +141000,k,87003B20E6A165CDD8640BADE909B504C2DC8498EC12867946D5DA69BCB4D150 +141000,u,6AD2D8D57A3D2DF138904E4724A1E7E781D9A6107A62397B8C3B4E2FA110CF28 +142000,k,2A43D5E3BBFD2C8A70C357B8D55D77A08EED0C4029B9F3709F76188365C8A51D +142000,u,7C9437099954E6C654AA1DEA49F9680E896252228D2141BF2C6EBCB8FD7A9D4D +143000,k,599D15B664E1DE125B99ABC0FB03219779B37A16EDB4504375E34F0586020B4C +143000,u,CF4E148CF44FA92337D43E6A5CA1F43FEFE7DB0902834DB010BC4900DBE2695B +144000,k,C4419C6ECE557B35897628C94209A777D8586D48DDEA8FED38C141755FB4F10A +144000,u,E7D6983AFF5CE9577036E95C1DF9BCAFD8B58D244EE4269BD74977B500AF290C +145000,k,EAF9A0446BD206B02C1583A85815AF497E760467E755ADDFE5AD61C748E0390C +145000,u,41B458A4A2FACD38E801962A2E579770C2FC0FAE5BE088C630C5BC5222C7923F +146000,k,0A045AA2B8C588A3BC23B8385E5093DBA156D6B790887826CA0339178E716C2B +146000,u,974F6524FD1AD63823999F951D1EB4C1CB4E8D1B74E6A1D8E478348C25204C63 +147000,k,D36D2055A12C633F5B225621D235B6510321651645516E4905F8513DF6CC4712 +147000,u,C3176F8703F6E43F04C312F864DC503388E9B67414437D52BEC2301F519E4C68 +148000,k,2C945F6F3DC6B768D89C9A3CB313F624126580BC044AEC8696CB27C87273C153 +148000,u,107734686F6AEC5640AA8620EC02C79EA3DE9F30DB0F201BED0793133D8B8A6E +149000,k,A671CE3B6D14D66281F40CAB902377FA3540AF40B8F2BE7CED8E901FE218754E +149000,u,9B92CD1BAFCFAA5AD016EF9663C9E63343D756DFC94766013023F10411676B64 +150000,k,513D4B5C920466E1C189E4EB8D79B4AE5B01960346A3687CE819E5F613B7472F +150000,u,81ABBC4BA6BA67B7574CD82C1394EEF68CA1D2F9AB7A0F8C2DB1464EDAC38E2C +151000,k,BE665ACEC5D3862F97E1AC8A883F42B6C7341F83DB5F81FC3D7AB2A9E9CCAC01 +151000,u,2DB471326CEE91249C93B364334A764C00A0B95B8EDAA558ED17842047DBD57F +152000,k,9CE108FDFFFA4091651D7C059FB86BB132F8C595CA09F6EC3E53E0B4FD2B6239 +152000,u,A9C27530C50EAC350C7CAA3014EA1F07CFF9A08FEA0E02A5AD71CA51EE899307 +153000,k,A34539DA1DA3C40C8EF0E24AE2E2D97299870E6E5D84ABC55707662A66B5B87C +153000,u,C8398963586DF81AF7E05F3E83061EA6F123CCAD2E38BAF48ABC367D55EF5369 +154000,k,7F0C60C3B0CD6F5D1044370315663F525F56D09D0D6B5DE99E216139E347AC2B +154000,u,C65DAB966122BC807DE16676B23F83FB4FD060321BFFDCFC84256D41A82E8811 +155000,k,B7C21F498E0F60B1C8E0AC3DD77126ED79A9083431AB0B14AEFC3BF5D798764F +155000,u,F2F9FAECB9FFB43E11B18015B5EE33126F448117D8D37E78A3474D302B01C74B +156000,k,6AA8AE9D95CBC79243913B157882626EA65936C793149D8DF0F3F9DFFC335355 +156000,u,B4441E231EFD67C78C5602C2C2E449BD13B72A56E28ABE36E6BECE6D11D95B12 +157000,k,3D02236481005CFBB119F285498CD219428C804CAD69A9260D5F1E27B8581D6F +157000,u,683BC8AC28CECFFC2E7CF76E5A4C8D83A7D5683D4BA497C64C1FF9B10269EC39 +158000,k,E9B0F4D55FA8799F5F5E2141E14F0CC54591EBA760EED5A6681C37E54815C43B +158000,u,94ECBD9CF6A627B84E63F8199AA0DFB0D9A1AFF962F662C7758138CD527BD057 +159000,k,50A9C41BB0962718E4A175BCBAA8330D95B5A1F63D2FDD879308C217088E615A +159000,u,4353A37BBE85D3CBB314CF9B83B9072A484A73641D9D57212C165C373DFD3B4F +160000,k,8B8FF168804955D221B35805D980BDE39C9ECE6272ECEC5A3924BBE548FA7155 +160000,u,B5BB0FF9E0BFEEB6B984BF16A260B7691D9DC9EAC41C1D7D235E22FF707DF317 +161000,k,830630FE37AD40F0DF0D96CD8684391168A673FB1789FD63FCF82BA51E6D811C +161000,u,475AF4FFDD5910E8CAF47B644D0B51B9312712ED32E6C54360733114ECAB5758 +162000,k,C4177FF02CB2734CE7775AC492BC099F1457B98966527EEE2BF61BE54ACD7F1E +162000,u,AF516AC629E31B63CBA37CA07FBAE9DCE9E00685C3A4F6D54296387C465F7712 +163000,k,9D9ACF9090773B575A043A6E60B907CA1203DAEB1C4F9A131C1FF98A7B293C40 +163000,u,E5145324CACF7F67F522CE0BE7217D81F5911A73A952792F692A3E00DAADBF07 +164000,k,62C9E828B14E7AA34C440C1D10EB5BA493837EAB9E7BF26F1FBCC5EEB4B9FD3F +164000,u,73F98651FF0D978FFAE281A7AA22F670F754AE6244D0E3576942651F7E6F7976 +165000,k,9325091A3627C21E03D76F306E4A59FB185AB1EAE0252B6C77761D6F4402447B +165000,u,92F8DF4E8B536F948B301F8375F9F847BC280760DCF84B5DBFE484CFFCA76A38 +166000,k,9665399BE8C4815977BD0D5EF8B54F5E6F00111ACD0CD57B2180C3AADCDAB174 +166000,u,DADE449B3D26A9872E67397564329476010D7389399DED9F97ACA622F008E023 +167000,k,BD8806592DF9C9BB580E701C02BDAED9E67AC311B89BEE443FD116B7E609323F +167000,u,026A9F73E39B8543BEEBED91E4A2D86FE5747AB77F8F14C3AC63442B9D696503 +168000,k,40ADE84769CE5CA1A674523A79879EECE6F2225748A2B7F3C9DDFEF48ADDCE6E +168000,u,BE7716B2D424948CDA1A0EAB22CDF0E09892AFA9CF0DC09B8BA755D45CFF6901 +169000,k,F3FF4549716F378CCEAD5E214BED54F7FCE88D1EE2154D2EF983A192C69B4134 +169000,u,A4371FB2E56C5E3544D5F8B64D2007256CEA9BD9E018056579936512EF44B07A +170000,k,C21AA18577495A5326048B1F8016BE68D4AF64026FE1E665A5D58FB912C92B1D +170000,u,BBA4BE4AA20DA3B5DAEBCC7A052E96A2EFE071D476726FAA06FF30D603D17D27 +171000,k,EAE4DCE83C06E494C5DBFCD298C02B2FAD49EBBF3B0D1ECFEC19767379696C2C +171000,u,073F60AC2E76CD037F4E504DF9C1569EF8136F3F33D0F5C61AA2C80F50070E5A +172000,k,14F73DAE4AC1E4F63059C54D8EC4A9A974647AC4E5F3214526A522308365F613 +172000,u,28C7139880FA0334988502FBF8F1CE186611C9EF88284BA67AA06C7AE8C4BB2B +173000,k,7471F57248589BDCD9A99D0344898884E2EE4E7A1C14896F8AD9C2CAB5119D4F +173000,u,6B7D0DC9B3902314FD1874189E46043B5C1F22B6B8F46C35F3ACAFEF2CD18B74 +174000,k,E4E59F637439D624C8E596055B8CF97FBAE76D1D8DF91873747259845632AE73 +174000,u,E897B81E5D8DDBE135E8795AED74762CB7C447759E6FE578EF3FAC3DB4D9C02E +175000,k,8204EEE0B81C6F5512EBC55187D127D585F3DBA8B0F89587752F3BF1EE42B903 +175000,u,B104DE66329DBEAC0B60A184E0CECCBBE20B9F8DEE31F51E75B41E4A2439782A +176000,k,3448939E2B2C02585453175100D6742A22F6FB1EA457C074EA1238949449A440 +176000,u,991FFF01700495BF95F8C5C420826DD12E7903FF5B667F18F5901761EEF66266 +177000,k,4A99E2B683C048780D0EE3C2F3AA4BF5ADBF35A202935A61582E870A38B9A03B +177000,u,C5F2EBCA310856D78646459C55ECB470A26724243BD7EE0BE0F812478903E76B +178000,k,3A22BDBB63D575EC921F0741A408194C052AADCD9C52FA71AB378622F1CD303B +178000,u,86A606D9CD79A0EB66AAFA66DC80C3B96C05F468054A91B61EFFB53F30A1255A +179000,k,B0E46245C75633924C2368DD52FDB463658E82265BDF653AB0AC6DA5245EF917 +179000,u,5197598DD3F8D53F5EFE3700BA37474B7F223B79EA105A3C1A85E869F58F5D0A +180000,k,9B09520F8FD123F992478652E25D4E1519499102FACFD92F53AE3C4787A40914 +180000,u,43F98E350E5B3C85A9E63BFD4C71D0D65029C36F15336943879C59CFA1E44926 +181000,k,672D2E522C2A7C22E326C1D22B171B4BB771907CB87F71FEA4D7D91D3C70BB64 +181000,u,0A223EBA8076AD21E8CA20B4C38641ADA1F3986F06FB1DB2D2E418622F33A35B +182000,k,3975960FCA6B3B3442FA0A3E71D460211C17114DCF296C14A780F8F92EFDC51C +182000,u,6F4F97B5883164BE295D16EB6CB7084EFF9DDBA4F264BB348911C0D2D2BAE84D +183000,k,D53DB0BD1A5B7B97B92D80E0FFE10B74BA54B9CECBB067614CEB9CF64BCCC458 +183000,u,8AA2E7634C585D7B12E02E0FA09865A52BF83222016E939846BB149C0305B031 +184000,k,07700651BADED0338D6150F5FC8E0A9A119D8D5C539EDAD979E7C053853D9152 +184000,u,CFF7687DDF08D7686A37E80C4CF5EA3269DBD9D9277231D529762757F5BC4D70 +185000,k,BD6CDB2537F7C249FF78040265D5E96F356B12130AEDFB5F2D350F8E844C3B73 +185000,u,D70B1A45B279478594B83C98842B39831413593D4437125E40226FB39E8C6268 +186000,k,9ADBEC956CB5644BC2E65C1E8BCD9C93990C918379AA8309156106EBE5B4E217 +186000,u,38FA6EBB39305DCE7E877E21EF845FC0EEC862536B46AD67C7A6A0CCCCAAEC63 +187000,k,AF98A80BAE732523ADB975296301AD071E5B5905D9BC7A8425910281A7BADA4F +187000,u,C61E1AEDCC29347ACECC6624204E25B7413FC9544D14EF76C473F8FF26819A2F +188000,k,80F253F08183F654D8DE87C55A4DF2841DBFC3EC472FB9FA56313ADD4BFAD617 +188000,u,2A375640210A72B26AD9CF809C328DC65DC94922B5F8998EECE6A1C4D5638B3E +189000,k,AF367CE65F2A9F6D443B716719F067313A39DEDACE893AAF9D0D92A53454A70B +189000,u,96E077ECB7F891B2699BBD1AE2C25BCAC370A2258F4735836C4F00930A9F4F64 +190000,k,CC60F4B404D7E2E35FA508735673B277597BB321E106B9FD32C811226D9CBF16 +190000,u,1BF234C04E66819721B1BC3A077EBD36627A3DD2CBCE3D595C92B981186D6D36 +191000,k,A78CFEC9C650D85E343A6B3B71CDA706CEB602E6CBF31BF9E481EBA45A26CF58 +191000,u,AB506C20C43978E3A7A2F888826BDDE2710211C6DD198D17F09AD861CCCAA737 +192000,k,F5C6009C83EB4622C070CE01315CA062ED499E7A1E15F1A142B0BF73DC7E0672 +192000,u,151FC2B135AD9530AD49445382B3630256D1C2B54F02C22E8876CB7CACBF227D +193000,k,A69F69E61220C3F2A554661E54D948D3AEBD1F1E4AF6F3730A6E27E3265E2046 +193000,u,2B183C6CBAF63E3CCEB7C27B5635BAF8AAC14BD3714AFC5C522A2D89273DAF1F +194000,k,56A7E0DA3D4B143D91418C21145F16BC2C9A62922AE674E6F861D272B0E4AA2D +194000,u,37CCFBFAEABFBA21216BDABC9979EA3C2A9D82554CC4BB84D47EEF7634E42766 +195000,k,4A41D2E2A0C5C7A8C419A25C9EF5F696E6562778C2B460BF2D854783DA691806 +195000,u,BC3A1EDDD48CECB9A4D1106025EF02E31D4FE3980C1E5D27A6A8D7E67C505954 +196000,k,6E2985EDB0BF111A33D58414199709DD653D2C14C1DA43F9EC17F874BB3D7C7E +196000,u,56690AF9919E6DCC1690E0AEDB452E653189052647BC39FC541B15000E0F6A5A +197000,k,9199B2347D13621CB2AA1DFBB7300495D043D3CE9FFCFF3764B08A591108D616 +197000,u,03DABDC3B9651C398B47E1A5C9F4294F72A1B7909DCD11A33EE12A3AB55A8D30 +198000,k,42E01381E96619AC84ED3BA3E40D7512E3C539D49674A7596EDB0B4827309052 +198000,u,9FC911FF3B5124FE3524DB1412C7283032A80FE9C05BE6F6B733F8E417871045 +199000,k,7F1A3C6BC3E07A06C5F69A6455E8E20ED3C87A10C20A3484A2A284A0E19C0829 +199000,u,F11E3282DDF9B527A9BE51DF8141BF41A0873622410858FA4E75722A58D43F36 +200000,k,B63B8F318E9CC1BA05780A1BF6C9DD15BC76C815843528BB35037B55D75AB10E +200000,u,B7FC08ECFB6E3CEB02C6B2B3FD6EC166CA18C247C5CB3EB30F0009FBD6B01142 +201000,k,2CCE2121007DD870C0FD365009534D37C9F9044AF98C282EED4E4B0EA01CC479 +201000,u,87F71845C4190D091DBF7F806AAA1DD03875482AC5F2CE106C16FF43F1F5AF5B +202000,k,03FCCA9205E5E4916481E8286B5994B89994D043A55C1BEBE9029A50D6EF1410 +202000,u,013C614A238127BDBC9B0C6983272C103F335C25BE2227B141AF881E52AE225D +203000,k,90CDDC1F9D9DDB27FDEC852B2D1974CF28FBF8BB62C3B43C526F217E54D98A0E +203000,u,64C48C0BBF545F7E482F2E2EF2372F04862E5D17C1D85116E7F0795FEFCCD61A +204000,k,09C94F697A8D48E19C67C39097F81BB15B4BED656E8D6363FC605011611B8459 +204000,u,C63C3B5EBE3298BF809B5C80D5051F215D88113B9F48EE69CBBDCEE77CAD4E2C +205000,k,01A76A67CA3FD18DB52C8B42DE84357EE808837E5CB0CA283EC459EAEAE20E76 +205000,u,5ACD908273B58F2646861984AC3F519ABDBCF9B18DFB9C219A0292612A0C0F71 +206000,k,096998DAFC484D4E2C01FDC7D35A2234C38B171CE62F12C1A1A144F9F6DE4E57 +206000,u,15490809CFE4CE30F4D620E4C2E97583F9DF1662104DE5984DE6626B38064D2A +207000,k,28A6B948448D40F33A3A4C08EFC36DB0C659FE9C69EBDD87DD11A0838917905A +207000,u,A5B3109533FA6FC0228883600F945E2005FCD365F2FCECAC543237644CE6014B +208000,k,FA736DB6FDACC56D6DD8C838139BAD0D25ED0F36025E18F55B782E959F014840 +208000,u,18E5B3570D9EAD24D2676BC0E3B06E5C7DD45A78448C82580AA17525557FD85A +209000,k,BC2E5968DAB0829CBB5D6227640F4D959BB2B6AC12CD1B3CC87DCA3CF3EFED49 +209000,u,1803264E8B8B31BF6C898DBF4977DBFB296769B719E1E879FC60E66DEDC0785D +210000,k,C070839C145090681893AB21BACF68083333FDF50740AD23B41A992B46133E44 +210000,u,D20AF8606F595B57D495626A48824BDC869E5C4B5C8A48A21E9BB9700E4A9747 +211000,k,D4D7E4C33301FFF893C3523EC6835B5628ADD0757C80627876C402EC6556CC3A +211000,u,46B41B1976CAC300B5067406BF07E24DF4F0211A66B93434034CE48DAACE1D09 +212000,k,32A2385E42AB539C159DC75B942EFA9581535803027B1C4FFEEAF0A0FE782013 +212000,u,B547315D20B8F514E94795CCB9830831D6271C95D8046188BF136E7111C42378 +213000,k,435E0C8D257BF10E1286219202D0240EE2B874AA1B8B283DF30351BFBC4B7F0A +213000,u,D3E32E33D4490ACFF92C13673635AE88B8D9DD719F909E41E636E0C9715CFA6A +214000,k,4A3AD28F438FFBD62741DDB05DB5ACF44070384D29BF94E2457843103E9FBE69 +214000,u,8356383477236E929BCF9103A82DC00B440308FE01BC4B2CF3181B1D68249750 +215000,k,0BF48B9E5612FD4592D573B7B669210646FA18E9FD0A2DD1305E760159664850 +215000,u,7B742C5810EEF9DCD84F4FC454E3C098F98CBBA0CF0A066460A870DDEE61BC17 +216000,k,A26EDB0D6BE4D2E9AE0A71354C5F8EE4064B682F2A3D5D210C21972013A7C42E +216000,u,538A7B760D00FDEE5F1C73A29353F71856180CCCED69666C7FF40573C3DDE637 +217000,k,BAD300785E366A3E38A3CEC73E8C515DAAB0DD886E58818BB58EEF44378F8D3B +217000,u,8927D2399590CDFE9943DB7485924A12AC39E8A041375DA6E984BF3002E4A504 +218000,k,9BCC52A887C96809740EAAD46C3729286E46203034D68DC803489E80AF60B068 +218000,u,7EEA6AFD17602F70A0DA2115448152BE6F26B503B76ACFB403E4442528F4E948 +219000,k,50F507AED2CD37A7B96A1D15EB5889D2C29183A39F2DA7DBACBF0645A91B8C24 +219000,u,795ED350E832852A1CF58078666AF3CFFF8AA14CBD3EFE22DA24B8F513B8651A +220000,k,E0FF07A09E8589CDA01B81214AFDC859880547D272B08CAF13A71CA4A7B89C67 +220000,u,9589A697C0CB63B1A91791E21BB66951260103B7929E3FA8B78662175D65A272 +221000,k,261F954ED5B16116734D0F14487A852668EEEFF3858DA655050C3C1062330E40 +221000,u,DBD6FC0E36F79B000E12E58E3645EDED9F0D602BE10F13CD25B278C69B66CD5D +222000,k,3873DFB1C176427257A95C0FD9BBFD0EDD75F7F860778289FE69414BE8CC594D +222000,u,D982237F2DC0FD964E3F363DF075A4A7A71B826C24BB9913BB2ED485E3BDEC29 +223000,k,582416509A9311E21A44F8B7E45D28E3493A64B9E723D75FCD90377D8F9BEA74 +223000,u,15C1FE32056FE5B2B79E40182373EC63E7501C39E44C603ECD3C5A74C6664922 +224000,k,27427E928B86ADF99811CBAF8956E55BA7A6C9B8B07E93DFF0AC4712F0D74631 +224000,u,D7A57FCFF2658D2621AFCC19ED5977F885CF44955A933BD935DC938B479C364F +225000,k,B075DE2888DC322C02E3601DB465C42267AAF0EF322124866580BFE45A348329 +225000,u,49F69CDCD443694B34435412353EB9CDD2B59B970DF7A7E6E08D9AB0EACBE116 +226000,k,241CF317478B7D4745168C63F504982B4C621AD61303A94D7F0AC7F00DC64B66 +226000,u,CB2A93009CC21A21B3B519EEB7AD919B739A382D5BE5D9C61BC21E8A8F644E2C +227000,k,2B8BBF79C1001472193BCE69E7808C16F2CCFA737034993265808FF4AA061417 +227000,u,35E63339819EB0CEF9DAE5B41CB7C03A9653D1863986B885C139B3D1297B1A38 +228000,k,D2101CE4791B596C24AE9B5B96CD894A79DF0884E5D1C4CF1F054A124EA3197E +228000,u,D3A3E857FF3678C918D89136097961851439CED340A79090F9623FC52853D807 +229000,k,8D55D138C8177960680C2C74F93D320B84FD29E9233BEBA6C10A0A9FF7960402 +229000,u,8E5967661CD01E183BFD41B092602608AE66D5EAD4A082C32D0529B5CB733C35 +230000,k,9527310F505FF349D2F3F72DEE0F98149FE92044E130E524992ACF42F5F4BE02 +230000,u,514AAE0B1D81848233C0556843EAE80FE72179AC5683EAB14515A2FA59458B60 +231000,k,519A02B5E563ACA7447DF57C3F330C9E21F15DB453CAA8FE1A39CFD0045F4638 +231000,u,31BAA9C1CAB0F2E144BF0AD4262CE347626624596016213FF29B54D50180B510 +232000,k,DF029C99EB8498B43247C6DDB3414432D6DF21E2B8B2280E46BC98C44BEE7F52 +232000,u,21051A5C8951A1DFF511B59CC713AF4576B4C3EF45EBD50653CAFF488A26DC0C +233000,k,B48C5D208066DDF474E6CA315313E2BA9283988D486AA10D0A54F84908803E63 +233000,u,EE0A0091D0ADEC67413650CDBDBF81E8C7D450866D63A5B7C71C4FC00F5A902D +234000,k,1DC505E16C6772BC3178EA7569626761137D59E903022BF49834B964BD804B42 +234000,u,B73BCB09233AB6EC84867D45B96E8B45160E7903A7C2A144F41106A0BA57D02A +235000,k,F082B376BD705A4356195CB54B02A624715BAB2C86D5A569844504E66CEE411E +235000,u,4D020DE650CC64F1FF40D2F7418FC84BFB94FC302EE6425C13101933EC76571A +236000,k,28D4ACA1A583487B93874BD236DEECE7218048C9106FE67836BB830128FBAE27 +236000,u,11475A279D9D33EB56BE29BA8E95F3B3496471211067192F8A58D452C2411150 +237000,k,052A0A5ADBC540ECA58EE4971C729D4EBAD2642D9333D27CD0AF987D0F167125 +237000,u,70A227AC19B61CE2B5803E0006D571BFA95D258D935FF2FD07034ACE2068E876 +238000,k,4DEE94CB58573EE87F71E6375B2EAB5B709BFD3FDA310110A26A3BDF23C77743 +238000,u,DA80A63CA6A63BEB33CEE54F5BB9E8BDC14A52A0332CE598E2123EDBA70F8205 +239000,k,EB607DE46F8A7EDB7D9AF7C129E37FFC18BB9E19008E43FE18D9D2D09FB9E35D +239000,u,32F522FB9DCCFD601937813EB7FF5BCB51A7759352F2A185DED67B995B68EF48 +240000,k,FC2AB2039C1E3AE0A9934C70F9843D3EC2171BD5EC33B883F2DD19032E8B4453 +240000,u,5944B3DDF4FBED4043E474BB5862E25A511A124F95B93689E66DA3D0E81C2A0C +241000,k,9AEC610FB028DB65D0417D298051D46B19352AD5EC8C51E1CBD24D9834AFDE41 +241000,u,3328F920399B5608E2B5182BD1EDFB137615E792DE91812CF288A7D482A2667D +242000,k,D82A697676EB1CB49A0BE3E6902B4785D0C610CDF275B2C0924128D74C5D0A5A +242000,u,1B9927EAC00E054C8C7A1603DE17223204A8F13E55F3A192670B5F92CA85A915 +243000,k,64CCE8C8C13EC639563EFEA4055925ABAEA6B98C23B21BE971F28C18863FE439 +243000,u,F1D370DC548240131D87D96026115AD07F107ECC48DB50C2DA2BBE326CF84E11 +244000,k,F7827E939B9231A7D3445994C41DA73A16AD8CA28F4DEE7CFF5D3D6ECEFEAE27 +244000,u,E2685E590787C8ED4F793BAD47B19360CCBA4B0B0174361E43A4B92F6B483E70 +245000,k,B20E2D8F1EB42A6A3B844504A365761B00A21F3F935568135B0E6FBE85EC733D +245000,u,7E8753A6F85CAC1E0C039EC5CB68097DC77F27D8E7230500DCCA494DDE1D7215 +246000,k,82E0A6F6A375AB8BCEA7EDB68C3F088ADF3D992F17664DD3CA53C8E6650F2E0E +246000,u,D57D45602A5FE551B630FC7322BF92C4CAD230589741C27C0CF633649D049C20 +247000,k,6A802BD2CEE9697541D1D5C034EA4827AEAA82E56D195FD40B94F2D0CD351F67 +247000,u,FE648867AFAFC8BC0E71C2424A8A39F87CBF897EE96D6C1803F36828F3064342 +248000,k,4AF0AD1442EA02DF6D06045E023FD64F48EBE8E0CAE9B60A0C254F65ACC5FB38 +248000,u,CFEEECDF32C53C6542D4BFE85E9750BB5990B302E1C25822241F7AE90065625A +249000,k,2769CBAB9DAE225546161E138C28F6BE6CB9433608FB0F499BB838D80BC90F5B +249000,u,5B5A2F6A7C2E4825FFE8086995ABE078C226E9642995FC49467E6D300DA39B3E +250000,k,4E9DEFFA7715D1254D7103B5B92D78AC6D93CD9B9A5830327FAC1D574240CE3D +250000,u,03A8650BEEDA5F60812932513BB6501911B23AA90C33A3EDAEF51D9329836B6C +251000,k,18A5464598E3ABF5E413F44757190361DC4F43EAF32321961325199513699102 +251000,u,19D84212A92D11B3D154AC600C94803D5B7C6D6079100C00267E45D840F8A85E +252000,k,B42EC21CAEC890B058AAD7F325FC89A5E1259738198E62E4CBFD87429CA0EA5E +252000,u,24A07B777C4BB5D824EEA666EE98ADC28629B87780E8723D83EB5BCB78819753 +253000,k,5A80F1963508A0817A0D4A25A64B84517D7AED5FFCFF3A4C5BC6DB6297629059 +253000,u,1AEF75F211F8C0967C58681401FDE965F2BBF8561D87DA79B4D2AA5D41BC363F +254000,k,2A2E45A367E1CD2E39043070276D1703C9A3AB5CA3E257E1AD37EA260B0EBF3A +254000,u,F167C86A2BCAF18EDC2CA0921562A0A4420D5E2E3D4629EB95BADE17BF946560 +255000,k,1A53D6E944585EDB35019A245715B25FF7F2EF79205411ED69BC5BDE638A1A66 +255000,u,C4C24FEEA3EEDDB4A1DD47F389B754612143B91E76EF3B1B2488FF760D7F9C71 +256000,k,4FFAD37D302B0D3C49D2A55E5DAA6CD7F034155203C1BD5B1D4270EEC4FCC96F +256000,u,A2BCB92BE056B85C94C0106EF9C4540DD65EF95B7DD2C4DD96BB88E43571CA1F +257000,k,C889260BF0D12489FEB541ECDD9E73485FA4A00EAC882C77735FAB53252DE529 +257000,u,5F27DCCE28DC312C5841765ABEC91197F4A7DB878A4C7C4D1D569DDE5D24B529 +258000,k,BE28B9AB0D653B028C580CB1684603A42835BBC5DBAECD050D21C4F9E51A3228 +258000,u,935B742D945B6590ABFF3E05CC5D6AC50032C8DE970CDFEC6D3CF2141DCA2B2E +259000,k,0EDA5D89761A7EED38568DFF25F7B67548718A85829A4ECE45554D903127F743 +259000,u,A1377FA65A4499A6F0E056C3192058FDA1794CDA2127440A16D163032DE08123 +260000,k,BD50E95149499E6A41C2559AFBB89FFC1DD6281CBA4103960F750CD9FD8C327A +260000,u,05746132E7C149F9C3D14DC2E4286E9B982143C5249F989200B9B35B4599713A +261000,k,99077C1D43C58D81A8AB5E8303DBA1963F6943D75E9B0A71D117FABB03E2562D +261000,u,781B714FA1034F107AF58F70007688449257C227BCE27963F7970FEEEBD5A00B +262000,k,5C77E3090F09083B430BAFE16949E01C70149CB4C5F7F910023D728A8DBDCA78 +262000,u,8BB784418FB4966ED04171B9EC9807270666725F9ECB360FE794C7FB1ECFBD0A +263000,k,63D4813C970D87CB5EB5641DCCF4FCD8B727CFF176B8E8810ED94C2C1E6DEE36 +263000,u,45F56AD77AB871E750CDB5A848A2D2C961B97CBD4C68BBA1B15B4F778CC3123E +264000,k,207A726F6112313E9067D194F89A6E0431FA1124267856A171E88ACFD3C10312 +264000,u,F336ED31B145C08C3BFED4213C7EF044E5BF5E0BB8F33357AE98E600B5B7BC16 +265000,k,E2034F83F6DDBF8B5A83FA7CC3220DD9D48CC3E70CB3341BAB756DB005D98B2B +265000,u,C49982E868C0F5B3095963D716D85A89BDA9C978F33668DA7A3C6C12A603B204 +266000,k,91117DA4331A568AC876A025DF63731FA4554D6FF0066CEBC5C5D1F08204E00A +266000,u,31C0887ABFDFFF4DEBD0F01F820E1E75CC6CF0677F778B321029D9C39BE3CD55 +267000,k,9A35189BB69BA7C3ECD4FC58961902F00CCDE1EA9405C0A99B838A9B478D251A +267000,u,BA4E196B20D454DDEC8C8653957CF5986FDA7BC1BDFEF2B233B68A4AB07DFD2A +268000,k,7685464B04F9A8C668CF60518460C75CB096342E86BB2B66A2365EC79E571609 +268000,u,A3483A39D90778672BD295AF5E1DA8C9180711C2A27C0EB7206DF51D402FB955 +269000,k,A291B24B5D4A55A371C2AE2CC8EB0E9B8D3ABE1017A13C5E2246C1DA704FA535 +269000,u,4666D951E2A6182C110B1CBAFB06F32F314AC028035BFBB4044F9DED3E769932 +270000,k,A995E37603FBC08F316808820670F7D9CEE71EB18133B4D45D185B23247DCF7A +270000,u,147415EA747C75B67865D8993B6F01630C3F9660554B8491A15655C9CCA7410E +271000,k,E3F9B29FB312768D1927D02A4D2D3CE29C86E7C70145117BF8F45C3457127A44 +271000,u,9750EF50599B6EECC2CB3FA44FA7701A81F4790AF9A9F8A1B3235E4378ECCD5A +272000,k,8CDCC7804CFA808BC5D5EA79B72FD874E983D54D64976DC9D18AE92DDB21FA43 +272000,u,F704C65BD8E5E1E06475B8B6B4D4E27230DE7131AD9564F468121E07F449AD7D +273000,k,A9A9A4FFF3D8895CE29815609C3E1BC1AA2D279B48C730E7C872BCCE090AFA72 +273000,u,B0D5BD57B62B7081D89A443D2FC891D20808B3D671E6B28DAA03213A432B3758 +274000,k,45A2028B04F7C663157E1A9EC488EEF45A93B1463B5CE6CE1F01CB1CFA9DCF1B +274000,u,BC695D0FEC17BBD65D16097A060446BB86A3C4676B5E7511BA709EA57EA70E51 +275000,k,F7A107A812BA669DF105EAC684C9D0FCEAC3B84FBC6F2A04F4A1204D47EEA35E +275000,u,7B4F7C4A06613ECFC45D588E8B4A4ADB76B34EB4EAAD444C5EB3E01B2489F567 +276000,k,194105B61DAB0FE34E746997A23AFF07DC138BC0D47E48E58B9001C9B369E533 +276000,u,E4719E304AC60C293D99B696920D049863E9B418BC1FE2E6F92CA3729B958F3D +277000,k,1471B8814E89B47F407D7A3C5E7DC21C1791636A7576931EA09AD7EFFC27104D +277000,u,F64B346342A64BDCB60152BDC27210E68B2660228E8A7CF4315710B51088FC23 +278000,k,F1DA97C9587ACD6DB6B90EEADE15E25A6E878B835989A8B1BF318C914DCA3911 +278000,u,F32E395595C84DE10A8FAB651F80DA7863AA790FB0F6E9FC1D1EAD6E3033D158 +279000,k,DC67CC600454E32CC66708EB96187D744CE7DA6E57DBB8728ADA61A26CDA0E23 +279000,u,69953E3B472C8828EC9675D17EBBFB48FDBDA6BF7BD8F694AEF49252B15D8C27 +280000,k,7FE4473739A690AE7A71EB2F0C552F65A794A8FE27D25366A5BDC5AABD28C125 +280000,u,9FEE4E00A5A44887CFC3561CE1F104124DCFBD3E91FE1CFB9465E476389BF022 +281000,k,19458A3AC26456D506D0F1CE962BC847D8B39AF9185AC66F887003D99845BB2E +281000,u,A7E3E585B65790A89B24AE9B5A22094243245C2BC5E76916E31CDFD354DAAD4F +282000,k,7B5B29FF2DD48720FF5D6F3D432DAC7C631C418AB6DF64DD2915960DF9AADA02 +282000,u,D4F64CA22135052A4B74E4DB7134B1B4D26E60E83282B170D3B8827E587AEB77 +283000,k,838C13800950097052EF3A1200A62B1125BA98AC866153E8C0857BBE351E8A4B +283000,u,B8534604FAF0327D2D1A3BDD5C68CFD935987BDB7DE7AFD2D38CA9087F4A1655 +284000,k,280BA42A45EC7560CC79B87911C110CE2D9E1AC102883291E31AD0D2128CCE2E +284000,u,057278065073F4F3D34061FD7163920FDBF604F467EC473B055103C627ECBC49 +285000,k,36948D635FB41F092D9F209BD1C5D8EA0C6153CFFB7CAF3E7ED138315EBA8A3F +285000,u,E2BFA75FD7CEE3A74B92F77F9B1F2D543B85B0F8B351297AD6342D39FBFBB11F +286000,k,4E3E82AC9C2A0A63EF8FCC8E9AD613847640CEBA11ABE926FD13797DF7EED275 +286000,u,5AF081CF9DE61A9E1249CC12011C52F8093C11D8BA9EC24740F02E852CDA8916 +287000,k,58BA905FB33D74249A83A4E24999ED33C71F262ED113E38CADB8DA705372F46A +287000,u,1BFF425F95506BD704E9C2EDAB2D3B0A04A8A6A2093548F2A1AE8B61FDEF162E +288000,k,DD3F57C3576E13728CB2BEDABC2C45D1553563403608B97062124796A3739203 +288000,u,B471E01159BD5BABC90E92A97B62341689AC513A2AEB7134FD71A79BD3B97D4C +289000,k,53FCE055798C8685FB6CA1D67ABADB7E178B8FC5BDA4BB36201381ABACFE3632 +289000,u,520F38842BE19EAA167139478A478DCE9F81AD3DF3D865D28E83BB912C57AC16 +290000,k,745EDB1E10486A0BBAFBCF8DE33254EE842BC1723F552644A3598FE974BFD419 +290000,u,EE13FF07FBDA10C499330751A3EFD0CF2F87F9CB7E216C62BACEFD984A57ED66 +291000,k,C7B7B59E831D44C1409F893A019D8B4D004AFF8BD5F88907349F2532140F653F +291000,u,7798C911280424B1B90FEEC86CE2249DD37228C8352C9EB5585799A8BD088103 +292000,k,47FEB66D367974212A40AA8E23289AD1C7BB2E524E58502FD2FC09EB76528977 +292000,u,7BA9C152CB28999F5454561B47CA70B539A378EDABA81B87259A580D72882621 +293000,k,B6A0776C7F09D7721333E72E203D23B32A19B565D08DE8E96E6AE9FE3537D071 +293000,u,85E0FFEC325D0A2E95353B12BCCA194040C6EE1BF34D9906D52EBE6BDA134721 +294000,k,7C43D1CAE4A3EFB1FA769C610BC09DA31A9D0480CF58881D2DB1E679BD6A500C +294000,u,7094621E543E0C2459379869593D6CDBFD701DD08905AA0306E675EE46537977 +295000,k,D3344E88A3251F7A3CE712E251ECB6DA1CDB7B66D1C345CB61D7338AC0A96D34 +295000,u,1F2ACFDDC4DC285E04C2CFCECBF05B294F93ABA13AD08994058CB5549FE59D49 +296000,k,DFAF4095F73D5F84E34E5C4DC18EA3BFDA55019217429FFE87DCECC61A6B2E75 +296000,u,B213E86C9878A3F81A68DEF5F39F05DDB4204653A6978AC9D2D70461EF03685C +297000,k,5F9DE98B8A925F54A5D76CA11B77DA35A3184297931BF899C00CF344F6A6F260 +297000,u,EA45A140ACA824CF7A1FD0D3BCB6A95AFE61FE5E82431FECF00A9329FF582F2D +298000,k,4D574D4341AE50F2E72B370C4965B2788AFEF847AF10F897F2F55693ED7C0F75 +298000,u,D4012D29326DFA636122F3DB0C82D2AD0F4FF3DA48D9757FFCED3E1F90205F78 +299000,k,A12A487186D6B35177F92581D21E073C2D11DDE4251329D5B7B57E7F95561A3E +299000,u,C7F40667828E9C8A85565D52E44B909F43CEC1E176514F50B8A931540F8AA008 +300000,k,8259F6EF04FE78595095D1670F06DE1811D906A8C4D84A29DDDC34678EA42474 +300000,u,151F2544D9992D0DB398AFAD8B54971405BCAE03DBE492A5D3F62F4867CA702F +301000,k,3CE204C282EC27EB8D2A74516F012638511100EEF8C2D7418CA6FE9948341856 +301000,u,EDC736660CD5D799332FDE354A43CEE73BC41A870363A0107E03A58D66E25C39 +302000,k,0C88C9E1B79FFF6A6E8E3F62CAB2C8DF1C9B8F38F06B2097333DD7A9A7615852 +302000,u,229B316AD8E529BDCE8FBFF6F40ACF62157CAE9F439CB638E1435994341DCE13 +303000,k,AB9D378BDC3CA2EEE63D5FE0E1020AEAC9A4DF441F41E9BDD9A78A393B86DA72 +303000,u,D28732D9CF06C873B540F8CCE47AA60E545940CFFB54C28051439B5A5E62A91D +304000,k,947E806FDBF2DABAB2FE248823286D1428F2AFE2DB7E956CC4FFD002AA5D6212 +304000,u,10D92F4A5CF3B2456CCE72344062DECD5BCC14695DEDC05A4341A2F75896B021 +305000,k,E6A914446B111FB9CD3F1E382A9E394B0D1CE2DB497B9B26ECA4EDA5D3175428 +305000,u,C8FDEA152827805F6CC2C34AF0C9AE7BCB3EB17A7B0668655244F7BD11D40B12 +306000,k,82669C826FC92B9221D969BC8DA31690909EB0624EB83CD27BCDB81BF6469E4D +306000,u,7CED7D31D8A992A8571F348C3F93C550A02D5EE957AE45792743801781B63654 +307000,k,D9D86CFE18BD62885075CB23602D6668DA51291F6B62DB18C77A847557B1E856 +307000,u,3D7CF72F3E3E612FA0A6F543047E87C59A5A4549D7AF18FC1981F778E8E77700 +308000,k,C192751140C595006B5AAEEB169D194FDC4166816452BE82B5B4FC80F18AF378 +308000,u,FCFC18483017CBCEB0316193F05FF0349AAC5303B005860CB0BF3BD5C1DAEC27 +309000,k,E68896B08D50ED51CCBC54C9845D4EC813EA1FBE1B6DC4EA163C1DA2AB9C227C +309000,u,B638C1DA81BA10876ED410C76FBAEEF667A2A572DECF76D00B040E4688E2D628 +310000,k,A6EBB79352F555480A4FB5B3EF67FC6D9BC75B7CEFCC72EBF55F90D60E9B0253 +310000,u,D1AB0569B7055F4A8A67FFF749D48DC4CFF8B427C5997E18579E7EB12E14AF65 +311000,k,20C8453CF0387BA029FB4AA3C8A251D5CAB8623C7BFF67AC7928C1DD82355048 +311000,u,6DA56D1DF208C2B66D997166ABBD40CAB3E1609ED80CB17A70FEE38002D5326A +312000,k,CC857D65B5B432F9B7996086EA809B456AD6EB010396F0A925A66895C480054E +312000,u,A8B3919BA3C612A078D14DA553E94CD2B1CB050FB82715AC99DFD0D1586CC647 +313000,k,9FA558E8766286DFDE8BC57C023A61B891666D0C948BC28BA244EE86475E9522 +313000,u,C489CEE9B9BB10D0D23EE07D5644519288D11CA2DFD01800ACAEDA16B1ECAC4F +314000,k,D81B78124B1E3109034E724AC742D645B8C3DFD3ACDE717D5CF8E996EAB4C671 +314000,u,DBD54ECF9B0FDCBF817F5EDD0C1C87752FD7401B69C80E08549659681511400C +315000,k,DC7DE3EE2FEBB5145C7966CF7D487AF23C0952793BFDFC9CD6B4864D76F80459 +315000,u,F3AA6DF11B0F6F5C36C0950F781517E02811A1681C756DE7D00FA40C58D8A33C +316000,k,FD7BF265D7C1D0C88CB35470798C863FCC98B990190557B9F1E85F0A75D68E48 +316000,u,975BA6193EE7E354B7FD66758A5C5ECE792561344F96B9E287F10A9007488443 +317000,k,14AABAA3919E63E8FAFF33EC6DEA99C39345DE0A160AF3A24947D8888F5E8B07 +317000,u,04F427437B97954AEDF18E44DBAC09F410B72414000CE5D20BA1DE794AFF7E57 +318000,k,230A60DD17A950A56EC564CB190D6C2D5C7C598D9305AD8C82CCEC74431E5020 +318000,u,91075622D48ABFCEF1C1D28CEEC774299D546AAF2E73FE195D1C19CDF7915134 +319000,k,C8338F41D7C53A3BFAC7179B5758956109BB9EF85DEF017A4969AF1A69809158 +319000,u,2B14FAC2438EC96A3483C41772362568ED0CC099A45B4A5C08352A5D40C77D63 +320000,k,0FB640EE1279CC3A95B99D2077255440E4D75E90DFE9E81E8F772027A6026E6F +320000,u,B6052092BD634CAF442CC59FFFA06692014B5B885DD8E2C39064209C223F3B4D +321000,k,73A772D7CBE9E0A24DE5D39608B3DAF4E578B21F0F4192AAB4FFC5E01C50C814 +321000,u,C492811A9915415022F72D068FB84B854FC6257FB6B60F1B151FC22361844B0E +322000,k,CD6730993BAC7676EEE0B0C37FFD4EC61AA1352E9A9CC3209FF99DB74DB3FC5A +322000,u,12E64005A64F19A1298F2FB7EA6486BF69483F391DEE9DF7571565406D8C5449 +323000,k,143CFD41D3B4AF99B269CB196D19E31CB13845A8B7E24560A6E19A51FE0C4A33 +323000,u,25AD1C205FBD7A0F404DF40FE995C6D8DEFD9297C9EA1EF785D58D504466FF26 +324000,k,455D2AD18000D66EEE5BE3C520D8DEAD10854EAA4E3F2DC9AB4D52F686833465 +324000,u,832187B2157001A43A7DC3A7EA9B22F26FBF22B1F31876D6C7319D8230B05D05 +325000,k,D50F0F88042A1F73084CCF3DD41F3E2A675ECD3E2568022004FA238399536740 +325000,u,215A09E55B4EFEC5D18459338C003F08A1049F992E9C6CB53DF639FC70AC2564 +326000,k,39D3A26CCC20FF8F25C7149C62768AF6E00C312932019CACAEAA30EAF7AB4161 +326000,u,464A102E5263128DAE1B840F71DCD85F1BC015615EF7AABEE5B6F28CE637042D +327000,k,1ADEB33F1E8E9B5221DE2CF6083517B513BFA296AED9C79282AB440359AC174B +327000,u,4F28158B585B77D315A464DF4F64210E25252F43EB1D9C4C003EF793DEE0AE42 +328000,k,4E9DB1DAD99805307A7AE341D96C9FF17C87EEBF5A63F3455979A9BF0EAAA179 +328000,u,74525E008F63EA7F0EB3BC13A80335A1C5BCAE75BBE1F14A365ED73E3D31851F +329000,k,ABA6C486BA852189C9244B4D64A31F50583FDF55D6F8581F7EA931F290904214 +329000,u,28258F375FFA6D7F76101AA2F71116FACACA9F17900AA5B5C25D41522249025F +330000,k,152D4D8D38C44185D21B0A13F414FD624B817B92E785EF202A5D3E73AEB9242D +330000,u,42D708E4956A7B561CBDAB4EEF704114500D9BB83D3BB6521FB40963D31B944C +331000,k,78C7F3D1398723EAA4B646D232BEC0C86A6FA1B1E5679E0D008F38ACFD66247F +331000,u,74D0DD39285EB2B112123691487ABBB1B0515E3CA1C87F1845F207E99B64CB1D +332000,k,CA5EF2D33227004361CE6486FE6BAA5301D7D39707171FE7703244E199D4E94A +332000,u,3CDFE64C909225667B66562C522D35A2F76B4C63126E5C5A40F7EBFF4DB91D29 +333000,k,D644F347F840AE69D7044CB38C91BC320FF81BBEEBA83D041CF50F237433DF48 +333000,u,2039E3598C0D8807F6690731D929FD56A5720A1948BD40C2C42530CFB8EAAC0F +334000,k,6C7E1C31A74C58303DD4857FDC0F239CDCA0C3B5FC1CFA224D7312400F868175 +334000,u,32EF4AD78881A62AC2CF2A2919B5BF107374CAD3FCB1F45933D52FE72DF0AB38 +335000,k,E00A3F1A2B2AFFE76F479C1CE33400B1DE2381249B1FA82F2D9DB57E2B36752E +335000,u,5A261D2E9EABEB54724C8A4ED116694EFB719590A7F1BD225A1EC35364E85674 +336000,k,CF3860006EA6DD7E60DBACBB24D6C9EF0613FA015CAAFAA1E53CAAEAE3578267 +336000,u,9F296365C63F69DC5BE1E253E62A9CC25F752D8335A614DD544823C973407940 +337000,k,F4A4195769C26EA2F901DFA1005BCCA629C620044EE2371FDBD8CB02546B1D22 +337000,u,70F810940E88CE2ADE2E72379822AC4A12870A90AAC595731D569DF2012C2A5D +338000,k,CF4527E23F95BF99E3822309F30FDC1B7DACBAFE7C1F28CD5EA39990D8F4AF21 +338000,u,A436472A45173A4760015871AA17D09A978F18871DF33FEC3094AAAFF49B4257 +339000,k,889361BB14D1C0FBA612F122F9F01788B451C28892432BB328B7E13E422E8109 +339000,u,70FFA24F7B2865AB5EFD204F45B903954CEAB00AE427F19B8B19B63ACDACA77E +340000,k,45EF1D5DA0E32C9E11F4F0C68C2160F836664A1602AD653A56DB56752B266C5E +340000,u,6897D0190D1DC57A5E1239AFF9BBCA15CD0060FDA4A099DC1036997E4A0E3F3D +341000,k,CD461076731D8EBABDB96B69A34A229CFBBFB39E8B95B93F852675BF72E48940 +341000,u,E16D0C9BE3BA8B6081FD0990F768D88DDA90D82336740A8949073715E4443727 +342000,k,2E2992A9645D3BE3C962004519833AF50FA33215CF07DA27263907F3680F7217 +342000,u,CB318E20C5332226B2BF8F1FE6DF30F9AED5548345A2C801BDB820BAF3B9E277 +343000,k,752F610FA67D34AC7CDDB9CE3CFBFCDE7875E40F23D5FC4ADE05226B8B46BE6B +343000,u,ED8E63191296F40047ADD029D048A128063B1A5E74BD66B3DF1D00661DB7B411 +344000,k,90AB47F78184EE5E36CDF9927B9020D5DC79E7484AC58F3C41200AE695748A65 +344000,u,D1DBAB5FFA7CC47C50E0CC069BD2CC9779AE4F95E039A97230981AB5F7F1F34D +345000,k,95EFCCB68BCB32336365980A304387847DAE6753DA2745230712C8495526434D +345000,u,ECE71BDA0E9A296FE953EF926312AABB3E94D4029B955504EE13D4536B2F4D73 +346000,k,6C3691DF42394F0E49C7CDD8E3241112BCAA9BF455ADC9474FDF45182E19FD30 +346000,u,B14B6D6F3768D9BE0CFE54B529E42749DD6C20447433FC47556567823604D04E +347000,k,8EADA94B067AA32FB09623764E5A14AC7CB3C56E649A6E866FF83837F7FDEC34 +347000,u,65A5A55EF204E78CEB7691F010E071EEF868498A1C1225247D6C8BD89A386978 +348000,k,7587614F2D0705B869DC2F07C56C04FDFBFBD3093F6AC4FEFD018741D046365B +348000,u,4A198353AB83069FDFB49ABA4A77C07928A03AEE39AD32757720850FEA63A16F +349000,k,D1B9E7ACEDC3E9D388EF59E86169FFFF9C2BA923ECE4EE286033E396D6EDC657 +349000,u,EE9C40FC5F3B2D69677C5FDABB66A8A69F2319D4765EF55F0FDC6EA360B90770 +350000,k,F7DA5474B40AB557034D62FFB10D672BD257671837DDAD8163CB7AF6F4813103 +350000,u,F2CD62888201B692DD9C805667E232EC2FF0F16AD2CBB48743B83C02BD93D56F +351000,k,68606EF1457455EDE804F9C3355CFEDBAD4DDC9E1FC9624D1F1D4904ADEB8C7F +351000,u,4EC63C6689B9282F417C03CD4FFEAC87AA5287BB4108CE985C9CD7EC1A82DB11 +352000,k,977E353B18ED809294E0219C14B4E6B158A092369D34357C0324DF1A6D057F50 +352000,u,8726F7F2313134B6D1BFDF9F1BAB6A07D11DA77B19D9455983BF54361AFBC64B +353000,k,609F6B34B469FE1A7359FDA3882D1FFEBBFBE0D5E237C96884084C3A54397850 +353000,u,3DD2E68D325CBB20DE89013F3E768FB2E75DCA8A8F2CB3D152D016E7DD393B1E +354000,k,91DFB60455E8D964E884E66198061431F577FAEEE06479F23760FC9EBC0C262D +354000,u,A0BE3520553F8A872170EF3309C1FF1FF74C614B3F07AE393F5B7639E3E3180B +355000,k,52E7B04578F0742DEFFAAE72D4EC37388D65ACFEDFFA8135600D9B0BEE7BC533 +355000,u,5ADCAA4C013EBF886B021C6BA1779BA7E749E5D57A37E236F0EEE4328D15E540 +356000,k,4117E13F2AFFE5460D64AF61BEF6B8DF64733BBF9A208DEC79FE2A64EAA94604 +356000,u,589C1E347DA75F989A32FFD8366E4121978255A581779AB1F8690E7F0E524966 +357000,k,549EC893AFFF2D54AAF613FDA3CA873384094055F07037CC8F9E36D63D844911 +357000,u,F99082A9BD163154848DB023CF379A67717592A5E755D69FAA14250785EBD531 +358000,k,DE895D5660ABDCEC7204D8DE0F7603502DE5632E4F4FB76E4BCCEAA904D19E3F +358000,u,2889673061ECDA6DB666A1BAF5149EEA3A733313F2DEDDDA5C3A66E8AF69D23A +359000,k,5B443F0CC132E38D683CAF65D8409F008349FD8FF9FC8F48ABFB1AAA7DC69262 +359000,u,D4990FDD7C2F54697E4B6D4B433F62E7D0C9BDB7DFFC93039D778A7A4DBA2725 +360000,k,DA9D6550AAD6DB24BF9996544CC13871D8FD5DAA82AE8982B575A8A8F4FAE861 +360000,u,954F1EE456B8F2DB104FFB0F7199DD5B0A7C9605E00748489CFA902A7A537E14 +361000,k,42CFCBDC7880E1D5DC9D06ABB7F11BBD5839ADE8DAD4698F89081C439BD46E32 +361000,u,E6059E6EF95073FF818030618357CBC63632D3B4FE61C07FFAD8920FC8ADB37E +362000,k,B6096401A9D0AF383E57493E19F04B10410241B644E8782A7CC63D6C1F069532 +362000,u,4190B9DF6AF054941320C2ECCD58A7215508B30C72B4B0BF921D582AD3BED505 +363000,k,C57BA8012D3C2042120D95D55F555E54DA212C25550EA3A11A4CB3415625053E +363000,u,3F0BBCA4AA1B33E6833000C7FC9349DCB11E4CBBC5327E07D5C89EBFCB33C515 +364000,k,04B80BCACA940229DE62367648F9D9BF1DF03D7B8B4BD4FFCB6CDDAC44776D4B +364000,u,E5CC517AC43410294EF54C817621F46710BFEEE7A26A5270E62B59775BB82961 +365000,k,48EB11E5D66A99E4781A98464E5830527E1BB3CEDECAA4A7F66ACA6370BDB300 +365000,u,B040331CF271159FF57D001570FD33B065051F7BD2AC46A92E632E0F9275A00F +366000,k,399784535BE153993C3FD72992C898C6B60CE55831EE0248DB8C84342B0A580F +366000,u,908B30F995DE2AA6EC6C2D21EA36699F29DE61518DF9638B493F18D0D5FD5645 +367000,k,8B050A9A3CB8B73A386BED9290FC254064BD3F84605E7AD75D80C7BE271F723B +367000,u,B4B0BA9C6AF0C9E33EF0B317E9691380C87B3FA3913124EACE420F4C55F72E2C +368000,k,72BC973D4495D534B28738F7D00EB039CEBBE8A72845C823837872BEBD03BF02 +368000,u,152585AA8365566A48F99C34C296F4D9B496F4558A7D65FE4A8C11DAC950C464 +369000,k,FD204A9BF621B6AE48CC541B72AF8445042974F147847FAA54A66086A932EC70 +369000,u,1FDA6B5D7145E50C8D90022888417DE91CA19F9641BFB867F602F7C68EFC134A +370000,k,7AC78516F6C1648CD331FD9E2B9302E6A341E47105FB64786A7A3065EF24C101 +370000,u,6F54ECAD469A4F21656C33BD9DA5CDBDF0ACD99BADD8DDD1CD8AD6B995713568 +371000,k,2588AD06B9667EC7FD18601800AA74C2EAAD3D5721A2A1202DF13222E1B23405 +371000,u,2819D5FC422869E6D9259CD4443C51234E516958054711038E2C1882885D7E5F +372000,k,773A2A1629D12773BD4F0278E5932F762660213154E1E6DE9959932DF860843A +372000,u,F87B634C3EFB2665E0EDA620A87CFF906C85FCEC311AD54A63774CBD7BECAE5B +373000,k,9B81EA5ED38A53A3AD8908E8E5D533A2CB7395121255136BFAE3A39D98D35362 +373000,u,8A2E5D1C800D671016ABB50F3C79FB7109F92B11B9A1629A10696B0131441304 +374000,k,4836230452F4B8BC9418BE1B30EAC0DC579D3852DD9CEACA4743256BFC56D61C +374000,u,E19DCB24FBFBE3D1A1241FBA4AE6B63A2006156A6642ED78FB36B441A3072867 +375000,k,B0E391CEBB6110536A2B7F5A58DD18D136DF9D8BE706C2C8FC06BA6B01639277 +375000,u,FF746A5D5A609889C6D4FE937F858612B283E3EB6255C0951B6546E62E44AF1A +376000,k,04E9D72D9AEE107107631BFE7690C353F8DFC76A98615D7E8A748BC06EE1B628 +376000,u,EABC99FC0F0B052DC11A672F5ECB572366A851207FB6FC0DFBD63FEC1CCBDB64 +377000,k,9C9B1CA6BB03E4ECF425133C5401460F489F51185166721B0BD1F3AB65983212 +377000,u,BD79B12B34F3D070C45BC3F515AED4CE8FE82E85EC90EAD4D36B82FF6E0B6D23 +378000,k,926468B67BF349D67EE0A04FD313C5BE620CD7156705A0EF899D46A3B7BAC106 +378000,u,1FAE8B0861CB74743A31DA88A9B3E1679182ABF2BA298B6C374C1C174DE8817C +379000,k,F5C1D003CA1FC6993E7916512EE6B8A7E4A6123B05D753236AB535FFBFAAB353 +379000,u,95D21E0C577BD211D54E524C7F17C5E5D076100111F5858A59398B61664BD714 +380000,k,1B3DA8A9A6181711744D37EB512E4C02895F5D871E673ACCF0AAB927C7C99057 +380000,u,73B2F03FA6ABCEA52D3EB457D28068B104D5F480DA9996DDD5805055DC4EA017 +381000,k,DAD9DA3D483B99C742DD28C738AAFF1160B66C26D65ECC8FED0FE9871D15306F +381000,u,CA445506FAF13502931072E59504AA50477FAE98A2945EDF5235C6B64E0AA919 +382000,k,D4E52907F5D3755AF2F9EFA8507EA1963D57E3F8C65196AE361253BCAC600277 +382000,u,C79D28F1E683242BEA66A321CE108AB1C5742E3401D8DE1BE350B80C63843C46 +383000,k,52B27B196D5DA932123C644C4C5FED090485D925F3608B0351B36D4BDAC1D275 +383000,u,377F6383E4675A3E601F130C24FDAA112CB306F9D9C60161FD8BFA0260344226 +384000,k,2479E9A9EC66E2591EC5E90C0F0627C72C0266468A2D8DAAA51F2F8A0EFCC939 +384000,u,0660EC89ABA1FA0015B4F35CE08090CE8FDA48CEB2A9C947F6186F748A812969 +385000,k,450C411854FAFB36A713EDCC03248B00C4886D3333662253D192D3B4A1816812 +385000,u,174A59940B8F3CEC55C63BD56C3366A202BE77097B0630C3569B55DC7AF00425 +386000,k,C711B866088916555B04D2174530F289B6A33E01A1A2375A4A48709E09CF833C +386000,u,286DE4D2B549EAE19151526E848F5C5E078687C3FCA1CC53F552AF5C51183250 +387000,k,56417F6154E4D34DD938A374AA7BF48C0F20E317E8D4393B2061B67BBD92012B +387000,u,28D2CED88A9662A5E40BD4911D1EC929C474FFC2F42FA0175ABA948DA05C6800 +388000,k,C0AC8F3924BFC9D6B5D560CFD66D323DE3C2A304465DB8DC6BC5DAE22EAA484A +388000,u,78D0121F5806DF07F3A66393988172193963E974B8BED83607099676F5EB1430 +389000,k,4200A8584264FCB9ECFB8C7FFD2523F9D36727A44685A1D27CC305BA916E3B5C +389000,u,D85FB1C3413482FC972FEA8E257E0BA6335EBAF9D5DB861A7AB4CC3407BD5C0E +390000,k,18402269F605683A6EADEEEBD04FCC4CE6F588AF8BCA03415F2E5AB19EB2CD4D +390000,u,3ABD2FD54FC340C7028AF863982022297AC0E3866210984475C1263D7E518910 +391000,k,AF271420ABE7A8EE378BA9606216CF8977D743F24AED141F438D64F18F82B307 +391000,u,49F34B874FFCB85B7D1C89F8F6D1D415BEA1260EF7E923B9258C7031D1C4386A +392000,k,FA5FC8FD5D249AA62DB0B9F1E498001B8878B5B5AC379351C63D76690D89D67C +392000,u,73914603A0629E7AF15B933C4EFA29C4268B314A7E535142AB40AE7C686CA15C +393000,k,A7CA7555500D2BDD876B9B5711CA17C214EFF05D107B12AA767BB77CF7E6881B +393000,u,BDD247895393D2536D50286011A37BF639CA77436F73BF41F2F710562D16C13A +394000,k,12707B79AA2A3CE0E75C638A7C5F4CF587102CD5D3AE21B7A23F02A58146E01B +394000,u,81B907E40F3A73D5F28CDB503134C2BDBAAFC95B3A21F98BEA067DE303BA4971 +395000,k,73791741F7F5C634F12C06EB1ACB051DB17A6266EB25EE61059DEA52C82A656A +395000,u,00AFA4A9989B797D1CC6F7F228B9621BF848FB5A8011099868419F9736C2DC27 +396000,k,FB6324DBAF722B4AD868B8686C2868EA46E7D1EB0D227F90B5B7839CFAA3603C +396000,u,22C64FFC3A57E13AACBCADFE2936115A3FF200605AD4263BCC894DBC0060D610 +397000,k,5DFBB34B194C939B70C2457E43F18536F27FD85314A070A18BFB6478C77CEE26 +397000,u,09A7D58E48D3D55FC079B28AEB57301C09D5C0807118A8C74D2B41177C731776 +398000,k,22C5F31E96D021E11057DBB4083A2713153F201533A833ED8AC168F9CE17D56A +398000,u,D88F610EA7EC0D377E6BE3B187D0E31EEF1B0F36879ACBFBE9AD98B6330B901E +399000,k,520FC34338BCDDA47709C00F8EB92271F10C5B9AA580789F99C696B694F8395E +399000,u,6F107F1136353B468A27E858303297C1FC09B450FB5DD2A5183E7DBD93B13C7D +400000,k,EFF2FC9C6496A11F932A1AD6649647E886AE1AAB005AA740D896DC672ED72464 +400000,u,DD9A6224CB4A562F7D81B946DA006F119C2DC143160C55B6C43ADBCEBB890C42 +401000,k,BD3BDDAAC31ECD2D4E249DFF88750BB70309AD1B57EAE1229A7BD58A88816807 +401000,u,104905838E6A41F98FCF9F9D0146CA1B9EC0701447B2B672BFD5F5CF57C29341 +402000,k,E4E95C5F18A0B99E387FDB418A1CC5CD7BCAB487C4501DC3C4548C9507E40D2C +402000,u,7CB83A580444A347F4DBBD1E09ED4684B858F0D925DA3BEBD44A537D8A0F102C +403000,k,FD47E44B64BA270B14563AB1E627472EC7FEC7E7B3C65D80026BD11B3B36A916 +403000,u,504EA18CB2460AD72235C3456E645936D60ACC3C775F1FBB1C227554DD7CB217 +404000,k,7E86D6140C55EE1641AA0845D82B728FFD394CDD86753C9DAA94676B746DFF49 +404000,u,4D98B136DB183F57848C84912824E9F2459E0692DA1E8EDF0A2621089278D63C +405000,k,964F8A80B984B343C9B0AC94F9D8AF3CB67A6C4EEFA7F3B2A158A0685DEF3C6E +405000,u,8ECB9E1FD0C05310DBA3AB51219288F5921F9E2CB1B890491F0B4B43378A050E +406000,k,D07A1779D3D4A733D3AEE69583806D096D45CABF8BD2991AC7F7E89E31B2DF4A +406000,u,5755FF1E004CB7823827C3F0DAB8900914F5E37520A5121A7E1AFD331518590A +407000,k,350C338AE1DE99E4459729BE364AF7043113D898A11D4EBF6B0CE8234BFEAC12 +407000,u,CEAD681158452B50A6AE2BD9FB9AF3601AF5E3C4E76BA922BE4D29BA2B8A0A15 +408000,k,5692EC0847988EC6D22FC0D64A2AF49DB6B561A0004A08E23727032DAF73B80B +408000,u,5FA4BDA2B10BA51A27CB3FF93C4055C1D064B777F966319CF28C25E28D33B15C +409000,k,6CEEFB850BB4A9538443D222D840EE391241EFA1CF336B685108A7D49FD1DB47 +409000,u,F8CFDD097AFE80FBF8F080B924358A944FD1828FD19C245946C128112D053218 +410000,k,3ADA62FE3E69027F4C05CC061BD8271D11B34F0551AB0DA602B884AA573AC237 +410000,u,7FCB1B28007AB0432C306E1B747FA8960440A68B1A0988845234EFA251C8856D +411000,k,A79E1CCC6D08044750351D8328033E18BE83E3B49212F05D4DCAC2CECEE7BE1C +411000,u,C78E229A18CCC976ECC6A735533C8643C70265EABCCDD99B174E6D0324FDAD3F +412000,k,E6AEE457DF8E45EBC93E9FE62FAD3A96C0256C7FE4D73CB288B9F64B26C3C273 +412000,u,2D831D712E5CC28D545CE4E2E41EB732A4531096B6BBCD65A90B59B196CCB162 +413000,k,D3C729EDD87B8196AA5FA71595D83E7BFAEAD5C955EA4F34F4FC81DB21D8BA5F +413000,u,3ED43D861EA315EA636D24075F39DD47BF004AE8B940098468EBB8921424D47C +414000,k,AFD0A57428BFE8000F67451A39C044EA8910345919FF7ADA26D5CCB19FE90615 +414000,u,BD86602C24D0EB3A9E48C147EDEBFF40F6725D72E2CAC60DC7D0A70689F1353D +415000,k,C6F32C8DDDB50220AA9E48F883D4467BE657116FFFCC8A20572322EECA57CF17 +415000,u,E3512FD03BB7BD6C0A3DCC0538D2F1DF7620F27B24E8E230283CC2C45245F811 +416000,k,5465EAD38FE256D22709F2CA12B8E481E5641FE4CA56E26BACE9E28F5E452F70 +416000,u,A74D4AB3D1D4A8A538A7B0A06ABFFD9015E739801CB5B3CA278CEFD995A04127 +417000,k,74AB2CAD92D1A6A4A621D424F81601ACAF0E383AD6B99ACECE8D0597B75B6914 +417000,u,C752A797636CEF5B847EDDFF2CAF28B19D420A88AC7F3772CBD5EA8F32C39F32 +418000,k,21B06CDD0CE0BA785CA5267EA8E69E86F377CD712614F17788B3248A6DB52607 +418000,u,09E50D2513CD52D1C2DA24B2CE7098BBF3FAF559C65DDAE84D9C868483896F1F +419000,k,CC62BE892099A6F1C9F3BBEA4029FC100DB922B9547716D9F01FDE06D0210F24 +419000,u,CA0EB887EDE6C699EDC4720DBE7E331DD17B853D5610AD34AE95BC4BFF064577 +420000,k,96783061F83983B3BA5DBB2E830DE20408ABBC53A678FD4A9693D0DB96A25E46 +420000,u,E876633E885BABDF7B88BE900CBD0F37100357DFF9DCC560274E29B7966F7258 +421000,k,61FCC6F99F53DBA8834892256FBE93DD1CFF80A0DD9CA5CAB268F3E219549C43 +421000,u,C5FE81313D2D7940581DCE8C66E6C25522AFC915078BE072A8000B67E430D23C +422000,k,A81A0FCD97450455AE402346A63743CB6528A1D8A25B4B419E2DFE3BB03C363B +422000,u,76B3E04D58CB0ABDC7A006E2E2B62069CE59995DE7050C3EEF894C5E698BC95B +423000,k,F61DE54ACAEB48C3169373F5A28A9F43114B9A4BC23FD891D2A261315F527708 +423000,u,A6B7AF05DD56332FFF6A44DFAB7F58E4EA1CD332D8DE134430C7E13E771D0E3D +424000,k,CFE299605E8A32CB30385204F50F956EF1D10CC9675CB0ED6F34D39B85C1AE0B +424000,u,355CE462589A66307E63EB4FD4D10E329493DD7EE35888F601ED8570E55EDD7E +425000,k,45387266BD45B11C25CF96A6AAF49FCD326DB4975719B16376E8D2DDD197031D +425000,u,9A32247DE374A992DC13C2784D2D9F66DB5B34E883E298234A8118E333742450 +426000,k,EB17BB60E3FC4BC71C507DF8D243DCFE1A1E8402349866EAC4147048CFADC85A +426000,u,BB5361C2818D544A87D589ADAAEA545B3F70FB1CC253BA985D86073FE2FA324E +427000,k,988A86E7148FA956714FF7E14E5FD53AE81F8FD46F2DB4E5B409217A0A8AE718 +427000,u,9D44AED1E604DA1FFC8AE26C027C0D9BDEC998C33519040C5E440AC8321D587C +428000,k,7300524270512D4E4F2E2FB12F3E5F263513C05594A2E44081F15268E6A67F19 +428000,u,1774A5465141536CD532FEA6BE5145C3A54132A468C1ACA4271DEF73BA0AFE19 +429000,k,00640867EC725CDAF31D1CAE3FBA2258A355B06DD36305A8BC86FF084EEF354D +429000,u,CD1442643612024399B64EAE5F9342AFEB32BE0CB6AC7296569653E4971FEA04 +430000,k,C0615E1233CB4CF22DCA07FDE7236CE281C0E574F7E49034BBF07E1A7A335B76 +430000,u,BAB7C0632D2A00C7E21B0DCBE7D47B5C9BD4CC409FFE59502EB85A6FA6AFAC75 +431000,k,2CA6A2E6B57235A685D26A95A96C9C2C824755E17720109C6858E9D00B5C763F +431000,u,FB8E77FC707B21E53D6E176C06EA855E0797A07292DB41910AC468CDFA601C37 +432000,k,481E20F59A5C8942E6B98C131B86F93481C5CD85B1011F7C8AB21168CD99FA5B +432000,u,9FA10FBF2A853081121A53D06D45894EBD394D9B335FC7CF0CB5E7B362962A7B +433000,k,5718AA66E52E8DB96EB5ABE8C2D398C46768C3392243BE6A91EE6B2BCA50411B +433000,u,D69FF1C411C6B08B04A95F01DC9543721EEAD81D55F93B5ABF673E3AF133C428 +434000,k,685735D485A5846AC185882647E37A124BF5D88A4AC739E2B0A0C3A6A1AA0B10 +434000,u,036CE4E41581B505426C4061785A9AA8F4D8D9D75BC25091164272D3540E0F55 +435000,k,D41E0C2A4C3A06A31E495EF1676C652AAA9501B7F0A9587DAE52278D7DA0EB00 +435000,u,C5BA2E4E887BC1D8C32F0301FAE07A8DFBDB3FEC4F6366A43A13FD89FED4F01A +436000,k,3C6AD9861918AB72EA92BF79CA370E950CDD3AD4A3D81B0CA957373AF9F77306 +436000,u,8BF11F7F83D913BF83A9AC1950A6F0C25AF0EFE97ECAB96469C82C2F1D177234 +437000,k,1A67630015943D04620FA94E644DD628CE583B623A76E1528938B1BF23F5962B +437000,u,3FB2BA783C3A7C3461F79C4567405DF5AA91D2B81E408DFCA3711829FE103F61 +438000,k,3620736CCA364A892E771BBECE5C413496342A3BFE388DDE8CA61E848C17A859 +438000,u,10956A5E5EE40BBA5C1313F7DE5001AAC6C0EDAC72A2C783DCFEF55767B25678 +439000,k,F4A64CDD89F0FD170E8A8A6F377DF6211C651313F1C709947BEAD66592B1145B +439000,u,9A37674F02EF58372AE8361A952E5E55344FDC7F25F3A201F1E5A6FC630CAF22 +440000,k,18E48620AFB9FA03FF0B8DC72BB0900AC31C441BA8CDED1C618D3A8322EBA171 +440000,u,98274DF4E87385FF1F13537B23B1D2DF83FD4892A32A7E10D22C3A5742327D33 +441000,k,724B80BC7532CC85025C1450D5D5C2DD221FD56B27B88371ACCAF247D24D2A73 +441000,u,1D785061A2A758F64347A19CA40979A8CF2DD3DC6A70A76E19CE85F358A54E5D +442000,k,72AAE83582F0BA53E4A8934719666DE2D20F763A9B0F0B0957F15A14391E0718 +442000,u,990BA6A8FAE5FE6A410FF9BCEC420A5F9ED7DC71187164E24441F716BD6DA76C +443000,k,35D8C5B9A4A07FEDE70D6A24D09848D2B4BEA21BE242616078573ECA69AAEF10 +443000,u,F7840A1B74193FAA56C6947775B2CC1C3D81C8468F17ECB13DEFA6FF944EB410 +444000,k,DE9FFE48FAC046C44532BC6159BCBEBCF0343A1BD4223ADDFF2161C2451E8E24 +444000,u,8E418E69FE016B92817184E9318BACF33E0A6529C003A0FBFE965F03EE768A18 +445000,k,F4E3B451780790831764AEE199F8B9C758AD18BD25110B0684B6E56E8802E642 +445000,u,01179538947B06CD8C7E61870EB18A445C46F52B9270FC6AAA21118A8577E04F +446000,k,6502C79F37C897FE7E36C2E96445FF699D67CC19BC7F25F8A623BF83F64CFF36 +446000,u,BEA54C8201CBB0B0CDB27BC586C0593D12C5C84C553C15C8623B11977318C802 +447000,k,ABBC53A545F331E2F2B0F605B262BCC4C7B10E6D8F32627515FFE4520071C469 +447000,u,530BA80C28E2B91B40ACE8DD8FBA724F3DFB2A21414E28A2A0717DC717DAEC66 +448000,k,5116B3CC5F378ADCBD5A4E61C4F31A6203EA594E9E9B4C0EED8C47A3B4F2F709 +448000,u,D2653E8BBAA60BA9C53F3189E6438D4AE724875FD5A1D03346646A29B111E81F +449000,k,865A3349E8D659916D87FE850256AF789CBAF5A0AE29326278D70DA042F81545 +449000,u,E23D6AF538D3A53DE3A71B797737B8F13D68D1D8DD9C1056962E9620A04E5F51 +450000,k,CB377C67F617930BC057B8A29BED4D52538709802889FB165EABF42F04C44750 +450000,u,B16F0C60264A00B1B3D8FCF15271A6238A1A11F8B4AB7AC807652B9A28CD2E69 +451000,k,43DB43290AE9844FF155A84A19A9CF1AD60878B4F28E3EAC1D74C0B05B81BF2B +451000,u,3983648101C31D2B866C24D070E2DDC9683B44E1F88055A332A52804DCAB272B +452000,k,E18B11080F5860A1061EBABBC6687360C64F9A27D01ECD5F24466A926C946100 +452000,u,F840DA219FD816476DE4A7A16AF051D0C03D60544F777AA279DF1A6EBE59A302 +453000,k,0A37BA97E99C11358B87BAE99834F014ACE970F5312D728149F732177A81D37A +453000,u,0B21FAD28161C6D4B10A02D08D074538D571031BBA07C4D5528F2E3F1BDC742B +454000,k,8CD8FEA77C788D0E1690F90BD681218BC20153D9B767272471216EB31416B010 +454000,u,AC3091FF2413B9D901EC22414C3F9CE776C3654A2007415C15E2C17DF6531578 +455000,k,118626AEFC3E0453D2B9443F84379F03AB6E978EA84B9A9772E11DF4F2951641 +455000,u,63264767C09281FD326646859BF67C68A0C0757644A6D60F60677238F0E54835 +456000,k,13AEB5EBF742F7A59439DA37B1030E50024801B816D325C65038E3AE298C6C0C +456000,u,D080160ED4AE468404396D3EC660A1439AB161522238B7D14DEDBD0B2AE32A74 +457000,k,64DDDAEDBB75AEE69BA9F2DFEDCDB1E04DF7D5CCC821D11A5C0E4D8B27570674 +457000,u,1EA8EAADC50AE8E4981A536A51E3E708B0081309743225D29AADFBA9B0B34175 +458000,k,E3BF4620E1D0518EC96F76CAB7CDF185F45B01303E4EA2442707126ADEE20E32 +458000,u,AAF582233D11BACC46F65362FA188003977E55BC3E720BE8F23EC6621189115A +459000,k,DEB5DB7AF8153CABFEDBC4166C4B43E04D51D3AE14AD899F1A02C162409F685C +459000,u,F4012C32900AE8361C9E9AB4D1EF2B0D8AEA869934C91F7430E8D4920A9F2274 +460000,k,9E8598AF47EA5D7E637BB4D944D52474052B061BBAFD75DBBFBA6F10BEF4B872 +460000,u,FBD7659FD1D372ADCC97AD64BFA1CEE32A8BBED307B7A087341F172C81A63003 +461000,k,9E8CF739932594EB26DB7BD40AE8C22F48623C7FA860935F0436BB896646234E +461000,u,0AAD907D6DB5A7399F27FDA7DE1938C8ED55A9C6492E484D92942F837ED8F274 +462000,k,6CA79F6C8539302F516FF765D90CD8A775AF17C06B61EEC77B240691FB8A3A2B +462000,u,00361B8EB5C424C02392D2AB20751892C732142B8E82EA43D90389CCFAEB5A54 +463000,k,FD1269D0F8F7C4E7805D61E1B493E23BC013493DF7C08D02074A5E8C3B357C49 +463000,u,13951574CA01D4C10D5D486F74032B0E33A9D4EEA1658D0ADDC5F06667917F7E +464000,k,2B8653A0363423F91E94CA4377FAA68DEFCBF30F8CDD316DA0E40EB859025633 +464000,u,E4C5EAE4BAA90AADB5F97CA773EFACF721A43076D085E8C596B3A9E934D0D42A +465000,k,0DD3867EAC954D325B19278AA455D1A06BA49401BD9D20B30A7E4784549D2B10 +465000,u,1A8F3953E8828D8F123F9BC1C4437ACE6DBDB08878EF20AE338F0FC15B470B4C +466000,k,B5CF019F14780CAE1D69276EA8EA96D4DCE2DCFE35F3BFFA1DDE60D219662541 +466000,u,9B7192FCF14AA741F3ABBC71660715CA9BB17214D2E0AF614B9EE65EE8189368 +467000,k,78E8130E07E5C0A49E8E94573622D7ED29AA530228A8D44CF6E87C11A168B64F +467000,u,1B23EAB848CCE206FB05C02D72A1A14D2C13C639BF583D722DB87EF319E4394E +468000,k,362D047978D4B6E281337FA7E943B16CC58D327962C2AAE58B3E84AC159E066A +468000,u,A795E02AB22D74E999412A4C400E8D04B5CE1A088FEA97C97686FD59B83B8A02 +469000,k,26FBC48A173B865C714093E33B844B38031651C7C642D81EB47E68589A1A046B +469000,u,23CA92136E2608DC2F8CA9C94BF79BC1C3D496CF75D84A7C729CEC6C1D2FF724 +470000,k,695BA09816AAFFCBDCE296D244E928D4ED09137615E54F8E570DD2409BBF0931 +470000,u,8BC80E3FFD7CBA7E5441D0514487D2AE23F2C8BAE0D6FF949192D3D71AE36535 +471000,k,7EA693E04991B057FA00A029B3938BDAC0E5D07761FF1E9963442469921FAF0C +471000,u,C2062D5586EA3CAF6CE2D7970919A5AF8F81AD432872EBDB7A88E5EBAC7FDA35 +472000,k,6946C1BBE7AE768E2DB580C15386132E88B3073226D41E9906D7A9F085BAAE78 +472000,u,8018BDC6348FB284FBF159DF8C51CB551D37C4F049FF0C772BF8BBB0B8575B2C +473000,k,6D3FE996FF580BD3833F9285C140658E0ADC2FE26047C55B13705DB82B03BA03 +473000,u,B57B9DCAF7543D3B5943B5943CD510467C35E5242B9D12E44E89FEA448414A27 +474000,k,0CE0207B79B23A6F766829C850D4C84D581C3F3BD5920848C21BF21902081701 +474000,u,E1E0FB72AD3C1966498DB4B527F55B1FFEE4196A14116A165F96CFC648183911 +475000,k,854C759A86666088A9BEE7FABACBA76EC09E1C617E4DE540F40B4DBE67813B24 +475000,u,9A4DDCA9B3B04DEB709B3D8EB840BFD2130CF76F8033445EA4BC80EBE4CDF053 +476000,k,089778927462709F70868C04FA9F06882AE85953249954B99AA998EC9B4C8661 +476000,u,88FC4118ADD4ED4E3A1D5C98DF9514AFD57880A05767F1481F2893A700F8EF20 +477000,k,091358ED14B1BAFD230952DE7F368B5D679706A5F3EC639C67CFBE9A2FC02567 +477000,u,24615DE66FA830BA9D4E81C6E79C6097411785123F642A01BE9D547C3F695D54 +478000,k,51ED06C93A865FD8CC183241EDBC35E7DFDC73297CEA7D200F50C98ED6C44D4F +478000,u,4C4E58500F2759B963529EDF31F2C7EB58403ED5E7A9751F1CA31F0B9AE10453 +479000,k,D5F36B7DDB69FBE3A86E79F93040CA7DDB907AD4820020B6C02F467CBB02D503 +479000,u,80F5042DB9049626789FD39483073345FB5C83F9F302EE5C35908E2D2FA8DD2D +480000,k,475CDF043B8DF64205A4FF3F3EF3A2978F709AF3E984E0F7C63B9C3943CBDE6F +480000,u,3645661B16EBFD3D411CF6BCBCFAB3FD7F0E9F5C7DF2ED59D8D948A045CE1270 +481000,k,03D9C24C2F8D81C9AA6B5CE6FE744EDECC105F20F01035ED2ACD07F7D0390348 +481000,u,B9BBBA902D5DC1120E05F2B3CB3F342755E27D5F2A66956FECAEBB8774133569 +482000,k,464B5750D694255D64CDBF49274292DB0A2AA55153BF0337607AF73222C9A408 +482000,u,41145398FAB1337F21FE09326D0C9926781D9CFD16E02E3E114629BC4491D260 +483000,k,913A2091528A7937DCB3D305BFC542E9B48FD2C07BEED040EE0D246BAF771C05 +483000,u,31F924CCE22A69FE487707735ED2F966991B83D26D6D9341CAF28E5C2EF97848 +484000,k,7839DB5199F21BAD42918DE9E7AB5983B5DA3000009FAB90DB7ADD4515ED0D77 +484000,u,FD5318AA9BA1C23366F3926A349B69092E4E5D1D39865FE83C42D04D5B728D08 +485000,k,2D3F2CB14752B8E5F798582726D2F8BBAB340D43C65B9EF7C610F3CDFE81632E +485000,u,56E60FFD9BA4ED055381A5E2C6130CAC48A5A52AD89499BEAB0E9AFC5889217C +486000,k,E41633FB5EB31E9BE3FB011C7C4CE47ACE3A3B956CF22C5DC0D57B150B86CA0B +486000,u,881FA416A821000AF077CB537BFC1AB937E8AB08EF37FCE26B1EF54EA78F7454 +487000,k,AC7C1F1C7B97F71916A56024F8D739B7BC2E187D0FF515AA2224810B9EF76930 +487000,u,BF80F9A14A2FB61C469FA2272E5856554CB01FA74123CC586C907EFA4284754F +488000,k,262510532412B2491944D1692E40E6BE1B7A35E603EC68375E6AAEC82A6E7A53 +488000,u,5E39E1ED9913F79B4D6A42BB7168CAD622FE10BE4C1A0E3705DC811A6B5C5264 +489000,k,209AB02B154485A5F1D2F43B1F5822D60A7870AE3F9A1D07454B5D10DB28A662 +489000,u,442121483369FAE5B86B855FA634B86FE93348B9271701BFFECE83A9D57DAB18 +490000,k,C72A8DABE218D21E05C967A8CFCEC3956CE9AF57268406DCC426D9C56025E574 +490000,u,A1238093AAD444D1A51BE6AE6290621722BA4EDED002D625A2D5AE5BDBBD9A2D +491000,k,74E0F499553B27836446D056AC986CDF827CB8C7E823D5D0BE3B68BE7006175B +491000,u,7786CD85B31DFBFFE60756842A1C328B5BE84528CF0FC976FDF6435BD626D352 +492000,k,7EE63B66A01926BE67BB03BF34309AB8BCEE31C971482BA6D126283A58967534 +492000,u,818F9DD6FDFF1C039ED440EB382AC076C532D69D4CF6C0A66BEC0EE3D00BC318 +493000,k,AAC1CA6D2E2C7E9A478267CCC1D86CF6688704BD729F6F65F8F8BC3F07D94E47 +493000,u,D5791AFDB21F89C5A67E4742BBFDAB2F27D92EAE9F4563B5B9CDB064A6AA3C08 +494000,k,CCAE6BF5F8929BA22F5AF0D18DDEFC6C8986805576B1534DE9274EAD1DEA0E38 +494000,u,0A6547364F9D95F0C1ECA428B3229F52214F7E649606599336BF6285EEC5347F +495000,k,070C467AA087602026EC5AFAE79A542C2D6F7DBE487FD268E5EF92AB95091E75 +495000,u,F3CB498DE87A9E5112D04950B3079AF8D279E2049E40BFE83EB6D3498F3B1F78 +496000,k,83022ED0C8A106B12E7C123337F1C718306042491616583B3C44FEB3AA72320E +496000,u,234302B2FE6FDE97BD00BD9C6068E1FB81466DAF1C7B002683F9ED09C022A17C +497000,k,976931437AD786B2424C4F0898FDB792F126BC29A05904948DAD18269669E838 +497000,u,0B1C2F495B3D8D996485FDE55778A057ED1B4D4E8C7F2172279D5B8A9CD74621 +498000,k,06030FBE1C51B0EFD52628E6053B0D94D5F451354D6158581CEE1408D88ED042 +498000,u,88C851ACF5D4C866A215172CB14DC1A6796C9E7EBB88C6BCD50BF01B52EAAD09 +499000,k,98E46BD58563109FA3E3CFD9F2E5FC95CF6F303E1FF90A6BEE6130E85F2ED71E +499000,u,E30871128D1C80E400E9BB08DB4CE51BCDAB19E9CF510BF582497ED4B311DA11 +500000,k,EF134A6BC887E43772479C9D3EEFF8FCF5F079BF50F38C3EBFA159A391A97616 +500000,u,1F47A3AAE82EA65758BB66A0D59F7F0DB5614763C5CC4D2A5F7291E1FE67280A +501000,k,5B5036E4942FB08A1223E4C17A3E8535BFC3E1272B20B1EFDC3C63C556FA7F17 +501000,u,331DD0C35F5B9682114C99CF41010AE8F5B61FC4802E09823A640C8F42F40C2D +502000,k,5760979FF00AFC0D63C69AA7C6FADDBCB89234504486288C122A36DFA00FA243 +502000,u,B7F5EEAA42AC8275DA1C1AB5F5904AC2E0695A2CEB9D0379AE2843EAA3CB107D +503000,k,583F78D6577652E79567060D79870C5941841F76EE31DAEED79B21BE2A3C6F65 +503000,u,CEF1DC834E2731519E22054107384C32BB878D9F5395BFF123DB7F30DC4D5774 +504000,k,17BD73125170BF75225E1DED13F7D33EB72B7ACADB476390D5946E02B9326A40 +504000,u,A12CBF8ACC681F3CBE8A60A8A77FF27A5AD1EFA4A8AB804AA9D5D9E67598C447 +505000,k,4FE76F1A0FC0EE0471DC18D0942D86EC0807871DF723E647FADE181A72424012 +505000,u,E0F5DE24BECF77E0297DBC159A08AA914F98F5B48A0C68EB814AC71C8F239B54 +506000,k,F78E21B6E65AB795B862C22B994FF8EC6A33EC2A19AD99E1627950F5E3839071 +506000,u,30DC99910169DAA1D45438A7FB7EECEAF0552940016034CE8CC19895CEF39819 +507000,k,8A0349BB7E7BA0B22D55BC6F061EC607AABFB6F44A5D86D14A34CB67B8409563 +507000,u,5607C4B148EAB98FF56E8616F5F94E0B6781933BD13A5B2AF17924C429E54708 +508000,k,295DF4ED6475C2444352A76AC4CD03A158991EA250515BF4E79AEE8B004EAE43 +508000,u,D77DBA5B4F1D77AB13D433EBE240F14146FC2824DF04D26DC6099BAE4AEFEE5B +509000,k,9370DFA83F70588668CF2173B4B0BD8E69BFAF4DA6E62F3F60241FC2AE555F39 +509000,u,F6F45517F1E74E892E4A54C1B561997F5E826DCB495D519AEA08EDFE9B9BBC3E +510000,k,4DD8317EE3905EDC1D694D105BE27D628F82EF3151449FE5710DDB7F15732E7F +510000,u,263D2B14BFED4241AD787857DF33163FDAF263B77DA0BD9AAF215CB0CA73457A +511000,k,79C1B1F7B7BC76389528701DC01B005EBFFF13C5D0926A5E724834A4F1516D50 +511000,u,46047F95244DD35164EE914CCCC8A91B85ED33C52B309BD3CD3D6AEC23EE2928 +512000,k,0907F260C114B27F1FA32B8C4F1FA131AE69600C526530991DC626D168C21A00 +512000,u,9422C9BC1DA41FD2C5B6356E7C458C66A5BE4B54AA16689675B1E8283A7DA774 +513000,k,BDAECDA9A144497138255D4E2663E44C05929B2064BB8D5BC080C5AADF8F1C50 +513000,u,258D50B9F719D85D949733FACD5CC26949AAC698F19566883EF72630C9197347 +514000,k,60886B7DC35A9274D617A7762681C146BADCEF4A3665716D52E17601A134AC3A +514000,u,03CD00B550E728534AD4E442D498AB5A4610BAC2156A3210318DDD0B296FA22C +515000,k,AD8C45889D3AA035C20F2DE70AC87BDA6ED634457A08AD0B130FBF4EE6275109 +515000,u,A8DEE1B1A437648CABBE142D67B693D89F109924F736814387BAF405C2498A2E +516000,k,26A234BC802E410A7E36ADA729E8590A4E1D3B06B0179A1626142F3C01D88F74 +516000,u,19D8EB3FE104E003F6C1C82A09D4F02AC6834545525689A780F1D432B97C8530 +517000,k,82A5F5B97B8E54D496FACD8E18BD33DAEE38613F962A3071BC30C0D30659AE68 +517000,u,FCFB9BEFD8E69F45AA1DF2D029F46032420051F0BB68E01147206AD3E0E52925 +518000,k,81E8133CB8C3157D9BE1C4644729F2B5BB3CD0C970E80F6CA656B5F4AA156C26 +518000,u,F21CB594FA81A8299B4ECE167DC29816D613B28A8CEBB2D2750C4AADBFF31178 +519000,k,966D5C812F730DAAAC28FF39958AB25A40D7F67935259A21ED69D08631815D17 +519000,u,291337DD780D042640E372632945CF4E5E4B561EC4B2423D596C68EDD356E326 +520000,k,9EF76924E166488F5FBEB17244FA857E3BFDA534198C29F5A0EDDC821388146F +520000,u,55F8E5A6D29CF1586007624CD8C21D66AC9B4EDED72D7B4F0711B96EC9678F4A +521000,k,490C40503D499687C35FDC9C8B5E32F85A1EBE52A490FABC020EE3FF838A7528 +521000,u,392E1C2DCD8C5B7F65D06EEDB14D33CF739EFDDC5FBA0C5B65ECB6CDA0EB7A0D +522000,k,53A1D4DC3B18D7B69CA03A8A358FEE017FE249BE2F5A4FEDD6B2A8525B72CB07 +522000,u,367BEA7218C76536BA56B6355C9983ED609A53D3B678D06418700170330AC570 +523000,k,281BDE895BC175F986E48C6236D4C5FDF5D1FD69FF75FC356661EC8230C50F04 +523000,u,70FD0FEBBB26C529BC3E81BD46B692CE237B41921251991965B2811C2835BD45 +524000,k,F9AFB8405A66FEDBC887DF005D1987817E54FD02D312F187D12B2A59FC1C3A54 +524000,u,7FE2789413421883DE45BBF8596087E9C25084219441ACD106FE1EEA3F5DD203 +525000,k,DC5E3AF638CC03F5BC2015280ED808411038E09B0CF53A50569B0E15C7B17F3A +525000,u,ACB837DF22F8CAA8422C62071EA7723755873E74B4D7AAA484A1CAF986A8A646 +526000,k,2A0CF5D5321D1C7A1EB4C483157609049FB5E48BCA5E6981CA47728B9853226A +526000,u,E08A21E5C481EE36EFE87ED55880710731851DA3870CE625D85FC695395B7917 +527000,k,1B59AF3A0FF292617E81E7CBC9E44426955631B005B5A2BD36A0B69743508C74 +527000,u,9C549D772CF1BA5D8E1259B24161858C8AFC8B22A3BD6EC93F2F36B9A7E2990C +528000,k,EB27AD80BA2A427D945160B0EC2306CBC3666530960BF226D27475371947015D +528000,u,BEABE09A8A291282B1EF9D13C31D6796085D4C3D3F6A50BB11D93B8022B96413 +529000,k,E6BC3E82651C3DF03FF9655901BD74B8A9D23E777B43AF15E8F3F8FC2A97735F +529000,u,155C45888977AC6D2D43D5E16CB44FAEFCBD15B437A90E0677FC5736475BCA5E +530000,k,B797B3849E08A72444C3A6938CFE277C57600AAB9435B722AB777BF9C4D0567A +530000,u,81C237277F8D64BE1AD29B776C7B2C51BD1774DF9EC2ED280E8F73F8DF5EFB6F +531000,k,E8F2ECB86CB7B43124B40C916CF408CFFBCF4E1FA0049CC1B1462F804D92801F +531000,u,540777C085AEFD3D45080483604C5E9F648CD893970B286D8119281E3BFC8F1A +532000,k,CAA8E0CACA37B23CB610BF5B02D5C02BDD000C02BA58D0142032AA0734BBAE6D +532000,u,42B93C17B81066B9B16BBD7CDBC3313EDDCE773B3D5AFFC806F5AE567C719931 +533000,k,F9F07D9814EEEF4CE9B606D9DA7043A46BACDB4BEC3BB3D023499FB730AFCE44 +533000,u,665F8AD1446AC9FB63450858F5CF7CF3D55DEE390F1EADABE12DF0240EB5B711 +534000,k,AAF173BF7A02A2C153ACD14DF534015087049F0203CD57F583525E8054338D67 +534000,u,54BD48F50CB2CA82601D4189EE9B6B8AFC3D69A70F29C900F643DF49D9BF0230 +535000,k,1245DB2F7818B6C250B5AAA093D5FCE4615D1D1543BF416C56C3A75FE2348C57 +535000,u,D54AF47260EDB4CAC05118292EB0ADBCCD64F7F24206D01B18FAFBD55F516E1C +536000,k,BE57832923EC704751A21FA2666C4CBB999BE346D28318F1C51F7FDF1E3C2C55 +536000,u,D022111C337E1714E5D9C08D76782A2010422BA59EF86F0235DAB74F39304436 +537000,k,FAB78F48AA11B88541FEFF5E3A5A20987D8BCF03134754E1D2FFC9E99A9C5803 +537000,u,81F3EADDD1A61A9826E40D7F5D91F308490B4B6D0329A91E921C0B5C557BF87A +538000,k,7A9B027DF2058515327C7B5FCBBE2ED6B25A78639D00428299DC858BDE3B4F4D +538000,u,2A989905CBEB77B09C3E28652A67188445CB5E2492958C5248FD2D9068D6D978 +539000,k,3EC04382C1B4C9EC66277B9AEBC2748A3619E2A1AD456E69C400C3288508303A +539000,u,7E46A7AE6E3D10D4B580F915A409F098FFAD99B87DABF938581272CF2799263A +540000,k,A2EE30613FA27A647CA36300CBFF2D3807B0DDF1D5C2947E767BABF7621E2F3B +540000,u,35651D21213B8D8E6A0198235E5D3E0A0D5EAC1B0BE1C5D21CD974BA4632B850 +541000,k,9CC43C92B446155EDB79D8EC50455D5F31D17A8138DB543C6D039A7DB1455978 +541000,u,262D4A6D302FB8FC163B4081EFC8942A848DB47D6F133EB2A28E63CD46403826 +542000,k,0FF726FBC4AAD34C6194E7053BD20308DADA31E812F3CB1ABBF65CF01D4A560A +542000,u,E108A97B817082D8B2E9CE128F0BE457BCA78CB6EE48568F3370593C5C8ACC7D +543000,k,E48167AD76512B8AC8219F0E397D6FE6EC42A19E16B738E49ADF46768D80D05B +543000,u,16C66CDEA4F2C7F7EC4BCCF1D48A34DA89EFA31B2F4D47145C744C13B7902971 +544000,k,00B04CC1F0D22AFB6EFFB7E7100402309AE263E0D65ABBF87EEAB19A2F7DA922 +544000,u,18BADC8A62F725CFA9415DEDA28B207D4597D7C4345B978972F7872664170420 +545000,k,DC7542C3685185FCC12C50F82B6A8221FDE8D2283567C06CB9EA7B541959BA38 +545000,u,30F4E488CF53C66FE249046B1F608EA16A4C5018261C7AFC9C68BA4FC97E1576 +546000,k,8B56B595009683A90C6CCEBC8BA0226A106C107EC5F58D382F7B7DCB7CE9986B +546000,u,04D696A818DE695C4A565F101C0FA9DE2B856CB0DB4E25285E0B7CBCFDDA5049 +547000,k,69139CD583826282698903FCDCB2230E103E07973BC29C5664809054660DBA4E +547000,u,C04EE5C2189D9E0CC1143BBA133971DAD889AB6AF98C6180D55369DE17F9FD03 +548000,k,A7ACE2852BFD46C02F810F4FAD63B27B53F797F90AC1D897B2A9070FA8A33650 +548000,u,182F788639A109419CB6D7163558D829599B33D04BF426D4158AD8FA29F01104 +549000,k,B2941174D162A28146165EEF37A67305EA402692BB51EE21F9834B76759E2C17 +549000,u,FDF301522829121247C39C7627DB55300949C19F2B5ADDE8174442978D2B3934 +550000,k,9750F4E2A8535FABB12C27E4C72C3368E4ACBE91BBD92ADD43A3E95BCD42B723 +550000,u,717B8A1646A2ABF9D376AE1D1333E97488E37E21ABE3584DADB0DAC6A433FF20 +551000,k,F85A8416C418F2EDB508820521DB18301BD195684FBACCCDB915FE106B6EC953 +551000,u,3543C838FC698DD2E43AD543C4E0AE2E6F23ED98D9A6B51AFFEDB9621A576264 +552000,k,11CB1A99BF23D4805739FD443FEAF0175BF45FA70AEAF61D5BCD02CF41465274 +552000,u,6ABAC61DC5CDED08162DA16EA0D099807976496FD26CDE3EDDB8ACDE76CEE865 +553000,k,AA02A20D86E3A68CD19B3517D12342D1BB0A58DF59D11624B9B1AE5771E40965 +553000,u,A967CC1BD5A30BF27230B8549D0A435AC3EFA94E7A84664FFE91FD746C1D4F20 +554000,k,2AF83F41EF47C5BB4501A664B54722F1D1D79C07FF5929625C5E27B4B942D245 +554000,u,DB5D936526AD0E5401A499832C1EE57D74CCA4A5857E1A62E1D0091B312D5210 +555000,k,E77A18F0E67994200CDDFED8FDF0504018B44203D4E6C201E15D05E5E59CDF11 +555000,u,BB98D2C188BE31D238D0D1278D9330D1A7AB970257F286C3866028BA57DD4423 +556000,k,1CA841F662DA7E5B78CB46A198536379515C37C5CFA6444B88B55B401431FB02 +556000,u,E3D4672AF366A88142256A9FF7B6A623462625E74E7CB80057E37B39EE68244B +557000,k,AE9D06E9F536FBC210EF32D9120A3787073CC056652A6765ECC42EB859C46929 +557000,u,90DDC359FBB759209A0484AD6C04E2C598FE9542E8CE3E4298B4687270EFCE42 +558000,k,7F3257AA873F93ACD81C7B6BEF3A0E10516B768361D963E53D272BBE04F7EF71 +558000,u,5EA2CB0F848242FD15D101C8E29673B6C5FD47E93B42675A7AB45CA7EBE86204 +559000,k,C5412E7AB88112A654A9A2B69D3F2F9B58C1EAEC5DD6C1E17D5FBFB4E77E7D0B +559000,u,200940B0C705BFDC143FB91974123E1F9B79D0EC24A16FCCEA3E4D1081FF184E +560000,k,16F8F26868DBEE3ED303AFEC685BA6ACCEFE967EE0E213C1661CB0017D69FD0E +560000,u,C4C8C95C149B9B8FA8AE79ACF40F76F02D85B7F630580B39030F8C8C83416D22 +561000,k,D66B388256E6E1DF63C7FB46C38360C19D04592ABD5478E2B3CBF3BFE745A125 +561000,u,D621FF9A30D4282BC7B2B0561B554AF21EA9CFACC56F4DEF84072728CC9DF53E +562000,k,A9E1E3C154C738BDBC891656719EF98EF8B1DCD83936C7370C8D068619C7A402 +562000,u,A5CB2C6F912291DFDD18365CF6E07A4BAF11527B7B8558818FA64734CFE2265D +563000,k,0079E70073305166571900019E76ABAF040BF1D2DC3EDEC0487CD846A5641726 +563000,u,9D0E08A7EC313FF8FE50F66C690430EB4BDA98C3F6BEF84A4230FCA7192C3F02 +564000,k,09BD653421BCE7D0B8F608F4CED00B2BE544D477DFA2F585CC87F81F2A7DEA12 +564000,u,95E250E0EBF4F04196E26C6BEB73A98163E7BC5E33B07FEF5294C89A38A4D538 +565000,k,B386D938A823B0459C520401248ED2B4540BBE4EF22FACB5C0F0229DAB6B5B21 +565000,u,474F353762BA22F4A855F909EDCF326D32E7B637E024E7B30F186812DAF7A85C +566000,k,15F4699416FD6387999D97511B89272AB0BC64D6723FC549746824C097D4C23E +566000,u,D8F06CACA6C671B8A3B72DC2E7744790759013C3227B84A2E6FBA6C95296F045 +567000,k,838273BC6F1A8F231319382911CDBF00B18C621AC7FA56B22BB0C5C9C9D0A10B +567000,u,0CAA9E530E4F2B1A2923F8057B81A28CC5B6973777A8FBCB42755B2942184F2E +568000,k,A32D9DE8B97241F7F8B9C233D72667568600EE1304B9E5377A30194D8005240A +568000,u,143507F51EADA650C376D53D44C1A0C1EC2E32C558FED0BA891D49ECDAFA7871 +569000,k,B846253AA1BFA6601E65C457015BB04AF7733D7B81E4181D6396A759422FF434 +569000,u,391CCB945011BCC03943EE5AEFBBF07726B73BF82C9D105B0E1E036A810B6410 +570000,k,7D0B442B4FAFA8894A7AD11E30EF85954827329285A01A57D639793EB716355F +570000,u,110DF9FB79844E78EBBD824D5715F37E689527D62A79D62EBF71F085603DFE16 +571000,k,700EC77742E32AE1512507B094FF1926FCABF0C77F79A54AC47C0774BDDCFE37 +571000,u,3A7881DE565DCB280BB04D56EBDA6CD164B28F75BEF82A6D66FBBC3101EB575B +572000,k,7F387F3B8AC58B2AFE702AB64B0A5E677377287D0F7FB981C9AC5A4B833D8269 +572000,u,A3BB957DBAE86BBA14BC2545D6CB13682F101C2D41027D498ABB1D0A466BBF4E +573000,k,9EBF556EA323F2ABE7F8685D970340E464491C0AEE91A7D5069EF3A0B6338539 +573000,u,AA6487C8CEB44408461C0A2BFD37EFCD09BBB419D2C82ED2F05EA0F7A505F32C +574000,k,6D62E00C3F1D2019ED5CD3BE8410C6B1F5F8A14DAF993A78152D1E4C03A3B577 +574000,u,4BFB957812AEBC5E5302692CC8AE747117222BCA2257F9A1D0A14CF3A23D520D +575000,k,32D808E4C88EFDDB65948B6C7CF8086B17F9AE8B33AF63DEFDDFED6ACC373E18 +575000,u,81FAD986BE28F2DBB96D7C24FD71CFD266305C5C2C73382068FE2AAE4D96CA6F +576000,k,C9E7C174B463B119F031F933233A504EC74C421998E28DAFC8069B64CE9DE07D +576000,u,0D4B7B29091FDA81542EA089A747B3CB830437979D0685A77375A3F2743B7570 +577000,k,850B91FCCB806B9F73306A8D81E368B6F690C74C7D334ADA93A47C4CA3CB3249 +577000,u,92C762310CF929550DC2E6159A7FEF0C4744A7CA22218D85D20005C61C2CFA3E +578000,k,39CABA7D88E485AF7B411FF9F12FEC91738E372D7D6DBA453AF8A5C4EBA56961 +578000,u,0EDF16C55F30FDF3D438C9A1A49DA7F1E3679CF13917AB517446D5E396F1AC72 +579000,k,E012F44B8A109A4C28E5326E9C93B079E7FDD6091B8252CFB4CE49E6B309287D +579000,u,607D9B1427E708CB46123B5ABDEEEE5C41E27E7823B24DC8DBBF82405D658137 +580000,k,38DBEC6BA1248911ADB4C81D6B20ECD2663A3467E780BCB5971586C19C305213 +580000,u,C068597989DCE313B09DB2BE33A6A66B435E7E0E775AF0BD4D7E81913196B631 +581000,k,F8C3582E68362892158F387F5F2BFBFC22143AB9CC6C84B568AAF0355F216964 +581000,u,AC765257766605EB1A1232792109D0264B09E42DF7D3ECD5549B838F4B9A8230 +582000,k,99336C10D27817C590F6589B5F19FA33396955D345E2A45C417C41B3E281D86A +582000,u,04D5CCBE72AD0CAC506CFC9905474A5C9185B30AD40263F7F59A3F436393627E +583000,k,C6624DA378382CBA6147CEC8935DD9BA5D5EFF9C4C8470F0A8F830B967F01A2B +583000,u,F387CB110024F310DAAF1472142E831836C6862C8E4BBAF2D0AF341C96FB2E27 +584000,k,5FC44EF7D44020A40CD67B353AD8252DFF790DB3B984560D135FD3B791518E38 +584000,u,A4CE6B0A6A2A9CC5EF84EC242485EB848520F9212C7FE01DDFC7E789DB596369 +585000,k,A3E2E48076C57B1FAFC93E281E3955609F972956EA9083DD2CC8725E31023B4B +585000,u,1045141D0F8F63B70DF1AD00BCA1154CD720F0306894CBD435139D881D2F2F39 +586000,k,573B923B41F74343BD1069104796511EE580D976A743B47A0C66C4F626F5F316 +586000,u,B2E10FA60F97D732C7D01C8E1B0C3433F6126174B8C0F73DDA9F685B600F3E73 +587000,k,D56C60CC9646A4899888A6B17EE0687DB18993E27C5A8BD3F50914055F7F2E21 +587000,u,034B0A06187854BF59E9AF061D9BF256934F6D13B2C7633E2314EB7F58C80262 +588000,k,34DD55CCFA56B5B7C2337E72EE49277B676E6F98F38EAB911DE1985128E11053 +588000,u,C08CABB5B5712A41E052E460B17DB5E7D8C6185FFD4997E90DD70AA29AC3A46D +589000,k,725C3371EA1EBA50CC44D2CB1EA1E35DD164035F31EBA8AB850C44470C6E1042 +589000,u,74F252967C1DC7DC8F893591E39E8C6EE26BFB351E074B8B01B5DA6EF2BD482C +590000,k,2B39673E2F66E26EDE71E25C30F10F35D066E017134E7D1284C4BEAF4DA12B4C +590000,u,78D11B4C0227B174B275801A215943A829683FC3F0EDFD5D5AE92C9AE7B44950 +591000,k,3DA8D00565B9BF728AD3B4F770BB0B9EDC0154C16B9C7E01267C9CA2E2281877 +591000,u,D8C2B12750BB9AD491F86F23CAD55396178FAA820ABB0605DC7357ABEC2A2877 +592000,k,E80F850E2775F4D6704975A065CFBC9366AC6E3DDDBAE64F965CBAEDD5E1B97A +592000,u,2C45973EB71DF310CA009AE20EAF1B07DF81E0993760C5F51ECEDA17C8C32632 +593000,k,F130CA219CE77488C528C98F1092E642B2A7170833E3A131826E141316B41210 +593000,u,26F37E44196C98B1E6AD349B66BE9B05A3CD3316A3526E68AE8CE214F73CD920 +594000,k,C4D85E6A7CBF1F38D132A9E5C2E5391FB6B594EB283AE52D8AB169857F660C2B +594000,u,EB98E6C28AE6ED1AAD64F28FF9CA5A40D75F1084A6C807BBA1BC911FF1CEB43B +595000,k,023F87A5E3E2C054D92F6E98FABFCBDBE2CBA093DF1FA89031CCACE92731E931 +595000,u,5D6D817AE7C65C5166317CBA659F1365A4D297892EB07FD46C1EB4D9A90A7B1C +596000,k,200F51ED56CA61FB8B3AD9FAE07FE6043FC16E6696EB849D4ABDD84D8E8D905E +596000,u,4DA74A2C91EE88B37AF7E433F3AC568A9CA2C3435AE0F15F917115FE8CA83659 +597000,k,5CF80EBD4301785D163E8EA3B69721F6A58C0386708C1A76378CDD5FCC91675D +597000,u,622B40416552BA8A6655DA19D2EB0779F7670006AC9A78E2B9B773467BDF0E3D +598000,k,39E2BE6B194E520456C2D58EA72302B3DF730D34E8C93E86774DA331AEDFF059 +598000,u,0FB2EA9FD22F34B92E28A894444757C984EEE565D0D2FEB6BE0B84FC1035984D +599000,k,8612E349B09C3B84ABFF09F29E5BAA3461C38740027F682465AE63DB8DAA4303 +599000,u,EB5815347EB3714AE89AD12DAD24214FCBC6D32C433C9E2AAC01A3D89257387F +600000,k,93796B663F1034AB975DA7BD025AF25367FE3A57874E746BC91239D842F56A2A +600000,u,A3116C53C4B1774DB95798A929D2C8411321C0CEAC11C30BDB02ACF485892258 +601000,k,32A68AF2E4FED47C0DE539234F8DE80F0EFD325C885F8F7230FD0817A522AE44 +601000,u,76909D9CB7A673A49B955428F56CFE558FBFFE73EEC34CB4C133F04C309EB419 +602000,k,ECAC668491C6CF3701B998BB16A1754358EFBD7A9B916C7DA3F5A0B5339D0563 +602000,u,F93F4F5BE3557905B95886ED3795BC8B1F63890AF099EBF009A5BE4930D2BF7D +603000,k,0D325AF0DA797F1D7E31649CBD27B087DFA1383E8966F777DE0C952B3A52966C +603000,u,30976E4BBAC642158A13E72A0DFFBBA4A83FCF2BD955F04BF2CD85DAA30F9B75 +604000,k,887753C94930D4E760AE3A245D145F0534891B196AB4BC74BA7049813F4A5A5D +604000,u,5E81AB9B881243A84198C583643F5061A467485826DBD24015506968419D7756 +605000,k,3530026A386A2CE2287DE0211E26E1239826943F97C354F3C896ECF73F33E778 +605000,u,CFC50208774489134A81A26F51E33E82919384775CEDAC215DBF35B416D3490A +606000,k,3A03859649665CB2EB43A739C70935632D4117C9F19E05EAE814B97DF35BFB24 +606000,u,3191897F00201A88C10E350084D835B4DCBB1200101F1D2096431C47467F2753 +607000,k,F586700488912B7DE7EBA33A7242DD2AE99F79BD6F2B8D40F6E47BBAB7DAEE67 +607000,u,4378CE37A62916E29A5A3100EE95C4308D2A6B6ABA387B3E0F8E08A50CE1A904 +608000,k,16283AE234B155906EB3F27653F057604D279C87C949D8AFB31FA78FF7201A06 +608000,u,4000D027BA04E8A0DCD398D89684D63BD48476A3ACB66138FEF798E756C74951 +609000,k,5EC245FB13D33DC174A11254FD146C8F7139126E02AD6FA991E07BF4DA4A7358 +609000,u,3436BC85C7383E31F2BA6CD0030BB77B89975264F467E45DB3C4ADA5A8722826 +610000,k,708F60CC3AE0949437DAC5E342FD05F333CEC986AE0EC5C730BB35318FBDE07E +610000,u,467B0EA49CFFE0DD4B20963A1FA613D51882CEB3E9F886F36E53C36F414DE775 +611000,k,13121ECD2338E79E3AF76B381C01C0263DB75B0D802EB2A2064666C97E65FE1E +611000,u,56971C2FB666519951D3BDF1415978153E52CE16375BCFAFBC692E050F63890A +612000,k,7B4F191761B2765E7699C0F53110177C4D922FCF1ACB365E4EB15C0A36042A4D +612000,u,89DEE44E4BD81C78847B0B7212E5973A72F6856AE61BBE96206B48BEEB7BEE02 +613000,k,884E2948C0BCF94D4707B0249D0D018208037933BE418FC8C5F2B77F8CBE794C +613000,u,4201F080D24AF802A2F4BB50105C0B0BE6D945F3853328AD878FCF5F5B9B205B +614000,k,327CB1FFCFC905566A925CF04D89A6AD981B954DFB2A209318D2B0EF52A0B672 +614000,u,175E7720251A14E3E88545937E42327416FB10B6B68C582CF50788B5F6653009 +615000,k,27ED14F737FDDE0D5E49F7757DC96A70828BF0C862B21B42E2158C51C233FD21 +615000,u,BDD0108BC2053E1ABA1CDE0EEDBC05388DD20C05BFCE76F51FC4CFB2FE618543 +616000,k,BA0CF3AB41E0820D24D8C8D19EA52D4976176F5AD1EE956736380D05A1470B5A +616000,u,4C1AB8BBC59A8E40C9EB64DAFDD4BF5FC007EEB3863EBE71A3FE454E9BA24157 +617000,k,7293131BBF13A076C0C1DC0BC3DB0ABBCAA48A52C0C2F0BCBA82C78A305D2879 +617000,u,D8CE01A797EC83FD34D11B54E4D1D14652CF8D3F34EC8F3E21C780DA655D9230 +618000,k,1528ED0302B84157C121211080983FAD405D2DF5DCED47D9A3F9E8BE32FDCE2F +618000,u,6D7A80122966B7B805AE12E63834967DDD77A84BE583245F9EA2A58F5F0C9D4D +619000,k,FF50C3362AADE9A5478AA7F01C4FEE7CB942C9BB4CA9F0528CF90FBBC1549813 +619000,u,1A6CD31B2F7D2539003F9F9A9A00A4D00FF2BF8B480BA364695E741C930B4F0D +620000,k,EAB6F7C69305C86BA9F569DFA7B7005BFF3F399BE6CCA607E1F8E3388F01EE1D +620000,u,529E0944FBA44AF980D523E2E1CCA54DCB0EBB1B0B3FCE823A45D19AEFCCA31C +621000,k,DD3464B0A0AE2C55E3D11A9D4B29AC2844069B45C3DAF176103FCA6B8C500B00 +621000,u,97F7BCFB394D403E037A99BC574CE7E52B91B46A9BA3387139770A93B035477A +622000,k,57D610D42EF0CBAD89A81B5AD9EFCA8A0D56BFD8B3993CD08E22234154A30F76 +622000,u,61F972C99B3BEDB26651ADF74B9ED0CA36031DA76259229DC0DF72EA80386A1E +623000,k,F3A9F6C2212BFECDDA39232E9C5B9A76CF0BB73ABF2F733AC8ECAD00AC0EA45A +623000,u,3B5E93A7AF7C937E8369AE8C796B810934323DBE1007E097B734743B3636E178 +624000,k,7848D6D515AA265B343E0BB001A5E53503FAE9B11ACB0803C4768FDA3828884F +624000,u,F516C7FCB2C216A87F8BA8ADD5DF37F1E9FD22B994CAA4FC5101091E2C2B0D42 +625000,k,182B4DB208E3E2E27C82F13EB0EA8C6B5FA2F6A7AF1612DF7E66F13595BC2425 +625000,u,2B9BC74C282DDCA379D4CDC8B9921990F0A29A80585721DCFE4A248CF28C9E26 +626000,k,23E85A989B12FBBA69AB81F90E999891347A2657B4021DE41A84B3B30DE2CA43 +626000,u,75310DB38CBE060678976E0A36EB72330C9FA58786E406DD574CAEC70879CA2C +627000,k,EB3E24A01271C72B59A2318B4224BF43EE3FB9BA1C93023CED1915449AD2F240 +627000,u,EC2C72A3C9F4648C005137D52C0270F0AC99F6610C7E5B775DCDA2EDF31F9F3F +628000,k,B170008FB7FF0B37F27CFDF7DA99111178C0E9E10EFBB639194878462AC39A07 +628000,u,1411212EB2F631FB33B7D732CA34B753ED4F73FD2A3243B76C05CB397E710B2E +629000,k,ABF1A16CEAA2BC9A120C93C0A71BE634DE76C66DAFB5808827EE13D78DCD122D +629000,u,AA4AC4F37E7D8BC2684EA5F1D609266BC1C4B82DCE9477F756CF5FE1451F0F1B +630000,k,7F6ACE8223152CA7B8ABC865F3CECCFAB85BADBCAA07B11165101395094B7813 +630000,u,75B62823ECBB259812E83551FDF12F0B88B25DA871F35A324B1F8E5F24BED11D +631000,k,AE8818E0781E5C38817731D4D983DFA43C552456D4597DA6BC6058C66B842150 +631000,u,EE7E03215F5C0963E10FEE3C823F33AF00A7BE3755235A1BC3E36EDF28CF974A +632000,k,CE55BBFA816AEFF3F5EBEC602DCA86AFA14DC2F3CE16548F0852DA1DF586DA4B +632000,u,2CD33C677D7B9FF699FBEABEF2039AB7500DA6BED8CCE180AD78E9C01DFAED32 +633000,k,AA02E4BA19BC34F63060A50D4F1D2FCDB5BCDC883CFDF9F24AA434B8FD234F7C +633000,u,4A71AD6D12384EEC152F4956C2DB08BA55230409D879685DA7902C4D2DA59E2F +634000,k,D1222906353362491599B05843F2DBB19A3C4FE371501A50161F087D3AEFEE01 +634000,u,FAA4547C55DE2FB1652AFC7DB56509D11F1ED0D3FA713BFB75099E3173B2F24E +635000,k,54992D2F344133C77CF1614E5E3780DF7C0727FB343A2B520669E45ED4D4DE4A +635000,u,2DBD250A210B3C9700ED36674FC3D02C62967DF8711BCDA42B926A8465C90E75 +636000,k,7E8A1B7AA2DFD893131CDAEBF343354B55A705F69C51C2BCDB6F936690617D5E +636000,u,976B9A4CBEFD403F13E372E93B379A1877A4CF882B9C525A72ECE25878979D0A +637000,k,FF56B4B2458FBCE91F506E46A9C6360822E6F49F4BEEF8BC33A1436EAD4EE066 +637000,u,C05367436B9D71910C68F96F91C008AA72A46A10CEFAF20E6F3567664959F473 +638000,k,9CB46039F26B90F72F54B2ED85DCEF0AB50913131F992AE272B173313B1E826C +638000,u,ACA7BCAF4E9A8904C577A466874E12347C36AFCB0C84A05E5645C0CC8F1F4B44 +639000,k,A422BBA3E8DACBA146ACB0A88A7A5119BD9A60507776392D758B3F0DCB65391E +639000,u,122BBF3CDE4001D61C0515C65953E8B8444F5A968BAB3997225203D5B066AF5F +640000,k,01EA7F58240F313B6A339B9A063420332CBC4A6D064A87ADB920C601615AF11E +640000,u,A88632DDFF0A81B3C8BE68A368E620F2046970419305C1F48FDAB5F2CAF4931D +641000,k,6DAC0F0996220F3C9B3E9741F8C2DE6FA6FC49CC26D4D0B90A291B1682877020 +641000,u,BCC36EBB45B813FA0D2B5DDDE6A0E739D24A00872E6FC23E4E147B02BAC1CD01 +642000,k,022F167AAA86F1BBAF74186E1431F1504ED0DB577AFF5AD05C5413CCF3F73347 +642000,u,669845279B3CD5141ECA6AF36F8A75B699ECB611FB6F05260DDBCB9A36A4D76A +643000,k,BB5B7ED332F09542A91594321F087C5FEA62011180351F8979CE467A530DE45F +643000,u,E86966A18F1C6A6E46CF091CDB4E29ED137350A9A4CC819184B0A1AAA1F2B943 +644000,k,F2360F9AA8BE553ABB088FD192489543E150989AC7990214116D8824ECD3494D +644000,u,821A21DFF3CD805B3D469640BBB047480908B7FF197F8C283F68D628DE49EA50 +645000,k,E6B2DCC6696CA20FF5566433E100FCC562B582F752D9F5E53BFCFC2BFF0CAF1C +645000,u,6E83BCF47BC8A66CD3A51781DB15C95F652BF2982052DA97CE179D611F059946 +646000,k,85336C6A34E8F33931DB52A1349D1B894AEF91C403C591C60D7ABE4D06F19956 +646000,u,BDE3FA6E433B11A58A097B11FC08862B2D2DF0AB08890BA93CFF65D9E6A6CF67 +647000,k,022604AEBAC5C0C5680F81D8A0DEFD5CC59299C928E249CEF4388A949492322D +647000,u,D6432871E498741F48DACE3BA4C6A5305983FC1E63F19CB7AE3552B4008D045A +648000,k,0EFB79BC23865ACC05256AF03C9337873750712A4E94279B516D54793461BB39 +648000,u,CB066AF559670731AD98D0163FDCF9F67F21AF04335061B913F5658BE7D7533C +649000,k,94B9BCE6C9E81298E70E271547F213091DCB9E24EC0A0F7CF9C042F3FDC96B5D +649000,u,A5170A641C410FA13BD52CCF4AF3841EF0CA2A47D0CDFD276495A4CB6F5D9B7B +650000,k,D24BABBBEC464E030D06FA1CF7BC7DBB1B7E1A9E8F81C1424AA8A3D08F88FC60 +650000,u,F62EF3B2332AE75BEB22E4798BB3F75D55C2A09DDF7816C34D5FFF8E5053B743 +651000,k,90FE1057B9080872BA2EB9B4D66A4BAA80EBF34B3E82157E7F87C56B843FF02A +651000,u,3AAA5CFC7253DC0D7A9832BAFCF50E62B9E522602EFD55A15059ED7D0B235871 +652000,k,FF3A5CD390BE0DAF3E693175E1E6EE4E3F0DB4AB5195D683ABBF54E26646923C +652000,u,FDC32B25964BD996C1DB7A667099C144F635B0B8546D316851F1588E23972E19 +653000,k,06E5260CE89284A6F5F0CE9972ED51C9D21311BECAC314D477884D56C6B53018 +653000,u,EDAB5CE167A90CCD3DC6F930C6D58E1DE5D7D23B3E7BDF040A4D4505C4FD7C33 +654000,k,1241B56A5B182C46914BCBB5A1328B04C4BE8E5387D361A805C074E2E408461E +654000,u,CBAA1326C566A0320ABBA916DB52FD161E4FA1AE7C0FD7371D0D36BF6423804D +655000,k,4D0C0E75FDE222C0672E9AAB01DFBE5D222AC600F74DC534447636817090091F +655000,u,176551FA34D45BA812D4375F808DD2605F46EE9ACCB398DE66F3ADBA357F0605 +656000,k,B13C48123AA0B0047F3DD5E00C97B26D1FDC5CEFABD995BE5D879AB8B5E88160 +656000,u,E8640A1094B7CF4EDC41C566F402563EB9DF9AE1FF6A32FA19C6CC1512D9A23E +657000,k,D389C355F174C961CFB922F6DA81B7B1AAF51AFF677A475719A1516B412D7C73 +657000,u,557EC3F45386D3AAD322BFBF623DD8C7105C0FEA3CC750342D49AB22512AD441 +658000,k,FA1672EC9E37DC01E9F1B92DF05C4BDDAB70053ECD98ECFBD262D0F2B04ED755 +658000,u,341EF8B59D86EA5915E70CE7CE3DD00954365D73B379B0B6782BBF2180F92E2B +659000,k,D75E634F59DE0CB6BFF1D2A1572A23592A6187B2F9C221D230D305B786EC3073 +659000,u,C6A399EEC4DCF0D3AE955FB305B2C6339503ECCE45A42255C13875213E314F13 +660000,k,FBD60EE8EA9516A2D0F00C4D690D6FD6DB284C186516DA7953CFD0F0FA8D8440 +660000,u,248E3ECB7663B7BD8B83F6E9A46A00DB28B09F35F4D68B3E3700612111825924 +661000,k,9A0939BDF4749FDEE9D852B3C21B82A54771B66CB2936FFE322300136CB37F0A +661000,u,D368FAECFCB92C1BD87E3EBA348FECF3C2E66C7F0DD1510C5F23CF2D26ABE205 +662000,k,2DF0014921D55BDFBE217CDCA3A6AEA90E3C1513673C0C02126B557928279710 +662000,u,DCAF69C097DC8D9636A6A64983E4B05DAD23683A62ACA45AC695488AF4EE4A4F +663000,k,05A51B80B190DBB34275D26145B54158371C182C78B370B87BD6FA2DD069853B +663000,u,C0EC52AF5932AF8E70D2266E3B74C097EC6588037429D9533988265F61FD054C +664000,k,F2D3CA647901E0EDE6C1E41F4C4D8C7736858DAF1493F89C140D81AEF032CA37 +664000,u,B02DB37EB9C9BC46257CD40B0C4F54CDD3CE89E2F8A8EB7FD0685083CCC64E6B +665000,k,71314082D2724DA3BED766820C18044D6E812887A306E30B3E124DE87A48695E +665000,u,8F38B12DC0F1F758C8306283C9503C86D95CD7023771D9A89E174D939CEDFA13 +666000,k,FAF3579510DF3010884BD04C2AA0A32431AD851A14443646680943B7104C770C +666000,u,079EC4F6B32570C93265B154A6C99E99146526A8A9D12F1F4DF3543D116BEB1D +667000,k,93A084140EAA138ED2CEFA058D64E1E465B1CBC9DC2472CBF99EF0BCABC52443 +667000,u,8D0CB8F770329E13E9C448977CAC0A6A728CC362EEE48FFC429C27F859A17828 +668000,k,39224CF53395F3FA82FA4599291C2D18E40FB6EB89CB7FE5FB3A33F4E3FE7D7E +668000,u,EBD0C799625EC6F737247742F1D7D59A9D6B5D9164B271AB3A3E4E0D941E1D30 +669000,k,C7ADC16922EB85C7D6369ECBC7796B6AAABE89CD36AD7BA9509458F47DB67760 +669000,u,6A40CADEA682F9F05EAE3E5CF33769FD61D29A91BFF2BD9E2ECC32415B30B929 +670000,k,8FA189832D83EEBBC69913045C72C7A77D756C9EE9C19C5E5D747342ECEBE432 +670000,u,6C91CB3EDEA3B3FD3EFFBA5EAF7DACEA2D40B133F107295AB262E74325D8D621 +671000,k,03004FD209350F2075F81E89F4CF6EA2998D30FB8B186ACD6233D80ADCBBF42D +671000,u,41BA9779E325125FD24BFBCCB0B19424936F441C79DA28BD58B19FB5FFBD5D70 +672000,k,338B1E9163A7773397A34D83BD6780FD6B6526FBF8F302A19B4DFAC04221A351 +672000,u,B46C563434593F84C5C9983B029FA7D1F130AE6F2BEF366FD984AD7B7540F722 +673000,k,821009610C850DDCCE6FF470B108C3A2351278961BD2406DEF7DB20C52CBF569 +673000,u,085D9A9C94162ADB19DE73DAE36BF7FC0E864D87ED2E1631CB6BB43C2461E449 +674000,k,7EDD4879C00E0ADFA0E54B624819512D04E9E4638A19FC73332B4F57A550BB3C +674000,u,369F6750123E9447AA5607F340719CDD17E42B6FD4F082254DF9C53BC517494E +675000,k,D34F88AE72FE4ECFC2A99A23BF0C140DCDEC95EF2C135C34291762BD4311FC05 +675000,u,79D83BE1947610EE5B07DA48CEDCE7DBF99ED528E8753D3C1C0C47B59E10533C +676000,k,E189520FDA9FA874716D56B92CF42C84223A48DF55EC2F33C443C6AC0CE18B47 +676000,u,E4974DBCDC773297E14626721A4CB9BC7BA1B149B37FB790CC0F05B968BFD365 +677000,k,FE83C5AE2B18C4F8F91F3A2732D395E740D5DAB7342AD95B372FCEFCCCAEAB73 +677000,u,92FA33E38D1A6DE7D7A455F6B7A1EABD02EEEAC1531DBE0E223141727F7F2338 +678000,k,8AA0ED2A64E2C5F8CB173680E6C6FC5AF985F7F52B1356DD53096E0F15A43E68 +678000,u,4D874718EB38B0C823F9D907663FA040341FA60BC951D849D0DE3E341BF23B6C +679000,k,B095B9108B57210F92BEB3D8094821245E39F115A24A5C894607D2F37F6A485F +679000,u,142EAA6CB52E3487BF92C3B89D6E6089B64F3D4B2CA2BAFFCFBC9C1E56A27E3D +680000,k,95757D57871A8D2286BAD17C6DC40A057667AF7D54146FA463CEF7ECFCBAD333 +680000,u,83B8D6CFA6550944657F80F898C4A0D1A003979A29847D6BE12AA54A8A56A92D +681000,k,5530A01E94488DD6977710EDB7006424020B6DF9C98DFE53428AA4CC06AC3E72 +681000,u,D3EDCE204B4E345C983DB65861EFBEEE8022ECFA88AA9BC30997FF6184EEE530 +682000,k,6016FAB38944208457DBE0CE863C72E9FFDF32D1D1DF5C2646A67C5D7AE47070 +682000,u,95F0B77520A939BCDFF3B435A9EB580602709C6E29A8E956C68955D4D83D4B0F +683000,k,163CDFEC29452463957DF40C5FB14771CFE3C6A743049BF50212003F1A9A1E0B +683000,u,F3C22BCBB83C4EE56A751CA2A4794576503902B2411AB011B374594C1FED010C +684000,k,CF683B56FD51B3E44757998ADFE9C1EFF4ABED020C382649A4FA268DE9109833 +684000,u,E1FE11AB96F7102FDE3B904B2FCED73D39C796C66BD4ED1BCBF8AE77DB6AD059 +685000,k,F2C84183FDA1833E8C2499E2812686A4F066CAAA9A21F66CBC61372097EE6F53 +685000,u,EC0BAC41DDDECF70AD1310471E55E6AA2BDF76DC3119F9C7144C0B41E9739241 +686000,k,3D1E62E9671EA75714266FD88D4A75D293BF69E92E96C6C0CAAD2EC3A13D6C33 +686000,u,D30EE7C5D88109EE124E0E8BC3D0BDA82994FEE745122B2518BC184DD154363F +687000,k,F8C3D9F4A39285585C782400B7AA22F332A4956C7C65900BA0BA445C2A0F4701 +687000,u,0EB2283A0148920141D9A8C6C179F5B90F5CA9623882974552C24E22A3BCE431 +688000,k,1E23A2B8113AC144724B41800129FF19CD485A3959FB4707D391B9E7B2F59D28 +688000,u,1D5950096824EDB7DD4ACD1E89184E523CCE4E20947CE1CBB8B2A71914656822 +689000,k,15D3B37A058CA69003A165E0DD6EBC760A1F982D0AEF272F324E1284D177B164 +689000,u,A81B02D9961245FE864BFFF2786E557FACAC528347CFD7BF34A14D27D8942B66 +690000,k,59DBFF3C577D5EFFB60E55E794FAA8DBF32A56F7BC22A5BDE955B9B6929DC253 +690000,u,09892C3EF5F81174901BB9BF284DFC81DF5BCB5002896CCD5B1D8B8D12134B5C +691000,k,CB49B30390E242AD8B42B6B7A221099B83FA891130C8102BADE823C69CDC2D5A +691000,u,FF0A68E3B255934C7C91421F8D2A7280863A3B8504139B84C009B5A7A872D25C +692000,k,5AAB5BE1AEC08961174AD434DF5D7C6C97DE0BB5ECB56DA8024590A38AFF7E46 +692000,u,ADC50A19C83F270DBD5F44CF87644EF2687242DD3725B55F45A7FF8F451A591E +693000,k,FADE2EAECB95C716BE3E677DC5B615A1E05B07F6DD8CC0BCFBA42CC3E54FBA1C +693000,u,201E836B71761956400217AC280EEED48F58CFF8A03F602F5799228C070F504C +694000,k,DCF733E049F05172D390CBEACAF3BA86593A425B7CBA70303859D7F4E84AFD4C +694000,u,2E4543EAD86A82069528E1E7EB473FF5D36F0C92CC65DF38AE55A38530DA3841 +695000,k,BAA2C8A00476C4EFF656629113132A26C819811FC6FBCD837145762E70C9EC17 +695000,u,BF7A96346A37F5B409CBB5AE900CFEF11C784D4394B62ACF2C243711F5A68D75 +696000,k,3BD5C25C51E5BDB8C05A6EF6321A60AF720302F118F417DBEE7DDF3EC80A352A +696000,u,C36DF80930D8C46E0AC51ABC82392DF0460F39AADDDD515FD036CD5A4B6CE816 +697000,k,4A8138ECD218131C17AFA344241F17493E956F1252DAAD30D9679F0CAEEE430B +697000,u,E2E52687295DA9C35698C9884CBCB65C296D754B9517751A09983FCD7F851916 +698000,k,63253F8242CF62B6EF81CD8AE37320808BDAB03B7AE86489516FDCBD92A9D367 +698000,u,A1260F2DC5A3B0E0A0023DE4D4A6D78F0041260CF345960DD11FB23B30D22E3A +699000,k,D295D012B3389798EA029B8A542B3DC64510BF31F0FB7921347FF7CB2029AF1C +699000,u,1725724B96195EB83617C83D5E0E5FEDFFCFE58DC5588D22458D64923B45653B +700000,k,937E2EC1AC8166024DF9A474A52337CB23F9BE7B42AE313E3AE350D58FCC7500 +700000,u,2E1FA477658654B45EE8CA5F93A466E0B03C814053820F73BDE96A1A381E3444 +701000,k,364A362BDA2A3FA5DE7B726FEF07F9025FEE56918D46FE9004FDB8A9F934193F +701000,u,4D43AF2CB49CFBC0B3E3B42A4E56A9FB131645F3552D87D0EABECD249CBC206D +702000,k,B0C6592687416584A181167322352A3C02B3CA410BCED11EF2D5378B68B8940F +702000,u,1E431265443A50460F366834BED34B58381DD2AB55F2274B18350CC65AE2C813 +703000,k,70412FC3BC749D06C9BF1E3505679BFD7D011E6F2440F2BA7880E318A0102542 +703000,u,735D457A27E31A71747B2E447183ACA3872F529B57E44B000760C3A138F78178 +704000,k,10D9559832380EF41FDBCE0B78B25A229B782EE603DD211522D237234CFBAC34 +704000,u,D7FEA8C8BEB62C746FB6430CB1B5ADE2C99409E88C1860C2FF45DA31DBF9F438 +705000,k,6C700C3A4C0D6D35224DEB78732076EED7967BC8220E168CC856D3BD4F41A761 +705000,u,693C5AB4F2A4D6F2D951041ECB1CBF58BA8EDE66058922CF839BDE9413373E28 +706000,k,FE257B5459E247F9FF7C497BF97DA7120FFF33462280CB1FBE9F0087B035B675 +706000,u,0C6B2335F2F5E5E95EFDC392C30657BCD7B9C6AC857C541E5895890909253D47 +707000,k,ABA5CD74E01973A5595517EBCD46C01DA5990112DF96EA319DA59EB43C86FD1E +707000,u,2C10A944CE7D0B14B2588D9F6D39EB9A0FCC24039384C281B6728484A34DDE42 +708000,k,1508E68B873F58B795C94704667E416E9097C890CE61F7E107E835F21ACD5B6B +708000,u,EDCBA3599966C151264F5E787F6D5846B1243D0E1FD89B2074D106FECB510F07 +709000,k,4210BB822FB71DA9F5EE54ABFE919BADC956BB5BCB0D1FFEE03F3255E7BE123D +709000,u,135E057BA8F34A02D17CE0B93527C30D94B0933BA29AFEE2FC26B8550655EE59 +710000,k,F507FBC3D6B5427E778C2D31B2B24CB7952EF4FD5F6C346EFFE72D5B4A019631 +710000,u,2B8099CA703C0974D7F5CC1F9F954A7A6484CDB0BA03A4DE5C63C8F13DB8E739 +711000,k,125F0D109653B2269F3B3FAD9E43CE4E37607DEACE8FB97FA73D9C6FD2C4F76F +711000,u,EBFAFC21032392D5E2BA215B7B7EE8C5D09F315D8AF94696997F37CC9A2CF66A +712000,k,A9A8B259193B4558483A547085E5F81A87DE1531B4357A4CD4B08F5DFBB8D139 +712000,u,F68D9893ACFA46D940A54F1E6A2AC752A752B5C96960089A18F6D5AA7C251D34 +713000,k,6A01645A9776172C130BB13832D82B90141302E07D865D69F23103368332A10D +713000,u,34E464E05DD05CDD3E0518142BEA8E310AFB3062B8EEE18861E3CF5CA8F96035 +714000,k,B9B5C91E6C6CF9553B01BCB9D7BD80E41B7B5E13C09BA3AC9DE38A26B2041A68 +714000,u,4F51F9029707526C63AFB473EEFF7358ADD8702B542E8E416D0106C4DFA1F42F +715000,k,6630C8C630CA6168EAE46C0B9D6C20B5522DDC4CE4985BCE608E05D89D68203C +715000,u,D2F51212AC20358DC8E75988A1A0E87DFE6BB6AF9E20CC7E59CE4B7041014D58 +716000,k,931BB668BE40D6062686C3559E915D22D7BA1C9E576E72E9B7B374C9D26C0A45 +716000,u,DA8FB1AEA8D7339803F87A654C90D38137E77587C1B6C4585C57BFB9D5423E38 +717000,k,B3E351AD6CCBF9769E1483E92AB72F9F7DE096F9F6E4A3BD07C5B44EE5CC612C +717000,u,72043356722BC22213E0F805017B4AF4E92EDBCDAAB1800F9DD6A8A2C7ABD82F +718000,k,875C41272D982505EFF0EA8B7A3562904BA4BD4F8AC45E4DF76BB185DB26DD46 +718000,u,67D0F3E10273B2B90AC087712C847A4C2E60D034307BA65AEAF896E4A631BC2F +719000,k,46B02EB33FB12164945F825A9B10100BDAC209A36C9865228B6FF7244CABB73C +719000,u,61ED2264951EB99ED630227079D9D99A63B216087CCD7679597FA9DF613EBE6F +720000,k,27E97DECEFB6936A510A5747DF45FE1CCBC276761BA6E571B3F7325D17AB0C6E +720000,u,36B6A482008F74A13E214E2BEB29FD7E184B13591773135DF756821A77E7A151 +721000,k,BB7EE54730DBE70DFEE272C4E25D72FDC822C4FC771AA4413E08F8D018E47C16 +721000,u,2F09E9EDA72055F960582B85462A9EEA9E6DF9F4220E2C1DAA98F5B8538AF654 +722000,k,A10E91FC04AC32C3E763381D0B9491CD7E2E14D03A8EA2563D28A6D068273622 +722000,u,643E90A70978C8EF8E9F39AF174E30B3BEB8C4456DE3DC3B89DFD3D880D98D52 +723000,k,FFCC4007BCDC2D80DF630A7D490A317CD089EF0D1CA50CDCA7A8A3E1C418BC44 +723000,u,223293A90916FC42AD1A1085BC6C267AE7F46F871A12883C3997C969E41EC907 +724000,k,42761E50221F0C2CA757E66368013E6D8FFB450281BC4225820AF45FC9870408 +724000,u,B651964784281B1D0BB71347C40066DDE9BE47A0DC03F0E299D02C9581AE6D19 +725000,k,65711B58B4B268F4D82F13DCF3DEF25A2D7A449C1A52A55B348FA26DDC3DC556 +725000,u,E4939EF942818CAB0D82D2FA0CB490272A4AD8EF2AB3D6D6EFE6FD19D35BB608 +726000,k,6B0D7F8F133D2AFF688ABF196C50891C21446D5C58FA84FDD8C550C0BD201738 +726000,u,9D15924949EB120193C4955BE0632F38BB00A80AB6814339AC25A5477A882F6C +727000,k,7CE3A8DB31501E1E67B5307D1ECA8CCDEBC9734E041B5E0C79947E1041C3AA66 +727000,u,25FF72CEEE428EAED85CEA1D0D57CC56ED1732CEE337A66B327235CDE4578F5A +728000,k,22509B0F1F240207DD3560DB2B05E5B2DB4C8B1A17F7ACA75ACF7147331D843C +728000,u,9AB290C035EE25B5AE83DC23EF01B66FB4FFF994248403DD4CE3D5E5080C352F +729000,k,5C64A4DC5F4F590E6766CCFD198EA68C7DC8175FFE9151AC7ADE06F1A7D75F36 +729000,u,90A8ECF67D907DD4BE1CBE4ED63E7653FA1C14664A87E75A94EDC8F9752E2E3C +730000,k,3D9E443D1A5CA72F5A91CEEEC7F5FD84C4171E881F52DD698E1BDA8DCED2205B +730000,u,6BA7B8E93325AFA9F88628F737718FB474175BECDA702C0F52A5C217F3C11D35 +731000,k,AC01F8A71150F8735436EB410C487D57B630303E1EA6D387D47F7A78B70F720E +731000,u,354E468AD7E8A443E952D05B97024243A718AE232EE481C52CBD597F50948112 +732000,k,6AA6F6D50125D1C08B6C21E376BD69FB64446DD7EB2AB2C2D0229AADCE74F32E +732000,u,F3366FE32281EEB7ABC48CD1B59E7D18ADF6EE93FB69C1F2C15C5B09B55CBE18 +733000,k,77A4A595846777971B41D4CE5F80F00C60A46C5ADADC588145836B4BDBB48672 +733000,u,5AA99F83B8543779A31628E595980F564D6ADE268631F37B60B5FDF5106D1566 +734000,k,CAC90B3CA6D5206366C24CEFBFFEE151B3579EFED4E3BE454780BF553E896B3B +734000,u,E664C54FC9DA63801EAF91F4D854F2D7423F3EBBA5E745A3D44157404B17C820 +735000,k,3360883F89D799506CCE6295DD9565D80F6A12ABA9722E84608C0A309F3C4C36 +735000,u,E9C1A8B7DEC6F9E07FBC74172A186F1C9C3FCB21D7885EF5FAA2C2CC838D8008 +736000,k,33FA162B99BE3F435EC8641B2A5E0E95C7EE3A4009D5C8024EEBF73708941834 +736000,u,3B303329431CF594ED6156E902E0EB196EF73EE546BF63DF8639E32E7DFCF820 +737000,k,8B071F40C4EFEEE3671F6BABC263B7CF166D0463570EE6C5356A79F44DEF5E1C +737000,u,7BC85A8A23DF0895FD4CEBFC3882AEAF3B89F103525369613BFDE3A454FBCB64 +738000,k,90040BE8DE246F834C7F919E05F86025295B94137C5EC02697E87B92AD31613F +738000,u,A057D103F5DDE0873BECFCFAF588538924D33623064790225D8D53F395016236 +739000,k,5D1C47816DC4866600439167414DF7FAE11ED489C53E3CAAB1BA673DB67D0032 +739000,u,9D2CD9B454B0D5897808B827E33403983CF6DE0C4EB9F2DEE4783DDDC3F63274 +740000,k,4E58DEE8605EBB8B96A9DF3010AA68A2A5D4A6005ECDA42E2C7224943DE08B6B +740000,u,8CB9095DC3AACA8E264221AEB8B834A9D801E31992AFC620D5477EC7CB197908 +741000,k,55A591A0DD1F4FA5DA74555D646512D0ACC77B7E22ED2531ECDF605A449D6A6D +741000,u,88DC6A281969B2D36AC468A6DA4D3CF40DB1339A3F22D19A23545ACDDE69905E +742000,k,1F8671B53E3D95A1E8C7BE8326702EC483309668926D3469DE474AF7CE40EA6A +742000,u,E96C4AEC2BCF84EFD5C70BF637BCDC819F711297A4BA65E67DC2C192967B802A +743000,k,6A3CE60496E96B1D159A635F7741FFA8592F7937B750FD1FA5965D032DC69A2A +743000,u,2EA5B8CFCA4569FE96E8BC365AAF4F83BB7734B36721786DFE6AC78D80CA6629 +744000,k,A05508ACBB56F39066E5CA096CB37F6065C80786AC8AE80A4A77D3416614D406 +744000,u,33BF79A0E7AC3CB9B1771A0F5FF65C6B030C5072154450D25A02302FFAB1B712 +745000,k,D27D811A57F8F3DD2E1C0127846F19B5F266118958C58150AB9C5C012CB77840 +745000,u,C51429C5F6EF908A69FE495F003B050F5736E169F166F84BF92899BDE9DB560F +746000,k,FB9C8F2AF1FBC504C840ACD1A54161BF40C1FC0801AB0F1090A899DF2C68E033 +746000,u,59C43A2B86946F00B6CBED63FE0E59E4801A1587A3AC2382F2F37D9FB8F6D463 +747000,k,7DC55E0A1743515E2AE2DEC36D635F300B3C54CA2E2FF58C16CA636AC2C07455 +747000,u,A687016DA311D54713706FDF950CD64BE0DE2ACA576C020B1904A5A0E3B89B50 +748000,k,028FED2B81F2CEEE0F89F502151B9C2B7F27CE06265DD161D7AF4B75CAC21175 +748000,u,6EFD692B441FEB5C0177236488462A449E175F44A4290EE1277A69DB52C3D60F +749000,k,49307449B36DB9D11BDFEC6F6B9C35849BE8AC88B587D837D10A60E9F9920E1E +749000,u,AE872C220A428838083E86FABAC094869D9D8D78F9D802A16E30AC4A0579E703 +750000,k,AB10496F084FACBAAA7297B198B6E8B8B6638BBFA4FF031BF6C6A8C12057B91B +750000,u,82CB8468AC1925C145A4B61BF54FC1939CE62044DC0B9C50DE901268AB90B134 +751000,k,CC27D47F53B65AA3DF98602DE0FD48503DE8B3F739FD592A5DEE857E00528576 +751000,u,948E5055A96CD4817587CA130ADE720DEF5C4C1A5CACD51CB12F98BC9CEBB709 +752000,k,A03F531B47D47C1E17C7CD176FAD6C9672B54186ACD4A7BAE582E8079C207345 +752000,u,92BD91F1F744E6397059CB153393F6DEFDCB432725BC6C0354DC0323879A347C +753000,k,6083FA646EB11BE4F507003C415BE26DFE8A98236EF78CA3026E8B743964E56C +753000,u,B9912D0FAD578E3F22883758A427A548BBC2596B300D2702D8BC2DD44FA91F1D +754000,k,C899238974FD41D210657266050427535EAE56DC30EE6ECF25FC2B75F1D1DD1C +754000,u,056AC1E730E86914C6B8E34FE9B889D5039BAAFA2EB9FC77AF32621330CDC904 +755000,k,70ACB789495F46A535452FF68D65B9B9ACF19906223D78679BB9875E7C2EFB5A +755000,u,4003839492C5569F09225B8EA9607DE0711CE5C678BF6730F8B9A8030567EA2A +756000,k,41990E9CD618A365681728C099CF4D2187E619860FAB8B67F35E3A351DB57529 +756000,u,937309D32D60B38EE333A02EE89470A934A050BFFDCE7EB5C94E83F0898F824C +757000,k,011AC27F69EC5974348CC1DB00A46064A25B4CCC37BFF41B14FBA9483CF58253 +757000,u,BD3FD13A56DA58975E9CD6801186BB3B118E681D9BF4AEEC8C065F4DEC82BF5F +758000,k,D68A8B2EA010E0DBE662E61FE8094A7E1B892B9ED046115071716E23D747BE61 +758000,u,E34340A599D6F25C0DCB03AD7EA0F168738B286ADCB6F8AB0D7A0DCEFB5D4916 +759000,k,601ACCA85E834F917A25DD349E25CC2355F0E8072C173C9DB9DD7E18387FB75F +759000,u,83C8AD59E7D3D0C87DACAE040A0B5DB98B17B73D06FBBA6D8FAAA85E61E45908 +760000,k,315EBAF59723D5C9EC4EE5FFAE1441C2ECFFC835D127F6CAF36AE4DF36180A26 +760000,u,2704B275E6A8A155AB277814664160E8A8FAD42325991F62D8417B7F7B57E746 +761000,k,DFEA7659F0BB1527ED622762AFCDEBE8C4C87B6A21E69964457F2A4FF47C9235 +761000,u,18926F76443D74BE416FDC5B565BAA1FB79CC4E233304478EE33C90C0C1B6953 +762000,k,BA65596B1EFEEBB7F8A443843A8C7F90003F74358238848458A59C11CE19AE11 +762000,u,A8C9E68D0EC43453818E84664D2ECC988D584B92C317688FC63B5C6F5C733425 +763000,k,A92DCACB48442FEB07F3B21998E52C447666830D013DEDD11AA0DFEAF75A9410 +763000,u,45DD83C27C5046398C391D675190C7D470A94D877E7DFDEDC50C092609E29B02 +764000,k,62B2E7F0271C07B332D687314AC150EB9C561647C614DC348B1A60D48F2B6063 +764000,u,6D90C28411937FF02B324DE164105ED2F1B5FCE17C57C99B9A6115B7D8382218 +765000,k,48EEDA1CAFCE99F1BDEA08B93026AFB87A307CC20EE35DCE0FFBD4070B29845A +765000,u,378A16C5677731DD4F956B4052A59BD0582A1263B3A3A3B7CC33F3CB07D7575E +766000,k,1A171AE1BEE4337C6A192C5A0FD02A86A27B16108860B0EC4D2EB6499A8F9F2B +766000,u,25C07D92CC4DF9DEE61D84D0C48B6C301743EC5567DA5126D63177635767623B +767000,k,F69161D368B80B2F087EB3116529B67095D1D6ADDF33EF4C2028CF4C9CCF8B4A +767000,u,F9F4C8BACC27C538AE5BB9FAFD6826CFCAAA85C05707FCE567E1BFB2409A135D +768000,k,7675EBA1964DDCE283110A6CB97E63C53BE3CBD193E8795801A0C0DB1593A655 +768000,u,0A0276350460722024CC3C58E645F4731B37A8538D8C9D4103D1CEAA07EF0A35 +769000,k,3C426022C7EFEAE2817C5EA7DE74C075BF0CEEE8290F2A8523EB61F964714674 +769000,u,36294D836782CD6677558B3C328DA93788FA4FCECB519C0B4FBBDF8D68D69806 +770000,k,EE270864D1BD1C9470E18450D9B2C1494824D03D7D557445404AB93C5C102322 +770000,u,333E9246D502517385CF8768B270B1E2691DF60BD0F9735394ED3EEEAA0DA366 +771000,k,FFDE69BDED73741398165202367D02F90D57CC44A194F667C7BB68BA5CE1451F +771000,u,033E65819A8E72B796D21418397CDAA2BD339DBB0D76E04D78692E5F1B3DEA19 +772000,k,E0BC530862FB7CACF8B0D6C5D9AF5EFA64AF58E0C5FA7788EFE317E0E1695A43 +772000,u,0362B20550055C3AD00D9B03BE78D5271F5C1CC60F0AE46416B103F4E7DE103F +773000,k,D2DDA856094B3F379C21930F4E312EEDBD4EB6FB604EF9370CCF822218F5CB4F +773000,u,C4D78F44FBB5B7F12CFAF261DC3D2F85BBA2021CBE9CA43675AF6A77A1352320 +774000,k,74C754617DACFDBD227BF7B3C8B1B5A420BF4A688019EC1B63FAF3234F156903 +774000,u,1B689AF8BF47373732357275321BEAB16BDC524D39542774B81EA60393AD2A03 +775000,k,AACCFDEEF68A1569E5D79FB67FC3B7C93EB1DA4EE504C497561D1FCAA338E566 +775000,u,64B192A1D92784F7B9A6674FBD5290C7B9C1BC1B4778BB12C230BD172393E605 +776000,k,ABE9B6E2E83DED1526DFE2C17C172FFF0B70D685F1A26AF24E44E30D4FB07174 +776000,u,D2FC439D3E8306537638375ED04E3396FB7AB88FA037F5DD37888CDEF8976E36 +777000,k,EDD5568F8754E62465158B6642406FCC120CCED96E771E8009A45E4A28B1FC7B +777000,u,8BA824269F80CB93CAB7234324E5AF17CFC6A075ED1209805E1F04D91128FE77 +778000,k,DFAA016B05EC3A9FE7265CB674478EBFD1A99AC2264B8C2BA6A523A8A6505E0C +778000,u,B126D4C335BE2F28539C398CFF10DDE1BF86EA09DD76A8C234FDF56D78831842 +779000,k,ABF77C7AB9C0FBB47286C718096F957885994169F91D445C883021CED022C607 +779000,u,4D7170F705E6EC425B91FDCF2393AECB52956A33D1997FC1382B1934B02E9D07 +780000,k,3C3AABFB9036DD3D02EF4410647DAE46C8886D50CA3D866E22E787E46DF1BB37 +780000,u,06B0A789C5CD50CB94CF172CD63E36620C96B6B9783D29EE2799992589A49E0F +781000,k,C6C84DC54932AF6A5F7741EF664ECE7E2817C8C5065CE966FDCBD5E1556AF250 +781000,u,B105F55C645B90750BB84652D5D8611C384D025B1F641EE11C8CA2E41A5FDB02 +782000,k,42DD480400B4CD54F208FA1F319301935C1D88B16E99502887527537F07F1664 +782000,u,C94F1A9E01344DF90DB547D6E7BDDA7774534D439F5B16095D1756F720F18458 +783000,k,C82EDE4630E6DAA8ED8CF47947C5DA756A243136A9853F18BE7D6F792C08A326 +783000,u,56CF4D65AEFFD7C592F98BFDB567E4B2D7464E46A2D23094D4199D29220BB94A +784000,k,F382A0E4AA9D112428A1DFC7691F632A8BC6D6DE870BC1FF6EE8EA2449383665 +784000,u,E3BB1106DE42ECA495E8F7AAF0A7372F1DE2FC697D7AC2D9EB8DA358B7618A22 +785000,k,C8B4D59D68705CCDB013875F783511DDCE25AB65C33D5EFFBD0DD8503CE42806 +785000,u,1E36CC35E03295B0B8C2216EE29D7D1571BE7CEC5E0DED355B06464AD5481D01 +786000,k,A424B74B55121D1C873D50BEC20AE51E080D308D5153F07E19996BFBA1F59078 +786000,u,D29C51E6B75CDB8A6F0DB06BCC9CB8ECDB79A3B3A875826523A28CA58D947811 +787000,k,6CC9BA48F95354F826012580B20FC7CFE794914DA556BBCD3B36660C46C8BD38 +787000,u,FB0A592E27227826F9CFBA106D402B394509310381A1A04EABA1C1D0D0417470 +788000,k,45C1E805F945E11E3408CBD8138A77BE3C0C22720B149475A7BA45B3B4649D78 +788000,u,7FB847C4C845E2C956C93147DD91DF55D5AD79A936641B5C4E6062849D2C574B +789000,k,757C0DE228FD7B557ACF63AE09B776745393865037F50F576639C903D4675C0A +789000,u,150C97B1DDF631814B5F0376306B6D4F4937CD3A419F32D4FBE318354A7B2436 +790000,k,F19D72B87C7AC131EB11ABBB652E4C46B81C44FFF87E192B1EF3529F97E18D6B +790000,u,6AA8C5E0050E3AF2AEFF675C7776A907793129C0CF281D37CCA061424AC1FB0F +791000,k,60791D7EED222D95044E311F8BF9861C83EE4C2016C281E31C78D35EE93EBD7B +791000,u,3F94B830B8B829EA1228616ABB866A2903865C0FCBA573128886C6BEB0C5AA1D +792000,k,B015359F179A566C59602B5080281DBE9A0115CACE95EFD82C0E0CD0CFAAD81D +792000,u,877D3C6DA1A3F442F0FDE5648DAD18748426523FA7F9A36F124BB240D00A7626 +793000,k,2BA07AB522D644612454009AB1EDF16C07EB6A65E7A07C8BF3A52B99CC7F9870 +793000,u,39ED943A2120799BCC58DFF1CB09EA54567493654476D1262CD89664DD83AE5D +794000,k,A5AAE015FCF736CD0960EEDCA0BB868B4FF2342E4DF8CA4FF8F98B966916BE48 +794000,u,4D207B903729E1E7AEC22C18093E615EF45BC3C7FA57526D672932ABCBE7A123 +795000,k,2A2634937E1FEE6FE55BEB3FB71590D8EF6C281A364A800FAA0A069A95117560 +795000,u,3E4B392365CDA73DA63CB24184EEB015AC9AB6E9EEBD510498A880FC36E0E42B +796000,k,3330014B724D0F1ACFBE279F794A0856C16F1B75C65651EA10AEB8127F1F3243 +796000,u,51DB18FE67FC3465A4B76646723FEA2487CDFE0B6924B5CD4801E6AD6D17013A +797000,k,C6D46E6F8116D0011835800B41D220D224DFC7F9BEC7405E02C633BD42825815 +797000,u,74BB8D437669F5E240F9A5444FF83840B9259EF26401810C9EDD9BA072993A1B +798000,k,D024FD0759D2EC4CC76F7BD213FEB73BA63CDE1ADFB36F3B0DA63B6A72161509 +798000,u,7AB77694B7DECA2753C0D7CBD92D3FBBB2352D67251A6E7C94C4B1D6A0438D3B +799000,k,8DE79538FB375FC1EF266417D03B7D6E5BE6D1F64AF5ABA88991E82962A1B501 +799000,u,D37BB6AF1118AE37902D58EDA15E9A0945625A1D4DC78AD5DF5596FF59B31F15 +800000,k,55750F77672C9D3FEC85C42EF4E02E2BCBA0A587A0A90936687F9F8D68867544 +800000,u,48289E9F296DF6A838CB35E8DB3F905275B801C0C4C7D176DDCAD205C7E07013 +801000,k,E995FD7D30C08EE9A92A7F02E65EF1F80E48A94C8C7B3ED1E7F893B6E9119709 +801000,u,D823E672532C1B0460368B9000A9B0B47C6E5C9E7200EBFFA4B2C52EE6D1ED44 +802000,k,DA13B05FFDFA94B5FD76C900568FCA95D105266481B0600DF8405A88CCE4E22D +802000,u,5C4BBC501CB7FAD509D468AE234955FEA29FBBE15DAA465D03C0FDF2500FDA32 +803000,k,D6230627ABA0BF7430D55FD965BD73180F15CFC4FD58A9FD41925712EFE8755F +803000,u,C1B4E26E1021A402884136E5DD310FFB3FDFF70A98999190634B50975D47812E +804000,k,A9C9C9D422417EADF0B0A0825070AD070BC24C8032BDC33E4A0B5E5B17238404 +804000,u,6FBA3F89584FF8894F90EA2D0152F3079FE16F24987C646A1C4651367FF68A35 +805000,k,E36D401E371723D6C39E419BC48B28038FDD0F4419CEEFE2E21AF343271E9721 +805000,u,B8795D439D91CF7BE097BF17F6742F6F81037346A5039D2E9A82EAADB7F88E07 +806000,k,3C48955008BDA0C71BB01661F73720B87DA48551FD10086883A6DD604AFD125B +806000,u,747345448B9E9DE042726921042BAEB6F8958483FD5FE1EFD971549F5DDE566D +807000,k,91F4F76BB336F2A29FF6BBEEC8AFB3DAD19C27965169AB65494E2047D3B5E155 +807000,u,D95785E9D7C9FDD1FAE55C581E9B94931A5D914ADB874F226F41E18A96E18C4C +808000,k,DDE7C320B19BD6C6E5E51335BE5C0CE494E357D581893228B240AAB5A0C66E5C +808000,u,B46F77B1D447C8B5DBD81031E6AB8D5015761FAA29111DF21B183ACD0876B315 +809000,k,E1429F6973CF286795F97A08D474AE6E33D3C95FAD375A06F1547E2AE0E9F239 +809000,u,4170115B7E5BCEAF055A73C3C3F66139B6AFDCC2C5E9B3922BFC3E60220B3675 +810000,k,C5312FE30BE3C6FA7E9209E10ED57CEFACCD0339183980D1C48EB6EE859D9002 +810000,u,62F9BD5511C43DC79B5BCC00BB3D7F6C9B9870B84FDA5144212FB19AAED47C67 +811000,k,7299A085FEC804A3EDF5E847BB95B6FCC6F131A7276CAB2BD5B7EFEF1903D315 +811000,u,EAE7B5992A4A1C47A035A89BA0524EB08E8DA5B0A83AE7614CA98685FFB65B3C +812000,k,B773118FA32AFB3DAABC624E22E0A3FFB715635B6BA22385E53490A19CFD0A24 +812000,u,C518CF8A8C8F01EB720446D7984E31D04556C1272BC2DBD50A59C5FF54E9721C +813000,k,1D541486F2841B775048B48CF907203951B533C15DE5425A7F78FAD0E731DA5A +813000,u,4F6CD4DE7CB4AF1E89ADAA49A9C5BC26D7BA32C0DC208DBC327F44A6778D3920 +814000,k,908A2E991F538EE00278636B04AE32B1B43B69229D0F29A5A0D45AC3C8E30546 +814000,u,74B8566AB34128CF227363F7935455885888D6971F5144BF0594CDC63768964E +815000,k,164AC1298BE55A8D522678007910A7117B4A5972868A4F4E8A64BA98F69A9131 +815000,u,B8B55E32A3646886F43708004618DFC492B4E3F3DEC368864809557EE16D8714 +816000,k,500F189CFEF5745158094989452454F7A5BA6B5D1FF37E29A3D06713F27A553C +816000,u,FCAEEE177EE3A262DC9C898E2108B101B3F615F6A64887D1F2B0B659DB96A242 +817000,k,2BF6BC3BFA0550D24B1E425A85553D2957CE3B048FB45A78BF8C743A0D144253 +817000,u,453E9C01C5A91E62B428E194DC4F54A6BF44208470E13FC244529BD84E628751 +818000,k,95C5BE3AAB12C2CAB7B6BE8704EC0197823D0660440A7BEBF1C54347B59F0764 +818000,u,1E35BDD306673667833EC730995182801AFB56023607CD7036A09DF61ABE2A0D +819000,k,D31F6F0C3DEA4F5E5BB21F5A6E301FFB141C0951FAF5D7948EBF35D181831112 +819000,u,172CDE193C7B479E523AE1B905DE2305B5EBB13ECA503DE5FCEB5A0F8946D931 +820000,k,56F0B673E30CBEE3626B6FD4D07B4B63EA703356FA8CDDC7599AA0DD24CE4833 +820000,u,DD440D08E2CC17985E26DDC5850B9BA1C410525364052037143C5D61AB9E260A +821000,k,82A1AA0363D56620A814DE1A4DB7E8BA712E3E8A984D3681496ED9A674493006 +821000,u,76364464FFBB8AD3BFBC2DA1CDCADA626C463B294D6BE08AB7153967FF20B968 +822000,k,4D5D8791C90E4F421232B04C03FAE6C8C0A9DAEBA1CC5EE1A04636D022665846 +822000,u,664136C7D3D329BF54F6B55AEA6A263406E40936304339C577FC9747BCFDF97C +823000,k,4C397ED43712CF094E14DDB7E094194B2D7FBEF894EC5ADCD1EBB1ADD4AEA27B +823000,u,EC91E948E631FFF7A8440E07F996DA218226A336634B5743EBA875CCCA4AA439 +824000,k,475C243E7C26D19E434F1868670261DCA9B7AB619AAC3FF9470C9913BA946615 +824000,u,2190F5A8FE60DB2B951BB8260C716F59FCC7805C58CBA5E90535CDBAD9488C0F +825000,k,A09B06BB1A8579F6EE1445DA511EC232032A73B756CA9071883D69D832747355 +825000,u,CFEACACE73F895A06C61447F5301479D2A3B347289AA74844BC6250B0A745C5C +826000,k,2454E2E45AB8BB5829DF4FC6014096F92508E765645A21C1400F6A712CED500A +826000,u,7D6B2D9BED7DDC4A81D18B010D79BE5944EFD7061EA11F84CA9B90D5450A3E18 +827000,k,8F3BDBC1A833096BEFD73D7F87688E2551D39B358B754CA7BCF6454ECE7B422D +827000,u,7FFA69C621F519A1E9E4E836FD91A5066F069F535CFD65E38A579742995E4334 +828000,k,C7B10F5E0AB6605B59799272C2F6EC8FB01036369E46F850E819B9B32E5EE455 +828000,u,0C567CA781CFA001D8559DDFD7827E4810E6A9642626EB9AF4CF7C476A08212D +829000,k,AC3CB15062297331EA0E278BFFAAFF40577144B5E4761196C5CDE3E8EF728A37 +829000,u,9BF64F734869A3F043841B0B7F9B9699E3DCBBA175607F2A3AD5082C1BF7975C +830000,k,6307727D341541439533DDFD294CE636F1F7C9ECB94DA8522624517B627C704E +830000,u,3B1937989DC3BC1CBC3D473447E40BEF0E8780C97B8376F83016891983C59E18 +831000,k,8711712A16E9E6A74AFDE0A6936970C4742D19958F35DB321A725599C7C2445C +831000,u,7A8B6179E828D7A1D0B35E477164F2FEFD207C7472DDAB10429178A6E76FC927 +832000,k,5D545F078A29ACD08626ECC4BC4B0432C1EFD30E3EE6D0A74DCAE71B677A4516 +832000,u,93C2BF4C8124C6E1767AF4EC1DB1F1765FD1FA61CD111D374AD54FBABB3BF878 +833000,k,0AA88EB88EE6092E76DA6C6D1819246930802897E41C17ABE3FB13BDA6C81F17 +833000,u,F3D9B9F908E7CB3C3698C2A0510F3BC92BE9D9846F16DEF3510944C98703A842 +834000,k,7C97DC46E206BE610BF51FD099F455C1BB7F7BD860B03072BF14E6D6F7DB2626 +834000,u,D4C19B8D8987E461E0EB7DD1020A2884E0AE6E972CBC1667E6C0446EB199EA48 +835000,k,9F0FFD5AE0B43D917FC296E977504A57ADE2004A9ACD5478370FD75D1A8A7220 +835000,u,251D7C6B403C939BF2A47F28A22F377F8706FFC92B466EE790D630F5C461F82E +836000,k,A021048B2FC37B962A25F899342CF7F4A707CD0C98C440D1B03DDB326893AD73 +836000,u,48BDC628CC4E7E6D0003136BBBB90C64109EC577133E2AAC9E9C82A984890442 +837000,k,E774B10ABB3E1FD9DEA0F69DF2D10B218736ED1191E399FF5509289918801760 +837000,u,DA10B033C94FF2D717322F4646813E4251277C3FD5B2A0E21C29F9443CDA910F +838000,k,E29A248621B7991C8AB7E9B2F994D41B2D88F766118E2F6218DDE40B734D081F +838000,u,D542647B12D0A3991F962A46691FD9B6BA6D4DA397090212837929F13815811F +839000,k,CBC575CDA7EEEF5CF13A5A90D4B4085A48C2B5E3EC28CD180FF29B4181710077 +839000,u,5A5178B9AF9D6CA81EA639B2F6B2C5BEA7668336186986BDDF962C6E943A481B +840000,k,64E9CF7C2DA1159078A7BBB9284DA2FD00DA641891A5CA7A9797395505B99C75 +840000,u,C81826CAA259566E919AF277BF003D9777A161C07418A952140529B95181C25E +841000,k,8AFAE8F718D60C7A237BBA8E8193ADEE7AA47C0F9DEF8BD88F8517D848221B07 +841000,u,C2D71FBFEBAAD50ABA1908AD38B662974F0B537B1577A0AA8CC2BBE32438AA33 +842000,k,618053712CF638922BB003535583EAA54A9F2238C0CFA5DD589D1E6337533774 +842000,u,EA85FE7F0BBD231485AF8D624AEE58F41E5C7DFBD9E0820ED85E64965A53A54B +843000,k,3888B0743E09B2081907BF4C833C0A4E265F6928AF55A719480EADAA775B6B40 +843000,u,748D198B95C85A7F2929A82F80B8DA62FC9277963D4B9AAF30F0B486EE282251 +844000,k,CBF816BF1BB138ADA7A1F99E63D71CA73153CC84B1A38836FC210A0859AA647B +844000,u,D3AE9CAFBCFBEA15AA4B4F2FEDFC43EBEA09BA36873E18E62EBCA31CA8411B00 +845000,k,E477F5167F4305B1162A2625CC7871C5C935EFE9833AC9A730900C1286F4ED63 +845000,u,7FB4A38A9F4FD367C6014FDE4747A3340DBBDFD2AA761CE4EB7883F9AE7A1D0C +846000,k,272E7C4A8B763D5A0ED76F3B3FBE0539DA6A4F9BDE8BFBF0D4E6BC15193B5131 +846000,u,3384503263C514CF9606DDE4C43252A95CFC48F2FA1B067A5F07AF1666394059 +847000,k,CB74D0CC11A36093CFC007CD89C40912056A9535F8D42FBD647098F5F4FFA326 +847000,u,B2B436AFDA48BAC7DCC05C58276CBBC61A4E396E02FE4F5E68D3555443CFD92A +848000,k,3D0BCAF5B788A1C18C16AC8DA2C468834EEE2A40894EC836C0FFBC7E743A5A58 +848000,u,E522B44650829D735885A9256A4F64A12E46632E53AECA3162A2E338EB22C03D +849000,k,3D19A19C3FC4B55E8DCD89BCC584EE983DDF910FA667F234CC9616E34F485F53 +849000,u,ADD2D26EE5C7432D716C311ED692039F2135BD19ACF608E4E52F2AF9EFA6C415 +850000,k,7C060A8815379868695ED1C7F351995A2A4DFE88354EE9257A5A8991A3E12E3E +850000,u,893AC0A5269F36BD1D99AA20D25A49B48766E40AC1BA40B0DA02673BC68E4D68 +851000,k,72526537CE6926CAB55312E8C4F638CC9E1581652B3073385B00570B7F97EC68 +851000,u,739C0D7B4D5032D30C5D45014BF04067A11C725746FEA30E96B989464849C15C +852000,k,B9F94663ECBBF6506EC58C605A36A0BD7AD4AFF5E60501B48CBFC8D73C087D1D +852000,u,7CDCDDA8700A5A7568F250CB511417179868A4D4DBB3B9924149EA48E3F44D31 +853000,k,830FEDAC5CA7E5A09F09D1057F8B6298F7803467848658B9278A38171EEBCB49 +853000,u,ECAEDE95BE638D5BBDBFB1AB607B061220B7C8E3CE6FF5D467AE3A5CF45CBE49 +854000,k,93B5F33E82F48F318A901A03BE3A9E88C3BBBE66610A6604D51F60CC0A13F157 +854000,u,28792C4B8F441B3330B38B44A936831AA78525FF09653C1F68219C5DAF631160 +855000,k,AA4C5A776AA2D3CA524A8242327C36872FE2D500F1595437524C0E71A5311447 +855000,u,4717A9D79F2E1367A9CFB1E7CA7847989C7C1C65E4B7DACB280C9BC225EB2603 +856000,k,161F2940D8DCCAF9B674A3E8C271D4A59F52F129B167C1EFD7177D31DF528C64 +856000,u,D1F638183BC30E69CC6E945933C2A45C62BACE1B366656046F0E3C77FB254C72 +857000,k,F52A1900409957E7896A0360D9C98EA1CAD8298A52A8576B0446373FC62DB231 +857000,u,B1053AC0CB181A7003E5403BD4E83770E6300E9AF503D799069CAAE1F1CA3D05 +858000,k,1D16821B87C5F5903C42A94A6D4F3F2ABFA68121FBE0F02E6075D26E79C3CE7E +858000,u,F58DA1372B4980374B60DDC83B95930EE987A1D0EC7D698A4B647CBC6FB2135C +859000,k,F08948E4331EF447DD77A11865D5189891977D702A5D66422B8BC62F795EC463 +859000,u,381EC3A2C442B1170ACEA52EEC93F9410BD99ACCFDA3618479D260BCE7FBAC0F +860000,k,790D4018482DCBFD093F1D69757CB1A7A6634FDC8FB21EF377C75AB23DA64D49 +860000,u,49935FDB4795192784C1577F1B82AB9C54D8FE127AA8B54F30985CA9D9B16378 +861000,k,3640B94E2E19835FC5B461B449CFD1C4B697D7384FA0D8D16CDFD9809E8ADD20 +861000,u,2C4331292A725CE46B10E7CDAD9AC4026116D685EBFE089A3A0E5D26D3FBAF00 +862000,k,DCFD5EBE92FCE8EDB72ED2DF8F3F2E3D2BAB986891D044A7862A7C1512E8FF2C +862000,u,7C798BC6AEA7A90A8A25A06EEE667CAF85DBF3B7C58E579F80566E333E411746 +863000,k,2C8A4A8FAA4F69DFD80031542B8D7673600BB3919C50F938A34971E7B4FC9878 +863000,u,BB85BE310545C7598AAFADFA13D05B3D531AC55BC8C46961404CEA65CC628038 +864000,k,474A86432F8139F6D75CC875396B396868A2C4E0C6542E9210170D4C3274A835 +864000,u,D3FF79B5AA72C6BA6033377993EBE4A87666C2ACC963B8C12655BC669F10F16C +865000,k,4267B9DADF807436A6B7DCF864FC562F4C9C12E13D44997C2C957CC3C0612B44 +865000,u,C3CCBDAC414CF078E1F4B1DF8A35BDE8F7F203DEB4B5ADBFFE0ADFCD3167483D +866000,k,A2E571AEF70B17F2E76CE2ABE5BC5A5F7AE10D86E3213C59EDD5D33C36CC9C15 +866000,u,BA57CAB4411F6703BAEE056FB4E816C7D2E906496D8CC13EEABA61AD6BBC0F0E +867000,k,FD95AD1DE7E7D476FF9FA5C934A5F541D817CC3DF9F5C3085324EDFA8432456E +867000,u,D172DD2BD6BDA9DF47BF6F5A0663614D5EC6DCA6A43FAD1B07E5C191F335AB37 +868000,k,1C5DB93D167AADDE90A0CB384CBC6677E420DC4486FD9719111276491567193E +868000,u,E9F2C0EF98F2BDB60B65AB8C5E4F13B1A86C0E7C984CBBCB52F959E872E23767 +869000,k,A7AC7FC49FF153BFB2F5FCBF0561DF8F98A57D638D4F6B1A73DA1924CFC3A151 +869000,u,8E84F046B9A4F3FED8C86E6520864BFE537660157EB74E24485788578F3C346A +870000,k,94902242570668F4CA9D010A13CC923D77E085520684ECA32218EAA2617A6475 +870000,u,92129A8D806EC18B590E165C3C85D4029833829A71C3E5F955CD44DD7C072D19 +871000,k,D61175719C3649D8652FDD6DC248B5F42203E61F59EFC05F9E31C47647987D5C +871000,u,1D32E09FB130E7C00BCEA2DFC18577021A0A58AE69AAECF0178E0D789118FD7C +872000,k,E49111051329FB7EC3718E88AC0F934FA3BCA597EF822418AE4F04949086163D +872000,u,D99514D82F885B326D1B151CCDB2B4A9B98B475E63ECF7471B00E4D8D237CA43 +873000,k,F5A68B398EB3450CA1E313430BFBF3C3D06DE8F9842D41D9288DB8C4FBB17519 +873000,u,735C65C4E5FB707A59058C5CA5CEC98107759DDDF1441C20DDAE09B07063B864 +874000,k,EA494343159DFDD9978B39F6F0C56C163C5388D4A57957F9DA18CFD6F91D036B +874000,u,A86C17A415D70F007F1034C91E629B1FA30B23038F9ECD4C7B3F5C104242EC57 +875000,k,850222B8CA96ED42057CD28D2DFB7FE1081CAFD8A726BC0C1F191638BFD7B100 +875000,u,DB1C5BB0300D2393164265AA25D2CEB1C465CE18527664CC7A073D7134ED1A7B +876000,k,005C6A299009748FA53BA548DC2986C47A441752451FF63443BA9F3ACAF5806D +876000,u,B5813C83FB9342BA04459D7A5E3134B33F47F87D18046310496AF79D33B5097D +877000,k,641928EA064E3FB6A14B3986BBE5D34F5E5E627BD05DF02B433D72E51F18707A +877000,u,A20F1B753081237CA6E025BBAC7583227ECAF61F0C8FB043BA8DD7FB2D654818 +878000,k,DD19C42859CB0495E1FF705C68219F7E89D3C9030D841B3390080991A8D2E253 +878000,u,F6B638BEA4C71A71DBF022817AFA6F6CA258D5A63E507376E96730172D665070 +879000,k,FAB8191624822C440D0B52E98430CD88F2266343E36729EA9CC9EEDD7434CF63 +879000,u,7134922706AE044B2805146E04C11E00D4B7AC1DF0D710260B20AD76DFCA623E +880000,k,84FC88C9B3ADF167F26D2410E33183965FBEC1BE62418CDA0A8A9BC668D0B026 +880000,u,DDB3E1BB88D97A8136A0DA0286287CDA55FFE20B14492E1770A3A3F32AAF1F7D +881000,k,ACF323A28145F1D3105B1FA75CB0B33B9FD762AF2B8AF50C891B48EA49BDBC32 +881000,u,86C9A9F54DF3B41111114953E58C3C6EA87B57EBCDBD5B6A61B2E85B50599E2A +882000,k,9CF15D934E7D8A384291EF06C6A1570E92D79E9A79C5F703769C1AAA13ECC805 +882000,u,82F7456ECED2BC0671E054360B5D4D50AC28DC3B265DFF99101B4168559D2960 +883000,k,B82C16C6784717C44741082DA697324886F1C3437776FDB8555180E203134924 +883000,u,68DC9A888ADEC6358CD3EA651F675400384B29AB7E5488B234DB4ADAA4A5B04C +884000,k,6CEC44903A3C16848FD0CD9297847161C6B3753ECDAF66D6A764DC23A965546E +884000,u,7FF2175C58306B25170BEC96970B4E19659319588EF7D674899106FD7F488D75 +885000,k,B2DEAD3ED06866F1672EA9B7E2203B8FA8F51CDA73B14862D684821D6838576A +885000,u,B16290BFEB5DAEA78EFECF4EA8637265934D8F93F4885E70D91E84905AEEBC01 +886000,k,C7A1986E9E9D7756DEB18B2EC405AACA770F2EB72BACEF527C3E01C280D0E239 +886000,u,1A3E5489037D49197275557D7CEB918A64EDFB73117894C303AACF2D42C57745 +887000,k,AF2C81BAA63EC8F6E14580FFFF8A0462CBC5E8B5735CADE7A83C8543D787AB31 +887000,u,0AC95025155EA23DF33269C2C5931B5C1E29594FB177C91474DF51DA64CF311E +888000,k,686341D3DA00873FBA3F2B6260C5CEC766C15EDED1DBBF13B01DEFBD84EFED67 +888000,u,D7CDDA5861BA080B88C1D86ADABE4F62AE11D07B87C91C90831A7047E40BCF77 +889000,k,44A3255120E5EB0FA2EFB2CA10E1E9133B6A1411DB55B3BA41A4F3B470A25D1B +889000,u,1701BDFD44B4CD0C68078E201BE09D6BD7098D74F7D25E64B87BE616F4F87618 +890000,k,5DE75FF6863F62BB6A138E270ABE837608D088C067885BC56947C22F688CF854 +890000,u,485B37E555EF71ABB0AD2A0C34A2B24D4EAAD542E884357A252628DE85D6DA38 +891000,k,AC2AC2D03351FE9FB4C957A32E90254C0B21AA955CA4163EC4B66E9633948558 +891000,u,C61DCD9C0BB9D2F03B9325546F829C1FCBD8F9C319DCDF4F1E23386284FCD518 +892000,k,E54CA4C5BBF25F6833DDF7A098FAED351DDE309912946C263BDD428A649B2230 +892000,u,6477CB666F7BEAFFC3806D29BFE8024BFE80886FFDE18EFB7A5B222AE93BFC51 +893000,k,B3852C43B679D726F4D1E0447DEA920D8AA69FD72B3D130E6C6A560C7D10365E +893000,u,AA2D848999C7C933C08A50726AFA63CE3CF7D6FB16B076C7943924EB7561B536 +894000,k,1F37539D805BE94D43F418D360613237A5C61ACA49EAD69B68BC34E81B204D52 +894000,u,97ED616B51BD27769BD5EDB222F9AC261D0197C5DCDAE33F44603918E19CB337 +895000,k,1F516B22A2CE4F538814FBC6549FD875A404353B70DDAFCC6D9B24A46438693E +895000,u,C7CE271A196D77D312C51166E7D112A7878A27BDDCF4B8359BB3827BC737B506 +896000,k,BFF99DA907870CBFE13D78C852737B480A3F3CEC48A5451471FF1D07F1F9594C +896000,u,5D01D4B1F70250C9ADF8A41FEADAFDE8AA8983C2355ECE11F2DAC6AC92786238 +897000,k,7691D6BD9F9B5E07876EC8D4719074D3548130C0FAC2AD3D8DACE725D941B846 +897000,u,17A9075C9D4948CC81873AFE92954935011487750B0C265A1DDA070885138617 +898000,k,060C414FA7C5BE851A01580B97B143E02D801AF5C8A0AAC8D6AD5C2358261F2D +898000,u,0BD830BED821F2D9A66A72A376AFC09CB6EB02BA5E72ACC4863EB0C629D0FA2B +899000,k,927FBEF0D692CBD2F32267C772DA752347295FA0E9936F9F7A5BA5F36F153622 +899000,u,1442565766B50E37960F76ADD78050D39D25F2F15D9EBB61205E35C904FB8F7E +900000,k,03AB9C057B018E0FBE51517040B739110E12B45880E73D1EC70D0592EC1A3B71 +900000,u,5BD6FD4AAC82C92A3BA7A545AEFA5F844BA879A9784C0F873CEE59CA10EAD944 +901000,k,6E66718073C56A4FBA5B8AFA83F46FD2C6C7586B305C10E82CF087D6651FCF23 +901000,u,897B0597EACDFFBC38DD018EEE07FBC5D03F45A4553F34D864E76189855FFB65 +902000,k,F2CFBC889002E0AD7EF0C239221D5083AE20D63FA97DB17A43A2F96FCC831B42 +902000,u,5BBAB8F4C10F8FE76479FFE103F79972AB9754F27E607488EA4DB60FDDFA9379 +903000,k,14E24011641748D0EDCF192459FA6CBBB72B61035259143D83679B68E4811D5E +903000,u,731BD997ADA0C9D45C6EBAF0FD33F805305E10675F18D1E158494D6CB410721A +904000,k,9034F4CB644A7E3318BEF086F9F1E28600350533ADCBE571F6BCF73D1D8C6320 +904000,u,6EBC7E4BEE7F1EBF3016F827C3631436469230A34E6A0420D424B0424391D42D +905000,k,B57D60BD272898942185102F52FCD8F9E8D0A552E6E586171E3B6E649E52A95E +905000,u,810C105EC6821A44028ABE7CBDD8A430EC3145FB4AA9FCE81A863C952AF2FE79 +906000,k,BDC04E09DBD302C026CC134CC026091FC9D57111BBC15C80087C553A81C1A41E +906000,u,6686267A439F2A51FE4801374234ADFFDFE8B2F96F13C7FC8933214E8C4E700E +907000,k,20AD54984932DD3B5021AE39E6CF96341D0F9A562A36AB6BC6878ABB1DAF7E7E +907000,u,E6901956770D86D2A74FD4C9DD4BE0EB05B7C19366D692ADA7A084460A539659 +908000,k,5D645B35FA4E0FBA2393A4B394C449DE6973E841E6C83439B215A75BBD4BAC4F +908000,u,784CBBF8300FEDB6B1A986E566EA3393040832DF6DCC64AF4B69659B912BDC5D +909000,k,4F17847FC18124D1CE2CF29C2E372CBE954560D1BE6CC03CEF34EC1C185F583A +909000,u,5A155D2E584FE76D7F24DAFB19C4D4498A3AF0B6D1915B66F02E7702F0D1D713 +910000,k,A4AB21FFFD8EDE595F4DA9F9AB6B25E0982C84A66415D7A3C8BBBA297057E216 +910000,u,799D90E38FFF188109B12B1CC442286D033EC6990374BCB7D9F2D08C70A5E27C +911000,k,342628590390604ED02629DF277BC0F530621CBDD8714470C5A028DF23E6F845 +911000,u,1AA00944658240AADC256F6704A0963229926057F94C50DB9FC7FDE7551EEB19 +912000,k,BB6CC83927EDBCAE711425A037E907FE42C7FE54704EB267184420B6CB6F5547 +912000,u,01EF39C213C961A24833BF8C2E2633CF8CAF3D46659F00235C6A9DDCC374DC02 +913000,k,2AB298FA090B252BA8717E6E9144AC850994850269527B1F98C17EE1C959A919 +913000,u,225C70F6AC1F59F8948D3A044D66BA1DDC421F5CBB9201F4DFC3EB4BB1A61D42 +914000,k,D721C61238228D4407EC3AA983BB64AE4081FB9E073E7D2BE90C82192FAD3435 +914000,u,84F9C7BE798778C47B45C9FFE9715F1D8B1CF41EBEF11B9AB3C7F1B72745996F +915000,k,64752C3F4FBD8E7F8C44F29541261E628656A38225A1138CC018A1697F7E7B4B +915000,u,F4CA1628736D3D9B7DF7DEFBDD4F2EC51B9954C4BF36AECF320A2A85B668AE60 +916000,k,C2FC7FF1FAC26EC2396E3403EFB1D201F2E69A827AABCAD43CA24290146DB56C +916000,u,E616459468CC53E1D8CD90E6FDC0E88E8B4083483BB7C01E96B003586928297F +917000,k,2E06EF3A49FC29C84BBE999852084639C221FEAE56F016A7F63EA4B5B5AEFB20 +917000,u,2464616CD05F58B33F0A9AC2A454B18E7FAD1226315201D87B0C32FC629A8070 +918000,k,D60812051DEE1078C699A181E96B0ED0E4D7022D2DD4FAFA2B3EB26F9102463C +918000,u,1C87CB3FEA86E436246B65F952F3A239CD37EE7B47AB7EEA9A4100D96818227B +919000,k,214E8E3667CE3C02CA0936B77F0693EE87EC599DF552F3106AE332420EA38466 +919000,u,8AF527B3DF5EABD51049C8BE65836FF9EA85015B15BF921865D5355A2D775024 +920000,k,973AA963174CF3F7B87677E0BD325746F3F2A7CA1223BAE286C13F32F65CC977 +920000,u,88BFA8D48A35D000180D1F08CAFD144AE1FD77734D8ADBB082D17A676C6B303C +921000,k,CD373926FA620FAB0F278BE01F98F46715B8BBF7E4266DC76B2CDF452A7FE222 +921000,u,26B7B3BCA4CA0DD22837B13FCDD07E2C126071BB19CCEF9315FDD2FDDD602B3A +922000,k,00AAE2582CC51B00D01A7B803AD294C3BD1E89C9181DA8829D397853AEBD8943 +922000,u,61410CE2731FBF624991E1CAFA2BE5C65D781440302C919A52A69CEC2B8EE20C +923000,k,426E6F29EE46FDEDDFFF0FE607B6F9446678C81A02ACB6B9C17D1D4EADB1864D +923000,u,7E6C35B5F84F58E07F3511D4CE03D0D7422A0A5C2000FE3F0024F5CCF593E163 +924000,k,B21B63319C8978C14676F20A96D1F7FC924B34966FB09ADA19F10FA6B42DB45C +924000,u,6EA2CEFBF44B1B9B423EEE0D6A1C26B9E2869F25E344E5420E90FF82DF791737 +925000,k,9A6978921697BD1D673DED6B48105FD5B2A8FC30CD9E9768ABF6EEFDA4902953 +925000,u,A9C1C99DCDAD16BCAEAD2542C66B62D8E949ACCA7666CE2DF3C47810DF27B914 +926000,k,7D7B0826C9F71F322BC121A24BF5458D02A4830F8F229D1AB707B0250F9F6C1C +926000,u,69C152367A26D47568D98035D0033395D51FA02278286822D775739B146C9453 +927000,k,4719A1E4B3F7C0D48315885854BD342306E3FAB12877011460255C7062C34E7B +927000,u,7EDFE2C217ADA2B4733011D17A60B32193DE1DB77CFA5C29229A4D27826D2728 +928000,k,EE885073B715F180E872541750393F8748FCA67478C821AE737BF8306755B469 +928000,u,C014F7B7053388C4EDC5CB669887077CBC74FA7F288DF5856DB3D6CA758C982B +929000,k,434606F7B724AEC9889F1DD3CC088BDA9F807849E0D9582452BD63C23F109C61 +929000,u,4C508E708C72F53A2DC42423FE36939D082074B25DFC24ECA38DF28CC25DC32B +930000,k,69A4180252A7D6B6051D6FD3AECE7B8366DBEC97C3D10733D34BC95A4953AB13 +930000,u,CD5683A21A690D8864D49C2517D22C3CCCE40D1139BAF8B8FF555D6D30E11001 +931000,k,C3899B577217BDCE8D6A54918347912B36B0062BE4B736A792F0841E80771A46 +931000,u,75EB89B2F734D1BB21323B60E2CFAB348A8CB5A8B21102CEB571D36E320DED72 +932000,k,185D88B3784F49CDEFFCEC184AF2F7AA716FEA0D54E94C9A44BBA4B6E4B33F72 +932000,u,FD1EA4EFF688BF9560483E21C5572751DFA55D15673C475E29E3E70FBEB80210 +933000,k,6C6ECD1C10C8A3512F5DD102A8FA02A6BAFEA98D997E937157B82AB832239E36 +933000,u,232B69E56A91003F52F03974119A710012252AA143571E9A77230B6C0027645F +934000,k,C9A1D78C3543C7EB0BE4A61B98F3116D3C367EA8874D42C63C4E3D3AB1916311 +934000,u,F48F9DBFFC2FDE41FF700EFB89D9D059456811BF1795E7755B47F862100C8F17 +935000,k,88655B34AD51D90FB24422961353FA828C8E92F07B8A51166BE1D1428C311343 +935000,u,027F3CD18B12676C67A8DF0BBF0C1C914BC369D8C569024EBD2FABB797919936 +936000,k,F9D6A392FC766DA43649692542C39A120BE800DACBACC5D30584D6616F31860A +936000,u,A0FBAA5B77A77401BDE73ACF82526A2F3A6E28614B1C15336385700AE1B5401C +937000,k,F088182CA36BAB32636A74FC5AB7B8D43186716A6CB72A92473DEBAD9F493744 +937000,u,4855C77D3865F34E44854B7761D5EA5FB751D6D5ADB0B4CC63E4B69D6EA6ED61 +938000,k,8B65C5BE1CC61FCCC200AD323A9FD2D1739269911FB604087FD33CFB73785114 +938000,u,DB1B93DF918517DBF7B510CA3F7FBE471A3F82886150CCD946A45C96EE24062B +939000,k,6174419A33C56EE1D7C914BCB47C13782DE634B10D2A6658CE8FBB4131EEF513 +939000,u,0B8ACFDC66EE2B17EAE937670AF000103A7DFD06AA4374E0F4CBC5FA31B9545E +940000,k,487D349BA6DEAF808808421D42323545CD1C804B177B8EC90C1F2CC232554615 +940000,u,7611E311E0BE3418619D62A672E919D3E209D1D0DBA72B0227E9CBC45A620E1B +941000,k,335AB61635ABC84C1982F4F06FD436811008E0DEF701CA11D7EBE3A1B93B314E +941000,u,FBCF1A721F922396AB6DE3BFA9B4EB41546F35137362E6A1BD35C8E5FDF5BF22 +942000,k,1E606BE46C1BA84E248BB3C3D46876D9B8268C1EEAE45A0C052D6825E0062330 +942000,u,401F15151CCF6C739615181395C4951E4400B65259AA11F0470824AAFD26BE35 +943000,k,F3651FBF6765986DF3B510613239B0F51D0BBC85D0BF4637E00A9A6DA2212E17 +943000,u,DEB50733FA5201D882926218B1F1481CEDF6DF418CD36A50076475A7A0199B5A +944000,k,A3D5B85FCD9B559E0848A9C0C2F91DE10979AE34A84BFA0C277A80435A119E73 +944000,u,E5E3A09B2B7F2A2038A178DA506A688BF33621DAB530C9BB9D8CF0D182C71169 +945000,k,159FEB00A2C2CBC0949DFFE242A3B18CD458106BD8A0C716A0EE2AF3D21BFA62 +945000,u,8F4F6EB646192AA302E7C3D2FE58A181E101B7F750834ADCC3E82028A2B48063 +946000,k,F95FA8B26FB738C812D25664E5AA9CCC7AC0564FB6DC0252CB79866BCF99FC47 +946000,u,8BB82FD1C3E5DD815881A43FD22B87A3A0D8DBA88B55141C4084DE3314D77E11 +947000,k,84B6D9DC897CC1AB5EDEF65F8D414E87CC7163FFA07043C4EB0F87007A6A406D +947000,u,7404F6352AB50F266BFCA3FF08F82836430934FBEE605F80B36E27C422076627 +948000,k,39860B98D8642A6E0245773C91F2AD2D8115500927E90CC7EDC105EA1501E83F +948000,u,87AD3D7EE48C3D80874138E54BEBC7B007C174B976A75B7FAC7F8BDB4579520D +949000,k,1456941A2B8DCADD301D6828368296CCF6911C21C270E3DCBDC485A36D075E39 +949000,u,33ADE6057113864650B73645382C5427A9C9D04B3F594702EE6BA3B98D2F4450 +950000,k,8BE69B12B1442715354D34894802EB5DDE90102575FEB8BDE5C2186279ABA642 +950000,u,85D6B4DE7EAE203DF667BD9973861AEAC6706C9C6FA897DF6A715C67E34B491E +951000,k,4BE0520E3E6015A535C58DADEE8585A24E1FB225E83072D5EDEDB16006693568 +951000,u,62608E7BDDEC03242A679110F2C4C8AEFFBB8ED1606F4B62E06B939BBDFBA552 +952000,k,A4E67228BE764C8F718A6035D95BE76F18BE73590C36CC4379EF6D083BB6F472 +952000,u,A7F868B73CCA6362627BCBEFA02A3680D40473354D35F962527A201A8EE1DE78 +953000,k,B588898C46B922F1C29CB1CE2D2842F31494A55DB7646D98148E909BBA99E838 +953000,u,FA2AD88DB50B9D653C58A2D9E8F295F730CBC70049B224C957E2328C1FBD8819 +954000,k,1BC46AA57C61816C5C362E4CAEA0306837B301A57930ADF3005DC47EAACD7860 +954000,u,E79DE5A3ACF4D1EEA2239004A5E103D4F38C659F5ECBFC94A42BE3B7DC0EC624 +955000,k,D86E2ACAF5AF3B53715FFA190B059C878E47A578558F338E88CD38A92FF96A76 +955000,u,5E390EF3650286A78B95B6DC0A79D85B6DD8DC2EEFE7382AA05E1370811CF866 +956000,k,F715835D6E771B17F74E67822315673C2C190CD5A7AC6C9128CFD2E099285B3F +956000,u,14ABFD7267C0CE229C6B0B80406B981B78A3BF30B720F45D4CE2C32347D23F44 +957000,k,C87CA041C86C96ED1BBB5595A39DB39358AB943768E0591597D2D7D010688838 +957000,u,306E43B59415DF62D6D7B11D7A35F74D60C426D9C30354CCADCE0AFA19548A42 +958000,k,BF4829D8541ECFEC5F4FAAE93746C4DBD2FF41C1F0292C3EB1EAD08AD07D7A32 +958000,u,CF76E7654D2F02A20EC161B636F9F518522F788902AF397D57DEAD5576118B7F +959000,k,48AAA751CCF391EDE1C7F12725E5308D28550BB01B1F050807AC55EF1A282514 +959000,u,F59912C060CD36703D701F6C026D5E7E457702486887BB1660DEECE9F161927A +960000,k,7AEDCEAC1F084FE7DD8DAB9516908B4B90DB2681297E49CC1B221FF1E90D800F +960000,u,0204D594DF6E714C3A28D15757943131700BA0F31DB2FA08DAFAC6A99257E82B +961000,k,6C1FDF3D8E6707B7573C9157738CD1EE6F394977CB4F4AA38F5531E6B83ADA4B +961000,u,F761E87DC9836225C5A837D11F409A3DD6880CA314F291B0B531E3ACC0333E63 +962000,k,0C9BF951E8C04E93E95F89EEC0143B224147DCFF14288E23CF1A6717F97C2D51 +962000,u,3BDCAA2A734F3035FCAAA1A4C8A52B79E8A69DFE54690790C1AB714668B44D60 +963000,k,01352BE13F25448737B3AACD63FF9A70E9C12377C951C13014AFD61130028A59 +963000,u,13E71F2AE605501E4401C9C8B2607DE54F7CCDA3914676AAF2598FFB9821A741 +964000,k,DBD130E5F6D94EBB9A237B6152D73FB14D90B5C98B316466043C9BE79E05A86D +964000,u,890C57BB402C47062E2CCC2B3B3CB9FFA0967DB654675DD20EAA35BAA6F99B71 +965000,k,E216E19D098E9AC2C70050C82B066461B5A546F5EE8D6EBE55A20C115121C242 +965000,u,D4DDCF5ACB670148D74499E6C669022BA4D5CE5A0470316DD812B03C5F2FDA46 +966000,k,FC486E49D078B73AA6AF7908630E35105C8AFB30EE9E3FFA591E190BE9A7683F +966000,u,41C5AC29A6EC2BC4BD0F6F9999F1915CDAEF06A005A31B1FFEC6B31AE34C116A +967000,k,31A47A24AC4EA3E028F8E52C2A7633187320F2DAE2FCB8A418E0937F6D1CA304 +967000,u,9245BA871F1C696BE12EE0191AE337587E69F2510C3FBE673D8C86AB0023343F +968000,k,482500A5872B4ECF499DB3263A9B0B4656159A889AABB9DED086C297E5056027 +968000,u,C241D5ACC66AEBF0ED1FFF33F29E3B97CBA7CD6352630ACE400BFA3846158438 +969000,k,A47D92B0E2F17A39D40AFC09038212BF90AF995AE8C1F61D82512DE8AA66A558 +969000,u,FA3DE555E91E77D33523474B16B38D0159FC2B7B49E68C20C1145980874E7561 +970000,k,16BDC3324325751A18F6BC9B292B941258F9417850888972E2EE56B294B1C216 +970000,u,80D7D76939B25398B6469D4F4324A3E11E065DA85B054FCAE6EDD099D07FAF19 +971000,k,BAA584169C3BCBC2FD5DE56FD16BD03C65308BAEC5EA62C63E84D399656B902A +971000,u,AC7190CD421E3D262DD3A84AC82681CC4445FCF427720B23973A841A54792E39 +972000,k,C51A848CC6E5536F31DD10FB442469BC2BE9985A7A2C50D337563B00957F9A3F +972000,u,A512BDC8AAEB4697D39704A19C21E55D8E7650887E41665F18F6D1E972402362 +973000,k,AB22007B1C09A968D5B0989A11EE697C5F5C679180C06F8873CCBF15B5177507 +973000,u,F664C4C2F14E15395809991BF811534BE226C07520688FEB17407648CB7B9F52 +974000,k,B5862FE471ED0BEAFECBEEF6A1D59C0C295890265555C8E236A12A3BBBEC214B +974000,u,35588EF9E8EAF8A8797DC5093024060FF01D4C91DC2C07694A79D58575D3C30A +975000,k,C693953E1567837E4A2949CC7B8695E74EA6230594AD83C5880F282042D7DA24 +975000,u,6A2D65401902C21A4DD55CBFA03545CC0106985FFCF173A74EBA73D65A313E13 +976000,k,D5AB8B40C3EBFEF1CCE4AE9B11DA82D3D37DA27A44ED0595FAA5A35C811EF37C +976000,u,5954A2CF863B3D80893D466F2CF40980767327A30A0C356D971545A42A4DDD7D +977000,k,0ABF8185A72B5A46A87E3EE45915F21608FDBE4ED2A300055CFF199F0AB61570 +977000,u,5E4DB274FF246E3369456D5D2C82ADA5A6B22E03C66EE6199315AC1613FD510D +978000,k,7AA62EC7CBCE2CC34DBF48231F0BBC0044B1B14E0AABAA19647B98C98508632D +978000,u,D53931F9CEC9D0C12D9341EB5B7108B0D5D64AF6EAEDED948452B7F59DCCDF0C +979000,k,7F4CC9954F3145B3AD63BDC436EDF70DDDA546099598A71F258C617A4C7E3F49 +979000,u,FFFF4011830132BBD0CFB3F874FDFFDF403121388880C5E5FB5EFB1778FC6A34 +980000,k,5CC0F16BCB87241ADA368B175BFE635D0E1176199F0554BF87655E5A0CD17508 +980000,u,C144FEE75A4A00E5167DE938D6FBC9BE8482E6D2E533781CADFB81441CBE595F +981000,k,0F9FB2213AFC87A404288D001CA3EC2B6A56732E57381E307201DEAB937B0903 +981000,u,212E9982C158648A75896409C78B184055EA727DD4B187BAA0D5FF7317657F73 +982000,k,3EE7B4B18BD15F09E3F9EB837EA5D8B03E6E0D30C1A189DCDE611AB0D326A857 +982000,u,8C71475EEC94F1ECE7807EB30F8C9D6EA77320E641D5041A4EB77E8DF6F7BE7B +983000,k,7943A2D5985315DB94ADD6BE0395806C10DC3DD11EFC068AF38D46E989217F29 +983000,u,E2825E58C6A3386E0EF704425C6588EFC71FB4B2FCCF366D6AF32AE36D54995F +984000,k,28C11B18B31DCB78E04F4D2EE93572D6EE3B08B570ACA75A38BC1E30EBB17436 +984000,u,4274BA7D5EE34493CBE7FC2EE608585AF206F8ED0A0340A177EDB15CED744748 +985000,k,3C8E514211FBFB4182D0C4EF487AE263C0A9604E97BB90E04BF241F8EE1CAC26 +985000,u,E36D7E3572D4BE292DDD5ACF19A722412DB4ADFE8E5FF4D45CC6C6924FD3220E +986000,k,33DD2DB97783A196E7374D90DB75DBDCAE4F797C78C0B3C717BA9643A14B7477 +986000,u,4EA2F1C5DCD817CED5184F0CECA5CA878661A5844349E76E16BE572BA0DDBD24 +987000,k,56A69891DCED11E6BC25A6A9EBA59124D57B3059E477EA7CFB6BF7DEF0F65939 +987000,u,A37EBB47A1B79206E3D6B9984FD0490998B052DEC3BB5ED485C4334B2DD24965 +988000,k,4A87C7C91320024D8AAE5AF344A4A6BAD8057916AEACDC7543211E0CC839DB01 +988000,u,96FBDA1FB99CDC8C47D3E8BA0767FA3280B3BCD4BD78F1AAFA7075A1DCD40C34 +989000,k,DD2BE18EFCAA493614D841AE2D120F6D8424766C36A3176990E45884F4D50819 +989000,u,08989B10FEBEC25B0C62200A31937CFEE195001D34F8B2B6EDF524DE4634B018 +990000,k,C9F1775A99940B1EEBC59A5A513A2AE94C5342089D83CAAF1272C40D2FD2742C +990000,u,A3DE2790039CB360A78805909891A9CB04A889DC32100B5E15C8499AF55C2363 +991000,k,FBDE2B18A67EEB30F7B1BB017951B1440212BB6E30D5737E8E9E590C082D626D +991000,u,BBD9932FFB38808F53A1964F965C34A05C56BFA1EEAE3745D88C183BA3CB1241 +992000,k,406B4148FDCAA46309E0D592609E9A7E16412A610841690EBC5F23EA0AC01B3B +992000,u,B047A874681C09E4ACCBF01660E0B0ECA439D2CF95EE6B2F42633A3F8C80D30A +993000,k,67B7D1F31F660C998DE57C0881E7B6145BA9FBC332C83E9FBF4E2C68C1EA523D +993000,u,F7FE1519B65BBDAD9DDA247ADB77CF97C5468EE5C5A9B175617DEC50BF02117F +994000,k,D8DFE4796EC9DD962DAA76B42DE33D102B5EBC4F74DA519C8A1BD61AFF211B07 +994000,u,C5024B02088690CD9014B97329C715EA380905134690578DC8959112A4DC8E1F +995000,k,3B2693169C564F9432E316306EB9BDBCAE982B21921441B589E1638E41446046 +995000,u,EF755967040A6A3E1C29C27A5449386B42E8C7C95839247CFCDAE91FA942E97B +996000,k,73E1B88B0660462D8D40877E9E682B0FF84ADAA8312D933FC5C0388AAE344002 +996000,u,F21C3206C73D2C4BDE98C0A3C037986D8CB66BC6965A6E502CD0BAAF9B31AF0B +997000,k,DD0CABE418D443854364B73A27698909016E3BF67D087DE3F2864E27EC59D008 +997000,u,B296A5A8DB14EBF7DB856C813E7BC961C083FF9C0CA91D16291BA95AFD03DA47 +998000,k,0CEF31A301BE3C38A2F30CA1BB07EA7AF2B20466B9775A905CC3851A2AB4E27C +998000,u,CEF176617398F7A9D9445E132513DC9A7D78D4608501DF0846B05DEB8F190E39 +999000,k,F7015F8F47FC24143A782347C8FA04FFE119C85D6C896ACBA82072D7844E9210 +999000,u,6A7FFE1C87BDA9D2CE0A2130B6C19B2DBB35EA3CA8DDFA65FE4238A3C2802F44 +1000000,k,7C3911E0AB2586FD864497297E575E6F3BC601C0883C30DF5F4DD2D24F665424 +1000000,u,DC05988D881A30B30040D3192EDD8DC2DFB5CCB212649422C1D7371676B45B2E diff --git a/test/jdk/sun/security/ec/xec/X448.iter b/test/jdk/sun/security/ec/xec/X448.iter new file mode 100644 index 00000000000..b5f773e2a21 --- /dev/null +++ b/test/jdk/sun/security/ec/xec/X448.iter @@ -0,0 +1,2002 @@ +0,k,0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0,u,0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1000,k,AA3B4749D55B9DAF1E5B00288826C467274CE3EBBDD5C17B975E09D4AF6C67CF10D087202DB88286E2B79FCEEA3EC353EF54FAA26E219F38 +1000,u,11F1326FB3E434B8F7F5ABC6882697B39188CBC91A990C2C7A9EC41ADE3DEF4F2D1E3D4AFA53F6EA7538768FBE0077080FE1B6A4242B2984 +2000,k,7D088ACF29FB1A4BA5AE49826F4974770B7AD2F316CB4401233EF944E08C179642B388CE916E8D3FC3649F75B38831DA756CF5F1C518CE14 +2000,u,3C6CADC5CB0787F3D5DFF388FBE5100EE90E54298A57F2295D374F866F3F11B05D310827DC4D88CFAD71AA0DD409A52F9192FAD25A759531 +3000,k,0DCAD9363AF9151EA0F760F59AEECD17C6689E37439E61633F28D3DBCB8A679C75EE6BB932E6B459C39F4F28BB5328B4633684C56FD0377D +3000,u,2721C8741E1DF0BD16117BFE94661F645D58BCD4D1E6E83DCF7D5A2F4E5D6CCA673C25975065873C8CE02C4C84393CD2F8121451F9646B7E +4000,k,38028CC9A4E29D274FFA0BEDAD8499EA968EBE423B486EAC9CE60C250207437A4456456F820169FAF06D3EBA912FC3731CA94C49F91EE47C +4000,u,A11BE8CB1CF219C9EFFA63DFA4AD82F726F05AA68BBFACA2945CE3537EA0849154DE14AF8B0CE482056E40FC1E565706E047A22452D771D4 +5000,k,8EEB26619DF3A2E5AF823E8CC9ACB925469C7B0F495CED6306E628401D0226D3776E9141283E3B049656717D64AF4C2F58338A5D26CD2AB3 +5000,u,00021B7968CCFC703F575CF4AF05137E8528DED6C148CD945FC12894DD3812ECA6C66460F073881A9D22337832A2E95876A383AF0290B496 +6000,k,078154C0D27606651DA6350D5FF905FB6D0C9C411EB55643E385A9A2591326FB845C27C56E4824C9D99E3AF46EB8867CD4FCE24E7F3A5C15 +6000,u,F343F6DEC527BA0DB0A01DB92A5A71BA5AB41AD7591FD549FFAEB31BB0C4A87E938ABD1B6DDB14C0DE263CD944FCDCF625414E6B232A6223 +7000,k,52D3291414B7BA76C8A75DDFDFD4381ABD274B3E13735BECFF9A95CBB106BD8DAA8E6336258800003FB7C21FA680DBCFF983DA234C093C76 +7000,u,E2E02ABA8505F2EEF0D25AAA24AC0554949DC1441D3E035E6BCB0D0A4BF9A208C2333EBCBA281F548C7957C076A50D50053F72CD2E299CA4 +8000,k,ECDA4D9E9E52BD0696E3D48CD09A5ECB345DD663D17507FD371410E1ABC8952774EF3550D7EAF9386037B1CF07BF75B128B3D3575A56E94F +8000,u,06B7848FE505B8370283A52743087606C9BCB604CA31865DB1124C303F812081A3B42D0954E40EB38CEABDC13022B1EAF15C616DDA75BED7 +9000,k,D172DDC185A5EC19FDB6FAD16600D2C706C5C68629E50175E791CD8A7F5520BF61A90B831B79F10B4C710A252AD0EEF86FD9DF8BAF522356 +9000,u,F9C47BEC7BEC936AB72AE70C027581C9754DCA77084C26FF5B396E8F0A8B3A524BEF9835F8C815B17D123F6F1F91813AB7464DD327417A25 +10000,k,D8D36C7E154FDD4BD2733F1F6038891928A94C8F9F8DD6A1D02BCFE027E320C5F2008F7B4C37B3AFF357EC7DD884C2D43681F1AE73675C11 +10000,u,CAECA6A3AF262B7D123A6D85344F0901E34A0ED1EC0B653B59EDA0D4917702A7F035A896E253BA6F71812404D20D80B2C99397A329381E12 +11000,k,A4196A64A9F85B9924F0603950C5766927A8F777ECC40B2E3A3C2A3FDDF0F92C6B83F548AC67A7102796A7EF27B73DA8B7297A155597E6F7 +11000,u,A25C2D0DDDC5A526DE8D0CA12C5C07E333718469454AA0D2930963AD8ACBDA19CAEEE65873FE31677DFDA43EF02AE8F0D28706F87CBE591D +12000,k,399F5217280740B9C9E5FA01DA9D4356282F3B59111B412B2B3D42DCF36DBF05947ADB4424FD06210A2909331928C9A9A7ED148730A6D5CE +12000,u,410ED2FBEC143F2AFDA569D86E59BA3DD115950C1AD55376CD14342D549BF33FEED4CC02BA300BF8ABB7F20FD4AD60763CAAD822BD53F0D7 +13000,k,02D20FC9FAE331B0055EDB4AA56FC3049DEB328BBDD90343A7BC86DD40D4BABA54CF1D3892AD29F699BF042C1C5711135C6FA4A3653291D7 +13000,u,D78D1FEFAAD54C2497637E19B9BFEE17CCE7EF7D592B76D1BED659A4B624B0D54D7174A3249C2A2C93F1D82AFA89E9662EC480299F55837D +14000,k,04D828FD828A3DAE719B9A26787DA5E157DAA76949674A81DFAEEED791396ADC9D5189183DE054348E1B997505AB7E4E15D56312D1F05A5A +14000,u,103DC760EFE70E4FF0B46A12785596598233E7FA38C67620C22E22218559C9C6C608559ADF86DFF155D6CA051B907B371F6E8EDA379E448C +15000,k,895716F1FB3DE4189E52BF5FCB720DC74D67F9D542AB6995E819A9CD43FB5436FC0DD81B6012AC35EECF621C179C19713C176D6935C9848C +15000,u,903F3BDD2D375EA654B9868ED6B98633193C4B5011D05098FA00BC6EADEE92028E38545D0E6037B2DB474147D1080FB868443A298659640B +16000,k,D0B6EB1F0DAB551C4092DAB496F36CD8142DFB86C60201D5CDF6B4853F400F42F4739FA8DE393DE2B8DFEF8A4EB608430430C61328412B28 +16000,u,B8DD596E127B9AD49668880AE43CB1B5740C4010203FCB99858BB23DCFD6AC362A3ADB4219C3C0B1A433415718E8597E0A9595942E36A3E7 +17000,k,2A0C84D2ECDBE820AD189C320FDF48612D00A408C2A881750FFB090B43D43F1FFAE953BEDF3164F35A659A0192935D00F2D588B6DCC3C941 +17000,u,EA4C97B205E9C449FD6B5129AF6CD87A4AB9ECA6307BB409BD23F0D91596F3DDC194210CEB2BE4B4B72679BA2EC84C611A93DE2C2D4B021F +18000,k,783EF0C6CFEDC67669DE983FBFA327575F2CFAD94BD5CA35A22A84A15DD3663471D8F1D002945FD6F8D898C38EF6AE3A38704014E325D375 +18000,u,61599E580D1A48A9AA6CC2D01DD2A4897B059D4F31850879EFD74C2E2844F85F2CD93E4C3A096B43093C6406741243031A7D301035B78745 +19000,k,19EB3C3504843BCF8C411E87E57B3475AC2FD695EB05B4D147AEA2E85A63D5B24ABA376546D70C5C3BDD6047DDD77307EBB824432EEACFD0 +19000,u,0BA457C986106C0C0A0E551FA09AE65B832A106F9C1412FFB22609A183E18B4B85AF94CCEA0B885BE6212CCAD4283BC9A9DF9057CD8826D9 +20000,k,F8E5B654C465EB1C5292F0E0964E4ECD0F837484CE6C9DE7BFB8494E4D3AB3FA466DAB502AD0ADC503CCBFFC188933C4C348CC57629EFCD7 +20000,u,06341FF68E7AA52BD622297BF7FE0BCE3F2D82480C2B3A53C9D5D603B8B26A85B44E3E753E42E42F22DD67137F2F46760E59F8161605C965 +21000,k,81300BF98F89335613141447481C9D9DEA5A231FAE201E10993B8080CEEC256A95A5D95DBBF0A588AC1F34F1AAA92914EE53CC673225D0E0 +21000,u,8C7F15F95DEC77331341B769367F4559729724ECDB7E1FCCB04A7BDBAFB2A497C29DDA929A107CFEA4FFDBC9D9524D6DA49BF773DED9FE6C +22000,k,E6C78D2322248958B4E6B836CB420DD59BE408E9CAA8C27055035138E904EC76E24319023FA75812E82DA3208216B84F4741CA5041A40000 +22000,u,7E9E09FB3E390A64E61368975C64D1EE7BF2ACDF36C7003FCF98710299D21EBBBB934373A4032CEABA0A7DE76A0A25ECD8F5C1B8E8DDA282 +23000,k,0E6B7C4871E3550F50038C1127237E975795FA66C0AB0C3F94EDC268BA360DF5A82329D64212638278351B7DFB4DF707681F4BAC83DFB154 +23000,u,13406745537FDE5AF0B3DECA7466F1592D7556D231E19769005A71A0457B145A021D5A11FBF4DE6B7F8E0CA1B5E3C4F1757D6FE6E41CBE8F +24000,k,07A4C0AFD3ABC2AA0DBDF21915EB898A176149BCAE4A45537664F03E9805199E15851EB468E691B94380E70B432B8DB4C47840870CFFD715 +24000,u,D3787E16C0776B8DC6CF18C49EE62403F8A377F20A68D1A77363EC2EF7BD93F51F09AD56414F0647C01B34C169885ECA1BBC7C7DEF67E255 +25000,k,DE7C7BA166D2E7223857A511DFCEBDBDA70C337AC316111EFAD57AAB5F515AE0AF5D8F4E9CAB88C79C90BF55CE6302E75DA3AD0BB8678F17 +25000,u,BD138421784D5A7BC0D95590BFE1153B047F9A3359F994563B7F67FB79FCB0759E662752E87E18BA25152D845D6E7D68A1F091EAF272DD44 +26000,k,7F733AB28F49E718968375E88AD336018C9A77000DCE6986A7728B54CAA839DB75B42F7C752324AF3BCAA7B55746CC9B2EFD96BD1036BB3D +26000,u,CEF7C45A7FAA60C797733FCE8C76B6095FB5D6C887B499CFBE1A0C2BF6FE4C41D47D0F159F3106752BF7C60D873B46983C4B286F69595FE1 +27000,k,AC6D448BD1A755616C06ACA3676195EF9B40E99FBEA50880C44D7403B2AF66A8ADF95403C07344E53C4251F3256B2523A2502EDB2A75341C +27000,u,9B788F943ACE2C3B9C7EF2D07FE1CCB058E2803BD37F622EFB9310457965C888715892BC0DBC3DB3A08E5AD7021DF793980C38FA9AE9C783 +28000,k,143D9B5D122775057A6DF0F29F7E2CC00DD43519512ECB31DC333367E06FC4C00A764E5D0753E13FC55C15AE267312135BA3FDB37C36A0CF +28000,u,839E020B0CF32E7D4D6E85D806C6C8266EA3AD689A72D05244404779B9133D63437CB71E68D300534519EDAD714FC234183E5D45F6083931 +29000,k,FB80DA2CB835284669398C7EABEEA8455E5D0CD48F33A138D45FEFD85A6942CBAC424B5ECCF808D73BFFE9689170D9F39B38760F93213D17 +29000,u,AB7131B1410E0B683E947FD88D50C96FD6039D939FA3004DC7C5B826295B091071CF4B85316E87F76825C85724D0DB4ABBC0ECBB552D14CD +30000,k,7D09CD83B20926367BB4A77B2475A5C1DC2DF0BF3155AF98AF049072CA000349B1105C764C1733E1BA680D2C4F2439F434BA319156DF21D0 +30000,u,1CF019AE668C88BD3985DC20962A32F86D089638B4FAF542D7B047A75D00DE446BAA2F0A146DCD20A4E4C3B334DC506234E28FEB3952F5A6 +31000,k,4ECB38C75664C34D061FE6576706999FF364703C71FD80C7897B5F386446A06CC5DB3C5B8F7F9551EACD3DB6ACA44EBB44A6B982E376E7DC +31000,u,E03E854A016A549DA5BD54B49ECC10AFA94BD270831AB1D2085E7432CDDB7C0ACD60F0DBAA25D5F77E6801E57AC5FB10849163B88514337B +32000,k,9921985B1C26B21AE07FDB26E11F64BFBD1224A4A91355E53D171CE50854F8D4B2129E3194C022DD88BC36C781EFF112D217EA59701D66A3 +32000,u,0E4DB5EC8780EB0F7E7969FE77D59845B84B10363DC83B0C0712E2C404D5F69779398029695E33FAA90BF9CD54747F240A92497D6F036B1D +33000,k,73B1D40422663FAFDA10122DAF20A85CA2AADA4ACA01ED0160D51F0D873C67A06A3E748C7EDE68211D6A9CFA9356234671A6801BD4746806 +33000,u,CB3F20B5C9E164F91415196D3C3C3A2C037A546F0C3896805D45326F61EFAB1C3BD11309D378BA507706147D05581E76D30D65BF576C2C26 +34000,k,135DEAACB25819EA57EB54A015D8CE060546322958B35CD7545D4D43B84BC8496FD8EB9E9458E1843187C700102E13D87F62DFA9D452D6FB +34000,u,0E77FE2B46FFB5E8C1D2230DA84E833BFD778B2D82B3E6561D804B8B8D6A0240C1E126F677E015565C2F89DFD5DB4237EB7249140E602647 +35000,k,373A8833D00A21E06D751008CC4799EBAA7DA4B9B9CE800E1AD8445928DA5906430BED8665B07F9689A8CA57549250EB9D2FE501E7A52507 +35000,u,2075B16305BCD90AF3F2CD9D990BBEAA53B89C2D300DC9C3675C4F4F7DA51E5A9C1DEFE57487276CD1C8F5B4D1A6F0EBDB9748D545E8D938 +36000,k,7145C9F8BDD079F25708B6654A42764078324525E0D550B9AE85730F6FEC8DFD4FD005CBDC0F734E0E42F4A0A31E09FB3AD05E8F36121897 +36000,u,2D8365560B0AF5B173022D9BE712DE69233C95990980618FDECE6D92C1E2AF6FDDC93E688A66E8BC060F659F39AD54712147F88138E27F6E +37000,k,03F63B397ECFD859BEC7B4746113966C2E0CF8EBFCE226B828DD4A84F0FB41D86BA2C313B6E04BC21171EF0EA6F034905AAC82AC5BEE477A +37000,u,F6CD0D9781504293D09A3C3CE90622BDB777EB6E8F512E9AB8E514B2D6D83BF87C1B355F62F47F4D1D636107ECBE514818C5EF6AFD315939 +38000,k,E6B11C65B8CCA9D8EEFFEA995FABBA687B0272CCA194B0E2132624B321A186767905BA77C8EDE5A2CBC153D4E41D7EEA1E8A695E13F8780D +38000,u,9601F8BB0F08E309B5CE56E2925F90278687DB1678D6719350B88BCBE3B46AE69E9DC845ED554855808C9DC93B99F08AD0E70B98C00331C8 +39000,k,61BB4C6E7F03C84F3396965558E268024746E141D1EF008CCCFDF9BC4A9C249AC1985F19C298B1F0ECFD15E006EFF559FC3B97ED49DB2213 +39000,u,AF3A4FE2894A7AF4733B8E25BB45350FCC8EF1B919423C0FE2EA10AF6EBF94A5A66A2AF7C6A53F9D134B1ABA088C23557BCE8E4DC1396CD2 +40000,k,BF38C703197E001E98C706C6A197B86C006B8E406311D6FB8CDEE6F719ABB0FA733B3076F3A941F7E289B548EC6FBF9818989A99EC732490 +40000,u,35D7D46D4B0D8CF9555824363EF5207A04F6D23532F094661848DA7F546228212024DFCC8DADEF3E83A6B46688A8F47C35F5C49075BE99B4 +41000,k,E3920811B5FF4DC9B741AC6B9F25501CA5B7CD787094865AE311A5EE781824271AC894B48766089052EF9D57FB518B6153E41765E91DDF01 +41000,u,AFCC5433551E580BCA168D23E480D9416FD027DB09BBDDD18BD66940B5444777767198447A220325F7A59C7BC860C2A64D72EF24FD693C22 +42000,k,0BCC15563F959B3E0733E8149D74675B7189644178F6220D63F90699D402DD88563BABBEBEE161175257F0B6242D084A9BFF15E791BD0F5F +42000,u,7E2A02C2D8AACF6A6A5D9CE42AE1A4089475CC1E66446539952998E15A7BE7DA0579A6AE6D5BB521A209F6A536F91AAC0D7A85BC44EAFAAF +43000,k,9A7D0A1AB8BE47E1AB5A485733497282C3F006A51F22445FFE56B0DDCC11F345F7105595C517E47A5CE55C59878824B27CA5884D3BE0EA0E +43000,u,813708EA64AFC1EDF950C2461049E7C322F8626A026D7050F5142B665FC441637AC55AEA41C59E6D6BBD4A7124A52561CF4CFBF8A2A7E86F +44000,k,93FE5375FE3DBB147EF7EE010907F73F898CB2C3970F98186133F9BF535A3B2E62BB74D0F3C8149F681C7C7CC244B04A65A0664A50D58F96 +44000,u,FC96043DF2CEA17C8AF3970652FC47A297A6A815BBC46183AFDEAC9FBB41B6B01426A5497523700A0822E24EA8706177ED62D66BE1DB57DA +45000,k,D8CD0B7E894B5E60C4E1D5F04C46D371DB9099096FA2859E38542E06D2565A31FD2DC06D134EA5840CE5E4BE0A7C5A0A6EF3771392CF130A +45000,u,230B522274AB424AD92C0F18978A72F516015708B2ABC72342AB174A8E6E68F2D0F081DF554940A92C12A80D5A1D354462DA54D5469F0448 +46000,k,2DF7DDACAC320867BD503CD93602ABA2FCA1D68C7AE4E29B9DD685C1C925E9059432D5BE01D364AC403D0CCE08F74BB41B7ECD4CE7884025 +46000,u,5E92540E2C91E4D332DEE37582B4408223580E095F8AA0E60772A32889E7DE5410DB909EBFD55EA799B8B91EB641C975356242E60A0837F3 +47000,k,BA1CF289ADD1DBE69B275C4FF8C4EDF7334D94BDA7BDE674F40D73158C64C833663A63FD0D71DE0C41ACCA55602EBBE370CA1460C7CBD954 +47000,u,1EA32EF97639E23570D959C770181AB5EFB8679CDA61E5AD808B77E47C97ACD4A58AD06FB97597670D7D19F1990B66F5C658BF7AA4B1D084 +48000,k,4DD1023A61F5DE11E8398EF900416FB631AFF53BA1BB7AE4D62AB02DD7402A4338ACBD860C9C9DC901363DC481277926C2A2705356B9A884 +48000,u,699966CB1AD307CFC618252ADACFB8EFC9E22BB1512E90325C0ACCC7090690806BB704F2AB2B9F0E1C9AEA773ED620F837BD3F9EF5D1F341 +49000,k,61E234180A2062514BA735802BF4D9E5F04B2B20A90AC8DDDEC98D2153C88236C4BE612020ACAA2E8DAFC661B462767E9C3F647EE070B74E +49000,u,3A78849FD3E2FA28D8B729903F2C4555AFA5A33D7BDD78C4A0A4C0EC77FB458C2A5B3F8C349F04FAF46541A1B91DFE7C108680B0439A3089 +50000,k,FEDEC067BB4617D630838E775AEC5D4BE05FFF626A25606F735476F93F7BC4581D3BE79EFF49F4157A72669AD3326C80BE0E87C86B78FF5F +50000,u,D9B50753F95A323821AEAFD4DD6FF91DD6ADB643BA5817FA2978DC871B5DAECB511E1752A03EA41204E0F6BCE28FDDF568BE7FFA3C057854 +51000,k,7C99C4B606C8A826D607B04CDEB59461B338C18D47B1A7CB91099CB162691932033E82A453593BC4D96C7904451F7CE307F653E1DFE4BEE5 +51000,u,4CEE426402A208BB83EEEBEB20058EBFF0D0BFFA0F60F9AC71F4D2325A39B342886181114F1F5CD2531AE0986535AB3BAC86EEDDF45D7E3F +52000,k,133D2D2DA0ECE820225F6AAED9593018D7EAF3AFE72D524041C1C69FC4702E6AC7CCCC0E34E9A581AA777E759702CBCB05015EAC4E33A17D +52000,u,05DE90B9781BD9B74FC1597A2FD86CA92D79E536446340A744702094A9093CAD79C5504AB9E90F01245D761F8CA4CD7FAAF133FF2B28C9A6 +53000,k,161E667CA9D2F370FFB6791A58BA7D3C71B85A22119A980D09D07D73C720ECA49222FE2BF55F31D9BC1DA6C6FEA308EBAB5B1DD9394A27EC +53000,u,933D496C12BD9746CD1A3154C5DE4248E203104CAB4139BF2111CF0570664D16367B7C38361FB281CEC72F2A540F9ADB93924D5B74E0B3B0 +54000,k,E90F5C4FBFB116F295ED0383D760AB5A4E2F3C57879F1F3252F39953B43F4DFFE134A6B7FD56B89A31883FBA192B8CE36D108F1C44760345 +54000,u,0E5C96AA3897E4D8A4422E50DEEF23B42D7E400890FA48B497AB8F88DEA7E85A01F4949FC997BDD04FE5418EF1024CEA83AE5EBE77EAD166 +55000,k,E3B01EB635AE9C80F7E49140FAC222D9EFB68A427401AD7293493C15A98BE5D5622F276C7815B57947258DC5C3B589F24BCE6FE229F859D5 +55000,u,028F0B86399C3E10DE3D3A14F2B4D79E0D28175D23268D0B0FC150879705263025A2C20A340A3EF7A8769305238AE1316B45CFA184C92F67 +56000,k,38F1589BA779ADCD5C476CB625E530FADB98E12636C62F2057720DBF2380264E13D07DD99E63B283EB6D7F77AFFD369009F99562F86ED7DE +56000,u,4E5BA1F182254DF43B9223E350B53980267E7FECB65ACA5D6AA55C81642F83D6369CDFA37F0B53CBD142C18FD4CA2C831D4FF6E0F43B9A61 +57000,k,DD3D44AD5BD97FF3A637CD84793FB0EEA2511443AA545161355CC4CBFE9F10C9A67E8729D3CBDECE80BB1DF45DBBF7F14C08B4BE211BDC38 +57000,u,DC27A60A6CB5C37027DF7FDD7E071AEF714769F2BE7E7461BF5267F0C4A65D409F7C64B069236BD40EB8C5244975E56D6A97324F3125F206 +58000,k,FFD4B7C2ECAC00929207C951D41565E3E1CBF93103B2F5EC505E27AA58E01D6E3D35F902AEBCF4F446DF22D46E6FF9F4A05E0D10BB2630B9 +58000,u,E5075B6BC2ED93C12A0C6B9518AE247A08D2CFE533546926D80EAF48F02DFBE41F6FD0FAA9C267474017AF9F291BE5D1B5714EF207301CC3 +59000,k,02B21D01DBCD1E45DC4C0C5F17E04E25CEBA39C28216DDB341E578C96CE825AEFF42C4765629E9260FE47BC8DBCD6D16C4641731C8A05AAD +59000,u,220CAFAA6675C57D71DA684E04B80D80ED062C51C657EC4A70F8EB21F1FF4A15AEBD26FB1CF9D08484820596393C7845EDF2FD605209B0FD +60000,k,330BD5E64998ADF94E47D5844267EC7B5C49D162542C2527ED84407057D08E696991322760A30D909B208D7FB7977B5879F8AD1E06434658 +60000,u,49C9DA729E92E9961A82207D820E34D756ECC2F635D43B4A9947D85C697B7DE27A9BEDA4819BBFCEE540F20B456FC5D0470BF21543C28F04 +61000,k,5D946EC29A7CE42940481EE9029395830BA8A6FC64480AE1099271EFD6C2461413DD7F15F67D0A084FBA76FD0CDAB6969A615901984D9FCB +61000,u,7291CA7AD14830C70E19FD7FAAF6965459A375F67866ABFC0061BFAE5E92A9916750C2D10E1FB1245B905ABAC28A16EC7FEB8642D9A5746E +62000,k,BDEC42199242662F346A04A61D1F1064D6AF73CC17EB44FFC81C8D8870E40696C71E604DECF070C46F33C5A441B81CE8E4A7EF295CA8151C +62000,u,3FFAA71D6CFAEB8B1CF6FC641E2893FB9F634925D3BF5A8F486763568A5AED5282725F86561578C5F24ADA9E2B414748E38A8276DE00B97C +63000,k,3381892684FFF47E52635F8C5388B401C2BE8B3E3E0B4062770AA072F5B6D6092256C9B40FC23B700987AF3969CE822B260F831182D2FC3F +63000,u,6DEB0388A091A1100A7021512536A9542301CC980C372A9931F8DA4A000D8EA4F0EDE5832E028AF514EC043B8D2C9B315923BC50D6C9E84E +64000,k,574C3BE4E4B1D835CB01179CB85598527BF2B9FB318404CDE765FD693303008DFDC10C4D5B88B7612B6110389713EEDBBD506BBBB6AA5169 +64000,u,0F37F519C6BD9010CF0225B88BAD1C10172CEF5AB3347B5D1D536681B09B336A5C0EE005696CBD3840EECF6526BDB02FA2F5C24CC0D7792C +65000,k,2406B6609AB0B49F69CED9590348772C7641A5A1FB4AD159756878CF9C168846B2A840752D17888BD10D21ED026768C2AC42F69A271F3980 +65000,u,8A042D84A3D063DBD977CBCCA885AD0C250F4044D6C04811AF3287044A93CEC087FFABBFC236AA94F4ED99697D28B1CA738CA4A35D68F7C9 +66000,k,7B710513A87EEED24EDCB9A4D898EEFFC7FD5A47AEE15E2132C6564D8C6A6AA74E44F2FACD0451CEE62049A2EE950DD074ED9F2FD0971894 +66000,u,D9DF2EB6FA3989B46810C6A691DBE1796AE89D1F435FF022FD435F612431B044C503E3766533F71337D94A84BEA5B85D447348436752AE21 +67000,k,49F7931FE46E9C50789D2EA65D84CE6A396FB97EA156170F24E74FCDBFB03129D959E77F497014D186FE0FB28E960603744B90F7F7E73C18 +67000,u,9DFEE2C872091E005B7C5E0BF6D4A6100DA99042EC0BA343A84C0C7C9104401E054FF2B506FF37CFA1C6CD769DD8B591AFE46238C501211E +68000,k,8C64AFF10FEE69DD129F7BF26567E09A0EFA6C880DC4A9E11F3B3EB0BCC9EF3FF9DFE635EDB7FAD7EFA7C227E0E69B8795AF0A1F27BCB20F +68000,u,A8869CF17C528BBD5A73181504142D778B206CBF38ECA0CB19D8B0A67041AFDB279CC41978346B22381ECFE1715F0BF11E278ED32ECD3715 +69000,k,FE0FE249A7C68ECFEC7C5EEC7E40BC504CF3B2EFCDE5F104EE1CAE794E2EBF146CD9BA5ECEE340C128D40436E45F9507F9D3233858941FFF +69000,u,DF92A6210815E99FE63CF54875B4C3393AF7BD78A87ABCB0E5F1B33D5CE51845410BCEE51B563C2471E4257CA8D4D9B4201E3F9DAC6285F9 +70000,k,0F129441A4E5505935DEE9A336127A688CCB5A307233FDE59B5250AEE647A6BFA8E6ED09B62590DF1E4FDF6BAFBB00A59CED5A5EF0CB049B +70000,u,B6B4164BB349DB6C89F3E6EDF802C89B5590817C6442B50929F5696779018533E008C47640FCE3E30D3DD66FCB56D06DC23A870F04B557CB +71000,k,4F7904D10CF0CC3D169A22F216F9FB5177A192BF59D7E1F43D8C7D3D0CCAAADC5D00C825536441ED531B9DE55428A203E01CF23A4F9F123F +71000,u,8C7AFF2E72AD0B365BDE9317E72F22976F8AD7440DEEAAA773B30A57D8EE216DD68C79DBE58EFCD49D76C315713B044DB81D1B58A5C26DF2 +72000,k,CBB55C60770E557FF8F479C6EAF9F2D94031E629CC570330017E3695A3EDC886A63858A0FCEFE6A19098D1E573DC7FA533610397F925FD5D +72000,u,BBF86A54B15EE38C7572C792B487E70C4738E3FEB4E66A86F6288EFBFED7166FEDEC6646A9065743CA52CABD0722807D56935892C649D0BB +73000,k,EDFDCD8E2679DABC56B383763C5302B67F9902F69AF06707C1ABBB20B95EB098A0207528C38EBBDE7DD2BBEAB5BD80A90205785639A37F7A +73000,u,1BBDB2331FD60AB670BC89728E45DC365680C2D45538C1C0E4A31644E954F53C85724E0405FC27812EBFC55B88937645A96865593B1562CE +74000,k,C87747C63B131A97F217108BDAD86D24BB67A914ABDE7D122B5CA271192B46ED90F11AC81252AEE969C6564DB7A5CB61BC9A5DFA6E24362B +74000,u,FFE68ECE7B359400EE04DCE663432E5A3DA72736EE526EFA4507076072F7A435D13200EEC436F529BCCB052764578BFE37488CD313B0D6F7 +75000,k,BD196A98956D3C90BAB72A7CCF8F3761BE2B6D8AEF8B3E7B2F786355E2AE118D06C5B976F1A90F99ED450F99E2F6CE8BE8E9C00854848556 +75000,u,86C6FD99F5BEB57AFCB16F452E89B69B192D34C9679E60093CFA5D61BF8F615CD1727EDD4BDDA1AC42559AA53E6190B78D57F00DB61A290A +76000,k,5B080D855E76D6039D8B5F6E4E725531B45755F294FBE5CC1D6E01020F6B116FE5B36344B90D5DFA04267341EE5B7335B577086C56B68096 +76000,u,BBE652DFED487F4667094AEBAF191AD0EA8F769576609E2C322E056A4C058AA2D37C0255D69019ABC7CECE965ADFE36614F384918A02A6E9 +77000,k,813F3BFB41F5ED30DA1A28D8C0D2F4E0747E6699FFB6DEFE05F774F7C8EE1626FD66E16A3814DA29B42B063C6BFDD0F6F0A781A54707AFF9 +77000,u,1851DCBBCDE31A5A7FD399CA28662313D80B4224BE843E54667BFA13D1E4B6E1EBE60969C2FB2631CC5D712815F46FFBFCB714B9B33CE3E6 +78000,k,E94B5B9F113FAAA851C7F588552FC0C68A32EAF682B7BE8E90736F3F6F67D618D6350941E1C085D47676F12F1CB52E436D478A831DEAE979 +78000,u,1D61FFA94FE80F03997025BC02F816478CBF6A5E0BFF4EE4E5F8364CDB9B1A3C49EE1DF1725CA5A58A17130BE5106CF9A681C2F5EB4B0924 +79000,k,8F65DA910ADFC7473FCEEAB729AB1C9674F5302E590911C8ECDD9A689FF4CB53B62E93852AFBE369D02845B5EE05EA0DE7F5A06086933DF5 +79000,u,C9F60DC7CC0E369E69223A3F18CF3D5FEEA9F9D3198F32110B7661C89BE9F744AACA99DDA2A4DE6B55DE0F7078BF58E4EF4020F221E72A96 +80000,k,4531D1D2AD9BBCDEAD3BB9568422348A233B6AB11D02D84E642A19B08675A3AABA28B7F54E7BE0F239FF354BDFDF8EE08BE74B2B7CE1AC46 +80000,u,0AFC9B3576D9B6151E1AA22F8137F95C4BBBE957EF12C339ED524AB8028A94FAC4107CD3ABD7DF6975CF375499ACE1ED35A718AEAE1A323A +81000,k,02E1DFD148014EEEFFFEA5D65B25E6CB475763B287210493B7A62BD8795621356DB56E073E460E1C95A61210A566EB201A9CE3750F7C0A84 +81000,u,68F6697ACA7F54FF4D3A2FAF2FCB137B196D3335FAC3A4752A61CB8F752800B2B2DCF0D9B94F9D8BB9664FCD0D864C8E115D6EBA82D76099 +82000,k,ABACEF14C8F76EFB59B9D05CD632A7C955C5F5DD23C22CC35FD2C51725CF789F9CFCBEF645F88B5AEEC6507D9D3F4DCC27F25B00768D096A +82000,u,CF1C21719AD02296935096EF536806C5A96CAFCAB088B22A2028E01C20F26A05666244ABF9E2DF25187BE5547E23784E2439797061DD49BD +83000,k,EB12637967E3E1B268774CF3E60FC6191E502368983856F59DE7ECDD182FAD243C2AB4FC1BC38AAC8FBA4EF2ACCA8D30D1653BCF52D4DA51 +83000,u,EB28F0C9053EE94F66CD9F1B79E78B33DB2C65296FD529A0D2D893258A19DA4F194FDE6860CBBF41E8B7DF2E457D7DD449A4E68AEE516983 +84000,k,00D2F613085A8C204C5D7752070D34A1B5644A6D63C4AD3402BFCF178D79D5B66C9BF3A7D08ADA8819717436DA46B8D5FB9C5E6B8AAD422A +84000,u,AE274A2DC79AFC8C9F1E103DEB980EECF43AB3290663F3DD95BD7B0D2475164C9A95D07028A05D650F93BDD2F20FC069305F02D7AE393FC8 +85000,k,AFFAAEC199F0BFB74E87F1256BE81B2CD59809717A313A6AE0683F24F15C8F03187CE3885DAEEB16C5903AC3B3DEF3E9AB833BF98A5878A7 +85000,u,99D0C82B9AF8BFB4A8B28C1F0679F2D4FCE0F31AF224FBF57236946E16FDC98A0986A58C7E5ED6269D652BC1E9FB25D3CB63D995EFB19C9B +86000,k,8BF8D92F7F96C813A88EB04B7FD1FFD441B20B62837D5F61C7E299C4AED7E11BD4753A311BC21263AEB1CAA1B771883E91DD3254FC0D27D6 +86000,u,F032AA6543297A78DB46062C35183080A721D481B6C98C01CAD39B758D70F3CB516406F07F46CDA627F8A4F116D335667682B9C5763A9D43 +87000,k,D1FD60CEF794B81BC2CE1BE9936BFFB5AAA6C84A3BDF337F3B2B1FB1560F61FAACBA819AC15B24B23359962C70DD72BC5B79A6B9C7E62C50 +87000,u,53B3DF35D9FABD7E647533A7F2625DABCAF1E6764F53598C2787EDD9D34E13AA9C57D46C64CA8CE4F54A7170B9712E162D96F446166D18D9 +88000,k,D409288314210F46F1D5EAF17BF6A007398C9B4209F244B65133BF1ACC708B92C7AAC27CD147F1A68239CA1EEB6357D62918F32467446D0E +88000,u,336006677895F9B45E69A0C0F0078C1E8F9F08659088E6E2DA175C9AD12004BB594143AD85CAB1538AABC19FE6B0818F0E12A6F6CA386627 +89000,k,4071438CAD5853956C5813BEE0FBF4200C93A36DDE09C2E5BC1EACCF366894A6CA8E0EDE13D9F5C0E90820CFD79AE64575963ED6B6F04C75 +89000,u,A2500DF2F7D444E64E50D692AF6D9A73B3F160E30F90B8DF624846F108EE29517043CDD37D0757AE9209E01C62B131445B1AE7ADDC3E1455 +90000,k,E2036DEDE9E1E3EF286E4CBE42F47D01C68A93B0852757BA10BEB90E795BCB7CCB92AA91DE5B1872762FB2D08B3A0F02EAB27ED83134DEC8 +90000,u,D6EBD6B963DFA134A3DB2868D2547AE960C9EAFD08F2ECBEA8736B537C9BA284C94F1409C400E06E7A750A85F3413B90DB1E4AEB2079F618 +91000,k,3D19F6B80D0DE7929A4270AE7CF4CB21E4A28834547425A753C3E59B9C1C028CA6244EB6509230DB95EB21FC12AEAC2D72224EC7817ECEFF +91000,u,1C5D8CE997D7325CE4E7F4C7E2DD36D7A643FBC190FD924A382FFCB25473E127F7829AEA6623A1BC065858FB5DEB236559B0884C464D0634 +92000,k,CA628EC9A14F2B5914A7C70F6447B50B926D3B82E3FCDDFBB5919E794F8DB8F107ACD6A5CE2AC0E41371B12AD60137498E1C690C214DE1B0 +92000,u,1835A9603ACB7DF04FE3A316A7A38FAE743C4D60CA49653E8C1F08240F0D7D45509CBCF595F7E2AC4BA78B61E99E1AFA451ACAD715F5DB44 +93000,k,FB11241D87B3D6F9F9A0FE9678B5E6707C66D35603E3DB1719C52DC827F66EA3ECC96263CD2C237B31E02305141FB54698AE1F2E6B94E53C +93000,u,7051DE04E3BEB954B06A3404006AABE8350273C4C679C6D41229FD424D03B589D63CEB18A4591DB8CDE1AEBA4D30BA8ED155BC717D99E40B +94000,k,596AE8F405E06E49DFEA242F4415B21701C230053B17969FF7A1D125B479AE6202125D178C5FACB5285912F2F17DD173E21D954E694630E4 +94000,u,E664DDB502A79ED2B4D80474AC7F9D714B99E22D62875305246F3D113503B06C6DF744D8E9BA0FC52CB5147370FA6EC64F79FFA25FAA57DF +95000,k,278BA0F0338F58B27F160E087DC4D9BCA99D86233F143AA6D8416143BE0E181AADDA710E45DE409865D8D48782E5FC42868E18C448206A45 +95000,u,155EFCC39C4DA0F50A0CFBE21C362F333886D24149CD937607CDF105E6A0CF3D04E8FAC8BD030BED502B44FE35DA801174DEC4313191DC5A +96000,k,05180478578E2A5171DFF43735004C49C4747498D004CAC733E3CD85416CCCF2D0937E63391C29903A93F815D068D9CF12E010536732EB9D +96000,u,3C0AD764804EB95DDC4932C843695A700938EB329FCC02D62C205D2563FE1454D746DA9A59BDF666CC2CC3FCE560CF4EB27382856756CC21 +97000,k,81CC5B7CF20BE73750350B469F3712AD9C01BF54164A97C5EB4EEC9AC4A94DBF2CAE5C444F8E7CC52A1A7385DFEB167ADB85E60CEDDE7C97 +97000,u,AA96359C7BE181B7D09D4C525FC8170345DA184846E48CAA68B58E5E5837E36D911E4AE7FCD99B0DA7950A49A4311D557215AE5F295B980D +98000,k,90A1D2C50A78E70F80ADEE785A45E24F6F7F5AB4C301B381857F71BA0B18ED223B040E91D12D3573D6D35F2C4CABF3150042AE7BD7497CD7 +98000,u,B953FFB95E0E7F12F5BD825F9A1DE19B5D0CFD5B00453A86E878B066B093D84DE2C2073EEA51ED8EA84D79E85DBDBEE93C465C9E88C23A72 +99000,k,9307050B39BCBC77E8A107D01CB0F83D6DFE521D2AD40AC2C65A02DDBB3A4E2859E57139EADFF48378ACFB545AAEA68B21A334E758EB5D58 +99000,u,2849FE248D5722AECE349DE2272FD03472AE59144F6B58896B73C0DAFB97528037A597ECA2BBD68F68A2573585260697B5ABEDE0A3AE1A13 +100000,k,48DC17EBA89DE7B6F0D60CDC50034FB5CD0285A7638F9597806B0016DE4110CBD658401C428835794B3D64C4BD074274B0A5BD43E1E1D1FA +100000,u,22FB490E3AB738C9E6A89D99FA9EF438B952446A3DB90874E08C7C64E67642A2D9A359D2B6EEFB5EA7553D52A03E8CF078D34D2CC972E6DF +101000,k,84594FBAB21A825EEAF161288C5A969D02D2C92AC347B152A02C87BCBC41B068F12F23112B20B987DA9DB73474930EA920EC03511C54F7D7 +101000,u,C8193E00426F373091A20F479C3CE46C5DDEB5E3B3999B59141EBB66EC28FB089803C1F23E997DE1301ED571BFED626EEF96FE913569283B +102000,k,C24EDD23573DF9EE7544EF213AA1E1065E87911C7BF70ABC8A2A25C59795DD38ECC5107A2B0A3B2235858B6A6784F2237EE9EC320AFB1458 +102000,u,E3FAC3D08EF30FC872E32644910C9D9364044F8CA778194B5FC5A530D1C49D11118A3A91121D0883E550B595D2194CBAFDDDA2CE7CA2FE55 +103000,k,F210F157BA1686C8DD8BF619C9CB9BA902C51339F307F4094CC24C6CADC9FB739B8A3AC7A581CD8D711C949FCAD67433984BFF521ED9799C +103000,u,D7CDA13089F1FEE3AB4AEA8328040A029A74E6E4841FAEAF5742E0ABDB59F3B089818ABDBC52A62B50AEF4E5666FFC3C22225C457205E4DC +104000,k,2051D8BDC2982AA6F84C499FF94825904781B12B4BFCCF21158A989148A0A270645181AE7542F4C248C7178972DB6FC808E4AF0CF81771CE +104000,u,8D0BD0D8CAC5B39F3DCFF54A9A0E9BD7AD8EEFF49082EAD64694F9984CDB465E188FE715DD9F309CC3052BE4E8D183B724456F3823B8B2E4 +105000,k,415157D2384A0EE599DAD6CACF73E1FD3F58811223DBB8D73E3C02DA7988089D544A93E7D284C22F3B2D015ACA0AD2A9F02C11168DDE2BDF +105000,u,692597ED787BD83A8DC296579172AA0BC0286B5FA7F8AD733FC215854FD1E2F54652B2A7B78A6329F6559672A38AC2241BD94036F69847FE +106000,k,22DB85DBE41DC1A741F2568DE11609ADFB7F75FC81A86565D45AF7C6A3F0EE2935D25180585026C308C163B86CFC4D2C4D9442E6DDCC825A +106000,u,097690DB6CC198018C4F6365304D3253C0751CD10A24698ABF5BF7BA2D3505E68126A7A9DE3F737CF8A8F68AD26AD69D5057E7FFAC60B4F6 +107000,k,B59D69327750559E5930DDC9D6479C1F5214DA2EAC093BB2BB3367AE0F6ABB6C4E6E6602EBD99F5EE341214C82F95698C0936B8B6839BEC0 +107000,u,8A529CD858567656DCAFBE7F9B8F3919E1FEA3C0BDDFF547369A84F2DE7BD0E10C932A9F18E2E18AB291836AFCBB0103C80FFFF1D88DC477 +108000,k,D6C5ADF56516F3F2FA1A54B6D71E8D08FD5AFA594186267C3CBE523135473FAEE22E17A27EE868643D1C8C671DF9A6A9104AB0EF52EE21F9 +108000,u,9975D1D36079F3D79FA42B2401F6A472116C964F640600D40811156F110E5AAA00D4BA57F3DD503A2F550D2A1CB089F97E9B3F0D632EC619 +109000,k,92B43F84599D592B51E0B1A99EED938600279DD85A1777759B3678CE745CBBE35EA12871F5FDF42F3D33F823FD2D3234EF79AF1570B03E28 +109000,u,28EC54FA8D0CF8ED7161487685BFFB7030BF9B2671EF2CCBDBB0985CFED45ED15D89B2F4C4AD02424D42BCFF0925DD55991C84CDC72E60DC +110000,k,B205BF66B2C40C633A560A283B686C4C5FC5F817869AF82A61ADF2AAC1D26D88CD00E26C1762E5F4EED6486BB5FDB9ED1BAF3E8ED2F27EB2 +110000,u,F35D7A88892EF7222010C4B0217D42E4D912D2F481CA2A7EC9C1865CA07CD93F194882C2FD45B33C10E7F424F3EF9ECF5891E3347F4FEA96 +111000,k,3BC39F28C13A58A48964C654647FB30E477E6133466DD594F3D4097AF16004564D87B5033D922C683573F7A12E550914B5BAE7A455BDBA82 +111000,u,F2F9C07735DB221145CA6955C19AB0895EB30F393FBDDB59D5DF9E596555104B5943C7EAB703E25EE33FB6E6B2F8F2F700355F6ABB623042 +112000,k,82F0B0C78CC91F37B585D81B3024EA6B47A50D13DD1AFDEBCB1A35EF4060EC37741D1319DCF4BC35CE538F6814E553FD952E1F65B272050E +112000,u,D2AEB383C96C542BC93156B7D0A730812927F1E95F055BDE662A659319D185F3162F3C34736BBB6EF4DF7832670E397444C5CC23AD9BD96B +113000,k,ED6CC36C13697A844601DD4BDFA502BB01C58CD201A4EE67B269519107A71A54581DC1039A776BE39070D0FE00097695E7AD8D4D0C3E90A3 +113000,u,AF064E0B21EE0C5DD6242B893379311B1B6A33420844813908FC8F1692279B764564F2441D0433D5ABEAED04691CE047618B483727DC0DC2 +114000,k,22FFF5865BA411372DE8A7240B0EF9AA37B7FA0ACDCB32CD4588A8C711D9A34F12400D9ABCD2244AE08CCA528A3F8FE0ACBC2A3D747F6742 +114000,u,99194BCD94CEE4B282A64703FA778328533F6928F6690AACE1914EEE593D480BE6C3F755D7C13E73E30F27D977903F586C2ACA351527EEE1 +115000,k,E452179EF80735FD73A41F5429DB1F5AA03CCB895F492B0B487469B438366A989B07AD2AFEE9407C14D9B68FF0EFC53C3970CF3A6C7A088D +115000,u,D546B85C441C5A23837F9A5C796237CB8363A213AC375FAE6B63B211DEDF37B0F2C5125D327455142AF336932BC3F3E8AF273375D6DEB6BC +116000,k,A617FDFE463636DDADDE4263F7642D7ED5690C624646A1A9102E694C1087F4B0318F46F251E20EFE30CD23776283E11515857964532EF2FC +116000,u,F72AE90E19B450D813F883C075362EFCA33487F2B523E7783442C15B4AB330D6DE129A9AD6C12C1A7A4831019E45C6DCFED917F5C723C55A +117000,k,91F43EDD42E2792D109E3707A8149E3743F1B5983EFEA5B8463F293C9E73A681827F60FB4EC0DBA98CDBA42E0408C4AE622D7343EAB33EEE +117000,u,99C9590F210AAB95B47BCD5C8AC3DA8AA0324E9C42EA31DD0860575AC55AB90E7E8228E759B8F54F05E362B079D81AC137E1C73B8C60A95E +118000,k,5D7163842E549D393F1D939BBB58AE6D89A2C84879DFE21F43C12ACB67198D8A26AB02E6FBEFD5DA28A39570B88BD97CFFE0A7A54C61EC35 +118000,u,80B362D542F06909D1B27A0B45CD67F9A606A6AFAD8E0E64297A997E3C18EE561E21E3DE87CDA038161A6F546B45662512C1A8C5EE754612 +119000,k,33649F19F9BF00610C0AF7059C77D337FC14AD2E3B1D5FF27D4F051B07395638654102E51ABAB4A6E0E822C206A21DF2BFE3AC2FE60CB937 +119000,u,20E9CFB023014F999E373EFAEF297981F2A699529D08E21E088ED5DD0E783C18F781128C1DC2AC1E686D4BE484B20D12F5F5F17135DA2D49 +120000,k,A39485D9E33F8608451C5281F7CAB01BFFAA5BF638515FE7C9ECECADF09E000239A2F85872A0DDE4F4DC484DB7FB5ABD3E78E1D824CDE947 +120000,u,CF94779B8CF0C963C1AAEB23D0B83220BA398ED70F96BCDDEF99FDC5E4E93EFAE165153D862F6453DC3460A8D2FFEE6399C39421177C1CC0 +121000,k,449BA28BDEF1B5FDC0F0CEDEE319E0C81F0FF1049A095363416B2F71ABF23B0056EB87E0DF50FD3DFEA1860140332B270242CA9E3A6ECE05 +121000,u,CD2C4FEAD8AE70F42CAAD8D5FDD91145DFF583248B4CC12343B44176FE55447B2038A40D8742C5385A7BEE3E4780F02B98F6DBC98E6C97DA +122000,k,85204E4F09EC0E6073B8AF92EC6C2B2916C2DAFB0A95F8D3A660F57CA447C43D032C818B36A552A0087DB5EF9AB96797BE066313458D2D7C +122000,u,CF1E1AB67829C9FD2C8C270BAB4E82038B47469590733BAB91325F9C44203D8426F21280DBBCCE671656CA474D64D0E29D450ABB30836043 +123000,k,ABD257808C26946EED9875FA5A88F7AC2ECD2B2D06BA95C25152AF79B688A2400A72A31123FBC19D9866634BF0C8A8E405C889B3237F3FA0 +123000,u,D91BCF6612ECD224FDF27C6B7647241D9579102A1DFEC039F7B9E3798B1919F0B7CAB95038FB6739AEAE4D67A6849A720A8131AC2C2AAE4A +124000,k,02F4CF67497E279252ADD80D609CA5329B94306D8C898029CEA1A2657A976B51F83FB8CAC9B99E5FAE17E51C7DD9137F1AD3C19F970820C6 +124000,u,EAEB4640B4DFEEE0115B589D82014CE09BB15994EE5C71EF1737BC22C9D8600757F377F1A8142AE0ED10C3AF0C31839530F37902DB563F36 +125000,k,1831DFD2AD13EFECB913C582F4BD9DCBB8E7E613FD4E824C69E767F8A68DE0AEDAD87C9538CA3B00BDFE3FC2F6845373E2DF844214A694E3 +125000,u,FEC5D6BB277A5694F22489BBCF96215282EF18DDA51E63A76FEA39C5A4ACB65A56196AFD80633606864A4423DAE96E880393A0E8A2B400E9 +126000,k,2C696EE8A6AEEFDA73FDC241B72D8D1FF83487319FA80C3CF603C506B747C3B78570846954C41C160857F6FB2D17F170957718C6F518C782 +126000,u,43BF0FC2D402C7389EB6ACF873FDA8B330EAA02D9832F837149DFD5BEE7FA96038741F06A6313905275CDE5A15CDDC7D70257468EB6F364C +127000,k,85EA268E1E3BD6CE792BB8A9F5E534C3CF268EE2BB6C53E495C17F4F1876583F82D6DBD55D6634DCE3D89197080D5F42C8B6E043F8A6DFB6 +127000,u,9F1341FEB6591DA2A9330FBE434225541341F24C877447A16C35C9BDF8022A668B502F16797AE50A785304AED491FE5196910B397DD7ECD1 +128000,k,D80924874AECA8546332D1AD7014C0F23A2559EEC3CA4E054A119C9C017E583417DC704041E15B8113A467353248EB401E6B4A3F0398DE81 +128000,u,86A24A7849E37701875E3997702C262EDFEDC8BC6DBBDD4286F0B559136EAA536BB33B4E8C3F1DABF05B9A5AADDC4EBCFAB602D516A73925 +129000,k,E1563AE0DED2A974365BD354E3EC9AB8A569806F5FA012E2957E2FE2504B9508D73BEFDBD04675451ACC7E5B4C5A3FF1F5F8E61CA857AF4F +129000,u,2A1280F063E10D7FC8D249E8F8275F960BD4F63170EC4F259F506218CC85FEBDF3CB37FCAA0726BA3F480C42832712573FFCE5894E3206E8 +130000,k,35A1808AE06FC004E2F1C16729E37C195B49CD231207146901B8DF159B47A3280FCC0CAF886B89D0415A1A5F924C5EBDA6E1D38FA8CDAC4A +130000,u,B584B4140DBC04DF475EC47410D77C80E44AF767004CDA11872D84195944F532DBD68396F592FB392EDB797A9EAA3F1819B00F4DC7DD8843 +131000,k,618C9C5D9348405CC7FE9B6B618EE54D2624A61CAFACB7DCA1313167C1AA0B26576FA859143611844014E8752BC94A1B6DFCD9BC18A96774 +131000,u,4EF19DFBE2659EED365B270CB6742D68208EF668D762DD03F5239FC5261F3753E29C6FB8E777C19D8536B1B5804786D6FF29492555FEF2CC +132000,k,5F70708399AD48E4D5EF65EE932B06B7A1753871BB1705B5C80A109BF73017C12FB637B37B5CEA846A85A17182572BDCD0A7CE8E667FE903 +132000,u,73265EF47BA3070C9EB0C1B8618FD02A6C8BF4528E92F231665E351FF0EFCE47FE41E62B17AEC4501FE286291C1405C30861F63F595C52B0 +133000,k,65563B2AF423C159E1736C34E5EB5A57613AA987BF7B0E68827A1530A72A5A63726AD8FBA0872E456617B4B47E9A43A4EE817DE39C711D12 +133000,u,D9682A5D46C25E2B309956BE21B5F4EC53C9EB8E73A3B27B3368CC9FF9063B972651284906C0487A2A147EB35BFB6F1804C47D17AF0196F8 +134000,k,121F6E3DE521C1A2F00112227FC9BA6A2DF9D7449F2D88FC11FDE39D16ACD72948B4BD63EA4DF03A0C13683B2DD97CE0BF9AA7E5D4F988B9 +134000,u,F0F47FDAABAD36A63B273312DED6E5E8D07334E224157C5157D1A36A82283867949E1AC430544F99BCA6BD0C570DC2001EFE974F71B37E1B +135000,k,4D9D8DC8D5F799612ED4A9211944C61DFB76AA9A80D65B211DBB1CF5840D9C483BD390B3C179E8059CD9773A3BCD9EC3E160E19F5697BAB9 +135000,u,9780BD6408210AEF84D91E791D987497CEDFA579B229906F20AB49FB1B33480B1A07426AAF1662B374F6E1334E7B1F8E9C9086D1325DD727 +136000,k,34E891ACDD8CD1861A9C6F1BDDD2F415D044E438CED4C29E93E090EC5955B0E550B333F2D4A7EB1E6B320418820241BDB95FCFBA60E3467B +136000,u,E5548ECF3B8715A1C5936B2F998A21D00EA7422C021343E8840F5CCF4554E8A599B8B75D1D9E41649E77BE835AE98BFFEEA5E9BE38898F72 +137000,k,D2DE3B1A9597BF02E560C94A4D5789B19295254353443DF20D804DFCF7C621F93F5584C49BB39F3D6EA261DCD0FD1AD66D58C1B4D457FDE5 +137000,u,72226B74A7D459609C394517025D506B4A22BCE1B8A452E48D7F3F6851A891680EDB6B84689C1E3D15B79783529F062E556325310D29EE5A +138000,k,B237FF18F0FCF773AD10DF545A0F6C38B8F9F34C238B3BA40A661B0FF45C5CCC1CA7837D22353A86DDE795C52172D789F1060891DA5F0FC7 +138000,u,E2F903874770F07BFB941CC0B1FE7CF40A0C8002C208F0369FF2E5576E00CE128E8E43FEE26B4E61E3788D8366B210A83123B791A71225C9 +139000,k,07183B05692B1D7D85B593E0454511FA54185987335C9C30D806872E462EACE540062BAD085B4B857CD2F2A55211755022D176BC3919CD58 +139000,u,F31477CC44795EDDD24D2165466E4751EA4056D4FA0C78350F4FA78678ABEE658D35197DE419DE7095E8118918EE0FD0F0E85B63374E24AF +140000,k,6D6AE4FA4FA320EFF2599B5D23ECBA5EC21E88BDEF2D8D866971EFB6E24BBF9D4D6B8CE47BD4766B841B58402E1AC5F1B39791BCB6A1D285 +140000,u,A4A046D8C2D562F68473B15ADCBB70F3D70442C7AB1AB21D262ED9AC50F2A7614C22FA994382950365B23DE1ECB1D7BFFFBBF4638CC346BC +141000,k,80FE0C759AAD6EF7C781E822E8955065C029D14C73E4234B7C22E72FE7AA8DA026E4945F48F1A8455C19CE23DA1F68EAAFF15414B57710F4 +141000,u,24BF43635037349D6C5B7E74BB0D472FA7FAF39796C2D6C806A27D7B362C0E9396243D62248B0D86E4400EABF217934FA35ACE3BA69E50A3 +142000,k,9A81CC474BD0F98A5F20FC5E653E5C2D7B04EEBDB3B79ADE7041EB8A2293865CE2C9912131B7BF7BD4E45F1B3437460B6F83E9C0B460C6E0 +142000,u,A7C9717456A69F399A0950F2943A7BB26ED50CF58E418BA6FE23A148568FB5B63D9F4F70645EDCE0E8A655E07DCC93C3889DEACD0209B1D5 +143000,k,A06623A08DC9A66109D141E43CA32751E4B64D557041A4970B033D2CEBFD508A01D3B41CF8B2AEF94D57EAD53A8D075E2020EA82DF827271 +143000,u,41DD8C63308D76F10C2586F7D2FCFDF117DD3CD4C9BCB1A6CA93A229F3AF67C0B37A545065EB9F4E1FE81B95BEC2E75E8A302C1E0CA3719C +144000,k,2D1292AD214253248EE0360096AC4594751789694DD9ED4A1CE5E73461CF861E22C0A08C53742DCD711D59BD8EC6A970CCE2ADF56408BDE0 +144000,u,B2AA77773569E79ACF28FB9ADFDC107CAB34A1F0FF37A5C892E35E8D39C9E3D2DA8E7B61B6D139508A939D2E9D3DBE250355A69E98474249 +145000,k,528D4EF878BDB277C2765D0BC9C4CAC20AF8B00C9DDF100DA3BF234A5B7858E4C9DEDCCC1FC36CA940987824C8316987DA0F216F98E72EDA +145000,u,C44DC59DB903F77720CF0622E19C8A75E2900E7009D89EC114A98C3819609ADCA8708C0E323A0C040A83B9E287FAD6507E1F056973696483 +146000,k,9A0F198BE84BE66BE5FD8EE3BE3C76EE30FBD95372DD64BA6D5C0A540E0A737E2DB885E1B681911D0990E2E282A72E42FACC126985A4926D +146000,u,374E4D6B67EC2681A987EA2901D07332804F434507C4CDC4C62C450972125990E587FC63BDCFBD32CBAFE0AB25B2B4FDD7EEB358547C16C5 +147000,k,D978C469A6450CECC834470A92EE51203461D1DEBD262B6FBE56707330B3FE4B08A0238450FC9AF6BF7018CEAF69AD821C58A3DE67F29513 +147000,u,D9BED9BF687B755367E38C0B06F7D3C992FA3D7F6B3D75C8E6A96731A8BE9EBAC38620B9B7472A262522052FE5670C535B5016EF9F4B7788 +148000,k,818CDA1F13F314A21557C9A43B06FAE40F8D3F9BD7889C23C69D4FD8B88723F2EBC7A295A9F4A506C5A3D3255ABC194C3B2C209E0647F3E8 +148000,u,CFD5027D2E9A5D1F4C6249C8520AE8AF464E036F07DD581D6F7786AE3C68700DBCDBF5402359FCBF0B6ECE665376ED96DF13BC558FECBBFE +149000,k,B7629B89A948BB867D882CBB831F16A86B107A9DB4AA0476F5BF8DAC3A4F7F2383DABBD8041D82186AC26CD4DB69335CA1F130F85CEDD0CA +149000,u,75BCCD8194EA2817B7C98BBAC35157B72219FDE466BEB0EA881DDD3E0BFEE7D41BC326364197A0A89E7E92FFDDF516AE671F5EBC344315CE +150000,k,E4BC5308F539F1BC2B58D166C08A7F1E00053D835BC128B61DB116AF41A150A39E11DE1CD0C9C8EE9D3297457A32BE961292A579296C6460 +150000,u,159C7CF61F21AF154122402032F5638BA7CD31F31CB6D70223FBC830164B5A612C7CE4004A9D1B565071CF22D2DC5C7D21D8749598892F10 +151000,k,0804123A2696C61F424BB7DA30497536D27E96B7C7B07FD90FC4909FA4142AB739A4C294AEE8C8C22BBE608D9A784C172B40F5CAC554B20B +151000,u,DB1E69A70A820C6FE1B359EBC8535AC559E2EBF29FD9228D3853EE5D5E2FCBF5765228DBBB3DDFE6CB256B72D2E9977AB63BA74FB7C92525 +152000,k,21CB58A894DD08668A705C84B7EACB7EECBB7D043C202ED79FDEA52C9F04F54E40D4C30082FEB04513DC8C648B0E0F74EAC87C7ABA645E2C +152000,u,B89C5C0BA5A97528CB9F6F05860CD62BBD82A36B83082D8533001293CEBE607E2617974D099093115B09F77B4F25BC626D459E22B3AB3652 +153000,k,027A648F30A512C11D8277C4AE6512FF501638E46081717B4AA72D57E8B5ED4357FEFF8BAC78847BD079289E421A3B6CE26A43976236B8E3 +153000,u,2AF57FA09ECC04421544F35055C641775F74BC98BC6D3BC78093FECE102D3BF4253B9F46AA55A1DAF3CE907EA6F60EFDBF8FA3018D8C5548 +154000,k,2201FCC406C92F8EC962E4462EC07CAEC7FC2AE766388B20867105BE59F0C427864258D5D7D05D68E12B4A82CD6847975A830B70CC52807E +154000,u,B67B8B591F861BE8B8EC3A3AB1D156B6140F8EF770576FBE36F9E1640B6BEFCE100ED3B65371D93A347F8D05811E4478C796185FE4809CF9 +155000,k,45E34F45687E2DF0F543F1D90A0AFAFFC8FC7CA01CB3ABAF39326999ADF5BFB667C52293E170CE251F35DD1AA7AB8AFFFE8117D9F0D18B5A +155000,u,64C93BBD5EBC128705DB967DBBC4382A440F201F19A12CB04CE71242BB1288BBEA5E635C107A15B4146E2BA3D053F20BB2F26E03EC1A29F9 +156000,k,0CEFC2EA0FADE47591F02082D8F8FAC93AF67972C2C021A4F76A9175EBB03912AC861000652C1FC5254FDFEE8BFA60D8E83F103EFA12AFBB +156000,u,B40E1A13FF08A0694CEDACD3A9D9DA3117277FCAE8AF8AD2FCAB182374682F3A88D62B9FC6750716266CAC3364C296E6F56ACD8229BDFE8B +157000,k,2AF843335F61CFC455387D4FF64F535D30CC61365FC5FD652381483169A362B4FDD747AEEAFC9CDE81109D4007EEAD0E132884117A3890A0 +157000,u,7E83FCFC1521DFDF70679442A5FC415592E1FFACFB2B5EFCB62BD519FEC0CFF8203EC39582B8A6487EE1C5B40CAB92E471E827A8B438E981 +158000,k,81D51725C9C5F64D4AAE0F3FC341A943B1A82E0B5CA9E6C1E36D74F5215144805AEE43C4A2F1BBB1A4959EB8D9656470DFCC07BAC9DC84A0 +158000,u,28E74A6CC3FBD742429CCBF88148F96B61DE41C54362B666345F8A4A9592CE186539FB31F106757C4300617DCC77221F165B5190AB4E8796 +159000,k,0282D32DB3589E79A7386F3ECFE4F1C6DBE8DB50824BA729D467B9026516493E07069684B8B192AEE4608EE3B1B8703289E2B353ADE36709 +159000,u,EB6253CA896DB3A87AE0F966B543E132951600A4ECE4631B912F9E0003B39838B8AC5CCF6C37EC3C47F2568B4CB9230B030EB1FC97C81EA3 +160000,k,BD4FB6C1ACABD591C4B1CAE360CD356C0A5B9B8F59355C3C2EC4B1178A74C4933DB6EED1D74F5F3A689B9DCC864C2B018C95BDCB283A33E4 +160000,u,20E64E37BD3024C0EC8F7653E43E7AABDF7375CE40C9E1F9CE483CAA8C7269630E6CD0824285BB4D60BDA42DDEDFB3169D87424CEFE31205 +161000,k,9795A357BE6B20BFF89359C705CD23A2AE845D89B90BFD619FCD7AF4909500471242641D16149F25C64400C5DEF29939A26AA85E1C1513EA +161000,u,426DD7FB376C4049E3A4099199A63C88CC2316EE0E5EA89EE19A1D6333FD3C296460AF699D4DC60AA7C274ED6A7997DE97C1C280273FE946 +162000,k,18E1362A5158B3C7D1CF70A48E6264F1B220D53790CDBC0A5AF2DBE1EBCEDE7A0DBC0DC6E49BC241CD21A1CD8912B52EC176A197B27B8F8A +162000,u,0C9FA13A9FBE1DD8E1E28CF599ACC2705BD27CA63271E483F6ED11A087445042CC0651181E787D1E4EBCA232CA6998D7CB494E704675E37A +163000,k,2E1955615C03C95FB07A7C70354B98CEAC41CD2951713168825DEF54E65C7A0A863D461E1ACDF85A974513FA1B849C8295CB0BE76A81AA6A +163000,u,0B55122194A97E6AB3172AFDB713187E3388CFBB94CBB6C3B037AC53B3AE6EA7A184ABB1863762A42BC2FD5C406235445A40EF09F5E0E163 +164000,k,4E51DB2D8DBA1588E0D03E86948DAD8340AE07CE0ABFB8B115DA0D4F4B9ECF0E7BF6B4CF3F96AEB0FA4AAD2BBC92144F536F212F18687FCD +164000,u,60B2C5BF03D511625C83A2F8E1FD0E8AA9F84CF743D935FC9F5A6312F49689A705C243C75DAFC992DF52EEAD1B79D392AF53007AB1D5344A +165000,k,E7262A3AA3F608EBA6022C5572C2A87EF87FEAE12A856D69642EFDE88338C8A64AE8671A513AD73E4EAB8F3498FB06DAD362815E83A8D8F2 +165000,u,7B562C1C1F33346D59D9A65F611589327776CBF8CDF7CED5085187C5414385F4A20C20BCA75FEB0D992C0C02A0021849E2FBF87FDDBAB85B +166000,k,A07C4343193D34DD4DFE1DFF7B516C52DD6F401A734863AD7297158E741733DE95E0EB65CE08CF6EBC36E10D03DAB5CBF04B6B0A4F1E731C +166000,u,E3DF441621E297018CB6C12EB7CEE52C0BEAAD8A76EE2AC9666CC7D268C03BE1BDABB901DD9AC8FE06732904047BCAB5234826DB257FAE58 +167000,k,07807AB7C3D199488F62B6971F71EE4459BD4579437427B90615C77E501A556615C316749CEFBEE8BFE2AD3AC85B8C2806C40AFB551914E6 +167000,u,A55C569E162F755409727C0A72E6214969B5D3960D18D402D6E685BFAF0A41139D2772FB8498E16B68173296848B8E183A16E4571EEA47FA +168000,k,B11502C956D82591B13F3B12BF4CB0696343484D8EB57717F2AB4839CA815B8A88C2750FBC9DE7064C9691F8144605F572E933BF0D3D7238 +168000,u,0F9B86A850EABD351BEDF66C6A65336DD2E6CF5BA532A17F0EA9F2DF5D06D26D95C051994827844AB71209A7B4D69824CCEA03A98B18EABB +169000,k,4486AB3202FFC2F74B48525F5CFE81DA180CE2811E5A37E38C091D00C0366A3C0BF4AB8521E33C18EDC98D4F50B598E2C6323AE1332BADBE +169000,u,0744BD9189D57EDF2502487D19A7925972A6CFEE7DDA40E8659E05861637D579CDC82046268A8FF2D6D0A6667C29A83A189D40B50DCAC7CB +170000,k,90FC4764F27369D92574F437552910BB10B33050CD5853AC5DE29A271E0BC25271913FB09F7996AC82BD592FA180256FE9D137C17556B1E8 +170000,u,CBAFEA26159B80D8BBABA43CC876D3397B02E5F077A4A38402D162B6260C26A30948A4108E3DEDD2BFF19F6745911BDBAC925B9A604B5303 +171000,k,5AF98F8186C284078CCA2B8EBA9EDE3D95332B495032B5D0247C1FE1A827A9AA008E7A676FB45D6207C9EE166B7D886B3D3580B91491F3F2 +171000,u,59C9F0BD9DA8EBABDBD2C90461F9183FA6B2BEA4214A62FB8B9357665452BE73D1683BE62A2C7B376F0E321419ABEFB26DE9E8C0A6CF4AAE +172000,k,285EE16D697BF0C536BDA18721884B92AE2DE92694AE3A65DEC0910D80BF90F840AC041F249F6FF5320A7DD54EB07B496B640082650001CA +172000,u,A4D812973112F9B9E1B536EB278577FBA287AD592EE9AA877FA9B0490E61E32545F404C32A0D3E04C2C06371DA71F8557ED3397A159B402D +173000,k,B6E4434191DCF28C9CD273844D74D33B56A5646AFFD10D7BE7ED62D76FD5FB0B36F357474CBFC739D336ED4EC8396DC8B482A3F169E05513 +173000,u,6F2F1D8C317FE97B8758457F2F99D3EF71E71AD7D5596E8C66B6BD136C78D99172B332D07887915EF23DE9C8654CA72A46F9F67906DE6DC7 +174000,k,54D725CB6AB17A177130D81F18BB858EBAC458506A3654676F00879379151D9F19473E1D75AE84CD2500D80440613AE528E56E45637DFAE1 +174000,u,A4B216F374892E15923C12A66967843722D3ECF5954E75E2E0D87A418918515B99CF53AFE7F9DC9126B7E720237D643EDB5CB4898171716F +175000,k,AF3F0FE01EA5A00E68C56C101E059288C87AD8609C96A1DA056B851407C9410FF06096403001B07E90E4B77FC5101ACD82E56DA10E7947E3 +175000,u,A85EC574EC6FFE5C4F14BB1FEB5230F21700CDC2C4389A6FF47DC6D3E630C6CA796CBC532EB0B695A8F33C8C7F6F9C5890515BEE3B66C32C +176000,k,13FED87D38C519E5B9C910E6A572477E43E3D92F480352C27BD83FC998113AB0D4155D9BC5810B60739D6F6448F72F841FFA3C9D34A88B55 +176000,u,1AAEE5C1A4A822DDC801DB55A3B7754A1B4C5046316A3F72E24A78893520368493D0F4E7A586291181CD3B27B1F7CB880725E98E3B8DC1E8 +177000,k,B7D7FEBF5BACC14925FB4887FA69400926A2965F215D214D295BE9A0C54842A499E5EF92745CEE9062F2506D5068D7BE689CF64E570F7F89 +177000,u,AC500E2A37EFBEBF147EB27B42700FDFBA294C41F66E89536B70879E43BF3BC38A2CBEB58C0B40CCED8EF3E177CC61A446E9C6F8B9635125 +178000,k,3878717639DA7800BFD823A8F1D3A27963BADEC708445B4E4B1A8423E191D81B5223956454FF422AB39D25120EE74649E0386476BA85D164 +178000,u,88D6D2C8F57AD064A5480DB2023802FDB33C6C103E437DE430A70D8C2C47023B1FC59A063F3592B4E4C98848B2E07B41B9D09A0C07CD86FA +179000,k,76ECDD7A71073405E62B74F9B32ACCB965C42D9DDF6BA326F3F8E08541B8780BDC78D24C85BFE74943B24E4BCAC73945639461B31646EF8C +179000,u,A5768E94BABD5CC9E96D1B5F5C33E8E1E7B0545C1F2FFFB9C737874FE78683AA1484AEA74AB66D0B21A53F60E7ACBCB615BBFB5D2EEFE505 +180000,k,F5934B5F81F47CADB1F5C53DCAEE5C581B4AC484BD86CA1487F47B6705239FD45BB8C8E23BA91D88FA4E0C10CDC0E429FB0CE3D08AAA4369 +180000,u,AF1948440EB004C78F5DEFB260B6C4DDBA6B5A25FF9313962C66A423943E01C817E32E26FB71AFCD2BEC7D472C2890FB2EF792A77FA9D944 +181000,k,AE5405897FF31648C4616FE6848C1E3C0760D39B80C1200D31750F81474AD1A95C0AE15C045187886C689B333CA20FD4B4A6F8766F6DD8E9 +181000,u,9AC426C79B3B33A14D0B793F7609E8363A145B01B44102B02D825A193976C425E464FB789FFB5D822A3CD7982654E5236150F81B56C44D5F +182000,k,B158F73932EE7A379BB52F66D9E4949AAE7EB15D2D6BCA9F109B38575CB54998CB067C56DDA25C9D14C9DA863478E41CD23DF2F46A59EEBC +182000,u,90FF7F846455F736DE8EF0225A64B3AD57E06832E16013ED70BD0D64FDF67A9B5359ED9F65C18123EB35B9C1B49D6BDE5EE01C9CA4611295 +183000,k,11579EE9EF3DB7F6F8D4A5C1EEFD46A0E867D82420DD02BA42D97094056BE31429132A3D1AD5A7E525522593C6E6FDFE6EACAF956D67210D +183000,u,04ED6991863F6877C2642D6A812479920649C144A1C58845DCC6C2F37DBDFBB0303F3B50B18AF1FB068FDF05B39AAF1F6654EDBEDBD78A39 +184000,k,FB37504533CB2D666FCA558C2EA9D35B4B11222F5C87A40D06545ACF5A687735EA0A41A98608CEAB337071372511D5E59F43C8F0540D5B8B +184000,u,33B22053D3C1CB6A3FDBF037A9A53CE66540776939CCDBEC75340FD8A3DEDB30BCFB2C80A6D21DE7541251C70B5AAFFFB1D7D88D6BEACB0D +185000,k,2AEDB81BEDE2F281E384084AE9DDBABDF8C1E9F7B564C05AFD6131B19C11D054674DCA22D557CF3D73D4A573EEE687127C88C2FB6BE65B84 +185000,u,2F5E2ED7721CF895D9A6ED1200F07FF83AAB5420A99A925AA4BD6E85C39B14C5F4DC21A6535187BF73B50A2094F4CDB6F2DB697309F8F0D8 +186000,k,1DC44F21F2B46A54C17801815B75926C1B04842D9BCD42D4427DF54EE541C29624E51C3D901BD78BD9E425F38B74D46FFC681C1F523A0641 +186000,u,5D5E1F54203DAE423EB81D3A825E9168C4457BB9F0B23EA2EA2E86ACFC2031428423CF2553D863697E7528E3E2CA88D19EDC09A54452836D +187000,k,323E5DB391D5EA28D4E737DA20C591466AACE3FBE8AD4BE8DB6901D67F0A08AD0B7F5291D328061EE2A510775378A5E05CD92232C0003BE3 +187000,u,83C05E37FB16942EB37B64DF05765E0DA38C1D7ADBB23BC474686DFB8A3B060C9E7229667F87222362E825D6956B660FA8BA6C92A4375213 +188000,k,E1019A0443B11452223AE7F0DDCAFAC3D44F07E6486DA99D80D8DF017334DB42DE4EF5F231A3D79A687292AFBDB5BF70840B04C087B4D2EB +188000,u,62920FC7866787B6EF38A12D3D9065A233E0068ADCBB73DD537360F82F55179B88347C75DEF77002029E36C7D0B2E8A2468ACC84D1D70879 +189000,k,4232862192FB7281E07FA5AB2038E548FCE5E877B1E18EBC59569B5F63BABB79B1FC60FB4116D196FA635631ED3885D40DF94D2557C95B56 +189000,u,BC666A9AED8094D55F3234B34EEBDBEF304907D3BD29BA5F58A71D689D7FD4BC693874AD68213509D82653D5F39866F1ECB86DE9D156911A +190000,k,0B320F0741730941741A27434A5134C88EA1C98724E249EA0A54246D08C26B78AD21A6C87B014250159395DA26C4E311B4E7E0C566E1CE4B +190000,u,93F548CCEA2D44DCDB9F939154ED61679E24B71AF8899B94449AC724A4CB01B3CCEDCFBA4AAE79E16D062083CDF110BA8375F143CEC0B22E +191000,k,0EB949154DF3A177DF3DB6FA495B7EF5805999FA5374D4B76C1C0EBD5937505297A131A3D60C9D61491CC9705A515C351923D22B6C16BF34 +191000,u,7D13B59451B3472D36D63824107A4EC2C917ECAAA4292429E45973E81FE808A71B8BD5D8D3A4572C712C4CC3C7FDEA51230A8905F95EFB0D +192000,k,64E2480E371BBEE778426B03103B7CD8CCF9E92CA523FD44710AD918271BC7EDCC0B6CEE4BF2C23D8AD2FC3FD2A08E2B0003F3E81FAD791A +192000,u,8A16D1FCE89BCA62F0451CE4410E1BDCB23197302761F62850C7E15ED2844168F9A24E70F89AA15D3444EAD715E9F2486722781E1D74A61D +193000,k,25A3D2DFFE12DF8356296D86BBAEAD34D2EEA8293D5151CEF4E485F05E1E7F02CD2243E8AAECBBB3DDD20BE67A416266BC354C715007F16F +193000,u,CF5CBDBB2081975E48349E8EB3DB67F048B846FFF481CF5FF274774D2850549F77B28F5CF9BCC69FE97831CD0A02103E949EFA858CDFBD39 +194000,k,1C3490B9CD04EE16865459465E6F2C35CE1C906316301080C3B96A90AD2FC5B1F1496348077C6FA56BA3ECFF50BBE1D73580D65F4F62430D +194000,u,AF25C2E14DFF46DAB5D8C71B8DC0279A318ACAE2B2A05A46002493D74C4E64A01C0237A5BE6F65B7E13D4D709F0E636F2FB762B8D48FF8E7 +195000,k,F1C0C301E26DE6BAE0C7B953527FF4D3313E2D41E5FE91FF71E89B3E7EA2427A918B603C18B2DC89A13CA732BF7B87CFD2358B452AE0CF7E +195000,u,BE4D059A6E7FCCA38C89ACE31C6F18C6270D78BCB1A8AADA92953BB99D7C02490B1C372B9381B94B560FDB198182B7BC5CE44AB202273331 +196000,k,2B04C2C29988E1DF3AEA1BD1C5709C4DD15B92CE74A372FE82C8F0F53656F9999D251709C8DFB615D78377B0CA825108284060AE42572D10 +196000,u,12474A421742679E814E887123442090A19E219B95C9431A9E16B85877A862FC877E9B2AC44A8C537306A8F78E4AFF39FFAED5C0324F5A57 +197000,k,F2C5F4D6C65D3E4BF1A5B4A9AD0210FF4E7C25A16DEFC0A4AD47548C2EAAB3A4DB167D8CD23D12EAAD5DE7C3BEBA804E37D3CD4457DE5482 +197000,u,1A35C9640560667B26F64EC1523331639115AA65791DA9B0CCC254CDE39905504FC3A422ED1A095F9A5B753E25E9B05FC9863D70C7D56FE2 +198000,k,368912E0C4363BEBD31DE28E8DFCC3F28335C42FEF709C0B4FE1EA04CB0B510D89D21099BD375CBFB939F1B9A5598F05546BDD0FAEFAC844 +198000,u,5D92BF8B74CB2FC6434169D72F261988D2B8E880C597D0941D0F6A93A49A6674BBAD9B915A2BA1881E535E00FA50C6BEB9526D4AE43CA8ED +199000,k,3608F9D031B3CB887DF58B19DD5BE9C1683A9718F0A8486691DC4E432AD91E54BDF29A41D31FBE2321388A6D2B553F010357731D4805B7ED +199000,u,BAD823816589ED01C4D7D7AD7E2D5CA5A5AE57D51475DC1EDBC6669742C05C50A58FC7A3E1EE16EFF4490E6B486262069963650A640B98E7 +200000,k,E86697A7D9C44EBEA5AF18C0D21C593BB4364257263C425B3351F7F68CFF3F5E847121610F92EF5D3A5773825A5E4E5B00EE7F7F107F7EE9 +200000,u,EAAE462D502E411810E74AF6AC0F228192F377C8CBFB83FE6BB42C3986B3A255253619F271B3C60B3462EF1EFE868CD95DBC5E66F28CC2B5 +201000,k,E1F3015283F249B5F443433205E854A5E073062FBF6B650BDF3069293E01BB3BEF328AABC1E68922C942B83CE546829DE5315FBAD998E367 +201000,u,5E06F23028EF3374A729EC7D71EFE121CFA7CA2C8B2100490F7674157615B4E4BC820DEEF86C7C60999A90A050913544A0429B9307F93263 +202000,k,709241235933B2B882A10AE66FF5BCDE39E12500B23F5E5738DC35D1385A2A0607B9C5C20E28E1002F4FC4F73052ED676B88FA453D5A12DC +202000,u,9AEE86889B2E669F6B9507FC986671ADCC14EA17984FC2D98296823F86A38083AB17EB277B50A8AE2E43CABCEAEA282DA50F8A496D7323BC +203000,k,986E0981DC70E4FCCCA524F0A4EDEF45DE4E56339A2A24ED3398E3D99A97F95FE48A5AA781DCBE6FB8E82276E3DA7C1C8252BBCCE6A5FFCE +203000,u,8513888844D835EBE427C9974B7333E0F2D3645727951C868CCFD6E607E9B4E4F4F75561FA6FA4319AEFFB86F403F81A79155A963E5C2663 +204000,k,DBC4789DFD69F6FECA7462E1A68F8D60867A78C1A802AB1033DF122BACF1B1E43295C337B200AEBDF70802A3AB9859D0D5E84FB8C0284B90 +204000,u,BD63941A34856E409B2944A56117BC3FE307B4CF9B02A1CC3FF8A2A5885A89A86B9A8647ED0D05B4D5510DAD2F1E6F2D8D887F5A12AF0A52 +205000,k,8743B3D203A823C9B712A8843448D6B920214CB07E8DCBB65F851D4844672B2AEA3ACBF31CA669F0F3E1FE744BE2C61370DDB5507284F4B5 +205000,u,F91D18A8487FACDF2B5D5AC5CFB6E45500E86E7D8E53412987ACAE7E81BE24A4A1994778D6638F3711FCD34C997363E7B2E698C4F129CF56 +206000,k,1ACD7BE623630D608A68B278E7A0646F60DC9168CD30013FD9598DE341B14F21CD51B9A78695190096048073AB16A7D4D2E9D1B85E5261CD +206000,u,D101F798194B92D9FEFCDE69E75D0F0BA7AE2262BB06405521A3626C94EBE943ACB3FBC27D73D2868D4704639518D7846D7D6E1389C68905 +207000,k,BD2E39D0285D84698F7B6896DB39570FB4510BD96611BEBC69B7D42A4A8A5277E917A1B13168C07C0103E3BAF8DF0FD84B069A0E6150F4E1 +207000,u,A6D8556CD04F6FB8E189D4CE2F2DD91E9CD2DA43C1A21E25EDB60757FD11A44074542F9C2583CC67E48E340BD62A21F3079BD19B4CCA6D47 +208000,k,C74510257E007FFF3791861AB0193D2C12BBAE0B8D982777A7BC950C6C0990282F73AC142A34B13A2B9245C623E27E3CC29423F9F5B1D147 +208000,u,DB826E1423F917F3FFB8F3B1A26829224DCBAFB44EA42FCA342922CC430EAD2EAE5AC9F1EF399A5127F8F902181E5C31E703EAD6073676F7 +209000,k,54AE305C884DD5033542A8B212D420786D95C653425ED6BC1BE3DB92D0655F3F8B790EBF8DD82E0233059E51E6B896346B825D13356897A4 +209000,u,1E7BC4138A6FD0D47F733538EFB90CA465A628A470D95F836BFEF9F494704FFBEF2265606D2FD5254002BBB2A109D4E6680FD7E75A2EF72F +210000,k,D1C07858B0A9BECD03970E00521598480E2BB6ADF78D90504E474CAA0801855ABD1CE946F7B001F9CC4135E57BF47DB1AFF6833599C32209 +210000,u,2DDA272429E19FB8730BBA92D48BBAC8F363B2083EDF964949F5299B349E2293692D0522F76448E573FA564D9BB6AE29FB74E9C51FC87452 +211000,k,0EF32C7FBFAC0351F2EE1BC3B6005EF339B6EB1B07FE1B2BD41DC755B9FD9B8DB87BCCC47CB320898AF440B773FD3A367BF85C5F9AE06413 +211000,u,B802C441D216348F394852384CBEC4DB2C9AB01B3653BA30F3DA38F30C52DFFA72690A868A7A46F6164F486109053B7FAACC4E747ADD9BB8 +212000,k,AA899FBA31DD21790ABF49A81F857C28CAB37332C28AF09511267D6D40087632073B454186BAFF6B7DA2364374DE116E1CE06B0F46143F60 +212000,u,74F900D263D75014242805C6469B27A513FB2C14E4676E263FBDBC28CE997AFBCAF1FEB4792439406B3D362FC959BE9007745E427A8826B0 +213000,k,5E5432E8A98E10B4AB03A5A840ED704681CEFA7AB5C6D4ACCA1F730175968AE399BCBCE52A4247049E2B2E558899AE85D02694209D8BA327 +213000,u,42DFC4CF62C806B4ADD47030BBA00A2D966B542E0BA09B2F1C5E3963A9C1202B9BDC1AACE24D8B58A53BEA0EAC9C348CB0F318F4E25F7B02 +214000,k,F317BA915FBA5BA256CBFAECF34B5A8B2E19CF06102DD0EEA163A40A65F42257FA0A6F5B4008624A30C3D1BAA17D53B662FA60E01BA9C63B +214000,u,63A028087EE7ED6FC6B0E8C0DED89F984F61A5D35455796A0D4046C1B362C3C51B82599CA3838F703986EC32801BA3E05BF22DDDABB8ADB9 +215000,k,3569443DA289DC96A4AC4908A7B2752629AA8A2A44BAB000149E418C168D0272F5B5ECDB1A287641AED3451A4D3735C5B5D14EF1BFD7E8C9 +215000,u,DB7A39B66986EDBC776D071329CD34D14B12734C3EEF3C5AA307EFFDAEAA957457EE9947E84F5082D59D477A4AEDB068A9D0E6845663E37F +216000,k,FEEB8C5DFF744D1D1ACF2E4E5934E1B040C03C1D6CD33FAF9F0653FCD7EB3F67704950AA5DB587B26FC9C489BFA7B0705190532860C91F54 +216000,u,7E671FAFC4EC13AE74A647126DFFC8102A00F08EC51BA48010120F03F781D08F734DA9764875566DD7D4AF00802B2F06F715C1B8E9E24DBE +217000,k,BA795F4955AC4F9A5CA555B153DE35CF8F4FE387AC9D7240420E6B7C98DDF7E60976D85EC2440C092C1F0971CF006FD1CD3E10697241FB13 +217000,u,46DD6F35922E4B01647DC9D04199963C7120FF3A506DED854F576661EE7266870C4DBBE374011E31ED9ACF978E3F2DFA1EDE5260D552D861 +218000,k,32799617DCA2EB06DE796C1DB1C08562AE12438C0E0E2A105756FC4BD0D487F6DE041231433EF20BFF694668A3D7FFC8E785C77A9270199F +218000,u,55BE2C15F7232159C971718B74C1C15020B1BC18EF944DF909D32188D51CED16CBB8FF43DC94B1F51CE48F89C9352764BDB7A48207C3BE2C +219000,k,A492557053025E52010EC1C9D317553A95E5FDA2B3FE4D9CDCAB6A5607C866E09FC284EEDD5AFC778F9CD4C7EA9C530E9C155DD3BE4FD556 +219000,u,353E518B340473BAA28A6588E39F0FA7A1857A4BBC0747E3E89FCBBF78D4263C477B18B751DDA7F0CB25D8066066C1B12BC6F4BB0C6B54C2 +220000,k,F31EA6D466D865A418A63E9C307DF347B498E218E8CD2AA03742EE6264E57A99892BC1667731CD690173C02623FA50E88E64ACC78DA00F2A +220000,u,DEC680C676C882F1CBE732FCF70F72970A1BD363450E4D2D24C1DB034CDE9445F9CA4D8B77743BBF79F70AE629BC4BA0374756076E751744 +221000,k,A6E0D01D62A4E2A6CD93E9CFC93DE44B26382C779C475124F8BBD6DDE312918746B38380D35AC0F35DBBD360A3B8E5484A6AC9870DBCD5D5 +221000,u,79069D3208B661E40E6E52B36ECEB98A4B0B0514A0E20E2F3B8BA9AA8A926032215655C1B48FE85FF164B96C4BF7FF812F71761D07C7CC2A +222000,k,0D6A112CCCD4AB8AC670166C292CC3E4DF1BBA7A586764C3ED1E1FC32A2ED7BEAB4ACCE31EBF1572358226FB97F93A3F84EE150AB8997E6D +222000,u,0158502B6005994196BEF68151637CFC2465362DF355265C1510CE9E7356BA948D9FE2132D4BE70DC665841E1A9FCB50E40D400B5BAE25DC +223000,k,8A85933FA53C58EA7B29BAABBF459BCF0EBF42A0B56702A4CF53D585F50C91342B30BF9C5DB61EFFDB08F706277615ABA2934E7D83B25197 +223000,u,1511D7DD3A2BEF2A5DFC2A92F050D0C9C036A0B4663B32972B2016301A0C938E95DF14A169620716A3A6019370DCC4BA2CFC7023FABC3029 +224000,k,B30B3BE5ABC6325BE1F427C01D604FA330317A43C4DED4D8051449AC728652CF93471F0E178FCC6FF3B0425689599F738F5B61FC0758B9D6 +224000,u,CBF95909ACDBCA49AE62C779E6DCAA144278B2BBFA97FB83823B6C71D0CB413D0C2EFE4207009A5F3017E65C7412DEF5FB064B86597AFF06 +225000,k,5879942BE18B24990ED31C24E4FE503BBB3B3DE4532A12185645C6741B92686EFF2C0BF21616D82B4423F404627CC4847AB6454AD3273CBF +225000,u,857F3DE72C8685AFFE5AF6F1C0AB3FCD80635314C2E75FD0631F76CEE285089E57F74706EC1BBC737A1FF6842578916F49473B09A797486C +226000,k,E3D15CC07552C6E7106992D8275F4F89508602F4435BFA868F9734B3A1EBD6DEAD94ACAFEF36A5DB0C009D859A2E8B05AE48946D00B3648E +226000,u,C73BDC0CC247F995A2FE2E2982046F428CAC5E67ABD799E6DA8714B73DEA8E6BC734616F5405BB9CDE77E1F7D914D83B55786592096D8A21 +227000,k,A89BEF53340E552B15D6149937FCB7F12D804A3EC12111C60A5B92EC0D29D42E8023562E38D53A2924A8EB492C66C760D8742297091F8791 +227000,u,0B75BFC2BF2B18E58E06581E78E2B56888CA1478DC7E4D83DA86B9E0CA7FD803D492D80589366331B256A35C9ACF4643BCACDAF26601EB9A +228000,k,1298DD37DE39E877284FBB2B3FA87EDA642ED3475B6ABFEE5201BCC7AEADEF546F427557096F1C2FAFFC417DCE74228A0DE54F468F3EFDF2 +228000,u,DB9CEADB3EA1F03CE76699898D531F7D42A336F1E0D841B0185E7F40A6D2078EB9CAD707D3FCBB8F1F74497917CF7C7743E64C6974F332DA +229000,k,1A3B04E58BA7301EED450C2F7905A1D0B52DAC9B029411D7ED0BE461304033E3C9F693DE28AF75E964001AD791CD327A7FEDA50CBF139066 +229000,u,CA29E677DEEA377960E5CABB84ECADF4153D8DC1D86C7FC2A343B468308085BFF4FD6CE6BCE23E2D3C05F0A66FD7BC9FE525131A32F9401D +230000,k,3EBAA617A6F20CB389F5DBDE06937BA4F92EDC1510CBF2EAD17477D1BBF7F26FCAFACA45199A7F25AFA5036A46CBDD796464F583811583F0 +230000,u,DE47D6EAE35E9BCDF012521209A48141F00212E22D5161D554B8938676571F1EEA492A647DE51A290333014A79EA9206402823342B7C2E0A +231000,k,FB753E0F331B2A13134DA2C978CC3C315B74C5D66EEB5CC66B712134F08FA9736A0ED92E5B2217FC5CC79EF3D12ABA5FE734F059F684ED48 +231000,u,A72FEC08B3DF6FBAC16BF6BCFC48175E68B668AD8616950276C61DF5A23B58E3091F57BBF757A78DE61B2B1E7417BA5B0A62AD6FD36343CB +232000,k,7709E7CEDD5E1C0A56192E8DB238E7C4FACE2266C876C130470330B912C096078B22E25A710585710CE468ACC63828D58434C109C0AAC884 +232000,u,165E84E3A37A599C52424053CCC25509950692965DA41E6B8600D566B6A1D123D84DC0CE074519672CEE229DDAE64C5BA00415D41FC0A9BD +233000,k,8EEA8D299A64A371D7E895307675983A09800A896A0D1CA191EE255A82CADC0A88ACFC0EF87EE2C99187B19814CBD51C287844519D4EB46D +233000,u,C5C61172074B25D9F7887D49B91E5398184D187F74525163935762FB6997ACCEA2A06C2FCE8C1F00809796085EFA5D37AF2B929C2AD33FD5 +234000,k,5FBB122F5F84970059042EE179AEFE09C38378292D44C92414635AEFD466440A4302F0AF8C92B96780967ED75E29A440D89164A37D060891 +234000,u,C33117AFBB60A7FE7D87DCD51B494A844D28652DC9C3F1EEC552364B75031DF0F5637A2895567F9ADAE962C081D49637795798C7BFA335C6 +235000,k,5C236A6C29E52B1DB8F533D61E73D0AAD0EBCBF794E9535441EC36D7D145EF9F524A18590AAA2647E4CFB9BBE78D9E359D489ABE4D4C3292 +235000,u,5CCF6B3BE68D269AA94A54F6E600ADB76C0FB25E1F0CCE3BCBDD1EC984A32EE8789BE0E9228A93777FAA92AA6D75E0BF61AD2066C2A074DD +236000,k,5C66900315BA358454505E42BE04731DF56E94DF1B39A006E8709EB05B9A999B1B305A3EDED91193D5EA4C33E4F416A3FFA4BBCEF3C10E3A +236000,u,D1DD376E81088D944C9F73051FA950813E5C0FA233217FE1E17783004D681448FAC74254A68D0C6AEBF2194ADB4211871D2328CD8CBA4B9E +237000,k,F84B60269DF33F2483F11C33F82B0B81DF89AE2DB9E798ED75D4FC2B5556EFEC6EE5891EC2791591F05C2FB573405398A2A7C10663DFF4F6 +237000,u,31AB66EE9CBA1CA06C6DE44D22D661DD706831763405DBF71732CF35846294B9F55ED846DD5865EBD32F6B76F6CC766969DB4A577F2FE3C8 +238000,k,809F73AAF264DB731BAF78B5C05E4BBBB6A053FE869E96407F2E7087403CF1DCF3B2418D7EB35005E40B9594CD17D20DE49FFAE34B5C12CB +238000,u,24A2FB5BEE895B2AEB712A174115839D997522CD2474DB8189B6D5D062AF3E70E06A20AE2634545CB340E3637B5057CD4CF275759A8CE67D +239000,k,A0FC15A152C072EEEA43C09C23ABCD24963B1DDE2B6B6DE8D585BB1481BA17E9638090F50BFE082FC460667E5526C610B75CF805200E97B2 +239000,u,D9F585EFE8441FDC96C0F412A392629BA5653A3CF1FF00BC5FD5D0B0727E5725EFAD68BD0E37E0C6D5CFA0BBFE9106A6023175A53D6E14A7 +240000,k,F89C5C2084017399E531980DF3F33E4AEA7F52895E48DE89018E3F8416BB8BEF682D4597F1E9BC4B0D4C7ABBA4CFBA248EF9C57E09E0E826 +240000,u,BC03169043B65EBF3DF9A7D2F2CA98638C014EFC49C918904C424E3A0EB884F9B5A8F09AE4F7BD180A91070B2FB9F6B614103F873D6F44F8 +241000,k,5A4A11A395FA1E0BFCD22794BC449A3B47DC8F35A708AEB8CD0E91917E7EF297D4DB5F86125C763C8DA3DAA5459BEF735308337B8002ACEC +241000,u,45AA7B2C938AAB6E0BD69B173E47EC1E9B0BD94C8F440B349A3F1A754E579336FA77C0E6D6E7236241DC513403307EBFC54B8E175C61DAE3 +242000,k,6D908C903FDA6E426A3401D0BCA24AD7CF0B4694C4C21CCF3DE25A8AF7C2D6AE3AF3FA43BFEB84CEB34F8770A883F41A110925D465ED5ADA +242000,u,D775035463E4BB2EA83E41F428DD008002D4CF036CDDE9EE79DD764846FB9343DF1D4C246B7140DECFD61BF34AE0664D4ED30E5DE6511426 +243000,k,0911D8F061BFF0A1439BC83B97D7773CF893B256329455989B840D7574C4132E4C393AA11B351F0E61AFA07F1C3C79A2E0AEBA6A9878CF7B +243000,u,C4253165A9884A65A69F134BA993FB6CBECFA66CA26ACA30D716547717183A189CE810F3970AFE0553E35D4836681941CFDA475539355945 +244000,k,8B4D854FF08C0513E548399ABD675E6214826DF3E687C70CDCEF3560A631B237CAC0A3454E8106BD03D5CDF3B7F349DD7F4F0A9BD04825B2 +244000,u,20E3BB8734C0D8CAFBE9BAC3A71A25D8FAC5CD4E5B7516C547764A7F0F856F0B3BE3E0060AD45E098A8EEE307885355E88A4767C0F1926B9 +245000,k,2D6EEDED9C81C4F23A54D20DD8D0AB4DCFB7A8BAB3AE68D79B7252976343628290AF784E7C6850CA713F5CEA2E8A782070BC207DCB51F580 +245000,u,5637DAA7454E99397DB2CA4778589C90C61DF0EA49904876E42739F4874198EA64A5DCC8CCEBC7226ACD4AFC3FDEA24A4F1E5D5528B85324 +246000,k,13697F437223331DD778A5ACAD04B6B61089A4E61EE269282A21B0235137282F3EC53B83EFA66DD682E5912C02342245FB051DB9EB370F36 +246000,u,E2EED30EC9011A0154B92FE08184EC1F934D979D0F03C581E30E79E9B9A82BAA240AECC9C46825B02CF547B2D91FA7CE39E3AE415564F3AB +247000,k,67D9BC9F86A54CAC8EAB15315A2204073C2462C565FC82B41FF3E323B58B91B2C854C955139942EFDA7EACB6CB2EC081364554C161ADAC7E +247000,u,50AFEC5BD33D807563E8B1D8F9485582BB04B95E7B7804060DA9C2A3CB8436995EF97D21E3873BA91B3DAABFEFA8013B0B44C9F21CAF99C1 +248000,k,8C2D4DEA940D58B86D0DDDE708B2A41E0566112055866CE9AC544B519E463F58587C39E9867FEB1C4B86908EDF255BB0FD1B6595FFDC81A6 +248000,u,7BD4A41A10AEF6B65DD887648EBF280928C43F12080F19189D530CD71A5E74B04E6F911329F8445FE1BF744632DE8261EAFE0F5FE67BE0E4 +249000,k,E3E4D599FCE9B98F57734062638C75D7013C180A0F605616F28E60FAF5F5B5B5D560BC7027A135C54B9731616FCD0DBE13666ADF36D2EF82 +249000,u,13914F98CAD2A45DD3314930BFF5809FF39719B653DBD61F7F447F7D593ABF13A774F78ACB1CED2489BEAD4555EF8AE03396C0C204958DCA +250000,k,33616E7506819313F263F339E5113A04E4932F006B866E0FF4E4D85897434F69B918BFDE694F4CE0E1A6C46B6CFAE7CEBAF00D7326857983 +250000,u,9D9DA6A3F61EA0C5F71718D1ED740A50868161CE6291F64BBDB1E5ACCDD93F27A0D43AD83B6F01F7C62C874C603C49240CB1F1E9B15FB9A8 +251000,k,F61A6A89932835C6E724A250C2DDBFDA9B5D470CF88BC7F3080EE070C328890CD4DE78CB51078F73BBE654369229FFC990C46811E7EC9A36 +251000,u,22D4CF0F2EFAA5443EEEB327C97BDD185D7CD03480983D0F0C1C5390CBD2CAFC115FEC24881F6F399BC2DF07553EA76CAFD92EBE69672FA2 +252000,k,AFCD1DB051C0393D0F94633B3D857CFC6228A56AA3967769ADE9570AA7C99D5A02C760E5498C45FA80AA88FEFAEA415EEF0EB70C8F664E0E +252000,u,8841ED37DCF7B482CD81AA5E74341D26B30C64ED46D22F98C188FE455B2AB7E9019FDA34930451BDAC3D3AF73FAD4BC6B7D885B6FCF0EFD9 +253000,k,034DFEF5070B757F25B70F5DBE89171E1B500492840FBB257D6DE9BBAA211B759391101F6E4F709F39D1096E4B8397A11B1EF7CBBD5B7A10 +253000,u,ED6D6C60C45455C1EEA8A2006569BF4ECD7DB8F4F0742908231E2F483679BCB14733A536B6DC1F8CD2A1C89B0CE68FF6057AA72DBEB36DA9 +254000,k,471844AB1CC00D7BCD886950BC656FE67D4D282468A5E39185A6DF343DFA8950B34BD55AF8DF5D85D01DADB07A6BA72194D0466327113387 +254000,u,49EC989C382E92CD2EBF07F60B491A14BEF841FE979C50EBF641FC1E97770EAFC7425DE7E597DBC190488E305BE5F2C24CF12CDEC50FA937 +255000,k,E741AA24B85C9E410AA7ACE9FA92E01A8ED9BEAAB33B1B267CD01BB1BE87566B0818390D3029C6D7B1B1803472A8C6BA04782750A65E27EE +255000,u,AB5C942DA95B4D421569F7A10FB24A9956C349A83CADFAA7742D5F19323E4EBE0AE1526581DC2CF8D9A2051AB2C6B7364507286A9C8AF6BB +256000,k,1054492DF81EBF5A7FDEC2966CA5D4F31D967913C8C825060CD4CDE23FA48B929D2BFA8803891E4C7F0616ADFF0AFCBD1DEE6436317E025B +256000,u,D1C75464B7F22352B4665C0CCFD9873AD75D03BA42473E453F8B9C205E223909458E5CA96972FB2CE989E471A8AA4CE97E4205C7CDBE8660 +257000,k,564527A8A65AE568E77B1E29DB94781FE0FB0A8895315189DEE7F8E0F09E3E47CA16951D9642EBE0BF873F48E3E33DF8009ECF6139543132 +257000,u,174068818DAF44E45392433953871AED89B4D28806CE567BDC02E9018E5E372032EE40276FAFC219EF5475286944945794D0F079FE62A773 +258000,k,A9D6246DDF5C7F703220D1DE89E9A8E2A4184ADFD6215ABC972A3325AA1B4918D07380C50AE7E6667D356BA5EE651B798A96A3BD4623BBA1 +258000,u,4C5BF125022157B955696B4CFE56A95CA99C5C3A02D1645809A9F19A626925B919B9711C4F81FC27096A88E20D90AB9E716D17870C55E3ED +259000,k,8A6F19C6F0108BF557A0FB23380848A617EA06C05B0C37FB3D6B8A5038D993156AF0F7176DEECC998BCEE48F91BBEA173CEFD38085D3A4E2 +259000,u,7F445EC5F069061D4C08E28F5BB9F341074C0ADE579958D111BACF1C35672B26C89724B93CE4F64925572942CAFCB95544EF8F61AE5F3905 +260000,k,0AE0209080AD2E8829747D0077F01A6EC2C6DFA7938688D91F58D28DB348E151E9EC2723B666BC146241162E53729CA8EAB3EC9DD72DD570 +260000,u,E8FD288979F70931339967913775E191A6B40743A86171D03CF21253723A408E714260FE2E6A9AEACE71D4A25FA78990E8BD8FD50FB280D5 +261000,k,58FFB1B1B1BC1CFD170822ABAEA7B56E96CDB5604BE35D15B3B1874804F4F841AFF813B76A5276D2E99253E697674271ADB521A9FFEB5CC9 +261000,u,837A947F96D0E4F9B189174D4D85910D3C3F3412D5057D32F1017893FE333CEB5526B821E882FFCD3A55C2C23AA3962682AFADBDA863E957 +262000,k,57B62BD7D1287DD18D15DBF8FDCD0FED41D32177ACD851AB6853637A93D018F30D83E5D9ECE9E7D6E2774049400922B3E7CEA31F002C01E0 +262000,u,AECB1AFAC0CB17F068FC1994332DD93F3E8DED16F85F061C49FD3135685C53F0F96F68D7FDD15D05E496FFC2999CD4D6F2F64935089B28DE +263000,k,A81AE0989291CB7EE7EF1D3D5EC6D013E864CE7FA3D9B3D41FD4C820DF671AD57DBE00B3B2B6068EA6CD6EABDE15E6DCDE3F8108EC839A00 +263000,u,1DBE477510F2939789FA49331C29A844B6BCE83267D9D7AD06C29C5DF9D9DB432D5C52CA487567A242A24B223B80DBA062420AB56D3AF230 +264000,k,EFC3269D87C355A0BE9994F24F8CF83CD7AB3637C4F397DB98AF6B3FDA0367516FEFA297697AEF19FFA67C9CA5DCF9871540851B65FEAD7B +264000,u,A9F32D6150B7C1B98FCF9FD0760309C56521A111905BBC4EBAA5F498B3B23614BD1B85911393015E46D5F7261F2A8D4BCAF90F70C04653B1 +265000,k,43CDA9BD9B7046851F337170E96E82B188F6C4EFDAE3B64C85574326B7F0991EA61C9A69052E8B84E84B4020B0CA9460811B98AAEC8C570C +265000,u,D80415F8FF6F0DBA3C12316B3C599691632732B3DAB133D57037EEF52AF4C5D88D557DD028FA4EA5001B45287F4FE2FCFEA95CE8DBBC2164 +266000,k,B4074982BE400892AE98E113FA5446B26DE02FF51571601D807AAE69F3652F48B439DBC90805BC09BB4D51A678530FF6B27DD683A75AB80A +266000,u,A87D3AB40A92B1C7AE439C9F7F2775E6C594E68AE98E4FD9280BBC9999FE52C264ED12551C959114A311666B5840D57059A2A11B056249F2 +267000,k,40689707A8022087CEEB6DB313000A1C943518BF43E49122F80533A261C8EA76F0839DDE4E5348F521F86D2859E2A5DCFA9B1741A92FE9B1 +267000,u,AB942CD89D9A9DB9E93526619FF5428CE9505E8EF65BE39917992F4E67ED10F2EFA3D3A577CD16D440FFAFF12F5BE07B167C31DD8A54EE81 +268000,k,2C8139CB6C3950B1B18F72B4A6FFC6869EA5A35B3E945B9CCFEDFFCFF0890A2AF894DAD79346F4EDABB1831AA7635175D712D1766873DEB2 +268000,u,56A19D1B54867331558CDB4E02EB20DF3E7B7A3D1D04E7B38239767BC76D03C0CCA806A74E1935DEF3F0381686E308ADFD96BDD7BC6AFBA7 +269000,k,173E83C0D3E5D4FACC7B4E86BF16669D8B081CD28E889D0597B45EC5B1BC1CB0673FBCD3AA394B9A0CF074F12753A565762722D817099657 +269000,u,2B20B4CB163480DB36F9B9CDBB9F287A86D4D5D55101FF98A53F05FF6E8D5D1306C5BA9CB7873B4F41411594EA1ED67897EDC576441E7660 +270000,k,F3727364D0A32BF395247E73B423C071D2E73F164DE59FCB71857000AFE2A859D81C5CB268B972C8A5AFEEFDE5579784E108BA4EA0DAE8B4 +270000,u,A411B5BBDF7836C4938995E87EF65DF0D9F8A83F1930EC65C46D09CA01751F709C8385D0E9F307F7C16E984BAA011CA89327A38AE4959A74 +271000,k,F1AEE52030FB66D2D94E8AC6304260E1B9D3B6CBF8C600F09B3324A339FFAA3748A95FFF7E8545D8E0E210EEDED139A2A9A7756A35A5933A +271000,u,B8EFC773EDD9ED0F6C0321EF134F94D837D6749F490CCAA273057B8786960045BF89F1B918600B35E59A2E9597D40A5DAF750CC125506010 +272000,k,266F84E9F3CB6B3C8C88F09C91F9C0192D6D2A3BCE53FB9EC17314B9A20A5316C4BBCC0F69C8E804F946F013E76E87873152BD6F80E9BD6E +272000,u,0973F5B68EB59F0263C0F685365AADB92396618D4BEC956779B2CCEA45C0A28136C9A4954E52F277D362ADE5D8694CA9DA15230967637C94 +273000,k,91093D1A343E1CC84E95E2FC7ACA04BEC4C5A2713004B896ED28F5B5C46CBCA3E58A495543E556A0EEADCF8E1A974832979128373FECD50A +273000,u,9A1793A786FCB86BCDFC37A237580F6895ECADAD18D93F1C80F109E872A5FC2EF98129405D2186FB0228AFE4353C6DB2A6583D9A20524F43 +274000,k,2E5C3C94F226ACAF98BE40AF87FF70600EE8A5C135BCEFF076139D55D68A8F7A997FE1157D3346CBC286CE57A9827D22835438A55A969FA6 +274000,u,E2AFA6CBC037B00808AD914D551F1A9BCDE696BAA25BEB7B2000418ACD8E17D9A813AB18A01350AE0486AC43BF322C286339751531125385 +275000,k,7973E9926EC760F343AC02664825C4C75B95025FF27EA7DB775D179E9881E29A1461E92C76A86BC6BB9ED69EC9B37EC6C11C2AB0A4F337EC +275000,u,91F964B9B345A56B2ED839BBEE61741D489754FCCA55B43490BFA198E02E83D1A621F500926A93829F007609ECB5C0D27A08020D35AECE0A +276000,k,0B73BDC786DE3E69C234FC128C9E2487A9A4304CB39E6ED900D3D55D4C861993F7AB2C9F4794C87C1A8B7B760D9A4733FB768CEE54D25C98 +276000,u,EA6FB326FD58692D380CD8590CC81D99C33A79F00FC8FF8B7E02225299EE4E86AA87ABA98D755D7352A2199B01532BA3F0A923F081C860F3 +277000,k,90CD54604369B7994C13764D0E2088DDC99673BEBF82ACEAFD97768D903514206993908256A60687FEE87CD20552BC4B2ADB8DF6BB2AF3CB +277000,u,AF2B2CC0C2F574F0FB492D940EB1C500664C16C6C123BE8960F0E2AE58163A9A1C057552D8C4A19DFD121CF7B2E535E36EFDC2B20A5E04CD +278000,k,51C857DE264F550F14E6D19C53B57E4A2EA07D6ECD56DCE6F94DBD8AF3A99A1183DC16A2C8A3B8AA8AA3E3DC2213EB86AE9A17D7DBBE22A5 +278000,u,EBDE768C260D88F507BAF07527DD0C1DC1EC7743A7DE5BE98E9F241E5D55A3E37218C0DD52DCF9E1F8AF59DBCCA23B3F0A621E9E962B55E5 +279000,k,885AE0AF25FB938AF35FC81DB22D515271712058B0E704DA94FF950F63BF776B6131B4FE81ECFB2CF4EB2DE718DB97EA67860E05F40ACAC1 +279000,u,86C0EB310EA33CD208C770F6031A4D22B828489D35910F3B679136796515DA363DB3E958988BEE40134FE28A6BEAD3062064CB3E765DD5B5 +280000,k,9AC7CA869616FBC2D1255CEF954FC067E1E458FDB1D34304A529DCA1666AEA89DE410CB3043E5F83A91EEA4F1AB1C6AD7EF3FBAE32ECB052 +280000,u,0D5685E417BBE75DF9E6B0A634CBA274D932810E2D91F797C0EC00F43F2F247C4136F78D30182DE4021EE857B415F14505BEC23ADE4523D9 +281000,k,1BD5486042BD076531D8D244206E54ACBBD3CFB65BC316EFF82097DEE90B05D30D902300F4F66E87DC61FE5A069D7D66876687AF3FB1A8F5 +281000,u,CC32261429F6C1C033E23D90B4721AE99470F9AA5D73DF1A6E4D846B37E4941BC29B60654B016427C9C5E23043E50796E71D333BFAF916C6 +282000,k,A0239F0C7541F456003D91A38D449EADCD9D471D4D1110D83999B96C1DEA6DDDF3CCD34DEDB3A01001C278B0DFCFBE6E585CF3C71ACC7D77 +282000,u,FB0F5534D20CD71F827C14730824F45BE3FFDB0F17DBB7F113EFFE4622983B440CD38E9DE999D1CF964EB34F52C5D80C4DDE122ECA99C406 +283000,k,DE1BE11073F0542BD09EDAE876D85AF75C9E80235DFD1ECF42ED54720B8B4C3E2C5E56AAABF277E0CE2EC57E4A83EB4B496D65EA858EF22D +283000,u,02CF62CB1D310283ED63E6C6C95D28B75ED7B1ABE896B1BC440001B9CDFAF7D1C08F6855E61A8CC7438EC650745D0F8DC0A61F7966E2A2FA +284000,k,2373A5713F69B023F20303B8DB28B4FD6EE26B7F60A6EC1244D1D345D54A575F18A6AE89846962B714270A670ACD36CAA28A9FB76A658086 +284000,u,DD366CAAF2D8F47568AFC1ADC0FC19E1A448DF424255340B0A323696002153068362120D2A4498C17BD6CB012715AB7E7BF56E462B421955 +285000,k,DFA5636D71C154858E326BB379C8B5E82A69C90E692313D1E28DC8B6E210CD2E22A56EACAE89758409913A7A5DE3A9C529127BA5A941F619 +285000,u,796A2C908B3599D95AC420224FB86A95F3118774844493699174580857210A61508D166DEA910936F511CE8149048CED0B30AC2CBD87097B +286000,k,296DFE8E92EC9B1E4CAD714DD3D4DBA9F8EDB5330029BF87191B9F49223EDDF924627306E24607D6AC6DA12515AAC8513529D60EA8BC4805 +286000,u,E610776CC18A72E3E27F66BD681E741E9034ECBF5FCAB0BC05658DB06C58F104CE265EF6D248C441D2E7C0EBCC21257747DA79A1053C1A45 +287000,k,D77AA99C3A43AE8A6B16F4347193FED06A70466BE6087AF91A827565B8211A667FBD1C858B8C91601F76347374A1B3D2D8A8AE56A04505D1 +287000,u,909A73011BC725136EA0089CAC6337DFF24200B5CA43B3F0FB652203209EEEC85636F633504E6B684E4899AD9780597B4A5F7F9097DB003E +288000,k,C3380BBA6764BBFCEDC57AA99449F0BB5ED40AE1CC75125BEE8435EA70F8FEE4F691F990F1CC243CA95E9653D6EAB1FB04887BCD549A0314 +288000,u,B1BEBDD29B1087ACA5B29C6F64B57D5687E271DF0BE67C6F17520F6D7C242CD628CD8C0B429BFE5D170214334C225532E9D7BB4EBB15AB4A +289000,k,9DA0D61DB95F3171F2D6B157F71C7EBF522C4D4ABBCAA4FF45F3D832D75298880B9CF9B242A1C710C9B71F555EC8ECF992F140A3559E3CF5 +289000,u,1393FBB4A5D4AEC947520155AC41257DFFCC332095346CA0EA7BE0A0AAA0EFF1D30BDC10F0205E8F3E0E9EDE308EE96A7DB89A9987D3F7F5 +290000,k,3D3BFBD92ECA2A326E293E374CE94B6E4EF8FF0E86FD947C55B0CD79D169B7597E19D64A15DFA73A7F2F0AF1D62B6A036C4FF9A6211CEFBE +290000,u,0875AF52032DC3E147DC5ECB477CD6E9E85909D0E7E17E20D54B8D6F22741AF015EC581D3EA77BE6B4838FA921EF845979DB0ADE3D4648B6 +291000,k,180E676E4547BF468F292149E61229F286B097C30BBB0800838FC917A9A1B5B3824568EBB590257A84E0C132CC04436D5B099F819E282951 +291000,u,EBE31616840A1400067954BD7D14DD82DF08A7E6BBF4F24258DDFFBC102A29980F2BA199E361AD6609B859BE893ABAAF9039FD1DC230125D +292000,k,69F034E1E7A52D53D41CAEBA836D951BF3B22365039D46E12FFC3E189189C9DFBEE1324F9E03C87435D7DD33EB0DE47CDD337FA34914AF1E +292000,u,CBDC094A49C6FA635E40C6E8DDE9D04B50CB04A0525E2389C67F0A4B55D53F0F8EA963B833A9204C6892CB4BCA9BAC6A98DAF0B6F876A328 +293000,k,55490754516F52DF9AB25D772DEFA9DABFE74978F3863A78CE9E60FD1598BB730153B64AD9B08CA9662F50CFCCA25518A188C181F54516CB +293000,u,969891FB77F424A5539386B74DA63C01B62C43A4FCEA1CD341C6DCC78C2D80F85D7C3808B9074AD3E6DA7CC9B13BD3F784F66E5EEABA88EB +294000,k,CB20FE95F500B8E9BA779780E9C1ED0D6545969A95274E6A74FEC888A62558854C06EFE24C2650F0959984C5CE24EAB8A6C14F08A78AD678 +294000,u,C05EB1B40E149ED1E92146CE9627703A26016E320C70FEEA50105E4C91FFFA6D5948AD94F22D410CE257CE8CBF0CB0FFE8C00D305E255839 +295000,k,2EC5D359D04E085657FFD229584309547538F976E42CEF2449BEB8A0ECAC1019EAA6BAAA4708CEAE5129CB033CE6978BE0B8AE8FE28D441C +295000,u,5575AFD5FDE13BD9DBA428FCEC6C9118D1BFDA50FBAAC74C4CACE57B92D037EA520023D0C9ADB9BBCDD2065F01D4BA5D3964DA7F6A7EFB9F +296000,k,2485EE669961BB26F5175411E26A50E92249C8BD1F837B11FFF158362F7626701FE52C9F48F035AF639A295A0301E82595578A785D0B20D8 +296000,u,BEC8FEB126216BAB42004AA2F75B7AD2C562F3D4E01460FC3B79F2FCC27329C63894714ABC0E4EC816F6A7AE248AFA482EFEE3ED2C61C145 +297000,k,D4CAA09CD2EEFD025B11E2F21E3F93E8669D1E3C29C5D9DAAEE838BCDF7CEFA97D67FEFF09F5B6C72C699887107D42EEDD76F4B4694DA375 +297000,u,677F5DA67C72C6C8B79C6BEBE0B1FF754A21AC33BED10E64DA8E9039867500D472AC029830F947AA6BA30968132D044E6D201ECD38FB7236 +298000,k,6A4FBA937AB22270B4E375212671ECD7778FFDFB1FFC2D81AA3B98C4B0C171BDDB24E9BFA086605DB9CDF262304B3B39515F6BDE59543DFD +298000,u,CA5E3638BD4F58D67A348CB469A0C2E4494C2BA01560A9203EE1E0E9F921A0E859BD69708B766BF163CD08AE888C56D2592F0C4741BDC7A5 +299000,k,E2E8D17210CEEFB60353E29A819ED00C2804F52FB2F3F8FCD446BFFA6E2467D04ADEE60762AA812392D9675F3A8563770880C1DEEB2C0013 +299000,u,2984FD017E8A59401EE8FAE10C8D0D395B42C83A2D3983ECC24AA0CD8CDDE40661CC448BBE8E83BD50641BEED539F9E1E183F434AE96B328 +300000,k,39AC758C14C41D112CECED83D16E24136DDE6A99F91C352A39CD8C192145F600A2C3B5D9864193C32D95AF3044A85847015B7A76727C61D2 +300000,u,F7B13D4B8492AB4215AD4F7F0806D83FF23DACCF482C482063F835020B3F1706790F10D521D0835BD71240B842AF03FF5505DCA48832B303 +301000,k,0D53F4430E069B1C98784B19D4D067106120082757FEA311C62F7B56563BE7F1510C0C0AD8E0C035495E3A86ADFEB567DE27897EE628DAEE +301000,u,2E49100BB9C607000A86DE953707E2C567B1DE6FBBD348ABECBAF0CF3CC05B1943A7219AE102645C401DB2A99568334504B5445173C40CD4 +302000,k,92BFEA234CE96A990B6E4D7C4AD563AFC12B175BC3463B615B2BEBF8C9A7051591441B77239B715C2E5B7157DA0FB934D7200F5D79EF889C +302000,u,19CF9CDEF6DECC61B59C8ECFF391E6F9FDFBDE7E3240DFE0E117A749E360EEFA71FE6CCCDEA38959BC8310703F8052D2D906DF3F039F979A +303000,k,7168FC09B82F6F69EF687155F7195EEB55F1E0E42D72FF7F46D5CFEEE73038A7448A31FA8B41F6312B2E22C7696A4B2DD4B064CE72C43227 +303000,u,5791214DC52145F980CE3D5DC8DAA9B62E4DFC75FFD76814CF294A2398DE0A0022A63D1B66AF79027D69D88D8797C5948ECE56230E0C41E8 +304000,k,C2B12F5BDF73BAF1000173CCCA768F49AEF491EF8142A11730F39C46BEEF0CA1342F03CADE7D832DBC2C5CACBCBECFF089F52FFBCD42F018 +304000,u,3E2F73A0557ACC36B78B6DE256E1D4BB30B3E66B86BC2F9CDBF37A9BD932CBEC528114A61372D8208565691737ADA1786177E8D8994EDBE1 +305000,k,747A9FE73BF975DAE18D9BBAD24F647F1B8F99866BDFE5699341A5A5D1BA150924B1EE6A94DFD65DF139BEB3A59C0C8803A4D0BCC532E0DF +305000,u,359CC5C74E1BF5D64154D7234A91000765A6848A8169B6DB8D534046AA4B7AA64D77DC5A488FEAA35D6AC0BE2064EF68E8B7D27AA502C09D +306000,k,00850383721A12D275B3928E6ED1EBFF24AFC0B25D11FEF9F1EA2CF4D9AC03C5B435B9FA350E3B30B6AC6E484139B6CCAB54D67156A6CFA1 +306000,u,A26BDE24EA7AB5AF0997C7F17DF054FFF36E38941AACFE3B3D095BCFBA4C959773360FE7FEA302FC4026B4F103E8C325D06CA8518AEBE96E +307000,k,5FEBC5C1700FEE09AF0FCEBEDE52C75A1307C71AECDFE22C295B29E252CF047AEB12E3DEA875925BFF20ED49DD5E9EBA2F71F752D4CC5553 +307000,u,107C51964BECEB7CA5BC63B56C4CBB1F48FAEA4C85C27961F7AA44EB77D3D876CAEF7AAC76EB7980BF2BE37AB1DEECABDC9DAEE7C6543F8E +308000,k,074911B31CBA9A3990C7B8CD6CF06C550029DA34767C75C11904DDBDB68113D83E366AEF58653F5F0E8BB0BABF881DF024D639FE691E553B +308000,u,DC83A4998AF1913F3CBF3D5F89D810301FD1D563AAA6A9845A321330BE36C98EC904A341505DCFC23F9A72BA3D03414A8608079BB150CA02 +309000,k,CB3AAEDE05F71FF701F81F470A0567C391EF860189C9FBC5546BC279AE8E90AEF820154E8E0264F75F0F5B57EB2DB5AB0F878E771684525D +309000,u,C406901CA84767E0A9CA0D730C23E838AF903442263E77C4F838433039A869F80CA93A300F0A0CC1DD1DCE1423D1A96C0303FFB86A846CD6 +310000,k,A33D368DC15E12C323FF38DAAFA82D4EA63BE292CBFC14A167A9206A88C51D231629E32FB2DAF98CB93C5352ADC1E07B802F4D820698D758 +310000,u,A22E7D4C2CB9667A371E666773A360F87E99E2F8377FAD9519F2EC408CEB413BC66D9F7A2B5A6A063A57EE575BE2B0C1E78B601FDDA35141 +311000,k,6A53A491A0718FCB260D28FA4663F2564F393C77CE970E88244528DA5C50B8A450E69D1D54E884890556F8EAB3FC98D46B3DC790B420B159 +311000,u,089D5902698D5297EAC22361DA5C4A8829CEFD13CB96B670036E427F500611F5564962FF853E6D0741B5B6F500514B23DD621C54D6870028 +312000,k,9AD4F69333609E40542EF49C65F672578F1B04EF5594C204CCE68037B95BA1CD2F52680776CB417AD712CE4269662668DD4066485C3B13BD +312000,u,54C47BBF3B43944B9EFDD33EDE0F9366C95B41F73C3DC3CDE76A0437DE70946B7C323173D93F373E439ECE78EF7D22007FC4D7D2F181A4C1 +313000,k,384B40636F152EA8164106D510CA18B6652A312C6C0F09061C3C3385DED9B438B7DB099CA78C66FE9BF15AF2D013F0E598B58FE56623DE28 +313000,u,804925B372B3387E14F249C1904758D5899A951EEFCA5020085B32EEFB9A73F2C959018F05E9BD6AC86B351D0DF6B29752678A5D7FFEC807 +314000,k,054FFB2341B86DDEE4713634A46CBC8BFC193AD07BCA69A347C2A4EBED3E96060D87CF9C3F552FF26BA2207A07D0F8BE662D933048CB5861 +314000,u,E94058356E2E31AB82381734EC59EE1A73F07E7C932D42A2DB2D3A191B65AFEA643077CF4D0B0D5579E0FA82B53C49F1C5BD2B1FA31E1904 +315000,k,F8876B2AA10F66B820FC7E70C3D1643E86C3C2F9FCBD69D925CA9AB2955AE4FF9D6FCD75C97068EDA7910BDF166B940234B5394C4FD8E0D1 +315000,u,D684988B8B6C7DD88D7AEEE440143F9E509E14C67C3CA5F127552DF830E47917596875475E595A56DE7ED04681F3BB10BEE49F91DFFA3C9E +316000,k,41D2DE99302A641740707DE7303C6EE1DCA1B6074446B499A2B4B4CB094BCF31825B26BF45E32057B064FC2FC4491A3167BB04CCE4D043C0 +316000,u,48BCF292BF09580A206BB19143757DA77FFC7953357D7EC0613D0CB09135450BBEFD36A1F781C51A60850DBF101D5CB8D5344FCD510580E5 +317000,k,DD5B87BBFBD3072F47B8E711EBBAA5EB7BE9ACE5529F9904A201A7B96BE5E396D0D8CBCCBB84B7EC9373C48D948B50CB6FF39C51501D56CD +317000,u,8BB922FC1171E88617A365418C03B6B0D59A48F87D2115D85D3AA96E9F07EBC4B7ABCFBD1D3F569FEE6314B6B85C2B6423BCF2AD394AF1A2 +318000,k,76CEB1C7798236DE65ACBEB114801142F1B1FE3D71C2AFA33C7D216D878FEAA515E911BA2D81877437E56E6A9155CB72ACD7DD05202EAE56 +318000,u,FECE0CF0E7BF671B5FA441140159C3E9D9965619829B62B5C57AA6AF494F8AB5EE55CE7876AD544B8F7089191E269A4FC5A084CF092ABC58 +319000,k,D99C4E08A8BB75F40705947DA69A668F7477C4C4B714349C58ED34D6252B9E819E2F1DE627D43AC2BB8D802E7D224ADB5D32F6231830A11E +319000,u,E0BC92A21161A49B1135459B274E1D5E0F776CA28BD467B47851A002179812DD2D4C7DED92F1B996A14A992E554C1EA46BDABDEC3FD7A51E +320000,k,EDCA1DAD776BD23F4B95EC464AF499B3899D6DD0E6DB312CB42C4D482FBC915C632C6DA97F8D069DB770F1B342329850108E9D03550A69A0 +320000,u,2C782215C445169E20B415A7E5FA1F49F67ABB609895EBB4FFF716399BD5D513762BFD660FFCF30A9DA0119A665CCC0601B3F1543F525CAB +321000,k,A44C36895F621B66748DCFD3F9854C54C1F0FC6106024D3DD1C8DBDB6E5BAE86A822EDB88BBD8A7C03760489EDED400B1F78462F646E1859 +321000,u,A5625ADB2C593B8827EB3FBDBD27EFD9C31184D7570533B82BE09B7E0D37247C6BBFE1EA22B0FE090C3774DA59A5E9CD7C385FFAD57873F9 +322000,k,1ECB1DC633B2C5298C2579C36715158344FCAC04F3ECF41F6F7A2AA095440328FBF775F0F66758FFD1380DA16406C377E1F02A040CECF927 +322000,u,1448234596BFAF00B52FCBC73D1B8286B9B5114740DB8E47BC8B90F4D4B6A3DF3EE9BB4EA207306D6A20CDF339875761FDE4769066A61F99 +323000,k,87545989893BA9DEF3219DFBF4A96F45F83760C7D30F136D41E7D690E7F30430A7673C535682B54CB3F1042A5A97FC91DA526B65FC70EB3A +323000,u,39211752A7498AF2D789E0B3709189EDCB08D027FC39E43D43C2F0AC69D3A51ADD299D685BCF36E24E64CA5A72A66CB42E86C59879BCF00B +324000,k,DF8BAA5777D789AFE180E0D6A6B5887AACE4FF8230A82D432368C202836D2B8A9E4FF41607ED05B47F9199A54D826693C82B3EE51F8D3C5C +324000,u,A20471B6FCF1C9620C617089E1F3AA5A5AA99F3A511B2884A6AAE65BF2EB9FDEB1AC85043D6F8D4C0EBBFC16AB7399FB79A1A75D45F9E942 +325000,k,3DA014CC164DE686061FBE082136760049E48FFC7BF96CE15B785E69F9C28E0076970ED21B270C9DF34E02EC12752CFCAFB3A0F803B13C3B +325000,u,776794B10AA87F88AEE32C168FDFFFC273A065C10BCD504F025105C88F8022092E18983FE38E57F0ED4E2F5E5BF2DB210B089D61EBDDFC35 +326000,k,06D9D1081A21806142D871203C9AA9D30DCD1DD2EC1C7BDC339ACD017B64F408D36252E2F80FA7B786995F9EA813A9761B71797D48C0032D +326000,u,1F6C59EBCC2BA02BBFE799355F83AAC90625FF886EED2DB9EA89EB83224677738071DE0934EE6D80E49860F6145496B653F4311E01E19C17 +327000,k,CBADF96C5B4C1094F01157664ED6711E60989FEDCB29F5DA36D1E9B40654D8AC033D6C3A17FC970F289CFA82D63C0FD2A6265F5B6D4D6053 +327000,u,ABCD4F7A658BB548C32EDA5B4D4969DC6E3283C4C38604BE6A86A914742F08576D606857E41A78D1A4E4093E32A403B17943EEE8B7C91B1D +328000,k,E14CBE9B3DF7A33B537C0AC0D2DE7CB1301E955B9CA5930829496A703B878297B89AB3F495BA67C7C590EA270249C765C5CBD2F8955201D8 +328000,u,F4E2393699778A551A5F1B701C20E62E13AA2513B9BE7F72C3C798CE42E03FB61AE8026457D5497AA7662E8EBCEBB44DD6C0B7762F00657B +329000,k,0C9E2089E640022CBE6FD3AEB2DC3F9783BAEE142093A18427223CF7BC2A86CD32A711952FABBA0D90530D5A5F949811002300092DAD0A18 +329000,u,5E159F616F57CEA24A9536CE4F7FB47C00A369C0060796E6CFB3E827EB671B5F420EE31C966F3CB9935F9E84DAED0CBD0A3A1372B65A97D1 +330000,k,68776718CF844DFB05A349C87EF7E0F55C350CFDE730139000B5BCAE570DCE1B355807F32C618DB394727467FC43CB9627BE6BAE0672F5DE +330000,u,AD1D02D898A5F3AD7E8B7353D8BA9C7DB478C6A86129CE9B606067C205EA5ADC7061A85DCED0681169797172428AD18C9CE18886741B73DD +331000,k,EC947E20BA25C8DEED0076491357286D2AC4DD5C1510F965C4E217CE348D4ADC270FCED7362D37D39D20784BB777939C60AB546909416751 +331000,u,D9F1CF15A9AE861E380A7014EB873343662A7CCD96183E0BC7DD2CFF24595108C09B58492C056CDE289298963AF2C5628C2C26CBAC7D5D88 +332000,k,40880A9731E22D44DF092DAC839C2266A80CE48C89EB53FFABA0AAC61FE6FF3ACC2558A40529CFFF4AE93569626B71EB1506949106E16519 +332000,u,3B8A72F9666F8C3C71CCF273EB07D5583E65CBB3AAFF348FC0912D467B44F3AB068157E4D50240CD5292203C4FCAF87B752BE7BB3A330D26 +333000,k,AC181E29F0BBF69C4BEC1C0EC606A437939E33B8EB489DA93EED67A8285686412000C55F6F78D9E5185B519754ABC6B0C1E0BFD47BE8D53C +333000,u,2540842C62CFF44684AFE1408341E073FF75885906FE779D075D1CD707BBD9D2F734852BEB72F17FBC9F6E5CE83BFD91CABE6C88D4CCB4FF +334000,k,92DB1008B56F81D2676A50192CB984AD6FF007104449F977D83A02F0B0714ED8D975394860B947998D6CDAD93762ACD811D0E4E1B4937FDE +334000,u,F28F2EDB6A4C759E7B73CBACF5EB86D4A44DFD3DAC1FB38C6E8F7F139B4C6BE8354274609F38E55EF441C9C2D5BE9EC30D647351B5F09B40 +335000,k,C6FE939FFD7DC387543C6A9A910B156BBCD3EB3D288EE1F6B0B4A3ACD372B8D0B8BE3BE4E2550A202E94DBB23075B0C3AB6CDAAC2648B1B4 +335000,u,B46D22A5BDF561C8ABE080FF58201BAB373CF6B5F044605C3FC627A9A48BB60AFF5A6A871F8546002CA7E002F1B3D16CFB6B97980CAE1F9B +336000,k,34B04C57DDCD6F5FD09B20D7648E2AA70C459CFB8EF06AD7CD797FF22E048B40F0B7FFD28994CB69CAE04BF92E0D0BDEC3AB48FCB75785E1 +336000,u,771A840F6D976FCECBF1713404851EEB71F40E14A996192804C92772A64EA88F7031E6D486A3E921BA17D0CF8BECAA6F09B271EBE4900324 +337000,k,896A90484A9C89697CF4B881402E4DC3D3F385A20F51BD55FF45DCF3AC41328C9888D8D21573D4C86AA9B334F380481519C1DF19D5E8B3D5 +337000,u,80D2C4CC57F088379CF08D0F1B373BD68FD7527B9E5F8948F49AB938FE83F65470EE118EE8883FC147D6E141E79D2917A593A055948889DB +338000,k,995841D2EE2F7AE33286C558C37944E01EBAAD19EDAD5459DD4639CBACB0186D78D1AC77E409625A14D092927589B9B01720199AB0D7E0AB +338000,u,49F8EC164BB6046446F0EAC0F9C626B2119D6AAA6EDEFBE9E68A702B8703555D206C33925C1BA97A13AF63AAB258567080ED784AD955182A +339000,k,854FC8DFD1CD1A7003A325B73353AF864BA567116C6D97E649F9568F9D1B559C893740AFA18328F0EAA19332796EDB335ABA8F5053E0F24F +339000,u,8C0F9359D1799593C37885307FF52825D087726CCF4A8FA777B8EF79F617357C0C78440F4553CF256A193647DBF6A427814337E4B3B1FBD0 +340000,k,1ED3D06DEF22F4473DBDF15B6D937D5E63AA15F4572C081461182391BF274A4DD45CF2C36B5DB7C4556130DDDA34BD6043DD9F3066A73E12 +340000,u,4FB9A7DDE444FCD01259F5250E3876802D5A0D9BB0A4A2559434065DC6ACC44FC440764C9E3254EBB39A94A71E630EFBD655E6F2A91AD4DD +341000,k,963FF78E32AAC504353EBC64454D05ADE9D91D44AD9DE768AF06764A965BAF63CF9D7251733C8223DBC96E6A6B1E6D6131069CB9438428E0 +341000,u,FEEE6F59456BA33AD8388D024AC29524F39B5B14A7EB58B7EBE09B1ED9A4151A3FC3B8172E6B9288752745ABB91D4020709CF6364F5BA104 +342000,k,82F85E6918D760FEA796C95F5EF15E1E679185F286953B680BFE3F70DD076E80C397B03C7D3E6665530949C992626F4BF38BDDD999EB9550 +342000,u,1244F5EDA9D41B93C493BE796B4F5A8EAE6C5052167D30FD549916C1C17DC3368B61DC365D59A768C6DFFAD4E22E28C1FE67E0E6DC5F3964 +343000,k,18D5DD999DFF0304FA1CF760A7CFC8AEEE73184CE82F277C7AA9CFC9A9FFCDB4591FFB4CAAF554B9232B1F2A2112A1334F28745E3D8AE721 +343000,u,7CF8FCF40BC8E89BCF2A2ABF84C4A07D9E2B60DEA98FC4EE3A87B36AAA13E6CEBFFCFC75BCAAB537BB87FAC167B57D166BE7E4621EB119F8 +344000,k,B24C1C82373C207308D163BFF5FE800ACB67565D4285567F31156B2F5BEE23C63C76282B6C57E5976BDBC2C722A26AEF4BB979011B11998B +344000,u,B26F4AEB085A72C93C6319F0DD2AA9AFCB4AE3ACFFCF0E761835D1F380CB9767C1D1E6AEEE3968B42173B503861110272CEB8DE9866222FA +345000,k,6745379C954BEB7D414B4F17B34CD644091B006CF45870DEB03EE893F71701BEA81A09B68E0B779C515DCA1AC53DF271E4023945BFF1B4CC +345000,u,E970B9ADA641FC7273ECF4941ADB17E3983B51FBB1B399BDA5671D1EA978D3A9E30E3D995B79236ECD3279CF5B0A45A427A0E4826E7DEC6E +346000,k,0C31CB4AF233A0081284B0C3EBEEA504E8C1E8D62B05154F112472B4271F824B762EB7347CFEEB20FD79630A89CF1942C336A00F8DE0E707 +346000,u,8B30003870ECB00CFB8508992C7BD85EA4450A4750F31E2C6F525BBF6B59C4449551F9BE02AB50F99315ABFADC57BD401B9A7FCB3DC7A013 +347000,k,09266A9577C879BA7C6BE761856E32B609058FCE2ECFE4F348A8D5BB0D5A36E353BC0B84860B043A4AB2B1285FBDE524678FDA2253F69276 +347000,u,68C36881DE37E0C11B5AC2168EEB270DAD251EA627D95EADDDB151E877518F69C44C4079E7DE0F8CDC07C0492FACAEBB8CA2C17120F14992 +348000,k,6498488FFC2DF9790AD9BDC622297593700EAF3E4CDAEC5049C4067EEA1647A61BAEAA92DAC251FF04E7BF46D297EA5C99C235246027051C +348000,u,061F0549F48A3491715FE29DA3CD62CFACB01C2A2393CF71F0BA4AEF85027E0688B06D977A971DF50658E3A50F6A753E5434B06982AA1134 +349000,k,C4FF7CD83F15FEBC6E6B2FC8675B33ADA6BC81F1D0EB3DF3EBF8CC393A4CF872FD3440E7A0B18AE8C0BA46BB65EE31045CF7B02AA0A5D1DB +349000,u,BB25CED40889CC0829B924245E11F6BC27E5830B85462CD1C96B4C771D38B9EA88C7E8A42F90EDB4E107D31EE8B66D4640961CFACC23C13C +350000,k,07EEFFE1109B768D716DB2D92528F58979DD7E0B898013F9CF727CD8AB0A42A4886932CF6E81859CC07FDDF29537DFAC392CDCE4523C5586 +350000,u,0FA1E1AC0941518CD411B250A30A50C0991C3531E7FD03F65774686C8E9D9C31EE4C1AA73D2267032F520D7E7AA00EE23779E3A616EB1368 +351000,k,36F50F3D666EC75FC82DE07B10529AC243A0470CE02424259FCD8B8FC8D81600784719B2C94843CCEFA11E455AEE274838E747A0F11FAB7C +351000,u,5B08E14124247F39E9F2EE3DFF7470FE1CDEE57C6CD7EE569F3966312BC755D2A91050042C122489743BCF39D9C5E1C9EA492FEB6456ECB0 +352000,k,B69C2710D459317D55AA5AE93F344D8FF404E4AAD74E25B57F75502EB539848582170BDDBEE16BFA03D40E4513953463C4336053EE2AFB9D +352000,u,1E0488E22E3098103E457EC28C9AD9C13AC9A2F21C4E3A5ED59F537E1B256DD882BABE1896D979F9D48CA0AC2B02A07267F2A4660E97C941 +353000,k,0AD06F6DB2711290EB217F25D2583AC4EB849CD514D90D52D8A3CCE8B26295A34AA234869A12452B62397C60B931878755C8C17B6EF87248 +353000,u,7636BBE48F4C17763D7A7AFCBDA58E3E40B3FAF1D5F498F70F48C129C6DF3308BD7AFC8BFDE1E36C0DA1190B5A8C5E081FB63CCDE8646D56 +354000,k,3C45DFAAE84FD60E0BF4B467A1C022E85CAC941934F0C032F8F2645ADB0A467C38411A3C35FDF84735FB58BD3D91BC02DBC0725CED6138F8 +354000,u,7F8CE58A832074ECEF090DB31FC8C4EA0E2479E023418A97C9B55E7AB734E061766F3FAA5EA42427EE03B96D80D5181665621672BBE704F4 +355000,k,2F1BF7970EB07A20E9A41E10EC116D01BCE8CFC0A162E2C074493353F64F685A5EF6379864B455635B936654D78F61685B077BB454C37C9E +355000,u,B7D727EB02A9AF02FC5DD9C868D96398D5488F7DE8C2C9C63777319D72E5E88B8BFB8E4A1C5C63BA9BCD1EC2959403A927E0B5AF30F9A82C +356000,k,83352FE37F1E88490857E705BEE5FB10B7189B73894613D140672B07B6199005A0BA210DC45CEB1D36BDD674EC03E7CC8B30A4F397345F84 +356000,u,466809F8247885CFA7910506C58B1033B60AA86B0F1F44851A62B0F6CD107EF8AEBFDCBC5B991A0A7F79E6D46F6266B8C5763D30C09C8491 +357000,k,D07C21AA4FAAA38BAD357AD8AC4CC5A2C1C69F6B60F82ED4D93583665347EF4A725B7BD8AC43067F36FA017AEB63CACB75247F30376E64E2 +357000,u,ED1103A2F95AD245401C29085F1034C6557617758B0E6B65AFA113699176322DE6EE6C73E4BE991A9AEFD23BD75D11CB12FFD3C98D91BB0D +358000,k,ED0E04A7CD83966093F5FA1EB98BF3512F38E336B7D002551187B4B92F92EE0F066CDF3E6B25A6748C943EEA51BD114306D4040818542271 +358000,u,A799C27D93ABE811A0AD4B1050983E2AF5320613E02A65C5FBCD5D9BDB0BE09D5EA9BAEF1DF19C0225C58188B44ADE04E11B5B192DEFAE4E +359000,k,176932FE8F083D6B1A7DDC5B2FC9CA1E7F4155CC0E9B630A3BEA6C0169B8FC99979AC55FFF48665732CC3E222347502916029165F5679252 +359000,u,05666DAF2A57A2AE20ABDC50719BBFA6003336A268E19F8D206AEA57731290E8AB356CEFA26D57A705943F16278B1DE28E77DE46DAA60DEF +360000,k,189338BBD5AA1A37FD17EAE57B27C019B9CE50AE1C6071E665866158843C77C2855C3D87174FDDC508E893176042763CF1AAEC5C41E2F892 +360000,u,001F0BF83E008A20F61463C4F02EC7DDF9C3F41050795B5C66D6FC742E8408509CE34A2710BCDCE5FCD2B87BAF19B488410C1BEE422E5D76 +361000,k,0BD0199C566EDA6676240417BD3DF5D5DD504125A0DF5F1F5FA63BA508385749E9C8E9209EAD4D0F958A4135F625185563165BB958F45CF4 +361000,u,8EA8B4BE0A2852C0DBD6F81F92ACEC8E8A22FBFB05F57E54E9E1C7C68F837C13D919D67200D6251015D8F35771ECE6C58A2716C7B741DA59 +362000,k,E476ACFFC2F5F8C327F8E95F915E77EEA1E396E418C26AF47C8617E2A156253C7C15702EE1B4F9DD92DAFB8B1255D6D9C9756F449AB78CA7 +362000,u,4F0CCBFD49436363561E8C2755D50937052BCEEFEE420CE59C25BDF5DD64C89D060DC2A38FE03AC265680D4C98695C594F420274A83BDB5C +363000,k,49D171AFDA0F57288E160E19232B348C49BA72F4CEF09A2AF4FD208EE69D2E8E149C050AD36DC1C28C9619B5BEFAA0260B3B0535E323FB35 +363000,u,8B230BA52BDDA46E5A48DC878037AE04907CCDF00D3881AB45661C491BD2957E21AD98E37AA75AF006EF93C4A7B9155330EE3BAACB6E30A9 +364000,k,5B5AD421567D2F250B942425E69A928624CAD35E302E943B9E471BA804BB824101FA451072851658E62B5F2F7ABF1CBE487C8636BEA9A0E3 +364000,u,A5C0253F6E7FA76235C005357AC9038B6016C17788E730024E4AAD28BE8E3C60B4D4E3E156EBAB0E73B40A53A2DE29388D9E9F13509229F9 +365000,k,A889EC192393A30EAE4EF11B0CFFBEC683B53C0EE327A85955D9A70D86A779CB074479DE44175424C3770F5DA79D75B9A3CAD9BDCE18CB1B +365000,u,0C098D54DE6BB07A12827B34D568AF69EEA03B59FC80CB93CC7981C98471D3441D6954B3E140DA3EA2654444505292BA65766AFE7D10AF50 +366000,k,511A52DCBF2CDFE610406A038E580AE3AB230D6B3BAF6CB546363A87FA5EC6F0E4B61DA0FC345B69CD3893D75C0D50B59A7F28B4B43E67D9 +366000,u,E7628D044E227FDE5FB96D3A94F120FC58B32623C793483DE12280819FD2A2128672C84345A34F8A60A5172673ABCFBE4C4EB18BF9AC59B8 +367000,k,7377DBDED547C36FCBED03FDC9F6A4067D2CC83673EC1446C446D39F5C41C8C91B7A473DE44117D6EF00735619C9B2B36C7862223D44DD9F +367000,u,963AE38869DFD6FF24B3887A53950F0151BC6EE3758F816D590AF6FF699F8D49E99353DB4102317D5B5EEE21AAEE8687DDF594AF4124EFB2 +368000,k,75189259F407F4201EF561B0DD4E7EE764051369B60074015FF9DDCACAEEE5DF16F8F94D29888E6256657A332D05AEEB5A14AD667474370A +368000,u,60F31B7EB8A042487EEB25DD4C03DDD1FDB3282A847E8F6217E81EFE9BC0EC368BA2D9C2C1429F0D6421468F751A0DB58574D1E9575236F2 +369000,k,52F700BF24E6A7B45DD7DCB7F32BAD64750E2A2429D1B67273DD9C75B3D01EDE7F2B0FD002D6E37B19BC6B0DF5A1EADDAE11FF05AFC7E1ED +369000,u,B9286E1E88465F561E05E81758FDCC079CBB07199D0125A188142FE19AF09D6BC82037A411333C7E8834D923A21864A5F9715DF7F2867F41 +370000,k,71BC01EFC80A4144E2A62BFE4BD8B6E0A004DA6AE048D2167F413A7BEF9ABB317A3AAA3C394C9F6BABEF3ABF32B340FE2D5ADD36255038D4 +370000,u,573B83C1004FC97341F5E584F64C4178BAEB03F70863D745DB2E0D9891E6FCF53700A764AA06CF2F628E634D0C34C9CA61D7849FA5BFDE47 +371000,k,8F97BC0A954B5B7BDF77ADFB8A9DADFD88F42E8B5FA4C22880C80AA4CA1B8E458C09D96A30B88E9E265892CCF2589F0132619A9838F2BB0B +371000,u,BE134EE2DE792B26C6B9ED3F28F5A8A1B7575DFC065844D0EA33B005D48C659498CE87E88565CA6B76B60FFBBFD663F6069B995EA3EBF686 +372000,k,0859FFAF1EBFD5A474E0C445F84C6F89465E1410EAF71EAFA9BE7532EE0C92EBD3BC27DF67F02023A5C42394F2028A963DDFDF16D9887C59 +372000,u,E22D94A6D864FDB6CF90313641CE9B05B49384A99B34846C9E1DEE5385EDD20E4254DECDF6207401F2C0E9DEEDBCE57E180600845F16F3A2 +373000,k,465F77ACBEB7806D5544F09A7C8EDC244EE3360977F2C5EA084ECD178B6F8C5D224C9CFEB14ACB51384E2E184836A9BAD0E278B4432770C3 +373000,u,58BB259A75A68434B89AB30DA83831A500B7C6502A63A9A9FC19237315F54A5862BF7AF55A48AAD0F97DBA9BA4F67723DF094406F57417C9 +374000,k,70172C111A7007122731353C02933E62A403A9A7F8AC9E9585571E2ADB14F57B6115E66CEEE913E696B52CBB65C125543511B33250172FC6 +374000,u,BB31CEBD2BFD712F43DCBB050CC04F5FDE4630664D88CFB0BA7417F2F350EC47FCD41F05AD56200B2F17636B0F622E9150911D2B7F222EEC +375000,k,56B2C4B0B3E71E4EC010C01393272661F05CCC25682B62EBB16182032150CED58020A33FA8F12D3E9249CA64E06F4851DC724883C192AD87 +375000,u,7A7125878B7AEE40CD538AF54C93C1431AA3F3394777D717E28872912DC43E395307F1D32050D2E12D14CE4F81A45A220CBEF3668756DFA5 +376000,k,3A01B45017D0E6F36AB3880199264EE971A1939B0C15B7709633F8564C99569D1C16A15E01D59079FB7871A05917B468B77AF87EDE417C1F +376000,u,CD995BD1C4259F16CF833F42BDB3986DCEF4217972B635BE844E170E431830830F6ED8C71B17E65A75AA3C0C31CCDD43C326EA5EDE5AC323 +377000,k,E5A6B2415C5150CC1DC6FF3BF2361D2FC19DD2C53B0D9880D49BEA95E865823F7C6B598844D5D6863B89999D18E9F4B0D5D1DBE615209E5A +377000,u,62DCC86E207B0A146B7737B305D9EA3E966B91F096698CF49A4348DB190FB841B226AC84FA74392E32AF2F2A559A949C55D5F6C4DCAFAC1F +378000,k,C632C6F1E9BD1B65AE8F8152DD79D8520BF8909A590EB89BD57972CF81D1759DB54C4B89796FE959110C6F2BF430A7CD86968C9ACF30DD7C +378000,u,0D11BF226F217AFF0B48E3784A70305DEF689EE568F98024728CDB6F8D7AF3F498B1BCF3A2010A611732BDA71D087F45EBBF988EEDDB4B04 +379000,k,F46C04B52C2BAB07CF6C8DFE8197D14ED164B6D880F1232E324598E4EA2385270B4FB60A47BA2167C5C8CF5691337F170B410FBB5AD50F7D +379000,u,3EFB5DDB9E32D31986E826F6F5962703205EB7BB84E76AF57A6EE73FB137A1A7BF3DC2DF0A4F2000193E6599B0DD2E329BCF26EA81179DC2 +380000,k,860D1AACF895F1BB7C6C98E2DF253A4EEDCD371B0FFCA1BD3053414B7445931272816E30514A81B7E66C58CC7E72C18B349EF5B462BEBCF6 +380000,u,4E05BB2AEC4DEC50EF6E0E47D51429689FE012EF23C8D36F313D91C5B4BC2A1526F7108E42D7E0D51913A33EC2062AEDC2658AA05FD2DC28 +381000,k,948F740D5F8514A1CB6801616992CA450E36D3EA444AAC930F41E8D4EC22E0BA4140F897F80C55B43E9DD65F3E262324B83D08AF917DD284 +381000,u,423D49665ECB88F8955542F2AA274ACA2AB9901C8B6C9E7EAC915B5732AA72065CDF600261EC799D36FDFA5DF610416DECB70368E03ECE3F +382000,k,211F783A509EFBA6A28654218EE594D3C5F06EB1A9DEAEF36401E321C82AEEED7FD6ECC408ED7269CBFF4FF79D06C7017C3F9CEF9CCE2CB2 +382000,u,B3CF6BBA93880DE754D8E4591C7195EC5CBBCE28A13F30B000909D747CB09D7379121EFF9D10A4677B55E42FDC7FAC968D1F38721E0D2B07 +383000,k,9E209987F700FA2C479F19B798BABC19118A400C01C613CE94B2612C1EB66C28D03DC30E01E6113FF634A5644529058479B8730A81F69AB6 +383000,u,E3F2E393D9ED91EB7242BAA4D5718462076D1EC179384B6A9EFDE7A708EE92F9F9B0D7A8F507A8B70F45FB829A9400F41576EFD8AEF4F903 +384000,k,2765A276B784A19D06B8FF2ABAADA6CCE6D2F3BC26B8C63CB37DA84F81C2F95FC8EADD6D947F808389C2FE76AD068CE0A49BD2FFE64E890B +384000,u,87D4F85CDE3FB3EC75747BF2C2BF7B15D8DE99486669AFE3DEB316D544E9FF79DDAF9CC078C757178BCF5D49DA7A22983FEEA351CA9BA546 +385000,k,847A2C868C880406CC32375BA42BB2EC355EBB43B0FE8FBB8A56EE841B133C6A55D78C09CC0BAE5E708232B091E05EA6115EF4E2A0C7E1C6 +385000,u,49F170D6E47B352491A7A219950E59459C2B22790E5CCAA8B5AFD42842D38B474BD75929B6D9053C41C122A3E7248E53640251F3A67AB9AC +386000,k,1443D8D290C2D5EB13FC01FA8BC6F476E9FFD1D77FD10AE3182A50AD9941AE5AF3883EACF2917D9553A48D2BC9EEB2FAAEB087D45D5C989D +386000,u,B5CC2B62706D0E00D1D7C8800ACAFCD08E0D6E3CD803AC40460689AEA124828331F7F840D297BEB54DA01DADF5224C6D11590EE714808293 +387000,k,C0E5E552B4BEB9AC62CCB2650F92FCEB842132462287CAC0F544641E61A4984D3BE2907D5209C1DF1DC32B89953129A0A7F069E844181C67 +387000,u,B20DFB1B5C13C33DC81C2BEA3FCA9A6007ABB2ED9B7F709AE5DE4A2A844699BAE6D52E04C6FE530B8E2534BAFF5D8273E7EAB392D8D9593A +388000,k,68411AA0353DB2AA46CF9BA36128F82592BF8CA721DD4EDBDFA65707978976918E76A3C90B4FF743A4A846DDE42EE23A73DFEE6743A2D626 +388000,u,52B4390D5E87F516CDDC418C26261CE33D59AFB579BBB6A3C324597A86AFB0E69D91471A1BC1F283806BCD860FC7A7D26578CD3000DA2D2A +389000,k,49586C5223DC1AD23EDB9BFC9B585FD5B24822481B4D6780E8C77932B7DF5B82054E9BBA246F21D70E38C387BA50B7AD20FC1EA57FEDC138 +389000,u,1AFA4394E94E0BA293B36C85C6FC96AD229087244609795FF64DF052878132D866E4F5475DF0A40960A1C322A6B117A6AC0AF337D59D54A3 +390000,k,9ECC6554ADCF89E8716FE8626633BC6AAD5835B4051D67822B3069C9D1DE1ADF5B7B94124C8F967A06DE024DCED80D8DE81735764F03AFEB +390000,u,319F8546DD3E35AE50553ED49852A84DD085AAC0BDCB8963B073791110ADED2844037CE6E216071D92C51C84C4851B5AF2B7668AF07F0388 +391000,k,F28E91CFD71B3DC743DA7D39138F2098ECA6C4EA408920652458BBD30FC7445EAE0EE6E8F4F0920797270312DD6B275AE7C5F8E0467CA26E +391000,u,A9987B5E588A0CDD9BF9A1E1123683EA5B4730A8FF256E71C02A007849A502A0D37FA420BF2AC30858A6BCB1CD7AE5B5D39AC3503BE7EF84 +392000,k,6C61ABBE6494314E2D8BF1F8043DA3B18401CBE8E641DE7C19174CC6CB440251B9351C6D0039808A1578276A696E099E4A1DE63F8A2E029B +392000,u,AC37AECF93942F248FCF44E0E183805F01510A771B1FB083B5FAAC40593EAC7C1B7F8D8B0919ED3951881AD51F7603FA9F9DB9B14AF85BC4 +393000,k,095092566A0EC763EF5EE40C1E0CCE9D7D72C90EDCE35DCAF0263DF476C836EA29BCA806447C8FD8441716A36AF2AE18547737FAF49F9D42 +393000,u,0F189E0FA8DE42F0747399A54B39DB62825AF456F61810458B63094DF850262EC8B2518EBC67F1D8F38F548B00A3D91EC5B2449D5EBB88ED +394000,k,B8CC76B52697B468A20743788B840C1FDDAB6C576EB2687EC65409E651513FA2C907404076B205DDCA12E17D73142B891EBB32A672A7D8CD +394000,u,5F6BD95B74E13A20124BF0389C9DB5B9698A46622B1FD948F93C1A3F19E96C39CBE4592AD43A0B93430A683B1C96338D82E30B6E63EB7F3B +395000,k,96CC713E913BFB9B66CB6AB55C3EE6B174BE1E038814EC30F9667FDD04485712986D56AEDC4BDA7FEEBD3102C8EF66FF06CB11C2188C5441 +395000,u,51349BD878B74413308E604D698B195D49C9A912A68277F63F9E9618D269FD911B99D16613F36188A4252472EE21A9419F8BD2D1E03B72FE +396000,k,B034B2BCC3E2DAF8B64A6851EC96B54DD5731110A3BBCB7D83B4B746B257F01851CE39207E9C1FF407C53C4B40DC9B311692A9D48801B018 +396000,u,ABFF412A9468679DFFC176BC6DFD30FD278C68BD19551959E7C51EC338D69B1CA714608253BDAF00AFAE25BE88994585C10C42C8CCEC2146 +397000,k,322BFB2FB04830499947FBBE4C61CCD3D0722D28B6ECB746BCC7EC1BC07E9F055268E1A0ACE34E507A16E6A8C1F39A4CAE71A13E9354C17C +397000,u,3CD0A4FE5E23760B9D79A26B06CB0FF3DB30C76FA27BD652BC0F4B4AD35B0EF7CBCC729892639C4DDFDE610790C17AAA53876889C9167423 +398000,k,AC803357E29D5948F01F326BAC8948BEEAE66BA81EA397D03F2352D71003FD5850D8BC5CBFCB4C086B74B9A8C690C63E1CE4DB5569096B7C +398000,u,3E254FF49CF2563F33334A4036B20B44838080D44CE3EAA59B56D815452B2ED9556D392086587085441E49398625C552AAA6B509A2E49D0F +399000,k,4D352E9184C9526E59CBC62B06B61B79C3C4ED0341C62BBB6B88E8FE3B51F4856817BC1ACF5FA1AE568577EC8C5931BF0E2F034151D3A7A2 +399000,u,A9389504CD351A95471E63D72B03ED78DED8CA19D944F1464A78B90A8CED009934FCE6AC02F7D1EF2F695CEB6E1A0D89BF44FC999621C8D5 +400000,k,822AE5BFE694872E266098113D861F71274602A15068B0829F7B19A0778D407BDB8AAA8FDDFB9E434EC76D5D2328625D1FE1CAC21C1BB051 +400000,u,423F22256B29666620C6C791AE8FB92350623BEFE4AC1F9C9E2BA604B6E2CFB069F974D14D89FB4C5D99C0F20F2B41BC5B47979E95BF04DB +401000,k,0FC0033E0EA36C380E58D2CFF5D1B360E6F37E90F1417F82DCCD45E970A5DC2105D86F3E035F3C9C573DFDBA69AA0074E2E72AE808B32063 +401000,u,947922AC9F9D022D239B7D630650DE389BE7B44B79B911EC8EC78BFAE43E782BFDB9D23BA46C0C0A57102FCB7AE3D0D804E2A71142474814 +402000,k,AE1B23D24B9D54F54A7FAE27AE07E34F8978A7E10199A73CDB865C1D334F8B6BB532BB7E09ECE4EE862ED5DB8124165D520DF15A5B81E35E +402000,u,2A0CF3467B865F3540743B1D5CE159F482AF3E308EBE191FC0A74D32EC2244D8A491CCCB7B7E43D781CA9B4FF5A38195E0311E3BD1E5A453 +403000,k,FCEB2E00A164FF90741396C520B8451D908057F4F41C2F85D7C6075D19C9EB9AA104BAD14B36FCCD49CE39F5193869E6268DBF4BFBD2FDBE +403000,u,BEDB6684F07CA25CC38264D0C46A9B4E2548B25AD5C054E858810A83BE74954F3C21930E5A328DFF75A69CF3BBD83A0F77D1261F5971FB36 +404000,k,670FAC158B76AA2B07DBF8792429A208B8265A7EE254FB83FE777F34DA7C2703DFECBD32921CF1856197CABA5B3CC14CEDCFEAB3464FC135 +404000,u,63C7CBA44358CFA9F69D568577FABA4D616F3C7C6781B0F62C53D8D21E930CBED6F4D2A6FA326E4D8BB7CC0FA257F1F67C8377135638D119 +405000,k,950E1B366AC217FBB0E08E71360B6E7E200152D8D5832184A46D07D97BEEF003B89D2E2D806B40C04F9C0D7B554D717A7F0496874DF896A4 +405000,u,0B86B6365EBA6B72F21263BA0F9F805AC988A18EDF527AEE23764E5AC1FFCCD8F747FC44093B0D60BC065C72051B5815E14111F70F5754F3 +406000,k,7F5E17544EA91A01E5856D2AB7C4C6322806DC9204EECDC270154F1D18924199F165134BFD716A845046D8DA91B5376B89FFFDDB92761429 +406000,u,14B55F86A83E9B073CD8AD7F2E9279A71B083FB482A77D439267F395D68829D4A5A30C3AE694153B470907DCEFA3C63007CE5967CABD4DD2 +407000,k,19199A6721BA91F28DE3AC6C2212F37791D0BB95410CC4A3C654973C70DC2003D14F0AC7121726B0E56AA4F9F509BDD23C92C0053DD4EF3B +407000,u,86F261E4F00B072E58B9E16A7872E3D8322AEE9A43D79CB76003CD656729D59CB1F630F67D25B9AA4FE8CAA8A8AC5620FD7E7DB767617EEF +408000,k,9A48E3898E36D8701A0C1E2A1F5530DAE69070FCA30934514E685A35DB78A023A7DC23F359E475799C9ABC2BDB07C2DB130C4B3DDCE88100 +408000,u,482CD0D1C31E8722A7EA901BC00A5E067F595B028C4A77E7C333891A270DE9AE00530C34CFBB7C4715BDFD996EB556648299804AA5BD3AFE +409000,k,0AB2B827A701F49B16BF995C6AEC7C4CD5F59AC7B749EFEA489D1B8CD06F038B00A4DC693C42DAA023744A850A85DC2383F68FB7A362AAC0 +409000,u,6039F3DEE96C8BC3783ABA97F36CF61254112FB28812AB66D965FAF217BF56E51FEBE99A7B9A209DABEEAFE798A6510EBAD719FB4FAB30E4 +410000,k,C5345BC7E4823032081B2C3168A3B809718107BE5621A63E52A087376B6B09E2A32CC0E8872B6BD7F41BBCB8498828D4E0CF0D3DE4886E9D +410000,u,ABBA2FDB51FAE7BB77138273F4B97365BC319AFEC50A873EC21979D977C95366C181C9DB31DEB105EE179EBE1940938893CDBBB13154CF0A +411000,k,E51A12DC60DD6E5F3373DAEE01003D5D85F50BEDBAB1676BDFDF08489BD2D782934108DFA50C1C2E9F7174D5CEE2F30BD35EBF8BAE141A9E +411000,u,CFD08A0B4296E9353879234842EF29914189FAEF41D38470403F90281672F22A4F4D68C9805D30C9D6BCB6E89DFDE7A9A64CA1BF311E8756 +412000,k,1ECDAD807EE85CFE1D4AF8C3942F85BD5AC266150B324DABCD905F24FDE9AD6F0D4278FE42AB2D57E58BABD7ABFB9516992F35F2F332DCE2 +412000,u,22474B3ADC54E7414CC586D5402E745582D33E7307EFF947390A1DBC7B698200A4F7978F7C8101EE9A8B50713226F53E93423DF23780D311 +413000,k,11514B1BF89E9AD350CE0BF35DE814F1C05AE31638D31D253976C64255F58E1DF6BFE825C4CDEC6CCFCA393E48893FE3F46FE21BB24673CA +413000,u,B0C1711264C97204B35CDD2AAD704442FB850B58CBD1C6C08B83FF350442AE72E45E0FF64509EC4850EEF61404CCB4C83351572D91A85C4C +414000,k,87556FAEE3DFD45A9E7DEAADF1BAF9281E322BEBB0531B8F76FBBDB3C999AE7243B544073ED6280F5E3FFA9814DD0FD45B15E8BB08B3155D +414000,u,AA22549303E6D50DB9F874ED852DF9AA74E5684AFD0C7EBD97DDB15B6E4C423ED67DBA512786FAC93CF2B7024CF569F37AC99073A77EF7D5 +415000,k,5A51975FDC9D4B5ECB0985D41FA2DB0D41EEDE2E1052DF4526DCAC125BAD1F6C8DBE3B7318E30A49B75C18EA66E10E3AB72F61949DC8B44D +415000,u,E89386E9F2347AA117DE007748B09DC8EBE6813926BBD4A533A64F3147D898766FBEFCE73AC7464D222566B532A54FCCD2F5A5A97F3420AC +416000,k,C683C7BF46D4C1EDECC42D9C90C90066819430A04547188F4A4940815B245AE86440EEFABBF61454782B8772F9BC281F37C3275498FA6BC7 +416000,u,BEDBA0EF149BF2AE3048290424A29CB43E8725BA30B9AB1C83FF60215DD7A8A086BD986508722B22D33E87B144C7E4D87C8EF13F6AB62539 +417000,k,16D2D98112A5B461B4946299214AF3EB5E9500F2F16E643C7290C8C65314728ADB210B6C6685F5DFE91DF12681DE6B1C46CE974C0CCA849F +417000,u,87B9306B65A6AD24D9558436DEB4CB9546F0C4766ACD06DA9B53327904CA26D8AB3CFE847619F7816F7F7737F82DCC90CECA7C7691E40C58 +418000,k,768F23C6A02E3FCB1104FA21DAD99D759D17947B14FD7176317112251D78D1C828CB3825EC000482A2430AFBFBC9F59B680E888ADF1A5071 +418000,u,4F22955D380B561F65E89018E1634FA3335AFD1DB7753209FC8F71866FCD48109AF1BCC74347D318803E3187FD009C4349D8E2C7B23AC8FC +419000,k,5D42DB5F014BCE09053E0B8EF1C2A340E23AE66DE8A874951E8266B33668C2D2D39F93BAA59F0FE727DED408B651881D554766AF7D562199 +419000,u,0864857F618851E9C51D9CEE4F1773C344D61912EAC9CA3E99472F31EFDD96838E2EEAEFBBBC434ABB987A57845BCA01CA55D8D9260F7964 +420000,k,A1E3E16CE91F2BD224AAE4B8496144FD97656C47FEC5DBB1CB51FFECEBBF9896F8CACDE7D7EB602FA8C04679DE26AFBA9219700ADDEA5C9C +420000,u,8C08F5B72D169DECA44BA183218189F59F3BCD81756D120ED135CF0FDDD0AD49E679877D482FD3E4E022DC5AB7471F1124BF0BC0D91E9FD4 +421000,k,C106E691E415D12AE35187F96F244904CA43AD42F30DC4528A9F4EB4B26D137E3018B2B94F770D8C3232EBBE72F272437B0D9F7384B09038 +421000,u,AC10BA86982674B43DFBEB797DC42E03960928FB16DBAC6250C6DF827C7E78CFCC97FA069805CD434533C3AAAC4B123BF501D08C8FF56253 +422000,k,6BD48142EE7D42DB6CDE1E55063D0BF1C65667AE081E6340E3F71ADBDAA89D49861580CBF256CBB437522FF8AF2956DB67B08B0164A96FCE +422000,u,A13ED143A028577BBA4CBF27EF37F76DAA3EE62B02D567F4D21E46E072E5D4E66DAEA5696DBA49C7CEED86BF2554F5C50D138E6D07E62487 +423000,k,1DB6532062DD531B3D258C32B8549FA2DF099E8971524F39760CAEDE8CA8658BFDB780EABC16E33AD8E411FF19E2D2B5E0016A811E289503 +423000,u,22ABFD0D16C57A795ADEAE337CD199875ECF445848EC5C3282C9C853DB2F84530DFE664EA9E000689FD5FFA1B74C82EC5AAEF2797D3F2767 +424000,k,2A5DB3C579A155CE23853237D28B783922E6F7827C6084F3B5AACCBE9E9B95AB758902FBD5CDDBC8FE0F82C92A44AF1237301B6FCB6E1F45 +424000,u,C4E9E9F674BD163409E166F495B074E0F7F1EDB552045A704C4B3B3B492BCC6B3CFBF3AC0A17BF1EC91C76955B2B8B93C3E70807ED11BC11 +425000,k,CE19A3C4EF390452B81DF4FCDFD384FD769C7A320DE69DA99A2CC89B156A89066FC4EE14331C87D6463D6CDB78534A80AF8983504CD9FAAA +425000,u,DA4886E1F69AE081D7CE77EF5F466B9948E13DE7BB7D1DF7D0921DF93CBD75611AD74371DE460892782FC67468A7EBEBD1E170809885CAA2 +426000,k,09B6937187F8A5F8913F0D97A39C493BA7855CDA66C390CF8BB8A1B4F3D23FEBE433185E4002E5B32D54BD5C199C757505900B5108D63FFD +426000,u,D4BC975BD85150E7818ABE6B1CC33EA485B9599C81DAF7A793B0574D6AA94CA0DBFF60534D99DE984FC62DB5FB1929BC88A9F84738BD8C4D +427000,k,E62C39359209C5FE98D0F6567BA50F5332A608EF0B37894EEA0FA4497515BC9F34F510D10FCB559BAC5DF1412C18E6DDC5C26DDF3BF9A801 +427000,u,D0F294BBB4A7D5CECD4CEA2EB2B01338D8DCA7E8E902769615DE66FAE8FE1A3F517B358724913C51CEB05C99D9CE79BC7DD9BB8AB104E6F1 +428000,k,0B6FDCFE48170F1165318EB8A8807AC6B09648411512039C78214B5E1C41AA23532A7F0E7B8D5875F5EA97557E1A211D876DE74E114B2DE1 +428000,u,5C51811F79F57C96E92608D36904367582D2973ABC3965BE24B12F060E5F6711E1E421AEAB12816553AA84B67E0654F44F6694B4F3429487 +429000,k,672F5D807F6194BDFDB43D025B45F99BEEDA3FF75FC1921CBEE5886F334F60BD97190EE42FFB0DD386A072E3F162F9D21D848BF4CB08E2D9 +429000,u,9B7B29E2FA176FF5EAA0C5941D1891DCA8FD1E6F0E7363F4D3ACFBE9A68FD6FD1463E0E996D12F0736ACA4CD0697D4A54EA699B118B29343 +430000,k,E5328484DC3A7DA176A94EAC322C99A5256C4B489870B944E17DEEC8212D000984B3D3C26E4405122949A4BFC822AF6640120260031D95D0 +430000,u,23860508000E0D0547AF18C0BE88BBB091978ADD9560E5F8E90D57E46035CFD546870EDCFFF85C58F0242C51EF0E46A3E68D96B31E7E5D0C +431000,k,6A2E53BC4C90F85AAA3BF23FEC1716FC2985DE84E482FFA360C29A839CA617FF0E735A93B073A7D93966663FF3AFB489B8EB1D2415D19D8E +431000,u,B44F2DA77943ED6A4F8F7850C9072BE339F45F55DDFB5CBC14085C455FEB39FD0DABDA693AC854837C1428727CBDB2B589DCE56F15C265E3 +432000,k,87ACB6D2E2401141603C652A216597AF718CB8C07713071580D2D09067CC1E463A85551C0758F202B7FDFDE6636CAC6800B9B7851B4455EA +432000,u,63E2E12C57933B79229A4F3FDE62EB25FE5FABE503A218EFAC208371CE6DD8D41CC98092987A90FF238A1834F52938621C43A8E55739CB37 +433000,k,1C7F34EA08D3B229CEEAA6394C78A9E7A7009EFCC10DC3E4B69A79D442D4EBB7C27E67C2041FDE9705CB87CCAACCA0DD7EB30307AA121561 +433000,u,44B79D64CA217AE3E01E985C7756333AA3CB7AE485BCADEF3003AE7E0B16B0C7D87F0A05ECBEEB91B267005874D88225EEBCCF6ED55A00F2 +434000,k,4E62B222B948BBBFA86FB79C9BF0722AA6451666DC4D35D7AEEBCA822CCD0C8FCC93F1AC4AE775BA9E5E3CCCA30DE845005B8C35B68EE6AB +434000,u,036EF9B1CEB3DFF7D4D55BE85847FFAE4005AA0AD307A9E19515A23A0FD0D558F1FFDAEB8E4C477BEBE474FF249DF68EFA4F2303683093BD +435000,k,E0E70D55F886FDADB07AAC645A7C7DE72514F66C30AF8FADFA1FD5AAC14FDCF320FD8C9467AC2E40D3CD1E640E9CABDB2B37081CB7531E53 +435000,u,3C50ECC0EA33BE06434788C0F79439EC38EB7C715F4B2E5E8276A5958E3C1492D1AF24961379D669B5A7C42776728B9A1721F0EB3F3B0A18 +436000,k,4B5BBEB79CED3FA87F58382F7A17FB476A29966781612838E17811FB74865069A535621064B07D1C6CC505E5658F77F7722D5605D02A9A07 +436000,u,640798F53B4BDB195E0E3E574DEB590FC0A69C4892A5EC1092919FDAE0FCF433F4CBE88551D3CB3716F631671278BE0C6BEC4173B028909B +437000,k,8CAD83D7806CBB0B3EEC35EAABBE70E484A360AE0DAD7CF04865E61EF6E2ED33B362F556C3E57D9B2F622B05C4FB6263C980ACE43882F55B +437000,u,1F6386327777021E2807E4CCB790859B977F05C897644B03568F9A386B547AE2D321FA7739811A9D1F7214487AD15D2460DD15F5DE3BE448 +438000,k,FC9A6BC10F118FD258C676F9E32835D4F2D218E7CC23C489E0DED481814C9EDFA8588B5A88C34499A462394C6BCD377719B93D3E8B4E192E +438000,u,9246A01325F92AA116B44BE2E6E2DFEA4768FE2BD8E0CE214E8D032704E42F6A1BC6240E6D806095FDE1860DA0F9FD03622F6327859352CB +439000,k,57944D7F7C204569DD1C21423CE2554C035EABA0AADE926310A3CD5E00691652916A6CAB1F7CD58F9DD81312054BDA296862D123AC4D181A +439000,u,F87DDA6D78FD4737D923F9254AB0F2E492A68BA55EA51B2E8AC0A7FCF8DE4036E3BB7A3419E423E28F783CECAED011B210A4F4C99C572589 +440000,k,53B1961FE79DD1E9E177C080B6399104A9F5D4306DB5BA1175D531D061ED2E8A1A81F7DF9E5B7B5AD312AE2CBE75317F4136E89F94C2E718 +440000,u,A2C30F58397B780EDB21FA9B0F8CE7F1191496C8B91FB44B24718964B999E8A5485A478C95D22BD35C1623A11B2731E8C56EB218A238CEAB +441000,k,E521C630ED4F02401B6BCB22B8441B3EA595F204A0D5275565952E2E49E6E71E9C34569A6CAE42DF1E25B6BE8E83AFCAF231A502D7DD299B +441000,u,4DEF66050A4D5CC825F69E563C1CD9B7404C05A1535591D4FBDB728E42D6BA874798FB81935F1323DE2B741D471D540088668A88C0FC0F39 +442000,k,BFCA2D9DA552B5AD1A5867F31425782480B720597A7F13F725DDECB35AC785E0404A9EA8E36C6E615E93A369FD6A2C3F5C4D4F07D1EE3953 +442000,u,6AA9317461D786980C9F9120BB011157BD460A89D2AD54BEC000AC201074CEEE5DF7CDA22E0441319E5E74310CDB83C8C60800C7B5992ACA +443000,k,9298292A135A36C3AD7256635581878161B5051F173124F2DCBF8C92839FCF848DBC999EB171BEBFC8E4D9754690F5F7710E6A43BFED5228 +443000,u,AE336DE4034FCB53D250EC85BB41CD5B78CD056A10EBE7D6118B6AE6D67CAEC304C519DF18D21930F6373EF58CA6553E22C4FBC93A4F29C5 +444000,k,C1E681CEB4E75B072C694CA4B9E5D8FA1895E8CD8AD3BCAF61029077B3E01D4B843FAF9A993DD1A50360CF69A6B311586FA6D27C388EDC20 +444000,u,1828E3352E9E0AF86F41D70310268F051F57B28AF4A270E88CF64C723B6CE2364656EDFE06176ECF86208DF9AC8360BE8E27866701DACF70 +445000,k,9B564D2BBE0699A896CB20CA98A3DE2AD102CFD8F52CF0B4E995A9D32467ACCB838BAE4D457BB140D7B289FE544EF6FFE43C5D727837FF26 +445000,u,00D1AC1B7A67EC75F14DADBC34AAB797F8AD6F8ABDE4C91F9B71511DFE084353C6F42D3D34B0B10EBE80A079B0C17C4A1CF65892A776F793 +446000,k,2DF63A39E0AE7B06942BE2CB68B125834B102A65177D8FD2122D16955E1D7B416B29487DD19FB7BE1860D090DD0FA84E7344EC5F5FB2F2C6 +446000,u,F6351DC998A896430C1DF1F260D1BAAD75BE9DAC7A6C8165F2E0F8401AF14A0A7C37F84388F4A8284CB09691F0C59B319D0CACDFEBB89C2D +447000,k,61FDDA21117A446D96F8B9E29AADA07E59346511D31DD9B1EE55E49A30AD1733090DBE0142561550F1B1DC4F6FADEA8671513D94AB677A88 +447000,u,A04B19022E63898EBBB5486478AA9F4BE9BBB5AB7107F3A5D6A85DCAD8D6D3392692B1772154736A71FD043C0882741DEA1123CCC0C78438 +448000,k,106839CA9B41BC35279AA0863BF8B261A87FFE9B098B2D80780BFE7CC671385A26FC486463137AB4F28A67ED60F9F4C276949234CA848962 +448000,u,A2BCA5D2773A11F3AC0FC9ACBA6278A8F811D205A7545A06D42EA36D86F1239510B2AD5F113DA33A8438585C63D1FD7FCE0DB16CE658B95C +449000,k,05F00C891C9316FD62F79C9E5CFF9C99F007FA7E14F092FA71359B7799795BA2FC17B65266D25551FA14FF33E6453CE841953740FE9082B2 +449000,u,3CB0D52CA2BEA0BE361CA7B64894A361CB0581E0103AC9578F060A067314BE0B7B7B7D88B4EE4B25009D2A889B186BD84840BD1E29E26FC4 +450000,k,7B3C00737C8234BA43C76C6B9EDA1DA23068CAF89CB3356BC9EB55109A7FC48F497086401C52DFEED1B16000B81BE6B6829B99361AB255C1 +450000,u,EC813DDFAA79FF0F51E36BE1ABDDF92354E2FCCB4CB27CAE72012F541A6ADEB916FF636930532F3B495D7650095B35EFA3AC6DC7A16D4682 +451000,k,98D4500886AF8D13109CFA8169DBFA3A2B5D6B8CF62142CBB757040CE6D2C3C424468C8550B4EDDF8B7E463848A21408299E142A1F94DFCB +451000,u,8C203B35A4C77B9710EF2537F2EA66104C7AD7606BA4292208ADAEB4855CE73E40D5A7950D23CFD1CF0B70FC79B71A08C1A20E85821DAF1E +452000,k,7957BA5DC3F000AAA6F70A353E8E465D6196A886CB65EBB8A8CC9AF0674F1CAB0D56992FAA031E79A1A621F1F46912D1C4B6DFF7A9A198FB +452000,u,CF51143AB9CF0639648723C36E383C2DD847262A4E9845D21F10DA80FF168669DCB248C3A78A662F3643060E08DD5CBB2D4A85207F886288 +453000,k,663E8219403CB8EA2B83FD6C886FF5697975D44ABC9484912504A9CD9D59EA56400975016008E7AD2C454964DD20D697906DC274994839AE +453000,u,98D6D396CB8839FF6A3A938D44325AC32A70B4D0082E4A4EF015234103C168E20CDAC675EFB7D3DD598D11C1D625A0275F357A4B1C3E6E33 +454000,k,F3DBD660437E5C2CC9D3ADEEA4EB22E60523E2017238ADE263719C1BC5FBDB2793783F7C90BA5E861E119BDD1EF38A9B0F414EE70B6DED99 +454000,u,D01FEF6D4BA56BA60D3AC374D501F79D6CCBFA130C16C2ADCDE445D9724A704AF55E076827116DA98F5D80155C06BD3FD97FB8FDCCA99862 +455000,k,D203686BCD6322EF4A59004ADB24F3E47389E605FA3B263EF22636A44F2AB23C702A06888C96EF868E19BB2B48236E7E5FF7CB0A56059A0E +455000,u,365A4DD3DAE4ADAD466642EEA8A2545EDF7194CC475106FF999839A0C1C0E04C93E693C3236CFB95E8E93FE0B51B0A48515A6380310470FC +456000,k,D6F8488B747DD02A808E83D759D59D4F022D60AEBF5BF8BE1C4B635690D901054A541EA4727D42AC2A5FD76DE225611204C1E1BA5FAA1A72 +456000,u,904895B82A089C40602DA1ABF6069C00F29297EBE1FCDDC67975336A7654C3157364224A6FC3EDFDEA1FBBFEF8DB776E244779417DD0BAC9 +457000,k,F788EE6E3ADB7262A206E7E269472FE1AA7E7BC6A4A5075B934F85462F1BDC8D3E37D6FDBACE584BEABD4266451FECCF607DACDD31FE09F0 +457000,u,BBA543C6C6CDA359B8458946F0E03E31D3DD18D1B9C65B89A7E5D54760F494CB56965BE23756672452A497F0066C191AC6369B501E9947D6 +458000,k,1927EC3663D20F36C9393A94EE23D3E99C017B76076D012E510C28B84443FC8B07E4BE924C7682ADA3E95527A2A603575EBBBBBF37DCC511 +458000,u,43C5FF9D03470D231277EC5BE975144C0ADADF1423024F91821CF807624889F4956960C5A907562643930D2BCA5575273516342AA83772FA +459000,k,98D017B6B56D206485D6D9B2AE65882DE394F7692BA86C0E68B4562251D169CA3FB5922E9122BCD4BAD1A8FCBF58D8B4625888D36FA3A203 +459000,u,4AB43A205BF7A8C1E53FDA7AA14E34EF2B506B015D6F7EC15973F323ACE6384367F3C8EF86A8CF3A50E1E545EC6582FCDF76DC821A3192F8 +460000,k,022E3586468BA5D486147632E8E36297BEAA52D08A29B37D5ED9105F7ABD51B7D7300970FF65B378F91C5C2A11907F9AA1EC6750A77A7F9F +460000,u,88985C777F82E76FBDFC9A977EB88EABC40B54C507A668BE87D5D2DAE529889240307990D04677996AF72C1742F7D0C5BC13905D60F0C638 +461000,k,0F659E84B6F207CB4FD8CA495E8676D88E8D6C41D6283416CDF1698B99527A48A28B15534C50A5FBCDFEF42A6B258D2195415A4986CDDA49 +461000,u,C30ECA600C7D7D5AC31B28AF8FEF107D18D505CC10613771CB9C0B72A7CE96F6CE0086E6F153EE171F332E75E9B998CDD1249985F3F5A571 +462000,k,7AB47C7C3A549958C6132A6C8384A1943E8AA22885BA50AFB527B830679C588803889218B831BC5FDE6578AF6424E96FD845724D2320341F +462000,u,A16F00FA1A5490F6413F082C6DCBEBC50901B76E5E13574BD001A229700F389F5BA97A7323B77FE0B5CD2013EAFFFE065ABFA9D2005DB073 +463000,k,E67E98EFBE2AD79EF2CFB612064950B668A1A21366436CEA1135982F0A66032043C787FFB4EC41E58FC5EF7091E998F4E25FED4BC36DBBB3 +463000,u,6E7FFF04851BEEC3C93041CB043241BD26A7F900CA3A115ADED2438CA11CB01B6E22C77BD176A744406FDBC321666295334572074DB72AAE +464000,k,0ED9246691ECC68002B26553695B6754B53CB217E09B9501F74D1248F2539229EB129FFCF4D95AE3D64937E160633D7BD10024D35492B384 +464000,u,4AA2436C3D05E29EEF196D35EA5A422F23B207BD6575F07F6111967DB16A00659C4546743D029C8C43DFB608DBAB186DDC36D92BD599FAA8 +465000,k,37F2B169AC3EB61BDD132197A379E1F6ED51F43C11BA6DD82D1AB03E4A2EB0B94172F8922C16F19207F3062EDE18E91B46E7DD7406E045E5 +465000,u,E9A3C0BF62FBE87C951207070AA31016B022AC2011AC6C18D9D0FF9A892242AAB8E4BB914F848789D2C7F62E4CFC99B9A72AE2AF17BD8BA7 +466000,k,AA0625DC8DC66EA7ACB8705A650107DAFB6E9183405791829D6D30DC2CA6212B9D2A71B3E29157E650796E4200064C17B4B2BA4F7587F908 +466000,u,D4AFD5A19CA2CA8A6331C1594EBA6936BFEDE8EB959A7B5F859C7CD6F8A29ED8DA7CB0164BC2A0AB8AE1BD16F7CC1CE233F731AE17B3167D +467000,k,F0F6FA611E9C3BD298F1A839F641AFB3AE566949A5DD681FD4338C37DD386F77349586A95F05AC008DE66F0973310E20B3853D69D518A39F +467000,u,7CB7D04171A615DF7CC774B7ADCDAD8E37EB928B3E2B02BFD7174DFBAA771BB36E53771DDF779B769760407F8E8A31A069BEC0F979C9951B +468000,k,481C3AA559EC0CB2EA211AE571B878D6B86533DFB3BDE90E97445C51E9E7E669F564FD6F0F8FAAA1E74CA58646E1A6255ED9E0D5A0F32041 +468000,u,C2561B171342C8FAEE092F36EE72D29555A87279BF6E1EC0FA0EE05C08800ED69A4E0E19A5BDC5F0858CA4D4E79A925A9596517070B86CB8 +469000,k,F00749C129D40E6A5805E79848DA17DC7E9FCE808FD3001C2347AE9CAB8FF27269AA35B2A5821032D3849FACE20F33A17912B47B980F418F +469000,u,168A014EABFE152EF3F667F7AA770EB8AAFEAA95BDD08F7C7947833FE9D8133D58E2265976C0C3E5C30A6D9A57593B44DC000FC10850465D +470000,k,6B33B4B570323DBE7D52B58CAB7A78C0A5730317D29A431E9FB6F58E96E8D536DC231EB1FC8BEC5081FB4CFB18E38BA4D79CB9E228B74F26 +470000,u,B49CB4ED7C2A06C03D33AD07FA330CE55D8D9CEDD69BF0DFBA66F5CFE76DF61EC5307E572078E57740221D49D992C82BBE09BA148B1D749A +471000,k,309D9AA30F67B36506AABDA49C5CC8AAC9AC089C28568303523F7D0B8328A78E95ADCA00B79EB5D94BFCCDA99176E35BC411C77D099CE5A4 +471000,u,18C292F726C67537C24CBDA65A9E1F17896C3CEB91F861FC48E57DBBECB64117C533195BFEC371FCA3B2E25B5C8A72C95899031907434B6A +472000,k,3B45C20B15521D5CADAA060F1DD0143AB98D9253FE8EB472F9291B508947F40975458264095E8D4B3414153AF52E00779CF448F497F47FE9 +472000,u,6EF50E14CC2F7F862FFCA62270BC84C9A6D883D74D63057A8A01E3A9DAA0192A49885D71C78480E6285ED184BFFCBD31569DE89FECEDB346 +473000,k,FAA9D87239DAF6AD737AA8302F0D9DEB0490D38E2F417F81779AAB9869F8C9AD4017DC8A8670B85DD72244610D33A9B1C4EFBB595F8328B9 +473000,u,7143E99EABCE0FF3F348D6E13F86107E54059023F4D7BB3909EB39DD32B16980DDBA077E17E217C278C81E0C75CBD6FDB549A5CB5AC6F9DD +474000,k,321E5689B8782347F762068C087054F517A60E847BA4564BC7ABDDFF155B7BBA35C1A32E8CB7642EE6C819A49965D242427C547EEE2DBD96 +474000,u,EB799533EC4A8D802C774CD9B0AB55A9C4FDA36185E19F6149952334C6828402635FBC90AC30788A96F7CA13F0858E2B55395D471B5D7D74 +475000,k,C3D2DF4E769C3C1359F1CFC12E0DE4AD1AD818021061FFA6599E4BE43C8B0D5A1672BFC5D9BC61B53F39EC2E50C3BA1883A94B3EE065F64C +475000,u,F3A608E8C7B9244693351471E82ADFF53EB2377B39B5D5F25E54D2E87FCD7C1E97011ABC3DE557DEE08A2187D0AACD6E2805C382218F24DB +476000,k,FD731022398249B0A8EFE72EAF80125FEE1A46E984A377D13D307F8AA2A564D3D5D933AB4257C0EB8BB8F1645EF81E455802FBA66969D6EA +476000,u,6BF9C87AA214DFB6815C0F73493425982F60E551F3711690DA645F59135435AE75B75A3F89550AFC90AFDA1B8AA0E6C284D691EB47BC360E +477000,k,E1103CF1B30A54E52C61F6C43F9BFD4368E43AC8D0D957FB8EF23308681355726A32C18D607CCBEABCA5725FCF6B7A326FC3374BC30721BE +477000,u,0BD9D2C03437B4F13810274000AF3FF51F86089EAAA79309686DECACDD8E18274FBEA24D74189520A0BECBD78C044B40434C726584C7EFB1 +478000,k,626ADE3CA7AF881FDC209367BE9C97DE2438C4485B844B8EDD55A08EBEE62223CD20BFBFD369425051A1F28F3E36DC8B7C7B98CFBD657CFC +478000,u,8E9063095FAE92B879B8EA5A514A58C268D920A681323E255C6D58B1995B16B98A50CC4E20B725D61464ABA2746C4BE846B6C8BBFF2328E5 +479000,k,975EE5A6DFA1DF549892B92D04F03BC51A4007BC4E6A2E8E8EC3992F89AE1A62BED673684C74BD89B0B42E14D06D1D0525A8F4E195764B26 +479000,u,A8B7F1C2CE4A36AD7A5872F39EB94CB019350FEDB70762AAD338D8B009DB7B7FD0C83B98BC70E39D634F96FCFDD54C70E7E74A6ADD1F2E36 +480000,k,49BC67180C6B86989499FD565BB8D977CB57FF820139590CC479102B6B84C507C195608EB3698654218DF447A7CB196D3C2744D8F3AB1293 +480000,u,3E8C43DA54CEAA025F533BD12C656A3B2AED40720C73B445516073DEA774DF1649DCF366A837001E63104AB8B97392E8E825B773B9B3D0D4 +481000,k,EAA7996B7F27A0FC75172B9016533BCF616D1514E222E8A20037826BBF5089030715041281AA26D37E7F3A66CAC6BDB6C787665B94FF598D +481000,u,368234B2E9172230A87E54B88D980F61D3AC7B86B400723DC53437F61A95A4E3B4EB91356B6E132927189C932721775053FBE01EA3AA3864 +482000,k,A1BF6382B9BBE5387AB0D2E8E4CB6F77BC7CC20B941A8C6964CE39B1796DB0D17045FAAA7E2BEFD3C2738928426821DC4028C58200B19779 +482000,u,47F869837BFAA4D452E8D4C53F47E41BDFAC3198EB853400979A7214C5F8BEB09B32CC551ACAC2DEB614C959304A318B84692B20BE657B9A +483000,k,2FAFD54E0967289D1413C7D23372E82CF388D0217A2386C5FCCB2298B0264BF40031985DC46BDB77748CA0920672E574C9C84E5F45001D17 +483000,u,6D307D085AB589173BF86B164AC4B2312C2C9AEBF381EA435B26ECFAFB634366B317A3C1C7C9A7E74DA485220B1B7DD3C06E6CC846102F5C +484000,k,1CCE2EF00812215CD844F7878D2DD6B8A40F2BE02EED2D67550EAF53D266FB7820D3A32A90744481A20DCD1D70B7B8D7B6776C34E0F089E2 +484000,u,4EDBE64F3A0DE899C6DF5B78840BC53C5EA8A3A1E4FCFC0D44CA987839DB2D23AD8EB2CAA235BFAE1E120C5C7D4CC62EFA62D266635552AD +485000,k,EF0A612A337C83589E962F1CB1A6145AC4082DF786F30342F4EBF2BA907D2EB592BC05EED88E661C843A2B60DD51A1346738E40C943289C8 +485000,u,3907E1F7D936C364F28BB2A0A3FB95BFFC76BC075F52AC283366A8D193AB8869AD61EDC3F36EDFA51940FE09E85C398901CA29615E843514 +486000,k,C034DBCE20C12E9C9BA8B16FB58BF210C297498DE5E1CB472774685804E29C25D655BDCCBAF170D9D2A9EBF78CB31E5EEC3474642F8BE7C9 +486000,u,FFD6CCF5C3578A75CD54622A22498B4C270659416A9869388B21C1BCFD31A431B53F364F7244773CACEAB839EE23F82301ECB562AE3A162D +487000,k,4B5C5C66FDD216FACBEF8631A5E3E0D62EB4DB2456545E7D740ED41E69E7CFA9FCFE2FE5E2799366A61A9239389274D9CE0C0ED4F27CD79A +487000,u,2E27F1AEFFAA8E9078D929FCAE42455084694B56D9411FC8491B592566B7F690A807242A23B1F5AB2292B5C71A7642EB94F2AC7C4337839E +488000,k,A0727E3AAE00527D369073A9740ADD43ECC34C8FD1DB110FF4AC6908A255849DFEFF5F6586E874A0EB2C0FF8913641E53AE8BC6BE01D5DE6 +488000,u,73EDD6D2E5638904C806662AF4AB0BEE3FCB011189CDDACCDA3815D54513160FD26B9BB1BDEEF2F88CA922F04B3084CB24B68C390AA5E214 +489000,k,44E98A1CAC2AE3DD69BE318A9D0B95D3647EB842F7661C28902B274FC03376748DAFEFB319F5E86E8438CA04BDA34F69F30E4530580835E9 +489000,u,23A85910E7DBD57BD028D833E46022E0E97EA94629E2A1F9A558297F61C1BB9082B18C8782132C0FDD3A8E5422AEF8BD1C5F0BEE8F0D1CDF +490000,k,2E63D6C56088F88D0D8A2F0D7547F90273128159C0B6BEC0FFE3CE718690A42919018B6838FA72D0F84B7932043D2C98EAAC2AF9E8199B24 +490000,u,866894788F2C3DFABFF5A3D4A3D1A171989C6575A9462B8E688EE831DFA53427FD0E630F9423E3F542792D161390DC7386043D98C5AA9A92 +491000,k,73B4B9F3A45329FCAEAA7BADC161E5BD6AB280AD527323008053B515B326AF40BBB98F2E9A029E25071D822A5201E10C19E9398581F4E8AB +491000,u,1C7F18CAB149EF33CB0E281BACBBF96666264D929D88C7FB89089093D802AADC2F63BEBC30D5CAAB77496CF9592BD10E9F17E54079CFC30A +492000,k,F93B3F40FE721A250A68142563D61F5FC3F7B7FF9E97A4684EDC82A9ADFF3FDF361EAD032D4A6EC330A9A8B3EA7BA917D03B52A53E6A8534 +492000,u,191CE27BF053470BB9C5AB8C9D21F97B862EADACA553CFA0672771515144DF7605243266E5180181E998A57C2CAD1056686F61D23272BF01 +493000,k,CA56F843B873363707AADA4CE2EFA15223CBBB3FBA3D5F2365D75E69DD020CE000E9F0E056953413163F93C03BB2D2154CECD13F2153C30D +493000,u,17FA30BE1ABFCB7135BC2D0675D94D75250A7783E836C97E29F77D0F5E351292476023002FA757B5D760D8794AA8EEBB66E377B08081920D +494000,k,052AFC3639A1A234582CE3ED42A8A45EF31B55D50EA23A1BC7A7FC0C836E665A11244011EF58CD2303ACBA1777E60976FC9512DF79876748 +494000,u,B82FC4DC539BB6B1D9BA56A8273C2777AFE9543B847FACD55B47D318B98E4E74514BC1036803915588D8C3563F2816E0ED13AEB34EB05871 +495000,k,64AB2F751C0CAC7074981D198ACC0844DFA417BBC49BB8330E15A67B5866C4B0EC56B14469849380C39043BCF415C060EDAA438F63F667B3 +495000,u,4D5191F70A5F7A2F8DBA16D4230078894FC0085DBBA249F1530BF893D4C557150096BC293B523EFE33C49B5758AF0305DE7C2D9CCE7F20E0 +496000,k,D20DF0290DC6456F06F86373D6219050C433968E8665D05F9BE4ECD4BD644A9077608FC71921B937671877BE6424B25CA5233553FFC65F60 +496000,u,E83F64B4E85B93FBB9C769CD4CEEF3C67A15ECE3216B3928A6591357A835D5B40087FCD0EDE0151A6D854E6646DD5165F2BAF9D53A461784 +497000,k,C4314B91A02D6811127DA9E63D05C312717D20E59712D14690F3EBF7ABC497812CED1F358613DD0A60208022D9A43625FFD62097F56EA3EC +497000,u,4608EE684666EC3C60340FA50B09606E66E44A0AEE029A44016923E8258ED31A511B0062990EC291C759450835FEB2495E74CF6B9607B113 +498000,k,50324BB0436023C7211C070C15B30C35979DAAA3A8B04CBD2FA428625CFE67747BA7C0080C401B70D1E90D490FC6C25F590BAF1C546BF31E +498000,u,373C7662195545524CBE9EBC0933C90D056DB5AEF5C90D0F5701B1478B6D27A45F6C36953C0DE8455686D920F10765070DF3BC43AE0A6988 +499000,k,8891F46FAD09554F8F9D0CB6EC99E8D6FFCC2642D35AE1BBDD84CD3383E1D91665B0752A9DF3315C84CACDDFB242789719AEC25FC42DFD7B +499000,u,0B729F3749B09572F70A6B648A9DD605B183D7E670D648D7489B3402CC6BDC0BD9B58EF36B01752D80FCE0AC0233255E39B2269102916901 +500000,k,6716809869A3939A2017CD86073A70FFCB79D9FC9AE7DDAAFF05F1E33A2A568CCFF5A8C1210044B6E5E855B0B6BF155C20D9217F5972908F +500000,u,D66687D53D623FF7A8B0AC538CDDDE740C1A68EA2CFBB7B56327D7B3C7740902C4A9B8D1B7EEF158230A613006406529030F7E75682A024B +501000,k,B5342982D9D4B666809DB7CDC6C065F8427DDC1D8D976D45764DCA5466E58B375CEFC7DA5833149DCD8B167DA42317F383FBC280027A04B2 +501000,u,0F2FD63C0250F87B77AC677E93418DC52198E0C2B61BEADC76FC17C24690996007E63958FCA5E66089390996E0B1B9C3DF84C57244BB1CB3 +502000,k,23B4DE7F82353EE5371ED6EAC45BC0A5B4EAD4EED933F6CB0A5F5781F9D21510244AC794ED59AC4BBF81CC7AC636897763226832111C6FCE +502000,u,87B798DAC603DDAFBC0B3C825DE4376B7DFACA87267AF36797C9F2158742DDA2DA1422FCA2963381FDFAE68D4A6258D4C5A09728614654A0 +503000,k,5BE6936813A4128ACBB8548366FDE2972579716A504D4349EC12E2EA77C24E2BAD795B2CF48FF9994CD4C74A4390BB6E5FEA67D219E00B0A +503000,u,2F5CBD020EAB8F63AAFC71908097CBA88F1657AE3BB382BC77AFE32502741BC23262B512CA66FFE9E649A8DD09C96B82CA04D8688D7AF7F3 +504000,k,19AF96C02C40861CEBCE5D5982A39FA42743100BD8C5129510DD3C4FC75EE5F548C7A27608D9027AB831636C2985040480326D8813612DA2 +504000,u,87F1A95563386CB27E195C20AB5E6182B9D590DE7E4682B597AF1E8FFB321902DC274EBBA0ADB1A79C45E46A3B43D2724FE32357C370E43F +505000,k,7D89CCDE5545FF26A1314889E04166B8CBEB5D40AABDF04D3D873314EC4B0CC673A3A788C88CC1595F95C7080FFD820B5A007DB90F09BE0F +505000,u,5E6B35890650AE8E398C5304A2F59B8079B500CB0FE3F2882A73D8143FC80889E7DC4C37F96050A0C531D51493481D8BB1BA046160A34F86 +506000,k,D3C96496DE1E13E0C29C25E6D89ED9D460094EF5CC9190515C264CD492DA11C376B9550E848751C73AF49C8EE7424068F96E1A60F9496E66 +506000,u,53AE0838F043090350CA20A627E3BCF5EDAA363D479E5537A9B90396D117B5B16F6500773F3FDFF1A9C1179836A6AAD8862A4B2C1F87D4E8 +507000,k,760C8BB326C74AC60A5154B211DA9935C1A0A380A338EBF62773957D25920B7274BBC3D4365B6C1EFCA450B16734370FB1045C4E0CEDD967 +507000,u,F681C6ADB0540DA4175D69AA785B358130CA4B55B558FAB7ED88689AC4B0DF53DA7506755F08C00E2F2B45043158D8F633694A1349F3A2E5 +508000,k,0659EE43A55A94E47A8931B396064FA5F1984368D5670B6D008C32C90D116020ACA79CF8EEA091ACCD453DB35887E47E0D3C71D01FC184C9 +508000,u,39C0F5A8BFE7F97D7C4CF42B5E036D7211B9A58FD93F7CE139FC2AC8A145BF4A2EF250AAAB284E48F42C897F84D5CE21BAA868F3B8EE07DE +509000,k,D1C246C72E1C1A59F4B343EDA2DC0179AB77BC58B51B24EA33AC62B012F4D003012E42D3752BFD6FEE8E2F2CDD02AEF728964843DC4232E4 +509000,u,BB1BD1FB6D5509D7860D6A5423019128E96FE76F0B2BB6C9FB6FB6D606AA08E47990DD267BB5E098148AF0BDD547A430E329978B6BA161DE +510000,k,65EE334B40CEC408167D90F802992B1B072F253114D7851A8FC94D830D9F1D3A208BBE2BB0892B5CCC6651B5BB95E2F16C93CB5FA9998A6F +510000,u,7665972A508756EE5A601D0A25CB6EFD10D500C21BDE920EB7A89AAC82CF86A6E9170A586FA8B07651ED962AE1DEDD6289863AF043857404 +511000,k,3A1086E705F6699328F38F1D4B2CDDF1C03746E264F579383D56AC3DC9203D52DA5A7C54264CDC293ABA23EACF850719B00FF093918010CD +511000,u,1E171C6EE540668827B71FEABD0949AF135EB72F44E1A97EC43E801D64655CBB15E05DFCC69EE9B55D24A92637663E937BE4B598F95B0EBD +512000,k,974D298DD07DE0FF2617DC95B58077D589E51BE17B73B5E989D0B982F548B9B65F6D3674D4BB44970C72C55E78A2AF38C2E3EF3F7FA44B59 +512000,u,DD43D73C743F772193D04F7D605511A6FC6472109E95DF15F1C2D8E53B9385E518D368384A49FD653A380FFB003BABD1B8E5004FD78AAB13 +513000,k,0D63D2F72ACC7D248D0FA93C26DCDF62C25344E6CE2B41B38BEC553A4FC554950BF6C8C355254A4F925C4F976407DB48F7B7EA8989BB4377 +513000,u,9E26092865B43B46F60BDEB537DB0234008CB483E507C24AF5FA8015540EC5E90AB4A677C6D030979E00E8A9BAFCAFF26B2253265F548ED7 +514000,k,6ECDB4B8B78AFAEDA54D007A2E7D6BA53A4C36AAEFEC429C700B38671133D43D242A29A0F7685418F0D040CD246BD95C240E139701A348AC +514000,u,379AB972D5C10D20E3E3E3E3F1D57A34A63E126663BA330FD13A1E478AF138AB5383F6A46D3687A217C69FE0F676B7BE5B351CA83B858F40 +515000,k,CA7E0F154DAE0202546D41E1432FBC3DEB307F195D647E5FC52BBA675999192BCE09F3BD624D73863A6421B5C622E75F970140E9D95576DD +515000,u,180392F33A0845DEFD3957D5D731B577913B7939A357F03930F918CACE108443D96CEF76067196BE26D647630C52E99A73C8A67B6EC66605 +516000,k,094AC2079B472267312411BF67049730DB270F306E6E93B23EE396144F0C4A854D59E482DF57FEACFF913FA94E51B034DC25EA9D6B1ECF6B +516000,u,8CA78F1E0884287DB0F151983F8214C767BEF83549DC123D36792E695E9C8737BD7551DE11B8CA9CBB166E6525A611B20E17F16FCD339F7B +517000,k,51A61835A7D024DD4E9E85E79DA712192800CC5BFC0F9D07742F0113DD2D7382D680AB5AEFF0464887403B525A3009DC8233A780EAE981A9 +517000,u,28A55EC474AAFC76673C675AF9F9C1368B486D17C9FD2627F4BD672A872BD509343021D868DAD7608056507F06E50D606425C8ECCEE973AA +518000,k,1228397EB433D0A4AC08FA06CEE44543270D9C3ED5518015BD7FA2C430C0F227AA582EB9D717969968C3BD073B8D00FB2C2153AE75BD82DE +518000,u,25DA17421BAD6136D8745C70DD5A6E07A7CD3F1C8E69CD9254FFAD21E1B49AD01221B20BFE91A6FDC1984213BE74CD43BB5694D5D3184710 +519000,k,E209437B47E78F7ED2CAD4AAE60E599C0548D69CA7AA156945C3FB4738EDC03D39A9945857E0298AFFAEBDE5F0E449AD2B4D5B6A134E02B0 +519000,u,3095D997E3990DD0978102D5A95FD62AC50D68492650D002E77550AEB8A6529628808178A614E83370107F082E5E88FB7E683A20C0DAC2D3 +520000,k,121047A588D1DAC8F64DDFDF1F39B7FEA8F304B31AB472BC0B9A3B997F16B5EEE72AFBE4FBD0B5D57870C29A49FB9FA8C59F88B65DB671D6 +520000,u,DF9CB4F99FAD45D93F9E5C2CEEC18A27704153410CABABC651A99DD08E8BA1AFFA00D726FD1814516A5CF88FE49AE7016CC4BD2906602D03 +521000,k,8170B06872951B0C4BC92DB6A9D310720B8786C971F9AF013EE4A7AF7CBAFCA9EEAB3C3173F4550B228D6C202551F296A1CB1F4D6CC3813E +521000,u,5E72CD81382891B32391E7728168250BC40377FED5F11E314CFDB1C383AFDAB3B7394678BE2FF92F6BB16875408FF0D0554815ED1A7AE6DA +522000,k,C76B45122C1DCFC88DE764BC2CF9A30BE6FF6BFC9082ABD77F3E97A3CADF51F66AB92AB9FAF51B96523BD0286FD1FA8F64CBFEA2B5918C6C +522000,u,67C342C060BCC31E8C03308BE328EAAC70FA2F1045FE83EA39874570C26C99B3937F685CB94698BDFED5F852C1BDAAA4E483F2A33109A603 +523000,k,B35408FC6C7A23EB4DB1AC5D516AAB9AFC24D6F6AC8C6EC3FF91F7F8AB0367348B992FA18E5588F5C86DC2C55EA637BEABA06217D341F598 +523000,u,4A7BCE48C1F49A8FC53E07B27C511C334D5B7C749C100EF52F795857264A0F9DDBA47CB4BA654B3509BE01EF3BE2CD6B803E7E2A1761D804 +524000,k,2B5160ABD48348A274C56046F6BCF1442A84485284568508C2BAD824499999BCCBEB3A9C68AE9BDF7E0364A1BAB9212F16B412A07DC713B8 +524000,u,02114291AE5F44EFF450E776D1932B56663FEE98B7E21AC2EA6C19BFBBB0D82FC11C1758442FF932CC7ACABE9B6490EE190210399058E2D7 +525000,k,F32B0D19C81C551C595C78E841E7E9C61693C5A39B420080991AF829479016C180E23609683E9C2C38E255FFA9284BEDF1CC1CAF4869595B +525000,u,EBE40D476BCF280617B763C06DE89DED9D88FEECDB342C9229C958E3B9006D193869C01FE77E1C8F44468BF5FC2209B12C0D8B198EFA6563 +526000,k,14EE2E22EABF253C6957B62DF68B2B2C35C3A6BD0753401C741579EF62775E456C40CCB4D5C9D339274A14240C880BE58418C36ABF1721BC +526000,u,74B06D464BED4AF20FE49735DA2F4F1AE32E9F8ECEBD9EE6785142D52C7CC8153D406107C4DA9BC488419469AFC75A828D5963006F5B8033 +527000,k,AC4B373E46D122BE3C2373835155DC0E5AEB160B4F0578065865ABA4CD84085642C4E7FD487924F6B3D3ED88A5C30F1F5CF4483455A91DDC +527000,u,ACD1984C51BC980862F4F862534A55CA3B2635FBE101DFBB08242AA380CCF44D476283C2353043F4D06A6A3961E3E31EC032170AAA046835 +528000,k,898E677A98A39493B24132980C48631853EB08E6260C083FB337072F6D90CED391B2721F3682F992CFA16CA3D7DDE6E1E75F3D51F4E8CAB0 +528000,u,F9C22E6E5C6ADA1A96D7EE507B3F8E2D128EEC43AD3ACC1147F94478F2F3E142A277F9CE4AE499B8360366EA9FB7784845C7524C5C3CCE03 +529000,k,0B6DE3FE6DD43B3C05BEAD4601E2F7D3FF746224ED9EE98C9406A23095B04AE405A5A22DD73F035C5F9A931888A899D0DFDD8C37729D1ED5 +529000,u,D01A8FAADDFAA105F4FD95DD65070485A7221510582395461AF092087BE0DD4ABF96A142B6B81DE4A858F37A763D5B3B15DFC2F1D68B58EC +530000,k,A9E0FF26C506D898F613B20D31619B127924774885377BA72CEF7FB0D2695DB331D94DE1B05280AEEE9DE958C65011936A29A41CF0E64A77 +530000,u,69136137798DA08E04FB18814B8616FE389D937532A76C363D42D1405E639AA1AFFFD9EFE116AA0C518C38E3A7C22E77DA55345E807C988F +531000,k,3FDD651F4F810D168E4531809D32F9E88E2929FBB8FA98A46AC8547459FB3EB8845B3DCC3458AC77D934B1325332521902F6B0A91F9C5326 +531000,u,42B5663E2CAB013AFA7B0D676216789DC35DC5640EC18E835F6E6347A506156138A9070F7825F5F982F58140D806143973F9D08B07DC81E7 +532000,k,9D36189CE323A8D08E2D3C170EEC7051A281B4442854A1274C9A70E213D560A988E03EDD77AB3509FA7D7E418CCEC2CE1A152E80C4C4F96E +532000,u,EDECF423CB48E195BA79AB30F3F42CB2B067CD2EDC810080DCA1A15C6B5E08D9BB5444B7831DEF7A0EE9A76902173361B1ADF43706EA3968 +533000,k,F8F474C2EE1F3633353B01BA7092643E5D6CD307992E6AB3FB76F5BBD7CD6AAE0063951AA97785E4D3D7D66FF660DE43E350A5665D02DC13 +533000,u,6A6EBEFD7CB523FE88737D6B3310ECB12E3FC05F4A2A526B7FBD09D16782A10FF344E38C318242652DE7876B0CF26D17D5C6C1E2761CF78D +534000,k,13C7660816B2B809E3AE1E4932CBE60672BF9E48307B75803ECC8B308574E443568507B4762902FDBE02C766DCDE068D593D6C728CDDA0FD +534000,u,D40D4A7AA8195E3096225D95B2991D0AA870049F4DB454F507CBF6DE90CE665A6953F9020CC4AE10000BC2628ABEA37094AD6FCA87B9A17A +535000,k,2C2E29FBD10FC4A000848C2343E68ECF372699D4A71AB57E1F018334A8FBA07F8483A056D8AEE80B1AF069395B343DA933B0D83A0CFA3CCB +535000,u,532A23240C74147F830471ADAA468720D1A5B4F0F0DB47849233A6A1FA0190D62631FC7EB2A9DD8E1D6682564A876692E8FD4A45A8C18C5F +536000,k,9C415193AF6D9C5732FD6D43892A405AEE199E44165B50E91C2D1ABAE9CBDBEE7B2EE5CB65965D6111C96B71A587560BD72ADAC2A7D640DD +536000,u,52D954FDFD59CD5B86789CB0436B135763FD962D0E0A2B4DA7C67B08CDC74F3A1BD9255767F311EF50D8D8066F0D564F0B5B816991B891B5 +537000,k,4BB6735B20104CD2E267E58BCCD0C094B63765B7619E5D5444CF5207127F03FCE5C381FB908F26687392BCCEB8A2E2EA35176D0469DA3E7C +537000,u,E05526894C548F1B1FB862814192C702AD309D6F4DF4CDCF833C133147428B34E3005E50A708838F1FC997E9493792FA8DC229E8867574D3 +538000,k,F572C2C0935F033C9D061FE3F55441C349CE35F7B7571971749595A5E03BCD792DE702D31CAF7384C81C5A7CE93FED9B2B9DFC620A34F66A +538000,u,47840CC422D0608EAD7ED729EF9391F13207D46D0A80D61DC7471200B648EE7DB0F6373EA8116EBDB95724451097079F1B05CE443E0B733A +539000,k,DB6D94279F8F086F887EF3C4353ED746DF968599B41CB8FFDF4FF6CC34752C274F8B2D4B28E243CB20D989FBD2F281FCFE9312656E809956 +539000,u,FAD52405E42E15F6B9086BBC70B334EC862A715107EAB3BD96D900CA62407005D4996C1FBB94D29840A0D9D2F0E51A1D357674215DBCA1A4 +540000,k,7609B088CB9A0C05628A1F9E94FF590E0CB538A9DCE6B7D5C4D0A60CC182310BDAEC17A07BF9723FAE218BD39C321917464A2D76DFD48245 +540000,u,1F34252501D884C645C98710B1A4EDDB4881DB3920C8EBB1ADE5134D922E80A06BB0D6F039B6B8D51629135101C64C208C277982CD8C545E +541000,k,D952B5A47223A0314BD0195E24AEAD6B6FE753FB2615C90EE5B76827A8104C284D48C95A095AB1F60E1ADAA39DF22282FD952D8801217D11 +541000,u,542DE4DA9DAEB3E3ECDA63B8F0979A585098E80AEB3E653BFA12AF46B959BB62532CA563D23618EEF0DAAF7A9C8BB199BC678CC97E852D9D +542000,k,ADD7C57479866A1F741303102D866EA9C3D0D856EC0929BDF8ED278F9900BA7D165C9887E7817485D6DEFC1704310A06B32A2A60642EC346 +542000,u,60ABF5FCC5F6B846F51146B040563185F7E987CCA46AEA1CFE18C9235CA488A5468858B5938718BBE609386AE1C066888E37771649D9A592 +543000,k,0684936D20C498F4324AD19422E1E03873003F79723F457E0649DFA4D66E50823C466D3C552FA7D6656D2981C635FBDBD637E66CDF170645 +543000,u,38DEBB5A39430F5F17309C8DC7FC59302BF033961E8760AD97123D7800FB0ADE11679EBD53104B54706CC5B2B76626B7BA56C8D58BA7EDC7 +544000,k,7D45B7A3B4AEDEC3F4B18953D7005C58276D5DFB5A5B12FC4461495E6520D93F10F4F1AD482792F168F6598704747C4B1FEF5160A2C6114C +544000,u,844BD3BE05AEC66DCBE0E5600D7F4DA94FF6428E4DF9FC14943E4544C52573715C76F03F2FB0247D920EE3359EE0A166FA2C0871695E1836 +545000,k,4CAA226A9EFF7AEB091711985AC8B904B30AE18CE303BAE893C69263E9FCD279246D14563B41B441FBF171D11BDDC245C79967E2D1A7BA09 +545000,u,E01D9566A30168495790B9961EE791E93A80535C8D543DFF597DE929D0E49849533178E485451C532F8F3A44601261AA88F7FC83D5D6958F +546000,k,C9E78D217EBA712AFA49D45032D751C1CA2AD827987708293F3ED9FF2390D8A984E991C603F1EB3722609E89CE6EF315A87247E1D87E4F63 +546000,u,B2C2CF8D7359D260AF573A5E3D3BC4CD1AA59F93B6C63616D02791EEAA481BC5FF97CAF55B40074CD01D398F0D057975BF3B70BD0DEF5D4C +547000,k,F21FCFEEE4700075FE936733C4E803AA6B27EB379E9F4BACD1DCFC67C8E3C53552F237358D8FCB9301278A903BD1FDE96931BC76E54AA1F5 +547000,u,25D5301C1557088A4CB7BEA2B82A06DC4A581E1E873B994C2BB13FF8BC59389B51182576B9B104150388A003496B5EBF4BDF924BC28412D4 +548000,k,ABBE7B8D3979113143E9D9FD02828810954D82E41CC3E8C4D304D644E9E17CECE95F09CD9647AF4261203967D05852F4C14CB9DFEF6413A8 +548000,u,C2261B5117F374E435785DF8D8A5C99FD42DAD6135F2630825E121E8F201C964786BC200AC60B478574E02AF6320BF260EAFD24F13139A61 +549000,k,AA55A6E206C0843CFC8F299A9B91A965848BD77BD0EF308AACD4DDFE4C52867FDB7BBFEF7D1271E2B16CB395300732948741300FCDBD8B06 +549000,u,AFC412B2E339EE7965CBDC9F8BEDDF8F7FFE2DDFAE57D5F3827CEDEF1E6F734646805E80DA854093725B1DA319FCCB9DE19323D6A06C4F6F +550000,k,F95A7F31CD009F93495604A60BC0B628CE950D5D33D2BB922454B8FDBB864EA637944099CC68039922BD5D410299FC2725E4AA6A8C9BBD00 +550000,u,6C491DB7D76FB883BCF739BDF6DEA45261CFF21A40EFA0DDCBE19EB3997E01DA5E5C9E1101768A2EDEAD9C5B098C9C24C142AAFBE5B756B1 +551000,k,550606785C2971D11BAFFCB5AE62D7EA8055069AE91B5B8BB2D323403C7175DAC8D393B7D09B375300BC059ABE1D3499D56822FF5048E0B9 +551000,u,9A8C932D10ECD96315FF22E0DA7ED9C0E834D18D3FBA3EA50155321C1A68F2779924AA1039A10FF8143D83FE9978D2C98844F08237612726 +552000,k,E3DD4F6E77B39DF3BC1D7E9A31255390660EF2C4ADA6203681FFEC8AFDACF0A155EC23454891F6030B7E846069A90539AA56434768CA98C9 +552000,u,73183AC9CEF871C4E4628C04C5861EA29E1088107EF72C26730D63021A0C5684C9A5B3B0FADC29F4986074DCF07C8D6591153650CFAEA9EA +553000,k,851F75A967E2B79CCAF3CE15C706655B0DF84EEEA0D82494958B85549F82C0989FCE8E4B755A6BD17D27DC00EB25CBF1A046A7AE88826ED6 +553000,u,694AFEE333E9E4E9EC7CD1936EFC1336A3A19D14A899BBDF83B51A813D0F783A90CB0445E832D8ABF2E616CA088CC5DBDB4104D9B4D4080E +554000,k,837734F9438243DCB9511C81A6615F185C79FDF0CFC14ADC2B363AE269347B5FDC306BDF91F9E02D9FE7C66DB8C9F7A1FE0CAD1DD509742D +554000,u,F640C1F67A7CC792C75FEE1B0FD000D35FDD60F672F899E27305B5AA68A7A4A3C7CE907F0DA96D43FD202854B58D88619BB1627C0217E866 +555000,k,D1DBBBC9BCC328289AA2BF9D2646A3A921519A10F2103CC16A719D6014F951238C81596A8B35ACDFE5B0F347408C7CA58650F3CE0E11E84C +555000,u,4DBE129FBA97A9D2D56C1C9E6C864809A7B219231DA0D16E6E6F0F9AEA359AF27A23100602BD52CD4B193E1D6AF9DCE347D52B73DFB97DCB +556000,k,0ED26A84D7E24C33A83A7D73C1852FFF0BCD963138F4063B68EBFD1E74D34EE2034E6F6C7378F8E53C4E95526A986C96A5F5413FD9143D2A +556000,u,7308DE66C809001A97B207DA2DAB7E9EA43252280EAD349733D68685D103C828EEC277DA6D00A953EBD539080F1CAA3DB948E86F0FD168E3 +557000,k,48570AE95387A338D6F0F9372134EBD3117AC151620B3E65DFECBF3C9A4B2916D8931B3A451B31488DD6C8FF99AF4E509EEB459ECB1CEFCB +557000,u,D992E54C3A2901B2405A3D8803D773E63E57B68BD954DA01DA4DCAE513D327D4820285A69114929D50590D26C2B33759C0A68D0857C75860 +558000,k,FBA104A5165A4B960EADC73B0619F7CCAB3DA04D8F7222A6CBB2426D0E2B2AA9F43E3D838DE8D8B534A7C8548581AD482CDCD263D82562BB +558000,u,1D213BC210169EA62764B7461C7E62670C49C90A98A9E21D918A0E0EDB28B174B08C1222DF639F7858F9B5E250B28A141C84AE266DDD5B74 +559000,k,B97D15036871308BC3C2117302F2E02A1B7AB8F118561EBBE590A4945B3F2106667D234D6A597BAE3D9115D6818D7142C4452E6847AE6EAC +559000,u,1474934F928FCCC9245A798F5F2E7DA20943A18F1C75A6ED65F23575890B8A2BB2E9991982C480CBEF941F14FE4E77629F434EB653F614BE +560000,k,C956CB3F5B4E3F2A02F371BF58F7C0E1A38BA83C3B60FA81A3E0364AF28F8A222A7C69796961F7CB984E604FACF834FDFB0315122754E894 +560000,u,BC5933E94C7B30E118E7CED2A2B29CB06EAFF7190261100D845EF4268550DF93E1F721496A0F60680CA7F0F3AFB233AB63E1E348E0C13BEB +561000,k,4B64D0B1E250BB3855684A0F68D5292F8B0880876EB0721424F12E63253FC0C2A718DB48B50E8673E5E05BE446737FBCA0CA834C510FB611 +561000,u,79BF69274B8E1EA87125A39D8FDA9225A3526A37ACE4BD602F62A70C56A91E841FA7A0D0EF5C188B84191B5486B93B111A5FEEAE48CFC4BB +562000,k,324F3C4D900BF13803792A2F632AE705FD0EC3BE1A9934FDE250588331A6E4CACFD93175CF8ED6DE7CA2FC89C574EE4C2FB7B8BF6478EC9D +562000,u,07853A7DCD0078A6226A21C4C271C9254F58BED65021B9FDF3A4DBC4E7A340D6E389C50343CE2B0A44E7079D5BFB4ABDECD3CDD207035C19 +563000,k,8E7AB696F89624B47C6689E05022BAF0D6EE851062BE859EA51FC4EF1CF56435A261DCAF9F24377B5A1C9628B839A8643853BCE8BB55439E +563000,u,266D71F4BDFCA0DFF9CF02DB0B0FEEE593D6F19CC2858BB53CC68A0A5B3BDAED2DE35B2ADA6A0426FE9A4AB3C676C3EF0863A42ACCAC8096 +564000,k,F31921BF88E5702E5DAF65599573C29591A5B7FC37CED304BFAAF2625CCDB1205C659DC09AD3D520CF42160FA2C37B3FB594655DBA537D6E +564000,u,AA733D4082749DD3BCB1BCC9661A5D840A64523AD19C2AE84B5207C032362C8417DAE686A7D3F3A800C595FB9DF64B141FB5C85F38D10322 +565000,k,AC3B851504D27C63E4BF56F8E39891A357FF131663774AEF198415E1E4461F970EA5A9641CDF7194EC7C9078BCDEE8512B138DB12278EE36 +565000,u,4C324CD1522248590BACEBE93EF8C54492F5A4004DBE888F68AD143D10EAA22DB286DE3961B76B0F247A7A2C849E3D1F714F463896B76E26 +566000,k,4E63BCDF3F70C17DF8AB09808AE69843F4BACD0254D329BFDDDBC3506390C8DC5FE162455CFC5D5DE2BE4F6944035A4A1C3C974A64329559 +566000,u,29211EB0D45CC6BDE28CB6DB7B48BE32DB150559B7A8C6B4632C9A27AFA85FE47A10F7DB0EB42712F636E8F1CC54ED83066EEEBDEB73217F +567000,k,44B98AEDA39ACE8A3514AFB16EDE979F7912746C6D17DF34BC8B7C824BAE17BBA70C5E11F8297B8C59E4754D06ADDB8D6CA979EC6B732D2E +567000,u,E6616627FE0E40FF2613F0A5B6764339574BFA33CE5B5DE3366C5171D2D920E46087E73214705E0F81460CBBE5734903FF1F8D316DE3953D +568000,k,6963D6EF41934CA7A639CF56FF941F18BBFCD708F417CD6CF0AA5ABF61B1EC46DE808BEE480B5A51BE8CC9CD2F25DCAC1E01D9C1A1C18FF8 +568000,u,88DA684448F2C4B4D63D5841B9DB7543CC7E17BDA6E1EC23CDC998DB4603B04EBB7CE8D9830F056F2C75369CB0E76837D8E2EA53F777BF52 +569000,k,9A78930A73883D2C1C4B59D3B9A8FAB1D2A0889E98221518DBBA098572AA209810335B3AE8D16353551A941CB08F171EEFFD882A8B27D428 +569000,u,2D932549AEF49604A9C1364F8398D359C8943F7D1023489E425252BEAFDF9F3440F4F4C4C89EB0F5EB2681FA799548E60B3680D9669FB3BC +570000,k,35D8051B4B1A9714C82F70B9956B30AD120137C8F582FF756AB7225FB5F876F4E8A2F070FF9396EECCA4DBD1798256180387528764E37B4A +570000,u,24B846F2ABC83DF91A00ACAD4750625A792024A2A36CE3E9F4F7CB8F76AE8EFD9E75982C02151887FC5434C7E85987A4BE7A4AF6279B9AC5 +571000,k,386144AF2BFB8CB704C5804DBB2EF5D9CB4660C6BC18892083932C2ABE336127E3E5CDEBA216EC8CE642BC2B164494D9FE5BF59C075508DD +571000,u,EBC4D16711901BC40D88BCDF5FEAA8DB68B8558135FB610D2140EC0C7B9FC9A3E88765EE13DE466A2DF285F8A361F48BEA2B65D22617F367 +572000,k,5D7797922149B7C1A84FDC0065F465FE03AC9D28541DB88DBC8A45C10B8B0196E48CB229B4B3D552A9FE7E9A7A90B5A551F371E056ECDA61 +572000,u,93C9E1D3ADD51C42DF3653093B238A2E69108B590CFAC1783A7B27340015FE772B3844DB887EE37475D5750672FA8545FAC17662AD2CC239 +573000,k,867B66F28EFB54AE106A625DA67DA352B649A307374C803BD8AA2716A1465AF9BA74C97386775E99F82F3E6B264F72F8FEBDB2DE37234C56 +573000,u,A85362D000AB131046F3377A3C65AD96A1B3BDAD733F176254299D0309183697A9B3C705D828FD6AD538DAEC7C0E8D6675676399FC53ABBB +574000,k,CBECDA46414949B9B65BCF7DEB7DC7E6936330A7D2A819F0A3167ACA8451510E9549A6502223CFC2D55E7137E2BAB34B98AC882904D4EB78 +574000,u,7358E2D1FAD07A053293D61F79C867F1FB43714E78412AC7DC878C22C2DE8134B49D945987AC4060F01363EBB2D678E25C0830E7B1483EB5 +575000,k,38E0A1D225F2B895B5BED6E2DAECFB369912DE63024B77572B6492C31A74D2EBAAECBE5829F80389F46BE713F8993E181514AFD89F140728 +575000,u,C4790DBF2A88666F696357702828C748E0655C7EC0E9F8D32EA2A17D5ED163EBB112611282E4C8B47B4A9DD4F651AE2E0CB84D9E3F483375 +576000,k,117F6CEE30236392E47FD2D96FFA759E0AA97BC22A02B1707C11D86B1B39F07D2A2F23ABB08F95466E8181305BA707189AE7DD72736B7541 +576000,u,8265369DEF55F87DFCC4A0D0E813BB22AA19FEA8A5DB3E61768EDEEC9699FE74754492FC002D0B63768EA5975D02502E5F83B2ADBFE7E5EB +577000,k,179813565F9971F95148A9543D0323A24A761ED6FC4759368809EEC788281243ACA5E32CBC6E34A459191DF6D97A5D8EDCF72090A7846DF7 +577000,u,8CC3DEE95A32E1D8236541C1475EC256D3243660884DEE6C05C0A18BD262C7F05F4A4E31D0027DEDB1A378D9633C7ABECEAFE5F6BD193E60 +578000,k,903D733D31981F3749FC5744D87FA86E8AB84B82216E28849E224C18306EDA758FA7D412EFFE03BCA08128A04B8AD8E6ABC5DBCB56A4D46B +578000,u,026A475086BB5C3390B993C13CBA8AE1A455FACADE369BC3BDA5D7581076981207CBEF187D03A5F908D0668EA504C010993A3E31E2B0B804 +579000,k,95A2604FD5922F3A440DC414814FF0E7DD3E920978C72956C586AA56FC93701B1AB4F9702A477C30BB10BA4D6120B8EF737A945606260952 +579000,u,4A60ACBC408198EC60175430F10E98B8DB9051E29D02D8F1FE4A345426F2A87BBC2981BE3E2C6C1887233EB817D8617F06A701563752328F +580000,k,F4A5B570DE958736B3EC30AAF6F70DE577E0646FECAADBA993898634CEA97564A4ADF8F5B96DF12FC7229C3BF70B567EAF0649FC7EAE1808 +580000,u,3C74B50862336F2615DECE2B38164CDEDDCCF9CFACADBAEB3C8D74876AF6E2281C41F6F8FE27968E694087FD0C451BE2A36A093555EAEC64 +581000,k,9D3E2E60EAE746B81F6E4B533A84864A6EB28CF0F0C776BC78012384EB3A87549C123D496267DCD5A0EB6ECC6D2046A79A9EDC85529EBC34 +581000,u,F9DB25E1D77BB726EDC33D5BCBECF0318F025115BA44220DE502B26A0196B6CD05E9D753F60A5D7B70ED122809F3FC1376614A67D9C317FD +582000,k,A04571E101001C41345F6D73CDD0750B5EB5596FD5B2AA3E8F15071EA4E1A7035B367A0038EBE9AFA569A21D3E65530D215EEC82F624FDFC +582000,u,A68A35B39DF53A46500708B291546F601BCCD54E878AEF24F4A607C695A3D11E225A13F2790D4B023D4A872D9F9A10C16BB4E7239F7091C6 +583000,k,FDE3A8424BDD686F13BFFED082115A2B3C93645B13B1306925ED9E457DA612E8728972BC2CF9D5BAAA4BC2FD579E064E12E42945BA4A9081 +583000,u,801BEB4AAEE0CD513466AFD91A2763B9ABC5D0D0C880C89C3F53D7ED5C917EBD4B1770FDE5246319AAABB7AC9C838CF555CDEF909CD5D902 +584000,k,9EEC33E92F588AB630997953D2A31F0B3B30B145ABC669349DC9911CA2D23E14055A59ED1760B1146988954ED075D22EC760DA2BF8ECCCEB +584000,u,E9BF32EC4D4C48DF54705739759369C2DE6B93ED22B0B4682F8F5FADE3F5E93DF699FC8D0DAA84BD00BF9219E78F88BE0CB14108EA13A6F3 +585000,k,B55E18BABF6FA0409C5BCFE1634CDA03BA95F67F21EB27934FB60E0E351A322A5E98FE4EAEAF179792D8B1750478A8F71D6DE787FA35274E +585000,u,8F96DC13EAC2C018A5F29802D563931572B5F127EA0D1131400F1F3CCAF07AD7F1277F16854551D5D3472C25B652CF09F2EFD75B497041A6 +586000,k,8A1D3BC5FA54B4307CF4E87ECB3EFCEC77D786418BE6FE96F0AFA50AFF9760B57D7FBF1B57C3C3C5C836484560C7DCA95D4067278D840E2C +586000,u,A2D6765E7A8861A9069F20971DA7DE0796807D103DE0E3F2D00FF6CF99C56B7A06A6C3DDE2DFC7FBD62E84F7CE3237CCC3D927E96F196493 +587000,k,B908F0EA7A901E962F0513DBCD6FC8C7A568BA4C0797B660ACA123D3D0E49A0FAF709862010E617C1A84DF64E5179E5E48734145D57D5281 +587000,u,650E377C0291C876388C7F9121A3ED2AD413F1F0A5BC3B70052AB017894F5324821E402A46E70376CAD719395ECF8D38C65CA79B46598398 +588000,k,66A99E74CBBC8B8BCBD0B08C864D7F73C8994C492352FA40966E85AB6310D39EDEC9C0BFD00B34CE06C66A9A98FF6723FFE03EC837B9B44B +588000,u,9FF0B4AADC6300F66C0FF2B593C9F0376B12AC38643F9024777FC1627ED015B21FD8969CBDBA7EB70320BFA0EAAA2EA1221510EECB9239A7 +589000,k,3056AFBCAFA809C003695BA9FC5087F530E4EB52500357AE7506F1C9CE888513A87DBF1F512BEA19A96AF968D06F5697193B289479054246 +589000,u,956C9B3204B863CF879EA3C70D83B0781AA125CF63CC82907265E4E7F01B0E075D483702DA223C936F61BE98CA4B6D47601867A43EC9CCC5 +590000,k,50D2E9FCEA6534335A18BC08F953D927D03F0075A68A4618C40E75E5DD3855BE5F458D9D2B2FBDC4E2EF15B09DFC4287CDF6628705CC4963 +590000,u,7B50AB542385071D3B6FBA57BC29976E628330DC7FC73055EAFFB168187E3117265E8E7716B3C0BC3BAF2B28B84F78030DC7C55A0C66270B +591000,k,FCDEB810470FFDA461AFFBD78173FF6394DADC78D10A0F72743E08AC55545668339E0EBF84948C55041268F8175A0357BA93FE57A8CCFB1B +591000,u,FEF7FA1470C158002ECF0E4612B18BC60A95557B94EE5833CE2B3876028EA67A96B4E9F8D31B3E432DA5E1310F6C5D9D7489BD2097AD574E +592000,k,5E78C71A8963AD8D2ED1E94632D7B41931E67F81D298B14DFE212AD0A0FB0BC90BB43F0A6324765F2FA3E032FDF3006B093AC7A3B1B2E3E9 +592000,u,A0599E963818EE6185FDCA13134E45B982E92F73D8FDE58D31BED699D6382FA3998D328DFC50EC9DCC4F1CA5012AA75355409078A4AF4EFB +593000,k,AC0F4709CA1E7F43C983DBF3177EF475009E229B084F6C7A0814FD4AF40C3A2105705EAEC08E5802B4CBD8FB17F64F6ECB3E2BFE694E8F98 +593000,u,479E3DF07C6FA9396436019497320BE9BB0C3ED7BC4025FFA7C19D77CBD1C9CCFA554B7D7DE3C666042F6711CB3DA7CEBE1A5B3CDF6D126E +594000,k,9800A570F103405667ED786C562F342D2778C9D510D589266EA53C77C76D75551771412E178DD705A4BBF7191379DF7F8CBFC787CCB10FC1 +594000,u,03791566FD7667BDBF57284D25D80B6E4498EFF3F1687BCDD2C332C03DAD185B11B037D7E22A14842F747CAFCC40F45F4E1C0CF8BBC2E8A1 +595000,k,CFBE8854BBD40B2FB50E879F25AC8C7B05D7C49D2874E6E61E232F16F161DD6336A18550DB02DEA7780DB0A8F6AE025768B27FBE86AC6227 +595000,u,68FB62317F1748E0C8D18A448758D966428370A18DCEBBD5FC0DEDBA91C5C2BF0071813444F4855FA717E0C5177AE2634365A98B6C20D734 +596000,k,6154CE541F8CD2720814D4EF3BB9E0EEF858AF8973AD4922D8BB0C14866F089A87D571B9B1770192D70DD721623E66D624BBD37E29200A51 +596000,u,A93F05948F784AC4EEB5864884521D0E1D347A2B8F54875A32636259250591FD7B6DD20BEA7FDAE78CC1B8D41943FFAE28EC70DAE9163925 +597000,k,7B3A4CE7FA818C160C199733497A983F393E37635FD289DCD3DA93E010D37B466276F26A9E7EF2C8375EE9181376EEDCA5EE20800303F9F5 +597000,u,277A20D9659EEF69DDCC80CCB697E8ACCC0CDB608CEC960C7D3DA579CA092F7B4AFCC693AC641DF5DD6F92F1A5B5E690F57451C4C96A8DDC +598000,k,1D2298A906DF1EAE45B537409AEDDAA5F675C79229A7B7654FAA92E8FD90571E64008395C83411DDF995DD2272CE19BB93E0980848836318 +598000,u,280BB69D9F424DDE44B37CCE24637828489DEE35C61BDDD55816B0F3FEE1AC71C208172D8B8F33B11BCD321402D24A6EFA2E51420D18A846 +599000,k,226EB6FFC3A4AE15BC64A497F72188FDFE5D0B9FE35531AC3FE4282808E276561B518CDCB8509339DD4FD6F778A0854DD4BC116561B7EE9F +599000,u,7460FE196BC26C05C369A814E7074359F59FEB2671996B5B926A54E51325168ED08FABD960C362BF947A0AF475A9FB94DE3356A6AFA55AC1 +600000,k,76416C18106B720EA498BCE60FBDC2E7E9A155D98260BEB490B9F848FA7C3F008F374B8268F5B2EEBFF0700070242FDAF780AC7603D4D02B +600000,u,961F7CCD23D31CCC20635FCF67FBD8665D3A86BBFA639F657145AD8B5B1635DD5D0D0369B85B373E7EB0828BDC85FFBBF0CF40B61A8878B8 +601000,k,C80AF8A4A69CE64D638EB8FD9B3F024767CCABE86D43CD70FC2B50EEC79E148F7811DA1791119DAE521F125F1870CB2808174284F865824C +601000,u,EB538ECC60DA627F08A91B840FD5588506C51F0B569355206E9C3E601B6EAB041F5663A3FBB429524F819445F6902C614BE43990BE45CA8A +602000,k,C71BD7F191F0B94723827A96D6F09B75D83B389107BAC75964334D9BE1CCCF1C86984BB00FC44A602739BB1B05EEC6B5B700AC7F13C26E90 +602000,u,787883D86D23D74462C1714583D9765E9DE1B455B59613D661C0DE3952A9E85C7AAF3C08D0DFA7A23C44CE58C45C376A590C7C509696A45B +603000,k,11A3B4BABCC1C20F76A3789AD2C3E2A9592CB4A819AE326C8AC547DB86C02C28021F1D69264B297D921ADDC16D08DCB10B62E15F7DDD35B8 +603000,u,BA0E2A799A2A216EF0FFF02738E019665F8591645A487AAEA345EB7DBDDDD0EDD21F21834B48E922D642986D3470D17488F35D18AC823189 +604000,k,A8546738EC87B0C10AA68C37C5A46C095EAA656244F90E7D22504C4355B6BEA68F4C1EAE52CD4D27185B3C4CF56384955A1D45BCCC89A75B +604000,u,3AA72214185A5AC2EBBDE39ED33F753F6DCCE55FBE26370FD39E67FF830BD87592F2A521F0A2392B0D4BAC4CB8729D283885120278F04550 +605000,k,D4FA233B6377B0657312B13247A49E46F29A9BB7F4C570AA62A2D343158174BE96FBAF974B5E44E682B211E129BF9BB45987270956641F12 +605000,u,41F6864660527F99E1E541399B55384CE602DE9554C8B8DD3CB856F6A66746E4D392B2F79E9A8EAE54A251E35DC8D662D684C1FD661AE3B9 +606000,k,C0CF03DC869B5A90AB75B3FF977C7C239FBF0F5DD74B8CA49864FD30188E1D05112C5D09683A2C86A94BC72FB08E1C1A98AC1608DFAC2401 +606000,u,82388156981B3D464E85A848EAA55016A0F83E91CEBE322B18AB350E62327241871D5D8B2BE3371CA32838D8B37D4DB6C8A26D913B4C4F9C +607000,k,7EE570BC7F385159B237FD091640E0B87C4601CAEFE8FAE37D4A9051175CA4FA80DDF3AA6C41EDE82408F2575B3C8569815E2A5AD7287404 +607000,u,C96C4B314B72299AFAE71A12080747C95CD840F962E413B470ED675135E02E045A76B3804ECAC1873B318BA87B1CF04730CD981DA5903D1A +608000,k,7BD7A5A23A6FBC19A368BD752E3A7CE559319C70E0319757B16D5014EBB1524D7E61D8D2A1CD77CAD6572D570E75CFCF61DAAF2D9FE957D1 +608000,u,76D3EF73CFF96A96F7793FA6F8D69643F5AAD44A4C1C2862FA46A54B7465A512E461E73532E581C76D073DD675DBF541C53130606299E61D +609000,k,86F47C4FD6185B62B790FA8144B867EAE453358B2D96668E3606CA66DD7215DB98BCFFBAA0796B4E23E5C1CBD6F3C3EF8B83E61CA795F20D +609000,u,A2D067A694B80FA6C580C230421DDCEC4F896B475CD78FB2C75784EA90F08D08C98BC3BC75B769A9848B2DD87FB9FA91EB337DB012B7C0EA +610000,k,5F8F1DB99C775C7FB182A131382486739593459A0AFCC6C4273906BAA21C6E5384C0AB9EE2584F7D21DD58FB29AD57D007CB9EAA0D254130 +610000,u,901C738395E82BEBC7596F440C3A6A1D5689DCFE395B9386CFE0905355651F87D62078960732597F2389C57DC1F1ED16F643E35147BE3684 +611000,k,34DE12C86DBE55AA9AF2D6E0C6D06B471208D95A83CCA3FC72590CBEF6B3DE077D0BE8BC08788E7CD386607628C483264972439068901642 +611000,u,13D5F46ADC50AEC4261A5FF92A776F605ADF57CCD5B9D62AE0211C80BA852C05438955828711BE597D0919310B02DDC21DCE6B041BCB66C8 +612000,k,8F2EAEBB52619166BA44D1BA2FEC18D9CF40A89A4772F3C5875032F91E78BCB38810B9DAAF4756C0AD06318CD792A31F404D23F5A1FAE46D +612000,u,3214A6BEAFA2FE4512AA0720D7FCA2C5BDB13B83A01CA06E5B1A096B1221E768B215CAA8FE45F85895768DB2BFDB4B055EAABF06BE3989BE +613000,k,A46496B43BA994C2F4630939644F62B2B6690EBC60DC2007B93D5F2C9582D3DFCEBA6F9C052C098A1A67E13C1F5ABFADED3E807706C97ADF +613000,u,2D8D99C454A396BD68DBF04E595DB53C3E6CFB573D5383F58AD438A49F56190ED693931A95A4A8BFB26D10CB5B1AFEBAC60C3DE98A86128A +614000,k,1A7306D71DA505ECF91CB766D3F0B9460709818203504CF64D9FF03C52536EE218A42A71B992FCEC364EAB4942D691E355CC9D0B59CF0BC1 +614000,u,83D4FF8C0A5A73E499BBA7B8B1212104645666FECE77E1D0F8A4478C71D352724DB837EF75E59662CA2AB601FF82E955E60346BECFC4135C +615000,k,A5E824B5A2C463A1662A2F18C03CCA21F76DC349BF68587BACE5D1919CA6BB1246EDA38F15887ADEC480E93052CB837608D88507175BD2EF +615000,u,BCA7F23170A65052FA2ED27B0C78C78CCACAB8DD209C5A611AA7DCB2A8413A47C3DC36721F096EC73F7CEF7C171EA477C357677A6508BBE8 +616000,k,E14E0A45935D35AC74820462B2152DBBEE56E7835BDA80E1A353090752CC1BB6ACC3CAA3A4A41B06BDDF2557C233FCBC5EB1E54FD0081D44 +616000,u,6D6087A65C8820A59AB871600385B76EF5F7B1F8A18711C589160696ECC1F0CA915E923A02C4F8ECC28151C4B28111680B60E21201F629C2 +617000,k,9FEE550156DD2953099954AA2884D9E7218D14C5E7827DDADD015F0BA8DA8C1C7C7F742685EBBD8E0BA2421CAB6E0BF9BD914C78EC8E0589 +617000,u,F4CABB16EF41D867175707EF00E0023B67A44C370DDC76D38473DB9193E96734E18F033573C3E604095E1564EB8795946CABD415ED6A8096 +618000,k,02BC14DC3BE43425D6A00060D00036927107D587B2B8BF6F142D8AF5CD4A19ACFD61DE980FD013A25671F26E4A8293211739E0C8528E5E9F +618000,u,03FCD997FAA0CD9DCC3C40479C2DAEFEBBE34DD7221478D332FBC4CBDF323DE1DD3E06012B18E337D8B31A99ED43BAE60B2924DC9594E4F0 +619000,k,CA63E4CA007ABB76D80CFBF2DA8410760B639736BD61332D65AD0852C48C53EC766E69F8EBC4E805A1F2D370FF25624C739CBE7680E1EAA6 +619000,u,9DC57D874318953A37928231F3C21DFC3256C1E253CE6B7A6163212BE5776893F3A8699363714443F283FE3C65D241CCD27EC91C22E31AA9 +620000,k,C27C98A41E05A970451F0C2854510140F6BE7E1341DCCA06268D794DCC4490F9E69C7F037FDA66B74C015B207304EFAEECF62DFDB237E5D4 +620000,u,86EB8EAC62622AE4DA2FF11640FB002627D0C5809585CE4C83538E6DB07AD6D14B74A908688D8D3C521A0095A524E3CEC90639CEB3633979 +621000,k,31BD6918DF1C208450085FD0B6EDBF02288A79E7B229448D6AC63B8C1356ECB4E54CE64F74870FF25AB1060F9DAB72E941509697C19E5317 +621000,u,C465A33C7AFCA1EBEB2CBA6FA0EDA85A66DE6C7C6E79EFC231408B7D2391A96393B22151C591A3197DD0D4C6DAE5CF1D3F1E8DA2AB6A7DA3 +622000,k,F5DC0199AA699593F3FA0A1D2DCFE3C459580AF21448269E98B798642683A805739C174D176F3BAFC0C4BFD5CEE3895727DBA207EF45D4B9 +622000,u,3E7EA6D8262F66768D09633DB80A3EE3D37CFC8B932CED738BBCC7A41E23CFA696D48723F0A2FC31C07EB88BBC247D83B2E21A38731402F1 +623000,k,D74280D6FB08D7BFD2112F40A161B9A0082994C34CFBBC0DB8E15F58FCC1A43EFB71AFFB04E0E811623D536E0CC725903AF7C175CE94E872 +623000,u,97D631406A9B8BDD8397A262E50A3CC000F472690F55799B4A7A82A3D2AF97224CBE0CE4554CEA4CC35623ABF7EE03043708438AEDA01469 +624000,k,D7EF700D02E33A0539B1A257C65E53972B2EAAB9F97B268D726D4AC728667C771C6C8CA36D92594D0D39B99DD193DA4B3AD9483DA24DDB3C +624000,u,C3648BCCF833094E8BAA3FB4B409474016695B9FAF8974FF931FD41714808CAF9F35C7683A48B4104977ACDBFF3A8E021667F6A93316EA23 +625000,k,E8292BF290CB393C40D64A2666EC5D3E6B6213EF56E651F29C3E8F201054689FDBF47137F080C8BF8E1A56A2FDD63B129DC088408D21C33D +625000,u,C40A56BDCE702E10427E4E406BD3A555EFAADA449019BE046181EFD2F3DAF9AB973E6C30B510E4E75CAB07CBA190B9B11181F285FA66548A +626000,k,07F57F76DAD24CA2E10F1DA824E73DA33F3DFD8B933672B671A7D9B488549992AC31B1F48F08A6F51D848941541B3F9E316C38E21C15B88B +626000,u,3E9530FA7D2F40CF4AAF1C5966F44522D33E02A82F940858FA72BDABF21A93066C3E87ADC355BE903D52DE45C25866BE4AC85335EC3CB918 +627000,k,AB33C8F696660AFC4F9B18B53939C6DBF16279623EB45F3A4948FDA0C40C5DF54CA8CA5ADCE25F63F3755BC634FAFC96B607D893AAE245A2 +627000,u,30F9D131F13FF60A35276A0269A91B3E079BC1EC2F6099D8A2BFB55BC8868320E6E171C91F8588C09613BE04099D1B84958381A9FC31A0E1 +628000,k,1DAE674334A33F8BD02A9F969FCDAD2C755937B5300AF24D05D18F61E4FBC4056B868EC03BEE907D86E07FBA7185A766F5F10761D58E4037 +628000,u,499ABE54FB45DBC51BEEC245A87059D41606B9D6FFC32764882686FFC5CAF04FBD6C990F0CBFCC00859DE481D65739E3DF2E16B3FCDB9618 +629000,k,AAABF0C78BD9E0415D3849410FF6452439B2AA3493910C2DB1E10FF33ECC7D6DF20857B4C2AC8FC1E43D2278C62FA38EBCAD272936D86548 +629000,u,BC733CDDACD72401DFC1F3FAEE1706881E37BB233C29ABBD68145A4BA81CADAC405E60F67C194CB04D4900766E901C976953D341A9434A81 +630000,k,1D79354857A9E9724D14A646917D30827FE210CC11313E846AFDF3EB9EEE48FBA54FF2BE71207ADECB624A698281919E3941A30D9C944007 +630000,u,96007AF236F45D516D3D94550F8C5FFF5EE6071174E60948BFBC994FEEC61E69D53F52F2BE7170E0FF2F4F73FEB7EB538E3D49D08AE02D9A +631000,k,2840F1485C7214289BD2E51126319599752A1112679BFBCD1AF803700024BC45CABB3AE27E101C28418B8D872768698630B0BB0B3837E6D8 +631000,u,AEB8F826BE3DC15D3AE78CA8FFE0816E271C2B102C52AC63538D1B9F18D83A0E8079CD5CB3D520629E23BEE818FB876E521B417CFBCA7C50 +632000,k,9F3BE1E29274DC266FDE718E5B5F1E0FED408F2CF55008F7416459801CDF76B27CACA25437C98AAB8C3444D6437567F4AB515B30941BD28E +632000,u,6A21C59DF08286ADAA6A8AB5DDBEE5982503D2CCA2E04DB52D027E92F71FB4394A5BABFB7782BFD87129BD70EF7E7BC4242FE1B6A3E6D289 +633000,k,AF360FE22DAC25931590F0AF5C16E392AE94D6C4DD4499FF5E76F6E08F47C66F6E2244525DA213330D3DA3A623E78B6050FDE59F13A4A44A +633000,u,6394892F3AE7596BBA585A70BC08188F9A28334BF029104490F1B9917094326407ED0B211B156384E40C581F20698B8A6912988FA81AE053 +634000,k,09CB1DC60CDBCCFF1EC7291AE4413782B7436F1D4883835108E001014E23FF7CDEACC61ADCE2B42FE17597AB591B7F00F7689E3A055C7749 +634000,u,E35C085BCC768CED23491C271B4C34874E9C90D1B62F9C681F3D138782B82902898DE4A6CC6B82F2B8C464AC981640A222FDE4840B092E8B +635000,k,210DFD4C5258992E4BE4D6ACE789E9E0F5111634632F17E4B23BF692F0F4509AF0682C857535F3BC82FDF34418C43ADEF1AB6CA46CD90BE0 +635000,u,9E553D9AF24E3145E558634DE373A2523A527002C51C2E3B21AB68F8C3F1D60DB92A86FF7278E04BCEFFC740EE00B523CE883E35636C3618 +636000,k,8BBF4FC39D92E8320B012C911A833E54BF7F3161FA29FCB54ECD438AEB0101B906BA3ADA400A1211541AAE22798CA46F79763D2D42290004 +636000,u,921D8E24D5CD2C7E431A1FB542384B12FE4FC71632EB9BB8D6D60B49FE76DD11E6BBA9881D024188C2BEF5CA1D6CB79D5AB2C481D3200851 +637000,k,B98B9D85F04E145A5073FA5A98D2CF842F859A554829892C2038BC6E4E161BF786599E7D2B6D1CFC899C97F872F12FBF137DBF54B1EDBA9C +637000,u,723863CE95E99CE15772DC0D5171602021157377AC532D97F2189ED2529B8C0D48B1C2B41A53FEB910A29DB213C794CB7231928E6B964E31 +638000,k,5732072DD8FE8E1ABE05A0B978D3B06EEF902B09E8962D45277AD938EC64FB7163A129EDADFDE1CC6A567406A754AE795391E12A096CA5B5 +638000,u,FC6BFDB2A61937CE07677687BB7CE67C5A2681ED3DD200FEBD3E87D36E28E67959C52C4281903D6813A532D6CA05AB8CA7C93D140E03AFF7 +639000,k,F39F18D277130A6967DEBEEBE9E33CD3DC54DA41796490548032C89C08D269B212842D88039E70457CB5137913F01B5B43C83A695260BF5B +639000,u,B05791BD2F367DA4BDE8939CA99F27C65151AB7D1D33FD55F1DB86001F0782AE966C265346781777EDD340351AB38A1F61C47F48F220FAFA +640000,k,B30157E9CB69633B8A43C18C31969B8DC5183631990F223AA706B49A7F4A9867D2E7D0D7DE9BF305EFA6FA3045C395E6DD3543F93E87D54F +640000,u,5C68FE37B94159DFF06B024762A4A3A5F845E9D7244A4C7A901D8ACD2ED4C7C38EB28F22663CB67EB38A1E058C68B9AEBED242F607EFDDBE +641000,k,3DB5DC7BF388972F1250622E901131B967FCD3A5A99CC5A2B7296A4421D525436FB58D33A2D42284BF66F298C1CADE00557804D7F1348590 +641000,u,8F327CFF6699C26D33FCB92F5FE58435CE6D898E44582C107B69ABF19E06838D8C7C9ABC1C9D0405238923B57DDA03EFCF661A0F048268E3 +642000,k,AD12E097E0FA69B75440F550C769233667C51DB7EFD74328F7AEF0EE94055C70719383719B889B89AD493F44E0389A74C58BFC8B17FF7E35 +642000,u,26339578B57B5D41C392B4E7BB3D733F1D2BF4675EB5DFEA7EF6D3FD26ECD125B1397F676E0A361258B3C27D46DB6A3D2A8FC573BEC499E7 +643000,k,8957B1C73F15E9B5D7BFE166BE64AF56D8F815338AB7E8CB459B0F744CCD5E15A1133F3E32A58D8C20A7B85127F0EF767AA405771B4F68A4 +643000,u,CF763013FA2944D61E3179E754E3187F1AB389BE7E32E75AD161E3F20EC9DA57F1EE9A5A560D2E58F6D0B164CC40D6CF7453EBA382DC0675 +644000,k,E6FEFD987B1BAD7B586F8338AE952FD80BCAB0B1772E284B8267B2A5B228A57F3C60E5FE3AD1A0A7DA570521006F0561CEEB011F85CA46DF +644000,u,F6A46CCC6328BBB95832D7134720FA4F066563838330D5843EF45F8666B12D5207A6F41F4BD6C75AE07A541C12952A135F9757BFF2897DBF +645000,k,D19E9EF651DDD3A13D2DDE2182378F06643CF6FA12AEF02F90512366A8924BCE47BD74218A071732F1804A7EB132F99F04AC57B1EDF16498 +645000,u,2AF4AE9185A0DA727B35355FB5AB9B729010DE60D2ADE603494FA374D6495A256C165A2820C2DCEAE1919C3CD12E35396ADB8761D89873F7 +646000,k,49B7118453CCA98A128DF339DC9D227C18B420090F975EF5A35D90A76F0D3E82D5B545A4C2B87BFB71280A7A4CE6A47D782C892513AA5700 +646000,u,8182C73B750FF7CEC3038BC0A06B9FAF558D9AB0B1CD2BE0AD880FFAEF02FAA8E2A76A20162C2442E5C451C04BE12C9B64DBC0BA5E501A26 +647000,k,012D5955C831C547329526240A791D905FE45373A4B4267E0A45F91364375F7D9D02A71F15FC624F052F36FBA1B4CEE2A8E345A421A1D476 +647000,u,BF70FF1FC5587BE585F5DFEDCF3BDF0A54D5132BD4C48C87B06B06BB9D99BE0B975FA186020345C4C389F5D685E181E6375FB3E29912977A +648000,k,2EDF1F9E50740783B897802BE52087AA76C3113FEB881D8125C3822A083A2AF64A5C62EE134F649A30E7ABBDE5AB7906D5513410BE7221D0 +648000,u,96C713E13EB276BD6E48F70F57C05738B7C3251739D06069BEC7780F2B1CE75C1A89B189224B146A3A602DD7ABEA139BA68C30ACCE7B96E0 +649000,k,FE67FF42BB8E647B1C14F3A132F1E84D5C890551BF277AFA07EE90F3179CFCC5C30D64B717246D0890EC7BACED18321F6EF1B93D4006C67D +649000,u,282429C729CDC9D2B6025C8683C9BBFCFAC9AE394D0BC382DA1EA72E0F2F91BDDEE320FC74319330D386A845253469D8F65220AAD12F0267 +650000,k,3FA406DD0EB57BEA14F6393A5BDA771017579AFD559F533A1EA7B7387B1EEF79298A21228976E9071FBC2954D790DD1E4D15D5DD4C286236 +650000,u,24E2AB5AFAE51B1403969DEC09DF9BEF92605022B2B8F84363D622E239CE7755601C65B66A90DEB9435B33ACAE0D41B7118B4D1E2BFE1CBE +651000,k,8F342A49329CF12B1E4CFED71B6400009F8EA694182EBC98C03AAB2BAA0375DBBDDC42D56F654673A5AC63A73DD193E37D4B35CC0354EAB6 +651000,u,0C0C2A23DEC542028429FD6775D7E833D1BB7235E709A42260E333BAEA3693F3D12AF1666649E142776D0DFD60EEF865EEB621C6352BE2E9 +652000,k,F86A61FEA64E539A164D3E305622635528969B735D555DAC3669B08345277B08BC1857B3EDCB95292C8224290E17C3CC69AD4EF9FC947EDF +652000,u,42609B5DA6DBAF3EB2181BE8C1331C126AAFF7DA0F25EDF79C224A478177B19F465800B277FC77A521DEE30CA537AB2E141CD94D248C9CE5 +653000,k,56AEF682E293290FB8D4558C67D4B4FA301033749D2BBF62B8E3D6D533177AC4114072E8DC8BA32306EB25B911E0522C389EE0427DD92465 +653000,u,2A6C86E5A18A35391D4848C0A4A7D721468B81E3F4858C2970E73DF27823A8EBD4691CBD16944C4FDA9ACD268004552AEC5969A9F8646DA7 +654000,k,E926A1DD64847D12D5EF83FA6AB1498F517AC26BEA3B291F26ECA63ACF7447E8AD66B4CFBC34C0E10382756BA41881D48677816CE02C4DC1 +654000,u,6D4FE5FD3378F315712DA4F6DE9D3B95D2EB362D88105950816274D282AC1862650034EE8CF707128C60D19632D9B8BAB6BF2392BFA12575 +655000,k,2AA8FAC69FAB7261B2E88DBD52CED984FF835EE4AC2F7FD69F0203D1E1D43C9F368AAC6821A81F1696240D94D3280145FB5F3956D121E233 +655000,u,8007D31EB4D2D7AA08030F6C733688F0F4B5BC43E31DB63C78629A8B1A6AFB10A0C91441F16A746D6DBB01A0046E06E1908F6B1D1FB0739A +656000,k,2CFCF1FA38B3B6853177F2B136A70B7B369FD0DDD110C3FDDAB27F1E6F18518B29ACDA4E2C142C5E6113BD1D9CB6B895EBD9EC9C2AA43085 +656000,u,128B3D45DC5A9B869E927658D87C864DE0FF4C4F4A89E18C41F8587C3B3B743DF3C994EF6DE2C7C0E692F66F9179F015AD70BEF75E64A826 +657000,k,B70115D8B2665F04CA2E5F1C6B87FBB1CA5AF2ECD9DF8CE9FF61FB8D362317C1EDCD0CD77C35B389636B064ACE3AA3CAE3299277A53772FE +657000,u,AC71CC903163B3A6445B1CD803D37E037C776562E05FB4FC313FFD3A0994A4B6FDC77E36B85B7EE9A1C72AAB1BDF85EDE6D5EF1A4C04B32C +658000,k,4737D330F114F8460F9AC03458D32B803BD52E904F536FDCFD1E03130012D4A9433580122B494912822F482A16E30F2ABB3B77C154D23F25 +658000,u,437CBFD46B5FE492AB68B0D7CDA3E8C63C35EC5D38EB6B6B9D74B8FF5475D372FD4BA0D7A0E2ED6AAD874AE432C1806498C74AD391B44598 +659000,k,384E3E4643FC588A39F306AB88D3DE4F3924F8622D7881EE26FE5F1D0877C25FEE84C75DEF7C64071E41626FDFF77B1723401E541731B741 +659000,u,829D565D5D75A7DF48B3E23DDB4C718C222F23CD77A7F31889DDDE04C3BCC3134C13B4C8B219B659F60914FFADE8C2632834D416CC045C69 +660000,k,23752415DCB20E81B7429709D179C6425C8E3CE919424A5B51436C71F4970773577616769DB93A9076E8B025EF54CA281DB397ABF865870E +660000,u,5883FFD1C4C7B7441FA01AC359EC7EC60AE55ED6C33B3B97D810AB1717D2C57403B2374F17A6C9B75E8B7F6D1D53FA41F48EC097B883FE86 +661000,k,57A4FC8972A571D835902871427CE4C8BCA026C5B4A9D90AB397BBEA611AEC0FAEE66ECEEB19215F5642851EAB06D89E1B2124C77B80D6EB +661000,u,708B6EA5FAE29C42A168E6B1FE59E1AFE57EC52E1466A7A2442263A2649B9C0BFF343D98B2999093350DBC1B7AAA279133333EBC759BD96C +662000,k,09FD39616F018A09C251D475A4B5E7A2B51504FC60F580F04725D4F7268E1A9B815BA3FA734BD332DCB1D1DAF37162370422FED8ECE0DF99 +662000,u,DA13E183C602D4AF21E5D8AAB6C6E16778CC3D67093F007B39C3BF9B7187F3D02C190CE10430CA05A3924CD4B7D29FF02DFB67B82D046FAE +663000,k,1E1C896F77CC55D7AF776525D0DFA0701B1868CC351E90E7B0E50196B9F1607C1334716D7F8528950FC713FCCF02675B512128AD8C541BAD +663000,u,77E86427F1297B03E5DFB567FDD6B0FF6AAA79ACC5DBF0944A437AFD9F130B92A21C363C183D02FD1CC256E1D543957A7C83B473410A36F9 +664000,k,1CED94F1AFBF38432637A2137506696167EA38339603239060EB6410207907B86CC0185C3AD930D0B56EB1A6874B1CC810E8F45DFC56F3BE +664000,u,F9E176ED74EF9294627692092198ED0B9AF63DD2FE641ED40F38D2613B8C7958729F4CC0374C33B0C7E3F441A258AA4A6FB86C03FFFC8F3E +665000,k,C3A393D7ACE38462D0C0B9CF3415EBDEA78862D7EC972188BD783E2E3B92A71065C5CEF5126F57CBFCBE0B09B7BAECE006655EAA861C42C8 +665000,u,B54D6C17A9BEBAD12EF83F3362ED91F862AC1335013CC09145EC823D23C70121594AE494FD8F7D4D2E82582B3B24B55C78F129DBC4C021F3 +666000,k,4E1DD91100B321B23CCCA30DA5FD6417DFE6438EA1B975781693A818F2CF02043E4C7FCCA69120416397CBF630F8CD39C25E078A3CE72997 +666000,u,613DD43E3DEE6B035CD9411F58221BD9752485E192F7E7871C698738257F212DAE427E954B7AEEF0638484DE2F67C78A2C7871840B5690F7 +667000,k,88AF44BF7C6A7F4143AE883A182247934C6FC0F3CEB74FFE763153C9CCF099CD5EBF4AC7E92AFFD2D52899D770154020A096A38CA8B65EBC +667000,u,DCAAABBF7183F4201DE7D14DFC9838EEDAC857AD6C1D381BFE36BF2270A86EE76DF18D42D98A18E394D4C4800103029A90ACFA18AABDE19E +668000,k,C9840F1616C7FA446B9614138BA7CC0CBA93D860F8339E8F0806CBD849312DB340E2C47662B3C573FE47285304CC611767C6CAA6A11F4EA4 +668000,u,A5E591FE6CF8587BDAE6CBFB5ACCEF5398440C8D25756EC7D2503786803749FA54EC2C64D3ACEF4B7098FE9FD9FC036F5670D8F3F99AAD71 +669000,k,D73D4938856E206FE7F515174B29C80447D98B69E90DB34D6269DA73660C7377895945C77CF82964779655918DE9525C50402A6810B83296 +669000,u,B7075A478FB7BE8C76C40CD30CC27E3FDF990D04F64E533AA566BBA8EF62FB1ACE9448E6DB85C8AC86513251C4F6A9B0D85FEFC30002FD32 +670000,k,D87F91DC14DFEF3FD88A88E247554F8C2FBD3AF8325DA4520D8A19EFE0953B78FCD37A39E21D1B6E079D34FB200CFE494346335D81A1E689 +670000,u,673B31FDEC37899DAB7D07A8DF6FCE3521FDF6DA907BD3C4CBCFBA9A15EB2545D197C8D2B464482C05ACFD2C9E14911BBAB8EBE7B136F601 +671000,k,9429963D25CF1AF814FDA7863D943F92135CE73542A8106F3FD5844B4F6C05712090337AA946CF86FA488574FC6425B717EB12F4E58BF337 +671000,u,AC68F1EF6F6D63FC3A3198EB28498094834658B01AE4E60934D5450087A7165C6901E95B59C689B80EE9BAB48783DF91529E9629CED07EE2 +672000,k,3EB126E80B46F6A70B139D97664BE254E3AEBE695658D6EEF10BFDA8A860FDBA6528B69063FBE91BE2DCE89D4EAF827C1B0C423D139577DC +672000,u,FC73E4DDA3910A0EE7F6198C1543C7C92F045ABABAC41C174D3703904FAC53D3F1044DD1AD1C4AE644D51BEAD16BA014040FCBDA0B923C59 +673000,k,E03F12D91BB6FF5D656140DB187C2A4223CD18DF9B2F41E7375A233D33E1D0672AA9988237D9FF43BFF55FC985BE172DE82184E3E3DDD0C2 +673000,u,CD45A7DCFD92054ABEEF3E17147C72FF9C4FEB6212FDC175078A4E010F842809DC4921C67B06338C3C25C878231423BAD21F1BB66D307FD4 +674000,k,33155DCF2BE0788E09AE6EE6CBBF976FFDAC43A34F1E21D130CCB814DC16DAAE83B71220C6D77E9AA550C30D3EF4C70BDAB96F51AEEC0A79 +674000,u,3C02D9ED28BE68394C977D00676B91996088EFF147390387C4A5B5CF478E0372D7168280BE591AD17B3E7A8C534B405C528923DF48476180 +675000,k,1349F36CF99D6DDAD5BDC80681D159DE54BDB4F3E2F4B5669B4F6D95A9240101443E871433C7B33F67F32464E78881CEF8ED594605F95DD1 +675000,u,FCB84FE7E5076ACBDF6C9D43B30F336D0045ED9F9B987A8BE74BA4ECD2424B1DB84BC44BBE74AFADF24033478CB4D7E743D970087185CDBD +676000,k,9A7FF6C9FF4053A694D043F5614A874FC09D3735093C1EE83200E8E9DC0A2AE45471265E9F7AB5C0464FF233BA7817D618A7AEB1E4FEC0CB +676000,u,B7E92D8081AC9297055658D315E22DC2509796E03297E195DDE7A6DB56BDAF6F1B039787D71C9C02D2398A384BDA77C7DBECAEB38F472DEA +677000,k,6EE559C000B6D7686774451E59C63F02545EA462FBBC37209890066881E31CA3F319590ECB278738629EA7FD24A1465D1AFFED6B8DF6CEF1 +677000,u,5A9BAAB63CFC86AB299A4DECB380FFBE75A8294C3DE757D8BF7F31FE098D2A3702F93CE4AA1BC296B072136393DA4B3C7411B05BBB0B906F +678000,k,14446E78923C79C4B311C648F6DCD640E2CFB5A015607FB5A21B069910B192CD952238C906CEEE9190F73274271BF5EFD10455877C4887B4 +678000,u,01E78F45E5D29C7D1FF9ED060F69CC20E62D038703071B165A944509CEA1310D11CD42F4516E80BE66707D753CED9E24DDB2B89D85136EC7 +679000,k,5E3F72B6530F33EF888E545CDC500A1CD777A5C98C70EE5396807E597A234641F320694B10078BF7FD6900890FA6903B6E705E461D43BC3A +679000,u,8AA9F9C272FBE79FFED517E03B9B0725E11BD09597E241BE1C6DCEB5EBCE1A0551072BC286E0F3F1D54972B9466AF929AA460FFDA40E1B4A +680000,k,93406EE19C5AEED2B71CFB3AA297A96B5D1EF17B570F3104660B7655713196CD2F329A5B80A6714968B114953CD0A3E8FB50B8BC56C2DF35 +680000,u,35454FA1CA2D9D9A42911DA28E631633A517AA22A34AA4C6E9FF0E16FE23DAFF91E759EA58F166AB3FC8B6BCE8D0B79EB655CFF8C314C1EE +681000,k,35978A68FC50007BE00B2ACF568D6D6E6BF3B79DFF30DE86B29304F0ED7302213A203F3BA229C8843013141FFEDCBED95ACF90AC21FF1810 +681000,u,7F315FA767F831D2B7B5C04F7E79978ABA6D85F2BF33074D57EFAE91BBC9AF10740F36C9AB3E5F1B1E1C64D9A9F817C17F38C4D263F01031 +682000,k,6E69D0C786D74591DC45390FC0FDEE7D1E954B144DA8035000C44A899D20CE5F574E554606FEB992DC59B50A95067602DCB437BAA4B5FCCE +682000,u,45410330D2B18D577CB21A70162CD46FDEF6FCB4491D3B4C103F975F065C331CB475F3A848AE2C3C450B74426084698BB24186D288B76763 +683000,k,96DA2B85C2F2D1C5DFC3D30295695FE4868B69BA9BF1FA04169BC7C232D1D642148238A4BFB0068F930C1A9F91C44ABC05DC8573F2A8D084 +683000,u,E87CCAEFC3F50F41C1E4CC8AFE178822983D810FF1D6698076E29080433C6A386B3B9689B84219E04AFBF1F6AB47CFBE814AA99CE6B126DC +684000,k,CE3A380657FA005E0824FA70BE059AB9D4FF4A7E409692E36B6A07966161B0ADFA1121ED88C8C47982A34E85E74AE203CA393BFCC8177586 +684000,u,D1D2E7211C8476B2D12314967206196701CB4B4EA09F72E542C8B291868B707DD8DF4ADAAF37D8505A7A3AE953508E073DFA925134A43D3C +685000,k,6B6B3A2B61CA241A5AFA63CED0002BB88752D98D1D6691CED95AB71B0C87D73004B8DF73C0F3F8C69B091E710CB5197FCF07812B959B9C4E +685000,u,6624AC6BC1A6B9A5B62F79488FEB48526D2DADBF504867C8295316D6A0313240AAC481E5AEB67E0B63F9B0DFC245B8B2EB449C4AFD36B744 +686000,k,F406268752369A3FA5AE719D83C412774BFD9BDE9E27A8CD5D0AD160DE669957E343F91CC0D01B63DBDAF3234C0BB06EF1E4ABB79B0001A7 +686000,u,CD703EA46E44EB84AEE1D166BFB9E06E612B7D7BC0B99533DB057150DCA0E2DCE8544FBF50583C18C973F083A13C0C660A858DC079BB14AF +687000,k,03AE3182ED3C830C3994C8CA3B7D0337724D27C2115B23C109FF9C58F03331B26590432B395E47334A75026280BBF04C853885A84AE1F7FB +687000,u,559CDDE2A4B8DEA2816034E802F5A13F9D4EF296E9E1A13C7633953763A693A244A6480B9633FA7F5D9990A0D637B34A6E5FE0FEE73053F4 +688000,k,4967A913033F9BA1A4DE08653519D7A1DE7E9D6C3AD147A8C1EDE718D9AD0D54AB6D8C63CB01F2E8E5F8B90ABDFA44407A17B58DCA3CA0E5 +688000,u,446E1C554BF8A59D2D3FA9EC2F7E63263C0B988E04B35537ABA7419AC968328B9E11868502B06B53D37BB8A012BA933627AF879F9B26217C +689000,k,41CB4D589F54698F781B5360C253EE484B39413293F000E98DE2F28307901B13B9DAEF5CE2F194B76235B0DADBA87FFFCDF0C5749563E5E7 +689000,u,6F524216695EF1AA30B5BC670A072E55D6E089A9F90A6DFD1C9159E5099FEB6E5F8F96209288D3123A42438AFDDBBCA084ECB832AAA44F35 +690000,k,73C5A844832284D3DCB933A1C121E9D01ECC61405BA837BBCDABC8172AF56344D8FBEC70379C24F84A34EC0C51BA7A71D13B2402B1F580E5 +690000,u,A2FC5418DDF200A2339F2CCEF9174BCCB51DB815EDFFCB2F914BBBDBBE0D2675B88ACA7CCC512367ACA8813391C594BF52ADEF279E4C8846 +691000,k,5C68B922E62EBD707F1A1AAB3B70BF0F739CEBF2595603C51624CAED2D7CADF7BD27B051A72C718687769C1A35C98B3C945941C7D221157D +691000,u,3CA1B8FA3811C7982AB7B982A768D707E6FF621A70973EAD1DAD5973B3F06C6429C2CF1E5CF7735E640885B094F144E6CAF0F747F975C11D +692000,k,03DB562E34548098E6000BB5E160533B87A9B275C5442A5C4C51E6BD1D33BA332035154E023FBD7B97F016AF0FDAECD9C011784EADC99C5D +692000,u,A72567F7047AD0147E17E51122059A100CEBDCC0E1E54EA6F7901F51A27FB8F3FAD3270FC1CF696314A56E0A7326D5BA93FE3072929949BD +693000,k,8B41736EAFA6F9482A19DB508D7064F45EFB8376D538D2A566D2DDF0F5A05298DA0E466653EB04163C81A650F1318D33144624416BB0A988 +693000,u,27FD0DF4DAEEC257C24C4FCFB8909667E98985A24CCF8AB5226500BFF7E642B1C626CD030D37A857506531253758ADFF2D8B4EC065C29927 +694000,k,A2E5707FD3D7539E689AB3B259DEADB1A8C184FA013B431A21347BC8E53AC93FEA0F1627E60D04E3E7B567C66A1530BD09F6F540CA83CDE0 +694000,u,AB06387B0C101322D18E083069AF792E1F219C3B38AE80E20E258D94110298ABC3B4391F2E10B94A088B175CB8C0716BB3BB4E362A2BDAB2 +695000,k,CCA41C2384197C25E7EBDE7C553E9DF3117CC3E8CA69038EF2BFF2D2047F9618AB0DFBFAA168CE2A20E4B4760809F0B6F0128F6EF315E01A +695000,u,752740411944DFD2BBE83CE23AA4BA586D7DF881CF83A992746320A93FE7C8805D3245ACABA26BD063DDA61A7A0A74775C8B2DA6F4E90C11 +696000,k,39E61FFB342065544F9D5B539A8DFDF86EA3F54ED5152FBFB14664F32ED329C36845CF8DC5C49503E4372F1D6BA0585FBD1A50F214445BAD +696000,u,3FDAB54F3A9D0BB8A4566A4C0E8DEC96D55E45EA9B30116A39E3794FC889508B7BCD36C27EDDC7130A6BA0E78039E391471E1DEE6A12B996 +697000,k,4ECD413799A2DC988BB6B7DA2B3ADCB2DF4168860BC8D1D657E6DC9FD5D78DD80653FFBABF037D21FA523112CCB32AFB0019F08D89D343C8 +697000,u,8B4800C22BD6A2D35DD37ABE201ECCA97AD84D24E30B03F91B33BC423C7DEFB65D1624507F82F152CAF4183DA9C1B95479FE5D524CD2C1F1 +698000,k,E6B10E3736A6B9DEF9959C141CC7B1158E4C3AEBBB9D0CF9C8C8E5F8B3B9A8A385BBACAA229DCDB7381940141192F50A29892871C42FF045 +698000,u,1D5791EEDCFBF2697DB99298ED4938459C1E31024D95CE1DD8584BCECE6892B9BFED4E0896D5EE76823901DB7557905179F13E3ED617D3B9 +699000,k,D6F7599D4690CF64AC44C8DF46A0A29DB683540D09BAA8B33877B4368E01B563249E8452259B72D707B981D9DDDE07E368AB955B3B3C6EB8 +699000,u,8419F5C2D65A1F0274D7F1535CA9B4BD7071CC2E8F8D97FF5B222DE4B168203684C84E4506D8129589B5EE8E37FBF86D520061CD8D7E77DF +700000,k,50FF60FD67E70E4D6EE1F4C7769DB7CBD0430F897DA5FB55702779B814680EF0A306F514DF476FB2093DFECA1DE76A16ABF0B13B10347BF0 +700000,u,7A72699B55C49146F43E1AF732C49DBA7AB263745B861D90A1FA16BD2C680267371117CA6869AC16BFA94300F53A5D47C059DBBB36A7E256 +701000,k,4F77B70B712387575EF47DFC3F62AD9CFEA0CC6CAC2004191B48EB36C982FE8644CE4053CA8D383655A749FB230C9B2E54E4186A0418F6B9 +701000,u,07EFA30F51DC614711EB9AAF4E2BF917823BFD79B2BD25AC1F0F167E56A364ACF82AA3D1298530AAD735405A7E47DEA51D4F168393F56339 +702000,k,E6115880E5633A783FED11CD6E345E808D3B35D4EECE004F5D51891F0B875AC795353B8BFFDC0452FC42D96E1B5A8A0AB3AE0F4DD83B6159 +702000,u,F672DFEB3AA94604AE3B02B0087918F8AE93B086DD1C5033B7BEE286A9091631B76299549797D1D2FBDCC28CFCE6F7E13B3336A7EEBBD24F +703000,k,9A336DCC504FCEF22EB72CA156F9D6C14C5661C1645B11E2048ED6E219B9C730E36F5CA4885FE2339B56ED83ECC73D15500D65EB1C06DF4D +703000,u,D00CE375F8F375BFFE949009814D142A70E8ABCF4E5D795E7600C3CC9F375C51FBC3F2CCA746ACC11319479C423BFFA88A7C9A3D22E72B8E +704000,k,75A6782D9DB311D4358B038139B4F4271FD5B9572D759CC708476DE82BF719E13848D86301B692C95E07ECD32DE563993325BF0D4ABAA5C5 +704000,u,874BF1A1719A6AB094596C807F3A6E18A898E60EE367E0F39DAA73BEF4DD59B9C09191B733DEF6A84FFB602B7488588FFE9D31D8B049A986 +705000,k,745DAED4CBEEE0648269E325EB979B4F866DBC87F0C8851D4E8CEFBB82D2E9CABFFE5F54722678DF18BD6C5EB99A746C2D8B97FE455DDBD2 +705000,u,3CEAE4D02B9BEB5EC77B03797B918B8D0986287360D07E7EDE7CDE1A642C6747A6A06C3BC2BAD1A84147530FB5AB4D4F7FE32FF37148FA8F +706000,k,089DAAAAFA4EF192652E35AC8073458BC1FAC623330DD5F2AE7197D2E06DC0CA0B147DFB671BED87A58E29A081AF7FD5EFEFF79E886FE47B +706000,u,5E69DE7DCE0EA38E655B227979F113FC9CC38317E2BF5AC63A42BCB0EAA038B8D2EA1299AE752E2397A00C09318229C46FEA5D4CF0DF01B2 +707000,k,EF740809CDFCF6C7C74F9F1E05201D05DBB236DED8D04E0712D2982D7004C26BB02FD334DF82E2164DC859520F02DD3DF4E328DF9B2DBBD9 +707000,u,63EC62581BAC13C2A566238A3DF8D3B55DE381A923687E0EBED08D53CA2459E2FDF5F4067BBA1E9B69FA2949E6F83980E5BE927AB53A1C36 +708000,k,8F1C912171103C4B4D5B525B8F358E469187BF9E3F7055D32D31A3BAE9377A5C7D1FD2E7C67FEEC3B37B7456EE552B5F2C3436EBF0FEAD0F +708000,u,32324CCAFC8413DF9A5567F34014486EFF8908798E215B4A9E1A858E9B0D2846D107A01803C8CF0194061899CE44A7D3308D667D57D02987 +709000,k,583023944EA95580EB7F7B21C68398C068556ABC4FA91263BA900A508F56188673CF0DF9487E520AC402B51C3E87FF34D90F05DEFD58C2FA +709000,u,C42F0FDA6250795A5C8D1D1A615B1174BF46D622EB8568BB156C70FA9CC46F396286FD2445FE83825115E5AFC1C5FD18652FF1A8B1258F88 +710000,k,1AE1DA07C41F1360718DF986AAB5512191A3F672AA5A94801C4D2BA9B4639CD9DB9A65B653C17F0C644A76E2E14937E6B7C1D9E44F8E1DCB +710000,u,3156211201733862763A2D02D54C7E1C6132DFBE849E119AEC044EB0D364D9AC52CCA46E6901864929B2E85201BAC4F8FD5BD28F40B7DAA0 +711000,k,1C1AA0E1A15FF2459657066DE5EA6829090CC3F04B94D0323EB6A0D3F110095C2BDF66D59C9CBE381C37C636BA725D855CC677773D3906FF +711000,u,FEB32EDAF1C7C344620B47BBED06689105A376961DA0A0D5F38376278540500E9AF348A7411AD842B69401CEC94EAF14F75CFACDBB7C3FDD +712000,k,E7BB1453CEA5BFA9A14854082FDA06F62C29C67F4878548D4AA7624DA4AD06BA10CEA53BE76D3086063FDEB95E35535F6304631314CD1EBD +712000,u,33CB8571405B996D6DAFF5D9E99EE60B91720F985E46C4636F96B7947172EDE5A1E150E53A6CAD515B131A7D815292AA755373C5FDCF0EA9 +713000,k,058294A3A58FA222C60851B229A7DD555BEF99DA936FA4B553E141D2718D679F0DE543973F51E3570AD96E53EE2EDC736555EEF8B245848D +713000,u,85A6DFC90AD54890F0005F50B51F7BB7D27A0AB2E49C8B5A033FBE05BD64D4745DC58E9684DE2E903830535B13BCD92A84870DDB66AA914E +714000,k,361C89879742FE18731F67FBD574024B14398C8A8FE8255C05F7F858EC986CBE5AF95E3B782CF10688D16B9A2C0983214BC548AF49738710 +714000,u,F20F88C55029825B0A75AC2F52BB697122C3F96DEF9FE583BC593522E531428EE76247FE44F549C007BC3022E2544E4D2410572BCA57DB30 +715000,k,8AC4F447F25C2510FB72D0D2DAD0F788E2606B5BC43737757FC1F07A8A76271093236C6E1E369383A065D31A3079D743C4A74CC9512D1017 +715000,u,EC37CBDBD311AC7A6C5F9026FA715D0343E1150B7473E8E98026EBD2E01B7B469B3F1312521EA4D9EF1DB94BF4C4FA18B110C7AA1A967EB5 +716000,k,4BD844C6512F7A418B55F81592C3D4BBC71F87793AA785D9AA1ABEC92DDEDE96625B13A69533987F0BE3BFC19A51E26ADB86279BDFE118F7 +716000,u,C83F76DE759FB26793077D001DFEB932F0189CCE072064C35C9712E068B9525BE59E08F7E6F7FCC921AE8A7F485E8FA945448A1F05750255 +717000,k,4842FADA079FF3435CC97F50DB80C36C15C89FB2F9FAD9106F887F876CED7ED164FF2347354DD4E8B1B767613E1042CEC37256B043D035A1 +717000,u,28EFC3D63DDA807EFF9B2B805E73F91588C59667D9878BDE02E309C80170DF6A6AF709D51F21CD655D039D7C74501A5B27484ED61922FF1C +718000,k,E5F8152186FB40511DF5CFEA4DE9D0F6A9721AFD4898A95C629F4A6CF918704D8FD817120808F018C3250D060E7637E7BEE08450D8C495BF +718000,u,0206352E26176DBE62E51C85628B9EDE89B2E178A5D9596E540075264621F5A1464C040484834735E4028A240522FD81D048FB46506E1B25 +719000,k,2997F6A3683F7E8DFEA7F088045668DAFFDA27959D7CC2568698AE4322B750F96CA8A0204604D4F100708F9E65CCAA9CCA91E21A193E95F7 +719000,u,286C8883B42613FAF57D9BDF7B4A4497EBE4FE5A50FC48B7B966656A228907E259AFD0BA66A441314DE2726D7E09AF32C39C8B68C44CF83E +720000,k,9299697A7700170BE7E32818EE13F991BAC1F979D87D07B5652ACDF2016BDA3D9229D2CFE31856B39E84C1622C6F816232040A99E13D408D +720000,u,5CE2F39C089517CB001B27D95D18370AA838B590FE705B5DEB63078E59123DB9BE36560B136A2C3DACD1A30972F80A5BB04E19BC8C41B0B9 +721000,k,FB387E6DEB54C3E1D94EBBEC0039894F5F3DF35728198BA55C6F7ACFAEBDABBA43F37650264FE87B9C5BD62F479F94117958A1630667F0A8 +721000,u,42B3C361BBA1B1DF542FC547172B5BD507DB28BDC6713D30455FCCAA4C28A82E6CDC812F7810051246CEEEE13D8D09D4EFEE2BFBAEBE39FA +722000,k,F04BBD3F9621B4386500698638491720F9C613B4A5A9AB6B569931020E93A932F60F662999D2D067092B9E31F3BCB3FFB174B09A8A16F759 +722000,u,2E9C4374D466AB3F41B2B09F4933A836013AE661E340D1F3183A520C5C7D42631D8EDCB2FFF19F66D33A8461135C77F11A742FDC0EEE541C +723000,k,C3D97C31B080AB337E899CC86C3D29449CB45A8082028AD07DE50704A2668B51DDC67A1E1654D42E91F0764D322EC83B3DD649384E1FBCCF +723000,u,7D6294235CE271E8DF3C32538B291A8FE0E4EABF7B6259C30E65850847BEC2E56CBED29407388940E6D962D6AE5AFD2AB000BA52D7030FB9 +724000,k,CCB2D3F10C7E9426F6DFB131E1042CAC896140A3635F8E36036FF8635C33D34FF8B1E479F9C239838DCFC4F6D4C2004D7A7C5F3D2EB0CCB5 +724000,u,CA6D67FAF57661442CD6CFE9FCF0FF014B1B999DC2156D09DC6895D7699B2797198CC9B4F974F333BDFEDF4DAFE3ADF7414B5BE8AB6B7606 +725000,k,053AAB67EDEC7E875187340A9EF3B55F7EBAB475586DF0AD6FE5BFD058A5542121BFCBEE7C61601EABB6A765847120CEA0D2B50007DA0A4D +725000,u,22B2740BF9F780317764BAC4FD65A7BE74D9013C7CB5843730FCD0371B58BAF519B00A84F3E321F0F2B9A9E62057CF718F5083D8D0FCF007 +726000,k,121A72FF24321DB2A17F54D506B01D43A9F62CF8C8D2D96D6EDA8C63DA4DB389BF61D28F4A6565CC212407EC71E18B981003AFD1B1E2DFD2 +726000,u,E8F7C381BDCC79560D4F54F8F12E28E8C0A228A07E63F16C925711454E5E3287DBB566CFA7AC8387A24858729878B43547FD891FFF520F0B +727000,k,40CDD5BFA3F17EB2BC3B15CD9FE0E39677DADF81C7A9905BAA2C251AFFABBBB39A9E30A7CD1512B8567E2F2EF2222A3E9C7BFB8049D16156 +727000,u,07C5E9728701C55E3F8C5B9F550AC7AC3CEA0E0C4EF8AC9C041C3F637F09F79205E0D14E2D999BDD83BB04E76E6FD58B6A715F4962FD4AE7 +728000,k,6A6D7DF6F9E754FB524012C35ECEC66A44782EEA7C600484D3FB1A387BBC2BB41734EF822EF9EED1B6016CCF2ED00F4F82CD7EF69ADE3CB1 +728000,u,5903BE054D74D2C8DF620218E25357169691810387B581FAFA47C56E69B18A51EB0DCD92566ECE110C359B1E6ED972252D5C6DA249721D90 +729000,k,84F9F62CDAA79C64344ABF3C84B58631372A93A59A616466888B259F6CB52AA3B88AB302E6D88185A3EB63D2BFCEBF038141F44F06982328 +729000,u,E04DDED1CB4EBBC2FC9AC6FC4D91597F6F2F8E9584347CBE0806D804B427C19E2D773602021BBD922EF52F68B5A58B71BDB9AEB6482920FE +730000,k,A98EE4499E9793AA94BAC61EFEE0ECEC8568FC0C5DE58F579B8E1E7369C8B8DA876BA2F8950FFA70A6F28AC2D9929627490BCE39D15CB803 +730000,u,A09E21391DEEC643CB142F6AED18A8B912B64D0517A2E89ACAB62C5829773293C119CFBE8074C382DF1A6A84B28C38778DE1BC4DFA698B5C +731000,k,7409FBFB320504506BE642E3B76770848BBB189B66D63073D70C5B5C6F02578352B08958CAF68DC2B0593F0EC955C80EBA88F076B6B61611 +731000,u,C6A98242DE40C7330EAB894ECC5113918732C6A60E5D3AA2D8A300AD98FBC263F1BAFB26FC9D0BF4B9B40DEF0F34D7C96D2918AE2DD18986 +732000,k,423BF4CDD84779ABC43B5069E356CBD3AEF963D8745DC82E7A7057944781C32FDAF6D78A058F559EC8E2E6E35B4590090C193D6DDB8CB206 +732000,u,559D85E22F3E51F01B1E7A55F8D35BE988510264A726CF047F63956ED446C3CA691E36DB58D91252EEC5F0F6DCCDC312D4F572C2F3E2FC7E +733000,k,B873EE1FCCBD9521C9ADE4DC49E4697EE2BD66FFFBDC803BDBC8E006B53435EAD634EAC0A671CB689CF85AE21419886FD76E19B72FCBA1A0 +733000,u,6A0BDE63771BCF47C9A4719120AD4B44FC09A95CA37116CF2889596F42E85B8D253E0BB0E488D7844AAACF281C7F6668209D7DB9B6E3E929 +734000,k,C54879267AACBFD4643AD4E319C7E24DEF3CBBE1710FAF460C7D6F8A89770B98EE887A8B500F60CF3276D8A885AE3E3D62FFCA1B83FBFC86 +734000,u,C0B42F65782F1378EF0EFC185356655C45EAA3DD282BC733065E68336F674AE81F7536BCD27AB4DEC26B4C339E720C1DC8AE153B67FF2B76 +735000,k,62A0FD98371E0F8A4B8FB40AA71FF497D4507AE95D5AA213B582E9BF9218FE9C8FCD8AF6C2C87C2331C4AFD3EA41C4C8FF49A2A544AB4C7B +735000,u,0B22ABA28160283824AF51476ECE5BC13E57CC37649EE584728D54ECA5FED2BBE2C3A727A6F08B774131400F067B53E2813E1626BA976FE5 +736000,k,C6A2F9DFEEC7FCB87A969E4AD59D125C596BDC37B529A608C5DF8EC43F5D3E64B9C531C86C71145E754FF10634B80360AB32F020414EC2C2 +736000,u,9C0265558E52A90DC5D87998B2A313BAEC85DA5773108198E09CFD8A0C950FBC588F0CF949A4D182356122070016D5F165A919D762A85793 +737000,k,21AD4822CF10332A02A72FBE1116BD96A3B652DAC0B74760C5C380E28975225EA60A9F8A2BC6893857D76AC12DB5EF4B5D35F7E50135F013 +737000,u,3DB03680748EA5EA554ED909ACFAFF235B2B735B3C977DEEF94FB6F98857E44FA152D1596A6B8D8B2C44DEA13C5CE6268CEDCC24C0FAB107 +738000,k,A383A82A69D6C5A73D7BE1F9D9F2ECA732E8560811CFE45817AD85CB01B9E8691B95903A6A48C343AEFC752C81696E40CBB97306E4FC8273 +738000,u,CFC67DF606B76C9DDD11135FB6A01657C055BE6859ADCC14151DD74540B66C580E7F13FC9C557A15E440A94C434978B18031F3DEDBCA7CC5 +739000,k,49B4E0E7245C9FB59ECC82C355AC4E93D14F2A2F61D799E3D05F9D9B7E69F3305513C585B73691F483331AED5B2883A7B3D3AE10526CAA80 +739000,u,AEA2D4625C02F45F66DAAB00F7C78381AE2158EACE63BD1A0738327238F337E9EE7F90EBE037CF67FE0836D5408FD47C5FAAB59664F42631 +740000,k,A45B58A801DC362FA145A7FE142DBE64F2DBF3ECD825438381B1CB42CE268AC03C0AAD04F68BE4EC41A5524A8D6D3CF6FF8697EB82813476 +740000,u,7FFCB4D940C3E8C481930DB0FACDC911BD86B299FFB1B7030FDFEB5F021D56136288C8FA0BF314C5604BC48099B006F744C2AD53C72FBAE0 +741000,k,7ED709416FFBCEA40CC05F60EF7DB7942F319EC75CCF973179539760CD44971A8F1F0037DC6CB913BB0CF67FAE8E8947286BCDDD041505C0 +741000,u,661939EED39BA52D1C8CE2BED96E5778E2EA4E65CB9AE9FB33A178A18A9454615D48CB87229597117383F1B6C242103CB16B689DBC243C8F +742000,k,B82D2C5CC2B6DC9DF986B27BF69CADD2AC7BB192B150FF6ADAED87B505C21682AC2050864EF4EAF1303CE6443129C699EA33885520F69EFB +742000,u,B92D65B88625225C86682235ADDD5BCC73C36B8F10E9C6836CFFE96E18EBE87C2B4AD80B912C1B897AF8871427277C41C1A8EB46BDE5E6CC +743000,k,B2E84AD73CC748A337E5E5827F3EB8E955F23C81A57A6A2BEC8E7276F72D9410D0FD4660C7BE1154E75A3626EF74F161F259AB8E6EFEA49C +743000,u,3E81609E8162967B8DB207E278EB62C1C2C4449266FDF0761BD9CF82C95BFC259AEA0ABDFF35327372DB9A4967DFD5ED461FE5FE063CD0FB +744000,k,FECB47D0984DE786EDE1B269461212B4B9CA97510B3DA554AE1DB17622BD3C79954791538565BEFBF0189881449277987ED961C096354FA8 +744000,u,FCF90FB5C7E8EAFA5454D0E51C9034BE7E7DF16F589A8B594CF618DFBF695DB0326EF5719F911F6A3FDB5B4685B915CFC372C34C83900E3C +745000,k,C2813F7318C7524834C820934411D8CD057D283CCCC4F33B7A71F85FD065B49355751E9A67A03599EF8243CECA64839A1CE1E03ACF9AFC46 +745000,u,843C0A3D6A2FE04A798F703A6F08A5349477135C23422E28C5AFF2F5053C3C1F278283B7191A3A33F7235C29EBC38DAE2D597AB19F8BD21A +746000,k,10C2C562DB892FFBD25E1CA64BD1CA91D388004610A9FAC66FE0EC03410291970A8088FE054AA8117D6233CBF6C22B0802B4729C1674209B +746000,u,46C374CFFFD15D00BB1F6503CFB7524C588D07B648BD35324F00A3DA9B6DEE0CB36AD5420ED58BAC31E8A305B39B01A8002AEE5D2A25A8AA +747000,k,B3C136A8C792D8A5707AB8E0AB2B451390A8476B9C9C3B7D7F6CFF4792845C07D260BD2D3641F331F01522584BDF83FD342EA678E1D71251 +747000,u,9E81A3E969022B5087413C7E14599882E5D88FEAB067A10CB945BCBFCC3D3A27CE1EB7DDA0E8B8AD45615D227A7860B1B5DF18776CAAC019 +748000,k,A1C4D4B8E27D5D58CD940267B25CF9AAA0E0A29BFA0D630C771AB56EF8067CA162F98A1F73D4B8A3A552165D941C82D4D89080CF4644FB40 +748000,u,3492DD3FAF5BB9D9064D053E66F89AE1493FCCED2A516908B4F6626B4CACFE1335B9CC642065FB8F6711E10E43B58B88E16F14A774697229 +749000,k,C1F8FD5E5D65746AE9A2870247D87E06F33DE9D4F77B75F74921A37E6EAA46C9C1DDC39B2E4181163AE4BA324A79897976DA3108E8E6CC5F +749000,u,1D4D588DDA3AC630456514251EE35BC1BCCE1BA6A930D6B49CFA38FA0B410683A9D27391E46659ABB42DCF8DE014459C99E46B3A3248BFD6 +750000,k,EE5B6516EFBD3C15E1C794616680E5BD5530F73D2DB9DFF260E5AB82F760FDA4D7435C3C007A5CE29F3508979F909FDE1598BEAB97D5EE4E +750000,u,6AA97027495866E9F99887788C7431920AC7ECB29929BEEF117EF6C461A24FBFD6DDADA9653513FC814645804F0C947B7C2D52DD3AFA454A +751000,k,BAFA267985286C12695961D514706FA62164D5BDCAC895122291AE806A2F8C848F4AE4F494E3C5B2C9B8AB9A0481AE735DB9C28581D64D9F +751000,u,8D48FD90D92F2C0B797E6DB32474470F097A3DD1B4758D26BE1755B14430AEDBE70846343469AEBFE42FFA23DF4B0F8E7A95F0F7D77C5804 +752000,k,779106FD283586DC89CFCDD43EE203B6C726EA6D9CB97BDD040AD9B2CE661540E1F16A2D0102307C13F76A460BDB978D37889E4783C04AD5 +752000,u,D52311D589F589F6351CF3D5CEF32B78364F94CB1B3A2750DC518005128F16533BA2E80E521483C53F74DC4A989CA2D1FA6EF1B6657EEDE6 +753000,k,9B53BE6CEC9FCC90B0133213D17A11B719B4EABEE0A097A3775FF3D56EF94669F14DE26235C792A734987050A0678754BA1D157CB81DDAF5 +753000,u,1BD8C3D1B609B590AE7E08FCE4B8C57BD3F6106CC1087B2A00BFB7390613D5E3E7A89C793E0A98AEBD3DD1603B2FDBFC04105E6B48D1A00B +754000,k,6A762233B81CA07DDA28695E45E7C96CA26023DDBBCC0461B8C659EF7C5E7D0C6BAF20BF8CD411B6C6F93C12E3FAD2E76170559E091FF000 +754000,u,60C6A35ECCB291E65C6AA2717E9D804DED4D3EE136F0833D0559241305048C82BF5CBF429045B72F6B8ABA6E62F454C4F7147017F5081D8F +755000,k,56C8408DB569EFFE37C7FB43557CA32F3712A20E84F94460AD5A2A470FC22479E1AB2E4AB92BF36E1D3F692C5224C522B6C56159897D9143 +755000,u,3010A973BB30287B609E9DCEC16F25982DF152EF24A84842B534BD070F181F131057EFDC64ED0181B195AEB849EDD8E2E8B156D2305C8D09 +756000,k,92C0733493A1AB36BD7C21B0716F1C66E84CFDF90C9DA99B99CA323064748EBF0B9B0416C8B6616156F36CF1A7E4E90297D3E9904B6B7E97 +756000,u,5DA0F6E6D3E68D7646D8C2B801C03BA4CB84FEEE0811FAD5338A6873DB9754FF0423074B35B228BEA927D3630F5ACE925973B6F0B51E3898 +757000,k,EC0CFEF6F664D30ABA972A21F1D82AB6CFFAC43A5E9B84EEDFD1F91088068A960FE4BE9048BE90FD7B76BE4F1EDAE3E75B64DCE3F4D261E7 +757000,u,2124B281E6A776C0448CC4F3D375EFAA6E61BAF57749FE861E6D339B3DE260E5F2E7B81861643BD40C5FE2C0A5C48EE3E4B6053B007AC9C5 +758000,k,0FF5CFD4CA6412679D98E1DC1312FF48B7410FCA26FDE1A3B99FA731287516A0D2203DDC5A5962D0DDEADD36811C54EE60557FF48EF92554 +758000,u,3F56BEC3976E7A8F12094B953FC54E88E51262F6DCE4FA0E7731F5A33BE62CC8E53E074B1F2A6C7A7D6E9EDC446E4DC88309C63EFA3B712A +759000,k,BE8DCA4C23022044C53209B97C1A9177E3F1ED7333C3C4C0ECF0E6C28129A2E7CEC44C53C121A0A3C4F0C0700D067565E2F4F96BB84F3BB7 +759000,u,4EC9C1C1F61B51A56524A5D46CEA36EAD4013B011E2CFA0A75B6DAC0656AA8CEAE465DE6F0E8DD726AB0C5A9108EA154C98BEA30A4410FFC +760000,k,8150D6B8772911945E039A875C7FA1B34782933B76C8E170571221A24A9879EA9426C69AD8E742B2DF234A722A89DA12B2967715C27F5FFE +760000,u,E13CD828DB9008B9BB09C8ACAA304522569253596EC3761FB984FE0ADA6A9BB23F612B6CE9CC5AD1A057E3567FCDC6EBDF3202E041CC1A10 +761000,k,B61991ACD9A897C6818953BD86645BE52A5EBBE935D761B7F6CDA923DF02608656C14BBEF33040F580FA8A8241281319080977C91D2F8A43 +761000,u,0E63854E9967FE02872ACD317A25EA533BEE8A5A87A7979C8C3327448566994FC1BAE28FA52B9B30AFAAF0FBFEB7F730DB264D21E237F3CA +762000,k,DEE9BF81CE9412621D9AF6BF5167E6F3BE45604499EA6AB6CCD37C1FAAF41746F00CEF5AEE6F2281B1FA3E3F51B5EE1B0A9EA3740E93A9A8 +762000,u,D2AD398989AF754D4EDC39E737273F0A23B46EF46C2AA2157972DAF14A18792766F422B851861D85C1F88500A6293C1F5CF3823E63A75F57 +763000,k,47EBE65DEBD389270707C28D020A23C39A25F08096C204741DC5742E4291C6FEF5AF587454E0498DB22F913FCA7858F238B47D9313807CE1 +763000,u,5C550001A73A4D668031D5E485914DD8C7EDBC05FA0F5490CB5DC066080E4C99DDA7669B6DE79EE71D99F7D5D68288844CDA8C54BFC0EBFC +764000,k,9C001CF8110B3D914C8FF78A2A6195CC3043D2003590D5E0FA6252DADC3E4750F05CD478866328DB016B74334037B5D1F64FD4EAB06891EE +764000,u,875ED4675AD284810AD9804D997703FD9E07069311BC1DA8802297B5034A67D27E045E74C9610EFFBF8465BC186A1CF7EBF903075C152C0F +765000,k,4841643783D4B5689CFEB83381382171464BB0007D1C28A83DFA79F68D32287552D7E322923520E588084BCF6277AB8EEF3BDE6B1DF91A8A +765000,u,E9EB0BF040732F72FEF446AE62E5DB79C3CD9439E653FB7964939270E4A1C1BCE6A5D1E6972AC1840177F8618E0537FE96A85FC41AD8D99A +766000,k,15AB43A4AB3A721835DAEB26DA277DA8D86ADB5022A4B3F33815C0A0CAD7EF4B72C613A6D22E91B2EB87FB8BAD02F53990634C29D81BFA7C +766000,u,E81095CF431767B29802FFA756477E99F38A24E743F7E02F2D0275CF86D490B24E0C6509069B0E47B6382F5773BFF513DFF72E0780878472 +767000,k,A724E16B08AD6425D65EEECF05BD37DC3F104F02B29157A8B9249C3DC0578042903DF62DB41A3648C83198533F0F4A3F3419A40584FF33BF +767000,u,F081A2336706F6FE7292B255A7D3A2704B6A203DFB85966692BF8A8EEF0EC820B3F6BD4DE0FCD58F8956A79B5199860DD894E313CE9D4B0C +768000,k,52DF5439F69070D863ACAC37DF5E80611037EACF8FFA92E60369076690F5670A7AA4027AC0DA359F67D16E3C1AE6A8889D2F296FDB491D0C +768000,u,F95F147392D00104B5C4BFDACD6F3298BC8579D75420B6934B81B5BE53126DF37276D8B2423B775A8ADC584FBF1611C8AE0B68053BC48DCD +769000,k,71ADE4FF4648A0C510B3F195CFCFCE1634DECF06B560A27AAAD27FDC3EE8DA8ECFD073A99792E2B289414D6B53954AF687750B342622E984 +769000,u,E466EFB0F71E584F8B345F44BF85747E77DF19475C409ED32206A8083BB88C7E50B5D8F02F3E65FFC9A66E1F3597A03F73CF47616843778D +770000,k,1D3FFD502EA4507434FA40CCE4CB50FE1AEAA63831AE51C343007307551B58DC1C87D44ADE79D1444FFC7D2A256A9515C35A2FC43215179F +770000,u,66BE027FDDFA2A8C4FABC89C0D81A7CD79649EC1AB98ED4B9B9C845411B85F590A68502A68B5994916D466EE46AB606FB8C7771A1DA6C925 +771000,k,6DB31243FF11479C05C5653F5F2433E65035D634AB5C12CE432D86BCCD4D02DC058F6C89930507604E20149EFD6FABED4DD6E5E7061D33B3 +771000,u,F777EB2C86F9E0D8CD23FB0191D57AC11D3A4F7B0E8D66EDD1801776DEB4572A59324D4573E0361C27DB48EB292E110F7CF54D900A2E6064 +772000,k,79680696EF1E20C1D071676C1F13B11D30E343E3E4D41071189898F60A4BFEF8D0D007FF38C8BB80767336629FDD3B30DA3A84CB4EE01073 +772000,u,4698FCF3D78A0238540CFDB46136379AE26D3944C37D79A1668B3D57B9186C2C71B6AB3CB3720C1AF5C771F79CC730C70F36F4AF09CA4197 +773000,k,F08FB731A74FA323CFA32CE9A4C842BD16B6FF109BAAEDA2C97FE0AC8C1CB5DB18E454F3E5E352EC126E09D2A973D554669AFE7FD2C5904F +773000,u,73E0AF4CCA5A3D7DE4B267D666D5A3176086B8A2DC492DAC898E6E4BF0AA83F307FB629C5ABD72B6E5F3178828661BCE4890F3FCDD2FF5A3 +774000,k,B226F8149AB96176F851489CF5E116A074110A57B885E5A5440BE56991B516B3064043408E35516AF08851E16594086A681818992F55C9BD +774000,u,32AFC011E1333CEF79DBE948DF24457E68C507A7289E5AAB46232CC66CA735106789A87A18A91488691DE8A2116A33DC5C535E1A44B9ACBA +775000,k,066F1242E56A21712B8A70F31836DB6D27EA2238A0E75D052234E836816AFB1637EC795AB93BF0343F1769E50D965C3DC4F1DE5F4456B6E7 +775000,u,97E9B342E2813159BBDB44E3A14641CD23C43072219E4AE59B92DCCC23FAAAF5C5455B0C6EEC5D36679DF15A69A3CC783E72017918F7D9D6 +776000,k,04439EFCE8D0C5052C3BD8F2AA0E2EA138C81F63364CBEAB4CAF31D609ED6A199E42817C0EF8F286CB2D465C463D330005D21A814A08F340 +776000,u,CB48C06A41DAC8ABAA9F40C20FAA6E3555956F63F5904438ACE0111698C8D4C4CC150F07FBD54207A97CDE8FCF29E17BBF2FE232380207F0 +777000,k,752E310BC8FF31CC6309429838B6B5F34F7BC9AB8978CE406EB5C29FF72867DA5146647409E68498587FEDF5EA5208AC20E2E9D54387162E +777000,u,F84976C4A2F783F19C87BFD90BC6731D04F29E292FDE1AEA13905F1D04351EE916DE8A67517656EC89F66B1C57D2046D7E8C78BC9405B59C +778000,k,9F24343D970367C01D13054631D65F47BACCC7F45E3F5E35E581AB214E1004638FDB95DADFB5BDFEFB22A580A3AF86569BDC4A2CCB332BB1 +778000,u,06724E76AC1017A8EA417F134FE54FFA8FE660A175B777FB2D44ACB61BA77A4A04A980B9BA85937532FD39C528EE7D0F9B789573A3218657 +779000,k,FE6F8A9AE3BF2012983E04BE202A2928D89DF542E8E56953837C52F2510346A060F8B02001854CFB1CF1EC7875404BDAFE86B9311AB87974 +779000,u,82F0D17BF5BF55F3616AA0F24E5ADE64757A82585147B674D3D5D38DE1C54F0B19E2E2006A7FAF773C43BF94F2D8B32EA1B0FDC692DE3A80 +780000,k,A576F6CD97740F5B28C29D6B800EC4D69DCB6FABF5590CAA27D0FF0BF14102E0F20C982E8FCA9FBBDA623C06FCB48A382903EA92CAB9276D +780000,u,CA53BA715C592BCFF196F9FFC022EC910B55778652C54FC6E9E7C2B6D59D8291B9FABB7E3D8945588A679A49AB6CAA1CF5DE7A35A53AC7F5 +781000,k,CF8FB7495821CED8D65C25E6BE0A7FDADBA876D1ABDAD3C3752B0A68FF360A68D50987635083F30B6DF6ADFA0A95543E4CB06305C2085D2D +781000,u,14200B0EC10146DAAF1DB95905F7B24C14CA9FAD6F7181A57C64ECDBCE50A05418F8A7029799CE2EB52D1CC4BD1EAC6193A295D6481D092E +782000,k,34187C69F90B18C070847B2CF6AF8C11B4E168BE02E1699D7605F4B22EB362D48AA68966E215ACB7B1EF1A83F563877782CCE8F54F6A61CD +782000,u,F2513F53DFCAE52A6865955689199CB9B21FF66A3B19A3D06702F4D5F4CC2027A36AC672C4CD0FE631A35961181051AA99C9394728CA8B07 +783000,k,EA1E0F2616D682127D0CB29C210240BEDABA11A9EE8E17C6FE09ABD45625B779B6A52746A7F0BBE8AAE8B6DAC928BA64187A9C7E654DD28B +783000,u,8D9474D1091A6F8214A77CBA382C0AA1814910386563A6D675B7B53324224963B06E64555F037DB9E58AC8AF6E673CAC7CC12767163C0257 +784000,k,AD658A90FC792E818AEB8FBA17556CB2638C0B7E5C319E9678BB884D63DBFCBD86D57BE30B7EA19AE4C3669C0148AD84D02C7E06982D0829 +784000,u,098E814F553A5F70445270722ACE41FD8E199C4345979B890A70A70E81A6911C454FF585D4D335D24C57C175CB5DB22DF3956E617A5FB3A5 +785000,k,0EA8FC91A08256C47E11F3F6B5ED64582E87B6F4916C990A1FE77CC0A489618A0BECA05A096C8E9B665C55FDD2629C814FC93F64D7910A6E +785000,u,3B5A3C75A0CF1F0E354E47C8EC2A3685E1EC96FCDE3D52D8E346875F67ADFE042A2CFEB714769357D69E1AF21FF030796821E373A4F4AD64 +786000,k,9287778FCB20638FA70F200692A073A3947D4C8A26D20A531D5E2A6EEB36367840E7A4EBC41E6293F4BF406A026F5C057AAD6F0E077B7E96 +786000,u,A9B14D8039017DBD9529002630E3167B9E2616B1788C8AB467036333D24CD2B22CD0A322C445C2D17D26F7F8FFE12425D39F9D74665B5E0E +787000,k,EA3B8B7001F7984ECD82252AC85B03A306F36F4162DCD93175330B4C6968BD9AF21558E1FF6D204E3699B7B2655C2A10E5F8CF4B5476776D +787000,u,6AB6AF33E10B21F2C4BCCC488926CD6D1964AE66F753E5B4BA9BE191FBCC66E4FD96F4C840E2688056D2B41D37627DFA95E84D038624CF0F +788000,k,227B0BEE81F3302B9E8BA1041C2FB923CA91D5274A817896E32A23C65A3AE8B269DF1452FE5F01626A699D60653C963D12BE8363B419472D +788000,u,EDA881813D16C72BDD19E44F91709EFC5A8F6A0E5D37A26589D74E25EFC0B5712AD7B8647B3572D35AEC1E588DF87E9D3D4566911F1499BA +789000,k,A1EC9553FD7DCC8376437800ECB5EE98141D995840BB6B9DFE6E0A36692809D309C685EC8A98A88B61BBA3E39D339D12F716E5D6B9A72947 +789000,u,EFB62A555ED6F4A552AB3973E644343F28A994B9E66AFE51D9C386C9F5BB3E075954CE364D516C0C32637F1908FE6D7367CAC395690C960C +790000,k,B3B8CA162B3A502D1DB19456B2EE3F2C1B16B8E9EEDFEAA165DF2A3410881E109FC248B9A077126927B794E293C3EB1CDD92B3D4F8D192E3 +790000,u,F2736799AA670CD819563837F43ED9B34996A6EE13D08C161339D624C41012DB170547D4E8C3873A2F576714D81B0D0B50BA0F137D8D22DD +791000,k,DC29012BB0882681B14C1A9BC997050F4019F0AFDF8B70B450A6AB401923A7DB1CE501B547D885F7BC5FE05B6935DDA6B8988FA0147448C0 +791000,u,EF4E89F8044941E1689D407FCC44E2927C1C523CF56057163D81676C099D9C9ED615CDE0A0785F66C4BD263BA66DA14C4BC797DCC254D2CA +792000,k,D8D5391418FDA24E1305AF1C8D2761026C5B4A1C6268734A1026C8D3DF041A73AB746CC98608FF432FAEAD47EC2C855AF4BD1265274B9483 +792000,u,2F258E4BAAFF580C287D8244D962B1A2856DCE2985A56921498443B6CCEC5ADA71E837CBB3BED7C977FA5127EE36B86F366E6345542044F6 +793000,k,AE28BF8D30C2268C95042F45DC7E81C7318FBB765CB0649AAFD31921814E512D9257F3E49C5A4BCA7A292971D8FB967120951E8C119A9562 +793000,u,F200CA0654D9C705738710B24E8233CF2FAD2335903A8C33FBC433039681DBDC2AE37535E62582B302E8BB66A4D248F811B95A8EB8056C45 +794000,k,BAC15D161495AE11CD592782026023DDB46E430AEA2E95D32857D792AAB756C349F5BA9E83EB88C87EAFABB5282548C76BACF7BF18613B88 +794000,u,1539D659AF5943B839E27B8A8CB370FEAF5BDD59C012052D40514B0D538440F9EE8761C9E23248D08C70CCC49268258A9DC9AD2EB7FEBFD9 +795000,k,4E24486A316E3A71377762490F2666E77F99763758573303AE8018E7DA637ECB5CDC78F9B37B9D249DAC16824A4B5F5EE5C02331ADEEA481 +795000,u,A9E2FD65D5D5E707BB1EED8FB39FE44A7567E12461A9BB3E8D7AC9521F3CFE453083F624D25E179E5CD27BECFECA328DFB573BCF207D0D8A +796000,k,FACBB1C996CDEB3FBED6DB716868533CF55E2BFFE355D508E789ADDB6D71419C410D6EE847EF293F5D78F14321706C796DA54B553327AC43 +796000,u,80A46F47CFF8F34A68865E336EC8FB747DB0F5C8E0A398ACEF936890A8D541069FCC8BA3EFCECD70448CFAC67BFA7F56147ADED3BE97C83F +797000,k,84FC00B93B825459159BA7ABA2A4CD620E291CE1ABB970431742A0F6138682DC5EDEB464382AD9D8A3130FC47C93F864E032EA96094B1D15 +797000,u,4378EE04EA275BD5525AC89E960CAD7C6814C3DB78A380FCC2DD68643EE79F27FB1C71600624E658DE260DC4C056EF976F58397B235990FA +798000,k,C2EC5ECB16D9B45936E1A9563D7E62A9421C816D0E2289849DBEA68BE5AAD7402209D3B1F8E09BCBA51EE8898CE272E5A1D40D05D5D7AE28 +798000,u,E3CF0F926CF3D0C4DE9722FD2472A90F106CF82AA0934D44723233A59F25040D1C39D544076D816AB7ECDB1AB8F018A72DFB0F3BF78606B5 +799000,k,F636A16202602A1917A8675F0BB5590829CCE8663A5915441BC8F7DC0635F3866D062E034BC7BC7EC9E993CE511FCA1F2EF8434AC7A1DCCF +799000,u,0BF49AA7FE22EA5A253E0B2C12FDB88ECD56E0A2058B40353479E9735C14338CE119067CD8B531E4D75855E724E9D554F9A03492A752E67A +800000,k,AEDA04386FDECCC6ED2C8B48FE81824F153677DCBE19951C577518C42A600523F61A14CF247E36A39B242A0EA338D013A2A6755243A24C87 +800000,u,71839BD2177C7626FFBBC488DE73B8E252C33EDE4E9C702720B88C44B73DB9D0F94B0DF17936260CC75BBA3F5FB9C296D35706F445B86DCC +801000,k,5DE7E7E74F1D9F85706EE78BDECC3A780465797213F1BED99791F3AA76193DC32BD2EFAD4428CB07420322AD43635981AC97B6BC853B30F3 +801000,u,92FBE44E21AD47EE6F6041D07A4AC36FACD795588A67A8E94339BFDEB7DD7F16B0FA5CF869B03F767EBB074C86F47E3DA99B483809876F7F +802000,k,660ABB608D7C880F99A7BB87CF9019ED2F28E541419542FD85FC74C345DE6484B6EE3C2A1D7C8F855F6913A8860BF1F8CEC7B5AAEF79C371 +802000,u,617F231D1EE95232349EDCAB3587B26CFFEF504C849000C03BEEB6F2FC7834CA16BEF6EAFBD97755E1E32B83E3552EAB7EBE1404A5A704C3 +803000,k,3A8F08A5DAB0A0A42B28C8E67B65660655D58EF8416159D8BDF974A97878209B8BD3965E4ECDCEF8A1DD716B1752E0AB2C2BBCA483E34F71 +803000,u,68F36AA0F69903596D0923818012563DE17AA0516DF1119548EB150B7019C5E2CB1B442DC61694F079C633B80352CC4A1812EAB3CB6270F7 +804000,k,7B09CF11D2108B2CA216B798418523FB27844B9A688DDCED1B9F91D84BC1BFCE3E50919DC182444EAC3FEE2CBD87F8E9A97E8F72A0B2884B +804000,u,432C3F2F021BEEE9D57CC4F669DDC1A167368D0677D01BD0B7F6BD9F2CDD29C3310AB517FAE198A80CD7B4B8D5B13EBE2E405B1BF645389C +805000,k,30A8E1286A709A11C245929F4BD73BC3A754C36A2B8B9B6BC6BF5D468B88A075511379DFC8684782CCEDDD2DDC2C8A8F0D3A92DE703FB070 +805000,u,D9129D022927559157DA09A1DDABF0DE1D82E6E22A6E224FB225083B70D11ED564A3FB09621E53B1B1C618F729EA3845C927338E6F79FFAE +806000,k,A9869BD81509071DEDAEB14F6CF82820A0C35F9C427A7191D1EA137088F696373D4B9852475F57447AB82A8A8675B056299B20BA9CD31206 +806000,u,D3948CA286295581E701EC048F3BB0623462E4C1FB01FE58F29905FF1AC692D671A8C9EC08A47F876E3B54921475428864D60D8EC2909135 +807000,k,B2A537BD67AEF72841CB2608A1B7B72B14C0234140D1F1E1E3FDDE48FFC35197A2178F7FAE3CD4B1EE818C529B48DF9B1E7E25A81251E11A +807000,u,251D09487686E7AC5CE766CF3347F6885F9740F85751E78BD27F00E1157B899C52FCB09F833BE96E8DFDF03BDD0DCDA76E0897C2DE8FF45E +808000,k,C7520FE0B682AA6E4ADC075060FEB99C7F9353A246EB8D4A1A8B781235ECB2BD70808A3D014E6BEACC0148747AD9F1953C4C8C87E9DE2B2D +808000,u,63E11C8ED64F48137F5D11147F803F68C72B5C215E348C7A5F46379B496F880C99765E664FD652A7E5C9E68DCD0B53E72EB2928BFF585A71 +809000,k,657F70637EF3E1FAC4962FD14A8E557174112D78A941FABEE2AE9ECA46DCC39AA58F2F5C755D8DE935EB5E4EC65605EBF43F4FECA2B1B10E +809000,u,C10F63AB69C74DE84277CB01853ED18C949CFB569198A843A37D9188E5AD2AEE790542C225AC830F31588B78C73A30EFAC9A02919A49B808 +810000,k,ECD2DDED03550298B3ACC34980BD6684C3C62E8EB7B813908933ECC94138ACFAF9CEB30254F711C2FFF394DBB047B0748DD62A751AD90EA3 +810000,u,2B343576166FE36418EC8702667CA48C8E3ABD6D4890EC6582D96C248C6C80346A25556DAD82BD1649127F38F4D87589848F7698AFBCDB89 +811000,k,9146DDB8DDCD006C3EEFA55BFA4D7DD30777BA7FC5ABF0A6DF3CE5FF0023A4CFB6463E868D1D735E2D19C7FE53ACB71624BA284AB67B1425 +811000,u,45795763EB408C3B4D8659ACD28286BE615273F26F50364BE1EEA406C1F68E2A79EB21388E12677F4910717B5EA37403A3FA3BFF10A846C0 +812000,k,352AFDD8DDD22B60363636834CA17CF476AC6E9F02673C74676355AB4A3D59D01EEDE5A3EA3EC1F16A22436CD852A0E8941AAE36D5FB871E +812000,u,788F2FE7E52AF3AAE239092D318E88F67C585671F0C85D7D5F02991DE93D8AA913DE00279BEDC3A5BB8C774AC2F1B72765C89C1474CD8FBB +813000,k,966F2C628965D537ABE2DE6AEA6837D4F61DF70B0E18D71358646EE25F4DBB7A65EF19700DE1B55F19A361BB117A351EA87555686AB0F1D8 +813000,u,CA14A89065E8FC4EABBFCCE45F168350DD34C27F352096E8AF9D5680F9E7DFB830EDEFA1A4100B0D070C4171619D3C2D00AEC3228FEED180 +814000,k,278D48E12BC2E240CA85096C674022879F8372D3900F358AAB85F413E82C06124B03B27661303790BCEB731E5D9DC1D779D9CAE02D8C5390 +814000,u,7F35A465CEE043A9360FC2FC3EECA8CD5697AAE2F82FA82274480739811BD7C8511B4E2785A1A5D93F983304229307512202F763C1F7D169 +815000,k,41876BAD6FD16BD96449D3BEE2AC5816483D2777D20F4658E02F506882489030DFE73199E374D9D6C823DA68B7FA356757CB99F6BD89ADD8 +815000,u,891FBCA54F30D46487FA2A018ED8DE2964B0FD47145291E478B768141D565E78EDE791FBD1B573212978AB12ADF7CCE4BEAE9258A2ED4023 +816000,k,5DF40CA2D394ED068B8355842963EC5698930D3A1B96EFFE48CD94B433F9ADED0551C3D6A248BBDF3BADFE6A608EF6CF01311E3F2A4FCCAB +816000,u,14409612BEDFEA837DB94BBF80CE659478F0DAAC8476CFEB5B77F06BF770C62BE95506122B3547E99AB310DE0D6D8AC80572C0F924D90555 +817000,k,197E43CB9F11F2F813AA60CCE8E3CD8666F60D0AC60CAC5207AE50E067D275BB4BF91ABF00644A0EA80BE150C0965B799496129DBBE9C762 +817000,u,2DA85BE648CA993A6C0864EAB595BDC2C136EEB4CB6F7B010438C7EC09C445EFB5CAC410A7D9642A371970807308A27B72464A830CF976DB +818000,k,45D90348631B5BCAC2C6F22A460F0757E88FF3F837164082860BEE6C8816CD26F3D0FB0534554C1C9073263585D5B50D4D8188CADC95C106 +818000,u,77509F245654325D7435E02FDC4576DB76D9908227526040E54DA22FDD4995C240C5DEF8D0A2092DC0FC71637B48C9EDF575E531A11C2B71 +819000,k,1A1C88088BCBEAA9869D9A1F107EFEDA54BB88D08C397C9AF88771C8ACBA77EBCF2F897AFB47077B9817C2135E88673B7EF22FE126C0DCE3 +819000,u,F0DA028901D52DC5E5E504A5D87105EB42E55D0CC5EE8489DE2956C032F1DA0871FC73F63F68089C814C6202ED6B5BEA4095F3984CCDBE83 +820000,k,5C68D327D1FEB9035D00E344914FBC180E3440E5556C9C6F352B119F750A917CBF2300C9D29818B9A23F32694C8A0E6CFE27108C168F2FF1 +820000,u,3439725A012B6AA806E81DF252987BA88DF6AE2A7A901E62AD18F489E95F7FA1AABAD0058C64E21D5BC1EB3C9AA50C38F32DCCAD675CE2EE +821000,k,A35D59C7DEFA62F7493B7F441B10F63CA2715B741CB3716CB6BC6F7AC15690FFBBD3A37874BA4955C7F335B813AADFCA5EB85D1CD8EDA423 +821000,u,7258AE9999D221A22B1EB68B97C83E55FA147923088936EC6F7B8E81003AC30812C6FCC047A9524A35AEEC6525D994050507A8CF0934AF93 +822000,k,7FF8BE9EC6E25B318FF06424C534B9729121A95E0C45D1EA2934DE62D6D93717E29B5E0FB82D027152655715AEB49CE1BD68182F274FCCD0 +822000,u,1A97709A9EEF7B52E4866749A086AE23DE8D4AB29967D70BC904F58A544FE375D654D1CC3B6340CEBEAA3F9EA69B27E51847DCCB0DFC9B23 +823000,k,FD1514176FBF5DF2F2A20485DECAEB95697F9A977105F9E8B76218D0B31AE82040A356AC8657889B018DE354C5A4EA213130726068E54615 +823000,u,891EEFDA706F90FA6FB26AF0981A7364E8D26508A3E3BC336A7DECADAF8078F4120ADEE65A0DADFC3BE56D9E3F44408F9158921EE62F97E9 +824000,k,3064531B53A38C53999ED6D8F7F092305843133ACEB8B00BA9568289DDB489D69F4E1B9E64F3DA12F96D1D89A301A606DA52A5AAAB786495 +824000,u,89496425139DC612F567FD0A57710193B04F425D5285A12EBB15797DF968F62246E5119E1D0F0735551DB6DA3DA8B1F4D39DE19EA1BF6FDA +825000,k,712A0CB59E60A4F47B65ACE46C78BEE24D35480EFC3AEFDCCCAFFA9880280A74853ED9C042977ECFE9EFC21D050332E992A9A8E54A2DBD2A +825000,u,FCC29AA1C551CD8E0B028A744AE30E4559527B6763F9FE8A8746F8B838195C21219DAA26863F1A89EBC51A5056F8CA13D184170DC1DAF710 +826000,k,B6BF96655F5181BE7EB64B449206C07905634DFC9BED238ACBEDFD97B27EBB9A17B86BD9EBF98CA269A827AD02C0A9DDB8A7174A8B138C49 +826000,u,1B92202B15CB89141BF0EB5B64046F576FE2BA4F307AA532F1E5B3378FE13512EB59FC6515DCCD3922E6C2CC832335DBFF603373CE1864E1 +827000,k,58F2D3CD76569B5793BF82B749FD7EE8C5D704CA9DECD3C283EF2435BD18CF194261380AE2AE77A90AD15A4B286D895F1DD18497530A11EA +827000,u,E352E38BC441FC77D112E781328FBF6CD6495792FD38869B89EDED8B1B514127E4BC2321FD609D0C60FAFF7B0D30291ED5495F25F03A8514 +828000,k,607471EFE2860BD3D518CA33492136E64EC8476A932297A4BDE8CEF8443F61C76166EE7C043F084AE95DF61AD6998859ECA4925C349BF38B +828000,u,5249D37F8D54AF419A70FA637ADB0254077F63D758A6610C2F9DAA5A8D4A65BBC42AF408AB86B6A3AC8B5CB4EF09D78C2C6F672DF5B7CC88 +829000,k,12708BF937885DC379757F7AB164D49E1564ACAE20C0D6943D81DD5DAB166C0AED38891B6BBEC5882B834CFEEDA2A2A256C30025B6CA7EA3 +829000,u,F938A62C6C0133A2AA1CF83372545F2146424867502E87F3692F4A0FED7F4ACC265497796A83CF222E592D9C8D84B56BC697124C7BD64A40 +830000,k,07C99C060D9CAE0B946185601A33938627897E6460C6C54E2D9481A41D5E22778B28C2CB15B559D53BBA7E879A18D3E927CD7528BFC3D4F8 +830000,u,1729C1F267230D94DA42D053FB57BBADDA9A2DEBA7055F2C2AFE134811C7E1274C9F8E84186CD917F4C84A2D5669B145B15A07D6D5A638B0 +831000,k,2E43BC193C63E241DCF5BB7362D9B25A93E18264A942802C862A4CBF9D3EBD49AF8FB6A61668B4B45637AE4913B08021614C6F3B3C1C677E +831000,u,80FD2093241FE4D5B444F08306A5D755A863CCFE36E051C82F39083C9A71C5DC95C36551F7DFC1ED091EE90409B078A7DC07407F70AF77C1 +832000,k,B7B8A828745F89C372EC0941D1FB5E036775E61B35F27589FF481751F373878ABE07C80B54893429F7F016748C517AC1B22E6D6C45836A69 +832000,u,2262E014E64A65517617DD70E4AA8DF64705645CBFA9E7E6F6FE4B86FBAC050A1166AC550D1F78C8C06BC17E1F7C82534EC64AE8555BD51D +833000,k,C8E7621FF378350B43F51C140ED48A98620141365094346A5321131B3BC0035A4F29103C227B3FF726839959BE356796D1A2C3748C37342E +833000,u,138DB7E09F8C993B9F5A2C57AE65FF461D75BDBB755657E6778498DC27EB9B5B83C4644050F4FCFC9A4CC62F2A2725C62F5D1DF885AD17D1 +834000,k,7AE179636E51CA78F24A8A633F92EDD7D24F35568D4CE1AB60ACC8FC8FFF9707D55909A676A17BD8AE39252DAE9BE90C9EBBD4D13D48BDCE +834000,u,640F897667BE01EE8FBB74CF66BB0698FDACA025BE7B34FA8AFDFD601053595352E12553E5E6F50F47BA9E169FBCB7AAED7DC2E126C7EAAA +835000,k,3CD7FE13713EB1A04EE8431E55EFBF819C4AB8CD82D635EA445DE9D6D34881D5F9D21C72F77D571E29BE5F3ABF0AAB23E373887C8CD40826 +835000,u,F4758DF69CC0E6258CC85FBBE02EDD5B959FB25CF8425C2179787AE964F5F0D60E44AA4AC2218D692104A5E74FDF75F2C1FFE56C1EBAEE5D +836000,k,98707ABD8FDA956FC09BC34641F79EECD7C4C0CDACA4F815511C593A09BD56A7C0CFE893D6922C14CD2241F1201849234746952993CB2E67 +836000,u,4F8B2EC406ED4382351643DF02B93FF3A224CA7ECB99485857BAD89582E81D07C8E82925BA491B393D7C9E0270CC5021110E9E0D6AB75A35 +837000,k,22FA641C6546B3429934AF6FE1F3BF7A76B7C24CC823C41A94A18200A80F50A64C124BB5370B7A242D0466ED0C2A1D147ED458485A32E502 +837000,u,C08B721C7F080C6CCDAD41F1C8F99994E897B8CB0B9E8A68572C1B5323F3ABB2B89858B2B51201D9095551FDCA4B41799CB8A3C59F604F3B +838000,k,14BA3C48C6EE3F536BBD1BE62EF64405579CF677591E60D082A6A66627EBCEE3129ADA3489A3F324C64FB8B0097F3A595F22AAB831D3E557 +838000,u,711D388123C6A4F45C8B9B8A3F7C78892BCE05A2CD4275B35B39E3E7AB72FBF7D842E4143266737B1FF3E7562BA1FD491C8C16873F231561 +839000,k,34547146A4271079FCD5FA38C2319631B67F98C765A483406F0D421B940FAED1AB8E0EA3F612538DFFC7A08A138A6AF22DE83A2BCEA84093 +839000,u,1BF929E87160C02B0D531C4AD0352ECA71271306D9294ECF7C18D8DFDD2082616DBF9B17AE9F0F51063BC37E8C060A5BD97F3A8E7437407C +840000,k,D4DA95AADDBD45B4FD0F1F5C093EE9A6D789DA1F15F8587F9C3B3BD190D2CC8039285DFF8B8158868478C51C1E42C2FADB3C9C824B54B9A1 +840000,u,8F24206185FC0B029B4B4EC4EC32C339B6DCEF8D74E80D758F4C0E66C56D80E454AEDC22E98D02FC18AF47C8912C1E79A7CF20835CCE3F41 +841000,k,EEC128F4911D9C79442DCE05467A1C2B853A98D7C13B9673D3018E210E278CFA343614AD85568A5E481A84034CE4529B4215FDCADF167DEE +841000,u,DADC903F4409F7395A03A7D708E290B75412723C63A66C33C964C702C203E1B4A50DB8EEC5D04D65FBA8472328BAB056373A07BEFF63D95C +842000,k,2AA16AAA5FEC4EA54DFE68C3462243BB6257968DC061505EC66016ABEA52E62B71C0FA009BE11829D4242AB97AC02E45108E94AB00A43B9F +842000,u,CE35D130FF0C67F05BE80F76DFA344803F48A383D29FF4F5F462838EDFF0C1F44746E6FC9D81FABE3D27C821D74913A459EC171EAD977FC7 +843000,k,AA0FE1BD154E334C9BF97A1DB8A56AD81E0F994850B1F67465F5C1778C33F56A819A649BB3D35E2B03A5368CC4BF01D80B6240860E8C58F9 +843000,u,5BA287650B4C663CDD32F01CED9DFADB4B4088F70E71402091E828423924DA2E252946E1752A8FAE0C27BB14E22D94A08AFD34A3098530FF +844000,k,666D2C5B6CFF1E6141F42BF3195DB7D464A4A1663AB121F82B6AE31A70B4C1637C2D71F21E51357CDC97A524E44B6C910826B81FE065B823 +844000,u,61F9DF273815C4E0F7E224FCB046B0CD3F36603275718D3C6CE0B24E21922FCE86D0753BC18514836D949939533175D9F56201A71DA5B92D +845000,k,2843D5796A6AACD6D61F9EE1047B5E3533843ADA550B7AB8FE05F885D045B151098CD9F6A54EC2CC30C9A1E29EFE4BA8BB4EBB3FD2B74ADA +845000,u,C5B80F41C2C6B51A35142417CD65E281F84572DA88C0CD26B422CE283D0FB51F16DE9BB3A260D6D04B3130BF99717D4124F95DD78F67EB87 +846000,k,BEEB05D790D4D9A268F095ECF74362096A3EE20192E722D7BFB2ACE48FED778D173160E375108FE611054EFC50C3A222AB56EC9097C469CE +846000,u,3F5657C219324ABCE01927B8650FA0077C6CFD1A5AE5242C86F9A4E139803D6317FCCE88723B5F22A375C028B0734F7AA9B7A2B531010BEC +847000,k,D1C3C22D2FED32F6D31328B0F4759DB25951954A8629083C02B85535789594E81EA23EF1A5F03B4A5CFCCB67A0B6AA30DD6240BEC4D10C75 +847000,u,87BC5868F1F7D086445F8FD6B98561C52ADDE5B5F2E2E7F41B163C1AB0423BB5F6836A2A1A459A50B62816CC176077CE15E669F10D0DD008 +848000,k,8731C1E753C4D8258B2CF18A8524F7FACC03D10900F82BA47C0A756FB28AD242D5C5124DBF374DFAF1AAAEEA44BA91C53B4BA7FCF5D5AE2C +848000,u,E1D0B85C33ED80E51441F0FFBE39BDC05B1C48AEC485D78AF2106A1174598AD0CD9B8BC98385B9FDED09D5104889E5932A12444EF62CC25C +849000,k,02ADAF777790555DA76E6B2D4726442FE66CC5DEA9563E57D290E7BA32779A50DDBFAFC54CCCC839BEE1E3049EEC6E08986231143640AD2F +849000,u,42BDBB166EFF95750BEB9F2FA88359D8DDD9B30B7F9E2F0F7514DE36419858B5E9DDEF3C23ACAD7F7E90C80F94731313CC8AF3DA5DD7725B +850000,k,32AAA9D394A6C8253AE2719C7C8906FF1B912C9CBC8859821956B5FECD7292AE141A0813F20C4139EF38BF5462FBCEDDFD197D9F3C6A9C42 +850000,u,0A25F827B9B5779BB509818C14FBA08F54DAEFE2D6638B8CE3DC5EA35E9493B480739ACEACB8FEBCE98DD78C1B81E980C85889FC90C17E11 +851000,k,660CCCF2E9E380395F3E13DE07DB11DF8734FA7EA183E22FF22D5D71150205FCED5C1572E44CE4606A6EA698C6155B210B8438D6D3DCE7FA +851000,u,21F08AC8077B3C0ECD47E2045EB69B0D78EF4F9FFB284E701CC95C4495CDBF0ED630B9A6BEF0B27571B841997631FF681F83B8515C0F59DE +852000,k,D8C5CF3405C5B39163047B19D678881A8F175412FE19336D8607B5021EE5D8F6E482B3CD0916F56C7F3BAF2449D61443A564ABFFDB558AEE +852000,u,D71DA7BD55EE3ABF33B3B6D95D243FB185982C56648DEBED422932CD9646DA24BE30A1F2F669BFAB9326EFCC9C11ABD038F6DD52EFBF1E66 +853000,k,B68213C7365838FA75C8176978FE447899AEC26B69865F1F6FA5535DDF773B064417919A7E272C2E4215D34B43DF358AA018B79DD0CDE3B2 +853000,u,A66533A513EA66B3D1C757E6FD8449523AF478464181CF1CADCA1DD6EC5960BF5F1C51C4438C08E5F1230107CFC198F792765E874D7DDA00 +854000,k,F56F162D21F32834F2EF665D4FAD38D45FC417742AFCF18DD382ABE74892F8B388FB0E464D6E0DFDE424929808479E1DF274B325349EA9C9 +854000,u,38BBCE1B7B3925D2A71460A8AC86350E26829C9CA40A3CE3FB58A65487A4669244AA73F5BE06DF22CD71F1240F56D5644689A268FD82DAB4 +855000,k,B26FC486C32B40616F07E0A30487D35B12F24DCF961350DDEA1C7C00EA135D24A7B641F327DAF87C56515A859839EAA777C0FD2427776E62 +855000,u,705E46C4032E07DD7068423D6D8F32B842F114DBEB76B894059B3EB43C8E7EF2C10B36C943F63E06A4A2A00C82E219309C487717F7C08AAA +856000,k,6D0DCC2D04E558512D0079897BD9E4862BFCB868FFBDEC316ACAC51264559305DEB2C90F5AB4842308D86928F6B9522E90963BEB371B222B +856000,u,E7D0E1A29A170C775A06FBCF9D7515BB8DDCD3D0DBF1BA8280001D3928483529F730AFF1EC37ABA1FCB89D2A7549BE1206CF4113775CBDB0 +857000,k,8FE784F2BB8A6EB6B5002DE2BC792B2401665E760D2687C1735FC655C0720F76326C0BE00424852B1C91EFE0E69362DBE4C38F3312721D28 +857000,u,BD0B3E7F50D6C4FBE2BB1FF2609CE8A864060316130CB35B094FF337C6288DF98588DBD4F8BF0E8D09FEC73983F6DD3ABA4C2832BFAC93AF +858000,k,2FC885D34C536699E10457E3452F26060C967A872465CB9A9BBE8CEDE726E8C30B5F4B775E39321F4B7EFEF60098653573DF1375FC3D614C +858000,u,BB7BC55F1B73F8FAE13051CD3B146679DA950596869EDF610363A34C3DD03A1D259F0F5B86CF661100B77EB66AB157C35EDBE7077C412209 +859000,k,0ABB5F58B75C9A2BD2B6E82DF10F133651B028E3DE42A2855A81659A5D1D338F0713289B6F47F06B7C5A901122BC842D528766CD01CDED9F +859000,u,D6349F814791C715ACCA99EEDD2E84730C5504FFD14DBD172E1D64CB587232184A413742AD23A03E568CC9F2882D68BC5351C0422FA33735 +860000,k,1A45A5F713C14A4667C3B2F61747229F9D905CA8EB4A360A15D2E44D909579702AC0820DEB4F25E8DAF1C5BFDA8ED569775C5022F01DE05C +860000,u,5FAB440DF23D553D32C2514DBC0D0CE89AAB71BBF4D7AF3C0921DF68D605667E9FCB50F5FA440AF9BAF90B2E0E0A2B9A489375CEEBEA23E4 +861000,k,8ECB1A5CBE58E302EBA370DEA55DA5F888C0687DB9055F88CF0DFC43EDEEDC9D7109397801FF61A77BF15A24FF2D7D7FF8AE1A5FE1E326BF +861000,u,5E2129EB1F6EB24BBC2F8E3898781926A9BF7664A54FD868EE3D35301E9147AD7407F94135CA1B2505BB1A2FB91164DCABE3097A2C66F4C6 +862000,k,9B4C21423AFF12CDC21DC0A700B86F181C69CA1AC4DF6E51510957936BC4CA339FCBB7315A02C3C72B9D2E6D2232BE14F24E56C25849E7D8 +862000,u,525921A998B7AEB73AC96F294FB2C2844856387272B3562AC4989B4923657AC6CA04312438AF54EB673F3C171B9E2DEC8DF12506674233E0 +863000,k,8680FD368B76A7AFD3FF71CA405800568CB8C910C204B67CD7262F1A7988745DBB33556ECAF53C97BF83CC21EB20C7977CF79512CC97204C +863000,u,F7AC68D2075BE6C139E03705B19037B8DBF33BCB9A2A55402DAFCB7D0BCBB57F05FC682E026495F5E1A7697CBD238EB8A5BF6465D5E8E37A +864000,k,6A87D09FAD0EE60D48466B2D61AE5E45A061CFD96DC22BF6B6B8807CA27879C3F7A7A0C0A55665AC8B92B990B7C7E416665DAB85B08427C1 +864000,u,3BC0CEA4446B071C81C52C44098721ED6377924DCBE897F8AE6A9E03B6979469099720FC0D1E330DB465BCF4FB48413972EC5C4D44EEB320 +865000,k,BF45B6B9F1CAADAC7D6158F5468C935932338A57B8CFAA08019904ADDE980A2C8CEADBD4FADFA2D009C73208BDFF0B906DDC60F31354B156 +865000,u,2F29362F12D3D5FF00FC3F942F4C76E3CCF8D864E8FB27B934C62665D7FEB25EE8D4DC3ABC3EB1126094306D6458061732BBA7E4542F6D34 +866000,k,E8C06B1369C7E0293459B53C632EC2853A36893A37A8AB4AED7921E8824FB64A69689F8753B5BB56790706F5B11EE60C732374E4F20F6F7B +866000,u,204455634FB1AF69289E66C21C24345C417A5AF3618DE02FFC1D32A98697FD72F9AEC759C708989823D1FE4AA02D94AA980AC749B758A18A +867000,k,53624892221D3852C59C97FAC9B35041972BA041201E577019B15BE31A395084E44A3F7ECCA5A6BDBA53B497D796197091EFED42AC756EBE +867000,u,4A071B39BAF8F644A761D2D93FEC19DF2FE7E5BED6F374797417116F9BD146C2202E971CD1D653DD959D2DA7BA91EB07F7C213D6964E715E +868000,k,80A74E90202E2AAA53EA2FC7091034E995A4E4349E24556DE50E64F09E9CEC941872B812A0C69F3E77FE6F091AC6A5DE11B80F8020620388 +868000,u,8E3900AD435FBA88B0C0397F9BED450ECB71182F19FE76E34875B7D6CF854BDC0F403A071E9E15BC76E064E87F5C90D779FA12228667B0F9 +869000,k,9EB30D2203F225CB71DE194ACC5E41B109E77EF16D3BC67F871C8301A566C7975D5096E88C14891BB19836E82407EBA594A33B6AEB77866E +869000,u,3A8CAE16574FE5D13F6BEFF6E465495AAE10DD8EC1EE7DFE011EEE3136F0A91A1F4A7509B8C8F1EB225E5BECC8644EF6EE11BC3167C2BD2F +870000,k,12B1E3B94297CAEDB733F9E38225F378A44CAD22777704D54B21C698E5B22B322E2479C5D3B98C643C3FD3B30489E89F671C67B6E432B0E5 +870000,u,35AF8CBBEF7B9F0EBC5DCEFE8E26634BBAB3B17C205B090E988D890687502934B8EB33F502E759C63232D6BAD026B9A4AF44C2C9BF881B4F +871000,k,413B45B2C4085BEB32C2F145CD3185C5C7A258358D455FE9757754F2BD4358DE208210AAD411473FD5F4AC09D2BEB1659473AE5BF0BA8CF4 +871000,u,9C6FAF2234F3295B9ECC80C59B416A052AC9CC4CA78D222F1462C4234EDC0C0642A9C3788360BE9AC0B7CBD88AD273D6F25EF82FAB02B8C4 +872000,k,8B5606CC5A0952BD26CF06EF04431A33633BDB6621C6125837A178369E25E04B0F169D00E4CB2FA420E339B5A73C7DD6547DE31BC419B24C +872000,u,C77E2745A5D4C07B1AEB431D4506CA2196F97B83E25DCF4556890DFCE3174619933BBEE519EB40E079C7AC61D52A500FDACCD18CE2C4767A +873000,k,E103933A76F72C6DB885B84D1B277E98142296511E463BFF366567850299996BF39F928D9649DD9774FC6C54F4A45C4DF4A2B9153CCFC708 +873000,u,0040F3198F2400417464E490A2F9A7544232809721DF6D490228E2870F784790934608EE83F2F68954E3CBDCB73E70A8229F06767B409B5B +874000,k,3E7AB1EA5F903D700904F6592F5089A5951D31AF35E25A6AFA224A8FE106088CC551D993FE4A16D0D47C05B5BD3EBDCA136A03702A5E0339 +874000,u,5774D696A03358288A6A2A8FC129D90987010AC88F25260A5031422290398F1489978DBEC0C1E936D49DE6D662BD3E73D8B2082AB0550D02 +875000,k,575C8C9BB945AC874797D79CA8229E3A554212B493C4631DE38C4FFC8240240ACF646BA9DA4DD966E04F57E8AD7457EFD502453A0815FBB9 +875000,u,F0F0A8460ACCC0FF2B4595CB19FC019656CA5B728254FE3D86D2A9AD7B42E7C4EE8941D8F0182955C48C360BCD755204A57BDD2FD221423B +876000,k,4A68DA8B554F0AD38C4F728B6ACE8152836F1C412E1F0E1956CDE8102C6E09BC9BB8BA19E87762732A2887BF37DB63101117472019E1D342 +876000,u,2D79EA590DB0BC2971D1072DE61EE7B1F79A065F9447E095EDEAC476380925891913773731C29CDEBE99ACFC78B2B6E571FAC9561A339046 +877000,k,9DCA2138FB5C054733F5E88E2E3A9B4F6B5F93C58A4C615C5CB488D4CEEC197A58007C6860BDE0D1C4F9A4F9A1EB4DBA5C046D75B5A54DE1 +877000,u,9C0E48EDB9B03BE9A154FA2F24DA6FCE28778CFBCAC84C5E6E73542154E0D753E82049942D6A06BB1042E610DBA3DBB81DEF8DFDC7ABEABD +878000,k,915C9B539CDBFB36EA51AF5EBF0F2B4CB0D405C49B23858216C7F6BE1393A5C1208A6E759A6F3B329746884D5BE3C461212D18F5016ABBC4 +878000,u,C41335ACA00739C9FE045F34996D0BEBCAA888B45AC591716F531E1E9A57FD4D99E0F478035CDF7A8C3AB0DE63E9088A9124689CC86429C8 +879000,k,2FA7193941FA8D163568C7341BE11A29BB8A9B0B73B8AAD7C0A036FED5992A4BB97294593276A8D3C6F869B47B930DB72A058CEFD1C0B371 +879000,u,36FC4334830B327965D6B16F70834CE50419A15F91F2D8841B7247732EF5BDBBBA74D17C336BFF8CE6E6C7EA0298CD5BFD07D8EC8578277B +880000,k,CE6014B9223ECEAADA9D9EE297BE53644DC203EBDE3D4DCB8ADFB3DEA0FB9D0CDB31C0FC13BC4C8D85222758F1716A4581FCE2C1365B8536 +880000,u,BC4B1D47B6AA487F7C691C4DCBC29237259F3DB991ECD5707DEDE170FCEC2736ED13505C91788003734D302290D2D7369D31D535CA8F721D +881000,k,137A1C96113BA2E8CF78AF1107CB0C589E7F0A3A6F65170CA2982BC2B577059EAC97DA8467B9BA566975A7F597BE95AC89B87574E4DEC113 +881000,u,552193A75F485414430B66AD29B63A0E87B4F0302290622B7691FB3E2C0BE68C86CE90ACBF9B4D077CFA04B66D8C02F0BE81E77988D0395A +882000,k,4D230518ECDD96BB2C7F739F0E9600F58BC1DE4E65220F829BC76A8AB73B229DCCB3226DB487B8B44FF64A545750DD441230E1CC3979B41C +882000,u,527F5771A50FF0FEEBCDA8EECDAE76AA1AB422664B92F005DDD3688B86E0BCE066E5512E355701F1B1BA86924AB2EBD31029E1ED2F237395 +883000,k,1D97670551ED7FA3510F19C7F00B8AEF95020DE776A8067E267F57801E839D34AAAC078EE68415156567B2223FD28200D4AFAAF3C9B135C9 +883000,u,185D84A9B7B8DB58D17FFF17E44EE73636AB8CA31374A39BE9F8A443AE45B674222E4A64EE7E4A3AAAACB3DDB612491F42707ABA2AD1A440 +884000,k,D2E5C02DEFB4F18A8F1207730FDEE44E4BAEBA95DF88302C3AEDEB2E37926C12CB66E5552F7F1A0144CA2D833B6462327DA88E2E0A5D1B24 +884000,u,396F0D5D6CD10343E5DD90C595422EC75C9FEEFCF303D347F54F2C9CE2F4A40B67A0F920D3F79BCA7CDB5DE26B13A0A5EB40403054667BB5 +885000,k,67168E14C1670D6378A7A2DC4060419AE1E539AB4C0B76E8B8369038293A6DDC184D7CCB65F6CB866DCED6D6F3B83BA595CEE087A162551A +885000,u,23B5C1EE6194B193487458003611D261E58DEDA53D4D568C0AF49AE7D27C311DDF281C34D5AE7EEC8B43C3F596C326A51A551759B905EECB +886000,k,CF55FB355B48E4875A43481A1CD010445A7722D66ECC784B30966D40CB15B22D81A70AF90E657B7BD100B931C6DE989B7F35119BA3BE761C +886000,u,8D29DB8BFD67C46918353F258F678FAB553D351324CEDDA59C36B605DE3DF1E8A18920334ECC80410498617160BC471AE9795E2B422E6490 +887000,k,2314C39B526DC99653883C521EF6E47001E2C2828F1C81BB8C3333228F25104C32C82563BCF3B9B23C8F71E385FC01411F7DBDEBD4ABE861 +887000,u,933AA226845BC8105FE288DC782BFE71DF74EF378178675CAB8B796B27ED50128223B30D5A36088C0624D94E93EF5BB668F32379FE86FFD2 +888000,k,7E1B338C358524CDB014018C2787A537299FE89976105E0ABF325CA8B4DAB0691F286D1993EDE44314F37AB19E062048F43F05D6DCE3619F +888000,u,260E26E030D8E5DA29A9D6FCA933CFC831129D39454F986FB36B2B4F12936BE29C9801B28A03154002272552D1CDBF3084C8FFD44C7DEAFC +889000,k,7C4A25510803D0078EE32FF6CC1E52565B874C6232DBFD513CE39BEDABE1DEBE54CCA916DF7A10EF45D363AC4ACB6B139579C513174C492C +889000,u,FC55DADD29FC9DC8065180F8C04E73DD02A8664C63312AE370B9BF88723BA50977664CF5D6CA032DB4DC962707B8A7D499B933BEDC8DA98D +890000,k,23D63F3ED458D51C8CB23AC9FEF67AE338D1FC8A80FFA0B3538CD612431F8925494F69725A2B2306310AD4633B579BD72710078DDAB71301 +890000,u,B5F68495517AF7DD36F72044E11392F39CB36B85342EF7F9AF4C34CB7D5119110A71F68C950FB0F20908019EB63476C93918397D0AB787C4 +891000,k,58A069A1F334B802B1497CE2F210CC49098CCC84D866F4059FCE5D2727F44144AF36C21C1150208531984AE484098CB4AF03248515FCBC94 +891000,u,DE3C6EF1F9C3F5D9A58B7BEAB6A583F1FC44D0CE4E892DB4F992AC98DCB288646F5FA39308FD8A606BDFA8B76D3CAB5F58A437C3BB684D28 +892000,k,F8E070071A56C4581F2F5B1597CCFBBA3DC88BB4DAE98949DD5FBB8B1A2CF92730A367F6B3BBEC9BB3B5A6CBD911EA43E8B363F96AEDBB2F +892000,u,99F9B0E3D08D4B30A012988F0E2323D7E5B2C34CC549588FAF9A2F2EE61A8E02DF8BDBF54CFA085559028B505B912B4B57612E858E2E2880 +893000,k,8CBCF3A926DED4E474262EED98B47F8FC7FFED52B850135BFEED2E7768959DCAADDDCE0F5FB989A80415B53483719A598293A6A8C7335D33 +893000,u,16BF2C7A281E8AA3A736F5909525C297F29F63C1331162E8A9B9271AEB643B019E34970240BB5018AFBC3844372AE1C7CE3E4F7F93160471 +894000,k,CC6162257CDDE7F9DA90476400B461FFBB9A84E44C5CD24A25482A9F9DC60947665CA8F86D0EBA3D0C9FA6D67FA2650A898163F62E0F1607 +894000,u,FFE26A30E7F2FEB70F027FB6B8A0FCDF667556AD3CAE353442FE7DFA525D99C71DFA38A29D81E64BFBE4574C60E7A979096168A9FFD39A8F +895000,k,D9669E0CDF997231ECA19C4991E03532930C80CC57170FE06A4610ADC4FA4D5A7676FB542AC99C69B284A25C8A59B2FC3E19F1CADD142296 +895000,u,E97ECD46A34EFFE7E13F39066ACADF06B9A5CA19151D1362481F6F14F393FB16556506B4844EB46A6BE1F6C1E8262A8F186DE3739FBD224E +896000,k,F7754A1915D8C435F80C67E3796164D66C77176FABB9132C63FB45B4DDD2353A9674F83BDF9257215116E86EE511A10C1CD79C3F795703E9 +896000,u,5469F53AC24A25617A3BE2A35E44B1F767E610F19ABE1537411B9D6BAED56EAC5A59CD98B0173E6879CD26964D56F3E85FF91037BB91BC29 +897000,k,158EC689C5336D2660145CB2199E8987F788BE2CEB0BA9E00387D08BE2C3D789E306DF0E694F5F981BAA618552D4A3B835603413803B3E61 +897000,u,63F8F17777E3C92E7D00AE35EA2707510D09E9E6368BD87BB1F93D953BFD7FD4A3D99AB7327DB5527CD07683589804C251EFD408C8388CBA +898000,k,FC3A7B0A234019F209621D6B80C30DC32AEDC9B92409B90C1B919C7C38791D12B48A250F1E10F1D72F07EC07F1B48E8DD93D795D4D90482F +898000,u,75ACAF8B35036CE8DAF8654E4F9429B2CC18A74F3D3FC3C217963EF94B7DF83A9F909F8F80BB27C31C5C3B4EE5B5EB7290D6306CA1AAC4C1 +899000,k,EFCEEF84E2A680B18874656594E9CF637931C489E3CF2700BB16E033789BFB8DBED3E8E6156E3FFB46CD22F5C22570B5E5AE5BF0E37EE574 +899000,u,E2C97EB4FFDF5EA19AA86D46E12D4FE7583126D4B1A584B481FF03CB11057FBEA7B495B3D3DACBABA2F2945992F23E5863D42FF60DE29D47 +900000,k,35F06381FB88C454B9542A143E47DF2FB182B195D28953DFA8438EE154079FA13217BAB462C5EC3FFA5092EFBA55D980D6E59CE158788362 +900000,u,680C924E52BE61AC067D8A0109A0371943A6F3003B10940D29711CC4C14200A021334ACC207A20699418B0BD226C413C311BA532DC1FFCAD +901000,k,25C9DFF139F4245F87231E4DA7EE3982178E140C59038548C36085CF47446C2506B7B85316F547571A00AF258EEA376E2A141A45D96F66B3 +901000,u,8CFF804BE3596D5F6ED5F7C0D5A0756AA41C9CD114EAAF92FFBF4C8725DF2F71A6123C5FA542BE59203F55C77399436AEFB89A169BC6ADD7 +902000,k,AC48100424655647D1A9350FD201ED06B3AB0D52A0E940C649230328020DEC52C7EA5649CF96D6C3F9A20D0A7C2AFE7278C60EE13327B5CD +902000,u,CA0C697FA0225DC44FF9687E2435261202D7241985609D1E9D63A1600860E336FDFDA52A717C6974F48D8B99BF5FFE7B08160E2681F698FB +903000,k,D5C60C4F72365C6AF389630C04C28086D3550911200972EF8F1B9669391F8F360D29AA57E7D09596C379A494D96F92B02E84AFFF9769683E +903000,u,65930602D330EF72862D8B32AA040EAEA28F213CEA23161261D970B93350B38C0B47FE0F111978ED5ABFA10DD2D39EBC8485676BA4698E56 +904000,k,DCAD87C3AA2FE5CBF9A8F8C469425173D40E88971D0B7EF38B9BC0DD8B2254B0FBDD87576149F83468319582B97E0EED268615E8E9993F86 +904000,u,917FD4D5D6CBBAAF56592C89728E913898A8E7E51DBC2B6543D9941FC5E28B3BF221AEF623666FCF7AA3F479528683DDA06A423B7FFB66C3 +905000,k,D89EFA0E522C0ECEBDEBF50E483B7108BA907CBB39927D9EF44209960449C304B47358858BBA42E800D2B44B2C0871E71981DB47E2C46DC7 +905000,u,75B31C13EE0A78EFCB6C738949A33673837747435A4CD93DBE98A912AF067B414FEF28BE8EB74B8EB35797C72687B7C126919330B227B2C8 +906000,k,EA47E7CB97F077E3A55C8DC3B102F2DDD105C230EB1B2055EFC4A805855DEF7A86225639E4C408EC8E9070BBD7924863D65D740A265D6E36 +906000,u,51AC04FD1F1A66E6EA147E31D734513D704276B0A5E6A0E395B817B2782BB2CF62499F012874B30934DD8DB3E0DAB81EDFB6A86BE1CB8EA9 +907000,k,F2CEA67853C4702679B5A3E14C43BFADE28F0EDD9FFDFFB136AA197894852C8E3FD7920F85C45C20299C77C7E278590B324489986376AB57 +907000,u,CBA0C1D80019C53974FC07676709C9C2C5C2B800772F9784A39C10F9991903F63BC8B9024766741DC6E53F25A8078605BF58301428EDFCC2 +908000,k,29274FC85ADB4A13E425328F5979966A21F0E596BC176290B5C77C393954D1BDAE0250B76A8169875C66F5439E011D80395B260120D7C615 +908000,u,485478E07EF3D25979358B8EBC90FBE92D6EDC3A934BAC40E942F54B24CB3E6552C395B498F43E85676A83D639C6489CE427A2D7306E4D89 +909000,k,2142CFFACA26C26298B25C29A638DD2172A5FD78618A4D24D211484827A6553989DADD7068F6FBD5CD2C03C09FC2FD0DADB98AAA679252F8 +909000,u,FB830A840C5EB5A712FDE3D1471B5E75BA35FBF41A199A5CD3533B1833776D255628C913E980E649AF07CBCC924A9F3254D651F2682BCCEF +910000,k,26FE10BD922AEC4CB5806D45FE9E065C4ED9D455B459CCA9F21140CE8283515E992020BA98D7A176EF341DC018B75A1CF03DD97226C6451E +910000,u,D68FACE884AB5DEC02274AFA2D1380B16AC9097221381A001B42C96574279970F6AEDA6415C485E8B1E500D904A6819C4A5EFB84EC5944E2 +911000,k,7182BABCADBA12F4FF461F6DE4EB86495192D3FD4F3D0CFB8C1C6C9C53B75A2F49D4BE62264B7040D6E9A97448F4AA83E00CE09963FB2425 +911000,u,7903A6392068B620685EED218D08EE59D87EE3FCEA41BA9778C0B9A96EA373B7E1CBDB1C95AF0C0EBE675638D9280ABF1957251219813F4F +912000,k,52692D35E75EB71D68BF150FEB411BDBA3D6D4EA460C475CA9FF23B29AB344A7B7A147D353ECACC18791689CC023786DB2C9DFE623709B6B +912000,u,3E98B901C6BFA7355B273D02D2CB1BF8682365E3E3A47028AD69597F69F980B63600A1DE64A3F47CAF8D10BE628668316CDC14467401914E +913000,k,641453D074D5E8E19D6CD79E3E4FC9BA1EF6CD6398EB1033D26D1D005EAA3F5807894944E90CB87B2CBE60458FBB0B42A4F852593D966683 +913000,u,EFE9BD61F45C2D736B951F3FA2991F1A77E93A83A3C5DD77ACE47D3E9682C0745D31E96A6B46EB1DE17D98167446AA2B80EA56D9C097E13B +914000,k,9ED25AB014C6C98AB02A5693112EE5401599D3DEB64F1308D5689415A52415F7FEE3E86EDB91677ADE85DF87B5B9EBCEBE995623710E91EE +914000,u,DB52DCDF60DCA36A66D0AF201F146D8798B40497AEBC18BE29A6F7FE4344E1A33E999C8AA058E398BD358F6ECC87C982B7B2C97F5DC60E51 +915000,k,C8EA6B9608EAE0ECE7BAC4259C18B5E50E366952CC1C43DBCD55155F291EFFC8F8475F03C5168D1847893A7D7FEFFCD7A04670B54C476663 +915000,u,1A089B59E6F86B5284D4182C6D43A94AA9F5568BF3C2B3C521B745E0C37E1E380DA88B1E2A77FC126AE3C5F1E489577E7A4423309F8A4F79 +916000,k,8367453DABD3E45A4310626DEB9E82C766C93E0B0CC3085D468A03D9C0CB6B83FC825F2A37D6B18371A59189456AAB699FFB04DCFBED4FCE +916000,u,69978DDD85640A28D2F9CAB55FB9E6C082F70E47F3E31F49EB00EE63A7E7CD57EC7C92E6FBC0E9ED2D0FA44951C2B9963EDDBF607A9ABFA2 +917000,k,47AC4907CEDDFA3596B51FAC0476E8D3D83DCCE9D4B3AFA2A9F2465CDDCC7DEFA901D62589FC156E674EFFDB59CF1F08B9A2E89B5C2D5E5E +917000,u,9DEBD4BF8C58495512D15D818E9CD8853D2F2255F4132A9B917410480B110C560495452D7D40521297491FB3F716CA955893115497C12F5B +918000,k,4A0B9B3E8F5BC46C7B315E1AC6693E9D3EB62AA3D93985C9854B24CEC61C3DD93AF763750F15E14141540ED1B0A11F6F004512EB8672206D +918000,u,F08C324E24AB1FEE225A737EE46FC9B3EB90B59E0822E8A669A7882C0F82AA6FC5D66D34D6EB1F3CA804DD1CBED15239F7DC6566FE76D938 +919000,k,94B96689AA2367D50173A950B2DE0DE92B1DDEFEA21E4C7989BB274439F3B9D3C119856E8BF1EC604BC545F6DA9043C9CF8E793CCCFE2134 +919000,u,59E4C62966EC85A975E68C212D6704E2959BF46647BC12050D4882D346029C35714AE91E54ED7E84DECD5237BEB9A12A0F364DD42E72A438 +920000,k,3CEA765B6DD108979C49CBF03525287751A17865B7DD68EC4419DA70895422124A70A81BCCC4C280238F445FCC06854E29A0912598511F19 +920000,u,4DC17D104004970960035EF0D0B4175417E27040D2B3B262C158A4803F982388EF1E2101D4AC09FF181A507A5266C38DE20773BBEA70A0F2 +921000,k,306A716C0CFB0B951239BA9A450B97A5C3553EC902FDB91D74565CD6FD6E0814BC43820F1E8655CC5A52B9B2CAD243273FEA930FD3566C86 +921000,u,117F05FCB0C2FF5BEACE77D99C6CC6185AE26DD231B152F59E7FBAAD8C8F2BA43341A5B902E4110D80E331DEE0A55EB5BF2DAEAE96D5940C +922000,k,5C439E26938C8C11EBF04109B5E2E3FBC28BB1FA1ACBCAD2B98098D52E94DCB8AFC9AAD64D2711EFA13A98146EBBCBDE88171BF3A6BF706A +922000,u,0E8B14986A163473936844758D42381A6320CEC629D2A9A5C364E06AB70F40D42D4DDA09E9AE597012D479C88653302BC1264AC68F658E6D +923000,k,37ACA295F4093EA12C0EC9610B08D14718122DFCDA809E71500B76A33A29C1743641FA6CC2EF802E5DBC9F83C834258A01A7B93DF5FFE39F +923000,u,495742EC624C84AF3A2A39831FDF916AAB629C6676C2DA9441D08A8219BED57A6D86A9FFB4BBED773526DB776FE832A427EB1897A5D82458 +924000,k,D5AA53A519A61FE4A4A37DE8564A02DF3028013D7A0276D477C9D11062EB2586846A509EE06F18D00DE2680DE5C8D2952B0F20DD2E075BFD +924000,u,EAA606EC548C791AC69204C1B6E130C3A3FDC9821B1B3ADDAD65344F5B4C4A4B0F292DC88710F3E12C16431E913FFBCF3FB9A748A683B3B5 +925000,k,AE70F4C9651BA06312F06173DBE2E75040C2FC4C7970E6AA7B49D02E752F6720215B25D506ACC801DBBBD1C8179FC31796B8D3601DFBD7E2 +925000,u,45E55523524E6775EF43BB6CED770493FC65C948B211E9EB0BBD9D86D325049C923DFF529E841274D3B2F45693FB824B1104224BD4DC41B4 +926000,k,ADA309A5E2E2EE3840040A1CC0CE19F30B0BD40068C410E897A8B7763F31830FB3F3E75158536D15B5D458C15A80018BD4A0915F7C6E5331 +926000,u,6DBE61F75FCFDF12985B47FC4D1CE6729EC7462671DCF2A94B4BA72A3847C3B87C23904E5245734AA11CC7C3B14F25479291267E52C90C9D +927000,k,73C4801DDCA60AAA32046F759C5159343BBD3CBE1E16A312379338FFB401157881C3B0F905A501F35BAEEDDB419EC5288B540E15AFBB8267 +927000,u,9133A432927D98E1AD5BADC04CA6AB0932A0353EF33BF519D0975824D489D6F84A146AE3E6A717B8CD967D0F24B9709ABA978EBB14CBA921 +928000,k,775FD7C35EFE7DFEA26B48E234FBDFB409C4BD77B84BA7599232E36D55A5B94CC61E601EE06E94AC0B477E84A64F43E47316503053C7E7CF +928000,u,48BD762B781A665F6208D49FD5106C06994A8756876ABB9C2AC098FAB45DF76538CF0F99D8E7759FCC53E14DF448AF51170E424F3D6952FF +929000,k,4E67830BD48E6AC29C8F0DB04B849BCF763DD7EF8250C711038F56C9525EA18A028C1CA76E5CAE8200198248B75CE22D248D2028CB497F89 +929000,u,DCFA65CB29C2F6714BA0AA8133512674C433B0ED5E9CC767DD598BCF51095397C4516C544392D5C91E05C710ECE8E556DE2589107BAF4BFB +930000,k,D4EB87F28D675A466A85C27CBF774E4A8939AB6F3E5D1C6C2C07B01BA55D4BCD62A4AC3ED186ECDA68764A28F7C2960C2301A66923E60097 +930000,u,9F2BCD41FCCBE642B26C3BCC467E7006EE956FD8126465DF1CEBA9677EF7417E55EF79D8C3970AEE93DBC70D0C14506C4F16992727FA4D6B +931000,k,CE3340313E997E1CAB7A2E3E07D8FBC92115200A575863E2820C2DED5AEDB766CA96A0AA82FADA12EFF078BCEE2C9CE65FA29046C59F1AF5 +931000,u,63F4DA62635422A871BA34D77495FF601988C8DAA41C97A8681F7300502189BE38B26728D5BD795EDAF96DB2F01178F752FE777BB10719E5 +932000,k,C4785D3743ADFF70C3B71B724E792C071400C4D4DAF4BF79A82BF7D0A6D830BE9961AAD74276511FC62EDA42B68007089A535EF5878B7CE1 +932000,u,5C0B668759FE6148A04F7C16AB67A940510BED3621E46D5AE193C716916F05F438EB83997E1A48DA59E7E0189BE4463EC8FDE93A39901D12 +933000,k,02E10CF45287A6E218CAEBEC55B9EC59FABDE7B57BF96CC6418ED59C27F04A24AB5CC9B2D607754F66BA8F3ED0EAB1BE6ED0C6C1CD26D502 +933000,u,EE5810BA4A17B04AC84C81F0FBB135252B8856BCC6242C793BE2EB4F9E77D0EFBF7F84AD60F4B01E87C1E93EC4EC68C7970019DF4C8BC39F +934000,k,3DC2813E1B7C357AC3AFCE1235B83AA44D122D217B78AFE17CDA9E8358411FF35E1CAFAB2F8B9F50802F2F3CF271BFA3C585CF1C64E7B71F +934000,u,F2FF413AE6E9B7814F4AE598CD9D75420E9D6EA83989E9A797D749230DD3AC66B6B9E2F137BFF19B37D488D32DDE6AA908C66D61347718AB +935000,k,06D90B2E26D87920BFEA6BE82480C262EB96003240CC8874420E9B2E6C5AEACC7B8BFE6BF150A043AE5B736901A9569603D86DE008EBAAAC +935000,u,DAFA24499D3B9203878C4AAF18C6AEC2ABD4FD24A24CB27ABCB3201C6AB46B2B12FDB7286FF6B93BBAB15F90EAA209376B9EBB1392355105 +936000,k,D82A20381DD71CE02BB161E2B1036DD0ADC64294E47B4C43B63AC91EC660B0C81B5A77287225D4F1BB93E1E749865CD454314A85600C02C9 +936000,u,054AFC6F429C6723C2BC41A1F557543E56EDCA126D7175F2CAC1F635525FC2394822370C83589E28E9F143CE97DC971EEA5ED269779A8D89 +937000,k,54AF7474BE16A9B3FA33A454865066DE8B258FF52B36A630D72229D93548A51B2DED71A7D0AD3526797C8B4A0AC82F9F271B0E0504FD1562 +937000,u,04B685AE0C7C3F90A8EAE0B8198BF2CCF51A88EABD8F3767F5B9FC2DC811B0EDE9F5CE86C5C68021B472D8A3B105BA360EE72475C33A96D2 +938000,k,A496C1FE3BFF066BCC9FCE7A311B6809DBB8B39B769353018F9FE87C83152ECA3C98CE0A0C622F3E2A2FE6F54894B2DC54E174D837DB1834 +938000,u,B9EBBF7CC9CF80F6A69556953AAAD7742BAAF779403EEB6F128D118BCFF80FAD603DE9636FB68BE832A4B03337BDF8C5254DF69C34DADC4C +939000,k,F1484382F0D9B0F4C68489A53A6AB79577D91F6446AF865C60F36A63AE2952A5D3B46E9A204D79E914FEB81EA7E0136DA740344E78E7DDC7 +939000,u,5E121C7400F8D0547523B6F4127115ED528887419813A218E20BB8A4158F771B6F3A7F75059463441CABBB83057285B5A7001D681FC0A684 +940000,k,3FC339A5F9916CFD303AF3C612518883D8B9345FE1761714F90CE724A330B596CA934DF7729B5AEF103B3A3E9FE608B9FBFCB368E68328C5 +940000,u,85CEAFB7B0DA29AB2BDE88D5374CADE0A9FA405547CE66698C14C0127FA86359577F6EC0FA1F342866A8A0CA216D89640AAD18BDDD5CE194 +941000,k,693871CCDAB55BCA9FB3EE7A06BD8C53DBD6BB3602C2919C2F3C7FAA20AA22682B390EDC7F9928EBA0D24D3AE426511ABD4120ABE7223C9E +941000,u,774F651483E08B102F01A2ABAC0E60BC196CC42C611135EE8783D8B08F5908D3A6FFB4A3C9AAC169E490E36352B921BF60D5DC2F7080BA07 +942000,k,AA81176E8D15ED002E5CB5FAF1B51CC2417242DBC88E0BDAA769759E81A162528D7E524B667A261F7A854DE9EED846A705FEB097F68CC7D3 +942000,u,5339886590E94D59F52329E641840F3FF8D4532D1C8BBA48D2BC933F892BA527AF4318A0AD9BF7396DFB6EC0B5EDDF0AC561BEC5CF6CF701 +943000,k,87FED504E3AC41F3B2B00CB99D199F1816FB4FBB6D86CC83572DFE24715B629B513EEA61E8C6CDEA77057A635536DB87EDDE5CB1628DFE15 +943000,u,D86DD96EBA52A478E7148FDABC3B2F61C92295AADBABF873021B320E116E2F23CFDD5263C6B4CF63628B7073C339189FFCEB6D6215B7B4CE +944000,k,7895CA4D99ADC19BE75A5919263D0D740B602076B83F21BD456B5EF185066B038E233B51427D3366066A3E4EA828C97EB82E42ABB2D20B04 +944000,u,351CEF7B32D473624851A10AE5F4436D3C7AF157735960FDCC25B638501D00167B0876AA76E7706D24785B9E3E7FC9DDE6E1D36F34A76153 +945000,k,30B70056DF39888BA765C7158833155F3E15FEE4CE7EE5ECAE02ED4BAC7A7028181EEF10B8E1B79A55D1F56E544C2543D79B9FD864B44ADE +945000,u,CF87C5EDA37A56C46FAC613BCA65B01B67352756CD35FA6403CF89B728552D08C90927B50A02634636C57B21D15036068CA0D5C5B9792E46 +946000,k,C1A4277521706C5BF4F5FFA5E5F54AB71432F9AA2A82BD3E36FA6CCD911EA3FDB52B6CE3E58F1A710194B733B23F1AA2DBE2F59A172B5FB7 +946000,u,6C5254E82EBAC9BDB8FFCADC103C7786D2AF4403323B5EA9A64F9FE8684299A8F304B9FCC99506B37219B6CAEF100A8D6765F565DAF08D74 +947000,k,27BCE769F161BF4BD96E964890583756D45DDEEDDB070ED15B51444C50BF53A9AA23FFB39A4FA2C99C22B1362E6882AD5E17FAAD212DF0C7 +947000,u,8DEE7AF2593A81C43432CE29F4762A4546449D6C06329F010A25E35951B82323ECAE2463F60F7C8CB23801D73958D19BCAC0368F5491B117 +948000,k,17652260E408B02CF101D2A44FDCDE0A620BF40469F165C2C3479EC5C7881311A9E4536A8429962B5A636CD6E79AC2139435E44C2078B22E +948000,u,9A9D2F6288A4E5D951C41BCB0199292A30693BFD8383CCA96BB508A88E9FD5BE05FBC04ED680A1F15DF55B7BBDAAC1D19CD1A83B5C726FB3 +949000,k,0B82084CB84B9BB6E6B6EB4C65DAF3AF98AB25DDE310C30786EEB1DC31958BEF9EB577A5F68E285D4A4D1F94EADA1A0E4D9BB266E23B370A +949000,u,88C2EA133A6E13A59BFE79C856299FD882F97523682C6F682E5845A56FEACE2A5B13148B05F5FBFDF6DF6BBB7D7566F46446106B87E17354 +950000,k,1FF3AE5485C23F1424AECFC1E2F52BE9A70E3C7E3FC92A98E14F7D216B4E721E4FD03E10D76CB058A56486CD92DA09CA6023703F895351EC +950000,u,6B35A9B1D071993B08D50AE8C01E9BE9936BFB6A7C551CCEF4DEF9ED434E37E46EE4865088B647C413C0E818EC132194ED9EC4EDFB7A592D +951000,k,D89B930D7FBAEF5517D9A8FC5498D36A09E978D0244583990EA35AD025CF74F58AD6A093AECBCF3EF6330C7FE65DBA29E0E2B4CA85B67837 +951000,u,C7057EE36157CD7DD9A42B2D366CC611204CD7F9BFEB6DBA3A182A3B19779FEAE897846EEDEFCFEE9069D4604C9C292605201B490773BD63 +952000,k,270151EA33E14690CD26B54CDC90693CE979B8927C892B7AD139041C9469868FDAB755ED4030F23AECF443CA6F217AD6D14C7A1A2F3115BD +952000,u,B6C3E4F1BA3CED11C6746FB71ECA5F01679178CB21203300E354A39DEB340D6FA070056BC1DF5469ED8F59B6C16197113DF1A558A815D89F +953000,k,ADDB534E8857C5B326CD4DC69F4D63276AC41390AEE529248AEC4A7540235380638399563E760AC452F652831AFAB0AD7C2868401B72C047 +953000,u,8706779C9D762012054497C90E6CC72D85E29DE2CC683F99E4FB551FF1867C05FF62B8F43E08B08BAEB9CA3F6BB610F241A7578ABDEBA413 +954000,k,40DE18FF480A6865951036F36E7CB3C03F9C89E3B7C6BE37A84F4CA0F2EF25D384C1FD129EB897CCABCC6670C484D5C546404F9C2E3256AC +954000,u,D60B3097B348F2E8235307AD0F934EFC1ED562886D82F2712652ACF700BAE94DEB01EC190F50D1B077A348B4D06C7892B28423A303EA37D1 +955000,k,8E369D2EE211F6552AD1783BEB9C412D0F5187E2E1692C99F29D3E2C3F5BCC1E58A58A1BB1A28237826B41769D2D952E86B6F7A76D67B209 +955000,u,2F142EFAD23C6E46FA9815D7B6C440C2E043D3D6645932B80AD0058238203E03EF40C46DDD0CCB551953A8AA60049F6A3989665D26470F59 +956000,k,00B85903B0C272D3E73368F444DAE472014B0DE40230DD8A7CADC7C4112FCA2F17E484831A4062C32C55B64E0F615329BA6320F87462B957 +956000,u,37229928B2DDC501407DF9FCA65ED66AA7CF4F553E4179339332B656AD3A0234E22E6187A6AFFC70512DE563F074E917EA42674AF7D63FF6 +957000,k,CF911E69BA8A7E7124B4372418B7F92F07E68F89196183E74064D5868B100E8C9F617D5BA9E6CB147C1C711E1C8C675889AEA5A4DE8D0DAD +957000,u,AA8DA27B0CDE2BAD70F5E4D364A7912BD64C209BF1C4AFCECD95EED5A018B55B572C91F787335E07C227963E100075EC43D857AD6F4208B7 +958000,k,84AFBB840B22581F0AD02A57093CE7A5EDCB75FC85A6554D598A6A6A596CEA3A7064C1D310B03588EE235D3D649F15C211F3BF5F5AAE8053 +958000,u,C083656931A65584B3E2024BFCC5F853A9DEE05153E948F5E61B23A543901941332FD67F0C8A93A22E387071E84BDFED82E8DA9AC1097B45 +959000,k,495230AC1E1C7FC2F0CBFE48B384FC45101B46977E6CB9E4CD72922B3C41B4EDC701BE08E8CF3282ABFE6D2CB70CAB70E547D399FB8629D0 +959000,u,EB99EBCF76D18ACAA4A4C918A4879106565BE84638D451CA8D6BDE4F8E3ECD11284C3177548A879066256AC22D643BDF235FA21690EFEC03 +960000,k,4B1CDD49E6DBD43E154EBD99A244A07B557DF91345B8D084B2EA800377595F165249BD9D40BB1988800F44A1030103C20478BA41754C7CD1 +960000,u,62F55DCE72547E02457732F687DAFED4529C52F8034C6D0F77FB6187BCB85D0E3BF8ACF5DE146BFF75E6FBE70824F1A23937A79083A409F5 +961000,k,4C7BF7114D53D96B33B2CB4BFD3AD4AD6DBE2DDB0A91DF27472C795F12C59A593953EAC89E42779A8F11E2BD77397ABF3A1A101DED29A02D +961000,u,566ABA28C84C41E2005E58EE6DB8EA3FA2946DC718BCF787ED802F27A9304AACB6F82745EE3EEF6CB548CA8B5E43A92839790C7CFBE94025 +962000,k,95803B54DE48763A7EEA3D837305DB8202E02F93B029B9D36A4DD6CDD68BE43C2F936A6C9B5BC1547858074B1C76A8E42C9E895AD6AE227D +962000,u,D7994C707E9C1127EF5B902A782EDB4C77C92C8B135B84FC76F28909F9046AD001732868FA00D7E78E9C2E8DCA1EE6FA1255D9F1E248090B +963000,k,D0B7BFADC371C47E4C94CF77A604C65419B918E3C9958E0AFA08384641EF6BE7685BC7997940C754EF0365C1B148AA0D3036F65B0FE50359 +963000,u,54C86E99289E619101158EDA38B49F09310CE9282526F5A0CAADF24E111C2564AB2E40CAA66074E886EDF9467ED06025400889A14D7C3848 +964000,k,03256F5F9833ED1E4F7429A354CE2D6427A771B8B274273DB1930F7CB63A33F08673BF80EB12BE7CCC6ED2213BB36970E740FC4FCB6B4F3F +964000,u,1DBAF14BF35F58BD88670C9E5A41DC9D68C380F874A65F7688E5CC1E607625BEF49968A12EA67D45FB2CE4A39D34FFFA24FC9076B23F4498 +965000,k,80B568E0871B83111479230DFC21B2FE1C46F7D202C94D60DFE4B5DCAD837C6EEB577834E0D96A754F62334561A70DD57884CD61BFFFEDA1 +965000,u,3C90FAC2FBEF3C6ACF8CE18161809E107BEF6884154A4C06AE0ACCAA141258F4DC13A49A699919BA6718CD9D4E59CC734EE447506F1CCD29 +966000,k,48F8A9CA67E40C505D946F0E4A85578CEF7A6B355E89B373397FBC9165C97B7EBA32505E1CE4B7253DDB9B504297C5CC4D0E3E6963A543B3 +966000,u,D8426599285414724D9A57829D2F99ACAC73C533DD53F059CBB82F1E7AE0A40C4EDE433688002CBF0DC44F9990EB097283C0DE040176C7CE +967000,k,DB9CF7EA6B1746C9573D231DEFE7A24518296C66EA0C69CCA558515285CE5A3912E5FBA915951ED6A3464CD84DBCADA6DBD1778A439B5A27 +967000,u,DF1A3A6F08C9BE44703FCDEC5F3AA4D1E79CE7F8A9226F3792457412513AF465956611F88A1007FE63AED9F67BF806BA95FA08FA6EBFD0E4 +968000,k,5193BAB52D2C36D3C1DECE426C4168F0B01A8BCA32D5B7DE95633244155E48A5BCC664223A4A9A47993086A42D5C3E9D24D6493914FEAFE4 +968000,u,AB0A30A1FCE5B3C06F5BB4F764F74128A49B5B770E8E9007161CED8474388B3B98AA13287D37EF011D9B0BB708484C8E6451D232DA5E6FB5 +969000,k,E88AB78D35FCCAC5C4CC071190D709111F4AEE2481AC3F4CDFAEB85363E2F8DDE749324858134B7D6C73F6DAA759414E3C448DA89E3839B5 +969000,u,1EA50A61E01136C4EE7510F76328D077F900BBC4C94DFC86785B9895B12C496788C9D5A6BE8CD2E36898C18691E11390B6133F42119C0417 +970000,k,5AEB8E5E5C78642691F40348A8CAF2E6D995E99591E6AEC6489821BA3941FEA3A5AABED1767FD1F1D9A05EB4A3C7A311B3FFAC82C1E17926 +970000,u,37D854C4E28538A415AAA181C31AC8FD2B5D9C4298F7AE9994A19818623342DFC39C77C439E10C9FCF39AE02E7B63F30B122081E15441F56 +971000,k,1C924490E80F8C62A6533B5A8A2E5340808CF2941F490E3A476AEA07F98BBD3ACD8CF67D748560EEA5250EEBA54A8DEA7168C58A9E2C8C65 +971000,u,8CCF97021A282CE6D0A387BDE807F03FE51B8EFF55A2BE504D63BE0EF03A479B828D1159B5AAF617A2C1776DB73846BDB8C5EAA1EB7DF0C0 +972000,k,83723A56C3893E83DAFB4BDA67C74A5A328F1DF27DA32C01998772404C9ABCAAD47B02FD6399E45562D315AE6076D1C15F42CAF7E22F98CC +972000,u,968E6C90DCF89C7566D6CD5D41A0B11AC180FE1300CC6C49ED171222240339404B4D3B79ACBD2911B0BDFE8B536CF03D2325B8C6CB51AD76 +973000,k,6FDBAA6FC9513B4D5B04456074888DCC3918872A2BE686841E9F64071652E1FD2068F3C87D1D891419C853EDBA98202E338838A9E61F1F55 +973000,u,8CDEE9D0801E6EEF0FA0B8E4A2662E8ABD128169BD075CBBA6C7FC94F1AAB70997E33806B0B7583F5CE7C4FF39E9D7050502872DD9AF336F +974000,k,2A4CB5AB4BAE7680F9F72F1C7782E1CBB4F15CD45979E336ED3FC4D2F7FD7CD2160E053180A9931EA5AC54E8C03789B87D03FCDB2E4AF46E +974000,u,3FE0FF91128CBD7A692866EA186DF6815A8CB82D09390E75A37F8FCED08A4972E2B51306548E7481AB0EB7CE2E17E92DA45F8B93316EB5E3 +975000,k,A5755DF3409757A4677D0E1B33A41EC42F62C2ADC3771220D59B50246879451A024415E5682D20EA37279C0CF22ED211BC7BD4F7A8507334 +975000,u,03CDFC805932CC640FDF8EA51BDA001E72B339326F355B67E2F98B733DFD67595C1829C4D468DFC4CE38F4C961F43D5B04FB49CBD4F10566 +976000,k,41DD9BDE908BC8075A0946DF56ECDD54BD3A30543239905CEC5DFB94C0DD4C6160A701B61FE85B8BBF9C6E708D22205EB555E4F747A25A2A +976000,u,D75CCE5028E90EDF13822B752E1C73114F945E6DF9AA1962389D45E2F9EC6C1ECD8FE32E6C34034C32C0E41A959D8B9A1E09459AE9435992 +977000,k,4135C6D6BA490B7285B1995E7532093E3C35C80909E82333B09BFAEA11A7922461C173F752745FF94F6725806509FF5591BE81C07A089B23 +977000,u,B94CDAA2B9B20F8BB46068508E30133DE7D79F6DFD77D98DE1670C487AFEFDA4D48665E0C6F7E19609FC6219D55A054B221354164D0F1567 +978000,k,04A4E023F0C419BBC61B29E90930E81F0F5A8835972497EBE6A060BF90F4162D25C36BFBCD4983C81BA0BBD8CA2A9B5AF18AB36F5453202A +978000,u,6FBF0C588D81309503F99DF941EA91D76C39BA09BC4C93868F27137644A5A620FE141A307CD1D539016BB7405A6BD88CFF7BCEF989125EFA +979000,k,013D586D2FBC7162C57B66454F1E2B7346BE9D8E0732B0F0FE60DCF47E9753780AA92816998B95910DAECACF819104BBFE6F517A0101317A +979000,u,301F17BD7F46BFED8C6E4ECD6F0EDBEDCCBA974FCEBA5C11544613FDC7B3B95CEB6C5187255D4494CF2FE6CCBB8B18FBA9B0369540D00C16 +980000,k,6873A2CD21EEBCEC4A2C0F264402C64AE09AB38C097AB218902433FF7BC4F98928239373B3ABC209117A7F8DD6AD186CB8DE52C69887B6E4 +980000,u,5824B2C6068CE915B757F708CF66E80AB956AF691CD1BBB8ED47975FD4F4C182CE9BD83775D1086EF080DA7236BF4DB3EA4920AB0F42C8D4 +981000,k,217D4B8E53C26DC67AF3A7A0756C1D17FEC0C06394DEB9AEDCAFE764AB1BD32D878AFCF099271B2C754A979C669F0DB065CF56D8DEC69BA7 +981000,u,B7226559D90F5C3A7091EC40FCCFCA2CFE2842A072BD77F52B16ED8F1B5395745797B2559D0100E68D5867E78A31FACDDCE7C98F4C14BD2C +982000,k,8D40EE053B744DA7B294BF91A3A61F96E1ACAA8606C65499E03BADF8CF9599760F23462EE59C2D6EC78AC3CD04A0F536E7A8954B486B10C7 +982000,u,40D3EEEFBCDD987D15D2EE279A47036E258C7A5118A65B1DE1E7D3AD484A1507E2DB0F275E6B75179288EC862142A6866FA894ED88A7855A +983000,k,79110927EE5683DB993351E55C4C15C515600821D6AE8410F9B1A6CEA80C05AF59141A016873B66A5D779398CA960A3117417506B2D11AD5 +983000,u,091DF62AB81A99F61295ACE526408CB6631593EDAB89668868CB3A5E58D7D9E673589347066230BDCB66E7C1441D883F1A77CB879F8FA44A +984000,k,9E975BEB30B2CED0F1995723E2F4D3BE8FD5B9B876A6820F9CC2AFB0C6667F8C5E4071598AF2AB20EBA5B767B81A0B37F7FBF211C36D4FC9 +984000,u,85A32751D1E43B9E64E62808C9A4700888151B7B017D27780DE37AE2EF997F551C52052427F96265E98B87CDF0636C9FB6FC09F6B98ED1CE +985000,k,56277A871868B30B0B2618C32D6130F5BBBA178A65112006D6D273DB91AE43023378938899373499723806821BAA60CE038FBE9C3B9BEB5B +985000,u,0A221B5DF32CA890769D6C2C8CC03EB8B8B4226404FE15DDD7E765DEF31FF6A0CC80869A4D51AA23A3AC5D370993BBF745C42B5850937A87 +986000,k,E9A6A064FDB7FF16F14CD775DCBCC6330E96B1D3D90393A8E996DE3B670A0F4FD4A658AB944E5972B36AB50FC21AE929211F040C01BDA4C5 +986000,u,60DD5CE5C481E62F1E9639D2121BFE0A2359C288842C5C03A60026635E790F90B72BC0315E2DAFB2EA591A5E25C13C6625F05A77876DCF1E +987000,k,D48B2E5105CA0E349A0AB48CE17938C6B9F09B7507471213C429E706BAAEEB3B484EF7E104D03990791FBEC8461BE8F38BE4E5B1964BC782 +987000,u,7E8B0C9E332FB381B85D57D13AD90F60E40AE4136E8DCE5309E6492502A9A9A4242F220867C670C0BC94C404029A2AE3F6A2B4061EA85447 +988000,k,86CBBD6ED3DB22700825162BA321CAC9D218B5172342EDFD58C835637CF83DC3E6588807376169F3875AC5890E6D38539E491FE75347A1BC +988000,u,8E9182769107ED1FBDD0696034143C83E5124E748BA0D6ACEA380DC237569948E3894450C6F8D1398E2FB18384237B16E3B156C2E8BD5EEB +989000,k,B6057D084971A1D17164F439580AE883933F278EDD145A5D12BAC104BA8E07D65615B7D3BD6BE265C36B3979494E9C1FB3AAB45E3DFE4257 +989000,u,2CB2719B12D20ADAE4F94A0586199996E5634BB40715A3E5E8952BEEE00D204053944667E296DB20DED66A1F094BCD9A7E34DE636D781570 +990000,k,AD15F461527A0E395FE3C32B2A780DCCF463D934F821CCDDBE410B04014AA3F69BD0DEE62D1A6E761DD8616FB1929D345F57F084B9F6E5FA +990000,u,99153864A9D7149B05F2F6987120E45F698B2808803839D5185B7E1A4D89F9C453398CAFEC7B0E1EF38017F477F491DE6FC6EDCB654EA4B7 +991000,k,8DEDA5B2E44D7979A4A71C963673702A890000BA28C5F581D90CD13223B0B8F8C449F078A339A20263162F951421139E10E8A3A3060FB032 +991000,u,0EA043A50EB051B77C97225BFE4999ECAE840B3CC65D0DDC6A1060E3D9CE9FFB097B9698C8AC21ED4F05AFC73FC9CF0F2515B569A75408E2 +992000,k,DFD6E351C5518B395BA97F78F006F2AD6E19DB0FA94BFA4992D75F2C410C609562F3573D4E50B22D23DF36DB2080529F1BC210356F07B0AA +992000,u,36B26BA66786E803DC56E4C317050F05CB11FBB3DEDA3C57BF3647C1D696F9110F5AF2FAEC5321EA2394A8CAA44618E48EBA1C049D918E1C +993000,k,3B5560675AD3DA4E8E55F8C6201DB63E846016D39ECB60BBBE399268FC473534AD2DE0E7F144BBD937A2C67B09E0B5A052A7CFA6B89CB7E2 +993000,u,36C716CA897F18FC751976CBBD02B1849BBB146C90C3BFAAF42767BCEED3B2D357138478D740CDA099F44C614192245E607746FBC6758054 +994000,k,09907D439AC73CB54940C5FE410E17FC66E9A5ECB5D8A49B1DB02E273241A99AE6489BB92F2F36D505484B91E11CB073E2FD505C578E6148 +994000,u,48BAC58FD3C7828CE17C5F16C07EC17420EE98F6A4D17E8D79E682E4E5E68D29654079BCDE1DEA8424D7847D290C808BCCDB38C7107F3E28 +995000,k,938954101E808977B6D527AF43384AC8DD28D9F3F81A59F737C34B2DB376F04FEA5ECC92D9D4701EC9B04B897CD5B0F8529171D524A5EB9D +995000,u,4C4D580F3B2DEA6CB405A46D8B83004B2C963986867448FE051D3924C4824C6533A29B97BF2CA737237B65042F5415DEB231E984F8B5B11E +996000,k,5F57132734294AD302B6B9A328DBFAB2AF456EE9F6770F349D1DDACAEF2D9AC6D0141E2CCAACD4D083A992410008CFCF8F6EE323E7071A29 +996000,u,F3BD6CF6D077CAAADD30E477D19F27A7776C3A521999CE9EA193C27FA26C6DEB1A1DF6A38FDCAA1079027AA7096FF1AA6BDC6524E4AAFD8C +997000,k,A8A78BE35BF22AFA2A24006048CC8658EE91F7D9D50AB6F97685A3BC2AC1071C642B7C9383A2CEF8FEC6E69FD421AEC5F894B574582CDF05 +997000,u,25CAE41B5ED53C507DFE3BA42D4F160642F410F2AF76CDB8639A4317F0C00B3D19B04112EFEA0BC7904A497E4DACE843EDAA0549A060FDBF +998000,k,C0D55D77778B87FA7F6E3D41753E184E4511220A170AB6D609065B38A4B51A71C1E65528C9CC452889B6CD99F17CFEC874F4908E105C36A9 +998000,u,86080CC763AC1F55BB79464F01934CEDDF5C7E9941E305A18F45911E5B612B7B1EBC1235E59006CAF821645AB9F3208F11982ED7E6A51FF0 +999000,k,663E3B9CAF0E75A520C87C4B56F0F8067DD82815551D5B4F83D08DB0467D8DE9593F991C4DDB1DCD1DE1173A8A1CFA6D669B2CE613CC4178 +999000,u,20620AC8719AF4B4867A9F25B1A422B23A6E57A24575F37E22F102031DEBEBABD3BE2E3590B4823223B010AFC8C4475FC688276A2B0FC80A +1000000,k,077F453681CACA3693198420BBE515CAE0002472519B3E67661A7E89CAB94695C8F4BCD66E61B9B9C946DA8D524DE3D69BD9D9D66B997E37 +1000000,u,2587A975FD303F32E750307485ABE285467CA36AB22C682E952E65EC7582752F97EAB484574021A8F2EB3BB7FF98CD12DB7184F9E035B178 diff --git a/test/jdk/sun/security/ec/xec/XECIterative.java b/test/jdk/sun/security/ec/xec/XECIterative.java new file mode 100644 index 00000000000..05ad0f57129 --- /dev/null +++ b/test/jdk/sun/security/ec/xec/XECIterative.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018, 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 8171277 + * @summary XEC curve operations iterative test vectors + * @library /test/lib + * @build jdk.test.lib.Convert + * @modules jdk.crypto.ec/sun.security.ec + * @run main XECIterative 0 10000 + * @run main XECIterative 10000 20000 + * @run main XECIterative 20000 30000 + * @run main XECIterative 30000 40000 + * @run main XECIterative 40000 50000 + * @run main XECIterative 50000 60000 + * @run main XECIterative 60000 70000 + * @run main XECIterative 70000 80000 + * @run main XECIterative 80000 90000 + * @run main XECIterative 90000 100000 + */ + +import sun.security.ec.*; + +import java.io.*; +import java.util.*; +import jdk.test.lib.Convert; + +/* + * This test is derived from the iterative test in RFC 7748. To produce the + * test vectors, the implementation ran for 1,000,000 iterations and saved + * values of k and u at periodic checkpoints. The RFC includes the correct + * value of k after 1,000,000 iterations, and this value was used to ensure + * that the test vectors are correct. This test has multiple @run tags so that + * no single run takes too long. + */ + +public class XECIterative { + + private static class KU { + + public byte[] k; + public byte[] u; + + } + + public static void main(String[] args) throws IOException { + + long start = Long.parseLong(args[0]); + long end = Long.parseLong(args[1]); + + XECIterative m = new XECIterative(); + + m.runIterativeTest("X25519", start, end); + m.runIterativeTest("X448", start, end); + + } + + private void runIterativeTest(String opName, long start, long end) + throws IOException { + + XECParameters settings = XECParameters.getByName(opName).get(); + XECOperations ops = new XECOperations(settings); + + File vectorFile = new File(System.getProperty("test.src", "."), + opName + ".iter"); + + Map<Long, KU> testIters = new HashMap<Long, KU>(); + BufferedReader in = new BufferedReader(new FileReader(vectorFile)); + String line; + while ((line = in.readLine()) != null) { + StringTokenizer tok = new StringTokenizer(line, ","); + long iter = Long.parseLong(tok.nextToken()); + String kOrU = tok.nextToken(); + byte[] value = Convert.hexStringToByteArray(tok.nextToken()); + KU entry = testIters.get(iter); + if (entry == null) { + entry = new KU(); + testIters.put(iter, entry); + } + if (kOrU.equals("k")) { + entry.k = value; + } else { + entry.u = value; + } + } + + KU startEntry = testIters.get(start); + byte[] k = startEntry.k.clone(); + byte[] u = startEntry.u.clone(); + + for (long i = start; i <= end; i++) { + KU curEntry; + if (i % 1000 == 0 && (curEntry = testIters.get(i)) != null) { + if (!Arrays.equals(k, curEntry.k)) { + throw new RuntimeException("At iter " + i + ": expected k: " + + Convert.byteArrayToHexString(curEntry.k) + + ", computed k: " + Convert.byteArrayToHexString(k)); + } + if (!Arrays.equals(u, curEntry.u)) { + throw new RuntimeException("At iter " + i + ": expected u: " + + Convert.byteArrayToHexString(curEntry.u) + + ", computed u: " + Convert.byteArrayToHexString(u)); + } + System.out.println(opName + " checkpoint passed at " + i); + } + + byte[] k_copy = Arrays.copyOf(k, k.length); + byte[] u_out = ops.encodedPointMultiply(k, u); + u = k_copy; + k = u_out; + } + } + +} + + diff --git a/test/lib/jdk/test/lib/Convert.java b/test/lib/jdk/test/lib/Convert.java new file mode 100644 index 00000000000..ac5235476ee --- /dev/null +++ b/test/lib/jdk/test/lib/Convert.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, 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 jdk.test.lib; + +import java.math.BigInteger; + +/** + * Utility class containing conversions between strings, arrays, and numeric + * values. + */ + +public class Convert { + + // Convert from a byte array to a hexadecimal representation as a string. + public static String byteArrayToHexString(byte[] arr) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < arr.length; ++i) { + byte curVal = arr[i]; + result.append(Character.forDigit(curVal >> 4 & 0xF, 16)); + result.append(Character.forDigit(curVal & 0xF, 16)); + } + return result.toString(); + } + + // Expand a single byte to a byte array + public static byte[] byteToByteArray(byte v, int length) { + byte[] result = new byte[length]; + result[0] = v; + return result; + } + + // Convert a hexadecimal string to a byte array + public static byte[] hexStringToByteArray(String str) { + byte[] result = new byte[str.length() / 2]; + for (int i = 0; i < result.length; i++) { + result[i] = (byte) Character.digit(str.charAt(2 * i), 16); + result[i] <<= 4; + result[i] += Character.digit(str.charAt(2 * i + 1), 16); + } + return result; + } + + /* + * Convert a hexadecimal string to the corresponding little-ending number + * as a BigInteger. The clearHighBit argument determines whether the most + * significant bit of the highest byte should be set to 0 in the result. + */ + public static + BigInteger hexStringToBigInteger(boolean clearHighBit, String str) { + BigInteger result = BigInteger.ZERO; + for (int i = 0; i < str.length() / 2; i++) { + int curVal = Character.digit(str.charAt(2 * i), 16); + curVal <<= 4; + curVal += Character.digit(str.charAt(2 * i + 1), 16); + if (clearHighBit && i == str.length() / 2 - 1) { + curVal &= 0x7F; + } + result = result.add(BigInteger.valueOf(curVal).shiftLeft(8 * i)); + } + return result; + } +} + + From 9ed9e26d5c29e58729503f6fe27785509cacc66c Mon Sep 17 00:00:00 2001 From: Thomas Schatzl <tschatzl@openjdk.org> Date: Tue, 8 May 2018 16:49:20 +0200 Subject: [PATCH 40/40] 8202781: Fix typo in DiscoveredListIterator::complete_enqeue Reviewed-by: kbarrett --- src/hotspot/share/gc/shared/referenceProcessor.cpp | 4 ++-- src/hotspot/share/gc/shared/referenceProcessor.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index 9bb39047ca6..e84682afc49 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -311,7 +311,7 @@ void DiscoveredListIterator::enqueue() { _next_discovered); } -void DiscoveredListIterator::complete_enqeue() { +void DiscoveredListIterator::complete_enqueue() { if (_prev_discovered != NULL) { // This is the last object. // Swap refs_list into pending list and set obj's @@ -474,7 +474,7 @@ void ReferenceProcessor::process_phase3(DiscoveredList& refs_list, assert(oopDesc::is_oop(iter.obj(), UseConcMarkSweepGC), "Adding a bad reference"); iter.next(); } - iter.complete_enqeue(); + iter.complete_enqueue(); // Close the reachable set complete_gc->do_void(); // Clear the list. diff --git a/src/hotspot/share/gc/shared/referenceProcessor.hpp b/src/hotspot/share/gc/shared/referenceProcessor.hpp index 86b52b42793..715ec32f5ed 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.hpp @@ -147,7 +147,7 @@ public: void enqueue(); // Move enqueued references to the reference pending list. - void complete_enqeue(); + void complete_enqueue(); // NULL out referent pointer. void clear_referent();